[automerger skipped] Add ForkJoinPool* threads to 911 Ignored regex am: e41a6d531c -s ours am: 60d1cc535f -s ours

am skip reason: Change-Id I3e9d64903f680ecdd6994d5ae1f1fa6362feda10 with SHA-1 2221bafe9a is in history

Original change: https://android-review.googlesource.com/c/platform/art/+/1184920

Change-Id: I448c0f2f188cba15bdabfd5151475279a2ede03e
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..95ce962
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,25 @@
+---
+BasedOnStyle: Google
+---
+
+Language: Cpp
+
+AlignConsecutiveMacros: AcrossComments
+AllowShortBlocksOnASingleLine: Empty
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Empty
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+AttributeMacros: ['__', 'NO_RETURN']
+BinPackArguments: false
+BinPackParameters: false
+BreakConstructorInitializers: BeforeColon
+BreakBeforeTernaryOperators: false
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+FixNamespaceComments: true
+PointerAlignment: Left
+TabWidth: 2
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 818fcfb..338bc69 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2,4 +2,32 @@
 
 package {
     default_visibility: ["//art:__subpackages__"],
+    default_applicable_licenses: ["art_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "art_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+        "SPDX-license-identifier-GPL-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
 }
diff --git a/Android.mk b/Android.mk
index d4de2e5..09cf3f2 100644
--- a/Android.mk
+++ b/Android.mk
@@ -18,12 +18,13 @@
 
 art_path := $(LOCAL_PATH)
 
+include $(art_path)/tools/veridex/Android.mk
+
 ########################################################################
 # clean-oat rules
 #
 
 include $(art_path)/build/Android.common_path.mk
-include $(art_path)/build/Android.oat.mk
 
 .PHONY: clean-oat
 clean-oat: clean-oat-host clean-oat-target
@@ -55,12 +56,64 @@
 include $(art_path)/build/Android.cpplint.mk
 
 ########################################################################
+# The art-tools package depends on helpers and tools that are useful for developers. Similar
+# dependencies exist for the APEX builds for these tools (see build/apex/Android.bp).
+
+ifneq ($(HOST_OS),darwin)
+include $(CLEAR_VARS)
+LOCAL_MODULE := art-tools
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD SPDX-license-identifier-GPL-2.0
+LOCAL_LICENSE_CONDITIONS := notice restricted
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
+LOCAL_IS_HOST_MODULE := true
+
+ifeq (true,$(my_art_module_source_build))
+
+LOCAL_REQUIRED_MODULES := \
+    ahat \
+    dexdump \
+    hprof-conv \
+
+# A subset of the tools are disabled when HOST_PREFER_32_BIT is defined as make reports that
+# they are not supported on host (b/129323791). This is likely due to art_apex disabling host
+# APEX builds when HOST_PREFER_32_BIT is set (b/120617876).
+ifneq ($(HOST_PREFER_32_BIT),true)
+LOCAL_REQUIRED_MODULES += \
+    dexdiag \
+    dexlist \
+    oatdump \
+
+endif
+
+else
+
+# The developer tools available as prebuilts.
+LOCAL_REQUIRED_MODULES := \
+    dexdump \
+    oatdump \
+
+endif # ifeq (true,$(my_art_module_source_build))
+
+include $(BUILD_PHONY_PACKAGE)
+endif # HOST_OS != darwin
+
+
+########################################################################
+# Everything below is only available in ART source builds
+# (SOONG_CONFIG_art_module_source_build=true).
+########################################################################
+
+# TODO(b/172480617): Clean up the platform dependencies on everything above and
+# remove this condition.
+ifeq (true,$(my_art_module_source_build))
+
+
+########################################################################
 # product rules
 
 include $(art_path)/oatdump/Android.mk
 include $(art_path)/tools/ahat/Android.mk
 include $(art_path)/tools/dexfuzz/Android.mk
-include $(art_path)/tools/veridex/Android.mk
 
 ART_HOST_DEPENDENCIES := \
   $(ART_HOST_EXECUTABLES) \
@@ -99,20 +152,24 @@
 
 # "mm test-art" to build and run all tests on host and device
 .PHONY: test-art
-test-art: test-art-host test-art-target
+test-art:
 	$(hide) $(call ART_TEST_PREREQ_FINISHED,$@)
 
 .PHONY: test-art-gtest
-test-art-gtest: test-art-host-gtest test-art-target-gtest
+test-art-gtest:
 	$(hide) $(call ART_TEST_PREREQ_FINISHED,$@)
 
 .PHONY: test-art-run-test
-test-art-run-test: test-art-host-run-test test-art-target-run-test
+test-art-run-test:
 	$(hide) $(call ART_TEST_PREREQ_FINISHED,$@)
 
 ########################################################################
 # host test rules
 
+test-art: test-art-host
+test-art-gtest: test-art-host-gtest
+test-art-run-test: test-art-host-run-test
+
 VIXL_TEST_DEPENDENCY :=
 # We can only run the vixl tests on 64-bit hosts (vixl testing issue) when its a
 # top-level build (to declare the vixl test rule).
@@ -205,6 +262,10 @@
 ########################################################################
 # target test rules
 
+test-art: test-art-target
+test-art-gtest: test-art-target-gtest
+test-art-run-test: test-art-target-run-test
+
 # "mm test-art-target" to build and run all target tests.
 .PHONY: test-art-target
 test-art-target: test-art-target-gtest test-art-target-run-test
@@ -276,76 +337,27 @@
 	$(hide) $(call ART_TEST_PREREQ_FINISHED,$@)
 endif
 
-
 #######################
-# ART APEX.
+# Reset LOCAL_PATH because previous includes may override its value.
+# Keep this after all "include $(art_path)/..." are done, and before any
+# "include $(BUILD_...)".
+LOCAL_PATH := $(art_path)
 
-include $(CLEAR_VARS)
-
-# The ART APEX comes in three flavors:
-# - the release module (`com.android.art.release`), containing
-#   only "release" artifacts;
-# - the debug module (`com.android.art.debug`), containing both
-#   "release" and "debug" artifacts, as well as additional tools;
-# - the testing module (`com.android.art.testing`), containing
-#   both "release" and "debug" artifacts, as well as additional tools
-#   and ART gtests).
-#
-# The ART APEX module (`com.android.art`) is an "alias" for either the
-# release or the debug module. By default, "user" build variants contain
-# the release module, while "userdebug" and "eng" build variants contain
-# the debug module. However, if `PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD`
-# is defined, it overrides the previous logic:
-# - if `PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD` is set to `false`, the
-#   build will include the release module (whatever the build
-#   variant);
-# - if `PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD` is set to `true`, the
-#   build will include the debug module (whatever the build variant).
-
-art_target_include_debug_build := $(PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD)
-ifneq (false,$(art_target_include_debug_build))
-  ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-    art_target_include_debug_build := true
-  endif
-endif
-ifeq (true,$(art_target_include_debug_build))
-  # Module with both release and debug variants, as well as
-  # additional tools.
-  TARGET_ART_APEX := $(DEBUG_ART_APEX)
-  APEX_TEST_MODULE := art-check-debug-apex-gen-fakebin
-else
-  # Release module (without debug variants nor tools).
-  TARGET_ART_APEX := $(RELEASE_ART_APEX)
-  APEX_TEST_MODULE := art-check-release-apex-gen-fakebin
-endif
-
-LOCAL_MODULE := com.android.art
-LOCAL_REQUIRED_MODULES := $(TARGET_ART_APEX)
-LOCAL_REQUIRED_MODULES += art_apex_boot_integrity
-
-# Clear locally used variable.
-art_target_include_debug_build :=
-
-include $(BUILD_PHONY_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.art
-LOCAL_IS_HOST_MODULE := true
-ifneq ($(HOST_OS),darwin)
-  LOCAL_REQUIRED_MODULES += $(APEX_TEST_MODULE)
-endif
-include $(BUILD_PHONY_PACKAGE)
-
-# Create canonical name -> file name symlink in the symbol directory
-# The symbol files for the debug or release variant are installed to
-# $(TARGET_OUT_UNSTRIPPED)/$(TARGET_ART_APEX) directory. However,
-# since they are available via /apex/com.android.art at runtime
-# regardless of which variant is installed, create a symlink so that
+# Create canonical name -> file name symlink in the symbol directory for the
+# debug APEX. The symbol files for it are installed to
+# $(TARGET_OUT_UNSTRIPPED)/apex/com.android.art.debug. However, since it's
+# available via /apex/com.android.art at runtime, create a symlink so that
 # $(TARGET_OUT_UNSTRIPPED)/apex/com.android.art is linked to
-# $(TARGET_OUT_UNSTRIPPED)/apex/$(TARGET_ART_APEX).
-# Note that installation of the symlink is triggered by the apex_manifest.pb
-# file which is the file that is guaranteed to be created regardless of the
-# value of TARGET_FLATTEN_APEX.
+# $(TARGET_OUT_UNSTRIPPED)/apex/$(TARGET_ART_APEX). We skip this for the release
+# APEX which has com.android.art as $(TARGET_ART_APEX). Note that installation
+# of the symlink is triggered by the apex_manifest.pb file which is the file
+# that is guaranteed to be created regardless of the value of
+# TARGET_FLATTEN_APEX.
+# TODO(b/171419613): the symlink is disabled because the
+# $OUT/symbols/apex/com.android.art name is taken by the com.android.art apex
+# even when com.android.art.debug is selected by TARGET_ART_APEX.
+# Disabling the symlink means that symbols for the com.android.art.debug apex
+# will not be found.
 ifeq ($(TARGET_FLATTEN_APEX),true)
 art_apex_manifest_file := $(PRODUCT_OUT)/system/apex/$(TARGET_ART_APEX)/apex_manifest.pb
 else
@@ -356,9 +368,15 @@
 $(art_apex_manifest_file): $(art_apex_symlink_timestamp)
 $(art_apex_manifest_file): PRIVATE_LINK_NAME := $(TARGET_OUT_UNSTRIPPED)/apex/com.android.art
 $(art_apex_symlink_timestamp):
-	$(hide) mkdir -p $(dir $(PRIVATE_LINK_NAME))
-	$(hide) ln -sf $(TARGET_ART_APEX) $(PRIVATE_LINK_NAME)
+#ifeq ($(TARGET_ART_APEX),com.android.art)
+#	$(hide) if [ -L $(PRIVATE_LINK_NAME) ]; then rm -f $(PRIVATE_LINK_NAME); fi
+#else
+#	$(hide) mkdir -p $(dir $(PRIVATE_LINK_NAME))
+#	$(hide) rm -rf $(PRIVATE_LINK_NAME)
+#	$(hide) ln -sf $(TARGET_ART_APEX) $(PRIVATE_LINK_NAME)
+#endif
 	$(hide) touch $@
+$(art_apex_symlink_timestamp): .KATI_SYMLINK_OUTPUTS := $(PRIVATE_LINK_NAME)
 
 art_apex_manifest_file :=
 
@@ -370,19 +388,36 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := art-runtime
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD SPDX-license-identifier-GPL-2.0
+LOCAL_LICENSE_CONDITIONS := notice restricted
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
+
+# Reference the libraries and binaries in the appropriate APEX module, because
+# they don't have platform variants. However if
+# SOONG_CONFIG_art_module_source_build isn't true then the APEX modules are
+# disabled, so Soong won't apply the APEX mutators to them, and then they are
+# available with their plain names.
+ifeq (true,$(SOONG_CONFIG_art_module_source_build))
+  art_module_lib = $(1).com.android.art
+  art_module_debug_lib = $(1).com.android.art.debug
+else
+  art_module_lib = $(1)
+  art_module_debug_lib = $(1)
+endif
 
 # Base requirements.
 LOCAL_REQUIRED_MODULES := \
-    dalvikvm.com.android.art.release \
-    dex2oat.com.android.art.release \
-    dexoptanalyzer.com.android.art.release \
-    libart.com.android.art.release \
-    libart-compiler.com.android.art.release \
-    libopenjdkjvm.com.android.art.release \
-    libopenjdkjvmti.com.android.art.release \
-    profman.com.android.art.release \
-    libadbconnection.com.android.art.release \
-    libperfetto_hprof.com.android.art.release \
+    $(call art_module_lib,dalvikvm) \
+    $(call art_module_lib,dex2oat) \
+    $(call art_module_lib,dexoptanalyzer) \
+    $(call art_module_lib,libart) \
+    $(call art_module_lib,libart-compiler) \
+    $(call art_module_lib,libopenjdkjvm) \
+    $(call art_module_lib,libopenjdkjvmti) \
+    $(call art_module_lib,odrefresh) \
+    $(call art_module_lib,profman) \
+    $(call art_module_lib,libadbconnection) \
+    $(call art_module_lib,libperfetto_hprof) \
 
 # Potentially add in debug variants:
 #
@@ -396,43 +431,22 @@
 endif
 ifeq (true,$(art_target_include_debug_build))
 LOCAL_REQUIRED_MODULES += \
-    dex2oatd.com.android.art.debug \
-    dexoptanalyzerd.com.android.art.debug \
-    libartd.com.android.art.debug \
-    libartd-compiler.com.android.art.debug \
-    libopenjdkd.com.android.art.debug \
-    libopenjdkjvmd.com.android.art.debug \
-    libopenjdkjvmtid.com.android.art.debug \
-    profmand.com.android.art.debug \
-    libadbconnectiond.com.android.art.debug \
-    libperfetto_hprofd.com.android.art.debug \
+    $(call art_module_debug_lib,dex2oatd) \
+    $(call art_module_debug_lib,dexoptanalyzerd) \
+    $(call art_module_debug_lib,libartd) \
+    $(call art_module_debug_lib,libartd-compiler) \
+    $(call art_module_debug_lib,libopenjdkd) \
+    $(call art_module_debug_lib,libopenjdkjvmd) \
+    $(call art_module_debug_lib,libopenjdkjvmtid) \
+    $(call art_module_debug_lib,profmand) \
+    $(call art_module_debug_lib,libadbconnectiond) \
+    $(call art_module_debug_lib,libperfetto_hprofd) \
 
 endif
 endif
 
-include $(BUILD_PHONY_PACKAGE)
-
-# The art-tools package depends on helpers and tools that are useful for developers. Similar
-# dependencies exist for the APEX builds for these tools (see build/apex/Android.bp).
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := art-tools
-LOCAL_IS_HOST_MODULE := true
-LOCAL_REQUIRED_MODULES := \
-    ahat \
-    dexdump \
-    hprof-conv \
-
-# A subset of the tools are disabled when HOST_PREFER_32_BIT is defined as make reports that
-# they are not supported on host (b/129323791). This is likely due to art_apex disabling host
-# APEX builds when HOST_PREFER_32_BIT is set (b/120617876).
-ifneq ($(HOST_PREFER_32_BIT),true)
-LOCAL_REQUIRED_MODULES += \
-    dexdiag \
-    dexlist \
-    oatdump \
-
-endif
+art_module_lib :=
+art_module_debug_lib :=
 
 include $(BUILD_PHONY_PACKAGE)
 
@@ -447,90 +461,71 @@
 #         64-bit systems, even if it is the default.
 
 # ART on the host.
+ifneq ($(HOST_OS),darwin)
 ifeq ($(ART_BUILD_HOST_DEBUG),true)
 include $(CLEAR_VARS)
 LOCAL_MODULE := art-libartd-libopenjdkd-host-dependency
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD SPDX-license-identifier-GPL-2.0
+LOCAL_LICENSE_CONDITIONS := notice restricted
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
 LOCAL_MULTILIB := both
 LOCAL_REQUIRED_MODULES := libopenjdkd
 LOCAL_IS_HOST_MODULE := true
 include $(BUILD_PHONY_PACKAGE)
 endif
-
-# ART on the target.
-ifeq ($(ART_BUILD_TARGET_DEBUG),true)
-include $(CLEAR_VARS)
-LOCAL_MODULE := art-libartd-libopenjdkd-target-dependency
-LOCAL_MULTILIB := both
-LOCAL_REQUIRED_MODULES := libopenjdkd
-include $(BUILD_PHONY_PACKAGE)
-endif
+endif # HOST_OS != darwin
 
 ########################################################################
 # "m build-art" for quick minimal build
 .PHONY: build-art
-build-art: build-art-host build-art-target
+
+build-art: build-art-host
+
+# For host, we extract the ICU data from the apex and install it to HOST_OUT/I18N_APEX.
+$(HOST_I18N_DATA): $(TARGET_OUT)/apex/$(I18N_APEX).apex $(HOST_OUT)/bin/deapexer
+	$(call extract-from-apex,$(I18N_APEX))
+	rm -rf $(HOST_OUT)/$(I18N_APEX)
+	mkdir -p $(HOST_OUT)/$(I18N_APEX)/
+	cp -R $(TARGET_OUT)/apex/$(I18N_APEX)/etc/ $(HOST_OUT)/$(I18N_APEX)/
+	touch $@
+
+$(HOST_TZDATA_DATA): $(TARGET_OUT)/apex/$(TZDATA_APEX).apex $(HOST_OUT)/bin/deapexer
+	$(call extract-from-apex,$(TZDATA_APEX))
+	rm -rf $(HOST_OUT)/$(TZDATA_APEX)
+	mkdir -p $(HOST_OUT)/$(TZDATA_APEX)/
+	cp -R $(TARGET_OUT)/apex/$(TZDATA_APEX)/etc/ $(HOST_OUT)/$(TZDATA_APEX)/
+	touch $@
 
 .PHONY: build-art-host
-build-art-host:   $(HOST_OUT_EXECUTABLES)/art $(ART_HOST_DEPENDENCIES) $(HOST_CORE_IMG_OUTS)
+build-art-host:   $(HOST_OUT_EXECUTABLES)/art $(ART_HOST_DEPENDENCIES) $(HOST_CORE_IMG_OUTS) $(HOST_I18N_DATA) $(HOST_TZDATA_DATA)
+
+build-art: build-art-target
 
 .PHONY: build-art-target
 build-art-target: $(TARGET_OUT_EXECUTABLES)/art $(ART_TARGET_DEPENDENCIES) $(TARGET_CORE_IMG_OUTS)
 
-########################################################################
-# Workaround for not using symbolic links for linker and bionic libraries
-# in a minimal setup (eg buildbot or golem).
-########################################################################
-
-PRIVATE_BIONIC_FILES := \
-  bin/bootstrap/linker \
-  bin/bootstrap/linker64 \
-  lib/bootstrap/libc.so \
-  lib/bootstrap/libm.so \
-  lib/bootstrap/libdl.so \
-  lib/bootstrap/libdl_android.so \
-  lib64/bootstrap/libc.so \
-  lib64/bootstrap/libm.so \
-  lib64/bootstrap/libdl.so \
-  lib64/bootstrap/libdl_android.so \
-
 PRIVATE_ART_APEX_DEPENDENCY_FILES := \
   bin/dalvikvm32 \
   bin/dalvikvm64 \
   bin/dalvikvm \
-  bin/dex2oat \
-  bin/dex2oatd \
+  bin/dex2oat32 \
+  bin/dex2oat64 \
   bin/dexdump \
 
 PRIVATE_ART_APEX_DEPENDENCY_LIBS := \
-  lib/libadbconnectiond.so \
   lib/libadbconnection.so \
-  lib/libandroidicu.so \
   lib/libandroidio.so \
-  lib/libartbased.so \
   lib/libartbase.so \
   lib/libart-compiler.so \
-  lib/libartd-compiler.so \
-  lib/libartd-dexlayout.so \
-  lib/libartd-disassembler.so \
   lib/libart-dexlayout.so \
   lib/libart-disassembler.so \
-  lib/libartd.so \
   lib/libartpalette.so \
   lib/libart.so \
   lib/libbacktrace.so \
-  lib/libbase.so \
-  lib/libcrypto.so \
-  lib/libdexfiled_external.so \
-  lib/libdexfiled.so \
-  lib/libdexfile_external.so \
   lib/libdexfile.so \
-  lib/libdexfile_support.so \
   lib/libdt_fd_forward.so \
   lib/libdt_socket.so \
   lib/libexpat.so \
-  lib/libicui18n.so \
-  lib/libicu_jni.so \
-  lib/libicuuc.so \
   lib/libjavacore.so \
   lib/libjdwp.so \
   lib/liblzma.so \
@@ -539,51 +534,28 @@
   lib/libnativehelper.so \
   lib/libnativeloader.so \
   lib/libnpt.so \
-  lib/libopenjdkd.so \
-  lib/libopenjdkjvmd.so \
   lib/libopenjdkjvm.so \
-  lib/libopenjdkjvmtid.so \
   lib/libopenjdkjvmti.so \
   lib/libopenjdk.so \
   lib/libpac.so \
   lib/libprocinfo.so \
-  lib/libprofiled.so \
   lib/libprofile.so \
   lib/libsigchain.so \
   lib/libunwindstack.so \
-  lib/libvixld.so \
-  lib/libvixl.so \
   lib/libziparchive.so \
-  lib/libz.so \
-  lib64/libadbconnectiond.so \
   lib64/libadbconnection.so \
-  lib64/libandroidicu.so \
   lib64/libandroidio.so \
-  lib64/libartbased.so \
   lib64/libartbase.so \
   lib64/libart-compiler.so \
-  lib64/libartd-compiler.so \
-  lib64/libartd-dexlayout.so \
-  lib64/libartd-disassembler.so \
   lib64/libart-dexlayout.so \
   lib64/libart-disassembler.so \
-  lib64/libartd.so \
   lib64/libartpalette.so \
   lib64/libart.so \
   lib64/libbacktrace.so \
-  lib64/libbase.so \
-  lib64/libcrypto.so \
-  lib64/libdexfiled_external.so \
-  lib64/libdexfiled.so \
-  lib64/libdexfile_external.so \
   lib64/libdexfile.so \
-  lib64/libdexfile_support.so \
   lib64/libdt_fd_forward.so \
   lib64/libdt_socket.so \
   lib64/libexpat.so \
-  lib64/libicui18n.so \
-  lib64/libicu_jni.so \
-  lib64/libicuuc.so \
   lib64/libjavacore.so \
   lib64/libjdwp.so \
   lib64/liblzma.so \
@@ -592,22 +564,27 @@
   lib64/libnativehelper.so \
   lib64/libnativeloader.so \
   lib64/libnpt.so \
-  lib64/libopenjdkd.so \
-  lib64/libopenjdkjvmd.so \
   lib64/libopenjdkjvm.so \
-  lib64/libopenjdkjvmtid.so \
   lib64/libopenjdkjvmti.so \
   lib64/libopenjdk.so \
   lib64/libpac.so \
   lib64/libprocinfo.so \
-  lib64/libprofiled.so \
   lib64/libprofile.so \
   lib64/libsigchain.so \
   lib64/libunwindstack.so \
-  lib64/libvixld.so \
-  lib64/libvixl.so \
   lib64/libziparchive.so \
-  lib64/libz.so \
+
+PRIVATE_RUNTIME_APEX_DEPENDENCY_FILES := \
+  bin/linker \
+  bin/linker64 \
+  lib/bionic/libc.so \
+  lib/bionic/libdl.so \
+  lib/bionic/libdl_android.so \
+  lib/bionic/libm.so \
+  lib64/bionic/libc.so \
+  lib64/bionic/libdl.so \
+  lib64/bionic/libdl_android.so \
+  lib64/bionic/libm.so \
 
 PRIVATE_CONSCRYPT_APEX_DEPENDENCY_LIBS := \
   lib/libcrypto.so \
@@ -617,26 +594,52 @@
   lib64/libjavacrypto.so \
   lib64/libssl.so \
 
-# Generate copies of Bionic bootstrap artifacts and ART APEX
-# libraries in the `system` (TARGET_OUT) directory. This is dangerous
-# as these files could inadvertently stay in this directory and be
-# included in a system image.
+PRIVATE_I18N_APEX_DEPENDENCY_LIBS := \
+  lib/libicu.so \
+  lib/libicui18n.so \
+  lib/libicu_jni.so \
+  lib/libicuuc.so \
+  lib64/libicu.so \
+  lib64/libicui18n.so \
+  lib64/libicu_jni.so \
+  lib64/libicuuc.so \
+
+PRIVATE_STATSD_APEX_DEPENDENCY_LIBS := \
+  lib/libstatssocket.so \
+  lib64/libstatssocket.so \
+
+# Extracts files from an APEX into a location. The APEX can be either a .apex
+# file in $(TARGET_OUT)/apex, or a directory in the same location. Files are
+# extracted to $(TARGET_OUT) with the same relative paths as under the APEX
+# root.
+# $(1): APEX base name
+# $(2): List of files to extract, with paths relative to the APEX root
 #
-# Copy some libraries into `$(TARGET_OUT)/lib(64)` (the
-# `/system/lib(64)` directory to be sync'd to the target) for ART testing
-# purposes:
-# - Bionic bootstrap libraries, copied from
-#   `$(TARGET_OUT)/lib(64)/bootstrap` (the `/system/lib(64)/bootstrap`
-#   directory to be sync'd to the target);
-# - Programs and libraries from the ART APEX; if the product
-#   to build uses flattened APEXes, these libraries are copied from
-#   `$(TARGET_OUT)/apex/com.android.art.debug` (the flattened
-#   (Debug) ART APEX directory to be sync'd to the target);
-#   otherwise, they are copied from
-#   `$(TARGET_OUT)/../apex/com.android.art.debug` (the local
-#   directory under the build tree containing the (Debug) ART APEX
-#   artifacts, which is not sync'd to the target).
-# - Libraries from the Conscrypt APEX may be loaded during golem runs.
+# "cp -d" below doesn't work on Darwin, but this is only used for Golem builds
+# and won't run on mac anyway.
+define extract-from-apex
+  apex_root=$(TARGET_OUT)/apex && \
+  apex_file=$$apex_root/$(1).apex && \
+  apex_dir=$$apex_root/$(1) && \
+  if [ -f $$apex_file ]; then \
+    rm -rf $$apex_dir && \
+    mkdir -p $$apex_dir && \
+    debugfs=$(HOST_OUT)/bin/debugfs_static && \
+    $(HOST_OUT)/bin/deapexer --debugfs_path $$debugfs extract $$apex_file $$apex_dir; \
+  fi && \
+  for f in $(2); do \
+    sf=$$apex_dir/$$f && \
+    df=$(TARGET_OUT)/$$f && \
+    if [ -f $$sf -o -h $$sf ]; then \
+      mkdir -p $$(dirname $$df) && \
+      cp -fd $$sf $$df; \
+    fi || exit 1; \
+  done
+endef
+
+# Copy or extract some required files from APEXes to the `system` (TARGET_OUT)
+# directory. This is dangerous as these files could inadvertently stay in this
+# directory and be included in a system image.
 #
 # This target is only used by Golem now.
 #
@@ -647,90 +650,67 @@
 # TODO(b/129332183): Remove this when Golem has full support for the
 # ART APEX.
 .PHONY: standalone-apex-files
-standalone-apex-files: libc.bootstrap \
-                       libdl.bootstrap \
-                       libdl_android.bootstrap \
-                       libm.bootstrap \
-                       linker \
-                       $(DEBUG_ART_APEX) \
-                       $(CONSCRYPT_APEX)
-	for f in $(PRIVATE_BIONIC_FILES); do \
-	  tf=$(TARGET_OUT)/$$f; \
-	  if [ -f $$tf ]; then cp -f $$tf $$(echo $$tf | sed 's,bootstrap/,,'); fi; \
-	done
-	if [ "x$(TARGET_FLATTEN_APEX)" = xtrue ]; then \
-          apex_orig_dir=$(TARGET_OUT)/apex; \
-	else \
-          apex_orig_dir=""; \
-	fi; \
-	art_apex_orig_dir=$$apex_orig_dir/$(DEBUG_ART_APEX); \
-	for f in $(PRIVATE_ART_APEX_DEPENDENCY_LIBS) $(PRIVATE_ART_APEX_DEPENDENCY_FILES); do \
-	  tf="$$art_apex_orig_dir/$$f"; \
-	  df="$(TARGET_OUT)/$$f"; \
-	  if [ -f $$tf ]; then \
-            if [ -h $$df ]; then rm $$df; fi; \
-            cp -fd $$tf $$df; \
-          fi; \
-	done; \
-	conscrypt_apex_orig_dir=$$apex_orig_dir/$(CONSCRYPT_APEX); \
-	for f in $(PRIVATE_CONSCRYPT_APEX_DEPENDENCY_LIBS); do \
-	  tf="$$conscrypt_apex_orig_dir/$$f"; \
-	  if [ -f $$tf ]; then cp -f $$tf $(TARGET_OUT)/$$f; fi; \
-	done; \
+standalone-apex-files: deapexer \
+                       $(RELEASE_ART_APEX) \
+                       $(RUNTIME_APEX) \
+                       $(CONSCRYPT_APEX) \
+                       $(I18N_APEX) \
+                       $(STATSD_APEX) \
+                       $(TZDATA_APEX)
+	$(call extract-from-apex,$(RELEASE_ART_APEX),\
+	  $(PRIVATE_ART_APEX_DEPENDENCY_LIBS) $(PRIVATE_ART_APEX_DEPENDENCY_FILES))
+	# The Runtime APEX has the Bionic libs in ${LIB}/bionic subdirectories,
+	# so we need to move them up a level after extraction.
+	# Also, platform libraries are installed in prebuilts, so copy them over.
+	$(call extract-from-apex,$(RUNTIME_APEX),\
+	  $(PRIVATE_RUNTIME_APEX_DEPENDENCY_FILES)) && \
+	  for libdir in $(TARGET_OUT)/lib $(TARGET_OUT)/lib64; do \
+	    if [ -d $$libdir/bionic ]; then \
+	      mv -f $$libdir/bionic/*.so $$libdir; \
+	    fi || exit 1; \
+	  done && \
+	  for libdir in $(TARGET_OUT)/lib $(TARGET_OUT)/lib64; do \
+	    if [ -d $$libdir ]; then \
+          cp prebuilts/runtime/mainline/platform/impl/$(TARGET_ARCH)/*.so $$libdir; \
+	    fi || exit 1; \
+	  done
+	$(call extract-from-apex,$(CONSCRYPT_APEX),\
+	  $(PRIVATE_CONSCRYPT_APEX_DEPENDENCY_LIBS))
+	$(call extract-from-apex,$(I18N_APEX),\
+	  $(PRIVATE_I18N_APEX_DEPENDENCY_LIBS))
+	$(call extract-from-apex,$(STATSD_APEX),\
+	  $(PRIVATE_STATSD_APEX_DEPENDENCY_LIBS))
+	$(call extract-from-apex,$(TZDATA_APEX),)
 
 ########################################################################
 # Phony target for only building what go/lem requires for pushing ART on /data.
 
 .PHONY: build-art-target-golem
+
+# TODO(b/129332183): Clean this up when Golem runs can mount the APEXes directly
+# in the chroot.
+
+ART_TARGET_PLATFORM_DEPENDENCIES := \
+  $(TARGET_OUT)/etc/public.libraries.txt \
+  $(TARGET_OUT_SHARED_LIBRARIES)/heapprofd_client_api.so \
+  $(TARGET_OUT_SHARED_LIBRARIES)/libartpalette-system.so \
+  $(TARGET_OUT_SHARED_LIBRARIES)/libcutils.so \
+  $(TARGET_OUT_SHARED_LIBRARIES)/liblz4.so \
+  $(TARGET_OUT_SHARED_LIBRARIES)/libprocessgroup.so \
+  $(TARGET_OUT_SHARED_LIBRARIES)/libprocinfo.so \
+  $(TARGET_OUT_SHARED_LIBRARIES)/libselinux.so \
+  $(TARGET_OUT_SHARED_LIBRARIES)/libtombstoned_client.so \
+  $(TARGET_OUT_SHARED_LIBRARIES)/libz.so \
+
 # 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, libdl_android,
-# libm). These are required as the "main" libc, libdl, libdl_android, and libm
-# have moved to the ART APEX. This is a temporary change needed until Golem
-# fully supports the ART APEX.
-#
-# TODO(b/129332183): Remove this when Golem has full support for the
-# ART APEX.
-
-# Also include:
-# - a copy of the ICU prebuilt .dat file in /system/etc/icu on target
-#   (see module `icu-data-art-test-i18n`); and
-# so that it can be found even if the ART APEX is not available, by setting the
-# environment variable `ART_TEST_ANDROID_ART_ROOT` to "/system" on device. This
-# is a temporary change needed until Golem fully supports the ART APEX.
-#
-# TODO(b/129332183): Remove this when Golem has full support for the
-# ART APEX.
-
-# Also include:
-# - a copy of the time zone data prebuilt files in
-#   /system/etc/tzdata_module/etc/tz and /system/etc/tzdata_module/etc/icu
-#   on target, (see modules `tzdata-art-test-tzdata`,
-#   `tzlookup.xml-art-test-tzdata`, and `tz_version-art-test-tzdata`, and
-#   `icu_overlay-art-test-tzdata`)
-# so that they can be found even if the Time Zone Data APEX is not available,
-# by setting the environment variable `ART_TEST_ANDROID_TZDATA_ROOT`
-# to "/system/etc/tzdata_module" on device. This is a temporary change needed
-# until Golem fully supports the Time Zone Data APEX.
-#
-# TODO(b/129332183): Remove this when Golem has full support for the
-# ART APEX (and TZ Data APEX).
-
 ART_TARGET_SHARED_LIBRARY_BENCHMARK := $(TARGET_OUT_SHARED_LIBRARIES)/libartbenchmark.so
-build-art-target-golem: dex2oat dalvikvm linker libstdc++ \
+
+build-art-target-golem: $(RELEASE_ART_APEX) com.android.runtime $(CONSCRYPT_APEX) \
                         $(TARGET_OUT_EXECUTABLES)/art \
-                        $(TARGET_OUT)/etc/public.libraries.txt \
-                        $(ART_TARGET_DEX_DEPENDENCIES) \
-                        $(ART_DEBUG_TARGET_SHARED_LIBRARY_DEPENDENCIES) \
+                        $(TARGET_OUT_EXECUTABLES)/dex2oat_wrapper \
+                        $(ART_TARGET_PLATFORM_DEPENDENCIES) \
                         $(ART_TARGET_SHARED_LIBRARY_BENCHMARK) \
-                        $(TARGET_CORE_IMG_OUT_BASE).art \
-                        $(TARGET_CORE_IMG_OUT_BASE)-interpreter.art \
-                        libartpalette-system \
-                        libc.bootstrap libdl.bootstrap libdl_android.bootstrap libm.bootstrap \
-                        icu-data-art-test-i18n \
-                        tzdata-art-test-tzdata tzlookup.xml-art-test-tzdata \
-                        tz_version-art-test-tzdata icu_overlay-art-test-tzdata \
                         standalone-apex-files
 	# remove debug libraries from public.libraries.txt because golem builds
 	# won't have it.
@@ -741,16 +721,19 @@
 
 ########################################################################
 # Phony target for building what go/lem requires on host.
+
 .PHONY: build-art-host-golem
 # Also include libartbenchmark, we always include it when running golem.
 ART_HOST_SHARED_LIBRARY_BENCHMARK := $(ART_HOST_OUT_SHARED_LIBRARIES)/libartbenchmark.so
 build-art-host-golem: build-art-host \
-                      $(ART_HOST_SHARED_LIBRARY_BENCHMARK)
+                      $(ART_HOST_SHARED_LIBRARY_BENCHMARK) \
+                      $(HOST_OUT_EXECUTABLES)/dex2oat_wrapper
 
 ########################################################################
 # Phony target for building what go/lem requires for syncing /system to target.
 .PHONY: build-art-unbundled-golem
-build-art-unbundled-golem: art-runtime linker oatdump $(ART_APEX_JARS) conscrypt crash_dump
+art_apex_jars := $(foreach pair,$(ART_APEX_JARS), $(call word-colon,2,$(pair)))
+build-art-unbundled-golem: art-runtime linker oatdump $(art_apex_jars) conscrypt crash_dump
 
 ########################################################################
 # Rules for building all dependencies for tests.
@@ -870,3 +853,59 @@
   $(HOST_OUT_EXECUTABLES)/dex2oats \
   $(HOST_OUT_EXECUTABLES)/dex2oatds \
   $(HOST_OUT_EXECUTABLES)/profman
+
+########################################################################
+
+# Build a target that contains dex public SDK stubs for SDK version in the list.
+# Zip files structure:
+#   public-sdk-28-stub.zip
+#     classes.dex
+#   public-sdk-29-stub.zip
+#     classes.dex
+#   public-sdk-30-stub.zip
+#     classes.dex
+MIN_SDK_VERSION := 28
+SDK_VERSIONS := $(call numbers_greater_or_equal_to,$(MIN_SDK_VERSION),$(TARGET_AVAIALBLE_SDK_VERSIONS))
+
+# Create dex public SDK stubs.
+define get_public_sdk_stub_dex
+$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/public_sdk_$(1)_stub_intermediates/classes.dex
+endef
+
+# The input is the SDK version.
+define create_public_sdk_dex
+public_sdk_$(1)_stub := $$(call get_public_sdk_stub_dex,$(1))
+$$(public_sdk_$(1)_stub): PRIVATE_MIN_SDK_VERSION := $(1)
+$$(public_sdk_$(1)_stub): $$(call resolve-prebuilt-sdk-jar-path,$(1)) $$(DX) $$(ZIP2ZIP)
+	$$(transform-classes.jar-to-dex)
+endef
+
+$(foreach version,$(SDK_VERSIONS),$(eval $(call create_public_sdk_dex,$(version))))
+
+# Create dex public SDK stubs zip.
+define get_public_sdk_stub_zip
+$(call intermediates-dir-for,PACKAGING,public_sdk_stub,HOST)/public-sdk-$(1)-stub.zip
+endef
+
+define create_public_sdk_zip
+PUBLIC_SDK_$(1)_STUB_ZIP_PATH := $$(call get_public_sdk_stub_zip,$(1))
+$$(PUBLIC_SDK_$(1)_STUB_ZIP_PATH): PRIVATE_SDK_STUBS_DEX_DIR := $$(dir $$(public_sdk_$(1)_stub))
+$$(PUBLIC_SDK_$(1)_STUB_ZIP_PATH): $$(SOONG_ZIP) $$(public_sdk_$(1)_stub)
+	rm -f $$@
+	$$(SOONG_ZIP) -o $$@ -C $$(PRIVATE_SDK_STUBS_DEX_DIR) -D $$(PRIVATE_SDK_STUBS_DEX_DIR)
+endef
+
+$(foreach version,$(SDK_VERSIONS),$(eval $(call create_public_sdk_zip,$(version))))
+
+# Make the zip files available for prebuilts.
+$(foreach version,$(SDK_VERSIONS),$(call dist-for-goals,sdk,$(call get_public_sdk_stub_zip,$(version))))
+
+STUB_ZIP_FILES = $(foreach version,$(SDK_VERSIONS),$(call get_public_sdk_stub_zip,$(version)))
+
+.PHONY: public_sdk_stubs
+public_sdk_stubs: $(STUB_ZIP_FILES)
+
+MIN_SDK_VERSION :=
+SDK_VERSIONS :=
+
+endif # ifeq (true,$(my_art_module_source_build))
diff --git a/CleanSpec.mk b/CleanSpec.mk
index fe613b2..3e1f5be 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -105,6 +105,16 @@
 # Remove empty dir for art APEX because it will be created on demand while mounting release|debug
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/apex/com.android.art)
 
+# Remove 'libart[d]?-simulator-container.so' which was briefly in the ART AREX.
+$(call add-clean-step, find $(OUT_DIR)/soong/.intermediates/art -name 'libart*-simulator-container.so' -type f | xargs rm -f)
+
+# Remove symbols/apex/com.android.art symlink (b/171406631)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/apex/com.android.art)
+
+# art/tools/build_linux_bionic_tests.sh uses find here and can encounter
+# libdexfile_external.so in incremental builds.
+$(call add-clean-step, rm -rf $(HOST_OUT))
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..6d8601b
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+  license_type: RESTRICTED
+}
diff --git a/OWNERS b/OWNERS
index 7297a14..1d8d2ba 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,15 @@
+dsrbecky@google.com
+hboehm@google.com
+jiakaiz@google.com
+lokeshgidra@google.com
+mast@google.com
+mingaleev@google.com
 ngeoffray@google.com
-sehr@google.com
-*
+nikitai@google.com
+oth@google.com
+prb@google.com
+rpl@google.com
+skvadrik@google.com
+sorinbasca@google.com
+vichang@google.com
+vmarko@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 6ab01dc..b8ee3c5 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,6 +1,12 @@
 [Hook Scripts]
 check_generated_tests_up_to_date = tools/test_presubmit.py
 
+hidden_api_txt_checksorted_hook = ${REPO_ROOT}/tools/platform-compat/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
+
+# TODO(b/189484095): Port libnativebridge tests to atest and enable in presubmit
+# so we don't need the custom runtests script and this check.
+check_libnativebridge_test_field = libnativebridge/tests/preupload_check_test_tag.sh ${PREUPLOAD_COMMIT_MESSAGE} ${PREUPLOAD_FILES}
+
 [Builtin Hooks]
 cpplint = true
 bpfmt = true
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 28dab29..3c07c65 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,10 +1,2371 @@
+// Generated by `regen-test-files`. Do not edit manually.
 {
+  "mainline-presubmit": [
+    {
+      "name": "art-run-test-001-HelloWorld[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-001-Main[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-002-sleep[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-004-InterfaceTest[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-004-checker-UnsafeTest18[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-006-args[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-007-count10[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-009-instanceof[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-010-instance[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-011-array-copy[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-012-math[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-013-math2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-014-math3[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-015-switch[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-016-intern[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-017-float[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-018-stack-overflow[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-019-wrong-array-type[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-020-string[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-021-string2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-022-interface[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-025-access-controller[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-026-access[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-027-arithmetic[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-028-array-write[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-029-assert[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-033-class-init-deadlock[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-035-enum[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-036-finalizer[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-037-inherit[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-039-join-main[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-040-miranda[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-041-narrowing[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-043-privates[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-045-reflect-array[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-046-reflect[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-047-returns[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-048-reflect-v8[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-049-show-object[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-050-sync-test[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-052-verifier-fun[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-053-wait-some[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-055-enum-performance[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-058-enum-order[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-059-finalizer-throw[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-061-out-of-memory[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-062-character-encodings[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-063-process-manager[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-067-preemptive-unpark[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-070-nio-buffer[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-072-precise-gc[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-072-reachability-fence[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-074-gc-thrash[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-076-boolean-put[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-078-polymorphic-virtual[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-079-phantom[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-080-oom-fragmentation[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-080-oom-throw[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-080-oom-throw-with-finalizer[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-081-hot-exceptions[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-082-inline-execute[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-083-compiler-regressions[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-084-class-init[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-090-loop-formation[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-092-locale[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-093-serialization[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-094-pattern[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-095-switch-MAX_INT[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-099-vmdebug[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-100-reflect2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-101-fibonacci[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-102-concurrent-gc[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-103-string-append[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-104-growth-limit[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-105-invoke[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-106-exceptions2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-107-int-math2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-108-check-cast[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-109-suspend-check[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-110-field-access[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-112-double-math[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-114-ParallelGC[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-120-hashcode[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-121-simple-suspend-check[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-122-npe[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-123-compiler-regressions-mt[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-123-inline-execute2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-125-gc-and-classloading[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-128-reg-spill-on-implicit-nullcheck[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-129-ThreadGetId[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-132-daemon-locks-shutdown[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-133-static-invoke-super[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-140-dce-regression[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-140-field-packing[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-143-string-value[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-144-static-field-sigquit[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-151-OpenFileLimit[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-152-dead-large-object[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-153-reference-stress[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-156-register-dex-file-multi-loader[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-159-app-image-fields[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-163-app-image-methods[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-165-lock-owner-proxy[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-168-vmstack-annotated[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-170-interface-init[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-174-escaping-instance-of-bad-class[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-175-alloc-big-bignums[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-176-app-image-string[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-1960-checker-bounds-codegen[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-1961-checker-loop-vectorizer[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-201-built-in-except-detail-messages[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2019-constantcalculationsinking[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-202-thread-oome[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2020-InvokeVirtual-Inlining[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2021-InvokeStatic-Inlining[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2022-Invariantloops[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2023-InvariantLoops_typecast[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2024-InvariantNegativeLoop[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2025-ChangedArrayValue[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2026-DifferentMemoryLSCouples[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2027-TwiceTheSameMemoryCouple[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2028-MultiBackward[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2029-contended-monitors[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2030-long-running-child[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2231-checker-heap-poisoning[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-2232-write-metrics-to-log[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-300-package-override[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-301-abstract-protected[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-302-float-conversion[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-304-method-tracing[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-401-optimizing-compiler[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-402-optimizing-control-flow[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-403-optimizing-long[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-404-optimizing-allocator[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-405-optimizing-long-allocator[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-406-fields[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-407-arrays[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-408-move-bug[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-409-materialized-condition[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-410-floats[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-411-checker-hdiv-hrem-pow2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-411-checker-instruct-simplifier-hrem[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-411-optimizing-arith[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-413-regalloc-regression[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-414-static-fields[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-418-const-string[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-419-long-parameter[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-420-const-class[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-421-exceptions[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-421-large-frame[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-422-instanceof[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-422-type-conversion[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-423-invoke-interface[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-424-checkcast[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-426-monitor[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-427-bitwise[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-427-bounds[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-429-ssa-builder[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-430-live-register-slow-path[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-433-gvn[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-434-shifter-operand[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-435-try-finally-without-catch[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-436-rem-float[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-436-shift-constant[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-437-inline[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-438-volatile[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-439-npe[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-439-swap-double[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-440-stmp[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-441-checker-inliner[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-443-not-bool-inline[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-444-checker-nce[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-445-checker-licm[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-446-checker-inliner2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-447-checker-inliner3[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-449-checker-bce-rem[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-451-regression-add-float[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-451-spill-splot[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-455-checker-gvn[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-456-baseline-array-set[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-458-long-to-fpu[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-464-checker-inline-sharpen-calls[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-465-checker-clinit-gvn[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-469-condition-materialization[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-470-huge-method[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-471-deopt-environment[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-472-type-propagation[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-473-checker-inliner-constants[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-473-remove-dead-block[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-474-checker-boolean-input[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-474-fp-sub-neg[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-475-simplify-mul-zero[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-476-checker-ctor-memory-barrier[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-476-clinit-inline-static-invoke[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-477-checker-bound-type[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-477-long-2-float-convers-precision[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-478-checker-inline-noreturn[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-478-checker-inliner-nested-loop[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-479-regression-implicit-null-check[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-480-checker-dead-blocks[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-481-regression-phi-cond[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-483-dce-block[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-485-checker-dce-switch[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-486-checker-must-do-null-check[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-487-checker-inline-calls[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-488-checker-inline-recursive-calls[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-489-current-method-regression[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-490-checker-inline[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-491-current-method[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-492-checker-inline-invoke-interface[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-493-checker-inline-invoke-interface[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-494-checker-instanceof-tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-495-checker-checkcast-tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-496-checker-inlining-class-loader[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-499-bce-phi-array-length[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-500-instanceof[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-505-simplifier-type-propagation[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-507-boolean-test[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-507-referrer[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-508-checker-disassembly[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-508-referrer-method[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-513-array-deopt[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-514-shifts[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-519-bound-load-class[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-521-checker-array-set-null[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-521-regression-integer-field-set[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-524-boolean-simplifier-regression[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-525-checker-arrays-fields1[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-525-checker-arrays-fields2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-526-long-regalloc[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-527-checker-array-access-simd[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-527-checker-array-access-split[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-528-long-hint[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-529-long-split[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-530-checker-loops1[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-530-checker-loops2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-530-checker-loops3[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-530-checker-loops4[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-530-checker-loops5[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-530-checker-lse-ctor-fences[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-530-checker-lse-simd[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-530-instanceof-checkcast[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-532-checker-nonnull-arrayset[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-534-checker-bce-deoptimization[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-535-deopt-and-inlining[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-536-checker-intrinsic-optimization[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-537-checker-arraycopy[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-537-checker-jump-over-jump[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-538-checker-embed-constants[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-540-checker-rtp-bug[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-542-bitfield-rotates[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-542-inline-trycatch[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-542-unresolved-access-check[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-545-tracing-and-jit[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-548-checker-inlining-and-dce[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-549-checker-types-merge[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-550-checker-multiply-accumulate[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-550-new-instance-clinit[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-551-checker-clinit[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-551-implicit-null-checks[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-552-checker-x86-avx2-bit-manipulation[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-554-checker-rtp-checkcast[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-557-checker-instruct-simplifier-ror[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-558-switch[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-559-bce-ssa[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-559-checker-rtp-ifnotnull[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-560-packed-switch[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-561-divrem[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-561-shared-slowpaths[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-562-bce-preheader[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-563-checker-invoke-super[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-564-checker-bitcount[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-564-checker-inline-loop[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-564-checker-negbitwise[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-565-checker-condition-liveness[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-566-checker-codegen-select[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-567-checker-builder-intrinsics[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-568-checker-onebit[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-570-checker-select[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-572-checker-array-get-regression[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-573-checker-checkcast-regression[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-576-polymorphic-inlining[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-577-checker-fp2int[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-578-bce-visit[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-578-polymorphic-inlining[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-579-inline-infinite[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-580-checker-round[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-580-crc32[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-581-rtp[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-582-checker-bce-length[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-584-checker-div-bool[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-589-super-imt[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-590-checker-arr-set-null-regression[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-591-checker-regression-dead-loop[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-593-checker-long-2-float-regression[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-594-checker-array-alias[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-594-load-string-regression[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-603-checker-instanceof[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-605-new-string-from-bytes[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-607-daemon-stress[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-609-checker-inline-interface[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-609-checker-x86-bounds-check[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-610-arraycopy[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-611-checker-simplify-if[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-614-checker-dump-constant-location[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-615-checker-arm64-store-zero[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-617-clinit-oome[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-618-checker-induction[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-619-checker-current-method[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-620-checker-bce-intrinsics[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-622-checker-bce-regressions[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-625-checker-licm-regressions[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-627-checker-unroll[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-628-vdex[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-631-checker-get-class[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-632-checker-char-at-bounds[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-635-checker-arm64-volatile-load-cc[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-636-arm64-veneer-pool[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-637-checker-throw-inline[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-640-checker-boolean-simd[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-640-checker-integer-valueof[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-640-checker-simd[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-641-checker-arraycopy[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-641-iterations[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-643-checker-bogus-ic[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-645-checker-abs-simd[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-646-checker-arraycopy-large-cst-pos[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-646-checker-long-const-to-int[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-646-checker-simd-hadd[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-650-checker-inline-access-thunks[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-654-checker-periodic[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-655-checker-simd-arm-opt[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-656-checker-simd-opt[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-657-branches[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-658-fp-read-barrier[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-660-checker-sad[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-660-checker-simd-sad[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-661-checker-simd-reduc[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-662-regression-alias[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-665-checker-simd-zero[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-666-dex-cache-itf[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-667-checker-simd-alignment[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-667-out-of-bounds[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-669-checker-break[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-671-npe-field-opts[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-672-checker-throw-method[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-673-checker-throw-vmethod[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-674-HelloWorld-Dm[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-676-proxy-jit-at-first-use[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-677-fsi2[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-680-sink-regression[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-684-checker-simd-dotprod[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-684-select-condition[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-689-multi-catch[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-694-clinit-jit[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-695-simplify-throws[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-696-loop[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-697-checker-string-append[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-698-selects[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-700-LoadArgRegs[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-703-floating-point-div[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-704-multiply-accumulate[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-705-register-conflict[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-711-checker-type-conversion[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-718-zipfile-finalizer[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-721-osr[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-726-array-store[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-730-checker-inlining-super[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-805-TooDeepClassInstanceOf[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-806-TooWideClassInstanceOf[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-812-recursive-default[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-814-large-field-offsets[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-815-invokeinterface-default[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-818-clinit-nterp[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-821-madvise-willneed[com.google.android.art.apex]"
+    },
+    {
+      "name": "art-run-test-963-default-range-smali[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_cmdline_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_compiler_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_dex2oat_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_dexdump_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_dexlist_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_dexoptanalyzer_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_libartbase_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_libartpalette_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_libdexfile_support_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_libdexfile_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_libprofile_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_oatdump_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_odrefresh_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_profman_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_runtime_compiler_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_runtime_tests[com.google.android.art.apex]"
+    },
+    {
+      "name": "art_standalone_sigchain_tests[com.google.android.art.apex]"
+    }
+  ],
   "presubmit": [
     {
       "name": "CtsJdwpTestCases"
     },
     {
       "name": "BootImageProfileTest"
+    },
+    {
+      "name": "art-run-test-001-HelloWorld"
+    },
+    {
+      "name": "art-run-test-001-Main"
+    },
+    {
+      "name": "art-run-test-002-sleep"
+    },
+    {
+      "name": "art-run-test-004-InterfaceTest"
+    },
+    {
+      "name": "art-run-test-004-checker-UnsafeTest18"
+    },
+    {
+      "name": "art-run-test-006-args"
+    },
+    {
+      "name": "art-run-test-007-count10"
+    },
+    {
+      "name": "art-run-test-009-instanceof"
+    },
+    {
+      "name": "art-run-test-010-instance"
+    },
+    {
+      "name": "art-run-test-011-array-copy"
+    },
+    {
+      "name": "art-run-test-012-math"
+    },
+    {
+      "name": "art-run-test-013-math2"
+    },
+    {
+      "name": "art-run-test-014-math3"
+    },
+    {
+      "name": "art-run-test-015-switch"
+    },
+    {
+      "name": "art-run-test-016-intern"
+    },
+    {
+      "name": "art-run-test-017-float"
+    },
+    {
+      "name": "art-run-test-018-stack-overflow"
+    },
+    {
+      "name": "art-run-test-019-wrong-array-type"
+    },
+    {
+      "name": "art-run-test-020-string"
+    },
+    {
+      "name": "art-run-test-021-string2"
+    },
+    {
+      "name": "art-run-test-022-interface"
+    },
+    {
+      "name": "art-run-test-025-access-controller"
+    },
+    {
+      "name": "art-run-test-026-access"
+    },
+    {
+      "name": "art-run-test-027-arithmetic"
+    },
+    {
+      "name": "art-run-test-028-array-write"
+    },
+    {
+      "name": "art-run-test-029-assert"
+    },
+    {
+      "name": "art-run-test-033-class-init-deadlock"
+    },
+    {
+      "name": "art-run-test-035-enum"
+    },
+    {
+      "name": "art-run-test-036-finalizer"
+    },
+    {
+      "name": "art-run-test-037-inherit"
+    },
+    {
+      "name": "art-run-test-039-join-main"
+    },
+    {
+      "name": "art-run-test-040-miranda"
+    },
+    {
+      "name": "art-run-test-041-narrowing"
+    },
+    {
+      "name": "art-run-test-043-privates"
+    },
+    {
+      "name": "art-run-test-045-reflect-array"
+    },
+    {
+      "name": "art-run-test-046-reflect"
+    },
+    {
+      "name": "art-run-test-047-returns"
+    },
+    {
+      "name": "art-run-test-048-reflect-v8"
+    },
+    {
+      "name": "art-run-test-049-show-object"
+    },
+    {
+      "name": "art-run-test-050-sync-test"
+    },
+    {
+      "name": "art-run-test-052-verifier-fun"
+    },
+    {
+      "name": "art-run-test-053-wait-some"
+    },
+    {
+      "name": "art-run-test-055-enum-performance"
+    },
+    {
+      "name": "art-run-test-058-enum-order"
+    },
+    {
+      "name": "art-run-test-059-finalizer-throw"
+    },
+    {
+      "name": "art-run-test-061-out-of-memory"
+    },
+    {
+      "name": "art-run-test-062-character-encodings"
+    },
+    {
+      "name": "art-run-test-063-process-manager"
+    },
+    {
+      "name": "art-run-test-067-preemptive-unpark"
+    },
+    {
+      "name": "art-run-test-070-nio-buffer"
+    },
+    {
+      "name": "art-run-test-072-precise-gc"
+    },
+    {
+      "name": "art-run-test-072-reachability-fence"
+    },
+    {
+      "name": "art-run-test-074-gc-thrash"
+    },
+    {
+      "name": "art-run-test-076-boolean-put"
+    },
+    {
+      "name": "art-run-test-078-polymorphic-virtual"
+    },
+    {
+      "name": "art-run-test-079-phantom"
+    },
+    {
+      "name": "art-run-test-080-oom-fragmentation"
+    },
+    {
+      "name": "art-run-test-080-oom-throw"
+    },
+    {
+      "name": "art-run-test-080-oom-throw-with-finalizer"
+    },
+    {
+      "name": "art-run-test-081-hot-exceptions"
+    },
+    {
+      "name": "art-run-test-082-inline-execute"
+    },
+    {
+      "name": "art-run-test-083-compiler-regressions"
+    },
+    {
+      "name": "art-run-test-084-class-init"
+    },
+    {
+      "name": "art-run-test-090-loop-formation"
+    },
+    {
+      "name": "art-run-test-092-locale"
+    },
+    {
+      "name": "art-run-test-093-serialization"
+    },
+    {
+      "name": "art-run-test-094-pattern"
+    },
+    {
+      "name": "art-run-test-095-switch-MAX_INT"
+    },
+    {
+      "name": "art-run-test-099-vmdebug"
+    },
+    {
+      "name": "art-run-test-100-reflect2"
+    },
+    {
+      "name": "art-run-test-101-fibonacci"
+    },
+    {
+      "name": "art-run-test-102-concurrent-gc"
+    },
+    {
+      "name": "art-run-test-103-string-append"
+    },
+    {
+      "name": "art-run-test-104-growth-limit"
+    },
+    {
+      "name": "art-run-test-105-invoke"
+    },
+    {
+      "name": "art-run-test-106-exceptions2"
+    },
+    {
+      "name": "art-run-test-107-int-math2"
+    },
+    {
+      "name": "art-run-test-108-check-cast"
+    },
+    {
+      "name": "art-run-test-109-suspend-check"
+    },
+    {
+      "name": "art-run-test-110-field-access"
+    },
+    {
+      "name": "art-run-test-112-double-math"
+    },
+    {
+      "name": "art-run-test-114-ParallelGC"
+    },
+    {
+      "name": "art-run-test-120-hashcode"
+    },
+    {
+      "name": "art-run-test-121-simple-suspend-check"
+    },
+    {
+      "name": "art-run-test-122-npe"
+    },
+    {
+      "name": "art-run-test-123-compiler-regressions-mt"
+    },
+    {
+      "name": "art-run-test-123-inline-execute2"
+    },
+    {
+      "name": "art-run-test-125-gc-and-classloading"
+    },
+    {
+      "name": "art-run-test-128-reg-spill-on-implicit-nullcheck"
+    },
+    {
+      "name": "art-run-test-129-ThreadGetId"
+    },
+    {
+      "name": "art-run-test-132-daemon-locks-shutdown"
+    },
+    {
+      "name": "art-run-test-133-static-invoke-super"
+    },
+    {
+      "name": "art-run-test-140-dce-regression"
+    },
+    {
+      "name": "art-run-test-140-field-packing"
+    },
+    {
+      "name": "art-run-test-143-string-value"
+    },
+    {
+      "name": "art-run-test-144-static-field-sigquit"
+    },
+    {
+      "name": "art-run-test-151-OpenFileLimit"
+    },
+    {
+      "name": "art-run-test-152-dead-large-object"
+    },
+    {
+      "name": "art-run-test-153-reference-stress"
+    },
+    {
+      "name": "art-run-test-156-register-dex-file-multi-loader"
+    },
+    {
+      "name": "art-run-test-159-app-image-fields"
+    },
+    {
+      "name": "art-run-test-163-app-image-methods"
+    },
+    {
+      "name": "art-run-test-165-lock-owner-proxy"
+    },
+    {
+      "name": "art-run-test-168-vmstack-annotated"
+    },
+    {
+      "name": "art-run-test-170-interface-init"
+    },
+    {
+      "name": "art-run-test-174-escaping-instance-of-bad-class"
+    },
+    {
+      "name": "art-run-test-175-alloc-big-bignums"
+    },
+    {
+      "name": "art-run-test-176-app-image-string"
+    },
+    {
+      "name": "art-run-test-1960-checker-bounds-codegen"
+    },
+    {
+      "name": "art-run-test-1961-checker-loop-vectorizer"
+    },
+    {
+      "name": "art-run-test-201-built-in-except-detail-messages"
+    },
+    {
+      "name": "art-run-test-2019-constantcalculationsinking"
+    },
+    {
+      "name": "art-run-test-202-thread-oome"
+    },
+    {
+      "name": "art-run-test-2020-InvokeVirtual-Inlining"
+    },
+    {
+      "name": "art-run-test-2021-InvokeStatic-Inlining"
+    },
+    {
+      "name": "art-run-test-2022-Invariantloops"
+    },
+    {
+      "name": "art-run-test-2023-InvariantLoops_typecast"
+    },
+    {
+      "name": "art-run-test-2024-InvariantNegativeLoop"
+    },
+    {
+      "name": "art-run-test-2025-ChangedArrayValue"
+    },
+    {
+      "name": "art-run-test-2026-DifferentMemoryLSCouples"
+    },
+    {
+      "name": "art-run-test-2027-TwiceTheSameMemoryCouple"
+    },
+    {
+      "name": "art-run-test-2028-MultiBackward"
+    },
+    {
+      "name": "art-run-test-2029-contended-monitors"
+    },
+    {
+      "name": "art-run-test-2030-long-running-child"
+    },
+    {
+      "name": "art-run-test-2231-checker-heap-poisoning"
+    },
+    {
+      "name": "art-run-test-2232-write-metrics-to-log"
+    },
+    {
+      "name": "art-run-test-300-package-override"
+    },
+    {
+      "name": "art-run-test-301-abstract-protected"
+    },
+    {
+      "name": "art-run-test-302-float-conversion"
+    },
+    {
+      "name": "art-run-test-304-method-tracing"
+    },
+    {
+      "name": "art-run-test-401-optimizing-compiler"
+    },
+    {
+      "name": "art-run-test-402-optimizing-control-flow"
+    },
+    {
+      "name": "art-run-test-403-optimizing-long"
+    },
+    {
+      "name": "art-run-test-404-optimizing-allocator"
+    },
+    {
+      "name": "art-run-test-405-optimizing-long-allocator"
+    },
+    {
+      "name": "art-run-test-406-fields"
+    },
+    {
+      "name": "art-run-test-407-arrays"
+    },
+    {
+      "name": "art-run-test-408-move-bug"
+    },
+    {
+      "name": "art-run-test-409-materialized-condition"
+    },
+    {
+      "name": "art-run-test-410-floats"
+    },
+    {
+      "name": "art-run-test-411-checker-hdiv-hrem-pow2"
+    },
+    {
+      "name": "art-run-test-411-checker-instruct-simplifier-hrem"
+    },
+    {
+      "name": "art-run-test-411-optimizing-arith"
+    },
+    {
+      "name": "art-run-test-413-regalloc-regression"
+    },
+    {
+      "name": "art-run-test-414-static-fields"
+    },
+    {
+      "name": "art-run-test-418-const-string"
+    },
+    {
+      "name": "art-run-test-419-long-parameter"
+    },
+    {
+      "name": "art-run-test-420-const-class"
+    },
+    {
+      "name": "art-run-test-421-exceptions"
+    },
+    {
+      "name": "art-run-test-421-large-frame"
+    },
+    {
+      "name": "art-run-test-422-instanceof"
+    },
+    {
+      "name": "art-run-test-422-type-conversion"
+    },
+    {
+      "name": "art-run-test-423-invoke-interface"
+    },
+    {
+      "name": "art-run-test-424-checkcast"
+    },
+    {
+      "name": "art-run-test-426-monitor"
+    },
+    {
+      "name": "art-run-test-427-bitwise"
+    },
+    {
+      "name": "art-run-test-427-bounds"
+    },
+    {
+      "name": "art-run-test-429-ssa-builder"
+    },
+    {
+      "name": "art-run-test-430-live-register-slow-path"
+    },
+    {
+      "name": "art-run-test-433-gvn"
+    },
+    {
+      "name": "art-run-test-434-shifter-operand"
+    },
+    {
+      "name": "art-run-test-435-try-finally-without-catch"
+    },
+    {
+      "name": "art-run-test-436-rem-float"
+    },
+    {
+      "name": "art-run-test-436-shift-constant"
+    },
+    {
+      "name": "art-run-test-437-inline"
+    },
+    {
+      "name": "art-run-test-438-volatile"
+    },
+    {
+      "name": "art-run-test-439-npe"
+    },
+    {
+      "name": "art-run-test-439-swap-double"
+    },
+    {
+      "name": "art-run-test-440-stmp"
+    },
+    {
+      "name": "art-run-test-441-checker-inliner"
+    },
+    {
+      "name": "art-run-test-443-not-bool-inline"
+    },
+    {
+      "name": "art-run-test-444-checker-nce"
+    },
+    {
+      "name": "art-run-test-445-checker-licm"
+    },
+    {
+      "name": "art-run-test-446-checker-inliner2"
+    },
+    {
+      "name": "art-run-test-447-checker-inliner3"
+    },
+    {
+      "name": "art-run-test-449-checker-bce-rem"
+    },
+    {
+      "name": "art-run-test-451-regression-add-float"
+    },
+    {
+      "name": "art-run-test-451-spill-splot"
+    },
+    {
+      "name": "art-run-test-455-checker-gvn"
+    },
+    {
+      "name": "art-run-test-456-baseline-array-set"
+    },
+    {
+      "name": "art-run-test-458-long-to-fpu"
+    },
+    {
+      "name": "art-run-test-464-checker-inline-sharpen-calls"
+    },
+    {
+      "name": "art-run-test-465-checker-clinit-gvn"
+    },
+    {
+      "name": "art-run-test-469-condition-materialization"
+    },
+    {
+      "name": "art-run-test-470-huge-method"
+    },
+    {
+      "name": "art-run-test-471-deopt-environment"
+    },
+    {
+      "name": "art-run-test-472-type-propagation"
+    },
+    {
+      "name": "art-run-test-473-checker-inliner-constants"
+    },
+    {
+      "name": "art-run-test-473-remove-dead-block"
+    },
+    {
+      "name": "art-run-test-474-checker-boolean-input"
+    },
+    {
+      "name": "art-run-test-474-fp-sub-neg"
+    },
+    {
+      "name": "art-run-test-475-simplify-mul-zero"
+    },
+    {
+      "name": "art-run-test-476-checker-ctor-memory-barrier"
+    },
+    {
+      "name": "art-run-test-476-clinit-inline-static-invoke"
+    },
+    {
+      "name": "art-run-test-477-checker-bound-type"
+    },
+    {
+      "name": "art-run-test-477-long-2-float-convers-precision"
+    },
+    {
+      "name": "art-run-test-478-checker-inline-noreturn"
+    },
+    {
+      "name": "art-run-test-478-checker-inliner-nested-loop"
+    },
+    {
+      "name": "art-run-test-479-regression-implicit-null-check"
+    },
+    {
+      "name": "art-run-test-480-checker-dead-blocks"
+    },
+    {
+      "name": "art-run-test-481-regression-phi-cond"
+    },
+    {
+      "name": "art-run-test-483-dce-block"
+    },
+    {
+      "name": "art-run-test-485-checker-dce-switch"
+    },
+    {
+      "name": "art-run-test-486-checker-must-do-null-check"
+    },
+    {
+      "name": "art-run-test-487-checker-inline-calls"
+    },
+    {
+      "name": "art-run-test-488-checker-inline-recursive-calls"
+    },
+    {
+      "name": "art-run-test-489-current-method-regression"
+    },
+    {
+      "name": "art-run-test-490-checker-inline"
+    },
+    {
+      "name": "art-run-test-491-current-method"
+    },
+    {
+      "name": "art-run-test-492-checker-inline-invoke-interface"
+    },
+    {
+      "name": "art-run-test-493-checker-inline-invoke-interface"
+    },
+    {
+      "name": "art-run-test-494-checker-instanceof-tests"
+    },
+    {
+      "name": "art-run-test-495-checker-checkcast-tests"
+    },
+    {
+      "name": "art-run-test-496-checker-inlining-class-loader"
+    },
+    {
+      "name": "art-run-test-499-bce-phi-array-length"
+    },
+    {
+      "name": "art-run-test-500-instanceof"
+    },
+    {
+      "name": "art-run-test-505-simplifier-type-propagation"
+    },
+    {
+      "name": "art-run-test-507-boolean-test"
+    },
+    {
+      "name": "art-run-test-507-referrer"
+    },
+    {
+      "name": "art-run-test-508-checker-disassembly"
+    },
+    {
+      "name": "art-run-test-508-referrer-method"
+    },
+    {
+      "name": "art-run-test-513-array-deopt"
+    },
+    {
+      "name": "art-run-test-514-shifts"
+    },
+    {
+      "name": "art-run-test-519-bound-load-class"
+    },
+    {
+      "name": "art-run-test-521-checker-array-set-null"
+    },
+    {
+      "name": "art-run-test-521-regression-integer-field-set"
+    },
+    {
+      "name": "art-run-test-524-boolean-simplifier-regression"
+    },
+    {
+      "name": "art-run-test-525-checker-arrays-fields1"
+    },
+    {
+      "name": "art-run-test-525-checker-arrays-fields2"
+    },
+    {
+      "name": "art-run-test-526-long-regalloc"
+    },
+    {
+      "name": "art-run-test-527-checker-array-access-simd"
+    },
+    {
+      "name": "art-run-test-527-checker-array-access-split"
+    },
+    {
+      "name": "art-run-test-528-long-hint"
+    },
+    {
+      "name": "art-run-test-529-long-split"
+    },
+    {
+      "name": "art-run-test-530-checker-loops1"
+    },
+    {
+      "name": "art-run-test-530-checker-loops2"
+    },
+    {
+      "name": "art-run-test-530-checker-loops3"
+    },
+    {
+      "name": "art-run-test-530-checker-loops4"
+    },
+    {
+      "name": "art-run-test-530-checker-loops5"
+    },
+    {
+      "name": "art-run-test-530-checker-lse-ctor-fences"
+    },
+    {
+      "name": "art-run-test-530-checker-lse-simd"
+    },
+    {
+      "name": "art-run-test-530-instanceof-checkcast"
+    },
+    {
+      "name": "art-run-test-532-checker-nonnull-arrayset"
+    },
+    {
+      "name": "art-run-test-534-checker-bce-deoptimization"
+    },
+    {
+      "name": "art-run-test-535-deopt-and-inlining"
+    },
+    {
+      "name": "art-run-test-536-checker-intrinsic-optimization"
+    },
+    {
+      "name": "art-run-test-537-checker-arraycopy"
+    },
+    {
+      "name": "art-run-test-537-checker-jump-over-jump"
+    },
+    {
+      "name": "art-run-test-538-checker-embed-constants"
+    },
+    {
+      "name": "art-run-test-540-checker-rtp-bug"
+    },
+    {
+      "name": "art-run-test-542-bitfield-rotates"
+    },
+    {
+      "name": "art-run-test-542-inline-trycatch"
+    },
+    {
+      "name": "art-run-test-542-unresolved-access-check"
+    },
+    {
+      "name": "art-run-test-545-tracing-and-jit"
+    },
+    {
+      "name": "art-run-test-548-checker-inlining-and-dce"
+    },
+    {
+      "name": "art-run-test-549-checker-types-merge"
+    },
+    {
+      "name": "art-run-test-550-checker-multiply-accumulate"
+    },
+    {
+      "name": "art-run-test-550-new-instance-clinit"
+    },
+    {
+      "name": "art-run-test-551-checker-clinit"
+    },
+    {
+      "name": "art-run-test-551-implicit-null-checks"
+    },
+    {
+      "name": "art-run-test-552-checker-x86-avx2-bit-manipulation"
+    },
+    {
+      "name": "art-run-test-554-checker-rtp-checkcast"
+    },
+    {
+      "name": "art-run-test-557-checker-instruct-simplifier-ror"
+    },
+    {
+      "name": "art-run-test-558-switch"
+    },
+    {
+      "name": "art-run-test-559-bce-ssa"
+    },
+    {
+      "name": "art-run-test-559-checker-rtp-ifnotnull"
+    },
+    {
+      "name": "art-run-test-560-packed-switch"
+    },
+    {
+      "name": "art-run-test-561-divrem"
+    },
+    {
+      "name": "art-run-test-561-shared-slowpaths"
+    },
+    {
+      "name": "art-run-test-562-bce-preheader"
+    },
+    {
+      "name": "art-run-test-563-checker-invoke-super"
+    },
+    {
+      "name": "art-run-test-564-checker-bitcount"
+    },
+    {
+      "name": "art-run-test-564-checker-inline-loop"
+    },
+    {
+      "name": "art-run-test-564-checker-negbitwise"
+    },
+    {
+      "name": "art-run-test-565-checker-condition-liveness"
+    },
+    {
+      "name": "art-run-test-566-checker-codegen-select"
+    },
+    {
+      "name": "art-run-test-567-checker-builder-intrinsics"
+    },
+    {
+      "name": "art-run-test-568-checker-onebit"
+    },
+    {
+      "name": "art-run-test-570-checker-select"
+    },
+    {
+      "name": "art-run-test-572-checker-array-get-regression"
+    },
+    {
+      "name": "art-run-test-573-checker-checkcast-regression"
+    },
+    {
+      "name": "art-run-test-576-polymorphic-inlining"
+    },
+    {
+      "name": "art-run-test-577-checker-fp2int"
+    },
+    {
+      "name": "art-run-test-578-bce-visit"
+    },
+    {
+      "name": "art-run-test-578-polymorphic-inlining"
+    },
+    {
+      "name": "art-run-test-579-inline-infinite"
+    },
+    {
+      "name": "art-run-test-580-checker-round"
+    },
+    {
+      "name": "art-run-test-580-crc32"
+    },
+    {
+      "name": "art-run-test-581-rtp"
+    },
+    {
+      "name": "art-run-test-582-checker-bce-length"
+    },
+    {
+      "name": "art-run-test-584-checker-div-bool"
+    },
+    {
+      "name": "art-run-test-589-super-imt"
+    },
+    {
+      "name": "art-run-test-590-checker-arr-set-null-regression"
+    },
+    {
+      "name": "art-run-test-591-checker-regression-dead-loop"
+    },
+    {
+      "name": "art-run-test-593-checker-long-2-float-regression"
+    },
+    {
+      "name": "art-run-test-594-checker-array-alias"
+    },
+    {
+      "name": "art-run-test-594-load-string-regression"
+    },
+    {
+      "name": "art-run-test-603-checker-instanceof"
+    },
+    {
+      "name": "art-run-test-605-new-string-from-bytes"
+    },
+    {
+      "name": "art-run-test-607-daemon-stress"
+    },
+    {
+      "name": "art-run-test-609-checker-inline-interface"
+    },
+    {
+      "name": "art-run-test-609-checker-x86-bounds-check"
+    },
+    {
+      "name": "art-run-test-610-arraycopy"
+    },
+    {
+      "name": "art-run-test-611-checker-simplify-if"
+    },
+    {
+      "name": "art-run-test-614-checker-dump-constant-location"
+    },
+    {
+      "name": "art-run-test-615-checker-arm64-store-zero"
+    },
+    {
+      "name": "art-run-test-617-clinit-oome"
+    },
+    {
+      "name": "art-run-test-618-checker-induction"
+    },
+    {
+      "name": "art-run-test-619-checker-current-method"
+    },
+    {
+      "name": "art-run-test-620-checker-bce-intrinsics"
+    },
+    {
+      "name": "art-run-test-622-checker-bce-regressions"
+    },
+    {
+      "name": "art-run-test-625-checker-licm-regressions"
+    },
+    {
+      "name": "art-run-test-627-checker-unroll"
+    },
+    {
+      "name": "art-run-test-628-vdex"
+    },
+    {
+      "name": "art-run-test-631-checker-get-class"
+    },
+    {
+      "name": "art-run-test-632-checker-char-at-bounds"
+    },
+    {
+      "name": "art-run-test-635-checker-arm64-volatile-load-cc"
+    },
+    {
+      "name": "art-run-test-636-arm64-veneer-pool"
+    },
+    {
+      "name": "art-run-test-637-checker-throw-inline"
+    },
+    {
+      "name": "art-run-test-640-checker-boolean-simd"
+    },
+    {
+      "name": "art-run-test-640-checker-integer-valueof"
+    },
+    {
+      "name": "art-run-test-640-checker-simd"
+    },
+    {
+      "name": "art-run-test-641-checker-arraycopy"
+    },
+    {
+      "name": "art-run-test-641-iterations"
+    },
+    {
+      "name": "art-run-test-643-checker-bogus-ic"
+    },
+    {
+      "name": "art-run-test-645-checker-abs-simd"
+    },
+    {
+      "name": "art-run-test-646-checker-arraycopy-large-cst-pos"
+    },
+    {
+      "name": "art-run-test-646-checker-long-const-to-int"
+    },
+    {
+      "name": "art-run-test-646-checker-simd-hadd"
+    },
+    {
+      "name": "art-run-test-650-checker-inline-access-thunks"
+    },
+    {
+      "name": "art-run-test-654-checker-periodic"
+    },
+    {
+      "name": "art-run-test-655-checker-simd-arm-opt"
+    },
+    {
+      "name": "art-run-test-656-checker-simd-opt"
+    },
+    {
+      "name": "art-run-test-657-branches"
+    },
+    {
+      "name": "art-run-test-658-fp-read-barrier"
+    },
+    {
+      "name": "art-run-test-660-checker-sad"
+    },
+    {
+      "name": "art-run-test-660-checker-simd-sad"
+    },
+    {
+      "name": "art-run-test-661-checker-simd-reduc"
+    },
+    {
+      "name": "art-run-test-662-regression-alias"
+    },
+    {
+      "name": "art-run-test-665-checker-simd-zero"
+    },
+    {
+      "name": "art-run-test-666-dex-cache-itf"
+    },
+    {
+      "name": "art-run-test-667-checker-simd-alignment"
+    },
+    {
+      "name": "art-run-test-667-out-of-bounds"
+    },
+    {
+      "name": "art-run-test-669-checker-break"
+    },
+    {
+      "name": "art-run-test-671-npe-field-opts"
+    },
+    {
+      "name": "art-run-test-672-checker-throw-method"
+    },
+    {
+      "name": "art-run-test-673-checker-throw-vmethod"
+    },
+    {
+      "name": "art-run-test-674-HelloWorld-Dm"
+    },
+    {
+      "name": "art-run-test-676-proxy-jit-at-first-use"
+    },
+    {
+      "name": "art-run-test-677-fsi2"
+    },
+    {
+      "name": "art-run-test-680-sink-regression"
+    },
+    {
+      "name": "art-run-test-684-checker-simd-dotprod"
+    },
+    {
+      "name": "art-run-test-684-select-condition"
+    },
+    {
+      "name": "art-run-test-689-multi-catch"
+    },
+    {
+      "name": "art-run-test-694-clinit-jit"
+    },
+    {
+      "name": "art-run-test-695-simplify-throws"
+    },
+    {
+      "name": "art-run-test-696-loop"
+    },
+    {
+      "name": "art-run-test-697-checker-string-append"
+    },
+    {
+      "name": "art-run-test-698-selects"
+    },
+    {
+      "name": "art-run-test-700-LoadArgRegs"
+    },
+    {
+      "name": "art-run-test-703-floating-point-div"
+    },
+    {
+      "name": "art-run-test-704-multiply-accumulate"
+    },
+    {
+      "name": "art-run-test-705-register-conflict"
+    },
+    {
+      "name": "art-run-test-711-checker-type-conversion"
+    },
+    {
+      "name": "art-run-test-718-zipfile-finalizer"
+    },
+    {
+      "name": "art-run-test-721-osr"
+    },
+    {
+      "name": "art-run-test-726-array-store"
+    },
+    {
+      "name": "art-run-test-730-checker-inlining-super"
+    },
+    {
+      "name": "art-run-test-805-TooDeepClassInstanceOf"
+    },
+    {
+      "name": "art-run-test-806-TooWideClassInstanceOf"
+    },
+    {
+      "name": "art-run-test-812-recursive-default"
+    },
+    {
+      "name": "art-run-test-814-large-field-offsets"
+    },
+    {
+      "name": "art-run-test-815-invokeinterface-default"
+    },
+    {
+      "name": "art-run-test-818-clinit-nterp"
+    },
+    {
+      "name": "art-run-test-821-madvise-willneed"
+    },
+    {
+      "name": "art-run-test-963-default-range-smali"
+    },
+    {
+      "name": "art_standalone_cmdline_tests"
+    },
+    {
+      "name": "art_standalone_compiler_tests"
+    },
+    {
+      "name": "art_standalone_dex2oat_tests"
+    },
+    {
+      "name": "art_standalone_dexdump_tests"
+    },
+    {
+      "name": "art_standalone_dexlist_tests"
+    },
+    {
+      "name": "art_standalone_dexoptanalyzer_tests"
+    },
+    {
+      "name": "art_standalone_libartbase_tests"
+    },
+    {
+      "name": "art_standalone_libartpalette_tests"
+    },
+    {
+      "name": "art_standalone_libdexfile_support_tests"
+    },
+    {
+      "name": "art_standalone_libdexfile_tests"
+    },
+    {
+      "name": "art_standalone_libprofile_tests"
+    },
+    {
+      "name": "art_standalone_oatdump_tests"
+    },
+    {
+      "name": "art_standalone_odrefresh_tests"
+    },
+    {
+      "name": "art_standalone_profman_tests"
+    },
+    {
+      "name": "art_standalone_runtime_compiler_tests"
+    },
+    {
+      "name": "art_standalone_runtime_tests"
+    },
+    {
+      "name": "art_standalone_sigchain_tests"
     }
   ]
 }
diff --git a/adbconnection/Android.bp b/adbconnection/Android.bp
index b03cd0d..ecad650 100644
--- a/adbconnection/Android.bp
+++ b/adbconnection/Android.bp
@@ -16,6 +16,15 @@
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "adbconnection-defaults",
     host_supported: true,
@@ -55,7 +64,7 @@
         "libartbase",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
diff --git a/adbconnection/adbconnection.cc b/adbconnection/adbconnection.cc
index 7ac2edb..cca4485 100644
--- a/adbconnection/adbconnection.cc
+++ b/adbconnection/adbconnection.cc
@@ -24,6 +24,7 @@
 #include "android-base/endian.h"
 #include "android-base/stringprintf.h"
 #include "base/file_utils.h"
+#include "base/globals.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/mutex.h"
@@ -61,6 +62,7 @@
 using dt_fd_forward::kListenEndMessage;
 using dt_fd_forward::kAcceptMessage;
 using dt_fd_forward::kCloseMessage;
+using dt_fd_forward::kHandshakeCompleteMessage;
 
 // Messages sent to the transport
 using dt_fd_forward::kPerformHandshakeMessage;
@@ -93,7 +95,10 @@
 
 // Begin running the debugger.
 void AdbConnectionDebuggerController::StartDebugger() {
-  if (IsDebuggingPossible()) {
+  // The debugger thread is started for a debuggable or profileable-from-shell process.
+  // The pid will be send to adbd for adb's "track-jdwp" and "track-app" services.
+  // The thread will also set up the jdwp tunnel if the process is debuggable.
+  if (IsDebuggingPossible() || art::Runtime::Current()->IsProfileableFromShell()) {
     connection_->StartDebuggerThreads();
   } else {
     LOG(ERROR) << "Not starting debugger since process cannot load the jdwp agent.";
@@ -161,11 +166,6 @@
     notified_ddm_active_(false),
     next_ddm_id_(1),
     started_debugger_threads_(false) {
-  // Setup the addr.
-  control_addr_.controlAddrUn.sun_family = AF_UNIX;
-  control_addr_len_ = sizeof(control_addr_.controlAddrUn.sun_family) + sizeof(kJdwpControlName) - 1;
-  memcpy(control_addr_.controlAddrUn.sun_path, kJdwpControlName, sizeof(kJdwpControlName) - 1);
-
   // Add the startup callback.
   art::ScopedObjectAccess soa(art::Thread::Current());
   art::Runtime::Current()->GetRuntimeCallbacks()->AddDebuggerControlCallback(&controller_);
@@ -346,7 +346,7 @@
                                        art::ArrayRef<const uint8_t> data) {
   // Get the write_event early to fail fast.
   ScopedEventFdLock lk(adb_write_event_fd_);
-  if (adb_connection_socket_ == -1) {
+  if (adb_connection_socket_ == -1 || !performed_handshake_) {
     VLOG(jdwp) << "Not sending ddms data of type "
                << StringPrintf("%c%c%c%c",
                                static_cast<char>(type >> 24),
@@ -481,11 +481,20 @@
   int sleep_ms = 500;
   const int sleep_max_ms = 2 * 1000;
 
+  const char* isa = GetInstructionSetString(art::Runtime::Current()->GetInstructionSet());
   const AdbConnectionClientInfo infos[] = {
-    {.type = AdbConnectionClientInfoType::pid, .data.pid = static_cast<uint64_t>(getpid())},
-    {.type = AdbConnectionClientInfoType::debuggable, .data.debuggable = true},
+      {.type = AdbConnectionClientInfoType::pid,
+       .data.pid = static_cast<uint64_t>(getpid())},
+      {.type = AdbConnectionClientInfoType::debuggable,
+       .data.debuggable = IsDebuggingPossible()},
+      {.type = AdbConnectionClientInfoType::profileable,
+       .data.profileable = art::Runtime::Current()->IsProfileableFromShell()},
+      {.type = AdbConnectionClientInfoType::architecture,
+       // GetInstructionSetString() returns a null-terminating C-style string.
+       .data.architecture.name = isa,
+       .data.architecture.size = strlen(isa)},
   };
-  const AdbConnectionClientInfo* info_ptrs[] = {&infos[0], &infos[1]};
+  const AdbConnectionClientInfo *info_ptrs[] = {&infos[0], &infos[1], &infos[2], &infos[3]};
 
   while (!shutting_down_) {
     // If adbd isn't running, because USB debugging was disabled or
@@ -517,6 +526,7 @@
 }
 
 void AdbConnectionState::RunPollLoop(art::Thread* self) {
+  DCHECK(IsDebuggingPossible() || art::Runtime::Current()->IsProfileableFromShell());
   CHECK_NE(agent_name_, "");
   CHECK_EQ(self->GetState(), art::kNative);
   art::Locks::mutator_lock_->AssertNotHeld(self);
@@ -554,6 +564,7 @@
       const struct pollfd& control_sock_poll       = pollfds[2];
       const struct pollfd& adb_socket_poll         = pollfds[3];
       if (FlagsSet(agent_control_sock_poll.revents, POLLIN)) {
+        CHECK(IsDebuggingPossible());  // This path is unexpected for a profileable process.
         DCHECK(agent_loaded_);
         char buf[257];
         res = TEMP_FAILURE_RETRY(recv(local_agent_control_sock_, buf, sizeof(buf) - 1, 0));
@@ -571,6 +582,10 @@
           }
         } else if (memcmp(kListenEndMessage, buf, sizeof(kListenEndMessage)) == 0) {
           agent_listening_ = false;
+        } else if (memcmp(kHandshakeCompleteMessage, buf, sizeof(kHandshakeCompleteMessage)) == 0) {
+          if (agent_has_socket_) {
+            performed_handshake_ = true;
+          }
         } else if (memcmp(kCloseMessage, buf, sizeof(kCloseMessage)) == 0) {
           CloseFds();
           agent_has_socket_ = false;
@@ -583,6 +598,11 @@
           LOG(ERROR) << "Unknown message received from debugger! '" << std::string(buf) << "'";
         }
       } else if (FlagsSet(control_sock_poll.revents, POLLIN)) {
+        if (!IsDebuggingPossible()) {
+            // For a profielable process, this path can execute when the adbd restarts.
+            control_ctx_.reset();
+            break;
+        }
         bool maybe_send_fds = false;
         {
           // Hold onto this lock so that concurrent ddm publishes don't try to use an illegal fd.
@@ -613,11 +633,13 @@
       } else if (FlagsSet(control_sock_poll.revents, POLLRDHUP)) {
         // The other end of the adb connection just dropped it.
         // Reset the connection since we don't have an active socket through the adb server.
+        // Note this path is expected for either debuggable or profileable processes.
         DCHECK(!agent_has_socket_) << "We shouldn't be doing anything if there is already a "
                                    << "connection active";
         control_ctx_.reset();
         break;
       } else if (FlagsSet(adb_socket_poll.revents, POLLIN)) {
+        CHECK(IsDebuggingPossible());  // This path is unexpected for a profileable process.
         DCHECK(!agent_has_socket_);
         if (!agent_loaded_) {
           HandleDataWithoutAgent(self);
@@ -627,6 +649,7 @@
           SendAgentFds(/*require_handshake=*/ true);
         }
       } else if (FlagsSet(adb_socket_poll.revents, POLLRDHUP)) {
+        CHECK(IsDebuggingPossible());  // This path is unexpected for a profileable process.
         DCHECK(!agent_has_socket_);
         CloseFds();
       } else {
diff --git a/adbconnection/adbconnection.h b/adbconnection/adbconnection.h
index 32f42ba..6500b79 100644
--- a/adbconnection/adbconnection.h
+++ b/adbconnection/adbconnection.h
@@ -163,7 +163,7 @@
 
   std::atomic<bool> sent_agent_fds_;
 
-  bool performed_handshake_;
+  std::atomic<bool> performed_handshake_;
 
   bool notified_ddm_active_;
 
@@ -171,12 +171,6 @@
 
   bool started_debugger_threads_;
 
-  socklen_t control_addr_len_;
-  union {
-    sockaddr_un controlAddrUn;
-    sockaddr controlAddrPlain;
-  } control_addr_;
-
   friend struct AdbConnectionDebuggerController;
 };
 
diff --git a/benchmark/Android.bp b/benchmark/Android.bp
index 3995ca2..da6b9e5 100644
--- a/benchmark/Android.bp
+++ b/benchmark/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 art_cc_library {
     name: "libartbenchmark",
     host_supported: true,
@@ -25,15 +34,17 @@
         "micro-native/micro_native.cc",
         "scoped-primitive-array/scoped_primitive_array.cc",
     ],
-    shared_libs: [
-        "libart",
-        "libbacktrace",
-        "libbase",
-        "libnativehelper",
-    ],
     cflags: [
         "-Wno-frame-larger-than=",
     ],
+    header_libs: [
+        "libnativehelper_header_only",
+    ],
+    // TODO(ngeoffray): find a way to link against the libraries in the apex.
+    shared_libs: [
+        "libart",
+        "libbase",
+    ],
 }
 
 art_cc_library {
diff --git a/benchmark/scoped-primitive-array/scoped_primitive_array.cc b/benchmark/scoped-primitive-array/scoped_primitive_array.cc
index 005cae4..459e8b1 100644
--- a/benchmark/scoped-primitive-array/scoped_primitive_array.cc
+++ b/benchmark/scoped-primitive-array/scoped_primitive_array.cc
@@ -15,7 +15,7 @@
  */
 
 #include "jni.h"
-#include "nativehelper/ScopedPrimitiveArray.h"
+#include "nativehelper/scoped_primitive_array.h"
 
 extern "C" JNIEXPORT jlong JNICALL Java_ScopedPrimitiveArrayBenchmark_measureByteArray(
     JNIEnv* env, jclass, int reps, jbyteArray arr) {
diff --git a/build/Android.bp b/build/Android.bp
index 946e5a6..21858db 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 bootstrap_go_package {
     name: "soong-art",
     pkgPath: "android/soong/art",
@@ -54,11 +63,30 @@
     "-modernize-pass-by-value",
 ]
 
-art_global_defaults {
+soong_config_module_type_import {
+    from: "art/build/SoongConfig.bp",
+    module_types: [
+        "art_module_art_global_defaults",
+        "art_module_cc_defaults",
+        "art_module_java_defaults",
+    ],
+}
+
+art_module_art_global_defaults {
     // Additional flags are computed by art.go
 
     name: "art_defaults",
 
+    // Disable all ART Soong modules by default when ART prebuilts are in use.
+    // TODO(b/172480617): Clean up when sources are gone from the platform tree
+    // and we no longer need to support sources present when prebuilts are used.
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+
     // This is the default visibility for the //art package, but we repeat it
     // here so that it gets merged with other visibility rules in modules
     // extending these defaults.
@@ -137,8 +165,6 @@
     target: {
         android: {
             cflags: [
-                "-DART_TARGET",
-
                 // To use oprofile_android --callgraph, uncomment this and recompile with
                 //    mmma -j art
                 // "-fno-omit-frame-pointer",
@@ -173,6 +199,13 @@
         darwin: {
             enabled: false,
         },
+        windows: {
+            // When the module is enabled globally in the soong_config_variables
+            // stanza above, it may get enabled on windows too for some module
+            // types. Hence we need to disable it explicitly.
+            // TODO(b/172480617): Clean up with that.
+            enabled: false,
+        },
         host: {
             cflags: [
                 // Bug: 15446488. We don't omit the frame pointer to work around
@@ -223,6 +256,51 @@
         // will still get the "real" errors.
         "-extra-arg=-Wno-unreachable-code",
     ],
+
+    min_sdk_version: "S",
+}
+
+// Used to generate binaries that can be backed by transparent hugepages.
+cc_defaults {
+    name: "art_hugepage_defaults",
+    arch: {
+        arm64: {
+            ldflags: ["-z max-page-size=0x200000"],
+        },
+        x86_64: {
+            ldflags: ["-z max-page-size=0x200000"],
+        },
+    },
+}
+
+cc_defaults {
+    name: "art_pgo_defaults",
+    visibility: ["//art:__subpackages__"],
+    pgo: {
+        sampling: true,
+    },
+    target: {
+        android_arm64: {
+            pgo: {
+                profile_file: "art/art_arm_arm64.profdata",
+            },
+        },
+        android_arm: {
+            pgo: {
+                profile_file: "art/art_arm_arm64.profdata",
+            },
+        },
+        android_x86_64: {
+            pgo: {
+                profile_file: "art/art_x86_x86_64.profdata",
+            },
+        },
+        android_x86: {
+            pgo: {
+                profile_file: "art/art_x86_x86_64.profdata",
+            },
+        },
+    },
 }
 
 art_debug_defaults {
@@ -247,4 +325,102 @@
             cflags: ["-Wno-frame-larger-than="],
         },
     },
+
+    min_sdk_version: "S",
+}
+
+// Use this to enable a cc_* module only when building ART from sources.
+// TODO(b/172480617): Clean up when sources are gone from the platform tree and
+// we no longer need to support sources present when prebuilts are used.
+art_module_cc_defaults {
+    name: "art_module_source_build_defaults",
+    defaults_visibility: [
+        "//art:__subpackages__",
+        "//libcore:__subpackages__",
+        "//libnativehelper:__subpackages__",
+    ],
+
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+    target: {
+        windows: {
+            // Windows is disabled by default, but if we set enabled:true
+            // globally above we need to disable it explicitly.
+            enabled: false,
+        },
+    },
+}
+
+// Use this to enable a java_* module only when building ART from sources.
+// TODO(b/172480617): Clean up when sources are gone from the platform tree and
+// we no longer need to support sources present when prebuilts are used.
+art_module_java_defaults {
+    name: "art_module_source_build_java_defaults",
+    defaults_visibility: [
+        "//art:__subpackages__",
+        "//libcore:__subpackages__",
+        "//libnativehelper:__subpackages__",
+    ],
+
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+    target: {
+        windows: {
+            // Windows is disabled by default, but if we set enabled:true
+            // globally above we need to disable it explicitly.
+            enabled: false,
+        },
+    },
+}
+
+// A version of conscrypt only for enabling the "-hostdex" version to test ART on host.
+java_library {
+    // We need our own name to not clash with the conscrypt library.
+    name: "conscrypt-host",
+    installable: true,
+    hostdex: true,
+    static_libs: ["conscrypt-for-host"],
+
+    // Tests and build files rely on this file to be installed as "conscrypt-hostdex",
+    // therefore set a stem. Without it, the file would be installed as
+    // "conscrypt-host-hostdex".
+    stem: "conscrypt",
+    sdk_version: "core_platform",
+    target: {
+        hostdex: {
+            required: ["libjavacrypto"],
+        },
+        darwin: {
+            // required module "libjavacrypto" is disabled on darwin
+            enabled: false,
+        },
+    },
+}
+
+// A version of core-icu4j only for enabling the "-hostdex" version to test ART on host.
+java_library {
+    // We need our own name to not clash with the core-icu4j library.
+    name: "core-icu4j-host",
+    installable: true,
+    hostdex: true,
+    static_libs: ["core-icu4j-for-host"],
+
+    // Tests and build files rely on this file to be installed as "core-icu4j-hostdex",
+    // therefore set a stem. Without it, the file would be installed as
+    // "core-icu4j-host-hostdex".
+    stem: "core-icu4j",
+    sdk_version: "core_platform",
+    target: {
+        hostdex: {
+            required: ["libicu_jni"],
+        },
+    },
 }
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 4d702e4..9ca4d0f 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -19,7 +19,8 @@
 
 ART_TARGET_SUPPORTED_ARCH := arm arm64 x86 x86_64
 ART_HOST_SUPPORTED_ARCH := x86 x86_64
-ART_DEXPREOPT_BOOT_JAR_DIR := system/framework
+ART_DEXPREOPT_BOOT_JAR_DIR := apex/com.android.art/javalib
+CONSCRYPT_DEXPREOPT_BOOT_JAR_DIR := apex/com.android.conscrypt/javalib
 
 ifneq ($(HOST_OS),darwin)
   ART_HOST_SUPPORTED_ARCH := x86 x86_64
diff --git a/build/Android.common_path.mk b/build/Android.common_path.mk
index 3403f2d..c6f4819 100644
--- a/build/Android.common_path.mk
+++ b/build/Android.common_path.mk
@@ -17,6 +17,21 @@
 ifndef ART_ANDROID_COMMON_PATH_MK
 ART_ANDROID_COMMON_PATH_MK := true
 
+# We cannot build things that require host core images from prebuilts, because
+# they aren't present there. Set up a variable to skip all build rules that
+# relate to them, because `m checkbuild` complains on rules with nonexisting
+# dependencies, even if they won't get called.
+# TODO(b/172480617): Remove this when ART sources are no longer in platform manifests.
+ifeq (true,$(SOONG_CONFIG_art_module_source_build))
+  my_art_module_source_build := true
+else ifeq (false,$(SOONG_CONFIG_art_module_source_build))
+  my_art_module_source_build := false
+else
+  $(error SOONG_CONFIG_art_module_source_build is neither true nor false - mk file ordering problem?)
+endif
+
+ifeq (true,$(my_art_module_source_build))
+
 include art/build/Android.common.mk
 include art/build/Android.common_build.mk
 
@@ -35,48 +50,10 @@
 ART_TARGET_TEST_DIR := /data/art-test
 ART_TARGET_TEST_OUT := $(TARGET_OUT_DATA)/art-test
 
-# core.oat location on the device.
-TARGET_CORE_OAT := $(ART_TARGET_TEST_DIR)/$(DEX2OAT_TARGET_ARCH)/core.oat
-ifdef TARGET_2ND_ARCH
-2ND_TARGET_CORE_OAT := $(ART_TARGET_TEST_DIR)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)/core.oat
-endif
-
-CORE_OAT_SUFFIX := .oat
-
-# core.oat locations under the out directory.
-HOST_CORE_OAT_OUT_BASE := $(HOST_OUT_JAVA_LIBRARIES)/$(ART_HOST_ARCH)/core
-ifneq ($(HOST_PREFER_32_BIT),true)
-2ND_HOST_CORE_OAT_OUT_BASE := $(HOST_OUT_JAVA_LIBRARIES)/$(2ND_ART_HOST_ARCH)/core
-endif
-HOST_CORE_OAT_OUTS :=
-TARGET_CORE_OAT_OUT_BASE := $(ART_TARGET_TEST_OUT)/$(DEX2OAT_TARGET_ARCH)/core
-ifdef TARGET_2ND_ARCH
-2ND_TARGET_CORE_OAT_OUT_BASE := $(ART_TARGET_TEST_OUT)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)/core
-endif
-TARGET_CORE_OAT_OUTS :=
-
-CORE_IMG_SUFFIX := .art
-
-# core.art locations under the out directory.
-HOST_CORE_IMG_OUT_BASE := $(HOST_OUT_JAVA_LIBRARIES)/$(ART_HOST_ARCH)/core
-ifneq ($(HOST_PREFER_32_BIT),true)
-2ND_HOST_CORE_IMG_OUT_BASE := $(HOST_OUT_JAVA_LIBRARIES)/$(2ND_ART_HOST_ARCH)/core
-endif
-HOST_CORE_IMG_OUTS :=
-TARGET_CORE_IMG_OUT_BASE := $(ART_TARGET_TEST_OUT)/$(DEX2OAT_TARGET_ARCH)/core
-ifdef TARGET_2ND_ARCH
-2ND_TARGET_CORE_IMG_OUT_BASE := $(ART_TARGET_TEST_OUT)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)/core
-endif
-TARGET_CORE_IMG_OUTS :=
-
-# Oat location of core.art.
-HOST_CORE_IMG_LOCATION := $(HOST_OUT_JAVA_LIBRARIES)/core.art
-TARGET_CORE_IMG_LOCATION := $(ART_TARGET_TEST_OUT)/core.art
-
 # Modules to compile for core.art.
-CORE_IMG_JARS := core-oj core-libart core-icu4j okhttp bouncycastle apache-xml
+CORE_IMG_JARS := core-oj core-libart okhttp bouncycastle apache-xml
 HOST_CORE_IMG_JARS   := $(addsuffix -hostdex,$(CORE_IMG_JARS))
-TARGET_CORE_IMG_JARS := $(addsuffix -testdex,$(CORE_IMG_JARS))
+TARGET_CORE_IMG_JARS := $(CORE_IMG_JARS)
 HOST_CORE_IMG_DEX_LOCATIONS   := $(foreach jar,$(HOST_CORE_IMG_JARS),  $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
 ifeq ($(ART_TEST_ANDROID_ROOT),)
 TARGET_CORE_IMG_DEX_LOCATIONS := $(foreach jar,$(TARGET_CORE_IMG_JARS),/$(ART_DEXPREOPT_BOOT_JAR_DIR)/$(jar).jar)
@@ -84,30 +61,33 @@
 TARGET_CORE_IMG_DEX_LOCATIONS := $(foreach jar,$(TARGET_CORE_IMG_JARS),$(ART_TEST_ANDROID_ROOT)/$(jar).jar)
 endif
 HOST_CORE_IMG_DEX_FILES   := $(foreach jar,$(HOST_CORE_IMG_JARS),  $(call intermediates-dir-for,JAVA_LIBRARIES,$(jar),t,COMMON)/javalib.jar)
-TARGET_CORE_IMG_DEX_FILES := $(foreach jar,$(TARGET_CORE_IMG_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar), ,COMMON)/javalib.jar)
+TARGET_CORE_IMG_DEX_FILES := $(foreach jar,$(TARGET_CORE_IMG_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar).com.android.art.testing, ,COMMON)/javalib.jar)
 
-# Jar files for the boot class path for testing. Must start with 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)
-ifeq ($(ART_TEST_ANDROID_ROOT),)
-TARGET_CORE_DEX_LOCATIONS := $(foreach jar,$(TARGET_TEST_CORE_JARS),/$(ART_DEXPREOPT_BOOT_JAR_DIR)/$(jar).jar)
-else
-TARGET_CORE_DEX_LOCATIONS := $(foreach jar,$(TARGET_TEST_CORE_JARS),$(ART_TEST_ANDROID_ROOT)/framework/$(jar).jar)
-endif
-HOST_CORE_DEX_FILES   := $(foreach jar,$(HOST_TEST_CORE_JARS),  $(call intermediates-dir-for,JAVA_LIBRARIES,$(jar),t,COMMON)/javalib.jar)
-TARGET_CORE_DEX_FILES := $(foreach jar,$(TARGET_TEST_CORE_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar), ,COMMON)/javalib.jar)
+# Also copy the jar files next to host boot.art image.
+HOST_BOOT_IMAGE_JARS := $(foreach jar,$(CORE_IMG_JARS),$(HOST_OUT)/apex/com.android.art/javalib/$(jar).jar)
+$(HOST_BOOT_IMAGE_JARS): $(HOST_OUT)/apex/com.android.art/javalib/%.jar : $(HOST_OUT_JAVA_LIBRARIES)/%-hostdex.jar
+	$(copy-file-to-target)
 
+HOST_BOOT_IMAGE_JARS += $(HOST_OUT)/apex/com.android.conscrypt/javalib/conscrypt.jar
+$(HOST_OUT)/apex/com.android.conscrypt/javalib/conscrypt.jar : $(HOST_OUT_JAVA_LIBRARIES)/conscrypt-hostdex.jar
+	$(copy-file-to-target)
+HOST_BOOT_IMAGE_JARS += $(HOST_OUT)/apex/com.android.i18n/javalib/core-icu4j.jar
+$(HOST_OUT)/apex/com.android.i18n/javalib/core-icu4j.jar : $(HOST_OUT_JAVA_LIBRARIES)/core-icu4j-hostdex.jar
+	$(copy-file-to-target)
+
+HOST_CORE_IMG_OUTS += $(HOST_BOOT_IMAGE_JARS) $(HOST_BOOT_IMAGE) $(2ND_HOST_BOOT_IMAGE)
+
+HOST_TEST_CORE_JARS   := $(addsuffix -hostdex,$(CORE_IMG_JARS) core-icu4j conscrypt)
 ART_HOST_DEX_DEPENDENCIES := $(foreach jar,$(HOST_TEST_CORE_JARS),$(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
-ART_TARGET_DEX_DEPENDENCIES := $(foreach jar,$(TARGET_TEST_CORE_JARS),$(TARGET_OUT_JAVA_LIBRARIES)/$(jar).jar)
+ART_TARGET_DEX_DEPENDENCIES := com.android.art.testing com.android.conscrypt com.android.i18n
 
-ART_CORE_SHARED_LIBRARIES := libicu_jni libjavacore libopenjdk libopenjdkjvm libopenjdkjvmti
+ART_CORE_SHARED_LIBRARIES := libjavacore libopenjdk libopenjdkjvm libopenjdkjvmti
 ART_CORE_SHARED_DEBUG_LIBRARIES := libopenjdkd libopenjdkjvmd libopenjdkjvmtid
-ART_HOST_SHARED_LIBRARY_DEPENDENCIES := $(foreach lib,$(ART_CORE_SHARED_LIBRARIES), $(ART_HOST_OUT_SHARED_LIBRARIES)/$(lib)$(ART_HOST_SHLIB_EXTENSION))
+ART_HOST_CORE_SHARED_LIBRARIES := $(ART_CORE_SHARED_LIBRARIES) libicuuc-host libicui18n-host libicu_jni
+ART_HOST_SHARED_LIBRARY_DEPENDENCIES := $(foreach lib,$(ART_HOST_CORE_SHARED_LIBRARIES), $(ART_HOST_OUT_SHARED_LIBRARIES)/$(lib)$(ART_HOST_SHLIB_EXTENSION))
 ART_HOST_SHARED_LIBRARY_DEBUG_DEPENDENCIES := $(foreach lib,$(ART_CORE_SHARED_DEBUG_LIBRARIES), $(ART_HOST_OUT_SHARED_LIBRARIES)/$(lib)$(ART_HOST_SHLIB_EXTENSION))
 ifdef HOST_2ND_ARCH
-ART_HOST_SHARED_LIBRARY_DEPENDENCIES += $(foreach lib,$(ART_CORE_SHARED_LIBRARIES), $(2ND_HOST_OUT_SHARED_LIBRARIES)/$(lib).so)
+ART_HOST_SHARED_LIBRARY_DEPENDENCIES += $(foreach lib,$(ART_HOST_CORE_SHARED_LIBRARIES), $(2ND_HOST_OUT_SHARED_LIBRARIES)/$(lib).so)
 ART_HOST_SHARED_LIBRARY_DEBUG_DEPENDENCIES += $(foreach lib,$(ART_CORE_SHARED_DEBUG_LIBRARIES), $(2ND_HOST_OUT_SHARED_LIBRARIES)/$(lib).so)
 endif
 
@@ -124,6 +104,7 @@
     dexoptanalyzer \
     imgdiag \
     oatdump \
+    odrefresh \
     profman \
 
 ART_CORE_EXECUTABLES := \
@@ -149,14 +130,24 @@
 endif
 
 # Release ART APEX, included by default in "user" builds.
-RELEASE_ART_APEX := com.android.art.release
+RELEASE_ART_APEX := com.android.art
 # Debug ART APEX, included by default in "userdebug" and "eng"
 # builds and used in ART device benchmarking.
 DEBUG_ART_APEX := com.android.art.debug
 # Testing ART APEX, used in ART device testing.
 TESTING_ART_APEX := com.android.art.testing
 
-# Conscrypt APEX
+RUNTIME_APEX := com.android.runtime
 CONSCRYPT_APEX := com.android.conscrypt
+I18N_APEX := com.android.i18n
+STATSD_APEX := com.android.os.statsd
+TZDATA_APEX := com.android.tzdata
+
+# A phony file to create the ICU data file for host.
+HOST_I18N_DATA := $(HOST_OUT)/$(I18N_APEX)/timestamp
+# A phony file to create the tz data file for host.
+HOST_TZDATA_DATA := $(HOST_OUT)/$(TZDATA_APEX)/timestamp
+
+endif # ifeq (true,$(my_art_module_source_build))
 
 endif # ART_ANDROID_COMMON_PATH_MK
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk
index 55b8ae2..3a557b6 100644
--- a/build/Android.common_test.mk
+++ b/build/Android.common_test.mk
@@ -105,50 +105,4 @@
      || $(call ART_TEST_ANNOUNCE_SKIP_BROKEN,$(1)) ) && false))
 endef
 
-# Create a build rule to create the dex file for a test.
-# $(1): module prefix, e.g. art-test-dex
-# $(2): input test directory in art/test, e.g. HelloWorld
-# $(3): target output module path (default module path is used on host)
-# $(4): additional dependencies
-# $(5): a make variable used to collate target dependencies, e.g ART_TEST_TARGET_OAT_HelloWorld_DEX
-# $(6): a make variable used to collate host dependencies, e.g ART_TEST_HOST_OAT_HelloWorld_DEX
-#
-# If the input test directory contains a file called main.list,
-# then a multi-dex file is created passing main.list as the --main-dex-list
-# argument to dx.
-define build-art-test-dex
-  ifeq ($(ART_BUILD_TARGET),true)
-    include $(CLEAR_VARS)
-    LOCAL_MODULE := $(1)-$(2)
-    LOCAL_SRC_FILES := $(call all-java-files-under, $(2))
-    LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_DEX_PREOPT := false
-    LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_test.mk $(4)
-    LOCAL_MODULE_TAGS := tests
-    LOCAL_JAVA_LIBRARIES := $(TARGET_TEST_CORE_JARS)
-    LOCAL_MODULE_PATH := $(3)
-    ifneq ($(wildcard $(LOCAL_PATH)/$(2)/main.list),)
-      LOCAL_MIN_SDK_VERSION := 19
-      LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(LOCAL_PATH)/$(2)/main.list --minimal-main-dex
-    endif
-    include $(BUILD_JAVA_LIBRARY)
-    $(5) := $$(LOCAL_INSTALLED_MODULE)
-  endif
-  ifeq ($(ART_BUILD_HOST),true)
-    include $(CLEAR_VARS)
-    LOCAL_MODULE := $(1)-$(2)
-    LOCAL_SRC_FILES := $(call all-java-files-under, $(2))
-    LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_DEX_PREOPT := false
-    LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_test.mk $(4)
-    LOCAL_JAVA_LIBRARIES := $(HOST_TEST_CORE_JARS)
-    ifneq ($(wildcard $(LOCAL_PATH)/$(2)/main.list),)
-      LOCAL_MIN_SDK_VERSION := 19
-      LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(LOCAL_PATH)/$(2)/main.list --minimal-main-dex
-    endif
-    include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
-    $(6) := $$(LOCAL_INSTALLED_MODULE)
-  endif
-endef
-
 endif # ART_ANDROID_COMMON_TEST_MK
diff --git a/build/Android.cpplint.mk b/build/Android.cpplint.mk
index 964a4c8..af446ff 100644
--- a/build/Android.cpplint.mk
+++ b/build/Android.cpplint.mk
@@ -67,6 +67,9 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := cpplint-art-phony
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
 LOCAL_MODULE_TAGS := optional
 LOCAL_ADDITIONAL_DEPENDENCIES := $(ART_CPPLINT_TARGETS)
 include $(BUILD_PHONY_PACKAGE)
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index a9855cd..461a70c 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -14,6 +14,85 @@
 # limitations under the License.
 #
 
+# Build rules are excluded from Mac, since we can not run ART tests there in the first place.
+ifneq ($(HOST_OS),darwin)
+
+LOCAL_PATH := $(call my-dir)
+
+###################################################################################################
+# Create module in testcases to hold all common data and tools needed for ART host tests.
+
+# ART binary tools and libraries (automatic list of all art_cc_binary/art_cc_library modules).
+my_files := $(ART_TESTCASES_CONTENT)
+
+# Manually add system libraries that we need to run the host ART tools.
+my_files += \
+  $(foreach lib, libbacktrace libbase libc++ libicu libicu_jni liblog libsigchain libunwindstack \
+    libziparchive libjavacore libandroidio libopenjdkd liblz4 liblzma, \
+    $(call intermediates-dir-for,SHARED_LIBRARIES,$(lib),HOST)/$(lib).so:lib64/$(lib).so \
+    $(call intermediates-dir-for,SHARED_LIBRARIES,$(lib),HOST,,2ND)/$(lib).so:lib/$(lib).so) \
+  $(foreach lib, libcrypto libz libicuuc libicui18n libexpat, \
+    $(call intermediates-dir-for,SHARED_LIBRARIES,$(lib),HOST)/$(lib).so:lib64/$(lib)-host.so \
+    $(call intermediates-dir-for,SHARED_LIBRARIES,$(lib),HOST,,2ND)/$(lib).so:lib/$(lib)-host.so)
+
+# Add apex directories for art, conscrypt and i18n.
+icu_data_file := $(firstword $(wildcard external/icu/icu4c/source/stubdata/icu*.dat))
+my_files += $(foreach infix,_ _VDEX_,$(foreach suffix,$(HOST_ARCH) $(HOST_2ND_ARCH), \
+  $(DEXPREOPT_IMAGE$(infix)BUILT_INSTALLED_art_host_$(suffix))))
+my_files += \
+  $(foreach jar,$(CORE_IMG_JARS),\
+    $(HOST_OUT_JAVA_LIBRARIES)/$(jar)-hostdex.jar:apex/com.android.art/javalib/$(jar).jar) \
+  $(HOST_OUT_JAVA_LIBRARIES)/conscrypt-hostdex.jar:apex/com.android.conscrypt/javalib/conscrypt.jar\
+  $(HOST_OUT_JAVA_LIBRARIES)/core-icu4j-hostdex.jar:apex/com.android.i18n/javalib/core-icu4j.jar \
+  $(icu_data_file):com.android.i18n/etc/icu/$(notdir $(icu_data_file))
+
+# Create phony module that will copy all the data files into testcases directory.
+# For now, this copies everything to "out/host/linux-x86/" subdirectory, since it
+# is hard-coded in many places. TODO: Refactor tests to remove the need for this.
+include $(CLEAR_VARS)
+LOCAL_IS_HOST_MODULE := true
+LOCAL_MODULE := art_common
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_CLASS := NATIVE_TESTS
+LOCAL_MODULE_SUFFIX := .txt
+LOCAL_COMPATIBILITY_SUITE := art-host-tests
+LOCAL_COMPATIBILITY_SUPPORT_FILES := $(ART_TESTCASES_PREBUILT_CONTENT) \
+	$(foreach f,$(my_files),$(call word-colon,1,$f):out/host/linux-x86/$(call word-colon,2,$f))
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE):
+	@mkdir -p $(dir $@)
+	echo "This directory contains common data and tools needed for ART host tests" > $@
+
+my_files :=
+include $(CLEAR_VARS)
+###################################################################################################
+
+# Create a phony module that contains data needed for ART chroot-based testing.
+include $(CLEAR_VARS)
+LOCAL_MODULE := art_chroot
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_CLASS := NATIVE_TESTS
+LOCAL_MODULE_SUFFIX := .txt
+LOCAL_COMPATIBILITY_SUITE := general-tests
+LOCAL_COMPATIBILITY_SUPPORT_FILES := \
+	$(foreach apex,$(TESTING_ART_APEX) $(RUNTIME_APEX) $(CONSCRYPT_APEX) $(I18N_APEX),\
+		$(PRODUCT_OUT)/system/apex/$(apex).apex:system/apex/$(apex).apex)
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE):
+	@mkdir -p $(dir $@)
+	echo "This directory contains common data and tools needed for ART target tests" > $@
+
+include $(CLEAR_VARS)
+###################################################################################################
+
 # The path for which all the dex files are relative, not actually the current directory.
 LOCAL_PATH := art/test
 
@@ -21,232 +100,11 @@
 include art/build/Android.common_path.mk
 include art/build/Android.common_build.mk
 
-# Subdirectories in art/test which contain dex files used as inputs for gtests.
-GTEST_DEX_DIRECTORIES := \
-  AbstractMethod \
-  AllFields \
-  DefaultMethods \
-  DexToDexDecompiler \
-  ErroneousA \
-  ErroneousB \
-  ErroneousInit \
-  Extension1 \
-  Extension2 \
-  ForClassLoaderA \
-  ForClassLoaderB \
-  ForClassLoaderC \
-  ForClassLoaderD \
-  ExceptionHandle \
-  GetMethodSignature \
-  HiddenApi \
-  HiddenApiSignatures \
-  HiddenApiStubs \
-  ImageLayoutA \
-  ImageLayoutB \
-  IMTA \
-  IMTB \
-  Instrumentation \
-  Interfaces \
-  Lookup \
-  Main \
-  ManyMethods \
-  MethodTypes \
-  MultiDex \
-  MultiDexModifiedSecondary \
-  MyClass \
-  MyClassNatives \
-  Nested \
-  NonStaticLeafMethods \
-  Packages \
-  ProtoCompare \
-  ProtoCompare2 \
-  ProfileTestMultiDex \
-  StaticLeafMethods \
-  Statics \
-  StaticsFromCode \
-  StringLiterals \
-  Transaction \
-  XandY
-
-# Create build rules for each dex file recording the dependency.
-$(foreach dir,$(GTEST_DEX_DIRECTORIES), $(eval $(call build-art-test-dex,art-gtest,$(dir), \
-  $(ART_TARGET_NATIVETEST_OUT),art/build/Android.gtest.mk,ART_TEST_TARGET_GTEST_$(dir)_DEX, \
-  ART_TEST_HOST_GTEST_$(dir)_DEX)))
-
-# Create rules for MainStripped, a copy of Main with the classes.dex stripped
-# for the oat file assistant tests.
-ART_TEST_HOST_GTEST_MainStripped_DEX := $(basename $(ART_TEST_HOST_GTEST_Main_DEX))Stripped$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
-ART_TEST_TARGET_GTEST_MainStripped_DEX := $(basename $(ART_TEST_TARGET_GTEST_Main_DEX))Stripped$(suffix $(ART_TEST_TARGET_GTEST_Main_DEX))
-
-# Create rules for MainUncompressedAligned, a copy of Main with the classes.dex uncompressed
-# for the dex2oat tests.
-ART_TEST_HOST_GTEST_MainUncompressedAligned_DEX := $(basename $(ART_TEST_HOST_GTEST_Main_DEX))UncompressedAligned$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
-ART_TEST_TARGET_GTEST_MainUncompressedAligned_DEX := $(basename $(ART_TEST_TARGET_GTEST_Main_DEX))UncompressedAligned$(suffix $(ART_TEST_TARGET_GTEST_Main_DEX))
-
-# Create rules for UncompressedEmpty, a classes.dex that is empty and uncompressed
-# for the dex2oat tests.
-ART_TEST_HOST_GTEST_EmptyUncompressed_DEX := $(basename $(ART_TEST_HOST_GTEST_Main_DEX))EmptyUncompressed$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
-ART_TEST_TARGET_GTEST_EmptyUncompressed_DEX := $(basename $(ART_TEST_TARGET_GTEST_Main_DEX))EmptyUncompressed$(suffix $(ART_TEST_TARGET_GTEST_Main_DEX))
-
-# Create rules for UncompressedEmptyAligned, a classes.dex that is empty, uncompressed,
-# and 4 byte aligned for the dex2oat tests.
-ART_TEST_HOST_GTEST_EmptyUncompressedAligned_DEX := $(basename $(ART_TEST_HOST_GTEST_Main_DEX))EmptyUncompressedAligned$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
-ART_TEST_TARGET_GTEST_EmptyUncompressedAligned_DEX := $(basename $(ART_TEST_TARGET_GTEST_Main_DEX))EmptyUncompressedAligned$(suffix $(ART_TEST_TARGET_GTEST_Main_DEX))
-
-# Create rules for MultiDexUncompressedAligned, a copy of MultiDex with the classes.dex uncompressed
-# for the OatFile tests.
-ART_TEST_HOST_GTEST_MultiDexUncompressedAligned_DEX := $(basename $(ART_TEST_HOST_GTEST_MultiDex_DEX))UncompressedAligned$(suffix $(ART_TEST_HOST_GTEST_MultiDex_DEX))
-ART_TEST_TARGET_GTEST_MultiDexUncompressedAligned_DEX := $(basename $(ART_TEST_TARGET_GTEST_MultiDex_DEX))UncompressedAligned$(suffix $(ART_TEST_TARGET_GTEST_MultiDex_DEX))
-
-ifdef ART_TEST_HOST_GTEST_Main_DEX
-$(ART_TEST_HOST_GTEST_MainStripped_DEX): $(ART_TEST_HOST_GTEST_Main_DEX)
-	cp $< $@
-	$(call dexpreopt-remove-classes.dex,$@)
-endif
-
-ifdef ART_TEST_TARGET_GTEST_Main_DEX
-$(ART_TEST_TARGET_GTEST_MainStripped_DEX): $(ART_TEST_TARGET_GTEST_Main_DEX)
-	cp $< $@
-	$(call dexpreopt-remove-classes.dex,$@)
-endif
-
-ifdef ART_TEST_HOST_GTEST_Main_DEX
-$(ART_TEST_HOST_GTEST_MainUncompressedAligned_DEX): $(ART_TEST_HOST_GTEST_Main_DEX) $(ZIPALIGN)
-	cp $< $@
-	$(call uncompress-dexs, $@)
-	$(call align-package, $@)
-endif
-
-ifdef ART_TEST_TARGET_GTEST_Main_DEX
-$(ART_TEST_TARGET_GTEST_MainUncompressedAligned_DEX): $(ART_TEST_TARGET_GTEST_Main_DEX) $(ZIPALIGN)
-	cp $< $@
-	$(call uncompress-dexs, $@)
-	$(call align-package, $@)
-endif
-
-ifdef ART_TEST_HOST_GTEST_Main_DEX
-$(ART_TEST_HOST_GTEST_EmptyUncompressed_DEX):
-	touch $@_classes.dex
-	zip -j -qD -X -0 $@ $@_classes.dex
-	rm $@_classes.dex
-endif
-
-ifdef ART_TEST_TARGET_GTEST_Main_DEX
-$(ART_TEST_TARGET_GTEST_EmptyUncompressed_DEX):
-	touch $@_classes.dex
-	zip -j -qD -X -0 $@ $@_classes.dex
-	rm $@_classes.dex
-endif
-
-ifdef ART_TEST_HOST_GTEST_Main_DEX
-$(ART_TEST_HOST_GTEST_EmptyUncompressedAligned_DEX): $(ZIPALIGN)
-	touch $@_classes.dex
-	zip -j -0 $@_temp.zip $@_classes.dex
-	$(ZIPALIGN) -f 4 $@_temp.zip $@
-	rm $@_classes.dex
-	rm $@_temp.zip
-endif
-
-ifdef ART_TEST_TARGET_GTEST_Main_DEX
-$(ART_TEST_TARGET_GTEST_EmptyUncompressedAligned_DEX): $(ZIPALIGN)
-	touch $@_classes.dex
-	zip -j -0 $@_temp.zip $@_classes.dex
-	$(ZIPALIGN) -f 4 $@_temp.zip $@
-	rm $@_classes.dex
-	rm $@_temp.zip
-endif
-
-ifdef ART_TEST_HOST_GTEST_MultiDex_DEX
-$(ART_TEST_HOST_GTEST_MultiDexUncompressedAligned_DEX): $(ART_TEST_HOST_GTEST_MultiDex_DEX) $(ZIPALIGN)
-	cp $< $@
-	$(call uncompress-dexs, $@)
-	$(call align-package, $@)
-endif
-
-ifdef ART_TEST_TARGET_GTEST_MultiDex_DEX
-$(ART_TEST_TARGET_GTEST_MultiDexUncompressedAligned_DEX): $(ART_TEST_TARGET_GTEST_MultiDex_DEX) $(ZIPALIGN)
-	cp $< $@
-	$(call uncompress-dexs, $@)
-	$(call align-package, $@)
-endif
-
-ART_TEST_GTEST_VerifierDeps_SRC := $(abspath $(wildcard $(LOCAL_PATH)/VerifierDeps/*.smali))
-ART_TEST_GTEST_VerifierDepsMulti_SRC := $(abspath $(wildcard $(LOCAL_PATH)/VerifierDepsMulti/*.smali))
-ART_TEST_HOST_GTEST_VerifierDeps_DEX := $(dir $(ART_TEST_HOST_GTEST_Main_DEX))$(subst Main,VerifierDeps,$(basename $(notdir $(ART_TEST_HOST_GTEST_Main_DEX))))$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
-ART_TEST_TARGET_GTEST_VerifierDeps_DEX := $(dir $(ART_TEST_TARGET_GTEST_Main_DEX))$(subst Main,VerifierDeps,$(basename $(notdir $(ART_TEST_TARGET_GTEST_Main_DEX))))$(suffix $(ART_TEST_TARGET_GTEST_Main_DEX))
-ART_TEST_HOST_GTEST_VerifierDepsMulti_DEX := $(dir $(ART_TEST_HOST_GTEST_Main_DEX))$(subst Main,VerifierDepsMulti,$(basename $(notdir $(ART_TEST_HOST_GTEST_Main_DEX))))$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
-ART_TEST_TARGET_GTEST_VerifierDepsMulti_DEX := $(dir $(ART_TEST_TARGET_GTEST_Main_DEX))$(subst Main,VerifierDepsMulti,$(basename $(notdir $(ART_TEST_TARGET_GTEST_Main_DEX))))$(suffix $(ART_TEST_TARGET_GTEST_Main_DEX))
-
-$(ART_TEST_HOST_GTEST_VerifierDeps_DEX): $(ART_TEST_GTEST_VerifierDeps_SRC) $(HOST_OUT_EXECUTABLES)/smali
-	 $(HOST_OUT_EXECUTABLES)/smali assemble --output $@ $(filter %.smali,$^)
-
-$(ART_TEST_TARGET_GTEST_VerifierDeps_DEX): $(ART_TEST_GTEST_VerifierDeps_SRC) $(HOST_OUT_EXECUTABLES)/smali
-	 $(HOST_OUT_EXECUTABLES)/smali assemble --output $@ $(filter %.smali,$^)
-
-$(ART_TEST_HOST_GTEST_VerifierDepsMulti_DEX): $(ART_TEST_GTEST_VerifierDepsMulti_SRC) $(HOST_OUT_EXECUTABLES)/smali
-	 $(HOST_OUT_EXECUTABLES)/smali assemble --output $@ $(filter %.smali,$^)
-
-$(ART_TEST_TARGET_GTEST_VerifierDepsMulti_DEX): $(ART_TEST_GTEST_VerifierDepsMulti_SRC) $(HOST_OUT_EXECUTABLES)/smali
-	 $(HOST_OUT_EXECUTABLES)/smali assemble --output $@ $(filter %.smali,$^)
-
-ART_TEST_GTEST_VerifySoftFailDuringClinit_SRC := $(abspath $(wildcard $(LOCAL_PATH)/VerifySoftFailDuringClinit/*.smali))
-ART_TEST_HOST_GTEST_VerifySoftFailDuringClinit_DEX := $(dir $(ART_TEST_HOST_GTEST_Main_DEX))$(subst Main,VerifySoftFailDuringClinit,$(basename $(notdir $(ART_TEST_HOST_GTEST_Main_DEX))))$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
-ART_TEST_TARGET_GTEST_VerifySoftFailDuringClinit_DEX := $(dir $(ART_TEST_TARGET_GTEST_Main_DEX))$(subst Main,VerifySoftFailDuringClinit,$(basename $(notdir $(ART_TEST_TARGET_GTEST_Main_DEX))))$(suffix $(ART_TEST_TARGET_GTEST_Main_DEX))
-
-$(ART_TEST_HOST_GTEST_VerifySoftFailDuringClinit_DEX): $(ART_TEST_GTEST_VerifySoftFailDuringClinit_SRC) $(HOST_OUT_EXECUTABLES)/smali
-	 $(HOST_OUT_EXECUTABLES)/smali assemble --output $@ $(filter %.smali,$^)
-
-$(ART_TEST_TARGET_GTEST_VerifySoftFailDuringClinit_DEX): $(ART_TEST_GTEST_VerifySoftFailDuringClinit_SRC) $(HOST_OUT_EXECUTABLES)/smali
-	 $(HOST_OUT_EXECUTABLES)/smali assemble --output $@ $(filter %.smali,$^)
-
-# Dex file dependencies for each gtest.
-ART_GTEST_art_dex_file_loader_test_DEX_DEPS := GetMethodSignature Main Nested MultiDex
-ART_GTEST_dex2oat_environment_tests_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary MyClassNatives Nested VerifierDeps VerifierDepsMulti
-
-ART_GTEST_atomic_dex_ref_map_test_DEX_DEPS := Interfaces
-ART_GTEST_class_linker_test_DEX_DEPS := AllFields ErroneousA ErroneousB ErroneousInit ForClassLoaderA ForClassLoaderB ForClassLoaderC ForClassLoaderD Interfaces MethodTypes MultiDex MyClass Nested Statics StaticsFromCode
-ART_GTEST_class_loader_context_test_DEX_DEPS := Main MultiDex MyClass ForClassLoaderA ForClassLoaderB ForClassLoaderC ForClassLoaderD
-ART_GTEST_class_table_test_DEX_DEPS := XandY
-ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod StaticLeafMethods ProfileTestMultiDex
-ART_GTEST_dex_cache_test_DEX_DEPS := Main Packages MethodTypes
-ART_GTEST_dexanalyze_test_DEX_DEPS := MultiDex
-ART_GTEST_dexlayout_test_DEX_DEPS := ManyMethods
-ART_GTEST_dex2oat_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) ManyMethods Statics VerifierDeps MainUncompressedAligned EmptyUncompressed EmptyUncompressedAligned StringLiterals
-ART_GTEST_dex2oat_image_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) Statics VerifierDeps
-ART_GTEST_exception_test_DEX_DEPS := ExceptionHandle
-ART_GTEST_hiddenapi_test_DEX_DEPS := HiddenApi HiddenApiStubs
-ART_GTEST_hidden_api_test_DEX_DEPS := HiddenApiSignatures Main MultiDex
-ART_GTEST_image_test_DEX_DEPS := ImageLayoutA ImageLayoutB DefaultMethods VerifySoftFailDuringClinit
-ART_GTEST_imtable_test_DEX_DEPS := IMTA IMTB
-ART_GTEST_instrumentation_test_DEX_DEPS := Instrumentation
-ART_GTEST_jni_compiler_test_DEX_DEPS := MyClassNatives
-ART_GTEST_jni_internal_test_DEX_DEPS := AllFields StaticLeafMethods MyClassNatives
-ART_GTEST_oat_file_assistant_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS)
-ART_GTEST_dexoptanalyzer_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS)
-ART_GTEST_image_space_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) Extension1 Extension2
-ART_GTEST_oat_file_test_DEX_DEPS := Main MultiDex MainUncompressedAligned MultiDexUncompressedAligned MainStripped Nested MultiDexModifiedSecondary
-ART_GTEST_oat_test_DEX_DEPS := Main
-ART_GTEST_oat_writer_test_DEX_DEPS := Main
-# two_runtimes_test build off dex2oat_environment_test, which does sanity checks on the following dex files.
-ART_GTEST_two_runtimes_test_DEX_DEPS := Main MainStripped Nested MultiDex MultiDexModifiedSecondary
-ART_GTEST_object_test_DEX_DEPS := ProtoCompare ProtoCompare2 StaticsFromCode XandY
-ART_GTEST_proxy_test_DEX_DEPS := Interfaces
-ART_GTEST_reflection_test_DEX_DEPS := Main NonStaticLeafMethods StaticLeafMethods
-ART_GTEST_profile_assistant_test_DEX_DEPS := ProfileTestMultiDex
-ART_GTEST_profile_compilation_info_test_DEX_DEPS := ManyMethods ProfileTestMultiDex
-ART_GTEST_profile_boot_info_test_DEX_DEPS := ManyMethods ProfileTestMultiDex MultiDex
-ART_GTEST_profiling_info_test_DEX_DEPS := ProfileTestMultiDex
-ART_GTEST_runtime_callbacks_test_DEX_DEPS := XandY
-ART_GTEST_stub_test_DEX_DEPS := AllFields
-ART_GTEST_transaction_test_DEX_DEPS := Transaction
-ART_GTEST_type_lookup_table_test_DEX_DEPS := Lookup
-ART_GTEST_unstarted_runtime_test_DEX_DEPS := Nested
-ART_GTEST_heap_verification_test_DEX_DEPS := ProtoCompare ProtoCompare2 StaticsFromCode XandY
-ART_GTEST_verifier_deps_test_DEX_DEPS := VerifierDeps VerifierDepsMulti MultiDex
-ART_GTEST_dex_to_dex_decompiler_test_DEX_DEPS := VerifierDeps DexToDexDecompiler
-ART_GTEST_oatdump_app_test_DEX_DEPS := ProfileTestMultiDex
-ART_GTEST_oatdump_test_DEX_DEPS := ProfileTestMultiDex
-ART_GTEST_reg_type_test_DEX_DEPS := Interfaces
+# Deprecated core.art dependencies.
+HOST_CORE_IMAGE_DEFAULT_32 :=
+HOST_CORE_IMAGE_DEFAULT_64 :=
+TARGET_CORE_IMAGE_DEFAULT_32 :=
+TARGET_CORE_IMAGE_DEFAULT_64 :=
 
 # The elf writer test has dependencies on core.oat.
 ART_GTEST_elf_writer_test_HOST_DEPS := $(HOST_CORE_IMAGE_DEFAULT_64) $(HOST_CORE_IMAGE_DEFAULT_32)
@@ -260,156 +118,6 @@
 ART_GTEST_transaction_test_HOST_DEPS := $(HOST_CORE_IMAGE_DEFAULT_64) $(HOST_CORE_IMAGE_DEFAULT_32)
 ART_GTEST_transaction_test_TARGET_DEPS := $(TARGET_CORE_IMAGE_DEFAULT_64) $(TARGET_CORE_IMAGE_DEFAULT_32)
 
-ART_GTEST_dex2oat_environment_tests_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_optimizing_64) \
-  $(HOST_CORE_IMAGE_optimizing_32) \
-  $(HOST_CORE_IMAGE_interpreter_64) \
-  $(HOST_CORE_IMAGE_interpreter_32)
-ART_GTEST_dex2oat_environment_tests_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_optimizing_64) \
-  $(TARGET_CORE_IMAGE_optimizing_32) \
-  $(TARGET_CORE_IMAGE_interpreter_64) \
-  $(TARGET_CORE_IMAGE_interpreter_32)
-
-ART_GTEST_oat_file_test_HOST_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS) \
-  $(HOST_OUT_EXECUTABLES)/dex2oatd
-ART_GTEST_oat_file_test_TARGET_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS) \
-  dex2oatd.com.android.art.debug
-
-ART_GTEST_oat_file_assistant_test_HOST_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS)
-ART_GTEST_oat_file_assistant_test_TARGET_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS)
-
-ART_GTEST_dexoptanalyzer_test_HOST_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS) \
-  $(HOST_OUT_EXECUTABLES)/dexoptanalyzerd
-ART_GTEST_dexoptanalyzer_test_TARGET_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS) \
-  $(TESTING_ART_APEX)  # For dexoptanalyzerd.
-
-ART_GTEST_image_space_test_HOST_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS)
-ART_GTEST_image_space_test_TARGET_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS)
-
-ART_GTEST_dex2oat_test_HOST_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS) \
-  $(HOST_OUT_EXECUTABLES)/dex2oatd
-ART_GTEST_dex2oat_test_TARGET_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS) \
-  $(TESTING_ART_APEX)  # For dex2oatd.
-
-ART_GTEST_dex2oat_image_test_HOST_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS) \
-  $(HOST_OUT_EXECUTABLES)/dex2oatd
-ART_GTEST_dex2oat_image_test_TARGET_DEPS := \
-  $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS) \
-  $(TESTING_ART_APEX)  # For dex2oatd.
-
-ART_GTEST_module_exclusion_test_HOST_DEPS := \
-  $(ART_GTEST_dex2oat_image_test_HOST_DEPS)
-ART_GTEST_module_exclusion_test_TARGET_DEPS := \
-  $(ART_GTEST_dex2oat_image_test_TARGET_DEPS)
-
-# TODO: document why this is needed.
-ART_GTEST_proxy_test_HOST_DEPS := $(HOST_CORE_IMAGE_DEFAULT_64) $(HOST_CORE_IMAGE_DEFAULT_32)
-
-# The dexdiag test requires the dexdiag utility.
-ART_GTEST_dexdiag_test_HOST_DEPS := $(HOST_OUT_EXECUTABLES)/dexdiag
-ART_GTEST_dexdiag_test_TARGET_DEPS := $(TESTING_ART_APEX)  # For dexdiag.
-
-# The dexdump test requires an image and the dexdump utility.
-# TODO: rename into dexdump when migration completes
-ART_GTEST_dexdump_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_DEFAULT_64) \
-  $(HOST_CORE_IMAGE_DEFAULT_32) \
-  $(HOST_OUT_EXECUTABLES)/dexdump
-ART_GTEST_dexdump_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_DEFAULT_64) \
-  $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  dexdump.com.android.art.debug
-
-# The dexanalyze test requires an image and the dexanalyze utility.
-ART_GTEST_dexanalyze_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_DEFAULT_64) \
-  $(HOST_CORE_IMAGE_DEFAULT_32) \
-  $(HOST_OUT_EXECUTABLES)/dexanalyze
-ART_GTEST_dexanalyze_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_DEFAULT_64) \
-  $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  dexanalyze.com.android.art.debug
-
-# The dexlayout test requires an image and the dexlayout utility.
-# TODO: rename into dexdump when migration completes
-ART_GTEST_dexlayout_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_DEFAULT_64) \
-  $(HOST_CORE_IMAGE_DEFAULT_32) \
-  $(HOST_OUT_EXECUTABLES)/dexlayoutd \
-  $(HOST_OUT_EXECUTABLES)/dexdump
-ART_GTEST_dexlayout_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_DEFAULT_64) \
-  $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  dexlayoutd.com.android.art.debug \
-  dexdump.com.android.art.debug
-
-# The dexlist test requires an image and the dexlist utility.
-ART_GTEST_dexlist_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_DEFAULT_64) \
-  $(HOST_CORE_IMAGE_DEFAULT_32) \
-  $(HOST_OUT_EXECUTABLES)/dexlist
-ART_GTEST_dexlist_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_DEFAULT_64) \
-  $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  $(TESTING_ART_APEX)   # For dexlist.
-
-# The imgdiag test has dependencies on core.oat since it needs to load it during the test.
-# For the host, also add the installed tool (in the base size, that should suffice). For the
-# target, just the module is fine, the sync will happen late enough.
-ART_GTEST_imgdiag_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_DEFAULT_64) \
-  $(HOST_CORE_IMAGE_DEFAULT_32) \
-  $(HOST_OUT_EXECUTABLES)/imgdiagd
-ART_GTEST_imgdiag_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_DEFAULT_64) \
-  $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  imgdiagd.com.android.art.debug
-
-# Dex analyze test requires dexanalyze.
-ART_GTEST_dexanalyze_test_HOST_DEPS := \
-  $(HOST_OUT_EXECUTABLES)/dexanalyze
-ART_GTEST_dexanalyze_test_TARGET_DEPS := \
-  dexanalyze.com.android.art.debug
-
-# Oatdump test requires an image and oatfile to dump.
-ART_GTEST_oatdump_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_DEFAULT_64) \
-  $(HOST_CORE_IMAGE_DEFAULT_32) \
-  $(HOST_OUT_EXECUTABLES)/oatdumpd \
-  $(HOST_OUT_EXECUTABLES)/oatdumpds \
-  $(HOST_OUT_EXECUTABLES)/dexdump \
-  $(HOST_OUT_EXECUTABLES)/dex2oatd \
-  $(HOST_OUT_EXECUTABLES)/dex2oatds
-ART_GTEST_oatdump_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_DEFAULT_64) \
-  $(TARGET_CORE_IMAGE_DEFAULT_32) \
-  $(TESTING_ART_APEX)    # For oatdumpd, dexdump, dex2oatd.
-ART_GTEST_oatdump_image_test_HOST_DEPS := $(ART_GTEST_oatdump_test_HOST_DEPS)
-ART_GTEST_oatdump_image_test_TARGET_DEPS := $(ART_GTEST_oatdump_test_TARGET_DEPS)
-ART_GTEST_oatdump_app_test_HOST_DEPS := $(ART_GTEST_oatdump_test_HOST_DEPS)
-ART_GTEST_oatdump_app_test_TARGET_DEPS := $(ART_GTEST_oatdump_test_TARGET_DEPS)
-
-# Profile assistant tests requires profman utility.
-ART_GTEST_profile_assistant_test_HOST_DEPS := $(HOST_OUT_EXECUTABLES)/profmand
-ART_GTEST_profile_assistant_test_TARGET_DEPS := $(TESTING_ART_APEX)  # For profmand.
-
-ART_GTEST_hiddenapi_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_DEFAULT_64) \
-  $(HOST_CORE_IMAGE_DEFAULT_32) \
-  $(HOST_OUT_EXECUTABLES)/hiddenapid
-
 # The path for which all the source files are relative, not actually the current directory.
 LOCAL_PATH := art
 
@@ -434,6 +142,7 @@
     art_libdexfile_tests \
     art_libprofile_tests \
     art_oatdump_tests \
+    art_odrefresh_tests \
     art_profman_tests \
     art_runtime_compiler_tests \
     art_runtime_tests \
@@ -457,9 +166,15 @@
 ART_TEST_HOST_GTEST$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
 ART_TEST_HOST_GTEST$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
 ART_TEST_HOST_GTEST_RULES :=
+ART_TEST_HOST_GTEST$(ART_PHONY_TEST_HOST_SUFFIX)_BUILD_RULES :=
+ART_TEST_HOST_GTEST$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_BUILD_RULES :=
+ART_TEST_HOST_GTEST_BUILD_RULES :=
 ART_TEST_TARGET_GTEST$(ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
 ART_TEST_TARGET_GTEST$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
 ART_TEST_TARGET_GTEST_RULES :=
+ART_TEST_TARGET_GTEST$(ART_PHONY_TEST_TARGET_SUFFIX)_BUILD_RULES :=
+ART_TEST_TARGET_GTEST$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)_BUILD_RULES :=
+ART_TEST_TARGET_GTEST_BUILD_RULES :=
 ART_TEST_HOST_GTEST_DEPENDENCIES :=
 ART_TEST_TARGET_GTEST_DEPENDENCIES :=
 
@@ -490,11 +205,15 @@
 define define-art-gtest-rule-host
   gtest_suffix := $(1)$$($(3)ART_PHONY_TEST_HOST_SUFFIX)
   gtest_rule := test-art-host-gtest-$$(gtest_suffix)
+  gtest_build_rule := test-art-host-gtest-dependencies-$$(gtest_suffix)
   gtest_output := $(call intermediates-dir-for,PACKAGING,art-host-gtest,HOST)/$$(gtest_suffix).xml
   $$(call dist-for-goals,$$(gtest_rule),$$(gtest_output):gtest/$$(gtest_suffix))
   gtest_exe := $(2)
   # Dependencies for all host gtests.
-  gtest_deps := $$(HOST_CORE_DEX_LOCATIONS) \
+  gtest_deps := $$(ART_HOST_DEX_DEPENDENCIES) \
+    $$(ART_TEST_HOST_GTEST_DEPENDENCIES) \
+    $$(HOST_OUT)/$$(I18N_APEX)/timestamp \
+    $$(HOST_BOOT_IMAGE_JARS) \
     $$($(3)ART_HOST_OUT_SHARED_LIBRARIES)/libicu_jni$$(ART_HOST_SHLIB_EXTENSION) \
     $$($(3)ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$$(ART_HOST_SHLIB_EXTENSION) \
     $$($(3)ART_HOST_OUT_SHARED_LIBRARIES)/libopenjdkd$$(ART_HOST_SHLIB_EXTENSION) \
@@ -503,7 +222,31 @@
     $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX)) \
     $(HOST_OUT_EXECUTABLES)/signal_dumper
 
-  ART_TEST_HOST_GTEST_DEPENDENCIES += $$(gtest_deps)
+  # Note: The "host arch" Make variables defined in build/make/core/envsetup.mk
+  # and art/build/Android.common.mk have different meanings:
+  #
+  #   * In build/make/core/envsetup.mk:
+  #     * HOST_ARCH := x86_64
+  #     * HOST_2ND_ARCH := x86
+  #
+  #   * In art/build/Android.common.mk:
+  #     * When `HOST_PREFER_32_BIT` is `true`:
+  #       * ART_HOST_ARCH := x86
+  #       * 2ND_ART_HOST_ARCH :=
+  #       * 2ND_HOST_ARCH :=
+  #     * Otherwise:
+  #       * ART_HOST_ARCH := x86_64
+  #       * 2ND_ART_HOST_ARCH := x86
+  #       * 2ND_HOST_ARCH := x86
+  ifeq ($(HOST_PREFER_32_BIT),true)
+    gtest_deps += $$(2ND_HOST_BOOT_IMAGE) # Depend on the 32-bit boot image.
+  else
+    gtest_deps += $$($(3)HOST_BOOT_IMAGE)
+  endif
+
+.PHONY: $$(gtest_build_rule)
+$$(gtest_build_rule) : $$(gtest_exe) $$(gtest_deps)
+
 
 .PHONY: $$(gtest_rule)
 $$(gtest_rule): $$(gtest_output)
@@ -511,6 +254,8 @@
 # Re-run the tests, even if nothing changed. Until the build system has a dedicated "no cache"
 # option, claim to write a file that is never produced.
 $$(gtest_output): .KATI_IMPLICIT_OUTPUTS := $$(gtest_output)-nocache
+# Limit concurrent runs. Each test itself is already highly parallel (and thus memory hungry).
+$$(gtest_output): .KATI_NINJA_POOL := highmem_pool
 $$(gtest_output): NAME := $$(gtest_rule)
 ifeq (,$(SANITIZE_HOST))
 $$(gtest_output): $$(gtest_exe) $$(gtest_deps)
@@ -538,6 +283,8 @@
 endif
 
   ART_TEST_HOST_GTEST$$($(3)ART_PHONY_TEST_HOST_SUFFIX)_RULES += $$(gtest_rule)
+  ART_TEST_HOST_GTEST_BUILD_RULES += $$(gtest_build_rule)
+  ART_TEST_HOST_GTEST$$($(3)ART_PHONY_TEST_HOST_SUFFIX)_BUILD_RULES += $$(gtest_build_rule)
   ART_TEST_HOST_GTEST_RULES += $$(gtest_rule)
   ART_TEST_HOST_GTEST_$(1)_RULES += $$(gtest_rule)
 
@@ -550,6 +297,9 @@
   gtest_suffix :=
 endef  # define-art-gtest-rule-host
 
+ART_TEST_HOST_GTEST_DEPENDENCIES := $(HOST_I18N_DATA)
+ART_TEST_TARGET_GTEST_DEPENDENCIES := $(TESTING_ART_APEX)
+
 # Add the additional dependencies for the specified test
 # $(1): test name
 define add-art-gtest-dependencies
@@ -599,10 +349,11 @@
 ifeq ($(ART_BUILD_TARGET),true)
   $(foreach name,$(ART_TARGET_GTEST_NAMES), $(eval $(call add-art-gtest-dependencies,$(name),)))
   ART_TEST_TARGET_GTEST_DEPENDENCIES += \
-    libicu_jni.com.android.art.debug \
-    libjavacore.com.android.art.debug \
-    libopenjdkd.com.android.art.debug \
-    $(foreach jar,$(TARGET_TEST_CORE_JARS),$(TARGET_OUT_JAVA_LIBRARIES)/$(jar).jar)
+    com.android.i18n \
+    libjavacore.com.android.art.testing \
+    libopenjdkd.com.android.art.testing \
+    com.android.art.testing \
+    com.android.conscrypt
 endif
 ifeq ($(ART_BUILD_HOST),true)
   $(foreach file,$(ART_HOST_GTEST_FILES), $(eval $(call define-art-gtest-host,$(file),)))
@@ -613,21 +364,6 @@
   $(foreach file,$(ART_HOST_GTEST_FILES), $(eval $(call define-art-gtest-host-both,$$(notdir $$(basename $$(file))))))
 endif
 
-# Used outside the art project to get a list of the current tests
-RUNTIME_TARGET_GTEST_MAKE_TARGETS :=
-art_target_gtest_files := $(foreach m,$(ART_TEST_MODULES),$(ART_TEST_LIST_device_$(TARGET_ARCH)_$(m)))
-# If testdir == testfile, assume this is not a test_per_src module
-$(foreach file,$(art_target_gtest_files),\
-  $(eval testdir := $$(notdir $$(patsubst %/,%,$$(dir $$(file)))))\
-  $(eval testfile := $$(notdir $$(basename $$(file))))\
-  $(if $(call streq,$(testdir),$(testfile)),,\
-    $(eval testfile := $(testdir)_$(testfile)))\
-  $(eval RUNTIME_TARGET_GTEST_MAKE_TARGETS += $(testfile))\
-)
-testdir :=
-testfile :=
-art_target_gtest_files :=
-
 # Define all the combinations of host/target and suffix such as:
 # test-art-host-gtest or test-art-host-gtest64
 # $(1): host or target
@@ -670,6 +406,48 @@
 $(eval $(call define-test-art-gtest-combination,host,HOST,$(2ND_ART_PHONY_TEST_HOST_SUFFIX)))
 endif
 
+# Define all the combinations of host/target and suffix such as:
+# test-art-host-gtest-dependencies or test-art-host-gtest-dependencies64
+# $(1): host or target
+# $(2): HOST or TARGET
+# $(3): undefined, 32 or 64
+define define-test-art-gtest-dependency-combination
+  ifeq ($(1),host)
+    ifneq ($(2),HOST)
+      $$(error argument mismatch $(1) and ($2))
+    endif
+  else
+    ifneq ($(1),target)
+      $$(error found $(1) expected host or target)
+    endif
+    ifneq ($(2),TARGET)
+      $$(error argument mismatch $(1) and ($2))
+    endif
+  endif
+
+  rule_name := test-art-$(1)-gtest-dependencies$(3)
+  dependencies := $$(ART_TEST_$(2)_GTEST$(3)_BUILD_RULES)
+
+.PHONY: $$(rule_name)
+$$(rule_name): $$(dependencies) d8
+
+  # Clear locally defined variables.
+  rule_name :=
+  dependencies :=
+endef  # define-test-art-gtest-dependency-combination
+
+# TODO Get target-deps working too
+# $(eval $(call define-test-art-gtest-dependency-combination,target,TARGET,))
+# $(eval $(call define-test-art-gtest-dependency-combination,target,TARGET,$(ART_PHONY_TEST_TARGET_SUFFIX)))
+# ifdef 2ND_ART_PHONY_TEST_TARGET_SUFFIX
+# $(eval $(call define-test-art-gtest-dependency-combination,target,TARGET,$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)))
+# endif
+$(eval $(call define-test-art-gtest-dependency-combination,host,HOST,))
+$(eval $(call define-test-art-gtest-dependency-combination,host,HOST,$(ART_PHONY_TEST_HOST_SUFFIX)))
+ifneq ($(HOST_PREFER_32_BIT),true)
+$(eval $(call define-test-art-gtest-dependency-combination,host,HOST,$(2ND_ART_PHONY_TEST_HOST_SUFFIX)))
+endif
+
 # Clear locally defined variables.
 define-art-gtest-rule-target :=
 define-art-gtest-rule-host :=
@@ -684,9 +462,15 @@
 ART_TEST_HOST_GTEST$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
 ART_TEST_HOST_GTEST$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
 ART_TEST_HOST_GTEST_RULES :=
+ART_TEST_HOST_GTEST$(ART_PHONY_TEST_HOST_SUFFIX)_BUILD_RULES :=
+ART_TEST_HOST_GTEST$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_BUILD_RULES :=
+ART_TEST_HOST_GTEST_BUILD_RULES :=
 ART_TEST_TARGET_GTEST$(ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
 ART_TEST_TARGET_GTEST$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
 ART_TEST_TARGET_GTEST_RULES :=
+ART_TEST_TARGET_GTEST$(ART_PHONY_TEST_TARGET_SUFFIX)_BUILD_RULES :=
+ART_TEST_TARGET_GTEST$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)_BUILD_RULES :=
+ART_TEST_TARGET_GTEST_BUILD_RULES :=
 ART_GTEST_TARGET_ANDROID_ROOT :=
 ART_GTEST_TARGET_ANDROID_I18N_ROOT :=
 ART_GTEST_TARGET_ANDROID_ART_ROOT :=
@@ -743,3 +527,5 @@
 ART_TEST_TARGET_GTEST_VerifySoftFailDuringClinit_DEX :=
 GTEST_DEX_DIRECTORIES :=
 LOCAL_PATH :=
+
+endif # ifneq ($(HOST_OS),darwin)
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
deleted file mode 100644
index c6fe400..0000000
--- a/build/Android.oat.mk
+++ /dev/null
@@ -1,271 +0,0 @@
-#
-# 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.
-#
-
-########################################################################
-# Rules to build a smaller "core" image to support core libraries
-# (that is, non-Android frameworks) testing on the host and target
-#
-# The main rules to build the default "boot" image are in
-# build/core/dex_preopt_libart.mk
-
-include art/build/Android.common_build.mk
-
-LOCAL_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES_OPTION :=
-ifeq ($(DEX2OAT_HOST_INSTRUCTION_SET_FEATURES),)
-  LOCAL_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES_OPTION := --instruction-set-features=default
-else
-  LOCAL_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES_OPTION := --instruction-set-features=$(DEX2OAT_HOST_INSTRUCTION_SET_FEATURES)
-endif
-LOCAL_$(HOST_2ND_ARCH_VAR_PREFIX)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES_OPTION :=
-ifeq ($($(HOST_2ND_ARCH_VAR_PREFIX)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES),)
-  LOCAL_$(HOST_2ND_ARCH_VAR_PREFIX)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES_OPTION := --instruction-set-features=default
-else
-  LOCAL_$(HOST_2ND_ARCH_VAR_PREFIX)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES_OPTION := --instruction-set-features=$($(HOST_2ND_ARCH_VAR_PREFIX)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES)
-endif
-
-# Use dex2oat debug version for better error reporting
-# $(1): compiler - optimizing, interpreter or interp-ac (interpreter-access-checks).
-# $(2): 2ND_ or undefined, 2ND_ for 32-bit host builds.
-define create-core-oat-host-rules
-  core_compile_options :=
-  core_image_name :=
-  core_oat_name :=
-  core_infix :=
-  core_dex2oat_dependency := $(DEX2OAT)
-
-  ifeq ($(1),optimizing)
-    core_compile_options += --compiler-backend=Optimizing
-  endif
-  ifeq ($(1),interpreter)
-    core_compile_options += --compiler-filter=quicken
-    core_infix := -interpreter
-  endif
-  ifeq ($(1),interp-ac)
-    core_compile_options += --compiler-filter=extract --runtime-arg -Xverify:softfail
-    core_infix := -interp-ac
-  endif
-  ifneq ($(filter-out interpreter interp-ac optimizing,$(1)),)
-    #Technically this test is not precise, but hopefully good enough.
-    $$(error found $(1) expected interpreter, interp-ac, or optimizing)
-  endif
-
-  core_image_location := $(HOST_OUT_JAVA_LIBRARIES)/core$$(core_infix)$(CORE_IMG_SUFFIX)
-  core_image_name := $($(2)HOST_CORE_IMG_OUT_BASE)$$(core_infix)$(CORE_IMG_SUFFIX)
-  core_oat_name := $($(2)HOST_CORE_OAT_OUT_BASE)$$(core_infix)$(CORE_OAT_SUFFIX)
-
-  # Using the bitness suffix makes it easier to add as a dependency for the run-test mk.
-  ifeq ($(2),)
-    HOST_CORE_IMAGE_$(1)_64 := $$(core_image_name)
-  else
-    HOST_CORE_IMAGE_$(1)_32 := $$(core_image_name)
-  endif
-  HOST_CORE_IMG_OUTS += $$(core_image_name)
-  HOST_CORE_OAT_OUTS += $$(core_oat_name)
-
-$$(core_image_name): PRIVATE_CORE_COMPILE_OPTIONS := $$(core_compile_options)
-$$(core_image_name): PRIVATE_CORE_IMAGE_LOCATION := $$(core_image_location)
-$$(core_image_name): PRIVATE_CORE_IMG_NAME := $$(core_image_name)
-$$(core_image_name): PRIVATE_CORE_OAT_NAME := $$(core_oat_name)
-# In addition to the primary core image containing HOST_CORE_IMG_DEX_FILES,
-# also build a boot image extension for the remaining HOST_CORE_DEX_FILES.
-$$(core_image_name): $$(HOST_CORE_DEX_LOCATIONS) $$(core_dex2oat_dependency)
-	@echo "host dex2oat: $$@"
-	@mkdir -p $$(dir $$@)
-	$$(hide) ANDROID_LOG_TAGS="*:e" $$(DEX2OAT) \
-	  --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
-	  --runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
-	  $$(addprefix --dex-file=,$$(HOST_CORE_IMG_DEX_FILES)) \
-	  $$(addprefix --dex-location=,$$(HOST_CORE_IMG_DEX_LOCATIONS)) \
-	  --oat-file=$$(PRIVATE_CORE_OAT_NAME) \
-	  --oat-location=$$(PRIVATE_CORE_OAT_NAME) \
-          --image=$$(PRIVATE_CORE_IMG_NAME) \
-	  --base=$$(LIBART_IMG_HOST_BASE_ADDRESS) \
-	  --instruction-set=$$($(2)ART_HOST_ARCH) \
-	  $$(LOCAL_$(2)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES_OPTION) \
-	  --host --android-root=$$(HOST_OUT) \
-	  --generate-debug-info --generate-build-id \
-	  --runtime-arg -XX:SlowDebug=true \
-	  --no-inline-from=core-oj-hostdex.jar \
-	  $$(PRIVATE_CORE_COMPILE_OPTIONS) && \
-	ANDROID_LOG_TAGS="*:e" $$(DEX2OAT) \
-	  --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
-	  --runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
-	  --runtime-arg -Xbootclasspath:$$(subst $$(space),:,$$(strip \
-	        $$(HOST_CORE_DEX_FILES))) \
-	  --runtime-arg -Xbootclasspath-locations:$$(subst $$(space),:,$$(strip \
-	        $$(HOST_CORE_DEX_LOCATIONS))) \
-	  $$(addprefix --dex-file=, \
-	      $$(filter-out $$(HOST_CORE_IMG_DEX_FILES),$$(HOST_CORE_DEX_FILES))) \
-	  $$(addprefix --dex-location=, \
-	      $$(filter-out $$(HOST_CORE_IMG_DEX_LOCATIONS),$$(HOST_CORE_DEX_LOCATIONS))) \
-	  --oat-file=$$(PRIVATE_CORE_OAT_NAME) \
-	  --oat-location=$$(PRIVATE_CORE_OAT_NAME) \
-	  --boot-image=$$(PRIVATE_CORE_IMAGE_LOCATION) \
-	  --image=$$(PRIVATE_CORE_IMG_NAME) \
-	  --instruction-set=$$($(2)ART_HOST_ARCH) \
-	  $$(LOCAL_$(2)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES_OPTION) \
-	  --host --android-root=$$(HOST_OUT) \
-	  --generate-debug-info --generate-build-id \
-	  --runtime-arg -XX:SlowDebug=true \
-	  --no-inline-from=core-oj-hostdex.jar \
-	  $$(PRIVATE_CORE_COMPILE_OPTIONS)
-
-$$(core_oat_name): $$(core_image_name)
-
-  # Clean up locally used variables.
-  core_dex2oat_dependency :=
-  core_compile_options :=
-  core_image_name :=
-  core_oat_name :=
-  core_infix :=
-endef  # create-core-oat-host-rules
-
-# $(1): compiler - optimizing, interpreter or interp-ac (interpreter-access-checks).
-define create-core-oat-host-rule-combination
-  $(call create-core-oat-host-rules,$(1),)
-
-  ifneq ($(HOST_PREFER_32_BIT),true)
-    $(call create-core-oat-host-rules,$(1),2ND_)
-  endif
-endef
-
-$(eval $(call create-core-oat-host-rule-combination,optimizing))
-$(eval $(call create-core-oat-host-rule-combination,interpreter))
-$(eval $(call create-core-oat-host-rule-combination,interp-ac))
-
-.PHONY: test-art-host-dex2oat-host
-test-art-host-dex2oat-host: $(HOST_CORE_IMG_OUTS)
-
-# $(1): compiler - optimizing, interpreter or interp-ac (interpreter-access-checks).
-# $(2): 2ND_ or undefined
-define create-core-oat-target-rules
-  core_compile_options :=
-  core_image_name :=
-  core_oat_name :=
-  core_infix :=
-  core_dex2oat_dependency := $(DEX2OAT)
-
-  ifeq ($(1),optimizing)
-    core_compile_options += --compiler-backend=Optimizing
-  endif
-  ifeq ($(1),interpreter)
-    core_compile_options += --compiler-filter=quicken
-    core_infix := -interpreter
-  endif
-  ifeq ($(1),interp-ac)
-    core_compile_options += --compiler-filter=extract --runtime-arg -Xverify:softfail
-    core_infix := -interp-ac
-  endif
-  ifneq ($(filter-out interpreter interp-ac optimizing,$(1)),)
-    # Technically this test is not precise, but hopefully good enough.
-    $$(error found $(1) expected interpreter, interp-ac, or optimizing)
-  endif
-
-  core_image_location := $(ART_TARGET_TEST_OUT)/core$$(core_infix)$(CORE_IMG_SUFFIX)
-  core_image_name := $($(2)TARGET_CORE_IMG_OUT_BASE)$$(core_infix)$(CORE_IMG_SUFFIX)
-  core_oat_name := $($(2)TARGET_CORE_OAT_OUT_BASE)$$(core_infix)$(CORE_OAT_SUFFIX)
-
-  # Using the bitness suffix makes it easier to add as a dependency for the run-test mk.
-  ifeq ($(2),)
-    ifdef TARGET_2ND_ARCH
-      TARGET_CORE_IMAGE_$(1)_64 := $$(core_image_name)
-    else
-      TARGET_CORE_IMAGE_$(1)_32 := $$(core_image_name)
-    endif
-  else
-    TARGET_CORE_IMAGE_$(1)_32 := $$(core_image_name)
-  endif
-  TARGET_CORE_IMG_OUTS += $$(core_image_name)
-  TARGET_CORE_OAT_OUTS += $$(core_oat_name)
-
-$$(core_image_name): PRIVATE_CORE_COMPILE_OPTIONS := $$(core_compile_options)
-$$(core_image_name): PRIVATE_CORE_IMAGE_LOCATION := $$(core_image_location)
-$$(core_image_name): PRIVATE_CORE_IMG_NAME := $$(core_image_name)
-$$(core_image_name): PRIVATE_CORE_OAT_NAME := $$(core_oat_name)
-# In addition to the primary core image containing TARGET_CORE_IMG_DEX_FILES,
-# also build a boot image extension for the remaining TARGET_CORE_DEX_FILES.
-$$(core_image_name): $$(TARGET_CORE_DEX_FILES) $$(core_dex2oat_dependency)
-	@echo "target dex2oat: $$@"
-	@mkdir -p $$(dir $$@)
-	$$(hide) $$(DEX2OAT) \
-	  --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
-	  --runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
-	  $$(addprefix --dex-file=,$$(TARGET_CORE_IMG_DEX_FILES)) \
-	  $$(addprefix --dex-location=,$$(TARGET_CORE_IMG_DEX_LOCATIONS)) \
-	  --oat-file=$$(PRIVATE_CORE_OAT_NAME) \
-	  --oat-location=$$(PRIVATE_CORE_OAT_NAME) \
-	  --image=$$(PRIVATE_CORE_IMG_NAME) \
-	  --base=$$(LIBART_IMG_TARGET_BASE_ADDRESS) \
-	  --instruction-set=$$($(2)TARGET_ARCH) \
-	  --instruction-set-variant=$$($(2)DEX2OAT_TARGET_CPU_VARIANT) \
-	  --instruction-set-features=$$($(2)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
-	  --android-root=$$(PRODUCT_OUT)/system \
-	  --generate-debug-info --generate-build-id \
-	  --runtime-arg -XX:SlowDebug=true \
-	  $$(PRIVATE_CORE_COMPILE_OPTIONS) && \
-	$$(DEX2OAT) \
-	  --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
-	  --runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
-	  --runtime-arg -Xbootclasspath:$$(subst $$(space),:,$$(strip \
-	        $$(TARGET_CORE_DEX_FILES))) \
-	  --runtime-arg -Xbootclasspath-locations:$$(subst $$(space),:,$$(strip \
-	        $$(TARGET_CORE_DEX_LOCATIONS))) \
-	  $$(addprefix --dex-file=, \
-	       $$(filter-out $$(TARGET_CORE_IMG_DEX_FILES),$$(TARGET_CORE_DEX_FILES))) \
-	  $$(addprefix --dex-location=, \
-	       $$(filter-out $$(TARGET_CORE_IMG_DEX_LOCATIONS),$$(TARGET_CORE_DEX_LOCATIONS))) \
-	  --oat-file=$$(PRIVATE_CORE_OAT_NAME) \
-	  --oat-location=$$(PRIVATE_CORE_OAT_NAME) \
-	  --boot-image=$$(PRIVATE_CORE_IMAGE_LOCATION) \
-	  --image=$$(PRIVATE_CORE_IMG_NAME) \
-	  --instruction-set=$$($(2)TARGET_ARCH) \
-	  --instruction-set-variant=$$($(2)DEX2OAT_TARGET_CPU_VARIANT) \
-	  --instruction-set-features=$$($(2)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
-	  --android-root=$$(PRODUCT_OUT)/system \
-	  --generate-debug-info --generate-build-id \
-	  --runtime-arg -XX:SlowDebug=true \
-	  $$(PRIVATE_CORE_COMPILE_OPTIONS) || \
-	(rm $$(PRIVATE_CORE_OAT_NAME); exit 1)
-
-$$(core_oat_name): $$(core_image_name)
-
-  # Clean up locally used variables.
-  core_dex2oat_dependency :=
-  core_compile_options :=
-  core_image_name :=
-  core_oat_name :=
-  core_infix :=
-endef  # create-core-oat-target-rules
-
-# $(1): compiler - optimizing, interpreter or interp-ac (interpreter-access-checks).
-define create-core-oat-target-rule-combination
-  $(call create-core-oat-target-rules,$(1),)
-
-  ifdef TARGET_2ND_ARCH
-    $(call create-core-oat-target-rules,$(1),2ND_)
-  endif
-endef
-
-$(eval $(call create-core-oat-target-rule-combination,optimizing))
-$(eval $(call create-core-oat-target-rule-combination,interpreter))
-$(eval $(call create-core-oat-target-rule-combination,interp-ac))
-
-# Define a default core image that can be used for things like gtests that
-# need some image to run, but don't otherwise care which image is used.
-HOST_CORE_IMAGE_DEFAULT_32 := $(HOST_CORE_IMAGE_optimizing_32)
-HOST_CORE_IMAGE_DEFAULT_64 := $(HOST_CORE_IMAGE_optimizing_64)
-TARGET_CORE_IMAGE_DEFAULT_32 := $(TARGET_CORE_IMAGE_optimizing_32)
-TARGET_CORE_IMAGE_DEFAULT_64 := $(TARGET_CORE_IMAGE_optimizing_64)
diff --git a/build/README.md b/build/README.md
new file mode 100644
index 0000000..cc422c3
--- /dev/null
+++ b/build/README.md
@@ -0,0 +1,133 @@
+# Building the ART Module
+
+ART is built as a module in the form of an APEX package, `com.android.art.apex`.
+That package can be installed with `adb install` on a device running Android S
+or later. It is also included in the system partition (in the `system/apex`
+directory) of platform releases, to ensure it is always available.
+
+The recommended way to build the ART Module is to use the `master-art` manifest,
+which only has the sources and dependencies required for the module.
+
+Currently it is also possible to build ART directly from sources in a platform
+build, i.e. as has been the traditional way up until Android S. However that
+method is being phased out.
+
+The ART Module is available as a debug variant, `com.android.art.debug.apex`,
+which has extra internal consistency checks enabled, and some debug tools. A
+device cannot have both the non-debug and debug variants installed at once - it
+may not boot then.
+
+`com.google.android.art.apex` (note `.google.`) is the Google signed variant of
+the module. It is also mutually exclusive with the other ones.
+
+
+## Building as a module on `master-art`
+
+1.  Check out the `master-art` tree:
+
+    ```
+    repo init -b master-art -u <repository url>
+    ```
+
+    See the [Android source access
+    instructions](https://source.android.com/setup/build/downloading) for
+    further details.
+
+2.  Set up the development environment:
+
+    ```
+    banchan com.android.art <arch>
+    export SOONG_ALLOW_MISSING_DEPENDENCIES=true
+    ```
+
+    For Google internal builds on the internal master-art branch, specify
+    instead the Google variant of the module and product:
+
+    ```
+    banchan com.google.android.art mainline_modules_<arch>
+    export SOONG_ALLOW_MISSING_DEPENDENCIES=true
+    ```
+
+    `<arch>` is the device architecture, one of `arm`, `arm64`, `x86`, or
+    `x86_64`. Regardless of the device architecture, the build also includes the
+    usual host architectures, and 64/32-bit multilib for the 64-bit products.
+
+    To build the debug variant of the module, specify `com.android.art.debug`
+    instead of `com.android.art`. It is also possible to list both.
+
+3.  Build the module:
+
+    ```
+    m
+    ```
+
+4.  Install the module and reboot:
+
+    ```
+    adb install out/target/product/generic_<arch>/system/apex/com.android.art.apex
+    adb reboot
+    ```
+
+    The name of the APEX file depends on what you passed to `banchan`.
+
+
+## Building as part of the base system image
+
+NOTE: This method of building is slated to be obsoleted in favor of the
+module build on `master-art` above (b/172480617).
+
+1.  Check out a full Android platform tree and lunch the appropriate product the
+    normal way.
+
+2.  Ensure the ART Module is built from source:
+
+    ```
+    export SOONG_CONFIG_art_module_source_build=true
+    ```
+
+    If this isn't set then the build may use prebuilts of the ART Module that
+    may be older than the sources.
+
+3.  Build the system image the normal way, for example:
+
+    ```
+    m droid
+    ```
+
+
+## Updating prebuilts
+
+Prebuilts are used for the ART Module dependencies that have sources outside the
+`master-art` manifest. Conversely the ART Module is (normally) a prebuilt when
+used in platform builds of the base system image.
+
+The locations of the prebuilts are:
+
+*  `prebuilts/runtime/mainline` for prebuilts and SDKs required to build the ART
+   Module.
+
+   See
+   [prebuilts/runtime/mainline/README.md](https://android.googlesource.com/platform/prebuilts/runtime/+/master/mainline/README.md)
+   for instructions on how to update them.
+
+*  `packages/modules/ArtPrebuilt` for the ART Module APEX packages.
+
+*  `prebuilts/module_sdk/art` for the ART Module SDK and other tools, needed to
+   build platform images and other modules that depend on the ART Module.
+
+To update the ART Module prebuilts in the two last locations:
+
+1.  Ensure the changes that need to go into the prebuilt are submitted.
+
+2.  Wait for a new build on branch `aosp-master-art`, target `aosp_art_module`.
+
+3.  In a full platform tree, run:
+
+    ```
+    packages/modules/ArtPrebuilt/update-art-module-prebuilts.py \
+      --build <build id> --upload
+    ```
+
+    This will download the prebuilts from the given `<build id>` (an integer
+    number), create a CL topic, and upload it to Gerrit. Get it reviewed and
+    submit. Please do not make any file changes locally.
diff --git a/build/SoongConfig.bp b/build/SoongConfig.bp
new file mode 100644
index 0000000..3e2d8fc
--- /dev/null
+++ b/build/SoongConfig.bp
@@ -0,0 +1,86 @@
+// Set up Soong config variables.
+// https://android.googlesource.com/platform/build/soong/+/master/README.md#soong-config-variables
+
+// The source_build variable in the art_module namespace is used to enable the
+// apex, sdk, and module_exports modules that make up the ART Module by setting
+// SOONG_CONFIG_art_module_source_build in make.
+// TODO(b/172480617): Clean up when ART source is no longer in the platform
+// manifest.
+soong_config_bool_variable {
+    name: "source_build",
+}
+
+soong_config_module_type {
+    name: "art_module_art_global_defaults",
+    module_type: "art_global_defaults",
+    config_namespace: "art_module",
+    bool_variables: ["source_build"],
+    properties: ["enabled"],
+}
+
+soong_config_module_type {
+    name: "art_module_apex_defaults",
+    module_type: "apex_defaults",
+    config_namespace: "art_module",
+    bool_variables: ["source_build"],
+    properties: ["enabled"],
+}
+
+soong_config_module_type {
+    name: "art_module_cc_defaults",
+    module_type: "cc_defaults",
+    config_namespace: "art_module",
+    bool_variables: ["source_build"],
+    properties: [
+        "enabled",
+        "target.android.test_for",
+    ],
+}
+
+soong_config_module_type {
+    name: "art_module_cc_genrule",
+    module_type: "cc_genrule",
+    config_namespace: "art_module",
+    bool_variables: ["source_build"],
+    properties: ["enabled"],
+}
+
+soong_config_module_type {
+    name: "art_module_exports",
+    module_type: "module_exports",
+    config_namespace: "art_module",
+    bool_variables: ["source_build"],
+    properties: ["enabled"],
+}
+
+soong_config_module_type {
+    name: "art_module_genrule_defaults",
+    module_type: "genrule_defaults",
+    config_namespace: "art_module",
+    bool_variables: ["source_build"],
+    properties: ["enabled"],
+}
+
+soong_config_module_type {
+    name: "art_module_java_defaults",
+    module_type: "java_defaults",
+    config_namespace: "art_module",
+    bool_variables: ["source_build"],
+    properties: ["enabled"],
+}
+
+soong_config_module_type {
+    name: "art_module_sdk",
+    module_type: "sdk",
+    config_namespace: "art_module",
+    bool_variables: ["source_build"],
+    properties: ["enabled"],
+}
+
+soong_config_module_type {
+    name: "art_module_sh_binary",
+    module_type: "sh_binary",
+    config_namespace: "art_module",
+    bool_variables: ["source_build"],
+    properties: ["enabled"],
+}
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 22510ef..c5acc91 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -3,20 +3,40 @@
 // Contains both the Android Managed Runtime (ART) and the Android Core Library
 // (Libcore).
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+soong_config_module_type_import {
+    from: "art/build/SoongConfig.bp",
+    module_types: [
+        "art_module_apex_defaults",
+        "art_module_cc_defaults",
+        "art_module_genrule_defaults",
+    ],
+}
+
 // Modules listed in LOCAL_REQUIRED_MODULES for module art-runtime in art/Android.mk.
-// - Base requirements (binaries for which both 32- and 64-bit versions are built, if relevant).
+// - Base requirements (binaries for which both 32- and 64-bit versions are built, if possible).
 art_runtime_base_binaries_both = [
     "dalvikvm",
 ]
 art_runtime_base_binaries_both_on_device_first_on_host = [
     "dex2oat",
 ]
-// - Base requirements (binaries for which a 32-bit version is preferred on device, but for which
-//   only the "first" (likely 64-bit) version is required on host).
-art_runtime_base_binaries_prefer32_on_device_first_on_host = [
+// - Base requirements (binaries for which the "first" version is preferred on device
+//  (likely 64-bit) and on host).
+art_runtime_base_binaries_first_on_device_first_on_host = [
     "dexoptanalyzer",
+    "odrefresh",
     "profman",
 ]
+
 // - Base requirements (libraries).
 //
 // Note: ART on-device chroot-based testing and benchmarking is not yet using
@@ -30,10 +50,11 @@
 // the ART APEX.
 art_runtime_base_native_shared_libs = [
     // External API (having APEX stubs).
-    "libdexfile_external",
+    "libdexfile",
     "libnativebridge",
     "libnativehelper",
     "libnativeloader",
+    "libsigchain",
     // libadbconnection is internal and loaded with dlopen(), but it cannot use
     // "required" because of cyclic dependency (b/124505714).
     "libadbconnection",
@@ -62,11 +83,13 @@
 
 bionic_binaries_both = [
     "linker",
+    // To validate the zip file generated by cloud server.
+    "ziptool",
 ]
 
-// - Debug variants (binaries for which a 32-bit version is preferred on device, but for which
-//   only the "first" (likely 64-bit) version is required on host).
-art_runtime_debug_binaries_prefer32_on_device_first_on_host = [
+// - Debug variants (binaries for which the "first" version is preferred on device
+//  (likely 64-bit) and on host).
+art_runtime_debug_binaries_first_on_device_first_on_host = [
     "dexoptanalyzerd",
     "profmand",
 ]
@@ -79,7 +102,7 @@
     "libadbconnectiond",
     "libartd",
     "libartd-compiler",
-    "libdexfiled_external",
+    "libdexfiled",
     "libopenjdkjvmd",
     "libopenjdkjvmtid",
 ]
@@ -140,7 +163,6 @@
 libcore_java_libs = [
     "core-oj",
     "core-libart",
-    "core-icu4j",
     "okhttp",
     "bouncycastle",
     "apache-xml",
@@ -159,14 +181,10 @@
 // the ART APEX.
 libcore_native_shared_libs = [
     // External API (having APEX stubs).
-    "libandroidicu",
     "libandroidio",
     // TODO(b/124476339): Clean up the following libraries once "required"
     // dependencies work with APEX libraries.
     "libexpat",
-    "libicui18n",
-    "libicuuc",
-    "libicu_jni",
     "libjavacore",
     "libopenjdk",
 ]
@@ -174,12 +192,6 @@
     "libopenjdkd",
 ]
 
-libcore_native_device_only_shared_libs = [
-    // TODO(b/122876336): Remove libpac.so once it's migrated to Webview.
-    // libpac is used by frameworks, not by ART host.
-    "libpac",
-]
-
 // Temporary library includes for b/123591866 as all libraries are moved into the main art-apex.
 art_runtime_libraries_zipapex = [
     "libnativebridge",
@@ -199,48 +211,76 @@
     private_key: "com.android.art.pem",
 }
 
-prebuilt_etc {
-    name: "com.android.art.ld.config.txt",
-    src: "ld.config.txt",
-    filename: "ld.config.txt",
-    installable: false,
+art_module_apex_defaults {
+    name: "com.android.art-defaults",
+
+    // Enable if SOONG_CONFIG_art_module_source_build is true.
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+
+    target: {
+        windows: {
+            // When the Soong config variable above sets enabled:true, it
+            // overrides the default false for targets, so we need to disable
+            // windows explicitly.
+            enabled: false,
+        },
+    },
 }
 
 // Default values shared by device ART APEXes.
 apex_defaults {
-    name: "com.android.art-defaults",
+    name: "com.android.art-device-defaults",
+    defaults: ["com.android.art-defaults"],
     compile_multilib: "both",
     manifest: "manifest-art.json",
+    bootclasspath_fragments: ["art-bootclasspath-fragment"],
+    compat_configs: ["libcore-platform-compat-config"],
     java_libs: libcore_java_libs,
     native_shared_libs: art_runtime_base_native_shared_libs +
         art_runtime_base_native_device_only_shared_libs +
-        libcore_native_device_only_shared_libs +
         libcore_native_shared_libs,
     multilib: {
         both: {
             binaries: art_runtime_base_binaries_both +
                 art_runtime_base_binaries_both_on_device_first_on_host,
         },
-        prefer32: {
-            binaries: art_runtime_base_binaries_prefer32_on_device_first_on_host,
-        },
         first: {
-            binaries: art_tools_common_binaries +
+            binaries: art_runtime_base_binaries_first_on_device_first_on_host +
+                art_tools_common_binaries +
                 art_tools_device_only_binaries,
         },
     },
-    prebuilts: ["com.android.art.ld.config.txt"],
     key: "com.android.art.key",
     required: [
-        "art_apex_boot_integrity",
         "com.android.i18n",
     ],
+    prebuilts: [
+        "art-linker-config",
+        "current_sdkinfo",
+    ],
+    // ART APEXes depend on bouncycastle which is disabled for PDK builds.
+    // Since the dependency is disabled, ART APEXes can't be built either.
+    // Disable the APEXes too. See b/157267166.
+    product_variables: {
+        pdk: {
+            enabled: false,
+        },
+    },
+    min_sdk_version: "S",
+    // Indicates that pre-installed version of this apex can be compressed.
+    // Whether it actually will be compressed is controlled on per-device basis.
+    compressible: true,
 }
 
 // Default values shared by (device) Debug and Testing ART APEXes.
 apex_defaults {
-    name: "com.android.art-dev-defaults",
-    defaults: ["com.android.art-defaults"],
+    name: "com.android.art-devel-defaults",
+    defaults: ["com.android.art-device-defaults"],
     native_shared_libs: art_runtime_base_native_device_only_debug_shared_libs +
         art_runtime_run_test_libs +
         art_runtime_debug_native_shared_libs +
@@ -250,22 +290,29 @@
             binaries: art_tools_debug_binaries_both +
                 art_runtime_debug_binaries_both_on_device_first_on_host,
         },
-        prefer32: {
-            binaries: art_runtime_debug_binaries_prefer32_on_device_first_on_host,
-        },
         first: {
-            binaries: art_tools_debug_binaries +
+            binaries: art_runtime_debug_binaries_first_on_device_first_on_host +
+                art_tools_debug_binaries +
                 art_tools_debug_device_only_binaries,
         },
     },
 }
 
+apex_test {
+    name: "test_com.android.art",
+    defaults: ["com.android.art-devel-defaults"],
+    manifest: "test_apex_manifest.json",
+    file_contexts: ":com.android.art.debug-file_contexts",
+    certificate: ":com.android.art.certificate",
+    installable: false,
+}
+
 // Release version of the ART APEX module (not containing debug
 // variants nor tools), included in user builds. Also used for
 // storage-constrained devices in userdebug and eng builds.
 art_apex {
-    name: "com.android.art.release",
-    defaults: ["com.android.art-defaults"],
+    name: "com.android.art",
+    defaults: ["com.android.art-device-defaults"],
     certificate: ":com.android.art.certificate",
 }
 
@@ -274,7 +321,7 @@
 // eng build.
 art_apex {
     name: "com.android.art.debug",
-    defaults: ["com.android.art-dev-defaults"],
+    defaults: ["com.android.art-devel-defaults"],
     certificate: ":com.android.art.certificate",
 }
 
@@ -296,6 +343,7 @@
     "art_libdexfile_support_tests",
     "art_libprofile_tests",
     "art_oatdump_tests",
+    "art_odrefresh_tests",
     "art_profman_tests",
     "art_runtime_compiler_tests",
     "art_runtime_tests",
@@ -307,11 +355,12 @@
 // purposes only.
 art_apex_test {
     name: "com.android.art.testing",
-    defaults: ["com.android.art-dev-defaults"],
+    defaults: ["com.android.art-devel-defaults"],
     file_contexts: ":com.android.art.debug-file_contexts",
     certificate: ":com.android.art.certificate",
     tests: art_gtests,
     binaries: ["signal_dumper"], // Need signal_dumper for run-tests.
+    updatable: false,
 }
 
 // TODO: Do this better. art_apex_test_host will disable host builds when
@@ -321,11 +370,13 @@
 // See b/120617876 for more information.
 art_apex_test_host {
     name: "com.android.art.host",
+    defaults: ["com.android.art-defaults"],
     compile_multilib: "both",
     payload_type: "zip",
     host_supported: true,
     device_supported: false,
     manifest: "manifest-art.json",
+    updatable: false,
     java_libs: libcore_java_libs,
     ignore_system_library_special_case: true,
     native_shared_libs: art_runtime_base_native_shared_libs +
@@ -340,9 +391,9 @@
                 art_tools_debug_binaries_both,
         },
         first: {
-            binaries: art_runtime_base_binaries_prefer32_on_device_first_on_host +
-                art_runtime_base_binaries_both_on_device_first_on_host +
-                art_runtime_debug_binaries_prefer32_on_device_first_on_host +
+            binaries: art_runtime_base_binaries_both_on_device_first_on_host +
+                art_runtime_base_binaries_first_on_device_first_on_host +
+                art_runtime_debug_binaries_first_on_device_first_on_host +
                 art_runtime_debug_binaries_both_on_device_first_on_host +
                 art_tools_common_binaries +
                 art_tools_debug_binaries + // Host APEX is always debug.
@@ -355,7 +406,6 @@
             enabled: false,
         },
         linux_bionic: {
-            enabled: true,
             multilib: {
                 both: {
                     native_shared_libs: bionic_native_shared_libs,
@@ -364,42 +414,62 @@
             },
         },
     },
+    // ART APEXes depend on bouncycastle which is disabled for PDK builds.
+    // Since the dependency is disabled, ART APEXes can't be built either.
+    // Disable the APEXes too. See b/157267166.
+    product_variables: {
+        pdk: {
+            enabled: false,
+        },
+    },
 }
 
 python_binary_host {
     name: "art-apex-tester",
     srcs: ["art_apex_test.py"],
     main: "art_apex_test.py",
-    version: {
-        py2: {
-            enabled: true,
-        },
-        py3: {
-            enabled: false,
-        },
-    },
 }
 
 // Genrules so we can run the checker, and empty Java library so that it gets executed.
 
 art_check_apex_gen_stem = "$(location art-apex-tester)" +
-    " --debugfs $(location debugfs)" +
+    " --deapexer $(location deapexer)" +
+    " --debugfs $(location debugfs_static)" +
     " --tmpdir $(genDir)"
 
 // The non-flattened APEXes are always checked, as they are always generated
 // (even when APEX flattening is enabled).
-genrule_defaults {
+art_module_genrule_defaults {
     name: "art-check-apex-gen-defaults",
+
+    // Enable if SOONG_CONFIG_art_module_source_build is true.
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+
     tools: [
         "art-apex-tester",
-        "debugfs",
+        "deapexer",
+        "debugfs_static",
     ],
 }
 
-cc_defaults {
+art_module_cc_defaults {
     name: "art-check-apex-gen-fakebin-defaults",
     host_supported: true,
     device_supported: false,
+
+    // Enable if SOONG_CONFIG_art_module_source_build is true.
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+
     target: {
         darwin: {
             enabled: false, // No python3.
@@ -410,12 +480,13 @@
 genrule {
     name: "art-check-release-apex-gen",
     defaults: ["art-check-apex-gen-defaults"],
-    srcs: [":com.android.art.release"],
+    srcs: [":com.android.art"],
     cmd: art_check_apex_gen_stem +
         " --flavor release" +
         " $(in)" +
-        " && touch $(out)",
-    out: ["art-check-release-apex-gen.dummy"],
+        " && touch $(out)" +
+        " && chmod a+x $(out)",
+    out: ["art-check-release-apex-gen.unused"],
 }
 
 cc_prebuilt_binary {
@@ -431,8 +502,9 @@
     cmd: art_check_apex_gen_stem +
         " --flavor debug" +
         " $(in)" +
-        " && touch $(out)",
-    out: ["art-check-debug-apex-gen.dummy"],
+        " && touch $(out)" +
+        " && chmod a+x $(out)",
+    out: ["art-check-debug-apex-gen.unused"],
 }
 
 cc_prebuilt_binary {
@@ -448,8 +520,9 @@
     cmd: art_check_apex_gen_stem +
         " --flavor testing" +
         " $(in)" +
-        " && touch $(out)",
-    out: ["art-check-testing-apex-gen.dummy"],
+        " && touch $(out)" +
+        " && chmod a+x $(out)",
+    out: ["art-check-testing-apex-gen.unused"],
 }
 
 cc_prebuilt_binary {
@@ -457,3 +530,9 @@
     defaults: ["art-check-apex-gen-fakebin-defaults"],
     srcs: [":art-check-testing-apex-gen"],
 }
+
+linker_config {
+    name: "art-linker-config",
+    src: "linker.config.json",
+    installable: false,
+}
diff --git a/build/apex/art_apex_boot_integrity.rc b/build/apex/art_apex_boot_integrity.rc
deleted file mode 100644
index 92f616b..0000000
--- a/build/apex/art_apex_boot_integrity.rc
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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.
-#
-
-# Check that boot classpath files in /data/dalvik-cache have fsverity
-# protection
-
-on post-fs-data
-    # TODO: Use apex path once feature is implemented.
-    exec - root -- /system/bin/art_apex_boot_integrity
diff --git a/build/apex/art_apex_boot_integrity.sh b/build/apex/art_apex_boot_integrity.sh
deleted file mode 100644
index 36d0f7f..0000000
--- a/build/apex/art_apex_boot_integrity.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/system/bin/sh
-
-# 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.
-#
-
-alias log_info="log -t art_apex -p i"
-alias log_error="log -t art_apex -p f"
-
-log_info "=== ART pre-boot integrity checks ==="
-
-# Measure (and enable) fsverity to see if things are installed. Enable is not
-# idempotent, and we'd need to parse the error string to see whether it says
-# data was installed. Rather do a two-step.
-FILES=`find /data/dalvik-cache -type f -a -name 'system@framework@boot*' -o name 'system@framework@*jar*'`
-
-if [ ! -f "/system/bin/fsverity" ] ; then
-  log_error "Device is not fsverity-enabled."
-  rm -f $FILES
-  exit 0
-fi
-
-for FILE in $FILES ; do
-  if [ ! -f "$FILE" ] ; then
-    continue # May have deleted already.
-  fi
-
-  # Check for fsverity protection.
-  fsverity measure $FILE || \
-    ENABLE_MSG=`fsverity enable $FILE 2>&1` || \
-      {
-        # No installed data, can't enable - clean up.
-        # Note: to avoid side effects, only delete the tested files. To avoid
-        #       understanding arches here, delete all, even if that may delete
-        #       too aggressively.
-        log_error "Enable failed: $ENABLE_MSG" ;
-        rm -f $FILES ;
-        exit 1 ;
-      }
-
-  # Check for integrity.
-  INTEGRITY_MSG=`dd if=$FILE of=/dev/null bs=4k 2>&1` || \
-    { log_error "Integrity failed: $INTEGRITY_MSG" ; rm -f $FILES ; exit 2 ; }
-done
diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py
index 6bccdf5..4c090a2 100755
--- a/build/apex/art_apex_test.py
+++ b/build/apex/art_apex_test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 # Copyright (C) 2019 The Android Open Source Project
@@ -21,6 +21,7 @@
 import logging
 import os
 import os.path
+import shutil
 import subprocess
 import sys
 import zipfile
@@ -57,6 +58,17 @@
   return var in os.environ and os.environ[var] == 'true'
 
 
+def extract_apex(apex_path, deapexer_path, debugfs_path, tmpdir):
+  _, apex_name = os.path.split(apex_path)
+  extract_path = os.path.join(tmpdir, apex_name)
+  if os.path.exists(extract_path):
+    shutil.rmtree(extract_path)
+  subprocess.check_call([deapexer_path, '--debugfs', debugfs_path,
+                         'extract', apex_path, extract_path],
+                        stdout=subprocess.DEVNULL)
+  return extract_path
+
+
 class FSObject:
   def __init__(self, name, is_dir, is_exec, is_symlink, size):
     self.name = name
@@ -71,83 +83,6 @@
 
 
 class TargetApexProvider:
-  def __init__(self, apex, tmpdir, debugfs):
-    self._tmpdir = tmpdir
-    self._debugfs = debugfs
-    self._folder_cache = {}
-    self._payload = os.path.join(self._tmpdir, 'apex_payload.img')
-    # Extract payload to tmpdir.
-    apex_zip = zipfile.ZipFile(apex)
-    apex_zip.extract('apex_payload.img', tmpdir)
-
-  def __del__(self):
-    # Delete temps.
-    if os.path.exists(self._payload):
-      os.remove(self._payload)
-
-  def get(self, path):
-    apex_dir, name = os.path.split(path)
-    if not apex_dir:
-      apex_dir = '.'
-    apex_map = self.read_dir(apex_dir)
-    return apex_map[name] if name in apex_map else None
-
-  def read_dir(self, apex_dir):
-    if apex_dir in self._folder_cache:
-      return self._folder_cache[apex_dir]
-    # Cannot use check_output as it will annoy with stderr.
-    process = subprocess.Popen([self._debugfs, '-R', 'ls -l -p %s' % apex_dir, self._payload],
-                               stdout=subprocess.PIPE, stderr=subprocess.PIPE,
-                               universal_newlines=True)
-    stdout, _ = process.communicate()
-    res = str(stdout)
-    apex_map = {}
-    # Debugfs output looks like this:
-    #   debugfs 1.44.4 (18-Aug-2018)
-    #   /12/040755/0/2000/.//
-    #   /2/040755/1000/1000/..//
-    #   /13/100755/0/2000/dalvikvm32/28456/
-    #   /14/100755/0/2000/dexoptanalyzer/20396/
-    #   /15/100755/0/2000/linker/1152724/
-    #   /16/100755/0/2000/dex2oat/563508/
-    #   /17/100755/0/2000/linker64/1605424/
-    #   /18/100755/0/2000/profman/85304/
-    #   /19/100755/0/2000/dalvikvm64/28576/
-    #    |     |   |   |       |        |
-    #    |     |   |   #- gid  #- name  #- size
-    #    |     |   #- uid
-    #    |     #- type and permission bits
-    #    #- inode nr (?)
-    #
-    # Note: could break just on '/' to avoid names with newlines.
-    for line in res.split("\n"):
-      if not line:
-        continue
-      comps = line.split('/')
-      if len(comps) != 8:
-        logging.warning('Could not break and parse line \'%s\'', line)
-        continue
-      bits = comps[2]
-      name = comps[5]
-      size_str = comps[6]
-      # Use a negative value as an indicator of undefined/unknown size.
-      size = int(size_str) if size_str != '' else -1
-      if len(bits) != 6:
-        logging.warning('Dont understand bits \'%s\'', bits)
-        continue
-      is_dir = bits[1] == '4'
-
-      def is_exec_bit(ch):
-        return int(ch) & 1 == 1
-
-      is_exec = is_exec_bit(bits[3]) and is_exec_bit(bits[4]) and is_exec_bit(bits[5])
-      is_symlink = bits[1] == '2'
-      apex_map[name] = FSObject(name, is_dir, is_exec, is_symlink, size)
-    self._folder_cache[apex_dir] = apex_map
-    return apex_map
-
-
-class TargetFlattenedApexProvider:
   def __init__(self, apex):
     self._folder_cache = {}
     self._apex = apex
@@ -337,6 +272,14 @@
       if not self._provider.get(test_path).is_exec:
         self.fail('%s is not executable', test_path)
 
+  def check_art_test_data(self, filename):
+    dirs = self.arch_dirs_for_path(ART_TEST_DIR)
+    if not dirs:
+      self.fail('ART test data missing: %s', filename)
+    for dir in dirs:
+      if not self.check_file('%s/%s' % (dir, filename)):
+        return
+
   def check_single_library(self, filename):
     lib_path = 'lib/%s' % filename
     lib64_path = 'lib64/%s' % filename
@@ -519,7 +462,7 @@
     self._checker.check_symlinked_multilib_executable('dalvikvm')
 
     # Check exported libraries for ART.
-    self._checker.check_native_library('libdexfile_external')
+    self._checker.check_native_library('libdexfile')
     self._checker.check_native_library('libnativebridge')
     self._checker.check_native_library('libnativehelper')
     self._checker.check_native_library('libnativeloader')
@@ -532,17 +475,15 @@
     self._checker.check_native_library('libart-disassembler')
     self._checker.check_native_library('libartbase')
     self._checker.check_native_library('libartpalette')
-    self._checker.check_native_library('libdexfile')
-    self._checker.check_native_library('libdexfile_support')
+    self._checker.check_native_library('libdt_fd_forward')
     self._checker.check_native_library('libopenjdkjvm')
     self._checker.check_native_library('libopenjdkjvmti')
     self._checker.check_native_library('libprofile')
     self._checker.check_native_library('libsigchain')
 
-    # Check java libraries for Managed Core Library.
+    # Check Java libraries for Managed Core Library.
     self._checker.check_java_library('apache-xml')
     self._checker.check_java_library('bouncycastle')
-    self._checker.check_java_library('core-icu4j')
     self._checker.check_java_library('core-libart')
     self._checker.check_java_library('core-oj')
     self._checker.check_java_library('okhttp')
@@ -568,14 +509,13 @@
     self._checker.check_native_library('libbacktrace')
     self._checker.check_native_library('libbase')
     self._checker.check_native_library('libc++')
-    self._checker.check_native_library('libdt_fd_forward')
     self._checker.check_native_library('libdt_socket')
     self._checker.check_native_library('libjdwp')
+    self._checker.check_native_library('liblz4')
     self._checker.check_native_library('liblzma')
     self._checker.check_native_library('libnpt')
     self._checker.check_native_library('libunwindstack')
     self._checker.check_native_library('libziparchive')
-    self._checker.check_optional_native_library('libvixl')  # Only on ARM/ARM64
 
     # Allow extra dependencies that appear in ASAN builds.
     self._checker.check_optional_native_library('libclang_rt.asan*')
@@ -586,7 +526,6 @@
     self._checker.check_dexpreopt('boot')
     self._checker.check_dexpreopt('boot-apache-xml')
     self._checker.check_dexpreopt('boot-bouncycastle')
-    self._checker.check_dexpreopt('boot-core-icu4j')
     self._checker.check_dexpreopt('boot-core-libart')
     self._checker.check_dexpreopt('boot-okhttp')
     if isEnvTrue('EMMA_INSTRUMENT_FRAMEWORK'):
@@ -607,31 +546,19 @@
     # removed in Android R.
 
     # Check binaries for ART.
-    self._checker.check_executable('oatdump')
     self._checker.check_multilib_executable('dex2oat')
+    self._checker.check_executable('oatdump')
+    self._checker.check_executable("odrefresh")
 
     # Check internal libraries for ART.
-    self._checker.check_prefer64_library('libart-disassembler')
     self._checker.check_native_library('libperfetto_hprof')
 
     # Check exported native libraries for Managed Core Library.
-    self._checker.check_native_library('libandroidicu')
     self._checker.check_native_library('libandroidio')
 
     # Check internal native library dependencies.
     self._checker.check_native_library('libcrypto')
     self._checker.check_native_library('libexpat')
-    self._checker.check_native_library('libicui18n')
-    self._checker.check_native_library('libicuuc')
-    self._checker.check_native_library('libicu_jni')
-    self._checker.check_native_library('libpac')
-    self._checker.check_native_library('libz')
-
-    # TODO(b/139046641): Fix proper 2nd arch checks. For now, just ignore these
-    # directories.
-    self._checker.ignore_path('bin/arm')
-    self._checker.ignore_path('lib/arm')
-    self._checker.ignore_path('lib64/arm')
 
 
 class ReleaseHostChecker:
@@ -646,16 +573,14 @@
     self._checker.check_executable('hprof-conv')
     self._checker.check_symlinked_first_executable('dex2oatd')
     self._checker.check_symlinked_first_executable('dex2oat')
+    self._checker.check_executable("odrefresh")
 
     # Check exported native libraries for Managed Core Library.
-    self._checker.check_native_library('libandroidicu-host')
+    self._checker.check_native_library('libicu')
     self._checker.check_native_library('libandroidio')
 
     # Check internal libraries for Managed Core Library.
     self._checker.check_native_library('libexpat-host')
-    self._checker.check_native_library('libicui18n-host')
-    self._checker.check_native_library('libicuuc-host')
-    self._checker.check_native_library('libicu_jni')
     self._checker.check_native_library('libz-host')
 
 
@@ -679,15 +604,16 @@
     self._checker.check_symlinked_multilib_executable('imgdiagd')
     self._checker.check_executable('profmand')
 
+    # Check exported libraries for ART.
+    self._checker.check_native_library('libdexfiled')
+
     # Check internal libraries for ART.
     self._checker.check_native_library('libadbconnectiond')
-    self._checker.check_native_library('libart-disassembler')
     self._checker.check_native_library('libartbased')
     self._checker.check_native_library('libartd')
     self._checker.check_native_library('libartd-compiler')
     self._checker.check_native_library('libartd-dexlayout')
     self._checker.check_native_library('libartd-disassembler')
-    self._checker.check_native_library('libdexfiled')
     self._checker.check_native_library('libopenjdkjvmd')
     self._checker.check_native_library('libopenjdkjvmtid')
     self._checker.check_native_library('libprofiled')
@@ -710,7 +636,6 @@
     self._checker.check_executable('oatdumpd')
 
     # Check ART internal libraries.
-    self._checker.check_native_library('libdexfiled_external')
     self._checker.check_native_library('libperfetto_hprofd')
 
     # Check internal native library dependencies.
@@ -725,7 +650,6 @@
     # double_loadable:true, cf. go/double_loadable). Also, like in the release
     # package we need to look out for dependencies that should go through
     # exported library stubs (until b/128708192 is fixed).
-    self._checker.check_optional_native_library('libvixld')  # Only on ARM/ARM64
     self._checker.check_prefer64_library('libmeminfo')
     self._checker.check_prefer64_library('libprocinfo')
 
@@ -738,254 +662,91 @@
     return 'Testing (Target) Checker'
 
   def run(self):
-    # Check cmdline tests.
-    self._checker.check_optional_art_test_executable('cmdline_parser_test')
-
-    # Check compiler tests.
-    self._checker.check_art_test_executable('atomic_dex_ref_map_test')
-    self._checker.check_art_test_executable('bounds_check_elimination_test')
-    self._checker.check_art_test_executable('codegen_test')
-    self._checker.check_art_test_executable('compiled_method_storage_test')
-    self._checker.check_art_test_executable('data_type_test')
-    self._checker.check_art_test_executable('dedupe_set_test')
-    self._checker.check_art_test_executable('dominator_test')
-    self._checker.check_art_test_executable('dwarf_test')
-    self._checker.check_art_test_executable('exception_test')
-    self._checker.check_art_test_executable('find_loops_test')
-    self._checker.check_art_test_executable('graph_checker_test')
-    self._checker.check_art_test_executable('graph_test')
-    self._checker.check_art_test_executable('gvn_test')
-    self._checker.check_art_test_executable('induction_var_analysis_test')
-    self._checker.check_art_test_executable('induction_var_range_test')
-    self._checker.check_art_test_executable('jni_cfi_test')
-    self._checker.check_art_test_executable('jni_compiler_test')
-    self._checker.check_art_test_executable('licm_test')
-    self._checker.check_art_test_executable('linker_patch_test')
-    self._checker.check_art_test_executable('live_interval_test')
-    self._checker.check_art_test_executable('load_store_analysis_test')
-    self._checker.check_art_test_executable('load_store_elimination_test')
-    self._checker.check_art_test_executable('loop_optimization_test')
-    self._checker.check_art_test_executable('nodes_test')
-    self._checker.check_art_test_executable('nodes_vector_test')
-    self._checker.check_art_test_executable('optimizing_cfi_test')
-    self._checker.check_art_test_executable('output_stream_test')
-    self._checker.check_art_test_executable('parallel_move_test')
-    self._checker.check_art_test_executable('pretty_printer_test')
-    self._checker.check_art_test_executable('reference_type_propagation_test')
-    self._checker.check_art_test_executable('scheduler_test')
-    self._checker.check_art_test_executable('select_generator_test')
-    self._checker.check_art_test_executable('side_effects_test')
-    self._checker.check_art_test_executable('src_map_elem_test')
-    self._checker.check_art_test_executable('ssa_liveness_analysis_test')
-    self._checker.check_art_test_executable('ssa_test')
-    self._checker.check_art_test_executable('stack_map_test')
-    self._checker.check_art_test_executable('superblock_cloner_test')
-    self._checker.check_art_test_executable('suspend_check_test')
-    self._checker.check_art_test_executable('swap_space_test')
-    # These tests depend on a specific code generator and are conditionally included.
-    self._checker.check_optional_art_test_executable('constant_folding_test')
-    self._checker.check_optional_art_test_executable('dead_code_elimination_test')
-    self._checker.check_optional_art_test_executable('linearize_test')
-    self._checker.check_optional_art_test_executable('live_ranges_test')
-    self._checker.check_optional_art_test_executable('liveness_test')
-    self._checker.check_optional_art_test_executable('managed_register_arm64_test')
-    self._checker.check_optional_art_test_executable('managed_register_arm_test')
-    self._checker.check_optional_art_test_executable('managed_register_x86_64_test')
-    self._checker.check_optional_art_test_executable('managed_register_x86_test')
-    self._checker.check_optional_art_test_executable('register_allocator_test')
-
-    # Check dex2oat tests.
-    self._checker.check_art_test_executable('compiler_driver_test')
-    self._checker.check_art_test_executable('dex2oat_image_test')
-    self._checker.check_art_test_executable('dex2oat_test')
-    self._checker.check_art_test_executable('dex_to_dex_decompiler_test')
-    self._checker.check_art_test_executable('elf_writer_test')
-    self._checker.check_art_test_executable('image_test')
-    self._checker.check_art_test_executable('image_write_read_test')
-    self._checker.check_art_test_executable('index_bss_mapping_encoder_test')
-    self._checker.check_art_test_executable('multi_oat_relative_patcher_test')
-    self._checker.check_art_test_executable('oat_writer_test')
-    self._checker.check_art_test_executable('verifier_deps_test')
-    # These tests depend on a specific code generator and are conditionally included.
-    self._checker.check_optional_art_test_executable('relative_patcher_arm64_test')
-    self._checker.check_optional_art_test_executable('relative_patcher_thumb2_test')
-    self._checker.check_optional_art_test_executable('relative_patcher_x86_64_test')
-    self._checker.check_optional_art_test_executable('relative_patcher_x86_test')
-
-    # Check dexanalyze tests.
-    self._checker.check_optional_art_test_executable('dexanalyze_test')
-
-    # Check dexdiag tests.
-    self._checker.check_optional_art_test_executable('dexdiag_test')
-
-    # Check dexdump tests.
-    self._checker.check_art_test_executable('dexdump_test')
-
-    # Check dexlayout tests.
-    self._checker.check_optional_art_test_executable('dexlayout_test')
-
-    # Check dexlist tests.
-    self._checker.check_art_test_executable('dexlist_test')
-
-    # Check dexoptanalyzer tests.
-    self._checker.check_art_test_executable('dexoptanalyzer_test')
-
-    # Check imgdiag tests.
-    self._checker.check_art_test_executable('imgdiag_test')
-
-    # Check libartbase tests.
-    self._checker.check_art_test_executable('arena_allocator_test')
-    self._checker.check_art_test_executable('bit_field_test')
-    self._checker.check_art_test_executable('bit_memory_region_test')
-    self._checker.check_art_test_executable('bit_string_test')
-    self._checker.check_art_test_executable('bit_struct_test')
-    self._checker.check_art_test_executable('bit_table_test')
-    self._checker.check_art_test_executable('bit_utils_test')
-    self._checker.check_art_test_executable('bit_vector_test')
-    self._checker.check_art_test_executable('fd_file_test')
-    self._checker.check_art_test_executable('file_utils_test')
-    self._checker.check_art_test_executable('hash_set_test')
-    self._checker.check_art_test_executable('hex_dump_test')
-    self._checker.check_art_test_executable('histogram_test')
-    self._checker.check_art_test_executable('indenter_test')
-    self._checker.check_art_test_executable('instruction_set_test')
-    self._checker.check_art_test_executable('intrusive_forward_list_test')
-    self._checker.check_art_test_executable('leb128_test')
-    self._checker.check_art_test_executable('logging_test')
-    self._checker.check_art_test_executable('mem_map_test')
-    self._checker.check_art_test_executable('membarrier_test')
-    self._checker.check_art_test_executable('memfd_test')
-    self._checker.check_art_test_executable('memory_region_test')
-    self._checker.check_art_test_executable('safe_copy_test')
-    self._checker.check_art_test_executable('scoped_flock_test')
-    self._checker.check_art_test_executable('time_utils_test')
-    self._checker.check_art_test_executable('transform_array_ref_test')
-    self._checker.check_art_test_executable('transform_iterator_test')
-    self._checker.check_art_test_executable('utils_test')
-    self._checker.check_art_test_executable('variant_map_test')
-    self._checker.check_art_test_executable('zip_archive_test')
-
-    # Check libartpalette tests.
-    self._checker.check_art_test_executable('palette_test')
-
-    # Check libdexfile tests.
-    self._checker.check_art_test_executable('art_dex_file_loader_test')
+    # Check ART test binaries.
+    self._checker.check_art_test_executable('art_cmdline_tests')
+    self._checker.check_art_test_executable('art_compiler_tests')
+    self._checker.check_art_test_executable('art_dex2oat_tests')
+    self._checker.check_art_test_executable('art_dexanalyze_tests')
+    self._checker.check_art_test_executable('art_dexdiag_tests')
+    self._checker.check_art_test_executable('art_dexdump_tests')
+    self._checker.check_art_test_executable('art_dexlayout_tests')
+    self._checker.check_art_test_executable('art_dexlist_tests')
+    self._checker.check_art_test_executable('art_dexoptanalyzer_tests')
+    self._checker.check_art_test_executable('art_imgdiag_tests')
+    self._checker.check_art_test_executable('art_libartbase_tests')
+    self._checker.check_art_test_executable('art_libartpalette_tests')
     self._checker.check_art_test_executable('art_libdexfile_support_tests')
-    self._checker.check_art_test_executable('class_accessor_test')
-    self._checker.check_art_test_executable('code_item_accessors_test')
-    self._checker.check_art_test_executable('compact_dex_file_test')
-    self._checker.check_art_test_executable('compact_offset_table_test')
-    self._checker.check_art_test_executable('descriptors_names_test')
-    self._checker.check_art_test_executable('dex_file_loader_test')
-    self._checker.check_art_test_executable('dex_file_verifier_test')
-    self._checker.check_art_test_executable('dex_instruction_test')
-    self._checker.check_art_test_executable('primitive_test')
-    self._checker.check_art_test_executable('string_reference_test')
-    self._checker.check_art_test_executable('test_dex_file_builder_test')
-    self._checker.check_art_test_executable('type_lookup_table_test')
-    self._checker.check_art_test_executable('utf_test')
-
-    # Check libprofile tests.
-    self._checker.check_optional_art_test_executable('profile_boot_info_test')
-    self._checker.check_optional_art_test_executable('profile_compilation_info_test')
-
-    # Check oatdump tests.
-    self._checker.check_art_test_executable('oatdump_app_test')
-    self._checker.check_art_test_executable('oatdump_image_test')
-    self._checker.check_art_test_executable('oatdump_test')
-
-    # Check profman tests.
-    self._checker.check_art_test_executable('profile_assistant_test')
-
-    # Check runtime compiler tests.
-    self._checker.check_art_test_executable('module_exclusion_test')
-    self._checker.check_art_test_executable('reflection_test')
-
-    # Check runtime tests.
-    self._checker.check_art_test_executable('arch_test')
-    self._checker.check_art_test_executable('barrier_test')
-    self._checker.check_art_test_executable('card_table_test')
-    self._checker.check_art_test_executable('cha_test')
-    self._checker.check_art_test_executable('class_linker_test')
-    self._checker.check_art_test_executable('class_loader_context_test')
-    self._checker.check_art_test_executable('class_table_test')
-    self._checker.check_art_test_executable('compiler_filter_test')
-    self._checker.check_art_test_executable('dex_cache_test')
-    self._checker.check_art_test_executable('dlmalloc_space_random_test')
-    self._checker.check_art_test_executable('dlmalloc_space_static_test')
-    self._checker.check_art_test_executable('entrypoints_order_test')
-    self._checker.check_art_test_executable('exec_utils_test')
-    self._checker.check_art_test_executable('gtest_test')
-    self._checker.check_art_test_executable('handle_scope_test')
-    self._checker.check_art_test_executable('heap_test')
-    self._checker.check_art_test_executable('heap_verification_test')
-    self._checker.check_art_test_executable('hidden_api_test')
-    self._checker.check_art_test_executable('image_space_test')
-    self._checker.check_art_test_executable('immune_spaces_test')
-    self._checker.check_art_test_executable('imtable_test')
-    self._checker.check_art_test_executable('indirect_reference_table_test')
-    self._checker.check_art_test_executable('instruction_set_features_arm64_test')
-    self._checker.check_art_test_executable('instruction_set_features_arm_test')
-    self._checker.check_art_test_executable('instruction_set_features_test')
-    self._checker.check_art_test_executable('instruction_set_features_x86_64_test')
-    self._checker.check_art_test_executable('instruction_set_features_x86_test')
-    self._checker.check_art_test_executable('instrumentation_test')
-    self._checker.check_art_test_executable('intern_table_test')
-    self._checker.check_art_test_executable('java_vm_ext_test')
-    self._checker.check_art_test_executable('jit_memory_region_test')
-    self._checker.check_art_test_executable('jni_internal_test')
-    self._checker.check_art_test_executable('large_object_space_test')
-    self._checker.check_art_test_executable('math_entrypoints_test')
-    self._checker.check_art_test_executable('memcmp16_test')
-    self._checker.check_art_test_executable('method_handles_test')
-    self._checker.check_art_test_executable('method_type_test')
-    self._checker.check_art_test_executable('method_verifier_test')
-    self._checker.check_art_test_executable('mod_union_table_test')
-    self._checker.check_art_test_executable('monitor_pool_test')
-    self._checker.check_art_test_executable('monitor_test')
-    self._checker.check_art_test_executable('mutex_test')
-    self._checker.check_art_test_executable('oat_file_assistant_test')
-    self._checker.check_art_test_executable('oat_file_test')
-    self._checker.check_art_test_executable('object_test')
-    self._checker.check_art_test_executable('parsed_options_test')
-    self._checker.check_art_test_executable('prebuilt_tools_test')
-    self._checker.check_art_test_executable('profiling_info_test')
-    self._checker.check_art_test_executable('profile_saver_test')
-    self._checker.check_art_test_executable('proxy_test')
-    self._checker.check_art_test_executable('quick_trampoline_entrypoints_test')
-    self._checker.check_art_test_executable('reference_queue_test')
-    self._checker.check_art_test_executable('reference_table_test')
-    self._checker.check_art_test_executable('reg_type_test')
-    self._checker.check_art_test_executable('rosalloc_space_random_test')
-    self._checker.check_art_test_executable('rosalloc_space_static_test')
-    self._checker.check_art_test_executable('runtime_callbacks_test')
-    self._checker.check_art_test_executable('runtime_test')
-    self._checker.check_art_test_executable('safe_math_test')
-    self._checker.check_art_test_executable('space_bitmap_test')
-    self._checker.check_art_test_executable('space_create_test')
-    self._checker.check_art_test_executable('stub_test')
-    self._checker.check_art_test_executable('subtype_check_info_test')
-    self._checker.check_art_test_executable('subtype_check_test')
-    self._checker.check_art_test_executable('system_weak_test')
-    self._checker.check_art_test_executable('task_processor_test')
-    self._checker.check_art_test_executable('thread_pool_test')
-    self._checker.check_art_test_executable('timing_logger_test')
-    self._checker.check_art_test_executable('transaction_test')
-    self._checker.check_art_test_executable('two_runtimes_test')
-    self._checker.check_art_test_executable('unstarted_runtime_test')
-    self._checker.check_art_test_executable('var_handle_test')
-    self._checker.check_art_test_executable('vdex_file_test')
-
-    # Check sigchainlib tests.
-    self._checker.check_art_test_executable('sigchain_test')
+    self._checker.check_art_test_executable('art_libdexfile_tests')
+    self._checker.check_art_test_executable('art_libprofile_tests')
+    self._checker.check_art_test_executable('art_oatdump_tests')
+    self._checker.check_art_test_executable('art_odrefresh_tests')
+    self._checker.check_art_test_executable('art_profman_tests')
+    self._checker.check_art_test_executable('art_runtime_compiler_tests')
+    self._checker.check_art_test_executable('art_runtime_tests')
+    self._checker.check_art_test_executable('art_sigchain_tests')
 
     # Check ART test (internal) libraries.
-    self._checker.check_native_library('libart-gtest')
+    self._checker.check_native_library('libartd-gtest')
     self._checker.check_native_library('libartd-simulator-container')
 
     # Check ART test tools.
     self._checker.check_executable('signal_dumper')
 
+    # Check ART jar files which are needed for gtests.
+    self._checker.check_art_test_data('art-gtest-jars-AbstractMethod.jar')
+    self._checker.check_art_test_data('art-gtest-jars-MyClassNatives.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Main.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ProtoCompare.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Transaction.jar')
+    self._checker.check_art_test_data('art-gtest-jars-VerifierDepsMulti.dex')
+    self._checker.check_art_test_data('art-gtest-jars-Nested.jar')
+    self._checker.check_art_test_data('art-gtest-jars-MyClass.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ManyMethods.jar')
+    self._checker.check_art_test_data('art-gtest-jars-GetMethodSignature.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Lookup.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Instrumentation.jar')
+    self._checker.check_art_test_data('art-gtest-jars-MainUncompressedAligned.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ForClassLoaderD.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ForClassLoaderC.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ErroneousA.jar')
+    self._checker.check_art_test_data('art-gtest-jars-DexToDexDecompiler.jar')
+    self._checker.check_art_test_data('art-gtest-jars-HiddenApiSignatures.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ForClassLoaderB.jar')
+    self._checker.check_art_test_data('art-gtest-jars-LinkageTest.dex')
+    self._checker.check_art_test_data('art-gtest-jars-MethodTypes.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ErroneousInit.jar')
+    self._checker.check_art_test_data('art-gtest-jars-VerifierDeps.dex')
+    self._checker.check_art_test_data('art-gtest-jars-StringLiterals.jar')
+    self._checker.check_art_test_data('art-gtest-jars-XandY.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ExceptionHandle.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ImageLayoutB.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Interfaces.jar')
+    self._checker.check_art_test_data('art-gtest-jars-IMTB.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Extension2.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Extension1.jar')
+    self._checker.check_art_test_data('art-gtest-jars-MainEmptyUncompressedAligned.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ErroneousB.jar')
+    self._checker.check_art_test_data('art-gtest-jars-MultiDexModifiedSecondary.jar')
+    self._checker.check_art_test_data('art-gtest-jars-NonStaticLeafMethods.jar')
+    self._checker.check_art_test_data('art-gtest-jars-DefaultMethods.jar')
+    self._checker.check_art_test_data('art-gtest-jars-MultiDexUncompressedAligned.jar')
+    self._checker.check_art_test_data('art-gtest-jars-StaticsFromCode.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ProfileTestMultiDex.jar')
+    self._checker.check_art_test_data('art-gtest-jars-VerifySoftFailDuringClinit.dex')
+    self._checker.check_art_test_data('art-gtest-jars-MainStripped.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ForClassLoaderA.jar')
+    self._checker.check_art_test_data('art-gtest-jars-StaticLeafMethods.jar')
+    self._checker.check_art_test_data('art-gtest-jars-MultiDex.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Packages.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ProtoCompare2.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Statics.jar')
+    self._checker.check_art_test_data('art-gtest-jars-AllFields.jar')
+    self._checker.check_art_test_data('art-gtest-jars-IMTA.jar')
+    self._checker.check_art_test_data('art-gtest-jars-ImageLayoutA.jar')
+    self._checker.check_art_test_data('art-gtest-jars-MainEmptyUncompressed.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Dex2oatVdexTestDex.jar')
+    self._checker.check_art_test_data('art-gtest-jars-Dex2oatVdexPublicSdkDex.dex')
+
 
 class NoSuperfluousBinariesChecker:
   def __init__(self, checker):
@@ -1118,9 +879,13 @@
   if not test_args.flattened and not test_args.tmpdir:
     logging.error("Need a tmpdir.")
     return 1
-  if not test_args.flattened and not test_args.host and not test_args.debugfs:
-    logging.error("Need debugfs.")
-    return 1
+  if not test_args.flattened and not test_args.host:
+    if not test_args.deapexer:
+      logging.error("Need deapexer.")
+      return 1
+    if not test_args.debugfs:
+      logging.error("Need debugfs.")
+      return 1
 
   if test_args.host:
     # Host APEX.
@@ -1133,13 +898,21 @@
     # Device APEX.
     if test_args.flavor == FLAVOR_AUTO:
       logging.warning('--flavor=auto, trying to autodetect. This may be incorrect!')
-      for flavor in [ FLAVOR_RELEASE, FLAVOR_DEBUG, FLAVOR_TESTING ]:
-        flavor_pattern = '*.%s*' % flavor
+      # The order of flavors in the list below matters, as the release tag (empty string) will
+      # match any package name.
+      for flavor in [ FLAVOR_DEBUG, FLAVOR_TESTING, FLAVOR_RELEASE ]:
+        flavor_tag = flavor
+        # Special handling for the release flavor, whose name is no longer part of the Release ART
+        # APEX file name (`com.android.art.capex` / `com.android.art`).
+        if flavor == FLAVOR_RELEASE:
+          flavor_tag = ''
+        flavor_pattern = '*.%s*' % flavor_tag
         if fnmatch.fnmatch(test_args.apex, flavor_pattern):
           test_args.flavor = flavor
+          logging.warning('  Detected %s flavor', flavor)
           break
       if test_args.flavor == FLAVOR_AUTO:
-        logging.error('  Could not detect APEX flavor, neither \'%s\', \'%s\' nor \'%s\' in \'%s\'',
+        logging.error('  Could not detect APEX flavor, neither %s, %s nor %s for \'%s\'',
                     FLAVOR_RELEASE, FLAVOR_DEBUG, FLAVOR_TESTING, test_args.apex)
         return 1
 
@@ -1147,10 +920,13 @@
     if test_args.host:
       apex_provider = HostApexProvider(test_args.apex, test_args.tmpdir)
     else:
-      if test_args.flattened:
-        apex_provider = TargetFlattenedApexProvider(test_args.apex)
-      else:
-        apex_provider = TargetApexProvider(test_args.apex, test_args.tmpdir, test_args.debugfs)
+      apex_dir = test_args.apex
+      if not test_args.flattened:
+        # Extract the apex. It would be nice to use the output from "deapexer list"
+        # to avoid this work, but it doesn't provide info about executable bits.
+        apex_dir = extract_apex(test_args.apex, test_args.deapexer, test_args.debugfs,
+                                test_args.tmpdir)
+      apex_provider = TargetApexProvider(apex_dir)
   except (zipfile.BadZipFile, zipfile.LargeZipFile) as e:
     logging.error('Failed to create provider: %s', e)
     return 1
@@ -1233,7 +1009,7 @@
     sys.exit(1)
   host_out = os.environ['ANDROID_HOST_OUT']
 
-  test_args = test_parser.parse_args(['dummy'])  # For consistency.
+  test_args = test_parser.parse_args(['unused'])  # For consistency.
   test_args.debugfs = '%s/bin/debugfs' % host_out
   test_args.tmpdir = '.'
   test_args.tree = False
@@ -1249,15 +1025,16 @@
   # TODO: Add host support.
   # TODO: Add support for flattened APEX packages.
   configs = [
-    {'name': 'com.android.art.release', 'flavor': FLAVOR_RELEASE, 'host': False},
-    {'name': 'com.android.art.debug',   'flavor': FLAVOR_DEBUG,   'host': False},
-    {'name': 'com.android.art.testing', 'flavor': FLAVOR_TESTING, 'host': False},
+    {'name': 'com.android.art.capex',         'flavor': FLAVOR_RELEASE, 'host': False},
+    {'name': 'com.android.art.debug.capex',   'flavor': FLAVOR_DEBUG,   'host': False},
+    # Note: The Testing ART APEX is not a Compressed APEX.
+    {'name': 'com.android.art.testing.apex',  'flavor': FLAVOR_TESTING, 'host': False},
   ]
 
   for config in configs:
     logging.info(config['name'])
     # TODO: Host will need different path.
-    test_args.apex = '%s/system/apex/%s.apex' % (product_out, config['name'])
+    test_args.apex = '%s/system/apex/%s' % (product_out, config['name'])
     if not os.path.exists(test_args.apex):
       failed = True
       logging.error("Cannot find APEX %s. Please build it first.", test_args.apex)
@@ -1287,6 +1064,7 @@
   parser.add_argument('--size', help='Print file sizes', action='store_true')
 
   parser.add_argument('--tmpdir', help='Directory for temp files')
+  parser.add_argument('--deapexer', help='Path to deapexer')
   parser.add_argument('--debugfs', help='Path to debugfs')
 
   parser.add_argument('--bitness', help='Bitness to check', choices=BITNESS_ALL,
diff --git a/build/apex/ld.config.txt b/build/apex/ld.config.txt
deleted file mode 100644
index 0d80f3b..0000000
--- a/build/apex/ld.config.txt
+++ /dev/null
@@ -1,179 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Bionic loader config file for the ART APEX.
-#
-# There are no versioned APEX paths here - this APEX module does not support
-# having several versions mounted.
-
-dir.art = /apex/com.android.art/bin/
-
-[art]
-additional.namespaces = system,conscrypt,art,neuralnetworks,adbd
-
-# The default namespace here only links to other namespaces, in particular "art"
-# where the real library loading takes place. Any outgoing links from "art" also
-# need to be present here.
-namespace.default.isolated = true
-namespace.default.links = art,system,adbd
-namespace.default.link.art.allow_all_shared_libs = true
-namespace.default.link.system.allow_all_shared_libs = true
-namespace.default.link.adbd.shared_libs = libadbconnection_client.so
-
-###############################################################################
-# "art" APEX namespace
-#
-# This is the local namespace of this APEX, with the proper name "art" to make
-# links created e.g. through android_link_namespace work consistently with the
-# system linker config.
-###############################################################################
-namespace.art.isolated = true
-# Visible to allow links to be created at runtime, e.g. through
-# android_link_namespaces in libnativeloader.
-namespace.art.visible = true
-
-# Keep in sync with the "art" namespace in system/core/rootdir/etc/ld.config*.txt.
-namespace.art.search.paths = /apex/com.android.art/${LIB}
-namespace.art.asan.search.paths = /apex/com.android.art/${LIB}
-# JVMTI libraries used in ART testing are located under /data; dalvikvm
-# has to be able to dlopen them.
-# TODO(b/129534335): Move this to the linker configuration of the Test
-# ART APEX when it is available.
-namespace.art.permitted.paths = /data
-namespace.art.asan.permitted.paths = /data
-# odex files are in /system/framework and /apex/com.android.art/javalib.
-# dalvikvm has to be able to dlopen the files for CTS.
-namespace.art.permitted.paths += /system/framework
-namespace.art.permitted.paths += /apex/com.android.art/javalib
-namespace.art.asan.permitted.paths += /system/framework
-namespace.art.asan.permitted.paths += /apex/com.android.art/javalib
-# TODO(b/144533348): to allow symlinks pointing the libs under /system/lib
-# Note that this however does not open all libs in the system partition to
-# the APEX namespaces, because searching of the libs are NOT done in
-# /system/lib, but in /apex/<module>/lib directory.
-namespace.art.permitted.paths += /system/${LIB}
-namespace.art.asan.permitted.paths += /system/${LIB}
-namespace.art.links = system,neuralnetworks,adbd
-# Need allow_all_shared_libs because libart.so can dlopen oat files in
-# /system/framework and /data.
-# TODO(b/130340935): Use a dynamically created linker namespace similar to
-# classloader-namespace for oat files, and tighten this up.
-namespace.art.link.system.allow_all_shared_libs = true
-namespace.art.link.neuralnetworks.shared_libs = libneuralnetworks.so
-namespace.art.link.adbd.shared_libs = libadbconnection_client.so
-
-###############################################################################
-# "system" namespace
-#
-# Corresponds to the default namespace in /system/etc/ld.config.txt. Please keep
-# in sync with linker config files in system/core/rootdir/etc.
-###############################################################################
-namespace.system.isolated = true
-# Visible to allow links to be created at runtime, e.g. through
-# android_link_namespaces in libnativeloader.
-namespace.system.visible = true
-
-namespace.system.search.paths = /system/${LIB}
-namespace.system.asan.search.paths = /data/asan/system/${LIB}
-
-namespace.system.links = art,adbd
-namespace.system.link.art.shared_libs  = libandroidicu.so
-namespace.system.link.art.shared_libs += libdexfile_external.so
-namespace.system.link.art.shared_libs += libdexfiled_external.so
-# TODO(b/120786417 or b/134659294): libicuuc.so and libicui18n.so are kept for app compat.
-namespace.system.link.art.shared_libs += libicui18n.so
-namespace.system.link.art.shared_libs += libicuuc.so
-namespace.system.link.art.shared_libs += libnativebridge.so
-namespace.system.link.art.shared_libs += libnativehelper.so
-namespace.system.link.art.shared_libs += libnativeloader.so
-
-# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
-namespace.system.link.art.shared_libs += libpac.so
-
-namespace.system.link.adbd.shared_libs = libadb_pairing_auth.so
-namespace.system.link.adbd.shared_libs += libadb_pairing_connection.so
-namespace.system.link.adbd.shared_libs += libadb_pairing_server.so
-
-# /system/lib/libc.so, etc are symlinks to
-# /apex/com.android.runtime/lib/bionic/libc.so, etc. Add the path to the
-# permitted paths because linker uses realpath(3) to check the accessibility
-# of the lib. We could add this to search.paths instead but that makes the
-# resolution of bionic libs be dependent on the order of /system/lib and
-# /apex/.../lib/bionic in search.paths. If the latter is after the former,
-# then the latter is never tried because libc.so is always found in
-# /system/lib but fails to pass the accessibility test because of its realpath.
-# It's better to not depend on the ordering if possible.
-namespace.system.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
-namespace.system.asan.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
-
-# Note that we don't need to link the art namespace with conscrypt:
-# the runtime Java code and binaries do not explicitly load native libraries
-# from it.
-
-###############################################################################
-# "conscrypt" APEX namespace
-#
-# This namespace is for libraries within the conscrypt APEX.
-###############################################################################
-
-# Keep in sync with the "conscrypt" namespace in system/core/rootdir/etc/ld.config*.txt.
-namespace.conscrypt.isolated = true
-namespace.conscrypt.visible = true
-
-namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.asan.search.paths = /apex/com.android.conscrypt/${LIB}
-# TODO(b/144533348): to allow symlinks pointing the libs under /system/lib
-# Note that this however does not open all libs in the system partition to
-# the APEX namespaces, because searching of the libs are NOT done in
-# /system/lib, but in /apex/<module>/lib directory.
-namespace.conscrypt.permitted.paths = /system/${LIB}
-namespace.conscrypt.asan.permitted.paths = /system/${LIB}
-namespace.conscrypt.links = art,system
-namespace.conscrypt.link.art.shared_libs = libandroidio.so
-namespace.conscrypt.link.system.shared_libs  = libc.so
-namespace.conscrypt.link.system.shared_libs += libm.so
-namespace.conscrypt.link.system.shared_libs += libdl.so
-namespace.conscrypt.link.system.shared_libs += liblog.so
-
-###############################################################################
-# "neuralnetworks" APEX namespace
-#
-# This namespace is for libraries within the NNAPI APEX.
-###############################################################################
-namespace.neuralnetworks.isolated = true
-namespace.neuralnetworks.visible = true
-
-namespace.neuralnetworks.search.paths = /apex/com.android.neuralnetworks/${LIB}
-namespace.neuralnetworks.asan.search.paths = /apex/com.android.neuralnetworks/${LIB}
-# TODO(b/144533348): to allow symlinks pointing the libs under /system/lib
-# Note that this however does not open all libs in the system partition to
-# the APEX namespaces, because searching of the libs are NOT done in
-# /system/lib, but in /apex/<module>/lib directory.
-namespace.neuralnetworks.permitted.paths = /system/${LIB}
-namespace.neuralnetworks.asan.permitted.paths = /system/${LIB}
-namespace.neuralnetworks.links = system
-namespace.neuralnetworks.link.system.shared_libs  = libc.so
-namespace.neuralnetworks.link.system.shared_libs += libcgrouprc.so
-namespace.neuralnetworks.link.system.shared_libs += libdl.so
-namespace.neuralnetworks.link.system.shared_libs += liblog.so
-namespace.neuralnetworks.link.system.shared_libs += libm.so
-namespace.neuralnetworks.link.system.shared_libs += libnativewindow.so
-namespace.neuralnetworks.link.system.shared_libs += libneuralnetworks_packageinfo.so
-namespace.neuralnetworks.link.system.shared_libs += libsync.so
-namespace.neuralnetworks.link.system.shared_libs += libvndksupport.so
-
-###############################################################################
-# "adbd" APEX namespace
-#
-# This namespace is for libraries within the adbd APEX.
-###############################################################################
-
-namespace.adbd.isolated = true
-namespace.adbd.visible = true
-
-namespace.adbd.search.paths = /apex/com.android.adbd/${LIB}
-namespace.adbd.asan.search.paths = /apex/com.android.adbd/${LIB}
-namespace.adbd.links = system
-namespace.adbd.link.system.shared_libs  = libc.so
-namespace.adbd.link.system.shared_libs += libm.so
-namespace.adbd.link.system.shared_libs += libdl.so
-namespace.adbd.link.system.shared_libs += liblog.so
diff --git a/build/apex/linker.config.json b/build/apex/linker.config.json
new file mode 100644
index 0000000..f99b4b5
--- /dev/null
+++ b/build/apex/linker.config.json
@@ -0,0 +1,10 @@
+{
+  "permittedPaths": [
+    // JVMTI libraries used in ART testing are located under /data.
+    // TODO(b/171732668): Narrow this down.
+    "/data",
+
+    // For ART APEX primary boot image and odex files.
+    "/apex/com.android.art/javalib"
+  ]
+}
diff --git a/build/apex/manifest-art.json b/build/apex/manifest-art.json
index 59cbfac..7d31ade 100644
--- a/build/apex/manifest-art.json
+++ b/build/apex/manifest-art.json
@@ -1,4 +1,10 @@
 {
   "name": "com.android.art",
-  "version": 1
+  "version": 319999900,
+  "provideNativeLibs": [
+    "libjdwp.so"
+  ],
+  "requireNativeLibs": [
+    "libicu_jni.so"
+  ]
 }
diff --git a/build/apex/runtests.sh b/build/apex/runtests.sh
index 72bf74b..232daa3 100755
--- a/build/apex/runtests.sh
+++ b/build/apex/runtests.sh
@@ -34,23 +34,34 @@
 }
 
 function setup_die {
-  die "You need to source and lunch before you can use this script."
+  die "You need to run lunch, banchan, or tapas before you can use this script."
 }
 
 [[ -n "$ANDROID_BUILD_TOP" ]] || setup_die
 [[ -n "$ANDROID_PRODUCT_OUT" ]] || setup_die
 [[ -n "$ANDROID_HOST_OUT" ]] || setup_die
 
-flattened_apex_p=$($ANDROID_BUILD_TOP/build/soong/soong_ui.bash --dumpvar-mode TARGET_FLATTEN_APEX)\
+flattened_apex_p=$($ANDROID_BUILD_TOP/build/soong/soong_ui.bash \
+    --dumpvar-mode TARGET_FLATTEN_APEX) \
   || setup_die
 
-have_debugfs_p=false
+compressed_apex_p=$($ANDROID_BUILD_TOP/build/soong/soong_ui.bash \
+    --dumpvar-mode PRODUCT_COMPRESSED_APEX) \
+  || setup_die
+
+# Switch the build system to unbundled mode in the reduced manifest branch.
+if [ ! -d $ANDROID_BUILD_TOP/frameworks/base ]; then
+  export TARGET_BUILD_UNBUNDLED=true
+fi
+
+have_deapexer_p=false
 if $flattened_apex_p; then :; else
-  if [ ! -e "$ANDROID_HOST_OUT/bin/debugfs" ] ; then
-    say "Could not find debugfs, building now."
-    build/soong/soong_ui.bash --make-mode debugfs-host || die "Cannot build debugfs"
+  if [ ! -e "$ANDROID_HOST_OUT/bin/deapexer" -o ! -e "$ANDROID_HOST_OUT/bin/debugfs_static" ] ; then
+    say "Could not find deapexer and/or debugfs_static, building now."
+    build/soong/soong_ui.bash --make-mode deapexer debugfs_static-host || \
+      die "Cannot build deapexer and debugfs_static"
   fi
-  have_debugfs_p=true
+  have_deapexer_p=true
 fi
 
 # Fail early.
@@ -63,8 +74,9 @@
 
 function usage {
   cat <<EOF
-Usage: $0 [OPTION]
-Build (optional) and run tests on ART APEX package (on host).
+Usage: $0 [OPTION] [apexes...]
+Build (optional) and run tests on ART APEX package (on host). Defaults to all
+applicable APEXes if none is given on the command line.
 
   -B, --skip-build    skip the build step
   -l, --list-files    list the contents of the ext4 image (\`find\`-like style)
@@ -76,6 +88,8 @@
   exit
 }
 
+apex_modules=()
+
 while [[ $# -gt 0 ]]; do
   case "$1" in
     (-B|--skip-build)  build_apex_p=false;;
@@ -83,8 +97,9 @@
     (-t|--print-tree)  print_image_tree_p=true;;
     (-s|--print-sizes) print_file_sizes_p=true;;
     (-h|--help) usage;;
-    (*) die "Unknown option: '$1'
+    (-*) die "Unknown option: '$1'
 Try '$0 --help' for more information.";;
+    (*) apex_modules+=($1);;
   esac
   shift
 done
@@ -124,17 +139,18 @@
   exit_status=1
 }
 
-# Test all modules, if possible.
-
-apex_modules=(
-  "com.android.art.release"
-  "com.android.art.debug"
-  "com.android.art.testing"
-)
-if [[ "$HOST_PREFER_32_BIT" = true ]]; then
-  say "Skipping com.android.art.host, as \`HOST_PREFER_32_BIT\` equals \`true\`"
-else
-  apex_modules+=("com.android.art.host")
+if [ ${#apex_modules[@]} -eq 0 ]; then
+  # Test as many modules as possible.
+  apex_modules=(
+    "com.android.art"
+    "com.android.art.debug"
+    "com.android.art.testing"
+  )
+  if [[ "$HOST_PREFER_32_BIT" = true ]]; then
+    say "Skipping com.android.art.host, as \`HOST_PREFER_32_BIT\` equals \`true\`"
+  else
+    apex_modules+=("com.android.art.host")
+  fi
 fi
 
 # Build the APEX packages (optional).
@@ -169,15 +185,21 @@
       apex_path="$ANDROID_PRODUCT_OUT/system/apex/${apex_module}"
       art_apex_test_args="$art_apex_test_args --flattened"
     else
-      apex_path="$ANDROID_PRODUCT_OUT/system/apex/${apex_module}.apex"
+      # Note: The Testing ART APEX is never built as a Compressed APEX.
+      if $compressed_apex_p && [[ $apex_module != *.testing ]]; then
+        apex_path="$ANDROID_PRODUCT_OUT/system/apex/${apex_module}.capex"
+      else
+        apex_path="$ANDROID_PRODUCT_OUT/system/apex/${apex_module}.apex"
+      fi
     fi
-    if $have_debugfs_p; then
-      art_apex_test_args="$art_apex_test_args --debugfs $ANDROID_HOST_OUT/bin/debugfs"
+    if $have_deapexer_p; then
+      art_apex_test_args="$art_apex_test_args --deapexer $ANDROID_HOST_OUT/bin/deapexer"
+      art_apex_test_args="$art_apex_test_args --debugfs $ANDROID_HOST_OUT/bin/debugfs_static"
     fi
     case $apex_module in
-      (*.release) test_only_args="--flavor release";;
       (*.debug)   test_only_args="--flavor debug";;
       (*.testing) test_only_args="--flavor testing";;
+      (*)         test_only_args="--flavor release";;
     esac
   fi
   say "APEX package path: $apex_path"
diff --git a/build/apex/test_apex_manifest.json b/build/apex/test_apex_manifest.json
new file mode 100644
index 0000000..ee6dacb
--- /dev/null
+++ b/build/apex/test_apex_manifest.json
@@ -0,0 +1,10 @@
+{
+  "name": "com.android.art",
+  "version": 2147483647,
+  "provideNativeLibs": [
+    "libjdwp.so"
+  ],
+  "requireNativeLibs": [
+    "libicu_jni.so"
+  ]
+}
diff --git a/build/art.go b/build/art.go
index 5a09be0..a24da80 100644
--- a/build/art.go
+++ b/build/art.go
@@ -17,6 +17,8 @@
 import (
 	"fmt"
 	"log"
+	"path/filepath"
+	"strings"
 	"sync"
 
 	"github.com/google/blueprint/proptools"
@@ -24,6 +26,7 @@
 	"android/soong/android"
 	"android/soong/apex"
 	"android/soong/cc"
+	"android/soong/cc/config"
 )
 
 var supportedArches = []string{"arm", "arm64", "x86", "x86_64"}
@@ -49,9 +52,6 @@
 		cflags = append(cflags, "-DART_USE_TLAB=1")
 	}
 
-	imtSize := ctx.Config().GetenvWithDefault("ART_IMT_SIZE", "43")
-	cflags = append(cflags, "-DIMT_SIZE="+imtSize)
-
 	if ctx.Config().IsEnvTrue("ART_HEAP_POISONING") {
 		cflags = append(cflags, "-DART_HEAP_POISONING=1")
 		asflags = append(asflags, "-DART_HEAP_POISONING=1")
@@ -132,11 +132,6 @@
 	)
 
 	cflags = append(cflags, "-DART_BASE_ADDRESS="+ctx.Config().LibartImgDeviceBaseAddress())
-	if ctx.Config().IsEnvTrue("ART_TARGET_LINUX") {
-		cflags = append(cflags, "-DART_TARGET_LINUX")
-	} else {
-		cflags = append(cflags, "-DART_TARGET_ANDROID")
-	}
 	minDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_TARGET_MIN_BASE_ADDRESS_DELTA", "-0x1000000")
 	maxDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_TARGET_MAX_BASE_ADDRESS_DELTA", "0x1000000")
 	cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta)
@@ -169,6 +164,9 @@
 		cflags = append(cflags, "-DART_ENABLE_ADDRESS_SANITIZER=1")
 	}
 
+	clang_path := filepath.Join(config.ClangDefaultBase, ctx.Config().PrebuiltOS(), config.ClangDefaultVersion)
+	cflags = append(cflags, "-DART_CLANG_PATH=\""+clang_path+"\"")
+
 	return cflags
 }
 
@@ -204,6 +202,26 @@
 	ctx.AppendProperties(p)
 }
 
+// Hook that adds flags that are implicit for all cc_art_* modules.
+func addImplicitFlags(ctx android.LoadHookContext) {
+	type props struct {
+		Target struct {
+			Android struct {
+				Cflags []string
+			}
+		}
+	}
+
+	p := &props{}
+	if ctx.Config().IsEnvTrue("ART_TARGET_LINUX") {
+		p.Target.Android.Cflags = []string{"-DART_TARGET", "-DART_TARGET_LINUX"}
+	} else {
+		p.Target.Android.Cflags = []string{"-DART_TARGET", "-DART_TARGET_ANDROID"}
+	}
+
+	ctx.AppendProperties(p)
+}
+
 func debugDefaults(ctx android.LoadHookContext) {
 	type props struct {
 		Cflags []string
@@ -274,6 +292,38 @@
 	testMap[name] = tests
 }
 
+var testcasesContentKey = android.NewOnceKey("artTestcasesContent")
+
+func testcasesContent(config android.Config) map[string]string {
+	return config.Once(testcasesContentKey, func() interface{} {
+		return make(map[string]string)
+	}).(map[string]string)
+}
+
+// Binaries and libraries also need to be copied in the testcases directory for
+// running tests on host.  This method adds module to the list of needed files.
+// The 'key' is the file in testcases and 'value' is the path to copy it from.
+// The actual copy will be done in make since soong does not do installations.
+func addTestcasesFile(ctx android.InstallHookContext) {
+	if ctx.Os() != android.BuildOs || ctx.Module().IsSkipInstall() {
+		return
+	}
+
+	testcasesContent := testcasesContent(ctx.Config())
+
+	artTestMutex.Lock()
+	defer artTestMutex.Unlock()
+
+	src := ctx.SrcPath().String()
+	path := strings.Split(ctx.Path().ToMakePath().String(), "/")
+	// Keep last two parts of the install path (e.g. bin/dex2oat).
+	dst := strings.Join(path[len(path)-2:], "/")
+	if oldSrc, ok := testcasesContent[dst]; ok {
+		ctx.ModuleErrorf("Conflicting sources for %s: %s and %s", dst, oldSrc, src)
+	}
+	testcasesContent[dst] = src
+}
+
 var artTestMutex sync.Mutex
 
 func init() {
@@ -351,6 +401,7 @@
 
 func artGlobalDefaultsFactory() android.Module {
 	module := artDefaultsFactory()
+	android.AddLoadHook(module, addImplicitFlags)
 	android.AddLoadHook(module, globalDefaults)
 
 	return module
@@ -392,6 +443,8 @@
 
 	installCodegenCustomizer(module, staticAndSharedLibrary)
 
+	android.AddLoadHook(module, addImplicitFlags)
+	android.AddInstallHook(module, addTestcasesFile)
 	return module
 }
 
@@ -400,14 +453,17 @@
 
 	installCodegenCustomizer(module, staticLibrary)
 
+	android.AddLoadHook(module, addImplicitFlags)
 	return module
 }
 
 func artBinary() android.Module {
 	module := cc.BinaryFactory()
 
+	android.AddLoadHook(module, addImplicitFlags)
 	android.AddLoadHook(module, customLinker)
 	android.AddLoadHook(module, prefer32Bit)
+	android.AddInstallHook(module, addTestcasesFile)
 	return module
 }
 
@@ -416,6 +472,7 @@
 
 	installCodegenCustomizer(module, binary)
 
+	android.AddLoadHook(module, addImplicitFlags)
 	android.AddLoadHook(module, customLinker)
 	android.AddLoadHook(module, prefer32Bit)
 	android.AddInstallHook(module, testInstall)
@@ -427,6 +484,7 @@
 
 	installCodegenCustomizer(module, staticAndSharedLibrary)
 
+	android.AddLoadHook(module, addImplicitFlags)
 	android.AddLoadHook(module, prefer32Bit)
 	android.AddInstallHook(module, testInstall)
 	return module
diff --git a/build/boot/Android.bp b/build/boot/Android.bp
new file mode 100644
index 0000000..16b6d95
--- /dev/null
+++ b/build/boot/Android.bp
@@ -0,0 +1,78 @@
+// Copyright (C) 2021 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.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Encapsulate the contributions made by the com.android.art to the bootclasspath.
+bootclasspath_fragment {
+    name: "art-bootclasspath-fragment",
+    image_name: "art",
+    // Must match the ART_APEX_JARS set in build/make/core/envsetup.mk
+    contents: [
+        "core-oj",
+        "core-libart",
+        "okhttp",
+        "bouncycastle",
+        "apache-xml",
+    ],
+
+    api: {
+        stub_libs: [
+            // Stubs for the core-oj and core-libart. The other modules do not
+            // have any public API.
+            "art.module.public.api",
+        ],
+    },
+    core_platform_api: {
+        stub_libs: [
+            // Core platform (aka. module_lib) stubs for all the non-coverage contents.
+            "art.module.public.api.stubs.module_lib",
+        ],
+    },
+
+    // Additional properties to append when coverage is enabled, i.e. when
+    // EMMA_INSTRUMENT_FRAMEWORK=true
+    coverage: {
+        contents: [
+            "jacocoagent",
+        ],
+        api: {
+            stub_libs: [
+                // Stubs for the jacocoagent.
+                "jacoco-stubs",
+            ],
+        },
+    },
+    visibility: [
+        "//art/build/apex",
+        "//art/build/sdk",
+    ],
+    apex_available: [
+        "com.android.art",
+        "com.android.art.debug",
+    ],
+
+    hidden_api: {
+        blocked: ["hiddenapi/hiddenapi-blocked.txt"],
+        max_target_o_low_priority: ["hiddenapi/hiddenapi-max-target-o-low-priority.txt"],
+        unsupported_packages: ["hiddenapi/hiddenapi-unsupported-packages.txt"],
+    },
+}
diff --git a/build/boot/boot-image-profile.txt b/build/boot/boot-image-profile.txt
new file mode 100644
index 0000000..5111acf
--- /dev/null
+++ b/build/boot/boot-image-profile.txt
@@ -0,0 +1,12385 @@
+#
+# Copyright (C) 2017 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.
+#
+HSPLandroid/compat/Compatibility;->isChangeEnabled(J)Z+]Landroid/compat/Compatibility$BehaviorChangeDelegate;Landroid/app/AppCompatCallbacks;
+HSPLandroid/compat/Compatibility;->setBehaviorChangeDelegate(Landroid/compat/Compatibility$BehaviorChangeDelegate;)V
+HSPLandroid/system/ErrnoException;-><init>(Ljava/lang/String;I)V
+HSPLandroid/system/ErrnoException;->getMessage()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Llibcore/io/Os;missing_types
+HSPLandroid/system/ErrnoException;->rethrowAsIOException()Ljava/io/IOException;+]Ljava/io/IOException;Ljava/io/IOException;]Landroid/system/ErrnoException;Landroid/system/ErrnoException;
+HSPLandroid/system/GaiException;-><init>(Ljava/lang/String;I)V
+HSPLandroid/system/GaiException;->getMessage()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/GaiException;->rethrowAsUnknownHostException(Ljava/lang/String;)Ljava/net/UnknownHostException;+]Ljava/net/UnknownHostException;Ljava/net/UnknownHostException;
+HSPLandroid/system/Int32Ref;-><init>(I)V
+HSPLandroid/system/Os;->accept(Ljava/io/FileDescriptor;Ljava/net/InetSocketAddress;)Ljava/io/FileDescriptor;
+HSPLandroid/system/Os;->accept(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)Ljava/io/FileDescriptor;
+HSPLandroid/system/Os;->bind(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->capget(Landroid/system/StructCapUserHeader;)[Landroid/system/StructCapUserData;
+HSPLandroid/system/Os;->chmod(Ljava/lang/String;I)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->close(Ljava/io/FileDescriptor;)V+]Llibcore/io/Os;missing_types
+HSPLandroid/system/Os;->fcntlInt(Ljava/io/FileDescriptor;II)I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->fdatasync(Ljava/io/FileDescriptor;)V+]Llibcore/io/Os;missing_types
+HSPLandroid/system/Os;->fstat(Ljava/io/FileDescriptor;)Landroid/system/StructStat;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->getpeername(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;,Llibcore/io/BlockGuardOs;
+HSPLandroid/system/Os;->getpgid(I)I
+HSPLandroid/system/Os;->getpid()I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->gettid()I+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;,Llibcore/io/BlockGuardOs;
+HSPLandroid/system/Os;->getuid()I+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;,Llibcore/io/BlockGuardOs;
+HSPLandroid/system/Os;->getxattr(Ljava/lang/String;Ljava/lang/String;)[B+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->ioctlInt(Ljava/io/FileDescriptor;I)I+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->listen(Ljava/io/FileDescriptor;I)V
+HSPLandroid/system/Os;->lseek(Ljava/io/FileDescriptor;JI)J+]Llibcore/io/Os;missing_types
+HSPLandroid/system/Os;->lstat(Ljava/lang/String;)Landroid/system/StructStat;+]Llibcore/io/Os;missing_types
+HSPLandroid/system/Os;->mkdir(Ljava/lang/String;I)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;
+HSPLandroid/system/Os;->mmap(JJIILjava/io/FileDescriptor;J)J+]Llibcore/io/Os;missing_types
+HSPLandroid/system/Os;->open(Ljava/lang/String;II)Ljava/io/FileDescriptor;+]Llibcore/io/Os;missing_types
+HSPLandroid/system/Os;->poll([Landroid/system/StructPollfd;I)I+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->read(Ljava/io/FileDescriptor;[BII)I+]Llibcore/io/Os;missing_types
+HSPLandroid/system/Os;->rename(Ljava/lang/String;Ljava/lang/String;)V+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->setpgid(II)V
+HSPLandroid/system/Os;->setregid(II)V
+HSPLandroid/system/Os;->setreuid(II)V
+HSPLandroid/system/Os;->setsockoptInt(Ljava/io/FileDescriptor;III)V+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V+]Llibcore/io/Os;missing_types
+HSPLandroid/system/Os;->socket(III)Ljava/io/FileDescriptor;+]Llibcore/io/Os;missing_types
+HSPLandroid/system/Os;->socketpair(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Landroid/app/ActivityThread$AndroidOs;
+HSPLandroid/system/Os;->stat(Ljava/lang/String;)Landroid/system/StructStat;+]Llibcore/io/Os;missing_types
+HSPLandroid/system/Os;->statvfs(Ljava/lang/String;)Landroid/system/StructStatVfs;+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;,Llibcore/io/BlockGuardOs;
+HSPLandroid/system/Os;->sysconf(I)J+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;
+HSPLandroid/system/Os;->write(Ljava/io/FileDescriptor;[BII)I+]Llibcore/io/Os;missing_types
+HSPLandroid/system/OsConstants;->S_ISDIR(I)Z
+HSPLandroid/system/OsConstants;->errnoName(I)Ljava/lang/String;
+HSPLandroid/system/OsConstants;->gaiName(I)Ljava/lang/String;
+HSPLandroid/system/StructAddrinfo;-><init>()V
+HSPLandroid/system/StructCapUserData;-><init>(III)V
+HSPLandroid/system/StructCapUserHeader;-><init>(II)V
+HSPLandroid/system/StructIfaddrs;-><init>(Ljava/lang/String;ILjava/net/InetAddress;Ljava/net/InetAddress;Ljava/net/InetAddress;[B)V
+HSPLandroid/system/StructLinger;-><init>(II)V
+HSPLandroid/system/StructLinger;->isOn()Z
+HSPLandroid/system/StructPollfd;-><init>()V
+HSPLandroid/system/StructStat;-><init>(JJIJIIJJLandroid/system/StructTimespec;Landroid/system/StructTimespec;Landroid/system/StructTimespec;JJ)V
+HSPLandroid/system/StructStatVfs;-><init>(JJJJJJJJJJJ)V
+HSPLandroid/system/StructTimespec;-><init>(JJ)V
+HSPLandroid/system/StructTimespec;->equals(Ljava/lang/Object;)Z+]Ljava/lang/Object;Landroid/system/StructTimespec;
+HSPLandroid/system/StructTimeval;-><init>(JJ)V
+HSPLandroid/system/StructTimeval;->fromMillis(J)Landroid/system/StructTimeval;
+HSPLcom/android/okhttp/Address;-><init>(Ljava/lang/String;ILcom/android/okhttp/Dns;Ljavax/net/SocketFactory;Ljavax/net/ssl/SSLSocketFactory;Ljavax/net/ssl/HostnameVerifier;Lcom/android/okhttp/CertificatePinner;Lcom/android/okhttp/Authenticator;Ljava/net/Proxy;Ljava/util/List;Ljava/util/List;Ljava/net/ProxySelector;)V+]Lcom/android/okhttp/HttpUrl$Builder;Lcom/android/okhttp/HttpUrl$Builder;
+HSPLcom/android/okhttp/Address;->equals(Ljava/lang/Object;)Z+]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;]Ljava/lang/Object;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/Address;->getCertificatePinner()Lcom/android/okhttp/CertificatePinner;
+HSPLcom/android/okhttp/Address;->getConnectionSpecs()Ljava/util/List;
+HSPLcom/android/okhttp/Address;->getDns()Lcom/android/okhttp/Dns;
+HSPLcom/android/okhttp/Address;->getHostnameVerifier()Ljavax/net/ssl/HostnameVerifier;
+HSPLcom/android/okhttp/Address;->getProtocols()Ljava/util/List;
+HSPLcom/android/okhttp/Address;->getProxy()Ljava/net/Proxy;
+HSPLcom/android/okhttp/Address;->getProxySelector()Ljava/net/ProxySelector;
+HSPLcom/android/okhttp/Address;->getSocketFactory()Ljavax/net/SocketFactory;
+HSPLcom/android/okhttp/Address;->getSslSocketFactory()Ljavax/net/ssl/SSLSocketFactory;
+HSPLcom/android/okhttp/Address;->getUriHost()Ljava/lang/String;+]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/Address;->getUriPort()I+]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/Address;->hashCode()I+]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;]Ljava/lang/Object;missing_types]Ljava/util/List;missing_types]Ljava/net/Proxy;missing_types
+HSPLcom/android/okhttp/Address;->url()Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/CacheControl;-><init>(ZZIIZZZIIZZLjava/lang/String;)V
+HSPLcom/android/okhttp/CacheControl;->onlyIfCached()Z
+HSPLcom/android/okhttp/CacheControl;->parse(Lcom/android/okhttp/Headers;)Lcom/android/okhttp/CacheControl;+]Ljava/lang/String;missing_types]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/ConfigAwareConnectionPool$1;-><init>(Lcom/android/okhttp/ConfigAwareConnectionPool;)V
+HSPLcom/android/okhttp/ConfigAwareConnectionPool$1;->onNetworkConfigurationChanged()V
+HSPLcom/android/okhttp/ConfigAwareConnectionPool;->access$002(Lcom/android/okhttp/ConfigAwareConnectionPool;Lcom/android/okhttp/ConnectionPool;)Lcom/android/okhttp/ConnectionPool;
+HSPLcom/android/okhttp/ConfigAwareConnectionPool;->get()Lcom/android/okhttp/ConnectionPool;
+HSPLcom/android/okhttp/ConfigAwareConnectionPool;->getInstance()Lcom/android/okhttp/ConfigAwareConnectionPool;
+HSPLcom/android/okhttp/ConnectionPool$1;-><init>(Lcom/android/okhttp/ConnectionPool;)V
+HSPLcom/android/okhttp/ConnectionPool$1;->run()V+]Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/ConnectionPool;]Ljava/lang/Object;Lcom/android/okhttp/ConnectionPool;
+HSPLcom/android/okhttp/ConnectionPool;-><init>(IJ)V
+HSPLcom/android/okhttp/ConnectionPool;-><init>(IJLjava/util/concurrent/TimeUnit;)V+]Ljava/util/concurrent/TimeUnit;missing_types
+HSPLcom/android/okhttp/ConnectionPool;->cleanup(J)J+]Ljava/util/Deque;missing_types]Lcom/android/okhttp/internal/io/RealConnection;Lcom/android/okhttp/internal/io/RealConnection;]Ljava/util/Iterator;missing_types
+HSPLcom/android/okhttp/ConnectionPool;->connectionBecameIdle(Lcom/android/okhttp/internal/io/RealConnection;)Z+]Ljava/util/Deque;missing_types]Ljava/lang/Object;Lcom/android/okhttp/ConnectionPool;
+HSPLcom/android/okhttp/ConnectionPool;->get(Lcom/android/okhttp/Address;Lcom/android/okhttp/internal/http/StreamAllocation;)Lcom/android/okhttp/internal/io/RealConnection;+]Ljava/util/Deque;missing_types]Lcom/android/okhttp/internal/io/RealConnection;Lcom/android/okhttp/internal/io/RealConnection;]Ljava/util/List;missing_types]Lcom/android/okhttp/Address;Lcom/android/okhttp/Address;]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;]Ljava/util/Iterator;missing_types
+HSPLcom/android/okhttp/ConnectionPool;->pruneAndGetAllocationCount(Lcom/android/okhttp/internal/io/RealConnection;J)I+]Ljava/lang/ref/Reference;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/ConnectionPool;->put(Lcom/android/okhttp/internal/io/RealConnection;)V+]Ljava/util/Deque;missing_types]Ljava/util/concurrent/Executor;missing_types
+HSPLcom/android/okhttp/ConnectionSpec$Builder;-><init>(Lcom/android/okhttp/ConnectionSpec;)V
+HSPLcom/android/okhttp/ConnectionSpec$Builder;->access$000(Lcom/android/okhttp/ConnectionSpec$Builder;)Z
+HSPLcom/android/okhttp/ConnectionSpec$Builder;->access$100(Lcom/android/okhttp/ConnectionSpec$Builder;)[Ljava/lang/String;
+HSPLcom/android/okhttp/ConnectionSpec$Builder;->access$200(Lcom/android/okhttp/ConnectionSpec$Builder;)[Ljava/lang/String;
+HSPLcom/android/okhttp/ConnectionSpec$Builder;->access$300(Lcom/android/okhttp/ConnectionSpec$Builder;)Z
+HSPLcom/android/okhttp/ConnectionSpec$Builder;->build()Lcom/android/okhttp/ConnectionSpec;
+HSPLcom/android/okhttp/ConnectionSpec$Builder;->cipherSuites([Ljava/lang/String;)Lcom/android/okhttp/ConnectionSpec$Builder;+][Ljava/lang/String;[Ljava/lang/String;
+HSPLcom/android/okhttp/ConnectionSpec$Builder;->tlsVersions([Ljava/lang/String;)Lcom/android/okhttp/ConnectionSpec$Builder;+][Ljava/lang/String;[Ljava/lang/String;
+HSPLcom/android/okhttp/ConnectionSpec;-><init>(Lcom/android/okhttp/ConnectionSpec$Builder;)V
+HSPLcom/android/okhttp/ConnectionSpec;-><init>(Lcom/android/okhttp/ConnectionSpec$Builder;Lcom/android/okhttp/ConnectionSpec$1;)V
+HSPLcom/android/okhttp/ConnectionSpec;->access$400(Lcom/android/okhttp/ConnectionSpec;)Z
+HSPLcom/android/okhttp/ConnectionSpec;->access$500(Lcom/android/okhttp/ConnectionSpec;)[Ljava/lang/String;
+HSPLcom/android/okhttp/ConnectionSpec;->access$600(Lcom/android/okhttp/ConnectionSpec;)[Ljava/lang/String;
+HSPLcom/android/okhttp/ConnectionSpec;->access$700(Lcom/android/okhttp/ConnectionSpec;)Z
+HSPLcom/android/okhttp/ConnectionSpec;->apply(Ljavax/net/ssl/SSLSocket;Z)V+]Ljavax/net/ssl/SSLSocket;missing_types
+HSPLcom/android/okhttp/ConnectionSpec;->equals(Ljava/lang/Object;)Z
+HSPLcom/android/okhttp/ConnectionSpec;->hashCode()I
+HSPLcom/android/okhttp/ConnectionSpec;->isCompatible(Ljavax/net/ssl/SSLSocket;)Z
+HSPLcom/android/okhttp/ConnectionSpec;->supportedSpec(Ljavax/net/ssl/SSLSocket;Z)Lcom/android/okhttp/ConnectionSpec;+]Lcom/android/okhttp/ConnectionSpec$Builder;Lcom/android/okhttp/ConnectionSpec$Builder;]Ljavax/net/ssl/SSLSocket;missing_types
+HSPLcom/android/okhttp/ConnectionSpec;->supportsTlsExtensions()Z
+HSPLcom/android/okhttp/Dispatcher;-><init>()V
+HSPLcom/android/okhttp/Dns$1;->lookup(Ljava/lang/String;)Ljava/util/List;
+HSPLcom/android/okhttp/Handshake;-><init>(Ljava/lang/String;Ljava/util/List;Ljava/util/List;)V
+HSPLcom/android/okhttp/Handshake;->get(Ljavax/net/ssl/SSLSession;)Lcom/android/okhttp/Handshake;+]Ljavax/net/ssl/SSLSession;missing_types
+HSPLcom/android/okhttp/Headers$Builder;-><init>()V
+HSPLcom/android/okhttp/Headers$Builder;->access$000(Lcom/android/okhttp/Headers$Builder;)Ljava/util/List;
+HSPLcom/android/okhttp/Headers$Builder;->add(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Headers$Builder;->addLenient(Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;+]Ljava/lang/String;missing_types]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Headers$Builder;->addLenient(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;+]Ljava/lang/String;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/Headers$Builder;->build()Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/Headers$Builder;->checkNameAndValue(Ljava/lang/String;Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLcom/android/okhttp/Headers$Builder;->get(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/Headers$Builder;->removeAll(Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;+]Ljava/lang/String;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/Headers$Builder;->set(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Headers;-><init>(Lcom/android/okhttp/Headers$Builder;)V+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/Headers;-><init>(Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$1;)V
+HSPLcom/android/okhttp/Headers;->get(Ljava/lang/String;)Ljava/lang/String;
+HSPLcom/android/okhttp/Headers;->get([Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;missing_types
+HSPLcom/android/okhttp/Headers;->name(I)Ljava/lang/String;
+HSPLcom/android/okhttp/Headers;->newBuilder()Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Headers;->size()I
+HSPLcom/android/okhttp/Headers;->value(I)Ljava/lang/String;
+HSPLcom/android/okhttp/HttpHandler$CleartextURLFilter;->checkURLPermitted(Ljava/net/URL;)V+]Ljava/net/URL;missing_types]Llibcore/net/NetworkSecurityPolicy;missing_types
+HSPLcom/android/okhttp/HttpHandler;-><init>()V
+HSPLcom/android/okhttp/HttpHandler;->createHttpOkUrlFactory(Ljava/net/Proxy;)Lcom/android/okhttp/OkUrlFactory;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/HttpHandler;->newOkUrlFactory(Ljava/net/Proxy;)Lcom/android/okhttp/OkUrlFactory;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Lcom/android/okhttp/OkUrlFactory;Lcom/android/okhttp/OkUrlFactory;]Lcom/android/okhttp/ConfigAwareConnectionPool;Lcom/android/okhttp/ConfigAwareConnectionPool;
+HSPLcom/android/okhttp/HttpHandler;->openConnection(Ljava/net/URL;)Ljava/net/URLConnection;+]Lcom/android/okhttp/OkUrlFactory;Lcom/android/okhttp/OkUrlFactory;]Lcom/android/okhttp/HttpHandler;Lcom/android/okhttp/HttpsHandler;,Lcom/android/okhttp/HttpHandler;
+HSPLcom/android/okhttp/HttpUrl$Builder;-><init>()V+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/HttpUrl$Builder;->build()Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/HttpUrl$Builder;->canonicalizeHost(Ljava/lang/String;II)Ljava/lang/String;+]Ljava/lang/String;missing_types]Ljava/net/InetAddress;Ljava/net/Inet6Address;
+HSPLcom/android/okhttp/HttpUrl$Builder;->containsInvalidHostnameAsciiCodes(Ljava/lang/String;)Z
+HSPLcom/android/okhttp/HttpUrl$Builder;->domainToAscii(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;missing_types
+HSPLcom/android/okhttp/HttpUrl$Builder;->effectivePort()I
+HSPLcom/android/okhttp/HttpUrl$Builder;->encodedQuery(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+HSPLcom/android/okhttp/HttpUrl$Builder;->host(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+HSPLcom/android/okhttp/HttpUrl$Builder;->isDot(Ljava/lang/String;)Z+]Ljava/lang/String;missing_types
+HSPLcom/android/okhttp/HttpUrl$Builder;->isDotDot(Ljava/lang/String;)Z+]Ljava/lang/String;missing_types
+HSPLcom/android/okhttp/HttpUrl$Builder;->parse(Lcom/android/okhttp/HttpUrl;Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder$ParseResult;+]Ljava/lang/String;missing_types
+HSPLcom/android/okhttp/HttpUrl$Builder;->port(I)Lcom/android/okhttp/HttpUrl$Builder;
+HSPLcom/android/okhttp/HttpUrl$Builder;->portColonOffset(Ljava/lang/String;II)I
+HSPLcom/android/okhttp/HttpUrl$Builder;->push(Ljava/lang/String;IIZZ)V+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/HttpUrl$Builder;->reencodeForUri()Lcom/android/okhttp/HttpUrl$Builder;+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/HttpUrl$Builder;->resolvePath(Ljava/lang/String;II)V+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/HttpUrl$Builder;->scheme(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;+]Ljava/lang/String;missing_types
+HSPLcom/android/okhttp/HttpUrl$Builder;->schemeDelimiterOffset(Ljava/lang/String;II)I
+HSPLcom/android/okhttp/HttpUrl$Builder;->skipLeadingAsciiWhitespace(Ljava/lang/String;II)I
+HSPLcom/android/okhttp/HttpUrl$Builder;->skipTrailingAsciiWhitespace(Ljava/lang/String;II)I
+HSPLcom/android/okhttp/HttpUrl$Builder;->slashCount(Ljava/lang/String;II)I
+HSPLcom/android/okhttp/HttpUrl$Builder;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;missing_types]Lcom/android/okhttp/HttpUrl$Builder;Lcom/android/okhttp/HttpUrl$Builder;
+HSPLcom/android/okhttp/HttpUrl;-><init>(Lcom/android/okhttp/HttpUrl$Builder;)V+]Lcom/android/okhttp/HttpUrl$Builder;Lcom/android/okhttp/HttpUrl$Builder;
+HSPLcom/android/okhttp/HttpUrl;-><init>(Lcom/android/okhttp/HttpUrl$Builder;Lcom/android/okhttp/HttpUrl$1;)V
+HSPLcom/android/okhttp/HttpUrl;->access$200(Ljava/lang/String;IILjava/lang/String;)I
+HSPLcom/android/okhttp/HttpUrl;->canonicalize(Ljava/lang/String;IILjava/lang/String;ZZZZ)Ljava/lang/String;+]Ljava/lang/String;missing_types]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/HttpUrl;->canonicalize(Ljava/lang/String;Ljava/lang/String;ZZZZ)Ljava/lang/String;
+HSPLcom/android/okhttp/HttpUrl;->decodeHexDigit(C)I
+HSPLcom/android/okhttp/HttpUrl;->defaultPort(Ljava/lang/String;)I
+HSPLcom/android/okhttp/HttpUrl;->delimiterOffset(Ljava/lang/String;IILjava/lang/String;)I
+HSPLcom/android/okhttp/HttpUrl;->encodedFragment()Ljava/lang/String;
+HSPLcom/android/okhttp/HttpUrl;->encodedPassword()Ljava/lang/String;
+HSPLcom/android/okhttp/HttpUrl;->encodedPath()Ljava/lang/String;+]Ljava/lang/String;missing_types
+HSPLcom/android/okhttp/HttpUrl;->encodedPathSegments()Ljava/util/List;+]Ljava/lang/String;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/HttpUrl;->encodedQuery()Ljava/lang/String;+]Ljava/lang/String;missing_types
+HSPLcom/android/okhttp/HttpUrl;->encodedUsername()Ljava/lang/String;
+HSPLcom/android/okhttp/HttpUrl;->equals(Ljava/lang/Object;)Z
+HSPLcom/android/okhttp/HttpUrl;->getChecked(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl;+]Lcom/android/okhttp/HttpUrl$Builder$ParseResult;Lcom/android/okhttp/HttpUrl$Builder$ParseResult;]Lcom/android/okhttp/HttpUrl$Builder;Lcom/android/okhttp/HttpUrl$Builder;
+HSPLcom/android/okhttp/HttpUrl;->hashCode()I+]Ljava/lang/String;missing_types
+HSPLcom/android/okhttp/HttpUrl;->host()Ljava/lang/String;
+HSPLcom/android/okhttp/HttpUrl;->isHttps()Z
+HSPLcom/android/okhttp/HttpUrl;->namesAndValuesToQueryString(Ljava/lang/StringBuilder;Ljava/util/List;)V+]Ljava/lang/StringBuilder;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/HttpUrl;->newBuilder()Lcom/android/okhttp/HttpUrl$Builder;+]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;]Ljava/util/List;missing_types]Lcom/android/okhttp/HttpUrl$Builder;Lcom/android/okhttp/HttpUrl$Builder;
+HSPLcom/android/okhttp/HttpUrl;->pathSegmentsToString(Ljava/lang/StringBuilder;Ljava/util/List;)V+]Ljava/lang/StringBuilder;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/HttpUrl;->percentDecode(Lcom/android/okhttp/okio/Buffer;Ljava/lang/String;IIZ)V+]Ljava/lang/String;missing_types]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/HttpUrl;->percentDecode(Ljava/lang/String;IIZ)Ljava/lang/String;+]Ljava/lang/String;missing_types]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/HttpUrl;->percentDecode(Ljava/lang/String;Z)Ljava/lang/String;
+HSPLcom/android/okhttp/HttpUrl;->percentDecode(Ljava/util/List;Z)Ljava/util/List;+]Ljava/util/List;missing_types]Ljava/util/Iterator;missing_types
+HSPLcom/android/okhttp/HttpUrl;->port()I
+HSPLcom/android/okhttp/HttpUrl;->queryStringToNamesAndValues(Ljava/lang/String;)Ljava/util/List;+]Ljava/lang/String;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/HttpUrl;->scheme()Ljava/lang/String;
+HSPLcom/android/okhttp/HttpUrl;->uri()Ljava/net/URI;+]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;]Lcom/android/okhttp/HttpUrl$Builder;Lcom/android/okhttp/HttpUrl$Builder;
+HSPLcom/android/okhttp/HttpUrl;->url()Ljava/net/URL;
+HSPLcom/android/okhttp/HttpsHandler;-><init>()V
+HSPLcom/android/okhttp/HttpsHandler;->createHttpsOkUrlFactory(Ljava/net/Proxy;)Lcom/android/okhttp/OkUrlFactory;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Lcom/android/okhttp/OkUrlFactory;Lcom/android/okhttp/OkUrlFactory;
+HSPLcom/android/okhttp/HttpsHandler;->newOkUrlFactory(Ljava/net/Proxy;)Lcom/android/okhttp/OkUrlFactory;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Lcom/android/okhttp/OkUrlFactory;Lcom/android/okhttp/OkUrlFactory;]Lcom/android/okhttp/ConfigAwareConnectionPool;Lcom/android/okhttp/ConfigAwareConnectionPool;
+HSPLcom/android/okhttp/OkHttpClient$1;->addLenient(Lcom/android/okhttp/Headers$Builder;Ljava/lang/String;)V+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/OkHttpClient$1;->apply(Lcom/android/okhttp/ConnectionSpec;Ljavax/net/ssl/SSLSocket;Z)V+]Lcom/android/okhttp/ConnectionSpec;Lcom/android/okhttp/ConnectionSpec;
+HSPLcom/android/okhttp/OkHttpClient$1;->connectionBecameIdle(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/internal/io/RealConnection;)Z+]Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/ConnectionPool;
+HSPLcom/android/okhttp/OkHttpClient$1;->get(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/Address;Lcom/android/okhttp/internal/http/StreamAllocation;)Lcom/android/okhttp/internal/io/RealConnection;+]Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/ConnectionPool;
+HSPLcom/android/okhttp/OkHttpClient$1;->getHttpUrlChecked(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/OkHttpClient$1;->internalCache(Lcom/android/okhttp/OkHttpClient;)Lcom/android/okhttp/internal/InternalCache;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient$1;->put(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/internal/io/RealConnection;)V+]Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/ConnectionPool;
+HSPLcom/android/okhttp/OkHttpClient$1;->routeDatabase(Lcom/android/okhttp/ConnectionPool;)Lcom/android/okhttp/internal/RouteDatabase;
+HSPLcom/android/okhttp/OkHttpClient;-><init>()V
+HSPLcom/android/okhttp/OkHttpClient;-><init>(Lcom/android/okhttp/OkHttpClient;)V+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/OkHttpClient;->copyWithDefaults()Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient;->getAuthenticator()Lcom/android/okhttp/Authenticator;
+HSPLcom/android/okhttp/OkHttpClient;->getCertificatePinner()Lcom/android/okhttp/CertificatePinner;
+HSPLcom/android/okhttp/OkHttpClient;->getConnectTimeout()I
+HSPLcom/android/okhttp/OkHttpClient;->getConnectionPool()Lcom/android/okhttp/ConnectionPool;
+HSPLcom/android/okhttp/OkHttpClient;->getConnectionSpecs()Ljava/util/List;
+HSPLcom/android/okhttp/OkHttpClient;->getCookieHandler()Ljava/net/CookieHandler;
+HSPLcom/android/okhttp/OkHttpClient;->getDefaultSSLSocketFactory()Ljavax/net/ssl/SSLSocketFactory;
+HSPLcom/android/okhttp/OkHttpClient;->getDns()Lcom/android/okhttp/Dns;
+HSPLcom/android/okhttp/OkHttpClient;->getFollowRedirects()Z
+HSPLcom/android/okhttp/OkHttpClient;->getHostnameVerifier()Ljavax/net/ssl/HostnameVerifier;
+HSPLcom/android/okhttp/OkHttpClient;->getProtocols()Ljava/util/List;
+HSPLcom/android/okhttp/OkHttpClient;->getProxy()Ljava/net/Proxy;
+HSPLcom/android/okhttp/OkHttpClient;->getProxySelector()Ljava/net/ProxySelector;
+HSPLcom/android/okhttp/OkHttpClient;->getReadTimeout()I
+HSPLcom/android/okhttp/OkHttpClient;->getRetryOnConnectionFailure()Z
+HSPLcom/android/okhttp/OkHttpClient;->getSocketFactory()Ljavax/net/SocketFactory;
+HSPLcom/android/okhttp/OkHttpClient;->getSslSocketFactory()Ljavax/net/ssl/SSLSocketFactory;
+HSPLcom/android/okhttp/OkHttpClient;->getWriteTimeout()I
+HSPLcom/android/okhttp/OkHttpClient;->internalCache()Lcom/android/okhttp/internal/InternalCache;
+HSPLcom/android/okhttp/OkHttpClient;->setCertificatePinner(Lcom/android/okhttp/CertificatePinner;)Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient;->setConnectTimeout(JLjava/util/concurrent/TimeUnit;)V+]Ljava/util/concurrent/TimeUnit;missing_types
+HSPLcom/android/okhttp/OkHttpClient;->setConnectionPool(Lcom/android/okhttp/ConnectionPool;)Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient;->setConnectionSpecs(Ljava/util/List;)Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient;->setDns(Lcom/android/okhttp/Dns;)Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient;->setFollowRedirects(Z)V
+HSPLcom/android/okhttp/OkHttpClient;->setFollowSslRedirects(Z)Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient;->setHostnameVerifier(Ljavax/net/ssl/HostnameVerifier;)Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient;->setProtocols(Ljava/util/List;)Lcom/android/okhttp/OkHttpClient;+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/OkHttpClient;->setProxy(Ljava/net/Proxy;)Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient;->setReadTimeout(JLjava/util/concurrent/TimeUnit;)V+]Ljava/util/concurrent/TimeUnit;missing_types
+HSPLcom/android/okhttp/OkHttpClient;->setSocketFactory(Ljavax/net/SocketFactory;)Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient;->setSslSocketFactory(Ljavax/net/ssl/SSLSocketFactory;)Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkHttpClient;->setWriteTimeout(JLjava/util/concurrent/TimeUnit;)V+]Ljava/util/concurrent/TimeUnit;missing_types
+HSPLcom/android/okhttp/OkUrlFactories;->open(Lcom/android/okhttp/OkUrlFactory;Ljava/net/URL;Ljava/net/Proxy;)Ljava/net/HttpURLConnection;+]Lcom/android/okhttp/OkUrlFactory;Lcom/android/okhttp/OkUrlFactory;
+HSPLcom/android/okhttp/OkUrlFactories;->setUrlFilter(Lcom/android/okhttp/OkUrlFactory;Lcom/android/okhttp/internal/URLFilter;)V+]Lcom/android/okhttp/OkUrlFactory;Lcom/android/okhttp/OkUrlFactory;
+HSPLcom/android/okhttp/OkUrlFactory;-><init>(Lcom/android/okhttp/OkHttpClient;)V
+HSPLcom/android/okhttp/OkUrlFactory;->client()Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/OkUrlFactory;->open(Ljava/net/URL;)Ljava/net/HttpURLConnection;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Lcom/android/okhttp/OkUrlFactory;Lcom/android/okhttp/OkUrlFactory;
+HSPLcom/android/okhttp/OkUrlFactory;->open(Ljava/net/URL;Ljava/net/Proxy;)Ljava/net/HttpURLConnection;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Ljava/net/URL;missing_types
+HSPLcom/android/okhttp/OkUrlFactory;->setUrlFilter(Lcom/android/okhttp/internal/URLFilter;)V
+HSPLcom/android/okhttp/Protocol;->get(Ljava/lang/String;)Lcom/android/okhttp/Protocol;
+HSPLcom/android/okhttp/Protocol;->toString()Ljava/lang/String;
+HSPLcom/android/okhttp/Request$Builder;-><init>()V
+HSPLcom/android/okhttp/Request$Builder;-><init>(Lcom/android/okhttp/Request;)V+]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/Request$Builder;-><init>(Lcom/android/okhttp/Request;Lcom/android/okhttp/Request$1;)V
+HSPLcom/android/okhttp/Request$Builder;->access$000(Lcom/android/okhttp/Request$Builder;)Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/Request$Builder;->access$100(Lcom/android/okhttp/Request$Builder;)Ljava/lang/String;
+HSPLcom/android/okhttp/Request$Builder;->access$200(Lcom/android/okhttp/Request$Builder;)Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Request$Builder;->access$300(Lcom/android/okhttp/Request$Builder;)Lcom/android/okhttp/RequestBody;
+HSPLcom/android/okhttp/Request$Builder;->access$400(Lcom/android/okhttp/Request$Builder;)Ljava/lang/Object;
+HSPLcom/android/okhttp/Request$Builder;->addHeader(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Request$Builder;+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Request$Builder;->build()Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/Request$Builder;->header(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Request$Builder;+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Request$Builder;->method(Ljava/lang/String;Lcom/android/okhttp/RequestBody;)Lcom/android/okhttp/Request$Builder;
+HSPLcom/android/okhttp/Request$Builder;->url(Lcom/android/okhttp/HttpUrl;)Lcom/android/okhttp/Request$Builder;
+HSPLcom/android/okhttp/Request;-><init>(Lcom/android/okhttp/Request$Builder;)V+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Request;-><init>(Lcom/android/okhttp/Request$Builder;Lcom/android/okhttp/Request$1;)V
+HSPLcom/android/okhttp/Request;->access$1000(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/Request;->access$600(Lcom/android/okhttp/Request;)Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/Request;->access$700(Lcom/android/okhttp/Request;)Ljava/lang/String;
+HSPLcom/android/okhttp/Request;->access$800(Lcom/android/okhttp/Request;)Lcom/android/okhttp/RequestBody;
+HSPLcom/android/okhttp/Request;->access$900(Lcom/android/okhttp/Request;)Ljava/lang/Object;
+HSPLcom/android/okhttp/Request;->cacheControl()Lcom/android/okhttp/CacheControl;
+HSPLcom/android/okhttp/Request;->header(Ljava/lang/String;)Ljava/lang/String;+]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/Request;->headers()Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/Request;->httpUrl()Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/Request;->isHttps()Z+]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/Request;->method()Ljava/lang/String;
+HSPLcom/android/okhttp/Request;->newBuilder()Lcom/android/okhttp/Request$Builder;
+HSPLcom/android/okhttp/Request;->url()Ljava/net/URL;+]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/Response$Builder;-><init>()V
+HSPLcom/android/okhttp/Response$Builder;-><init>(Lcom/android/okhttp/Response;)V+]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/Response$Builder;-><init>(Lcom/android/okhttp/Response;Lcom/android/okhttp/Response$1;)V
+HSPLcom/android/okhttp/Response$Builder;->access$000(Lcom/android/okhttp/Response$Builder;)Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/Response$Builder;->access$100(Lcom/android/okhttp/Response$Builder;)Lcom/android/okhttp/Protocol;
+HSPLcom/android/okhttp/Response$Builder;->access$200(Lcom/android/okhttp/Response$Builder;)I
+HSPLcom/android/okhttp/Response$Builder;->access$300(Lcom/android/okhttp/Response$Builder;)Ljava/lang/String;
+HSPLcom/android/okhttp/Response$Builder;->access$400(Lcom/android/okhttp/Response$Builder;)Lcom/android/okhttp/Handshake;
+HSPLcom/android/okhttp/Response$Builder;->access$500(Lcom/android/okhttp/Response$Builder;)Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Response$Builder;->access$600(Lcom/android/okhttp/Response$Builder;)Lcom/android/okhttp/ResponseBody;
+HSPLcom/android/okhttp/Response$Builder;->access$700(Lcom/android/okhttp/Response$Builder;)Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/Response$Builder;->access$800(Lcom/android/okhttp/Response$Builder;)Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/Response$Builder;->access$900(Lcom/android/okhttp/Response$Builder;)Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/Response$Builder;->body(Lcom/android/okhttp/ResponseBody;)Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/Response$Builder;->build()Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/Response$Builder;->cacheResponse(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/Response$Builder;->checkSupportResponse(Ljava/lang/String;Lcom/android/okhttp/Response;)V
+HSPLcom/android/okhttp/Response$Builder;->code(I)Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/Response$Builder;->handshake(Lcom/android/okhttp/Handshake;)Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/Response$Builder;->header(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Response$Builder;+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Response$Builder;->headers(Lcom/android/okhttp/Headers;)Lcom/android/okhttp/Response$Builder;+]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/Response$Builder;->message(Ljava/lang/String;)Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/Response$Builder;->networkResponse(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/Response$Builder;->priorResponse(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/Response$Builder;->protocol(Lcom/android/okhttp/Protocol;)Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/Response$Builder;->request(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/Response;-><init>(Lcom/android/okhttp/Response$Builder;)V+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/Response;-><init>(Lcom/android/okhttp/Response$Builder;Lcom/android/okhttp/Response$1;)V
+HSPLcom/android/okhttp/Response;->access$1100(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/Response;->access$1200(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Protocol;
+HSPLcom/android/okhttp/Response;->access$1300(Lcom/android/okhttp/Response;)I
+HSPLcom/android/okhttp/Response;->access$1400(Lcom/android/okhttp/Response;)Ljava/lang/String;
+HSPLcom/android/okhttp/Response;->access$1500(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Handshake;
+HSPLcom/android/okhttp/Response;->access$1600(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/Response;->access$1700(Lcom/android/okhttp/Response;)Lcom/android/okhttp/ResponseBody;
+HSPLcom/android/okhttp/Response;->access$1800(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/Response;->access$1900(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/Response;->access$2000(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/Response;->body()Lcom/android/okhttp/ResponseBody;
+HSPLcom/android/okhttp/Response;->cacheResponse()Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/Response;->code()I
+HSPLcom/android/okhttp/Response;->header(Ljava/lang/String;)Ljava/lang/String;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/Response;->header(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/Response;->headers()Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/Response;->message()Ljava/lang/String;
+HSPLcom/android/okhttp/Response;->networkResponse()Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/Response;->newBuilder()Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/Response;->protocol()Lcom/android/okhttp/Protocol;
+HSPLcom/android/okhttp/Response;->request()Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/ResponseBody;-><init>()V
+HSPLcom/android/okhttp/ResponseBody;->byteStream()Ljava/io/InputStream;+]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Lcom/android/okhttp/ResponseBody;Lcom/android/okhttp/internal/http/RealResponseBody;,Lcom/android/okhttp/Cache$CacheResponseBody;
+HSPLcom/android/okhttp/Route;-><init>(Lcom/android/okhttp/Address;Ljava/net/Proxy;Ljava/net/InetSocketAddress;)V
+HSPLcom/android/okhttp/Route;->equals(Ljava/lang/Object;)Z+]Lcom/android/okhttp/Address;Lcom/android/okhttp/Address;]Ljava/net/Proxy;missing_types]Ljava/net/InetSocketAddress;missing_types
+HSPLcom/android/okhttp/Route;->getAddress()Lcom/android/okhttp/Address;
+HSPLcom/android/okhttp/Route;->getProxy()Ljava/net/Proxy;
+HSPLcom/android/okhttp/Route;->getSocketAddress()Ljava/net/InetSocketAddress;
+HSPLcom/android/okhttp/Route;->hashCode()I+]Lcom/android/okhttp/Address;Lcom/android/okhttp/Address;]Ljava/net/Proxy;missing_types]Ljava/net/InetSocketAddress;missing_types
+HSPLcom/android/okhttp/Route;->requiresTunnel()Z+]Ljava/net/Proxy;missing_types
+HSPLcom/android/okhttp/internal/ConnectionSpecSelector;-><init>(Ljava/util/List;)V
+HSPLcom/android/okhttp/internal/ConnectionSpecSelector;->configureSecureSocket(Ljavax/net/ssl/SSLSocket;)Lcom/android/okhttp/ConnectionSpec;+]Lcom/android/okhttp/internal/Internal;Lcom/android/okhttp/OkHttpClient$1;]Ljava/util/List;missing_types]Lcom/android/okhttp/ConnectionSpec;Lcom/android/okhttp/ConnectionSpec;
+HSPLcom/android/okhttp/internal/ConnectionSpecSelector;->connectionFailed(Ljava/io/IOException;)Z
+HSPLcom/android/okhttp/internal/ConnectionSpecSelector;->isFallbackPossible(Ljavax/net/ssl/SSLSocket;)Z+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/internal/OptionalMethod;->getMethod(Ljava/lang/Class;)Ljava/lang/reflect/Method;
+HSPLcom/android/okhttp/internal/OptionalMethod;->getPublicMethod(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;+]Ljava/lang/reflect/Method;missing_types]Ljava/lang/Class;missing_types
+HSPLcom/android/okhttp/internal/OptionalMethod;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/reflect/Method;missing_types
+HSPLcom/android/okhttp/internal/OptionalMethod;->invokeOptional(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/reflect/Method;missing_types
+HSPLcom/android/okhttp/internal/OptionalMethod;->invokeOptionalWithoutCheckedException(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+]Lcom/android/okhttp/internal/OptionalMethod;Lcom/android/okhttp/internal/OptionalMethod;
+HSPLcom/android/okhttp/internal/OptionalMethod;->invokeWithoutCheckedException(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+]Lcom/android/okhttp/internal/OptionalMethod;Lcom/android/okhttp/internal/OptionalMethod;
+HSPLcom/android/okhttp/internal/OptionalMethod;->isSupported(Ljava/lang/Object;)Z
+HSPLcom/android/okhttp/internal/Platform;->afterHandshake(Ljavax/net/ssl/SSLSocket;)V
+HSPLcom/android/okhttp/internal/Platform;->concatLengthPrefixed(Ljava/util/List;)[B+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Ljava/util/List;Ljava/util/Collections$UnmodifiableRandomAccessList;]Lcom/android/okhttp/Protocol;Lcom/android/okhttp/Protocol;
+HSPLcom/android/okhttp/internal/Platform;->configureTlsExtensions(Ljavax/net/ssl/SSLSocket;Ljava/lang/String;Ljava/util/List;)V+]Ljavax/net/ssl/SSLParameters;missing_types]Lcom/android/okhttp/internal/OptionalMethod;Lcom/android/okhttp/internal/OptionalMethod;]Ljavax/net/ssl/SSLSocket;missing_types
+HSPLcom/android/okhttp/internal/Platform;->connectSocket(Ljava/net/Socket;Ljava/net/InetSocketAddress;I)V+]Ljava/net/Socket;missing_types
+HSPLcom/android/okhttp/internal/Platform;->get()Lcom/android/okhttp/internal/Platform;+]Ljava/util/concurrent/atomic/AtomicReference;Ljava/util/concurrent/atomic/AtomicReference;
+HSPLcom/android/okhttp/internal/Platform;->getProtocolIds(Ljava/util/List;)[Ljava/lang/String;
+HSPLcom/android/okhttp/internal/Platform;->getSelectedProtocol(Ljavax/net/ssl/SSLSocket;)Ljava/lang/String;+]Ljavax/net/ssl/SSLSocket;missing_types
+HSPLcom/android/okhttp/internal/Platform;->isPlatformSocket(Ljavax/net/ssl/SSLSocket;)Z
+HSPLcom/android/okhttp/internal/RouteDatabase;-><init>()V
+HSPLcom/android/okhttp/internal/RouteDatabase;->connected(Lcom/android/okhttp/Route;)V+]Ljava/util/Set;missing_types
+HSPLcom/android/okhttp/internal/RouteDatabase;->failed(Lcom/android/okhttp/Route;)V+]Ljava/util/Set;Ljava/util/LinkedHashSet;
+HSPLcom/android/okhttp/internal/RouteDatabase;->shouldPostpone(Lcom/android/okhttp/Route;)Z+]Ljava/util/Set;missing_types
+HSPLcom/android/okhttp/internal/Util$1;-><init>(Ljava/lang/String;Z)V
+HSPLcom/android/okhttp/internal/Util$1;->newThread(Ljava/lang/Runnable;)Ljava/lang/Thread;+]Ljava/lang/Thread;Ljava/lang/Thread;
+HSPLcom/android/okhttp/internal/Util;->checkOffsetAndCount(JJJ)V
+HSPLcom/android/okhttp/internal/Util;->closeQuietly(Ljava/io/Closeable;)V
+HSPLcom/android/okhttp/internal/Util;->closeQuietly(Ljava/net/Socket;)V+]Ljava/net/Socket;Ljava/net/Socket;,Lcom/android/org/conscrypt/Java8EngineSocket;
+HSPLcom/android/okhttp/internal/Util;->discard(Lcom/android/okhttp/okio/Source;ILjava/util/concurrent/TimeUnit;)Z
+HSPLcom/android/okhttp/internal/Util;->equal(Ljava/lang/Object;Ljava/lang/Object;)Z
+HSPLcom/android/okhttp/internal/Util;->hostHeader(Lcom/android/okhttp/HttpUrl;Z)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/internal/Util;->immutableList(Ljava/util/List;)Ljava/util/List;
+HSPLcom/android/okhttp/internal/Util;->immutableList([Ljava/lang/Object;)Ljava/util/List;
+HSPLcom/android/okhttp/internal/Util;->skipAll(Lcom/android/okhttp/okio/Source;ILjava/util/concurrent/TimeUnit;)Z+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Timeout;Lcom/android/okhttp/okio/ForwardingTimeout;]Lcom/android/okhttp/okio/Source;Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;,Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;
+HSPLcom/android/okhttp/internal/Util;->threadFactory(Ljava/lang/String;Z)Ljava/util/concurrent/ThreadFactory;
+HSPLcom/android/okhttp/internal/Util;->toHumanReadableAscii(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLcom/android/okhttp/internal/http/CacheStrategy$Factory;-><init>(JLcom/android/okhttp/Request;Lcom/android/okhttp/Response;)V+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Ljava/lang/String;missing_types]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/internal/http/CacheStrategy$Factory;->get()Lcom/android/okhttp/internal/http/CacheStrategy;+]Lcom/android/okhttp/CacheControl;Lcom/android/okhttp/CacheControl;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/internal/http/CacheStrategy$Factory;->getCandidate()Lcom/android/okhttp/internal/http/CacheStrategy;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/CacheControl;Lcom/android/okhttp/CacheControl;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Lcom/android/okhttp/Response$Builder;Lcom/android/okhttp/Response$Builder;]Lcom/android/okhttp/Request$Builder;Lcom/android/okhttp/Request$Builder;
+HSPLcom/android/okhttp/internal/http/CacheStrategy;-><init>(Lcom/android/okhttp/Request;Lcom/android/okhttp/Response;)V
+HSPLcom/android/okhttp/internal/http/CacheStrategy;-><init>(Lcom/android/okhttp/Request;Lcom/android/okhttp/Response;Lcom/android/okhttp/internal/http/CacheStrategy$1;)V
+HSPLcom/android/okhttp/internal/http/HeaderParser;->skipUntil(Ljava/lang/String;ILjava/lang/String;)I
+HSPLcom/android/okhttp/internal/http/HeaderParser;->skipWhitespace(Ljava/lang/String;I)I
+HSPLcom/android/okhttp/internal/http/Http1xStream$AbstractSource;-><init>(Lcom/android/okhttp/internal/http/Http1xStream;)V+]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/internal/http/Http1xStream$AbstractSource;-><init>(Lcom/android/okhttp/internal/http/Http1xStream;Lcom/android/okhttp/internal/http/Http1xStream$1;)V
+HSPLcom/android/okhttp/internal/http/Http1xStream$AbstractSource;->endOfInput()V+]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;
+HSPLcom/android/okhttp/internal/http/Http1xStream$AbstractSource;->timeout()Lcom/android/okhttp/okio/Timeout;
+HSPLcom/android/okhttp/internal/http/Http1xStream$AbstractSource;->unexpectedEndOfInput()V
+HSPLcom/android/okhttp/internal/http/Http1xStream$ChunkedSink;-><init>(Lcom/android/okhttp/internal/http/Http1xStream;)V+]Lcom/android/okhttp/okio/BufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/internal/http/Http1xStream$ChunkedSink;-><init>(Lcom/android/okhttp/internal/http/Http1xStream;Lcom/android/okhttp/internal/http/Http1xStream$1;)V
+HSPLcom/android/okhttp/internal/http/Http1xStream$ChunkedSink;->close()V
+HSPLcom/android/okhttp/internal/http/Http1xStream$ChunkedSink;->flush()V
+HSPLcom/android/okhttp/internal/http/Http1xStream$ChunkedSink;->write(Lcom/android/okhttp/okio/Buffer;J)V+]Lcom/android/okhttp/okio/BufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;-><init>(Lcom/android/okhttp/internal/http/Http1xStream;Lcom/android/okhttp/internal/http/HttpEngine;)V
+HSPLcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;->close()V+]Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;
+HSPLcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;->read(Lcom/android/okhttp/okio/Buffer;J)J+]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;
+HSPLcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;->readChunkSize()V+]Ljava/lang/String;missing_types]Lcom/android/okhttp/internal/http/Http1xStream;Lcom/android/okhttp/internal/http/Http1xStream;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;]Ljava/lang/NumberFormatException;Ljava/lang/NumberFormatException;
+HSPLcom/android/okhttp/internal/http/Http1xStream$FixedLengthSink;-><init>(Lcom/android/okhttp/internal/http/Http1xStream;J)V+]Lcom/android/okhttp/okio/BufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/internal/http/Http1xStream$FixedLengthSink;-><init>(Lcom/android/okhttp/internal/http/Http1xStream;JLcom/android/okhttp/internal/http/Http1xStream$1;)V
+HSPLcom/android/okhttp/internal/http/Http1xStream$FixedLengthSink;->close()V
+HSPLcom/android/okhttp/internal/http/Http1xStream$FixedLengthSink;->flush()V+]Lcom/android/okhttp/okio/BufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/internal/http/Http1xStream$FixedLengthSink;->write(Lcom/android/okhttp/okio/Buffer;J)V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/BufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;-><init>(Lcom/android/okhttp/internal/http/Http1xStream;J)V+]Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;
+HSPLcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;->close()V+]Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;
+HSPLcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;->read(Lcom/android/okhttp/okio/Buffer;J)J+]Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/internal/http/Http1xStream;-><init>(Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/BufferedSink;)V
+HSPLcom/android/okhttp/internal/http/Http1xStream;->access$300(Lcom/android/okhttp/internal/http/Http1xStream;)Lcom/android/okhttp/okio/BufferedSink;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->access$400(Lcom/android/okhttp/internal/http/Http1xStream;Lcom/android/okhttp/okio/ForwardingTimeout;)V
+HSPLcom/android/okhttp/internal/http/Http1xStream;->access$500(Lcom/android/okhttp/internal/http/Http1xStream;)I
+HSPLcom/android/okhttp/internal/http/Http1xStream;->access$502(Lcom/android/okhttp/internal/http/Http1xStream;I)I
+HSPLcom/android/okhttp/internal/http/Http1xStream;->access$600(Lcom/android/okhttp/internal/http/Http1xStream;)Lcom/android/okhttp/okio/BufferedSource;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->access$700(Lcom/android/okhttp/internal/http/Http1xStream;)Lcom/android/okhttp/internal/http/StreamAllocation;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->cancel()V
+HSPLcom/android/okhttp/internal/http/Http1xStream;->createRequestBody(Lcom/android/okhttp/Request;J)Lcom/android/okhttp/okio/Sink;+]Ljava/lang/String;Ljava/lang/String;]Lcom/android/okhttp/internal/http/Http1xStream;Lcom/android/okhttp/internal/http/Http1xStream;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->detachTimeout(Lcom/android/okhttp/okio/ForwardingTimeout;)V+]Lcom/android/okhttp/okio/Timeout;Lcom/android/okhttp/okio/Okio$3;]Lcom/android/okhttp/okio/ForwardingTimeout;Lcom/android/okhttp/okio/ForwardingTimeout;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->finishRequest()V+]Lcom/android/okhttp/okio/BufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->getTransferStream(Lcom/android/okhttp/Response;)Lcom/android/okhttp/okio/Source;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Ljava/lang/String;missing_types]Lcom/android/okhttp/internal/http/Http1xStream;Lcom/android/okhttp/internal/http/Http1xStream;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->newChunkedSink()Lcom/android/okhttp/okio/Sink;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->newChunkedSource(Lcom/android/okhttp/internal/http/HttpEngine;)Lcom/android/okhttp/okio/Source;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->newFixedLengthSink(J)Lcom/android/okhttp/okio/Sink;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->newFixedLengthSource(J)Lcom/android/okhttp/okio/Source;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->openResponseBody(Lcom/android/okhttp/Response;)Lcom/android/okhttp/ResponseBody;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->readHeaders()Lcom/android/okhttp/Headers;+]Lcom/android/okhttp/internal/Internal;Lcom/android/okhttp/OkHttpClient$1;]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->readResponse()Lcom/android/okhttp/Response$Builder;+]Lcom/android/okhttp/internal/http/Http1xStream;Lcom/android/okhttp/internal/http/Http1xStream;]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Lcom/android/okhttp/Response$Builder;Lcom/android/okhttp/Response$Builder;]Ljava/lang/StringBuilder;missing_types]Ljava/io/IOException;missing_types
+HSPLcom/android/okhttp/internal/http/Http1xStream;->readResponseHeaders()Lcom/android/okhttp/Response$Builder;+]Lcom/android/okhttp/internal/http/Http1xStream;Lcom/android/okhttp/internal/http/Http1xStream;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->setHttpEngine(Lcom/android/okhttp/internal/http/HttpEngine;)V
+HSPLcom/android/okhttp/internal/http/Http1xStream;->writeRequest(Lcom/android/okhttp/Headers;Ljava/lang/String;)V+]Lcom/android/okhttp/okio/BufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->writeRequestBody(Lcom/android/okhttp/internal/http/RetryableSink;)V+]Lcom/android/okhttp/internal/http/RetryableSink;Lcom/android/okhttp/internal/http/RetryableSink;
+HSPLcom/android/okhttp/internal/http/Http1xStream;->writeRequestHeaders(Lcom/android/okhttp/Request;)V+]Lcom/android/okhttp/Route;Lcom/android/okhttp/Route;]Lcom/android/okhttp/internal/http/Http1xStream;Lcom/android/okhttp/internal/http/Http1xStream;]Lcom/android/okhttp/Connection;Lcom/android/okhttp/internal/io/RealConnection;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Ljava/net/Proxy;missing_types
+HSPLcom/android/okhttp/internal/http/HttpEngine;-><init>(Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/Request;ZZZLcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/RetryableSink;Lcom/android/okhttp/Response;)V+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->cacheWritingResponse(Lcom/android/okhttp/internal/http/CacheRequest;Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/internal/http/CacheRequest;Lcom/android/okhttp/Cache$CacheRequestImpl;]Lcom/android/okhttp/ResponseBody;Lcom/android/okhttp/internal/http/RealResponseBody;]Lcom/android/okhttp/Response$Builder;Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->cancel()V+]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->close()Lcom/android/okhttp/internal/http/StreamAllocation;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->connect()Lcom/android/okhttp/internal/http/HttpStream;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->createAddress(Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/Request;)Lcom/android/okhttp/Address;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->followUpRequest()Lcom/android/okhttp/Request;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/Route;Lcom/android/okhttp/Route;]Lcom/android/okhttp/Connection;Lcom/android/okhttp/internal/io/RealConnection;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;]Lcom/android/okhttp/Request$Builder;Lcom/android/okhttp/Request$Builder;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->getBufferedRequestBody()Lcom/android/okhttp/okio/BufferedSink;+]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->getConnection()Lcom/android/okhttp/Connection;+]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->getRequest()Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->getRequestBody()Lcom/android/okhttp/okio/Sink;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->getResponse()Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->hasBody(Lcom/android/okhttp/Response;)Z+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Ljava/lang/String;Ljava/lang/String;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->hasResponse()Z
+HSPLcom/android/okhttp/internal/http/HttpEngine;->maybeCache()V+]Lcom/android/okhttp/internal/Internal;Lcom/android/okhttp/OkHttpClient$1;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Lcom/android/okhttp/internal/InternalCache;Lcom/android/okhttp/Cache$1;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->networkRequest(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Request;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Lcom/android/okhttp/Request$Builder;Lcom/android/okhttp/Request$Builder;]Ljava/net/CookieHandler;missing_types
+HSPLcom/android/okhttp/internal/http/HttpEngine;->permitsRequestBody(Lcom/android/okhttp/Request;)Z+]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->readNetworkResponse()Lcom/android/okhttp/Response;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Ljava/lang/String;missing_types]Lcom/android/okhttp/internal/io/RealConnection;Lcom/android/okhttp/internal/io/RealConnection;]Lcom/android/okhttp/internal/http/HttpStream;Lcom/android/okhttp/internal/http/Http1xStream;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;]Lcom/android/okhttp/Response$Builder;Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->readResponse()V+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/BufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;]Lcom/android/okhttp/internal/http/HttpStream;Lcom/android/okhttp/internal/http/Http1xStream;]Lcom/android/okhttp/Response$Builder;Lcom/android/okhttp/Response$Builder;]Lcom/android/okhttp/internal/http/RetryableSink;Lcom/android/okhttp/internal/http/RetryableSink;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Lcom/android/okhttp/Request$Builder;Lcom/android/okhttp/Request$Builder;]Lcom/android/okhttp/okio/Sink;Lcom/android/okhttp/internal/http/RetryableSink;]Lcom/android/okhttp/internal/Internal;Lcom/android/okhttp/OkHttpClient$1;]Lcom/android/okhttp/ResponseBody;Lcom/android/okhttp/internal/http/RealResponseBody;]Lcom/android/okhttp/internal/InternalCache;Lcom/android/okhttp/Cache$1;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->receiveHeaders(Lcom/android/okhttp/Headers;)V+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Ljava/net/CookieHandler;missing_types]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->recover(Lcom/android/okhttp/internal/http/RouteException;)Lcom/android/okhttp/internal/http/HttpEngine;+]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->recover(Ljava/io/IOException;)Lcom/android/okhttp/internal/http/HttpEngine;+]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->recover(Ljava/io/IOException;Lcom/android/okhttp/okio/Sink;)Lcom/android/okhttp/internal/http/HttpEngine;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->releaseStreamAllocation()V+]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->sendRequest()V+]Lcom/android/okhttp/internal/Internal;Lcom/android/okhttp/OkHttpClient$1;]Lcom/android/okhttp/internal/http/CacheStrategy$Factory;Lcom/android/okhttp/internal/http/CacheStrategy$Factory;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/internal/http/HttpStream;Lcom/android/okhttp/internal/http/Http1xStream;]Lcom/android/okhttp/internal/InternalCache;Lcom/android/okhttp/Cache$1;]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/Response$Builder;Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->stripBody(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/Response$Builder;Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->unzip(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Ljava/lang/String;missing_types]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;]Lcom/android/okhttp/ResponseBody;Lcom/android/okhttp/internal/http/RealResponseBody;]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;]Lcom/android/okhttp/Response$Builder;Lcom/android/okhttp/Response$Builder;
+HSPLcom/android/okhttp/internal/http/HttpEngine;->writingRequestHeaders()V
+HSPLcom/android/okhttp/internal/http/HttpMethod;->permitsRequestBody(Ljava/lang/String;)Z
+HSPLcom/android/okhttp/internal/http/HttpMethod;->requiresRequestBody(Ljava/lang/String;)Z
+HSPLcom/android/okhttp/internal/http/OkHeaders$1;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Lcom/android/okhttp/internal/http/OkHeaders$1;Lcom/android/okhttp/internal/http/OkHeaders$1;
+HSPLcom/android/okhttp/internal/http/OkHeaders$1;->compare(Ljava/lang/String;Ljava/lang/String;)I+]Ljava/util/Comparator;missing_types
+HSPLcom/android/okhttp/internal/http/OkHeaders;->contentLength(Lcom/android/okhttp/Headers;)J+]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/internal/http/OkHeaders;->contentLength(Lcom/android/okhttp/Request;)J+]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/internal/http/OkHeaders;->contentLength(Lcom/android/okhttp/Response;)J+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/internal/http/OkHeaders;->stringToLong(Ljava/lang/String;)J
+HSPLcom/android/okhttp/internal/http/OkHeaders;->toMultimap(Lcom/android/okhttp/Headers;Ljava/lang/String;)Ljava/util/Map;+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/Map;Ljava/util/TreeMap;]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/internal/http/RealResponseBody;-><init>(Lcom/android/okhttp/Headers;Lcom/android/okhttp/okio/BufferedSource;)V
+HSPLcom/android/okhttp/internal/http/RealResponseBody;->source()Lcom/android/okhttp/okio/BufferedSource;
+HSPLcom/android/okhttp/internal/http/RequestLine;->get(Lcom/android/okhttp/Request;Ljava/net/Proxy$Type;)Ljava/lang/String;+]Ljava/lang/StringBuilder;missing_types]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/internal/http/RequestLine;->includeAuthorityInRequestLine(Lcom/android/okhttp/Request;Ljava/net/Proxy$Type;)Z+]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;
+HSPLcom/android/okhttp/internal/http/RequestLine;->requestPath(Lcom/android/okhttp/HttpUrl;)Ljava/lang/String;+]Ljava/lang/StringBuilder;missing_types]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;
+HSPLcom/android/okhttp/internal/http/RetryableSink;-><init>()V
+HSPLcom/android/okhttp/internal/http/RetryableSink;-><init>(I)V
+HSPLcom/android/okhttp/internal/http/RetryableSink;->close()V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/internal/http/RetryableSink;->contentLength()J+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/internal/http/RetryableSink;->flush()V
+HSPLcom/android/okhttp/internal/http/RetryableSink;->write(Lcom/android/okhttp/okio/Buffer;J)V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/internal/http/RetryableSink;->writeToSocket(Lcom/android/okhttp/okio/Sink;)V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Sink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/internal/http/RouteException;-><init>(Ljava/io/IOException;)V
+HSPLcom/android/okhttp/internal/http/RouteException;->getLastConnectException()Ljava/io/IOException;
+HSPLcom/android/okhttp/internal/http/RouteSelector;-><init>(Lcom/android/okhttp/Address;Lcom/android/okhttp/internal/RouteDatabase;)V+]Lcom/android/okhttp/Address;Lcom/android/okhttp/Address;
+HSPLcom/android/okhttp/internal/http/RouteSelector;->connectFailed(Lcom/android/okhttp/Route;Ljava/io/IOException;)V+]Lcom/android/okhttp/Route;Lcom/android/okhttp/Route;]Lcom/android/okhttp/internal/RouteDatabase;Lcom/android/okhttp/internal/RouteDatabase;]Ljava/net/Proxy;Ljava/net/Proxy;
+HSPLcom/android/okhttp/internal/http/RouteSelector;->hasNext()Z
+HSPLcom/android/okhttp/internal/http/RouteSelector;->hasNextInetSocketAddress()Z+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/internal/http/RouteSelector;->hasNextPostponed()Z+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLcom/android/okhttp/internal/http/RouteSelector;->hasNextProxy()Z+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/internal/http/RouteSelector;->next()Lcom/android/okhttp/Route;+]Lcom/android/okhttp/internal/RouteDatabase;Lcom/android/okhttp/internal/RouteDatabase;]Ljava/util/List;Ljava/util/ArrayList;]Lcom/android/okhttp/internal/http/RouteSelector;Lcom/android/okhttp/internal/http/RouteSelector;
+HSPLcom/android/okhttp/internal/http/RouteSelector;->nextInetSocketAddress()Ljava/net/InetSocketAddress;+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/internal/http/RouteSelector;->nextPostponed()Lcom/android/okhttp/Route;
+HSPLcom/android/okhttp/internal/http/RouteSelector;->nextProxy()Ljava/net/Proxy;+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/internal/http/RouteSelector;->resetNextInetSocketAddress(Ljava/net/Proxy;)V+]Lcom/android/okhttp/Dns;Lcom/android/okhttp/Dns$1;,Lcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory$DnsAdapter;]Ljava/util/List;missing_types]Lcom/android/okhttp/Address;Lcom/android/okhttp/Address;]Ljava/net/Proxy;missing_types
+HSPLcom/android/okhttp/internal/http/RouteSelector;->resetNextProxy(Lcom/android/okhttp/HttpUrl;Ljava/net/Proxy;)V+]Lcom/android/okhttp/HttpUrl;Lcom/android/okhttp/HttpUrl;]Ljava/util/List;missing_types]Lcom/android/okhttp/Address;Lcom/android/okhttp/Address;]Ljava/net/ProxySelector;missing_types
+HSPLcom/android/okhttp/internal/http/StatusLine;-><init>(Lcom/android/okhttp/Protocol;ILjava/lang/String;)V
+HSPLcom/android/okhttp/internal/http/StatusLine;->get(Lcom/android/okhttp/Response;)Lcom/android/okhttp/internal/http/StatusLine;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;
+HSPLcom/android/okhttp/internal/http/StatusLine;->parse(Ljava/lang/String;)Lcom/android/okhttp/internal/http/StatusLine;+]Ljava/lang/String;missing_types
+HSPLcom/android/okhttp/internal/http/StatusLine;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;missing_types
+HSPLcom/android/okhttp/internal/http/StreamAllocation;-><init>(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/Address;)V
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->acquire(Lcom/android/okhttp/internal/io/RealConnection;)V+]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->cancel()V+]Lcom/android/okhttp/internal/http/HttpStream;Lcom/android/okhttp/internal/http/Http1xStream;
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->connection()Lcom/android/okhttp/internal/io/RealConnection;
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->connectionFailed()V
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->connectionFailed(Ljava/io/IOException;)V+]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;]Lcom/android/okhttp/internal/io/RealConnection;Lcom/android/okhttp/internal/io/RealConnection;]Lcom/android/okhttp/internal/http/RouteSelector;Lcom/android/okhttp/internal/http/RouteSelector;
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->deallocate(ZZZ)V+]Lcom/android/okhttp/internal/Internal;Lcom/android/okhttp/OkHttpClient$1;]Lcom/android/okhttp/internal/io/RealConnection;Lcom/android/okhttp/internal/io/RealConnection;]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->findConnection(IIIZ)Lcom/android/okhttp/internal/io/RealConnection;+]Lcom/android/okhttp/internal/Internal;Lcom/android/okhttp/OkHttpClient$1;]Lcom/android/okhttp/internal/io/RealConnection;Lcom/android/okhttp/internal/io/RealConnection;]Lcom/android/okhttp/internal/RouteDatabase;Lcom/android/okhttp/internal/RouteDatabase;]Lcom/android/okhttp/Address;Lcom/android/okhttp/Address;]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;]Lcom/android/okhttp/internal/http/RouteSelector;Lcom/android/okhttp/internal/http/RouteSelector;
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->findHealthyConnection(IIIZZ)Lcom/android/okhttp/internal/io/RealConnection;+]Lcom/android/okhttp/internal/io/RealConnection;Lcom/android/okhttp/internal/io/RealConnection;]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->isRecoverable(Lcom/android/okhttp/internal/http/RouteException;)Z
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->isRecoverable(Ljava/io/IOException;)Z
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->newStream(IIIZZ)Lcom/android/okhttp/internal/http/HttpStream;+]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Lcom/android/okhttp/okio/Timeout;Lcom/android/okhttp/okio/Okio$3;]Lcom/android/okhttp/internal/io/RealConnection;Lcom/android/okhttp/internal/io/RealConnection;]Lcom/android/okhttp/okio/BufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;]Ljava/net/Socket;missing_types
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->noNewStreams()V
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->recover(Lcom/android/okhttp/internal/http/RouteException;)Z+]Lcom/android/okhttp/internal/http/RouteSelector;Lcom/android/okhttp/internal/http/RouteSelector;]Lcom/android/okhttp/internal/http/RouteException;Lcom/android/okhttp/internal/http/RouteException;
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->recover(Ljava/io/IOException;Lcom/android/okhttp/okio/Sink;)Z
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->release()V
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->release(Lcom/android/okhttp/internal/io/RealConnection;)V+]Ljava/lang/ref/Reference;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->routeDatabase()Lcom/android/okhttp/internal/RouteDatabase;+]Lcom/android/okhttp/internal/Internal;Lcom/android/okhttp/OkHttpClient$1;
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->streamFinished(Lcom/android/okhttp/internal/http/HttpStream;)V
+HSPLcom/android/okhttp/internal/http/StreamAllocation;->toString()Ljava/lang/String;+]Ljava/lang/Object;Lcom/android/okhttp/Address;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;-><init>(Ljava/net/HttpURLConnection;)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->addRequestProperty(Ljava/lang/String;Ljava/lang/String;)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->connect()V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->disconnect()V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getContentEncoding()Ljava/lang/String;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getContentLength()I+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getContentType()Ljava/lang/String;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getErrorStream()Ljava/io/InputStream;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getHeaderField(Ljava/lang/String;)Ljava/lang/String;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getHeaderFields()Ljava/util/Map;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getInputStream()Ljava/io/InputStream;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getOutputStream()Ljava/io/OutputStream;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getRequestMethod()Ljava/lang/String;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getRequestProperties()Ljava/util/Map;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getRequestProperty(Ljava/lang/String;)Ljava/lang/String;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getResponseCode()I+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getResponseMessage()Ljava/lang/String;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->getURL()Ljava/net/URL;+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setChunkedStreamingMode(I)V
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setConnectTimeout(I)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setDefaultUseCaches(Z)V
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setDoInput(Z)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setDoOutput(Z)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setFixedLengthStreamingMode(I)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setInstanceFollowRedirects(Z)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setReadTimeout(I)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setRequestMethod(Ljava/lang/String;)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setRequestProperty(Ljava/lang/String;Ljava/lang/String;)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;->setUseCaches(Z)V+]Ljava/net/HttpURLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;-><init>(Ljava/net/URL;Lcom/android/okhttp/OkHttpClient;)V
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;-><init>(Ljava/net/URL;Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/internal/URLFilter;)V
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->addRequestProperty(Ljava/lang/String;Ljava/lang/String;)V+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->connect()V
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->defaultUserAgent()Ljava/lang/String;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->disconnect()V+]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->execute(Z)Z+]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/Connection;Lcom/android/okhttp/internal/io/RealConnection;]Lcom/android/okhttp/internal/http/RouteException;Lcom/android/okhttp/internal/http/RouteException;]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Lcom/android/okhttp/internal/URLFilter;Lcom/android/okhttp/HttpHandler$CleartextURLFilter;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getErrorStream()Ljava/io/InputStream;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/ResponseBody;Lcom/android/okhttp/internal/http/RealResponseBody;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getHeaderField(Ljava/lang/String;)Ljava/lang/String;+]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getHeaderFields()Ljava/util/Map;+]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/internal/http/StatusLine;Lcom/android/okhttp/internal/http/StatusLine;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getHeaders()Lcom/android/okhttp/Headers;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;]Lcom/android/okhttp/Protocol;Lcom/android/okhttp/Protocol;]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getInputStream()Ljava/io/InputStream;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;]Lcom/android/okhttp/ResponseBody;Lcom/android/okhttp/internal/http/RealResponseBody;,Lcom/android/okhttp/Cache$CacheResponseBody;]Ljava/net/URL;missing_types
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getOutputStream()Ljava/io/OutputStream;+]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;]Lcom/android/okhttp/okio/BufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getRequestProperties()Ljava/util/Map;+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getRequestProperty(Ljava/lang/String;)Ljava/lang/String;+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getResponse()Lcom/android/okhttp/internal/http/HttpEngine;+]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;]Lcom/android/okhttp/Request;Lcom/android/okhttp/Request;]Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/StreamAllocation;]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getResponseCode()I+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->getResponseMessage()Ljava/lang/String;+]Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;]Lcom/android/okhttp/internal/http/HttpEngine;Lcom/android/okhttp/internal/http/HttpEngine;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->initHttpEngine()V
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->newHttpEngine(Ljava/lang/String;Lcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/RetryableSink;Lcom/android/okhttp/Response;)Lcom/android/okhttp/internal/http/HttpEngine;+]Lcom/android/okhttp/internal/Internal;Lcom/android/okhttp/OkHttpClient$1;]Ljava/net/URL;missing_types]Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;]Lcom/android/okhttp/Request$Builder;Lcom/android/okhttp/Request$Builder;]Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->responseSourceHeader(Lcom/android/okhttp/Response;)Ljava/lang/String;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->setConnectTimeout(I)V+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->setFixedLengthStreamingMode(I)V+]Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->setFixedLengthStreamingMode(J)V
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->setInstanceFollowRedirects(Z)V+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->setReadTimeout(I)V+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->setRequestMethod(Ljava/lang/String;)V+]Ljava/util/Set;missing_types
+HSPLcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->setRequestProperty(Ljava/lang/String;Ljava/lang/String;)V+]Lcom/android/okhttp/Headers$Builder;Lcom/android/okhttp/Headers$Builder;]Ljava/lang/StringBuilder;missing_types]Lcom/android/okhttp/internal/Platform;Lcom/android/okhttp/internal/Platform;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;-><init>(Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;-><init>(Ljava/net/URL;Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/internal/URLFilter;)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->addRequestProperty(Ljava/lang/String;Ljava/lang/String;)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->connect()V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->disconnect()V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getContentEncoding()Ljava/lang/String;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getContentLength()I
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getContentType()Ljava/lang/String;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getErrorStream()Ljava/io/InputStream;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getHeaderField(Ljava/lang/String;)Ljava/lang/String;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getHeaderFields()Ljava/util/Map;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getInputStream()Ljava/io/InputStream;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getOutputStream()Ljava/io/OutputStream;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getRequestMethod()Ljava/lang/String;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getRequestProperties()Ljava/util/Map;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getRequestProperty(Ljava/lang/String;)Ljava/lang/String;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getResponseCode()I
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getResponseMessage()Ljava/lang/String;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->getURL()Ljava/net/URL;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setChunkedStreamingMode(I)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setConnectTimeout(I)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setDefaultUseCaches(Z)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setDoInput(Z)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setDoOutput(Z)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setFixedLengthStreamingMode(I)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setInstanceFollowRedirects(Z)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setReadTimeout(I)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setRequestMethod(Ljava/lang/String;)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setRequestProperty(Ljava/lang/String;Ljava/lang/String;)V
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setSSLSocketFactory(Ljavax/net/ssl/SSLSocketFactory;)V+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;
+HSPLcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->setUseCaches(Z)V
+HSPLcom/android/okhttp/internal/io/RealConnection;-><init>(Lcom/android/okhttp/Route;)V
+HSPLcom/android/okhttp/internal/io/RealConnection;->allocationLimit()I
+HSPLcom/android/okhttp/internal/io/RealConnection;->cancel()V
+HSPLcom/android/okhttp/internal/io/RealConnection;->connect(IIILjava/util/List;Z)V+]Lcom/android/okhttp/Route;Lcom/android/okhttp/Route;]Ljavax/net/SocketFactory;missing_types]Ljava/util/List;Ljava/util/Collections$UnmodifiableRandomAccessList;]Lcom/android/okhttp/Address;Lcom/android/okhttp/Address;]Ljava/net/Proxy;missing_types]Lcom/android/okhttp/internal/ConnectionSpecSelector;Lcom/android/okhttp/internal/ConnectionSpecSelector;
+HSPLcom/android/okhttp/internal/io/RealConnection;->connectSocket(IIILcom/android/okhttp/internal/ConnectionSpecSelector;)V+]Lcom/android/okhttp/Route;Lcom/android/okhttp/Route;]Lcom/android/okhttp/internal/Platform;Lcom/android/okhttp/internal/Platform;]Ljava/net/Socket;missing_types]Lcom/android/okhttp/Address;Lcom/android/okhttp/Address;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLcom/android/okhttp/internal/io/RealConnection;->connectTls(IILcom/android/okhttp/internal/ConnectionSpecSelector;)V+]Lcom/android/okhttp/Route;Lcom/android/okhttp/Route;]Ljavax/net/ssl/HostnameVerifier;missing_types]Lcom/android/okhttp/internal/Platform;Lcom/android/okhttp/internal/Platform;]Ljavax/net/ssl/SSLSocket;missing_types]Lcom/android/okhttp/internal/ConnectionSpecSelector;Lcom/android/okhttp/internal/ConnectionSpecSelector;]Lcom/android/okhttp/Address;Lcom/android/okhttp/Address;]Ljavax/net/ssl/SSLSocketFactory;missing_types]Lcom/android/okhttp/ConnectionSpec;Lcom/android/okhttp/ConnectionSpec;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/security/cert/X509Certificate;missing_types]Lcom/android/okhttp/Handshake;Lcom/android/okhttp/Handshake;]Ljava/security/Principal;Ljavax/security/auth/x500/X500Principal;]Ljava/util/List;Ljava/util/Collections$UnmodifiableRandomAccessList;
+HSPLcom/android/okhttp/internal/io/RealConnection;->getHandshake()Lcom/android/okhttp/Handshake;
+HSPLcom/android/okhttp/internal/io/RealConnection;->getRoute()Lcom/android/okhttp/Route;
+HSPLcom/android/okhttp/internal/io/RealConnection;->getSocket()Ljava/net/Socket;
+HSPLcom/android/okhttp/internal/io/RealConnection;->isHealthy(Z)Z+]Ljava/net/Socket;missing_types]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/internal/tls/OkHostnameVerifier;->getSubjectAltNames(Ljava/security/cert/X509Certificate;I)Ljava/util/List;+]Ljava/security/cert/X509Certificate;missing_types]Ljava/lang/Integer;Ljava/lang/Integer;]Ljava/util/List;Ljava/util/Collections$UnmodifiableRandomAccessList;,Ljava/util/ArrayList;]Ljava/util/Collection;Ljava/util/Collections$UnmodifiableCollection;]Ljava/util/Iterator;Ljava/util/Collections$UnmodifiableCollection$1;
+HSPLcom/android/okhttp/internal/tls/OkHostnameVerifier;->isPrintableAscii(Ljava/lang/String;)Z+]Ljava/lang/String;Ljava/lang/String;
+HSPLcom/android/okhttp/internal/tls/OkHostnameVerifier;->verify(Ljava/lang/String;Ljava/security/cert/X509Certificate;)Z
+HSPLcom/android/okhttp/internal/tls/OkHostnameVerifier;->verify(Ljava/lang/String;Ljavax/net/ssl/SSLSession;)Z+]Ljavax/net/ssl/SSLSession;missing_types]Lcom/android/okhttp/internal/tls/OkHostnameVerifier;Lcom/android/okhttp/internal/tls/OkHostnameVerifier;
+HSPLcom/android/okhttp/internal/tls/OkHostnameVerifier;->verifyAsIpAddress(Ljava/lang/String;)Z
+HSPLcom/android/okhttp/internal/tls/OkHostnameVerifier;->verifyHostName(Ljava/lang/String;Ljava/lang/String;)Z+]Ljava/lang/String;missing_types]Ljava/lang/StringBuilder;missing_types
+HSPLcom/android/okhttp/internal/tls/OkHostnameVerifier;->verifyHostName(Ljava/lang/String;Ljava/security/cert/X509Certificate;)Z+]Ljava/lang/String;missing_types]Ljava/util/List;missing_types
+HSPLcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory$DnsAdapter;-><init>(Lcom/android/okhttp/internalandroidapi/Dns;)V
+HSPLcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory$DnsAdapter;->hashCode()I+]Ljava/lang/Object;missing_types
+HSPLcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory$DnsAdapter;->lookup(Ljava/lang/String;)Ljava/util/List;+]Lcom/android/okhttp/internalandroidapi/Dns;missing_types
+HSPLcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory;-><init>()V
+HSPLcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory;->internalOpenConnection(Ljava/net/URL;Ljavax/net/SocketFactory;Ljava/net/Proxy;)Ljava/net/URLConnection;+]Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/OkHttpClient;]Ljava/net/URL;missing_types]Lcom/android/okhttp/OkUrlFactory;Lcom/android/okhttp/OkUrlFactory;
+HSPLcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory;->openConnection(Ljava/net/URL;Ljavax/net/SocketFactory;Ljava/net/Proxy;)Ljava/net/URLConnection;
+HSPLcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory;->setDns(Lcom/android/okhttp/internalandroidapi/Dns;)V
+HSPLcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory;->setNewConnectionPool(IJLjava/util/concurrent/TimeUnit;)V
+HSPLcom/android/okhttp/okio/AsyncTimeout$1;-><init>(Lcom/android/okhttp/okio/AsyncTimeout;Lcom/android/okhttp/okio/Sink;)V
+HSPLcom/android/okhttp/okio/AsyncTimeout$1;->flush()V+]Lcom/android/okhttp/okio/AsyncTimeout;Lcom/android/okhttp/okio/Okio$3;]Lcom/android/okhttp/okio/Sink;Lcom/android/okhttp/okio/Okio$1;
+HSPLcom/android/okhttp/okio/AsyncTimeout$1;->timeout()Lcom/android/okhttp/okio/Timeout;
+HSPLcom/android/okhttp/okio/AsyncTimeout$1;->write(Lcom/android/okhttp/okio/Buffer;J)V+]Lcom/android/okhttp/okio/AsyncTimeout;Lcom/android/okhttp/okio/Okio$3;]Lcom/android/okhttp/okio/Sink;Lcom/android/okhttp/okio/Okio$1;
+HSPLcom/android/okhttp/okio/AsyncTimeout$2;-><init>(Lcom/android/okhttp/okio/AsyncTimeout;Lcom/android/okhttp/okio/Source;)V
+HSPLcom/android/okhttp/okio/AsyncTimeout$2;->read(Lcom/android/okhttp/okio/Buffer;J)J+]Lcom/android/okhttp/okio/Source;Lcom/android/okhttp/okio/Okio$2;]Lcom/android/okhttp/okio/AsyncTimeout;Lcom/android/okhttp/okio/Okio$3;
+HSPLcom/android/okhttp/okio/AsyncTimeout$2;->timeout()Lcom/android/okhttp/okio/Timeout;
+HSPLcom/android/okhttp/okio/AsyncTimeout$Watchdog;-><init>()V
+HSPLcom/android/okhttp/okio/AsyncTimeout$Watchdog;->run()V
+HSPLcom/android/okhttp/okio/AsyncTimeout;-><init>()V
+HSPLcom/android/okhttp/okio/AsyncTimeout;->access$000()Lcom/android/okhttp/okio/AsyncTimeout;
+HSPLcom/android/okhttp/okio/AsyncTimeout;->awaitTimeout()Lcom/android/okhttp/okio/AsyncTimeout;+]Ljava/lang/Object;missing_types
+HSPLcom/android/okhttp/okio/AsyncTimeout;->cancelScheduledTimeout(Lcom/android/okhttp/okio/AsyncTimeout;)Z
+HSPLcom/android/okhttp/okio/AsyncTimeout;->enter()V+]Lcom/android/okhttp/okio/AsyncTimeout;Lcom/android/okhttp/okio/Okio$3;
+HSPLcom/android/okhttp/okio/AsyncTimeout;->exit()Z
+HSPLcom/android/okhttp/okio/AsyncTimeout;->exit(Ljava/io/IOException;)Ljava/io/IOException;+]Lcom/android/okhttp/okio/AsyncTimeout;Lcom/android/okhttp/okio/Okio$3;
+HSPLcom/android/okhttp/okio/AsyncTimeout;->exit(Z)V+]Lcom/android/okhttp/okio/AsyncTimeout;Lcom/android/okhttp/okio/Okio$3;
+HSPLcom/android/okhttp/okio/AsyncTimeout;->remainingNanos(J)J
+HSPLcom/android/okhttp/okio/AsyncTimeout;->scheduleTimeout(Lcom/android/okhttp/okio/AsyncTimeout;JZ)V+]Ljava/lang/Object;missing_types]Lcom/android/okhttp/okio/AsyncTimeout;Lcom/android/okhttp/okio/Okio$3;
+HSPLcom/android/okhttp/okio/AsyncTimeout;->sink(Lcom/android/okhttp/okio/Sink;)Lcom/android/okhttp/okio/Sink;
+HSPLcom/android/okhttp/okio/AsyncTimeout;->source(Lcom/android/okhttp/okio/Source;)Lcom/android/okhttp/okio/Source;
+HSPLcom/android/okhttp/okio/Buffer;-><init>()V
+HSPLcom/android/okhttp/okio/Buffer;->clear()V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->completeSegmentByteCount()J
+HSPLcom/android/okhttp/okio/Buffer;->copyTo(Lcom/android/okhttp/okio/Buffer;JJ)Lcom/android/okhttp/okio/Buffer;+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Buffer;->exhausted()Z
+HSPLcom/android/okhttp/okio/Buffer;->getByte(J)B
+HSPLcom/android/okhttp/okio/Buffer;->indexOf(BJ)J
+HSPLcom/android/okhttp/okio/Buffer;->read(Lcom/android/okhttp/okio/Buffer;J)J+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->read([BII)I+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Buffer;->readByte()B+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Buffer;->readByteArray()[B+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->readByteArray(J)[B+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->readByteString()Lcom/android/okhttp/okio/ByteString;
+HSPLcom/android/okhttp/okio/Buffer;->readFully([B)V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->readHexadecimalUnsignedLong()J+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Buffer;->readInt()I+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->readIntLe()I+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->readShort()S+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->readString(JLjava/nio/charset/Charset;)Ljava/lang/String;+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->readUtf8()Ljava/lang/String;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->readUtf8(J)Ljava/lang/String;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->readUtf8Line(J)Ljava/lang/String;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->size()J
+HSPLcom/android/okhttp/okio/Buffer;->skip(J)V+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Buffer;->writableSegment(I)Lcom/android/okhttp/okio/Segment;+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Buffer;->write(Lcom/android/okhttp/okio/Buffer;J)V+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Buffer;->write([BII)Lcom/android/okhttp/okio/Buffer;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->writeByte(I)Lcom/android/okhttp/okio/Buffer;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->writeHexadecimalUnsignedLong(J)Lcom/android/okhttp/okio/Buffer;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->writeUtf8(Ljava/lang/String;)Lcom/android/okhttp/okio/Buffer;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->writeUtf8(Ljava/lang/String;II)Lcom/android/okhttp/okio/Buffer;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/Buffer;->writeUtf8CodePoint(I)Lcom/android/okhttp/okio/Buffer;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/ByteString;-><init>([B)V
+HSPLcom/android/okhttp/okio/ByteString;->hex()Ljava/lang/String;
+HSPLcom/android/okhttp/okio/ForwardingTimeout;-><init>(Lcom/android/okhttp/okio/Timeout;)V
+HSPLcom/android/okhttp/okio/ForwardingTimeout;->clearDeadline()Lcom/android/okhttp/okio/Timeout;+]Lcom/android/okhttp/okio/Timeout;Lcom/android/okhttp/okio/Timeout$1;,Lcom/android/okhttp/okio/Okio$3;
+HSPLcom/android/okhttp/okio/ForwardingTimeout;->deadlineNanoTime(J)Lcom/android/okhttp/okio/Timeout;+]Lcom/android/okhttp/okio/Timeout;Lcom/android/okhttp/okio/Okio$3;
+HSPLcom/android/okhttp/okio/ForwardingTimeout;->delegate()Lcom/android/okhttp/okio/Timeout;
+HSPLcom/android/okhttp/okio/ForwardingTimeout;->hasDeadline()Z+]Lcom/android/okhttp/okio/Timeout;Lcom/android/okhttp/okio/Okio$3;
+HSPLcom/android/okhttp/okio/ForwardingTimeout;->setDelegate(Lcom/android/okhttp/okio/Timeout;)Lcom/android/okhttp/okio/ForwardingTimeout;
+HSPLcom/android/okhttp/okio/GzipSource;-><init>(Lcom/android/okhttp/okio/Source;)V
+HSPLcom/android/okhttp/okio/GzipSource;->checkEqual(Ljava/lang/String;II)V
+HSPLcom/android/okhttp/okio/GzipSource;->close()V+]Lcom/android/okhttp/okio/InflaterSource;Lcom/android/okhttp/okio/InflaterSource;
+HSPLcom/android/okhttp/okio/GzipSource;->consumeHeader()V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/okio/GzipSource;->consumeTrailer()V+]Ljava/util/zip/CRC32;Ljava/util/zip/CRC32;]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLcom/android/okhttp/okio/GzipSource;->read(Lcom/android/okhttp/okio/Buffer;J)J+]Lcom/android/okhttp/okio/InflaterSource;Lcom/android/okhttp/okio/InflaterSource;]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/okio/GzipSource;->updateCrc(Lcom/android/okhttp/okio/Buffer;JJ)V+]Ljava/util/zip/CRC32;missing_types
+HSPLcom/android/okhttp/okio/InflaterSource;-><init>(Lcom/android/okhttp/okio/BufferedSource;Ljava/util/zip/Inflater;)V
+HSPLcom/android/okhttp/okio/InflaterSource;->close()V+]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLcom/android/okhttp/okio/InflaterSource;->read(Lcom/android/okhttp/okio/Buffer;J)J+]Lcom/android/okhttp/okio/InflaterSource;Lcom/android/okhttp/okio/InflaterSource;]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Ljava/util/zip/Inflater;missing_types
+HSPLcom/android/okhttp/okio/InflaterSource;->refill()Z+]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Ljava/util/zip/Inflater;missing_types
+HSPLcom/android/okhttp/okio/InflaterSource;->releaseInflatedBytes()V+]Lcom/android/okhttp/okio/BufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Ljava/util/zip/Inflater;missing_types
+HSPLcom/android/okhttp/okio/Okio$1;-><init>(Lcom/android/okhttp/okio/Timeout;Ljava/io/OutputStream;)V
+HSPLcom/android/okhttp/okio/Okio$1;->flush()V+]Ljava/io/OutputStream;missing_types
+HSPLcom/android/okhttp/okio/Okio$1;->write(Lcom/android/okhttp/okio/Buffer;J)V+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;]Lcom/android/okhttp/okio/Timeout;Lcom/android/okhttp/okio/Okio$3;,Lcom/android/okhttp/okio/Timeout;]Ljava/io/OutputStream;missing_types
+HSPLcom/android/okhttp/okio/Okio$2;-><init>(Lcom/android/okhttp/okio/Timeout;Ljava/io/InputStream;)V
+HSPLcom/android/okhttp/okio/Okio$2;->read(Lcom/android/okhttp/okio/Buffer;J)J+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Timeout;Lcom/android/okhttp/okio/Okio$3;,Lcom/android/okhttp/okio/Timeout;]Ljava/io/InputStream;missing_types
+HSPLcom/android/okhttp/okio/Okio$3;-><init>(Ljava/net/Socket;)V
+HSPLcom/android/okhttp/okio/Okio$3;->newTimeoutException(Ljava/io/IOException;)Ljava/io/IOException;
+HSPLcom/android/okhttp/okio/Okio$3;->timedOut()V
+HSPLcom/android/okhttp/okio/Okio;->buffer(Lcom/android/okhttp/okio/Sink;)Lcom/android/okhttp/okio/BufferedSink;
+HSPLcom/android/okhttp/okio/Okio;->buffer(Lcom/android/okhttp/okio/Source;)Lcom/android/okhttp/okio/BufferedSource;
+HSPLcom/android/okhttp/okio/Okio;->sink(Ljava/io/OutputStream;Lcom/android/okhttp/okio/Timeout;)Lcom/android/okhttp/okio/Sink;
+HSPLcom/android/okhttp/okio/Okio;->sink(Ljava/net/Socket;)Lcom/android/okhttp/okio/Sink;
+HSPLcom/android/okhttp/okio/Okio;->source(Ljava/io/InputStream;Lcom/android/okhttp/okio/Timeout;)Lcom/android/okhttp/okio/Source;
+HSPLcom/android/okhttp/okio/Okio;->source(Ljava/net/Socket;)Lcom/android/okhttp/okio/Source;
+HSPLcom/android/okhttp/okio/Okio;->timeout(Ljava/net/Socket;)Lcom/android/okhttp/okio/AsyncTimeout;
+HSPLcom/android/okhttp/okio/RealBufferedSink$1;-><init>(Lcom/android/okhttp/okio/RealBufferedSink;)V
+HSPLcom/android/okhttp/okio/RealBufferedSink$1;->close()V+]Lcom/android/okhttp/okio/RealBufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/okio/RealBufferedSink$1;->flush()V+]Lcom/android/okhttp/okio/RealBufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/okio/RealBufferedSink$1;->write([BII)V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/RealBufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/okio/RealBufferedSink;-><init>(Lcom/android/okhttp/okio/Sink;)V
+HSPLcom/android/okhttp/okio/RealBufferedSink;-><init>(Lcom/android/okhttp/okio/Sink;Lcom/android/okhttp/okio/Buffer;)V
+HSPLcom/android/okhttp/okio/RealBufferedSink;->access$000(Lcom/android/okhttp/okio/RealBufferedSink;)Z
+HSPLcom/android/okhttp/okio/RealBufferedSink;->buffer()Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/RealBufferedSink;->close()V+]Lcom/android/okhttp/okio/Sink;megamorphic_types
+HSPLcom/android/okhttp/okio/RealBufferedSink;->emit()Lcom/android/okhttp/okio/BufferedSink;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Sink;Lcom/android/okhttp/internal/http/RetryableSink;,Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSink;
+HSPLcom/android/okhttp/okio/RealBufferedSink;->emitCompleteSegments()Lcom/android/okhttp/okio/BufferedSink;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Sink;megamorphic_types
+HSPLcom/android/okhttp/okio/RealBufferedSink;->flush()V+]Lcom/android/okhttp/okio/Sink;megamorphic_types
+HSPLcom/android/okhttp/okio/RealBufferedSink;->outputStream()Ljava/io/OutputStream;
+HSPLcom/android/okhttp/okio/RealBufferedSink;->timeout()Lcom/android/okhttp/okio/Timeout;+]Lcom/android/okhttp/okio/Sink;Lcom/android/okhttp/okio/AsyncTimeout$1;
+HSPLcom/android/okhttp/okio/RealBufferedSink;->write(Lcom/android/okhttp/okio/Buffer;J)V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/RealBufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/okio/RealBufferedSink;->writeHexadecimalUnsignedLong(J)Lcom/android/okhttp/okio/BufferedSink;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/RealBufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/okio/RealBufferedSink;->writeUtf8(Ljava/lang/String;)Lcom/android/okhttp/okio/BufferedSink;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/RealBufferedSink;Lcom/android/okhttp/okio/RealBufferedSink;
+HSPLcom/android/okhttp/okio/RealBufferedSource$1;-><init>(Lcom/android/okhttp/okio/RealBufferedSource;)V
+HSPLcom/android/okhttp/okio/RealBufferedSource$1;->available()I
+HSPLcom/android/okhttp/okio/RealBufferedSource$1;->close()V+]Lcom/android/okhttp/okio/RealBufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/okio/RealBufferedSource$1;->read()I+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Source;Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;,Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;,Lcom/android/okhttp/okio/GzipSource;,Lcom/android/okhttp/internal/http/HttpEngine$2;
+HSPLcom/android/okhttp/okio/RealBufferedSource$1;->read([BII)I+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Source;megamorphic_types
+HSPLcom/android/okhttp/okio/RealBufferedSource;-><init>(Lcom/android/okhttp/okio/Source;)V
+HSPLcom/android/okhttp/okio/RealBufferedSource;-><init>(Lcom/android/okhttp/okio/Source;Lcom/android/okhttp/okio/Buffer;)V
+HSPLcom/android/okhttp/okio/RealBufferedSource;->access$000(Lcom/android/okhttp/okio/RealBufferedSource;)Z
+HSPLcom/android/okhttp/okio/RealBufferedSource;->buffer()Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->close()V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Source;megamorphic_types
+HSPLcom/android/okhttp/okio/RealBufferedSource;->exhausted()Z+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Source;Lcom/android/okhttp/okio/AsyncTimeout$2;,Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->indexOf(B)J+]Lcom/android/okhttp/okio/RealBufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->indexOf(BJ)J+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Source;Lcom/android/okhttp/okio/AsyncTimeout$2;,Lcom/android/okhttp/okio/Okio$2;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->inputStream()Ljava/io/InputStream;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->read(Lcom/android/okhttp/okio/Buffer;J)J+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/Source;Lcom/android/okhttp/okio/AsyncTimeout$2;,Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;,Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;,Lcom/android/okhttp/internal/http/HttpEngine$2;,Lcom/android/okhttp/Cache$CacheResponseBody$1;,Lcom/android/okhttp/internal/http/Http1xStream$UnknownLengthSource;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->readHexadecimalUnsignedLong()J+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/RealBufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->readIntLe()I+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/RealBufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->readShort()S+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/RealBufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->readUtf8LineStrict()Ljava/lang/String;+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;]Lcom/android/okhttp/okio/RealBufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;]Ljava/lang/StringBuilder;missing_types]Lcom/android/okhttp/okio/ByteString;Lcom/android/okhttp/okio/ByteString;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->request(J)Z+]Lcom/android/okhttp/okio/Source;Lcom/android/okhttp/okio/AsyncTimeout$2;,Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->require(J)V+]Lcom/android/okhttp/okio/RealBufferedSource;Lcom/android/okhttp/okio/RealBufferedSource;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->skip(J)V+]Lcom/android/okhttp/okio/Buffer;Lcom/android/okhttp/okio/Buffer;
+HSPLcom/android/okhttp/okio/RealBufferedSource;->timeout()Lcom/android/okhttp/okio/Timeout;+]Lcom/android/okhttp/okio/Source;Lcom/android/okhttp/okio/AsyncTimeout$2;,Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;
+HSPLcom/android/okhttp/okio/Segment;-><init>()V
+HSPLcom/android/okhttp/okio/Segment;-><init>(Lcom/android/okhttp/okio/Segment;)V
+HSPLcom/android/okhttp/okio/Segment;-><init>([BII)V
+HSPLcom/android/okhttp/okio/Segment;->compact()V+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Segment;->pop()Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Segment;->push(Lcom/android/okhttp/okio/Segment;)Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Segment;->split(I)Lcom/android/okhttp/okio/Segment;+]Lcom/android/okhttp/okio/Segment;Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Segment;->writeTo(Lcom/android/okhttp/okio/Segment;I)V
+HSPLcom/android/okhttp/okio/SegmentPool;->recycle(Lcom/android/okhttp/okio/Segment;)V
+HSPLcom/android/okhttp/okio/SegmentPool;->take()Lcom/android/okhttp/okio/Segment;
+HSPLcom/android/okhttp/okio/Timeout;-><init>()V
+HSPLcom/android/okhttp/okio/Timeout;->clearDeadline()Lcom/android/okhttp/okio/Timeout;
+HSPLcom/android/okhttp/okio/Timeout;->clearTimeout()Lcom/android/okhttp/okio/Timeout;
+HSPLcom/android/okhttp/okio/Timeout;->deadlineNanoTime()J
+HSPLcom/android/okhttp/okio/Timeout;->deadlineNanoTime(J)Lcom/android/okhttp/okio/Timeout;
+HSPLcom/android/okhttp/okio/Timeout;->hasDeadline()Z
+HSPLcom/android/okhttp/okio/Timeout;->throwIfReached()V
+HSPLcom/android/okhttp/okio/Timeout;->timeout(JLjava/util/concurrent/TimeUnit;)Lcom/android/okhttp/okio/Timeout;+]Ljava/util/concurrent/TimeUnit;missing_types
+HSPLcom/android/okhttp/okio/Timeout;->timeoutNanos()J
+HSPLcom/android/okhttp/okio/Util;->checkOffsetAndCount(JJJ)V
+HSPLcom/android/okhttp/okio/Util;->reverseBytesInt(I)I
+HSPLcom/android/org/bouncycastle/asn1/ASN1BitString;-><init>([BI)V
+HSPLcom/android/org/bouncycastle/asn1/ASN1BitString;->fromInputStream(ILjava/io/InputStream;)Lcom/android/org/bouncycastle/asn1/ASN1BitString;+]Ljava/io/InputStream;Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;
+HSPLcom/android/org/bouncycastle/asn1/ASN1EncodableVector;-><init>()V
+HSPLcom/android/org/bouncycastle/asn1/ASN1EncodableVector;->add(Lcom/android/org/bouncycastle/asn1/ASN1Encodable;)V
+HSPLcom/android/org/bouncycastle/asn1/ASN1EncodableVector;->get(I)Lcom/android/org/bouncycastle/asn1/ASN1Encodable;
+HSPLcom/android/org/bouncycastle/asn1/ASN1EncodableVector;->size()I
+HSPLcom/android/org/bouncycastle/asn1/ASN1InputStream;-><init>(Ljava/io/InputStream;)V
+HSPLcom/android/org/bouncycastle/asn1/ASN1InputStream;-><init>(Ljava/io/InputStream;I)V
+HSPLcom/android/org/bouncycastle/asn1/ASN1InputStream;-><init>(Ljava/io/InputStream;IZ)V
+HSPLcom/android/org/bouncycastle/asn1/ASN1InputStream;-><init>([B)V
+HSPLcom/android/org/bouncycastle/asn1/ASN1InputStream;->buildObject(III)Lcom/android/org/bouncycastle/asn1/ASN1Primitive;+]Lcom/android/org/bouncycastle/asn1/ASN1InputStream;Lcom/android/org/bouncycastle/asn1/ASN1InputStream;]Lcom/android/org/bouncycastle/asn1/ASN1StreamParser;Lcom/android/org/bouncycastle/asn1/ASN1StreamParser;
+HSPLcom/android/org/bouncycastle/asn1/ASN1InputStream;->createPrimitiveDERObject(ILcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;[[B)Lcom/android/org/bouncycastle/asn1/ASN1Primitive;+]Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;
+HSPLcom/android/org/bouncycastle/asn1/ASN1InputStream;->getBuffer(Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;[[B)[B+]Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;
+HSPLcom/android/org/bouncycastle/asn1/ASN1InputStream;->readLength()I
+HSPLcom/android/org/bouncycastle/asn1/ASN1InputStream;->readObject()Lcom/android/org/bouncycastle/asn1/ASN1Primitive;+]Lcom/android/org/bouncycastle/asn1/ASN1InputStream;Lcom/android/org/bouncycastle/asn1/ASN1InputStream;
+HSPLcom/android/org/bouncycastle/asn1/ASN1InputStream;->readTagNumber(Ljava/io/InputStream;I)I
+HSPLcom/android/org/bouncycastle/asn1/ASN1Integer;-><init>(Ljava/math/BigInteger;)V+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Integer;-><init>([BZ)V
+HSPLcom/android/org/bouncycastle/asn1/ASN1Integer;->encodedLength()I
+HSPLcom/android/org/bouncycastle/asn1/ASN1Integer;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/ASN1Integer;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Integer;->getValue()Ljava/math/BigInteger;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Integer;->isMalformed([B)Z
+HSPLcom/android/org/bouncycastle/asn1/ASN1Object;-><init>()V
+HSPLcom/android/org/bouncycastle/asn1/ASN1Object;->getEncoded()[B
+HSPLcom/android/org/bouncycastle/asn1/ASN1Object;->getEncoded(Ljava/lang/String;)[B+]Lcom/android/org/bouncycastle/asn1/ASN1Object;Lcom/android/org/bouncycastle/asn1/ASN1Integer;,Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;,Lcom/android/org/bouncycastle/asn1/DERSequence;]Ljava/io/ByteArrayOutputStream;Ljava/io/ByteArrayOutputStream;
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier$OidHandle;-><init>([B)V
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier$OidHandle;->equals(Ljava/lang/Object;)Z
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier$OidHandle;->hashCode()I
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;-><init>([B)V+]Ljava/lang/String;missing_types]Ljava/lang/StringBuffer;missing_types
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;->asn1Equals(Lcom/android/org/bouncycastle/asn1/ASN1Primitive;)Z
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;->doOutput(Ljava/io/ByteArrayOutputStream;)V+]Lcom/android/org/bouncycastle/asn1/OIDTokenizer;Lcom/android/org/bouncycastle/asn1/OIDTokenizer;
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;->encodedLength()I
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;->fromOctetString([B)Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;->getBody()[B
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;->getId()Ljava/lang/String;
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;
+HSPLcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;->writeField(Ljava/io/ByteArrayOutputStream;J)V
+HSPLcom/android/org/bouncycastle/asn1/ASN1OutputStream;-><init>(Ljava/io/OutputStream;)V
+HSPLcom/android/org/bouncycastle/asn1/ASN1OutputStream;->write(I)V+]Ljava/io/OutputStream;Ljava/io/ByteArrayOutputStream;
+HSPLcom/android/org/bouncycastle/asn1/ASN1OutputStream;->writeLength(I)V+]Lcom/android/org/bouncycastle/asn1/ASN1OutputStream;Lcom/android/org/bouncycastle/asn1/DEROutputStream;,Lcom/android/org/bouncycastle/asn1/ASN1OutputStream;
+HSPLcom/android/org/bouncycastle/asn1/ASN1OutputStream;->writeObject(Lcom/android/org/bouncycastle/asn1/ASN1Encodable;)V+]Lcom/android/org/bouncycastle/asn1/ASN1Encodable;Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;,Lcom/android/org/bouncycastle/asn1/pkcs/PrivateKeyInfo;]Lcom/android/org/bouncycastle/asn1/ASN1OutputStream;Lcom/android/org/bouncycastle/asn1/DEROutputStream;,Lcom/android/org/bouncycastle/asn1/ASN1OutputStream;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Primitive;-><init>()V
+HSPLcom/android/org/bouncycastle/asn1/ASN1Primitive;->fromByteArray([B)Lcom/android/org/bouncycastle/asn1/ASN1Primitive;+]Lcom/android/org/bouncycastle/asn1/ASN1InputStream;Lcom/android/org/bouncycastle/asn1/ASN1InputStream;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Primitive;->toASN1Primitive()Lcom/android/org/bouncycastle/asn1/ASN1Primitive;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Primitive;->toDERObject()Lcom/android/org/bouncycastle/asn1/ASN1Primitive;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Sequence;-><init>()V
+HSPLcom/android/org/bouncycastle/asn1/ASN1Sequence;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;)V+]Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Sequence;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/ASN1Sequence;+]Lcom/android/org/bouncycastle/asn1/ASN1Encodable;Lcom/android/org/bouncycastle/asn1/x500/X500Name;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Sequence;->getObjectAt(I)Lcom/android/org/bouncycastle/asn1/ASN1Encodable;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Sequence;->getObjects()Ljava/util/Enumeration;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Sequence;->size()I
+HSPLcom/android/org/bouncycastle/asn1/ASN1Sequence;->toDERObject()Lcom/android/org/bouncycastle/asn1/ASN1Primitive;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Set;-><init>()V
+HSPLcom/android/org/bouncycastle/asn1/ASN1Set;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;Z)V+]Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Set;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/ASN1Set;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Set;->getObjectAt(I)Lcom/android/org/bouncycastle/asn1/ASN1Encodable;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Set;->getObjects()Ljava/util/Enumeration;
+HSPLcom/android/org/bouncycastle/asn1/ASN1Set;->size()I
+HSPLcom/android/org/bouncycastle/asn1/ASN1TaggedObject;->getObject()Lcom/android/org/bouncycastle/asn1/ASN1Primitive;+]Lcom/android/org/bouncycastle/asn1/ASN1Encodable;Lcom/android/org/bouncycastle/asn1/ASN1Integer;,Lcom/android/org/bouncycastle/asn1/DLSequence;
+HSPLcom/android/org/bouncycastle/asn1/DERBitString;-><init>([BI)V
+HSPLcom/android/org/bouncycastle/asn1/DERBitString;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/DERBitString;
+HSPLcom/android/org/bouncycastle/asn1/DERFactory;->createSequence(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;)Lcom/android/org/bouncycastle/asn1/ASN1Sequence;
+HSPLcom/android/org/bouncycastle/asn1/DERNull;->encodedLength()I
+HSPLcom/android/org/bouncycastle/asn1/DEROutputStream;-><init>(Ljava/io/OutputStream;)V
+HSPLcom/android/org/bouncycastle/asn1/DERSequence;-><init>()V
+HSPLcom/android/org/bouncycastle/asn1/DERSequence;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;)V
+HSPLcom/android/org/bouncycastle/asn1/DERSequence;->encodedLength()I
+HSPLcom/android/org/bouncycastle/asn1/DERSequence;->getBodyLength()I+]Lcom/android/org/bouncycastle/asn1/ASN1Encodable;Lcom/android/org/bouncycastle/asn1/ASN1Integer;,Lcom/android/org/bouncycastle/asn1/DERSequence;,Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;]Lcom/android/org/bouncycastle/asn1/ASN1Primitive;Lcom/android/org/bouncycastle/asn1/ASN1Integer;,Lcom/android/org/bouncycastle/asn1/DERSequence;,Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
+HSPLcom/android/org/bouncycastle/asn1/DLSequence;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;)V
+HSPLcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;->getRemaining()I
+HSPLcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;->read()I+]Ljava/io/InputStream;Lcom/android/org/bouncycastle/asn1/ASN1InputStream;,Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;]Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;
+HSPLcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;->read([BII)I+]Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;]Ljava/io/InputStream;Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;,Lcom/android/org/bouncycastle/asn1/ASN1InputStream;
+HSPLcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;->toByteArray()[B+]Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;
+HSPLcom/android/org/bouncycastle/asn1/LimitedInputStream;-><init>(Ljava/io/InputStream;I)V
+HSPLcom/android/org/bouncycastle/asn1/LimitedInputStream;->setParentEofDetect(Z)V
+HSPLcom/android/org/bouncycastle/asn1/OIDTokenizer;-><init>(Ljava/lang/String;)V
+HSPLcom/android/org/bouncycastle/asn1/OIDTokenizer;->hasMoreTokens()Z
+HSPLcom/android/org/bouncycastle/asn1/OIDTokenizer;->nextToken()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLcom/android/org/bouncycastle/asn1/StreamUtil;->calculateBodyLength(I)I
+HSPLcom/android/org/bouncycastle/asn1/StreamUtil;->findLimit(Ljava/io/InputStream;)I+]Ljava/lang/Runtime;Ljava/lang/Runtime;]Lcom/android/org/bouncycastle/asn1/LimitedInputStream;Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;
+HSPLcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;Lcom/android/org/bouncycastle/asn1/ASN1Encodable;)V
+HSPLcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1Sequence;)V+]Lcom/android/org/bouncycastle/asn1/ASN1Sequence;Lcom/android/org/bouncycastle/asn1/DLSequence;
+HSPLcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;->getAlgorithm()Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
+HSPLcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;
+HSPLcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;->getParameters()Lcom/android/org/bouncycastle/asn1/ASN1Encodable;
+HSPLcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;->toASN1Primitive()Lcom/android/org/bouncycastle/asn1/ASN1Primitive;+]Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;
+HSPLcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1Sequence;)V+]Ljava/util/Enumeration;Lcom/android/org/bouncycastle/asn1/ASN1Sequence$1;]Lcom/android/org/bouncycastle/asn1/ASN1Sequence;Lcom/android/org/bouncycastle/asn1/DLSequence;
+HSPLcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;
+HSPLcom/android/org/bouncycastle/crypto/BufferedBlockCipher;-><init>()V
+HSPLcom/android/org/bouncycastle/crypto/BufferedBlockCipher;->getBlockSize()I+]Lcom/android/org/bouncycastle/crypto/BlockCipher;Lcom/android/org/bouncycastle/crypto/engines/AESEngine;,Lcom/android/org/bouncycastle/crypto/modes/CBCBlockCipher;
+HSPLcom/android/org/bouncycastle/crypto/BufferedBlockCipher;->getUnderlyingCipher()Lcom/android/org/bouncycastle/crypto/BlockCipher;
+HSPLcom/android/org/bouncycastle/crypto/BufferedBlockCipher;->reset()V+]Lcom/android/org/bouncycastle/crypto/BlockCipher;Lcom/android/org/bouncycastle/crypto/engines/AESEngine;,Lcom/android/org/bouncycastle/crypto/modes/CBCBlockCipher;,Lcom/android/org/bouncycastle/crypto/modes/SICBlockCipher;,Lcom/android/org/bouncycastle/crypto/modes/CFBBlockCipher;
+HSPLcom/android/org/bouncycastle/crypto/CryptoServicesRegistrar;->getSecureRandom()Ljava/security/SecureRandom;
+HSPLcom/android/org/bouncycastle/crypto/PBEParametersGenerator;-><init>()V
+HSPLcom/android/org/bouncycastle/crypto/PBEParametersGenerator;->PKCS5PasswordToUTF8Bytes([C)[B
+HSPLcom/android/org/bouncycastle/crypto/PBEParametersGenerator;->init([B[BI)V
+HSPLcom/android/org/bouncycastle/crypto/digests/AndroidDigestFactory;->getSHA1()Lcom/android/org/bouncycastle/crypto/Digest;
+HSPLcom/android/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL;->getSHA1()Lcom/android/org/bouncycastle/crypto/Digest;
+HSPLcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest$SHA1;-><init>()V
+HSPLcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest;-><init>(Ljava/lang/String;I)V
+HSPLcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest;->doFinal([BI)I+]Ljava/security/MessageDigest;missing_types
+HSPLcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest;->getByteLength()I
+HSPLcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest;->getDigestSize()I+]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;
+HSPLcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest;->reset()V
+HSPLcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest;->update([BII)V+]Ljava/security/MessageDigest;missing_types
+HSPLcom/android/org/bouncycastle/crypto/engines/AESEngine;-><init>()V
+HSPLcom/android/org/bouncycastle/crypto/engines/AESEngine;->getBlockSize()I
+HSPLcom/android/org/bouncycastle/crypto/engines/DESEngine;-><clinit>()V
+HSPLcom/android/org/bouncycastle/crypto/engines/DESEngine;-><init>()V
+HSPLcom/android/org/bouncycastle/crypto/engines/DESEngine;->generateWorkingKey(Z[B)[I
+HSPLcom/android/org/bouncycastle/crypto/macs/HMac;-><clinit>()V
+HSPLcom/android/org/bouncycastle/crypto/macs/HMac;-><init>(Lcom/android/org/bouncycastle/crypto/Digest;)V
+HSPLcom/android/org/bouncycastle/crypto/macs/HMac;-><init>(Lcom/android/org/bouncycastle/crypto/Digest;I)V
+HSPLcom/android/org/bouncycastle/crypto/macs/HMac;->doFinal([BI)I+]Lcom/android/org/bouncycastle/crypto/Digest;Lcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest$SHA1;,Lcom/android/org/bouncycastle/crypto/digests/SHA1Digest;,Lcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest$SHA512;]Lcom/android/org/bouncycastle/util/Memoable;Lcom/android/org/bouncycastle/crypto/digests/SHA1Digest;
+HSPLcom/android/org/bouncycastle/crypto/macs/HMac;->getByteLength(Lcom/android/org/bouncycastle/crypto/Digest;)I
+HSPLcom/android/org/bouncycastle/crypto/macs/HMac;->getMacSize()I
+HSPLcom/android/org/bouncycastle/crypto/macs/HMac;->init(Lcom/android/org/bouncycastle/crypto/CipherParameters;)V+]Lcom/android/org/bouncycastle/crypto/Digest;Lcom/android/org/bouncycastle/crypto/digests/SHA1Digest;]Lcom/android/org/bouncycastle/util/Memoable;Lcom/android/org/bouncycastle/crypto/digests/SHA1Digest;]Lcom/android/org/bouncycastle/crypto/params/KeyParameter;Lcom/android/org/bouncycastle/crypto/params/KeyParameter;
+HSPLcom/android/org/bouncycastle/crypto/macs/HMac;->update([BII)V+]Lcom/android/org/bouncycastle/crypto/Digest;Lcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest$SHA1;
+HSPLcom/android/org/bouncycastle/crypto/macs/HMac;->xorPad([BIB)V
+HSPLcom/android/org/bouncycastle/crypto/modes/CBCBlockCipher;-><init>(Lcom/android/org/bouncycastle/crypto/BlockCipher;)V
+HSPLcom/android/org/bouncycastle/crypto/modes/CBCBlockCipher;->getBlockSize()I
+HSPLcom/android/org/bouncycastle/crypto/modes/CBCBlockCipher;->init(ZLcom/android/org/bouncycastle/crypto/CipherParameters;)V
+HSPLcom/android/org/bouncycastle/crypto/modes/CBCBlockCipher;->reset()V
+HSPLcom/android/org/bouncycastle/crypto/paddings/PKCS7Padding;-><init>()V
+HSPLcom/android/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher;-><init>(Lcom/android/org/bouncycastle/crypto/BlockCipher;)V
+HSPLcom/android/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher;-><init>(Lcom/android/org/bouncycastle/crypto/BlockCipher;Lcom/android/org/bouncycastle/crypto/paddings/BlockCipherPadding;)V+]Lcom/android/org/bouncycastle/crypto/BlockCipher;megamorphic_types
+HSPLcom/android/org/bouncycastle/crypto/params/AsymmetricKeyParameter;-><init>(Z)V
+HSPLcom/android/org/bouncycastle/crypto/params/DSAKeyParameters;-><init>(ZLcom/android/org/bouncycastle/crypto/params/DSAParameters;)V
+HSPLcom/android/org/bouncycastle/crypto/params/DSAParameters;-><init>(Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;)V
+HSPLcom/android/org/bouncycastle/crypto/params/DSAParameters;->getP()Ljava/math/BigInteger;
+HSPLcom/android/org/bouncycastle/crypto/params/DSAParameters;->getQ()Ljava/math/BigInteger;
+HSPLcom/android/org/bouncycastle/crypto/params/DSAPublicKeyParameters;-><init>(Ljava/math/BigInteger;Lcom/android/org/bouncycastle/crypto/params/DSAParameters;)V
+HSPLcom/android/org/bouncycastle/crypto/params/DSAPublicKeyParameters;->validate(Ljava/math/BigInteger;Lcom/android/org/bouncycastle/crypto/params/DSAParameters;)Ljava/math/BigInteger;+]Ljava/math/BigInteger;Ljava/math/BigInteger;]Lcom/android/org/bouncycastle/crypto/params/DSAParameters;Lcom/android/org/bouncycastle/crypto/params/DSAParameters;
+HSPLcom/android/org/bouncycastle/crypto/params/KeyParameter;-><init>([B)V
+HSPLcom/android/org/bouncycastle/crypto/params/KeyParameter;-><init>([BII)V
+HSPLcom/android/org/bouncycastle/crypto/params/KeyParameter;->getKey()[B
+HSPLcom/android/org/bouncycastle/crypto/params/ParametersWithIV;-><init>(Lcom/android/org/bouncycastle/crypto/CipherParameters;[BII)V
+HSPLcom/android/org/bouncycastle/crypto/params/ParametersWithIV;->getIV()[B
+HSPLcom/android/org/bouncycastle/crypto/params/ParametersWithIV;->getParameters()Lcom/android/org/bouncycastle/crypto/CipherParameters;
+HSPLcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey;->getParams()Ljava/security/interfaces/DSAParams;
+HSPLcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey;->getY()Ljava/math/BigInteger;
+HSPLcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey;->hashCode()I+]Ljava/math/BigInteger;missing_types]Ljava/security/interfaces/DSAParams;missing_types]Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey;Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey;
+HSPLcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey;->readObject(Ljava/io/ObjectInputStream;)V+]Ljava/math/BigInteger;missing_types]Ljava/io/ObjectInputStream;missing_types
+HSPLcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil;->toDSAParameters(Ljava/security/interfaces/DSAParams;)Lcom/android/org/bouncycastle/crypto/params/DSAParameters;+]Ljava/security/interfaces/DSAParams;Ljava/security/spec/DSAParameterSpec;
+HSPLcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$Std;-><init>()V
+HSPLcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$StoreEntry;-><init>(Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi;Ljava/lang/String;Ljava/security/cert/Certificate;)V
+HSPLcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$StoreEntry;->getObject()Ljava/lang/Object;
+HSPLcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$StoreEntry;->getType()I
+HSPLcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi;-><init>(I)V
+HSPLcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi;->engineAliases()Ljava/util/Enumeration;
+HSPLcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi;->engineGetCertificate(Ljava/lang/String;)Ljava/security/cert/Certificate;
+HSPLcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi;->engineLoad(Ljava/io/InputStream;[C)V+]Lcom/android/org/bouncycastle/crypto/macs/HMac;Lcom/android/org/bouncycastle/crypto/macs/HMac;]Ljava/io/DataInputStream;Ljava/io/DataInputStream;]Ljava/util/Hashtable;Ljava/util/Hashtable;]Lcom/android/org/bouncycastle/crypto/PBEParametersGenerator;Lcom/android/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator;]Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi;Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$Std;
+HSPLcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi;->engineSetCertificateEntry(Ljava/lang/String;Ljava/security/cert/Certificate;)V+]Ljava/util/Hashtable;Ljava/util/Hashtable;]Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$StoreEntry;Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$StoreEntry;
+HSPLcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi;->engineSize()I
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/AES$ECB$1;-><init>()V
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/AES$ECB$1;->get()Lcom/android/org/bouncycastle/crypto/BlockCipher;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/AES$ECB;-><init>()V
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey;-><init>(Ljava/lang/String;Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;IIIILjavax/crypto/spec/PBEKeySpec;Lcom/android/org/bouncycastle/crypto/CipherParameters;)V+]Ljavax/crypto/spec/PBEKeySpec;Ljavax/crypto/spec/PBEKeySpec;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey;->getEncoded()[B+]Lcom/android/org/bouncycastle/crypto/params/KeyParameter;Lcom/android/org/bouncycastle/crypto/params/KeyParameter;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$BufferedGenericBlockCipher;-><init>(Lcom/android/org/bouncycastle/crypto/BlockCipher;)V
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$BufferedGenericBlockCipher;->doFinal([BI)I+]Lcom/android/org/bouncycastle/crypto/BufferedBlockCipher;Lcom/android/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$BufferedGenericBlockCipher;->getOutputSize(I)I+]Lcom/android/org/bouncycastle/crypto/BufferedBlockCipher;Lcom/android/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$BufferedGenericBlockCipher;->init(ZLcom/android/org/bouncycastle/crypto/CipherParameters;)V+]Lcom/android/org/bouncycastle/crypto/BufferedBlockCipher;Lcom/android/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$BufferedGenericBlockCipher;->processBytes([BII[BI)I+]Lcom/android/org/bouncycastle/crypto/BufferedBlockCipher;Lcom/android/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher;-><init>(Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BlockCipherProvider;)V+]Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BlockCipherProvider;Lcom/android/org/bouncycastle/jcajce/provider/symmetric/AES$ECB$1;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher;->engineDoFinal([BII)[B+]Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher;Lcom/android/org/bouncycastle/jcajce/provider/symmetric/AES$ECB;]Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$GenericBlockCipher;Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$BufferedGenericBlockCipher;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher;->engineGetOutputSize(I)I+]Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$GenericBlockCipher;Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$BufferedGenericBlockCipher;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher;->engineInit(ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)V+]Ljava/lang/String;missing_types]Lcom/android/org/bouncycastle/crypto/BlockCipher;Lcom/android/org/bouncycastle/crypto/engines/AESEngine;,Lcom/android/org/bouncycastle/crypto/engines/BlowfishEngine;]Ljava/security/Key;missing_types]Ljava/lang/Class;missing_types]Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$GenericBlockCipher;Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$BufferedGenericBlockCipher;]Ljavax/crypto/spec/IvParameterSpec;Ljavax/crypto/spec/IvParameterSpec;]Ljavax/crypto/SecretKey;Lcom/android/org/bouncycastle/jcajce/PKCS12Key;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseSecretKeyFactory;-><init>(Ljava/lang/String;Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;)V
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher;-><init>()V
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/PBE$Util;->convertPassword(ILjavax/crypto/spec/PBEKeySpec;)[B
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/PBE$Util;->makePBEGenerator(II)Lcom/android/org/bouncycastle/crypto/PBEParametersGenerator;
+HSPLcom/android/org/bouncycastle/jcajce/provider/symmetric/util/PBE$Util;->makePBEMacParameters(Ljavax/crypto/spec/PBEKeySpec;III)Lcom/android/org/bouncycastle/crypto/CipherParameters;+]Ljavax/crypto/spec/PBEKeySpec;Ljavax/crypto/spec/PBEKeySpec;]Lcom/android/org/bouncycastle/crypto/PBEParametersGenerator;Lcom/android/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator;
+HSPLcom/android/org/bouncycastle/jcajce/util/BCJcaJceHelper;-><init>()V
+HSPLcom/android/org/bouncycastle/jcajce/util/BCJcaJceHelper;->getBouncyCastleProvider()Ljava/security/Provider;
+HSPLcom/android/org/bouncycastle/jcajce/util/DefaultJcaJceHelper;-><init>()V
+HSPLcom/android/org/bouncycastle/jcajce/util/ProviderJcaJceHelper;-><init>(Ljava/security/Provider;)V
+HSPLcom/android/org/bouncycastle/jce/provider/CertStoreCollectionSpi;-><init>(Ljava/security/cert/CertStoreParameters;)V
+HSPLcom/android/org/bouncycastle/util/Arrays;->areEqual([B[B)Z
+HSPLcom/android/org/bouncycastle/util/Arrays;->clone([B)[B+][B[B
+HSPLcom/android/org/bouncycastle/util/Arrays;->fill([BB)V
+HSPLcom/android/org/bouncycastle/util/Arrays;->hashCode([B)I
+HSPLcom/android/org/bouncycastle/util/BigIntegers;-><clinit>()V
+HSPLcom/android/org/bouncycastle/util/Integers;->valueOf(I)Ljava/lang/Integer;
+HSPLcom/android/org/bouncycastle/util/Pack;->intToBigEndian(I[BI)V
+HSPLcom/android/org/bouncycastle/util/Properties$1;-><init>(Ljava/lang/String;)V
+HSPLcom/android/org/bouncycastle/util/Properties$1;->run()Ljava/lang/Object;
+HSPLcom/android/org/bouncycastle/util/Properties;->isOverrideSet(Ljava/lang/String;)Z
+HSPLcom/android/org/bouncycastle/util/Strings;->toUTF8ByteArray([C)[B+]Ljava/io/ByteArrayOutputStream;Ljava/io/ByteArrayOutputStream;
+HSPLcom/android/org/bouncycastle/util/Strings;->toUTF8ByteArray([CLjava/io/OutputStream;)V+]Ljava/io/OutputStream;Ljava/io/ByteArrayOutputStream;
+HSPLcom/android/org/bouncycastle/util/Strings;->toUpperCase(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLcom/android/org/bouncycastle/util/io/Streams;->readFully(Ljava/io/InputStream;[B)I
+HSPLcom/android/org/bouncycastle/util/io/Streams;->readFully(Ljava/io/InputStream;[BII)I+]Ljava/io/InputStream;Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;,Lcom/android/org/bouncycastle/asn1/ASN1InputStream;
+HSPLcom/android/org/kxml2/io/KXmlParser;-><init>()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->adjustNsp()Z+]Lcom/android/org/kxml2/io/KXmlParser;Lcom/android/org/kxml2/io/KXmlParser;]Ljava/lang/String;Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->close()V+]Ljava/io/Reader;missing_types
+HSPLcom/android/org/kxml2/io/KXmlParser;->ensureCapacity([Ljava/lang/String;I)[Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->fillBuffer(I)Z+]Ljava/io/Reader;missing_types
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeCount()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeName(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeValue(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeValue(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getColumnNumber()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getDepth()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getEventType()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getLineNumber()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getName()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getNamespace()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getNamespace(Ljava/lang/String;)Ljava/lang/String;+]Lcom/android/org/kxml2/io/KXmlParser;Lcom/android/org/kxml2/io/KXmlParser;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getNamespaceCount(I)I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getText()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->next()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->next(Z)I+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLcom/android/org/kxml2/io/KXmlParser;->nextTag()I+]Lcom/android/org/kxml2/io/KXmlParser;Lcom/android/org/kxml2/io/KXmlParser;
+HSPLcom/android/org/kxml2/io/KXmlParser;->nextToken()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->parseStartTag(ZZ)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->peekCharacter()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->peekType(Z)I
+HSPLcom/android/org/kxml2/io/KXmlParser;->read(C)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->read([C)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->readComment(Z)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readEndTag()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->readEntity(Ljava/lang/StringBuilder;ZZLcom/android/org/kxml2/io/KXmlParser$ValueContext;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readName()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Llibcore/internal/StringPool;Llibcore/internal/StringPool;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readUntil([CZ)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Llibcore/internal/StringPool;Llibcore/internal/StringPool;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readValue(CZZLcom/android/org/kxml2/io/KXmlParser$ValueContext;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Llibcore/internal/StringPool;Llibcore/internal/StringPool;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readXmlDeclaration()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->require(ILjava/lang/String;Ljava/lang/String;)V+]Lcom/android/org/kxml2/io/KXmlParser;Lcom/android/org/kxml2/io/KXmlParser;
+HSPLcom/android/org/kxml2/io/KXmlParser;->setFeature(Ljava/lang/String;Z)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->setInput(Ljava/io/InputStream;Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/io/InputStream;missing_types]Lcom/android/org/kxml2/io/KXmlParser;Lcom/android/org/kxml2/io/KXmlParser;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLcom/android/org/kxml2/io/KXmlParser;->setInput(Ljava/io/Reader;)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->skip()V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->append(C)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->append(Ljava/lang/String;)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->append(Ljava/lang/String;II)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->attribute(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->check(Z)V+]Lcom/android/org/kxml2/io/KXmlSerializer;Lcom/android/org/kxml2/io/KXmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->endDocument()V+]Lcom/android/org/kxml2/io/KXmlSerializer;Lcom/android/org/kxml2/io/KXmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->endTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->flush()V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->flushBuffer()V+]Ljava/io/Writer;Ljava/io/OutputStreamWriter;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->setOutput(Ljava/io/OutputStream;Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;]Lcom/android/org/kxml2/io/KXmlSerializer;Lcom/android/org/kxml2/io/KXmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->setOutput(Ljava/io/Writer;)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->startDocument(Ljava/lang/String;Ljava/lang/Boolean;)V+]Ljava/lang/Boolean;Ljava/lang/Boolean;]Ljava/lang/String;Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->startTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->writeEscaped(Ljava/lang/String;I)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLdalvik/system/AppSpecializationHooks;->handleCompatChangesBeforeBindingApplication()V
+HSPLdalvik/system/BaseDexClassLoader;-><init>(Ljava/lang/String;Ljava/io/File;Ljava/lang/String;Ljava/lang/ClassLoader;)V
+HSPLdalvik/system/BaseDexClassLoader;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;[Ljava/lang/ClassLoader;)V
+HSPLdalvik/system/BaseDexClassLoader;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;[Ljava/lang/ClassLoader;Z)V
+HSPLdalvik/system/BaseDexClassLoader;->addNativePath(Ljava/util/Collection;)V+]Ldalvik/system/DexPathList;Ldalvik/system/DexPathList;
+HSPLdalvik/system/BaseDexClassLoader;->findClass(Ljava/lang/String;)Ljava/lang/Class;+]Ldalvik/system/DexPathList;Ldalvik/system/DexPathList;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/lang/ClassLoader;Ldalvik/system/PathClassLoader;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;]Ljava/lang/ClassNotFoundException;Ljava/lang/ClassNotFoundException;
+HSPLdalvik/system/BaseDexClassLoader;->findLibrary(Ljava/lang/String;)Ljava/lang/String;+]Ldalvik/system/DexPathList;Ldalvik/system/DexPathList;
+HSPLdalvik/system/BaseDexClassLoader;->findResource(Ljava/lang/String;)Ljava/net/URL;+]Ldalvik/system/DexPathList;Ldalvik/system/DexPathList;]Ljava/lang/ClassLoader;Ldalvik/system/PathClassLoader;
+HSPLdalvik/system/BaseDexClassLoader;->findResources(Ljava/lang/String;)Ljava/util/Enumeration;+]Ldalvik/system/DexPathList;Ldalvik/system/DexPathList;
+HSPLdalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/List;Ljava/util/ArrayList;]Ldalvik/system/DexPathList;Ldalvik/system/DexPathList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLdalvik/system/BaseDexClassLoader;->getPackage(Ljava/lang/String;)Ljava/lang/Package;+]Ldalvik/system/BaseDexClassLoader;Ldalvik/system/PathClassLoader;
+HSPLdalvik/system/BaseDexClassLoader;->reportClassLoaderChain()V
+HSPLdalvik/system/BaseDexClassLoader;->setReporter(Ldalvik/system/BaseDexClassLoader$Reporter;)V
+HSPLdalvik/system/BaseDexClassLoader;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Object;Ldalvik/system/PathClassLoader;,Ldalvik/system/DelegateLastClassLoader;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLdalvik/system/BlockGuard$1;->onExplicitGc()V
+HSPLdalvik/system/BlockGuard$1;->onNetwork()V
+HSPLdalvik/system/BlockGuard$1;->onReadFromDisk()V
+HSPLdalvik/system/BlockGuard$1;->onUnbufferedIO()V
+HSPLdalvik/system/BlockGuard$1;->onWriteToDisk()V
+HSPLdalvik/system/BlockGuard$2;->onPathAccess(Ljava/lang/String;)V
+HSPLdalvik/system/BlockGuard$3;->initialValue()Ldalvik/system/BlockGuard$Policy;
+HSPLdalvik/system/BlockGuard$3;->initialValue()Ljava/lang/Object;+]Ldalvik/system/BlockGuard$3;Ldalvik/system/BlockGuard$3;
+HSPLdalvik/system/BlockGuard;->getThreadPolicy()Ldalvik/system/BlockGuard$Policy;+]Ljava/lang/ThreadLocal;Ldalvik/system/BlockGuard$3;
+HSPLdalvik/system/BlockGuard;->getVmPolicy()Ldalvik/system/BlockGuard$VmPolicy;
+HSPLdalvik/system/BlockGuard;->setThreadPolicy(Ldalvik/system/BlockGuard$Policy;)V+]Ljava/lang/ThreadLocal;Ldalvik/system/BlockGuard$3;
+HSPLdalvik/system/BlockGuard;->setVmPolicy(Ldalvik/system/BlockGuard$VmPolicy;)V
+HSPLdalvik/system/CloseGuard;-><init>()V
+HSPLdalvik/system/CloseGuard;->close()V
+HSPLdalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard;
+HSPLdalvik/system/CloseGuard;->getReporter()Ldalvik/system/CloseGuard$Reporter;
+HSPLdalvik/system/CloseGuard;->open(Ljava/lang/String;)V+]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
+HSPLdalvik/system/CloseGuard;->openWithCallSite(Ljava/lang/String;Ljava/lang/String;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLdalvik/system/CloseGuard;->setEnabled(Z)V
+HSPLdalvik/system/CloseGuard;->setReporter(Ldalvik/system/CloseGuard$Reporter;)V
+HSPLdalvik/system/CloseGuard;->warnIfOpen()V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ldalvik/system/CloseGuard$Reporter;Landroid/os/StrictMode$AndroidCloseGuardReporter;
+HSPLdalvik/system/DelegateLastClassLoader;-><init>(Ljava/lang/String;Ljava/lang/ClassLoader;)V
+HSPLdalvik/system/DelegateLastClassLoader;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;Z)V
+HSPLdalvik/system/DelegateLastClassLoader;->loadClass(Ljava/lang/String;Z)Ljava/lang/Class;+]Ldalvik/system/DelegateLastClassLoader;Ldalvik/system/DelegateLastClassLoader;
+HSPLdalvik/system/DexClassLoader;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V
+HSPLdalvik/system/DexFile;-><init>(Ljava/io/File;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)V
+HSPLdalvik/system/DexFile;-><init>(Ljava/lang/String;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)V
+HSPLdalvik/system/DexFile;->defineClass(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/Object;Ldalvik/system/DexFile;Ljava/util/List;)Ljava/lang/Class;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLdalvik/system/DexFile;->finalize()V
+HSPLdalvik/system/DexFile;->isBackedByOatFile()Z
+HSPLdalvik/system/DexFile;->loadClassBinaryName(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/util/List;)Ljava/lang/Class;
+HSPLdalvik/system/DexFile;->openDexFile(Ljava/lang/String;Ljava/lang/String;ILjava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ljava/lang/Object;
+HSPLdalvik/system/DexFile;->verifyInBackground(Ljava/lang/ClassLoader;)V
+HSPLdalvik/system/DexPathList$Element;-><init>(Ldalvik/system/DexFile;Ljava/io/File;)V
+HSPLdalvik/system/DexPathList$Element;-><init>(Ljava/io/File;)V
+HSPLdalvik/system/DexPathList$Element;->access$000(Ldalvik/system/DexPathList$Element;)Ldalvik/system/DexFile;
+HSPLdalvik/system/DexPathList$Element;->findClass(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/util/List;)Ljava/lang/Class;+]Ldalvik/system/DexFile;Ldalvik/system/DexFile;
+HSPLdalvik/system/DexPathList$Element;->findResource(Ljava/lang/String;)Ljava/net/URL;+]Ldalvik/system/DexPathList$Element;Ldalvik/system/DexPathList$Element;]Llibcore/io/ClassPathURLStreamHandler;Llibcore/io/ClassPathURLStreamHandler;]Ljava/io/File;Ljava/io/File;
+HSPLdalvik/system/DexPathList$Element;->maybeInit()V
+HSPLdalvik/system/DexPathList$Element;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLdalvik/system/DexPathList$NativeLibraryElement;-><init>(Ljava/io/File;)V
+HSPLdalvik/system/DexPathList$NativeLibraryElement;-><init>(Ljava/io/File;Ljava/lang/String;)V
+HSPLdalvik/system/DexPathList$NativeLibraryElement;->equals(Ljava/lang/Object;)Z
+HSPLdalvik/system/DexPathList$NativeLibraryElement;->findNativeLibrary(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/io/File;Ljava/io/File;]Ldalvik/system/DexPathList$NativeLibraryElement;Ldalvik/system/DexPathList$NativeLibraryElement;]Llibcore/io/ClassPathURLStreamHandler;Llibcore/io/ClassPathURLStreamHandler;
+HSPLdalvik/system/DexPathList$NativeLibraryElement;->maybeInit()V
+HSPLdalvik/system/DexPathList;-><init>(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;Ljava/io/File;Z)V
+HSPLdalvik/system/DexPathList;->addNativePath(Ljava/util/Collection;)V+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/Collection;Ljava/util/ArrayList;]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLdalvik/system/DexPathList;->findClass(Ljava/lang/String;Ljava/util/List;)Ljava/lang/Class;+]Ljava/util/List;Ljava/util/ArrayList;]Ldalvik/system/DexPathList$Element;Ldalvik/system/DexPathList$Element;
+HSPLdalvik/system/DexPathList;->findLibrary(Ljava/lang/String;)Ljava/lang/String;+]Ldalvik/system/DexPathList$NativeLibraryElement;Ldalvik/system/DexPathList$NativeLibraryElement;
+HSPLdalvik/system/DexPathList;->findResource(Ljava/lang/String;)Ljava/net/URL;+]Ldalvik/system/DexPathList$Element;Ldalvik/system/DexPathList$Element;
+HSPLdalvik/system/DexPathList;->findResources(Ljava/lang/String;)Ljava/util/Enumeration;+]Ldalvik/system/DexPathList$Element;Ldalvik/system/DexPathList$Element;
+HSPLdalvik/system/DexPathList;->getAllNativeLibraryDirectories()Ljava/util/List;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLdalvik/system/DexPathList;->getNativeLibraryDirectories()Ljava/util/List;
+HSPLdalvik/system/DexPathList;->loadDexFile(Ljava/io/File;Ljava/io/File;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ldalvik/system/DexFile;
+HSPLdalvik/system/DexPathList;->makeDexElements(Ljava/util/List;Ljava/io/File;Ljava/util/List;Ljava/lang/ClassLoader;Z)[Ldalvik/system/DexPathList$Element;
+HSPLdalvik/system/DexPathList;->makePathElements(Ljava/util/List;)[Ldalvik/system/DexPathList$NativeLibraryElement;+]Ljava/lang/String;Ljava/lang/String;]Ljava/io/File;Ljava/io/File;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLdalvik/system/DexPathList;->maybeRunBackgroundVerification(Ljava/lang/ClassLoader;)V
+HSPLdalvik/system/DexPathList;->splitDexPath(Ljava/lang/String;)Ljava/util/List;
+HSPLdalvik/system/DexPathList;->splitPaths(Ljava/lang/String;Z)Ljava/util/List;+]Ljava/lang/String;Ljava/lang/String;]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;]Ljava/util/List;Ljava/util/ArrayList;
+HSPLdalvik/system/DexPathList;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/List;Ljava/util/ArrayList;
+HSPLdalvik/system/PathClassLoader;-><init>(Ljava/lang/String;Ljava/lang/ClassLoader;)V
+HSPLdalvik/system/PathClassLoader;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V
+HSPLdalvik/system/PathClassLoader;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;[Ljava/lang/ClassLoader;)V
+HSPLdalvik/system/RuntimeHooks;->getTimeZoneIdSupplier()Ljava/util/function/Supplier;
+HSPLdalvik/system/RuntimeHooks;->setTimeZoneIdSupplier(Ljava/util/function/Supplier;)V
+HSPLdalvik/system/RuntimeHooks;->setUncaughtExceptionPreHandler(Ljava/lang/Thread$UncaughtExceptionHandler;)V
+HSPLdalvik/system/SocketTagger;-><init>()V
+HSPLdalvik/system/SocketTagger;->get()Ldalvik/system/SocketTagger;
+HSPLdalvik/system/SocketTagger;->set(Ldalvik/system/SocketTagger;)V
+HSPLdalvik/system/SocketTagger;->tag(Ljava/net/Socket;)V
+HSPLdalvik/system/SocketTagger;->untag(Ljava/net/Socket;)V
+HSPLdalvik/system/VMRuntime;->getInstructionSet(Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLdalvik/system/VMRuntime;->getRuntime()Ldalvik/system/VMRuntime;
+HSPLdalvik/system/VMRuntime;->getTargetSdkVersion()I
+HSPLdalvik/system/VMRuntime;->hiddenApiUsed(ILjava/lang/String;Ljava/lang/String;IZ)V
+HSPLdalvik/system/VMRuntime;->notifyNativeAllocation()V+]Ldalvik/system/VMRuntime;Ldalvik/system/VMRuntime;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLdalvik/system/VMRuntime;->registerNativeAllocation(I)V+]Ldalvik/system/VMRuntime;Ldalvik/system/VMRuntime;
+HSPLdalvik/system/VMRuntime;->registerNativeFree(I)V+]Ldalvik/system/VMRuntime;Ldalvik/system/VMRuntime;
+HSPLdalvik/system/VMRuntime;->runFinalization(J)V
+HSPLdalvik/system/VMRuntime;->runFinalizationSync()V
+HSPLdalvik/system/VMRuntime;->setDisabledCompatChanges([J)V
+HSPLdalvik/system/VMRuntime;->setHiddenApiUsageLogger(Ldalvik/system/VMRuntime$HiddenApiUsageLogger;)V
+HSPLdalvik/system/VMRuntime;->setNonSdkApiUsageConsumer(Ljava/util/function/Consumer;)V
+HSPLdalvik/system/VMRuntime;->setTargetSdkVersion(I)V
+HSPLdalvik/system/ZygoteHooks;->gcAndFinalize()V
+HSPLdalvik/system/ZygoteHooks;->isIndefiniteThreadSuspensionSafe()Z
+HSPLdalvik/system/ZygoteHooks;->onEndPreload()V
+HSPLdalvik/system/ZygoteHooks;->postForkChild(IZZLjava/lang/String;)V
+HSPLdalvik/system/ZygoteHooks;->postForkCommon()V
+HSPLdalvik/system/ZygoteHooks;->preFork()V
+HSPLdalvik/system/ZygoteHooks;->waitUntilAllThreadsStopped()V
+HSPLjava/io/Bits;->getBoolean([BI)Z
+HSPLjava/io/Bits;->getDouble([BI)D
+HSPLjava/io/Bits;->getFloat([BI)F
+HSPLjava/io/Bits;->getInt([BI)I
+HSPLjava/io/Bits;->getLong([BI)J
+HSPLjava/io/Bits;->getShort([BI)S
+HSPLjava/io/Bits;->putBoolean([BIZ)V
+HSPLjava/io/Bits;->putDouble([BID)V
+HSPLjava/io/Bits;->putFloat([BIF)V
+HSPLjava/io/Bits;->putInt([BII)V
+HSPLjava/io/Bits;->putLong([BIJ)V
+HSPLjava/io/Bits;->putShort([BIS)V
+HSPLjava/io/BufferedInputStream;-><init>(Ljava/io/InputStream;)V
+HSPLjava/io/BufferedInputStream;-><init>(Ljava/io/InputStream;I)V
+HSPLjava/io/BufferedInputStream;->available()I+]Ljava/io/InputStream;megamorphic_types
+HSPLjava/io/BufferedInputStream;->close()V+]Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;]Ljava/io/InputStream;missing_types
+HSPLjava/io/BufferedInputStream;->fill()V+]Ljava/io/InputStream;missing_types]Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;
+HSPLjava/io/BufferedInputStream;->getBufIfOpen()[B
+HSPLjava/io/BufferedInputStream;->getInIfOpen()Ljava/io/InputStream;
+HSPLjava/io/BufferedInputStream;->mark(I)V
+HSPLjava/io/BufferedInputStream;->markSupported()Z
+HSPLjava/io/BufferedInputStream;->read()I
+HSPLjava/io/BufferedInputStream;->read([BII)I+]Ljava/io/InputStream;missing_types
+HSPLjava/io/BufferedInputStream;->read1([BII)I+]Ljava/io/InputStream;megamorphic_types
+HSPLjava/io/BufferedInputStream;->reset()V
+HSPLjava/io/BufferedInputStream;->skip(J)J+]Ljava/io/InputStream;missing_types
+HSPLjava/io/BufferedOutputStream;-><init>(Ljava/io/OutputStream;)V
+HSPLjava/io/BufferedOutputStream;-><init>(Ljava/io/OutputStream;I)V
+HSPLjava/io/BufferedOutputStream;->flush()V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/BufferedOutputStream;->flushBuffer()V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/BufferedOutputStream;->write(I)V
+HSPLjava/io/BufferedOutputStream;->write([BII)V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/BufferedReader;-><init>(Ljava/io/Reader;)V
+HSPLjava/io/BufferedReader;-><init>(Ljava/io/Reader;I)V
+HSPLjava/io/BufferedReader;->close()V+]Ljava/io/Reader;missing_types
+HSPLjava/io/BufferedReader;->ensureOpen()V
+HSPLjava/io/BufferedReader;->fill()V+]Ljava/io/Reader;Ljava/io/StringReader;,Ljava/io/InputStreamReader;,Ljava/io/FileReader;
+HSPLjava/io/BufferedReader;->read()I
+HSPLjava/io/BufferedReader;->read([CII)I+]Ljava/io/Reader;missing_types
+HSPLjava/io/BufferedReader;->read1([CII)I+]Ljava/io/Reader;Ljava/io/InputStreamReader;,Ljava/io/FileReader;
+HSPLjava/io/BufferedReader;->readLine()Ljava/lang/String;+]Ljava/io/BufferedReader;Ljava/io/BufferedReader;
+HSPLjava/io/BufferedReader;->readLine(Z)Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/io/BufferedWriter;-><init>(Ljava/io/Writer;)V
+HSPLjava/io/BufferedWriter;-><init>(Ljava/io/Writer;I)V
+HSPLjava/io/BufferedWriter;->close()V+]Ljava/io/Writer;Ljava/io/OutputStreamWriter;,Ljava/io/FileWriter;]Ljava/io/BufferedWriter;Ljava/io/BufferedWriter;
+HSPLjava/io/BufferedWriter;->ensureOpen()V
+HSPLjava/io/BufferedWriter;->flush()V+]Ljava/io/Writer;Ljava/io/OutputStreamWriter;,Ljava/io/FileWriter;,Ljava/io/PrintWriter;,Ljava/io/StringWriter;]Ljava/io/BufferedWriter;Ljava/io/BufferedWriter;
+HSPLjava/io/BufferedWriter;->flushBuffer()V+]Ljava/io/Writer;missing_types
+HSPLjava/io/BufferedWriter;->min(II)I
+HSPLjava/io/BufferedWriter;->newLine()V+]Ljava/io/BufferedWriter;Ljava/io/BufferedWriter;
+HSPLjava/io/BufferedWriter;->write(I)V+]Ljava/io/BufferedWriter;Ljava/io/BufferedWriter;
+HSPLjava/io/BufferedWriter;->write(Ljava/lang/String;II)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/io/BufferedWriter;Ljava/io/BufferedWriter;
+HSPLjava/io/BufferedWriter;->write([CII)V+]Ljava/io/Writer;Ljava/io/FileWriter;]Ljava/io/BufferedWriter;Ljava/io/BufferedWriter;
+HSPLjava/io/ByteArrayInputStream;-><init>([B)V
+HSPLjava/io/ByteArrayInputStream;-><init>([BII)V
+HSPLjava/io/ByteArrayInputStream;->available()I
+HSPLjava/io/ByteArrayInputStream;->close()V
+HSPLjava/io/ByteArrayInputStream;->mark(I)V
+HSPLjava/io/ByteArrayInputStream;->markSupported()Z
+HSPLjava/io/ByteArrayInputStream;->read()I
+HSPLjava/io/ByteArrayInputStream;->read([BII)I
+HSPLjava/io/ByteArrayInputStream;->reset()V
+HSPLjava/io/ByteArrayInputStream;->skip(J)J
+HSPLjava/io/ByteArrayOutputStream;-><init>()V
+HSPLjava/io/ByteArrayOutputStream;-><init>(I)V
+HSPLjava/io/ByteArrayOutputStream;->close()V
+HSPLjava/io/ByteArrayOutputStream;->ensureCapacity(I)V
+HSPLjava/io/ByteArrayOutputStream;->grow(I)V
+HSPLjava/io/ByteArrayOutputStream;->reset()V
+HSPLjava/io/ByteArrayOutputStream;->size()I
+HSPLjava/io/ByteArrayOutputStream;->toByteArray()[B
+HSPLjava/io/ByteArrayOutputStream;->toString()Ljava/lang/String;
+HSPLjava/io/ByteArrayOutputStream;->toString(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/io/ByteArrayOutputStream;->write(I)V
+HSPLjava/io/ByteArrayOutputStream;->write([BII)V
+HSPLjava/io/ByteArrayOutputStream;->writeTo(Ljava/io/OutputStream;)V+]Ljava/io/OutputStream;Ljava/io/FileOutputStream;,Ljava/io/ByteArrayOutputStream;,Ljava/io/DataOutputStream;
+HSPLjava/io/CharArrayWriter;-><init>()V
+HSPLjava/io/CharArrayWriter;-><init>(I)V
+HSPLjava/io/CharArrayWriter;->flush()V
+HSPLjava/io/CharArrayWriter;->reset()V
+HSPLjava/io/CharArrayWriter;->toCharArray()[C
+HSPLjava/io/CharArrayWriter;->toString()Ljava/lang/String;
+HSPLjava/io/CharArrayWriter;->write(I)V
+HSPLjava/io/CharArrayWriter;->write([CII)V
+HSPLjava/io/DataInputStream;-><init>(Ljava/io/InputStream;)V
+HSPLjava/io/DataInputStream;->read([B)I+]Ljava/io/InputStream;missing_types
+HSPLjava/io/DataInputStream;->read([BII)I+]Ljava/io/InputStream;megamorphic_types
+HSPLjava/io/DataInputStream;->readBoolean()Z+]Ljava/io/InputStream;missing_types
+HSPLjava/io/DataInputStream;->readByte()B+]Ljava/io/InputStream;missing_types
+HSPLjava/io/DataInputStream;->readFully([B)V+]Ljava/io/DataInputStream;missing_types
+HSPLjava/io/DataInputStream;->readFully([BII)V+]Ljava/io/InputStream;megamorphic_types
+HSPLjava/io/DataInputStream;->readInt()I+]Ljava/io/DataInputStream;missing_types
+HSPLjava/io/DataInputStream;->readLong()J+]Ljava/io/DataInputStream;missing_types
+HSPLjava/io/DataInputStream;->readShort()S+]Ljava/io/DataInputStream;Ljava/io/DataInputStream;
+HSPLjava/io/DataInputStream;->readUTF()Ljava/lang/String;
+HSPLjava/io/DataInputStream;->readUTF(Ljava/io/DataInput;)Ljava/lang/String;+]Ljava/io/DataInput;missing_types
+HSPLjava/io/DataInputStream;->readUnsignedByte()I+]Ljava/io/InputStream;missing_types
+HSPLjava/io/DataInputStream;->readUnsignedShort()I+]Ljava/io/DataInputStream;missing_types
+HSPLjava/io/DataInputStream;->skipBytes(I)I+]Ljava/io/InputStream;Ljava/io/BufferedInputStream;,Ljava/io/ByteArrayInputStream;,Ljava/io/FileInputStream;
+HSPLjava/io/DataOutputStream;-><init>(Ljava/io/OutputStream;)V
+HSPLjava/io/DataOutputStream;->flush()V+]Ljava/io/OutputStream;megamorphic_types
+HSPLjava/io/DataOutputStream;->incCount(I)V
+HSPLjava/io/DataOutputStream;->write(I)V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/DataOutputStream;->write([BII)V+]Ljava/io/OutputStream;megamorphic_types
+HSPLjava/io/DataOutputStream;->writeBoolean(Z)V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/DataOutputStream;->writeByte(I)V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/DataOutputStream;->writeInt(I)V+]Ljava/io/OutputStream;megamorphic_types
+HSPLjava/io/DataOutputStream;->writeLong(J)V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/DataOutputStream;->writeShort(I)V+]Ljava/io/OutputStream;megamorphic_types
+HSPLjava/io/DataOutputStream;->writeUTF(Ljava/lang/String;)V
+HSPLjava/io/DataOutputStream;->writeUTF(Ljava/lang/String;Ljava/io/DataOutput;)I+]Ljava/io/DataOutput;missing_types
+HSPLjava/io/EOFException;-><init>()V
+HSPLjava/io/EOFException;-><init>(Ljava/lang/String;)V
+HSPLjava/io/ExpiringCache;->clear()V+]Ljava/util/Map;Ljava/io/ExpiringCache$1;
+HSPLjava/io/File$TempDirectory;->generateFile(Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)Ljava/io/File;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/io/File;Ljava/io/File;
+HSPLjava/io/File;-><init>(Ljava/io/File;Ljava/lang/String;)V+]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;-><init>(Ljava/lang/String;)V+]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;-><init>(Ljava/lang/String;I)V
+HSPLjava/io/File;-><init>(Ljava/lang/String;Ljava/io/File;)V+]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;-><init>(Ljava/lang/String;Ljava/lang/String;)V+]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->canExecute()Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->canRead()Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->canWrite()Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->compareTo(Ljava/io/File;)I+]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->compareTo(Ljava/lang/Object;)I+]Ljava/io/File;Ljava/io/File;
+HSPLjava/io/File;->createNewFile()Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->createTempFile(Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)Ljava/io/File;
+HSPLjava/io/File;->delete()Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->equals(Ljava/lang/Object;)Z+]Ljava/io/File;missing_types
+HSPLjava/io/File;->exists()Z+]Ljava/io/File;missing_types]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->getAbsoluteFile()Ljava/io/File;+]Ljava/io/File;missing_types]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->getAbsolutePath()Ljava/lang/String;+]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->getCanonicalFile()Ljava/io/File;+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->getCanonicalPath()Ljava/lang/String;+]Ljava/io/File;missing_types]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->getFreeSpace()J+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->getName()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/io/File;->getParent()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/io/File;->getParentFile()Ljava/io/File;+]Ljava/io/File;missing_types
+HSPLjava/io/File;->getPath()Ljava/lang/String;
+HSPLjava/io/File;->getPrefixLength()I
+HSPLjava/io/File;->getTotalSpace()J+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->getUsableSpace()J+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->hashCode()I+]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->isAbsolute()Z+]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->isDirectory()Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->isFile()Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->isInvalid()Z
+HSPLjava/io/File;->lastModified()J+]Ljava/io/File;missing_types]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->length()J+]Ljava/io/File;missing_types]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->list()[Ljava/lang/String;+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->list(Ljava/io/FilenameFilter;)[Ljava/lang/String;+]Ljava/io/File;Ljava/io/File;]Ljava/util/List;Ljava/util/ArrayList;
+HSPLjava/io/File;->listFiles()[Ljava/io/File;+]Ljava/io/File;Ljava/io/File;
+HSPLjava/io/File;->listFiles(Ljava/io/FileFilter;)[Ljava/io/File;+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileFilter;missing_types]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/io/File;->listFiles(Ljava/io/FilenameFilter;)[Ljava/io/File;+]Ljava/io/File;Ljava/io/File;]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/io/FilenameFilter;Landroid/app/ContextImpl$1;,Landroid/media/ThumbnailUtils$$ExternalSyntheticLambda0;
+HSPLjava/io/File;->mkdir()Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->mkdirs()Z+]Ljava/io/File;Ljava/io/File;
+HSPLjava/io/File;->renameTo(Ljava/io/File;)Z+]Ljava/io/File;missing_types]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->setExecutable(Z)Z+]Ljava/io/File;Ljava/io/File;
+HSPLjava/io/File;->setExecutable(ZZ)Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->setLastModified(J)Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->setReadable(ZZ)Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->setWritable(Z)Z+]Ljava/io/File;Ljava/io/File;
+HSPLjava/io/File;->setWritable(ZZ)Z+]Ljava/io/File;Ljava/io/File;]Ljava/io/FileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/File;->slashify(Ljava/lang/String;Z)Ljava/lang/String;
+HSPLjava/io/File;->toPath()Ljava/nio/file/Path;+]Ljava/nio/file/FileSystem;Lsun/nio/fs/LinuxFileSystem;
+HSPLjava/io/File;->toString()Ljava/lang/String;+]Ljava/io/File;Ljava/io/File;
+HSPLjava/io/File;->toURI()Ljava/net/URI;+]Ljava/lang/String;Ljava/lang/String;]Ljava/io/File;Ljava/io/File;
+HSPLjava/io/FileDescriptor$1;->set(Ljava/io/FileDescriptor;I)V
+HSPLjava/io/FileDescriptor;-><init>()V
+HSPLjava/io/FileDescriptor;->access$002(Ljava/io/FileDescriptor;I)I
+HSPLjava/io/FileDescriptor;->cloneForFork()V
+HSPLjava/io/FileDescriptor;->getInt$()I
+HSPLjava/io/FileDescriptor;->getOwnerId$()J
+HSPLjava/io/FileDescriptor;->isSocket$()Z
+HSPLjava/io/FileDescriptor;->release$()Ljava/io/FileDescriptor;
+HSPLjava/io/FileDescriptor;->setInt$(I)V
+HSPLjava/io/FileDescriptor;->setOwnerId$(J)V
+HSPLjava/io/FileDescriptor;->valid()Z
+HSPLjava/io/FileInputStream;-><init>(Ljava/io/File;)V+]Ljava/io/File;missing_types]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/io/FileInputStream;-><init>(Ljava/io/FileDescriptor;)V
+HSPLjava/io/FileInputStream;-><init>(Ljava/io/FileDescriptor;Z)V
+HSPLjava/io/FileInputStream;-><init>(Ljava/lang/String;)V
+HSPLjava/io/FileInputStream;->available()I
+HSPLjava/io/FileInputStream;->close()V+]Ljava/nio/channels/FileChannel;Lsun/nio/ch/FileChannelImpl;]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/io/FileInputStream;->finalize()V+]Ljava/io/FileInputStream;missing_types]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/io/FileInputStream;->getChannel()Ljava/nio/channels/FileChannel;
+HSPLjava/io/FileInputStream;->getFD()Ljava/io/FileDescriptor;
+HSPLjava/io/FileInputStream;->read()I+]Ljava/io/FileInputStream;missing_types
+HSPLjava/io/FileInputStream;->read([B)I+]Ljava/io/FileInputStream;missing_types
+HSPLjava/io/FileInputStream;->read([BII)I+]Llibcore/io/IoTracker;missing_types
+HSPLjava/io/FileInputStream;->skip(J)J+]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLjava/io/FileNotFoundException;-><init>(Ljava/lang/String;)V
+HSPLjava/io/FileOutputStream;-><init>(Ljava/io/File;)V
+HSPLjava/io/FileOutputStream;-><init>(Ljava/io/File;Z)V+]Ljava/io/File;missing_types]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/io/FileOutputStream;-><init>(Ljava/io/FileDescriptor;)V
+HSPLjava/io/FileOutputStream;-><init>(Ljava/io/FileDescriptor;Z)V
+HSPLjava/io/FileOutputStream;-><init>(Ljava/lang/String;)V
+HSPLjava/io/FileOutputStream;-><init>(Ljava/lang/String;Z)V
+HSPLjava/io/FileOutputStream;->close()V+]Ljava/nio/channels/FileChannel;Lsun/nio/ch/FileChannelImpl;]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/io/FileOutputStream;->finalize()V+]Ldalvik/system/CloseGuard;missing_types]Ljava/io/FileOutputStream;missing_types
+HSPLjava/io/FileOutputStream;->getChannel()Ljava/nio/channels/FileChannel;
+HSPLjava/io/FileOutputStream;->getFD()Ljava/io/FileDescriptor;
+HSPLjava/io/FileOutputStream;->write(I)V+]Ljava/io/FileOutputStream;Ljava/io/FileOutputStream;,Landroid/os/ParcelFileDescriptor$AutoCloseOutputStream;
+HSPLjava/io/FileOutputStream;->write([B)V+]Ljava/io/FileOutputStream;missing_types
+HSPLjava/io/FileOutputStream;->write([BII)V+]Llibcore/io/IoTracker;missing_types
+HSPLjava/io/FileReader;-><init>(Ljava/io/File;)V
+HSPLjava/io/FileReader;-><init>(Ljava/lang/String;)V
+HSPLjava/io/FileWriter;-><init>(Ljava/io/File;)V
+HSPLjava/io/FileWriter;-><init>(Ljava/io/File;Z)V
+HSPLjava/io/FilterInputStream;-><init>(Ljava/io/InputStream;)V
+HSPLjava/io/FilterInputStream;->available()I+]Ljava/io/InputStream;missing_types
+HSPLjava/io/FilterInputStream;->close()V+]Ljava/io/InputStream;megamorphic_types
+HSPLjava/io/FilterInputStream;->mark(I)V+]Ljava/io/InputStream;missing_types
+HSPLjava/io/FilterInputStream;->read()I+]Ljava/io/InputStream;megamorphic_types
+HSPLjava/io/FilterInputStream;->read([B)I+]Ljava/io/FilterInputStream;megamorphic_types
+HSPLjava/io/FilterInputStream;->read([BII)I+]Ljava/io/InputStream;megamorphic_types
+HSPLjava/io/FilterInputStream;->reset()V+]Ljava/io/InputStream;missing_types
+HSPLjava/io/FilterInputStream;->skip(J)J+]Ljava/io/InputStream;Ljava/io/BufferedInputStream;,Ljava/io/ByteArrayInputStream;,Landroid/os/ParcelFileDescriptor$AutoCloseInputStream;,Ljavax/crypto/CipherInputStream;
+HSPLjava/io/FilterOutputStream;-><init>(Ljava/io/OutputStream;)V
+HSPLjava/io/FilterOutputStream;->close()V+]Ljava/io/OutputStream;megamorphic_types]Ljava/io/FilterOutputStream;missing_types]Ljava/lang/Throwable;Ljava/io/IOException;
+HSPLjava/io/FilterOutputStream;->flush()V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/FilterOutputStream;->write([B)V+]Ljava/io/FilterOutputStream;megamorphic_types
+HSPLjava/io/FilterReader;-><init>(Ljava/io/Reader;)V
+HSPLjava/io/FilterReader;->read()I+]Ljava/io/Reader;Ljava/io/BufferedReader;
+HSPLjava/io/IOException;-><init>()V
+HSPLjava/io/IOException;-><init>(Ljava/lang/String;)V
+HSPLjava/io/IOException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+HSPLjava/io/IOException;-><init>(Ljava/lang/Throwable;)V
+HSPLjava/io/InputStream;-><init>()V
+HSPLjava/io/InputStream;->available()I
+HSPLjava/io/InputStream;->close()V
+HSPLjava/io/InputStream;->markSupported()Z
+HSPLjava/io/InputStream;->read([B)I+]Ljava/io/InputStream;megamorphic_types
+HSPLjava/io/InputStream;->read([BII)I+]Ljava/io/InputStream;missing_types
+HSPLjava/io/InputStreamReader;-><init>(Ljava/io/InputStream;)V
+HSPLjava/io/InputStreamReader;-><init>(Ljava/io/InputStream;Ljava/lang/String;)V
+HSPLjava/io/InputStreamReader;-><init>(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
+HSPLjava/io/InputStreamReader;-><init>(Ljava/io/InputStream;Ljava/nio/charset/CharsetDecoder;)V
+HSPLjava/io/InputStreamReader;->close()V+]Lsun/nio/cs/StreamDecoder;Lsun/nio/cs/StreamDecoder;
+HSPLjava/io/InputStreamReader;->read()I+]Lsun/nio/cs/StreamDecoder;Lsun/nio/cs/StreamDecoder;
+HSPLjava/io/InputStreamReader;->read([CII)I+]Lsun/nio/cs/StreamDecoder;Lsun/nio/cs/StreamDecoder;
+HSPLjava/io/InputStreamReader;->ready()Z+]Lsun/nio/cs/StreamDecoder;Lsun/nio/cs/StreamDecoder;
+HSPLjava/io/InterruptedIOException;-><init>()V
+HSPLjava/io/InterruptedIOException;-><init>(Ljava/lang/String;)V
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;-><init>(Ljava/io/ObjectInputStream;Ljava/io/InputStream;)V
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->close()V+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->currentBlockRemaining()I
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->getBlockDataMode()Z
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->peek()I+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->peekByte()B+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->read()I+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->read([BII)I+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->read([BIIZ)I+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readBlockHeader(Z)I+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readBoolean()Z+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readByte()B+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readFloat()F
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readFully([BIIZ)V+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readInt()I+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;]Ljava/io/DataInputStream;Ljava/io/DataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readLong()J+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;]Ljava/io/DataInputStream;Ljava/io/DataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readShort()S+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;]Ljava/io/DataInputStream;Ljava/io/DataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readUTF()Ljava/lang/String;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readUTFBody(J)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readUTFChar(Ljava/lang/StringBuilder;J)I+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readUTFSpan(Ljava/lang/StringBuilder;J)J+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->readUnsignedShort()I+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;]Ljava/io/DataInputStream;Ljava/io/DataInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->refill()V+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->setBlockDataMode(Z)Z
+HSPLjava/io/ObjectInputStream$BlockDataInputStream;->skipBlockData()V
+HSPLjava/io/ObjectInputStream$GetField;-><init>()V
+HSPLjava/io/ObjectInputStream$GetFieldImpl;-><init>(Ljava/io/ObjectInputStream;Ljava/io/ObjectStreamClass;)V+]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;
+HSPLjava/io/ObjectInputStream$GetFieldImpl;->get(Ljava/lang/String;I)I
+HSPLjava/io/ObjectInputStream$GetFieldImpl;->get(Ljava/lang/String;J)J
+HSPLjava/io/ObjectInputStream$GetFieldImpl;->get(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;
+HSPLjava/io/ObjectInputStream$GetFieldImpl;->get(Ljava/lang/String;Z)Z
+HSPLjava/io/ObjectInputStream$GetFieldImpl;->getFieldOffset(Ljava/lang/String;Ljava/lang/Class;)I+]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectInputStream$GetFieldImpl;->readFields()V+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectInputStream$HandleTable$HandleList;-><init>()V
+HSPLjava/io/ObjectInputStream$HandleTable$HandleList;->add(I)V
+HSPLjava/io/ObjectInputStream$HandleTable;-><init>(I)V
+HSPLjava/io/ObjectInputStream$HandleTable;->assign(Ljava/lang/Object;)I
+HSPLjava/io/ObjectInputStream$HandleTable;->clear()V
+HSPLjava/io/ObjectInputStream$HandleTable;->finish(I)V
+HSPLjava/io/ObjectInputStream$HandleTable;->grow()V
+HSPLjava/io/ObjectInputStream$HandleTable;->lookupException(I)Ljava/lang/ClassNotFoundException;
+HSPLjava/io/ObjectInputStream$HandleTable;->lookupObject(I)Ljava/lang/Object;
+HSPLjava/io/ObjectInputStream$HandleTable;->markDependency(II)V+]Ljava/io/ObjectInputStream$HandleTable$HandleList;Ljava/io/ObjectInputStream$HandleTable$HandleList;
+HSPLjava/io/ObjectInputStream$HandleTable;->setObject(ILjava/lang/Object;)V
+HSPLjava/io/ObjectInputStream$HandleTable;->size()I
+HSPLjava/io/ObjectInputStream$PeekInputStream;-><init>(Ljava/io/InputStream;)V
+HSPLjava/io/ObjectInputStream$PeekInputStream;->close()V+]Ljava/io/InputStream;missing_types
+HSPLjava/io/ObjectInputStream$PeekInputStream;->peek()I+]Ljava/io/InputStream;missing_types
+HSPLjava/io/ObjectInputStream$PeekInputStream;->read()I+]Ljava/io/InputStream;missing_types
+HSPLjava/io/ObjectInputStream$PeekInputStream;->read([BII)I+]Ljava/io/InputStream;missing_types
+HSPLjava/io/ObjectInputStream$PeekInputStream;->readFully([BII)V+]Ljava/io/ObjectInputStream$PeekInputStream;Ljava/io/ObjectInputStream$PeekInputStream;
+HSPLjava/io/ObjectInputStream$ValidationList;-><init>()V
+HSPLjava/io/ObjectInputStream$ValidationList;->clear()V
+HSPLjava/io/ObjectInputStream$ValidationList;->doCallbacks()V
+HSPLjava/io/ObjectInputStream;-><init>(Ljava/io/InputStream;)V+]Ljava/io/ObjectInputStream;missing_types]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->access$000(Ljava/io/ObjectInputStream;)I
+HSPLjava/io/ObjectInputStream;->access$002(Ljava/io/ObjectInputStream;I)I
+HSPLjava/io/ObjectInputStream;->access$100(Ljava/io/ObjectInputStream;)Ljava/io/ObjectInputStream$HandleTable;
+HSPLjava/io/ObjectInputStream;->access$200(Ljava/io/ObjectInputStream;)Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->access$300(Ljava/io/ObjectInputStream;Z)Ljava/lang/Object;
+HSPLjava/io/ObjectInputStream;->access$500(Ljava/io/ObjectInputStream;)Z
+HSPLjava/io/ObjectInputStream;->checkResolve(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;
+HSPLjava/io/ObjectInputStream;->clear()V+]Ljava/io/ObjectInputStream$ValidationList;Ljava/io/ObjectInputStream$ValidationList;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;
+HSPLjava/io/ObjectInputStream;->close()V+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->defaultReadFields(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectInputStream;->defaultReadObject()V+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;]Ljava/io/SerialCallbackContext;Ljava/io/SerialCallbackContext;
+HSPLjava/io/ObjectInputStream;->isCustomSubclass()Z+]Ljava/lang/Object;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectInputStream;->latestUserDefinedLoader()Ljava/lang/ClassLoader;
+HSPLjava/io/ObjectInputStream;->readArray(Z)Ljava/lang/Object;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectInputStream;->readBoolean()Z+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->readByte()B+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->readClassDesc(Z)Ljava/io/ObjectStreamClass;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->readClassDescriptor()Ljava/io/ObjectStreamClass;+]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;
+HSPLjava/io/ObjectInputStream;->readEnum(Z)Ljava/lang/Enum;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;
+HSPLjava/io/ObjectInputStream;->readFields()Ljava/io/ObjectInputStream$GetField;+]Ljava/io/ObjectInputStream$GetFieldImpl;Ljava/io/ObjectInputStream$GetFieldImpl;]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/SerialCallbackContext;Ljava/io/SerialCallbackContext;
+HSPLjava/io/ObjectInputStream;->readFloat()F
+HSPLjava/io/ObjectInputStream;->readHandle(Z)Ljava/lang/Object;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;
+HSPLjava/io/ObjectInputStream;->readInt()I+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->readLong()J+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->readNonProxyDesc(Z)Ljava/io/ObjectStreamClass;+]Ljava/io/ObjectInputStream;missing_types]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;
+HSPLjava/io/ObjectInputStream;->readNull()Ljava/lang/Object;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->readObject()Ljava/lang/Object;+]Ljava/io/ObjectInputStream$ValidationList;Ljava/io/ObjectInputStream$ValidationList;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;
+HSPLjava/io/ObjectInputStream;->readObject0(Z)Ljava/lang/Object;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->readOrdinaryObject(Z)Ljava/lang/Object;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;
+HSPLjava/io/ObjectInputStream;->readSerialData(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;]Ljava/io/SerialCallbackContext;Ljava/io/SerialCallbackContext;
+HSPLjava/io/ObjectInputStream;->readShort()S+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->readStreamHeader()V+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->readString(Z)Ljava/lang/String;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;]Ljava/io/ObjectInputStream$HandleTable;Ljava/io/ObjectInputStream$HandleTable;
+HSPLjava/io/ObjectInputStream;->readTypeString()Ljava/lang/String;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->readUTF()Ljava/lang/String;+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->resolveClass(Ljava/io/ObjectStreamClass;)Ljava/lang/Class;+]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/util/HashMap;Ljava/util/HashMap;
+HSPLjava/io/ObjectInputStream;->skipCustomData()V+]Ljava/io/ObjectInputStream$BlockDataInputStream;Ljava/io/ObjectInputStream$BlockDataInputStream;
+HSPLjava/io/ObjectInputStream;->verifySubclass()V+]Ljava/lang/Object;missing_types
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;-><init>(Ljava/io/OutputStream;)V
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->close()V+]Ljava/io/OutputStream;missing_types]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->drain()V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->flush()V+]Ljava/io/OutputStream;missing_types]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->getUTFLength(Ljava/lang/String;)J+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->setBlockDataMode(Z)Z+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->warnIfClosed()V
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->write([BIIZ)V+]Ljava/io/OutputStream;missing_types]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->writeBlockHeader(I)V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->writeByte(I)V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->writeBytes(Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->writeFloat(F)V
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->writeInt(I)V+]Ljava/io/DataOutputStream;Ljava/io/DataOutputStream;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->writeLong(J)V+]Ljava/io/DataOutputStream;Ljava/io/DataOutputStream;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->writeShort(I)V+]Ljava/io/DataOutputStream;Ljava/io/DataOutputStream;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->writeUTF(Ljava/lang/String;)V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream$BlockDataOutputStream;->writeUTF(Ljava/lang/String;J)V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream$HandleTable;-><init>(IF)V+]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;
+HSPLjava/io/ObjectOutputStream$HandleTable;->assign(Ljava/lang/Object;)I
+HSPLjava/io/ObjectOutputStream$HandleTable;->clear()V
+HSPLjava/io/ObjectOutputStream$HandleTable;->growEntries()V
+HSPLjava/io/ObjectOutputStream$HandleTable;->growSpine()V
+HSPLjava/io/ObjectOutputStream$HandleTable;->hash(Ljava/lang/Object;)I
+HSPLjava/io/ObjectOutputStream$HandleTable;->insert(Ljava/lang/Object;I)V
+HSPLjava/io/ObjectOutputStream$HandleTable;->lookup(Ljava/lang/Object;)I
+HSPLjava/io/ObjectOutputStream$PutField;-><init>()V
+HSPLjava/io/ObjectOutputStream$PutFieldImpl;-><init>(Ljava/io/ObjectOutputStream;Ljava/io/ObjectStreamClass;)V
+HSPLjava/io/ObjectOutputStream$PutFieldImpl;->getFieldOffset(Ljava/lang/String;Ljava/lang/Class;)I
+HSPLjava/io/ObjectOutputStream$PutFieldImpl;->put(Ljava/lang/String;D)V
+HSPLjava/io/ObjectOutputStream$PutFieldImpl;->put(Ljava/lang/String;J)V
+HSPLjava/io/ObjectOutputStream$PutFieldImpl;->put(Ljava/lang/String;Z)V
+HSPLjava/io/ObjectOutputStream$PutFieldImpl;->writeFields()V
+HSPLjava/io/ObjectOutputStream$ReplaceTable;-><init>(IF)V
+HSPLjava/io/ObjectOutputStream$ReplaceTable;->assign(Ljava/lang/Object;Ljava/lang/Object;)V+]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;
+HSPLjava/io/ObjectOutputStream$ReplaceTable;->lookup(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;
+HSPLjava/io/ObjectOutputStream;-><init>(Ljava/io/OutputStream;)V+]Ljava/io/ObjectOutputStream;missing_types]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->access$000(Ljava/io/ObjectOutputStream;)Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->annotateClass(Ljava/lang/Class;)V
+HSPLjava/io/ObjectOutputStream;->close()V+]Ljava/io/ObjectOutputStream;missing_types]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->defaultWriteFields(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V+]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectOutputStream;->defaultWriteObject()V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;]Ljava/io/SerialCallbackContext;Ljava/io/SerialCallbackContext;
+HSPLjava/io/ObjectOutputStream;->flush()V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->isCustomSubclass()Z+]Ljava/lang/Object;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectOutputStream;->putFields()Ljava/io/ObjectOutputStream$PutField;+]Ljava/io/SerialCallbackContext;Ljava/io/SerialCallbackContext;
+HSPLjava/io/ObjectOutputStream;->verifySubclass()V+]Ljava/lang/Object;missing_types
+HSPLjava/io/ObjectOutputStream;->writeArray(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V+]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectOutputStream;->writeByte(I)V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeClassDesc(Ljava/io/ObjectStreamClass;Z)V+]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;
+HSPLjava/io/ObjectOutputStream;->writeClassDescriptor(Ljava/io/ObjectStreamClass;)V+]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;
+HSPLjava/io/ObjectOutputStream;->writeEnum(Ljava/lang/Enum;Ljava/io/ObjectStreamClass;Z)V+]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeFields()V+]Ljava/io/ObjectOutputStream$PutFieldImpl;Ljava/io/ObjectOutputStream$PutFieldImpl;]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeFloat(F)V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeHandle(I)V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeInt(I)V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeLong(J)V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeNonProxyDesc(Ljava/io/ObjectStreamClass;Z)V+]Ljava/io/ObjectOutputStream;missing_types]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeNull()V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeObject(Ljava/lang/Object;)V
+HSPLjava/io/ObjectOutputStream;->writeObject0(Ljava/lang/Object;Z)V+]Ljava/io/ObjectOutputStream$ReplaceTable;Ljava/io/ObjectOutputStream$ReplaceTable;]Ljava/lang/Object;megamorphic_types]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectOutputStream;->writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V+]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeSerialData(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V+]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;]Ljava/io/SerialCallbackContext;Ljava/io/SerialCallbackContext;
+HSPLjava/io/ObjectOutputStream;->writeShort(I)V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeStreamHeader()V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeString(Ljava/lang/String;Z)V+]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectOutputStream;->writeTypeString(Ljava/lang/String;)V+]Ljava/io/ObjectOutputStream$HandleTable;Ljava/io/ObjectOutputStream$HandleTable;
+HSPLjava/io/ObjectOutputStream;->writeUTF(Ljava/lang/String;)V+]Ljava/io/ObjectOutputStream$BlockDataOutputStream;Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+HSPLjava/io/ObjectStreamClass$1;-><init>(Ljava/io/ObjectStreamClass;)V
+HSPLjava/io/ObjectStreamClass$1;->run()Ljava/lang/Long;
+HSPLjava/io/ObjectStreamClass$1;->run()Ljava/lang/Object;
+HSPLjava/io/ObjectStreamClass$2;-><init>(Ljava/io/ObjectStreamClass;Ljava/lang/Class;)V
+HSPLjava/io/ObjectStreamClass$2;->run()Ljava/lang/Object;
+HSPLjava/io/ObjectStreamClass$2;->run()Ljava/lang/Void;
+HSPLjava/io/ObjectStreamClass$3;-><init>()V
+HSPLjava/io/ObjectStreamClass$3;->compare(Ljava/io/ObjectStreamClass$MemberSignature;Ljava/io/ObjectStreamClass$MemberSignature;)I
+HSPLjava/io/ObjectStreamClass$3;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/io/ObjectStreamClass$3;Ljava/io/ObjectStreamClass$3;
+HSPLjava/io/ObjectStreamClass$4;-><init>()V
+HSPLjava/io/ObjectStreamClass$4;->compare(Ljava/io/ObjectStreamClass$MemberSignature;Ljava/io/ObjectStreamClass$MemberSignature;)I
+HSPLjava/io/ObjectStreamClass$4;->compare(Ljava/lang/Object;Ljava/lang/Object;)I
+HSPLjava/io/ObjectStreamClass$5;-><init>()V
+HSPLjava/io/ObjectStreamClass$5;->compare(Ljava/io/ObjectStreamClass$MemberSignature;Ljava/io/ObjectStreamClass$MemberSignature;)I
+HSPLjava/io/ObjectStreamClass$5;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/io/ObjectStreamClass$5;Ljava/io/ObjectStreamClass$5;
+HSPLjava/io/ObjectStreamClass$Caches;->access$200()Ljava/lang/ref/ReferenceQueue;
+HSPLjava/io/ObjectStreamClass$Caches;->access$2600()Ljava/lang/ref/ReferenceQueue;
+HSPLjava/io/ObjectStreamClass$ClassDataSlot;-><init>(Ljava/io/ObjectStreamClass;Z)V
+HSPLjava/io/ObjectStreamClass$EntryFuture;-><init>()V
+HSPLjava/io/ObjectStreamClass$EntryFuture;-><init>(Ljava/io/ObjectStreamClass$1;)V
+HSPLjava/io/ObjectStreamClass$EntryFuture;->get()Ljava/lang/Object;
+HSPLjava/io/ObjectStreamClass$EntryFuture;->getOwner()Ljava/lang/Thread;
+HSPLjava/io/ObjectStreamClass$EntryFuture;->set(Ljava/lang/Object;)Z+]Ljava/lang/Object;Ljava/io/ObjectStreamClass$EntryFuture;
+HSPLjava/io/ObjectStreamClass$ExceptionInfo;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/io/ObjectStreamClass$FieldReflector;-><init>([Ljava/io/ObjectStreamField;)V+]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;]Lsun/misc/Unsafe;Lsun/misc/Unsafe;]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLjava/io/ObjectStreamClass$FieldReflector;->getFields()[Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectStreamClass$FieldReflector;->getObjFieldValues(Ljava/lang/Object;[Ljava/lang/Object;)V
+HSPLjava/io/ObjectStreamClass$FieldReflector;->getPrimFieldValues(Ljava/lang/Object;[B)V+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/io/ObjectStreamClass$FieldReflector;->setObjFieldValues(Ljava/lang/Object;[Ljava/lang/Object;)V+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass$FieldReflector;->setPrimFieldValues(Ljava/lang/Object;[B)V+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/io/ObjectStreamClass$FieldReflectorKey;-><init>(Ljava/lang/Class;[Ljava/io/ObjectStreamField;Ljava/lang/ref/ReferenceQueue;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectStreamClass$FieldReflectorKey;->equals(Ljava/lang/Object;)Z+]Ljava/io/ObjectStreamClass$FieldReflectorKey;Ljava/io/ObjectStreamClass$FieldReflectorKey;
+HSPLjava/io/ObjectStreamClass$FieldReflectorKey;->hashCode()I
+HSPLjava/io/ObjectStreamClass$MemberSignature;-><init>(Ljava/lang/reflect/Constructor;)V+]Ljava/lang/reflect/Constructor;Ljava/lang/reflect/Constructor;
+HSPLjava/io/ObjectStreamClass$MemberSignature;-><init>(Ljava/lang/reflect/Field;)V+]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;
+HSPLjava/io/ObjectStreamClass$MemberSignature;-><init>(Ljava/lang/reflect/Method;)V+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass$WeakClassKey;-><init>(Ljava/lang/Class;Ljava/lang/ref/ReferenceQueue;)V
+HSPLjava/io/ObjectStreamClass$WeakClassKey;->equals(Ljava/lang/Object;)Z+]Ljava/io/ObjectStreamClass$WeakClassKey;Ljava/io/ObjectStreamClass$WeakClassKey;
+HSPLjava/io/ObjectStreamClass$WeakClassKey;->hashCode()I
+HSPLjava/io/ObjectStreamClass;-><init>()V
+HSPLjava/io/ObjectStreamClass;-><init>(Ljava/lang/Class;)V+]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass;->access$000(Ljava/io/ObjectStreamClass;)Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass;->access$100(Ljava/lang/Class;)J
+HSPLjava/io/ObjectStreamClass;->access$1200(Ljava/io/ObjectStreamClass;)Z
+HSPLjava/io/ObjectStreamClass;->access$1302(Ljava/io/ObjectStreamClass;Ljava/lang/reflect/Constructor;)Ljava/lang/reflect/Constructor;
+HSPLjava/io/ObjectStreamClass;->access$1500(Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
+HSPLjava/io/ObjectStreamClass;->access$1600(Ljava/io/ObjectStreamClass;)Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->access$1602(Ljava/io/ObjectStreamClass;Ljava/lang/reflect/Method;)Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->access$1700(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->access$1802(Ljava/io/ObjectStreamClass;Ljava/lang/reflect/Method;)Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->access$1902(Ljava/io/ObjectStreamClass;Ljava/lang/reflect/Method;)Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->access$2002(Ljava/io/ObjectStreamClass;Z)Z
+HSPLjava/io/ObjectStreamClass;->access$2102(Ljava/io/ObjectStreamClass;Ljava/lang/reflect/Method;)Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->access$2200(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->access$2302(Ljava/io/ObjectStreamClass;Ljava/lang/reflect/Method;)Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->access$2400(Ljava/lang/Class;)Ljava/lang/String;
+HSPLjava/io/ObjectStreamClass;->access$2500([Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/String;
+HSPLjava/io/ObjectStreamClass;->access$400(Ljava/io/ObjectStreamClass;)Z
+HSPLjava/io/ObjectStreamClass;->access$502(Ljava/io/ObjectStreamClass;Ljava/lang/Long;)Ljava/lang/Long;
+HSPLjava/io/ObjectStreamClass;->access$602(Ljava/io/ObjectStreamClass;[Ljava/io/ObjectStreamField;)[Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectStreamClass;->access$700(Ljava/lang/Class;)Ljava/lang/Long;
+HSPLjava/io/ObjectStreamClass;->access$800(Ljava/lang/Class;)[Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectStreamClass;->access$900(Ljava/io/ObjectStreamClass;)V
+HSPLjava/io/ObjectStreamClass;->checkDefaultSerialize()V+]Ljava/io/ObjectStreamClass$ExceptionInfo;Ljava/io/ObjectStreamClass$ExceptionInfo;
+HSPLjava/io/ObjectStreamClass;->checkDeserialize()V+]Ljava/io/ObjectStreamClass$ExceptionInfo;Ljava/io/ObjectStreamClass$ExceptionInfo;
+HSPLjava/io/ObjectStreamClass;->checkSerialize()V
+HSPLjava/io/ObjectStreamClass;->classNamesEqual(Ljava/lang/String;Ljava/lang/String;)Z+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/io/ObjectStreamClass;->computeDefaultSUID(Ljava/lang/Class;)J+]Ldalvik/system/VMRuntime;missing_types]Ljava/lang/String;Ljava/lang/String;]Ljava/io/DataOutputStream;Ljava/io/DataOutputStream;]Ljava/lang/reflect/Member;Ljava/lang/reflect/Field;,Ljava/lang/reflect/Method;,Ljava/lang/reflect/Constructor;]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;]Ljava/io/ByteArrayOutputStream;Ljava/io/ByteArrayOutputStream;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass;->computeFieldOffsets()V+]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectStreamClass;->forClass()Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass;->getClassDataLayout()[Ljava/io/ObjectStreamClass$ClassDataSlot;
+HSPLjava/io/ObjectStreamClass;->getClassDataLayout0()[Ljava/io/ObjectStreamClass$ClassDataSlot;+]Ljava/util/HashSet;Ljava/util/HashSet;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/io/ObjectStreamClass;->getClassSignature(Ljava/lang/Class;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass;->getDeclaredSUID(Ljava/lang/Class;)Ljava/lang/Long;
+HSPLjava/io/ObjectStreamClass;->getDeclaredSerialFields(Ljava/lang/Class;)[Ljava/io/ObjectStreamField;+]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLjava/io/ObjectStreamClass;->getDefaultSerialFields(Ljava/lang/Class;)[Ljava/io/ObjectStreamField;+]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass;->getField(Ljava/lang/String;Ljava/lang/Class;)Ljava/io/ObjectStreamField;+]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass;->getFields(Z)[Ljava/io/ObjectStreamField;+][Ljava/io/ObjectStreamField;[Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectStreamClass;->getInheritableMethod(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/reflect/Method;+]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->getMethodSignature([Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/io/ObjectStreamClass;->getName()Ljava/lang/String;
+HSPLjava/io/ObjectStreamClass;->getNumObjFields()I
+HSPLjava/io/ObjectStreamClass;->getObjFieldValues(Ljava/lang/Object;[Ljava/lang/Object;)V+]Ljava/io/ObjectStreamClass$FieldReflector;Ljava/io/ObjectStreamClass$FieldReflector;
+HSPLjava/io/ObjectStreamClass;->getPackageName(Ljava/lang/Class;)Ljava/lang/String;
+HSPLjava/io/ObjectStreamClass;->getPrimDataSize()I
+HSPLjava/io/ObjectStreamClass;->getPrimFieldValues(Ljava/lang/Object;[B)V+]Ljava/io/ObjectStreamClass$FieldReflector;Ljava/io/ObjectStreamClass$FieldReflector;
+HSPLjava/io/ObjectStreamClass;->getPrivateMethod(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/reflect/Method;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass;->getReflector([Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamClass;)Ljava/io/ObjectStreamClass$FieldReflector;+]Ljava/lang/ref/Reference;Ljava/lang/ref/SoftReference;]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/io/ObjectStreamClass$EntryFuture;Ljava/io/ObjectStreamClass$EntryFuture;
+HSPLjava/io/ObjectStreamClass;->getResolveException()Ljava/lang/ClassNotFoundException;
+HSPLjava/io/ObjectStreamClass;->getSerialFields(Ljava/lang/Class;)[Ljava/io/ObjectStreamField;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass;->getSerialVersionUID()J+]Ljava/lang/Long;Ljava/lang/Long;
+HSPLjava/io/ObjectStreamClass;->getSerializableConstructor(Ljava/lang/Class;)Ljava/lang/reflect/Constructor;+]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/reflect/Constructor;Ljava/lang/reflect/Constructor;
+HSPLjava/io/ObjectStreamClass;->getSuperDesc()Ljava/io/ObjectStreamClass;
+HSPLjava/io/ObjectStreamClass;->getVariantFor(Ljava/lang/Class;)Ljava/io/ObjectStreamClass;
+HSPLjava/io/ObjectStreamClass;->hasReadObjectMethod()Z
+HSPLjava/io/ObjectStreamClass;->hasReadResolveMethod()Z
+HSPLjava/io/ObjectStreamClass;->hasWriteObjectData()Z
+HSPLjava/io/ObjectStreamClass;->hasWriteObjectMethod()Z
+HSPLjava/io/ObjectStreamClass;->hasWriteReplaceMethod()Z
+HSPLjava/io/ObjectStreamClass;->initNonProxy(Ljava/io/ObjectStreamClass;Ljava/lang/Class;Ljava/lang/ClassNotFoundException;Ljava/io/ObjectStreamClass;)V+]Ljava/io/ObjectStreamClass$FieldReflector;Ljava/io/ObjectStreamClass$FieldReflector;]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/lang/Long;Ljava/lang/Long;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/io/ObjectStreamClass;->invokeReadObject(Ljava/lang/Object;Ljava/io/ObjectInputStream;)V+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/reflect/InvocationTargetException;Ljava/lang/reflect/InvocationTargetException;
+HSPLjava/io/ObjectStreamClass;->invokeReadResolve(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->invokeWriteObject(Ljava/lang/Object;Ljava/io/ObjectOutputStream;)V+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->invokeWriteReplace(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/io/ObjectStreamClass;->isEnum()Z
+HSPLjava/io/ObjectStreamClass;->isExternalizable()Z
+HSPLjava/io/ObjectStreamClass;->isInstantiable()Z
+HSPLjava/io/ObjectStreamClass;->isProxy()Z
+HSPLjava/io/ObjectStreamClass;->lookup(Ljava/lang/Class;Z)Ljava/io/ObjectStreamClass;+]Ljava/lang/ref/Reference;Ljava/lang/ref/SoftReference;]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/io/ObjectStreamClass$EntryFuture;Ljava/io/ObjectStreamClass$EntryFuture;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamClass;->matchFields([Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamClass;)[Ljava/io/ObjectStreamField;+]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectStreamClass;->newInstance()Ljava/lang/Object;+]Ljava/lang/reflect/Constructor;Ljava/lang/reflect/Constructor;
+HSPLjava/io/ObjectStreamClass;->packageEquals(Ljava/lang/Class;Ljava/lang/Class;)Z
+HSPLjava/io/ObjectStreamClass;->processQueue(Ljava/lang/ref/ReferenceQueue;Ljava/util/concurrent/ConcurrentMap;)V+]Ljava/lang/ref/ReferenceQueue;Ljava/lang/ref/ReferenceQueue;
+HSPLjava/io/ObjectStreamClass;->readNonProxy(Ljava/io/ObjectInputStream;)V+]Ljava/io/ObjectInputStream;missing_types]Ljava/lang/Long;Ljava/lang/Long;
+HSPLjava/io/ObjectStreamClass;->requireInitialized()V
+HSPLjava/io/ObjectStreamClass;->setObjFieldValues(Ljava/lang/Object;[Ljava/lang/Object;)V+]Ljava/io/ObjectStreamClass$FieldReflector;Ljava/io/ObjectStreamClass$FieldReflector;
+HSPLjava/io/ObjectStreamClass;->setPrimFieldValues(Ljava/lang/Object;[B)V+]Ljava/io/ObjectStreamClass$FieldReflector;Ljava/io/ObjectStreamClass$FieldReflector;
+HSPLjava/io/ObjectStreamClass;->writeNonProxy(Ljava/io/ObjectOutputStream;)V+]Ljava/io/ObjectOutputStream;missing_types]Ljava/io/ObjectStreamClass;Ljava/io/ObjectStreamClass;]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectStreamField;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
+HSPLjava/io/ObjectStreamField;-><init>(Ljava/lang/String;Ljava/lang/Class;Z)V
+HSPLjava/io/ObjectStreamField;-><init>(Ljava/lang/String;Ljava/lang/String;Z)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/io/ObjectStreamField;-><init>(Ljava/lang/reflect/Field;ZZ)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamField;->compareTo(Ljava/lang/Object;)I+]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectStreamField;->getClassSignature(Ljava/lang/Class;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/io/ObjectStreamField;->getField()Ljava/lang/reflect/Field;
+HSPLjava/io/ObjectStreamField;->getName()Ljava/lang/String;
+HSPLjava/io/ObjectStreamField;->getOffset()I
+HSPLjava/io/ObjectStreamField;->getSignature()Ljava/lang/String;
+HSPLjava/io/ObjectStreamField;->getType()Ljava/lang/Class;
+HSPLjava/io/ObjectStreamField;->getTypeCode()C
+HSPLjava/io/ObjectStreamField;->getTypeString()Ljava/lang/String;+]Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamField;
+HSPLjava/io/ObjectStreamField;->isPrimitive()Z
+HSPLjava/io/ObjectStreamField;->isUnshared()Z
+HSPLjava/io/ObjectStreamField;->setOffset(I)V
+HSPLjava/io/OutputStream;-><init>()V
+HSPLjava/io/OutputStream;->close()V
+HSPLjava/io/OutputStream;->flush()V
+HSPLjava/io/OutputStream;->write([B)V+]Ljava/io/OutputStream;missing_types
+HSPLjava/io/OutputStreamWriter;-><init>(Ljava/io/OutputStream;)V
+HSPLjava/io/OutputStreamWriter;-><init>(Ljava/io/OutputStream;Ljava/lang/String;)V
+HSPLjava/io/OutputStreamWriter;-><init>(Ljava/io/OutputStream;Ljava/nio/charset/Charset;)V
+HSPLjava/io/OutputStreamWriter;->close()V+]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;
+HSPLjava/io/OutputStreamWriter;->flush()V+]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;
+HSPLjava/io/OutputStreamWriter;->write(I)V+]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;
+HSPLjava/io/OutputStreamWriter;->write(Ljava/lang/String;II)V+]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;
+HSPLjava/io/OutputStreamWriter;->write([CII)V+]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;
+HSPLjava/io/PrintStream;-><init>(Ljava/io/OutputStream;)V
+HSPLjava/io/PrintStream;-><init>(Ljava/io/OutputStream;Z)V
+HSPLjava/io/PrintStream;-><init>(ZLjava/io/OutputStream;)V
+HSPLjava/io/PrintStream;->close()V+]Ljava/io/OutputStream;Ljava/io/FileOutputStream;,Ljava/io/ByteArrayOutputStream;]Ljava/io/BufferedWriter;Ljava/io/BufferedWriter;
+HSPLjava/io/PrintStream;->requireNonNull(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
+HSPLjava/io/PrintWriter;-><init>(Ljava/io/OutputStream;)V
+HSPLjava/io/PrintWriter;-><init>(Ljava/io/OutputStream;Z)V
+HSPLjava/io/PrintWriter;-><init>(Ljava/io/Writer;)V
+HSPLjava/io/PrintWriter;-><init>(Ljava/io/Writer;Z)V
+HSPLjava/io/PrintWriter;->append(C)Ljava/io/PrintWriter;+]Ljava/io/PrintWriter;missing_types
+HSPLjava/io/PrintWriter;->append(Ljava/lang/CharSequence;)Ljava/io/PrintWriter;+]Ljava/io/PrintWriter;missing_types]Ljava/lang/CharSequence;Ljava/lang/String;,Ljava/lang/StringBuilder;
+HSPLjava/io/PrintWriter;->append(Ljava/lang/CharSequence;)Ljava/lang/Appendable;+]Ljava/io/PrintWriter;missing_types
+HSPLjava/io/PrintWriter;->close()V+]Ljava/io/Writer;Lcom/android/internal/util/FastPrintWriter;,Ljava/io/BufferedWriter;
+HSPLjava/io/PrintWriter;->ensureOpen()V
+HSPLjava/io/PrintWriter;->flush()V+]Ljava/io/Writer;missing_types
+HSPLjava/io/PrintWriter;->format(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintWriter;+]Ljava/util/Formatter;Ljava/util/Formatter;
+HSPLjava/io/PrintWriter;->newLine()V+]Ljava/io/Writer;missing_types
+HSPLjava/io/PrintWriter;->print(C)V+]Ljava/io/PrintWriter;Ljava/io/PrintWriter;,Landroid/util/IndentingPrintWriter;,Lcom/android/internal/util/IndentingPrintWriter;
+HSPLjava/io/PrintWriter;->print(I)V+]Ljava/io/PrintWriter;missing_types
+HSPLjava/io/PrintWriter;->print(J)V+]Ljava/io/PrintWriter;missing_types
+HSPLjava/io/PrintWriter;->print(Ljava/lang/String;)V+]Ljava/io/PrintWriter;megamorphic_types
+HSPLjava/io/PrintWriter;->print(Z)V+]Ljava/io/PrintWriter;missing_types
+HSPLjava/io/PrintWriter;->printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintWriter;+]Ljava/io/PrintWriter;missing_types
+HSPLjava/io/PrintWriter;->println()V
+HSPLjava/io/PrintWriter;->println(I)V+]Ljava/io/PrintWriter;missing_types
+HSPLjava/io/PrintWriter;->println(Ljava/lang/Object;)V+]Ljava/io/PrintWriter;megamorphic_types
+HSPLjava/io/PrintWriter;->println(Ljava/lang/String;)V+]Ljava/io/PrintWriter;megamorphic_types
+HSPLjava/io/PrintWriter;->write(I)V+]Ljava/io/Writer;missing_types
+HSPLjava/io/PrintWriter;->write(Ljava/lang/String;)V+]Ljava/io/PrintWriter;megamorphic_types
+HSPLjava/io/PrintWriter;->write(Ljava/lang/String;II)V+]Ljava/io/Writer;missing_types
+HSPLjava/io/PrintWriter;->write([CII)V+]Ljava/io/Writer;missing_types
+HSPLjava/io/PushbackInputStream;-><init>(Ljava/io/InputStream;I)V
+HSPLjava/io/PushbackInputStream;->close()V
+HSPLjava/io/PushbackInputStream;->ensureOpen()V
+HSPLjava/io/PushbackInputStream;->markSupported()Z
+HSPLjava/io/PushbackInputStream;->read()I
+HSPLjava/io/PushbackInputStream;->read([BII)I
+HSPLjava/io/PushbackInputStream;->unread([BII)V
+HSPLjava/io/PushbackReader;-><init>(Ljava/io/Reader;I)V
+HSPLjava/io/PushbackReader;->ensureOpen()V
+HSPLjava/io/PushbackReader;->read()I
+HSPLjava/io/PushbackReader;->unread(I)V
+HSPLjava/io/RandomAccessFile;-><init>(Ljava/io/File;Ljava/lang/String;)V+]Ljava/io/File;missing_types]Ldalvik/system/CloseGuard;missing_types]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/io/RandomAccessFile;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/io/RandomAccessFile;->close()V+]Ldalvik/system/CloseGuard;missing_types]Ljava/nio/channels/FileChannel;Lsun/nio/ch/FileChannelImpl;
+HSPLjava/io/RandomAccessFile;->finalize()V+]Ljava/io/RandomAccessFile;missing_types]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/io/RandomAccessFile;->getChannel()Ljava/nio/channels/FileChannel;
+HSPLjava/io/RandomAccessFile;->getFD()Ljava/io/FileDescriptor;
+HSPLjava/io/RandomAccessFile;->getFilePointer()J+]Llibcore/io/Os;missing_types
+HSPLjava/io/RandomAccessFile;->length()J+]Llibcore/io/Os;missing_types
+HSPLjava/io/RandomAccessFile;->maybeSync()V+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLjava/io/RandomAccessFile;->read()I+]Ljava/io/RandomAccessFile;Ljava/io/RandomAccessFile;
+HSPLjava/io/RandomAccessFile;->read([B)I
+HSPLjava/io/RandomAccessFile;->read([BII)I
+HSPLjava/io/RandomAccessFile;->readBytes([BII)I+]Llibcore/io/IoTracker;missing_types
+HSPLjava/io/RandomAccessFile;->readFully([B)V+]Ljava/io/RandomAccessFile;Ljava/io/RandomAccessFile;
+HSPLjava/io/RandomAccessFile;->readFully([BII)V+]Ljava/io/RandomAccessFile;Ljava/io/RandomAccessFile;
+HSPLjava/io/RandomAccessFile;->readInt()I+]Ljava/io/RandomAccessFile;Ljava/io/RandomAccessFile;
+HSPLjava/io/RandomAccessFile;->seek(J)V+]Llibcore/io/Os;missing_types]Llibcore/io/IoTracker;missing_types
+HSPLjava/io/RandomAccessFile;->setLength(J)V+]Llibcore/io/Os;missing_types]Ljava/io/RandomAccessFile;Ljava/io/RandomAccessFile;
+HSPLjava/io/RandomAccessFile;->write(I)V+]Ljava/io/RandomAccessFile;Ljava/io/RandomAccessFile;
+HSPLjava/io/RandomAccessFile;->write([B)V
+HSPLjava/io/RandomAccessFile;->write([BII)V
+HSPLjava/io/RandomAccessFile;->writeBytes([BII)V+]Llibcore/io/IoTracker;missing_types
+HSPLjava/io/RandomAccessFile;->writeInt(I)V+]Ljava/io/RandomAccessFile;Ljava/io/RandomAccessFile;
+HSPLjava/io/RandomAccessFile;->writeUTF(Ljava/lang/String;)V
+HSPLjava/io/Reader;-><init>()V
+HSPLjava/io/Reader;-><init>(Ljava/lang/Object;)V
+HSPLjava/io/Reader;->read(Ljava/nio/CharBuffer;)I+]Ljava/io/Reader;Ljava/io/InputStreamReader;,Ljava/io/StringReader;,Lsun/nio/cs/StreamDecoder;]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;
+HSPLjava/io/Reader;->read([C)I+]Ljava/io/Reader;missing_types
+HSPLjava/io/SequenceInputStream;-><init>(Ljava/io/InputStream;Ljava/io/InputStream;)V+]Ljava/util/Vector;Ljava/util/Vector;]Ljava/io/SequenceInputStream;Ljava/io/SequenceInputStream;
+HSPLjava/io/SequenceInputStream;->close()V+]Ljava/io/SequenceInputStream;Ljava/io/SequenceInputStream;
+HSPLjava/io/SequenceInputStream;->nextStream()V+]Ljava/util/Enumeration;missing_types]Ljava/io/InputStream;Ljava/io/ByteArrayInputStream;,Ljava/io/SequenceInputStream;,Ljava/io/BufferedInputStream;
+HSPLjava/io/SequenceInputStream;->read()I+]Ljava/io/InputStream;Ljava/io/ByteArrayInputStream;,Ljava/util/zip/GZIPInputStream$1;,Ljava/io/BufferedInputStream;]Ljava/io/SequenceInputStream;Ljava/io/SequenceInputStream;
+HSPLjava/io/SequenceInputStream;->read([BII)I+]Ljava/io/InputStream;missing_types]Ljava/io/SequenceInputStream;Ljava/io/SequenceInputStream;
+HSPLjava/io/SerialCallbackContext;-><init>(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V
+HSPLjava/io/SerialCallbackContext;->check()V
+HSPLjava/io/SerialCallbackContext;->checkAndSetUsed()V
+HSPLjava/io/SerialCallbackContext;->getDesc()Ljava/io/ObjectStreamClass;
+HSPLjava/io/SerialCallbackContext;->getObj()Ljava/lang/Object;
+HSPLjava/io/SerialCallbackContext;->setUsed()V
+HSPLjava/io/StringReader;-><init>(Ljava/lang/String;)V
+HSPLjava/io/StringReader;->close()V
+HSPLjava/io/StringReader;->ensureOpen()V
+HSPLjava/io/StringReader;->read()I
+HSPLjava/io/StringReader;->read([CII)I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/io/StringWriter;-><init>()V
+HSPLjava/io/StringWriter;->append(C)Ljava/io/StringWriter;+]Ljava/io/StringWriter;Ljava/io/StringWriter;
+HSPLjava/io/StringWriter;->append(C)Ljava/io/Writer;+]Ljava/io/StringWriter;Ljava/io/StringWriter;
+HSPLjava/io/StringWriter;->append(Ljava/lang/CharSequence;)Ljava/io/StringWriter;+]Ljava/lang/CharSequence;Ljava/lang/String;]Ljava/io/StringWriter;Ljava/io/StringWriter;
+HSPLjava/io/StringWriter;->append(Ljava/lang/CharSequence;)Ljava/io/Writer;+]Ljava/io/StringWriter;Ljava/io/StringWriter;
+HSPLjava/io/StringWriter;->close()V
+HSPLjava/io/StringWriter;->flush()V
+HSPLjava/io/StringWriter;->getBuffer()Ljava/lang/StringBuffer;
+HSPLjava/io/StringWriter;->toString()Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/io/StringWriter;->write(I)V+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/io/StringWriter;->write(Ljava/lang/String;)V+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/io/StringWriter;->write(Ljava/lang/String;II)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/io/StringWriter;->write([CII)V+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/io/UnixFileSystem;->canonicalize(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/io/UnixFileSystem;->checkAccess(Ljava/io/File;I)Z+]Ljava/io/File;missing_types]Llibcore/io/Os;missing_types
+HSPLjava/io/UnixFileSystem;->compare(Ljava/io/File;Ljava/io/File;)I+]Ljava/io/File;missing_types
+HSPLjava/io/UnixFileSystem;->createDirectory(Ljava/io/File;)Z+]Ljava/io/File;Ljava/io/File;]Ldalvik/system/BlockGuard$VmPolicy;missing_types]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLjava/io/UnixFileSystem;->createFileExclusively(Ljava/lang/String;)Z+]Ldalvik/system/BlockGuard$VmPolicy;missing_types]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLjava/io/UnixFileSystem;->delete(Ljava/io/File;)Z+]Ljava/io/ExpiringCache;Ljava/io/ExpiringCache;]Ljava/io/File;Ljava/io/File;]Llibcore/io/Os;missing_types
+HSPLjava/io/UnixFileSystem;->getBooleanAttributes(Ljava/io/File;)I+]Ljava/io/File;Ljava/io/File;]Ldalvik/system/BlockGuard$VmPolicy;Landroid/os/StrictMode$5;,Ldalvik/system/BlockGuard$2;]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLjava/io/UnixFileSystem;->getDefaultParent()Ljava/lang/String;
+HSPLjava/io/UnixFileSystem;->getLastModifiedTime(Ljava/io/File;)J+]Ljava/io/File;missing_types]Ldalvik/system/BlockGuard$VmPolicy;missing_types]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLjava/io/UnixFileSystem;->getLength(Ljava/io/File;)J+]Ljava/io/File;missing_types]Llibcore/io/Os;missing_types
+HSPLjava/io/UnixFileSystem;->getSpace(Ljava/io/File;I)J+]Ljava/io/File;Ljava/io/File;]Ldalvik/system/BlockGuard$VmPolicy;missing_types]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLjava/io/UnixFileSystem;->hashCode(Ljava/io/File;)I+]Ljava/lang/String;Ljava/lang/String;]Ljava/io/File;missing_types
+HSPLjava/io/UnixFileSystem;->isAbsolute(Ljava/io/File;)Z+]Ljava/io/File;missing_types
+HSPLjava/io/UnixFileSystem;->list(Ljava/io/File;)[Ljava/lang/String;+]Ljava/io/File;Ljava/io/File;]Ldalvik/system/BlockGuard$VmPolicy;Ldalvik/system/BlockGuard$2;,Landroid/os/StrictMode$5;]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLjava/io/UnixFileSystem;->normalize(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/io/UnixFileSystem;->prefixLength(Ljava/lang/String;)I
+HSPLjava/io/UnixFileSystem;->rename(Ljava/io/File;Ljava/io/File;)Z+]Ljava/io/ExpiringCache;Ljava/io/ExpiringCache;]Ljava/io/File;missing_types]Llibcore/io/Os;missing_types
+HSPLjava/io/UnixFileSystem;->resolve(Ljava/io/File;)Ljava/lang/String;+]Ljava/io/File;missing_types]Ljava/io/UnixFileSystem;Ljava/io/UnixFileSystem;
+HSPLjava/io/UnixFileSystem;->resolve(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/io/UnixFileSystem;->setLastModifiedTime(Ljava/io/File;J)Z+]Ljava/io/File;Ljava/io/File;]Ldalvik/system/BlockGuard$VmPolicy;missing_types]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLjava/io/UnixFileSystem;->setPermission(Ljava/io/File;IZZ)Z+]Ljava/io/File;Ljava/io/File;]Ldalvik/system/BlockGuard$VmPolicy;missing_types]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLjava/io/Writer;-><init>()V
+HSPLjava/io/Writer;-><init>(Ljava/lang/Object;)V
+HSPLjava/io/Writer;->append(C)Ljava/io/Writer;+]Ljava/io/Writer;Ljava/io/OutputStreamWriter;,Ljava/io/BufferedWriter;,Ljava/io/FileWriter;
+HSPLjava/io/Writer;->append(Ljava/lang/CharSequence;)Ljava/io/Writer;+]Ljava/io/Writer;Ljava/io/FileWriter;,Ljava/io/BufferedWriter;,Ljava/io/OutputStreamWriter;]Ljava/lang/CharSequence;Ljava/lang/StringBuilder;,Ljava/lang/String;
+HSPLjava/io/Writer;->write(Ljava/lang/String;)V+]Ljava/io/Writer;missing_types
+HSPLjava/lang/AbstractStringBuilder;-><init>(I)V
+HSPLjava/lang/AbstractStringBuilder;->append(C)Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->append(D)Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->append(F)Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->append(I)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/AbstractStringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->append(J)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/AbstractStringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->append(Ljava/lang/AbstractStringBuilder;)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/AbstractStringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->append(Ljava/lang/CharSequence;)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/CharSequence;megamorphic_types]Ljava/lang/AbstractStringBuilder;Ljava/lang/StringBuilder;,Ljava/lang/StringBuffer;
+HSPLjava/lang/AbstractStringBuilder;->append(Ljava/lang/CharSequence;II)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/CharSequence;Ljava/lang/String;,Ljava/nio/HeapCharBuffer;,Landroid/icu/impl/FormattedStringBuilder;,Landroid/text/SpannableStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->append(Ljava/lang/String;)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/AbstractStringBuilder;->append(Ljava/lang/StringBuffer;)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/lang/AbstractStringBuilder;->append(Z)Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->append([CII)Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->appendCodePoint(I)Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->appendNull()Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->charAt(I)C
+HSPLjava/lang/AbstractStringBuilder;->codePointAt(I)I
+HSPLjava/lang/AbstractStringBuilder;->delete(II)Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->deleteCharAt(I)Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->ensureCapacity(I)V
+HSPLjava/lang/AbstractStringBuilder;->ensureCapacityInternal(I)V
+HSPLjava/lang/AbstractStringBuilder;->getChars(II[CI)V
+HSPLjava/lang/AbstractStringBuilder;->indexOf(Ljava/lang/String;)I+]Ljava/lang/AbstractStringBuilder;Ljava/lang/StringBuilder;,Ljava/lang/StringBuffer;
+HSPLjava/lang/AbstractStringBuilder;->indexOf(Ljava/lang/String;I)I
+HSPLjava/lang/AbstractStringBuilder;->insert(IC)Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->insert(II)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/AbstractStringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->insert(ILjava/lang/String;)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/AbstractStringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->lastIndexOf(Ljava/lang/String;I)I
+HSPLjava/lang/AbstractStringBuilder;->length()I
+HSPLjava/lang/AbstractStringBuilder;->newCapacity(I)I
+HSPLjava/lang/AbstractStringBuilder;->replace(IILjava/lang/String;)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/AbstractStringBuilder;->reverse()Ljava/lang/AbstractStringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->setCharAt(IC)V
+HSPLjava/lang/AbstractStringBuilder;->setLength(I)V
+HSPLjava/lang/AbstractStringBuilder;->subSequence(II)Ljava/lang/CharSequence;+]Ljava/lang/AbstractStringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->substring(I)Ljava/lang/String;+]Ljava/lang/AbstractStringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/AbstractStringBuilder;->substring(II)Ljava/lang/String;
+HSPLjava/lang/Boolean;-><init>(Z)V
+HSPLjava/lang/Boolean;->booleanValue()Z
+HSPLjava/lang/Boolean;->compare(ZZ)I
+HSPLjava/lang/Boolean;->compareTo(Ljava/lang/Boolean;)I
+HSPLjava/lang/Boolean;->compareTo(Ljava/lang/Object;)I+]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLjava/lang/Boolean;->equals(Ljava/lang/Object;)Z+]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLjava/lang/Boolean;->getBoolean(Ljava/lang/String;)Z
+HSPLjava/lang/Boolean;->hashCode()I
+HSPLjava/lang/Boolean;->hashCode(Z)I
+HSPLjava/lang/Boolean;->parseBoolean(Ljava/lang/String;)Z+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/Boolean;->toString()Ljava/lang/String;
+HSPLjava/lang/Boolean;->toString(Z)Ljava/lang/String;
+HSPLjava/lang/Boolean;->valueOf(Ljava/lang/String;)Ljava/lang/Boolean;
+HSPLjava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
+HSPLjava/lang/BootClassLoader;->findClass(Ljava/lang/String;)Ljava/lang/Class;
+HSPLjava/lang/BootClassLoader;->findResource(Ljava/lang/String;)Ljava/net/URL;
+HSPLjava/lang/BootClassLoader;->findResources(Ljava/lang/String;)Ljava/util/Enumeration;
+HSPLjava/lang/BootClassLoader;->getInstance()Ljava/lang/BootClassLoader;
+HSPLjava/lang/BootClassLoader;->getResource(Ljava/lang/String;)Ljava/net/URL;+]Ljava/lang/BootClassLoader;Ljava/lang/BootClassLoader;
+HSPLjava/lang/BootClassLoader;->getResources(Ljava/lang/String;)Ljava/util/Enumeration;+]Ljava/lang/BootClassLoader;Ljava/lang/BootClassLoader;
+HSPLjava/lang/BootClassLoader;->loadClass(Ljava/lang/String;Z)Ljava/lang/Class;+]Ljava/lang/BootClassLoader;Ljava/lang/BootClassLoader;
+HSPLjava/lang/Byte;-><init>(B)V
+HSPLjava/lang/Byte;->byteValue()B
+HSPLjava/lang/Byte;->compare(BB)I
+HSPLjava/lang/Byte;->equals(Ljava/lang/Object;)Z+]Ljava/lang/Byte;Ljava/lang/Byte;
+HSPLjava/lang/Byte;->hashCode()I
+HSPLjava/lang/Byte;->hashCode(B)I
+HSPLjava/lang/Byte;->parseByte(Ljava/lang/String;I)B
+HSPLjava/lang/Byte;->toString()Ljava/lang/String;
+HSPLjava/lang/Byte;->toString(B)Ljava/lang/String;
+HSPLjava/lang/Byte;->toUnsignedInt(B)I
+HSPLjava/lang/Byte;->valueOf(B)Ljava/lang/Byte;
+HSPLjava/lang/CaseMapper;->toLowerCase(Ljava/util/Locale;Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Locale;Ljava/util/Locale;
+HSPLjava/lang/CaseMapper;->toUpperCase(Ljava/util/Locale;Ljava/lang/String;I)Ljava/lang/String;+]Ljava/util/Locale;Ljava/util/Locale;
+HSPLjava/lang/CaseMapper;->upperIndex(I)I
+HSPLjava/lang/Character$Subset;->hashCode()I
+HSPLjava/lang/Character$UnicodeBlock;->of(I)Ljava/lang/Character$UnicodeBlock;
+HSPLjava/lang/Character;-><init>(C)V
+HSPLjava/lang/Character;->charCount(I)I
+HSPLjava/lang/Character;->charValue()C
+HSPLjava/lang/Character;->codePointAt(Ljava/lang/CharSequence;I)I+]Ljava/lang/CharSequence;megamorphic_types
+HSPLjava/lang/Character;->codePointAtImpl([CII)I
+HSPLjava/lang/Character;->codePointBefore(Ljava/lang/CharSequence;I)I+]Ljava/lang/CharSequence;missing_types
+HSPLjava/lang/Character;->codePointCount(Ljava/lang/CharSequence;II)I+]Ljava/lang/CharSequence;missing_types
+HSPLjava/lang/Character;->digit(CI)I
+HSPLjava/lang/Character;->digit(II)I
+HSPLjava/lang/Character;->equals(Ljava/lang/Object;)Z+]Ljava/lang/Character;Ljava/lang/Character;
+HSPLjava/lang/Character;->forDigit(II)C
+HSPLjava/lang/Character;->getDirectionality(C)B
+HSPLjava/lang/Character;->getDirectionality(I)B
+HSPLjava/lang/Character;->getNumericValue(C)I
+HSPLjava/lang/Character;->getNumericValue(I)I
+HSPLjava/lang/Character;->getType(I)I
+HSPLjava/lang/Character;->hashCode()I
+HSPLjava/lang/Character;->hashCode(C)I
+HSPLjava/lang/Character;->highSurrogate(I)C
+HSPLjava/lang/Character;->isBmpCodePoint(I)Z
+HSPLjava/lang/Character;->isDigit(C)Z
+HSPLjava/lang/Character;->isDigit(I)Z
+HSPLjava/lang/Character;->isHighSurrogate(C)Z
+HSPLjava/lang/Character;->isISOControl(I)Z
+HSPLjava/lang/Character;->isJavaIdentifierPart(C)Z
+HSPLjava/lang/Character;->isJavaIdentifierPart(I)Z
+HSPLjava/lang/Character;->isLetter(C)Z
+HSPLjava/lang/Character;->isLetter(I)Z
+HSPLjava/lang/Character;->isLetterOrDigit(C)Z
+HSPLjava/lang/Character;->isLetterOrDigit(I)Z
+HSPLjava/lang/Character;->isLowSurrogate(C)Z
+HSPLjava/lang/Character;->isLowerCase(I)Z
+HSPLjava/lang/Character;->isSpaceChar(C)Z
+HSPLjava/lang/Character;->isSpaceChar(I)Z
+HSPLjava/lang/Character;->isSurrogate(C)Z
+HSPLjava/lang/Character;->isSurrogatePair(CC)Z
+HSPLjava/lang/Character;->isUpperCase(C)Z
+HSPLjava/lang/Character;->isUpperCase(I)Z
+HSPLjava/lang/Character;->isValidCodePoint(I)Z
+HSPLjava/lang/Character;->isWhitespace(C)Z
+HSPLjava/lang/Character;->isWhitespace(I)Z
+HSPLjava/lang/Character;->lowSurrogate(I)C
+HSPLjava/lang/Character;->toChars(I)[C
+HSPLjava/lang/Character;->toChars(I[CI)I
+HSPLjava/lang/Character;->toCodePoint(CC)I
+HSPLjava/lang/Character;->toLowerCase(C)C
+HSPLjava/lang/Character;->toLowerCase(I)I
+HSPLjava/lang/Character;->toString()Ljava/lang/String;
+HSPLjava/lang/Character;->toString(C)Ljava/lang/String;
+HSPLjava/lang/Character;->toSurrogates(I[CI)V
+HSPLjava/lang/Character;->toUpperCase(C)C
+HSPLjava/lang/Character;->toUpperCase(I)I
+HSPLjava/lang/Character;->valueOf(C)Ljava/lang/Character;
+HSPLjava/lang/Class$Caches;->access$000()Llibcore/util/BasicLruCache;
+HSPLjava/lang/Class;->asSubclass(Ljava/lang/Class;)Ljava/lang/Class;+]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/Class;->cast(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->classNameImpliesTopLevel()Z+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->desiredAssertionStatus()Z
+HSPLjava/lang/Class;->findInterfaceMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class;
+HSPLjava/lang/Class;->forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;+]Ljava/lang/ClassNotFoundException;Ljava/lang/ClassNotFoundException;
+HSPLjava/lang/Class;->getAccessFlags()I
+HSPLjava/lang/Class;->getAnnotation(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getCanonicalName()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getClassLoader()Ljava/lang/ClassLoader;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getComponentType()Ljava/lang/Class;
+HSPLjava/lang/Class;->getConstructor([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
+HSPLjava/lang/Class;->getConstructor0([Ljava/lang/Class;I)Ljava/lang/reflect/Constructor;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/reflect/Constructor;Ljava/lang/reflect/Constructor;
+HSPLjava/lang/Class;->getConstructors()[Ljava/lang/reflect/Constructor;
+HSPLjava/lang/Class;->getDeclaredConstructor([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
+HSPLjava/lang/Class;->getDeclaredConstructors()[Ljava/lang/reflect/Constructor;
+HSPLjava/lang/Class;->getDeclaredMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
+HSPLjava/lang/Class;->getDeclaredMethods()[Ljava/lang/reflect/Method;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getEnclosingConstructor()Ljava/lang/reflect/Constructor;
+HSPLjava/lang/Class;->getEnclosingMethod()Ljava/lang/reflect/Method;
+HSPLjava/lang/Class;->getEnumConstants()[Ljava/lang/Object;+]Ljava/lang/Class;Ljava/lang/Class;][Ljava/lang/Object;missing_types
+HSPLjava/lang/Class;->getEnumConstantsShared()[Ljava/lang/Object;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getField(Ljava/lang/String;)Ljava/lang/reflect/Field;
+HSPLjava/lang/Class;->getFields()[Ljava/lang/reflect/Field;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLjava/lang/Class;->getGenericInterfaces()[Ljava/lang/reflect/Type;+]Llibcore/util/BasicLruCache;missing_types]Ljava/lang/Class;Ljava/lang/Class;]Llibcore/reflect/GenericSignatureParser;missing_types][Ljava/lang/reflect/Type;[Ljava/lang/Class;,[Ljava/lang/reflect/Type;
+HSPLjava/lang/Class;->getGenericSuperclass()Ljava/lang/reflect/Type;+]Llibcore/reflect/GenericSignatureParser;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getInterfaces()[Ljava/lang/Class;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
+HSPLjava/lang/Class;->getMethod(Ljava/lang/String;[Ljava/lang/Class;Z)Ljava/lang/reflect/Method;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getMethods()[Ljava/lang/reflect/Method;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLjava/lang/Class;->getModifiers()I+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getName()Ljava/lang/String;
+HSPLjava/lang/Class;->getPackage()Ljava/lang/Package;+]Ljava/lang/ClassLoader;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getPackageName()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getProtectionDomain()Ljava/security/ProtectionDomain;
+HSPLjava/lang/Class;->getPublicFieldsRecursive(Ljava/util/List;)V
+HSPLjava/lang/Class;->getPublicMethodRecursive(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getPublicMethodsInternal(Ljava/util/List;)V+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getResourceAsStream(Ljava/lang/String;)Ljava/io/InputStream;
+HSPLjava/lang/Class;->getSignatureAttribute()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/Class;->getSimpleName()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/Class;->getSuperclass()Ljava/lang/Class;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->getTypeName()Ljava/lang/String;+]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/Class;->getTypeParameters()[Ljava/lang/reflect/TypeVariable;+]Ljava/lang/Class;Ljava/lang/Class;]Llibcore/reflect/GenericSignatureParser;missing_types
+HSPLjava/lang/Class;->isAnnotation()Z+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->isAnnotationPresent(Ljava/lang/Class;)Z+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->isArray()Z+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->isAssignableFrom(Ljava/lang/Class;)Z+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->isEnum()Z+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->isInstance(Ljava/lang/Object;)Z+]Ljava/lang/Object;megamorphic_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->isInterface()Z
+HSPLjava/lang/Class;->isLocalClass()Z+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->isLocalOrAnonymousClass()Z+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->isMemberClass()Z+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Class;->isPrimitive()Z
+HSPLjava/lang/Class;->isProxy()Z
+HSPLjava/lang/Class;->resolveName(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/Class;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/ClassCastException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/ClassLoader;-><init>()V
+HSPLjava/lang/ClassLoader;-><init>(Ljava/lang/ClassLoader;)V
+HSPLjava/lang/ClassLoader;-><init>(Ljava/lang/Void;Ljava/lang/ClassLoader;)V
+HSPLjava/lang/ClassLoader;->checkCreateClassLoader()Ljava/lang/Void;
+HSPLjava/lang/ClassLoader;->definePackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/net/URL;)Ljava/lang/Package;
+HSPLjava/lang/ClassLoader;->findLoadedClass(Ljava/lang/String;)Ljava/lang/Class;
+HSPLjava/lang/ClassLoader;->getClassLoader(Ljava/lang/Class;)Ljava/lang/ClassLoader;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/ClassLoader;->getPackage(Ljava/lang/String;)Ljava/lang/Package;+]Ljava/util/HashMap;Ljava/util/HashMap;
+HSPLjava/lang/ClassLoader;->getParent()Ljava/lang/ClassLoader;
+HSPLjava/lang/ClassLoader;->getResource(Ljava/lang/String;)Ljava/net/URL;+]Ljava/lang/ClassLoader;Ldalvik/system/PathClassLoader;,Ljava/lang/BootClassLoader;
+HSPLjava/lang/ClassLoader;->getResourceAsStream(Ljava/lang/String;)Ljava/io/InputStream;+]Ljava/net/URL;Ljava/net/URL;]Ljava/lang/ClassLoader;Ldalvik/system/PathClassLoader;
+HSPLjava/lang/ClassLoader;->getResources(Ljava/lang/String;)Ljava/util/Enumeration;+]Ljava/lang/ClassLoader;Ldalvik/system/PathClassLoader;,Ljava/lang/BootClassLoader;
+HSPLjava/lang/ClassLoader;->getSystemClassLoader()Ljava/lang/ClassLoader;
+HSPLjava/lang/ClassLoader;->loadClass(Ljava/lang/String;)Ljava/lang/Class;+]Ljava/lang/ClassLoader;missing_types
+HSPLjava/lang/ClassLoader;->loadClass(Ljava/lang/String;Z)Ljava/lang/Class;+]Ljava/lang/ClassLoader;missing_types
+HSPLjava/lang/ClassNotFoundException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/ClassNotFoundException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+HSPLjava/lang/ClassNotFoundException;->getCause()Ljava/lang/Throwable;
+HSPLjava/lang/Daemons$Daemon;->interrupt(Ljava/lang/Thread;)V
+HSPLjava/lang/Daemons$Daemon;->isRunning()Z
+HSPLjava/lang/Daemons$Daemon;->run()V+]Ljava/lang/Daemons$Daemon;Ljava/lang/Daemons$ReferenceQueueDaemon;,Ljava/lang/Daemons$FinalizerDaemon;,Ljava/lang/Daemons$FinalizerWatchdogDaemon;,Ljava/lang/Daemons$HeapTaskDaemon;]Ljava/util/concurrent/CountDownLatch;Ljava/util/concurrent/CountDownLatch;
+HSPLjava/lang/Daemons$Daemon;->startInternal()V+]Ljava/lang/Thread;Ljava/lang/Thread;
+HSPLjava/lang/Daemons$Daemon;->startPostZygoteFork()V+]Ljava/lang/Daemons$Daemon;Ljava/lang/Daemons$FinalizerWatchdogDaemon;
+HSPLjava/lang/Daemons$Daemon;->stop()V
+HSPLjava/lang/Daemons$FinalizerDaemon;->access$200()Ljava/lang/Daemons$FinalizerDaemon;
+HSPLjava/lang/Daemons$FinalizerDaemon;->access$900(Ljava/lang/Daemons$FinalizerDaemon;)Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/lang/Daemons$FinalizerDaemon;->doFinalize(Ljava/lang/ref/FinalizerReference;)V+]Ljava/lang/Object;megamorphic_types]Ljava/lang/ref/FinalizerReference;Ljava/lang/ref/FinalizerReference;
+HSPLjava/lang/Daemons$FinalizerDaemon;->runInternal()V
+HSPLjava/lang/Daemons$FinalizerWatchdogDaemon;->access$300()Ljava/lang/Daemons$FinalizerWatchdogDaemon;
+HSPLjava/lang/Daemons$FinalizerWatchdogDaemon;->access$600(Ljava/lang/Daemons$FinalizerWatchdogDaemon;)V
+HSPLjava/lang/Daemons$FinalizerWatchdogDaemon;->access$700(Ljava/lang/Daemons$FinalizerWatchdogDaemon;)V
+HSPLjava/lang/Daemons$FinalizerWatchdogDaemon;->getNeedToWork()Z
+HSPLjava/lang/Daemons$FinalizerWatchdogDaemon;->goToSleep()V
+HSPLjava/lang/Daemons$FinalizerWatchdogDaemon;->runInternal()V
+HSPLjava/lang/Daemons$FinalizerWatchdogDaemon;->sleepForNanos(J)Z
+HSPLjava/lang/Daemons$FinalizerWatchdogDaemon;->sleepUntilNeeded()Z+]Ljava/lang/Object;Ljava/lang/Daemons$FinalizerWatchdogDaemon;
+HSPLjava/lang/Daemons$FinalizerWatchdogDaemon;->waitForFinalization()Ljava/lang/Object;+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/lang/Daemons$FinalizerWatchdogDaemon;->wakeUp()V+]Ljava/lang/Object;Ljava/lang/Daemons$FinalizerWatchdogDaemon;
+HSPLjava/lang/Daemons$HeapTaskDaemon;->interrupt(Ljava/lang/Thread;)V
+HSPLjava/lang/Daemons$HeapTaskDaemon;->runInternal()V
+HSPLjava/lang/Daemons$ReferenceQueueDaemon;->runInternal()V
+HSPLjava/lang/Daemons;->access$400()Ljava/util/concurrent/CountDownLatch;
+HSPLjava/lang/Daemons;->access$802(J)J
+HSPLjava/lang/Daemons;->startPostZygoteFork()V
+HSPLjava/lang/Daemons;->stop()V
+HSPLjava/lang/Double;-><init>(D)V
+HSPLjava/lang/Double;->compare(DD)I
+HSPLjava/lang/Double;->compareTo(Ljava/lang/Double;)I
+HSPLjava/lang/Double;->compareTo(Ljava/lang/Object;)I+]Ljava/lang/Double;Ljava/lang/Double;
+HSPLjava/lang/Double;->doubleToLongBits(D)J
+HSPLjava/lang/Double;->doubleValue()D
+HSPLjava/lang/Double;->equals(Ljava/lang/Object;)Z
+HSPLjava/lang/Double;->floatValue()F
+HSPLjava/lang/Double;->hashCode()I
+HSPLjava/lang/Double;->hashCode(D)I
+HSPLjava/lang/Double;->intValue()I
+HSPLjava/lang/Double;->isInfinite(D)Z
+HSPLjava/lang/Double;->isNaN(D)Z
+HSPLjava/lang/Double;->longValue()J
+HSPLjava/lang/Double;->parseDouble(Ljava/lang/String;)D
+HSPLjava/lang/Double;->toString()Ljava/lang/String;
+HSPLjava/lang/Double;->toString(D)Ljava/lang/String;
+HSPLjava/lang/Double;->valueOf(D)Ljava/lang/Double;
+HSPLjava/lang/Double;->valueOf(Ljava/lang/String;)Ljava/lang/Double;
+HSPLjava/lang/Enum$1;->create(Ljava/lang/Class;)[Ljava/lang/Object;
+HSPLjava/lang/Enum$1;->create(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/Enum$1;Ljava/lang/Enum$1;
+HSPLjava/lang/Enum;-><init>(Ljava/lang/String;I)V
+HSPLjava/lang/Enum;->access$000(Ljava/lang/Class;)[Ljava/lang/Object;
+HSPLjava/lang/Enum;->compareTo(Ljava/lang/Enum;)I+]Ljava/lang/Object;missing_types]Ljava/lang/Enum;missing_types
+HSPLjava/lang/Enum;->compareTo(Ljava/lang/Object;)I
+HSPLjava/lang/Enum;->enumValues(Ljava/lang/Class;)[Ljava/lang/Object;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Enum;->equals(Ljava/lang/Object;)Z
+HSPLjava/lang/Enum;->getDeclaringClass()Ljava/lang/Class;+]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/Object;missing_types
+HSPLjava/lang/Enum;->getSharedConstants(Ljava/lang/Class;)[Ljava/lang/Enum;+]Llibcore/util/BasicLruCache;Ljava/lang/Enum$1;
+HSPLjava/lang/Enum;->hashCode()I
+HSPLjava/lang/Enum;->name()Ljava/lang/String;
+HSPLjava/lang/Enum;->ordinal()I
+HSPLjava/lang/Enum;->toString()Ljava/lang/String;
+HSPLjava/lang/Enum;->valueOf(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;+]Ljava/lang/Enum;megamorphic_types]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Error;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/Exception;-><init>()V
+HSPLjava/lang/Exception;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/Exception;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+HSPLjava/lang/Exception;-><init>(Ljava/lang/String;Ljava/lang/Throwable;ZZ)V
+HSPLjava/lang/Exception;-><init>(Ljava/lang/Throwable;)V
+HSPLjava/lang/Float;-><init>(F)V
+HSPLjava/lang/Float;->compare(FF)I
+HSPLjava/lang/Float;->compareTo(Ljava/lang/Float;)I
+HSPLjava/lang/Float;->compareTo(Ljava/lang/Object;)I+]Ljava/lang/Float;Ljava/lang/Float;
+HSPLjava/lang/Float;->doubleValue()D
+HSPLjava/lang/Float;->equals(Ljava/lang/Object;)Z
+HSPLjava/lang/Float;->floatToIntBits(F)I
+HSPLjava/lang/Float;->floatValue()F
+HSPLjava/lang/Float;->hashCode()I
+HSPLjava/lang/Float;->hashCode(F)I
+HSPLjava/lang/Float;->isFinite(F)Z
+HSPLjava/lang/Float;->isInfinite(F)Z
+HSPLjava/lang/Float;->isNaN(F)Z
+HSPLjava/lang/Float;->parseFloat(Ljava/lang/String;)F
+HSPLjava/lang/Float;->toString()Ljava/lang/String;
+HSPLjava/lang/Float;->toString(F)Ljava/lang/String;
+HSPLjava/lang/Float;->valueOf(F)Ljava/lang/Float;
+HSPLjava/lang/Float;->valueOf(Ljava/lang/String;)Ljava/lang/Float;
+HSPLjava/lang/IllegalAccessException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/IllegalArgumentException;-><init>()V
+HSPLjava/lang/IllegalArgumentException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/IllegalArgumentException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+HSPLjava/lang/IllegalStateException;-><init>()V
+HSPLjava/lang/IllegalStateException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/IllegalStateException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+HSPLjava/lang/IncompatibleClassChangeError;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/IndexOutOfBoundsException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/InheritableThreadLocal;->childValue(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/lang/InheritableThreadLocal;->createMap(Ljava/lang/Thread;Ljava/lang/Object;)V
+HSPLjava/lang/InheritableThreadLocal;->getMap(Ljava/lang/Thread;)Ljava/lang/ThreadLocal$ThreadLocalMap;
+HSPLjava/lang/Integer;-><init>(I)V
+HSPLjava/lang/Integer;->bitCount(I)I
+HSPLjava/lang/Integer;->byteValue()B
+HSPLjava/lang/Integer;->compare(II)I
+HSPLjava/lang/Integer;->compareTo(Ljava/lang/Integer;)I
+HSPLjava/lang/Integer;->compareTo(Ljava/lang/Object;)I+]Ljava/lang/Integer;Ljava/lang/Integer;
+HSPLjava/lang/Integer;->decode(Ljava/lang/String;)Ljava/lang/Integer;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/Integer;Ljava/lang/Integer;
+HSPLjava/lang/Integer;->divideUnsigned(II)I
+HSPLjava/lang/Integer;->doubleValue()D
+HSPLjava/lang/Integer;->equals(Ljava/lang/Object;)Z+]Ljava/lang/Integer;Ljava/lang/Integer;
+HSPLjava/lang/Integer;->formatUnsignedInt(II[CII)I
+HSPLjava/lang/Integer;->getChars(II[C)V
+HSPLjava/lang/Integer;->getInteger(Ljava/lang/String;I)Ljava/lang/Integer;
+HSPLjava/lang/Integer;->getInteger(Ljava/lang/String;Ljava/lang/Integer;)Ljava/lang/Integer;
+HSPLjava/lang/Integer;->hashCode()I
+HSPLjava/lang/Integer;->hashCode(I)I
+HSPLjava/lang/Integer;->highestOneBit(I)I
+HSPLjava/lang/Integer;->intValue()I
+HSPLjava/lang/Integer;->longValue()J
+HSPLjava/lang/Integer;->lowestOneBit(I)I
+HSPLjava/lang/Integer;->max(II)I
+HSPLjava/lang/Integer;->min(II)I
+HSPLjava/lang/Integer;->numberOfLeadingZeros(I)I
+HSPLjava/lang/Integer;->numberOfTrailingZeros(I)I
+HSPLjava/lang/Integer;->parseInt(Ljava/lang/String;)I
+HSPLjava/lang/Integer;->parseInt(Ljava/lang/String;I)I
+HSPLjava/lang/Integer;->reverse(I)I
+HSPLjava/lang/Integer;->reverseBytes(I)I
+HSPLjava/lang/Integer;->rotateLeft(II)I
+HSPLjava/lang/Integer;->rotateRight(II)I
+HSPLjava/lang/Integer;->shortValue()S
+HSPLjava/lang/Integer;->signum(I)I
+HSPLjava/lang/Integer;->stringSize(I)I
+HSPLjava/lang/Integer;->sum(II)I
+HSPLjava/lang/Integer;->toBinaryString(I)Ljava/lang/String;
+HSPLjava/lang/Integer;->toHexString(I)Ljava/lang/String;
+HSPLjava/lang/Integer;->toString()Ljava/lang/String;
+HSPLjava/lang/Integer;->toString(I)Ljava/lang/String;
+HSPLjava/lang/Integer;->toString(II)Ljava/lang/String;
+HSPLjava/lang/Integer;->toUnsignedLong(I)J
+HSPLjava/lang/Integer;->toUnsignedString0(II)Ljava/lang/String;
+HSPLjava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
+HSPLjava/lang/Integer;->valueOf(Ljava/lang/String;)Ljava/lang/Integer;
+HSPLjava/lang/Integer;->valueOf(Ljava/lang/String;I)Ljava/lang/Integer;
+HSPLjava/lang/InterruptedException;-><init>()V
+HSPLjava/lang/Iterable;->forEach(Ljava/util/function/Consumer;)V+]Ljava/lang/Iterable;missing_types]Ljava/util/Iterator;missing_types
+HSPLjava/lang/LinkageError;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/Long;-><init>(J)V
+HSPLjava/lang/Long;->bitCount(J)I
+HSPLjava/lang/Long;->compare(JJ)I
+HSPLjava/lang/Long;->compareTo(Ljava/lang/Long;)I
+HSPLjava/lang/Long;->compareTo(Ljava/lang/Object;)I+]Ljava/lang/Long;Ljava/lang/Long;
+HSPLjava/lang/Long;->compareUnsigned(JJ)I
+HSPLjava/lang/Long;->decode(Ljava/lang/String;)Ljava/lang/Long;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/Long;Ljava/lang/Long;
+HSPLjava/lang/Long;->divideUnsigned(JJ)J
+HSPLjava/lang/Long;->doubleValue()D
+HSPLjava/lang/Long;->equals(Ljava/lang/Object;)Z+]Ljava/lang/Long;Ljava/lang/Long;
+HSPLjava/lang/Long;->formatUnsignedLong(JI[CII)I
+HSPLjava/lang/Long;->getChars(JI[C)V
+HSPLjava/lang/Long;->getLong(Ljava/lang/String;J)Ljava/lang/Long;
+HSPLjava/lang/Long;->getLong(Ljava/lang/String;Ljava/lang/Long;)Ljava/lang/Long;
+HSPLjava/lang/Long;->hashCode()I
+HSPLjava/lang/Long;->hashCode(J)I
+HSPLjava/lang/Long;->highestOneBit(J)J
+HSPLjava/lang/Long;->intValue()I
+HSPLjava/lang/Long;->longValue()J
+HSPLjava/lang/Long;->lowestOneBit(J)J
+HSPLjava/lang/Long;->numberOfLeadingZeros(J)I
+HSPLjava/lang/Long;->numberOfTrailingZeros(J)I
+HSPLjava/lang/Long;->parseLong(Ljava/lang/String;)J
+HSPLjava/lang/Long;->parseLong(Ljava/lang/String;I)J
+HSPLjava/lang/Long;->reverse(J)J
+HSPLjava/lang/Long;->reverseBytes(J)J
+HSPLjava/lang/Long;->rotateLeft(JI)J
+HSPLjava/lang/Long;->rotateRight(JI)J
+HSPLjava/lang/Long;->signum(J)I
+HSPLjava/lang/Long;->stringSize(J)I
+HSPLjava/lang/Long;->sum(JJ)J
+HSPLjava/lang/Long;->toHexString(J)Ljava/lang/String;
+HSPLjava/lang/Long;->toString()Ljava/lang/String;
+HSPLjava/lang/Long;->toString(J)Ljava/lang/String;
+HSPLjava/lang/Long;->toString(JI)Ljava/lang/String;
+HSPLjava/lang/Long;->toUnsignedString0(JI)Ljava/lang/String;
+HSPLjava/lang/Long;->valueOf(J)Ljava/lang/Long;
+HSPLjava/lang/Long;->valueOf(Ljava/lang/String;)Ljava/lang/Long;
+HSPLjava/lang/Long;->valueOf(Ljava/lang/String;I)Ljava/lang/Long;
+HSPLjava/lang/Math;->abs(D)D
+HSPLjava/lang/Math;->abs(F)F
+HSPLjava/lang/Math;->abs(I)I
+HSPLjava/lang/Math;->abs(J)J
+HSPLjava/lang/Math;->addExact(JJ)J
+HSPLjava/lang/Math;->copySign(DD)D
+HSPLjava/lang/Math;->copySign(FF)F
+HSPLjava/lang/Math;->floorDiv(II)I
+HSPLjava/lang/Math;->floorDiv(JI)J
+HSPLjava/lang/Math;->floorDiv(JJ)J
+HSPLjava/lang/Math;->floorMod(II)I
+HSPLjava/lang/Math;->floorMod(JI)I
+HSPLjava/lang/Math;->floorMod(JJ)J
+HSPLjava/lang/Math;->getExponent(D)I
+HSPLjava/lang/Math;->getExponent(F)I
+HSPLjava/lang/Math;->max(DD)D
+HSPLjava/lang/Math;->max(FF)F
+HSPLjava/lang/Math;->max(II)I
+HSPLjava/lang/Math;->max(JJ)J
+HSPLjava/lang/Math;->min(DD)D
+HSPLjava/lang/Math;->min(FF)F
+HSPLjava/lang/Math;->min(II)I
+HSPLjava/lang/Math;->min(JJ)J
+HSPLjava/lang/Math;->multiplyExact(JI)J
+HSPLjava/lang/Math;->multiplyExact(JJ)J
+HSPLjava/lang/Math;->multiplyHigh(JJ)J
+HSPLjava/lang/Math;->nextAfter(DD)D
+HSPLjava/lang/Math;->powerOfTwoD(I)D
+HSPLjava/lang/Math;->powerOfTwoF(I)F
+HSPLjava/lang/Math;->random()D+]Ljava/util/Random;Ljava/util/Random;
+HSPLjava/lang/Math;->randomLongInternal()J+]Ljava/util/Random;Ljava/util/Random;
+HSPLjava/lang/Math;->round(D)J
+HSPLjava/lang/Math;->round(F)I
+HSPLjava/lang/Math;->scalb(FI)F
+HSPLjava/lang/Math;->setRandomSeedInternal(J)V
+HSPLjava/lang/Math;->signum(F)F
+HSPLjava/lang/Math;->subtractExact(JJ)J
+HSPLjava/lang/Math;->toDegrees(D)D
+HSPLjava/lang/Math;->toIntExact(J)I
+HSPLjava/lang/Math;->toRadians(D)D
+HSPLjava/lang/Math;->ulp(F)F
+HSPLjava/lang/NoClassDefFoundError;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/NoSuchFieldException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/NoSuchMethodError;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/NoSuchMethodException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/NullPointerException;-><init>()V
+HSPLjava/lang/NullPointerException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/Number;-><init>()V
+HSPLjava/lang/NumberFormatException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/NumberFormatException;->forInputString(Ljava/lang/String;)Ljava/lang/NumberFormatException;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/Object;-><init>()V
+HSPLjava/lang/Object;->clone()Ljava/lang/Object;
+HSPLjava/lang/Object;->equals(Ljava/lang/Object;)Z
+HSPLjava/lang/Object;->finalize()V
+HSPLjava/lang/Object;->getClass()Ljava/lang/Class;
+HSPLjava/lang/Object;->hashCode()I
+HSPLjava/lang/Object;->identityHashCode(Ljava/lang/Object;)I
+HSPLjava/lang/Object;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Object;megamorphic_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Object;->wait()V+]Ljava/lang/Object;megamorphic_types
+HSPLjava/lang/Object;->wait(J)V+]Ljava/lang/Object;megamorphic_types
+HSPLjava/lang/Package;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/net/URL;Ljava/lang/ClassLoader;)V
+HSPLjava/lang/Package;->getName()Ljava/lang/String;
+HSPLjava/lang/Process;-><init>()V
+HSPLjava/lang/ProcessBuilder$NullInputStream;->available()I
+HSPLjava/lang/ProcessBuilder$NullInputStream;->read()I
+HSPLjava/lang/ProcessBuilder;-><init>([Ljava/lang/String;)V+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLjava/lang/ProcessBuilder;->directory(Ljava/io/File;)Ljava/lang/ProcessBuilder;
+HSPLjava/lang/ProcessBuilder;->environment([Ljava/lang/String;)Ljava/lang/ProcessBuilder;
+HSPLjava/lang/ProcessBuilder;->start()Ljava/lang/Process;+]Ljava/util/List;Ljava/util/ArrayList;][Ljava/lang/String;[Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Exception;Ljava/io/IOException;
+HSPLjava/lang/ProcessEnvironment;->toEnvironmentBlock(Ljava/util/Map;[I)[B
+HSPLjava/lang/ProcessImpl;->start([Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;[Ljava/lang/ProcessBuilder$Redirect;Z)Ljava/lang/Process;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/ProcessImpl;->toCString(Ljava/lang/String;)[B+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/ReflectiveOperationException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/ReflectiveOperationException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+HSPLjava/lang/ReflectiveOperationException;-><init>(Ljava/lang/Throwable;)V
+HSPLjava/lang/Runtime;->addShutdownHook(Ljava/lang/Thread;)V
+HSPLjava/lang/Runtime;->availableProcessors()I+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;
+HSPLjava/lang/Runtime;->exec(Ljava/lang/String;)Ljava/lang/Process;+]Ljava/lang/Runtime;Ljava/lang/Runtime;
+HSPLjava/lang/Runtime;->exec(Ljava/lang/String;[Ljava/lang/String;Ljava/io/File;)Ljava/lang/Process;+]Ljava/util/StringTokenizer;Ljava/util/StringTokenizer;]Ljava/lang/Runtime;Ljava/lang/Runtime;
+HSPLjava/lang/Runtime;->exec([Ljava/lang/String;)Ljava/lang/Process;
+HSPLjava/lang/Runtime;->exec([Ljava/lang/String;[Ljava/lang/String;Ljava/io/File;)Ljava/lang/Process;+]Ljava/lang/ProcessBuilder;Ljava/lang/ProcessBuilder;
+HSPLjava/lang/Runtime;->gc()V+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLjava/lang/Runtime;->getLibPaths()[Ljava/lang/String;
+HSPLjava/lang/Runtime;->getRuntime()Ljava/lang/Runtime;
+HSPLjava/lang/Runtime;->load0(Ljava/lang/Class;Ljava/lang/String;)V+]Ljava/io/File;Ljava/io/File;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/Runtime;->loadLibrary0(Ljava/lang/Class;Ljava/lang/String;)V
+HSPLjava/lang/Runtime;->loadLibrary0(Ljava/lang/ClassLoader;Ljava/lang/Class;Ljava/lang/String;)V+]Ljava/lang/Object;Ldalvik/system/PathClassLoader;]Ljava/lang/ClassLoader;Ldalvik/system/PathClassLoader;
+HSPLjava/lang/Runtime;->nativeLoad(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/String;
+HSPLjava/lang/Runtime;->runFinalization()V
+HSPLjava/lang/RuntimeException;-><init>()V
+HSPLjava/lang/RuntimeException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/RuntimeException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+HSPLjava/lang/RuntimeException;-><init>(Ljava/lang/Throwable;)V
+HSPLjava/lang/SecurityException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/Short;-><init>(S)V
+HSPLjava/lang/Short;->hashCode()I
+HSPLjava/lang/Short;->hashCode(S)I
+HSPLjava/lang/Short;->parseShort(Ljava/lang/String;I)S
+HSPLjava/lang/Short;->reverseBytes(S)S
+HSPLjava/lang/Short;->shortValue()S
+HSPLjava/lang/Short;->toUnsignedInt(S)I
+HSPLjava/lang/Short;->valueOf(Ljava/lang/String;)Ljava/lang/Short;
+HSPLjava/lang/Short;->valueOf(Ljava/lang/String;I)Ljava/lang/Short;
+HSPLjava/lang/Short;->valueOf(S)Ljava/lang/Short;
+HSPLjava/lang/StackTraceElement;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V
+HSPLjava/lang/StackTraceElement;->equals(Ljava/lang/Object;)Z
+HSPLjava/lang/StackTraceElement;->getClassName()Ljava/lang/String;
+HSPLjava/lang/StackTraceElement;->getFileName()Ljava/lang/String;
+HSPLjava/lang/StackTraceElement;->getLineNumber()I
+HSPLjava/lang/StackTraceElement;->getMethodName()Ljava/lang/String;
+HSPLjava/lang/StackTraceElement;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/StackTraceElement;->isNativeMethod()Z
+HSPLjava/lang/StackTraceElement;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/StackTraceElement;Ljava/lang/StackTraceElement;
+HSPLjava/lang/String$CaseInsensitiveComparator;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/lang/String$CaseInsensitiveComparator;Ljava/lang/String$CaseInsensitiveComparator;
+HSPLjava/lang/String$CaseInsensitiveComparator;->compare(Ljava/lang/String;Ljava/lang/String;)I
+HSPLjava/lang/String;->codePointAt(I)I
+HSPLjava/lang/String;->codePointCount(II)I
+HSPLjava/lang/String;->compareTo(Ljava/lang/Object;)I
+HSPLjava/lang/String;->compareToIgnoreCase(Ljava/lang/String;)I+]Ljava/util/Comparator;Ljava/lang/String$CaseInsensitiveComparator;
+HSPLjava/lang/String;->contains(Ljava/lang/CharSequence;)Z+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/CharSequence;Ljava/lang/String;,Landroid/text/SpannableStringBuilder;,Landroid/text/SpannableString;
+HSPLjava/lang/String;->contentEquals(Ljava/lang/CharSequence;)Z+]Ljava/lang/CharSequence;Landroid/text/SpannableString;,Landroid/text/SpannedString;,Landroid/text/SpannableStringBuilder;
+HSPLjava/lang/String;->copyValueOf([C)Ljava/lang/String;
+HSPLjava/lang/String;->endsWith(Ljava/lang/String;)Z+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->equals(Ljava/lang/Object;)Z
+HSPLjava/lang/String;->equalsIgnoreCase(Ljava/lang/String;)Z+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->format(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;+]Ljava/util/Formatter;Ljava/util/Formatter;
+HSPLjava/lang/String;->format(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;+]Ljava/util/Formatter;Ljava/util/Formatter;
+HSPLjava/lang/String;->getBytes()[B+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->getBytes(Ljava/lang/String;)[B+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->getBytes(Ljava/nio/charset/Charset;)[B+]Ljava/nio/charset/Charset;missing_types]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/lang/String;->getChars(II[CI)V
+HSPLjava/lang/String;->getChars([CI)V
+HSPLjava/lang/String;->hashCode()I
+HSPLjava/lang/String;->indexOf(I)I
+HSPLjava/lang/String;->indexOf(II)I
+HSPLjava/lang/String;->indexOf(Ljava/lang/String;)I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->indexOf(Ljava/lang/String;I)I
+HSPLjava/lang/String;->indexOf(Ljava/lang/String;Ljava/lang/String;I)I
+HSPLjava/lang/String;->indexOf([CIILjava/lang/String;I)I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->indexOf([CII[CIII)I
+HSPLjava/lang/String;->isEmpty()Z
+HSPLjava/lang/String;->join(Ljava/lang/CharSequence;Ljava/lang/Iterable;)Ljava/lang/String;+]Ljava/util/StringJoiner;Ljava/util/StringJoiner;]Ljava/lang/Iterable;megamorphic_types]Ljava/util/Iterator;megamorphic_types
+HSPLjava/lang/String;->join(Ljava/lang/CharSequence;[Ljava/lang/CharSequence;)Ljava/lang/String;+]Ljava/util/StringJoiner;Ljava/util/StringJoiner;
+HSPLjava/lang/String;->lastIndexOf(I)I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->lastIndexOf(II)I
+HSPLjava/lang/String;->lastIndexOf(Ljava/lang/String;)I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->lastIndexOf(Ljava/lang/String;I)I
+HSPLjava/lang/String;->lastIndexOf(Ljava/lang/String;Ljava/lang/String;I)I
+HSPLjava/lang/String;->lastIndexOf([CIILjava/lang/String;I)I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->lastIndexOf([CII[CIII)I
+HSPLjava/lang/String;->length()I
+HSPLjava/lang/String;->matches(Ljava/lang/String;)Z
+HSPLjava/lang/String;->regionMatches(ILjava/lang/String;II)Z
+HSPLjava/lang/String;->regionMatches(ZILjava/lang/String;II)Z
+HSPLjava/lang/String;->replace(CC)Ljava/lang/String;
+HSPLjava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/CharSequence;Ljava/lang/String;,Ljava/lang/StringBuilder;
+HSPLjava/lang/String;->replaceAll(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;]Ljava/util/regex/Pattern;Ljava/util/regex/Pattern;
+HSPLjava/lang/String;->replaceFirst(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;]Ljava/util/regex/Pattern;Ljava/util/regex/Pattern;
+HSPLjava/lang/String;->split(Ljava/lang/String;)[Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->split(Ljava/lang/String;I)[Ljava/lang/String;+]Ljava/util/regex/Pattern;Ljava/util/regex/Pattern;
+HSPLjava/lang/String;->startsWith(Ljava/lang/String;)Z+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->startsWith(Ljava/lang/String;I)Z
+HSPLjava/lang/String;->subSequence(II)Ljava/lang/CharSequence;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->substring(I)Ljava/lang/String;
+HSPLjava/lang/String;->substring(II)Ljava/lang/String;
+HSPLjava/lang/String;->toLowerCase()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->toLowerCase(Ljava/util/Locale;)Ljava/lang/String;
+HSPLjava/lang/String;->toString()Ljava/lang/String;
+HSPLjava/lang/String;->toUpperCase()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->toUpperCase(Ljava/util/Locale;)Ljava/lang/String;
+HSPLjava/lang/String;->trim()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/lang/String;->valueOf(C)Ljava/lang/String;
+HSPLjava/lang/String;->valueOf(D)Ljava/lang/String;
+HSPLjava/lang/String;->valueOf(F)Ljava/lang/String;
+HSPLjava/lang/String;->valueOf(I)Ljava/lang/String;
+HSPLjava/lang/String;->valueOf(J)Ljava/lang/String;
+HSPLjava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;+]Ljava/lang/Object;megamorphic_types
+HSPLjava/lang/String;->valueOf(Z)Ljava/lang/String;
+HSPLjava/lang/String;->valueOf([C)Ljava/lang/String;
+HSPLjava/lang/StringBuffer;-><init>()V
+HSPLjava/lang/StringBuffer;-><init>(I)V
+HSPLjava/lang/StringBuffer;-><init>(Ljava/lang/String;)V+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(C)Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(I)Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(J)Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(Ljava/lang/CharSequence;)Ljava/lang/Appendable;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(Ljava/lang/CharSequence;)Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(Ljava/lang/CharSequence;II)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(Ljava/lang/CharSequence;II)Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(Ljava/lang/Object;)Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(Ljava/lang/String;)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(Ljava/lang/String;)Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append(Z)Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->append([CII)Ljava/lang/StringBuffer;
+HSPLjava/lang/StringBuffer;->charAt(I)C
+HSPLjava/lang/StringBuffer;->codePointAt(I)I
+HSPLjava/lang/StringBuffer;->getChars(II[CI)V
+HSPLjava/lang/StringBuffer;->length()I
+HSPLjava/lang/StringBuffer;->setLength(I)V
+HSPLjava/lang/StringBuffer;->toString()Ljava/lang/String;
+HSPLjava/lang/StringBuilder;-><init>()V
+HSPLjava/lang/StringBuilder;-><init>(I)V
+HSPLjava/lang/StringBuilder;-><init>(Ljava/lang/CharSequence;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/CharSequence;missing_types
+HSPLjava/lang/StringBuilder;-><init>(Ljava/lang/String;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(C)Ljava/lang/Appendable;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(C)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(D)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(F)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(J)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(Ljava/lang/CharSequence;)Ljava/lang/Appendable;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(Ljava/lang/CharSequence;)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(Ljava/lang/CharSequence;II)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(Ljava/lang/CharSequence;II)Ljava/lang/Appendable;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(Ljava/lang/CharSequence;II)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append(Z)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append([C)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->append([CII)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->appendCodePoint(I)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->charAt(I)C
+HSPLjava/lang/StringBuilder;->delete(II)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->deleteCharAt(I)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->ensureCapacity(I)V
+HSPLjava/lang/StringBuilder;->getChars(II[CI)V
+HSPLjava/lang/StringBuilder;->indexOf(Ljava/lang/String;)I
+HSPLjava/lang/StringBuilder;->indexOf(Ljava/lang/String;I)I
+HSPLjava/lang/StringBuilder;->insert(IC)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->insert(II)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->insert(ILjava/lang/String;)Ljava/lang/AbstractStringBuilder;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->insert(ILjava/lang/String;)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->lastIndexOf(Ljava/lang/String;I)I
+HSPLjava/lang/StringBuilder;->length()I
+HSPLjava/lang/StringBuilder;->replace(IILjava/lang/String;)Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->reverse()Ljava/lang/StringBuilder;
+HSPLjava/lang/StringBuilder;->setCharAt(IC)V
+HSPLjava/lang/StringBuilder;->setLength(I)V
+HSPLjava/lang/StringBuilder;->subSequence(II)Ljava/lang/CharSequence;
+HSPLjava/lang/StringBuilder;->substring(I)Ljava/lang/String;
+HSPLjava/lang/StringBuilder;->substring(II)Ljava/lang/String;
+HSPLjava/lang/StringBuilder;->toString()Ljava/lang/String;
+HSPLjava/lang/StringFactory;->newEmptyString()Ljava/lang/String;
+HSPLjava/lang/StringFactory;->newStringFromBytes([B)Ljava/lang/String;
+HSPLjava/lang/StringFactory;->newStringFromBytes([BI)Ljava/lang/String;
+HSPLjava/lang/StringFactory;->newStringFromBytes([BII)Ljava/lang/String;
+HSPLjava/lang/StringFactory;->newStringFromBytes([BIILjava/lang/String;)Ljava/lang/String;
+HSPLjava/lang/StringFactory;->newStringFromBytes([BIILjava/nio/charset/Charset;)Ljava/lang/String;+]Ljava/nio/charset/Charset;Lcom/android/icu/charset/CharsetICU;
+HSPLjava/lang/StringFactory;->newStringFromBytes([BLjava/lang/String;)Ljava/lang/String;
+HSPLjava/lang/StringFactory;->newStringFromBytes([BLjava/nio/charset/Charset;)Ljava/lang/String;
+HSPLjava/lang/StringFactory;->newStringFromChars([C)Ljava/lang/String;
+HSPLjava/lang/StringFactory;->newStringFromChars([CII)Ljava/lang/String;
+HSPLjava/lang/System$PropertiesWithNonOverrideableDefaults;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Properties;Ljava/util/Properties;
+HSPLjava/lang/System$PropertiesWithNonOverrideableDefaults;->remove(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Properties;Ljava/util/Properties;
+HSPLjava/lang/System;->arraycopy([BI[BII)V
+HSPLjava/lang/System;->arraycopy([CI[CII)V
+HSPLjava/lang/System;->arraycopy([FI[FII)V
+HSPLjava/lang/System;->arraycopy([II[III)V
+HSPLjava/lang/System;->arraycopy([JI[JII)V
+HSPLjava/lang/System;->arraycopy([ZI[ZII)V
+HSPLjava/lang/System;->checkKey(Ljava/lang/String;)V
+HSPLjava/lang/System;->clearProperty(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/lang/System;->gc()V+]Ljava/lang/Runtime;Ljava/lang/Runtime;
+HSPLjava/lang/System;->getProperties()Ljava/util/Properties;
+HSPLjava/lang/System;->getProperty(Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Properties;Ljava/lang/System$PropertiesWithNonOverrideableDefaults;
+HSPLjava/lang/System;->getProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Properties;Ljava/lang/System$PropertiesWithNonOverrideableDefaults;
+HSPLjava/lang/System;->getSecurityManager()Ljava/lang/SecurityManager;
+HSPLjava/lang/System;->getenv(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/lang/System;->identityHashCode(Ljava/lang/Object;)I
+HSPLjava/lang/System;->lineSeparator()Ljava/lang/String;
+HSPLjava/lang/System;->loadLibrary(Ljava/lang/String;)V
+HSPLjava/lang/System;->logE(Ljava/lang/String;)V
+HSPLjava/lang/System;->logW(Ljava/lang/String;)V
+HSPLjava/lang/System;->runFinalization()V+]Ljava/lang/Runtime;Ljava/lang/Runtime;
+HSPLjava/lang/System;->setErr(Ljava/io/PrintStream;)V
+HSPLjava/lang/System;->setOut(Ljava/io/PrintStream;)V
+HSPLjava/lang/System;->setProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/lang/Thread$State;->values()[Ljava/lang/Thread$State;+][Ljava/lang/Thread$State;[Ljava/lang/Thread$State;
+HSPLjava/lang/Thread;-><init>()V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/Thread;-><init>(Ljava/lang/Runnable;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/Thread;-><init>(Ljava/lang/Runnable;Ljava/lang/String;)V
+HSPLjava/lang/Thread;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/Thread;-><init>(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;Ljava/lang/String;)V
+HSPLjava/lang/Thread;-><init>(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;Ljava/lang/String;J)V
+HSPLjava/lang/Thread;-><init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V
+HSPLjava/lang/Thread;-><init>(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V+]Ljava/lang/ThreadGroup;Ljava/lang/ThreadGroup;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/Thread;->activeCount()I+]Ljava/lang/Thread;Ljava/lang/Thread;]Ljava/lang/ThreadGroup;Ljava/lang/ThreadGroup;
+HSPLjava/lang/Thread;->blockedOn(Lsun/nio/ch/Interruptible;)V
+HSPLjava/lang/Thread;->checkAccess()V
+HSPLjava/lang/Thread;->getContextClassLoader()Ljava/lang/ClassLoader;
+HSPLjava/lang/Thread;->getDefaultUncaughtExceptionHandler()Ljava/lang/Thread$UncaughtExceptionHandler;
+HSPLjava/lang/Thread;->getId()J
+HSPLjava/lang/Thread;->getName()Ljava/lang/String;
+HSPLjava/lang/Thread;->getPriority()I
+HSPLjava/lang/Thread;->getStackTrace()[Ljava/lang/StackTraceElement;
+HSPLjava/lang/Thread;->getState()Ljava/lang/Thread$State;
+HSPLjava/lang/Thread;->getThreadGroup()Ljava/lang/ThreadGroup;+]Ljava/lang/Thread;missing_types
+HSPLjava/lang/Thread;->getUncaughtExceptionHandler()Ljava/lang/Thread$UncaughtExceptionHandler;
+HSPLjava/lang/Thread;->init(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;Ljava/lang/String;J)V
+HSPLjava/lang/Thread;->init(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;Ljava/lang/String;JLjava/security/AccessControlContext;)V+]Ljava/lang/Thread;missing_types]Ljava/lang/ThreadGroup;Ljava/lang/ThreadGroup;
+HSPLjava/lang/Thread;->init2(Ljava/lang/Thread;)V+]Ljava/lang/Thread;missing_types
+HSPLjava/lang/Thread;->interrupt()V+]Ljava/lang/Thread;missing_types
+HSPLjava/lang/Thread;->isAlive()Z
+HSPLjava/lang/Thread;->isDaemon()Z
+HSPLjava/lang/Thread;->join()V+]Ljava/lang/Thread;missing_types
+HSPLjava/lang/Thread;->join(J)V+]Ljava/lang/Thread;missing_types]Ljava/lang/Object;Ljava/lang/Object;
+HSPLjava/lang/Thread;->nextThreadID()J
+HSPLjava/lang/Thread;->nextThreadNum()I
+HSPLjava/lang/Thread;->run()V+]Ljava/lang/Runnable;megamorphic_types
+HSPLjava/lang/Thread;->setContextClassLoader(Ljava/lang/ClassLoader;)V
+HSPLjava/lang/Thread;->setDaemon(Z)V+]Ljava/lang/Thread;missing_types
+HSPLjava/lang/Thread;->setDefaultUncaughtExceptionHandler(Ljava/lang/Thread$UncaughtExceptionHandler;)V
+HSPLjava/lang/Thread;->setName(Ljava/lang/String;)V+]Ljava/lang/Thread;missing_types
+HSPLjava/lang/Thread;->setPriority(I)V+]Ljava/lang/Thread;missing_types]Ljava/lang/ThreadGroup;Ljava/lang/ThreadGroup;
+HSPLjava/lang/Thread;->setSystemDaemon(Z)V+]Ljava/lang/Thread;Ljava/lang/Thread;
+HSPLjava/lang/Thread;->setUncaughtExceptionHandler(Ljava/lang/Thread$UncaughtExceptionHandler;)V+]Ljava/lang/Thread;missing_types
+HSPLjava/lang/Thread;->setUncaughtExceptionPreHandler(Ljava/lang/Thread$UncaughtExceptionHandler;)V
+HSPLjava/lang/Thread;->sleep(J)V
+HSPLjava/lang/Thread;->sleep(JI)V
+HSPLjava/lang/Thread;->start()V+]Ljava/lang/ThreadGroup;Ljava/lang/ThreadGroup;
+HSPLjava/lang/Thread;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Thread;missing_types]Ljava/lang/ThreadGroup;Ljava/lang/ThreadGroup;
+HSPLjava/lang/ThreadGroup;-><init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V
+HSPLjava/lang/ThreadGroup;-><init>(Ljava/lang/Void;Ljava/lang/ThreadGroup;Ljava/lang/String;)V
+HSPLjava/lang/ThreadGroup;->activeCount()I+]Ljava/lang/ThreadGroup;Ljava/lang/ThreadGroup;
+HSPLjava/lang/ThreadGroup;->activeGroupCount()I
+HSPLjava/lang/ThreadGroup;->add(Ljava/lang/Thread;)V
+HSPLjava/lang/ThreadGroup;->add(Ljava/lang/ThreadGroup;)V
+HSPLjava/lang/ThreadGroup;->addUnstarted()V
+HSPLjava/lang/ThreadGroup;->checkAccess()V
+HSPLjava/lang/ThreadGroup;->checkParentAccess(Ljava/lang/ThreadGroup;)Ljava/lang/Void;
+HSPLjava/lang/ThreadGroup;->enumerate([Ljava/lang/Thread;)I
+HSPLjava/lang/ThreadGroup;->enumerate([Ljava/lang/Thread;IZ)I+]Ljava/lang/Thread;missing_types
+HSPLjava/lang/ThreadGroup;->enumerate([Ljava/lang/ThreadGroup;)I
+HSPLjava/lang/ThreadGroup;->enumerate([Ljava/lang/ThreadGroup;IZ)I
+HSPLjava/lang/ThreadGroup;->getMaxPriority()I
+HSPLjava/lang/ThreadGroup;->getName()Ljava/lang/String;
+HSPLjava/lang/ThreadGroup;->remove(Ljava/lang/Thread;)V
+HSPLjava/lang/ThreadGroup;->threadTerminated(Ljava/lang/Thread;)V+]Ljava/lang/Object;Ljava/lang/ThreadGroup;
+HSPLjava/lang/ThreadLocal$SuppliedThreadLocal;-><init>(Ljava/util/function/Supplier;)V
+HSPLjava/lang/ThreadLocal$SuppliedThreadLocal;->initialValue()Ljava/lang/Object;+]Ljava/util/function/Supplier;megamorphic_types
+HSPLjava/lang/ThreadLocal$ThreadLocalMap$Entry;-><init>(Ljava/lang/ThreadLocal;Ljava/lang/Object;)V
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;-><init>(Ljava/lang/ThreadLocal$ThreadLocalMap;)V+]Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;]Ljava/lang/ThreadLocal;Ljava/lang/InheritableThreadLocal;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;-><init>(Ljava/lang/ThreadLocal$ThreadLocalMap;Ljava/lang/ThreadLocal$1;)V
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;-><init>(Ljava/lang/ThreadLocal;Ljava/lang/Object;)V
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->access$000(Ljava/lang/ThreadLocal$ThreadLocalMap;Ljava/lang/ThreadLocal;)Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->access$100(Ljava/lang/ThreadLocal$ThreadLocalMap;Ljava/lang/ThreadLocal;Ljava/lang/Object;)V
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->access$200(Ljava/lang/ThreadLocal$ThreadLocalMap;Ljava/lang/ThreadLocal;)V
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->cleanSomeSlots(II)Z+]Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->expungeStaleEntries()V+]Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->expungeStaleEntry(I)I+]Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->getEntry(Ljava/lang/ThreadLocal;)Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->getEntryAfterMiss(Ljava/lang/ThreadLocal;ILjava/lang/ThreadLocal$ThreadLocalMap$Entry;)Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->nextIndex(II)I
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->prevIndex(II)I
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->rehash()V
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->remove(Ljava/lang/ThreadLocal;)V+]Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->replaceStaleEntry(Ljava/lang/ThreadLocal;Ljava/lang/Object;I)V+]Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->resize()V+]Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->set(Ljava/lang/ThreadLocal;Ljava/lang/Object;)V+]Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+HSPLjava/lang/ThreadLocal$ThreadLocalMap;->setThreshold(I)V
+HSPLjava/lang/ThreadLocal;-><init>()V
+HSPLjava/lang/ThreadLocal;->access$400(Ljava/lang/ThreadLocal;)I
+HSPLjava/lang/ThreadLocal;->createInheritedMap(Ljava/lang/ThreadLocal$ThreadLocalMap;)Ljava/lang/ThreadLocal$ThreadLocalMap;
+HSPLjava/lang/ThreadLocal;->createMap(Ljava/lang/Thread;Ljava/lang/Object;)V
+HSPLjava/lang/ThreadLocal;->get()Ljava/lang/Object;+]Ljava/lang/ThreadLocal;megamorphic_types
+HSPLjava/lang/ThreadLocal;->getMap(Ljava/lang/Thread;)Ljava/lang/ThreadLocal$ThreadLocalMap;
+HSPLjava/lang/ThreadLocal;->initialValue()Ljava/lang/Object;
+HSPLjava/lang/ThreadLocal;->nextHashCode()I+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/lang/ThreadLocal;->remove()V+]Ljava/lang/ThreadLocal;missing_types
+HSPLjava/lang/ThreadLocal;->set(Ljava/lang/Object;)V+]Ljava/lang/ThreadLocal;megamorphic_types
+HSPLjava/lang/ThreadLocal;->setInitialValue()Ljava/lang/Object;+]Ljava/lang/ThreadLocal;megamorphic_types
+HSPLjava/lang/ThreadLocal;->withInitial(Ljava/util/function/Supplier;)Ljava/lang/ThreadLocal;
+HSPLjava/lang/Throwable$PrintStreamOrWriter;-><init>()V
+HSPLjava/lang/Throwable$PrintStreamOrWriter;-><init>(Ljava/lang/Throwable$1;)V
+HSPLjava/lang/Throwable$WrappedPrintStream;-><init>(Ljava/io/PrintStream;)V
+HSPLjava/lang/Throwable$WrappedPrintStream;->lock()Ljava/lang/Object;
+HSPLjava/lang/Throwable$WrappedPrintStream;->println(Ljava/lang/Object;)V+]Ljava/io/PrintStream;missing_types
+HSPLjava/lang/Throwable$WrappedPrintWriter;-><init>(Ljava/io/PrintWriter;)V
+HSPLjava/lang/Throwable$WrappedPrintWriter;->lock()Ljava/lang/Object;
+HSPLjava/lang/Throwable$WrappedPrintWriter;->println(Ljava/lang/Object;)V+]Ljava/io/PrintWriter;missing_types
+HSPLjava/lang/Throwable;-><init>()V+]Ljava/lang/Throwable;megamorphic_types
+HSPLjava/lang/Throwable;-><init>(Ljava/lang/String;)V+]Ljava/lang/Throwable;megamorphic_types
+HSPLjava/lang/Throwable;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V+]Ljava/lang/Throwable;megamorphic_types
+HSPLjava/lang/Throwable;-><init>(Ljava/lang/String;Ljava/lang/Throwable;ZZ)V
+HSPLjava/lang/Throwable;-><init>(Ljava/lang/Throwable;)V+]Ljava/lang/Throwable;megamorphic_types
+HSPLjava/lang/Throwable;->addSuppressed(Ljava/lang/Throwable;)V+]Ljava/util/List;Ljava/util/Collections$EmptyList;,Ljava/util/ArrayList;
+HSPLjava/lang/Throwable;->fillInStackTrace()Ljava/lang/Throwable;
+HSPLjava/lang/Throwable;->getCause()Ljava/lang/Throwable;
+HSPLjava/lang/Throwable;->getLocalizedMessage()Ljava/lang/String;+]Ljava/lang/Throwable;megamorphic_types
+HSPLjava/lang/Throwable;->getMessage()Ljava/lang/String;
+HSPLjava/lang/Throwable;->getOurStackTrace()[Ljava/lang/StackTraceElement;
+HSPLjava/lang/Throwable;->getStackTrace()[Ljava/lang/StackTraceElement;+][Ljava/lang/StackTraceElement;[Ljava/lang/StackTraceElement;
+HSPLjava/lang/Throwable;->getSuppressed()[Ljava/lang/Throwable;+]Ljava/util/List;Ljava/util/Collections$EmptyList;,Ljava/util/ArrayList;
+HSPLjava/lang/Throwable;->initCause(Ljava/lang/Throwable;)Ljava/lang/Throwable;
+HSPLjava/lang/Throwable;->printEnclosedStackTrace(Ljava/lang/Throwable$PrintStreamOrWriter;[Ljava/lang/StackTraceElement;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Throwable$PrintStreamOrWriter;Ljava/lang/Throwable$WrappedPrintWriter;,Ljava/lang/Throwable$WrappedPrintStream;]Ljava/lang/Throwable;megamorphic_types]Ljava/lang/StackTraceElement;Ljava/lang/StackTraceElement;]Ljava/util/Set;Ljava/util/Collections$SetFromMap;
+HSPLjava/lang/Throwable;->printStackTrace()V+]Ljava/lang/Throwable;missing_types
+HSPLjava/lang/Throwable;->printStackTrace(Ljava/io/PrintStream;)V
+HSPLjava/lang/Throwable;->printStackTrace(Ljava/io/PrintWriter;)V
+HSPLjava/lang/Throwable;->printStackTrace(Ljava/lang/Throwable$PrintStreamOrWriter;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Throwable$PrintStreamOrWriter;Ljava/lang/Throwable$WrappedPrintWriter;,Ljava/lang/Throwable$WrappedPrintStream;]Ljava/lang/Throwable;megamorphic_types]Ljava/util/Set;Ljava/util/Collections$SetFromMap;
+HSPLjava/lang/Throwable;->readObject(Ljava/io/ObjectInputStream;)V+]Ljava/io/ObjectInputStream;Landroid/os/Parcel$2;]Ljava/util/List;Ljava/util/Collections$EmptyList;
+HSPLjava/lang/Throwable;->setStackTrace([Ljava/lang/StackTraceElement;)V+][Ljava/lang/StackTraceElement;[Ljava/lang/StackTraceElement;
+HSPLjava/lang/Throwable;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Object;megamorphic_types]Ljava/lang/Throwable;megamorphic_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/Throwable;->writeObject(Ljava/io/ObjectOutputStream;)V+]Ljava/io/ObjectOutputStream;Ljava/io/ObjectOutputStream;
+HSPLjava/lang/UNIXProcess$2;-><init>(Ljava/lang/UNIXProcess;[I)V
+HSPLjava/lang/UNIXProcess$2;->run()Ljava/lang/Object;+]Ljava/lang/UNIXProcess$2;Ljava/lang/UNIXProcess$2;
+HSPLjava/lang/UNIXProcess$2;->run()Ljava/lang/Void;+]Ljava/lang/UNIXProcess;Ljava/lang/UNIXProcess;
+HSPLjava/lang/UNIXProcess$3;-><init>(Ljava/lang/UNIXProcess;)V
+HSPLjava/lang/UNIXProcess$3;->run()V+]Ljava/lang/UNIXProcess;Ljava/lang/UNIXProcess;
+HSPLjava/lang/UNIXProcess$ProcessPipeInputStream;-><init>(I)V
+HSPLjava/lang/UNIXProcess$ProcessPipeInputStream;->drainInputStream(Ljava/io/InputStream;)[B+]Ljava/io/InputStream;Ljava/io/FileInputStream;
+HSPLjava/lang/UNIXProcess$ProcessPipeInputStream;->processExited()V+]Ljava/io/InputStream;Ljava/io/FileInputStream;
+HSPLjava/lang/UNIXProcess$ProcessPipeOutputStream;-><init>(I)V
+HSPLjava/lang/UNIXProcess$ProcessPipeOutputStream;->processExited()V+]Ljava/io/OutputStream;Ljava/io/FileOutputStream;
+HSPLjava/lang/UNIXProcess$ProcessReaperThreadFactory;->newThread(Ljava/lang/Runnable;)Ljava/lang/Thread;+]Ljava/lang/Thread;Ljava/lang/Thread;
+HSPLjava/lang/UNIXProcess;-><init>([B[BI[BI[B[IZ)V
+HSPLjava/lang/UNIXProcess;->access$100(Ljava/lang/UNIXProcess;)I
+HSPLjava/lang/UNIXProcess;->access$200(Ljava/lang/UNIXProcess;I)I
+HSPLjava/lang/UNIXProcess;->getErrorStream()Ljava/io/InputStream;
+HSPLjava/lang/UNIXProcess;->getInputStream()Ljava/io/InputStream;
+HSPLjava/lang/UNIXProcess;->initStreams([I)V+]Ljava/util/concurrent/Executor;Ljava/util/concurrent/ThreadPoolExecutor;
+HSPLjava/lang/UNIXProcess;->newFileDescriptor(I)Ljava/io/FileDescriptor;
+HSPLjava/lang/UNIXProcess;->processExited(I)V+]Ljava/lang/UNIXProcess$ProcessPipeOutputStream;Ljava/lang/UNIXProcess$ProcessPipeOutputStream;]Ljava/lang/Object;Ljava/lang/UNIXProcess;]Ljava/lang/UNIXProcess$ProcessPipeInputStream;Ljava/lang/UNIXProcess$ProcessPipeInputStream;
+HSPLjava/lang/UNIXProcess;->waitFor()I
+HSPLjava/lang/UnsatisfiedLinkError;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/UnsupportedOperationException;-><init>()V
+HSPLjava/lang/UnsupportedOperationException;-><init>(Ljava/lang/String;)V
+HSPLjava/lang/VMClassLoader;->getResource(Ljava/lang/String;)Ljava/net/URL;
+HSPLjava/lang/VMClassLoader;->getResources(Ljava/lang/String;)Ljava/util/List;
+HSPLjava/lang/invoke/MethodHandle;-><init>(JILjava/lang/invoke/MethodType;)V
+HSPLjava/lang/invoke/MethodHandleImpl;-><init>(JILjava/lang/invoke/MethodType;)V
+HSPLjava/lang/invoke/MethodHandles$Lookup;->checkAccess(Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/String;)V
+HSPLjava/lang/invoke/MethodHandles$Lookup;->createMethodHandle(Ljava/lang/reflect/Method;ILjava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
+HSPLjava/lang/invoke/MethodHandles$Lookup;->unreflect(Ljava/lang/reflect/Method;)Ljava/lang/invoke/MethodHandle;
+HSPLjava/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry;-><init>(Ljava/lang/Object;)V
+HSPLjava/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+HSPLjava/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry;->equals(Ljava/lang/Object;)Z
+HSPLjava/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry;->hashCode()I
+HSPLjava/lang/invoke/MethodType$ConcurrentWeakInternSet;->add(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/lang/invoke/MethodType$ConcurrentWeakInternSet;->expungeStaleElements()V
+HSPLjava/lang/invoke/MethodType$ConcurrentWeakInternSet;->get(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/lang/invoke/MethodType;-><init>(Ljava/lang/Class;[Ljava/lang/Class;Z)V
+HSPLjava/lang/invoke/MethodType;-><init>([Ljava/lang/Class;Ljava/lang/Class;)V
+HSPLjava/lang/invoke/MethodType;->checkPtype(Ljava/lang/Class;)V
+HSPLjava/lang/invoke/MethodType;->checkPtypes([Ljava/lang/Class;)I
+HSPLjava/lang/invoke/MethodType;->checkRtype(Ljava/lang/Class;)V
+HSPLjava/lang/invoke/MethodType;->checkSlotCount(I)V
+HSPLjava/lang/invoke/MethodType;->equals(Ljava/lang/Object;)Z
+HSPLjava/lang/invoke/MethodType;->equals(Ljava/lang/invoke/MethodType;)Z
+HSPLjava/lang/invoke/MethodType;->form()Ljava/lang/invoke/MethodTypeForm;
+HSPLjava/lang/invoke/MethodType;->genericMethodType(I)Ljava/lang/invoke/MethodType;
+HSPLjava/lang/invoke/MethodType;->genericMethodType(IZ)Ljava/lang/invoke/MethodType;
+HSPLjava/lang/invoke/MethodType;->hashCode()I+]Ljava/lang/Object;Ljava/lang/Class;
+HSPLjava/lang/invoke/MethodType;->insertParameterTypes(I[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
+HSPLjava/lang/invoke/MethodType;->makeImpl(Ljava/lang/Class;[Ljava/lang/Class;Z)Ljava/lang/invoke/MethodType;
+HSPLjava/lang/invoke/MethodType;->methodType(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
+HSPLjava/lang/invoke/MethodType;->parameterSlotCount()I
+HSPLjava/lang/invoke/MethodType;->ptypes()[Ljava/lang/Class;
+HSPLjava/lang/invoke/MethodType;->returnType()Ljava/lang/Class;
+HSPLjava/lang/invoke/MethodTypeForm;-><init>(Ljava/lang/invoke/MethodType;)V
+HSPLjava/lang/invoke/MethodTypeForm;->canonicalize(Ljava/lang/Class;I)Ljava/lang/Class;
+HSPLjava/lang/invoke/MethodTypeForm;->canonicalize(Ljava/lang/invoke/MethodType;II)Ljava/lang/invoke/MethodType;
+HSPLjava/lang/invoke/MethodTypeForm;->canonicalizeAll([Ljava/lang/Class;I)[Ljava/lang/Class;
+HSPLjava/lang/invoke/MethodTypeForm;->findForm(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodTypeForm;
+HSPLjava/lang/invoke/MethodTypeForm;->pack(IIII)J
+HSPLjava/lang/invoke/MethodTypeForm;->parameterSlotCount()I
+HSPLjava/lang/invoke/MethodTypeForm;->unpack(JI)C
+HSPLjava/lang/invoke/VarHandle;->acquireFence()V
+HSPLjava/lang/invoke/VarHandle;->fullFence()V
+HSPLjava/lang/invoke/VarHandle;->loadLoadFence()V
+HSPLjava/lang/invoke/VarHandle;->releaseFence()V
+HSPLjava/lang/invoke/VarHandle;->storeStoreFence()V
+HSPLjava/lang/ref/FinalizerReference$Sentinel;-><init>()V
+HSPLjava/lang/ref/FinalizerReference$Sentinel;-><init>(Ljava/lang/ref/FinalizerReference$1;)V
+HSPLjava/lang/ref/FinalizerReference$Sentinel;->awaitFinalization(J)V+]Ljava/lang/Object;Ljava/lang/ref/FinalizerReference$Sentinel;
+HSPLjava/lang/ref/FinalizerReference$Sentinel;->finalize()V+]Ljava/lang/Object;Ljava/lang/ref/FinalizerReference$Sentinel;
+HSPLjava/lang/ref/FinalizerReference;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+HSPLjava/lang/ref/FinalizerReference;->add(Ljava/lang/Object;)V
+HSPLjava/lang/ref/FinalizerReference;->clear()V
+HSPLjava/lang/ref/FinalizerReference;->enqueueSentinelReference(Ljava/lang/ref/FinalizerReference$Sentinel;)Z+]Ljava/lang/ref/FinalizerReference;Ljava/lang/ref/FinalizerReference;
+HSPLjava/lang/ref/FinalizerReference;->finalizeAllEnqueued(J)V+]Ljava/lang/ref/FinalizerReference$Sentinel;Ljava/lang/ref/FinalizerReference$Sentinel;
+HSPLjava/lang/ref/FinalizerReference;->get()Ljava/lang/Object;
+HSPLjava/lang/ref/FinalizerReference;->remove(Ljava/lang/ref/FinalizerReference;)V
+HSPLjava/lang/ref/PhantomReference;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+HSPLjava/lang/ref/Reference;-><init>(Ljava/lang/Object;)V
+HSPLjava/lang/ref/Reference;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+HSPLjava/lang/ref/Reference;->clear()V+]Ljava/lang/ref/Reference;missing_types
+HSPLjava/lang/ref/Reference;->get()Ljava/lang/Object;
+HSPLjava/lang/ref/Reference;->reachabilityFence(Ljava/lang/Object;)V
+HSPLjava/lang/ref/Reference;->refersTo(Ljava/lang/Object;)Z
+HSPLjava/lang/ref/ReferenceQueue;-><init>()V
+HSPLjava/lang/ref/ReferenceQueue;->add(Ljava/lang/ref/Reference;)V+]Ljava/lang/Object;Ljava/lang/Class;
+HSPLjava/lang/ref/ReferenceQueue;->enqueueLocked(Ljava/lang/ref/Reference;)Z+]Lsun/misc/Cleaner;Lsun/misc/Cleaner;
+HSPLjava/lang/ref/ReferenceQueue;->enqueuePending(Ljava/lang/ref/Reference;)V+]Ljava/lang/Object;Ljava/lang/Object;
+HSPLjava/lang/ref/ReferenceQueue;->poll()Ljava/lang/ref/Reference;
+HSPLjava/lang/ref/ReferenceQueue;->reallyPollLocked()Ljava/lang/ref/Reference;
+HSPLjava/lang/ref/ReferenceQueue;->remove()Ljava/lang/ref/Reference;+]Ljava/lang/ref/ReferenceQueue;Ljava/lang/ref/ReferenceQueue;
+HSPLjava/lang/ref/ReferenceQueue;->remove(J)Ljava/lang/ref/Reference;+]Ljava/lang/Object;Ljava/lang/Object;
+HSPLjava/lang/ref/SoftReference;-><init>(Ljava/lang/Object;)V
+HSPLjava/lang/ref/SoftReference;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+HSPLjava/lang/ref/SoftReference;->get()Ljava/lang/Object;
+HSPLjava/lang/ref/WeakReference;-><init>(Ljava/lang/Object;)V
+HSPLjava/lang/ref/WeakReference;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+HSPLjava/lang/reflect/AccessibleObject;-><init>()V
+HSPLjava/lang/reflect/AccessibleObject;->getAnnotations()[Ljava/lang/annotation/Annotation;+]Ljava/lang/reflect/AccessibleObject;Ljava/lang/reflect/Method;,Ljava/lang/reflect/Field;,Ljava/lang/reflect/Constructor;
+HSPLjava/lang/reflect/AccessibleObject;->isAccessible()Z
+HSPLjava/lang/reflect/AccessibleObject;->setAccessible(Z)V
+HSPLjava/lang/reflect/AccessibleObject;->setAccessible0(Ljava/lang/reflect/AccessibleObject;Z)V+]Ljava/lang/reflect/Constructor;Ljava/lang/reflect/Constructor;
+HSPLjava/lang/reflect/Array;->get(Ljava/lang/Object;I)Ljava/lang/Object;
+HSPLjava/lang/reflect/Array;->getLength(Ljava/lang/Object;)I
+HSPLjava/lang/reflect/Array;->newArray(Ljava/lang/Class;I)Ljava/lang/Object;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Array;->newInstance(Ljava/lang/Class;I)Ljava/lang/Object;
+HSPLjava/lang/reflect/Array;->newInstance(Ljava/lang/Class;[I)Ljava/lang/Object;
+HSPLjava/lang/reflect/Array;->set(Ljava/lang/Object;ILjava/lang/Object;)V+]Ljava/lang/Integer;Ljava/lang/Integer;]Ljava/lang/Object;missing_types]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/Boolean;Ljava/lang/Boolean;]Ljava/lang/Byte;Ljava/lang/Byte;]Ljava/lang/Double;Ljava/lang/Double;]Ljava/lang/Float;Ljava/lang/Float;]Ljava/lang/Long;Ljava/lang/Long;]Ljava/lang/Short;Ljava/lang/Short;
+HSPLjava/lang/reflect/Array;->setInt(Ljava/lang/Object;II)V
+HSPLjava/lang/reflect/Constructor;-><init>(Ljava/lang/Class;Ljava/lang/Class;)V
+HSPLjava/lang/reflect/Constructor;->getDeclaringClass()Ljava/lang/Class;
+HSPLjava/lang/reflect/Constructor;->getModifiers()I
+HSPLjava/lang/reflect/Constructor;->getName()Ljava/lang/String;+]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/reflect/Constructor;Ljava/lang/reflect/Constructor;
+HSPLjava/lang/reflect/Constructor;->getParameterTypes()[Ljava/lang/Class;
+HSPLjava/lang/reflect/Constructor;->newInstance([Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/lang/reflect/Constructor;->serializationCopy(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
+HSPLjava/lang/reflect/Executable$GenericInfo;-><init>(Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;Ljava/lang/reflect/Type;[Ljava/lang/reflect/TypeVariable;)V
+HSPLjava/lang/reflect/Executable;-><init>()V
+HSPLjava/lang/reflect/Executable;->equalNameAndParametersInternal(Ljava/lang/reflect/Method;)Z+]Ljava/lang/reflect/Executable;Ljava/lang/reflect/Method;]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/lang/reflect/Executable;->equalParamTypes([Ljava/lang/Class;[Ljava/lang/Class;)Z
+HSPLjava/lang/reflect/Executable;->fixMethodFlags(I)I
+HSPLjava/lang/reflect/Executable;->getAccessFlags()I
+HSPLjava/lang/reflect/Executable;->getAnnotation(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
+HSPLjava/lang/reflect/Executable;->getArtMethod()J
+HSPLjava/lang/reflect/Executable;->getDeclaredAnnotations()[Ljava/lang/annotation/Annotation;
+HSPLjava/lang/reflect/Executable;->getDeclaringClassInternal()Ljava/lang/Class;
+HSPLjava/lang/reflect/Executable;->getGenericParameterTypes()[Ljava/lang/reflect/Type;+]Ljava/lang/reflect/Executable;Ljava/lang/reflect/Method;,Ljava/lang/reflect/Constructor;
+HSPLjava/lang/reflect/Executable;->getMethodOrConstructorGenericInfoInternal()Ljava/lang/reflect/Executable$GenericInfo;+]Ljava/lang/reflect/Executable;Ljava/lang/reflect/Method;,Ljava/lang/reflect/Constructor;]Ljava/lang/Class;Ljava/lang/Class;]Llibcore/reflect/GenericSignatureParser;missing_types
+HSPLjava/lang/reflect/Executable;->getModifiersInternal()I
+HSPLjava/lang/reflect/Executable;->getParameterAnnotationsInternal()[[Ljava/lang/annotation/Annotation;+]Ljava/lang/reflect/Executable;Ljava/lang/reflect/Method;,Ljava/lang/reflect/Constructor;
+HSPLjava/lang/reflect/Executable;->getSignatureAttribute()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/reflect/Executable;->isAnnotationPresent(Ljava/lang/Class;)Z
+HSPLjava/lang/reflect/Executable;->isDefaultMethodInternal()Z
+HSPLjava/lang/reflect/Executable;->isSynthetic()Z
+HSPLjava/lang/reflect/Executable;->isVarArgs()Z
+HSPLjava/lang/reflect/Executable;->printModifiersIfNonzero(Ljava/lang/StringBuilder;IZ)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/reflect/Executable;Ljava/lang/reflect/Method;
+HSPLjava/lang/reflect/Executable;->separateWithCommas([Ljava/lang/Class;Ljava/lang/StringBuilder;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Executable;->sharedToString(IZ[Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/reflect/Executable;Ljava/lang/reflect/Method;
+HSPLjava/lang/reflect/Field;->getAnnotation(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
+HSPLjava/lang/reflect/Field;->getDeclaringClass()Ljava/lang/Class;
+HSPLjava/lang/reflect/Field;->getGenericType()Ljava/lang/reflect/Type;+]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;]Ljava/lang/Class;Ljava/lang/Class;]Llibcore/reflect/GenericSignatureParser;missing_types
+HSPLjava/lang/reflect/Field;->getModifiers()I
+HSPLjava/lang/reflect/Field;->getName()Ljava/lang/String;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Field;->getOffset()I
+HSPLjava/lang/reflect/Field;->getSignatureAttribute()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/reflect/Field;->getType()Ljava/lang/Class;
+HSPLjava/lang/reflect/Field;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Field;->isAnnotationPresent(Ljava/lang/Class;)Z
+HSPLjava/lang/reflect/Field;->isEnumConstant()Z+]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;
+HSPLjava/lang/reflect/Field;->isSynthetic()Z+]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;
+HSPLjava/lang/reflect/InvocationTargetException;-><init>(Ljava/lang/Throwable;)V
+HSPLjava/lang/reflect/InvocationTargetException;->getCause()Ljava/lang/Throwable;
+HSPLjava/lang/reflect/Method$1;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/lang/reflect/Method$1;Ljava/lang/reflect/Method$1;
+HSPLjava/lang/reflect/Method$1;->compare(Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)I+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Method;->equalNameAndParameters(Ljava/lang/reflect/Method;)Z+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/lang/reflect/Method;->equals(Ljava/lang/Object;)Z+]Ljava/lang/Object;Ljava/lang/Class;]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/lang/reflect/Method;->getAnnotation(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
+HSPLjava/lang/reflect/Method;->getDeclaredAnnotations()[Ljava/lang/annotation/Annotation;
+HSPLjava/lang/reflect/Method;->getDeclaringClass()Ljava/lang/Class;
+HSPLjava/lang/reflect/Method;->getGenericParameterTypes()[Ljava/lang/reflect/Type;
+HSPLjava/lang/reflect/Method;->getGenericReturnType()Ljava/lang/reflect/Type;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/lang/reflect/Method;->getModifiers()I
+HSPLjava/lang/reflect/Method;->getName()Ljava/lang/String;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/lang/reflect/Method;->getParameterAnnotations()[[Ljava/lang/annotation/Annotation;
+HSPLjava/lang/reflect/Method;->getParameterTypes()[Ljava/lang/Class;
+HSPLjava/lang/reflect/Method;->getReturnType()Ljava/lang/Class;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/lang/reflect/Method;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Method;->isDefault()Z
+HSPLjava/lang/reflect/Method;->isSynthetic()Z
+HSPLjava/lang/reflect/Method;->isVarArgs()Z
+HSPLjava/lang/reflect/Method;->specificToStringHeader(Ljava/lang/StringBuilder;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Method;->toString()Ljava/lang/String;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/lang/reflect/Modifier;->isAbstract(I)Z
+HSPLjava/lang/reflect/Modifier;->isFinal(I)Z
+HSPLjava/lang/reflect/Modifier;->isInterface(I)Z
+HSPLjava/lang/reflect/Modifier;->isPrivate(I)Z
+HSPLjava/lang/reflect/Modifier;->isProtected(I)Z
+HSPLjava/lang/reflect/Modifier;->isPublic(I)Z
+HSPLjava/lang/reflect/Modifier;->isStatic(I)Z
+HSPLjava/lang/reflect/Modifier;->isSynthetic(I)Z
+HSPLjava/lang/reflect/Modifier;->isTransient(I)Z
+HSPLjava/lang/reflect/Modifier;->isVolatile(I)Z
+HSPLjava/lang/reflect/Modifier;->methodModifiers()I
+HSPLjava/lang/reflect/Modifier;->toString(I)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/lang/reflect/Proxy$1;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/lang/reflect/Proxy$1;Ljava/lang/reflect/Proxy$1;
+HSPLjava/lang/reflect/Proxy$1;->compare(Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)I+]Ljava/util/Comparator;Ljava/lang/reflect/Method$1;]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Proxy$Key1;-><init>(Ljava/lang/Class;)V+]Ljava/lang/Object;Ljava/lang/Class;
+HSPLjava/lang/reflect/Proxy$Key1;->equals(Ljava/lang/Object;)Z+]Ljava/lang/Object;Ljava/lang/reflect/Proxy$Key1;]Ljava/lang/reflect/Proxy$Key1;Ljava/lang/reflect/Proxy$Key1;
+HSPLjava/lang/reflect/Proxy$Key1;->hashCode()I
+HSPLjava/lang/reflect/Proxy$KeyFactory;->apply(Ljava/lang/ClassLoader;[Ljava/lang/Class;)Ljava/lang/Object;
+HSPLjava/lang/reflect/Proxy$KeyFactory;->apply(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/reflect/Proxy$KeyFactory;Ljava/lang/reflect/Proxy$KeyFactory;
+HSPLjava/lang/reflect/Proxy$ProxyClassFactory;->apply(Ljava/lang/ClassLoader;[Ljava/lang/Class;)Ljava/lang/Class;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/String;Ljava/lang/String;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;]Ljava/util/Map;Ljava/util/IdentityHashMap;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Proxy$ProxyClassFactory;->apply(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/reflect/Proxy$ProxyClassFactory;Ljava/lang/reflect/Proxy$ProxyClassFactory;
+HSPLjava/lang/reflect/Proxy;->access$300([Ljava/lang/Class;)Ljava/util/List;
+HSPLjava/lang/reflect/Proxy;->access$400()Ljava/util/Comparator;
+HSPLjava/lang/reflect/Proxy;->access$500(Ljava/util/List;)V
+HSPLjava/lang/reflect/Proxy;->access$600(Ljava/util/List;)Ljava/util/List;
+HSPLjava/lang/reflect/Proxy;->access$700(Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/ClassLoader;[Ljava/lang/reflect/Method;[[Ljava/lang/Class;)Ljava/lang/Class;
+HSPLjava/lang/reflect/Proxy;->deduplicateAndGetExceptions(Ljava/util/List;)Ljava/util/List;+]Ljava/util/Comparator;Ljava/lang/reflect/Method$1;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLjava/lang/reflect/Proxy;->getMethods([Ljava/lang/Class;)Ljava/util/List;+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Proxy;->getMethodsRecursive([Ljava/lang/Class;Ljava/util/List;)V+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/lang/reflect/Proxy;->getProxyClass0(Ljava/lang/ClassLoader;[Ljava/lang/Class;)Ljava/lang/Class;+]Ljava/lang/reflect/WeakCache;Ljava/lang/reflect/WeakCache;
+HSPLjava/lang/reflect/Proxy;->intersectExceptions([Ljava/lang/Class;[Ljava/lang/Class;)[Ljava/lang/Class;
+HSPLjava/lang/reflect/Proxy;->invoke(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/reflect/InvocationHandler;missing_types
+HSPLjava/lang/reflect/Proxy;->isProxyClass(Ljava/lang/Class;)Z+]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/reflect/WeakCache;Ljava/lang/reflect/WeakCache;
+HSPLjava/lang/reflect/Proxy;->newProxyInstance(Ljava/lang/ClassLoader;[Ljava/lang/Class;Ljava/lang/reflect/InvocationHandler;)Ljava/lang/Object;+][Ljava/lang/Class;[Ljava/lang/Class;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/reflect/Constructor;Ljava/lang/reflect/Constructor;
+HSPLjava/lang/reflect/Proxy;->validateReturnTypes(Ljava/util/List;)V+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLjava/lang/reflect/WeakCache$CacheKey;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+HSPLjava/lang/reflect/WeakCache$CacheKey;->equals(Ljava/lang/Object;)Z+]Ljava/lang/Object;Ljava/lang/reflect/WeakCache$CacheKey;]Ljava/lang/reflect/WeakCache$CacheKey;Ljava/lang/reflect/WeakCache$CacheKey;
+HSPLjava/lang/reflect/WeakCache$CacheKey;->hashCode()I
+HSPLjava/lang/reflect/WeakCache$CacheKey;->valueOf(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)Ljava/lang/Object;
+HSPLjava/lang/reflect/WeakCache$CacheValue;-><init>(Ljava/lang/Object;)V
+HSPLjava/lang/reflect/WeakCache$CacheValue;->hashCode()I
+HSPLjava/lang/reflect/WeakCache$Factory;-><init>(Ljava/lang/reflect/WeakCache;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentMap;)V
+HSPLjava/lang/reflect/WeakCache$Factory;->get()Ljava/lang/Object;+]Ljava/util/function/BiFunction;Ljava/lang/reflect/Proxy$ProxyClassFactory;]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/lang/reflect/WeakCache;->access$000(Ljava/lang/reflect/WeakCache;)Ljava/util/function/BiFunction;
+HSPLjava/lang/reflect/WeakCache;->access$100(Ljava/lang/reflect/WeakCache;)Ljava/util/concurrent/ConcurrentMap;
+HSPLjava/lang/reflect/WeakCache;->expungeStaleEntries()V+]Ljava/lang/ref/ReferenceQueue;Ljava/lang/ref/ReferenceQueue;
+HSPLjava/lang/reflect/WeakCache;->get(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/function/BiFunction;Ljava/lang/reflect/Proxy$KeyFactory;]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/util/function/Supplier;Ljava/lang/reflect/WeakCache$CacheValue;,Ljava/lang/reflect/WeakCache$Factory;
+HSPLjava/math/BigDecimal;-><init>(I)V
+HSPLjava/math/BigDecimal;-><init>(J)V
+HSPLjava/math/BigDecimal;-><init>(Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/math/BigDecimal;-><init>(Ljava/math/BigInteger;JII)V
+HSPLjava/math/BigDecimal;-><init>([CII)V
+HSPLjava/math/BigDecimal;-><init>([CIILjava/math/MathContext;)V
+HSPLjava/math/BigDecimal;->add(JIJI)Ljava/math/BigDecimal;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigDecimal;->add(JJ)J
+HSPLjava/math/BigDecimal;->add(JJI)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->add(Ljava/math/BigDecimal;)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->checkScale(J)I
+HSPLjava/math/BigDecimal;->checkScale(JJ)I
+HSPLjava/math/BigDecimal;->compactValFor(Ljava/math/BigInteger;)J
+HSPLjava/math/BigDecimal;->compareTo(Ljava/math/BigDecimal;)I+]Ljava/math/BigDecimal;Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->createAndStripZerosToMatchScale(JIJ)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->divide(JIJIII)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->divide(Ljava/math/BigDecimal;II)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->divide(Ljava/math/BigDecimal;ILjava/math/RoundingMode;)Ljava/math/BigDecimal;+]Ljava/math/BigDecimal;Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->divideAndRound(JJIII)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->getValueString(ILjava/lang/String;I)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/math/BigDecimal;->inflated()Ljava/math/BigInteger;
+HSPLjava/math/BigDecimal;->longMultiplyPowerTen(JI)J
+HSPLjava/math/BigDecimal;->longValueExact()J+]Ljava/math/BigInteger;Ljava/math/BigInteger;]Ljava/math/BigDecimal;Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->movePointLeft(I)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->movePointRight(I)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->multiply(JJ)J
+HSPLjava/math/BigDecimal;->multiply(JJI)Ljava/math/BigDecimal;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigDecimal;->multiply(Ljava/math/BigDecimal;)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->scale()I
+HSPLjava/math/BigDecimal;->setScale(II)Ljava/math/BigDecimal;+]Ljava/math/BigDecimal;Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->setScale(ILjava/math/RoundingMode;)Ljava/math/BigDecimal;+]Ljava/math/BigDecimal;Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->signum()I+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigDecimal;->stripTrailingZeros()Ljava/math/BigDecimal;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigDecimal;->subtract(Ljava/math/BigDecimal;)Ljava/math/BigDecimal;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigDecimal;->toBigIntegerExact()Ljava/math/BigInteger;+]Ljava/math/BigDecimal;Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->toPlainString()Ljava/lang/String;+]Ljava/math/BigDecimal;Ljava/math/BigDecimal;]Ljava/math/BigInteger;Ljava/math/BigInteger;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/math/BigDecimal;->valueOf(J)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->valueOf(JI)Ljava/math/BigDecimal;
+HSPLjava/math/BigDecimal;->zeroValueOf(I)Ljava/math/BigDecimal;
+HSPLjava/math/BigInteger$UnsafeHolder;-><clinit>()V
+HSPLjava/math/BigInteger$UnsafeHolder;->putMag(Ljava/math/BigInteger;[I)V
+HSPLjava/math/BigInteger$UnsafeHolder;->putSign(Ljava/math/BigInteger;I)V
+HSPLjava/math/BigInteger;-><init>(I[B)V
+HSPLjava/math/BigInteger;-><init>(I[I)V
+HSPLjava/math/BigInteger;-><init>(J)V
+HSPLjava/math/BigInteger;-><init>(Ljava/lang/String;)V
+HSPLjava/math/BigInteger;-><init>(Ljava/lang/String;I)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/math/BigInteger;-><init>([B)V
+HSPLjava/math/BigInteger;-><init>([II)V
+HSPLjava/math/BigInteger;->abs()Ljava/math/BigInteger;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->add(Ljava/math/BigInteger;)Ljava/math/BigInteger;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->add([I[I)[I
+HSPLjava/math/BigInteger;->bigEndInts2NewBN([IZ)J
+HSPLjava/math/BigInteger;->bitLength()I
+HSPLjava/math/BigInteger;->bitLengthForInt(I)I
+HSPLjava/math/BigInteger;->bn2BigEndInts(J)[I
+HSPLjava/math/BigInteger;->compareMagnitude(Ljava/math/BigInteger;)I
+HSPLjava/math/BigInteger;->compareTo(Ljava/math/BigInteger;)I+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->destructiveMulAdd([III)V
+HSPLjava/math/BigInteger;->divideAndRemainder(Ljava/math/BigInteger;)[Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->divideAndRemainderKnuth(Ljava/math/BigInteger;)[Ljava/math/BigInteger;+]Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;
+HSPLjava/math/BigInteger;->equals(Ljava/lang/Object;)Z
+HSPLjava/math/BigInteger;->firstNonzeroIntNum()I
+HSPLjava/math/BigInteger;->getInt(I)I
+HSPLjava/math/BigInteger;->hashCode()I
+HSPLjava/math/BigInteger;->intValue()I
+HSPLjava/math/BigInteger;->longValue()J
+HSPLjava/math/BigInteger;->mod(Ljava/math/BigInteger;)Ljava/math/BigInteger;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->modPow(Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->multiply(Ljava/math/BigInteger;)Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->multiply(Ljava/math/BigInteger;Z)Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->multiplyByInt([III)Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->multiplyToLen([II[II[I)[I
+HSPLjava/math/BigInteger;->readObject(Ljava/io/ObjectInputStream;)V+]Ljava/io/ObjectInputStream;missing_types]Ljava/io/ObjectInputStream$GetField;Ljava/io/ObjectInputStream$GetFieldImpl;
+HSPLjava/math/BigInteger;->remainder(Ljava/math/BigInteger;)Ljava/math/BigInteger;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->remainderKnuth(Ljava/math/BigInteger;)Ljava/math/BigInteger;+]Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;
+HSPLjava/math/BigInteger;->reverse([I)[I
+HSPLjava/math/BigInteger;->shiftLeft(I)Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->shiftLeft([II)[I
+HSPLjava/math/BigInteger;->shiftRight(I)Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->shiftRightImpl(I)Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->signInt()I
+HSPLjava/math/BigInteger;->signum()I
+HSPLjava/math/BigInteger;->smallToString(I)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/math/BigInteger;Ljava/math/BigInteger;]Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;
+HSPLjava/math/BigInteger;->stripLeadingZeroBytes([B)[I
+HSPLjava/math/BigInteger;->stripLeadingZeroInts([I)[I
+HSPLjava/math/BigInteger;->subtract(Ljava/math/BigInteger;)Ljava/math/BigInteger;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->subtract([I[I)[I
+HSPLjava/math/BigInteger;->testBit(I)Z
+HSPLjava/math/BigInteger;->toByteArray()[B+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->toString()Ljava/lang/String;+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->toString(I)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/math/BigInteger;->trustedStripLeadingZeroInts([I)[I
+HSPLjava/math/BigInteger;->valueOf(J)Ljava/math/BigInteger;
+HSPLjava/math/MathContext;->equals(Ljava/lang/Object;)Z
+HSPLjava/math/MathContext;->getPrecision()I
+HSPLjava/math/MathContext;->getRoundingMode()Ljava/math/RoundingMode;
+HSPLjava/math/MutableBigInteger;-><clinit>()V
+HSPLjava/math/MutableBigInteger;-><init>()V
+HSPLjava/math/MutableBigInteger;-><init>(I)V
+HSPLjava/math/MutableBigInteger;-><init>(Ljava/math/MutableBigInteger;)V
+HSPLjava/math/MutableBigInteger;-><init>([I)V
+HSPLjava/math/MutableBigInteger;->clear()V
+HSPLjava/math/MutableBigInteger;->compare(Ljava/math/MutableBigInteger;)I
+HSPLjava/math/MutableBigInteger;->copyAndShift([III[III)V
+HSPLjava/math/MutableBigInteger;->divWord(JI)J
+HSPLjava/math/MutableBigInteger;->divide(Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;)Ljava/math/MutableBigInteger;+]Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;
+HSPLjava/math/MutableBigInteger;->divide(Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;Z)Ljava/math/MutableBigInteger;+]Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;
+HSPLjava/math/MutableBigInteger;->divideKnuth(Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;)Ljava/math/MutableBigInteger;+]Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;
+HSPLjava/math/MutableBigInteger;->divideKnuth(Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;Z)Ljava/math/MutableBigInteger;+]Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;,Ljava/math/SignedMutableBigInteger;
+HSPLjava/math/MutableBigInteger;->divideMagnitude(Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;Z)Ljava/math/MutableBigInteger;+]Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;
+HSPLjava/math/MutableBigInteger;->divideOneWord(ILjava/math/MutableBigInteger;)I+]Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;
+HSPLjava/math/MutableBigInteger;->getLowestSetBit()I
+HSPLjava/math/MutableBigInteger;->getMagnitudeArray()[I
+HSPLjava/math/MutableBigInteger;->mulsub([I[IIII)I
+HSPLjava/math/MutableBigInteger;->normalize()V
+HSPLjava/math/MutableBigInteger;->primitiveLeftShift(I)V
+HSPLjava/math/MutableBigInteger;->rightShift(I)V
+HSPLjava/math/MutableBigInteger;->toBigInteger(I)Ljava/math/BigInteger;
+HSPLjava/math/MutableBigInteger;->unsignedLongCompare(JJ)Z
+HSPLjava/math/RoundingMode;->values()[Ljava/math/RoundingMode;
+HSPLjava/net/AbstractPlainDatagramSocketImpl;->bind(ILjava/net/InetAddress;)V+]Ljava/net/AbstractPlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/AbstractPlainDatagramSocketImpl;->close()V+]Ljava/net/AbstractPlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/net/AbstractPlainDatagramSocketImpl;->create()V+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;]Ljava/net/AbstractPlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/net/AbstractPlainDatagramSocketImpl;->finalize()V+]Ljava/net/AbstractPlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/net/AbstractPlainDatagramSocketImpl;->isClosed()Z
+HSPLjava/net/AbstractPlainDatagramSocketImpl;->receive(Ljava/net/DatagramPacket;)V+]Ljava/net/AbstractPlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/AbstractPlainDatagramSocketImpl;->setOption(ILjava/lang/Object;)V+]Ljava/net/NetworkInterface;Ljava/net/NetworkInterface;]Ljava/net/AbstractPlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;]Ljava/lang/Integer;Ljava/lang/Integer;
+HSPLjava/net/AbstractPlainSocketImpl;-><init>()V
+HSPLjava/net/AbstractPlainSocketImpl;->accept(Ljava/net/SocketImpl;)V+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;
+HSPLjava/net/AbstractPlainSocketImpl;->acquireFD()Ljava/io/FileDescriptor;
+HSPLjava/net/AbstractPlainSocketImpl;->bind(Ljava/net/InetAddress;I)V+]Ljava/net/ServerSocket;Ljava/net/ServerSocket;]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/AbstractPlainSocketImpl;->close()V+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/net/AbstractPlainSocketImpl;->connect(Ljava/net/SocketAddress;I)V+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLjava/net/AbstractPlainSocketImpl;->connectToAddress(Ljava/net/InetAddress;II)V+]Ljava/net/InetAddress;Ljava/net/Inet4Address;,Ljava/net/Inet6Address;]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/AbstractPlainSocketImpl;->create(Z)V+]Ljava/net/Socket;missing_types]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;]Ldalvik/system/CloseGuard;missing_types]Ljava/net/ServerSocket;Ljava/net/ServerSocket;
+HSPLjava/net/AbstractPlainSocketImpl;->doConnect(Ljava/net/InetAddress;II)V+]Ljava/net/Socket;missing_types]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLjava/net/AbstractPlainSocketImpl;->finalize()V+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/net/AbstractPlainSocketImpl;->getInputStream()Ljava/io/InputStream;+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/AbstractPlainSocketImpl;->getOption(I)Ljava/lang/Object;+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/AbstractPlainSocketImpl;->getOutputStream()Ljava/io/OutputStream;+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/AbstractPlainSocketImpl;->getTimeout()I
+HSPLjava/net/AbstractPlainSocketImpl;->isClosedOrPending()Z+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLjava/net/AbstractPlainSocketImpl;->isConnectionReset()Z
+HSPLjava/net/AbstractPlainSocketImpl;->isConnectionResetPending()Z
+HSPLjava/net/AbstractPlainSocketImpl;->listen(I)V+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/AbstractPlainSocketImpl;->releaseFD()V+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/AbstractPlainSocketImpl;->setOption(ILjava/lang/Object;)V+]Ljava/lang/Integer;Ljava/lang/Integer;]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/AbstractPlainSocketImpl;->socketClose()V+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/AbstractPlainSocketImpl;->socketPreClose()V+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/AddressCache$AddressCacheEntry;-><init>(Ljava/lang/Object;)V
+HSPLjava/net/AddressCache$AddressCacheKey;-><init>(Ljava/lang/String;I)V
+HSPLjava/net/AddressCache$AddressCacheKey;->equals(Ljava/lang/Object;)Z
+HSPLjava/net/AddressCache$AddressCacheKey;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/net/AddressCache;->clear()V+]Llibcore/util/BasicLruCache;Llibcore/util/BasicLruCache;
+HSPLjava/net/AddressCache;->get(Ljava/lang/String;I)Ljava/lang/Object;+]Llibcore/util/BasicLruCache;Llibcore/util/BasicLruCache;
+HSPLjava/net/AddressCache;->put(Ljava/lang/String;I[Ljava/net/InetAddress;)V+]Llibcore/util/BasicLruCache;Llibcore/util/BasicLruCache;
+HSPLjava/net/AddressCache;->putUnknownHost(Ljava/lang/String;ILjava/lang/String;)V+]Llibcore/util/BasicLruCache;Llibcore/util/BasicLruCache;
+HSPLjava/net/ConnectException;-><init>(Ljava/lang/String;)V
+HSPLjava/net/ConnectException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+HSPLjava/net/CookieHandler;-><init>()V
+HSPLjava/net/CookieHandler;->getDefault()Ljava/net/CookieHandler;
+HSPLjava/net/CookieManager$CookiePathComparator;-><init>()V
+HSPLjava/net/CookieManager;-><init>()V
+HSPLjava/net/CookieManager;-><init>(Ljava/net/CookieStore;Ljava/net/CookiePolicy;)V
+HSPLjava/net/CookieManager;->get(Ljava/net/URI;Ljava/util/Map;)Ljava/util/Map;+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/List;Ljava/util/ArrayList;,Ljava/util/Collections$UnmodifiableRandomAccessList;,Ljava/util/Collections$EmptyList;]Ljava/net/CookieStore;missing_types]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;,Ljava/util/Collections$UnmodifiableCollection$1;,Ljava/util/Collections$EmptyIterator;]Ljava/net/URI;Ljava/net/URI;]Ljava/net/HttpCookie;Ljava/net/HttpCookie;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/net/CookieManager;->getCookieStore()Ljava/net/CookieStore;
+HSPLjava/net/CookieManager;->normalizePath(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/net/CookieManager;->pathMatches(Ljava/net/URI;Ljava/net/HttpCookie;)Z+]Ljava/lang/String;Ljava/lang/String;]Ljava/net/HttpCookie;Ljava/net/HttpCookie;]Ljava/net/URI;Ljava/net/URI;
+HSPLjava/net/CookieManager;->put(Ljava/net/URI;Ljava/util/Map;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/Map;missing_types]Ljava/util/Iterator;missing_types]Ljava/util/Set;missing_types]Ljava/util/List;missing_types]Ljava/net/HttpCookie;Ljava/net/HttpCookie;]Ljava/net/CookieStore;missing_types]Ljava/net/URI;Ljava/net/URI;
+HSPLjava/net/CookieManager;->shouldAcceptInternal(Ljava/net/URI;Ljava/net/HttpCookie;)Z+]Ljava/net/CookiePolicy;Ljava/net/CookiePolicy$3;,Ljava/net/CookiePolicy$1;
+HSPLjava/net/CookieManager;->sortByPath(Ljava/util/List;)Ljava/util/List;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/net/HttpCookie;Ljava/net/HttpCookie;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLjava/net/DatagramPacket;-><init>([BI)V
+HSPLjava/net/DatagramPacket;-><init>([BII)V+]Ljava/net/DatagramPacket;Ljava/net/DatagramPacket;
+HSPLjava/net/DatagramPacket;-><init>([BIILjava/net/InetAddress;I)V+]Ljava/net/DatagramPacket;Ljava/net/DatagramPacket;
+HSPLjava/net/DatagramPacket;-><init>([BILjava/net/InetAddress;I)V
+HSPLjava/net/DatagramPacket;->getAddress()Ljava/net/InetAddress;
+HSPLjava/net/DatagramPacket;->getData()[B
+HSPLjava/net/DatagramPacket;->getLength()I
+HSPLjava/net/DatagramPacket;->getOffset()I
+HSPLjava/net/DatagramPacket;->getPort()I
+HSPLjava/net/DatagramPacket;->setAddress(Ljava/net/InetAddress;)V
+HSPLjava/net/DatagramPacket;->setData([BII)V
+HSPLjava/net/DatagramPacket;->setPort(I)V
+HSPLjava/net/DatagramPacket;->setReceivedLength(I)V
+HSPLjava/net/DatagramSocket$1;-><init>(Ljava/net/DatagramSocket;)V
+HSPLjava/net/DatagramSocket$1;->run()Ljava/lang/Object;+]Ljava/net/DatagramSocket$1;Ljava/net/DatagramSocket$1;
+HSPLjava/net/DatagramSocket$1;->run()Ljava/lang/Void;+]Ljava/lang/Object;Ljava/net/PlainDatagramSocketImpl;,Lsun/nio/ch/DatagramSocketAdaptor$1;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/net/DatagramSocket;-><init>()V
+HSPLjava/net/DatagramSocket;-><init>(Ljava/net/SocketAddress;)V+]Ljava/net/DatagramSocket;Ljava/net/DatagramSocket;,Ljava/net/MulticastSocket;
+HSPLjava/net/DatagramSocket;->bind(Ljava/net/SocketAddress;)V+]Ljava/net/DatagramSocket;Ljava/net/MulticastSocket;,Ljava/net/DatagramSocket;]Ljava/net/DatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLjava/net/DatagramSocket;->checkAddress(Ljava/net/InetAddress;Ljava/lang/String;)V
+HSPLjava/net/DatagramSocket;->checkOldImpl()V
+HSPLjava/net/DatagramSocket;->close()V+]Ljava/net/DatagramSocket;Ljava/net/DatagramSocket;,Ljava/net/MulticastSocket;]Ljava/net/DatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/DatagramSocket;->createImpl()V+]Ljava/net/DatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/DatagramSocket;->getImpl()Ljava/net/DatagramSocketImpl;
+HSPLjava/net/DatagramSocket;->isBound()Z
+HSPLjava/net/DatagramSocket;->isClosed()Z
+HSPLjava/net/DatagramSocket;->receive(Ljava/net/DatagramPacket;)V+]Ljava/net/DatagramSocket;Ljava/net/MulticastSocket;,Ljava/net/DatagramSocket;]Ljava/net/DatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/DatagramSocket;->send(Ljava/net/DatagramPacket;)V+]Ljava/net/DatagramPacket;Ljava/net/DatagramPacket;]Ljava/net/DatagramSocket;Ljava/net/MulticastSocket;,Ljava/net/DatagramSocket;]Ljava/net/DatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/DatagramSocket;->setReuseAddress(Z)V+]Ljava/net/DatagramSocket;Ljava/net/DatagramSocket;,Ljava/net/MulticastSocket;]Ljava/net/DatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/DatagramSocket;->setSoTimeout(I)V+]Ljava/net/DatagramSocket;Ljava/net/DatagramSocket;,Ljava/net/MulticastSocket;]Ljava/net/DatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/DatagramSocketImpl;-><init>()V
+HSPLjava/net/DatagramSocketImpl;->setDatagramSocket(Ljava/net/DatagramSocket;)V
+HSPLjava/net/HttpCookie$11;->assign(Ljava/net/HttpCookie;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/util/Date;Ljava/util/Date;]Ljava/net/HttpCookie;Ljava/net/HttpCookie;
+HSPLjava/net/HttpCookie$4;->assign(Ljava/net/HttpCookie;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/net/HttpCookie;Ljava/net/HttpCookie;
+HSPLjava/net/HttpCookie$6;->assign(Ljava/net/HttpCookie;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/net/HttpCookie;Ljava/net/HttpCookie;
+HSPLjava/net/HttpCookie$8;->assign(Ljava/net/HttpCookie;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/net/HttpCookie;Ljava/net/HttpCookie;
+HSPLjava/net/HttpCookie$9;->assign(Ljava/net/HttpCookie;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/net/HttpCookie;Ljava/net/HttpCookie;
+HSPLjava/net/HttpCookie;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/net/HttpCookie;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/net/HttpCookie;->access$000(Ljava/net/HttpCookie;)J
+HSPLjava/net/HttpCookie;->assignAttribute(Ljava/net/HttpCookie;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/net/HttpCookie$CookieAttributeAssignor;megamorphic_types]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/net/HttpCookie;->getDomain()Ljava/lang/String;
+HSPLjava/net/HttpCookie;->getMaxAge()J
+HSPLjava/net/HttpCookie;->getName()Ljava/lang/String;
+HSPLjava/net/HttpCookie;->getPath()Ljava/lang/String;
+HSPLjava/net/HttpCookie;->getPortlist()Ljava/lang/String;
+HSPLjava/net/HttpCookie;->getValue()Ljava/lang/String;
+HSPLjava/net/HttpCookie;->getVersion()I
+HSPLjava/net/HttpCookie;->guessCookieVersion(Ljava/lang/String;)I
+HSPLjava/net/HttpCookie;->hasExpired()Z
+HSPLjava/net/HttpCookie;->isToken(Ljava/lang/String;)Z+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLjava/net/HttpCookie;->parse(Ljava/lang/String;)Ljava/util/List;
+HSPLjava/net/HttpCookie;->parse(Ljava/lang/String;Z)Ljava/util/List;+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/net/HttpCookie;Ljava/net/HttpCookie;]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/net/HttpCookie;->parseInternal(Ljava/lang/String;Z)Ljava/net/HttpCookie;+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/StringTokenizer;Ljava/util/StringTokenizer;
+HSPLjava/net/HttpCookie;->setDomain(Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/net/HttpCookie;->setHttpOnly(Z)V
+HSPLjava/net/HttpCookie;->setMaxAge(J)V
+HSPLjava/net/HttpCookie;->setPath(Ljava/lang/String;)V
+HSPLjava/net/HttpCookie;->setSecure(Z)V
+HSPLjava/net/HttpCookie;->setVersion(I)V
+HSPLjava/net/HttpCookie;->startsWithIgnoreCase(Ljava/lang/String;Ljava/lang/String;)Z+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/net/HttpCookie;->stripOffSurroundingQuote(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/HttpCookie;->toNetscapeHeaderString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/net/HttpCookie;Ljava/net/HttpCookie;
+HSPLjava/net/HttpCookie;->toString()Ljava/lang/String;+]Ljava/net/HttpCookie;Ljava/net/HttpCookie;
+HSPLjava/net/HttpURLConnection;-><init>(Ljava/net/URL;)V
+HSPLjava/net/HttpURLConnection;->getFollowRedirects()Z
+HSPLjava/net/HttpURLConnection;->getRequestMethod()Ljava/lang/String;
+HSPLjava/net/HttpURLConnection;->setChunkedStreamingMode(I)V
+HSPLjava/net/HttpURLConnection;->setInstanceFollowRedirects(Z)V
+HSPLjava/net/HttpURLConnection;->setRequestMethod(Ljava/lang/String;)V
+HSPLjava/net/IDN;->toASCII(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/IDN;->toASCII(Ljava/lang/String;I)Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/net/InMemoryCookieStore;-><init>()V
+HSPLjava/net/InMemoryCookieStore;-><init>(I)V
+HSPLjava/net/InMemoryCookieStore;->get(Ljava/net/URI;)Ljava/util/List;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/net/URI;Ljava/net/URI;
+HSPLjava/net/InMemoryCookieStore;->getEffectiveURI(Ljava/net/URI;)Ljava/net/URI;+]Ljava/net/URI;Ljava/net/URI;
+HSPLjava/net/InMemoryCookieStore;->getInternal1(Ljava/util/List;Ljava/util/Map;Ljava/lang/String;)V+]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/net/HttpCookie;Ljava/net/HttpCookie;]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;,Ljava/util/ArrayList$Itr;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;
+HSPLjava/net/InMemoryCookieStore;->getInternal2(Ljava/util/List;Ljava/util/Map;Ljava/lang/Comparable;)V+]Ljava/util/Map;Ljava/util/HashMap;]Ljava/lang/Comparable;Ljava/net/URI;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;,Ljava/util/ArrayList$Itr;]Ljava/util/Set;Ljava/util/HashMap$KeySet;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/net/HttpCookie;Ljava/net/HttpCookie;
+HSPLjava/net/Inet4Address;-><init>()V+]Ljava/net/Inet4Address;Ljava/net/Inet4Address;
+HSPLjava/net/Inet4Address;-><init>(Ljava/lang/String;[B)V+]Ljava/net/Inet4Address;Ljava/net/Inet4Address;
+HSPLjava/net/Inet4Address;->equals(Ljava/lang/Object;)Z+]Ljava/net/Inet4Address;Ljava/net/Inet4Address;]Ljava/net/InetAddress;Ljava/net/Inet4Address;]Ljava/net/InetAddress$InetAddressHolder;Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/Inet4Address;->getAddress()[B+]Ljava/net/Inet4Address;Ljava/net/Inet4Address;]Ljava/net/InetAddress$InetAddressHolder;Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/Inet4Address;->getHostAddress()Ljava/lang/String;+]Ljava/net/Inet4Address;Ljava/net/Inet4Address;
+HSPLjava/net/Inet4Address;->hashCode()I+]Ljava/net/Inet4Address;Ljava/net/Inet4Address;]Ljava/net/InetAddress$InetAddressHolder;Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/Inet4Address;->isAnyLocalAddress()Z+]Ljava/net/Inet4Address;Ljava/net/Inet4Address;]Ljava/net/InetAddress$InetAddressHolder;Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/Inet4Address;->isLinkLocalAddress()Z+]Ljava/net/Inet4Address;Ljava/net/Inet4Address;]Ljava/net/InetAddress$InetAddressHolder;Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/Inet4Address;->isLoopbackAddress()Z+]Ljava/net/Inet4Address;Ljava/net/Inet4Address;
+HSPLjava/net/Inet4Address;->isMulticastAddress()Z+]Ljava/net/Inet4Address;Ljava/net/Inet4Address;]Ljava/net/InetAddress$InetAddressHolder;Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/Inet4Address;->numericToTextFormat([B)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/net/Inet6Address$Inet6AddressHolder;-><init>(Ljava/net/Inet6Address;)V
+HSPLjava/net/Inet6Address$Inet6AddressHolder;-><init>(Ljava/net/Inet6Address;Ljava/net/Inet6Address$1;)V
+HSPLjava/net/Inet6Address$Inet6AddressHolder;->equals(Ljava/lang/Object;)Z
+HSPLjava/net/Inet6Address$Inet6AddressHolder;->hashCode()I
+HSPLjava/net/Inet6Address$Inet6AddressHolder;->init([BI)V+]Ljava/net/Inet6Address$Inet6AddressHolder;Ljava/net/Inet6Address$Inet6AddressHolder;
+HSPLjava/net/Inet6Address$Inet6AddressHolder;->isAnyLocalAddress()Z
+HSPLjava/net/Inet6Address$Inet6AddressHolder;->isLinkLocalAddress()Z
+HSPLjava/net/Inet6Address$Inet6AddressHolder;->isLoopbackAddress()Z
+HSPLjava/net/Inet6Address$Inet6AddressHolder;->isMulticastAddress()Z
+HSPLjava/net/Inet6Address$Inet6AddressHolder;->setAddr([B)V
+HSPLjava/net/Inet6Address;-><init>(Ljava/lang/String;[BI)V+]Ljava/net/Inet6Address$Inet6AddressHolder;Ljava/net/Inet6Address$Inet6AddressHolder;]Ljava/net/InetAddress$InetAddressHolder;Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/Inet6Address;->equals(Ljava/lang/Object;)Z+]Ljava/net/Inet6Address$Inet6AddressHolder;Ljava/net/Inet6Address$Inet6AddressHolder;
+HSPLjava/net/Inet6Address;->getAddress()[B+][B[B
+HSPLjava/net/Inet6Address;->getByAddress(Ljava/lang/String;[BI)Ljava/net/Inet6Address;
+HSPLjava/net/Inet6Address;->getHostAddress()Ljava/lang/String;+]Llibcore/io/Os;missing_types
+HSPLjava/net/Inet6Address;->getScopeId()I
+HSPLjava/net/Inet6Address;->hashCode()I+]Ljava/net/Inet6Address$Inet6AddressHolder;Ljava/net/Inet6Address$Inet6AddressHolder;
+HSPLjava/net/Inet6Address;->isAnyLocalAddress()Z+]Ljava/net/Inet6Address$Inet6AddressHolder;Ljava/net/Inet6Address$Inet6AddressHolder;
+HSPLjava/net/Inet6Address;->isLinkLocalAddress()Z+]Ljava/net/Inet6Address$Inet6AddressHolder;Ljava/net/Inet6Address$Inet6AddressHolder;
+HSPLjava/net/Inet6Address;->isLoopbackAddress()Z+]Ljava/net/Inet6Address$Inet6AddressHolder;Ljava/net/Inet6Address$Inet6AddressHolder;
+HSPLjava/net/Inet6Address;->isMulticastAddress()Z+]Ljava/net/Inet6Address$Inet6AddressHolder;Ljava/net/Inet6Address$Inet6AddressHolder;
+HSPLjava/net/Inet6AddressImpl;->clearAddressCache()V+]Ljava/net/AddressCache;missing_types
+HSPLjava/net/Inet6AddressImpl;->lookupAllHostAddr(Ljava/lang/String;I)[Ljava/net/InetAddress;
+HSPLjava/net/Inet6AddressImpl;->lookupHostByName(Ljava/lang/String;I)[Ljava/net/InetAddress;+]Llibcore/io/Os;missing_types]Ljava/net/AddressCache;missing_types]Ljava/net/InetAddress;Ljava/net/Inet4Address;,Ljava/net/Inet6Address;]Ldalvik/system/BlockGuard$Policy;missing_types]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Landroid/system/GaiException;missing_types
+HSPLjava/net/InetAddress$InetAddressHolder;-><init>()V
+HSPLjava/net/InetAddress$InetAddressHolder;->getAddress()I
+HSPLjava/net/InetAddress$InetAddressHolder;->getHostName()Ljava/lang/String;
+HSPLjava/net/InetAddress$InetAddressHolder;->init(Ljava/lang/String;I)V
+HSPLjava/net/InetAddress;-><init>()V
+HSPLjava/net/InetAddress;->clearDnsCache()V+]Ljava/net/InetAddressImpl;Ljava/net/Inet6AddressImpl;
+HSPLjava/net/InetAddress;->getAllByName(Ljava/lang/String;)[Ljava/net/InetAddress;+]Ljava/net/InetAddressImpl;Ljava/net/Inet6AddressImpl;][Ljava/net/InetAddress;[Ljava/net/InetAddress;
+HSPLjava/net/InetAddress;->getAllByNameOnNet(Ljava/lang/String;I)[Ljava/net/InetAddress;+]Ljava/net/InetAddressImpl;Ljava/net/Inet6AddressImpl;][Ljava/net/InetAddress;[Ljava/net/InetAddress;
+HSPLjava/net/InetAddress;->getByAddress(Ljava/lang/String;[B)Ljava/net/InetAddress;
+HSPLjava/net/InetAddress;->getByAddress(Ljava/lang/String;[BI)Ljava/net/InetAddress;
+HSPLjava/net/InetAddress;->getByAddress([B)Ljava/net/InetAddress;
+HSPLjava/net/InetAddress;->getByName(Ljava/lang/String;)Ljava/net/InetAddress;+]Ljava/net/InetAddressImpl;Ljava/net/Inet6AddressImpl;
+HSPLjava/net/InetAddress;->getHostName()Ljava/lang/String;+]Ljava/net/InetAddress;Ljava/net/Inet4Address;,Ljava/net/Inet6Address;]Ljava/net/InetAddress$InetAddressHolder;Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/InetAddress;->holder()Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/InetAddress;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/net/InetAddress;Ljava/net/Inet4Address;,Ljava/net/Inet6Address;]Ljava/net/InetAddress$InetAddressHolder;Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;-><init>(Ljava/lang/String;Ljava/net/InetAddress;I)V
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;-><init>(Ljava/lang/String;Ljava/net/InetAddress;ILjava/net/InetSocketAddress$1;)V
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->access$400(Ljava/net/InetSocketAddress$InetSocketAddressHolder;)I
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->access$500(Ljava/net/InetSocketAddress$InetSocketAddressHolder;)Ljava/net/InetAddress;
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->access$600(Ljava/net/InetSocketAddress$InetSocketAddressHolder;)Ljava/lang/String;
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->access$700(Ljava/net/InetSocketAddress$InetSocketAddressHolder;)Ljava/lang/String;
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->access$800(Ljava/net/InetSocketAddress$InetSocketAddressHolder;)Z
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->equals(Ljava/lang/Object;)Z+]Ljava/net/InetAddress;Ljava/net/Inet4Address;,Ljava/net/Inet6Address;
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->getAddress()Ljava/net/InetAddress;
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->getHostName()Ljava/lang/String;
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->getHostString()Ljava/lang/String;+]Ljava/net/InetAddress;Ljava/net/Inet4Address;,Ljava/net/Inet6Address;]Ljava/net/InetAddress$InetAddressHolder;Ljava/net/InetAddress$InetAddressHolder;
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->getPort()I
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;]Ljava/net/InetAddress;Ljava/net/Inet6Address;,Ljava/net/Inet4Address;
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->isUnresolved()Z
+HSPLjava/net/InetSocketAddress$InetSocketAddressHolder;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/net/InetAddress;Ljava/net/Inet6Address;,Ljava/net/Inet4Address;
+HSPLjava/net/InetSocketAddress;-><init>()V
+HSPLjava/net/InetSocketAddress;-><init>(I)V
+HSPLjava/net/InetSocketAddress;-><init>(ILjava/lang/String;)V
+HSPLjava/net/InetSocketAddress;-><init>(Ljava/lang/String;I)V
+HSPLjava/net/InetSocketAddress;-><init>(Ljava/net/InetAddress;I)V
+HSPLjava/net/InetSocketAddress;->checkHost(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/InetSocketAddress;->checkPort(I)I
+HSPLjava/net/InetSocketAddress;->createUnresolved(Ljava/lang/String;I)Ljava/net/InetSocketAddress;
+HSPLjava/net/InetSocketAddress;->equals(Ljava/lang/Object;)Z+]Ljava/net/InetSocketAddress$InetSocketAddressHolder;Ljava/net/InetSocketAddress$InetSocketAddressHolder;
+HSPLjava/net/InetSocketAddress;->getAddress()Ljava/net/InetAddress;
+HSPLjava/net/InetSocketAddress;->getHostName()Ljava/lang/String;
+HSPLjava/net/InetSocketAddress;->getHostString()Ljava/lang/String;
+HSPLjava/net/InetSocketAddress;->getPort()I
+HSPLjava/net/InetSocketAddress;->hashCode()I+]Ljava/net/InetSocketAddress$InetSocketAddressHolder;Ljava/net/InetSocketAddress$InetSocketAddressHolder;
+HSPLjava/net/InetSocketAddress;->isUnresolved()Z
+HSPLjava/net/InetSocketAddress;->toString()Ljava/lang/String;+]Ljava/net/InetSocketAddress$InetSocketAddressHolder;Ljava/net/InetSocketAddress$InetSocketAddressHolder;
+HSPLjava/net/InterfaceAddress;-><init>(Ljava/net/InetAddress;Ljava/net/Inet4Address;Ljava/net/InetAddress;)V
+HSPLjava/net/InterfaceAddress;->countPrefixLength(Ljava/net/InetAddress;)S+]Ljava/net/InetAddress;Ljava/net/Inet6Address;,Ljava/net/Inet4Address;
+HSPLjava/net/JarURLConnection;-><init>(Ljava/net/URL;)V
+HSPLjava/net/JarURLConnection;->getEntryName()Ljava/lang/String;
+HSPLjava/net/JarURLConnection;->parseSpecs(Ljava/net/URL;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/net/URL;Ljava/net/URL;
+HSPLjava/net/MulticastSocket;-><init>(Ljava/net/SocketAddress;)V+]Ljava/net/MulticastSocket;Ljava/net/MulticastSocket;
+HSPLjava/net/NetworkInterface$1checkedAddresses;-><init>(Ljava/net/NetworkInterface;)V
+HSPLjava/net/NetworkInterface$1checkedAddresses;->hasMoreElements()Z
+HSPLjava/net/NetworkInterface$1checkedAddresses;->nextElement()Ljava/lang/Object;+]Ljava/net/NetworkInterface$1checkedAddresses;Ljava/net/NetworkInterface$1checkedAddresses;
+HSPLjava/net/NetworkInterface$1checkedAddresses;->nextElement()Ljava/net/InetAddress;
+HSPLjava/net/NetworkInterface;-><init>(Ljava/lang/String;I[Ljava/net/InetAddress;)V
+HSPLjava/net/NetworkInterface;->access$000(Ljava/net/NetworkInterface;)[Ljava/net/InetAddress;
+HSPLjava/net/NetworkInterface;->getAll()[Ljava/net/NetworkInterface;+]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;]Ljava/net/NetworkInterface;Ljava/net/NetworkInterface;]Llibcore/io/Os;missing_types]Ljava/util/Collection;Ljava/util/HashMap$Values;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;,Ljava/util/ArrayList$Itr;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;
+HSPLjava/net/NetworkInterface;->getFlags()I+]Llibcore/io/Os;missing_types]Landroid/system/ErrnoException;missing_types
+HSPLjava/net/NetworkInterface;->getIndex()I
+HSPLjava/net/NetworkInterface;->getInetAddresses()Ljava/util/Enumeration;
+HSPLjava/net/NetworkInterface;->getName()Ljava/lang/String;
+HSPLjava/net/NetworkInterface;->getNetworkInterfaces()Ljava/util/Enumeration;
+HSPLjava/net/NetworkInterface;->isLoopback()Z
+HSPLjava/net/NetworkInterface;->isUp()Z
+HSPLjava/net/Parts;-><init>(Ljava/lang/String;Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/net/Parts;->getPath()Ljava/lang/String;
+HSPLjava/net/Parts;->getQuery()Ljava/lang/String;
+HSPLjava/net/Parts;->getRef()Ljava/lang/String;
+HSPLjava/net/PlainDatagramSocketImpl;->bind0(ILjava/net/InetAddress;)V+]Ljava/net/PlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLjava/net/PlainDatagramSocketImpl;->datagramSocketClose()V
+HSPLjava/net/PlainDatagramSocketImpl;->datagramSocketCreate()V+]Llibcore/io/Os;missing_types
+HSPLjava/net/PlainDatagramSocketImpl;->doRecv(Ljava/net/DatagramPacket;I)V+]Ljava/net/DatagramPacket;Ljava/net/DatagramPacket;]Ljava/net/PlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/PlainDatagramSocketImpl;->receive0(Ljava/net/DatagramPacket;)V
+HSPLjava/net/PlainDatagramSocketImpl;->send(Ljava/net/DatagramPacket;)V+]Ljava/net/DatagramPacket;Ljava/net/DatagramPacket;]Ljava/net/PlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/PlainDatagramSocketImpl;->socketSetOption(ILjava/lang/Object;)V+]Ljava/net/PlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/PlainDatagramSocketImpl;->socketSetOption0(ILjava/lang/Object;)V+]Ljava/net/PlainDatagramSocketImpl;Ljava/net/PlainDatagramSocketImpl;
+HSPLjava/net/PlainSocketImpl;-><init>()V
+HSPLjava/net/PlainSocketImpl;->getMarkerFD()Ljava/io/FileDescriptor;+]Llibcore/io/Os;missing_types
+HSPLjava/net/PlainSocketImpl;->socketAccept(Ljava/net/SocketImpl;)V+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLjava/net/PlainSocketImpl;->socketBind(Ljava/net/InetAddress;I)V+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLjava/net/PlainSocketImpl;->socketClose0(Z)V+]Llibcore/io/Os;missing_types]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLjava/net/PlainSocketImpl;->socketConnect(Ljava/net/InetAddress;II)V+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;]Ljava/net/PlainSocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLjava/net/PlainSocketImpl;->socketCreate(Z)V+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLjava/net/PlainSocketImpl;->socketGetOption(I)Ljava/lang/Object;
+HSPLjava/net/PlainSocketImpl;->socketListen(I)V+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLjava/net/PlainSocketImpl;->socketSetOption(ILjava/lang/Object;)V+]Ljava/net/PlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/PlainSocketImpl;->socketSetOption0(ILjava/lang/Object;)V
+HSPLjava/net/Proxy$Type;->values()[Ljava/net/Proxy$Type;
+HSPLjava/net/Proxy;->address()Ljava/net/SocketAddress;
+HSPLjava/net/Proxy;->equals(Ljava/lang/Object;)Z+]Ljava/net/Proxy;Ljava/net/Proxy;
+HSPLjava/net/Proxy;->hashCode()I+]Ljava/net/Proxy$Type;Ljava/net/Proxy$Type;]Ljava/net/Proxy;Ljava/net/Proxy;
+HSPLjava/net/Proxy;->type()Ljava/net/Proxy$Type;
+HSPLjava/net/ProxySelector;->getDefault()Ljava/net/ProxySelector;
+HSPLjava/net/ProxySelector;->setDefault(Ljava/net/ProxySelector;)V
+HSPLjava/net/ResponseCache;->getDefault()Ljava/net/ResponseCache;
+HSPLjava/net/ServerSocket;-><init>()V
+HSPLjava/net/ServerSocket;->accept()Ljava/net/Socket;+]Ljava/net/ServerSocket;Ljava/net/ServerSocket;
+HSPLjava/net/ServerSocket;->bind(Ljava/net/SocketAddress;)V
+HSPLjava/net/ServerSocket;->bind(Ljava/net/SocketAddress;I)V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/ServerSocket;Ljava/net/ServerSocket;]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLjava/net/ServerSocket;->createImpl()V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/ServerSocket;->getImpl()Ljava/net/SocketImpl;+]Ljava/net/ServerSocket;Ljava/net/ServerSocket;
+HSPLjava/net/ServerSocket;->implAccept(Ljava/net/Socket;)V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;Ljava/net/Socket;]Ljava/net/ServerSocket;Ljava/net/ServerSocket;
+HSPLjava/net/ServerSocket;->isBound()Z
+HSPLjava/net/ServerSocket;->isClosed()Z
+HSPLjava/net/ServerSocket;->setBound()V
+HSPLjava/net/ServerSocket;->setCreated()V
+HSPLjava/net/ServerSocket;->setImpl()V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/Socket$1;-><init>(Ljava/net/Socket;)V
+HSPLjava/net/Socket$1;->run()Ljava/lang/Boolean;+]Ljava/lang/Object;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/net/Socket$1;->run()Ljava/lang/Object;+]Ljava/net/Socket$1;Ljava/net/Socket$1;
+HSPLjava/net/Socket$2;-><init>(Ljava/net/Socket;)V
+HSPLjava/net/Socket$2;->run()Ljava/io/InputStream;+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/Socket$2;->run()Ljava/lang/Object;+]Ljava/net/Socket$2;Ljava/net/Socket$2;
+HSPLjava/net/Socket$3;-><init>(Ljava/net/Socket;)V
+HSPLjava/net/Socket$3;->run()Ljava/io/OutputStream;+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/Socket$3;->run()Ljava/lang/Object;+]Ljava/net/Socket$3;Ljava/net/Socket$3;
+HSPLjava/net/Socket;-><init>()V+]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;-><init>(Ljava/net/InetAddress;I)V
+HSPLjava/net/Socket;-><init>(Ljava/net/SocketImpl;)V+]Ljava/net/SocketImpl;missing_types
+HSPLjava/net/Socket;-><init>([Ljava/net/InetAddress;ILjava/net/SocketAddress;Z)V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->checkAddress(Ljava/net/InetAddress;Ljava/lang/String;)V
+HSPLjava/net/Socket;->checkOldImpl()V+]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLjava/net/Socket;->close()V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->connect(Ljava/net/SocketAddress;)V+]Ljava/net/Socket;Ljava/net/Socket;
+HSPLjava/net/Socket;->connect(Ljava/net/SocketAddress;I)V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;missing_types]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLjava/net/Socket;->createImpl(Z)V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/Socket;->getFileDescriptor$()Ljava/io/FileDescriptor;+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/Socket;->getImpl()Ljava/net/SocketImpl;+]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->getInetAddress()Ljava/net/InetAddress;+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->getInputStream()Ljava/io/InputStream;+]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->getLocalAddress()Ljava/net/InetAddress;+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;missing_types]Ljava/net/InetAddress;Ljava/net/Inet4Address;,Ljava/net/Inet6Address;
+HSPLjava/net/Socket;->getLocalPort()I+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->getLocalSocketAddress()Ljava/net/SocketAddress;+]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->getOutputStream()Ljava/io/OutputStream;+]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->getPort()I+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->getRemoteSocketAddress()Ljava/net/SocketAddress;+]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->getReuseAddress()Z+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;missing_types]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLjava/net/Socket;->getSoTimeout()I+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/lang/Integer;Ljava/lang/Integer;]Ljava/net/Socket;Ljava/net/Socket;
+HSPLjava/net/Socket;->isBound()Z
+HSPLjava/net/Socket;->isClosed()Z
+HSPLjava/net/Socket;->isConnected()Z
+HSPLjava/net/Socket;->isInputShutdown()Z
+HSPLjava/net/Socket;->isOutputShutdown()Z
+HSPLjava/net/Socket;->nonNullAddress(Ljava/net/InetAddress;)[Ljava/net/InetAddress;
+HSPLjava/net/Socket;->setBound()V
+HSPLjava/net/Socket;->setConnected()V
+HSPLjava/net/Socket;->setCreated()V
+HSPLjava/net/Socket;->setImpl()V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/Socket;->setSoTimeout(I)V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;missing_types
+HSPLjava/net/Socket;->setTcpNoDelay(Z)V+]Ljava/net/SocketImpl;Ljava/net/SocksSocketImpl;]Ljava/net/Socket;missing_types
+HSPLjava/net/SocketAddress;-><init>()V
+HSPLjava/net/SocketException;-><init>(Ljava/lang/String;)V
+HSPLjava/net/SocketException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+HSPLjava/net/SocketImpl;-><init>()V
+HSPLjava/net/SocketImpl;->getFileDescriptor()Ljava/io/FileDescriptor;
+HSPLjava/net/SocketImpl;->getInetAddress()Ljava/net/InetAddress;
+HSPLjava/net/SocketImpl;->getLocalPort()I
+HSPLjava/net/SocketImpl;->getPort()I
+HSPLjava/net/SocketImpl;->getSocket()Ljava/net/Socket;
+HSPLjava/net/SocketImpl;->setServerSocket(Ljava/net/ServerSocket;)V
+HSPLjava/net/SocketImpl;->setSocket(Ljava/net/Socket;)V
+HSPLjava/net/SocketInputStream;-><init>(Ljava/net/AbstractPlainSocketImpl;)V+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/SocketInputStream;->finalize()V
+HSPLjava/net/SocketInputStream;->read([BII)I+]Ljava/net/SocketInputStream;Ljava/net/SocketInputStream;]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;,Ljava/net/PlainSocketImpl;
+HSPLjava/net/SocketInputStream;->read([BIII)I+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;,Ljava/net/PlainSocketImpl;]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLjava/net/SocketInputStream;->socketRead(Ljava/io/FileDescriptor;[BIII)I
+HSPLjava/net/SocketOutputStream;-><init>(Ljava/net/AbstractPlainSocketImpl;)V+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;
+HSPLjava/net/SocketOutputStream;->finalize()V
+HSPLjava/net/SocketOutputStream;->socketWrite([BII)V+]Ljava/net/AbstractPlainSocketImpl;Ljava/net/SocksSocketImpl;,Ljava/net/PlainSocketImpl;]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLjava/net/SocketOutputStream;->write([BII)V
+HSPLjava/net/SocketTimeoutException;-><init>(Ljava/lang/String;)V
+HSPLjava/net/SocksSocketImpl;-><init>()V
+HSPLjava/net/SocksSocketImpl;->close()V
+HSPLjava/net/SocksSocketImpl;->connect(Ljava/net/SocketAddress;I)V
+HSPLjava/net/SocksSocketImpl;->getInetAddress()Ljava/net/InetAddress;
+HSPLjava/net/SocksSocketImpl;->getLocalPort()I
+HSPLjava/net/SocksSocketImpl;->getPort()I
+HSPLjava/net/SocksSocketImpl;->remainingMillis(J)I
+HSPLjava/net/URI$Parser;-><init>(Ljava/net/URI;Ljava/lang/String;)V
+HSPLjava/net/URI$Parser;->at(IIC)Z
+HSPLjava/net/URI$Parser;->charAt(I)C
+HSPLjava/net/URI$Parser;->checkChar(IJJLjava/lang/String;)V
+HSPLjava/net/URI$Parser;->checkChars(IIJJLjava/lang/String;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/net/URI$Parser;->parse(Z)V
+HSPLjava/net/URI$Parser;->parseAuthority(II)I
+HSPLjava/net/URI$Parser;->parseHierarchical(II)I
+HSPLjava/net/URI$Parser;->parseHostname(II)I
+HSPLjava/net/URI$Parser;->parseIPv4Address(II)I
+HSPLjava/net/URI$Parser;->parseServer(II)I
+HSPLjava/net/URI$Parser;->scan(IIC)I
+HSPLjava/net/URI$Parser;->scan(IIJJ)I
+HSPLjava/net/URI$Parser;->scan(IILjava/lang/String;Ljava/lang/String;)I
+HSPLjava/net/URI$Parser;->scanByte(II)I
+HSPLjava/net/URI$Parser;->scanEscape(IIC)I
+HSPLjava/net/URI$Parser;->scanIPv4Address(IIZ)I
+HSPLjava/net/URI$Parser;->substring(II)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/net/URI;-><init>(Ljava/lang/String;)V+]Ljava/net/URI$Parser;Ljava/net/URI$Parser;
+HSPLjava/net/URI;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/net/URI$Parser;Ljava/net/URI$Parser;
+HSPLjava/net/URI;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/net/URI;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/net/URI$Parser;Ljava/net/URI$Parser;
+HSPLjava/net/URI;->access$002(Ljava/net/URI;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/URI;->access$100()J
+HSPLjava/net/URI;->access$1002(Ljava/net/URI;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/URI;->access$1200()J
+HSPLjava/net/URI;->access$1300()J
+HSPLjava/net/URI;->access$1402(Ljava/net/URI;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/URI;->access$1502(Ljava/net/URI;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/URI;->access$1600()J
+HSPLjava/net/URI;->access$1700()J
+HSPLjava/net/URI;->access$200()J
+HSPLjava/net/URI;->access$2000()J
+HSPLjava/net/URI;->access$2100()J
+HSPLjava/net/URI;->access$2202(Ljava/net/URI;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/URI;->access$2402(Ljava/net/URI;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/URI;->access$2502(Ljava/net/URI;I)I
+HSPLjava/net/URI;->access$2800()J
+HSPLjava/net/URI;->access$2900()J
+HSPLjava/net/URI;->access$300(CJJ)Z
+HSPLjava/net/URI;->access$3000()J
+HSPLjava/net/URI;->access$3100()J
+HSPLjava/net/URI;->access$3200()J
+HSPLjava/net/URI;->access$3300()J
+HSPLjava/net/URI;->access$3400()J
+HSPLjava/net/URI;->access$3500()J
+HSPLjava/net/URI;->access$3600()J
+HSPLjava/net/URI;->access$400()J
+HSPLjava/net/URI;->access$500()J
+HSPLjava/net/URI;->access$600()J
+HSPLjava/net/URI;->access$702(Ljava/net/URI;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/URI;->access$800()J
+HSPLjava/net/URI;->access$900()J
+HSPLjava/net/URI;->appendAuthority(Ljava/lang/StringBuffer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/net/URI;->appendEscape(Ljava/lang/StringBuffer;B)V+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/net/URI;->appendFragment(Ljava/lang/StringBuffer;Ljava/lang/String;)V+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/net/URI;->appendSchemeSpecificPart(Ljava/lang/StringBuffer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/net/URI;->checkPath(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/net/URI;->create(Ljava/lang/String;)Ljava/net/URI;+]Ljava/net/URISyntaxException;Ljava/net/URISyntaxException;
+HSPLjava/net/URI;->decode(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/Object;Ljava/nio/HeapCharBuffer;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLjava/net/URI;->defineString()V+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/net/URI;Ljava/net/URI;
+HSPLjava/net/URI;->encode(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/net/URI;->equal(Ljava/lang/String;Ljava/lang/String;)Z
+HSPLjava/net/URI;->equalIgnoringCase(Ljava/lang/String;Ljava/lang/String;)Z
+HSPLjava/net/URI;->equals(Ljava/lang/Object;)Z+]Ljava/net/URI;Ljava/net/URI;
+HSPLjava/net/URI;->getAuthority()Ljava/lang/String;
+HSPLjava/net/URI;->getFragment()Ljava/lang/String;
+HSPLjava/net/URI;->getHost()Ljava/lang/String;
+HSPLjava/net/URI;->getPath()Ljava/lang/String;
+HSPLjava/net/URI;->getPort()I
+HSPLjava/net/URI;->getQuery()Ljava/lang/String;
+HSPLjava/net/URI;->getRawFragment()Ljava/lang/String;
+HSPLjava/net/URI;->getRawPath()Ljava/lang/String;
+HSPLjava/net/URI;->getRawQuery()Ljava/lang/String;
+HSPLjava/net/URI;->getScheme()Ljava/lang/String;
+HSPLjava/net/URI;->getUserInfo()Ljava/lang/String;
+HSPLjava/net/URI;->hash(ILjava/lang/String;)I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/net/URI;->hashCode()I+]Ljava/net/URI;Ljava/net/URI;
+HSPLjava/net/URI;->hashIgnoringCase(ILjava/lang/String;)I
+HSPLjava/net/URI;->isAbsolute()Z
+HSPLjava/net/URI;->isOpaque()Z
+HSPLjava/net/URI;->match(CJJ)Z
+HSPLjava/net/URI;->quote(Ljava/lang/String;JJ)Ljava/lang/String;
+HSPLjava/net/URI;->toASCIIString()Ljava/lang/String;
+HSPLjava/net/URI;->toLower(C)I
+HSPLjava/net/URI;->toString()Ljava/lang/String;
+HSPLjava/net/URI;->toString(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/net/URI;->toURL()Ljava/net/URL;+]Ljava/net/URI;Ljava/net/URI;
+HSPLjava/net/URL;-><init>(Ljava/lang/String;)V
+HSPLjava/net/URL;-><init>(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)V
+HSPLjava/net/URL;-><init>(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/net/URLStreamHandler;)V+]Ljava/net/Parts;Ljava/net/Parts;]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/net/URL;-><init>(Ljava/net/URL;Ljava/lang/String;)V
+HSPLjava/net/URL;-><init>(Ljava/net/URL;Ljava/lang/String;Ljava/net/URLStreamHandler;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/net/URLStreamHandler;missing_types]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/net/MalformedURLException;Ljava/net/MalformedURLException;]Ljava/lang/Exception;Ljava/lang/NullPointerException;
+HSPLjava/net/URL;->createBuiltinHandler(Ljava/lang/String;)Ljava/net/URLStreamHandler;
+HSPLjava/net/URL;->getAuthority()Ljava/lang/String;
+HSPLjava/net/URL;->getFile()Ljava/lang/String;
+HSPLjava/net/URL;->getHost()Ljava/lang/String;
+HSPLjava/net/URL;->getPath()Ljava/lang/String;
+HSPLjava/net/URL;->getPort()I
+HSPLjava/net/URL;->getProtocol()Ljava/lang/String;
+HSPLjava/net/URL;->getQuery()Ljava/lang/String;
+HSPLjava/net/URL;->getRef()Ljava/lang/String;
+HSPLjava/net/URL;->getURLStreamHandler(Ljava/lang/String;)Ljava/net/URLStreamHandler;+]Ljava/util/Hashtable;Ljava/util/Hashtable;]Ljava/util/StringTokenizer;Ljava/util/StringTokenizer;
+HSPLjava/net/URL;->getUserInfo()Ljava/lang/String;
+HSPLjava/net/URL;->isValidProtocol(Ljava/lang/String;)Z
+HSPLjava/net/URL;->openConnection()Ljava/net/URLConnection;+]Ljava/net/URLStreamHandler;missing_types
+HSPLjava/net/URL;->openStream()Ljava/io/InputStream;
+HSPLjava/net/URL;->set(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/net/URL;->toExternalForm()Ljava/lang/String;+]Ljava/net/URLStreamHandler;missing_types
+HSPLjava/net/URL;->toString()Ljava/lang/String;+]Ljava/net/URL;Ljava/net/URL;
+HSPLjava/net/URLConnection;-><init>(Ljava/net/URL;)V
+HSPLjava/net/URLConnection;->getContentEncoding()Ljava/lang/String;+]Ljava/net/URLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLjava/net/URLConnection;->getContentLength()I+]Ljava/net/URLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLjava/net/URLConnection;->getContentLengthLong()J+]Ljava/net/URLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLjava/net/URLConnection;->getContentType()Ljava/lang/String;+]Ljava/net/URLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLjava/net/URLConnection;->getHeaderFieldInt(Ljava/lang/String;I)I+]Ljava/net/URLConnection;Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+HSPLjava/net/URLConnection;->getHeaderFieldLong(Ljava/lang/String;J)J+]Ljava/net/URLConnection;missing_types
+HSPLjava/net/URLConnection;->getReadTimeout()I
+HSPLjava/net/URLConnection;->getURL()Ljava/net/URL;
+HSPLjava/net/URLConnection;->getUseCaches()Z
+HSPLjava/net/URLConnection;->setDefaultUseCaches(Z)V
+HSPLjava/net/URLConnection;->setDoInput(Z)V
+HSPLjava/net/URLConnection;->setDoOutput(Z)V
+HSPLjava/net/URLConnection;->setReadTimeout(I)V
+HSPLjava/net/URLConnection;->setUseCaches(Z)V
+HSPLjava/net/URLDecoder;->decode(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/net/URLDecoder;->isValidHexChar(C)Z
+HSPLjava/net/URLEncoder;->encode(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/BitSet;Ljava/util/BitSet;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/lang/String;Ljava/lang/String;]Ljava/io/CharArrayWriter;Ljava/io/CharArrayWriter;
+HSPLjava/net/URLStreamHandler;-><init>()V
+HSPLjava/net/URLStreamHandler;->parseURL(Ljava/net/URL;Ljava/lang/String;II)V+]Ljava/net/URLStreamHandler;missing_types]Ljava/lang/String;Ljava/lang/String;]Ljava/net/URL;Ljava/net/URL;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/net/URLStreamHandler;->setURL(Ljava/net/URL;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/net/URL;Ljava/net/URL;
+HSPLjava/net/URLStreamHandler;->toExternalForm(Ljava/net/URL;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/net/URL;Ljava/net/URL;
+HSPLjava/net/UnknownHostException;-><init>(Ljava/lang/String;)V
+HSPLjava/nio/Bits;->byteOrder()Ljava/nio/ByteOrder;
+HSPLjava/nio/Bits;->char0(C)B
+HSPLjava/nio/Bits;->char1(C)B
+HSPLjava/nio/Bits;->getFloat(Ljava/nio/ByteBuffer;IZ)F
+HSPLjava/nio/Bits;->getFloatL(Ljava/nio/ByteBuffer;I)F
+HSPLjava/nio/Bits;->getInt(Ljava/nio/ByteBuffer;IZ)I
+HSPLjava/nio/Bits;->getIntB(Ljava/nio/ByteBuffer;I)I+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->getIntL(Ljava/nio/ByteBuffer;I)I+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->getLong(Ljava/nio/ByteBuffer;IZ)J
+HSPLjava/nio/Bits;->getLongB(Ljava/nio/ByteBuffer;I)J+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->getLongL(Ljava/nio/ByteBuffer;I)J+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->getShort(Ljava/nio/ByteBuffer;IZ)S
+HSPLjava/nio/Bits;->getShortB(Ljava/nio/ByteBuffer;I)S+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->getShortL(Ljava/nio/ByteBuffer;I)S+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->int0(I)B
+HSPLjava/nio/Bits;->int1(I)B
+HSPLjava/nio/Bits;->int2(I)B
+HSPLjava/nio/Bits;->int3(I)B
+HSPLjava/nio/Bits;->long0(J)B
+HSPLjava/nio/Bits;->long1(J)B
+HSPLjava/nio/Bits;->long2(J)B
+HSPLjava/nio/Bits;->long3(J)B
+HSPLjava/nio/Bits;->long4(J)B
+HSPLjava/nio/Bits;->long5(J)B
+HSPLjava/nio/Bits;->long6(J)B
+HSPLjava/nio/Bits;->long7(J)B
+HSPLjava/nio/Bits;->makeInt(BBBB)I
+HSPLjava/nio/Bits;->makeLong(BBBBBBBB)J
+HSPLjava/nio/Bits;->makeShort(BB)S
+HSPLjava/nio/Bits;->pageCount(J)I
+HSPLjava/nio/Bits;->pageSize()I
+HSPLjava/nio/Bits;->putChar(Ljava/nio/ByteBuffer;ICZ)V
+HSPLjava/nio/Bits;->putCharB(Ljava/nio/ByteBuffer;IC)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->putCharL(Ljava/nio/ByteBuffer;IC)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->putFloat(Ljava/nio/ByteBuffer;IFZ)V
+HSPLjava/nio/Bits;->putInt(Ljava/nio/ByteBuffer;IIZ)V
+HSPLjava/nio/Bits;->putIntB(Ljava/nio/ByteBuffer;II)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->putIntL(Ljava/nio/ByteBuffer;II)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->putLong(Ljava/nio/ByteBuffer;IJZ)V
+HSPLjava/nio/Bits;->putLongB(Ljava/nio/ByteBuffer;IJ)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->putLongL(Ljava/nio/ByteBuffer;IJ)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->putShort(Ljava/nio/ByteBuffer;ISZ)V
+HSPLjava/nio/Bits;->putShortB(Ljava/nio/ByteBuffer;IS)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->putShortL(Ljava/nio/ByteBuffer;IS)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/Bits;->short0(S)B
+HSPLjava/nio/Bits;->short1(S)B
+HSPLjava/nio/Bits;->unsafe()Lsun/misc/Unsafe;
+HSPLjava/nio/Buffer;-><init>(IIIII)V+]Ljava/nio/Buffer;megamorphic_types
+HSPLjava/nio/Buffer;->capacity()I
+HSPLjava/nio/Buffer;->checkBounds(III)V
+HSPLjava/nio/Buffer;->checkIndex(I)I
+HSPLjava/nio/Buffer;->checkIndex(II)I
+HSPLjava/nio/Buffer;->clear()Ljava/nio/Buffer;
+HSPLjava/nio/Buffer;->discardMark()V
+HSPLjava/nio/Buffer;->flip()Ljava/nio/Buffer;
+HSPLjava/nio/Buffer;->hasRemaining()Z
+HSPLjava/nio/Buffer;->limit()I
+HSPLjava/nio/Buffer;->limit(I)Ljava/nio/Buffer;
+HSPLjava/nio/Buffer;->mark()Ljava/nio/Buffer;
+HSPLjava/nio/Buffer;->markValue()I
+HSPLjava/nio/Buffer;->nextGetIndex()I
+HSPLjava/nio/Buffer;->nextGetIndex(I)I
+HSPLjava/nio/Buffer;->nextPutIndex()I
+HSPLjava/nio/Buffer;->nextPutIndex(I)I
+HSPLjava/nio/Buffer;->position()I
+HSPLjava/nio/Buffer;->position(I)Ljava/nio/Buffer;
+HSPLjava/nio/Buffer;->remaining()I
+HSPLjava/nio/Buffer;->reset()Ljava/nio/Buffer;
+HSPLjava/nio/Buffer;->rewind()Ljava/nio/Buffer;
+HSPLjava/nio/ByteBuffer;-><init>(IIII)V
+HSPLjava/nio/ByteBuffer;-><init>(IIII[BI)V
+HSPLjava/nio/ByteBuffer;->allocate(I)Ljava/nio/ByteBuffer;
+HSPLjava/nio/ByteBuffer;->allocateDirect(I)Ljava/nio/ByteBuffer;
+HSPLjava/nio/ByteBuffer;->array()Ljava/lang/Object;+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/ByteBuffer;->array()[B
+HSPLjava/nio/ByteBuffer;->arrayOffset()I
+HSPLjava/nio/ByteBuffer;->clear()Ljava/nio/Buffer;
+HSPLjava/nio/ByteBuffer;->compare(BB)I
+HSPLjava/nio/ByteBuffer;->compareTo(Ljava/nio/ByteBuffer;)I+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/ByteBuffer;->equals(BB)Z
+HSPLjava/nio/ByteBuffer;->equals(Ljava/lang/Object;)Z+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/ByteBuffer;->flip()Ljava/nio/Buffer;
+HSPLjava/nio/ByteBuffer;->get([B)Ljava/nio/ByteBuffer;+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/ByteBuffer;->hasArray()Z
+HSPLjava/nio/ByteBuffer;->hashCode()I+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/ByteBuffer;->limit(I)Ljava/nio/Buffer;
+HSPLjava/nio/ByteBuffer;->mark()Ljava/nio/Buffer;
+HSPLjava/nio/ByteBuffer;->order()Ljava/nio/ByteOrder;
+HSPLjava/nio/ByteBuffer;->order(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;
+HSPLjava/nio/ByteBuffer;->position(I)Ljava/nio/Buffer;
+HSPLjava/nio/ByteBuffer;->put(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/ByteBuffer;->put([B)Ljava/nio/ByteBuffer;+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/ByteBuffer;->reset()Ljava/nio/Buffer;
+HSPLjava/nio/ByteBuffer;->rewind()Ljava/nio/Buffer;
+HSPLjava/nio/ByteBuffer;->wrap([B)Ljava/nio/ByteBuffer;
+HSPLjava/nio/ByteBuffer;->wrap([BII)Ljava/nio/ByteBuffer;
+HSPLjava/nio/ByteBufferAsCharBuffer;-><init>(Ljava/nio/ByteBuffer;IIIIILjava/nio/ByteOrder;)V+]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;,Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/ByteBufferAsCharBuffer;->duplicate()Ljava/nio/CharBuffer;+]Ljava/nio/ByteBufferAsCharBuffer;Ljava/nio/ByteBufferAsCharBuffer;
+HSPLjava/nio/ByteBufferAsCharBuffer;->get(I)C+]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;]Ljava/nio/ByteBufferAsCharBuffer;Ljava/nio/ByteBufferAsCharBuffer;
+HSPLjava/nio/ByteBufferAsCharBuffer;->get([CII)Ljava/nio/CharBuffer;+]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;]Ljava/nio/ByteBufferAsCharBuffer;Ljava/nio/ByteBufferAsCharBuffer;
+HSPLjava/nio/ByteBufferAsCharBuffer;->isDirect()Z
+HSPLjava/nio/ByteBufferAsCharBuffer;->ix(I)I
+HSPLjava/nio/ByteBufferAsCharBuffer;->subSequence(II)Ljava/lang/CharSequence;
+HSPLjava/nio/ByteBufferAsCharBuffer;->subSequence(II)Ljava/nio/CharBuffer;
+HSPLjava/nio/ByteBufferAsCharBuffer;->toString(II)Ljava/lang/String;+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;,Ljava/nio/ByteBufferAsCharBuffer;]Ljava/nio/ByteBufferAsCharBuffer;Ljava/nio/ByteBufferAsCharBuffer;
+HSPLjava/nio/ByteBufferAsFloatBuffer;-><init>(Ljava/nio/ByteBuffer;IIIIILjava/nio/ByteOrder;)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/ByteBufferAsFloatBuffer;->ix(I)I
+HSPLjava/nio/ByteBufferAsFloatBuffer;->put(IF)Ljava/nio/FloatBuffer;+]Ljava/nio/ByteBufferAsFloatBuffer;Ljava/nio/ByteBufferAsFloatBuffer;]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/ByteBufferAsFloatBuffer;->put([FII)Ljava/nio/FloatBuffer;+]Ljava/nio/ByteBufferAsFloatBuffer;Ljava/nio/ByteBufferAsFloatBuffer;]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;,Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/ByteBufferAsIntBuffer;-><init>(Ljava/nio/ByteBuffer;IIIIILjava/nio/ByteOrder;)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/ByteBufferAsIntBuffer;->get([III)Ljava/nio/IntBuffer;+]Ljava/nio/ByteBufferAsIntBuffer;Ljava/nio/ByteBufferAsIntBuffer;]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;,Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/ByteBufferAsIntBuffer;->ix(I)I
+HSPLjava/nio/ByteBufferAsLongBuffer;-><init>(Ljava/nio/ByteBuffer;IIIIILjava/nio/ByteOrder;)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/ByteBufferAsLongBuffer;->ix(I)I
+HSPLjava/nio/ByteBufferAsShortBuffer;-><init>(Ljava/nio/ByteBuffer;IIIIILjava/nio/ByteOrder;)V+]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;,Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/ByteBufferAsShortBuffer;->get([SII)Ljava/nio/ShortBuffer;+]Ljava/nio/ByteBufferAsShortBuffer;Ljava/nio/ByteBufferAsShortBuffer;]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/ByteBufferAsShortBuffer;->ix(I)I
+HSPLjava/nio/ByteBufferAsShortBuffer;->put([SII)Ljava/nio/ShortBuffer;+]Ljava/nio/ByteBufferAsShortBuffer;Ljava/nio/ByteBufferAsShortBuffer;]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;,Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/ByteOrder;->nativeOrder()Ljava/nio/ByteOrder;
+HSPLjava/nio/CharBuffer;-><init>(IIII)V
+HSPLjava/nio/CharBuffer;-><init>(IIII[CI)V
+HSPLjava/nio/CharBuffer;->allocate(I)Ljava/nio/CharBuffer;
+HSPLjava/nio/CharBuffer;->array()[C
+HSPLjava/nio/CharBuffer;->arrayOffset()I
+HSPLjava/nio/CharBuffer;->charAt(I)C+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;,Ljava/nio/ByteBufferAsCharBuffer;
+HSPLjava/nio/CharBuffer;->clear()Ljava/nio/Buffer;
+HSPLjava/nio/CharBuffer;->flip()Ljava/nio/Buffer;
+HSPLjava/nio/CharBuffer;->get([C)Ljava/nio/CharBuffer;+]Ljava/nio/CharBuffer;Ljava/nio/ByteBufferAsCharBuffer;
+HSPLjava/nio/CharBuffer;->get([CII)Ljava/nio/CharBuffer;+]Ljava/nio/CharBuffer;Ljava/nio/StringCharBuffer;
+HSPLjava/nio/CharBuffer;->hasArray()Z
+HSPLjava/nio/CharBuffer;->length()I+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;,Ljava/nio/ByteBufferAsCharBuffer;,Ljava/nio/StringCharBuffer;
+HSPLjava/nio/CharBuffer;->limit(I)Ljava/nio/Buffer;
+HSPLjava/nio/CharBuffer;->position(I)Ljava/nio/Buffer;
+HSPLjava/nio/CharBuffer;->toString()Ljava/lang/String;+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;,Ljava/nio/ByteBufferAsCharBuffer;
+HSPLjava/nio/CharBuffer;->wrap(Ljava/lang/CharSequence;)Ljava/nio/CharBuffer;+]Ljava/lang/CharSequence;Ljava/lang/String;,Ljava/lang/StringBuilder;
+HSPLjava/nio/CharBuffer;->wrap(Ljava/lang/CharSequence;II)Ljava/nio/CharBuffer;
+HSPLjava/nio/CharBuffer;->wrap([C)Ljava/nio/CharBuffer;
+HSPLjava/nio/CharBuffer;->wrap([CII)Ljava/nio/CharBuffer;
+HSPLjava/nio/DirectByteBuffer$MemoryRef;-><init>(I)V+]Ldalvik/system/VMRuntime;missing_types
+HSPLjava/nio/DirectByteBuffer$MemoryRef;-><init>(JLjava/lang/Object;)V
+HSPLjava/nio/DirectByteBuffer$MemoryRef;->free()V
+HSPLjava/nio/DirectByteBuffer;-><init>(IJLjava/io/FileDescriptor;Ljava/lang/Runnable;Z)V
+HSPLjava/nio/DirectByteBuffer;-><init>(ILjava/nio/DirectByteBuffer$MemoryRef;)V
+HSPLjava/nio/DirectByteBuffer;-><init>(JI)V
+HSPLjava/nio/DirectByteBuffer;-><init>(Ljava/nio/DirectByteBuffer$MemoryRef;IIIIIZ)V
+HSPLjava/nio/DirectByteBuffer;->address()J
+HSPLjava/nio/DirectByteBuffer;->asCharBuffer()Ljava/nio/CharBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->asFloatBuffer()Ljava/nio/FloatBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->asIntBuffer()Ljava/nio/IntBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->asReadOnlyBuffer()Ljava/nio/ByteBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->asShortBuffer()Ljava/nio/ShortBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->cleaner()Lsun/misc/Cleaner;
+HSPLjava/nio/DirectByteBuffer;->duplicate()Ljava/nio/ByteBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->get()B+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->get(I)B+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->get(J)B
+HSPLjava/nio/DirectByteBuffer;->get([BII)Ljava/nio/ByteBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->getChar()C+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->getChar(I)C+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->getCharUnchecked(I)C
+HSPLjava/nio/DirectByteBuffer;->getInt()I+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->getInt(I)I+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->getInt(J)I
+HSPLjava/nio/DirectByteBuffer;->getLong(I)J+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->getLong(J)J
+HSPLjava/nio/DirectByteBuffer;->getShort()S+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->getShort(I)S+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->getShort(J)S
+HSPLjava/nio/DirectByteBuffer;->getUnchecked(I[CII)V
+HSPLjava/nio/DirectByteBuffer;->getUnchecked(I[III)V
+HSPLjava/nio/DirectByteBuffer;->getUnchecked(I[SII)V
+HSPLjava/nio/DirectByteBuffer;->isDirect()Z
+HSPLjava/nio/DirectByteBuffer;->isReadOnly()Z
+HSPLjava/nio/DirectByteBuffer;->ix(I)J
+HSPLjava/nio/DirectByteBuffer;->put(B)Ljava/nio/ByteBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->put(IB)Ljava/nio/ByteBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->put(JB)Ljava/nio/ByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->put(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->put([BII)Ljava/nio/ByteBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->putDouble(JD)Ljava/nio/ByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->putFloat(JF)Ljava/nio/ByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->putFloatUnchecked(IF)V
+HSPLjava/nio/DirectByteBuffer;->putInt(I)Ljava/nio/ByteBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->putInt(II)Ljava/nio/ByteBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->putInt(JI)Ljava/nio/ByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->putLong(IJ)Ljava/nio/ByteBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->putLong(JJ)Ljava/nio/ByteBuffer;
+HSPLjava/nio/DirectByteBuffer;->putUnchecked(I[FII)V
+HSPLjava/nio/DirectByteBuffer;->setAccessible(Z)V
+HSPLjava/nio/DirectByteBuffer;->slice()Ljava/nio/ByteBuffer;+]Ljava/nio/DirectByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/FloatBuffer;-><init>(IIII)V
+HSPLjava/nio/FloatBuffer;-><init>(IIII[FI)V
+HSPLjava/nio/FloatBuffer;->limit(I)Ljava/nio/Buffer;
+HSPLjava/nio/FloatBuffer;->position(I)Ljava/nio/Buffer;
+HSPLjava/nio/FloatBuffer;->put([F)Ljava/nio/FloatBuffer;+]Ljava/nio/FloatBuffer;Ljava/nio/ByteBufferAsFloatBuffer;,Ljava/nio/HeapFloatBuffer;
+HSPLjava/nio/HeapByteBuffer;-><init>(II)V
+HSPLjava/nio/HeapByteBuffer;-><init>(IIZ)V
+HSPLjava/nio/HeapByteBuffer;-><init>([BII)V
+HSPLjava/nio/HeapByteBuffer;-><init>([BIIIIIZ)V
+HSPLjava/nio/HeapByteBuffer;-><init>([BIIZ)V
+HSPLjava/nio/HeapByteBuffer;->_get(I)B
+HSPLjava/nio/HeapByteBuffer;->_put(IB)V
+HSPLjava/nio/HeapByteBuffer;->asIntBuffer()Ljava/nio/IntBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->asLongBuffer()Ljava/nio/LongBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->asReadOnlyBuffer()Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->asShortBuffer()Ljava/nio/ShortBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->compact()Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->duplicate()Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->get()B+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->get(I)B+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->get([BII)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->getFloat()F+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->getFloat(I)F+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->getInt()I+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->getInt(I)I+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->getLong()J+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->getLong(I)J+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->getShort()S+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->getShort(I)S+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->getUnchecked(I[III)V+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->getUnchecked(I[SII)V
+HSPLjava/nio/HeapByteBuffer;->isDirect()Z
+HSPLjava/nio/HeapByteBuffer;->isReadOnly()Z
+HSPLjava/nio/HeapByteBuffer;->ix(I)I
+HSPLjava/nio/HeapByteBuffer;->put(B)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->put(IB)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->put([BII)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->putChar(C)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->putFloat(F)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->putInt(I)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->putInt(II)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->putLong(IJ)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->putLong(J)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->putShort(IS)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->putShort(S)Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapByteBuffer;->slice()Ljava/nio/ByteBuffer;+]Ljava/nio/HeapByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/HeapCharBuffer;-><init>(II)V
+HSPLjava/nio/HeapCharBuffer;-><init>(IIZ)V
+HSPLjava/nio/HeapCharBuffer;-><init>([CII)V
+HSPLjava/nio/HeapCharBuffer;-><init>([CIIIIIZ)V
+HSPLjava/nio/HeapCharBuffer;-><init>([CIIZ)V
+HSPLjava/nio/HeapCharBuffer;->get(I)C+]Ljava/nio/HeapCharBuffer;Ljava/nio/HeapCharBuffer;
+HSPLjava/nio/HeapCharBuffer;->ix(I)I
+HSPLjava/nio/HeapCharBuffer;->put(Ljava/nio/CharBuffer;)Ljava/nio/CharBuffer;+]Ljava/nio/HeapCharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/nio/CharBuffer;Ljava/nio/ByteBufferAsCharBuffer;
+HSPLjava/nio/HeapCharBuffer;->put([CII)Ljava/nio/CharBuffer;+]Ljava/nio/HeapCharBuffer;Ljava/nio/HeapCharBuffer;
+HSPLjava/nio/HeapCharBuffer;->slice()Ljava/nio/CharBuffer;+]Ljava/nio/HeapCharBuffer;Ljava/nio/HeapCharBuffer;
+HSPLjava/nio/HeapCharBuffer;->toString(II)Ljava/lang/String;
+HSPLjava/nio/IntBuffer;-><init>(IIII)V
+HSPLjava/nio/IntBuffer;-><init>(IIII[II)V
+HSPLjava/nio/IntBuffer;->allocate(I)Ljava/nio/IntBuffer;
+HSPLjava/nio/IntBuffer;->array()Ljava/lang/Object;+]Ljava/nio/IntBuffer;Ljava/nio/HeapIntBuffer;
+HSPLjava/nio/IntBuffer;->array()[I
+HSPLjava/nio/IntBuffer;->arrayOffset()I
+HSPLjava/nio/IntBuffer;->get([I)Ljava/nio/IntBuffer;+]Ljava/nio/IntBuffer;Ljava/nio/ByteBufferAsIntBuffer;
+HSPLjava/nio/IntBuffer;->hasArray()Z
+HSPLjava/nio/IntBuffer;->limit(I)Ljava/nio/Buffer;
+HSPLjava/nio/IntBuffer;->position(I)Ljava/nio/Buffer;
+HSPLjava/nio/LongBuffer;-><init>(IIII)V
+HSPLjava/nio/LongBuffer;-><init>(IIII[JI)V
+HSPLjava/nio/LongBuffer;->limit(I)Ljava/nio/Buffer;
+HSPLjava/nio/LongBuffer;->position(I)Ljava/nio/Buffer;
+HSPLjava/nio/MappedByteBuffer;-><init>(IIII)V
+HSPLjava/nio/MappedByteBuffer;-><init>(IIIILjava/io/FileDescriptor;)V
+HSPLjava/nio/MappedByteBuffer;-><init>(IIII[BI)V
+HSPLjava/nio/MappedByteBuffer;->checkMapped()V
+HSPLjava/nio/MappedByteBuffer;->load()Ljava/nio/MappedByteBuffer;+]Ljava/nio/MappedByteBuffer;Ljava/nio/DirectByteBuffer;]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/nio/MappedByteBuffer;->mappingAddress(J)J
+HSPLjava/nio/MappedByteBuffer;->mappingLength(J)J+]Ljava/nio/MappedByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLjava/nio/MappedByteBuffer;->mappingOffset()J
+HSPLjava/nio/NIOAccess;->getBaseArray(Ljava/nio/Buffer;)Ljava/lang/Object;+]Ljava/nio/Buffer;Ljava/nio/HeapIntBuffer;,Ljava/nio/HeapByteBuffer;,Ljava/nio/HeapShortBuffer;,Ljava/nio/HeapFloatBuffer;
+HSPLjava/nio/NIOAccess;->getBaseArrayOffset(Ljava/nio/Buffer;)I+]Ljava/nio/Buffer;Ljava/nio/HeapIntBuffer;,Ljava/nio/HeapByteBuffer;,Ljava/nio/HeapShortBuffer;,Ljava/nio/HeapFloatBuffer;
+HSPLjava/nio/NioUtils;->freeDirectBuffer(Ljava/nio/ByteBuffer;)V+]Ljava/nio/DirectByteBuffer$MemoryRef;Ljava/nio/DirectByteBuffer$MemoryRef;]Lsun/misc/Cleaner;Lsun/misc/Cleaner;
+HSPLjava/nio/ShortBuffer;-><init>(IIII)V
+HSPLjava/nio/ShortBuffer;-><init>(IIII[SI)V
+HSPLjava/nio/ShortBuffer;->get([S)Ljava/nio/ShortBuffer;+]Ljava/nio/ShortBuffer;Ljava/nio/ByteBufferAsShortBuffer;
+HSPLjava/nio/ShortBuffer;->limit(I)Ljava/nio/Buffer;
+HSPLjava/nio/ShortBuffer;->position(I)Ljava/nio/Buffer;
+HSPLjava/nio/StringCharBuffer;-><init>(Ljava/lang/CharSequence;II)V+]Ljava/lang/CharSequence;Ljava/lang/String;,Ljava/lang/StringBuilder;
+HSPLjava/nio/StringCharBuffer;->get()C+]Ljava/nio/StringCharBuffer;Ljava/nio/StringCharBuffer;]Ljava/lang/CharSequence;Ljava/lang/String;,Ljava/lang/StringBuilder;
+HSPLjava/nio/channels/Channels$1;-><init>(Ljava/nio/channels/WritableByteChannel;)V
+HSPLjava/nio/channels/Channels$1;->write([BII)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/nio/channels/Channels$WritableByteChannelImpl;-><init>(Ljava/io/OutputStream;)V
+HSPLjava/nio/channels/Channels$WritableByteChannelImpl;->write(Ljava/nio/ByteBuffer;)I+]Ljava/nio/channels/Channels$WritableByteChannelImpl;Ljava/nio/channels/Channels$WritableByteChannelImpl;]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;,Ljava/nio/HeapByteBuffer;]Ljava/io/OutputStream;Landroid/os/ParcelFileDescriptor$AutoCloseOutputStream;,Ljava/io/ByteArrayOutputStream;,Ljava/io/FileOutputStream;
+HSPLjava/nio/channels/Channels;->access$000(Ljava/nio/channels/WritableByteChannel;Ljava/nio/ByteBuffer;)V
+HSPLjava/nio/channels/Channels;->checkNotNull(Ljava/lang/Object;Ljava/lang/String;)V
+HSPLjava/nio/channels/Channels;->newChannel(Ljava/io/OutputStream;)Ljava/nio/channels/WritableByteChannel;
+HSPLjava/nio/channels/Channels;->newInputStream(Ljava/nio/channels/ReadableByteChannel;)Ljava/io/InputStream;
+HSPLjava/nio/channels/Channels;->newOutputStream(Ljava/nio/channels/WritableByteChannel;)Ljava/io/OutputStream;
+HSPLjava/nio/channels/Channels;->writeFully(Ljava/nio/channels/WritableByteChannel;Ljava/nio/ByteBuffer;)V+]Ljava/nio/channels/SelectableChannel;Lsun/nio/ch/SocketChannelImpl;
+HSPLjava/nio/channels/Channels;->writeFullyImpl(Ljava/nio/channels/WritableByteChannel;Ljava/nio/ByteBuffer;)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/nio/channels/WritableByteChannel;Lsun/nio/ch/FileChannelImpl;,Lsun/nio/ch/SocketChannelImpl;
+HSPLjava/nio/channels/FileChannel;-><init>()V
+HSPLjava/nio/channels/FileChannel;->lock()Ljava/nio/channels/FileLock;+]Ljava/nio/channels/FileChannel;Lsun/nio/ch/FileChannelImpl;
+HSPLjava/nio/channels/FileChannel;->open(Ljava/nio/file/Path;Ljava/util/Set;[Ljava/nio/file/attribute/FileAttribute;)Ljava/nio/channels/FileChannel;+]Ljava/nio/file/spi/FileSystemProvider;Lsun/nio/fs/LinuxFileSystemProvider;]Ljava/nio/file/FileSystem;Lsun/nio/fs/LinuxFileSystem;]Ljava/nio/file/Path;Lsun/nio/fs/UnixPath;
+HSPLjava/nio/channels/FileChannel;->open(Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/nio/channels/FileChannel;
+HSPLjava/nio/channels/FileChannel;->tryLock()Ljava/nio/channels/FileLock;
+HSPLjava/nio/channels/FileLock;-><init>(Ljava/nio/channels/FileChannel;JJZ)V
+HSPLjava/nio/channels/FileLock;->acquiredBy()Ljava/nio/channels/Channel;
+HSPLjava/nio/channels/FileLock;->position()J
+HSPLjava/nio/channels/FileLock;->size()J
+HSPLjava/nio/channels/SelectableChannel;-><init>()V
+HSPLjava/nio/channels/SelectableChannel;->register(Ljava/nio/channels/Selector;I)Ljava/nio/channels/SelectionKey;+]Ljava/nio/channels/SelectableChannel;Lsun/nio/ch/DatagramChannelImpl;
+HSPLjava/nio/channels/SelectionKey;-><init>()V
+HSPLjava/nio/channels/SelectionKey;->attach(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;
+HSPLjava/nio/channels/Selector;-><init>()V
+HSPLjava/nio/channels/Selector;->open()Ljava/nio/channels/Selector;+]Ljava/nio/channels/spi/SelectorProvider;Lsun/nio/ch/PollSelectorProvider;
+HSPLjava/nio/channels/SocketChannel;-><init>(Ljava/nio/channels/spi/SelectorProvider;)V
+HSPLjava/nio/channels/SocketChannel;->open()Ljava/nio/channels/SocketChannel;+]Ljava/nio/channels/spi/SelectorProvider;Lsun/nio/ch/PollSelectorProvider;
+HSPLjava/nio/channels/SocketChannel;->validOps()I
+HSPLjava/nio/channels/spi/AbstractInterruptibleChannel$1;-><init>(Ljava/nio/channels/spi/AbstractInterruptibleChannel;)V
+HSPLjava/nio/channels/spi/AbstractInterruptibleChannel;-><init>()V
+HSPLjava/nio/channels/spi/AbstractInterruptibleChannel;->begin()V+]Ljava/lang/Thread;missing_types]Lsun/nio/ch/Interruptible;Ljava/nio/channels/spi/AbstractInterruptibleChannel$1;
+HSPLjava/nio/channels/spi/AbstractInterruptibleChannel;->blockedOn(Lsun/nio/ch/Interruptible;)V+]Ljava/lang/Thread;megamorphic_types
+HSPLjava/nio/channels/spi/AbstractInterruptibleChannel;->close()V+]Ljava/nio/channels/spi/AbstractInterruptibleChannel;missing_types
+HSPLjava/nio/channels/spi/AbstractInterruptibleChannel;->end(Z)V
+HSPLjava/nio/channels/spi/AbstractInterruptibleChannel;->isOpen()Z
+HSPLjava/nio/channels/spi/AbstractSelectableChannel;-><init>(Ljava/nio/channels/spi/SelectorProvider;)V
+HSPLjava/nio/channels/spi/AbstractSelectableChannel;->addKey(Ljava/nio/channels/SelectionKey;)V
+HSPLjava/nio/channels/spi/AbstractSelectableChannel;->blockingLock()Ljava/lang/Object;
+HSPLjava/nio/channels/spi/AbstractSelectableChannel;->configureBlocking(Z)Ljava/nio/channels/SelectableChannel;+]Ljava/nio/channels/spi/AbstractSelectableChannel;Lsun/nio/ch/DatagramChannelImpl;,Lsun/nio/ch/SocketChannelImpl;
+HSPLjava/nio/channels/spi/AbstractSelectableChannel;->findKey(Ljava/nio/channels/Selector;)Ljava/nio/channels/SelectionKey;+]Ljava/nio/channels/SelectionKey;Lsun/nio/ch/SelectionKeyImpl;
+HSPLjava/nio/channels/spi/AbstractSelectableChannel;->implCloseChannel()V+]Ljava/nio/channels/spi/AbstractSelectableChannel;Lsun/nio/ch/DatagramChannelImpl;,Lsun/nio/ch/SocketChannelImpl;]Ljava/nio/channels/SelectionKey;Lsun/nio/ch/SelectionKeyImpl;
+HSPLjava/nio/channels/spi/AbstractSelectableChannel;->isBlocking()Z
+HSPLjava/nio/channels/spi/AbstractSelectableChannel;->isRegistered()Z
+HSPLjava/nio/channels/spi/AbstractSelectableChannel;->register(Ljava/nio/channels/Selector;ILjava/lang/Object;)Ljava/nio/channels/SelectionKey;+]Ljava/nio/channels/spi/AbstractSelector;Lsun/nio/ch/PollSelectorImpl;]Ljava/nio/channels/spi/AbstractSelectableChannel;Lsun/nio/ch/DatagramChannelImpl;,Lsun/nio/ch/SocketChannelImpl;,Lsun/nio/ch/ServerSocketChannelImpl;
+HSPLjava/nio/channels/spi/AbstractSelectableChannel;->removeKey(Ljava/nio/channels/SelectionKey;)V+]Ljava/nio/channels/spi/AbstractSelectionKey;Lsun/nio/ch/SelectionKeyImpl;
+HSPLjava/nio/channels/spi/AbstractSelectionKey;-><init>()V
+HSPLjava/nio/channels/spi/AbstractSelectionKey;->invalidate()V
+HSPLjava/nio/channels/spi/AbstractSelectionKey;->isValid()Z
+HSPLjava/nio/channels/spi/AbstractSelector$1;-><init>(Ljava/nio/channels/spi/AbstractSelector;)V
+HSPLjava/nio/channels/spi/AbstractSelector;-><init>(Ljava/nio/channels/spi/SelectorProvider;)V
+HSPLjava/nio/channels/spi/AbstractSelector;->begin()V+]Ljava/lang/Thread;missing_types
+HSPLjava/nio/channels/spi/AbstractSelector;->cancelledKeys()Ljava/util/Set;
+HSPLjava/nio/channels/spi/AbstractSelector;->close()V+]Ljava/util/concurrent/atomic/AtomicBoolean;Ljava/util/concurrent/atomic/AtomicBoolean;]Ljava/nio/channels/spi/AbstractSelector;Lsun/nio/ch/PollSelectorImpl;
+HSPLjava/nio/channels/spi/AbstractSelector;->deregister(Ljava/nio/channels/spi/AbstractSelectionKey;)V+]Ljava/nio/channels/spi/AbstractSelectableChannel;Lsun/nio/ch/SocketChannelImpl;,Lsun/nio/ch/DatagramChannelImpl;]Ljava/nio/channels/spi/AbstractSelectionKey;Lsun/nio/ch/SelectionKeyImpl;
+HSPLjava/nio/channels/spi/AbstractSelector;->end()V
+HSPLjava/nio/channels/spi/AbstractSelector;->isOpen()Z+]Ljava/util/concurrent/atomic/AtomicBoolean;Ljava/util/concurrent/atomic/AtomicBoolean;
+HSPLjava/nio/channels/spi/SelectorProvider$1;-><init>()V
+HSPLjava/nio/channels/spi/SelectorProvider$1;->run()Ljava/lang/Object;
+HSPLjava/nio/channels/spi/SelectorProvider$1;->run()Ljava/nio/channels/spi/SelectorProvider;
+HSPLjava/nio/channels/spi/SelectorProvider;-><init>()V
+HSPLjava/nio/channels/spi/SelectorProvider;->access$000()Z
+HSPLjava/nio/channels/spi/SelectorProvider;->access$100()Ljava/nio/channels/spi/SelectorProvider;
+HSPLjava/nio/channels/spi/SelectorProvider;->access$102(Ljava/nio/channels/spi/SelectorProvider;)Ljava/nio/channels/spi/SelectorProvider;
+HSPLjava/nio/channels/spi/SelectorProvider;->access$200()Z
+HSPLjava/nio/channels/spi/SelectorProvider;->loadProviderAsService()Z
+HSPLjava/nio/channels/spi/SelectorProvider;->loadProviderFromProperty()Z
+HSPLjava/nio/channels/spi/SelectorProvider;->provider()Ljava/nio/channels/spi/SelectorProvider;
+HSPLjava/nio/charset/Charset;-><init>(Ljava/lang/String;[Ljava/lang/String;)V
+HSPLjava/nio/charset/Charset;->aliases()Ljava/util/Set;+]Ljava/util/HashSet;Ljava/util/HashSet;
+HSPLjava/nio/charset/Charset;->atBugLevel(Ljava/lang/String;)Z
+HSPLjava/nio/charset/Charset;->cache(Ljava/lang/String;Ljava/nio/charset/Charset;)V
+HSPLjava/nio/charset/Charset;->checkName(Ljava/lang/String;)V
+HSPLjava/nio/charset/Charset;->decode(Ljava/nio/ByteBuffer;)Ljava/nio/CharBuffer;+]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLjava/nio/charset/Charset;->defaultCharset()Ljava/nio/charset/Charset;
+HSPLjava/nio/charset/Charset;->encode(Ljava/lang/String;)Ljava/nio/ByteBuffer;+]Ljava/nio/charset/Charset;missing_types
+HSPLjava/nio/charset/Charset;->encode(Ljava/nio/CharBuffer;)Ljava/nio/ByteBuffer;+]Ljava/nio/charset/CharsetEncoder;missing_types
+HSPLjava/nio/charset/Charset;->equals(Ljava/lang/Object;)Z+]Ljava/nio/charset/Charset;missing_types
+HSPLjava/nio/charset/Charset;->forName(Ljava/lang/String;)Ljava/nio/charset/Charset;
+HSPLjava/nio/charset/Charset;->forNameUEE(Ljava/lang/String;)Ljava/nio/charset/Charset;
+HSPLjava/nio/charset/Charset;->isSupported(Ljava/lang/String;)Z
+HSPLjava/nio/charset/Charset;->lookup(Ljava/lang/String;)Ljava/nio/charset/Charset;+]Ljava/util/Map$Entry;Ljava/util/AbstractMap$SimpleImmutableEntry;
+HSPLjava/nio/charset/Charset;->lookup2(Ljava/lang/String;)Ljava/nio/charset/Charset;+]Ljava/util/HashMap;Ljava/util/HashMap;
+HSPLjava/nio/charset/Charset;->name()Ljava/lang/String;
+HSPLjava/nio/charset/CharsetDecoder;-><init>(Ljava/nio/charset/Charset;FF)V
+HSPLjava/nio/charset/CharsetDecoder;-><init>(Ljava/nio/charset/Charset;FFLjava/lang/String;)V
+HSPLjava/nio/charset/CharsetDecoder;->averageCharsPerByte()F
+HSPLjava/nio/charset/CharsetDecoder;->charset()Ljava/nio/charset/Charset;
+HSPLjava/nio/charset/CharsetDecoder;->decode(Ljava/nio/ByteBuffer;)Ljava/nio/CharBuffer;+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLjava/nio/charset/CharsetDecoder;->decode(Ljava/nio/ByteBuffer;Ljava/nio/CharBuffer;Z)Ljava/nio/charset/CoderResult;+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;]Ljava/nio/charset/CharsetDecoder;Lcom/android/icu/charset/CharsetDecoderICU;
+HSPLjava/nio/charset/CharsetDecoder;->flush(Ljava/nio/CharBuffer;)Ljava/nio/charset/CoderResult;+]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLjava/nio/charset/CharsetDecoder;->malformedInputAction()Ljava/nio/charset/CodingErrorAction;
+HSPLjava/nio/charset/CharsetDecoder;->maxCharsPerByte()F
+HSPLjava/nio/charset/CharsetDecoder;->onMalformedInput(Ljava/nio/charset/CodingErrorAction;)Ljava/nio/charset/CharsetDecoder;+]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLjava/nio/charset/CharsetDecoder;->onUnmappableCharacter(Ljava/nio/charset/CodingErrorAction;)Ljava/nio/charset/CharsetDecoder;+]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLjava/nio/charset/CharsetDecoder;->replaceWith(Ljava/lang/String;)Ljava/nio/charset/CharsetDecoder;+]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLjava/nio/charset/CharsetDecoder;->replacement()Ljava/lang/String;
+HSPLjava/nio/charset/CharsetDecoder;->reset()Ljava/nio/charset/CharsetDecoder;+]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLjava/nio/charset/CharsetDecoder;->unmappableCharacterAction()Ljava/nio/charset/CodingErrorAction;
+HSPLjava/nio/charset/CharsetEncoder;-><init>(Ljava/nio/charset/Charset;FF[BZ)V
+HSPLjava/nio/charset/CharsetEncoder;->averageBytesPerChar()F
+HSPLjava/nio/charset/CharsetEncoder;->canEncode(Ljava/lang/CharSequence;)Z
+HSPLjava/nio/charset/CharsetEncoder;->canEncode(Ljava/nio/CharBuffer;)Z+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;,Ljava/nio/StringCharBuffer;]Ljava/nio/charset/CharsetEncoder;Lcom/android/icu/charset/CharsetEncoderICU;
+HSPLjava/nio/charset/CharsetEncoder;->charset()Ljava/nio/charset/Charset;
+HSPLjava/nio/charset/CharsetEncoder;->encode(Ljava/nio/CharBuffer;)Ljava/nio/ByteBuffer;+]Ljava/nio/CharBuffer;Ljava/nio/StringCharBuffer;,Ljava/nio/HeapCharBuffer;]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/nio/charset/CharsetEncoder;missing_types]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;
+HSPLjava/nio/charset/CharsetEncoder;->encode(Ljava/nio/CharBuffer;Ljava/nio/ByteBuffer;Z)Ljava/nio/charset/CoderResult;+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;,Ljava/nio/StringCharBuffer;,Ljava/nio/ByteBufferAsCharBuffer;]Ljava/nio/charset/CharsetEncoder;missing_types]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;
+HSPLjava/nio/charset/CharsetEncoder;->flush(Ljava/nio/ByteBuffer;)Ljava/nio/charset/CoderResult;+]Ljava/nio/charset/CharsetEncoder;missing_types]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;
+HSPLjava/nio/charset/CharsetEncoder;->malformedInputAction()Ljava/nio/charset/CodingErrorAction;
+HSPLjava/nio/charset/CharsetEncoder;->maxBytesPerChar()F
+HSPLjava/nio/charset/CharsetEncoder;->onMalformedInput(Ljava/nio/charset/CodingErrorAction;)Ljava/nio/charset/CharsetEncoder;+]Ljava/nio/charset/CharsetEncoder;missing_types
+HSPLjava/nio/charset/CharsetEncoder;->onUnmappableCharacter(Ljava/nio/charset/CodingErrorAction;)Ljava/nio/charset/CharsetEncoder;+]Ljava/nio/charset/CharsetEncoder;missing_types
+HSPLjava/nio/charset/CharsetEncoder;->replacement()[B
+HSPLjava/nio/charset/CharsetEncoder;->reset()Ljava/nio/charset/CharsetEncoder;+]Ljava/nio/charset/CharsetEncoder;missing_types
+HSPLjava/nio/charset/CharsetEncoder;->unmappableCharacterAction()Ljava/nio/charset/CodingErrorAction;
+HSPLjava/nio/charset/CoderResult;->isError()Z
+HSPLjava/nio/charset/CoderResult;->isOverflow()Z
+HSPLjava/nio/charset/CoderResult;->isUnderflow()Z
+HSPLjava/nio/file/AccessMode;->values()[Ljava/nio/file/AccessMode;
+HSPLjava/nio/file/FileAlreadyExistsException;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/nio/file/FileSystemException;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/nio/file/FileSystems;->getDefault()Ljava/nio/file/FileSystem;
+HSPLjava/nio/file/Files$AcceptAllFilter;->accept(Ljava/lang/Object;)Z+]Ljava/nio/file/Files$AcceptAllFilter;Ljava/nio/file/Files$AcceptAllFilter;
+HSPLjava/nio/file/Files$AcceptAllFilter;->accept(Ljava/nio/file/Path;)Z
+HSPLjava/nio/file/Files;->exists(Ljava/nio/file/Path;[Ljava/nio/file/LinkOption;)Z+]Ljava/nio/file/spi/FileSystemProvider;Lsun/nio/fs/LinuxFileSystemProvider;
+HSPLjava/nio/file/Files;->followLinks([Ljava/nio/file/LinkOption;)Z
+HSPLjava/nio/file/Files;->isAccessible(Ljava/nio/file/Path;[Ljava/nio/file/AccessMode;)Z
+HSPLjava/nio/file/Files;->isRegularFile(Ljava/nio/file/Path;[Ljava/nio/file/LinkOption;)Z
+HSPLjava/nio/file/Files;->isWritable(Ljava/nio/file/Path;)Z
+HSPLjava/nio/file/Files;->newBufferedReader(Ljava/nio/file/Path;Ljava/nio/charset/Charset;)Ljava/io/BufferedReader;+]Ljava/nio/charset/Charset;missing_types
+HSPLjava/nio/file/Files;->newByteChannel(Ljava/nio/file/Path;Ljava/util/Set;[Ljava/nio/file/attribute/FileAttribute;)Ljava/nio/channels/SeekableByteChannel;+]Ljava/nio/file/spi/FileSystemProvider;Lsun/nio/fs/LinuxFileSystemProvider;
+HSPLjava/nio/file/Files;->newByteChannel(Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/nio/channels/SeekableByteChannel;
+HSPLjava/nio/file/Files;->newDirectoryStream(Ljava/nio/file/Path;)Ljava/nio/file/DirectoryStream;+]Ljava/nio/file/spi/FileSystemProvider;Lsun/nio/fs/LinuxFileSystemProvider;
+HSPLjava/nio/file/Files;->newInputStream(Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/io/InputStream;+]Ljava/nio/file/spi/FileSystemProvider;Lsun/nio/fs/LinuxFileSystemProvider;
+HSPLjava/nio/file/Files;->provider(Ljava/nio/file/Path;)Ljava/nio/file/spi/FileSystemProvider;+]Ljava/nio/file/FileSystem;Lsun/nio/fs/LinuxFileSystem;]Ljava/nio/file/Path;Lsun/nio/fs/UnixPath;
+HSPLjava/nio/file/Files;->read(Ljava/io/InputStream;I)[B+]Ljava/io/InputStream;Lsun/nio/ch/ChannelInputStream;
+HSPLjava/nio/file/Files;->readAllBytes(Ljava/nio/file/Path;)[B+]Ljava/io/InputStream;Lsun/nio/ch/ChannelInputStream;]Ljava/nio/channels/SeekableByteChannel;Lsun/nio/ch/FileChannelImpl;
+HSPLjava/nio/file/Files;->readAttributes(Ljava/nio/file/Path;Ljava/lang/Class;[Ljava/nio/file/LinkOption;)Ljava/nio/file/attribute/BasicFileAttributes;+]Ljava/nio/file/spi/FileSystemProvider;Lsun/nio/fs/LinuxFileSystemProvider;
+HSPLjava/nio/file/NoSuchFileException;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/nio/file/Paths;->get(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path;+]Ljava/nio/file/FileSystem;Lsun/nio/fs/LinuxFileSystem;
+HSPLjava/nio/file/StandardOpenOption;->values()[Ljava/nio/file/StandardOpenOption;
+HSPLjava/nio/file/attribute/FileTime;-><init>(JLjava/util/concurrent/TimeUnit;Ljava/time/Instant;)V
+HSPLjava/nio/file/attribute/FileTime;->append(Ljava/lang/StringBuilder;II)Ljava/lang/StringBuilder;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/nio/file/attribute/FileTime;->from(JLjava/util/concurrent/TimeUnit;)Ljava/nio/file/attribute/FileTime;
+HSPLjava/nio/file/attribute/FileTime;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$4;
+HSPLjava/nio/file/spi/FileSystemProvider;->newInputStream(Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/io/InputStream;
+HSPLjava/security/AccessControlContext;-><init>([Ljava/security/ProtectionDomain;)V
+HSPLjava/security/AccessController;->doPrivileged(Ljava/security/PrivilegedAction;)Ljava/lang/Object;+]Ljava/security/PrivilegedAction;megamorphic_types
+HSPLjava/security/AccessController;->doPrivileged(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;+]Ljava/security/PrivilegedExceptionAction;missing_types
+HSPLjava/security/AccessController;->getContext()Ljava/security/AccessControlContext;
+HSPLjava/security/AlgorithmParameters;->getInstance(Ljava/lang/String;)Ljava/security/AlgorithmParameters;
+HSPLjava/security/AlgorithmParametersSpi;-><init>()V
+HSPLjava/security/CodeSigner;-><init>(Ljava/security/cert/CertPath;Ljava/security/Timestamp;)V
+HSPLjava/security/CodeSigner;->getSignerCertPath()Ljava/security/cert/CertPath;
+HSPLjava/security/DigestInputStream;->read([BII)I+]Ljava/io/InputStream;missing_types]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;
+HSPLjava/security/GeneralSecurityException;-><init>(Ljava/lang/String;)V
+HSPLjava/security/KeyFactory;-><init>(Ljava/lang/String;)V+]Ljava/util/List;Lsun/security/jca/ProviderList$ServiceList;
+HSPLjava/security/KeyFactory;->generatePrivate(Ljava/security/spec/KeySpec;)Ljava/security/PrivateKey;+]Ljava/security/KeyFactorySpi;missing_types
+HSPLjava/security/KeyFactory;->generatePublic(Ljava/security/spec/KeySpec;)Ljava/security/PublicKey;+]Ljava/security/KeyFactorySpi;missing_types
+HSPLjava/security/KeyFactory;->getInstance(Ljava/lang/String;)Ljava/security/KeyFactory;
+HSPLjava/security/KeyFactory;->nextSpi(Ljava/security/KeyFactorySpi;)Ljava/security/KeyFactorySpi;+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/util/Iterator;Lsun/security/jca/ProviderList$ServiceList$1;
+HSPLjava/security/KeyFactorySpi;-><init>()V
+HSPLjava/security/KeyPair;-><init>(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V
+HSPLjava/security/KeyPair;->getPrivate()Ljava/security/PrivateKey;
+HSPLjava/security/KeyPair;->getPublic()Ljava/security/PublicKey;
+HSPLjava/security/KeyPairGenerator;-><init>(Ljava/lang/String;)V
+HSPLjava/security/KeyPairGenerator;->getInstance(Lsun/security/jca/GetInstance$Instance;Ljava/lang/String;)Ljava/security/KeyPairGenerator;
+HSPLjava/security/KeyPairGeneratorSpi;-><init>()V
+HSPLjava/security/KeyStore$1;-><init>()V
+HSPLjava/security/KeyStore$1;->run()Ljava/lang/Object;
+HSPLjava/security/KeyStore$1;->run()Ljava/lang/String;
+HSPLjava/security/KeyStore$SecretKeyEntry;-><init>(Ljavax/crypto/SecretKey;)V
+HSPLjava/security/KeyStore$SecretKeyEntry;->getSecretKey()Ljavax/crypto/SecretKey;
+HSPLjava/security/KeyStore;-><init>(Ljava/security/KeyStoreSpi;Ljava/security/Provider;Ljava/lang/String;)V
+HSPLjava/security/KeyStore;->aliases()Ljava/util/Enumeration;+]Ljava/security/KeyStoreSpi;Lcom/android/org/conscrypt/TrustedCertificateKeyStoreSpi;
+HSPLjava/security/KeyStore;->containsAlias(Ljava/lang/String;)Z+]Ljava/security/KeyStoreSpi;Landroid/security/keystore2/AndroidKeyStoreSpi;
+HSPLjava/security/KeyStore;->getCertificate(Ljava/lang/String;)Ljava/security/cert/Certificate;+]Ljava/security/KeyStoreSpi;missing_types
+HSPLjava/security/KeyStore;->getDefaultType()Ljava/lang/String;
+HSPLjava/security/KeyStore;->getEntry(Ljava/lang/String;Ljava/security/KeyStore$ProtectionParameter;)Ljava/security/KeyStore$Entry;
+HSPLjava/security/KeyStore;->getInstance(Ljava/lang/String;)Ljava/security/KeyStore;
+HSPLjava/security/KeyStore;->getKey(Ljava/lang/String;[C)Ljava/security/Key;+]Ljava/security/KeyStoreSpi;Landroid/security/keystore2/AndroidKeyStoreSpi;
+HSPLjava/security/KeyStore;->getType()Ljava/lang/String;
+HSPLjava/security/KeyStore;->load(Ljava/io/InputStream;[C)V+]Ljava/security/KeyStoreSpi;Lcom/android/org/conscrypt/TrustedCertificateKeyStoreSpi;
+HSPLjava/security/KeyStore;->load(Ljava/security/KeyStore$LoadStoreParameter;)V+]Ljava/security/KeyStoreSpi;missing_types
+HSPLjava/security/KeyStore;->setCertificateEntry(Ljava/lang/String;Ljava/security/cert/Certificate;)V+]Ljava/security/KeyStoreSpi;Landroid/security/keystore2/AndroidKeyStoreSpi;,Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$Std;
+HSPLjava/security/KeyStore;->size()I
+HSPLjava/security/KeyStoreSpi;-><init>()V
+HSPLjava/security/KeyStoreSpi;->engineGetEntry(Ljava/lang/String;Ljava/security/KeyStore$ProtectionParameter;)Ljava/security/KeyStore$Entry;+]Ljava/security/KeyStoreSpi;Landroid/security/keystore2/AndroidKeyStoreSpi;
+HSPLjava/security/KeyStoreSpi;->engineLoad(Ljava/security/KeyStore$LoadStoreParameter;)V
+HSPLjava/security/MessageDigest$Delegate;-><init>(Ljava/security/MessageDigestSpi;Ljava/lang/String;)V
+HSPLjava/security/MessageDigest$Delegate;->clone()Ljava/lang/Object;+]Ljava/security/MessageDigestSpi;missing_types
+HSPLjava/security/MessageDigest$Delegate;->engineDigest()[B+]Ljava/security/MessageDigestSpi;megamorphic_types
+HSPLjava/security/MessageDigest$Delegate;->engineDigest([BII)I+]Ljava/security/MessageDigestSpi;missing_types
+HSPLjava/security/MessageDigest$Delegate;->engineGetDigestLength()I+]Ljava/security/MessageDigestSpi;missing_types
+HSPLjava/security/MessageDigest$Delegate;->engineReset()V+]Ljava/security/MessageDigestSpi;missing_types
+HSPLjava/security/MessageDigest$Delegate;->engineUpdate(B)V+]Ljava/security/MessageDigestSpi;missing_types
+HSPLjava/security/MessageDigest$Delegate;->engineUpdate(Ljava/nio/ByteBuffer;)V+]Ljava/security/MessageDigestSpi;missing_types
+HSPLjava/security/MessageDigest$Delegate;->engineUpdate([BII)V+]Ljava/security/MessageDigestSpi;megamorphic_types
+HSPLjava/security/MessageDigest;-><init>(Ljava/lang/String;)V
+HSPLjava/security/MessageDigest;->access$000(Ljava/security/MessageDigest;)Ljava/lang/String;
+HSPLjava/security/MessageDigest;->access$100(Ljava/security/MessageDigest;)Ljava/security/Provider;
+HSPLjava/security/MessageDigest;->access$102(Ljava/security/MessageDigest;Ljava/security/Provider;)Ljava/security/Provider;
+HSPLjava/security/MessageDigest;->access$200(Ljava/security/MessageDigest;)I
+HSPLjava/security/MessageDigest;->access$202(Ljava/security/MessageDigest;I)I
+HSPLjava/security/MessageDigest;->digest()[B+]Ljava/security/MessageDigest;missing_types
+HSPLjava/security/MessageDigest;->digest([B)[B+]Ljava/security/MessageDigest;missing_types
+HSPLjava/security/MessageDigest;->digest([BII)I+]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;
+HSPLjava/security/MessageDigest;->getDigestLength()I+]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;
+HSPLjava/security/MessageDigest;->getInstance(Ljava/lang/String;)Ljava/security/MessageDigest;
+HSPLjava/security/MessageDigest;->getInstance(Ljava/lang/String;Ljava/lang/String;)Ljava/security/MessageDigest;
+HSPLjava/security/MessageDigest;->getInstance(Ljava/lang/String;Ljava/security/Provider;)Ljava/security/MessageDigest;
+HSPLjava/security/MessageDigest;->isEqual([B[B)Z
+HSPLjava/security/MessageDigest;->reset()V+]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;
+HSPLjava/security/MessageDigest;->update(B)V+]Ljava/security/MessageDigest;missing_types
+HSPLjava/security/MessageDigest;->update(Ljava/nio/ByteBuffer;)V+]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;
+HSPLjava/security/MessageDigest;->update([B)V+]Ljava/security/MessageDigest;missing_types
+HSPLjava/security/MessageDigest;->update([BII)V+]Ljava/security/MessageDigest;missing_types
+HSPLjava/security/MessageDigestSpi;-><init>()V
+HSPLjava/security/MessageDigestSpi;->engineDigest([BII)I+]Ljava/security/MessageDigestSpi;missing_types
+HSPLjava/security/MessageDigestSpi;->engineUpdate(Ljava/nio/ByteBuffer;)V+]Ljava/security/MessageDigestSpi;missing_types]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLjava/security/NoSuchAlgorithmException;-><init>(Ljava/lang/String;)V
+HSPLjava/security/Provider$EngineDescription;->getConstructorParameterClass()Ljava/lang/Class;
+HSPLjava/security/Provider$Service;-><init>(Ljava/security/Provider;)V
+HSPLjava/security/Provider$Service;-><init>(Ljava/security/Provider;Ljava/security/Provider$1;)V
+HSPLjava/security/Provider$Service;->access$000(Ljava/security/Provider$Service;)Z
+HSPLjava/security/Provider$Service;->access$302(Ljava/security/Provider$Service;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/security/Provider$Service;->access$402(Ljava/security/Provider$Service;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/security/Provider$Service;->access$500(Ljava/security/Provider$Service;Ljava/lang/String;)V
+HSPLjava/security/Provider$Service;->access$602(Ljava/security/Provider$Service;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/security/Provider$Service;->addAlias(Ljava/lang/String;)V+]Ljava/util/List;Ljava/util/Collections$EmptyList;,Ljava/util/ArrayList;
+HSPLjava/security/Provider$Service;->addAttribute(Ljava/lang/String;Ljava/lang/String;)V+]Ljava/util/Map;Ljava/util/HashMap;,Ljava/util/Collections$EmptyMap;
+HSPLjava/security/Provider$Service;->getAlgorithm()Ljava/lang/String;
+HSPLjava/security/Provider$Service;->getAttribute(Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Map;Ljava/util/HashMap;,Ljava/util/Collections$EmptyMap;
+HSPLjava/security/Provider$Service;->getClassName()Ljava/lang/String;
+HSPLjava/security/Provider$Service;->getImplClass()Ljava/lang/Class;+]Ljava/lang/ref/Reference;Ljava/lang/ref/WeakReference;]Ljava/lang/Object;megamorphic_types]Ljava/lang/ClassLoader;missing_types]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/security/Provider$Service;->getKeyClass(Ljava/lang/String;)Ljava/lang/Class;
+HSPLjava/security/Provider$Service;->getProvider()Ljava/security/Provider;
+HSPLjava/security/Provider$Service;->getType()Ljava/lang/String;
+HSPLjava/security/Provider$Service;->hasKeyAttributes()Z+]Ljava/lang/Boolean;Ljava/lang/Boolean;]Ljava/lang/String;Ljava/lang/String;]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/util/List;Ljava/util/ArrayList;
+HSPLjava/security/Provider$Service;->isValid()Z
+HSPLjava/security/Provider$Service;->newInstance(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/security/Provider;megamorphic_types]Ljava/util/Map;Ljava/util/HashMap;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/reflect/Constructor;Ljava/lang/reflect/Constructor;]Ljava/security/Provider$EngineDescription;Ljava/security/Provider$EngineDescription;]Ljava/lang/Object;Ljava/security/cert/CollectionCertStoreParameters;
+HSPLjava/security/Provider$Service;->supportsKeyClass(Ljava/security/Key;)Z+]Ljava/lang/Object;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/security/Provider$Service;->supportsKeyFormat(Ljava/security/Key;)Z+]Ljava/security/Key;missing_types
+HSPLjava/security/Provider$Service;->supportsParameter(Ljava/lang/Object;)Z+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/security/Provider$ServiceKey;-><init>(Ljava/lang/String;Ljava/lang/String;Z)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/security/Provider$ServiceKey;-><init>(Ljava/lang/String;Ljava/lang/String;ZLjava/security/Provider$1;)V
+HSPLjava/security/Provider$ServiceKey;->equals(Ljava/lang/Object;)Z
+HSPLjava/security/Provider$ServiceKey;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/security/Provider$ServiceKey;->matches(Ljava/lang/String;Ljava/lang/String;)Z
+HSPLjava/security/Provider$UString;-><init>(Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/security/Provider$UString;->equals(Ljava/lang/Object;)Z
+HSPLjava/security/Provider$UString;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/security/Provider;-><init>(Ljava/lang/String;DLjava/lang/String;)V
+HSPLjava/security/Provider;->access$1000()Ljava/util/Map;
+HSPLjava/security/Provider;->check(Ljava/lang/String;)V
+HSPLjava/security/Provider;->checkInitialized()V
+HSPLjava/security/Provider;->checkLegacy(Ljava/lang/Object;)Z+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/security/Provider;->ensureLegacyParsed()V+]Ljava/util/Map$Entry;Ljava/util/LinkedHashMap$LinkedHashMapEntry;]Ljava/util/Map;Ljava/util/LinkedHashMap;]Ljava/util/Iterator;Ljava/util/LinkedHashMap$LinkedEntryIterator;]Ljava/util/Set;Ljava/util/LinkedHashMap$LinkedEntrySet;
+HSPLjava/security/Provider;->getEngineName(Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/security/Provider;->getName()Ljava/lang/String;
+HSPLjava/security/Provider;->getService(Ljava/lang/String;Ljava/lang/String;)Ljava/security/Provider$Service;+]Ljava/security/Provider$ServiceKey;Ljava/security/Provider$ServiceKey;]Ljava/util/Map;Ljava/util/LinkedHashMap;
+HSPLjava/security/Provider;->getServices()Ljava/util/Set;
+HSPLjava/security/Provider;->getTypeAndAlgorithm(Ljava/lang/String;)[Ljava/lang/String;
+HSPLjava/security/Provider;->implPut(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Map;Ljava/util/LinkedHashMap;
+HSPLjava/security/Provider;->parseLegacyPut(Ljava/lang/String;Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/util/Map;Ljava/util/LinkedHashMap;
+HSPLjava/security/Provider;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/security/Provider;->putId()V
+HSPLjava/security/Provider;->removeInvalidServices(Ljava/util/Map;)V+]Ljava/util/Map$Entry;Ljava/util/LinkedHashMap$LinkedHashMapEntry;]Ljava/util/Map;Ljava/util/LinkedHashMap;]Ljava/util/Iterator;Ljava/util/LinkedHashMap$LinkedEntryIterator;]Ljava/util/Set;Ljava/util/LinkedHashMap$LinkedEntrySet;
+HSPLjava/security/Provider;->warmUpServiceProvision()V
+HSPLjava/security/SecureRandom;-><init>()V
+HSPLjava/security/SecureRandom;-><init>(Ljava/security/SecureRandomSpi;Ljava/security/Provider;Ljava/lang/String;)V
+HSPLjava/security/SecureRandom;->getDefaultPRNG(Z[B)V+]Ljava/lang/Object;Ljava/security/SecureRandom;]Ljava/security/SecureRandom;Ljava/security/SecureRandom;
+HSPLjava/security/SecureRandom;->getInstance(Ljava/lang/String;)Ljava/security/SecureRandom;
+HSPLjava/security/SecureRandom;->getPrngAlgorithm()Ljava/lang/String;+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/util/List;Lsun/security/jca/ProviderList$3;]Ljava/security/Provider;missing_types]Ljava/util/Iterator;Ljava/util/AbstractList$Itr;,Ljava/util/Collections$UnmodifiableCollection$1;]Ljava/util/Set;Ljava/util/Collections$UnmodifiableSet;
+HSPLjava/security/SecureRandom;->getProvider()Ljava/security/Provider;
+HSPLjava/security/SecureRandom;->getSecureRandomSpi()Ljava/security/SecureRandomSpi;
+HSPLjava/security/SecureRandom;->next(I)I+]Ljava/security/SecureRandom;Ljava/security/SecureRandom;
+HSPLjava/security/SecureRandom;->nextBytes([B)V+]Ljava/security/SecureRandomSpi;missing_types
+HSPLjava/security/SecureRandom;->setSeed(J)V
+HSPLjava/security/SecureRandomSpi;-><init>()V
+HSPLjava/security/Security;->addProvider(Ljava/security/Provider;)I
+HSPLjava/security/Security;->getImpl(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/Object;+]Lsun/security/jca/GetInstance$Instance;Lsun/security/jca/GetInstance$Instance;
+HSPLjava/security/Security;->getImpl(Ljava/lang/String;Ljava/lang/String;Ljava/security/Provider;)[Ljava/lang/Object;
+HSPLjava/security/Security;->getProperty(Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Properties;Ljava/util/Properties;]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/security/Security;->getProvider(Ljava/lang/String;)Ljava/security/Provider;+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;
+HSPLjava/security/Security;->getProviders()[Ljava/security/Provider;+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;
+HSPLjava/security/Security;->getSpiClass(Ljava/lang/String;)Ljava/lang/Class;+]Ljava/util/Map;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/security/Security;->getVersion()I
+HSPLjava/security/Security;->increaseVersion()V
+HSPLjava/security/Security;->insertProviderAt(Ljava/security/Provider;I)I
+HSPLjava/security/Security;->invalidateSMCache(Ljava/lang/String;)V
+HSPLjava/security/Security;->setProperty(Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/security/Signature$Delegate;-><init>(Ljava/lang/String;)V
+HSPLjava/security/Signature$Delegate;->chooseFirstProvider()V
+HSPLjava/security/Signature$Delegate;->chooseProvider(ILjava/security/Key;Ljava/security/SecureRandom;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/util/List;Lsun/security/jca/ProviderList$ServiceList;]Ljava/util/Iterator;Lsun/security/jca/ProviderList$ServiceList$1;
+HSPLjava/security/Signature$Delegate;->engineInitSign(Ljava/security/PrivateKey;)V
+HSPLjava/security/Signature$Delegate;->engineInitVerify(Ljava/security/PublicKey;)V
+HSPLjava/security/Signature$Delegate;->engineSign()[B
+HSPLjava/security/Signature$Delegate;->engineUpdate(Ljava/nio/ByteBuffer;)V+]Ljava/security/SignatureSpi;Lcom/android/org/conscrypt/OpenSSLSignature$SHA256RSA;,Lcom/android/org/conscrypt/OpenSSLSignature$SHA512RSA;,Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner$dsa256;]Ljava/security/Signature$Delegate;Ljava/security/Signature$Delegate;
+HSPLjava/security/Signature$Delegate;->engineUpdate([BII)V+]Ljava/security/Signature$Delegate;Ljava/security/Signature$Delegate;]Ljava/security/SignatureSpi;missing_types
+HSPLjava/security/Signature$Delegate;->engineVerify([B)Z+]Ljava/security/Signature$Delegate;Ljava/security/Signature$Delegate;]Ljava/security/SignatureSpi;missing_types
+HSPLjava/security/Signature$Delegate;->init(Ljava/security/SignatureSpi;ILjava/security/Key;Ljava/security/SecureRandom;)V+]Ljava/security/SignatureSpi;megamorphic_types
+HSPLjava/security/Signature$Delegate;->newInstance(Ljava/security/Provider$Service;)Ljava/security/SignatureSpi;+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;
+HSPLjava/security/Signature;-><init>(Ljava/lang/String;)V
+HSPLjava/security/Signature;->access$000(Ljava/security/Signature;)Ljava/lang/String;
+HSPLjava/security/Signature;->access$200(Ljava/security/Provider$Service;)Z
+HSPLjava/security/Signature;->getInstance(Ljava/lang/String;)Ljava/security/Signature;+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/List;Lsun/security/jca/ProviderList$ServiceList;]Ljava/util/Iterator;Lsun/security/jca/ProviderList$ServiceList$1;
+HSPLjava/security/Signature;->initSign(Ljava/security/PrivateKey;)V
+HSPLjava/security/Signature;->initVerify(Ljava/security/PublicKey;)V+]Ljava/security/Signature;Ljava/security/Signature$Delegate;
+HSPLjava/security/Signature;->isSpi(Ljava/security/Provider$Service;)Z+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/lang/Boolean;Ljava/lang/Boolean;]Ljava/util/Map;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/security/Signature;->sign()[B
+HSPLjava/security/Signature;->update(Ljava/nio/ByteBuffer;)V+]Ljava/security/Signature;Ljava/security/Signature$Delegate;
+HSPLjava/security/Signature;->update([B)V+]Ljava/security/Signature;Ljava/security/Signature$Delegate;
+HSPLjava/security/Signature;->update([BII)V+]Ljava/security/Signature;Ljava/security/Signature$Delegate;
+HSPLjava/security/Signature;->verify([B)Z+]Ljava/security/Signature;Ljava/security/Signature$Delegate;
+HSPLjava/security/SignatureSpi;-><init>()V
+HSPLjava/security/SignatureSpi;->engineUpdate(Ljava/nio/ByteBuffer;)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/security/SignatureSpi;megamorphic_types
+HSPLjava/security/cert/CertPath;-><init>(Ljava/lang/String;)V
+HSPLjava/security/cert/CertPath;->getType()Ljava/lang/String;
+HSPLjava/security/cert/CertPathValidator;-><init>(Ljava/security/cert/CertPathValidatorSpi;Ljava/security/Provider;Ljava/lang/String;)V
+HSPLjava/security/cert/CertPathValidator;->getInstance(Ljava/lang/String;)Ljava/security/cert/CertPathValidator;
+HSPLjava/security/cert/CertPathValidator;->getRevocationChecker()Ljava/security/cert/CertPathChecker;
+HSPLjava/security/cert/CertPathValidator;->validate(Ljava/security/cert/CertPath;Ljava/security/cert/CertPathParameters;)Ljava/security/cert/CertPathValidatorResult;+]Ljava/security/cert/CertPathValidatorSpi;Lsun/security/provider/certpath/PKIXCertPathValidator;,Lcom/android/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi;
+HSPLjava/security/cert/CertPathValidatorSpi;-><init>()V
+HSPLjava/security/cert/CertStore;-><init>(Ljava/security/cert/CertStoreSpi;Ljava/security/Provider;Ljava/lang/String;Ljava/security/cert/CertStoreParameters;)V
+HSPLjava/security/cert/CertStore;->getInstance(Ljava/lang/String;Ljava/security/cert/CertStoreParameters;)Ljava/security/cert/CertStore;
+HSPLjava/security/cert/CertStoreSpi;-><init>(Ljava/security/cert/CertStoreParameters;)V
+HSPLjava/security/cert/Certificate;-><init>(Ljava/lang/String;)V
+HSPLjava/security/cert/Certificate;->equals(Ljava/lang/Object;)Z
+HSPLjava/security/cert/Certificate;->getType()Ljava/lang/String;
+HSPLjava/security/cert/Certificate;->hashCode()I
+HSPLjava/security/cert/CertificateFactory;-><init>(Ljava/security/cert/CertificateFactorySpi;Ljava/security/Provider;Ljava/lang/String;)V
+HSPLjava/security/cert/CertificateFactory;->generateCertPath(Ljava/util/List;)Ljava/security/cert/CertPath;+]Ljava/security/cert/CertificateFactorySpi;missing_types
+HSPLjava/security/cert/CertificateFactory;->generateCertificate(Ljava/io/InputStream;)Ljava/security/cert/Certificate;+]Ljava/security/cert/CertificateFactorySpi;missing_types
+HSPLjava/security/cert/CertificateFactory;->generateCertificates(Ljava/io/InputStream;)Ljava/util/Collection;
+HSPLjava/security/cert/CertificateFactory;->getInstance(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;
+HSPLjava/security/cert/CertificateFactorySpi;-><init>()V
+HSPLjava/security/cert/CollectionCertStoreParameters;-><init>(Ljava/util/Collection;)V
+HSPLjava/security/cert/CollectionCertStoreParameters;->clone()Ljava/lang/Object;
+HSPLjava/security/cert/PKIXCertPathChecker;-><init>()V
+HSPLjava/security/cert/PKIXCertPathChecker;->clone()Ljava/lang/Object;
+HSPLjava/security/cert/PKIXCertPathValidatorResult;-><init>(Ljava/security/cert/TrustAnchor;Ljava/security/cert/PolicyNode;Ljava/security/PublicKey;)V
+HSPLjava/security/cert/PKIXParameters;-><init>(Ljava/util/Set;)V+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;
+HSPLjava/security/cert/PKIXParameters;->addCertPathChecker(Ljava/security/cert/PKIXCertPathChecker;)V+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/security/cert/PKIXCertPathChecker;missing_types
+HSPLjava/security/cert/PKIXParameters;->getCertPathCheckers()Ljava/util/List;+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/security/cert/PKIXCertPathChecker;missing_types]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLjava/security/cert/PKIXParameters;->getCertStores()Ljava/util/List;
+HSPLjava/security/cert/PKIXParameters;->getDate()Ljava/util/Date;
+HSPLjava/security/cert/PKIXParameters;->getInitialPolicies()Ljava/util/Set;
+HSPLjava/security/cert/PKIXParameters;->getPolicyQualifiersRejected()Z
+HSPLjava/security/cert/PKIXParameters;->getSigProvider()Ljava/lang/String;
+HSPLjava/security/cert/PKIXParameters;->getTargetCertConstraints()Ljava/security/cert/CertSelector;
+HSPLjava/security/cert/PKIXParameters;->getTrustAnchors()Ljava/util/Set;
+HSPLjava/security/cert/PKIXParameters;->isAnyPolicyInhibited()Z
+HSPLjava/security/cert/PKIXParameters;->isExplicitPolicyRequired()Z
+HSPLjava/security/cert/PKIXParameters;->isPolicyMappingInhibited()Z
+HSPLjava/security/cert/PKIXParameters;->isRevocationEnabled()Z
+HSPLjava/security/cert/PKIXParameters;->setCertPathCheckers(Ljava/util/List;)V+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/security/cert/PKIXCertPathChecker;Lsun/security/provider/certpath/RevocationChecker;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLjava/security/cert/PKIXParameters;->setRevocationEnabled(Z)V
+HSPLjava/security/cert/PKIXParameters;->setTrustAnchors(Ljava/util/Set;)V+]Ljava/util/Iterator;missing_types]Ljava/util/Set;missing_types
+HSPLjava/security/cert/PKIXRevocationChecker;-><init>()V
+HSPLjava/security/cert/PKIXRevocationChecker;->clone()Ljava/security/cert/PKIXRevocationChecker;+]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;][B[B]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;
+HSPLjava/security/cert/PKIXRevocationChecker;->getOcspExtensions()Ljava/util/List;
+HSPLjava/security/cert/PKIXRevocationChecker;->getOcspResponder()Ljava/net/URI;
+HSPLjava/security/cert/PKIXRevocationChecker;->getOcspResponderCert()Ljava/security/cert/X509Certificate;
+HSPLjava/security/cert/PKIXRevocationChecker;->getOcspResponses()Ljava/util/Map;+]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;][B[B]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;
+HSPLjava/security/cert/PKIXRevocationChecker;->getOptions()Ljava/util/Set;
+HSPLjava/security/cert/PKIXRevocationChecker;->setOcspResponses(Ljava/util/Map;)V+]Ljava/util/Map$Entry;Ljava/util/AbstractMap$SimpleImmutableEntry;][B[B]Ljava/util/Map;Ljava/util/HashMap;,Ljava/util/Collections$SingletonMap;]Ljava/util/Iterator;Ljava/util/Collections$1;]Ljava/util/Set;Ljava/util/Collections$SingletonSet;
+HSPLjava/security/cert/PKIXRevocationChecker;->setOptions(Ljava/util/Set;)V
+HSPLjava/security/cert/PolicyQualifierInfo;-><init>([B)V+]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;]Lsun/security/util/DerValue;Lsun/security/util/DerValue;][B[B]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLjava/security/cert/TrustAnchor;-><init>(Ljava/security/cert/X509Certificate;[B)V
+HSPLjava/security/cert/TrustAnchor;->getNameConstraints()[B
+HSPLjava/security/cert/TrustAnchor;->getTrustedCert()Ljava/security/cert/X509Certificate;
+HSPLjava/security/cert/TrustAnchor;->setNameConstraints([B)V
+HSPLjava/security/cert/X509CertSelector;-><init>()V
+HSPLjava/security/cert/X509CertSelector;->match(Ljava/security/cert/Certificate;)Z+]Ljava/security/cert/X509Certificate;missing_types]Ljavax/security/auth/x500/X500Principal;Ljavax/security/auth/x500/X500Principal;
+HSPLjava/security/cert/X509CertSelector;->matchAuthorityKeyID(Ljava/security/cert/X509Certificate;)Z
+HSPLjava/security/cert/X509CertSelector;->matchBasicConstraints(Ljava/security/cert/X509Certificate;)Z+]Ljava/security/cert/X509Certificate;missing_types
+HSPLjava/security/cert/X509CertSelector;->matchExtendedKeyUsage(Ljava/security/cert/X509Certificate;)Z
+HSPLjava/security/cert/X509CertSelector;->matchKeyUsage(Ljava/security/cert/X509Certificate;)Z
+HSPLjava/security/cert/X509CertSelector;->matchNameConstraints(Ljava/security/cert/X509Certificate;)Z
+HSPLjava/security/cert/X509CertSelector;->matchPathToNames(Ljava/security/cert/X509Certificate;)Z
+HSPLjava/security/cert/X509CertSelector;->matchPolicy(Ljava/security/cert/X509Certificate;)Z
+HSPLjava/security/cert/X509CertSelector;->matchPrivateKeyValid(Ljava/security/cert/X509Certificate;)Z
+HSPLjava/security/cert/X509CertSelector;->matchSubjectAlternativeNames(Ljava/security/cert/X509Certificate;)Z
+HSPLjava/security/cert/X509CertSelector;->matchSubjectKeyID(Ljava/security/cert/X509Certificate;)Z
+HSPLjava/security/cert/X509CertSelector;->matchSubjectPublicKeyAlgID(Ljava/security/cert/X509Certificate;)Z
+HSPLjava/security/cert/X509CertSelector;->setSubject(Ljavax/security/auth/x500/X500Principal;)V
+HSPLjava/security/cert/X509Certificate;-><init>()V
+HSPLjava/security/spec/DSAParameterSpec;-><init>(Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;)V
+HSPLjava/security/spec/DSAParameterSpec;->getG()Ljava/math/BigInteger;
+HSPLjava/security/spec/DSAParameterSpec;->getP()Ljava/math/BigInteger;
+HSPLjava/security/spec/DSAParameterSpec;->getQ()Ljava/math/BigInteger;
+HSPLjava/security/spec/ECFieldFp;-><init>(Ljava/math/BigInteger;)V+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/security/spec/ECFieldFp;->getFieldSize()I+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/security/spec/ECFieldFp;->getP()Ljava/math/BigInteger;
+HSPLjava/security/spec/ECParameterSpec;-><init>(Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V+]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLjava/security/spec/ECParameterSpec;->getCurve()Ljava/security/spec/EllipticCurve;
+HSPLjava/security/spec/ECParameterSpec;->getOrder()Ljava/math/BigInteger;
+HSPLjava/security/spec/ECParameterSpec;->setCurveName(Ljava/lang/String;)V
+HSPLjava/security/spec/ECPoint;-><init>(Ljava/math/BigInteger;Ljava/math/BigInteger;)V
+HSPLjava/security/spec/ECPoint;->getAffineX()Ljava/math/BigInteger;
+HSPLjava/security/spec/ECPoint;->getAffineY()Ljava/math/BigInteger;
+HSPLjava/security/spec/EllipticCurve;-><init>(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V
+HSPLjava/security/spec/EllipticCurve;-><init>(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;[B)V
+HSPLjava/security/spec/EllipticCurve;->checkValidity(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/lang/String;)V+]Ljava/math/BigInteger;Ljava/math/BigInteger;]Ljava/security/spec/ECFieldFp;Ljava/security/spec/ECFieldFp;
+HSPLjava/security/spec/EllipticCurve;->getField()Ljava/security/spec/ECField;
+HSPLjava/security/spec/EncodedKeySpec;-><init>([B)V+][B[B
+HSPLjava/security/spec/EncodedKeySpec;->getEncoded()[B+][B[B
+HSPLjava/security/spec/PKCS8EncodedKeySpec;-><init>([B)V
+HSPLjava/security/spec/PKCS8EncodedKeySpec;->getEncoded()[B
+HSPLjava/security/spec/X509EncodedKeySpec;-><init>([B)V
+HSPLjava/security/spec/X509EncodedKeySpec;->getEncoded()[B
+HSPLjava/text/AttributedCharacterIterator$Attribute;->equals(Ljava/lang/Object;)Z
+HSPLjava/text/BreakIterator;-><init>()V
+HSPLjava/text/BreakIterator;->getWordInstance(Ljava/util/Locale;)Ljava/text/BreakIterator;
+HSPLjava/text/CalendarBuilder;-><init>()V
+HSPLjava/text/CalendarBuilder;->establish(Ljava/util/Calendar;)Ljava/util/Calendar;+]Ljava/text/CalendarBuilder;Ljava/text/CalendarBuilder;]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/text/CalendarBuilder;->isSet(I)Z
+HSPLjava/text/CalendarBuilder;->set(II)Ljava/text/CalendarBuilder;
+HSPLjava/text/CollationKey;-><init>(Ljava/lang/String;)V
+HSPLjava/text/Collator;-><init>(Landroid/icu/text/Collator;)V
+HSPLjava/text/Collator;->decompositionMode_Java_ICU(I)I
+HSPLjava/text/Collator;->getInstance()Ljava/text/Collator;
+HSPLjava/text/Collator;->getInstance(Ljava/util/Locale;)Ljava/text/Collator;
+HSPLjava/text/Collator;->setDecomposition(I)V+]Landroid/icu/text/Collator;missing_types
+HSPLjava/text/Collator;->setStrength(I)V+]Landroid/icu/text/Collator;missing_types
+HSPLjava/text/DateFormat;-><init>()V
+HSPLjava/text/DateFormat;->format(Ljava/lang/Object;Ljava/lang/StringBuffer;Ljava/text/FieldPosition;)Ljava/lang/StringBuffer;+]Ljava/lang/Number;Ljava/lang/Long;,Ljava/lang/Integer;]Ljava/text/DateFormat;Ljava/text/SimpleDateFormat;
+HSPLjava/text/DateFormat;->format(Ljava/util/Date;)Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/text/DateFormat;missing_types
+HSPLjava/text/DateFormat;->get(IIILjava/util/Locale;)Ljava/text/DateFormat;
+HSPLjava/text/DateFormat;->getDateInstance(ILjava/util/Locale;)Ljava/text/DateFormat;
+HSPLjava/text/DateFormat;->getDateTimeInstance()Ljava/text/DateFormat;
+HSPLjava/text/DateFormat;->getDateTimeInstance(II)Ljava/text/DateFormat;
+HSPLjava/text/DateFormat;->getDateTimeInstance(IILjava/util/Locale;)Ljava/text/DateFormat;
+HSPLjava/text/DateFormat;->getTimeInstance(ILjava/util/Locale;)Ljava/text/DateFormat;
+HSPLjava/text/DateFormat;->getTimeZone()Ljava/util/TimeZone;+]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/text/DateFormat;->parse(Ljava/lang/String;)Ljava/util/Date;+]Ljava/text/DateFormat;missing_types]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/text/DateFormat;->set24HourTimePref(Ljava/lang/Boolean;)V
+HSPLjava/text/DateFormat;->setCalendar(Ljava/util/Calendar;)V
+HSPLjava/text/DateFormat;->setLenient(Z)V+]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/text/DateFormat;->setTimeZone(Ljava/util/TimeZone;)V+]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/text/DateFormatSymbols;-><init>(Ljava/util/Locale;)V
+HSPLjava/text/DateFormatSymbols;->clone()Ljava/lang/Object;
+HSPLjava/text/DateFormatSymbols;->copyMembers(Ljava/text/DateFormatSymbols;Ljava/text/DateFormatSymbols;)V
+HSPLjava/text/DateFormatSymbols;->getAmPmStrings()[Ljava/lang/String;
+HSPLjava/text/DateFormatSymbols;->getCachedInstance(Ljava/util/Locale;)Ljava/text/DateFormatSymbols;+]Ljava/lang/ref/SoftReference;Ljava/lang/ref/SoftReference;]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/text/DateFormatSymbols;->getInstance(Ljava/util/Locale;)Ljava/text/DateFormatSymbols;+]Ljava/text/DateFormatSymbols;Ljava/text/DateFormatSymbols;
+HSPLjava/text/DateFormatSymbols;->getInstanceRef(Ljava/util/Locale;)Ljava/text/DateFormatSymbols;
+HSPLjava/text/DateFormatSymbols;->getMonths()[Ljava/lang/String;
+HSPLjava/text/DateFormatSymbols;->getShortMonths()[Ljava/lang/String;
+HSPLjava/text/DateFormatSymbols;->getShortWeekdays()[Ljava/lang/String;
+HSPLjava/text/DateFormatSymbols;->getWeekdays()[Ljava/lang/String;
+HSPLjava/text/DateFormatSymbols;->initializeData(Ljava/util/Locale;)V+]Ljava/lang/ref/SoftReference;Ljava/lang/ref/SoftReference;]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/text/DateFormatSymbols;->initializeSupplementaryData(Llibcore/icu/LocaleData;)V
+HSPLjava/text/DecimalFormat;-><init>(Ljava/lang/String;)V
+HSPLjava/text/DecimalFormat;-><init>(Ljava/lang/String;Ljava/text/DecimalFormatSymbols;)V+]Ljava/text/DecimalFormatSymbols;Ljava/text/DecimalFormatSymbols;
+HSPLjava/text/DecimalFormat;->clone()Ljava/lang/Object;+]Ljava/text/DecimalFormatSymbols;Ljava/text/DecimalFormatSymbols;]Landroid/icu/text/DecimalFormat;missing_types
+HSPLjava/text/DecimalFormat;->equals(Ljava/lang/Object;)Z
+HSPLjava/text/DecimalFormat;->format(DLjava/lang/StringBuffer;Ljava/text/FieldPosition;)Ljava/lang/StringBuffer;+]Ljava/text/FieldPosition;Ljava/text/DontCareFieldPosition;,Ljava/text/FieldPosition;]Landroid/icu/text/DecimalFormat;missing_types
+HSPLjava/text/DecimalFormat;->format(JLjava/lang/StringBuffer;Ljava/text/FieldPosition;)Ljava/lang/StringBuffer;+]Ljava/text/FieldPosition;Ljava/text/DontCareFieldPosition;,Ljava/text/FieldPosition;]Landroid/icu/text/DecimalFormat;missing_types
+HSPLjava/text/DecimalFormat;->format(Ljava/lang/Object;Ljava/lang/StringBuffer;Ljava/text/FieldPosition;)Ljava/lang/StringBuffer;+]Ljava/lang/Number;Ljava/lang/Float;,Ljava/lang/Double;,Ljava/lang/Integer;,Ljava/lang/Long;]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;
+HSPLjava/text/DecimalFormat;->getDecimalFormatSymbols()Ljava/text/DecimalFormatSymbols;+]Landroid/icu/text/DecimalFormat;missing_types
+HSPLjava/text/DecimalFormat;->getIcuFieldPosition(Ljava/text/FieldPosition;)Ljava/text/FieldPosition;+]Ljava/text/FieldPosition;Ljava/text/FieldPosition;,Ljava/text/DontCareFieldPosition;
+HSPLjava/text/DecimalFormat;->getMaximumFractionDigits()I
+HSPLjava/text/DecimalFormat;->getMaximumIntegerDigits()I
+HSPLjava/text/DecimalFormat;->getMinimumFractionDigits()I
+HSPLjava/text/DecimalFormat;->getMinimumIntegerDigits()I
+HSPLjava/text/DecimalFormat;->getNegativePrefix()Ljava/lang/String;
+HSPLjava/text/DecimalFormat;->getNegativeSuffix()Ljava/lang/String;+]Landroid/icu/text/DecimalFormat;Landroid/icu/text/DecimalFormat;
+HSPLjava/text/DecimalFormat;->getPositivePrefix()Ljava/lang/String;+]Landroid/icu/text/DecimalFormat;Landroid/icu/text/DecimalFormat;
+HSPLjava/text/DecimalFormat;->getPositiveSuffix()Ljava/lang/String;+]Landroid/icu/text/DecimalFormat;Landroid/icu/text/DecimalFormat;
+HSPLjava/text/DecimalFormat;->initPattern(Ljava/lang/String;)V+]Ljava/text/DecimalFormatSymbols;Ljava/text/DecimalFormatSymbols;
+HSPLjava/text/DecimalFormat;->isParseBigDecimal()Z+]Landroid/icu/text/DecimalFormat;missing_types
+HSPLjava/text/DecimalFormat;->isParseIntegerOnly()Z+]Landroid/icu/text/DecimalFormat;missing_types
+HSPLjava/text/DecimalFormat;->parse(Ljava/lang/String;Ljava/text/ParsePosition;)Ljava/lang/Number;+]Ljava/lang/Object;Ljava/lang/Long;]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;]Landroid/icu/text/DecimalFormat;missing_types]Ljava/lang/Number;Landroid/icu/math/BigDecimal;
+HSPLjava/text/DecimalFormat;->setDecimalSeparatorAlwaysShown(Z)V+]Landroid/icu/text/DecimalFormat;Landroid/icu/text/DecimalFormat;
+HSPLjava/text/DecimalFormat;->setGroupingUsed(Z)V+]Landroid/icu/text/DecimalFormat;Landroid/icu/text/DecimalFormat;
+HSPLjava/text/DecimalFormat;->setMaximumFractionDigits(I)V+]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;]Landroid/icu/text/DecimalFormat;Landroid/icu/text/DecimalFormat;
+HSPLjava/text/DecimalFormat;->setMaximumIntegerDigits(I)V+]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;]Landroid/icu/text/DecimalFormat;missing_types
+HSPLjava/text/DecimalFormat;->setMinimumFractionDigits(I)V+]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;]Landroid/icu/text/DecimalFormat;Landroid/icu/text/DecimalFormat;
+HSPLjava/text/DecimalFormat;->setMinimumIntegerDigits(I)V+]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;]Landroid/icu/text/DecimalFormat;missing_types
+HSPLjava/text/DecimalFormat;->setParseIntegerOnly(Z)V+]Landroid/icu/text/DecimalFormat;Landroid/icu/text/DecimalFormat;
+HSPLjava/text/DecimalFormat;->toPattern()Ljava/lang/String;+]Landroid/icu/text/DecimalFormat;Landroid/icu/text/DecimalFormat;
+HSPLjava/text/DecimalFormat;->updateFieldsFromIcu()V+]Landroid/icu/text/DecimalFormat;missing_types
+HSPLjava/text/DecimalFormatSymbols;-><init>(Ljava/util/Locale;)V
+HSPLjava/text/DecimalFormatSymbols;->clone()Ljava/lang/Object;
+HSPLjava/text/DecimalFormatSymbols;->fromIcuInstance(Landroid/icu/text/DecimalFormatSymbols;)Ljava/text/DecimalFormatSymbols;+]Ljava/text/DecimalFormatSymbols;Ljava/text/DecimalFormatSymbols;]Landroid/icu/text/DecimalFormatSymbols;Landroid/icu/text/DecimalFormatSymbols;]Landroid/icu/util/Currency;Landroid/icu/util/Currency;
+HSPLjava/text/DecimalFormatSymbols;->getDecimalSeparator()C
+HSPLjava/text/DecimalFormatSymbols;->getGroupingSeparator()C
+HSPLjava/text/DecimalFormatSymbols;->getIcuDecimalFormatSymbols()Landroid/icu/text/DecimalFormatSymbols;+]Ljava/util/Currency;Ljava/util/Currency;]Landroid/icu/text/DecimalFormatSymbols;missing_types
+HSPLjava/text/DecimalFormatSymbols;->getInfinity()Ljava/lang/String;
+HSPLjava/text/DecimalFormatSymbols;->getInstance(Ljava/util/Locale;)Ljava/text/DecimalFormatSymbols;
+HSPLjava/text/DecimalFormatSymbols;->getNaN()Ljava/lang/String;
+HSPLjava/text/DecimalFormatSymbols;->getZeroDigit()C
+HSPLjava/text/DecimalFormatSymbols;->initialize(Ljava/util/Locale;)V+]Ljava/util/Currency;Ljava/util/Currency;]Ljava/util/Locale;Ljava/util/Locale;
+HSPLjava/text/DecimalFormatSymbols;->maybeStripMarkers(Ljava/lang/String;C)C
+HSPLjava/text/DecimalFormatSymbols;->setCurrency(Ljava/util/Currency;)V+]Ljava/util/Currency;Ljava/util/Currency;
+HSPLjava/text/DecimalFormatSymbols;->setCurrencySymbol(Ljava/lang/String;)V
+HSPLjava/text/DecimalFormatSymbols;->setDecimalSeparator(C)V
+HSPLjava/text/DecimalFormatSymbols;->setDigit(C)V
+HSPLjava/text/DecimalFormatSymbols;->setExponentSeparator(Ljava/lang/String;)V
+HSPLjava/text/DecimalFormatSymbols;->setGroupingSeparator(C)V
+HSPLjava/text/DecimalFormatSymbols;->setInfinity(Ljava/lang/String;)V
+HSPLjava/text/DecimalFormatSymbols;->setInternationalCurrencySymbol(Ljava/lang/String;)V+]Ljava/util/Currency;Ljava/util/Currency;
+HSPLjava/text/DecimalFormatSymbols;->setMinusSign(C)V
+HSPLjava/text/DecimalFormatSymbols;->setMonetaryDecimalSeparator(C)V
+HSPLjava/text/DecimalFormatSymbols;->setNaN(Ljava/lang/String;)V
+HSPLjava/text/DecimalFormatSymbols;->setPatternSeparator(C)V
+HSPLjava/text/DecimalFormatSymbols;->setPerMill(C)V
+HSPLjava/text/DecimalFormatSymbols;->setPercent(C)V
+HSPLjava/text/DecimalFormatSymbols;->setZeroDigit(C)V
+HSPLjava/text/DontCareFieldPosition$1;->formatted(ILjava/text/Format$Field;Ljava/lang/Object;IILjava/lang/StringBuffer;)V
+HSPLjava/text/DontCareFieldPosition;->getFieldDelegate()Ljava/text/Format$FieldDelegate;
+HSPLjava/text/FieldPosition$Delegate;-><init>(Ljava/text/FieldPosition;)V
+HSPLjava/text/FieldPosition$Delegate;-><init>(Ljava/text/FieldPosition;Ljava/text/FieldPosition$1;)V
+HSPLjava/text/FieldPosition$Delegate;->formatted(ILjava/text/Format$Field;Ljava/lang/Object;IILjava/lang/StringBuffer;)V
+HSPLjava/text/FieldPosition;-><init>(I)V
+HSPLjava/text/FieldPosition;->access$200(Ljava/text/FieldPosition;Ljava/text/Format$Field;I)Z
+HSPLjava/text/FieldPosition;->getBeginIndex()I
+HSPLjava/text/FieldPosition;->getEndIndex()I
+HSPLjava/text/FieldPosition;->getField()I
+HSPLjava/text/FieldPosition;->getFieldAttribute()Ljava/text/Format$Field;
+HSPLjava/text/FieldPosition;->getFieldDelegate()Ljava/text/Format$FieldDelegate;
+HSPLjava/text/FieldPosition;->matchesField(Ljava/text/Format$Field;I)Z
+HSPLjava/text/FieldPosition;->setBeginIndex(I)V
+HSPLjava/text/FieldPosition;->setEndIndex(I)V
+HSPLjava/text/Format;-><init>()V
+HSPLjava/text/Format;->clone()Ljava/lang/Object;
+HSPLjava/text/Format;->format(Ljava/lang/Object;)Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/text/Format;megamorphic_types
+HSPLjava/text/IcuIteratorWrapper;-><init>(Landroid/icu/text/BreakIterator;)V
+HSPLjava/text/IcuIteratorWrapper;->checkOffset(ILjava/text/CharacterIterator;)V+]Ljava/text/CharacterIterator;Ljava/text/StringCharacterIterator;
+HSPLjava/text/IcuIteratorWrapper;->getText()Ljava/text/CharacterIterator;+]Landroid/icu/text/BreakIterator;Landroid/icu/text/RuleBasedBreakIterator;
+HSPLjava/text/IcuIteratorWrapper;->next()I+]Landroid/icu/text/BreakIterator;missing_types
+HSPLjava/text/IcuIteratorWrapper;->preceding(I)I+]Landroid/icu/text/BreakIterator;Landroid/icu/text/RuleBasedBreakIterator;]Ljava/text/IcuIteratorWrapper;Ljava/text/IcuIteratorWrapper;
+HSPLjava/text/IcuIteratorWrapper;->setText(Ljava/lang/String;)V+]Landroid/icu/text/BreakIterator;missing_types
+HSPLjava/text/MessageFormat;-><init>(Ljava/lang/String;)V+]Ljava/text/MessageFormat;Ljava/text/MessageFormat;
+HSPLjava/text/MessageFormat;->applyPattern(Ljava/lang/String;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/text/MessageFormat;->format(Ljava/lang/Object;Ljava/lang/StringBuffer;Ljava/text/FieldPosition;)Ljava/lang/StringBuffer;
+HSPLjava/text/MessageFormat;->format(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;+]Ljava/text/MessageFormat;Ljava/text/MessageFormat;
+HSPLjava/text/MessageFormat;->makeFormat(II[Ljava/lang/StringBuilder;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/text/MessageFormat;->subformat([Ljava/lang/Object;Ljava/lang/StringBuffer;Ljava/text/FieldPosition;Ljava/util/List;)Ljava/lang/StringBuffer;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/text/FieldPosition;Ljava/text/FieldPosition;]Ljava/text/MessageFormat$Field;Ljava/text/MessageFormat$Field;]Ljava/text/Format;Ljava/text/DecimalFormat;,Ljava/text/ChoiceFormat;]Ljava/lang/Object;missing_types
+HSPLjava/text/Normalizer$Form$$ExternalSyntheticLambda3;->get()Ljava/lang/Object;
+HSPLjava/text/Normalizer$Form;->access$000(Ljava/text/Normalizer$Form;)Ljava/util/function/Supplier;
+HSPLjava/text/Normalizer;->normalize(Ljava/lang/CharSequence;Ljava/text/Normalizer$Form;)Ljava/lang/String;+]Ljava/util/function/Supplier;Ljava/text/Normalizer$Form$$ExternalSyntheticLambda3;,Ljava/text/Normalizer$Form$$ExternalSyntheticLambda2;]Landroid/icu/text/Normalizer2;Landroid/icu/impl/Norm2AllModes$DecomposeNormalizer2;,Landroid/icu/impl/Norm2AllModes$ComposeNormalizer2;
+HSPLjava/text/NumberFormat;-><init>()V
+HSPLjava/text/NumberFormat;->clone()Ljava/lang/Object;
+HSPLjava/text/NumberFormat;->format(D)Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/text/NumberFormat;Ljava/text/DecimalFormat;
+HSPLjava/text/NumberFormat;->format(J)Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/text/NumberFormat;Ljava/text/DecimalFormat;
+HSPLjava/text/NumberFormat;->getInstance()Ljava/text/NumberFormat;
+HSPLjava/text/NumberFormat;->getInstance(Ljava/util/Locale;)Ljava/text/NumberFormat;
+HSPLjava/text/NumberFormat;->getInstance(Ljava/util/Locale;I)Ljava/text/NumberFormat;+]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;
+HSPLjava/text/NumberFormat;->getIntegerInstance(Ljava/util/Locale;)Ljava/text/NumberFormat;
+HSPLjava/text/NumberFormat;->getNumberInstance(Ljava/util/Locale;)Ljava/text/NumberFormat;
+HSPLjava/text/NumberFormat;->getPercentInstance()Ljava/text/NumberFormat;
+HSPLjava/text/NumberFormat;->setMaximumFractionDigits(I)V
+HSPLjava/text/NumberFormat;->setMaximumIntegerDigits(I)V
+HSPLjava/text/NumberFormat;->setMinimumFractionDigits(I)V
+HSPLjava/text/NumberFormat;->setMinimumIntegerDigits(I)V
+HSPLjava/text/NumberFormat;->setParseIntegerOnly(Z)V
+HSPLjava/text/ParseException;-><init>(Ljava/lang/String;I)V
+HSPLjava/text/ParsePosition;-><init>(I)V
+HSPLjava/text/ParsePosition;->getErrorIndex()I
+HSPLjava/text/ParsePosition;->getIndex()I
+HSPLjava/text/ParsePosition;->setIndex(I)V
+HSPLjava/text/RuleBasedCollator;-><init>(Landroid/icu/text/RuleBasedCollator;)V
+HSPLjava/text/RuleBasedCollator;->compare(Ljava/lang/String;Ljava/lang/String;)I+]Landroid/icu/text/Collator;missing_types
+HSPLjava/text/RuleBasedCollator;->getCollationKey(Ljava/lang/String;)Ljava/text/CollationKey;+]Landroid/icu/text/Collator;Landroid/icu/text/RuleBasedCollator;
+HSPLjava/text/SimpleDateFormat;-><init>()V
+HSPLjava/text/SimpleDateFormat;-><init>(IILjava/util/Locale;)V
+HSPLjava/text/SimpleDateFormat;-><init>(Ljava/lang/String;)V
+HSPLjava/text/SimpleDateFormat;-><init>(Ljava/lang/String;Ljava/util/Locale;)V
+HSPLjava/text/SimpleDateFormat;->checkNegativeNumberExpression()V+]Ljava/text/NumberFormat;Ljava/text/DecimalFormat;]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;
+HSPLjava/text/SimpleDateFormat;->compile(Ljava/lang/String;)[C+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/text/SimpleDateFormat;->encode(IILjava/lang/StringBuilder;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/text/SimpleDateFormat;->format(Ljava/util/Date;Ljava/lang/StringBuffer;Ljava/text/FieldPosition;)Ljava/lang/StringBuffer;+]Ljava/text/FieldPosition;Ljava/text/DontCareFieldPosition;,Ljava/text/FieldPosition;
+HSPLjava/text/SimpleDateFormat;->format(Ljava/util/Date;Ljava/lang/StringBuffer;Ljava/text/Format$FieldDelegate;)Ljava/lang/StringBuffer;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/text/SimpleDateFormat;->formatMonth(IIILjava/lang/StringBuffer;ZZII)Ljava/lang/String;+]Ljava/text/DateFormatSymbols;Ljava/text/DateFormatSymbols;
+HSPLjava/text/SimpleDateFormat;->formatWeekday(IIZZ)Ljava/lang/String;+]Ljava/text/DateFormatSymbols;Ljava/text/DateFormatSymbols;
+HSPLjava/text/SimpleDateFormat;->getDateTimeFormat(IILjava/util/Locale;)Ljava/lang/String;+]Llibcore/icu/LocaleData;Llibcore/icu/LocaleData;
+HSPLjava/text/SimpleDateFormat;->getExtendedTimeZoneNames()Lcom/android/icu/text/ExtendedTimeZoneNames;
+HSPLjava/text/SimpleDateFormat;->getTimeZoneNames()Landroid/icu/text/TimeZoneNames;+]Lcom/android/icu/text/ExtendedTimeZoneNames;missing_types
+HSPLjava/text/SimpleDateFormat;->initialize(Ljava/util/Locale;)V+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/text/NumberFormat;Ljava/text/DecimalFormat;
+HSPLjava/text/SimpleDateFormat;->initializeCalendar(Ljava/util/Locale;)V
+HSPLjava/text/SimpleDateFormat;->initializeDefaultCentury()V+]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/text/SimpleDateFormat;->isDigit(C)Z
+HSPLjava/text/SimpleDateFormat;->matchString(Ljava/lang/String;II[Ljava/lang/String;Ljava/text/CalendarBuilder;)I+]Ljava/lang/String;Ljava/lang/String;]Ljava/text/CalendarBuilder;Ljava/text/CalendarBuilder;
+HSPLjava/text/SimpleDateFormat;->parse(Ljava/lang/String;Ljava/text/ParsePosition;)Ljava/util/Date;+]Ljava/text/SimpleDateFormat;missing_types
+HSPLjava/text/SimpleDateFormat;->parseAmbiguousDatesAsAfter(Ljava/util/Date;)V+]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/text/SimpleDateFormat;->parseInternal(Ljava/lang/String;Ljava/text/ParsePosition;)Ljava/util/Date;+]Ljava/text/CalendarBuilder;Ljava/text/CalendarBuilder;]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/text/SimpleDateFormat;->parseMonth(Ljava/lang/String;IIIILjava/text/ParsePosition;ZZLjava/text/CalendarBuilder;)I+]Ljava/text/DateFormatSymbols;Ljava/text/DateFormatSymbols;]Ljava/text/CalendarBuilder;Ljava/text/CalendarBuilder;
+HSPLjava/text/SimpleDateFormat;->parseWeekday(Ljava/lang/String;IIZZLjava/text/CalendarBuilder;)I+]Ljava/text/DateFormatSymbols;Ljava/text/DateFormatSymbols;
+HSPLjava/text/SimpleDateFormat;->subFormat(IILjava/text/Format$FieldDelegate;Ljava/lang/StringBuffer;Z)V+]Ljava/text/Format$FieldDelegate;Ljava/text/DontCareFieldPosition$1;,Ljava/text/FieldPosition$Delegate;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/util/Calendar;Ljava/util/GregorianCalendar;]Ljava/text/DateFormatSymbols;Ljava/text/DateFormatSymbols;]Landroid/icu/text/TimeZoneNames;missing_types]Ljava/util/TimeZone;missing_types
+HSPLjava/text/SimpleDateFormat;->subParse(Ljava/lang/String;IIIZ[ZLjava/text/ParsePosition;ZLjava/text/CalendarBuilder;)I+]Ljava/lang/String;Ljava/lang/String;]Ljava/text/ParsePosition;Ljava/text/ParsePosition;]Ljava/text/CalendarBuilder;Ljava/text/CalendarBuilder;]Ljava/lang/Number;Ljava/lang/Long;]Ljava/text/NumberFormat;Ljava/text/DecimalFormat;]Ljava/text/DateFormatSymbols;Ljava/text/DateFormatSymbols;]Ljava/text/SimpleDateFormat;Ljava/text/SimpleDateFormat;]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/text/SimpleDateFormat;->subParseNumericZone(Ljava/lang/String;IIIZLjava/text/CalendarBuilder;)I+]Ljava/text/CalendarBuilder;Ljava/text/CalendarBuilder;
+HSPLjava/text/SimpleDateFormat;->toPattern()Ljava/lang/String;
+HSPLjava/text/SimpleDateFormat;->useDateFormatSymbols()Z+]Ljava/lang/Object;Ljava/util/GregorianCalendar;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/text/SimpleDateFormat;->zeroPaddingNumber(IIILjava/lang/StringBuffer;)V+]Ljava/text/DecimalFormatSymbols;Ljava/text/DecimalFormatSymbols;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;]Ljava/text/NumberFormat;Ljava/text/DecimalFormat;
+HSPLjava/text/StringCharacterIterator;-><init>(Ljava/lang/String;)V
+HSPLjava/text/StringCharacterIterator;-><init>(Ljava/lang/String;I)V
+HSPLjava/text/StringCharacterIterator;-><init>(Ljava/lang/String;III)V
+HSPLjava/text/StringCharacterIterator;->clone()Ljava/lang/Object;
+HSPLjava/text/StringCharacterIterator;->current()C
+HSPLjava/text/StringCharacterIterator;->first()C+]Ljava/text/StringCharacterIterator;Ljava/text/StringCharacterIterator;
+HSPLjava/text/StringCharacterIterator;->getBeginIndex()I
+HSPLjava/text/StringCharacterIterator;->getEndIndex()I
+HSPLjava/text/StringCharacterIterator;->getIndex()I
+HSPLjava/text/StringCharacterIterator;->next()C
+HSPLjava/text/StringCharacterIterator;->setIndex(I)C+]Ljava/text/StringCharacterIterator;Ljava/text/StringCharacterIterator;
+HSPLjava/time/Clock$SystemClock;-><init>(Ljava/time/ZoneId;)V
+HSPLjava/time/Clock$SystemClock;->getZone()Ljava/time/ZoneId;
+HSPLjava/time/Clock$SystemClock;->instant()Ljava/time/Instant;+]Ljava/time/Clock$SystemClock;Ljava/time/Clock$SystemClock;
+HSPLjava/time/Clock$SystemClock;->millis()J
+HSPLjava/time/Clock;-><init>()V
+HSPLjava/time/Clock;->systemDefaultZone()Ljava/time/Clock;
+HSPLjava/time/Clock;->systemUTC()Ljava/time/Clock;
+HSPLjava/time/DayOfWeek;->getValue()I+]Ljava/time/DayOfWeek;Ljava/time/DayOfWeek;
+HSPLjava/time/DayOfWeek;->of(I)Ljava/time/DayOfWeek;
+HSPLjava/time/DayOfWeek;->plus(J)Ljava/time/DayOfWeek;
+HSPLjava/time/Duration;-><init>(JI)V
+HSPLjava/time/Duration;->compareTo(Ljava/time/Duration;)I
+HSPLjava/time/Duration;->create(JI)Ljava/time/Duration;
+HSPLjava/time/Duration;->getSeconds()J
+HSPLjava/time/Duration;->ofDays(J)Ljava/time/Duration;
+HSPLjava/time/Duration;->ofMinutes(J)Ljava/time/Duration;
+HSPLjava/time/Duration;->toMillis()J
+HSPLjava/time/Duration;->toNanos()J
+HSPLjava/time/Instant;-><init>(JI)V
+HSPLjava/time/Instant;->atOffset(Ljava/time/ZoneOffset;)Ljava/time/OffsetDateTime;
+HSPLjava/time/Instant;->atZone(Ljava/time/ZoneId;)Ljava/time/ZonedDateTime;
+HSPLjava/time/Instant;->compareTo(Ljava/time/Instant;)I
+HSPLjava/time/Instant;->create(JI)Ljava/time/Instant;
+HSPLjava/time/Instant;->from(Ljava/time/temporal/TemporalAccessor;)Ljava/time/Instant;
+HSPLjava/time/Instant;->getEpochSecond()J
+HSPLjava/time/Instant;->getLong(Ljava/time/temporal/TemporalField;)J+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/Instant;->getNano()I
+HSPLjava/time/Instant;->isAfter(Ljava/time/Instant;)Z+]Ljava/time/Instant;Ljava/time/Instant;
+HSPLjava/time/Instant;->isSupported(Ljava/time/temporal/TemporalField;)Z
+HSPLjava/time/Instant;->minus(JLjava/time/temporal/TemporalUnit;)Ljava/time/Instant;+]Ljava/time/Instant;Ljava/time/Instant;
+HSPLjava/time/Instant;->nanosUntil(Ljava/time/Instant;)J
+HSPLjava/time/Instant;->now()Ljava/time/Instant;+]Ljava/time/Clock;Ljava/time/Clock$SystemClock;
+HSPLjava/time/Instant;->ofEpochMilli(J)Ljava/time/Instant;
+HSPLjava/time/Instant;->ofEpochSecond(JJ)Ljava/time/Instant;
+HSPLjava/time/Instant;->plus(JJ)Ljava/time/Instant;
+HSPLjava/time/Instant;->plus(JLjava/time/temporal/TemporalUnit;)Ljava/time/Instant;+]Ljava/time/Instant;Ljava/time/Instant;]Ljava/time/temporal/ChronoUnit;Ljava/time/temporal/ChronoUnit;
+HSPLjava/time/Instant;->plusMillis(J)Ljava/time/Instant;
+HSPLjava/time/Instant;->plusSeconds(J)Ljava/time/Instant;
+HSPLjava/time/Instant;->toEpochMilli()J
+HSPLjava/time/Instant;->toString()Ljava/lang/String;+]Ljava/time/format/DateTimeFormatter;Ljava/time/format/DateTimeFormatter;
+HSPLjava/time/Instant;->until(Ljava/time/temporal/Temporal;Ljava/time/temporal/TemporalUnit;)J+]Ljava/time/temporal/ChronoUnit;Ljava/time/temporal/ChronoUnit;
+HSPLjava/time/LocalDate;-><init>(III)V
+HSPLjava/time/LocalDate;->atTime(Ljava/time/LocalTime;)Ljava/time/LocalDateTime;
+HSPLjava/time/LocalDate;->atTime(Ljava/time/LocalTime;)Ljava/time/chrono/ChronoLocalDateTime;+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->compareTo0(Ljava/time/LocalDate;)I
+HSPLjava/time/LocalDate;->create(III)Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->get(Ljava/time/temporal/TemporalField;)I
+HSPLjava/time/LocalDate;->get0(Ljava/time/temporal/TemporalField;)I+]Ljava/time/LocalDate;Ljava/time/LocalDate;]Ljava/time/DayOfWeek;Ljava/time/DayOfWeek;]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/LocalDate;->getChronology()Ljava/time/chrono/Chronology;+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->getChronology()Ljava/time/chrono/IsoChronology;
+HSPLjava/time/LocalDate;->getDayOfMonth()I
+HSPLjava/time/LocalDate;->getDayOfWeek()Ljava/time/DayOfWeek;+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->getLong(Ljava/time/temporal/TemporalField;)J+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->getMonthValue()I
+HSPLjava/time/LocalDate;->getYear()I
+HSPLjava/time/LocalDate;->isLeapYear()Z+]Ljava/time/chrono/IsoChronology;Ljava/time/chrono/IsoChronology;
+HSPLjava/time/LocalDate;->isSupported(Ljava/time/temporal/TemporalField;)Z
+HSPLjava/time/LocalDate;->minus(JLjava/time/temporal/TemporalUnit;)Ljava/time/LocalDate;+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->minus(JLjava/time/temporal/TemporalUnit;)Ljava/time/temporal/Temporal;+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->of(III)Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->of(ILjava/time/Month;I)Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->ofEpochDay(J)Ljava/time/LocalDate;+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/LocalDate;->plus(JLjava/time/temporal/TemporalUnit;)Ljava/time/LocalDate;+]Ljava/time/LocalDate;Ljava/time/LocalDate;]Ljava/time/temporal/ChronoUnit;Ljava/time/temporal/ChronoUnit;
+HSPLjava/time/LocalDate;->plus(JLjava/time/temporal/TemporalUnit;)Ljava/time/temporal/Temporal;+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->plusDays(J)Ljava/time/LocalDate;+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->toEpochDay()J+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDate;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/time/LocalDate;->with(Ljava/time/temporal/TemporalAdjuster;)Ljava/time/LocalDate;+]Ljava/time/temporal/TemporalAdjuster;Ljava/time/temporal/TemporalAdjusters$$ExternalSyntheticLambda3;,Ljava/time/temporal/TemporalAdjusters$$ExternalSyntheticLambda1;
+HSPLjava/time/LocalDateTime;-><init>(Ljava/time/LocalDate;Ljava/time/LocalTime;)V
+HSPLjava/time/LocalDateTime;->atOffset(Ljava/time/ZoneOffset;)Ljava/time/OffsetDateTime;
+HSPLjava/time/LocalDateTime;->atZone(Ljava/time/ZoneId;)Ljava/time/ZonedDateTime;
+HSPLjava/time/LocalDateTime;->atZone(Ljava/time/ZoneId;)Ljava/time/chrono/ChronoZonedDateTime;+]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;
+HSPLjava/time/LocalDateTime;->compareTo0(Ljava/time/LocalDateTime;)I+]Ljava/time/LocalTime;Ljava/time/LocalTime;]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDateTime;->getDayOfMonth()I+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDateTime;->getHour()I+]Ljava/time/LocalTime;Ljava/time/LocalTime;
+HSPLjava/time/LocalDateTime;->getLong(Ljava/time/temporal/TemporalField;)J+]Ljava/time/LocalTime;Ljava/time/LocalTime;]Ljava/time/LocalDate;Ljava/time/LocalDate;]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;]Ljava/time/temporal/TemporalField;Ljava/time/temporal/JulianFields$Field;
+HSPLjava/time/LocalDateTime;->getMinute()I+]Ljava/time/LocalTime;Ljava/time/LocalTime;
+HSPLjava/time/LocalDateTime;->getMonthValue()I+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDateTime;->getNano()I+]Ljava/time/LocalTime;Ljava/time/LocalTime;
+HSPLjava/time/LocalDateTime;->getSecond()I+]Ljava/time/LocalTime;Ljava/time/LocalTime;
+HSPLjava/time/LocalDateTime;->getYear()I+]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDateTime;->isAfter(Ljava/time/chrono/ChronoLocalDateTime;)Z
+HSPLjava/time/LocalDateTime;->isBefore(Ljava/time/chrono/ChronoLocalDateTime;)Z
+HSPLjava/time/LocalDateTime;->isSupported(Ljava/time/temporal/TemporalField;)Z+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/LocalDateTime;->now()Ljava/time/LocalDateTime;
+HSPLjava/time/LocalDateTime;->of(Ljava/time/LocalDate;Ljava/time/LocalTime;)Ljava/time/LocalDateTime;
+HSPLjava/time/LocalDateTime;->ofEpochSecond(JILjava/time/ZoneOffset;)Ljava/time/LocalDateTime;+]Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/LocalDateTime;->ofInstant(Ljava/time/Instant;Ljava/time/ZoneId;)Ljava/time/LocalDateTime;+]Ljava/time/Instant;Ljava/time/Instant;]Ljava/time/ZoneId;Ljava/time/ZoneRegion;]Ljava/time/zone/ZoneRules;Ljava/time/zone/ZoneRules;
+HSPLjava/time/LocalDateTime;->plusSeconds(J)Ljava/time/LocalDateTime;
+HSPLjava/time/LocalDateTime;->plusWithOverflow(Ljava/time/LocalDate;JJJJI)Ljava/time/LocalDateTime;+]Ljava/time/LocalTime;Ljava/time/LocalTime;]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDateTime;->toLocalDate()Ljava/time/LocalDate;
+HSPLjava/time/LocalDateTime;->toLocalDate()Ljava/time/chrono/ChronoLocalDate;+]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;
+HSPLjava/time/LocalDateTime;->toLocalTime()Ljava/time/LocalTime;
+HSPLjava/time/LocalDateTime;->toString()Ljava/lang/String;+]Ljava/time/LocalTime;Ljava/time/LocalTime;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/LocalDateTime;->with(Ljava/time/LocalDate;Ljava/time/LocalTime;)Ljava/time/LocalDateTime;
+HSPLjava/time/LocalTime$1;-><clinit>()V
+HSPLjava/time/LocalTime;-><init>(IIII)V
+HSPLjava/time/LocalTime;->create(IIII)Ljava/time/LocalTime;
+HSPLjava/time/LocalTime;->get0(Ljava/time/temporal/TemporalField;)I+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/LocalTime;->getHour()I
+HSPLjava/time/LocalTime;->getLong(Ljava/time/temporal/TemporalField;)J
+HSPLjava/time/LocalTime;->getMinute()I
+HSPLjava/time/LocalTime;->getNano()I
+HSPLjava/time/LocalTime;->getSecond()I
+HSPLjava/time/LocalTime;->isSupported(Ljava/time/temporal/TemporalField;)Z+]Ljava/time/temporal/TemporalField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/LocalTime;->of(IIII)Ljava/time/LocalTime;+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/LocalTime;->ofNanoOfDay(J)Ljava/time/LocalTime;+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/LocalTime;->ofSecondOfDay(J)Ljava/time/LocalTime;+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/LocalTime;->toNanoOfDay()J
+HSPLjava/time/LocalTime;->toSecondOfDay()I
+HSPLjava/time/LocalTime;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/time/Month$1;-><clinit>()V
+HSPLjava/time/Month;->getValue()I
+HSPLjava/time/Month;->length(Z)I+]Ljava/time/Month;Ljava/time/Month;
+HSPLjava/time/Month;->maxLength()I
+HSPLjava/time/Month;->of(I)Ljava/time/Month;
+HSPLjava/time/Month;->plus(J)Ljava/time/Month;
+HSPLjava/time/Month;->values()[Ljava/time/Month;
+HSPLjava/time/OffsetDateTime;-><clinit>()V
+HSPLjava/time/OffsetDateTime;-><init>(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;)V
+HSPLjava/time/OffsetDateTime;->getYear()I
+HSPLjava/time/OffsetDateTime;->of(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;)Ljava/time/OffsetDateTime;
+HSPLjava/time/OffsetDateTime;->ofInstant(Ljava/time/Instant;Ljava/time/ZoneId;)Ljava/time/OffsetDateTime;+]Ljava/time/Instant;Ljava/time/Instant;]Ljava/time/ZoneId;Ljava/time/ZoneOffset;]Ljava/time/zone/ZoneRules;Ljava/time/zone/ZoneRules;
+HSPLjava/time/OffsetDateTime;->toLocalDateTime()Ljava/time/LocalDateTime;
+HSPLjava/time/Period;->isZero()Z
+HSPLjava/time/ZoneId;-><init>()V+]Ljava/lang/Object;Ljava/time/ZoneRegion;,Ljava/time/ZoneOffset;
+HSPLjava/time/ZoneId;->equals(Ljava/lang/Object;)Z+]Ljava/time/ZoneId;Ljava/time/ZoneRegion;
+HSPLjava/time/ZoneId;->from(Ljava/time/temporal/TemporalAccessor;)Ljava/time/ZoneId;+]Ljava/time/temporal/TemporalAccessor;Ljava/time/format/Parsed;
+HSPLjava/time/ZoneId;->of(Ljava/lang/String;)Ljava/time/ZoneId;
+HSPLjava/time/ZoneId;->of(Ljava/lang/String;Ljava/util/Map;)Ljava/time/ZoneId;+]Ljava/util/Map;Ljava/util/Collections$UnmodifiableMap;
+HSPLjava/time/ZoneId;->of(Ljava/lang/String;Z)Ljava/time/ZoneId;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/time/ZoneId;->systemDefault()Ljava/time/ZoneId;+]Ljava/util/TimeZone;missing_types
+HSPLjava/time/ZoneId;->toString()Ljava/lang/String;+]Ljava/time/ZoneId;Ljava/time/ZoneRegion;
+HSPLjava/time/ZoneOffset;-><init>(I)V
+HSPLjava/time/ZoneOffset;->buildId(I)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/time/ZoneOffset;->equals(Ljava/lang/Object;)Z
+HSPLjava/time/ZoneOffset;->getId()Ljava/lang/String;
+HSPLjava/time/ZoneOffset;->getRules()Ljava/time/zone/ZoneRules;
+HSPLjava/time/ZoneOffset;->getTotalSeconds()I
+HSPLjava/time/ZoneOffset;->ofTotalSeconds(I)Ljava/time/ZoneOffset;+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;
+HSPLjava/time/ZoneRegion;-><init>(Ljava/lang/String;Ljava/time/zone/ZoneRules;)V
+HSPLjava/time/ZoneRegion;->checkName(Ljava/lang/String;)V
+HSPLjava/time/ZoneRegion;->getId()Ljava/lang/String;
+HSPLjava/time/ZoneRegion;->getRules()Ljava/time/zone/ZoneRules;
+HSPLjava/time/ZoneRegion;->ofId(Ljava/lang/String;Z)Ljava/time/ZoneRegion;
+HSPLjava/time/ZonedDateTime$1;-><clinit>()V
+HSPLjava/time/ZonedDateTime;-><init>(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;Ljava/time/ZoneId;)V
+HSPLjava/time/ZonedDateTime;->create(JILjava/time/ZoneId;)Ljava/time/ZonedDateTime;+]Ljava/time/ZoneId;Ljava/time/ZoneRegion;,Ljava/time/ZoneOffset;]Ljava/time/zone/ZoneRules;Ljava/time/zone/ZoneRules;
+HSPLjava/time/ZonedDateTime;->from(Ljava/time/temporal/TemporalAccessor;)Ljava/time/ZonedDateTime;+]Ljava/time/temporal/TemporalAccessor;Ljava/time/format/Parsed;
+HSPLjava/time/ZonedDateTime;->getLong(Ljava/time/temporal/TemporalField;)J+]Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;]Ljava/time/ZonedDateTime;Ljava/time/ZonedDateTime;]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/ZonedDateTime;->getOffset()Ljava/time/ZoneOffset;
+HSPLjava/time/ZonedDateTime;->getZone()Ljava/time/ZoneId;
+HSPLjava/time/ZonedDateTime;->of(Ljava/time/LocalDateTime;Ljava/time/ZoneId;)Ljava/time/ZonedDateTime;
+HSPLjava/time/ZonedDateTime;->ofInstant(Ljava/time/Instant;Ljava/time/ZoneId;)Ljava/time/ZonedDateTime;+]Ljava/time/Instant;Ljava/time/Instant;
+HSPLjava/time/ZonedDateTime;->ofLocal(Ljava/time/LocalDateTime;Ljava/time/ZoneId;Ljava/time/ZoneOffset;)Ljava/time/ZonedDateTime;+]Ljava/time/ZoneId;Ljava/time/ZoneRegion;]Ljava/util/List;Ljava/util/Collections$SingletonList;,Ljava/util/Arrays$ArrayList;,Ljava/util/Collections$EmptyList;]Ljava/time/zone/ZoneRules;Ljava/time/zone/ZoneRules;]Ljava/time/Duration;Ljava/time/Duration;]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;]Ljava/time/zone/ZoneOffsetTransition;Ljava/time/zone/ZoneOffsetTransition;
+HSPLjava/time/ZonedDateTime;->query(Ljava/time/temporal/TemporalQuery;)Ljava/lang/Object;
+HSPLjava/time/ZonedDateTime;->toLocalDate()Ljava/time/LocalDate;+]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;
+HSPLjava/time/ZonedDateTime;->toLocalDate()Ljava/time/chrono/ChronoLocalDate;+]Ljava/time/ZonedDateTime;Ljava/time/ZonedDateTime;
+HSPLjava/time/ZonedDateTime;->toLocalTime()Ljava/time/LocalTime;+]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;
+HSPLjava/time/chrono/AbstractChronology;->equals(Ljava/lang/Object;)Z
+HSPLjava/time/chrono/AbstractChronology;->resolveDate(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;+]Ljava/time/chrono/AbstractChronology;Ljava/time/chrono/IsoChronology;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/chrono/ChronoLocalDate;->isSupported(Ljava/time/temporal/TemporalField;)Z+]Ljava/time/temporal/TemporalField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/chrono/ChronoLocalDateTime;->toEpochSecond(Ljava/time/ZoneOffset;)J+]Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;]Ljava/time/LocalTime;Ljava/time/LocalTime;]Ljava/time/chrono/ChronoLocalDateTime;Ljava/time/LocalDateTime;]Ljava/time/chrono/ChronoLocalDate;Ljava/time/LocalDate;
+HSPLjava/time/chrono/ChronoZonedDateTime;->getChronology()Ljava/time/chrono/Chronology;+]Ljava/time/chrono/ChronoZonedDateTime;Ljava/time/ZonedDateTime;]Ljava/time/chrono/ChronoLocalDate;Ljava/time/LocalDate;
+HSPLjava/time/chrono/ChronoZonedDateTime;->query(Ljava/time/temporal/TemporalQuery;)Ljava/lang/Object;+]Ljava/time/chrono/ChronoZonedDateTime;Ljava/time/ZonedDateTime;]Ljava/time/temporal/TemporalQuery;Ljava/time/format/DateTimeFormatterBuilder$$ExternalSyntheticLambda0;
+HSPLjava/time/chrono/ChronoZonedDateTime;->toEpochSecond()J+]Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;]Ljava/time/LocalTime;Ljava/time/LocalTime;]Ljava/time/chrono/ChronoZonedDateTime;Ljava/time/ZonedDateTime;]Ljava/time/chrono/ChronoLocalDate;Ljava/time/LocalDate;
+HSPLjava/time/chrono/IsoChronology;->isLeapYear(J)Z
+HSPLjava/time/chrono/IsoChronology;->resolveDate(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/LocalDate;
+HSPLjava/time/chrono/IsoChronology;->resolveDate(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;+]Ljava/time/chrono/IsoChronology;Ljava/time/chrono/IsoChronology;
+HSPLjava/time/chrono/IsoChronology;->resolveProlepticMonth(Ljava/util/Map;Ljava/time/format/ResolverStyle;)V+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/chrono/IsoChronology;->resolveYMD(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/LocalDate;+]Ljava/lang/Long;Ljava/lang/Long;]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/chrono/IsoChronology;->resolveYMD(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;+]Ljava/time/chrono/IsoChronology;Ljava/time/chrono/IsoChronology;
+HSPLjava/time/chrono/IsoChronology;->resolveYearOfEra(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/LocalDate;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/chrono/IsoChronology;->resolveYearOfEra(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;+]Ljava/time/chrono/IsoChronology;Ljava/time/chrono/IsoChronology;
+HSPLjava/time/format/DateTimeFormatter;-><init>(Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;Ljava/util/Locale;Ljava/time/format/DecimalStyle;Ljava/time/format/ResolverStyle;Ljava/util/Set;Ljava/time/chrono/Chronology;Ljava/time/ZoneId;)V
+HSPLjava/time/format/DateTimeFormatter;->format(Ljava/time/temporal/TemporalAccessor;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/time/format/DateTimeFormatter;Ljava/time/format/DateTimeFormatter;
+HSPLjava/time/format/DateTimeFormatter;->formatTo(Ljava/time/temporal/TemporalAccessor;Ljava/lang/Appendable;)V+]Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;
+HSPLjava/time/format/DateTimeFormatter;->getChronology()Ljava/time/chrono/Chronology;
+HSPLjava/time/format/DateTimeFormatter;->getDecimalStyle()Ljava/time/format/DecimalStyle;
+HSPLjava/time/format/DateTimeFormatter;->getZone()Ljava/time/ZoneId;
+HSPLjava/time/format/DateTimeFormatter;->parse(Ljava/lang/CharSequence;Ljava/time/temporal/TemporalQuery;)Ljava/lang/Object;+]Ljava/time/temporal/TemporalAccessor;Ljava/time/format/Parsed;
+HSPLjava/time/format/DateTimeFormatter;->parseResolved0(Ljava/lang/CharSequence;Ljava/text/ParsePosition;)Ljava/time/temporal/TemporalAccessor;+]Ljava/text/ParsePosition;Ljava/text/ParsePosition;]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;]Ljava/lang/CharSequence;Ljava/lang/String;
+HSPLjava/time/format/DateTimeFormatter;->parseUnresolved0(Ljava/lang/CharSequence;Ljava/text/ParsePosition;)Ljava/time/format/DateTimeParseContext;+]Ljava/text/ParsePosition;Ljava/text/ParsePosition;]Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;
+HSPLjava/time/format/DateTimeFormatterBuilder$3;-><clinit>()V
+HSPLjava/time/format/DateTimeFormatterBuilder$CharLiteralPrinterParser;-><init>(C)V
+HSPLjava/time/format/DateTimeFormatterBuilder$CharLiteralPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/time/format/DateTimeFormatterBuilder$CharLiteralPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I+]Ljava/lang/CharSequence;Ljava/lang/String;]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;
+HSPLjava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;-><init>(Ljava/util/List;Z)V+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLjava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;-><init>([Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;Z)V
+HSPLjava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;megamorphic_types]Ljava/time/format/DateTimePrintContext;Ljava/time/format/DateTimePrintContext;
+HSPLjava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I+]Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;megamorphic_types]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;
+HSPLjava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;-><init>(Ljava/time/temporal/TemporalField;IIZ)V+]Ljava/time/temporal/TemporalField;Ljava/time/temporal/ChronoField;]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->convertFromFraction(Ljava/math/BigDecimal;)J+]Ljava/time/temporal/TemporalField;Ljava/time/temporal/ChronoField;]Ljava/math/BigDecimal;Ljava/math/BigDecimal;]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->convertToFraction(J)Ljava/math/BigDecimal;+]Ljava/time/temporal/TemporalField;Ljava/time/temporal/ChronoField;]Ljava/math/BigDecimal;Ljava/math/BigDecimal;]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/time/format/DateTimePrintContext;Ljava/time/format/DateTimePrintContext;]Ljava/lang/Long;Ljava/lang/Long;]Ljava/math/BigDecimal;Ljava/math/BigDecimal;]Ljava/time/format/DecimalStyle;Ljava/time/format/DecimalStyle;
+HSPLjava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I+]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;]Ljava/math/BigDecimal;Ljava/math/BigDecimal;]Ljava/lang/CharSequence;Ljava/lang/String;]Ljava/time/format/DecimalStyle;Ljava/time/format/DecimalStyle;
+HSPLjava/time/format/DateTimeFormatterBuilder$InstantPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;]Ljava/time/temporal/TemporalAccessor;Ljava/time/Instant;]Ljava/time/format/DateTimePrintContext;Ljava/time/format/DateTimePrintContext;]Ljava/lang/Long;Ljava/lang/Long;]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;-><init>(Ljava/time/temporal/TemporalField;IILjava/time/format/SignStyle;)V
+HSPLjava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/time/format/DateTimePrintContext;Ljava/time/format/DateTimePrintContext;]Ljava/lang/Long;Ljava/lang/Long;]Ljava/time/format/SignStyle;Ljava/time/format/SignStyle;]Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;]Ljava/time/format/DecimalStyle;Ljava/time/format/DecimalStyle;
+HSPLjava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->getValue(Ljava/time/format/DateTimePrintContext;J)J
+HSPLjava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I+]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;]Ljava/time/format/SignStyle;Ljava/time/format/SignStyle;]Ljava/lang/CharSequence;Ljava/lang/String;]Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;]Ljava/time/format/DecimalStyle;Ljava/time/format/DecimalStyle;
+HSPLjava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->setValue(Ljava/time/format/DateTimeParseContext;JII)I+]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;
+HSPLjava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/time/format/DateTimePrintContext;Ljava/time/format/DateTimePrintContext;]Ljava/lang/Long;Ljava/lang/Long;
+HSPLjava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I+]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;]Ljava/lang/CharSequence;Ljava/lang/String;
+HSPLjava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->parseNumber([IILjava/lang/CharSequence;Z)Z+]Ljava/lang/CharSequence;Ljava/lang/String;
+HSPLjava/time/format/DateTimeFormatterBuilder$SettingsParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+HSPLjava/time/format/DateTimeFormatterBuilder$SettingsParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I+]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;]Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;
+HSPLjava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/time/ZoneId;Ljava/time/ZoneRegion;]Ljava/time/format/DateTimePrintContext;Ljava/time/format/DateTimePrintContext;
+HSPLjava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->getTree(Ljava/time/format/DateTimeParseContext;)Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;+]Ljava/util/Map$Entry;Ljava/util/AbstractMap$SimpleImmutableEntry;]Ljava/lang/Integer;Ljava/lang/Integer;]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLjava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I+]Ljava/text/ParsePosition;Ljava/text/ParsePosition;]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;]Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;]Ljava/lang/CharSequence;Ljava/lang/String;]Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;
+HSPLjava/time/format/DateTimeFormatterBuilder;-><init>()V
+HSPLjava/time/format/DateTimeFormatterBuilder;->appendFraction(Ljava/time/temporal/TemporalField;IIZ)Ljava/time/format/DateTimeFormatterBuilder;
+HSPLjava/time/format/DateTimeFormatterBuilder;->appendInternal(Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;)I+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLjava/time/format/DateTimeFormatterBuilder;->appendLiteral(C)Ljava/time/format/DateTimeFormatterBuilder;
+HSPLjava/time/format/DateTimeFormatterBuilder;->appendValue(Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;)Ljava/time/format/DateTimeFormatterBuilder;
+HSPLjava/time/format/DateTimeFormatterBuilder;->appendValue(Ljava/time/temporal/TemporalField;I)Ljava/time/format/DateTimeFormatterBuilder;
+HSPLjava/time/format/DateTimeFormatterBuilder;->toFormatter()Ljava/time/format/DateTimeFormatter;+]Ljava/time/format/DateTimeFormatterBuilder;Ljava/time/format/DateTimeFormatterBuilder;
+HSPLjava/time/format/DateTimeFormatterBuilder;->toFormatter(Ljava/util/Locale;)Ljava/time/format/DateTimeFormatter;
+HSPLjava/time/format/DateTimeFormatterBuilder;->toFormatter(Ljava/util/Locale;Ljava/time/format/ResolverStyle;Ljava/time/chrono/Chronology;)Ljava/time/format/DateTimeFormatter;
+HSPLjava/time/format/DateTimeParseContext;-><init>(Ljava/time/format/DateTimeFormatter;)V+]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/time/format/DateTimeParseContext;->charEquals(CC)Z+]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;
+HSPLjava/time/format/DateTimeParseContext;->currentParsed()Ljava/time/format/Parsed;+]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/time/format/DateTimeParseContext;->endOptional(Z)V+]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/time/format/DateTimeParseContext;->getDecimalStyle()Ljava/time/format/DecimalStyle;+]Ljava/time/format/DateTimeFormatter;Ljava/time/format/DateTimeFormatter;
+HSPLjava/time/format/DateTimeParseContext;->getEffectiveChronology()Ljava/time/chrono/Chronology;+]Ljava/time/format/DateTimeFormatter;Ljava/time/format/DateTimeFormatter;
+HSPLjava/time/format/DateTimeParseContext;->isCaseSensitive()Z
+HSPLjava/time/format/DateTimeParseContext;->isStrict()Z
+HSPLjava/time/format/DateTimeParseContext;->setCaseSensitive(Z)V
+HSPLjava/time/format/DateTimeParseContext;->setParsed(Ljava/time/ZoneId;)V
+HSPLjava/time/format/DateTimeParseContext;->setParsedField(Ljava/time/temporal/TemporalField;JII)I+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/format/DateTimeParseContext;->startOptional()V+]Ljava/time/format/Parsed;Ljava/time/format/Parsed;]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/time/format/DateTimeParseContext;->subSequenceEquals(Ljava/lang/CharSequence;ILjava/lang/CharSequence;II)Z+]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;]Ljava/lang/CharSequence;Ljava/lang/String;
+HSPLjava/time/format/DateTimeParseContext;->toResolved(Ljava/time/format/ResolverStyle;Ljava/util/Set;)Ljava/time/temporal/TemporalAccessor;+]Ljava/time/format/Parsed;Ljava/time/format/Parsed;]Ljava/time/format/DateTimeParseContext;Ljava/time/format/DateTimeParseContext;]Ljava/time/format/DateTimeFormatter;Ljava/time/format/DateTimeFormatter;
+HSPLjava/time/format/DateTimePrintContext;-><init>(Ljava/time/temporal/TemporalAccessor;Ljava/time/format/DateTimeFormatter;)V
+HSPLjava/time/format/DateTimePrintContext;->adjust(Ljava/time/temporal/TemporalAccessor;Ljava/time/format/DateTimeFormatter;)Ljava/time/temporal/TemporalAccessor;
+HSPLjava/time/format/DateTimePrintContext;->getValue(Ljava/time/temporal/TemporalField;)Ljava/lang/Long;+]Ljava/time/temporal/TemporalAccessor;Ljava/time/ZonedDateTime;,Ljava/time/Instant;
+HSPLjava/time/format/DecimalStyle;->convertNumberToI18N(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/time/format/DecimalStyle;->convertToDigit(C)I
+HSPLjava/time/format/DecimalStyle;->getDecimalSeparator()C
+HSPLjava/time/format/DecimalStyle;->getNegativeSign()C
+HSPLjava/time/format/DecimalStyle;->getPositiveSign()C
+HSPLjava/time/format/DecimalStyle;->getZeroDigit()C
+HSPLjava/time/format/Parsed;-><init>()V
+HSPLjava/time/format/Parsed;->copy()Ljava/time/format/Parsed;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/format/Parsed;->crossCheck()V+]Ljava/time/chrono/ChronoLocalDate;Ljava/time/LocalDate;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/format/Parsed;->crossCheck(Ljava/time/temporal/TemporalAccessor;)V+]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;]Ljava/time/temporal/TemporalAccessor;Ljava/time/LocalTime;,Ljava/time/LocalDateTime;,Ljava/time/LocalDate;]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;
+HSPLjava/time/format/Parsed;->getLong(Ljava/time/temporal/TemporalField;)J+]Ljava/time/LocalTime;Ljava/time/LocalTime;]Ljava/lang/Long;Ljava/lang/Long;]Ljava/time/chrono/ChronoLocalDate;Ljava/time/LocalDate;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/format/Parsed;->isSupported(Ljava/time/temporal/TemporalField;)Z+]Ljava/time/LocalTime;Ljava/time/LocalTime;]Ljava/time/chrono/ChronoLocalDate;Ljava/time/LocalDate;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/format/Parsed;->query(Ljava/time/temporal/TemporalQuery;)Ljava/lang/Object;+]Ljava/time/temporal/TemporalQuery;Ljava/time/temporal/TemporalQueries$$ExternalSyntheticLambda4;,Ljava/time/LocalDateTime$$ExternalSyntheticLambda0;,Ljava/time/Instant$$ExternalSyntheticLambda0;,Ljava/time/ZonedDateTime$$ExternalSyntheticLambda0;
+HSPLjava/time/format/Parsed;->resolve(Ljava/time/format/ResolverStyle;Ljava/util/Set;)Ljava/time/temporal/TemporalAccessor;
+HSPLjava/time/format/Parsed;->resolveDateFields()V+]Ljava/time/chrono/Chronology;Ljava/time/chrono/IsoChronology;
+HSPLjava/time/format/Parsed;->resolveFields()V+]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;]Ljava/time/temporal/TemporalField;Ljava/time/temporal/ChronoField;]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;
+HSPLjava/time/format/Parsed;->resolveFractional()V+]Ljava/lang/Long;Ljava/lang/Long;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/format/Parsed;->resolveInstant()V+]Ljava/time/chrono/ChronoLocalDateTime;Ljava/time/LocalDateTime;]Ljava/time/chrono/ChronoZonedDateTime;Ljava/time/ZonedDateTime;]Ljava/time/chrono/ChronoLocalDate;Ljava/time/LocalDate;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/format/Parsed;->resolveInstantFields()V+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/format/Parsed;->resolvePeriod()V+]Ljava/time/Period;Ljava/time/Period;
+HSPLjava/time/format/Parsed;->resolveTime(JJJJ)V+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/format/Parsed;->resolveTimeFields()V+]Ljava/lang/Long;Ljava/lang/Long;]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/time/format/Parsed;->resolveTimeLenient()V+]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;]Ljava/time/temporal/TemporalField;Ljava/time/temporal/ChronoField;]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;]Ljava/lang/Long;Ljava/lang/Long;]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/format/Parsed;->updateCheckConflict(Ljava/time/LocalTime;Ljava/time/Period;)V
+HSPLjava/time/format/Parsed;->updateCheckConflict(Ljava/time/chrono/ChronoLocalDate;)V+]Ljava/time/chrono/Chronology;Ljava/time/chrono/IsoChronology;]Ljava/time/chrono/ChronoLocalDate;Ljava/time/LocalDate;
+HSPLjava/time/format/SignStyle;->values()[Ljava/time/format/SignStyle;
+HSPLjava/time/temporal/ChronoField;->checkValidIntValue(J)I+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/temporal/ChronoField;->checkValidValue(J)J+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/temporal/ChronoField;->isDateBased()Z+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/temporal/ChronoField;->isTimeBased()Z+]Ljava/time/temporal/ChronoField;Ljava/time/temporal/ChronoField;
+HSPLjava/time/temporal/ChronoField;->range()Ljava/time/temporal/ValueRange;
+HSPLjava/time/temporal/ChronoField;->values()[Ljava/time/temporal/ChronoField;
+HSPLjava/time/temporal/ChronoUnit;->getDuration()Ljava/time/Duration;
+HSPLjava/time/temporal/ChronoUnit;->values()[Ljava/time/temporal/ChronoUnit;
+HSPLjava/time/temporal/TemporalAccessor;->get(Ljava/time/temporal/TemporalField;)I+]Ljava/time/temporal/TemporalAccessor;Ljava/time/format/Parsed;]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/temporal/TemporalAccessor;->range(Ljava/time/temporal/TemporalField;)Ljava/time/temporal/ValueRange;+]Ljava/time/temporal/TemporalField;Ljava/time/temporal/ChronoField;]Ljava/time/temporal/TemporalAccessor;Ljava/time/format/Parsed;
+HSPLjava/time/temporal/TemporalAdjusters$$ExternalSyntheticLambda1;-><init>(I)V
+HSPLjava/time/temporal/TemporalAdjusters$$ExternalSyntheticLambda1;->adjustInto(Ljava/time/temporal/Temporal;)Ljava/time/temporal/Temporal;
+HSPLjava/time/temporal/TemporalAdjusters;->lambda$nextOrSame$10(ILjava/time/temporal/Temporal;)Ljava/time/temporal/Temporal;+]Ljava/time/temporal/Temporal;Ljava/time/LocalDate;
+HSPLjava/time/temporal/TemporalAdjusters;->lambda$previousOrSame$12(ILjava/time/temporal/Temporal;)Ljava/time/temporal/Temporal;+]Ljava/time/temporal/Temporal;Ljava/time/LocalDate;
+HSPLjava/time/temporal/TemporalAdjusters;->nextOrSame(Ljava/time/DayOfWeek;)Ljava/time/temporal/TemporalAdjuster;+]Ljava/time/DayOfWeek;Ljava/time/DayOfWeek;
+HSPLjava/time/temporal/TemporalAdjusters;->previousOrSame(Ljava/time/DayOfWeek;)Ljava/time/temporal/TemporalAdjuster;+]Ljava/time/DayOfWeek;Ljava/time/DayOfWeek;
+HSPLjava/time/temporal/TemporalField;->resolve(Ljava/util/Map;Ljava/time/temporal/TemporalAccessor;Ljava/time/format/ResolverStyle;)Ljava/time/temporal/TemporalAccessor;
+HSPLjava/time/temporal/TemporalQueries;->chronology()Ljava/time/temporal/TemporalQuery;
+HSPLjava/time/temporal/TemporalQueries;->lambda$static$4(Ljava/time/temporal/TemporalAccessor;)Ljava/time/ZoneId;+]Ljava/time/temporal/TemporalAccessor;Ljava/time/format/Parsed;
+HSPLjava/time/temporal/TemporalQueries;->localDate()Ljava/time/temporal/TemporalQuery;
+HSPLjava/time/temporal/TemporalQueries;->localTime()Ljava/time/temporal/TemporalQuery;
+HSPLjava/time/temporal/TemporalQueries;->offset()Ljava/time/temporal/TemporalQuery;
+HSPLjava/time/temporal/TemporalQueries;->precision()Ljava/time/temporal/TemporalQuery;
+HSPLjava/time/temporal/TemporalQueries;->zone()Ljava/time/temporal/TemporalQuery;
+HSPLjava/time/temporal/TemporalQueries;->zoneId()Ljava/time/temporal/TemporalQuery;
+HSPLjava/time/temporal/ValueRange;->checkValidIntValue(JLjava/time/temporal/TemporalField;)I+]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/temporal/ValueRange;->checkValidValue(JLjava/time/temporal/TemporalField;)J+]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/temporal/ValueRange;->getMaximum()J
+HSPLjava/time/temporal/ValueRange;->getMinimum()J
+HSPLjava/time/temporal/ValueRange;->isFixed()Z
+HSPLjava/time/temporal/ValueRange;->isIntValue()Z+]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/temporal/ValueRange;->isValidIntValue(J)Z+]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/temporal/ValueRange;->isValidValue(J)Z+]Ljava/time/temporal/ValueRange;Ljava/time/temporal/ValueRange;
+HSPLjava/time/zone/IcuZoneRulesProvider$ZoneRulesCache;->create(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/time/zone/IcuZoneRulesProvider$ZoneRulesCache;->create(Ljava/lang/String;)Ljava/time/zone/ZoneRules;
+HSPLjava/time/zone/IcuZoneRulesProvider;->generateZoneRules(Ljava/lang/String;)Ljava/time/zone/ZoneRules;
+HSPLjava/time/zone/IcuZoneRulesProvider;->provideRules(Ljava/lang/String;Z)Ljava/time/zone/ZoneRules;+]Llibcore/util/BasicLruCache;Ljava/time/zone/IcuZoneRulesProvider$ZoneRulesCache;
+HSPLjava/time/zone/ZoneOffsetTransition;-><init>(JLjava/time/ZoneOffset;Ljava/time/ZoneOffset;)V
+HSPLjava/time/zone/ZoneOffsetTransition;-><init>(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;)V
+HSPLjava/time/zone/ZoneOffsetTransition;->getDateTimeAfter()Ljava/time/LocalDateTime;+]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;
+HSPLjava/time/zone/ZoneOffsetTransition;->getDateTimeBefore()Ljava/time/LocalDateTime;
+HSPLjava/time/zone/ZoneOffsetTransition;->getDurationSeconds()I+]Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;]Ljava/time/zone/ZoneOffsetTransition;Ljava/time/zone/ZoneOffsetTransition;
+HSPLjava/time/zone/ZoneOffsetTransition;->getOffsetAfter()Ljava/time/ZoneOffset;
+HSPLjava/time/zone/ZoneOffsetTransition;->getOffsetBefore()Ljava/time/ZoneOffset;
+HSPLjava/time/zone/ZoneOffsetTransition;->isGap()Z+]Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;]Ljava/time/zone/ZoneOffsetTransition;Ljava/time/zone/ZoneOffsetTransition;
+HSPLjava/time/zone/ZoneOffsetTransition;->of(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;)Ljava/time/zone/ZoneOffsetTransition;+]Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;
+HSPLjava/time/zone/ZoneOffsetTransition;->toEpochSecond()J+]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;
+HSPLjava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;->createDateTime(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;)Ljava/time/LocalDateTime;+]Ljava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;Ljava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;]Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;
+HSPLjava/time/zone/ZoneOffsetTransitionRule;-><init>(Ljava/time/Month;ILjava/time/DayOfWeek;Ljava/time/LocalTime;ZLjava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;)V
+HSPLjava/time/zone/ZoneOffsetTransitionRule;->createTransition(I)Ljava/time/zone/ZoneOffsetTransition;+]Ljava/time/LocalDate;Ljava/time/LocalDate;]Ljava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;Ljava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;]Ljava/time/Month;Ljava/time/Month;]Ljava/time/chrono/IsoChronology;Ljava/time/chrono/IsoChronology;
+HSPLjava/time/zone/ZoneOffsetTransitionRule;->getOffsetAfter()Ljava/time/ZoneOffset;
+HSPLjava/time/zone/ZoneOffsetTransitionRule;->of(Ljava/time/Month;ILjava/time/DayOfWeek;Ljava/time/LocalTime;ZLjava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;)Ljava/time/zone/ZoneOffsetTransitionRule;
+HSPLjava/time/zone/ZoneRules;-><init>(Ljava/time/ZoneOffset;)V
+HSPLjava/time/zone/ZoneRules;-><init>(Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;Ljava/util/List;Ljava/util/List;Ljava/util/List;)V+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/time/zone/ZoneOffsetTransition;Ljava/time/zone/ZoneOffsetTransition;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLjava/time/zone/ZoneRules;->findOffsetInfo(Ljava/time/LocalDateTime;Ljava/time/zone/ZoneOffsetTransition;)Ljava/lang/Object;+]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;]Ljava/time/zone/ZoneOffsetTransition;Ljava/time/zone/ZoneOffsetTransition;
+HSPLjava/time/zone/ZoneRules;->findTransitionArray(I)[Ljava/time/zone/ZoneOffsetTransition;+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/time/zone/ZoneOffsetTransitionRule;Ljava/time/zone/ZoneOffsetTransitionRule;
+HSPLjava/time/zone/ZoneRules;->findYear(JLjava/time/ZoneOffset;)I+]Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;]Ljava/time/LocalDate;Ljava/time/LocalDate;
+HSPLjava/time/zone/ZoneRules;->getOffset(Ljava/time/Instant;)Ljava/time/ZoneOffset;+]Ljava/time/Instant;Ljava/time/Instant;]Ljava/time/zone/ZoneOffsetTransition;Ljava/time/zone/ZoneOffsetTransition;
+HSPLjava/time/zone/ZoneRules;->getOffsetInfo(Ljava/time/LocalDateTime;)Ljava/lang/Object;+]Ljava/time/LocalDateTime;Ljava/time/LocalDateTime;]Ljava/lang/Object;Ljava/time/ZoneOffset;]Ljava/time/zone/ZoneOffsetTransition;Ljava/time/zone/ZoneOffsetTransition;
+HSPLjava/time/zone/ZoneRules;->getValidOffsets(Ljava/time/LocalDateTime;)Ljava/util/List;+]Ljava/time/zone/ZoneOffsetTransition;Ljava/time/zone/ZoneOffsetTransition;
+HSPLjava/time/zone/ZoneRules;->of(Ljava/time/ZoneOffset;)Ljava/time/zone/ZoneRules;
+HSPLjava/time/zone/ZoneRules;->of(Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;Ljava/util/List;Ljava/util/List;Ljava/util/List;)Ljava/time/zone/ZoneRules;
+HSPLjava/time/zone/ZoneRulesProvider;->getAvailableZoneIds()Ljava/util/Set;+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/time/zone/ZoneRulesProvider;->getProvider(Ljava/lang/String;)Ljava/time/zone/ZoneRulesProvider;+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/time/zone/ZoneRulesProvider;->getRules(Ljava/lang/String;Z)Ljava/time/zone/ZoneRules;+]Ljava/time/zone/ZoneRulesProvider;Ljava/time/zone/IcuZoneRulesProvider;
+HSPLjava/util/AbstractCollection;-><init>()V
+HSPLjava/util/AbstractCollection;->addAll(Ljava/util/Collection;)Z+]Ljava/util/AbstractCollection;megamorphic_types]Ljava/util/Collection;megamorphic_types]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/AbstractCollection;->clear()V+]Ljava/util/AbstractCollection;Ljava/util/TreeMap$AscendingSubMap$AscendingEntrySetView;]Ljava/util/Iterator;Ljava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;
+HSPLjava/util/AbstractCollection;->contains(Ljava/lang/Object;)Z+]Ljava/util/AbstractCollection;missing_types]Ljava/lang/Object;missing_types]Ljava/util/Iterator;missing_types
+HSPLjava/util/AbstractCollection;->containsAll(Ljava/util/Collection;)Z+]Ljava/util/AbstractCollection;megamorphic_types]Ljava/util/Collection;megamorphic_types]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/AbstractCollection;->isEmpty()Z+]Ljava/util/AbstractCollection;megamorphic_types
+HSPLjava/util/AbstractCollection;->remove(Ljava/lang/Object;)Z+]Ljava/util/Iterator;missing_types]Ljava/util/AbstractCollection;missing_types
+HSPLjava/util/AbstractCollection;->removeAll(Ljava/util/Collection;)Z+]Ljava/util/AbstractCollection;missing_types]Ljava/util/Collection;Ljava/util/Collections$SingletonSet;,Ljava/util/ArrayList;,Ljava/util/Collections$UnmodifiableRandomAccessList;,Ljava/util/LinkedList;,Ljava/util/HashSet;,Ljava/util/Vector;]Ljava/util/Iterator;missing_types
+HSPLjava/util/AbstractCollection;->retainAll(Ljava/util/Collection;)Z+]Ljava/util/AbstractCollection;Ljava/util/LinkedHashSet;,Ljava/util/TreeSet;,Ljava/util/HashSet;,Ljava/util/WeakHashMap$KeySet;,Ljava/util/TreeMap$KeySet;,Ljava/util/HashMap$KeySet;,Ljava/util/LinkedHashMap$LinkedKeySet;]Ljava/util/Collection;megamorphic_types]Ljava/util/Iterator;Ljava/util/LinkedHashMap$LinkedKeyIterator;,Ljava/util/HashMap$KeyIterator;,Ljava/util/TreeMap$KeyIterator;,Ljava/util/WeakHashMap$KeyIterator;
+HSPLjava/util/AbstractCollection;->toArray()[Ljava/lang/Object;+]Ljava/util/AbstractCollection;megamorphic_types]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/AbstractCollection;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;+]Ljava/util/AbstractCollection;megamorphic_types]Ljava/lang/Object;megamorphic_types]Ljava/lang/Class;Ljava/lang/Class;]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/AbstractCollection;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/AbstractCollection;megamorphic_types]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/AbstractList$Itr;-><init>(Ljava/util/AbstractList;)V
+HSPLjava/util/AbstractList$Itr;-><init>(Ljava/util/AbstractList;Ljava/util/AbstractList$1;)V
+HSPLjava/util/AbstractList$Itr;->checkForComodification()V
+HSPLjava/util/AbstractList$Itr;->hasNext()Z+]Ljava/util/AbstractList;missing_types
+HSPLjava/util/AbstractList$Itr;->next()Ljava/lang/Object;+]Ljava/util/AbstractList$Itr;Ljava/util/AbstractList$Itr;,Ljava/util/AbstractList$ListItr;]Ljava/util/AbstractList;missing_types
+HSPLjava/util/AbstractList$ListItr;-><init>(Ljava/util/AbstractList;I)V
+HSPLjava/util/AbstractList$ListItr;->hasPrevious()Z
+HSPLjava/util/AbstractList$ListItr;->nextIndex()I
+HSPLjava/util/AbstractList$ListItr;->previous()Ljava/lang/Object;+]Ljava/util/AbstractList;missing_types]Ljava/util/AbstractList$ListItr;Ljava/util/AbstractList$ListItr;
+HSPLjava/util/AbstractList$ListItr;->previousIndex()I
+HSPLjava/util/AbstractList$RandomAccessSpliterator;-><init>(Ljava/util/List;)V
+HSPLjava/util/AbstractList$RandomAccessSpliterator;->characteristics()I
+HSPLjava/util/AbstractList$RandomAccessSpliterator;->checkAbstractListModCount(Ljava/util/AbstractList;I)V
+HSPLjava/util/AbstractList$RandomAccessSpliterator;->estimateSize()J
+HSPLjava/util/AbstractList$RandomAccessSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V+]Ljava/util/function/Consumer;megamorphic_types
+HSPLjava/util/AbstractList$RandomAccessSpliterator;->get(Ljava/util/List;I)Ljava/lang/Object;+]Ljava/util/List;missing_types
+HSPLjava/util/AbstractList$RandomAccessSpliterator;->getFence()I+]Ljava/util/List;missing_types
+HSPLjava/util/AbstractList$RandomAccessSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z+]Ljava/util/function/Consumer;megamorphic_types
+HSPLjava/util/AbstractList$RandomAccessSubList;-><init>(Ljava/util/AbstractList;II)V
+HSPLjava/util/AbstractList$SubList$1;-><init>(Ljava/util/AbstractList$SubList;I)V+]Ljava/util/AbstractList;missing_types
+HSPLjava/util/AbstractList$SubList$1;->hasNext()Z+]Ljava/util/AbstractList$SubList$1;Ljava/util/AbstractList$SubList$1;
+HSPLjava/util/AbstractList$SubList$1;->next()Ljava/lang/Object;+]Ljava/util/AbstractList$SubList$1;Ljava/util/AbstractList$SubList$1;]Ljava/util/ListIterator;Ljava/util/AbstractList$ListItr;
+HSPLjava/util/AbstractList$SubList$1;->nextIndex()I+]Ljava/util/ListIterator;Ljava/util/AbstractList$ListItr;
+HSPLjava/util/AbstractList$SubList;-><init>(Ljava/util/AbstractList;II)V
+HSPLjava/util/AbstractList$SubList;->access$100(Ljava/util/AbstractList$SubList;)I
+HSPLjava/util/AbstractList$SubList;->access$200(Ljava/util/AbstractList$SubList;)Ljava/util/AbstractList;
+HSPLjava/util/AbstractList$SubList;->checkForComodification()V
+HSPLjava/util/AbstractList$SubList;->get(I)Ljava/lang/Object;+]Ljava/util/AbstractList;missing_types
+HSPLjava/util/AbstractList$SubList;->iterator()Ljava/util/Iterator;+]Ljava/util/AbstractList$SubList;Ljava/util/AbstractList$SubList;,Ljava/util/AbstractList$RandomAccessSubList;
+HSPLjava/util/AbstractList$SubList;->listIterator(I)Ljava/util/ListIterator;
+HSPLjava/util/AbstractList$SubList;->rangeCheckForAdd(I)V
+HSPLjava/util/AbstractList$SubList;->size()I
+HSPLjava/util/AbstractList;-><init>()V
+HSPLjava/util/AbstractList;->add(Ljava/lang/Object;)Z+]Ljava/util/AbstractList;Ljava/util/ArrayList$SubList;
+HSPLjava/util/AbstractList;->clear()V+]Ljava/util/AbstractList;Ljava/util/ArrayList$SubList;,Ljava/util/Collections$EmptyList;,Ljava/util/AbstractList$SubList;,Ljava/util/AbstractList$RandomAccessSubList;
+HSPLjava/util/AbstractList;->equals(Ljava/lang/Object;)Z+]Ljava/util/ListIterator;megamorphic_types]Ljava/util/AbstractList;missing_types]Ljava/util/List;megamorphic_types]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/AbstractList;->hashCode()I+]Ljava/lang/Object;megamorphic_types]Ljava/util/AbstractList;missing_types]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/AbstractList;->indexOf(Ljava/lang/Object;)I+]Ljava/util/ListIterator;Ljava/util/ArrayList$SubList$1;,Ljava/util/AbstractList$ListItr;]Ljava/lang/Object;missing_types]Ljava/util/AbstractList;missing_types
+HSPLjava/util/AbstractList;->iterator()Ljava/util/Iterator;
+HSPLjava/util/AbstractList;->listIterator()Ljava/util/ListIterator;+]Ljava/util/AbstractList;megamorphic_types
+HSPLjava/util/AbstractList;->listIterator(I)Ljava/util/ListIterator;
+HSPLjava/util/AbstractList;->rangeCheckForAdd(I)V+]Ljava/util/AbstractList;missing_types
+HSPLjava/util/AbstractList;->subList(II)Ljava/util/List;+]Ljava/util/AbstractList;missing_types
+HSPLjava/util/AbstractList;->subListRangeCheck(III)V
+HSPLjava/util/AbstractMap$2$1;-><init>(Ljava/util/AbstractMap$2;)V+]Ljava/util/AbstractMap;missing_types]Ljava/util/Set;missing_types
+HSPLjava/util/AbstractMap$2$1;->hasNext()Z+]Ljava/util/Iterator;missing_types
+HSPLjava/util/AbstractMap$2$1;->next()Ljava/lang/Object;+]Ljava/util/Map$Entry;missing_types]Ljava/util/Iterator;missing_types
+HSPLjava/util/AbstractMap$2;-><init>(Ljava/util/AbstractMap;)V
+HSPLjava/util/AbstractMap$2;->iterator()Ljava/util/Iterator;
+HSPLjava/util/AbstractMap$SimpleEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
+HSPLjava/util/AbstractMap$SimpleEntry;->getKey()Ljava/lang/Object;
+HSPLjava/util/AbstractMap$SimpleEntry;->getValue()Ljava/lang/Object;
+HSPLjava/util/AbstractMap$SimpleImmutableEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
+HSPLjava/util/AbstractMap$SimpleImmutableEntry;-><init>(Ljava/util/Map$Entry;)V+]Ljava/util/Map$Entry;Ljava/util/TreeMap$TreeMapEntry;,Ljava/util/AbstractMap$SimpleImmutableEntry;
+HSPLjava/util/AbstractMap$SimpleImmutableEntry;->equals(Ljava/lang/Object;)Z+]Ljava/util/Map$Entry;Ljava/util/AbstractMap$SimpleImmutableEntry;
+HSPLjava/util/AbstractMap$SimpleImmutableEntry;->getKey()Ljava/lang/Object;
+HSPLjava/util/AbstractMap$SimpleImmutableEntry;->getValue()Ljava/lang/Object;
+HSPLjava/util/AbstractMap$SimpleImmutableEntry;->hashCode()I+]Ljava/lang/Object;missing_types
+HSPLjava/util/AbstractMap;-><init>()V
+HSPLjava/util/AbstractMap;->access$000(Ljava/lang/Object;Ljava/lang/Object;)Z
+HSPLjava/util/AbstractMap;->clear()V+]Ljava/util/AbstractMap;missing_types]Ljava/util/Set;missing_types
+HSPLjava/util/AbstractMap;->clone()Ljava/lang/Object;
+HSPLjava/util/AbstractMap;->eq(Ljava/lang/Object;Ljava/lang/Object;)Z+]Ljava/lang/Object;missing_types
+HSPLjava/util/AbstractMap;->equals(Ljava/lang/Object;)Z+]Ljava/util/AbstractMap;missing_types]Ljava/util/Map;missing_types]Ljava/util/Iterator;missing_types]Ljava/util/Set;missing_types]Ljava/util/Map$Entry;missing_types]Ljava/lang/Object;missing_types
+HSPLjava/util/AbstractMap;->hashCode()I+]Ljava/util/Map$Entry;missing_types]Ljava/util/AbstractMap;missing_types]Ljava/util/Iterator;missing_types]Ljava/util/Set;missing_types
+HSPLjava/util/AbstractMap;->isEmpty()Z+]Ljava/util/AbstractMap;missing_types
+HSPLjava/util/AbstractMap;->putAll(Ljava/util/Map;)V+]Ljava/util/Map$Entry;megamorphic_types]Ljava/util/AbstractMap;missing_types]Ljava/util/Map;missing_types]Ljava/util/Iterator;missing_types]Ljava/util/Set;missing_types
+HSPLjava/util/AbstractMap;->size()I
+HSPLjava/util/AbstractMap;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Map$Entry;missing_types]Ljava/util/AbstractMap;missing_types]Ljava/util/Iterator;megamorphic_types]Ljava/util/Set;megamorphic_types
+HSPLjava/util/AbstractMap;->values()Ljava/util/Collection;
+HSPLjava/util/AbstractQueue;-><init>()V
+HSPLjava/util/AbstractQueue;->add(Ljava/lang/Object;)Z+]Ljava/util/AbstractQueue;missing_types
+HSPLjava/util/AbstractQueue;->addAll(Ljava/util/Collection;)Z+]Ljava/util/Collection;Ljava/util/Collections$UnmodifiableRandomAccessList;,Ljava/util/ArrayList;,Ljava/util/TreeMap$KeySet;,Ljava/util/Arrays$ArrayList;,Ljava/util/LinkedList;,Ljava/util/PriorityQueue;,Ljava/util/HashSet;,Ljava/util/HashMap$Values;]Ljava/util/Iterator;Ljava/util/Collections$UnmodifiableCollection$1;,Ljava/util/ArrayList$Itr;,Ljava/util/TreeMap$KeyIterator;,Ljava/util/AbstractList$Itr;,Ljava/util/PriorityQueue$Itr;,Ljava/util/LinkedList$ListItr;,Ljava/util/HashMap$KeyIterator;,Ljava/util/HashMap$ValueIterator;]Ljava/util/AbstractQueue;Ljava/util/PriorityQueue;,Ljava/util/concurrent/PriorityBlockingQueue;,Ljava/util/concurrent/LinkedBlockingQueue;
+HSPLjava/util/AbstractQueue;->clear()V+]Ljava/util/AbstractQueue;missing_types
+HSPLjava/util/AbstractQueue;->remove()Ljava/lang/Object;+]Ljava/util/AbstractQueue;Ljava/util/PriorityQueue;,Ljava/util/concurrent/ConcurrentLinkedQueue;,Ljava/util/concurrent/LinkedBlockingQueue;,Ljava/util/concurrent/ArrayBlockingQueue;
+HSPLjava/util/AbstractSequentialList;-><init>()V
+HSPLjava/util/AbstractSequentialList;->iterator()Ljava/util/Iterator;+]Ljava/util/AbstractSequentialList;missing_types
+HSPLjava/util/AbstractSet;-><init>()V
+HSPLjava/util/AbstractSet;->equals(Ljava/lang/Object;)Z+]Ljava/util/Collection;megamorphic_types]Ljava/util/AbstractSet;megamorphic_types
+HSPLjava/util/AbstractSet;->hashCode()I+]Ljava/lang/Object;missing_types]Ljava/util/AbstractSet;megamorphic_types]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/AbstractSet;->removeAll(Ljava/util/Collection;)Z+]Ljava/util/Collection;megamorphic_types]Ljava/util/AbstractSet;megamorphic_types]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/ArrayDeque$DeqIterator;-><init>(Ljava/util/ArrayDeque;)V
+HSPLjava/util/ArrayDeque$DeqIterator;-><init>(Ljava/util/ArrayDeque;Ljava/util/ArrayDeque$1;)V
+HSPLjava/util/ArrayDeque$DeqIterator;->hasNext()Z
+HSPLjava/util/ArrayDeque$DeqIterator;->next()Ljava/lang/Object;
+HSPLjava/util/ArrayDeque$DeqIterator;->remove()V+]Ljava/util/ArrayDeque;Ljava/util/ArrayDeque;
+HSPLjava/util/ArrayDeque$DescendingIterator;->next()Ljava/lang/Object;
+HSPLjava/util/ArrayDeque;-><init>()V
+HSPLjava/util/ArrayDeque;-><init>(I)V
+HSPLjava/util/ArrayDeque;-><init>(Ljava/util/Collection;)V+]Ljava/util/ArrayDeque;Ljava/util/ArrayDeque;]Ljava/util/Collection;missing_types
+HSPLjava/util/ArrayDeque;->add(Ljava/lang/Object;)Z+]Ljava/util/ArrayDeque;missing_types
+HSPLjava/util/ArrayDeque;->addFirst(Ljava/lang/Object;)V
+HSPLjava/util/ArrayDeque;->addLast(Ljava/lang/Object;)V
+HSPLjava/util/ArrayDeque;->allocateElements(I)V
+HSPLjava/util/ArrayDeque;->checkInvariants()V
+HSPLjava/util/ArrayDeque;->clear()V
+HSPLjava/util/ArrayDeque;->contains(Ljava/lang/Object;)Z+]Ljava/lang/Object;missing_types
+HSPLjava/util/ArrayDeque;->delete(I)Z
+HSPLjava/util/ArrayDeque;->descendingIterator()Ljava/util/Iterator;
+HSPLjava/util/ArrayDeque;->doubleCapacity()V
+HSPLjava/util/ArrayDeque;->getFirst()Ljava/lang/Object;
+HSPLjava/util/ArrayDeque;->getLast()Ljava/lang/Object;
+HSPLjava/util/ArrayDeque;->isEmpty()Z
+HSPLjava/util/ArrayDeque;->iterator()Ljava/util/Iterator;
+HSPLjava/util/ArrayDeque;->offer(Ljava/lang/Object;)Z+]Ljava/util/ArrayDeque;missing_types
+HSPLjava/util/ArrayDeque;->offerLast(Ljava/lang/Object;)Z+]Ljava/util/ArrayDeque;missing_types
+HSPLjava/util/ArrayDeque;->peek()Ljava/lang/Object;+]Ljava/util/ArrayDeque;Ljava/util/ArrayDeque;
+HSPLjava/util/ArrayDeque;->peekFirst()Ljava/lang/Object;
+HSPLjava/util/ArrayDeque;->peekLast()Ljava/lang/Object;
+HSPLjava/util/ArrayDeque;->poll()Ljava/lang/Object;+]Ljava/util/ArrayDeque;missing_types
+HSPLjava/util/ArrayDeque;->pollFirst()Ljava/lang/Object;
+HSPLjava/util/ArrayDeque;->pollLast()Ljava/lang/Object;
+HSPLjava/util/ArrayDeque;->pop()Ljava/lang/Object;+]Ljava/util/ArrayDeque;Ljava/util/ArrayDeque;
+HSPLjava/util/ArrayDeque;->push(Ljava/lang/Object;)V+]Ljava/util/ArrayDeque;Ljava/util/ArrayDeque;
+HSPLjava/util/ArrayDeque;->remove()Ljava/lang/Object;+]Ljava/util/ArrayDeque;Ljava/util/ArrayDeque;
+HSPLjava/util/ArrayDeque;->remove(Ljava/lang/Object;)Z+]Ljava/util/ArrayDeque;missing_types
+HSPLjava/util/ArrayDeque;->removeFirst()Ljava/lang/Object;+]Ljava/util/ArrayDeque;missing_types
+HSPLjava/util/ArrayDeque;->removeFirstOccurrence(Ljava/lang/Object;)Z+]Ljava/util/ArrayDeque;missing_types]Ljava/lang/Object;missing_types
+HSPLjava/util/ArrayDeque;->removeLast()Ljava/lang/Object;+]Ljava/util/ArrayDeque;Ljava/util/ArrayDeque;
+HSPLjava/util/ArrayDeque;->size()I
+HSPLjava/util/ArrayDeque;->toArray()[Ljava/lang/Object;
+HSPLjava/util/ArrayDeque;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;+]Ljava/lang/Object;[Ljava/lang/StackTraceElement;
+HSPLjava/util/ArrayList$ArrayListSpliterator;-><init>(Ljava/util/ArrayList;III)V
+HSPLjava/util/ArrayList$ArrayListSpliterator;->characteristics()I
+HSPLjava/util/ArrayList$ArrayListSpliterator;->estimateSize()J
+HSPLjava/util/ArrayList$ArrayListSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V+]Ljava/util/function/Consumer;megamorphic_types
+HSPLjava/util/ArrayList$ArrayListSpliterator;->getFence()I
+HSPLjava/util/ArrayList$ArrayListSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z+]Ljava/util/function/Consumer;Ljava/util/stream/ReferencePipeline$2$1;,Ljava/util/stream/MatchOps$1MatchSink;,Ljava/util/stream/ReferencePipeline$3$1;,Ljava/util/stream/FindOps$FindSink$OfRef;,Ljava/util/stream/ReferencePipeline$4$1;
+HSPLjava/util/ArrayList$Itr;-><init>(Ljava/util/ArrayList;)V
+HSPLjava/util/ArrayList$Itr;-><init>(Ljava/util/ArrayList;Ljava/util/ArrayList$1;)V
+HSPLjava/util/ArrayList$Itr;->hasNext()Z
+HSPLjava/util/ArrayList$Itr;->next()Ljava/lang/Object;
+HSPLjava/util/ArrayList$Itr;->remove()V+]Ljava/util/ArrayList;missing_types
+HSPLjava/util/ArrayList$ListItr;-><init>(Ljava/util/ArrayList;I)V
+HSPLjava/util/ArrayList$ListItr;->hasPrevious()Z
+HSPLjava/util/ArrayList$ListItr;->nextIndex()I
+HSPLjava/util/ArrayList$ListItr;->previous()Ljava/lang/Object;
+HSPLjava/util/ArrayList$ListItr;->set(Ljava/lang/Object;)V+]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/util/ArrayList$SubList$1;-><init>(Ljava/util/ArrayList$SubList;II)V
+HSPLjava/util/ArrayList$SubList$1;->hasNext()Z
+HSPLjava/util/ArrayList$SubList$1;->next()Ljava/lang/Object;
+HSPLjava/util/ArrayList$SubList;-><init>(Ljava/util/ArrayList;Ljava/util/AbstractList;III)V
+HSPLjava/util/ArrayList$SubList;->get(I)Ljava/lang/Object;
+HSPLjava/util/ArrayList$SubList;->iterator()Ljava/util/Iterator;+]Ljava/util/ArrayList$SubList;Ljava/util/ArrayList$SubList;
+HSPLjava/util/ArrayList$SubList;->listIterator(I)Ljava/util/ListIterator;
+HSPLjava/util/ArrayList$SubList;->removeRange(II)V+]Ljava/util/AbstractList;Ljava/util/ArrayList;,Ljava/util/ArrayList$SubList;
+HSPLjava/util/ArrayList$SubList;->size()I
+HSPLjava/util/ArrayList$SubList;->subList(II)Ljava/util/List;
+HSPLjava/util/ArrayList;-><init>()V
+HSPLjava/util/ArrayList;-><init>(I)V
+HSPLjava/util/ArrayList;-><init>(Ljava/util/Collection;)V+]Ljava/lang/Object;megamorphic_types]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/ArrayList;->access$100(Ljava/util/ArrayList;)I
+HSPLjava/util/ArrayList;->add(ILjava/lang/Object;)V
+HSPLjava/util/ArrayList;->add(Ljava/lang/Object;)Z
+HSPLjava/util/ArrayList;->addAll(ILjava/util/Collection;)Z+]Ljava/util/Collection;missing_types
+HSPLjava/util/ArrayList;->addAll(Ljava/util/Collection;)Z+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/ArrayList;->batchRemove(Ljava/util/Collection;Z)Z+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/ArrayList;->clear()V
+HSPLjava/util/ArrayList;->clone()Ljava/lang/Object;
+HSPLjava/util/ArrayList;->contains(Ljava/lang/Object;)Z+]Ljava/util/ArrayList;missing_types
+HSPLjava/util/ArrayList;->ensureCapacity(I)V
+HSPLjava/util/ArrayList;->ensureCapacityInternal(I)V
+HSPLjava/util/ArrayList;->ensureExplicitCapacity(I)V
+HSPLjava/util/ArrayList;->fastRemove(I)V
+HSPLjava/util/ArrayList;->forEach(Ljava/util/function/Consumer;)V+]Ljava/util/function/Consumer;missing_types
+HSPLjava/util/ArrayList;->get(I)Ljava/lang/Object;
+HSPLjava/util/ArrayList;->grow(I)V
+HSPLjava/util/ArrayList;->indexOf(Ljava/lang/Object;)I+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/ArrayList;->isEmpty()Z
+HSPLjava/util/ArrayList;->iterator()Ljava/util/Iterator;
+HSPLjava/util/ArrayList;->listIterator()Ljava/util/ListIterator;
+HSPLjava/util/ArrayList;->listIterator(I)Ljava/util/ListIterator;
+HSPLjava/util/ArrayList;->readObject(Ljava/io/ObjectInputStream;)V+]Ljava/io/ObjectInputStream;missing_types
+HSPLjava/util/ArrayList;->remove(I)Ljava/lang/Object;
+HSPLjava/util/ArrayList;->remove(Ljava/lang/Object;)Z+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/ArrayList;->removeAll(Ljava/util/Collection;)Z
+HSPLjava/util/ArrayList;->removeIf(Ljava/util/function/Predicate;)Z+]Ljava/util/BitSet;Ljava/util/BitSet;]Ljava/util/function/Predicate;missing_types
+HSPLjava/util/ArrayList;->removeRange(II)V
+HSPLjava/util/ArrayList;->set(ILjava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/ArrayList;->size()I
+HSPLjava/util/ArrayList;->sort(Ljava/util/Comparator;)V
+HSPLjava/util/ArrayList;->spliterator()Ljava/util/Spliterator;
+HSPLjava/util/ArrayList;->subList(II)Ljava/util/List;
+HSPLjava/util/ArrayList;->subListRangeCheck(III)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/ArrayList;->toArray()[Ljava/lang/Object;
+HSPLjava/util/ArrayList;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/ArrayList;->trimToSize()V
+HSPLjava/util/ArrayList;->writeObject(Ljava/io/ObjectOutputStream;)V+]Ljava/io/ObjectOutputStream;missing_types
+HSPLjava/util/Arrays$ArrayList;-><init>([Ljava/lang/Object;)V
+HSPLjava/util/Arrays$ArrayList;->contains(Ljava/lang/Object;)Z+]Ljava/util/Arrays$ArrayList;Ljava/util/Arrays$ArrayList;
+HSPLjava/util/Arrays$ArrayList;->forEach(Ljava/util/function/Consumer;)V+]Ljava/util/function/Consumer;Landroid/database/CursorToBulkCursorAdaptor$ContentObserverProxy$$ExternalSyntheticLambda0;
+HSPLjava/util/Arrays$ArrayList;->get(I)Ljava/lang/Object;
+HSPLjava/util/Arrays$ArrayList;->indexOf(Ljava/lang/Object;)I+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/Arrays$ArrayList;->size()I
+HSPLjava/util/Arrays$ArrayList;->sort(Ljava/util/Comparator;)V
+HSPLjava/util/Arrays$ArrayList;->spliterator()Ljava/util/Spliterator;
+HSPLjava/util/Arrays$ArrayList;->toArray()[Ljava/lang/Object;+][Ljava/lang/Object;missing_types
+HSPLjava/util/Arrays$ArrayList;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;+]Ljava/util/Arrays$ArrayList;Ljava/util/Arrays$ArrayList;]Ljava/lang/Object;[Ljava/lang/String;,[Ljava/security/cert/X509Certificate;
+HSPLjava/util/Arrays;->asList([Ljava/lang/Object;)Ljava/util/List;
+HSPLjava/util/Arrays;->binarySearch([CC)I
+HSPLjava/util/Arrays;->binarySearch([II)I
+HSPLjava/util/Arrays;->binarySearch([IIII)I
+HSPLjava/util/Arrays;->binarySearch([JIIJ)I
+HSPLjava/util/Arrays;->binarySearch([JJ)I
+HSPLjava/util/Arrays;->binarySearch([Ljava/lang/Object;Ljava/lang/Object;)I
+HSPLjava/util/Arrays;->binarySearch([Ljava/lang/Object;Ljava/lang/Object;Ljava/util/Comparator;)I
+HSPLjava/util/Arrays;->binarySearch0([CIIC)I
+HSPLjava/util/Arrays;->binarySearch0([IIII)I
+HSPLjava/util/Arrays;->binarySearch0([JIIJ)I
+HSPLjava/util/Arrays;->binarySearch0([Ljava/lang/Object;IILjava/lang/Object;)I+]Ljava/lang/Comparable;missing_types
+HSPLjava/util/Arrays;->binarySearch0([Ljava/lang/Object;IILjava/lang/Object;Ljava/util/Comparator;)I+]Ljava/util/Comparator;missing_types
+HSPLjava/util/Arrays;->copyOf([BI)[B
+HSPLjava/util/Arrays;->copyOf([CI)[C
+HSPLjava/util/Arrays;->copyOf([DI)[D
+HSPLjava/util/Arrays;->copyOf([FI)[F
+HSPLjava/util/Arrays;->copyOf([II)[I
+HSPLjava/util/Arrays;->copyOf([JI)[J
+HSPLjava/util/Arrays;->copyOf([Ljava/lang/Object;I)[Ljava/lang/Object;+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/Arrays;->copyOf([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/Arrays;->copyOf([ZI)[Z
+HSPLjava/util/Arrays;->copyOfRange([BII)[B
+HSPLjava/util/Arrays;->copyOfRange([CII)[C
+HSPLjava/util/Arrays;->copyOfRange([III)[I
+HSPLjava/util/Arrays;->copyOfRange([JII)[J
+HSPLjava/util/Arrays;->copyOfRange([Ljava/lang/Object;II)[Ljava/lang/Object;+]Ljava/lang/Object;missing_types
+HSPLjava/util/Arrays;->copyOfRange([Ljava/lang/Object;IILjava/lang/Class;)[Ljava/lang/Object;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/Arrays;->deepEquals([Ljava/lang/Object;[Ljava/lang/Object;)Z
+HSPLjava/util/Arrays;->deepEquals0(Ljava/lang/Object;Ljava/lang/Object;)Z+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/Arrays;->deepHashCode([Ljava/lang/Object;)I+]Ljava/lang/Object;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/Arrays;->deepToString([Ljava/lang/Object;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Arrays;->deepToString([Ljava/lang/Object;Ljava/lang/StringBuilder;Ljava/util/Set;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Object;missing_types]Ljava/lang/Class;Ljava/lang/Class;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLjava/util/Arrays;->equals([B[B)Z
+HSPLjava/util/Arrays;->equals([F[F)Z
+HSPLjava/util/Arrays;->equals([I[I)Z
+HSPLjava/util/Arrays;->equals([J[J)Z
+HSPLjava/util/Arrays;->equals([Ljava/lang/Object;[Ljava/lang/Object;)Z+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/Arrays;->fill([BB)V
+HSPLjava/util/Arrays;->fill([BIIB)V
+HSPLjava/util/Arrays;->fill([CC)V
+HSPLjava/util/Arrays;->fill([CIIC)V
+HSPLjava/util/Arrays;->fill([DD)V
+HSPLjava/util/Arrays;->fill([FF)V
+HSPLjava/util/Arrays;->fill([II)V
+HSPLjava/util/Arrays;->fill([IIII)V
+HSPLjava/util/Arrays;->fill([JIIJ)V
+HSPLjava/util/Arrays;->fill([JJ)V
+HSPLjava/util/Arrays;->fill([Ljava/lang/Object;IILjava/lang/Object;)V
+HSPLjava/util/Arrays;->fill([Ljava/lang/Object;Ljava/lang/Object;)V
+HSPLjava/util/Arrays;->fill([SS)V
+HSPLjava/util/Arrays;->fill([ZZ)V
+HSPLjava/util/Arrays;->hashCode([B)I
+HSPLjava/util/Arrays;->hashCode([F)I
+HSPLjava/util/Arrays;->hashCode([I)I
+HSPLjava/util/Arrays;->hashCode([J)I
+HSPLjava/util/Arrays;->hashCode([Ljava/lang/Object;)I+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/Arrays;->rangeCheck(III)V
+HSPLjava/util/Arrays;->sort([C)V
+HSPLjava/util/Arrays;->sort([F)V
+HSPLjava/util/Arrays;->sort([I)V
+HSPLjava/util/Arrays;->sort([III)V
+HSPLjava/util/Arrays;->sort([J)V
+HSPLjava/util/Arrays;->sort([Ljava/lang/Object;)V
+HSPLjava/util/Arrays;->sort([Ljava/lang/Object;II)V
+HSPLjava/util/Arrays;->sort([Ljava/lang/Object;IILjava/util/Comparator;)V
+HSPLjava/util/Arrays;->sort([Ljava/lang/Object;Ljava/util/Comparator;)V
+HSPLjava/util/Arrays;->spliterator([III)Ljava/util/Spliterator$OfInt;
+HSPLjava/util/Arrays;->spliterator([Ljava/lang/Object;II)Ljava/util/Spliterator;
+HSPLjava/util/Arrays;->stream([I)Ljava/util/stream/IntStream;
+HSPLjava/util/Arrays;->stream([III)Ljava/util/stream/IntStream;
+HSPLjava/util/Arrays;->stream([Ljava/lang/Object;)Ljava/util/stream/Stream;
+HSPLjava/util/Arrays;->stream([Ljava/lang/Object;II)Ljava/util/stream/Stream;
+HSPLjava/util/Arrays;->toString([B)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Arrays;->toString([F)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Arrays;->toString([I)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Arrays;->toString([J)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Arrays;->toString([Ljava/lang/Object;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Base64$Decoder;->decode(Ljava/lang/String;)[B+]Ljava/util/Base64$Decoder;Ljava/util/Base64$Decoder;]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/Base64$Decoder;->decode([B)[B
+HSPLjava/util/Base64$Decoder;->decode0([BII[B)I
+HSPLjava/util/Base64$Decoder;->outLength([BII)I
+HSPLjava/util/Base64;->getDecoder()Ljava/util/Base64$Decoder;
+HSPLjava/util/Base64;->getEncoder()Ljava/util/Base64$Encoder;
+HSPLjava/util/Base64;->getMimeDecoder()Ljava/util/Base64$Decoder;
+HSPLjava/util/BitSet;-><init>()V
+HSPLjava/util/BitSet;-><init>(I)V
+HSPLjava/util/BitSet;-><init>([J)V
+HSPLjava/util/BitSet;->andNot(Ljava/util/BitSet;)V
+HSPLjava/util/BitSet;->cardinality()I
+HSPLjava/util/BitSet;->checkInvariants()V
+HSPLjava/util/BitSet;->checkRange(II)V
+HSPLjava/util/BitSet;->clear()V
+HSPLjava/util/BitSet;->clear(I)V
+HSPLjava/util/BitSet;->clone()Ljava/lang/Object;+][J[J
+HSPLjava/util/BitSet;->ensureCapacity(I)V
+HSPLjava/util/BitSet;->equals(Ljava/lang/Object;)Z
+HSPLjava/util/BitSet;->expandTo(I)V
+HSPLjava/util/BitSet;->flip(II)V
+HSPLjava/util/BitSet;->get(I)Z
+HSPLjava/util/BitSet;->initWords(I)V
+HSPLjava/util/BitSet;->isEmpty()Z
+HSPLjava/util/BitSet;->length()I
+HSPLjava/util/BitSet;->nextClearBit(I)I
+HSPLjava/util/BitSet;->nextSetBit(I)I
+HSPLjava/util/BitSet;->or(Ljava/util/BitSet;)V
+HSPLjava/util/BitSet;->recalculateWordsInUse()V
+HSPLjava/util/BitSet;->set(I)V
+HSPLjava/util/BitSet;->set(II)V
+HSPLjava/util/BitSet;->set(IIZ)V+]Ljava/util/BitSet;Ljava/util/BitSet;
+HSPLjava/util/BitSet;->set(IZ)V+]Ljava/util/BitSet;Ljava/util/BitSet;
+HSPLjava/util/BitSet;->size()I
+HSPLjava/util/BitSet;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/BitSet;Ljava/util/BitSet;
+HSPLjava/util/BitSet;->trimToSize()V
+HSPLjava/util/BitSet;->valueOf([J)Ljava/util/BitSet;
+HSPLjava/util/BitSet;->wordIndex(I)I
+HSPLjava/util/Calendar;-><init>()V
+HSPLjava/util/Calendar;-><init>(Ljava/util/TimeZone;Ljava/util/Locale;)V
+HSPLjava/util/Calendar;->aggregateStamp(II)I
+HSPLjava/util/Calendar;->before(Ljava/lang/Object;)Z+]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/util/Calendar;->clear()V
+HSPLjava/util/Calendar;->clone()Ljava/lang/Object;+]Ljava/util/TimeZone;missing_types
+HSPLjava/util/Calendar;->compareTo(J)I
+HSPLjava/util/Calendar;->compareTo(Ljava/util/Calendar;)I
+HSPLjava/util/Calendar;->complete()V+]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/util/Calendar;->createCalendar(Ljava/util/TimeZone;Ljava/util/Locale;)Ljava/util/Calendar;
+HSPLjava/util/Calendar;->get(I)I+]Ljava/util/Calendar;missing_types
+HSPLjava/util/Calendar;->getFirstDayOfWeek()I
+HSPLjava/util/Calendar;->getInstance()Ljava/util/Calendar;
+HSPLjava/util/Calendar;->getInstance(Ljava/util/Locale;)Ljava/util/Calendar;
+HSPLjava/util/Calendar;->getInstance(Ljava/util/TimeZone;)Ljava/util/Calendar;
+HSPLjava/util/Calendar;->getInstance(Ljava/util/TimeZone;Ljava/util/Locale;)Ljava/util/Calendar;
+HSPLjava/util/Calendar;->getMillisOf(Ljava/util/Calendar;)J+]Ljava/util/Calendar;missing_types
+HSPLjava/util/Calendar;->getMinimalDaysInFirstWeek()I
+HSPLjava/util/Calendar;->getSetStateFields()I
+HSPLjava/util/Calendar;->getTime()Ljava/util/Date;+]Ljava/util/Calendar;missing_types
+HSPLjava/util/Calendar;->getTimeInMillis()J
+HSPLjava/util/Calendar;->getTimeZone()Ljava/util/TimeZone;
+HSPLjava/util/Calendar;->getZone()Ljava/util/TimeZone;
+HSPLjava/util/Calendar;->internalGet(I)I
+HSPLjava/util/Calendar;->internalSet(II)V
+HSPLjava/util/Calendar;->isExternallySet(I)Z
+HSPLjava/util/Calendar;->isFieldSet(II)Z
+HSPLjava/util/Calendar;->isFullyNormalized()Z
+HSPLjava/util/Calendar;->isLenient()Z
+HSPLjava/util/Calendar;->isPartiallyNormalized()Z
+HSPLjava/util/Calendar;->isSet(I)Z
+HSPLjava/util/Calendar;->selectFields()I
+HSPLjava/util/Calendar;->set(II)V+]Ljava/util/Calendar;missing_types
+HSPLjava/util/Calendar;->set(III)V+]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/util/Calendar;->set(IIIIII)V+]Ljava/util/Calendar;Ljava/util/GregorianCalendar;
+HSPLjava/util/Calendar;->setFieldsComputed(I)V
+HSPLjava/util/Calendar;->setFieldsNormalized(I)V
+HSPLjava/util/Calendar;->setLenient(Z)V
+HSPLjava/util/Calendar;->setTime(Ljava/util/Date;)V+]Ljava/util/Date;missing_types]Ljava/util/Calendar;missing_types
+HSPLjava/util/Calendar;->setTimeInMillis(J)V+]Ljava/util/Calendar;missing_types
+HSPLjava/util/Calendar;->setTimeZone(Ljava/util/TimeZone;)V
+HSPLjava/util/Calendar;->setWeekCountData(Ljava/util/Locale;)V+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/lang/Integer;Ljava/lang/Integer;
+HSPLjava/util/Calendar;->setZoneShared(Z)V
+HSPLjava/util/Calendar;->updateTime()V+]Ljava/util/Calendar;missing_types
+HSPLjava/util/Collection;->removeIf(Ljava/util/function/Predicate;)Z+]Ljava/util/Collection;megamorphic_types]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/Collection;->spliterator()Ljava/util/Spliterator;
+HSPLjava/util/Collection;->stream()Ljava/util/stream/Stream;+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$1;-><init>(Ljava/lang/Object;)V
+HSPLjava/util/Collections$1;->hasNext()Z
+HSPLjava/util/Collections$1;->next()Ljava/lang/Object;
+HSPLjava/util/Collections$3;-><init>(Ljava/util/Collection;)V+]Ljava/util/Collection;Ljava/util/Arrays$ArrayList;,Ljava/util/HashSet;,Ljava/util/ArrayList;
+HSPLjava/util/Collections$3;->hasMoreElements()Z
+HSPLjava/util/Collections$3;->nextElement()Ljava/lang/Object;
+HSPLjava/util/Collections$CopiesList;-><init>(ILjava/lang/Object;)V
+HSPLjava/util/Collections$CopiesList;->get(I)Ljava/lang/Object;
+HSPLjava/util/Collections$CopiesList;->size()I
+HSPLjava/util/Collections$CopiesList;->toArray()[Ljava/lang/Object;
+HSPLjava/util/Collections$EmptyEnumeration;->hasMoreElements()Z
+HSPLjava/util/Collections$EmptyIterator;->hasNext()Z
+HSPLjava/util/Collections$EmptyList;->contains(Ljava/lang/Object;)Z
+HSPLjava/util/Collections$EmptyList;->containsAll(Ljava/util/Collection;)Z+]Ljava/util/Collection;Ljava/util/ArrayList;,Ljava/util/Collections$EmptyList;
+HSPLjava/util/Collections$EmptyList;->equals(Ljava/lang/Object;)Z+]Ljava/util/List;missing_types
+HSPLjava/util/Collections$EmptyList;->isEmpty()Z
+HSPLjava/util/Collections$EmptyList;->iterator()Ljava/util/Iterator;
+HSPLjava/util/Collections$EmptyList;->listIterator()Ljava/util/ListIterator;
+HSPLjava/util/Collections$EmptyList;->readResolve()Ljava/lang/Object;
+HSPLjava/util/Collections$EmptyList;->size()I
+HSPLjava/util/Collections$EmptyList;->sort(Ljava/util/Comparator;)V
+HSPLjava/util/Collections$EmptyList;->spliterator()Ljava/util/Spliterator;
+HSPLjava/util/Collections$EmptyList;->toArray()[Ljava/lang/Object;
+HSPLjava/util/Collections$EmptyList;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;
+HSPLjava/util/Collections$EmptyMap;->containsKey(Ljava/lang/Object;)Z
+HSPLjava/util/Collections$EmptyMap;->entrySet()Ljava/util/Set;
+HSPLjava/util/Collections$EmptyMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/Collections$EmptyMap;->isEmpty()Z
+HSPLjava/util/Collections$EmptyMap;->keySet()Ljava/util/Set;
+HSPLjava/util/Collections$EmptyMap;->size()I
+HSPLjava/util/Collections$EmptyMap;->values()Ljava/util/Collection;
+HSPLjava/util/Collections$EmptySet;->contains(Ljava/lang/Object;)Z
+HSPLjava/util/Collections$EmptySet;->containsAll(Ljava/util/Collection;)Z+]Ljava/util/Collection;Ljava/util/HashSet;,Ljava/util/Collections$EmptySet;
+HSPLjava/util/Collections$EmptySet;->isEmpty()Z
+HSPLjava/util/Collections$EmptySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/Collections$EmptySet;->size()I
+HSPLjava/util/Collections$EmptySet;->toArray()[Ljava/lang/Object;
+HSPLjava/util/Collections$EmptySet;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;
+HSPLjava/util/Collections$ReverseComparator2;-><init>(Ljava/util/Comparator;)V
+HSPLjava/util/Collections$ReverseComparator2;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/util/Comparator;missing_types
+HSPLjava/util/Collections$ReverseComparator;->compare(Ljava/lang/Comparable;Ljava/lang/Comparable;)I+]Ljava/lang/Comparable;missing_types
+HSPLjava/util/Collections$ReverseComparator;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/util/Collections$ReverseComparator;Ljava/util/Collections$ReverseComparator;
+HSPLjava/util/Collections$SetFromMap;-><init>(Ljava/util/Map;)V+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SetFromMap;->add(Ljava/lang/Object;)Z+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SetFromMap;->clear()V+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SetFromMap;->contains(Ljava/lang/Object;)Z+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SetFromMap;->isEmpty()Z+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SetFromMap;->iterator()Ljava/util/Iterator;+]Ljava/util/Set;missing_types
+HSPLjava/util/Collections$SetFromMap;->remove(Ljava/lang/Object;)Z+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SetFromMap;->size()I+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SetFromMap;->toArray()[Ljava/lang/Object;+]Ljava/util/Set;Ljava/util/WeakHashMap$KeySet;,Ljava/util/IdentityHashMap$KeySet;
+HSPLjava/util/Collections$SetFromMap;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;+]Ljava/util/Set;Ljava/util/WeakHashMap$KeySet;
+HSPLjava/util/Collections$SingletonList;-><init>(Ljava/lang/Object;)V
+HSPLjava/util/Collections$SingletonList;->contains(Ljava/lang/Object;)Z
+HSPLjava/util/Collections$SingletonList;->get(I)Ljava/lang/Object;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Collections$SingletonList;->iterator()Ljava/util/Iterator;
+HSPLjava/util/Collections$SingletonList;->size()I
+HSPLjava/util/Collections$SingletonMap;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
+HSPLjava/util/Collections$SingletonMap;->containsKey(Ljava/lang/Object;)Z
+HSPLjava/util/Collections$SingletonMap;->entrySet()Ljava/util/Set;
+HSPLjava/util/Collections$SingletonMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/Collections$SingletonMap;->keySet()Ljava/util/Set;
+HSPLjava/util/Collections$SingletonMap;->size()I
+HSPLjava/util/Collections$SingletonMap;->values()Ljava/util/Collection;
+HSPLjava/util/Collections$SingletonSet;-><init>(Ljava/lang/Object;)V
+HSPLjava/util/Collections$SingletonSet;->contains(Ljava/lang/Object;)Z
+HSPLjava/util/Collections$SingletonSet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/Collections$SingletonSet;->size()I
+HSPLjava/util/Collections$SynchronizedCollection;-><init>(Ljava/util/Collection;)V
+HSPLjava/util/Collections$SynchronizedCollection;-><init>(Ljava/util/Collection;Ljava/lang/Object;)V
+HSPLjava/util/Collections$SynchronizedCollection;->add(Ljava/lang/Object;)Z+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$SynchronizedCollection;->addAll(Ljava/util/Collection;)Z+]Ljava/util/Collection;Ljava/util/ArrayList;,Ljava/util/HashSet;,Ljava/util/LinkedList;
+HSPLjava/util/Collections$SynchronizedCollection;->clear()V+]Ljava/util/Collection;missing_types
+HSPLjava/util/Collections$SynchronizedCollection;->contains(Ljava/lang/Object;)Z+]Ljava/util/Collection;missing_types
+HSPLjava/util/Collections$SynchronizedCollection;->isEmpty()Z+]Ljava/util/Collection;Ljava/util/ArrayList;,Ljava/util/HashSet;,Ljava/util/HashMap$KeySet;,Ljava/util/Hashtable$ValueCollection;,Landroid/util/ArraySet;,Ljava/util/LinkedHashSet;,Ljava/util/LinkedList;,Ljava/util/HashMap$EntrySet;,Ljava/util/RegularEnumSet;
+HSPLjava/util/Collections$SynchronizedCollection;->iterator()Ljava/util/Iterator;+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$SynchronizedCollection;->remove(Ljava/lang/Object;)Z+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$SynchronizedCollection;->size()I+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$SynchronizedCollection;->toArray()[Ljava/lang/Object;+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$SynchronizedCollection;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;+]Ljava/util/Collection;Ljava/util/Collections$SetFromMap;,Ljava/util/LinkedHashSet;,Ljava/util/ArrayList;,Ljava/util/HashSet;
+HSPLjava/util/Collections$SynchronizedList;-><init>(Ljava/util/List;)V
+HSPLjava/util/Collections$SynchronizedList;->get(I)Ljava/lang/Object;+]Ljava/util/List;Ljava/util/ArrayList;,Ljava/util/LinkedList;
+HSPLjava/util/Collections$SynchronizedMap;-><init>(Ljava/util/Map;)V
+HSPLjava/util/Collections$SynchronizedMap;->clear()V+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SynchronizedMap;->containsKey(Ljava/lang/Object;)Z+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SynchronizedMap;->entrySet()Ljava/util/Set;+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SynchronizedMap;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SynchronizedMap;->getOrDefault(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SynchronizedMap;->isEmpty()Z+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SynchronizedMap;->keySet()Ljava/util/Set;+]Ljava/util/Map;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;,Ljava/util/TreeMap;,Ljava/util/WeakHashMap;
+HSPLjava/util/Collections$SynchronizedMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SynchronizedMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Map;megamorphic_types
+HSPLjava/util/Collections$SynchronizedMap;->size()I+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$SynchronizedMap;->values()Ljava/util/Collection;+]Ljava/util/Map;Ljava/util/TreeMap;,Ljava/util/HashMap;,Ljava/util/LinkedHashMap;,Ljava/util/EnumMap;
+HSPLjava/util/Collections$SynchronizedRandomAccessList;-><init>(Ljava/util/List;)V
+HSPLjava/util/Collections$SynchronizedSet;-><init>(Ljava/util/Set;)V
+HSPLjava/util/Collections$SynchronizedSet;-><init>(Ljava/util/Set;Ljava/lang/Object;)V
+HSPLjava/util/Collections$SynchronizedSet;->equals(Ljava/lang/Object;)Z+]Ljava/util/Collection;Ljava/util/Hashtable$KeySet;
+HSPLjava/util/Collections$UnmodifiableCollection$1;-><init>(Ljava/util/Collections$UnmodifiableCollection;)V+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableCollection$1;->hasNext()Z+]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableCollection$1;->next()Ljava/lang/Object;+]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableCollection;-><init>(Ljava/util/Collection;)V
+HSPLjava/util/Collections$UnmodifiableCollection;->contains(Ljava/lang/Object;)Z+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableCollection;->containsAll(Ljava/util/Collection;)Z+]Ljava/util/Collection;Ljava/util/HashSet;,Ljava/util/RegularEnumSet;,Ljava/util/ArrayList;
+HSPLjava/util/Collections$UnmodifiableCollection;->forEach(Ljava/util/function/Consumer;)V+]Ljava/util/Collection;Ljava/util/HashSet;,Ljava/util/ArrayList;
+HSPLjava/util/Collections$UnmodifiableCollection;->isEmpty()Z+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableCollection;->iterator()Ljava/util/Iterator;
+HSPLjava/util/Collections$UnmodifiableCollection;->size()I+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableCollection;->stream()Ljava/util/stream/Stream;+]Ljava/util/Collection;Ljava/util/HashSet;,Ljava/util/ArrayList;,Ljava/util/HashMap$Values;
+HSPLjava/util/Collections$UnmodifiableCollection;->toArray()[Ljava/lang/Object;+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableCollection;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableCollection;->toString()Ljava/lang/String;+]Ljava/lang/Object;missing_types
+HSPLjava/util/Collections$UnmodifiableList$1;-><init>(Ljava/util/Collections$UnmodifiableList;I)V+]Ljava/util/List;missing_types
+HSPLjava/util/Collections$UnmodifiableList$1;->hasNext()Z+]Ljava/util/ListIterator;missing_types
+HSPLjava/util/Collections$UnmodifiableList$1;->next()Ljava/lang/Object;+]Ljava/util/ListIterator;Ljava/util/ArrayList$ListItr;,Ljava/util/AbstractList$ListItr;,Ljava/util/ArrayList$SubList$1;,Ljava/util/Collections$UnmodifiableList$1;,Ljava/util/AbstractList$SubList$1;,Ljava/util/LinkedList$ListItr;
+HSPLjava/util/Collections$UnmodifiableList;-><init>(Ljava/util/List;)V
+HSPLjava/util/Collections$UnmodifiableList;->equals(Ljava/lang/Object;)Z+]Ljava/util/List;missing_types
+HSPLjava/util/Collections$UnmodifiableList;->get(I)Ljava/lang/Object;+]Ljava/util/List;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableList;->hashCode()I+]Ljava/util/List;missing_types
+HSPLjava/util/Collections$UnmodifiableList;->indexOf(Ljava/lang/Object;)I+]Ljava/util/List;Ljava/util/Collections$UnmodifiableRandomAccessList;,Ljava/util/ArrayList$SubList;,Ljava/util/ArrayList;,Ljava/util/Arrays$ArrayList;,Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/Collections$UnmodifiableList;->listIterator()Ljava/util/ListIterator;+]Ljava/util/Collections$UnmodifiableList;Ljava/util/Collections$UnmodifiableRandomAccessList;
+HSPLjava/util/Collections$UnmodifiableList;->listIterator(I)Ljava/util/ListIterator;
+HSPLjava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1;-><init>(Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet;)V+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1;->hasNext()Z+]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1;->next()Ljava/lang/Object;+]Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1;Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1;
+HSPLjava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1;->next()Ljava/util/Map$Entry;+]Ljava/util/Iterator;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry;-><init>(Ljava/util/Map$Entry;)V
+HSPLjava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry;->getKey()Ljava/lang/Object;+]Ljava/util/Map$Entry;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry;->getValue()Ljava/lang/Object;+]Ljava/util/Map$Entry;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet;-><init>(Ljava/util/Set;)V
+HSPLjava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/Collections$UnmodifiableMap;-><init>(Ljava/util/Map;)V
+HSPLjava/util/Collections$UnmodifiableMap;->containsKey(Ljava/lang/Object;)Z+]Ljava/util/Map;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableMap;->entrySet()Ljava/util/Set;+]Ljava/util/Map;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableMap;->equals(Ljava/lang/Object;)Z+]Ljava/util/Map;Ljava/util/HashMap;,Ljava/util/Collections$UnmodifiableMap;,Landroid/util/ArrayMap;,Ljava/util/Collections$EmptyMap;,Ljava/util/TreeMap;
+HSPLjava/util/Collections$UnmodifiableMap;->forEach(Ljava/util/function/BiConsumer;)V
+HSPLjava/util/Collections$UnmodifiableMap;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Map;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableMap;->hashCode()I+]Ljava/util/Map;Ljava/util/HashMap;,Ljava/util/Collections$UnmodifiableMap;
+HSPLjava/util/Collections$UnmodifiableMap;->isEmpty()Z+]Ljava/util/Map;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableMap;->keySet()Ljava/util/Set;+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$UnmodifiableMap;->size()I+]Ljava/util/Map;megamorphic_types
+HSPLjava/util/Collections$UnmodifiableMap;->toString()Ljava/lang/String;+]Ljava/lang/Object;Ljava/util/HashMap;,Ljava/util/TreeMap;,Landroid/util/ArrayMap;
+HSPLjava/util/Collections$UnmodifiableMap;->values()Ljava/util/Collection;+]Ljava/util/Map;missing_types
+HSPLjava/util/Collections$UnmodifiableRandomAccessList;-><init>(Ljava/util/List;)V
+HSPLjava/util/Collections$UnmodifiableRandomAccessList;->subList(II)Ljava/util/List;+]Ljava/util/List;missing_types
+HSPLjava/util/Collections$UnmodifiableSet;-><init>(Ljava/util/Set;)V
+HSPLjava/util/Collections$UnmodifiableSet;->equals(Ljava/lang/Object;)Z+]Ljava/util/Collection;Ljava/util/HashSet;,Landroid/util/ArraySet;,Ljava/util/LinkedHashSet;
+HSPLjava/util/Collections$UnmodifiableSortedMap;-><init>(Ljava/util/SortedMap;)V
+HSPLjava/util/Collections$UnmodifiableSortedSet;-><init>(Ljava/util/SortedSet;)V
+HSPLjava/util/Collections;->addAll(Ljava/util/Collection;[Ljava/lang/Object;)Z+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Collections;->binarySearch(Ljava/util/List;Ljava/lang/Object;)I
+HSPLjava/util/Collections;->binarySearch(Ljava/util/List;Ljava/lang/Object;Ljava/util/Comparator;)I+]Ljava/util/List;Ljava/util/Collections$SynchronizedList;
+HSPLjava/util/Collections;->disjoint(Ljava/util/Collection;Ljava/util/Collection;)Z+]Ljava/util/Collection;missing_types]Ljava/util/Iterator;missing_types
+HSPLjava/util/Collections;->emptyEnumeration()Ljava/util/Enumeration;
+HSPLjava/util/Collections;->emptyIterator()Ljava/util/Iterator;
+HSPLjava/util/Collections;->emptyList()Ljava/util/List;
+HSPLjava/util/Collections;->emptyListIterator()Ljava/util/ListIterator;
+HSPLjava/util/Collections;->emptyMap()Ljava/util/Map;
+HSPLjava/util/Collections;->emptySet()Ljava/util/Set;
+HSPLjava/util/Collections;->enumeration(Ljava/util/Collection;)Ljava/util/Enumeration;
+HSPLjava/util/Collections;->eq(Ljava/lang/Object;Ljava/lang/Object;)Z+]Ljava/lang/Object;missing_types
+HSPLjava/util/Collections;->indexedBinarySearch(Ljava/util/List;Ljava/lang/Object;)I+]Ljava/util/List;missing_types]Ljava/lang/Comparable;megamorphic_types
+HSPLjava/util/Collections;->indexedBinarySearch(Ljava/util/List;Ljava/lang/Object;Ljava/util/Comparator;)I+]Ljava/util/Comparator;missing_types]Ljava/util/List;missing_types
+HSPLjava/util/Collections;->list(Ljava/util/Enumeration;)Ljava/util/ArrayList;+]Ljava/util/Enumeration;missing_types]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/util/Collections;->max(Ljava/util/Collection;)Ljava/lang/Object;+]Ljava/util/Collection;missing_types]Ljava/lang/Comparable;missing_types]Ljava/util/Iterator;missing_types
+HSPLjava/util/Collections;->max(Ljava/util/Collection;Ljava/util/Comparator;)Ljava/lang/Object;+]Ljava/util/Collection;missing_types]Ljava/util/Iterator;missing_types]Ljava/util/Comparator;Ljava/util/Comparator$$ExternalSyntheticLambda4;
+HSPLjava/util/Collections;->min(Ljava/util/Collection;Ljava/util/Comparator;)Ljava/lang/Object;+]Ljava/util/Collection;missing_types]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;,Ljava/util/Collections$UnmodifiableCollection$1;,Ljava/util/AbstractList$Itr;]Ljava/util/Comparator;Ljava/util/Comparator$$ExternalSyntheticLambda4;
+HSPLjava/util/Collections;->nCopies(ILjava/lang/Object;)Ljava/util/List;
+HSPLjava/util/Collections;->newSetFromMap(Ljava/util/Map;)Ljava/util/Set;
+HSPLjava/util/Collections;->reverse(Ljava/util/List;)V+]Ljava/util/List;missing_types
+HSPLjava/util/Collections;->reverseOrder()Ljava/util/Comparator;
+HSPLjava/util/Collections;->reverseOrder(Ljava/util/Comparator;)Ljava/util/Comparator;
+HSPLjava/util/Collections;->rotate(Ljava/util/List;I)V
+HSPLjava/util/Collections;->rotate1(Ljava/util/List;I)V+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLjava/util/Collections;->shuffle(Ljava/util/List;)V
+HSPLjava/util/Collections;->shuffle(Ljava/util/List;Ljava/util/Random;)V+]Ljava/util/Random;missing_types]Ljava/util/List;Ljava/util/ArrayList;,Ljava/util/Arrays$ArrayList;
+HSPLjava/util/Collections;->singleton(Ljava/lang/Object;)Ljava/util/Set;
+HSPLjava/util/Collections;->singletonIterator(Ljava/lang/Object;)Ljava/util/Iterator;
+HSPLjava/util/Collections;->singletonList(Ljava/lang/Object;)Ljava/util/List;
+HSPLjava/util/Collections;->singletonMap(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/Map;
+HSPLjava/util/Collections;->sort(Ljava/util/List;)V
+HSPLjava/util/Collections;->sort(Ljava/util/List;Ljava/util/Comparator;)V+]Ldalvik/system/VMRuntime;missing_types]Ljava/util/List;megamorphic_types]Ljava/lang/Object;Ljava/util/ArrayList;,Ljava/util/LinkedList;]Ljava/util/ListIterator;Ljava/util/LinkedList$ListItr;
+HSPLjava/util/Collections;->swap(Ljava/util/List;II)V+]Ljava/util/List;missing_types
+HSPLjava/util/Collections;->synchronizedCollection(Ljava/util/Collection;)Ljava/util/Collection;
+HSPLjava/util/Collections;->synchronizedCollection(Ljava/util/Collection;Ljava/lang/Object;)Ljava/util/Collection;
+HSPLjava/util/Collections;->synchronizedList(Ljava/util/List;)Ljava/util/List;
+HSPLjava/util/Collections;->synchronizedMap(Ljava/util/Map;)Ljava/util/Map;
+HSPLjava/util/Collections;->synchronizedSet(Ljava/util/Set;)Ljava/util/Set;
+HSPLjava/util/Collections;->synchronizedSet(Ljava/util/Set;Ljava/lang/Object;)Ljava/util/Set;
+HSPLjava/util/Collections;->unmodifiableCollection(Ljava/util/Collection;)Ljava/util/Collection;
+HSPLjava/util/Collections;->unmodifiableList(Ljava/util/List;)Ljava/util/List;
+HSPLjava/util/Collections;->unmodifiableMap(Ljava/util/Map;)Ljava/util/Map;
+HSPLjava/util/Collections;->unmodifiableSet(Ljava/util/Set;)Ljava/util/Set;
+HSPLjava/util/Collections;->unmodifiableSortedMap(Ljava/util/SortedMap;)Ljava/util/SortedMap;
+HSPLjava/util/Collections;->unmodifiableSortedSet(Ljava/util/SortedSet;)Ljava/util/SortedSet;
+HSPLjava/util/ComparableTimSort;-><init>([Ljava/lang/Object;[Ljava/lang/Object;II)V
+HSPLjava/util/ComparableTimSort;->binarySort([Ljava/lang/Object;III)V+]Ljava/lang/Comparable;megamorphic_types
+HSPLjava/util/ComparableTimSort;->countRunAndMakeAscending([Ljava/lang/Object;II)I+]Ljava/lang/Comparable;megamorphic_types
+HSPLjava/util/ComparableTimSort;->ensureCapacity(I)[Ljava/lang/Object;
+HSPLjava/util/ComparableTimSort;->gallopLeft(Ljava/lang/Comparable;[Ljava/lang/Object;III)I+]Ljava/lang/Comparable;missing_types
+HSPLjava/util/ComparableTimSort;->gallopRight(Ljava/lang/Comparable;[Ljava/lang/Object;III)I+]Ljava/lang/Comparable;missing_types
+HSPLjava/util/ComparableTimSort;->mergeAt(I)V
+HSPLjava/util/ComparableTimSort;->mergeCollapse()V
+HSPLjava/util/ComparableTimSort;->mergeForceCollapse()V
+HSPLjava/util/ComparableTimSort;->mergeHi(IIII)V+]Ljava/lang/Comparable;missing_types
+HSPLjava/util/ComparableTimSort;->mergeLo(IIII)V+]Ljava/lang/Comparable;missing_types
+HSPLjava/util/ComparableTimSort;->minRunLength(I)I
+HSPLjava/util/ComparableTimSort;->pushRun(II)V
+HSPLjava/util/ComparableTimSort;->reverseRange([Ljava/lang/Object;II)V
+HSPLjava/util/ComparableTimSort;->sort([Ljava/lang/Object;II[Ljava/lang/Object;II)V
+HSPLjava/util/Comparator$$ExternalSyntheticLambda2;-><init>(Ljava/util/function/Function;)V
+HSPLjava/util/Comparator$$ExternalSyntheticLambda4;-><init>(Ljava/util/function/ToIntFunction;)V
+HSPLjava/util/Comparator;->comparing(Ljava/util/function/Function;)Ljava/util/Comparator;
+HSPLjava/util/Comparator;->comparingInt(Ljava/util/function/ToIntFunction;)Ljava/util/Comparator;
+HSPLjava/util/Comparator;->comparingLong(Ljava/util/function/ToLongFunction;)Ljava/util/Comparator;
+HSPLjava/util/Comparator;->lambda$comparing$77a9974f$1(Ljava/util/function/Function;Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/util/function/Function;missing_types]Ljava/lang/Comparable;Ljava/lang/Integer;,Ljava/lang/Boolean;,Ljava/lang/String;,Ljava/lang/Long;,Landroid/content/ComponentName;,Ljava/lang/Double;,Ljava/lang/Float;
+HSPLjava/util/Comparator;->lambda$comparingInt$7b0bb60$1(Ljava/util/function/ToIntFunction;Ljava/lang/Object;Ljava/lang/Object;)I
+HSPLjava/util/Comparator;->lambda$thenComparing$36697e65$1(Ljava/util/Comparator;Ljava/util/Comparator;Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/util/Comparator;missing_types
+HSPLjava/util/Comparator;->naturalOrder()Ljava/util/Comparator;
+HSPLjava/util/Comparator;->reversed()Ljava/util/Comparator;
+HSPLjava/util/Comparator;->thenComparing(Ljava/util/Comparator;)Ljava/util/Comparator;
+HSPLjava/util/Comparator;->thenComparing(Ljava/util/function/Function;)Ljava/util/Comparator;+]Ljava/util/Comparator;Ljava/util/Comparator$$ExternalSyntheticLambda2;
+HSPLjava/util/Comparators$NaturalOrderComparator;->compare(Ljava/lang/Comparable;Ljava/lang/Comparable;)I+]Ljava/lang/Comparable;missing_types
+HSPLjava/util/Comparators$NaturalOrderComparator;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/util/Comparators$NaturalOrderComparator;Ljava/util/Comparators$NaturalOrderComparator;
+HSPLjava/util/Currency;-><init>(Landroid/icu/util/Currency;)V
+HSPLjava/util/Currency;->getCurrencyCode()Ljava/lang/String;
+HSPLjava/util/Currency;->getInstance(Ljava/lang/String;)Ljava/util/Currency;+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/Currency;->getInstance(Ljava/util/Locale;)Ljava/util/Currency;+]Ljava/util/Locale;Ljava/util/Locale;]Landroid/icu/util/Currency;Landroid/icu/util/Currency;
+HSPLjava/util/Currency;->getSymbol(Ljava/util/Locale;)Ljava/lang/String;+]Landroid/icu/util/Currency;missing_types
+HSPLjava/util/Date;-><init>()V
+HSPLjava/util/Date;-><init>(J)V
+HSPLjava/util/Date;->after(Ljava/util/Date;)Z
+HSPLjava/util/Date;->before(Ljava/util/Date;)Z
+HSPLjava/util/Date;->clone()Ljava/lang/Object;
+HSPLjava/util/Date;->compareTo(Ljava/util/Date;)I
+HSPLjava/util/Date;->convertToAbbr(Ljava/lang/StringBuilder;Ljava/lang/String;)Ljava/lang/StringBuilder;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Date;->equals(Ljava/lang/Object;)Z+]Ljava/util/Date;Ljava/util/Date;
+HSPLjava/util/Date;->getCalendarSystem(J)Lsun/util/calendar/BaseCalendar;+]Ljava/util/TimeZone;Llibcore/util/ZoneInfo;
+HSPLjava/util/Date;->getDate()I+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLjava/util/Date;->getHours()I
+HSPLjava/util/Date;->getMillisOf(Ljava/util/Date;)J+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;]Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/Gregorian;
+HSPLjava/util/Date;->getMinutes()I+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLjava/util/Date;->getMonth()I+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLjava/util/Date;->getSeconds()I+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLjava/util/Date;->getTime()J
+HSPLjava/util/Date;->getTimeImpl()J+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLjava/util/Date;->getYear()I+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLjava/util/Date;->normalize()Lsun/util/calendar/BaseCalendar$Date;+]Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/Gregorian;,Lsun/util/calendar/JulianCalendar;]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLjava/util/Date;->setTime(J)V
+HSPLjava/util/Date;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/TimeZone;missing_types]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;,Lsun/util/calendar/JulianCalendar$Date;
+HSPLjava/util/Dictionary;-><init>()V
+HSPLjava/util/DualPivotQuicksort;->doSort([CII[CII)V
+HSPLjava/util/DualPivotQuicksort;->doSort([FII[FII)V
+HSPLjava/util/DualPivotQuicksort;->sort([CIIZ)V
+HSPLjava/util/DualPivotQuicksort;->sort([CII[CII)V
+HSPLjava/util/DualPivotQuicksort;->sort([FIIZ)V
+HSPLjava/util/DualPivotQuicksort;->sort([FII[FII)V
+HSPLjava/util/DualPivotQuicksort;->sort([IIIZ)V
+HSPLjava/util/DualPivotQuicksort;->sort([III[III)V
+HSPLjava/util/DualPivotQuicksort;->sort([JIIZ)V
+HSPLjava/util/DualPivotQuicksort;->sort([JII[JII)V
+HSPLjava/util/EnumMap$EntryIterator$Entry;-><init>(Ljava/util/EnumMap$EntryIterator;I)V
+HSPLjava/util/EnumMap$EntryIterator$Entry;-><init>(Ljava/util/EnumMap$EntryIterator;ILjava/util/EnumMap$1;)V
+HSPLjava/util/EnumMap$EntryIterator$Entry;->checkIndexForEntryUse()V
+HSPLjava/util/EnumMap$EntryIterator$Entry;->getKey()Ljava/lang/Enum;
+HSPLjava/util/EnumMap$EntryIterator$Entry;->getKey()Ljava/lang/Object;+]Ljava/util/EnumMap$EntryIterator$Entry;Ljava/util/EnumMap$EntryIterator$Entry;
+HSPLjava/util/EnumMap$EntryIterator$Entry;->getValue()Ljava/lang/Object;
+HSPLjava/util/EnumMap$EntryIterator;-><init>(Ljava/util/EnumMap;)V
+HSPLjava/util/EnumMap$EntryIterator;-><init>(Ljava/util/EnumMap;Ljava/util/EnumMap$1;)V
+HSPLjava/util/EnumMap$EntryIterator;->next()Ljava/lang/Object;+]Ljava/util/EnumMap$EntryIterator;Ljava/util/EnumMap$EntryIterator;
+HSPLjava/util/EnumMap$EntryIterator;->next()Ljava/util/Map$Entry;+]Ljava/util/EnumMap$EntryIterator;Ljava/util/EnumMap$EntryIterator;
+HSPLjava/util/EnumMap$EntrySet;-><init>(Ljava/util/EnumMap;)V
+HSPLjava/util/EnumMap$EntrySet;-><init>(Ljava/util/EnumMap;Ljava/util/EnumMap$1;)V
+HSPLjava/util/EnumMap$EntrySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/EnumMap$EntrySet;->size()I
+HSPLjava/util/EnumMap$EnumMapIterator;-><init>(Ljava/util/EnumMap;)V
+HSPLjava/util/EnumMap$EnumMapIterator;-><init>(Ljava/util/EnumMap;Ljava/util/EnumMap$1;)V
+HSPLjava/util/EnumMap$EnumMapIterator;->hasNext()Z
+HSPLjava/util/EnumMap$KeyIterator;-><init>(Ljava/util/EnumMap;)V
+HSPLjava/util/EnumMap$KeyIterator;-><init>(Ljava/util/EnumMap;Ljava/util/EnumMap$1;)V
+HSPLjava/util/EnumMap$KeyIterator;->next()Ljava/lang/Enum;+]Ljava/util/EnumMap$KeyIterator;Ljava/util/EnumMap$KeyIterator;
+HSPLjava/util/EnumMap$KeyIterator;->next()Ljava/lang/Object;+]Ljava/util/EnumMap$KeyIterator;Ljava/util/EnumMap$KeyIterator;
+HSPLjava/util/EnumMap$KeySet;-><init>(Ljava/util/EnumMap;)V
+HSPLjava/util/EnumMap$KeySet;-><init>(Ljava/util/EnumMap;Ljava/util/EnumMap$1;)V
+HSPLjava/util/EnumMap$KeySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/EnumMap$ValueIterator;-><init>(Ljava/util/EnumMap;)V
+HSPLjava/util/EnumMap$ValueIterator;-><init>(Ljava/util/EnumMap;Ljava/util/EnumMap$1;)V
+HSPLjava/util/EnumMap$ValueIterator;->next()Ljava/lang/Object;+]Ljava/util/EnumMap$ValueIterator;Ljava/util/EnumMap$ValueIterator;
+HSPLjava/util/EnumMap$Values;-><init>(Ljava/util/EnumMap;)V
+HSPLjava/util/EnumMap$Values;-><init>(Ljava/util/EnumMap;Ljava/util/EnumMap$1;)V
+HSPLjava/util/EnumMap$Values;->iterator()Ljava/util/Iterator;
+HSPLjava/util/EnumMap;-><init>(Ljava/lang/Class;)V
+HSPLjava/util/EnumMap;-><init>(Ljava/util/Map;)V+][Ljava/lang/Object;[Ljava/lang/Object;]Ljava/util/EnumMap;Ljava/util/EnumMap;
+HSPLjava/util/EnumMap;->access$1100(Ljava/util/EnumMap;)[Ljava/lang/Enum;
+HSPLjava/util/EnumMap;->access$1200(Ljava/util/EnumMap;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/EnumMap;->access$200(Ljava/util/EnumMap;)I
+HSPLjava/util/EnumMap;->access$600(Ljava/util/EnumMap;)[Ljava/lang/Object;
+HSPLjava/util/EnumMap;->clear()V
+HSPLjava/util/EnumMap;->containsKey(Ljava/lang/Object;)Z
+HSPLjava/util/EnumMap;->entrySet()Ljava/util/Set;
+HSPLjava/util/EnumMap;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/Enum;megamorphic_types
+HSPLjava/util/EnumMap;->getKeyUniverse(Ljava/lang/Class;)[Ljava/lang/Enum;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/EnumMap;->isValidKey(Ljava/lang/Object;)Z+]Ljava/lang/Object;megamorphic_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/EnumMap;->keySet()Ljava/util/Set;
+HSPLjava/util/EnumMap;->maskNull(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/EnumMap;->put(Ljava/lang/Enum;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/Enum;megamorphic_types
+HSPLjava/util/EnumMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/EnumMap;Ljava/util/EnumMap;
+HSPLjava/util/EnumMap;->putAll(Ljava/util/Map;)V
+HSPLjava/util/EnumMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/EnumMap;->size()I
+HSPLjava/util/EnumMap;->typeCheck(Ljava/lang/Enum;)V+]Ljava/lang/Object;megamorphic_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/EnumMap;->unmaskNull(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/EnumMap;->values()Ljava/util/Collection;
+HSPLjava/util/EnumSet;-><init>(Ljava/lang/Class;[Ljava/lang/Enum;)V
+HSPLjava/util/EnumSet;->allOf(Ljava/lang/Class;)Ljava/util/EnumSet;+]Ljava/util/EnumSet;Ljava/util/RegularEnumSet;,Ljava/util/JumboEnumSet;
+HSPLjava/util/EnumSet;->clone()Ljava/util/EnumSet;
+HSPLjava/util/EnumSet;->complementOf(Ljava/util/EnumSet;)Ljava/util/EnumSet;+]Ljava/util/EnumSet;Ljava/util/RegularEnumSet;
+HSPLjava/util/EnumSet;->copyOf(Ljava/util/Collection;)Ljava/util/EnumSet;+]Ljava/util/EnumSet;Ljava/util/RegularEnumSet;,Ljava/util/JumboEnumSet;]Ljava/util/Collection;missing_types]Ljava/util/Iterator;missing_types
+HSPLjava/util/EnumSet;->copyOf(Ljava/util/EnumSet;)Ljava/util/EnumSet;+]Ljava/util/EnumSet;Ljava/util/RegularEnumSet;
+HSPLjava/util/EnumSet;->getUniverse(Ljava/lang/Class;)[Ljava/lang/Enum;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/EnumSet;->noneOf(Ljava/lang/Class;)Ljava/util/EnumSet;
+HSPLjava/util/EnumSet;->of(Ljava/lang/Enum;)Ljava/util/EnumSet;+]Ljava/util/EnumSet;Ljava/util/RegularEnumSet;,Ljava/util/JumboEnumSet;
+HSPLjava/util/EnumSet;->of(Ljava/lang/Enum;Ljava/lang/Enum;)Ljava/util/EnumSet;+]Ljava/util/EnumSet;Ljava/util/RegularEnumSet;,Ljava/util/JumboEnumSet;
+HSPLjava/util/EnumSet;->of(Ljava/lang/Enum;Ljava/lang/Enum;Ljava/lang/Enum;)Ljava/util/EnumSet;+]Ljava/util/EnumSet;Ljava/util/RegularEnumSet;
+HSPLjava/util/EnumSet;->of(Ljava/lang/Enum;Ljava/lang/Enum;Ljava/lang/Enum;Ljava/lang/Enum;)Ljava/util/EnumSet;+]Ljava/util/EnumSet;Ljava/util/RegularEnumSet;
+HSPLjava/util/EnumSet;->of(Ljava/lang/Enum;[Ljava/lang/Enum;)Ljava/util/EnumSet;+]Ljava/util/EnumSet;Ljava/util/JumboEnumSet;,Ljava/util/RegularEnumSet;
+HSPLjava/util/EnumSet;->typeCheck(Ljava/lang/Enum;)V+]Ljava/lang/Object;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/Formatter$Conversion;->isCharacter(C)Z
+HSPLjava/util/Formatter$Conversion;->isFloat(C)Z
+HSPLjava/util/Formatter$Conversion;->isGeneral(C)Z
+HSPLjava/util/Formatter$Conversion;->isInteger(C)Z
+HSPLjava/util/Formatter$Conversion;->isText(C)Z
+HSPLjava/util/Formatter$Conversion;->isValid(C)Z
+HSPLjava/util/Formatter$DateTime;->isValid(C)Z
+HSPLjava/util/Formatter$FixedString;-><init>(Ljava/util/Formatter;Ljava/lang/String;)V
+HSPLjava/util/Formatter$FixedString;->index()I
+HSPLjava/util/Formatter$FixedString;->print(Ljava/lang/Object;Ljava/util/Locale;)V+]Ljava/lang/Appendable;megamorphic_types
+HSPLjava/util/Formatter$Flags;-><init>(I)V
+HSPLjava/util/Formatter$Flags;->access$100(Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;)Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$Flags;->add(Ljava/util/Formatter$Flags;)Ljava/util/Formatter$Flags;+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$Flags;->contains(Ljava/util/Formatter$Flags;)Z+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$Flags;->parse(C)Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$Flags;->parse(Ljava/lang/String;)Ljava/util/Formatter$Flags;+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$Flags;->valueOf()I
+HSPLjava/util/Formatter$FormatSpecifier;-><init>(Ljava/util/Formatter;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/util/Formatter$FormatSpecifier;->addZeros([CI)[C
+HSPLjava/util/Formatter$FormatSpecifier;->adjustWidth(ILjava/util/Formatter$Flags;Z)I+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->checkBadFlags([Ljava/util/Formatter$Flags;)V+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->checkCharacter()V+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->checkDateTime()V+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->checkFloat()V
+HSPLjava/util/Formatter$FormatSpecifier;->checkGeneral()V+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->checkInteger()V
+HSPLjava/util/Formatter$FormatSpecifier;->checkNumeric()V+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->checkText()V+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->conversion(Ljava/lang/String;)C
+HSPLjava/util/Formatter$FormatSpecifier;->flags(Ljava/lang/String;)Ljava/util/Formatter$Flags;+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->getZero(Ljava/util/Locale;)C+]Ljava/util/Formatter;Ljava/util/Formatter;]Ljava/util/Locale;Ljava/util/Locale;]Ljava/text/DecimalFormatSymbols;Ljava/text/DecimalFormatSymbols;
+HSPLjava/util/Formatter$FormatSpecifier;->index()I
+HSPLjava/util/Formatter$FormatSpecifier;->index(Ljava/lang/String;)I
+HSPLjava/util/Formatter$FormatSpecifier;->justify(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->leadingSign(Ljava/lang/StringBuilder;Z)Ljava/lang/StringBuilder;+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Formatter$FormatSpecifier;->localizedMagnitude(Ljava/lang/StringBuilder;JLjava/util/Formatter$Flags;ILjava/util/Locale;)Ljava/lang/StringBuilder;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/Formatter$FormatSpecifier;->localizedMagnitude(Ljava/lang/StringBuilder;[CLjava/util/Formatter$Flags;ILjava/util/Locale;)Ljava/lang/StringBuilder;+]Ljava/text/DecimalFormatSymbols;Ljava/text/DecimalFormatSymbols;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;]Ljava/util/Locale;Ljava/util/Locale;]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;
+HSPLjava/util/Formatter$FormatSpecifier;->precision(Ljava/lang/String;)I
+HSPLjava/util/Formatter$FormatSpecifier;->print(BLjava/util/Locale;)V
+HSPLjava/util/Formatter$FormatSpecifier;->print(DLjava/util/Locale;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Appendable;missing_types]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->print(FLjava/util/Locale;)V
+HSPLjava/util/Formatter$FormatSpecifier;->print(ILjava/util/Locale;)V
+HSPLjava/util/Formatter$FormatSpecifier;->print(JLjava/util/Locale;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;]Ljava/lang/Appendable;missing_types
+HSPLjava/util/Formatter$FormatSpecifier;->print(Ljava/lang/Object;Ljava/util/Locale;)V+]Ljava/lang/Appendable;missing_types
+HSPLjava/util/Formatter$FormatSpecifier;->print(Ljava/lang/String;)V+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;]Ljava/lang/Appendable;megamorphic_types]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/Formatter$FormatSpecifier;->print(Ljava/lang/StringBuilder;DLjava/util/Locale;Ljava/util/Formatter$Flags;CIZ)V+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;]Lsun/misc/FormattedFloatingDecimal;Lsun/misc/FormattedFloatingDecimal;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/Formatter$FormatSpecifier;->print(Ljava/lang/StringBuilder;Ljava/util/Calendar;CLjava/util/Locale;)Ljava/lang/Appendable;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Calendar;Ljava/util/GregorianCalendar;]Ljava/lang/Appendable;Ljava/lang/StringBuilder;]Ljava/text/DateFormatSymbols;Ljava/text/DateFormatSymbols;]Ljava/lang/String;Ljava/lang/String;]Ljava/util/TimeZone;Llibcore/util/ZoneInfo;
+HSPLjava/util/Formatter$FormatSpecifier;->print(Ljava/math/BigInteger;Ljava/util/Locale;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;]Ljava/math/BigInteger;Ljava/math/BigInteger;]Ljava/lang/Appendable;Ljava/lang/StringBuilder;
+HSPLjava/util/Formatter$FormatSpecifier;->print(Ljava/util/Calendar;CLjava/util/Locale;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;]Ljava/lang/Appendable;Ljava/lang/StringBuilder;,Lcom/android/internal/util/FastPrintWriter;]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/Formatter$FormatSpecifier;->printBoolean(Ljava/lang/Object;)V+]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLjava/util/Formatter$FormatSpecifier;->printCharacter(Ljava/lang/Object;)V+]Ljava/lang/Character;Ljava/lang/Character;]Ljava/lang/Integer;Ljava/lang/Integer;
+HSPLjava/util/Formatter$FormatSpecifier;->printDateTime(Ljava/lang/Object;Ljava/util/Locale;)V+]Ljava/util/Calendar;Ljava/util/GregorianCalendar;]Ljava/lang/Long;Ljava/lang/Long;
+HSPLjava/util/Formatter$FormatSpecifier;->printFloat(Ljava/lang/Object;Ljava/util/Locale;)V+]Ljava/lang/Double;Ljava/lang/Double;]Ljava/lang/Float;Ljava/lang/Float;
+HSPLjava/util/Formatter$FormatSpecifier;->printInteger(Ljava/lang/Object;Ljava/util/Locale;)V+]Ljava/lang/Integer;Ljava/lang/Integer;]Ljava/lang/Long;Ljava/lang/Long;]Ljava/lang/Byte;Ljava/lang/Byte;]Ljava/lang/Short;Ljava/lang/Short;
+HSPLjava/util/Formatter$FormatSpecifier;->printString(Ljava/lang/Object;Ljava/util/Locale;)V+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;]Ljava/lang/Object;megamorphic_types]Ljava/util/Formatter;Ljava/util/Formatter;
+HSPLjava/util/Formatter$FormatSpecifier;->trailingSign(Ljava/lang/StringBuilder;Z)Ljava/lang/StringBuilder;+]Ljava/util/Formatter$Flags;Ljava/util/Formatter$Flags;
+HSPLjava/util/Formatter$FormatSpecifier;->width(Ljava/lang/String;)I
+HSPLjava/util/Formatter$FormatSpecifierParser;-><init>(Ljava/util/Formatter;Ljava/lang/String;I)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Formatter$FormatSpecifierParser;->advance()C
+HSPLjava/util/Formatter$FormatSpecifierParser;->back(I)V
+HSPLjava/util/Formatter$FormatSpecifierParser;->getEndIdx()I
+HSPLjava/util/Formatter$FormatSpecifierParser;->getFormatSpecifier()Ljava/util/Formatter$FormatSpecifier;
+HSPLjava/util/Formatter$FormatSpecifierParser;->isEnd()Z
+HSPLjava/util/Formatter$FormatSpecifierParser;->nextInt()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/Formatter$FormatSpecifierParser;->nextIsInt()Z
+HSPLjava/util/Formatter$FormatSpecifierParser;->peek()C
+HSPLjava/util/Formatter;-><init>()V
+HSPLjava/util/Formatter;-><init>(Ljava/lang/Appendable;)V
+HSPLjava/util/Formatter;-><init>(Ljava/lang/Appendable;Ljava/util/Locale;)V
+HSPLjava/util/Formatter;-><init>(Ljava/util/Locale;)V
+HSPLjava/util/Formatter;-><init>(Ljava/util/Locale;Ljava/lang/Appendable;)V
+HSPLjava/util/Formatter;->access$000(Ljava/util/Formatter;)Ljava/lang/Appendable;
+HSPLjava/util/Formatter;->access$400(Ljava/util/Formatter;)C
+HSPLjava/util/Formatter;->close()V
+HSPLjava/util/Formatter;->ensureOpen()V
+HSPLjava/util/Formatter;->format(Ljava/lang/String;[Ljava/lang/Object;)Ljava/util/Formatter;+]Ljava/util/Formatter;Ljava/util/Formatter;
+HSPLjava/util/Formatter;->format(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/util/Formatter;+]Ljava/util/Formatter$FormatString;Ljava/util/Formatter$FixedString;,Ljava/util/Formatter$FormatSpecifier;
+HSPLjava/util/Formatter;->getZero(Ljava/util/Locale;)C+]Ljava/text/DecimalFormatSymbols;Ljava/text/DecimalFormatSymbols;]Ljava/util/Locale;Ljava/util/Locale;
+HSPLjava/util/Formatter;->locale()Ljava/util/Locale;
+HSPLjava/util/Formatter;->nonNullAppendable(Ljava/lang/Appendable;)Ljava/lang/Appendable;
+HSPLjava/util/Formatter;->out()Ljava/lang/Appendable;
+HSPLjava/util/Formatter;->parse(Ljava/lang/String;)[Ljava/util/Formatter$FormatString;+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/Formatter$FormatSpecifierParser;Ljava/util/Formatter$FormatSpecifierParser;]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/util/Formatter;->toString()Ljava/lang/String;+]Ljava/lang/Object;Ljava/lang/StringBuilder;
+HSPLjava/util/GregorianCalendar;-><init>()V+]Ljava/util/GregorianCalendar;missing_types
+HSPLjava/util/GregorianCalendar;-><init>(IIIIII)V
+HSPLjava/util/GregorianCalendar;-><init>(IIIIIII)V+]Lsun/util/calendar/Gregorian;Lsun/util/calendar/Gregorian;]Ljava/util/GregorianCalendar;Ljava/util/GregorianCalendar;
+HSPLjava/util/GregorianCalendar;-><init>(Ljava/util/TimeZone;)V
+HSPLjava/util/GregorianCalendar;-><init>(Ljava/util/TimeZone;Ljava/util/Locale;)V+]Lsun/util/calendar/Gregorian;Lsun/util/calendar/Gregorian;]Ljava/util/GregorianCalendar;missing_types
+HSPLjava/util/GregorianCalendar;->add(II)V+]Ljava/util/GregorianCalendar;missing_types
+HSPLjava/util/GregorianCalendar;->adjustDstOffsetForInvalidWallClock(JLjava/util/TimeZone;I)I+]Ljava/util/TimeZone;missing_types
+HSPLjava/util/GregorianCalendar;->adjustForZoneAndDaylightSavingsTime(IJLjava/util/TimeZone;)J+]Ljava/util/TimeZone;missing_types]Llibcore/util/ZoneInfo;missing_types]Ljava/util/GregorianCalendar;Ljava/util/GregorianCalendar;
+HSPLjava/util/GregorianCalendar;->clone()Ljava/lang/Object;+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLjava/util/GregorianCalendar;->computeFields()V+]Ljava/util/GregorianCalendar;missing_types
+HSPLjava/util/GregorianCalendar;->computeFields(II)I+]Lsun/util/calendar/Gregorian;Lsun/util/calendar/Gregorian;]Ljava/util/GregorianCalendar;missing_types]Ljava/util/TimeZone;Ljava/util/SimpleTimeZone;]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;,Lsun/util/calendar/JulianCalendar$Date;]Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/Gregorian;,Lsun/util/calendar/JulianCalendar;]Llibcore/util/ZoneInfo;missing_types]Lsun/util/calendar/JulianCalendar;Lsun/util/calendar/JulianCalendar;
+HSPLjava/util/GregorianCalendar;->computeTime()V+]Ljava/util/GregorianCalendar;missing_types
+HSPLjava/util/GregorianCalendar;->getActualMaximum(I)I+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;]Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/Gregorian;]Ljava/util/GregorianCalendar;Ljava/util/GregorianCalendar;]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;
+HSPLjava/util/GregorianCalendar;->getCalendarDate(J)Lsun/util/calendar/BaseCalendar$Date;
+HSPLjava/util/GregorianCalendar;->getCurrentFixedDate()J
+HSPLjava/util/GregorianCalendar;->getFixedDate(Lsun/util/calendar/BaseCalendar;II)J+]Ljava/util/GregorianCalendar;missing_types]Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/Gregorian;,Lsun/util/calendar/JulianCalendar;
+HSPLjava/util/GregorianCalendar;->getGregorianCutoverDate()Lsun/util/calendar/BaseCalendar$Date;
+HSPLjava/util/GregorianCalendar;->getJulianCalendarSystem()Lsun/util/calendar/BaseCalendar;
+HSPLjava/util/GregorianCalendar;->getLeastMaximum(I)I
+HSPLjava/util/GregorianCalendar;->getMaximum(I)I
+HSPLjava/util/GregorianCalendar;->getMinimum(I)I
+HSPLjava/util/GregorianCalendar;->getNormalizedCalendar()Ljava/util/GregorianCalendar;+]Ljava/util/GregorianCalendar;Ljava/util/GregorianCalendar;
+HSPLjava/util/GregorianCalendar;->getTimeZone()Ljava/util/TimeZone;+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;,Lsun/util/calendar/JulianCalendar$Date;
+HSPLjava/util/GregorianCalendar;->getWeekNumber(JJ)I+]Ljava/util/GregorianCalendar;missing_types
+HSPLjava/util/GregorianCalendar;->internalGetEra()I+]Ljava/util/GregorianCalendar;missing_types
+HSPLjava/util/GregorianCalendar;->isCutoverYear(I)Z
+HSPLjava/util/GregorianCalendar;->isLeapYear(I)Z
+HSPLjava/util/GregorianCalendar;->monthLength(I)I+]Ljava/util/GregorianCalendar;Ljava/util/GregorianCalendar;
+HSPLjava/util/GregorianCalendar;->monthLength(II)I+]Ljava/util/GregorianCalendar;Ljava/util/GregorianCalendar;
+HSPLjava/util/GregorianCalendar;->pinDayOfMonth()V+]Ljava/util/GregorianCalendar;Ljava/util/GregorianCalendar;
+HSPLjava/util/GregorianCalendar;->setGregorianChange(J)V
+HSPLjava/util/GregorianCalendar;->setGregorianChange(Ljava/util/Date;)V
+HSPLjava/util/GregorianCalendar;->setTimeZone(Ljava/util/TimeZone;)V+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;,Lsun/util/calendar/JulianCalendar$Date;
+HSPLjava/util/HashMap$EntryIterator;-><init>(Ljava/util/HashMap;)V
+HSPLjava/util/HashMap$EntryIterator;->next()Ljava/lang/Object;+]Ljava/util/HashMap$EntryIterator;Ljava/util/HashMap$EntryIterator;
+HSPLjava/util/HashMap$EntryIterator;->next()Ljava/util/Map$Entry;+]Ljava/util/HashMap$EntryIterator;Ljava/util/HashMap$EntryIterator;
+HSPLjava/util/HashMap$EntrySet;-><init>(Ljava/util/HashMap;)V
+HSPLjava/util/HashMap$EntrySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/HashMap$EntrySet;->size()I
+HSPLjava/util/HashMap$HashIterator;-><init>(Ljava/util/HashMap;)V
+HSPLjava/util/HashMap$HashIterator;->hasNext()Z
+HSPLjava/util/HashMap$HashIterator;->nextNode()Ljava/util/HashMap$Node;
+HSPLjava/util/HashMap$HashIterator;->remove()V+]Ljava/util/HashMap;missing_types
+HSPLjava/util/HashMap$HashMapSpliterator;-><init>(Ljava/util/HashMap;IIII)V
+HSPLjava/util/HashMap$HashMapSpliterator;->estimateSize()J+]Ljava/util/HashMap$HashMapSpliterator;Ljava/util/HashMap$EntrySpliterator;,Ljava/util/HashMap$ValueSpliterator;,Ljava/util/HashMap$KeySpliterator;
+HSPLjava/util/HashMap$HashMapSpliterator;->getFence()I
+HSPLjava/util/HashMap$KeyIterator;-><init>(Ljava/util/HashMap;)V
+HSPLjava/util/HashMap$KeyIterator;->next()Ljava/lang/Object;+]Ljava/util/HashMap$KeyIterator;Ljava/util/HashMap$KeyIterator;
+HSPLjava/util/HashMap$KeySet;-><init>(Ljava/util/HashMap;)V
+HSPLjava/util/HashMap$KeySet;->contains(Ljava/lang/Object;)Z+]Ljava/util/HashMap;missing_types
+HSPLjava/util/HashMap$KeySet;->forEach(Ljava/util/function/Consumer;)V
+HSPLjava/util/HashMap$KeySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/HashMap$KeySet;->remove(Ljava/lang/Object;)Z+]Ljava/util/HashMap;Ljava/util/HashMap;
+HSPLjava/util/HashMap$KeySet;->size()I
+HSPLjava/util/HashMap$KeySpliterator;-><init>(Ljava/util/HashMap;IIII)V
+HSPLjava/util/HashMap$KeySpliterator;->characteristics()I
+HSPLjava/util/HashMap$KeySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V+]Ljava/util/function/Consumer;Ljava/util/stream/ReferencePipeline$4$1;,Ljava/util/stream/ReferencePipeline$3$1;,Ljava/util/stream/ReferencePipeline$2$1;,Ljava/util/stream/SortedOps$SizedRefSortingSink;,Ljava/util/stream/ReduceOps$2ReducingSink;,Ljava/util/stream/ReduceOps$3ReducingSink;,Ljava/util/stream/ForEachOps$ForEachOp$OfRef;
+HSPLjava/util/HashMap$Node;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)V
+HSPLjava/util/HashMap$Node;->getKey()Ljava/lang/Object;
+HSPLjava/util/HashMap$Node;->getValue()Ljava/lang/Object;
+HSPLjava/util/HashMap$Node;->hashCode()I
+HSPLjava/util/HashMap$Node;->setValue(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/HashMap$TreeNode;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)V
+HSPLjava/util/HashMap$TreeNode;->balanceInsertion(Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;)Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap$TreeNode;->find(ILjava/lang/Object;Ljava/lang/Class;)Ljava/util/HashMap$TreeNode;+]Ljava/lang/Object;missing_types]Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap$TreeNode;->getTreeNode(ILjava/lang/Object;)Ljava/util/HashMap$TreeNode;+]Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap$TreeNode;->moveRootToFront([Ljava/util/HashMap$Node;Ljava/util/HashMap$TreeNode;)V
+HSPLjava/util/HashMap$TreeNode;->putTreeVal(Ljava/util/HashMap;[Ljava/util/HashMap$Node;ILjava/lang/Object;Ljava/lang/Object;)Ljava/util/HashMap$TreeNode;+]Ljava/util/HashMap;missing_types]Ljava/lang/Object;missing_types]Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap$TreeNode;->rotateLeft(Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;)Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap$TreeNode;->rotateRight(Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;)Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap$TreeNode;->split(Ljava/util/HashMap;[Ljava/util/HashMap$Node;II)V+]Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap$TreeNode;->treeify([Ljava/util/HashMap$Node;)V
+HSPLjava/util/HashMap$TreeNode;->untreeify(Ljava/util/HashMap;)Ljava/util/HashMap$Node;+]Ljava/util/HashMap;missing_types
+HSPLjava/util/HashMap$ValueIterator;-><init>(Ljava/util/HashMap;)V
+HSPLjava/util/HashMap$ValueIterator;->next()Ljava/lang/Object;+]Ljava/util/HashMap$ValueIterator;Ljava/util/HashMap$ValueIterator;
+HSPLjava/util/HashMap$ValueSpliterator;-><init>(Ljava/util/HashMap;IIII)V
+HSPLjava/util/HashMap$ValueSpliterator;->characteristics()I
+HSPLjava/util/HashMap$ValueSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V+]Ljava/util/function/Consumer;missing_types
+HSPLjava/util/HashMap$ValueSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z+]Ljava/util/HashMap$ValueSpliterator;Ljava/util/HashMap$ValueSpliterator;]Ljava/util/function/Consumer;Ljava/util/stream/ReferencePipeline$2$1;,Ljava/util/stream/ReferencePipeline$7$1;,Ljava/util/stream/MatchOps$1MatchSink;
+HSPLjava/util/HashMap$Values;-><init>(Ljava/util/HashMap;)V
+HSPLjava/util/HashMap$Values;->forEach(Ljava/util/function/Consumer;)V
+HSPLjava/util/HashMap$Values;->iterator()Ljava/util/Iterator;
+HSPLjava/util/HashMap$Values;->size()I
+HSPLjava/util/HashMap$Values;->spliterator()Ljava/util/Spliterator;
+HSPLjava/util/HashMap;-><init>()V
+HSPLjava/util/HashMap;-><init>(I)V
+HSPLjava/util/HashMap;-><init>(IF)V
+HSPLjava/util/HashMap;-><init>(Ljava/util/Map;)V+]Ljava/util/HashMap;missing_types
+HSPLjava/util/HashMap;->afterNodeAccess(Ljava/util/HashMap$Node;)V
+HSPLjava/util/HashMap;->afterNodeInsertion(Z)V
+HSPLjava/util/HashMap;->afterNodeRemoval(Ljava/util/HashMap$Node;)V
+HSPLjava/util/HashMap;->capacity()I
+HSPLjava/util/HashMap;->clear()V
+HSPLjava/util/HashMap;->clone()Ljava/lang/Object;+]Ljava/util/HashMap;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;
+HSPLjava/util/HashMap;->computeIfAbsent(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;+]Ljava/util/HashMap;Ljava/util/HashMap;]Ljava/util/function/Function;Ljava/util/stream/Collectors$$ExternalSyntheticLambda49;]Ljava/lang/Object;missing_types
+HSPLjava/util/HashMap;->containsKey(Ljava/lang/Object;)Z+]Ljava/util/HashMap;megamorphic_types
+HSPLjava/util/HashMap;->containsValue(Ljava/lang/Object;)Z+]Ljava/lang/Object;missing_types
+HSPLjava/util/HashMap;->entrySet()Ljava/util/Set;
+HSPLjava/util/HashMap;->forEach(Ljava/util/function/BiConsumer;)V+]Ljava/util/function/BiConsumer;missing_types
+HSPLjava/util/HashMap;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/HashMap;megamorphic_types
+HSPLjava/util/HashMap;->getNode(ILjava/lang/Object;)Ljava/util/HashMap$Node;+]Ljava/lang/Object;megamorphic_types]Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap;->getOrDefault(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/HashMap;missing_types
+HSPLjava/util/HashMap;->hash(Ljava/lang/Object;)I+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/HashMap;->internalWriteEntries(Ljava/io/ObjectOutputStream;)V+]Ljava/io/ObjectOutputStream;Ljava/io/ObjectOutputStream;
+HSPLjava/util/HashMap;->isEmpty()Z
+HSPLjava/util/HashMap;->keySet()Ljava/util/Set;
+HSPLjava/util/HashMap;->loadFactor()F
+HSPLjava/util/HashMap;->merge(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;+]Ljava/util/HashMap;Ljava/util/HashMap;]Ljava/util/function/BiFunction;Lcom/android/internal/graphics/palette/QuantizerMap$$ExternalSyntheticLambda0;]Ljava/lang/Object;Ljava/lang/Integer;]Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap;->newNode(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node;
+HSPLjava/util/HashMap;->newTreeNode(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/HashMap;megamorphic_types
+HSPLjava/util/HashMap;->putAll(Ljava/util/Map;)V+]Ljava/util/HashMap;missing_types
+HSPLjava/util/HashMap;->putIfAbsent(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/HashMap;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;
+HSPLjava/util/HashMap;->putMapEntries(Ljava/util/Map;Z)V+]Ljava/util/HashMap;missing_types]Ljava/util/Map$Entry;megamorphic_types]Ljava/util/Map;megamorphic_types]Ljava/util/Iterator;megamorphic_types]Ljava/util/Set;megamorphic_types
+HSPLjava/util/HashMap;->putVal(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object;+]Ljava/util/HashMap;megamorphic_types]Ljava/lang/Object;megamorphic_types]Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap;->readObject(Ljava/io/ObjectInputStream;)V+]Ljava/util/HashMap;missing_types]Ljava/io/ObjectInputStream;missing_types
+HSPLjava/util/HashMap;->reinitialize()V
+HSPLjava/util/HashMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/HashMap;missing_types
+HSPLjava/util/HashMap;->removeNode(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/util/HashMap$Node;+]Ljava/util/HashMap;megamorphic_types]Ljava/lang/Object;megamorphic_types]Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap;->replacementNode(Ljava/util/HashMap$Node;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node;
+HSPLjava/util/HashMap;->replacementTreeNode(Ljava/util/HashMap$Node;Ljava/util/HashMap$Node;)Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap;->resize()[Ljava/util/HashMap$Node;+]Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap;->size()I
+HSPLjava/util/HashMap;->tableSizeFor(I)I
+HSPLjava/util/HashMap;->treeifyBin([Ljava/util/HashMap$Node;I)V+]Ljava/util/HashMap;missing_types]Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;
+HSPLjava/util/HashMap;->values()Ljava/util/Collection;
+HSPLjava/util/HashMap;->writeObject(Ljava/io/ObjectOutputStream;)V+]Ljava/util/HashMap;missing_types]Ljava/io/ObjectOutputStream;Ljava/io/ObjectOutputStream;
+HSPLjava/util/HashSet;-><init>()V
+HSPLjava/util/HashSet;-><init>(I)V
+HSPLjava/util/HashSet;-><init>(IF)V
+HSPLjava/util/HashSet;-><init>(IFZ)V
+HSPLjava/util/HashSet;-><init>(Ljava/util/Collection;)V+]Ljava/util/Collection;megamorphic_types]Ljava/util/HashSet;missing_types
+HSPLjava/util/HashSet;->add(Ljava/lang/Object;)Z+]Ljava/util/HashMap;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;
+HSPLjava/util/HashSet;->clear()V+]Ljava/util/HashMap;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;
+HSPLjava/util/HashSet;->clone()Ljava/lang/Object;+]Ljava/util/HashMap;Ljava/util/HashMap;
+HSPLjava/util/HashSet;->contains(Ljava/lang/Object;)Z+]Ljava/util/HashMap;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;
+HSPLjava/util/HashSet;->isEmpty()Z+]Ljava/util/HashMap;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;
+HSPLjava/util/HashSet;->iterator()Ljava/util/Iterator;+]Ljava/util/HashMap;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;]Ljava/util/Set;Ljava/util/HashMap$KeySet;,Ljava/util/LinkedHashMap$LinkedKeySet;
+HSPLjava/util/HashSet;->readObject(Ljava/io/ObjectInputStream;)V+]Ljava/util/HashMap;Ljava/util/HashMap;]Ljava/io/ObjectInputStream;missing_types
+HSPLjava/util/HashSet;->remove(Ljava/lang/Object;)Z+]Ljava/util/HashMap;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;
+HSPLjava/util/HashSet;->size()I+]Ljava/util/HashMap;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;
+HSPLjava/util/HashSet;->spliterator()Ljava/util/Spliterator;
+HSPLjava/util/HashSet;->writeObject(Ljava/io/ObjectOutputStream;)V+]Ljava/util/HashMap;Ljava/util/HashMap;,Ljava/util/LinkedHashMap;]Ljava/io/ObjectOutputStream;Ljava/io/ObjectOutputStream;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;,Ljava/util/LinkedHashMap$LinkedKeyIterator;]Ljava/util/Set;Ljava/util/HashMap$KeySet;,Ljava/util/LinkedHashMap$LinkedKeySet;
+HSPLjava/util/Hashtable$EntrySet;-><init>(Ljava/util/Hashtable;)V
+HSPLjava/util/Hashtable$EntrySet;-><init>(Ljava/util/Hashtable;Ljava/util/Hashtable$1;)V
+HSPLjava/util/Hashtable$EntrySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/Hashtable$Enumerator;-><init>(Ljava/util/Hashtable;IZ)V
+HSPLjava/util/Hashtable$Enumerator;->hasMoreElements()Z
+HSPLjava/util/Hashtable$Enumerator;->hasNext()Z+]Ljava/util/Hashtable$Enumerator;Ljava/util/Hashtable$Enumerator;
+HSPLjava/util/Hashtable$Enumerator;->next()Ljava/lang/Object;+]Ljava/util/Hashtable$Enumerator;Ljava/util/Hashtable$Enumerator;
+HSPLjava/util/Hashtable$Enumerator;->nextElement()Ljava/lang/Object;
+HSPLjava/util/Hashtable$HashtableEntry;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/Hashtable$HashtableEntry;)V
+HSPLjava/util/Hashtable$HashtableEntry;->getKey()Ljava/lang/Object;
+HSPLjava/util/Hashtable$HashtableEntry;->getValue()Ljava/lang/Object;
+HSPLjava/util/Hashtable$KeySet;-><init>(Ljava/util/Hashtable;)V
+HSPLjava/util/Hashtable$KeySet;-><init>(Ljava/util/Hashtable;Ljava/util/Hashtable$1;)V
+HSPLjava/util/Hashtable$KeySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/Hashtable$KeySet;->size()I
+HSPLjava/util/Hashtable$ValueCollection;-><init>(Ljava/util/Hashtable;)V
+HSPLjava/util/Hashtable$ValueCollection;-><init>(Ljava/util/Hashtable;Ljava/util/Hashtable$1;)V
+HSPLjava/util/Hashtable$ValueCollection;->iterator()Ljava/util/Iterator;
+HSPLjava/util/Hashtable$ValueCollection;->size()I
+HSPLjava/util/Hashtable;-><init>()V
+HSPLjava/util/Hashtable;-><init>(I)V
+HSPLjava/util/Hashtable;-><init>(IF)V
+HSPLjava/util/Hashtable;->access$100(Ljava/util/Hashtable;I)Ljava/util/Iterator;
+HSPLjava/util/Hashtable;->access$200(Ljava/util/Hashtable;)I
+HSPLjava/util/Hashtable;->access$400(Ljava/util/Hashtable;)[Ljava/util/Hashtable$HashtableEntry;
+HSPLjava/util/Hashtable;->access$500(Ljava/util/Hashtable;)I
+HSPLjava/util/Hashtable;->addEntry(ILjava/lang/Object;Ljava/lang/Object;I)V+]Ljava/lang/Object;missing_types]Ljava/util/Hashtable;missing_types
+HSPLjava/util/Hashtable;->clear()V
+HSPLjava/util/Hashtable;->containsKey(Ljava/lang/Object;)Z+]Ljava/lang/Object;missing_types
+HSPLjava/util/Hashtable;->entrySet()Ljava/util/Set;
+HSPLjava/util/Hashtable;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/Object;missing_types
+HSPLjava/util/Hashtable;->getEnumeration(I)Ljava/util/Enumeration;
+HSPLjava/util/Hashtable;->getIterator(I)Ljava/util/Iterator;
+HSPLjava/util/Hashtable;->isEmpty()Z
+HSPLjava/util/Hashtable;->keySet()Ljava/util/Set;
+HSPLjava/util/Hashtable;->keys()Ljava/util/Enumeration;
+HSPLjava/util/Hashtable;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/Object;missing_types
+HSPLjava/util/Hashtable;->rehash()V
+HSPLjava/util/Hashtable;->remove(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/Object;missing_types
+HSPLjava/util/Hashtable;->remove(Ljava/lang/Object;Ljava/lang/Object;)Z+]Ljava/lang/Object;Ljava/lang/String;,Ljava/util/logging/LogManager$LoggerWeakRef;
+HSPLjava/util/Hashtable;->size()I
+HSPLjava/util/Hashtable;->values()Ljava/util/Collection;
+HSPLjava/util/IdentityHashMap$EntryIterator$Entry;-><init>(Ljava/util/IdentityHashMap$EntryIterator;I)V
+HSPLjava/util/IdentityHashMap$EntryIterator$Entry;-><init>(Ljava/util/IdentityHashMap$EntryIterator;ILjava/util/IdentityHashMap$1;)V
+HSPLjava/util/IdentityHashMap$EntryIterator$Entry;->checkIndexForEntryUse()V
+HSPLjava/util/IdentityHashMap$EntryIterator$Entry;->getKey()Ljava/lang/Object;
+HSPLjava/util/IdentityHashMap$EntryIterator$Entry;->getValue()Ljava/lang/Object;
+HSPLjava/util/IdentityHashMap$EntryIterator;-><init>(Ljava/util/IdentityHashMap;)V
+HSPLjava/util/IdentityHashMap$EntryIterator;-><init>(Ljava/util/IdentityHashMap;Ljava/util/IdentityHashMap$1;)V
+HSPLjava/util/IdentityHashMap$EntryIterator;->next()Ljava/lang/Object;+]Ljava/util/IdentityHashMap$EntryIterator;Ljava/util/IdentityHashMap$EntryIterator;
+HSPLjava/util/IdentityHashMap$EntryIterator;->next()Ljava/util/Map$Entry;+]Ljava/util/IdentityHashMap$EntryIterator;Ljava/util/IdentityHashMap$EntryIterator;
+HSPLjava/util/IdentityHashMap$EntrySet;-><init>(Ljava/util/IdentityHashMap;)V
+HSPLjava/util/IdentityHashMap$EntrySet;-><init>(Ljava/util/IdentityHashMap;Ljava/util/IdentityHashMap$1;)V
+HSPLjava/util/IdentityHashMap$EntrySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/IdentityHashMap$IdentityHashMapIterator;-><init>(Ljava/util/IdentityHashMap;)V
+HSPLjava/util/IdentityHashMap$IdentityHashMapIterator;-><init>(Ljava/util/IdentityHashMap;Ljava/util/IdentityHashMap$1;)V
+HSPLjava/util/IdentityHashMap$IdentityHashMapIterator;->hasNext()Z
+HSPLjava/util/IdentityHashMap$IdentityHashMapIterator;->nextIndex()I+]Ljava/util/IdentityHashMap$IdentityHashMapIterator;Ljava/util/IdentityHashMap$KeyIterator;
+HSPLjava/util/IdentityHashMap$KeyIterator;-><init>(Ljava/util/IdentityHashMap;)V
+HSPLjava/util/IdentityHashMap$KeyIterator;-><init>(Ljava/util/IdentityHashMap;Ljava/util/IdentityHashMap$1;)V
+HSPLjava/util/IdentityHashMap$KeyIterator;->next()Ljava/lang/Object;+]Ljava/util/IdentityHashMap$KeyIterator;Ljava/util/IdentityHashMap$KeyIterator;
+HSPLjava/util/IdentityHashMap$KeySet;-><init>(Ljava/util/IdentityHashMap;)V
+HSPLjava/util/IdentityHashMap$KeySet;-><init>(Ljava/util/IdentityHashMap;Ljava/util/IdentityHashMap$1;)V
+HSPLjava/util/IdentityHashMap$KeySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/IdentityHashMap$KeySet;->size()I
+HSPLjava/util/IdentityHashMap$ValueIterator;-><init>(Ljava/util/IdentityHashMap;)V
+HSPLjava/util/IdentityHashMap$ValueIterator;-><init>(Ljava/util/IdentityHashMap;Ljava/util/IdentityHashMap$1;)V
+HSPLjava/util/IdentityHashMap$ValueIterator;->next()Ljava/lang/Object;+]Ljava/util/IdentityHashMap$ValueIterator;Ljava/util/IdentityHashMap$ValueIterator;
+HSPLjava/util/IdentityHashMap$Values;-><init>(Ljava/util/IdentityHashMap;)V
+HSPLjava/util/IdentityHashMap$Values;-><init>(Ljava/util/IdentityHashMap;Ljava/util/IdentityHashMap$1;)V
+HSPLjava/util/IdentityHashMap$Values;->iterator()Ljava/util/Iterator;
+HSPLjava/util/IdentityHashMap;-><init>()V
+HSPLjava/util/IdentityHashMap;-><init>(I)V
+HSPLjava/util/IdentityHashMap;->capacity(I)I
+HSPLjava/util/IdentityHashMap;->clear()V
+HSPLjava/util/IdentityHashMap;->closeDeletion(I)V
+HSPLjava/util/IdentityHashMap;->containsKey(Ljava/lang/Object;)Z
+HSPLjava/util/IdentityHashMap;->entrySet()Ljava/util/Set;
+HSPLjava/util/IdentityHashMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/IdentityHashMap;->hash(Ljava/lang/Object;I)I
+HSPLjava/util/IdentityHashMap;->init(I)V
+HSPLjava/util/IdentityHashMap;->isEmpty()Z
+HSPLjava/util/IdentityHashMap;->keySet()Ljava/util/Set;
+HSPLjava/util/IdentityHashMap;->maskNull(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/IdentityHashMap;->nextKeyIndex(II)I
+HSPLjava/util/IdentityHashMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/IdentityHashMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/IdentityHashMap;->resize(I)Z
+HSPLjava/util/IdentityHashMap;->size()I
+HSPLjava/util/IdentityHashMap;->unmaskNull(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/IdentityHashMap;->values()Ljava/util/Collection;
+HSPLjava/util/ImmutableCollections$AbstractImmutableCollection;-><init>()V
+HSPLjava/util/ImmutableCollections$AbstractImmutableList;-><init>()V
+HSPLjava/util/ImmutableCollections$ListN;-><init>([Ljava/lang/Object;)V
+HSPLjava/util/ImmutableCollections;-><clinit>()V
+HSPLjava/util/Iterator;->forEachRemaining(Ljava/util/function/Consumer;)V+]Ljava/util/function/Consumer;megamorphic_types]Ljava/util/Iterator;missing_types
+HSPLjava/util/JumboEnumSet$EnumSetIterator;-><init>(Ljava/util/JumboEnumSet;)V
+HSPLjava/util/JumboEnumSet$EnumSetIterator;->hasNext()Z
+HSPLjava/util/JumboEnumSet$EnumSetIterator;->next()Ljava/lang/Enum;+]Ljava/util/JumboEnumSet$EnumSetIterator;Ljava/util/JumboEnumSet$EnumSetIterator;
+HSPLjava/util/JumboEnumSet$EnumSetIterator;->next()Ljava/lang/Object;+]Ljava/util/JumboEnumSet$EnumSetIterator;Ljava/util/JumboEnumSet$EnumSetIterator;
+HSPLjava/util/JumboEnumSet;-><init>(Ljava/lang/Class;[Ljava/lang/Enum;)V
+HSPLjava/util/JumboEnumSet;->access$000(Ljava/util/JumboEnumSet;)[J
+HSPLjava/util/JumboEnumSet;->add(Ljava/lang/Enum;)Z+]Ljava/util/JumboEnumSet;Ljava/util/JumboEnumSet;
+HSPLjava/util/JumboEnumSet;->add(Ljava/lang/Object;)Z+]Ljava/util/JumboEnumSet;Ljava/util/JumboEnumSet;
+HSPLjava/util/JumboEnumSet;->contains(Ljava/lang/Object;)Z
+HSPLjava/util/JumboEnumSet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/JumboEnumSet;->size()I
+HSPLjava/util/LinkedHashMap$LinkedEntryIterator;-><init>(Ljava/util/LinkedHashMap;)V
+HSPLjava/util/LinkedHashMap$LinkedEntryIterator;->next()Ljava/lang/Object;+]Ljava/util/LinkedHashMap$LinkedEntryIterator;Ljava/util/LinkedHashMap$LinkedEntryIterator;
+HSPLjava/util/LinkedHashMap$LinkedEntryIterator;->next()Ljava/util/Map$Entry;+]Ljava/util/LinkedHashMap$LinkedEntryIterator;Ljava/util/LinkedHashMap$LinkedEntryIterator;
+HSPLjava/util/LinkedHashMap$LinkedEntrySet;-><init>(Ljava/util/LinkedHashMap;)V
+HSPLjava/util/LinkedHashMap$LinkedEntrySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/LinkedHashMap$LinkedEntrySet;->size()I
+HSPLjava/util/LinkedHashMap$LinkedHashIterator;-><init>(Ljava/util/LinkedHashMap;)V
+HSPLjava/util/LinkedHashMap$LinkedHashIterator;->hasNext()Z
+HSPLjava/util/LinkedHashMap$LinkedHashIterator;->nextNode()Ljava/util/LinkedHashMap$LinkedHashMapEntry;
+HSPLjava/util/LinkedHashMap$LinkedHashIterator;->remove()V+]Ljava/util/LinkedHashMap;missing_types
+HSPLjava/util/LinkedHashMap$LinkedHashMapEntry;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)V
+HSPLjava/util/LinkedHashMap$LinkedKeyIterator;-><init>(Ljava/util/LinkedHashMap;)V
+HSPLjava/util/LinkedHashMap$LinkedKeyIterator;->next()Ljava/lang/Object;+]Ljava/util/LinkedHashMap$LinkedHashMapEntry;Ljava/util/LinkedHashMap$LinkedHashMapEntry;,Ljava/util/HashMap$TreeNode;]Ljava/util/LinkedHashMap$LinkedKeyIterator;Ljava/util/LinkedHashMap$LinkedKeyIterator;
+HSPLjava/util/LinkedHashMap$LinkedKeySet;-><init>(Ljava/util/LinkedHashMap;)V
+HSPLjava/util/LinkedHashMap$LinkedKeySet;->contains(Ljava/lang/Object;)Z+]Ljava/util/LinkedHashMap;missing_types
+HSPLjava/util/LinkedHashMap$LinkedKeySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/LinkedHashMap$LinkedKeySet;->size()I
+HSPLjava/util/LinkedHashMap$LinkedValueIterator;-><init>(Ljava/util/LinkedHashMap;)V
+HSPLjava/util/LinkedHashMap$LinkedValueIterator;->next()Ljava/lang/Object;+]Ljava/util/LinkedHashMap$LinkedValueIterator;Ljava/util/LinkedHashMap$LinkedValueIterator;
+HSPLjava/util/LinkedHashMap$LinkedValues;-><init>(Ljava/util/LinkedHashMap;)V
+HSPLjava/util/LinkedHashMap$LinkedValues;->iterator()Ljava/util/Iterator;
+HSPLjava/util/LinkedHashMap$LinkedValues;->size()I
+HSPLjava/util/LinkedHashMap;-><init>()V
+HSPLjava/util/LinkedHashMap;-><init>(I)V
+HSPLjava/util/LinkedHashMap;-><init>(IF)V
+HSPLjava/util/LinkedHashMap;-><init>(IFZ)V
+HSPLjava/util/LinkedHashMap;-><init>(Ljava/util/Map;)V+]Ljava/util/LinkedHashMap;missing_types
+HSPLjava/util/LinkedHashMap;->afterNodeAccess(Ljava/util/HashMap$Node;)V
+HSPLjava/util/LinkedHashMap;->afterNodeInsertion(Z)V+]Ljava/util/LinkedHashMap;missing_types
+HSPLjava/util/LinkedHashMap;->afterNodeRemoval(Ljava/util/HashMap$Node;)V
+HSPLjava/util/LinkedHashMap;->clear()V
+HSPLjava/util/LinkedHashMap;->eldest()Ljava/util/Map$Entry;
+HSPLjava/util/LinkedHashMap;->entrySet()Ljava/util/Set;
+HSPLjava/util/LinkedHashMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/LinkedHashMap;->keySet()Ljava/util/Set;
+HSPLjava/util/LinkedHashMap;->linkNodeLast(Ljava/util/LinkedHashMap$LinkedHashMapEntry;)V
+HSPLjava/util/LinkedHashMap;->newNode(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node;
+HSPLjava/util/LinkedHashMap;->reinitialize()V
+HSPLjava/util/LinkedHashMap;->removeEldestEntry(Ljava/util/Map$Entry;)Z
+HSPLjava/util/LinkedHashMap;->values()Ljava/util/Collection;
+HSPLjava/util/LinkedHashSet;-><init>()V
+HSPLjava/util/LinkedHashSet;-><init>(I)V
+HSPLjava/util/LinkedHashSet;-><init>(Ljava/util/Collection;)V+]Ljava/util/Collection;megamorphic_types]Ljava/util/LinkedHashSet;Ljava/util/LinkedHashSet;
+HSPLjava/util/LinkedList$ListItr;-><init>(Ljava/util/LinkedList;I)V+]Ljava/util/LinkedList;missing_types
+HSPLjava/util/LinkedList$ListItr;->add(Ljava/lang/Object;)V+]Ljava/util/LinkedList;Ljava/util/LinkedList;]Ljava/util/LinkedList$ListItr;Ljava/util/LinkedList$ListItr;
+HSPLjava/util/LinkedList$ListItr;->checkForComodification()V
+HSPLjava/util/LinkedList$ListItr;->hasNext()Z
+HSPLjava/util/LinkedList$ListItr;->hasPrevious()Z
+HSPLjava/util/LinkedList$ListItr;->next()Ljava/lang/Object;+]Ljava/util/LinkedList$ListItr;Ljava/util/LinkedList$ListItr;
+HSPLjava/util/LinkedList$ListItr;->previous()Ljava/lang/Object;+]Ljava/util/LinkedList$ListItr;Ljava/util/LinkedList$ListItr;
+HSPLjava/util/LinkedList$ListItr;->remove()V+]Ljava/util/LinkedList;Ljava/util/LinkedList;]Ljava/util/LinkedList$ListItr;Ljava/util/LinkedList$ListItr;
+HSPLjava/util/LinkedList$ListItr;->set(Ljava/lang/Object;)V+]Ljava/util/LinkedList$ListItr;Ljava/util/LinkedList$ListItr;
+HSPLjava/util/LinkedList$Node;-><init>(Ljava/util/LinkedList$Node;Ljava/lang/Object;Ljava/util/LinkedList$Node;)V
+HSPLjava/util/LinkedList;-><init>()V
+HSPLjava/util/LinkedList;-><init>(Ljava/util/Collection;)V+]Ljava/util/LinkedList;Ljava/util/LinkedList;
+HSPLjava/util/LinkedList;->add(ILjava/lang/Object;)V+]Ljava/util/LinkedList;Ljava/util/LinkedList;
+HSPLjava/util/LinkedList;->add(Ljava/lang/Object;)Z+]Ljava/util/LinkedList;missing_types
+HSPLjava/util/LinkedList;->addAll(ILjava/util/Collection;)Z+]Ljava/util/Collection;megamorphic_types]Ljava/util/LinkedList;Ljava/util/LinkedList;
+HSPLjava/util/LinkedList;->addAll(Ljava/util/Collection;)Z+]Ljava/util/LinkedList;Ljava/util/LinkedList;
+HSPLjava/util/LinkedList;->addFirst(Ljava/lang/Object;)V
+HSPLjava/util/LinkedList;->addLast(Ljava/lang/Object;)V+]Ljava/util/LinkedList;missing_types
+HSPLjava/util/LinkedList;->checkElementIndex(I)V
+HSPLjava/util/LinkedList;->checkPositionIndex(I)V
+HSPLjava/util/LinkedList;->clear()V
+HSPLjava/util/LinkedList;->contains(Ljava/lang/Object;)Z+]Ljava/util/LinkedList;Ljava/util/LinkedList;
+HSPLjava/util/LinkedList;->get(I)Ljava/lang/Object;+]Ljava/util/LinkedList;missing_types
+HSPLjava/util/LinkedList;->getFirst()Ljava/lang/Object;
+HSPLjava/util/LinkedList;->getLast()Ljava/lang/Object;
+HSPLjava/util/LinkedList;->indexOf(Ljava/lang/Object;)I+]Ljava/lang/Object;missing_types
+HSPLjava/util/LinkedList;->isElementIndex(I)Z
+HSPLjava/util/LinkedList;->isPositionIndex(I)Z
+HSPLjava/util/LinkedList;->linkBefore(Ljava/lang/Object;Ljava/util/LinkedList$Node;)V
+HSPLjava/util/LinkedList;->linkFirst(Ljava/lang/Object;)V
+HSPLjava/util/LinkedList;->linkLast(Ljava/lang/Object;)V
+HSPLjava/util/LinkedList;->listIterator(I)Ljava/util/ListIterator;
+HSPLjava/util/LinkedList;->node(I)Ljava/util/LinkedList$Node;
+HSPLjava/util/LinkedList;->offer(Ljava/lang/Object;)Z+]Ljava/util/LinkedList;Ljava/util/LinkedList;
+HSPLjava/util/LinkedList;->peek()Ljava/lang/Object;
+HSPLjava/util/LinkedList;->peekFirst()Ljava/lang/Object;
+HSPLjava/util/LinkedList;->peekLast()Ljava/lang/Object;
+HSPLjava/util/LinkedList;->poll()Ljava/lang/Object;
+HSPLjava/util/LinkedList;->pop()Ljava/lang/Object;+]Ljava/util/LinkedList;Ljava/util/LinkedList;
+HSPLjava/util/LinkedList;->push(Ljava/lang/Object;)V+]Ljava/util/LinkedList;Ljava/util/LinkedList;
+HSPLjava/util/LinkedList;->remove()Ljava/lang/Object;+]Ljava/util/LinkedList;missing_types
+HSPLjava/util/LinkedList;->remove(I)Ljava/lang/Object;+]Ljava/util/LinkedList;Ljava/util/LinkedList;
+HSPLjava/util/LinkedList;->remove(Ljava/lang/Object;)Z+]Ljava/lang/Object;missing_types]Ljava/util/LinkedList;missing_types
+HSPLjava/util/LinkedList;->removeFirst()Ljava/lang/Object;
+HSPLjava/util/LinkedList;->removeLast()Ljava/lang/Object;
+HSPLjava/util/LinkedList;->set(ILjava/lang/Object;)Ljava/lang/Object;+]Ljava/util/LinkedList;Ljava/util/LinkedList;
+HSPLjava/util/LinkedList;->size()I
+HSPLjava/util/LinkedList;->toArray()[Ljava/lang/Object;
+HSPLjava/util/LinkedList;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;+]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/Object;missing_types
+HSPLjava/util/LinkedList;->unlink(Ljava/util/LinkedList$Node;)Ljava/lang/Object;
+HSPLjava/util/LinkedList;->unlinkFirst(Ljava/util/LinkedList$Node;)Ljava/lang/Object;
+HSPLjava/util/LinkedList;->unlinkLast(Ljava/util/LinkedList$Node;)Ljava/lang/Object;
+HSPLjava/util/List;->sort(Ljava/util/Comparator;)V+]Ljava/util/ListIterator;Ljava/util/LinkedList$ListItr;,Ljava/util/ArrayList$SubList$1;,Ljava/util/AbstractList$SubList$1;]Ljava/util/List;Ljava/util/LinkedList;,Ljava/util/ArrayList$SubList;,Ljava/util/AbstractList$SubList;
+HSPLjava/util/List;->spliterator()Ljava/util/Spliterator;
+HSPLjava/util/Locale$Builder;-><init>()V
+HSPLjava/util/Locale$Builder;->build()Ljava/util/Locale;+]Lsun/util/locale/InternalLocaleBuilder;Lsun/util/locale/InternalLocaleBuilder;]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale$Builder;->setLanguage(Ljava/lang/String;)Ljava/util/Locale$Builder;+]Lsun/util/locale/InternalLocaleBuilder;Lsun/util/locale/InternalLocaleBuilder;
+HSPLjava/util/Locale$Builder;->setRegion(Ljava/lang/String;)Ljava/util/Locale$Builder;+]Lsun/util/locale/InternalLocaleBuilder;Lsun/util/locale/InternalLocaleBuilder;
+HSPLjava/util/Locale$Builder;->setScript(Ljava/lang/String;)Ljava/util/Locale$Builder;+]Lsun/util/locale/InternalLocaleBuilder;Lsun/util/locale/InternalLocaleBuilder;
+HSPLjava/util/Locale$Builder;->setVariant(Ljava/lang/String;)Ljava/util/Locale$Builder;+]Lsun/util/locale/InternalLocaleBuilder;Lsun/util/locale/InternalLocaleBuilder;
+HSPLjava/util/Locale$Cache;->createObject(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Locale$Cache;Ljava/util/Locale$Cache;
+HSPLjava/util/Locale$Cache;->createObject(Ljava/util/Locale$LocaleKey;)Ljava/util/Locale;
+HSPLjava/util/Locale$LocaleKey;-><init>(Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;)V+]Lsun/util/locale/LocaleExtensions;Lsun/util/locale/LocaleExtensions;]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale$LocaleKey;-><init>(Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;Ljava/util/Locale$1;)V
+HSPLjava/util/Locale$LocaleKey;->access$200(Ljava/util/Locale$LocaleKey;)Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale$LocaleKey;->access$300(Ljava/util/Locale$LocaleKey;)Lsun/util/locale/LocaleExtensions;
+HSPLjava/util/Locale$LocaleKey;->equals(Ljava/lang/Object;)Z+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;]Lsun/util/locale/LocaleExtensions;Lsun/util/locale/LocaleExtensions;
+HSPLjava/util/Locale$LocaleKey;->hashCode()I
+HSPLjava/util/Locale;-><init>(Ljava/lang/String;)V
+HSPLjava/util/Locale;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/util/Locale;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/util/Locale;-><init>(Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;)V
+HSPLjava/util/Locale;-><init>(Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;Ljava/util/Locale$1;)V
+HSPLjava/util/Locale;->access$700(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lsun/util/locale/LocaleExtensions;
+HSPLjava/util/Locale;->clone()Ljava/lang/Object;
+HSPLjava/util/Locale;->convertOldISOCodes(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/Locale;->equals(Ljava/lang/Object;)Z+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->forLanguageTag(Ljava/lang/String;)Ljava/util/Locale;+]Lsun/util/locale/InternalLocaleBuilder;Lsun/util/locale/InternalLocaleBuilder;]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->getAvailableLocales()[Ljava/util/Locale;
+HSPLjava/util/Locale;->getBaseLocale()Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->getCompatibilityExtensions(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lsun/util/locale/LocaleExtensions;
+HSPLjava/util/Locale;->getCountry()Ljava/lang/String;+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->getDefault()Ljava/util/Locale;
+HSPLjava/util/Locale;->getDefault(Ljava/util/Locale$Category;)Ljava/util/Locale;+]Ljava/util/Locale$Category;Ljava/util/Locale$Category;
+HSPLjava/util/Locale;->getDisplayCountry(Ljava/util/Locale;)Ljava/lang/String;+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->getDisplayLanguage()Ljava/lang/String;+]Ljava/util/Locale;Ljava/util/Locale;
+HSPLjava/util/Locale;->getDisplayLanguage(Ljava/util/Locale;)Ljava/lang/String;+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->getExtensionKeys()Ljava/util/Set;
+HSPLjava/util/Locale;->getISO3Country()Ljava/lang/String;
+HSPLjava/util/Locale;->getISO3Language()Ljava/lang/String;
+HSPLjava/util/Locale;->getInstance(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lsun/util/locale/LocaleExtensions;)Ljava/util/Locale;
+HSPLjava/util/Locale;->getInstance(Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;)Ljava/util/Locale;+]Ljava/util/Locale$Cache;Ljava/util/Locale$Cache;
+HSPLjava/util/Locale;->getLanguage()Ljava/lang/String;+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->getScript()Ljava/lang/String;+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->getVariant()Ljava/lang/String;+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->hasExtensions()Z
+HSPLjava/util/Locale;->hashCode()I+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->isValidBcp47Alpha(Ljava/lang/String;II)Z
+HSPLjava/util/Locale;->readObject(Ljava/io/ObjectInputStream;)V+]Ljava/io/ObjectInputStream;missing_types]Ljava/io/ObjectInputStream$GetField;Ljava/io/ObjectInputStream$GetFieldImpl;
+HSPLjava/util/Locale;->readResolve()Ljava/lang/Object;+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->setDefault(Ljava/util/Locale$Category;Ljava/util/Locale;)V+]Ljava/util/Locale$Category;Ljava/util/Locale$Category;
+HSPLjava/util/Locale;->setDefault(Ljava/util/Locale;)V
+HSPLjava/util/Locale;->toLanguageTag()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lsun/util/locale/LanguageTag;Lsun/util/locale/LanguageTag;]Ljava/util/List;Ljava/util/Collections$EmptyList;,Ljava/util/Collections$UnmodifiableRandomAccessList;]Ljava/util/Iterator;Ljava/util/Collections$EmptyIterator;,Ljava/util/Collections$UnmodifiableCollection$1;
+HSPLjava/util/Locale;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Locale;->writeObject(Ljava/io/ObjectOutputStream;)V+]Ljava/io/ObjectOutputStream$PutField;Ljava/io/ObjectOutputStream$PutFieldImpl;]Ljava/io/ObjectOutputStream;Ljava/io/ObjectOutputStream;]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;
+HSPLjava/util/Map;->computeIfAbsent(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;+]Ljava/util/Map;Landroid/util/ArrayMap;,Ljava/util/EnumMap;]Ljava/util/function/Function;missing_types
+HSPLjava/util/Map;->forEach(Ljava/util/function/BiConsumer;)V+]Ljava/util/Map$Entry;missing_types]Ljava/util/Map;missing_types]Ljava/util/Iterator;missing_types]Ljava/util/Set;missing_types
+HSPLjava/util/Map;->getOrDefault(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Map;missing_types
+HSPLjava/util/MissingResourceException;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/util/NoSuchElementException;-><init>()V
+HSPLjava/util/NoSuchElementException;-><init>(Ljava/lang/String;)V
+HSPLjava/util/Objects;->checkIndex(II)I
+HSPLjava/util/Objects;->equals(Ljava/lang/Object;Ljava/lang/Object;)Z+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/Objects;->hash([Ljava/lang/Object;)I
+HSPLjava/util/Objects;->hashCode(Ljava/lang/Object;)I+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/Objects;->nonNull(Ljava/lang/Object;)Z
+HSPLjava/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/Objects;->requireNonNull(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
+HSPLjava/util/Objects;->toString(Ljava/lang/Object;)Ljava/lang/String;
+HSPLjava/util/Objects;->toString(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/Object;Ljava/lang/String;
+HSPLjava/util/Observable;-><init>()V
+HSPLjava/util/Observable;->addObserver(Ljava/util/Observer;)V+]Ljava/util/Vector;Ljava/util/Vector;
+HSPLjava/util/Observable;->clearChanged()V
+HSPLjava/util/Observable;->hasChanged()Z
+HSPLjava/util/Observable;->notifyObservers()V
+HSPLjava/util/Observable;->notifyObservers(Ljava/lang/Object;)V+]Ljava/util/Vector;Ljava/util/Vector;
+HSPLjava/util/Observable;->setChanged()V
+HSPLjava/util/Optional;-><init>(Ljava/lang/Object;)V
+HSPLjava/util/Optional;->empty()Ljava/util/Optional;
+HSPLjava/util/Optional;->flatMap(Ljava/util/function/Function;)Ljava/util/Optional;+]Ljava/util/Optional;Ljava/util/Optional;
+HSPLjava/util/Optional;->get()Ljava/lang/Object;
+HSPLjava/util/Optional;->ifPresent(Ljava/util/function/Consumer;)V
+HSPLjava/util/Optional;->isPresent()Z
+HSPLjava/util/Optional;->map(Ljava/util/function/Function;)Ljava/util/Optional;+]Ljava/util/Optional;Ljava/util/Optional;]Ljava/util/function/Function;missing_types
+HSPLjava/util/Optional;->of(Ljava/lang/Object;)Ljava/util/Optional;
+HSPLjava/util/Optional;->ofNullable(Ljava/lang/Object;)Ljava/util/Optional;
+HSPLjava/util/Optional;->orElse(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/Optional;->orElseGet(Ljava/util/function/Supplier;)Ljava/lang/Object;
+HSPLjava/util/OptionalDouble;-><clinit>()V
+HSPLjava/util/OptionalDouble;-><init>()V
+HSPLjava/util/OptionalDouble;-><init>(D)V
+HSPLjava/util/OptionalDouble;->of(D)Ljava/util/OptionalDouble;
+HSPLjava/util/OptionalDouble;->orElseGet(Ljava/util/function/DoubleSupplier;)D
+HSPLjava/util/PriorityQueue$Itr;-><init>(Ljava/util/PriorityQueue;)V
+HSPLjava/util/PriorityQueue$Itr;-><init>(Ljava/util/PriorityQueue;Ljava/util/PriorityQueue$1;)V
+HSPLjava/util/PriorityQueue$Itr;->hasNext()Z
+HSPLjava/util/PriorityQueue$Itr;->next()Ljava/lang/Object;
+HSPLjava/util/PriorityQueue$Itr;->remove()V+]Ljava/util/PriorityQueue;Ljava/util/PriorityQueue;
+HSPLjava/util/PriorityQueue;-><init>()V
+HSPLjava/util/PriorityQueue;-><init>(ILjava/util/Comparator;)V
+HSPLjava/util/PriorityQueue;-><init>(Ljava/util/PriorityQueue;)V+]Ljava/util/PriorityQueue;Ljava/util/PriorityQueue;
+HSPLjava/util/PriorityQueue;->add(Ljava/lang/Object;)Z+]Ljava/util/PriorityQueue;missing_types
+HSPLjava/util/PriorityQueue;->clear()V
+HSPLjava/util/PriorityQueue;->comparator()Ljava/util/Comparator;
+HSPLjava/util/PriorityQueue;->contains(Ljava/lang/Object;)Z
+HSPLjava/util/PriorityQueue;->grow(I)V
+HSPLjava/util/PriorityQueue;->indexOf(Ljava/lang/Object;)I+]Ljava/lang/Object;missing_types
+HSPLjava/util/PriorityQueue;->initFromPriorityQueue(Ljava/util/PriorityQueue;)V+]Ljava/lang/Object;Ljava/util/PriorityQueue;]Ljava/util/PriorityQueue;Ljava/util/PriorityQueue;
+HSPLjava/util/PriorityQueue;->iterator()Ljava/util/Iterator;
+HSPLjava/util/PriorityQueue;->offer(Ljava/lang/Object;)Z
+HSPLjava/util/PriorityQueue;->peek()Ljava/lang/Object;
+HSPLjava/util/PriorityQueue;->poll()Ljava/lang/Object;
+HSPLjava/util/PriorityQueue;->remove(Ljava/lang/Object;)Z+]Ljava/util/PriorityQueue;Ljava/util/PriorityQueue;
+HSPLjava/util/PriorityQueue;->removeAt(I)Ljava/lang/Object;
+HSPLjava/util/PriorityQueue;->siftDown(ILjava/lang/Object;)V
+HSPLjava/util/PriorityQueue;->siftDownComparable(ILjava/lang/Object;)V+]Ljava/lang/Comparable;missing_types
+HSPLjava/util/PriorityQueue;->siftDownUsingComparator(ILjava/lang/Object;)V+]Ljava/util/Comparator;missing_types
+HSPLjava/util/PriorityQueue;->siftUp(ILjava/lang/Object;)V
+HSPLjava/util/PriorityQueue;->siftUpComparable(ILjava/lang/Object;)V+]Ljava/lang/Comparable;missing_types
+HSPLjava/util/PriorityQueue;->siftUpUsingComparator(ILjava/lang/Object;)V+]Ljava/util/Comparator;missing_types
+HSPLjava/util/PriorityQueue;->size()I
+HSPLjava/util/PriorityQueue;->toArray()[Ljava/lang/Object;
+HSPLjava/util/PriorityQueue;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;
+HSPLjava/util/Properties$LineReader;-><init>(Ljava/util/Properties;Ljava/io/InputStream;)V
+HSPLjava/util/Properties$LineReader;-><init>(Ljava/util/Properties;Ljava/io/Reader;)V
+HSPLjava/util/Properties$LineReader;->readLine()I+]Ljava/io/Reader;Ljava/io/FileReader;,Ljava/io/InputStreamReader;,Ljava/io/StringReader;]Ljava/io/InputStream;missing_types
+HSPLjava/util/Properties;-><init>()V
+HSPLjava/util/Properties;-><init>(Ljava/util/Properties;)V
+HSPLjava/util/Properties;->getProperty(Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Properties;Ljava/util/Properties;
+HSPLjava/util/Properties;->getProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Properties;Ljava/lang/System$PropertiesWithNonOverrideableDefaults;,Ljava/util/Properties;
+HSPLjava/util/Properties;->load(Ljava/io/InputStream;)V
+HSPLjava/util/Properties;->load(Ljava/io/Reader;)V
+HSPLjava/util/Properties;->load0(Ljava/util/Properties$LineReader;)V+]Ljava/util/Properties;Ljava/util/Properties;]Ljava/util/Properties$LineReader;Ljava/util/Properties$LineReader;
+HSPLjava/util/Properties;->loadConvert([CII[C)Ljava/lang/String;
+HSPLjava/util/Properties;->setProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;+]Ljava/util/Properties;Ljava/util/Properties;,Ljava/lang/System$PropertiesWithNonOverrideableDefaults;
+HSPLjava/util/Properties;->store(Ljava/io/OutputStream;Ljava/lang/String;)V
+HSPLjava/util/Properties;->store0(Ljava/io/BufferedWriter;Ljava/lang/String;Z)V+]Ljava/util/Date;Ljava/util/Date;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Properties;Ljava/util/Properties;]Ljava/util/Enumeration;Ljava/util/Hashtable$Enumerator;]Ljava/io/BufferedWriter;Ljava/io/BufferedWriter;
+HSPLjava/util/PropertyResourceBundle;-><init>(Ljava/io/Reader;)V
+HSPLjava/util/Random;-><init>()V
+HSPLjava/util/Random;-><init>(J)V+]Ljava/util/Random;missing_types]Ljava/lang/Object;missing_types
+HSPLjava/util/Random;->initialScramble(J)J
+HSPLjava/util/Random;->next(I)I+]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/Random;->nextBoolean()Z+]Ljava/util/Random;Ljava/util/Random;
+HSPLjava/util/Random;->nextBytes([B)V+]Ljava/util/Random;missing_types
+HSPLjava/util/Random;->nextDouble()D+]Ljava/util/Random;missing_types
+HSPLjava/util/Random;->nextFloat()F+]Ljava/util/Random;missing_types
+HSPLjava/util/Random;->nextGaussian()D+]Ljava/util/Random;Ljava/util/Random;,Ljava/security/SecureRandom;
+HSPLjava/util/Random;->nextInt()I+]Ljava/util/Random;missing_types
+HSPLjava/util/Random;->nextInt(I)I+]Ljava/util/Random;missing_types
+HSPLjava/util/Random;->nextLong()J+]Ljava/util/Random;missing_types
+HSPLjava/util/Random;->readObject(Ljava/io/ObjectInputStream;)V
+HSPLjava/util/Random;->resetSeed(J)V
+HSPLjava/util/Random;->seedUniquifier()J+]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/Random;->setSeed(J)V+]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/Random;->writeObject(Ljava/io/ObjectOutputStream;)V+]Ljava/io/ObjectOutputStream$PutField;Ljava/io/ObjectOutputStream$PutFieldImpl;]Ljava/io/ObjectOutputStream;Ljava/io/ObjectOutputStream;]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/RegularEnumSet$EnumSetIterator;-><init>(Ljava/util/RegularEnumSet;)V
+HSPLjava/util/RegularEnumSet$EnumSetIterator;->hasNext()Z
+HSPLjava/util/RegularEnumSet$EnumSetIterator;->next()Ljava/lang/Enum;
+HSPLjava/util/RegularEnumSet$EnumSetIterator;->next()Ljava/lang/Object;+]Ljava/util/RegularEnumSet$EnumSetIterator;Ljava/util/RegularEnumSet$EnumSetIterator;
+HSPLjava/util/RegularEnumSet;-><init>(Ljava/lang/Class;[Ljava/lang/Enum;)V
+HSPLjava/util/RegularEnumSet;->access$000(Ljava/util/RegularEnumSet;)J
+HSPLjava/util/RegularEnumSet;->add(Ljava/lang/Enum;)Z+]Ljava/lang/Enum;missing_types]Ljava/util/RegularEnumSet;Ljava/util/RegularEnumSet;
+HSPLjava/util/RegularEnumSet;->add(Ljava/lang/Object;)Z+]Ljava/util/RegularEnumSet;Ljava/util/RegularEnumSet;
+HSPLjava/util/RegularEnumSet;->addAll()V
+HSPLjava/util/RegularEnumSet;->addAll(Ljava/util/Collection;)Z
+HSPLjava/util/RegularEnumSet;->complement()V
+HSPLjava/util/RegularEnumSet;->contains(Ljava/lang/Object;)Z+]Ljava/lang/Object;missing_types]Ljava/lang/Enum;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/RegularEnumSet;->containsAll(Ljava/util/Collection;)Z
+HSPLjava/util/RegularEnumSet;->equals(Ljava/lang/Object;)Z
+HSPLjava/util/RegularEnumSet;->isEmpty()Z
+HSPLjava/util/RegularEnumSet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/RegularEnumSet;->remove(Ljava/lang/Object;)Z+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/RegularEnumSet;->size()I
+HSPLjava/util/ResourceBundle$BundleReference;-><init>(Ljava/util/ResourceBundle;Ljava/lang/ref/ReferenceQueue;Ljava/util/ResourceBundle$CacheKey;)V
+HSPLjava/util/ResourceBundle$BundleReference;->getCacheKey()Ljava/util/ResourceBundle$CacheKey;
+HSPLjava/util/ResourceBundle$CacheKey;-><init>(Ljava/lang/String;Ljava/util/Locale;Ljava/lang/ClassLoader;)V
+HSPLjava/util/ResourceBundle$CacheKey;->access$400(Ljava/util/ResourceBundle$CacheKey;)Ljava/lang/Throwable;
+HSPLjava/util/ResourceBundle$CacheKey;->access$600(Ljava/util/ResourceBundle$CacheKey;)J
+HSPLjava/util/ResourceBundle$CacheKey;->access$602(Ljava/util/ResourceBundle$CacheKey;J)J
+HSPLjava/util/ResourceBundle$CacheKey;->calculateHashCode()V+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/ResourceBundle$CacheKey;Ljava/util/ResourceBundle$CacheKey;]Ljava/util/Locale;Ljava/util/Locale;]Ljava/lang/Object;Ldalvik/system/PathClassLoader;
+HSPLjava/util/ResourceBundle$CacheKey;->clone()Ljava/lang/Object;
+HSPLjava/util/ResourceBundle$CacheKey;->equals(Ljava/lang/Object;)Z+]Ljava/util/Locale;Ljava/util/Locale;]Ljava/util/ResourceBundle$LoaderReference;Ljava/util/ResourceBundle$LoaderReference;
+HSPLjava/util/ResourceBundle$CacheKey;->getCause()Ljava/lang/Throwable;
+HSPLjava/util/ResourceBundle$CacheKey;->getLoader()Ljava/lang/ClassLoader;+]Ljava/util/ResourceBundle$LoaderReference;Ljava/util/ResourceBundle$LoaderReference;
+HSPLjava/util/ResourceBundle$CacheKey;->getLocale()Ljava/util/Locale;
+HSPLjava/util/ResourceBundle$CacheKey;->getName()Ljava/lang/String;
+HSPLjava/util/ResourceBundle$CacheKey;->hashCode()I
+HSPLjava/util/ResourceBundle$CacheKey;->setFormat(Ljava/lang/String;)V
+HSPLjava/util/ResourceBundle$CacheKey;->setLocale(Ljava/util/Locale;)Ljava/util/ResourceBundle$CacheKey;+]Ljava/util/Locale;Ljava/util/Locale;
+HSPLjava/util/ResourceBundle$Control$1;-><init>(Ljava/util/ResourceBundle$Control;ZLjava/lang/ClassLoader;Ljava/lang/String;)V
+HSPLjava/util/ResourceBundle$Control$1;->run()Ljava/io/InputStream;
+HSPLjava/util/ResourceBundle$Control$1;->run()Ljava/lang/Object;
+HSPLjava/util/ResourceBundle$Control$CandidateListCache;->createObject(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/ResourceBundle$Control$CandidateListCache;->createObject(Lsun/util/locale/BaseLocale;)Ljava/util/List;
+HSPLjava/util/ResourceBundle$Control$CandidateListCache;->getDefaultList(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
+HSPLjava/util/ResourceBundle$Control;->access$300()Ljava/util/ResourceBundle$Control;
+HSPLjava/util/ResourceBundle$Control;->getCandidateLocales(Ljava/lang/String;Ljava/util/Locale;)Ljava/util/List;+]Ljava/util/ResourceBundle$Control$CandidateListCache;Ljava/util/ResourceBundle$Control$CandidateListCache;]Ljava/util/Locale;Ljava/util/Locale;
+HSPLjava/util/ResourceBundle$Control;->getFallbackLocale(Ljava/lang/String;Ljava/util/Locale;)Ljava/util/Locale;+]Ljava/util/Locale;Ljava/util/Locale;
+HSPLjava/util/ResourceBundle$Control;->getFormats(Ljava/lang/String;)Ljava/util/List;
+HSPLjava/util/ResourceBundle$Control;->getTimeToLive(Ljava/lang/String;Ljava/util/Locale;)J
+HSPLjava/util/ResourceBundle$Control;->newBundle(Ljava/lang/String;Ljava/util/Locale;Ljava/lang/String;Ljava/lang/ClassLoader;Z)Ljava/util/ResourceBundle;
+HSPLjava/util/ResourceBundle$Control;->toBundleName(Ljava/lang/String;Ljava/util/Locale;)Ljava/lang/String;
+HSPLjava/util/ResourceBundle$Control;->toResourceName(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/util/ResourceBundle$Control;->toResourceName0(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/util/ResourceBundle$LoaderReference;-><init>(Ljava/lang/ClassLoader;Ljava/lang/ref/ReferenceQueue;Ljava/util/ResourceBundle$CacheKey;)V
+HSPLjava/util/ResourceBundle;-><init>()V
+HSPLjava/util/ResourceBundle;->access$200()Ljava/lang/ref/ReferenceQueue;
+HSPLjava/util/ResourceBundle;->findBundle(Ljava/util/ResourceBundle$CacheKey;Ljava/util/List;Ljava/util/List;ILjava/util/ResourceBundle$Control;Ljava/util/ResourceBundle;)Ljava/util/ResourceBundle;+]Ljava/util/ResourceBundle$CacheKey;Ljava/util/ResourceBundle$CacheKey;]Ljava/lang/ref/ReferenceQueue;Ljava/lang/ref/ReferenceQueue;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/ResourceBundle;Ljava/util/PropertyResourceBundle;
+HSPLjava/util/ResourceBundle;->findBundleInCache(Ljava/util/ResourceBundle$CacheKey;Ljava/util/ResourceBundle$Control;)Ljava/util/ResourceBundle;+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/util/ResourceBundle$BundleReference;Ljava/util/ResourceBundle$BundleReference;
+HSPLjava/util/ResourceBundle;->getBundle(Ljava/lang/String;Ljava/util/Locale;Ljava/lang/ClassLoader;)Ljava/util/ResourceBundle;
+HSPLjava/util/ResourceBundle;->getBundleImpl(Ljava/lang/String;Ljava/util/Locale;Ljava/lang/ClassLoader;Ljava/util/ResourceBundle$Control;)Ljava/util/ResourceBundle;+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/util/Locale;Ljava/util/Locale;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/ResourceBundle$Control;Ljava/util/ResourceBundle$Control;]Ljava/util/ResourceBundle$BundleReference;Ljava/util/ResourceBundle$BundleReference;
+HSPLjava/util/ResourceBundle;->getDefaultControl(Ljava/lang/String;)Ljava/util/ResourceBundle$Control;
+HSPLjava/util/ResourceBundle;->getObject(Ljava/lang/String;)Ljava/lang/Object;
+HSPLjava/util/ResourceBundle;->getString(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/util/ResourceBundle;->isValidBundle(Ljava/util/ResourceBundle;)Z
+HSPLjava/util/ResourceBundle;->loadBundle(Ljava/util/ResourceBundle$CacheKey;Ljava/util/List;Ljava/util/ResourceBundle$Control;Z)Ljava/util/ResourceBundle;
+HSPLjava/util/ResourceBundle;->putBundleInCache(Ljava/util/ResourceBundle$CacheKey;Ljava/util/ResourceBundle;Ljava/util/ResourceBundle$Control;)Ljava/util/ResourceBundle;
+HSPLjava/util/ResourceBundle;->setExpirationTime(Ljava/util/ResourceBundle$CacheKey;Ljava/util/ResourceBundle$Control;)V
+HSPLjava/util/ResourceBundle;->setParent(Ljava/util/ResourceBundle;)V
+HSPLjava/util/Scanner$1;-><init>(Ljava/util/Scanner;I)V
+HSPLjava/util/Scanner$1;->create(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/Scanner$1;->create(Ljava/lang/String;)Ljava/util/regex/Pattern;
+HSPLjava/util/Scanner;-><init>(Ljava/io/InputStream;)V
+HSPLjava/util/Scanner;-><init>(Ljava/lang/Readable;Ljava/util/regex/Pattern;)V+]Ljava/util/Scanner;Ljava/util/Scanner;]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;]Ljava/util/regex/Pattern;Ljava/util/regex/Pattern;
+HSPLjava/util/Scanner;-><init>(Ljava/lang/String;)V
+HSPLjava/util/Scanner;->clearCaches()V
+HSPLjava/util/Scanner;->close()V+]Ljava/io/Closeable;Ljava/io/StringReader;,Ljava/io/InputStreamReader;
+HSPLjava/util/Scanner;->ensureOpen()V
+HSPLjava/util/Scanner;->getCompleteTokenInBuffer(Ljava/util/regex/Pattern;)Ljava/lang/String;+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/Scanner;->hasNext()Z
+HSPLjava/util/Scanner;->hasTokenInBuffer()Z+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/Scanner;->makeSpace()Z+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/Scanner;->next()Ljava/lang/String;
+HSPLjava/util/Scanner;->readInput()V+]Ljava/lang/Readable;Lsun/nio/cs/StreamDecoder;,Ljava/io/StringReader;,Ljava/io/InputStreamReader;,Ljava/io/FileReader;,Ljava/io/BufferedReader;]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/Scanner;->revertState(Z)Z
+HSPLjava/util/Scanner;->saveState()V
+HSPLjava/util/Scanner;->translateSavedIndexes(I)V
+HSPLjava/util/Scanner;->useDelimiter(Ljava/lang/String;)Ljava/util/Scanner;
+HSPLjava/util/Scanner;->useLocale(Ljava/util/Locale;)Ljava/util/Scanner;+]Ljava/text/DecimalFormatSymbols;Ljava/text/DecimalFormatSymbols;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Locale;Ljava/util/Locale;]Ljava/text/DecimalFormat;Ljava/text/DecimalFormat;
+HSPLjava/util/ServiceLoader$1;-><init>(Ljava/util/ServiceLoader;)V+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;]Ljava/util/Set;Ljava/util/LinkedHashMap$LinkedEntrySet;
+HSPLjava/util/ServiceLoader$1;->hasNext()Z+]Ljava/util/ServiceLoader$LazyIterator;Ljava/util/ServiceLoader$LazyIterator;]Ljava/util/Iterator;Ljava/util/LinkedHashMap$LinkedEntryIterator;
+HSPLjava/util/ServiceLoader$LazyIterator;-><init>(Ljava/util/ServiceLoader;Ljava/lang/Class;Ljava/lang/ClassLoader;)V
+HSPLjava/util/ServiceLoader$LazyIterator;-><init>(Ljava/util/ServiceLoader;Ljava/lang/Class;Ljava/lang/ClassLoader;Ljava/util/ServiceLoader$1;)V
+HSPLjava/util/ServiceLoader$LazyIterator;->hasNext()Z
+HSPLjava/util/ServiceLoader$LazyIterator;->hasNextService()Z+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/Enumeration;Lsun/misc/CompoundEnumeration;]Ljava/lang/ClassLoader;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/ServiceLoader;-><init>(Ljava/lang/Class;Ljava/lang/ClassLoader;)V+]Ljava/util/ServiceLoader;Ljava/util/ServiceLoader;
+HSPLjava/util/ServiceLoader;->access$300(Ljava/util/ServiceLoader;)Ljava/util/LinkedHashMap;
+HSPLjava/util/ServiceLoader;->access$400(Ljava/util/ServiceLoader;)Ljava/util/ServiceLoader$LazyIterator;
+HSPLjava/util/ServiceLoader;->iterator()Ljava/util/Iterator;
+HSPLjava/util/ServiceLoader;->load(Ljava/lang/Class;Ljava/lang/ClassLoader;)Ljava/util/ServiceLoader;
+HSPLjava/util/ServiceLoader;->reload()V+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;
+HSPLjava/util/Set;->spliterator()Ljava/util/Spliterator;
+HSPLjava/util/SimpleTimeZone;-><init>(ILjava/lang/String;)V+]Ljava/util/SimpleTimeZone;Ljava/util/SimpleTimeZone;
+HSPLjava/util/SimpleTimeZone;->clone()Ljava/lang/Object;
+HSPLjava/util/SimpleTimeZone;->getOffset(J)I+]Ljava/util/SimpleTimeZone;Ljava/util/SimpleTimeZone;
+HSPLjava/util/SimpleTimeZone;->getOffsets(J[I)I
+HSPLjava/util/SimpleTimeZone;->getRawOffset()I
+HSPLjava/util/SimpleTimeZone;->hasSameRules(Ljava/util/TimeZone;)Z
+HSPLjava/util/Spliterator$OfInt;->forEachRemaining(Ljava/util/function/Consumer;)V+]Ljava/util/Spliterator$OfInt;Ljava/util/Spliterators$IntArraySpliterator;,Ljava/util/stream/Streams$RangeIntSpliterator;
+HSPLjava/util/Spliterator;->getExactSizeIfKnown()J+]Ljava/util/Spliterator;megamorphic_types
+HSPLjava/util/Spliterators$ArraySpliterator;-><init>([Ljava/lang/Object;I)V
+HSPLjava/util/Spliterators$ArraySpliterator;-><init>([Ljava/lang/Object;III)V
+HSPLjava/util/Spliterators$ArraySpliterator;->characteristics()I
+HSPLjava/util/Spliterators$ArraySpliterator;->estimateSize()J
+HSPLjava/util/Spliterators$ArraySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V+]Ljava/util/function/Consumer;megamorphic_types
+HSPLjava/util/Spliterators$ArraySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z+]Ljava/util/function/Consumer;Ljava/util/stream/MatchOps$1MatchSink;,Ljava/util/stream/ReferencePipeline$2$1;
+HSPLjava/util/Spliterators$EmptySpliterator$OfInt;->forEachRemaining(Ljava/util/function/IntConsumer;)V
+HSPLjava/util/Spliterators$EmptySpliterator$OfRef;->forEachRemaining(Ljava/util/function/Consumer;)V
+HSPLjava/util/Spliterators$EmptySpliterator;->characteristics()I
+HSPLjava/util/Spliterators$EmptySpliterator;->estimateSize()J
+HSPLjava/util/Spliterators$EmptySpliterator;->forEachRemaining(Ljava/lang/Object;)V
+HSPLjava/util/Spliterators$IntArraySpliterator;-><init>([IIII)V
+HSPLjava/util/Spliterators$IntArraySpliterator;->characteristics()I
+HSPLjava/util/Spliterators$IntArraySpliterator;->estimateSize()J
+HSPLjava/util/Spliterators$IntArraySpliterator;->forEachRemaining(Ljava/util/function/IntConsumer;)V+]Ljava/util/function/IntConsumer;missing_types
+HSPLjava/util/Spliterators$IntArraySpliterator;->tryAdvance(Ljava/util/function/IntConsumer;)Z+]Ljava/util/function/IntConsumer;Ljava/util/stream/MatchOps$2MatchSink;
+HSPLjava/util/Spliterators$IteratorSpliterator;-><init>(Ljava/util/Collection;I)V
+HSPLjava/util/Spliterators$IteratorSpliterator;->characteristics()I
+HSPLjava/util/Spliterators$IteratorSpliterator;->estimateSize()J+]Ljava/util/Collection;megamorphic_types
+HSPLjava/util/Spliterators$IteratorSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V+]Ljava/util/Iterator;megamorphic_types]Ljava/util/Collection;Landroid/util/MapCollections$ValuesCollection;,Landroid/util/ArraySet;
+HSPLjava/util/Spliterators$IteratorSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z+]Ljava/util/function/Consumer;Ljava/util/stream/MatchOps$1MatchSink;,Ljava/util/stream/ReferencePipeline$2$1;,Ljava/util/stream/ReferencePipeline$3$1;,Ljava/util/stream/SliceOps$1$1;,Ljava/util/stream/FindOps$FindSink$OfRef;]Ljava/util/Iterator;missing_types
+HSPLjava/util/Spliterators;->checkFromToBounds(III)V
+HSPLjava/util/Spliterators;->emptyIntSpliterator()Ljava/util/Spliterator$OfInt;
+HSPLjava/util/Spliterators;->emptySpliterator()Ljava/util/Spliterator;
+HSPLjava/util/Spliterators;->spliterator(Ljava/util/Collection;I)Ljava/util/Spliterator;
+HSPLjava/util/Spliterators;->spliterator([IIII)Ljava/util/Spliterator$OfInt;
+HSPLjava/util/Spliterators;->spliterator([Ljava/lang/Object;I)Ljava/util/Spliterator;
+HSPLjava/util/Spliterators;->spliterator([Ljava/lang/Object;III)Ljava/util/Spliterator;
+HSPLjava/util/Stack;-><init>()V
+HSPLjava/util/Stack;->empty()Z+]Ljava/util/Stack;missing_types
+HSPLjava/util/Stack;->peek()Ljava/lang/Object;+]Ljava/util/Stack;missing_types
+HSPLjava/util/Stack;->pop()Ljava/lang/Object;+]Ljava/util/Stack;missing_types
+HSPLjava/util/Stack;->push(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Stack;missing_types
+HSPLjava/util/StringJoiner;-><init>(Ljava/lang/CharSequence;)V
+HSPLjava/util/StringJoiner;-><init>(Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/CharSequence;Ljava/lang/String;
+HSPLjava/util/StringJoiner;->add(Ljava/lang/CharSequence;)Ljava/util/StringJoiner;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/StringJoiner;->prepareBuilder()Ljava/lang/StringBuilder;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/StringJoiner;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/StringTokenizer;-><init>(Ljava/lang/String;)V
+HSPLjava/util/StringTokenizer;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/util/StringTokenizer;-><init>(Ljava/lang/String;Ljava/lang/String;Z)V
+HSPLjava/util/StringTokenizer;->countTokens()I
+HSPLjava/util/StringTokenizer;->hasMoreElements()Z+]Ljava/util/StringTokenizer;Ljava/util/StringTokenizer;
+HSPLjava/util/StringTokenizer;->hasMoreTokens()Z
+HSPLjava/util/StringTokenizer;->nextToken()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/StringTokenizer;->scanToken(I)I
+HSPLjava/util/StringTokenizer;->setMaxDelimCodePoint()V
+HSPLjava/util/StringTokenizer;->skipDelimiters(I)I
+HSPLjava/util/TaskQueue;-><init>()V
+HSPLjava/util/TaskQueue;->add(Ljava/util/TimerTask;)V
+HSPLjava/util/TaskQueue;->clear()V
+HSPLjava/util/TaskQueue;->fixDown(I)V
+HSPLjava/util/TaskQueue;->fixUp(I)V
+HSPLjava/util/TaskQueue;->getMin()Ljava/util/TimerTask;
+HSPLjava/util/TaskQueue;->isEmpty()Z
+HSPLjava/util/TaskQueue;->removeMin()V
+HSPLjava/util/TaskQueue;->rescheduleMin(J)V
+HSPLjava/util/TimSort;-><init>([Ljava/lang/Object;Ljava/util/Comparator;[Ljava/lang/Object;II)V+]Ljava/lang/Object;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/TimSort;->binarySort([Ljava/lang/Object;IIILjava/util/Comparator;)V+]Ljava/util/Comparator;megamorphic_types
+HSPLjava/util/TimSort;->countRunAndMakeAscending([Ljava/lang/Object;IILjava/util/Comparator;)I+]Ljava/util/Comparator;megamorphic_types
+HSPLjava/util/TimSort;->ensureCapacity(I)[Ljava/lang/Object;+]Ljava/lang/Object;missing_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/TimSort;->gallopLeft(Ljava/lang/Object;[Ljava/lang/Object;IIILjava/util/Comparator;)I+]Ljava/util/Comparator;megamorphic_types
+HSPLjava/util/TimSort;->gallopRight(Ljava/lang/Object;[Ljava/lang/Object;IIILjava/util/Comparator;)I+]Ljava/util/Comparator;megamorphic_types
+HSPLjava/util/TimSort;->mergeAt(I)V
+HSPLjava/util/TimSort;->mergeCollapse()V
+HSPLjava/util/TimSort;->mergeForceCollapse()V
+HSPLjava/util/TimSort;->mergeHi(IIII)V+]Ljava/util/Comparator;missing_types
+HSPLjava/util/TimSort;->mergeLo(IIII)V+]Ljava/util/Comparator;megamorphic_types
+HSPLjava/util/TimSort;->minRunLength(I)I
+HSPLjava/util/TimSort;->pushRun(II)V
+HSPLjava/util/TimSort;->reverseRange([Ljava/lang/Object;II)V
+HSPLjava/util/TimSort;->sort([Ljava/lang/Object;IILjava/util/Comparator;[Ljava/lang/Object;II)V
+HSPLjava/util/TimeZone;-><init>()V
+HSPLjava/util/TimeZone;->appendNumber(Ljava/lang/StringBuilder;II)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/TimeZone;->clone()Ljava/lang/Object;
+HSPLjava/util/TimeZone;->createGmtOffsetString(ZZI)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/TimeZone;->getAvailableIDs()[Ljava/lang/String;
+HSPLjava/util/TimeZone;->getDefault()Ljava/util/TimeZone;+]Ljava/util/TimeZone;Llibcore/util/ZoneInfo;
+HSPLjava/util/TimeZone;->getDefaultRef()Ljava/util/TimeZone;
+HSPLjava/util/TimeZone;->getDisplayName(ZILjava/util/Locale;)Ljava/lang/String;+]Landroid/icu/text/TimeZoneNames;missing_types]Ljava/util/TimeZone;missing_types
+HSPLjava/util/TimeZone;->getID()Ljava/lang/String;
+HSPLjava/util/TimeZone;->getTimeZone(Ljava/lang/String;)Ljava/util/TimeZone;+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/TimeZone;Ljava/util/SimpleTimeZone;]Lcom/android/i18n/timezone/ZoneInfoDb;Lcom/android/i18n/timezone/ZoneInfoDb;
+HSPLjava/util/TimeZone;->setDefault(Ljava/util/TimeZone;)V
+HSPLjava/util/TimeZone;->setID(Ljava/lang/String;)V
+HSPLjava/util/TimeZone;->toZoneId()Ljava/time/ZoneId;+]Ljava/util/TimeZone;missing_types
+HSPLjava/util/Timer$1;-><init>(Ljava/util/Timer;)V
+HSPLjava/util/Timer$1;->finalize()V+]Ljava/lang/Object;Ljava/util/TaskQueue;
+HSPLjava/util/Timer;-><init>()V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Timer;-><init>(Ljava/lang/String;)V+]Ljava/util/TimerThread;Ljava/util/TimerThread;
+HSPLjava/util/Timer;-><init>(Ljava/lang/String;Z)V+]Ljava/util/TimerThread;Ljava/util/TimerThread;
+HSPLjava/util/Timer;->access$000(Ljava/util/Timer;)Ljava/util/TaskQueue;
+HSPLjava/util/Timer;->access$100(Ljava/util/Timer;)Ljava/util/TimerThread;
+HSPLjava/util/Timer;->cancel()V+]Ljava/lang/Object;Ljava/util/TaskQueue;]Ljava/util/TaskQueue;Ljava/util/TaskQueue;
+HSPLjava/util/Timer;->sched(Ljava/util/TimerTask;JJ)V+]Ljava/lang/Object;Ljava/util/TaskQueue;]Ljava/util/TaskQueue;Ljava/util/TaskQueue;
+HSPLjava/util/Timer;->schedule(Ljava/util/TimerTask;J)V
+HSPLjava/util/Timer;->scheduleAtFixedRate(Ljava/util/TimerTask;JJ)V
+HSPLjava/util/Timer;->serialNumber()I+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/TimerTask;-><init>()V
+HSPLjava/util/TimerTask;->cancel()Z
+HSPLjava/util/TimerThread;-><init>(Ljava/util/TaskQueue;)V
+HSPLjava/util/TimerThread;->mainLoop()V+]Ljava/lang/Object;Ljava/util/TaskQueue;]Ljava/util/TaskQueue;Ljava/util/TaskQueue;]Ljava/util/TimerTask;Lgov/nist/javax/sip/clientauthutils/CredentialsCache$TimeoutTask;,Lgov/nist/javax/sip/stack/UDPMessageChannel$PingBackTimerTask;,Lgov/nist/javax/sip/stack/SIPClientTransaction$TransactionTimer;
+HSPLjava/util/TimerThread;->run()V+]Ljava/util/TaskQueue;Ljava/util/TaskQueue;
+HSPLjava/util/TreeMap$AscendingSubMap$AscendingEntrySetView;-><init>(Ljava/util/TreeMap$AscendingSubMap;)V
+HSPLjava/util/TreeMap$AscendingSubMap$AscendingEntrySetView;->iterator()Ljava/util/Iterator;+]Ljava/util/TreeMap$AscendingSubMap;Ljava/util/TreeMap$AscendingSubMap;
+HSPLjava/util/TreeMap$AscendingSubMap;-><init>(Ljava/util/TreeMap;ZLjava/lang/Object;ZZLjava/lang/Object;Z)V
+HSPLjava/util/TreeMap$AscendingSubMap;->entrySet()Ljava/util/Set;
+HSPLjava/util/TreeMap$AscendingSubMap;->keyIterator()Ljava/util/Iterator;+]Ljava/util/TreeMap$AscendingSubMap;Ljava/util/TreeMap$AscendingSubMap;
+HSPLjava/util/TreeMap$DescendingSubMap;-><init>(Ljava/util/TreeMap;ZLjava/lang/Object;ZZLjava/lang/Object;Z)V
+HSPLjava/util/TreeMap$DescendingSubMap;->keyIterator()Ljava/util/Iterator;+]Ljava/util/TreeMap$DescendingSubMap;Ljava/util/TreeMap$DescendingSubMap;
+HSPLjava/util/TreeMap$EntryIterator;-><init>(Ljava/util/TreeMap;Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap$EntryIterator;->next()Ljava/lang/Object;+]Ljava/util/TreeMap$EntryIterator;Ljava/util/TreeMap$EntryIterator;
+HSPLjava/util/TreeMap$EntryIterator;->next()Ljava/util/Map$Entry;+]Ljava/util/TreeMap$EntryIterator;Ljava/util/TreeMap$EntryIterator;
+HSPLjava/util/TreeMap$EntrySet;-><init>(Ljava/util/TreeMap;)V
+HSPLjava/util/TreeMap$EntrySet;->iterator()Ljava/util/Iterator;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap$EntrySet;->size()I+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap$KeyIterator;-><init>(Ljava/util/TreeMap;Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap$KeyIterator;->next()Ljava/lang/Object;+]Ljava/util/TreeMap$KeyIterator;Ljava/util/TreeMap$KeyIterator;
+HSPLjava/util/TreeMap$KeySet;-><init>(Ljava/util/NavigableMap;)V
+HSPLjava/util/TreeMap$KeySet;->isEmpty()Z+]Ljava/util/NavigableMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap$KeySet;->iterator()Ljava/util/Iterator;+]Ljava/util/TreeMap;Ljava/util/TreeMap;]Ljava/util/TreeMap$NavigableSubMap;Ljava/util/TreeMap$AscendingSubMap;,Ljava/util/TreeMap$DescendingSubMap;
+HSPLjava/util/TreeMap$KeySet;->size()I+]Ljava/util/NavigableMap;Ljava/util/TreeMap$AscendingSubMap;,Ljava/util/TreeMap;
+HSPLjava/util/TreeMap$NavigableSubMap$EntrySetView;-><init>(Ljava/util/TreeMap$NavigableSubMap;)V
+HSPLjava/util/TreeMap$NavigableSubMap$EntrySetView;->isEmpty()Z+]Ljava/util/TreeMap$NavigableSubMap;Ljava/util/TreeMap$AscendingSubMap;
+HSPLjava/util/TreeMap$NavigableSubMap$EntrySetView;->size()I+]Ljava/util/TreeMap$NavigableSubMap$EntrySetView;Ljava/util/TreeMap$AscendingSubMap$AscendingEntrySetView;]Ljava/util/Iterator;Ljava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;-><init>(Ljava/util/TreeMap$NavigableSubMap;Ljava/util/TreeMap$TreeMapEntry;Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;->next()Ljava/lang/Object;+]Ljava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;Ljava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;->next()Ljava/util/Map$Entry;+]Ljava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;Ljava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;->remove()V+]Ljava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;Ljava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapIterator;-><init>(Ljava/util/TreeMap$NavigableSubMap;Ljava/util/TreeMap$TreeMapEntry;Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapIterator;->hasNext()Z
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapIterator;->nextEntry()Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapIterator;->prevEntry()Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapIterator;->removeAscending()V
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapKeyIterator;-><init>(Ljava/util/TreeMap$NavigableSubMap;Ljava/util/TreeMap$TreeMapEntry;Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap$NavigableSubMap$SubMapKeyIterator;->next()Ljava/lang/Object;+]Ljava/util/TreeMap$NavigableSubMap$SubMapKeyIterator;Ljava/util/TreeMap$NavigableSubMap$SubMapKeyIterator;
+HSPLjava/util/TreeMap$NavigableSubMap;-><init>(Ljava/util/TreeMap;ZLjava/lang/Object;ZZLjava/lang/Object;Z)V+]Ljava/util/TreeMap;missing_types
+HSPLjava/util/TreeMap$NavigableSubMap;->absHighFence()Ljava/util/TreeMap$TreeMapEntry;+]Ljava/util/TreeMap;missing_types
+HSPLjava/util/TreeMap$NavigableSubMap;->absHighest()Ljava/util/TreeMap$TreeMapEntry;+]Ljava/util/TreeMap;Ljava/util/TreeMap;]Ljava/util/TreeMap$NavigableSubMap;Ljava/util/TreeMap$DescendingSubMap;,Ljava/util/TreeMap$AscendingSubMap;
+HSPLjava/util/TreeMap$NavigableSubMap;->absLowFence()Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap$NavigableSubMap;->absLowest()Ljava/util/TreeMap$TreeMapEntry;+]Ljava/util/TreeMap;missing_types]Ljava/util/TreeMap$NavigableSubMap;Ljava/util/TreeMap$AscendingSubMap;
+HSPLjava/util/TreeMap$NavigableSubMap;->isEmpty()Z+]Ljava/util/TreeMap$NavigableSubMap;Ljava/util/TreeMap$AscendingSubMap;]Ljava/util/Set;Ljava/util/TreeMap$AscendingSubMap$AscendingEntrySetView;
+HSPLjava/util/TreeMap$NavigableSubMap;->navigableKeySet()Ljava/util/NavigableSet;
+HSPLjava/util/TreeMap$NavigableSubMap;->size()I+]Ljava/util/TreeMap$NavigableSubMap;Ljava/util/TreeMap$AscendingSubMap;]Ljava/util/Set;Ljava/util/TreeMap$AscendingSubMap$AscendingEntrySetView;
+HSPLjava/util/TreeMap$NavigableSubMap;->tooHigh(Ljava/lang/Object;)Z+]Ljava/util/TreeMap;missing_types
+HSPLjava/util/TreeMap$NavigableSubMap;->tooLow(Ljava/lang/Object;)Z+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap$PrivateEntryIterator;-><init>(Ljava/util/TreeMap;Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap$PrivateEntryIterator;->hasNext()Z
+HSPLjava/util/TreeMap$PrivateEntryIterator;->nextEntry()Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap$PrivateEntryIterator;->remove()V
+HSPLjava/util/TreeMap$TreeMapEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap$TreeMapEntry;->getKey()Ljava/lang/Object;
+HSPLjava/util/TreeMap$TreeMapEntry;->getValue()Ljava/lang/Object;
+HSPLjava/util/TreeMap$TreeMapEntry;->setValue(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/TreeMap$ValueIterator;-><init>(Ljava/util/TreeMap;Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap$ValueIterator;->next()Ljava/lang/Object;+]Ljava/util/TreeMap$ValueIterator;Ljava/util/TreeMap$ValueIterator;
+HSPLjava/util/TreeMap$Values;-><init>(Ljava/util/TreeMap;)V
+HSPLjava/util/TreeMap$Values;->iterator()Ljava/util/Iterator;+]Ljava/util/TreeMap;missing_types
+HSPLjava/util/TreeMap$Values;->size()I+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;-><init>()V
+HSPLjava/util/TreeMap;-><init>(Ljava/util/Comparator;)V
+HSPLjava/util/TreeMap;-><init>(Ljava/util/Map;)V+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->access$000(Ljava/util/TreeMap;Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap;->access$100(Ljava/util/TreeMap;)I
+HSPLjava/util/TreeMap;->access$200()Ljava/lang/Object;
+HSPLjava/util/TreeMap;->access$300(Ljava/util/TreeMap;)Ljava/util/Comparator;
+HSPLjava/util/TreeMap;->addAllForTreeSet(Ljava/util/SortedSet;Ljava/lang/Object;)V+]Ljava/util/SortedSet;Ljava/util/TreeSet;
+HSPLjava/util/TreeMap;->buildFromSorted(IIIILjava/util/Iterator;Ljava/io/ObjectInputStream;Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;+]Ljava/util/Map$Entry;Ljava/util/TreeMap$TreeMapEntry;,Ljava/util/AbstractMap$SimpleImmutableEntry;]Ljava/util/Iterator;missing_types]Ljava/io/ObjectInputStream;Landroid/os/Parcel$2;
+HSPLjava/util/TreeMap;->buildFromSorted(ILjava/util/Iterator;Ljava/io/ObjectInputStream;Ljava/lang/Object;)V
+HSPLjava/util/TreeMap;->ceilingEntry(Ljava/lang/Object;)Ljava/util/Map$Entry;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->ceilingKey(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->clear()V
+HSPLjava/util/TreeMap;->clone()Ljava/lang/Object;+]Ljava/util/TreeMap;Ljava/util/TreeMap;]Ljava/util/Set;Ljava/util/TreeMap$EntrySet;
+HSPLjava/util/TreeMap;->colorOf(Ljava/util/TreeMap$TreeMapEntry;)Z
+HSPLjava/util/TreeMap;->comparator()Ljava/util/Comparator;
+HSPLjava/util/TreeMap;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/util/Comparator;missing_types]Ljava/lang/Comparable;megamorphic_types
+HSPLjava/util/TreeMap;->computeRedLevel(I)I
+HSPLjava/util/TreeMap;->containsKey(Ljava/lang/Object;)Z+]Ljava/util/TreeMap;missing_types
+HSPLjava/util/TreeMap;->deleteEntry(Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap;->descendingKeySet()Ljava/util/NavigableSet;+]Ljava/util/NavigableMap;Ljava/util/TreeMap$DescendingSubMap;]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->descendingMap()Ljava/util/NavigableMap;
+HSPLjava/util/TreeMap;->entrySet()Ljava/util/Set;
+HSPLjava/util/TreeMap;->exportEntry(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/Map$Entry;
+HSPLjava/util/TreeMap;->firstKey()Ljava/lang/Object;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->fixAfterDeletion(Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap;->fixAfterInsertion(Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap;->floorEntry(Ljava/lang/Object;)Ljava/util/Map$Entry;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->floorKey(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/TreeMap;missing_types
+HSPLjava/util/TreeMap;->getCeilingEntry(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;+]Ljava/util/TreeMap;missing_types
+HSPLjava/util/TreeMap;->getEntry(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;+]Ljava/util/TreeMap;missing_types]Ljava/lang/Comparable;megamorphic_types
+HSPLjava/util/TreeMap;->getEntryUsingComparator(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;+]Ljava/util/Comparator;missing_types
+HSPLjava/util/TreeMap;->getFirstEntry()Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap;->getFloorEntry(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;+]Ljava/util/TreeMap;missing_types
+HSPLjava/util/TreeMap;->getHigherEntry(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;+]Ljava/util/TreeMap;missing_types
+HSPLjava/util/TreeMap;->getLastEntry()Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap;->getLowerEntry(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->headMap(Ljava/lang/Object;Z)Ljava/util/NavigableMap;
+HSPLjava/util/TreeMap;->key(Ljava/util/TreeMap$TreeMapEntry;)Ljava/lang/Object;
+HSPLjava/util/TreeMap;->keyIterator()Ljava/util/Iterator;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->keyOrNull(Ljava/util/TreeMap$TreeMapEntry;)Ljava/lang/Object;
+HSPLjava/util/TreeMap;->keySet()Ljava/util/Set;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->lastKey()Ljava/lang/Object;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->leftOf(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap;->lowerEntry(Ljava/lang/Object;)Ljava/util/Map$Entry;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->navigableKeySet()Ljava/util/NavigableSet;
+HSPLjava/util/TreeMap;->parentOf(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap;->pollFirstEntry()Ljava/util/Map$Entry;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->predecessor(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Comparator;missing_types]Ljava/util/TreeMap$TreeMapEntry;Ljava/util/TreeMap$TreeMapEntry;]Ljava/util/TreeMap;missing_types]Ljava/lang/Comparable;missing_types
+HSPLjava/util/TreeMap;->putAll(Ljava/util/Map;)V+]Ljava/util/Map;missing_types]Ljava/util/SortedMap;missing_types]Ljava/util/Set;missing_types
+HSPLjava/util/TreeMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->rightOf(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap;->rotateLeft(Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap;->rotateRight(Ljava/util/TreeMap$TreeMapEntry;)V
+HSPLjava/util/TreeMap;->setColor(Ljava/util/TreeMap$TreeMapEntry;Z)V
+HSPLjava/util/TreeMap;->size()I
+HSPLjava/util/TreeMap;->subMap(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/SortedMap;+]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeMap;->subMap(Ljava/lang/Object;ZLjava/lang/Object;Z)Ljava/util/NavigableMap;
+HSPLjava/util/TreeMap;->successor(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/TreeMap$TreeMapEntry;
+HSPLjava/util/TreeMap;->tailMap(Ljava/lang/Object;Z)Ljava/util/NavigableMap;
+HSPLjava/util/TreeMap;->values()Ljava/util/Collection;
+HSPLjava/util/TreeSet;-><init>()V
+HSPLjava/util/TreeSet;-><init>(Ljava/util/Collection;)V+]Ljava/util/TreeSet;missing_types
+HSPLjava/util/TreeSet;-><init>(Ljava/util/Comparator;)V
+HSPLjava/util/TreeSet;-><init>(Ljava/util/NavigableMap;)V
+HSPLjava/util/TreeSet;-><init>(Ljava/util/SortedSet;)V+]Ljava/util/SortedSet;Ljava/util/TreeSet;]Ljava/util/TreeSet;Ljava/util/TreeSet;
+HSPLjava/util/TreeSet;->add(Ljava/lang/Object;)Z+]Ljava/util/NavigableMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeSet;->addAll(Ljava/util/Collection;)Z+]Ljava/util/NavigableMap;Ljava/util/TreeMap;]Ljava/util/Collection;megamorphic_types]Ljava/util/SortedSet;Ljava/util/TreeSet;]Ljava/util/TreeMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeSet;->ceiling(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/NavigableMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeSet;->clear()V+]Ljava/util/NavigableMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeSet;->comparator()Ljava/util/Comparator;+]Ljava/util/NavigableMap;Ljava/util/TreeMap;,Ljava/util/TreeMap$AscendingSubMap;
+HSPLjava/util/TreeSet;->contains(Ljava/lang/Object;)Z+]Ljava/util/NavigableMap;Ljava/util/TreeMap;,Ljava/util/TreeMap$AscendingSubMap;
+HSPLjava/util/TreeSet;->first()Ljava/lang/Object;+]Ljava/util/NavigableMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeSet;->isEmpty()Z+]Ljava/util/NavigableMap;Ljava/util/TreeMap;,Ljava/util/TreeMap$AscendingSubMap;
+HSPLjava/util/TreeSet;->iterator()Ljava/util/Iterator;+]Ljava/util/NavigableMap;Ljava/util/TreeMap;,Ljava/util/TreeMap$AscendingSubMap;,Ljava/util/TreeMap$DescendingSubMap;]Ljava/util/NavigableSet;Ljava/util/TreeMap$KeySet;
+HSPLjava/util/TreeSet;->last()Ljava/lang/Object;+]Ljava/util/NavigableMap;Ljava/util/TreeMap;,Ljava/util/TreeMap$AscendingSubMap;
+HSPLjava/util/TreeSet;->remove(Ljava/lang/Object;)Z+]Ljava/util/NavigableMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeSet;->size()I+]Ljava/util/NavigableMap;Ljava/util/TreeMap;,Ljava/util/TreeMap$AscendingSubMap;,Ljava/util/TreeMap$DescendingSubMap;
+HSPLjava/util/TreeSet;->subSet(Ljava/lang/Object;ZLjava/lang/Object;Z)Ljava/util/NavigableSet;+]Ljava/util/NavigableMap;Ljava/util/TreeMap;
+HSPLjava/util/TreeSet;->tailSet(Ljava/lang/Object;Z)Ljava/util/NavigableSet;+]Ljava/util/NavigableMap;Ljava/util/TreeMap;
+HSPLjava/util/UUID;-><init>(JJ)V
+HSPLjava/util/UUID;-><init>([B)V
+HSPLjava/util/UUID;->digits(JI)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/UUID;->equals(Ljava/lang/Object;)Z+]Ljava/lang/Object;missing_types
+HSPLjava/util/UUID;->fromString(Ljava/lang/String;)Ljava/util/UUID;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/Long;Ljava/lang/Long;
+HSPLjava/util/UUID;->getLeastSignificantBits()J
+HSPLjava/util/UUID;->getMostSignificantBits()J
+HSPLjava/util/UUID;->hashCode()I
+HSPLjava/util/UUID;->nameUUIDFromBytes([B)Ljava/util/UUID;+]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;
+HSPLjava/util/UUID;->randomUUID()Ljava/util/UUID;+]Ljava/security/SecureRandom;Ljava/security/SecureRandom;
+HSPLjava/util/UUID;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLjava/util/Vector$1;-><init>(Ljava/util/Vector;)V
+HSPLjava/util/Vector$1;->hasMoreElements()Z
+HSPLjava/util/Vector$1;->nextElement()Ljava/lang/Object;+]Ljava/util/Vector;Ljava/util/Vector;
+HSPLjava/util/Vector$Itr;-><init>(Ljava/util/Vector;)V
+HSPLjava/util/Vector$Itr;-><init>(Ljava/util/Vector;Ljava/util/Vector$1;)V
+HSPLjava/util/Vector$Itr;->checkForComodification()V
+HSPLjava/util/Vector$Itr;->hasNext()Z
+HSPLjava/util/Vector$Itr;->next()Ljava/lang/Object;+]Ljava/util/Vector;missing_types]Ljava/util/Vector$Itr;Ljava/util/Vector$Itr;,Ljava/util/Vector$ListItr;
+HSPLjava/util/Vector;-><init>()V
+HSPLjava/util/Vector;-><init>(I)V
+HSPLjava/util/Vector;-><init>(II)V
+HSPLjava/util/Vector;->add(Ljava/lang/Object;)Z
+HSPLjava/util/Vector;->addElement(Ljava/lang/Object;)V
+HSPLjava/util/Vector;->clear()V+]Ljava/util/Vector;Ljava/util/Stack;,Ljava/util/Vector;
+HSPLjava/util/Vector;->contains(Ljava/lang/Object;)Z+]Ljava/util/Vector;Ljava/util/Vector;,Ljava/util/Stack;
+HSPLjava/util/Vector;->copyInto([Ljava/lang/Object;)V
+HSPLjava/util/Vector;->elementAt(I)Ljava/lang/Object;+]Ljava/util/Vector;missing_types
+HSPLjava/util/Vector;->elementData(I)Ljava/lang/Object;
+HSPLjava/util/Vector;->elements()Ljava/util/Enumeration;
+HSPLjava/util/Vector;->ensureCapacityHelper(I)V
+HSPLjava/util/Vector;->get(I)Ljava/lang/Object;+]Ljava/util/Vector;missing_types
+HSPLjava/util/Vector;->grow(I)V
+HSPLjava/util/Vector;->indexOf(Ljava/lang/Object;)I+]Ljava/util/Vector;Ljava/util/Vector;
+HSPLjava/util/Vector;->indexOf(Ljava/lang/Object;I)I+]Ljava/lang/Object;missing_types
+HSPLjava/util/Vector;->isEmpty()Z
+HSPLjava/util/Vector;->iterator()Ljava/util/Iterator;
+HSPLjava/util/Vector;->removeAllElements()V
+HSPLjava/util/Vector;->removeElement(Ljava/lang/Object;)Z+]Ljava/util/Vector;Ljava/util/Vector;
+HSPLjava/util/Vector;->removeElementAt(I)V
+HSPLjava/util/Vector;->size()I
+HSPLjava/util/Vector;->sort(Ljava/util/Comparator;)V
+HSPLjava/util/Vector;->toArray()[Ljava/lang/Object;
+HSPLjava/util/Vector;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;
+HSPLjava/util/WeakHashMap$Entry;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;ILjava/util/WeakHashMap$Entry;)V
+HSPLjava/util/WeakHashMap$Entry;->getKey()Ljava/lang/Object;+]Ljava/util/WeakHashMap$Entry;Ljava/util/WeakHashMap$Entry;
+HSPLjava/util/WeakHashMap$Entry;->getValue()Ljava/lang/Object;
+HSPLjava/util/WeakHashMap$EntryIterator;-><init>(Ljava/util/WeakHashMap;)V
+HSPLjava/util/WeakHashMap$EntryIterator;-><init>(Ljava/util/WeakHashMap;Ljava/util/WeakHashMap$1;)V
+HSPLjava/util/WeakHashMap$EntryIterator;->next()Ljava/lang/Object;+]Ljava/util/WeakHashMap$EntryIterator;Ljava/util/WeakHashMap$EntryIterator;
+HSPLjava/util/WeakHashMap$EntryIterator;->next()Ljava/util/Map$Entry;+]Ljava/util/WeakHashMap$EntryIterator;Ljava/util/WeakHashMap$EntryIterator;
+HSPLjava/util/WeakHashMap$EntrySet;-><init>(Ljava/util/WeakHashMap;)V
+HSPLjava/util/WeakHashMap$EntrySet;-><init>(Ljava/util/WeakHashMap;Ljava/util/WeakHashMap$1;)V
+HSPLjava/util/WeakHashMap$EntrySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/WeakHashMap$HashIterator;-><init>(Ljava/util/WeakHashMap;)V+]Ljava/util/WeakHashMap;Ljava/util/WeakHashMap;
+HSPLjava/util/WeakHashMap$HashIterator;->hasNext()Z+]Ljava/util/WeakHashMap$Entry;Ljava/util/WeakHashMap$Entry;
+HSPLjava/util/WeakHashMap$HashIterator;->nextEntry()Ljava/util/WeakHashMap$Entry;+]Ljava/util/WeakHashMap$HashIterator;Ljava/util/WeakHashMap$KeyIterator;
+HSPLjava/util/WeakHashMap$KeyIterator;-><init>(Ljava/util/WeakHashMap;)V
+HSPLjava/util/WeakHashMap$KeyIterator;-><init>(Ljava/util/WeakHashMap;Ljava/util/WeakHashMap$1;)V
+HSPLjava/util/WeakHashMap$KeyIterator;->next()Ljava/lang/Object;+]Ljava/util/WeakHashMap$KeyIterator;Ljava/util/WeakHashMap$KeyIterator;]Ljava/util/WeakHashMap$Entry;Ljava/util/WeakHashMap$Entry;
+HSPLjava/util/WeakHashMap$KeySet;-><init>(Ljava/util/WeakHashMap;)V
+HSPLjava/util/WeakHashMap$KeySet;-><init>(Ljava/util/WeakHashMap;Ljava/util/WeakHashMap$1;)V
+HSPLjava/util/WeakHashMap$KeySet;->iterator()Ljava/util/Iterator;
+HSPLjava/util/WeakHashMap$KeySet;->size()I+]Ljava/util/WeakHashMap;Ljava/util/WeakHashMap;
+HSPLjava/util/WeakHashMap$ValueIterator;-><init>(Ljava/util/WeakHashMap;)V
+HSPLjava/util/WeakHashMap$ValueIterator;-><init>(Ljava/util/WeakHashMap;Ljava/util/WeakHashMap$1;)V
+HSPLjava/util/WeakHashMap$ValueIterator;->next()Ljava/lang/Object;+]Ljava/util/WeakHashMap$ValueIterator;Ljava/util/WeakHashMap$ValueIterator;
+HSPLjava/util/WeakHashMap$Values;-><init>(Ljava/util/WeakHashMap;)V
+HSPLjava/util/WeakHashMap$Values;-><init>(Ljava/util/WeakHashMap;Ljava/util/WeakHashMap$1;)V
+HSPLjava/util/WeakHashMap$Values;->iterator()Ljava/util/Iterator;
+HSPLjava/util/WeakHashMap;-><init>()V
+HSPLjava/util/WeakHashMap;-><init>(I)V
+HSPLjava/util/WeakHashMap;-><init>(IF)V
+HSPLjava/util/WeakHashMap;->clear()V+]Ljava/lang/ref/ReferenceQueue;Ljava/lang/ref/ReferenceQueue;
+HSPLjava/util/WeakHashMap;->containsKey(Ljava/lang/Object;)Z+]Ljava/util/WeakHashMap;Ljava/util/WeakHashMap;
+HSPLjava/util/WeakHashMap;->entrySet()Ljava/util/Set;
+HSPLjava/util/WeakHashMap;->eq(Ljava/lang/Object;Ljava/lang/Object;)Z+]Ljava/lang/Object;missing_types
+HSPLjava/util/WeakHashMap;->expungeStaleEntries()V+]Ljava/lang/ref/ReferenceQueue;Ljava/lang/ref/ReferenceQueue;
+HSPLjava/util/WeakHashMap;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/WeakHashMap;Ljava/util/WeakHashMap;]Ljava/util/WeakHashMap$Entry;Ljava/util/WeakHashMap$Entry;
+HSPLjava/util/WeakHashMap;->getEntry(Ljava/lang/Object;)Ljava/util/WeakHashMap$Entry;+]Ljava/util/WeakHashMap;missing_types]Ljava/util/WeakHashMap$Entry;Ljava/util/WeakHashMap$Entry;
+HSPLjava/util/WeakHashMap;->getTable()[Ljava/util/WeakHashMap$Entry;
+HSPLjava/util/WeakHashMap;->hash(Ljava/lang/Object;)I+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/WeakHashMap;->indexFor(II)I
+HSPLjava/util/WeakHashMap;->isEmpty()Z+]Ljava/util/WeakHashMap;Ljava/util/WeakHashMap;
+HSPLjava/util/WeakHashMap;->keySet()Ljava/util/Set;
+HSPLjava/util/WeakHashMap;->maskNull(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/WeakHashMap;->newTable(I)[Ljava/util/WeakHashMap$Entry;
+HSPLjava/util/WeakHashMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/WeakHashMap;missing_types]Ljava/util/WeakHashMap$Entry;Ljava/util/WeakHashMap$Entry;
+HSPLjava/util/WeakHashMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/WeakHashMap;Ljava/util/WeakHashMap;]Ljava/util/WeakHashMap$Entry;Ljava/util/WeakHashMap$Entry;
+HSPLjava/util/WeakHashMap;->resize(I)V
+HSPLjava/util/WeakHashMap;->size()I
+HSPLjava/util/WeakHashMap;->transfer([Ljava/util/WeakHashMap$Entry;[Ljava/util/WeakHashMap$Entry;)V+]Ljava/util/WeakHashMap$Entry;Ljava/util/WeakHashMap$Entry;
+HSPLjava/util/WeakHashMap;->unmaskNull(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/WeakHashMap;->values()Ljava/util/Collection;
+HSPLjava/util/concurrent/AbstractExecutorService;-><init>()V
+HSPLjava/util/concurrent/AbstractExecutorService;->invokeAll(Ljava/util/Collection;JLjava/util/concurrent/TimeUnit;)Ljava/util/List;+]Ljava/util/concurrent/Future;Ljava/util/concurrent/FutureTask;]Ljava/util/Collection;Ljava/util/ArrayList;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;]Ljava/util/concurrent/AbstractExecutorService;Ljava/util/concurrent/ThreadPoolExecutor;]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLjava/util/concurrent/AbstractExecutorService;->newTaskFor(Ljava/lang/Runnable;Ljava/lang/Object;)Ljava/util/concurrent/RunnableFuture;
+HSPLjava/util/concurrent/AbstractExecutorService;->newTaskFor(Ljava/util/concurrent/Callable;)Ljava/util/concurrent/RunnableFuture;
+HSPLjava/util/concurrent/AbstractExecutorService;->submit(Ljava/lang/Runnable;)Ljava/util/concurrent/Future;+]Ljava/util/concurrent/AbstractExecutorService;missing_types
+HSPLjava/util/concurrent/AbstractExecutorService;->submit(Ljava/lang/Runnable;Ljava/lang/Object;)Ljava/util/concurrent/Future;
+HSPLjava/util/concurrent/AbstractExecutorService;->submit(Ljava/util/concurrent/Callable;)Ljava/util/concurrent/Future;+]Ljava/util/concurrent/AbstractExecutorService;missing_types
+HSPLjava/util/concurrent/ArrayBlockingQueue;-><init>(I)V
+HSPLjava/util/concurrent/ArrayBlockingQueue;-><init>(IZ)V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->add(Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/ArrayBlockingQueue;->dequeue()Ljava/lang/Object;+]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->drainTo(Ljava/util/Collection;I)I+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/Collection;Ljava/util/ArrayList;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->enqueue(Ljava/lang/Object;)V+]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->itemAt(I)Ljava/lang/Object;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->offer(Ljava/lang/Object;)Z+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->peek()Ljava/lang/Object;+]Ljava/util/concurrent/ArrayBlockingQueue;Ljava/util/concurrent/ArrayBlockingQueue;]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->poll()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->poll(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$1;,Ljava/util/concurrent/TimeUnit$4;,Ljava/util/concurrent/TimeUnit$5;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->put(Ljava/lang/Object;)V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->size()I+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ArrayBlockingQueue;->take()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/CancellationException;-><init>()V
+HSPLjava/util/concurrent/CancellationException;-><init>(Ljava/lang/String;)V
+HSPLjava/util/concurrent/CompletableFuture$Completion;-><init>()V
+HSPLjava/util/concurrent/CompletableFuture$Signaller;-><init>(ZJJ)V
+HSPLjava/util/concurrent/CompletableFuture$Signaller;->block()Z+]Ljava/util/concurrent/CompletableFuture$Signaller;Ljava/util/concurrent/CompletableFuture$Signaller;
+HSPLjava/util/concurrent/CompletableFuture$Signaller;->isReleasable()Z
+HSPLjava/util/concurrent/CompletableFuture$Signaller;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+HSPLjava/util/concurrent/CompletableFuture;-><init>()V
+HSPLjava/util/concurrent/CompletableFuture;->casStack(Ljava/util/concurrent/CompletableFuture$Completion;Ljava/util/concurrent/CompletableFuture$Completion;)Z
+HSPLjava/util/concurrent/CompletableFuture;->complete(Ljava/lang/Object;)Z+]Ljava/util/concurrent/CompletableFuture;megamorphic_types
+HSPLjava/util/concurrent/CompletableFuture;->completeValue(Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/CompletableFuture;->get()Ljava/lang/Object;
+HSPLjava/util/concurrent/CompletableFuture;->get(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;+]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$4;
+HSPLjava/util/concurrent/CompletableFuture;->internalComplete(Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/CompletableFuture;->isDone()Z
+HSPLjava/util/concurrent/CompletableFuture;->lazySetNext(Ljava/util/concurrent/CompletableFuture$Completion;Ljava/util/concurrent/CompletableFuture$Completion;)V
+HSPLjava/util/concurrent/CompletableFuture;->postComplete()V+]Ljava/util/concurrent/CompletableFuture$Completion;megamorphic_types]Ljava/util/concurrent/CompletableFuture;missing_types
+HSPLjava/util/concurrent/CompletableFuture;->reportGet(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/concurrent/CompletableFuture;->timedGet(J)Ljava/lang/Object;+]Ljava/util/concurrent/CompletableFuture;missing_types
+HSPLjava/util/concurrent/CompletableFuture;->tryPushStack(Ljava/util/concurrent/CompletableFuture$Completion;)Z
+HSPLjava/util/concurrent/CompletableFuture;->waitingGet(Z)Ljava/lang/Object;+]Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;,Lcom/android/internal/infra/AndroidFuture;,Lcom/android/internal/infra/AndroidFuture$ThenComposeAsync;
+HSPLjava/util/concurrent/ConcurrentHashMap$BaseIterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIILjava/util/concurrent/ConcurrentHashMap;)V+]Ljava/util/concurrent/ConcurrentHashMap$BaseIterator;Ljava/util/concurrent/ConcurrentHashMap$ValueIterator;,Ljava/util/concurrent/ConcurrentHashMap$EntryIterator;,Ljava/util/concurrent/ConcurrentHashMap$KeyIterator;
+HSPLjava/util/concurrent/ConcurrentHashMap$BaseIterator;->hasNext()Z
+HSPLjava/util/concurrent/ConcurrentHashMap$BaseIterator;->remove()V+]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/concurrent/ConcurrentHashMap$CollectionView;-><init>(Ljava/util/concurrent/ConcurrentHashMap;)V
+HSPLjava/util/concurrent/ConcurrentHashMap$CollectionView;->size()I+]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/concurrent/ConcurrentHashMap$CollectionView;->toArray()[Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/util/Iterator;Ljava/util/concurrent/ConcurrentHashMap$EntryIterator;,Ljava/util/concurrent/ConcurrentHashMap$ValueIterator;,Ljava/util/concurrent/ConcurrentHashMap$KeyIterator;]Ljava/util/concurrent/ConcurrentHashMap$CollectionView;Ljava/util/concurrent/ConcurrentHashMap$EntrySetView;,Ljava/util/concurrent/ConcurrentHashMap$KeySetView;,Ljava/util/concurrent/ConcurrentHashMap$ValuesView;
+HSPLjava/util/concurrent/ConcurrentHashMap$CounterCell;-><init>(J)V
+HSPLjava/util/concurrent/ConcurrentHashMap$EntryIterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIILjava/util/concurrent/ConcurrentHashMap;)V
+HSPLjava/util/concurrent/ConcurrentHashMap$EntryIterator;->next()Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentHashMap$EntryIterator;Ljava/util/concurrent/ConcurrentHashMap$EntryIterator;
+HSPLjava/util/concurrent/ConcurrentHashMap$EntryIterator;->next()Ljava/util/Map$Entry;+]Ljava/util/concurrent/ConcurrentHashMap$EntryIterator;Ljava/util/concurrent/ConcurrentHashMap$EntryIterator;
+HSPLjava/util/concurrent/ConcurrentHashMap$EntrySetView;-><init>(Ljava/util/concurrent/ConcurrentHashMap;)V
+HSPLjava/util/concurrent/ConcurrentHashMap$EntrySetView;->iterator()Ljava/util/Iterator;
+HSPLjava/util/concurrent/ConcurrentHashMap$ForwardingNode;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;)V
+HSPLjava/util/concurrent/ConcurrentHashMap$ForwardingNode;->find(ILjava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$Node;+]Ljava/lang/Object;Ljava/util/Locale$LocaleKey;
+HSPLjava/util/concurrent/ConcurrentHashMap$KeyIterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIILjava/util/concurrent/ConcurrentHashMap;)V
+HSPLjava/util/concurrent/ConcurrentHashMap$KeyIterator;->next()Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentHashMap$KeyIterator;Ljava/util/concurrent/ConcurrentHashMap$KeyIterator;
+HSPLjava/util/concurrent/ConcurrentHashMap$KeySetView;-><init>(Ljava/util/concurrent/ConcurrentHashMap;Ljava/lang/Object;)V
+HSPLjava/util/concurrent/ConcurrentHashMap$KeySetView;->iterator()Ljava/util/Iterator;
+HSPLjava/util/concurrent/ConcurrentHashMap$KeySetView;->spliterator()Ljava/util/Spliterator;+]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/concurrent/ConcurrentHashMap$MapEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentHashMap;)V
+HSPLjava/util/concurrent/ConcurrentHashMap$MapEntry;->getKey()Ljava/lang/Object;
+HSPLjava/util/concurrent/ConcurrentHashMap$MapEntry;->getValue()Ljava/lang/Object;
+HSPLjava/util/concurrent/ConcurrentHashMap$Node;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentHashMap$Node;)V
+HSPLjava/util/concurrent/ConcurrentHashMap$ReservationNode;-><init>()V
+HSPLjava/util/concurrent/ConcurrentHashMap$Traverser;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;III)V
+HSPLjava/util/concurrent/ConcurrentHashMap$Traverser;->advance()Ljava/util/concurrent/ConcurrentHashMap$Node;
+HSPLjava/util/concurrent/ConcurrentHashMap$TreeBin;->find(ILjava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$Node;
+HSPLjava/util/concurrent/ConcurrentHashMap$TreeNode;->findTreeNode(ILjava/lang/Object;Ljava/lang/Class;)Ljava/util/concurrent/ConcurrentHashMap$TreeNode;+]Ljava/lang/Object;Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier$OidHandle;
+HSPLjava/util/concurrent/ConcurrentHashMap$ValueIterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIILjava/util/concurrent/ConcurrentHashMap;)V
+HSPLjava/util/concurrent/ConcurrentHashMap$ValueIterator;->next()Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentHashMap$ValueIterator;Ljava/util/concurrent/ConcurrentHashMap$ValueIterator;
+HSPLjava/util/concurrent/ConcurrentHashMap$ValuesView;-><init>(Ljava/util/concurrent/ConcurrentHashMap;)V
+HSPLjava/util/concurrent/ConcurrentHashMap$ValuesView;->iterator()Ljava/util/Iterator;
+HSPLjava/util/concurrent/ConcurrentHashMap;-><init>()V
+HSPLjava/util/concurrent/ConcurrentHashMap;-><init>(I)V
+HSPLjava/util/concurrent/ConcurrentHashMap;-><init>(IFI)V
+HSPLjava/util/concurrent/ConcurrentHashMap;-><init>(Ljava/util/Map;)V+]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/concurrent/ConcurrentHashMap;->addCount(JI)V+]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/ConcurrentHashMap;->casTabAt([Ljava/util/concurrent/ConcurrentHashMap$Node;ILjava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$Node;)Z
+HSPLjava/util/concurrent/ConcurrentHashMap;->clear()V
+HSPLjava/util/concurrent/ConcurrentHashMap;->computeIfAbsent(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;+]Ljava/lang/Object;missing_types
+HSPLjava/util/concurrent/ConcurrentHashMap;->containsKey(Ljava/lang/Object;)Z+]Ljava/util/concurrent/ConcurrentHashMap;missing_types
+HSPLjava/util/concurrent/ConcurrentHashMap;->entrySet()Ljava/util/Set;
+HSPLjava/util/concurrent/ConcurrentHashMap;->fullAddCount(JZ)V
+HSPLjava/util/concurrent/ConcurrentHashMap;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/Object;megamorphic_types]Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$ForwardingNode;,Ljava/util/concurrent/ConcurrentHashMap$ReservationNode;
+HSPLjava/util/concurrent/ConcurrentHashMap;->getOrDefault(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/concurrent/ConcurrentHashMap;->helpTransfer([Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$Node;)[Ljava/util/concurrent/ConcurrentHashMap$Node;
+HSPLjava/util/concurrent/ConcurrentHashMap;->initTable()[Ljava/util/concurrent/ConcurrentHashMap$Node;
+HSPLjava/util/concurrent/ConcurrentHashMap;->isEmpty()Z+]Ljava/util/concurrent/ConcurrentHashMap;missing_types
+HSPLjava/util/concurrent/ConcurrentHashMap;->keySet()Ljava/util/Set;
+HSPLjava/util/concurrent/ConcurrentHashMap;->mappingCount()J+]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/concurrent/ConcurrentHashMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentHashMap;missing_types
+HSPLjava/util/concurrent/ConcurrentHashMap;->putAll(Ljava/util/Map;)V+]Ljava/util/Map$Entry;missing_types]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/util/Map;missing_types]Ljava/util/Iterator;missing_types]Ljava/util/Set;missing_types
+HSPLjava/util/concurrent/ConcurrentHashMap;->putIfAbsent(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/concurrent/ConcurrentHashMap;->putVal(Ljava/lang/Object;Ljava/lang/Object;Z)Ljava/lang/Object;+]Ljava/lang/Object;megamorphic_types]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/concurrent/ConcurrentHashMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentHashMap;missing_types
+HSPLjava/util/concurrent/ConcurrentHashMap;->replace(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z+]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/concurrent/ConcurrentHashMap;->replaceNode(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/Object;megamorphic_types]Ljava/util/concurrent/ConcurrentHashMap$TreeNode;Ljava/util/concurrent/ConcurrentHashMap$TreeNode;]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLjava/util/concurrent/ConcurrentHashMap;->resizeStamp(I)I
+HSPLjava/util/concurrent/ConcurrentHashMap;->setTabAt([Ljava/util/concurrent/ConcurrentHashMap$Node;ILjava/util/concurrent/ConcurrentHashMap$Node;)V
+HSPLjava/util/concurrent/ConcurrentHashMap;->size()I+]Ljava/util/concurrent/ConcurrentHashMap;missing_types
+HSPLjava/util/concurrent/ConcurrentHashMap;->spread(I)I
+HSPLjava/util/concurrent/ConcurrentHashMap;->sumCount()J
+HSPLjava/util/concurrent/ConcurrentHashMap;->tabAt([Ljava/util/concurrent/ConcurrentHashMap$Node;I)Ljava/util/concurrent/ConcurrentHashMap$Node;
+HSPLjava/util/concurrent/ConcurrentHashMap;->tableSizeFor(I)I
+HSPLjava/util/concurrent/ConcurrentHashMap;->transfer([Ljava/util/concurrent/ConcurrentHashMap$Node;[Ljava/util/concurrent/ConcurrentHashMap$Node;)V
+HSPLjava/util/concurrent/ConcurrentHashMap;->treeifyBin([Ljava/util/concurrent/ConcurrentHashMap$Node;I)V
+HSPLjava/util/concurrent/ConcurrentHashMap;->tryPresize(I)V
+HSPLjava/util/concurrent/ConcurrentHashMap;->values()Ljava/util/Collection;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque$Node;-><init>(Ljava/lang/Object;)V
+HSPLjava/util/concurrent/ConcurrentLinkedDeque$Node;->casItem(Ljava/lang/Object;Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/ConcurrentLinkedDeque$Node;->casNext(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Z
+HSPLjava/util/concurrent/ConcurrentLinkedDeque$Node;->casPrev(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Z
+HSPLjava/util/concurrent/ConcurrentLinkedDeque$Node;->lazySetNext(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V
+HSPLjava/util/concurrent/ConcurrentLinkedDeque$Node;->lazySetPrev(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;-><init>()V
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->add(Ljava/lang/Object;)Z+]Ljava/util/concurrent/ConcurrentLinkedDeque;Ljava/util/concurrent/ConcurrentLinkedDeque;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->casTail(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Z
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->first()Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->isEmpty()Z+]Ljava/util/concurrent/ConcurrentLinkedDeque;Ljava/util/concurrent/ConcurrentLinkedDeque;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->linkLast(Ljava/lang/Object;)V+]Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->nextTerminator()Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->offerLast(Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->peekFirst()Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentLinkedDeque;Ljava/util/concurrent/ConcurrentLinkedDeque;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->pollFirst()Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentLinkedDeque;Ljava/util/concurrent/ConcurrentLinkedDeque;]Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->prevTerminator()Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->size()I+]Ljava/util/concurrent/ConcurrentLinkedDeque;Ljava/util/concurrent/ConcurrentLinkedDeque;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->skipDeletedPredecessors(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V+]Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->skipDeletedSuccessors(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V+]Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->succ(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Ljava/util/concurrent/ConcurrentLinkedDeque$Node;+]Ljava/util/concurrent/ConcurrentLinkedDeque;Ljava/util/concurrent/ConcurrentLinkedDeque;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->unlink(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V+]Ljava/util/concurrent/ConcurrentLinkedDeque;Ljava/util/concurrent/ConcurrentLinkedDeque;]Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->unlinkLast(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V+]Ljava/util/concurrent/ConcurrentLinkedDeque;Ljava/util/concurrent/ConcurrentLinkedDeque;]Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->updateHead()V
+HSPLjava/util/concurrent/ConcurrentLinkedDeque;->updateTail()V
+HSPLjava/util/concurrent/ConcurrentLinkedQueue$Itr;-><init>(Ljava/util/concurrent/ConcurrentLinkedQueue;)V+]Ljava/util/concurrent/ConcurrentLinkedQueue;missing_types
+HSPLjava/util/concurrent/ConcurrentLinkedQueue$Itr;->hasNext()Z
+HSPLjava/util/concurrent/ConcurrentLinkedQueue$Itr;->next()Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentLinkedQueue;Ljava/util/concurrent/ConcurrentLinkedQueue;
+HSPLjava/util/concurrent/ConcurrentLinkedQueue$Node;-><init>()V
+HSPLjava/util/concurrent/ConcurrentLinkedQueue$Node;-><init>(Ljava/util/concurrent/ConcurrentLinkedQueue$1;)V
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;-><init>()V
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->add(Ljava/lang/Object;)Z+]Ljava/util/concurrent/ConcurrentLinkedQueue;missing_types
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->casHead(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)Z
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->casItem(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/lang/Object;Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->casNext(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)Z
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->casTail(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)Z
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->contains(Ljava/lang/Object;)Z+]Ljava/util/concurrent/ConcurrentLinkedQueue;Ljava/util/concurrent/ConcurrentLinkedQueue;
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->first()Ljava/util/concurrent/ConcurrentLinkedQueue$Node;+]Ljava/util/concurrent/ConcurrentLinkedQueue;missing_types
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->isEmpty()Z+]Ljava/util/concurrent/ConcurrentLinkedQueue;missing_types
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->iterator()Ljava/util/Iterator;
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->lazySetNext(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)V
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->newNode(Ljava/lang/Object;)Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->offer(Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->peek()Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentLinkedQueue;Ljava/util/concurrent/ConcurrentLinkedQueue;
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->poll()Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentLinkedQueue;missing_types
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->remove(Ljava/lang/Object;)Z+]Ljava/util/concurrent/ConcurrentLinkedQueue;Ljava/util/concurrent/ConcurrentLinkedQueue;]Ljava/lang/Object;missing_types
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->size()I+]Ljava/util/concurrent/ConcurrentLinkedQueue;missing_types
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->succ(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->toArray()[Ljava/lang/Object;
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->toArrayInternal([Ljava/lang/Object;)[Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentLinkedQueue;Ljava/util/concurrent/ConcurrentLinkedQueue;
+HSPLjava/util/concurrent/ConcurrentLinkedQueue;->updateHead(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)V
+HSPLjava/util/concurrent/ConcurrentSkipListMap$HeadIndex;-><init>(Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;I)V
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Index;-><init>(Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;)V
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Index;->casRight(Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;)Z
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Index;->link(Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;)Z+]Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;,Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Index;->unlink(Ljava/util/concurrent/ConcurrentSkipListMap$Index;)Z+]Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;,Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Iter;-><init>(Ljava/util/concurrent/ConcurrentSkipListMap;)V+]Ljava/util/concurrent/ConcurrentSkipListMap;Ljava/util/concurrent/ConcurrentSkipListMap;
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Iter;->advance()V
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Iter;->hasNext()Z
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Node;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentSkipListMap$Node;)V
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Node;-><init>(Ljava/util/concurrent/ConcurrentSkipListMap$Node;)V
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Node;->appendMarker(Ljava/util/concurrent/ConcurrentSkipListMap$Node;)Z+]Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Node;->casNext(Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/concurrent/ConcurrentSkipListMap$Node;)Z
+HSPLjava/util/concurrent/ConcurrentSkipListMap$Node;->casValue(Ljava/lang/Object;Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/ConcurrentSkipListMap;-><init>()V
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->casHead(Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;)Z
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->cpr(Ljava/util/Comparator;Ljava/lang/Object;Ljava/lang/Object;)I+]Ljava/lang/Comparable;missing_types
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->doGet(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->doPut(Ljava/lang/Object;Ljava/lang/Object;Z)Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/concurrent/ConcurrentSkipListMap$Node;]Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;,Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->doRemove(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/concurrent/ConcurrentSkipListMap$Node;]Ljava/lang/Object;Ljava/lang/Boolean;
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->findFirst()Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->findPredecessor(Ljava/lang/Object;Ljava/util/Comparator;)Ljava/util/concurrent/ConcurrentSkipListMap$Node;+]Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;,Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->initialize()V
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->putIfAbsent(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentSkipListMap;Ljava/util/concurrent/ConcurrentSkipListMap;
+HSPLjava/util/concurrent/ConcurrentSkipListMap;->tryReduceLevel()V
+HSPLjava/util/concurrent/ConcurrentSkipListSet;-><init>()V
+HSPLjava/util/concurrent/ConcurrentSkipListSet;->add(Ljava/lang/Object;)Z+]Ljava/util/concurrent/ConcurrentNavigableMap;Ljava/util/concurrent/ConcurrentSkipListMap;
+HSPLjava/util/concurrent/CopyOnWriteArrayList$COWIterator;-><init>([Ljava/lang/Object;I)V
+HSPLjava/util/concurrent/CopyOnWriteArrayList$COWIterator;->hasNext()Z
+HSPLjava/util/concurrent/CopyOnWriteArrayList$COWIterator;->next()Ljava/lang/Object;+]Ljava/util/concurrent/CopyOnWriteArrayList$COWIterator;Ljava/util/concurrent/CopyOnWriteArrayList$COWIterator;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;-><init>()V+]Ljava/util/concurrent/CopyOnWriteArrayList;missing_types
+HSPLjava/util/concurrent/CopyOnWriteArrayList;-><init>(Ljava/util/Collection;)V+]Ljava/lang/Object;missing_types]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;]Ljava/util/Collection;missing_types
+HSPLjava/util/concurrent/CopyOnWriteArrayList;-><init>([Ljava/lang/Object;)V+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->add(ILjava/lang/Object;)V+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->add(Ljava/lang/Object;)Z+]Ljava/util/concurrent/CopyOnWriteArrayList;missing_types
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->addAll(Ljava/util/Collection;)Z+]Ljava/lang/Object;missing_types]Ljava/util/Collection;missing_types]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->addAllAbsent(Ljava/util/Collection;)I+]Ljava/util/Collection;missing_types]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->addIfAbsent(Ljava/lang/Object;)Z+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->addIfAbsent(Ljava/lang/Object;[Ljava/lang/Object;)Z+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->clear()V+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->contains(Ljava/lang/Object;)Z+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->get(I)Ljava/lang/Object;+]Ljava/util/concurrent/CopyOnWriteArrayList;missing_types
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->get([Ljava/lang/Object;I)Ljava/lang/Object;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->getArray()[Ljava/lang/Object;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->indexOf(Ljava/lang/Object;[Ljava/lang/Object;II)I+]Ljava/lang/Object;megamorphic_types
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->isEmpty()Z+]Ljava/util/concurrent/CopyOnWriteArrayList;missing_types
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->iterator()Ljava/util/Iterator;+]Ljava/util/concurrent/CopyOnWriteArrayList;missing_types
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->remove(I)Ljava/lang/Object;+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->remove(Ljava/lang/Object;)Z+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->remove(Ljava/lang/Object;[Ljava/lang/Object;I)Z+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->removeAll(Ljava/util/Collection;)Z+]Ljava/util/Collection;missing_types]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->setArray([Ljava/lang/Object;)V
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->size()I+]Ljava/util/concurrent/CopyOnWriteArrayList;missing_types
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->toArray()[Ljava/lang/Object;+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;+]Ljava/lang/Object;[Ljava/util/logging/Handler;]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArrayList;->toString()Ljava/lang/String;+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArraySet;-><init>()V
+HSPLjava/util/concurrent/CopyOnWriteArraySet;->add(Ljava/lang/Object;)Z+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArraySet;->clear()V+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArraySet;->contains(Ljava/lang/Object;)Z+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArraySet;->isEmpty()Z+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArraySet;->iterator()Ljava/util/Iterator;+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArraySet;->remove(Ljava/lang/Object;)Z+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CopyOnWriteArraySet;->size()I+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/concurrent/CountDownLatch$Sync;-><init>(I)V+]Ljava/util/concurrent/CountDownLatch$Sync;Ljava/util/concurrent/CountDownLatch$Sync;
+HSPLjava/util/concurrent/CountDownLatch$Sync;->getCount()I+]Ljava/util/concurrent/CountDownLatch$Sync;Ljava/util/concurrent/CountDownLatch$Sync;
+HSPLjava/util/concurrent/CountDownLatch$Sync;->tryAcquireShared(I)I+]Ljava/util/concurrent/CountDownLatch$Sync;Ljava/util/concurrent/CountDownLatch$Sync;
+HSPLjava/util/concurrent/CountDownLatch$Sync;->tryReleaseShared(I)Z+]Ljava/util/concurrent/CountDownLatch$Sync;Ljava/util/concurrent/CountDownLatch$Sync;
+HSPLjava/util/concurrent/CountDownLatch;-><init>(I)V
+HSPLjava/util/concurrent/CountDownLatch;->await()V+]Ljava/util/concurrent/CountDownLatch$Sync;Ljava/util/concurrent/CountDownLatch$Sync;
+HSPLjava/util/concurrent/CountDownLatch;->await(JLjava/util/concurrent/TimeUnit;)Z+]Ljava/util/concurrent/CountDownLatch$Sync;Ljava/util/concurrent/CountDownLatch$Sync;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$4;,Ljava/util/concurrent/TimeUnit$5;,Ljava/util/concurrent/TimeUnit$1;
+HSPLjava/util/concurrent/CountDownLatch;->countDown()V+]Ljava/util/concurrent/CountDownLatch$Sync;Ljava/util/concurrent/CountDownLatch$Sync;
+HSPLjava/util/concurrent/CountDownLatch;->getCount()J+]Ljava/util/concurrent/CountDownLatch$Sync;Ljava/util/concurrent/CountDownLatch$Sync;
+HSPLjava/util/concurrent/DelayQueue;-><init>()V
+HSPLjava/util/concurrent/DelayQueue;->add(Ljava/util/concurrent/Delayed;)Z+]Ljava/util/concurrent/DelayQueue;Ljava/util/concurrent/DelayQueue;
+HSPLjava/util/concurrent/DelayQueue;->offer(Ljava/util/concurrent/Delayed;)Z+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;]Ljava/util/PriorityQueue;Ljava/util/PriorityQueue;
+HSPLjava/util/concurrent/ExecutionException;-><init>(Ljava/lang/Throwable;)V
+HSPLjava/util/concurrent/Executors$DefaultThreadFactory;-><init>()V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Thread;missing_types]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/Executors$DefaultThreadFactory;->newThread(Ljava/lang/Runnable;)Ljava/lang/Thread;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Thread;Ljava/lang/Thread;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/Executors$DelegatedExecutorService;-><init>(Ljava/util/concurrent/ExecutorService;)V
+HSPLjava/util/concurrent/Executors$DelegatedExecutorService;->execute(Ljava/lang/Runnable;)V+]Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ThreadPoolExecutor;,Ljava/util/concurrent/ScheduledThreadPoolExecutor;
+HSPLjava/util/concurrent/Executors$DelegatedExecutorService;->isShutdown()Z+]Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ScheduledThreadPoolExecutor;,Ljava/util/concurrent/ThreadPoolExecutor;
+HSPLjava/util/concurrent/Executors$DelegatedExecutorService;->shutdown()V+]Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ThreadPoolExecutor;,Ljava/util/concurrent/ScheduledThreadPoolExecutor;
+HSPLjava/util/concurrent/Executors$DelegatedExecutorService;->shutdownNow()Ljava/util/List;+]Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ThreadPoolExecutor;,Ljava/util/concurrent/ScheduledThreadPoolExecutor;
+HSPLjava/util/concurrent/Executors$DelegatedExecutorService;->submit(Ljava/lang/Runnable;)Ljava/util/concurrent/Future;+]Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ThreadPoolExecutor;,Ljava/util/concurrent/ScheduledThreadPoolExecutor;
+HSPLjava/util/concurrent/Executors$DelegatedExecutorService;->submit(Ljava/util/concurrent/Callable;)Ljava/util/concurrent/Future;+]Ljava/util/concurrent/ExecutorService;Ljava/util/concurrent/ThreadPoolExecutor;
+HSPLjava/util/concurrent/Executors$DelegatedScheduledExecutorService;-><init>(Ljava/util/concurrent/ScheduledExecutorService;)V
+HSPLjava/util/concurrent/Executors$DelegatedScheduledExecutorService;->schedule(Ljava/lang/Runnable;JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/ScheduledFuture;+]Ljava/util/concurrent/ScheduledExecutorService;Ljava/util/concurrent/ScheduledThreadPoolExecutor;
+HSPLjava/util/concurrent/Executors$DelegatedScheduledExecutorService;->scheduleAtFixedRate(Ljava/lang/Runnable;JJLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/ScheduledFuture;
+HSPLjava/util/concurrent/Executors$FinalizableDelegatedExecutorService;-><init>(Ljava/util/concurrent/ExecutorService;)V
+HSPLjava/util/concurrent/Executors$FinalizableDelegatedExecutorService;->finalize()V
+HSPLjava/util/concurrent/Executors$RunnableAdapter;-><init>(Ljava/lang/Runnable;Ljava/lang/Object;)V
+HSPLjava/util/concurrent/Executors$RunnableAdapter;->call()Ljava/lang/Object;+]Ljava/lang/Runnable;missing_types
+HSPLjava/util/concurrent/Executors;->callable(Ljava/lang/Runnable;)Ljava/util/concurrent/Callable;
+HSPLjava/util/concurrent/Executors;->callable(Ljava/lang/Runnable;Ljava/lang/Object;)Ljava/util/concurrent/Callable;
+HSPLjava/util/concurrent/Executors;->defaultThreadFactory()Ljava/util/concurrent/ThreadFactory;
+HSPLjava/util/concurrent/Executors;->newCachedThreadPool()Ljava/util/concurrent/ExecutorService;
+HSPLjava/util/concurrent/Executors;->newCachedThreadPool(Ljava/util/concurrent/ThreadFactory;)Ljava/util/concurrent/ExecutorService;
+HSPLjava/util/concurrent/Executors;->newFixedThreadPool(I)Ljava/util/concurrent/ExecutorService;
+HSPLjava/util/concurrent/Executors;->newFixedThreadPool(ILjava/util/concurrent/ThreadFactory;)Ljava/util/concurrent/ExecutorService;
+HSPLjava/util/concurrent/Executors;->newScheduledThreadPool(I)Ljava/util/concurrent/ScheduledExecutorService;
+HSPLjava/util/concurrent/Executors;->newScheduledThreadPool(ILjava/util/concurrent/ThreadFactory;)Ljava/util/concurrent/ScheduledExecutorService;
+HSPLjava/util/concurrent/Executors;->newSingleThreadExecutor()Ljava/util/concurrent/ExecutorService;
+HSPLjava/util/concurrent/Executors;->newSingleThreadExecutor(Ljava/util/concurrent/ThreadFactory;)Ljava/util/concurrent/ExecutorService;
+HSPLjava/util/concurrent/Executors;->newSingleThreadScheduledExecutor()Ljava/util/concurrent/ScheduledExecutorService;
+HSPLjava/util/concurrent/Executors;->newSingleThreadScheduledExecutor(Ljava/util/concurrent/ThreadFactory;)Ljava/util/concurrent/ScheduledExecutorService;
+HSPLjava/util/concurrent/Executors;->unconfigurableExecutorService(Ljava/util/concurrent/ExecutorService;)Ljava/util/concurrent/ExecutorService;
+HSPLjava/util/concurrent/Executors;->unconfigurableScheduledExecutorService(Ljava/util/concurrent/ScheduledExecutorService;)Ljava/util/concurrent/ScheduledExecutorService;
+HSPLjava/util/concurrent/ForkJoinPool;->managedBlock(Ljava/util/concurrent/ForkJoinPool$ManagedBlocker;)V
+HSPLjava/util/concurrent/ForkJoinTask;-><init>()V
+HSPLjava/util/concurrent/FutureTask$WaitNode;-><init>()V
+HSPLjava/util/concurrent/FutureTask;-><init>(Ljava/lang/Runnable;Ljava/lang/Object;)V
+HSPLjava/util/concurrent/FutureTask;-><init>(Ljava/util/concurrent/Callable;)V
+HSPLjava/util/concurrent/FutureTask;->awaitDone(ZJ)I
+HSPLjava/util/concurrent/FutureTask;->cancel(Z)Z+]Ljava/lang/Thread;missing_types
+HSPLjava/util/concurrent/FutureTask;->done()V
+HSPLjava/util/concurrent/FutureTask;->finishCompletion()V+]Ljava/util/concurrent/FutureTask;missing_types
+HSPLjava/util/concurrent/FutureTask;->get()Ljava/lang/Object;
+HSPLjava/util/concurrent/FutureTask;->get(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;+]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$4;,Ljava/util/concurrent/TimeUnit$1;,Ljava/util/concurrent/TimeUnit$5;
+HSPLjava/util/concurrent/FutureTask;->handlePossibleCancellationInterrupt(I)V
+HSPLjava/util/concurrent/FutureTask;->isCancelled()Z
+HSPLjava/util/concurrent/FutureTask;->isDone()Z
+HSPLjava/util/concurrent/FutureTask;->removeWaiter(Ljava/util/concurrent/FutureTask$WaitNode;)V
+HSPLjava/util/concurrent/FutureTask;->report(I)Ljava/lang/Object;
+HSPLjava/util/concurrent/FutureTask;->run()V+]Ljava/util/concurrent/Callable;missing_types]Ljava/util/concurrent/FutureTask;missing_types
+HSPLjava/util/concurrent/FutureTask;->runAndReset()Z+]Ljava/util/concurrent/Callable;Ljava/util/concurrent/Executors$RunnableAdapter;]Ljava/util/concurrent/FutureTask;Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;
+HSPLjava/util/concurrent/FutureTask;->set(Ljava/lang/Object;)V
+HSPLjava/util/concurrent/FutureTask;->setException(Ljava/lang/Throwable;)V
+HSPLjava/util/concurrent/LinkedBlockingDeque$Node;-><init>(Ljava/lang/Object;)V
+HSPLjava/util/concurrent/LinkedBlockingDeque;-><init>()V
+HSPLjava/util/concurrent/LinkedBlockingDeque;-><init>(I)V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->add(Ljava/lang/Object;)Z+]Ljava/util/concurrent/LinkedBlockingDeque;Ljava/util/concurrent/LinkedBlockingDeque;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->addFirst(Ljava/lang/Object;)V+]Ljava/util/concurrent/LinkedBlockingDeque;Ljava/util/concurrent/LinkedBlockingDeque;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->addLast(Ljava/lang/Object;)V+]Ljava/util/concurrent/LinkedBlockingDeque;Ljava/util/concurrent/LinkedBlockingDeque;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->iterator()Ljava/util/Iterator;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->linkFirst(Ljava/util/concurrent/LinkedBlockingDeque$Node;)Z+]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->linkLast(Ljava/util/concurrent/LinkedBlockingDeque$Node;)Z+]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->offer(Ljava/lang/Object;)Z+]Ljava/util/concurrent/LinkedBlockingDeque;Ljava/util/concurrent/LinkedBlockingDeque;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->offerFirst(Ljava/lang/Object;)Z+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->offerLast(Ljava/lang/Object;)Z+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->peekFirst()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->poll()Ljava/lang/Object;+]Ljava/util/concurrent/LinkedBlockingDeque;Ljava/util/concurrent/LinkedBlockingDeque;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->poll(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;+]Ljava/util/concurrent/LinkedBlockingDeque;Ljava/util/concurrent/LinkedBlockingDeque;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->pollFirst()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->pollFirst(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$1;,Ljava/util/concurrent/TimeUnit$3;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->size()I+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->take()Ljava/lang/Object;+]Ljava/util/concurrent/LinkedBlockingDeque;missing_types
+HSPLjava/util/concurrent/LinkedBlockingDeque;->takeFirst()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/LinkedBlockingDeque;->unlinkFirst()Ljava/lang/Object;+]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/LinkedBlockingQueue$Node;-><init>(Ljava/lang/Object;)V
+HSPLjava/util/concurrent/LinkedBlockingQueue;-><init>()V
+HSPLjava/util/concurrent/LinkedBlockingQueue;-><init>(I)V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->clear()V+]Ljava/util/concurrent/LinkedBlockingQueue;Ljava/util/concurrent/LinkedBlockingQueue;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->dequeue()Ljava/lang/Object;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->drainTo(Ljava/util/Collection;)I+]Ljava/util/concurrent/LinkedBlockingQueue;Ljava/util/concurrent/LinkedBlockingQueue;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->drainTo(Ljava/util/Collection;I)I+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;]Ljava/util/Collection;Ljava/util/ArrayList;,Ljava/util/HashSet;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->enqueue(Ljava/util/concurrent/LinkedBlockingQueue$Node;)V
+HSPLjava/util/concurrent/LinkedBlockingQueue;->fullyLock()V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->fullyUnlock()V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->offer(Ljava/lang/Object;)Z+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->poll()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->poll(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$1;,Ljava/util/concurrent/TimeUnit$4;,Ljava/util/concurrent/TimeUnit$2;,Ljava/util/concurrent/TimeUnit$6;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->put(Ljava/lang/Object;)V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->signalNotEmpty()V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->signalNotFull()V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->size()I+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/LinkedBlockingQueue;->take()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/PriorityBlockingQueue;-><init>()V
+HSPLjava/util/concurrent/PriorityBlockingQueue;-><init>(ILjava/util/Comparator;)V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->add(Ljava/lang/Object;)Z+]Ljava/util/concurrent/PriorityBlockingQueue;Ljava/util/concurrent/PriorityBlockingQueue;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->dequeue()Ljava/lang/Object;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->indexOf(Ljava/lang/Object;)I+]Ljava/lang/Object;Ljava/lang/Integer;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->offer(Ljava/lang/Object;)Z+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->peek()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->poll()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->put(Ljava/lang/Object;)V+]Ljava/util/concurrent/PriorityBlockingQueue;Ljava/util/concurrent/PriorityBlockingQueue;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->remove(Ljava/lang/Object;)Z+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->removeAt(I)V
+HSPLjava/util/concurrent/PriorityBlockingQueue;->siftDownComparable(ILjava/lang/Object;[Ljava/lang/Object;I)V
+HSPLjava/util/concurrent/PriorityBlockingQueue;->siftDownUsingComparator(ILjava/lang/Object;[Ljava/lang/Object;ILjava/util/Comparator;)V+]Ljava/util/Comparator;Ljava/util/Collections$ReverseComparator;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->siftUpComparable(ILjava/lang/Object;[Ljava/lang/Object;)V
+HSPLjava/util/concurrent/PriorityBlockingQueue;->siftUpUsingComparator(ILjava/lang/Object;[Ljava/lang/Object;Ljava/util/Comparator;)V+]Ljava/util/Comparator;Ljava/util/Collections$ReverseComparator;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->size()I+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->take()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/PriorityBlockingQueue;->tryGrow([Ljava/lang/Object;I)V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;-><init>(Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;[Ljava/util/concurrent/RunnableScheduledFuture;)V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;->hasNext()Z
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;->next()Ljava/lang/Object;+]Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;->next()Ljava/lang/Runnable;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;->remove()V+]Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;-><init>()V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->add(Ljava/lang/Object;)Z+]Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->add(Ljava/lang/Runnable;)Z+]Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->drainTo(Ljava/util/Collection;)I+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->finishPoll(Ljava/util/concurrent/RunnableScheduledFuture;)Ljava/util/concurrent/RunnableScheduledFuture;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->grow()V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->indexOf(Ljava/lang/Object;)I
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->isEmpty()Z+]Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->iterator()Ljava/util/Iterator;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->offer(Ljava/lang/Runnable;)Z+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->peekExpired()Ljava/util/concurrent/RunnableScheduledFuture;+]Ljava/util/concurrent/RunnableScheduledFuture;Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->poll(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;+]Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->poll(JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/RunnableScheduledFuture;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/RunnableScheduledFuture;missing_types]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$1;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->remove(Ljava/lang/Object;)Z+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->setIndex(Ljava/util/concurrent/RunnableScheduledFuture;I)V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->siftDown(ILjava/util/concurrent/RunnableScheduledFuture;)V+]Ljava/util/concurrent/RunnableScheduledFuture;missing_types
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->siftUp(ILjava/util/concurrent/RunnableScheduledFuture;)V+]Ljava/util/concurrent/RunnableScheduledFuture;missing_types
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->size()I+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->take()Ljava/lang/Object;+]Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->take()Ljava/util/concurrent/RunnableScheduledFuture;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/RunnableScheduledFuture;missing_types]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->toArray()[Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;-><init>(Ljava/util/concurrent/ScheduledThreadPoolExecutor;Ljava/lang/Runnable;Ljava/lang/Object;JJ)V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;-><init>(Ljava/util/concurrent/ScheduledThreadPoolExecutor;Ljava/lang/Runnable;Ljava/lang/Object;JJJ)V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;-><init>(Ljava/util/concurrent/ScheduledThreadPoolExecutor;Ljava/util/concurrent/Callable;JJ)V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->cancel(Z)Z+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->compareTo(Ljava/lang/Object;)I+]Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->compareTo(Ljava/util/concurrent/Delayed;)I+]Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->getDelay(Ljava/util/concurrent/TimeUnit;)J+]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$1;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->isPeriodic()Z
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->run()V+]Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->setNextRunTime()V+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;-><init>(I)V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;-><init>(ILjava/util/concurrent/ThreadFactory;)V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;-><init>(ILjava/util/concurrent/ThreadFactory;Ljava/util/concurrent/RejectedExecutionHandler;)V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->canRunInCurrentRunState(Z)Z+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->decorateTask(Ljava/lang/Runnable;Ljava/util/concurrent/RunnableScheduledFuture;)Ljava/util/concurrent/RunnableScheduledFuture;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->decorateTask(Ljava/util/concurrent/Callable;Ljava/util/concurrent/RunnableScheduledFuture;)Ljava/util/concurrent/RunnableScheduledFuture;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->delayedExecute(Ljava/util/concurrent/RunnableScheduledFuture;)V+]Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types]Ljava/util/concurrent/RunnableScheduledFuture;Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->execute(Ljava/lang/Runnable;)V+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->getContinueExistingPeriodicTasksAfterShutdownPolicy()Z
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->getExecuteExistingDelayedTasksAfterShutdownPolicy()Z
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->onShutdown()V+]Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;]Ljava/util/concurrent/ScheduledThreadPoolExecutor;Ljava/util/concurrent/ScheduledThreadPoolExecutor;]Ljava/util/concurrent/RunnableScheduledFuture;Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->reExecutePeriodic(Ljava/util/concurrent/RunnableScheduledFuture;)V+]Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->schedule(Ljava/lang/Runnable;JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/ScheduledFuture;+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->schedule(Ljava/util/concurrent/Callable;JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/ScheduledFuture;+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->scheduleAtFixedRate(Ljava/lang/Runnable;JJLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/ScheduledFuture;+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$4;,Ljava/util/concurrent/TimeUnit$5;,Ljava/util/concurrent/TimeUnit$6;]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->scheduleWithFixedDelay(Ljava/lang/Runnable;JJLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/ScheduledFuture;+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;Ljava/util/concurrent/ScheduledThreadPoolExecutor;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->setRemoveOnCancelPolicy(Z)V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->shutdown()V
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->shutdownNow()Ljava/util/List;
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->submit(Ljava/lang/Runnable;)Ljava/util/concurrent/Future;+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->submit(Ljava/util/concurrent/Callable;)Ljava/util/concurrent/Future;+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->triggerTime(J)J
+HSPLjava/util/concurrent/ScheduledThreadPoolExecutor;->triggerTime(JLjava/util/concurrent/TimeUnit;)J+]Ljava/util/concurrent/ScheduledThreadPoolExecutor;missing_types]Ljava/util/concurrent/TimeUnit;megamorphic_types
+HSPLjava/util/concurrent/Semaphore$FairSync;-><init>(I)V
+HSPLjava/util/concurrent/Semaphore$FairSync;->tryAcquireShared(I)I+]Ljava/util/concurrent/Semaphore$FairSync;Ljava/util/concurrent/Semaphore$FairSync;
+HSPLjava/util/concurrent/Semaphore$NonfairSync;-><init>(I)V
+HSPLjava/util/concurrent/Semaphore$NonfairSync;->tryAcquireShared(I)I+]Ljava/util/concurrent/Semaphore$NonfairSync;Ljava/util/concurrent/Semaphore$NonfairSync;
+HSPLjava/util/concurrent/Semaphore$Sync;-><init>(I)V+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$NonfairSync;,Ljava/util/concurrent/Semaphore$FairSync;
+HSPLjava/util/concurrent/Semaphore$Sync;->getPermits()I+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$NonfairSync;,Ljava/util/concurrent/Semaphore$FairSync;
+HSPLjava/util/concurrent/Semaphore$Sync;->nonfairTryAcquireShared(I)I+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$NonfairSync;,Ljava/util/concurrent/Semaphore$FairSync;
+HSPLjava/util/concurrent/Semaphore$Sync;->tryReleaseShared(I)Z+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$FairSync;,Ljava/util/concurrent/Semaphore$NonfairSync;
+HSPLjava/util/concurrent/Semaphore;-><init>(I)V
+HSPLjava/util/concurrent/Semaphore;-><init>(IZ)V
+HSPLjava/util/concurrent/Semaphore;->acquire()V+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$NonfairSync;,Ljava/util/concurrent/Semaphore$FairSync;
+HSPLjava/util/concurrent/Semaphore;->acquireUninterruptibly()V+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$NonfairSync;,Ljava/util/concurrent/Semaphore$FairSync;
+HSPLjava/util/concurrent/Semaphore;->availablePermits()I+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$NonfairSync;,Ljava/util/concurrent/Semaphore$FairSync;
+HSPLjava/util/concurrent/Semaphore;->release()V+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$FairSync;,Ljava/util/concurrent/Semaphore$NonfairSync;
+HSPLjava/util/concurrent/Semaphore;->release(I)V+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$NonfairSync;
+HSPLjava/util/concurrent/Semaphore;->tryAcquire()Z+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$NonfairSync;
+HSPLjava/util/concurrent/Semaphore;->tryAcquire(IJLjava/util/concurrent/TimeUnit;)Z+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$FairSync;,Ljava/util/concurrent/Semaphore$NonfairSync;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$4;
+HSPLjava/util/concurrent/Semaphore;->tryAcquire(JLjava/util/concurrent/TimeUnit;)Z+]Ljava/util/concurrent/Semaphore$Sync;Ljava/util/concurrent/Semaphore$NonfairSync;,Ljava/util/concurrent/Semaphore$FairSync;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack$SNode;-><init>(Ljava/lang/Object;)V
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack$SNode;->casNext(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;)Z
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack$SNode;->isCancelled()Z
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack$SNode;->tryCancel()V
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack$SNode;->tryMatch(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;)Z
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack;-><init>()V
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack;->awaitFulfill(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;ZJ)Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;+]Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;]Ljava/lang/Thread;missing_types]Ljava/util/concurrent/SynchronousQueue$TransferStack;Ljava/util/concurrent/SynchronousQueue$TransferStack;
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack;->casHead(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;)Z
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack;->clean(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;)V+]Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;]Ljava/util/concurrent/SynchronousQueue$TransferStack;Ljava/util/concurrent/SynchronousQueue$TransferStack;
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack;->isFulfilling(I)Z
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack;->shouldSpin(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;)Z
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack;->snode(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;Ljava/lang/Object;Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;I)Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;
+HSPLjava/util/concurrent/SynchronousQueue$TransferStack;->transfer(Ljava/lang/Object;ZJ)Ljava/lang/Object;+]Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;]Ljava/util/concurrent/SynchronousQueue$TransferStack;Ljava/util/concurrent/SynchronousQueue$TransferStack;
+HSPLjava/util/concurrent/SynchronousQueue$Transferer;-><init>()V
+HSPLjava/util/concurrent/SynchronousQueue;-><init>()V
+HSPLjava/util/concurrent/SynchronousQueue;-><init>(Z)V
+HSPLjava/util/concurrent/SynchronousQueue;->isEmpty()Z
+HSPLjava/util/concurrent/SynchronousQueue;->offer(Ljava/lang/Object;)Z+]Ljava/util/concurrent/SynchronousQueue$Transferer;Ljava/util/concurrent/SynchronousQueue$TransferStack;,Ljava/util/concurrent/SynchronousQueue$TransferQueue;
+HSPLjava/util/concurrent/SynchronousQueue;->poll(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;+]Ljava/util/concurrent/SynchronousQueue$Transferer;Ljava/util/concurrent/SynchronousQueue$TransferStack;,Ljava/util/concurrent/SynchronousQueue$TransferQueue;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$1;
+HSPLjava/util/concurrent/SynchronousQueue;->take()Ljava/lang/Object;+]Ljava/util/concurrent/SynchronousQueue$Transferer;Ljava/util/concurrent/SynchronousQueue$TransferStack;
+HSPLjava/util/concurrent/ThreadLocalRandom;->current()Ljava/util/concurrent/ThreadLocalRandom;
+HSPLjava/util/concurrent/ThreadLocalRandom;->getProbe()I
+HSPLjava/util/concurrent/ThreadLocalRandom;->localInit()V
+HSPLjava/util/concurrent/ThreadLocalRandom;->mix32(J)I
+HSPLjava/util/concurrent/ThreadLocalRandom;->mix64(J)J
+HSPLjava/util/concurrent/ThreadLocalRandom;->nextInt()I+]Ljava/util/concurrent/ThreadLocalRandom;Ljava/util/concurrent/ThreadLocalRandom;
+HSPLjava/util/concurrent/ThreadLocalRandom;->nextSecondarySeed()I+]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/concurrent/ThreadLocalRandom;->nextSeed()J
+HSPLjava/util/concurrent/ThreadPoolExecutor$DiscardPolicy;-><init>()V
+HSPLjava/util/concurrent/ThreadPoolExecutor$Worker;-><init>(Ljava/util/concurrent/ThreadPoolExecutor;Ljava/lang/Runnable;)V+]Ljava/util/concurrent/ThreadPoolExecutor;missing_types]Ljava/util/concurrent/ThreadFactory;missing_types]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+HSPLjava/util/concurrent/ThreadPoolExecutor$Worker;->interruptIfStarted()V+]Ljava/lang/Thread;Ljava/lang/Thread;]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+HSPLjava/util/concurrent/ThreadPoolExecutor$Worker;->isHeldExclusively()Z+]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+HSPLjava/util/concurrent/ThreadPoolExecutor$Worker;->isLocked()Z+]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+HSPLjava/util/concurrent/ThreadPoolExecutor$Worker;->lock()V+]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+HSPLjava/util/concurrent/ThreadPoolExecutor$Worker;->run()V+]Ljava/util/concurrent/ThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ThreadPoolExecutor$Worker;->tryAcquire(I)Z+]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+HSPLjava/util/concurrent/ThreadPoolExecutor$Worker;->tryLock()Z+]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+HSPLjava/util/concurrent/ThreadPoolExecutor$Worker;->tryRelease(I)Z+]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+HSPLjava/util/concurrent/ThreadPoolExecutor$Worker;->unlock()V+]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+HSPLjava/util/concurrent/ThreadPoolExecutor;-><init>(IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;)V
+HSPLjava/util/concurrent/ThreadPoolExecutor;-><init>(IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/RejectedExecutionHandler;)V
+HSPLjava/util/concurrent/ThreadPoolExecutor;-><init>(IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/ThreadFactory;)V
+HSPLjava/util/concurrent/ThreadPoolExecutor;-><init>(IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/ThreadFactory;Ljava/util/concurrent/RejectedExecutionHandler;)V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$4;,Ljava/util/concurrent/TimeUnit$1;,Ljava/util/concurrent/TimeUnit$5;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->addWorker(Ljava/lang/Runnable;Z)Z+]Ljava/lang/Thread;missing_types]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/HashSet;Ljava/util/HashSet;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;]Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/LinkedBlockingQueue;,Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;,Ljava/util/concurrent/SynchronousQueue;,Ljava/util/concurrent/PriorityBlockingQueue;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->advanceRunState(I)V+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->afterExecute(Ljava/lang/Runnable;Ljava/lang/Throwable;)V
+HSPLjava/util/concurrent/ThreadPoolExecutor;->allowCoreThreadTimeOut(Z)V
+HSPLjava/util/concurrent/ThreadPoolExecutor;->awaitTermination(JLjava/util/concurrent/TimeUnit;)Z+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$4;,Ljava/util/concurrent/TimeUnit$3;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->beforeExecute(Ljava/lang/Thread;Ljava/lang/Runnable;)V
+HSPLjava/util/concurrent/ThreadPoolExecutor;->checkShutdownAccess()V
+HSPLjava/util/concurrent/ThreadPoolExecutor;->compareAndDecrementWorkerCount(I)Z+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->compareAndIncrementWorkerCount(I)Z+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->ctlOf(II)I
+HSPLjava/util/concurrent/ThreadPoolExecutor;->decrementWorkerCount()V+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->drainQueue()Ljava/util/List;+]Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;,Ljava/util/concurrent/SynchronousQueue;,Ljava/util/concurrent/LinkedBlockingQueue;]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->ensurePrestart()V+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->execute(Ljava/lang/Runnable;)V+]Ljava/util/concurrent/BlockingQueue;megamorphic_types]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;]Ljava/util/concurrent/ThreadPoolExecutor;Ljava/util/concurrent/ThreadPoolExecutor;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->finalize()V+]Ljava/util/concurrent/ThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ThreadPoolExecutor;->getMaximumPoolSize()I
+HSPLjava/util/concurrent/ThreadPoolExecutor;->getQueue()Ljava/util/concurrent/BlockingQueue;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->getRejectedExecutionHandler()Ljava/util/concurrent/RejectedExecutionHandler;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->getTask()Ljava/lang/Runnable;+]Ljava/util/concurrent/BlockingQueue;megamorphic_types]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->getThreadFactory()Ljava/util/concurrent/ThreadFactory;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->interruptIdleWorkers()V
+HSPLjava/util/concurrent/ThreadPoolExecutor;->interruptIdleWorkers(Z)V+]Ljava/lang/Thread;missing_types]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/HashSet;Ljava/util/HashSet;]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->interruptWorkers()V+]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/HashSet;Ljava/util/HashSet;]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->isRunning(I)Z
+HSPLjava/util/concurrent/ThreadPoolExecutor;->isRunningOrShutdown(Z)Z+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->isShutdown()Z+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->isTerminated()Z+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->onShutdown()V
+HSPLjava/util/concurrent/ThreadPoolExecutor;->prestartAllCoreThreads()I
+HSPLjava/util/concurrent/ThreadPoolExecutor;->prestartCoreThread()Z+]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->processWorkerExit(Ljava/util/concurrent/ThreadPoolExecutor$Worker;Z)V+]Ljava/util/concurrent/BlockingQueue;megamorphic_types]Ljava/util/concurrent/ThreadPoolExecutor;missing_types]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/HashSet;Ljava/util/HashSet;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->purge()V+]Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;]Ljava/util/concurrent/ThreadPoolExecutor;Ljava/util/concurrent/ScheduledThreadPoolExecutor;]Ljava/util/Iterator;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;]Ljava/util/concurrent/Future;Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->remove(Ljava/lang/Runnable;)Z+]Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;,Ljava/util/concurrent/LinkedBlockingQueue;]Ljava/util/concurrent/ThreadPoolExecutor;missing_types
+HSPLjava/util/concurrent/ThreadPoolExecutor;->runStateAtLeast(II)Z
+HSPLjava/util/concurrent/ThreadPoolExecutor;->runStateLessThan(II)Z
+HSPLjava/util/concurrent/ThreadPoolExecutor;->runStateOf(I)I
+HSPLjava/util/concurrent/ThreadPoolExecutor;->runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V+]Ljava/util/concurrent/ThreadPoolExecutor;missing_types]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;]Ljava/lang/Runnable;megamorphic_types]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;]Ljava/lang/Thread;Ljava/lang/Thread;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->setKeepAliveTime(JLjava/util/concurrent/TimeUnit;)V+]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$4;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->setMaximumPoolSize(I)V
+HSPLjava/util/concurrent/ThreadPoolExecutor;->setRejectedExecutionHandler(Ljava/util/concurrent/RejectedExecutionHandler;)V
+HSPLjava/util/concurrent/ThreadPoolExecutor;->setThreadFactory(Ljava/util/concurrent/ThreadFactory;)V
+HSPLjava/util/concurrent/ThreadPoolExecutor;->shutdown()V+]Ljava/util/concurrent/ThreadPoolExecutor;missing_types]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->shutdownNow()Ljava/util/List;+]Ljava/util/concurrent/ThreadPoolExecutor;missing_types]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->terminated()V
+HSPLjava/util/concurrent/ThreadPoolExecutor;->toString()Ljava/lang/String;+]Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/LinkedBlockingQueue;,Ljava/util/concurrent/SynchronousQueue;,Ljava/util/concurrent/ArrayBlockingQueue;,Ljava/util/concurrent/DelayQueue;,Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/HashSet;Ljava/util/HashSet;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;]Ljava/util/concurrent/ThreadPoolExecutor$Worker;Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->tryTerminate()V+]Ljava/util/concurrent/BlockingQueue;megamorphic_types]Ljava/util/concurrent/ThreadPoolExecutor;missing_types]Ljava/util/concurrent/locks/ReentrantLock;Ljava/util/concurrent/locks/ReentrantLock;]Ljava/util/concurrent/locks/Condition;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;]Ljava/util/concurrent/atomic/AtomicInteger;Ljava/util/concurrent/atomic/AtomicInteger;
+HSPLjava/util/concurrent/ThreadPoolExecutor;->workerCountOf(I)I
+HSPLjava/util/concurrent/TimeUnit$1;->convert(JLjava/util/concurrent/TimeUnit;)J+]Ljava/util/concurrent/TimeUnit;megamorphic_types
+HSPLjava/util/concurrent/TimeUnit$1;->excessNanos(JJ)I
+HSPLjava/util/concurrent/TimeUnit$1;->toDays(J)J
+HSPLjava/util/concurrent/TimeUnit$1;->toHours(J)J
+HSPLjava/util/concurrent/TimeUnit$1;->toMicros(J)J
+HSPLjava/util/concurrent/TimeUnit$1;->toMillis(J)J
+HSPLjava/util/concurrent/TimeUnit$1;->toMinutes(J)J
+HSPLjava/util/concurrent/TimeUnit$1;->toNanos(J)J
+HSPLjava/util/concurrent/TimeUnit$1;->toSeconds(J)J
+HSPLjava/util/concurrent/TimeUnit$2;->convert(JLjava/util/concurrent/TimeUnit;)J+]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$1;,Ljava/util/concurrent/TimeUnit$4;,Ljava/util/concurrent/TimeUnit$2;
+HSPLjava/util/concurrent/TimeUnit$2;->toMicros(J)J
+HSPLjava/util/concurrent/TimeUnit$2;->toMillis(J)J
+HSPLjava/util/concurrent/TimeUnit$2;->toNanos(J)J
+HSPLjava/util/concurrent/TimeUnit$2;->toSeconds(J)J
+HSPLjava/util/concurrent/TimeUnit$3;->convert(JLjava/util/concurrent/TimeUnit;)J+]Ljava/util/concurrent/TimeUnit;megamorphic_types
+HSPLjava/util/concurrent/TimeUnit$3;->excessNanos(JJ)I
+HSPLjava/util/concurrent/TimeUnit$3;->toDays(J)J
+HSPLjava/util/concurrent/TimeUnit$3;->toHours(J)J
+HSPLjava/util/concurrent/TimeUnit$3;->toMicros(J)J
+HSPLjava/util/concurrent/TimeUnit$3;->toMillis(J)J
+HSPLjava/util/concurrent/TimeUnit$3;->toMinutes(J)J
+HSPLjava/util/concurrent/TimeUnit$3;->toNanos(J)J
+HSPLjava/util/concurrent/TimeUnit$3;->toSeconds(J)J
+HSPLjava/util/concurrent/TimeUnit$4;->convert(JLjava/util/concurrent/TimeUnit;)J+]Ljava/util/concurrent/TimeUnit;megamorphic_types
+HSPLjava/util/concurrent/TimeUnit$4;->toMicros(J)J
+HSPLjava/util/concurrent/TimeUnit$4;->toMillis(J)J
+HSPLjava/util/concurrent/TimeUnit$4;->toMinutes(J)J
+HSPLjava/util/concurrent/TimeUnit$4;->toNanos(J)J
+HSPLjava/util/concurrent/TimeUnit$4;->toSeconds(J)J
+HSPLjava/util/concurrent/TimeUnit$5;->convert(JLjava/util/concurrent/TimeUnit;)J+]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$4;,Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$6;,Ljava/util/concurrent/TimeUnit$1;
+HSPLjava/util/concurrent/TimeUnit$5;->toMillis(J)J
+HSPLjava/util/concurrent/TimeUnit$5;->toNanos(J)J
+HSPLjava/util/concurrent/TimeUnit$5;->toSeconds(J)J
+HSPLjava/util/concurrent/TimeUnit$6;->convert(JLjava/util/concurrent/TimeUnit;)J+]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$1;,Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$4;
+HSPLjava/util/concurrent/TimeUnit$6;->toMicros(J)J
+HSPLjava/util/concurrent/TimeUnit$6;->toMillis(J)J
+HSPLjava/util/concurrent/TimeUnit$6;->toMinutes(J)J
+HSPLjava/util/concurrent/TimeUnit$6;->toNanos(J)J
+HSPLjava/util/concurrent/TimeUnit$6;->toSeconds(J)J
+HSPLjava/util/concurrent/TimeUnit$7;->convert(JLjava/util/concurrent/TimeUnit;)J+]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$1;,Ljava/util/concurrent/TimeUnit$3;
+HSPLjava/util/concurrent/TimeUnit$7;->toHours(J)J
+HSPLjava/util/concurrent/TimeUnit$7;->toMillis(J)J
+HSPLjava/util/concurrent/TimeUnit$7;->toMinutes(J)J
+HSPLjava/util/concurrent/TimeUnit$7;->toNanos(J)J
+HSPLjava/util/concurrent/TimeUnit$7;->toSeconds(J)J
+HSPLjava/util/concurrent/TimeUnit;->sleep(J)V+]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$4;,Ljava/util/concurrent/TimeUnit$1;
+HSPLjava/util/concurrent/TimeUnit;->values()[Ljava/util/concurrent/TimeUnit;
+HSPLjava/util/concurrent/TimeUnit;->x(JJJ)J
+HSPLjava/util/concurrent/TimeoutException;-><init>()V
+HSPLjava/util/concurrent/TimeoutException;-><init>(Ljava/lang/String;)V
+HSPLjava/util/concurrent/atomic/AtomicBoolean;-><init>()V
+HSPLjava/util/concurrent/atomic/AtomicBoolean;-><init>(Z)V
+HSPLjava/util/concurrent/atomic/AtomicBoolean;->compareAndSet(ZZ)Z
+HSPLjava/util/concurrent/atomic/AtomicBoolean;->get()Z
+HSPLjava/util/concurrent/atomic/AtomicBoolean;->getAndSet(Z)Z+]Ljava/util/concurrent/atomic/AtomicBoolean;Ljava/util/concurrent/atomic/AtomicBoolean;
+HSPLjava/util/concurrent/atomic/AtomicBoolean;->lazySet(Z)V
+HSPLjava/util/concurrent/atomic/AtomicBoolean;->set(Z)V
+HSPLjava/util/concurrent/atomic/AtomicBoolean;->toString()Ljava/lang/String;+]Ljava/util/concurrent/atomic/AtomicBoolean;Ljava/util/concurrent/atomic/AtomicBoolean;
+HSPLjava/util/concurrent/atomic/AtomicInteger;-><init>()V
+HSPLjava/util/concurrent/atomic/AtomicInteger;-><init>(I)V
+HSPLjava/util/concurrent/atomic/AtomicInteger;->addAndGet(I)I+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicInteger;->compareAndSet(II)Z
+HSPLjava/util/concurrent/atomic/AtomicInteger;->decrementAndGet()I+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicInteger;->get()I
+HSPLjava/util/concurrent/atomic/AtomicInteger;->getAndAdd(I)I+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicInteger;->getAndDecrement()I+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicInteger;->getAndIncrement()I+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicInteger;->getAndSet(I)I+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicInteger;->incrementAndGet()I+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicInteger;->lazySet(I)V
+HSPLjava/util/concurrent/atomic/AtomicInteger;->set(I)V
+HSPLjava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;-><init>(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)V
+HSPLjava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->accessCheck(Ljava/lang/Object;)V+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->compareAndSet(Ljava/lang/Object;II)Z
+HSPLjava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->decrementAndGet(Ljava/lang/Object;)I+]Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;
+HSPLjava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->getAndAdd(Ljava/lang/Object;I)I+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->incrementAndGet(Ljava/lang/Object;)I+]Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;
+HSPLjava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->set(Ljava/lang/Object;I)V
+HSPLjava/util/concurrent/atomic/AtomicIntegerFieldUpdater;-><init>()V
+HSPLjava/util/concurrent/atomic/AtomicIntegerFieldUpdater;->newUpdater(Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater;
+HSPLjava/util/concurrent/atomic/AtomicLong;-><init>()V
+HSPLjava/util/concurrent/atomic/AtomicLong;-><init>(J)V
+HSPLjava/util/concurrent/atomic/AtomicLong;->addAndGet(J)J+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicLong;->compareAndSet(JJ)Z+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicLong;->decrementAndGet()J+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicLong;->get()J
+HSPLjava/util/concurrent/atomic/AtomicLong;->getAndAdd(J)J+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicLong;->getAndIncrement()J+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicLong;->getAndSet(J)J+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicLong;->incrementAndGet()J+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicLong;->lazySet(J)V
+HSPLjava/util/concurrent/atomic/AtomicLong;->set(J)V
+HSPLjava/util/concurrent/atomic/AtomicLong;->toString()Ljava/lang/String;+]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;-><init>(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)V
+HSPLjava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->accessCheck(Ljava/lang/Object;)V+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->addAndGet(Ljava/lang/Object;J)J+]Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;
+HSPLjava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->compareAndSet(Ljava/lang/Object;JJ)Z+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->getAndAdd(Ljava/lang/Object;J)J+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->incrementAndGet(Ljava/lang/Object;)J+]Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;
+HSPLjava/util/concurrent/atomic/AtomicLongFieldUpdater;-><init>()V
+HSPLjava/util/concurrent/atomic/AtomicLongFieldUpdater;->newUpdater(Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicLongFieldUpdater;
+HSPLjava/util/concurrent/atomic/AtomicReference;-><init>()V
+HSPLjava/util/concurrent/atomic/AtomicReference;-><init>(Ljava/lang/Object;)V
+HSPLjava/util/concurrent/atomic/AtomicReference;->compareAndSet(Ljava/lang/Object;Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/atomic/AtomicReference;->get()Ljava/lang/Object;
+HSPLjava/util/concurrent/atomic/AtomicReference;->getAndSet(Ljava/lang/Object;)Ljava/lang/Object;+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicReference;->lazySet(Ljava/lang/Object;)V
+HSPLjava/util/concurrent/atomic/AtomicReference;->set(Ljava/lang/Object;)V
+HSPLjava/util/concurrent/atomic/AtomicReference;->updateAndGet(Ljava/util/function/UnaryOperator;)Ljava/lang/Object;+]Ljava/util/function/UnaryOperator;missing_types]Ljava/util/concurrent/atomic/AtomicReference;Ljava/util/concurrent/atomic/AtomicReference;
+HSPLjava/util/concurrent/atomic/AtomicReferenceArray;-><init>(I)V
+HSPLjava/util/concurrent/atomic/AtomicReferenceArray;->byteOffset(I)J
+HSPLjava/util/concurrent/atomic/AtomicReferenceArray;->checkedByteOffset(I)J
+HSPLjava/util/concurrent/atomic/AtomicReferenceArray;->compareAndSet(ILjava/lang/Object;Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/atomic/AtomicReferenceArray;->compareAndSetRaw(JLjava/lang/Object;Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/atomic/AtomicReferenceArray;->get(I)Ljava/lang/Object;
+HSPLjava/util/concurrent/atomic/AtomicReferenceArray;->getRaw(J)Ljava/lang/Object;
+HSPLjava/util/concurrent/atomic/AtomicReferenceArray;->lazySet(ILjava/lang/Object;)V
+HSPLjava/util/concurrent/atomic/AtomicReferenceArray;->length()I
+HSPLjava/util/concurrent/atomic/AtomicReferenceArray;->set(ILjava/lang/Object;)V
+HSPLjava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;-><init>(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)V
+HSPLjava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->accessCheck(Ljava/lang/Object;)V+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->compareAndSet(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z
+HSPLjava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->getAndSet(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->lazySet(Ljava/lang/Object;Ljava/lang/Object;)V
+HSPLjava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->valueCheck(Ljava/lang/Object;)V+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLjava/util/concurrent/atomic/AtomicReferenceFieldUpdater;-><init>()V
+HSPLjava/util/concurrent/atomic/AtomicReferenceFieldUpdater;->newUpdater(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;
+HSPLjava/util/concurrent/atomic/LongAdder;-><init>()V
+HSPLjava/util/concurrent/atomic/LongAdder;->add(J)V+]Ljava/util/concurrent/atomic/LongAdder;Ljava/util/concurrent/atomic/LongAdder;]Ljava/util/concurrent/atomic/Striped64$Cell;Ljava/util/concurrent/atomic/Striped64$Cell;
+HSPLjava/util/concurrent/atomic/Striped64$Cell;-><clinit>()V
+HSPLjava/util/concurrent/atomic/Striped64$Cell;-><init>(J)V
+HSPLjava/util/concurrent/atomic/Striped64;-><init>()V
+HSPLjava/util/concurrent/atomic/Striped64;->casBase(JJ)Z+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/atomic/Striped64;->casCellsBusy()Z
+HSPLjava/util/concurrent/atomic/Striped64;->getProbe()I
+HSPLjava/util/concurrent/atomic/Striped64;->longAccumulate(JLjava/util/function/LongBinaryOperator;Z)V
+HSPLjava/util/concurrent/locks/AbstractOwnableSynchronizer;-><init>()V
+HSPLjava/util/concurrent/locks/AbstractOwnableSynchronizer;->getExclusiveOwnerThread()Ljava/lang/Thread;
+HSPLjava/util/concurrent/locks/AbstractOwnableSynchronizer;->setExclusiveOwnerThread(Ljava/lang/Thread;)V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;-><init>(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;)V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->addConditionWaiter()Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->await()V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->awaitNanos(J)J+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->checkInterruptWhileWaiting(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)I+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->doSignal(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->doSignalAll(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->reportInterruptAfterWait(I)V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->signal()V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->signalAll()V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->unlinkCancelledWaiters()V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;-><init>()V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;-><init>(I)V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;-><init>(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->compareAndSetNext(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->compareAndSetWaitStatus(II)Z
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->isShared()Z
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->predecessor()Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;-><init>()V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->acquire(I)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;megamorphic_types
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->acquireInterruptibly(I)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->acquireQueued(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;I)Z+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;megamorphic_types]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->acquireShared(I)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;missing_types
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->acquireSharedInterruptibly(I)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;missing_types
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->addWaiter(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->apparentlyFirstQueuedIsExclusive()Z+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->cancelAcquire(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->compareAndSetState(II)Z
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->compareAndSetTail(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->doAcquireInterruptibly(I)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->doAcquireShared(I)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/Semaphore$NonfairSync;,Ljava/util/concurrent/Semaphore$FairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->doAcquireSharedInterruptibly(I)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;missing_types]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->doAcquireSharedNanos(IJ)Z+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/CountDownLatch$Sync;,Ljava/util/concurrent/Semaphore$FairSync;,Ljava/util/concurrent/Semaphore$NonfairSync;]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->doReleaseShared()V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->enq(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->findNodeFromTail(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->fullyRelease(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)I+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->getState()I
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->hasQueuedPredecessors()Z
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->initializeSyncQueue()V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->isOnSyncQueue(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->parkAndCheckInterrupt()Z
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->release(I)Z+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;megamorphic_types
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->releaseShared(I)Z+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;megamorphic_types
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->selfInterrupt()V+]Ljava/lang/Thread;Ljava/lang/Thread;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->setHead(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->setHeadAndPropagate(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;I)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->setState(I)V
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->shouldParkAfterFailedAcquire(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->transferAfterCancelledWait(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->transferForSignal(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->tryAcquireSharedNanos(IJ)Z+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;Ljava/util/concurrent/CountDownLatch$Sync;,Ljava/util/concurrent/Semaphore$FairSync;,Ljava/util/concurrent/Semaphore$NonfairSync;
+HSPLjava/util/concurrent/locks/AbstractQueuedSynchronizer;->unparkSuccessor(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V+]Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+HSPLjava/util/concurrent/locks/LockSupport;->park(Ljava/lang/Object;)V+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/locks/LockSupport;->parkNanos(J)V+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/locks/LockSupport;->parkNanos(Ljava/lang/Object;J)V+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/locks/LockSupport;->setBlocker(Ljava/lang/Thread;Ljava/lang/Object;)V
+HSPLjava/util/concurrent/locks/LockSupport;->unpark(Ljava/lang/Thread;)V+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLjava/util/concurrent/locks/ReentrantLock$FairSync;-><init>()V
+HSPLjava/util/concurrent/locks/ReentrantLock$FairSync;->lock()V+]Ljava/util/concurrent/locks/ReentrantLock$FairSync;Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock$FairSync;->tryAcquire(I)Z+]Ljava/util/concurrent/locks/ReentrantLock$FairSync;Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock$NonfairSync;-><init>()V
+HSPLjava/util/concurrent/locks/ReentrantLock$NonfairSync;->lock()V+]Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock$NonfairSync;->tryAcquire(I)Z+]Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock$Sync;-><init>()V
+HSPLjava/util/concurrent/locks/ReentrantLock$Sync;->isHeldExclusively()Z+]Ljava/util/concurrent/locks/ReentrantLock$Sync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock$Sync;->newCondition()Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+HSPLjava/util/concurrent/locks/ReentrantLock$Sync;->nonfairTryAcquire(I)Z+]Ljava/util/concurrent/locks/ReentrantLock$Sync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock$Sync;->tryRelease(I)Z+]Ljava/util/concurrent/locks/ReentrantLock$Sync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock;-><init>()V
+HSPLjava/util/concurrent/locks/ReentrantLock;-><init>(Z)V
+HSPLjava/util/concurrent/locks/ReentrantLock;->isHeldByCurrentThread()Z+]Ljava/util/concurrent/locks/ReentrantLock$Sync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock;->lock()V+]Ljava/util/concurrent/locks/ReentrantLock$Sync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock;->lockInterruptibly()V+]Ljava/util/concurrent/locks/ReentrantLock$Sync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock;->newCondition()Ljava/util/concurrent/locks/Condition;+]Ljava/util/concurrent/locks/ReentrantLock$Sync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock;->tryLock()Z+]Ljava/util/concurrent/locks/ReentrantLock$Sync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;
+HSPLjava/util/concurrent/locks/ReentrantLock;->unlock()V+]Ljava/util/concurrent/locks/ReentrantLock$Sync;Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;-><init>()V
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;->readerShouldBlock()Z+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;->writerShouldBlock()Z+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;-><init>()V
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;->readerShouldBlock()Z+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;->writerShouldBlock()Z
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$ReadLock;-><init>(Ljava/util/concurrent/locks/ReentrantReadWriteLock;)V
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$ReadLock;->lock()V+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$ReadLock;->unlock()V+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync$HoldCounter;-><init>()V
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;-><init>()V
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;->initialValue()Ljava/lang/Object;+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;->initialValue()Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$HoldCounter;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync;-><init>()V+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->exclusiveCount(I)I
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->fullTryAcquireShared(Ljava/lang/Thread;)I+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->isHeldExclusively()Z+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->sharedCount(I)I
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->tryAcquire(I)Z+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->tryAcquireShared(I)I+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->tryRelease(I)Z+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->tryReleaseShared(I)Z+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$WriteLock;-><init>(Ljava/util/concurrent/locks/ReentrantReadWriteLock;)V
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$WriteLock;->lock()V+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock$WriteLock;->unlock()V+]Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;,Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock;-><init>()V
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock;-><init>(Z)V
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock;->getThreadId(Ljava/lang/Thread;)J
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock;->readLock()Ljava/util/concurrent/locks/Lock;+]Ljava/util/concurrent/locks/ReentrantReadWriteLock;Ljava/util/concurrent/locks/ReentrantReadWriteLock;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock;->readLock()Ljava/util/concurrent/locks/ReentrantReadWriteLock$ReadLock;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock;->writeLock()Ljava/util/concurrent/locks/Lock;+]Ljava/util/concurrent/locks/ReentrantReadWriteLock;Ljava/util/concurrent/locks/ReentrantReadWriteLock;
+HSPLjava/util/concurrent/locks/ReentrantReadWriteLock;->writeLock()Ljava/util/concurrent/locks/ReentrantReadWriteLock$WriteLock;
+HSPLjava/util/function/BinaryOperator;->maxBy(Ljava/util/Comparator;)Ljava/util/function/BinaryOperator;
+HSPLjava/util/function/DoubleUnaryOperator;->andThen(Ljava/util/function/DoubleUnaryOperator;)Ljava/util/function/DoubleUnaryOperator;
+HSPLjava/util/function/Function$$ExternalSyntheticLambda2;-><clinit>()V
+HSPLjava/util/function/Function$$ExternalSyntheticLambda2;-><init>()V
+HSPLjava/util/function/Function$$ExternalSyntheticLambda2;->apply(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/function/Function;->identity()Ljava/util/function/Function;
+HSPLjava/util/function/Function;->lambda$identity$2(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLjava/util/jar/Attributes$Name;-><init>(Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/jar/Attributes$Name;->equals(Ljava/lang/Object;)Z+]Ljava/util/Comparator;Lsun/misc/ASCIICaseInsensitiveComparator;
+HSPLjava/util/jar/Attributes$Name;->hashCode()I
+HSPLjava/util/jar/Attributes$Name;->isAlpha(C)Z
+HSPLjava/util/jar/Attributes$Name;->isDigit(C)Z
+HSPLjava/util/jar/Attributes$Name;->isValid(C)Z
+HSPLjava/util/jar/Attributes$Name;->isValid(Ljava/lang/String;)Z
+HSPLjava/util/jar/Attributes$Name;->toString()Ljava/lang/String;
+HSPLjava/util/jar/Attributes;-><init>()V
+HSPLjava/util/jar/Attributes;-><init>(I)V
+HSPLjava/util/jar/Attributes;->entrySet()Ljava/util/Set;
+HSPLjava/util/jar/Attributes;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/util/jar/Attributes;->getValue(Ljava/util/jar/Attributes$Name;)Ljava/lang/String;
+HSPLjava/util/jar/Attributes;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/util/jar/Attributes;->putValue(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/jar/Attributes;Ljava/util/jar/Attributes;
+HSPLjava/util/jar/Attributes;->read(Ljava/util/jar/Manifest$FastInputStream;[B)V+]Ljava/util/jar/Attributes;Ljava/util/jar/Attributes;]Ljava/util/jar/Manifest$FastInputStream;Ljava/util/jar/Manifest$FastInputStream;
+HSPLjava/util/jar/Attributes;->size()I+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/util/jar/JarEntry;-><init>(Ljava/util/zip/ZipEntry;)V
+HSPLjava/util/jar/JarFile$JarFileEntry;-><init>(Ljava/util/jar/JarFile;Ljava/util/zip/ZipEntry;)V
+HSPLjava/util/jar/JarFile;-><init>(Ljava/io/File;ZI)V
+HSPLjava/util/jar/JarFile;-><init>(Ljava/lang/String;)V
+HSPLjava/util/jar/JarFile;->getBytes(Ljava/util/zip/ZipEntry;)[B
+HSPLjava/util/jar/JarFile;->getEntry(Ljava/lang/String;)Ljava/util/zip/ZipEntry;
+HSPLjava/util/jar/JarFile;->getInputStream(Ljava/util/zip/ZipEntry;)Ljava/io/InputStream;
+HSPLjava/util/jar/JarFile;->getJarEntry(Ljava/lang/String;)Ljava/util/jar/JarEntry;
+HSPLjava/util/jar/JarFile;->getManEntry()Ljava/util/jar/JarEntry;
+HSPLjava/util/jar/JarFile;->getManifest()Ljava/util/jar/Manifest;
+HSPLjava/util/jar/JarFile;->getManifestFromReference()Ljava/util/jar/Manifest;
+HSPLjava/util/jar/JarFile;->initializeVerifier()V+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/jar/JarVerifier;Ljava/util/jar/JarVerifier;]Ljava/util/jar/JarFile;Ljava/util/jar/JarFile;
+HSPLjava/util/jar/JarFile;->maybeInstantiateVerifier()V+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/jar/JarFile;Ljava/util/jar/JarFile;
+HSPLjava/util/jar/JarVerifier$3;-><init>(Ljava/util/jar/JarVerifier;)V
+HSPLjava/util/jar/JarVerifier$VerifierStream;-><init>(Ljava/util/jar/Manifest;Ljava/util/jar/JarEntry;Ljava/io/InputStream;Ljava/util/jar/JarVerifier;)V
+HSPLjava/util/jar/JarVerifier$VerifierStream;->available()I
+HSPLjava/util/jar/JarVerifier$VerifierStream;->close()V
+HSPLjava/util/jar/JarVerifier$VerifierStream;->read()I+]Ljava/io/InputStream;Ljava/util/zip/ZipFile$ZipFileInputStream;,Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;]Ljava/util/jar/JarVerifier;Ljava/util/jar/JarVerifier;
+HSPLjava/util/jar/JarVerifier$VerifierStream;->read([BII)I+]Ljava/io/InputStream;Ljava/util/zip/ZipFile$ZipFileInputStream;,Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;]Ljava/util/jar/JarVerifier;Ljava/util/jar/JarVerifier;
+HSPLjava/util/jar/JarVerifier;-><init>([B)V
+HSPLjava/util/jar/JarVerifier;->beginEntry(Ljava/util/jar/JarEntry;Lsun/security/util/ManifestEntryVerifier;)V
+HSPLjava/util/jar/JarVerifier;->doneWithMeta()V
+HSPLjava/util/jar/JarVerifier;->mapSignersToCertArray([Ljava/security/CodeSigner;)[Ljava/security/cert/Certificate;
+HSPLjava/util/jar/JarVerifier;->nothingToVerify()Z
+HSPLjava/util/jar/JarVerifier;->processEntry(Lsun/security/util/ManifestEntryVerifier;)V
+HSPLjava/util/jar/JarVerifier;->update(ILsun/security/util/ManifestEntryVerifier;)V+]Lsun/security/util/ManifestEntryVerifier;Lsun/security/util/ManifestEntryVerifier;
+HSPLjava/util/jar/JarVerifier;->update(I[BIILsun/security/util/ManifestEntryVerifier;)V+]Lsun/security/util/ManifestEntryVerifier;Lsun/security/util/ManifestEntryVerifier;]Ljava/io/ByteArrayOutputStream;Ljava/io/ByteArrayOutputStream;
+HSPLjava/util/jar/Manifest$FastInputStream;-><init>(Ljava/io/InputStream;)V
+HSPLjava/util/jar/Manifest$FastInputStream;-><init>(Ljava/io/InputStream;I)V
+HSPLjava/util/jar/Manifest$FastInputStream;->fill()V
+HSPLjava/util/jar/Manifest$FastInputStream;->peek()B
+HSPLjava/util/jar/Manifest$FastInputStream;->readLine([B)I+]Ljava/util/jar/Manifest$FastInputStream;Ljava/util/jar/Manifest$FastInputStream;
+HSPLjava/util/jar/Manifest$FastInputStream;->readLine([BII)I
+HSPLjava/util/jar/Manifest;-><init>()V
+HSPLjava/util/jar/Manifest;-><init>(Ljava/io/InputStream;)V
+HSPLjava/util/jar/Manifest;->getAttributes(Ljava/lang/String;)Ljava/util/jar/Attributes;+]Ljava/util/jar/Manifest;Ljava/util/jar/Manifest;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLjava/util/jar/Manifest;->getEntries()Ljava/util/Map;
+HSPLjava/util/jar/Manifest;->getMainAttributes()Ljava/util/jar/Attributes;
+HSPLjava/util/jar/Manifest;->parseName([BI)Ljava/lang/String;
+HSPLjava/util/jar/Manifest;->read(Ljava/io/InputStream;)V+]Ljava/util/jar/Attributes;Ljava/util/jar/Attributes;]Ljava/util/jar/Manifest;Ljava/util/jar/Manifest;]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/jar/Manifest$FastInputStream;Ljava/util/jar/Manifest$FastInputStream;
+HSPLjava/util/jar/Manifest;->toLower(I)I
+HSPLjava/util/logging/ErrorManager;-><init>()V
+HSPLjava/util/logging/FileHandler$1;-><init>(Ljava/util/logging/FileHandler;)V
+HSPLjava/util/logging/FileHandler$1;->run()Ljava/lang/Object;
+HSPLjava/util/logging/FileHandler$InitializationErrorManager;-><init>()V
+HSPLjava/util/logging/FileHandler$InitializationErrorManager;-><init>(Ljava/util/logging/FileHandler$1;)V
+HSPLjava/util/logging/FileHandler$MeteredStream;-><init>(Ljava/util/logging/FileHandler;Ljava/io/OutputStream;I)V
+HSPLjava/util/logging/FileHandler$MeteredStream;->close()V
+HSPLjava/util/logging/FileHandler$MeteredStream;->flush()V+]Ljava/io/OutputStream;Ljava/io/BufferedOutputStream;
+HSPLjava/util/logging/FileHandler$MeteredStream;->write([BII)V+]Ljava/io/OutputStream;Ljava/io/BufferedOutputStream;
+HSPLjava/util/logging/FileHandler;-><clinit>()V
+HSPLjava/util/logging/FileHandler;-><init>(Ljava/lang/String;IIZ)V
+HSPLjava/util/logging/FileHandler;->access$100(Ljava/util/logging/FileHandler;)V
+HSPLjava/util/logging/FileHandler;->configure()V
+HSPLjava/util/logging/FileHandler;->generate(Ljava/lang/String;II)Ljava/io/File;
+HSPLjava/util/logging/FileHandler;->isParentWritable(Ljava/nio/file/Path;)Z
+HSPLjava/util/logging/FileHandler;->open(Ljava/io/File;Z)V
+HSPLjava/util/logging/FileHandler;->openFiles()V
+HSPLjava/util/logging/FileHandler;->publish(Ljava/util/logging/LogRecord;)V+]Ljava/util/logging/FileHandler;Ljava/util/logging/FileHandler;
+HSPLjava/util/logging/FileHandler;->rotate()V
+HSPLjava/util/logging/Formatter;-><init>()V
+HSPLjava/util/logging/Formatter;->getHead(Ljava/util/logging/Handler;)Ljava/lang/String;
+HSPLjava/util/logging/Formatter;->getTail(Ljava/util/logging/Handler;)Ljava/lang/String;
+HSPLjava/util/logging/Handler;-><init>()V
+HSPLjava/util/logging/Handler;->checkPermission()V+]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/Handler;->getEncoding()Ljava/lang/String;
+HSPLjava/util/logging/Handler;->getFilter()Ljava/util/logging/Filter;
+HSPLjava/util/logging/Handler;->getFormatter()Ljava/util/logging/Formatter;
+HSPLjava/util/logging/Handler;->getLevel()Ljava/util/logging/Level;
+HSPLjava/util/logging/Handler;->isLoggable(Ljava/util/logging/LogRecord;)Z+]Ljava/util/logging/Handler;Ljava/util/logging/FileHandler;]Ljava/util/logging/Level;Ljava/util/logging/Level;]Ljava/util/logging/LogRecord;Ljava/util/logging/LogRecord;
+HSPLjava/util/logging/Handler;->setEncoding(Ljava/lang/String;)V
+HSPLjava/util/logging/Handler;->setErrorManager(Ljava/util/logging/ErrorManager;)V
+HSPLjava/util/logging/Handler;->setFilter(Ljava/util/logging/Filter;)V
+HSPLjava/util/logging/Handler;->setFormatter(Ljava/util/logging/Formatter;)V
+HSPLjava/util/logging/Handler;->setLevel(Ljava/util/logging/Level;)V
+HSPLjava/util/logging/Level;->equals(Ljava/lang/Object;)Z
+HSPLjava/util/logging/Level;->intValue()I
+HSPLjava/util/logging/LogManager$5;-><init>(Ljava/util/logging/LogManager;Ljava/lang/String;Ljava/util/logging/Logger;)V
+HSPLjava/util/logging/LogManager$5;->run()Ljava/lang/Object;
+HSPLjava/util/logging/LogManager$LogNode;-><init>(Ljava/util/logging/LogManager$LogNode;Ljava/util/logging/LogManager$LoggerContext;)V
+HSPLjava/util/logging/LogManager$LogNode;->walkAndSetParent(Ljava/util/logging/Logger;)V
+HSPLjava/util/logging/LogManager$LoggerContext$1;-><init>(Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/Logger;Ljava/util/logging/LogManager;Ljava/lang/String;)V
+HSPLjava/util/logging/LogManager$LoggerContext$1;->run()Ljava/lang/Object;+]Ljava/util/logging/LogManager$LoggerContext$1;Ljava/util/logging/LogManager$LoggerContext$1;
+HSPLjava/util/logging/LogManager$LoggerContext$1;->run()Ljava/lang/Void;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/LogManager$LoggerContext;->addLocalLogger(Ljava/util/logging/Logger;)Z+]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$SystemLoggerContext;,Ljava/util/logging/LogManager$LoggerContext;
+HSPLjava/util/logging/LogManager$LoggerContext;->addLocalLogger(Ljava/util/logging/Logger;Z)Z+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$SystemLoggerContext;,Ljava/util/logging/LogManager$LoggerContext;]Ljava/util/logging/LogManager$LogNode;Ljava/util/logging/LogManager$LogNode;]Ljava/util/Hashtable;Ljava/util/Hashtable;]Ljava/util/logging/Logger;Ljava/util/logging/Logger;]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;]Ljava/util/logging/LogManager$LoggerWeakRef;Ljava/util/logging/LogManager$LoggerWeakRef;
+HSPLjava/util/logging/LogManager$LoggerContext;->ensureAllDefaultLoggers(Ljava/util/logging/Logger;)V+]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$SystemLoggerContext;,Ljava/util/logging/LogManager$LoggerContext;]Ljava/util/logging/Logger;Ljava/util/logging/Logger;
+HSPLjava/util/logging/LogManager$LoggerContext;->ensureDefaultLogger(Ljava/util/logging/Logger;)V+]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$SystemLoggerContext;,Ljava/util/logging/LogManager$LoggerContext;]Ljava/util/Hashtable;Ljava/util/Hashtable;]Ljava/util/logging/Logger;Ljava/util/logging/LogManager$RootLogger;,Ljava/util/logging/Logger;
+HSPLjava/util/logging/LogManager$LoggerContext;->ensureInitialized()V+]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$LoggerContext;,Ljava/util/logging/LogManager$SystemLoggerContext;
+HSPLjava/util/logging/LogManager$LoggerContext;->findLogger(Ljava/lang/String;)Ljava/util/logging/Logger;+]Ljava/util/Hashtable;Ljava/util/Hashtable;]Ljava/util/logging/LogManager$LoggerWeakRef;Ljava/util/logging/LogManager$LoggerWeakRef;
+HSPLjava/util/logging/LogManager$LoggerContext;->getGlobalLogger()Ljava/util/logging/Logger;
+HSPLjava/util/logging/LogManager$LoggerContext;->getLoggerNames()Ljava/util/Enumeration;
+HSPLjava/util/logging/LogManager$LoggerContext;->getNode(Ljava/lang/String;)Ljava/util/logging/LogManager$LogNode;+]Ljava/util/HashMap;Ljava/util/HashMap;]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/logging/LogManager$LoggerContext;->getOwner()Ljava/util/logging/LogManager;
+HSPLjava/util/logging/LogManager$LoggerContext;->getRootLogger()Ljava/util/logging/Logger;+]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$LoggerContext;,Ljava/util/logging/LogManager$SystemLoggerContext;
+HSPLjava/util/logging/LogManager$LoggerContext;->processParentHandlers(Ljava/util/logging/Logger;Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$LoggerContext;,Ljava/util/logging/LogManager$SystemLoggerContext;]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/LogManager$LoggerContext;->removeLoggerRef(Ljava/lang/String;Ljava/util/logging/LogManager$LoggerWeakRef;)V+]Ljava/util/Hashtable;Ljava/util/Hashtable;
+HSPLjava/util/logging/LogManager$LoggerContext;->requiresDefaultLoggers()Z+]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$LoggerContext;,Ljava/util/logging/LogManager$SystemLoggerContext;]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/LogManager$LoggerWeakRef;-><init>(Ljava/util/logging/LogManager;Ljava/util/logging/Logger;)V+]Ljava/util/logging/Logger;Ljava/util/logging/Logger;
+HSPLjava/util/logging/LogManager$LoggerWeakRef;->dispose()V+]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$SystemLoggerContext;,Ljava/util/logging/LogManager$LoggerContext;]Ljava/lang/ref/WeakReference;Ljava/lang/ref/WeakReference;]Ljava/util/logging/Logger;Ljava/util/logging/LogManager$RootLogger;
+HSPLjava/util/logging/LogManager$LoggerWeakRef;->setNode(Ljava/util/logging/LogManager$LogNode;)V
+HSPLjava/util/logging/LogManager$LoggerWeakRef;->setParentRef(Ljava/lang/ref/WeakReference;)V
+HSPLjava/util/logging/LogManager$RootLogger;->accessCheckedHandlers()[Ljava/util/logging/Handler;
+HSPLjava/util/logging/LogManager$RootLogger;->addHandler(Ljava/util/logging/Handler;)V
+HSPLjava/util/logging/LogManager$SystemLoggerContext;->demandLogger(Ljava/lang/String;Ljava/lang/String;)Ljava/util/logging/Logger;+]Ljava/util/logging/LogManager$SystemLoggerContext;Ljava/util/logging/LogManager$SystemLoggerContext;
+HSPLjava/util/logging/LogManager;->access$1300(Ljava/util/logging/Logger;Ljava/util/logging/Logger;)V
+HSPLjava/util/logging/LogManager;->access$1400(Ljava/util/logging/LogManager;Ljava/lang/String;)[Ljava/lang/String;
+HSPLjava/util/logging/LogManager;->access$1500(Ljava/util/logging/LogManager;)Ljava/lang/ref/ReferenceQueue;
+HSPLjava/util/logging/LogManager;->access$1600(Ljava/util/logging/LogManager;)V
+HSPLjava/util/logging/LogManager;->access$200()Ljava/util/logging/LogManager;
+HSPLjava/util/logging/LogManager;->access$600(Ljava/util/logging/LogManager;)Ljava/util/logging/Logger;
+HSPLjava/util/logging/LogManager;->addLogger(Ljava/util/logging/Logger;)Z+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$LoggerContext;]Ljava/util/logging/Logger;Ljava/util/logging/Logger;]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/LogManager;->checkPermission()V
+HSPLjava/util/logging/LogManager;->contexts()Ljava/util/List;
+HSPLjava/util/logging/LogManager;->demandLogger(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)Ljava/util/logging/Logger;+]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/LogManager;->demandSystemLogger(Ljava/lang/String;Ljava/lang/String;)Ljava/util/logging/Logger;
+HSPLjava/util/logging/LogManager;->doSetParent(Ljava/util/logging/Logger;Ljava/util/logging/Logger;)V+]Ljava/util/logging/Logger;Ljava/util/logging/Logger;
+HSPLjava/util/logging/LogManager;->drainLoggerRefQueueBounded()V+]Ljava/lang/ref/ReferenceQueue;Ljava/lang/ref/ReferenceQueue;]Ljava/util/logging/LogManager$LoggerWeakRef;Ljava/util/logging/LogManager$LoggerWeakRef;
+HSPLjava/util/logging/LogManager;->ensureLogManagerInitialized()V
+HSPLjava/util/logging/LogManager;->getBooleanProperty(Ljava/lang/String;Z)Z+]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/LogManager;->getFilterProperty(Ljava/lang/String;Ljava/util/logging/Filter;)Ljava/util/logging/Filter;
+HSPLjava/util/logging/LogManager;->getFormatterProperty(Ljava/lang/String;Ljava/util/logging/Formatter;)Ljava/util/logging/Formatter;
+HSPLjava/util/logging/LogManager;->getIntProperty(Ljava/lang/String;I)I
+HSPLjava/util/logging/LogManager;->getLevelProperty(Ljava/lang/String;Ljava/util/logging/Level;)Ljava/util/logging/Level;+]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/LogManager;->getLogManager()Ljava/util/logging/LogManager;+]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/LogManager;->getLogger(Ljava/lang/String;)Ljava/util/logging/Logger;+]Ljava/util/logging/LogManager$LoggerContext;Ljava/util/logging/LogManager$LoggerContext;
+HSPLjava/util/logging/LogManager;->getProperty(Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Properties;Ljava/util/Properties;
+HSPLjava/util/logging/LogManager;->getStringProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/util/logging/LogManager;->getSystemContext()Ljava/util/logging/LogManager$LoggerContext;
+HSPLjava/util/logging/LogManager;->getUserContext()Ljava/util/logging/LogManager$LoggerContext;
+HSPLjava/util/logging/LogManager;->initializeGlobalHandlers()V
+HSPLjava/util/logging/LogManager;->loadLoggerHandlers(Ljava/util/logging/Logger;Ljava/lang/String;Ljava/lang/String;)V
+HSPLjava/util/logging/LogManager;->parseClassNames(Ljava/lang/String;)[Ljava/lang/String;
+HSPLjava/util/logging/LogManager;->reset()V
+HSPLjava/util/logging/LogManager;->resetLogger(Ljava/util/logging/Logger;)V
+HSPLjava/util/logging/LogRecord;-><init>(Ljava/util/logging/Level;Ljava/lang/String;)V+]Ljava/lang/Object;Ljava/util/logging/Level;]Ljava/util/concurrent/atomic/AtomicLong;Ljava/util/concurrent/atomic/AtomicLong;
+HSPLjava/util/logging/LogRecord;->defaultThreadID()I+]Ljava/lang/Thread;missing_types
+HSPLjava/util/logging/LogRecord;->getLevel()Ljava/util/logging/Level;
+HSPLjava/util/logging/LogRecord;->getLoggerName()Ljava/lang/String;
+HSPLjava/util/logging/LogRecord;->getMessage()Ljava/lang/String;
+HSPLjava/util/logging/LogRecord;->getThrown()Ljava/lang/Throwable;
+HSPLjava/util/logging/LogRecord;->setLoggerName(Ljava/lang/String;)V
+HSPLjava/util/logging/LogRecord;->setParameters([Ljava/lang/Object;)V
+HSPLjava/util/logging/LogRecord;->setSourceClassName(Ljava/lang/String;)V
+HSPLjava/util/logging/LogRecord;->setSourceMethodName(Ljava/lang/String;)V
+HSPLjava/util/logging/LogRecord;->setThrown(Ljava/lang/Throwable;)V
+HSPLjava/util/logging/Logger$1;-><init>(Ljava/util/Locale;)V
+HSPLjava/util/logging/Logger$1;->run()Ljava/lang/Object;
+HSPLjava/util/logging/Logger$1;->run()Ljava/util/ResourceBundle;
+HSPLjava/util/logging/Logger$LoggerBundle;->get(Ljava/lang/String;Ljava/util/ResourceBundle;)Ljava/util/logging/Logger$LoggerBundle;
+HSPLjava/util/logging/Logger$LoggerBundle;->isSystemBundle()Z
+HSPLjava/util/logging/Logger;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/util/logging/LogManager;Z)V+]Ljava/util/logging/Level;Ljava/util/logging/Level;
+HSPLjava/util/logging/Logger;->access$100()Ljava/util/logging/Logger$LoggerBundle;
+HSPLjava/util/logging/Logger;->accessCheckedHandlers()[Ljava/util/logging/Handler;+]Ljava/util/concurrent/CopyOnWriteArrayList;Ljava/util/concurrent/CopyOnWriteArrayList;
+HSPLjava/util/logging/Logger;->addHandler(Ljava/util/logging/Handler;)V
+HSPLjava/util/logging/Logger;->checkPermission()V
+HSPLjava/util/logging/Logger;->demandLogger(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)Ljava/util/logging/Logger;+]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/Logger;->doLog(Ljava/util/logging/LogRecord;)V+]Ljava/util/logging/LogRecord;Ljava/util/logging/LogRecord;]Ljava/util/logging/Logger;Ljava/util/logging/Logger;
+HSPLjava/util/logging/Logger;->doSetParent(Ljava/util/logging/Logger;)V+]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;]Ljava/util/logging/LogManager$LoggerWeakRef;Ljava/util/logging/LogManager$LoggerWeakRef;
+HSPLjava/util/logging/Logger;->findResourceBundle(Ljava/lang/String;Z)Ljava/util/ResourceBundle;
+HSPLjava/util/logging/Logger;->findSystemResourceBundle(Ljava/util/Locale;)Ljava/util/ResourceBundle;
+HSPLjava/util/logging/Logger;->getCallersClassLoader()Ljava/lang/ClassLoader;
+HSPLjava/util/logging/Logger;->getEffectiveLoggerBundle()Ljava/util/logging/Logger$LoggerBundle;+]Ljava/util/logging/Logger$LoggerBundle;Ljava/util/logging/Logger$LoggerBundle;]Ljava/util/logging/Logger;Ljava/util/logging/LogManager$RootLogger;,Ljava/util/logging/Logger;
+HSPLjava/util/logging/Logger;->getHandlers()[Ljava/util/logging/Handler;+]Ljava/util/logging/Logger;Ljava/util/logging/Logger;,Ljava/util/logging/LogManager$RootLogger;
+HSPLjava/util/logging/Logger;->getLogger(Ljava/lang/String;)Ljava/util/logging/Logger;
+HSPLjava/util/logging/Logger;->getName()Ljava/lang/String;
+HSPLjava/util/logging/Logger;->getParent()Ljava/util/logging/Logger;
+HSPLjava/util/logging/Logger;->getPlatformLogger(Ljava/lang/String;)Ljava/util/logging/Logger;
+HSPLjava/util/logging/Logger;->getResourceBundle()Ljava/util/ResourceBundle;+]Ljava/util/logging/Logger;Ljava/util/logging/Logger;
+HSPLjava/util/logging/Logger;->getResourceBundleName()Ljava/lang/String;
+HSPLjava/util/logging/Logger;->getUseParentHandlers()Z
+HSPLjava/util/logging/Logger;->isLoggable(Ljava/util/logging/Level;)Z+]Ljava/util/logging/Level;Ljava/util/logging/Level;
+HSPLjava/util/logging/Logger;->log(Ljava/util/logging/Level;Ljava/lang/String;)V+]Ljava/util/logging/Logger;Ljava/util/logging/Logger;
+HSPLjava/util/logging/Logger;->log(Ljava/util/logging/LogRecord;)V+]Ljava/util/logging/Handler;missing_types]Ljava/util/logging/LogRecord;Ljava/util/logging/LogRecord;]Ljava/util/logging/Logger;Ljava/util/logging/Logger;,Ljava/util/logging/LogManager$RootLogger;
+HSPLjava/util/logging/Logger;->logp(Ljava/util/logging/Level;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/util/logging/LogRecord;Ljava/util/logging/LogRecord;]Ljava/util/logging/Logger;Ljava/util/logging/Logger;
+HSPLjava/util/logging/Logger;->logp(Ljava/util/logging/Level;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V+]Ljava/util/logging/Logger;Ljava/util/logging/Logger;]Ljava/util/logging/LogRecord;Ljava/util/logging/LogRecord;
+HSPLjava/util/logging/Logger;->logp(Ljava/util/logging/Level;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)V+]Ljava/util/logging/Logger;Ljava/util/logging/Logger;]Ljava/util/logging/LogRecord;Ljava/util/logging/LogRecord;
+HSPLjava/util/logging/Logger;->removeChildLogger(Ljava/util/logging/LogManager$LoggerWeakRef;)V+]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLjava/util/logging/Logger;->setCallersClassLoaderRef(Ljava/lang/Class;)V
+HSPLjava/util/logging/Logger;->setLevel(Ljava/util/logging/Level;)V
+HSPLjava/util/logging/Logger;->setLogManager(Ljava/util/logging/LogManager;)V
+HSPLjava/util/logging/Logger;->setParent(Ljava/util/logging/Logger;)V+]Ljava/util/logging/LogManager;Ljava/util/logging/LogManager;
+HSPLjava/util/logging/Logger;->setUseParentHandlers(Z)V
+HSPLjava/util/logging/Logger;->setupResourceInfo(Ljava/lang/String;Ljava/lang/Class;)V
+HSPLjava/util/logging/Logger;->updateEffectiveLevel()V+]Ljava/util/logging/Level;Ljava/util/logging/Level;
+HSPLjava/util/logging/LoggingProxyImpl;->getLogger(Ljava/lang/String;)Ljava/lang/Object;
+HSPLjava/util/logging/LoggingProxyImpl;->getProperty(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/util/logging/SimpleFormatter;-><clinit>()V
+HSPLjava/util/logging/SimpleFormatter;-><init>()V
+HSPLjava/util/logging/StreamHandler;-><init>()V
+HSPLjava/util/logging/StreamHandler;->close()V
+HSPLjava/util/logging/StreamHandler;->configure()V
+HSPLjava/util/logging/StreamHandler;->flush()V+]Ljava/io/Writer;Ljava/io/OutputStreamWriter;
+HSPLjava/util/logging/StreamHandler;->flushAndClose()V
+HSPLjava/util/logging/StreamHandler;->isLoggable(Ljava/util/logging/LogRecord;)Z
+HSPLjava/util/logging/StreamHandler;->publish(Ljava/util/logging/LogRecord;)V+]Ljava/io/Writer;Ljava/io/OutputStreamWriter;]Ljava/util/logging/StreamHandler;Ljava/util/logging/FileHandler;
+HSPLjava/util/logging/StreamHandler;->setEncoding(Ljava/lang/String;)V
+HSPLjava/util/logging/StreamHandler;->setOutputStream(Ljava/io/OutputStream;)V
+HSPLjava/util/logging/XMLFormatter;-><init>()V
+HSPLjava/util/regex/Matcher;-><init>(Ljava/util/regex/Pattern;Ljava/lang/CharSequence;)V+]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->appendEvaluated(Ljava/lang/StringBuffer;Ljava/lang/String;)V+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/regex/Matcher;->appendReplacement(Ljava/lang/StringBuffer;Ljava/lang/String;)Ljava/util/regex/Matcher;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->appendTail(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLjava/util/regex/Matcher;->end()I+]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->end(I)I+]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->ensureMatch()V
+HSPLjava/util/regex/Matcher;->find()Z+]Lcom/android/icu/util/regex/MatcherNative;Lcom/android/icu/util/regex/MatcherNative;
+HSPLjava/util/regex/Matcher;->find(I)Z+]Lcom/android/icu/util/regex/MatcherNative;missing_types]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->getSubSequence(II)Ljava/lang/CharSequence;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/regex/Matcher;->getTextLength()I
+HSPLjava/util/regex/Matcher;->group()Ljava/lang/String;+]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->group(I)Ljava/lang/String;+]Ljava/lang/CharSequence;Ljava/lang/String;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->groupCount()I+]Lcom/android/icu/util/regex/MatcherNative;missing_types
+HSPLjava/util/regex/Matcher;->hitEnd()Z+]Lcom/android/icu/util/regex/MatcherNative;missing_types
+HSPLjava/util/regex/Matcher;->lookingAt()Z+]Lcom/android/icu/util/regex/MatcherNative;missing_types
+HSPLjava/util/regex/Matcher;->matches()Z+]Lcom/android/icu/util/regex/MatcherNative;missing_types
+HSPLjava/util/regex/Matcher;->pattern()Ljava/util/regex/Pattern;
+HSPLjava/util/regex/Matcher;->region(II)Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->replaceAll(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->replaceFirst(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/regex/Matcher;->reset()Ljava/util/regex/Matcher;+]Ljava/lang/CharSequence;missing_types
+HSPLjava/util/regex/Matcher;->reset(Ljava/lang/CharSequence;)Ljava/util/regex/Matcher;+]Ljava/lang/CharSequence;megamorphic_types
+HSPLjava/util/regex/Matcher;->reset(Ljava/lang/CharSequence;II)Ljava/util/regex/Matcher;+]Ljava/lang/CharSequence;megamorphic_types
+HSPLjava/util/regex/Matcher;->resetForInput()V+]Lcom/android/icu/util/regex/MatcherNative;Lcom/android/icu/util/regex/MatcherNative;
+HSPLjava/util/regex/Matcher;->start()I+]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->start(I)I+]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->useAnchoringBounds(Z)Ljava/util/regex/Matcher;+]Lcom/android/icu/util/regex/MatcherNative;missing_types
+HSPLjava/util/regex/Matcher;->usePattern(Ljava/util/regex/Pattern;)Ljava/util/regex/Matcher;+]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Matcher;->useTransparentBounds(Z)Ljava/util/regex/Matcher;+]Lcom/android/icu/util/regex/MatcherNative;missing_types
+HSPLjava/util/regex/Pattern;-><init>(Ljava/lang/String;I)V
+HSPLjava/util/regex/Pattern;->compile()V
+HSPLjava/util/regex/Pattern;->compile(Ljava/lang/String;)Ljava/util/regex/Pattern;
+HSPLjava/util/regex/Pattern;->compile(Ljava/lang/String;I)Ljava/util/regex/Pattern;
+HSPLjava/util/regex/Pattern;->fastSplit(Ljava/lang/String;Ljava/lang/String;I)[Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/regex/Pattern;->matcher(Ljava/lang/CharSequence;)Ljava/util/regex/Matcher;
+HSPLjava/util/regex/Pattern;->matches(Ljava/lang/String;Ljava/lang/CharSequence;)Z+]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;]Ljava/util/regex/Pattern;Ljava/util/regex/Pattern;
+HSPLjava/util/regex/Pattern;->pattern()Ljava/lang/String;
+HSPLjava/util/regex/Pattern;->quote(Ljava/lang/String;)Ljava/lang/String;
+HSPLjava/util/regex/Pattern;->split(Ljava/lang/CharSequence;)[Ljava/lang/String;+]Ljava/util/regex/Pattern;Ljava/util/regex/Pattern;
+HSPLjava/util/regex/Pattern;->split(Ljava/lang/CharSequence;I)[Ljava/lang/String;+]Ljava/util/List;Ljava/util/ArrayList$SubList;]Ljava/lang/CharSequence;Ljava/lang/String;,Ljava/lang/StringBuilder;]Ljava/util/regex/Pattern;Ljava/util/regex/Pattern;]Ljava/util/regex/Matcher;Ljava/util/regex/Matcher;]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ldalvik/system/VMRuntime;missing_types
+HSPLjava/util/regex/Pattern;->toString()Ljava/lang/String;
+HSPLjava/util/stream/AbstractPipeline;-><init>(Ljava/util/Spliterator;IZ)V
+HSPLjava/util/stream/AbstractPipeline;-><init>(Ljava/util/stream/AbstractPipeline;I)V+]Ljava/util/stream/AbstractPipeline;megamorphic_types
+HSPLjava/util/stream/AbstractPipeline;->close()V
+HSPLjava/util/stream/AbstractPipeline;->copyInto(Ljava/util/stream/Sink;Ljava/util/Spliterator;)V+]Ljava/util/Spliterator;megamorphic_types]Ljava/util/stream/AbstractPipeline;megamorphic_types]Ljava/util/stream/Sink;megamorphic_types]Ljava/util/stream/StreamOpFlag;Ljava/util/stream/StreamOpFlag;
+HSPLjava/util/stream/AbstractPipeline;->copyIntoWithCancel(Ljava/util/stream/Sink;Ljava/util/Spliterator;)V+]Ljava/util/Spliterator;megamorphic_types]Ljava/util/stream/AbstractPipeline;Ljava/util/stream/IntPipeline$Head;,Ljava/util/stream/ReferencePipeline$Head;]Ljava/util/stream/Sink;megamorphic_types
+HSPLjava/util/stream/AbstractPipeline;->evaluate(Ljava/util/Spliterator;ZLjava/util/function/IntFunction;)Ljava/util/stream/Node;+]Ljava/util/stream/Node$Builder;megamorphic_types]Ljava/util/stream/AbstractPipeline;megamorphic_types
+HSPLjava/util/stream/AbstractPipeline;->evaluate(Ljava/util/stream/TerminalOp;)Ljava/lang/Object;+]Ljava/util/stream/TerminalOp;megamorphic_types]Ljava/util/stream/AbstractPipeline;megamorphic_types
+HSPLjava/util/stream/AbstractPipeline;->evaluateToArrayNode(Ljava/util/function/IntFunction;)Ljava/util/stream/Node;+]Ljava/util/stream/AbstractPipeline;megamorphic_types
+HSPLjava/util/stream/AbstractPipeline;->exactOutputSizeIfKnown(Ljava/util/Spliterator;)J+]Ljava/util/Spliterator;megamorphic_types]Ljava/util/stream/AbstractPipeline;megamorphic_types]Ljava/util/stream/StreamOpFlag;Ljava/util/stream/StreamOpFlag;
+HSPLjava/util/stream/AbstractPipeline;->getStreamAndOpFlags()I
+HSPLjava/util/stream/AbstractPipeline;->isParallel()Z
+HSPLjava/util/stream/AbstractPipeline;->lambda$spliterator$0$AbstractPipeline()Ljava/util/Spliterator;
+HSPLjava/util/stream/AbstractPipeline;->onClose(Ljava/lang/Runnable;)Ljava/util/stream/BaseStream;
+HSPLjava/util/stream/AbstractPipeline;->sequential()Ljava/util/stream/BaseStream;
+HSPLjava/util/stream/AbstractPipeline;->sourceSpliterator(I)Ljava/util/Spliterator;+]Ljava/util/stream/AbstractPipeline;megamorphic_types]Ljava/util/function/Supplier;Ljava/lang/CharSequence$$ExternalSyntheticLambda0;
+HSPLjava/util/stream/AbstractPipeline;->sourceStageSpliterator()Ljava/util/Spliterator;
+HSPLjava/util/stream/AbstractPipeline;->spliterator()Ljava/util/Spliterator;+]Ljava/util/stream/AbstractPipeline;Ljava/util/stream/IntPipeline$4;,Ljava/util/stream/SliceOps$1;,Ljava/util/stream/ReferencePipeline$3;
+HSPLjava/util/stream/AbstractPipeline;->wrapAndCopyInto(Ljava/util/stream/Sink;Ljava/util/Spliterator;)Ljava/util/stream/Sink;+]Ljava/util/stream/AbstractPipeline;megamorphic_types
+HSPLjava/util/stream/AbstractPipeline;->wrapSink(Ljava/util/stream/Sink;)Ljava/util/stream/Sink;+]Ljava/util/stream/AbstractPipeline;megamorphic_types
+HSPLjava/util/stream/AbstractSpinedBuffer;-><init>()V
+HSPLjava/util/stream/AbstractSpinedBuffer;->count()J
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda20;->accept(Ljava/lang/Object;Ljava/lang/Object;)V+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda21;-><clinit>()V
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda21;-><init>()V
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda21;->accept(Ljava/lang/Object;Ljava/lang/Object;)V+]Ljava/util/Set;Ljava/util/HashSet;
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda22;->accept(Ljava/lang/Object;Ljava/lang/Object;)V+]Ljava/util/StringJoiner;Ljava/util/StringJoiner;
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda26;-><init>(Ljava/util/function/BinaryOperator;)V
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda36;-><clinit>()V
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda36;-><init>()V
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda54;->apply(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/StringJoiner;Ljava/util/StringJoiner;
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda66;-><init>(Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;)V
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda66;->get()Ljava/lang/Object;
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda77;->get()Ljava/lang/Object;
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda79;->get()Ljava/lang/Object;
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda80;-><clinit>()V
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda80;-><init>()V
+HSPLjava/util/stream/Collectors$$ExternalSyntheticLambda80;->get()Ljava/lang/Object;
+HSPLjava/util/stream/Collectors$CollectorImpl;-><init>(Ljava/util/function/Supplier;Ljava/util/function/BiConsumer;Ljava/util/function/BinaryOperator;Ljava/util/Set;)V
+HSPLjava/util/stream/Collectors$CollectorImpl;-><init>(Ljava/util/function/Supplier;Ljava/util/function/BiConsumer;Ljava/util/function/BinaryOperator;Ljava/util/function/Function;Ljava/util/Set;)V
+HSPLjava/util/stream/Collectors$CollectorImpl;->accumulator()Ljava/util/function/BiConsumer;
+HSPLjava/util/stream/Collectors$CollectorImpl;->characteristics()Ljava/util/Set;
+HSPLjava/util/stream/Collectors$CollectorImpl;->combiner()Ljava/util/function/BinaryOperator;
+HSPLjava/util/stream/Collectors$CollectorImpl;->finisher()Ljava/util/function/Function;
+HSPLjava/util/stream/Collectors$CollectorImpl;->supplier()Ljava/util/function/Supplier;
+HSPLjava/util/stream/Collectors;->access$000()Ljava/util/function/Function;
+HSPLjava/util/stream/Collectors;->castingIdentity()Ljava/util/function/Function;
+HSPLjava/util/stream/Collectors;->groupingBy(Ljava/util/function/Function;)Ljava/util/stream/Collector;
+HSPLjava/util/stream/Collectors;->groupingBy(Ljava/util/function/Function;Ljava/util/function/Supplier;Ljava/util/stream/Collector;)Ljava/util/stream/Collector;+]Ljava/util/stream/Collector;Ljava/util/stream/Collectors$CollectorImpl;]Ljava/util/Set;Ljava/util/Collections$UnmodifiableSet;
+HSPLjava/util/stream/Collectors;->groupingBy(Ljava/util/function/Function;Ljava/util/stream/Collector;)Ljava/util/stream/Collector;
+HSPLjava/util/stream/Collectors;->joining(Ljava/lang/CharSequence;)Ljava/util/stream/Collector;
+HSPLjava/util/stream/Collectors;->joining(Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/util/stream/Collector;
+HSPLjava/util/stream/Collectors;->lambda$joining$6(Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/util/StringJoiner;
+HSPLjava/util/stream/Collectors;->mapMerger(Ljava/util/function/BinaryOperator;)Ljava/util/function/BinaryOperator;
+HSPLjava/util/stream/Collectors;->throwingMerger()Ljava/util/function/BinaryOperator;
+HSPLjava/util/stream/Collectors;->toCollection(Ljava/util/function/Supplier;)Ljava/util/stream/Collector;
+HSPLjava/util/stream/Collectors;->toList()Ljava/util/stream/Collector;
+HSPLjava/util/stream/Collectors;->toMap(Ljava/util/function/Function;Ljava/util/function/Function;)Ljava/util/stream/Collector;
+HSPLjava/util/stream/Collectors;->toMap(Ljava/util/function/Function;Ljava/util/function/Function;Ljava/util/function/BinaryOperator;Ljava/util/function/Supplier;)Ljava/util/stream/Collector;
+HSPLjava/util/stream/Collectors;->toSet()Ljava/util/stream/Collector;
+HSPLjava/util/stream/DistinctOps$1$2;-><init>(Ljava/util/stream/DistinctOps$1;Ljava/util/stream/Sink;)V
+HSPLjava/util/stream/DistinctOps$1$2;->accept(Ljava/lang/Object;)V+]Ljava/util/stream/Sink;Ljava/util/stream/Nodes$SpinedNodeBuilder;,Ljava/util/stream/ReferencePipeline$4$1;,Ljava/util/stream/ReduceOps$3ReducingSink;,Ljava/util/stream/ReferencePipeline$5$1;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLjava/util/stream/DistinctOps$1$2;->begin(J)V+]Ljava/util/stream/Sink;Ljava/util/stream/ReduceOps$3ReducingSink;,Ljava/util/stream/Nodes$SpinedNodeBuilder;,Ljava/util/stream/ReferencePipeline$4$1;,Ljava/util/stream/ReferencePipeline$5$1;
+HSPLjava/util/stream/DistinctOps$1$2;->end()V+]Ljava/util/stream/Sink;Ljava/util/stream/ReduceOps$3ReducingSink;,Ljava/util/stream/Nodes$SpinedNodeBuilder;,Ljava/util/stream/ReferencePipeline$4$1;,Ljava/util/stream/ReferencePipeline$5$1;
+HSPLjava/util/stream/DistinctOps$1;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+HSPLjava/util/stream/DistinctOps$1;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;+]Ljava/util/stream/StreamOpFlag;Ljava/util/stream/StreamOpFlag;
+HSPLjava/util/stream/DistinctOps;->makeRef(Ljava/util/stream/AbstractPipeline;)Ljava/util/stream/ReferencePipeline;
+HSPLjava/util/stream/DoublePipeline$StatelessOp;-><clinit>()V
+HSPLjava/util/stream/DoublePipeline$StatelessOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+HSPLjava/util/stream/DoublePipeline$StatelessOp;->opIsStateful()Z
+HSPLjava/util/stream/DoublePipeline;-><init>(Ljava/util/stream/AbstractPipeline;I)V
+HSPLjava/util/stream/DoublePipeline;->max()Ljava/util/OptionalDouble;
+HSPLjava/util/stream/DoublePipeline;->reduce(Ljava/util/function/DoubleBinaryOperator;)Ljava/util/OptionalDouble;
+HSPLjava/util/stream/FindOps$$ExternalSyntheticLambda7;->get()Ljava/lang/Object;
+HSPLjava/util/stream/FindOps$FindOp;-><init>(ZLjava/util/stream/StreamShape;Ljava/lang/Object;Ljava/util/function/Predicate;Ljava/util/function/Supplier;)V
+HSPLjava/util/stream/FindOps$FindOp;->evaluateSequential(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;)Ljava/lang/Object;+]Ljava/util/stream/PipelineHelper;megamorphic_types]Ljava/util/function/Supplier;Ljava/util/stream/FindOps$$ExternalSyntheticLambda4;,Ljava/util/stream/FindOps$$ExternalSyntheticLambda5;,Ljava/util/stream/FindOps$$ExternalSyntheticLambda7;]Ljava/util/stream/TerminalSink;Ljava/util/stream/FindOps$FindSink$OfInt;,Ljava/util/stream/FindOps$FindSink$OfRef;,Ljava/util/stream/FindOps$FindSink$OfDouble;
+HSPLjava/util/stream/FindOps$FindOp;->getOpFlags()I
+HSPLjava/util/stream/FindOps$FindSink$OfRef;-><init>()V
+HSPLjava/util/stream/FindOps$FindSink$OfRef;->get()Ljava/lang/Object;+]Ljava/util/stream/FindOps$FindSink$OfRef;Ljava/util/stream/FindOps$FindSink$OfRef;
+HSPLjava/util/stream/FindOps$FindSink$OfRef;->get()Ljava/util/Optional;
+HSPLjava/util/stream/FindOps$FindSink;-><init>()V
+HSPLjava/util/stream/FindOps$FindSink;->accept(Ljava/lang/Object;)V
+HSPLjava/util/stream/FindOps$FindSink;->cancellationRequested()Z
+HSPLjava/util/stream/FindOps;->makeRef(Z)Ljava/util/stream/TerminalOp;
+HSPLjava/util/stream/ForEachOps$ForEachOp$OfRef;-><init>(Ljava/util/function/Consumer;Z)V
+HSPLjava/util/stream/ForEachOps$ForEachOp$OfRef;->accept(Ljava/lang/Object;)V+]Ljava/util/function/Consumer;missing_types
+HSPLjava/util/stream/ForEachOps$ForEachOp;-><init>(Z)V
+HSPLjava/util/stream/ForEachOps$ForEachOp;->evaluateSequential(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;)Ljava/lang/Object;+]Ljava/util/stream/ForEachOps$ForEachOp;Ljava/util/stream/ForEachOps$ForEachOp$OfRef;,Ljava/util/stream/ForEachOps$ForEachOp$OfInt;
+HSPLjava/util/stream/ForEachOps$ForEachOp;->evaluateSequential(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;)Ljava/lang/Void;+]Ljava/util/stream/PipelineHelper;Ljava/util/stream/ReferencePipeline$3;,Ljava/util/stream/ReferencePipeline$2;,Ljava/util/stream/ReferencePipeline$7;,Ljava/util/stream/IntPipeline$9;,Ljava/util/stream/SortedOps$OfRef;,Ljava/util/stream/IntPipeline$4;]Ljava/util/stream/ForEachOps$ForEachOp;Ljava/util/stream/ForEachOps$ForEachOp$OfRef;,Ljava/util/stream/ForEachOps$ForEachOp$OfInt;
+HSPLjava/util/stream/ForEachOps$ForEachOp;->get()Ljava/lang/Void;
+HSPLjava/util/stream/ForEachOps$ForEachOp;->getOpFlags()I
+HSPLjava/util/stream/ForEachOps;->makeRef(Ljava/util/function/Consumer;Z)Ljava/util/stream/TerminalOp;
+HSPLjava/util/stream/IntPipeline$$ExternalSyntheticLambda7;->apply(I)Ljava/lang/Object;
+HSPLjava/util/stream/IntPipeline$4$1;-><init>(Ljava/util/stream/IntPipeline$4;Ljava/util/stream/Sink;)V
+HSPLjava/util/stream/IntPipeline$4$1;->accept(I)V+]Ljava/util/function/IntFunction;megamorphic_types]Ljava/util/stream/Sink;Ljava/util/stream/ReduceOps$3ReducingSink;,Ljava/util/stream/DistinctOps$1$2;,Ljava/util/stream/ReferencePipeline$2$1;,Ljava/util/stream/StreamSpliterators$WrappingSpliterator$$ExternalSyntheticLambda2;,Ljava/util/stream/ForEachOps$ForEachOp$OfRef;
+HSPLjava/util/stream/IntPipeline$4;-><init>(Ljava/util/stream/IntPipeline;Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;ILjava/util/function/IntFunction;)V
+HSPLjava/util/stream/IntPipeline$4;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+HSPLjava/util/stream/IntPipeline$Head;-><init>(Ljava/util/Spliterator;IZ)V
+HSPLjava/util/stream/IntPipeline$Head;->forEach(Ljava/util/function/IntConsumer;)V+]Ljava/util/stream/IntPipeline$Head;Ljava/util/stream/IntPipeline$Head;]Ljava/util/Spliterator$OfInt;Ljava/util/stream/Streams$RangeIntSpliterator;,Ljava/util/Spliterators$EmptySpliterator$OfInt;,Ljava/util/stream/Streams$IntStreamBuilderImpl;,Ljava/util/Spliterators$IntArraySpliterator;
+HSPLjava/util/stream/IntPipeline$StatelessOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+HSPLjava/util/stream/IntPipeline$StatelessOp;->opIsStateful()Z
+HSPLjava/util/stream/IntPipeline;-><init>(Ljava/util/Spliterator;IZ)V
+HSPLjava/util/stream/IntPipeline;-><init>(Ljava/util/stream/AbstractPipeline;I)V
+HSPLjava/util/stream/IntPipeline;->access$000(Ljava/util/Spliterator;)Ljava/util/Spliterator$OfInt;
+HSPLjava/util/stream/IntPipeline;->adapt(Ljava/util/Spliterator;)Ljava/util/Spliterator$OfInt;
+HSPLjava/util/stream/IntPipeline;->adapt(Ljava/util/stream/Sink;)Ljava/util/function/IntConsumer;
+HSPLjava/util/stream/IntPipeline;->allMatch(Ljava/util/function/IntPredicate;)Z+]Ljava/lang/Boolean;Ljava/lang/Boolean;]Ljava/util/stream/IntPipeline;Ljava/util/stream/IntPipeline$Head;
+HSPLjava/util/stream/IntPipeline;->boxed()Ljava/util/stream/Stream;+]Ljava/util/stream/IntPipeline;Ljava/util/stream/IntPipeline$Head;,Ljava/util/stream/ReferencePipeline$4;,Ljava/util/stream/IntPipeline$9;,Ljava/util/stream/IntPipeline$3;
+HSPLjava/util/stream/IntPipeline;->distinct()Ljava/util/stream/IntStream;+]Ljava/util/stream/Stream;Ljava/util/stream/DistinctOps$1;,Ljava/util/stream/IntPipeline$4;]Ljava/util/stream/IntPipeline;Ljava/util/stream/ReferencePipeline$4;
+HSPLjava/util/stream/IntPipeline;->forEachWithCancel(Ljava/util/Spliterator;Ljava/util/stream/Sink;)V+]Ljava/util/Spliterator$OfInt;Ljava/util/Spliterators$IntArraySpliterator;,Ljava/util/Spliterators$EmptySpliterator$OfInt;,Ljava/util/stream/Streams$RangeIntSpliterator;,Ljava/util/Spliterators$IntIteratorSpliterator;]Ljava/util/stream/Sink;Ljava/util/stream/MatchOps$2MatchSink;,Ljava/util/stream/IntPipeline$9$1;
+HSPLjava/util/stream/IntPipeline;->makeNodeBuilder(JLjava/util/function/IntFunction;)Ljava/util/stream/Node$Builder;
+HSPLjava/util/stream/IntPipeline;->mapToObj(Ljava/util/function/IntFunction;)Ljava/util/stream/Stream;
+HSPLjava/util/stream/IntPipeline;->reduce(ILjava/util/function/IntBinaryOperator;)I+]Ljava/lang/Integer;Ljava/lang/Integer;]Ljava/util/stream/IntPipeline;Ljava/util/stream/IntPipeline$Head;
+HSPLjava/util/stream/IntPipeline;->sum()I+]Ljava/util/stream/IntPipeline;Ljava/util/stream/IntPipeline$Head;
+HSPLjava/util/stream/IntPipeline;->toArray()[I+]Ljava/util/stream/IntPipeline;Ljava/util/stream/ReferencePipeline$4;,Ljava/util/stream/IntPipeline$9;,Ljava/util/stream/ReferencePipeline$8;,Ljava/util/stream/SliceOps$2;,Ljava/util/stream/IntPipeline$Head;]Ljava/util/stream/Node$OfInt;Ljava/util/stream/Nodes$IntFixedNodeBuilder;,Ljava/util/stream/Nodes$IntSpinedNodeBuilder;
+HSPLjava/util/stream/IntStream;->empty()Ljava/util/stream/IntStream;
+HSPLjava/util/stream/IntStream;->of([I)Ljava/util/stream/IntStream;
+HSPLjava/util/stream/IntStream;->range(II)Ljava/util/stream/IntStream;
+HSPLjava/util/stream/LongPipeline$$ExternalSyntheticLambda4;-><clinit>()V
+HSPLjava/util/stream/LongPipeline$$ExternalSyntheticLambda4;-><init>()V
+HSPLjava/util/stream/LongPipeline$$ExternalSyntheticLambda4;->applyAsLong(JJ)J
+HSPLjava/util/stream/LongPipeline$StatelessOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+HSPLjava/util/stream/LongPipeline$StatelessOp;->opIsStateful()Z
+HSPLjava/util/stream/LongPipeline;-><init>(Ljava/util/stream/AbstractPipeline;I)V
+HSPLjava/util/stream/LongPipeline;->reduce(JLjava/util/function/LongBinaryOperator;)J+]Ljava/lang/Long;Ljava/lang/Long;]Ljava/util/stream/LongPipeline;Ljava/util/stream/ReferencePipeline$5;
+HSPLjava/util/stream/LongPipeline;->sum()J+]Ljava/util/stream/LongPipeline;Ljava/util/stream/ReferencePipeline$5;
+HSPLjava/util/stream/MatchOps$$ExternalSyntheticLambda3;-><init>(Ljava/util/stream/MatchOps$MatchKind;Ljava/util/function/Predicate;)V
+HSPLjava/util/stream/MatchOps$$ExternalSyntheticLambda3;->get()Ljava/lang/Object;
+HSPLjava/util/stream/MatchOps$1MatchSink;-><init>(Ljava/util/stream/MatchOps$MatchKind;Ljava/util/function/Predicate;)V
+HSPLjava/util/stream/MatchOps$1MatchSink;->accept(Ljava/lang/Object;)V+]Ljava/util/function/Predicate;megamorphic_types
+HSPLjava/util/stream/MatchOps$BooleanTerminalSink;-><init>(Ljava/util/stream/MatchOps$MatchKind;)V
+HSPLjava/util/stream/MatchOps$BooleanTerminalSink;->cancellationRequested()Z
+HSPLjava/util/stream/MatchOps$BooleanTerminalSink;->getAndClearState()Z
+HSPLjava/util/stream/MatchOps$MatchKind;->access$000(Ljava/util/stream/MatchOps$MatchKind;)Z
+HSPLjava/util/stream/MatchOps$MatchKind;->access$100(Ljava/util/stream/MatchOps$MatchKind;)Z
+HSPLjava/util/stream/MatchOps$MatchOp;-><init>(Ljava/util/stream/StreamShape;Ljava/util/stream/MatchOps$MatchKind;Ljava/util/function/Supplier;)V
+HSPLjava/util/stream/MatchOps$MatchOp;->evaluateSequential(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;)Ljava/lang/Boolean;+]Ljava/util/stream/PipelineHelper;Ljava/util/stream/IntPipeline$Head;,Ljava/util/stream/ReferencePipeline$Head;,Ljava/util/stream/ReferencePipeline$7;,Ljava/util/stream/ReferencePipeline$3;,Ljava/util/stream/ReferencePipeline$2;]Ljava/util/function/Supplier;Ljava/util/stream/MatchOps$$ExternalSyntheticLambda3;,Ljava/util/stream/MatchOps$$ExternalSyntheticLambda1;]Ljava/util/stream/MatchOps$BooleanTerminalSink;Ljava/util/stream/MatchOps$2MatchSink;,Ljava/util/stream/MatchOps$1MatchSink;
+HSPLjava/util/stream/MatchOps$MatchOp;->evaluateSequential(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;)Ljava/lang/Object;+]Ljava/util/stream/MatchOps$MatchOp;Ljava/util/stream/MatchOps$MatchOp;
+HSPLjava/util/stream/MatchOps$MatchOp;->getOpFlags()I
+HSPLjava/util/stream/MatchOps;->lambda$makeInt$1(Ljava/util/stream/MatchOps$MatchKind;Ljava/util/function/IntPredicate;)Ljava/util/stream/MatchOps$BooleanTerminalSink;
+HSPLjava/util/stream/MatchOps;->lambda$makeRef$0(Ljava/util/stream/MatchOps$MatchKind;Ljava/util/function/Predicate;)Ljava/util/stream/MatchOps$BooleanTerminalSink;
+HSPLjava/util/stream/MatchOps;->makeInt(Ljava/util/function/IntPredicate;Ljava/util/stream/MatchOps$MatchKind;)Ljava/util/stream/TerminalOp;
+HSPLjava/util/stream/MatchOps;->makeRef(Ljava/util/function/Predicate;Ljava/util/stream/MatchOps$MatchKind;)Ljava/util/stream/TerminalOp;
+HSPLjava/util/stream/Node;->getChildCount()I
+HSPLjava/util/stream/Nodes$ArrayNode;-><init>(JLjava/util/function/IntFunction;)V+]Ljava/util/function/IntFunction;megamorphic_types
+HSPLjava/util/stream/Nodes$ArrayNode;->asArray(Ljava/util/function/IntFunction;)[Ljava/lang/Object;
+HSPLjava/util/stream/Nodes$FixedNodeBuilder;-><init>(JLjava/util/function/IntFunction;)V
+HSPLjava/util/stream/Nodes$FixedNodeBuilder;->accept(Ljava/lang/Object;)V
+HSPLjava/util/stream/Nodes$FixedNodeBuilder;->begin(J)V
+HSPLjava/util/stream/Nodes$FixedNodeBuilder;->build()Ljava/util/stream/Node;
+HSPLjava/util/stream/Nodes$FixedNodeBuilder;->end()V
+HSPLjava/util/stream/Nodes$IntArrayNode;-><init>(J)V
+HSPLjava/util/stream/Nodes$IntArrayNode;->asPrimitiveArray()Ljava/lang/Object;+]Ljava/util/stream/Nodes$IntArrayNode;Ljava/util/stream/Nodes$IntFixedNodeBuilder;
+HSPLjava/util/stream/Nodes$IntArrayNode;->asPrimitiveArray()[I
+HSPLjava/util/stream/Nodes$IntFixedNodeBuilder;-><init>(J)V
+HSPLjava/util/stream/Nodes$IntFixedNodeBuilder;->accept(I)V
+HSPLjava/util/stream/Nodes$IntFixedNodeBuilder;->begin(J)V
+HSPLjava/util/stream/Nodes$IntFixedNodeBuilder;->build()Ljava/util/stream/Node$OfInt;
+HSPLjava/util/stream/Nodes$IntFixedNodeBuilder;->build()Ljava/util/stream/Node;+]Ljava/util/stream/Nodes$IntFixedNodeBuilder;Ljava/util/stream/Nodes$IntFixedNodeBuilder;
+HSPLjava/util/stream/Nodes$IntFixedNodeBuilder;->end()V
+HSPLjava/util/stream/Nodes$SpinedNodeBuilder;-><clinit>()V
+HSPLjava/util/stream/Nodes$SpinedNodeBuilder;-><init>()V
+HSPLjava/util/stream/Nodes;->builder()Ljava/util/stream/Node$Builder;
+HSPLjava/util/stream/Nodes;->builder(JLjava/util/function/IntFunction;)Ljava/util/stream/Node$Builder;
+HSPLjava/util/stream/Nodes;->flatten(Ljava/util/stream/Node;Ljava/util/function/IntFunction;)Ljava/util/stream/Node;+]Ljava/util/stream/Node;Ljava/util/stream/Nodes$FixedNodeBuilder;,Ljava/util/stream/Nodes$SpinedNodeBuilder;
+HSPLjava/util/stream/Nodes;->flattenInt(Ljava/util/stream/Node$OfInt;)Ljava/util/stream/Node$OfInt;+]Ljava/util/stream/Node$OfInt;Ljava/util/stream/Nodes$IntFixedNodeBuilder;,Ljava/util/stream/Nodes$IntSpinedNodeBuilder;
+HSPLjava/util/stream/Nodes;->intBuilder(J)Ljava/util/stream/Node$Builder$OfInt;
+HSPLjava/util/stream/PipelineHelper;-><init>()V
+HSPLjava/util/stream/ReduceOps$12;-><init>(Ljava/util/stream/StreamShape;Ljava/util/function/DoubleBinaryOperator;)V
+HSPLjava/util/stream/ReduceOps$12;->makeSink()Ljava/util/stream/ReduceOps$12ReducingSink;
+HSPLjava/util/stream/ReduceOps$12;->makeSink()Ljava/util/stream/ReduceOps$AccumulatingSink;
+HSPLjava/util/stream/ReduceOps$12ReducingSink;-><init>(Ljava/util/function/DoubleBinaryOperator;)V
+HSPLjava/util/stream/ReduceOps$12ReducingSink;->accept(D)V+]Ljava/util/function/DoubleBinaryOperator;Ljava/util/stream/DoublePipeline$$ExternalSyntheticLambda4;
+HSPLjava/util/stream/ReduceOps$12ReducingSink;->begin(J)V
+HSPLjava/util/stream/ReduceOps$12ReducingSink;->get()Ljava/lang/Object;
+HSPLjava/util/stream/ReduceOps$12ReducingSink;->get()Ljava/util/OptionalDouble;
+HSPLjava/util/stream/ReduceOps$2;-><init>(Ljava/util/stream/StreamShape;Ljava/util/function/BinaryOperator;)V
+HSPLjava/util/stream/ReduceOps$2;->makeSink()Ljava/util/stream/ReduceOps$2ReducingSink;
+HSPLjava/util/stream/ReduceOps$2;->makeSink()Ljava/util/stream/ReduceOps$AccumulatingSink;
+HSPLjava/util/stream/ReduceOps$2ReducingSink;-><init>(Ljava/util/function/BinaryOperator;)V
+HSPLjava/util/stream/ReduceOps$2ReducingSink;->begin(J)V
+HSPLjava/util/stream/ReduceOps$2ReducingSink;->get()Ljava/lang/Object;
+HSPLjava/util/stream/ReduceOps$2ReducingSink;->get()Ljava/util/Optional;
+HSPLjava/util/stream/ReduceOps$3;-><init>(Ljava/util/stream/StreamShape;Ljava/util/function/BinaryOperator;Ljava/util/function/BiConsumer;Ljava/util/function/Supplier;Ljava/util/stream/Collector;)V
+HSPLjava/util/stream/ReduceOps$3;->getOpFlags()I+]Ljava/util/stream/Collector;Ljava/util/stream/Collectors$CollectorImpl;]Ljava/util/Set;Ljava/util/Collections$UnmodifiableSet;,Ljava/util/Collections$EmptySet;
+HSPLjava/util/stream/ReduceOps$3;->makeSink()Ljava/util/stream/ReduceOps$3ReducingSink;
+HSPLjava/util/stream/ReduceOps$3;->makeSink()Ljava/util/stream/ReduceOps$AccumulatingSink;+]Ljava/util/stream/ReduceOps$3;Ljava/util/stream/ReduceOps$3;
+HSPLjava/util/stream/ReduceOps$3ReducingSink;-><init>(Ljava/util/function/Supplier;Ljava/util/function/BiConsumer;Ljava/util/function/BinaryOperator;)V
+HSPLjava/util/stream/ReduceOps$3ReducingSink;->accept(Ljava/lang/Object;)V+]Ljava/util/function/BiConsumer;megamorphic_types
+HSPLjava/util/stream/ReduceOps$3ReducingSink;->begin(J)V+]Ljava/util/function/Supplier;megamorphic_types
+HSPLjava/util/stream/ReduceOps$5;-><init>(Ljava/util/stream/StreamShape;Ljava/util/function/IntBinaryOperator;I)V
+HSPLjava/util/stream/ReduceOps$5;->makeSink()Ljava/util/stream/ReduceOps$5ReducingSink;
+HSPLjava/util/stream/ReduceOps$5;->makeSink()Ljava/util/stream/ReduceOps$AccumulatingSink;+]Ljava/util/stream/ReduceOps$5;Ljava/util/stream/ReduceOps$5;
+HSPLjava/util/stream/ReduceOps$5ReducingSink;-><init>(ILjava/util/function/IntBinaryOperator;)V
+HSPLjava/util/stream/ReduceOps$5ReducingSink;->begin(J)V
+HSPLjava/util/stream/ReduceOps$5ReducingSink;->get()Ljava/lang/Integer;
+HSPLjava/util/stream/ReduceOps$5ReducingSink;->get()Ljava/lang/Object;+]Ljava/util/stream/ReduceOps$5ReducingSink;Ljava/util/stream/ReduceOps$5ReducingSink;
+HSPLjava/util/stream/ReduceOps$8;-><init>(Ljava/util/stream/StreamShape;Ljava/util/function/LongBinaryOperator;J)V
+HSPLjava/util/stream/ReduceOps$8;->makeSink()Ljava/util/stream/ReduceOps$8ReducingSink;
+HSPLjava/util/stream/ReduceOps$8;->makeSink()Ljava/util/stream/ReduceOps$AccumulatingSink;+]Ljava/util/stream/ReduceOps$8;Ljava/util/stream/ReduceOps$8;
+HSPLjava/util/stream/ReduceOps$8ReducingSink;-><init>(JLjava/util/function/LongBinaryOperator;)V
+HSPLjava/util/stream/ReduceOps$8ReducingSink;->accept(J)V+]Ljava/util/function/LongBinaryOperator;Ljava/util/stream/LongPipeline$$ExternalSyntheticLambda4;
+HSPLjava/util/stream/ReduceOps$8ReducingSink;->begin(J)V
+HSPLjava/util/stream/ReduceOps$8ReducingSink;->get()Ljava/lang/Long;
+HSPLjava/util/stream/ReduceOps$8ReducingSink;->get()Ljava/lang/Object;+]Ljava/util/stream/ReduceOps$8ReducingSink;Ljava/util/stream/ReduceOps$8ReducingSink;
+HSPLjava/util/stream/ReduceOps$Box;-><init>()V
+HSPLjava/util/stream/ReduceOps$Box;->get()Ljava/lang/Object;
+HSPLjava/util/stream/ReduceOps$ReduceOp;-><init>(Ljava/util/stream/StreamShape;)V
+HSPLjava/util/stream/ReduceOps$ReduceOp;->evaluateSequential(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;)Ljava/lang/Object;+]Ljava/util/stream/ReduceOps$AccumulatingSink;megamorphic_types]Ljava/util/stream/PipelineHelper;megamorphic_types]Ljava/util/stream/ReduceOps$ReduceOp;megamorphic_types
+HSPLjava/util/stream/ReduceOps;->makeDouble(Ljava/util/function/DoubleBinaryOperator;)Ljava/util/stream/TerminalOp;
+HSPLjava/util/stream/ReduceOps;->makeInt(ILjava/util/function/IntBinaryOperator;)Ljava/util/stream/TerminalOp;
+HSPLjava/util/stream/ReduceOps;->makeLong(JLjava/util/function/LongBinaryOperator;)Ljava/util/stream/TerminalOp;
+HSPLjava/util/stream/ReduceOps;->makeRef(Ljava/util/function/BinaryOperator;)Ljava/util/stream/TerminalOp;
+HSPLjava/util/stream/ReduceOps;->makeRef(Ljava/util/stream/Collector;)Ljava/util/stream/TerminalOp;+]Ljava/util/stream/Collector;Ljava/util/stream/Collectors$CollectorImpl;
+HSPLjava/util/stream/ReferencePipeline$$ExternalSyntheticLambda2;-><clinit>()V
+HSPLjava/util/stream/ReferencePipeline$$ExternalSyntheticLambda2;-><init>()V
+HSPLjava/util/stream/ReferencePipeline$$ExternalSyntheticLambda2;->applyAsLong(Ljava/lang/Object;)J
+HSPLjava/util/stream/ReferencePipeline$2$1;-><init>(Ljava/util/stream/ReferencePipeline$2;Ljava/util/stream/Sink;)V
+HSPLjava/util/stream/ReferencePipeline$2$1;->accept(Ljava/lang/Object;)V+]Ljava/util/stream/Sink;megamorphic_types]Ljava/util/function/Predicate;megamorphic_types
+HSPLjava/util/stream/ReferencePipeline$2$1;->begin(J)V+]Ljava/util/stream/Sink;megamorphic_types
+HSPLjava/util/stream/ReferencePipeline$2;-><init>(Ljava/util/stream/ReferencePipeline;Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;ILjava/util/function/Predicate;)V
+HSPLjava/util/stream/ReferencePipeline$2;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+HSPLjava/util/stream/ReferencePipeline$3$1;-><init>(Ljava/util/stream/ReferencePipeline$3;Ljava/util/stream/Sink;)V
+HSPLjava/util/stream/ReferencePipeline$3$1;->accept(Ljava/lang/Object;)V+]Ljava/util/stream/Sink;megamorphic_types]Ljava/util/function/Function;megamorphic_types
+HSPLjava/util/stream/ReferencePipeline$3;-><init>(Ljava/util/stream/ReferencePipeline;Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;ILjava/util/function/Function;)V
+HSPLjava/util/stream/ReferencePipeline$3;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+HSPLjava/util/stream/ReferencePipeline$4$1;-><init>(Ljava/util/stream/ReferencePipeline$4;Ljava/util/stream/Sink;)V
+HSPLjava/util/stream/ReferencePipeline$4$1;->accept(Ljava/lang/Object;)V+]Ljava/util/function/ToIntFunction;megamorphic_types]Ljava/util/stream/Sink;Ljava/util/stream/Nodes$IntFixedNodeBuilder;,Ljava/util/stream/Nodes$IntSpinedNodeBuilder;,Ljava/util/stream/IntPipeline$4$1;,Ljava/util/stream/ReduceOps$5ReducingSink;,Ljava/util/stream/ReduceOps$6ReducingSink;,Ljava/util/stream/IntPipeline$9$1;
+HSPLjava/util/stream/ReferencePipeline$4;-><init>(Ljava/util/stream/ReferencePipeline;Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;ILjava/util/function/ToIntFunction;)V
+HSPLjava/util/stream/ReferencePipeline$4;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+HSPLjava/util/stream/ReferencePipeline$5$1;-><init>(Ljava/util/stream/ReferencePipeline$5;Ljava/util/stream/Sink;)V
+HSPLjava/util/stream/ReferencePipeline$5$1;->accept(Ljava/lang/Object;)V+]Ljava/util/function/ToLongFunction;missing_types]Ljava/util/stream/Sink;Ljava/util/stream/ReduceOps$8ReducingSink;,Ljava/util/stream/Nodes$LongFixedNodeBuilder;,Ljava/util/stream/LongPipeline$8$1;,Ljava/util/stream/ReduceOps$9ReducingSink;
+HSPLjava/util/stream/ReferencePipeline$5;-><init>(Ljava/util/stream/ReferencePipeline;Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;ILjava/util/function/ToLongFunction;)V
+HSPLjava/util/stream/ReferencePipeline$5;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+HSPLjava/util/stream/ReferencePipeline$6$1;-><init>(Ljava/util/stream/ReferencePipeline$6;Ljava/util/stream/Sink;)V
+HSPLjava/util/stream/ReferencePipeline$6$1;->accept(Ljava/lang/Object;)V+]Ljava/util/stream/Sink;Ljava/util/stream/SortedOps$DoubleSortingSink;,Ljava/util/stream/ReduceOps$13ReducingSink;
+HSPLjava/util/stream/ReferencePipeline$6;-><init>(Ljava/util/stream/ReferencePipeline;Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;ILjava/util/function/ToDoubleFunction;)V
+HSPLjava/util/stream/ReferencePipeline$6;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+HSPLjava/util/stream/ReferencePipeline$Head;-><init>(Ljava/util/Spliterator;IZ)V
+HSPLjava/util/stream/ReferencePipeline$Head;->forEach(Ljava/util/function/Consumer;)V+]Ljava/util/Spliterator;megamorphic_types]Ljava/util/stream/ReferencePipeline$Head;Ljava/util/stream/ReferencePipeline$Head;
+HSPLjava/util/stream/ReferencePipeline$StatefulOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+HSPLjava/util/stream/ReferencePipeline$StatefulOp;->opIsStateful()Z
+HSPLjava/util/stream/ReferencePipeline$StatelessOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+HSPLjava/util/stream/ReferencePipeline$StatelessOp;->opIsStateful()Z
+HSPLjava/util/stream/ReferencePipeline;-><init>(Ljava/util/Spliterator;IZ)V
+HSPLjava/util/stream/ReferencePipeline;-><init>(Ljava/util/stream/AbstractPipeline;I)V
+HSPLjava/util/stream/ReferencePipeline;->anyMatch(Ljava/util/function/Predicate;)Z+]Ljava/util/stream/ReferencePipeline;Ljava/util/stream/ReferencePipeline$Head;,Ljava/util/stream/ReferencePipeline$7;,Ljava/util/stream/ReferencePipeline$3;,Ljava/util/stream/ReferencePipeline$2;]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLjava/util/stream/ReferencePipeline;->collect(Ljava/util/stream/Collector;)Ljava/lang/Object;+]Ljava/util/stream/Collector;Ljava/util/stream/Collectors$CollectorImpl;]Ljava/util/function/Function;missing_types]Ljava/util/stream/ReferencePipeline;megamorphic_types]Ljava/util/Set;Ljava/util/Collections$UnmodifiableSet;,Ljava/util/Collections$EmptySet;
+HSPLjava/util/stream/ReferencePipeline;->count()J+]Ljava/util/stream/ReferencePipeline;Ljava/util/stream/ReferencePipeline$3;,Ljava/util/stream/ReferencePipeline$2;,Ljava/util/stream/DistinctOps$1;]Ljava/util/stream/LongStream;Ljava/util/stream/ReferencePipeline$5;
+HSPLjava/util/stream/ReferencePipeline;->distinct()Ljava/util/stream/Stream;
+HSPLjava/util/stream/ReferencePipeline;->filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
+HSPLjava/util/stream/ReferencePipeline;->findAny()Ljava/util/Optional;+]Ljava/util/stream/ReferencePipeline;Ljava/util/stream/ReferencePipeline$2;,Ljava/util/stream/ReferencePipeline$3;
+HSPLjava/util/stream/ReferencePipeline;->findFirst()Ljava/util/Optional;+]Ljava/util/stream/ReferencePipeline;Ljava/util/stream/ReferencePipeline$2;,Ljava/util/stream/SliceOps$1;,Ljava/util/stream/SortedOps$OfRef;,Ljava/util/stream/ReferencePipeline$Head;
+HSPLjava/util/stream/ReferencePipeline;->flatMap(Ljava/util/function/Function;)Ljava/util/stream/Stream;
+HSPLjava/util/stream/ReferencePipeline;->forEach(Ljava/util/function/Consumer;)V+]Ljava/util/stream/ReferencePipeline;Ljava/util/stream/ReferencePipeline$3;,Ljava/util/stream/ReferencePipeline$2;,Ljava/util/stream/ReferencePipeline$7;,Ljava/util/stream/SortedOps$OfRef;,Ljava/util/stream/ReferencePipeline$Head;,Ljava/util/stream/IntPipeline$4;
+HSPLjava/util/stream/ReferencePipeline;->forEachWithCancel(Ljava/util/Spliterator;Ljava/util/stream/Sink;)V+]Ljava/util/Spliterator;megamorphic_types]Ljava/util/stream/Sink;megamorphic_types
+HSPLjava/util/stream/ReferencePipeline;->lambda$count$2(Ljava/lang/Object;)J
+HSPLjava/util/stream/ReferencePipeline;->makeNodeBuilder(JLjava/util/function/IntFunction;)Ljava/util/stream/Node$Builder;
+HSPLjava/util/stream/ReferencePipeline;->map(Ljava/util/function/Function;)Ljava/util/stream/Stream;
+HSPLjava/util/stream/ReferencePipeline;->mapToDouble(Ljava/util/function/ToDoubleFunction;)Ljava/util/stream/DoubleStream;
+HSPLjava/util/stream/ReferencePipeline;->mapToInt(Ljava/util/function/ToIntFunction;)Ljava/util/stream/IntStream;
+HSPLjava/util/stream/ReferencePipeline;->mapToLong(Ljava/util/function/ToLongFunction;)Ljava/util/stream/LongStream;
+HSPLjava/util/stream/ReferencePipeline;->max(Ljava/util/Comparator;)Ljava/util/Optional;+]Ljava/util/stream/ReferencePipeline;Ljava/util/stream/ReferencePipeline$2;,Ljava/util/stream/ReferencePipeline$Head;,Ljava/util/stream/ReferencePipeline$3;
+HSPLjava/util/stream/ReferencePipeline;->reduce(Ljava/util/function/BinaryOperator;)Ljava/util/Optional;+]Ljava/util/stream/ReferencePipeline;Ljava/util/stream/ReferencePipeline$Head;,Ljava/util/stream/ReferencePipeline$2;,Ljava/util/stream/ReferencePipeline$3;
+HSPLjava/util/stream/ReferencePipeline;->sorted()Ljava/util/stream/Stream;
+HSPLjava/util/stream/ReferencePipeline;->sorted(Ljava/util/Comparator;)Ljava/util/stream/Stream;
+HSPLjava/util/stream/ReferencePipeline;->toArray(Ljava/util/function/IntFunction;)[Ljava/lang/Object;+]Ljava/util/stream/Node;Ljava/util/stream/Nodes$FixedNodeBuilder;,Ljava/util/stream/Nodes$SpinedNodeBuilder;]Ljava/util/stream/ReferencePipeline;Ljava/util/stream/ReferencePipeline$Head;,Ljava/util/stream/ReferencePipeline$3;,Ljava/util/stream/DistinctOps$1;,Ljava/util/stream/SortedOps$OfRef;,Ljava/util/stream/ReferencePipeline$2;
+HSPLjava/util/stream/ReferencePipeline;->wrap(Ljava/util/stream/PipelineHelper;Ljava/util/function/Supplier;Z)Ljava/util/Spliterator;
+HSPLjava/util/stream/Sink$ChainedInt;-><init>(Ljava/util/stream/Sink;)V
+HSPLjava/util/stream/Sink$ChainedInt;->begin(J)V+]Ljava/util/stream/Sink;megamorphic_types
+HSPLjava/util/stream/Sink$ChainedInt;->end()V+]Ljava/util/stream/Sink;megamorphic_types
+HSPLjava/util/stream/Sink$ChainedReference;-><init>(Ljava/util/stream/Sink;)V
+HSPLjava/util/stream/Sink$ChainedReference;->begin(J)V+]Ljava/util/stream/Sink;megamorphic_types
+HSPLjava/util/stream/Sink$ChainedReference;->cancellationRequested()Z+]Ljava/util/stream/Sink;megamorphic_types
+HSPLjava/util/stream/Sink$ChainedReference;->end()V+]Ljava/util/stream/Sink;megamorphic_types
+HSPLjava/util/stream/Sink;->begin(J)V
+HSPLjava/util/stream/Sink;->end()V
+HSPLjava/util/stream/SortedOps$AbstractRefSortingSink;-><init>(Ljava/util/stream/Sink;Ljava/util/Comparator;)V
+HSPLjava/util/stream/SortedOps$OfRef;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/Comparator;)V
+HSPLjava/util/stream/SortedOps$OfRef;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;+]Ljava/util/stream/StreamOpFlag;Ljava/util/stream/StreamOpFlag;
+HSPLjava/util/stream/SortedOps$RefSortingSink;-><init>(Ljava/util/stream/Sink;Ljava/util/Comparator;)V
+HSPLjava/util/stream/SortedOps$RefSortingSink;->begin(J)V
+HSPLjava/util/stream/SortedOps$RefSortingSink;->end()V+]Ljava/util/stream/Sink;Ljava/util/stream/ReferencePipeline$3$1;,Ljava/util/stream/ReduceOps$3ReducingSink;,Ljava/util/stream/Nodes$SpinedNodeBuilder;]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLjava/util/stream/SortedOps;->makeRef(Ljava/util/stream/AbstractPipeline;Ljava/util/Comparator;)Ljava/util/stream/Stream;
+HSPLjava/util/stream/Stream;->builder()Ljava/util/stream/Stream$Builder;
+HSPLjava/util/stream/Stream;->concat(Ljava/util/stream/Stream;Ljava/util/stream/Stream;)Ljava/util/stream/Stream;+]Ljava/util/stream/Stream;Ljava/util/stream/ReferencePipeline$Head;,Ljava/util/stream/ReferencePipeline$3;,Ljava/util/stream/ReferencePipeline$7;
+HSPLjava/util/stream/Stream;->of([Ljava/lang/Object;)Ljava/util/stream/Stream;
+HSPLjava/util/stream/StreamOpFlag;->combineOpFlags(II)I
+HSPLjava/util/stream/StreamOpFlag;->fromCharacteristics(Ljava/util/Spliterator;)I+]Ljava/util/Spliterator;megamorphic_types
+HSPLjava/util/stream/StreamOpFlag;->getMask(I)I
+HSPLjava/util/stream/StreamOpFlag;->isKnown(I)Z
+HSPLjava/util/stream/StreamSupport;->intStream(Ljava/util/Spliterator$OfInt;Z)Ljava/util/stream/IntStream;
+HSPLjava/util/stream/StreamSupport;->stream(Ljava/util/Spliterator;Z)Ljava/util/stream/Stream;
+HSPLjava/util/stream/Streams$2;-><init>(Ljava/util/stream/BaseStream;Ljava/util/stream/BaseStream;)V
+HSPLjava/util/stream/Streams$ConcatSpliterator$OfRef;-><init>(Ljava/util/Spliterator;Ljava/util/Spliterator;)V
+HSPLjava/util/stream/Streams$ConcatSpliterator;-><init>(Ljava/util/Spliterator;Ljava/util/Spliterator;)V+]Ljava/util/Spliterator;megamorphic_types
+HSPLjava/util/stream/Streams$ConcatSpliterator;->characteristics()I+]Ljava/util/Spliterator;megamorphic_types
+HSPLjava/util/stream/Streams$RangeIntSpliterator;-><init>(III)V
+HSPLjava/util/stream/Streams$RangeIntSpliterator;-><init>(IIZ)V
+HSPLjava/util/stream/Streams$RangeIntSpliterator;->characteristics()I
+HSPLjava/util/stream/Streams$RangeIntSpliterator;->estimateSize()J
+HSPLjava/util/stream/Streams$RangeIntSpliterator;->forEachRemaining(Ljava/util/function/IntConsumer;)V+]Ljava/util/function/IntConsumer;missing_types
+HSPLjava/util/stream/Streams$RangeIntSpliterator;->getComparator()Ljava/util/Comparator;
+HSPLjava/util/stream/Streams;->composedClose(Ljava/util/stream/BaseStream;Ljava/util/stream/BaseStream;)Ljava/lang/Runnable;
+HSPLjava/util/stream/TerminalOp;->getOpFlags()I
+HSPLjava/util/zip/Adler32;-><init>()V
+HSPLjava/util/zip/Adler32;->getValue()J
+HSPLjava/util/zip/Adler32;->update([BII)V
+HSPLjava/util/zip/CRC32;-><init>()V
+HSPLjava/util/zip/CRC32;->getValue()J
+HSPLjava/util/zip/CRC32;->reset()V
+HSPLjava/util/zip/CRC32;->update(I)V
+HSPLjava/util/zip/CRC32;->update([B)V
+HSPLjava/util/zip/CRC32;->update([BII)V
+HSPLjava/util/zip/CheckedInputStream;-><init>(Ljava/io/InputStream;Ljava/util/zip/Checksum;)V
+HSPLjava/util/zip/CheckedInputStream;->read()I+]Ljava/io/InputStream;missing_types]Ljava/util/zip/Checksum;Ljava/util/zip/CRC32;
+HSPLjava/util/zip/CheckedInputStream;->read([BII)I+]Ljava/io/InputStream;missing_types]Ljava/util/zip/Checksum;Ljava/util/zip/CRC32;,Ljava/util/zip/Adler32;
+HSPLjava/util/zip/Deflater;-><init>()V
+HSPLjava/util/zip/Deflater;-><init>(IZ)V+]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/util/zip/Deflater;->deflate([BII)I+]Ljava/util/zip/Deflater;Ljava/util/zip/Deflater;
+HSPLjava/util/zip/Deflater;->deflate([BIII)I+]Ljava/util/zip/ZStreamRef;Ljava/util/zip/ZStreamRef;
+HSPLjava/util/zip/Deflater;->end()V+]Ljava/util/zip/ZStreamRef;Ljava/util/zip/ZStreamRef;]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/util/zip/Deflater;->ensureOpen()V+]Ljava/util/zip/ZStreamRef;Ljava/util/zip/ZStreamRef;
+HSPLjava/util/zip/Deflater;->finalize()V+]Ljava/util/zip/Deflater;Ljava/util/zip/Deflater;]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
+HSPLjava/util/zip/Deflater;->finish()V
+HSPLjava/util/zip/Deflater;->finished()Z
+HSPLjava/util/zip/Deflater;->getBytesRead()J
+HSPLjava/util/zip/Deflater;->getTotalIn()I+]Ljava/util/zip/Deflater;Ljava/util/zip/Deflater;
+HSPLjava/util/zip/Deflater;->needsInput()Z
+HSPLjava/util/zip/Deflater;->reset()V+]Ljava/util/zip/ZStreamRef;Ljava/util/zip/ZStreamRef;
+HSPLjava/util/zip/Deflater;->setInput([BII)V
+HSPLjava/util/zip/DeflaterOutputStream;-><init>(Ljava/io/OutputStream;)V
+HSPLjava/util/zip/DeflaterOutputStream;-><init>(Ljava/io/OutputStream;Ljava/util/zip/Deflater;)V
+HSPLjava/util/zip/DeflaterOutputStream;-><init>(Ljava/io/OutputStream;Ljava/util/zip/Deflater;IZ)V
+HSPLjava/util/zip/DeflaterOutputStream;-><init>(Ljava/io/OutputStream;Z)V
+HSPLjava/util/zip/DeflaterOutputStream;->close()V+]Ljava/util/zip/Deflater;Ljava/util/zip/Deflater;]Ljava/util/zip/DeflaterOutputStream;missing_types]Ljava/io/OutputStream;missing_types
+HSPLjava/util/zip/DeflaterOutputStream;->deflate()V+]Ljava/util/zip/Deflater;Ljava/util/zip/Deflater;]Ljava/io/OutputStream;missing_types
+HSPLjava/util/zip/DeflaterOutputStream;->finish()V+]Ljava/util/zip/Deflater;Ljava/util/zip/Deflater;]Ljava/util/zip/DeflaterOutputStream;Ljava/util/zip/DeflaterOutputStream;
+HSPLjava/util/zip/DeflaterOutputStream;->flush()V+]Ljava/io/OutputStream;missing_types
+HSPLjava/util/zip/DeflaterOutputStream;->write([BII)V+]Ljava/util/zip/Deflater;Ljava/util/zip/Deflater;]Ljava/util/zip/DeflaterOutputStream;missing_types
+HSPLjava/util/zip/GZIPInputStream$1;-><init>(Ljava/util/zip/GZIPInputStream;Ljava/io/InputStream;)V
+HSPLjava/util/zip/GZIPInputStream;-><init>(Ljava/io/InputStream;)V
+HSPLjava/util/zip/GZIPInputStream;-><init>(Ljava/io/InputStream;I)V+]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/GZIPInputStream;->close()V
+HSPLjava/util/zip/GZIPInputStream;->ensureOpen()V
+HSPLjava/util/zip/GZIPInputStream;->read([BII)I+]Ljava/util/zip/CRC32;Ljava/util/zip/CRC32;
+HSPLjava/util/zip/GZIPInputStream;->readHeader(Ljava/io/InputStream;)I+]Ljava/util/zip/CRC32;Ljava/util/zip/CRC32;
+HSPLjava/util/zip/GZIPInputStream;->readTrailer()Z+]Ljava/util/zip/CRC32;Ljava/util/zip/CRC32;]Ljava/io/InputStream;missing_types]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/GZIPInputStream;->readUByte(Ljava/io/InputStream;)I+]Ljava/io/InputStream;megamorphic_types
+HSPLjava/util/zip/GZIPInputStream;->readUInt(Ljava/io/InputStream;)J
+HSPLjava/util/zip/GZIPInputStream;->readUShort(Ljava/io/InputStream;)I
+HSPLjava/util/zip/GZIPInputStream;->skipBytes(Ljava/io/InputStream;I)V+]Ljava/io/InputStream;Ljava/util/zip/CheckedInputStream;
+HSPLjava/util/zip/GZIPOutputStream;-><init>(Ljava/io/OutputStream;)V
+HSPLjava/util/zip/GZIPOutputStream;-><init>(Ljava/io/OutputStream;IZ)V+]Ljava/util/zip/CRC32;Ljava/util/zip/CRC32;
+HSPLjava/util/zip/GZIPOutputStream;->finish()V+]Ljava/util/zip/Deflater;Ljava/util/zip/Deflater;]Ljava/io/OutputStream;missing_types
+HSPLjava/util/zip/GZIPOutputStream;->write([BII)V+]Ljava/util/zip/CRC32;Ljava/util/zip/CRC32;
+HSPLjava/util/zip/GZIPOutputStream;->writeHeader()V+]Ljava/io/OutputStream;missing_types
+HSPLjava/util/zip/GZIPOutputStream;->writeInt(I[BI)V
+HSPLjava/util/zip/GZIPOutputStream;->writeShort(I[BI)V
+HSPLjava/util/zip/GZIPOutputStream;->writeTrailer([BI)V+]Ljava/util/zip/CRC32;Ljava/util/zip/CRC32;]Ljava/util/zip/Deflater;Ljava/util/zip/Deflater;
+HSPLjava/util/zip/Inflater;-><init>()V
+HSPLjava/util/zip/Inflater;-><init>(Z)V+]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/util/zip/Inflater;->end()V+]Ljava/util/zip/ZStreamRef;Ljava/util/zip/ZStreamRef;]Ldalvik/system/CloseGuard;missing_types
+HSPLjava/util/zip/Inflater;->ended()Z+]Ljava/util/zip/ZStreamRef;Ljava/util/zip/ZStreamRef;
+HSPLjava/util/zip/Inflater;->ensureOpen()V+]Ljava/util/zip/ZStreamRef;Ljava/util/zip/ZStreamRef;
+HSPLjava/util/zip/Inflater;->finalize()V+]Ldalvik/system/CloseGuard;missing_types]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/Inflater;->finished()Z
+HSPLjava/util/zip/Inflater;->getBytesRead()J
+HSPLjava/util/zip/Inflater;->getBytesWritten()J
+HSPLjava/util/zip/Inflater;->getRemaining()I
+HSPLjava/util/zip/Inflater;->getTotalOut()I+]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/Inflater;->inflate([BII)I+]Ljava/util/zip/ZStreamRef;Ljava/util/zip/ZStreamRef;
+HSPLjava/util/zip/Inflater;->needsDictionary()Z
+HSPLjava/util/zip/Inflater;->needsInput()Z
+HSPLjava/util/zip/Inflater;->reset()V+]Ljava/util/zip/ZStreamRef;Ljava/util/zip/ZStreamRef;
+HSPLjava/util/zip/Inflater;->setInput([BII)V
+HSPLjava/util/zip/InflaterInputStream;-><init>(Ljava/io/InputStream;Ljava/util/zip/Inflater;I)V
+HSPLjava/util/zip/InflaterInputStream;->available()I+]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/InflaterInputStream;->close()V+]Ljava/io/InputStream;megamorphic_types]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/InflaterInputStream;->ensureOpen()V
+HSPLjava/util/zip/InflaterInputStream;->fill()V+]Ljava/util/zip/Inflater;missing_types]Ljava/io/InputStream;megamorphic_types
+HSPLjava/util/zip/InflaterInputStream;->read()I+]Ljava/util/zip/InflaterInputStream;Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;,Ljava/util/zip/ZipInputStream;,Ljava/util/zip/InflaterInputStream;,Ljava/util/zip/GZIPInputStream;
+HSPLjava/util/zip/InflaterInputStream;->read([BII)I+]Ljava/util/zip/InflaterInputStream;missing_types]Ljava/util/zip/Inflater;missing_types
+HSPLjava/util/zip/ZStreamRef;-><init>(J)V
+HSPLjava/util/zip/ZStreamRef;->address()J
+HSPLjava/util/zip/ZStreamRef;->clear()V
+HSPLjava/util/zip/ZipCoder;-><init>(Ljava/nio/charset/Charset;)V+]Ljava/nio/charset/Charset;Lcom/android/icu/charset/CharsetICU;
+HSPLjava/util/zip/ZipCoder;->decoder()Ljava/nio/charset/CharsetDecoder;+]Ljava/nio/charset/Charset;missing_types]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLjava/util/zip/ZipCoder;->encoder()Ljava/nio/charset/CharsetEncoder;+]Ljava/nio/charset/Charset;missing_types]Ljava/nio/charset/CharsetEncoder;missing_types
+HSPLjava/util/zip/ZipCoder;->get(Ljava/nio/charset/Charset;)Ljava/util/zip/ZipCoder;
+HSPLjava/util/zip/ZipCoder;->getBytes(Ljava/lang/String;)[B+]Ljava/lang/String;Ljava/lang/String;]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/nio/charset/CharsetEncoder;missing_types]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;
+HSPLjava/util/zip/ZipCoder;->isUTF8()Z
+HSPLjava/util/zip/ZipCoder;->toString([BI)Ljava/lang/String;+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLjava/util/zip/ZipEntry;-><init>()V
+HSPLjava/util/zip/ZipEntry;-><init>(Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/zip/ZipEntry;-><init>(Ljava/util/zip/ZipEntry;)V
+HSPLjava/util/zip/ZipEntry;->getCompressedSize()J
+HSPLjava/util/zip/ZipEntry;->getMethod()I
+HSPLjava/util/zip/ZipEntry;->getName()Ljava/lang/String;
+HSPLjava/util/zip/ZipEntry;->getSize()J
+HSPLjava/util/zip/ZipEntry;->isDirectory()Z+]Ljava/lang/String;Ljava/lang/String;
+HSPLjava/util/zip/ZipEntry;->setExtra0([BZ)V
+HSPLjava/util/zip/ZipFile$ZipEntryIterator;-><init>(Ljava/util/zip/ZipFile;)V
+HSPLjava/util/zip/ZipFile$ZipEntryIterator;->hasMoreElements()Z+]Ljava/util/zip/ZipFile$ZipEntryIterator;Ljava/util/zip/ZipFile$ZipEntryIterator;
+HSPLjava/util/zip/ZipFile$ZipEntryIterator;->hasNext()Z
+HSPLjava/util/zip/ZipFile$ZipEntryIterator;->next()Ljava/util/zip/ZipEntry;
+HSPLjava/util/zip/ZipFile$ZipEntryIterator;->nextElement()Ljava/lang/Object;+]Ljava/util/zip/ZipFile$ZipEntryIterator;Ljava/util/zip/ZipFile$ZipEntryIterator;
+HSPLjava/util/zip/ZipFile$ZipEntryIterator;->nextElement()Ljava/util/zip/ZipEntry;+]Ljava/util/zip/ZipFile$ZipEntryIterator;Ljava/util/zip/ZipFile$ZipEntryIterator;
+HSPLjava/util/zip/ZipFile$ZipFileInflaterInputStream;-><init>(Ljava/util/zip/ZipFile;Ljava/util/zip/ZipFile$ZipFileInputStream;Ljava/util/zip/Inflater;I)V
+HSPLjava/util/zip/ZipFile$ZipFileInflaterInputStream;->available()I+]Ljava/util/zip/ZipFile$ZipFileInputStream;Ljava/util/zip/ZipFile$ZipFileInputStream;]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/ZipFile$ZipFileInflaterInputStream;->close()V+]Ljava/util/Map;Ljava/util/WeakHashMap;
+HSPLjava/util/zip/ZipFile$ZipFileInflaterInputStream;->fill()V+]Ljava/io/InputStream;Ljava/util/zip/ZipFile$ZipFileInputStream;]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/ZipFile$ZipFileInflaterInputStream;->finalize()V+]Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;
+HSPLjava/util/zip/ZipFile$ZipFileInputStream;-><init>(Ljava/util/zip/ZipFile;J)V
+HSPLjava/util/zip/ZipFile$ZipFileInputStream;->available()I
+HSPLjava/util/zip/ZipFile$ZipFileInputStream;->close()V+]Ljava/util/Map;Ljava/util/WeakHashMap;
+HSPLjava/util/zip/ZipFile$ZipFileInputStream;->finalize()V+]Ljava/util/zip/ZipFile$ZipFileInputStream;Ljava/util/zip/ZipFile$ZipFileInputStream;
+HSPLjava/util/zip/ZipFile$ZipFileInputStream;->read()I+]Ljava/util/zip/ZipFile$ZipFileInputStream;Ljava/util/zip/ZipFile$ZipFileInputStream;
+HSPLjava/util/zip/ZipFile$ZipFileInputStream;->read([BII)I+]Ljava/util/zip/ZipFile$ZipFileInputStream;Ljava/util/zip/ZipFile$ZipFileInputStream;
+HSPLjava/util/zip/ZipFile$ZipFileInputStream;->size()J
+HSPLjava/util/zip/ZipFile;-><init>(Ljava/io/File;)V
+HSPLjava/util/zip/ZipFile;-><init>(Ljava/io/File;I)V
+HSPLjava/util/zip/ZipFile;-><init>(Ljava/io/File;ILjava/nio/charset/Charset;)V+]Ljava/io/File;Ljava/io/File;]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
+HSPLjava/util/zip/ZipFile;-><init>(Ljava/lang/String;)V
+HSPLjava/util/zip/ZipFile;->access$000(Ljava/util/zip/ZipFile;)Ljava/util/Map;
+HSPLjava/util/zip/ZipFile;->access$100(Ljava/util/zip/ZipFile;Ljava/util/zip/Inflater;)V
+HSPLjava/util/zip/ZipFile;->access$1000(JJ)V
+HSPLjava/util/zip/ZipFile;->access$1100(J)J
+HSPLjava/util/zip/ZipFile;->access$1200(J)J
+HSPLjava/util/zip/ZipFile;->access$1300(Ljava/util/zip/ZipFile;)V
+HSPLjava/util/zip/ZipFile;->access$1400(JJJ[BII)I
+HSPLjava/util/zip/ZipFile;->access$200(Ljava/util/zip/ZipFile;)V
+HSPLjava/util/zip/ZipFile;->access$300(Ljava/util/zip/ZipFile;)I
+HSPLjava/util/zip/ZipFile;->access$400(Ljava/util/zip/ZipFile;)J
+HSPLjava/util/zip/ZipFile;->access$500(JI)J
+HSPLjava/util/zip/ZipFile;->access$900(Ljava/util/zip/ZipFile;Ljava/lang/String;J)Ljava/util/zip/ZipEntry;
+HSPLjava/util/zip/ZipFile;->close()V+]Ljava/util/Deque;Ljava/util/ArrayDeque;]Ljava/util/Map;Ljava/util/WeakHashMap;,Ljava/util/HashMap;]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;]Ljava/io/InputStream;Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;
+HSPLjava/util/zip/ZipFile;->ensureOpen()V
+HSPLjava/util/zip/ZipFile;->ensureOpenOrZipException()V
+HSPLjava/util/zip/ZipFile;->entries()Ljava/util/Enumeration;
+HSPLjava/util/zip/ZipFile;->finalize()V+]Ljava/util/zip/ZipFile;Ljava/util/zip/ZipFile;]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
+HSPLjava/util/zip/ZipFile;->getEntry(Ljava/lang/String;)Ljava/util/zip/ZipEntry;+]Ljava/util/zip/ZipCoder;Ljava/util/zip/ZipCoder;
+HSPLjava/util/zip/ZipFile;->getInflater()Ljava/util/zip/Inflater;+]Ljava/util/Deque;Ljava/util/ArrayDeque;
+HSPLjava/util/zip/ZipFile;->getInputStream(Ljava/util/zip/ZipEntry;)Ljava/io/InputStream;+]Ljava/util/zip/ZipCoder;Ljava/util/zip/ZipCoder;]Ljava/util/Map;Ljava/util/WeakHashMap;
+HSPLjava/util/zip/ZipFile;->getZipEntry(Ljava/lang/String;J)Ljava/util/zip/ZipEntry;+]Ljava/util/zip/ZipEntry;Ljava/util/zip/ZipEntry;]Ljava/util/zip/ZipCoder;Ljava/util/zip/ZipCoder;
+HSPLjava/util/zip/ZipFile;->releaseInflater(Ljava/util/zip/Inflater;)V+]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/ZipInputStream;-><init>(Ljava/io/InputStream;)V
+HSPLjava/util/zip/ZipInputStream;-><init>(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
+HSPLjava/util/zip/ZipInputStream;->close()V
+HSPLjava/util/zip/ZipInputStream;->closeEntry()V+]Ljava/util/zip/ZipInputStream;Ljava/util/zip/ZipInputStream;
+HSPLjava/util/zip/ZipInputStream;->createZipEntry(Ljava/lang/String;)Ljava/util/zip/ZipEntry;
+HSPLjava/util/zip/ZipInputStream;->ensureOpen()V
+HSPLjava/util/zip/ZipInputStream;->getNextEntry()Ljava/util/zip/ZipEntry;+]Ljava/util/zip/CRC32;Ljava/util/zip/CRC32;]Ljava/util/zip/ZipInputStream;Ljava/util/zip/ZipInputStream;]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/ZipInputStream;->read([BII)I+]Ljava/util/zip/CRC32;Ljava/util/zip/CRC32;]Ljava/io/InputStream;Ljava/io/PushbackInputStream;
+HSPLjava/util/zip/ZipInputStream;->readEnd(Ljava/util/zip/ZipEntry;)V+]Ljava/util/zip/CRC32;Ljava/util/zip/CRC32;]Ljava/io/PushbackInputStream;Ljava/io/PushbackInputStream;]Ljava/util/zip/Inflater;Ljava/util/zip/Inflater;
+HSPLjava/util/zip/ZipInputStream;->readFully([BII)V+]Ljava/io/InputStream;Ljava/io/PushbackInputStream;
+HSPLjava/util/zip/ZipInputStream;->readLOC()Ljava/util/zip/ZipEntry;+]Ljava/util/zip/ZipEntry;Ljava/util/zip/ZipEntry;]Ljava/util/zip/ZipInputStream;Ljava/util/zip/ZipInputStream;]Ljava/util/zip/ZipCoder;Ljava/util/zip/ZipCoder;
+HSPLjava/util/zip/ZipUtils;->get16([BI)I
+HSPLjava/util/zip/ZipUtils;->get32([BI)J
+HSPLjava/util/zip/ZipUtils;->unixTimeToFileTime(J)Ljava/nio/file/attribute/FileTime;
+HSPLjavax/crypto/Cipher$CipherSpiAndProvider;-><init>(Ljavax/crypto/CipherSpi;Ljava/security/Provider;)V
+HSPLjavax/crypto/Cipher$InitParams;-><init>(Ljavax/crypto/Cipher$InitType;ILjava/security/Key;Ljava/security/SecureRandom;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/AlgorithmParameters;)V
+HSPLjavax/crypto/Cipher$SpiAndProviderUpdater;-><init>(Ljavax/crypto/Cipher;Ljava/security/Provider;Ljavax/crypto/CipherSpi;)V
+HSPLjavax/crypto/Cipher$SpiAndProviderUpdater;->setCipherSpiImplAndProvider(Ljavax/crypto/CipherSpi;Ljava/security/Provider;)V
+HSPLjavax/crypto/Cipher$SpiAndProviderUpdater;->updateAndGetSpiAndProvider(Ljavax/crypto/Cipher$InitParams;Ljavax/crypto/CipherSpi;Ljava/security/Provider;)Ljavax/crypto/Cipher$CipherSpiAndProvider;+]Ljavax/crypto/Cipher$SpiAndProviderUpdater;Ljavax/crypto/Cipher$SpiAndProviderUpdater;
+HSPLjavax/crypto/Cipher$Transform;-><init>(Ljava/lang/String;Ljavax/crypto/Cipher$NeedToSet;)V
+HSPLjavax/crypto/Cipher$Transform;->access$300(Ljavax/crypto/Cipher$Transform;)Ljava/lang/String;
+HSPLjavax/crypto/Cipher$Transform;->access$400(Ljavax/crypto/Cipher$Transform;)Ljavax/crypto/Cipher$NeedToSet;
+HSPLjavax/crypto/Cipher;-><init>(Ljavax/crypto/CipherSpi;Ljava/security/Provider;Ljava/lang/String;[Ljava/lang/String;)V
+HSPLjavax/crypto/Cipher;->access$002(Ljavax/crypto/Cipher;Ljavax/crypto/CipherSpi;)Ljavax/crypto/CipherSpi;
+HSPLjavax/crypto/Cipher;->access$102(Ljavax/crypto/Cipher;Ljava/security/Provider;)Ljava/security/Provider;
+HSPLjavax/crypto/Cipher;->access$200(Ljavax/crypto/Cipher;)[Ljava/lang/String;
+HSPLjavax/crypto/Cipher;->checkCipherState()V
+HSPLjavax/crypto/Cipher;->checkOpmode(I)V
+HSPLjavax/crypto/Cipher;->chooseProvider(Ljavax/crypto/Cipher$InitType;ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/AlgorithmParameters;Ljava/security/SecureRandom;)V+]Ljavax/crypto/Cipher$SpiAndProviderUpdater;Ljavax/crypto/Cipher$SpiAndProviderUpdater;
+HSPLjavax/crypto/Cipher;->createCipher(Ljava/lang/String;Ljava/security/Provider;)Ljavax/crypto/Cipher;
+HSPLjavax/crypto/Cipher;->doFinal()[B+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;]Ljavax/crypto/CipherSpi;Lcom/android/org/conscrypt/OpenSSLEvpCipherAES$AES$CBC$PKCS5Padding;,Lcom/android/org/conscrypt/OpenSSLEvpCipherAES$AES$CTR;,Landroid/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi$CBC$PKCS7Padding;
+HSPLjavax/crypto/Cipher;->doFinal([B)[B+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;]Ljavax/crypto/CipherSpi;megamorphic_types
+HSPLjavax/crypto/Cipher;->doFinal([BII)[B+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;]Ljavax/crypto/CipherSpi;missing_types
+HSPLjavax/crypto/Cipher;->doFinal([BII[BI)I+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;]Ljavax/crypto/CipherSpi;Lcom/android/org/conscrypt/OpenSSLEvpCipherAES$AES$CBC$PKCS5Padding;,Lcom/android/org/conscrypt/OpenSSLAeadCipherAES$GCM;
+HSPLjavax/crypto/Cipher;->getBlockSize()I+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;]Ljavax/crypto/CipherSpi;missing_types
+HSPLjavax/crypto/Cipher;->getIV()[B+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;]Ljavax/crypto/CipherSpi;missing_types
+HSPLjavax/crypto/Cipher;->getInstance(Ljava/lang/String;)Ljavax/crypto/Cipher;
+HSPLjavax/crypto/Cipher;->getInstance(Ljava/lang/String;Ljava/security/Provider;)Ljavax/crypto/Cipher;
+HSPLjavax/crypto/Cipher;->getOutputSize(I)I+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;]Ljavax/crypto/CipherSpi;missing_types
+HSPLjavax/crypto/Cipher;->init(ILjava/security/Key;)V+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;
+HSPLjavax/crypto/Cipher;->init(ILjava/security/Key;Ljava/security/SecureRandom;)V
+HSPLjavax/crypto/Cipher;->init(ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;)V+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;
+HSPLjavax/crypto/Cipher;->init(ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)V
+HSPLjavax/crypto/Cipher;->matchAttribute(Ljava/security/Provider$Service;Ljava/lang/String;Ljava/lang/String;)Z+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;
+HSPLjavax/crypto/Cipher;->tokenizeTransformation(Ljava/lang/String;)[Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/StringTokenizer;Ljava/util/StringTokenizer;
+HSPLjavax/crypto/Cipher;->tryCombinations(Ljavax/crypto/Cipher$InitParams;Ljava/security/Provider;[Ljava/lang/String;)Ljavax/crypto/Cipher$CipherSpiAndProvider;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/security/Provider$Service;missing_types]Ljava/security/Provider;megamorphic_types]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLjavax/crypto/Cipher;->tryTransformWithProvider(Ljavax/crypto/Cipher$InitParams;[Ljava/lang/String;Ljavax/crypto/Cipher$NeedToSet;Ljava/security/Provider$Service;)Ljavax/crypto/Cipher$CipherSpiAndProvider;+]Ljava/security/Provider$Service;missing_types]Ljavax/crypto/Cipher$InitType;Ljavax/crypto/Cipher$InitType;]Ljavax/crypto/CipherSpi;megamorphic_types
+HSPLjavax/crypto/Cipher;->unwrap([BLjava/lang/String;I)Ljava/security/Key;+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;]Ljavax/crypto/CipherSpi;Landroid/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi$GCM$NoPadding;
+HSPLjavax/crypto/Cipher;->updateAAD([B)V+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;
+HSPLjavax/crypto/Cipher;->updateAAD([BII)V+]Ljavax/crypto/Cipher;Ljavax/crypto/Cipher;]Ljavax/crypto/CipherSpi;missing_types
+HSPLjavax/crypto/Cipher;->updateProviderIfNeeded()V+]Ljavax/crypto/Cipher$SpiAndProviderUpdater;Ljavax/crypto/Cipher$SpiAndProviderUpdater;
+HSPLjavax/crypto/CipherSpi;-><init>()V
+HSPLjavax/crypto/JarVerifier;-><init>(Ljava/net/URL;Z)V
+HSPLjavax/crypto/JarVerifier;->verify()V
+HSPLjavax/crypto/JceSecurity$1;-><init>(Ljava/lang/Class;)V
+HSPLjavax/crypto/JceSecurity$1;->run()Ljava/lang/Object;
+HSPLjavax/crypto/JceSecurity$1;->run()Ljava/net/URL;
+HSPLjavax/crypto/JceSecurity;->access$000()Ljava/net/URL;
+HSPLjavax/crypto/JceSecurity;->canUseProvider(Ljava/security/Provider;)Z
+HSPLjavax/crypto/JceSecurity;->getCodeBase(Ljava/lang/Class;)Ljava/net/URL;
+HSPLjavax/crypto/JceSecurity;->getVerificationResult(Ljava/security/Provider;)Ljava/lang/Exception;+]Ljava/util/Map;Ljava/util/IdentityHashMap;
+HSPLjavax/crypto/JceSecurity;->verifyProviderJar(Ljava/net/URL;)V
+HSPLjavax/crypto/KeyGenerator;-><init>(Ljava/lang/String;)V+]Ljava/util/List;Lsun/security/jca/ProviderList$ServiceList;
+HSPLjavax/crypto/KeyGenerator;->generateKey()Ljavax/crypto/SecretKey;+]Ljavax/crypto/KeyGeneratorSpi;Lcom/android/org/conscrypt/KeyGeneratorImpl$AES;
+HSPLjavax/crypto/KeyGenerator;->getInstance(Ljava/lang/String;)Ljavax/crypto/KeyGenerator;
+HSPLjavax/crypto/KeyGenerator;->init(ILjava/security/SecureRandom;)V
+HSPLjavax/crypto/KeyGenerator;->nextSpi(Ljavax/crypto/KeyGeneratorSpi;Z)Ljavax/crypto/KeyGeneratorSpi;+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/util/Iterator;Lsun/security/jca/ProviderList$ServiceList$1;
+HSPLjavax/crypto/KeyGeneratorSpi;-><init>()V
+HSPLjavax/crypto/Mac;-><init>(Ljava/lang/String;)V
+HSPLjavax/crypto/Mac;->chooseFirstProvider()V+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/util/List;Lsun/security/jca/ProviderList$ServiceList;]Ljava/util/Iterator;Lsun/security/jca/ProviderList$ServiceList$1;
+HSPLjavax/crypto/Mac;->chooseProvider(Ljava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;)V+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/util/List;Lsun/security/jca/ProviderList$ServiceList;]Ljavax/crypto/MacSpi;missing_types]Ljava/util/Iterator;Lsun/security/jca/ProviderList$ServiceList$1;
+HSPLjavax/crypto/Mac;->doFinal()[B+]Ljavax/crypto/MacSpi;missing_types]Ljavax/crypto/Mac;Ljavax/crypto/Mac;
+HSPLjavax/crypto/Mac;->doFinal([B)[B+]Ljavax/crypto/Mac;Ljavax/crypto/Mac;
+HSPLjavax/crypto/Mac;->doFinal([BI)V+]Ljavax/crypto/Mac;Ljavax/crypto/Mac;
+HSPLjavax/crypto/Mac;->getAlgorithm()Ljava/lang/String;
+HSPLjavax/crypto/Mac;->getInstance(Ljava/lang/String;)Ljavax/crypto/Mac;+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/util/List;Lsun/security/jca/ProviderList$ServiceList;]Ljava/util/Iterator;Lsun/security/jca/ProviderList$ServiceList$1;
+HSPLjavax/crypto/Mac;->getMacLength()I+]Ljavax/crypto/Mac;Ljavax/crypto/Mac;]Ljavax/crypto/MacSpi;missing_types
+HSPLjavax/crypto/Mac;->init(Ljava/security/Key;)V+]Ljavax/crypto/MacSpi;Lcom/android/org/conscrypt/OpenSSLMac$HmacSHA256;
+HSPLjavax/crypto/Mac;->update(B)V+]Ljavax/crypto/Mac;Ljavax/crypto/Mac;]Ljavax/crypto/MacSpi;missing_types
+HSPLjavax/crypto/Mac;->update([B)V+]Ljavax/crypto/MacSpi;missing_types]Ljavax/crypto/Mac;Ljavax/crypto/Mac;
+HSPLjavax/crypto/Mac;->update([BII)V+]Ljavax/crypto/Mac;Ljavax/crypto/Mac;]Ljavax/crypto/MacSpi;missing_types
+HSPLjavax/crypto/MacSpi;-><init>()V
+HSPLjavax/crypto/SecretKeyFactory;-><init>(Ljava/lang/String;)V+]Ljava/util/List;Lsun/security/jca/ProviderList$ServiceList;
+HSPLjavax/crypto/SecretKeyFactory;->generateSecret(Ljava/security/spec/KeySpec;)Ljavax/crypto/SecretKey;+]Ljavax/crypto/SecretKeyFactorySpi;Lcom/android/org/bouncycastle/jcajce/provider/symmetric/AES$PBEWithMD5And128BitAESCBCOpenSSL;,Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2$PBKDF2WithHmacSHA1UTF8;
+HSPLjavax/crypto/SecretKeyFactory;->getInstance(Ljava/lang/String;)Ljavax/crypto/SecretKeyFactory;
+HSPLjavax/crypto/SecretKeyFactory;->nextSpi(Ljavax/crypto/SecretKeyFactorySpi;)Ljavax/crypto/SecretKeyFactorySpi;+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/util/Iterator;Lsun/security/jca/ProviderList$ServiceList$1;
+HSPLjavax/crypto/SecretKeyFactorySpi;-><init>()V
+HSPLjavax/crypto/spec/GCMParameterSpec;-><init>(I[B)V
+HSPLjavax/crypto/spec/GCMParameterSpec;-><init>(I[BII)V
+HSPLjavax/crypto/spec/GCMParameterSpec;->getIV()[B+][B[B
+HSPLjavax/crypto/spec/GCMParameterSpec;->getTLen()I
+HSPLjavax/crypto/spec/GCMParameterSpec;->init(I[BII)V
+HSPLjavax/crypto/spec/IvParameterSpec;-><init>([B)V
+HSPLjavax/crypto/spec/IvParameterSpec;-><init>([BII)V
+HSPLjavax/crypto/spec/IvParameterSpec;->getIV()[B+][B[B
+HSPLjavax/crypto/spec/PBEKeySpec;-><init>([C[BII)V+][B[B][C[C
+HSPLjavax/crypto/spec/PBEKeySpec;->getIterationCount()I
+HSPLjavax/crypto/spec/PBEKeySpec;->getKeyLength()I
+HSPLjavax/crypto/spec/PBEKeySpec;->getPassword()[C+][C[C
+HSPLjavax/crypto/spec/PBEKeySpec;->getSalt()[B+][B[B
+HSPLjavax/crypto/spec/SecretKeySpec;-><init>([BLjava/lang/String;)V+][B[B
+HSPLjavax/crypto/spec/SecretKeySpec;->getAlgorithm()Ljava/lang/String;
+HSPLjavax/crypto/spec/SecretKeySpec;->getEncoded()[B+][B[B
+HSPLjavax/crypto/spec/SecretKeySpec;->getFormat()Ljava/lang/String;
+HSPLjavax/net/DefaultSocketFactory;-><init>()V
+HSPLjavax/net/DefaultSocketFactory;->createSocket()Ljava/net/Socket;
+HSPLjavax/net/DefaultSocketFactory;->createSocket(Ljava/net/InetAddress;I)Ljava/net/Socket;
+HSPLjavax/net/ServerSocketFactory;-><init>()V
+HSPLjavax/net/SocketFactory;-><init>()V
+HSPLjavax/net/SocketFactory;->getDefault()Ljavax/net/SocketFactory;
+HSPLjavax/net/ssl/ExtendedSSLSession;-><init>()V
+HSPLjavax/net/ssl/HttpsURLConnection$NoPreloadHolder;-><clinit>()V
+HSPLjavax/net/ssl/HttpsURLConnection;-><init>(Ljava/net/URL;)V
+HSPLjavax/net/ssl/HttpsURLConnection;->getDefaultHostnameVerifier()Ljavax/net/ssl/HostnameVerifier;
+HSPLjavax/net/ssl/HttpsURLConnection;->getDefaultSSLSocketFactory()Ljavax/net/ssl/SSLSocketFactory;
+HSPLjavax/net/ssl/HttpsURLConnection;->setDefaultHostnameVerifier(Ljavax/net/ssl/HostnameVerifier;)V
+HSPLjavax/net/ssl/HttpsURLConnection;->setDefaultSSLSocketFactory(Ljavax/net/ssl/SSLSocketFactory;)V
+HSPLjavax/net/ssl/KeyManagerFactory$1;-><init>()V
+HSPLjavax/net/ssl/KeyManagerFactory$1;->run()Ljava/lang/Object;
+HSPLjavax/net/ssl/KeyManagerFactory$1;->run()Ljava/lang/String;
+HSPLjavax/net/ssl/KeyManagerFactory;-><init>(Ljavax/net/ssl/KeyManagerFactorySpi;Ljava/security/Provider;Ljava/lang/String;)V
+HSPLjavax/net/ssl/KeyManagerFactory;->getDefaultAlgorithm()Ljava/lang/String;
+HSPLjavax/net/ssl/KeyManagerFactory;->getInstance(Ljava/lang/String;)Ljavax/net/ssl/KeyManagerFactory;
+HSPLjavax/net/ssl/KeyManagerFactory;->getKeyManagers()[Ljavax/net/ssl/KeyManager;
+HSPLjavax/net/ssl/KeyManagerFactory;->init(Ljava/security/KeyStore;[C)V
+HSPLjavax/net/ssl/KeyManagerFactorySpi;-><init>()V
+HSPLjavax/net/ssl/SNIHostName;-><init>(Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjavax/net/ssl/SNIHostName;->checkHostName()V+]Ljava/lang/String;Ljava/lang/String;
+HSPLjavax/net/ssl/SNIHostName;->getAsciiName()Ljava/lang/String;
+HSPLjavax/net/ssl/SNIServerName;-><init>(I[B)V+][B[B
+HSPLjavax/net/ssl/SNIServerName;->getType()I
+HSPLjavax/net/ssl/SSLContext;-><init>(Ljavax/net/ssl/SSLContextSpi;Ljava/security/Provider;Ljava/lang/String;)V
+HSPLjavax/net/ssl/SSLContext;->getDefault()Ljavax/net/ssl/SSLContext;
+HSPLjavax/net/ssl/SSLContext;->getInstance(Ljava/lang/String;)Ljavax/net/ssl/SSLContext;
+HSPLjavax/net/ssl/SSLContext;->getInstance(Ljava/lang/String;Ljava/security/Provider;)Ljavax/net/ssl/SSLContext;
+HSPLjavax/net/ssl/SSLContext;->getServerSocketFactory()Ljavax/net/ssl/SSLServerSocketFactory;
+HSPLjavax/net/ssl/SSLContext;->getSocketFactory()Ljavax/net/ssl/SSLSocketFactory;+]Ljavax/net/ssl/SSLContextSpi;missing_types
+HSPLjavax/net/ssl/SSLContext;->init([Ljavax/net/ssl/KeyManager;[Ljavax/net/ssl/TrustManager;Ljava/security/SecureRandom;)V+]Ljavax/net/ssl/SSLContextSpi;missing_types
+HSPLjavax/net/ssl/SSLContext;->setDefault(Ljavax/net/ssl/SSLContext;)V
+HSPLjavax/net/ssl/SSLContextSpi;-><init>()V
+HSPLjavax/net/ssl/SSLEngine;-><init>()V
+HSPLjavax/net/ssl/SSLEngine;->getSSLParameters()Ljavax/net/ssl/SSLParameters;+]Ljavax/net/ssl/SSLParameters;Ljavax/net/ssl/SSLParameters;]Ljavax/net/ssl/SSLEngine;missing_types
+HSPLjavax/net/ssl/SSLEngine;->setSSLParameters(Ljavax/net/ssl/SSLParameters;)V+]Ljavax/net/ssl/SSLParameters;Ljavax/net/ssl/SSLParameters;]Ljavax/net/ssl/SSLEngine;missing_types
+HSPLjavax/net/ssl/SSLEngine;->wrap([Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)Ljavax/net/ssl/SSLEngineResult;+]Ljavax/net/ssl/SSLEngine;missing_types
+HSPLjavax/net/ssl/SSLEngineResult$HandshakeStatus;->values()[Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;+][Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;[Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;
+HSPLjavax/net/ssl/SSLEngineResult$Status;->values()[Ljavax/net/ssl/SSLEngineResult$Status;+][Ljavax/net/ssl/SSLEngineResult$Status;[Ljavax/net/ssl/SSLEngineResult$Status;
+HSPLjavax/net/ssl/SSLEngineResult;-><init>(Ljavax/net/ssl/SSLEngineResult$Status;Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;II)V
+HSPLjavax/net/ssl/SSLEngineResult;->bytesConsumed()I
+HSPLjavax/net/ssl/SSLEngineResult;->bytesProduced()I
+HSPLjavax/net/ssl/SSLEngineResult;->getHandshakeStatus()Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;
+HSPLjavax/net/ssl/SSLEngineResult;->getStatus()Ljavax/net/ssl/SSLEngineResult$Status;
+HSPLjavax/net/ssl/SSLException;-><init>(Ljava/lang/String;)V
+HSPLjavax/net/ssl/SSLParameters;-><init>()V
+HSPLjavax/net/ssl/SSLParameters;->clone([Ljava/lang/String;)[Ljava/lang/String;+][Ljava/lang/String;[Ljava/lang/String;
+HSPLjavax/net/ssl/SSLParameters;->getApplicationProtocols()[Ljava/lang/String;+][Ljava/lang/String;[Ljava/lang/String;
+HSPLjavax/net/ssl/SSLParameters;->getCipherSuites()[Ljava/lang/String;
+HSPLjavax/net/ssl/SSLParameters;->getEndpointIdentificationAlgorithm()Ljava/lang/String;
+HSPLjavax/net/ssl/SSLParameters;->getNeedClientAuth()Z
+HSPLjavax/net/ssl/SSLParameters;->getProtocols()[Ljava/lang/String;
+HSPLjavax/net/ssl/SSLParameters;->getServerNames()Ljava/util/List;+]Ljava/util/Map;Ljava/util/LinkedHashMap;
+HSPLjavax/net/ssl/SSLParameters;->getUseCipherSuitesOrder()Z
+HSPLjavax/net/ssl/SSLParameters;->getWantClientAuth()Z
+HSPLjavax/net/ssl/SSLParameters;->setApplicationProtocols([Ljava/lang/String;)V+][Ljava/lang/String;[Ljava/lang/String;
+HSPLjavax/net/ssl/SSLParameters;->setCipherSuites([Ljava/lang/String;)V
+HSPLjavax/net/ssl/SSLParameters;->setEndpointIdentificationAlgorithm(Ljava/lang/String;)V
+HSPLjavax/net/ssl/SSLParameters;->setProtocols([Ljava/lang/String;)V
+HSPLjavax/net/ssl/SSLParameters;->setServerNames(Ljava/util/List;)V+]Ljavax/net/ssl/SNIServerName;Ljavax/net/ssl/SNIHostName;]Ljava/util/List;Ljava/util/Collections$SingletonList;]Ljava/util/Map;Ljava/util/LinkedHashMap;]Ljava/util/Iterator;Ljava/util/Collections$1;
+HSPLjavax/net/ssl/SSLParameters;->setUseCipherSuitesOrder(Z)V
+HSPLjavax/net/ssl/SSLServerSocketFactory;-><init>()V
+HSPLjavax/net/ssl/SSLServerSocketFactory;->getDefault()Ljavax/net/ServerSocketFactory;
+HSPLjavax/net/ssl/SSLServerSocketFactory;->log(Ljava/lang/String;)V
+HSPLjavax/net/ssl/SSLSocket;-><init>()V
+HSPLjavax/net/ssl/SSLSocket;->getSSLParameters()Ljavax/net/ssl/SSLParameters;+]Ljavax/net/ssl/SSLParameters;Ljavax/net/ssl/SSLParameters;
+HSPLjavax/net/ssl/SSLSocket;->setSSLParameters(Ljavax/net/ssl/SSLParameters;)V+]Ljavax/net/ssl/SSLParameters;Ljavax/net/ssl/SSLParameters;
+HSPLjavax/net/ssl/SSLSocketFactory$1;-><init>(Ljava/lang/String;)V
+HSPLjavax/net/ssl/SSLSocketFactory$1;->run()Ljava/lang/Object;
+HSPLjavax/net/ssl/SSLSocketFactory$1;->run()Ljava/lang/String;
+HSPLjavax/net/ssl/SSLSocketFactory;-><init>()V
+HSPLjavax/net/ssl/SSLSocketFactory;->getDefault()Ljavax/net/SocketFactory;
+HSPLjavax/net/ssl/SSLSocketFactory;->getSecurityProperty(Ljava/lang/String;)Ljava/lang/String;
+HSPLjavax/net/ssl/SSLSocketFactory;->log(Ljava/lang/String;)V
+HSPLjavax/net/ssl/TrustManagerFactory$1;-><init>()V
+HSPLjavax/net/ssl/TrustManagerFactory$1;->run()Ljava/lang/Object;+]Ljavax/net/ssl/TrustManagerFactory$1;Ljavax/net/ssl/TrustManagerFactory$1;
+HSPLjavax/net/ssl/TrustManagerFactory$1;->run()Ljava/lang/String;
+HSPLjavax/net/ssl/TrustManagerFactory;-><init>(Ljavax/net/ssl/TrustManagerFactorySpi;Ljava/security/Provider;Ljava/lang/String;)V
+HSPLjavax/net/ssl/TrustManagerFactory;->getDefaultAlgorithm()Ljava/lang/String;
+HSPLjavax/net/ssl/TrustManagerFactory;->getInstance(Ljava/lang/String;)Ljavax/net/ssl/TrustManagerFactory;
+HSPLjavax/net/ssl/TrustManagerFactory;->getTrustManagers()[Ljavax/net/ssl/TrustManager;+]Ljavax/net/ssl/TrustManagerFactorySpi;missing_types
+HSPLjavax/net/ssl/TrustManagerFactory;->init(Ljava/security/KeyStore;)V+]Ljavax/net/ssl/TrustManagerFactorySpi;missing_types
+HSPLjavax/net/ssl/TrustManagerFactorySpi;-><init>()V
+HSPLjavax/net/ssl/X509ExtendedKeyManager;-><init>()V
+HSPLjavax/net/ssl/X509ExtendedTrustManager;-><init>()V
+HSPLjavax/security/auth/x500/X500Principal;-><init>(Ljava/lang/String;)V
+HSPLjavax/security/auth/x500/X500Principal;-><init>(Ljava/lang/String;Ljava/util/Map;)V
+HSPLjavax/security/auth/x500/X500Principal;-><init>(Lsun/security/x509/X500Name;)V
+HSPLjavax/security/auth/x500/X500Principal;-><init>([B)V
+HSPLjavax/security/auth/x500/X500Principal;->equals(Ljava/lang/Object;)Z+]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLjavax/security/auth/x500/X500Principal;->getEncoded()[B+]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLjavax/security/auth/x500/X500Principal;->getName()Ljava/lang/String;+]Ljavax/security/auth/x500/X500Principal;Ljavax/security/auth/x500/X500Principal;
+HSPLjavax/security/auth/x500/X500Principal;->getName(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLjavax/security/auth/x500/X500Principal;->hashCode()I+]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLjavax/xml/parsers/DocumentBuilder;->parse(Ljava/io/InputStream;)Lorg/w3c/dom/Document;+]Ljavax/xml/parsers/DocumentBuilder;Lorg/apache/harmony/xml/parsers/DocumentBuilderImpl;
+HSPLjavax/xml/parsers/DocumentBuilderFactory;-><init>()V
+HSPLjavax/xml/parsers/DocumentBuilderFactory;->isCoalescing()Z
+HSPLjavax/xml/parsers/DocumentBuilderFactory;->isIgnoringComments()Z
+HSPLjavax/xml/parsers/DocumentBuilderFactory;->isIgnoringElementContentWhitespace()Z
+HSPLjavax/xml/parsers/DocumentBuilderFactory;->isNamespaceAware()Z
+HSPLjavax/xml/parsers/DocumentBuilderFactory;->isValidating()Z
+HSPLjavax/xml/parsers/DocumentBuilderFactory;->newInstance()Ljavax/xml/parsers/DocumentBuilderFactory;
+HSPLjdk/internal/util/Preconditions;->checkIndex(IILjava/util/function/BiFunction;)I
+HSPLlibcore/content/type/MimeMap$Builder$Element;-><init>(Ljava/lang/String;Z)V
+HSPLlibcore/content/type/MimeMap$Builder$Element;->ofExtensionSpec(Ljava/lang/String;)Llibcore/content/type/MimeMap$Builder$Element;
+HSPLlibcore/content/type/MimeMap$Builder$Element;->ofMimeSpec(Ljava/lang/String;)Llibcore/content/type/MimeMap$Builder$Element;
+HSPLlibcore/content/type/MimeMap$Builder;->maybePut(Ljava/util/Map;Llibcore/content/type/MimeMap$Builder$Element;Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLlibcore/content/type/MimeMap$MemoizingSupplier;->get()Ljava/lang/Object;
+HSPLlibcore/content/type/MimeMap;-><init>(Ljava/util/Map;Ljava/util/Map;)V
+HSPLlibcore/content/type/MimeMap;->access$000(Ljava/lang/String;)Ljava/lang/String;
+HSPLlibcore/content/type/MimeMap;->checkValidExtension(Ljava/lang/String;)V
+HSPLlibcore/content/type/MimeMap;->checkValidMimeType(Ljava/lang/String;)V
+HSPLlibcore/content/type/MimeMap;->getDefault()Llibcore/content/type/MimeMap;+]Llibcore/content/type/MimeMap$MemoizingSupplier;Llibcore/content/type/MimeMap$MemoizingSupplier;
+HSPLlibcore/content/type/MimeMap;->guessMimeTypeFromExtension(Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLlibcore/content/type/MimeMap;->isValidMimeTypeOrExtension(Ljava/lang/String;)Z
+HSPLlibcore/content/type/MimeMap;->toLowerCase(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLlibcore/icu/CollationKeyICU;-><init>(Ljava/lang/String;Landroid/icu/text/CollationKey;)V
+HSPLlibcore/icu/CollationKeyICU;->toByteArray()[B+]Landroid/icu/text/CollationKey;Landroid/icu/text/CollationKey;
+HSPLlibcore/icu/ICU;->getAvailableLocales()[Ljava/util/Locale;
+HSPLlibcore/icu/ICU;->getCurrencyCode(Ljava/lang/String;)Ljava/lang/String;+]Landroid/icu/util/ULocale$Builder;Landroid/icu/util/ULocale$Builder;
+HSPLlibcore/icu/ICU;->getExtendedCalendar(Ljava/util/Locale;Ljava/lang/String;)Lcom/android/icu/util/ExtendedCalendar;
+HSPLlibcore/icu/ICU;->isIsoCountry(Ljava/lang/String;)Z+]Ljava/util/Set;Ljava/util/HashSet;
+HSPLlibcore/icu/ICU;->localeFromIcuLocaleId(Ljava/lang/String;)Ljava/util/Locale;+]Ljava/util/Locale$Builder;Ljava/util/Locale$Builder;]Ljava/util/Map;Ljava/util/Collections$EmptyMap;]Ljava/util/Iterator;Ljava/util/Collections$EmptyIterator;]Ljava/util/Set;Ljava/util/Collections$EmptySet;
+HSPLlibcore/icu/ICU;->localesFromStrings([Ljava/lang/String;)[Ljava/util/Locale;
+HSPLlibcore/icu/ICU;->parseLangScriptRegionAndVariants(Ljava/lang/String;[Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLlibcore/icu/ICU;->setDefaultLocale(Ljava/lang/String;)V
+HSPLlibcore/icu/ICU;->transformIcuDateTimePattern(Ljava/lang/String;)Ljava/lang/String;
+HSPLlibcore/icu/ICU;->transformIcuDateTimePattern_forJavaText(Ljava/lang/String;)Ljava/lang/String;
+HSPLlibcore/icu/LocaleData;-><init>(Ljava/util/Locale;)V
+HSPLlibcore/icu/LocaleData;->get(Ljava/util/Locale;)Llibcore/icu/LocaleData;+]Ljava/util/HashMap;Ljava/util/HashMap;]Ljava/util/Locale;Ljava/util/Locale;
+HSPLlibcore/icu/LocaleData;->getCompatibleLocaleForBug159514442(Ljava/util/Locale;)Ljava/util/Locale;+]Ldalvik/system/VMRuntime;Ldalvik/system/VMRuntime;]Ljava/util/Locale;Ljava/util/Locale;
+HSPLlibcore/icu/LocaleData;->getDateFormat(I)Ljava/lang/String;
+HSPLlibcore/icu/LocaleData;->getDateTimeFormatString(Lcom/android/icu/util/ExtendedCalendar;II)Ljava/lang/String;
+HSPLlibcore/icu/LocaleData;->getTimeFormat(I)Ljava/lang/String;+]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLlibcore/icu/LocaleData;->initLocaleData(Ljava/util/Locale;)Llibcore/icu/LocaleData;
+HSPLlibcore/icu/LocaleData;->initializeCalendarData(Ljava/util/Locale;)V
+HSPLlibcore/icu/LocaleData;->initializeDateFormatData(Ljava/util/Locale;)V
+HSPLlibcore/icu/LocaleData;->initializeDateTimePatterns(Ljava/util/Locale;)V
+HSPLlibcore/icu/LocaleData;->initializeDecimalFormatData(Ljava/util/Locale;)V
+HSPLlibcore/icu/LocaleData;->initializePatternSeparator(Llibcore/icu/LocaleData;Ljava/util/Locale;)V
+HSPLlibcore/icu/LocaleData;->mapInvalidAndNullLocales(Ljava/util/Locale;)Ljava/util/Locale;+]Ljava/util/Locale;Ljava/util/Locale;
+HSPLlibcore/internal/StringPool;-><init>()V
+HSPLlibcore/internal/StringPool;->contentEquals(Ljava/lang/String;[CII)Z
+HSPLlibcore/internal/StringPool;->get([CII)Ljava/lang/String;
+HSPLlibcore/io/BlockGuardOs;->accept(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)Ljava/io/FileDescriptor;+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;
+HSPLlibcore/io/BlockGuardOs;->access(Ljava/lang/String;I)Z+]Ldalvik/system/BlockGuard$VmPolicy;missing_types]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLlibcore/io/BlockGuardOs;->android_getaddrinfo(Ljava/lang/String;Landroid/system/StructAddrinfo;I)[Ljava/net/InetAddress;+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLlibcore/io/BlockGuardOs;->chmod(Ljava/lang/String;I)V+]Ldalvik/system/BlockGuard$VmPolicy;Ldalvik/system/BlockGuard$2;,Landroid/os/StrictMode$5;]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLlibcore/io/BlockGuardOs;->close(Ljava/io/FileDescriptor;)V+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLlibcore/io/BlockGuardOs;->connect(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLlibcore/io/BlockGuardOs;->fdatasync(Ljava/io/FileDescriptor;)V+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLlibcore/io/BlockGuardOs;->fstat(Ljava/io/FileDescriptor;)Landroid/system/StructStat;+]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLlibcore/io/BlockGuardOs;->ftruncate(Ljava/io/FileDescriptor;J)V+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLlibcore/io/BlockGuardOs;->getxattr(Ljava/lang/String;Ljava/lang/String;)[B+]Ldalvik/system/BlockGuard$VmPolicy;Ldalvik/system/BlockGuard$2;]Ldalvik/system/BlockGuard$Policy;Landroid/os/StrictMode$AndroidBlockGuardPolicy;,Ldalvik/system/BlockGuard$1;
+HSPLlibcore/io/BlockGuardOs;->isInetDomain(I)Z
+HSPLlibcore/io/BlockGuardOs;->isInetSocket(Ljava/io/FileDescriptor;)Z+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/BlockGuardOs;->isLingerSocket(Ljava/io/FileDescriptor;)Z+]Llibcore/io/Os;missing_types]Landroid/system/StructLinger;Landroid/system/StructLinger;
+HSPLlibcore/io/BlockGuardOs;->isNonBlockingFile(Ljava/io/FileDescriptor;)Z
+HSPLlibcore/io/BlockGuardOs;->isUdpSocket(Ljava/io/FileDescriptor;)Z+]Llibcore/io/Os;missing_types
+HSPLlibcore/io/BlockGuardOs;->isUnixDomain(I)Z
+HSPLlibcore/io/BlockGuardOs;->isUnixSocket(Ljava/io/FileDescriptor;)Z+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/BlockGuardOs;->lseek(Ljava/io/FileDescriptor;JI)J+]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLlibcore/io/BlockGuardOs;->lstat(Ljava/lang/String;)Landroid/system/StructStat;+]Ldalvik/system/BlockGuard$VmPolicy;Ldalvik/system/BlockGuard$2;]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;
+HSPLlibcore/io/BlockGuardOs;->mkdir(Ljava/lang/String;I)V+]Ldalvik/system/BlockGuard$VmPolicy;Ldalvik/system/BlockGuard$2;,Landroid/os/StrictMode$5;]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLlibcore/io/BlockGuardOs;->open(Ljava/lang/String;II)Ljava/io/FileDescriptor;+]Ldalvik/system/BlockGuard$VmPolicy;missing_types]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLlibcore/io/BlockGuardOs;->poll([Landroid/system/StructPollfd;I)I+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLlibcore/io/BlockGuardOs;->posix_fallocate(Ljava/io/FileDescriptor;JJ)V+]Ldalvik/system/BlockGuard$Policy;Landroid/os/StrictMode$AndroidBlockGuardPolicy;,Ldalvik/system/BlockGuard$1;
+HSPLlibcore/io/BlockGuardOs;->read(Ljava/io/FileDescriptor;[BII)I+]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLlibcore/io/BlockGuardOs;->readlink(Ljava/lang/String;)Ljava/lang/String;+]Ldalvik/system/BlockGuard$VmPolicy;Landroid/os/StrictMode$5;,Ldalvik/system/BlockGuard$2;]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLlibcore/io/BlockGuardOs;->recvfrom(Ljava/io/FileDescriptor;[BIIILjava/net/InetSocketAddress;)I+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLlibcore/io/BlockGuardOs;->remove(Ljava/lang/String;)V+]Ldalvik/system/BlockGuard$VmPolicy;Ldalvik/system/BlockGuard$2;,Landroid/os/StrictMode$5;]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLlibcore/io/BlockGuardOs;->rename(Ljava/lang/String;Ljava/lang/String;)V+]Ldalvik/system/BlockGuard$Policy;missing_types]Ldalvik/system/BlockGuard$VmPolicy;Ldalvik/system/BlockGuard$2;,Landroid/os/StrictMode$5;
+HSPLlibcore/io/BlockGuardOs;->sendto(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;I)I+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;
+HSPLlibcore/io/BlockGuardOs;->socket(III)Ljava/io/FileDescriptor;
+HSPLlibcore/io/BlockGuardOs;->socketpair(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V
+HSPLlibcore/io/BlockGuardOs;->stat(Ljava/lang/String;)Landroid/system/StructStat;+]Ldalvik/system/BlockGuard$VmPolicy;Ldalvik/system/BlockGuard$2;,Landroid/os/StrictMode$5;]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLlibcore/io/BlockGuardOs;->statvfs(Ljava/lang/String;)Landroid/system/StructStatVfs;+]Ldalvik/system/BlockGuard$VmPolicy;Landroid/os/StrictMode$5;,Ldalvik/system/BlockGuard$2;]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLlibcore/io/BlockGuardOs;->tagSocket(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;+]Ldalvik/system/SocketTagger;Lcom/android/server/NetworkManagementSocketTagger;
+HSPLlibcore/io/BlockGuardOs;->write(Ljava/io/FileDescriptor;[BII)I+]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLlibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection$1;-><init>(Llibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection;Ljava/io/InputStream;)V
+HSPLlibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection$1;->close()V
+HSPLlibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection;-><init>(Llibcore/io/ClassPathURLStreamHandler;Ljava/net/URL;)V
+HSPLlibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection;->access$100(Llibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection;)Ljava/util/jar/JarFile;
+HSPLlibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection;->connect()V
+HSPLlibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection;->getInputStream()Ljava/io/InputStream;
+HSPLlibcore/io/ClassPathURLStreamHandler;-><init>(Ljava/lang/String;)V
+HSPLlibcore/io/ClassPathURLStreamHandler;->access$000(Llibcore/io/ClassPathURLStreamHandler;)Ljava/util/jar/JarFile;
+HSPLlibcore/io/ClassPathURLStreamHandler;->getEntryUrlOrNull(Ljava/lang/String;)Ljava/net/URL;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/jar/JarFile;Ljava/util/jar/JarFile;
+HSPLlibcore/io/ClassPathURLStreamHandler;->isEntryStored(Ljava/lang/String;)Z+]Ljava/util/jar/JarFile;Ljava/util/jar/JarFile;]Ljava/util/zip/ZipEntry;Ljava/util/jar/JarFile$JarFileEntry;
+HSPLlibcore/io/ClassPathURLStreamHandler;->openConnection(Ljava/net/URL;)Ljava/net/URLConnection;
+HSPLlibcore/io/ForwardingOs;-><init>(Llibcore/io/Os;)V
+HSPLlibcore/io/ForwardingOs;->accept(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)Ljava/io/FileDescriptor;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->access(Ljava/lang/String;I)Z+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->android_fdsan_exchange_owner_tag(Ljava/io/FileDescriptor;JJ)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->android_getaddrinfo(Ljava/lang/String;Landroid/system/StructAddrinfo;I)[Ljava/net/InetAddress;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->bind(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->bind(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->capget(Landroid/system/StructCapUserHeader;)[Landroid/system/StructCapUserData;
+HSPLlibcore/io/ForwardingOs;->chmod(Ljava/lang/String;I)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->close(Ljava/io/FileDescriptor;)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->connect(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->dup2(Ljava/io/FileDescriptor;I)Ljava/io/FileDescriptor;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->fcntlInt(Ljava/io/FileDescriptor;II)I+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->fcntlVoid(Ljava/io/FileDescriptor;I)I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->fdatasync(Ljava/io/FileDescriptor;)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->fstat(Ljava/io/FileDescriptor;)Landroid/system/StructStat;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->ftruncate(Ljava/io/FileDescriptor;J)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->gai_strerror(I)Ljava/lang/String;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->getenv(Ljava/lang/String;)Ljava/lang/String;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->getifaddrs()[Landroid/system/StructIfaddrs;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->getnameinfo(Ljava/net/InetAddress;I)Ljava/lang/String;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->getpeername(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->getpgid(I)I
+HSPLlibcore/io/ForwardingOs;->getpid()I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->getsockname(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->getsockoptInt(Ljava/io/FileDescriptor;II)I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->getsockoptLinger(Ljava/io/FileDescriptor;II)Landroid/system/StructLinger;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->gettid()I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->getuid()I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->getxattr(Ljava/lang/String;Ljava/lang/String;)[B+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->if_nametoindex(Ljava/lang/String;)I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->ioctlInt(Ljava/io/FileDescriptor;I)I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->listen(Ljava/io/FileDescriptor;I)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->lseek(Ljava/io/FileDescriptor;JI)J+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->lstat(Ljava/lang/String;)Landroid/system/StructStat;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->mkdir(Ljava/lang/String;I)V+]Llibcore/io/Os;Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->mmap(JJIILjava/io/FileDescriptor;J)J+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->open(Ljava/lang/String;II)Ljava/io/FileDescriptor;+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->pipe2(I)[Ljava/io/FileDescriptor;+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->poll([Landroid/system/StructPollfd;I)I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->posix_fallocate(Ljava/io/FileDescriptor;JJ)V+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->read(Ljava/io/FileDescriptor;[BII)I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->readlink(Ljava/lang/String;)Ljava/lang/String;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->recvfrom(Ljava/io/FileDescriptor;[BIIILjava/net/InetSocketAddress;)I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->remove(Ljava/lang/String;)V+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->rename(Ljava/lang/String;Ljava/lang/String;)V+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->sendto(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;I)I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->setpgid(II)V
+HSPLlibcore/io/ForwardingOs;->setregid(II)V
+HSPLlibcore/io/ForwardingOs;->setreuid(II)V
+HSPLlibcore/io/ForwardingOs;->setsockoptInt(Ljava/io/FileDescriptor;III)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->shutdown(Ljava/io/FileDescriptor;I)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->socket(III)Ljava/io/FileDescriptor;+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->socketpair(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->stat(Ljava/lang/String;)Landroid/system/StructStat;+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->statvfs(Ljava/lang/String;)Landroid/system/StructStatVfs;+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->strerror(I)Ljava/lang/String;+]Llibcore/io/Os;Llibcore/io/Linux;,Llibcore/io/BlockGuardOs;
+HSPLlibcore/io/ForwardingOs;->sysconf(I)J+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/ForwardingOs;->write(Ljava/io/FileDescriptor;[BII)I+]Llibcore/io/Os;Llibcore/io/BlockGuardOs;,Llibcore/io/Linux;
+HSPLlibcore/io/IoBridge;->bind(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V+]Ljava/net/Inet6Address;Ljava/net/Inet6Address;]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;
+HSPLlibcore/io/IoBridge;->booleanFromInt(I)Z
+HSPLlibcore/io/IoBridge;->booleanToInt(Z)I
+HSPLlibcore/io/IoBridge;->closeAndSignalBlockedThreads(Ljava/io/FileDescriptor;)V+]Llibcore/io/Os;missing_types]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLlibcore/io/IoBridge;->connect(Ljava/io/FileDescriptor;Ljava/net/InetAddress;II)V
+HSPLlibcore/io/IoBridge;->connectErrno(Ljava/io/FileDescriptor;Ljava/net/InetAddress;II)V+]Llibcore/io/Os;missing_types]Ljava/util/concurrent/TimeUnit;Ljava/util/concurrent/TimeUnit$3;,Ljava/util/concurrent/TimeUnit$1;
+HSPLlibcore/io/IoBridge;->createMessageForException(Ljava/io/FileDescriptor;Ljava/net/InetAddress;IILjava/lang/Exception;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Exception;Landroid/system/ErrnoException;]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLlibcore/io/IoBridge;->getLocalInetSocketAddress(Ljava/io/FileDescriptor;)Ljava/net/InetSocketAddress;+]Llibcore/io/Os;missing_types
+HSPLlibcore/io/IoBridge;->getSocketOption(Ljava/io/FileDescriptor;I)Ljava/lang/Object;
+HSPLlibcore/io/IoBridge;->getSocketOptionErrno(Ljava/io/FileDescriptor;I)Ljava/lang/Object;+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLlibcore/io/IoBridge;->isConnected(Ljava/io/FileDescriptor;Ljava/net/InetAddress;III)Z+]Llibcore/io/Os;missing_types]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLlibcore/io/IoBridge;->open(Ljava/lang/String;I)Ljava/io/FileDescriptor;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Llibcore/io/Os;missing_types]Landroid/system/ErrnoException;Landroid/system/ErrnoException;]Ljava/io/FileNotFoundException;Ljava/io/FileNotFoundException;
+HSPLlibcore/io/IoBridge;->poll(Ljava/io/FileDescriptor;II)V
+HSPLlibcore/io/IoBridge;->postRecvfrom(ZLjava/net/DatagramPacket;Ljava/net/InetSocketAddress;I)I+]Ljava/net/DatagramPacket;Ljava/net/DatagramPacket;]Ljava/net/InetAddress;Ljava/net/Inet6Address;,Ljava/net/Inet4Address;]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLlibcore/io/IoBridge;->read(Ljava/io/FileDescriptor;[BII)I+]Llibcore/io/Os;missing_types]Landroid/system/ErrnoException;Landroid/system/ErrnoException;
+HSPLlibcore/io/IoBridge;->recvfrom(ZLjava/io/FileDescriptor;[BIIILjava/net/DatagramPacket;Z)I+]Llibcore/io/Os;missing_types
+HSPLlibcore/io/IoBridge;->sendto(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;I)I+]Llibcore/io/Os;missing_types
+HSPLlibcore/io/IoBridge;->setSocketOption(Ljava/io/FileDescriptor;ILjava/lang/Object;)V+]Landroid/system/ErrnoException;Landroid/system/ErrnoException;
+HSPLlibcore/io/IoBridge;->setSocketOptionErrno(Ljava/io/FileDescriptor;ILjava/lang/Object;)V+]Ljava/lang/Integer;Ljava/lang/Integer;]Llibcore/io/Os;missing_types]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLlibcore/io/IoBridge;->socket(III)Ljava/io/FileDescriptor;+]Llibcore/io/Os;missing_types
+HSPLlibcore/io/IoBridge;->write(Ljava/io/FileDescriptor;[BII)V+]Llibcore/io/Os;missing_types]Landroid/system/ErrnoException;Landroid/system/ErrnoException;
+HSPLlibcore/io/IoTracker;-><init>()V
+HSPLlibcore/io/IoTracker;->reset()V
+HSPLlibcore/io/IoTracker;->trackIo(I)V+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLlibcore/io/IoTracker;->trackIo(ILlibcore/io/IoTracker$Mode;)V+]Llibcore/io/IoTracker;Llibcore/io/IoTracker;
+HSPLlibcore/io/IoUtils;->acquireRawFd(Ljava/io/FileDescriptor;)I+]Llibcore/io/Os;missing_types]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLlibcore/io/IoUtils;->canOpenReadOnly(Ljava/lang/String;)Z+]Llibcore/io/Os;Landroid/app/ActivityThread$AndroidOs;
+HSPLlibcore/io/IoUtils;->close(Ljava/io/FileDescriptor;)V
+HSPLlibcore/io/IoUtils;->closeQuietly(Ljava/io/FileDescriptor;)V
+HSPLlibcore/io/IoUtils;->closeQuietly(Ljava/lang/AutoCloseable;)V+]Ljava/lang/AutoCloseable;megamorphic_types
+HSPLlibcore/io/IoUtils;->generateFdOwnerId(Ljava/lang/Object;)J
+HSPLlibcore/io/IoUtils;->isParcelFileDescriptor(Ljava/lang/Object;)Z+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLlibcore/io/IoUtils;->setBlocking(Ljava/io/FileDescriptor;Z)V+]Llibcore/io/Os;missing_types
+HSPLlibcore/io/IoUtils;->setFdOwner(Ljava/io/FileDescriptor;Ljava/lang/Object;)V+]Llibcore/io/Os;missing_types]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLlibcore/io/Libcore;->compareAndSetOs(Llibcore/io/Os;Llibcore/io/Os;)Z
+HSPLlibcore/io/Libcore;->getOs()Llibcore/io/Os;
+HSPLlibcore/io/Linux;->read(Ljava/io/FileDescriptor;[BII)I
+HSPLlibcore/io/Linux;->recvfrom(Ljava/io/FileDescriptor;[BIIILjava/net/InetSocketAddress;)I
+HSPLlibcore/io/Linux;->sendto(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;I)I
+HSPLlibcore/io/Linux;->write(Ljava/io/FileDescriptor;[BII)I
+HSPLlibcore/io/Memory;->peekInt(JZ)I
+HSPLlibcore/io/Memory;->peekInt([BILjava/nio/ByteOrder;)I
+HSPLlibcore/io/Memory;->peekLong(JZ)J
+HSPLlibcore/io/Memory;->peekShort(JZ)S
+HSPLlibcore/io/Memory;->peekShort([BILjava/nio/ByteOrder;)S
+HSPLlibcore/io/Memory;->pokeInt(JIZ)V
+HSPLlibcore/io/Memory;->pokeInt([BIILjava/nio/ByteOrder;)V
+HSPLlibcore/io/Memory;->pokeLong(JJZ)V
+HSPLlibcore/io/Memory;->pokeShort(JSZ)V
+HSPLlibcore/io/Os;->compareAndSetDefault(Llibcore/io/Os;Llibcore/io/Os;)Z
+HSPLlibcore/io/Os;->getDefault()Llibcore/io/Os;
+HSPLlibcore/net/InetAddressUtils;->parseNumericAddress(Ljava/lang/String;)Ljava/net/InetAddress;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLlibcore/net/InetAddressUtils;->parseNumericAddressNoThrow(Ljava/lang/String;)Ljava/net/InetAddress;+]Llibcore/io/Os;missing_types
+HSPLlibcore/net/InetAddressUtils;->parseNumericAddressNoThrowStripOptionalBrackets(Ljava/lang/String;)Ljava/net/InetAddress;+]Ljava/lang/String;Ljava/lang/String;
+HSPLlibcore/net/NetworkSecurityPolicy;-><init>()V
+HSPLlibcore/net/NetworkSecurityPolicy;->getInstance()Llibcore/net/NetworkSecurityPolicy;
+HSPLlibcore/net/NetworkSecurityPolicy;->setInstance(Llibcore/net/NetworkSecurityPolicy;)V
+HSPLlibcore/net/event/NetworkEventDispatcher;->addListener(Llibcore/net/event/NetworkEventListener;)V
+HSPLlibcore/net/event/NetworkEventDispatcher;->dispatchNetworkConfigurationChange()V
+HSPLlibcore/net/event/NetworkEventDispatcher;->getInstance()Llibcore/net/event/NetworkEventDispatcher;
+HSPLlibcore/net/event/NetworkEventListener;-><init>()V
+HSPLlibcore/net/http/HttpDate$1;->initialValue()Ljava/lang/Object;
+HSPLlibcore/net/http/HttpDate$1;->initialValue()Ljava/text/DateFormat;+]Ljava/text/DateFormat;Ljava/text/SimpleDateFormat;
+HSPLlibcore/net/http/HttpDate;->parse(Ljava/lang/String;)Ljava/util/Date;+]Ljava/text/SimpleDateFormat;Ljava/text/SimpleDateFormat;]Ljava/lang/ThreadLocal;Llibcore/net/http/HttpDate$1;]Ljava/text/DateFormat;Ljava/text/SimpleDateFormat;
+HSPLlibcore/reflect/AnnotationFactory;-><init>(Ljava/lang/Class;[Llibcore/reflect/AnnotationMember;)V+]Llibcore/reflect/AnnotationMember;Llibcore/reflect/AnnotationMember;
+HSPLlibcore/reflect/AnnotationFactory;->createAnnotation(Ljava/lang/Class;[Llibcore/reflect/AnnotationMember;)Ljava/lang/annotation/Annotation;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLlibcore/reflect/AnnotationFactory;->getElementsDescription(Ljava/lang/Class;)[Llibcore/reflect/AnnotationMember;+]Ljava/util/Map;Ljava/util/WeakHashMap;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;
+HSPLlibcore/reflect/AnnotationFactory;->invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Llibcore/reflect/AnnotationMember;Llibcore/reflect/AnnotationMember;]Llibcore/reflect/AnnotationFactory;Llibcore/reflect/AnnotationFactory;
+HSPLlibcore/reflect/AnnotationMember;-><init>(Ljava/lang/String;Ljava/lang/Object;)V+]Ljava/lang/Object;megamorphic_types]Ljava/lang/Class;Ljava/lang/Class;
+HSPLlibcore/reflect/AnnotationMember;-><init>(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/reflect/Method;)V
+HSPLlibcore/reflect/AnnotationMember;->copyValue()Ljava/lang/Object;+]Ljava/lang/Object;missing_types][Ljava/lang/Object;missing_types][I[I
+HSPLlibcore/reflect/AnnotationMember;->setDefinition(Llibcore/reflect/AnnotationMember;)Llibcore/reflect/AnnotationMember;
+HSPLlibcore/reflect/AnnotationMember;->validateValue()Ljava/lang/Object;+]Ljava/lang/Object;megamorphic_types]Llibcore/reflect/AnnotationMember;Llibcore/reflect/AnnotationMember;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLlibcore/reflect/GenericArrayTypeImpl;->getGenericComponentType()Ljava/lang/reflect/Type;+]Llibcore/reflect/ParameterizedTypeImpl;Llibcore/reflect/ParameterizedTypeImpl;
+HSPLlibcore/reflect/GenericSignatureParser;-><init>(Ljava/lang/ClassLoader;)V
+HSPLlibcore/reflect/GenericSignatureParser;->expect(C)V+]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->isStopSymbol(C)Z
+HSPLlibcore/reflect/GenericSignatureParser;->parseClassSignature()V+]Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseClassTypeSignature()Ljava/lang/reflect/Type;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseFieldTypeSignature()Ljava/lang/reflect/Type;+]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseForClass(Ljava/lang/reflect/GenericDeclaration;Ljava/lang/String;)V+]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseForField(Ljava/lang/reflect/GenericDeclaration;Ljava/lang/String;)V+]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseForMethod(Ljava/lang/reflect/GenericDeclaration;Ljava/lang/String;[Ljava/lang/Class;)V+]Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseFormalTypeParameter()Llibcore/reflect/TypeVariableImpl;+]Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;]Ljava/lang/String;Ljava/lang/String;]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseMethodTypeSignature([Ljava/lang/Class;)V+]Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseOptFormalTypeParameters()V+]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;]Llibcore/reflect/ListOfVariables;Llibcore/reflect/ListOfVariables;
+HSPLlibcore/reflect/GenericSignatureParser;->parseOptTypeArguments()Llibcore/reflect/ListOfTypes;+]Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseReturnType()Ljava/lang/reflect/Type;+]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseTypeArgument()Ljava/lang/reflect/Type;+]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;]Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;
+HSPLlibcore/reflect/GenericSignatureParser;->parseTypeSignature()Ljava/lang/reflect/Type;+]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->parseTypeVariableSignature()Llibcore/reflect/TypeVariableImpl;+]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->scanIdentifier()V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/GenericSignatureParser;->scanSymbol()V
+HSPLlibcore/reflect/GenericSignatureParser;->setInput(Ljava/lang/reflect/GenericDeclaration;Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;]Llibcore/reflect/GenericSignatureParser;Llibcore/reflect/GenericSignatureParser;
+HSPLlibcore/reflect/ListOfTypes;-><init>(I)V
+HSPLlibcore/reflect/ListOfTypes;-><init>([Ljava/lang/reflect/Type;)V+]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLlibcore/reflect/ListOfTypes;->add(Ljava/lang/reflect/Type;)V+]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLlibcore/reflect/ListOfTypes;->getResolvedTypes()[Ljava/lang/reflect/Type;
+HSPLlibcore/reflect/ListOfTypes;->length()I+]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLlibcore/reflect/ListOfTypes;->resolveTypes(Ljava/util/List;)[Ljava/lang/reflect/Type;+]Ljava/util/List;Ljava/util/ArrayList;]Llibcore/reflect/ParameterizedTypeImpl;Llibcore/reflect/ParameterizedTypeImpl;
+HSPLlibcore/reflect/ListOfVariables;-><init>()V
+HSPLlibcore/reflect/ListOfVariables;->add(Ljava/lang/reflect/TypeVariable;)V+]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLlibcore/reflect/ListOfVariables;->getArray()[Ljava/lang/reflect/TypeVariable;+]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLlibcore/reflect/ParameterizedTypeImpl;-><init>(Llibcore/reflect/ParameterizedTypeImpl;Ljava/lang/String;Llibcore/reflect/ListOfTypes;Ljava/lang/ClassLoader;)V
+HSPLlibcore/reflect/ParameterizedTypeImpl;->getActualTypeArguments()[Ljava/lang/reflect/Type;+]Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;][Ljava/lang/reflect/Type;[Ljava/lang/reflect/Type;
+HSPLlibcore/reflect/ParameterizedTypeImpl;->getOwnerType()Ljava/lang/reflect/Type;+]Llibcore/reflect/ParameterizedTypeImpl;Llibcore/reflect/ParameterizedTypeImpl;]Ljava/lang/Class;Ljava/lang/Class;
+HSPLlibcore/reflect/ParameterizedTypeImpl;->getRawType()Ljava/lang/Class;
+HSPLlibcore/reflect/ParameterizedTypeImpl;->getRawType()Ljava/lang/reflect/Type;+]Llibcore/reflect/ParameterizedTypeImpl;Llibcore/reflect/ParameterizedTypeImpl;
+HSPLlibcore/reflect/ParameterizedTypeImpl;->getResolvedType()Ljava/lang/reflect/Type;+]Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;]Llibcore/reflect/ParameterizedTypeImpl;Llibcore/reflect/ParameterizedTypeImpl;
+HSPLlibcore/reflect/TypeVariableImpl;-><init>(Ljava/lang/reflect/GenericDeclaration;Ljava/lang/String;)V
+HSPLlibcore/reflect/TypeVariableImpl;-><init>(Ljava/lang/reflect/GenericDeclaration;Ljava/lang/String;Llibcore/reflect/ListOfTypes;)V
+HSPLlibcore/reflect/TypeVariableImpl;->equals(Ljava/lang/Object;)Z+]Ljava/lang/reflect/TypeVariable;Llibcore/reflect/TypeVariableImpl;]Llibcore/reflect/TypeVariableImpl;Llibcore/reflect/TypeVariableImpl;]Ljava/lang/Object;Ljava/lang/Class;,Ljava/lang/reflect/Method;
+HSPLlibcore/reflect/TypeVariableImpl;->findFormalVar(Ljava/lang/reflect/GenericDeclaration;Ljava/lang/String;)Ljava/lang/reflect/TypeVariable;+]Ljava/lang/reflect/TypeVariable;Llibcore/reflect/TypeVariableImpl;]Ljava/lang/reflect/GenericDeclaration;Ljava/lang/Class;,Ljava/lang/reflect/Constructor;,Ljava/lang/reflect/Method;
+HSPLlibcore/reflect/TypeVariableImpl;->getGenericDeclaration()Ljava/lang/reflect/GenericDeclaration;+]Llibcore/reflect/TypeVariableImpl;Llibcore/reflect/TypeVariableImpl;
+HSPLlibcore/reflect/TypeVariableImpl;->getName()Ljava/lang/String;
+HSPLlibcore/reflect/TypeVariableImpl;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;]Llibcore/reflect/TypeVariableImpl;Llibcore/reflect/TypeVariableImpl;]Ljava/lang/Object;Ljava/lang/Class;,Ljava/lang/reflect/Method;
+HSPLlibcore/reflect/TypeVariableImpl;->resolve()V
+HSPLlibcore/reflect/Types;->getType(Ljava/lang/reflect/Type;)Ljava/lang/reflect/Type;+]Llibcore/reflect/ParameterizedTypeImpl;Llibcore/reflect/ParameterizedTypeImpl;
+HSPLlibcore/reflect/Types;->getTypeArray(Llibcore/reflect/ListOfTypes;Z)[Ljava/lang/reflect/Type;+]Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;
+HSPLlibcore/reflect/WildcardTypeImpl;-><init>(Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;)V
+HSPLlibcore/util/ArrayUtils;->throwsIfOutOfBounds(III)V
+HSPLlibcore/util/BasicLruCache;->create(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLlibcore/util/BasicLruCache;->entryEvicted(Ljava/lang/Object;Ljava/lang/Object;)V
+HSPLlibcore/util/BasicLruCache;->evictAll()V
+HSPLlibcore/util/BasicLruCache;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Llibcore/util/BasicLruCache;Ljava/lang/Enum$1;,Llibcore/util/BasicLruCache;,Ljava/time/zone/IcuZoneRulesProvider$ZoneRulesCache;,Llibcore/icu/TimeZoneNames$ZoneStringsCache;]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;
+HSPLlibcore/util/BasicLruCache;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;
+HSPLlibcore/util/BasicLruCache;->trimToSize(I)V+]Llibcore/util/BasicLruCache;Llibcore/util/BasicLruCache;,Ljava/lang/Enum$1;]Ljava/util/Map$Entry;Ljava/util/LinkedHashMap$LinkedHashMapEntry;]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;
+HSPLlibcore/util/CollectionUtils;->removeDuplicates(Ljava/util/List;Ljava/util/Comparator;)V+]Ljava/util/Comparator;Ljava/lang/reflect/Method$1;]Ljava/util/List;Ljava/util/ArrayList$SubList;,Ljava/util/ArrayList;
+HSPLlibcore/util/FP16;->ceil(S)S
+HSPLlibcore/util/FP16;->floor(S)S
+HSPLlibcore/util/FP16;->greater(SS)Z
+HSPLlibcore/util/FP16;->greaterEquals(SS)Z
+HSPLlibcore/util/FP16;->less(SS)Z
+HSPLlibcore/util/FP16;->lessEquals(SS)Z
+HSPLlibcore/util/FP16;->rint(S)S
+HSPLlibcore/util/FP16;->toFloat(S)F
+HSPLlibcore/util/FP16;->toHalf(F)S
+HSPLlibcore/util/NativeAllocationRegistry$CleanerRunner;-><init>(Lsun/misc/Cleaner;)V
+HSPLlibcore/util/NativeAllocationRegistry$CleanerRunner;->run()V+]Lsun/misc/Cleaner;Lsun/misc/Cleaner;
+HSPLlibcore/util/NativeAllocationRegistry$CleanerThunk;-><init>(Llibcore/util/NativeAllocationRegistry;)V
+HSPLlibcore/util/NativeAllocationRegistry$CleanerThunk;->run()V
+HSPLlibcore/util/NativeAllocationRegistry$CleanerThunk;->setNativePtr(J)V
+HSPLlibcore/util/NativeAllocationRegistry;-><init>(Ljava/lang/ClassLoader;JJZ)V
+HSPLlibcore/util/NativeAllocationRegistry;->access$000(Llibcore/util/NativeAllocationRegistry;)J
+HSPLlibcore/util/NativeAllocationRegistry;->access$100(Llibcore/util/NativeAllocationRegistry;)J
+HSPLlibcore/util/NativeAllocationRegistry;->access$200(J)V
+HSPLlibcore/util/NativeAllocationRegistry;->createMalloced(Ljava/lang/ClassLoader;J)Llibcore/util/NativeAllocationRegistry;
+HSPLlibcore/util/NativeAllocationRegistry;->createMalloced(Ljava/lang/ClassLoader;JJ)Llibcore/util/NativeAllocationRegistry;
+HSPLlibcore/util/NativeAllocationRegistry;->createNonmalloced(Ljava/lang/ClassLoader;JJ)Llibcore/util/NativeAllocationRegistry;
+HSPLlibcore/util/NativeAllocationRegistry;->registerNativeAllocation(J)V+]Ldalvik/system/VMRuntime;Ldalvik/system/VMRuntime;
+HSPLlibcore/util/NativeAllocationRegistry;->registerNativeAllocation(Ljava/lang/Object;J)Ljava/lang/Runnable;+]Llibcore/util/NativeAllocationRegistry$CleanerThunk;Llibcore/util/NativeAllocationRegistry$CleanerThunk;
+HSPLlibcore/util/NativeAllocationRegistry;->registerNativeFree(J)V+]Ldalvik/system/VMRuntime;Ldalvik/system/VMRuntime;
+HSPLlibcore/util/SneakyThrow;->sneakyThrow(Ljava/lang/Throwable;)V
+HSPLlibcore/util/SneakyThrow;->sneakyThrow_(Ljava/lang/Throwable;)V
+HSPLlibcore/util/XmlObjectFactory;->newXmlPullParser()Lorg/xmlpull/v1/XmlPullParser;
+HSPLlibcore/util/ZoneInfo;-><init>(Lcom/android/i18n/timezone/ZoneInfoData;IZ)V+]Lcom/android/i18n/timezone/ZoneInfoData;Lcom/android/i18n/timezone/ZoneInfoData;]Llibcore/util/ZoneInfo;Llibcore/util/ZoneInfo;
+HSPLlibcore/util/ZoneInfo;->clone()Ljava/lang/Object;
+HSPLlibcore/util/ZoneInfo;->createZoneInfo(Lcom/android/i18n/timezone/ZoneInfoData;)Llibcore/util/ZoneInfo;
+HSPLlibcore/util/ZoneInfo;->createZoneInfo(Lcom/android/i18n/timezone/ZoneInfoData;J)Llibcore/util/ZoneInfo;+]Lcom/android/i18n/timezone/ZoneInfoData;Lcom/android/i18n/timezone/ZoneInfoData;]Ljava/lang/Integer;Ljava/lang/Integer;
+HSPLlibcore/util/ZoneInfo;->getDSTSavings()I
+HSPLlibcore/util/ZoneInfo;->getOffset(J)I+]Lcom/android/i18n/timezone/ZoneInfoData;Lcom/android/i18n/timezone/ZoneInfoData;
+HSPLlibcore/util/ZoneInfo;->getOffsetsByUtcTime(J[I)I+]Lcom/android/i18n/timezone/ZoneInfoData;Lcom/android/i18n/timezone/ZoneInfoData;
+HSPLlibcore/util/ZoneInfo;->getRawOffset()I+]Lcom/android/i18n/timezone/ZoneInfoData;Lcom/android/i18n/timezone/ZoneInfoData;
+HSPLlibcore/util/ZoneInfo;->hasSameRules(Ljava/util/TimeZone;)Z+]Lcom/android/i18n/timezone/ZoneInfoData;Lcom/android/i18n/timezone/ZoneInfoData;]Llibcore/util/ZoneInfo;Llibcore/util/ZoneInfo;
+HSPLlibcore/util/ZoneInfo;->hashCode()I
+HSPLlibcore/util/ZoneInfo;->inDaylightTime(Ljava/util/Date;)Z+]Ljava/util/Date;missing_types]Lcom/android/i18n/timezone/ZoneInfoData;Lcom/android/i18n/timezone/ZoneInfoData;
+HSPLorg/apache/harmony/dalvik/ddmc/Chunk;-><init>(ILjava/nio/ByteBuffer;)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLorg/apache/harmony/dalvik/ddmc/Chunk;-><init>(I[BII)V
+HSPLorg/apache/harmony/dalvik/ddmc/DdmServer;->broadcast(I)V+]Lorg/apache/harmony/dalvik/ddmc/ChunkHandler;megamorphic_types]Ljava/util/HashMap;Ljava/util/HashMap;]Ljava/util/Collection;Ljava/util/HashMap$Values;]Ljava/util/Iterator;Ljava/util/HashMap$ValueIterator;
+HSPLorg/apache/harmony/dalvik/ddmc/DdmServer;->dispatch(I[BII)Lorg/apache/harmony/dalvik/ddmc/Chunk;+]Lorg/apache/harmony/dalvik/ddmc/ChunkHandler;Landroid/ddm/DdmHandleProfiling;,Landroid/ddm/DdmHandleHello;]Ljava/util/HashMap;Ljava/util/HashMap;
+HSPLorg/apache/harmony/dalvik/ddmc/DdmServer;->sendChunk(Lorg/apache/harmony/dalvik/ddmc/Chunk;)V
+HSPLorg/apache/harmony/xml/dom/CharacterDataImpl;->getData()Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLorg/apache/harmony/xml/dom/CharacterDataImpl;->getNodeValue()Ljava/lang/String;+]Lorg/apache/harmony/xml/dom/CharacterDataImpl;Lorg/apache/harmony/xml/dom/TextImpl;,Lorg/apache/harmony/xml/dom/CDATASectionImpl;
+HSPLorg/apache/harmony/xml/dom/DocumentImpl;-><init>(Lorg/apache/harmony/xml/dom/DOMImplementationImpl;Ljava/lang/String;Ljava/lang/String;Lorg/w3c/dom/DocumentType;Ljava/lang/String;)V
+HSPLorg/apache/harmony/xml/dom/DocumentImpl;->getDocumentElement()Lorg/w3c/dom/Element;+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLorg/apache/harmony/xml/dom/DocumentImpl;->insertChildAt(Lorg/w3c/dom/Node;I)Lorg/w3c/dom/Node;+]Lorg/apache/harmony/xml/dom/DocumentImpl;Lorg/apache/harmony/xml/dom/DocumentImpl;
+HSPLorg/apache/harmony/xml/dom/DocumentImpl;->isXMLIdentifier(Ljava/lang/String;)Z
+HSPLorg/apache/harmony/xml/dom/DocumentImpl;->isXMLIdentifierPart(C)Z
+HSPLorg/apache/harmony/xml/dom/DocumentImpl;->isXMLIdentifierStart(C)Z
+HSPLorg/apache/harmony/xml/dom/ElementImpl;->getNodeName()Ljava/lang/String;+]Lorg/apache/harmony/xml/dom/ElementImpl;Lorg/apache/harmony/xml/dom/ElementImpl;
+HSPLorg/apache/harmony/xml/dom/ElementImpl;->getNodeType()S
+HSPLorg/apache/harmony/xml/dom/ElementImpl;->getTagName()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLorg/apache/harmony/xml/dom/InnerNodeImpl;-><init>(Lorg/apache/harmony/xml/dom/DocumentImpl;)V
+HSPLorg/apache/harmony/xml/dom/InnerNodeImpl;->appendChild(Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node;+]Ljava/util/List;Ljava/util/ArrayList;]Lorg/apache/harmony/xml/dom/InnerNodeImpl;Lorg/apache/harmony/xml/dom/ElementImpl;,Lorg/apache/harmony/xml/dom/DocumentImpl;
+HSPLorg/apache/harmony/xml/dom/InnerNodeImpl;->getChildNodes()Lorg/w3c/dom/NodeList;+]Lorg/apache/harmony/xml/dom/NodeListImpl;Lorg/apache/harmony/xml/dom/NodeListImpl;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLorg/apache/harmony/xml/dom/InnerNodeImpl;->getFirstChild()Lorg/w3c/dom/Node;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/apache/harmony/xml/dom/InnerNodeImpl;->getLastChild()Lorg/w3c/dom/Node;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/apache/harmony/xml/dom/InnerNodeImpl;->getTextContent()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lorg/w3c/dom/Node;Lorg/apache/harmony/xml/dom/TextImpl;,Lorg/apache/harmony/xml/dom/ElementImpl;,Lorg/apache/harmony/xml/dom/CDATASectionImpl;]Lorg/apache/harmony/xml/dom/InnerNodeImpl;Lorg/apache/harmony/xml/dom/ElementImpl;
+HSPLorg/apache/harmony/xml/dom/InnerNodeImpl;->hasTextContent(Lorg/w3c/dom/Node;)Z+]Lorg/w3c/dom/Node;Lorg/apache/harmony/xml/dom/TextImpl;,Lorg/apache/harmony/xml/dom/ElementImpl;,Lorg/apache/harmony/xml/dom/CDATASectionImpl;,Lorg/apache/harmony/xml/dom/CommentImpl;
+HSPLorg/apache/harmony/xml/dom/InnerNodeImpl;->insertChildAt(Lorg/w3c/dom/Node;I)Lorg/w3c/dom/Node;+]Lorg/apache/harmony/xml/dom/LeafNodeImpl;megamorphic_types]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/apache/harmony/xml/dom/InnerNodeImpl;->isParentOf(Lorg/w3c/dom/Node;)Z
+HSPLorg/apache/harmony/xml/dom/InnerNodeImpl;->refreshIndices(I)V+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/apache/harmony/xml/dom/LeafNodeImpl;-><init>(Lorg/apache/harmony/xml/dom/DocumentImpl;)V
+HSPLorg/apache/harmony/xml/dom/LeafNodeImpl;->getNextSibling()Lorg/w3c/dom/Node;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/apache/harmony/xml/dom/LeafNodeImpl;->isParentOf(Lorg/w3c/dom/Node;)Z
+HSPLorg/apache/harmony/xml/dom/NodeImpl;-><init>(Lorg/apache/harmony/xml/dom/DocumentImpl;)V
+HSPLorg/apache/harmony/xml/dom/NodeImpl;->getTextContent()Ljava/lang/String;+]Lorg/apache/harmony/xml/dom/NodeImpl;Lorg/apache/harmony/xml/dom/TextImpl;,Lorg/apache/harmony/xml/dom/AttrImpl;,Lorg/apache/harmony/xml/dom/CDATASectionImpl;
+HSPLorg/apache/harmony/xml/dom/NodeListImpl;-><init>()V
+HSPLorg/apache/harmony/xml/dom/NodeListImpl;->add(Lorg/apache/harmony/xml/dom/NodeImpl;)V+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/apache/harmony/xml/dom/NodeListImpl;->getLength()I+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/apache/harmony/xml/dom/NodeListImpl;->item(I)Lorg/w3c/dom/Node;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/apache/harmony/xml/dom/TextImpl;->getNodeType()S
+HSPLorg/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl;-><init>()V
+HSPLorg/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl;->newDocumentBuilder()Ljavax/xml/parsers/DocumentBuilder;+]Lorg/apache/harmony/xml/parsers/DocumentBuilderImpl;Lorg/apache/harmony/xml/parsers/DocumentBuilderImpl;]Lorg/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl;Lorg/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl;
+HSPLorg/apache/harmony/xml/parsers/DocumentBuilderImpl;-><clinit>()V
+HSPLorg/json/JSON;->checkDouble(D)D
+HSPLorg/json/JSON;->toBoolean(Ljava/lang/Object;)Ljava/lang/Boolean;+]Ljava/lang/String;Ljava/lang/String;
+HSPLorg/json/JSON;->toDouble(Ljava/lang/Object;)Ljava/lang/Double;+]Ljava/lang/Number;Ljava/lang/Integer;
+HSPLorg/json/JSON;->toInteger(Ljava/lang/Object;)Ljava/lang/Integer;+]Ljava/lang/Number;Ljava/lang/Double;,Ljava/lang/Long;
+HSPLorg/json/JSON;->toLong(Ljava/lang/Object;)Ljava/lang/Long;+]Ljava/lang/Number;Ljava/lang/Integer;,Ljava/lang/Double;
+HSPLorg/json/JSON;->toString(Ljava/lang/Object;)Ljava/lang/String;
+HSPLorg/json/JSONArray;-><init>()V
+HSPLorg/json/JSONArray;-><init>(Ljava/lang/String;)V
+HSPLorg/json/JSONArray;-><init>(Ljava/util/Collection;)V+]Ljava/util/Collection;megamorphic_types]Ljava/util/Iterator;megamorphic_types]Lorg/json/JSONArray;Lorg/json/JSONArray;
+HSPLorg/json/JSONArray;-><init>(Lorg/json/JSONTokener;)V+]Lorg/json/JSONTokener;Lorg/json/JSONTokener;
+HSPLorg/json/JSONArray;->get(I)Ljava/lang/Object;+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLorg/json/JSONArray;->getInt(I)I+]Ljava/lang/Integer;Ljava/lang/Integer;]Lorg/json/JSONArray;Lorg/json/JSONArray;
+HSPLorg/json/JSONArray;->getJSONArray(I)Lorg/json/JSONArray;+]Lorg/json/JSONArray;Lorg/json/JSONArray;
+HSPLorg/json/JSONArray;->getJSONObject(I)Lorg/json/JSONObject;+]Lorg/json/JSONArray;missing_types
+HSPLorg/json/JSONArray;->getString(I)Ljava/lang/String;+]Lorg/json/JSONArray;Lorg/json/JSONArray;
+HSPLorg/json/JSONArray;->length()I+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONArray;->opt(I)Ljava/lang/Object;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONArray;->optJSONObject(I)Lorg/json/JSONObject;+]Lorg/json/JSONArray;Lorg/json/JSONArray;
+HSPLorg/json/JSONArray;->optString(I)Ljava/lang/String;+]Lorg/json/JSONArray;Lorg/json/JSONArray;
+HSPLorg/json/JSONArray;->optString(ILjava/lang/String;)Ljava/lang/String;+]Lorg/json/JSONArray;Lorg/json/JSONArray;
+HSPLorg/json/JSONArray;->put(I)Lorg/json/JSONArray;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONArray;->put(J)Lorg/json/JSONArray;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONArray;->put(Ljava/lang/Object;)Lorg/json/JSONArray;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONArray;->toString()Ljava/lang/String;+]Lorg/json/JSONStringer;Lorg/json/JSONStringer;]Lorg/json/JSONArray;Lorg/json/JSONArray;
+HSPLorg/json/JSONArray;->writeTo(Lorg/json/JSONStringer;)V+]Lorg/json/JSONStringer;missing_types]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLorg/json/JSONException;-><init>(Ljava/lang/String;)V
+HSPLorg/json/JSONObject$1;->toString()Ljava/lang/String;
+HSPLorg/json/JSONObject;-><init>()V
+HSPLorg/json/JSONObject;-><init>(Ljava/lang/String;)V
+HSPLorg/json/JSONObject;-><init>(Ljava/util/Map;)V+]Ljava/util/Map$Entry;megamorphic_types]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;]Ljava/util/Map;megamorphic_types]Ljava/util/Iterator;megamorphic_types]Ljava/util/Set;megamorphic_types
+HSPLorg/json/JSONObject;-><init>(Lorg/json/JSONTokener;)V+]Lorg/json/JSONTokener;Lorg/json/JSONTokener;
+HSPLorg/json/JSONObject;->checkName(Ljava/lang/String;)Ljava/lang/String;
+HSPLorg/json/JSONObject;->get(Ljava/lang/String;)Ljava/lang/Object;+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLorg/json/JSONObject;->getBoolean(Ljava/lang/String;)Z+]Ljava/lang/Boolean;Ljava/lang/Boolean;]Lorg/json/JSONObject;Lorg/json/JSONObject;
+HSPLorg/json/JSONObject;->getDouble(Ljava/lang/String;)D+]Lorg/json/JSONObject;Lorg/json/JSONObject;]Ljava/lang/Double;Ljava/lang/Double;
+HSPLorg/json/JSONObject;->getInt(Ljava/lang/String;)I+]Ljava/lang/Integer;Ljava/lang/Integer;]Lorg/json/JSONObject;Lorg/json/JSONObject;
+HSPLorg/json/JSONObject;->getJSONArray(Ljava/lang/String;)Lorg/json/JSONArray;+]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->getJSONObject(Ljava/lang/String;)Lorg/json/JSONObject;+]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->getLong(Ljava/lang/String;)J+]Lorg/json/JSONObject;missing_types]Ljava/lang/Long;Ljava/lang/Long;
+HSPLorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String;+]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->has(Ljava/lang/String;)Z+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;
+HSPLorg/json/JSONObject;->isNull(Ljava/lang/String;)Z+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;
+HSPLorg/json/JSONObject;->keys()Ljava/util/Iterator;+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;]Ljava/util/Set;Ljava/util/LinkedHashMap$LinkedKeySet;
+HSPLorg/json/JSONObject;->length()I+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;
+HSPLorg/json/JSONObject;->numberToString(Ljava/lang/Number;)Ljava/lang/String;+]Ljava/lang/Object;megamorphic_types]Ljava/lang/Number;megamorphic_types
+HSPLorg/json/JSONObject;->opt(Ljava/lang/String;)Ljava/lang/Object;+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;
+HSPLorg/json/JSONObject;->optBoolean(Ljava/lang/String;)Z+]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->optBoolean(Ljava/lang/String;Z)Z+]Ljava/lang/Boolean;Ljava/lang/Boolean;]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->optDouble(Ljava/lang/String;D)D+]Lorg/json/JSONObject;Lorg/json/JSONObject;]Ljava/lang/Double;Ljava/lang/Double;
+HSPLorg/json/JSONObject;->optInt(Ljava/lang/String;)I+]Lorg/json/JSONObject;Lorg/json/JSONObject;
+HSPLorg/json/JSONObject;->optInt(Ljava/lang/String;I)I+]Ljava/lang/Integer;Ljava/lang/Integer;]Lorg/json/JSONObject;Lorg/json/JSONObject;
+HSPLorg/json/JSONObject;->optJSONArray(Ljava/lang/String;)Lorg/json/JSONArray;+]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->optJSONObject(Ljava/lang/String;)Lorg/json/JSONObject;+]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->optLong(Ljava/lang/String;)J+]Lorg/json/JSONObject;Lorg/json/JSONObject;
+HSPLorg/json/JSONObject;->optLong(Ljava/lang/String;J)J+]Lorg/json/JSONObject;missing_types]Ljava/lang/Long;Ljava/lang/Long;
+HSPLorg/json/JSONObject;->optString(Ljava/lang/String;)Ljava/lang/String;+]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->optString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;+]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->put(Ljava/lang/String;D)Lorg/json/JSONObject;+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->put(Ljava/lang/String;I)Lorg/json/JSONObject;+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->put(Ljava/lang/String;J)Lorg/json/JSONObject;+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->put(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;]Ljava/lang/Number;megamorphic_types]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->put(Ljava/lang/String;Z)Lorg/json/JSONObject;+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->putOpt(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;+]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->remove(Ljava/lang/String;)Ljava/lang/Object;+]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;
+HSPLorg/json/JSONObject;->toString()Ljava/lang/String;+]Lorg/json/JSONStringer;Lorg/json/JSONStringer;]Lorg/json/JSONObject;missing_types
+HSPLorg/json/JSONObject;->toString(I)Ljava/lang/String;+]Lorg/json/JSONStringer;Lorg/json/JSONStringer;]Lorg/json/JSONObject;Lorg/json/JSONObject;
+HSPLorg/json/JSONObject;->wrap(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/Object;megamorphic_types]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/Package;Ljava/lang/Package;]Ljava/lang/String;Ljava/lang/String;
+HSPLorg/json/JSONObject;->writeTo(Lorg/json/JSONStringer;)V+]Ljava/util/Map$Entry;Ljava/util/LinkedHashMap$LinkedHashMapEntry;]Ljava/util/LinkedHashMap;Ljava/util/LinkedHashMap;]Lorg/json/JSONStringer;missing_types]Ljava/util/Iterator;Ljava/util/LinkedHashMap$LinkedEntryIterator;]Ljava/util/Set;Ljava/util/LinkedHashMap$LinkedEntrySet;
+HSPLorg/json/JSONStringer;-><init>()V
+HSPLorg/json/JSONStringer;-><init>(I)V
+HSPLorg/json/JSONStringer;->array()Lorg/json/JSONStringer;+]Lorg/json/JSONStringer;missing_types
+HSPLorg/json/JSONStringer;->beforeKey()V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLorg/json/JSONStringer;->beforeValue()V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONStringer;->close(Lorg/json/JSONStringer$Scope;Lorg/json/JSONStringer$Scope;Ljava/lang/String;)Lorg/json/JSONStringer;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONStringer;->endArray()Lorg/json/JSONStringer;+]Lorg/json/JSONStringer;missing_types
+HSPLorg/json/JSONStringer;->endObject()Lorg/json/JSONStringer;+]Lorg/json/JSONStringer;missing_types
+HSPLorg/json/JSONStringer;->key(Ljava/lang/String;)Lorg/json/JSONStringer;
+HSPLorg/json/JSONStringer;->newline()V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONStringer;->object()Lorg/json/JSONStringer;+]Lorg/json/JSONStringer;missing_types
+HSPLorg/json/JSONStringer;->open(Lorg/json/JSONStringer$Scope;Ljava/lang/String;)Lorg/json/JSONStringer;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONStringer;->peek()Lorg/json/JSONStringer$Scope;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONStringer;->replaceTop(Lorg/json/JSONStringer$Scope;)V+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLorg/json/JSONStringer;->string(Ljava/lang/String;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLorg/json/JSONStringer;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLorg/json/JSONStringer;->value(Ljava/lang/Object;)Lorg/json/JSONStringer;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/Object;missing_types]Lorg/json/JSONObject;missing_types]Ljava/util/List;Ljava/util/ArrayList;]Lorg/json/JSONArray;missing_types
+HSPLorg/json/JSONTokener;-><init>(Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLorg/json/JSONTokener;->nextCleanInternal()I+]Ljava/lang/String;Ljava/lang/String;
+HSPLorg/json/JSONTokener;->nextString(C)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lorg/json/JSONTokener;Lorg/json/JSONTokener;
+HSPLorg/json/JSONTokener;->nextToInternal(Ljava/lang/String;)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;
+HSPLorg/json/JSONTokener;->nextValue()Ljava/lang/Object;+]Lorg/json/JSONTokener;Lorg/json/JSONTokener;
+HSPLorg/json/JSONTokener;->readArray()Lorg/json/JSONArray;+]Lorg/json/JSONTokener;Lorg/json/JSONTokener;]Lorg/json/JSONArray;Lorg/json/JSONArray;
+HSPLorg/json/JSONTokener;->readEscapeCharacter()C+]Ljava/lang/String;Ljava/lang/String;
+HSPLorg/json/JSONTokener;->readLiteral()Ljava/lang/Object;+]Ljava/lang/String;Ljava/lang/String;]Lorg/json/JSONTokener;Lorg/json/JSONTokener;
+HSPLorg/json/JSONTokener;->readObject()Lorg/json/JSONObject;+]Lorg/json/JSONObject;Lorg/json/JSONObject;]Lorg/json/JSONTokener;Lorg/json/JSONTokener;
+HSPLorg/json/JSONTokener;->syntaxError(Ljava/lang/String;)Lorg/json/JSONException;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLorg/json/JSONTokener;->toString()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLorg/xml/sax/InputSource;-><init>(Ljava/io/InputStream;)V+]Lorg/xml/sax/InputSource;Lorg/xml/sax/InputSource;
+HSPLorg/xml/sax/InputSource;-><init>(Ljava/io/Reader;)V+]Lorg/xml/sax/InputSource;Lorg/xml/sax/InputSource;
+HSPLorg/xml/sax/InputSource;->getByteStream()Ljava/io/InputStream;
+HSPLorg/xml/sax/InputSource;->getCharacterStream()Ljava/io/Reader;
+HSPLorg/xml/sax/InputSource;->getEncoding()Ljava/lang/String;
+HSPLorg/xml/sax/InputSource;->getPublicId()Ljava/lang/String;
+HSPLorg/xml/sax/InputSource;->getSystemId()Ljava/lang/String;
+HSPLorg/xml/sax/InputSource;->setByteStream(Ljava/io/InputStream;)V
+HSPLorg/xml/sax/InputSource;->setCharacterStream(Ljava/io/Reader;)V
+HSPLorg/xml/sax/helpers/DefaultHandler;-><init>()V
+HSPLorg/xmlpull/v1/XmlPullParserFactory;-><init>()V+]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLorg/xmlpull/v1/XmlPullParserFactory;->getParserInstance()Lorg/xmlpull/v1/XmlPullParser;+]Ljava/lang/Class;Ljava/lang/Class;]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLorg/xmlpull/v1/XmlPullParserFactory;->newInstance()Lorg/xmlpull/v1/XmlPullParserFactory;
+HSPLorg/xmlpull/v1/XmlPullParserFactory;->newPullParser()Lorg/xmlpull/v1/XmlPullParser;+]Ljava/util/HashMap;Ljava/util/HashMap;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;]Ljava/lang/Boolean;Ljava/lang/Boolean;]Lorg/xmlpull/v1/XmlPullParser;Lcom/android/org/kxml2/io/KXmlParser;
+HSPLorg/xmlpull/v1/XmlPullParserFactory;->setNamespaceAware(Z)V+]Ljava/util/HashMap;Ljava/util/HashMap;
+HSPLsun/invoke/util/Wrapper;->findPrimitiveType(Ljava/lang/Class;)Lsun/invoke/util/Wrapper;
+HSPLsun/invoke/util/Wrapper;->forPrimitiveType(Ljava/lang/Class;)Lsun/invoke/util/Wrapper;
+HSPLsun/invoke/util/Wrapper;->hashPrim(Ljava/lang/Class;)I
+HSPLsun/invoke/util/Wrapper;->isDoubleWord()Z
+HSPLsun/invoke/util/Wrapper;->isIntegral()Z
+HSPLsun/invoke/util/Wrapper;->isNumeric()Z
+HSPLsun/invoke/util/Wrapper;->isSingleWord()Z
+HSPLsun/invoke/util/Wrapper;->isSubwordOrInt()Z
+HSPLsun/misc/ASCIICaseInsensitiveComparator;->compare(Ljava/lang/Object;Ljava/lang/Object;)I+]Lsun/misc/ASCIICaseInsensitiveComparator;Lsun/misc/ASCIICaseInsensitiveComparator;
+HSPLsun/misc/ASCIICaseInsensitiveComparator;->compare(Ljava/lang/String;Ljava/lang/String;)I
+HSPLsun/misc/ASCIICaseInsensitiveComparator;->isUpper(I)Z
+HSPLsun/misc/ASCIICaseInsensitiveComparator;->lowerCaseHashCode(Ljava/lang/String;)I
+HSPLsun/misc/ASCIICaseInsensitiveComparator;->toLower(I)I
+HSPLsun/misc/Cleaner;-><init>(Ljava/lang/Object;Ljava/lang/Runnable;)V
+HSPLsun/misc/Cleaner;->add(Lsun/misc/Cleaner;)Lsun/misc/Cleaner;
+HSPLsun/misc/Cleaner;->clean()V+]Ljava/lang/Runnable;megamorphic_types
+HSPLsun/misc/Cleaner;->create(Ljava/lang/Object;Ljava/lang/Runnable;)Lsun/misc/Cleaner;
+HSPLsun/misc/Cleaner;->remove(Lsun/misc/Cleaner;)Z
+HSPLsun/misc/CompoundEnumeration;-><init>([Ljava/util/Enumeration;)V
+HSPLsun/misc/CompoundEnumeration;->hasMoreElements()Z
+HSPLsun/misc/CompoundEnumeration;->next()Z+]Ljava/util/Enumeration;Lsun/misc/CompoundEnumeration;,Ljava/util/Collections$3;
+HSPLsun/misc/CompoundEnumeration;->nextElement()Ljava/lang/Object;
+HSPLsun/misc/FDBigInteger;-><init>(J[CII)V
+HSPLsun/misc/FDBigInteger;-><init>([II)V
+HSPLsun/misc/FDBigInteger;->add(Lsun/misc/FDBigInteger;)Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->addAndCmp(Lsun/misc/FDBigInteger;Lsun/misc/FDBigInteger;)I+]Lsun/misc/FDBigInteger;Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->big5pow(I)Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->checkZeroTail([II)I
+HSPLsun/misc/FDBigInteger;->cmp(Lsun/misc/FDBigInteger;)I
+HSPLsun/misc/FDBigInteger;->cmpPow52(II)I+]Lsun/misc/FDBigInteger;Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->getNormalizationBias()I
+HSPLsun/misc/FDBigInteger;->leftInplaceSub(Lsun/misc/FDBigInteger;)Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->leftShift(I)Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->leftShift([II[IIII)V
+HSPLsun/misc/FDBigInteger;->makeImmutable()V
+HSPLsun/misc/FDBigInteger;->mult([IIII[I)V
+HSPLsun/misc/FDBigInteger;->mult([III[I)V
+HSPLsun/misc/FDBigInteger;->multAddMe(II)V
+HSPLsun/misc/FDBigInteger;->multAndCarryBy10([II[I)I
+HSPLsun/misc/FDBigInteger;->multBy10()Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->multByPow52(II)Lsun/misc/FDBigInteger;+]Lsun/misc/FDBigInteger;Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->multDiffMe(JLsun/misc/FDBigInteger;)J
+HSPLsun/misc/FDBigInteger;->quoRemIteration(Lsun/misc/FDBigInteger;)I
+HSPLsun/misc/FDBigInteger;->rightInplaceSub(Lsun/misc/FDBigInteger;)Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->size()I
+HSPLsun/misc/FDBigInteger;->trimLeadingZeros()V
+HSPLsun/misc/FDBigInteger;->valueOfMulPow52(JII)Lsun/misc/FDBigInteger;+]Lsun/misc/FDBigInteger;Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->valueOfPow2(I)Lsun/misc/FDBigInteger;
+HSPLsun/misc/FDBigInteger;->valueOfPow52(II)Lsun/misc/FDBigInteger;+]Lsun/misc/FDBigInteger;Lsun/misc/FDBigInteger;
+HSPLsun/misc/FloatingDecimal$1;->initialValue()Ljava/lang/Object;+]Lsun/misc/FloatingDecimal$1;Lsun/misc/FloatingDecimal$1;
+HSPLsun/misc/FloatingDecimal$1;->initialValue()Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;
+HSPLsun/misc/FloatingDecimal$ASCIIToBinaryBuffer;-><init>(ZI[CI)V
+HSPLsun/misc/FloatingDecimal$ASCIIToBinaryBuffer;->doubleValue()D+]Lsun/misc/FDBigInteger;Lsun/misc/FDBigInteger;
+HSPLsun/misc/FloatingDecimal$ASCIIToBinaryBuffer;->floatValue()F+]Lsun/misc/FDBigInteger;Lsun/misc/FDBigInteger;
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;-><init>()V
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->access$000(Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;Z)V
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->access$100(Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;IJIZ)V
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->appendTo(Ljava/lang/Appendable;)V+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->developLongDigits(IJI)V
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->dtoa(IJIZ)V+]Lsun/misc/FDBigInteger;Lsun/misc/FDBigInteger;
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->estimateDecExp(JI)I
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->getChars([C)I
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->getDecimalExponent()I
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->getDigits([C)I
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->isExceptional()Z
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->isNegative()Z
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->roundup()V
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->setSign(Z)V
+HSPLsun/misc/FloatingDecimal$BinaryToASCIIBuffer;->toJavaFormatString()Ljava/lang/String;
+HSPLsun/misc/FloatingDecimal$PreparedASCIIToBinaryBuffer;->doubleValue()D
+HSPLsun/misc/FloatingDecimal$PreparedASCIIToBinaryBuffer;->floatValue()F
+HSPLsun/misc/FloatingDecimal;->appendTo(DLjava/lang/Appendable;)V+]Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;,Lsun/misc/FloatingDecimal$ExceptionalBinaryToASCIIBuffer;
+HSPLsun/misc/FloatingDecimal;->appendTo(FLjava/lang/Appendable;)V+]Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;,Lsun/misc/FloatingDecimal$ExceptionalBinaryToASCIIBuffer;
+HSPLsun/misc/FloatingDecimal;->getBinaryToASCIIBuffer()Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;+]Ljava/lang/ThreadLocal;Lsun/misc/FloatingDecimal$1;
+HSPLsun/misc/FloatingDecimal;->getBinaryToASCIIConverter(D)Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;
+HSPLsun/misc/FloatingDecimal;->getBinaryToASCIIConverter(DZ)Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;
+HSPLsun/misc/FloatingDecimal;->getBinaryToASCIIConverter(F)Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;
+HSPLsun/misc/FloatingDecimal;->parseDouble(Ljava/lang/String;)D+]Lsun/misc/FloatingDecimal$ASCIIToBinaryConverter;Lsun/misc/FloatingDecimal$PreparedASCIIToBinaryBuffer;,Lsun/misc/FloatingDecimal$ASCIIToBinaryBuffer;
+HSPLsun/misc/FloatingDecimal;->parseFloat(Ljava/lang/String;)F+]Lsun/misc/FloatingDecimal$ASCIIToBinaryConverter;Lsun/misc/FloatingDecimal$PreparedASCIIToBinaryBuffer;,Lsun/misc/FloatingDecimal$ASCIIToBinaryBuffer;
+HSPLsun/misc/FloatingDecimal;->readJavaFormatString(Ljava/lang/String;)Lsun/misc/FloatingDecimal$ASCIIToBinaryConverter;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLsun/misc/FloatingDecimal;->toJavaFormatString(D)Ljava/lang/String;+]Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;,Lsun/misc/FloatingDecimal$ExceptionalBinaryToASCIIBuffer;
+HSPLsun/misc/FloatingDecimal;->toJavaFormatString(F)Ljava/lang/String;+]Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;,Lsun/misc/FloatingDecimal$ExceptionalBinaryToASCIIBuffer;
+HSPLsun/misc/FormattedFloatingDecimal$1;->initialValue()Ljava/lang/Object;
+HSPLsun/misc/FormattedFloatingDecimal;-><init>(ILsun/misc/FormattedFloatingDecimal$Form;Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;)V+]Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;]Lsun/misc/FormattedFloatingDecimal$Form;Lsun/misc/FormattedFloatingDecimal$Form;
+HSPLsun/misc/FormattedFloatingDecimal;->applyPrecision(I[CII)I
+HSPLsun/misc/FormattedFloatingDecimal;->create(ZI)[C
+HSPLsun/misc/FormattedFloatingDecimal;->fillDecimal(I[CIIZ)V
+HSPLsun/misc/FormattedFloatingDecimal;->getBuffer()[C+]Ljava/lang/ThreadLocal;Lsun/misc/FormattedFloatingDecimal$1;
+HSPLsun/misc/FormattedFloatingDecimal;->getExponent()[C
+HSPLsun/misc/FormattedFloatingDecimal;->getExponentRounded()I
+HSPLsun/misc/FormattedFloatingDecimal;->getMantissa()[C
+HSPLsun/misc/FormattedFloatingDecimal;->valueOf(DILsun/misc/FormattedFloatingDecimal$Form;)Lsun/misc/FormattedFloatingDecimal;
+HSPLsun/misc/IOUtils;->readFully(Ljava/io/InputStream;IZ)[B+]Ljava/io/InputStream;Lsun/security/util/DerInputBuffer;,Ljava/io/ByteArrayInputStream;,Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;
+HSPLsun/misc/LRUCache;-><init>(I)V
+HSPLsun/misc/LRUCache;->forName(Ljava/lang/Object;)Ljava/lang/Object;+]Lsun/misc/LRUCache;Ljava/util/Scanner$1;
+HSPLsun/misc/LRUCache;->moveToFront([Ljava/lang/Object;I)V
+HSPLsun/misc/Unsafe;->arrayBaseOffset(Ljava/lang/Class;)I
+HSPLsun/misc/Unsafe;->arrayIndexScale(Ljava/lang/Class;)I
+HSPLsun/misc/Unsafe;->getAndAddInt(Ljava/lang/Object;JI)I
+HSPLsun/misc/Unsafe;->getAndAddLong(Ljava/lang/Object;JJ)J+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLsun/misc/Unsafe;->getAndSetInt(Ljava/lang/Object;JI)I
+HSPLsun/misc/Unsafe;->getAndSetLong(Ljava/lang/Object;JJ)J+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLsun/misc/Unsafe;->getAndSetObject(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;
+HSPLsun/misc/Unsafe;->getUnsafe()Lsun/misc/Unsafe;+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLsun/misc/Unsafe;->objectFieldOffset(Ljava/lang/reflect/Field;)J+]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;
+HSPLsun/misc/VM;->isBooted()Z
+HSPLsun/net/NetHooks;->beforeTcpBind(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V
+HSPLsun/net/NetHooks;->beforeTcpConnect(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V
+HSPLsun/net/NetProperties;->get(Ljava/lang/String;)Ljava/lang/String;+]Ljava/util/Properties;Ljava/util/Properties;
+HSPLsun/net/spi/DefaultProxySelector$1;-><init>(Lsun/net/spi/DefaultProxySelector;Ljava/lang/String;Lsun/net/spi/DefaultProxySelector$NonProxyInfo;Ljava/lang/String;)V
+HSPLsun/net/spi/DefaultProxySelector$1;->run()Ljava/lang/Object;+]Lsun/net/spi/DefaultProxySelector$1;Lsun/net/spi/DefaultProxySelector$1;
+HSPLsun/net/spi/DefaultProxySelector$1;->run()Ljava/net/Proxy;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLsun/net/spi/DefaultProxySelector;->select(Ljava/net/URI;)Ljava/util/List;+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/net/URI;Ljava/net/URI;
+HSPLsun/net/util/IPAddressUtil;->convertFromIPv4MappedAddress([B)[B
+HSPLsun/net/util/IPAddressUtil;->isIPv4MappedAddress([B)Z
+HSPLsun/net/www/ParseUtil;->decode(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/net/www/ParseUtil;->encodePath(Ljava/lang/String;Z)Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/util/BitSet;Ljava/util/BitSet;
+HSPLsun/net/www/protocol/file/Handler;->parseURL(Ljava/net/URL;Ljava/lang/String;II)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/net/www/protocol/jar/Handler;-><init>()V
+HSPLsun/nio/ch/AbstractPollArrayWrapper;-><init>()V
+HSPLsun/nio/ch/AbstractPollArrayWrapper;->getReventOps(I)I+]Lsun/nio/ch/AllocatedNativeObject;Lsun/nio/ch/AllocatedNativeObject;
+HSPLsun/nio/ch/AbstractPollArrayWrapper;->putDescriptor(II)V+]Lsun/nio/ch/AllocatedNativeObject;Lsun/nio/ch/AllocatedNativeObject;
+HSPLsun/nio/ch/AbstractPollArrayWrapper;->putEventOps(II)V+]Lsun/nio/ch/AllocatedNativeObject;Lsun/nio/ch/AllocatedNativeObject;
+HSPLsun/nio/ch/AbstractPollArrayWrapper;->putReventOps(II)V+]Lsun/nio/ch/AllocatedNativeObject;Lsun/nio/ch/AllocatedNativeObject;
+HSPLsun/nio/ch/AbstractPollSelectorImpl;-><init>(Ljava/nio/channels/spi/SelectorProvider;II)V
+HSPLsun/nio/ch/AbstractPollSelectorImpl;->implClose()V+]Ljava/nio/channels/SelectableChannel;Lsun/nio/ch/DatagramChannelImpl;]Lsun/nio/ch/PollArrayWrapper;Lsun/nio/ch/PollArrayWrapper;]Lsun/nio/ch/AbstractPollSelectorImpl;Lsun/nio/ch/PollSelectorImpl;]Lsun/nio/ch/SelectionKeyImpl;Lsun/nio/ch/SelectionKeyImpl;
+HSPLsun/nio/ch/AbstractPollSelectorImpl;->implRegister(Lsun/nio/ch/SelectionKeyImpl;)V+]Lsun/nio/ch/PollArrayWrapper;Lsun/nio/ch/PollArrayWrapper;]Lsun/nio/ch/SelectionKeyImpl;Lsun/nio/ch/SelectionKeyImpl;]Ljava/util/HashSet;Ljava/util/HashSet;
+HSPLsun/nio/ch/AbstractPollSelectorImpl;->putEventOps(Lsun/nio/ch/SelectionKeyImpl;I)V+]Lsun/nio/ch/PollArrayWrapper;Lsun/nio/ch/PollArrayWrapper;]Lsun/nio/ch/SelectionKeyImpl;Lsun/nio/ch/SelectionKeyImpl;
+HSPLsun/nio/ch/AbstractPollSelectorImpl;->updateSelectedKeys()I+]Lsun/nio/ch/SelChImpl;Lsun/nio/ch/DatagramChannelImpl;,Lsun/nio/ch/SocketChannelImpl;,Lsun/nio/ch/SourceChannelImpl;]Lsun/nio/ch/PollArrayWrapper;Lsun/nio/ch/PollArrayWrapper;]Lsun/nio/ch/SelectionKeyImpl;Lsun/nio/ch/SelectionKeyImpl;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLsun/nio/ch/AllocatedNativeObject;-><init>(IZ)V
+HSPLsun/nio/ch/AllocatedNativeObject;->free()V+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLsun/nio/ch/ChannelInputStream;-><init>(Ljava/nio/channels/ReadableByteChannel;)V
+HSPLsun/nio/ch/ChannelInputStream;->available()I+]Ljava/nio/channels/SeekableByteChannel;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/ChannelInputStream;->close()V+]Ljava/nio/channels/ReadableByteChannel;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/ChannelInputStream;->read()I+]Lsun/nio/ch/ChannelInputStream;Lsun/nio/ch/ChannelInputStream;
+HSPLsun/nio/ch/ChannelInputStream;->read(Ljava/nio/ByteBuffer;)I
+HSPLsun/nio/ch/ChannelInputStream;->read(Ljava/nio/channels/ReadableByteChannel;Ljava/nio/ByteBuffer;Z)I+]Ljava/nio/channels/ReadableByteChannel;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/ChannelInputStream;->read([BII)I+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Lsun/nio/ch/ChannelInputStream;Lsun/nio/ch/ChannelInputStream;,Lsun/nio/ch/SocketAdaptor$SocketInputStream;
+HSPLsun/nio/ch/DefaultSelectorProvider;->create()Ljava/nio/channels/spi/SelectorProvider;
+HSPLsun/nio/ch/FileChannelImpl$Unmapper;-><init>(JJILjava/io/FileDescriptor;)V
+HSPLsun/nio/ch/FileChannelImpl$Unmapper;-><init>(JJILjava/io/FileDescriptor;Lsun/nio/ch/FileChannelImpl$1;)V
+HSPLsun/nio/ch/FileChannelImpl$Unmapper;->run()V+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;
+HSPLsun/nio/ch/FileChannelImpl;-><init>(Ljava/io/FileDescriptor;Ljava/lang/String;ZZZLjava/lang/Object;)V+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;]Ldalvik/system/CloseGuard;missing_types
+HSPLsun/nio/ch/FileChannelImpl;->access$000(JJ)I
+HSPLsun/nio/ch/FileChannelImpl;->ensureOpen()V+]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/FileChannelImpl;->fileLockTable()Lsun/nio/ch/FileLockTable;+]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;
+HSPLsun/nio/ch/FileChannelImpl;->finalize()V+]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;]Ldalvik/system/CloseGuard;missing_types
+HSPLsun/nio/ch/FileChannelImpl;->force(Z)V+]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Lsun/nio/ch/FileDispatcher;Lsun/nio/ch/FileDispatcherImpl;]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/FileChannelImpl;->implCloseChannel()V+]Lsun/nio/ch/FileDispatcher;Lsun/nio/ch/FileDispatcherImpl;]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Ldalvik/system/CloseGuard;missing_types]Lsun/nio/ch/FileLockImpl;Lsun/nio/ch/FileLockImpl;]Ljava/nio/channels/FileLock;Lsun/nio/ch/FileLockImpl;]Ljava/io/Closeable;missing_types]Ljava/util/List;Ljava/util/ArrayList;]Lsun/nio/ch/FileLockTable;Lsun/nio/ch/SharedFileLockTable;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
+HSPLsun/nio/ch/FileChannelImpl;->isSharedFileLockTable()Z
+HSPLsun/nio/ch/FileChannelImpl;->lock(JJZ)Ljava/nio/channels/FileLock;+]Lsun/nio/ch/FileDispatcher;Lsun/nio/ch/FileDispatcherImpl;]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Lsun/nio/ch/FileLockTable;Lsun/nio/ch/SharedFileLockTable;]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/FileChannelImpl;->map(Ljava/nio/channels/FileChannel$MapMode;JJ)Ljava/nio/MappedByteBuffer;+]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Lsun/nio/ch/FileDispatcher;Lsun/nio/ch/FileDispatcherImpl;]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLsun/nio/ch/FileChannelImpl;->open(Ljava/io/FileDescriptor;Ljava/lang/String;ZZLjava/lang/Object;)Ljava/nio/channels/FileChannel;
+HSPLsun/nio/ch/FileChannelImpl;->open(Ljava/io/FileDescriptor;Ljava/lang/String;ZZZLjava/lang/Object;)Ljava/nio/channels/FileChannel;
+HSPLsun/nio/ch/FileChannelImpl;->position()J+]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/FileChannelImpl;->position(J)Ljava/nio/channels/FileChannel;+]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLsun/nio/ch/FileChannelImpl;->read(Ljava/nio/ByteBuffer;)I+]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/FileChannelImpl;->release(Lsun/nio/ch/FileLockImpl;)V+]Lsun/nio/ch/FileDispatcher;Lsun/nio/ch/FileDispatcherImpl;]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Lsun/nio/ch/FileLockImpl;Lsun/nio/ch/FileLockImpl;]Lsun/nio/ch/FileLockTable;Lsun/nio/ch/SharedFileLockTable;
+HSPLsun/nio/ch/FileChannelImpl;->size()J+]Lsun/nio/ch/FileDispatcher;Lsun/nio/ch/FileDispatcherImpl;]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/FileChannelImpl;->tryLock(JJZ)Ljava/nio/channels/FileLock;+]Lsun/nio/ch/FileDispatcher;Lsun/nio/ch/FileDispatcherImpl;]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Lsun/nio/ch/FileLockTable;Lsun/nio/ch/SharedFileLockTable;
+HSPLsun/nio/ch/FileChannelImpl;->write(Ljava/nio/ByteBuffer;)I+]Lsun/nio/ch/NativeThreadSet;Lsun/nio/ch/NativeThreadSet;]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/FileDescriptorHolderSocketImpl;-><init>(Ljava/io/FileDescriptor;)V
+HSPLsun/nio/ch/FileDispatcher;-><init>()V
+HSPLsun/nio/ch/FileDispatcherImpl;-><init>(Z)V
+HSPLsun/nio/ch/FileDispatcherImpl;->close(Ljava/io/FileDescriptor;)V
+HSPLsun/nio/ch/FileDispatcherImpl;->duplicateForMapping(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;
+HSPLsun/nio/ch/FileDispatcherImpl;->force(Ljava/io/FileDescriptor;Z)I+]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLsun/nio/ch/FileDispatcherImpl;->lock(Ljava/io/FileDescriptor;ZJJZ)I+]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLsun/nio/ch/FileDispatcherImpl;->read(Ljava/io/FileDescriptor;JI)I+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLsun/nio/ch/FileDispatcherImpl;->release(Ljava/io/FileDescriptor;JJ)V+]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLsun/nio/ch/FileDispatcherImpl;->size(Ljava/io/FileDescriptor;)J+]Ldalvik/system/BlockGuard$Policy;missing_types
+HSPLsun/nio/ch/FileDispatcherImpl;->truncate(Ljava/io/FileDescriptor;J)I
+HSPLsun/nio/ch/FileDispatcherImpl;->write(Ljava/io/FileDescriptor;JI)I+]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;,Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+HSPLsun/nio/ch/FileKey;-><init>()V
+HSPLsun/nio/ch/FileKey;->create(Ljava/io/FileDescriptor;)Lsun/nio/ch/FileKey;
+HSPLsun/nio/ch/FileKey;->hashCode()I
+HSPLsun/nio/ch/FileLockImpl;-><init>(Ljava/nio/channels/FileChannel;JJZ)V
+HSPLsun/nio/ch/FileLockImpl;->invalidate()V
+HSPLsun/nio/ch/FileLockImpl;->isValid()Z
+HSPLsun/nio/ch/FileLockImpl;->release()V+]Lsun/nio/ch/FileLockImpl;Lsun/nio/ch/FileLockImpl;]Ljava/nio/channels/Channel;Lsun/nio/ch/FileChannelImpl;]Lsun/nio/ch/FileChannelImpl;Lsun/nio/ch/FileChannelImpl;
+HSPLsun/nio/ch/FileLockTable;-><init>()V
+HSPLsun/nio/ch/FileLockTable;->newSharedFileLockTable(Ljava/nio/channels/Channel;Ljava/io/FileDescriptor;)Lsun/nio/ch/FileLockTable;
+HSPLsun/nio/ch/IOStatus;->checkAll(J)Z
+HSPLsun/nio/ch/IOStatus;->normalize(I)I
+HSPLsun/nio/ch/IOStatus;->normalize(J)J
+HSPLsun/nio/ch/IOUtil;->newFD(I)Ljava/io/FileDescriptor;
+HSPLsun/nio/ch/IOUtil;->read(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;JLsun/nio/ch/NativeDispatcher;)I+]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLsun/nio/ch/IOUtil;->readIntoNativeBuffer(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;JLsun/nio/ch/NativeDispatcher;)I+]Lsun/nio/ch/NativeDispatcher;Lsun/nio/ch/FileDispatcherImpl;]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;]Lsun/nio/ch/DirectBuffer;Ljava/nio/DirectByteBuffer;
+HSPLsun/nio/ch/IOUtil;->write(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;JLsun/nio/ch/NativeDispatcher;)I+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;,Ljava/nio/DirectByteBuffer;
+HSPLsun/nio/ch/IOUtil;->writeFromNativeBuffer(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;JLsun/nio/ch/NativeDispatcher;)I+]Lsun/nio/ch/NativeDispatcher;Lsun/nio/ch/FileDispatcherImpl;]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;]Lsun/nio/ch/DirectBuffer;Ljava/nio/DirectByteBuffer;
+HSPLsun/nio/ch/NativeDispatcher;-><init>()V
+HSPLsun/nio/ch/NativeDispatcher;->needsPositionLock()Z
+HSPLsun/nio/ch/NativeObject;-><init>(IZ)V+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLsun/nio/ch/NativeObject;->address()J
+HSPLsun/nio/ch/NativeObject;->getShort(I)S+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLsun/nio/ch/NativeObject;->putInt(II)V+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLsun/nio/ch/NativeObject;->putShort(IS)V+]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLsun/nio/ch/NativeThreadSet;-><init>(I)V
+HSPLsun/nio/ch/NativeThreadSet;->add()I
+HSPLsun/nio/ch/NativeThreadSet;->remove(I)V+]Ljava/lang/Object;Lsun/nio/ch/NativeThreadSet;
+HSPLsun/nio/ch/NativeThreadSet;->signalAndWait()V
+HSPLsun/nio/ch/Net;->checkAddress(Ljava/net/SocketAddress;)Ljava/net/InetSocketAddress;
+HSPLsun/nio/ch/Net;->connect(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I
+HSPLsun/nio/ch/Net;->connect(Ljava/net/ProtocolFamily;Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I
+HSPLsun/nio/ch/Net;->isIPv6Available()Z
+HSPLsun/nio/ch/Net;->localAddress(Ljava/io/FileDescriptor;)Ljava/net/InetSocketAddress;
+HSPLsun/nio/ch/Net;->socket(Ljava/net/ProtocolFamily;Z)Ljava/io/FileDescriptor;
+HSPLsun/nio/ch/Net;->socket(Z)Ljava/io/FileDescriptor;
+HSPLsun/nio/ch/PollArrayWrapper;-><init>(I)V+]Lsun/nio/ch/AllocatedNativeObject;Lsun/nio/ch/AllocatedNativeObject;
+HSPLsun/nio/ch/PollArrayWrapper;->addEntry(Lsun/nio/ch/SelChImpl;)V+]Lsun/nio/ch/SelChImpl;Lsun/nio/ch/DatagramChannelImpl;,Lsun/nio/ch/SocketChannelImpl;]Lsun/nio/ch/PollArrayWrapper;Lsun/nio/ch/PollArrayWrapper;
+HSPLsun/nio/ch/PollArrayWrapper;->free()V+]Lsun/nio/ch/AllocatedNativeObject;Lsun/nio/ch/AllocatedNativeObject;
+HSPLsun/nio/ch/PollArrayWrapper;->initInterrupt(II)V+]Lsun/nio/ch/PollArrayWrapper;Lsun/nio/ch/PollArrayWrapper;
+HSPLsun/nio/ch/PollArrayWrapper;->interrupt()V
+HSPLsun/nio/ch/PollArrayWrapper;->poll(IIJ)I
+HSPLsun/nio/ch/PollArrayWrapper;->release(I)V
+HSPLsun/nio/ch/PollSelectorImpl;-><init>(Ljava/nio/channels/spi/SelectorProvider;)V+]Lsun/nio/ch/PollArrayWrapper;Lsun/nio/ch/PollArrayWrapper;
+HSPLsun/nio/ch/PollSelectorImpl;->doSelect(J)I+]Lsun/nio/ch/PollArrayWrapper;Lsun/nio/ch/PollArrayWrapper;]Lsun/nio/ch/PollSelectorImpl;Lsun/nio/ch/PollSelectorImpl;
+HSPLsun/nio/ch/PollSelectorImpl;->implCloseInterrupt()V+]Lsun/nio/ch/PollArrayWrapper;Lsun/nio/ch/PollArrayWrapper;
+HSPLsun/nio/ch/PollSelectorImpl;->wakeup()Ljava/nio/channels/Selector;+]Lsun/nio/ch/PollArrayWrapper;Lsun/nio/ch/PollArrayWrapper;
+HSPLsun/nio/ch/PollSelectorProvider;-><init>()V
+HSPLsun/nio/ch/PollSelectorProvider;->openSelector()Ljava/nio/channels/spi/AbstractSelector;
+HSPLsun/nio/ch/SelectionKeyImpl;-><init>(Lsun/nio/ch/SelChImpl;Lsun/nio/ch/SelectorImpl;)V
+HSPLsun/nio/ch/SelectionKeyImpl;->channel()Ljava/nio/channels/SelectableChannel;
+HSPLsun/nio/ch/SelectionKeyImpl;->ensureValid()V+]Lsun/nio/ch/SelectionKeyImpl;Lsun/nio/ch/SelectionKeyImpl;
+HSPLsun/nio/ch/SelectionKeyImpl;->getIndex()I
+HSPLsun/nio/ch/SelectionKeyImpl;->interestOps(I)Ljava/nio/channels/SelectionKey;+]Lsun/nio/ch/SelectionKeyImpl;Lsun/nio/ch/SelectionKeyImpl;
+HSPLsun/nio/ch/SelectionKeyImpl;->nioInterestOps()I
+HSPLsun/nio/ch/SelectionKeyImpl;->nioInterestOps(I)Ljava/nio/channels/SelectionKey;+]Lsun/nio/ch/SelChImpl;Lsun/nio/ch/DatagramChannelImpl;,Lsun/nio/ch/SocketChannelImpl;,Lsun/nio/ch/ServerSocketChannelImpl;]Ljava/nio/channels/SelectableChannel;Lsun/nio/ch/DatagramChannelImpl;,Lsun/nio/ch/SocketChannelImpl;,Lsun/nio/ch/ServerSocketChannelImpl;]Lsun/nio/ch/SelectionKeyImpl;Lsun/nio/ch/SelectionKeyImpl;
+HSPLsun/nio/ch/SelectionKeyImpl;->nioReadyOps()I
+HSPLsun/nio/ch/SelectionKeyImpl;->nioReadyOps(I)V
+HSPLsun/nio/ch/SelectionKeyImpl;->setIndex(I)V
+HSPLsun/nio/ch/SelectorImpl;-><init>(Ljava/nio/channels/spi/SelectorProvider;)V
+HSPLsun/nio/ch/SelectorImpl;->implCloseSelector()V+]Lsun/nio/ch/SelectorImpl;Lsun/nio/ch/PollSelectorImpl;
+HSPLsun/nio/ch/SelectorImpl;->lockAndDoSelect(J)I+]Lsun/nio/ch/SelectorImpl;Lsun/nio/ch/PollSelectorImpl;
+HSPLsun/nio/ch/SelectorImpl;->processDeregisterQueue()V+]Lsun/nio/ch/SelectorImpl;Lsun/nio/ch/PollSelectorImpl;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLsun/nio/ch/SelectorImpl;->register(Ljava/nio/channels/spi/AbstractSelectableChannel;ILjava/lang/Object;)Ljava/nio/channels/SelectionKey;+]Lsun/nio/ch/SelectionKeyImpl;Lsun/nio/ch/SelectionKeyImpl;]Lsun/nio/ch/SelectorImpl;Lsun/nio/ch/PollSelectorImpl;
+HSPLsun/nio/ch/SelectorImpl;->select(J)I
+HSPLsun/nio/ch/SelectorProviderImpl;-><init>()V
+HSPLsun/nio/ch/SelectorProviderImpl;->openSocketChannel()Ljava/nio/channels/SocketChannel;
+HSPLsun/nio/ch/SharedFileLockTable$FileLockReference;-><init>(Ljava/nio/channels/FileLock;Ljava/lang/ref/ReferenceQueue;Lsun/nio/ch/FileKey;)V
+HSPLsun/nio/ch/SharedFileLockTable$FileLockReference;->fileKey()Lsun/nio/ch/FileKey;
+HSPLsun/nio/ch/SharedFileLockTable;-><init>(Ljava/nio/channels/Channel;Ljava/io/FileDescriptor;)V
+HSPLsun/nio/ch/SharedFileLockTable;->add(Ljava/nio/channels/FileLock;)V+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;]Ljava/nio/channels/FileLock;Lsun/nio/ch/FileLockImpl;
+HSPLsun/nio/ch/SharedFileLockTable;->remove(Ljava/nio/channels/FileLock;)V+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;]Lsun/nio/ch/SharedFileLockTable$FileLockReference;Lsun/nio/ch/SharedFileLockTable$FileLockReference;
+HSPLsun/nio/ch/SharedFileLockTable;->removeAll()Ljava/util/List;+]Ljava/nio/channels/FileLock;Lsun/nio/ch/FileLockImpl;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;]Lsun/nio/ch/SharedFileLockTable$FileLockReference;Lsun/nio/ch/SharedFileLockTable$FileLockReference;
+HSPLsun/nio/ch/SharedFileLockTable;->removeKeyIfEmpty(Lsun/nio/ch/FileKey;Ljava/util/List;)V+]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;
+HSPLsun/nio/ch/SharedFileLockTable;->removeStaleEntries()V+]Ljava/lang/ref/ReferenceQueue;Ljava/lang/ref/ReferenceQueue;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/concurrent/ConcurrentHashMap;Ljava/util/concurrent/ConcurrentHashMap;]Lsun/nio/ch/SharedFileLockTable$FileLockReference;Lsun/nio/ch/SharedFileLockTable$FileLockReference;
+HSPLsun/nio/ch/SocketAdaptor;-><init>(Lsun/nio/ch/SocketChannelImpl;)V+]Lsun/nio/ch/SocketChannelImpl;Lsun/nio/ch/SocketChannelImpl;
+HSPLsun/nio/ch/SocketAdaptor;->create(Lsun/nio/ch/SocketChannelImpl;)Ljava/net/Socket;
+HSPLsun/nio/ch/SocketAdaptor;->isClosed()Z+]Lsun/nio/ch/SocketChannelImpl;Lsun/nio/ch/SocketChannelImpl;
+HSPLsun/nio/ch/SocketChannelImpl;-><init>(Ljava/nio/channels/spi/SelectorProvider;)V+]Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
+HSPLsun/nio/ch/SocketChannelImpl;->connect(Ljava/net/SocketAddress;)Z+]Lsun/nio/ch/SocketChannelImpl;Lsun/nio/ch/SocketChannelImpl;]Ljava/net/InetAddress;Ljava/net/Inet4Address;,Ljava/net/Inet6Address;]Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;
+HSPLsun/nio/ch/SocketChannelImpl;->ensureOpenAndUnconnected()V+]Lsun/nio/ch/SocketChannelImpl;Lsun/nio/ch/SocketChannelImpl;
+HSPLsun/nio/ch/SocketChannelImpl;->finishConnect()Z+]Lsun/nio/ch/SocketChannelImpl;Lsun/nio/ch/SocketChannelImpl;]Ldalvik/system/BlockGuard$Policy;Ldalvik/system/BlockGuard$1;
+HSPLsun/nio/ch/SocketChannelImpl;->getFD()Ljava/io/FileDescriptor;
+HSPLsun/nio/ch/SocketChannelImpl;->implCloseSelectableChannel()V+]Lsun/nio/ch/NativeDispatcher;Lsun/nio/ch/SocketDispatcher;]Lsun/nio/ch/SocketChannelImpl;Lsun/nio/ch/SocketChannelImpl;]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
+HSPLsun/nio/ch/SocketChannelImpl;->implConfigureBlocking(Z)V
+HSPLsun/nio/ch/SocketChannelImpl;->isConnected()Z
+HSPLsun/nio/ch/SocketChannelImpl;->kill()V+]Lsun/nio/ch/NativeDispatcher;Lsun/nio/ch/SocketDispatcher;
+HSPLsun/nio/ch/SocketChannelImpl;->readerCleanup()V+]Lsun/nio/ch/SocketChannelImpl;Lsun/nio/ch/SocketChannelImpl;
+HSPLsun/nio/ch/SocketChannelImpl;->socket()Ljava/net/Socket;
+HSPLsun/nio/ch/SocketChannelImpl;->translateAndSetInterestOps(ILsun/nio/ch/SelectionKeyImpl;)V+]Lsun/nio/ch/SelectorImpl;Lsun/nio/ch/PollSelectorImpl;
+HSPLsun/nio/ch/SocketChannelImpl;->translateAndSetReadyOps(ILsun/nio/ch/SelectionKeyImpl;)Z+]Lsun/nio/ch/SocketChannelImpl;Lsun/nio/ch/SocketChannelImpl;
+HSPLsun/nio/ch/SocketChannelImpl;->translateReadyOps(IILsun/nio/ch/SelectionKeyImpl;)Z+]Lsun/nio/ch/SelectionKeyImpl;Lsun/nio/ch/SelectionKeyImpl;
+HSPLsun/nio/ch/SocketDispatcher;->close(Ljava/io/FileDescriptor;)V
+HSPLsun/nio/ch/SocketDispatcher;->preClose(Ljava/io/FileDescriptor;)V
+HSPLsun/nio/ch/Util$1;->initialValue()Ljava/lang/Object;+]Lsun/nio/ch/Util$1;Lsun/nio/ch/Util$1;
+HSPLsun/nio/ch/Util$1;->initialValue()Lsun/nio/ch/Util$BufferCache;
+HSPLsun/nio/ch/Util$3;-><init>(Ljava/util/Set;)V
+HSPLsun/nio/ch/Util$BufferCache;-><init>()V
+HSPLsun/nio/ch/Util$BufferCache;->get(I)Ljava/nio/ByteBuffer;+]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLsun/nio/ch/Util$BufferCache;->isEmpty()Z
+HSPLsun/nio/ch/Util$BufferCache;->next(I)I
+HSPLsun/nio/ch/Util$BufferCache;->offerFirst(Ljava/nio/ByteBuffer;)Z
+HSPLsun/nio/ch/Util$BufferCache;->removeFirst()Ljava/nio/ByteBuffer;
+HSPLsun/nio/ch/Util;->access$000()I
+HSPLsun/nio/ch/Util;->atBugLevel(Ljava/lang/String;)Z
+HSPLsun/nio/ch/Util;->free(Ljava/nio/ByteBuffer;)V
+HSPLsun/nio/ch/Util;->getTemporaryDirectBuffer(I)Ljava/nio/ByteBuffer;+]Ljava/lang/ThreadLocal;Lsun/nio/ch/Util$1;]Lsun/nio/ch/Util$BufferCache;Lsun/nio/ch/Util$BufferCache;
+HSPLsun/nio/ch/Util;->isBufferTooLarge(I)Z
+HSPLsun/nio/ch/Util;->isBufferTooLarge(Ljava/nio/ByteBuffer;)Z+]Ljava/nio/ByteBuffer;Ljava/nio/DirectByteBuffer;
+HSPLsun/nio/ch/Util;->offerFirstTemporaryDirectBuffer(Ljava/nio/ByteBuffer;)V+]Ljava/lang/ThreadLocal;Lsun/nio/ch/Util$1;]Lsun/nio/ch/Util$BufferCache;Lsun/nio/ch/Util$BufferCache;
+HSPLsun/nio/ch/Util;->ungrowableSet(Ljava/util/Set;)Ljava/util/Set;
+HSPLsun/nio/cs/StreamDecoder;-><init>(Ljava/io/InputStream;Ljava/lang/Object;Ljava/nio/charset/Charset;)V+]Ljava/nio/charset/Charset;missing_types]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLsun/nio/cs/StreamDecoder;-><init>(Ljava/io/InputStream;Ljava/lang/Object;Ljava/nio/charset/CharsetDecoder;)V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLsun/nio/cs/StreamDecoder;->close()V+]Lsun/nio/cs/StreamDecoder;Lsun/nio/cs/StreamDecoder;
+HSPLsun/nio/cs/StreamDecoder;->ensureOpen()V
+HSPLsun/nio/cs/StreamDecoder;->forInputStreamReader(Ljava/io/InputStream;Ljava/lang/Object;Ljava/lang/String;)Lsun/nio/cs/StreamDecoder;+]Ljava/nio/charset/Charset;missing_types
+HSPLsun/nio/cs/StreamDecoder;->forInputStreamReader(Ljava/io/InputStream;Ljava/lang/Object;Ljava/nio/charset/Charset;)Lsun/nio/cs/StreamDecoder;
+HSPLsun/nio/cs/StreamDecoder;->forInputStreamReader(Ljava/io/InputStream;Ljava/lang/Object;Ljava/nio/charset/CharsetDecoder;)Lsun/nio/cs/StreamDecoder;
+HSPLsun/nio/cs/StreamDecoder;->implClose()V+]Ljava/io/InputStream;megamorphic_types
+HSPLsun/nio/cs/StreamDecoder;->implRead([CII)I+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;]Ljava/nio/charset/CharsetDecoder;Lcom/android/icu/charset/CharsetDecoderICU;
+HSPLsun/nio/cs/StreamDecoder;->implReady()Z+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLsun/nio/cs/StreamDecoder;->inReady()Z+]Ljava/io/InputStream;megamorphic_types
+HSPLsun/nio/cs/StreamDecoder;->read()I
+HSPLsun/nio/cs/StreamDecoder;->read([CII)I+]Lsun/nio/cs/StreamDecoder;Lsun/nio/cs/StreamDecoder;
+HSPLsun/nio/cs/StreamDecoder;->read0()I+]Lsun/nio/cs/StreamDecoder;Lsun/nio/cs/StreamDecoder;
+HSPLsun/nio/cs/StreamDecoder;->readBytes()I+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/io/InputStream;megamorphic_types
+HSPLsun/nio/cs/StreamDecoder;->ready()Z+]Lsun/nio/cs/StreamDecoder;Lsun/nio/cs/StreamDecoder;
+HSPLsun/nio/cs/StreamEncoder;-><init>(Ljava/io/OutputStream;Ljava/lang/Object;Ljava/nio/charset/Charset;)V+]Ljava/nio/charset/Charset;missing_types]Ljava/nio/charset/CharsetEncoder;missing_types
+HSPLsun/nio/cs/StreamEncoder;-><init>(Ljava/io/OutputStream;Ljava/lang/Object;Ljava/nio/charset/CharsetEncoder;)V+]Ljava/nio/charset/CharsetEncoder;missing_types
+HSPLsun/nio/cs/StreamEncoder;->close()V+]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;
+HSPLsun/nio/cs/StreamEncoder;->ensureOpen()V
+HSPLsun/nio/cs/StreamEncoder;->flush()V+]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;
+HSPLsun/nio/cs/StreamEncoder;->flushLeftoverChar(Ljava/nio/CharBuffer;Z)V+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/nio/charset/CharsetEncoder;missing_types]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;
+HSPLsun/nio/cs/StreamEncoder;->forOutputStreamWriter(Ljava/io/OutputStream;Ljava/lang/Object;Ljava/lang/String;)Lsun/nio/cs/StreamEncoder;+]Ljava/nio/charset/Charset;missing_types
+HSPLsun/nio/cs/StreamEncoder;->forOutputStreamWriter(Ljava/io/OutputStream;Ljava/lang/Object;Ljava/nio/charset/Charset;)Lsun/nio/cs/StreamEncoder;
+HSPLsun/nio/cs/StreamEncoder;->implClose()V+]Ljava/nio/charset/CharsetEncoder;missing_types]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/io/OutputStream;missing_types]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;
+HSPLsun/nio/cs/StreamEncoder;->implFlush()V+]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;]Ljava/io/OutputStream;missing_types
+HSPLsun/nio/cs/StreamEncoder;->implFlushBuffer()V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;
+HSPLsun/nio/cs/StreamEncoder;->implWrite([CII)V+]Ljava/nio/CharBuffer;Ljava/nio/HeapCharBuffer;]Ljava/nio/charset/CharsetEncoder;missing_types]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;
+HSPLsun/nio/cs/StreamEncoder;->write(I)V+]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;
+HSPLsun/nio/cs/StreamEncoder;->write(Ljava/lang/String;II)V+]Ljava/lang/String;Ljava/lang/String;]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;
+HSPLsun/nio/cs/StreamEncoder;->write([CII)V+]Lsun/nio/cs/StreamEncoder;Lsun/nio/cs/StreamEncoder;
+HSPLsun/nio/cs/StreamEncoder;->writeBytes()V+]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/io/OutputStream;missing_types
+HSPLsun/nio/cs/ThreadLocalCoders$1;->create(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLsun/nio/cs/ThreadLocalCoders$1;->hasName(Ljava/lang/Object;Ljava/lang/Object;)Z+]Ljava/nio/charset/Charset;missing_types]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLsun/nio/cs/ThreadLocalCoders$2;->create(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLsun/nio/cs/ThreadLocalCoders$2;->hasName(Ljava/lang/Object;Ljava/lang/Object;)Z+]Ljava/nio/charset/Charset;missing_types]Ljava/nio/charset/CharsetEncoder;missing_types
+HSPLsun/nio/cs/ThreadLocalCoders$Cache;->forName(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/lang/ThreadLocal;Ljava/lang/ThreadLocal;]Lsun/nio/cs/ThreadLocalCoders$Cache;Lsun/nio/cs/ThreadLocalCoders$2;,Lsun/nio/cs/ThreadLocalCoders$1;
+HSPLsun/nio/cs/ThreadLocalCoders$Cache;->moveToFront([Ljava/lang/Object;I)V
+HSPLsun/nio/cs/ThreadLocalCoders;->decoderFor(Ljava/lang/Object;)Ljava/nio/charset/CharsetDecoder;+]Lsun/nio/cs/ThreadLocalCoders$Cache;Lsun/nio/cs/ThreadLocalCoders$1;]Ljava/nio/charset/CharsetDecoder;missing_types
+HSPLsun/nio/cs/ThreadLocalCoders;->encoderFor(Ljava/lang/Object;)Ljava/nio/charset/CharsetEncoder;+]Ljava/nio/charset/CharsetEncoder;missing_types]Lsun/nio/cs/ThreadLocalCoders$Cache;Lsun/nio/cs/ThreadLocalCoders$2;
+HSPLsun/nio/fs/AbstractBasicFileAttributeView;-><init>()V
+HSPLsun/nio/fs/AbstractPath;-><init>()V
+HSPLsun/nio/fs/AbstractPath;->resolve(Ljava/lang/String;)Ljava/nio/file/Path;+]Ljava/nio/file/FileSystem;Lsun/nio/fs/LinuxFileSystem;]Lsun/nio/fs/AbstractPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/AbstractPath;->toFile()Ljava/io/File;+]Ljava/lang/Object;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/LinuxFileSystemProvider;->getFileAttributeView(Ljava/nio/file/Path;Ljava/lang/Class;[Ljava/nio/file/LinkOption;)Ljava/nio/file/attribute/FileAttributeView;
+HSPLsun/nio/fs/LinuxFileSystemProvider;->readAttributes(Ljava/nio/file/Path;Ljava/lang/Class;[Ljava/nio/file/LinkOption;)Ljava/nio/file/attribute/BasicFileAttributes;
+HSPLsun/nio/fs/NativeBuffer$Deallocator;-><init>(J)V
+HSPLsun/nio/fs/NativeBuffer$Deallocator;->run()V
+HSPLsun/nio/fs/NativeBuffer;-><init>(I)V
+HSPLsun/nio/fs/NativeBuffer;->access$000()Lsun/misc/Unsafe;
+HSPLsun/nio/fs/NativeBuffer;->address()J
+HSPLsun/nio/fs/NativeBuffer;->owner()Ljava/lang/Object;
+HSPLsun/nio/fs/NativeBuffer;->release()V
+HSPLsun/nio/fs/NativeBuffer;->setOwner(Ljava/lang/Object;)V
+HSPLsun/nio/fs/NativeBuffer;->size()I
+HSPLsun/nio/fs/NativeBuffers;->allocNativeBuffer(I)Lsun/nio/fs/NativeBuffer;
+HSPLsun/nio/fs/NativeBuffers;->copyCStringToNativeBuffer([BLsun/nio/fs/NativeBuffer;)V+]Lsun/nio/fs/NativeBuffer;Lsun/nio/fs/NativeBuffer;]Lsun/misc/Unsafe;Lsun/misc/Unsafe;
+HSPLsun/nio/fs/NativeBuffers;->getNativeBufferFromCache(I)Lsun/nio/fs/NativeBuffer;+]Ljava/lang/ThreadLocal;Ljava/lang/ThreadLocal;]Lsun/nio/fs/NativeBuffer;Lsun/nio/fs/NativeBuffer;
+HSPLsun/nio/fs/NativeBuffers;->releaseNativeBuffer(Lsun/nio/fs/NativeBuffer;)V+]Ljava/lang/ThreadLocal;Ljava/lang/ThreadLocal;
+HSPLsun/nio/fs/UnixChannelFactory$1;-><clinit>()V
+HSPLsun/nio/fs/UnixChannelFactory$Flags;-><init>()V
+HSPLsun/nio/fs/UnixChannelFactory$Flags;->toFlags(Ljava/util/Set;)Lsun/nio/fs/UnixChannelFactory$Flags;+]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;]Ljava/util/Set;Ljava/util/HashSet;]Ljava/nio/file/StandardOpenOption;Ljava/nio/file/StandardOpenOption;
+HSPLsun/nio/fs/UnixChannelFactory;->newFileChannel(ILsun/nio/fs/UnixPath;Ljava/lang/String;Ljava/util/Set;I)Ljava/nio/channels/FileChannel;+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixChannelFactory;->newFileChannel(Lsun/nio/fs/UnixPath;Ljava/util/Set;I)Ljava/nio/channels/FileChannel;
+HSPLsun/nio/fs/UnixChannelFactory;->open(ILsun/nio/fs/UnixPath;Ljava/lang/String;Lsun/nio/fs/UnixChannelFactory$Flags;I)Ljava/io/FileDescriptor;+]Lsun/misc/JavaIOFileDescriptorAccess;Ljava/io/FileDescriptor$1;
+HSPLsun/nio/fs/UnixDirectoryStream$UnixDirectoryIterator;-><clinit>()V
+HSPLsun/nio/fs/UnixDirectoryStream$UnixDirectoryIterator;-><init>(Lsun/nio/fs/UnixDirectoryStream;Ljava/nio/file/DirectoryStream;)V
+HSPLsun/nio/fs/UnixDirectoryStream$UnixDirectoryIterator;->hasNext()Z
+HSPLsun/nio/fs/UnixDirectoryStream$UnixDirectoryIterator;->isSelfOrParent([B)Z
+HSPLsun/nio/fs/UnixDirectoryStream$UnixDirectoryIterator;->readNextEntry()Ljava/nio/file/Path;+]Lsun/nio/fs/UnixDirectoryStream;Lsun/nio/fs/UnixDirectoryStream;]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;]Ljava/nio/file/DirectoryStream$Filter;Ljava/nio/file/Files$AcceptAllFilter;]Ljava/util/concurrent/locks/Lock;Ljava/util/concurrent/locks/ReentrantReadWriteLock$ReadLock;
+HSPLsun/nio/fs/UnixDirectoryStream;-><init>(Lsun/nio/fs/UnixPath;JLjava/nio/file/DirectoryStream$Filter;)V+]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
+HSPLsun/nio/fs/UnixDirectoryStream;->access$000(Lsun/nio/fs/UnixDirectoryStream;)J
+HSPLsun/nio/fs/UnixDirectoryStream;->closeImpl()Z+]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
+HSPLsun/nio/fs/UnixDirectoryStream;->isOpen()Z
+HSPLsun/nio/fs/UnixDirectoryStream;->iterator(Ljava/nio/file/DirectoryStream;)Ljava/util/Iterator;
+HSPLsun/nio/fs/UnixDirectoryStream;->readLock()Ljava/util/concurrent/locks/Lock;+]Ljava/util/concurrent/locks/ReentrantReadWriteLock;Ljava/util/concurrent/locks/ReentrantReadWriteLock;
+HSPLsun/nio/fs/UnixDirectoryStream;->writeLock()Ljava/util/concurrent/locks/Lock;+]Ljava/util/concurrent/locks/ReentrantReadWriteLock;Ljava/util/concurrent/locks/ReentrantReadWriteLock;
+HSPLsun/nio/fs/UnixException;-><init>(I)V
+HSPLsun/nio/fs/UnixException;->errno()I
+HSPLsun/nio/fs/UnixException;->rethrowAsIOException(Lsun/nio/fs/UnixPath;)V+]Lsun/nio/fs/UnixException;Lsun/nio/fs/UnixException;
+HSPLsun/nio/fs/UnixException;->rethrowAsIOException(Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;)V+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixException;->translateToIOException(Ljava/lang/String;Ljava/lang/String;)Ljava/io/IOException;+]Lsun/nio/fs/UnixException;Lsun/nio/fs/UnixException;
+HSPLsun/nio/fs/UnixFileAttributeViews$Basic;-><init>(Lsun/nio/fs/UnixPath;Z)V
+HSPLsun/nio/fs/UnixFileAttributeViews$Basic;->readAttributes()Ljava/nio/file/attribute/BasicFileAttributes;+]Lsun/nio/fs/UnixException;Lsun/nio/fs/UnixException;]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;]Lsun/nio/fs/UnixFileAttributes;Lsun/nio/fs/UnixFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributeViews;->createBasicView(Lsun/nio/fs/UnixPath;Z)Lsun/nio/fs/UnixFileAttributeViews$Basic;
+HSPLsun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes;-><init>(Lsun/nio/fs/UnixFileAttributes;)V
+HSPLsun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes;->creationTime()Ljava/nio/file/attribute/FileTime;+]Lsun/nio/fs/UnixFileAttributes;Lsun/nio/fs/UnixFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes;->isDirectory()Z+]Lsun/nio/fs/UnixFileAttributes;Lsun/nio/fs/UnixFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes;->isRegularFile()Z+]Lsun/nio/fs/UnixFileAttributes;Lsun/nio/fs/UnixFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes;->lastAccessTime()Ljava/nio/file/attribute/FileTime;+]Lsun/nio/fs/UnixFileAttributes;Lsun/nio/fs/UnixFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes;->lastModifiedTime()Ljava/nio/file/attribute/FileTime;+]Lsun/nio/fs/UnixFileAttributes;Lsun/nio/fs/UnixFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes;->size()J+]Lsun/nio/fs/UnixFileAttributes;Lsun/nio/fs/UnixFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes;->wrap(Lsun/nio/fs/UnixFileAttributes;)Lsun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributes;-><init>()V
+HSPLsun/nio/fs/UnixFileAttributes;->asBasicFileAttributes()Ljava/nio/file/attribute/BasicFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributes;->creationTime()Ljava/nio/file/attribute/FileTime;+]Lsun/nio/fs/UnixFileAttributes;Lsun/nio/fs/UnixFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributes;->get(Lsun/nio/fs/UnixPath;Z)Lsun/nio/fs/UnixFileAttributes;
+HSPLsun/nio/fs/UnixFileAttributes;->isDirectory()Z
+HSPLsun/nio/fs/UnixFileAttributes;->isRegularFile()Z
+HSPLsun/nio/fs/UnixFileAttributes;->isSymbolicLink()Z
+HSPLsun/nio/fs/UnixFileAttributes;->lastAccessTime()Ljava/nio/file/attribute/FileTime;
+HSPLsun/nio/fs/UnixFileAttributes;->lastModifiedTime()Ljava/nio/file/attribute/FileTime;
+HSPLsun/nio/fs/UnixFileAttributes;->size()J
+HSPLsun/nio/fs/UnixFileAttributes;->toFileTime(JJ)Ljava/nio/file/attribute/FileTime;
+HSPLsun/nio/fs/UnixFileModeAttribute;->toUnixMode(I[Ljava/nio/file/attribute/FileAttribute;)I
+HSPLsun/nio/fs/UnixFileSystem;->getPath(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLsun/nio/fs/UnixFileSystem;->needToResolveAgainstDefaultDirectory()Z
+HSPLsun/nio/fs/UnixFileSystem;->normalizeJavaPath(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/nio/fs/UnixFileSystem;->normalizeNativePath([C)[C
+HSPLsun/nio/fs/UnixFileSystem;->provider()Ljava/nio/file/spi/FileSystemProvider;
+HSPLsun/nio/fs/UnixFileSystemProvider$3;-><clinit>()V
+HSPLsun/nio/fs/UnixFileSystemProvider;->checkAccess(Ljava/nio/file/Path;[Ljava/nio/file/AccessMode;)V+]Lsun/nio/fs/UnixException;Lsun/nio/fs/UnixException;]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixFileSystemProvider;->checkPath(Ljava/nio/file/Path;)Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixFileSystemProvider;->getFileAttributeView(Ljava/nio/file/Path;Ljava/lang/Class;[Ljava/nio/file/LinkOption;)Ljava/nio/file/attribute/FileAttributeView;
+HSPLsun/nio/fs/UnixFileSystemProvider;->newByteChannel(Ljava/nio/file/Path;Ljava/util/Set;[Ljava/nio/file/attribute/FileAttribute;)Ljava/nio/channels/SeekableByteChannel;+]Lsun/nio/fs/UnixException;Lsun/nio/fs/UnixException;
+HSPLsun/nio/fs/UnixFileSystemProvider;->newDirectoryStream(Ljava/nio/file/Path;Ljava/nio/file/DirectoryStream$Filter;)Ljava/nio/file/DirectoryStream;+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixFileSystemProvider;->newFileChannel(Ljava/nio/file/Path;Ljava/util/Set;[Ljava/nio/file/attribute/FileAttribute;)Ljava/nio/channels/FileChannel;+]Lsun/nio/fs/UnixFileSystemProvider;Lsun/nio/fs/LinuxFileSystemProvider;
+HSPLsun/nio/fs/UnixFileSystemProvider;->readAttributes(Ljava/nio/file/Path;Ljava/lang/Class;[Ljava/nio/file/LinkOption;)Ljava/nio/file/attribute/BasicFileAttributes;+]Ljava/nio/file/attribute/BasicFileAttributeView;Lsun/nio/fs/UnixFileAttributeViews$Basic;]Lsun/nio/fs/UnixFileSystemProvider;Lsun/nio/fs/LinuxFileSystemProvider;
+HSPLsun/nio/fs/UnixNativeDispatcher;->access(Lsun/nio/fs/UnixPath;I)V
+HSPLsun/nio/fs/UnixNativeDispatcher;->copyToNativeBuffer(Lsun/nio/fs/UnixPath;)Lsun/nio/fs/NativeBuffer;
+HSPLsun/nio/fs/UnixNativeDispatcher;->lstat(Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixFileAttributes;)V
+HSPLsun/nio/fs/UnixNativeDispatcher;->open(Lsun/nio/fs/UnixPath;II)I
+HSPLsun/nio/fs/UnixNativeDispatcher;->openatSupported()Z
+HSPLsun/nio/fs/UnixPath;-><init>(Lsun/nio/fs/UnixFileSystem;Ljava/lang/String;)V
+HSPLsun/nio/fs/UnixPath;-><init>(Lsun/nio/fs/UnixFileSystem;[B)V
+HSPLsun/nio/fs/UnixPath;->asByteArray()[B
+HSPLsun/nio/fs/UnixPath;->checkNotNul(Ljava/lang/String;C)V
+HSPLsun/nio/fs/UnixPath;->checkRead()V
+HSPLsun/nio/fs/UnixPath;->checkWrite()V
+HSPLsun/nio/fs/UnixPath;->encode(Lsun/nio/fs/UnixFileSystem;Ljava/lang/String;)[B+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/ref/SoftReference;Ljava/lang/ref/SoftReference;]Ljava/nio/charset/Charset;missing_types]Ljava/nio/ByteBuffer;Ljava/nio/HeapByteBuffer;]Ljava/nio/charset/CharsetEncoder;missing_types]Ljava/lang/ThreadLocal;Ljava/lang/ThreadLocal;]Lsun/nio/fs/UnixFileSystem;Lsun/nio/fs/LinuxFileSystem;]Ljava/nio/charset/CoderResult;Ljava/nio/charset/CoderResult;
+HSPLsun/nio/fs/UnixPath;->getByteArrayForSysCalls()[B+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;]Lsun/nio/fs/UnixFileSystem;Lsun/nio/fs/LinuxFileSystem;
+HSPLsun/nio/fs/UnixPath;->getFileSystem()Ljava/nio/file/FileSystem;+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixPath;->getFileSystem()Lsun/nio/fs/UnixFileSystem;
+HSPLsun/nio/fs/UnixPath;->getParent()Ljava/nio/file/Path;+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixPath;->getParent()Lsun/nio/fs/UnixPath;+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixPath;->getPathForExceptionMessage()Ljava/lang/String;+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixPath;->initOffsets()V
+HSPLsun/nio/fs/UnixPath;->isEmpty()Z
+HSPLsun/nio/fs/UnixPath;->normalizeAndCheck(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/nio/fs/UnixPath;->resolve(Ljava/nio/file/Path;)Ljava/nio/file/Path;+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixPath;->resolve(Ljava/nio/file/Path;)Lsun/nio/fs/UnixPath;+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixPath;->resolve([B)Lsun/nio/fs/UnixPath;+]Lsun/nio/fs/UnixPath;Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixPath;->resolve([B[B)[B
+HSPLsun/nio/fs/UnixPath;->toString()Ljava/lang/String;+]Lsun/nio/fs/UnixFileSystem;Lsun/nio/fs/LinuxFileSystem;
+HSPLsun/nio/fs/UnixPath;->toUnixPath(Ljava/nio/file/Path;)Lsun/nio/fs/UnixPath;
+HSPLsun/nio/fs/UnixSecureDirectoryStream;-><init>(Lsun/nio/fs/UnixPath;JILjava/nio/file/DirectoryStream$Filter;)V+]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
+HSPLsun/nio/fs/UnixSecureDirectoryStream;->close()V+]Lsun/nio/fs/UnixDirectoryStream;Lsun/nio/fs/UnixDirectoryStream;]Ljava/util/concurrent/locks/Lock;Ljava/util/concurrent/locks/ReentrantReadWriteLock$WriteLock;]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
+HSPLsun/nio/fs/UnixSecureDirectoryStream;->iterator()Ljava/util/Iterator;
+HSPLsun/nio/fs/Util;->followLinks([Ljava/nio/file/LinkOption;)Z
+HSPLsun/nio/fs/Util;->jnuEncoding()Ljava/nio/charset/Charset;
+HSPLsun/nio/fs/Util;->toString([B)Ljava/lang/String;
+HSPLsun/reflect/Reflection;->ensureMemberAccess(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;I)V
+HSPLsun/reflect/Reflection;->getCallerClass()Ljava/lang/Class;
+HSPLsun/reflect/Reflection;->isSameClassPackage(Ljava/lang/Class;Ljava/lang/Class;)Z
+HSPLsun/reflect/Reflection;->isSameClassPackage(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Z
+HSPLsun/reflect/Reflection;->verifyMemberAccess(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;I)Z
+HSPLsun/reflect/misc/ReflectUtil;->ensureMemberAccess(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;I)V
+HSPLsun/security/action/GetPropertyAction;-><init>(Ljava/lang/String;)V
+HSPLsun/security/action/GetPropertyAction;->run()Ljava/lang/Object;+]Lsun/security/action/GetPropertyAction;Lsun/security/action/GetPropertyAction;
+HSPLsun/security/action/GetPropertyAction;->run()Ljava/lang/String;
+HSPLsun/security/jca/GetInstance$Instance;-><init>(Ljava/security/Provider;Ljava/lang/Object;)V
+HSPLsun/security/jca/GetInstance$Instance;-><init>(Ljava/security/Provider;Ljava/lang/Object;Lsun/security/jca/GetInstance$1;)V
+HSPLsun/security/jca/GetInstance$Instance;->toArray()[Ljava/lang/Object;
+HSPLsun/security/jca/GetInstance;->checkSuperClass(Ljava/security/Provider$Service;Ljava/lang/Class;Ljava/lang/Class;)V+]Ljava/lang/Class;Ljava/lang/Class;
+HSPLsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)Lsun/security/jca/GetInstance$Instance;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Lsun/security/jca/GetInstance$Instance;
+HSPLsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;)Lsun/security/jca/GetInstance$Instance;
+HSPLsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/security/Provider;)Lsun/security/jca/GetInstance$Instance;
+HSPLsun/security/jca/GetInstance;->getInstance(Ljava/security/Provider$Service;Ljava/lang/Class;)Lsun/security/jca/GetInstance$Instance;+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/lang/Object;megamorphic_types
+HSPLsun/security/jca/GetInstance;->getInstance(Ljava/security/Provider$Service;Ljava/lang/Class;Ljava/lang/Object;)Lsun/security/jca/GetInstance$Instance;+]Ljava/security/Provider$Service;Ljava/security/Provider$Service;]Ljava/lang/Object;Lcom/android/org/bouncycastle/jce/provider/CertStoreCollectionSpi;
+HSPLsun/security/jca/GetInstance;->getService(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/security/Provider$Service;+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;]Ljava/security/Provider;missing_types
+HSPLsun/security/jca/GetInstance;->getService(Ljava/lang/String;Ljava/lang/String;Ljava/security/Provider;)Ljava/security/Provider$Service;+]Ljava/security/Provider;Lcom/android/org/conscrypt/OpenSSLProvider;
+HSPLsun/security/jca/GetInstance;->getServices(Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/JCAUtil;->getSecureRandom()Ljava/security/SecureRandom;
+HSPLsun/security/jca/ProviderConfig;-><init>(Ljava/lang/String;)V
+HSPLsun/security/jca/ProviderConfig;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+HSPLsun/security/jca/ProviderConfig;-><init>(Ljava/security/Provider;)V
+HSPLsun/security/jca/ProviderConfig;->equals(Ljava/lang/Object;)Z
+HSPLsun/security/jca/ProviderConfig;->expand(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/security/jca/ProviderConfig;->getProvider()Ljava/security/Provider;
+HSPLsun/security/jca/ProviderList$3;-><init>(Lsun/security/jca/ProviderList;)V
+HSPLsun/security/jca/ProviderList$3;->get(I)Ljava/lang/Object;+]Lsun/security/jca/ProviderList$3;Lsun/security/jca/ProviderList$3;
+HSPLsun/security/jca/ProviderList$3;->get(I)Ljava/security/Provider;+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/ProviderList$3;->size()I
+HSPLsun/security/jca/ProviderList$ServiceList$1;-><init>(Lsun/security/jca/ProviderList$ServiceList;)V
+HSPLsun/security/jca/ProviderList$ServiceList$1;->hasNext()Z
+HSPLsun/security/jca/ProviderList$ServiceList$1;->next()Ljava/lang/Object;+]Lsun/security/jca/ProviderList$ServiceList$1;Lsun/security/jca/ProviderList$ServiceList$1;
+HSPLsun/security/jca/ProviderList$ServiceList$1;->next()Ljava/security/Provider$Service;
+HSPLsun/security/jca/ProviderList$ServiceList;-><init>(Lsun/security/jca/ProviderList;Ljava/lang/String;Ljava/lang/String;)V
+HSPLsun/security/jca/ProviderList$ServiceList;->access$200(Lsun/security/jca/ProviderList$ServiceList;I)Ljava/security/Provider$Service;
+HSPLsun/security/jca/ProviderList$ServiceList;->addService(Ljava/security/Provider$Service;)V+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLsun/security/jca/ProviderList$ServiceList;->iterator()Ljava/util/Iterator;
+HSPLsun/security/jca/ProviderList$ServiceList;->tryGet(I)Ljava/security/Provider$Service;+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;]Ljava/security/Provider;megamorphic_types]Ljava/util/List;Ljava/util/ArrayList;,Ljava/util/Arrays$ArrayList;]Ljava/util/Iterator;Ljava/util/AbstractList$Itr;
+HSPLsun/security/jca/ProviderList;-><init>([Lsun/security/jca/ProviderConfig;Z)V
+HSPLsun/security/jca/ProviderList;->access$100(Lsun/security/jca/ProviderList;)[Lsun/security/jca/ProviderConfig;
+HSPLsun/security/jca/ProviderList;->getIndex(Ljava/lang/String;)I+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;]Ljava/security/Provider;megamorphic_types
+HSPLsun/security/jca/ProviderList;->getJarList([Ljava/lang/String;)Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/ProviderList;->getProvider(I)Ljava/security/Provider;+]Lsun/security/jca/ProviderConfig;Lsun/security/jca/ProviderConfig;
+HSPLsun/security/jca/ProviderList;->getProvider(Ljava/lang/String;)Ljava/security/Provider;+]Lsun/security/jca/ProviderConfig;Lsun/security/jca/ProviderConfig;
+HSPLsun/security/jca/ProviderList;->getProviderConfig(Ljava/lang/String;)Lsun/security/jca/ProviderConfig;+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/ProviderList;->getService(Ljava/lang/String;Ljava/lang/String;)Ljava/security/Provider$Service;+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;]Ljava/security/Provider;megamorphic_types
+HSPLsun/security/jca/ProviderList;->getServices(Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
+HSPLsun/security/jca/ProviderList;->insertAt(Lsun/security/jca/ProviderList;Ljava/security/Provider;I)Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/ProviderList;->loadAll()I
+HSPLsun/security/jca/ProviderList;->providers()Ljava/util/List;
+HSPLsun/security/jca/ProviderList;->removeInvalid()Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/ProviderList;->toArray()[Ljava/security/Provider;+]Lsun/security/jca/ProviderList;Lsun/security/jca/ProviderList;]Ljava/util/List;Lsun/security/jca/ProviderList$3;
+HSPLsun/security/jca/Providers;->beginThreadProviderList(Lsun/security/jca/ProviderList;)Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/Providers;->checkBouncyCastleDeprecation(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+HSPLsun/security/jca/Providers;->checkBouncyCastleDeprecation(Ljava/security/Provider;Ljava/lang/String;Ljava/lang/String;)V
+HSPLsun/security/jca/Providers;->endThreadProviderList(Lsun/security/jca/ProviderList;)V
+HSPLsun/security/jca/Providers;->getFullProviderList()Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/Providers;->getProviderList()Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/Providers;->getSystemProviderList()Lsun/security/jca/ProviderList;
+HSPLsun/security/jca/Providers;->getThreadProviderList()Lsun/security/jca/ProviderList;+]Ljava/lang/ThreadLocal;Ljava/lang/InheritableThreadLocal;
+HSPLsun/security/jca/Providers;->setProviderList(Lsun/security/jca/ProviderList;)V
+HSPLsun/security/jca/Providers;->setSystemProviderList(Lsun/security/jca/ProviderList;)V
+HSPLsun/security/jca/Providers;->startJarVerification()Ljava/lang/Object;
+HSPLsun/security/jca/Providers;->stopJarVerification(Ljava/lang/Object;)V
+HSPLsun/security/pkcs/ContentInfo;-><init>(Lsun/security/util/DerInputStream;)V
+HSPLsun/security/pkcs/ContentInfo;-><init>(Lsun/security/util/DerInputStream;Z)V
+HSPLsun/security/pkcs/ContentInfo;->getContent()Lsun/security/util/DerValue;
+HSPLsun/security/pkcs/ContentInfo;->getData()[B
+HSPLsun/security/pkcs/PKCS7$VerbatimX509Certificate;-><init>(Ljava/security/cert/X509Certificate;[B)V
+HSPLsun/security/pkcs/PKCS7$WrappedX509Certificate;-><init>(Ljava/security/cert/X509Certificate;)V
+HSPLsun/security/pkcs/PKCS7$WrappedX509Certificate;->getIssuerDN()Ljava/security/Principal;
+HSPLsun/security/pkcs/PKCS7$WrappedX509Certificate;->getKeyUsage()[Z
+HSPLsun/security/pkcs/PKCS7$WrappedX509Certificate;->getPublicKey()Ljava/security/PublicKey;
+HSPLsun/security/pkcs/PKCS7$WrappedX509Certificate;->getSerialNumber()Ljava/math/BigInteger;
+HSPLsun/security/pkcs/PKCS7$WrappedX509Certificate;->getSubjectDN()Ljava/security/Principal;
+HSPLsun/security/pkcs/PKCS7$WrappedX509Certificate;->getTBSCertificate()[B
+HSPLsun/security/pkcs/PKCS7$WrappedX509Certificate;->hasUnsupportedCriticalExtension()Z
+HSPLsun/security/pkcs/PKCS7;-><init>([B)V
+HSPLsun/security/pkcs/PKCS7;->getCertificate(Ljava/math/BigInteger;Lsun/security/x509/X500Name;)Ljava/security/cert/X509Certificate;
+HSPLsun/security/pkcs/PKCS7;->getCertificates()[Ljava/security/cert/X509Certificate;
+HSPLsun/security/pkcs/PKCS7;->getContentInfo()Lsun/security/pkcs/ContentInfo;
+HSPLsun/security/pkcs/PKCS7;->parse(Lsun/security/util/DerInputStream;)V
+HSPLsun/security/pkcs/PKCS7;->parse(Lsun/security/util/DerInputStream;Z)V
+HSPLsun/security/pkcs/PKCS7;->parseSignedData(Lsun/security/util/DerValue;)V
+HSPLsun/security/pkcs/PKCS7;->populateCertIssuerNames()V
+HSPLsun/security/pkcs/PKCS7;->verify(Lsun/security/pkcs/SignerInfo;[B)Lsun/security/pkcs/SignerInfo;
+HSPLsun/security/pkcs/PKCS7;->verify([B)[Lsun/security/pkcs/SignerInfo;
+HSPLsun/security/pkcs/SignerInfo;-><init>(Lsun/security/util/DerInputStream;)V
+HSPLsun/security/pkcs/SignerInfo;-><init>(Lsun/security/util/DerInputStream;Z)V
+HSPLsun/security/pkcs/SignerInfo;->getCertificate(Lsun/security/pkcs/PKCS7;)Ljava/security/cert/X509Certificate;
+HSPLsun/security/pkcs/SignerInfo;->getCertificateChain(Lsun/security/pkcs/PKCS7;)Ljava/util/ArrayList;
+HSPLsun/security/pkcs/SignerInfo;->getDigestAlgorithmId()Lsun/security/x509/AlgorithmId;
+HSPLsun/security/pkcs/SignerInfo;->getDigestEncryptionAlgorithmId()Lsun/security/x509/AlgorithmId;
+HSPLsun/security/pkcs/SignerInfo;->getTimestamp()Ljava/security/Timestamp;
+HSPLsun/security/pkcs/SignerInfo;->getTsToken()Lsun/security/pkcs/PKCS7;
+HSPLsun/security/pkcs/SignerInfo;->verify(Lsun/security/pkcs/PKCS7;Ljava/io/InputStream;)Lsun/security/pkcs/SignerInfo;+]Ljava/security/Signature;Ljava/security/Signature$Delegate;]Ljava/security/cert/X509Certificate;Lsun/security/pkcs/PKCS7$VerbatimX509Certificate;]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;]Lsun/security/util/DisabledAlgorithmConstraints;Lsun/security/util/DisabledAlgorithmConstraints;]Ljava/io/InputStream;Ljava/io/ByteArrayInputStream;]Lsun/security/pkcs/SignerInfo;Lsun/security/pkcs/SignerInfo;]Lsun/security/pkcs/PKCS7;Lsun/security/pkcs/PKCS7;
+HSPLsun/security/pkcs/SignerInfo;->verify(Lsun/security/pkcs/PKCS7;[B)Lsun/security/pkcs/SignerInfo;
+HSPLsun/security/provider/X509Factory;->addToCache(Lsun/security/util/Cache;[BLjava/lang/Object;)V+]Lsun/security/util/Cache;Lsun/security/util/MemoryCache;
+HSPLsun/security/provider/X509Factory;->getFromCache(Lsun/security/util/Cache;[B)Ljava/lang/Object;+]Lsun/security/util/Cache;Lsun/security/util/MemoryCache;
+HSPLsun/security/provider/X509Factory;->intern(Ljava/security/cert/X509Certificate;)Lsun/security/x509/X509CertImpl;+]Ljava/security/cert/X509Certificate;missing_types]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/provider/certpath/AdaptableX509CertSelector;-><init>()V
+HSPLsun/security/provider/certpath/AdaptableX509CertSelector;->match(Ljava/security/cert/Certificate;)Z+]Ljava/security/cert/X509Certificate;missing_types]Ljava/math/BigInteger;Ljava/math/BigInteger;
+HSPLsun/security/provider/certpath/AdaptableX509CertSelector;->matchSubjectKeyID(Ljava/security/cert/X509Certificate;)Z+]Ljava/security/cert/X509Certificate;missing_types]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/provider/certpath/AdaptableX509CertSelector;->setSkiAndSerialNumber(Lsun/security/x509/AuthorityKeyIdentifierExtension;)V+]Lsun/security/x509/AuthorityKeyIdentifierExtension;Lsun/security/x509/AuthorityKeyIdentifierExtension;
+HSPLsun/security/provider/certpath/AlgorithmChecker;-><init>(Ljava/security/cert/TrustAnchor;)V
+HSPLsun/security/provider/certpath/AlgorithmChecker;-><init>(Ljava/security/cert/TrustAnchor;Ljava/security/AlgorithmConstraints;)V+]Ljava/security/cert/X509Certificate;missing_types]Ljava/security/cert/TrustAnchor;Ljava/security/cert/TrustAnchor;
+HSPLsun/security/provider/certpath/AlgorithmChecker;->check(Ljava/security/PublicKey;Lsun/security/x509/AlgorithmId;)V
+HSPLsun/security/provider/certpath/AlgorithmChecker;->check(Ljava/security/cert/Certificate;Ljava/util/Collection;)V+]Ljava/security/cert/X509Certificate;missing_types]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;]Ljava/security/cert/Certificate;missing_types]Lsun/security/util/DisabledAlgorithmConstraints;Lsun/security/util/DisabledAlgorithmConstraints;]Ljava/security/AlgorithmConstraints;Lsun/security/util/DisabledAlgorithmConstraints;]Ljava/util/Set;Ljava/util/RegularEnumSet;
+HSPLsun/security/provider/certpath/AlgorithmChecker;->checkFingerprint(Ljava/security/cert/X509Certificate;)Z
+HSPLsun/security/provider/certpath/AlgorithmChecker;->init(Z)V
+HSPLsun/security/provider/certpath/BasicChecker;-><init>(Ljava/security/cert/TrustAnchor;Ljava/util/Date;Ljava/lang/String;Z)V+]Ljava/security/cert/X509Certificate;missing_types]Ljava/security/cert/TrustAnchor;Ljava/security/cert/TrustAnchor;
+HSPLsun/security/provider/certpath/BasicChecker;->check(Ljava/security/cert/Certificate;Ljava/util/Collection;)V
+HSPLsun/security/provider/certpath/BasicChecker;->getPublicKey()Ljava/security/PublicKey;
+HSPLsun/security/provider/certpath/BasicChecker;->init(Z)V
+HSPLsun/security/provider/certpath/BasicChecker;->updateState(Ljava/security/cert/X509Certificate;)V+]Ljava/security/cert/X509Certificate;missing_types
+HSPLsun/security/provider/certpath/BasicChecker;->verifyNameChaining(Ljava/security/cert/X509Certificate;)V+]Ljava/security/cert/X509Certificate;missing_types]Ljavax/security/auth/x500/X500Principal;Ljavax/security/auth/x500/X500Principal;]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLsun/security/provider/certpath/BasicChecker;->verifySignature(Ljava/security/cert/X509Certificate;)V+]Ljava/security/cert/X509Certificate;missing_types
+HSPLsun/security/provider/certpath/BasicChecker;->verifyTimestamp(Ljava/security/cert/X509Certificate;)V+]Ljava/security/cert/X509Certificate;missing_types
+HSPLsun/security/provider/certpath/CertId;-><init>(Ljava/security/cert/X509Certificate;Lsun/security/x509/SerialNumber;)V
+HSPLsun/security/provider/certpath/CertId;-><init>(Ljavax/security/auth/x500/X500Principal;Ljava/security/PublicKey;Lsun/security/x509/SerialNumber;)V+]Ljavax/security/auth/x500/X500Principal;Ljavax/security/auth/x500/X500Principal;]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Ljava/security/PublicKey;missing_types]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;
+HSPLsun/security/provider/certpath/CertId;-><init>(Lsun/security/util/DerInputStream;)V+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/provider/certpath/CertId;->equals(Ljava/lang/Object;)Z+]Ljava/math/BigInteger;Ljava/math/BigInteger;]Lsun/security/provider/certpath/CertId;Lsun/security/provider/certpath/CertId;]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;]Lsun/security/x509/SerialNumber;Lsun/security/x509/SerialNumber;
+HSPLsun/security/provider/certpath/CertId;->getHashAlgorithm()Lsun/security/x509/AlgorithmId;
+HSPLsun/security/provider/certpath/CertId;->getIssuerKeyHash()[B
+HSPLsun/security/provider/certpath/CertId;->getIssuerNameHash()[B
+HSPLsun/security/provider/certpath/CertId;->getSerialNumber()Ljava/math/BigInteger;
+HSPLsun/security/provider/certpath/CertId;->hashCode()I+]Ljava/math/BigInteger;Ljava/math/BigInteger;]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;]Lsun/security/x509/SerialNumber;Lsun/security/x509/SerialNumber;
+HSPLsun/security/provider/certpath/ConstraintsChecker;-><init>(I)V
+HSPLsun/security/provider/certpath/ConstraintsChecker;->check(Ljava/security/cert/Certificate;Ljava/util/Collection;)V+]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;]Ljava/util/Collection;Ljava/util/HashSet;
+HSPLsun/security/provider/certpath/ConstraintsChecker;->checkBasicConstraints(Ljava/security/cert/X509Certificate;)V+]Ljava/security/cert/X509Certificate;missing_types
+HSPLsun/security/provider/certpath/ConstraintsChecker;->init(Z)V
+HSPLsun/security/provider/certpath/ConstraintsChecker;->mergeNameConstraints(Ljava/security/cert/X509Certificate;Lsun/security/x509/NameConstraintsExtension;)Lsun/security/x509/NameConstraintsExtension;+]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/provider/certpath/ConstraintsChecker;->verifyNameConstraints(Ljava/security/cert/X509Certificate;)V
+HSPLsun/security/provider/certpath/KeyChecker;-><init>(ILjava/security/cert/CertSelector;)V
+HSPLsun/security/provider/certpath/KeyChecker;->check(Ljava/security/cert/Certificate;Ljava/util/Collection;)V+]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;]Ljava/util/Collection;Ljava/util/HashSet;]Ljava/security/cert/CertSelector;Ljava/security/cert/X509CertSelector;
+HSPLsun/security/provider/certpath/KeyChecker;->init(Z)V
+HSPLsun/security/provider/certpath/KeyChecker;->verifyCAKeyUsage(Ljava/security/cert/X509Certificate;)V+]Ljava/security/cert/X509Certificate;missing_types
+HSPLsun/security/provider/certpath/OCSPResponse$SingleResponse;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/provider/certpath/OCSPResponse$SingleResponse;-><init>(Lsun/security/util/DerValue;Lsun/security/provider/certpath/OCSPResponse$1;)V
+HSPLsun/security/provider/certpath/OCSPResponse$SingleResponse;->access$100(Lsun/security/provider/certpath/OCSPResponse$SingleResponse;)Lsun/security/provider/certpath/CertId;
+HSPLsun/security/provider/certpath/OCSPResponse$SingleResponse;->access$200(Lsun/security/provider/certpath/OCSPResponse$SingleResponse;)Ljava/util/Date;
+HSPLsun/security/provider/certpath/OCSPResponse$SingleResponse;->access$300(Lsun/security/provider/certpath/OCSPResponse$SingleResponse;)Ljava/util/Date;
+HSPLsun/security/provider/certpath/OCSPResponse$SingleResponse;->getCertId()Lsun/security/provider/certpath/CertId;
+HSPLsun/security/provider/certpath/OCSPResponse$SingleResponse;->getCertStatus()Lsun/security/provider/certpath/OCSP$RevocationStatus$CertStatus;
+HSPLsun/security/provider/certpath/OCSPResponse;-><init>([B)V+]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/List;Ljava/util/ArrayList;
+HSPLsun/security/provider/certpath/OCSPResponse;->getSingleResponse(Lsun/security/provider/certpath/CertId;)Lsun/security/provider/certpath/OCSPResponse$SingleResponse;
+HSPLsun/security/provider/certpath/OCSPResponse;->verify(Ljava/util/List;Ljava/security/cert/X509Certificate;Ljava/security/cert/X509Certificate;Ljava/util/Date;[B)V+]Lsun/security/provider/certpath/OCSPResponse;Lsun/security/provider/certpath/OCSPResponse;]Ljava/util/Date;Ljava/util/Date;]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;]Lsun/security/provider/certpath/OCSPResponse$ResponseStatus;Lsun/security/provider/certpath/OCSPResponse$ResponseStatus;]Ljava/util/Collection;Ljava/util/HashMap$Values;]Ljava/util/List;Ljava/util/Collections$SingletonList;,Ljava/util/ArrayList;,Ljava/util/Collections$UnmodifiableRandomAccessList;]Lsun/security/x509/KeyIdentifier;Lsun/security/x509/KeyIdentifier;]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;,Ljava/util/HashMap$ValueIterator;,Ljava/util/Collections$1;]Ljava/security/cert/X509Certificate;missing_types]Ljavax/security/auth/x500/X500Principal;Ljavax/security/auth/x500/X500Principal;]Lsun/security/provider/certpath/AlgorithmChecker;Lsun/security/provider/certpath/AlgorithmChecker;
+HSPLsun/security/provider/certpath/OCSPResponse;->verifySignature(Ljava/security/cert/X509Certificate;)Z
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;-><init>(Ljava/security/cert/CertPath;Ljava/security/cert/PKIXParameters;)V+]Ljava/security/cert/CertPath;missing_types
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;-><init>(Ljava/security/cert/PKIXParameters;)V+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;,Ljava/security/cert/PKIXBuilderParameters;]Ljava/security/cert/TrustAnchor;Ljava/security/cert/TrustAnchor;]Ljava/util/Iterator;Ljava/util/Collections$UnmodifiableCollection$1;]Ljava/util/Set;Ljava/util/Collections$UnmodifiableSet;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->anyPolicyInhibited()Z+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->certPath()Ljava/security/cert/CertPath;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->certPathCheckers()Ljava/util/List;+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;,Ljava/security/cert/PKIXBuilderParameters;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->certStores()Ljava/util/List;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->certificates()Ljava/util/List;+]Ljava/security/cert/CertPath;missing_types
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->date()Ljava/util/Date;+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->explicitPolicyRequired()Z+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->initialPolicies()Ljava/util/Set;+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->policyMappingInhibited()Z+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->policyQualifiersRejected()Z+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->revocationEnabled()Z+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->sigProvider()Ljava/lang/String;+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->targetCertConstraints()Ljava/security/cert/CertSelector;+]Ljava/security/cert/PKIXParameters;Ljava/security/cert/PKIXParameters;
+HSPLsun/security/provider/certpath/PKIX$ValidatorParams;->trustAnchors()Ljava/util/Set;
+HSPLsun/security/provider/certpath/PKIX;->checkParams(Ljava/security/cert/CertPath;Ljava/security/cert/CertPathParameters;)Lsun/security/provider/certpath/PKIX$ValidatorParams;
+HSPLsun/security/provider/certpath/PKIX;->isDSAPublicKeyWithoutParams(Ljava/security/PublicKey;)Z
+HSPLsun/security/provider/certpath/PKIXCertPathValidator;-><init>()V
+HSPLsun/security/provider/certpath/PKIXCertPathValidator;->engineGetRevocationChecker()Ljava/security/cert/CertPathChecker;
+HSPLsun/security/provider/certpath/PKIXCertPathValidator;->engineValidate(Ljava/security/cert/CertPath;Ljava/security/cert/CertPathParameters;)Ljava/security/cert/CertPathValidatorResult;
+HSPLsun/security/provider/certpath/PKIXCertPathValidator;->validate(Ljava/security/cert/TrustAnchor;Lsun/security/provider/certpath/PKIX$ValidatorParams;)Ljava/security/cert/PKIXCertPathValidatorResult;+]Lsun/security/provider/certpath/PKIX$ValidatorParams;Lsun/security/provider/certpath/PKIX$ValidatorParams;]Lsun/security/provider/certpath/BasicChecker;Lsun/security/provider/certpath/BasicChecker;]Ljava/util/List;Ljava/util/Collections$UnmodifiableRandomAccessList;,Ljava/util/ArrayList;]Lsun/security/provider/certpath/PolicyChecker;Lsun/security/provider/certpath/PolicyChecker;]Ljava/util/Iterator;Ljava/util/Collections$UnmodifiableCollection$1;]Lsun/security/provider/certpath/RevocationChecker;Lsun/security/provider/certpath/RevocationChecker;
+HSPLsun/security/provider/certpath/PKIXCertPathValidator;->validate(Lsun/security/provider/certpath/PKIX$ValidatorParams;)Ljava/security/cert/PKIXCertPathValidatorResult;+]Lsun/security/provider/certpath/PKIX$ValidatorParams;Lsun/security/provider/certpath/PKIX$ValidatorParams;]Ljava/security/cert/X509Certificate;missing_types]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;]Ljava/util/List;Ljava/util/ArrayList;]Lsun/security/provider/certpath/AdaptableX509CertSelector;Lsun/security/provider/certpath/AdaptableX509CertSelector;]Ljava/security/cert/TrustAnchor;Ljava/security/cert/TrustAnchor;]Ljava/util/Iterator;Ljava/util/Collections$UnmodifiableCollection$1;]Ljava/util/Set;Ljava/util/Collections$UnmodifiableSet;
+HSPLsun/security/provider/certpath/PKIXMasterCertPathValidator;->validate(Ljava/security/cert/CertPath;Ljava/util/List;Ljava/util/List;)V+]Ljava/security/cert/X509Certificate;missing_types]Ljava/util/List;Ljava/util/ArrayList;]Ljava/security/cert/PKIXCertPathChecker;megamorphic_types]Ljava/util/Set;Ljava/util/HashSet;]Ljava/security/cert/CertPathValidatorException;Ljava/security/cert/CertPathValidatorException;
+HSPLsun/security/provider/certpath/PolicyChecker;-><init>(Ljava/util/Set;IZZZZLsun/security/provider/certpath/PolicyNodeImpl;)V+]Ljava/util/Set;Ljava/util/HashSet;,Ljava/util/Collections$EmptySet;
+HSPLsun/security/provider/certpath/PolicyChecker;->check(Ljava/security/cert/Certificate;Ljava/util/Collection;)V+]Ljava/util/Collection;Ljava/util/HashSet;]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;
+HSPLsun/security/provider/certpath/PolicyChecker;->checkPolicy(Ljava/security/cert/X509Certificate;)V
+HSPLsun/security/provider/certpath/PolicyChecker;->getPolicyTree()Ljava/security/cert/PolicyNode;+]Lsun/security/provider/certpath/PolicyNodeImpl;Lsun/security/provider/certpath/PolicyNodeImpl;
+HSPLsun/security/provider/certpath/PolicyChecker;->init(Z)V
+HSPLsun/security/provider/certpath/PolicyChecker;->mergeExplicitPolicy(ILsun/security/x509/X509CertImpl;Z)I+]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/provider/certpath/PolicyChecker;->mergeInhibitAnyPolicy(ILsun/security/x509/X509CertImpl;)I+]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/provider/certpath/PolicyChecker;->mergePolicyMapping(ILsun/security/x509/X509CertImpl;)I+]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/provider/certpath/PolicyChecker;->processParents(IZZLsun/security/provider/certpath/PolicyNodeImpl;Ljava/lang/String;Ljava/util/Set;Z)Z+]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;,Ljava/util/Collections$UnmodifiableCollection$1;]Lsun/security/provider/certpath/PolicyNodeImpl;Lsun/security/provider/certpath/PolicyNodeImpl;]Ljava/util/Set;Ljava/util/HashSet;,Ljava/util/Collections$UnmodifiableSet;
+HSPLsun/security/provider/certpath/PolicyChecker;->processPolicies(ILjava/util/Set;IIIZLsun/security/provider/certpath/PolicyNodeImpl;Lsun/security/x509/X509CertImpl;Z)Lsun/security/provider/certpath/PolicyNodeImpl;+]Lsun/security/x509/CertificatePoliciesExtension;Lsun/security/x509/CertificatePoliciesExtension;]Lsun/security/x509/CertificatePolicyId;Lsun/security/x509/CertificatePolicyId;]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;]Lsun/security/x509/PolicyInformation;Lsun/security/x509/PolicyInformation;]Ljava/util/List;Ljava/util/ArrayList;]Lsun/security/provider/certpath/PolicyNodeImpl;Lsun/security/provider/certpath/PolicyNodeImpl;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;,Ljava/util/Collections$UnmodifiableCollection$1;]Ljava/util/Set;Ljava/util/HashSet;,Ljava/util/Collections$EmptySet;,Ljava/util/LinkedHashSet;
+HSPLsun/security/provider/certpath/PolicyChecker;->processPolicyMappings(Lsun/security/x509/X509CertImpl;IILsun/security/provider/certpath/PolicyNodeImpl;ZLjava/util/Set;)Lsun/security/provider/certpath/PolicyNodeImpl;+]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;-><init>(Lsun/security/provider/certpath/PolicyNodeImpl;Ljava/lang/String;Ljava/util/Set;ZLjava/util/Set;Z)V+]Lsun/security/provider/certpath/PolicyNodeImpl;Lsun/security/provider/certpath/PolicyNodeImpl;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;-><init>(Lsun/security/provider/certpath/PolicyNodeImpl;Lsun/security/provider/certpath/PolicyNodeImpl;)V
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->addChild(Lsun/security/provider/certpath/PolicyNodeImpl;)V+]Ljava/util/HashSet;Ljava/util/HashSet;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->copyTree()Lsun/security/provider/certpath/PolicyNodeImpl;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->copyTree(Lsun/security/provider/certpath/PolicyNodeImpl;)Lsun/security/provider/certpath/PolicyNodeImpl;+]Ljava/util/HashSet;Ljava/util/HashSet;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->getChildren()Ljava/util/Iterator;+]Ljava/util/Set;Ljava/util/Collections$UnmodifiableSet;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->getDepth()I
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->getExpectedPolicies()Ljava/util/Set;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->getPolicyNodes(I)Ljava/util/Set;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->getPolicyNodes(ILjava/util/Set;)V+]Ljava/util/Set;Ljava/util/HashSet;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->getPolicyNodesExpected(ILjava/lang/String;Z)Ljava/util/Set;+]Lsun/security/provider/certpath/PolicyNodeImpl;Lsun/security/provider/certpath/PolicyNodeImpl;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->getPolicyNodesExpectedHelper(ILjava/lang/String;Z)Ljava/util/Set;+]Ljava/util/HashSet;Ljava/util/HashSet;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->getValidPolicy()Ljava/lang/String;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->prune(I)V+]Ljava/util/HashSet;Ljava/util/HashSet;]Lsun/security/provider/certpath/PolicyNodeImpl;Lsun/security/provider/certpath/PolicyNodeImpl;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;
+HSPLsun/security/provider/certpath/PolicyNodeImpl;->setImmutable()V+]Ljava/util/HashSet;Ljava/util/HashSet;]Lsun/security/provider/certpath/PolicyNodeImpl;Lsun/security/provider/certpath/PolicyNodeImpl;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;
+HSPLsun/security/provider/certpath/RevocationChecker$1;-><init>()V
+HSPLsun/security/provider/certpath/RevocationChecker$1;->run()Ljava/lang/Object;
+HSPLsun/security/provider/certpath/RevocationChecker$1;->run()Lsun/security/provider/certpath/RevocationChecker$RevocationProperties;
+HSPLsun/security/provider/certpath/RevocationChecker$RevocationProperties;-><init>()V
+HSPLsun/security/provider/certpath/RevocationChecker$RevocationProperties;-><init>(Lsun/security/provider/certpath/RevocationChecker$1;)V
+HSPLsun/security/provider/certpath/RevocationChecker;-><init>()V
+HSPLsun/security/provider/certpath/RevocationChecker;->certCanSignCrl(Ljava/security/cert/X509Certificate;)Z
+HSPLsun/security/provider/certpath/RevocationChecker;->check(Ljava/security/cert/Certificate;Ljava/util/Collection;)V
+HSPLsun/security/provider/certpath/RevocationChecker;->check(Ljava/security/cert/X509Certificate;Ljava/util/Collection;Ljava/security/PublicKey;Z)V
+HSPLsun/security/provider/certpath/RevocationChecker;->checkOCSP(Ljava/security/cert/X509Certificate;Ljava/util/Collection;)V+]Lsun/security/provider/certpath/PKIX$ValidatorParams;Lsun/security/provider/certpath/PKIX$ValidatorParams;]Lsun/security/provider/certpath/OCSPResponse;Lsun/security/provider/certpath/OCSPResponse;]Lsun/security/provider/certpath/OCSP$RevocationStatus;Lsun/security/provider/certpath/OCSPResponse$SingleResponse;]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;]Ljava/util/List;Ljava/util/Collections$UnmodifiableRandomAccessList;]Ljava/util/Map;Ljava/util/HashMap;]Ljava/util/Iterator;Ljava/util/Collections$UnmodifiableCollection$1;
+HSPLsun/security/provider/certpath/RevocationChecker;->clone()Ljava/lang/Object;
+HSPLsun/security/provider/certpath/RevocationChecker;->clone()Lsun/security/provider/certpath/RevocationChecker;
+HSPLsun/security/provider/certpath/RevocationChecker;->getResponderCert(Lsun/security/provider/certpath/RevocationChecker$RevocationProperties;Ljava/util/Set;Ljava/util/List;)Ljava/security/cert/X509Certificate;
+HSPLsun/security/provider/certpath/RevocationChecker;->getRevocationProperties()Lsun/security/provider/certpath/RevocationChecker$RevocationProperties;
+HSPLsun/security/provider/certpath/RevocationChecker;->init(Ljava/security/cert/TrustAnchor;Lsun/security/provider/certpath/PKIX$ValidatorParams;)V+]Lsun/security/provider/certpath/PKIX$ValidatorParams;Lsun/security/provider/certpath/PKIX$ValidatorParams;]Lsun/security/provider/certpath/RevocationChecker;Lsun/security/provider/certpath/RevocationChecker;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/Collections$UnmodifiableCollection$1;]Ljava/util/Set;Ljava/util/Collections$UnmodifiableSet;]Ljava/security/cert/PKIXRevocationChecker$Option;Ljava/security/cert/PKIXRevocationChecker$Option;
+HSPLsun/security/provider/certpath/RevocationChecker;->init(Z)V+]Ljava/security/cert/X509Certificate;missing_types]Lsun/security/provider/certpath/PKIX$ValidatorParams;Lsun/security/provider/certpath/PKIX$ValidatorParams;]Ljava/util/List;Ljava/util/Collections$UnmodifiableRandomAccessList;]Ljava/util/LinkedList;Ljava/util/LinkedList;]Ljava/security/cert/CertPath;missing_types]Ljava/security/cert/TrustAnchor;Ljava/security/cert/TrustAnchor;
+HSPLsun/security/provider/certpath/RevocationChecker;->toURI(Ljava/lang/String;)Ljava/net/URI;
+HSPLsun/security/provider/certpath/RevocationChecker;->updateState(Ljava/security/cert/X509Certificate;)V
+HSPLsun/security/util/AbstractAlgorithmConstraints;->checkAlgorithm([Ljava/lang/String;Ljava/lang/String;Lsun/security/util/AlgorithmDecomposer;)Z+]Ljava/lang/String;Ljava/lang/String;]Lsun/security/util/AlgorithmDecomposer;Lsun/security/util/AlgorithmDecomposer;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLsun/security/util/AlgorithmDecomposer;->decompose(Ljava/lang/String;)Ljava/util/Set;+]Ljava/util/Set;Ljava/util/HashSet;
+HSPLsun/security/util/AlgorithmDecomposer;->decomposeImpl(Ljava/lang/String;)Ljava/util/Set;+]Ljava/util/regex/Pattern;Ljava/util/regex/Pattern;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLsun/security/util/AlgorithmDecomposer;->decomposeOneHash(Ljava/lang/String;)Ljava/util/Set;
+HSPLsun/security/util/AlgorithmDecomposer;->hasLoop(Ljava/util/Set;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/util/Set;Ljava/util/HashSet;
+HSPLsun/security/util/BitArray;-><init>(I[B)V
+HSPLsun/security/util/BitArray;->get(I)Z
+HSPLsun/security/util/BitArray;->length()I
+HSPLsun/security/util/BitArray;->position(I)I
+HSPLsun/security/util/BitArray;->subscript(I)I
+HSPLsun/security/util/BitArray;->toBooleanArray()[Z
+HSPLsun/security/util/BitArray;->toByteArray()[B+][B[B
+HSPLsun/security/util/Cache$EqualByteArray;-><init>([B)V
+HSPLsun/security/util/Cache$EqualByteArray;->equals(Ljava/lang/Object;)Z
+HSPLsun/security/util/Cache$EqualByteArray;->hashCode()I
+HSPLsun/security/util/CertConstraintParameters;-><init>(Ljava/security/cert/X509Certificate;Z)V
+HSPLsun/security/util/CertConstraintParameters;->getCertificate()Ljava/security/cert/X509Certificate;
+HSPLsun/security/util/DerIndefLenConverter;->isIndefinite(I)Z
+HSPLsun/security/util/DerIndefLenConverter;->isLongForm(I)Z
+HSPLsun/security/util/DerInputBuffer;-><init>([B)V
+HSPLsun/security/util/DerInputBuffer;-><init>([BII)V
+HSPLsun/security/util/DerInputBuffer;->dup()Lsun/security/util/DerInputBuffer;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;]Ljava/lang/Object;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputBuffer;->getBigInteger(IZ)Ljava/math/BigInteger;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputBuffer;->getBitString()[B+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputBuffer;->getBitString(I)[B+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputBuffer;->getGeneralizedTime(I)Ljava/util/Date;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputBuffer;->getInteger(I)I+]Ljava/math/BigInteger;Ljava/math/BigInteger;]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputBuffer;->getPos()I
+HSPLsun/security/util/DerInputBuffer;->getSlice(II)[B
+HSPLsun/security/util/DerInputBuffer;->getTime(IZ)Ljava/util/Date;+]Lsun/util/calendar/CalendarSystem;Lsun/util/calendar/Gregorian;]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;
+HSPLsun/security/util/DerInputBuffer;->getUTCTime(I)Ljava/util/Date;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputBuffer;->getUnalignedBitString()Lsun/security/util/BitArray;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputBuffer;->peek()I
+HSPLsun/security/util/DerInputBuffer;->toByteArray()[B+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputBuffer;->truncate(I)V+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;-><init>(Lsun/security/util/DerInputBuffer;)V+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;-><init>([B)V
+HSPLsun/security/util/DerInputStream;->available()I+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->getBigInteger()Ljava/math/BigInteger;
+HSPLsun/security/util/DerInputStream;->getByte()I+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->getBytes([B)V+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->getDerValue()Lsun/security/util/DerValue;
+HSPLsun/security/util/DerInputStream;->getEnumerated()I
+HSPLsun/security/util/DerInputStream;->getGeneralizedTime()Ljava/util/Date;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->getLength()I
+HSPLsun/security/util/DerInputStream;->getLength(ILjava/io/InputStream;)I+]Ljava/io/InputStream;Lsun/security/util/DerInputBuffer;,Ljava/io/ByteArrayInputStream;
+HSPLsun/security/util/DerInputStream;->getLength(Ljava/io/InputStream;)I+]Ljava/io/InputStream;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->getOID()Lsun/security/util/ObjectIdentifier;
+HSPLsun/security/util/DerInputStream;->getOctetString()[B+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->getSequence(I)[Lsun/security/util/DerValue;+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerInputStream;->getSequence(IZ)[Lsun/security/util/DerValue;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerInputStream;->getSet(I)[Lsun/security/util/DerValue;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerInputStream;->getSet(IZ)[Lsun/security/util/DerValue;
+HSPLsun/security/util/DerInputStream;->getSet(IZZ)[Lsun/security/util/DerValue;
+HSPLsun/security/util/DerInputStream;->getUTCTime()Ljava/util/Date;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->getUnalignedBitString()Lsun/security/util/BitArray;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->init([BIIZ)V+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->mark(I)V
+HSPLsun/security/util/DerInputStream;->peekByte()I
+HSPLsun/security/util/DerInputStream;->readVector(I)[Lsun/security/util/DerValue;+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerInputStream;->readVector(IZ)[Lsun/security/util/DerValue;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;]Ljava/util/Vector;Ljava/util/Vector;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerInputStream;->reset()V+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->subStream(IZ)Lsun/security/util/DerInputStream;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerInputStream;->toByteArray()[B+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerOutputStream;-><init>()V
+HSPLsun/security/util/DerOutputStream;->putDerValue(Lsun/security/util/DerValue;)V
+HSPLsun/security/util/DerOutputStream;->putLength(I)V+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/util/DerOutputStream;->putNull()V+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/util/DerOutputStream;->putOID(Lsun/security/util/ObjectIdentifier;)V+]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;
+HSPLsun/security/util/DerOutputStream;->putOctetString([B)V+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/util/DerOutputStream;->putOrderedSet(B[Lsun/security/util/DerEncoder;Ljava/util/Comparator;)V+]Lsun/security/util/DerEncoder;Lsun/security/x509/AVA;]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/util/DerOutputStream;->putOrderedSetOf(B[Lsun/security/util/DerEncoder;)V
+HSPLsun/security/util/DerOutputStream;->putUnalignedBitString(Lsun/security/util/BitArray;)V+]Lsun/security/util/BitArray;Lsun/security/util/BitArray;]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/util/DerOutputStream;->write(BLsun/security/util/DerOutputStream;)V+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/util/DerOutputStream;->write(B[B)V+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/util/DerValue;-><init>(B[B)V
+HSPLsun/security/util/DerValue;-><init>(Ljava/io/InputStream;)V
+HSPLsun/security/util/DerValue;-><init>(Ljava/lang/String;)V
+HSPLsun/security/util/DerValue;-><init>(Lsun/security/util/DerInputBuffer;Z)V+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerValue;-><init>([B)V
+HSPLsun/security/util/DerValue;->encode(Lsun/security/util/DerOutputStream;)V+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/util/DerValue;->getBigInteger()Ljava/math/BigInteger;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerValue;->getBitString()[B+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerValue;->getBoolean()Z+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerValue;->getData()Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerValue;->getDataBytes()[B+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerValue;->getIA5String()Ljava/lang/String;+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;
+HSPLsun/security/util/DerValue;->getInteger()I+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerValue;->getOID()Lsun/security/util/ObjectIdentifier;
+HSPLsun/security/util/DerValue;->getOctetString()[B+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;]Lsun/security/util/DerValue;Lsun/security/util/DerValue;
+HSPLsun/security/util/DerValue;->getOriginalEncodedForm()[B
+HSPLsun/security/util/DerValue;->getTag()B
+HSPLsun/security/util/DerValue;->getUnalignedBitString()Lsun/security/util/BitArray;+]Lsun/security/util/DerInputBuffer;Lsun/security/util/DerInputBuffer;
+HSPLsun/security/util/DerValue;->init(BLjava/lang/String;)Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerValue;->init(ZLjava/io/InputStream;)Lsun/security/util/DerInputStream;+]Ljava/io/InputStream;Lsun/security/util/DerInputBuffer;,Ljava/io/ByteArrayInputStream;
+HSPLsun/security/util/DerValue;->isConstructed()Z
+HSPLsun/security/util/DerValue;->isContextSpecific()Z
+HSPLsun/security/util/DerValue;->isContextSpecific(B)Z+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;
+HSPLsun/security/util/DerValue;->isPrintableStringChar(C)Z
+HSPLsun/security/util/DerValue;->length()I
+HSPLsun/security/util/DerValue;->resetTag(B)V
+HSPLsun/security/util/DerValue;->toByteArray()[B+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DerValue;->toDerInputStream()Lsun/security/util/DerInputStream;
+HSPLsun/security/util/DisabledAlgorithmConstraints$Constraints;->getConstraints(Ljava/lang/String;)Ljava/util/Set;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLsun/security/util/DisabledAlgorithmConstraints$Constraints;->permits(Ljava/security/Key;)Z+]Lsun/security/util/DisabledAlgorithmConstraints$Constraint;Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;]Ljava/security/Key;missing_types]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLsun/security/util/DisabledAlgorithmConstraints$Constraints;->permits(Lsun/security/util/CertConstraintParameters;)V+]Ljava/security/cert/X509Certificate;missing_types]Lsun/security/util/CertConstraintParameters;Lsun/security/util/CertConstraintParameters;]Ljava/security/PublicKey;missing_types]Lsun/security/util/DisabledAlgorithmConstraints$Constraint;Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;]Ljava/util/Iterator;Ljava/util/HashMap$KeyIterator;]Ljava/util/Set;Ljava/util/HashSet;
+HSPLsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;->permits(Ljava/security/Key;)Z
+HSPLsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;->permits(Lsun/security/util/CertConstraintParameters;)V+]Ljava/security/cert/X509Certificate;missing_types]Lsun/security/util/CertConstraintParameters;Lsun/security/util/CertConstraintParameters;
+HSPLsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;->permitsImpl(Ljava/security/Key;)Z+]Ljava/lang/String;Ljava/lang/String;]Ljava/security/Key;missing_types
+HSPLsun/security/util/DisabledAlgorithmConstraints;->access$000()Lsun/security/util/Debug;
+HSPLsun/security/util/DisabledAlgorithmConstraints;->checkConstraints(Ljava/util/Set;Ljava/lang/String;Ljava/security/Key;Ljava/security/AlgorithmParameters;)Z+]Lsun/security/util/DisabledAlgorithmConstraints;Lsun/security/util/DisabledAlgorithmConstraints;]Lsun/security/util/DisabledAlgorithmConstraints$Constraints;Lsun/security/util/DisabledAlgorithmConstraints$Constraints;]Ljava/security/Key;missing_types
+HSPLsun/security/util/DisabledAlgorithmConstraints;->checkConstraints(Ljava/util/Set;Lsun/security/util/CertConstraintParameters;)V+]Ljava/security/cert/X509Certificate;missing_types]Lsun/security/util/CertConstraintParameters;Lsun/security/util/CertConstraintParameters;]Lsun/security/util/DisabledAlgorithmConstraints;Lsun/security/util/DisabledAlgorithmConstraints;]Ljava/security/PublicKey;missing_types]Lsun/security/util/DisabledAlgorithmConstraints$Constraints;Lsun/security/util/DisabledAlgorithmConstraints$Constraints;
+HSPLsun/security/util/DisabledAlgorithmConstraints;->permits(Ljava/util/Set;Ljava/lang/String;Ljava/security/AlgorithmParameters;)Z+]Ljava/util/Set;Ljava/util/RegularEnumSet;,Ljava/util/Collections$UnmodifiableSet;
+HSPLsun/security/util/DisabledAlgorithmConstraints;->permits(Ljava/util/Set;Ljava/lang/String;Ljava/security/Key;Ljava/security/AlgorithmParameters;)Z
+HSPLsun/security/util/DisabledAlgorithmConstraints;->permits(Ljava/util/Set;Ljava/security/Key;)Z
+HSPLsun/security/util/DisabledAlgorithmConstraints;->permits(Ljava/util/Set;Lsun/security/util/CertConstraintParameters;)V
+HSPLsun/security/util/KeyUtil;->getKeySize(Ljava/security/Key;)I+]Ljava/security/interfaces/ECKey;missing_types]Ljava/security/interfaces/RSAKey;missing_types]Ljava/math/BigInteger;Ljava/math/BigInteger;]Ljava/security/spec/ECParameterSpec;Ljava/security/spec/ECParameterSpec;
+HSPLsun/security/util/ManifestDigester$Entry;-><init>(III[B)V
+HSPLsun/security/util/ManifestDigester$Position;-><init>()V
+HSPLsun/security/util/ManifestDigester;-><init>([B)V+]Ljava/util/HashMap;Ljava/util/HashMap;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLsun/security/util/ManifestDigester;->findSection(ILsun/security/util/ManifestDigester$Position;)Z
+HSPLsun/security/util/ManifestDigester;->isNameAttr([BI)Z
+HSPLsun/security/util/ManifestDigester;->manifestDigest(Ljava/security/MessageDigest;)[B
+HSPLsun/security/util/ManifestEntryVerifier$SunProviderHolder;->access$000()Ljava/security/Provider;
+HSPLsun/security/util/ManifestEntryVerifier;-><init>(Ljava/util/jar/Manifest;)V
+HSPLsun/security/util/ManifestEntryVerifier;->getEntry()Ljava/util/jar/JarEntry;
+HSPLsun/security/util/ManifestEntryVerifier;->setEntry(Ljava/lang/String;Ljava/util/jar/JarEntry;)V+]Ljava/util/Base64$Decoder;Ljava/util/Base64$Decoder;]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;]Ljava/lang/String;Ljava/lang/String;]Ljava/util/HashMap;Ljava/util/HashMap;]Ljava/util/jar/Attributes;Ljava/util/jar/Attributes;]Ljava/lang/Object;Ljava/util/jar/Attributes$Name;]Ljava/util/jar/Manifest;Ljava/util/jar/Manifest;]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;
+HSPLsun/security/util/ManifestEntryVerifier;->update(B)V+]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLsun/security/util/ManifestEntryVerifier;->update([BII)V+]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLsun/security/util/ManifestEntryVerifier;->verify(Ljava/util/Hashtable;Ljava/util/Hashtable;)[Ljava/security/CodeSigner;+]Ljava/util/Hashtable;Ljava/util/Hashtable;]Ljava/util/ArrayList;Ljava/util/ArrayList;]Ljava/security/MessageDigest;Ljava/security/MessageDigest$Delegate;
+HSPLsun/security/util/MemoryCache$SoftCacheEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;JLjava/lang/ref/ReferenceQueue;)V
+HSPLsun/security/util/MemoryCache$SoftCacheEntry;->getValue()Ljava/lang/Object;+]Lsun/security/util/MemoryCache$SoftCacheEntry;Lsun/security/util/MemoryCache$SoftCacheEntry;
+HSPLsun/security/util/MemoryCache$SoftCacheEntry;->isValid(J)Z+]Lsun/security/util/MemoryCache$SoftCacheEntry;Lsun/security/util/MemoryCache$SoftCacheEntry;
+HSPLsun/security/util/MemoryCache;->emptyQueue()V+]Ljava/lang/ref/ReferenceQueue;Ljava/lang/ref/ReferenceQueue;]Ljava/util/Map;Ljava/util/LinkedHashMap;]Lsun/security/util/MemoryCache$CacheEntry;Lsun/security/util/MemoryCache$SoftCacheEntry;
+HSPLsun/security/util/MemoryCache;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Lsun/security/util/MemoryCache$CacheEntry;Lsun/security/util/MemoryCache$SoftCacheEntry;]Ljava/util/Map;Ljava/util/LinkedHashMap;
+HSPLsun/security/util/MemoryCache;->newEntry(Ljava/lang/Object;Ljava/lang/Object;JLjava/lang/ref/ReferenceQueue;)Lsun/security/util/MemoryCache$CacheEntry;
+HSPLsun/security/util/MemoryCache;->put(Ljava/lang/Object;Ljava/lang/Object;)V+]Lsun/security/util/MemoryCache;Lsun/security/util/MemoryCache;]Ljava/util/Map;Ljava/util/LinkedHashMap;]Lsun/security/util/MemoryCache$CacheEntry;Lsun/security/util/MemoryCache$SoftCacheEntry;]Ljava/util/Collection;Ljava/util/LinkedHashMap$LinkedValues;]Ljava/util/Iterator;Ljava/util/LinkedHashMap$LinkedValueIterator;
+HSPLsun/security/util/ObjectIdentifier;-><init>(Lsun/security/util/DerInputBuffer;)V+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/ObjectIdentifier;-><init>(Lsun/security/util/DerInputStream;)V+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/util/ObjectIdentifier;->check([B)V
+HSPLsun/security/util/ObjectIdentifier;->encode(Lsun/security/util/DerOutputStream;)V+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/util/ObjectIdentifier;->equals(Ljava/lang/Object;)Z
+HSPLsun/security/util/ObjectIdentifier;->hashCode()I
+HSPLsun/security/util/ObjectIdentifier;->toString()Ljava/lang/String;+]Ljava/lang/StringBuffer;Ljava/lang/StringBuffer;
+HSPLsun/security/util/SignatureFileVerifier;-><init>(Ljava/util/ArrayList;Lsun/security/util/ManifestDigester;Ljava/lang/String;[B)V
+HSPLsun/security/util/SignatureFileVerifier;->getDigest(Ljava/lang/String;)Ljava/security/MessageDigest;
+HSPLsun/security/util/SignatureFileVerifier;->getSigners([Lsun/security/pkcs/SignerInfo;Lsun/security/pkcs/PKCS7;)[Ljava/security/CodeSigner;
+HSPLsun/security/util/SignatureFileVerifier;->isBlockOrSF(Ljava/lang/String;)Z+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/security/util/SignatureFileVerifier;->matches([Ljava/security/CodeSigner;[Ljava/security/CodeSigner;[Ljava/security/CodeSigner;)Z
+HSPLsun/security/util/SignatureFileVerifier;->needSignatureFileBytes()Z
+HSPLsun/security/util/SignatureFileVerifier;->process(Ljava/util/Hashtable;Ljava/util/List;)V
+HSPLsun/security/util/SignatureFileVerifier;->processImpl(Ljava/util/Hashtable;Ljava/util/List;)V+]Ljava/util/Map$Entry;Ljava/util/HashMap$Node;]Ljava/lang/String;Ljava/lang/String;]Ljava/util/jar/Attributes;Ljava/util/jar/Attributes;]Ljava/util/jar/Manifest;Ljava/util/jar/Manifest;]Ljava/util/Map;Ljava/util/HashMap;]Lsun/security/pkcs/PKCS7;Lsun/security/pkcs/PKCS7;]Lsun/security/util/SignatureFileVerifier;Lsun/security/util/SignatureFileVerifier;]Ljava/util/Iterator;Ljava/util/HashMap$EntryIterator;]Ljava/util/Set;Ljava/util/HashMap$EntrySet;
+HSPLsun/security/util/SignatureFileVerifier;->setSignatureFile([B)V
+HSPLsun/security/util/SignatureFileVerifier;->updateSigners([Ljava/security/CodeSigner;Ljava/util/Hashtable;Ljava/lang/String;)V+]Ljava/util/Hashtable;Ljava/util/Hashtable;]Ljava/util/ArrayList;Ljava/util/ArrayList;
+HSPLsun/security/util/SignatureFileVerifier;->verifyManifestHash(Ljava/util/jar/Manifest;Lsun/security/util/ManifestDigester;Ljava/util/List;)Z
+HSPLsun/security/x509/AVA;-><init>(Ljava/io/Reader;ILjava/util/Map;)V
+HSPLsun/security/x509/AVA;-><init>(Ljava/io/Reader;Ljava/util/Map;)V
+HSPLsun/security/x509/AVA;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/AVA;->derEncode(Ljava/io/OutputStream;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;]Ljava/io/OutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/x509/AVA;->isDerString(Lsun/security/util/DerValue;Z)Z
+HSPLsun/security/x509/AVA;->isTerminator(II)Z
+HSPLsun/security/x509/AVA;->parseString(Ljava/io/Reader;IILjava/lang/StringBuilder;)Lsun/security/util/DerValue;
+HSPLsun/security/x509/AVA;->readChar(Ljava/io/Reader;Ljava/lang/String;)I
+HSPLsun/security/x509/AVA;->toKeyword(ILjava/util/Map;)Ljava/lang/String;
+HSPLsun/security/x509/AVA;->toRFC2253CanonicalString()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lsun/security/util/DerValue;Lsun/security/util/DerValue;
+HSPLsun/security/x509/AVA;->toRFC2253String(Ljava/util/Map;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/String;Ljava/lang/String;]Lsun/security/util/DerValue;Lsun/security/util/DerValue;
+HSPLsun/security/x509/AVAKeyword;->getKeyword(Lsun/security/util/ObjectIdentifier;ILjava/util/Map;)Ljava/lang/String;+]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;]Ljava/util/Map;Ljava/util/HashMap;,Ljava/util/Collections$EmptyMap;
+HSPLsun/security/x509/AVAKeyword;->getOID(Ljava/lang/String;ILjava/util/Map;)Lsun/security/util/ObjectIdentifier;
+HSPLsun/security/x509/AVAKeyword;->isCompliant(I)Z
+HSPLsun/security/x509/AccessDescription;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/AlgorithmId;-><init>(Lsun/security/util/ObjectIdentifier;Lsun/security/util/DerValue;)V+]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;
+HSPLsun/security/x509/AlgorithmId;->decodeParams()V
+HSPLsun/security/x509/AlgorithmId;->derEncode(Ljava/io/OutputStream;)V+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;]Ljava/io/OutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/x509/AlgorithmId;->encode(Lsun/security/util/DerOutputStream;)V+]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;
+HSPLsun/security/x509/AlgorithmId;->equals(Lsun/security/x509/AlgorithmId;)Z+]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;
+HSPLsun/security/x509/AlgorithmId;->getEncAlgFromSigAlg(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/security/x509/AlgorithmId;->getName()Ljava/lang/String;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLsun/security/x509/AlgorithmId;->getParameters()Ljava/security/AlgorithmParameters;
+HSPLsun/security/x509/AlgorithmId;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;
+HSPLsun/security/x509/AlgorithmId;->makeSigAlg(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/security/x509/AlgorithmId;->paramsToString()Ljava/lang/String;
+HSPLsun/security/x509/AlgorithmId;->parse(Lsun/security/util/DerValue;)Lsun/security/x509/AlgorithmId;+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/AuthorityInfoAccessExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V+]Ljava/lang/Boolean;Ljava/lang/Boolean;]Ljava/util/List;Ljava/util/ArrayList;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/AuthorityInfoAccessExtension;->getName()Ljava/lang/String;
+HSPLsun/security/x509/AuthorityKeyIdentifierExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Ljava/lang/Boolean;Ljava/lang/Boolean;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/AuthorityKeyIdentifierExtension;->get(Ljava/lang/String;)Ljava/lang/Object;+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/security/x509/AuthorityKeyIdentifierExtension;->getEncodedKeyIdentifier()[B+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;]Lsun/security/x509/KeyIdentifier;Lsun/security/x509/KeyIdentifier;
+HSPLsun/security/x509/AuthorityKeyIdentifierExtension;->getName()Ljava/lang/String;
+HSPLsun/security/x509/BasicConstraintsExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Ljava/lang/Boolean;Ljava/lang/Boolean;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/BasicConstraintsExtension;->getName()Ljava/lang/String;
+HSPLsun/security/x509/CRLDistributionPointsExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V
+HSPLsun/security/x509/CRLDistributionPointsExtension;-><init>(Lsun/security/util/ObjectIdentifier;Ljava/lang/Boolean;Ljava/lang/Object;Ljava/lang/String;)V+]Ljava/lang/Boolean;Ljava/lang/Boolean;]Ljava/util/List;Ljava/util/ArrayList;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/CRLDistributionPointsExtension;->getName()Ljava/lang/String;
+HSPLsun/security/x509/CertificateAlgorithmId;-><init>(Lsun/security/util/DerInputStream;)V+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/CertificateAlgorithmId;->get(Ljava/lang/String;)Lsun/security/x509/AlgorithmId;+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/security/x509/CertificateExtensions;-><init>(Lsun/security/util/DerInputStream;)V
+HSPLsun/security/x509/CertificateExtensions;->getAllExtensions()Ljava/util/Collection;+]Ljava/util/Map;Ljava/util/Collections$SynchronizedMap;
+HSPLsun/security/x509/CertificateExtensions;->getExtension(Ljava/lang/String;)Lsun/security/x509/Extension;+]Ljava/util/Map;Ljava/util/Collections$SynchronizedMap;
+HSPLsun/security/x509/CertificateExtensions;->init(Lsun/security/util/DerInputStream;)V+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/CertificateExtensions;->parseExtension(Lsun/security/x509/Extension;)V+]Lsun/security/x509/Extension;Lsun/security/x509/Extension;]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;]Lsun/security/x509/CertAttrSet;megamorphic_types]Ljava/util/Map;Ljava/util/Collections$SynchronizedMap;]Ljava/lang/Class;Ljava/lang/Class;]Ljava/lang/reflect/Constructor;Ljava/lang/reflect/Constructor;
+HSPLsun/security/x509/CertificatePoliciesExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V+]Ljava/lang/Boolean;Ljava/lang/Boolean;]Ljava/util/List;Ljava/util/ArrayList;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/CertificatePoliciesExtension;->get(Ljava/lang/String;)Ljava/util/List;+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/security/x509/CertificatePoliciesExtension;->getName()Ljava/lang/String;
+HSPLsun/security/x509/CertificatePolicyId;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;
+HSPLsun/security/x509/CertificatePolicyId;->getIdentifier()Lsun/security/util/ObjectIdentifier;
+HSPLsun/security/x509/CertificateSerialNumber;-><init>(Lsun/security/util/DerValue;)V
+HSPLsun/security/x509/CertificateSerialNumber;->get(Ljava/lang/String;)Lsun/security/x509/SerialNumber;
+HSPLsun/security/x509/CertificateValidity;-><init>(Lsun/security/util/DerInputStream;)V+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/CertificateValidity;->construct(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/CertificateVersion;-><init>()V
+HSPLsun/security/x509/CertificateVersion;-><init>(Lsun/security/util/DerValue;)V
+HSPLsun/security/x509/CertificateVersion;->compare(I)I
+HSPLsun/security/x509/CertificateVersion;->construct(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/CertificateX509Key;-><init>(Lsun/security/util/DerInputStream;)V+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/CertificateX509Key;->get(Ljava/lang/String;)Ljava/security/PublicKey;+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/security/x509/DNSName;-><init>(Ljava/lang/String;)V
+HSPLsun/security/x509/DNSName;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;
+HSPLsun/security/x509/DistributionPoint;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/ExtendedKeyUsageExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Ljava/lang/Boolean;Ljava/lang/Boolean;]Ljava/util/Vector;Ljava/util/Vector;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/ExtendedKeyUsageExtension;->getName()Ljava/lang/String;
+HSPLsun/security/x509/Extension;-><init>()V
+HSPLsun/security/x509/Extension;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/Extension;->getExtensionId()Lsun/security/util/ObjectIdentifier;
+HSPLsun/security/x509/Extension;->getExtensionValue()[B
+HSPLsun/security/x509/Extension;->isCritical()Z
+HSPLsun/security/x509/GeneralName;-><init>(Lsun/security/util/DerValue;)V
+HSPLsun/security/x509/GeneralName;-><init>(Lsun/security/util/DerValue;Z)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;
+HSPLsun/security/x509/GeneralNames;-><init>()V
+HSPLsun/security/x509/GeneralNames;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/x509/GeneralNames;Lsun/security/x509/GeneralNames;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/GeneralNames;->add(Lsun/security/x509/GeneralName;)Lsun/security/x509/GeneralNames;+]Ljava/util/List;Ljava/util/ArrayList;
+HSPLsun/security/x509/KeyIdentifier;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;
+HSPLsun/security/x509/KeyIdentifier;-><init>([B)V
+HSPLsun/security/x509/KeyIdentifier;->encode(Lsun/security/util/DerOutputStream;)V+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/x509/KeyIdentifier;->equals(Ljava/lang/Object;)Z
+HSPLsun/security/x509/KeyUsageExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V+]Lsun/security/util/BitArray;Lsun/security/util/BitArray;]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLsun/security/x509/KeyUsageExtension;->getName()Ljava/lang/String;
+HSPLsun/security/x509/OIDMap$OIDInfo;->getClazz()Ljava/lang/Class;
+HSPLsun/security/x509/OIDMap;->getClass(Lsun/security/util/ObjectIdentifier;)Ljava/lang/Class;+]Lsun/security/x509/OIDMap$OIDInfo;Lsun/security/x509/OIDMap$OIDInfo;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLsun/security/x509/PolicyInformation;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;]Ljava/util/Set;Ljava/util/LinkedHashSet;
+HSPLsun/security/x509/PolicyInformation;->getPolicyIdentifier()Lsun/security/x509/CertificatePolicyId;
+HSPLsun/security/x509/PolicyInformation;->getPolicyQualifiers()Ljava/util/Set;
+HSPLsun/security/x509/RDN;-><init>(Ljava/lang/String;Ljava/util/Map;)V
+HSPLsun/security/x509/RDN;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/RDN;->encode(Lsun/security/util/DerOutputStream;)V+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/x509/RDN;->toRFC2253String(Ljava/util/Map;)Ljava/lang/String;
+HSPLsun/security/x509/RDN;->toRFC2253String(Z)Ljava/lang/String;
+HSPLsun/security/x509/RDN;->toRFC2253StringInternal(ZLjava/util/Map;)Ljava/lang/String;+]Lsun/security/x509/AVA;Lsun/security/x509/AVA;
+HSPLsun/security/x509/SerialNumber;-><init>(Lsun/security/util/DerInputStream;)V
+HSPLsun/security/x509/SerialNumber;-><init>(Lsun/security/util/DerValue;)V
+HSPLsun/security/x509/SerialNumber;->construct(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/SerialNumber;->getNumber()Ljava/math/BigInteger;
+HSPLsun/security/x509/SubjectAlternativeNameExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V+]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLsun/security/x509/SubjectAlternativeNameExtension;->getName()Ljava/lang/String;
+HSPLsun/security/x509/SubjectKeyIdentifierExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V+]Ljava/lang/Boolean;Ljava/lang/Boolean;
+HSPLsun/security/x509/SubjectKeyIdentifierExtension;->get(Ljava/lang/String;)Lsun/security/x509/KeyIdentifier;
+HSPLsun/security/x509/SubjectKeyIdentifierExtension;->getName()Ljava/lang/String;
+HSPLsun/security/x509/URIName;-><init>(Ljava/lang/String;)V+]Ljava/net/URI;Ljava/net/URI;
+HSPLsun/security/x509/URIName;-><init>(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;
+HSPLsun/security/x509/X500Name;-><init>(Ljava/lang/String;Ljava/util/Map;)V
+HSPLsun/security/x509/X500Name;-><init>(Lsun/security/util/DerInputStream;)V
+HSPLsun/security/x509/X500Name;-><init>(Lsun/security/util/DerValue;)V
+HSPLsun/security/x509/X500Name;-><init>([B)V
+HSPLsun/security/x509/X500Name;->asX500Name(Ljavax/security/auth/x500/X500Principal;)Lsun/security/x509/X500Name;+]Ljava/lang/reflect/Field;Ljava/lang/reflect/Field;
+HSPLsun/security/x509/X500Name;->asX500Principal()Ljavax/security/auth/x500/X500Principal;+]Ljava/lang/reflect/Constructor;Ljava/lang/reflect/Constructor;
+HSPLsun/security/x509/X500Name;->checkNoNewLinesNorTabsAtBeginningOfDN(Ljava/lang/String;)V
+HSPLsun/security/x509/X500Name;->countQuotes(Ljava/lang/String;II)I
+HSPLsun/security/x509/X500Name;->equals(Ljava/lang/Object;)Z+]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLsun/security/x509/X500Name;->escaped(IILjava/lang/String;)Z
+HSPLsun/security/x509/X500Name;->generateRFC2253DN(Ljava/util/Map;)Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lsun/security/x509/RDN;Lsun/security/x509/RDN;
+HSPLsun/security/x509/X500Name;->getEncoded()[B+][B[B]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLsun/security/x509/X500Name;->getEncodedInternal()[B+]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;]Lsun/security/x509/RDN;Lsun/security/x509/RDN;
+HSPLsun/security/x509/X500Name;->getRFC2253CanonicalName()Ljava/lang/String;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lsun/security/x509/RDN;Lsun/security/x509/RDN;
+HSPLsun/security/x509/X500Name;->getRFC2253Name()Ljava/lang/String;+]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLsun/security/x509/X500Name;->getRFC2253Name(Ljava/util/Map;)Ljava/lang/String;+]Ljava/util/Map;Ljava/util/Collections$EmptyMap;
+HSPLsun/security/x509/X500Name;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLsun/security/x509/X500Name;->intern(Lsun/security/util/ObjectIdentifier;)Lsun/security/util/ObjectIdentifier;+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLsun/security/x509/X500Name;->isEmpty()Z
+HSPLsun/security/x509/X500Name;->parseDER(Lsun/security/util/DerInputStream;)V+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/X500Name;->parseDN(Ljava/lang/String;Ljava/util/Map;)V
+HSPLsun/security/x509/X509AttributeName;-><init>(Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/security/x509/X509AttributeName;->getPrefix()Ljava/lang/String;
+HSPLsun/security/x509/X509AttributeName;->getSuffix()Ljava/lang/String;
+HSPLsun/security/x509/X509CertImpl;-><init>([B)V
+HSPLsun/security/x509/X509CertImpl;->get(Ljava/lang/String;)Ljava/lang/Object;+]Ljava/lang/String;Ljava/lang/String;]Lsun/security/x509/X509AttributeName;Lsun/security/x509/X509AttributeName;]Lsun/security/x509/X509CertInfo;Lsun/security/x509/X509CertInfo;
+HSPLsun/security/x509/X509CertImpl;->getAuthorityKeyIdentifierExtension()Lsun/security/x509/AuthorityKeyIdentifierExtension;+]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/x509/X509CertImpl;->getCertificatePoliciesExtension()Lsun/security/x509/CertificatePoliciesExtension;+]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/x509/X509CertImpl;->getEncodedInternal()[B
+HSPLsun/security/x509/X509CertImpl;->getEncodedInternal(Ljava/security/cert/Certificate;)[B+]Ljava/security/cert/Certificate;missing_types]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/x509/X509CertImpl;->getExtension(Lsun/security/util/ObjectIdentifier;)Lsun/security/x509/Extension;+]Lsun/security/x509/Extension;megamorphic_types]Lsun/security/util/ObjectIdentifier;Lsun/security/util/ObjectIdentifier;]Lsun/security/x509/X509CertInfo;Lsun/security/x509/X509CertInfo;]Ljava/util/Collection;Ljava/util/Collections$SynchronizedCollection;]Lsun/security/x509/CertificateExtensions;Lsun/security/x509/CertificateExtensions;]Ljava/util/Iterator;Ljava/util/TreeMap$ValueIterator;
+HSPLsun/security/x509/X509CertImpl;->getIssuerX500Principal()Ljavax/security/auth/x500/X500Principal;+]Lsun/security/x509/X509CertInfo;Lsun/security/x509/X509CertInfo;
+HSPLsun/security/x509/X509CertImpl;->getNameConstraintsExtension()Lsun/security/x509/NameConstraintsExtension;+]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/x509/X509CertImpl;->getPolicyConstraintsExtension()Lsun/security/x509/PolicyConstraintsExtension;+]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/x509/X509CertImpl;->getPolicyMappingsExtension()Lsun/security/x509/PolicyMappingsExtension;+]Lsun/security/x509/X509CertImpl;Lsun/security/x509/X509CertImpl;
+HSPLsun/security/x509/X509CertImpl;->getPublicKey()Ljava/security/PublicKey;+]Lsun/security/x509/X509CertInfo;Lsun/security/x509/X509CertInfo;
+HSPLsun/security/x509/X509CertImpl;->getSerialNumberObject()Lsun/security/x509/SerialNumber;
+HSPLsun/security/x509/X509CertImpl;->getSigAlgName()Ljava/lang/String;+]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;
+HSPLsun/security/x509/X509CertImpl;->getSubjectKeyId()Lsun/security/x509/KeyIdentifier;
+HSPLsun/security/x509/X509CertImpl;->getSubjectKeyIdentifierExtension()Lsun/security/x509/SubjectKeyIdentifierExtension;
+HSPLsun/security/x509/X509CertImpl;->getSubjectX500Principal()Ljavax/security/auth/x500/X500Principal;+]Lsun/security/x509/X509CertInfo;Lsun/security/x509/X509CertInfo;
+HSPLsun/security/x509/X509CertImpl;->isSelfIssued(Ljava/security/cert/X509Certificate;)Z+]Ljava/security/cert/X509Certificate;missing_types]Ljavax/security/auth/x500/X500Principal;Ljavax/security/auth/x500/X500Principal;
+HSPLsun/security/x509/X509CertImpl;->parse(Lsun/security/util/DerValue;)V
+HSPLsun/security/x509/X509CertImpl;->parse(Lsun/security/util/DerValue;[B)V+]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/x509/X509CertInfo;Lsun/security/x509/X509CertInfo;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/security/x509/X509CertImpl;->toImpl(Ljava/security/cert/X509Certificate;)Lsun/security/x509/X509CertImpl;
+HSPLsun/security/x509/X509CertImpl;->verify(Ljava/security/PublicKey;)V
+HSPLsun/security/x509/X509CertImpl;->verify(Ljava/security/PublicKey;Ljava/lang/String;)V
+HSPLsun/security/x509/X509CertInfo;-><init>(Lsun/security/util/DerValue;)V
+HSPLsun/security/x509/X509CertInfo;-><init>([B)V
+HSPLsun/security/x509/X509CertInfo;->attributeMap(Ljava/lang/String;)I+]Ljava/lang/Integer;Ljava/lang/Integer;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLsun/security/x509/X509CertInfo;->get(Ljava/lang/String;)Ljava/lang/Object;+]Lsun/security/x509/X509AttributeName;Lsun/security/x509/X509AttributeName;]Lsun/security/x509/CertificateAlgorithmId;Lsun/security/x509/CertificateAlgorithmId;]Lsun/security/x509/CertificateSerialNumber;Lsun/security/x509/CertificateSerialNumber;]Lsun/security/x509/CertificateX509Key;Lsun/security/x509/CertificateX509Key;]Lsun/security/x509/CertificateExtensions;Lsun/security/x509/CertificateExtensions;]Lsun/security/x509/CertificateValidity;Lsun/security/x509/CertificateValidity;
+HSPLsun/security/x509/X509CertInfo;->getEncodedInfo()[B
+HSPLsun/security/x509/X509CertInfo;->getX500Name(Ljava/lang/String;Z)Ljava/lang/Object;+]Ljava/lang/String;Ljava/lang/String;]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLsun/security/x509/X509CertInfo;->parse(Lsun/security/util/DerValue;)V+]Lsun/security/util/DerValue;Lsun/security/util/DerValue;]Lsun/security/x509/CertificateVersion;Lsun/security/x509/CertificateVersion;]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLsun/security/x509/X509CertInfo;->verifyCert(Lsun/security/x509/X500Name;Lsun/security/x509/CertificateExtensions;)V+]Lsun/security/x509/X500Name;Lsun/security/x509/X500Name;
+HSPLsun/security/x509/X509Key;->buildX509Key(Lsun/security/x509/AlgorithmId;Lsun/security/util/BitArray;)Ljava/security/PublicKey;+]Ljava/security/KeyFactory;Ljava/security/KeyFactory;]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/x509/X509Key;->encode(Lsun/security/util/DerOutputStream;Lsun/security/x509/AlgorithmId;Lsun/security/util/BitArray;)V+]Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;]Lsun/security/util/DerOutputStream;Lsun/security/util/DerOutputStream;
+HSPLsun/security/x509/X509Key;->parse(Lsun/security/util/DerValue;)Ljava/security/PublicKey;+]Lsun/security/util/DerInputStream;Lsun/security/util/DerInputStream;
+HSPLsun/util/calendar/AbstractCalendar;-><init>()V
+HSPLsun/util/calendar/AbstractCalendar;->getCalendarDate(JLsun/util/calendar/CalendarDate;)Lsun/util/calendar/CalendarDate;+]Lsun/util/calendar/AbstractCalendar;Lsun/util/calendar/Gregorian;,Lsun/util/calendar/JulianCalendar;]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;,Lsun/util/calendar/JulianCalendar$Date;]Llibcore/util/ZoneInfo;missing_types]Ljava/util/TimeZone;Ljava/util/SimpleTimeZone;
+HSPLsun/util/calendar/AbstractCalendar;->getDayOfWeekDateOnOrBefore(JI)J
+HSPLsun/util/calendar/AbstractCalendar;->getEras()[Lsun/util/calendar/Era;
+HSPLsun/util/calendar/AbstractCalendar;->getTime(Lsun/util/calendar/CalendarDate;)J+]Lsun/util/calendar/AbstractCalendar;Lsun/util/calendar/Gregorian;]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;]Ljava/util/TimeZone;missing_types
+HSPLsun/util/calendar/AbstractCalendar;->getTimeOfDay(Lsun/util/calendar/CalendarDate;)J+]Lsun/util/calendar/AbstractCalendar;Lsun/util/calendar/Gregorian;]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/AbstractCalendar;->getTimeOfDayValue(Lsun/util/calendar/CalendarDate;)J+]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/AbstractCalendar;->setEras([Lsun/util/calendar/Era;)V
+HSPLsun/util/calendar/AbstractCalendar;->setTimeOfDay(Lsun/util/calendar/CalendarDate;I)Lsun/util/calendar/CalendarDate;+]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;,Lsun/util/calendar/JulianCalendar$Date;
+HSPLsun/util/calendar/BaseCalendar$Date;-><init>(Ljava/util/TimeZone;)V
+HSPLsun/util/calendar/BaseCalendar$Date;->getCachedJan1()J
+HSPLsun/util/calendar/BaseCalendar$Date;->getCachedYear()I
+HSPLsun/util/calendar/BaseCalendar$Date;->hit(I)Z
+HSPLsun/util/calendar/BaseCalendar$Date;->hit(J)Z
+HSPLsun/util/calendar/BaseCalendar$Date;->setCache(IJI)V
+HSPLsun/util/calendar/BaseCalendar;-><init>()V
+HSPLsun/util/calendar/BaseCalendar;->getCalendarDateFromFixedDate(Lsun/util/calendar/CalendarDate;J)V+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;]Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/Gregorian;
+HSPLsun/util/calendar/BaseCalendar;->getDayOfWeekFromFixedDate(J)I
+HSPLsun/util/calendar/BaseCalendar;->getDayOfYear(III)J+]Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/Gregorian;,Lsun/util/calendar/JulianCalendar;
+HSPLsun/util/calendar/BaseCalendar;->getFixedDate(IIILsun/util/calendar/BaseCalendar$Date;)J+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;]Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/Gregorian;
+HSPLsun/util/calendar/BaseCalendar;->getFixedDate(Lsun/util/calendar/CalendarDate;)J+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;]Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/Gregorian;]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/BaseCalendar;->getGregorianYearFromFixedDate(J)I
+HSPLsun/util/calendar/BaseCalendar;->isLeapYear(I)Z
+HSPLsun/util/calendar/BaseCalendar;->isLeapYear(Lsun/util/calendar/CalendarDate;)Z+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;,Lsun/util/calendar/JulianCalendar$Date;]Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/Gregorian;,Lsun/util/calendar/JulianCalendar;
+HSPLsun/util/calendar/BaseCalendar;->normalizeMonth(Lsun/util/calendar/CalendarDate;)V+]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/CalendarDate;-><init>(Ljava/util/TimeZone;)V
+HSPLsun/util/calendar/CalendarDate;->clone()Ljava/lang/Object;
+HSPLsun/util/calendar/CalendarDate;->getDayOfMonth()I
+HSPLsun/util/calendar/CalendarDate;->getDayOfWeek()I+]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;,Lsun/util/calendar/JulianCalendar$Date;
+HSPLsun/util/calendar/CalendarDate;->getEra()Lsun/util/calendar/Era;
+HSPLsun/util/calendar/CalendarDate;->getHours()I
+HSPLsun/util/calendar/CalendarDate;->getMillis()I
+HSPLsun/util/calendar/CalendarDate;->getMinutes()I
+HSPLsun/util/calendar/CalendarDate;->getMonth()I
+HSPLsun/util/calendar/CalendarDate;->getSeconds()I
+HSPLsun/util/calendar/CalendarDate;->getTimeOfDay()J+]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/CalendarDate;->getYear()I
+HSPLsun/util/calendar/CalendarDate;->getZone()Ljava/util/TimeZone;
+HSPLsun/util/calendar/CalendarDate;->isDaylightTime()Z+]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;,Lsun/util/calendar/JulianCalendar$Date;
+HSPLsun/util/calendar/CalendarDate;->isLeapYear()Z
+HSPLsun/util/calendar/CalendarDate;->isNormalized()Z
+HSPLsun/util/calendar/CalendarDate;->isStandardTime()Z
+HSPLsun/util/calendar/CalendarDate;->setDate(III)Lsun/util/calendar/CalendarDate;+]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/CalendarDate;->setDayOfMonth(I)Lsun/util/calendar/CalendarDate;
+HSPLsun/util/calendar/CalendarDate;->setDayOfWeek(I)V
+HSPLsun/util/calendar/CalendarDate;->setDaylightSaving(I)V
+HSPLsun/util/calendar/CalendarDate;->setEra(Lsun/util/calendar/Era;)Lsun/util/calendar/CalendarDate;
+HSPLsun/util/calendar/CalendarDate;->setHours(I)Lsun/util/calendar/CalendarDate;
+HSPLsun/util/calendar/CalendarDate;->setLeapYear(Z)V
+HSPLsun/util/calendar/CalendarDate;->setMillis(I)Lsun/util/calendar/CalendarDate;
+HSPLsun/util/calendar/CalendarDate;->setMinutes(I)Lsun/util/calendar/CalendarDate;
+HSPLsun/util/calendar/CalendarDate;->setMonth(I)Lsun/util/calendar/CalendarDate;
+HSPLsun/util/calendar/CalendarDate;->setNormalized(Z)V
+HSPLsun/util/calendar/CalendarDate;->setSeconds(I)Lsun/util/calendar/CalendarDate;
+HSPLsun/util/calendar/CalendarDate;->setTimeOfDay(IIII)Lsun/util/calendar/CalendarDate;+]Lsun/util/calendar/CalendarDate;Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/CalendarDate;->setTimeOfDay(J)V
+HSPLsun/util/calendar/CalendarDate;->setYear(I)Lsun/util/calendar/CalendarDate;
+HSPLsun/util/calendar/CalendarDate;->setZone(Ljava/util/TimeZone;)Lsun/util/calendar/CalendarDate;
+HSPLsun/util/calendar/CalendarDate;->setZoneOffset(I)V
+HSPLsun/util/calendar/CalendarSystem;-><init>()V
+HSPLsun/util/calendar/CalendarSystem;->forName(Ljava/lang/String;)Lsun/util/calendar/CalendarSystem;
+HSPLsun/util/calendar/CalendarSystem;->getGregorianCalendar()Lsun/util/calendar/Gregorian;
+HSPLsun/util/calendar/CalendarUtils;->floorDivide(II)I
+HSPLsun/util/calendar/CalendarUtils;->floorDivide(JJ)J
+HSPLsun/util/calendar/CalendarUtils;->isGregorianLeapYear(I)Z
+HSPLsun/util/calendar/CalendarUtils;->isJulianLeapYear(I)Z
+HSPLsun/util/calendar/CalendarUtils;->mod(II)I
+HSPLsun/util/calendar/CalendarUtils;->mod(JJ)J
+HSPLsun/util/calendar/CalendarUtils;->sprintf0d(Ljava/lang/StringBuilder;II)Ljava/lang/StringBuilder;+]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLsun/util/calendar/Gregorian$Date;-><init>(Ljava/util/TimeZone;)V
+HSPLsun/util/calendar/Gregorian$Date;->getNormalizedYear()I+]Lsun/util/calendar/Gregorian$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/Gregorian$Date;->setNormalizedYear(I)V+]Lsun/util/calendar/Gregorian$Date;Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/Gregorian;->getCalendarDate(JLjava/util/TimeZone;)Lsun/util/calendar/CalendarDate;+]Lsun/util/calendar/Gregorian;Lsun/util/calendar/Gregorian;
+HSPLsun/util/calendar/Gregorian;->getCalendarDate(JLjava/util/TimeZone;)Lsun/util/calendar/Gregorian$Date;+]Lsun/util/calendar/Gregorian;Lsun/util/calendar/Gregorian;
+HSPLsun/util/calendar/Gregorian;->getCalendarDate(JLsun/util/calendar/CalendarDate;)Lsun/util/calendar/CalendarDate;+]Lsun/util/calendar/Gregorian;Lsun/util/calendar/Gregorian;
+HSPLsun/util/calendar/Gregorian;->getCalendarDate(JLsun/util/calendar/CalendarDate;)Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/Gregorian;->newCalendarDate(Ljava/util/TimeZone;)Lsun/util/calendar/CalendarDate;+]Lsun/util/calendar/Gregorian;Lsun/util/calendar/Gregorian;
+HSPLsun/util/calendar/Gregorian;->newCalendarDate(Ljava/util/TimeZone;)Lsun/util/calendar/Gregorian$Date;
+HSPLsun/util/calendar/JulianCalendar$Date;-><init>(Ljava/util/TimeZone;)V
+HSPLsun/util/calendar/JulianCalendar$Date;->getNormalizedYear()I
+HSPLsun/util/calendar/JulianCalendar$Date;->setKnownEra(Lsun/util/calendar/Era;)V
+HSPLsun/util/calendar/JulianCalendar$Date;->setNormalizedYear(I)V
+HSPLsun/util/calendar/JulianCalendar;-><init>()V
+HSPLsun/util/calendar/JulianCalendar;->access$000()[Lsun/util/calendar/Era;
+HSPLsun/util/calendar/JulianCalendar;->getCalendarDateFromFixedDate(Lsun/util/calendar/CalendarDate;J)V+]Lsun/util/calendar/JulianCalendar;Lsun/util/calendar/JulianCalendar;]Lsun/util/calendar/JulianCalendar$Date;Lsun/util/calendar/JulianCalendar$Date;
+HSPLsun/util/calendar/JulianCalendar;->getFixedDate(IIILsun/util/calendar/BaseCalendar$Date;)J+]Lsun/util/calendar/JulianCalendar;Lsun/util/calendar/JulianCalendar;]Lsun/util/calendar/BaseCalendar$Date;Lsun/util/calendar/JulianCalendar$Date;
+HSPLsun/util/calendar/JulianCalendar;->isLeapYear(I)Z
+HSPLsun/util/calendar/JulianCalendar;->newCalendarDate(Ljava/util/TimeZone;)Lsun/util/calendar/CalendarDate;
+HSPLsun/util/calendar/JulianCalendar;->newCalendarDate(Ljava/util/TimeZone;)Lsun/util/calendar/JulianCalendar$Date;
+HSPLsun/util/locale/BaseLocale$Cache;->createObject(Ljava/lang/Object;)Ljava/lang/Object;+]Lsun/util/locale/BaseLocale$Cache;Lsun/util/locale/BaseLocale$Cache;
+HSPLsun/util/locale/BaseLocale$Cache;->createObject(Lsun/util/locale/BaseLocale$Key;)Lsun/util/locale/BaseLocale;+]Ljava/lang/ref/SoftReference;Ljava/lang/ref/SoftReference;
+HSPLsun/util/locale/BaseLocale$Cache;->normalizeKey(Ljava/lang/Object;)Ljava/lang/Object;+]Lsun/util/locale/BaseLocale$Cache;Lsun/util/locale/BaseLocale$Cache;
+HSPLsun/util/locale/BaseLocale$Cache;->normalizeKey(Lsun/util/locale/BaseLocale$Key;)Lsun/util/locale/BaseLocale$Key;
+HSPLsun/util/locale/BaseLocale$Key;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+HSPLsun/util/locale/BaseLocale$Key;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
+HSPLsun/util/locale/BaseLocale$Key;->access$100(Lsun/util/locale/BaseLocale$Key;)Ljava/lang/ref/SoftReference;
+HSPLsun/util/locale/BaseLocale$Key;->access$200(Lsun/util/locale/BaseLocale$Key;)Ljava/lang/ref/SoftReference;
+HSPLsun/util/locale/BaseLocale$Key;->access$300(Lsun/util/locale/BaseLocale$Key;)Ljava/lang/ref/SoftReference;
+HSPLsun/util/locale/BaseLocale$Key;->access$400(Lsun/util/locale/BaseLocale$Key;)Ljava/lang/ref/SoftReference;
+HSPLsun/util/locale/BaseLocale$Key;->equals(Ljava/lang/Object;)Z+]Ljava/lang/ref/SoftReference;Ljava/lang/ref/SoftReference;
+HSPLsun/util/locale/BaseLocale$Key;->hashCode()I
+HSPLsun/util/locale/BaseLocale$Key;->normalize(Lsun/util/locale/BaseLocale$Key;)Lsun/util/locale/BaseLocale$Key;+]Ljava/lang/ref/SoftReference;Ljava/lang/ref/SoftReference;]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/util/locale/BaseLocale;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/util/locale/BaseLocale;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lsun/util/locale/BaseLocale$1;)V
+HSPLsun/util/locale/BaseLocale;->equals(Ljava/lang/Object;)Z
+HSPLsun/util/locale/BaseLocale;->getInstance(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lsun/util/locale/BaseLocale;+]Lsun/util/locale/BaseLocale$Cache;Lsun/util/locale/BaseLocale$Cache;
+HSPLsun/util/locale/BaseLocale;->getLanguage()Ljava/lang/String;
+HSPLsun/util/locale/BaseLocale;->getRegion()Ljava/lang/String;
+HSPLsun/util/locale/BaseLocale;->getScript()Ljava/lang/String;
+HSPLsun/util/locale/BaseLocale;->getVariant()Ljava/lang/String;
+HSPLsun/util/locale/BaseLocale;->hashCode()I+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/util/locale/InternalLocaleBuilder;-><init>()V
+HSPLsun/util/locale/InternalLocaleBuilder;->checkVariants(Ljava/lang/String;Ljava/lang/String;)I
+HSPLsun/util/locale/InternalLocaleBuilder;->clear()Lsun/util/locale/InternalLocaleBuilder;+]Lsun/util/locale/InternalLocaleBuilder;Lsun/util/locale/InternalLocaleBuilder;
+HSPLsun/util/locale/InternalLocaleBuilder;->clearExtensions()Lsun/util/locale/InternalLocaleBuilder;
+HSPLsun/util/locale/InternalLocaleBuilder;->getBaseLocale()Lsun/util/locale/BaseLocale;+]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;]Ljava/util/Map;Ljava/util/HashMap;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/util/locale/InternalLocaleBuilder;->getLocaleExtensions()Lsun/util/locale/LocaleExtensions;+]Lsun/util/locale/LocaleExtensions;Lsun/util/locale/LocaleExtensions;
+HSPLsun/util/locale/InternalLocaleBuilder;->setExtensions(Ljava/util/List;Ljava/lang/String;)Lsun/util/locale/InternalLocaleBuilder;+]Lsun/util/locale/InternalLocaleBuilder;Lsun/util/locale/InternalLocaleBuilder;]Ljava/lang/String;Ljava/lang/String;]Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveChar;Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveChar;]Ljava/util/List;Ljava/util/Collections$UnmodifiableRandomAccessList;]Ljava/util/Iterator;Ljava/util/Collections$UnmodifiableCollection$1;]Ljava/util/Set;Ljava/util/HashSet;]Ljava/util/Map;Ljava/util/HashMap;
+HSPLsun/util/locale/InternalLocaleBuilder;->setLanguage(Ljava/lang/String;)Lsun/util/locale/InternalLocaleBuilder;
+HSPLsun/util/locale/InternalLocaleBuilder;->setLanguageTag(Lsun/util/locale/LanguageTag;)Lsun/util/locale/InternalLocaleBuilder;+]Lsun/util/locale/InternalLocaleBuilder;Lsun/util/locale/InternalLocaleBuilder;]Lsun/util/locale/LanguageTag;Lsun/util/locale/LanguageTag;]Ljava/util/List;Ljava/util/Collections$EmptyList;,Ljava/util/Collections$UnmodifiableRandomAccessList;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLsun/util/locale/InternalLocaleBuilder;->setRegion(Ljava/lang/String;)Lsun/util/locale/InternalLocaleBuilder;
+HSPLsun/util/locale/InternalLocaleBuilder;->setScript(Ljava/lang/String;)Lsun/util/locale/InternalLocaleBuilder;
+HSPLsun/util/locale/InternalLocaleBuilder;->setVariant(Ljava/lang/String;)Lsun/util/locale/InternalLocaleBuilder;+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/util/locale/LanguageTag;-><init>()V
+HSPLsun/util/locale/LanguageTag;->canonicalizeLanguage(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/util/locale/LanguageTag;->canonicalizeRegion(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/util/locale/LanguageTag;->canonicalizeScript(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/util/locale/LanguageTag;->getExtensions()Ljava/util/List;+]Ljava/util/List;Ljava/util/Collections$EmptyList;,Ljava/util/ArrayList;
+HSPLsun/util/locale/LanguageTag;->getExtlangs()Ljava/util/List;+]Ljava/util/List;Ljava/util/Collections$EmptyList;
+HSPLsun/util/locale/LanguageTag;->getLanguage()Ljava/lang/String;
+HSPLsun/util/locale/LanguageTag;->getPrivateuse()Ljava/lang/String;
+HSPLsun/util/locale/LanguageTag;->getRegion()Ljava/lang/String;
+HSPLsun/util/locale/LanguageTag;->getScript()Ljava/lang/String;
+HSPLsun/util/locale/LanguageTag;->getVariants()Ljava/util/List;+]Ljava/util/List;Ljava/util/Collections$EmptyList;,Ljava/util/ArrayList;
+HSPLsun/util/locale/LanguageTag;->isExtlang(Ljava/lang/String;)Z
+HSPLsun/util/locale/LanguageTag;->isLanguage(Ljava/lang/String;)Z
+HSPLsun/util/locale/LanguageTag;->isRegion(Ljava/lang/String;)Z
+HSPLsun/util/locale/LanguageTag;->isScript(Ljava/lang/String;)Z
+HSPLsun/util/locale/LanguageTag;->isVariant(Ljava/lang/String;)Z
+HSPLsun/util/locale/LanguageTag;->parse(Ljava/lang/String;Lsun/util/locale/ParseStatus;)Lsun/util/locale/LanguageTag;+]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;]Ljava/util/Map;Ljava/util/HashMap;]Lsun/util/locale/ParseStatus;Lsun/util/locale/ParseStatus;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLsun/util/locale/LanguageTag;->parseExtensions(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z+]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Ljava/util/List;Ljava/util/Collections$EmptyList;,Ljava/util/ArrayList;]Lsun/util/locale/ParseStatus;Lsun/util/locale/ParseStatus;
+HSPLsun/util/locale/LanguageTag;->parseExtlangs(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z+]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;]Lsun/util/locale/ParseStatus;Lsun/util/locale/ParseStatus;
+HSPLsun/util/locale/LanguageTag;->parseLanguage(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z+]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;]Lsun/util/locale/ParseStatus;Lsun/util/locale/ParseStatus;
+HSPLsun/util/locale/LanguageTag;->parseLocale(Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;)Lsun/util/locale/LanguageTag;+]Lsun/util/locale/BaseLocale;Lsun/util/locale/BaseLocale;]Ljava/util/List;Ljava/util/ArrayList;]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Lsun/util/locale/Extension;Lsun/util/locale/UnicodeLocaleExtension;]Lsun/util/locale/LocaleExtensions;Lsun/util/locale/LocaleExtensions;]Ljava/lang/Character;Ljava/lang/Character;]Ljava/util/Iterator;Ljava/util/Collections$UnmodifiableCollection$1;]Ljava/util/Set;Ljava/util/Collections$UnmodifiableSet;
+HSPLsun/util/locale/LanguageTag;->parsePrivateuse(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z+]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;]Lsun/util/locale/ParseStatus;Lsun/util/locale/ParseStatus;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;
+HSPLsun/util/locale/LanguageTag;->parseRegion(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z+]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;]Lsun/util/locale/ParseStatus;Lsun/util/locale/ParseStatus;
+HSPLsun/util/locale/LanguageTag;->parseScript(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z+]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;]Lsun/util/locale/ParseStatus;Lsun/util/locale/ParseStatus;
+HSPLsun/util/locale/LanguageTag;->parseVariants(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z+]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;]Ljava/util/List;Ljava/util/Collections$EmptyList;,Ljava/util/ArrayList;]Lsun/util/locale/ParseStatus;Lsun/util/locale/ParseStatus;
+HSPLsun/util/locale/LocaleObjectCache$CacheEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+HSPLsun/util/locale/LocaleObjectCache$CacheEntry;->getKey()Ljava/lang/Object;
+HSPLsun/util/locale/LocaleObjectCache;->cleanStaleEntries()V+]Ljava/lang/ref/ReferenceQueue;Ljava/lang/ref/ReferenceQueue;
+HSPLsun/util/locale/LocaleObjectCache;->get(Ljava/lang/Object;)Ljava/lang/Object;+]Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentHashMap;]Lsun/util/locale/LocaleObjectCache$CacheEntry;Lsun/util/locale/LocaleObjectCache$CacheEntry;]Lsun/util/locale/LocaleObjectCache;Ljava/util/Locale$Cache;,Lsun/util/locale/BaseLocale$Cache;,Ljava/util/ResourceBundle$Control$CandidateListCache;
+HSPLsun/util/locale/LocaleObjectCache;->normalizeKey(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLsun/util/locale/LocaleUtils;->caseIgnoreMatch(Ljava/lang/String;Ljava/lang/String;)Z
+HSPLsun/util/locale/LocaleUtils;->isAlpha(C)Z
+HSPLsun/util/locale/LocaleUtils;->isAlphaNumeric(C)Z
+HSPLsun/util/locale/LocaleUtils;->isAlphaNumericString(Ljava/lang/String;)Z
+HSPLsun/util/locale/LocaleUtils;->isAlphaString(Ljava/lang/String;)Z
+HSPLsun/util/locale/LocaleUtils;->isEmpty(Ljava/lang/String;)Z
+HSPLsun/util/locale/LocaleUtils;->isEmpty(Ljava/util/List;)Z+]Ljava/util/List;Ljava/util/Collections$EmptyList;,Ljava/util/Collections$UnmodifiableRandomAccessList;
+HSPLsun/util/locale/LocaleUtils;->isEmpty(Ljava/util/Map;)Z+]Ljava/util/Map;Ljava/util/HashMap;
+HSPLsun/util/locale/LocaleUtils;->isEmpty(Ljava/util/Set;)Z
+HSPLsun/util/locale/LocaleUtils;->isLower(C)Z
+HSPLsun/util/locale/LocaleUtils;->isNumeric(C)Z
+HSPLsun/util/locale/LocaleUtils;->isNumericString(Ljava/lang/String;)Z
+HSPLsun/util/locale/LocaleUtils;->isUpper(C)Z
+HSPLsun/util/locale/LocaleUtils;->toLower(C)C
+HSPLsun/util/locale/LocaleUtils;->toLowerString(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/util/locale/LocaleUtils;->toTitleString(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/util/locale/LocaleUtils;->toUpperString(Ljava/lang/String;)Ljava/lang/String;
+HSPLsun/util/locale/ParseStatus;-><init>()V+]Lsun/util/locale/ParseStatus;Lsun/util/locale/ParseStatus;
+HSPLsun/util/locale/ParseStatus;->isError()Z
+HSPLsun/util/locale/ParseStatus;->reset()V
+HSPLsun/util/locale/StringTokenIterator;-><init>(Ljava/lang/String;Ljava/lang/String;)V+]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;
+HSPLsun/util/locale/StringTokenIterator;->current()Ljava/lang/String;
+HSPLsun/util/locale/StringTokenIterator;->currentEnd()I
+HSPLsun/util/locale/StringTokenIterator;->hasNext()Z
+HSPLsun/util/locale/StringTokenIterator;->isDone()Z
+HSPLsun/util/locale/StringTokenIterator;->next()Ljava/lang/String;+]Ljava/lang/String;Ljava/lang/String;]Lsun/util/locale/StringTokenIterator;Lsun/util/locale/StringTokenIterator;
+HSPLsun/util/locale/StringTokenIterator;->nextDelimiter(I)I
+HSPLsun/util/locale/StringTokenIterator;->setStart(I)Lsun/util/locale/StringTokenIterator;+]Ljava/lang/String;Ljava/lang/String;
+HSPLsun/util/logging/LoggingSupport$2;-><init>()V
+HSPLsun/util/logging/LoggingSupport$2;->run()Ljava/lang/Object;
+HSPLsun/util/logging/LoggingSupport$2;->run()Ljava/lang/String;
+HSPLsun/util/logging/LoggingSupport;->getSimpleFormat()Ljava/lang/String;
+HSPLsun/util/logging/LoggingSupport;->getSimpleFormat(Z)Ljava/lang/String;
+HSPLsun/util/logging/PlatformLogger$JavaLoggerProxy;-><init>(Ljava/lang/String;)V
+HSPLsun/util/logging/PlatformLogger$JavaLoggerProxy;-><init>(Ljava/lang/String;Lsun/util/logging/PlatformLogger$Level;)V
+HSPLsun/util/logging/PlatformLogger$LoggerProxy;-><init>(Ljava/lang/String;)V
+HSPLsun/util/logging/PlatformLogger;-><init>(Ljava/lang/String;)V
+Landroid/compat/Compatibility$1;
+Landroid/compat/Compatibility$BehaviorChangeDelegate;
+Landroid/compat/Compatibility$ChangeConfig;
+Landroid/compat/Compatibility;
+Landroid/system/ErrnoException;
+Landroid/system/GaiException;
+Landroid/system/Int32Ref;
+Landroid/system/Int64Ref;
+Landroid/system/NetlinkSocketAddress;
+Landroid/system/Os;
+Landroid/system/OsConstants;
+Landroid/system/PacketSocketAddress;
+Landroid/system/StructAddrinfo;
+Landroid/system/StructCapUserData;
+Landroid/system/StructCapUserHeader;
+Landroid/system/StructCmsghdr;
+Landroid/system/StructGroupReq;
+Landroid/system/StructIfaddrs;
+Landroid/system/StructLinger;
+Landroid/system/StructMsghdr;
+Landroid/system/StructPasswd;
+Landroid/system/StructPollfd;
+Landroid/system/StructRlimit;
+Landroid/system/StructStat;
+Landroid/system/StructStatVfs;
+Landroid/system/StructTimespec;
+Landroid/system/StructTimeval;
+Landroid/system/StructUcred;
+Landroid/system/StructUtsname;
+Landroid/system/UnixSocketAddress;
+Landroid/system/VmSocketAddress;
+Lcom/android/okhttp/Address;
+Lcom/android/okhttp/AndroidShimResponseCache;
+Lcom/android/okhttp/Authenticator;
+Lcom/android/okhttp/Cache$1;
+Lcom/android/okhttp/Cache$CacheResponseBody$1;
+Lcom/android/okhttp/Cache$CacheResponseBody;
+Lcom/android/okhttp/Cache$Entry;
+Lcom/android/okhttp/Cache;
+Lcom/android/okhttp/CacheControl$Builder;
+Lcom/android/okhttp/CacheControl;
+Lcom/android/okhttp/CertificatePinner$Builder;
+Lcom/android/okhttp/CertificatePinner;
+Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/ConfigAwareConnectionPool$1;
+Lcom/android/okhttp/ConfigAwareConnectionPool;
+Lcom/android/okhttp/Connection;
+Lcom/android/okhttp/ConnectionPool$1;
+Lcom/android/okhttp/ConnectionPool;
+Lcom/android/okhttp/ConnectionSpec$Builder;
+Lcom/android/okhttp/ConnectionSpec;
+Lcom/android/okhttp/ConnectionSpecs;
+Lcom/android/okhttp/Dispatcher;
+Lcom/android/okhttp/Dns$1;
+Lcom/android/okhttp/Dns;
+Lcom/android/okhttp/Handshake;
+Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/HttpHandler$CleartextURLFilter;
+Lcom/android/okhttp/HttpHandler;
+Lcom/android/okhttp/HttpUrl$1;
+Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/HttpsHandler;
+Lcom/android/okhttp/OkCacheContainer;
+Lcom/android/okhttp/OkHttpClient$1;
+Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkUrlFactories;
+Lcom/android/okhttp/OkUrlFactory;
+Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request;
+Lcom/android/okhttp/RequestBody$2;
+Lcom/android/okhttp/RequestBody;
+Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response;
+Lcom/android/okhttp/ResponseBody;
+Lcom/android/okhttp/Route;
+Lcom/android/okhttp/TlsVersion;
+Lcom/android/okhttp/internal/ConnectionSpecSelector;
+Lcom/android/okhttp/internal/DiskLruCache$1;
+Lcom/android/okhttp/internal/DiskLruCache$4;
+Lcom/android/okhttp/internal/DiskLruCache$Editor;
+Lcom/android/okhttp/internal/DiskLruCache$Entry;
+Lcom/android/okhttp/internal/DiskLruCache;
+Lcom/android/okhttp/internal/FaultHidingSink;
+Lcom/android/okhttp/internal/Internal;
+Lcom/android/okhttp/internal/InternalCache;
+Lcom/android/okhttp/internal/OptionalMethod;
+Lcom/android/okhttp/internal/Platform;
+Lcom/android/okhttp/internal/RouteDatabase;
+Lcom/android/okhttp/internal/URLFilter;
+Lcom/android/okhttp/internal/Util$1;
+Lcom/android/okhttp/internal/Util;
+Lcom/android/okhttp/internal/http/AuthenticatorAdapter;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;
+Lcom/android/okhttp/internal/http/CacheStrategy;
+Lcom/android/okhttp/internal/http/HeaderParser;
+Lcom/android/okhttp/internal/http/Http1xStream$AbstractSource;
+Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSink;
+Lcom/android/okhttp/internal/http/Http1xStream$ChunkedSource;
+Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSink;
+Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;
+Lcom/android/okhttp/internal/http/Http1xStream;
+Lcom/android/okhttp/internal/http/HttpDate$1;
+Lcom/android/okhttp/internal/http/HttpDate;
+Lcom/android/okhttp/internal/http/HttpEngine$1;
+Lcom/android/okhttp/internal/http/HttpEngine;
+Lcom/android/okhttp/internal/http/HttpMethod;
+Lcom/android/okhttp/internal/http/HttpStream;
+Lcom/android/okhttp/internal/http/OkHeaders$1;
+Lcom/android/okhttp/internal/http/OkHeaders;
+Lcom/android/okhttp/internal/http/RealResponseBody;
+Lcom/android/okhttp/internal/http/RequestException;
+Lcom/android/okhttp/internal/http/RequestLine;
+Lcom/android/okhttp/internal/http/RetryableSink;
+Lcom/android/okhttp/internal/http/RouteException;
+Lcom/android/okhttp/internal/http/RouteSelector;
+Lcom/android/okhttp/internal/http/StatusLine;
+Lcom/android/okhttp/internal/http/StreamAllocation;
+Lcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;
+Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+Lcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;
+Lcom/android/okhttp/internal/io/FileSystem$1;
+Lcom/android/okhttp/internal/io/FileSystem;
+Lcom/android/okhttp/internal/io/RealConnection;
+Lcom/android/okhttp/internal/tls/OkHostnameVerifier;
+Lcom/android/okhttp/internal/tls/RealTrustRootIndex;
+Lcom/android/okhttp/internal/tls/TrustRootIndex;
+Lcom/android/okhttp/internalandroidapi/AndroidResponseCacheAdapter;
+Lcom/android/okhttp/internalandroidapi/Dns;
+Lcom/android/okhttp/internalandroidapi/HasCacheHolder$CacheHolder;
+Lcom/android/okhttp/internalandroidapi/HasCacheHolder;
+Lcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory$DnsAdapter;
+Lcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory;
+Lcom/android/okhttp/okio/AsyncTimeout$1;
+Lcom/android/okhttp/okio/AsyncTimeout$2;
+Lcom/android/okhttp/okio/AsyncTimeout$Watchdog;
+Lcom/android/okhttp/okio/AsyncTimeout;
+Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSource;
+Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ForwardingSink;
+Lcom/android/okhttp/okio/ForwardingSource;
+Lcom/android/okhttp/okio/ForwardingTimeout;
+Lcom/android/okhttp/okio/GzipSource;
+Lcom/android/okhttp/okio/InflaterSource;
+Lcom/android/okhttp/okio/Okio$1;
+Lcom/android/okhttp/okio/Okio$2;
+Lcom/android/okhttp/okio/Okio$3;
+Lcom/android/okhttp/okio/Okio;
+Lcom/android/okhttp/okio/RealBufferedSink$1;
+Lcom/android/okhttp/okio/RealBufferedSink;
+Lcom/android/okhttp/okio/RealBufferedSource$1;
+Lcom/android/okhttp/okio/RealBufferedSource;
+Lcom/android/okhttp/okio/Segment;
+Lcom/android/okhttp/okio/SegmentPool;
+Lcom/android/okhttp/okio/Sink;
+Lcom/android/okhttp/okio/Source;
+Lcom/android/okhttp/okio/Timeout$1;
+Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Util;
+Lcom/android/org/bouncycastle/asn1/ASN1BitString;
+Lcom/android/org/bouncycastle/asn1/ASN1Choice;
+Lcom/android/org/bouncycastle/asn1/ASN1Encodable;
+Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;
+Lcom/android/org/bouncycastle/asn1/ASN1InputStream;
+Lcom/android/org/bouncycastle/asn1/ASN1Integer;
+Lcom/android/org/bouncycastle/asn1/ASN1Null;
+Lcom/android/org/bouncycastle/asn1/ASN1Object;
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier$OidHandle;
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
+Lcom/android/org/bouncycastle/asn1/ASN1OutputStream;
+Lcom/android/org/bouncycastle/asn1/ASN1Primitive;
+Lcom/android/org/bouncycastle/asn1/ASN1Sequence;
+Lcom/android/org/bouncycastle/asn1/ASN1SequenceParser;
+Lcom/android/org/bouncycastle/asn1/ASN1Set;
+Lcom/android/org/bouncycastle/asn1/ASN1String;
+Lcom/android/org/bouncycastle/asn1/ASN1TaggedObject;
+Lcom/android/org/bouncycastle/asn1/ASN1TaggedObjectParser;
+Lcom/android/org/bouncycastle/asn1/BERTags;
+Lcom/android/org/bouncycastle/asn1/DERBitString;
+Lcom/android/org/bouncycastle/asn1/DERFactory;
+Lcom/android/org/bouncycastle/asn1/DERInteger;
+Lcom/android/org/bouncycastle/asn1/DERNull;
+Lcom/android/org/bouncycastle/asn1/DEROutputStream;
+Lcom/android/org/bouncycastle/asn1/DERSequence;
+Lcom/android/org/bouncycastle/asn1/DERSet;
+Lcom/android/org/bouncycastle/asn1/DERTaggedObject;
+Lcom/android/org/bouncycastle/asn1/DLSequence;
+Lcom/android/org/bouncycastle/asn1/DefiniteLengthInputStream;
+Lcom/android/org/bouncycastle/asn1/InMemoryRepresentable;
+Lcom/android/org/bouncycastle/asn1/IndefiniteLengthInputStream;
+Lcom/android/org/bouncycastle/asn1/LimitedInputStream;
+Lcom/android/org/bouncycastle/asn1/OIDTokenizer;
+Lcom/android/org/bouncycastle/asn1/StreamUtil;
+Lcom/android/org/bouncycastle/asn1/bc/BCObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/iana/IANAObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/misc/MiscObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/nist/NISTObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/x500/X500Name;
+Lcom/android/org/bouncycastle/asn1/x500/X500NameStyle;
+Lcom/android/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle;
+Lcom/android/org/bouncycastle/asn1/x500/style/BCStyle;
+Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;
+Lcom/android/org/bouncycastle/asn1/x509/Certificate;
+Lcom/android/org/bouncycastle/asn1/x509/DSAParameter;
+Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;
+Lcom/android/org/bouncycastle/asn1/x509/Time;
+Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;
+Lcom/android/org/bouncycastle/asn1/x509/X509ExtensionsGenerator;
+Lcom/android/org/bouncycastle/asn1/x509/X509Name;
+Lcom/android/org/bouncycastle/asn1/x509/X509ObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/x9/X9ECParameters;
+Lcom/android/org/bouncycastle/asn1/x9/X9ObjectIdentifiers;
+Lcom/android/org/bouncycastle/crypto/BlockCipher;
+Lcom/android/org/bouncycastle/crypto/BufferedBlockCipher;
+Lcom/android/org/bouncycastle/crypto/CipherParameters;
+Lcom/android/org/bouncycastle/crypto/CryptoException;
+Lcom/android/org/bouncycastle/crypto/CryptoServicesPermission;
+Lcom/android/org/bouncycastle/crypto/CryptoServicesRegistrar$Property;
+Lcom/android/org/bouncycastle/crypto/CryptoServicesRegistrar;
+Lcom/android/org/bouncycastle/crypto/DataLengthException;
+Lcom/android/org/bouncycastle/crypto/Digest;
+Lcom/android/org/bouncycastle/crypto/ExtendedDigest;
+Lcom/android/org/bouncycastle/crypto/InvalidCipherTextException;
+Lcom/android/org/bouncycastle/crypto/OutputLengthException;
+Lcom/android/org/bouncycastle/crypto/PBEParametersGenerator;
+Lcom/android/org/bouncycastle/crypto/RuntimeCryptoException;
+Lcom/android/org/bouncycastle/crypto/digests/AndroidDigestFactory;
+Lcom/android/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle;
+Lcom/android/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface;
+Lcom/android/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL;
+Lcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest$MD5;
+Lcom/android/org/bouncycastle/crypto/digests/OpenSSLDigest;
+Lcom/android/org/bouncycastle/crypto/engines/AESEngine;
+Lcom/android/org/bouncycastle/crypto/paddings/BlockCipherPadding;
+Lcom/android/org/bouncycastle/crypto/paddings/PKCS7Padding;
+Lcom/android/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher;
+Lcom/android/org/bouncycastle/crypto/params/AsymmetricKeyParameter;
+Lcom/android/org/bouncycastle/crypto/params/DHParameters;
+Lcom/android/org/bouncycastle/crypto/params/DHValidationParameters;
+Lcom/android/org/bouncycastle/crypto/params/DSAKeyParameters;
+Lcom/android/org/bouncycastle/crypto/params/DSAParameters;
+Lcom/android/org/bouncycastle/crypto/params/DSAPublicKeyParameters;
+Lcom/android/org/bouncycastle/crypto/params/DSAValidationParameters;
+Lcom/android/org/bouncycastle/crypto/params/KeyParameter;
+Lcom/android/org/bouncycastle/crypto/params/ParametersWithIV;
+Lcom/android/org/bouncycastle/crypto/params/ParametersWithRandom;
+Lcom/android/org/bouncycastle/jcajce/PBKDFKey;
+Lcom/android/org/bouncycastle/jcajce/PKCS12Key;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/DH$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/DH;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/DSA$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/EC$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/EC;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/RSA$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/RSA;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/X509$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyFactorySpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi$EC;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi$NoPadding;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/rsa/RSAUtil;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/util/KeyUtil;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil$Boundaries;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil;
+Lcom/android/org/bouncycastle/jcajce/provider/config/ConfigurableProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/config/ProviderConfiguration;
+Lcom/android/org/bouncycastle/jcajce/provider/config/ProviderConfigurationPermission;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/DigestAlgorithmProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/MD5$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/MD5;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA1$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA1;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA224$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA224;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA256$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA256;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA384$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA384;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA512$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA512;
+Lcom/android/org/bouncycastle/jcajce/provider/keystore/BC$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/keystore/PKCS12$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$Std;
+Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$StoreEntry;
+Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/AES$ECB$1;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/AES$ECB;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/AES$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/AES;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/ARC4$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/ARC4;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/Blowfish$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/Blowfish;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/DES$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/DES;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/DESede$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/DESede;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBEPKCS12$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBEPKCS12;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBES2AlgorithmParameters$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBES2AlgorithmParameters;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/RC2$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/RC2;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/Twofish$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/Twofish;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$AEADGenericBlockCipher;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$BufferedGenericBlockCipher;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher$GenericBlockCipher;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseSecretKeyFactory;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/BlockCipherProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/ClassUtil;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/PBE$Util;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/util/PBE;
+Lcom/android/org/bouncycastle/jcajce/provider/util/AlgorithmProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/util/AsymmetricKeyInfoConverter;
+Lcom/android/org/bouncycastle/jcajce/provider/util/DigestFactory;
+Lcom/android/org/bouncycastle/jcajce/spec/AEADParameterSpec;
+Lcom/android/org/bouncycastle/jcajce/util/BCJcaJceHelper;
+Lcom/android/org/bouncycastle/jcajce/util/DefaultJcaJceHelper;
+Lcom/android/org/bouncycastle/jcajce/util/JcaJceHelper;
+Lcom/android/org/bouncycastle/jcajce/util/ProviderJcaJceHelper;
+Lcom/android/org/bouncycastle/jce/X509Principal;
+Lcom/android/org/bouncycastle/jce/interfaces/BCKeyStore;
+Lcom/android/org/bouncycastle/jce/interfaces/PKCS12BagAttributeCarrier;
+Lcom/android/org/bouncycastle/jce/provider/BouncyCastleProvider$1;
+Lcom/android/org/bouncycastle/jce/provider/BouncyCastleProvider;
+Lcom/android/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration;
+Lcom/android/org/bouncycastle/jce/provider/CertStoreCollectionSpi;
+Lcom/android/org/bouncycastle/jce/provider/X509CertificateObject;
+Lcom/android/org/bouncycastle/jce/spec/ECKeySpec;
+Lcom/android/org/bouncycastle/jce/spec/ECPublicKeySpec;
+Lcom/android/org/bouncycastle/util/Arrays;
+Lcom/android/org/bouncycastle/util/Encodable;
+Lcom/android/org/bouncycastle/util/Integers;
+Lcom/android/org/bouncycastle/util/Iterable;
+Lcom/android/org/bouncycastle/util/Pack;
+Lcom/android/org/bouncycastle/util/Properties$1;
+Lcom/android/org/bouncycastle/util/Properties;
+Lcom/android/org/bouncycastle/util/Strings$1;
+Lcom/android/org/bouncycastle/util/Strings;
+Lcom/android/org/bouncycastle/util/encoders/Encoder;
+Lcom/android/org/bouncycastle/util/encoders/Hex;
+Lcom/android/org/bouncycastle/util/encoders/HexEncoder;
+Lcom/android/org/bouncycastle/util/io/Streams;
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;
+Lcom/android/org/kxml2/io/KXmlParser$ContentSource;
+Lcom/android/org/kxml2/io/KXmlParser$ValueContext;
+Lcom/android/org/kxml2/io/KXmlParser;
+Lcom/android/org/kxml2/io/KXmlSerializer;
+Lcom/sun/security/cert/internal/x509/X509V1CertImpl;
+Ldalvik/annotation/optimization/CriticalNative;
+Ldalvik/annotation/optimization/FastNative;
+Ldalvik/system/AppSpecializationHooks;
+Ldalvik/system/BaseDexClassLoader$Reporter;
+Ldalvik/system/BaseDexClassLoader;
+Ldalvik/system/BlockGuard$1;
+Ldalvik/system/BlockGuard$2;
+Ldalvik/system/BlockGuard$3;
+Ldalvik/system/BlockGuard$BlockGuardPolicyException;
+Ldalvik/system/BlockGuard$Policy;
+Ldalvik/system/BlockGuard$VmPolicy;
+Ldalvik/system/BlockGuard;
+Ldalvik/system/ClassExt;
+Ldalvik/system/CloseGuard$DefaultReporter;
+Ldalvik/system/CloseGuard$Reporter;
+Ldalvik/system/CloseGuard$Tracker;
+Ldalvik/system/CloseGuard;
+Ldalvik/system/DelegateLastClassLoader;
+Ldalvik/system/DexClassLoader;
+Ldalvik/system/DexFile$1;
+Ldalvik/system/DexFile$DFEnum;
+Ldalvik/system/DexFile$OptimizationInfo;
+Ldalvik/system/DexFile;
+Ldalvik/system/DexPathList$$ExternalSyntheticLambda0;
+Ldalvik/system/DexPathList$Element;
+Ldalvik/system/DexPathList$NativeLibraryElement;
+Ldalvik/system/DexPathList;
+Ldalvik/system/EmulatedStackFrame$Range;
+Ldalvik/system/EmulatedStackFrame;
+Ldalvik/system/InMemoryDexClassLoader;
+Ldalvik/system/PathClassLoader;
+Ldalvik/system/RuntimeHooks;
+Ldalvik/system/SocketTagger$1;
+Ldalvik/system/SocketTagger;
+Ldalvik/system/VMDebug;
+Ldalvik/system/VMRuntime$HiddenApiUsageLogger;
+Ldalvik/system/VMRuntime;
+Ldalvik/system/VMStack;
+Ldalvik/system/ZygoteHooks;
+Ljava/awt/font/NumericShaper;
+Ljava/awt/font/TextAttribute;
+Ljava/io/Bits;
+Ljava/io/BufferedInputStream;
+Ljava/io/BufferedOutputStream;
+Ljava/io/BufferedReader;
+Ljava/io/BufferedWriter;
+Ljava/io/ByteArrayInputStream;
+Ljava/io/ByteArrayOutputStream;
+Ljava/io/CharArrayReader;
+Ljava/io/CharArrayWriter;
+Ljava/io/Closeable;
+Ljava/io/Console;
+Ljava/io/DataInput;
+Ljava/io/DataInputStream;
+Ljava/io/DataOutput;
+Ljava/io/DataOutputStream;
+Ljava/io/DefaultFileSystem;
+Ljava/io/EOFException;
+Ljava/io/ExpiringCache$1;
+Ljava/io/ExpiringCache;
+Ljava/io/Externalizable;
+Ljava/io/File$PathStatus;
+Ljava/io/File$TempDirectory;
+Ljava/io/File;
+Ljava/io/FileDescriptor$1;
+Ljava/io/FileDescriptor;
+Ljava/io/FileFilter;
+Ljava/io/FileInputStream$UseManualSkipException;
+Ljava/io/FileInputStream;
+Ljava/io/FileNotFoundException;
+Ljava/io/FileOutputStream;
+Ljava/io/FileReader;
+Ljava/io/FileSystem;
+Ljava/io/FileWriter;
+Ljava/io/FilenameFilter;
+Ljava/io/FilterInputStream;
+Ljava/io/FilterOutputStream;
+Ljava/io/FilterReader;
+Ljava/io/Flushable;
+Ljava/io/IOException;
+Ljava/io/InputStream;
+Ljava/io/InputStreamReader;
+Ljava/io/InterruptedIOException;
+Ljava/io/InvalidClassException;
+Ljava/io/InvalidObjectException;
+Ljava/io/LineNumberReader;
+Ljava/io/NotSerializableException;
+Ljava/io/ObjectInput;
+Ljava/io/ObjectInputStream$BlockDataInputStream;
+Ljava/io/ObjectInputStream$GetField;
+Ljava/io/ObjectInputStream$GetFieldImpl;
+Ljava/io/ObjectInputStream$HandleTable$HandleList;
+Ljava/io/ObjectInputStream$HandleTable;
+Ljava/io/ObjectInputStream$PeekInputStream;
+Ljava/io/ObjectInputStream$ValidationList;
+Ljava/io/ObjectInputStream;
+Ljava/io/ObjectOutput;
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+Ljava/io/ObjectOutputStream$HandleTable;
+Ljava/io/ObjectOutputStream$PutField;
+Ljava/io/ObjectOutputStream$ReplaceTable;
+Ljava/io/ObjectOutputStream;
+Ljava/io/ObjectStreamClass$$ExternalSyntheticLambda0;
+Ljava/io/ObjectStreamClass$1;
+Ljava/io/ObjectStreamClass$2;
+Ljava/io/ObjectStreamClass$3;
+Ljava/io/ObjectStreamClass$4;
+Ljava/io/ObjectStreamClass$5;
+Ljava/io/ObjectStreamClass$Caches;
+Ljava/io/ObjectStreamClass$ClassDataSlot;
+Ljava/io/ObjectStreamClass$DefaultSUIDCompatibilityListener;
+Ljava/io/ObjectStreamClass$EntryFuture;
+Ljava/io/ObjectStreamClass$ExceptionInfo;
+Ljava/io/ObjectStreamClass$FieldReflector;
+Ljava/io/ObjectStreamClass$FieldReflectorKey;
+Ljava/io/ObjectStreamClass$MemberSignature;
+Ljava/io/ObjectStreamClass$WeakClassKey;
+Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectStreamConstants;
+Ljava/io/ObjectStreamException;
+Ljava/io/ObjectStreamField;
+Ljava/io/OptionalDataException;
+Ljava/io/OutputStream;
+Ljava/io/OutputStreamWriter;
+Ljava/io/PrintStream;
+Ljava/io/PrintWriter;
+Ljava/io/PushbackInputStream;
+Ljava/io/PushbackReader;
+Ljava/io/RandomAccessFile;
+Ljava/io/Reader;
+Ljava/io/SequenceInputStream;
+Ljava/io/SerialCallbackContext;
+Ljava/io/Serializable;
+Ljava/io/SerializablePermission;
+Ljava/io/StreamCorruptedException;
+Ljava/io/StringBufferInputStream;
+Ljava/io/StringReader;
+Ljava/io/StringWriter;
+Ljava/io/UTFDataFormatException;
+Ljava/io/UncheckedIOException;
+Ljava/io/UnixFileSystem;
+Ljava/io/UnsupportedEncodingException;
+Ljava/io/Writer;
+Ljava/lang/AbstractMethodError;
+Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AndroidHardcodedSystemProperties;
+Ljava/lang/Appendable;
+Ljava/lang/ArithmeticException;
+Ljava/lang/ArrayIndexOutOfBoundsException;
+Ljava/lang/ArrayStoreException;
+Ljava/lang/AssertionError;
+Ljava/lang/AutoCloseable;
+Ljava/lang/Boolean;
+Ljava/lang/BootClassLoader;
+Ljava/lang/Byte$ByteCache;
+Ljava/lang/Byte;
+Ljava/lang/CaseMapper$1;
+Ljava/lang/CaseMapper;
+Ljava/lang/CharSequence$$ExternalSyntheticLambda0;
+Ljava/lang/CharSequence$$ExternalSyntheticLambda1;
+Ljava/lang/CharSequence$1CharIterator;
+Ljava/lang/CharSequence$1CodePointIterator;
+Ljava/lang/CharSequence;
+Ljava/lang/Character$CharacterCache;
+Ljava/lang/Character$Subset;
+Ljava/lang/Character$UnicodeBlock;
+Ljava/lang/Character;
+Ljava/lang/Class$Caches;
+Ljava/lang/Class;
+Ljava/lang/ClassCastException;
+Ljava/lang/ClassFormatError;
+Ljava/lang/ClassLoader$SystemClassLoader;
+Ljava/lang/ClassLoader;
+Ljava/lang/ClassNotFoundException;
+Ljava/lang/CloneNotSupportedException;
+Ljava/lang/Cloneable;
+Ljava/lang/Comparable;
+Ljava/lang/Daemons$Daemon;
+Ljava/lang/Daemons$FinalizerDaemon;
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;
+Ljava/lang/Daemons$HeapTaskDaemon;
+Ljava/lang/Daemons$ReferenceQueueDaemon;
+Ljava/lang/Daemons;
+Ljava/lang/Deprecated;
+Ljava/lang/DexCache;
+Ljava/lang/Double;
+Ljava/lang/Enum$1;
+Ljava/lang/Enum;
+Ljava/lang/EnumConstantNotPresentException;
+Ljava/lang/Error;
+Ljava/lang/Exception;
+Ljava/lang/ExceptionInInitializerError;
+Ljava/lang/Float;
+Ljava/lang/IllegalAccessError;
+Ljava/lang/IllegalAccessException;
+Ljava/lang/IllegalArgumentException;
+Ljava/lang/IllegalMonitorStateException;
+Ljava/lang/IllegalStateException;
+Ljava/lang/IllegalThreadStateException;
+Ljava/lang/IncompatibleClassChangeError;
+Ljava/lang/IndexOutOfBoundsException;
+Ljava/lang/InheritableThreadLocal;
+Ljava/lang/InstantiationError;
+Ljava/lang/InstantiationException;
+Ljava/lang/Integer$IntegerCache;
+Ljava/lang/Integer;
+Ljava/lang/InternalError;
+Ljava/lang/InterruptedException;
+Ljava/lang/Iterable;
+Ljava/lang/LinkageError;
+Ljava/lang/Long$LongCache;
+Ljava/lang/Long;
+Ljava/lang/Math$RandomNumberGeneratorHolder;
+Ljava/lang/Math;
+Ljava/lang/NegativeArraySizeException;
+Ljava/lang/NoClassDefFoundError;
+Ljava/lang/NoSuchFieldError;
+Ljava/lang/NoSuchFieldException;
+Ljava/lang/NoSuchMethodError;
+Ljava/lang/NoSuchMethodException;
+Ljava/lang/NullPointerException;
+Ljava/lang/Number;
+Ljava/lang/NumberFormatException;
+Ljava/lang/Object;
+Ljava/lang/OutOfMemoryError;
+Ljava/lang/Package;
+Ljava/lang/Process;
+Ljava/lang/ProcessBuilder$NullInputStream;
+Ljava/lang/ProcessBuilder$NullOutputStream;
+Ljava/lang/ProcessBuilder;
+Ljava/lang/ProcessEnvironment$ExternalData;
+Ljava/lang/ProcessEnvironment$StringEnvironment;
+Ljava/lang/ProcessEnvironment$Value;
+Ljava/lang/ProcessEnvironment$Variable;
+Ljava/lang/ProcessEnvironment;
+Ljava/lang/ProcessImpl;
+Ljava/lang/Readable;
+Ljava/lang/ReflectiveOperationException;
+Ljava/lang/Runnable;
+Ljava/lang/Runtime;
+Ljava/lang/RuntimeException;
+Ljava/lang/RuntimePermission;
+Ljava/lang/SecurityException;
+Ljava/lang/SecurityManager;
+Ljava/lang/Short$ShortCache;
+Ljava/lang/Short;
+Ljava/lang/StackOverflowError;
+Ljava/lang/StackTraceElement;
+Ljava/lang/StrictMath;
+Ljava/lang/String$1;
+Ljava/lang/String$CaseInsensitiveComparator;
+Ljava/lang/String;
+Ljava/lang/StringBuffer;
+Ljava/lang/StringBuilder;
+Ljava/lang/StringFactory;
+Ljava/lang/StringIndexOutOfBoundsException;
+Ljava/lang/System$PropertiesWithNonOverrideableDefaults;
+Ljava/lang/System;
+Ljava/lang/Thread$1;
+Ljava/lang/Thread$Caches;
+Ljava/lang/Thread$State;
+Ljava/lang/Thread$UncaughtExceptionHandler;
+Ljava/lang/Thread$WeakClassKey;
+Ljava/lang/Thread;
+Ljava/lang/ThreadDeath;
+Ljava/lang/ThreadGroup;
+Ljava/lang/ThreadLocal$SuppliedThreadLocal;
+Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+Ljava/lang/ThreadLocal$ThreadLocalMap;
+Ljava/lang/ThreadLocal;
+Ljava/lang/Throwable$PrintStreamOrWriter;
+Ljava/lang/Throwable$SentinelHolder;
+Ljava/lang/Throwable$WrappedPrintStream;
+Ljava/lang/Throwable$WrappedPrintWriter;
+Ljava/lang/Throwable;
+Ljava/lang/TypeNotPresentException;
+Ljava/lang/UNIXProcess$1;
+Ljava/lang/UNIXProcess$2;
+Ljava/lang/UNIXProcess$3;
+Ljava/lang/UNIXProcess$ProcessPipeInputStream;
+Ljava/lang/UNIXProcess$ProcessPipeOutputStream;
+Ljava/lang/UNIXProcess$ProcessReaperThreadFactory$1;
+Ljava/lang/UNIXProcess$ProcessReaperThreadFactory;
+Ljava/lang/UNIXProcess;
+Ljava/lang/UnsatisfiedLinkError;
+Ljava/lang/UnsupportedOperationException;
+Ljava/lang/VMClassLoader;
+Ljava/lang/VerifyError;
+Ljava/lang/VirtualMachineError;
+Ljava/lang/Void;
+Ljava/lang/annotation/Annotation;
+Ljava/lang/annotation/AnnotationTypeMismatchException;
+Ljava/lang/annotation/Documented;
+Ljava/lang/annotation/IncompleteAnnotationException;
+Ljava/lang/annotation/Inherited;
+Ljava/lang/annotation/Retention;
+Ljava/lang/annotation/Target;
+Ljava/lang/invoke/ArrayElementVarHandle;
+Ljava/lang/invoke/ByteArrayViewVarHandle;
+Ljava/lang/invoke/ByteBufferViewVarHandle;
+Ljava/lang/invoke/CallSite;
+Ljava/lang/invoke/ConstantCallSite;
+Ljava/lang/invoke/FieldVarHandle;
+Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandleImpl$HandleInfo;
+Ljava/lang/invoke/MethodHandleImpl;
+Ljava/lang/invoke/MethodHandleInfo;
+Ljava/lang/invoke/MethodHandleStatics;
+Ljava/lang/invoke/MethodHandles$Lookup;
+Ljava/lang/invoke/MethodHandles;
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry;
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;
+Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodTypeForm;
+Ljava/lang/invoke/SerializedLambda;
+Ljava/lang/invoke/Transformers$AlwaysThrow;
+Ljava/lang/invoke/Transformers$BindTo;
+Ljava/lang/invoke/Transformers$CatchException;
+Ljava/lang/invoke/Transformers$CollectArguments;
+Ljava/lang/invoke/Transformers$Collector;
+Ljava/lang/invoke/Transformers$Constant;
+Ljava/lang/invoke/Transformers$Construct;
+Ljava/lang/invoke/Transformers$DropArguments;
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;
+Ljava/lang/invoke/Transformers$FilterArguments;
+Ljava/lang/invoke/Transformers$FilterReturnValue;
+Ljava/lang/invoke/Transformers$FoldArguments;
+Ljava/lang/invoke/Transformers$GuardWithTest;
+Ljava/lang/invoke/Transformers$InsertArguments;
+Ljava/lang/invoke/Transformers$Invoker;
+Ljava/lang/invoke/Transformers$PermuteArguments;
+Ljava/lang/invoke/Transformers$ReferenceArrayElementGetter;
+Ljava/lang/invoke/Transformers$ReferenceArrayElementSetter;
+Ljava/lang/invoke/Transformers$ReferenceIdentity;
+Ljava/lang/invoke/Transformers$Spreader;
+Ljava/lang/invoke/Transformers$Transformer;
+Ljava/lang/invoke/Transformers$VarargsCollector;
+Ljava/lang/invoke/VarHandle$1;
+Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle;
+Ljava/lang/invoke/WrongMethodTypeException;
+Ljava/lang/ref/FinalizerReference$1;
+Ljava/lang/ref/FinalizerReference$Sentinel;
+Ljava/lang/ref/FinalizerReference;
+Ljava/lang/ref/PhantomReference;
+Ljava/lang/ref/Reference$SinkHolder$1;
+Ljava/lang/ref/Reference$SinkHolder;
+Ljava/lang/ref/Reference;
+Ljava/lang/ref/ReferenceQueue;
+Ljava/lang/ref/SoftReference;
+Ljava/lang/ref/WeakReference;
+Ljava/lang/reflect/AccessibleObject;
+Ljava/lang/reflect/AnnotatedElement;
+Ljava/lang/reflect/Array;
+Ljava/lang/reflect/Constructor;
+Ljava/lang/reflect/Executable$GenericInfo;
+Ljava/lang/reflect/Executable;
+Ljava/lang/reflect/Field;
+Ljava/lang/reflect/GenericArrayType;
+Ljava/lang/reflect/GenericDeclaration;
+Ljava/lang/reflect/GenericSignatureFormatError;
+Ljava/lang/reflect/InvocationHandler;
+Ljava/lang/reflect/InvocationTargetException;
+Ljava/lang/reflect/MalformedParametersException;
+Ljava/lang/reflect/Member;
+Ljava/lang/reflect/Method$1;
+Ljava/lang/reflect/Method;
+Ljava/lang/reflect/Modifier;
+Ljava/lang/reflect/Parameter;
+Ljava/lang/reflect/ParameterizedType;
+Ljava/lang/reflect/Proxy$1;
+Ljava/lang/reflect/Proxy$Key1;
+Ljava/lang/reflect/Proxy$Key2;
+Ljava/lang/reflect/Proxy$KeyFactory;
+Ljava/lang/reflect/Proxy$KeyX;
+Ljava/lang/reflect/Proxy$ProxyClassFactory;
+Ljava/lang/reflect/Proxy;
+Ljava/lang/reflect/Type;
+Ljava/lang/reflect/TypeVariable;
+Ljava/lang/reflect/UndeclaredThrowableException;
+Ljava/lang/reflect/WeakCache$CacheKey;
+Ljava/lang/reflect/WeakCache$CacheValue;
+Ljava/lang/reflect/WeakCache$Factory;
+Ljava/lang/reflect/WeakCache$LookupValue;
+Ljava/lang/reflect/WeakCache$Value;
+Ljava/lang/reflect/WeakCache;
+Ljava/lang/reflect/WildcardType;
+Ljava/math/BigDecimal$1;
+Ljava/math/BigDecimal;
+Ljava/math/BigInteger$UnsafeHolder;
+Ljava/math/BigInteger;
+Ljava/math/MathContext;
+Ljava/math/MutableBigInteger;
+Ljava/math/RoundingMode;
+Ljava/net/AbstractPlainDatagramSocketImpl;
+Ljava/net/AbstractPlainSocketImpl;
+Ljava/net/AddressCache$AddressCacheEntry;
+Ljava/net/AddressCache$AddressCacheKey;
+Ljava/net/AddressCache;
+Ljava/net/Authenticator$RequestorType;
+Ljava/net/Authenticator;
+Ljava/net/ConnectException;
+Ljava/net/CookieHandler;
+Ljava/net/CookieManager$CookiePathComparator;
+Ljava/net/CookieManager;
+Ljava/net/CookiePolicy$1;
+Ljava/net/CookiePolicy$2;
+Ljava/net/CookiePolicy$3;
+Ljava/net/CookiePolicy;
+Ljava/net/CookieStore;
+Ljava/net/DatagramPacket;
+Ljava/net/DatagramSocket$1;
+Ljava/net/DatagramSocket;
+Ljava/net/DatagramSocketImpl;
+Ljava/net/DefaultDatagramSocketImplFactory;
+Ljava/net/DefaultInterface;
+Ljava/net/HttpCookie$10;
+Ljava/net/HttpCookie$11;
+Ljava/net/HttpCookie$1;
+Ljava/net/HttpCookie$2;
+Ljava/net/HttpCookie$3;
+Ljava/net/HttpCookie$4;
+Ljava/net/HttpCookie$5;
+Ljava/net/HttpCookie$6;
+Ljava/net/HttpCookie$7;
+Ljava/net/HttpCookie$8;
+Ljava/net/HttpCookie$9;
+Ljava/net/HttpCookie$CookieAttributeAssignor;
+Ljava/net/HttpCookie;
+Ljava/net/HttpRetryException;
+Ljava/net/HttpURLConnection;
+Ljava/net/IDN;
+Ljava/net/InMemoryCookieStore;
+Ljava/net/Inet4Address;
+Ljava/net/Inet6Address$Inet6AddressHolder;
+Ljava/net/Inet6Address;
+Ljava/net/Inet6AddressImpl;
+Ljava/net/InetAddress$1;
+Ljava/net/InetAddress$InetAddressHolder;
+Ljava/net/InetAddress;
+Ljava/net/InetAddressImpl;
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;
+Ljava/net/InetSocketAddress;
+Ljava/net/InterfaceAddress;
+Ljava/net/JarURLConnection;
+Ljava/net/MalformedURLException;
+Ljava/net/MulticastSocket;
+Ljava/net/NetPermission;
+Ljava/net/NetworkInterface$1checkedAddresses;
+Ljava/net/NetworkInterface;
+Ljava/net/NoRouteToHostException;
+Ljava/net/Parts;
+Ljava/net/PasswordAuthentication;
+Ljava/net/PlainDatagramSocketImpl;
+Ljava/net/PlainSocketImpl;
+Ljava/net/PortUnreachableException;
+Ljava/net/ProtocolException;
+Ljava/net/ProtocolFamily;
+Ljava/net/Proxy$Type;
+Ljava/net/Proxy;
+Ljava/net/ProxySelector;
+Ljava/net/ResponseCache;
+Ljava/net/ServerSocket;
+Ljava/net/Socket$1;
+Ljava/net/Socket$2;
+Ljava/net/Socket$3;
+Ljava/net/Socket;
+Ljava/net/SocketAddress;
+Ljava/net/SocketException;
+Ljava/net/SocketImpl;
+Ljava/net/SocketImplFactory;
+Ljava/net/SocketInputStream;
+Ljava/net/SocketOptions;
+Ljava/net/SocketOutputStream;
+Ljava/net/SocketPermission;
+Ljava/net/SocketTimeoutException;
+Ljava/net/SocksConsts;
+Ljava/net/SocksSocketImpl;
+Ljava/net/StandardProtocolFamily;
+Ljava/net/URI$Parser;
+Ljava/net/URI;
+Ljava/net/URISyntaxException;
+Ljava/net/URL;
+Ljava/net/URLConnection;
+Ljava/net/URLDecoder;
+Ljava/net/URLEncoder;
+Ljava/net/URLStreamHandler;
+Ljava/net/URLStreamHandlerFactory;
+Ljava/net/UnknownHostException;
+Ljava/net/UnknownServiceException;
+Ljava/nio/Bits;
+Ljava/nio/Buffer;
+Ljava/nio/BufferOverflowException;
+Ljava/nio/BufferUnderflowException;
+Ljava/nio/ByteBuffer;
+Ljava/nio/ByteBufferAsCharBuffer;
+Ljava/nio/ByteBufferAsDoubleBuffer;
+Ljava/nio/ByteBufferAsFloatBuffer;
+Ljava/nio/ByteBufferAsIntBuffer;
+Ljava/nio/ByteBufferAsLongBuffer;
+Ljava/nio/ByteBufferAsShortBuffer;
+Ljava/nio/ByteOrder;
+Ljava/nio/CharBuffer;
+Ljava/nio/DirectByteBuffer$MemoryRef;
+Ljava/nio/DirectByteBuffer;
+Ljava/nio/DoubleBuffer;
+Ljava/nio/FloatBuffer;
+Ljava/nio/HeapByteBuffer;
+Ljava/nio/HeapCharBuffer;
+Ljava/nio/IntBuffer;
+Ljava/nio/InvalidMarkException;
+Ljava/nio/LongBuffer;
+Ljava/nio/MappedByteBuffer;
+Ljava/nio/NIOAccess;
+Ljava/nio/NioUtils;
+Ljava/nio/ReadOnlyBufferException;
+Ljava/nio/ShortBuffer;
+Ljava/nio/StringCharBuffer;
+Ljava/nio/channels/AsynchronousCloseException;
+Ljava/nio/channels/ByteChannel;
+Ljava/nio/channels/Channel;
+Ljava/nio/channels/Channels$1;
+Ljava/nio/channels/Channels;
+Ljava/nio/channels/ClosedByInterruptException;
+Ljava/nio/channels/ClosedChannelException;
+Ljava/nio/channels/DatagramChannel;
+Ljava/nio/channels/FileChannel$MapMode;
+Ljava/nio/channels/FileChannel;
+Ljava/nio/channels/FileLock;
+Ljava/nio/channels/GatheringByteChannel;
+Ljava/nio/channels/InterruptibleChannel;
+Ljava/nio/channels/MulticastChannel;
+Ljava/nio/channels/NetworkChannel;
+Ljava/nio/channels/OverlappingFileLockException;
+Ljava/nio/channels/ReadableByteChannel;
+Ljava/nio/channels/ScatteringByteChannel;
+Ljava/nio/channels/SeekableByteChannel;
+Ljava/nio/channels/SelectableChannel;
+Ljava/nio/channels/SelectionKey;
+Ljava/nio/channels/Selector;
+Ljava/nio/channels/ServerSocketChannel;
+Ljava/nio/channels/SocketChannel;
+Ljava/nio/channels/WritableByteChannel;
+Ljava/nio/channels/spi/AbstractInterruptibleChannel$1;
+Ljava/nio/channels/spi/AbstractInterruptibleChannel;
+Ljava/nio/channels/spi/AbstractSelectableChannel;
+Ljava/nio/channels/spi/AbstractSelectionKey;
+Ljava/nio/channels/spi/AbstractSelector$1;
+Ljava/nio/channels/spi/AbstractSelector;
+Ljava/nio/channels/spi/SelectorProvider$1;
+Ljava/nio/channels/spi/SelectorProvider;
+Ljava/nio/charset/CharacterCodingException;
+Ljava/nio/charset/Charset;
+Ljava/nio/charset/CharsetDecoder;
+Ljava/nio/charset/CharsetEncoder;
+Ljava/nio/charset/CoderMalfunctionError;
+Ljava/nio/charset/CoderResult$1;
+Ljava/nio/charset/CoderResult$2;
+Ljava/nio/charset/CoderResult$Cache;
+Ljava/nio/charset/CoderResult;
+Ljava/nio/charset/CodingErrorAction;
+Ljava/nio/charset/IllegalCharsetNameException;
+Ljava/nio/charset/StandardCharsets;
+Ljava/nio/charset/UnsupportedCharsetException;
+Ljava/nio/file/AccessMode;
+Ljava/nio/file/CopyMoveHelper;
+Ljava/nio/file/CopyOption;
+Ljava/nio/file/DirectoryStream$Filter;
+Ljava/nio/file/DirectoryStream;
+Ljava/nio/file/FileAlreadyExistsException;
+Ljava/nio/file/FileSystem;
+Ljava/nio/file/FileSystemException;
+Ljava/nio/file/FileSystems$DefaultFileSystemHolder$1;
+Ljava/nio/file/FileSystems$DefaultFileSystemHolder;
+Ljava/nio/file/FileSystems;
+Ljava/nio/file/Files$AcceptAllFilter;
+Ljava/nio/file/Files;
+Ljava/nio/file/InvalidPathException;
+Ljava/nio/file/LinkOption;
+Ljava/nio/file/NoSuchFileException;
+Ljava/nio/file/OpenOption;
+Ljava/nio/file/Path;
+Ljava/nio/file/Paths;
+Ljava/nio/file/StandardCopyOption;
+Ljava/nio/file/StandardOpenOption;
+Ljava/nio/file/Watchable;
+Ljava/nio/file/attribute/AttributeView;
+Ljava/nio/file/attribute/BasicFileAttributeView;
+Ljava/nio/file/attribute/BasicFileAttributes;
+Ljava/nio/file/attribute/FileAttribute;
+Ljava/nio/file/attribute/FileAttributeView;
+Ljava/nio/file/attribute/FileTime;
+Ljava/nio/file/attribute/PosixFileAttributes;
+Ljava/nio/file/spi/FileSystemProvider;
+Ljava/security/AccessControlContext;
+Ljava/security/AccessControlException;
+Ljava/security/AccessController;
+Ljava/security/AlgorithmConstraints;
+Ljava/security/AlgorithmParameters;
+Ljava/security/AlgorithmParametersSpi;
+Ljava/security/AllPermission;
+Ljava/security/BasicPermission;
+Ljava/security/CodeSigner;
+Ljava/security/CryptoPrimitive;
+Ljava/security/DigestException;
+Ljava/security/GeneralSecurityException;
+Ljava/security/Guard;
+Ljava/security/InvalidAlgorithmParameterException;
+Ljava/security/InvalidKeyException;
+Ljava/security/InvalidParameterException;
+Ljava/security/Key;
+Ljava/security/KeyException;
+Ljava/security/KeyFactory;
+Ljava/security/KeyFactorySpi;
+Ljava/security/KeyManagementException;
+Ljava/security/KeyPair;
+Ljava/security/KeyPairGenerator$Delegate;
+Ljava/security/KeyPairGenerator;
+Ljava/security/KeyPairGeneratorSpi;
+Ljava/security/KeyStore$1;
+Ljava/security/KeyStore$Entry;
+Ljava/security/KeyStore$LoadStoreParameter;
+Ljava/security/KeyStore$PasswordProtection;
+Ljava/security/KeyStore$PrivateKeyEntry;
+Ljava/security/KeyStore$ProtectionParameter;
+Ljava/security/KeyStore$SecretKeyEntry;
+Ljava/security/KeyStore$TrustedCertificateEntry;
+Ljava/security/KeyStore;
+Ljava/security/KeyStoreException;
+Ljava/security/KeyStoreSpi;
+Ljava/security/MessageDigest$Delegate;
+Ljava/security/MessageDigest;
+Ljava/security/MessageDigestSpi;
+Ljava/security/NoSuchAlgorithmException;
+Ljava/security/NoSuchProviderException;
+Ljava/security/Permission;
+Ljava/security/PermissionCollection;
+Ljava/security/Permissions;
+Ljava/security/Principal;
+Ljava/security/PrivateKey;
+Ljava/security/PrivilegedAction;
+Ljava/security/PrivilegedActionException;
+Ljava/security/PrivilegedExceptionAction;
+Ljava/security/ProtectionDomain;
+Ljava/security/Provider$EngineDescription;
+Ljava/security/Provider$Service;
+Ljava/security/Provider$ServiceKey;
+Ljava/security/Provider$UString;
+Ljava/security/Provider;
+Ljava/security/ProviderException;
+Ljava/security/PublicKey;
+Ljava/security/SecureRandom;
+Ljava/security/SecureRandomSpi;
+Ljava/security/Security;
+Ljava/security/SecurityPermission;
+Ljava/security/Signature$Delegate;
+Ljava/security/Signature;
+Ljava/security/SignatureException;
+Ljava/security/SignatureSpi;
+Ljava/security/UnrecoverableEntryException;
+Ljava/security/UnrecoverableKeyException;
+Ljava/security/cert/CRL;
+Ljava/security/cert/CRLException;
+Ljava/security/cert/CRLReason;
+Ljava/security/cert/CertPath;
+Ljava/security/cert/CertPathBuilderException;
+Ljava/security/cert/CertPathChecker;
+Ljava/security/cert/CertPathHelperImpl;
+Ljava/security/cert/CertPathParameters;
+Ljava/security/cert/CertPathValidator;
+Ljava/security/cert/CertPathValidatorException;
+Ljava/security/cert/CertPathValidatorResult;
+Ljava/security/cert/CertPathValidatorSpi;
+Ljava/security/cert/CertSelector;
+Ljava/security/cert/CertStore;
+Ljava/security/cert/CertStoreException;
+Ljava/security/cert/CertStoreParameters;
+Ljava/security/cert/CertStoreSpi;
+Ljava/security/cert/Certificate;
+Ljava/security/cert/CertificateEncodingException;
+Ljava/security/cert/CertificateException;
+Ljava/security/cert/CertificateExpiredException;
+Ljava/security/cert/CertificateFactory;
+Ljava/security/cert/CertificateFactorySpi;
+Ljava/security/cert/CertificateNotYetValidException;
+Ljava/security/cert/CertificateParsingException;
+Ljava/security/cert/CollectionCertStoreParameters;
+Ljava/security/cert/Extension;
+Ljava/security/cert/PKIXCertPathChecker;
+Ljava/security/cert/PKIXCertPathValidatorResult;
+Ljava/security/cert/PKIXParameters;
+Ljava/security/cert/PKIXRevocationChecker$Option;
+Ljava/security/cert/PKIXRevocationChecker;
+Ljava/security/cert/PolicyNode;
+Ljava/security/cert/PolicyQualifierInfo;
+Ljava/security/cert/TrustAnchor;
+Ljava/security/cert/X509CRL;
+Ljava/security/cert/X509CRLEntry;
+Ljava/security/cert/X509CertSelector;
+Ljava/security/cert/X509Certificate;
+Ljava/security/cert/X509Extension;
+Ljava/security/interfaces/DSAKey;
+Ljava/security/interfaces/DSAParams;
+Ljava/security/interfaces/DSAPublicKey;
+Ljava/security/interfaces/ECKey;
+Ljava/security/interfaces/ECPrivateKey;
+Ljava/security/interfaces/ECPublicKey;
+Ljava/security/interfaces/RSAKey;
+Ljava/security/interfaces/RSAPrivateCrtKey;
+Ljava/security/interfaces/RSAPrivateKey;
+Ljava/security/interfaces/RSAPublicKey;
+Ljava/security/spec/AlgorithmParameterSpec;
+Ljava/security/spec/DSAParameterSpec;
+Ljava/security/spec/DSAPublicKeySpec;
+Ljava/security/spec/ECField;
+Ljava/security/spec/ECFieldFp;
+Ljava/security/spec/ECGenParameterSpec;
+Ljava/security/spec/ECParameterSpec;
+Ljava/security/spec/ECPoint;
+Ljava/security/spec/ECPrivateKeySpec;
+Ljava/security/spec/ECPublicKeySpec;
+Ljava/security/spec/EllipticCurve;
+Ljava/security/spec/EncodedKeySpec;
+Ljava/security/spec/InvalidKeySpecException;
+Ljava/security/spec/InvalidParameterSpecException;
+Ljava/security/spec/KeySpec;
+Ljava/security/spec/MGF1ParameterSpec;
+Ljava/security/spec/PKCS8EncodedKeySpec;
+Ljava/security/spec/PSSParameterSpec;
+Ljava/security/spec/RSAKeyGenParameterSpec;
+Ljava/security/spec/RSAPrivateCrtKeySpec;
+Ljava/security/spec/RSAPrivateKeySpec;
+Ljava/security/spec/RSAPublicKeySpec;
+Ljava/security/spec/X509EncodedKeySpec;
+Ljava/sql/Date;
+Ljava/sql/SQLException;
+Ljava/sql/Time;
+Ljava/sql/Timestamp;
+Ljava/text/AttributedCharacterIterator$Attribute;
+Ljava/text/AttributedCharacterIterator;
+Ljava/text/AttributedString;
+Ljava/text/Bidi;
+Ljava/text/BreakIterator;
+Ljava/text/CalendarBuilder;
+Ljava/text/CharacterIterator;
+Ljava/text/CharacterIteratorFieldDelegate;
+Ljava/text/ChoiceFormat;
+Ljava/text/CollationElementIterator;
+Ljava/text/CollationKey;
+Ljava/text/Collator;
+Ljava/text/DateFormat$Field;
+Ljava/text/DateFormat;
+Ljava/text/DateFormatSymbols;
+Ljava/text/DecimalFormat$1;
+Ljava/text/DecimalFormat;
+Ljava/text/DecimalFormatSymbols;
+Ljava/text/DontCareFieldPosition$1;
+Ljava/text/DontCareFieldPosition;
+Ljava/text/FieldPosition$Delegate;
+Ljava/text/FieldPosition;
+Ljava/text/Format$Field;
+Ljava/text/Format$FieldDelegate;
+Ljava/text/Format;
+Ljava/text/IcuIteratorWrapper;
+Ljava/text/MessageFormat$Field;
+Ljava/text/MessageFormat;
+Ljava/text/Normalizer$Form$$ExternalSyntheticLambda0;
+Ljava/text/Normalizer$Form$$ExternalSyntheticLambda1;
+Ljava/text/Normalizer$Form$$ExternalSyntheticLambda2;
+Ljava/text/Normalizer$Form$$ExternalSyntheticLambda3;
+Ljava/text/Normalizer$Form;
+Ljava/text/Normalizer;
+Ljava/text/NumberFormat$Field;
+Ljava/text/NumberFormat;
+Ljava/text/ParseException;
+Ljava/text/ParsePosition;
+Ljava/text/RuleBasedCollator;
+Ljava/text/SimpleDateFormat;
+Ljava/text/StringCharacterIterator;
+Ljava/time/Clock$SystemClock;
+Ljava/time/Clock;
+Ljava/time/DateTimeException;
+Ljava/time/DayOfWeek;
+Ljava/time/Duration;
+Ljava/time/Instant$1;
+Ljava/time/Instant;
+Ljava/time/LocalDate$1;
+Ljava/time/LocalDate;
+Ljava/time/LocalDateTime;
+Ljava/time/LocalTime;
+Ljava/time/Month;
+Ljava/time/OffsetDateTime;
+Ljava/time/Period;
+Ljava/time/ZoneId;
+Ljava/time/ZoneOffset;
+Ljava/time/ZoneRegion;
+Ljava/time/ZonedDateTime$$ExternalSyntheticLambda0;
+Ljava/time/ZonedDateTime;
+Ljava/time/chrono/AbstractChronology$$ExternalSyntheticLambda0;
+Ljava/time/chrono/AbstractChronology$$ExternalSyntheticLambda1;
+Ljava/time/chrono/AbstractChronology$$ExternalSyntheticLambda2;
+Ljava/time/chrono/AbstractChronology;
+Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/ChronoLocalDateTime;
+Ljava/time/chrono/ChronoPeriod;
+Ljava/time/chrono/ChronoZonedDateTime;
+Ljava/time/chrono/Chronology;
+Ljava/time/chrono/IsoChronology;
+Ljava/time/format/DateTimeFormatter$$ExternalSyntheticLambda0;
+Ljava/time/format/DateTimeFormatter$$ExternalSyntheticLambda1;
+Ljava/time/format/DateTimeFormatter;
+Ljava/time/format/DateTimeFormatterBuilder$$ExternalSyntheticLambda0;
+Ljava/time/format/DateTimeFormatterBuilder$1;
+Ljava/time/format/DateTimeFormatterBuilder$2;
+Ljava/time/format/DateTimeFormatterBuilder$CharLiteralPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$InstantPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;
+Ljava/time/format/DateTimeFormatterBuilder$StringLiteralPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$TextPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder;
+Ljava/time/format/DateTimeParseContext;
+Ljava/time/format/DateTimeParseException;
+Ljava/time/format/DateTimeTextProvider$1;
+Ljava/time/format/DateTimeTextProvider$LocaleStore;
+Ljava/time/format/DateTimeTextProvider;
+Ljava/time/format/DecimalStyle;
+Ljava/time/format/Parsed;
+Ljava/time/format/ResolverStyle;
+Ljava/time/format/SignStyle;
+Ljava/time/format/TextStyle;
+Ljava/time/temporal/ChronoField;
+Ljava/time/temporal/ChronoUnit;
+Ljava/time/temporal/IsoFields$Field$1;
+Ljava/time/temporal/IsoFields$Field$2;
+Ljava/time/temporal/IsoFields$Field$3;
+Ljava/time/temporal/IsoFields$Field$4;
+Ljava/time/temporal/IsoFields$Field;
+Ljava/time/temporal/IsoFields$Unit;
+Ljava/time/temporal/IsoFields;
+Ljava/time/temporal/JulianFields$Field;
+Ljava/time/temporal/JulianFields;
+Ljava/time/temporal/Temporal;
+Ljava/time/temporal/TemporalAccessor;
+Ljava/time/temporal/TemporalAdjuster;
+Ljava/time/temporal/TemporalAdjusters;
+Ljava/time/temporal/TemporalAmount;
+Ljava/time/temporal/TemporalField;
+Ljava/time/temporal/TemporalQueries$$ExternalSyntheticLambda0;
+Ljava/time/temporal/TemporalQueries$$ExternalSyntheticLambda1;
+Ljava/time/temporal/TemporalQueries$$ExternalSyntheticLambda2;
+Ljava/time/temporal/TemporalQueries$$ExternalSyntheticLambda3;
+Ljava/time/temporal/TemporalQueries$$ExternalSyntheticLambda4;
+Ljava/time/temporal/TemporalQueries$$ExternalSyntheticLambda5;
+Ljava/time/temporal/TemporalQueries$$ExternalSyntheticLambda6;
+Ljava/time/temporal/TemporalQueries;
+Ljava/time/temporal/TemporalQuery;
+Ljava/time/temporal/TemporalUnit;
+Ljava/time/temporal/UnsupportedTemporalTypeException;
+Ljava/time/temporal/ValueRange;
+Ljava/time/zone/IcuZoneRulesProvider$ZoneRulesCache;
+Ljava/time/zone/IcuZoneRulesProvider;
+Ljava/time/zone/ZoneOffsetTransition;
+Ljava/time/zone/ZoneOffsetTransitionRule$1;
+Ljava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;
+Ljava/time/zone/ZoneOffsetTransitionRule;
+Ljava/time/zone/ZoneRules;
+Ljava/time/zone/ZoneRulesException;
+Ljava/time/zone/ZoneRulesProvider;
+Ljava/util/AbstractCollection;
+Ljava/util/AbstractList$1;
+Ljava/util/AbstractList$Itr;
+Ljava/util/AbstractList$ListItr;
+Ljava/util/AbstractList$RandomAccessSpliterator;
+Ljava/util/AbstractList$RandomAccessSubList;
+Ljava/util/AbstractList$SubList;
+Ljava/util/AbstractList;
+Ljava/util/AbstractMap$1;
+Ljava/util/AbstractMap$2;
+Ljava/util/AbstractMap$SimpleEntry;
+Ljava/util/AbstractMap$SimpleImmutableEntry;
+Ljava/util/AbstractMap;
+Ljava/util/AbstractQueue;
+Ljava/util/AbstractSequentialList;
+Ljava/util/AbstractSet;
+Ljava/util/ArrayDeque$DeqIterator;
+Ljava/util/ArrayDeque;
+Ljava/util/ArrayList$1;
+Ljava/util/ArrayList$ArrayListSpliterator;
+Ljava/util/ArrayList$Itr;
+Ljava/util/ArrayList$ListItr;
+Ljava/util/ArrayList$SubList$1;
+Ljava/util/ArrayList$SubList;
+Ljava/util/ArrayList;
+Ljava/util/ArrayPrefixHelpers$CumulateTask;
+Ljava/util/ArrayPrefixHelpers$DoubleCumulateTask;
+Ljava/util/ArrayPrefixHelpers$IntCumulateTask;
+Ljava/util/ArrayPrefixHelpers$LongCumulateTask;
+Ljava/util/Arrays$$ExternalSyntheticLambda0;
+Ljava/util/Arrays$$ExternalSyntheticLambda1;
+Ljava/util/Arrays$$ExternalSyntheticLambda2;
+Ljava/util/Arrays$$ExternalSyntheticLambda3;
+Ljava/util/Arrays$ArrayList;
+Ljava/util/Arrays$NaturalOrder;
+Ljava/util/Arrays;
+Ljava/util/ArraysParallelSortHelpers$FJByte$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJChar$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJDouble$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJFloat$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJInt$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJLong$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJObject$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJShort$Sorter;
+Ljava/util/Base64$Decoder;
+Ljava/util/Base64$Encoder;
+Ljava/util/Base64;
+Ljava/util/BitSet;
+Ljava/util/Calendar$Builder;
+Ljava/util/Calendar;
+Ljava/util/Collection;
+Ljava/util/Collections$1;
+Ljava/util/Collections$2;
+Ljava/util/Collections$3;
+Ljava/util/Collections$AsLIFOQueue;
+Ljava/util/Collections$CheckedCollection;
+Ljava/util/Collections$CheckedList;
+Ljava/util/Collections$CheckedMap;
+Ljava/util/Collections$CheckedNavigableMap;
+Ljava/util/Collections$CheckedNavigableSet;
+Ljava/util/Collections$CheckedQueue;
+Ljava/util/Collections$CheckedRandomAccessList;
+Ljava/util/Collections$CheckedSet;
+Ljava/util/Collections$CheckedSortedMap;
+Ljava/util/Collections$CheckedSortedSet;
+Ljava/util/Collections$CopiesList;
+Ljava/util/Collections$EmptyEnumeration;
+Ljava/util/Collections$EmptyIterator;
+Ljava/util/Collections$EmptyList;
+Ljava/util/Collections$EmptyListIterator;
+Ljava/util/Collections$EmptyMap;
+Ljava/util/Collections$EmptySet;
+Ljava/util/Collections$ReverseComparator2;
+Ljava/util/Collections$ReverseComparator;
+Ljava/util/Collections$SetFromMap;
+Ljava/util/Collections$SingletonList;
+Ljava/util/Collections$SingletonMap;
+Ljava/util/Collections$SingletonSet;
+Ljava/util/Collections$SynchronizedCollection;
+Ljava/util/Collections$SynchronizedList;
+Ljava/util/Collections$SynchronizedMap;
+Ljava/util/Collections$SynchronizedNavigableMap;
+Ljava/util/Collections$SynchronizedNavigableSet;
+Ljava/util/Collections$SynchronizedRandomAccessList;
+Ljava/util/Collections$SynchronizedSet;
+Ljava/util/Collections$SynchronizedSortedMap;
+Ljava/util/Collections$SynchronizedSortedSet;
+Ljava/util/Collections$UnmodifiableCollection$1;
+Ljava/util/Collections$UnmodifiableCollection;
+Ljava/util/Collections$UnmodifiableList$1;
+Ljava/util/Collections$UnmodifiableList;
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1;
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry;
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet;
+Ljava/util/Collections$UnmodifiableMap;
+Ljava/util/Collections$UnmodifiableNavigableMap$EmptyNavigableMap;
+Ljava/util/Collections$UnmodifiableNavigableMap;
+Ljava/util/Collections$UnmodifiableNavigableSet$EmptyNavigableSet;
+Ljava/util/Collections$UnmodifiableNavigableSet;
+Ljava/util/Collections$UnmodifiableRandomAccessList;
+Ljava/util/Collections$UnmodifiableSet;
+Ljava/util/Collections$UnmodifiableSortedMap;
+Ljava/util/Collections$UnmodifiableSortedSet;
+Ljava/util/Collections;
+Ljava/util/ComparableTimSort;
+Ljava/util/Comparator$$ExternalSyntheticLambda0;
+Ljava/util/Comparator$$ExternalSyntheticLambda1;
+Ljava/util/Comparator$$ExternalSyntheticLambda2;
+Ljava/util/Comparator$$ExternalSyntheticLambda3;
+Ljava/util/Comparator$$ExternalSyntheticLambda4;
+Ljava/util/Comparator$$ExternalSyntheticLambda5;
+Ljava/util/Comparator;
+Ljava/util/Comparators$NaturalOrderComparator;
+Ljava/util/Comparators$NullComparator;
+Ljava/util/ConcurrentModificationException;
+Ljava/util/Currency;
+Ljava/util/Date;
+Ljava/util/Deque;
+Ljava/util/Dictionary;
+Ljava/util/DualPivotQuicksort;
+Ljava/util/DuplicateFormatFlagsException;
+Ljava/util/EnumMap$1;
+Ljava/util/EnumMap$EntryIterator$Entry;
+Ljava/util/EnumMap$EntryIterator;
+Ljava/util/EnumMap$EntrySet;
+Ljava/util/EnumMap$EnumMapIterator;
+Ljava/util/EnumMap$KeyIterator;
+Ljava/util/EnumMap$KeySet;
+Ljava/util/EnumMap$ValueIterator;
+Ljava/util/EnumMap$Values;
+Ljava/util/EnumMap;
+Ljava/util/EnumSet$SerializationProxy;
+Ljava/util/EnumSet;
+Ljava/util/Enumeration;
+Ljava/util/EventListener;
+Ljava/util/EventObject;
+Ljava/util/FormatFlagsConversionMismatchException;
+Ljava/util/Formattable;
+Ljava/util/Formatter$Conversion;
+Ljava/util/Formatter$DateTime;
+Ljava/util/Formatter$FixedString;
+Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$FormatSpecifier;
+Ljava/util/Formatter$FormatSpecifierParser;
+Ljava/util/Formatter$FormatString;
+Ljava/util/Formatter;
+Ljava/util/FormatterClosedException;
+Ljava/util/GregorianCalendar;
+Ljava/util/HashMap$EntryIterator;
+Ljava/util/HashMap$EntrySet;
+Ljava/util/HashMap$EntrySpliterator;
+Ljava/util/HashMap$HashIterator;
+Ljava/util/HashMap$HashMapSpliterator;
+Ljava/util/HashMap$KeyIterator;
+Ljava/util/HashMap$KeySet;
+Ljava/util/HashMap$KeySpliterator;
+Ljava/util/HashMap$Node;
+Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$ValueIterator;
+Ljava/util/HashMap$ValueSpliterator;
+Ljava/util/HashMap$Values;
+Ljava/util/HashMap;
+Ljava/util/HashSet;
+Ljava/util/Hashtable$EntrySet;
+Ljava/util/Hashtable$Enumerator;
+Ljava/util/Hashtable$HashtableEntry;
+Ljava/util/Hashtable$KeySet;
+Ljava/util/Hashtable$ValueCollection;
+Ljava/util/Hashtable;
+Ljava/util/IdentityHashMap$EntryIterator$Entry;
+Ljava/util/IdentityHashMap$EntryIterator;
+Ljava/util/IdentityHashMap$EntrySet;
+Ljava/util/IdentityHashMap$IdentityHashMapIterator;
+Ljava/util/IdentityHashMap$KeyIterator;
+Ljava/util/IdentityHashMap$KeySet;
+Ljava/util/IdentityHashMap$ValueIterator;
+Ljava/util/IdentityHashMap$Values;
+Ljava/util/IdentityHashMap;
+Ljava/util/IllegalFormatException;
+Ljava/util/IllegalFormatFlagsException;
+Ljava/util/IllegalFormatPrecisionException;
+Ljava/util/IllegalFormatWidthException;
+Ljava/util/IllformedLocaleException;
+Ljava/util/ImmutableCollections$AbstractImmutableCollection;
+Ljava/util/ImmutableCollections$AbstractImmutableList;
+Ljava/util/ImmutableCollections$AbstractImmutableMap;
+Ljava/util/ImmutableCollections$AbstractImmutableSet;
+Ljava/util/ImmutableCollections$List12;
+Ljava/util/ImmutableCollections$ListN;
+Ljava/util/ImmutableCollections$Map0;
+Ljava/util/ImmutableCollections$Map1;
+Ljava/util/ImmutableCollections$MapN;
+Ljava/util/ImmutableCollections$Set0;
+Ljava/util/ImmutableCollections$Set1;
+Ljava/util/ImmutableCollections$Set2;
+Ljava/util/ImmutableCollections$SetN;
+Ljava/util/ImmutableCollections;
+Ljava/util/Iterator;
+Ljava/util/JumboEnumSet$EnumSetIterator;
+Ljava/util/JumboEnumSet;
+Ljava/util/KeyValueHolder;
+Ljava/util/LinkedHashMap$LinkedEntryIterator;
+Ljava/util/LinkedHashMap$LinkedEntrySet;
+Ljava/util/LinkedHashMap$LinkedHashIterator;
+Ljava/util/LinkedHashMap$LinkedHashMapEntry;
+Ljava/util/LinkedHashMap$LinkedKeyIterator;
+Ljava/util/LinkedHashMap$LinkedKeySet;
+Ljava/util/LinkedHashMap$LinkedValueIterator;
+Ljava/util/LinkedHashMap$LinkedValues;
+Ljava/util/LinkedHashMap;
+Ljava/util/LinkedHashSet;
+Ljava/util/LinkedList$ListItr;
+Ljava/util/LinkedList$Node;
+Ljava/util/LinkedList;
+Ljava/util/List;
+Ljava/util/ListIterator;
+Ljava/util/ListResourceBundle;
+Ljava/util/Locale$1;
+Ljava/util/Locale$Builder;
+Ljava/util/Locale$Cache;
+Ljava/util/Locale$Category;
+Ljava/util/Locale$FilteringMode;
+Ljava/util/Locale$LanguageRange;
+Ljava/util/Locale$LocaleKey;
+Ljava/util/Locale$NoImagePreloadHolder;
+Ljava/util/Locale;
+Ljava/util/Map$Entry;
+Ljava/util/Map;
+Ljava/util/MissingFormatArgumentException;
+Ljava/util/MissingFormatWidthException;
+Ljava/util/MissingResourceException;
+Ljava/util/NavigableMap;
+Ljava/util/NavigableSet;
+Ljava/util/NoSuchElementException;
+Ljava/util/Objects;
+Ljava/util/Observable;
+Ljava/util/Observer;
+Ljava/util/Optional;
+Ljava/util/OptionalDouble;
+Ljava/util/OptionalInt;
+Ljava/util/PrimitiveIterator$OfInt;
+Ljava/util/PrimitiveIterator;
+Ljava/util/PriorityQueue$Itr;
+Ljava/util/PriorityQueue;
+Ljava/util/Properties$LineReader;
+Ljava/util/Properties;
+Ljava/util/PropertyPermission;
+Ljava/util/PropertyResourceBundle;
+Ljava/util/Queue;
+Ljava/util/Random;
+Ljava/util/RandomAccess;
+Ljava/util/RegularEnumSet$EnumSetIterator;
+Ljava/util/RegularEnumSet;
+Ljava/util/ResourceBundle$1;
+Ljava/util/ResourceBundle$BundleReference;
+Ljava/util/ResourceBundle$CacheKey;
+Ljava/util/ResourceBundle$CacheKeyReference;
+Ljava/util/ResourceBundle$Control$1;
+Ljava/util/ResourceBundle$Control$CandidateListCache;
+Ljava/util/ResourceBundle$Control;
+Ljava/util/ResourceBundle$LoaderReference;
+Ljava/util/ResourceBundle;
+Ljava/util/Scanner$1;
+Ljava/util/Scanner;
+Ljava/util/ServiceConfigurationError;
+Ljava/util/ServiceLoader$1;
+Ljava/util/ServiceLoader$LazyIterator;
+Ljava/util/ServiceLoader;
+Ljava/util/Set;
+Ljava/util/SimpleTimeZone;
+Ljava/util/SortedMap;
+Ljava/util/SortedSet;
+Ljava/util/Spliterator$OfDouble;
+Ljava/util/Spliterator$OfInt;
+Ljava/util/Spliterator$OfLong;
+Ljava/util/Spliterator$OfPrimitive;
+Ljava/util/Spliterator;
+Ljava/util/Spliterators$ArraySpliterator;
+Ljava/util/Spliterators$EmptySpliterator$OfDouble;
+Ljava/util/Spliterators$EmptySpliterator$OfInt;
+Ljava/util/Spliterators$EmptySpliterator$OfLong;
+Ljava/util/Spliterators$EmptySpliterator$OfRef;
+Ljava/util/Spliterators$EmptySpliterator;
+Ljava/util/Spliterators$IntArraySpliterator;
+Ljava/util/Spliterators$IteratorSpliterator;
+Ljava/util/Spliterators;
+Ljava/util/Stack;
+Ljava/util/StringJoiner;
+Ljava/util/StringTokenizer;
+Ljava/util/TaskQueue;
+Ljava/util/TimSort;
+Ljava/util/TimeZone;
+Ljava/util/Timer$1;
+Ljava/util/Timer;
+Ljava/util/TimerTask;
+Ljava/util/TimerThread;
+Ljava/util/TooManyListenersException;
+Ljava/util/TreeMap$AscendingSubMap$AscendingEntrySetView;
+Ljava/util/TreeMap$AscendingSubMap;
+Ljava/util/TreeMap$DescendingSubMap;
+Ljava/util/TreeMap$EntryIterator;
+Ljava/util/TreeMap$EntrySet;
+Ljava/util/TreeMap$KeyIterator;
+Ljava/util/TreeMap$KeySet;
+Ljava/util/TreeMap$NavigableSubMap$EntrySetView;
+Ljava/util/TreeMap$NavigableSubMap$SubMapEntryIterator;
+Ljava/util/TreeMap$NavigableSubMap$SubMapIterator;
+Ljava/util/TreeMap$NavigableSubMap$SubMapKeyIterator;
+Ljava/util/TreeMap$NavigableSubMap;
+Ljava/util/TreeMap$PrivateEntryIterator;
+Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$ValueIterator;
+Ljava/util/TreeMap$Values;
+Ljava/util/TreeMap;
+Ljava/util/TreeSet;
+Ljava/util/UUID$Holder;
+Ljava/util/UUID;
+Ljava/util/UnknownFormatConversionException;
+Ljava/util/Vector$1;
+Ljava/util/Vector$Itr;
+Ljava/util/Vector;
+Ljava/util/WeakHashMap$1;
+Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap$EntryIterator;
+Ljava/util/WeakHashMap$EntrySet;
+Ljava/util/WeakHashMap$HashIterator;
+Ljava/util/WeakHashMap$KeyIterator;
+Ljava/util/WeakHashMap$KeySet;
+Ljava/util/WeakHashMap$ValueIterator;
+Ljava/util/WeakHashMap$Values;
+Ljava/util/WeakHashMap;
+Ljava/util/concurrent/AbstractExecutorService;
+Ljava/util/concurrent/ArrayBlockingQueue;
+Ljava/util/concurrent/BlockingDeque;
+Ljava/util/concurrent/BlockingQueue;
+Ljava/util/concurrent/Callable;
+Ljava/util/concurrent/CancellationException;
+Ljava/util/concurrent/CompletableFuture$AltResult;
+Ljava/util/concurrent/CompletableFuture$AsynchronousCompletionTask;
+Ljava/util/concurrent/CompletableFuture$Completion;
+Ljava/util/concurrent/CompletableFuture$Signaller;
+Ljava/util/concurrent/CompletableFuture$UniCompletion;
+Ljava/util/concurrent/CompletableFuture$UniWhenComplete;
+Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletionStage;
+Ljava/util/concurrent/ConcurrentHashMap$BaseIterator;
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;
+Ljava/util/concurrent/ConcurrentHashMap$CollectionView;
+Ljava/util/concurrent/ConcurrentHashMap$CounterCell;
+Ljava/util/concurrent/ConcurrentHashMap$EntryIterator;
+Ljava/util/concurrent/ConcurrentHashMap$EntrySetView;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachEntryTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachKeyTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachMappingTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedEntryTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedKeyTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedMappingTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedValueTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachValueTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForwardingNode;
+Ljava/util/concurrent/ConcurrentHashMap$KeyIterator;
+Ljava/util/concurrent/ConcurrentHashMap$KeySetView;
+Ljava/util/concurrent/ConcurrentHashMap$MapEntry;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReservationNode;
+Ljava/util/concurrent/ConcurrentHashMap$SearchEntriesTask;
+Ljava/util/concurrent/ConcurrentHashMap$SearchKeysTask;
+Ljava/util/concurrent/ConcurrentHashMap$SearchMappingsTask;
+Ljava/util/concurrent/ConcurrentHashMap$SearchValuesTask;
+Ljava/util/concurrent/ConcurrentHashMap$Segment;
+Ljava/util/concurrent/ConcurrentHashMap$TableStack;
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;
+Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$ValueIterator;
+Ljava/util/concurrent/ConcurrentHashMap$ValuesView;
+Ljava/util/concurrent/ConcurrentHashMap;
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;
+Ljava/util/concurrent/ConcurrentLinkedQueue$Itr;
+Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentLinkedQueue;
+Ljava/util/concurrent/ConcurrentMap$$ExternalSyntheticLambda0;
+Ljava/util/concurrent/ConcurrentMap;
+Ljava/util/concurrent/ConcurrentNavigableMap;
+Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;
+Ljava/util/concurrent/ConcurrentSkipListMap$Iter;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap$ValueIterator;
+Ljava/util/concurrent/ConcurrentSkipListMap$Values;
+Ljava/util/concurrent/ConcurrentSkipListMap;
+Ljava/util/concurrent/ConcurrentSkipListSet;
+Ljava/util/concurrent/CopyOnWriteArrayList$COWIterator;
+Ljava/util/concurrent/CopyOnWriteArrayList;
+Ljava/util/concurrent/CopyOnWriteArraySet;
+Ljava/util/concurrent/CountDownLatch$Sync;
+Ljava/util/concurrent/CountDownLatch;
+Ljava/util/concurrent/CountedCompleter;
+Ljava/util/concurrent/DelayQueue;
+Ljava/util/concurrent/Delayed;
+Ljava/util/concurrent/ExecutionException;
+Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/ExecutorService;
+Ljava/util/concurrent/Executors$DefaultThreadFactory;
+Ljava/util/concurrent/Executors$DelegatedExecutorService;
+Ljava/util/concurrent/Executors$DelegatedScheduledExecutorService;
+Ljava/util/concurrent/Executors$FinalizableDelegatedExecutorService;
+Ljava/util/concurrent/Executors$RunnableAdapter;
+Ljava/util/concurrent/Executors;
+Ljava/util/concurrent/ForkJoinPool$1;
+Ljava/util/concurrent/ForkJoinPool$DefaultForkJoinWorkerThreadFactory;
+Ljava/util/concurrent/ForkJoinPool$ForkJoinWorkerThreadFactory;
+Ljava/util/concurrent/ForkJoinPool$ManagedBlocker;
+Ljava/util/concurrent/ForkJoinPool;
+Ljava/util/concurrent/ForkJoinTask$ExceptionNode;
+Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinWorkerThread;
+Ljava/util/concurrent/Future;
+Ljava/util/concurrent/FutureTask$WaitNode;
+Ljava/util/concurrent/FutureTask;
+Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque;
+Ljava/util/concurrent/LinkedBlockingQueue$Itr;
+Ljava/util/concurrent/LinkedBlockingQueue$Node;
+Ljava/util/concurrent/LinkedBlockingQueue;
+Ljava/util/concurrent/PriorityBlockingQueue;
+Ljava/util/concurrent/RejectedExecutionException;
+Ljava/util/concurrent/RejectedExecutionHandler;
+Ljava/util/concurrent/RunnableFuture;
+Ljava/util/concurrent/RunnableScheduledFuture;
+Ljava/util/concurrent/ScheduledExecutorService;
+Ljava/util/concurrent/ScheduledFuture;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;
+Ljava/util/concurrent/Semaphore$FairSync;
+Ljava/util/concurrent/Semaphore$NonfairSync;
+Ljava/util/concurrent/Semaphore$Sync;
+Ljava/util/concurrent/Semaphore;
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;
+Ljava/util/concurrent/SynchronousQueue$TransferStack;
+Ljava/util/concurrent/SynchronousQueue$Transferer;
+Ljava/util/concurrent/SynchronousQueue;
+Ljava/util/concurrent/ThreadFactory;
+Ljava/util/concurrent/ThreadLocalRandom$1;
+Ljava/util/concurrent/ThreadLocalRandom;
+Ljava/util/concurrent/ThreadPoolExecutor$AbortPolicy;
+Ljava/util/concurrent/ThreadPoolExecutor$DiscardPolicy;
+Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+Ljava/util/concurrent/ThreadPoolExecutor;
+Ljava/util/concurrent/TimeUnit$1;
+Ljava/util/concurrent/TimeUnit$2;
+Ljava/util/concurrent/TimeUnit$3;
+Ljava/util/concurrent/TimeUnit$4;
+Ljava/util/concurrent/TimeUnit$5;
+Ljava/util/concurrent/TimeUnit$6;
+Ljava/util/concurrent/TimeUnit$7;
+Ljava/util/concurrent/TimeUnit;
+Ljava/util/concurrent/TimeoutException;
+Ljava/util/concurrent/atomic/AtomicBoolean;
+Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/util/concurrent/atomic/AtomicIntegerArray;
+Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;
+Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater;
+Ljava/util/concurrent/atomic/AtomicLong;
+Ljava/util/concurrent/atomic/AtomicLongArray;
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater;
+Ljava/util/concurrent/atomic/AtomicReference;
+Ljava/util/concurrent/atomic/AtomicReferenceArray;
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;
+Ljava/util/concurrent/atomic/LongAdder;
+Ljava/util/concurrent/atomic/Striped64;
+Ljava/util/concurrent/locks/AbstractOwnableSynchronizer;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;
+Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/locks/Lock;
+Ljava/util/concurrent/locks/LockSupport;
+Ljava/util/concurrent/locks/ReadWriteLock;
+Ljava/util/concurrent/locks/ReentrantLock$FairSync;
+Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;
+Ljava/util/concurrent/locks/ReentrantLock$Sync;
+Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$ReadLock;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$HoldCounter;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$WriteLock;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock;
+Ljava/util/function/BiConsumer;
+Ljava/util/function/BiFunction$$ExternalSyntheticLambda0;
+Ljava/util/function/BiFunction;
+Ljava/util/function/BiPredicate;
+Ljava/util/function/BinaryOperator;
+Ljava/util/function/BooleanSupplier;
+Ljava/util/function/Consumer$$ExternalSyntheticLambda0;
+Ljava/util/function/Consumer;
+Ljava/util/function/DoubleBinaryOperator;
+Ljava/util/function/DoubleConsumer;
+Ljava/util/function/DoubleSupplier;
+Ljava/util/function/DoubleUnaryOperator$$ExternalSyntheticLambda0;
+Ljava/util/function/DoubleUnaryOperator$$ExternalSyntheticLambda2;
+Ljava/util/function/DoubleUnaryOperator;
+Ljava/util/function/Function$$ExternalSyntheticLambda2;
+Ljava/util/function/Function;
+Ljava/util/function/IntBinaryOperator;
+Ljava/util/function/IntConsumer;
+Ljava/util/function/IntFunction;
+Ljava/util/function/IntPredicate;
+Ljava/util/function/IntSupplier;
+Ljava/util/function/IntToDoubleFunction;
+Ljava/util/function/IntToLongFunction;
+Ljava/util/function/IntUnaryOperator;
+Ljava/util/function/LongBinaryOperator;
+Ljava/util/function/LongConsumer;
+Ljava/util/function/LongSupplier;
+Ljava/util/function/LongUnaryOperator;
+Ljava/util/function/Predicate;
+Ljava/util/function/Supplier;
+Ljava/util/function/ToDoubleBiFunction;
+Ljava/util/function/ToDoubleFunction;
+Ljava/util/function/ToIntBiFunction;
+Ljava/util/function/ToIntFunction;
+Ljava/util/function/ToLongBiFunction;
+Ljava/util/function/ToLongFunction;
+Ljava/util/function/UnaryOperator;
+Ljava/util/jar/Attributes$Name;
+Ljava/util/jar/Attributes;
+Ljava/util/jar/JarEntry;
+Ljava/util/jar/JarFile$JarEntryIterator;
+Ljava/util/jar/JarFile$JarFileEntry;
+Ljava/util/jar/JarFile;
+Ljava/util/jar/JarVerifier$3;
+Ljava/util/jar/JarVerifier$VerifierStream;
+Ljava/util/jar/JarVerifier;
+Ljava/util/jar/Manifest$FastInputStream;
+Ljava/util/jar/Manifest;
+Ljava/util/logging/ErrorManager;
+Ljava/util/logging/FileHandler$MeteredStream;
+Ljava/util/logging/Formatter;
+Ljava/util/logging/Handler;
+Ljava/util/logging/Level$KnownLevel;
+Ljava/util/logging/Level;
+Ljava/util/logging/LogManager$1;
+Ljava/util/logging/LogManager$2;
+Ljava/util/logging/LogManager$3;
+Ljava/util/logging/LogManager$5;
+Ljava/util/logging/LogManager$Cleaner;
+Ljava/util/logging/LogManager$LogNode;
+Ljava/util/logging/LogManager$LoggerContext$1;
+Ljava/util/logging/LogManager$LoggerContext;
+Ljava/util/logging/LogManager$LoggerWeakRef;
+Ljava/util/logging/LogManager$RootLogger;
+Ljava/util/logging/LogManager$SystemLoggerContext;
+Ljava/util/logging/LogManager;
+Ljava/util/logging/LogRecord;
+Ljava/util/logging/Logger$1;
+Ljava/util/logging/Logger$LoggerBundle;
+Ljava/util/logging/Logger$SystemLoggerHelper$1;
+Ljava/util/logging/Logger$SystemLoggerHelper;
+Ljava/util/logging/Logger;
+Ljava/util/logging/LoggingPermission;
+Ljava/util/logging/LoggingProxyImpl;
+Ljava/util/logging/StreamHandler;
+Ljava/util/prefs/AbstractPreferences;
+Ljava/util/prefs/BackingStoreException;
+Ljava/util/prefs/FileSystemPreferences$3;
+Ljava/util/prefs/FileSystemPreferences;
+Ljava/util/prefs/FileSystemPreferencesFactory;
+Ljava/util/prefs/Preferences;
+Ljava/util/prefs/PreferencesFactory;
+Ljava/util/regex/MatchResult;
+Ljava/util/regex/Matcher;
+Ljava/util/regex/Pattern;
+Ljava/util/regex/PatternSyntaxException;
+Ljava/util/stream/AbstractPipeline;
+Ljava/util/stream/AbstractSpinedBuffer;
+Ljava/util/stream/BaseStream;
+Ljava/util/stream/Collector$Characteristics;
+Ljava/util/stream/Collector;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda20;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda22;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda26;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda34;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda37;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda45;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda4;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda54;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda64;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda66;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda77;
+Ljava/util/stream/Collectors$$ExternalSyntheticLambda79;
+Ljava/util/stream/Collectors$CollectorImpl;
+Ljava/util/stream/Collectors;
+Ljava/util/stream/DistinctOps$1$2;
+Ljava/util/stream/DistinctOps$1;
+Ljava/util/stream/DistinctOps;
+Ljava/util/stream/DoublePipeline$$ExternalSyntheticLambda9;
+Ljava/util/stream/DoublePipeline$StatelessOp;
+Ljava/util/stream/DoublePipeline;
+Ljava/util/stream/DoubleStream;
+Ljava/util/stream/FindOps$$ExternalSyntheticLambda0;
+Ljava/util/stream/FindOps$$ExternalSyntheticLambda7;
+Ljava/util/stream/FindOps$FindOp;
+Ljava/util/stream/FindOps$FindSink$OfRef;
+Ljava/util/stream/FindOps$FindSink;
+Ljava/util/stream/FindOps;
+Ljava/util/stream/ForEachOps$ForEachOp$OfRef;
+Ljava/util/stream/ForEachOps$ForEachOp;
+Ljava/util/stream/ForEachOps;
+Ljava/util/stream/IntPipeline$$ExternalSyntheticLambda7;
+Ljava/util/stream/IntPipeline$$ExternalSyntheticLambda8;
+Ljava/util/stream/IntPipeline$4$1;
+Ljava/util/stream/IntPipeline$4;
+Ljava/util/stream/IntPipeline$Head;
+Ljava/util/stream/IntPipeline$StatelessOp;
+Ljava/util/stream/IntPipeline;
+Ljava/util/stream/IntStream;
+Ljava/util/stream/LongPipeline$$ExternalSyntheticLambda3;
+Ljava/util/stream/LongPipeline$StatelessOp;
+Ljava/util/stream/LongPipeline;
+Ljava/util/stream/LongStream;
+Ljava/util/stream/MatchOps$$ExternalSyntheticLambda1;
+Ljava/util/stream/MatchOps$1MatchSink;
+Ljava/util/stream/MatchOps$BooleanTerminalSink;
+Ljava/util/stream/MatchOps$MatchKind;
+Ljava/util/stream/MatchOps$MatchOp;
+Ljava/util/stream/MatchOps;
+Ljava/util/stream/Node$Builder$OfInt;
+Ljava/util/stream/Node$Builder;
+Ljava/util/stream/Node$OfDouble;
+Ljava/util/stream/Node$OfInt;
+Ljava/util/stream/Node$OfLong;
+Ljava/util/stream/Node$OfPrimitive;
+Ljava/util/stream/Node;
+Ljava/util/stream/Nodes$ArrayNode;
+Ljava/util/stream/Nodes$EmptyNode$OfDouble;
+Ljava/util/stream/Nodes$EmptyNode$OfInt;
+Ljava/util/stream/Nodes$EmptyNode$OfLong;
+Ljava/util/stream/Nodes$EmptyNode$OfRef;
+Ljava/util/stream/Nodes$EmptyNode;
+Ljava/util/stream/Nodes$FixedNodeBuilder;
+Ljava/util/stream/Nodes$IntArrayNode;
+Ljava/util/stream/Nodes$IntFixedNodeBuilder;
+Ljava/util/stream/Nodes$IntSpinedNodeBuilder;
+Ljava/util/stream/Nodes;
+Ljava/util/stream/PipelineHelper;
+Ljava/util/stream/ReduceOps$12;
+Ljava/util/stream/ReduceOps$12ReducingSink;
+Ljava/util/stream/ReduceOps$1;
+Ljava/util/stream/ReduceOps$1ReducingSink;
+Ljava/util/stream/ReduceOps$3;
+Ljava/util/stream/ReduceOps$3ReducingSink;
+Ljava/util/stream/ReduceOps$5;
+Ljava/util/stream/ReduceOps$5ReducingSink;
+Ljava/util/stream/ReduceOps$8;
+Ljava/util/stream/ReduceOps$8ReducingSink;
+Ljava/util/stream/ReduceOps$AccumulatingSink;
+Ljava/util/stream/ReduceOps$Box;
+Ljava/util/stream/ReduceOps$ReduceOp;
+Ljava/util/stream/ReduceOps;
+Ljava/util/stream/ReferencePipeline$2$1;
+Ljava/util/stream/ReferencePipeline$2;
+Ljava/util/stream/ReferencePipeline$3$1;
+Ljava/util/stream/ReferencePipeline$3;
+Ljava/util/stream/ReferencePipeline$4$1;
+Ljava/util/stream/ReferencePipeline$4;
+Ljava/util/stream/ReferencePipeline$5$1;
+Ljava/util/stream/ReferencePipeline$5;
+Ljava/util/stream/ReferencePipeline$6$1;
+Ljava/util/stream/ReferencePipeline$6;
+Ljava/util/stream/ReferencePipeline$Head;
+Ljava/util/stream/ReferencePipeline$StatefulOp;
+Ljava/util/stream/ReferencePipeline$StatelessOp;
+Ljava/util/stream/ReferencePipeline;
+Ljava/util/stream/Sink$ChainedInt;
+Ljava/util/stream/Sink$ChainedReference;
+Ljava/util/stream/Sink$OfDouble;
+Ljava/util/stream/Sink$OfInt;
+Ljava/util/stream/Sink$OfLong;
+Ljava/util/stream/Sink;
+Ljava/util/stream/SliceOps$1$1;
+Ljava/util/stream/SliceOps$1;
+Ljava/util/stream/SliceOps;
+Ljava/util/stream/SpinedBuffer$OfInt;
+Ljava/util/stream/SpinedBuffer$OfPrimitive;
+Ljava/util/stream/Stream;
+Ljava/util/stream/StreamOpFlag$MaskBuilder;
+Ljava/util/stream/StreamOpFlag$Type;
+Ljava/util/stream/StreamOpFlag;
+Ljava/util/stream/StreamShape;
+Ljava/util/stream/StreamSpliterators$InfiniteSupplyingSpliterator$OfRef;
+Ljava/util/stream/StreamSpliterators$InfiniteSupplyingSpliterator;
+Ljava/util/stream/StreamSupport;
+Ljava/util/stream/Streams$2;
+Ljava/util/stream/Streams$ConcatSpliterator$OfRef;
+Ljava/util/stream/Streams$ConcatSpliterator;
+Ljava/util/stream/Streams$RangeIntSpliterator;
+Ljava/util/stream/Streams;
+Ljava/util/stream/TerminalOp;
+Ljava/util/stream/TerminalSink;
+Ljava/util/zip/Adler32;
+Ljava/util/zip/CRC32;
+Ljava/util/zip/CheckedInputStream;
+Ljava/util/zip/Checksum;
+Ljava/util/zip/DataFormatException;
+Ljava/util/zip/Deflater;
+Ljava/util/zip/DeflaterOutputStream;
+Ljava/util/zip/GZIPInputStream$1;
+Ljava/util/zip/GZIPInputStream;
+Ljava/util/zip/GZIPOutputStream;
+Ljava/util/zip/Inflater;
+Ljava/util/zip/InflaterInputStream;
+Ljava/util/zip/ZStreamRef;
+Ljava/util/zip/ZipCoder;
+Ljava/util/zip/ZipConstants;
+Ljava/util/zip/ZipEntry;
+Ljava/util/zip/ZipError;
+Ljava/util/zip/ZipException;
+Ljava/util/zip/ZipFile$ZipEntryIterator;
+Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;
+Ljava/util/zip/ZipFile$ZipFileInputStream;
+Ljava/util/zip/ZipFile;
+Ljava/util/zip/ZipInputStream;
+Ljava/util/zip/ZipOutputStream;
+Ljava/util/zip/ZipUtils;
+Ljavax/crypto/AEADBadTagException;
+Ljavax/crypto/BadPaddingException;
+Ljavax/crypto/Cipher$1;
+Ljavax/crypto/Cipher$CipherSpiAndProvider;
+Ljavax/crypto/Cipher$InitParams;
+Ljavax/crypto/Cipher$InitType;
+Ljavax/crypto/Cipher$NeedToSet;
+Ljavax/crypto/Cipher$SpiAndProviderUpdater;
+Ljavax/crypto/Cipher$Transform;
+Ljavax/crypto/Cipher;
+Ljavax/crypto/CipherOutputStream;
+Ljavax/crypto/CipherSpi;
+Ljavax/crypto/IllegalBlockSizeException;
+Ljavax/crypto/JceSecurity;
+Ljavax/crypto/KeyAgreement;
+Ljavax/crypto/KeyAgreementSpi;
+Ljavax/crypto/KeyGenerator;
+Ljavax/crypto/KeyGeneratorSpi;
+Ljavax/crypto/Mac;
+Ljavax/crypto/MacSpi;
+Ljavax/crypto/NoSuchPaddingException;
+Ljavax/crypto/NullCipher;
+Ljavax/crypto/SecretKey;
+Ljavax/crypto/SecretKeyFactory;
+Ljavax/crypto/SecretKeyFactorySpi;
+Ljavax/crypto/ShortBufferException;
+Ljavax/crypto/interfaces/DHKey;
+Ljavax/crypto/interfaces/DHPrivateKey;
+Ljavax/crypto/interfaces/DHPublicKey;
+Ljavax/crypto/interfaces/PBEKey;
+Ljavax/crypto/spec/DESKeySpec;
+Ljavax/crypto/spec/DESedeKeySpec;
+Ljavax/crypto/spec/DHParameterSpec;
+Ljavax/crypto/spec/DHPrivateKeySpec;
+Ljavax/crypto/spec/DHPublicKeySpec;
+Ljavax/crypto/spec/GCMParameterSpec;
+Ljavax/crypto/spec/IvParameterSpec;
+Ljavax/crypto/spec/OAEPParameterSpec;
+Ljavax/crypto/spec/PBEKeySpec;
+Ljavax/crypto/spec/PBEParameterSpec;
+Ljavax/crypto/spec/PSource$PSpecified;
+Ljavax/crypto/spec/PSource;
+Ljavax/crypto/spec/SecretKeySpec;
+Ljavax/net/DefaultSocketFactory;
+Ljavax/net/ServerSocketFactory;
+Ljavax/net/SocketFactory;
+Ljavax/net/ssl/ExtendedSSLSession;
+Ljavax/net/ssl/HandshakeCompletedEvent;
+Ljavax/net/ssl/HandshakeCompletedListener;
+Ljavax/net/ssl/HostnameVerifier;
+Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder;
+Ljavax/net/ssl/HttpsURLConnection;
+Ljavax/net/ssl/KeyManager;
+Ljavax/net/ssl/KeyManagerFactory$1;
+Ljavax/net/ssl/KeyManagerFactory;
+Ljavax/net/ssl/KeyManagerFactorySpi;
+Ljavax/net/ssl/ManagerFactoryParameters;
+Ljavax/net/ssl/SNIHostName;
+Ljavax/net/ssl/SNIMatcher;
+Ljavax/net/ssl/SNIServerName;
+Ljavax/net/ssl/SSLContext;
+Ljavax/net/ssl/SSLContextSpi;
+Ljavax/net/ssl/SSLEngine;
+Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;
+Ljavax/net/ssl/SSLEngineResult$Status;
+Ljavax/net/ssl/SSLEngineResult;
+Ljavax/net/ssl/SSLException;
+Ljavax/net/ssl/SSLHandshakeException;
+Ljavax/net/ssl/SSLParameters;
+Ljavax/net/ssl/SSLPeerUnverifiedException;
+Ljavax/net/ssl/SSLProtocolException;
+Ljavax/net/ssl/SSLServerSocket;
+Ljavax/net/ssl/SSLServerSocketFactory;
+Ljavax/net/ssl/SSLSession;
+Ljavax/net/ssl/SSLSessionBindingEvent;
+Ljavax/net/ssl/SSLSessionBindingListener;
+Ljavax/net/ssl/SSLSessionContext;
+Ljavax/net/ssl/SSLSocket;
+Ljavax/net/ssl/SSLSocketFactory$1;
+Ljavax/net/ssl/SSLSocketFactory;
+Ljavax/net/ssl/TrustManager;
+Ljavax/net/ssl/TrustManagerFactory$1;
+Ljavax/net/ssl/TrustManagerFactory;
+Ljavax/net/ssl/TrustManagerFactorySpi;
+Ljavax/net/ssl/X509ExtendedKeyManager;
+Ljavax/net/ssl/X509ExtendedTrustManager;
+Ljavax/net/ssl/X509KeyManager;
+Ljavax/net/ssl/X509TrustManager;
+Ljavax/security/auth/Destroyable;
+Ljavax/security/auth/callback/UnsupportedCallbackException;
+Ljavax/security/auth/x500/X500Principal;
+Ljavax/security/cert/Certificate;
+Ljavax/security/cert/CertificateEncodingException;
+Ljavax/security/cert/CertificateException;
+Ljavax/security/cert/X509Certificate$1;
+Ljavax/security/cert/X509Certificate;
+Ljavax/xml/datatype/DatatypeConstants$Field;
+Ljavax/xml/datatype/DatatypeConstants;
+Ljavax/xml/datatype/Duration;
+Ljavax/xml/parsers/DocumentBuilder;
+Ljavax/xml/parsers/DocumentBuilderFactory;
+Ljavax/xml/parsers/ParserConfigurationException;
+Ljavax/xml/parsers/SAXParser;
+Ljavax/xml/parsers/SAXParserFactory;
+Ljdk/internal/util/Preconditions;
+Llibcore/content/type/MimeMap$$ExternalSyntheticLambda0;
+Llibcore/content/type/MimeMap$Builder;
+Llibcore/content/type/MimeMap$MemoizingSupplier;
+Llibcore/content/type/MimeMap;
+Llibcore/icu/CollationKeyICU;
+Llibcore/icu/DateIntervalFormat;
+Llibcore/icu/DateUtilsBridge;
+Llibcore/icu/ICU;
+Llibcore/icu/LocaleData;
+Llibcore/icu/TimeZoneNames$1;
+Llibcore/icu/TimeZoneNames$ZoneStringsCache;
+Llibcore/icu/TimeZoneNames;
+Llibcore/internal/StringPool;
+Llibcore/io/AsynchronousCloseMonitor;
+Llibcore/io/BlockGuardOs;
+Llibcore/io/BufferIterator;
+Llibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection$1;
+Llibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection;
+Llibcore/io/ClassPathURLStreamHandler;
+Llibcore/io/ForwardingOs;
+Llibcore/io/IoBridge;
+Llibcore/io/IoTracker$Mode;
+Llibcore/io/IoTracker;
+Llibcore/io/IoUtils$FileReader;
+Llibcore/io/IoUtils;
+Llibcore/io/Libcore;
+Llibcore/io/Linux;
+Llibcore/io/Memory;
+Llibcore/io/MemoryMappedFile;
+Llibcore/io/NioBufferIterator;
+Llibcore/io/Os;
+Llibcore/io/Streams;
+Llibcore/math/MathUtils;
+Llibcore/math/NativeBN;
+Llibcore/net/InetAddressUtils;
+Llibcore/net/NetworkSecurityPolicy$DefaultNetworkSecurityPolicy;
+Llibcore/net/NetworkSecurityPolicy;
+Llibcore/net/event/NetworkEventDispatcher;
+Llibcore/net/event/NetworkEventListener;
+Llibcore/net/http/Dns;
+Llibcore/net/http/HttpDate$1;
+Llibcore/net/http/HttpDate;
+Llibcore/net/http/HttpURLConnectionFactory;
+Llibcore/reflect/AnnotatedElements;
+Llibcore/reflect/AnnotationFactory;
+Llibcore/reflect/AnnotationMember$DefaultValues;
+Llibcore/reflect/AnnotationMember;
+Llibcore/reflect/GenericArrayTypeImpl;
+Llibcore/reflect/GenericSignatureParser;
+Llibcore/reflect/ListOfTypes;
+Llibcore/reflect/ListOfVariables;
+Llibcore/reflect/ParameterizedTypeImpl;
+Llibcore/reflect/TypeVariableImpl;
+Llibcore/reflect/Types;
+Llibcore/reflect/WildcardTypeImpl;
+Llibcore/util/ArrayUtils;
+Llibcore/util/BasicLruCache;
+Llibcore/util/CharsetUtils;
+Llibcore/util/CollectionUtils;
+Llibcore/util/EmptyArray;
+Llibcore/util/FP16;
+Llibcore/util/HexEncoding;
+Llibcore/util/NativeAllocationRegistry$CleanerRunner;
+Llibcore/util/NativeAllocationRegistry$CleanerThunk;
+Llibcore/util/NativeAllocationRegistry;
+Llibcore/util/Objects;
+Llibcore/util/SneakyThrow;
+Llibcore/util/XmlObjectFactory;
+Llibcore/util/ZoneInfo;
+Lorg/apache/harmony/dalvik/ddmc/Chunk;
+Lorg/apache/harmony/dalvik/ddmc/ChunkHandler;
+Lorg/apache/harmony/dalvik/ddmc/DdmServer;
+Lorg/apache/harmony/dalvik/ddmc/DdmVmInternal;
+Lorg/apache/harmony/xml/ExpatAttributes;
+Lorg/apache/harmony/xml/ExpatException;
+Lorg/apache/harmony/xml/ExpatParser$CurrentAttributes;
+Lorg/apache/harmony/xml/ExpatParser$ExpatLocator;
+Lorg/apache/harmony/xml/ExpatParser;
+Lorg/apache/harmony/xml/ExpatReader;
+Lorg/apache/harmony/xml/dom/CharacterDataImpl;
+Lorg/apache/harmony/xml/dom/DocumentImpl;
+Lorg/apache/harmony/xml/dom/ElementImpl;
+Lorg/apache/harmony/xml/dom/InnerNodeImpl;
+Lorg/apache/harmony/xml/dom/LeafNodeImpl;
+Lorg/apache/harmony/xml/dom/NodeImpl$1;
+Lorg/apache/harmony/xml/dom/NodeImpl;
+Lorg/apache/harmony/xml/dom/NodeListImpl;
+Lorg/apache/harmony/xml/dom/TextImpl;
+Lorg/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl;
+Lorg/apache/harmony/xml/parsers/SAXParserFactoryImpl;
+Lorg/apache/harmony/xml/parsers/SAXParserImpl;
+Lorg/json/JSON;
+Lorg/json/JSONArray;
+Lorg/json/JSONException;
+Lorg/json/JSONObject$1;
+Lorg/json/JSONObject;
+Lorg/json/JSONStringer$Scope;
+Lorg/json/JSONStringer;
+Lorg/json/JSONTokener;
+Lorg/w3c/dom/CharacterData;
+Lorg/w3c/dom/DOMImplementation;
+Lorg/w3c/dom/Document;
+Lorg/w3c/dom/Element;
+Lorg/w3c/dom/Node;
+Lorg/w3c/dom/NodeList;
+Lorg/w3c/dom/Text;
+Lorg/w3c/dom/TypeInfo;
+Lorg/xml/sax/AttributeList;
+Lorg/xml/sax/Attributes;
+Lorg/xml/sax/ContentHandler;
+Lorg/xml/sax/DTDHandler;
+Lorg/xml/sax/DocumentHandler;
+Lorg/xml/sax/EntityResolver;
+Lorg/xml/sax/ErrorHandler;
+Lorg/xml/sax/InputSource;
+Lorg/xml/sax/Locator;
+Lorg/xml/sax/Parser;
+Lorg/xml/sax/SAXException;
+Lorg/xml/sax/SAXNotRecognizedException;
+Lorg/xml/sax/SAXNotSupportedException;
+Lorg/xml/sax/XMLFilter;
+Lorg/xml/sax/XMLReader;
+Lorg/xml/sax/ext/DeclHandler;
+Lorg/xml/sax/ext/DefaultHandler2;
+Lorg/xml/sax/ext/EntityResolver2;
+Lorg/xml/sax/ext/LexicalHandler;
+Lorg/xml/sax/helpers/AttributesImpl;
+Lorg/xml/sax/helpers/DefaultHandler;
+Lorg/xml/sax/helpers/NamespaceSupport;
+Lorg/xml/sax/helpers/XMLFilterImpl;
+Lorg/xmlpull/v1/XmlPullParser;
+Lorg/xmlpull/v1/XmlPullParserException;
+Lorg/xmlpull/v1/XmlPullParserFactory;
+Lorg/xmlpull/v1/XmlSerializer;
+Lsun/invoke/util/BytecodeDescriptor;
+Lsun/invoke/util/VerifyAccess;
+Lsun/invoke/util/Wrapper$Format;
+Lsun/invoke/util/Wrapper;
+Lsun/misc/ASCIICaseInsensitiveComparator;
+Lsun/misc/Cleaner$1;
+Lsun/misc/Cleaner;
+Lsun/misc/CompoundEnumeration;
+Lsun/misc/FDBigInteger;
+Lsun/misc/FloatingDecimal$1;
+Lsun/misc/FloatingDecimal$ASCIIToBinaryBuffer;
+Lsun/misc/FloatingDecimal$ASCIIToBinaryConverter;
+Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;
+Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;
+Lsun/misc/FloatingDecimal$ExceptionalBinaryToASCIIBuffer;
+Lsun/misc/FloatingDecimal$PreparedASCIIToBinaryBuffer;
+Lsun/misc/FloatingDecimal;
+Lsun/misc/FormattedFloatingDecimal$1;
+Lsun/misc/FormattedFloatingDecimal$2;
+Lsun/misc/FormattedFloatingDecimal$Form;
+Lsun/misc/FormattedFloatingDecimal;
+Lsun/misc/IOUtils;
+Lsun/misc/JavaIOFileDescriptorAccess;
+Lsun/misc/LRUCache;
+Lsun/misc/SharedSecrets;
+Lsun/misc/Unsafe;
+Lsun/misc/VM;
+Lsun/misc/Version;
+Lsun/net/ConnectionResetException;
+Lsun/net/NetHooks;
+Lsun/net/NetProperties$1;
+Lsun/net/NetProperties;
+Lsun/net/ResourceManager;
+Lsun/net/spi/DefaultProxySelector$1;
+Lsun/net/spi/DefaultProxySelector$NonProxyInfo;
+Lsun/net/spi/DefaultProxySelector;
+Lsun/net/spi/nameservice/NameService;
+Lsun/net/util/IPAddressUtil;
+Lsun/net/www/ParseUtil;
+Lsun/net/www/protocol/file/Handler;
+Lsun/net/www/protocol/jar/Handler;
+Lsun/nio/ch/AbstractPollArrayWrapper;
+Lsun/nio/ch/AbstractPollSelectorImpl;
+Lsun/nio/ch/AllocatedNativeObject;
+Lsun/nio/ch/ChannelInputStream;
+Lsun/nio/ch/DatagramChannelImpl;
+Lsun/nio/ch/DatagramDispatcher;
+Lsun/nio/ch/DefaultSelectorProvider;
+Lsun/nio/ch/DirectBuffer;
+Lsun/nio/ch/FileChannelImpl$Unmapper;
+Lsun/nio/ch/FileChannelImpl;
+Lsun/nio/ch/FileDescriptorHolderSocketImpl;
+Lsun/nio/ch/FileDispatcher;
+Lsun/nio/ch/FileDispatcherImpl;
+Lsun/nio/ch/FileKey;
+Lsun/nio/ch/FileLockImpl;
+Lsun/nio/ch/FileLockTable;
+Lsun/nio/ch/IOStatus;
+Lsun/nio/ch/IOUtil;
+Lsun/nio/ch/Interruptible;
+Lsun/nio/ch/NativeDispatcher;
+Lsun/nio/ch/NativeObject;
+Lsun/nio/ch/NativeThread;
+Lsun/nio/ch/NativeThreadSet;
+Lsun/nio/ch/Net$1;
+Lsun/nio/ch/Net$3;
+Lsun/nio/ch/Net;
+Lsun/nio/ch/PollArrayWrapper;
+Lsun/nio/ch/PollSelectorImpl;
+Lsun/nio/ch/PollSelectorProvider;
+Lsun/nio/ch/SelChImpl;
+Lsun/nio/ch/SelectionKeyImpl;
+Lsun/nio/ch/SelectorImpl;
+Lsun/nio/ch/SelectorProviderImpl;
+Lsun/nio/ch/ServerSocketChannelImpl;
+Lsun/nio/ch/SharedFileLockTable$FileLockReference;
+Lsun/nio/ch/SharedFileLockTable;
+Lsun/nio/ch/SocketAdaptor$1;
+Lsun/nio/ch/SocketAdaptor$2;
+Lsun/nio/ch/SocketAdaptor$SocketInputStream;
+Lsun/nio/ch/SocketAdaptor;
+Lsun/nio/ch/SocketChannelImpl;
+Lsun/nio/ch/SocketDispatcher;
+Lsun/nio/ch/Util$1;
+Lsun/nio/ch/Util$2;
+Lsun/nio/ch/Util$3;
+Lsun/nio/ch/Util$BufferCache;
+Lsun/nio/ch/Util;
+Lsun/nio/cs/ArrayDecoder;
+Lsun/nio/cs/ArrayEncoder;
+Lsun/nio/cs/StreamDecoder;
+Lsun/nio/cs/StreamEncoder;
+Lsun/nio/cs/ThreadLocalCoders$1;
+Lsun/nio/cs/ThreadLocalCoders$2;
+Lsun/nio/cs/ThreadLocalCoders$Cache;
+Lsun/nio/cs/ThreadLocalCoders;
+Lsun/nio/fs/AbstractBasicFileAttributeView;
+Lsun/nio/fs/AbstractFileSystemProvider;
+Lsun/nio/fs/AbstractPath;
+Lsun/nio/fs/DefaultFileSystemProvider;
+Lsun/nio/fs/DynamicFileAttributeView;
+Lsun/nio/fs/LinuxFileSystem;
+Lsun/nio/fs/LinuxFileSystemProvider;
+Lsun/nio/fs/NativeBuffer$Deallocator;
+Lsun/nio/fs/NativeBuffer;
+Lsun/nio/fs/NativeBuffers;
+Lsun/nio/fs/UnixChannelFactory$Flags;
+Lsun/nio/fs/UnixChannelFactory;
+Lsun/nio/fs/UnixConstants;
+Lsun/nio/fs/UnixException;
+Lsun/nio/fs/UnixFileAttributeViews$Basic;
+Lsun/nio/fs/UnixFileAttributeViews;
+Lsun/nio/fs/UnixFileAttributes$UnixAsBasicFileAttributes;
+Lsun/nio/fs/UnixFileAttributes;
+Lsun/nio/fs/UnixFileModeAttribute;
+Lsun/nio/fs/UnixFileStoreAttributes;
+Lsun/nio/fs/UnixFileSystem;
+Lsun/nio/fs/UnixFileSystemProvider;
+Lsun/nio/fs/UnixMountEntry;
+Lsun/nio/fs/UnixNativeDispatcher;
+Lsun/nio/fs/UnixPath;
+Lsun/nio/fs/Util;
+Lsun/reflect/Reflection;
+Lsun/reflect/misc/ReflectUtil;
+Lsun/security/action/GetBooleanAction;
+Lsun/security/action/GetIntegerAction;
+Lsun/security/action/GetPropertyAction;
+Lsun/security/jca/GetInstance$Instance;
+Lsun/security/jca/GetInstance;
+Lsun/security/jca/JCAUtil$CachedSecureRandomHolder;
+Lsun/security/jca/JCAUtil;
+Lsun/security/jca/ProviderConfig$2;
+Lsun/security/jca/ProviderConfig;
+Lsun/security/jca/ProviderList$1;
+Lsun/security/jca/ProviderList$2;
+Lsun/security/jca/ProviderList$3;
+Lsun/security/jca/ProviderList$ServiceList$1;
+Lsun/security/jca/ProviderList$ServiceList;
+Lsun/security/jca/ProviderList;
+Lsun/security/jca/Providers;
+Lsun/security/jca/ServiceId;
+Lsun/security/pkcs/ContentInfo;
+Lsun/security/pkcs/PKCS7$VerbatimX509Certificate;
+Lsun/security/pkcs/PKCS7$WrappedX509Certificate;
+Lsun/security/pkcs/PKCS7;
+Lsun/security/pkcs/PKCS9Attribute;
+Lsun/security/pkcs/SignerInfo;
+Lsun/security/provider/CertPathProvider;
+Lsun/security/provider/X509Factory;
+Lsun/security/provider/certpath/AdaptableX509CertSelector;
+Lsun/security/provider/certpath/AlgorithmChecker;
+Lsun/security/provider/certpath/BasicChecker;
+Lsun/security/provider/certpath/CertId;
+Lsun/security/provider/certpath/CertPathHelper;
+Lsun/security/provider/certpath/ConstraintsChecker;
+Lsun/security/provider/certpath/KeyChecker;
+Lsun/security/provider/certpath/OCSP$RevocationStatus$CertStatus;
+Lsun/security/provider/certpath/OCSP$RevocationStatus;
+Lsun/security/provider/certpath/OCSPResponse$1;
+Lsun/security/provider/certpath/OCSPResponse$ResponseStatus;
+Lsun/security/provider/certpath/OCSPResponse$SingleResponse;
+Lsun/security/provider/certpath/OCSPResponse;
+Lsun/security/provider/certpath/PKIX$ValidatorParams;
+Lsun/security/provider/certpath/PKIX;
+Lsun/security/provider/certpath/PKIXCertPathValidator;
+Lsun/security/provider/certpath/PKIXMasterCertPathValidator;
+Lsun/security/provider/certpath/PolicyChecker;
+Lsun/security/provider/certpath/PolicyNodeImpl;
+Lsun/security/provider/certpath/RevocationChecker$1;
+Lsun/security/provider/certpath/RevocationChecker$2;
+Lsun/security/provider/certpath/RevocationChecker$Mode;
+Lsun/security/provider/certpath/RevocationChecker$RevocationProperties;
+Lsun/security/provider/certpath/RevocationChecker;
+Lsun/security/util/AbstractAlgorithmConstraints$1;
+Lsun/security/util/AbstractAlgorithmConstraints;
+Lsun/security/util/AlgorithmDecomposer;
+Lsun/security/util/BitArray;
+Lsun/security/util/ByteArrayLexOrder;
+Lsun/security/util/ByteArrayTagOrder;
+Lsun/security/util/Cache$EqualByteArray;
+Lsun/security/util/Cache;
+Lsun/security/util/CertConstraintParameters;
+Lsun/security/util/Debug;
+Lsun/security/util/DerEncoder;
+Lsun/security/util/DerIndefLenConverter;
+Lsun/security/util/DerInputBuffer;
+Lsun/security/util/DerInputStream;
+Lsun/security/util/DerOutputStream;
+Lsun/security/util/DerValue;
+Lsun/security/util/DisabledAlgorithmConstraints$1;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraints;
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;
+Lsun/security/util/DisabledAlgorithmConstraints;
+Lsun/security/util/KeyUtil;
+Lsun/security/util/Length;
+Lsun/security/util/ManifestDigester$Entry;
+Lsun/security/util/ManifestDigester$Position;
+Lsun/security/util/ManifestDigester;
+Lsun/security/util/ManifestEntryVerifier$SunProviderHolder;
+Lsun/security/util/ManifestEntryVerifier;
+Lsun/security/util/MemoryCache$CacheEntry;
+Lsun/security/util/MemoryCache$SoftCacheEntry;
+Lsun/security/util/MemoryCache;
+Lsun/security/util/ObjectIdentifier;
+Lsun/security/util/SecurityConstants;
+Lsun/security/util/SignatureFileVerifier;
+Lsun/security/x509/AVA;
+Lsun/security/x509/AVAKeyword;
+Lsun/security/x509/AccessDescription;
+Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/AuthorityInfoAccessExtension;
+Lsun/security/x509/AuthorityKeyIdentifierExtension;
+Lsun/security/x509/BasicConstraintsExtension;
+Lsun/security/x509/CRLDistributionPointsExtension;
+Lsun/security/x509/CRLNumberExtension;
+Lsun/security/x509/CRLReasonCodeExtension;
+Lsun/security/x509/CertAttrSet;
+Lsun/security/x509/CertificateAlgorithmId;
+Lsun/security/x509/CertificateExtensions;
+Lsun/security/x509/CertificateIssuerExtension;
+Lsun/security/x509/CertificatePoliciesExtension;
+Lsun/security/x509/CertificatePolicyId;
+Lsun/security/x509/CertificateSerialNumber;
+Lsun/security/x509/CertificateValidity;
+Lsun/security/x509/CertificateVersion;
+Lsun/security/x509/CertificateX509Key;
+Lsun/security/x509/DNSName;
+Lsun/security/x509/DeltaCRLIndicatorExtension;
+Lsun/security/x509/DistributionPoint;
+Lsun/security/x509/ExtendedKeyUsageExtension;
+Lsun/security/x509/Extension;
+Lsun/security/x509/FreshestCRLExtension;
+Lsun/security/x509/GeneralName;
+Lsun/security/x509/GeneralNameInterface;
+Lsun/security/x509/GeneralNames;
+Lsun/security/x509/InhibitAnyPolicyExtension;
+Lsun/security/x509/IssuerAlternativeNameExtension;
+Lsun/security/x509/IssuingDistributionPointExtension;
+Lsun/security/x509/KeyIdentifier;
+Lsun/security/x509/KeyUsageExtension;
+Lsun/security/x509/NameConstraintsExtension;
+Lsun/security/x509/NetscapeCertTypeExtension$MapEntry;
+Lsun/security/x509/NetscapeCertTypeExtension;
+Lsun/security/x509/OCSPNoCheckExtension;
+Lsun/security/x509/OIDMap$OIDInfo;
+Lsun/security/x509/OIDMap;
+Lsun/security/x509/PKIXExtensions;
+Lsun/security/x509/PolicyConstraintsExtension;
+Lsun/security/x509/PolicyInformation;
+Lsun/security/x509/PolicyMappingsExtension;
+Lsun/security/x509/PrivateKeyUsageExtension;
+Lsun/security/x509/RDN;
+Lsun/security/x509/SerialNumber;
+Lsun/security/x509/SubjectAlternativeNameExtension;
+Lsun/security/x509/SubjectInfoAccessExtension;
+Lsun/security/x509/SubjectKeyIdentifierExtension;
+Lsun/security/x509/URIName;
+Lsun/security/x509/X500Name$1;
+Lsun/security/x509/X500Name;
+Lsun/security/x509/X509AttributeName;
+Lsun/security/x509/X509CertImpl;
+Lsun/security/x509/X509CertInfo;
+Lsun/security/x509/X509Key;
+Lsun/util/calendar/AbstractCalendar;
+Lsun/util/calendar/BaseCalendar$Date;
+Lsun/util/calendar/BaseCalendar;
+Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarSystem;
+Lsun/util/calendar/CalendarUtils;
+Lsun/util/calendar/Era;
+Lsun/util/calendar/Gregorian$Date;
+Lsun/util/calendar/Gregorian;
+Lsun/util/calendar/ImmutableGregorianDate;
+Lsun/util/calendar/JulianCalendar;
+Lsun/util/calendar/LocalGregorianCalendar;
+Lsun/util/locale/BaseLocale$Cache;
+Lsun/util/locale/BaseLocale$Key;
+Lsun/util/locale/BaseLocale;
+Lsun/util/locale/Extension;
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveChar;
+Lsun/util/locale/InternalLocaleBuilder;
+Lsun/util/locale/LanguageTag;
+Lsun/util/locale/LocaleExtensions;
+Lsun/util/locale/LocaleMatcher;
+Lsun/util/locale/LocaleObjectCache$CacheEntry;
+Lsun/util/locale/LocaleObjectCache;
+Lsun/util/locale/LocaleSyntaxException;
+Lsun/util/locale/LocaleUtils;
+Lsun/util/locale/ParseStatus;
+Lsun/util/locale/StringTokenIterator;
+Lsun/util/locale/UnicodeLocaleExtension;
+Lsun/util/logging/LoggingProxy;
+Lsun/util/logging/LoggingSupport$1;
+Lsun/util/logging/LoggingSupport;
+Lsun/util/logging/PlatformLogger$1;
+Lsun/util/logging/PlatformLogger$JavaLoggerProxy;
+Lsun/util/logging/PlatformLogger$Level;
+Lsun/util/logging/PlatformLogger$LoggerProxy;
+Lsun/util/logging/PlatformLogger;
+[B
+[C
+[D
+[F
+[I
+[J
+[Landroid/system/StructCapUserData;
+[Landroid/system/StructPollfd;
+[Lcom/android/okhttp/CipherSuite;
+[Lcom/android/okhttp/ConnectionSpec;
+[Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+[Lcom/android/okhttp/Protocol;
+[Lcom/android/okhttp/TlsVersion;
+[Lcom/android/org/bouncycastle/asn1/ASN1Encodable;
+[Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
+[Lcom/android/org/bouncycastle/crypto/params/DHParameters;
+[Lcom/android/org/bouncycastle/crypto/params/DSAParameters;
+[Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil$Boundaries;
+[Lcom/android/org/kxml2/io/KXmlParser$ValueContext;
+[Ldalvik/system/DexPathList$Element;
+[Ldalvik/system/DexPathList$NativeLibraryElement;
+[Ljava/io/File$PathStatus;
+[Ljava/io/File;
+[Ljava/io/FileDescriptor;
+[Ljava/io/IOException;
+[Ljava/io/ObjectInputStream$HandleTable$HandleList;
+[Ljava/io/ObjectStreamField;
+[Ljava/lang/Byte;
+[Ljava/lang/CharSequence;
+[Ljava/lang/Character$UnicodeBlock;
+[Ljava/lang/Character;
+[Ljava/lang/Class;
+[Ljava/lang/ClassLoader;
+[Ljava/lang/Comparable;
+[Ljava/lang/Daemons$Daemon;
+[Ljava/lang/Enum;
+[Ljava/lang/Float;
+[Ljava/lang/Integer;
+[Ljava/lang/Long;
+[Ljava/lang/Object;
+[Ljava/lang/Package;
+[Ljava/lang/Runnable;
+[Ljava/lang/Short;
+[Ljava/lang/StackTraceElement;
+[Ljava/lang/String;
+[Ljava/lang/Thread$State;
+[Ljava/lang/Thread;
+[Ljava/lang/ThreadGroup;
+[Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+[Ljava/lang/Throwable;
+[Ljava/lang/annotation/Annotation;
+[Ljava/lang/invoke/MethodHandle;
+[Ljava/lang/invoke/MethodType;
+[Ljava/lang/invoke/VarHandle$AccessMode;
+[Ljava/lang/invoke/VarHandle$AccessType;
+[Ljava/lang/ref/WeakReference;
+[Ljava/lang/reflect/AccessibleObject;
+[Ljava/lang/reflect/Constructor;
+[Ljava/lang/reflect/Field;
+[Ljava/lang/reflect/Method;
+[Ljava/lang/reflect/Parameter;
+[Ljava/lang/reflect/Type;
+[Ljava/lang/reflect/TypeVariable;
+[Ljava/math/BigDecimal;
+[Ljava/math/BigInteger;
+[Ljava/math/MathContext;
+[Ljava/math/RoundingMode;
+[Ljava/net/Authenticator$RequestorType;
+[Ljava/net/InetAddress;
+[Ljava/net/Proxy$Type;
+[Ljava/net/StandardProtocolFamily;
+[Ljava/nio/ByteBuffer;
+[Ljava/nio/file/AccessMode;
+[Ljava/nio/file/LinkOption;
+[Ljava/nio/file/StandardCopyOption;
+[Ljava/nio/file/StandardOpenOption;
+[Ljava/nio/file/attribute/FileAttribute;
+[Ljava/security/CryptoPrimitive;
+[Ljava/security/Principal;
+[Ljava/security/Provider;
+[Ljava/security/cert/CRLReason;
+[Ljava/security/cert/Certificate;
+[Ljava/security/cert/PKIXRevocationChecker$Option;
+[Ljava/security/cert/X509Certificate;
+[Ljava/text/DateFormat$Field;
+[Ljava/text/DateFormat;
+[Ljava/text/Normalizer$Form;
+[Ljava/time/DayOfWeek;
+[Ljava/time/LocalDateTime;
+[Ljava/time/LocalTime;
+[Ljava/time/Month;
+[Ljava/time/ZoneOffset;
+[Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;
+[Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;
+[Ljava/time/format/ResolverStyle;
+[Ljava/time/format/SignStyle;
+[Ljava/time/format/TextStyle;
+[Ljava/time/temporal/ChronoField;
+[Ljava/time/temporal/ChronoUnit;
+[Ljava/time/temporal/IsoFields$Field;
+[Ljava/time/temporal/IsoFields$Unit;
+[Ljava/time/temporal/JulianFields$Field;
+[Ljava/time/temporal/TemporalUnit;
+[Ljava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;
+[Ljava/time/zone/ZoneOffsetTransitionRule;
+[Ljava/util/ArrayList;
+[Ljava/util/Comparators$NaturalOrderComparator;
+[Ljava/util/Enumeration;
+[Ljava/util/Formatter$Flags;
+[Ljava/util/Formatter$FormatString;
+[Ljava/util/HashMap$Node;
+[Ljava/util/HashMap;
+[Ljava/util/Hashtable$HashtableEntry;
+[Ljava/util/List;
+[Ljava/util/Locale$Category;
+[Ljava/util/Locale$FilteringMode;
+[Ljava/util/Locale;
+[Ljava/util/Map$Entry;
+[Ljava/util/WeakHashMap$Entry;
+[Ljava/util/concurrent/ConcurrentHashMap$CounterCell;
+[Ljava/util/concurrent/ConcurrentHashMap$Node;
+[Ljava/util/concurrent/ConcurrentHashMap$Segment;
+[Ljava/util/concurrent/ForkJoinTask$ExceptionNode;
+[Ljava/util/concurrent/ForkJoinTask;
+[Ljava/util/concurrent/RunnableScheduledFuture;
+[Ljava/util/concurrent/TimeUnit;
+[Ljava/util/logging/Handler;
+[Ljava/util/prefs/AbstractPreferences;
+[Ljava/util/regex/Pattern;
+[Ljava/util/stream/Collector$Characteristics;
+[Ljava/util/stream/MatchOps$MatchKind;
+[Ljava/util/stream/StreamOpFlag$Type;
+[Ljava/util/stream/StreamOpFlag;
+[Ljava/util/stream/StreamShape;
+[Ljavax/crypto/Cipher$InitType;
+[Ljavax/crypto/Cipher$NeedToSet;
+[Ljavax/net/ssl/KeyManager;
+[Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;
+[Ljavax/net/ssl/SSLEngineResult$Status;
+[Ljavax/net/ssl/TrustManager;
+[Ljavax/security/auth/x500/X500Principal;
+[Ljavax/security/cert/X509Certificate;
+[Llibcore/io/ClassPathURLStreamHandler;
+[Llibcore/io/IoTracker$Mode;
+[Llibcore/reflect/AnnotationMember$DefaultValues;
+[Llibcore/reflect/AnnotationMember;
+[Lorg/json/JSONStringer$Scope;
+[Lsun/invoke/util/Wrapper;
+[Lsun/misc/FDBigInteger;
+[Lsun/misc/FormattedFloatingDecimal$Form;
+[Lsun/security/jca/ProviderConfig;
+[Lsun/security/jca/ServiceId;
+[Lsun/security/pkcs/SignerInfo;
+[Lsun/security/provider/certpath/OCSP$RevocationStatus$CertStatus;
+[Lsun/security/provider/certpath/OCSPResponse$ResponseStatus;
+[Lsun/security/provider/certpath/RevocationChecker$Mode;
+[Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+[Lsun/security/util/ObjectIdentifier;
+[Lsun/security/x509/AVA;
+[Lsun/security/x509/NetscapeCertTypeExtension$MapEntry;
+[Lsun/security/x509/RDN;
+[Lsun/util/calendar/Era;
+[Lsun/util/logging/PlatformLogger$Level;
+[S
+[Z
+[[B
+[[C
+[[F
+[[I
+[[J
+[[Ljava/lang/Byte;
+[[Ljava/lang/Class;
+[[Ljava/lang/Long;
+[[Ljava/lang/Object;
+[[Ljava/lang/String;
+[[Ljava/lang/annotation/Annotation;
+[[Ljava/math/BigInteger;
+[[S
+[[[B
+[[[I
diff --git a/build/boot/hiddenapi/OWNERS b/build/boot/hiddenapi/OWNERS
new file mode 100644
index 0000000..ac8a2b6
--- /dev/null
+++ b/build/boot/hiddenapi/OWNERS
@@ -0,0 +1,5 @@
+# soong-team@ as the hiddenapi files are tightly coupled with Soong
+file:platform/build/soong:/OWNERS
+
+# compat-team@ for changes to hiddenapi files
+file:tools/platform-compat:/OWNERS
diff --git a/build/boot/hiddenapi/hiddenapi-blocked.txt b/build/boot/hiddenapi/hiddenapi-blocked.txt
new file mode 100644
index 0000000..b328f2a
--- /dev/null
+++ b/build/boot/hiddenapi/hiddenapi-blocked.txt
@@ -0,0 +1,40 @@
+Ldalvik/system/VMRuntime;->setHiddenApiExemptions([Ljava/lang/String;)V
+Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V
+Ldalvik/system/VMRuntime;->setTargetSdkVersionNative(I)V
+Ljava/lang/invoke/MethodHandles$Lookup;->IMPL_LOOKUP:Ljava/lang/invoke/MethodHandles$Lookup;
+Ljava/lang/invoke/VarHandle;->acquireFence()V
+Ljava/lang/invoke/VarHandle;->compareAndExchange([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->compareAndExchangeAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->compareAndExchangeRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->compareAndSet([Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->fullFence()V
+Ljava/lang/invoke/VarHandle;->get([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndAdd([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndAddAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndAddRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseAnd([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseAndAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseAndRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseOr([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseOrAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseOrRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseXor([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseXorAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseXorRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndSet([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndSetAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndSetRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getOpaque([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getVolatile([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->loadLoadFence()V
+Ljava/lang/invoke/VarHandle;->releaseFence()V
+Ljava/lang/invoke/VarHandle;->set([Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->setOpaque([Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->setRelease([Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->setVolatile([Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->storeStoreFence()V
+Ljava/lang/invoke/VarHandle;->weakCompareAndSet([Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSetAcquire([Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSetPlain([Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSetRelease([Ljava/lang/Object;)Z
diff --git a/build/boot/hiddenapi/hiddenapi-max-target-o-low-priority.txt b/build/boot/hiddenapi/hiddenapi-max-target-o-low-priority.txt
new file mode 100644
index 0000000..f7b21a5
--- /dev/null
+++ b/build/boot/hiddenapi/hiddenapi-max-target-o-low-priority.txt
@@ -0,0 +1,11747 @@
+Landroid/system/ErrnoException;->functionName:Ljava/lang/String;
+Landroid/system/ErrnoException;->rethrowAsIOException()Ljava/io/IOException;
+Landroid/system/ErrnoException;->rethrowAsSocketException()Ljava/net/SocketException;
+Landroid/system/GaiException;-><init>(Ljava/lang/String;I)V
+Landroid/system/GaiException;-><init>(Ljava/lang/String;ILjava/lang/Throwable;)V
+Landroid/system/GaiException;->error:I
+Landroid/system/GaiException;->functionName:Ljava/lang/String;
+Landroid/system/GaiException;->rethrowAsUnknownHostException()Ljava/net/UnknownHostException;
+Landroid/system/GaiException;->rethrowAsUnknownHostException(Ljava/lang/String;)Ljava/net/UnknownHostException;
+Landroid/system/Int32Ref;-><init>(I)V
+Landroid/system/NetlinkSocketAddress;-><init>()V
+Landroid/system/NetlinkSocketAddress;-><init>(I)V
+Landroid/system/NetlinkSocketAddress;->getGroupsMask()I
+Landroid/system/NetlinkSocketAddress;->getPortId()I
+Landroid/system/NetlinkSocketAddress;->nlGroupsMask:I
+Landroid/system/NetlinkSocketAddress;->nlPortId:I
+Landroid/system/Os;-><init>()V
+Landroid/system/Os;->accept(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)Ljava/io/FileDescriptor;
+Landroid/system/Os;->android_getaddrinfo(Ljava/lang/String;Landroid/system/StructAddrinfo;I)[Ljava/net/InetAddress;
+Landroid/system/Os;->capget(Landroid/system/StructCapUserHeader;)[Landroid/system/StructCapUserData;
+Landroid/system/Os;->capset(Landroid/system/StructCapUserHeader;[Landroid/system/StructCapUserData;)V
+Landroid/system/Os;->fcntlFlock(Ljava/io/FileDescriptor;ILandroid/system/StructFlock;)I
+Landroid/system/Os;->fcntlInt(Ljava/io/FileDescriptor;II)I
+Landroid/system/Os;->fcntlVoid(Ljava/io/FileDescriptor;I)I
+Landroid/system/Os;->getifaddrs()[Landroid/system/StructIfaddrs;
+Landroid/system/Os;->getnameinfo(Ljava/net/InetAddress;I)Ljava/lang/String;
+Landroid/system/Os;->getpgid(I)I
+Landroid/system/Os;->getpwnam(Ljava/lang/String;)Landroid/system/StructPasswd;
+Landroid/system/Os;->getpwuid(I)Landroid/system/StructPasswd;
+Landroid/system/Os;->getrlimit(I)Landroid/system/StructRlimit;
+Landroid/system/Os;->getsockoptByte(Ljava/io/FileDescriptor;II)I
+Landroid/system/Os;->getsockoptInAddr(Ljava/io/FileDescriptor;II)Ljava/net/InetAddress;
+Landroid/system/Os;->getsockoptInt(Ljava/io/FileDescriptor;II)I
+Landroid/system/Os;->getsockoptLinger(Ljava/io/FileDescriptor;II)Landroid/system/StructLinger;
+Landroid/system/Os;->getsockoptTimeval(Ljava/io/FileDescriptor;II)Landroid/system/StructTimeval;
+Landroid/system/Os;->getsockoptUcred(Ljava/io/FileDescriptor;II)Landroid/system/StructUcred;
+Landroid/system/Os;->ioctlInetAddress(Ljava/io/FileDescriptor;ILjava/lang/String;)Ljava/net/InetAddress;
+Landroid/system/Os;->ioctlInt(Ljava/io/FileDescriptor;ILandroid/system/Int32Ref;)I
+Landroid/system/Os;->pipe2(I)[Ljava/io/FileDescriptor;
+Landroid/system/Os;->realpath(Ljava/lang/String;)Ljava/lang/String;
+Landroid/system/Os;->setpgid(II)V
+Landroid/system/Os;->setregid(II)V
+Landroid/system/Os;->setreuid(II)V
+Landroid/system/Os;->setsockoptByte(Ljava/io/FileDescriptor;III)V
+Landroid/system/Os;->setsockoptGroupReq(Ljava/io/FileDescriptor;IILandroid/system/StructGroupReq;)V
+Landroid/system/Os;->setsockoptIpMreqn(Ljava/io/FileDescriptor;III)V
+Landroid/system/Os;->setsockoptLinger(Ljava/io/FileDescriptor;IILandroid/system/StructLinger;)V
+Landroid/system/Os;->splice(Ljava/io/FileDescriptor;Landroid/system/Int64Ref;Ljava/io/FileDescriptor;Landroid/system/Int64Ref;JI)J
+Landroid/system/Os;->unlink(Ljava/lang/String;)V
+Landroid/system/Os;->waitpid(ILandroid/system/Int32Ref;I)I
+Landroid/system/PacketSocketAddress;-><init>(SISB[B)V
+Landroid/system/PacketSocketAddress;->sll_addr:[B
+Landroid/system/PacketSocketAddress;->sll_hatype:S
+Landroid/system/PacketSocketAddress;->sll_ifindex:I
+Landroid/system/PacketSocketAddress;->sll_pkttype:B
+Landroid/system/PacketSocketAddress;->sll_protocol:S
+Landroid/system/StructAddrinfo;-><init>()V
+Landroid/system/StructAddrinfo;->ai_addr:Ljava/net/InetAddress;
+Landroid/system/StructAddrinfo;->ai_family:I
+Landroid/system/StructAddrinfo;->ai_flags:I
+Landroid/system/StructAddrinfo;->ai_next:Landroid/system/StructAddrinfo;
+Landroid/system/StructAddrinfo;->ai_protocol:I
+Landroid/system/StructAddrinfo;->ai_socktype:I
+Landroid/system/StructCapUserData;-><init>(III)V
+Landroid/system/StructCapUserData;->effective:I
+Landroid/system/StructCapUserData;->inheritable:I
+Landroid/system/StructCapUserData;->permitted:I
+Landroid/system/StructCapUserHeader;-><init>(II)V
+Landroid/system/StructCapUserHeader;->pid:I
+Landroid/system/StructCapUserHeader;->version:I
+Landroid/system/StructFlock;-><init>()V
+Landroid/system/StructFlock;->l_len:J
+Landroid/system/StructFlock;->l_pid:I
+Landroid/system/StructFlock;->l_start:J
+Landroid/system/StructFlock;->l_type:S
+Landroid/system/StructFlock;->l_whence:S
+Landroid/system/StructGroupReq;-><init>(ILjava/net/InetAddress;)V
+Landroid/system/StructGroupReq;->gr_group:Ljava/net/InetAddress;
+Landroid/system/StructGroupReq;->gr_interface:I
+Landroid/system/StructIcmpHdr;-><init>()V
+Landroid/system/StructIcmpHdr;->getBytes()[B
+Landroid/system/StructIcmpHdr;->IcmpEchoHdr(ZI)Landroid/system/StructIcmpHdr;
+Landroid/system/StructIcmpHdr;->packet:[B
+Landroid/system/StructIfaddrs;-><init>(Ljava/lang/String;ILjava/net/InetAddress;Ljava/net/InetAddress;Ljava/net/InetAddress;[B)V
+Landroid/system/StructIfaddrs;->hwaddr:[B
+Landroid/system/StructIfaddrs;->ifa_addr:Ljava/net/InetAddress;
+Landroid/system/StructIfaddrs;->ifa_broadaddr:Ljava/net/InetAddress;
+Landroid/system/StructIfaddrs;->ifa_flags:I
+Landroid/system/StructIfaddrs;->ifa_name:Ljava/lang/String;
+Landroid/system/StructIfaddrs;->ifa_netmask:Ljava/net/InetAddress;
+Landroid/system/StructLinger;-><init>(II)V
+Landroid/system/StructLinger;->isOn()Z
+Landroid/system/StructLinger;->l_linger:I
+Landroid/system/StructLinger;->l_onoff:I
+Landroid/system/StructPasswd;-><init>(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V
+Landroid/system/StructPasswd;->pw_dir:Ljava/lang/String;
+Landroid/system/StructPasswd;->pw_gid:I
+Landroid/system/StructPasswd;->pw_name:Ljava/lang/String;
+Landroid/system/StructPasswd;->pw_shell:Ljava/lang/String;
+Landroid/system/StructPasswd;->pw_uid:I
+Landroid/system/StructRlimit;-><init>(JJ)V
+Landroid/system/StructRlimit;->rlim_cur:J
+Landroid/system/StructRlimit;->rlim_max:J
+Landroid/system/StructTimeval;-><init>(JJ)V
+Landroid/system/StructTimeval;->toMillis()J
+Landroid/system/StructTimeval;->tv_sec:J
+Landroid/system/StructTimeval;->tv_usec:J
+Landroid/system/StructUcred;-><init>(III)V
+Landroid/system/StructUcred;->gid:I
+Landroid/system/StructUcred;->pid:I
+Landroid/system/StructUcred;->uid:I
+Lcom/android/okhttp/Address;-><init>(Ljava/lang/String;ILcom/android/okhttp/Dns;Ljavax/net/SocketFactory;Ljavax/net/ssl/SSLSocketFactory;Ljavax/net/ssl/HostnameVerifier;Lcom/android/okhttp/CertificatePinner;Lcom/android/okhttp/Authenticator;Ljava/net/Proxy;Ljava/util/List;Ljava/util/List;Ljava/net/ProxySelector;)V
+Lcom/android/okhttp/Address;->authenticator:Lcom/android/okhttp/Authenticator;
+Lcom/android/okhttp/Address;->certificatePinner:Lcom/android/okhttp/CertificatePinner;
+Lcom/android/okhttp/Address;->connectionSpecs:Ljava/util/List;
+Lcom/android/okhttp/Address;->dns:Lcom/android/okhttp/Dns;
+Lcom/android/okhttp/Address;->getAuthenticator()Lcom/android/okhttp/Authenticator;
+Lcom/android/okhttp/Address;->getCertificatePinner()Lcom/android/okhttp/CertificatePinner;
+Lcom/android/okhttp/Address;->getConnectionSpecs()Ljava/util/List;
+Lcom/android/okhttp/Address;->getDns()Lcom/android/okhttp/Dns;
+Lcom/android/okhttp/Address;->getHostnameVerifier()Ljavax/net/ssl/HostnameVerifier;
+Lcom/android/okhttp/Address;->getProtocols()Ljava/util/List;
+Lcom/android/okhttp/Address;->getProxy()Ljava/net/Proxy;
+Lcom/android/okhttp/Address;->getProxySelector()Ljava/net/ProxySelector;
+Lcom/android/okhttp/Address;->getSocketFactory()Ljavax/net/SocketFactory;
+Lcom/android/okhttp/Address;->getSslSocketFactory()Ljavax/net/ssl/SSLSocketFactory;
+Lcom/android/okhttp/Address;->getUriHost()Ljava/lang/String;
+Lcom/android/okhttp/Address;->getUriPort()I
+Lcom/android/okhttp/Address;->hostnameVerifier:Ljavax/net/ssl/HostnameVerifier;
+Lcom/android/okhttp/Address;->protocols:Ljava/util/List;
+Lcom/android/okhttp/Address;->proxy:Ljava/net/Proxy;
+Lcom/android/okhttp/Address;->proxySelector:Ljava/net/ProxySelector;
+Lcom/android/okhttp/Address;->socketFactory:Ljavax/net/SocketFactory;
+Lcom/android/okhttp/Address;->sslSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
+Lcom/android/okhttp/Address;->url()Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/Address;->url:Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/AndroidShimResponseCache;-><init>(Lcom/android/okhttp/Cache;)V
+Lcom/android/okhttp/AndroidShimResponseCache;->close()V
+Lcom/android/okhttp/AndroidShimResponseCache;->create(Ljava/io/File;J)Lcom/android/okhttp/AndroidShimResponseCache;
+Lcom/android/okhttp/AndroidShimResponseCache;->delegate:Lcom/android/okhttp/Cache;
+Lcom/android/okhttp/AndroidShimResponseCache;->delete()V
+Lcom/android/okhttp/AndroidShimResponseCache;->flush()V
+Lcom/android/okhttp/AndroidShimResponseCache;->getCache()Lcom/android/okhttp/Cache;
+Lcom/android/okhttp/AndroidShimResponseCache;->getHitCount()I
+Lcom/android/okhttp/AndroidShimResponseCache;->getNetworkCount()I
+Lcom/android/okhttp/AndroidShimResponseCache;->getRequestCount()I
+Lcom/android/okhttp/AndroidShimResponseCache;->isEquivalent(Ljava/io/File;J)Z
+Lcom/android/okhttp/AndroidShimResponseCache;->maxSize()J
+Lcom/android/okhttp/AndroidShimResponseCache;->size()J
+Lcom/android/okhttp/Authenticator;->authenticate(Ljava/net/Proxy;Lcom/android/okhttp/Response;)Lcom/android/okhttp/Request;
+Lcom/android/okhttp/Authenticator;->authenticateProxy(Ljava/net/Proxy;Lcom/android/okhttp/Response;)Lcom/android/okhttp/Request;
+Lcom/android/okhttp/Cache$CacheRequestImpl;->abort()V
+Lcom/android/okhttp/Cache$CacheRequestImpl;->body()Lcom/android/okhttp/okio/Sink;
+Lcom/android/okhttp/Cache$CacheRequestImpl;->body:Lcom/android/okhttp/okio/Sink;
+Lcom/android/okhttp/Cache$CacheRequestImpl;->cacheOut:Lcom/android/okhttp/okio/Sink;
+Lcom/android/okhttp/Cache$CacheRequestImpl;->done:Z
+Lcom/android/okhttp/Cache$CacheRequestImpl;->editor:Lcom/android/okhttp/internal/DiskLruCache$Editor;
+Lcom/android/okhttp/Cache$CacheResponseBody;-><init>(Lcom/android/okhttp/internal/DiskLruCache$Snapshot;Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/okhttp/Cache$CacheResponseBody;->bodySource:Lcom/android/okhttp/okio/BufferedSource;
+Lcom/android/okhttp/Cache$CacheResponseBody;->contentLength()J
+Lcom/android/okhttp/Cache$CacheResponseBody;->contentLength:Ljava/lang/String;
+Lcom/android/okhttp/Cache$CacheResponseBody;->contentType()Lcom/android/okhttp/MediaType;
+Lcom/android/okhttp/Cache$CacheResponseBody;->contentType:Ljava/lang/String;
+Lcom/android/okhttp/Cache$CacheResponseBody;->snapshot:Lcom/android/okhttp/internal/DiskLruCache$Snapshot;
+Lcom/android/okhttp/Cache$CacheResponseBody;->source()Lcom/android/okhttp/okio/BufferedSource;
+Lcom/android/okhttp/Cache$Entry;-><init>(Lcom/android/okhttp/okio/Source;)V
+Lcom/android/okhttp/Cache$Entry;-><init>(Lcom/android/okhttp/Response;)V
+Lcom/android/okhttp/Cache$Entry;->code:I
+Lcom/android/okhttp/Cache$Entry;->handshake:Lcom/android/okhttp/Handshake;
+Lcom/android/okhttp/Cache$Entry;->isHttps()Z
+Lcom/android/okhttp/Cache$Entry;->matches(Lcom/android/okhttp/Request;Lcom/android/okhttp/Response;)Z
+Lcom/android/okhttp/Cache$Entry;->message:Ljava/lang/String;
+Lcom/android/okhttp/Cache$Entry;->protocol:Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Cache$Entry;->readCertificateList(Lcom/android/okhttp/okio/BufferedSource;)Ljava/util/List;
+Lcom/android/okhttp/Cache$Entry;->requestMethod:Ljava/lang/String;
+Lcom/android/okhttp/Cache$Entry;->response(Lcom/android/okhttp/Request;Lcom/android/okhttp/internal/DiskLruCache$Snapshot;)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Cache$Entry;->responseHeaders:Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Cache$Entry;->url:Ljava/lang/String;
+Lcom/android/okhttp/Cache$Entry;->varyHeaders:Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Cache$Entry;->writeCertList(Lcom/android/okhttp/okio/BufferedSink;Ljava/util/List;)V
+Lcom/android/okhttp/Cache$Entry;->writeTo(Lcom/android/okhttp/internal/DiskLruCache$Editor;)V
+Lcom/android/okhttp/Cache;-><init>(Ljava/io/File;J)V
+Lcom/android/okhttp/Cache;-><init>(Ljava/io/File;JLcom/android/okhttp/internal/io/FileSystem;)V
+Lcom/android/okhttp/Cache;->abortQuietly(Lcom/android/okhttp/internal/DiskLruCache$Editor;)V
+Lcom/android/okhttp/Cache;->cache:Lcom/android/okhttp/internal/DiskLruCache;
+Lcom/android/okhttp/Cache;->close()V
+Lcom/android/okhttp/Cache;->delete()V
+Lcom/android/okhttp/Cache;->ENTRY_BODY:I
+Lcom/android/okhttp/Cache;->ENTRY_COUNT:I
+Lcom/android/okhttp/Cache;->ENTRY_METADATA:I
+Lcom/android/okhttp/Cache;->evictAll()V
+Lcom/android/okhttp/Cache;->flush()V
+Lcom/android/okhttp/Cache;->get(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Cache;->getDirectory()Ljava/io/File;
+Lcom/android/okhttp/Cache;->getHitCount()I
+Lcom/android/okhttp/Cache;->getMaxSize()J
+Lcom/android/okhttp/Cache;->getNetworkCount()I
+Lcom/android/okhttp/Cache;->getRequestCount()I
+Lcom/android/okhttp/Cache;->getSize()J
+Lcom/android/okhttp/Cache;->getWriteAbortCount()I
+Lcom/android/okhttp/Cache;->getWriteSuccessCount()I
+Lcom/android/okhttp/Cache;->hitCount:I
+Lcom/android/okhttp/Cache;->initialize()V
+Lcom/android/okhttp/Cache;->internalCache:Lcom/android/okhttp/internal/InternalCache;
+Lcom/android/okhttp/Cache;->isClosed()Z
+Lcom/android/okhttp/Cache;->networkCount:I
+Lcom/android/okhttp/Cache;->put(Lcom/android/okhttp/Response;)Lcom/android/okhttp/internal/http/CacheRequest;
+Lcom/android/okhttp/Cache;->readInt(Lcom/android/okhttp/okio/BufferedSource;)I
+Lcom/android/okhttp/Cache;->remove(Lcom/android/okhttp/Request;)V
+Lcom/android/okhttp/Cache;->requestCount:I
+Lcom/android/okhttp/Cache;->trackConditionalCacheHit()V
+Lcom/android/okhttp/Cache;->trackResponse(Lcom/android/okhttp/internal/http/CacheStrategy;)V
+Lcom/android/okhttp/Cache;->update(Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;)V
+Lcom/android/okhttp/Cache;->urls()Ljava/util/Iterator;
+Lcom/android/okhttp/Cache;->urlToKey(Lcom/android/okhttp/Request;)Ljava/lang/String;
+Lcom/android/okhttp/Cache;->VERSION:I
+Lcom/android/okhttp/Cache;->writeAbortCount:I
+Lcom/android/okhttp/Cache;->writeSuccessCount:I
+Lcom/android/okhttp/CacheControl$Builder;-><init>()V
+Lcom/android/okhttp/CacheControl$Builder;->build()Lcom/android/okhttp/CacheControl;
+Lcom/android/okhttp/CacheControl$Builder;->maxAge(ILjava/util/concurrent/TimeUnit;)Lcom/android/okhttp/CacheControl$Builder;
+Lcom/android/okhttp/CacheControl$Builder;->maxAgeSeconds:I
+Lcom/android/okhttp/CacheControl$Builder;->maxStale(ILjava/util/concurrent/TimeUnit;)Lcom/android/okhttp/CacheControl$Builder;
+Lcom/android/okhttp/CacheControl$Builder;->maxStaleSeconds:I
+Lcom/android/okhttp/CacheControl$Builder;->minFresh(ILjava/util/concurrent/TimeUnit;)Lcom/android/okhttp/CacheControl$Builder;
+Lcom/android/okhttp/CacheControl$Builder;->minFreshSeconds:I
+Lcom/android/okhttp/CacheControl$Builder;->noCache()Lcom/android/okhttp/CacheControl$Builder;
+Lcom/android/okhttp/CacheControl$Builder;->noCache:Z
+Lcom/android/okhttp/CacheControl$Builder;->noStore()Lcom/android/okhttp/CacheControl$Builder;
+Lcom/android/okhttp/CacheControl$Builder;->noStore:Z
+Lcom/android/okhttp/CacheControl$Builder;->noTransform()Lcom/android/okhttp/CacheControl$Builder;
+Lcom/android/okhttp/CacheControl$Builder;->noTransform:Z
+Lcom/android/okhttp/CacheControl$Builder;->onlyIfCached()Lcom/android/okhttp/CacheControl$Builder;
+Lcom/android/okhttp/CacheControl$Builder;->onlyIfCached:Z
+Lcom/android/okhttp/CacheControl;-><init>(Lcom/android/okhttp/CacheControl$Builder;)V
+Lcom/android/okhttp/CacheControl;-><init>(ZZIIZZZIIZZLjava/lang/String;)V
+Lcom/android/okhttp/CacheControl;->FORCE_CACHE:Lcom/android/okhttp/CacheControl;
+Lcom/android/okhttp/CacheControl;->FORCE_NETWORK:Lcom/android/okhttp/CacheControl;
+Lcom/android/okhttp/CacheControl;->headerValue()Ljava/lang/String;
+Lcom/android/okhttp/CacheControl;->headerValue:Ljava/lang/String;
+Lcom/android/okhttp/CacheControl;->isPrivate()Z
+Lcom/android/okhttp/CacheControl;->isPrivate:Z
+Lcom/android/okhttp/CacheControl;->isPublic()Z
+Lcom/android/okhttp/CacheControl;->isPublic:Z
+Lcom/android/okhttp/CacheControl;->maxAgeSeconds()I
+Lcom/android/okhttp/CacheControl;->maxAgeSeconds:I
+Lcom/android/okhttp/CacheControl;->maxStaleSeconds()I
+Lcom/android/okhttp/CacheControl;->maxStaleSeconds:I
+Lcom/android/okhttp/CacheControl;->minFreshSeconds()I
+Lcom/android/okhttp/CacheControl;->minFreshSeconds:I
+Lcom/android/okhttp/CacheControl;->mustRevalidate()Z
+Lcom/android/okhttp/CacheControl;->mustRevalidate:Z
+Lcom/android/okhttp/CacheControl;->noCache()Z
+Lcom/android/okhttp/CacheControl;->noCache:Z
+Lcom/android/okhttp/CacheControl;->noStore()Z
+Lcom/android/okhttp/CacheControl;->noStore:Z
+Lcom/android/okhttp/CacheControl;->noTransform()Z
+Lcom/android/okhttp/CacheControl;->noTransform:Z
+Lcom/android/okhttp/CacheControl;->onlyIfCached()Z
+Lcom/android/okhttp/CacheControl;->onlyIfCached:Z
+Lcom/android/okhttp/CacheControl;->parse(Lcom/android/okhttp/Headers;)Lcom/android/okhttp/CacheControl;
+Lcom/android/okhttp/CacheControl;->sMaxAgeSeconds()I
+Lcom/android/okhttp/CacheControl;->sMaxAgeSeconds:I
+Lcom/android/okhttp/Call$ApplicationInterceptorChain;->connection()Lcom/android/okhttp/Connection;
+Lcom/android/okhttp/Call$ApplicationInterceptorChain;->forWebSocket:Z
+Lcom/android/okhttp/Call$ApplicationInterceptorChain;->index:I
+Lcom/android/okhttp/Call$ApplicationInterceptorChain;->proceed(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Call$ApplicationInterceptorChain;->request()Lcom/android/okhttp/Request;
+Lcom/android/okhttp/Call$ApplicationInterceptorChain;->request:Lcom/android/okhttp/Request;
+Lcom/android/okhttp/Call$AsyncCall;->cancel()V
+Lcom/android/okhttp/Call$AsyncCall;->execute()V
+Lcom/android/okhttp/Call$AsyncCall;->forWebSocket:Z
+Lcom/android/okhttp/Call$AsyncCall;->get()Lcom/android/okhttp/Call;
+Lcom/android/okhttp/Call$AsyncCall;->host()Ljava/lang/String;
+Lcom/android/okhttp/Call$AsyncCall;->request()Lcom/android/okhttp/Request;
+Lcom/android/okhttp/Call$AsyncCall;->responseCallback:Lcom/android/okhttp/Callback;
+Lcom/android/okhttp/Call$AsyncCall;->tag()Ljava/lang/Object;
+Lcom/android/okhttp/Call;-><init>(Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/Request;)V
+Lcom/android/okhttp/Call;->cancel()V
+Lcom/android/okhttp/Call;->canceled:Z
+Lcom/android/okhttp/Call;->client:Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/Call;->engine:Lcom/android/okhttp/internal/http/HttpEngine;
+Lcom/android/okhttp/Call;->enqueue(Lcom/android/okhttp/Callback;)V
+Lcom/android/okhttp/Call;->enqueue(Lcom/android/okhttp/Callback;Z)V
+Lcom/android/okhttp/Call;->execute()Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Call;->executed:Z
+Lcom/android/okhttp/Call;->getResponse(Lcom/android/okhttp/Request;Z)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Call;->getResponseWithInterceptorChain(Z)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Call;->isCanceled()Z
+Lcom/android/okhttp/Call;->isExecuted()Z
+Lcom/android/okhttp/Call;->originalRequest:Lcom/android/okhttp/Request;
+Lcom/android/okhttp/Call;->tag()Ljava/lang/Object;
+Lcom/android/okhttp/Call;->toLoggableString()Ljava/lang/String;
+Lcom/android/okhttp/Callback;->onFailure(Lcom/android/okhttp/Request;Ljava/io/IOException;)V
+Lcom/android/okhttp/Callback;->onResponse(Lcom/android/okhttp/Response;)V
+Lcom/android/okhttp/CertificatePinner$Builder;-><init>()V
+Lcom/android/okhttp/CertificatePinner$Builder;->build()Lcom/android/okhttp/CertificatePinner;
+Lcom/android/okhttp/CertificatePinner$Builder;->hostnameToPins:Ljava/util/Map;
+Lcom/android/okhttp/CertificatePinner;-><init>(Lcom/android/okhttp/CertificatePinner$Builder;)V
+Lcom/android/okhttp/CertificatePinner;->check(Ljava/lang/String;Ljava/util/List;)V
+Lcom/android/okhttp/CertificatePinner;->DEFAULT:Lcom/android/okhttp/CertificatePinner;
+Lcom/android/okhttp/CertificatePinner;->findMatchingPins(Ljava/lang/String;)Ljava/util/Set;
+Lcom/android/okhttp/CertificatePinner;->hostnameToPins:Ljava/util/Map;
+Lcom/android/okhttp/CertificatePinner;->pin(Ljava/security/cert/Certificate;)Ljava/lang/String;
+Lcom/android/okhttp/CertificatePinner;->sha1(Ljava/security/cert/X509Certificate;)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/Challenge;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/okhttp/Challenge;->getRealm()Ljava/lang/String;
+Lcom/android/okhttp/Challenge;->getScheme()Ljava/lang/String;
+Lcom/android/okhttp/Challenge;->realm:Ljava/lang/String;
+Lcom/android/okhttp/Challenge;->scheme:Ljava/lang/String;
+Lcom/android/okhttp/CipherSuite;->forJavaName(Ljava/lang/String;)Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->javaName:Ljava/lang/String;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_DSS_WITH_AES_128_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_DSS_WITH_AES_256_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_DSS_WITH_DES_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_RSA_WITH_AES_128_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_RSA_WITH_AES_256_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DHE_RSA_WITH_DES_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_EXPORT_WITH_RC4_40_MD5:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_WITH_AES_128_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_WITH_AES_128_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_WITH_AES_128_GCM_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_WITH_AES_256_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_WITH_AES_256_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_WITH_AES_256_GCM_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_WITH_DES_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_DH_anon_WITH_RC4_128_MD5:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_ECDSA_WITH_NULL_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_RSA_WITH_NULL_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDHE_RSA_WITH_RC4_128_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_anon_WITH_AES_128_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_anon_WITH_AES_256_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_anon_WITH_NULL_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_anon_WITH_RC4_128_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_ECDSA_WITH_NULL_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_ECDSA_WITH_RC4_128_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_RSA_WITH_NULL_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_ECDH_RSA_WITH_RC4_128_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_EMPTY_RENEGOTIATION_INFO_SCSV:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_KRB5_EXPORT_WITH_RC4_40_MD5:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_KRB5_EXPORT_WITH_RC4_40_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_KRB5_WITH_3DES_EDE_CBC_MD5:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_KRB5_WITH_3DES_EDE_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_KRB5_WITH_DES_CBC_MD5:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_KRB5_WITH_DES_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_KRB5_WITH_RC4_128_MD5:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_KRB5_WITH_RC4_128_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_EXPORT_WITH_DES40_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_EXPORT_WITH_RC4_40_MD5:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_3DES_EDE_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_AES_128_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_AES_128_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_AES_128_GCM_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_AES_256_CBC_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_AES_256_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_AES_256_GCM_SHA384:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_DES_CBC_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_NULL_MD5:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_NULL_SHA256:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_NULL_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_RC4_128_MD5:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->TLS_RSA_WITH_RC4_128_SHA:Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->valueOf(Ljava/lang/String;)Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/CipherSuite;->values()[Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/Connection;->getHandshake()Lcom/android/okhttp/Handshake;
+Lcom/android/okhttp/Connection;->getProtocol()Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Connection;->getRoute()Lcom/android/okhttp/Route;
+Lcom/android/okhttp/ConnectionPool;-><init>(IJ)V
+Lcom/android/okhttp/ConnectionPool;-><init>(IJLjava/util/concurrent/TimeUnit;)V
+Lcom/android/okhttp/ConnectionPool;->cleanup(J)J
+Lcom/android/okhttp/ConnectionPool;->cleanupRunnable:Ljava/lang/Runnable;
+Lcom/android/okhttp/ConnectionPool;->connectionBecameIdle(Lcom/android/okhttp/internal/io/RealConnection;)Z
+Lcom/android/okhttp/ConnectionPool;->DEFAULT_KEEP_ALIVE_DURATION_MS:J
+Lcom/android/okhttp/ConnectionPool;->evictAll()V
+Lcom/android/okhttp/ConnectionPool;->executor:Ljava/util/concurrent/Executor;
+Lcom/android/okhttp/ConnectionPool;->get(Lcom/android/okhttp/Address;Lcom/android/okhttp/internal/http/StreamAllocation;)Lcom/android/okhttp/internal/io/RealConnection;
+Lcom/android/okhttp/ConnectionPool;->getConnectionCount()I
+Lcom/android/okhttp/ConnectionPool;->getDefault()Lcom/android/okhttp/ConnectionPool;
+Lcom/android/okhttp/ConnectionPool;->getHttpConnectionCount()I
+Lcom/android/okhttp/ConnectionPool;->getIdleConnectionCount()I
+Lcom/android/okhttp/ConnectionPool;->getMultiplexedConnectionCount()I
+Lcom/android/okhttp/ConnectionPool;->getSpdyConnectionCount()I
+Lcom/android/okhttp/ConnectionPool;->pruneAndGetAllocationCount(Lcom/android/okhttp/internal/io/RealConnection;J)I
+Lcom/android/okhttp/ConnectionPool;->put(Lcom/android/okhttp/internal/io/RealConnection;)V
+Lcom/android/okhttp/ConnectionPool;->routeDatabase:Lcom/android/okhttp/internal/RouteDatabase;
+Lcom/android/okhttp/ConnectionPool;->setCleanupRunnableForTest(Ljava/lang/Runnable;)V
+Lcom/android/okhttp/ConnectionSpec$Builder;-><init>(Lcom/android/okhttp/ConnectionSpec;)V
+Lcom/android/okhttp/ConnectionSpec$Builder;-><init>(Z)V
+Lcom/android/okhttp/ConnectionSpec$Builder;->allEnabledCipherSuites()Lcom/android/okhttp/ConnectionSpec$Builder;
+Lcom/android/okhttp/ConnectionSpec$Builder;->allEnabledTlsVersions()Lcom/android/okhttp/ConnectionSpec$Builder;
+Lcom/android/okhttp/ConnectionSpec$Builder;->build()Lcom/android/okhttp/ConnectionSpec;
+Lcom/android/okhttp/ConnectionSpec$Builder;->cipherSuites:[Ljava/lang/String;
+Lcom/android/okhttp/ConnectionSpec$Builder;->supportsTlsExtensions(Z)Lcom/android/okhttp/ConnectionSpec$Builder;
+Lcom/android/okhttp/ConnectionSpec$Builder;->supportsTlsExtensions:Z
+Lcom/android/okhttp/ConnectionSpec$Builder;->tls:Z
+Lcom/android/okhttp/ConnectionSpec$Builder;->tlsVersions:[Ljava/lang/String;
+Lcom/android/okhttp/ConnectionSpec;-><init>(Lcom/android/okhttp/ConnectionSpec$Builder;)V
+Lcom/android/okhttp/ConnectionSpec;->apply(Ljavax/net/ssl/SSLSocket;Z)V
+Lcom/android/okhttp/ConnectionSpec;->APPROVED_CIPHER_SUITES:[Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/ConnectionSpec;->cipherSuites()Ljava/util/List;
+Lcom/android/okhttp/ConnectionSpec;->cipherSuites:[Ljava/lang/String;
+Lcom/android/okhttp/ConnectionSpec;->CLEARTEXT:Lcom/android/okhttp/ConnectionSpec;
+Lcom/android/okhttp/ConnectionSpec;->COMPATIBLE_TLS:Lcom/android/okhttp/ConnectionSpec;
+Lcom/android/okhttp/ConnectionSpec;->isCompatible(Ljavax/net/ssl/SSLSocket;)Z
+Lcom/android/okhttp/ConnectionSpec;->isTls()Z
+Lcom/android/okhttp/ConnectionSpec;->MODERN_TLS:Lcom/android/okhttp/ConnectionSpec;
+Lcom/android/okhttp/ConnectionSpec;->nonEmptyIntersection([Ljava/lang/String;[Ljava/lang/String;)Z
+Lcom/android/okhttp/ConnectionSpec;->supportedSpec(Ljavax/net/ssl/SSLSocket;Z)Lcom/android/okhttp/ConnectionSpec;
+Lcom/android/okhttp/ConnectionSpec;->supportsTlsExtensions()Z
+Lcom/android/okhttp/ConnectionSpec;->supportsTlsExtensions:Z
+Lcom/android/okhttp/ConnectionSpec;->tls:Z
+Lcom/android/okhttp/ConnectionSpec;->tlsVersions()Ljava/util/List;
+Lcom/android/okhttp/ConnectionSpec;->tlsVersions:[Ljava/lang/String;
+Lcom/android/okhttp/Dispatcher;-><init>()V
+Lcom/android/okhttp/Dispatcher;-><init>(Ljava/util/concurrent/ExecutorService;)V
+Lcom/android/okhttp/Dispatcher;->cancel(Ljava/lang/Object;)V
+Lcom/android/okhttp/Dispatcher;->enqueue(Lcom/android/okhttp/Call$AsyncCall;)V
+Lcom/android/okhttp/Dispatcher;->executed(Lcom/android/okhttp/Call;)V
+Lcom/android/okhttp/Dispatcher;->executedCalls:Ljava/util/Deque;
+Lcom/android/okhttp/Dispatcher;->executorService:Ljava/util/concurrent/ExecutorService;
+Lcom/android/okhttp/Dispatcher;->finished(Lcom/android/okhttp/Call$AsyncCall;)V
+Lcom/android/okhttp/Dispatcher;->finished(Lcom/android/okhttp/Call;)V
+Lcom/android/okhttp/Dispatcher;->getExecutorService()Ljava/util/concurrent/ExecutorService;
+Lcom/android/okhttp/Dispatcher;->getMaxRequests()I
+Lcom/android/okhttp/Dispatcher;->getMaxRequestsPerHost()I
+Lcom/android/okhttp/Dispatcher;->getQueuedCallCount()I
+Lcom/android/okhttp/Dispatcher;->getRunningCallCount()I
+Lcom/android/okhttp/Dispatcher;->maxRequests:I
+Lcom/android/okhttp/Dispatcher;->maxRequestsPerHost:I
+Lcom/android/okhttp/Dispatcher;->promoteCalls()V
+Lcom/android/okhttp/Dispatcher;->readyCalls:Ljava/util/Deque;
+Lcom/android/okhttp/Dispatcher;->runningCalls:Ljava/util/Deque;
+Lcom/android/okhttp/Dispatcher;->runningCallsForHost(Lcom/android/okhttp/Call$AsyncCall;)I
+Lcom/android/okhttp/Dispatcher;->setMaxRequests(I)V
+Lcom/android/okhttp/Dispatcher;->setMaxRequestsPerHost(I)V
+Lcom/android/okhttp/Dns;->lookup(Ljava/lang/String;)Ljava/util/List;
+Lcom/android/okhttp/Dns;->SYSTEM:Lcom/android/okhttp/Dns;
+Lcom/android/okhttp/Handshake;-><init>(Ljava/lang/String;Ljava/util/List;Ljava/util/List;)V
+Lcom/android/okhttp/Handshake;->cipherSuite()Ljava/lang/String;
+Lcom/android/okhttp/Handshake;->cipherSuite:Ljava/lang/String;
+Lcom/android/okhttp/Handshake;->get(Ljava/lang/String;Ljava/util/List;Ljava/util/List;)Lcom/android/okhttp/Handshake;
+Lcom/android/okhttp/Handshake;->get(Ljavax/net/ssl/SSLSession;)Lcom/android/okhttp/Handshake;
+Lcom/android/okhttp/Handshake;->localCertificates()Ljava/util/List;
+Lcom/android/okhttp/Handshake;->localCertificates:Ljava/util/List;
+Lcom/android/okhttp/Handshake;->localPrincipal()Ljava/security/Principal;
+Lcom/android/okhttp/Handshake;->peerCertificates()Ljava/util/List;
+Lcom/android/okhttp/Handshake;->peerCertificates:Ljava/util/List;
+Lcom/android/okhttp/Handshake;->peerPrincipal()Ljava/security/Principal;
+Lcom/android/okhttp/Headers$Builder;-><init>()V
+Lcom/android/okhttp/Headers$Builder;->add(Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/Headers$Builder;->add(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/Headers$Builder;->addLenient(Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/Headers$Builder;->addLenient(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/Headers$Builder;->build()Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Headers$Builder;->checkNameAndValue(Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/okhttp/Headers$Builder;->get(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/okhttp/Headers$Builder;->namesAndValues:Ljava/util/List;
+Lcom/android/okhttp/Headers$Builder;->removeAll(Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/Headers$Builder;->set(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/Headers;-><init>(Lcom/android/okhttp/Headers$Builder;)V
+Lcom/android/okhttp/Headers;-><init>([Ljava/lang/String;)V
+Lcom/android/okhttp/Headers;->get(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/okhttp/Headers;->get([Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/okhttp/Headers;->getDate(Ljava/lang/String;)Ljava/util/Date;
+Lcom/android/okhttp/Headers;->name(I)Ljava/lang/String;
+Lcom/android/okhttp/Headers;->names()Ljava/util/Set;
+Lcom/android/okhttp/Headers;->namesAndValues:[Ljava/lang/String;
+Lcom/android/okhttp/Headers;->newBuilder()Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/Headers;->of(Ljava/util/Map;)Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Headers;->size()I
+Lcom/android/okhttp/Headers;->toMultimap()Ljava/util/Map;
+Lcom/android/okhttp/Headers;->value(I)Ljava/lang/String;
+Lcom/android/okhttp/Headers;->values(Ljava/lang/String;)Ljava/util/List;
+Lcom/android/okhttp/HttpUrl$Builder$ParseResult;->INVALID_HOST:Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+Lcom/android/okhttp/HttpUrl$Builder$ParseResult;->INVALID_PORT:Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+Lcom/android/okhttp/HttpUrl$Builder$ParseResult;->MISSING_SCHEME:Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+Lcom/android/okhttp/HttpUrl$Builder$ParseResult;->SUCCESS:Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+Lcom/android/okhttp/HttpUrl$Builder$ParseResult;->UNSUPPORTED_SCHEME:Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+Lcom/android/okhttp/HttpUrl$Builder$ParseResult;->valueOf(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+Lcom/android/okhttp/HttpUrl$Builder$ParseResult;->values()[Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+Lcom/android/okhttp/HttpUrl$Builder;-><init>()V
+Lcom/android/okhttp/HttpUrl$Builder;->addEncodedPathSegment(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->addEncodedQueryParameter(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->addPathSegment(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->addQueryParameter(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->canonicalizeHost(Ljava/lang/String;II)Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl$Builder;->containsInvalidHostnameAsciiCodes(Ljava/lang/String;)Z
+Lcom/android/okhttp/HttpUrl$Builder;->decodeIpv4Suffix(Ljava/lang/String;II[BI)Z
+Lcom/android/okhttp/HttpUrl$Builder;->decodeIpv6(Ljava/lang/String;II)Ljava/net/InetAddress;
+Lcom/android/okhttp/HttpUrl$Builder;->domainToAscii(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl$Builder;->effectivePort()I
+Lcom/android/okhttp/HttpUrl$Builder;->encodedFragment(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->encodedFragment:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl$Builder;->encodedPassword(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->encodedPassword:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl$Builder;->encodedPath(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->encodedPathSegments:Ljava/util/List;
+Lcom/android/okhttp/HttpUrl$Builder;->encodedQuery(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->encodedQueryNamesAndValues:Ljava/util/List;
+Lcom/android/okhttp/HttpUrl$Builder;->encodedUsername(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->encodedUsername:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl$Builder;->fragment(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->host(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->host:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl$Builder;->inet6AddressToAscii([B)Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl$Builder;->isDot(Ljava/lang/String;)Z
+Lcom/android/okhttp/HttpUrl$Builder;->isDotDot(Ljava/lang/String;)Z
+Lcom/android/okhttp/HttpUrl$Builder;->parse(Lcom/android/okhttp/HttpUrl;Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+Lcom/android/okhttp/HttpUrl$Builder;->parsePort(Ljava/lang/String;II)I
+Lcom/android/okhttp/HttpUrl$Builder;->password(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->pop()V
+Lcom/android/okhttp/HttpUrl$Builder;->port(I)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->port:I
+Lcom/android/okhttp/HttpUrl$Builder;->portColonOffset(Ljava/lang/String;II)I
+Lcom/android/okhttp/HttpUrl$Builder;->push(Ljava/lang/String;IIZZ)V
+Lcom/android/okhttp/HttpUrl$Builder;->query(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->reencodeForUri()Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->removeAllCanonicalQueryParameters(Ljava/lang/String;)V
+Lcom/android/okhttp/HttpUrl$Builder;->removeAllEncodedQueryParameters(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->removeAllQueryParameters(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->removePathSegment(I)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->resolvePath(Ljava/lang/String;II)V
+Lcom/android/okhttp/HttpUrl$Builder;->scheme(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->scheme:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl$Builder;->schemeDelimiterOffset(Ljava/lang/String;II)I
+Lcom/android/okhttp/HttpUrl$Builder;->setEncodedPathSegment(ILjava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->setEncodedQueryParameter(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->setPathSegment(ILjava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->setQueryParameter(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder;->skipLeadingAsciiWhitespace(Ljava/lang/String;II)I
+Lcom/android/okhttp/HttpUrl$Builder;->skipTrailingAsciiWhitespace(Ljava/lang/String;II)I
+Lcom/android/okhttp/HttpUrl$Builder;->slashCount(Ljava/lang/String;II)I
+Lcom/android/okhttp/HttpUrl$Builder;->username(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl;-><init>(Lcom/android/okhttp/HttpUrl$Builder;)V
+Lcom/android/okhttp/HttpUrl;->canonicalize(Lcom/android/okhttp/okio/Buffer;Ljava/lang/String;IILjava/lang/String;ZZZZ)V
+Lcom/android/okhttp/HttpUrl;->canonicalize(Ljava/lang/String;IILjava/lang/String;ZZZZ)Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->canonicalize(Ljava/lang/String;Ljava/lang/String;ZZZZ)Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->decodeHexDigit(C)I
+Lcom/android/okhttp/HttpUrl;->defaultPort(Ljava/lang/String;)I
+Lcom/android/okhttp/HttpUrl;->delimiterOffset(Ljava/lang/String;IILjava/lang/String;)I
+Lcom/android/okhttp/HttpUrl;->encodedFragment()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->encodedPassword()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->encodedPathSegments()Ljava/util/List;
+Lcom/android/okhttp/HttpUrl;->encodedQuery()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->encodedUsername()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->FORM_ENCODE_SET:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->fragment()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->fragment:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->FRAGMENT_ENCODE_SET:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->FRAGMENT_ENCODE_SET_URI:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->get(Ljava/net/URI;)Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/HttpUrl;->get(Ljava/net/URL;)Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/HttpUrl;->getChecked(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/HttpUrl;->HEX_DIGITS:[C
+Lcom/android/okhttp/HttpUrl;->host()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->host:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->isHttps()Z
+Lcom/android/okhttp/HttpUrl;->namesAndValuesToQueryString(Ljava/lang/StringBuilder;Ljava/util/List;)V
+Lcom/android/okhttp/HttpUrl;->password()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->password:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->PASSWORD_ENCODE_SET:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->pathSegments()Ljava/util/List;
+Lcom/android/okhttp/HttpUrl;->pathSegments:Ljava/util/List;
+Lcom/android/okhttp/HttpUrl;->pathSegmentsToString(Ljava/lang/StringBuilder;Ljava/util/List;)V
+Lcom/android/okhttp/HttpUrl;->pathSize()I
+Lcom/android/okhttp/HttpUrl;->PATH_SEGMENT_ENCODE_SET:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->PATH_SEGMENT_ENCODE_SET_URI:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->percentDecode(Lcom/android/okhttp/okio/Buffer;Ljava/lang/String;IIZ)V
+Lcom/android/okhttp/HttpUrl;->percentDecode(Ljava/lang/String;IIZ)Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->percentDecode(Ljava/lang/String;Z)Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->percentDecode(Ljava/util/List;Z)Ljava/util/List;
+Lcom/android/okhttp/HttpUrl;->percentEncoded(Ljava/lang/String;II)Z
+Lcom/android/okhttp/HttpUrl;->port()I
+Lcom/android/okhttp/HttpUrl;->port:I
+Lcom/android/okhttp/HttpUrl;->queryNamesAndValues:Ljava/util/List;
+Lcom/android/okhttp/HttpUrl;->queryParameter(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->queryParameterName(I)Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->queryParameterNames()Ljava/util/Set;
+Lcom/android/okhttp/HttpUrl;->queryParameterValue(I)Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->queryParameterValues(Ljava/lang/String;)Ljava/util/List;
+Lcom/android/okhttp/HttpUrl;->querySize()I
+Lcom/android/okhttp/HttpUrl;->queryStringToNamesAndValues(Ljava/lang/String;)Ljava/util/List;
+Lcom/android/okhttp/HttpUrl;->QUERY_COMPONENT_ENCODE_SET:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->QUERY_COMPONENT_ENCODE_SET_URI:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->QUERY_ENCODE_SET:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->resolve(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/HttpUrl;->scheme()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->scheme:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->uri()Ljava/net/URI;
+Lcom/android/okhttp/HttpUrl;->url()Ljava/net/URL;
+Lcom/android/okhttp/HttpUrl;->url:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->username()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->username:Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->USERNAME_ENCODE_SET:Ljava/lang/String;
+Lcom/android/okhttp/Interceptor$Chain;->connection()Lcom/android/okhttp/Connection;
+Lcom/android/okhttp/Interceptor$Chain;->proceed(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Interceptor$Chain;->request()Lcom/android/okhttp/Request;
+Lcom/android/okhttp/Interceptor;->intercept(Lcom/android/okhttp/Interceptor$Chain;)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/CacheRequest;->abort()V
+Lcom/android/okhttp/internal/http/CacheRequest;->body()Lcom/android/okhttp/okio/Sink;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;-><init>(JLcom/android/okhttp/Request;Lcom/android/okhttp/Response;)V
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->ageSeconds:I
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->cacheResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->cacheResponseAge()J
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->computeFreshnessLifetime()J
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->etag:Ljava/lang/String;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->expires:Ljava/util/Date;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->get()Lcom/android/okhttp/internal/http/CacheStrategy;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->getCandidate()Lcom/android/okhttp/internal/http/CacheStrategy;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->hasConditions(Lcom/android/okhttp/Request;)Z
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->isFreshnessLifetimeHeuristic()Z
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->lastModified:Ljava/util/Date;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->lastModifiedString:Ljava/lang/String;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->nowMillis:J
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->receivedResponseMillis:J
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->request:Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->sentRequestMillis:J
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->servedDate:Ljava/util/Date;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;->servedDateString:Ljava/lang/String;
+Lcom/android/okhttp/internal/http/CacheStrategy;-><init>(Lcom/android/okhttp/Request;Lcom/android/okhttp/Response;)V
+Lcom/android/okhttp/internal/http/CacheStrategy;->cacheResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/CacheStrategy;->isCacheable(Lcom/android/okhttp/Response;Lcom/android/okhttp/Request;)Z
+Lcom/android/okhttp/internal/http/CacheStrategy;->networkRequest:Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/HttpEngine$NetworkInterceptorChain;->calls:I
+Lcom/android/okhttp/internal/http/HttpEngine$NetworkInterceptorChain;->connection()Lcom/android/okhttp/Connection;
+Lcom/android/okhttp/internal/http/HttpEngine$NetworkInterceptorChain;->index:I
+Lcom/android/okhttp/internal/http/HttpEngine$NetworkInterceptorChain;->proceed(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/HttpEngine$NetworkInterceptorChain;->request()Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/HttpEngine$NetworkInterceptorChain;->request:Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/HttpEngine;-><init>(Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/Request;ZZZLcom/android/okhttp/internal/http/StreamAllocation;Lcom/android/okhttp/internal/http/RetryableSink;Lcom/android/okhttp/Response;)V
+Lcom/android/okhttp/internal/http/HttpEngine;->bufferedRequestBody:Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/internal/http/HttpEngine;->bufferRequestBody:Z
+Lcom/android/okhttp/internal/http/HttpEngine;->cacheResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/HttpEngine;->cacheStrategy:Lcom/android/okhttp/internal/http/CacheStrategy;
+Lcom/android/okhttp/internal/http/HttpEngine;->cacheWritingResponse(Lcom/android/okhttp/internal/http/CacheRequest;Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/HttpEngine;->callerWritesRequestBody:Z
+Lcom/android/okhttp/internal/http/HttpEngine;->cancel()V
+Lcom/android/okhttp/internal/http/HttpEngine;->client:Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/internal/http/HttpEngine;->close()Lcom/android/okhttp/internal/http/StreamAllocation;
+Lcom/android/okhttp/internal/http/HttpEngine;->combine(Lcom/android/okhttp/Headers;Lcom/android/okhttp/Headers;)Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/internal/http/HttpEngine;->connect()Lcom/android/okhttp/internal/http/HttpStream;
+Lcom/android/okhttp/internal/http/HttpEngine;->createAddress(Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/Request;)Lcom/android/okhttp/Address;
+Lcom/android/okhttp/internal/http/HttpEngine;->EMPTY_BODY:Lcom/android/okhttp/ResponseBody;
+Lcom/android/okhttp/internal/http/HttpEngine;->followUpRequest()Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/HttpEngine;->forWebSocket:Z
+Lcom/android/okhttp/internal/http/HttpEngine;->getBufferedRequestBody()Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/internal/http/HttpEngine;->getRequest()Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/HttpEngine;->getRequestBody()Lcom/android/okhttp/okio/Sink;
+Lcom/android/okhttp/internal/http/HttpEngine;->getResponse()Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/HttpEngine;->hasBody(Lcom/android/okhttp/Response;)Z
+Lcom/android/okhttp/internal/http/HttpEngine;->MAX_FOLLOW_UPS:I
+Lcom/android/okhttp/internal/http/HttpEngine;->maybeCache()V
+Lcom/android/okhttp/internal/http/HttpEngine;->permitsRequestBody(Lcom/android/okhttp/Request;)Z
+Lcom/android/okhttp/internal/http/HttpEngine;->readNetworkResponse()Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/HttpEngine;->receiveHeaders(Lcom/android/okhttp/Headers;)V
+Lcom/android/okhttp/internal/http/HttpEngine;->recover(Lcom/android/okhttp/internal/http/RouteException;)Lcom/android/okhttp/internal/http/HttpEngine;
+Lcom/android/okhttp/internal/http/HttpEngine;->recover(Ljava/io/IOException;)Lcom/android/okhttp/internal/http/HttpEngine;
+Lcom/android/okhttp/internal/http/HttpEngine;->recover(Ljava/io/IOException;Lcom/android/okhttp/okio/Sink;)Lcom/android/okhttp/internal/http/HttpEngine;
+Lcom/android/okhttp/internal/http/HttpEngine;->releaseStreamAllocation()V
+Lcom/android/okhttp/internal/http/HttpEngine;->requestBodyOut:Lcom/android/okhttp/okio/Sink;
+Lcom/android/okhttp/internal/http/HttpEngine;->sameConnection(Lcom/android/okhttp/HttpUrl;)Z
+Lcom/android/okhttp/internal/http/HttpEngine;->storeRequest:Lcom/android/okhttp/internal/http/CacheRequest;
+Lcom/android/okhttp/internal/http/HttpEngine;->streamAllocation:Lcom/android/okhttp/internal/http/StreamAllocation;
+Lcom/android/okhttp/internal/http/HttpEngine;->stripBody(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/HttpEngine;->transparentGzip:Z
+Lcom/android/okhttp/internal/http/HttpEngine;->unzip(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/HttpEngine;->userRequest:Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/HttpEngine;->validate(Lcom/android/okhttp/Response;Lcom/android/okhttp/Response;)Z
+Lcom/android/okhttp/internal/http/HttpStream;->cancel()V
+Lcom/android/okhttp/internal/http/HttpStream;->createRequestBody(Lcom/android/okhttp/Request;J)Lcom/android/okhttp/okio/Sink;
+Lcom/android/okhttp/internal/http/HttpStream;->DISCARD_STREAM_TIMEOUT_MILLIS:I
+Lcom/android/okhttp/internal/http/HttpStream;->finishRequest()V
+Lcom/android/okhttp/internal/http/HttpStream;->openResponseBody(Lcom/android/okhttp/Response;)Lcom/android/okhttp/ResponseBody;
+Lcom/android/okhttp/internal/http/HttpStream;->readResponseHeaders()Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/internal/http/HttpStream;->setHttpEngine(Lcom/android/okhttp/internal/http/HttpEngine;)V
+Lcom/android/okhttp/internal/http/HttpStream;->writeRequestBody(Lcom/android/okhttp/internal/http/RetryableSink;)V
+Lcom/android/okhttp/internal/http/HttpStream;->writeRequestHeaders(Lcom/android/okhttp/Request;)V
+Lcom/android/okhttp/internal/http/RequestException;-><init>(Ljava/io/IOException;)V
+Lcom/android/okhttp/internal/http/RetryableSink;-><init>()V
+Lcom/android/okhttp/internal/http/RetryableSink;-><init>(I)V
+Lcom/android/okhttp/internal/http/RetryableSink;->closed:Z
+Lcom/android/okhttp/internal/http/RetryableSink;->content:Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/internal/http/RetryableSink;->contentLength()J
+Lcom/android/okhttp/internal/http/RetryableSink;->limit:I
+Lcom/android/okhttp/internal/http/RetryableSink;->timeout()Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/internal/http/RetryableSink;->write(Lcom/android/okhttp/okio/Buffer;J)V
+Lcom/android/okhttp/internal/http/RetryableSink;->writeToSocket(Lcom/android/okhttp/okio/Sink;)V
+Lcom/android/okhttp/internal/http/RouteException;-><init>(Ljava/io/IOException;)V
+Lcom/android/okhttp/internal/http/RouteException;->addConnectException(Ljava/io/IOException;)V
+Lcom/android/okhttp/internal/http/RouteException;->addSuppressedExceptionMethod:Ljava/lang/reflect/Method;
+Lcom/android/okhttp/internal/http/RouteException;->addSuppressedIfPossible(Ljava/io/IOException;Ljava/io/IOException;)V
+Lcom/android/okhttp/internal/http/RouteException;->getLastConnectException()Ljava/io/IOException;
+Lcom/android/okhttp/internal/http/RouteException;->lastException:Ljava/io/IOException;
+Lcom/android/okhttp/internal/http/RouteSelector;-><init>(Lcom/android/okhttp/Address;Lcom/android/okhttp/internal/RouteDatabase;)V
+Lcom/android/okhttp/internal/http/RouteSelector;->address:Lcom/android/okhttp/Address;
+Lcom/android/okhttp/internal/http/RouteSelector;->connectFailed(Lcom/android/okhttp/Route;Ljava/io/IOException;)V
+Lcom/android/okhttp/internal/http/RouteSelector;->getHostString(Ljava/net/InetSocketAddress;)Ljava/lang/String;
+Lcom/android/okhttp/internal/http/RouteSelector;->hasNextInetSocketAddress()Z
+Lcom/android/okhttp/internal/http/RouteSelector;->hasNextPostponed()Z
+Lcom/android/okhttp/internal/http/RouteSelector;->hasNextProxy()Z
+Lcom/android/okhttp/internal/http/RouteSelector;->inetSocketAddresses:Ljava/util/List;
+Lcom/android/okhttp/internal/http/RouteSelector;->lastInetSocketAddress:Ljava/net/InetSocketAddress;
+Lcom/android/okhttp/internal/http/RouteSelector;->lastProxy:Ljava/net/Proxy;
+Lcom/android/okhttp/internal/http/RouteSelector;->next()Lcom/android/okhttp/Route;
+Lcom/android/okhttp/internal/http/RouteSelector;->nextInetSocketAddress()Ljava/net/InetSocketAddress;
+Lcom/android/okhttp/internal/http/RouteSelector;->nextInetSocketAddressIndex:I
+Lcom/android/okhttp/internal/http/RouteSelector;->nextPostponed()Lcom/android/okhttp/Route;
+Lcom/android/okhttp/internal/http/RouteSelector;->nextProxy()Ljava/net/Proxy;
+Lcom/android/okhttp/internal/http/RouteSelector;->nextProxyIndex:I
+Lcom/android/okhttp/internal/http/RouteSelector;->postponedRoutes:Ljava/util/List;
+Lcom/android/okhttp/internal/http/RouteSelector;->proxies:Ljava/util/List;
+Lcom/android/okhttp/internal/http/RouteSelector;->resetNextInetSocketAddress(Ljava/net/Proxy;)V
+Lcom/android/okhttp/internal/http/RouteSelector;->resetNextProxy(Lcom/android/okhttp/HttpUrl;Ljava/net/Proxy;)V
+Lcom/android/okhttp/internal/http/RouteSelector;->routeDatabase:Lcom/android/okhttp/internal/RouteDatabase;
+Lcom/android/okhttp/internal/http/StreamAllocation;-><init>(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/Address;)V
+Lcom/android/okhttp/internal/http/StreamAllocation;->acquire(Lcom/android/okhttp/internal/io/RealConnection;)V
+Lcom/android/okhttp/internal/http/StreamAllocation;->address:Lcom/android/okhttp/Address;
+Lcom/android/okhttp/internal/http/StreamAllocation;->cancel()V
+Lcom/android/okhttp/internal/http/StreamAllocation;->canceled:Z
+Lcom/android/okhttp/internal/http/StreamAllocation;->connection()Lcom/android/okhttp/internal/io/RealConnection;
+Lcom/android/okhttp/internal/http/StreamAllocation;->connection:Lcom/android/okhttp/internal/io/RealConnection;
+Lcom/android/okhttp/internal/http/StreamAllocation;->connectionFailed()V
+Lcom/android/okhttp/internal/http/StreamAllocation;->connectionFailed(Ljava/io/IOException;)V
+Lcom/android/okhttp/internal/http/StreamAllocation;->connectionPool:Lcom/android/okhttp/ConnectionPool;
+Lcom/android/okhttp/internal/http/StreamAllocation;->deallocate(ZZZ)V
+Lcom/android/okhttp/internal/http/StreamAllocation;->findConnection(IIIZ)Lcom/android/okhttp/internal/io/RealConnection;
+Lcom/android/okhttp/internal/http/StreamAllocation;->findHealthyConnection(IIIZZ)Lcom/android/okhttp/internal/io/RealConnection;
+Lcom/android/okhttp/internal/http/StreamAllocation;->isRecoverable(Lcom/android/okhttp/internal/http/RouteException;)Z
+Lcom/android/okhttp/internal/http/StreamAllocation;->isRecoverable(Ljava/io/IOException;)Z
+Lcom/android/okhttp/internal/http/StreamAllocation;->newStream(IIIZZ)Lcom/android/okhttp/internal/http/HttpStream;
+Lcom/android/okhttp/internal/http/StreamAllocation;->noNewStreams()V
+Lcom/android/okhttp/internal/http/StreamAllocation;->recover(Lcom/android/okhttp/internal/http/RouteException;)Z
+Lcom/android/okhttp/internal/http/StreamAllocation;->recover(Ljava/io/IOException;Lcom/android/okhttp/okio/Sink;)Z
+Lcom/android/okhttp/internal/http/StreamAllocation;->release()V
+Lcom/android/okhttp/internal/http/StreamAllocation;->release(Lcom/android/okhttp/internal/io/RealConnection;)V
+Lcom/android/okhttp/internal/http/StreamAllocation;->released:Z
+Lcom/android/okhttp/internal/http/StreamAllocation;->routeDatabase()Lcom/android/okhttp/internal/RouteDatabase;
+Lcom/android/okhttp/internal/http/StreamAllocation;->routeSelector:Lcom/android/okhttp/internal/http/RouteSelector;
+Lcom/android/okhttp/internal/http/StreamAllocation;->stream()Lcom/android/okhttp/internal/http/HttpStream;
+Lcom/android/okhttp/internal/http/StreamAllocation;->stream:Lcom/android/okhttp/internal/http/HttpStream;
+Lcom/android/okhttp/internal/http/StreamAllocation;->streamFinished(Lcom/android/okhttp/internal/http/HttpStream;)V
+Lcom/android/okhttp/MediaType;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/okhttp/MediaType;->charset()Ljava/nio/charset/Charset;
+Lcom/android/okhttp/MediaType;->charset(Ljava/nio/charset/Charset;)Ljava/nio/charset/Charset;
+Lcom/android/okhttp/MediaType;->charset:Ljava/lang/String;
+Lcom/android/okhttp/MediaType;->mediaType:Ljava/lang/String;
+Lcom/android/okhttp/MediaType;->PARAMETER:Ljava/util/regex/Pattern;
+Lcom/android/okhttp/MediaType;->parse(Ljava/lang/String;)Lcom/android/okhttp/MediaType;
+Lcom/android/okhttp/MediaType;->QUOTED:Ljava/lang/String;
+Lcom/android/okhttp/MediaType;->subtype()Ljava/lang/String;
+Lcom/android/okhttp/MediaType;->subtype:Ljava/lang/String;
+Lcom/android/okhttp/MediaType;->TOKEN:Ljava/lang/String;
+Lcom/android/okhttp/MediaType;->type()Ljava/lang/String;
+Lcom/android/okhttp/MediaType;->type:Ljava/lang/String;
+Lcom/android/okhttp/MediaType;->TYPE_SUBTYPE:Ljava/util/regex/Pattern;
+Lcom/android/okhttp/OkCacheContainer;->getCache()Lcom/android/okhttp/Cache;
+Lcom/android/okhttp/OkHttpClient;-><init>(Lcom/android/okhttp/OkHttpClient;)V
+Lcom/android/okhttp/OkHttpClient;->authenticator:Lcom/android/okhttp/Authenticator;
+Lcom/android/okhttp/OkHttpClient;->cache:Lcom/android/okhttp/Cache;
+Lcom/android/okhttp/OkHttpClient;->cancel(Ljava/lang/Object;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->certificatePinner:Lcom/android/okhttp/CertificatePinner;
+Lcom/android/okhttp/OkHttpClient;->connectionSpecs:Ljava/util/List;
+Lcom/android/okhttp/OkHttpClient;->connectTimeout:I
+Lcom/android/okhttp/OkHttpClient;->cookieHandler:Ljava/net/CookieHandler;
+Lcom/android/okhttp/OkHttpClient;->copyWithDefaults()Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->defaultSslSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
+Lcom/android/okhttp/OkHttpClient;->DEFAULT_CONNECTION_SPECS:Ljava/util/List;
+Lcom/android/okhttp/OkHttpClient;->dispatcher:Lcom/android/okhttp/Dispatcher;
+Lcom/android/okhttp/OkHttpClient;->followRedirects:Z
+Lcom/android/okhttp/OkHttpClient;->followSslRedirects:Z
+Lcom/android/okhttp/OkHttpClient;->getAuthenticator()Lcom/android/okhttp/Authenticator;
+Lcom/android/okhttp/OkHttpClient;->getCache()Lcom/android/okhttp/Cache;
+Lcom/android/okhttp/OkHttpClient;->getCertificatePinner()Lcom/android/okhttp/CertificatePinner;
+Lcom/android/okhttp/OkHttpClient;->getConnectionSpecs()Ljava/util/List;
+Lcom/android/okhttp/OkHttpClient;->getConnectTimeout()I
+Lcom/android/okhttp/OkHttpClient;->getDefaultSSLSocketFactory()Ljavax/net/ssl/SSLSocketFactory;
+Lcom/android/okhttp/OkHttpClient;->getDispatcher()Lcom/android/okhttp/Dispatcher;
+Lcom/android/okhttp/OkHttpClient;->getDns()Lcom/android/okhttp/Dns;
+Lcom/android/okhttp/OkHttpClient;->getFollowRedirects()Z
+Lcom/android/okhttp/OkHttpClient;->getFollowSslRedirects()Z
+Lcom/android/okhttp/OkHttpClient;->getProtocols()Ljava/util/List;
+Lcom/android/okhttp/OkHttpClient;->getReadTimeout()I
+Lcom/android/okhttp/OkHttpClient;->getRetryOnConnectionFailure()Z
+Lcom/android/okhttp/OkHttpClient;->getSocketFactory()Ljavax/net/SocketFactory;
+Lcom/android/okhttp/OkHttpClient;->getWriteTimeout()I
+Lcom/android/okhttp/OkHttpClient;->hostnameVerifier:Ljavax/net/ssl/HostnameVerifier;
+Lcom/android/okhttp/OkHttpClient;->interceptors()Ljava/util/List;
+Lcom/android/okhttp/OkHttpClient;->interceptors:Ljava/util/List;
+Lcom/android/okhttp/OkHttpClient;->internalCache()Lcom/android/okhttp/internal/InternalCache;
+Lcom/android/okhttp/OkHttpClient;->internalCache:Lcom/android/okhttp/internal/InternalCache;
+Lcom/android/okhttp/OkHttpClient;->networkInterceptors()Ljava/util/List;
+Lcom/android/okhttp/OkHttpClient;->networkInterceptors:Ljava/util/List;
+Lcom/android/okhttp/OkHttpClient;->newCall(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Call;
+Lcom/android/okhttp/OkHttpClient;->protocols:Ljava/util/List;
+Lcom/android/okhttp/OkHttpClient;->proxy:Ljava/net/Proxy;
+Lcom/android/okhttp/OkHttpClient;->proxySelector:Ljava/net/ProxySelector;
+Lcom/android/okhttp/OkHttpClient;->readTimeout:I
+Lcom/android/okhttp/OkHttpClient;->retryOnConnectionFailure:Z
+Lcom/android/okhttp/OkHttpClient;->routeDatabase()Lcom/android/okhttp/internal/RouteDatabase;
+Lcom/android/okhttp/OkHttpClient;->routeDatabase:Lcom/android/okhttp/internal/RouteDatabase;
+Lcom/android/okhttp/OkHttpClient;->setAuthenticator(Lcom/android/okhttp/Authenticator;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setCache(Lcom/android/okhttp/Cache;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setCertificatePinner(Lcom/android/okhttp/CertificatePinner;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setConnectionPool(Lcom/android/okhttp/ConnectionPool;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setConnectionSpecs(Ljava/util/List;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setConnectTimeout(JLjava/util/concurrent/TimeUnit;)V
+Lcom/android/okhttp/OkHttpClient;->setCookieHandler(Ljava/net/CookieHandler;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setDispatcher(Lcom/android/okhttp/Dispatcher;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setDns(Lcom/android/okhttp/Dns;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setFollowRedirects(Z)V
+Lcom/android/okhttp/OkHttpClient;->setFollowSslRedirects(Z)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setHostnameVerifier(Ljavax/net/ssl/HostnameVerifier;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setInternalCache(Lcom/android/okhttp/internal/InternalCache;)V
+Lcom/android/okhttp/OkHttpClient;->setProxy(Ljava/net/Proxy;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setProxySelector(Ljava/net/ProxySelector;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setReadTimeout(JLjava/util/concurrent/TimeUnit;)V
+Lcom/android/okhttp/OkHttpClient;->setSocketFactory(Ljavax/net/SocketFactory;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setSslSocketFactory(Ljavax/net/ssl/SSLSocketFactory;)Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient;->setWriteTimeout(JLjava/util/concurrent/TimeUnit;)V
+Lcom/android/okhttp/OkHttpClient;->socketFactory:Ljavax/net/SocketFactory;
+Lcom/android/okhttp/OkHttpClient;->sslSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
+Lcom/android/okhttp/OkHttpClient;->writeTimeout:I
+Lcom/android/okhttp/okio/AsyncTimeout$Watchdog;-><init>()V
+Lcom/android/okhttp/okio/AsyncTimeout;-><init>()V
+Lcom/android/okhttp/okio/AsyncTimeout;->awaitTimeout()Lcom/android/okhttp/okio/AsyncTimeout;
+Lcom/android/okhttp/okio/AsyncTimeout;->cancelScheduledTimeout(Lcom/android/okhttp/okio/AsyncTimeout;)Z
+Lcom/android/okhttp/okio/AsyncTimeout;->enter()V
+Lcom/android/okhttp/okio/AsyncTimeout;->exit()Z
+Lcom/android/okhttp/okio/AsyncTimeout;->exit(Ljava/io/IOException;)Ljava/io/IOException;
+Lcom/android/okhttp/okio/AsyncTimeout;->exit(Z)V
+Lcom/android/okhttp/okio/AsyncTimeout;->head:Lcom/android/okhttp/okio/AsyncTimeout;
+Lcom/android/okhttp/okio/AsyncTimeout;->inQueue:Z
+Lcom/android/okhttp/okio/AsyncTimeout;->newTimeoutException(Ljava/io/IOException;)Ljava/io/IOException;
+Lcom/android/okhttp/okio/AsyncTimeout;->next:Lcom/android/okhttp/okio/AsyncTimeout;
+Lcom/android/okhttp/okio/AsyncTimeout;->remainingNanos(J)J
+Lcom/android/okhttp/okio/AsyncTimeout;->scheduleTimeout(Lcom/android/okhttp/okio/AsyncTimeout;JZ)V
+Lcom/android/okhttp/okio/AsyncTimeout;->sink(Lcom/android/okhttp/okio/Sink;)Lcom/android/okhttp/okio/Sink;
+Lcom/android/okhttp/okio/AsyncTimeout;->source(Lcom/android/okhttp/okio/Source;)Lcom/android/okhttp/okio/Source;
+Lcom/android/okhttp/okio/AsyncTimeout;->timedOut()V
+Lcom/android/okhttp/okio/AsyncTimeout;->timeoutAt:J
+Lcom/android/okhttp/okio/Buffer;-><init>()V
+Lcom/android/okhttp/okio/Buffer;->buffer()Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->clear()V
+Lcom/android/okhttp/okio/Buffer;->completeSegmentByteCount()J
+Lcom/android/okhttp/okio/Buffer;->copyTo(Lcom/android/okhttp/okio/Buffer;JJ)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->copyTo(Ljava/io/OutputStream;)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->copyTo(Ljava/io/OutputStream;JJ)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->DIGITS:[B
+Lcom/android/okhttp/okio/Buffer;->emit()Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->emitCompleteSegments()Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->emitCompleteSegments()Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->exhausted()Z
+Lcom/android/okhttp/okio/Buffer;->getByte(J)B
+Lcom/android/okhttp/okio/Buffer;->head:Lcom/android/okhttp/okio/Segment;
+Lcom/android/okhttp/okio/Buffer;->indexOf(B)J
+Lcom/android/okhttp/okio/Buffer;->indexOf(BJ)J
+Lcom/android/okhttp/okio/Buffer;->indexOf(Lcom/android/okhttp/okio/ByteString;)J
+Lcom/android/okhttp/okio/Buffer;->indexOf(Lcom/android/okhttp/okio/ByteString;J)J
+Lcom/android/okhttp/okio/Buffer;->indexOfElement(Lcom/android/okhttp/okio/ByteString;)J
+Lcom/android/okhttp/okio/Buffer;->indexOfElement(Lcom/android/okhttp/okio/ByteString;J)J
+Lcom/android/okhttp/okio/Buffer;->inputStream()Ljava/io/InputStream;
+Lcom/android/okhttp/okio/Buffer;->outputStream()Ljava/io/OutputStream;
+Lcom/android/okhttp/okio/Buffer;->rangeEquals(JLcom/android/okhttp/okio/ByteString;)Z
+Lcom/android/okhttp/okio/Buffer;->read(Lcom/android/okhttp/okio/Buffer;J)J
+Lcom/android/okhttp/okio/Buffer;->read([B)I
+Lcom/android/okhttp/okio/Buffer;->read([BII)I
+Lcom/android/okhttp/okio/Buffer;->readAll(Lcom/android/okhttp/okio/Sink;)J
+Lcom/android/okhttp/okio/Buffer;->readByte()B
+Lcom/android/okhttp/okio/Buffer;->readByteArray()[B
+Lcom/android/okhttp/okio/Buffer;->readByteArray(J)[B
+Lcom/android/okhttp/okio/Buffer;->readByteString()Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/Buffer;->readByteString(J)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/Buffer;->readDecimalLong()J
+Lcom/android/okhttp/okio/Buffer;->readFrom(Ljava/io/InputStream;)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->readFrom(Ljava/io/InputStream;J)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->readFrom(Ljava/io/InputStream;JZ)V
+Lcom/android/okhttp/okio/Buffer;->readFully(Lcom/android/okhttp/okio/Buffer;J)V
+Lcom/android/okhttp/okio/Buffer;->readFully([B)V
+Lcom/android/okhttp/okio/Buffer;->readHexadecimalUnsignedLong()J
+Lcom/android/okhttp/okio/Buffer;->readInt()I
+Lcom/android/okhttp/okio/Buffer;->readIntLe()I
+Lcom/android/okhttp/okio/Buffer;->readLong()J
+Lcom/android/okhttp/okio/Buffer;->readLongLe()J
+Lcom/android/okhttp/okio/Buffer;->readShort()S
+Lcom/android/okhttp/okio/Buffer;->readShortLe()S
+Lcom/android/okhttp/okio/Buffer;->readString(JLjava/nio/charset/Charset;)Ljava/lang/String;
+Lcom/android/okhttp/okio/Buffer;->readString(Ljava/nio/charset/Charset;)Ljava/lang/String;
+Lcom/android/okhttp/okio/Buffer;->readUtf8()Ljava/lang/String;
+Lcom/android/okhttp/okio/Buffer;->readUtf8(J)Ljava/lang/String;
+Lcom/android/okhttp/okio/Buffer;->readUtf8CodePoint()I
+Lcom/android/okhttp/okio/Buffer;->readUtf8Line()Ljava/lang/String;
+Lcom/android/okhttp/okio/Buffer;->readUtf8Line(J)Ljava/lang/String;
+Lcom/android/okhttp/okio/Buffer;->readUtf8LineStrict()Ljava/lang/String;
+Lcom/android/okhttp/okio/Buffer;->REPLACEMENT_CHARACTER:I
+Lcom/android/okhttp/okio/Buffer;->request(J)Z
+Lcom/android/okhttp/okio/Buffer;->require(J)V
+Lcom/android/okhttp/okio/Buffer;->segmentSizes()Ljava/util/List;
+Lcom/android/okhttp/okio/Buffer;->size()J
+Lcom/android/okhttp/okio/Buffer;->size:J
+Lcom/android/okhttp/okio/Buffer;->skip(J)V
+Lcom/android/okhttp/okio/Buffer;->snapshot()Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/Buffer;->snapshot(I)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/Buffer;->timeout()Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Buffer;->writableSegment(I)Lcom/android/okhttp/okio/Segment;
+Lcom/android/okhttp/okio/Buffer;->write(Lcom/android/okhttp/okio/Buffer;J)V
+Lcom/android/okhttp/okio/Buffer;->write(Lcom/android/okhttp/okio/ByteString;)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->write(Lcom/android/okhttp/okio/ByteString;)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->write(Lcom/android/okhttp/okio/Source;J)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->write([B)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->write([B)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->write([BII)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->write([BII)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeAll(Lcom/android/okhttp/okio/Source;)J
+Lcom/android/okhttp/okio/Buffer;->writeByte(I)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeByte(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeDecimalLong(J)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeDecimalLong(J)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeHexadecimalUnsignedLong(J)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeHexadecimalUnsignedLong(J)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeInt(I)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeInt(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeIntLe(I)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeIntLe(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeLong(J)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeLong(J)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeLongLe(J)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeLongLe(J)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeShort(I)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeShort(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeShortLe(I)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeShortLe(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeString(Ljava/lang/String;IILjava/nio/charset/Charset;)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeString(Ljava/lang/String;IILjava/nio/charset/Charset;)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeString(Ljava/lang/String;Ljava/nio/charset/Charset;)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeString(Ljava/lang/String;Ljava/nio/charset/Charset;)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeTo(Ljava/io/OutputStream;)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeTo(Ljava/io/OutputStream;J)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeUtf8(Ljava/lang/String;)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeUtf8(Ljava/lang/String;)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeUtf8(Ljava/lang/String;II)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeUtf8(Ljava/lang/String;II)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/Buffer;->writeUtf8CodePoint(I)Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/Buffer;->writeUtf8CodePoint(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->buffer()Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/BufferedSink;->emit()Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->emitCompleteSegments()Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->outputStream()Ljava/io/OutputStream;
+Lcom/android/okhttp/okio/BufferedSink;->write(Lcom/android/okhttp/okio/ByteString;)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->write(Lcom/android/okhttp/okio/Source;J)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->write([B)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->write([BII)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeAll(Lcom/android/okhttp/okio/Source;)J
+Lcom/android/okhttp/okio/BufferedSink;->writeByte(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeDecimalLong(J)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeHexadecimalUnsignedLong(J)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeInt(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeIntLe(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeLong(J)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeLongLe(J)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeShort(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeShortLe(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeString(Ljava/lang/String;IILjava/nio/charset/Charset;)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeString(Ljava/lang/String;Ljava/nio/charset/Charset;)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeUtf8(Ljava/lang/String;)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeUtf8(Ljava/lang/String;II)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSink;->writeUtf8CodePoint(I)Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSource;->buffer()Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/BufferedSource;->exhausted()Z
+Lcom/android/okhttp/okio/BufferedSource;->indexOf(B)J
+Lcom/android/okhttp/okio/BufferedSource;->indexOf(BJ)J
+Lcom/android/okhttp/okio/BufferedSource;->indexOf(Lcom/android/okhttp/okio/ByteString;)J
+Lcom/android/okhttp/okio/BufferedSource;->indexOf(Lcom/android/okhttp/okio/ByteString;J)J
+Lcom/android/okhttp/okio/BufferedSource;->indexOfElement(Lcom/android/okhttp/okio/ByteString;)J
+Lcom/android/okhttp/okio/BufferedSource;->indexOfElement(Lcom/android/okhttp/okio/ByteString;J)J
+Lcom/android/okhttp/okio/BufferedSource;->inputStream()Ljava/io/InputStream;
+Lcom/android/okhttp/okio/BufferedSource;->read([B)I
+Lcom/android/okhttp/okio/BufferedSource;->read([BII)I
+Lcom/android/okhttp/okio/BufferedSource;->readAll(Lcom/android/okhttp/okio/Sink;)J
+Lcom/android/okhttp/okio/BufferedSource;->readByte()B
+Lcom/android/okhttp/okio/BufferedSource;->readByteArray()[B
+Lcom/android/okhttp/okio/BufferedSource;->readByteArray(J)[B
+Lcom/android/okhttp/okio/BufferedSource;->readByteString()Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/BufferedSource;->readByteString(J)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/BufferedSource;->readDecimalLong()J
+Lcom/android/okhttp/okio/BufferedSource;->readFully(Lcom/android/okhttp/okio/Buffer;J)V
+Lcom/android/okhttp/okio/BufferedSource;->readFully([B)V
+Lcom/android/okhttp/okio/BufferedSource;->readHexadecimalUnsignedLong()J
+Lcom/android/okhttp/okio/BufferedSource;->readInt()I
+Lcom/android/okhttp/okio/BufferedSource;->readIntLe()I
+Lcom/android/okhttp/okio/BufferedSource;->readLong()J
+Lcom/android/okhttp/okio/BufferedSource;->readLongLe()J
+Lcom/android/okhttp/okio/BufferedSource;->readShort()S
+Lcom/android/okhttp/okio/BufferedSource;->readShortLe()S
+Lcom/android/okhttp/okio/BufferedSource;->readString(JLjava/nio/charset/Charset;)Ljava/lang/String;
+Lcom/android/okhttp/okio/BufferedSource;->readString(Ljava/nio/charset/Charset;)Ljava/lang/String;
+Lcom/android/okhttp/okio/BufferedSource;->readUtf8()Ljava/lang/String;
+Lcom/android/okhttp/okio/BufferedSource;->readUtf8(J)Ljava/lang/String;
+Lcom/android/okhttp/okio/BufferedSource;->readUtf8CodePoint()I
+Lcom/android/okhttp/okio/BufferedSource;->readUtf8Line()Ljava/lang/String;
+Lcom/android/okhttp/okio/BufferedSource;->readUtf8LineStrict()Ljava/lang/String;
+Lcom/android/okhttp/okio/BufferedSource;->request(J)Z
+Lcom/android/okhttp/okio/BufferedSource;->require(J)V
+Lcom/android/okhttp/okio/BufferedSource;->skip(J)V
+Lcom/android/okhttp/okio/ByteString;-><init>([B)V
+Lcom/android/okhttp/okio/ByteString;->base64()Ljava/lang/String;
+Lcom/android/okhttp/okio/ByteString;->base64Url()Ljava/lang/String;
+Lcom/android/okhttp/okio/ByteString;->compareTo(Lcom/android/okhttp/okio/ByteString;)I
+Lcom/android/okhttp/okio/ByteString;->compareTo(Ljava/lang/Object;)I
+Lcom/android/okhttp/okio/ByteString;->data:[B
+Lcom/android/okhttp/okio/ByteString;->decodeBase64(Ljava/lang/String;)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->decodeHex(Ljava/lang/String;)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->decodeHexDigit(C)I
+Lcom/android/okhttp/okio/ByteString;->digest(Ljava/lang/String;)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->EMPTY:Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->encodeUtf8(Ljava/lang/String;)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->getByte(I)B
+Lcom/android/okhttp/okio/ByteString;->hashCode:I
+Lcom/android/okhttp/okio/ByteString;->hex()Ljava/lang/String;
+Lcom/android/okhttp/okio/ByteString;->HEX_DIGITS:[C
+Lcom/android/okhttp/okio/ByteString;->md5()Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->of([BII)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->rangeEquals(ILcom/android/okhttp/okio/ByteString;II)Z
+Lcom/android/okhttp/okio/ByteString;->rangeEquals(I[BII)Z
+Lcom/android/okhttp/okio/ByteString;->read(Ljava/io/InputStream;I)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->sha256()Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->size()I
+Lcom/android/okhttp/okio/ByteString;->substring(I)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->substring(II)Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->toAsciiLowercase()Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->toAsciiUppercase()Lcom/android/okhttp/okio/ByteString;
+Lcom/android/okhttp/okio/ByteString;->toByteArray()[B
+Lcom/android/okhttp/okio/ByteString;->utf8()Ljava/lang/String;
+Lcom/android/okhttp/okio/ByteString;->utf8:Ljava/lang/String;
+Lcom/android/okhttp/okio/ByteString;->write(Lcom/android/okhttp/okio/Buffer;)V
+Lcom/android/okhttp/okio/ByteString;->write(Ljava/io/OutputStream;)V
+Lcom/android/okhttp/okio/Segment;-><init>()V
+Lcom/android/okhttp/okio/Segment;-><init>(Lcom/android/okhttp/okio/Segment;)V
+Lcom/android/okhttp/okio/Segment;-><init>([BII)V
+Lcom/android/okhttp/okio/Segment;->compact()V
+Lcom/android/okhttp/okio/Segment;->data:[B
+Lcom/android/okhttp/okio/Segment;->limit:I
+Lcom/android/okhttp/okio/Segment;->next:Lcom/android/okhttp/okio/Segment;
+Lcom/android/okhttp/okio/Segment;->owner:Z
+Lcom/android/okhttp/okio/Segment;->pop()Lcom/android/okhttp/okio/Segment;
+Lcom/android/okhttp/okio/Segment;->pos:I
+Lcom/android/okhttp/okio/Segment;->prev:Lcom/android/okhttp/okio/Segment;
+Lcom/android/okhttp/okio/Segment;->push(Lcom/android/okhttp/okio/Segment;)Lcom/android/okhttp/okio/Segment;
+Lcom/android/okhttp/okio/Segment;->shared:Z
+Lcom/android/okhttp/okio/Segment;->SIZE:I
+Lcom/android/okhttp/okio/Segment;->split(I)Lcom/android/okhttp/okio/Segment;
+Lcom/android/okhttp/okio/Segment;->writeTo(Lcom/android/okhttp/okio/Segment;I)V
+Lcom/android/okhttp/okio/Sink;->timeout()Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Sink;->write(Lcom/android/okhttp/okio/Buffer;J)V
+Lcom/android/okhttp/okio/Source;->read(Lcom/android/okhttp/okio/Buffer;J)J
+Lcom/android/okhttp/okio/Source;->timeout()Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Timeout;-><init>()V
+Lcom/android/okhttp/okio/Timeout;->clearDeadline()Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Timeout;->clearTimeout()Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Timeout;->deadline(JLjava/util/concurrent/TimeUnit;)Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Timeout;->deadlineNanoTime()J
+Lcom/android/okhttp/okio/Timeout;->deadlineNanoTime(J)Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Timeout;->deadlineNanoTime:J
+Lcom/android/okhttp/okio/Timeout;->hasDeadline()Z
+Lcom/android/okhttp/okio/Timeout;->hasDeadline:Z
+Lcom/android/okhttp/okio/Timeout;->NONE:Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Timeout;->throwIfReached()V
+Lcom/android/okhttp/okio/Timeout;->timeout(JLjava/util/concurrent/TimeUnit;)Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Timeout;->timeoutNanos()J
+Lcom/android/okhttp/okio/Timeout;->timeoutNanos:J
+Lcom/android/okhttp/Protocol;->get(Ljava/lang/String;)Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Protocol;->HTTP_1_0:Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Protocol;->HTTP_1_1:Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Protocol;->HTTP_2:Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Protocol;->protocol:Ljava/lang/String;
+Lcom/android/okhttp/Protocol;->SPDY_3:Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Protocol;->valueOf(Ljava/lang/String;)Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Protocol;->values()[Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Request$Builder;-><init>()V
+Lcom/android/okhttp/Request$Builder;-><init>(Lcom/android/okhttp/Request;)V
+Lcom/android/okhttp/Request$Builder;->addHeader(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->body:Lcom/android/okhttp/RequestBody;
+Lcom/android/okhttp/Request$Builder;->build()Lcom/android/okhttp/Request;
+Lcom/android/okhttp/Request$Builder;->cacheControl(Lcom/android/okhttp/CacheControl;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->delete()Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->delete(Lcom/android/okhttp/RequestBody;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->get()Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->head()Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->header(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->headers(Lcom/android/okhttp/Headers;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->headers:Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/Request$Builder;->method(Ljava/lang/String;Lcom/android/okhttp/RequestBody;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->method:Ljava/lang/String;
+Lcom/android/okhttp/Request$Builder;->patch(Lcom/android/okhttp/RequestBody;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->post(Lcom/android/okhttp/RequestBody;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->put(Lcom/android/okhttp/RequestBody;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->removeHeader(Ljava/lang/String;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->tag(Ljava/lang/Object;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->tag:Ljava/lang/Object;
+Lcom/android/okhttp/Request$Builder;->url(Lcom/android/okhttp/HttpUrl;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->url(Ljava/lang/String;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->url(Ljava/net/URL;)Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request$Builder;->url:Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/Request;-><init>(Lcom/android/okhttp/Request$Builder;)V
+Lcom/android/okhttp/Request;->body()Lcom/android/okhttp/RequestBody;
+Lcom/android/okhttp/Request;->body:Lcom/android/okhttp/RequestBody;
+Lcom/android/okhttp/Request;->cacheControl()Lcom/android/okhttp/CacheControl;
+Lcom/android/okhttp/Request;->cacheControl:Lcom/android/okhttp/CacheControl;
+Lcom/android/okhttp/Request;->header(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/okhttp/Request;->headers()Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Request;->headers(Ljava/lang/String;)Ljava/util/List;
+Lcom/android/okhttp/Request;->httpUrl()Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/Request;->isHttps()Z
+Lcom/android/okhttp/Request;->javaNetUri:Ljava/net/URI;
+Lcom/android/okhttp/Request;->javaNetUrl:Ljava/net/URL;
+Lcom/android/okhttp/Request;->method()Ljava/lang/String;
+Lcom/android/okhttp/Request;->newBuilder()Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Request;->tag()Ljava/lang/Object;
+Lcom/android/okhttp/Request;->tag:Ljava/lang/Object;
+Lcom/android/okhttp/Request;->uri()Ljava/net/URI;
+Lcom/android/okhttp/Request;->url()Ljava/net/URL;
+Lcom/android/okhttp/Request;->urlString()Ljava/lang/String;
+Lcom/android/okhttp/RequestBody;-><init>()V
+Lcom/android/okhttp/RequestBody;->contentLength()J
+Lcom/android/okhttp/RequestBody;->contentType()Lcom/android/okhttp/MediaType;
+Lcom/android/okhttp/RequestBody;->create(Lcom/android/okhttp/MediaType;Lcom/android/okhttp/okio/ByteString;)Lcom/android/okhttp/RequestBody;
+Lcom/android/okhttp/RequestBody;->create(Lcom/android/okhttp/MediaType;Ljava/io/File;)Lcom/android/okhttp/RequestBody;
+Lcom/android/okhttp/RequestBody;->create(Lcom/android/okhttp/MediaType;Ljava/lang/String;)Lcom/android/okhttp/RequestBody;
+Lcom/android/okhttp/RequestBody;->create(Lcom/android/okhttp/MediaType;[B)Lcom/android/okhttp/RequestBody;
+Lcom/android/okhttp/RequestBody;->create(Lcom/android/okhttp/MediaType;[BII)Lcom/android/okhttp/RequestBody;
+Lcom/android/okhttp/RequestBody;->writeTo(Lcom/android/okhttp/okio/BufferedSink;)V
+Lcom/android/okhttp/Response$Builder;-><init>()V
+Lcom/android/okhttp/Response$Builder;-><init>(Lcom/android/okhttp/Response;)V
+Lcom/android/okhttp/Response$Builder;->addHeader(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->body(Lcom/android/okhttp/ResponseBody;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->body:Lcom/android/okhttp/ResponseBody;
+Lcom/android/okhttp/Response$Builder;->build()Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response$Builder;->cacheResponse(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->cacheResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response$Builder;->checkPriorResponse(Lcom/android/okhttp/Response;)V
+Lcom/android/okhttp/Response$Builder;->checkSupportResponse(Ljava/lang/String;Lcom/android/okhttp/Response;)V
+Lcom/android/okhttp/Response$Builder;->code(I)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->code:I
+Lcom/android/okhttp/Response$Builder;->handshake(Lcom/android/okhttp/Handshake;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->handshake:Lcom/android/okhttp/Handshake;
+Lcom/android/okhttp/Response$Builder;->header(Ljava/lang/String;Ljava/lang/String;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->headers(Lcom/android/okhttp/Headers;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->headers:Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/Response$Builder;->message(Ljava/lang/String;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->message:Ljava/lang/String;
+Lcom/android/okhttp/Response$Builder;->networkResponse(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->networkResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response$Builder;->priorResponse(Lcom/android/okhttp/Response;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->priorResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response$Builder;->protocol(Lcom/android/okhttp/Protocol;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->protocol:Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Response$Builder;->removeHeader(Ljava/lang/String;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->request(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response$Builder;->request:Lcom/android/okhttp/Request;
+Lcom/android/okhttp/Response;-><init>(Lcom/android/okhttp/Response$Builder;)V
+Lcom/android/okhttp/Response;->body()Lcom/android/okhttp/ResponseBody;
+Lcom/android/okhttp/Response;->body:Lcom/android/okhttp/ResponseBody;
+Lcom/android/okhttp/Response;->cacheControl()Lcom/android/okhttp/CacheControl;
+Lcom/android/okhttp/Response;->cacheControl:Lcom/android/okhttp/CacheControl;
+Lcom/android/okhttp/Response;->cacheResponse()Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response;->cacheResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response;->challenges()Ljava/util/List;
+Lcom/android/okhttp/Response;->code()I
+Lcom/android/okhttp/Response;->handshake()Lcom/android/okhttp/Handshake;
+Lcom/android/okhttp/Response;->handshake:Lcom/android/okhttp/Handshake;
+Lcom/android/okhttp/Response;->header(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/okhttp/Response;->header(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/okhttp/Response;->headers()Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Response;->headers(Ljava/lang/String;)Ljava/util/List;
+Lcom/android/okhttp/Response;->isRedirect()Z
+Lcom/android/okhttp/Response;->isSuccessful()Z
+Lcom/android/okhttp/Response;->message()Ljava/lang/String;
+Lcom/android/okhttp/Response;->networkResponse()Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response;->newBuilder()Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Response;->priorResponse()Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response;->priorResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response;->protocol()Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Response;->request()Lcom/android/okhttp/Request;
+Lcom/android/okhttp/Response;->request:Lcom/android/okhttp/Request;
+Lcom/android/okhttp/ResponseBody;-><init>()V
+Lcom/android/okhttp/ResponseBody;->bytes()[B
+Lcom/android/okhttp/ResponseBody;->byteStream()Ljava/io/InputStream;
+Lcom/android/okhttp/ResponseBody;->charset()Ljava/nio/charset/Charset;
+Lcom/android/okhttp/ResponseBody;->charStream()Ljava/io/Reader;
+Lcom/android/okhttp/ResponseBody;->contentLength()J
+Lcom/android/okhttp/ResponseBody;->contentType()Lcom/android/okhttp/MediaType;
+Lcom/android/okhttp/ResponseBody;->create(Lcom/android/okhttp/MediaType;JLcom/android/okhttp/okio/BufferedSource;)Lcom/android/okhttp/ResponseBody;
+Lcom/android/okhttp/ResponseBody;->create(Lcom/android/okhttp/MediaType;Ljava/lang/String;)Lcom/android/okhttp/ResponseBody;
+Lcom/android/okhttp/ResponseBody;->create(Lcom/android/okhttp/MediaType;[B)Lcom/android/okhttp/ResponseBody;
+Lcom/android/okhttp/ResponseBody;->reader:Ljava/io/Reader;
+Lcom/android/okhttp/ResponseBody;->source()Lcom/android/okhttp/okio/BufferedSource;
+Lcom/android/okhttp/ResponseBody;->string()Ljava/lang/String;
+Lcom/android/okhttp/Route;-><init>(Lcom/android/okhttp/Address;Ljava/net/Proxy;Ljava/net/InetSocketAddress;)V
+Lcom/android/okhttp/Route;->address:Lcom/android/okhttp/Address;
+Lcom/android/okhttp/Route;->getAddress()Lcom/android/okhttp/Address;
+Lcom/android/okhttp/Route;->getProxy()Ljava/net/Proxy;
+Lcom/android/okhttp/Route;->getSocketAddress()Ljava/net/InetSocketAddress;
+Lcom/android/okhttp/Route;->inetSocketAddress:Ljava/net/InetSocketAddress;
+Lcom/android/okhttp/Route;->proxy:Ljava/net/Proxy;
+Lcom/android/okhttp/Route;->requiresTunnel()Z
+Lcom/android/okhttp/TlsVersion;->forJavaName(Ljava/lang/String;)Lcom/android/okhttp/TlsVersion;
+Lcom/android/okhttp/TlsVersion;->javaName()Ljava/lang/String;
+Lcom/android/okhttp/TlsVersion;->javaName:Ljava/lang/String;
+Lcom/android/okhttp/TlsVersion;->SSL_3_0:Lcom/android/okhttp/TlsVersion;
+Lcom/android/okhttp/TlsVersion;->TLS_1_0:Lcom/android/okhttp/TlsVersion;
+Lcom/android/okhttp/TlsVersion;->TLS_1_1:Lcom/android/okhttp/TlsVersion;
+Lcom/android/okhttp/TlsVersion;->TLS_1_2:Lcom/android/okhttp/TlsVersion;
+Lcom/android/okhttp/TlsVersion;->valueOf(Ljava/lang/String;)Lcom/android/okhttp/TlsVersion;
+Lcom/android/okhttp/TlsVersion;->values()[Lcom/android/okhttp/TlsVersion;
+Ldalvik/bytecode/OpcodeInfo;-><init>()V
+Ldalvik/bytecode/OpcodeInfo;->isInvoke(I)Z
+Ldalvik/system/AllocationLimitError;-><init>()V
+Ldalvik/system/AllocationLimitError;-><init>(Ljava/lang/String;)V
+Ldalvik/system/AnnotatedStackTraceElement;-><init>()V
+Ldalvik/system/AnnotatedStackTraceElement;->blockedOn:Ljava/lang/Object;
+Ldalvik/system/AnnotatedStackTraceElement;->getBlockedOn()Ljava/lang/Object;
+Ldalvik/system/AnnotatedStackTraceElement;->getHeldLocks()[Ljava/lang/Object;
+Ldalvik/system/AnnotatedStackTraceElement;->getStackTraceElement()Ljava/lang/StackTraceElement;
+Ldalvik/system/AnnotatedStackTraceElement;->heldLocks:[Ljava/lang/Object;
+Ldalvik/system/AnnotatedStackTraceElement;->stackTraceElement:Ljava/lang/StackTraceElement;
+Ldalvik/system/BaseDexClassLoader$Reporter;->report(Ljava/util/List;Ljava/util/List;)V
+Ldalvik/system/BaseDexClassLoader;-><init>([Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V
+Ldalvik/system/BaseDexClassLoader;->addNativePath(Ljava/util/Collection;)V
+Ldalvik/system/BaseDexClassLoader;->getReporter()Ldalvik/system/BaseDexClassLoader$Reporter;
+Ldalvik/system/BaseDexClassLoader;->reportClassLoaderChain()V
+Ldalvik/system/BaseDexClassLoader;->reporter:Ldalvik/system/BaseDexClassLoader$Reporter;
+Ldalvik/system/BaseDexClassLoader;->setReporter(Ldalvik/system/BaseDexClassLoader$Reporter;)V
+Ldalvik/system/BlockGuard$BlockGuardPolicyException;-><init>(II)V
+Ldalvik/system/BlockGuard$BlockGuardPolicyException;->getPolicy()I
+Ldalvik/system/BlockGuard$BlockGuardPolicyException;->getPolicyViolation()I
+Ldalvik/system/BlockGuard$Policy;->getPolicyMask()I
+Ldalvik/system/BlockGuard$Policy;->onUnbufferedIO()V
+Ldalvik/system/BlockGuard$Policy;->onWriteToDisk()V
+Ldalvik/system/BlockGuard;-><init>()V
+Ldalvik/system/BlockGuard;->DISALLOW_DISK_READ:I
+Ldalvik/system/BlockGuard;->DISALLOW_DISK_WRITE:I
+Ldalvik/system/BlockGuard;->DISALLOW_NETWORK:I
+Ldalvik/system/BlockGuard;->PASS_RESTRICTIONS_VIA_RPC:I
+Ldalvik/system/BlockGuard;->PENALTY_DEATH:I
+Ldalvik/system/BlockGuard;->PENALTY_DIALOG:I
+Ldalvik/system/BlockGuard;->PENALTY_LOG:I
+Ldalvik/system/ClassExt;-><init>()V
+Ldalvik/system/ClassExt;->obsoleteDexCaches:[Ljava/lang/Object;
+Ldalvik/system/ClassExt;->obsoleteMethods:Ljava/lang/Object;
+Ldalvik/system/ClassExt;->originalDexFile:Ljava/lang/Object;
+Ldalvik/system/ClassExt;->verifyError:Ljava/lang/Object;
+Ldalvik/system/CloseGuard$DefaultReporter;->report(Ljava/lang/String;Ljava/lang/Throwable;)V
+Ldalvik/system/CloseGuard$Tracker;->close(Ljava/lang/Throwable;)V
+Ldalvik/system/CloseGuard$Tracker;->open(Ljava/lang/Throwable;)V
+Ldalvik/system/CloseGuard;->closerNameOrAllocationInfo:Ljava/lang/Object;
+Ldalvik/system/CloseGuard;->currentTracker:Ldalvik/system/CloseGuard$Tracker;
+Ldalvik/system/CloseGuard;->getReporter()Ldalvik/system/CloseGuard$Reporter;
+Ldalvik/system/CloseGuard;->getTracker()Ldalvik/system/CloseGuard$Tracker;
+Ldalvik/system/CloseGuard;->isEnabled()Z
+Ldalvik/system/CloseGuard;->reporter:Ldalvik/system/CloseGuard$Reporter;
+Ldalvik/system/CloseGuard;->setTracker(Ldalvik/system/CloseGuard$Tracker;)V
+Ldalvik/system/CloseGuard;->stackAndTrackingEnabled:Z
+Ldalvik/system/DalvikLogging;-><init>()V
+Ldalvik/system/DalvikLogging;->loggerNameToTag(Ljava/lang/String;)Ljava/lang/String;
+Ldalvik/system/DalvikLogHandler;->publish(Ljava/util/logging/Logger;Ljava/lang/String;Ljava/util/logging/Level;Ljava/lang/String;)V
+Ldalvik/system/DexFile$DFEnum;-><init>(Ldalvik/system/DexFile;)V
+Ldalvik/system/DexFile$DFEnum;->mIndex:I
+Ldalvik/system/DexFile$OptimizationInfo;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Ldalvik/system/DexFile$OptimizationInfo;->getReason()Ljava/lang/String;
+Ldalvik/system/DexFile$OptimizationInfo;->getStatus()Ljava/lang/String;
+Ldalvik/system/DexFile$OptimizationInfo;->reason:Ljava/lang/String;
+Ldalvik/system/DexFile$OptimizationInfo;->status:Ljava/lang/String;
+Ldalvik/system/DexFile;-><init>(Ljava/io/File;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)V
+Ldalvik/system/DexFile;-><init>(Ljava/lang/String;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)V
+Ldalvik/system/DexFile;-><init>(Ljava/lang/String;Ljava/lang/String;ILjava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)V
+Ldalvik/system/DexFile;-><init>(Ljava/nio/ByteBuffer;)V
+Ldalvik/system/DexFile;->closeDexFile(Ljava/lang/Object;)Z
+Ldalvik/system/DexFile;->createCookieWithArray([BII)Ljava/lang/Object;
+Ldalvik/system/DexFile;->createCookieWithDirectBuffer(Ljava/nio/ByteBuffer;II)Ljava/lang/Object;
+Ldalvik/system/DexFile;->defineClass(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/Object;Ldalvik/system/DexFile;Ljava/util/List;)Ljava/lang/Class;
+Ldalvik/system/DexFile;->defineClassNative(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/Object;Ldalvik/system/DexFile;)Ljava/lang/Class;
+Ldalvik/system/DexFile;->DEX2OAT_FOR_BOOT_IMAGE:I
+Ldalvik/system/DexFile;->DEX2OAT_FOR_FILTER:I
+Ldalvik/system/DexFile;->DEX2OAT_FOR_RELOCATION:I
+Ldalvik/system/DexFile;->DEX2OAT_FROM_SCRATCH:I
+Ldalvik/system/DexFile;->getDexFileOptimizationInfo(Ljava/lang/String;Ljava/lang/String;)Ldalvik/system/DexFile$OptimizationInfo;
+Ldalvik/system/DexFile;->getDexFileOptimizationStatus(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;
+Ldalvik/system/DexFile;->getDexFileOutputPaths(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;
+Ldalvik/system/DexFile;->getDexFileStatus(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Ldalvik/system/DexFile;->getDexOptNeeded(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZ)I
+Ldalvik/system/DexFile;->getDexOptNeeded(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZ)I
+Ldalvik/system/DexFile;->getNonProfileGuidedCompilerFilter(Ljava/lang/String;)Ljava/lang/String;
+Ldalvik/system/DexFile;->getSafeModeCompilerFilter(Ljava/lang/String;)Ljava/lang/String;
+Ldalvik/system/DexFile;->getStaticSizeOfDexFile()J
+Ldalvik/system/DexFile;->getStaticSizeOfDexFile(Ljava/lang/Object;)J
+Ldalvik/system/DexFile;->isBackedByOatFile(Ljava/lang/Object;)Z
+Ldalvik/system/DexFile;->isProfileGuidedCompilerFilter(Ljava/lang/String;)Z
+Ldalvik/system/DexFile;->isValidCompilerFilter(Ljava/lang/String;)Z
+Ldalvik/system/DexFile;->NO_DEXOPT_NEEDED:I
+Ldalvik/system/DexFile;->openInMemoryDexFile(Ljava/nio/ByteBuffer;)Ljava/lang/Object;
+Ldalvik/system/DexFile;->setTrusted()V
+Ldalvik/system/DexFile;->setTrusted(Ljava/lang/Object;)V
+Ldalvik/system/DexPathList$Element;-><init>(Ldalvik/system/DexFile;)V
+Ldalvik/system/DexPathList$Element;-><init>(Ljava/io/File;)V
+Ldalvik/system/DexPathList$Element;->findClass(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/util/List;)Ljava/lang/Class;
+Ldalvik/system/DexPathList$Element;->findResource(Ljava/lang/String;)Ljava/net/URL;
+Ldalvik/system/DexPathList$Element;->getDexPath()Ljava/lang/String;
+Ldalvik/system/DexPathList$Element;->initialized:Z
+Ldalvik/system/DexPathList$Element;->maybeInit()V
+Ldalvik/system/DexPathList$Element;->urlHandler:Llibcore/io/ClassPathURLStreamHandler;
+Ldalvik/system/DexPathList$NativeLibraryElement;-><init>(Ljava/io/File;Ljava/lang/String;)V
+Ldalvik/system/DexPathList$NativeLibraryElement;->findNativeLibrary(Ljava/lang/String;)Ljava/lang/String;
+Ldalvik/system/DexPathList$NativeLibraryElement;->initialized:Z
+Ldalvik/system/DexPathList$NativeLibraryElement;->maybeInit()V
+Ldalvik/system/DexPathList$NativeLibraryElement;->urlHandler:Llibcore/io/ClassPathURLStreamHandler;
+Ldalvik/system/DexPathList$NativeLibraryElement;->zipDir:Ljava/lang/String;
+Ldalvik/system/DexPathList;-><init>(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;Ljava/io/File;Z)V
+Ldalvik/system/DexPathList;-><init>(Ljava/lang/ClassLoader;[Ljava/nio/ByteBuffer;)V
+Ldalvik/system/DexPathList;->addDexPath(Ljava/lang/String;Ljava/io/File;Z)V
+Ldalvik/system/DexPathList;->DEX_SUFFIX:Ljava/lang/String;
+Ldalvik/system/DexPathList;->findClass(Ljava/lang/String;Ljava/util/List;)Ljava/lang/Class;
+Ldalvik/system/DexPathList;->findLibrary(Ljava/lang/String;)Ljava/lang/String;
+Ldalvik/system/DexPathList;->findResource(Ljava/lang/String;)Ljava/net/URL;
+Ldalvik/system/DexPathList;->findResources(Ljava/lang/String;)Ljava/util/Enumeration;
+Ldalvik/system/DexPathList;->getDexPaths()Ljava/util/List;
+Ldalvik/system/DexPathList;->getNativeLibraryDirectories()Ljava/util/List;
+Ldalvik/system/DexPathList;->makeDexElements(Ljava/util/List;Ljava/io/File;Ljava/util/List;Ljava/lang/ClassLoader;Z)[Ldalvik/system/DexPathList$Element;
+Ldalvik/system/DexPathList;->optimizedPathFor(Ljava/io/File;Ljava/io/File;)Ljava/lang/String;
+Ldalvik/system/DexPathList;->splitDexPath(Ljava/lang/String;)Ljava/util/List;
+Ldalvik/system/DexPathList;->zipSeparator:Ljava/lang/String;
+Ldalvik/system/EmulatedStackFrame$Range;-><init>(IIII)V
+Ldalvik/system/EmulatedStackFrame$Range;->all(Ljava/lang/invoke/MethodType;)Ldalvik/system/EmulatedStackFrame$Range;
+Ldalvik/system/EmulatedStackFrame$Range;->numBytes:I
+Ldalvik/system/EmulatedStackFrame$Range;->numReferences:I
+Ldalvik/system/EmulatedStackFrame$Range;->of(Ljava/lang/invoke/MethodType;II)Ldalvik/system/EmulatedStackFrame$Range;
+Ldalvik/system/EmulatedStackFrame$Range;->referencesStart:I
+Ldalvik/system/EmulatedStackFrame$Range;->stackFrameStart:I
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;-><init>()V
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->argumentIdx:I
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->attach(Ldalvik/system/EmulatedStackFrame;)Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->attach(Ldalvik/system/EmulatedStackFrame;III)Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->checkType(Ljava/lang/Class;)V
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->copyNext(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ldalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/Class;)V
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->frame:Ldalvik/system/EmulatedStackFrame;
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->frameBuf:Ljava/nio/ByteBuffer;
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->makeReturnValueAccessor()V
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->numArgs:I
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->referencesOffset:I
+Ldalvik/system/EmulatedStackFrame$StackFrameAccessor;->RETURN_VALUE_IDX:I
+Ldalvik/system/EmulatedStackFrame$StackFrameReader;-><init>()V
+Ldalvik/system/EmulatedStackFrame$StackFrameReader;->nextBoolean()Z
+Ldalvik/system/EmulatedStackFrame$StackFrameReader;->nextByte()B
+Ldalvik/system/EmulatedStackFrame$StackFrameReader;->nextChar()C
+Ldalvik/system/EmulatedStackFrame$StackFrameReader;->nextDouble()D
+Ldalvik/system/EmulatedStackFrame$StackFrameReader;->nextFloat()F
+Ldalvik/system/EmulatedStackFrame$StackFrameReader;->nextInt()I
+Ldalvik/system/EmulatedStackFrame$StackFrameReader;->nextLong()J
+Ldalvik/system/EmulatedStackFrame$StackFrameReader;->nextReference(Ljava/lang/Class;)Ljava/lang/Object;
+Ldalvik/system/EmulatedStackFrame$StackFrameReader;->nextShort()S
+Ldalvik/system/EmulatedStackFrame$StackFrameWriter;-><init>()V
+Ldalvik/system/EmulatedStackFrame$StackFrameWriter;->putNextBoolean(Z)V
+Ldalvik/system/EmulatedStackFrame$StackFrameWriter;->putNextByte(B)V
+Ldalvik/system/EmulatedStackFrame$StackFrameWriter;->putNextChar(C)V
+Ldalvik/system/EmulatedStackFrame$StackFrameWriter;->putNextDouble(D)V
+Ldalvik/system/EmulatedStackFrame$StackFrameWriter;->putNextFloat(F)V
+Ldalvik/system/EmulatedStackFrame$StackFrameWriter;->putNextInt(I)V
+Ldalvik/system/EmulatedStackFrame$StackFrameWriter;->putNextLong(J)V
+Ldalvik/system/EmulatedStackFrame$StackFrameWriter;->putNextReference(Ljava/lang/Object;Ljava/lang/Class;)V
+Ldalvik/system/EmulatedStackFrame$StackFrameWriter;->putNextShort(S)V
+Ldalvik/system/EmulatedStackFrame;-><init>(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;[B)V
+Ldalvik/system/EmulatedStackFrame;->callsiteType:Ljava/lang/invoke/MethodType;
+Ldalvik/system/EmulatedStackFrame;->copyRangeTo(Ldalvik/system/EmulatedStackFrame;Ldalvik/system/EmulatedStackFrame$Range;II)V
+Ldalvik/system/EmulatedStackFrame;->copyReturnValueTo(Ldalvik/system/EmulatedStackFrame;)V
+Ldalvik/system/EmulatedStackFrame;->create(Ljava/lang/invoke/MethodType;)Ldalvik/system/EmulatedStackFrame;
+Ldalvik/system/EmulatedStackFrame;->getCallsiteType()Ljava/lang/invoke/MethodType;
+Ldalvik/system/EmulatedStackFrame;->getMethodType()Ljava/lang/invoke/MethodType;
+Ldalvik/system/EmulatedStackFrame;->getReference(ILjava/lang/Class;)Ljava/lang/Object;
+Ldalvik/system/EmulatedStackFrame;->getSize(Ljava/lang/Class;)I
+Ldalvik/system/EmulatedStackFrame;->is64BitPrimitive(Ljava/lang/Class;)Z
+Ldalvik/system/EmulatedStackFrame;->references:[Ljava/lang/Object;
+Ldalvik/system/EmulatedStackFrame;->setReference(ILjava/lang/Object;)V
+Ldalvik/system/EmulatedStackFrame;->setReturnValueTo(Ljava/lang/Object;)V
+Ldalvik/system/EmulatedStackFrame;->stackFrame:[B
+Ldalvik/system/EmulatedStackFrame;->type:Ljava/lang/invoke/MethodType;
+Ldalvik/system/PotentialDeadlockError;-><init>()V
+Ldalvik/system/PotentialDeadlockError;-><init>(Ljava/lang/String;)V
+Ldalvik/system/SocketTagger;-><init>()V
+Ldalvik/system/SocketTagger;->set(Ldalvik/system/SocketTagger;)V
+Ldalvik/system/SocketTagger;->tag(Ljava/io/FileDescriptor;)V
+Ldalvik/system/SocketTagger;->tag(Ljava/net/DatagramSocket;)V
+Ldalvik/system/SocketTagger;->tagger:Ldalvik/system/SocketTagger;
+Ldalvik/system/SocketTagger;->untag(Ljava/io/FileDescriptor;)V
+Ldalvik/system/SocketTagger;->untag(Ljava/net/DatagramSocket;)V
+Ldalvik/system/TemporaryDirectory;-><init>()V
+Ldalvik/system/TemporaryDirectory;->setUpDirectory(Ljava/io/File;)V
+Ldalvik/system/TemporaryDirectory;->setUpDirectory(Ljava/lang/String;)V
+Ldalvik/system/VMDebug;-><init>()V
+Ldalvik/system/VMDebug;->attachAgent(Ljava/lang/String;)V
+Ldalvik/system/VMDebug;->attachAgent(Ljava/lang/String;Ljava/lang/ClassLoader;)V
+Ldalvik/system/VMDebug;->cacheRegisterMap(Ljava/lang/String;)Z
+Ldalvik/system/VMDebug;->checkBufferSize(I)I
+Ldalvik/system/VMDebug;->countInstancesOfClass(Ljava/lang/Class;Z)J
+Ldalvik/system/VMDebug;->countInstancesOfClasses([Ljava/lang/Class;Z)[J
+Ldalvik/system/VMDebug;->crash()V
+Ldalvik/system/VMDebug;->dumpHprofData(Ljava/lang/String;)V
+Ldalvik/system/VMDebug;->dumpHprofData(Ljava/lang/String;I)V
+Ldalvik/system/VMDebug;->dumpHprofData(Ljava/lang/String;Ljava/io/FileDescriptor;)V
+Ldalvik/system/VMDebug;->dumpHprofDataDdms()V
+Ldalvik/system/VMDebug;->getAllocCount(I)I
+Ldalvik/system/VMDebug;->getHeapSpaceStats([J)V
+Ldalvik/system/VMDebug;->getInstancesOfClasses([Ljava/lang/Class;Z)[[Ljava/lang/Object;
+Ldalvik/system/VMDebug;->getInstructionCount([I)V
+Ldalvik/system/VMDebug;->getLoadedClassCount()I
+Ldalvik/system/VMDebug;->getMethodTracingMode()I
+Ldalvik/system/VMDebug;->getRuntimeStat(Ljava/lang/String;)Ljava/lang/String;
+Ldalvik/system/VMDebug;->getRuntimeStatInternal(I)Ljava/lang/String;
+Ldalvik/system/VMDebug;->getRuntimeStats()Ljava/util/Map;
+Ldalvik/system/VMDebug;->getRuntimeStatsInternal()[Ljava/lang/String;
+Ldalvik/system/VMDebug;->getVmFeatureList()[Ljava/lang/String;
+Ldalvik/system/VMDebug;->infopoint(I)V
+Ldalvik/system/VMDebug;->isDebuggingEnabled()Z
+Ldalvik/system/VMDebug;->KIND_ALLOCATED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_ALLOCATED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_ALL_COUNTS:I
+Ldalvik/system/VMDebug;->KIND_CLASS_INIT_COUNT:I
+Ldalvik/system/VMDebug;->KIND_CLASS_INIT_TIME:I
+Ldalvik/system/VMDebug;->KIND_EXT_ALLOCATED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_EXT_ALLOCATED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_EXT_FREED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_EXT_FREED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_FREED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_FREED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_GC_INVOCATIONS:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_ALLOCATED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_ALLOCATED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_CLASS_INIT_COUNT:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_CLASS_INIT_TIME:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_EXT_ALLOCATED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_EXT_ALLOCATED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_EXT_FREED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_EXT_FREED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_FREED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_FREED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_GLOBAL_GC_INVOCATIONS:I
+Ldalvik/system/VMDebug;->KIND_THREAD_ALLOCATED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_THREAD_ALLOCATED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_THREAD_CLASS_INIT_COUNT:I
+Ldalvik/system/VMDebug;->KIND_THREAD_CLASS_INIT_TIME:I
+Ldalvik/system/VMDebug;->KIND_THREAD_EXT_ALLOCATED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_THREAD_EXT_ALLOCATED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_THREAD_EXT_FREED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_THREAD_EXT_FREED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_THREAD_FREED_BYTES:I
+Ldalvik/system/VMDebug;->KIND_THREAD_FREED_OBJECTS:I
+Ldalvik/system/VMDebug;->KIND_THREAD_GC_INVOCATIONS:I
+Ldalvik/system/VMDebug;->lastDebuggerActivity()J
+Ldalvik/system/VMDebug;->nativeAttachAgent(Ljava/lang/String;Ljava/lang/ClassLoader;)V
+Ldalvik/system/VMDebug;->printLoadedClasses(I)V
+Ldalvik/system/VMDebug;->resetAllocCount(I)V
+Ldalvik/system/VMDebug;->resetInstructionCount()V
+Ldalvik/system/VMDebug;->runtimeStatsMap:Ljava/util/HashMap;
+Ldalvik/system/VMDebug;->setAllocationLimit(I)I
+Ldalvik/system/VMDebug;->setGlobalAllocationLimit(I)I
+Ldalvik/system/VMDebug;->startAllocCounting()V
+Ldalvik/system/VMDebug;->startClassPrep()V
+Ldalvik/system/VMDebug;->startEmulatorTracing()V
+Ldalvik/system/VMDebug;->startGC()V
+Ldalvik/system/VMDebug;->startInstructionCounting()V
+Ldalvik/system/VMDebug;->startMethodTracing()V
+Ldalvik/system/VMDebug;->startMethodTracing(Ljava/lang/String;IIZI)V
+Ldalvik/system/VMDebug;->startMethodTracing(Ljava/lang/String;Ljava/io/FileDescriptor;IIZI)V
+Ldalvik/system/VMDebug;->startMethodTracing(Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V
+Ldalvik/system/VMDebug;->startMethodTracingDdms(IIZI)V
+Ldalvik/system/VMDebug;->startMethodTracingDdmsImpl(IIZI)V
+Ldalvik/system/VMDebug;->startMethodTracingFd(Ljava/lang/String;IIIZIZ)V
+Ldalvik/system/VMDebug;->startMethodTracingFilename(Ljava/lang/String;IIZI)V
+Ldalvik/system/VMDebug;->stopAllocCounting()V
+Ldalvik/system/VMDebug;->stopEmulatorTracing()V
+Ldalvik/system/VMDebug;->stopInstructionCounting()V
+Ldalvik/system/VMDebug;->stopMethodTracing()V
+Ldalvik/system/VMDebug;->threadCpuTimeNanos()J
+Ldalvik/system/VMDebug;->TRACE_COUNT_ALLOCS:I
+Ldalvik/system/VMRuntime;-><init>()V
+Ldalvik/system/VMRuntime;->ABI_TO_INSTRUCTION_SET_MAP:Ljava/util/Map;
+Ldalvik/system/VMRuntime;->bootClassPath()Ljava/lang/String;
+Ldalvik/system/VMRuntime;->clampGrowthLimit()V
+Ldalvik/system/VMRuntime;->classPath()Ljava/lang/String;
+Ldalvik/system/VMRuntime;->concurrentGC()V
+Ldalvik/system/VMRuntime;->didPruneDalvikCache()Z
+Ldalvik/system/VMRuntime;->disableJitCompilation()V
+Ldalvik/system/VMRuntime;->getTargetHeapUtilization()F
+Ldalvik/system/VMRuntime;->getTargetSdkVersion()I
+Ldalvik/system/VMRuntime;->hasUsedHiddenApi()Z
+Ldalvik/system/VMRuntime;->is64BitInstructionSet(Ljava/lang/String;)Z
+Ldalvik/system/VMRuntime;->isBootClassPathOnDisk(Ljava/lang/String;)Z
+Ldalvik/system/VMRuntime;->isCheckJniEnabled()Z
+Ldalvik/system/VMRuntime;->isDebuggerActive()Z
+Ldalvik/system/VMRuntime;->isJavaDebuggable()Z
+Ldalvik/system/VMRuntime;->isNativeDebuggable()Z
+Ldalvik/system/VMRuntime;->nativeSetTargetHeapUtilization(F)V
+Ldalvik/system/VMRuntime;->newUnpaddedArray(Ljava/lang/Class;I)Ljava/lang/Object;
+Ldalvik/system/VMRuntime;->nonSdkApiUsageConsumer:Ljava/util/function/Consumer;
+Ldalvik/system/VMRuntime;->preloadDexCaches()V
+Ldalvik/system/VMRuntime;->properties()[Ljava/lang/String;
+Ldalvik/system/VMRuntime;->registerAppInfo(Ljava/lang/String;[Ljava/lang/String;)V
+Ldalvik/system/VMRuntime;->registerSensitiveThread()V
+Ldalvik/system/VMRuntime;->requestConcurrentGC()V
+Ldalvik/system/VMRuntime;->requestHeapTrim()V
+Ldalvik/system/VMRuntime;->runHeapTasks()V
+Ldalvik/system/VMRuntime;->SDK_VERSION_CUR_DEVELOPMENT:I
+Ldalvik/system/VMRuntime;->setDedupeHiddenApiWarnings(Z)V
+Ldalvik/system/VMRuntime;->setHiddenApiAccessLogSamplingRate(I)V
+Ldalvik/system/VMRuntime;->setNonSdkApiUsageConsumer(Ljava/util/function/Consumer;)V
+Ldalvik/system/VMRuntime;->setProcessPackageName(Ljava/lang/String;)V
+Ldalvik/system/VMRuntime;->setSystemDaemonThreadPriority()V
+Ldalvik/system/VMRuntime;->startHeapTaskProcessor()V
+Ldalvik/system/VMRuntime;->startJitCompilation()V
+Ldalvik/system/VMRuntime;->stopHeapTaskProcessor()V
+Ldalvik/system/VMRuntime;->targetSdkVersion:I
+Ldalvik/system/VMRuntime;->THE_ONE:Ldalvik/system/VMRuntime;
+Ldalvik/system/VMRuntime;->trimHeap()V
+Ldalvik/system/VMRuntime;->updateProcessState(I)V
+Ldalvik/system/VMRuntime;->vmVersion()Ljava/lang/String;
+Ldalvik/system/VMStack;-><init>()V
+Ldalvik/system/VMStack;->getAnnotatedThreadStackTrace(Ljava/lang/Thread;)[Ldalvik/system/AnnotatedStackTraceElement;
+Ldalvik/system/VMStack;->getClosestUserClassLoader()Ljava/lang/ClassLoader;
+Ldalvik/system/VMStack;->getStackClass1()Ljava/lang/Class;
+Ldalvik/system/ZygoteHooks;-><init>()V
+Ldalvik/system/ZygoteHooks;->nativePostForkChild(JIZZLjava/lang/String;)V
+Ldalvik/system/ZygoteHooks;->nativePreFork()J
+Ldalvik/system/ZygoteHooks;->postForkChild(IZZLjava/lang/String;)V
+Ldalvik/system/ZygoteHooks;->postForkCommon()V
+Ldalvik/system/ZygoteHooks;->preFork()V
+Ldalvik/system/ZygoteHooks;->startZygoteNoThreadCreation()V
+Ldalvik/system/ZygoteHooks;->stopZygoteNoThreadCreation()V
+Ldalvik/system/ZygoteHooks;->token:J
+Ldalvik/system/ZygoteHooks;->waitUntilAllThreadsStopped()V
+Ljava/awt/font/NumericShaper$Range;->base:I
+Ljava/awt/font/NumericShaper$Range;->end:I
+Ljava/awt/font/NumericShaper$Range;->getDigitBase()I
+Ljava/awt/font/NumericShaper$Range;->getNumericBase()C
+Ljava/awt/font/NumericShaper$Range;->indexToRange(I)Ljava/awt/font/NumericShaper$Range;
+Ljava/awt/font/NumericShaper$Range;->inRange(I)Z
+Ljava/awt/font/NumericShaper$Range;->maskToRangeSet(I)Ljava/util/Set;
+Ljava/awt/font/NumericShaper$Range;->start:I
+Ljava/awt/font/NumericShaper$Range;->toRangeIndex(Ljava/awt/font/NumericShaper$Range;)I
+Ljava/awt/font/NumericShaper$Range;->toRangeMask(Ljava/util/Set;)I
+Ljava/awt/font/NumericShaper;-><init>(II)V
+Ljava/awt/font/NumericShaper;-><init>(Ljava/awt/font/NumericShaper$Range;Ljava/util/Set;)V
+Ljava/awt/font/NumericShaper;->ARABIC_KEY:I
+Ljava/awt/font/NumericShaper;->bases:[C
+Ljava/awt/font/NumericShaper;->BENGALI_KEY:I
+Ljava/awt/font/NumericShaper;->BSEARCH_THRESHOLD:I
+Ljava/awt/font/NumericShaper;->checkParams([CII)V
+Ljava/awt/font/NumericShaper;->contexts:[C
+Ljava/awt/font/NumericShaper;->CONTEXTUAL_MASK:I
+Ljava/awt/font/NumericShaper;->ctCache:I
+Ljava/awt/font/NumericShaper;->ctCacheLimit:I
+Ljava/awt/font/NumericShaper;->currentRange:Ljava/awt/font/NumericShaper$Range;
+Ljava/awt/font/NumericShaper;->DEVANAGARI_KEY:I
+Ljava/awt/font/NumericShaper;->EASTERN_ARABIC_KEY:I
+Ljava/awt/font/NumericShaper;->ETHIOPIC_KEY:I
+Ljava/awt/font/NumericShaper;->EUROPEAN_KEY:I
+Ljava/awt/font/NumericShaper;->getContextKey(C)I
+Ljava/awt/font/NumericShaper;->getHighBit(I)I
+Ljava/awt/font/NumericShaper;->getKeyFromMask(I)I
+Ljava/awt/font/NumericShaper;->GUJARATI_KEY:I
+Ljava/awt/font/NumericShaper;->GURMUKHI_KEY:I
+Ljava/awt/font/NumericShaper;->isStrongDirectional(C)Z
+Ljava/awt/font/NumericShaper;->KANNADA_KEY:I
+Ljava/awt/font/NumericShaper;->key:I
+Ljava/awt/font/NumericShaper;->KHMER_KEY:I
+Ljava/awt/font/NumericShaper;->LAO_KEY:I
+Ljava/awt/font/NumericShaper;->MALAYALAM_KEY:I
+Ljava/awt/font/NumericShaper;->mask:I
+Ljava/awt/font/NumericShaper;->MONGOLIAN_KEY:I
+Ljava/awt/font/NumericShaper;->MYANMAR_KEY:I
+Ljava/awt/font/NumericShaper;->NUM_KEYS:I
+Ljava/awt/font/NumericShaper;->ORIYA_KEY:I
+Ljava/awt/font/NumericShaper;->rangeArray:[Ljava/awt/font/NumericShaper$Range;
+Ljava/awt/font/NumericShaper;->rangeForCodePoint(I)Ljava/awt/font/NumericShaper$Range;
+Ljava/awt/font/NumericShaper;->rangeSet:Ljava/util/Set;
+Ljava/awt/font/NumericShaper;->search(I[III)I
+Ljava/awt/font/NumericShaper;->shapeContextually([CIII)V
+Ljava/awt/font/NumericShaper;->shapeContextually([CIILjava/awt/font/NumericShaper$Range;)V
+Ljava/awt/font/NumericShaper;->shapeNonContextually([CII)V
+Ljava/awt/font/NumericShaper;->shapingRange:Ljava/awt/font/NumericShaper$Range;
+Ljava/awt/font/NumericShaper;->stCache:I
+Ljava/awt/font/NumericShaper;->strongTable:[I
+Ljava/awt/font/NumericShaper;->TAMIL_KEY:I
+Ljava/awt/font/NumericShaper;->TELUGU_KEY:I
+Ljava/awt/font/NumericShaper;->THAI_KEY:I
+Ljava/awt/font/NumericShaper;->TIBETAN_KEY:I
+Ljava/awt/font/TextAttribute;->instanceMap:Ljava/util/Map;
+Ljava/beans/ChangeListenerMap;-><init>()V
+Ljava/beans/ChangeListenerMap;->add(Ljava/lang/String;Ljava/util/EventListener;)V
+Ljava/beans/ChangeListenerMap;->extract(Ljava/util/EventListener;)Ljava/util/EventListener;
+Ljava/beans/ChangeListenerMap;->get(Ljava/lang/String;)[Ljava/util/EventListener;
+Ljava/beans/ChangeListenerMap;->getEntries()Ljava/util/Set;
+Ljava/beans/ChangeListenerMap;->getListeners()[Ljava/util/EventListener;
+Ljava/beans/ChangeListenerMap;->getListeners(Ljava/lang/String;)[Ljava/util/EventListener;
+Ljava/beans/ChangeListenerMap;->hasListeners(Ljava/lang/String;)Z
+Ljava/beans/ChangeListenerMap;->map:Ljava/util/Map;
+Ljava/beans/ChangeListenerMap;->newArray(I)[Ljava/util/EventListener;
+Ljava/beans/ChangeListenerMap;->newProxy(Ljava/lang/String;Ljava/util/EventListener;)Ljava/util/EventListener;
+Ljava/beans/ChangeListenerMap;->remove(Ljava/lang/String;Ljava/util/EventListener;)V
+Ljava/beans/ChangeListenerMap;->set(Ljava/lang/String;[Ljava/util/EventListener;)V
+Ljava/beans/IndexedPropertyChangeEvent;->appendTo(Ljava/lang/StringBuilder;)V
+Ljava/beans/IndexedPropertyChangeEvent;->index:I
+Ljava/beans/PropertyChangeEvent;->appendTo(Ljava/lang/StringBuilder;)V
+Ljava/beans/PropertyChangeEvent;->newValue:Ljava/lang/Object;
+Ljava/beans/PropertyChangeEvent;->oldValue:Ljava/lang/Object;
+Ljava/beans/PropertyChangeEvent;->propagationId:Ljava/lang/Object;
+Ljava/beans/PropertyChangeEvent;->propertyName:Ljava/lang/String;
+Ljava/beans/PropertyChangeListenerProxy;->propertyName:Ljava/lang/String;
+Ljava/beans/PropertyChangeSupport$PropertyChangeListenerMap;-><init>()V
+Ljava/beans/PropertyChangeSupport$PropertyChangeListenerMap;->EMPTY:[Ljava/beans/PropertyChangeListener;
+Ljava/beans/PropertyChangeSupport$PropertyChangeListenerMap;->extract(Ljava/beans/PropertyChangeListener;)Ljava/beans/PropertyChangeListener;
+Ljava/beans/PropertyChangeSupport$PropertyChangeListenerMap;->newArray(I)[Ljava/beans/PropertyChangeListener;
+Ljava/beans/PropertyChangeSupport$PropertyChangeListenerMap;->newProxy(Ljava/lang/String;Ljava/beans/PropertyChangeListener;)Ljava/beans/PropertyChangeListener;
+Ljava/beans/PropertyChangeSupport;->fire([Ljava/beans/PropertyChangeListener;Ljava/beans/PropertyChangeEvent;)V
+Ljava/beans/PropertyChangeSupport;->map:Ljava/beans/PropertyChangeSupport$PropertyChangeListenerMap;
+Ljava/beans/PropertyChangeSupport;->source:Ljava/lang/Object;
+Ljava/io/BufferedInputStream;->bufUpdater:Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;
+Ljava/io/BufferedInputStream;->DEFAULT_BUFFER_SIZE:I
+Ljava/io/BufferedInputStream;->fill()V
+Ljava/io/BufferedInputStream;->getBufIfOpen()[B
+Ljava/io/BufferedInputStream;->getInIfOpen()Ljava/io/InputStream;
+Ljava/io/BufferedInputStream;->MAX_BUFFER_SIZE:I
+Ljava/io/BufferedInputStream;->read1([BII)I
+Ljava/io/BufferedOutputStream;->flushBuffer()V
+Ljava/io/BufferedReader;->cb:[C
+Ljava/io/BufferedReader;->defaultCharBufferSize:I
+Ljava/io/BufferedReader;->defaultExpectedLineLength:I
+Ljava/io/BufferedReader;->ensureOpen()V
+Ljava/io/BufferedReader;->fill()V
+Ljava/io/BufferedReader;->in:Ljava/io/Reader;
+Ljava/io/BufferedReader;->INVALIDATED:I
+Ljava/io/BufferedReader;->markedChar:I
+Ljava/io/BufferedReader;->markedSkipLF:Z
+Ljava/io/BufferedReader;->nChars:I
+Ljava/io/BufferedReader;->nextChar:I
+Ljava/io/BufferedReader;->read1([CII)I
+Ljava/io/BufferedReader;->readAheadLimit:I
+Ljava/io/BufferedReader;->readLine(Z)Ljava/lang/String;
+Ljava/io/BufferedReader;->skipLF:Z
+Ljava/io/BufferedReader;->UNMARKED:I
+Ljava/io/BufferedWriter;->cb:[C
+Ljava/io/BufferedWriter;->defaultCharBufferSize:I
+Ljava/io/BufferedWriter;->ensureOpen()V
+Ljava/io/BufferedWriter;->flushBuffer()V
+Ljava/io/BufferedWriter;->lineSeparator:Ljava/lang/String;
+Ljava/io/BufferedWriter;->min(II)I
+Ljava/io/BufferedWriter;->nChars:I
+Ljava/io/BufferedWriter;->nextChar:I
+Ljava/io/BufferedWriter;->out:Ljava/io/Writer;
+Ljava/io/ByteArrayOutputStream;->ensureCapacity(I)V
+Ljava/io/ByteArrayOutputStream;->grow(I)V
+Ljava/io/ByteArrayOutputStream;->hugeCapacity(I)I
+Ljava/io/ByteArrayOutputStream;->MAX_ARRAY_SIZE:I
+Ljava/io/CharArrayReader;->ensureOpen()V
+Ljava/io/Console$LineReader;->cb:[C
+Ljava/io/Console$LineReader;->in:Ljava/io/Reader;
+Ljava/io/Console$LineReader;->leftoverLF:Z
+Ljava/io/Console$LineReader;->nChars:I
+Ljava/io/Console$LineReader;->nextChar:I
+Ljava/io/Console;-><init>()V
+Ljava/io/Console;-><init>(Ljava/io/InputStream;Ljava/io/OutputStream;)V
+Ljava/io/Console;->cons:Ljava/io/Console;
+Ljava/io/Console;->console()Ljava/io/Console;
+Ljava/io/Console;->cs:Ljava/nio/charset/Charset;
+Ljava/io/Console;->echo(Z)Z
+Ljava/io/Console;->echoOff:Z
+Ljava/io/Console;->formatter:Ljava/util/Formatter;
+Ljava/io/Console;->grow()[C
+Ljava/io/Console;->istty()Z
+Ljava/io/Console;->out:Ljava/io/Writer;
+Ljava/io/Console;->pw:Ljava/io/PrintWriter;
+Ljava/io/Console;->rcb:[C
+Ljava/io/Console;->reader:Ljava/io/Reader;
+Ljava/io/Console;->readline(Z)[C
+Ljava/io/Console;->readLock:Ljava/lang/Object;
+Ljava/io/Console;->writeLock:Ljava/lang/Object;
+Ljava/io/DataInputStream;->bytearr:[B
+Ljava/io/DataInputStream;->chararr:[C
+Ljava/io/DataInputStream;->lineBuffer:[C
+Ljava/io/DataInputStream;->readBuffer:[B
+Ljava/io/DataOutputStream;->bytearr:[B
+Ljava/io/DataOutputStream;->incCount(I)V
+Ljava/io/DataOutputStream;->writeBuffer:[B
+Ljava/io/DataOutputStream;->writeUTF(Ljava/lang/String;Ljava/io/DataOutput;)I
+Ljava/io/File$PathStatus;->CHECKED:Ljava/io/File$PathStatus;
+Ljava/io/File$PathStatus;->INVALID:Ljava/io/File$PathStatus;
+Ljava/io/File$PathStatus;->valueOf(Ljava/lang/String;)Ljava/io/File$PathStatus;
+Ljava/io/File$PathStatus;->values()[Ljava/io/File$PathStatus;
+Ljava/io/File$TempDirectory;-><init>()V
+Ljava/io/File$TempDirectory;->generateFile(Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)Ljava/io/File;
+Ljava/io/File;-><init>(Ljava/lang/String;I)V
+Ljava/io/File;-><init>(Ljava/lang/String;Ljava/io/File;)V
+Ljava/io/File;->getPrefixLength()I
+Ljava/io/File;->isInvalid()Z
+Ljava/io/File;->PATH_OFFSET:J
+Ljava/io/File;->PREFIX_LENGTH_OFFSET:J
+Ljava/io/File;->slashify(Ljava/lang/String;Z)Ljava/lang/String;
+Ljava/io/File;->UNSAFE:Lsun/misc/Unsafe;
+Ljava/io/FileDescriptor;-><init>(I)V
+Ljava/io/FileDescriptor;->dupFd(I)Ljava/io/FileDescriptor;
+Ljava/io/FileDescriptor;->isSocket(I)Z
+Ljava/io/FileInputStream$UseManualSkipException;-><init>()V
+Ljava/io/FileInputStream;-><init>(Ljava/io/FileDescriptor;Z)V
+Ljava/io/FileInputStream;->available0()I
+Ljava/io/FileInputStream;->channel:Ljava/nio/channels/FileChannel;
+Ljava/io/FileInputStream;->closed:Z
+Ljava/io/FileInputStream;->closeLock:Ljava/lang/Object;
+Ljava/io/FileInputStream;->guard:Ldalvik/system/CloseGuard;
+Ljava/io/FileInputStream;->isFdOwner:Z
+Ljava/io/FileInputStream;->open(Ljava/lang/String;)V
+Ljava/io/FileInputStream;->open0(Ljava/lang/String;)V
+Ljava/io/FileInputStream;->path:Ljava/lang/String;
+Ljava/io/FileInputStream;->skip0(J)J
+Ljava/io/FileInputStream;->tracker:Llibcore/io/IoTracker;
+Ljava/io/FileNotFoundException;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Ljava/io/FileOutputStream;-><init>(Ljava/io/FileDescriptor;Z)V
+Ljava/io/FileOutputStream;->append:Z
+Ljava/io/FileOutputStream;->closed:Z
+Ljava/io/FileOutputStream;->closeLock:Ljava/lang/Object;
+Ljava/io/FileOutputStream;->guard:Ldalvik/system/CloseGuard;
+Ljava/io/FileOutputStream;->isFdOwner:Z
+Ljava/io/FileOutputStream;->open(Ljava/lang/String;Z)V
+Ljava/io/FileOutputStream;->open0(Ljava/lang/String;Z)V
+Ljava/io/FileOutputStream;->path:Ljava/lang/String;
+Ljava/io/FileOutputStream;->tracker:Llibcore/io/IoTracker;
+Ljava/io/FileSystem;-><init>()V
+Ljava/io/FileSystem;->ACCESS_EXECUTE:I
+Ljava/io/FileSystem;->ACCESS_OK:I
+Ljava/io/FileSystem;->ACCESS_READ:I
+Ljava/io/FileSystem;->ACCESS_WRITE:I
+Ljava/io/FileSystem;->BA_DIRECTORY:I
+Ljava/io/FileSystem;->BA_EXISTS:I
+Ljava/io/FileSystem;->BA_HIDDEN:I
+Ljava/io/FileSystem;->BA_REGULAR:I
+Ljava/io/FileSystem;->getBooleanProperty(Ljava/lang/String;Z)Z
+Ljava/io/FileSystem;->SPACE_FREE:I
+Ljava/io/FileSystem;->SPACE_TOTAL:I
+Ljava/io/FileSystem;->SPACE_USABLE:I
+Ljava/io/FileSystem;->useCanonCaches:Z
+Ljava/io/FileSystem;->useCanonPrefixCache:Z
+Ljava/io/InputStream;->MAX_SKIP_BUFFER_SIZE:I
+Ljava/io/InputStreamReader;->sd:Lsun/nio/cs/StreamDecoder;
+Ljava/io/InterruptedIOException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/io/InterruptedIOException;-><init>(Ljava/lang/Throwable;)V
+Ljava/io/LineNumberInputStream;->lineNumber:I
+Ljava/io/LineNumberInputStream;->markLineNumber:I
+Ljava/io/LineNumberInputStream;->markPushBack:I
+Ljava/io/LineNumberInputStream;->pushBack:I
+Ljava/io/LineNumberReader;->lineNumber:I
+Ljava/io/LineNumberReader;->markedLineNumber:I
+Ljava/io/LineNumberReader;->markedSkipLF:Z
+Ljava/io/LineNumberReader;->maxSkipBufferSize:I
+Ljava/io/LineNumberReader;->skipBuffer:[C
+Ljava/io/LineNumberReader;->skipLF:Z
+Ljava/io/ObjectInputStream$BlockDataInputStream;->blkmode:Z
+Ljava/io/ObjectInputStream$BlockDataInputStream;->buf:[B
+Ljava/io/ObjectInputStream$BlockDataInputStream;->cbuf:[C
+Ljava/io/ObjectInputStream$BlockDataInputStream;->CHAR_BUF_SIZE:I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->currentBlockRemaining()I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->din:Ljava/io/DataInputStream;
+Ljava/io/ObjectInputStream$BlockDataInputStream;->end:I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->getBlockDataMode()Z
+Ljava/io/ObjectInputStream$BlockDataInputStream;->hbuf:[B
+Ljava/io/ObjectInputStream$BlockDataInputStream;->HEADER_BLOCKED:I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->in:Ljava/io/ObjectInputStream$PeekInputStream;
+Ljava/io/ObjectInputStream$BlockDataInputStream;->MAX_BLOCK_SIZE:I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->MAX_HEADER_SIZE:I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->peek()I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->peekByte()B
+Ljava/io/ObjectInputStream$BlockDataInputStream;->pos:I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->read([BIIZ)I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readBlockHeader(Z)I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readBooleans([ZII)V
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readChars([CII)V
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readDoubles([DII)V
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readFloats([FII)V
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readFully([BIIZ)V
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readInts([III)V
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readLongs([JII)V
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readLongUTF()Ljava/lang/String;
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readShorts([SII)V
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readUTFBody(J)Ljava/lang/String;
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readUTFChar(Ljava/lang/StringBuilder;J)I
+Ljava/io/ObjectInputStream$BlockDataInputStream;->readUTFSpan(Ljava/lang/StringBuilder;J)J
+Ljava/io/ObjectInputStream$BlockDataInputStream;->refill()V
+Ljava/io/ObjectInputStream$BlockDataInputStream;->setBlockDataMode(Z)Z
+Ljava/io/ObjectInputStream$BlockDataInputStream;->skipBlockData()V
+Ljava/io/ObjectInputStream$BlockDataInputStream;->unread:I
+Ljava/io/ObjectInputStream$Caches;-><init>()V
+Ljava/io/ObjectInputStream$Caches;->subclassAudits:Ljava/util/concurrent/ConcurrentMap;
+Ljava/io/ObjectInputStream$Caches;->subclassAuditsQueue:Ljava/lang/ref/ReferenceQueue;
+Ljava/io/ObjectInputStream$GetFieldImpl;->desc:Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectInputStream$GetFieldImpl;->getFieldOffset(Ljava/lang/String;Ljava/lang/Class;)I
+Ljava/io/ObjectInputStream$GetFieldImpl;->objHandles:[I
+Ljava/io/ObjectInputStream$GetFieldImpl;->objVals:[Ljava/lang/Object;
+Ljava/io/ObjectInputStream$GetFieldImpl;->primVals:[B
+Ljava/io/ObjectInputStream$GetFieldImpl;->readFields()V
+Ljava/io/ObjectInputStream$HandleTable$HandleList;-><init>()V
+Ljava/io/ObjectInputStream$HandleTable$HandleList;->add(I)V
+Ljava/io/ObjectInputStream$HandleTable$HandleList;->get(I)I
+Ljava/io/ObjectInputStream$HandleTable$HandleList;->list:[I
+Ljava/io/ObjectInputStream$HandleTable$HandleList;->size()I
+Ljava/io/ObjectInputStream$HandleTable$HandleList;->size:I
+Ljava/io/ObjectInputStream$HandleTable;-><init>(I)V
+Ljava/io/ObjectInputStream$HandleTable;->assign(Ljava/lang/Object;)I
+Ljava/io/ObjectInputStream$HandleTable;->clear()V
+Ljava/io/ObjectInputStream$HandleTable;->deps:[Ljava/io/ObjectInputStream$HandleTable$HandleList;
+Ljava/io/ObjectInputStream$HandleTable;->entries:[Ljava/lang/Object;
+Ljava/io/ObjectInputStream$HandleTable;->finish(I)V
+Ljava/io/ObjectInputStream$HandleTable;->grow()V
+Ljava/io/ObjectInputStream$HandleTable;->lookupException(I)Ljava/lang/ClassNotFoundException;
+Ljava/io/ObjectInputStream$HandleTable;->lookupObject(I)Ljava/lang/Object;
+Ljava/io/ObjectInputStream$HandleTable;->lowDep:I
+Ljava/io/ObjectInputStream$HandleTable;->markDependency(II)V
+Ljava/io/ObjectInputStream$HandleTable;->markException(ILjava/lang/ClassNotFoundException;)V
+Ljava/io/ObjectInputStream$HandleTable;->setObject(ILjava/lang/Object;)V
+Ljava/io/ObjectInputStream$HandleTable;->size()I
+Ljava/io/ObjectInputStream$HandleTable;->size:I
+Ljava/io/ObjectInputStream$HandleTable;->status:[B
+Ljava/io/ObjectInputStream$HandleTable;->STATUS_EXCEPTION:B
+Ljava/io/ObjectInputStream$HandleTable;->STATUS_OK:B
+Ljava/io/ObjectInputStream$HandleTable;->STATUS_UNKNOWN:B
+Ljava/io/ObjectInputStream$PeekInputStream;-><init>(Ljava/io/InputStream;)V
+Ljava/io/ObjectInputStream$PeekInputStream;->in:Ljava/io/InputStream;
+Ljava/io/ObjectInputStream$PeekInputStream;->peek()I
+Ljava/io/ObjectInputStream$PeekInputStream;->peekb:I
+Ljava/io/ObjectInputStream$PeekInputStream;->readFully([BII)V
+Ljava/io/ObjectInputStream$ValidationList$Callback;-><init>(Ljava/io/ObjectInputValidation;ILjava/io/ObjectInputStream$ValidationList$Callback;Ljava/security/AccessControlContext;)V
+Ljava/io/ObjectInputStream$ValidationList$Callback;->acc:Ljava/security/AccessControlContext;
+Ljava/io/ObjectInputStream$ValidationList$Callback;->next:Ljava/io/ObjectInputStream$ValidationList$Callback;
+Ljava/io/ObjectInputStream$ValidationList$Callback;->obj:Ljava/io/ObjectInputValidation;
+Ljava/io/ObjectInputStream$ValidationList$Callback;->priority:I
+Ljava/io/ObjectInputStream$ValidationList;-><init>()V
+Ljava/io/ObjectInputStream$ValidationList;->clear()V
+Ljava/io/ObjectInputStream$ValidationList;->doCallbacks()V
+Ljava/io/ObjectInputStream$ValidationList;->list:Ljava/io/ObjectInputStream$ValidationList$Callback;
+Ljava/io/ObjectInputStream$ValidationList;->register(Ljava/io/ObjectInputValidation;I)V
+Ljava/io/ObjectInputStream;->auditSubclass(Ljava/lang/Class;)Z
+Ljava/io/ObjectInputStream;->checkResolve(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/io/ObjectInputStream;->clear()V
+Ljava/io/ObjectInputStream;->cloneArray(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/io/ObjectInputStream;->closed:Z
+Ljava/io/ObjectInputStream;->curContext:Ljava/io/SerialCallbackContext;
+Ljava/io/ObjectInputStream;->defaultDataEnd:Z
+Ljava/io/ObjectInputStream;->defaultReadFields(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V
+Ljava/io/ObjectInputStream;->depth:I
+Ljava/io/ObjectInputStream;->enableOverride:Z
+Ljava/io/ObjectInputStream;->enableResolve:Z
+Ljava/io/ObjectInputStream;->handleReset()V
+Ljava/io/ObjectInputStream;->handles:Ljava/io/ObjectInputStream$HandleTable;
+Ljava/io/ObjectInputStream;->isCustomSubclass()Z
+Ljava/io/ObjectInputStream;->latestUserDefinedLoader()Ljava/lang/ClassLoader;
+Ljava/io/ObjectInputStream;->NULL_HANDLE:I
+Ljava/io/ObjectInputStream;->passHandle:I
+Ljava/io/ObjectInputStream;->primClasses:Ljava/util/HashMap;
+Ljava/io/ObjectInputStream;->primVals:[B
+Ljava/io/ObjectInputStream;->readArray(Z)Ljava/lang/Object;
+Ljava/io/ObjectInputStream;->readClass(Z)Ljava/lang/Class;
+Ljava/io/ObjectInputStream;->readClassDesc(Z)Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectInputStream;->readEnum(Z)Ljava/lang/Enum;
+Ljava/io/ObjectInputStream;->readExternalData(Ljava/io/Externalizable;Ljava/io/ObjectStreamClass;)V
+Ljava/io/ObjectInputStream;->readFatalException()Ljava/io/IOException;
+Ljava/io/ObjectInputStream;->readHandle(Z)Ljava/lang/Object;
+Ljava/io/ObjectInputStream;->readNonProxyDesc(Z)Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectInputStream;->readNull()Ljava/lang/Object;
+Ljava/io/ObjectInputStream;->readObject0(Z)Ljava/lang/Object;
+Ljava/io/ObjectInputStream;->readOrdinaryObject(Z)Ljava/lang/Object;
+Ljava/io/ObjectInputStream;->readProxyDesc(Z)Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectInputStream;->readSerialData(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V
+Ljava/io/ObjectInputStream;->readString(Z)Ljava/lang/String;
+Ljava/io/ObjectInputStream;->readTypeString()Ljava/lang/String;
+Ljava/io/ObjectInputStream;->skipCustomData()V
+Ljava/io/ObjectInputStream;->unsharedMarker:Ljava/lang/Object;
+Ljava/io/ObjectInputStream;->verifySubclass()V
+Ljava/io/ObjectInputStream;->vlist:Ljava/io/ObjectInputStream$ValidationList;
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;-><init>(Ljava/io/OutputStream;)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->blkmode:Z
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->buf:[B
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->cbuf:[C
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->CHAR_BUF_SIZE:I
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->dout:Ljava/io/DataOutputStream;
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->drain()V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->getBlockDataMode()Z
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->getUTFLength(Ljava/lang/String;)J
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->hbuf:[B
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->MAX_BLOCK_SIZE:I
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->MAX_HEADER_SIZE:I
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->out:Ljava/io/OutputStream;
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->pos:I
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->setBlockDataMode(Z)Z
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->warnIfClosed()V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->warnOnceWhenWriting:Z
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->write([BIIZ)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeBlockHeader(I)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeBooleans([ZII)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeChars([CII)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeDoubles([DII)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeFloats([FII)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeInts([III)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeLongs([JII)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeLongUTF(Ljava/lang/String;)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeLongUTF(Ljava/lang/String;J)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeShorts([SII)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeUTF(Ljava/lang/String;J)V
+Ljava/io/ObjectOutputStream$BlockDataOutputStream;->writeUTFBody(Ljava/lang/String;)V
+Ljava/io/ObjectOutputStream$Caches;-><init>()V
+Ljava/io/ObjectOutputStream$Caches;->subclassAudits:Ljava/util/concurrent/ConcurrentMap;
+Ljava/io/ObjectOutputStream$Caches;->subclassAuditsQueue:Ljava/lang/ref/ReferenceQueue;
+Ljava/io/ObjectOutputStream$DebugTraceInfoStack;-><init>()V
+Ljava/io/ObjectOutputStream$DebugTraceInfoStack;->clear()V
+Ljava/io/ObjectOutputStream$DebugTraceInfoStack;->pop()V
+Ljava/io/ObjectOutputStream$DebugTraceInfoStack;->push(Ljava/lang/String;)V
+Ljava/io/ObjectOutputStream$DebugTraceInfoStack;->stack:Ljava/util/List;
+Ljava/io/ObjectOutputStream$HandleTable;-><init>(IF)V
+Ljava/io/ObjectOutputStream$HandleTable;->assign(Ljava/lang/Object;)I
+Ljava/io/ObjectOutputStream$HandleTable;->clear()V
+Ljava/io/ObjectOutputStream$HandleTable;->growEntries()V
+Ljava/io/ObjectOutputStream$HandleTable;->growSpine()V
+Ljava/io/ObjectOutputStream$HandleTable;->hash(Ljava/lang/Object;)I
+Ljava/io/ObjectOutputStream$HandleTable;->insert(Ljava/lang/Object;I)V
+Ljava/io/ObjectOutputStream$HandleTable;->loadFactor:F
+Ljava/io/ObjectOutputStream$HandleTable;->lookup(Ljava/lang/Object;)I
+Ljava/io/ObjectOutputStream$HandleTable;->next:[I
+Ljava/io/ObjectOutputStream$HandleTable;->objs:[Ljava/lang/Object;
+Ljava/io/ObjectOutputStream$HandleTable;->size()I
+Ljava/io/ObjectOutputStream$HandleTable;->size:I
+Ljava/io/ObjectOutputStream$HandleTable;->spine:[I
+Ljava/io/ObjectOutputStream$HandleTable;->threshold:I
+Ljava/io/ObjectOutputStream$PutFieldImpl;->desc:Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectOutputStream$PutFieldImpl;->getFieldOffset(Ljava/lang/String;Ljava/lang/Class;)I
+Ljava/io/ObjectOutputStream$PutFieldImpl;->objVals:[Ljava/lang/Object;
+Ljava/io/ObjectOutputStream$PutFieldImpl;->primVals:[B
+Ljava/io/ObjectOutputStream$PutFieldImpl;->writeFields()V
+Ljava/io/ObjectOutputStream$ReplaceTable;-><init>(IF)V
+Ljava/io/ObjectOutputStream$ReplaceTable;->assign(Ljava/lang/Object;Ljava/lang/Object;)V
+Ljava/io/ObjectOutputStream$ReplaceTable;->clear()V
+Ljava/io/ObjectOutputStream$ReplaceTable;->grow()V
+Ljava/io/ObjectOutputStream$ReplaceTable;->htab:Ljava/io/ObjectOutputStream$HandleTable;
+Ljava/io/ObjectOutputStream$ReplaceTable;->lookup(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/io/ObjectOutputStream$ReplaceTable;->reps:[Ljava/lang/Object;
+Ljava/io/ObjectOutputStream$ReplaceTable;->size()I
+Ljava/io/ObjectOutputStream;->auditSubclass(Ljava/lang/Class;)Z
+Ljava/io/ObjectOutputStream;->bout:Ljava/io/ObjectOutputStream$BlockDataOutputStream;
+Ljava/io/ObjectOutputStream;->clear()V
+Ljava/io/ObjectOutputStream;->curContext:Ljava/io/SerialCallbackContext;
+Ljava/io/ObjectOutputStream;->curPut:Ljava/io/ObjectOutputStream$PutFieldImpl;
+Ljava/io/ObjectOutputStream;->debugInfoStack:Ljava/io/ObjectOutputStream$DebugTraceInfoStack;
+Ljava/io/ObjectOutputStream;->defaultWriteFields(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V
+Ljava/io/ObjectOutputStream;->depth:I
+Ljava/io/ObjectOutputStream;->doublesToBytes([DI[BII)V
+Ljava/io/ObjectOutputStream;->enableOverride:Z
+Ljava/io/ObjectOutputStream;->enableReplace:Z
+Ljava/io/ObjectOutputStream;->extendedDebugInfo:Z
+Ljava/io/ObjectOutputStream;->floatsToBytes([FI[BII)V
+Ljava/io/ObjectOutputStream;->getProtocolVersion()I
+Ljava/io/ObjectOutputStream;->handles:Ljava/io/ObjectOutputStream$HandleTable;
+Ljava/io/ObjectOutputStream;->isCustomSubclass()Z
+Ljava/io/ObjectOutputStream;->primVals:[B
+Ljava/io/ObjectOutputStream;->subs:Ljava/io/ObjectOutputStream$ReplaceTable;
+Ljava/io/ObjectOutputStream;->verifySubclass()V
+Ljava/io/ObjectOutputStream;->writeArray(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V
+Ljava/io/ObjectOutputStream;->writeClass(Ljava/lang/Class;Z)V
+Ljava/io/ObjectOutputStream;->writeClassDesc(Ljava/io/ObjectStreamClass;Z)V
+Ljava/io/ObjectOutputStream;->writeEnum(Ljava/lang/Enum;Ljava/io/ObjectStreamClass;Z)V
+Ljava/io/ObjectOutputStream;->writeExternalData(Ljava/io/Externalizable;)V
+Ljava/io/ObjectOutputStream;->writeFatalException(Ljava/io/IOException;)V
+Ljava/io/ObjectOutputStream;->writeHandle(I)V
+Ljava/io/ObjectOutputStream;->writeNonProxyDesc(Ljava/io/ObjectStreamClass;Z)V
+Ljava/io/ObjectOutputStream;->writeNull()V
+Ljava/io/ObjectOutputStream;->writeObject0(Ljava/lang/Object;Z)V
+Ljava/io/ObjectOutputStream;->writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V
+Ljava/io/ObjectOutputStream;->writeProxyDesc(Ljava/io/ObjectStreamClass;Z)V
+Ljava/io/ObjectOutputStream;->writeSerialData(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V
+Ljava/io/ObjectOutputStream;->writeString(Ljava/lang/String;Z)V
+Ljava/io/ObjectOutputStream;->writeTypeString(Ljava/lang/String;)V
+Ljava/io/ObjectStreamClass$Caches;-><init>()V
+Ljava/io/ObjectStreamClass$Caches;->localDescs:Ljava/util/concurrent/ConcurrentMap;
+Ljava/io/ObjectStreamClass$Caches;->localDescsQueue:Ljava/lang/ref/ReferenceQueue;
+Ljava/io/ObjectStreamClass$Caches;->reflectors:Ljava/util/concurrent/ConcurrentMap;
+Ljava/io/ObjectStreamClass$Caches;->reflectorsQueue:Ljava/lang/ref/ReferenceQueue;
+Ljava/io/ObjectStreamClass$ClassDataSlot;-><init>(Ljava/io/ObjectStreamClass;Z)V
+Ljava/io/ObjectStreamClass$ClassDataSlot;->desc:Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectStreamClass$ClassDataSlot;->hasData:Z
+Ljava/io/ObjectStreamClass$EntryFuture;-><init>()V
+Ljava/io/ObjectStreamClass$EntryFuture;->entry:Ljava/lang/Object;
+Ljava/io/ObjectStreamClass$EntryFuture;->get()Ljava/lang/Object;
+Ljava/io/ObjectStreamClass$EntryFuture;->getOwner()Ljava/lang/Thread;
+Ljava/io/ObjectStreamClass$EntryFuture;->owner:Ljava/lang/Thread;
+Ljava/io/ObjectStreamClass$EntryFuture;->set(Ljava/lang/Object;)Z
+Ljava/io/ObjectStreamClass$EntryFuture;->unset:Ljava/lang/Object;
+Ljava/io/ObjectStreamClass$ExceptionInfo;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Ljava/io/ObjectStreamClass$ExceptionInfo;->className:Ljava/lang/String;
+Ljava/io/ObjectStreamClass$ExceptionInfo;->message:Ljava/lang/String;
+Ljava/io/ObjectStreamClass$ExceptionInfo;->newInvalidClassException()Ljava/io/InvalidClassException;
+Ljava/io/ObjectStreamClass$FieldReflector;-><init>([Ljava/io/ObjectStreamField;)V
+Ljava/io/ObjectStreamClass$FieldReflector;->fields:[Ljava/io/ObjectStreamField;
+Ljava/io/ObjectStreamClass$FieldReflector;->getFields()[Ljava/io/ObjectStreamField;
+Ljava/io/ObjectStreamClass$FieldReflector;->getObjFieldValues(Ljava/lang/Object;[Ljava/lang/Object;)V
+Ljava/io/ObjectStreamClass$FieldReflector;->getPrimFieldValues(Ljava/lang/Object;[B)V
+Ljava/io/ObjectStreamClass$FieldReflector;->numPrimFields:I
+Ljava/io/ObjectStreamClass$FieldReflector;->offsets:[I
+Ljava/io/ObjectStreamClass$FieldReflector;->readKeys:[J
+Ljava/io/ObjectStreamClass$FieldReflector;->setObjFieldValues(Ljava/lang/Object;[Ljava/lang/Object;)V
+Ljava/io/ObjectStreamClass$FieldReflector;->setPrimFieldValues(Ljava/lang/Object;[B)V
+Ljava/io/ObjectStreamClass$FieldReflector;->typeCodes:[C
+Ljava/io/ObjectStreamClass$FieldReflector;->types:[Ljava/lang/Class;
+Ljava/io/ObjectStreamClass$FieldReflector;->unsafe:Lsun/misc/Unsafe;
+Ljava/io/ObjectStreamClass$FieldReflector;->writeKeys:[J
+Ljava/io/ObjectStreamClass$FieldReflectorKey;-><init>(Ljava/lang/Class;[Ljava/io/ObjectStreamField;Ljava/lang/ref/ReferenceQueue;)V
+Ljava/io/ObjectStreamClass$FieldReflectorKey;->hash:I
+Ljava/io/ObjectStreamClass$FieldReflectorKey;->nullClass:Z
+Ljava/io/ObjectStreamClass$FieldReflectorKey;->sigs:Ljava/lang/String;
+Ljava/io/ObjectStreamClass$MemberSignature;-><init>(Ljava/lang/reflect/Constructor;)V
+Ljava/io/ObjectStreamClass$MemberSignature;-><init>(Ljava/lang/reflect/Field;)V
+Ljava/io/ObjectStreamClass$MemberSignature;-><init>(Ljava/lang/reflect/Method;)V
+Ljava/io/ObjectStreamClass$MemberSignature;->member:Ljava/lang/reflect/Member;
+Ljava/io/ObjectStreamClass$MemberSignature;->name:Ljava/lang/String;
+Ljava/io/ObjectStreamClass$MemberSignature;->signature:Ljava/lang/String;
+Ljava/io/ObjectStreamClass$WeakClassKey;-><init>(Ljava/lang/Class;Ljava/lang/ref/ReferenceQueue;)V
+Ljava/io/ObjectStreamClass$WeakClassKey;->hash:I
+Ljava/io/ObjectStreamClass;-><init>()V
+Ljava/io/ObjectStreamClass;-><init>(Ljava/lang/Class;)V
+Ljava/io/ObjectStreamClass;->checkDefaultSerialize()V
+Ljava/io/ObjectStreamClass;->checkDeserialize()V
+Ljava/io/ObjectStreamClass;->checkSerialize()V
+Ljava/io/ObjectStreamClass;->cl:Ljava/lang/Class;
+Ljava/io/ObjectStreamClass;->classNamesEqual(Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/io/ObjectStreamClass;->cons:Ljava/lang/reflect/Constructor;
+Ljava/io/ObjectStreamClass;->dataLayout:[Ljava/io/ObjectStreamClass$ClassDataSlot;
+Ljava/io/ObjectStreamClass;->defaultSerializeEx:Ljava/io/ObjectStreamClass$ExceptionInfo;
+Ljava/io/ObjectStreamClass;->deserializeEx:Ljava/io/ObjectStreamClass$ExceptionInfo;
+Ljava/io/ObjectStreamClass;->externalizable:Z
+Ljava/io/ObjectStreamClass;->fieldRefl:Ljava/io/ObjectStreamClass$FieldReflector;
+Ljava/io/ObjectStreamClass;->getClassDataLayout()[Ljava/io/ObjectStreamClass$ClassDataSlot;
+Ljava/io/ObjectStreamClass;->getClassDataLayout0()[Ljava/io/ObjectStreamClass$ClassDataSlot;
+Ljava/io/ObjectStreamClass;->getClassSignature(Ljava/lang/Class;)Ljava/lang/String;
+Ljava/io/ObjectStreamClass;->getDeclaredSerialFields(Ljava/lang/Class;)[Ljava/io/ObjectStreamField;
+Ljava/io/ObjectStreamClass;->getDeclaredSUID(Ljava/lang/Class;)Ljava/lang/Long;
+Ljava/io/ObjectStreamClass;->getDefaultSerialFields(Ljava/lang/Class;)[Ljava/io/ObjectStreamField;
+Ljava/io/ObjectStreamClass;->getExternalizableConstructor(Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
+Ljava/io/ObjectStreamClass;->getField(Ljava/lang/String;Ljava/lang/Class;)Ljava/io/ObjectStreamField;
+Ljava/io/ObjectStreamClass;->getFields(Z)[Ljava/io/ObjectStreamField;
+Ljava/io/ObjectStreamClass;->getInheritableMethod(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/reflect/Method;
+Ljava/io/ObjectStreamClass;->getMethodSignature([Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/String;
+Ljava/io/ObjectStreamClass;->getObjFieldValues(Ljava/lang/Object;[Ljava/lang/Object;)V
+Ljava/io/ObjectStreamClass;->getPackageName(Ljava/lang/Class;)Ljava/lang/String;
+Ljava/io/ObjectStreamClass;->getPrimFieldValues(Ljava/lang/Object;[B)V
+Ljava/io/ObjectStreamClass;->getPrivateMethod(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/reflect/Method;
+Ljava/io/ObjectStreamClass;->getReflector([Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamClass;)Ljava/io/ObjectStreamClass$FieldReflector;
+Ljava/io/ObjectStreamClass;->getResolveException()Ljava/lang/ClassNotFoundException;
+Ljava/io/ObjectStreamClass;->getSerialFields(Ljava/lang/Class;)[Ljava/io/ObjectStreamField;
+Ljava/io/ObjectStreamClass;->getSerializableConstructor(Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
+Ljava/io/ObjectStreamClass;->getSuperDesc()Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectStreamClass;->getVariantFor(Ljava/lang/Class;)Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectStreamClass;->hasBlockExternalData()Z
+Ljava/io/ObjectStreamClass;->hasBlockExternalData:Z
+Ljava/io/ObjectStreamClass;->hasReadResolveMethod()Z
+Ljava/io/ObjectStreamClass;->hasStaticInitializer(Ljava/lang/Class;Z)Z
+Ljava/io/ObjectStreamClass;->hasWriteObjectData:Z
+Ljava/io/ObjectStreamClass;->hasWriteObjectMethod()Z
+Ljava/io/ObjectStreamClass;->hasWriteReplaceMethod()Z
+Ljava/io/ObjectStreamClass;->initialized:Z
+Ljava/io/ObjectStreamClass;->initNonProxy(Ljava/io/ObjectStreamClass;Ljava/lang/Class;Ljava/lang/ClassNotFoundException;Ljava/io/ObjectStreamClass;)V
+Ljava/io/ObjectStreamClass;->initProxy(Ljava/lang/Class;Ljava/lang/ClassNotFoundException;Ljava/io/ObjectStreamClass;)V
+Ljava/io/ObjectStreamClass;->invokeReadObject(Ljava/lang/Object;Ljava/io/ObjectInputStream;)V
+Ljava/io/ObjectStreamClass;->invokeReadObjectNoData(Ljava/lang/Object;)V
+Ljava/io/ObjectStreamClass;->invokeReadResolve(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/io/ObjectStreamClass;->invokeWriteObject(Ljava/lang/Object;Ljava/io/ObjectOutputStream;)V
+Ljava/io/ObjectStreamClass;->invokeWriteReplace(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/io/ObjectStreamClass;->isEnum()Z
+Ljava/io/ObjectStreamClass;->isEnum:Z
+Ljava/io/ObjectStreamClass;->isExternalizable()Z
+Ljava/io/ObjectStreamClass;->isInstantiable()Z
+Ljava/io/ObjectStreamClass;->isProxy()Z
+Ljava/io/ObjectStreamClass;->isProxy:Z
+Ljava/io/ObjectStreamClass;->isSerializable()Z
+Ljava/io/ObjectStreamClass;->localDesc:Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectStreamClass;->lookup(Ljava/lang/Class;Z)Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectStreamClass;->matchFields([Ljava/io/ObjectStreamField;Ljava/io/ObjectStreamClass;)[Ljava/io/ObjectStreamField;
+Ljava/io/ObjectStreamClass;->MAX_SDK_TARGET_FOR_CLINIT_UIDGEN_WORKAROUND:I
+Ljava/io/ObjectStreamClass;->name:Ljava/lang/String;
+Ljava/io/ObjectStreamClass;->numObjFields:I
+Ljava/io/ObjectStreamClass;->packageEquals(Ljava/lang/Class;Ljava/lang/Class;)Z
+Ljava/io/ObjectStreamClass;->primDataSize:I
+Ljava/io/ObjectStreamClass;->processQueue(Ljava/lang/ref/ReferenceQueue;Ljava/util/concurrent/ConcurrentMap;)V
+Ljava/io/ObjectStreamClass;->readNonProxy(Ljava/io/ObjectInputStream;)V
+Ljava/io/ObjectStreamClass;->readObjectMethod:Ljava/lang/reflect/Method;
+Ljava/io/ObjectStreamClass;->readObjectNoDataMethod:Ljava/lang/reflect/Method;
+Ljava/io/ObjectStreamClass;->readResolveMethod:Ljava/lang/reflect/Method;
+Ljava/io/ObjectStreamClass;->requireInitialized()V
+Ljava/io/ObjectStreamClass;->resolveEx:Ljava/lang/ClassNotFoundException;
+Ljava/io/ObjectStreamClass;->serializable:Z
+Ljava/io/ObjectStreamClass;->serializeEx:Ljava/io/ObjectStreamClass$ExceptionInfo;
+Ljava/io/ObjectStreamClass;->setObjFieldValues(Ljava/lang/Object;[Ljava/lang/Object;)V
+Ljava/io/ObjectStreamClass;->setPrimFieldValues(Ljava/lang/Object;[B)V
+Ljava/io/ObjectStreamClass;->suid:Ljava/lang/Long;
+Ljava/io/ObjectStreamClass;->superDesc:Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectStreamClass;->throwMiscException(Ljava/lang/Throwable;)V
+Ljava/io/ObjectStreamClass;->writeNonProxy(Ljava/io/ObjectOutputStream;)V
+Ljava/io/ObjectStreamClass;->writeObjectMethod:Ljava/lang/reflect/Method;
+Ljava/io/ObjectStreamClass;->writeReplaceMethod:Ljava/lang/reflect/Method;
+Ljava/io/ObjectStreamField;-><init>(Ljava/lang/reflect/Field;ZZ)V
+Ljava/io/ObjectStreamField;-><init>(Ljava/lang/String;Ljava/lang/String;Z)V
+Ljava/io/ObjectStreamField;->field:Ljava/lang/reflect/Field;
+Ljava/io/ObjectStreamField;->getClassSignature(Ljava/lang/Class;)Ljava/lang/String;
+Ljava/io/ObjectStreamField;->getSignature()Ljava/lang/String;
+Ljava/io/ObjectStreamField;->name:Ljava/lang/String;
+Ljava/io/ObjectStreamField;->offset:I
+Ljava/io/ObjectStreamField;->signature:Ljava/lang/String;
+Ljava/io/ObjectStreamField;->type:Ljava/lang/Class;
+Ljava/io/ObjectStreamField;->unshared:Z
+Ljava/io/OptionalDataException;-><init>(I)V
+Ljava/io/OptionalDataException;-><init>(Z)V
+Ljava/io/OutputStreamWriter;->flushBuffer()V
+Ljava/io/OutputStreamWriter;->se:Lsun/nio/cs/StreamEncoder;
+Ljava/io/PipedInputStream;->awaitSpace()V
+Ljava/io/PipedInputStream;->checkStateForReceive()V
+Ljava/io/PipedInputStream;->closedByReader:Z
+Ljava/io/PipedInputStream;->closedByWriter:Z
+Ljava/io/PipedInputStream;->connected:Z
+Ljava/io/PipedInputStream;->DEFAULT_PIPE_SIZE:I
+Ljava/io/PipedInputStream;->initPipe(I)V
+Ljava/io/PipedInputStream;->readSide:Ljava/lang/Thread;
+Ljava/io/PipedInputStream;->receive([BII)V
+Ljava/io/PipedInputStream;->receivedLast()V
+Ljava/io/PipedInputStream;->writeSide:Ljava/lang/Thread;
+Ljava/io/PipedOutputStream;->sink:Ljava/io/PipedInputStream;
+Ljava/io/PipedReader;->buffer:[C
+Ljava/io/PipedReader;->closedByReader:Z
+Ljava/io/PipedReader;->closedByWriter:Z
+Ljava/io/PipedReader;->connected:Z
+Ljava/io/PipedReader;->DEFAULT_PIPE_SIZE:I
+Ljava/io/PipedReader;->in:I
+Ljava/io/PipedReader;->initPipe(I)V
+Ljava/io/PipedReader;->out:I
+Ljava/io/PipedReader;->readSide:Ljava/lang/Thread;
+Ljava/io/PipedReader;->receive(I)V
+Ljava/io/PipedReader;->receive([CII)V
+Ljava/io/PipedReader;->receivedLast()V
+Ljava/io/PipedReader;->writeSide:Ljava/lang/Thread;
+Ljava/io/PipedWriter;->closed:Z
+Ljava/io/PipedWriter;->sink:Ljava/io/PipedReader;
+Ljava/io/PrintStream;-><init>(ZLjava/io/OutputStream;)V
+Ljava/io/PrintStream;-><init>(ZLjava/io/OutputStream;Ljava/nio/charset/Charset;)V
+Ljava/io/PrintStream;-><init>(ZLjava/nio/charset/Charset;Ljava/io/OutputStream;)V
+Ljava/io/PrintStream;->autoFlush:Z
+Ljava/io/PrintStream;->charOut:Ljava/io/OutputStreamWriter;
+Ljava/io/PrintStream;->charset:Ljava/nio/charset/Charset;
+Ljava/io/PrintStream;->closing:Z
+Ljava/io/PrintStream;->ensureOpen()V
+Ljava/io/PrintStream;->formatter:Ljava/util/Formatter;
+Ljava/io/PrintStream;->getTextOut()Ljava/io/BufferedWriter;
+Ljava/io/PrintStream;->newLine()V
+Ljava/io/PrintStream;->requireNonNull(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
+Ljava/io/PrintStream;->textOut:Ljava/io/BufferedWriter;
+Ljava/io/PrintStream;->toCharset(Ljava/lang/String;)Ljava/nio/charset/Charset;
+Ljava/io/PrintStream;->trouble:Z
+Ljava/io/PrintStream;->write(Ljava/lang/String;)V
+Ljava/io/PrintStream;->write([C)V
+Ljava/io/PrintWriter;-><init>(Ljava/nio/charset/Charset;Ljava/io/File;)V
+Ljava/io/PrintWriter;->autoFlush:Z
+Ljava/io/PrintWriter;->ensureOpen()V
+Ljava/io/PrintWriter;->formatter:Ljava/util/Formatter;
+Ljava/io/PrintWriter;->lineSeparator:Ljava/lang/String;
+Ljava/io/PrintWriter;->newLine()V
+Ljava/io/PrintWriter;->psOut:Ljava/io/PrintStream;
+Ljava/io/PrintWriter;->toCharset(Ljava/lang/String;)Ljava/nio/charset/Charset;
+Ljava/io/PrintWriter;->trouble:Z
+Ljava/io/PushbackInputStream;->ensureOpen()V
+Ljava/io/PushbackReader;->buf:[C
+Ljava/io/PushbackReader;->ensureOpen()V
+Ljava/io/PushbackReader;->pos:I
+Ljava/io/RandomAccessFile;->channel:Ljava/nio/channels/FileChannel;
+Ljava/io/RandomAccessFile;->closed:Z
+Ljava/io/RandomAccessFile;->closeLock:Ljava/lang/Object;
+Ljava/io/RandomAccessFile;->flushAfterWrite:I
+Ljava/io/RandomAccessFile;->FLUSH_FDATASYNC:I
+Ljava/io/RandomAccessFile;->FLUSH_FSYNC:I
+Ljava/io/RandomAccessFile;->FLUSH_NONE:I
+Ljava/io/RandomAccessFile;->guard:Ldalvik/system/CloseGuard;
+Ljava/io/RandomAccessFile;->ioTracker:Llibcore/io/IoTracker;
+Ljava/io/RandomAccessFile;->maybeSync()V
+Ljava/io/RandomAccessFile;->mode:I
+Ljava/io/RandomAccessFile;->path:Ljava/lang/String;
+Ljava/io/RandomAccessFile;->readBytes([BII)I
+Ljava/io/RandomAccessFile;->rw:Z
+Ljava/io/RandomAccessFile;->scratch:[B
+Ljava/io/RandomAccessFile;->writeBytes([BII)V
+Ljava/io/Reader;->maxSkipBufferSize:I
+Ljava/io/Reader;->skipBuffer:[C
+Ljava/io/SequenceInputStream;->e:Ljava/util/Enumeration;
+Ljava/io/SequenceInputStream;->in:Ljava/io/InputStream;
+Ljava/io/SequenceInputStream;->nextStream()V
+Ljava/io/SerialCallbackContext;-><init>(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V
+Ljava/io/SerialCallbackContext;->check()V
+Ljava/io/SerialCallbackContext;->checkAndSetUsed()V
+Ljava/io/SerialCallbackContext;->desc:Ljava/io/ObjectStreamClass;
+Ljava/io/SerialCallbackContext;->getDesc()Ljava/io/ObjectStreamClass;
+Ljava/io/SerialCallbackContext;->getObj()Ljava/lang/Object;
+Ljava/io/SerialCallbackContext;->obj:Ljava/lang/Object;
+Ljava/io/SerialCallbackContext;->setUsed()V
+Ljava/io/SerialCallbackContext;->thread:Ljava/lang/Thread;
+Ljava/io/StreamTokenizer;-><init>()V
+Ljava/io/StreamTokenizer;->buf:[C
+Ljava/io/StreamTokenizer;->ctype:[B
+Ljava/io/StreamTokenizer;->CT_ALPHA:B
+Ljava/io/StreamTokenizer;->CT_COMMENT:B
+Ljava/io/StreamTokenizer;->CT_DIGIT:B
+Ljava/io/StreamTokenizer;->CT_QUOTE:B
+Ljava/io/StreamTokenizer;->CT_WHITESPACE:B
+Ljava/io/StreamTokenizer;->eolIsSignificantP:Z
+Ljava/io/StreamTokenizer;->forceLower:Z
+Ljava/io/StreamTokenizer;->input:Ljava/io/InputStream;
+Ljava/io/StreamTokenizer;->LINENO:I
+Ljava/io/StreamTokenizer;->NEED_CHAR:I
+Ljava/io/StreamTokenizer;->peekc:I
+Ljava/io/StreamTokenizer;->pushedBack:Z
+Ljava/io/StreamTokenizer;->read()I
+Ljava/io/StreamTokenizer;->reader:Ljava/io/Reader;
+Ljava/io/StreamTokenizer;->SKIP_LF:I
+Ljava/io/StreamTokenizer;->slashSlashCommentsP:Z
+Ljava/io/StreamTokenizer;->slashStarCommentsP:Z
+Ljava/io/StreamTokenizer;->TT_NOTHING:I
+Ljava/io/StringReader;->ensureOpen()V
+Ljava/io/StringReader;->length:I
+Ljava/io/StringReader;->mark:I
+Ljava/io/StringReader;->next:I
+Ljava/io/StringReader;->str:Ljava/lang/String;
+Ljava/io/StringWriter;->buf:Ljava/lang/StringBuffer;
+Ljava/io/Writer;->writeBuffer:[C
+Ljava/io/Writer;->WRITE_BUFFER_SIZE:I
+Ljava/lang/AbstractStringBuilder;-><init>()V
+Ljava/lang/AbstractStringBuilder;-><init>(I)V
+Ljava/lang/AbstractStringBuilder;->append(D)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->append(F)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->append(I)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->append(J)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->append(Ljava/lang/AbstractStringBuilder;)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->append(Ljava/lang/Object;)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->append(Ljava/lang/String;)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->append(Ljava/lang/StringBuffer;)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->append(Z)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->append([C)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->append([CII)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->appendCodePoint(I)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->appendNull()Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->capacity()I
+Ljava/lang/AbstractStringBuilder;->codePointAt(I)I
+Ljava/lang/AbstractStringBuilder;->codePointBefore(I)I
+Ljava/lang/AbstractStringBuilder;->codePointCount(II)I
+Ljava/lang/AbstractStringBuilder;->count:I
+Ljava/lang/AbstractStringBuilder;->delete(II)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->deleteCharAt(I)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->ensureCapacity(I)V
+Ljava/lang/AbstractStringBuilder;->ensureCapacityInternal(I)V
+Ljava/lang/AbstractStringBuilder;->getChars(II[CI)V
+Ljava/lang/AbstractStringBuilder;->getValue()[C
+Ljava/lang/AbstractStringBuilder;->hugeCapacity(I)I
+Ljava/lang/AbstractStringBuilder;->indexOf(Ljava/lang/String;)I
+Ljava/lang/AbstractStringBuilder;->indexOf(Ljava/lang/String;I)I
+Ljava/lang/AbstractStringBuilder;->insert(IC)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(ID)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(IF)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(II)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(IJ)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(ILjava/lang/CharSequence;)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(ILjava/lang/CharSequence;II)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(ILjava/lang/Object;)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(ILjava/lang/String;)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(IZ)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(I[C)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->insert(I[CII)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->lastIndexOf(Ljava/lang/String;)I
+Ljava/lang/AbstractStringBuilder;->lastIndexOf(Ljava/lang/String;I)I
+Ljava/lang/AbstractStringBuilder;->MAX_ARRAY_SIZE:I
+Ljava/lang/AbstractStringBuilder;->newCapacity(I)I
+Ljava/lang/AbstractStringBuilder;->offsetByCodePoints(II)I
+Ljava/lang/AbstractStringBuilder;->replace(IILjava/lang/String;)Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->reverse()Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AbstractStringBuilder;->reverseAllValidSurrogatePairs()V
+Ljava/lang/AbstractStringBuilder;->setCharAt(IC)V
+Ljava/lang/AbstractStringBuilder;->setLength(I)V
+Ljava/lang/AbstractStringBuilder;->substring(I)Ljava/lang/String;
+Ljava/lang/AbstractStringBuilder;->substring(II)Ljava/lang/String;
+Ljava/lang/AbstractStringBuilder;->trimToSize()V
+Ljava/lang/AndroidHardcodedSystemProperties;-><init>()V
+Ljava/lang/AndroidHardcodedSystemProperties;->JAVA_VERSION:Ljava/lang/String;
+Ljava/lang/AndroidHardcodedSystemProperties;->STATIC_PROPERTIES:[[Ljava/lang/String;
+Ljava/lang/annotation/AnnotationTypeMismatchException;->element:Ljava/lang/reflect/Method;
+Ljava/lang/annotation/AnnotationTypeMismatchException;->foundType:Ljava/lang/String;
+Ljava/lang/annotation/IncompleteAnnotationException;->annotationType:Ljava/lang/Class;
+Ljava/lang/annotation/IncompleteAnnotationException;->elementName:Ljava/lang/String;
+Ljava/lang/ArrayIndexOutOfBoundsException;-><init>(II)V
+Ljava/lang/ArrayIndexOutOfBoundsException;-><init>(III)V
+Ljava/lang/AssertionError;-><init>(Ljava/lang/String;)V
+Ljava/lang/Byte$ByteCache;-><init>()V
+Ljava/lang/Byte$ByteCache;->cache:[Ljava/lang/Byte;
+Ljava/lang/Byte;->DIGITS:[C
+Ljava/lang/Byte;->UPPER_CASE_DIGITS:[C
+Ljava/lang/Character$CharacterCache;-><init>()V
+Ljava/lang/Character$CharacterCache;->cache:[Ljava/lang/Character;
+Ljava/lang/Character$Subset;->name:Ljava/lang/String;
+Ljava/lang/Character$UnicodeBlock;-><init>(Ljava/lang/String;)V
+Ljava/lang/Character$UnicodeBlock;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Ljava/lang/Character$UnicodeBlock;-><init>(Ljava/lang/String;Z)V
+Ljava/lang/Character$UnicodeBlock;->blocks:[Ljava/lang/Character$UnicodeBlock;
+Ljava/lang/Character$UnicodeBlock;->blockStarts:[I
+Ljava/lang/Character$UnicodeBlock;->map:Ljava/util/Map;
+Ljava/lang/Character$UnicodeScript;->aliases:Ljava/util/HashMap;
+Ljava/lang/Character$UnicodeScript;->scripts:[Ljava/lang/Character$UnicodeScript;
+Ljava/lang/Character$UnicodeScript;->scriptStarts:[I
+Ljava/lang/Character;->codePointAtImpl([CII)I
+Ljava/lang/Character;->codePointBeforeImpl([CII)I
+Ljava/lang/Character;->codePointCountImpl([CII)I
+Ljava/lang/Character;->digitImpl(II)I
+Ljava/lang/Character;->DIRECTIONALITY:[B
+Ljava/lang/Character;->ERROR:I
+Ljava/lang/Character;->getDirectionalityImpl(I)B
+Ljava/lang/Character;->getNameImpl(I)Ljava/lang/String;
+Ljava/lang/Character;->getNumericValueImpl(I)I
+Ljava/lang/Character;->getTypeImpl(I)I
+Ljava/lang/Character;->isAlphabeticImpl(I)Z
+Ljava/lang/Character;->isDefinedImpl(I)Z
+Ljava/lang/Character;->isDigitImpl(I)Z
+Ljava/lang/Character;->isIdentifierIgnorableImpl(I)Z
+Ljava/lang/Character;->isIdeographicImpl(I)Z
+Ljava/lang/Character;->isLetterImpl(I)Z
+Ljava/lang/Character;->isLetterOrDigitImpl(I)Z
+Ljava/lang/Character;->isLowerCaseImpl(I)Z
+Ljava/lang/Character;->isMirroredImpl(I)Z
+Ljava/lang/Character;->isSpaceCharImpl(I)Z
+Ljava/lang/Character;->isTitleCaseImpl(I)Z
+Ljava/lang/Character;->isUnicodeIdentifierPartImpl(I)Z
+Ljava/lang/Character;->isUnicodeIdentifierStartImpl(I)Z
+Ljava/lang/Character;->isUpperCaseImpl(I)Z
+Ljava/lang/Character;->isWhitespaceImpl(I)Z
+Ljava/lang/Character;->offsetByCodePointsImpl([CIIII)I
+Ljava/lang/Character;->toLowerCaseImpl(I)I
+Ljava/lang/Character;->toSurrogates(I[CI)V
+Ljava/lang/Character;->toTitleCaseImpl(I)I
+Ljava/lang/Character;->toUpperCaseImpl(I)I
+Ljava/lang/Class$Caches;-><init>()V
+Ljava/lang/Class$Caches;->genericInterfaces:Llibcore/util/BasicLruCache;
+Ljava/lang/Class;->ANNOTATION:I
+Ljava/lang/Class;->cannotCastMsg(Ljava/lang/Object;)Ljava/lang/String;
+Ljava/lang/Class;->classFlags:I
+Ljava/lang/Class;->classForName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
+Ljava/lang/Class;->classNameImpliesTopLevel()Z
+Ljava/lang/Class;->classSize:I
+Ljava/lang/Class;->componentType:Ljava/lang/Class;
+Ljava/lang/Class;->copiedMethodsOffset:S
+Ljava/lang/Class;->dexTypeIndex:I
+Ljava/lang/Class;->ENUM:I
+Ljava/lang/Class;->extData:Ldalvik/system/ClassExt;
+Ljava/lang/Class;->FINALIZABLE:I
+Ljava/lang/Class;->findInterfaceMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
+Ljava/lang/Class;->getAccessFlags()I
+Ljava/lang/Class;->getConstructor0([Ljava/lang/Class;I)Ljava/lang/reflect/Constructor;
+Ljava/lang/Class;->getDeclaredConstructorInternal([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
+Ljava/lang/Class;->getDeclaredConstructorsInternal(Z)[Ljava/lang/reflect/Constructor;
+Ljava/lang/Class;->getDeclaredFieldsUnchecked(Z)[Ljava/lang/reflect/Field;
+Ljava/lang/Class;->getDeclaredMethodInternal(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
+Ljava/lang/Class;->getEnclosingConstructorNative()Ljava/lang/reflect/Constructor;
+Ljava/lang/Class;->getEnclosingMethodNative()Ljava/lang/reflect/Method;
+Ljava/lang/Class;->getEnumConstantsShared()[Ljava/lang/Object;
+Ljava/lang/Class;->getInnerClassFlags(I)I
+Ljava/lang/Class;->getInnerClassName()Ljava/lang/String;
+Ljava/lang/Class;->getInstanceMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
+Ljava/lang/Class;->getInterfacesInternal()[Ljava/lang/Class;
+Ljava/lang/Class;->getNameNative()Ljava/lang/String;
+Ljava/lang/Class;->getPackageName$()Ljava/lang/String;
+Ljava/lang/Class;->getPrimitiveClass(Ljava/lang/String;)Ljava/lang/Class;
+Ljava/lang/Class;->getPublicDeclaredFields()[Ljava/lang/reflect/Field;
+Ljava/lang/Class;->getPublicFieldRecursive(Ljava/lang/String;)Ljava/lang/reflect/Field;
+Ljava/lang/Class;->getPublicFieldsRecursive(Ljava/util/List;)V
+Ljava/lang/Class;->getPublicMethodRecursive(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
+Ljava/lang/Class;->getPublicMethodsInternal(Ljava/util/List;)V
+Ljava/lang/Class;->getSignatureAnnotation()[Ljava/lang/String;
+Ljava/lang/Class;->getSignatureAttribute()Ljava/lang/String;
+Ljava/lang/Class;->iFields:J
+Ljava/lang/Class;->isDeclaredAnnotationPresent(Ljava/lang/Class;)Z
+Ljava/lang/Class;->isFinalizable()Z
+Ljava/lang/Class;->isLocalOrAnonymousClass()Z
+Ljava/lang/Class;->isProxy()Z
+Ljava/lang/Class;->methods:J
+Ljava/lang/Class;->numReferenceInstanceFields:I
+Ljava/lang/Class;->numReferenceStaticFields:I
+Ljava/lang/Class;->objectSizeAllocFastPath:I
+Ljava/lang/Class;->primitiveType:I
+Ljava/lang/Class;->referenceInstanceOffsets:I
+Ljava/lang/Class;->resolveName(Ljava/lang/String;)Ljava/lang/String;
+Ljava/lang/Class;->sFields:J
+Ljava/lang/Class;->superClass:Ljava/lang/Class;
+Ljava/lang/Class;->SYNTHETIC:I
+Ljava/lang/Class;->virtualMethodsOffset:S
+Ljava/lang/Class;->vtable:Ljava/lang/Object;
+Ljava/lang/ClassLoader$SystemClassLoader;-><init>()V
+Ljava/lang/ClassLoader$SystemClassLoader;->loader:Ljava/lang/ClassLoader;
+Ljava/lang/ClassLoader;-><init>(Ljava/lang/Void;Ljava/lang/ClassLoader;)V
+Ljava/lang/ClassLoader;->allocator:J
+Ljava/lang/ClassLoader;->checkCreateClassLoader()Ljava/lang/Void;
+Ljava/lang/ClassLoader;->classTable:J
+Ljava/lang/ClassLoader;->createSystemClassLoader()Ljava/lang/ClassLoader;
+Ljava/lang/ClassLoader;->findBootstrapClassOrNull(Ljava/lang/String;)Ljava/lang/Class;
+Ljava/lang/ClassLoader;->getBootstrapResource(Ljava/lang/String;)Ljava/net/URL;
+Ljava/lang/ClassLoader;->getBootstrapResources(Ljava/lang/String;)Ljava/util/Enumeration;
+Ljava/lang/ClassLoader;->packages:Ljava/util/HashMap;
+Ljava/lang/ClassLoader;->proxyCache:Ljava/util/Map;
+Ljava/lang/ClassNotFoundException;->ex:Ljava/lang/Throwable;
+Ljava/lang/Compiler;-><init>()V
+Ljava/lang/Daemons$Daemon;-><init>(Ljava/lang/String;)V
+Ljava/lang/Daemons$Daemon;->getStackTrace()[Ljava/lang/StackTraceElement;
+Ljava/lang/Daemons$Daemon;->interrupt()V
+Ljava/lang/Daemons$Daemon;->interrupt(Ljava/lang/Thread;)V
+Ljava/lang/Daemons$Daemon;->name:Ljava/lang/String;
+Ljava/lang/Daemons$Daemon;->postZygoteFork:Z
+Ljava/lang/Daemons$Daemon;->runInternal()V
+Ljava/lang/Daemons$Daemon;->startInternal()V
+Ljava/lang/Daemons$Daemon;->startPostZygoteFork()V
+Ljava/lang/Daemons$FinalizerDaemon;-><init>()V
+Ljava/lang/Daemons$FinalizerDaemon;->doFinalize(Ljava/lang/ref/FinalizerReference;)V
+Ljava/lang/Daemons$FinalizerDaemon;->progressCounter:Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/lang/Daemons$FinalizerDaemon;->queue:Ljava/lang/ref/ReferenceQueue;
+Ljava/lang/Daemons$FinalizerDaemon;->runInternal()V
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;-><init>()V
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;->finalizerTimedOut(Ljava/lang/Object;)V
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;->getNeedToWork()Z
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;->goToSleep()V
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;->needToWork:Z
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;->runInternal()V
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;->sleepFor(J)Z
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;->sleepUntilNeeded()Z
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;->waitForFinalization()Ljava/lang/Object;
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;->wakeUp()V
+Ljava/lang/Daemons$HeapTaskDaemon;-><init>()V
+Ljava/lang/Daemons$HeapTaskDaemon;->INSTANCE:Ljava/lang/Daemons$HeapTaskDaemon;
+Ljava/lang/Daemons$HeapTaskDaemon;->interrupt(Ljava/lang/Thread;)V
+Ljava/lang/Daemons$HeapTaskDaemon;->runInternal()V
+Ljava/lang/Daemons$ReferenceQueueDaemon;-><init>()V
+Ljava/lang/Daemons$ReferenceQueueDaemon;->runInternal()V
+Ljava/lang/Daemons;-><init>()V
+Ljava/lang/Daemons;->NANOS_PER_MILLI:I
+Ljava/lang/Daemons;->NANOS_PER_SECOND:I
+Ljava/lang/Daemons;->requestGC()V
+Ljava/lang/Daemons;->startPostZygoteFork()V
+Ljava/lang/Enum;->sharedConstantsCache:Llibcore/util/BasicLruCache;
+Ljava/lang/EnumConstantNotPresentException;->constantName:Ljava/lang/String;
+Ljava/lang/EnumConstantNotPresentException;->enumType:Ljava/lang/Class;
+Ljava/lang/ExceptionInInitializerError;->exception:Ljava/lang/Throwable;
+Ljava/lang/InheritableThreadLocal;->createMap(Ljava/lang/Thread;Ljava/lang/Object;)V
+Ljava/lang/InheritableThreadLocal;->getMap(Ljava/lang/Thread;)Ljava/lang/ThreadLocal$ThreadLocalMap;
+Ljava/lang/Integer$IntegerCache;-><init>()V
+Ljava/lang/Integer$IntegerCache;->cache:[Ljava/lang/Integer;
+Ljava/lang/Integer$IntegerCache;->high:I
+Ljava/lang/Integer$IntegerCache;->low:I
+Ljava/lang/Integer;->DigitOnes:[C
+Ljava/lang/Integer;->digits:[C
+Ljava/lang/Integer;->DigitTens:[C
+Ljava/lang/Integer;->formatUnsignedInt(II[CII)I
+Ljava/lang/Integer;->getChars(II[C)V
+Ljava/lang/Integer;->sizeTable:[I
+Ljava/lang/Integer;->SMALL_NEG_VALUES:[Ljava/lang/String;
+Ljava/lang/Integer;->SMALL_NONNEG_VALUES:[Ljava/lang/String;
+Ljava/lang/Integer;->stringSize(I)I
+Ljava/lang/Integer;->toUnsignedString0(II)Ljava/lang/String;
+Ljava/lang/invoke/CallSite;-><init>(Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/CallSite;-><init>(Ljava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/CallSite;-><init>(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/CallSite;->checkTargetChange(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/CallSite;->getTargetVolatile()Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/CallSite;->GET_TARGET:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/CallSite;->initializeGetTarget()V
+Ljava/lang/invoke/CallSite;->makeDynamicInvoker()Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/CallSite;->setTargetNormal(Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/CallSite;->setTargetVolatile(Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/CallSite;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/CallSite;->TARGET_OFFSET:J
+Ljava/lang/invoke/CallSite;->wrongTargetType(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/WrongMethodTypeException;
+Ljava/lang/invoke/ConstantCallSite;->isFrozen:Z
+Ljava/lang/invoke/MethodHandle;-><init>(JILjava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/MethodHandle;->artFieldOrMethod:J
+Ljava/lang/invoke/MethodHandle;->asCollectorChecks(Ljava/lang/Class;I)Z
+Ljava/lang/invoke/MethodHandle;->asSpreaderChecks(Ljava/lang/Class;I)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodHandle;->cachedSpreadInvoker:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandle;->duplicate()Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandle;->getHandleKind()I
+Ljava/lang/invoke/MethodHandle;->handleKind:I
+Ljava/lang/invoke/MethodHandle;->IGET:I
+Ljava/lang/invoke/MethodHandle;->INVOKE_CALLSITE_TRANSFORM:I
+Ljava/lang/invoke/MethodHandle;->INVOKE_DIRECT:I
+Ljava/lang/invoke/MethodHandle;->INVOKE_INTERFACE:I
+Ljava/lang/invoke/MethodHandle;->INVOKE_STATIC:I
+Ljava/lang/invoke/MethodHandle;->INVOKE_SUPER:I
+Ljava/lang/invoke/MethodHandle;->INVOKE_TRANSFORM:I
+Ljava/lang/invoke/MethodHandle;->INVOKE_VAR_HANDLE:I
+Ljava/lang/invoke/MethodHandle;->INVOKE_VAR_HANDLE_EXACT:I
+Ljava/lang/invoke/MethodHandle;->INVOKE_VIRTUAL:I
+Ljava/lang/invoke/MethodHandle;->IPUT:I
+Ljava/lang/invoke/MethodHandle;->nominalType:Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodHandle;->SGET:I
+Ljava/lang/invoke/MethodHandle;->spreadArrayChecks(Ljava/lang/Class;I)V
+Ljava/lang/invoke/MethodHandle;->SPUT:I
+Ljava/lang/invoke/MethodHandle;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/MethodHandle;->transformInternal(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/MethodHandle;->type:Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodHandleImpl$HandleInfo;-><init>(Ljava/lang/reflect/Member;Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/MethodHandleImpl$HandleInfo;->handle:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandleImpl$HandleInfo;->member:Ljava/lang/reflect/Member;
+Ljava/lang/invoke/MethodHandleImpl;-><init>(JILjava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/MethodHandleImpl;->getMemberInternal()Ljava/lang/reflect/Member;
+Ljava/lang/invoke/MethodHandleImpl;->info:Ljava/lang/invoke/MethodHandleImpl$HandleInfo;
+Ljava/lang/invoke/MethodHandleImpl;->reveal()Ljava/lang/invoke/MethodHandleInfo;
+Ljava/lang/invoke/MethodHandles$Lookup;-><init>(Ljava/lang/Class;)V
+Ljava/lang/invoke/MethodHandles$Lookup;->accessFailedMessage(Ljava/lang/Class;Ljava/lang/Class;I)Ljava/lang/String;
+Ljava/lang/invoke/MethodHandles$Lookup;->allowedModes:I
+Ljava/lang/invoke/MethodHandles$Lookup;->ALL_MODES:I
+Ljava/lang/invoke/MethodHandles$Lookup;->checkAccess(Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/String;)V
+Ljava/lang/invoke/MethodHandles$Lookup;->checkReturnType(Ljava/lang/reflect/Method;Ljava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/MethodHandles$Lookup;->checkSpecialCaller(Ljava/lang/Class;)V
+Ljava/lang/invoke/MethodHandles$Lookup;->checkUnprivilegedlookupClass(Ljava/lang/Class;I)V
+Ljava/lang/invoke/MethodHandles$Lookup;->commonFieldChecks(Ljava/lang/reflect/Field;Ljava/lang/Class;Ljava/lang/Class;ZZ)V
+Ljava/lang/invoke/MethodHandles$Lookup;->createMethodHandle(Ljava/lang/reflect/Method;ILjava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandles$Lookup;->createMethodHandleForConstructor(Ljava/lang/reflect/Constructor;)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandles$Lookup;->findAccessor(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandles$Lookup;->findAccessor(Ljava/lang/reflect/Field;Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandles$Lookup;->findFieldOfType(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/reflect/Field;
+Ljava/lang/invoke/MethodHandles$Lookup;->findSpecial(Ljava/lang/reflect/Method;Ljava/lang/invoke/MethodType;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandles$Lookup;->findStaticVarHandle(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;
+Ljava/lang/invoke/MethodHandles$Lookup;->findVarHandle(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;
+Ljava/lang/invoke/MethodHandles$Lookup;->findVirtualForMH(Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandles$Lookup;->findVirtualForVH(Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandles$Lookup;->fixmods(I)I
+Ljava/lang/invoke/MethodHandles$Lookup;->hasPrivateAccess()Z
+Ljava/lang/invoke/MethodHandles$Lookup;->initMethodType(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodHandles$Lookup;->lookupClass:Ljava/lang/Class;
+Ljava/lang/invoke/MethodHandles$Lookup;->PUBLIC_LOOKUP:Ljava/lang/invoke/MethodHandles$Lookup;
+Ljava/lang/invoke/MethodHandles$Lookup;->throwMakeAccessException(Ljava/lang/String;Ljava/lang/Object;)V
+Ljava/lang/invoke/MethodHandles$Lookup;->unreflectVarHandle(Ljava/lang/reflect/Field;)Ljava/lang/invoke/VarHandle;
+Ljava/lang/invoke/MethodHandles;-><init>()V
+Ljava/lang/invoke/MethodHandles;->arrayElementGetter([BI)B
+Ljava/lang/invoke/MethodHandles;->arrayElementGetter([CI)C
+Ljava/lang/invoke/MethodHandles;->arrayElementGetter([DI)D
+Ljava/lang/invoke/MethodHandles;->arrayElementGetter([FI)F
+Ljava/lang/invoke/MethodHandles;->arrayElementGetter([II)I
+Ljava/lang/invoke/MethodHandles;->arrayElementGetter([JI)J
+Ljava/lang/invoke/MethodHandles;->arrayElementGetter([SI)S
+Ljava/lang/invoke/MethodHandles;->arrayElementGetter([ZI)Z
+Ljava/lang/invoke/MethodHandles;->arrayElementSetter([BIB)V
+Ljava/lang/invoke/MethodHandles;->arrayElementSetter([CIC)V
+Ljava/lang/invoke/MethodHandles;->arrayElementSetter([DID)V
+Ljava/lang/invoke/MethodHandles;->arrayElementSetter([FIF)V
+Ljava/lang/invoke/MethodHandles;->arrayElementSetter([III)V
+Ljava/lang/invoke/MethodHandles;->arrayElementSetter([JIJ)V
+Ljava/lang/invoke/MethodHandles;->arrayElementSetter([SIS)V
+Ljava/lang/invoke/MethodHandles;->arrayElementSetter([ZIZ)V
+Ljava/lang/invoke/MethodHandles;->arrayElementVarHandle(Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;
+Ljava/lang/invoke/MethodHandles;->byteArrayViewVarHandle(Ljava/lang/Class;Ljava/nio/ByteOrder;)Ljava/lang/invoke/VarHandle;
+Ljava/lang/invoke/MethodHandles;->byteBufferViewVarHandle(Ljava/lang/Class;Ljava/nio/ByteOrder;)Ljava/lang/invoke/VarHandle;
+Ljava/lang/invoke/MethodHandles;->checkClassIsArray(Ljava/lang/Class;)V
+Ljava/lang/invoke/MethodHandles;->checkTypeIsViewable(Ljava/lang/Class;)V
+Ljava/lang/invoke/MethodHandles;->collectArgumentsChecks(Ljava/lang/invoke/MethodHandle;ILjava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodHandles;->copyTypes(Ljava/util/List;)Ljava/util/List;
+Ljava/lang/invoke/MethodHandles;->dropArgumentChecks(Ljava/lang/invoke/MethodType;ILjava/util/List;)I
+Ljava/lang/invoke/MethodHandles;->explicitCastArgumentsChecks(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/MethodHandles;->filterArgumentChecks(Ljava/lang/invoke/MethodHandle;ILjava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/MethodHandles;->filterArgumentsCheckArity(Ljava/lang/invoke/MethodHandle;I[Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/MethodHandles;->filterReturnValueChecks(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/MethodHandles;->foldArgumentChecks(ILjava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;)Ljava/lang/Class;
+Ljava/lang/invoke/MethodHandles;->getMethodHandleImpl(Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandleImpl;
+Ljava/lang/invoke/MethodHandles;->identity(B)B
+Ljava/lang/invoke/MethodHandles;->identity(C)C
+Ljava/lang/invoke/MethodHandles;->identity(D)D
+Ljava/lang/invoke/MethodHandles;->identity(F)F
+Ljava/lang/invoke/MethodHandles;->identity(I)I
+Ljava/lang/invoke/MethodHandles;->identity(J)J
+Ljava/lang/invoke/MethodHandles;->identity(S)S
+Ljava/lang/invoke/MethodHandles;->identity(Z)Z
+Ljava/lang/invoke/MethodHandles;->insertArgumentsChecks(Ljava/lang/invoke/MethodHandle;II)[Ljava/lang/Class;
+Ljava/lang/invoke/MethodHandles;->methodHandleForVarHandleAccessor(Ljava/lang/invoke/VarHandle$AccessMode;Ljava/lang/invoke/MethodType;Z)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandles;->misMatchedTypes(Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;)Ljava/lang/RuntimeException;
+Ljava/lang/invoke/MethodHandles;->permuteArgumentChecks([ILjava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;)Z
+Ljava/lang/invoke/MethodHandles;->varHandleExactInvoker(Ljava/lang/invoke/VarHandle$AccessMode;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandles;->varHandleInvoker(Ljava/lang/invoke/VarHandle$AccessMode;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry;-><init>(Ljava/lang/Object;)V
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry;->hashcode:I
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;-><init>()V
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;->add(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;->expungeStaleElements()V
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;->get(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;->map:Ljava/util/concurrent/ConcurrentMap;
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;->stale:Ljava/lang/ref/ReferenceQueue;
+Ljava/lang/invoke/MethodType;-><init>()V
+Ljava/lang/invoke/MethodType;-><init>(Ljava/lang/Class;[Ljava/lang/Class;Z)V
+Ljava/lang/invoke/MethodType;-><init>([Ljava/lang/Class;Ljava/lang/Class;)V
+Ljava/lang/invoke/MethodType;->asCollectorType(Ljava/lang/Class;I)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodType;->asSpreaderType(Ljava/lang/Class;I)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodType;->basicType()Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodType;->canConvert(Ljava/lang/Class;Ljava/lang/Class;)Z
+Ljava/lang/invoke/MethodType;->canConvertParameters([Ljava/lang/Class;[Ljava/lang/Class;)Z
+Ljava/lang/invoke/MethodType;->checkPtype(Ljava/lang/Class;)V
+Ljava/lang/invoke/MethodType;->checkPtypes([Ljava/lang/Class;)I
+Ljava/lang/invoke/MethodType;->checkRtype(Ljava/lang/Class;)V
+Ljava/lang/invoke/MethodType;->checkSlotCount(I)V
+Ljava/lang/invoke/MethodType;->equals(Ljava/lang/invoke/MethodType;)Z
+Ljava/lang/invoke/MethodType;->explicitCastEquivalentToAsType(Ljava/lang/Class;Ljava/lang/Class;)Z
+Ljava/lang/invoke/MethodType;->explicitCastEquivalentToAsType(Ljava/lang/invoke/MethodType;)Z
+Ljava/lang/invoke/MethodType;->form()Ljava/lang/invoke/MethodTypeForm;
+Ljava/lang/invoke/MethodType;->form:Ljava/lang/invoke/MethodTypeForm;
+Ljava/lang/invoke/MethodType;->internTable:Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;
+Ljava/lang/invoke/MethodType;->invokerType()Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodType;->isConvertibleTo(Ljava/lang/invoke/MethodType;)Z
+Ljava/lang/invoke/MethodType;->isGeneric()Z
+Ljava/lang/invoke/MethodType;->lastParameterType()Ljava/lang/Class;
+Ljava/lang/invoke/MethodType;->leadingReferenceParameter()Ljava/lang/Class;
+Ljava/lang/invoke/MethodType;->listToArray(Ljava/util/List;)[Ljava/lang/Class;
+Ljava/lang/invoke/MethodType;->makeImpl(Ljava/lang/Class;[Ljava/lang/Class;Z)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodType;->MAX_JVM_ARITY:I
+Ljava/lang/invoke/MethodType;->MAX_MH_ARITY:I
+Ljava/lang/invoke/MethodType;->MAX_MH_INVOKER_ARITY:I
+Ljava/lang/invoke/MethodType;->methodDescriptor:Ljava/lang/String;
+Ljava/lang/invoke/MethodType;->MethodType_init(Ljava/lang/Class;[Ljava/lang/Class;)V
+Ljava/lang/invoke/MethodType;->newIndexOutOfBoundsException(Ljava/lang/Object;)Ljava/lang/IndexOutOfBoundsException;
+Ljava/lang/invoke/MethodType;->NO_PTYPES:[Ljava/lang/Class;
+Ljava/lang/invoke/MethodType;->objectOnlyTypes:[Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodType;->parameterSlotCount()I
+Ljava/lang/invoke/MethodType;->ptypes()[Ljava/lang/Class;
+Ljava/lang/invoke/MethodType;->ptypes:[Ljava/lang/Class;
+Ljava/lang/invoke/MethodType;->ptypesOffset:J
+Ljava/lang/invoke/MethodType;->rtype()Ljava/lang/Class;
+Ljava/lang/invoke/MethodType;->rtype:Ljava/lang/Class;
+Ljava/lang/invoke/MethodType;->rtypeOffset:J
+Ljava/lang/invoke/MethodType;->toFieldDescriptorString(Ljava/lang/Class;)Ljava/lang/String;
+Ljava/lang/invoke/MethodType;->unwrapWithNoPrims(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodType;->wrapAlt:Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodType;->wrapWithPrims(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodTypeForm;-><init>(Ljava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/MethodTypeForm;->argCounts:J
+Ljava/lang/invoke/MethodTypeForm;->argSlotToParameter(I)I
+Ljava/lang/invoke/MethodTypeForm;->argToSlotTable:[I
+Ljava/lang/invoke/MethodTypeForm;->assertIsBasicType()Z
+Ljava/lang/invoke/MethodTypeForm;->basicType()Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodTypeForm;->basicType:Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodTypeForm;->canonicalize(Ljava/lang/Class;I)Ljava/lang/Class;
+Ljava/lang/invoke/MethodTypeForm;->canonicalize(Ljava/lang/invoke/MethodType;II)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodTypeForm;->canonicalizeAll([Ljava/lang/Class;I)[Ljava/lang/Class;
+Ljava/lang/invoke/MethodTypeForm;->ERASE:I
+Ljava/lang/invoke/MethodTypeForm;->erasedType()Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodTypeForm;->erasedType:Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodTypeForm;->findForm(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodTypeForm;
+Ljava/lang/invoke/MethodTypeForm;->hasLongPrimitives()Z
+Ljava/lang/invoke/MethodTypeForm;->hasNonVoidPrimitives()Z
+Ljava/lang/invoke/MethodTypeForm;->hasPrimitives()Z
+Ljava/lang/invoke/MethodTypeForm;->INTS:I
+Ljava/lang/invoke/MethodTypeForm;->longPrimitiveParameterCount()I
+Ljava/lang/invoke/MethodTypeForm;->longPrimitiveReturnCount()I
+Ljava/lang/invoke/MethodTypeForm;->LONGS:I
+Ljava/lang/invoke/MethodTypeForm;->NO_CHANGE:I
+Ljava/lang/invoke/MethodTypeForm;->pack(IIII)J
+Ljava/lang/invoke/MethodTypeForm;->parameterCount()I
+Ljava/lang/invoke/MethodTypeForm;->parameterSlotCount()I
+Ljava/lang/invoke/MethodTypeForm;->parameterToArgSlot(I)I
+Ljava/lang/invoke/MethodTypeForm;->primCounts:J
+Ljava/lang/invoke/MethodTypeForm;->primitiveParameterCount()I
+Ljava/lang/invoke/MethodTypeForm;->primitiveReturnCount()I
+Ljava/lang/invoke/MethodTypeForm;->RAW_RETURN:I
+Ljava/lang/invoke/MethodTypeForm;->returnCount()I
+Ljava/lang/invoke/MethodTypeForm;->returnSlotCount()I
+Ljava/lang/invoke/MethodTypeForm;->slotToArgTable:[I
+Ljava/lang/invoke/MethodTypeForm;->unpack(JI)C
+Ljava/lang/invoke/MethodTypeForm;->UNWRAP:I
+Ljava/lang/invoke/MethodTypeForm;->WRAP:I
+Ljava/lang/invoke/Transformers$AlwaysThrow;-><init>(Ljava/lang/Class;Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$AlwaysThrow;->exceptionType:Ljava/lang/Class;
+Ljava/lang/invoke/Transformers$AlwaysThrow;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$BindTo;-><init>(Ljava/lang/invoke/MethodHandle;Ljava/lang/Object;)V
+Ljava/lang/invoke/Transformers$BindTo;->delegate:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$BindTo;->range:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$BindTo;->receiver:Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$BindTo;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$CatchException;-><init>(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$CatchException;->exType:Ljava/lang/Class;
+Ljava/lang/invoke/Transformers$CatchException;->handler:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$CatchException;->handlerArgsRange:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$CatchException;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$CatchException;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$CollectArguments;-><init>(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;ILjava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/Transformers$CollectArguments;->collector:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$CollectArguments;->collectorRange:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$CollectArguments;->pos:I
+Ljava/lang/invoke/Transformers$CollectArguments;->range1:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$CollectArguments;->range2:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$CollectArguments;->referencesOffset:I
+Ljava/lang/invoke/Transformers$CollectArguments;->stackFrameOffset:I
+Ljava/lang/invoke/Transformers$CollectArguments;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$CollectArguments;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$Collector;-><init>(Ljava/lang/invoke/MethodHandle;Ljava/lang/Class;I)V
+Ljava/lang/invoke/Transformers$Collector;->arrayOffset:I
+Ljava/lang/invoke/Transformers$Collector;->arrayTypeChar:C
+Ljava/lang/invoke/Transformers$Collector;->copyRange:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$Collector;->numArrayArgs:I
+Ljava/lang/invoke/Transformers$Collector;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$Collector;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$Constant;-><init>(Ljava/lang/Class;Ljava/lang/Object;)V
+Ljava/lang/invoke/Transformers$Constant;->asDouble:D
+Ljava/lang/invoke/Transformers$Constant;->asFloat:F
+Ljava/lang/invoke/Transformers$Constant;->asInt:I
+Ljava/lang/invoke/Transformers$Constant;->asLong:J
+Ljava/lang/invoke/Transformers$Constant;->asReference:Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$Constant;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$Constant;->type:Ljava/lang/Class;
+Ljava/lang/invoke/Transformers$Constant;->typeChar:C
+Ljava/lang/invoke/Transformers$Construct;-><init>(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/Transformers$Construct;->callerRange:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$Construct;->checkInstantiable(Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$Construct;->constructorHandle:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$Construct;->getConstructorHandle()Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$Construct;->isAbstract(Ljava/lang/Class;)Z
+Ljava/lang/invoke/Transformers$Construct;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$DropArguments;-><init>(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;II)V
+Ljava/lang/invoke/Transformers$DropArguments;->delegate:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$DropArguments;->range1:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$DropArguments;->range2:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$DropArguments;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;-><init>(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->box(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;Ldalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->explicitCast(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;Ldalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->explicitCastArguments(Ldalvik/system/EmulatedStackFrame;Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->explicitCastFromBoolean(ZLdalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->explicitCastPrimitives(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;Ldalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->explicitCastReturnValue(Ldalvik/system/EmulatedStackFrame;Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->explicitCastToBoolean(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;Ldalvik/system/EmulatedStackFrame$StackFrameWriter;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->readPrimitiveAsByte(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;)B
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->readPrimitiveAsChar(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;)C
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->readPrimitiveAsDouble(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;)D
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->readPrimitiveAsFloat(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;)F
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->readPrimitiveAsInt(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;)I
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->readPrimitiveAsLong(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;)J
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->readPrimitiveAsShort(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ljava/lang/Class;)S
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->throwUnexpectedType(Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->toBoolean(B)Z
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->unbox(Ljava/lang/Object;Ljava/lang/Class;Ldalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->unboxNonNull(Ljava/lang/Object;Ljava/lang/Class;Ldalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$ExplicitCastArguments;->unboxNull(Ldalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$FilterArguments;-><init>(Ljava/lang/invoke/MethodHandle;I[Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/Transformers$FilterArguments;->deriveType(Ljava/lang/invoke/MethodHandle;I[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/Transformers$FilterArguments;->filters:[Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$FilterArguments;->pos:I
+Ljava/lang/invoke/Transformers$FilterArguments;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$FilterArguments;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$FilterReturnValue;-><init>(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/Transformers$FilterReturnValue;->allArgs:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$FilterReturnValue;->filter:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$FilterReturnValue;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$FilterReturnValue;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$FoldArguments;-><init>(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/Transformers$FoldArguments;->combiner:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$FoldArguments;->combinerArgs:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$FoldArguments;->deriveType(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/Transformers$FoldArguments;->referencesOffset:I
+Ljava/lang/invoke/Transformers$FoldArguments;->stackFrameOffset:I
+Ljava/lang/invoke/Transformers$FoldArguments;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$FoldArguments;->targetArgs:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$FoldArguments;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$GuardWithTest;-><init>(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/Transformers$GuardWithTest;->fallback:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$GuardWithTest;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$GuardWithTest;->test:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$GuardWithTest;->testArgsRange:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$GuardWithTest;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$InsertArguments;-><init>(Ljava/lang/invoke/MethodHandle;I[Ljava/lang/Object;)V
+Ljava/lang/invoke/Transformers$InsertArguments;->pos:I
+Ljava/lang/invoke/Transformers$InsertArguments;->range1:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$InsertArguments;->range2:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$InsertArguments;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$InsertArguments;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$InsertArguments;->values:[Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$Invoker;-><init>(Ljava/lang/invoke/MethodType;Z)V
+Ljava/lang/invoke/Transformers$Invoker;->copyRange:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$Invoker;->isExactInvoker:Z
+Ljava/lang/invoke/Transformers$Invoker;->targetType:Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/Transformers$Invoker;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$PermuteArguments;-><init>(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;[I)V
+Ljava/lang/invoke/Transformers$PermuteArguments;->reorder:[I
+Ljava/lang/invoke/Transformers$PermuteArguments;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$PermuteArguments;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$ReferenceArrayElementGetter;-><init>(Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$ReferenceArrayElementGetter;->arrayClass:Ljava/lang/Class;
+Ljava/lang/invoke/Transformers$ReferenceArrayElementGetter;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$ReferenceArrayElementSetter;-><init>(Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$ReferenceArrayElementSetter;->arrayClass:Ljava/lang/Class;
+Ljava/lang/invoke/Transformers$ReferenceArrayElementSetter;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$ReferenceIdentity;-><init>(Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$ReferenceIdentity;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$ReferenceIdentity;->type:Ljava/lang/Class;
+Ljava/lang/invoke/Transformers$Spreader;-><init>(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;I)V
+Ljava/lang/invoke/Transformers$Spreader;->arrayOffset:I
+Ljava/lang/invoke/Transformers$Spreader;->arrayTypeChar:C
+Ljava/lang/invoke/Transformers$Spreader;->copyRange:Ldalvik/system/EmulatedStackFrame$Range;
+Ljava/lang/invoke/Transformers$Spreader;->numArrayArgs:I
+Ljava/lang/invoke/Transformers$Spreader;->spreadArray([BLdalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/invoke/MethodType;II)V
+Ljava/lang/invoke/Transformers$Spreader;->spreadArray([CLdalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/invoke/MethodType;II)V
+Ljava/lang/invoke/Transformers$Spreader;->spreadArray([DLdalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/invoke/MethodType;II)V
+Ljava/lang/invoke/Transformers$Spreader;->spreadArray([FLdalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/invoke/MethodType;II)V
+Ljava/lang/invoke/Transformers$Spreader;->spreadArray([ILdalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/invoke/MethodType;II)V
+Ljava/lang/invoke/Transformers$Spreader;->spreadArray([JLdalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/invoke/MethodType;II)V
+Ljava/lang/invoke/Transformers$Spreader;->spreadArray([Ljava/lang/Object;Ldalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/invoke/MethodType;II)V
+Ljava/lang/invoke/Transformers$Spreader;->spreadArray([SLdalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/invoke/MethodType;II)V
+Ljava/lang/invoke/Transformers$Spreader;->spreadArray([ZLdalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/invoke/MethodType;II)V
+Ljava/lang/invoke/Transformers$Spreader;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$Spreader;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$Transformer;-><init>(Ljava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/Transformers$Transformer;-><init>(Ljava/lang/invoke/MethodType;I)V
+Ljava/lang/invoke/Transformers$VarargsCollector;-><init>(Ljava/lang/invoke/MethodHandle;)V
+Ljava/lang/invoke/Transformers$VarargsCollector;->arityArgumentsConvertible([Ljava/lang/Class;ILjava/lang/Class;)Z
+Ljava/lang/invoke/Transformers$VarargsCollector;->booleanArray(Ldalvik/system/EmulatedStackFrame$StackFrameReader;[Ljava/lang/Class;II)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->byteArray(Ldalvik/system/EmulatedStackFrame$StackFrameReader;[Ljava/lang/Class;II)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->charArray(Ldalvik/system/EmulatedStackFrame$StackFrameReader;[Ljava/lang/Class;II)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->collectArguments(CLjava/lang/Class;Ldalvik/system/EmulatedStackFrame$StackFrameReader;[Ljava/lang/Class;II)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->copyParameter(Ldalvik/system/EmulatedStackFrame$StackFrameReader;Ldalvik/system/EmulatedStackFrame$StackFrameWriter;Ljava/lang/Class;)V
+Ljava/lang/invoke/Transformers$VarargsCollector;->doubleArray(Ldalvik/system/EmulatedStackFrame$StackFrameReader;[Ljava/lang/Class;II)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->floatArray(Ldalvik/system/EmulatedStackFrame$StackFrameReader;[Ljava/lang/Class;II)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->intArray(Ldalvik/system/EmulatedStackFrame$StackFrameReader;[Ljava/lang/Class;II)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->lastParameterTypeIsAnArray([Ljava/lang/Class;)Z
+Ljava/lang/invoke/Transformers$VarargsCollector;->longArray(Ldalvik/system/EmulatedStackFrame$StackFrameReader;[Ljava/lang/Class;II)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->makeArityArray(Ljava/lang/invoke/MethodType;Ldalvik/system/EmulatedStackFrame$StackFrameReader;ILjava/lang/Class;)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->makeTargetFrameType(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/Transformers$VarargsCollector;->prepareFrame(Ldalvik/system/EmulatedStackFrame;Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers$VarargsCollector;->referenceArray(Ldalvik/system/EmulatedStackFrame$StackFrameReader;[Ljava/lang/Class;Ljava/lang/Class;II)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->shortArray(Ldalvik/system/EmulatedStackFrame$StackFrameReader;[Ljava/lang/Class;II)Ljava/lang/Object;
+Ljava/lang/invoke/Transformers$VarargsCollector;->target:Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/Transformers$VarargsCollector;->throwWrongMethodTypeException(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;)V
+Ljava/lang/invoke/Transformers$VarargsCollector;->transform(Ldalvik/system/EmulatedStackFrame;)V
+Ljava/lang/invoke/Transformers;-><init>()V
+Ljava/lang/invoke/Transformers;->TRANSFORM_INTERNAL:Ljava/lang/reflect/Method;
+Ljava/lang/invoke/VarHandle$AccessMode;->at:Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle$AccessMode;->COMPARE_AND_EXCHANGE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->COMPARE_AND_EXCHANGE_ACQUIRE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->COMPARE_AND_EXCHANGE_RELEASE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->COMPARE_AND_SET:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_ACQUIRE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_ADD:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_ADD_ACQUIRE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_ADD_RELEASE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_BITWISE_AND:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_BITWISE_AND_ACQUIRE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_BITWISE_AND_RELEASE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_BITWISE_OR:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_BITWISE_OR_ACQUIRE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_BITWISE_OR_RELEASE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_BITWISE_XOR:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_BITWISE_XOR_ACQUIRE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_BITWISE_XOR_RELEASE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_SET:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_SET_ACQUIRE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_AND_SET_RELEASE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_OPAQUE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->GET_VOLATILE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->methodName()Ljava/lang/String;
+Ljava/lang/invoke/VarHandle$AccessMode;->methodName:Ljava/lang/String;
+Ljava/lang/invoke/VarHandle$AccessMode;->methodNameToAccessMode:Ljava/util/Map;
+Ljava/lang/invoke/VarHandle$AccessMode;->SET:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->SET_OPAQUE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->SET_RELEASE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->SET_VOLATILE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->valueFromMethodName(Ljava/lang/String;)Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->valueOf(Ljava/lang/String;)Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->values()[Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->WEAK_COMPARE_AND_SET:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->WEAK_COMPARE_AND_SET_ACQUIRE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->WEAK_COMPARE_AND_SET_PLAIN:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessMode;->WEAK_COMPARE_AND_SET_RELEASE:Ljava/lang/invoke/VarHandle$AccessMode;
+Ljava/lang/invoke/VarHandle$AccessType;->COMPARE_AND_EXCHANGE:Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle$AccessType;->COMPARE_AND_SWAP:Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle$AccessType;->GET:Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle$AccessType;->GET_AND_UPDATE:Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle$AccessType;->GET_AND_UPDATE_BITWISE:Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle$AccessType;->GET_AND_UPDATE_NUMERIC:Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle$AccessType;->SET:Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle$AccessType;->valueOf(Ljava/lang/String;)Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle$AccessType;->values()[Ljava/lang/invoke/VarHandle$AccessType;
+Ljava/lang/invoke/VarHandle;-><init>(Ljava/lang/Class;Ljava/lang/Class;ZLjava/lang/Class;Ljava/lang/Class;)V
+Ljava/lang/invoke/VarHandle;-><init>(Ljava/lang/Class;Z)V
+Ljava/lang/invoke/VarHandle;-><init>(Ljava/lang/Class;ZLjava/lang/Class;)V
+Ljava/lang/invoke/VarHandle;->accessModesBitMask:I
+Ljava/lang/invoke/VarHandle;->accessModeType(Ljava/lang/invoke/VarHandle$AccessMode;)Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/VarHandle;->accessTypesToBitMask(Ljava/util/EnumSet;)I
+Ljava/lang/invoke/VarHandle;->alignedAccessModesBitMask(Ljava/lang/Class;Z)I
+Ljava/lang/invoke/VarHandle;->ALL_MODES_BIT_MASK:I
+Ljava/lang/invoke/VarHandle;->ATOMIC_UPDATE_ACCESS_MODES_BIT_MASK:I
+Ljava/lang/invoke/VarHandle;->BITWISE_ATOMIC_UPDATE_ACCESS_MODES_BIT_MASK:I
+Ljava/lang/invoke/VarHandle;->coordinateType0:Ljava/lang/Class;
+Ljava/lang/invoke/VarHandle;->coordinateType1:Ljava/lang/Class;
+Ljava/lang/invoke/VarHandle;->coordinateTypes()Ljava/util/List;
+Ljava/lang/invoke/VarHandle;->isAccessModeSupported(Ljava/lang/invoke/VarHandle$AccessMode;)Z
+Ljava/lang/invoke/VarHandle;->NUMERIC_ATOMIC_UPDATE_ACCESS_MODES_BIT_MASK:I
+Ljava/lang/invoke/VarHandle;->READ_ACCESS_MODES_BIT_MASK:I
+Ljava/lang/invoke/VarHandle;->toMethodHandle(Ljava/lang/invoke/VarHandle$AccessMode;)Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/VarHandle;->unalignedAccessModesBitMask(Ljava/lang/Class;)I
+Ljava/lang/invoke/VarHandle;->UNSAFE:Lsun/misc/Unsafe;
+Ljava/lang/invoke/VarHandle;->varType()Ljava/lang/Class;
+Ljava/lang/invoke/VarHandle;->varType:Ljava/lang/Class;
+Ljava/lang/invoke/VarHandle;->WRITE_ACCESS_MODES_BIT_MASK:I
+Ljava/lang/invoke/WrongMethodTypeException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/lang/invoke/WrongMethodTypeException;-><init>(Ljava/lang/Throwable;)V
+Ljava/lang/Long$LongCache;-><init>()V
+Ljava/lang/Long$LongCache;->cache:[Ljava/lang/Long;
+Ljava/lang/Long;->formatUnsignedLong(JI[CII)I
+Ljava/lang/Long;->getChars(JI[C)V
+Ljava/lang/Long;->stringSize(J)I
+Ljava/lang/Long;->toUnsignedBigInteger(J)Ljava/math/BigInteger;
+Ljava/lang/Long;->toUnsignedString0(JI)Ljava/lang/String;
+Ljava/lang/Math$RandomNumberGeneratorHolder;-><init>()V
+Ljava/lang/Math$RandomNumberGeneratorHolder;->randomNumberGenerator:Ljava/util/Random;
+Ljava/lang/Math;-><init>()V
+Ljava/lang/Math;->negativeZeroDoubleBits:J
+Ljava/lang/Math;->negativeZeroFloatBits:J
+Ljava/lang/Math;->powerOfTwoD(I)D
+Ljava/lang/Math;->powerOfTwoF(I)F
+Ljava/lang/Math;->randomIntInternal()I
+Ljava/lang/Math;->randomLongInternal()J
+Ljava/lang/Math;->setRandomSeedInternal(J)V
+Ljava/lang/Math;->twoToTheDoubleScaleDown:D
+Ljava/lang/Math;->twoToTheDoubleScaleUp:D
+Ljava/lang/NoClassDefFoundError;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/lang/NumberFormatException;->forInputString(Ljava/lang/String;)Ljava/lang/NumberFormatException;
+Ljava/lang/Object;->identityHashCodeNative(Ljava/lang/Object;)I
+Ljava/lang/Object;->internalClone()Ljava/lang/Object;
+Ljava/lang/Object;->shadow$_klass_:Ljava/lang/Class;
+Ljava/lang/Object;->shadow$_monitor_:I
+Ljava/lang/Package;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/net/URL;Ljava/lang/ClassLoader;)V
+Ljava/lang/Package;-><init>(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;Ljava/lang/ClassLoader;)V
+Ljava/lang/Package;->defineSystemPackage(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Package;
+Ljava/lang/Package;->getPackage(Ljava/lang/Class;)Ljava/lang/Package;
+Ljava/lang/Package;->getPackageInfo()Ljava/lang/Class;
+Ljava/lang/Package;->getSystemPackage(Ljava/lang/String;)Ljava/lang/Package;
+Ljava/lang/Package;->getSystemPackage0(Ljava/lang/String;)Ljava/lang/String;
+Ljava/lang/Package;->getSystemPackages()[Ljava/lang/Package;
+Ljava/lang/Package;->getSystemPackages0()[Ljava/lang/String;
+Ljava/lang/Package;->implTitle:Ljava/lang/String;
+Ljava/lang/Package;->implVendor:Ljava/lang/String;
+Ljava/lang/Package;->implVersion:Ljava/lang/String;
+Ljava/lang/Package;->loader:Ljava/lang/ClassLoader;
+Ljava/lang/Package;->loadManifest(Ljava/lang/String;)Ljava/util/jar/Manifest;
+Ljava/lang/Package;->mans:Ljava/util/Map;
+Ljava/lang/Package;->packageInfo:Ljava/lang/Class;
+Ljava/lang/Package;->pkgName:Ljava/lang/String;
+Ljava/lang/Package;->pkgs:Ljava/util/Map;
+Ljava/lang/Package;->sealBase:Ljava/net/URL;
+Ljava/lang/Package;->specTitle:Ljava/lang/String;
+Ljava/lang/Package;->specVendor:Ljava/lang/String;
+Ljava/lang/Package;->specVersion:Ljava/lang/String;
+Ljava/lang/Package;->urls:Ljava/util/Map;
+Ljava/lang/ProcessBuilder$NullInputStream;-><init>()V
+Ljava/lang/ProcessBuilder$NullInputStream;->INSTANCE:Ljava/lang/ProcessBuilder$NullInputStream;
+Ljava/lang/ProcessBuilder$NullOutputStream;-><init>()V
+Ljava/lang/ProcessBuilder$NullOutputStream;->INSTANCE:Ljava/lang/ProcessBuilder$NullOutputStream;
+Ljava/lang/ProcessBuilder$Redirect;-><init>()V
+Ljava/lang/ProcessBuilder$Redirect;->append()Z
+Ljava/lang/ProcessBuilder;->command:Ljava/util/List;
+Ljava/lang/ProcessBuilder;->directory:Ljava/io/File;
+Ljava/lang/ProcessBuilder;->environment([Ljava/lang/String;)Ljava/lang/ProcessBuilder;
+Ljava/lang/ProcessBuilder;->environment:Ljava/util/Map;
+Ljava/lang/ProcessBuilder;->redirectErrorStream:Z
+Ljava/lang/ProcessBuilder;->redirects()[Ljava/lang/ProcessBuilder$Redirect;
+Ljava/lang/ProcessBuilder;->redirects:[Ljava/lang/ProcessBuilder$Redirect;
+Ljava/lang/ref/FinalizerReference$Sentinel;-><init>()V
+Ljava/lang/ref/FinalizerReference$Sentinel;->awaitFinalization(J)V
+Ljava/lang/ref/FinalizerReference$Sentinel;->finalized:Z
+Ljava/lang/ref/FinalizerReference;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+Ljava/lang/ref/FinalizerReference;->enqueueSentinelReference(Ljava/lang/ref/FinalizerReference$Sentinel;)Z
+Ljava/lang/ref/FinalizerReference;->finalizeAllEnqueued(J)V
+Ljava/lang/ref/FinalizerReference;->getReferent()Ljava/lang/Object;
+Ljava/lang/ref/FinalizerReference;->LIST_LOCK:Ljava/lang/Object;
+Ljava/lang/ref/FinalizerReference;->makeCircularListIfUnenqueued()Z
+Ljava/lang/ref/FinalizerReference;->prev:Ljava/lang/ref/FinalizerReference;
+Ljava/lang/ref/FinalizerReference;->zombie:Ljava/lang/Object;
+Ljava/lang/ref/Reference$SinkHolder;-><init>()V
+Ljava/lang/ref/Reference$SinkHolder;->finalize_count:I
+Ljava/lang/ref/Reference$SinkHolder;->sink:Ljava/lang/Object;
+Ljava/lang/ref/Reference$SinkHolder;->sinkUser:Ljava/lang/Object;
+Ljava/lang/ref/Reference;-><init>(Ljava/lang/Object;)V
+Ljava/lang/ref/Reference;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+Ljava/lang/ref/Reference;->clearReferent()V
+Ljava/lang/ref/Reference;->disableIntrinsic:Z
+Ljava/lang/ref/Reference;->pendingNext:Ljava/lang/ref/Reference;
+Ljava/lang/ref/Reference;->queue:Ljava/lang/ref/ReferenceQueue;
+Ljava/lang/ref/Reference;->queueNext:Ljava/lang/ref/Reference;
+Ljava/lang/ref/Reference;->slowPathEnabled:Z
+Ljava/lang/ref/ReferenceQueue;->enqueue(Ljava/lang/ref/Reference;)Z
+Ljava/lang/ref/ReferenceQueue;->enqueueLocked(Ljava/lang/ref/Reference;)Z
+Ljava/lang/ref/ReferenceQueue;->enqueuePending(Ljava/lang/ref/Reference;)V
+Ljava/lang/ref/ReferenceQueue;->head:Ljava/lang/ref/Reference;
+Ljava/lang/ref/ReferenceQueue;->isEnqueued(Ljava/lang/ref/Reference;)Z
+Ljava/lang/ref/ReferenceQueue;->lock:Ljava/lang/Object;
+Ljava/lang/ref/ReferenceQueue;->reallyPollLocked()Ljava/lang/ref/Reference;
+Ljava/lang/ref/ReferenceQueue;->sQueueNextUnenqueued:Ljava/lang/ref/Reference;
+Ljava/lang/ref/ReferenceQueue;->tail:Ljava/lang/ref/Reference;
+Ljava/lang/ref/ReferenceQueue;->unenqueued:Ljava/lang/ref/Reference;
+Ljava/lang/ref/SoftReference;->clock:J
+Ljava/lang/ref/SoftReference;->timestamp:J
+Ljava/lang/reflect/AccessibleObject;->setAccessible0(Ljava/lang/reflect/AccessibleObject;Z)V
+Ljava/lang/reflect/Array;-><init>()V
+Ljava/lang/reflect/Array;->badArray(Ljava/lang/Object;)Ljava/lang/RuntimeException;
+Ljava/lang/reflect/Array;->createMultiArray(Ljava/lang/Class;[I)Ljava/lang/Object;
+Ljava/lang/reflect/Array;->createObjectArray(Ljava/lang/Class;I)Ljava/lang/Object;
+Ljava/lang/reflect/Array;->incompatibleType(Ljava/lang/Object;)Ljava/lang/IllegalArgumentException;
+Ljava/lang/reflect/Array;->newArray(Ljava/lang/Class;I)Ljava/lang/Object;
+Ljava/lang/reflect/Array;->notAnArray(Ljava/lang/Object;)Ljava/lang/IllegalArgumentException;
+Ljava/lang/reflect/Constructor;-><init>()V
+Ljava/lang/reflect/Constructor;-><init>(Ljava/lang/Class;Ljava/lang/Class;)V
+Ljava/lang/reflect/Constructor;->hasGenericInformation()Z
+Ljava/lang/reflect/Constructor;->newInstanceFromSerialization(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Object;
+Ljava/lang/reflect/Constructor;->ORDER_BY_SIGNATURE:Ljava/util/Comparator;
+Ljava/lang/reflect/Constructor;->serializationClass:Ljava/lang/Class;
+Ljava/lang/reflect/Constructor;->serializationCtor:Ljava/lang/Class;
+Ljava/lang/reflect/Constructor;->specificToGenericStringHeader(Ljava/lang/StringBuilder;)V
+Ljava/lang/reflect/Constructor;->specificToStringHeader(Ljava/lang/StringBuilder;)V
+Ljava/lang/reflect/Executable$GenericInfo;-><init>(Llibcore/reflect/ListOfTypes;Llibcore/reflect/ListOfTypes;Ljava/lang/reflect/Type;[Ljava/lang/reflect/TypeVariable;)V
+Ljava/lang/reflect/Executable$GenericInfo;->formalTypeParameters:[Ljava/lang/reflect/TypeVariable;
+Ljava/lang/reflect/Executable$GenericInfo;->genericExceptionTypes:Llibcore/reflect/ListOfTypes;
+Ljava/lang/reflect/Executable$GenericInfo;->genericParameterTypes:Llibcore/reflect/ListOfTypes;
+Ljava/lang/reflect/Executable$GenericInfo;->genericReturnType:Ljava/lang/reflect/Type;
+Ljava/lang/reflect/Executable;-><init>()V
+Ljava/lang/reflect/Executable;->accessFlags:I
+Ljava/lang/reflect/Executable;->compareMethodParametersInternal(Ljava/lang/reflect/Method;)I
+Ljava/lang/reflect/Executable;->declaringClass:Ljava/lang/Class;
+Ljava/lang/reflect/Executable;->declaringClassOfOverriddenMethod:Ljava/lang/Class;
+Ljava/lang/reflect/Executable;->dexMethodIndex:I
+Ljava/lang/reflect/Executable;->equalNameAndParametersInternal(Ljava/lang/reflect/Method;)Z
+Ljava/lang/reflect/Executable;->equalParamTypes([Ljava/lang/Class;[Ljava/lang/Class;)Z
+Ljava/lang/reflect/Executable;->fixMethodFlags(I)I
+Ljava/lang/reflect/Executable;->getAccessFlags()I
+Ljava/lang/reflect/Executable;->getAllGenericParameterTypes()[Ljava/lang/reflect/Type;
+Ljava/lang/reflect/Executable;->getAnnotationNative(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
+Ljava/lang/reflect/Executable;->getArtMethod()J
+Ljava/lang/reflect/Executable;->getDeclaredAnnotationsNative()[Ljava/lang/annotation/Annotation;
+Ljava/lang/reflect/Executable;->getDeclaringClassInternal()Ljava/lang/Class;
+Ljava/lang/reflect/Executable;->getMethodNameInternal()Ljava/lang/String;
+Ljava/lang/reflect/Executable;->getMethodOrConstructorGenericInfoInternal()Ljava/lang/reflect/Executable$GenericInfo;
+Ljava/lang/reflect/Executable;->getMethodReturnTypeInternal()Ljava/lang/Class;
+Ljava/lang/reflect/Executable;->getModifiersInternal()I
+Ljava/lang/reflect/Executable;->getParameterAnnotationsInternal()[[Ljava/lang/annotation/Annotation;
+Ljava/lang/reflect/Executable;->getParameterAnnotationsNative()[[Ljava/lang/annotation/Annotation;
+Ljava/lang/reflect/Executable;->getParameterCountInternal()I
+Ljava/lang/reflect/Executable;->getParameters0()[Ljava/lang/reflect/Parameter;
+Ljava/lang/reflect/Executable;->getParameterTypesInternal()[Ljava/lang/Class;
+Ljava/lang/reflect/Executable;->getSignatureAnnotation()[Ljava/lang/String;
+Ljava/lang/reflect/Executable;->getSignatureAttribute()Ljava/lang/String;
+Ljava/lang/reflect/Executable;->hasGenericInformation()Z
+Ljava/lang/reflect/Executable;->hasGenericInformationInternal()Z
+Ljava/lang/reflect/Executable;->hasRealParameterData()Z
+Ljava/lang/reflect/Executable;->hasRealParameterData:Z
+Ljava/lang/reflect/Executable;->isAnnotationPresentNative(Ljava/lang/Class;)Z
+Ljava/lang/reflect/Executable;->isBridgeMethodInternal()Z
+Ljava/lang/reflect/Executable;->isDefaultMethodInternal()Z
+Ljava/lang/reflect/Executable;->parameters:[Ljava/lang/reflect/Parameter;
+Ljava/lang/reflect/Executable;->printModifiersIfNonzero(Ljava/lang/StringBuilder;IZ)V
+Ljava/lang/reflect/Executable;->privateGetParameters()[Ljava/lang/reflect/Parameter;
+Ljava/lang/reflect/Executable;->separateWithCommas([Ljava/lang/Class;Ljava/lang/StringBuilder;)V
+Ljava/lang/reflect/Executable;->sharedToGenericString(IZ)Ljava/lang/String;
+Ljava/lang/reflect/Executable;->sharedToString(IZ[Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/String;
+Ljava/lang/reflect/Executable;->specificToGenericStringHeader(Ljava/lang/StringBuilder;)V
+Ljava/lang/reflect/Executable;->specificToStringHeader(Ljava/lang/StringBuilder;)V
+Ljava/lang/reflect/Executable;->synthesizeAllParams()[Ljava/lang/reflect/Parameter;
+Ljava/lang/reflect/Executable;->verifyParameters([Ljava/lang/reflect/Parameter;)V
+Ljava/lang/reflect/Field;-><init>()V
+Ljava/lang/reflect/Field;->declaringClass:Ljava/lang/Class;
+Ljava/lang/reflect/Field;->dexFieldIndex:I
+Ljava/lang/reflect/Field;->getAnnotationNative(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
+Ljava/lang/reflect/Field;->getArtField()J
+Ljava/lang/reflect/Field;->getDexFieldIndex()I
+Ljava/lang/reflect/Field;->getNameInternal()Ljava/lang/String;
+Ljava/lang/reflect/Field;->getSignatureAnnotation()[Ljava/lang/String;
+Ljava/lang/reflect/Field;->getSignatureAttribute()Ljava/lang/String;
+Ljava/lang/reflect/Field;->isAnnotationPresentNative(Ljava/lang/Class;)Z
+Ljava/lang/reflect/Field;->offset:I
+Ljava/lang/reflect/Field;->type:Ljava/lang/Class;
+Ljava/lang/reflect/InvocationTargetException;->target:Ljava/lang/Throwable;
+Ljava/lang/reflect/Method;-><init>()V
+Ljava/lang/reflect/Method;->equalNameAndParameters(Ljava/lang/reflect/Method;)Z
+Ljava/lang/reflect/Method;->hasGenericInformation()Z
+Ljava/lang/reflect/Method;->ORDER_BY_SIGNATURE:Ljava/util/Comparator;
+Ljava/lang/reflect/Method;->specificToGenericStringHeader(Ljava/lang/StringBuilder;)V
+Ljava/lang/reflect/Method;->specificToStringHeader(Ljava/lang/StringBuilder;)V
+Ljava/lang/reflect/Modifier;->ACCESS_MODIFIERS:I
+Ljava/lang/reflect/Modifier;->ANNOTATION:I
+Ljava/lang/reflect/Modifier;->BRIDGE:I
+Ljava/lang/reflect/Modifier;->CLASS_MODIFIERS:I
+Ljava/lang/reflect/Modifier;->CONSTRUCTOR:I
+Ljava/lang/reflect/Modifier;->CONSTRUCTOR_MODIFIERS:I
+Ljava/lang/reflect/Modifier;->DEFAULT:I
+Ljava/lang/reflect/Modifier;->ENUM:I
+Ljava/lang/reflect/Modifier;->FIELD_MODIFIERS:I
+Ljava/lang/reflect/Modifier;->INTERFACE_MODIFIERS:I
+Ljava/lang/reflect/Modifier;->isConstructor(I)Z
+Ljava/lang/reflect/Modifier;->isMandated(I)Z
+Ljava/lang/reflect/Modifier;->isSynthetic(I)Z
+Ljava/lang/reflect/Modifier;->MANDATED:I
+Ljava/lang/reflect/Modifier;->METHOD_MODIFIERS:I
+Ljava/lang/reflect/Modifier;->PARAMETER_MODIFIERS:I
+Ljava/lang/reflect/Modifier;->SYNTHETIC:I
+Ljava/lang/reflect/Modifier;->VARARGS:I
+Ljava/lang/reflect/Parameter;->executable:Ljava/lang/reflect/Executable;
+Ljava/lang/reflect/Parameter;->getAnnotationNative(Ljava/lang/reflect/Executable;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;
+Ljava/lang/reflect/Parameter;->getRealName()Ljava/lang/String;
+Ljava/lang/reflect/Parameter;->index:I
+Ljava/lang/reflect/Parameter;->modifiers:I
+Ljava/lang/reflect/Parameter;->name:Ljava/lang/String;
+Ljava/lang/reflect/Parameter;->parameterClassCache:Ljava/lang/Class;
+Ljava/lang/reflect/Parameter;->parameterTypeCache:Ljava/lang/reflect/Type;
+Ljava/lang/reflect/Proxy$Key1;-><init>(Ljava/lang/Class;)V
+Ljava/lang/reflect/Proxy$Key1;->hash:I
+Ljava/lang/reflect/Proxy$Key2;-><init>(Ljava/lang/Class;Ljava/lang/Class;)V
+Ljava/lang/reflect/Proxy$Key2;->hash:I
+Ljava/lang/reflect/Proxy$Key2;->ref2:Ljava/lang/ref/WeakReference;
+Ljava/lang/reflect/Proxy$KeyFactory;-><init>()V
+Ljava/lang/reflect/Proxy$KeyFactory;->apply(Ljava/lang/ClassLoader;[Ljava/lang/Class;)Ljava/lang/Object;
+Ljava/lang/reflect/Proxy$KeyX;-><init>([Ljava/lang/Class;)V
+Ljava/lang/reflect/Proxy$KeyX;->equals([Ljava/lang/ref/WeakReference;[Ljava/lang/ref/WeakReference;)Z
+Ljava/lang/reflect/Proxy$KeyX;->hash:I
+Ljava/lang/reflect/Proxy$KeyX;->refs:[Ljava/lang/ref/WeakReference;
+Ljava/lang/reflect/Proxy$ProxyClassFactory;-><init>()V
+Ljava/lang/reflect/Proxy$ProxyClassFactory;->apply(Ljava/lang/ClassLoader;[Ljava/lang/Class;)Ljava/lang/Class;
+Ljava/lang/reflect/Proxy$ProxyClassFactory;->nextUniqueNumber:Ljava/util/concurrent/atomic/AtomicLong;
+Ljava/lang/reflect/Proxy$ProxyClassFactory;->proxyClassNamePrefix:Ljava/lang/String;
+Ljava/lang/reflect/Proxy;-><init>()V
+Ljava/lang/reflect/Proxy;->constructorParams:[Ljava/lang/Class;
+Ljava/lang/reflect/Proxy;->deduplicateAndGetExceptions(Ljava/util/List;)Ljava/util/List;
+Ljava/lang/reflect/Proxy;->generateProxy(Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/ClassLoader;[Ljava/lang/reflect/Method;[[Ljava/lang/Class;)Ljava/lang/Class;
+Ljava/lang/reflect/Proxy;->getMethods([Ljava/lang/Class;)Ljava/util/List;
+Ljava/lang/reflect/Proxy;->getMethodsRecursive([Ljava/lang/Class;Ljava/util/List;)V
+Ljava/lang/reflect/Proxy;->intersectExceptions([Ljava/lang/Class;[Ljava/lang/Class;)[Ljava/lang/Class;
+Ljava/lang/reflect/Proxy;->key0:Ljava/lang/Object;
+Ljava/lang/reflect/Proxy;->ORDER_BY_SIGNATURE_AND_SUBTYPE:Ljava/util/Comparator;
+Ljava/lang/reflect/Proxy;->proxyClassCache:Ljava/lang/reflect/WeakCache;
+Ljava/lang/reflect/Proxy;->validateReturnTypes(Ljava/util/List;)V
+Ljava/lang/reflect/UndeclaredThrowableException;->undeclaredThrowable:Ljava/lang/Throwable;
+Ljava/lang/reflect/WeakCache$CacheKey;-><init>(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+Ljava/lang/reflect/WeakCache$CacheKey;->expungeFrom(Ljava/util/concurrent/ConcurrentMap;Ljava/util/concurrent/ConcurrentMap;)V
+Ljava/lang/reflect/WeakCache$CacheKey;->hash:I
+Ljava/lang/reflect/WeakCache$CacheKey;->NULL_KEY:Ljava/lang/Object;
+Ljava/lang/reflect/WeakCache$CacheKey;->valueOf(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)Ljava/lang/Object;
+Ljava/lang/reflect/WeakCache$CacheValue;-><init>(Ljava/lang/Object;)V
+Ljava/lang/reflect/WeakCache$CacheValue;->hash:I
+Ljava/lang/reflect/WeakCache$Factory;->key:Ljava/lang/Object;
+Ljava/lang/reflect/WeakCache$Factory;->parameter:Ljava/lang/Object;
+Ljava/lang/reflect/WeakCache$Factory;->subKey:Ljava/lang/Object;
+Ljava/lang/reflect/WeakCache$Factory;->valuesMap:Ljava/util/concurrent/ConcurrentMap;
+Ljava/lang/reflect/WeakCache$LookupValue;-><init>(Ljava/lang/Object;)V
+Ljava/lang/reflect/WeakCache$LookupValue;->value:Ljava/lang/Object;
+Ljava/lang/reflect/WeakCache;-><init>(Ljava/util/function/BiFunction;Ljava/util/function/BiFunction;)V
+Ljava/lang/reflect/WeakCache;->containsValue(Ljava/lang/Object;)Z
+Ljava/lang/reflect/WeakCache;->expungeStaleEntries()V
+Ljava/lang/reflect/WeakCache;->get(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/reflect/WeakCache;->map:Ljava/util/concurrent/ConcurrentMap;
+Ljava/lang/reflect/WeakCache;->refQueue:Ljava/lang/ref/ReferenceQueue;
+Ljava/lang/reflect/WeakCache;->reverseMap:Ljava/util/concurrent/ConcurrentMap;
+Ljava/lang/reflect/WeakCache;->size()I
+Ljava/lang/reflect/WeakCache;->subKeyFactory:Ljava/util/function/BiFunction;
+Ljava/lang/reflect/WeakCache;->valueFactory:Ljava/util/function/BiFunction;
+Ljava/lang/Runtime;->checkTargetSdkVersionForLoad(Ljava/lang/String;)V
+Ljava/lang/Runtime;->currentRuntime:Ljava/lang/Runtime;
+Ljava/lang/Runtime;->finalizeOnExit:Z
+Ljava/lang/Runtime;->getLibPaths()[Ljava/lang/String;
+Ljava/lang/Runtime;->initLibPaths()[Ljava/lang/String;
+Ljava/lang/Runtime;->load0(Ljava/lang/Class;Ljava/lang/String;)V
+Ljava/lang/Runtime;->nativeExit(I)V
+Ljava/lang/Runtime;->runFinalization0()V
+Ljava/lang/Runtime;->shutdownHooks:Ljava/util/List;
+Ljava/lang/Runtime;->shuttingDown:Z
+Ljava/lang/Runtime;->tracingMethods:Z
+Ljava/lang/Short$ShortCache;-><init>()V
+Ljava/lang/Short$ShortCache;->cache:[Ljava/lang/Short;
+Ljava/lang/StrictMath$RandomNumberGeneratorHolder;-><init>()V
+Ljava/lang/StrictMath$RandomNumberGeneratorHolder;->randomNumberGenerator:Ljava/util/Random;
+Ljava/lang/StrictMath;-><init>()V
+Ljava/lang/StrictMath;->floorOrCeil(DDDD)D
+Ljava/lang/String$CaseInsensitiveComparator;-><init>()V
+Ljava/lang/String$CaseInsensitiveComparator;->compare(Ljava/lang/String;Ljava/lang/String;)I
+Ljava/lang/String;->doReplace(CC)Ljava/lang/String;
+Ljava/lang/String;->fastSubstring(II)Ljava/lang/String;
+Ljava/lang/String;->getChars([CI)V
+Ljava/lang/String;->indexOf(Ljava/lang/String;Ljava/lang/String;I)I
+Ljava/lang/String;->indexOfSupplementary(II)I
+Ljava/lang/String;->lastIndexOf(Ljava/lang/String;Ljava/lang/String;I)I
+Ljava/lang/String;->lastIndexOfSupplementary(II)I
+Ljava/lang/String;->nonSyncContentEquals(Ljava/lang/AbstractStringBuilder;)Z
+Ljava/lang/StringBuffer;->append(Ljava/lang/AbstractStringBuilder;)Ljava/lang/StringBuffer;
+Ljava/lang/StringBuffer;->toStringCache:[C
+Ljava/lang/StringIndexOutOfBoundsException;-><init>(II)V
+Ljava/lang/StringIndexOutOfBoundsException;-><init>(III)V
+Ljava/lang/StringIndexOutOfBoundsException;-><init>(Ljava/lang/String;I)V
+Ljava/lang/StringIndexOutOfBoundsException;-><init>(Ljava/lang/String;II)V
+Ljava/lang/System$PropertiesWithNonOverrideableDefaults;-><init>(Ljava/util/Properties;)V
+Ljava/lang/System$PropertiesWithNonOverrideableDefaults;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/System;->addLegacyLocaleSystemProperties()V
+Ljava/lang/System;->arraycopy([DI[DII)V
+Ljava/lang/System;->arraycopyBooleanUnchecked([ZI[ZII)V
+Ljava/lang/System;->arraycopyByteUnchecked([BI[BII)V
+Ljava/lang/System;->arraycopyCharUnchecked([CI[CII)V
+Ljava/lang/System;->arraycopyDoubleUnchecked([DI[DII)V
+Ljava/lang/System;->arraycopyFloatUnchecked([FI[FII)V
+Ljava/lang/System;->arraycopyIntUnchecked([II[III)V
+Ljava/lang/System;->arraycopyLongUnchecked([JI[JII)V
+Ljava/lang/System;->arraycopyShortUnchecked([SI[SII)V
+Ljava/lang/System;->ARRAYCOPY_SHORT_BOOLEAN_ARRAY_THRESHOLD:I
+Ljava/lang/System;->ARRAYCOPY_SHORT_BYTE_ARRAY_THRESHOLD:I
+Ljava/lang/System;->ARRAYCOPY_SHORT_CHAR_ARRAY_THRESHOLD:I
+Ljava/lang/System;->ARRAYCOPY_SHORT_DOUBLE_ARRAY_THRESHOLD:I
+Ljava/lang/System;->ARRAYCOPY_SHORT_FLOAT_ARRAY_THRESHOLD:I
+Ljava/lang/System;->ARRAYCOPY_SHORT_INT_ARRAY_THRESHOLD:I
+Ljava/lang/System;->ARRAYCOPY_SHORT_LONG_ARRAY_THRESHOLD:I
+Ljava/lang/System;->ARRAYCOPY_SHORT_SHORT_ARRAY_THRESHOLD:I
+Ljava/lang/System;->checkKey(Ljava/lang/String;)V
+Ljava/lang/System;->cons:Ljava/io/Console;
+Ljava/lang/System;->initProperties()Ljava/util/Properties;
+Ljava/lang/System;->initUnchangeableSystemProperties()Ljava/util/Properties;
+Ljava/lang/System;->justRanFinalization:Z
+Ljava/lang/System;->lineSeparator:Ljava/lang/String;
+Ljava/lang/System;->LOCK:Ljava/lang/Object;
+Ljava/lang/System;->logI(Ljava/lang/String;)V
+Ljava/lang/System;->logI(Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/lang/System;->logW(Ljava/lang/String;)V
+Ljava/lang/System;->newPrintStream(Ljava/io/FileOutputStream;Ljava/lang/String;)Ljava/io/PrintStream;
+Ljava/lang/System;->parsePropertyAssignments(Ljava/util/Properties;[Ljava/lang/String;)V
+Ljava/lang/System;->props:Ljava/util/Properties;
+Ljava/lang/System;->runGC:Z
+Ljava/lang/System;->setDefaultChangeableProperties(Ljava/util/Properties;)Ljava/util/Properties;
+Ljava/lang/System;->setErr0(Ljava/io/PrintStream;)V
+Ljava/lang/System;->setIn0(Ljava/io/InputStream;)V
+Ljava/lang/System;->setOut0(Ljava/io/PrintStream;)V
+Ljava/lang/System;->setUnchangeableSystemProperty(Ljava/lang/String;Ljava/lang/String;)V
+Ljava/lang/System;->specialProperties()[Ljava/lang/String;
+Ljava/lang/System;->unchangeableProps:Ljava/util/Properties;
+Ljava/lang/Thread$Caches;-><init>()V
+Ljava/lang/Thread$Caches;->subclassAudits:Ljava/util/concurrent/ConcurrentMap;
+Ljava/lang/Thread$Caches;->subclassAuditsQueue:Ljava/lang/ref/ReferenceQueue;
+Ljava/lang/Thread$ParkState;-><init>()V
+Ljava/lang/Thread$ParkState;->PARKED:I
+Ljava/lang/Thread$ParkState;->PREEMPTIVELY_UNPARKED:I
+Ljava/lang/Thread$ParkState;->UNPARKED:I
+Ljava/lang/Thread$WeakClassKey;-><init>(Ljava/lang/Class;Ljava/lang/ref/ReferenceQueue;)V
+Ljava/lang/Thread$WeakClassKey;->hash:I
+Ljava/lang/Thread;->auditSubclass(Ljava/lang/Class;)Z
+Ljava/lang/Thread;->blockedOn(Lsun/nio/ch/Interruptible;)V
+Ljava/lang/Thread;->blocker:Lsun/nio/ch/Interruptible;
+Ljava/lang/Thread;->blockerLock:Ljava/lang/Object;
+Ljava/lang/Thread;->defaultUncaughtExceptionHandler:Ljava/lang/Thread$UncaughtExceptionHandler;
+Ljava/lang/Thread;->eetop:J
+Ljava/lang/Thread;->EMPTY_STACK_TRACE:[Ljava/lang/StackTraceElement;
+Ljava/lang/Thread;->exit()V
+Ljava/lang/Thread;->init(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;Ljava/lang/String;J)V
+Ljava/lang/Thread;->init2(Ljava/lang/Thread;)V
+Ljava/lang/Thread;->isCCLOverridden(Ljava/lang/Class;)Z
+Ljava/lang/Thread;->NANOS_PER_MILLI:I
+Ljava/lang/Thread;->nativeCreate(Ljava/lang/Thread;JZ)V
+Ljava/lang/Thread;->nativeGetStatus(Z)I
+Ljava/lang/Thread;->nativeHoldsLock(Ljava/lang/Object;)Z
+Ljava/lang/Thread;->nativeInterrupt()V
+Ljava/lang/Thread;->nativeParkEventPointer:J
+Ljava/lang/Thread;->nativeSetName(Ljava/lang/String;)V
+Ljava/lang/Thread;->nativeSetPriority(I)V
+Ljava/lang/Thread;->nextThreadID()J
+Ljava/lang/Thread;->nextThreadNum()I
+Ljava/lang/Thread;->parkFor$(J)V
+Ljava/lang/Thread;->parkState:I
+Ljava/lang/Thread;->parkUntil$(J)V
+Ljava/lang/Thread;->processQueue(Ljava/lang/ref/ReferenceQueue;Ljava/util/concurrent/ConcurrentMap;)V
+Ljava/lang/Thread;->setUncaughtExceptionPreHandler(Ljava/lang/Thread$UncaughtExceptionHandler;)V
+Ljava/lang/Thread;->single_step:Z
+Ljava/lang/Thread;->sleep(Ljava/lang/Object;JI)V
+Ljava/lang/Thread;->stackSize:J
+Ljava/lang/Thread;->started:Z
+Ljava/lang/Thread;->stillborn:Z
+Ljava/lang/Thread;->SUBCLASS_IMPLEMENTATION_PERMISSION:Ljava/lang/RuntimePermission;
+Ljava/lang/Thread;->threadInitNumber:I
+Ljava/lang/Thread;->threadLocalRandomProbe:I
+Ljava/lang/Thread;->threadLocalRandomSecondarySeed:I
+Ljava/lang/Thread;->threadLocalRandomSeed:J
+Ljava/lang/Thread;->threadQ:Ljava/lang/Thread;
+Ljava/lang/Thread;->threadStatus:I
+Ljava/lang/Thread;->tid:J
+Ljava/lang/Thread;->uncaughtExceptionHandler:Ljava/lang/Thread$UncaughtExceptionHandler;
+Ljava/lang/Thread;->uncaughtExceptionPreHandler:Ljava/lang/Thread$UncaughtExceptionHandler;
+Ljava/lang/Thread;->unpark$()V
+Ljava/lang/ThreadGroup;-><init>()V
+Ljava/lang/ThreadGroup;-><init>(Ljava/lang/Void;Ljava/lang/ThreadGroup;Ljava/lang/String;)V
+Ljava/lang/ThreadGroup;->add(Ljava/lang/ThreadGroup;)V
+Ljava/lang/ThreadGroup;->addUnstarted()V
+Ljava/lang/ThreadGroup;->checkParentAccess(Ljava/lang/ThreadGroup;)Ljava/lang/Void;
+Ljava/lang/ThreadGroup;->daemon:Z
+Ljava/lang/ThreadGroup;->destroyed:Z
+Ljava/lang/ThreadGroup;->enumerate([Ljava/lang/Thread;IZ)I
+Ljava/lang/ThreadGroup;->enumerate([Ljava/lang/ThreadGroup;IZ)I
+Ljava/lang/ThreadGroup;->list(Ljava/io/PrintStream;I)V
+Ljava/lang/ThreadGroup;->maxPriority:I
+Ljava/lang/ThreadGroup;->nthreads:I
+Ljava/lang/ThreadGroup;->nUnstartedThreads:I
+Ljava/lang/ThreadGroup;->remove(Ljava/lang/Thread;)V
+Ljava/lang/ThreadGroup;->remove(Ljava/lang/ThreadGroup;)V
+Ljava/lang/ThreadGroup;->stopOrSuspend(Z)Z
+Ljava/lang/ThreadGroup;->threads:[Ljava/lang/Thread;
+Ljava/lang/ThreadGroup;->threadStartFailed(Ljava/lang/Thread;)V
+Ljava/lang/ThreadGroup;->vmAllowSuspension:Z
+Ljava/lang/ThreadLocal$SuppliedThreadLocal;-><init>(Ljava/util/function/Supplier;)V
+Ljava/lang/ThreadLocal$SuppliedThreadLocal;->supplier:Ljava/util/function/Supplier;
+Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;-><init>(Ljava/lang/ThreadLocal;Ljava/lang/Object;)V
+Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;->value:Ljava/lang/Object;
+Ljava/lang/ThreadLocal$ThreadLocalMap;-><init>(Ljava/lang/ThreadLocal$ThreadLocalMap;)V
+Ljava/lang/ThreadLocal$ThreadLocalMap;-><init>(Ljava/lang/ThreadLocal;Ljava/lang/Object;)V
+Ljava/lang/ThreadLocal$ThreadLocalMap;->cleanSomeSlots(II)Z
+Ljava/lang/ThreadLocal$ThreadLocalMap;->expungeStaleEntries()V
+Ljava/lang/ThreadLocal$ThreadLocalMap;->expungeStaleEntry(I)I
+Ljava/lang/ThreadLocal$ThreadLocalMap;->getEntry(Ljava/lang/ThreadLocal;)Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+Ljava/lang/ThreadLocal$ThreadLocalMap;->getEntryAfterMiss(Ljava/lang/ThreadLocal;ILjava/lang/ThreadLocal$ThreadLocalMap$Entry;)Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+Ljava/lang/ThreadLocal$ThreadLocalMap;->INITIAL_CAPACITY:I
+Ljava/lang/ThreadLocal$ThreadLocalMap;->nextIndex(II)I
+Ljava/lang/ThreadLocal$ThreadLocalMap;->prevIndex(II)I
+Ljava/lang/ThreadLocal$ThreadLocalMap;->rehash()V
+Ljava/lang/ThreadLocal$ThreadLocalMap;->remove(Ljava/lang/ThreadLocal;)V
+Ljava/lang/ThreadLocal$ThreadLocalMap;->replaceStaleEntry(Ljava/lang/ThreadLocal;Ljava/lang/Object;I)V
+Ljava/lang/ThreadLocal$ThreadLocalMap;->resize()V
+Ljava/lang/ThreadLocal$ThreadLocalMap;->set(Ljava/lang/ThreadLocal;Ljava/lang/Object;)V
+Ljava/lang/ThreadLocal$ThreadLocalMap;->setThreshold(I)V
+Ljava/lang/ThreadLocal$ThreadLocalMap;->size:I
+Ljava/lang/ThreadLocal$ThreadLocalMap;->table:[Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+Ljava/lang/ThreadLocal$ThreadLocalMap;->threshold:I
+Ljava/lang/ThreadLocal;->childValue(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/ThreadLocal;->createInheritedMap(Ljava/lang/ThreadLocal$ThreadLocalMap;)Ljava/lang/ThreadLocal$ThreadLocalMap;
+Ljava/lang/ThreadLocal;->createMap(Ljava/lang/Thread;Ljava/lang/Object;)V
+Ljava/lang/ThreadLocal;->HASH_INCREMENT:I
+Ljava/lang/ThreadLocal;->nextHashCode()I
+Ljava/lang/ThreadLocal;->nextHashCode:Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/lang/ThreadLocal;->setInitialValue()Ljava/lang/Object;
+Ljava/lang/ThreadLocal;->threadLocalHashCode:I
+Ljava/lang/Throwable$PrintStreamOrWriter;-><init>()V
+Ljava/lang/Throwable$PrintStreamOrWriter;->lock()Ljava/lang/Object;
+Ljava/lang/Throwable$PrintStreamOrWriter;->println(Ljava/lang/Object;)V
+Ljava/lang/Throwable$SentinelHolder;-><init>()V
+Ljava/lang/Throwable$SentinelHolder;->STACK_TRACE_ELEMENT_SENTINEL:Ljava/lang/StackTraceElement;
+Ljava/lang/Throwable$SentinelHolder;->STACK_TRACE_SENTINEL:[Ljava/lang/StackTraceElement;
+Ljava/lang/Throwable$WrappedPrintStream;-><init>(Ljava/io/PrintStream;)V
+Ljava/lang/Throwable$WrappedPrintStream;->lock()Ljava/lang/Object;
+Ljava/lang/Throwable$WrappedPrintStream;->println(Ljava/lang/Object;)V
+Ljava/lang/Throwable$WrappedPrintStream;->printStream:Ljava/io/PrintStream;
+Ljava/lang/Throwable$WrappedPrintWriter;-><init>(Ljava/io/PrintWriter;)V
+Ljava/lang/Throwable$WrappedPrintWriter;->lock()Ljava/lang/Object;
+Ljava/lang/Throwable$WrappedPrintWriter;->println(Ljava/lang/Object;)V
+Ljava/lang/Throwable$WrappedPrintWriter;->printWriter:Ljava/io/PrintWriter;
+Ljava/lang/Throwable;->CAUSE_CAPTION:Ljava/lang/String;
+Ljava/lang/Throwable;->EMPTY_THROWABLE_ARRAY:[Ljava/lang/Throwable;
+Ljava/lang/Throwable;->nativeGetStackTrace(Ljava/lang/Object;)[Ljava/lang/StackTraceElement;
+Ljava/lang/Throwable;->NULL_CAUSE_MESSAGE:Ljava/lang/String;
+Ljava/lang/Throwable;->printEnclosedStackTrace(Ljava/lang/Throwable$PrintStreamOrWriter;[Ljava/lang/StackTraceElement;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;)V
+Ljava/lang/Throwable;->SELF_SUPPRESSION_MESSAGE:Ljava/lang/String;
+Ljava/lang/Throwable;->SUPPRESSED_CAPTION:Ljava/lang/String;
+Ljava/lang/TypeNotPresentException;->typeName:Ljava/lang/String;
+Ljava/math/BigDecimal;-><init>(II)V
+Ljava/math/BigDecimal;-><init>(JI)V
+Ljava/math/BigDecimal;->addAndMult10(Ljava/math/BigDecimal;Ljava/math/BigDecimal;I)Ljava/math/BigDecimal;
+Ljava/math/BigDecimal;->approxPrecision()I
+Ljava/math/BigDecimal;->bitLength(I)I
+Ljava/math/BigDecimal;->bitLength(J)I
+Ljava/math/BigDecimal;->bitLength:I
+Ljava/math/BigDecimal;->BI_SCALED_BY_ZERO:[Ljava/math/BigDecimal;
+Ljava/math/BigDecimal;->BI_SCALED_BY_ZERO_LENGTH:I
+Ljava/math/BigDecimal;->CH_ZEROS:[C
+Ljava/math/BigDecimal;->compareAbsoluteValues(JJ)I
+Ljava/math/BigDecimal;->compareForRounding(JJ)I
+Ljava/math/BigDecimal;->decimalDigitsInLong(J)I
+Ljava/math/BigDecimal;->divideBigIntegers(Ljava/math/BigInteger;Ljava/math/BigInteger;ILjava/math/RoundingMode;)Ljava/math/BigDecimal;
+Ljava/math/BigDecimal;->dividePrimitiveLongs(JJILjava/math/RoundingMode;)Ljava/math/BigDecimal;
+Ljava/math/BigDecimal;->FIVE_POW:[Ljava/math/BigInteger;
+Ljava/math/BigDecimal;->getUnscaledValue()Ljava/math/BigInteger;
+Ljava/math/BigDecimal;->hashCode:I
+Ljava/math/BigDecimal;->inplaceRound(Ljava/math/MathContext;)V
+Ljava/math/BigDecimal;->intVal:Ljava/math/BigInteger;
+Ljava/math/BigDecimal;->isZero()Z
+Ljava/math/BigDecimal;->LOG10_2:D
+Ljava/math/BigDecimal;->LONG_FIVE_POW:[J
+Ljava/math/BigDecimal;->LONG_FIVE_POW_BIT_LENGTH:[I
+Ljava/math/BigDecimal;->LONG_POWERS_OF_TEN_BIT_LENGTH:[I
+Ljava/math/BigDecimal;->movePoint(J)Ljava/math/BigDecimal;
+Ljava/math/BigDecimal;->precision:I
+Ljava/math/BigDecimal;->roundingBehavior(IILjava/math/RoundingMode;)I
+Ljava/math/BigDecimal;->safeLongToInt(J)I
+Ljava/math/BigDecimal;->scale:I
+Ljava/math/BigDecimal;->setUnscaledValue(Ljava/math/BigInteger;)V
+Ljava/math/BigDecimal;->smallRound(Ljava/math/MathContext;I)V
+Ljava/math/BigDecimal;->smallValue:J
+Ljava/math/BigDecimal;->TEN_POW:[Ljava/math/BigInteger;
+Ljava/math/BigDecimal;->toStringImage:Ljava/lang/String;
+Ljava/math/BigDecimal;->valueExact(I)J
+Ljava/math/BigDecimal;->zeroScaledBy(J)Ljava/math/BigDecimal;
+Ljava/math/BigDecimal;->ZERO_SCALED_BY:[Ljava/math/BigDecimal;
+Ljava/math/BigInt;-><init>()V
+Ljava/math/BigInt;->add(Ljava/math/BigInt;)V
+Ljava/math/BigInt;->addition(Ljava/math/BigInt;Ljava/math/BigInt;)Ljava/math/BigInt;
+Ljava/math/BigInt;->addPositiveInt(I)V
+Ljava/math/BigInt;->bigEndianMagnitude()[B
+Ljava/math/BigInt;->bigExp(Ljava/math/BigInt;Ljava/math/BigInt;)Ljava/math/BigInt;
+Ljava/math/BigInt;->bignum:J
+Ljava/math/BigInt;->bitLength()I
+Ljava/math/BigInt;->checkString(Ljava/lang/String;I)Ljava/lang/String;
+Ljava/math/BigInt;->cmp(Ljava/math/BigInt;Ljava/math/BigInt;)I
+Ljava/math/BigInt;->copy()Ljava/math/BigInt;
+Ljava/math/BigInt;->decString()Ljava/lang/String;
+Ljava/math/BigInt;->division(Ljava/math/BigInt;Ljava/math/BigInt;Ljava/math/BigInt;Ljava/math/BigInt;)V
+Ljava/math/BigInt;->exp(Ljava/math/BigInt;I)Ljava/math/BigInt;
+Ljava/math/BigInt;->gcd(Ljava/math/BigInt;Ljava/math/BigInt;)Ljava/math/BigInt;
+Ljava/math/BigInt;->generatePrimeDefault(I)Ljava/math/BigInt;
+Ljava/math/BigInt;->hasNativeBignum()Z
+Ljava/math/BigInt;->hexString()Ljava/lang/String;
+Ljava/math/BigInt;->invalidBigInteger(Ljava/lang/String;)Ljava/lang/NumberFormatException;
+Ljava/math/BigInt;->isBitSet(I)Z
+Ljava/math/BigInt;->isPrime(I)Z
+Ljava/math/BigInt;->littleEndianIntsMagnitude()[I
+Ljava/math/BigInt;->longInt()J
+Ljava/math/BigInt;->makeValid()V
+Ljava/math/BigInt;->modExp(Ljava/math/BigInt;Ljava/math/BigInt;Ljava/math/BigInt;)Ljava/math/BigInt;
+Ljava/math/BigInt;->modInverse(Ljava/math/BigInt;Ljava/math/BigInt;)Ljava/math/BigInt;
+Ljava/math/BigInt;->modulus(Ljava/math/BigInt;Ljava/math/BigInt;)Ljava/math/BigInt;
+Ljava/math/BigInt;->multiplyByPositiveInt(I)V
+Ljava/math/BigInt;->newBigInt()Ljava/math/BigInt;
+Ljava/math/BigInt;->product(Ljava/math/BigInt;Ljava/math/BigInt;)Ljava/math/BigInt;
+Ljava/math/BigInt;->putBigEndian([BZ)V
+Ljava/math/BigInt;->putBigEndianTwosComplement([B)V
+Ljava/math/BigInt;->putCopy(Ljava/math/BigInt;)V
+Ljava/math/BigInt;->putDecString(Ljava/lang/String;)V
+Ljava/math/BigInt;->putHexString(Ljava/lang/String;)V
+Ljava/math/BigInt;->putLittleEndianInts([IZ)V
+Ljava/math/BigInt;->putLongInt(J)V
+Ljava/math/BigInt;->putULongInt(JZ)V
+Ljava/math/BigInt;->registry:Llibcore/util/NativeAllocationRegistry;
+Ljava/math/BigInt;->remainderByPositiveInt(Ljava/math/BigInt;I)I
+Ljava/math/BigInt;->setSign(I)V
+Ljava/math/BigInt;->shift(I)V
+Ljava/math/BigInt;->shift(Ljava/math/BigInt;I)Ljava/math/BigInt;
+Ljava/math/BigInt;->sign()I
+Ljava/math/BigInt;->subtraction(Ljava/math/BigInt;Ljava/math/BigInt;)Ljava/math/BigInt;
+Ljava/math/BigInt;->toAscii(Ljava/lang/String;I)Ljava/lang/String;
+Ljava/math/BigInt;->twosCompFitsIntoBytes(I)Z
+Ljava/math/BigInteger;-><init>(II[I)V
+Ljava/math/BigInteger;-><init>(IJ)V
+Ljava/math/BigInteger;-><init>(Ljava/math/BigInt;)V
+Ljava/math/BigInteger;->bigInt:Ljava/math/BigInt;
+Ljava/math/BigInteger;->copy()Ljava/math/BigInteger;
+Ljava/math/BigInteger;->digits:[I
+Ljava/math/BigInteger;->firstNonzeroDigit:I
+Ljava/math/BigInteger;->getBigInt()Ljava/math/BigInt;
+Ljava/math/BigInteger;->getFirstNonzeroDigit()I
+Ljava/math/BigInteger;->hashCode:I
+Ljava/math/BigInteger;->inplaceAdd([III)I
+Ljava/math/BigInteger;->isSmallPrime(I)Z
+Ljava/math/BigInteger;->javaIsValid:Z
+Ljava/math/BigInteger;->magnitude:[B
+Ljava/math/BigInteger;->MINUS_ONE:Ljava/math/BigInteger;
+Ljava/math/BigInteger;->multiplyByInt([I[III)I
+Ljava/math/BigInteger;->nativeIsValid:Z
+Ljava/math/BigInteger;->numberLength:I
+Ljava/math/BigInteger;->parseFromString(Ljava/math/BigInteger;Ljava/lang/String;I)V
+Ljava/math/BigInteger;->prepareJavaRepresentation()V
+Ljava/math/BigInteger;->setBigInt(Ljava/math/BigInt;)V
+Ljava/math/BigInteger;->setJavaRepresentation(II[I)V
+Ljava/math/BigInteger;->shiftLeftOneBit()Ljava/math/BigInteger;
+Ljava/math/BigInteger;->sign:I
+Ljava/math/BigInteger;->signum:I
+Ljava/math/BigInteger;->SMALL_VALUES:[Ljava/math/BigInteger;
+Ljava/math/BigInteger;->twosComplement()[B
+Ljava/math/MathContext;->checkValid()V
+Ljava/math/MathContext;->invalidMathContext(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/IllegalArgumentException;
+Ljava/math/MathContext;->precision:I
+Ljava/math/MathContext;->roundingMode:Ljava/math/RoundingMode;
+Ljava/math/RoundingMode;->bigDecimalRM:I
+Ljava/net/Authenticator;->requestingAuthType:Ljava/net/Authenticator$RequestorType;
+Ljava/net/Authenticator;->requestingHost:Ljava/lang/String;
+Ljava/net/Authenticator;->requestingPort:I
+Ljava/net/Authenticator;->requestingPrompt:Ljava/lang/String;
+Ljava/net/Authenticator;->requestingProtocol:Ljava/lang/String;
+Ljava/net/Authenticator;->requestingScheme:Ljava/lang/String;
+Ljava/net/Authenticator;->requestingSite:Ljava/net/InetAddress;
+Ljava/net/Authenticator;->requestingURL:Ljava/net/URL;
+Ljava/net/Authenticator;->reset()V
+Ljava/net/BindException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/net/ConnectException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/net/CookieHandler;->cookieHandler:Ljava/net/CookieHandler;
+Ljava/net/CookieManager$CookiePathComparator;-><init>()V
+Ljava/net/CookieManager$CookiePathComparator;->compare(Ljava/net/HttpCookie;Ljava/net/HttpCookie;)I
+Ljava/net/CookieManager;->cookieJar:Ljava/net/CookieStore;
+Ljava/net/CookieManager;->isInPortList(Ljava/lang/String;I)Z
+Ljava/net/CookieManager;->normalizePath(Ljava/lang/String;)Ljava/lang/String;
+Ljava/net/CookieManager;->pathMatches(Ljava/net/URI;Ljava/net/HttpCookie;)Z
+Ljava/net/CookieManager;->policyCallback:Ljava/net/CookiePolicy;
+Ljava/net/CookieManager;->shouldAcceptInternal(Ljava/net/URI;Ljava/net/HttpCookie;)Z
+Ljava/net/CookieManager;->sortByPath(Ljava/util/List;)Ljava/util/List;
+Ljava/net/DatagramPacket;->address:Ljava/net/InetAddress;
+Ljava/net/DatagramPacket;->buf:[B
+Ljava/net/DatagramPacket;->bufLength:I
+Ljava/net/DatagramPacket;->length:I
+Ljava/net/DatagramPacket;->offset:I
+Ljava/net/DatagramPacket;->port:I
+Ljava/net/DatagramPacket;->setReceivedLength(I)V
+Ljava/net/DatagramSocket;->bound:Z
+Ljava/net/DatagramSocket;->bytesLeftToFilter:I
+Ljava/net/DatagramSocket;->checkAddress(Ljava/net/InetAddress;Ljava/lang/String;)V
+Ljava/net/DatagramSocket;->checkFiltering(Ljava/net/DatagramPacket;)Z
+Ljava/net/DatagramSocket;->checkOldImpl()V
+Ljava/net/DatagramSocket;->closed:Z
+Ljava/net/DatagramSocket;->closeLock:Ljava/lang/Object;
+Ljava/net/DatagramSocket;->connectedAddress:Ljava/net/InetAddress;
+Ljava/net/DatagramSocket;->connectedPort:I
+Ljava/net/DatagramSocket;->connectInternal(Ljava/net/InetAddress;I)V
+Ljava/net/DatagramSocket;->connectState:I
+Ljava/net/DatagramSocket;->created:Z
+Ljava/net/DatagramSocket;->createImpl()V
+Ljava/net/DatagramSocket;->explicitFilter:Z
+Ljava/net/DatagramSocket;->factory:Ljava/net/DatagramSocketImplFactory;
+Ljava/net/DatagramSocket;->getImpl()Ljava/net/DatagramSocketImpl;
+Ljava/net/DatagramSocket;->implClass:Ljava/lang/Class;
+Ljava/net/DatagramSocket;->oldImpl:Z
+Ljava/net/DatagramSocket;->pendingConnectException:Ljava/net/SocketException;
+Ljava/net/DatagramSocket;->ST_CONNECTED:I
+Ljava/net/DatagramSocket;->ST_CONNECTED_NO_IMPL:I
+Ljava/net/DatagramSocket;->ST_NOT_CONNECTED:I
+Ljava/net/DatagramSocketImpl;->dataAvailable()I
+Ljava/net/DatagramSocketImpl;->getDatagramSocket()Ljava/net/DatagramSocket;
+Ljava/net/DatagramSocketImpl;->getOption(Ljava/net/SocketOption;)Ljava/lang/Object;
+Ljava/net/DatagramSocketImpl;->setDatagramSocket(Ljava/net/DatagramSocket;)V
+Ljava/net/DatagramSocketImpl;->setOption(Ljava/net/SocketOption;Ljava/lang/Object;)V
+Ljava/net/DatagramSocketImpl;->socket:Ljava/net/DatagramSocket;
+Ljava/net/HttpCookie$CookieAttributeAssignor;->assign(Ljava/net/HttpCookie;Ljava/lang/String;Ljava/lang/String;)V
+Ljava/net/HttpCookie;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Ljava/net/HttpCookie;->assignAttribute(Ljava/net/HttpCookie;Ljava/lang/String;Ljava/lang/String;)V
+Ljava/net/HttpCookie;->equalsIgnoreCase(Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/net/HttpCookie;->GMT:Ljava/util/TimeZone;
+Ljava/net/HttpCookie;->guessCookieVersion(Ljava/lang/String;)I
+Ljava/net/HttpCookie;->header()Ljava/lang/String;
+Ljava/net/HttpCookie;->isFullyQualifiedDomainName(Ljava/lang/String;I)Z
+Ljava/net/HttpCookie;->isToken(Ljava/lang/String;)Z
+Ljava/net/HttpCookie;->MAX_AGE_UNSPECIFIED:J
+Ljava/net/HttpCookie;->parse(Ljava/lang/String;Z)Ljava/util/List;
+Ljava/net/HttpCookie;->parseInternal(Ljava/lang/String;Z)Ljava/net/HttpCookie;
+Ljava/net/HttpCookie;->RESERVED_NAMES:Ljava/util/Set;
+Ljava/net/HttpCookie;->SET_COOKIE2:Ljava/lang/String;
+Ljava/net/HttpCookie;->SET_COOKIE:Ljava/lang/String;
+Ljava/net/HttpCookie;->splitMultiCookies(Ljava/lang/String;)Ljava/util/List;
+Ljava/net/HttpCookie;->startsWithIgnoreCase(Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/net/HttpCookie;->stripOffSurroundingQuote(Ljava/lang/String;)Ljava/lang/String;
+Ljava/net/HttpCookie;->toNetscapeHeaderString()Ljava/lang/String;
+Ljava/net/HttpCookie;->toRFC2965HeaderString()Ljava/lang/String;
+Ljava/net/HttpRetryException;->location:Ljava/lang/String;
+Ljava/net/HttpRetryException;->responseCode:I
+Ljava/net/HttpURLConnection;->DEFAULT_CHUNK_SIZE:I
+Ljava/net/HttpURLConnection;->followRedirects:Z
+Ljava/net/HttpURLConnection;->methods:[Ljava/lang/String;
+Ljava/net/IDN;-><init>()V
+Ljava/net/IDN;->convertFullStop(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
+Ljava/net/IDN;->isLabelSeperator(C)Z
+Ljava/net/Inet4Address;-><init>(Ljava/lang/String;I)V
+Ljava/net/Inet4Address;-><init>(Ljava/lang/String;[B)V
+Ljava/net/Inet4Address;->INADDRSZ:I
+Ljava/net/Inet4Address;->LOOPBACK:Ljava/net/InetAddress;
+Ljava/net/Inet4Address;->numericToTextFormat([B)Ljava/lang/String;
+Ljava/net/Inet6Address$Inet6AddressHolder;->init([BI)V
+Ljava/net/Inet6Address$Inet6AddressHolder;->init([BLjava/net/NetworkInterface;)V
+Ljava/net/Inet6Address$Inet6AddressHolder;->isAnyLocalAddress()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->isIPv4CompatibleAddress()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->isLinkLocalAddress()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->isLoopbackAddress()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->isMCGlobal()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->isMCLinkLocal()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->isMCNodeLocal()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->isMCOrgLocal()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->isMCSiteLocal()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->isMulticastAddress()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->isSiteLocalAddress()Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->scope_ifname_set:Z
+Ljava/net/Inet6Address$Inet6AddressHolder;->setAddr([B)V
+Ljava/net/Inet6Address;-><init>(Ljava/lang/String;[B)V
+Ljava/net/Inet6Address;-><init>(Ljava/lang/String;[BI)V
+Ljava/net/Inet6Address;-><init>(Ljava/lang/String;[BLjava/lang/String;)V
+Ljava/net/Inet6Address;-><init>(Ljava/lang/String;[BLjava/net/NetworkInterface;)V
+Ljava/net/Inet6Address;->deriveNumericScope(Ljava/lang/String;)I
+Ljava/net/Inet6Address;->deriveNumericScope([BLjava/net/NetworkInterface;)I
+Ljava/net/Inet6Address;->FIELDS_OFFSET:J
+Ljava/net/Inet6Address;->INADDRSZ:I
+Ljava/net/Inet6Address;->initif(Ljava/lang/String;[BLjava/net/NetworkInterface;)V
+Ljava/net/Inet6Address;->initstr(Ljava/lang/String;[BLjava/lang/String;)V
+Ljava/net/Inet6Address;->INT16SZ:I
+Ljava/net/Inet6Address;->isDifferentLocalAddressType([B[B)Z
+Ljava/net/Inet6Address;->isLinkLocalAddress([B)Z
+Ljava/net/Inet6Address;->isSiteLocalAddress([B)Z
+Ljava/net/Inet6Address;->LOOPBACK:Ljava/net/InetAddress;
+Ljava/net/Inet6Address;->numericToTextFormat([B)Ljava/lang/String;
+Ljava/net/Inet6Address;->UNSAFE:Lsun/misc/Unsafe;
+Ljava/net/InetAddress$InetAddressHolder;-><init>()V
+Ljava/net/InetAddress$InetAddressHolder;-><init>(Ljava/lang/String;II)V
+Ljava/net/InetAddress$InetAddressHolder;->getAddress()I
+Ljava/net/InetAddress$InetAddressHolder;->getFamily()I
+Ljava/net/InetAddress$InetAddressHolder;->getHostName()Ljava/lang/String;
+Ljava/net/InetAddress$InetAddressHolder;->getOriginalHostName()Ljava/lang/String;
+Ljava/net/InetAddress$InetAddressHolder;->init(Ljava/lang/String;I)V
+Ljava/net/InetAddress;-><init>()V
+Ljava/net/InetAddress;->anyLocalAddress()Ljava/net/InetAddress;
+Ljava/net/InetAddress;->BOOT_CLASSLOADER:Ljava/lang/ClassLoader;
+Ljava/net/InetAddress;->canonicalHostName:Ljava/lang/String;
+Ljava/net/InetAddress;->disallowDeprecatedFormats(Ljava/lang/String;Ljava/net/InetAddress;)Ljava/net/InetAddress;
+Ljava/net/InetAddress;->getAllByName0(Ljava/lang/String;Z)[Ljava/net/InetAddress;
+Ljava/net/InetAddress;->getByAddress(Ljava/lang/String;[BI)Ljava/net/InetAddress;
+Ljava/net/InetAddress;->getByNameOnNet(Ljava/lang/String;I)Ljava/net/InetAddress;
+Ljava/net/InetAddress;->getHostFromNameService(Ljava/net/InetAddress;)Ljava/lang/String;
+Ljava/net/InetAddress;->getHostName(Z)Ljava/lang/String;
+Ljava/net/InetAddress;->impl:Ljava/net/InetAddressImpl;
+Ljava/net/InetAddress;->isReachableByICMP(I)Z
+Ljava/net/InetAddress;->nameService:Lsun/net/spi/nameservice/NameService;
+Ljava/net/InetAddress;->NETID_UNSET:I
+Ljava/net/InetAddress;->parseNumericAddressNoThrow(Ljava/lang/String;)Ljava/net/InetAddress;
+Ljava/net/InetAddress;->readObjectNoData(Ljava/io/ObjectInputStream;)V
+Ljava/net/InetAddressImpl;->anyLocalAddress()Ljava/net/InetAddress;
+Ljava/net/InetAddressImpl;->clearAddressCache()V
+Ljava/net/InetAddressImpl;->getHostByAddr([B)Ljava/lang/String;
+Ljava/net/InetAddressImpl;->isReachable(Ljava/net/InetAddress;ILjava/net/NetworkInterface;I)Z
+Ljava/net/InetAddressImpl;->lookupAllHostAddr(Ljava/lang/String;I)[Ljava/net/InetAddress;
+Ljava/net/InetAddressImpl;->loopbackAddresses()[Ljava/net/InetAddress;
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;-><init>(Ljava/lang/String;Ljava/net/InetAddress;I)V
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;->addr:Ljava/net/InetAddress;
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;->getAddress()Ljava/net/InetAddress;
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;->getHostName()Ljava/lang/String;
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;->getHostString()Ljava/lang/String;
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;->getPort()I
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;->hostname:Ljava/lang/String;
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;->isUnresolved()Z
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;->port:I
+Ljava/net/InetSocketAddress;-><init>()V
+Ljava/net/InetSocketAddress;-><init>(ILjava/lang/String;)V
+Ljava/net/InetSocketAddress;->checkHost(Ljava/lang/String;)Ljava/lang/String;
+Ljava/net/InetSocketAddress;->checkPort(I)I
+Ljava/net/InetSocketAddress;->FIELDS_OFFSET:J
+Ljava/net/InetSocketAddress;->UNSAFE:Lsun/misc/Unsafe;
+Ljava/net/InMemoryCookieStore;-><init>()V
+Ljava/net/InMemoryCookieStore;-><init>(I)V
+Ljava/net/InMemoryCookieStore;->addIndex(Ljava/util/Map;Ljava/lang/Object;Ljava/net/HttpCookie;)V
+Ljava/net/InMemoryCookieStore;->applyMCompatibility:Z
+Ljava/net/InMemoryCookieStore;->getEffectiveURI(Ljava/net/URI;)Ljava/net/URI;
+Ljava/net/InMemoryCookieStore;->getInternal1(Ljava/util/List;Ljava/util/Map;Ljava/lang/String;)V
+Ljava/net/InMemoryCookieStore;->getInternal2(Ljava/util/List;Ljava/util/Map;Ljava/lang/Comparable;)V
+Ljava/net/InMemoryCookieStore;->lock:Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/net/InMemoryCookieStore;->netscapeDomainMatches(Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/net/InMemoryCookieStore;->uriIndex:Ljava/util/Map;
+Ljava/net/InterfaceAddress;-><init>(Ljava/net/InetAddress;Ljava/net/Inet4Address;Ljava/net/InetAddress;)V
+Ljava/net/InterfaceAddress;->address:Ljava/net/InetAddress;
+Ljava/net/InterfaceAddress;->broadcast:Ljava/net/Inet4Address;
+Ljava/net/InterfaceAddress;->countPrefixLength(Ljava/net/InetAddress;)S
+Ljava/net/InterfaceAddress;->maskLength:S
+Ljava/net/JarURLConnection;->entryName:Ljava/lang/String;
+Ljava/net/JarURLConnection;->jarFileURL:Ljava/net/URL;
+Ljava/net/JarURLConnection;->parseSpecs(Ljava/net/URL;)V
+Ljava/net/MulticastSocket;->infAddress:Ljava/net/InetAddress;
+Ljava/net/MulticastSocket;->infLock:Ljava/lang/Object;
+Ljava/net/MulticastSocket;->interfaceSet:Z
+Ljava/net/MulticastSocket;->ttlLock:Ljava/lang/Object;
+Ljava/net/NetworkInterface;-><init>()V
+Ljava/net/NetworkInterface;-><init>(Ljava/lang/String;I[Ljava/net/InetAddress;)V
+Ljava/net/NetworkInterface;->addrs:[Ljava/net/InetAddress;
+Ljava/net/NetworkInterface;->bindings:[Ljava/net/InterfaceAddress;
+Ljava/net/NetworkInterface;->childs:Ljava/util/List;
+Ljava/net/NetworkInterface;->defaultIndex:I
+Ljava/net/NetworkInterface;->defaultInterface:Ljava/net/NetworkInterface;
+Ljava/net/NetworkInterface;->displayName:Ljava/lang/String;
+Ljava/net/NetworkInterface;->getAll()[Ljava/net/NetworkInterface;
+Ljava/net/NetworkInterface;->getDefault()Ljava/net/NetworkInterface;
+Ljava/net/NetworkInterface;->getFlags()I
+Ljava/net/NetworkInterface;->hardwareAddr:[B
+Ljava/net/NetworkInterface;->index:I
+Ljava/net/NetworkInterface;->name:Ljava/lang/String;
+Ljava/net/NetworkInterface;->parent:Ljava/net/NetworkInterface;
+Ljava/net/NetworkInterface;->virtual:Z
+Ljava/net/PasswordAuthentication;->password:[C
+Ljava/net/PasswordAuthentication;->userName:Ljava/lang/String;
+Ljava/net/PortUnreachableException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/net/ProtocolException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/net/Proxy;->sa:Ljava/net/SocketAddress;
+Ljava/net/Proxy;->type:Ljava/net/Proxy$Type;
+Ljava/net/ProxySelector;->theProxySelector:Ljava/net/ProxySelector;
+Ljava/net/ResponseCache;->theResponseCache:Ljava/net/ResponseCache;
+Ljava/net/ServerSocket;-><init>(Ljava/net/SocketImpl;)V
+Ljava/net/ServerSocket;->bound:Z
+Ljava/net/ServerSocket;->checkOldImpl()V
+Ljava/net/ServerSocket;->closed:Z
+Ljava/net/ServerSocket;->closeLock:Ljava/lang/Object;
+Ljava/net/ServerSocket;->created:Z
+Ljava/net/ServerSocket;->createImpl()V
+Ljava/net/ServerSocket;->getFileDescriptor$()Ljava/io/FileDescriptor;
+Ljava/net/ServerSocket;->getImpl()Ljava/net/SocketImpl;
+Ljava/net/ServerSocket;->impl:Ljava/net/SocketImpl;
+Ljava/net/ServerSocket;->oldImpl:Z
+Ljava/net/ServerSocket;->setBound()V
+Ljava/net/ServerSocket;->setCreated()V
+Ljava/net/ServerSocket;->setImpl()V
+Ljava/net/Socket;-><init>([Ljava/net/InetAddress;ILjava/net/SocketAddress;Z)V
+Ljava/net/Socket;->bound:Z
+Ljava/net/Socket;->checkAddress(Ljava/net/InetAddress;Ljava/lang/String;)V
+Ljava/net/Socket;->checkOldImpl()V
+Ljava/net/Socket;->closed:Z
+Ljava/net/Socket;->closeLock:Ljava/lang/Object;
+Ljava/net/Socket;->connected:Z
+Ljava/net/Socket;->created:Z
+Ljava/net/Socket;->createImpl(Z)V
+Ljava/net/Socket;->getImpl()Ljava/net/SocketImpl;
+Ljava/net/Socket;->nonNullAddress(Ljava/net/InetAddress;)[Ljava/net/InetAddress;
+Ljava/net/Socket;->oldImpl:Z
+Ljava/net/Socket;->postAccept()V
+Ljava/net/Socket;->setBound()V
+Ljava/net/Socket;->setConnected()V
+Ljava/net/Socket;->setCreated()V
+Ljava/net/Socket;->setImpl()V
+Ljava/net/Socket;->shutIn:Z
+Ljava/net/Socket;->shutOut:Z
+Ljava/net/SocketException;-><init>(Ljava/lang/Throwable;)V
+Ljava/net/SocketImpl;->getFD$()Ljava/io/FileDescriptor;
+Ljava/net/SocketImpl;->getOption(Ljava/net/SocketOption;)Ljava/lang/Object;
+Ljava/net/SocketImpl;->getServerSocket()Ljava/net/ServerSocket;
+Ljava/net/SocketImpl;->getSocket()Ljava/net/Socket;
+Ljava/net/SocketImpl;->reset()V
+Ljava/net/SocketImpl;->setOption(Ljava/net/SocketOption;Ljava/lang/Object;)V
+Ljava/net/SocketImpl;->setServerSocket(Ljava/net/ServerSocket;)V
+Ljava/net/SocketImpl;->setSocket(Ljava/net/Socket;)V
+Ljava/net/SocketTimeoutException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/net/SocketTimeoutException;-><init>(Ljava/lang/Throwable;)V
+Ljava/net/StandardSocketOptions$StdSocketOption;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
+Ljava/net/StandardSocketOptions$StdSocketOption;->name:Ljava/lang/String;
+Ljava/net/StandardSocketOptions$StdSocketOption;->type:Ljava/lang/Class;
+Ljava/net/StandardSocketOptions;-><init>()V
+Ljava/net/URI$Parser;->at(IIC)Z
+Ljava/net/URI$Parser;->at(IILjava/lang/String;)Z
+Ljava/net/URI$Parser;->charAt(I)C
+Ljava/net/URI$Parser;->checkChar(IJJLjava/lang/String;)V
+Ljava/net/URI$Parser;->checkChars(IIJJLjava/lang/String;)V
+Ljava/net/URI$Parser;->fail(Ljava/lang/String;)V
+Ljava/net/URI$Parser;->fail(Ljava/lang/String;I)V
+Ljava/net/URI$Parser;->failExpecting(Ljava/lang/String;I)V
+Ljava/net/URI$Parser;->failExpecting(Ljava/lang/String;Ljava/lang/String;I)V
+Ljava/net/URI$Parser;->input:Ljava/lang/String;
+Ljava/net/URI$Parser;->ipv6byteCount:I
+Ljava/net/URI$Parser;->parse(Z)V
+Ljava/net/URI$Parser;->parseAuthority(II)I
+Ljava/net/URI$Parser;->parseHierarchical(II)I
+Ljava/net/URI$Parser;->parseHostname(II)I
+Ljava/net/URI$Parser;->parseIPv4Address(II)I
+Ljava/net/URI$Parser;->parseIPv6Reference(II)I
+Ljava/net/URI$Parser;->parseServer(II)I
+Ljava/net/URI$Parser;->requireServerAuthority:Z
+Ljava/net/URI$Parser;->scan(IIC)I
+Ljava/net/URI$Parser;->scan(IIJJ)I
+Ljava/net/URI$Parser;->scan(IILjava/lang/String;Ljava/lang/String;)I
+Ljava/net/URI$Parser;->scanByte(II)I
+Ljava/net/URI$Parser;->scanEscape(IIC)I
+Ljava/net/URI$Parser;->scanHexPost(II)I
+Ljava/net/URI$Parser;->scanHexSeq(II)I
+Ljava/net/URI$Parser;->scanIPv4Address(IIZ)I
+Ljava/net/URI$Parser;->substring(II)Ljava/lang/String;
+Ljava/net/URI$Parser;->takeIPv4Address(IILjava/lang/String;)I
+Ljava/net/URI;-><init>()V
+Ljava/net/URI;->appendAuthority(Ljava/lang/StringBuffer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V
+Ljava/net/URI;->appendEncoded(Ljava/lang/StringBuffer;C)V
+Ljava/net/URI;->appendEscape(Ljava/lang/StringBuffer;B)V
+Ljava/net/URI;->appendFragment(Ljava/lang/StringBuffer;Ljava/lang/String;)V
+Ljava/net/URI;->appendSchemeSpecificPart(Ljava/lang/StringBuffer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
+Ljava/net/URI;->authority:Ljava/lang/String;
+Ljava/net/URI;->checkPath(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Ljava/net/URI;->compare(Ljava/lang/String;Ljava/lang/String;)I
+Ljava/net/URI;->compareIgnoringCase(Ljava/lang/String;Ljava/lang/String;)I
+Ljava/net/URI;->decode(C)I
+Ljava/net/URI;->decode(CC)B
+Ljava/net/URI;->decode(Ljava/lang/String;)Ljava/lang/String;
+Ljava/net/URI;->decodedAuthority:Ljava/lang/String;
+Ljava/net/URI;->decodedFragment:Ljava/lang/String;
+Ljava/net/URI;->decodedPath:Ljava/lang/String;
+Ljava/net/URI;->decodedQuery:Ljava/lang/String;
+Ljava/net/URI;->decodedSchemeSpecificPart:Ljava/lang/String;
+Ljava/net/URI;->decodedUserInfo:Ljava/lang/String;
+Ljava/net/URI;->defineSchemeSpecificPart()V
+Ljava/net/URI;->defineString()V
+Ljava/net/URI;->encode(Ljava/lang/String;)Ljava/lang/String;
+Ljava/net/URI;->equal(Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/net/URI;->equalIgnoringCase(Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/net/URI;->hash(ILjava/lang/String;)I
+Ljava/net/URI;->hash:I
+Ljava/net/URI;->hashIgnoringCase(ILjava/lang/String;)I
+Ljava/net/URI;->hexDigits:[C
+Ljava/net/URI;->highMask(CC)J
+Ljava/net/URI;->highMask(Ljava/lang/String;)J
+Ljava/net/URI;->H_ALPHA:J
+Ljava/net/URI;->H_ALPHANUM:J
+Ljava/net/URI;->H_DASH:J
+Ljava/net/URI;->H_DIGIT:J
+Ljava/net/URI;->H_DOT:J
+Ljava/net/URI;->H_ESCAPED:J
+Ljava/net/URI;->H_HEX:J
+Ljava/net/URI;->H_LEFT_BRACKET:J
+Ljava/net/URI;->H_LOWALPHA:J
+Ljava/net/URI;->H_MARK:J
+Ljava/net/URI;->H_PATH:J
+Ljava/net/URI;->H_PCHAR:J
+Ljava/net/URI;->H_REG_NAME:J
+Ljava/net/URI;->H_RESERVED:J
+Ljava/net/URI;->H_SCHEME:J
+Ljava/net/URI;->H_SERVER:J
+Ljava/net/URI;->H_SERVER_PERCENT:J
+Ljava/net/URI;->H_UNDERSCORE:J
+Ljava/net/URI;->H_UNRESERVED:J
+Ljava/net/URI;->H_UPALPHA:J
+Ljava/net/URI;->H_URIC:J
+Ljava/net/URI;->H_URIC_NO_SLASH:J
+Ljava/net/URI;->H_USERINFO:J
+Ljava/net/URI;->join([C[I)I
+Ljava/net/URI;->lowMask(CC)J
+Ljava/net/URI;->lowMask(Ljava/lang/String;)J
+Ljava/net/URI;->L_ALPHA:J
+Ljava/net/URI;->L_ALPHANUM:J
+Ljava/net/URI;->L_DASH:J
+Ljava/net/URI;->L_DIGIT:J
+Ljava/net/URI;->L_DOT:J
+Ljava/net/URI;->L_ESCAPED:J
+Ljava/net/URI;->L_HEX:J
+Ljava/net/URI;->L_LEFT_BRACKET:J
+Ljava/net/URI;->L_LOWALPHA:J
+Ljava/net/URI;->L_MARK:J
+Ljava/net/URI;->L_PATH:J
+Ljava/net/URI;->L_PCHAR:J
+Ljava/net/URI;->L_REG_NAME:J
+Ljava/net/URI;->L_RESERVED:J
+Ljava/net/URI;->L_SCHEME:J
+Ljava/net/URI;->L_SERVER:J
+Ljava/net/URI;->L_SERVER_PERCENT:J
+Ljava/net/URI;->L_UNDERSCORE:J
+Ljava/net/URI;->L_UNRESERVED:J
+Ljava/net/URI;->L_UPALPHA:J
+Ljava/net/URI;->L_URIC:J
+Ljava/net/URI;->L_URIC_NO_SLASH:J
+Ljava/net/URI;->L_USERINFO:J
+Ljava/net/URI;->match(CJJ)Z
+Ljava/net/URI;->maybeAddLeadingDot([C[I)V
+Ljava/net/URI;->needsNormalization(Ljava/lang/String;)I
+Ljava/net/URI;->normalize(Ljava/lang/String;)Ljava/lang/String;
+Ljava/net/URI;->normalize(Ljava/lang/String;Z)Ljava/lang/String;
+Ljava/net/URI;->normalize(Ljava/net/URI;)Ljava/net/URI;
+Ljava/net/URI;->normalizedHash(ILjava/lang/String;)I
+Ljava/net/URI;->path:Ljava/lang/String;
+Ljava/net/URI;->quote(Ljava/lang/String;JJ)Ljava/lang/String;
+Ljava/net/URI;->relativize(Ljava/net/URI;Ljava/net/URI;)Ljava/net/URI;
+Ljava/net/URI;->removeDots([C[IZ)V
+Ljava/net/URI;->resolve(Ljava/net/URI;Ljava/net/URI;)Ljava/net/URI;
+Ljava/net/URI;->resolvePath(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;
+Ljava/net/URI;->scheme:Ljava/lang/String;
+Ljava/net/URI;->schemeSpecificPart:Ljava/lang/String;
+Ljava/net/URI;->split([C[I)V
+Ljava/net/URI;->toLower(C)I
+Ljava/net/URI;->toString(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Ljava/net/URI;->toUpper(C)I
+Ljava/net/URI;->userInfo:Ljava/lang/String;
+Ljava/net/URISyntaxException;->index:I
+Ljava/net/URISyntaxException;->input:Ljava/lang/String;
+Ljava/net/URL;->authority:Ljava/lang/String;
+Ljava/net/URL;->BUILTIN_HANDLER_CLASS_NAMES:Ljava/util/Set;
+Ljava/net/URL;->checkSpecifyHandler(Ljava/lang/SecurityManager;)V
+Ljava/net/URL;->createBuiltinHandler(Ljava/lang/String;)Ljava/net/URLStreamHandler;
+Ljava/net/URL;->createBuiltinHandlerClassNames()Ljava/util/Set;
+Ljava/net/URL;->fabricateNewURL()Ljava/net/URL;
+Ljava/net/URL;->file:Ljava/lang/String;
+Ljava/net/URL;->getURLStreamHandler(Ljava/lang/String;)Ljava/net/URLStreamHandler;
+Ljava/net/URL;->hashCode:I
+Ljava/net/URL;->host:Ljava/lang/String;
+Ljava/net/URL;->hostAddress:Ljava/net/InetAddress;
+Ljava/net/URL;->isBuiltinStreamHandler(Ljava/lang/String;)Z
+Ljava/net/URL;->isValidProtocol(Ljava/lang/String;)Z
+Ljava/net/URL;->path:Ljava/lang/String;
+Ljava/net/URL;->port:I
+Ljava/net/URL;->protocolPathProp:Ljava/lang/String;
+Ljava/net/URL;->query:Ljava/lang/String;
+Ljava/net/URL;->ref:Ljava/lang/String;
+Ljava/net/URL;->resetState()V
+Ljava/net/URL;->set(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
+Ljava/net/URL;->set(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Ljava/net/URL;->setDeserializedFields(Ljava/net/URLStreamHandler;)Ljava/net/URL;
+Ljava/net/URL;->setSerializedHashCode(I)V
+Ljava/net/URL;->streamHandlerLock:Ljava/lang/Object;
+Ljava/net/URL;->tempState:Ljava/net/UrlDeserializedState;
+Ljava/net/URL;->userInfo:Ljava/lang/String;
+Ljava/net/URLClassLoader;-><init>([Ljava/net/URL;Ljava/lang/ClassLoader;Ljava/security/AccessControlContext;)V
+Ljava/net/URLClassLoader;-><init>([Ljava/net/URL;Ljava/security/AccessControlContext;)V
+Ljava/net/URLClassLoader;->closeables:Ljava/util/WeakHashMap;
+Ljava/net/URLClassLoader;->defineClass(Ljava/lang/String;Lsun/misc/Resource;)Ljava/lang/Class;
+Ljava/net/URLClassLoader;->definePackageInternal(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V
+Ljava/net/URLClassLoader;->getAndVerifyPackage(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)Ljava/lang/Package;
+Ljava/net/URLClassLoader;->isSealed(Ljava/lang/String;Ljava/util/jar/Manifest;)Z
+Ljava/net/URLConnection;->checkfpx(Ljava/io/InputStream;)Z
+Ljava/net/URLConnection;->connectTimeout:I
+Ljava/net/URLConnection;->contentClassPrefix:Ljava/lang/String;
+Ljava/net/URLConnection;->contentPathProp:Ljava/lang/String;
+Ljava/net/URLConnection;->defaultAllowUserInteraction:Z
+Ljava/net/URLConnection;->defaultUseCaches:Z
+Ljava/net/URLConnection;->factory:Ljava/net/ContentHandlerFactory;
+Ljava/net/URLConnection;->fileNameMap:Ljava/net/FileNameMap;
+Ljava/net/URLConnection;->getContentHandler()Ljava/net/ContentHandler;
+Ljava/net/URLConnection;->getContentHandlerPkgPrefixes()Ljava/lang/String;
+Ljava/net/URLConnection;->handlers:Ljava/util/Hashtable;
+Ljava/net/URLConnection;->lookupContentHandlerClassFor(Ljava/lang/String;)Ljava/net/ContentHandler;
+Ljava/net/URLConnection;->readBytes([IILjava/io/InputStream;)I
+Ljava/net/URLConnection;->readTimeout:I
+Ljava/net/URLConnection;->requests:Lsun/net/www/MessageHeader;
+Ljava/net/URLConnection;->skipForward(Ljava/io/InputStream;J)J
+Ljava/net/URLConnection;->stripOffParameters(Ljava/lang/String;)Ljava/lang/String;
+Ljava/net/URLConnection;->typeToPackageName(Ljava/lang/String;)Ljava/lang/String;
+Ljava/net/URLDecoder;->dfltEncName:Ljava/lang/String;
+Ljava/net/URLDecoder;->isValidHexChar(C)Z
+Ljava/net/UrlDeserializedState;-><init>(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V
+Ljava/net/UrlDeserializedState;->authority:Ljava/lang/String;
+Ljava/net/UrlDeserializedState;->file:Ljava/lang/String;
+Ljava/net/UrlDeserializedState;->getAuthority()Ljava/lang/String;
+Ljava/net/UrlDeserializedState;->getFile()Ljava/lang/String;
+Ljava/net/UrlDeserializedState;->getHashCode()I
+Ljava/net/UrlDeserializedState;->getHost()Ljava/lang/String;
+Ljava/net/UrlDeserializedState;->getPort()I
+Ljava/net/UrlDeserializedState;->getProtocol()Ljava/lang/String;
+Ljava/net/UrlDeserializedState;->getRef()Ljava/lang/String;
+Ljava/net/UrlDeserializedState;->hashCode:I
+Ljava/net/UrlDeserializedState;->host:Ljava/lang/String;
+Ljava/net/UrlDeserializedState;->port:I
+Ljava/net/UrlDeserializedState;->protocol:Ljava/lang/String;
+Ljava/net/UrlDeserializedState;->reconstituteUrlString()Ljava/lang/String;
+Ljava/net/UrlDeserializedState;->ref:Ljava/lang/String;
+Ljava/net/URLEncoder;-><init>()V
+Ljava/net/URLEncoder;->caseDiff:I
+Ljava/net/URLEncoder;->dfltEncName:Ljava/lang/String;
+Ljava/net/URLEncoder;->dontNeedEncoding:Ljava/util/BitSet;
+Ljava/nio/Buffer;-><init>(IIIII)V
+Ljava/nio/Buffer;->checkBounds(III)V
+Ljava/nio/Buffer;->checkIndex(I)I
+Ljava/nio/Buffer;->checkIndex(II)I
+Ljava/nio/Buffer;->discardMark()V
+Ljava/nio/Buffer;->getElementSizeShift()I
+Ljava/nio/Buffer;->mark:I
+Ljava/nio/Buffer;->markValue()I
+Ljava/nio/Buffer;->nextGetIndex()I
+Ljava/nio/Buffer;->nextGetIndex(I)I
+Ljava/nio/Buffer;->nextPutIndex()I
+Ljava/nio/Buffer;->nextPutIndex(I)I
+Ljava/nio/Buffer;->SPLITERATOR_CHARACTERISTICS:I
+Ljava/nio/Buffer;->truncate()V
+Ljava/nio/ByteBuffer;-><init>(IIII)V
+Ljava/nio/ByteBuffer;-><init>(IIII[BI)V
+Ljava/nio/ByteBuffer;->bigEndian:Z
+Ljava/nio/ByteBuffer;->compare(BB)I
+Ljava/nio/ByteBuffer;->equals(BB)Z
+Ljava/nio/ByteBuffer;->getCharUnchecked(I)C
+Ljava/nio/ByteBuffer;->getDoubleUnchecked(I)D
+Ljava/nio/ByteBuffer;->getFloatUnchecked(I)F
+Ljava/nio/ByteBuffer;->getIntUnchecked(I)I
+Ljava/nio/ByteBuffer;->getLongUnchecked(I)J
+Ljava/nio/ByteBuffer;->getShortUnchecked(I)S
+Ljava/nio/ByteBuffer;->getUnchecked(I[CII)V
+Ljava/nio/ByteBuffer;->getUnchecked(I[DII)V
+Ljava/nio/ByteBuffer;->getUnchecked(I[FII)V
+Ljava/nio/ByteBuffer;->getUnchecked(I[III)V
+Ljava/nio/ByteBuffer;->getUnchecked(I[JII)V
+Ljava/nio/ByteBuffer;->getUnchecked(I[SII)V
+Ljava/nio/ByteBuffer;->isAccessible()Z
+Ljava/nio/ByteBuffer;->nativeByteOrder:Z
+Ljava/nio/ByteBuffer;->putCharUnchecked(IC)V
+Ljava/nio/ByteBuffer;->putDoubleUnchecked(ID)V
+Ljava/nio/ByteBuffer;->putFloatUnchecked(IF)V
+Ljava/nio/ByteBuffer;->putIntUnchecked(II)V
+Ljava/nio/ByteBuffer;->putLongUnchecked(IJ)V
+Ljava/nio/ByteBuffer;->putShortUnchecked(IS)V
+Ljava/nio/ByteBuffer;->putUnchecked(I[CII)V
+Ljava/nio/ByteBuffer;->putUnchecked(I[DII)V
+Ljava/nio/ByteBuffer;->putUnchecked(I[FII)V
+Ljava/nio/ByteBuffer;->putUnchecked(I[III)V
+Ljava/nio/ByteBuffer;->putUnchecked(I[JII)V
+Ljava/nio/ByteBuffer;->putUnchecked(I[SII)V
+Ljava/nio/ByteBuffer;->setAccessible(Z)V
+Ljava/nio/ByteBuffer;->_get(I)B
+Ljava/nio/ByteBuffer;->_put(IB)V
+Ljava/nio/ByteOrder;-><init>(Ljava/lang/String;)V
+Ljava/nio/ByteOrder;->name:Ljava/lang/String;
+Ljava/nio/channels/AsynchronousChannelGroup;->provider:Ljava/nio/channels/spi/AsynchronousChannelProvider;
+Ljava/nio/channels/AsynchronousFileChannel;->NO_ATTRIBUTES:[Ljava/nio/file/attribute/FileAttribute;
+Ljava/nio/channels/AsynchronousServerSocketChannel;->provider:Ljava/nio/channels/spi/AsynchronousChannelProvider;
+Ljava/nio/channels/AsynchronousSocketChannel;->provider:Ljava/nio/channels/spi/AsynchronousChannelProvider;
+Ljava/nio/channels/Channels$ReadableByteChannelImpl;-><init>(Ljava/io/InputStream;)V
+Ljava/nio/channels/Channels$ReadableByteChannelImpl;->buf:[B
+Ljava/nio/channels/Channels$ReadableByteChannelImpl;->in:Ljava/io/InputStream;
+Ljava/nio/channels/Channels$ReadableByteChannelImpl;->open:Z
+Ljava/nio/channels/Channels$ReadableByteChannelImpl;->readLock:Ljava/lang/Object;
+Ljava/nio/channels/Channels$ReadableByteChannelImpl;->TRANSFER_SIZE:I
+Ljava/nio/channels/Channels$WritableByteChannelImpl;-><init>(Ljava/io/OutputStream;)V
+Ljava/nio/channels/Channels$WritableByteChannelImpl;->buf:[B
+Ljava/nio/channels/Channels$WritableByteChannelImpl;->open:Z
+Ljava/nio/channels/Channels$WritableByteChannelImpl;->out:Ljava/io/OutputStream;
+Ljava/nio/channels/Channels$WritableByteChannelImpl;->TRANSFER_SIZE:I
+Ljava/nio/channels/Channels$WritableByteChannelImpl;->writeLock:Ljava/lang/Object;
+Ljava/nio/channels/Channels;-><init>()V
+Ljava/nio/channels/Channels;->checkNotNull(Ljava/lang/Object;Ljava/lang/String;)V
+Ljava/nio/channels/Channels;->writeFully(Ljava/nio/channels/WritableByteChannel;Ljava/nio/ByteBuffer;)V
+Ljava/nio/channels/Channels;->writeFullyImpl(Ljava/nio/channels/WritableByteChannel;Ljava/nio/ByteBuffer;)V
+Ljava/nio/channels/FileChannel$MapMode;-><init>(Ljava/lang/String;)V
+Ljava/nio/channels/FileChannel$MapMode;->name:Ljava/lang/String;
+Ljava/nio/channels/FileChannel;->NO_ATTRIBUTES:[Ljava/nio/file/attribute/FileAttribute;
+Ljava/nio/channels/FileLock;->channel:Ljava/nio/channels/Channel;
+Ljava/nio/channels/FileLock;->position:J
+Ljava/nio/channels/FileLock;->shared:Z
+Ljava/nio/channels/FileLock;->size:J
+Ljava/nio/channels/SelectionKey;->attachment:Ljava/lang/Object;
+Ljava/nio/channels/SelectionKey;->attachmentUpdater:Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;
+Ljava/nio/channels/spi/AbstractInterruptibleChannel;->blockedOn(Lsun/nio/ch/Interruptible;)V
+Ljava/nio/channels/spi/AbstractInterruptibleChannel;->closeLock:Ljava/lang/Object;
+Ljava/nio/channels/spi/AbstractInterruptibleChannel;->interrupted:Ljava/lang/Thread;
+Ljava/nio/channels/spi/AbstractInterruptibleChannel;->interruptor:Lsun/nio/ch/Interruptible;
+Ljava/nio/channels/spi/AbstractInterruptibleChannel;->open:Z
+Ljava/nio/channels/spi/AbstractSelectableChannel;->addKey(Ljava/nio/channels/SelectionKey;)V
+Ljava/nio/channels/spi/AbstractSelectableChannel;->blocking:Z
+Ljava/nio/channels/spi/AbstractSelectableChannel;->findKey(Ljava/nio/channels/Selector;)Ljava/nio/channels/SelectionKey;
+Ljava/nio/channels/spi/AbstractSelectableChannel;->haveValidKeys()Z
+Ljava/nio/channels/spi/AbstractSelectableChannel;->keyCount:I
+Ljava/nio/channels/spi/AbstractSelectableChannel;->keyLock:Ljava/lang/Object;
+Ljava/nio/channels/spi/AbstractSelectableChannel;->keys:[Ljava/nio/channels/SelectionKey;
+Ljava/nio/channels/spi/AbstractSelectableChannel;->provider:Ljava/nio/channels/spi/SelectorProvider;
+Ljava/nio/channels/spi/AbstractSelectableChannel;->regLock:Ljava/lang/Object;
+Ljava/nio/channels/spi/AbstractSelectableChannel;->removeKey(Ljava/nio/channels/SelectionKey;)V
+Ljava/nio/channels/spi/AbstractSelectionKey;->invalidate()V
+Ljava/nio/channels/spi/AbstractSelectionKey;->valid:Z
+Ljava/nio/channels/spi/AbstractSelector;->cancel(Ljava/nio/channels/SelectionKey;)V
+Ljava/nio/channels/spi/AbstractSelector;->cancelledKeys:Ljava/util/Set;
+Ljava/nio/channels/spi/AbstractSelector;->interruptor:Lsun/nio/ch/Interruptible;
+Ljava/nio/channels/spi/AbstractSelector;->provider:Ljava/nio/channels/spi/SelectorProvider;
+Ljava/nio/channels/spi/AbstractSelector;->selectorOpen:Ljava/util/concurrent/atomic/AtomicBoolean;
+Ljava/nio/channels/spi/AsynchronousChannelProvider$ProviderHolder;-><init>()V
+Ljava/nio/channels/spi/AsynchronousChannelProvider$ProviderHolder;->load()Ljava/nio/channels/spi/AsynchronousChannelProvider;
+Ljava/nio/channels/spi/AsynchronousChannelProvider$ProviderHolder;->loadProviderAsService()Ljava/nio/channels/spi/AsynchronousChannelProvider;
+Ljava/nio/channels/spi/AsynchronousChannelProvider$ProviderHolder;->loadProviderFromProperty()Ljava/nio/channels/spi/AsynchronousChannelProvider;
+Ljava/nio/channels/spi/AsynchronousChannelProvider$ProviderHolder;->provider:Ljava/nio/channels/spi/AsynchronousChannelProvider;
+Ljava/nio/channels/spi/AsynchronousChannelProvider;-><init>(Ljava/lang/Void;)V
+Ljava/nio/channels/spi/AsynchronousChannelProvider;->checkPermission()Ljava/lang/Void;
+Ljava/nio/channels/spi/SelectorProvider;->loadProviderAsService()Z
+Ljava/nio/channels/spi/SelectorProvider;->loadProviderFromProperty()Z
+Ljava/nio/channels/spi/SelectorProvider;->lock:Ljava/lang/Object;
+Ljava/nio/channels/spi/SelectorProvider;->provider:Ljava/nio/channels/spi/SelectorProvider;
+Ljava/nio/CharBuffer;-><init>(IIII)V
+Ljava/nio/CharBuffer;-><init>(IIII[CI)V
+Ljava/nio/CharBuffer;->compare(CC)I
+Ljava/nio/CharBuffer;->equals(CC)Z
+Ljava/nio/CharBuffer;->getUnchecked(I)C
+Ljava/nio/CharBuffer;->hb:[C
+Ljava/nio/CharBuffer;->isReadOnly:Z
+Ljava/nio/CharBuffer;->offset:I
+Ljava/nio/charset/Charset;->aliases:[Ljava/lang/String;
+Ljava/nio/charset/Charset;->aliasSet:Ljava/util/Set;
+Ljava/nio/charset/Charset;->atBugLevel(Ljava/lang/String;)Z
+Ljava/nio/charset/Charset;->bugLevel:Ljava/lang/String;
+Ljava/nio/charset/Charset;->cache(Ljava/lang/String;Ljava/nio/charset/Charset;)V
+Ljava/nio/charset/Charset;->cache1:Ljava/util/Map$Entry;
+Ljava/nio/charset/Charset;->cache2:Ljava/util/HashMap;
+Ljava/nio/charset/Charset;->checkName(Ljava/lang/String;)V
+Ljava/nio/charset/Charset;->forNameUEE(Ljava/lang/String;)Ljava/nio/charset/Charset;
+Ljava/nio/charset/Charset;->gate:Ljava/lang/ThreadLocal;
+Ljava/nio/charset/Charset;->lookup(Ljava/lang/String;)Ljava/nio/charset/Charset;
+Ljava/nio/charset/Charset;->lookup2(Ljava/lang/String;)Ljava/nio/charset/Charset;
+Ljava/nio/charset/Charset;->lookupViaProviders(Ljava/lang/String;)Ljava/nio/charset/Charset;
+Ljava/nio/charset/Charset;->name:Ljava/lang/String;
+Ljava/nio/charset/Charset;->providers()Ljava/util/Iterator;
+Ljava/nio/charset/Charset;->put(Ljava/util/Iterator;Ljava/util/Map;)V
+Ljava/nio/charset/CharsetDecoder;-><init>(Ljava/nio/charset/Charset;FFLjava/lang/String;)V
+Ljava/nio/charset/CharsetDecoder;->averageCharsPerByte:F
+Ljava/nio/charset/CharsetDecoder;->charset:Ljava/nio/charset/Charset;
+Ljava/nio/charset/CharsetDecoder;->malformedInputAction:Ljava/nio/charset/CodingErrorAction;
+Ljava/nio/charset/CharsetDecoder;->maxCharsPerByte:F
+Ljava/nio/charset/CharsetDecoder;->replacement:Ljava/lang/String;
+Ljava/nio/charset/CharsetDecoder;->state:I
+Ljava/nio/charset/CharsetDecoder;->stateNames:[Ljava/lang/String;
+Ljava/nio/charset/CharsetDecoder;->ST_CODING:I
+Ljava/nio/charset/CharsetDecoder;->ST_END:I
+Ljava/nio/charset/CharsetDecoder;->ST_FLUSHED:I
+Ljava/nio/charset/CharsetDecoder;->ST_RESET:I
+Ljava/nio/charset/CharsetDecoder;->throwIllegalStateException(II)V
+Ljava/nio/charset/CharsetDecoder;->unmappableCharacterAction:Ljava/nio/charset/CodingErrorAction;
+Ljava/nio/charset/CharsetEncoder;-><init>(Ljava/nio/charset/Charset;FF[BZ)V
+Ljava/nio/charset/CharsetEncoder;->averageBytesPerChar:F
+Ljava/nio/charset/CharsetEncoder;->cachedDecoder:Ljava/lang/ref/WeakReference;
+Ljava/nio/charset/CharsetEncoder;->charset:Ljava/nio/charset/Charset;
+Ljava/nio/charset/CharsetEncoder;->malformedInputAction:Ljava/nio/charset/CodingErrorAction;
+Ljava/nio/charset/CharsetEncoder;->maxBytesPerChar:F
+Ljava/nio/charset/CharsetEncoder;->replacement:[B
+Ljava/nio/charset/CharsetEncoder;->state:I
+Ljava/nio/charset/CharsetEncoder;->stateNames:[Ljava/lang/String;
+Ljava/nio/charset/CharsetEncoder;->ST_CODING:I
+Ljava/nio/charset/CharsetEncoder;->ST_END:I
+Ljava/nio/charset/CharsetEncoder;->ST_FLUSHED:I
+Ljava/nio/charset/CharsetEncoder;->ST_RESET:I
+Ljava/nio/charset/CharsetEncoder;->throwIllegalStateException(II)V
+Ljava/nio/charset/CharsetEncoder;->unmappableCharacterAction:Ljava/nio/charset/CodingErrorAction;
+Ljava/nio/charset/CoderResult$Cache;-><init>()V
+Ljava/nio/charset/CoderResult$Cache;->cache:Ljava/util/Map;
+Ljava/nio/charset/CoderResult$Cache;->create(I)Ljava/nio/charset/CoderResult;
+Ljava/nio/charset/CoderResult$Cache;->get(I)Ljava/nio/charset/CoderResult;
+Ljava/nio/charset/CoderResult;-><init>(II)V
+Ljava/nio/charset/CoderResult;->CR_ERROR_MIN:I
+Ljava/nio/charset/CoderResult;->CR_MALFORMED:I
+Ljava/nio/charset/CoderResult;->CR_OVERFLOW:I
+Ljava/nio/charset/CoderResult;->CR_UNDERFLOW:I
+Ljava/nio/charset/CoderResult;->CR_UNMAPPABLE:I
+Ljava/nio/charset/CoderResult;->length:I
+Ljava/nio/charset/CoderResult;->malformedCache:Ljava/nio/charset/CoderResult$Cache;
+Ljava/nio/charset/CoderResult;->names:[Ljava/lang/String;
+Ljava/nio/charset/CoderResult;->type:I
+Ljava/nio/charset/CoderResult;->unmappableCache:Ljava/nio/charset/CoderResult$Cache;
+Ljava/nio/charset/CodingErrorAction;-><init>(Ljava/lang/String;)V
+Ljava/nio/charset/CodingErrorAction;->name:Ljava/lang/String;
+Ljava/nio/charset/IllegalCharsetNameException;->charsetName:Ljava/lang/String;
+Ljava/nio/charset/MalformedInputException;->inputLength:I
+Ljava/nio/charset/ModifiedUtf8;-><init>()V
+Ljava/nio/charset/ModifiedUtf8;->countBytes(Ljava/lang/String;Z)J
+Ljava/nio/charset/ModifiedUtf8;->decode([B[CII)Ljava/lang/String;
+Ljava/nio/charset/ModifiedUtf8;->encode(Ljava/lang/String;)[B
+Ljava/nio/charset/ModifiedUtf8;->encode([BILjava/lang/String;)V
+Ljava/nio/charset/StandardCharsets;-><init>()V
+Ljava/nio/charset/UnmappableCharacterException;->inputLength:I
+Ljava/nio/charset/UnsupportedCharsetException;->charsetName:Ljava/lang/String;
+Ljava/nio/DirectByteBuffer$MemoryRef;-><init>(I)V
+Ljava/nio/DirectByteBuffer$MemoryRef;-><init>(JLjava/lang/Object;)V
+Ljava/nio/DirectByteBuffer$MemoryRef;->allocatedAddress:J
+Ljava/nio/DirectByteBuffer$MemoryRef;->buffer:[B
+Ljava/nio/DirectByteBuffer$MemoryRef;->free()V
+Ljava/nio/DirectByteBuffer$MemoryRef;->isAccessible:Z
+Ljava/nio/DirectByteBuffer$MemoryRef;->isFreed:Z
+Ljava/nio/DirectByteBuffer$MemoryRef;->offset:I
+Ljava/nio/DirectByteBuffer$MemoryRef;->originalBufferObject:Ljava/lang/Object;
+Ljava/nio/DirectByteBuffer;-><init>(IJLjava/io/FileDescriptor;Ljava/lang/Runnable;Z)V
+Ljava/nio/DirectByteBuffer;-><init>(ILjava/nio/DirectByteBuffer$MemoryRef;)V
+Ljava/nio/DirectByteBuffer;-><init>(Ljava/nio/DirectByteBuffer$MemoryRef;IIIII)V
+Ljava/nio/DirectByteBuffer;-><init>(Ljava/nio/DirectByteBuffer$MemoryRef;IIIIIZ)V
+Ljava/nio/DirectByteBuffer;->cleaner:Lsun/misc/Cleaner;
+Ljava/nio/DirectByteBuffer;->get(J)B
+Ljava/nio/DirectByteBuffer;->getCharUnchecked(I)C
+Ljava/nio/DirectByteBuffer;->getDouble(J)D
+Ljava/nio/DirectByteBuffer;->getDoubleUnchecked(I)D
+Ljava/nio/DirectByteBuffer;->getFloat(J)F
+Ljava/nio/DirectByteBuffer;->getFloatUnchecked(I)F
+Ljava/nio/DirectByteBuffer;->getInt(J)I
+Ljava/nio/DirectByteBuffer;->getIntUnchecked(I)I
+Ljava/nio/DirectByteBuffer;->getLong(J)J
+Ljava/nio/DirectByteBuffer;->getLongUnchecked(I)J
+Ljava/nio/DirectByteBuffer;->getShort(J)S
+Ljava/nio/DirectByteBuffer;->getShortUnchecked(I)S
+Ljava/nio/DirectByteBuffer;->getUnchecked(I[CII)V
+Ljava/nio/DirectByteBuffer;->getUnchecked(I[DII)V
+Ljava/nio/DirectByteBuffer;->getUnchecked(I[FII)V
+Ljava/nio/DirectByteBuffer;->getUnchecked(I[III)V
+Ljava/nio/DirectByteBuffer;->getUnchecked(I[JII)V
+Ljava/nio/DirectByteBuffer;->getUnchecked(I[SII)V
+Ljava/nio/DirectByteBuffer;->isAccessible()Z
+Ljava/nio/DirectByteBuffer;->ix(I)J
+Ljava/nio/DirectByteBuffer;->memoryRef:Ljava/nio/DirectByteBuffer$MemoryRef;
+Ljava/nio/DirectByteBuffer;->put(JB)Ljava/nio/ByteBuffer;
+Ljava/nio/DirectByteBuffer;->putChar(JC)Ljava/nio/ByteBuffer;
+Ljava/nio/DirectByteBuffer;->putCharUnchecked(IC)V
+Ljava/nio/DirectByteBuffer;->putDouble(JD)Ljava/nio/ByteBuffer;
+Ljava/nio/DirectByteBuffer;->putDoubleUnchecked(ID)V
+Ljava/nio/DirectByteBuffer;->putFloat(JF)Ljava/nio/ByteBuffer;
+Ljava/nio/DirectByteBuffer;->putFloatUnchecked(IF)V
+Ljava/nio/DirectByteBuffer;->putInt(JI)Ljava/nio/ByteBuffer;
+Ljava/nio/DirectByteBuffer;->putIntUnchecked(II)V
+Ljava/nio/DirectByteBuffer;->putLong(JJ)Ljava/nio/ByteBuffer;
+Ljava/nio/DirectByteBuffer;->putLongUnchecked(IJ)V
+Ljava/nio/DirectByteBuffer;->putShort(JS)Ljava/nio/ByteBuffer;
+Ljava/nio/DirectByteBuffer;->putShortUnchecked(IS)V
+Ljava/nio/DirectByteBuffer;->putUnchecked(I[CII)V
+Ljava/nio/DirectByteBuffer;->putUnchecked(I[DII)V
+Ljava/nio/DirectByteBuffer;->putUnchecked(I[FII)V
+Ljava/nio/DirectByteBuffer;->putUnchecked(I[III)V
+Ljava/nio/DirectByteBuffer;->putUnchecked(I[JII)V
+Ljava/nio/DirectByteBuffer;->putUnchecked(I[SII)V
+Ljava/nio/DirectByteBuffer;->setAccessible(Z)V
+Ljava/nio/DirectByteBuffer;->_get(I)B
+Ljava/nio/DirectByteBuffer;->_put(IB)V
+Ljava/nio/DoubleBuffer;-><init>(IIII)V
+Ljava/nio/DoubleBuffer;-><init>(IIII[DI)V
+Ljava/nio/DoubleBuffer;->compare(DD)I
+Ljava/nio/DoubleBuffer;->equals(DD)Z
+Ljava/nio/DoubleBuffer;->hb:[D
+Ljava/nio/DoubleBuffer;->isReadOnly:Z
+Ljava/nio/DoubleBuffer;->offset:I
+Ljava/nio/file/attribute/AclEntry$Builder;-><init>(Ljava/nio/file/attribute/AclEntryType;Ljava/nio/file/attribute/UserPrincipal;Ljava/util/Set;Ljava/util/Set;)V
+Ljava/nio/file/attribute/AclEntry$Builder;->checkSet(Ljava/util/Set;Ljava/lang/Class;)V
+Ljava/nio/file/attribute/AclEntry$Builder;->flags:Ljava/util/Set;
+Ljava/nio/file/attribute/AclEntry$Builder;->perms:Ljava/util/Set;
+Ljava/nio/file/attribute/AclEntry$Builder;->type:Ljava/nio/file/attribute/AclEntryType;
+Ljava/nio/file/attribute/AclEntry$Builder;->who:Ljava/nio/file/attribute/UserPrincipal;
+Ljava/nio/file/attribute/AclEntry;-><init>(Ljava/nio/file/attribute/AclEntryType;Ljava/nio/file/attribute/UserPrincipal;Ljava/util/Set;Ljava/util/Set;)V
+Ljava/nio/file/attribute/AclEntry;->flags:Ljava/util/Set;
+Ljava/nio/file/attribute/AclEntry;->hash(ILjava/lang/Object;)I
+Ljava/nio/file/attribute/AclEntry;->hash:I
+Ljava/nio/file/attribute/AclEntry;->perms:Ljava/util/Set;
+Ljava/nio/file/attribute/AclEntry;->type:Ljava/nio/file/attribute/AclEntryType;
+Ljava/nio/file/attribute/AclEntry;->who:Ljava/nio/file/attribute/UserPrincipal;
+Ljava/nio/file/attribute/FileTime;-><init>(JLjava/util/concurrent/TimeUnit;Ljava/time/Instant;)V
+Ljava/nio/file/attribute/FileTime;->append(Ljava/lang/StringBuilder;II)Ljava/lang/StringBuilder;
+Ljava/nio/file/attribute/FileTime;->DAYS_PER_10000_YEARS:J
+Ljava/nio/file/attribute/FileTime;->HOURS_PER_DAY:J
+Ljava/nio/file/attribute/FileTime;->instant:Ljava/time/Instant;
+Ljava/nio/file/attribute/FileTime;->MAX_SECOND:J
+Ljava/nio/file/attribute/FileTime;->MICROS_PER_SECOND:J
+Ljava/nio/file/attribute/FileTime;->MILLIS_PER_SECOND:J
+Ljava/nio/file/attribute/FileTime;->MINUTES_PER_HOUR:J
+Ljava/nio/file/attribute/FileTime;->MIN_SECOND:J
+Ljava/nio/file/attribute/FileTime;->NANOS_PER_MICRO:I
+Ljava/nio/file/attribute/FileTime;->NANOS_PER_MILLI:I
+Ljava/nio/file/attribute/FileTime;->NANOS_PER_SECOND:J
+Ljava/nio/file/attribute/FileTime;->scale(JJJ)J
+Ljava/nio/file/attribute/FileTime;->SECONDS_0000_TO_1970:J
+Ljava/nio/file/attribute/FileTime;->SECONDS_PER_10000_YEARS:J
+Ljava/nio/file/attribute/FileTime;->SECONDS_PER_DAY:J
+Ljava/nio/file/attribute/FileTime;->SECONDS_PER_HOUR:J
+Ljava/nio/file/attribute/FileTime;->SECONDS_PER_MINUTE:J
+Ljava/nio/file/attribute/FileTime;->toDays()J
+Ljava/nio/file/attribute/FileTime;->toExcessNanos(J)J
+Ljava/nio/file/attribute/FileTime;->unit:Ljava/util/concurrent/TimeUnit;
+Ljava/nio/file/attribute/FileTime;->value:J
+Ljava/nio/file/attribute/FileTime;->valueAsString:Ljava/lang/String;
+Ljava/nio/file/attribute/PosixFilePermissions;-><init>()V
+Ljava/nio/file/attribute/PosixFilePermissions;->isR(C)Z
+Ljava/nio/file/attribute/PosixFilePermissions;->isSet(CC)Z
+Ljava/nio/file/attribute/PosixFilePermissions;->isW(C)Z
+Ljava/nio/file/attribute/PosixFilePermissions;->isX(C)Z
+Ljava/nio/file/attribute/PosixFilePermissions;->writeBits(Ljava/lang/StringBuilder;ZZZ)V
+Ljava/nio/file/attribute/UserPrincipalNotFoundException;->name:Ljava/lang/String;
+Ljava/nio/file/Files$AcceptAllFilter;-><init>()V
+Ljava/nio/file/Files$AcceptAllFilter;->accept(Ljava/nio/file/Path;)Z
+Ljava/nio/file/Files$AcceptAllFilter;->FILTER:Ljava/nio/file/Files$AcceptAllFilter;
+Ljava/nio/file/Files$FileTypeDetectors;-><init>()V
+Ljava/nio/file/Files$FileTypeDetectors;->createDefaultFileTypeDetector()Ljava/nio/file/spi/FileTypeDetector;
+Ljava/nio/file/Files$FileTypeDetectors;->defaultFileTypeDetector:Ljava/nio/file/spi/FileTypeDetector;
+Ljava/nio/file/Files$FileTypeDetectors;->installeDetectors:Ljava/util/List;
+Ljava/nio/file/Files$FileTypeDetectors;->loadInstalledDetectors()Ljava/util/List;
+Ljava/nio/file/Files;-><init>()V
+Ljava/nio/file/Files;->asUncheckedRunnable(Ljava/io/Closeable;)Ljava/lang/Runnable;
+Ljava/nio/file/Files;->BUFFER_SIZE:I
+Ljava/nio/file/Files;->copy(Ljava/io/InputStream;Ljava/io/OutputStream;)J
+Ljava/nio/file/Files;->MAX_BUFFER_SIZE:I
+Ljava/nio/file/Files;->provider(Ljava/nio/file/Path;)Ljava/nio/file/spi/FileSystemProvider;
+Ljava/nio/file/Files;->read(Ljava/io/InputStream;I)[B
+Ljava/nio/file/FileSystemException;->file:Ljava/lang/String;
+Ljava/nio/file/FileSystemException;->other:Ljava/lang/String;
+Ljava/nio/file/FileSystems$DefaultFileSystemHolder;-><init>()V
+Ljava/nio/file/FileSystems$DefaultFileSystemHolder;->defaultFileSystem()Ljava/nio/file/FileSystem;
+Ljava/nio/file/FileSystems$DefaultFileSystemHolder;->defaultFileSystem:Ljava/nio/file/FileSystem;
+Ljava/nio/file/FileSystems$DefaultFileSystemHolder;->getDefaultProvider()Ljava/nio/file/spi/FileSystemProvider;
+Ljava/nio/file/FileSystems;-><init>()V
+Ljava/nio/file/InvalidPathException;->index:I
+Ljava/nio/file/InvalidPathException;->input:Ljava/lang/String;
+Ljava/nio/file/LinkPermission;->checkName(Ljava/lang/String;)V
+Ljava/nio/file/Paths;-><init>()V
+Ljava/nio/file/spi/FileSystemProvider;-><init>(Ljava/lang/Void;)V
+Ljava/nio/file/spi/FileSystemProvider;->checkPermission()Ljava/lang/Void;
+Ljava/nio/file/spi/FileSystemProvider;->installedProviders:Ljava/util/List;
+Ljava/nio/file/spi/FileSystemProvider;->loadingProviders:Z
+Ljava/nio/file/spi/FileSystemProvider;->loadInstalledProviders()Ljava/util/List;
+Ljava/nio/file/spi/FileSystemProvider;->lock:Ljava/lang/Object;
+Ljava/nio/file/spi/FileTypeDetector;-><init>(Ljava/lang/Void;)V
+Ljava/nio/file/spi/FileTypeDetector;->checkPermission()Ljava/lang/Void;
+Ljava/nio/file/StandardWatchEventKinds$StdWatchEventKind;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
+Ljava/nio/file/StandardWatchEventKinds$StdWatchEventKind;->name:Ljava/lang/String;
+Ljava/nio/file/StandardWatchEventKinds$StdWatchEventKind;->type:Ljava/lang/Class;
+Ljava/nio/file/StandardWatchEventKinds;-><init>()V
+Ljava/nio/FloatBuffer;-><init>(IIII)V
+Ljava/nio/FloatBuffer;-><init>(IIII[FI)V
+Ljava/nio/FloatBuffer;->compare(FF)I
+Ljava/nio/FloatBuffer;->equals(FF)Z
+Ljava/nio/FloatBuffer;->hb:[F
+Ljava/nio/FloatBuffer;->isReadOnly:Z
+Ljava/nio/FloatBuffer;->offset:I
+Ljava/nio/IntBuffer;-><init>(IIII)V
+Ljava/nio/IntBuffer;-><init>(IIII[II)V
+Ljava/nio/IntBuffer;->compare(II)I
+Ljava/nio/IntBuffer;->equals(II)Z
+Ljava/nio/IntBuffer;->hb:[I
+Ljava/nio/IntBuffer;->isReadOnly:Z
+Ljava/nio/IntBuffer;->offset:I
+Ljava/nio/LongBuffer;-><init>(IIII)V
+Ljava/nio/LongBuffer;-><init>(IIII[JI)V
+Ljava/nio/LongBuffer;->compare(JJ)I
+Ljava/nio/LongBuffer;->equals(JJ)Z
+Ljava/nio/LongBuffer;->hb:[J
+Ljava/nio/LongBuffer;->isReadOnly:Z
+Ljava/nio/LongBuffer;->offset:I
+Ljava/nio/MappedByteBuffer;-><init>(IIII)V
+Ljava/nio/MappedByteBuffer;-><init>(IIIILjava/io/FileDescriptor;)V
+Ljava/nio/MappedByteBuffer;-><init>(IIII[BI)V
+Ljava/nio/MappedByteBuffer;->checkMapped()V
+Ljava/nio/MappedByteBuffer;->fd:Ljava/io/FileDescriptor;
+Ljava/nio/MappedByteBuffer;->force0(Ljava/io/FileDescriptor;JJ)V
+Ljava/nio/MappedByteBuffer;->isLoaded0(JJI)Z
+Ljava/nio/MappedByteBuffer;->load0(JJ)V
+Ljava/nio/MappedByteBuffer;->mappingAddress(J)J
+Ljava/nio/MappedByteBuffer;->mappingLength(J)J
+Ljava/nio/MappedByteBuffer;->mappingOffset()J
+Ljava/nio/MappedByteBuffer;->unused:B
+Ljava/nio/NIOAccess;-><init>()V
+Ljava/nio/NioUtils;-><init>()V
+Ljava/nio/NioUtils;->getFD(Ljava/nio/channels/FileChannel;)Ljava/io/FileDescriptor;
+Ljava/nio/NioUtils;->newFileChannel(Ljava/io/Closeable;Ljava/io/FileDescriptor;I)Ljava/nio/channels/FileChannel;
+Ljava/nio/ShortBuffer;-><init>(IIII)V
+Ljava/nio/ShortBuffer;-><init>(IIII[SI)V
+Ljava/nio/ShortBuffer;->compare(SS)I
+Ljava/nio/ShortBuffer;->equals(SS)Z
+Ljava/nio/ShortBuffer;->hb:[S
+Ljava/nio/ShortBuffer;->isReadOnly:Z
+Ljava/nio/ShortBuffer;->offset:I
+Ljava/security/AccessControlException;->perm:Ljava/security/Permission;
+Ljava/security/AccessController;-><init>()V
+Ljava/security/AlgorithmParameterGenerator;->algorithm:Ljava/lang/String;
+Ljava/security/AlgorithmParameterGenerator;->paramGenSpi:Ljava/security/AlgorithmParameterGeneratorSpi;
+Ljava/security/AlgorithmParameterGenerator;->provider:Ljava/security/Provider;
+Ljava/security/AlgorithmParameters;->algorithm:Ljava/lang/String;
+Ljava/security/AlgorithmParameters;->initialized:Z
+Ljava/security/AlgorithmParameters;->paramSpi:Ljava/security/AlgorithmParametersSpi;
+Ljava/security/AlgorithmParameters;->provider:Ljava/security/Provider;
+Ljava/security/cert/Certificate$CertificateRep;->data:[B
+Ljava/security/cert/Certificate$CertificateRep;->type:Ljava/lang/String;
+Ljava/security/cert/Certificate;->hash:I
+Ljava/security/cert/Certificate;->type:Ljava/lang/String;
+Ljava/security/cert/CertificateFactory;->certFacSpi:Ljava/security/cert/CertificateFactorySpi;
+Ljava/security/cert/CertificateFactory;->provider:Ljava/security/Provider;
+Ljava/security/cert/CertificateFactory;->type:Ljava/lang/String;
+Ljava/security/cert/CertificateRevokedException;->authority:Ljavax/security/auth/x500/X500Principal;
+Ljava/security/cert/CertificateRevokedException;->extensions:Ljava/util/Map;
+Ljava/security/cert/CertificateRevokedException;->reason:Ljava/security/cert/CRLReason;
+Ljava/security/cert/CertificateRevokedException;->revocationDate:Ljava/util/Date;
+Ljava/security/cert/CertPath$CertPathRep;->data:[B
+Ljava/security/cert/CertPath$CertPathRep;->type:Ljava/lang/String;
+Ljava/security/cert/CertPath;->type:Ljava/lang/String;
+Ljava/security/cert/CertPathBuilder;->algorithm:Ljava/lang/String;
+Ljava/security/cert/CertPathBuilder;->builderSpi:Ljava/security/cert/CertPathBuilderSpi;
+Ljava/security/cert/CertPathBuilder;->CPB_TYPE:Ljava/lang/String;
+Ljava/security/cert/CertPathBuilder;->provider:Ljava/security/Provider;
+Ljava/security/cert/CertPathValidator;->algorithm:Ljava/lang/String;
+Ljava/security/cert/CertPathValidator;->CPV_TYPE:Ljava/lang/String;
+Ljava/security/cert/CertPathValidator;->provider:Ljava/security/Provider;
+Ljava/security/cert/CertPathValidator;->validatorSpi:Ljava/security/cert/CertPathValidatorSpi;
+Ljava/security/cert/CertPathValidatorException;->certPath:Ljava/security/cert/CertPath;
+Ljava/security/cert/CertPathValidatorException;->index:I
+Ljava/security/cert/CertPathValidatorException;->reason:Ljava/security/cert/CertPathValidatorException$Reason;
+Ljava/security/cert/CertStore;->CERTSTORE_TYPE:Ljava/lang/String;
+Ljava/security/cert/CertStore;->handleException(Ljava/security/NoSuchAlgorithmException;)Ljava/security/cert/CertStore;
+Ljava/security/cert/CertStore;->params:Ljava/security/cert/CertStoreParameters;
+Ljava/security/cert/CertStore;->provider:Ljava/security/Provider;
+Ljava/security/cert/CertStore;->storeSpi:Ljava/security/cert/CertStoreSpi;
+Ljava/security/cert/CertStore;->type:Ljava/lang/String;
+Ljava/security/cert/CollectionCertStoreParameters;->coll:Ljava/util/Collection;
+Ljava/security/cert/CRL;->type:Ljava/lang/String;
+Ljava/security/cert/LDAPCertStoreParameters;->LDAP_DEFAULT_PORT:I
+Ljava/security/cert/LDAPCertStoreParameters;->port:I
+Ljava/security/cert/LDAPCertStoreParameters;->serverName:Ljava/lang/String;
+Ljava/security/cert/PKIXBuilderParameters;->maxPathLength:I
+Ljava/security/cert/PKIXCertPathBuilderResult;->certPath:Ljava/security/cert/CertPath;
+Ljava/security/cert/PKIXCertPathValidatorResult;->policyTree:Ljava/security/cert/PolicyNode;
+Ljava/security/cert/PKIXCertPathValidatorResult;->subjectPublicKey:Ljava/security/PublicKey;
+Ljava/security/cert/PKIXCertPathValidatorResult;->trustAnchor:Ljava/security/cert/TrustAnchor;
+Ljava/security/cert/PKIXParameters;->anyPolicyInhibited:Z
+Ljava/security/cert/PKIXParameters;->certPathCheckers:Ljava/util/List;
+Ljava/security/cert/PKIXParameters;->certSelector:Ljava/security/cert/CertSelector;
+Ljava/security/cert/PKIXParameters;->certStores:Ljava/util/List;
+Ljava/security/cert/PKIXParameters;->date:Ljava/util/Date;
+Ljava/security/cert/PKIXParameters;->explicitPolicyRequired:Z
+Ljava/security/cert/PKIXParameters;->policyMappingInhibited:Z
+Ljava/security/cert/PKIXParameters;->policyQualifiersRejected:Z
+Ljava/security/cert/PKIXParameters;->revocationEnabled:Z
+Ljava/security/cert/PKIXParameters;->sigProvider:Ljava/lang/String;
+Ljava/security/cert/PKIXParameters;->unmodInitialPolicies:Ljava/util/Set;
+Ljava/security/cert/PKIXParameters;->unmodTrustAnchors:Ljava/util/Set;
+Ljava/security/cert/PKIXRevocationChecker;->ocspExtensions:Ljava/util/List;
+Ljava/security/cert/PKIXRevocationChecker;->ocspResponder:Ljava/net/URI;
+Ljava/security/cert/PKIXRevocationChecker;->ocspResponderCert:Ljava/security/cert/X509Certificate;
+Ljava/security/cert/PKIXRevocationChecker;->ocspResponses:Ljava/util/Map;
+Ljava/security/cert/PKIXRevocationChecker;->options:Ljava/util/Set;
+Ljava/security/cert/PolicyQualifierInfo;->mData:[B
+Ljava/security/cert/PolicyQualifierInfo;->mEncoded:[B
+Ljava/security/cert/PolicyQualifierInfo;->mId:Ljava/lang/String;
+Ljava/security/cert/PolicyQualifierInfo;->pqiString:Ljava/lang/String;
+Ljava/security/cert/TrustAnchor;->caName:Ljava/lang/String;
+Ljava/security/cert/TrustAnchor;->caPrincipal:Ljavax/security/auth/x500/X500Principal;
+Ljava/security/cert/TrustAnchor;->nc:Lsun/security/x509/NameConstraintsExtension;
+Ljava/security/cert/TrustAnchor;->ncBytes:[B
+Ljava/security/cert/TrustAnchor;->pubKey:Ljava/security/PublicKey;
+Ljava/security/cert/TrustAnchor;->setNameConstraints([B)V
+Ljava/security/cert/TrustAnchor;->trustedCert:Ljava/security/cert/X509Certificate;
+Ljava/security/cert/X509Certificate;->issuerX500Principal:Ljavax/security/auth/x500/X500Principal;
+Ljava/security/cert/X509Certificate;->subjectX500Principal:Ljavax/security/auth/x500/X500Principal;
+Ljava/security/cert/X509CertSelector;->addPathToNameInternal(ILjava/lang/Object;)V
+Ljava/security/cert/X509CertSelector;->addSubjectAlternativeNameInternal(ILjava/lang/Object;)V
+Ljava/security/cert/X509CertSelector;->ANY_EXTENDED_KEY_USAGE:Lsun/security/util/ObjectIdentifier;
+Ljava/security/cert/X509CertSelector;->authorityKeyID:[B
+Ljava/security/cert/X509CertSelector;->basicConstraints:I
+Ljava/security/cert/X509CertSelector;->certificateValid:Ljava/util/Date;
+Ljava/security/cert/X509CertSelector;->CERT_POLICIES_ID:I
+Ljava/security/cert/X509CertSelector;->cloneAndCheckNames(Ljava/util/Collection;)Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->cloneNames(Ljava/util/Collection;)Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->cloneSet(Ljava/util/Set;)Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->debug:Lsun/security/util/Debug;
+Ljava/security/cert/X509CertSelector;->equalNames(Ljava/util/Collection;Ljava/util/Collection;)Z
+Ljava/security/cert/X509CertSelector;->EXTENDED_KEY_USAGE_ID:I
+Ljava/security/cert/X509CertSelector;->EXTENSION_OIDS:[Ljava/lang/String;
+Ljava/security/cert/X509CertSelector;->FALSE:Ljava/lang/Boolean;
+Ljava/security/cert/X509CertSelector;->getExtensionObject(Ljava/security/cert/X509Certificate;I)Ljava/security/cert/Extension;
+Ljava/security/cert/X509CertSelector;->issuer:Ljavax/security/auth/x500/X500Principal;
+Ljava/security/cert/X509CertSelector;->keyPurposeOIDSet:Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->keyPurposeSet:Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->keyUsage:[Z
+Ljava/security/cert/X509CertSelector;->keyUsageToString([Z)Ljava/lang/String;
+Ljava/security/cert/X509CertSelector;->makeGeneralNameInterface(ILjava/lang/Object;)Lsun/security/x509/GeneralNameInterface;
+Ljava/security/cert/X509CertSelector;->matchAllSubjectAltNames:Z
+Ljava/security/cert/X509CertSelector;->matchAuthorityKeyID(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->matchBasicConstraints(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->matchExcluded(Lsun/security/x509/GeneralSubtrees;)Z
+Ljava/security/cert/X509CertSelector;->matchExtendedKeyUsage(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->matchKeyUsage(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->matchNameConstraints(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->matchPathToNames(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->matchPermitted(Lsun/security/x509/GeneralSubtrees;)Z
+Ljava/security/cert/X509CertSelector;->matchPolicy(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->matchPrivateKeyValid(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->matchSubjectAlternativeNames(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->matchSubjectKeyID(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->matchSubjectPublicKeyAlgID(Ljava/security/cert/X509Certificate;)Z
+Ljava/security/cert/X509CertSelector;->NAME_ANY:I
+Ljava/security/cert/X509CertSelector;->NAME_CONSTRAINTS_ID:I
+Ljava/security/cert/X509CertSelector;->NAME_DIRECTORY:I
+Ljava/security/cert/X509CertSelector;->NAME_DNS:I
+Ljava/security/cert/X509CertSelector;->NAME_EDI:I
+Ljava/security/cert/X509CertSelector;->NAME_IP:I
+Ljava/security/cert/X509CertSelector;->NAME_OID:I
+Ljava/security/cert/X509CertSelector;->NAME_RFC822:I
+Ljava/security/cert/X509CertSelector;->NAME_URI:I
+Ljava/security/cert/X509CertSelector;->NAME_X400:I
+Ljava/security/cert/X509CertSelector;->nc:Lsun/security/x509/NameConstraintsExtension;
+Ljava/security/cert/X509CertSelector;->ncBytes:[B
+Ljava/security/cert/X509CertSelector;->NUM_OF_EXTENSIONS:I
+Ljava/security/cert/X509CertSelector;->parseNames(Ljava/util/Collection;)Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->pathToGeneralNames:Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->pathToNames:Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->policy:Lsun/security/x509/CertificatePolicySet;
+Ljava/security/cert/X509CertSelector;->policySet:Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->privateKeyValid:Ljava/util/Date;
+Ljava/security/cert/X509CertSelector;->PRIVATE_KEY_USAGE_ID:I
+Ljava/security/cert/X509CertSelector;->serialNumber:Ljava/math/BigInteger;
+Ljava/security/cert/X509CertSelector;->setPathToNamesInternal(Ljava/util/Set;)V
+Ljava/security/cert/X509CertSelector;->subject:Ljavax/security/auth/x500/X500Principal;
+Ljava/security/cert/X509CertSelector;->subjectAlternativeGeneralNames:Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->subjectAlternativeNames:Ljava/util/Set;
+Ljava/security/cert/X509CertSelector;->subjectKeyID:[B
+Ljava/security/cert/X509CertSelector;->subjectPublicKey:Ljava/security/PublicKey;
+Ljava/security/cert/X509CertSelector;->subjectPublicKeyAlgID:Lsun/security/util/ObjectIdentifier;
+Ljava/security/cert/X509CertSelector;->subjectPublicKeyBytes:[B
+Ljava/security/cert/X509CertSelector;->SUBJECT_ALT_NAME_ID:I
+Ljava/security/cert/X509CertSelector;->x509Cert:Ljava/security/cert/X509Certificate;
+Ljava/security/cert/X509CRL;->issuerPrincipal:Ljavax/security/auth/x500/X500Principal;
+Ljava/security/cert/X509CRLSelector;->addIssuerNameInternal(Ljava/lang/Object;Ljavax/security/auth/x500/X500Principal;)V
+Ljava/security/cert/X509CRLSelector;->certChecking:Ljava/security/cert/X509Certificate;
+Ljava/security/cert/X509CRLSelector;->cloneAndCheckIssuerNames(Ljava/util/Collection;)Ljava/util/HashSet;
+Ljava/security/cert/X509CRLSelector;->cloneIssuerNames(Ljava/util/Collection;)Ljava/util/HashSet;
+Ljava/security/cert/X509CRLSelector;->dateAndTime:Ljava/util/Date;
+Ljava/security/cert/X509CRLSelector;->debug:Lsun/security/util/Debug;
+Ljava/security/cert/X509CRLSelector;->issuerNames:Ljava/util/HashSet;
+Ljava/security/cert/X509CRLSelector;->issuerX500Principals:Ljava/util/HashSet;
+Ljava/security/cert/X509CRLSelector;->maxCRL:Ljava/math/BigInteger;
+Ljava/security/cert/X509CRLSelector;->minCRL:Ljava/math/BigInteger;
+Ljava/security/cert/X509CRLSelector;->parseIssuerNames(Ljava/util/Collection;)Ljava/util/HashSet;
+Ljava/security/cert/X509CRLSelector;->setDateAndTime(Ljava/util/Date;J)V
+Ljava/security/cert/X509CRLSelector;->skew:J
+Ljava/security/CodeSigner;->myhash:I
+Ljava/security/CodeSigner;->signerCertPath:Ljava/security/cert/CertPath;
+Ljava/security/CodeSigner;->timestamp:Ljava/security/Timestamp;
+Ljava/security/CodeSource;->location:Ljava/net/URL;
+Ljava/security/DigestInputStream;->on:Z
+Ljava/security/DigestOutputStream;->on:Z
+Ljava/security/DomainLoadStoreParameter;->configuration:Ljava/net/URI;
+Ljava/security/DomainLoadStoreParameter;->protectionParams:Ljava/util/Map;
+Ljava/security/GuardedObject;->guard:Ljava/security/Guard;
+Ljava/security/GuardedObject;->object:Ljava/lang/Object;
+Ljava/security/Identity;->certificates:Ljava/util/Vector;
+Ljava/security/Identity;->check(Ljava/lang/String;)V
+Ljava/security/Identity;->fullName()Ljava/lang/String;
+Ljava/security/Identity;->info:Ljava/lang/String;
+Ljava/security/Identity;->keyEquals(Ljava/security/PublicKey;Ljava/security/PublicKey;)Z
+Ljava/security/Identity;->name:Ljava/lang/String;
+Ljava/security/Identity;->printCertificates()Ljava/lang/String;
+Ljava/security/Identity;->printKeys()Ljava/lang/String;
+Ljava/security/Identity;->publicKey:Ljava/security/PublicKey;
+Ljava/security/Identity;->scope:Ljava/security/IdentityScope;
+Ljava/security/IdentityScope;->check(Ljava/lang/String;)V
+Ljava/security/IdentityScope;->initializeSystemScope()V
+Ljava/security/IdentityScope;->scope:Ljava/security/IdentityScope;
+Ljava/security/KeyFactory;-><init>(Ljava/lang/String;)V
+Ljava/security/KeyFactory;->algorithm:Ljava/lang/String;
+Ljava/security/KeyFactory;->debug:Lsun/security/util/Debug;
+Ljava/security/KeyFactory;->lock:Ljava/lang/Object;
+Ljava/security/KeyFactory;->nextSpi(Ljava/security/KeyFactorySpi;)Ljava/security/KeyFactorySpi;
+Ljava/security/KeyFactory;->provider:Ljava/security/Provider;
+Ljava/security/KeyFactory;->serviceIterator:Ljava/util/Iterator;
+Ljava/security/KeyFactory;->spi:Ljava/security/KeyFactorySpi;
+Ljava/security/KeyPair;->privateKey:Ljava/security/PrivateKey;
+Ljava/security/KeyPair;->publicKey:Ljava/security/PublicKey;
+Ljava/security/KeyPairGenerator$Delegate;-><init>(Ljava/security/KeyPairGeneratorSpi;Ljava/lang/String;)V
+Ljava/security/KeyPairGenerator$Delegate;-><init>(Lsun/security/jca/GetInstance$Instance;Ljava/util/Iterator;Ljava/lang/String;)V
+Ljava/security/KeyPairGenerator$Delegate;->disableFailover()V
+Ljava/security/KeyPairGenerator$Delegate;->initKeySize:I
+Ljava/security/KeyPairGenerator$Delegate;->initParams:Ljava/security/spec/AlgorithmParameterSpec;
+Ljava/security/KeyPairGenerator$Delegate;->initRandom:Ljava/security/SecureRandom;
+Ljava/security/KeyPairGenerator$Delegate;->initType:I
+Ljava/security/KeyPairGenerator$Delegate;->I_NONE:I
+Ljava/security/KeyPairGenerator$Delegate;->I_PARAMS:I
+Ljava/security/KeyPairGenerator$Delegate;->I_SIZE:I
+Ljava/security/KeyPairGenerator$Delegate;->lock:Ljava/lang/Object;
+Ljava/security/KeyPairGenerator$Delegate;->nextSpi(Ljava/security/KeyPairGeneratorSpi;Z)Ljava/security/KeyPairGeneratorSpi;
+Ljava/security/KeyPairGenerator$Delegate;->serviceIterator:Ljava/util/Iterator;
+Ljava/security/KeyPairGenerator$Delegate;->spi:Ljava/security/KeyPairGeneratorSpi;
+Ljava/security/KeyPairGenerator;->algorithm:Ljava/lang/String;
+Ljava/security/KeyPairGenerator;->disableFailover()V
+Ljava/security/KeyPairGenerator;->provider:Ljava/security/Provider;
+Ljava/security/KeyRep;->algorithm:Ljava/lang/String;
+Ljava/security/KeyRep;->encoded:[B
+Ljava/security/KeyRep;->format:Ljava/lang/String;
+Ljava/security/KeyRep;->PKCS8:Ljava/lang/String;
+Ljava/security/KeyRep;->RAW:Ljava/lang/String;
+Ljava/security/KeyRep;->type:Ljava/security/KeyRep$Type;
+Ljava/security/KeyRep;->X509:Ljava/lang/String;
+Ljava/security/KeyStore$Builder$FileBuilder;-><init>(Ljava/lang/String;Ljava/security/Provider;Ljava/io/File;Ljava/security/KeyStore$ProtectionParameter;Ljava/security/AccessControlContext;)V
+Ljava/security/KeyStore$Builder$FileBuilder;->context:Ljava/security/AccessControlContext;
+Ljava/security/KeyStore$Builder$FileBuilder;->file:Ljava/io/File;
+Ljava/security/KeyStore$Builder$FileBuilder;->keyProtection:Ljava/security/KeyStore$ProtectionParameter;
+Ljava/security/KeyStore$Builder$FileBuilder;->keyStore:Ljava/security/KeyStore;
+Ljava/security/KeyStore$Builder$FileBuilder;->oldException:Ljava/lang/Throwable;
+Ljava/security/KeyStore$Builder$FileBuilder;->protection:Ljava/security/KeyStore$ProtectionParameter;
+Ljava/security/KeyStore$Builder$FileBuilder;->provider:Ljava/security/Provider;
+Ljava/security/KeyStore$Builder$FileBuilder;->type:Ljava/lang/String;
+Ljava/security/KeyStore$Builder;->MAX_CALLBACK_TRIES:I
+Ljava/security/KeyStore$CallbackHandlerProtection;->handler:Ljavax/security/auth/callback/CallbackHandler;
+Ljava/security/KeyStore$PasswordProtection;->destroyed:Z
+Ljava/security/KeyStore$PasswordProtection;->password:[C
+Ljava/security/KeyStore$PasswordProtection;->protectionAlgorithm:Ljava/lang/String;
+Ljava/security/KeyStore$PasswordProtection;->protectionParameters:Ljava/security/spec/AlgorithmParameterSpec;
+Ljava/security/KeyStore$PrivateKeyEntry;->attributes:Ljava/util/Set;
+Ljava/security/KeyStore$PrivateKeyEntry;->chain:[Ljava/security/cert/Certificate;
+Ljava/security/KeyStore$PrivateKeyEntry;->privKey:Ljava/security/PrivateKey;
+Ljava/security/KeyStore$SecretKeyEntry;->attributes:Ljava/util/Set;
+Ljava/security/KeyStore$SecretKeyEntry;->sKey:Ljavax/crypto/SecretKey;
+Ljava/security/KeyStore$SimpleLoadStoreParameter;-><init>(Ljava/security/KeyStore$ProtectionParameter;)V
+Ljava/security/KeyStore$SimpleLoadStoreParameter;->protection:Ljava/security/KeyStore$ProtectionParameter;
+Ljava/security/KeyStore$TrustedCertificateEntry;->attributes:Ljava/util/Set;
+Ljava/security/KeyStore$TrustedCertificateEntry;->cert:Ljava/security/cert/Certificate;
+Ljava/security/KeyStore;->initialized:Z
+Ljava/security/KeyStore;->KEYSTORE_TYPE:Ljava/lang/String;
+Ljava/security/KeyStore;->provider:Ljava/security/Provider;
+Ljava/security/KeyStore;->type:Ljava/lang/String;
+Ljava/security/MessageDigest$Delegate;-><init>(Ljava/security/MessageDigestSpi;Ljava/lang/String;)V
+Ljava/security/MessageDigest$Delegate;->digestSpi:Ljava/security/MessageDigestSpi;
+Ljava/security/MessageDigest;->algorithm:Ljava/lang/String;
+Ljava/security/MessageDigest;->INITIAL:I
+Ljava/security/MessageDigest;->IN_PROGRESS:I
+Ljava/security/MessageDigest;->provider:Ljava/security/Provider;
+Ljava/security/MessageDigest;->state:I
+Ljava/security/MessageDigestSpi;->tempArray:[B
+Ljava/security/Permission;->name:Ljava/lang/String;
+Ljava/security/PKCS12Attribute;->COLON_SEPARATED_HEX_PAIRS:Ljava/util/regex/Pattern;
+Ljava/security/PKCS12Attribute;->encode(Lsun/security/util/ObjectIdentifier;[Ljava/lang/String;)[B
+Ljava/security/PKCS12Attribute;->encoded:[B
+Ljava/security/PKCS12Attribute;->hashValue:I
+Ljava/security/PKCS12Attribute;->name:Ljava/lang/String;
+Ljava/security/PKCS12Attribute;->parse([B)V
+Ljava/security/PKCS12Attribute;->value:Ljava/lang/String;
+Ljava/security/Policy$UnsupportedEmptyCollection;-><init>()V
+Ljava/security/PrivilegedActionException;->exception:Ljava/lang/Exception;
+Ljava/security/Provider$EngineDescription;-><init>(Ljava/lang/String;ZLjava/lang/String;)V
+Ljava/security/Provider$EngineDescription;->constructorParameterClass:Ljava/lang/Class;
+Ljava/security/Provider$EngineDescription;->constructorParameterClassName:Ljava/lang/String;
+Ljava/security/Provider$EngineDescription;->getConstructorParameterClass()Ljava/lang/Class;
+Ljava/security/Provider$EngineDescription;->name:Ljava/lang/String;
+Ljava/security/Provider$EngineDescription;->supportsParameter:Z
+Ljava/security/Provider$Service;-><init>(Ljava/security/Provider;)V
+Ljava/security/Provider$Service;->addAlias(Ljava/lang/String;)V
+Ljava/security/Provider$Service;->addAttribute(Ljava/lang/String;Ljava/lang/String;)V
+Ljava/security/Provider$Service;->algorithm:Ljava/lang/String;
+Ljava/security/Provider$Service;->aliases:Ljava/util/List;
+Ljava/security/Provider$Service;->attributes:Ljava/util/Map;
+Ljava/security/Provider$Service;->CLASS0:[Ljava/lang/Class;
+Ljava/security/Provider$Service;->className:Ljava/lang/String;
+Ljava/security/Provider$Service;->classRef:Ljava/lang/ref/Reference;
+Ljava/security/Provider$Service;->getAliases()Ljava/util/List;
+Ljava/security/Provider$Service;->getImplClass()Ljava/lang/Class;
+Ljava/security/Provider$Service;->getKeyClass(Ljava/lang/String;)Ljava/lang/Class;
+Ljava/security/Provider$Service;->hasKeyAttributes()Z
+Ljava/security/Provider$Service;->hasKeyAttributes:Ljava/lang/Boolean;
+Ljava/security/Provider$Service;->isValid()Z
+Ljava/security/Provider$Service;->newInstanceGeneric(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/security/Provider$Service;->provider:Ljava/security/Provider;
+Ljava/security/Provider$Service;->registered:Z
+Ljava/security/Provider$Service;->supportedClasses:[Ljava/lang/Class;
+Ljava/security/Provider$Service;->supportedFormats:[Ljava/lang/String;
+Ljava/security/Provider$Service;->supportsKeyClass(Ljava/security/Key;)Z
+Ljava/security/Provider$Service;->supportsKeyFormat(Ljava/security/Key;)Z
+Ljava/security/Provider$Service;->type:Ljava/lang/String;
+Ljava/security/Provider$ServiceKey;-><init>(Ljava/lang/String;Ljava/lang/String;Z)V
+Ljava/security/Provider$ServiceKey;->algorithm:Ljava/lang/String;
+Ljava/security/Provider$ServiceKey;->matches(Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/security/Provider$ServiceKey;->originalAlgorithm:Ljava/lang/String;
+Ljava/security/Provider$ServiceKey;->type:Ljava/lang/String;
+Ljava/security/Provider$UString;-><init>(Ljava/lang/String;)V
+Ljava/security/Provider$UString;->lowerString:Ljava/lang/String;
+Ljava/security/Provider$UString;->string:Ljava/lang/String;
+Ljava/security/Provider;->addEngine(Ljava/lang/String;ZLjava/lang/String;)V
+Ljava/security/Provider;->ALIAS_LENGTH:I
+Ljava/security/Provider;->ALIAS_PREFIX:Ljava/lang/String;
+Ljava/security/Provider;->ALIAS_PREFIX_LOWER:Ljava/lang/String;
+Ljava/security/Provider;->check(Ljava/lang/String;)V
+Ljava/security/Provider;->checkInitialized()V
+Ljava/security/Provider;->checkLegacy(Ljava/lang/Object;)Z
+Ljava/security/Provider;->debug:Lsun/security/util/Debug;
+Ljava/security/Provider;->ensureLegacyParsed()V
+Ljava/security/Provider;->entrySet:Ljava/util/Set;
+Ljava/security/Provider;->entrySetCallCount:I
+Ljava/security/Provider;->getEngineName(Ljava/lang/String;)Ljava/lang/String;
+Ljava/security/Provider;->getTypeAndAlgorithm(Ljava/lang/String;)[Ljava/lang/String;
+Ljava/security/Provider;->implClear()V
+Ljava/security/Provider;->implCompute(Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;
+Ljava/security/Provider;->implComputeIfAbsent(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;
+Ljava/security/Provider;->implComputeIfPresent(Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;
+Ljava/security/Provider;->implMerge(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;
+Ljava/security/Provider;->implPut(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/security/Provider;->implPutAll(Ljava/util/Map;)V
+Ljava/security/Provider;->implPutIfAbsent(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/security/Provider;->implRemove(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/security/Provider;->implRemove(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/security/Provider;->implRemoveService(Ljava/security/Provider$Service;)V
+Ljava/security/Provider;->implReplace(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/security/Provider;->implReplace(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/security/Provider;->implReplaceAll(Ljava/util/function/BiFunction;)V
+Ljava/security/Provider;->info:Ljava/lang/String;
+Ljava/security/Provider;->initialized:Z
+Ljava/security/Provider;->isRegistered()Z
+Ljava/security/Provider;->knownEngines:Ljava/util/Map;
+Ljava/security/Provider;->legacyChanged:Z
+Ljava/security/Provider;->legacyMap:Ljava/util/Map;
+Ljava/security/Provider;->legacyStrings:Ljava/util/Map;
+Ljava/security/Provider;->name:Ljava/lang/String;
+Ljava/security/Provider;->parseLegacyPut(Ljava/lang/String;Ljava/lang/String;)V
+Ljava/security/Provider;->previousKey:Ljava/security/Provider$ServiceKey;
+Ljava/security/Provider;->putId()V
+Ljava/security/Provider;->putPropertyStrings(Ljava/security/Provider$Service;)V
+Ljava/security/Provider;->registered:Z
+Ljava/security/Provider;->removeInvalidServices(Ljava/util/Map;)V
+Ljava/security/Provider;->removePropertyStrings(Ljava/security/Provider$Service;)V
+Ljava/security/Provider;->serviceMap:Ljava/util/Map;
+Ljava/security/Provider;->servicesChanged:Z
+Ljava/security/Provider;->serviceSet:Ljava/util/Set;
+Ljava/security/Provider;->setRegistered()V
+Ljava/security/Provider;->setUnregistered()V
+Ljava/security/Provider;->version:D
+Ljava/security/Provider;->warmUpServiceProvision()V
+Ljava/security/SecureClassLoader;->check()V
+Ljava/security/SecureClassLoader;->debug:Lsun/security/util/Debug;
+Ljava/security/SecureClassLoader;->getProtectionDomain(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;
+Ljava/security/SecureClassLoader;->initialized:Z
+Ljava/security/SecureClassLoader;->pdcache:Ljava/util/HashMap;
+Ljava/security/SecureRandom$StrongPatternHolder;-><init>()V
+Ljava/security/SecureRandom$StrongPatternHolder;->pattern:Ljava/util/regex/Pattern;
+Ljava/security/SecureRandom;-><init>(Ljava/security/SecureRandomSpi;Ljava/security/Provider;Ljava/lang/String;)V
+Ljava/security/SecureRandom;->algorithm:Ljava/lang/String;
+Ljava/security/SecureRandom;->counter:J
+Ljava/security/SecureRandom;->digest:Ljava/security/MessageDigest;
+Ljava/security/SecureRandom;->getDefaultPRNG(Z[B)V
+Ljava/security/SecureRandom;->getPrngAlgorithm()Ljava/lang/String;
+Ljava/security/SecureRandom;->getSecureRandomSpi()Ljava/security/SecureRandomSpi;
+Ljava/security/SecureRandom;->longToByteArray(J)[B
+Ljava/security/SecureRandom;->provider:Ljava/security/Provider;
+Ljava/security/SecureRandom;->randomBytes:[B
+Ljava/security/SecureRandom;->randomBytesUsed:I
+Ljava/security/SecureRandom;->secureRandomSpi:Ljava/security/SecureRandomSpi;
+Ljava/security/SecureRandom;->seedGenerator:Ljava/security/SecureRandom;
+Ljava/security/SecureRandom;->state:[B
+Ljava/security/Security$ProviderProperty;-><init>()V
+Ljava/security/Security$ProviderProperty;->className:Ljava/lang/String;
+Ljava/security/Security$ProviderProperty;->provider:Ljava/security/Provider;
+Ljava/security/Security;-><init>()V
+Ljava/security/Security;->getAllQualifyingCandidates(Ljava/lang/String;Ljava/lang/String;[Ljava/security/Provider;)Ljava/util/LinkedHashSet;
+Ljava/security/Security;->getFilterComponents(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;
+Ljava/security/Security;->getImpl(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/Object;
+Ljava/security/Security;->getImpl(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)[Ljava/lang/Object;
+Ljava/security/Security;->getImpl(Ljava/lang/String;Ljava/lang/String;Ljava/security/Provider;)[Ljava/lang/Object;
+Ljava/security/Security;->getImpl(Ljava/lang/String;Ljava/lang/String;Ljava/security/Provider;Ljava/lang/Object;)[Ljava/lang/Object;
+Ljava/security/Security;->getProviderProperty(Ljava/lang/String;)Ljava/security/Security$ProviderProperty;
+Ljava/security/Security;->getProviderProperty(Ljava/lang/String;Ljava/security/Provider;)Ljava/lang/String;
+Ljava/security/Security;->getProvidersNotUsingCache(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/security/Provider;)Ljava/util/LinkedHashSet;
+Ljava/security/Security;->getSpiClass(Ljava/lang/String;)Ljava/lang/Class;
+Ljava/security/Security;->getVersion()I
+Ljava/security/Security;->increaseVersion()V
+Ljava/security/Security;->initializeStatic()V
+Ljava/security/Security;->invalidateSMCache(Ljava/lang/String;)V
+Ljava/security/Security;->isConstraintSatisfied(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/security/Security;->isCriterionSatisfied(Ljava/security/Provider;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/security/Security;->isStandardAttr(Ljava/lang/String;)Z
+Ljava/security/Security;->props:Ljava/util/Properties;
+Ljava/security/Security;->spiMap:Ljava/util/Map;
+Ljava/security/Security;->version:Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/security/Signature$CipherAdapter;-><init>(Ljavax/crypto/Cipher;)V
+Ljava/security/Signature$CipherAdapter;->cipher:Ljavax/crypto/Cipher;
+Ljava/security/Signature$CipherAdapter;->data:Ljava/io/ByteArrayOutputStream;
+Ljava/security/Signature$Delegate;-><init>(Ljava/lang/String;)V
+Ljava/security/Signature$Delegate;-><init>(Ljava/security/SignatureSpi;Ljava/lang/String;)V
+Ljava/security/Signature$Delegate;->chooseFirstProvider()V
+Ljava/security/Signature$Delegate;->chooseProvider(ILjava/security/Key;Ljava/security/SecureRandom;)V
+Ljava/security/Signature$Delegate;->getCurrentSpi()Ljava/security/SignatureSpi;
+Ljava/security/Signature$Delegate;->init(Ljava/security/SignatureSpi;ILjava/security/Key;Ljava/security/SecureRandom;)V
+Ljava/security/Signature$Delegate;->I_PRIV:I
+Ljava/security/Signature$Delegate;->I_PRIV_SR:I
+Ljava/security/Signature$Delegate;->I_PUB:I
+Ljava/security/Signature$Delegate;->lock:Ljava/lang/Object;
+Ljava/security/Signature$Delegate;->newInstance(Ljava/security/Provider$Service;)Ljava/security/SignatureSpi;
+Ljava/security/Signature$Delegate;->sigSpi:Ljava/security/SignatureSpi;
+Ljava/security/Signature$Delegate;->warnCount:I
+Ljava/security/Signature;->algorithm:Ljava/lang/String;
+Ljava/security/Signature;->chooseFirstProvider()V
+Ljava/security/Signature;->getCurrentSpi()Ljava/security/SignatureSpi;
+Ljava/security/Signature;->getInstanceRSA(Ljava/security/Provider;)Ljava/security/Signature;
+Ljava/security/Signature;->isSpi(Ljava/security/Provider$Service;)Z
+Ljava/security/Signature;->provider:Ljava/security/Provider;
+Ljava/security/Signature;->rsaIds:Ljava/util/List;
+Ljava/security/Signature;->RSA_CIPHER:Ljava/lang/String;
+Ljava/security/Signature;->RSA_SIGNATURE:Ljava/lang/String;
+Ljava/security/Signature;->signatureInfo:Ljava/util/Map;
+Ljava/security/SignedObject;->content:[B
+Ljava/security/SignedObject;->sign(Ljava/security/PrivateKey;Ljava/security/Signature;)V
+Ljava/security/SignedObject;->signature:[B
+Ljava/security/SignedObject;->thealgorithm:Ljava/lang/String;
+Ljava/security/Signer;->check(Ljava/lang/String;)V
+Ljava/security/Signer;->printKeys()Ljava/lang/String;
+Ljava/security/Signer;->privateKey:Ljava/security/PrivateKey;
+Ljava/security/spec/DSAParameterSpec;->g:Ljava/math/BigInteger;
+Ljava/security/spec/DSAParameterSpec;->p:Ljava/math/BigInteger;
+Ljava/security/spec/DSAParameterSpec;->q:Ljava/math/BigInteger;
+Ljava/security/spec/DSAPrivateKeySpec;->g:Ljava/math/BigInteger;
+Ljava/security/spec/DSAPrivateKeySpec;->p:Ljava/math/BigInteger;
+Ljava/security/spec/DSAPrivateKeySpec;->q:Ljava/math/BigInteger;
+Ljava/security/spec/DSAPrivateKeySpec;->x:Ljava/math/BigInteger;
+Ljava/security/spec/DSAPublicKeySpec;->g:Ljava/math/BigInteger;
+Ljava/security/spec/DSAPublicKeySpec;->p:Ljava/math/BigInteger;
+Ljava/security/spec/DSAPublicKeySpec;->q:Ljava/math/BigInteger;
+Ljava/security/spec/DSAPublicKeySpec;->y:Ljava/math/BigInteger;
+Ljava/security/spec/ECFieldF2m;->ks:[I
+Ljava/security/spec/ECFieldF2m;->m:I
+Ljava/security/spec/ECFieldF2m;->rp:Ljava/math/BigInteger;
+Ljava/security/spec/ECFieldFp;->p:Ljava/math/BigInteger;
+Ljava/security/spec/ECGenParameterSpec;->name:Ljava/lang/String;
+Ljava/security/spec/ECParameterSpec;->curve:Ljava/security/spec/EllipticCurve;
+Ljava/security/spec/ECParameterSpec;->curveName:Ljava/lang/String;
+Ljava/security/spec/ECParameterSpec;->g:Ljava/security/spec/ECPoint;
+Ljava/security/spec/ECParameterSpec;->h:I
+Ljava/security/spec/ECParameterSpec;->n:Ljava/math/BigInteger;
+Ljava/security/spec/ECPoint;-><init>()V
+Ljava/security/spec/ECPoint;->x:Ljava/math/BigInteger;
+Ljava/security/spec/ECPoint;->y:Ljava/math/BigInteger;
+Ljava/security/spec/ECPrivateKeySpec;->params:Ljava/security/spec/ECParameterSpec;
+Ljava/security/spec/ECPrivateKeySpec;->s:Ljava/math/BigInteger;
+Ljava/security/spec/ECPublicKeySpec;->params:Ljava/security/spec/ECParameterSpec;
+Ljava/security/spec/ECPublicKeySpec;->w:Ljava/security/spec/ECPoint;
+Ljava/security/spec/EllipticCurve;->a:Ljava/math/BigInteger;
+Ljava/security/spec/EllipticCurve;->b:Ljava/math/BigInteger;
+Ljava/security/spec/EllipticCurve;->checkValidity(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/lang/String;)V
+Ljava/security/spec/EllipticCurve;->field:Ljava/security/spec/ECField;
+Ljava/security/spec/EllipticCurve;->seed:[B
+Ljava/security/spec/EncodedKeySpec;->encodedKey:[B
+Ljava/security/spec/MGF1ParameterSpec;->mdName:Ljava/lang/String;
+Ljava/security/spec/PSSParameterSpec;-><init>()V
+Ljava/security/spec/PSSParameterSpec;->mdName:Ljava/lang/String;
+Ljava/security/spec/PSSParameterSpec;->mgfName:Ljava/lang/String;
+Ljava/security/spec/PSSParameterSpec;->mgfSpec:Ljava/security/spec/AlgorithmParameterSpec;
+Ljava/security/spec/PSSParameterSpec;->saltLen:I
+Ljava/security/spec/PSSParameterSpec;->trailerField:I
+Ljava/security/spec/RSAKeyGenParameterSpec;->keysize:I
+Ljava/security/spec/RSAKeyGenParameterSpec;->publicExponent:Ljava/math/BigInteger;
+Ljava/security/spec/RSAMultiPrimePrivateCrtKeySpec;->crtCoefficient:Ljava/math/BigInteger;
+Ljava/security/spec/RSAMultiPrimePrivateCrtKeySpec;->otherPrimeInfo:[Ljava/security/spec/RSAOtherPrimeInfo;
+Ljava/security/spec/RSAMultiPrimePrivateCrtKeySpec;->primeExponentP:Ljava/math/BigInteger;
+Ljava/security/spec/RSAMultiPrimePrivateCrtKeySpec;->primeExponentQ:Ljava/math/BigInteger;
+Ljava/security/spec/RSAMultiPrimePrivateCrtKeySpec;->primeP:Ljava/math/BigInteger;
+Ljava/security/spec/RSAMultiPrimePrivateCrtKeySpec;->primeQ:Ljava/math/BigInteger;
+Ljava/security/spec/RSAMultiPrimePrivateCrtKeySpec;->publicExponent:Ljava/math/BigInteger;
+Ljava/security/spec/RSAOtherPrimeInfo;->crtCoefficient:Ljava/math/BigInteger;
+Ljava/security/spec/RSAOtherPrimeInfo;->prime:Ljava/math/BigInteger;
+Ljava/security/spec/RSAOtherPrimeInfo;->primeExponent:Ljava/math/BigInteger;
+Ljava/security/spec/RSAPrivateCrtKeySpec;->crtCoefficient:Ljava/math/BigInteger;
+Ljava/security/spec/RSAPrivateCrtKeySpec;->primeExponentP:Ljava/math/BigInteger;
+Ljava/security/spec/RSAPrivateCrtKeySpec;->primeExponentQ:Ljava/math/BigInteger;
+Ljava/security/spec/RSAPrivateCrtKeySpec;->primeP:Ljava/math/BigInteger;
+Ljava/security/spec/RSAPrivateCrtKeySpec;->primeQ:Ljava/math/BigInteger;
+Ljava/security/spec/RSAPrivateCrtKeySpec;->publicExponent:Ljava/math/BigInteger;
+Ljava/security/spec/RSAPrivateKeySpec;->modulus:Ljava/math/BigInteger;
+Ljava/security/spec/RSAPrivateKeySpec;->privateExponent:Ljava/math/BigInteger;
+Ljava/security/spec/RSAPublicKeySpec;->modulus:Ljava/math/BigInteger;
+Ljava/security/spec/RSAPublicKeySpec;->publicExponent:Ljava/math/BigInteger;
+Ljava/security/Timestamp;->myhash:I
+Ljava/security/Timestamp;->signerCertPath:Ljava/security/cert/CertPath;
+Ljava/security/Timestamp;->timestamp:Ljava/util/Date;
+Ljava/sql/BatchUpdateException;->updateCounts:[I
+Ljava/sql/DataTruncation;->dataSize:I
+Ljava/sql/DataTruncation;->index:I
+Ljava/sql/DataTruncation;->parameter:Z
+Ljava/sql/DataTruncation;->read:Z
+Ljava/sql/DataTruncation;->transferSize:I
+Ljava/sql/DriverInfo;-><init>(Ljava/sql/Driver;)V
+Ljava/sql/DriverInfo;->driver:Ljava/sql/Driver;
+Ljava/sql/DriverManager;-><init>()V
+Ljava/sql/DriverManager;->getConnection(Ljava/lang/String;Ljava/util/Properties;Ljava/lang/ClassLoader;)Ljava/sql/Connection;
+Ljava/sql/DriverManager;->isDriverAllowed(Ljava/sql/Driver;Ljava/lang/ClassLoader;)Z
+Ljava/sql/DriverManager;->loadInitialDrivers()V
+Ljava/sql/DriverManager;->loginTimeout:I
+Ljava/sql/DriverManager;->logStream:Ljava/io/PrintStream;
+Ljava/sql/DriverManager;->logSync:Ljava/lang/Object;
+Ljava/sql/DriverManager;->logWriter:Ljava/io/PrintWriter;
+Ljava/sql/DriverManager;->registeredDrivers:Ljava/util/concurrent/CopyOnWriteArrayList;
+Ljava/sql/DriverManager;->SET_LOG_PERMISSION:Ljava/sql/SQLPermission;
+Ljava/sql/SQLClientInfoException;->failedProperties:Ljava/util/Map;
+Ljava/sql/SQLException;->next:Ljava/sql/SQLException;
+Ljava/sql/SQLException;->nextUpdater:Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;
+Ljava/sql/SQLException;->SQLState:Ljava/lang/String;
+Ljava/sql/SQLException;->vendorCode:I
+Ljava/sql/Timestamp;->nanos:I
+Ljava/sql/Types;-><init>()V
+Ljava/text/Annotation;->value:Ljava/lang/Object;
+Ljava/text/AttributedCharacterIterator$Attribute;->instanceMap:Ljava/util/Map;
+Ljava/text/AttributedCharacterIterator$Attribute;->name:Ljava/lang/String;
+Ljava/text/AttributedString$AttributedStringIterator;->beginIndex:I
+Ljava/text/AttributedString$AttributedStringIterator;->currentIndex:I
+Ljava/text/AttributedString$AttributedStringIterator;->currentRunIndex:I
+Ljava/text/AttributedString$AttributedStringIterator;->currentRunLimit:I
+Ljava/text/AttributedString$AttributedStringIterator;->currentRunStart:I
+Ljava/text/AttributedString$AttributedStringIterator;->endIndex:I
+Ljava/text/AttributedString$AttributedStringIterator;->getString()Ljava/text/AttributedString;
+Ljava/text/AttributedString$AttributedStringIterator;->internalSetIndex(I)C
+Ljava/text/AttributedString$AttributedStringIterator;->relevantAttributes:[Ljava/text/AttributedCharacterIterator$Attribute;
+Ljava/text/AttributedString$AttributedStringIterator;->updateRunInfo()V
+Ljava/text/AttributedString$AttributeMap;->beginIndex:I
+Ljava/text/AttributedString$AttributeMap;->endIndex:I
+Ljava/text/AttributedString$AttributeMap;->runIndex:I
+Ljava/text/AttributedString;-><init>([Ljava/text/AttributedCharacterIterator;)V
+Ljava/text/AttributedString;->addAttributeImpl(Ljava/text/AttributedCharacterIterator$Attribute;Ljava/lang/Object;II)V
+Ljava/text/AttributedString;->addAttributeRunData(Ljava/text/AttributedCharacterIterator$Attribute;Ljava/lang/Object;II)V
+Ljava/text/AttributedString;->appendContents(Ljava/lang/StringBuffer;Ljava/text/CharacterIterator;)V
+Ljava/text/AttributedString;->ARRAY_SIZE_INCREMENT:I
+Ljava/text/AttributedString;->attributeValuesMatch(Ljava/util/Set;II)Z
+Ljava/text/AttributedString;->charAt(I)C
+Ljava/text/AttributedString;->createRunAttributeDataVectors()V
+Ljava/text/AttributedString;->ensureRunBreak(I)I
+Ljava/text/AttributedString;->ensureRunBreak(IZ)I
+Ljava/text/AttributedString;->getAttribute(Ljava/text/AttributedCharacterIterator$Attribute;I)Ljava/lang/Object;
+Ljava/text/AttributedString;->getAttributeCheckRange(Ljava/text/AttributedCharacterIterator$Attribute;III)Ljava/lang/Object;
+Ljava/text/AttributedString;->length()I
+Ljava/text/AttributedString;->mapsDiffer(Ljava/util/Map;Ljava/util/Map;)Z
+Ljava/text/AttributedString;->runArraySize:I
+Ljava/text/AttributedString;->runAttributes:[Ljava/util/Vector;
+Ljava/text/AttributedString;->runAttributeValues:[Ljava/util/Vector;
+Ljava/text/AttributedString;->runCount:I
+Ljava/text/AttributedString;->runStarts:[I
+Ljava/text/AttributedString;->setAttributes(Ljava/util/Map;I)V
+Ljava/text/AttributedString;->text:Ljava/lang/String;
+Ljava/text/AttributedString;->valuesMatch(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/text/Bidi;-><init>(Landroid/icu/text/Bidi;)V
+Ljava/text/Bidi;->bidiBase:Landroid/icu/text/Bidi;
+Ljava/text/Bidi;->translateConstToIcu(I)I
+Ljava/text/CalendarBuilder;-><init>()V
+Ljava/text/CalendarBuilder;->addYear(I)Ljava/text/CalendarBuilder;
+Ljava/text/CalendarBuilder;->clear(I)Ljava/text/CalendarBuilder;
+Ljava/text/CalendarBuilder;->COMPUTED:I
+Ljava/text/CalendarBuilder;->establish(Ljava/util/Calendar;)Ljava/util/Calendar;
+Ljava/text/CalendarBuilder;->field:[I
+Ljava/text/CalendarBuilder;->ISO_DAY_OF_WEEK:I
+Ljava/text/CalendarBuilder;->isSet(I)Z
+Ljava/text/CalendarBuilder;->isValidDayOfWeek(I)Z
+Ljava/text/CalendarBuilder;->maxFieldIndex:I
+Ljava/text/CalendarBuilder;->MAX_FIELD:I
+Ljava/text/CalendarBuilder;->MINIMUM_USER_STAMP:I
+Ljava/text/CalendarBuilder;->nextStamp:I
+Ljava/text/CalendarBuilder;->set(II)Ljava/text/CalendarBuilder;
+Ljava/text/CalendarBuilder;->toCalendarDayOfWeek(I)I
+Ljava/text/CalendarBuilder;->toISODayOfWeek(I)I
+Ljava/text/CalendarBuilder;->UNSET:I
+Ljava/text/CalendarBuilder;->WEEK_YEAR:I
+Ljava/text/ChoiceFormat;->choiceFormats:[Ljava/lang/String;
+Ljava/text/ChoiceFormat;->choiceLimits:[D
+Ljava/text/ChoiceFormat;->doubleArraySize([D)[D
+Ljava/text/ChoiceFormat;->doubleArraySize([Ljava/lang/String;)[Ljava/lang/String;
+Ljava/text/ChoiceFormat;->EXPONENT:J
+Ljava/text/ChoiceFormat;->POSITIVEINFINITY:J
+Ljava/text/ChoiceFormat;->SIGN:J
+Ljava/text/CollationElementIterator;-><init>(Landroid/icu/text/CollationElementIterator;)V
+Ljava/text/CollationElementIterator;->icuIterator:Landroid/icu/text/CollationElementIterator;
+Ljava/text/CollationKey;->source:Ljava/lang/String;
+Ljava/text/Collator;-><init>(Landroid/icu/text/Collator;)V
+Ljava/text/Collator;->decompositionMode_ICU_Java(I)I
+Ljava/text/Collator;->decompositionMode_Java_ICU(I)I
+Ljava/text/DateFormat$Field;->calendarField:I
+Ljava/text/DateFormat$Field;->calendarToFieldMapping:[Ljava/text/DateFormat$Field;
+Ljava/text/DateFormat$Field;->instanceMap:Ljava/util/Map;
+Ljava/text/DateFormat;->get(IIILjava/util/Locale;)Ljava/text/DateFormat;
+Ljava/text/DateFormat;->set24HourTimePref(Ljava/lang/Boolean;)V
+Ljava/text/DateFormatSymbols;->ampms:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->cachedHashCode:I
+Ljava/text/DateFormatSymbols;->cachedInstances:Ljava/util/concurrent/ConcurrentMap;
+Ljava/text/DateFormatSymbols;->copyMembers(Ljava/text/DateFormatSymbols;Ljava/text/DateFormatSymbols;)V
+Ljava/text/DateFormatSymbols;->currentSerialVersion:I
+Ljava/text/DateFormatSymbols;->eras:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->getCachedInstance(Ljava/util/Locale;)Ljava/text/DateFormatSymbols;
+Ljava/text/DateFormatSymbols;->getInstanceRef(Ljava/util/Locale;)Ljava/text/DateFormatSymbols;
+Ljava/text/DateFormatSymbols;->getShortStandAloneMonths()[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->getShortStandAloneWeekdays()[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->getStandAloneMonths()[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->getStandAloneWeekdays()[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->getTinyMonths()[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->getTinyStandAloneMonths()[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->getTinyStandAloneWeekdays()[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->getTinyWeekdays()[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->getZoneIndex(Ljava/lang/String;)I
+Ljava/text/DateFormatSymbols;->getZoneStringsImpl(Z)[[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->getZoneStringsWrapper()[[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->initializeData(Ljava/util/Locale;)V
+Ljava/text/DateFormatSymbols;->initializeSupplementaryData(Llibcore/icu/LocaleData;)V
+Ljava/text/DateFormatSymbols;->internalZoneStrings()[[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->isSubclassObject()Z
+Ljava/text/DateFormatSymbols;->isZoneStringsSet:Z
+Ljava/text/DateFormatSymbols;->lastZoneIndex:I
+Ljava/text/DateFormatSymbols;->locale:Ljava/util/Locale;
+Ljava/text/DateFormatSymbols;->localPatternChars:Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->millisPerHour:I
+Ljava/text/DateFormatSymbols;->months:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->patternChars:Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->PATTERN_AM_PM:I
+Ljava/text/DateFormatSymbols;->PATTERN_DAY_OF_MONTH:I
+Ljava/text/DateFormatSymbols;->PATTERN_DAY_OF_WEEK:I
+Ljava/text/DateFormatSymbols;->PATTERN_DAY_OF_WEEK_IN_MONTH:I
+Ljava/text/DateFormatSymbols;->PATTERN_DAY_OF_YEAR:I
+Ljava/text/DateFormatSymbols;->PATTERN_DAY_PERIOD:I
+Ljava/text/DateFormatSymbols;->PATTERN_ERA:I
+Ljava/text/DateFormatSymbols;->PATTERN_FLEXIBLE_DAY_PERIOD:I
+Ljava/text/DateFormatSymbols;->PATTERN_HOUR0:I
+Ljava/text/DateFormatSymbols;->PATTERN_HOUR1:I
+Ljava/text/DateFormatSymbols;->PATTERN_HOUR_OF_DAY0:I
+Ljava/text/DateFormatSymbols;->PATTERN_HOUR_OF_DAY1:I
+Ljava/text/DateFormatSymbols;->PATTERN_ISO_DAY_OF_WEEK:I
+Ljava/text/DateFormatSymbols;->PATTERN_ISO_ZONE:I
+Ljava/text/DateFormatSymbols;->PATTERN_MILLISECOND:I
+Ljava/text/DateFormatSymbols;->PATTERN_MINUTE:I
+Ljava/text/DateFormatSymbols;->PATTERN_MONTH:I
+Ljava/text/DateFormatSymbols;->PATTERN_MONTH_STANDALONE:I
+Ljava/text/DateFormatSymbols;->PATTERN_SECOND:I
+Ljava/text/DateFormatSymbols;->PATTERN_STANDALONE_DAY_OF_WEEK:I
+Ljava/text/DateFormatSymbols;->PATTERN_WEEK_OF_MONTH:I
+Ljava/text/DateFormatSymbols;->PATTERN_WEEK_OF_YEAR:I
+Ljava/text/DateFormatSymbols;->PATTERN_WEEK_YEAR:I
+Ljava/text/DateFormatSymbols;->PATTERN_YEAR:I
+Ljava/text/DateFormatSymbols;->PATTERN_ZONE_NAME:I
+Ljava/text/DateFormatSymbols;->PATTERN_ZONE_VALUE:I
+Ljava/text/DateFormatSymbols;->serialVersionOnStream:I
+Ljava/text/DateFormatSymbols;->shortMonths:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->shortStandAloneMonths:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->shortStandAloneWeekdays:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->shortWeekdays:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->standAloneMonths:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->standAloneWeekdays:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->tinyMonths:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->tinyStandAloneMonths:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->tinyStandAloneWeekdays:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->tinyWeekdays:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->weekdays:[Ljava/lang/String;
+Ljava/text/DateFormatSymbols;->zoneStrings:[[Ljava/lang/String;
+Ljava/text/DecimalFormat;->adjustForCurrencyDefaultFractionDigits()V
+Ljava/text/DecimalFormat;->compareIcuRoundingIncrement(Landroid/icu/text/DecimalFormat_ICU58_Android;)Z
+Ljava/text/DecimalFormat;->convertRoundingMode(Ljava/math/RoundingMode;)I
+Ljava/text/DecimalFormat;->currentSerialVersion:I
+Ljava/text/DecimalFormat;->DOUBLE_FRACTION_DIGITS:I
+Ljava/text/DecimalFormat;->DOUBLE_INTEGER_DIGITS:I
+Ljava/text/DecimalFormat;->format(Ljava/math/BigDecimal;Ljava/lang/StringBuffer;Ljava/text/FieldPosition;)Ljava/lang/StringBuffer;
+Ljava/text/DecimalFormat;->format(Ljava/math/BigInteger;Ljava/lang/StringBuffer;Ljava/text/FieldPosition;)Ljava/lang/StringBuffer;
+Ljava/text/DecimalFormat;->getIcuFieldPosition(Ljava/text/FieldPosition;)Ljava/text/FieldPosition;
+Ljava/text/DecimalFormat;->icuDecimalFormat:Landroid/icu/text/DecimalFormat_ICU58_Android;
+Ljava/text/DecimalFormat;->initPattern(Ljava/lang/String;)V
+Ljava/text/DecimalFormat;->maximumFractionDigits:I
+Ljava/text/DecimalFormat;->maximumIntegerDigits:I
+Ljava/text/DecimalFormat;->MAXIMUM_FRACTION_DIGITS:I
+Ljava/text/DecimalFormat;->MAXIMUM_INTEGER_DIGITS:I
+Ljava/text/DecimalFormat;->minimumFractionDigits:I
+Ljava/text/DecimalFormat;->minimumIntegerDigits:I
+Ljava/text/DecimalFormat;->roundingMode:Ljava/math/RoundingMode;
+Ljava/text/DecimalFormat;->symbols:Ljava/text/DecimalFormatSymbols;
+Ljava/text/DecimalFormat;->toJavaFieldAttribute(Ljava/text/AttributedCharacterIterator$Attribute;)Ljava/text/NumberFormat$Field;
+Ljava/text/DecimalFormat;->updateFieldsFromIcu()V
+Ljava/text/DecimalFormatSymbols;->cachedIcuDFS:Landroid/icu/text/DecimalFormatSymbols;
+Ljava/text/DecimalFormatSymbols;->currency:Ljava/util/Currency;
+Ljava/text/DecimalFormatSymbols;->currencySymbol:Ljava/lang/String;
+Ljava/text/DecimalFormatSymbols;->currentSerialVersion:I
+Ljava/text/DecimalFormatSymbols;->decimalSeparator:C
+Ljava/text/DecimalFormatSymbols;->digit:C
+Ljava/text/DecimalFormatSymbols;->exponential:C
+Ljava/text/DecimalFormatSymbols;->exponentialSeparator:Ljava/lang/String;
+Ljava/text/DecimalFormatSymbols;->fromIcuInstance(Landroid/icu/text/DecimalFormatSymbols;)Ljava/text/DecimalFormatSymbols;
+Ljava/text/DecimalFormatSymbols;->getExponentialSymbol()C
+Ljava/text/DecimalFormatSymbols;->getIcuDecimalFormatSymbols()Landroid/icu/text/DecimalFormatSymbols;
+Ljava/text/DecimalFormatSymbols;->getMinusSignString()Ljava/lang/String;
+Ljava/text/DecimalFormatSymbols;->groupingSeparator:C
+Ljava/text/DecimalFormatSymbols;->infinity:Ljava/lang/String;
+Ljava/text/DecimalFormatSymbols;->initialize(Ljava/util/Locale;)V
+Ljava/text/DecimalFormatSymbols;->intlCurrencySymbol:Ljava/lang/String;
+Ljava/text/DecimalFormatSymbols;->locale:Ljava/util/Locale;
+Ljava/text/DecimalFormatSymbols;->maybeStripMarkers(Ljava/lang/String;C)C
+Ljava/text/DecimalFormatSymbols;->minusSign:C
+Ljava/text/DecimalFormatSymbols;->monetarySeparator:C
+Ljava/text/DecimalFormatSymbols;->NaN:Ljava/lang/String;
+Ljava/text/DecimalFormatSymbols;->patternSeparator:C
+Ljava/text/DecimalFormatSymbols;->percent:C
+Ljava/text/DecimalFormatSymbols;->perMill:C
+Ljava/text/DecimalFormatSymbols;->serialVersionOnStream:I
+Ljava/text/DecimalFormatSymbols;->setExponentialSymbol(C)V
+Ljava/text/DecimalFormatSymbols;->zeroDigit:C
+Ljava/text/FieldPosition$Delegate;->encounteredField:Z
+Ljava/text/FieldPosition$Delegate;->formatted(ILjava/text/Format$Field;Ljava/lang/Object;IILjava/lang/StringBuffer;)V
+Ljava/text/FieldPosition$Delegate;->formatted(Ljava/text/Format$Field;Ljava/lang/Object;IILjava/lang/StringBuffer;)V
+Ljava/text/FieldPosition;->attribute:Ljava/text/Format$Field;
+Ljava/text/FieldPosition;->beginIndex:I
+Ljava/text/FieldPosition;->endIndex:I
+Ljava/text/FieldPosition;->field:I
+Ljava/text/FieldPosition;->getFieldDelegate()Ljava/text/Format$FieldDelegate;
+Ljava/text/FieldPosition;->matchesField(Ljava/text/Format$Field;)Z
+Ljava/text/FieldPosition;->matchesField(Ljava/text/Format$Field;I)Z
+Ljava/text/Format$FieldDelegate;->formatted(ILjava/text/Format$Field;Ljava/lang/Object;IILjava/lang/StringBuffer;)V
+Ljava/text/Format$FieldDelegate;->formatted(Ljava/text/Format$Field;Ljava/lang/Object;IILjava/lang/StringBuffer;)V
+Ljava/text/Format;->createAttributedCharacterIterator(Ljava/lang/String;)Ljava/text/AttributedCharacterIterator;
+Ljava/text/Format;->createAttributedCharacterIterator(Ljava/lang/String;Ljava/text/AttributedCharacterIterator$Attribute;Ljava/lang/Object;)Ljava/text/AttributedCharacterIterator;
+Ljava/text/Format;->createAttributedCharacterIterator(Ljava/text/AttributedCharacterIterator;Ljava/text/AttributedCharacterIterator$Attribute;Ljava/lang/Object;)Ljava/text/AttributedCharacterIterator;
+Ljava/text/Format;->createAttributedCharacterIterator([Ljava/text/AttributedCharacterIterator;)Ljava/text/AttributedCharacterIterator;
+Ljava/text/MessageFormat;->append(Ljava/lang/StringBuffer;Ljava/text/CharacterIterator;)V
+Ljava/text/MessageFormat;->argumentNumbers:[I
+Ljava/text/MessageFormat;->copyAndFixQuotes(Ljava/lang/String;IILjava/lang/StringBuilder;)V
+Ljava/text/MessageFormat;->DATE_TIME_MODIFIERS:[I
+Ljava/text/MessageFormat;->DATE_TIME_MODIFIER_KEYWORDS:[Ljava/lang/String;
+Ljava/text/MessageFormat;->findKeyword(Ljava/lang/String;[Ljava/lang/String;)I
+Ljava/text/MessageFormat;->formats:[Ljava/text/Format;
+Ljava/text/MessageFormat;->INITIAL_FORMATS:I
+Ljava/text/MessageFormat;->locale:Ljava/util/Locale;
+Ljava/text/MessageFormat;->makeFormat(II[Ljava/lang/StringBuilder;)V
+Ljava/text/MessageFormat;->maxOffset:I
+Ljava/text/MessageFormat;->MODIFIER_CURRENCY:I
+Ljava/text/MessageFormat;->MODIFIER_DEFAULT:I
+Ljava/text/MessageFormat;->MODIFIER_FULL:I
+Ljava/text/MessageFormat;->MODIFIER_INTEGER:I
+Ljava/text/MessageFormat;->MODIFIER_LONG:I
+Ljava/text/MessageFormat;->MODIFIER_MEDIUM:I
+Ljava/text/MessageFormat;->MODIFIER_PERCENT:I
+Ljava/text/MessageFormat;->MODIFIER_SHORT:I
+Ljava/text/MessageFormat;->NUMBER_MODIFIER_KEYWORDS:[Ljava/lang/String;
+Ljava/text/MessageFormat;->offsets:[I
+Ljava/text/MessageFormat;->pattern:Ljava/lang/String;
+Ljava/text/MessageFormat;->SEG_INDEX:I
+Ljava/text/MessageFormat;->SEG_MODIFIER:I
+Ljava/text/MessageFormat;->SEG_RAW:I
+Ljava/text/MessageFormat;->SEG_TYPE:I
+Ljava/text/MessageFormat;->subformat([Ljava/lang/Object;Ljava/lang/StringBuffer;Ljava/text/FieldPosition;Ljava/util/List;)Ljava/lang/StringBuffer;
+Ljava/text/MessageFormat;->TYPE_CHOICE:I
+Ljava/text/MessageFormat;->TYPE_DATE:I
+Ljava/text/MessageFormat;->TYPE_KEYWORDS:[Ljava/lang/String;
+Ljava/text/MessageFormat;->TYPE_NULL:I
+Ljava/text/MessageFormat;->TYPE_NUMBER:I
+Ljava/text/MessageFormat;->TYPE_TIME:I
+Ljava/text/Normalizer$Form;->icuMode:Landroid/icu/text/Normalizer$Mode;
+Ljava/text/Normalizer;-><init>()V
+Ljava/text/NumberFormat$Field;->instanceMap:Ljava/util/Map;
+Ljava/text/NumberFormat;->CURRENCYSTYLE:I
+Ljava/text/NumberFormat;->currentSerialVersion:I
+Ljava/text/NumberFormat;->groupingUsed:Z
+Ljava/text/NumberFormat;->INTEGERSTYLE:I
+Ljava/text/NumberFormat;->maxFractionDigits:B
+Ljava/text/NumberFormat;->maximumFractionDigits:I
+Ljava/text/NumberFormat;->maximumIntegerDigits:I
+Ljava/text/NumberFormat;->maxIntegerDigits:B
+Ljava/text/NumberFormat;->minFractionDigits:B
+Ljava/text/NumberFormat;->minimumFractionDigits:I
+Ljava/text/NumberFormat;->minimumIntegerDigits:I
+Ljava/text/NumberFormat;->minIntegerDigits:B
+Ljava/text/NumberFormat;->NUMBERSTYLE:I
+Ljava/text/NumberFormat;->parseIntegerOnly:Z
+Ljava/text/NumberFormat;->PERCENTSTYLE:I
+Ljava/text/NumberFormat;->serialVersionOnStream:I
+Ljava/text/ParseException;->errorOffset:I
+Ljava/text/ParsePosition;->errorIndex:I
+Ljava/text/ParsePosition;->index:I
+Ljava/text/RuleBasedCollator;-><init>(Landroid/icu/text/RuleBasedCollator;)V
+Ljava/text/RuleBasedCollator;->collAsICU()Landroid/icu/text/RuleBasedCollator;
+Ljava/text/SimpleDateFormat;-><init>(IILjava/util/Locale;)V
+Ljava/text/SimpleDateFormat;->cachedNumberFormatData:Ljava/util/concurrent/ConcurrentMap;
+Ljava/text/SimpleDateFormat;->checkNegativeNumberExpression()V
+Ljava/text/SimpleDateFormat;->compile(Ljava/lang/String;)[C
+Ljava/text/SimpleDateFormat;->compiledPattern:[C
+Ljava/text/SimpleDateFormat;->currentSerialVersion:I
+Ljava/text/SimpleDateFormat;->defaultCenturyStart:Ljava/util/Date;
+Ljava/text/SimpleDateFormat;->defaultCenturyStartYear:I
+Ljava/text/SimpleDateFormat;->DST_NAME_TYPES:Ljava/util/Set;
+Ljava/text/SimpleDateFormat;->encode(IILjava/lang/StringBuilder;)V
+Ljava/text/SimpleDateFormat;->format(Ljava/util/Date;Ljava/lang/StringBuffer;Ljava/text/Format$FieldDelegate;)Ljava/lang/StringBuffer;
+Ljava/text/SimpleDateFormat;->formatData:Ljava/text/DateFormatSymbols;
+Ljava/text/SimpleDateFormat;->formatMonth(IIILjava/lang/StringBuffer;ZZ)Ljava/lang/String;
+Ljava/text/SimpleDateFormat;->formatWeekday(IIZZ)Ljava/lang/String;
+Ljava/text/SimpleDateFormat;->getCalendarName()Ljava/lang/String;
+Ljava/text/SimpleDateFormat;->getDateTimeFormat(IILjava/util/Locale;)Ljava/lang/String;
+Ljava/text/SimpleDateFormat;->getTimeZoneNames()Landroid/icu/text/TimeZoneNames;
+Ljava/text/SimpleDateFormat;->GMT:Ljava/lang/String;
+Ljava/text/SimpleDateFormat;->hasFollowingMinusSign:Z
+Ljava/text/SimpleDateFormat;->initialize(Ljava/util/Locale;)V
+Ljava/text/SimpleDateFormat;->initializeCalendar(Ljava/util/Locale;)V
+Ljava/text/SimpleDateFormat;->initializeDefaultCentury()V
+Ljava/text/SimpleDateFormat;->isDigit(C)Z
+Ljava/text/SimpleDateFormat;->isGregorianCalendar()Z
+Ljava/text/SimpleDateFormat;->locale:Ljava/util/Locale;
+Ljava/text/SimpleDateFormat;->matchString(Ljava/lang/String;IILjava/util/Map;Ljava/text/CalendarBuilder;)I
+Ljava/text/SimpleDateFormat;->matchString(Ljava/lang/String;II[Ljava/lang/String;Ljava/text/CalendarBuilder;)I
+Ljava/text/SimpleDateFormat;->matchZoneString(Ljava/lang/String;I[Ljava/lang/String;)I
+Ljava/text/SimpleDateFormat;->MILLIS_PER_MINUTE:I
+Ljava/text/SimpleDateFormat;->minusSign:C
+Ljava/text/SimpleDateFormat;->NAME_TYPES:Ljava/util/EnumSet;
+Ljava/text/SimpleDateFormat;->originalNumberFormat:Ljava/text/NumberFormat;
+Ljava/text/SimpleDateFormat;->originalNumberPattern:Ljava/lang/String;
+Ljava/text/SimpleDateFormat;->parseAmbiguousDatesAsAfter(Ljava/util/Date;)V
+Ljava/text/SimpleDateFormat;->parseInternal(Ljava/lang/String;Ljava/text/ParsePosition;)Ljava/util/Date;
+Ljava/text/SimpleDateFormat;->parseMonth(Ljava/lang/String;IIIILjava/text/ParsePosition;ZZLjava/text/CalendarBuilder;)I
+Ljava/text/SimpleDateFormat;->parseWeekday(Ljava/lang/String;IIZZLjava/text/CalendarBuilder;)I
+Ljava/text/SimpleDateFormat;->pattern:Ljava/lang/String;
+Ljava/text/SimpleDateFormat;->PATTERN_INDEX_TO_CALENDAR_FIELD:[I
+Ljava/text/SimpleDateFormat;->PATTERN_INDEX_TO_DATE_FORMAT_FIELD:[I
+Ljava/text/SimpleDateFormat;->PATTERN_INDEX_TO_DATE_FORMAT_FIELD_ID:[Ljava/text/DateFormat$Field;
+Ljava/text/SimpleDateFormat;->serialVersionOnStream:I
+Ljava/text/SimpleDateFormat;->subFormat(IILjava/text/Format$FieldDelegate;Ljava/lang/StringBuffer;Z)V
+Ljava/text/SimpleDateFormat;->subParse(Ljava/lang/String;IIIZ[ZLjava/text/ParsePosition;ZLjava/text/CalendarBuilder;)I
+Ljava/text/SimpleDateFormat;->subParseNumericZone(Ljava/lang/String;IIIZLjava/text/CalendarBuilder;)I
+Ljava/text/SimpleDateFormat;->subParseZoneString(Ljava/lang/String;ILjava/text/CalendarBuilder;)I
+Ljava/text/SimpleDateFormat;->subParseZoneStringFromICU(Ljava/lang/String;ILjava/text/CalendarBuilder;)I
+Ljava/text/SimpleDateFormat;->subParseZoneStringFromSymbols(Ljava/lang/String;ILjava/text/CalendarBuilder;)I
+Ljava/text/SimpleDateFormat;->TAG_QUOTE_ASCII_CHAR:I
+Ljava/text/SimpleDateFormat;->TAG_QUOTE_CHARS:I
+Ljava/text/SimpleDateFormat;->timeZoneNames:Landroid/icu/text/TimeZoneNames;
+Ljava/text/SimpleDateFormat;->translatePattern(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Ljava/text/SimpleDateFormat;->useDateFormatSymbols()Z
+Ljava/text/SimpleDateFormat;->useDateFormatSymbols:Z
+Ljava/text/SimpleDateFormat;->zeroDigit:C
+Ljava/text/SimpleDateFormat;->zeroPaddingNumber(IIILjava/lang/StringBuffer;)V
+Ljava/text/StringCharacterIterator;->begin:I
+Ljava/text/StringCharacterIterator;->end:I
+Ljava/text/StringCharacterIterator;->pos:I
+Ljava/text/StringCharacterIterator;->text:Ljava/lang/String;
+Ljava/time/chrono/AbstractChronology;->addFieldValue(Ljava/util/Map;Ljava/time/temporal/ChronoField;J)V
+Ljava/time/chrono/AbstractChronology;->CHRONOS_BY_ID:Ljava/util/concurrent/ConcurrentHashMap;
+Ljava/time/chrono/AbstractChronology;->CHRONOS_BY_TYPE:Ljava/util/concurrent/ConcurrentHashMap;
+Ljava/time/chrono/AbstractChronology;->DATE_ORDER:Ljava/util/Comparator;
+Ljava/time/chrono/AbstractChronology;->DATE_TIME_ORDER:Ljava/util/Comparator;
+Ljava/time/chrono/AbstractChronology;->getAvailableChronologies()Ljava/util/Set;
+Ljava/time/chrono/AbstractChronology;->initCache()Z
+Ljava/time/chrono/AbstractChronology;->INSTANT_ORDER:Ljava/util/Comparator;
+Ljava/time/chrono/AbstractChronology;->of(Ljava/lang/String;)Ljava/time/chrono/Chronology;
+Ljava/time/chrono/AbstractChronology;->of0(Ljava/lang/String;)Ljava/time/chrono/Chronology;
+Ljava/time/chrono/AbstractChronology;->ofLocale(Ljava/util/Locale;)Ljava/time/chrono/Chronology;
+Ljava/time/chrono/AbstractChronology;->readExternal(Ljava/io/DataInput;)Ljava/time/chrono/Chronology;
+Ljava/time/chrono/AbstractChronology;->registerChrono(Ljava/time/chrono/Chronology;)Ljava/time/chrono/Chronology;
+Ljava/time/chrono/AbstractChronology;->registerChrono(Ljava/time/chrono/Chronology;Ljava/lang/String;)Ljava/time/chrono/Chronology;
+Ljava/time/chrono/AbstractChronology;->resolveAligned(Ljava/time/chrono/ChronoLocalDate;JJJ)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/AbstractChronology;->resolveProlepticMonth(Ljava/util/Map;Ljava/time/format/ResolverStyle;)V
+Ljava/time/chrono/AbstractChronology;->resolveYAA(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/AbstractChronology;->resolveYAD(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/AbstractChronology;->resolveYD(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/AbstractChronology;->resolveYearOfEra(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/AbstractChronology;->resolveYMAA(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/AbstractChronology;->resolveYMAD(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/AbstractChronology;->resolveYMD(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/AbstractChronology;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/chrono/ChronoLocalDateImpl;-><init>()V
+Ljava/time/chrono/ChronoLocalDateImpl;->daysUntil(Ljava/time/chrono/ChronoLocalDate;)J
+Ljava/time/chrono/ChronoLocalDateImpl;->ensureValid(Ljava/time/chrono/Chronology;Ljava/time/temporal/Temporal;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/ChronoLocalDateImpl;->minusDays(J)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/ChronoLocalDateImpl;->minusMonths(J)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/ChronoLocalDateImpl;->minusWeeks(J)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/ChronoLocalDateImpl;->minusYears(J)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/ChronoLocalDateImpl;->monthsUntil(Ljava/time/chrono/ChronoLocalDate;)J
+Ljava/time/chrono/ChronoLocalDateImpl;->plusDays(J)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/ChronoLocalDateImpl;->plusMonths(J)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/ChronoLocalDateImpl;->plusWeeks(J)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/ChronoLocalDateImpl;->plusYears(J)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/HijrahChronology;-><init>(Ljava/lang/String;)V
+Ljava/time/chrono/HijrahChronology;->calendarProperties:Ljava/util/Properties;
+Ljava/time/chrono/HijrahChronology;->calendarType:Ljava/lang/String;
+Ljava/time/chrono/HijrahChronology;->checkCalendarInit()V
+Ljava/time/chrono/HijrahChronology;->checkValidDayOfYear(I)V
+Ljava/time/chrono/HijrahChronology;->checkValidMonth(I)V
+Ljava/time/chrono/HijrahChronology;->checkValidYear(J)I
+Ljava/time/chrono/HijrahChronology;->createEpochMonths(IIILjava/util/Map;)[I
+Ljava/time/chrono/HijrahChronology;->epochDayToEpochMonth(I)I
+Ljava/time/chrono/HijrahChronology;->epochMonthLength(I)I
+Ljava/time/chrono/HijrahChronology;->epochMonthToEpochDay(I)I
+Ljava/time/chrono/HijrahChronology;->epochMonthToMonth(I)I
+Ljava/time/chrono/HijrahChronology;->epochMonthToYear(I)I
+Ljava/time/chrono/HijrahChronology;->getDayOfYear(II)I
+Ljava/time/chrono/HijrahChronology;->getEpochDay(III)J
+Ljava/time/chrono/HijrahChronology;->getHijrahDateInfo(I)[I
+Ljava/time/chrono/HijrahChronology;->getMaximumDayOfYear()I
+Ljava/time/chrono/HijrahChronology;->getMaximumMonthLength()I
+Ljava/time/chrono/HijrahChronology;->getMaximumYear()I
+Ljava/time/chrono/HijrahChronology;->getMinimumMonthLength()I
+Ljava/time/chrono/HijrahChronology;->getMinimumYear()I
+Ljava/time/chrono/HijrahChronology;->getMonthLength(II)I
+Ljava/time/chrono/HijrahChronology;->getSmallestMaximumDayOfYear()I
+Ljava/time/chrono/HijrahChronology;->getYearLength(I)I
+Ljava/time/chrono/HijrahChronology;->hijrahEpochMonthStartDays:[I
+Ljava/time/chrono/HijrahChronology;->hijrahStartEpochMonth:I
+Ljava/time/chrono/HijrahChronology;->initComplete:Z
+Ljava/time/chrono/HijrahChronology;->KEY_ID:Ljava/lang/String;
+Ljava/time/chrono/HijrahChronology;->KEY_ISO_START:Ljava/lang/String;
+Ljava/time/chrono/HijrahChronology;->KEY_TYPE:Ljava/lang/String;
+Ljava/time/chrono/HijrahChronology;->KEY_VERSION:Ljava/lang/String;
+Ljava/time/chrono/HijrahChronology;->loadCalendarData()V
+Ljava/time/chrono/HijrahChronology;->maxEpochDay:I
+Ljava/time/chrono/HijrahChronology;->maxMonthLength:I
+Ljava/time/chrono/HijrahChronology;->maxYearLength:I
+Ljava/time/chrono/HijrahChronology;->minEpochDay:I
+Ljava/time/chrono/HijrahChronology;->minMonthLength:I
+Ljava/time/chrono/HijrahChronology;->minYearLength:I
+Ljava/time/chrono/HijrahChronology;->parseMonths(Ljava/lang/String;)[I
+Ljava/time/chrono/HijrahChronology;->parseYMD(Ljava/lang/String;)[I
+Ljava/time/chrono/HijrahChronology;->PROP_PREFIX:Ljava/lang/String;
+Ljava/time/chrono/HijrahChronology;->PROP_TYPE_SUFFIX:Ljava/lang/String;
+Ljava/time/chrono/HijrahChronology;->readConfigProperties(Ljava/lang/String;)Ljava/util/Properties;
+Ljava/time/chrono/HijrahChronology;->registerVariants()V
+Ljava/time/chrono/HijrahChronology;->typeId:Ljava/lang/String;
+Ljava/time/chrono/HijrahChronology;->yearMonthToDayOfYear(II)I
+Ljava/time/chrono/HijrahChronology;->yearToEpochMonth(I)I
+Ljava/time/chrono/HijrahDate;-><init>(Ljava/time/chrono/HijrahChronology;III)V
+Ljava/time/chrono/HijrahDate;-><init>(Ljava/time/chrono/HijrahChronology;J)V
+Ljava/time/chrono/HijrahDate;->chrono:Ljava/time/chrono/HijrahChronology;
+Ljava/time/chrono/HijrahDate;->dayOfMonth:I
+Ljava/time/chrono/HijrahDate;->getDayOfWeek()I
+Ljava/time/chrono/HijrahDate;->getDayOfYear()I
+Ljava/time/chrono/HijrahDate;->getEraValue()I
+Ljava/time/chrono/HijrahDate;->getProlepticMonth()J
+Ljava/time/chrono/HijrahDate;->minusDays(J)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->minusMonths(J)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->minusWeeks(J)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->minusYears(J)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->monthOfYear:I
+Ljava/time/chrono/HijrahDate;->of(Ljava/time/chrono/HijrahChronology;III)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->ofEpochDay(Ljava/time/chrono/HijrahChronology;J)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->plusDays(J)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->plusMonths(J)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->plusWeeks(J)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->plusYears(J)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->prolepticYear:I
+Ljava/time/chrono/HijrahDate;->readExternal(Ljava/io/ObjectInput;)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->resolvePreviousValid(III)Ljava/time/chrono/HijrahDate;
+Ljava/time/chrono/HijrahDate;->writeExternal(Ljava/io/ObjectOutput;)V
+Ljava/time/chrono/IsoChronology;-><init>()V
+Ljava/time/chrono/IsoChronology;->resolveProlepticMonth(Ljava/util/Map;Ljava/time/format/ResolverStyle;)V
+Ljava/time/chrono/IsoChronology;->resolveYearOfEra(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/LocalDate;
+Ljava/time/chrono/IsoChronology;->resolveYMD(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/LocalDate;
+Ljava/time/chrono/JapaneseChronology;-><init>()V
+Ljava/time/chrono/JapaneseChronology;->createCalendar()Ljava/util/Calendar;
+Ljava/time/chrono/JapaneseChronology;->getCurrentEra()Ljava/time/chrono/JapaneseEra;
+Ljava/time/chrono/JapaneseChronology;->JCAL:Lsun/util/calendar/LocalGregorianCalendar;
+Ljava/time/chrono/JapaneseChronology;->LOCALE:Ljava/util/Locale;
+Ljava/time/chrono/JapaneseChronology;->prolepticYearLenient(Ljava/time/chrono/JapaneseEra;I)I
+Ljava/time/chrono/JapaneseChronology;->resolveYD(Ljava/time/chrono/JapaneseEra;ILjava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/JapaneseChronology;->resolveYearOfEra(Ljava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/JapaneseChronology;->resolveYMD(Ljava/time/chrono/JapaneseEra;ILjava/util/Map;Ljava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/chrono/JapaneseDate;-><init>(Ljava/time/chrono/JapaneseEra;ILjava/time/LocalDate;)V
+Ljava/time/chrono/JapaneseDate;-><init>(Ljava/time/LocalDate;)V
+Ljava/time/chrono/JapaneseDate;->era:Ljava/time/chrono/JapaneseEra;
+Ljava/time/chrono/JapaneseDate;->isoDate:Ljava/time/LocalDate;
+Ljava/time/chrono/JapaneseDate;->MEIJI_6_ISODATE:Ljava/time/LocalDate;
+Ljava/time/chrono/JapaneseDate;->minusDays(J)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->minusMonths(J)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->minusWeeks(J)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->minusYears(J)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->ofYearDay(Ljava/time/chrono/JapaneseEra;II)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->plusDays(J)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->plusMonths(J)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->plusWeeks(J)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->plusYears(J)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->readExternal(Ljava/io/DataInput;)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->toPrivateJapaneseDate(Ljava/time/LocalDate;)Lsun/util/calendar/LocalGregorianCalendar$Date;
+Ljava/time/chrono/JapaneseDate;->with(Ljava/time/LocalDate;)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->withYear(I)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->withYear(Ljava/time/chrono/JapaneseEra;I)Ljava/time/chrono/JapaneseDate;
+Ljava/time/chrono/JapaneseDate;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/chrono/JapaneseDate;->yearOfEra:I
+Ljava/time/chrono/JapaneseEra;-><init>(ILjava/time/LocalDate;)V
+Ljava/time/chrono/JapaneseEra;->eraValue:I
+Ljava/time/chrono/JapaneseEra;->ERA_CONFIG:[Lsun/util/calendar/Era;
+Ljava/time/chrono/JapaneseEra;->ERA_OFFSET:I
+Ljava/time/chrono/JapaneseEra;->from(Ljava/time/LocalDate;)Ljava/time/chrono/JapaneseEra;
+Ljava/time/chrono/JapaneseEra;->getAbbreviation()Ljava/lang/String;
+Ljava/time/chrono/JapaneseEra;->getName()Ljava/lang/String;
+Ljava/time/chrono/JapaneseEra;->getPrivateEra()Lsun/util/calendar/Era;
+Ljava/time/chrono/JapaneseEra;->KNOWN_ERAS:[Ljava/time/chrono/JapaneseEra;
+Ljava/time/chrono/JapaneseEra;->N_ERA_CONSTANTS:I
+Ljava/time/chrono/JapaneseEra;->ordinal(I)I
+Ljava/time/chrono/JapaneseEra;->privateEraFrom(Ljava/time/LocalDate;)Lsun/util/calendar/Era;
+Ljava/time/chrono/JapaneseEra;->readExternal(Ljava/io/DataInput;)Ljava/time/chrono/JapaneseEra;
+Ljava/time/chrono/JapaneseEra;->since:Ljava/time/LocalDate;
+Ljava/time/chrono/JapaneseEra;->toJapaneseEra(Lsun/util/calendar/Era;)Ljava/time/chrono/JapaneseEra;
+Ljava/time/chrono/JapaneseEra;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/chrono/MinguoChronology;-><init>()V
+Ljava/time/chrono/MinguoChronology;->YEARS_DIFFERENCE:I
+Ljava/time/chrono/MinguoDate;-><init>(Ljava/time/LocalDate;)V
+Ljava/time/chrono/MinguoDate;->getProlepticMonth()J
+Ljava/time/chrono/MinguoDate;->getProlepticYear()I
+Ljava/time/chrono/MinguoDate;->isoDate:Ljava/time/LocalDate;
+Ljava/time/chrono/MinguoDate;->minusDays(J)Ljava/time/chrono/MinguoDate;
+Ljava/time/chrono/MinguoDate;->minusMonths(J)Ljava/time/chrono/MinguoDate;
+Ljava/time/chrono/MinguoDate;->minusWeeks(J)Ljava/time/chrono/MinguoDate;
+Ljava/time/chrono/MinguoDate;->minusYears(J)Ljava/time/chrono/MinguoDate;
+Ljava/time/chrono/MinguoDate;->plusDays(J)Ljava/time/chrono/MinguoDate;
+Ljava/time/chrono/MinguoDate;->plusMonths(J)Ljava/time/chrono/MinguoDate;
+Ljava/time/chrono/MinguoDate;->plusWeeks(J)Ljava/time/chrono/MinguoDate;
+Ljava/time/chrono/MinguoDate;->plusYears(J)Ljava/time/chrono/MinguoDate;
+Ljava/time/chrono/MinguoDate;->readExternal(Ljava/io/DataInput;)Ljava/time/chrono/MinguoDate;
+Ljava/time/chrono/MinguoDate;->with(Ljava/time/LocalDate;)Ljava/time/chrono/MinguoDate;
+Ljava/time/chrono/MinguoDate;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/chrono/ThaiBuddhistChronology;-><init>()V
+Ljava/time/chrono/ThaiBuddhistChronology;->ERA_FULL_NAMES:Ljava/util/HashMap;
+Ljava/time/chrono/ThaiBuddhistChronology;->ERA_NARROW_NAMES:Ljava/util/HashMap;
+Ljava/time/chrono/ThaiBuddhistChronology;->ERA_SHORT_NAMES:Ljava/util/HashMap;
+Ljava/time/chrono/ThaiBuddhistChronology;->FALLBACK_LANGUAGE:Ljava/lang/String;
+Ljava/time/chrono/ThaiBuddhistChronology;->TARGET_LANGUAGE:Ljava/lang/String;
+Ljava/time/chrono/ThaiBuddhistChronology;->YEARS_DIFFERENCE:I
+Ljava/time/chrono/ThaiBuddhistDate;-><init>(Ljava/time/LocalDate;)V
+Ljava/time/chrono/ThaiBuddhistDate;->getProlepticMonth()J
+Ljava/time/chrono/ThaiBuddhistDate;->getProlepticYear()I
+Ljava/time/chrono/ThaiBuddhistDate;->isoDate:Ljava/time/LocalDate;
+Ljava/time/chrono/ThaiBuddhistDate;->minusDays(J)Ljava/time/chrono/ThaiBuddhistDate;
+Ljava/time/chrono/ThaiBuddhistDate;->minusMonths(J)Ljava/time/chrono/ThaiBuddhistDate;
+Ljava/time/chrono/ThaiBuddhistDate;->minusWeeks(J)Ljava/time/chrono/ThaiBuddhistDate;
+Ljava/time/chrono/ThaiBuddhistDate;->minusYears(J)Ljava/time/chrono/ThaiBuddhistDate;
+Ljava/time/chrono/ThaiBuddhistDate;->plusDays(J)Ljava/time/chrono/ThaiBuddhistDate;
+Ljava/time/chrono/ThaiBuddhistDate;->plusMonths(J)Ljava/time/chrono/ThaiBuddhistDate;
+Ljava/time/chrono/ThaiBuddhistDate;->plusWeeks(J)Ljava/time/chrono/ThaiBuddhistDate;
+Ljava/time/chrono/ThaiBuddhistDate;->plusYears(J)Ljava/time/chrono/ThaiBuddhistDate;
+Ljava/time/chrono/ThaiBuddhistDate;->readExternal(Ljava/io/DataInput;)Ljava/time/chrono/ThaiBuddhistDate;
+Ljava/time/chrono/ThaiBuddhistDate;->with(Ljava/time/LocalDate;)Ljava/time/chrono/ThaiBuddhistDate;
+Ljava/time/chrono/ThaiBuddhistDate;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/Clock$FixedClock;-><init>(Ljava/time/Instant;Ljava/time/ZoneId;)V
+Ljava/time/Clock$FixedClock;->instant:Ljava/time/Instant;
+Ljava/time/Clock$FixedClock;->zone:Ljava/time/ZoneId;
+Ljava/time/Clock$OffsetClock;-><init>(Ljava/time/Clock;Ljava/time/Duration;)V
+Ljava/time/Clock$OffsetClock;->baseClock:Ljava/time/Clock;
+Ljava/time/Clock$OffsetClock;->offset:Ljava/time/Duration;
+Ljava/time/Clock$SystemClock;-><init>(Ljava/time/ZoneId;)V
+Ljava/time/Clock$SystemClock;->zone:Ljava/time/ZoneId;
+Ljava/time/Clock$TickClock;-><init>(Ljava/time/Clock;J)V
+Ljava/time/Clock$TickClock;->baseClock:Ljava/time/Clock;
+Ljava/time/Clock$TickClock;->tickNanos:J
+Ljava/time/DayOfWeek;->ENUMS:[Ljava/time/DayOfWeek;
+Ljava/time/Duration$DurationUnits;-><init>()V
+Ljava/time/Duration$DurationUnits;->UNITS:Ljava/util/List;
+Ljava/time/Duration;-><init>(JI)V
+Ljava/time/Duration;->BI_NANOS_PER_SECOND:Ljava/math/BigInteger;
+Ljava/time/Duration;->create(JI)Ljava/time/Duration;
+Ljava/time/Duration;->create(Ljava/math/BigDecimal;)Ljava/time/Duration;
+Ljava/time/Duration;->create(ZJJJJI)Ljava/time/Duration;
+Ljava/time/Duration;->nanos:I
+Ljava/time/Duration;->parseFraction(Ljava/lang/CharSequence;Ljava/lang/String;I)I
+Ljava/time/Duration;->parseNumber(Ljava/lang/CharSequence;Ljava/lang/String;ILjava/lang/String;)J
+Ljava/time/Duration;->PATTERN:Ljava/util/regex/Pattern;
+Ljava/time/Duration;->plus(JJ)Ljava/time/Duration;
+Ljava/time/Duration;->readExternal(Ljava/io/DataInput;)Ljava/time/Duration;
+Ljava/time/Duration;->seconds:J
+Ljava/time/Duration;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/format/DateTimeFormatter$ClassicFormat;-><init>(Ljava/time/format/DateTimeFormatter;Ljava/time/temporal/TemporalQuery;)V
+Ljava/time/format/DateTimeFormatter$ClassicFormat;->formatter:Ljava/time/format/DateTimeFormatter;
+Ljava/time/format/DateTimeFormatter$ClassicFormat;->parseType:Ljava/time/temporal/TemporalQuery;
+Ljava/time/format/DateTimeFormatter;-><init>(Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;Ljava/util/Locale;Ljava/time/format/DecimalStyle;Ljava/time/format/ResolverStyle;Ljava/util/Set;Ljava/time/chrono/Chronology;Ljava/time/ZoneId;)V
+Ljava/time/format/DateTimeFormatter;->chrono:Ljava/time/chrono/Chronology;
+Ljava/time/format/DateTimeFormatter;->createError(Ljava/lang/CharSequence;Ljava/lang/RuntimeException;)Ljava/time/format/DateTimeParseException;
+Ljava/time/format/DateTimeFormatter;->decimalStyle:Ljava/time/format/DecimalStyle;
+Ljava/time/format/DateTimeFormatter;->locale:Ljava/util/Locale;
+Ljava/time/format/DateTimeFormatter;->PARSED_EXCESS_DAYS:Ljava/time/temporal/TemporalQuery;
+Ljava/time/format/DateTimeFormatter;->PARSED_LEAP_SECOND:Ljava/time/temporal/TemporalQuery;
+Ljava/time/format/DateTimeFormatter;->parseResolved0(Ljava/lang/CharSequence;Ljava/text/ParsePosition;)Ljava/time/temporal/TemporalAccessor;
+Ljava/time/format/DateTimeFormatter;->parseUnresolved0(Ljava/lang/CharSequence;Ljava/text/ParsePosition;)Ljava/time/format/DateTimeParseContext;
+Ljava/time/format/DateTimeFormatter;->printerParser:Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;
+Ljava/time/format/DateTimeFormatter;->resolverFields:Ljava/util/Set;
+Ljava/time/format/DateTimeFormatter;->resolverStyle:Ljava/time/format/ResolverStyle;
+Ljava/time/format/DateTimeFormatter;->toPrinterParser(Z)Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;
+Ljava/time/format/DateTimeFormatter;->zone:Ljava/time/ZoneId;
+Ljava/time/format/DateTimeFormatterBuilder$CharLiteralPrinterParser;-><init>(C)V
+Ljava/time/format/DateTimeFormatterBuilder$CharLiteralPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$CharLiteralPrinterParser;->literal:C
+Ljava/time/format/DateTimeFormatterBuilder$CharLiteralPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$ChronoPrinterParser;-><init>(Ljava/time/format/TextStyle;)V
+Ljava/time/format/DateTimeFormatterBuilder$ChronoPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$ChronoPrinterParser;->getChronologyName(Ljava/time/chrono/Chronology;Ljava/util/Locale;)Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$ChronoPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$ChronoPrinterParser;->textStyle:Ljava/time/format/TextStyle;
+Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;-><init>(Ljava/util/List;Z)V
+Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;-><init>([Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;Z)V
+Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;->optional:Z
+Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;->printerParsers:[Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;->withOptional(Z)Ljava/time/format/DateTimeFormatterBuilder$CompositePrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$DefaultValueParser;-><init>(Ljava/time/temporal/TemporalField;J)V
+Ljava/time/format/DateTimeFormatterBuilder$DefaultValueParser;->field:Ljava/time/temporal/TemporalField;
+Ljava/time/format/DateTimeFormatterBuilder$DefaultValueParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$DefaultValueParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$DefaultValueParser;->value:J
+Ljava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;-><init>(Ljava/time/temporal/TemporalField;IIZ)V
+Ljava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->convertFromFraction(Ljava/math/BigDecimal;)J
+Ljava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->convertToFraction(J)Ljava/math/BigDecimal;
+Ljava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->decimalPoint:Z
+Ljava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->field:Ljava/time/temporal/TemporalField;
+Ljava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->maxWidth:I
+Ljava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->minWidth:I
+Ljava/time/format/DateTimeFormatterBuilder$FractionPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$InstantPrinterParser;-><init>(I)V
+Ljava/time/format/DateTimeFormatterBuilder$InstantPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$InstantPrinterParser;->fractionalDigits:I
+Ljava/time/format/DateTimeFormatterBuilder$InstantPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$InstantPrinterParser;->SECONDS_0000_TO_1970:J
+Ljava/time/format/DateTimeFormatterBuilder$InstantPrinterParser;->SECONDS_PER_10000_YEARS:J
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedOffsetIdPrinterParser;-><init>(Ljava/time/format/TextStyle;)V
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedOffsetIdPrinterParser;->appendHMS(Ljava/lang/StringBuilder;I)Ljava/lang/StringBuilder;
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedOffsetIdPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedOffsetIdPrinterParser;->getDigit(Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedOffsetIdPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedOffsetIdPrinterParser;->style:Ljava/time/format/TextStyle;
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedPrinterParser;-><init>(Ljava/time/format/FormatStyle;Ljava/time/format/FormatStyle;)V
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedPrinterParser;->dateStyle:Ljava/time/format/FormatStyle;
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedPrinterParser;->formatter(Ljava/util/Locale;Ljava/time/chrono/Chronology;)Ljava/time/format/DateTimeFormatter;
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedPrinterParser;->FORMATTER_CACHE:Ljava/util/concurrent/ConcurrentMap;
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$LocalizedPrinterParser;->timeStyle:Ljava/time/format/FormatStyle;
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;-><init>(Ljava/time/temporal/TemporalField;IILjava/time/format/SignStyle;)V
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;-><init>(Ljava/time/temporal/TemporalField;IILjava/time/format/SignStyle;I)V
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->EXCEED_POINTS:[J
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->field:Ljava/time/temporal/TemporalField;
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->getValue(Ljava/time/format/DateTimePrintContext;J)J
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->isFixedWidth(Ljava/time/format/DateTimeParseContext;)Z
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->maxWidth:I
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->minWidth:I
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->setValue(Ljava/time/format/DateTimeParseContext;JII)I
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->signStyle:Ljava/time/format/SignStyle;
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->subsequentWidth:I
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->withFixedWidth()Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;->withSubsequentWidth(I)Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->checkPattern(Ljava/lang/String;)I
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->INSTANCE_ID_Z:Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->INSTANCE_ID_ZERO:Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->noOffsetText:Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->parseNumber([IILjava/lang/CharSequence;Z)Z
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->PATTERNS:[Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;->type:I
+Ljava/time/format/DateTimeFormatterBuilder$PadPrinterParserDecorator;-><init>(Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;IC)V
+Ljava/time/format/DateTimeFormatterBuilder$PadPrinterParserDecorator;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$PadPrinterParserDecorator;->padChar:C
+Ljava/time/format/DateTimeFormatterBuilder$PadPrinterParserDecorator;->padWidth:I
+Ljava/time/format/DateTimeFormatterBuilder$PadPrinterParserDecorator;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$PadPrinterParserDecorator;->printerParser:Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$CI;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;)V
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$CI;->isEqual(CC)Z
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$CI;->newNode(Ljava/lang/String;Ljava/lang/String;Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;)Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$CI;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$CI;->prefixOf(Ljava/lang/CharSequence;II)Z
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$LENIENT;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;)V
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$LENIENT;->isLenientChar(C)Z
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$LENIENT;->match(Ljava/lang/CharSequence;Ljava/text/ParsePosition;)Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$LENIENT;->newNode(Ljava/lang/String;Ljava/lang/String;Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;)Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$CI;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree$LENIENT;->toKey(Ljava/lang/String;)Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;)V
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->add(Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->add0(Ljava/lang/String;Ljava/lang/String;)Z
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->c0:C
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->child:Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->copyTree()Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->isEqual(CC)Z
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->key:Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->match(Ljava/lang/CharSequence;II)Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->match(Ljava/lang/CharSequence;Ljava/text/ParsePosition;)Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->newNode(Ljava/lang/String;Ljava/lang/String;Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;)Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->newTree(Ljava/time/format/DateTimeParseContext;)Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->newTree(Ljava/util/Set;Ljava/time/format/DateTimeParseContext;)Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->prefixLength(Ljava/lang/String;)I
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->prefixOf(Ljava/lang/CharSequence;II)Z
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->sibling:Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->toKey(Ljava/lang/String;)Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;->value:Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;-><init>(Ljava/time/temporal/TemporalField;IIILjava/time/chrono/ChronoLocalDate;)V
+Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;-><init>(Ljava/time/temporal/TemporalField;IIILjava/time/chrono/ChronoLocalDate;I)V
+Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;->baseDate:Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;->baseValue:I
+Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;->BASE_DATE:Ljava/time/LocalDate;
+Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;->getValue(Ljava/time/format/DateTimePrintContext;J)J
+Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;->isFixedWidth(Ljava/time/format/DateTimeParseContext;)Z
+Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;->setValue(Ljava/time/format/DateTimeParseContext;JII)I
+Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;->withFixedWidth()Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;->withSubsequentWidth(I)Ljava/time/format/DateTimeFormatterBuilder$ReducedPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;->INSENSITIVE:Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;
+Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;->LENIENT:Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;
+Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;->SENSITIVE:Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;
+Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;->STRICT:Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;
+Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;->valueOf(Ljava/lang/String;)Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;
+Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;->values()[Ljava/time/format/DateTimeFormatterBuilder$SettingsParser;
+Ljava/time/format/DateTimeFormatterBuilder$StringLiteralPrinterParser;-><init>(Ljava/lang/String;)V
+Ljava/time/format/DateTimeFormatterBuilder$StringLiteralPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$StringLiteralPrinterParser;->literal:Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$StringLiteralPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$TextPrinterParser;-><init>(Ljava/time/temporal/TemporalField;Ljava/time/format/TextStyle;Ljava/time/format/DateTimeTextProvider;)V
+Ljava/time/format/DateTimeFormatterBuilder$TextPrinterParser;->field:Ljava/time/temporal/TemporalField;
+Ljava/time/format/DateTimeFormatterBuilder$TextPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$TextPrinterParser;->numberPrinterParser()Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$TextPrinterParser;->numberPrinterParser:Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$TextPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$TextPrinterParser;->provider:Ljava/time/format/DateTimeTextProvider;
+Ljava/time/format/DateTimeFormatterBuilder$TextPrinterParser;->textStyle:Ljava/time/format/TextStyle;
+Ljava/time/format/DateTimeFormatterBuilder$WeekBasedFieldPrinterParser;-><init>(CI)V
+Ljava/time/format/DateTimeFormatterBuilder$WeekBasedFieldPrinterParser;->chr:C
+Ljava/time/format/DateTimeFormatterBuilder$WeekBasedFieldPrinterParser;->count:I
+Ljava/time/format/DateTimeFormatterBuilder$WeekBasedFieldPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$WeekBasedFieldPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$WeekBasedFieldPrinterParser;->printerParser(Ljava/util/Locale;)Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;-><init>(Ljava/time/temporal/TemporalQuery;Ljava/lang/String;)V
+Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->cachedPrefixTree:Ljava/util/Map$Entry;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->cachedPrefixTreeCI:Ljava/util/Map$Entry;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->description:Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->getTree(Ljava/time/format/DateTimeParseContext;)Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->parse(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;I)I
+Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->parseOffsetBased(Ljava/time/format/DateTimeParseContext;Ljava/lang/CharSequence;IILjava/time/format/DateTimeFormatterBuilder$OffsetIdPrinterParser;)I
+Ljava/time/format/DateTimeFormatterBuilder$ZoneIdPrinterParser;->query:Ljava/time/temporal/TemporalQuery;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;-><init>(Ljava/time/format/TextStyle;Ljava/util/Set;)V
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->cache:Ljava/util/Map;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->cachedTree:Ljava/util/Map;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->cachedTreeCI:Ljava/util/Map;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->DST:I
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->format(Ljava/time/format/DateTimePrintContext;Ljava/lang/StringBuilder;)Z
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->FULL_TYPES:[Landroid/icu/text/TimeZoneNames$NameType;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->GENERIC:I
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->getDisplayName(Ljava/lang/String;ILjava/util/Locale;)Ljava/lang/String;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->getTree(Ljava/time/format/DateTimeParseContext;)Ljava/time/format/DateTimeFormatterBuilder$PrefixTree;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->preferredZones:Ljava/util/Set;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->SHORT_TYPES:[Landroid/icu/text/TimeZoneNames$NameType;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->STD:I
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->textStyle:Ljava/time/format/TextStyle;
+Ljava/time/format/DateTimeFormatterBuilder$ZoneTextPrinterParser;->TYPES:[Landroid/icu/text/TimeZoneNames$NameType;
+Ljava/time/format/DateTimeFormatterBuilder;-><init>(Ljava/time/format/DateTimeFormatterBuilder;Z)V
+Ljava/time/format/DateTimeFormatterBuilder;->active:Ljava/time/format/DateTimeFormatterBuilder;
+Ljava/time/format/DateTimeFormatterBuilder;->appendInternal(Ljava/time/format/DateTimeFormatterBuilder$DateTimePrinterParser;)I
+Ljava/time/format/DateTimeFormatterBuilder;->appendValue(Ljava/time/format/DateTimeFormatterBuilder$NumberPrinterParser;)Ljava/time/format/DateTimeFormatterBuilder;
+Ljava/time/format/DateTimeFormatterBuilder;->convertStyle(Ljava/time/format/FormatStyle;)I
+Ljava/time/format/DateTimeFormatterBuilder;->FIELD_MAP:Ljava/util/Map;
+Ljava/time/format/DateTimeFormatterBuilder;->LENGTH_SORT:Ljava/util/Comparator;
+Ljava/time/format/DateTimeFormatterBuilder;->optional:Z
+Ljava/time/format/DateTimeFormatterBuilder;->padNextChar:C
+Ljava/time/format/DateTimeFormatterBuilder;->padNextWidth:I
+Ljava/time/format/DateTimeFormatterBuilder;->parent:Ljava/time/format/DateTimeFormatterBuilder;
+Ljava/time/format/DateTimeFormatterBuilder;->parseField(CILjava/time/temporal/TemporalField;)V
+Ljava/time/format/DateTimeFormatterBuilder;->parsePattern(Ljava/lang/String;)V
+Ljava/time/format/DateTimeFormatterBuilder;->printerParsers:Ljava/util/List;
+Ljava/time/format/DateTimeFormatterBuilder;->QUERY_REGION_ONLY:Ljava/time/temporal/TemporalQuery;
+Ljava/time/format/DateTimeFormatterBuilder;->toFormatter(Ljava/time/format/ResolverStyle;Ljava/time/chrono/Chronology;)Ljava/time/format/DateTimeFormatter;
+Ljava/time/format/DateTimeFormatterBuilder;->toFormatter(Ljava/util/Locale;Ljava/time/format/ResolverStyle;Ljava/time/chrono/Chronology;)Ljava/time/format/DateTimeFormatter;
+Ljava/time/format/DateTimeFormatterBuilder;->valueParserIndex:I
+Ljava/time/format/DateTimeParseContext;-><init>(Ljava/time/format/DateTimeFormatter;)V
+Ljava/time/format/DateTimeParseContext;->addChronoChangedListener(Ljava/util/function/Consumer;)V
+Ljava/time/format/DateTimeParseContext;->caseSensitive:Z
+Ljava/time/format/DateTimeParseContext;->charEquals(CC)Z
+Ljava/time/format/DateTimeParseContext;->charEqualsIgnoreCase(CC)Z
+Ljava/time/format/DateTimeParseContext;->chronoListeners:Ljava/util/ArrayList;
+Ljava/time/format/DateTimeParseContext;->copy()Ljava/time/format/DateTimeParseContext;
+Ljava/time/format/DateTimeParseContext;->currentParsed()Ljava/time/format/Parsed;
+Ljava/time/format/DateTimeParseContext;->endOptional(Z)V
+Ljava/time/format/DateTimeParseContext;->formatter:Ljava/time/format/DateTimeFormatter;
+Ljava/time/format/DateTimeParseContext;->getDecimalStyle()Ljava/time/format/DecimalStyle;
+Ljava/time/format/DateTimeParseContext;->getEffectiveChronology()Ljava/time/chrono/Chronology;
+Ljava/time/format/DateTimeParseContext;->getLocale()Ljava/util/Locale;
+Ljava/time/format/DateTimeParseContext;->getParsed(Ljava/time/temporal/TemporalField;)Ljava/lang/Long;
+Ljava/time/format/DateTimeParseContext;->isCaseSensitive()Z
+Ljava/time/format/DateTimeParseContext;->isStrict()Z
+Ljava/time/format/DateTimeParseContext;->parsed:Ljava/util/ArrayList;
+Ljava/time/format/DateTimeParseContext;->setCaseSensitive(Z)V
+Ljava/time/format/DateTimeParseContext;->setParsed(Ljava/time/chrono/Chronology;)V
+Ljava/time/format/DateTimeParseContext;->setParsed(Ljava/time/ZoneId;)V
+Ljava/time/format/DateTimeParseContext;->setParsedField(Ljava/time/temporal/TemporalField;JII)I
+Ljava/time/format/DateTimeParseContext;->setParsedLeapSecond()V
+Ljava/time/format/DateTimeParseContext;->setStrict(Z)V
+Ljava/time/format/DateTimeParseContext;->startOptional()V
+Ljava/time/format/DateTimeParseContext;->strict:Z
+Ljava/time/format/DateTimeParseContext;->subSequenceEquals(Ljava/lang/CharSequence;ILjava/lang/CharSequence;II)Z
+Ljava/time/format/DateTimeParseContext;->toResolved(Ljava/time/format/ResolverStyle;Ljava/util/Set;)Ljava/time/temporal/TemporalAccessor;
+Ljava/time/format/DateTimeParseContext;->toUnresolved()Ljava/time/format/Parsed;
+Ljava/time/format/DateTimeParseException;->errorIndex:I
+Ljava/time/format/DateTimeParseException;->parsedString:Ljava/lang/String;
+Ljava/time/format/DateTimePrintContext;-><init>(Ljava/time/temporal/TemporalAccessor;Ljava/time/format/DateTimeFormatter;)V
+Ljava/time/format/DateTimePrintContext;->adjust(Ljava/time/temporal/TemporalAccessor;Ljava/time/format/DateTimeFormatter;)Ljava/time/temporal/TemporalAccessor;
+Ljava/time/format/DateTimePrintContext;->endOptional()V
+Ljava/time/format/DateTimePrintContext;->formatter:Ljava/time/format/DateTimeFormatter;
+Ljava/time/format/DateTimePrintContext;->getDecimalStyle()Ljava/time/format/DecimalStyle;
+Ljava/time/format/DateTimePrintContext;->getLocale()Ljava/util/Locale;
+Ljava/time/format/DateTimePrintContext;->getTemporal()Ljava/time/temporal/TemporalAccessor;
+Ljava/time/format/DateTimePrintContext;->getValue(Ljava/time/temporal/TemporalField;)Ljava/lang/Long;
+Ljava/time/format/DateTimePrintContext;->getValue(Ljava/time/temporal/TemporalQuery;)Ljava/lang/Object;
+Ljava/time/format/DateTimePrintContext;->optional:I
+Ljava/time/format/DateTimePrintContext;->startOptional()V
+Ljava/time/format/DateTimePrintContext;->temporal:Ljava/time/temporal/TemporalAccessor;
+Ljava/time/format/DateTimeTextProvider$LocaleStore;-><init>(Ljava/util/Map;)V
+Ljava/time/format/DateTimeTextProvider$LocaleStore;->getText(JLjava/time/format/TextStyle;)Ljava/lang/String;
+Ljava/time/format/DateTimeTextProvider$LocaleStore;->getTextIterator(Ljava/time/format/TextStyle;)Ljava/util/Iterator;
+Ljava/time/format/DateTimeTextProvider$LocaleStore;->parsable:Ljava/util/Map;
+Ljava/time/format/DateTimeTextProvider$LocaleStore;->valueTextMap:Ljava/util/Map;
+Ljava/time/format/DateTimeTextProvider;-><init>()V
+Ljava/time/format/DateTimeTextProvider;->CACHE:Ljava/util/concurrent/ConcurrentMap;
+Ljava/time/format/DateTimeTextProvider;->COMPARATOR:Ljava/util/Comparator;
+Ljava/time/format/DateTimeTextProvider;->createEntry(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/Map$Entry;
+Ljava/time/format/DateTimeTextProvider;->createStore(Ljava/time/temporal/TemporalField;Ljava/util/Locale;)Ljava/lang/Object;
+Ljava/time/format/DateTimeTextProvider;->extractQuarters(Landroid/icu/impl/ICUResourceBundle;Ljava/lang/String;)Ljava/util/Map;
+Ljava/time/format/DateTimeTextProvider;->findStore(Ljava/time/temporal/TemporalField;Ljava/util/Locale;)Ljava/lang/Object;
+Ljava/time/format/DateTimeTextProvider;->getInstance()Ljava/time/format/DateTimeTextProvider;
+Ljava/time/format/DateTimeTextProvider;->getText(Ljava/time/chrono/Chronology;Ljava/time/temporal/TemporalField;JLjava/time/format/TextStyle;Ljava/util/Locale;)Ljava/lang/String;
+Ljava/time/format/DateTimeTextProvider;->getText(Ljava/time/temporal/TemporalField;JLjava/time/format/TextStyle;Ljava/util/Locale;)Ljava/lang/String;
+Ljava/time/format/DateTimeTextProvider;->getTextIterator(Ljava/time/chrono/Chronology;Ljava/time/temporal/TemporalField;Ljava/time/format/TextStyle;Ljava/util/Locale;)Ljava/util/Iterator;
+Ljava/time/format/DateTimeTextProvider;->getTextIterator(Ljava/time/temporal/TemporalField;Ljava/time/format/TextStyle;Ljava/util/Locale;)Ljava/util/Iterator;
+Ljava/time/format/DateTimeTextProvider;->toWeekDay(I)I
+Ljava/time/format/DecimalStyle;-><init>(CCCC)V
+Ljava/time/format/DecimalStyle;->CACHE:Ljava/util/concurrent/ConcurrentMap;
+Ljava/time/format/DecimalStyle;->convertNumberToI18N(Ljava/lang/String;)Ljava/lang/String;
+Ljava/time/format/DecimalStyle;->convertToDigit(C)I
+Ljava/time/format/DecimalStyle;->create(Ljava/util/Locale;)Ljava/time/format/DecimalStyle;
+Ljava/time/format/DecimalStyle;->decimalSeparator:C
+Ljava/time/format/DecimalStyle;->negativeSign:C
+Ljava/time/format/DecimalStyle;->positiveSign:C
+Ljava/time/format/DecimalStyle;->zeroDigit:C
+Ljava/time/format/Parsed;-><init>()V
+Ljava/time/format/Parsed;->chrono:Ljava/time/chrono/Chronology;
+Ljava/time/format/Parsed;->copy()Ljava/time/format/Parsed;
+Ljava/time/format/Parsed;->crossCheck()V
+Ljava/time/format/Parsed;->crossCheck(Ljava/time/temporal/TemporalAccessor;)V
+Ljava/time/format/Parsed;->date:Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/format/Parsed;->excessDays:Ljava/time/Period;
+Ljava/time/format/Parsed;->fieldValues:Ljava/util/Map;
+Ljava/time/format/Parsed;->leapSecond:Z
+Ljava/time/format/Parsed;->resolve(Ljava/time/format/ResolverStyle;Ljava/util/Set;)Ljava/time/temporal/TemporalAccessor;
+Ljava/time/format/Parsed;->resolveDateFields()V
+Ljava/time/format/Parsed;->resolveFields()V
+Ljava/time/format/Parsed;->resolveFractional()V
+Ljava/time/format/Parsed;->resolveInstant()V
+Ljava/time/format/Parsed;->resolveInstantFields()V
+Ljava/time/format/Parsed;->resolveInstantFields0(Ljava/time/ZoneId;)V
+Ljava/time/format/Parsed;->resolvePeriod()V
+Ljava/time/format/Parsed;->resolverStyle:Ljava/time/format/ResolverStyle;
+Ljava/time/format/Parsed;->resolveTime(JJJJ)V
+Ljava/time/format/Parsed;->resolveTimeFields()V
+Ljava/time/format/Parsed;->resolveTimeLenient()V
+Ljava/time/format/Parsed;->time:Ljava/time/LocalTime;
+Ljava/time/format/Parsed;->updateCheckConflict(Ljava/time/chrono/ChronoLocalDate;)V
+Ljava/time/format/Parsed;->updateCheckConflict(Ljava/time/LocalTime;Ljava/time/Period;)V
+Ljava/time/format/Parsed;->updateCheckConflict(Ljava/time/temporal/TemporalField;Ljava/time/temporal/TemporalField;Ljava/lang/Long;)V
+Ljava/time/format/Parsed;->zone:Ljava/time/ZoneId;
+Ljava/time/format/SignStyle;->parse(ZZZ)Z
+Ljava/time/format/TextStyle;->calendarStyle:I
+Ljava/time/format/TextStyle;->toCalendarStyle()I
+Ljava/time/format/TextStyle;->zoneNameStyleIndex()I
+Ljava/time/format/TextStyle;->zoneNameStyleIndex:I
+Ljava/time/Instant;-><init>(JI)V
+Ljava/time/Instant;->create(JI)Ljava/time/Instant;
+Ljava/time/Instant;->MAX_SECOND:J
+Ljava/time/Instant;->MIN_SECOND:J
+Ljava/time/Instant;->nanos:I
+Ljava/time/Instant;->nanosUntil(Ljava/time/Instant;)J
+Ljava/time/Instant;->plus(JJ)Ljava/time/Instant;
+Ljava/time/Instant;->readExternal(Ljava/io/DataInput;)Ljava/time/Instant;
+Ljava/time/Instant;->seconds:J
+Ljava/time/Instant;->secondsUntil(Ljava/time/Instant;)J
+Ljava/time/Instant;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/LocalDate;-><init>(III)V
+Ljava/time/LocalDate;->compareTo0(Ljava/time/LocalDate;)I
+Ljava/time/LocalDate;->create(III)Ljava/time/LocalDate;
+Ljava/time/LocalDate;->day:S
+Ljava/time/LocalDate;->daysUntil(Ljava/time/LocalDate;)J
+Ljava/time/LocalDate;->DAYS_0000_TO_1970:J
+Ljava/time/LocalDate;->DAYS_PER_CYCLE:I
+Ljava/time/LocalDate;->get0(Ljava/time/temporal/TemporalField;)I
+Ljava/time/LocalDate;->getProlepticMonth()J
+Ljava/time/LocalDate;->month:S
+Ljava/time/LocalDate;->monthsUntil(Ljava/time/LocalDate;)J
+Ljava/time/LocalDate;->readExternal(Ljava/io/DataInput;)Ljava/time/LocalDate;
+Ljava/time/LocalDate;->resolvePreviousValid(III)Ljava/time/LocalDate;
+Ljava/time/LocalDate;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/LocalDate;->year:I
+Ljava/time/LocalDateTime;-><init>(Ljava/time/LocalDate;Ljava/time/LocalTime;)V
+Ljava/time/LocalDateTime;->compareTo0(Ljava/time/LocalDateTime;)I
+Ljava/time/LocalDateTime;->date:Ljava/time/LocalDate;
+Ljava/time/LocalDateTime;->plusWithOverflow(Ljava/time/LocalDate;JJJJI)Ljava/time/LocalDateTime;
+Ljava/time/LocalDateTime;->readExternal(Ljava/io/DataInput;)Ljava/time/LocalDateTime;
+Ljava/time/LocalDateTime;->time:Ljava/time/LocalTime;
+Ljava/time/LocalDateTime;->with(Ljava/time/LocalDate;Ljava/time/LocalTime;)Ljava/time/LocalDateTime;
+Ljava/time/LocalDateTime;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/LocalTime;-><init>(IIII)V
+Ljava/time/LocalTime;->create(IIII)Ljava/time/LocalTime;
+Ljava/time/LocalTime;->get0(Ljava/time/temporal/TemporalField;)I
+Ljava/time/LocalTime;->hour:B
+Ljava/time/LocalTime;->HOURS:[Ljava/time/LocalTime;
+Ljava/time/LocalTime;->HOURS_PER_DAY:I
+Ljava/time/LocalTime;->MICROS_PER_DAY:J
+Ljava/time/LocalTime;->MILLIS_PER_DAY:J
+Ljava/time/LocalTime;->minute:B
+Ljava/time/LocalTime;->MINUTES_PER_DAY:I
+Ljava/time/LocalTime;->MINUTES_PER_HOUR:I
+Ljava/time/LocalTime;->nano:I
+Ljava/time/LocalTime;->NANOS_PER_DAY:J
+Ljava/time/LocalTime;->NANOS_PER_HOUR:J
+Ljava/time/LocalTime;->NANOS_PER_MINUTE:J
+Ljava/time/LocalTime;->NANOS_PER_SECOND:J
+Ljava/time/LocalTime;->readExternal(Ljava/io/DataInput;)Ljava/time/LocalTime;
+Ljava/time/LocalTime;->second:B
+Ljava/time/LocalTime;->SECONDS_PER_DAY:I
+Ljava/time/LocalTime;->SECONDS_PER_HOUR:I
+Ljava/time/LocalTime;->SECONDS_PER_MINUTE:I
+Ljava/time/LocalTime;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/Month;->ENUMS:[Ljava/time/Month;
+Ljava/time/MonthDay;-><init>(II)V
+Ljava/time/MonthDay;->day:I
+Ljava/time/MonthDay;->month:I
+Ljava/time/MonthDay;->PARSER:Ljava/time/format/DateTimeFormatter;
+Ljava/time/MonthDay;->readExternal(Ljava/io/DataInput;)Ljava/time/MonthDay;
+Ljava/time/MonthDay;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/OffsetDateTime;->compareInstant(Ljava/time/OffsetDateTime;Ljava/time/OffsetDateTime;)I
+Ljava/time/OffsetDateTime;->dateTime:Ljava/time/LocalDateTime;
+Ljava/time/OffsetDateTime;->offset:Ljava/time/ZoneOffset;
+Ljava/time/OffsetDateTime;->readExternal(Ljava/io/ObjectInput;)Ljava/time/OffsetDateTime;
+Ljava/time/OffsetDateTime;->with(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;)Ljava/time/OffsetDateTime;
+Ljava/time/OffsetDateTime;->writeExternal(Ljava/io/ObjectOutput;)V
+Ljava/time/OffsetTime;-><init>(Ljava/time/LocalTime;Ljava/time/ZoneOffset;)V
+Ljava/time/OffsetTime;->offset:Ljava/time/ZoneOffset;
+Ljava/time/OffsetTime;->readExternal(Ljava/io/ObjectInput;)Ljava/time/OffsetTime;
+Ljava/time/OffsetTime;->time:Ljava/time/LocalTime;
+Ljava/time/OffsetTime;->toEpochNano()J
+Ljava/time/OffsetTime;->with(Ljava/time/LocalTime;Ljava/time/ZoneOffset;)Ljava/time/OffsetTime;
+Ljava/time/OffsetTime;->writeExternal(Ljava/io/ObjectOutput;)V
+Ljava/time/Period;-><init>(III)V
+Ljava/time/Period;->create(III)Ljava/time/Period;
+Ljava/time/Period;->days:I
+Ljava/time/Period;->months:I
+Ljava/time/Period;->parseNumber(Ljava/lang/CharSequence;Ljava/lang/String;I)I
+Ljava/time/Period;->PATTERN:Ljava/util/regex/Pattern;
+Ljava/time/Period;->readExternal(Ljava/io/DataInput;)Ljava/time/Period;
+Ljava/time/Period;->SUPPORTED_UNITS:Ljava/util/List;
+Ljava/time/Period;->validateChrono(Ljava/time/temporal/TemporalAccessor;)V
+Ljava/time/Period;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/Period;->years:I
+Ljava/time/temporal/ChronoField;->baseUnit:Ljava/time/temporal/TemporalUnit;
+Ljava/time/temporal/ChronoField;->displayNameKey:Ljava/lang/String;
+Ljava/time/temporal/ChronoField;->getIcuFieldNumber(Ljava/time/temporal/ChronoField;)I
+Ljava/time/temporal/ChronoField;->name:Ljava/lang/String;
+Ljava/time/temporal/ChronoField;->range:Ljava/time/temporal/ValueRange;
+Ljava/time/temporal/ChronoField;->rangeUnit:Ljava/time/temporal/TemporalUnit;
+Ljava/time/temporal/ChronoUnit;->duration:Ljava/time/Duration;
+Ljava/time/temporal/ChronoUnit;->name:Ljava/lang/String;
+Ljava/time/temporal/IsoFields$Field;->DAY_OF_QUARTER:Ljava/time/temporal/IsoFields$Field;
+Ljava/time/temporal/IsoFields$Field;->ensureIso(Ljava/time/temporal/TemporalAccessor;)V
+Ljava/time/temporal/IsoFields$Field;->getWeek(Ljava/time/LocalDate;)I
+Ljava/time/temporal/IsoFields$Field;->getWeekBasedYear(Ljava/time/LocalDate;)I
+Ljava/time/temporal/IsoFields$Field;->getWeekRange(I)I
+Ljava/time/temporal/IsoFields$Field;->getWeekRange(Ljava/time/LocalDate;)Ljava/time/temporal/ValueRange;
+Ljava/time/temporal/IsoFields$Field;->isIso(Ljava/time/temporal/TemporalAccessor;)Z
+Ljava/time/temporal/IsoFields$Field;->QUARTER_DAYS:[I
+Ljava/time/temporal/IsoFields$Field;->QUARTER_OF_YEAR:Ljava/time/temporal/IsoFields$Field;
+Ljava/time/temporal/IsoFields$Field;->valueOf(Ljava/lang/String;)Ljava/time/temporal/IsoFields$Field;
+Ljava/time/temporal/IsoFields$Field;->values()[Ljava/time/temporal/IsoFields$Field;
+Ljava/time/temporal/IsoFields$Field;->WEEK_BASED_YEAR:Ljava/time/temporal/IsoFields$Field;
+Ljava/time/temporal/IsoFields$Field;->WEEK_OF_WEEK_BASED_YEAR:Ljava/time/temporal/IsoFields$Field;
+Ljava/time/temporal/IsoFields$Unit;->duration:Ljava/time/Duration;
+Ljava/time/temporal/IsoFields$Unit;->name:Ljava/lang/String;
+Ljava/time/temporal/IsoFields$Unit;->QUARTER_YEARS:Ljava/time/temporal/IsoFields$Unit;
+Ljava/time/temporal/IsoFields$Unit;->valueOf(Ljava/lang/String;)Ljava/time/temporal/IsoFields$Unit;
+Ljava/time/temporal/IsoFields$Unit;->values()[Ljava/time/temporal/IsoFields$Unit;
+Ljava/time/temporal/IsoFields$Unit;->WEEK_BASED_YEARS:Ljava/time/temporal/IsoFields$Unit;
+Ljava/time/temporal/IsoFields;-><init>()V
+Ljava/time/temporal/JulianFields$Field;->baseUnit:Ljava/time/temporal/TemporalUnit;
+Ljava/time/temporal/JulianFields$Field;->JULIAN_DAY:Ljava/time/temporal/JulianFields$Field;
+Ljava/time/temporal/JulianFields$Field;->MODIFIED_JULIAN_DAY:Ljava/time/temporal/JulianFields$Field;
+Ljava/time/temporal/JulianFields$Field;->name:Ljava/lang/String;
+Ljava/time/temporal/JulianFields$Field;->offset:J
+Ljava/time/temporal/JulianFields$Field;->range:Ljava/time/temporal/ValueRange;
+Ljava/time/temporal/JulianFields$Field;->rangeUnit:Ljava/time/temporal/TemporalUnit;
+Ljava/time/temporal/JulianFields$Field;->RATA_DIE:Ljava/time/temporal/JulianFields$Field;
+Ljava/time/temporal/JulianFields$Field;->valueOf(Ljava/lang/String;)Ljava/time/temporal/JulianFields$Field;
+Ljava/time/temporal/JulianFields$Field;->values()[Ljava/time/temporal/JulianFields$Field;
+Ljava/time/temporal/JulianFields;-><init>()V
+Ljava/time/temporal/JulianFields;->JULIAN_DAY_OFFSET:J
+Ljava/time/temporal/TemporalAdjusters;-><init>()V
+Ljava/time/temporal/TemporalQueries;-><init>()V
+Ljava/time/temporal/TemporalQueries;->CHRONO:Ljava/time/temporal/TemporalQuery;
+Ljava/time/temporal/TemporalQueries;->LOCAL_DATE:Ljava/time/temporal/TemporalQuery;
+Ljava/time/temporal/TemporalQueries;->LOCAL_TIME:Ljava/time/temporal/TemporalQuery;
+Ljava/time/temporal/TemporalQueries;->OFFSET:Ljava/time/temporal/TemporalQuery;
+Ljava/time/temporal/TemporalQueries;->PRECISION:Ljava/time/temporal/TemporalQuery;
+Ljava/time/temporal/TemporalQueries;->ZONE:Ljava/time/temporal/TemporalQuery;
+Ljava/time/temporal/TemporalQueries;->ZONE_ID:Ljava/time/temporal/TemporalQuery;
+Ljava/time/temporal/ValueRange;-><init>(JJJJ)V
+Ljava/time/temporal/ValueRange;->genInvalidFieldMessage(Ljava/time/temporal/TemporalField;J)Ljava/lang/String;
+Ljava/time/temporal/ValueRange;->maxLargest:J
+Ljava/time/temporal/ValueRange;->maxSmallest:J
+Ljava/time/temporal/ValueRange;->minLargest:J
+Ljava/time/temporal/ValueRange;->minSmallest:J
+Ljava/time/temporal/WeekFields$ComputedDayOfField;-><init>(Ljava/lang/String;Ljava/time/temporal/WeekFields;Ljava/time/temporal/TemporalUnit;Ljava/time/temporal/TemporalUnit;Ljava/time/temporal/ValueRange;)V
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->baseUnit:Ljava/time/temporal/TemporalUnit;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->computeWeek(II)I
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->DAY_OF_WEEK_RANGE:Ljava/time/temporal/ValueRange;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->localizedDayOfWeek(I)I
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->localizedDayOfWeek(Ljava/time/temporal/TemporalAccessor;)I
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->localizedWeekBasedYear(Ljava/time/temporal/TemporalAccessor;)I
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->localizedWeekOfMonth(Ljava/time/temporal/TemporalAccessor;)J
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->localizedWeekOfWeekBasedYear(Ljava/time/temporal/TemporalAccessor;)I
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->localizedWeekOfYear(Ljava/time/temporal/TemporalAccessor;)J
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->name:Ljava/lang/String;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->ofDayOfWeekField(Ljava/time/temporal/WeekFields;)Ljava/time/temporal/WeekFields$ComputedDayOfField;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->ofWeekBasedYear(Ljava/time/chrono/Chronology;III)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->ofWeekBasedYearField(Ljava/time/temporal/WeekFields;)Ljava/time/temporal/WeekFields$ComputedDayOfField;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->ofWeekOfMonthField(Ljava/time/temporal/WeekFields;)Ljava/time/temporal/WeekFields$ComputedDayOfField;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->ofWeekOfWeekBasedYearField(Ljava/time/temporal/WeekFields;)Ljava/time/temporal/WeekFields$ComputedDayOfField;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->ofWeekOfYearField(Ljava/time/temporal/WeekFields;)Ljava/time/temporal/WeekFields$ComputedDayOfField;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->range:Ljava/time/temporal/ValueRange;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->rangeByWeek(Ljava/time/temporal/TemporalAccessor;Ljava/time/temporal/TemporalField;)Ljava/time/temporal/ValueRange;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->rangeUnit:Ljava/time/temporal/TemporalUnit;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->rangeWeekOfWeekBasedYear(Ljava/time/temporal/TemporalAccessor;)Ljava/time/temporal/ValueRange;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->resolveWBY(Ljava/util/Map;Ljava/time/chrono/Chronology;ILjava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->resolveWoM(Ljava/util/Map;Ljava/time/chrono/Chronology;IJJILjava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->resolveWoY(Ljava/util/Map;Ljava/time/chrono/Chronology;IJILjava/time/format/ResolverStyle;)Ljava/time/chrono/ChronoLocalDate;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->startOfWeekOffset(II)I
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->weekDef:Ljava/time/temporal/WeekFields;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->WEEK_OF_MONTH_RANGE:Ljava/time/temporal/ValueRange;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->WEEK_OF_WEEK_BASED_YEAR_RANGE:Ljava/time/temporal/ValueRange;
+Ljava/time/temporal/WeekFields$ComputedDayOfField;->WEEK_OF_YEAR_RANGE:Ljava/time/temporal/ValueRange;
+Ljava/time/temporal/WeekFields;-><init>(Ljava/time/DayOfWeek;I)V
+Ljava/time/temporal/WeekFields;->CACHE:Ljava/util/concurrent/ConcurrentMap;
+Ljava/time/temporal/WeekFields;->dayOfWeek:Ljava/time/temporal/TemporalField;
+Ljava/time/temporal/WeekFields;->firstDayOfWeek:Ljava/time/DayOfWeek;
+Ljava/time/temporal/WeekFields;->minimalDays:I
+Ljava/time/temporal/WeekFields;->weekBasedYear:Ljava/time/temporal/TemporalField;
+Ljava/time/temporal/WeekFields;->weekOfMonth:Ljava/time/temporal/TemporalField;
+Ljava/time/temporal/WeekFields;->weekOfWeekBasedYear:Ljava/time/temporal/TemporalField;
+Ljava/time/temporal/WeekFields;->weekOfYear:Ljava/time/temporal/TemporalField;
+Ljava/time/Year;-><init>(I)V
+Ljava/time/Year;->PARSER:Ljava/time/format/DateTimeFormatter;
+Ljava/time/Year;->readExternal(Ljava/io/DataInput;)Ljava/time/Year;
+Ljava/time/Year;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/Year;->year:I
+Ljava/time/YearMonth;-><init>(II)V
+Ljava/time/YearMonth;->getProlepticMonth()J
+Ljava/time/YearMonth;->month:I
+Ljava/time/YearMonth;->PARSER:Ljava/time/format/DateTimeFormatter;
+Ljava/time/YearMonth;->readExternal(Ljava/io/DataInput;)Ljava/time/YearMonth;
+Ljava/time/YearMonth;->with(II)Ljava/time/YearMonth;
+Ljava/time/YearMonth;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/YearMonth;->year:I
+Ljava/time/zone/ZoneOffsetTransition;-><init>(JLjava/time/ZoneOffset;Ljava/time/ZoneOffset;)V
+Ljava/time/zone/ZoneOffsetTransition;-><init>(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;)V
+Ljava/time/zone/ZoneOffsetTransition;->getDurationSeconds()I
+Ljava/time/zone/ZoneOffsetTransition;->getValidOffsets()Ljava/util/List;
+Ljava/time/zone/ZoneOffsetTransition;->offsetAfter:Ljava/time/ZoneOffset;
+Ljava/time/zone/ZoneOffsetTransition;->offsetBefore:Ljava/time/ZoneOffset;
+Ljava/time/zone/ZoneOffsetTransition;->readExternal(Ljava/io/DataInput;)Ljava/time/zone/ZoneOffsetTransition;
+Ljava/time/zone/ZoneOffsetTransition;->transition:Ljava/time/LocalDateTime;
+Ljava/time/zone/ZoneOffsetTransition;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/zone/ZoneOffsetTransitionRule;-><init>(Ljava/time/Month;ILjava/time/DayOfWeek;Ljava/time/LocalTime;ZLjava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;)V
+Ljava/time/zone/ZoneOffsetTransitionRule;->dom:B
+Ljava/time/zone/ZoneOffsetTransitionRule;->dow:Ljava/time/DayOfWeek;
+Ljava/time/zone/ZoneOffsetTransitionRule;->month:Ljava/time/Month;
+Ljava/time/zone/ZoneOffsetTransitionRule;->offsetAfter:Ljava/time/ZoneOffset;
+Ljava/time/zone/ZoneOffsetTransitionRule;->offsetBefore:Ljava/time/ZoneOffset;
+Ljava/time/zone/ZoneOffsetTransitionRule;->readExternal(Ljava/io/DataInput;)Ljava/time/zone/ZoneOffsetTransitionRule;
+Ljava/time/zone/ZoneOffsetTransitionRule;->standardOffset:Ljava/time/ZoneOffset;
+Ljava/time/zone/ZoneOffsetTransitionRule;->time:Ljava/time/LocalTime;
+Ljava/time/zone/ZoneOffsetTransitionRule;->timeDefinition:Ljava/time/zone/ZoneOffsetTransitionRule$TimeDefinition;
+Ljava/time/zone/ZoneOffsetTransitionRule;->timeEndOfDay:Z
+Ljava/time/zone/ZoneOffsetTransitionRule;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/zone/ZoneRules;-><init>(Ljava/time/ZoneOffset;)V
+Ljava/time/zone/ZoneRules;-><init>(Ljava/time/ZoneOffset;Ljava/time/ZoneOffset;Ljava/util/List;Ljava/util/List;Ljava/util/List;)V
+Ljava/time/zone/ZoneRules;-><init>([J[Ljava/time/ZoneOffset;[J[Ljava/time/ZoneOffset;[Ljava/time/zone/ZoneOffsetTransitionRule;)V
+Ljava/time/zone/ZoneRules;->EMPTY_LASTRULES:[Ljava/time/zone/ZoneOffsetTransitionRule;
+Ljava/time/zone/ZoneRules;->EMPTY_LDT_ARRAY:[Ljava/time/LocalDateTime;
+Ljava/time/zone/ZoneRules;->EMPTY_LONG_ARRAY:[J
+Ljava/time/zone/ZoneRules;->findOffsetInfo(Ljava/time/LocalDateTime;Ljava/time/zone/ZoneOffsetTransition;)Ljava/lang/Object;
+Ljava/time/zone/ZoneRules;->findTransitionArray(I)[Ljava/time/zone/ZoneOffsetTransition;
+Ljava/time/zone/ZoneRules;->findYear(JLjava/time/ZoneOffset;)I
+Ljava/time/zone/ZoneRules;->getOffsetInfo(Ljava/time/LocalDateTime;)Ljava/lang/Object;
+Ljava/time/zone/ZoneRules;->lastRules:[Ljava/time/zone/ZoneOffsetTransitionRule;
+Ljava/time/zone/ZoneRules;->lastRulesCache:Ljava/util/concurrent/ConcurrentMap;
+Ljava/time/zone/ZoneRules;->LAST_CACHED_YEAR:I
+Ljava/time/zone/ZoneRules;->readExternal(Ljava/io/DataInput;)Ljava/time/zone/ZoneRules;
+Ljava/time/zone/ZoneRules;->savingsInstantTransitions:[J
+Ljava/time/zone/ZoneRules;->savingsLocalTransitions:[Ljava/time/LocalDateTime;
+Ljava/time/zone/ZoneRules;->standardOffsets:[Ljava/time/ZoneOffset;
+Ljava/time/zone/ZoneRules;->standardTransitions:[J
+Ljava/time/zone/ZoneRules;->wallOffsets:[Ljava/time/ZoneOffset;
+Ljava/time/zone/ZoneRules;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/ZonedDateTime;-><init>(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;Ljava/time/ZoneId;)V
+Ljava/time/ZonedDateTime;->create(JILjava/time/ZoneId;)Ljava/time/ZonedDateTime;
+Ljava/time/ZonedDateTime;->dateTime:Ljava/time/LocalDateTime;
+Ljava/time/ZonedDateTime;->offset:Ljava/time/ZoneOffset;
+Ljava/time/ZonedDateTime;->ofLenient(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;Ljava/time/ZoneId;)Ljava/time/ZonedDateTime;
+Ljava/time/ZonedDateTime;->readExternal(Ljava/io/ObjectInput;)Ljava/time/ZonedDateTime;
+Ljava/time/ZonedDateTime;->resolveInstant(Ljava/time/LocalDateTime;)Ljava/time/ZonedDateTime;
+Ljava/time/ZonedDateTime;->resolveLocal(Ljava/time/LocalDateTime;)Ljava/time/ZonedDateTime;
+Ljava/time/ZonedDateTime;->resolveOffset(Ljava/time/ZoneOffset;)Ljava/time/ZonedDateTime;
+Ljava/time/ZonedDateTime;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/time/ZonedDateTime;->zone:Ljava/time/ZoneId;
+Ljava/time/ZoneId;-><init>()V
+Ljava/time/ZoneId;->ofWithPrefix(Ljava/lang/String;IZ)Ljava/time/ZoneId;
+Ljava/time/ZoneId;->toTemporal()Ljava/time/temporal/TemporalAccessor;
+Ljava/time/ZoneId;->write(Ljava/io/DataOutput;)V
+Ljava/time/ZoneOffset;-><init>(I)V
+Ljava/time/ZoneOffset;->buildId(I)Ljava/lang/String;
+Ljava/time/ZoneOffset;->id:Ljava/lang/String;
+Ljava/time/ZoneOffset;->ID_CACHE:Ljava/util/concurrent/ConcurrentMap;
+Ljava/time/ZoneOffset;->MAX_SECONDS:I
+Ljava/time/ZoneOffset;->parseNumber(Ljava/lang/CharSequence;IZ)I
+Ljava/time/ZoneOffset;->readExternal(Ljava/io/DataInput;)Ljava/time/ZoneOffset;
+Ljava/time/ZoneOffset;->SECONDS_CACHE:Ljava/util/concurrent/ConcurrentMap;
+Ljava/time/ZoneOffset;->totalSeconds(III)I
+Ljava/time/ZoneOffset;->totalSeconds:I
+Ljava/time/ZoneOffset;->validate(III)V
+Ljava/time/ZoneOffset;->write(Ljava/io/DataOutput;)V
+Ljava/time/ZoneOffset;->writeExternal(Ljava/io/DataOutput;)V
+Ljava/util/AbstractCollection;->finishToArray([Ljava/lang/Object;Ljava/util/Iterator;)[Ljava/lang/Object;
+Ljava/util/AbstractCollection;->hugeCapacity(I)I
+Ljava/util/AbstractCollection;->MAX_ARRAY_SIZE:I
+Ljava/util/AbstractList$Itr;->checkForComodification()V
+Ljava/util/AbstractList$Itr;->cursor:I
+Ljava/util/AbstractList$Itr;->expectedModCount:I
+Ljava/util/AbstractList$Itr;->lastRet:I
+Ljava/util/AbstractList;->outOfBoundsMsg(I)Ljava/lang/String;
+Ljava/util/AbstractList;->rangeCheckForAdd(I)V
+Ljava/util/AbstractMap$SimpleEntry;->key:Ljava/lang/Object;
+Ljava/util/AbstractMap$SimpleEntry;->value:Ljava/lang/Object;
+Ljava/util/AbstractMap$SimpleImmutableEntry;->key:Ljava/lang/Object;
+Ljava/util/AbstractMap$SimpleImmutableEntry;->value:Ljava/lang/Object;
+Ljava/util/AbstractMap;->eq(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/AbstractMap;->keySet:Ljava/util/Set;
+Ljava/util/AbstractMap;->values:Ljava/util/Collection;
+Ljava/util/ArrayDeque$DeqIterator;->cursor:I
+Ljava/util/ArrayDeque$DeqIterator;->fence:I
+Ljava/util/ArrayDeque$DeqIterator;->lastRet:I
+Ljava/util/ArrayDeque$DeqSpliterator;-><init>(Ljava/util/ArrayDeque;II)V
+Ljava/util/ArrayDeque$DeqSpliterator;->deq:Ljava/util/ArrayDeque;
+Ljava/util/ArrayDeque$DeqSpliterator;->fence:I
+Ljava/util/ArrayDeque$DeqSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/ArrayDeque$DeqSpliterator;->getFence()I
+Ljava/util/ArrayDeque$DeqSpliterator;->index:I
+Ljava/util/ArrayDeque$DeqSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/ArrayDeque$DescendingIterator;->cursor:I
+Ljava/util/ArrayDeque$DescendingIterator;->fence:I
+Ljava/util/ArrayDeque$DescendingIterator;->lastRet:I
+Ljava/util/ArrayDeque;->allocateElements(I)V
+Ljava/util/ArrayDeque;->checkInvariants()V
+Ljava/util/ArrayDeque;->delete(I)Z
+Ljava/util/ArrayDeque;->doubleCapacity()V
+Ljava/util/ArrayDeque;->MIN_INITIAL_CAPACITY:I
+Ljava/util/ArrayList$ArrayListSpliterator;-><init>(Ljava/util/ArrayList;III)V
+Ljava/util/ArrayList$ArrayListSpliterator;->expectedModCount:I
+Ljava/util/ArrayList$ArrayListSpliterator;->fence:I
+Ljava/util/ArrayList$ArrayListSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/ArrayList$ArrayListSpliterator;->getFence()I
+Ljava/util/ArrayList$ArrayListSpliterator;->index:I
+Ljava/util/ArrayList$ArrayListSpliterator;->list:Ljava/util/ArrayList;
+Ljava/util/ArrayList$ArrayListSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/ArrayList$Itr;->cursor:I
+Ljava/util/ArrayList$Itr;->expectedModCount:I
+Ljava/util/ArrayList$Itr;->lastRet:I
+Ljava/util/ArrayList$Itr;->limit:I
+Ljava/util/ArrayList$SubList;->outOfBoundsMsg(I)Ljava/lang/String;
+Ljava/util/ArrayList;->batchRemove(Ljava/util/Collection;Z)Z
+Ljava/util/ArrayList;->DEFAULTCAPACITY_EMPTY_ELEMENTDATA:[Ljava/lang/Object;
+Ljava/util/ArrayList;->DEFAULT_CAPACITY:I
+Ljava/util/ArrayList;->EMPTY_ELEMENTDATA:[Ljava/lang/Object;
+Ljava/util/ArrayList;->ensureCapacityInternal(I)V
+Ljava/util/ArrayList;->ensureExplicitCapacity(I)V
+Ljava/util/ArrayList;->fastRemove(I)V
+Ljava/util/ArrayList;->grow(I)V
+Ljava/util/ArrayList;->hugeCapacity(I)I
+Ljava/util/ArrayList;->MAX_ARRAY_SIZE:I
+Ljava/util/ArrayList;->outOfBoundsMsg(I)Ljava/lang/String;
+Ljava/util/ArrayList;->subListRangeCheck(III)V
+Ljava/util/Arrays$ArrayList;-><init>([Ljava/lang/Object;)V
+Ljava/util/Arrays$ArrayList;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Arrays$NaturalOrder;-><init>()V
+Ljava/util/Arrays$NaturalOrder;->compare(Ljava/lang/Object;Ljava/lang/Object;)I
+Ljava/util/Arrays$NaturalOrder;->INSTANCE:Ljava/util/Arrays$NaturalOrder;
+Ljava/util/Arrays;-><init>()V
+Ljava/util/Arrays;->binarySearch0([BIIB)I
+Ljava/util/Arrays;->binarySearch0([CIIC)I
+Ljava/util/Arrays;->binarySearch0([DIID)I
+Ljava/util/Arrays;->binarySearch0([FIIF)I
+Ljava/util/Arrays;->binarySearch0([IIII)I
+Ljava/util/Arrays;->binarySearch0([JIIJ)I
+Ljava/util/Arrays;->binarySearch0([Ljava/lang/Object;IILjava/lang/Object;)I
+Ljava/util/Arrays;->binarySearch0([Ljava/lang/Object;IILjava/lang/Object;Ljava/util/Comparator;)I
+Ljava/util/Arrays;->binarySearch0([SIIS)I
+Ljava/util/Arrays;->deepEquals0(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/Arrays;->INSERTIONSORT_THRESHOLD:I
+Ljava/util/Arrays;->mergeSort([Ljava/lang/Object;[Ljava/lang/Object;III)V
+Ljava/util/Arrays;->MIN_ARRAY_SORT_GRAN:I
+Ljava/util/Arrays;->rangeCheck(III)V
+Ljava/util/Arrays;->swap([Ljava/lang/Object;II)V
+Ljava/util/Base64$DecInputStream;-><init>(Ljava/io/InputStream;[IZ)V
+Ljava/util/Base64$DecInputStream;->base64:[I
+Ljava/util/Base64$DecInputStream;->bits:I
+Ljava/util/Base64$DecInputStream;->closed:Z
+Ljava/util/Base64$DecInputStream;->eof:Z
+Ljava/util/Base64$DecInputStream;->is:Ljava/io/InputStream;
+Ljava/util/Base64$DecInputStream;->isMIME:Z
+Ljava/util/Base64$DecInputStream;->nextin:I
+Ljava/util/Base64$DecInputStream;->nextout:I
+Ljava/util/Base64$DecInputStream;->sbBuf:[B
+Ljava/util/Base64$Decoder;-><init>(ZZ)V
+Ljava/util/Base64$Decoder;->decode0([BII[B)I
+Ljava/util/Base64$Decoder;->fromBase64:[I
+Ljava/util/Base64$Decoder;->fromBase64URL:[I
+Ljava/util/Base64$Decoder;->isMIME:Z
+Ljava/util/Base64$Decoder;->isURL:Z
+Ljava/util/Base64$Decoder;->outLength([BII)I
+Ljava/util/Base64$Decoder;->RFC2045:Ljava/util/Base64$Decoder;
+Ljava/util/Base64$Decoder;->RFC4648:Ljava/util/Base64$Decoder;
+Ljava/util/Base64$Decoder;->RFC4648_URLSAFE:Ljava/util/Base64$Decoder;
+Ljava/util/Base64$Encoder;-><init>(Z[BIZ)V
+Ljava/util/Base64$Encoder;->CRLF:[B
+Ljava/util/Base64$Encoder;->doPadding:Z
+Ljava/util/Base64$Encoder;->encode0([BII[B)I
+Ljava/util/Base64$Encoder;->isURL:Z
+Ljava/util/Base64$Encoder;->linemax:I
+Ljava/util/Base64$Encoder;->MIMELINEMAX:I
+Ljava/util/Base64$Encoder;->newline:[B
+Ljava/util/Base64$Encoder;->outLength(I)I
+Ljava/util/Base64$Encoder;->RFC2045:Ljava/util/Base64$Encoder;
+Ljava/util/Base64$Encoder;->RFC4648:Ljava/util/Base64$Encoder;
+Ljava/util/Base64$Encoder;->RFC4648_URLSAFE:Ljava/util/Base64$Encoder;
+Ljava/util/Base64$Encoder;->toBase64:[C
+Ljava/util/Base64$Encoder;->toBase64URL:[C
+Ljava/util/Base64$EncOutputStream;-><init>(Ljava/io/OutputStream;[C[BIZ)V
+Ljava/util/Base64$EncOutputStream;->b0:I
+Ljava/util/Base64$EncOutputStream;->b1:I
+Ljava/util/Base64$EncOutputStream;->b2:I
+Ljava/util/Base64$EncOutputStream;->base64:[C
+Ljava/util/Base64$EncOutputStream;->checkNewline()V
+Ljava/util/Base64$EncOutputStream;->closed:Z
+Ljava/util/Base64$EncOutputStream;->doPadding:Z
+Ljava/util/Base64$EncOutputStream;->leftover:I
+Ljava/util/Base64$EncOutputStream;->linemax:I
+Ljava/util/Base64$EncOutputStream;->linepos:I
+Ljava/util/Base64$EncOutputStream;->newline:[B
+Ljava/util/Base64;-><init>()V
+Ljava/util/BitSet;-><init>([J)V
+Ljava/util/BitSet;->ADDRESS_BITS_PER_WORD:I
+Ljava/util/BitSet;->BITS_PER_WORD:I
+Ljava/util/BitSet;->BIT_INDEX_MASK:I
+Ljava/util/BitSet;->checkInvariants()V
+Ljava/util/BitSet;->checkRange(II)V
+Ljava/util/BitSet;->ensureCapacity(I)V
+Ljava/util/BitSet;->expandTo(I)V
+Ljava/util/BitSet;->initWords(I)V
+Ljava/util/BitSet;->recalculateWordsInUse()V
+Ljava/util/BitSet;->sizeIsSticky:Z
+Ljava/util/BitSet;->trimToSize()V
+Ljava/util/BitSet;->wordIndex(I)I
+Ljava/util/BitSet;->words:[J
+Ljava/util/BitSet;->wordsInUse:I
+Ljava/util/BitSet;->WORD_MASK:J
+Ljava/util/Calendar$AvailableCalendarTypes;-><init>()V
+Ljava/util/Calendar$AvailableCalendarTypes;->SET:Ljava/util/Set;
+Ljava/util/Calendar$Builder;->allocateFields()V
+Ljava/util/Calendar$Builder;->fields:[I
+Ljava/util/Calendar$Builder;->firstDayOfWeek:I
+Ljava/util/Calendar$Builder;->instant:J
+Ljava/util/Calendar$Builder;->internalSet(II)V
+Ljava/util/Calendar$Builder;->isInstantSet()Z
+Ljava/util/Calendar$Builder;->isSet(I)Z
+Ljava/util/Calendar$Builder;->isValidWeekParameter(I)Z
+Ljava/util/Calendar$Builder;->lenient:Z
+Ljava/util/Calendar$Builder;->locale:Ljava/util/Locale;
+Ljava/util/Calendar$Builder;->maxFieldIndex:I
+Ljava/util/Calendar$Builder;->minimalDaysInFirstWeek:I
+Ljava/util/Calendar$Builder;->nextStamp:I
+Ljava/util/Calendar$Builder;->NFIELDS:I
+Ljava/util/Calendar$Builder;->type:Ljava/lang/String;
+Ljava/util/Calendar$Builder;->WEEK_YEAR:I
+Ljava/util/Calendar$Builder;->zone:Ljava/util/TimeZone;
+Ljava/util/Calendar$CalendarAccessControlContext;-><init>()V
+Ljava/util/Calendar$CalendarAccessControlContext;->INSTANCE:Ljava/security/AccessControlContext;
+Ljava/util/Calendar;->adjustStamp()V
+Ljava/util/Calendar;->aggregateStamp(II)I
+Ljava/util/Calendar;->ALL_FIELDS:I
+Ljava/util/Calendar;->AM_PM_MASK:I
+Ljava/util/Calendar;->appendValue(Ljava/lang/StringBuilder;Ljava/lang/String;ZJ)V
+Ljava/util/Calendar;->areAllFieldsSet:Z
+Ljava/util/Calendar;->cachedLocaleData:Ljava/util/concurrent/ConcurrentMap;
+Ljava/util/Calendar;->checkDisplayNameParams(IIIILjava/util/Locale;I)Z
+Ljava/util/Calendar;->compareTo(J)I
+Ljava/util/Calendar;->COMPUTED:I
+Ljava/util/Calendar;->createCalendar(Ljava/util/TimeZone;Ljava/util/Locale;)Ljava/util/Calendar;
+Ljava/util/Calendar;->currentSerialVersion:I
+Ljava/util/Calendar;->DATE_MASK:I
+Ljava/util/Calendar;->DAY_OF_MONTH_MASK:I
+Ljava/util/Calendar;->DAY_OF_WEEK_IN_MONTH_MASK:I
+Ljava/util/Calendar;->DAY_OF_WEEK_MASK:I
+Ljava/util/Calendar;->DAY_OF_YEAR_MASK:I
+Ljava/util/Calendar;->DST_OFFSET_MASK:I
+Ljava/util/Calendar;->ERA_MASK:I
+Ljava/util/Calendar;->FIELD_NAME:[Ljava/lang/String;
+Ljava/util/Calendar;->firstDayOfWeek:I
+Ljava/util/Calendar;->getBaseStyle(I)I
+Ljava/util/Calendar;->getDisplayNamesImpl(IILjava/util/Locale;)Ljava/util/Map;
+Ljava/util/Calendar;->getFieldName(I)Ljava/lang/String;
+Ljava/util/Calendar;->getFieldStrings(IILjava/text/DateFormatSymbols;)[Ljava/lang/String;
+Ljava/util/Calendar;->getJapaneseImperialInstance(Ljava/util/TimeZone;Ljava/util/Locale;)Ljava/util/Calendar;
+Ljava/util/Calendar;->getMillisOf(Ljava/util/Calendar;)J
+Ljava/util/Calendar;->getSetStateFields()I
+Ljava/util/Calendar;->getZone()Ljava/util/TimeZone;
+Ljava/util/Calendar;->HOUR_MASK:I
+Ljava/util/Calendar;->HOUR_OF_DAY_MASK:I
+Ljava/util/Calendar;->internalSet(II)V
+Ljava/util/Calendar;->invalidateWeekFields()V
+Ljava/util/Calendar;->isExternallySet(I)Z
+Ljava/util/Calendar;->isFieldSet(II)Z
+Ljava/util/Calendar;->isFullyNormalized()Z
+Ljava/util/Calendar;->isNarrowFormatStyle(I)Z
+Ljava/util/Calendar;->isNarrowStyle(I)Z
+Ljava/util/Calendar;->isPartiallyNormalized()Z
+Ljava/util/Calendar;->isStandaloneStyle(I)Z
+Ljava/util/Calendar;->lenient:Z
+Ljava/util/Calendar;->MILLISECOND_MASK:I
+Ljava/util/Calendar;->minimalDaysInFirstWeek:I
+Ljava/util/Calendar;->MINIMUM_USER_STAMP:I
+Ljava/util/Calendar;->MINUTE_MASK:I
+Ljava/util/Calendar;->MONTH_MASK:I
+Ljava/util/Calendar;->nextStamp:I
+Ljava/util/Calendar;->SECOND_MASK:I
+Ljava/util/Calendar;->selectFields()I
+Ljava/util/Calendar;->serialVersionOnStream:I
+Ljava/util/Calendar;->setFieldsComputed(I)V
+Ljava/util/Calendar;->setFieldsNormalized(I)V
+Ljava/util/Calendar;->setUnnormalized()V
+Ljava/util/Calendar;->setWeekCountData(Ljava/util/Locale;)V
+Ljava/util/Calendar;->setZoneShared(Z)V
+Ljava/util/Calendar;->sharedZone:Z
+Ljava/util/Calendar;->stamp:[I
+Ljava/util/Calendar;->STANDALONE_MASK:I
+Ljava/util/Calendar;->toStandaloneStyle(I)I
+Ljava/util/Calendar;->UNSET:I
+Ljava/util/Calendar;->updateTime()V
+Ljava/util/Calendar;->WEEK_OF_MONTH_MASK:I
+Ljava/util/Calendar;->WEEK_OF_YEAR_MASK:I
+Ljava/util/Calendar;->YEAR_MASK:I
+Ljava/util/Calendar;->ZONE_OFFSET_MASK:I
+Ljava/util/Collections$AsLIFOQueue;-><init>(Ljava/util/Deque;)V
+Ljava/util/Collections$AsLIFOQueue;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$AsLIFOQueue;->q:Ljava/util/Deque;
+Ljava/util/Collections$CheckedCollection;-><init>(Ljava/util/Collection;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedCollection;->badElementMsg(Ljava/lang/Object;)Ljava/lang/String;
+Ljava/util/Collections$CheckedCollection;->c:Ljava/util/Collection;
+Ljava/util/Collections$CheckedCollection;->checkedCopyOf(Ljava/util/Collection;)Ljava/util/Collection;
+Ljava/util/Collections$CheckedCollection;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$CheckedCollection;->type:Ljava/lang/Class;
+Ljava/util/Collections$CheckedCollection;->typeCheck(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/Collections$CheckedCollection;->zeroLengthElementArray()[Ljava/lang/Object;
+Ljava/util/Collections$CheckedCollection;->zeroLengthElementArray:[Ljava/lang/Object;
+Ljava/util/Collections$CheckedList;-><init>(Ljava/util/List;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedList;->list:Ljava/util/List;
+Ljava/util/Collections$CheckedMap$CheckedEntrySet$CheckedEntry;-><init>(Ljava/util/Map$Entry;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedMap$CheckedEntrySet$CheckedEntry;->badValueMsg(Ljava/lang/Object;)Ljava/lang/String;
+Ljava/util/Collections$CheckedMap$CheckedEntrySet$CheckedEntry;->e:Ljava/util/Map$Entry;
+Ljava/util/Collections$CheckedMap$CheckedEntrySet$CheckedEntry;->valueType:Ljava/lang/Class;
+Ljava/util/Collections$CheckedMap$CheckedEntrySet;-><init>(Ljava/util/Set;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedMap$CheckedEntrySet;->add(Ljava/util/Map$Entry;)Z
+Ljava/util/Collections$CheckedMap$CheckedEntrySet;->addAll(Ljava/util/Collection;)Z
+Ljava/util/Collections$CheckedMap$CheckedEntrySet;->batchRemove(Ljava/util/Collection;Z)Z
+Ljava/util/Collections$CheckedMap$CheckedEntrySet;->checkedEntry(Ljava/util/Map$Entry;Ljava/lang/Class;)Ljava/util/Collections$CheckedMap$CheckedEntrySet$CheckedEntry;
+Ljava/util/Collections$CheckedMap$CheckedEntrySet;->s:Ljava/util/Set;
+Ljava/util/Collections$CheckedMap$CheckedEntrySet;->valueType:Ljava/lang/Class;
+Ljava/util/Collections$CheckedMap;-><init>(Ljava/util/Map;Ljava/lang/Class;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedMap;->badKeyMsg(Ljava/lang/Object;)Ljava/lang/String;
+Ljava/util/Collections$CheckedMap;->badValueMsg(Ljava/lang/Object;)Ljava/lang/String;
+Ljava/util/Collections$CheckedMap;->entrySet:Ljava/util/Set;
+Ljava/util/Collections$CheckedMap;->keyType:Ljava/lang/Class;
+Ljava/util/Collections$CheckedMap;->m:Ljava/util/Map;
+Ljava/util/Collections$CheckedMap;->typeCheck(Ljava/lang/Object;Ljava/lang/Object;)V
+Ljava/util/Collections$CheckedMap;->typeCheck(Ljava/util/function/BiFunction;)Ljava/util/function/BiFunction;
+Ljava/util/Collections$CheckedMap;->valueType:Ljava/lang/Class;
+Ljava/util/Collections$CheckedNavigableMap;-><init>(Ljava/util/NavigableMap;Ljava/lang/Class;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedNavigableMap;->nm:Ljava/util/NavigableMap;
+Ljava/util/Collections$CheckedNavigableSet;-><init>(Ljava/util/NavigableSet;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedNavigableSet;->ns:Ljava/util/NavigableSet;
+Ljava/util/Collections$CheckedQueue;-><init>(Ljava/util/Queue;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedQueue;->queue:Ljava/util/Queue;
+Ljava/util/Collections$CheckedRandomAccessList;-><init>(Ljava/util/List;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedSet;-><init>(Ljava/util/Set;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedSortedMap;-><init>(Ljava/util/SortedMap;Ljava/lang/Class;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedSortedMap;->sm:Ljava/util/SortedMap;
+Ljava/util/Collections$CheckedSortedSet;-><init>(Ljava/util/SortedSet;Ljava/lang/Class;)V
+Ljava/util/Collections$CheckedSortedSet;->ss:Ljava/util/SortedSet;
+Ljava/util/Collections$CopiesList;-><init>(ILjava/lang/Object;)V
+Ljava/util/Collections$CopiesList;->element:Ljava/lang/Object;
+Ljava/util/Collections$CopiesList;->n:I
+Ljava/util/Collections$EmptyEnumeration;-><init>()V
+Ljava/util/Collections$EmptyEnumeration;->EMPTY_ENUMERATION:Ljava/util/Collections$EmptyEnumeration;
+Ljava/util/Collections$EmptyIterator;-><init>()V
+Ljava/util/Collections$EmptyIterator;->EMPTY_ITERATOR:Ljava/util/Collections$EmptyIterator;
+Ljava/util/Collections$EmptyList;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$EmptyListIterator;-><init>()V
+Ljava/util/Collections$EmptyListIterator;->EMPTY_ITERATOR:Ljava/util/Collections$EmptyListIterator;
+Ljava/util/Collections$EmptySet;-><init>()V
+Ljava/util/Collections$EmptySet;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$ReverseComparator2;-><init>(Ljava/util/Comparator;)V
+Ljava/util/Collections$ReverseComparator2;->cmp:Ljava/util/Comparator;
+Ljava/util/Collections$ReverseComparator;-><init>()V
+Ljava/util/Collections$ReverseComparator;->compare(Ljava/lang/Comparable;Ljava/lang/Comparable;)I
+Ljava/util/Collections$ReverseComparator;->REVERSE_ORDER:Ljava/util/Collections$ReverseComparator;
+Ljava/util/Collections$SetFromMap;-><init>(Ljava/util/Map;)V
+Ljava/util/Collections$SetFromMap;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$SetFromMap;->m:Ljava/util/Map;
+Ljava/util/Collections$SetFromMap;->s:Ljava/util/Set;
+Ljava/util/Collections$SingletonList;-><init>(Ljava/lang/Object;)V
+Ljava/util/Collections$SingletonList;->element:Ljava/lang/Object;
+Ljava/util/Collections$SingletonList;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$SingletonMap;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
+Ljava/util/Collections$SingletonMap;->entrySet:Ljava/util/Set;
+Ljava/util/Collections$SingletonMap;->k:Ljava/lang/Object;
+Ljava/util/Collections$SingletonMap;->keySet:Ljava/util/Set;
+Ljava/util/Collections$SingletonMap;->v:Ljava/lang/Object;
+Ljava/util/Collections$SingletonMap;->values:Ljava/util/Collection;
+Ljava/util/Collections$SingletonSet;-><init>(Ljava/lang/Object;)V
+Ljava/util/Collections$SingletonSet;->element:Ljava/lang/Object;
+Ljava/util/Collections$SingletonSet;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$SynchronizedCollection;-><init>(Ljava/util/Collection;)V
+Ljava/util/Collections$SynchronizedCollection;-><init>(Ljava/util/Collection;Ljava/lang/Object;)V
+Ljava/util/Collections$SynchronizedCollection;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$SynchronizedCollection;->mutex:Ljava/lang/Object;
+Ljava/util/Collections$SynchronizedList;-><init>(Ljava/util/List;)V
+Ljava/util/Collections$SynchronizedList;-><init>(Ljava/util/List;Ljava/lang/Object;)V
+Ljava/util/Collections$SynchronizedMap;-><init>(Ljava/util/Map;)V
+Ljava/util/Collections$SynchronizedMap;-><init>(Ljava/util/Map;Ljava/lang/Object;)V
+Ljava/util/Collections$SynchronizedMap;->entrySet:Ljava/util/Set;
+Ljava/util/Collections$SynchronizedMap;->keySet:Ljava/util/Set;
+Ljava/util/Collections$SynchronizedMap;->mutex:Ljava/lang/Object;
+Ljava/util/Collections$SynchronizedMap;->values:Ljava/util/Collection;
+Ljava/util/Collections$SynchronizedNavigableMap;-><init>(Ljava/util/NavigableMap;)V
+Ljava/util/Collections$SynchronizedNavigableMap;-><init>(Ljava/util/NavigableMap;Ljava/lang/Object;)V
+Ljava/util/Collections$SynchronizedNavigableMap;->nm:Ljava/util/NavigableMap;
+Ljava/util/Collections$SynchronizedNavigableSet;-><init>(Ljava/util/NavigableSet;)V
+Ljava/util/Collections$SynchronizedNavigableSet;-><init>(Ljava/util/NavigableSet;Ljava/lang/Object;)V
+Ljava/util/Collections$SynchronizedNavigableSet;->ns:Ljava/util/NavigableSet;
+Ljava/util/Collections$SynchronizedRandomAccessList;-><init>(Ljava/util/List;)V
+Ljava/util/Collections$SynchronizedRandomAccessList;-><init>(Ljava/util/List;Ljava/lang/Object;)V
+Ljava/util/Collections$SynchronizedSet;-><init>(Ljava/util/Set;)V
+Ljava/util/Collections$SynchronizedSet;-><init>(Ljava/util/Set;Ljava/lang/Object;)V
+Ljava/util/Collections$SynchronizedSortedMap;-><init>(Ljava/util/SortedMap;)V
+Ljava/util/Collections$SynchronizedSortedMap;-><init>(Ljava/util/SortedMap;Ljava/lang/Object;)V
+Ljava/util/Collections$SynchronizedSortedMap;->sm:Ljava/util/SortedMap;
+Ljava/util/Collections$SynchronizedSortedSet;-><init>(Ljava/util/SortedSet;)V
+Ljava/util/Collections$SynchronizedSortedSet;-><init>(Ljava/util/SortedSet;Ljava/lang/Object;)V
+Ljava/util/Collections$SynchronizedSortedSet;->ss:Ljava/util/SortedSet;
+Ljava/util/Collections$UnmodifiableCollection;-><init>(Ljava/util/Collection;)V
+Ljava/util/Collections$UnmodifiableCollection;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$UnmodifiableList;-><init>(Ljava/util/List;)V
+Ljava/util/Collections$UnmodifiableList;->list:Ljava/util/List;
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry;-><init>(Ljava/util/Map$Entry;)V
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry;->e:Ljava/util/Map$Entry;
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntrySetSpliterator;-><init>(Ljava/util/Spliterator;)V
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntrySetSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntrySetSpliterator;->s:Ljava/util/Spliterator;
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntrySetSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet;-><init>(Ljava/util/Set;)V
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet;->entryConsumer(Ljava/util/function/Consumer;)Ljava/util/function/Consumer;
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/Collections$UnmodifiableMap;-><init>(Ljava/util/Map;)V
+Ljava/util/Collections$UnmodifiableMap;->entrySet:Ljava/util/Set;
+Ljava/util/Collections$UnmodifiableMap;->keySet:Ljava/util/Set;
+Ljava/util/Collections$UnmodifiableMap;->values:Ljava/util/Collection;
+Ljava/util/Collections$UnmodifiableNavigableMap$EmptyNavigableMap;-><init>()V
+Ljava/util/Collections$UnmodifiableNavigableMap;-><init>(Ljava/util/NavigableMap;)V
+Ljava/util/Collections$UnmodifiableNavigableMap;->EMPTY_NAVIGABLE_MAP:Ljava/util/Collections$UnmodifiableNavigableMap$EmptyNavigableMap;
+Ljava/util/Collections$UnmodifiableNavigableMap;->nm:Ljava/util/NavigableMap;
+Ljava/util/Collections$UnmodifiableNavigableSet$EmptyNavigableSet;-><init>()V
+Ljava/util/Collections$UnmodifiableNavigableSet;-><init>(Ljava/util/NavigableSet;)V
+Ljava/util/Collections$UnmodifiableNavigableSet;->EMPTY_NAVIGABLE_SET:Ljava/util/NavigableSet;
+Ljava/util/Collections$UnmodifiableNavigableSet;->ns:Ljava/util/NavigableSet;
+Ljava/util/Collections$UnmodifiableRandomAccessList;-><init>(Ljava/util/List;)V
+Ljava/util/Collections$UnmodifiableSet;-><init>(Ljava/util/Set;)V
+Ljava/util/Collections$UnmodifiableSortedMap;-><init>(Ljava/util/SortedMap;)V
+Ljava/util/Collections$UnmodifiableSortedMap;->sm:Ljava/util/SortedMap;
+Ljava/util/Collections$UnmodifiableSortedSet;-><init>(Ljava/util/SortedSet;)V
+Ljava/util/Collections$UnmodifiableSortedSet;->ss:Ljava/util/SortedSet;
+Ljava/util/Collections;-><init>()V
+Ljava/util/Collections;->BINARYSEARCH_THRESHOLD:I
+Ljava/util/Collections;->COPY_THRESHOLD:I
+Ljava/util/Collections;->eq(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/Collections;->FILL_THRESHOLD:I
+Ljava/util/Collections;->get(Ljava/util/ListIterator;I)Ljava/lang/Object;
+Ljava/util/Collections;->indexedBinarySearch(Ljava/util/List;Ljava/lang/Object;)I
+Ljava/util/Collections;->indexedBinarySearch(Ljava/util/List;Ljava/lang/Object;Ljava/util/Comparator;)I
+Ljava/util/Collections;->INDEXOFSUBLIST_THRESHOLD:I
+Ljava/util/Collections;->iteratorBinarySearch(Ljava/util/List;Ljava/lang/Object;)I
+Ljava/util/Collections;->iteratorBinarySearch(Ljava/util/List;Ljava/lang/Object;Ljava/util/Comparator;)I
+Ljava/util/Collections;->r:Ljava/util/Random;
+Ljava/util/Collections;->REPLACEALL_THRESHOLD:I
+Ljava/util/Collections;->REVERSE_THRESHOLD:I
+Ljava/util/Collections;->rotate1(Ljava/util/List;I)V
+Ljava/util/Collections;->rotate2(Ljava/util/List;I)V
+Ljava/util/Collections;->ROTATE_THRESHOLD:I
+Ljava/util/Collections;->SHUFFLE_THRESHOLD:I
+Ljava/util/Collections;->singletonIterator(Ljava/lang/Object;)Ljava/util/Iterator;
+Ljava/util/Collections;->singletonSpliterator(Ljava/lang/Object;)Ljava/util/Spliterator;
+Ljava/util/Collections;->swap([Ljava/lang/Object;II)V
+Ljava/util/Collections;->synchronizedCollection(Ljava/util/Collection;Ljava/lang/Object;)Ljava/util/Collection;
+Ljava/util/Collections;->synchronizedList(Ljava/util/List;Ljava/lang/Object;)Ljava/util/List;
+Ljava/util/Collections;->synchronizedSet(Ljava/util/Set;Ljava/lang/Object;)Ljava/util/Set;
+Ljava/util/Collections;->zeroLengthArray(Ljava/lang/Class;)[Ljava/lang/Object;
+Ljava/util/concurrent/AbstractExecutorService;->cancelAll(Ljava/util/ArrayList;)V
+Ljava/util/concurrent/AbstractExecutorService;->cancelAll(Ljava/util/ArrayList;I)V
+Ljava/util/concurrent/AbstractExecutorService;->doInvokeAny(Ljava/util/Collection;ZJ)Ljava/lang/Object;
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->cursor:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->detach()V
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->DETACHED:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->distance(III)I
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->incCursor(I)I
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->incorporateDequeues()V
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->invalidated(IIJI)Z
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->isDetached()Z
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->lastItem:Ljava/lang/Object;
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->lastRet:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->nextIndex:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->nextItem:Ljava/lang/Object;
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->NONE:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->noNext()V
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->prevCycles:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->prevTakeIndex:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->REMOVED:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->removedAt(I)Z
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->shutdown()V
+Ljava/util/concurrent/ArrayBlockingQueue$Itr;->takeIndexWrapped()Z
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs$Node;->next:Ljava/util/concurrent/ArrayBlockingQueue$Itrs$Node;
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->cycles:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->doSomeSweeping(Z)V
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->elementDequeued()V
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->head:Ljava/util/concurrent/ArrayBlockingQueue$Itrs$Node;
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->LONG_SWEEP_PROBES:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->queueIsEmpty()V
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->register(Ljava/util/concurrent/ArrayBlockingQueue$Itr;)V
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->removedAt(I)V
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->SHORT_SWEEP_PROBES:I
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->sweeper:Ljava/util/concurrent/ArrayBlockingQueue$Itrs$Node;
+Ljava/util/concurrent/ArrayBlockingQueue$Itrs;->takeIndexWrapped()V
+Ljava/util/concurrent/ArrayBlockingQueue;->count:I
+Ljava/util/concurrent/ArrayBlockingQueue;->dec(I)I
+Ljava/util/concurrent/ArrayBlockingQueue;->dequeue()Ljava/lang/Object;
+Ljava/util/concurrent/ArrayBlockingQueue;->enqueue(Ljava/lang/Object;)V
+Ljava/util/concurrent/ArrayBlockingQueue;->itemAt(I)Ljava/lang/Object;
+Ljava/util/concurrent/ArrayBlockingQueue;->items:[Ljava/lang/Object;
+Ljava/util/concurrent/ArrayBlockingQueue;->itrs:Ljava/util/concurrent/ArrayBlockingQueue$Itrs;
+Ljava/util/concurrent/ArrayBlockingQueue;->lock:Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/util/concurrent/ArrayBlockingQueue;->notEmpty:Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/ArrayBlockingQueue;->notFull:Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/ArrayBlockingQueue;->putIndex:I
+Ljava/util/concurrent/ArrayBlockingQueue;->removeAt(I)V
+Ljava/util/concurrent/ArrayBlockingQueue;->takeIndex:I
+Ljava/util/concurrent/atomic/AtomicBoolean;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicBoolean;->value:I
+Ljava/util/concurrent/atomic/AtomicBoolean;->VALUE:J
+Ljava/util/concurrent/atomic/AtomicInteger;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicInteger;->VALUE:J
+Ljava/util/concurrent/atomic/AtomicIntegerArray;->ABASE:I
+Ljava/util/concurrent/atomic/AtomicIntegerArray;->array:[I
+Ljava/util/concurrent/atomic/AtomicIntegerArray;->ASHIFT:I
+Ljava/util/concurrent/atomic/AtomicIntegerArray;->byteOffset(I)J
+Ljava/util/concurrent/atomic/AtomicIntegerArray;->checkedByteOffset(I)J
+Ljava/util/concurrent/atomic/AtomicIntegerArray;->compareAndSetRaw(JII)Z
+Ljava/util/concurrent/atomic/AtomicIntegerArray;->getRaw(J)I
+Ljava/util/concurrent/atomic/AtomicIntegerArray;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;-><init>(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)V
+Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->accessCheck(Ljava/lang/Object;)V
+Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->cclass:Ljava/lang/Class;
+Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->offset:J
+Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->tclass:Ljava/lang/Class;
+Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->throwAccessCheckException(Ljava/lang/Object;)V
+Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicLong;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicLong;->VALUE:J
+Ljava/util/concurrent/atomic/AtomicLong;->value:J
+Ljava/util/concurrent/atomic/AtomicLong;->VMSupportsCS8()Z
+Ljava/util/concurrent/atomic/AtomicLong;->VM_SUPPORTS_LONG_CAS:Z
+Ljava/util/concurrent/atomic/AtomicLongArray;->ABASE:I
+Ljava/util/concurrent/atomic/AtomicLongArray;->array:[J
+Ljava/util/concurrent/atomic/AtomicLongArray;->ASHIFT:I
+Ljava/util/concurrent/atomic/AtomicLongArray;->byteOffset(I)J
+Ljava/util/concurrent/atomic/AtomicLongArray;->checkedByteOffset(I)J
+Ljava/util/concurrent/atomic/AtomicLongArray;->compareAndSetRaw(JJJ)Z
+Ljava/util/concurrent/atomic/AtomicLongArray;->getRaw(J)J
+Ljava/util/concurrent/atomic/AtomicLongArray;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;-><init>(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)V
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->accessCheck(Ljava/lang/Object;)V
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->cclass:Ljava/lang/Class;
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->offset:J
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->tclass:Ljava/lang/Class;
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->throwAccessCheckException(Ljava/lang/Object;)V
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater;-><init>(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)V
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater;->accessCheck(Ljava/lang/Object;)V
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater;->accessCheckException(Ljava/lang/Object;)Ljava/lang/RuntimeException;
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater;->cclass:Ljava/lang/Class;
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater;->offset:J
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater;->tclass:Ljava/lang/Class;
+Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicMarkableReference$Pair;-><init>(Ljava/lang/Object;Z)V
+Ljava/util/concurrent/atomic/AtomicMarkableReference$Pair;->mark:Z
+Ljava/util/concurrent/atomic/AtomicMarkableReference$Pair;->of(Ljava/lang/Object;Z)Ljava/util/concurrent/atomic/AtomicMarkableReference$Pair;
+Ljava/util/concurrent/atomic/AtomicMarkableReference$Pair;->reference:Ljava/lang/Object;
+Ljava/util/concurrent/atomic/AtomicMarkableReference;->casPair(Ljava/util/concurrent/atomic/AtomicMarkableReference$Pair;Ljava/util/concurrent/atomic/AtomicMarkableReference$Pair;)Z
+Ljava/util/concurrent/atomic/AtomicMarkableReference;->PAIR:J
+Ljava/util/concurrent/atomic/AtomicMarkableReference;->pair:Ljava/util/concurrent/atomic/AtomicMarkableReference$Pair;
+Ljava/util/concurrent/atomic/AtomicMarkableReference;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicReference;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicReference;->VALUE:J
+Ljava/util/concurrent/atomic/AtomicReference;->value:Ljava/lang/Object;
+Ljava/util/concurrent/atomic/AtomicReferenceArray;->ABASE:I
+Ljava/util/concurrent/atomic/AtomicReferenceArray;->ARRAY:J
+Ljava/util/concurrent/atomic/AtomicReferenceArray;->array:[Ljava/lang/Object;
+Ljava/util/concurrent/atomic/AtomicReferenceArray;->ASHIFT:I
+Ljava/util/concurrent/atomic/AtomicReferenceArray;->byteOffset(I)J
+Ljava/util/concurrent/atomic/AtomicReferenceArray;->checkedByteOffset(I)J
+Ljava/util/concurrent/atomic/AtomicReferenceArray;->compareAndSetRaw(JLjava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/concurrent/atomic/AtomicReferenceArray;->getRaw(J)Ljava/lang/Object;
+Ljava/util/concurrent/atomic/AtomicReferenceArray;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;-><init>(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)V
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->accessCheck(Ljava/lang/Object;)V
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->cclass:Ljava/lang/Class;
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->offset:J
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->tclass:Ljava/lang/Class;
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->throwAccessCheckException(Ljava/lang/Object;)V
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->throwCCE()V
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->valueCheck(Ljava/lang/Object;)V
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;->vclass:Ljava/lang/Class;
+Ljava/util/concurrent/atomic/AtomicStampedReference$Pair;-><init>(Ljava/lang/Object;I)V
+Ljava/util/concurrent/atomic/AtomicStampedReference$Pair;->of(Ljava/lang/Object;I)Ljava/util/concurrent/atomic/AtomicStampedReference$Pair;
+Ljava/util/concurrent/atomic/AtomicStampedReference$Pair;->reference:Ljava/lang/Object;
+Ljava/util/concurrent/atomic/AtomicStampedReference$Pair;->stamp:I
+Ljava/util/concurrent/atomic/AtomicStampedReference;->casPair(Ljava/util/concurrent/atomic/AtomicStampedReference$Pair;Ljava/util/concurrent/atomic/AtomicStampedReference$Pair;)Z
+Ljava/util/concurrent/atomic/AtomicStampedReference;->PAIR:J
+Ljava/util/concurrent/atomic/AtomicStampedReference;->pair:Ljava/util/concurrent/atomic/AtomicStampedReference$Pair;
+Ljava/util/concurrent/atomic/AtomicStampedReference;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/DoubleAccumulator$SerializationProxy;-><init>(DLjava/util/function/DoubleBinaryOperator;J)V
+Ljava/util/concurrent/atomic/DoubleAccumulator$SerializationProxy;->function:Ljava/util/function/DoubleBinaryOperator;
+Ljava/util/concurrent/atomic/DoubleAccumulator$SerializationProxy;->identity:J
+Ljava/util/concurrent/atomic/DoubleAccumulator$SerializationProxy;->value:D
+Ljava/util/concurrent/atomic/DoubleAccumulator;->function:Ljava/util/function/DoubleBinaryOperator;
+Ljava/util/concurrent/atomic/DoubleAccumulator;->identity:J
+Ljava/util/concurrent/atomic/DoubleAdder$SerializationProxy;-><init>(Ljava/util/concurrent/atomic/DoubleAdder;)V
+Ljava/util/concurrent/atomic/DoubleAdder$SerializationProxy;->value:D
+Ljava/util/concurrent/atomic/LongAccumulator$SerializationProxy;-><init>(JLjava/util/function/LongBinaryOperator;J)V
+Ljava/util/concurrent/atomic/LongAccumulator$SerializationProxy;->function:Ljava/util/function/LongBinaryOperator;
+Ljava/util/concurrent/atomic/LongAccumulator$SerializationProxy;->identity:J
+Ljava/util/concurrent/atomic/LongAccumulator$SerializationProxy;->value:J
+Ljava/util/concurrent/atomic/LongAccumulator;->function:Ljava/util/function/LongBinaryOperator;
+Ljava/util/concurrent/atomic/LongAccumulator;->identity:J
+Ljava/util/concurrent/atomic/LongAdder$SerializationProxy;-><init>(Ljava/util/concurrent/atomic/LongAdder;)V
+Ljava/util/concurrent/atomic/LongAdder$SerializationProxy;->value:J
+Ljava/util/concurrent/atomic/Striped64$Cell;-><init>(J)V
+Ljava/util/concurrent/atomic/Striped64$Cell;->cas(JJ)Z
+Ljava/util/concurrent/atomic/Striped64$Cell;->reset()V
+Ljava/util/concurrent/atomic/Striped64$Cell;->reset(J)V
+Ljava/util/concurrent/atomic/Striped64$Cell;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/atomic/Striped64$Cell;->VALUE:J
+Ljava/util/concurrent/atomic/Striped64$Cell;->value:J
+Ljava/util/concurrent/atomic/Striped64;-><init>()V
+Ljava/util/concurrent/atomic/Striped64;->advanceProbe(I)I
+Ljava/util/concurrent/atomic/Striped64;->apply(Ljava/util/function/DoubleBinaryOperator;JD)J
+Ljava/util/concurrent/atomic/Striped64;->BASE:J
+Ljava/util/concurrent/atomic/Striped64;->base:J
+Ljava/util/concurrent/atomic/Striped64;->casBase(JJ)Z
+Ljava/util/concurrent/atomic/Striped64;->casCellsBusy()Z
+Ljava/util/concurrent/atomic/Striped64;->cells:[Ljava/util/concurrent/atomic/Striped64$Cell;
+Ljava/util/concurrent/atomic/Striped64;->cellsBusy:I
+Ljava/util/concurrent/atomic/Striped64;->CELLSBUSY:J
+Ljava/util/concurrent/atomic/Striped64;->doubleAccumulate(DLjava/util/function/DoubleBinaryOperator;Z)V
+Ljava/util/concurrent/atomic/Striped64;->getProbe()I
+Ljava/util/concurrent/atomic/Striped64;->longAccumulate(JLjava/util/function/LongBinaryOperator;Z)V
+Ljava/util/concurrent/atomic/Striped64;->NCPU:I
+Ljava/util/concurrent/atomic/Striped64;->PROBE:J
+Ljava/util/concurrent/atomic/Striped64;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/CompletableFuture$AltResult;-><init>(Ljava/lang/Throwable;)V
+Ljava/util/concurrent/CompletableFuture$AltResult;->ex:Ljava/lang/Throwable;
+Ljava/util/concurrent/CompletableFuture$AsyncRun;-><init>(Ljava/util/concurrent/CompletableFuture;Ljava/lang/Runnable;)V
+Ljava/util/concurrent/CompletableFuture$AsyncRun;->dep:Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$AsyncRun;->fn:Ljava/lang/Runnable;
+Ljava/util/concurrent/CompletableFuture$AsyncRun;->setRawResult(Ljava/lang/Void;)V
+Ljava/util/concurrent/CompletableFuture$AsyncSupply;-><init>(Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Supplier;)V
+Ljava/util/concurrent/CompletableFuture$AsyncSupply;->dep:Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$AsyncSupply;->fn:Ljava/util/function/Supplier;
+Ljava/util/concurrent/CompletableFuture$AsyncSupply;->setRawResult(Ljava/lang/Void;)V
+Ljava/util/concurrent/CompletableFuture$BiAccept;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/BiConsumer;)V
+Ljava/util/concurrent/CompletableFuture$BiAccept;->fn:Ljava/util/function/BiConsumer;
+Ljava/util/concurrent/CompletableFuture$BiAccept;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$BiApply;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/BiFunction;)V
+Ljava/util/concurrent/CompletableFuture$BiApply;->fn:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/CompletableFuture$BiApply;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$BiCompletion;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;)V
+Ljava/util/concurrent/CompletableFuture$BiCompletion;->snd:Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$BiRelay;-><init>(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;)V
+Ljava/util/concurrent/CompletableFuture$BiRelay;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$BiRun;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/lang/Runnable;)V
+Ljava/util/concurrent/CompletableFuture$BiRun;->fn:Ljava/lang/Runnable;
+Ljava/util/concurrent/CompletableFuture$BiRun;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$Canceller;-><init>(Ljava/util/concurrent/Future;)V
+Ljava/util/concurrent/CompletableFuture$Canceller;->accept(Ljava/lang/Object;Ljava/lang/Throwable;)V
+Ljava/util/concurrent/CompletableFuture$Canceller;->f:Ljava/util/concurrent/Future;
+Ljava/util/concurrent/CompletableFuture$CoCompletion;-><init>(Ljava/util/concurrent/CompletableFuture$BiCompletion;)V
+Ljava/util/concurrent/CompletableFuture$CoCompletion;->base:Ljava/util/concurrent/CompletableFuture$BiCompletion;
+Ljava/util/concurrent/CompletableFuture$CoCompletion;->isLive()Z
+Ljava/util/concurrent/CompletableFuture$CoCompletion;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$Completion;-><init>()V
+Ljava/util/concurrent/CompletableFuture$Completion;->isLive()Z
+Ljava/util/concurrent/CompletableFuture$Completion;->next:Ljava/util/concurrent/CompletableFuture$Completion;
+Ljava/util/concurrent/CompletableFuture$Completion;->setRawResult(Ljava/lang/Void;)V
+Ljava/util/concurrent/CompletableFuture$Completion;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$DelayedCompleter;-><init>(Ljava/util/concurrent/CompletableFuture;Ljava/lang/Object;)V
+Ljava/util/concurrent/CompletableFuture$DelayedCompleter;->f:Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$DelayedCompleter;->u:Ljava/lang/Object;
+Ljava/util/concurrent/CompletableFuture$DelayedExecutor;-><init>(JLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/Executor;)V
+Ljava/util/concurrent/CompletableFuture$DelayedExecutor;->delay:J
+Ljava/util/concurrent/CompletableFuture$DelayedExecutor;->executor:Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/CompletableFuture$DelayedExecutor;->unit:Ljava/util/concurrent/TimeUnit;
+Ljava/util/concurrent/CompletableFuture$Delayer$DaemonThreadFactory;-><init>()V
+Ljava/util/concurrent/CompletableFuture$Delayer;-><init>()V
+Ljava/util/concurrent/CompletableFuture$Delayer;->delay(Ljava/lang/Runnable;JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/ScheduledFuture;
+Ljava/util/concurrent/CompletableFuture$Delayer;->delayer:Ljava/util/concurrent/ScheduledThreadPoolExecutor;
+Ljava/util/concurrent/CompletableFuture$MinimalStage;-><init>()V
+Ljava/util/concurrent/CompletableFuture$MinimalStage;-><init>(Ljava/lang/Object;)V
+Ljava/util/concurrent/CompletableFuture$MinimalStage;->completeAsync(Ljava/util/function/Supplier;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$MinimalStage;->completeAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$MinimalStage;->completeOnTimeout(Ljava/lang/Object;JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$MinimalStage;->newIncompleteFuture()Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$MinimalStage;->orTimeout(JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$OrAccept;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/CompletableFuture$OrAccept;->fn:Ljava/util/function/Consumer;
+Ljava/util/concurrent/CompletableFuture$OrAccept;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$OrApply;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Function;)V
+Ljava/util/concurrent/CompletableFuture$OrApply;->fn:Ljava/util/function/Function;
+Ljava/util/concurrent/CompletableFuture$OrApply;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$OrRelay;-><init>(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;)V
+Ljava/util/concurrent/CompletableFuture$OrRelay;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$OrRun;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/lang/Runnable;)V
+Ljava/util/concurrent/CompletableFuture$OrRun;->fn:Ljava/lang/Runnable;
+Ljava/util/concurrent/CompletableFuture$OrRun;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$Signaller;-><init>(ZJJ)V
+Ljava/util/concurrent/CompletableFuture$Signaller;->deadline:J
+Ljava/util/concurrent/CompletableFuture$Signaller;->interrupted:Z
+Ljava/util/concurrent/CompletableFuture$Signaller;->interruptible:Z
+Ljava/util/concurrent/CompletableFuture$Signaller;->isLive()Z
+Ljava/util/concurrent/CompletableFuture$Signaller;->nanos:J
+Ljava/util/concurrent/CompletableFuture$Signaller;->thread:Ljava/lang/Thread;
+Ljava/util/concurrent/CompletableFuture$Signaller;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$TaskSubmitter;-><init>(Ljava/util/concurrent/Executor;Ljava/lang/Runnable;)V
+Ljava/util/concurrent/CompletableFuture$TaskSubmitter;->action:Ljava/lang/Runnable;
+Ljava/util/concurrent/CompletableFuture$TaskSubmitter;->executor:Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/CompletableFuture$ThreadPerTaskExecutor;-><init>()V
+Ljava/util/concurrent/CompletableFuture$Timeout;-><init>(Ljava/util/concurrent/CompletableFuture;)V
+Ljava/util/concurrent/CompletableFuture$Timeout;->f:Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$UniAccept;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/CompletableFuture$UniAccept;->fn:Ljava/util/function/Consumer;
+Ljava/util/concurrent/CompletableFuture$UniAccept;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$UniApply;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Function;)V
+Ljava/util/concurrent/CompletableFuture$UniApply;->fn:Ljava/util/function/Function;
+Ljava/util/concurrent/CompletableFuture$UniApply;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$UniCompletion;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;)V
+Ljava/util/concurrent/CompletableFuture$UniCompletion;->claim()Z
+Ljava/util/concurrent/CompletableFuture$UniCompletion;->dep:Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$UniCompletion;->executor:Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/CompletableFuture$UniCompletion;->isLive()Z
+Ljava/util/concurrent/CompletableFuture$UniCompletion;->src:Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$UniCompose;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Function;)V
+Ljava/util/concurrent/CompletableFuture$UniCompose;->fn:Ljava/util/function/Function;
+Ljava/util/concurrent/CompletableFuture$UniCompose;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$UniExceptionally;-><init>(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Function;)V
+Ljava/util/concurrent/CompletableFuture$UniExceptionally;->fn:Ljava/util/function/Function;
+Ljava/util/concurrent/CompletableFuture$UniExceptionally;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$UniHandle;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/BiFunction;)V
+Ljava/util/concurrent/CompletableFuture$UniHandle;->fn:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/CompletableFuture$UniHandle;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$UniRelay;-><init>(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;)V
+Ljava/util/concurrent/CompletableFuture$UniRelay;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$UniRun;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/lang/Runnable;)V
+Ljava/util/concurrent/CompletableFuture$UniRun;->fn:Ljava/lang/Runnable;
+Ljava/util/concurrent/CompletableFuture$UniRun;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$UniWhenComplete;-><init>(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/BiConsumer;)V
+Ljava/util/concurrent/CompletableFuture$UniWhenComplete;->fn:Ljava/util/function/BiConsumer;
+Ljava/util/concurrent/CompletableFuture$UniWhenComplete;->tryFire(I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;-><init>(Ljava/lang/Object;)V
+Ljava/util/concurrent/CompletableFuture;->andTree([Ljava/util/concurrent/CompletableFuture;II)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->ASYNC:I
+Ljava/util/concurrent/CompletableFuture;->asyncRunStage(Ljava/util/concurrent/Executor;Ljava/lang/Runnable;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->asyncSupplyStage(Ljava/util/concurrent/Executor;Ljava/util/function/Supplier;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->ASYNC_POOL:Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/CompletableFuture;->biAccept(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/BiConsumer;Ljava/util/concurrent/CompletableFuture$BiAccept;)Z
+Ljava/util/concurrent/CompletableFuture;->biAcceptStage(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletionStage;Ljava/util/function/BiConsumer;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->biApply(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/BiFunction;Ljava/util/concurrent/CompletableFuture$BiApply;)Z
+Ljava/util/concurrent/CompletableFuture;->biApplyStage(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletionStage;Ljava/util/function/BiFunction;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->bipush(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture$BiCompletion;)V
+Ljava/util/concurrent/CompletableFuture;->biRelay(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;)Z
+Ljava/util/concurrent/CompletableFuture;->biRun(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/lang/Runnable;Ljava/util/concurrent/CompletableFuture$BiRun;)Z
+Ljava/util/concurrent/CompletableFuture;->biRunStage(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletionStage;Ljava/lang/Runnable;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->casStack(Ljava/util/concurrent/CompletableFuture$Completion;Ljava/util/concurrent/CompletableFuture$Completion;)Z
+Ljava/util/concurrent/CompletableFuture;->cleanStack()V
+Ljava/util/concurrent/CompletableFuture;->completeAsync(Ljava/util/function/Supplier;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->completeAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->completedStage(Ljava/lang/Object;)Ljava/util/concurrent/CompletionStage;
+Ljava/util/concurrent/CompletableFuture;->completeNull()Z
+Ljava/util/concurrent/CompletableFuture;->completeOnTimeout(Ljava/lang/Object;JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->completeRelay(Ljava/lang/Object;)Z
+Ljava/util/concurrent/CompletableFuture;->completeThrowable(Ljava/lang/Throwable;)Z
+Ljava/util/concurrent/CompletableFuture;->completeThrowable(Ljava/lang/Throwable;Ljava/lang/Object;)Z
+Ljava/util/concurrent/CompletableFuture;->completeValue(Ljava/lang/Object;)Z
+Ljava/util/concurrent/CompletableFuture;->copy()Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->defaultExecutor()Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/CompletableFuture;->delayedExecutor(JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/CompletableFuture;->delayedExecutor(JLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/CompletableFuture;->encodeOutcome(Ljava/lang/Object;Ljava/lang/Throwable;)Ljava/lang/Object;
+Ljava/util/concurrent/CompletableFuture;->encodeRelay(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/CompletableFuture;->encodeThrowable(Ljava/lang/Throwable;)Ljava/util/concurrent/CompletableFuture$AltResult;
+Ljava/util/concurrent/CompletableFuture;->encodeThrowable(Ljava/lang/Throwable;Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/CompletableFuture;->encodeValue(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/CompletableFuture;->failedFuture(Ljava/lang/Throwable;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->failedStage(Ljava/lang/Throwable;)Ljava/util/concurrent/CompletionStage;
+Ljava/util/concurrent/CompletableFuture;->internalComplete(Ljava/lang/Object;)Z
+Ljava/util/concurrent/CompletableFuture;->lazySetNext(Ljava/util/concurrent/CompletableFuture$Completion;Ljava/util/concurrent/CompletableFuture$Completion;)V
+Ljava/util/concurrent/CompletableFuture;->minimalCompletionStage()Ljava/util/concurrent/CompletionStage;
+Ljava/util/concurrent/CompletableFuture;->NESTED:I
+Ljava/util/concurrent/CompletableFuture;->newIncompleteFuture()Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->NEXT:J
+Ljava/util/concurrent/CompletableFuture;->NIL:Ljava/util/concurrent/CompletableFuture$AltResult;
+Ljava/util/concurrent/CompletableFuture;->orAccept(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Consumer;Ljava/util/concurrent/CompletableFuture$OrAccept;)Z
+Ljava/util/concurrent/CompletableFuture;->orAcceptStage(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletionStage;Ljava/util/function/Consumer;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->orApply(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Function;Ljava/util/concurrent/CompletableFuture$OrApply;)Z
+Ljava/util/concurrent/CompletableFuture;->orApplyStage(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletionStage;Ljava/util/function/Function;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->orpush(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture$BiCompletion;)V
+Ljava/util/concurrent/CompletableFuture;->orRelay(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;)Z
+Ljava/util/concurrent/CompletableFuture;->orRun(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;Ljava/lang/Runnable;Ljava/util/concurrent/CompletableFuture$OrRun;)Z
+Ljava/util/concurrent/CompletableFuture;->orRunStage(Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletionStage;Ljava/lang/Runnable;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->orTimeout(JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->orTree([Ljava/util/concurrent/CompletableFuture;II)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->postComplete()V
+Ljava/util/concurrent/CompletableFuture;->postFire(Ljava/util/concurrent/CompletableFuture;I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->postFire(Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;I)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->push(Ljava/util/concurrent/CompletableFuture$UniCompletion;)V
+Ljava/util/concurrent/CompletableFuture;->pushStack(Ljava/util/concurrent/CompletableFuture$Completion;)V
+Ljava/util/concurrent/CompletableFuture;->reportGet(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/CompletableFuture;->reportJoin(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/CompletableFuture;->RESULT:J
+Ljava/util/concurrent/CompletableFuture;->result:Ljava/lang/Object;
+Ljava/util/concurrent/CompletableFuture;->screenExecutor(Ljava/util/concurrent/Executor;)Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/CompletableFuture;->SPINS:I
+Ljava/util/concurrent/CompletableFuture;->STACK:J
+Ljava/util/concurrent/CompletableFuture;->stack:Ljava/util/concurrent/CompletableFuture$Completion;
+Ljava/util/concurrent/CompletableFuture;->SYNC:I
+Ljava/util/concurrent/CompletableFuture;->timedGet(J)Ljava/lang/Object;
+Ljava/util/concurrent/CompletableFuture;->tryPushStack(Ljava/util/concurrent/CompletableFuture$Completion;)Z
+Ljava/util/concurrent/CompletableFuture;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/CompletableFuture;->uniAccept(Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Consumer;Ljava/util/concurrent/CompletableFuture$UniAccept;)Z
+Ljava/util/concurrent/CompletableFuture;->uniAcceptStage(Ljava/util/concurrent/Executor;Ljava/util/function/Consumer;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->uniApply(Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Function;Ljava/util/concurrent/CompletableFuture$UniApply;)Z
+Ljava/util/concurrent/CompletableFuture;->uniApplyStage(Ljava/util/concurrent/Executor;Ljava/util/function/Function;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->uniAsMinimalStage()Ljava/util/concurrent/CompletableFuture$MinimalStage;
+Ljava/util/concurrent/CompletableFuture;->uniCompose(Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Function;Ljava/util/concurrent/CompletableFuture$UniCompose;)Z
+Ljava/util/concurrent/CompletableFuture;->uniComposeStage(Ljava/util/concurrent/Executor;Ljava/util/function/Function;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->uniCopyStage()Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->uniExceptionally(Ljava/util/concurrent/CompletableFuture;Ljava/util/function/Function;Ljava/util/concurrent/CompletableFuture$UniExceptionally;)Z
+Ljava/util/concurrent/CompletableFuture;->uniExceptionallyStage(Ljava/util/function/Function;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->uniHandle(Ljava/util/concurrent/CompletableFuture;Ljava/util/function/BiFunction;Ljava/util/concurrent/CompletableFuture$UniHandle;)Z
+Ljava/util/concurrent/CompletableFuture;->uniHandleStage(Ljava/util/concurrent/Executor;Ljava/util/function/BiFunction;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->uniRelay(Ljava/util/concurrent/CompletableFuture;)Z
+Ljava/util/concurrent/CompletableFuture;->uniRun(Ljava/util/concurrent/CompletableFuture;Ljava/lang/Runnable;Ljava/util/concurrent/CompletableFuture$UniRun;)Z
+Ljava/util/concurrent/CompletableFuture;->uniRunStage(Ljava/util/concurrent/Executor;Ljava/lang/Runnable;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->uniWhenComplete(Ljava/util/concurrent/CompletableFuture;Ljava/util/function/BiConsumer;Ljava/util/concurrent/CompletableFuture$UniWhenComplete;)Z
+Ljava/util/concurrent/CompletableFuture;->uniWhenCompleteStage(Ljava/util/concurrent/Executor;Ljava/util/function/BiConsumer;)Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture;->USE_COMMON_POOL:Z
+Ljava/util/concurrent/CompletableFuture;->waitingGet(Z)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$BaseIterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIILjava/util/concurrent/ConcurrentHashMap;)V
+Ljava/util/concurrent/ConcurrentHashMap$BaseIterator;->hasNext()Z
+Ljava/util/concurrent/ConcurrentHashMap$BaseIterator;->lastReturned:Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$BaseIterator;->map:Ljava/util/concurrent/ConcurrentHashMap;
+Ljava/util/concurrent/ConcurrentHashMap$BaseIterator;->remove()V
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;)V
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->advance()Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->baseIndex:I
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->baseLimit:I
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->baseSize:I
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->batch:I
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->index:I
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->next:Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->pushState([Ljava/util/concurrent/ConcurrentHashMap$Node;II)V
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->recoverState(I)V
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->spare:Ljava/util/concurrent/ConcurrentHashMap$TableStack;
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->stack:Ljava/util/concurrent/ConcurrentHashMap$TableStack;
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;->tab:[Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$CollectionView;-><init>(Ljava/util/concurrent/ConcurrentHashMap;)V
+Ljava/util/concurrent/ConcurrentHashMap$CollectionView;->getMap()Ljava/util/concurrent/ConcurrentHashMap;
+Ljava/util/concurrent/ConcurrentHashMap$CollectionView;->map:Ljava/util/concurrent/ConcurrentHashMap;
+Ljava/util/concurrent/ConcurrentHashMap$CollectionView;->OOME_MSG:Ljava/lang/String;
+Ljava/util/concurrent/ConcurrentHashMap$CounterCell;-><init>(J)V
+Ljava/util/concurrent/ConcurrentHashMap$CounterCell;->value:J
+Ljava/util/concurrent/ConcurrentHashMap$EntryIterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIILjava/util/concurrent/ConcurrentHashMap;)V
+Ljava/util/concurrent/ConcurrentHashMap$EntrySetView;-><init>(Ljava/util/concurrent/ConcurrentHashMap;)V
+Ljava/util/concurrent/ConcurrentHashMap$EntrySetView;->add(Ljava/util/Map$Entry;)Z
+Ljava/util/concurrent/ConcurrentHashMap$EntrySetView;->addAll(Ljava/util/Collection;)Z
+Ljava/util/concurrent/ConcurrentHashMap$EntrySetView;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$EntrySetView;->removeIf(Ljava/util/function/Predicate;)Z
+Ljava/util/concurrent/ConcurrentHashMap$EntrySpliterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIIJLjava/util/concurrent/ConcurrentHashMap;)V
+Ljava/util/concurrent/ConcurrentHashMap$EntrySpliterator;->est:J
+Ljava/util/concurrent/ConcurrentHashMap$EntrySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$EntrySpliterator;->map:Ljava/util/concurrent/ConcurrentHashMap;
+Ljava/util/concurrent/ConcurrentHashMap$EntrySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/ConcurrentHashMap$ForEachEntryTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$ForEachEntryTask;->action:Ljava/util/function/Consumer;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachKeyTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$ForEachKeyTask;->action:Ljava/util/function/Consumer;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachMappingTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/BiConsumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$ForEachMappingTask;->action:Ljava/util/function/BiConsumer;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedEntryTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Function;Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedEntryTask;->action:Ljava/util/function/Consumer;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedEntryTask;->transformer:Ljava/util/function/Function;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedKeyTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Function;Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedKeyTask;->action:Ljava/util/function/Consumer;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedKeyTask;->transformer:Ljava/util/function/Function;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedMappingTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/BiFunction;Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedMappingTask;->action:Ljava/util/function/Consumer;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedMappingTask;->transformer:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedValueTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Function;Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedValueTask;->action:Ljava/util/function/Consumer;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedValueTask;->transformer:Ljava/util/function/Function;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachValueTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$ForEachValueTask;->action:Ljava/util/function/Consumer;
+Ljava/util/concurrent/ConcurrentHashMap$ForwardingNode;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;)V
+Ljava/util/concurrent/ConcurrentHashMap$ForwardingNode;->find(ILjava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$ForwardingNode;->nextTable:[Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$KeyIterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIILjava/util/concurrent/ConcurrentHashMap;)V
+Ljava/util/concurrent/ConcurrentHashMap$KeySetView;-><init>(Ljava/util/concurrent/ConcurrentHashMap;Ljava/lang/Object;)V
+Ljava/util/concurrent/ConcurrentHashMap$KeySetView;->value:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$KeySpliterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIIJ)V
+Ljava/util/concurrent/ConcurrentHashMap$KeySpliterator;->est:J
+Ljava/util/concurrent/ConcurrentHashMap$KeySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$KeySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/ConcurrentHashMap$MapEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentHashMap;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapEntry;->key:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$MapEntry;->map:Ljava/util/concurrent/ConcurrentHashMap;
+Ljava/util/concurrent/ConcurrentHashMap$MapEntry;->val:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;Ljava/util/function/Function;Ljava/util/function/BiFunction;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;->reducer:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;->result:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;->transformer:Ljava/util/function/Function;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;Ljava/util/function/ToDoubleFunction;DLjava/util/function/DoubleBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;->basis:D
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;->reducer:Ljava/util/function/DoubleBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;->result:D
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;->transformer:Ljava/util/function/ToDoubleFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;Ljava/util/function/ToIntFunction;ILjava/util/function/IntBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;->basis:I
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;->reducer:Ljava/util/function/IntBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;->result:I
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;->transformer:Ljava/util/function/ToIntFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;Ljava/util/function/ToLongFunction;JLjava/util/function/LongBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;->basis:J
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;->reducer:Ljava/util/function/LongBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;->result:J
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;->transformer:Ljava/util/function/ToLongFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;Ljava/util/function/Function;Ljava/util/function/BiFunction;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;->reducer:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;->result:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;->transformer:Ljava/util/function/Function;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;Ljava/util/function/ToDoubleFunction;DLjava/util/function/DoubleBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;->basis:D
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;->reducer:Ljava/util/function/DoubleBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;->result:D
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;->transformer:Ljava/util/function/ToDoubleFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;Ljava/util/function/ToIntFunction;ILjava/util/function/IntBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;->basis:I
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;->reducer:Ljava/util/function/IntBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;->result:I
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;->transformer:Ljava/util/function/ToIntFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;Ljava/util/function/ToLongFunction;JLjava/util/function/LongBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;->basis:J
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;->reducer:Ljava/util/function/LongBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;->result:J
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;->transformer:Ljava/util/function/ToLongFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;Ljava/util/function/BiFunction;Ljava/util/function/BiFunction;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;->reducer:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;->result:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;->transformer:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;Ljava/util/function/ToDoubleBiFunction;DLjava/util/function/DoubleBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;->basis:D
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;->reducer:Ljava/util/function/DoubleBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;->result:D
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;->transformer:Ljava/util/function/ToDoubleBiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;Ljava/util/function/ToIntBiFunction;ILjava/util/function/IntBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;->basis:I
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;->reducer:Ljava/util/function/IntBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;->result:I
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;->transformer:Ljava/util/function/ToIntBiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;Ljava/util/function/ToLongBiFunction;JLjava/util/function/LongBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;->basis:J
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;->reducer:Ljava/util/function/LongBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;->result:J
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;->transformer:Ljava/util/function/ToLongBiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;Ljava/util/function/Function;Ljava/util/function/BiFunction;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;->reducer:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;->result:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;->transformer:Ljava/util/function/Function;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;Ljava/util/function/ToDoubleFunction;DLjava/util/function/DoubleBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;->basis:D
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;->reducer:Ljava/util/function/DoubleBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;->result:D
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;->transformer:Ljava/util/function/ToDoubleFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;Ljava/util/function/ToIntFunction;ILjava/util/function/IntBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;->basis:I
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;->reducer:Ljava/util/function/IntBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;->result:I
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;->transformer:Ljava/util/function/ToIntFunction;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;Ljava/util/function/ToLongFunction;JLjava/util/function/LongBinaryOperator;)V
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;->basis:J
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;->reducer:Ljava/util/function/LongBinaryOperator;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;->result:J
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;->transformer:Ljava/util/function/ToLongFunction;
+Ljava/util/concurrent/ConcurrentHashMap$Node;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentHashMap$Node;)V
+Ljava/util/concurrent/ConcurrentHashMap$Node;->find(ILjava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$Node;->hash:I
+Ljava/util/concurrent/ConcurrentHashMap$Node;->key:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$Node;->next:Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$Node;->val:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;Ljava/util/function/BiFunction;)V
+Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;->reducer:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;->result:Ljava/util/Map$Entry;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;Ljava/util/function/BiFunction;)V
+Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;->reducer:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;->result:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;Ljava/util/function/BiFunction;)V
+Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;->nextRight:Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;->reducer:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;->result:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;->rights:Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReservationNode;-><init>()V
+Ljava/util/concurrent/ConcurrentHashMap$ReservationNode;->find(ILjava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$SearchEntriesTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Function;Ljava/util/concurrent/atomic/AtomicReference;)V
+Ljava/util/concurrent/ConcurrentHashMap$SearchEntriesTask;->result:Ljava/util/concurrent/atomic/AtomicReference;
+Ljava/util/concurrent/ConcurrentHashMap$SearchEntriesTask;->searchFunction:Ljava/util/function/Function;
+Ljava/util/concurrent/ConcurrentHashMap$SearchKeysTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Function;Ljava/util/concurrent/atomic/AtomicReference;)V
+Ljava/util/concurrent/ConcurrentHashMap$SearchKeysTask;->result:Ljava/util/concurrent/atomic/AtomicReference;
+Ljava/util/concurrent/ConcurrentHashMap$SearchKeysTask;->searchFunction:Ljava/util/function/Function;
+Ljava/util/concurrent/ConcurrentHashMap$SearchMappingsTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/BiFunction;Ljava/util/concurrent/atomic/AtomicReference;)V
+Ljava/util/concurrent/ConcurrentHashMap$SearchMappingsTask;->result:Ljava/util/concurrent/atomic/AtomicReference;
+Ljava/util/concurrent/ConcurrentHashMap$SearchMappingsTask;->searchFunction:Ljava/util/function/BiFunction;
+Ljava/util/concurrent/ConcurrentHashMap$SearchValuesTask;-><init>(Ljava/util/concurrent/ConcurrentHashMap$BulkTask;III[Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/function/Function;Ljava/util/concurrent/atomic/AtomicReference;)V
+Ljava/util/concurrent/ConcurrentHashMap$SearchValuesTask;->result:Ljava/util/concurrent/atomic/AtomicReference;
+Ljava/util/concurrent/ConcurrentHashMap$SearchValuesTask;->searchFunction:Ljava/util/function/Function;
+Ljava/util/concurrent/ConcurrentHashMap$Segment;-><init>(F)V
+Ljava/util/concurrent/ConcurrentHashMap$Segment;->loadFactor:F
+Ljava/util/concurrent/ConcurrentHashMap$TableStack;-><init>()V
+Ljava/util/concurrent/ConcurrentHashMap$TableStack;->index:I
+Ljava/util/concurrent/ConcurrentHashMap$TableStack;->length:I
+Ljava/util/concurrent/ConcurrentHashMap$TableStack;->next:Ljava/util/concurrent/ConcurrentHashMap$TableStack;
+Ljava/util/concurrent/ConcurrentHashMap$TableStack;->tab:[Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;III)V
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->advance()Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->baseIndex:I
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->baseLimit:I
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->baseSize:I
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->index:I
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->next:Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->pushState([Ljava/util/concurrent/ConcurrentHashMap$Node;II)V
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->recoverState(I)V
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->spare:Ljava/util/concurrent/ConcurrentHashMap$TableStack;
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->stack:Ljava/util/concurrent/ConcurrentHashMap$TableStack;
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;->tab:[Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;-><init>(Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)V
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->balanceDeletion(Ljava/util/concurrent/ConcurrentHashMap$TreeNode;Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->balanceInsertion(Ljava/util/concurrent/ConcurrentHashMap$TreeNode;Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->checkInvariants(Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)Z
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->contendedLock()V
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->find(ILjava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->first:Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->lockRoot()V
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->lockState:I
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->LOCKSTATE:J
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->putTreeVal(ILjava/lang/Object;Ljava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->READER:I
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->removeTreeNode(Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)Z
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->root:Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->rotateLeft(Ljava/util/concurrent/ConcurrentHashMap$TreeNode;Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->rotateRight(Ljava/util/concurrent/ConcurrentHashMap$TreeNode;Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->tieBreakOrder(Ljava/lang/Object;Ljava/lang/Object;)I
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->unlockRoot()V
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->WAITER:I
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->waiter:Ljava/lang/Thread;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;->WRITER:I
+Ljava/util/concurrent/ConcurrentHashMap$TreeNode;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$TreeNode;)V
+Ljava/util/concurrent/ConcurrentHashMap$TreeNode;->find(ILjava/lang/Object;)Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$TreeNode;->findTreeNode(ILjava/lang/Object;Ljava/lang/Class;)Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeNode;->left:Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeNode;->parent:Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeNode;->prev:Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$TreeNode;->red:Z
+Ljava/util/concurrent/ConcurrentHashMap$TreeNode;->right:Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$ValueIterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIILjava/util/concurrent/ConcurrentHashMap;)V
+Ljava/util/concurrent/ConcurrentHashMap$ValueSpliterator;-><init>([Ljava/util/concurrent/ConcurrentHashMap$Node;IIIJ)V
+Ljava/util/concurrent/ConcurrentHashMap$ValueSpliterator;->est:J
+Ljava/util/concurrent/ConcurrentHashMap$ValueSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$ValueSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/ConcurrentHashMap$ValuesView;-><init>(Ljava/util/concurrent/ConcurrentHashMap;)V
+Ljava/util/concurrent/ConcurrentHashMap$ValuesView;->add(Ljava/lang/Object;)Z
+Ljava/util/concurrent/ConcurrentHashMap$ValuesView;->addAll(Ljava/util/Collection;)Z
+Ljava/util/concurrent/ConcurrentHashMap$ValuesView;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentHashMap$ValuesView;->removeIf(Ljava/util/function/Predicate;)Z
+Ljava/util/concurrent/ConcurrentHashMap;->ABASE:I
+Ljava/util/concurrent/ConcurrentHashMap;->addCount(JI)V
+Ljava/util/concurrent/ConcurrentHashMap;->ASHIFT:I
+Ljava/util/concurrent/ConcurrentHashMap;->BASECOUNT:J
+Ljava/util/concurrent/ConcurrentHashMap;->baseCount:J
+Ljava/util/concurrent/ConcurrentHashMap;->batchFor(J)I
+Ljava/util/concurrent/ConcurrentHashMap;->casTabAt([Ljava/util/concurrent/ConcurrentHashMap$Node;ILjava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$Node;)Z
+Ljava/util/concurrent/ConcurrentHashMap;->cellsBusy:I
+Ljava/util/concurrent/ConcurrentHashMap;->CELLSBUSY:J
+Ljava/util/concurrent/ConcurrentHashMap;->CELLVALUE:J
+Ljava/util/concurrent/ConcurrentHashMap;->comparableClassFor(Ljava/lang/Object;)Ljava/lang/Class;
+Ljava/util/concurrent/ConcurrentHashMap;->compareComparables(Ljava/lang/Class;Ljava/lang/Object;Ljava/lang/Object;)I
+Ljava/util/concurrent/ConcurrentHashMap;->counterCells:[Ljava/util/concurrent/ConcurrentHashMap$CounterCell;
+Ljava/util/concurrent/ConcurrentHashMap;->DEFAULT_CAPACITY:I
+Ljava/util/concurrent/ConcurrentHashMap;->DEFAULT_CONCURRENCY_LEVEL:I
+Ljava/util/concurrent/ConcurrentHashMap;->entrySet:Ljava/util/concurrent/ConcurrentHashMap$EntrySetView;
+Ljava/util/concurrent/ConcurrentHashMap;->fullAddCount(JZ)V
+Ljava/util/concurrent/ConcurrentHashMap;->HASH_BITS:I
+Ljava/util/concurrent/ConcurrentHashMap;->helpTransfer([Ljava/util/concurrent/ConcurrentHashMap$Node;Ljava/util/concurrent/ConcurrentHashMap$Node;)[Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap;->initTable()[Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap;->keySet:Ljava/util/concurrent/ConcurrentHashMap$KeySetView;
+Ljava/util/concurrent/ConcurrentHashMap;->LOAD_FACTOR:F
+Ljava/util/concurrent/ConcurrentHashMap;->MAXIMUM_CAPACITY:I
+Ljava/util/concurrent/ConcurrentHashMap;->MAX_ARRAY_SIZE:I
+Ljava/util/concurrent/ConcurrentHashMap;->MAX_RESIZERS:I
+Ljava/util/concurrent/ConcurrentHashMap;->MIN_TRANSFER_STRIDE:I
+Ljava/util/concurrent/ConcurrentHashMap;->MIN_TREEIFY_CAPACITY:I
+Ljava/util/concurrent/ConcurrentHashMap;->MOVED:I
+Ljava/util/concurrent/ConcurrentHashMap;->NCPU:I
+Ljava/util/concurrent/ConcurrentHashMap;->nextTable:[Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap;->putVal(Ljava/lang/Object;Ljava/lang/Object;Z)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap;->removeEntryIf(Ljava/util/function/Predicate;)Z
+Ljava/util/concurrent/ConcurrentHashMap;->removeValueIf(Ljava/util/function/Predicate;)Z
+Ljava/util/concurrent/ConcurrentHashMap;->replaceNode(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentHashMap;->RESERVED:I
+Ljava/util/concurrent/ConcurrentHashMap;->resizeStamp(I)I
+Ljava/util/concurrent/ConcurrentHashMap;->RESIZE_STAMP_BITS:I
+Ljava/util/concurrent/ConcurrentHashMap;->RESIZE_STAMP_SHIFT:I
+Ljava/util/concurrent/ConcurrentHashMap;->setTabAt([Ljava/util/concurrent/ConcurrentHashMap$Node;ILjava/util/concurrent/ConcurrentHashMap$Node;)V
+Ljava/util/concurrent/ConcurrentHashMap;->sizeCtl:I
+Ljava/util/concurrent/ConcurrentHashMap;->SIZECTL:J
+Ljava/util/concurrent/ConcurrentHashMap;->spread(I)I
+Ljava/util/concurrent/ConcurrentHashMap;->sumCount()J
+Ljava/util/concurrent/ConcurrentHashMap;->tabAt([Ljava/util/concurrent/ConcurrentHashMap$Node;I)Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap;->table:[Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap;->tableSizeFor(I)I
+Ljava/util/concurrent/ConcurrentHashMap;->transfer([Ljava/util/concurrent/ConcurrentHashMap$Node;[Ljava/util/concurrent/ConcurrentHashMap$Node;)V
+Ljava/util/concurrent/ConcurrentHashMap;->transferIndex:I
+Ljava/util/concurrent/ConcurrentHashMap;->TRANSFERINDEX:J
+Ljava/util/concurrent/ConcurrentHashMap;->TREEBIN:I
+Ljava/util/concurrent/ConcurrentHashMap;->treeifyBin([Ljava/util/concurrent/ConcurrentHashMap$Node;I)V
+Ljava/util/concurrent/ConcurrentHashMap;->TREEIFY_THRESHOLD:I
+Ljava/util/concurrent/ConcurrentHashMap;->tryPresize(I)V
+Ljava/util/concurrent/ConcurrentHashMap;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ConcurrentHashMap;->untreeify(Ljava/util/concurrent/ConcurrentHashMap$Node;)Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap;->UNTREEIFY_THRESHOLD:I
+Ljava/util/concurrent/ConcurrentHashMap;->values:Ljava/util/concurrent/ConcurrentHashMap$ValuesView;
+Ljava/util/concurrent/ConcurrentLinkedDeque$AbstractItr;->advance()V
+Ljava/util/concurrent/ConcurrentLinkedDeque$AbstractItr;->lastRet:Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$AbstractItr;->nextItem:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentLinkedDeque$AbstractItr;->nextNode(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$AbstractItr;->nextNode:Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$AbstractItr;->startNode()Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$CLDSpliterator;-><init>(Ljava/util/concurrent/ConcurrentLinkedDeque;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque$CLDSpliterator;->batch:I
+Ljava/util/concurrent/ConcurrentLinkedDeque$CLDSpliterator;->current:Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$CLDSpliterator;->exhausted:Z
+Ljava/util/concurrent/ConcurrentLinkedDeque$CLDSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque$CLDSpliterator;->MAX_BATCH:I
+Ljava/util/concurrent/ConcurrentLinkedDeque$CLDSpliterator;->queue:Ljava/util/concurrent/ConcurrentLinkedDeque;
+Ljava/util/concurrent/ConcurrentLinkedDeque$CLDSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/ConcurrentLinkedDeque$DescendingItr;->nextNode(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$DescendingItr;->startNode()Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$Itr;->nextNode(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$Itr;->startNode()Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;-><init>()V
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;-><init>(Ljava/lang/Object;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->casItem(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->casNext(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Z
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->casPrev(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Z
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->ITEM:J
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->item:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->lazySetNext(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->lazySetPrev(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->NEXT:J
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->next:Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->PREV:J
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->prev:Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->casHead(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Z
+Ljava/util/concurrent/ConcurrentLinkedDeque;->casTail(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Z
+Ljava/util/concurrent/ConcurrentLinkedDeque;->first()Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->HEAD:J
+Ljava/util/concurrent/ConcurrentLinkedDeque;->head:Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->HOPS:I
+Ljava/util/concurrent/ConcurrentLinkedDeque;->initHeadTail(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->last()Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->linkFirst(Ljava/lang/Object;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->linkLast(Ljava/lang/Object;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->nextTerminator()Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->NEXT_TERMINATOR:Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->pred(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->prevTerminator()Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->PREV_TERMINATOR:Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->screenNullResult(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->skipDeletedPredecessors(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->skipDeletedSuccessors(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->succ(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->TAIL:J
+Ljava/util/concurrent/ConcurrentLinkedDeque;->tail:Ljava/util/concurrent/ConcurrentLinkedDeque$Node;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->toArrayInternal([Ljava/lang/Object;)[Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ConcurrentLinkedDeque;->unlink(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->unlinkFirst(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->unlinkLast(Ljava/util/concurrent/ConcurrentLinkedDeque$Node;Ljava/util/concurrent/ConcurrentLinkedDeque$Node;)V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->updateHead()V
+Ljava/util/concurrent/ConcurrentLinkedDeque;->updateTail()V
+Ljava/util/concurrent/ConcurrentLinkedQueue$CLQSpliterator;-><init>(Ljava/util/concurrent/ConcurrentLinkedQueue;)V
+Ljava/util/concurrent/ConcurrentLinkedQueue$CLQSpliterator;->batch:I
+Ljava/util/concurrent/ConcurrentLinkedQueue$CLQSpliterator;->current:Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentLinkedQueue$CLQSpliterator;->exhausted:Z
+Ljava/util/concurrent/ConcurrentLinkedQueue$CLQSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentLinkedQueue$CLQSpliterator;->MAX_BATCH:I
+Ljava/util/concurrent/ConcurrentLinkedQueue$CLQSpliterator;->queue:Ljava/util/concurrent/ConcurrentLinkedQueue;
+Ljava/util/concurrent/ConcurrentLinkedQueue$CLQSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/ConcurrentLinkedQueue$Itr;->lastRet:Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentLinkedQueue$Itr;->nextItem:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentLinkedQueue$Itr;->nextNode:Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentLinkedQueue$Node;-><init>()V
+Ljava/util/concurrent/ConcurrentLinkedQueue$Node;->item:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentLinkedQueue$Node;->next:Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentLinkedQueue;->casHead(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)Z
+Ljava/util/concurrent/ConcurrentLinkedQueue;->casItem(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/concurrent/ConcurrentLinkedQueue;->casNext(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)Z
+Ljava/util/concurrent/ConcurrentLinkedQueue;->casTail(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)Z
+Ljava/util/concurrent/ConcurrentLinkedQueue;->first()Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentLinkedQueue;->HEAD:J
+Ljava/util/concurrent/ConcurrentLinkedQueue;->head:Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentLinkedQueue;->ITEM:J
+Ljava/util/concurrent/ConcurrentLinkedQueue;->lazySetNext(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)V
+Ljava/util/concurrent/ConcurrentLinkedQueue;->newNode(Ljava/lang/Object;)Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentLinkedQueue;->NEXT:J
+Ljava/util/concurrent/ConcurrentLinkedQueue;->succ(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentLinkedQueue;->TAIL:J
+Ljava/util/concurrent/ConcurrentLinkedQueue;->tail:Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentLinkedQueue;->toArrayInternal([Ljava/lang/Object;)[Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentLinkedQueue;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ConcurrentLinkedQueue;->updateHead(Ljava/util/concurrent/ConcurrentLinkedQueue$Node;Ljava/util/concurrent/ConcurrentLinkedQueue$Node;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$CSLMSpliterator;-><init>(Ljava/util/Comparator;Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/lang/Object;I)V
+Ljava/util/concurrent/ConcurrentSkipListMap$CSLMSpliterator;->comparator:Ljava/util/Comparator;
+Ljava/util/concurrent/ConcurrentSkipListMap$CSLMSpliterator;->current:Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap$CSLMSpliterator;->est:I
+Ljava/util/concurrent/ConcurrentSkipListMap$CSLMSpliterator;->estimateSize()J
+Ljava/util/concurrent/ConcurrentSkipListMap$CSLMSpliterator;->fence:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$CSLMSpliterator;->row:Ljava/util/concurrent/ConcurrentSkipListMap$Index;
+Ljava/util/concurrent/ConcurrentSkipListMap$EntrySet;-><init>(Ljava/util/concurrent/ConcurrentNavigableMap;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$EntrySet;->m:Ljava/util/concurrent/ConcurrentNavigableMap;
+Ljava/util/concurrent/ConcurrentSkipListMap$EntrySet;->removeIf(Ljava/util/function/Predicate;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$EntrySpliterator;-><init>(Ljava/util/Comparator;Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/lang/Object;I)V
+Ljava/util/concurrent/ConcurrentSkipListMap$EntrySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$EntrySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;-><init>(Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;I)V
+Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;->level:I
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;-><init>(Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;->casRight(Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;->down:Ljava/util/concurrent/ConcurrentSkipListMap$Index;
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;->indexesDeletedNode()Z
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;->link(Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Index;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;->node:Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;->RIGHT:J
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;->right:Ljava/util/concurrent/ConcurrentSkipListMap$Index;
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ConcurrentSkipListMap$Index;->unlink(Ljava/util/concurrent/ConcurrentSkipListMap$Index;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$Iter;->advance()V
+Ljava/util/concurrent/ConcurrentSkipListMap$Iter;->lastReturned:Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap$Iter;->next:Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap$Iter;->nextValue:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;-><init>(Ljava/util/concurrent/ConcurrentNavigableMap;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->ceiling(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->floor(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->headSet(Ljava/lang/Object;)Ljava/util/NavigableSet;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->headSet(Ljava/lang/Object;Z)Ljava/util/NavigableSet;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->higher(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->lower(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->m:Ljava/util/concurrent/ConcurrentNavigableMap;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->subSet(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/NavigableSet;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->subSet(Ljava/lang/Object;ZLjava/lang/Object;Z)Ljava/util/NavigableSet;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->tailSet(Ljava/lang/Object;)Ljava/util/NavigableSet;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;->tailSet(Ljava/lang/Object;Z)Ljava/util/NavigableSet;
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySpliterator;-><init>(Ljava/util/Comparator;Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/lang/Object;I)V
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$KeySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/concurrent/ConcurrentSkipListMap$Node;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;-><init>(Ljava/util/concurrent/ConcurrentSkipListMap$Node;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->appendMarker(Ljava/util/concurrent/ConcurrentSkipListMap$Node;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->casNext(Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/concurrent/ConcurrentSkipListMap$Node;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->casValue(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->createSnapshot()Ljava/util/AbstractMap$SimpleImmutableEntry;
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->getValidValue()Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->helpDelete(Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/concurrent/ConcurrentSkipListMap$Node;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->isBaseHeader()Z
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->isMarker()Z
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->key:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->NEXT:J
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->next:Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->VALUE:J
+Ljava/util/concurrent/ConcurrentSkipListMap$Node;->value:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap$SubMapIter;->advance()V
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap$SubMapIter;->ascend()V
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap$SubMapIter;->descend()V
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap$SubMapIter;->lastReturned:Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap$SubMapIter;->next:Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap$SubMapIter;->nextValue:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;-><init>(Ljava/util/concurrent/ConcurrentSkipListMap;Ljava/lang/Object;ZLjava/lang/Object;ZZ)V
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->checkKeyBounds(Ljava/lang/Object;Ljava/util/Comparator;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->entrySetView:Ljava/util/Set;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->getNearEntry(Ljava/lang/Object;I)Ljava/util/Map$Entry;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->getNearKey(Ljava/lang/Object;I)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->hi:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->highestEntry()Ljava/util/Map$Entry;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->highestKey()Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->hiInclusive:Z
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->hiNode(Ljava/util/Comparator;)Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->inBounds(Ljava/lang/Object;Ljava/util/Comparator;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->isBeforeEnd(Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/util/Comparator;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->isDescending:Z
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->keySetView:Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->lo:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->loInclusive:Z
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->loNode(Ljava/util/Comparator;)Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->lowestEntry()Ljava/util/Map$Entry;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->lowestKey()Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->m:Ljava/util/concurrent/ConcurrentSkipListMap;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->newSubMap(Ljava/lang/Object;ZLjava/lang/Object;Z)Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->removeHighest()Ljava/util/Map$Entry;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->removeLowest()Ljava/util/Map$Entry;
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->tooHigh(Ljava/lang/Object;Ljava/util/Comparator;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->tooLow(Ljava/lang/Object;Ljava/util/Comparator;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->valuesView:Ljava/util/Collection;
+Ljava/util/concurrent/ConcurrentSkipListMap$Values;-><init>(Ljava/util/concurrent/ConcurrentNavigableMap;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$Values;->m:Ljava/util/concurrent/ConcurrentNavigableMap;
+Ljava/util/concurrent/ConcurrentSkipListMap$Values;->removeIf(Ljava/util/function/Predicate;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap$ValueSpliterator;-><init>(Ljava/util/Comparator;Ljava/util/concurrent/ConcurrentSkipListMap$Index;Ljava/util/concurrent/ConcurrentSkipListMap$Node;Ljava/lang/Object;I)V
+Ljava/util/concurrent/ConcurrentSkipListMap$ValueSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/ConcurrentSkipListMap$ValueSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap;->BASE_HEADER:Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap;->buildFromSorted(Ljava/util/SortedMap;)V
+Ljava/util/concurrent/ConcurrentSkipListMap;->casHead(Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap;->clearIndexToFirst()V
+Ljava/util/concurrent/ConcurrentSkipListMap;->comparator:Ljava/util/Comparator;
+Ljava/util/concurrent/ConcurrentSkipListMap;->cpr(Ljava/util/Comparator;Ljava/lang/Object;Ljava/lang/Object;)I
+Ljava/util/concurrent/ConcurrentSkipListMap;->descendingMap:Ljava/util/concurrent/ConcurrentNavigableMap;
+Ljava/util/concurrent/ConcurrentSkipListMap;->doGet(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap;->doPut(Ljava/lang/Object;Ljava/lang/Object;Z)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap;->doRemove(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/concurrent/ConcurrentSkipListMap;->doRemoveFirstEntry()Ljava/util/Map$Entry;
+Ljava/util/concurrent/ConcurrentSkipListMap;->doRemoveLastEntry()Ljava/util/Map$Entry;
+Ljava/util/concurrent/ConcurrentSkipListMap;->entrySet:Ljava/util/concurrent/ConcurrentSkipListMap$EntrySet;
+Ljava/util/concurrent/ConcurrentSkipListMap;->entrySpliterator()Ljava/util/concurrent/ConcurrentSkipListMap$EntrySpliterator;
+Ljava/util/concurrent/ConcurrentSkipListMap;->EQ:I
+Ljava/util/concurrent/ConcurrentSkipListMap;->findFirst()Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap;->findLast()Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap;->findNear(Ljava/lang/Object;ILjava/util/Comparator;)Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap;->findNode(Ljava/lang/Object;)Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap;->findPredecessor(Ljava/lang/Object;Ljava/util/Comparator;)Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap;->findPredecessorOfLast()Ljava/util/concurrent/ConcurrentSkipListMap$Node;
+Ljava/util/concurrent/ConcurrentSkipListMap;->getNear(Ljava/lang/Object;I)Ljava/util/AbstractMap$SimpleImmutableEntry;
+Ljava/util/concurrent/ConcurrentSkipListMap;->GT:I
+Ljava/util/concurrent/ConcurrentSkipListMap;->HEAD:J
+Ljava/util/concurrent/ConcurrentSkipListMap;->head:Ljava/util/concurrent/ConcurrentSkipListMap$HeadIndex;
+Ljava/util/concurrent/ConcurrentSkipListMap;->initialize()V
+Ljava/util/concurrent/ConcurrentSkipListMap;->keySet:Ljava/util/concurrent/ConcurrentSkipListMap$KeySet;
+Ljava/util/concurrent/ConcurrentSkipListMap;->keySpliterator()Ljava/util/concurrent/ConcurrentSkipListMap$KeySpliterator;
+Ljava/util/concurrent/ConcurrentSkipListMap;->LT:I
+Ljava/util/concurrent/ConcurrentSkipListMap;->removeEntryIf(Ljava/util/function/Predicate;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap;->removeValueIf(Ljava/util/function/Predicate;)Z
+Ljava/util/concurrent/ConcurrentSkipListMap;->toList(Ljava/util/Collection;)Ljava/util/List;
+Ljava/util/concurrent/ConcurrentSkipListMap;->tryReduceLevel()V
+Ljava/util/concurrent/ConcurrentSkipListMap;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ConcurrentSkipListMap;->values:Ljava/util/concurrent/ConcurrentSkipListMap$Values;
+Ljava/util/concurrent/ConcurrentSkipListMap;->valueSpliterator()Ljava/util/concurrent/ConcurrentSkipListMap$ValueSpliterator;
+Ljava/util/concurrent/ConcurrentSkipListSet;-><init>(Ljava/util/concurrent/ConcurrentNavigableMap;)V
+Ljava/util/concurrent/ConcurrentSkipListSet;->m:Ljava/util/concurrent/ConcurrentNavigableMap;
+Ljava/util/concurrent/ConcurrentSkipListSet;->MAP:J
+Ljava/util/concurrent/ConcurrentSkipListSet;->setMap(Ljava/util/concurrent/ConcurrentNavigableMap;)V
+Ljava/util/concurrent/ConcurrentSkipListSet;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/CopyOnWriteArrayList$COWIterator;-><init>([Ljava/lang/Object;I)V
+Ljava/util/concurrent/CopyOnWriteArrayList$COWIterator;->cursor:I
+Ljava/util/concurrent/CopyOnWriteArrayList$COWIterator;->snapshot:[Ljava/lang/Object;
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubList;-><init>(Ljava/util/concurrent/CopyOnWriteArrayList;II)V
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubList;->checkForComodification()V
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubList;->expectedArray:[Ljava/lang/Object;
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubList;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubList;->l:Ljava/util/concurrent/CopyOnWriteArrayList;
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubList;->offset:I
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubList;->rangeCheck(I)V
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubList;->size:I
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubListIterator;-><init>(Ljava/util/List;III)V
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubListIterator;->it:Ljava/util/ListIterator;
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubListIterator;->offset:I
+Ljava/util/concurrent/CopyOnWriteArrayList$COWSubListIterator;->size:I
+Ljava/util/concurrent/CopyOnWriteArrayList;->addIfAbsent(Ljava/lang/Object;[Ljava/lang/Object;)Z
+Ljava/util/concurrent/CopyOnWriteArrayList;->get([Ljava/lang/Object;I)Ljava/lang/Object;
+Ljava/util/concurrent/CopyOnWriteArrayList;->getArray()[Ljava/lang/Object;
+Ljava/util/concurrent/CopyOnWriteArrayList;->indexOf(Ljava/lang/Object;[Ljava/lang/Object;II)I
+Ljava/util/concurrent/CopyOnWriteArrayList;->lastIndexOf(Ljava/lang/Object;[Ljava/lang/Object;I)I
+Ljava/util/concurrent/CopyOnWriteArrayList;->LOCK:J
+Ljava/util/concurrent/CopyOnWriteArrayList;->lock:Ljava/lang/Object;
+Ljava/util/concurrent/CopyOnWriteArrayList;->outOfBounds(II)Ljava/lang/String;
+Ljava/util/concurrent/CopyOnWriteArrayList;->remove(Ljava/lang/Object;[Ljava/lang/Object;I)Z
+Ljava/util/concurrent/CopyOnWriteArrayList;->removeRange(II)V
+Ljava/util/concurrent/CopyOnWriteArrayList;->resetLock()V
+Ljava/util/concurrent/CopyOnWriteArrayList;->setArray([Ljava/lang/Object;)V
+Ljava/util/concurrent/CopyOnWriteArrayList;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/CopyOnWriteArraySet;->compareSets([Ljava/lang/Object;Ljava/util/Set;)I
+Ljava/util/concurrent/CountDownLatch$Sync;-><init>(I)V
+Ljava/util/concurrent/CountDownLatch$Sync;->getCount()I
+Ljava/util/concurrent/CountDownLatch;->sync:Ljava/util/concurrent/CountDownLatch$Sync;
+Ljava/util/concurrent/CountedCompleter;->completer:Ljava/util/concurrent/CountedCompleter;
+Ljava/util/concurrent/CountedCompleter;->internalPropagateException(Ljava/lang/Throwable;)V
+Ljava/util/concurrent/CountedCompleter;->pending:I
+Ljava/util/concurrent/CountedCompleter;->PENDING:J
+Ljava/util/concurrent/CountedCompleter;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/CyclicBarrier$Generation;-><init>()V
+Ljava/util/concurrent/CyclicBarrier$Generation;->broken:Z
+Ljava/util/concurrent/CyclicBarrier;->barrierCommand:Ljava/lang/Runnable;
+Ljava/util/concurrent/CyclicBarrier;->breakBarrier()V
+Ljava/util/concurrent/CyclicBarrier;->count:I
+Ljava/util/concurrent/CyclicBarrier;->dowait(ZJ)I
+Ljava/util/concurrent/CyclicBarrier;->generation:Ljava/util/concurrent/CyclicBarrier$Generation;
+Ljava/util/concurrent/CyclicBarrier;->lock:Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/util/concurrent/CyclicBarrier;->nextGeneration()V
+Ljava/util/concurrent/CyclicBarrier;->parties:I
+Ljava/util/concurrent/CyclicBarrier;->trip:Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/DelayQueue$Itr;->array:[Ljava/lang/Object;
+Ljava/util/concurrent/DelayQueue$Itr;->cursor:I
+Ljava/util/concurrent/DelayQueue$Itr;->lastRet:I
+Ljava/util/concurrent/DelayQueue;->available:Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/DelayQueue;->leader:Ljava/lang/Thread;
+Ljava/util/concurrent/DelayQueue;->lock:Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/util/concurrent/DelayQueue;->peekExpired()Ljava/util/concurrent/Delayed;
+Ljava/util/concurrent/DelayQueue;->q:Ljava/util/PriorityQueue;
+Ljava/util/concurrent/DelayQueue;->removeEQ(Ljava/lang/Object;)V
+Ljava/util/concurrent/Exchanger$Node;-><init>()V
+Ljava/util/concurrent/Exchanger$Node;->bound:I
+Ljava/util/concurrent/Exchanger$Node;->collides:I
+Ljava/util/concurrent/Exchanger$Node;->hash:I
+Ljava/util/concurrent/Exchanger$Node;->index:I
+Ljava/util/concurrent/Exchanger$Node;->item:Ljava/lang/Object;
+Ljava/util/concurrent/Exchanger$Node;->match:Ljava/lang/Object;
+Ljava/util/concurrent/Exchanger$Node;->parked:Ljava/lang/Thread;
+Ljava/util/concurrent/Exchanger$Participant;-><init>()V
+Ljava/util/concurrent/Exchanger;->ABASE:I
+Ljava/util/concurrent/Exchanger;->arena:[Ljava/util/concurrent/Exchanger$Node;
+Ljava/util/concurrent/Exchanger;->arenaExchange(Ljava/lang/Object;ZJ)Ljava/lang/Object;
+Ljava/util/concurrent/Exchanger;->ASHIFT:I
+Ljava/util/concurrent/Exchanger;->BLOCKER:J
+Ljava/util/concurrent/Exchanger;->bound:I
+Ljava/util/concurrent/Exchanger;->BOUND:J
+Ljava/util/concurrent/Exchanger;->FULL:I
+Ljava/util/concurrent/Exchanger;->MATCH:J
+Ljava/util/concurrent/Exchanger;->MMASK:I
+Ljava/util/concurrent/Exchanger;->NCPU:I
+Ljava/util/concurrent/Exchanger;->NULL_ITEM:Ljava/lang/Object;
+Ljava/util/concurrent/Exchanger;->participant:Ljava/util/concurrent/Exchanger$Participant;
+Ljava/util/concurrent/Exchanger;->SEQ:I
+Ljava/util/concurrent/Exchanger;->SLOT:J
+Ljava/util/concurrent/Exchanger;->slot:Ljava/util/concurrent/Exchanger$Node;
+Ljava/util/concurrent/Exchanger;->slotExchange(Ljava/lang/Object;ZJ)Ljava/lang/Object;
+Ljava/util/concurrent/Exchanger;->SPINS:I
+Ljava/util/concurrent/Exchanger;->TIMED_OUT:Ljava/lang/Object;
+Ljava/util/concurrent/Exchanger;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ExecutorCompletionService$QueueingFuture;-><init>(Ljava/util/concurrent/RunnableFuture;Ljava/util/concurrent/BlockingQueue;)V
+Ljava/util/concurrent/ExecutorCompletionService$QueueingFuture;->completionQueue:Ljava/util/concurrent/BlockingQueue;
+Ljava/util/concurrent/ExecutorCompletionService$QueueingFuture;->task:Ljava/util/concurrent/Future;
+Ljava/util/concurrent/ExecutorCompletionService;->aes:Ljava/util/concurrent/AbstractExecutorService;
+Ljava/util/concurrent/ExecutorCompletionService;->completionQueue:Ljava/util/concurrent/BlockingQueue;
+Ljava/util/concurrent/ExecutorCompletionService;->executor:Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/ExecutorCompletionService;->newTaskFor(Ljava/lang/Runnable;Ljava/lang/Object;)Ljava/util/concurrent/RunnableFuture;
+Ljava/util/concurrent/ExecutorCompletionService;->newTaskFor(Ljava/util/concurrent/Callable;)Ljava/util/concurrent/RunnableFuture;
+Ljava/util/concurrent/Executors$DefaultThreadFactory;-><init>()V
+Ljava/util/concurrent/Executors$DefaultThreadFactory;->group:Ljava/lang/ThreadGroup;
+Ljava/util/concurrent/Executors$DefaultThreadFactory;->namePrefix:Ljava/lang/String;
+Ljava/util/concurrent/Executors$DefaultThreadFactory;->poolNumber:Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/util/concurrent/Executors$DefaultThreadFactory;->threadNumber:Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/util/concurrent/Executors$DelegatedExecutorService;-><init>(Ljava/util/concurrent/ExecutorService;)V
+Ljava/util/concurrent/Executors$DelegatedExecutorService;->e:Ljava/util/concurrent/ExecutorService;
+Ljava/util/concurrent/Executors$DelegatedScheduledExecutorService;-><init>(Ljava/util/concurrent/ScheduledExecutorService;)V
+Ljava/util/concurrent/Executors$DelegatedScheduledExecutorService;->e:Ljava/util/concurrent/ScheduledExecutorService;
+Ljava/util/concurrent/Executors$FinalizableDelegatedExecutorService;-><init>(Ljava/util/concurrent/ExecutorService;)V
+Ljava/util/concurrent/Executors$PrivilegedCallable;-><init>(Ljava/util/concurrent/Callable;)V
+Ljava/util/concurrent/Executors$PrivilegedCallable;->acc:Ljava/security/AccessControlContext;
+Ljava/util/concurrent/Executors$PrivilegedCallable;->task:Ljava/util/concurrent/Callable;
+Ljava/util/concurrent/Executors$PrivilegedCallableUsingCurrentClassLoader;-><init>(Ljava/util/concurrent/Callable;)V
+Ljava/util/concurrent/Executors$PrivilegedCallableUsingCurrentClassLoader;->acc:Ljava/security/AccessControlContext;
+Ljava/util/concurrent/Executors$PrivilegedCallableUsingCurrentClassLoader;->ccl:Ljava/lang/ClassLoader;
+Ljava/util/concurrent/Executors$PrivilegedCallableUsingCurrentClassLoader;->task:Ljava/util/concurrent/Callable;
+Ljava/util/concurrent/Executors$PrivilegedThreadFactory;-><init>()V
+Ljava/util/concurrent/Executors$PrivilegedThreadFactory;->acc:Ljava/security/AccessControlContext;
+Ljava/util/concurrent/Executors$PrivilegedThreadFactory;->ccl:Ljava/lang/ClassLoader;
+Ljava/util/concurrent/Executors$RunnableAdapter;-><init>(Ljava/lang/Runnable;Ljava/lang/Object;)V
+Ljava/util/concurrent/Executors$RunnableAdapter;->result:Ljava/lang/Object;
+Ljava/util/concurrent/Executors;-><init>()V
+Ljava/util/concurrent/ForkJoinPool$AuxState;-><init>()V
+Ljava/util/concurrent/ForkJoinPool$AuxState;->indexSeed:J
+Ljava/util/concurrent/ForkJoinPool$AuxState;->stealCount:J
+Ljava/util/concurrent/ForkJoinPool$DefaultForkJoinWorkerThreadFactory;-><init>()V
+Ljava/util/concurrent/ForkJoinPool$EmptyTask;-><init>()V
+Ljava/util/concurrent/ForkJoinPool$EmptyTask;->setRawResult(Ljava/lang/Void;)V
+Ljava/util/concurrent/ForkJoinPool$InnocuousForkJoinWorkerThreadFactory;-><init>()V
+Ljava/util/concurrent/ForkJoinPool$InnocuousForkJoinWorkerThreadFactory;->innocuousAcc:Ljava/security/AccessControlContext;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;-><init>(Ljava/util/concurrent/ForkJoinPool;Ljava/util/concurrent/ForkJoinWorkerThread;)V
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->ABASE:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->array:[Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->ASHIFT:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->base:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->cancelAll()V
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->config:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->currentJoin:Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->currentSteal:Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->getPoolIndex()I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->growAndSharedPush(Ljava/util/concurrent/ForkJoinTask;)V
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->growArray()[Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->hint:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->INITIAL_QUEUE_CAPACITY:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->isApparentlyUnblocked()Z
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->isEmpty()Z
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->localPollAndExec()V
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->localPopAndExec()V
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->MAXIMUM_QUEUE_CAPACITY:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->nextLocalTask()Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->nsteals:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->owner:Ljava/util/concurrent/ForkJoinWorkerThread;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->parker:Ljava/lang/Thread;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->peek()Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->poll()Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->pollAndExecCC(Ljava/util/concurrent/CountedCompleter;)I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->pollAt(I)Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->pool:Ljava/util/concurrent/ForkJoinPool;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->pop()Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->popCC(Ljava/util/concurrent/CountedCompleter;I)Ljava/util/concurrent/CountedCompleter;
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->push(Ljava/util/concurrent/ForkJoinTask;)V
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->qlock:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->QLOCK:J
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->queueSize()I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->runTask(Ljava/util/concurrent/ForkJoinTask;)V
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->scanState:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->sharedPush(Ljava/util/concurrent/ForkJoinTask;)I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->stackPred:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->top:I
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->transferStealCount(Ljava/util/concurrent/ForkJoinPool;)V
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->tryRemoveAndExec(Ljava/util/concurrent/ForkJoinTask;)Z
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->trySharedUnpush(Ljava/util/concurrent/ForkJoinTask;)Z
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->tryUnpush(Ljava/util/concurrent/ForkJoinTask;)Z
+Ljava/util/concurrent/ForkJoinPool$WorkQueue;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ForkJoinPool;-><init>(ILjava/util/concurrent/ForkJoinPool$ForkJoinWorkerThreadFactory;Ljava/lang/Thread$UncaughtExceptionHandler;ILjava/lang/String;)V
+Ljava/util/concurrent/ForkJoinPool;->ABASE:I
+Ljava/util/concurrent/ForkJoinPool;->AC_MASK:J
+Ljava/util/concurrent/ForkJoinPool;->AC_SHIFT:I
+Ljava/util/concurrent/ForkJoinPool;->AC_UNIT:J
+Ljava/util/concurrent/ForkJoinPool;->ADD_WORKER:J
+Ljava/util/concurrent/ForkJoinPool;->ASHIFT:I
+Ljava/util/concurrent/ForkJoinPool;->auxState:Ljava/util/concurrent/ForkJoinPool$AuxState;
+Ljava/util/concurrent/ForkJoinPool;->awaitJoin(Ljava/util/concurrent/ForkJoinPool$WorkQueue;Ljava/util/concurrent/ForkJoinTask;J)I
+Ljava/util/concurrent/ForkJoinPool;->awaitWork(Ljava/util/concurrent/ForkJoinPool$WorkQueue;)I
+Ljava/util/concurrent/ForkJoinPool;->checkFactory(Ljava/util/concurrent/ForkJoinPool$ForkJoinWorkerThreadFactory;)Ljava/util/concurrent/ForkJoinPool$ForkJoinWorkerThreadFactory;
+Ljava/util/concurrent/ForkJoinPool;->checkParallelism(I)I
+Ljava/util/concurrent/ForkJoinPool;->checkPermission()V
+Ljava/util/concurrent/ForkJoinPool;->common:Ljava/util/concurrent/ForkJoinPool;
+Ljava/util/concurrent/ForkJoinPool;->commonSubmitterQueue()Ljava/util/concurrent/ForkJoinPool$WorkQueue;
+Ljava/util/concurrent/ForkJoinPool;->COMMON_MAX_SPARES:I
+Ljava/util/concurrent/ForkJoinPool;->COMMON_PARALLELISM:I
+Ljava/util/concurrent/ForkJoinPool;->config:I
+Ljava/util/concurrent/ForkJoinPool;->createWorker(Z)Z
+Ljava/util/concurrent/ForkJoinPool;->CTL:J
+Ljava/util/concurrent/ForkJoinPool;->ctl:J
+Ljava/util/concurrent/ForkJoinPool;->DEFAULT_COMMON_MAX_SPARES:I
+Ljava/util/concurrent/ForkJoinPool;->deregisterWorker(Ljava/util/concurrent/ForkJoinWorkerThread;Ljava/lang/Throwable;)V
+Ljava/util/concurrent/ForkJoinPool;->EVENMASK:I
+Ljava/util/concurrent/ForkJoinPool;->externalHelpComplete(Ljava/util/concurrent/CountedCompleter;I)I
+Ljava/util/concurrent/ForkJoinPool;->externalPush(Ljava/util/concurrent/ForkJoinTask;)V
+Ljava/util/concurrent/ForkJoinPool;->externalSubmit(Ljava/util/concurrent/ForkJoinTask;)Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool;->factory:Ljava/util/concurrent/ForkJoinPool$ForkJoinWorkerThreadFactory;
+Ljava/util/concurrent/ForkJoinPool;->FIFO_QUEUE:I
+Ljava/util/concurrent/ForkJoinPool;->findNonEmptyStealQueue()Ljava/util/concurrent/ForkJoinPool$WorkQueue;
+Ljava/util/concurrent/ForkJoinPool;->getSurplusQueuedTaskCount()I
+Ljava/util/concurrent/ForkJoinPool;->helpComplete(Ljava/util/concurrent/ForkJoinPool$WorkQueue;Ljava/util/concurrent/CountedCompleter;I)I
+Ljava/util/concurrent/ForkJoinPool;->helpQuiescePool(Ljava/util/concurrent/ForkJoinPool$WorkQueue;)V
+Ljava/util/concurrent/ForkJoinPool;->helpStealer(Ljava/util/concurrent/ForkJoinPool$WorkQueue;Ljava/util/concurrent/ForkJoinTask;)V
+Ljava/util/concurrent/ForkJoinPool;->IDLE_TIMEOUT_MS:J
+Ljava/util/concurrent/ForkJoinPool;->inactivate(Ljava/util/concurrent/ForkJoinPool$WorkQueue;I)V
+Ljava/util/concurrent/ForkJoinPool;->IS_OWNED:I
+Ljava/util/concurrent/ForkJoinPool;->LIFO_QUEUE:I
+Ljava/util/concurrent/ForkJoinPool;->makeCommonPool()Ljava/util/concurrent/ForkJoinPool;
+Ljava/util/concurrent/ForkJoinPool;->MAX_CAP:I
+Ljava/util/concurrent/ForkJoinPool;->MODE_MASK:I
+Ljava/util/concurrent/ForkJoinPool;->modifyThreadPermission:Ljava/lang/RuntimePermission;
+Ljava/util/concurrent/ForkJoinPool;->nextPoolId()I
+Ljava/util/concurrent/ForkJoinPool;->nextTaskFor(Ljava/util/concurrent/ForkJoinPool$WorkQueue;)Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinPool;->POLL_LIMIT:I
+Ljava/util/concurrent/ForkJoinPool;->poolNumberSequence:I
+Ljava/util/concurrent/ForkJoinPool;->quiesceCommonPool()V
+Ljava/util/concurrent/ForkJoinPool;->registerWorker(Ljava/util/concurrent/ForkJoinWorkerThread;)Ljava/util/concurrent/ForkJoinPool$WorkQueue;
+Ljava/util/concurrent/ForkJoinPool;->runState:I
+Ljava/util/concurrent/ForkJoinPool;->RUNSTATE:J
+Ljava/util/concurrent/ForkJoinPool;->runWorker(Ljava/util/concurrent/ForkJoinPool$WorkQueue;)V
+Ljava/util/concurrent/ForkJoinPool;->scan(Ljava/util/concurrent/ForkJoinPool$WorkQueue;III)I
+Ljava/util/concurrent/ForkJoinPool;->SEED_INCREMENT:I
+Ljava/util/concurrent/ForkJoinPool;->SHUTDOWN:I
+Ljava/util/concurrent/ForkJoinPool;->signalWork()V
+Ljava/util/concurrent/ForkJoinPool;->SMASK:I
+Ljava/util/concurrent/ForkJoinPool;->SPARE_WORKER:I
+Ljava/util/concurrent/ForkJoinPool;->SP_MASK:J
+Ljava/util/concurrent/ForkJoinPool;->SQMASK:I
+Ljava/util/concurrent/ForkJoinPool;->SS_SEQ:I
+Ljava/util/concurrent/ForkJoinPool;->STARTED:I
+Ljava/util/concurrent/ForkJoinPool;->STOP:I
+Ljava/util/concurrent/ForkJoinPool;->TC_MASK:J
+Ljava/util/concurrent/ForkJoinPool;->TC_SHIFT:I
+Ljava/util/concurrent/ForkJoinPool;->TC_UNIT:J
+Ljava/util/concurrent/ForkJoinPool;->TERMINATED:I
+Ljava/util/concurrent/ForkJoinPool;->timedAwaitWork(Ljava/util/concurrent/ForkJoinPool$WorkQueue;J)I
+Ljava/util/concurrent/ForkJoinPool;->TIMEOUT_SLOP_MS:J
+Ljava/util/concurrent/ForkJoinPool;->tryAddWorker(J)V
+Ljava/util/concurrent/ForkJoinPool;->tryCompensate(Ljava/util/concurrent/ForkJoinPool$WorkQueue;)Z
+Ljava/util/concurrent/ForkJoinPool;->tryCreateExternalQueue(I)V
+Ljava/util/concurrent/ForkJoinPool;->tryDropSpare(Ljava/util/concurrent/ForkJoinPool$WorkQueue;)Z
+Ljava/util/concurrent/ForkJoinPool;->tryExternalUnpush(Ljava/util/concurrent/ForkJoinTask;)Z
+Ljava/util/concurrent/ForkJoinPool;->tryInitialize(Z)V
+Ljava/util/concurrent/ForkJoinPool;->tryReactivate(Ljava/util/concurrent/ForkJoinPool$WorkQueue;[Ljava/util/concurrent/ForkJoinPool$WorkQueue;I)V
+Ljava/util/concurrent/ForkJoinPool;->tryRelease(JLjava/util/concurrent/ForkJoinPool$WorkQueue;J)Z
+Ljava/util/concurrent/ForkJoinPool;->tryTerminate(ZZ)I
+Ljava/util/concurrent/ForkJoinPool;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ForkJoinPool;->UC_MASK:J
+Ljava/util/concurrent/ForkJoinPool;->ueh:Ljava/lang/Thread$UncaughtExceptionHandler;
+Ljava/util/concurrent/ForkJoinPool;->UNREGISTERED:I
+Ljava/util/concurrent/ForkJoinPool;->UNSIGNALLED:I
+Ljava/util/concurrent/ForkJoinPool;->workerNamePrefix:Ljava/lang/String;
+Ljava/util/concurrent/ForkJoinPool;->workQueues:[Ljava/util/concurrent/ForkJoinPool$WorkQueue;
+Ljava/util/concurrent/ForkJoinTask$AdaptedCallable;-><init>(Ljava/util/concurrent/Callable;)V
+Ljava/util/concurrent/ForkJoinTask$AdaptedCallable;->callable:Ljava/util/concurrent/Callable;
+Ljava/util/concurrent/ForkJoinTask$AdaptedCallable;->result:Ljava/lang/Object;
+Ljava/util/concurrent/ForkJoinTask$AdaptedCallable;->setRawResult(Ljava/lang/Object;)V
+Ljava/util/concurrent/ForkJoinTask$AdaptedRunnable;-><init>(Ljava/lang/Runnable;Ljava/lang/Object;)V
+Ljava/util/concurrent/ForkJoinTask$AdaptedRunnable;->result:Ljava/lang/Object;
+Ljava/util/concurrent/ForkJoinTask$AdaptedRunnable;->runnable:Ljava/lang/Runnable;
+Ljava/util/concurrent/ForkJoinTask$AdaptedRunnable;->setRawResult(Ljava/lang/Object;)V
+Ljava/util/concurrent/ForkJoinTask$AdaptedRunnableAction;-><init>(Ljava/lang/Runnable;)V
+Ljava/util/concurrent/ForkJoinTask$AdaptedRunnableAction;->runnable:Ljava/lang/Runnable;
+Ljava/util/concurrent/ForkJoinTask$AdaptedRunnableAction;->setRawResult(Ljava/lang/Void;)V
+Ljava/util/concurrent/ForkJoinTask$ExceptionNode;-><init>(Ljava/util/concurrent/ForkJoinTask;Ljava/lang/Throwable;Ljava/util/concurrent/ForkJoinTask$ExceptionNode;Ljava/lang/ref/ReferenceQueue;)V
+Ljava/util/concurrent/ForkJoinTask$ExceptionNode;->ex:Ljava/lang/Throwable;
+Ljava/util/concurrent/ForkJoinTask$ExceptionNode;->hashCode:I
+Ljava/util/concurrent/ForkJoinTask$ExceptionNode;->next:Ljava/util/concurrent/ForkJoinTask$ExceptionNode;
+Ljava/util/concurrent/ForkJoinTask$ExceptionNode;->thrower:J
+Ljava/util/concurrent/ForkJoinTask$RunnableExecuteAction;-><init>(Ljava/lang/Runnable;)V
+Ljava/util/concurrent/ForkJoinTask$RunnableExecuteAction;->internalPropagateException(Ljava/lang/Throwable;)V
+Ljava/util/concurrent/ForkJoinTask$RunnableExecuteAction;->runnable:Ljava/lang/Runnable;
+Ljava/util/concurrent/ForkJoinTask$RunnableExecuteAction;->setRawResult(Ljava/lang/Void;)V
+Ljava/util/concurrent/ForkJoinTask;->cancelIgnoringExceptions(Ljava/util/concurrent/ForkJoinTask;)V
+Ljava/util/concurrent/ForkJoinTask;->CANCELLED:I
+Ljava/util/concurrent/ForkJoinTask;->clearExceptionalCompletion()V
+Ljava/util/concurrent/ForkJoinTask;->doExec()I
+Ljava/util/concurrent/ForkJoinTask;->doInvoke()I
+Ljava/util/concurrent/ForkJoinTask;->doJoin()I
+Ljava/util/concurrent/ForkJoinTask;->DONE_MASK:I
+Ljava/util/concurrent/ForkJoinTask;->EXCEPTIONAL:I
+Ljava/util/concurrent/ForkJoinTask;->exceptionTable:[Ljava/util/concurrent/ForkJoinTask$ExceptionNode;
+Ljava/util/concurrent/ForkJoinTask;->exceptionTableLock:Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/util/concurrent/ForkJoinTask;->exceptionTableRefQueue:Ljava/lang/ref/ReferenceQueue;
+Ljava/util/concurrent/ForkJoinTask;->EXCEPTION_MAP_CAPACITY:I
+Ljava/util/concurrent/ForkJoinTask;->expungeStaleExceptions()V
+Ljava/util/concurrent/ForkJoinTask;->externalAwaitDone()I
+Ljava/util/concurrent/ForkJoinTask;->externalInterruptibleAwaitDone()I
+Ljava/util/concurrent/ForkJoinTask;->getThrowableException()Ljava/lang/Throwable;
+Ljava/util/concurrent/ForkJoinTask;->helpExpungeStaleExceptions()V
+Ljava/util/concurrent/ForkJoinTask;->internalPropagateException(Ljava/lang/Throwable;)V
+Ljava/util/concurrent/ForkJoinTask;->internalWait(J)V
+Ljava/util/concurrent/ForkJoinTask;->NORMAL:I
+Ljava/util/concurrent/ForkJoinTask;->pollSubmission()Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinTask;->recordExceptionalCompletion(Ljava/lang/Throwable;)I
+Ljava/util/concurrent/ForkJoinTask;->reportException(I)V
+Ljava/util/concurrent/ForkJoinTask;->rethrow(Ljava/lang/Throwable;)V
+Ljava/util/concurrent/ForkJoinTask;->setCompletion(I)I
+Ljava/util/concurrent/ForkJoinTask;->setExceptionalCompletion(Ljava/lang/Throwable;)I
+Ljava/util/concurrent/ForkJoinTask;->SIGNAL:I
+Ljava/util/concurrent/ForkJoinTask;->SMASK:I
+Ljava/util/concurrent/ForkJoinTask;->status:I
+Ljava/util/concurrent/ForkJoinTask;->STATUS:J
+Ljava/util/concurrent/ForkJoinTask;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ForkJoinTask;->uncheckedThrow(Ljava/lang/Throwable;)V
+Ljava/util/concurrent/ForkJoinWorkerThread$InnocuousForkJoinWorkerThread;-><init>(Ljava/util/concurrent/ForkJoinPool;)V
+Ljava/util/concurrent/ForkJoinWorkerThread$InnocuousForkJoinWorkerThread;->afterTopLevelExec()V
+Ljava/util/concurrent/ForkJoinWorkerThread$InnocuousForkJoinWorkerThread;->createThreadGroup()Ljava/lang/ThreadGroup;
+Ljava/util/concurrent/ForkJoinWorkerThread$InnocuousForkJoinWorkerThread;->innocuousThreadGroup:Ljava/lang/ThreadGroup;
+Ljava/util/concurrent/ForkJoinWorkerThread$InnocuousForkJoinWorkerThread;->INNOCUOUS_ACC:Ljava/security/AccessControlContext;
+Ljava/util/concurrent/ForkJoinWorkerThread;-><init>(Ljava/util/concurrent/ForkJoinPool;Ljava/lang/ThreadGroup;Ljava/security/AccessControlContext;)V
+Ljava/util/concurrent/ForkJoinWorkerThread;->afterTopLevelExec()V
+Ljava/util/concurrent/ForkJoinWorkerThread;->eraseThreadLocals()V
+Ljava/util/concurrent/ForkJoinWorkerThread;->INHERITABLETHREADLOCALS:J
+Ljava/util/concurrent/ForkJoinWorkerThread;->INHERITEDACCESSCONTROLCONTEXT:J
+Ljava/util/concurrent/ForkJoinWorkerThread;->pool:Ljava/util/concurrent/ForkJoinPool;
+Ljava/util/concurrent/ForkJoinWorkerThread;->THREADLOCALS:J
+Ljava/util/concurrent/ForkJoinWorkerThread;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ForkJoinWorkerThread;->workQueue:Ljava/util/concurrent/ForkJoinPool$WorkQueue;
+Ljava/util/concurrent/FutureTask$WaitNode;-><init>()V
+Ljava/util/concurrent/FutureTask$WaitNode;->next:Ljava/util/concurrent/FutureTask$WaitNode;
+Ljava/util/concurrent/FutureTask$WaitNode;->thread:Ljava/lang/Thread;
+Ljava/util/concurrent/FutureTask;->awaitDone(ZJ)I
+Ljava/util/concurrent/FutureTask;->CANCELLED:I
+Ljava/util/concurrent/FutureTask;->COMPLETING:I
+Ljava/util/concurrent/FutureTask;->finishCompletion()V
+Ljava/util/concurrent/FutureTask;->handlePossibleCancellationInterrupt(I)V
+Ljava/util/concurrent/FutureTask;->INTERRUPTED:I
+Ljava/util/concurrent/FutureTask;->INTERRUPTING:I
+Ljava/util/concurrent/FutureTask;->NEW:I
+Ljava/util/concurrent/FutureTask;->NORMAL:I
+Ljava/util/concurrent/FutureTask;->removeWaiter(Ljava/util/concurrent/FutureTask$WaitNode;)V
+Ljava/util/concurrent/FutureTask;->report(I)Ljava/lang/Object;
+Ljava/util/concurrent/FutureTask;->RUNNER:J
+Ljava/util/concurrent/FutureTask;->runner:Ljava/lang/Thread;
+Ljava/util/concurrent/FutureTask;->STATE:J
+Ljava/util/concurrent/FutureTask;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/FutureTask;->WAITERS:J
+Ljava/util/concurrent/FutureTask;->waiters:Ljava/util/concurrent/FutureTask$WaitNode;
+Ljava/util/concurrent/LinkedBlockingDeque$AbstractItr;->advance()V
+Ljava/util/concurrent/LinkedBlockingDeque$AbstractItr;->firstNode()Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$AbstractItr;->lastRet:Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$AbstractItr;->next:Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$AbstractItr;->nextItem:Ljava/lang/Object;
+Ljava/util/concurrent/LinkedBlockingDeque$AbstractItr;->nextNode(Ljava/util/concurrent/LinkedBlockingDeque$Node;)Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$AbstractItr;->succ(Ljava/util/concurrent/LinkedBlockingDeque$Node;)Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$DescendingItr;->firstNode()Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$DescendingItr;->nextNode(Ljava/util/concurrent/LinkedBlockingDeque$Node;)Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$Itr;->firstNode()Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$Itr;->nextNode(Ljava/util/concurrent/LinkedBlockingDeque$Node;)Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$LBDSpliterator;-><init>(Ljava/util/concurrent/LinkedBlockingDeque;)V
+Ljava/util/concurrent/LinkedBlockingDeque$LBDSpliterator;->batch:I
+Ljava/util/concurrent/LinkedBlockingDeque$LBDSpliterator;->current:Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$LBDSpliterator;->est:J
+Ljava/util/concurrent/LinkedBlockingDeque$LBDSpliterator;->exhausted:Z
+Ljava/util/concurrent/LinkedBlockingDeque$LBDSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/LinkedBlockingDeque$LBDSpliterator;->MAX_BATCH:I
+Ljava/util/concurrent/LinkedBlockingDeque$LBDSpliterator;->queue:Ljava/util/concurrent/LinkedBlockingDeque;
+Ljava/util/concurrent/LinkedBlockingDeque$LBDSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/LinkedBlockingDeque$Node;-><init>(Ljava/lang/Object;)V
+Ljava/util/concurrent/LinkedBlockingDeque$Node;->item:Ljava/lang/Object;
+Ljava/util/concurrent/LinkedBlockingDeque$Node;->next:Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque$Node;->prev:Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque;->capacity:I
+Ljava/util/concurrent/LinkedBlockingDeque;->count:I
+Ljava/util/concurrent/LinkedBlockingDeque;->last:Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque;->linkFirst(Ljava/util/concurrent/LinkedBlockingDeque$Node;)Z
+Ljava/util/concurrent/LinkedBlockingDeque;->linkLast(Ljava/util/concurrent/LinkedBlockingDeque$Node;)Z
+Ljava/util/concurrent/LinkedBlockingDeque;->notEmpty:Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/LinkedBlockingDeque;->notFull:Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/LinkedBlockingDeque;->unlink(Ljava/util/concurrent/LinkedBlockingDeque$Node;)V
+Ljava/util/concurrent/LinkedBlockingDeque;->unlinkFirst()Ljava/lang/Object;
+Ljava/util/concurrent/LinkedBlockingDeque;->unlinkLast()Ljava/lang/Object;
+Ljava/util/concurrent/LinkedBlockingQueue$Itr;->current:Ljava/util/concurrent/LinkedBlockingQueue$Node;
+Ljava/util/concurrent/LinkedBlockingQueue$Itr;->currentElement:Ljava/lang/Object;
+Ljava/util/concurrent/LinkedBlockingQueue$Itr;->lastRet:Ljava/util/concurrent/LinkedBlockingQueue$Node;
+Ljava/util/concurrent/LinkedBlockingQueue$LBQSpliterator;-><init>(Ljava/util/concurrent/LinkedBlockingQueue;)V
+Ljava/util/concurrent/LinkedBlockingQueue$LBQSpliterator;->batch:I
+Ljava/util/concurrent/LinkedBlockingQueue$LBQSpliterator;->current:Ljava/util/concurrent/LinkedBlockingQueue$Node;
+Ljava/util/concurrent/LinkedBlockingQueue$LBQSpliterator;->est:J
+Ljava/util/concurrent/LinkedBlockingQueue$LBQSpliterator;->exhausted:Z
+Ljava/util/concurrent/LinkedBlockingQueue$LBQSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/LinkedBlockingQueue$LBQSpliterator;->MAX_BATCH:I
+Ljava/util/concurrent/LinkedBlockingQueue$LBQSpliterator;->queue:Ljava/util/concurrent/LinkedBlockingQueue;
+Ljava/util/concurrent/LinkedBlockingQueue$LBQSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/LinkedBlockingQueue$Node;-><init>(Ljava/lang/Object;)V
+Ljava/util/concurrent/LinkedBlockingQueue$Node;->item:Ljava/lang/Object;
+Ljava/util/concurrent/LinkedBlockingQueue$Node;->next:Ljava/util/concurrent/LinkedBlockingQueue$Node;
+Ljava/util/concurrent/LinkedBlockingQueue;->count:Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/util/concurrent/LinkedBlockingQueue;->dequeue()Ljava/lang/Object;
+Ljava/util/concurrent/LinkedBlockingQueue;->enqueue(Ljava/util/concurrent/LinkedBlockingQueue$Node;)V
+Ljava/util/concurrent/LinkedBlockingQueue;->fullyLock()V
+Ljava/util/concurrent/LinkedBlockingQueue;->fullyUnlock()V
+Ljava/util/concurrent/LinkedBlockingQueue;->last:Ljava/util/concurrent/LinkedBlockingQueue$Node;
+Ljava/util/concurrent/LinkedBlockingQueue;->notEmpty:Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/LinkedBlockingQueue;->notFull:Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/LinkedBlockingQueue;->signalNotEmpty()V
+Ljava/util/concurrent/LinkedBlockingQueue;->signalNotFull()V
+Ljava/util/concurrent/LinkedBlockingQueue;->unlink(Ljava/util/concurrent/LinkedBlockingQueue$Node;Ljava/util/concurrent/LinkedBlockingQueue$Node;)V
+Ljava/util/concurrent/LinkedTransferQueue$Itr;->advance(Ljava/util/concurrent/LinkedTransferQueue$Node;)V
+Ljava/util/concurrent/LinkedTransferQueue$Itr;->lastPred:Ljava/util/concurrent/LinkedTransferQueue$Node;
+Ljava/util/concurrent/LinkedTransferQueue$Itr;->lastRet:Ljava/util/concurrent/LinkedTransferQueue$Node;
+Ljava/util/concurrent/LinkedTransferQueue$Itr;->nextItem:Ljava/lang/Object;
+Ljava/util/concurrent/LinkedTransferQueue$Itr;->nextNode:Ljava/util/concurrent/LinkedTransferQueue$Node;
+Ljava/util/concurrent/LinkedTransferQueue$LTQSpliterator;->batch:I
+Ljava/util/concurrent/LinkedTransferQueue$LTQSpliterator;->current:Ljava/util/concurrent/LinkedTransferQueue$Node;
+Ljava/util/concurrent/LinkedTransferQueue$LTQSpliterator;->exhausted:Z
+Ljava/util/concurrent/LinkedTransferQueue$LTQSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/LinkedTransferQueue$LTQSpliterator;->MAX_BATCH:I
+Ljava/util/concurrent/LinkedTransferQueue$LTQSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/LinkedTransferQueue$Node;-><init>(Ljava/lang/Object;Z)V
+Ljava/util/concurrent/LinkedTransferQueue$Node;->cannotPrecede(Z)Z
+Ljava/util/concurrent/LinkedTransferQueue$Node;->casItem(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/concurrent/LinkedTransferQueue$Node;->casNext(Ljava/util/concurrent/LinkedTransferQueue$Node;Ljava/util/concurrent/LinkedTransferQueue$Node;)Z
+Ljava/util/concurrent/LinkedTransferQueue$Node;->forgetContents()V
+Ljava/util/concurrent/LinkedTransferQueue$Node;->forgetNext()V
+Ljava/util/concurrent/LinkedTransferQueue$Node;->isData:Z
+Ljava/util/concurrent/LinkedTransferQueue$Node;->isMatched()Z
+Ljava/util/concurrent/LinkedTransferQueue$Node;->isUnmatchedRequest()Z
+Ljava/util/concurrent/LinkedTransferQueue$Node;->ITEM:J
+Ljava/util/concurrent/LinkedTransferQueue$Node;->item:Ljava/lang/Object;
+Ljava/util/concurrent/LinkedTransferQueue$Node;->NEXT:J
+Ljava/util/concurrent/LinkedTransferQueue$Node;->next:Ljava/util/concurrent/LinkedTransferQueue$Node;
+Ljava/util/concurrent/LinkedTransferQueue$Node;->tryMatchData()Z
+Ljava/util/concurrent/LinkedTransferQueue$Node;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/LinkedTransferQueue$Node;->WAITER:J
+Ljava/util/concurrent/LinkedTransferQueue$Node;->waiter:Ljava/lang/Thread;
+Ljava/util/concurrent/LinkedTransferQueue;->ASYNC:I
+Ljava/util/concurrent/LinkedTransferQueue;->awaitMatch(Ljava/util/concurrent/LinkedTransferQueue$Node;Ljava/util/concurrent/LinkedTransferQueue$Node;Ljava/lang/Object;ZJ)Ljava/lang/Object;
+Ljava/util/concurrent/LinkedTransferQueue;->casHead(Ljava/util/concurrent/LinkedTransferQueue$Node;Ljava/util/concurrent/LinkedTransferQueue$Node;)Z
+Ljava/util/concurrent/LinkedTransferQueue;->casSweepVotes(II)Z
+Ljava/util/concurrent/LinkedTransferQueue;->casTail(Ljava/util/concurrent/LinkedTransferQueue$Node;Ljava/util/concurrent/LinkedTransferQueue$Node;)Z
+Ljava/util/concurrent/LinkedTransferQueue;->CHAINED_SPINS:I
+Ljava/util/concurrent/LinkedTransferQueue;->countOfMode(Z)I
+Ljava/util/concurrent/LinkedTransferQueue;->findAndRemove(Ljava/lang/Object;)Z
+Ljava/util/concurrent/LinkedTransferQueue;->firstDataNode()Ljava/util/concurrent/LinkedTransferQueue$Node;
+Ljava/util/concurrent/LinkedTransferQueue;->FRONT_SPINS:I
+Ljava/util/concurrent/LinkedTransferQueue;->HEAD:J
+Ljava/util/concurrent/LinkedTransferQueue;->head:Ljava/util/concurrent/LinkedTransferQueue$Node;
+Ljava/util/concurrent/LinkedTransferQueue;->MP:Z
+Ljava/util/concurrent/LinkedTransferQueue;->NOW:I
+Ljava/util/concurrent/LinkedTransferQueue;->spinsFor(Ljava/util/concurrent/LinkedTransferQueue$Node;Z)I
+Ljava/util/concurrent/LinkedTransferQueue;->succ(Ljava/util/concurrent/LinkedTransferQueue$Node;)Ljava/util/concurrent/LinkedTransferQueue$Node;
+Ljava/util/concurrent/LinkedTransferQueue;->sweep()V
+Ljava/util/concurrent/LinkedTransferQueue;->sweepVotes:I
+Ljava/util/concurrent/LinkedTransferQueue;->SWEEPVOTES:J
+Ljava/util/concurrent/LinkedTransferQueue;->SWEEP_THRESHOLD:I
+Ljava/util/concurrent/LinkedTransferQueue;->SYNC:I
+Ljava/util/concurrent/LinkedTransferQueue;->TAIL:J
+Ljava/util/concurrent/LinkedTransferQueue;->tail:Ljava/util/concurrent/LinkedTransferQueue$Node;
+Ljava/util/concurrent/LinkedTransferQueue;->TIMED:I
+Ljava/util/concurrent/LinkedTransferQueue;->toArrayInternal([Ljava/lang/Object;)[Ljava/lang/Object;
+Ljava/util/concurrent/LinkedTransferQueue;->tryAppend(Ljava/util/concurrent/LinkedTransferQueue$Node;Z)Ljava/util/concurrent/LinkedTransferQueue$Node;
+Ljava/util/concurrent/LinkedTransferQueue;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/LinkedTransferQueue;->unsplice(Ljava/util/concurrent/LinkedTransferQueue$Node;Ljava/util/concurrent/LinkedTransferQueue$Node;)V
+Ljava/util/concurrent/LinkedTransferQueue;->xfer(Ljava/lang/Object;ZIJ)Ljava/lang/Object;
+Ljava/util/concurrent/locks/AbstractOwnableSynchronizer;->exclusiveOwnerThread:Ljava/lang/Thread;
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->addConditionWaiter()Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->checkInterruptWhileWaiting(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)I
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->doSignal(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->doSignalAll(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->firstWaiter:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->isOwnedBy(Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;)Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->lastWaiter:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->REINTERRUPT:I
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->reportInterruptAfterWait(I)V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->THROW_IE:I
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->unlinkCancelledWaiters()V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->acquireQueued(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;J)Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->addWaiter(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->apparentlyFirstQueuedIsExclusive()Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->cancelAcquire(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->compareAndSetTail(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->doAcquireInterruptibly(J)V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->doAcquireNanos(JJ)Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->doAcquireShared(J)V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->doAcquireSharedInterruptibly(J)V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->doAcquireSharedNanos(JJ)Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->doReleaseShared()V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->enq(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->findNodeFromTail(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->fullGetFirstQueuedThread()Ljava/lang/Thread;
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->fullyRelease(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)J
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->HEAD:J
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->head:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->initializeSyncQueue()V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->isOnSyncQueue(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->parkAndCheckInterrupt()Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->selfInterrupt()V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->setHead(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->setHeadAndPropagate(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;J)V
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->shouldParkAfterFailedAcquire(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->SPIN_FOR_TIMEOUT_THRESHOLD:J
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->STATE:J
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->state:J
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->TAIL:J
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->tail:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->transferAfterCancelledWait(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->transferForSignal(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->unparkSuccessor(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->addConditionWaiter()Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->checkInterruptWhileWaiting(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)I
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->doSignal(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->doSignalAll(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->firstWaiter:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->isOwnedBy(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->lastWaiter:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->REINTERRUPT:I
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->reportInterruptAfterWait(I)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->THROW_IE:I
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->unlinkCancelledWaiters()V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;-><init>()V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;-><init>(I)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;-><init>(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->CANCELLED:I
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->compareAndSetNext(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->compareAndSetWaitStatus(II)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->CONDITION:I
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->EXCLUSIVE:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->isShared()Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->NEXT:J
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->next:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->nextWaiter:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->predecessor()Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->PREV:J
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->prev:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->PROPAGATE:I
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->SHARED:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->SIGNAL:I
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->THREAD:J
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->thread:Ljava/lang/Thread;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->waitStatus:I
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;->WAITSTATUS:J
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->acquireQueued(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;I)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->addWaiter(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->apparentlyFirstQueuedIsExclusive()Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->cancelAcquire(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->compareAndSetTail(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->doAcquireInterruptibly(I)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->doAcquireNanos(IJ)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->doAcquireShared(I)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->doAcquireSharedInterruptibly(I)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->doAcquireSharedNanos(IJ)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->doReleaseShared()V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->enq(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->findNodeFromTail(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->fullGetFirstQueuedThread()Ljava/lang/Thread;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->fullyRelease(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)I
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->HEAD:J
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->head:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->initializeSyncQueue()V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->isOnSyncQueue(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->parkAndCheckInterrupt()Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->selfInterrupt()V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->setHead(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->setHeadAndPropagate(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;I)V
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->shouldParkAfterFailedAcquire(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->SPIN_FOR_TIMEOUT_THRESHOLD:J
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->state:I
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->STATE:J
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->TAIL:J
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->tail:Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->transferAfterCancelledWait(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->transferForSignal(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)Z
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->unparkSuccessor(Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;)V
+Ljava/util/concurrent/locks/LockSupport;-><init>()V
+Ljava/util/concurrent/locks/LockSupport;->nextSecondarySeed()I
+Ljava/util/concurrent/locks/LockSupport;->PARKBLOCKER:J
+Ljava/util/concurrent/locks/LockSupport;->SECONDARY:J
+Ljava/util/concurrent/locks/LockSupport;->setBlocker(Ljava/lang/Thread;Ljava/lang/Object;)V
+Ljava/util/concurrent/locks/LockSupport;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/locks/ReentrantLock$FairSync;-><init>()V
+Ljava/util/concurrent/locks/ReentrantLock$FairSync;->lock()V
+Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;-><init>()V
+Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;->lock()V
+Ljava/util/concurrent/locks/ReentrantLock$Sync;-><init>()V
+Ljava/util/concurrent/locks/ReentrantLock$Sync;->getHoldCount()I
+Ljava/util/concurrent/locks/ReentrantLock$Sync;->getOwner()Ljava/lang/Thread;
+Ljava/util/concurrent/locks/ReentrantLock$Sync;->isLocked()Z
+Ljava/util/concurrent/locks/ReentrantLock$Sync;->lock()V
+Ljava/util/concurrent/locks/ReentrantLock$Sync;->newCondition()Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+Ljava/util/concurrent/locks/ReentrantLock$Sync;->nonfairTryAcquire(I)Z
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;-><init>()V
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;->readerShouldBlock()Z
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;->writerShouldBlock()Z
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;-><init>()V
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;->readerShouldBlock()Z
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;->writerShouldBlock()Z
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$ReadLock;->sync:Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$HoldCounter;-><init>()V
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$HoldCounter;->count:I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$HoldCounter;->tid:J
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;-><init>()V
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;-><init>()V
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->cachedHoldCounter:Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$HoldCounter;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->exclusiveCount(I)I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->EXCLUSIVE_MASK:I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->firstReader:Ljava/lang/Thread;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->firstReaderHoldCount:I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->fullTryAcquireShared(Ljava/lang/Thread;)I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->getCount()I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->getOwner()Ljava/lang/Thread;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->getReadHoldCount()I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->getReadLockCount()I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->getWriteHoldCount()I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->isWriteLocked()Z
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->MAX_COUNT:I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->newCondition()Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->readerShouldBlock()Z
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->readHolds:Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->sharedCount(I)I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->SHARED_SHIFT:I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->SHARED_UNIT:I
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->tryReadLock()Z
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->tryWriteLock()Z
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->unmatchedUnlockException()Ljava/lang/IllegalMonitorStateException;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->writerShouldBlock()Z
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$WriteLock;->sync:Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock;->getThreadId(Ljava/lang/Thread;)J
+Ljava/util/concurrent/locks/ReentrantReadWriteLock;->readerLock:Ljava/util/concurrent/locks/ReentrantReadWriteLock$ReadLock;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock;->sync:Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock;->TID:J
+Ljava/util/concurrent/locks/ReentrantReadWriteLock;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock;->writerLock:Ljava/util/concurrent/locks/ReentrantReadWriteLock$WriteLock;
+Ljava/util/concurrent/locks/StampedLock$WNode;-><init>(ILjava/util/concurrent/locks/StampedLock$WNode;)V
+Ljava/util/concurrent/locks/StampedLock$WNode;->cowait:Ljava/util/concurrent/locks/StampedLock$WNode;
+Ljava/util/concurrent/locks/StampedLock$WNode;->mode:I
+Ljava/util/concurrent/locks/StampedLock$WNode;->next:Ljava/util/concurrent/locks/StampedLock$WNode;
+Ljava/util/concurrent/locks/StampedLock$WNode;->prev:Ljava/util/concurrent/locks/StampedLock$WNode;
+Ljava/util/concurrent/locks/StampedLock$WNode;->status:I
+Ljava/util/concurrent/locks/StampedLock$WNode;->thread:Ljava/lang/Thread;
+Ljava/util/concurrent/locks/StampedLock;->ABITS:J
+Ljava/util/concurrent/locks/StampedLock;->acquireRead(ZJ)J
+Ljava/util/concurrent/locks/StampedLock;->acquireWrite(ZJ)J
+Ljava/util/concurrent/locks/StampedLock;->CANCELLED:I
+Ljava/util/concurrent/locks/StampedLock;->cancelWaiter(Ljava/util/concurrent/locks/StampedLock$WNode;Ljava/util/concurrent/locks/StampedLock$WNode;Z)J
+Ljava/util/concurrent/locks/StampedLock;->getReadLockCount(J)I
+Ljava/util/concurrent/locks/StampedLock;->HEAD_SPINS:I
+Ljava/util/concurrent/locks/StampedLock;->INTERRUPTED:J
+Ljava/util/concurrent/locks/StampedLock;->LG_READERS:I
+Ljava/util/concurrent/locks/StampedLock;->MAX_HEAD_SPINS:I
+Ljava/util/concurrent/locks/StampedLock;->NCPU:I
+Ljava/util/concurrent/locks/StampedLock;->ORIGIN:J
+Ljava/util/concurrent/locks/StampedLock;->OVERFLOW_YIELD_RATE:I
+Ljava/util/concurrent/locks/StampedLock;->PARKBLOCKER:J
+Ljava/util/concurrent/locks/StampedLock;->RBITS:J
+Ljava/util/concurrent/locks/StampedLock;->readerOverflow:I
+Ljava/util/concurrent/locks/StampedLock;->readLockView:Ljava/util/concurrent/locks/StampedLock$ReadLockView;
+Ljava/util/concurrent/locks/StampedLock;->readWriteLockView:Ljava/util/concurrent/locks/StampedLock$ReadWriteLockView;
+Ljava/util/concurrent/locks/StampedLock;->release(Ljava/util/concurrent/locks/StampedLock$WNode;)V
+Ljava/util/concurrent/locks/StampedLock;->RFULL:J
+Ljava/util/concurrent/locks/StampedLock;->RMODE:I
+Ljava/util/concurrent/locks/StampedLock;->RUNIT:J
+Ljava/util/concurrent/locks/StampedLock;->SBITS:J
+Ljava/util/concurrent/locks/StampedLock;->SPINS:I
+Ljava/util/concurrent/locks/StampedLock;->STATE:J
+Ljava/util/concurrent/locks/StampedLock;->state:J
+Ljava/util/concurrent/locks/StampedLock;->tryDecReaderOverflow(J)J
+Ljava/util/concurrent/locks/StampedLock;->tryIncReaderOverflow(J)J
+Ljava/util/concurrent/locks/StampedLock;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/locks/StampedLock;->unstampedUnlockRead()V
+Ljava/util/concurrent/locks/StampedLock;->unstampedUnlockWrite()V
+Ljava/util/concurrent/locks/StampedLock;->WAITING:I
+Ljava/util/concurrent/locks/StampedLock;->WBIT:J
+Ljava/util/concurrent/locks/StampedLock;->WCOWAIT:J
+Ljava/util/concurrent/locks/StampedLock;->WHEAD:J
+Ljava/util/concurrent/locks/StampedLock;->whead:Ljava/util/concurrent/locks/StampedLock$WNode;
+Ljava/util/concurrent/locks/StampedLock;->WMODE:I
+Ljava/util/concurrent/locks/StampedLock;->WNEXT:J
+Ljava/util/concurrent/locks/StampedLock;->writeLockView:Ljava/util/concurrent/locks/StampedLock$WriteLockView;
+Ljava/util/concurrent/locks/StampedLock;->WSTATUS:J
+Ljava/util/concurrent/locks/StampedLock;->WTAIL:J
+Ljava/util/concurrent/locks/StampedLock;->wtail:Ljava/util/concurrent/locks/StampedLock$WNode;
+Ljava/util/concurrent/Phaser$QNode;-><init>(Ljava/util/concurrent/Phaser;IZZJ)V
+Ljava/util/concurrent/Phaser$QNode;->deadline:J
+Ljava/util/concurrent/Phaser$QNode;->interruptible:Z
+Ljava/util/concurrent/Phaser$QNode;->nanos:J
+Ljava/util/concurrent/Phaser$QNode;->next:Ljava/util/concurrent/Phaser$QNode;
+Ljava/util/concurrent/Phaser$QNode;->phase:I
+Ljava/util/concurrent/Phaser$QNode;->phaser:Ljava/util/concurrent/Phaser;
+Ljava/util/concurrent/Phaser$QNode;->thread:Ljava/lang/Thread;
+Ljava/util/concurrent/Phaser$QNode;->timed:Z
+Ljava/util/concurrent/Phaser$QNode;->wasInterrupted:Z
+Ljava/util/concurrent/Phaser;->abortWait(I)I
+Ljava/util/concurrent/Phaser;->arrivedOf(J)I
+Ljava/util/concurrent/Phaser;->badArrive(J)Ljava/lang/String;
+Ljava/util/concurrent/Phaser;->badRegister(J)Ljava/lang/String;
+Ljava/util/concurrent/Phaser;->COUNTS_MASK:J
+Ljava/util/concurrent/Phaser;->doArrive(I)I
+Ljava/util/concurrent/Phaser;->doRegister(I)I
+Ljava/util/concurrent/Phaser;->EMPTY:I
+Ljava/util/concurrent/Phaser;->evenQ:Ljava/util/concurrent/atomic/AtomicReference;
+Ljava/util/concurrent/Phaser;->internalAwaitAdvance(ILjava/util/concurrent/Phaser$QNode;)I
+Ljava/util/concurrent/Phaser;->MAX_PARTIES:I
+Ljava/util/concurrent/Phaser;->MAX_PHASE:I
+Ljava/util/concurrent/Phaser;->NCPU:I
+Ljava/util/concurrent/Phaser;->oddQ:Ljava/util/concurrent/atomic/AtomicReference;
+Ljava/util/concurrent/Phaser;->ONE_ARRIVAL:I
+Ljava/util/concurrent/Phaser;->ONE_DEREGISTER:I
+Ljava/util/concurrent/Phaser;->ONE_PARTY:I
+Ljava/util/concurrent/Phaser;->parent:Ljava/util/concurrent/Phaser;
+Ljava/util/concurrent/Phaser;->partiesOf(J)I
+Ljava/util/concurrent/Phaser;->PARTIES_MASK:J
+Ljava/util/concurrent/Phaser;->PARTIES_SHIFT:I
+Ljava/util/concurrent/Phaser;->phaseOf(J)I
+Ljava/util/concurrent/Phaser;->PHASE_SHIFT:I
+Ljava/util/concurrent/Phaser;->queueFor(I)Ljava/util/concurrent/atomic/AtomicReference;
+Ljava/util/concurrent/Phaser;->reconcileState()J
+Ljava/util/concurrent/Phaser;->releaseWaiters(I)V
+Ljava/util/concurrent/Phaser;->root:Ljava/util/concurrent/Phaser;
+Ljava/util/concurrent/Phaser;->SPINS_PER_ARRIVAL:I
+Ljava/util/concurrent/Phaser;->STATE:J
+Ljava/util/concurrent/Phaser;->state:J
+Ljava/util/concurrent/Phaser;->stateToString(J)Ljava/lang/String;
+Ljava/util/concurrent/Phaser;->TERMINATION_BIT:J
+Ljava/util/concurrent/Phaser;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/Phaser;->unarrivedOf(J)I
+Ljava/util/concurrent/Phaser;->UNARRIVED_MASK:I
+Ljava/util/concurrent/PriorityBlockingQueue$Itr;->array:[Ljava/lang/Object;
+Ljava/util/concurrent/PriorityBlockingQueue$Itr;->cursor:I
+Ljava/util/concurrent/PriorityBlockingQueue$Itr;->lastRet:I
+Ljava/util/concurrent/PriorityBlockingQueue$PBQSpliterator;-><init>(Ljava/util/concurrent/PriorityBlockingQueue;[Ljava/lang/Object;II)V
+Ljava/util/concurrent/PriorityBlockingQueue$PBQSpliterator;->array:[Ljava/lang/Object;
+Ljava/util/concurrent/PriorityBlockingQueue$PBQSpliterator;->fence:I
+Ljava/util/concurrent/PriorityBlockingQueue$PBQSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/concurrent/PriorityBlockingQueue$PBQSpliterator;->getFence()I
+Ljava/util/concurrent/PriorityBlockingQueue$PBQSpliterator;->index:I
+Ljava/util/concurrent/PriorityBlockingQueue$PBQSpliterator;->queue:Ljava/util/concurrent/PriorityBlockingQueue;
+Ljava/util/concurrent/PriorityBlockingQueue$PBQSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/concurrent/PriorityBlockingQueue;->allocationSpinLock:I
+Ljava/util/concurrent/PriorityBlockingQueue;->ALLOCATIONSPINLOCK:J
+Ljava/util/concurrent/PriorityBlockingQueue;->comparator:Ljava/util/Comparator;
+Ljava/util/concurrent/PriorityBlockingQueue;->DEFAULT_INITIAL_CAPACITY:I
+Ljava/util/concurrent/PriorityBlockingQueue;->heapify()V
+Ljava/util/concurrent/PriorityBlockingQueue;->indexOf(Ljava/lang/Object;)I
+Ljava/util/concurrent/PriorityBlockingQueue;->MAX_ARRAY_SIZE:I
+Ljava/util/concurrent/PriorityBlockingQueue;->q:Ljava/util/PriorityQueue;
+Ljava/util/concurrent/PriorityBlockingQueue;->queue:[Ljava/lang/Object;
+Ljava/util/concurrent/PriorityBlockingQueue;->removeAt(I)V
+Ljava/util/concurrent/PriorityBlockingQueue;->removeEQ(Ljava/lang/Object;)V
+Ljava/util/concurrent/PriorityBlockingQueue;->siftDownComparable(ILjava/lang/Object;[Ljava/lang/Object;I)V
+Ljava/util/concurrent/PriorityBlockingQueue;->siftDownUsingComparator(ILjava/lang/Object;[Ljava/lang/Object;ILjava/util/Comparator;)V
+Ljava/util/concurrent/PriorityBlockingQueue;->siftUpComparable(ILjava/lang/Object;[Ljava/lang/Object;)V
+Ljava/util/concurrent/PriorityBlockingQueue;->siftUpUsingComparator(ILjava/lang/Object;[Ljava/lang/Object;Ljava/util/Comparator;)V
+Ljava/util/concurrent/PriorityBlockingQueue;->size:I
+Ljava/util/concurrent/PriorityBlockingQueue;->tryGrow([Ljava/lang/Object;I)V
+Ljava/util/concurrent/PriorityBlockingQueue;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/RecursiveTask;->result:Ljava/lang/Object;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;->array:[Ljava/util/concurrent/RunnableScheduledFuture;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;->cursor:I
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr;->lastRet:I
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;-><init>()V
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->add(Ljava/lang/Runnable;)Z
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->available:Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->drainTo(Ljava/util/Collection;)I
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->drainTo(Ljava/util/Collection;I)I
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->finishPoll(Ljava/util/concurrent/RunnableScheduledFuture;)Ljava/util/concurrent/RunnableScheduledFuture;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->grow()V
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->indexOf(Ljava/lang/Object;)I
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->INITIAL_CAPACITY:I
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->leader:Ljava/lang/Thread;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->lock:Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->offer(Ljava/lang/Runnable;)Z
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->offer(Ljava/lang/Runnable;JLjava/util/concurrent/TimeUnit;)Z
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->peekExpired()Ljava/util/concurrent/RunnableScheduledFuture;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->put(Ljava/lang/Runnable;)V
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->queue:[Ljava/util/concurrent/RunnableScheduledFuture;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->setIndex(Ljava/util/concurrent/RunnableScheduledFuture;I)V
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->siftDown(ILjava/util/concurrent/RunnableScheduledFuture;)V
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->siftUp(ILjava/util/concurrent/RunnableScheduledFuture;)V
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue;->size:I
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->compareTo(Ljava/util/concurrent/Delayed;)I
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->heapIndex:I
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->outerTask:Ljava/util/concurrent/RunnableScheduledFuture;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->period:J
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->sequenceNumber:J
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->setNextRunTime()V
+Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;->time:J
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->canRunInCurrentRunState(Z)Z
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->continueExistingPeriodicTasksAfterShutdown:Z
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->DEFAULT_KEEPALIVE_MILLIS:J
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->delayedExecute(Ljava/util/concurrent/RunnableScheduledFuture;)V
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->executeExistingDelayedTasksAfterShutdown:Z
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->onShutdown()V
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->overflowFree(J)J
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->reExecutePeriodic(Ljava/util/concurrent/RunnableScheduledFuture;)V
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->removeOnCancel:Z
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->sequencer:Ljava/util/concurrent/atomic/AtomicLong;
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->triggerTime(J)J
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;->triggerTime(JLjava/util/concurrent/TimeUnit;)J
+Ljava/util/concurrent/Semaphore$FairSync;-><init>(I)V
+Ljava/util/concurrent/Semaphore$NonfairSync;-><init>(I)V
+Ljava/util/concurrent/Semaphore$Sync;-><init>(I)V
+Ljava/util/concurrent/Semaphore$Sync;->drainPermits()I
+Ljava/util/concurrent/Semaphore$Sync;->getPermits()I
+Ljava/util/concurrent/Semaphore$Sync;->nonfairTryAcquireShared(I)I
+Ljava/util/concurrent/Semaphore$Sync;->reducePermits(I)V
+Ljava/util/concurrent/Semaphore;->sync:Ljava/util/concurrent/Semaphore$Sync;
+Ljava/util/concurrent/SynchronousQueue$FifoWaitQueue;-><init>()V
+Ljava/util/concurrent/SynchronousQueue$LifoWaitQueue;-><init>()V
+Ljava/util/concurrent/SynchronousQueue$Transferer;-><init>()V
+Ljava/util/concurrent/SynchronousQueue$Transferer;->transfer(Ljava/lang/Object;ZJ)Ljava/lang/Object;
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;-><init>(Ljava/lang/Object;Z)V
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->casItem(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->casNext(Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;)Z
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->isCancelled()Z
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->isData:Z
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->isOffList()Z
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->ITEM:J
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->item:Ljava/lang/Object;
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->NEXT:J
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->next:Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->tryCancel(Ljava/lang/Object;)V
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;->waiter:Ljava/lang/Thread;
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;-><init>()V
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->advanceHead(Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;)V
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->advanceTail(Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;)V
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->awaitFulfill(Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;Ljava/lang/Object;ZJ)Ljava/lang/Object;
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->casCleanMe(Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;)Z
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->clean(Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;)V
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->CLEANME:J
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->cleanMe:Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->HEAD:J
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->head:Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->TAIL:J
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->tail:Ljava/util/concurrent/SynchronousQueue$TransferQueue$QNode;
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->transfer(Ljava/lang/Object;ZJ)Ljava/lang/Object;
+Ljava/util/concurrent/SynchronousQueue$TransferQueue;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;-><init>(Ljava/lang/Object;)V
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->casNext(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;)Z
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->isCancelled()Z
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->item:Ljava/lang/Object;
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->MATCH:J
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->match:Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->mode:I
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->NEXT:J
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->next:Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->tryCancel()V
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->tryMatch(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;)Z
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;->waiter:Ljava/lang/Thread;
+Ljava/util/concurrent/SynchronousQueue$TransferStack;-><init>()V
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->awaitFulfill(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;ZJ)Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->casHead(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;)Z
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->clean(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;)V
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->DATA:I
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->FULFILLING:I
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->HEAD:J
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->head:Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->isFulfilling(I)Z
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->REQUEST:I
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->shouldSpin(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;)Z
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->snode(Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;Ljava/lang/Object;Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;I)Ljava/util/concurrent/SynchronousQueue$TransferStack$SNode;
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->transfer(Ljava/lang/Object;ZJ)Ljava/lang/Object;
+Ljava/util/concurrent/SynchronousQueue$TransferStack;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/SynchronousQueue$WaitQueue;-><init>()V
+Ljava/util/concurrent/SynchronousQueue;->MAX_TIMED_SPINS:I
+Ljava/util/concurrent/SynchronousQueue;->MAX_UNTIMED_SPINS:I
+Ljava/util/concurrent/SynchronousQueue;->qlock:Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/util/concurrent/SynchronousQueue;->SPIN_FOR_TIMEOUT_THRESHOLD:J
+Ljava/util/concurrent/SynchronousQueue;->transferer:Ljava/util/concurrent/SynchronousQueue$Transferer;
+Ljava/util/concurrent/SynchronousQueue;->waitingConsumers:Ljava/util/concurrent/SynchronousQueue$WaitQueue;
+Ljava/util/concurrent/SynchronousQueue;->waitingProducers:Ljava/util/concurrent/SynchronousQueue$WaitQueue;
+Ljava/util/concurrent/ThreadLocalRandom$RandomDoublesSpliterator;-><init>(JJDD)V
+Ljava/util/concurrent/ThreadLocalRandom$RandomDoublesSpliterator;->bound:D
+Ljava/util/concurrent/ThreadLocalRandom$RandomDoublesSpliterator;->fence:J
+Ljava/util/concurrent/ThreadLocalRandom$RandomDoublesSpliterator;->index:J
+Ljava/util/concurrent/ThreadLocalRandom$RandomDoublesSpliterator;->origin:D
+Ljava/util/concurrent/ThreadLocalRandom$RandomIntsSpliterator;-><init>(JJII)V
+Ljava/util/concurrent/ThreadLocalRandom$RandomIntsSpliterator;->bound:I
+Ljava/util/concurrent/ThreadLocalRandom$RandomIntsSpliterator;->fence:J
+Ljava/util/concurrent/ThreadLocalRandom$RandomIntsSpliterator;->index:J
+Ljava/util/concurrent/ThreadLocalRandom$RandomIntsSpliterator;->origin:I
+Ljava/util/concurrent/ThreadLocalRandom$RandomLongsSpliterator;-><init>(JJJJ)V
+Ljava/util/concurrent/ThreadLocalRandom$RandomLongsSpliterator;->bound:J
+Ljava/util/concurrent/ThreadLocalRandom$RandomLongsSpliterator;->fence:J
+Ljava/util/concurrent/ThreadLocalRandom$RandomLongsSpliterator;->index:J
+Ljava/util/concurrent/ThreadLocalRandom$RandomLongsSpliterator;->origin:J
+Ljava/util/concurrent/ThreadLocalRandom;-><init>()V
+Ljava/util/concurrent/ThreadLocalRandom;->advanceProbe(I)I
+Ljava/util/concurrent/ThreadLocalRandom;->BAD_BOUND:Ljava/lang/String;
+Ljava/util/concurrent/ThreadLocalRandom;->BAD_RANGE:Ljava/lang/String;
+Ljava/util/concurrent/ThreadLocalRandom;->BAD_SIZE:Ljava/lang/String;
+Ljava/util/concurrent/ThreadLocalRandom;->DOUBLE_UNIT:D
+Ljava/util/concurrent/ThreadLocalRandom;->FLOAT_UNIT:F
+Ljava/util/concurrent/ThreadLocalRandom;->GAMMA:J
+Ljava/util/concurrent/ThreadLocalRandom;->getProbe()I
+Ljava/util/concurrent/ThreadLocalRandom;->initialized:Z
+Ljava/util/concurrent/ThreadLocalRandom;->instance:Ljava/util/concurrent/ThreadLocalRandom;
+Ljava/util/concurrent/ThreadLocalRandom;->internalNextDouble(DD)D
+Ljava/util/concurrent/ThreadLocalRandom;->internalNextInt(II)I
+Ljava/util/concurrent/ThreadLocalRandom;->internalNextLong(JJ)J
+Ljava/util/concurrent/ThreadLocalRandom;->localInit()V
+Ljava/util/concurrent/ThreadLocalRandom;->mix32(J)I
+Ljava/util/concurrent/ThreadLocalRandom;->mix64(J)J
+Ljava/util/concurrent/ThreadLocalRandom;->nextLocalGaussian:Ljava/lang/ThreadLocal;
+Ljava/util/concurrent/ThreadLocalRandom;->nextSecondarySeed()I
+Ljava/util/concurrent/ThreadLocalRandom;->nextSeed()J
+Ljava/util/concurrent/ThreadLocalRandom;->PROBE:J
+Ljava/util/concurrent/ThreadLocalRandom;->probeGenerator:Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/util/concurrent/ThreadLocalRandom;->PROBE_INCREMENT:I
+Ljava/util/concurrent/ThreadLocalRandom;->SECONDARY:J
+Ljava/util/concurrent/ThreadLocalRandom;->SEED:J
+Ljava/util/concurrent/ThreadLocalRandom;->seeder:Ljava/util/concurrent/atomic/AtomicLong;
+Ljava/util/concurrent/ThreadLocalRandom;->SEEDER_INCREMENT:J
+Ljava/util/concurrent/ThreadLocalRandom;->U:Lsun/misc/Unsafe;
+Ljava/util/concurrent/ThreadPoolExecutor$Worker;->completedTasks:J
+Ljava/util/concurrent/ThreadPoolExecutor$Worker;->firstTask:Ljava/lang/Runnable;
+Ljava/util/concurrent/ThreadPoolExecutor$Worker;->interruptIfStarted()V
+Ljava/util/concurrent/ThreadPoolExecutor$Worker;->isLocked()Z
+Ljava/util/concurrent/ThreadPoolExecutor$Worker;->lock()V
+Ljava/util/concurrent/ThreadPoolExecutor$Worker;->thread:Ljava/lang/Thread;
+Ljava/util/concurrent/ThreadPoolExecutor$Worker;->tryLock()Z
+Ljava/util/concurrent/ThreadPoolExecutor$Worker;->unlock()V
+Ljava/util/concurrent/ThreadPoolExecutor;->addWorker(Ljava/lang/Runnable;Z)Z
+Ljava/util/concurrent/ThreadPoolExecutor;->addWorkerFailed(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V
+Ljava/util/concurrent/ThreadPoolExecutor;->advanceRunState(I)V
+Ljava/util/concurrent/ThreadPoolExecutor;->CAPACITY:I
+Ljava/util/concurrent/ThreadPoolExecutor;->checkShutdownAccess()V
+Ljava/util/concurrent/ThreadPoolExecutor;->compareAndDecrementWorkerCount(I)Z
+Ljava/util/concurrent/ThreadPoolExecutor;->compareAndIncrementWorkerCount(I)Z
+Ljava/util/concurrent/ThreadPoolExecutor;->completedTaskCount:J
+Ljava/util/concurrent/ThreadPoolExecutor;->corePoolSize:I
+Ljava/util/concurrent/ThreadPoolExecutor;->COUNT_BITS:I
+Ljava/util/concurrent/ThreadPoolExecutor;->ctlOf(II)I
+Ljava/util/concurrent/ThreadPoolExecutor;->decrementWorkerCount()V
+Ljava/util/concurrent/ThreadPoolExecutor;->drainQueue()Ljava/util/List;
+Ljava/util/concurrent/ThreadPoolExecutor;->ensurePrestart()V
+Ljava/util/concurrent/ThreadPoolExecutor;->getTask()Ljava/lang/Runnable;
+Ljava/util/concurrent/ThreadPoolExecutor;->handler:Ljava/util/concurrent/RejectedExecutionHandler;
+Ljava/util/concurrent/ThreadPoolExecutor;->interruptIdleWorkers()V
+Ljava/util/concurrent/ThreadPoolExecutor;->interruptIdleWorkers(Z)V
+Ljava/util/concurrent/ThreadPoolExecutor;->interruptWorkers()V
+Ljava/util/concurrent/ThreadPoolExecutor;->isRunning(I)Z
+Ljava/util/concurrent/ThreadPoolExecutor;->isRunningOrShutdown(Z)Z
+Ljava/util/concurrent/ThreadPoolExecutor;->keepAliveTime:J
+Ljava/util/concurrent/ThreadPoolExecutor;->largestPoolSize:I
+Ljava/util/concurrent/ThreadPoolExecutor;->maximumPoolSize:I
+Ljava/util/concurrent/ThreadPoolExecutor;->ONLY_ONE:Z
+Ljava/util/concurrent/ThreadPoolExecutor;->onShutdown()V
+Ljava/util/concurrent/ThreadPoolExecutor;->processWorkerExit(Ljava/util/concurrent/ThreadPoolExecutor$Worker;Z)V
+Ljava/util/concurrent/ThreadPoolExecutor;->reject(Ljava/lang/Runnable;)V
+Ljava/util/concurrent/ThreadPoolExecutor;->RUNNING:I
+Ljava/util/concurrent/ThreadPoolExecutor;->runStateAtLeast(II)Z
+Ljava/util/concurrent/ThreadPoolExecutor;->runStateLessThan(II)Z
+Ljava/util/concurrent/ThreadPoolExecutor;->runStateOf(I)I
+Ljava/util/concurrent/ThreadPoolExecutor;->runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V
+Ljava/util/concurrent/ThreadPoolExecutor;->SHUTDOWN:I
+Ljava/util/concurrent/ThreadPoolExecutor;->shutdownPerm:Ljava/lang/RuntimePermission;
+Ljava/util/concurrent/ThreadPoolExecutor;->STOP:I
+Ljava/util/concurrent/ThreadPoolExecutor;->TERMINATED:I
+Ljava/util/concurrent/ThreadPoolExecutor;->termination:Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/ThreadPoolExecutor;->threadFactory:Ljava/util/concurrent/ThreadFactory;
+Ljava/util/concurrent/ThreadPoolExecutor;->TIDYING:I
+Ljava/util/concurrent/ThreadPoolExecutor;->tryTerminate()V
+Ljava/util/concurrent/ThreadPoolExecutor;->workerCountOf(I)I
+Ljava/util/concurrent/ThreadPoolExecutor;->workers:Ljava/util/HashSet;
+Ljava/util/concurrent/ThreadPoolExecutor;->workQueue:Ljava/util/concurrent/BlockingQueue;
+Ljava/util/concurrent/TimeUnit;->C0:J
+Ljava/util/concurrent/TimeUnit;->C1:J
+Ljava/util/concurrent/TimeUnit;->C2:J
+Ljava/util/concurrent/TimeUnit;->C3:J
+Ljava/util/concurrent/TimeUnit;->C4:J
+Ljava/util/concurrent/TimeUnit;->C5:J
+Ljava/util/concurrent/TimeUnit;->C6:J
+Ljava/util/concurrent/TimeUnit;->excessNanos(JJ)I
+Ljava/util/concurrent/TimeUnit;->MAX:J
+Ljava/util/concurrent/TimeUnit;->x(JJJ)J
+Ljava/util/Currency;-><init>(Landroid/icu/util/Currency;)V
+Ljava/util/Currency;->available:Ljava/util/HashSet;
+Ljava/util/Currency;->currencyCode:Ljava/lang/String;
+Ljava/util/Currency;->icuCurrency:Landroid/icu/util/Currency;
+Ljava/util/Currency;->instances:Ljava/util/concurrent/ConcurrentMap;
+Ljava/util/Date;->cdate:Lsun/util/calendar/BaseCalendar$Date;
+Ljava/util/Date;->convertToAbbr(Ljava/lang/StringBuilder;Ljava/lang/String;)Ljava/lang/StringBuilder;
+Ljava/util/Date;->defaultCenturyStart:I
+Ljava/util/Date;->fastTime:J
+Ljava/util/Date;->gcal:Lsun/util/calendar/BaseCalendar;
+Ljava/util/Date;->getCalendarDate()Lsun/util/calendar/BaseCalendar$Date;
+Ljava/util/Date;->getCalendarSystem(I)Lsun/util/calendar/BaseCalendar;
+Ljava/util/Date;->getCalendarSystem(J)Lsun/util/calendar/BaseCalendar;
+Ljava/util/Date;->getCalendarSystem(Lsun/util/calendar/BaseCalendar$Date;)Lsun/util/calendar/BaseCalendar;
+Ljava/util/Date;->getJulianCalendar()Lsun/util/calendar/BaseCalendar;
+Ljava/util/Date;->getMillisOf(Ljava/util/Date;)J
+Ljava/util/Date;->getTimeImpl()J
+Ljava/util/Date;->jcal:Lsun/util/calendar/BaseCalendar;
+Ljava/util/Date;->normalize()Lsun/util/calendar/BaseCalendar$Date;
+Ljava/util/Date;->normalize(Lsun/util/calendar/BaseCalendar$Date;)Lsun/util/calendar/BaseCalendar$Date;
+Ljava/util/Date;->ttb:[I
+Ljava/util/Date;->wtb:[Ljava/lang/String;
+Ljava/util/DoubleSummaryStatistics;->count:J
+Ljava/util/DoubleSummaryStatistics;->max:D
+Ljava/util/DoubleSummaryStatistics;->min:D
+Ljava/util/DoubleSummaryStatistics;->simpleSum:D
+Ljava/util/DoubleSummaryStatistics;->sum:D
+Ljava/util/DoubleSummaryStatistics;->sumCompensation:D
+Ljava/util/DoubleSummaryStatistics;->sumWithCompensation(D)V
+Ljava/util/DuplicateFormatFlagsException;->flags:Ljava/lang/String;
+Ljava/util/EnumMap$EntryIterator$Entry;->checkIndexForEntryUse()V
+Ljava/util/EnumMap$EntryIterator$Entry;->index:I
+Ljava/util/EnumMap$EntryIterator;->lastReturnedEntry:Ljava/util/EnumMap$EntryIterator$Entry;
+Ljava/util/EnumMap$EntrySet;->fillEntryArray([Ljava/lang/Object;)[Ljava/lang/Object;
+Ljava/util/EnumMap$EnumMapIterator;->checkLastReturnedIndex()V
+Ljava/util/EnumMap$EnumMapIterator;->index:I
+Ljava/util/EnumMap$EnumMapIterator;->lastReturnedIndex:I
+Ljava/util/EnumMap;->containsMapping(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/EnumMap;->entryHashCode(I)I
+Ljava/util/EnumMap;->entrySet:Ljava/util/Set;
+Ljava/util/EnumMap;->equals(Ljava/util/EnumMap;)Z
+Ljava/util/EnumMap;->getKeyUniverse(Ljava/lang/Class;)[Ljava/lang/Enum;
+Ljava/util/EnumMap;->isValidKey(Ljava/lang/Object;)Z
+Ljava/util/EnumMap;->keyUniverse:[Ljava/lang/Enum;
+Ljava/util/EnumMap;->maskNull(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/EnumMap;->NULL:Ljava/lang/Object;
+Ljava/util/EnumMap;->removeMapping(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/EnumMap;->size:I
+Ljava/util/EnumMap;->typeCheck(Ljava/lang/Enum;)V
+Ljava/util/EnumMap;->unmaskNull(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/EnumMap;->vals:[Ljava/lang/Object;
+Ljava/util/EnumMap;->ZERO_LENGTH_ENUM_ARRAY:[Ljava/lang/Enum;
+Ljava/util/EnumSet$SerializationProxy;-><init>(Ljava/util/EnumSet;)V
+Ljava/util/EnumSet$SerializationProxy;->elements:[Ljava/lang/Enum;
+Ljava/util/EnumSet$SerializationProxy;->elementType:Ljava/lang/Class;
+Ljava/util/EnumSet;-><init>(Ljava/lang/Class;[Ljava/lang/Enum;)V
+Ljava/util/EnumSet;->addAll()V
+Ljava/util/EnumSet;->addRange(Ljava/lang/Enum;Ljava/lang/Enum;)V
+Ljava/util/EnumSet;->complement()V
+Ljava/util/EnumSet;->getUniverse(Ljava/lang/Class;)[Ljava/lang/Enum;
+Ljava/util/EnumSet;->typeCheck(Ljava/lang/Enum;)V
+Ljava/util/EnumSet;->universe:[Ljava/lang/Enum;
+Ljava/util/EnumSet;->ZERO_LENGTH_ENUM_ARRAY:[Ljava/lang/Enum;
+Ljava/util/EventListenerProxy;->listener:Ljava/util/EventListener;
+Ljava/util/FormatFlagsConversionMismatchException;->c:C
+Ljava/util/FormatFlagsConversionMismatchException;->f:Ljava/lang/String;
+Ljava/util/FormattableFlags;-><init>()V
+Ljava/util/Formatter$Conversion;-><init>()V
+Ljava/util/Formatter$Conversion;->BOOLEAN:C
+Ljava/util/Formatter$Conversion;->BOOLEAN_UPPER:C
+Ljava/util/Formatter$Conversion;->CHARACTER:C
+Ljava/util/Formatter$Conversion;->CHARACTER_UPPER:C
+Ljava/util/Formatter$Conversion;->DATE_TIME:C
+Ljava/util/Formatter$Conversion;->DATE_TIME_UPPER:C
+Ljava/util/Formatter$Conversion;->DECIMAL_FLOAT:C
+Ljava/util/Formatter$Conversion;->DECIMAL_INTEGER:C
+Ljava/util/Formatter$Conversion;->GENERAL:C
+Ljava/util/Formatter$Conversion;->GENERAL_UPPER:C
+Ljava/util/Formatter$Conversion;->HASHCODE:C
+Ljava/util/Formatter$Conversion;->HASHCODE_UPPER:C
+Ljava/util/Formatter$Conversion;->HEXADECIMAL_FLOAT:C
+Ljava/util/Formatter$Conversion;->HEXADECIMAL_FLOAT_UPPER:C
+Ljava/util/Formatter$Conversion;->HEXADECIMAL_INTEGER:C
+Ljava/util/Formatter$Conversion;->HEXADECIMAL_INTEGER_UPPER:C
+Ljava/util/Formatter$Conversion;->isCharacter(C)Z
+Ljava/util/Formatter$Conversion;->isFloat(C)Z
+Ljava/util/Formatter$Conversion;->isGeneral(C)Z
+Ljava/util/Formatter$Conversion;->isInteger(C)Z
+Ljava/util/Formatter$Conversion;->isText(C)Z
+Ljava/util/Formatter$Conversion;->isValid(C)Z
+Ljava/util/Formatter$Conversion;->LINE_SEPARATOR:C
+Ljava/util/Formatter$Conversion;->OCTAL_INTEGER:C
+Ljava/util/Formatter$Conversion;->PERCENT_SIGN:C
+Ljava/util/Formatter$Conversion;->SCIENTIFIC:C
+Ljava/util/Formatter$Conversion;->SCIENTIFIC_UPPER:C
+Ljava/util/Formatter$Conversion;->STRING:C
+Ljava/util/Formatter$Conversion;->STRING_UPPER:C
+Ljava/util/Formatter$DateTime;-><init>()V
+Ljava/util/Formatter$DateTime;->AM_PM:C
+Ljava/util/Formatter$DateTime;->CENTURY:C
+Ljava/util/Formatter$DateTime;->DATE:C
+Ljava/util/Formatter$DateTime;->DATE_TIME:C
+Ljava/util/Formatter$DateTime;->DAY_OF_MONTH:C
+Ljava/util/Formatter$DateTime;->DAY_OF_MONTH_0:C
+Ljava/util/Formatter$DateTime;->DAY_OF_YEAR:C
+Ljava/util/Formatter$DateTime;->HOUR:C
+Ljava/util/Formatter$DateTime;->HOUR_0:C
+Ljava/util/Formatter$DateTime;->HOUR_OF_DAY:C
+Ljava/util/Formatter$DateTime;->HOUR_OF_DAY_0:C
+Ljava/util/Formatter$DateTime;->ISO_STANDARD_DATE:C
+Ljava/util/Formatter$DateTime;->isValid(C)Z
+Ljava/util/Formatter$DateTime;->MILLISECOND:C
+Ljava/util/Formatter$DateTime;->MILLISECOND_SINCE_EPOCH:C
+Ljava/util/Formatter$DateTime;->MINUTE:C
+Ljava/util/Formatter$DateTime;->MONTH:C
+Ljava/util/Formatter$DateTime;->NAME_OF_DAY:C
+Ljava/util/Formatter$DateTime;->NAME_OF_DAY_ABBREV:C
+Ljava/util/Formatter$DateTime;->NAME_OF_MONTH:C
+Ljava/util/Formatter$DateTime;->NAME_OF_MONTH_ABBREV:C
+Ljava/util/Formatter$DateTime;->NAME_OF_MONTH_ABBREV_X:C
+Ljava/util/Formatter$DateTime;->NANOSECOND:C
+Ljava/util/Formatter$DateTime;->SECOND:C
+Ljava/util/Formatter$DateTime;->SECONDS_SINCE_EPOCH:C
+Ljava/util/Formatter$DateTime;->TIME:C
+Ljava/util/Formatter$DateTime;->TIME_12_HOUR:C
+Ljava/util/Formatter$DateTime;->TIME_24_HOUR:C
+Ljava/util/Formatter$DateTime;->YEAR_2:C
+Ljava/util/Formatter$DateTime;->YEAR_4:C
+Ljava/util/Formatter$DateTime;->ZONE:C
+Ljava/util/Formatter$DateTime;->ZONE_NUMERIC:C
+Ljava/util/Formatter$FixedString;->index()I
+Ljava/util/Formatter$FixedString;->print(Ljava/lang/Object;Ljava/util/Locale;)V
+Ljava/util/Formatter$FixedString;->s:Ljava/lang/String;
+Ljava/util/Formatter$Flags;-><init>(I)V
+Ljava/util/Formatter$Flags;->add(Ljava/util/Formatter$Flags;)Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->ALTERNATE:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->contains(Ljava/util/Formatter$Flags;)Z
+Ljava/util/Formatter$Flags;->dup()Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->flags:I
+Ljava/util/Formatter$Flags;->GROUP:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->LEADING_SPACE:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->LEFT_JUSTIFY:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->NONE:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->PARENTHESES:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->parse(C)Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->parse(Ljava/lang/String;)Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->PLUS:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->PREVIOUS:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->remove(Ljava/util/Formatter$Flags;)Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->toString(Ljava/util/Formatter$Flags;)Ljava/lang/String;
+Ljava/util/Formatter$Flags;->UPPERCASE:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$Flags;->valueOf()I
+Ljava/util/Formatter$Flags;->ZERO_PAD:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->dot:Z
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->exp:Ljava/lang/StringBuilder;
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->exponent()[C
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->hasDot()Z
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->layout(Ljava/math/BigInteger;ILjava/util/Formatter$BigDecimalLayoutForm;)V
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->layoutChars()[C
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->mant:Ljava/lang/StringBuilder;
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->mantissa()[C
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->scale()I
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->scale:I
+Ljava/util/Formatter$FormatSpecifier$BigDecimalLayout;->toCharArray(Ljava/lang/StringBuilder;)[C
+Ljava/util/Formatter$FormatSpecifier;->addDot([C)[C
+Ljava/util/Formatter$FormatSpecifier;->addZeros([CI)[C
+Ljava/util/Formatter$FormatSpecifier;->adjustWidth(ILjava/util/Formatter$Flags;Z)I
+Ljava/util/Formatter$FormatSpecifier;->c:C
+Ljava/util/Formatter$FormatSpecifier;->checkCharacter()V
+Ljava/util/Formatter$FormatSpecifier;->checkDateTime()V
+Ljava/util/Formatter$FormatSpecifier;->checkFloat()V
+Ljava/util/Formatter$FormatSpecifier;->checkGeneral()V
+Ljava/util/Formatter$FormatSpecifier;->checkInteger()V
+Ljava/util/Formatter$FormatSpecifier;->checkNumeric()V
+Ljava/util/Formatter$FormatSpecifier;->checkText()V
+Ljava/util/Formatter$FormatSpecifier;->conversion()C
+Ljava/util/Formatter$FormatSpecifier;->conversion(Ljava/lang/String;)C
+Ljava/util/Formatter$FormatSpecifier;->dt:Z
+Ljava/util/Formatter$FormatSpecifier;->f:Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$FormatSpecifier;->failConversion(CLjava/lang/Object;)V
+Ljava/util/Formatter$FormatSpecifier;->failMismatch(Ljava/util/Formatter$Flags;C)V
+Ljava/util/Formatter$FormatSpecifier;->flags()Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$FormatSpecifier;->flags(Ljava/lang/String;)Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$FormatSpecifier;->getZero(Ljava/util/Locale;)C
+Ljava/util/Formatter$FormatSpecifier;->hexDouble(DI)Ljava/lang/String;
+Ljava/util/Formatter$FormatSpecifier;->index()I
+Ljava/util/Formatter$FormatSpecifier;->index(Ljava/lang/String;)I
+Ljava/util/Formatter$FormatSpecifier;->index:I
+Ljava/util/Formatter$FormatSpecifier;->justify(Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/Formatter$FormatSpecifier;->leadingSign(Ljava/lang/StringBuilder;Z)Ljava/lang/StringBuilder;
+Ljava/util/Formatter$FormatSpecifier;->localizedMagnitude(Ljava/lang/StringBuilder;JLjava/util/Formatter$Flags;ILjava/util/Locale;)Ljava/lang/StringBuilder;
+Ljava/util/Formatter$FormatSpecifier;->localizedMagnitude(Ljava/lang/StringBuilder;[CLjava/util/Formatter$Flags;ILjava/util/Locale;)Ljava/lang/StringBuilder;
+Ljava/util/Formatter$FormatSpecifier;->precision()I
+Ljava/util/Formatter$FormatSpecifier;->precision(Ljava/lang/String;)I
+Ljava/util/Formatter$FormatSpecifier;->precision:I
+Ljava/util/Formatter$FormatSpecifier;->print(BLjava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->print(DLjava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->print(FLjava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->print(ILjava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->print(JLjava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->print(Ljava/lang/Object;Ljava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->print(Ljava/lang/String;)V
+Ljava/util/Formatter$FormatSpecifier;->print(Ljava/lang/StringBuilder;DLjava/util/Locale;Ljava/util/Formatter$Flags;CIZ)V
+Ljava/util/Formatter$FormatSpecifier;->print(Ljava/lang/StringBuilder;Ljava/math/BigDecimal;Ljava/util/Locale;Ljava/util/Formatter$Flags;CIZ)V
+Ljava/util/Formatter$FormatSpecifier;->print(Ljava/lang/StringBuilder;Ljava/time/temporal/TemporalAccessor;CLjava/util/Locale;)Ljava/lang/Appendable;
+Ljava/util/Formatter$FormatSpecifier;->print(Ljava/lang/StringBuilder;Ljava/util/Calendar;CLjava/util/Locale;)Ljava/lang/Appendable;
+Ljava/util/Formatter$FormatSpecifier;->print(Ljava/math/BigDecimal;Ljava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->print(Ljava/math/BigInteger;Ljava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->print(Ljava/time/temporal/TemporalAccessor;CLjava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->print(Ljava/util/Calendar;CLjava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->print(SLjava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->printBoolean(Ljava/lang/Object;)V
+Ljava/util/Formatter$FormatSpecifier;->printCharacter(Ljava/lang/Object;)V
+Ljava/util/Formatter$FormatSpecifier;->printDateTime(Ljava/lang/Object;Ljava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->printFloat(Ljava/lang/Object;Ljava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->printHashCode(Ljava/lang/Object;)V
+Ljava/util/Formatter$FormatSpecifier;->printInteger(Ljava/lang/Object;Ljava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->printString(Ljava/lang/Object;Ljava/util/Locale;)V
+Ljava/util/Formatter$FormatSpecifier;->trailingSign(Ljava/lang/StringBuilder;Z)Ljava/lang/StringBuilder;
+Ljava/util/Formatter$FormatSpecifier;->trailingZeros([CI)[C
+Ljava/util/Formatter$FormatSpecifier;->width()I
+Ljava/util/Formatter$FormatSpecifier;->width(Ljava/lang/String;)I
+Ljava/util/Formatter$FormatSpecifier;->width:I
+Ljava/util/Formatter$FormatSpecifierParser;->advance()C
+Ljava/util/Formatter$FormatSpecifierParser;->back(I)V
+Ljava/util/Formatter$FormatSpecifierParser;->conv:Ljava/lang/String;
+Ljava/util/Formatter$FormatSpecifierParser;->cursor:I
+Ljava/util/Formatter$FormatSpecifierParser;->FLAGS:Ljava/lang/String;
+Ljava/util/Formatter$FormatSpecifierParser;->flags:Ljava/lang/String;
+Ljava/util/Formatter$FormatSpecifierParser;->format:Ljava/lang/String;
+Ljava/util/Formatter$FormatSpecifierParser;->fs:Ljava/util/Formatter$FormatSpecifier;
+Ljava/util/Formatter$FormatSpecifierParser;->getEndIdx()I
+Ljava/util/Formatter$FormatSpecifierParser;->getFormatSpecifier()Ljava/util/Formatter$FormatSpecifier;
+Ljava/util/Formatter$FormatSpecifierParser;->index:Ljava/lang/String;
+Ljava/util/Formatter$FormatSpecifierParser;->isEnd()Z
+Ljava/util/Formatter$FormatSpecifierParser;->nextInt()Ljava/lang/String;
+Ljava/util/Formatter$FormatSpecifierParser;->nextIsInt()Z
+Ljava/util/Formatter$FormatSpecifierParser;->peek()C
+Ljava/util/Formatter$FormatSpecifierParser;->precision:Ljava/lang/String;
+Ljava/util/Formatter$FormatSpecifierParser;->tT:Ljava/lang/String;
+Ljava/util/Formatter$FormatSpecifierParser;->width:Ljava/lang/String;
+Ljava/util/Formatter$FormatString;->index()I
+Ljava/util/Formatter$FormatString;->print(Ljava/lang/Object;Ljava/util/Locale;)V
+Ljava/util/Formatter;-><init>(Ljava/nio/charset/Charset;Ljava/util/Locale;Ljava/io/File;)V
+Ljava/util/Formatter;-><init>(Ljava/util/Locale;Ljava/lang/Appendable;)V
+Ljava/util/Formatter;->a:Ljava/lang/Appendable;
+Ljava/util/Formatter;->ensureOpen()V
+Ljava/util/Formatter;->getZero(Ljava/util/Locale;)C
+Ljava/util/Formatter;->l:Ljava/util/Locale;
+Ljava/util/Formatter;->lastException:Ljava/io/IOException;
+Ljava/util/Formatter;->MAX_FD_CHARS:I
+Ljava/util/Formatter;->nonNullAppendable(Ljava/lang/Appendable;)Ljava/lang/Appendable;
+Ljava/util/Formatter;->parse(Ljava/lang/String;)[Ljava/util/Formatter$FormatString;
+Ljava/util/Formatter;->scaleUp:D
+Ljava/util/Formatter;->toCharset(Ljava/lang/String;)Ljava/nio/charset/Charset;
+Ljava/util/Formatter;->zero:C
+Ljava/util/GregorianCalendar;-><init>(IIIIIII)V
+Ljava/util/GregorianCalendar;-><init>(J)V
+Ljava/util/GregorianCalendar;-><init>(Ljava/util/TimeZone;Ljava/util/Locale;Z)V
+Ljava/util/GregorianCalendar;->actualMonthLength()I
+Ljava/util/GregorianCalendar;->adjustDstOffsetForInvalidWallClock(JLjava/util/TimeZone;I)I
+Ljava/util/GregorianCalendar;->adjustForZoneAndDaylightSavingsTime(IJLjava/util/TimeZone;)J
+Ljava/util/GregorianCalendar;->BCE:I
+Ljava/util/GregorianCalendar;->cachedFixedDate:J
+Ljava/util/GregorianCalendar;->calsys:Lsun/util/calendar/BaseCalendar;
+Ljava/util/GregorianCalendar;->cdate:Lsun/util/calendar/BaseCalendar$Date;
+Ljava/util/GregorianCalendar;->CE:I
+Ljava/util/GregorianCalendar;->computeFields(II)I
+Ljava/util/GregorianCalendar;->DEFAULT_GREGORIAN_CUTOVER:J
+Ljava/util/GregorianCalendar;->EPOCH_OFFSET:I
+Ljava/util/GregorianCalendar;->EPOCH_YEAR:I
+Ljava/util/GregorianCalendar;->gcal:Lsun/util/calendar/Gregorian;
+Ljava/util/GregorianCalendar;->gdate:Lsun/util/calendar/BaseCalendar$Date;
+Ljava/util/GregorianCalendar;->getCalendarDate(J)Lsun/util/calendar/BaseCalendar$Date;
+Ljava/util/GregorianCalendar;->getCurrentFixedDate()J
+Ljava/util/GregorianCalendar;->getCutoverCalendarSystem()Lsun/util/calendar/BaseCalendar;
+Ljava/util/GregorianCalendar;->getFixedDate(Lsun/util/calendar/BaseCalendar;II)J
+Ljava/util/GregorianCalendar;->getFixedDateJan1(Lsun/util/calendar/BaseCalendar$Date;J)J
+Ljava/util/GregorianCalendar;->getFixedDateMonth1(Lsun/util/calendar/BaseCalendar$Date;J)J
+Ljava/util/GregorianCalendar;->getGregorianCutoverDate()Lsun/util/calendar/BaseCalendar$Date;
+Ljava/util/GregorianCalendar;->getJulianCalendarSystem()Lsun/util/calendar/BaseCalendar;
+Ljava/util/GregorianCalendar;->getLastJulianDate()Lsun/util/calendar/BaseCalendar$Date;
+Ljava/util/GregorianCalendar;->getNormalizedCalendar()Ljava/util/GregorianCalendar;
+Ljava/util/GregorianCalendar;->getRolledValue(IIII)I
+Ljava/util/GregorianCalendar;->getWeekNumber(JJ)I
+Ljava/util/GregorianCalendar;->getYearOffsetInMillis()J
+Ljava/util/GregorianCalendar;->gregorianCutover:J
+Ljava/util/GregorianCalendar;->gregorianCutoverDate:J
+Ljava/util/GregorianCalendar;->gregorianCutoverYear:I
+Ljava/util/GregorianCalendar;->gregorianCutoverYearJulian:I
+Ljava/util/GregorianCalendar;->internalGetEra()I
+Ljava/util/GregorianCalendar;->isCutoverYear(I)Z
+Ljava/util/GregorianCalendar;->jcal:Lsun/util/calendar/JulianCalendar;
+Ljava/util/GregorianCalendar;->jeras:[Lsun/util/calendar/Era;
+Ljava/util/GregorianCalendar;->LEAP_MONTH_LENGTH:[I
+Ljava/util/GregorianCalendar;->LEAST_MAX_VALUES:[I
+Ljava/util/GregorianCalendar;->MAX_VALUES:[I
+Ljava/util/GregorianCalendar;->MIN_VALUES:[I
+Ljava/util/GregorianCalendar;->monthLength(I)I
+Ljava/util/GregorianCalendar;->monthLength(II)I
+Ljava/util/GregorianCalendar;->MONTH_LENGTH:[I
+Ljava/util/GregorianCalendar;->ONE_DAY:J
+Ljava/util/GregorianCalendar;->ONE_HOUR:I
+Ljava/util/GregorianCalendar;->ONE_MINUTE:I
+Ljava/util/GregorianCalendar;->ONE_SECOND:I
+Ljava/util/GregorianCalendar;->ONE_WEEK:J
+Ljava/util/GregorianCalendar;->originalFields:[I
+Ljava/util/GregorianCalendar;->pinDayOfMonth()V
+Ljava/util/GregorianCalendar;->setGregorianChange(J)V
+Ljava/util/GregorianCalendar;->yearLength()I
+Ljava/util/GregorianCalendar;->yearLength(I)I
+Ljava/util/GregorianCalendar;->zoneOffsets:[I
+Ljava/util/HashMap$EntrySet;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/HashMap$EntrySpliterator;-><init>(Ljava/util/HashMap;IIII)V
+Ljava/util/HashMap$EntrySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/HashMap$EntrySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/HashMap$HashIterator;->current:Ljava/util/HashMap$Node;
+Ljava/util/HashMap$HashIterator;->expectedModCount:I
+Ljava/util/HashMap$HashIterator;->index:I
+Ljava/util/HashMap$HashIterator;->next:Ljava/util/HashMap$Node;
+Ljava/util/HashMap$HashIterator;->nextNode()Ljava/util/HashMap$Node;
+Ljava/util/HashMap$HashMapSpliterator;-><init>(Ljava/util/HashMap;IIII)V
+Ljava/util/HashMap$HashMapSpliterator;->current:Ljava/util/HashMap$Node;
+Ljava/util/HashMap$HashMapSpliterator;->est:I
+Ljava/util/HashMap$HashMapSpliterator;->estimateSize()J
+Ljava/util/HashMap$HashMapSpliterator;->expectedModCount:I
+Ljava/util/HashMap$HashMapSpliterator;->fence:I
+Ljava/util/HashMap$HashMapSpliterator;->getFence()I
+Ljava/util/HashMap$HashMapSpliterator;->index:I
+Ljava/util/HashMap$HashMapSpliterator;->map:Ljava/util/HashMap;
+Ljava/util/HashMap$KeySet;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/HashMap$KeySpliterator;-><init>(Ljava/util/HashMap;IIII)V
+Ljava/util/HashMap$KeySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/HashMap$KeySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/HashMap$Node;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)V
+Ljava/util/HashMap$Node;->hash:I
+Ljava/util/HashMap$TreeNode;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)V
+Ljava/util/HashMap$TreeNode;->balanceDeletion(Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;)Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->balanceInsertion(Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;)Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->checkInvariants(Ljava/util/HashMap$TreeNode;)Z
+Ljava/util/HashMap$TreeNode;->find(ILjava/lang/Object;Ljava/lang/Class;)Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->getTreeNode(ILjava/lang/Object;)Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->left:Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->moveRootToFront([Ljava/util/HashMap$Node;Ljava/util/HashMap$TreeNode;)V
+Ljava/util/HashMap$TreeNode;->parent:Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->prev:Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->putTreeVal(Ljava/util/HashMap;[Ljava/util/HashMap$Node;ILjava/lang/Object;Ljava/lang/Object;)Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->red:Z
+Ljava/util/HashMap$TreeNode;->removeTreeNode(Ljava/util/HashMap;[Ljava/util/HashMap$Node;Z)V
+Ljava/util/HashMap$TreeNode;->right:Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->root()Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->rotateLeft(Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;)Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->rotateRight(Ljava/util/HashMap$TreeNode;Ljava/util/HashMap$TreeNode;)Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$TreeNode;->split(Ljava/util/HashMap;[Ljava/util/HashMap$Node;II)V
+Ljava/util/HashMap$TreeNode;->tieBreakOrder(Ljava/lang/Object;Ljava/lang/Object;)I
+Ljava/util/HashMap$TreeNode;->treeify([Ljava/util/HashMap$Node;)V
+Ljava/util/HashMap$TreeNode;->untreeify(Ljava/util/HashMap;)Ljava/util/HashMap$Node;
+Ljava/util/HashMap$Values;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/HashMap$ValueSpliterator;-><init>(Ljava/util/HashMap;IIII)V
+Ljava/util/HashMap$ValueSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/HashMap$ValueSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/HashMap;->afterNodeAccess(Ljava/util/HashMap$Node;)V
+Ljava/util/HashMap;->afterNodeInsertion(Z)V
+Ljava/util/HashMap;->afterNodeRemoval(Ljava/util/HashMap$Node;)V
+Ljava/util/HashMap;->capacity()I
+Ljava/util/HashMap;->comparableClassFor(Ljava/lang/Object;)Ljava/lang/Class;
+Ljava/util/HashMap;->compareComparables(Ljava/lang/Class;Ljava/lang/Object;Ljava/lang/Object;)I
+Ljava/util/HashMap;->DEFAULT_INITIAL_CAPACITY:I
+Ljava/util/HashMap;->DEFAULT_LOAD_FACTOR:F
+Ljava/util/HashMap;->entrySet:Ljava/util/Set;
+Ljava/util/HashMap;->getNode(ILjava/lang/Object;)Ljava/util/HashMap$Node;
+Ljava/util/HashMap;->hash(Ljava/lang/Object;)I
+Ljava/util/HashMap;->internalWriteEntries(Ljava/io/ObjectOutputStream;)V
+Ljava/util/HashMap;->loadFactor()F
+Ljava/util/HashMap;->loadFactor:F
+Ljava/util/HashMap;->MAXIMUM_CAPACITY:I
+Ljava/util/HashMap;->MIN_TREEIFY_CAPACITY:I
+Ljava/util/HashMap;->newNode(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node;
+Ljava/util/HashMap;->newTreeNode(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap;->putMapEntries(Ljava/util/Map;Z)V
+Ljava/util/HashMap;->putVal(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object;
+Ljava/util/HashMap;->reinitialize()V
+Ljava/util/HashMap;->removeNode(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/util/HashMap$Node;
+Ljava/util/HashMap;->replacementNode(Ljava/util/HashMap$Node;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node;
+Ljava/util/HashMap;->replacementTreeNode(Ljava/util/HashMap$Node;Ljava/util/HashMap$Node;)Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap;->resize()[Ljava/util/HashMap$Node;
+Ljava/util/HashMap;->size:I
+Ljava/util/HashMap;->tableSizeFor(I)I
+Ljava/util/HashMap;->threshold:I
+Ljava/util/HashMap;->treeifyBin([Ljava/util/HashMap$Node;I)V
+Ljava/util/HashMap;->TREEIFY_THRESHOLD:I
+Ljava/util/HashMap;->UNTREEIFY_THRESHOLD:I
+Ljava/util/HashSet;-><init>(IFZ)V
+Ljava/util/HashSet;->PRESENT:Ljava/lang/Object;
+Ljava/util/Hashtable$EntrySet;->add(Ljava/util/Map$Entry;)Z
+Ljava/util/Hashtable$Enumerator;->entry:Ljava/util/Hashtable$HashtableEntry;
+Ljava/util/Hashtable$Enumerator;->expectedModCount:I
+Ljava/util/Hashtable$Enumerator;->index:I
+Ljava/util/Hashtable$Enumerator;->iterator:Z
+Ljava/util/Hashtable$Enumerator;->lastReturned:Ljava/util/Hashtable$HashtableEntry;
+Ljava/util/Hashtable$Enumerator;->table:[Ljava/util/Hashtable$HashtableEntry;
+Ljava/util/Hashtable$Enumerator;->type:I
+Ljava/util/Hashtable$HashtableEntry;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/Hashtable$HashtableEntry;)V
+Ljava/util/Hashtable$HashtableEntry;->hash:I
+Ljava/util/Hashtable$HashtableEntry;->key:Ljava/lang/Object;
+Ljava/util/Hashtable$HashtableEntry;->next:Ljava/util/Hashtable$HashtableEntry;
+Ljava/util/Hashtable$HashtableEntry;->value:Ljava/lang/Object;
+Ljava/util/Hashtable;->addEntry(ILjava/lang/Object;Ljava/lang/Object;I)V
+Ljava/util/Hashtable;->count:I
+Ljava/util/Hashtable;->ENTRIES:I
+Ljava/util/Hashtable;->entrySet:Ljava/util/Set;
+Ljava/util/Hashtable;->getEnumeration(I)Ljava/util/Enumeration;
+Ljava/util/Hashtable;->getIterator(I)Ljava/util/Iterator;
+Ljava/util/Hashtable;->KEYS:I
+Ljava/util/Hashtable;->keySet:Ljava/util/Set;
+Ljava/util/Hashtable;->loadFactor:F
+Ljava/util/Hashtable;->MAX_ARRAY_SIZE:I
+Ljava/util/Hashtable;->modCount:I
+Ljava/util/Hashtable;->reconstitutionPut([Ljava/util/Hashtable$HashtableEntry;Ljava/lang/Object;Ljava/lang/Object;)V
+Ljava/util/Hashtable;->table:[Ljava/util/Hashtable$HashtableEntry;
+Ljava/util/Hashtable;->threshold:I
+Ljava/util/Hashtable;->VALUES:I
+Ljava/util/Hashtable;->values:Ljava/util/Collection;
+Ljava/util/IdentityHashMap$EntryIterator$Entry;->checkIndexForEntryUse()V
+Ljava/util/IdentityHashMap$EntryIterator$Entry;->index:I
+Ljava/util/IdentityHashMap$EntryIterator;->lastReturnedEntry:Ljava/util/IdentityHashMap$EntryIterator$Entry;
+Ljava/util/IdentityHashMap$EntrySpliterator;-><init>(Ljava/util/IdentityHashMap;IIII)V
+Ljava/util/IdentityHashMap$EntrySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/IdentityHashMap$EntrySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/IdentityHashMap$IdentityHashMapIterator;->expectedModCount:I
+Ljava/util/IdentityHashMap$IdentityHashMapIterator;->index:I
+Ljava/util/IdentityHashMap$IdentityHashMapIterator;->indexValid:Z
+Ljava/util/IdentityHashMap$IdentityHashMapIterator;->lastReturnedIndex:I
+Ljava/util/IdentityHashMap$IdentityHashMapIterator;->nextIndex()I
+Ljava/util/IdentityHashMap$IdentityHashMapIterator;->traversalTable:[Ljava/lang/Object;
+Ljava/util/IdentityHashMap$IdentityHashMapSpliterator;-><init>(Ljava/util/IdentityHashMap;IIII)V
+Ljava/util/IdentityHashMap$IdentityHashMapSpliterator;->est:I
+Ljava/util/IdentityHashMap$IdentityHashMapSpliterator;->estimateSize()J
+Ljava/util/IdentityHashMap$IdentityHashMapSpliterator;->expectedModCount:I
+Ljava/util/IdentityHashMap$IdentityHashMapSpliterator;->fence:I
+Ljava/util/IdentityHashMap$IdentityHashMapSpliterator;->getFence()I
+Ljava/util/IdentityHashMap$IdentityHashMapSpliterator;->index:I
+Ljava/util/IdentityHashMap$IdentityHashMapSpliterator;->map:Ljava/util/IdentityHashMap;
+Ljava/util/IdentityHashMap$KeySpliterator;-><init>(Ljava/util/IdentityHashMap;IIII)V
+Ljava/util/IdentityHashMap$KeySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/IdentityHashMap$KeySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/IdentityHashMap$ValueSpliterator;-><init>(Ljava/util/IdentityHashMap;IIII)V
+Ljava/util/IdentityHashMap$ValueSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/IdentityHashMap$ValueSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/IdentityHashMap;->capacity(I)I
+Ljava/util/IdentityHashMap;->closeDeletion(I)V
+Ljava/util/IdentityHashMap;->containsMapping(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/IdentityHashMap;->DEFAULT_CAPACITY:I
+Ljava/util/IdentityHashMap;->entrySet:Ljava/util/Set;
+Ljava/util/IdentityHashMap;->hash(Ljava/lang/Object;I)I
+Ljava/util/IdentityHashMap;->init(I)V
+Ljava/util/IdentityHashMap;->maskNull(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/IdentityHashMap;->MAXIMUM_CAPACITY:I
+Ljava/util/IdentityHashMap;->MINIMUM_CAPACITY:I
+Ljava/util/IdentityHashMap;->modCount:I
+Ljava/util/IdentityHashMap;->nextKeyIndex(II)I
+Ljava/util/IdentityHashMap;->NULL_KEY:Ljava/lang/Object;
+Ljava/util/IdentityHashMap;->putForCreate(Ljava/lang/Object;Ljava/lang/Object;)V
+Ljava/util/IdentityHashMap;->removeMapping(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/IdentityHashMap;->resize(I)Z
+Ljava/util/IdentityHashMap;->size:I
+Ljava/util/IdentityHashMap;->table:[Ljava/lang/Object;
+Ljava/util/IdentityHashMap;->unmaskNull(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/IllegalFormatCodePointException;->c:I
+Ljava/util/IllegalFormatConversionException;->arg:Ljava/lang/Class;
+Ljava/util/IllegalFormatConversionException;->c:C
+Ljava/util/IllegalFormatException;-><init>()V
+Ljava/util/IllegalFormatFlagsException;->flags:Ljava/lang/String;
+Ljava/util/IllegalFormatPrecisionException;->p:I
+Ljava/util/IllegalFormatWidthException;->w:I
+Ljava/util/IllformedLocaleException;->_errIdx:I
+Ljava/util/IntSummaryStatistics;->count:J
+Ljava/util/IntSummaryStatistics;->max:I
+Ljava/util/IntSummaryStatistics;->min:I
+Ljava/util/IntSummaryStatistics;->sum:J
+Ljava/util/jar/Attributes$Name;->hashCode:I
+Ljava/util/jar/Attributes$Name;->isAlpha(C)Z
+Ljava/util/jar/Attributes$Name;->isDigit(C)Z
+Ljava/util/jar/Attributes$Name;->isValid(C)Z
+Ljava/util/jar/Attributes$Name;->isValid(Ljava/lang/String;)Z
+Ljava/util/jar/Attributes$Name;->name:Ljava/lang/String;
+Ljava/util/jar/Attributes$Name;->NAME:Ljava/util/jar/Attributes$Name;
+Ljava/util/jar/Attributes;->read(Ljava/util/jar/Manifest$FastInputStream;[B)V
+Ljava/util/jar/Attributes;->write(Ljava/io/DataOutputStream;)V
+Ljava/util/jar/Attributes;->writeMain(Ljava/io/DataOutputStream;)V
+Ljava/util/jar/JarEntry;->attr:Ljava/util/jar/Attributes;
+Ljava/util/jar/JarEntry;->certs:[Ljava/security/cert/Certificate;
+Ljava/util/jar/JarEntry;->signers:[Ljava/security/CodeSigner;
+Ljava/util/jar/JarFile$JarEntryIterator;->e:Ljava/util/Enumeration;
+Ljava/util/jar/JarFile;->checkForSpecialAttributes()V
+Ljava/util/jar/JarFile;->CLASSPATH_CHARS:[C
+Ljava/util/jar/JarFile;->CLASSPATH_LASTOCC:[I
+Ljava/util/jar/JarFile;->CLASSPATH_OPTOSFT:[I
+Ljava/util/jar/JarFile;->getBytes(Ljava/util/zip/ZipEntry;)[B
+Ljava/util/jar/JarFile;->getManEntry()Ljava/util/jar/JarEntry;
+Ljava/util/jar/JarFile;->getManifestFromReference()Ljava/util/jar/Manifest;
+Ljava/util/jar/JarFile;->getMetaInfEntryNames()[Ljava/lang/String;
+Ljava/util/jar/JarFile;->hasCheckedSpecialAttributes:Z
+Ljava/util/jar/JarFile;->hasClassPathAttribute()Z
+Ljava/util/jar/JarFile;->hasClassPathAttribute:Z
+Ljava/util/jar/JarFile;->initializeVerifier()V
+Ljava/util/jar/JarFile;->jv:Ljava/util/jar/JarVerifier;
+Ljava/util/jar/JarFile;->jvInitialized:Z
+Ljava/util/jar/JarFile;->manEntry:Ljava/util/jar/JarEntry;
+Ljava/util/jar/JarFile;->match([C[B[I[I)Z
+Ljava/util/jar/JarFile;->maybeInstantiateVerifier()V
+Ljava/util/jar/JarFile;->META_DIR:Ljava/lang/String;
+Ljava/util/jar/JarFile;->newEntry(Ljava/util/zip/ZipEntry;)Ljava/util/jar/JarEntry;
+Ljava/util/jar/JarFile;->verify:Z
+Ljava/util/jar/JarInputStream;->checkManifest(Ljava/util/jar/JarEntry;)Ljava/util/jar/JarEntry;
+Ljava/util/jar/JarInputStream;->doVerify:Z
+Ljava/util/jar/JarInputStream;->first:Ljava/util/jar/JarEntry;
+Ljava/util/jar/JarInputStream;->getBytes(Ljava/io/InputStream;)[B
+Ljava/util/jar/JarInputStream;->jv:Ljava/util/jar/JarVerifier;
+Ljava/util/jar/JarInputStream;->man:Ljava/util/jar/Manifest;
+Ljava/util/jar/JarInputStream;->mev:Lsun/security/util/ManifestEntryVerifier;
+Ljava/util/jar/JarInputStream;->tryManifest:Z
+Ljava/util/jar/JarOutputStream;->firstEntry:Z
+Ljava/util/jar/JarOutputStream;->get16([BI)I
+Ljava/util/jar/JarOutputStream;->hasMagic([B)Z
+Ljava/util/jar/JarOutputStream;->JAR_MAGIC:I
+Ljava/util/jar/JarOutputStream;->set16([BII)V
+Ljava/util/jar/JarVerifier$VerifierCodeSource;-><init>(Ljava/lang/Object;Ljava/net/URL;[Ljava/security/cert/Certificate;)V
+Ljava/util/jar/JarVerifier$VerifierCodeSource;-><init>(Ljava/lang/Object;Ljava/net/URL;[Ljava/security/CodeSigner;)V
+Ljava/util/jar/JarVerifier$VerifierCodeSource;->csdomain:Ljava/lang/Object;
+Ljava/util/jar/JarVerifier$VerifierCodeSource;->getPrivateCertificates()[Ljava/security/cert/Certificate;
+Ljava/util/jar/JarVerifier$VerifierCodeSource;->getPrivateSigners()[Ljava/security/CodeSigner;
+Ljava/util/jar/JarVerifier$VerifierCodeSource;->isSameDomain(Ljava/lang/Object;)Z
+Ljava/util/jar/JarVerifier$VerifierCodeSource;->vcerts:[Ljava/security/cert/Certificate;
+Ljava/util/jar/JarVerifier$VerifierCodeSource;->vlocation:Ljava/net/URL;
+Ljava/util/jar/JarVerifier$VerifierCodeSource;->vsigners:[Ljava/security/CodeSigner;
+Ljava/util/jar/JarVerifier$VerifierStream;-><init>(Ljava/util/jar/Manifest;Ljava/util/jar/JarEntry;Ljava/io/InputStream;Ljava/util/jar/JarVerifier;)V
+Ljava/util/jar/JarVerifier$VerifierStream;->is:Ljava/io/InputStream;
+Ljava/util/jar/JarVerifier$VerifierStream;->jv:Ljava/util/jar/JarVerifier;
+Ljava/util/jar/JarVerifier$VerifierStream;->mev:Lsun/security/util/ManifestEntryVerifier;
+Ljava/util/jar/JarVerifier$VerifierStream;->numLeft:J
+Ljava/util/jar/JarVerifier;-><init>([B)V
+Ljava/util/jar/JarVerifier;->anyToVerify:Z
+Ljava/util/jar/JarVerifier;->baos:Ljava/io/ByteArrayOutputStream;
+Ljava/util/jar/JarVerifier;->beginEntry(Ljava/util/jar/JarEntry;Lsun/security/util/ManifestEntryVerifier;)V
+Ljava/util/jar/JarVerifier;->csdomain:Ljava/lang/Object;
+Ljava/util/jar/JarVerifier;->debug:Lsun/security/util/Debug;
+Ljava/util/jar/JarVerifier;->doneWithMeta()V
+Ljava/util/jar/JarVerifier;->eagerValidation:Z
+Ljava/util/jar/JarVerifier;->emptyEnumeration:Ljava/util/Enumeration;
+Ljava/util/jar/JarVerifier;->emptySigner:[Ljava/security/CodeSigner;
+Ljava/util/jar/JarVerifier;->entries2(Ljava/util/jar/JarFile;Ljava/util/Enumeration;)Ljava/util/Enumeration;
+Ljava/util/jar/JarVerifier;->entryNames(Ljava/util/jar/JarFile;[Ljava/security/CodeSource;)Ljava/util/Enumeration;
+Ljava/util/jar/JarVerifier;->findMatchingSigners(Ljava/security/CodeSource;)[Ljava/security/CodeSigner;
+Ljava/util/jar/JarVerifier;->getCerts(Ljava/lang/String;)[Ljava/security/cert/Certificate;
+Ljava/util/jar/JarVerifier;->getCerts(Ljava/util/jar/JarFile;Ljava/util/jar/JarEntry;)[Ljava/security/cert/Certificate;
+Ljava/util/jar/JarVerifier;->getCodeSigners(Ljava/lang/String;)[Ljava/security/CodeSigner;
+Ljava/util/jar/JarVerifier;->getCodeSigners(Ljava/util/jar/JarFile;Ljava/util/jar/JarEntry;)[Ljava/security/CodeSigner;
+Ljava/util/jar/JarVerifier;->getCodeSource(Ljava/net/URL;Ljava/lang/String;)Ljava/security/CodeSource;
+Ljava/util/jar/JarVerifier;->getCodeSource(Ljava/net/URL;Ljava/util/jar/JarFile;Ljava/util/jar/JarEntry;)Ljava/security/CodeSource;
+Ljava/util/jar/JarVerifier;->getCodeSources(Ljava/util/jar/JarFile;Ljava/net/URL;)[Ljava/security/CodeSource;
+Ljava/util/jar/JarVerifier;->getJarCodeSigners()Ljava/util/List;
+Ljava/util/jar/JarVerifier;->getManifestDigests()Ljava/util/List;
+Ljava/util/jar/JarVerifier;->getUnsignedCS(Ljava/net/URL;)Ljava/security/CodeSource;
+Ljava/util/jar/JarVerifier;->isSigningRelated(Ljava/lang/String;)Z
+Ljava/util/jar/JarVerifier;->jarCodeSigners:Ljava/util/List;
+Ljava/util/jar/JarVerifier;->lastURL:Ljava/net/URL;
+Ljava/util/jar/JarVerifier;->lastURLMap:Ljava/util/Map;
+Ljava/util/jar/JarVerifier;->manDig:Lsun/security/util/ManifestDigester;
+Ljava/util/jar/JarVerifier;->manifestDigests:Ljava/util/List;
+Ljava/util/jar/JarVerifier;->manifestRawBytes:[B
+Ljava/util/jar/JarVerifier;->mapSignersToCertArray([Ljava/security/CodeSigner;)[Ljava/security/cert/Certificate;
+Ljava/util/jar/JarVerifier;->mapSignersToCodeSource(Ljava/net/URL;[Ljava/security/CodeSigner;)Ljava/security/CodeSource;
+Ljava/util/jar/JarVerifier;->mapSignersToCodeSources(Ljava/net/URL;Ljava/util/List;Z)[Ljava/security/CodeSource;
+Ljava/util/jar/JarVerifier;->nothingToVerify()Z
+Ljava/util/jar/JarVerifier;->parsingBlockOrSF:Z
+Ljava/util/jar/JarVerifier;->parsingMeta:Z
+Ljava/util/jar/JarVerifier;->pendingBlocks:Ljava/util/ArrayList;
+Ljava/util/jar/JarVerifier;->processEntry(Lsun/security/util/ManifestEntryVerifier;)V
+Ljava/util/jar/JarVerifier;->setEagerValidation(Z)V
+Ljava/util/jar/JarVerifier;->sigFileData:Ljava/util/Hashtable;
+Ljava/util/jar/JarVerifier;->sigFileSigners:Ljava/util/Hashtable;
+Ljava/util/jar/JarVerifier;->signerCache:Ljava/util/ArrayList;
+Ljava/util/jar/JarVerifier;->signerMap()Ljava/util/Map;
+Ljava/util/jar/JarVerifier;->signerMap:Ljava/util/Map;
+Ljava/util/jar/JarVerifier;->signerToCodeSource:Ljava/util/Map;
+Ljava/util/jar/JarVerifier;->unsignedEntryNames(Ljava/util/jar/JarFile;)Ljava/util/Enumeration;
+Ljava/util/jar/JarVerifier;->update(ILsun/security/util/ManifestEntryVerifier;)V
+Ljava/util/jar/JarVerifier;->update(I[BIILsun/security/util/ManifestEntryVerifier;)V
+Ljava/util/jar/JarVerifier;->urlToCodeSourceMap:Ljava/util/Map;
+Ljava/util/jar/JarVerifier;->verifiedSigners:Ljava/util/Hashtable;
+Ljava/util/jar/Manifest$FastInputStream;-><init>(Ljava/io/InputStream;)V
+Ljava/util/jar/Manifest$FastInputStream;-><init>(Ljava/io/InputStream;I)V
+Ljava/util/jar/Manifest$FastInputStream;->buf:[B
+Ljava/util/jar/Manifest$FastInputStream;->count:I
+Ljava/util/jar/Manifest$FastInputStream;->fill()V
+Ljava/util/jar/Manifest$FastInputStream;->peek()B
+Ljava/util/jar/Manifest$FastInputStream;->pos:I
+Ljava/util/jar/Manifest$FastInputStream;->readLine([B)I
+Ljava/util/jar/Manifest$FastInputStream;->readLine([BII)I
+Ljava/util/jar/Manifest;->attr:Ljava/util/jar/Attributes;
+Ljava/util/jar/Manifest;->entries:Ljava/util/Map;
+Ljava/util/jar/Manifest;->make72Safe(Ljava/lang/StringBuffer;)V
+Ljava/util/jar/Manifest;->parseName([BI)Ljava/lang/String;
+Ljava/util/jar/Manifest;->toLower(I)I
+Ljava/util/jar/Pack200;-><init>()V
+Ljava/util/jar/Pack200;->newInstance(Ljava/lang/String;)Ljava/lang/Object;
+Ljava/util/jar/Pack200;->packerImpl:Ljava/lang/Class;
+Ljava/util/jar/Pack200;->PACK_PROVIDER:Ljava/lang/String;
+Ljava/util/jar/Pack200;->unpackerImpl:Ljava/lang/Class;
+Ljava/util/jar/Pack200;->UNPACK_PROVIDER:Ljava/lang/String;
+Ljava/util/LinkedHashMap$LinkedEntrySet;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/LinkedHashMap$LinkedHashIterator;->current:Ljava/util/LinkedHashMap$LinkedHashMapEntry;
+Ljava/util/LinkedHashMap$LinkedHashIterator;->expectedModCount:I
+Ljava/util/LinkedHashMap$LinkedHashIterator;->next:Ljava/util/LinkedHashMap$LinkedHashMapEntry;
+Ljava/util/LinkedHashMap$LinkedHashIterator;->nextNode()Ljava/util/LinkedHashMap$LinkedHashMapEntry;
+Ljava/util/LinkedHashMap$LinkedHashIterator;->remove()V
+Ljava/util/LinkedHashMap$LinkedHashMapEntry;-><init>(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)V
+Ljava/util/LinkedHashMap$LinkedHashMapEntry;->after:Ljava/util/LinkedHashMap$LinkedHashMapEntry;
+Ljava/util/LinkedHashMap$LinkedHashMapEntry;->before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;
+Ljava/util/LinkedHashMap$LinkedKeySet;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/LinkedHashMap$LinkedValues;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/LinkedHashMap;->afterNodeAccess(Ljava/util/HashMap$Node;)V
+Ljava/util/LinkedHashMap;->afterNodeInsertion(Z)V
+Ljava/util/LinkedHashMap;->afterNodeRemoval(Ljava/util/HashMap$Node;)V
+Ljava/util/LinkedHashMap;->head:Ljava/util/LinkedHashMap$LinkedHashMapEntry;
+Ljava/util/LinkedHashMap;->internalWriteEntries(Ljava/io/ObjectOutputStream;)V
+Ljava/util/LinkedHashMap;->linkNodeLast(Ljava/util/LinkedHashMap$LinkedHashMapEntry;)V
+Ljava/util/LinkedHashMap;->newNode(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node;
+Ljava/util/LinkedHashMap;->newTreeNode(ILjava/lang/Object;Ljava/lang/Object;Ljava/util/HashMap$Node;)Ljava/util/HashMap$TreeNode;
+Ljava/util/LinkedHashMap;->reinitialize()V
+Ljava/util/LinkedHashMap;->replacementNode(Ljava/util/HashMap$Node;Ljava/util/HashMap$Node;)Ljava/util/HashMap$Node;
+Ljava/util/LinkedHashMap;->replacementTreeNode(Ljava/util/HashMap$Node;Ljava/util/HashMap$Node;)Ljava/util/HashMap$TreeNode;
+Ljava/util/LinkedHashMap;->tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;
+Ljava/util/LinkedHashMap;->transferLinks(Ljava/util/LinkedHashMap$LinkedHashMapEntry;Ljava/util/LinkedHashMap$LinkedHashMapEntry;)V
+Ljava/util/LinkedList$DescendingIterator;->itr:Ljava/util/LinkedList$ListItr;
+Ljava/util/LinkedList$ListItr;->checkForComodification()V
+Ljava/util/LinkedList$ListItr;->expectedModCount:I
+Ljava/util/LinkedList$ListItr;->lastReturned:Ljava/util/LinkedList$Node;
+Ljava/util/LinkedList$ListItr;->next:Ljava/util/LinkedList$Node;
+Ljava/util/LinkedList$ListItr;->nextIndex:I
+Ljava/util/LinkedList$LLSpliterator;-><init>(Ljava/util/LinkedList;II)V
+Ljava/util/LinkedList$LLSpliterator;->batch:I
+Ljava/util/LinkedList$LLSpliterator;->BATCH_UNIT:I
+Ljava/util/LinkedList$LLSpliterator;->current:Ljava/util/LinkedList$Node;
+Ljava/util/LinkedList$LLSpliterator;->est:I
+Ljava/util/LinkedList$LLSpliterator;->expectedModCount:I
+Ljava/util/LinkedList$LLSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/LinkedList$LLSpliterator;->getEst()I
+Ljava/util/LinkedList$LLSpliterator;->list:Ljava/util/LinkedList;
+Ljava/util/LinkedList$LLSpliterator;->MAX_BATCH:I
+Ljava/util/LinkedList$LLSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/LinkedList$Node;-><init>(Ljava/util/LinkedList$Node;Ljava/lang/Object;Ljava/util/LinkedList$Node;)V
+Ljava/util/LinkedList$Node;->prev:Ljava/util/LinkedList$Node;
+Ljava/util/LinkedList;->checkElementIndex(I)V
+Ljava/util/LinkedList;->checkPositionIndex(I)V
+Ljava/util/LinkedList;->isElementIndex(I)Z
+Ljava/util/LinkedList;->isPositionIndex(I)Z
+Ljava/util/LinkedList;->last:Ljava/util/LinkedList$Node;
+Ljava/util/LinkedList;->linkBefore(Ljava/lang/Object;Ljava/util/LinkedList$Node;)V
+Ljava/util/LinkedList;->linkFirst(Ljava/lang/Object;)V
+Ljava/util/LinkedList;->linkLast(Ljava/lang/Object;)V
+Ljava/util/LinkedList;->node(I)Ljava/util/LinkedList$Node;
+Ljava/util/LinkedList;->outOfBoundsMsg(I)Ljava/lang/String;
+Ljava/util/LinkedList;->superClone()Ljava/util/LinkedList;
+Ljava/util/LinkedList;->unlink(Ljava/util/LinkedList$Node;)Ljava/lang/Object;
+Ljava/util/LinkedList;->unlinkFirst(Ljava/util/LinkedList$Node;)Ljava/lang/Object;
+Ljava/util/LinkedList;->unlinkLast(Ljava/util/LinkedList$Node;)Ljava/lang/Object;
+Ljava/util/ListResourceBundle;->loadLookup()V
+Ljava/util/ListResourceBundle;->lookup:Ljava/util/Map;
+Ljava/util/Locale$Builder;->localeBuilder:Lsun/util/locale/InternalLocaleBuilder;
+Ljava/util/Locale$Cache;-><init>()V
+Ljava/util/Locale$Cache;->createObject(Ljava/util/Locale$LocaleKey;)Ljava/util/Locale;
+Ljava/util/Locale$Category;->countryKey:Ljava/lang/String;
+Ljava/util/Locale$Category;->languageKey:Ljava/lang/String;
+Ljava/util/Locale$Category;->scriptKey:Ljava/lang/String;
+Ljava/util/Locale$Category;->variantKey:Ljava/lang/String;
+Ljava/util/Locale$LanguageRange;->hash:I
+Ljava/util/Locale$LanguageRange;->isSubtagIllFormed(Ljava/lang/String;Z)Z
+Ljava/util/Locale$LanguageRange;->range:Ljava/lang/String;
+Ljava/util/Locale$LanguageRange;->weight:D
+Ljava/util/Locale$LocaleKey;-><init>(Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;)V
+Ljava/util/Locale$LocaleKey;->base:Lsun/util/locale/BaseLocale;
+Ljava/util/Locale$LocaleKey;->exts:Lsun/util/locale/LocaleExtensions;
+Ljava/util/Locale$LocaleKey;->hash:I
+Ljava/util/Locale$NoImagePreloadHolder;-><init>()V
+Ljava/util/Locale$NoImagePreloadHolder;->defaultLocale:Ljava/util/Locale;
+Ljava/util/Locale;-><init>(Lsun/util/locale/BaseLocale;Lsun/util/locale/LocaleExtensions;)V
+Ljava/util/Locale;->adjustLanguageCode(Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/Locale;->baseLocale:Lsun/util/locale/BaseLocale;
+Ljava/util/Locale;->composeList(Ljava/text/MessageFormat;[Ljava/lang/String;)[Ljava/lang/String;
+Ljava/util/Locale;->convertOldISOCodes(Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/Locale;->defaultDisplayLocale:Ljava/util/Locale;
+Ljava/util/Locale;->defaultFormatLocale:Ljava/util/Locale;
+Ljava/util/Locale;->DISPLAY_COUNTRY:I
+Ljava/util/Locale;->DISPLAY_LANGUAGE:I
+Ljava/util/Locale;->DISPLAY_SCRIPT:I
+Ljava/util/Locale;->DISPLAY_VARIANT:I
+Ljava/util/Locale;->formatList([Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/Locale;->getBaseLocale()Lsun/util/locale/BaseLocale;
+Ljava/util/Locale;->getCompatibilityExtensions(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lsun/util/locale/LocaleExtensions;
+Ljava/util/Locale;->getInstance(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/util/Locale;
+Ljava/util/Locale;->getInstance(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lsun/util/locale/LocaleExtensions;)Ljava/util/Locale;
+Ljava/util/Locale;->getLocaleExtensions()Lsun/util/locale/LocaleExtensions;
+Ljava/util/Locale;->hashCodeValue:I
+Ljava/util/Locale;->initDefault()Ljava/util/Locale;
+Ljava/util/Locale;->initDefault(Ljava/util/Locale$Category;)Ljava/util/Locale;
+Ljava/util/Locale;->isAsciiAlphaNum(Ljava/lang/String;)Z
+Ljava/util/Locale;->isoCountries:[Ljava/lang/String;
+Ljava/util/Locale;->isoLanguages:[Ljava/lang/String;
+Ljava/util/Locale;->isUnicodeExtensionKey(Ljava/lang/String;)Z
+Ljava/util/Locale;->isUnM49AreaCode(Ljava/lang/String;)Z
+Ljava/util/Locale;->isValidBcp47Alpha(Ljava/lang/String;II)Z
+Ljava/util/Locale;->isValidVariantSubtag(Ljava/lang/String;)Z
+Ljava/util/Locale;->languageTag:Ljava/lang/String;
+Ljava/util/Locale;->LOCALECACHE:Ljava/util/Locale$Cache;
+Ljava/util/Locale;->localeExtensions:Lsun/util/locale/LocaleExtensions;
+Ljava/util/Locale;->normalizeAndValidateLanguage(Ljava/lang/String;Z)Ljava/lang/String;
+Ljava/util/Locale;->normalizeAndValidateRegion(Ljava/lang/String;Z)Ljava/lang/String;
+Ljava/util/Locale;->normalizeAndValidateVariant(Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/Locale;->UNDETERMINED_LANGUAGE:Ljava/lang/String;
+Ljava/util/logging/ConsoleHandler;->configure()V
+Ljava/util/logging/ErrorManager;->reported:Z
+Ljava/util/logging/FileHandler$InitializationErrorManager;-><init>()V
+Ljava/util/logging/FileHandler$InitializationErrorManager;->lastException:Ljava/lang/Exception;
+Ljava/util/logging/FileHandler$MeteredStream;->out:Ljava/io/OutputStream;
+Ljava/util/logging/FileHandler$MeteredStream;->written:I
+Ljava/util/logging/FileHandler;->append:Z
+Ljava/util/logging/FileHandler;->configure()V
+Ljava/util/logging/FileHandler;->count:I
+Ljava/util/logging/FileHandler;->files:[Ljava/io/File;
+Ljava/util/logging/FileHandler;->generate(Ljava/lang/String;II)Ljava/io/File;
+Ljava/util/logging/FileHandler;->isParentWritable(Ljava/nio/file/Path;)Z
+Ljava/util/logging/FileHandler;->limit:I
+Ljava/util/logging/FileHandler;->lockFileChannel:Ljava/nio/channels/FileChannel;
+Ljava/util/logging/FileHandler;->lockFileName:Ljava/lang/String;
+Ljava/util/logging/FileHandler;->locks:Ljava/util/Set;
+Ljava/util/logging/FileHandler;->MAX_LOCKS:I
+Ljava/util/logging/FileHandler;->meter:Ljava/util/logging/FileHandler$MeteredStream;
+Ljava/util/logging/FileHandler;->open(Ljava/io/File;Z)V
+Ljava/util/logging/FileHandler;->openFiles()V
+Ljava/util/logging/FileHandler;->pattern:Ljava/lang/String;
+Ljava/util/logging/FileHandler;->rotate()V
+Ljava/util/logging/Handler;->checkPermission()V
+Ljava/util/logging/Handler;->encoding:Ljava/lang/String;
+Ljava/util/logging/Handler;->errorManager:Ljava/util/logging/ErrorManager;
+Ljava/util/logging/Handler;->filter:Ljava/util/logging/Filter;
+Ljava/util/logging/Handler;->formatter:Ljava/util/logging/Formatter;
+Ljava/util/logging/Handler;->logLevel:Ljava/util/logging/Level;
+Ljava/util/logging/Handler;->manager:Ljava/util/logging/LogManager;
+Ljava/util/logging/Handler;->offValue:I
+Ljava/util/logging/Level$KnownLevel;-><init>(Ljava/util/logging/Level;)V
+Ljava/util/logging/Level$KnownLevel;->add(Ljava/util/logging/Level;)V
+Ljava/util/logging/Level$KnownLevel;->findByLocalizedLevelName(Ljava/lang/String;)Ljava/util/logging/Level$KnownLevel;
+Ljava/util/logging/Level$KnownLevel;->findByName(Ljava/lang/String;)Ljava/util/logging/Level$KnownLevel;
+Ljava/util/logging/Level$KnownLevel;->findByValue(I)Ljava/util/logging/Level$KnownLevel;
+Ljava/util/logging/Level$KnownLevel;->intToLevels:Ljava/util/Map;
+Ljava/util/logging/Level$KnownLevel;->levelObject:Ljava/util/logging/Level;
+Ljava/util/logging/Level$KnownLevel;->matches(Ljava/util/logging/Level;)Ljava/util/logging/Level$KnownLevel;
+Ljava/util/logging/Level$KnownLevel;->mirroredLevel:Ljava/util/logging/Level;
+Ljava/util/logging/Level$KnownLevel;->nameToLevels:Ljava/util/Map;
+Ljava/util/logging/Level;-><init>(Ljava/lang/String;ILjava/lang/String;Z)V
+Ljava/util/logging/Level;->cachedLocale:Ljava/util/Locale;
+Ljava/util/logging/Level;->computeLocalizedLevelName(Ljava/util/Locale;)Ljava/lang/String;
+Ljava/util/logging/Level;->defaultBundle:Ljava/lang/String;
+Ljava/util/logging/Level;->findLevel(Ljava/lang/String;)Ljava/util/logging/Level;
+Ljava/util/logging/Level;->getCachedLocalizedLevelName()Ljava/lang/String;
+Ljava/util/logging/Level;->getLevelName()Ljava/lang/String;
+Ljava/util/logging/Level;->getLocalizedLevelName()Ljava/lang/String;
+Ljava/util/logging/Level;->localizedLevelName:Ljava/lang/String;
+Ljava/util/logging/Level;->name:Ljava/lang/String;
+Ljava/util/logging/Level;->resourceBundleName:Ljava/lang/String;
+Ljava/util/logging/Level;->value:I
+Ljava/util/logging/Logger$LoggerBundle;-><init>(Ljava/lang/String;Ljava/util/ResourceBundle;)V
+Ljava/util/logging/Logger$LoggerBundle;->get(Ljava/lang/String;Ljava/util/ResourceBundle;)Ljava/util/logging/Logger$LoggerBundle;
+Ljava/util/logging/Logger$LoggerBundle;->isSystemBundle()Z
+Ljava/util/logging/Logger$LoggerBundle;->resourceBundleName:Ljava/lang/String;
+Ljava/util/logging/Logger$LoggerBundle;->userBundle:Ljava/util/ResourceBundle;
+Ljava/util/logging/Logger$SystemLoggerHelper;-><init>()V
+Ljava/util/logging/Logger$SystemLoggerHelper;->disableCallerCheck:Z
+Ljava/util/logging/Logger$SystemLoggerHelper;->getBooleanProperty(Ljava/lang/String;)Z
+Ljava/util/logging/Logger;-><init>(Ljava/lang/String;)V
+Ljava/util/logging/Logger;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/util/logging/LogManager;Z)V
+Ljava/util/logging/Logger;->accessCheckedHandlers()[Ljava/util/logging/Handler;
+Ljava/util/logging/Logger;->anonymous:Z
+Ljava/util/logging/Logger;->callersClassLoaderRef:Ljava/lang/ref/WeakReference;
+Ljava/util/logging/Logger;->catalog:Ljava/util/ResourceBundle;
+Ljava/util/logging/Logger;->catalogLocale:Ljava/util/Locale;
+Ljava/util/logging/Logger;->catalogName:Ljava/lang/String;
+Ljava/util/logging/Logger;->checkPermission()V
+Ljava/util/logging/Logger;->demandLogger(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)Ljava/util/logging/Logger;
+Ljava/util/logging/Logger;->doLog(Ljava/util/logging/LogRecord;)V
+Ljava/util/logging/Logger;->doLog(Ljava/util/logging/LogRecord;Ljava/lang/String;)V
+Ljava/util/logging/Logger;->doLog(Ljava/util/logging/LogRecord;Ljava/util/ResourceBundle;)V
+Ljava/util/logging/Logger;->doSetParent(Ljava/util/logging/Logger;)V
+Ljava/util/logging/Logger;->emptyHandlers:[Ljava/util/logging/Handler;
+Ljava/util/logging/Logger;->filter:Ljava/util/logging/Filter;
+Ljava/util/logging/Logger;->findResourceBundle(Ljava/lang/String;Z)Ljava/util/ResourceBundle;
+Ljava/util/logging/Logger;->findSystemResourceBundle(Ljava/util/Locale;)Ljava/util/ResourceBundle;
+Ljava/util/logging/Logger;->getCallersClassLoader()Ljava/lang/ClassLoader;
+Ljava/util/logging/Logger;->getEffectiveLoggerBundle()Ljava/util/logging/Logger$LoggerBundle;
+Ljava/util/logging/Logger;->getPlatformLogger(Ljava/lang/String;)Ljava/util/logging/Logger;
+Ljava/util/logging/Logger;->handlers:Ljava/util/concurrent/CopyOnWriteArrayList;
+Ljava/util/logging/Logger;->isLevelInitialized()Z
+Ljava/util/logging/Logger;->isSystemLogger:Z
+Ljava/util/logging/Logger;->kids:Ljava/util/ArrayList;
+Ljava/util/logging/Logger;->levelObject:Ljava/util/logging/Level;
+Ljava/util/logging/Logger;->levelValue:I
+Ljava/util/logging/Logger;->loggerBundle:Ljava/util/logging/Logger$LoggerBundle;
+Ljava/util/logging/Logger;->manager:Ljava/util/logging/LogManager;
+Ljava/util/logging/Logger;->name:Ljava/lang/String;
+Ljava/util/logging/Logger;->NO_RESOURCE_BUNDLE:Ljava/util/logging/Logger$LoggerBundle;
+Ljava/util/logging/Logger;->offValue:I
+Ljava/util/logging/Logger;->parent:Ljava/util/logging/Logger;
+Ljava/util/logging/Logger;->removeChildLogger(Ljava/util/logging/LogManager$LoggerWeakRef;)V
+Ljava/util/logging/Logger;->setCallersClassLoaderRef(Ljava/lang/Class;)V
+Ljava/util/logging/Logger;->setLogManager(Ljava/util/logging/LogManager;)V
+Ljava/util/logging/Logger;->setupResourceInfo(Ljava/lang/String;Ljava/lang/Class;)V
+Ljava/util/logging/Logger;->SYSTEM_BUNDLE:Ljava/util/logging/Logger$LoggerBundle;
+Ljava/util/logging/Logger;->SYSTEM_LOGGER_RB_NAME:Ljava/lang/String;
+Ljava/util/logging/Logger;->updateEffectiveLevel()V
+Ljava/util/logging/Logger;->useParentHandlers:Z
+Ljava/util/logging/LogManager$Beans;-><init>()V
+Ljava/util/logging/LogManager$Beans;->getClass(Ljava/lang/String;)Ljava/lang/Class;
+Ljava/util/logging/LogManager$Beans;->invokePropertyChange(Ljava/lang/Object;Ljava/lang/Object;)V
+Ljava/util/logging/LogManager$Beans;->isBeansPresent()Z
+Ljava/util/logging/LogManager$Beans;->newPropertyChangeEvent(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/logging/LogManager$Beans;->propertyChangeEventClass:Ljava/lang/Class;
+Ljava/util/logging/LogManager$Beans;->propertyChangeListenerClass:Ljava/lang/Class;
+Ljava/util/logging/LogManager$Beans;->propertyChangeMethod:Ljava/lang/reflect/Method;
+Ljava/util/logging/LogManager$Beans;->propertyEventCtor:Ljava/lang/reflect/Constructor;
+Ljava/util/logging/LogManager$LoggerContext;->addLocalLogger(Ljava/util/logging/Logger;)Z
+Ljava/util/logging/LogManager$LoggerContext;->addLocalLogger(Ljava/util/logging/Logger;Ljava/util/logging/LogManager;)Z
+Ljava/util/logging/LogManager$LoggerContext;->addLocalLogger(Ljava/util/logging/Logger;Z)Z
+Ljava/util/logging/LogManager$LoggerContext;->addLocalLogger(Ljava/util/logging/Logger;ZLjava/util/logging/LogManager;)Z
+Ljava/util/logging/LogManager$LoggerContext;->demandLogger(Ljava/lang/String;Ljava/lang/String;)Ljava/util/logging/Logger;
+Ljava/util/logging/LogManager$LoggerContext;->ensureAllDefaultLoggers(Ljava/util/logging/Logger;)V
+Ljava/util/logging/LogManager$LoggerContext;->ensureDefaultLogger(Ljava/util/logging/Logger;)V
+Ljava/util/logging/LogManager$LoggerContext;->ensureInitialized()V
+Ljava/util/logging/LogManager$LoggerContext;->findLogger(Ljava/lang/String;)Ljava/util/logging/Logger;
+Ljava/util/logging/LogManager$LoggerContext;->getGlobalLogger()Ljava/util/logging/Logger;
+Ljava/util/logging/LogManager$LoggerContext;->getLoggerNames()Ljava/util/Enumeration;
+Ljava/util/logging/LogManager$LoggerContext;->getNode(Ljava/lang/String;)Ljava/util/logging/LogManager$LogNode;
+Ljava/util/logging/LogManager$LoggerContext;->getOwner()Ljava/util/logging/LogManager;
+Ljava/util/logging/LogManager$LoggerContext;->getRootLogger()Ljava/util/logging/Logger;
+Ljava/util/logging/LogManager$LoggerContext;->namedLoggers:Ljava/util/Hashtable;
+Ljava/util/logging/LogManager$LoggerContext;->processParentHandlers(Ljava/util/logging/Logger;Ljava/lang/String;)V
+Ljava/util/logging/LogManager$LoggerContext;->removeLoggerRef(Ljava/lang/String;Ljava/util/logging/LogManager$LoggerWeakRef;)V
+Ljava/util/logging/LogManager$LoggerContext;->requiresDefaultLoggers()Z
+Ljava/util/logging/LogManager$LoggerContext;->root:Ljava/util/logging/LogManager$LogNode;
+Ljava/util/logging/LogManager$LoggerWeakRef;->dispose()V
+Ljava/util/logging/LogManager$LoggerWeakRef;->disposed:Z
+Ljava/util/logging/LogManager$LoggerWeakRef;->name:Ljava/lang/String;
+Ljava/util/logging/LogManager$LoggerWeakRef;->node:Ljava/util/logging/LogManager$LogNode;
+Ljava/util/logging/LogManager$LoggerWeakRef;->parentRef:Ljava/lang/ref/WeakReference;
+Ljava/util/logging/LogManager$LoggerWeakRef;->setNode(Ljava/util/logging/LogManager$LogNode;)V
+Ljava/util/logging/LogManager$LoggerWeakRef;->setParentRef(Ljava/lang/ref/WeakReference;)V
+Ljava/util/logging/LogManager$LogNode;-><init>(Ljava/util/logging/LogManager$LogNode;Ljava/util/logging/LogManager$LoggerContext;)V
+Ljava/util/logging/LogManager$LogNode;->children:Ljava/util/HashMap;
+Ljava/util/logging/LogManager$LogNode;->context:Ljava/util/logging/LogManager$LoggerContext;
+Ljava/util/logging/LogManager$LogNode;->loggerRef:Ljava/util/logging/LogManager$LoggerWeakRef;
+Ljava/util/logging/LogManager$LogNode;->parent:Ljava/util/logging/LogManager$LogNode;
+Ljava/util/logging/LogManager$LogNode;->walkAndSetParent(Ljava/util/logging/Logger;)V
+Ljava/util/logging/LogManager$RootLogger;->accessCheckedHandlers()[Ljava/util/logging/Handler;
+Ljava/util/logging/LogManager$SystemLoggerContext;->demandLogger(Ljava/lang/String;Ljava/lang/String;)Ljava/util/logging/Logger;
+Ljava/util/logging/LogManager;-><init>(Ljava/lang/Void;)V
+Ljava/util/logging/LogManager;->checkPermission()V
+Ljava/util/logging/LogManager;->checkSubclassPermissions()Ljava/lang/Void;
+Ljava/util/logging/LogManager;->contexts()Ljava/util/List;
+Ljava/util/logging/LogManager;->contextsMap:Ljava/util/WeakHashMap;
+Ljava/util/logging/LogManager;->controlPermission:Ljava/security/Permission;
+Ljava/util/logging/LogManager;->deathImminent:Z
+Ljava/util/logging/LogManager;->defaultLevel:Ljava/util/logging/Level;
+Ljava/util/logging/LogManager;->demandLogger(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)Ljava/util/logging/Logger;
+Ljava/util/logging/LogManager;->demandSystemLogger(Ljava/lang/String;Ljava/lang/String;)Ljava/util/logging/Logger;
+Ljava/util/logging/LogManager;->doSetLevel(Ljava/util/logging/Logger;Ljava/util/logging/Level;)V
+Ljava/util/logging/LogManager;->doSetParent(Ljava/util/logging/Logger;Ljava/util/logging/Logger;)V
+Ljava/util/logging/LogManager;->drainLoggerRefQueueBounded()V
+Ljava/util/logging/LogManager;->ensureLogManagerInitialized()V
+Ljava/util/logging/LogManager;->getBooleanProperty(Ljava/lang/String;Z)Z
+Ljava/util/logging/LogManager;->getClassInstance(Ljava/lang/String;)Ljava/lang/Class;
+Ljava/util/logging/LogManager;->getFilterProperty(Ljava/lang/String;Ljava/util/logging/Filter;)Ljava/util/logging/Filter;
+Ljava/util/logging/LogManager;->getIntProperty(Ljava/lang/String;I)I
+Ljava/util/logging/LogManager;->getLevelProperty(Ljava/lang/String;Ljava/util/logging/Level;)Ljava/util/logging/Level;
+Ljava/util/logging/LogManager;->getStringProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/logging/LogManager;->getSystemContext()Ljava/util/logging/LogManager$LoggerContext;
+Ljava/util/logging/LogManager;->getUserContext()Ljava/util/logging/LogManager$LoggerContext;
+Ljava/util/logging/LogManager;->initializationDone:Z
+Ljava/util/logging/LogManager;->initializedCalled:Z
+Ljava/util/logging/LogManager;->initializedGlobalHandlers:Z
+Ljava/util/logging/LogManager;->initializeGlobalHandlers()V
+Ljava/util/logging/LogManager;->listenerMap:Ljava/util/Map;
+Ljava/util/logging/LogManager;->loadLoggerHandlers(Ljava/util/logging/Logger;Ljava/lang/String;Ljava/lang/String;)V
+Ljava/util/logging/LogManager;->loggerRefQueue:Ljava/lang/ref/ReferenceQueue;
+Ljava/util/logging/LogManager;->loggingMXBean:Ljava/util/logging/LoggingMXBean;
+Ljava/util/logging/LogManager;->manager:Ljava/util/logging/LogManager;
+Ljava/util/logging/LogManager;->MAX_ITERATIONS:I
+Ljava/util/logging/LogManager;->parseClassNames(Ljava/lang/String;)[Ljava/lang/String;
+Ljava/util/logging/LogManager;->props:Ljava/util/Properties;
+Ljava/util/logging/LogManager;->readPrimordialConfiguration()V
+Ljava/util/logging/LogManager;->readPrimordialConfiguration:Z
+Ljava/util/logging/LogManager;->resetLogger(Ljava/util/logging/Logger;)V
+Ljava/util/logging/LogManager;->rootLogger:Ljava/util/logging/Logger;
+Ljava/util/logging/LogManager;->setLevelsOnExistingLoggers()V
+Ljava/util/logging/LogManager;->systemContext:Ljava/util/logging/LogManager$LoggerContext;
+Ljava/util/logging/LogManager;->userContext:Ljava/util/logging/LogManager$LoggerContext;
+Ljava/util/logging/LogRecord;->defaultThreadID()I
+Ljava/util/logging/LogRecord;->globalSequenceNumber:Ljava/util/concurrent/atomic/AtomicLong;
+Ljava/util/logging/LogRecord;->inferCaller()V
+Ljava/util/logging/LogRecord;->isLoggerImplFrame(Ljava/lang/String;)Z
+Ljava/util/logging/LogRecord;->level:Ljava/util/logging/Level;
+Ljava/util/logging/LogRecord;->loggerName:Ljava/lang/String;
+Ljava/util/logging/LogRecord;->message:Ljava/lang/String;
+Ljava/util/logging/LogRecord;->millis:J
+Ljava/util/logging/LogRecord;->MIN_SEQUENTIAL_THREAD_ID:I
+Ljava/util/logging/LogRecord;->needToInferCaller:Z
+Ljava/util/logging/LogRecord;->nextThreadId:Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/util/logging/LogRecord;->parameters:[Ljava/lang/Object;
+Ljava/util/logging/LogRecord;->resourceBundle:Ljava/util/ResourceBundle;
+Ljava/util/logging/LogRecord;->resourceBundleName:Ljava/lang/String;
+Ljava/util/logging/LogRecord;->sequenceNumber:J
+Ljava/util/logging/LogRecord;->sourceClassName:Ljava/lang/String;
+Ljava/util/logging/LogRecord;->sourceMethodName:Ljava/lang/String;
+Ljava/util/logging/LogRecord;->threadID:I
+Ljava/util/logging/LogRecord;->threadIds:Ljava/lang/ThreadLocal;
+Ljava/util/logging/LogRecord;->thrown:Ljava/lang/Throwable;
+Ljava/util/logging/MemoryHandler;->buffer:[Ljava/util/logging/LogRecord;
+Ljava/util/logging/MemoryHandler;->configure()V
+Ljava/util/logging/MemoryHandler;->count:I
+Ljava/util/logging/MemoryHandler;->DEFAULT_SIZE:I
+Ljava/util/logging/MemoryHandler;->init()V
+Ljava/util/logging/MemoryHandler;->pushLevel:Ljava/util/logging/Level;
+Ljava/util/logging/MemoryHandler;->size:I
+Ljava/util/logging/MemoryHandler;->start:I
+Ljava/util/logging/MemoryHandler;->target:Ljava/util/logging/Handler;
+Ljava/util/logging/SimpleFormatter;->dat:Ljava/util/Date;
+Ljava/util/logging/SimpleFormatter;->format:Ljava/lang/String;
+Ljava/util/logging/SocketHandler;->configure()V
+Ljava/util/logging/SocketHandler;->connect()V
+Ljava/util/logging/SocketHandler;->host:Ljava/lang/String;
+Ljava/util/logging/SocketHandler;->port:I
+Ljava/util/logging/SocketHandler;->sock:Ljava/net/Socket;
+Ljava/util/logging/StreamHandler;->configure()V
+Ljava/util/logging/StreamHandler;->doneHeader:Z
+Ljava/util/logging/StreamHandler;->flushAndClose()V
+Ljava/util/logging/StreamHandler;->output:Ljava/io/OutputStream;
+Ljava/util/logging/StreamHandler;->writer:Ljava/io/Writer;
+Ljava/util/logging/XMLFormatter;->a2(Ljava/lang/StringBuilder;I)V
+Ljava/util/logging/XMLFormatter;->appendISO8601(Ljava/lang/StringBuilder;J)V
+Ljava/util/logging/XMLFormatter;->escape(Ljava/lang/StringBuilder;Ljava/lang/String;)V
+Ljava/util/logging/XMLFormatter;->manager:Ljava/util/logging/LogManager;
+Ljava/util/LongSummaryStatistics;->count:J
+Ljava/util/LongSummaryStatistics;->max:J
+Ljava/util/LongSummaryStatistics;->min:J
+Ljava/util/LongSummaryStatistics;->sum:J
+Ljava/util/MissingFormatArgumentException;->s:Ljava/lang/String;
+Ljava/util/MissingFormatWidthException;->s:Ljava/lang/String;
+Ljava/util/MissingResourceException;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/util/MissingResourceException;->className:Ljava/lang/String;
+Ljava/util/MissingResourceException;->key:Ljava/lang/String;
+Ljava/util/Objects;-><init>()V
+Ljava/util/Observable;->changed:Z
+Ljava/util/Observable;->obs:Ljava/util/Vector;
+Ljava/util/Optional;-><init>()V
+Ljava/util/Optional;-><init>(Ljava/lang/Object;)V
+Ljava/util/Optional;->EMPTY:Ljava/util/Optional;
+Ljava/util/Optional;->value:Ljava/lang/Object;
+Ljava/util/OptionalDouble;-><init>()V
+Ljava/util/OptionalDouble;-><init>(D)V
+Ljava/util/OptionalDouble;->EMPTY:Ljava/util/OptionalDouble;
+Ljava/util/OptionalDouble;->isPresent:Z
+Ljava/util/OptionalDouble;->value:D
+Ljava/util/OptionalInt;-><init>()V
+Ljava/util/OptionalInt;-><init>(I)V
+Ljava/util/OptionalInt;->EMPTY:Ljava/util/OptionalInt;
+Ljava/util/OptionalInt;->isPresent:Z
+Ljava/util/OptionalInt;->value:I
+Ljava/util/OptionalLong;-><init>()V
+Ljava/util/OptionalLong;-><init>(J)V
+Ljava/util/OptionalLong;->EMPTY:Ljava/util/OptionalLong;
+Ljava/util/OptionalLong;->isPresent:Z
+Ljava/util/OptionalLong;->value:J
+Ljava/util/prefs/AbstractPreferences$EventDispatchThread;-><init>()V
+Ljava/util/prefs/AbstractPreferences;->absolutePath:Ljava/lang/String;
+Ljava/util/prefs/AbstractPreferences;->EMPTY_ABSTRACT_PREFS_ARRAY:[Ljava/util/prefs/AbstractPreferences;
+Ljava/util/prefs/AbstractPreferences;->EMPTY_STRING_ARRAY:[Ljava/lang/String;
+Ljava/util/prefs/AbstractPreferences;->enqueueNodeAddedEvent(Ljava/util/prefs/Preferences;)V
+Ljava/util/prefs/AbstractPreferences;->enqueueNodeRemovedEvent(Ljava/util/prefs/Preferences;)V
+Ljava/util/prefs/AbstractPreferences;->enqueuePreferenceChangeEvent(Ljava/lang/String;Ljava/lang/String;)V
+Ljava/util/prefs/AbstractPreferences;->eventDispatchThread:Ljava/lang/Thread;
+Ljava/util/prefs/AbstractPreferences;->eventQueue:Ljava/util/List;
+Ljava/util/prefs/AbstractPreferences;->flush2()V
+Ljava/util/prefs/AbstractPreferences;->kidCache:Ljava/util/Map;
+Ljava/util/prefs/AbstractPreferences;->name:Ljava/lang/String;
+Ljava/util/prefs/AbstractPreferences;->node(Ljava/util/StringTokenizer;)Ljava/util/prefs/Preferences;
+Ljava/util/prefs/AbstractPreferences;->nodeExists(Ljava/util/StringTokenizer;)Z
+Ljava/util/prefs/AbstractPreferences;->nodeListeners()[Ljava/util/prefs/NodeChangeListener;
+Ljava/util/prefs/AbstractPreferences;->nodeListeners:Ljava/util/ArrayList;
+Ljava/util/prefs/AbstractPreferences;->parent:Ljava/util/prefs/AbstractPreferences;
+Ljava/util/prefs/AbstractPreferences;->prefListeners()[Ljava/util/prefs/PreferenceChangeListener;
+Ljava/util/prefs/AbstractPreferences;->prefListeners:Ljava/util/ArrayList;
+Ljava/util/prefs/AbstractPreferences;->removed:Z
+Ljava/util/prefs/AbstractPreferences;->removeNode2()V
+Ljava/util/prefs/AbstractPreferences;->root:Ljava/util/prefs/AbstractPreferences;
+Ljava/util/prefs/AbstractPreferences;->startEventDispatchThreadIfNecessary()V
+Ljava/util/prefs/AbstractPreferences;->sync2()V
+Ljava/util/prefs/FileSystemPreferences$Change;->replay()V
+Ljava/util/prefs/FileSystemPreferences$NodeCreate;->replay()V
+Ljava/util/prefs/FileSystemPreferences$Put;->key:Ljava/lang/String;
+Ljava/util/prefs/FileSystemPreferences$Put;->replay()V
+Ljava/util/prefs/FileSystemPreferences$Put;->value:Ljava/lang/String;
+Ljava/util/prefs/FileSystemPreferences$Remove;->key:Ljava/lang/String;
+Ljava/util/prefs/FileSystemPreferences$Remove;->replay()V
+Ljava/util/prefs/FileSystemPreferences;-><init>(Ljava/lang/String;Ljava/io/File;Z)V
+Ljava/util/prefs/FileSystemPreferences;-><init>(Ljava/util/prefs/FileSystemPreferences;Ljava/lang/String;)V
+Ljava/util/prefs/FileSystemPreferences;-><init>(Z)V
+Ljava/util/prefs/FileSystemPreferences;->byteArray(Ljava/lang/String;)[B
+Ljava/util/prefs/FileSystemPreferences;->changeLog:Ljava/util/List;
+Ljava/util/prefs/FileSystemPreferences;->checkLockFile0ErrorCode(I)V
+Ljava/util/prefs/FileSystemPreferences;->chmod(Ljava/lang/String;I)I
+Ljava/util/prefs/FileSystemPreferences;->dir:Ljava/io/File;
+Ljava/util/prefs/FileSystemPreferences;->dirName(Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/prefs/FileSystemPreferences;->EACCES:I
+Ljava/util/prefs/FileSystemPreferences;->EAGAIN:I
+Ljava/util/prefs/FileSystemPreferences;->EMPTY_STRING_ARRAY:[Ljava/lang/String;
+Ljava/util/prefs/FileSystemPreferences;->ERROR_CODE:I
+Ljava/util/prefs/FileSystemPreferences;->getLogger()Lsun/util/logging/PlatformLogger;
+Ljava/util/prefs/FileSystemPreferences;->getSystemRoot()Ljava/util/prefs/Preferences;
+Ljava/util/prefs/FileSystemPreferences;->getUserRoot()Ljava/util/prefs/Preferences;
+Ljava/util/prefs/FileSystemPreferences;->initCacheIfNecessary()V
+Ljava/util/prefs/FileSystemPreferences;->INIT_SLEEP_TIME:I
+Ljava/util/prefs/FileSystemPreferences;->isDirChar(C)Z
+Ljava/util/prefs/FileSystemPreferences;->isSystemRootModified:Z
+Ljava/util/prefs/FileSystemPreferences;->isSystemRootWritable:Z
+Ljava/util/prefs/FileSystemPreferences;->isUserNode:Z
+Ljava/util/prefs/FileSystemPreferences;->isUserRootModified:Z
+Ljava/util/prefs/FileSystemPreferences;->isUserRootWritable:Z
+Ljava/util/prefs/FileSystemPreferences;->lastSyncTime:J
+Ljava/util/prefs/FileSystemPreferences;->loadCache()V
+Ljava/util/prefs/FileSystemPreferences;->lockFile(Z)Z
+Ljava/util/prefs/FileSystemPreferences;->lockFile0(Ljava/lang/String;IZ)[I
+Ljava/util/prefs/FileSystemPreferences;->LOCK_HANDLE:I
+Ljava/util/prefs/FileSystemPreferences;->MAX_ATTEMPTS:I
+Ljava/util/prefs/FileSystemPreferences;->nodeCreate:Ljava/util/prefs/FileSystemPreferences$NodeCreate;
+Ljava/util/prefs/FileSystemPreferences;->nodeName(Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/prefs/FileSystemPreferences;->prefsCache:Ljava/util/Map;
+Ljava/util/prefs/FileSystemPreferences;->prefsFile:Ljava/io/File;
+Ljava/util/prefs/FileSystemPreferences;->replayChanges()V
+Ljava/util/prefs/FileSystemPreferences;->setupSystemRoot()V
+Ljava/util/prefs/FileSystemPreferences;->setupUserRoot()V
+Ljava/util/prefs/FileSystemPreferences;->syncSpiPrivileged()V
+Ljava/util/prefs/FileSystemPreferences;->syncWorld()V
+Ljava/util/prefs/FileSystemPreferences;->systemLockFile:Ljava/io/File;
+Ljava/util/prefs/FileSystemPreferences;->systemRoot:Ljava/util/prefs/Preferences;
+Ljava/util/prefs/FileSystemPreferences;->systemRootDir:Ljava/io/File;
+Ljava/util/prefs/FileSystemPreferences;->systemRootLockHandle:I
+Ljava/util/prefs/FileSystemPreferences;->systemRootModFile:Ljava/io/File;
+Ljava/util/prefs/FileSystemPreferences;->systemRootModTime:J
+Ljava/util/prefs/FileSystemPreferences;->tmpFile:Ljava/io/File;
+Ljava/util/prefs/FileSystemPreferences;->unlockFile()V
+Ljava/util/prefs/FileSystemPreferences;->unlockFile0(I)I
+Ljava/util/prefs/FileSystemPreferences;->userLockFile:Ljava/io/File;
+Ljava/util/prefs/FileSystemPreferences;->userRoot:Ljava/util/prefs/Preferences;
+Ljava/util/prefs/FileSystemPreferences;->userRootDir:Ljava/io/File;
+Ljava/util/prefs/FileSystemPreferences;->userRootLockHandle:I
+Ljava/util/prefs/FileSystemPreferences;->userRootModFile:Ljava/io/File;
+Ljava/util/prefs/FileSystemPreferences;->userRootModTime:J
+Ljava/util/prefs/FileSystemPreferences;->USER_READ_WRITE:I
+Ljava/util/prefs/FileSystemPreferences;->USER_RWX:I
+Ljava/util/prefs/FileSystemPreferences;->USER_RWX_ALL_RX:I
+Ljava/util/prefs/FileSystemPreferences;->USER_RW_ALL_READ:I
+Ljava/util/prefs/FileSystemPreferences;->writeBackCache()V
+Ljava/util/prefs/NodeChangeEvent;->child:Ljava/util/prefs/Preferences;
+Ljava/util/prefs/PreferenceChangeEvent;->key:Ljava/lang/String;
+Ljava/util/prefs/PreferenceChangeEvent;->newValue:Ljava/lang/String;
+Ljava/util/prefs/Preferences;->factory:Ljava/util/prefs/PreferencesFactory;
+Ljava/util/prefs/Preferences;->findPreferencesFactory()Ljava/util/prefs/PreferencesFactory;
+Ljava/util/prefs/Preferences;->nodeName(Ljava/lang/Class;)Ljava/lang/String;
+Ljava/util/prefs/Preferences;->prefsPerm:Ljava/security/Permission;
+Ljava/util/prefs/Preferences;->setPreferencesFactory(Ljava/util/prefs/PreferencesFactory;)Ljava/util/prefs/PreferencesFactory;
+Ljava/util/PriorityQueue$Itr;->cursor:I
+Ljava/util/PriorityQueue$Itr;->expectedModCount:I
+Ljava/util/PriorityQueue$Itr;->forgetMeNot:Ljava/util/ArrayDeque;
+Ljava/util/PriorityQueue$Itr;->lastRet:I
+Ljava/util/PriorityQueue$Itr;->lastRetElt:Ljava/lang/Object;
+Ljava/util/PriorityQueue$PriorityQueueSpliterator;-><init>(Ljava/util/PriorityQueue;III)V
+Ljava/util/PriorityQueue$PriorityQueueSpliterator;->expectedModCount:I
+Ljava/util/PriorityQueue$PriorityQueueSpliterator;->fence:I
+Ljava/util/PriorityQueue$PriorityQueueSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/PriorityQueue$PriorityQueueSpliterator;->getFence()I
+Ljava/util/PriorityQueue$PriorityQueueSpliterator;->index:I
+Ljava/util/PriorityQueue$PriorityQueueSpliterator;->pq:Ljava/util/PriorityQueue;
+Ljava/util/PriorityQueue$PriorityQueueSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/PriorityQueue;->comparator:Ljava/util/Comparator;
+Ljava/util/PriorityQueue;->DEFAULT_INITIAL_CAPACITY:I
+Ljava/util/PriorityQueue;->grow(I)V
+Ljava/util/PriorityQueue;->heapify()V
+Ljava/util/PriorityQueue;->hugeCapacity(I)I
+Ljava/util/PriorityQueue;->indexOf(Ljava/lang/Object;)I
+Ljava/util/PriorityQueue;->initElementsFromCollection(Ljava/util/Collection;)V
+Ljava/util/PriorityQueue;->initFromCollection(Ljava/util/Collection;)V
+Ljava/util/PriorityQueue;->initFromPriorityQueue(Ljava/util/PriorityQueue;)V
+Ljava/util/PriorityQueue;->MAX_ARRAY_SIZE:I
+Ljava/util/PriorityQueue;->removeAt(I)Ljava/lang/Object;
+Ljava/util/PriorityQueue;->removeEq(Ljava/lang/Object;)Z
+Ljava/util/PriorityQueue;->siftDown(ILjava/lang/Object;)V
+Ljava/util/PriorityQueue;->siftDownComparable(ILjava/lang/Object;)V
+Ljava/util/PriorityQueue;->siftDownUsingComparator(ILjava/lang/Object;)V
+Ljava/util/PriorityQueue;->siftUp(ILjava/lang/Object;)V
+Ljava/util/PriorityQueue;->siftUpComparable(ILjava/lang/Object;)V
+Ljava/util/PriorityQueue;->siftUpUsingComparator(ILjava/lang/Object;)V
+Ljava/util/Properties$LineReader;->inByteBuf:[B
+Ljava/util/Properties$LineReader;->inCharBuf:[C
+Ljava/util/Properties$LineReader;->inLimit:I
+Ljava/util/Properties$LineReader;->inOff:I
+Ljava/util/Properties$LineReader;->inStream:Ljava/io/InputStream;
+Ljava/util/Properties$LineReader;->lineBuf:[C
+Ljava/util/Properties$LineReader;->reader:Ljava/io/Reader;
+Ljava/util/Properties$LineReader;->readLine()I
+Ljava/util/Properties;->enumerate(Ljava/util/Hashtable;)V
+Ljava/util/Properties;->enumerateStringProperties(Ljava/util/Hashtable;)V
+Ljava/util/Properties;->hexDigit:[C
+Ljava/util/Properties;->load0(Ljava/util/Properties$LineReader;)V
+Ljava/util/Properties;->loadConvert([CII[C)Ljava/lang/String;
+Ljava/util/Properties;->store0(Ljava/io/BufferedWriter;Ljava/lang/String;Z)V
+Ljava/util/Properties;->toHex(I)C
+Ljava/util/Properties;->writeComments(Ljava/io/BufferedWriter;Ljava/lang/String;)V
+Ljava/util/PropertyResourceBundle;->lookup:Ljava/util/Map;
+Ljava/util/Random$RandomDoublesSpliterator;-><init>(Ljava/util/Random;JJDD)V
+Ljava/util/Random$RandomDoublesSpliterator;->bound:D
+Ljava/util/Random$RandomDoublesSpliterator;->fence:J
+Ljava/util/Random$RandomDoublesSpliterator;->index:J
+Ljava/util/Random$RandomDoublesSpliterator;->origin:D
+Ljava/util/Random$RandomDoublesSpliterator;->rng:Ljava/util/Random;
+Ljava/util/Random$RandomIntsSpliterator;-><init>(Ljava/util/Random;JJII)V
+Ljava/util/Random$RandomIntsSpliterator;->bound:I
+Ljava/util/Random$RandomIntsSpliterator;->fence:J
+Ljava/util/Random$RandomIntsSpliterator;->index:J
+Ljava/util/Random$RandomIntsSpliterator;->origin:I
+Ljava/util/Random$RandomIntsSpliterator;->rng:Ljava/util/Random;
+Ljava/util/Random$RandomLongsSpliterator;-><init>(Ljava/util/Random;JJJJ)V
+Ljava/util/Random$RandomLongsSpliterator;->bound:J
+Ljava/util/Random$RandomLongsSpliterator;->fence:J
+Ljava/util/Random$RandomLongsSpliterator;->index:J
+Ljava/util/Random$RandomLongsSpliterator;->origin:J
+Ljava/util/Random$RandomLongsSpliterator;->rng:Ljava/util/Random;
+Ljava/util/Random;->addend:J
+Ljava/util/Random;->BadBound:Ljava/lang/String;
+Ljava/util/Random;->BadRange:Ljava/lang/String;
+Ljava/util/Random;->BadSize:Ljava/lang/String;
+Ljava/util/Random;->DOUBLE_UNIT:D
+Ljava/util/Random;->haveNextNextGaussian:Z
+Ljava/util/Random;->initialScramble(J)J
+Ljava/util/Random;->internalNextDouble(DD)D
+Ljava/util/Random;->internalNextInt(II)I
+Ljava/util/Random;->internalNextLong(JJ)J
+Ljava/util/Random;->mask:J
+Ljava/util/Random;->multiplier:J
+Ljava/util/Random;->nextNextGaussian:D
+Ljava/util/Random;->resetSeed(J)V
+Ljava/util/Random;->seed:Ljava/util/concurrent/atomic/AtomicLong;
+Ljava/util/Random;->seedOffset:J
+Ljava/util/Random;->seedUniquifier:Ljava/util/concurrent/atomic/AtomicLong;
+Ljava/util/Random;->unsafe:Lsun/misc/Unsafe;
+Ljava/util/regex/Matcher$OffsetBasedMatchResult;-><init>(Ljava/lang/String;[I)V
+Ljava/util/regex/Matcher$OffsetBasedMatchResult;->input:Ljava/lang/String;
+Ljava/util/regex/Matcher$OffsetBasedMatchResult;->offsets:[I
+Ljava/util/regex/Matcher;-><init>(Ljava/util/regex/Pattern;Ljava/lang/CharSequence;)V
+Ljava/util/regex/Matcher;->address:J
+Ljava/util/regex/Matcher;->anchoringBounds:Z
+Ljava/util/regex/Matcher;->appendEvaluated(Ljava/lang/StringBuffer;Ljava/lang/String;)V
+Ljava/util/regex/Matcher;->ensureMatch()V
+Ljava/util/regex/Matcher;->findImpl(JI[I)Z
+Ljava/util/regex/Matcher;->findNextImpl(J[I)Z
+Ljava/util/regex/Matcher;->getMatchedGroupIndex(JLjava/lang/String;)I
+Ljava/util/regex/Matcher;->getMatchedGroupIndex0(JLjava/lang/String;)I
+Ljava/util/regex/Matcher;->getNativeFinalizer()J
+Ljava/util/regex/Matcher;->groupCountImpl(J)I
+Ljava/util/regex/Matcher;->hitEndImpl(J)Z
+Ljava/util/regex/Matcher;->input:Ljava/lang/String;
+Ljava/util/regex/Matcher;->lookingAtImpl(J[I)Z
+Ljava/util/regex/Matcher;->matchesImpl(J[I)Z
+Ljava/util/regex/Matcher;->matchFound:Z
+Ljava/util/regex/Matcher;->matchOffsets:[I
+Ljava/util/regex/Matcher;->nativeFinalizer:Ljava/lang/Runnable;
+Ljava/util/regex/Matcher;->nativeSize()I
+Ljava/util/regex/Matcher;->openImpl(J)J
+Ljava/util/regex/Matcher;->originalInput:Ljava/lang/CharSequence;
+Ljava/util/regex/Matcher;->pattern:Ljava/util/regex/Pattern;
+Ljava/util/regex/Matcher;->regionEnd:I
+Ljava/util/regex/Matcher;->regionStart:I
+Ljava/util/regex/Matcher;->registry:Llibcore/util/NativeAllocationRegistry;
+Ljava/util/regex/Matcher;->requireEndImpl(J)Z
+Ljava/util/regex/Matcher;->reset(Ljava/lang/CharSequence;II)Ljava/util/regex/Matcher;
+Ljava/util/regex/Matcher;->resetForInput()V
+Ljava/util/regex/Matcher;->setInputImpl(JLjava/lang/String;II)V
+Ljava/util/regex/Matcher;->transparentBounds:Z
+Ljava/util/regex/Matcher;->useAnchoringBoundsImpl(JZ)V
+Ljava/util/regex/Matcher;->useTransparentBoundsImpl(JZ)V
+Ljava/util/regex/Pattern;-><init>(Ljava/lang/String;I)V
+Ljava/util/regex/Pattern;->address:J
+Ljava/util/regex/Pattern;->compile()V
+Ljava/util/regex/Pattern;->compileImpl(Ljava/lang/String;I)J
+Ljava/util/regex/Pattern;->fastSplit(Ljava/lang/String;Ljava/lang/String;I)[Ljava/lang/String;
+Ljava/util/regex/Pattern;->FASTSPLIT_METACHARACTERS:Ljava/lang/String;
+Ljava/util/regex/Pattern;->flags:I
+Ljava/util/regex/Pattern;->getNativeFinalizer()J
+Ljava/util/regex/Pattern;->nativeSize()I
+Ljava/util/regex/Pattern;->pattern:Ljava/lang/String;
+Ljava/util/regex/Pattern;->registry:Llibcore/util/NativeAllocationRegistry;
+Ljava/util/regex/PatternSyntaxException;->desc:Ljava/lang/String;
+Ljava/util/regex/PatternSyntaxException;->index:I
+Ljava/util/regex/PatternSyntaxException;->nl:Ljava/lang/String;
+Ljava/util/regex/PatternSyntaxException;->pattern:Ljava/lang/String;
+Ljava/util/ResourceBundle$BundleReference;-><init>(Ljava/util/ResourceBundle;Ljava/lang/ref/ReferenceQueue;Ljava/util/ResourceBundle$CacheKey;)V
+Ljava/util/ResourceBundle$BundleReference;->cacheKey:Ljava/util/ResourceBundle$CacheKey;
+Ljava/util/ResourceBundle$BundleReference;->getCacheKey()Ljava/util/ResourceBundle$CacheKey;
+Ljava/util/ResourceBundle$CacheKey;-><init>(Ljava/lang/String;Ljava/util/Locale;Ljava/lang/ClassLoader;)V
+Ljava/util/ResourceBundle$CacheKey;->calculateHashCode()V
+Ljava/util/ResourceBundle$CacheKey;->cause:Ljava/lang/Throwable;
+Ljava/util/ResourceBundle$CacheKey;->expirationTime:J
+Ljava/util/ResourceBundle$CacheKey;->format:Ljava/lang/String;
+Ljava/util/ResourceBundle$CacheKey;->getCause()Ljava/lang/Throwable;
+Ljava/util/ResourceBundle$CacheKey;->getFormat()Ljava/lang/String;
+Ljava/util/ResourceBundle$CacheKey;->getLoader()Ljava/lang/ClassLoader;
+Ljava/util/ResourceBundle$CacheKey;->getLocale()Ljava/util/Locale;
+Ljava/util/ResourceBundle$CacheKey;->getName()Ljava/lang/String;
+Ljava/util/ResourceBundle$CacheKey;->hashCodeCache:I
+Ljava/util/ResourceBundle$CacheKey;->loaderRef:Ljava/util/ResourceBundle$LoaderReference;
+Ljava/util/ResourceBundle$CacheKey;->loadTime:J
+Ljava/util/ResourceBundle$CacheKey;->locale:Ljava/util/Locale;
+Ljava/util/ResourceBundle$CacheKey;->name:Ljava/lang/String;
+Ljava/util/ResourceBundle$CacheKey;->setCause(Ljava/lang/Throwable;)V
+Ljava/util/ResourceBundle$CacheKey;->setFormat(Ljava/lang/String;)V
+Ljava/util/ResourceBundle$CacheKey;->setLocale(Ljava/util/Locale;)Ljava/util/ResourceBundle$CacheKey;
+Ljava/util/ResourceBundle$CacheKey;->setName(Ljava/lang/String;)Ljava/util/ResourceBundle$CacheKey;
+Ljava/util/ResourceBundle$CacheKeyReference;->getCacheKey()Ljava/util/ResourceBundle$CacheKey;
+Ljava/util/ResourceBundle$Control$CandidateListCache;-><init>()V
+Ljava/util/ResourceBundle$Control$CandidateListCache;->createObject(Lsun/util/locale/BaseLocale;)Ljava/util/List;
+Ljava/util/ResourceBundle$Control$CandidateListCache;->getDefaultList(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
+Ljava/util/ResourceBundle$Control;->CANDIDATES_CACHE:Ljava/util/ResourceBundle$Control$CandidateListCache;
+Ljava/util/ResourceBundle$Control;->INSTANCE:Ljava/util/ResourceBundle$Control;
+Ljava/util/ResourceBundle$Control;->toResourceName0(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/ResourceBundle$LoaderReference;-><init>(Ljava/lang/ClassLoader;Ljava/lang/ref/ReferenceQueue;Ljava/util/ResourceBundle$CacheKey;)V
+Ljava/util/ResourceBundle$LoaderReference;->cacheKey:Ljava/util/ResourceBundle$CacheKey;
+Ljava/util/ResourceBundle$LoaderReference;->getCacheKey()Ljava/util/ResourceBundle$CacheKey;
+Ljava/util/ResourceBundle$NoFallbackControl;-><init>(Ljava/util/List;)V
+Ljava/util/ResourceBundle$NoFallbackControl;->CLASS_ONLY_NO_FALLBACK:Ljava/util/ResourceBundle$Control;
+Ljava/util/ResourceBundle$NoFallbackControl;->NO_FALLBACK:Ljava/util/ResourceBundle$Control;
+Ljava/util/ResourceBundle$NoFallbackControl;->PROPERTIES_ONLY_NO_FALLBACK:Ljava/util/ResourceBundle$Control;
+Ljava/util/ResourceBundle$RBClassLoader;-><init>()V
+Ljava/util/ResourceBundle$RBClassLoader;->INSTANCE:Ljava/util/ResourceBundle$RBClassLoader;
+Ljava/util/ResourceBundle$RBClassLoader;->loader:Ljava/lang/ClassLoader;
+Ljava/util/ResourceBundle$SingleFormatControl;-><init>(Ljava/util/List;)V
+Ljava/util/ResourceBundle$SingleFormatControl;->CLASS_ONLY:Ljava/util/ResourceBundle$Control;
+Ljava/util/ResourceBundle$SingleFormatControl;->formats:Ljava/util/List;
+Ljava/util/ResourceBundle$SingleFormatControl;->PROPERTIES_ONLY:Ljava/util/ResourceBundle$Control;
+Ljava/util/ResourceBundle;->cacheKey:Ljava/util/ResourceBundle$CacheKey;
+Ljava/util/ResourceBundle;->cacheList:Ljava/util/concurrent/ConcurrentMap;
+Ljava/util/ResourceBundle;->checkList(Ljava/util/List;)Z
+Ljava/util/ResourceBundle;->expired:Z
+Ljava/util/ResourceBundle;->findBundle(Ljava/util/ResourceBundle$CacheKey;Ljava/util/List;Ljava/util/List;ILjava/util/ResourceBundle$Control;Ljava/util/ResourceBundle;)Ljava/util/ResourceBundle;
+Ljava/util/ResourceBundle;->findBundleInCache(Ljava/util/ResourceBundle$CacheKey;Ljava/util/ResourceBundle$Control;)Ljava/util/ResourceBundle;
+Ljava/util/ResourceBundle;->getBundleImpl(Ljava/lang/String;Ljava/util/Locale;Ljava/lang/ClassLoader;Ljava/util/ResourceBundle$Control;)Ljava/util/ResourceBundle;
+Ljava/util/ResourceBundle;->getDefaultControl(Ljava/lang/String;)Ljava/util/ResourceBundle$Control;
+Ljava/util/ResourceBundle;->getLoader(Ljava/lang/ClassLoader;)Ljava/lang/ClassLoader;
+Ljava/util/ResourceBundle;->hasValidParentChain(Ljava/util/ResourceBundle;)Z
+Ljava/util/ResourceBundle;->INITIAL_CACHE_SIZE:I
+Ljava/util/ResourceBundle;->isValidBundle(Ljava/util/ResourceBundle;)Z
+Ljava/util/ResourceBundle;->keySet:Ljava/util/Set;
+Ljava/util/ResourceBundle;->loadBundle(Ljava/util/ResourceBundle$CacheKey;Ljava/util/List;Ljava/util/ResourceBundle$Control;Z)Ljava/util/ResourceBundle;
+Ljava/util/ResourceBundle;->locale:Ljava/util/Locale;
+Ljava/util/ResourceBundle;->name:Ljava/lang/String;
+Ljava/util/ResourceBundle;->NONEXISTENT_BUNDLE:Ljava/util/ResourceBundle;
+Ljava/util/ResourceBundle;->putBundleInCache(Ljava/util/ResourceBundle$CacheKey;Ljava/util/ResourceBundle;Ljava/util/ResourceBundle$Control;)Ljava/util/ResourceBundle;
+Ljava/util/ResourceBundle;->referenceQueue:Ljava/lang/ref/ReferenceQueue;
+Ljava/util/ResourceBundle;->setExpirationTime(Ljava/util/ResourceBundle$CacheKey;Ljava/util/ResourceBundle$Control;)V
+Ljava/util/ResourceBundle;->throwMissingResourceException(Ljava/lang/String;Ljava/util/Locale;Ljava/lang/Throwable;)V
+Ljava/util/Scanner;-><init>(Ljava/io/File;Ljava/nio/charset/CharsetDecoder;)V
+Ljava/util/Scanner;-><init>(Ljava/lang/Readable;Ljava/util/regex/Pattern;)V
+Ljava/util/Scanner;-><init>(Ljava/nio/file/Path;Ljava/nio/charset/Charset;)V
+Ljava/util/Scanner;->BOOLEAN_PATTERN:Ljava/lang/String;
+Ljava/util/Scanner;->boolPattern()Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->boolPattern:Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->buf:Ljava/nio/CharBuffer;
+Ljava/util/Scanner;->BUFFER_SIZE:I
+Ljava/util/Scanner;->buildFloatAndDecimalPattern()V
+Ljava/util/Scanner;->buildIntegerPatternString()Ljava/lang/String;
+Ljava/util/Scanner;->cacheResult()V
+Ljava/util/Scanner;->cacheResult(Ljava/lang/String;)V
+Ljava/util/Scanner;->clearCaches()V
+Ljava/util/Scanner;->closed:Z
+Ljava/util/Scanner;->decimalPattern()Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->decimalPattern:Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->decimalSeparator:Ljava/lang/String;
+Ljava/util/Scanner;->defaultRadix:I
+Ljava/util/Scanner;->delimPattern:Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->digits:Ljava/lang/String;
+Ljava/util/Scanner;->ensureOpen()V
+Ljava/util/Scanner;->findPatternInBuffer(Ljava/util/regex/Pattern;I)Ljava/lang/String;
+Ljava/util/Scanner;->FIND_ANY_PATTERN:Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->floatPattern()Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->floatPattern:Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->getCachedResult()Ljava/lang/String;
+Ljava/util/Scanner;->getCompleteTokenInBuffer(Ljava/util/regex/Pattern;)Ljava/lang/String;
+Ljava/util/Scanner;->groupSeparator:Ljava/lang/String;
+Ljava/util/Scanner;->hasNextPattern:Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->hasNextPosition:I
+Ljava/util/Scanner;->hasNextResult:Ljava/lang/String;
+Ljava/util/Scanner;->hasTokenInBuffer()Z
+Ljava/util/Scanner;->infinityString:Ljava/lang/String;
+Ljava/util/Scanner;->integerPattern()Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->integerPattern:Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->lastException:Ljava/io/IOException;
+Ljava/util/Scanner;->linePattern()Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->linePattern:Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->LINE_PATTERN:Ljava/lang/String;
+Ljava/util/Scanner;->LINE_SEPARATOR_PATTERN:Ljava/lang/String;
+Ljava/util/Scanner;->locale:Ljava/util/Locale;
+Ljava/util/Scanner;->makeReadable(Ljava/io/InputStream;Ljava/nio/charset/Charset;)Ljava/lang/Readable;
+Ljava/util/Scanner;->makeReadable(Ljava/nio/channels/ReadableByteChannel;)Ljava/lang/Readable;
+Ljava/util/Scanner;->makeReadable(Ljava/nio/channels/ReadableByteChannel;Ljava/nio/charset/CharsetDecoder;)Ljava/lang/Readable;
+Ljava/util/Scanner;->makeSpace()Z
+Ljava/util/Scanner;->matcher:Ljava/util/regex/Matcher;
+Ljava/util/Scanner;->matchPatternInBuffer(Ljava/util/regex/Pattern;)Ljava/lang/String;
+Ljava/util/Scanner;->matchValid:Z
+Ljava/util/Scanner;->nanString:Ljava/lang/String;
+Ljava/util/Scanner;->needInput:Z
+Ljava/util/Scanner;->negativePrefix:Ljava/lang/String;
+Ljava/util/Scanner;->negativeSuffix:Ljava/lang/String;
+Ljava/util/Scanner;->non0Digit:Ljava/lang/String;
+Ljava/util/Scanner;->NON_ASCII_DIGIT:Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->patternCache:Lsun/misc/LRUCache;
+Ljava/util/Scanner;->position:I
+Ljava/util/Scanner;->positivePrefix:Ljava/lang/String;
+Ljava/util/Scanner;->positiveSuffix:Ljava/lang/String;
+Ljava/util/Scanner;->processFloatToken(Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/Scanner;->processIntegerToken(Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/Scanner;->radix:I
+Ljava/util/Scanner;->readInput()V
+Ljava/util/Scanner;->revertState()V
+Ljava/util/Scanner;->revertState(Z)Z
+Ljava/util/Scanner;->savedScannerPosition:I
+Ljava/util/Scanner;->saveState()V
+Ljava/util/Scanner;->separatorPattern()Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->separatorPattern:Ljava/util/regex/Pattern;
+Ljava/util/Scanner;->setRadix(I)V
+Ljava/util/Scanner;->SIMPLE_GROUP_INDEX:I
+Ljava/util/Scanner;->skipped:Z
+Ljava/util/Scanner;->source:Ljava/lang/Readable;
+Ljava/util/Scanner;->sourceClosed:Z
+Ljava/util/Scanner;->throwFor()V
+Ljava/util/Scanner;->toCharset(Ljava/lang/String;)Ljava/nio/charset/Charset;
+Ljava/util/Scanner;->toDecoder(Ljava/lang/String;)Ljava/nio/charset/CharsetDecoder;
+Ljava/util/Scanner;->translateSavedIndexes(I)V
+Ljava/util/Scanner;->typeCache:Ljava/lang/Object;
+Ljava/util/Scanner;->useTypeCache()V
+Ljava/util/Scanner;->WHITESPACE_PATTERN:Ljava/util/regex/Pattern;
+Ljava/util/ServiceLoader$LazyIterator;->configs:Ljava/util/Enumeration;
+Ljava/util/ServiceLoader$LazyIterator;->hasNextService()Z
+Ljava/util/ServiceLoader$LazyIterator;->loader:Ljava/lang/ClassLoader;
+Ljava/util/ServiceLoader$LazyIterator;->nextName:Ljava/lang/String;
+Ljava/util/ServiceLoader$LazyIterator;->nextService()Ljava/lang/Object;
+Ljava/util/ServiceLoader$LazyIterator;->pending:Ljava/util/Iterator;
+Ljava/util/ServiceLoader$LazyIterator;->service:Ljava/lang/Class;
+Ljava/util/ServiceLoader;-><init>(Ljava/lang/Class;Ljava/lang/ClassLoader;)V
+Ljava/util/ServiceLoader;->fail(Ljava/lang/Class;Ljava/lang/String;)V
+Ljava/util/ServiceLoader;->fail(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Throwable;)V
+Ljava/util/ServiceLoader;->fail(Ljava/lang/Class;Ljava/net/URL;ILjava/lang/String;)V
+Ljava/util/ServiceLoader;->loader:Ljava/lang/ClassLoader;
+Ljava/util/ServiceLoader;->loadFromSystemProperty(Ljava/lang/Class;)Ljava/lang/Object;
+Ljava/util/ServiceLoader;->lookupIterator:Ljava/util/ServiceLoader$LazyIterator;
+Ljava/util/ServiceLoader;->parse(Ljava/lang/Class;Ljava/net/URL;)Ljava/util/Iterator;
+Ljava/util/ServiceLoader;->parseLine(Ljava/lang/Class;Ljava/net/URL;Ljava/io/BufferedReader;ILjava/util/List;)I
+Ljava/util/ServiceLoader;->PREFIX:Ljava/lang/String;
+Ljava/util/ServiceLoader;->providers:Ljava/util/LinkedHashMap;
+Ljava/util/ServiceLoader;->service:Ljava/lang/Class;
+Ljava/util/SimpleTimeZone;->cacheEnd:J
+Ljava/util/SimpleTimeZone;->cacheStart:J
+Ljava/util/SimpleTimeZone;->cacheYear:J
+Ljava/util/SimpleTimeZone;->currentSerialVersion:I
+Ljava/util/SimpleTimeZone;->decodeEndRule()V
+Ljava/util/SimpleTimeZone;->decodeRules()V
+Ljava/util/SimpleTimeZone;->decodeStartRule()V
+Ljava/util/SimpleTimeZone;->DOM_MODE:I
+Ljava/util/SimpleTimeZone;->DOW_GE_DOM_MODE:I
+Ljava/util/SimpleTimeZone;->DOW_IN_MONTH_MODE:I
+Ljava/util/SimpleTimeZone;->DOW_LE_DOM_MODE:I
+Ljava/util/SimpleTimeZone;->dstSavings:I
+Ljava/util/SimpleTimeZone;->endDay:I
+Ljava/util/SimpleTimeZone;->endDayOfWeek:I
+Ljava/util/SimpleTimeZone;->endMode:I
+Ljava/util/SimpleTimeZone;->endMonth:I
+Ljava/util/SimpleTimeZone;->endTime:I
+Ljava/util/SimpleTimeZone;->endTimeMode:I
+Ljava/util/SimpleTimeZone;->gcal:Lsun/util/calendar/Gregorian;
+Ljava/util/SimpleTimeZone;->getEnd(Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/BaseCalendar$Date;I)J
+Ljava/util/SimpleTimeZone;->getOffset(Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/BaseCalendar$Date;IJ)I
+Ljava/util/SimpleTimeZone;->getOffsets(J[I)I
+Ljava/util/SimpleTimeZone;->getStart(Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/BaseCalendar$Date;I)J
+Ljava/util/SimpleTimeZone;->getTransition(Lsun/util/calendar/BaseCalendar;Lsun/util/calendar/BaseCalendar$Date;IIIIII)J
+Ljava/util/SimpleTimeZone;->invalidateCache()V
+Ljava/util/SimpleTimeZone;->makeRulesCompatible()V
+Ljava/util/SimpleTimeZone;->millisPerDay:I
+Ljava/util/SimpleTimeZone;->millisPerHour:I
+Ljava/util/SimpleTimeZone;->monthLength:[B
+Ljava/util/SimpleTimeZone;->packRules()[B
+Ljava/util/SimpleTimeZone;->packTimes()[I
+Ljava/util/SimpleTimeZone;->rawOffset:I
+Ljava/util/SimpleTimeZone;->serialVersionOnStream:I
+Ljava/util/SimpleTimeZone;->startDay:I
+Ljava/util/SimpleTimeZone;->startDayOfWeek:I
+Ljava/util/SimpleTimeZone;->startMode:I
+Ljava/util/SimpleTimeZone;->startMonth:I
+Ljava/util/SimpleTimeZone;->startTime:I
+Ljava/util/SimpleTimeZone;->startTimeMode:I
+Ljava/util/SimpleTimeZone;->startYear:I
+Ljava/util/SimpleTimeZone;->staticLeapMonthLength:[B
+Ljava/util/SimpleTimeZone;->staticMonthLength:[B
+Ljava/util/SimpleTimeZone;->unpackRules([B)V
+Ljava/util/SimpleTimeZone;->unpackTimes([I)V
+Ljava/util/SimpleTimeZone;->useDaylight:Z
+Ljava/util/Spliterators$AbstractDoubleSpliterator$HoldingDoubleConsumer;-><init>()V
+Ljava/util/Spliterators$AbstractDoubleSpliterator$HoldingDoubleConsumer;->value:D
+Ljava/util/Spliterators$AbstractDoubleSpliterator;->batch:I
+Ljava/util/Spliterators$AbstractDoubleSpliterator;->BATCH_UNIT:I
+Ljava/util/Spliterators$AbstractDoubleSpliterator;->characteristics:I
+Ljava/util/Spliterators$AbstractDoubleSpliterator;->est:J
+Ljava/util/Spliterators$AbstractDoubleSpliterator;->MAX_BATCH:I
+Ljava/util/Spliterators$AbstractIntSpliterator$HoldingIntConsumer;-><init>()V
+Ljava/util/Spliterators$AbstractIntSpliterator$HoldingIntConsumer;->value:I
+Ljava/util/Spliterators$AbstractIntSpliterator;->batch:I
+Ljava/util/Spliterators$AbstractIntSpliterator;->BATCH_UNIT:I
+Ljava/util/Spliterators$AbstractIntSpliterator;->characteristics:I
+Ljava/util/Spliterators$AbstractIntSpliterator;->est:J
+Ljava/util/Spliterators$AbstractIntSpliterator;->MAX_BATCH:I
+Ljava/util/Spliterators$AbstractLongSpliterator$HoldingLongConsumer;-><init>()V
+Ljava/util/Spliterators$AbstractLongSpliterator$HoldingLongConsumer;->value:J
+Ljava/util/Spliterators$AbstractLongSpliterator;->batch:I
+Ljava/util/Spliterators$AbstractLongSpliterator;->BATCH_UNIT:I
+Ljava/util/Spliterators$AbstractLongSpliterator;->characteristics:I
+Ljava/util/Spliterators$AbstractLongSpliterator;->est:J
+Ljava/util/Spliterators$AbstractLongSpliterator;->MAX_BATCH:I
+Ljava/util/Spliterators$AbstractSpliterator$HoldingConsumer;-><init>()V
+Ljava/util/Spliterators$AbstractSpliterator$HoldingConsumer;->value:Ljava/lang/Object;
+Ljava/util/Spliterators$AbstractSpliterator;->batch:I
+Ljava/util/Spliterators$AbstractSpliterator;->BATCH_UNIT:I
+Ljava/util/Spliterators$AbstractSpliterator;->characteristics:I
+Ljava/util/Spliterators$AbstractSpliterator;->est:J
+Ljava/util/Spliterators$AbstractSpliterator;->MAX_BATCH:I
+Ljava/util/Spliterators$ArraySpliterator;-><init>([Ljava/lang/Object;I)V
+Ljava/util/Spliterators$ArraySpliterator;-><init>([Ljava/lang/Object;III)V
+Ljava/util/Spliterators$ArraySpliterator;->array:[Ljava/lang/Object;
+Ljava/util/Spliterators$ArraySpliterator;->characteristics:I
+Ljava/util/Spliterators$ArraySpliterator;->fence:I
+Ljava/util/Spliterators$ArraySpliterator;->index:I
+Ljava/util/Spliterators$DoubleArraySpliterator;-><init>([DI)V
+Ljava/util/Spliterators$DoubleArraySpliterator;-><init>([DIII)V
+Ljava/util/Spliterators$DoubleArraySpliterator;->array:[D
+Ljava/util/Spliterators$DoubleArraySpliterator;->characteristics:I
+Ljava/util/Spliterators$DoubleArraySpliterator;->fence:I
+Ljava/util/Spliterators$DoubleArraySpliterator;->index:I
+Ljava/util/Spliterators$DoubleIteratorSpliterator;-><init>(Ljava/util/PrimitiveIterator$OfDouble;I)V
+Ljava/util/Spliterators$DoubleIteratorSpliterator;-><init>(Ljava/util/PrimitiveIterator$OfDouble;JI)V
+Ljava/util/Spliterators$DoubleIteratorSpliterator;->batch:I
+Ljava/util/Spliterators$DoubleIteratorSpliterator;->BATCH_UNIT:I
+Ljava/util/Spliterators$DoubleIteratorSpliterator;->characteristics:I
+Ljava/util/Spliterators$DoubleIteratorSpliterator;->est:J
+Ljava/util/Spliterators$DoubleIteratorSpliterator;->it:Ljava/util/PrimitiveIterator$OfDouble;
+Ljava/util/Spliterators$DoubleIteratorSpliterator;->MAX_BATCH:I
+Ljava/util/Spliterators$EmptySpliterator$OfDouble;-><init>()V
+Ljava/util/Spliterators$EmptySpliterator$OfInt;-><init>()V
+Ljava/util/Spliterators$EmptySpliterator$OfLong;-><init>()V
+Ljava/util/Spliterators$EmptySpliterator$OfRef;-><init>()V
+Ljava/util/Spliterators$EmptySpliterator;-><init>()V
+Ljava/util/Spliterators$EmptySpliterator;->characteristics()I
+Ljava/util/Spliterators$EmptySpliterator;->estimateSize()J
+Ljava/util/Spliterators$EmptySpliterator;->forEachRemaining(Ljava/lang/Object;)V
+Ljava/util/Spliterators$EmptySpliterator;->tryAdvance(Ljava/lang/Object;)Z
+Ljava/util/Spliterators$EmptySpliterator;->trySplit()Ljava/util/Spliterator;
+Ljava/util/Spliterators$IntArraySpliterator;-><init>([II)V
+Ljava/util/Spliterators$IntArraySpliterator;-><init>([IIII)V
+Ljava/util/Spliterators$IntArraySpliterator;->array:[I
+Ljava/util/Spliterators$IntArraySpliterator;->characteristics:I
+Ljava/util/Spliterators$IntArraySpliterator;->fence:I
+Ljava/util/Spliterators$IntArraySpliterator;->index:I
+Ljava/util/Spliterators$IntIteratorSpliterator;-><init>(Ljava/util/PrimitiveIterator$OfInt;I)V
+Ljava/util/Spliterators$IntIteratorSpliterator;-><init>(Ljava/util/PrimitiveIterator$OfInt;JI)V
+Ljava/util/Spliterators$IntIteratorSpliterator;->batch:I
+Ljava/util/Spliterators$IntIteratorSpliterator;->BATCH_UNIT:I
+Ljava/util/Spliterators$IntIteratorSpliterator;->characteristics:I
+Ljava/util/Spliterators$IntIteratorSpliterator;->est:J
+Ljava/util/Spliterators$IntIteratorSpliterator;->it:Ljava/util/PrimitiveIterator$OfInt;
+Ljava/util/Spliterators$IntIteratorSpliterator;->MAX_BATCH:I
+Ljava/util/Spliterators$IteratorSpliterator;-><init>(Ljava/util/Collection;I)V
+Ljava/util/Spliterators$IteratorSpliterator;-><init>(Ljava/util/Iterator;I)V
+Ljava/util/Spliterators$IteratorSpliterator;-><init>(Ljava/util/Iterator;JI)V
+Ljava/util/Spliterators$IteratorSpliterator;->batch:I
+Ljava/util/Spliterators$IteratorSpliterator;->BATCH_UNIT:I
+Ljava/util/Spliterators$IteratorSpliterator;->characteristics:I
+Ljava/util/Spliterators$IteratorSpliterator;->collection:Ljava/util/Collection;
+Ljava/util/Spliterators$IteratorSpliterator;->est:J
+Ljava/util/Spliterators$IteratorSpliterator;->it:Ljava/util/Iterator;
+Ljava/util/Spliterators$IteratorSpliterator;->MAX_BATCH:I
+Ljava/util/Spliterators$LongArraySpliterator;-><init>([JI)V
+Ljava/util/Spliterators$LongArraySpliterator;-><init>([JIII)V
+Ljava/util/Spliterators$LongArraySpliterator;->array:[J
+Ljava/util/Spliterators$LongArraySpliterator;->characteristics:I
+Ljava/util/Spliterators$LongArraySpliterator;->fence:I
+Ljava/util/Spliterators$LongArraySpliterator;->index:I
+Ljava/util/Spliterators$LongIteratorSpliterator;-><init>(Ljava/util/PrimitiveIterator$OfLong;I)V
+Ljava/util/Spliterators$LongIteratorSpliterator;-><init>(Ljava/util/PrimitiveIterator$OfLong;JI)V
+Ljava/util/Spliterators$LongIteratorSpliterator;->batch:I
+Ljava/util/Spliterators$LongIteratorSpliterator;->BATCH_UNIT:I
+Ljava/util/Spliterators$LongIteratorSpliterator;->characteristics:I
+Ljava/util/Spliterators$LongIteratorSpliterator;->est:J
+Ljava/util/Spliterators$LongIteratorSpliterator;->it:Ljava/util/PrimitiveIterator$OfLong;
+Ljava/util/Spliterators$LongIteratorSpliterator;->MAX_BATCH:I
+Ljava/util/Spliterators;-><init>()V
+Ljava/util/Spliterators;->checkFromToBounds(III)V
+Ljava/util/Spliterators;->EMPTY_DOUBLE_SPLITERATOR:Ljava/util/Spliterator$OfDouble;
+Ljava/util/Spliterators;->EMPTY_INT_SPLITERATOR:Ljava/util/Spliterator$OfInt;
+Ljava/util/Spliterators;->EMPTY_LONG_SPLITERATOR:Ljava/util/Spliterator$OfLong;
+Ljava/util/Spliterators;->EMPTY_SPLITERATOR:Ljava/util/Spliterator;
+Ljava/util/SplittableRandom$RandomDoublesSpliterator;-><init>(Ljava/util/SplittableRandom;JJDD)V
+Ljava/util/SplittableRandom$RandomDoublesSpliterator;->bound:D
+Ljava/util/SplittableRandom$RandomDoublesSpliterator;->fence:J
+Ljava/util/SplittableRandom$RandomDoublesSpliterator;->index:J
+Ljava/util/SplittableRandom$RandomDoublesSpliterator;->origin:D
+Ljava/util/SplittableRandom$RandomDoublesSpliterator;->rng:Ljava/util/SplittableRandom;
+Ljava/util/SplittableRandom$RandomIntsSpliterator;-><init>(Ljava/util/SplittableRandom;JJII)V
+Ljava/util/SplittableRandom$RandomIntsSpliterator;->bound:I
+Ljava/util/SplittableRandom$RandomIntsSpliterator;->fence:J
+Ljava/util/SplittableRandom$RandomIntsSpliterator;->index:J
+Ljava/util/SplittableRandom$RandomIntsSpliterator;->origin:I
+Ljava/util/SplittableRandom$RandomIntsSpliterator;->rng:Ljava/util/SplittableRandom;
+Ljava/util/SplittableRandom$RandomLongsSpliterator;-><init>(Ljava/util/SplittableRandom;JJJJ)V
+Ljava/util/SplittableRandom$RandomLongsSpliterator;->bound:J
+Ljava/util/SplittableRandom$RandomLongsSpliterator;->fence:J
+Ljava/util/SplittableRandom$RandomLongsSpliterator;->index:J
+Ljava/util/SplittableRandom$RandomLongsSpliterator;->origin:J
+Ljava/util/SplittableRandom$RandomLongsSpliterator;->rng:Ljava/util/SplittableRandom;
+Ljava/util/SplittableRandom;-><init>(JJ)V
+Ljava/util/SplittableRandom;->BAD_BOUND:Ljava/lang/String;
+Ljava/util/SplittableRandom;->BAD_RANGE:Ljava/lang/String;
+Ljava/util/SplittableRandom;->BAD_SIZE:Ljava/lang/String;
+Ljava/util/SplittableRandom;->defaultGen:Ljava/util/concurrent/atomic/AtomicLong;
+Ljava/util/SplittableRandom;->DOUBLE_UNIT:D
+Ljava/util/SplittableRandom;->gamma:J
+Ljava/util/SplittableRandom;->GOLDEN_GAMMA:J
+Ljava/util/SplittableRandom;->internalNextDouble(DD)D
+Ljava/util/SplittableRandom;->internalNextInt(II)I
+Ljava/util/SplittableRandom;->internalNextLong(JJ)J
+Ljava/util/SplittableRandom;->mix32(J)I
+Ljava/util/SplittableRandom;->mix64(J)J
+Ljava/util/SplittableRandom;->mixGamma(J)J
+Ljava/util/SplittableRandom;->nextSeed()J
+Ljava/util/SplittableRandom;->seed:J
+Ljava/util/stream/AbstractPipeline;-><init>(Ljava/util/function/Supplier;IZ)V
+Ljava/util/stream/AbstractPipeline;-><init>(Ljava/util/Spliterator;IZ)V
+Ljava/util/stream/AbstractPipeline;-><init>(Ljava/util/stream/AbstractPipeline;I)V
+Ljava/util/stream/AbstractPipeline;->combinedFlags:I
+Ljava/util/stream/AbstractPipeline;->copyInto(Ljava/util/stream/Sink;Ljava/util/Spliterator;)V
+Ljava/util/stream/AbstractPipeline;->copyIntoWithCancel(Ljava/util/stream/Sink;Ljava/util/Spliterator;)V
+Ljava/util/stream/AbstractPipeline;->depth:I
+Ljava/util/stream/AbstractPipeline;->evaluate(Ljava/util/Spliterator;ZLjava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/AbstractPipeline;->evaluate(Ljava/util/stream/TerminalOp;)Ljava/lang/Object;
+Ljava/util/stream/AbstractPipeline;->evaluateToArrayNode(Ljava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/AbstractPipeline;->evaluateToNode(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;ZLjava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/AbstractPipeline;->exactOutputSizeIfKnown(Ljava/util/Spliterator;)J
+Ljava/util/stream/AbstractPipeline;->forEachWithCancel(Ljava/util/Spliterator;Ljava/util/stream/Sink;)V
+Ljava/util/stream/AbstractPipeline;->getOutputShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/AbstractPipeline;->getSourceShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/AbstractPipeline;->getStreamAndOpFlags()I
+Ljava/util/stream/AbstractPipeline;->getStreamFlags()I
+Ljava/util/stream/AbstractPipeline;->isOrdered()Z
+Ljava/util/stream/AbstractPipeline;->lazySpliterator(Ljava/util/function/Supplier;)Ljava/util/Spliterator;
+Ljava/util/stream/AbstractPipeline;->linkedOrConsumed:Z
+Ljava/util/stream/AbstractPipeline;->makeNodeBuilder(JLjava/util/function/IntFunction;)Ljava/util/stream/Node$Builder;
+Ljava/util/stream/AbstractPipeline;->MSG_CONSUMED:Ljava/lang/String;
+Ljava/util/stream/AbstractPipeline;->MSG_STREAM_LINKED:Ljava/lang/String;
+Ljava/util/stream/AbstractPipeline;->nextStage:Ljava/util/stream/AbstractPipeline;
+Ljava/util/stream/AbstractPipeline;->opEvaluateParallel(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;Ljava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/AbstractPipeline;->opEvaluateParallelLazy(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;)Ljava/util/Spliterator;
+Ljava/util/stream/AbstractPipeline;->opIsStateful()Z
+Ljava/util/stream/AbstractPipeline;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+Ljava/util/stream/AbstractPipeline;->parallel:Z
+Ljava/util/stream/AbstractPipeline;->previousStage:Ljava/util/stream/AbstractPipeline;
+Ljava/util/stream/AbstractPipeline;->sourceAnyStateful:Z
+Ljava/util/stream/AbstractPipeline;->sourceCloseAction:Ljava/lang/Runnable;
+Ljava/util/stream/AbstractPipeline;->sourceOrOpFlags:I
+Ljava/util/stream/AbstractPipeline;->sourceSpliterator(I)Ljava/util/Spliterator;
+Ljava/util/stream/AbstractPipeline;->sourceSpliterator:Ljava/util/Spliterator;
+Ljava/util/stream/AbstractPipeline;->sourceStage:Ljava/util/stream/AbstractPipeline;
+Ljava/util/stream/AbstractPipeline;->sourceStageSpliterator()Ljava/util/Spliterator;
+Ljava/util/stream/AbstractPipeline;->sourceSupplier:Ljava/util/function/Supplier;
+Ljava/util/stream/AbstractPipeline;->wrap(Ljava/util/stream/PipelineHelper;Ljava/util/function/Supplier;Z)Ljava/util/Spliterator;
+Ljava/util/stream/AbstractPipeline;->wrapAndCopyInto(Ljava/util/stream/Sink;Ljava/util/Spliterator;)Ljava/util/stream/Sink;
+Ljava/util/stream/AbstractPipeline;->wrapSink(Ljava/util/stream/Sink;)Ljava/util/stream/Sink;
+Ljava/util/stream/AbstractPipeline;->wrapSpliterator(Ljava/util/Spliterator;)Ljava/util/Spliterator;
+Ljava/util/stream/AbstractSpinedBuffer;-><init>()V
+Ljava/util/stream/AbstractSpinedBuffer;-><init>(I)V
+Ljava/util/stream/AbstractSpinedBuffer;->chunkSize(I)I
+Ljava/util/stream/AbstractSpinedBuffer;->clear()V
+Ljava/util/stream/AbstractSpinedBuffer;->count()J
+Ljava/util/stream/AbstractSpinedBuffer;->elementIndex:I
+Ljava/util/stream/AbstractSpinedBuffer;->initialChunkPower:I
+Ljava/util/stream/AbstractSpinedBuffer;->isEmpty()Z
+Ljava/util/stream/AbstractSpinedBuffer;->MAX_CHUNK_POWER:I
+Ljava/util/stream/AbstractSpinedBuffer;->MIN_CHUNK_POWER:I
+Ljava/util/stream/AbstractSpinedBuffer;->MIN_CHUNK_SIZE:I
+Ljava/util/stream/AbstractSpinedBuffer;->MIN_SPINE_SIZE:I
+Ljava/util/stream/AbstractSpinedBuffer;->priorElementCount:[J
+Ljava/util/stream/AbstractSpinedBuffer;->spineIndex:I
+Ljava/util/stream/Collectors$CollectorImpl;-><init>(Ljava/util/function/Supplier;Ljava/util/function/BiConsumer;Ljava/util/function/BinaryOperator;Ljava/util/function/Function;Ljava/util/Set;)V
+Ljava/util/stream/Collectors$CollectorImpl;-><init>(Ljava/util/function/Supplier;Ljava/util/function/BiConsumer;Ljava/util/function/BinaryOperator;Ljava/util/Set;)V
+Ljava/util/stream/Collectors$CollectorImpl;->accumulator:Ljava/util/function/BiConsumer;
+Ljava/util/stream/Collectors$CollectorImpl;->characteristics:Ljava/util/Set;
+Ljava/util/stream/Collectors$CollectorImpl;->combiner:Ljava/util/function/BinaryOperator;
+Ljava/util/stream/Collectors$CollectorImpl;->finisher:Ljava/util/function/Function;
+Ljava/util/stream/Collectors$CollectorImpl;->supplier:Ljava/util/function/Supplier;
+Ljava/util/stream/Collectors$Partition;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
+Ljava/util/stream/Collectors$Partition;->forFalse:Ljava/lang/Object;
+Ljava/util/stream/Collectors$Partition;->forTrue:Ljava/lang/Object;
+Ljava/util/stream/Collectors;-><init>()V
+Ljava/util/stream/Collectors;->boxSupplier(Ljava/lang/Object;)Ljava/util/function/Supplier;
+Ljava/util/stream/Collectors;->castingIdentity()Ljava/util/function/Function;
+Ljava/util/stream/Collectors;->CH_CONCURRENT_ID:Ljava/util/Set;
+Ljava/util/stream/Collectors;->CH_CONCURRENT_NOID:Ljava/util/Set;
+Ljava/util/stream/Collectors;->CH_ID:Ljava/util/Set;
+Ljava/util/stream/Collectors;->CH_NOID:Ljava/util/Set;
+Ljava/util/stream/Collectors;->CH_UNORDERED_ID:Ljava/util/Set;
+Ljava/util/stream/Collectors;->computeFinalSum([D)D
+Ljava/util/stream/Collectors;->mapMerger(Ljava/util/function/BinaryOperator;)Ljava/util/function/BinaryOperator;
+Ljava/util/stream/Collectors;->sumWithCompensation([DD)[D
+Ljava/util/stream/Collectors;->throwingMerger()Ljava/util/function/BinaryOperator;
+Ljava/util/stream/DoublePipeline$Head;-><init>(Ljava/util/function/Supplier;IZ)V
+Ljava/util/stream/DoublePipeline$Head;-><init>(Ljava/util/Spliterator;IZ)V
+Ljava/util/stream/DoublePipeline$Head;->opIsStateful()Z
+Ljava/util/stream/DoublePipeline$Head;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+Ljava/util/stream/DoublePipeline$StatefulOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+Ljava/util/stream/DoublePipeline$StatefulOp;->opEvaluateParallel(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;Ljava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/DoublePipeline$StatefulOp;->opIsStateful()Z
+Ljava/util/stream/DoublePipeline$StatelessOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+Ljava/util/stream/DoublePipeline$StatelessOp;->opIsStateful()Z
+Ljava/util/stream/DoublePipeline;-><init>(Ljava/util/function/Supplier;IZ)V
+Ljava/util/stream/DoublePipeline;-><init>(Ljava/util/Spliterator;IZ)V
+Ljava/util/stream/DoublePipeline;-><init>(Ljava/util/stream/AbstractPipeline;I)V
+Ljava/util/stream/DoublePipeline;->adapt(Ljava/util/Spliterator;)Ljava/util/Spliterator$OfDouble;
+Ljava/util/stream/DoublePipeline;->adapt(Ljava/util/stream/Sink;)Ljava/util/function/DoubleConsumer;
+Ljava/util/stream/DoublePipeline;->evaluateToNode(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;ZLjava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/DoublePipeline;->forEachWithCancel(Ljava/util/Spliterator;Ljava/util/stream/Sink;)V
+Ljava/util/stream/DoublePipeline;->getOutputShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/DoublePipeline;->lazySpliterator(Ljava/util/function/Supplier;)Ljava/util/Spliterator$OfDouble;
+Ljava/util/stream/DoublePipeline;->makeNodeBuilder(JLjava/util/function/IntFunction;)Ljava/util/stream/Node$Builder;
+Ljava/util/stream/DoublePipeline;->wrap(Ljava/util/stream/PipelineHelper;Ljava/util/function/Supplier;Z)Ljava/util/Spliterator;
+Ljava/util/stream/IntPipeline$Head;-><init>(Ljava/util/function/Supplier;IZ)V
+Ljava/util/stream/IntPipeline$Head;-><init>(Ljava/util/Spliterator;IZ)V
+Ljava/util/stream/IntPipeline$Head;->opIsStateful()Z
+Ljava/util/stream/IntPipeline$Head;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+Ljava/util/stream/IntPipeline$StatefulOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+Ljava/util/stream/IntPipeline$StatefulOp;->opEvaluateParallel(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;Ljava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/IntPipeline$StatefulOp;->opIsStateful()Z
+Ljava/util/stream/IntPipeline$StatelessOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+Ljava/util/stream/IntPipeline$StatelessOp;->opIsStateful()Z
+Ljava/util/stream/IntPipeline;-><init>(Ljava/util/function/Supplier;IZ)V
+Ljava/util/stream/IntPipeline;-><init>(Ljava/util/Spliterator;IZ)V
+Ljava/util/stream/IntPipeline;-><init>(Ljava/util/stream/AbstractPipeline;I)V
+Ljava/util/stream/IntPipeline;->adapt(Ljava/util/Spliterator;)Ljava/util/Spliterator$OfInt;
+Ljava/util/stream/IntPipeline;->adapt(Ljava/util/stream/Sink;)Ljava/util/function/IntConsumer;
+Ljava/util/stream/IntPipeline;->evaluateToNode(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;ZLjava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/IntPipeline;->forEachWithCancel(Ljava/util/Spliterator;Ljava/util/stream/Sink;)V
+Ljava/util/stream/IntPipeline;->getOutputShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/IntPipeline;->lazySpliterator(Ljava/util/function/Supplier;)Ljava/util/Spliterator$OfInt;
+Ljava/util/stream/IntPipeline;->makeNodeBuilder(JLjava/util/function/IntFunction;)Ljava/util/stream/Node$Builder;
+Ljava/util/stream/IntPipeline;->wrap(Ljava/util/stream/PipelineHelper;Ljava/util/function/Supplier;Z)Ljava/util/Spliterator;
+Ljava/util/stream/LongPipeline$Head;-><init>(Ljava/util/function/Supplier;IZ)V
+Ljava/util/stream/LongPipeline$Head;-><init>(Ljava/util/Spliterator;IZ)V
+Ljava/util/stream/LongPipeline$Head;->opIsStateful()Z
+Ljava/util/stream/LongPipeline$Head;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+Ljava/util/stream/LongPipeline$StatefulOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+Ljava/util/stream/LongPipeline$StatefulOp;->opEvaluateParallel(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;Ljava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/LongPipeline$StatefulOp;->opIsStateful()Z
+Ljava/util/stream/LongPipeline$StatelessOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+Ljava/util/stream/LongPipeline$StatelessOp;->opIsStateful()Z
+Ljava/util/stream/LongPipeline;-><init>(Ljava/util/function/Supplier;IZ)V
+Ljava/util/stream/LongPipeline;-><init>(Ljava/util/Spliterator;IZ)V
+Ljava/util/stream/LongPipeline;-><init>(Ljava/util/stream/AbstractPipeline;I)V
+Ljava/util/stream/LongPipeline;->adapt(Ljava/util/Spliterator;)Ljava/util/Spliterator$OfLong;
+Ljava/util/stream/LongPipeline;->adapt(Ljava/util/stream/Sink;)Ljava/util/function/LongConsumer;
+Ljava/util/stream/LongPipeline;->evaluateToNode(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;ZLjava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/LongPipeline;->forEachWithCancel(Ljava/util/Spliterator;Ljava/util/stream/Sink;)V
+Ljava/util/stream/LongPipeline;->getOutputShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/LongPipeline;->lazySpliterator(Ljava/util/function/Supplier;)Ljava/util/Spliterator$OfLong;
+Ljava/util/stream/LongPipeline;->makeNodeBuilder(JLjava/util/function/IntFunction;)Ljava/util/stream/Node$Builder;
+Ljava/util/stream/LongPipeline;->wrap(Ljava/util/stream/PipelineHelper;Ljava/util/function/Supplier;Z)Ljava/util/Spliterator;
+Ljava/util/stream/Node$Builder$OfDouble;->build()Ljava/util/stream/Node$OfDouble;
+Ljava/util/stream/Node$Builder$OfInt;->build()Ljava/util/stream/Node$OfInt;
+Ljava/util/stream/Node$Builder$OfLong;->build()Ljava/util/stream/Node$OfLong;
+Ljava/util/stream/Node$Builder;->build()Ljava/util/stream/Node;
+Ljava/util/stream/Node$OfDouble;->copyInto([Ljava/lang/Double;I)V
+Ljava/util/stream/Node$OfDouble;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/Node$OfDouble;->getShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/Node$OfDouble;->newArray(I)[D
+Ljava/util/stream/Node$OfDouble;->truncate(JJLjava/util/function/IntFunction;)Ljava/util/stream/Node$OfDouble;
+Ljava/util/stream/Node$OfInt;->copyInto([Ljava/lang/Integer;I)V
+Ljava/util/stream/Node$OfInt;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/Node$OfInt;->getShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/Node$OfInt;->newArray(I)[I
+Ljava/util/stream/Node$OfInt;->truncate(JJLjava/util/function/IntFunction;)Ljava/util/stream/Node$OfInt;
+Ljava/util/stream/Node$OfLong;->copyInto([Ljava/lang/Long;I)V
+Ljava/util/stream/Node$OfLong;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/Node$OfLong;->getShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/Node$OfLong;->newArray(I)[J
+Ljava/util/stream/Node$OfLong;->truncate(JJLjava/util/function/IntFunction;)Ljava/util/stream/Node$OfLong;
+Ljava/util/stream/Node$OfPrimitive;->asArray(Ljava/util/function/IntFunction;)[Ljava/lang/Object;
+Ljava/util/stream/Node$OfPrimitive;->asPrimitiveArray()Ljava/lang/Object;
+Ljava/util/stream/Node$OfPrimitive;->copyInto(Ljava/lang/Object;I)V
+Ljava/util/stream/Node$OfPrimitive;->forEach(Ljava/lang/Object;)V
+Ljava/util/stream/Node$OfPrimitive;->getChild(I)Ljava/util/stream/Node$OfPrimitive;
+Ljava/util/stream/Node$OfPrimitive;->newArray(I)Ljava/lang/Object;
+Ljava/util/stream/Node$OfPrimitive;->spliterator()Ljava/util/Spliterator$OfPrimitive;
+Ljava/util/stream/Node$OfPrimitive;->truncate(JJLjava/util/function/IntFunction;)Ljava/util/stream/Node$OfPrimitive;
+Ljava/util/stream/Node;->asArray(Ljava/util/function/IntFunction;)[Ljava/lang/Object;
+Ljava/util/stream/Node;->copyInto([Ljava/lang/Object;I)V
+Ljava/util/stream/Node;->count()J
+Ljava/util/stream/Node;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/Node;->getChild(I)Ljava/util/stream/Node;
+Ljava/util/stream/Node;->getChildCount()I
+Ljava/util/stream/Node;->getShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/Node;->spliterator()Ljava/util/Spliterator;
+Ljava/util/stream/Node;->truncate(JJLjava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/PipelineHelper;-><init>()V
+Ljava/util/stream/PipelineHelper;->copyInto(Ljava/util/stream/Sink;Ljava/util/Spliterator;)V
+Ljava/util/stream/PipelineHelper;->copyIntoWithCancel(Ljava/util/stream/Sink;Ljava/util/Spliterator;)V
+Ljava/util/stream/PipelineHelper;->evaluate(Ljava/util/Spliterator;ZLjava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/PipelineHelper;->exactOutputSizeIfKnown(Ljava/util/Spliterator;)J
+Ljava/util/stream/PipelineHelper;->getSourceShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/PipelineHelper;->getStreamAndOpFlags()I
+Ljava/util/stream/PipelineHelper;->makeNodeBuilder(JLjava/util/function/IntFunction;)Ljava/util/stream/Node$Builder;
+Ljava/util/stream/PipelineHelper;->wrapAndCopyInto(Ljava/util/stream/Sink;Ljava/util/Spliterator;)Ljava/util/stream/Sink;
+Ljava/util/stream/PipelineHelper;->wrapSink(Ljava/util/stream/Sink;)Ljava/util/stream/Sink;
+Ljava/util/stream/PipelineHelper;->wrapSpliterator(Ljava/util/Spliterator;)Ljava/util/Spliterator;
+Ljava/util/stream/ReferencePipeline$Head;-><init>(Ljava/util/function/Supplier;IZ)V
+Ljava/util/stream/ReferencePipeline$Head;-><init>(Ljava/util/Spliterator;IZ)V
+Ljava/util/stream/ReferencePipeline$Head;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/ReferencePipeline$Head;->forEachOrdered(Ljava/util/function/Consumer;)V
+Ljava/util/stream/ReferencePipeline$Head;->opIsStateful()Z
+Ljava/util/stream/ReferencePipeline$Head;->opWrapSink(ILjava/util/stream/Sink;)Ljava/util/stream/Sink;
+Ljava/util/stream/ReferencePipeline$StatefulOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+Ljava/util/stream/ReferencePipeline$StatefulOp;->opEvaluateParallel(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;Ljava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/ReferencePipeline$StatefulOp;->opIsStateful()Z
+Ljava/util/stream/ReferencePipeline$StatelessOp;-><init>(Ljava/util/stream/AbstractPipeline;Ljava/util/stream/StreamShape;I)V
+Ljava/util/stream/ReferencePipeline$StatelessOp;->opIsStateful()Z
+Ljava/util/stream/ReferencePipeline;-><init>(Ljava/util/function/Supplier;IZ)V
+Ljava/util/stream/ReferencePipeline;-><init>(Ljava/util/Spliterator;IZ)V
+Ljava/util/stream/ReferencePipeline;-><init>(Ljava/util/stream/AbstractPipeline;I)V
+Ljava/util/stream/ReferencePipeline;->allMatch(Ljava/util/function/Predicate;)Z
+Ljava/util/stream/ReferencePipeline;->anyMatch(Ljava/util/function/Predicate;)Z
+Ljava/util/stream/ReferencePipeline;->collect(Ljava/util/function/Supplier;Ljava/util/function/BiConsumer;Ljava/util/function/BiConsumer;)Ljava/lang/Object;
+Ljava/util/stream/ReferencePipeline;->collect(Ljava/util/stream/Collector;)Ljava/lang/Object;
+Ljava/util/stream/ReferencePipeline;->evaluateToNode(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;ZLjava/util/function/IntFunction;)Ljava/util/stream/Node;
+Ljava/util/stream/ReferencePipeline;->filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
+Ljava/util/stream/ReferencePipeline;->flatMap(Ljava/util/function/Function;)Ljava/util/stream/Stream;
+Ljava/util/stream/ReferencePipeline;->flatMapToDouble(Ljava/util/function/Function;)Ljava/util/stream/DoubleStream;
+Ljava/util/stream/ReferencePipeline;->flatMapToInt(Ljava/util/function/Function;)Ljava/util/stream/IntStream;
+Ljava/util/stream/ReferencePipeline;->flatMapToLong(Ljava/util/function/Function;)Ljava/util/stream/LongStream;
+Ljava/util/stream/ReferencePipeline;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/ReferencePipeline;->forEachOrdered(Ljava/util/function/Consumer;)V
+Ljava/util/stream/ReferencePipeline;->forEachWithCancel(Ljava/util/Spliterator;Ljava/util/stream/Sink;)V
+Ljava/util/stream/ReferencePipeline;->getOutputShape()Ljava/util/stream/StreamShape;
+Ljava/util/stream/ReferencePipeline;->lazySpliterator(Ljava/util/function/Supplier;)Ljava/util/Spliterator;
+Ljava/util/stream/ReferencePipeline;->makeNodeBuilder(JLjava/util/function/IntFunction;)Ljava/util/stream/Node$Builder;
+Ljava/util/stream/ReferencePipeline;->map(Ljava/util/function/Function;)Ljava/util/stream/Stream;
+Ljava/util/stream/ReferencePipeline;->mapToDouble(Ljava/util/function/ToDoubleFunction;)Ljava/util/stream/DoubleStream;
+Ljava/util/stream/ReferencePipeline;->mapToInt(Ljava/util/function/ToIntFunction;)Ljava/util/stream/IntStream;
+Ljava/util/stream/ReferencePipeline;->mapToLong(Ljava/util/function/ToLongFunction;)Ljava/util/stream/LongStream;
+Ljava/util/stream/ReferencePipeline;->max(Ljava/util/Comparator;)Ljava/util/Optional;
+Ljava/util/stream/ReferencePipeline;->min(Ljava/util/Comparator;)Ljava/util/Optional;
+Ljava/util/stream/ReferencePipeline;->noneMatch(Ljava/util/function/Predicate;)Z
+Ljava/util/stream/ReferencePipeline;->peek(Ljava/util/function/Consumer;)Ljava/util/stream/Stream;
+Ljava/util/stream/ReferencePipeline;->reduce(Ljava/lang/Object;Ljava/util/function/BiFunction;Ljava/util/function/BinaryOperator;)Ljava/lang/Object;
+Ljava/util/stream/ReferencePipeline;->reduce(Ljava/lang/Object;Ljava/util/function/BinaryOperator;)Ljava/lang/Object;
+Ljava/util/stream/ReferencePipeline;->reduce(Ljava/util/function/BinaryOperator;)Ljava/util/Optional;
+Ljava/util/stream/ReferencePipeline;->sorted(Ljava/util/Comparator;)Ljava/util/stream/Stream;
+Ljava/util/stream/ReferencePipeline;->wrap(Ljava/util/stream/PipelineHelper;Ljava/util/function/Supplier;Z)Ljava/util/Spliterator;
+Ljava/util/stream/Sink$ChainedDouble;-><init>(Ljava/util/stream/Sink;)V
+Ljava/util/stream/Sink$ChainedDouble;->begin(J)V
+Ljava/util/stream/Sink$ChainedDouble;->cancellationRequested()Z
+Ljava/util/stream/Sink$ChainedDouble;->downstream:Ljava/util/stream/Sink;
+Ljava/util/stream/Sink$ChainedDouble;->end()V
+Ljava/util/stream/Sink$ChainedInt;-><init>(Ljava/util/stream/Sink;)V
+Ljava/util/stream/Sink$ChainedInt;->begin(J)V
+Ljava/util/stream/Sink$ChainedInt;->cancellationRequested()Z
+Ljava/util/stream/Sink$ChainedInt;->downstream:Ljava/util/stream/Sink;
+Ljava/util/stream/Sink$ChainedInt;->end()V
+Ljava/util/stream/Sink$ChainedLong;-><init>(Ljava/util/stream/Sink;)V
+Ljava/util/stream/Sink$ChainedLong;->begin(J)V
+Ljava/util/stream/Sink$ChainedLong;->cancellationRequested()Z
+Ljava/util/stream/Sink$ChainedLong;->downstream:Ljava/util/stream/Sink;
+Ljava/util/stream/Sink$ChainedLong;->end()V
+Ljava/util/stream/Sink$ChainedReference;-><init>(Ljava/util/stream/Sink;)V
+Ljava/util/stream/Sink$ChainedReference;->begin(J)V
+Ljava/util/stream/Sink$ChainedReference;->cancellationRequested()Z
+Ljava/util/stream/Sink$ChainedReference;->downstream:Ljava/util/stream/Sink;
+Ljava/util/stream/Sink$ChainedReference;->end()V
+Ljava/util/stream/Sink$OfDouble;->accept(Ljava/lang/Double;)V
+Ljava/util/stream/Sink$OfInt;->accept(Ljava/lang/Integer;)V
+Ljava/util/stream/Sink$OfLong;->accept(Ljava/lang/Long;)V
+Ljava/util/stream/Sink;->accept(D)V
+Ljava/util/stream/Sink;->accept(I)V
+Ljava/util/stream/Sink;->accept(J)V
+Ljava/util/stream/Sink;->begin(J)V
+Ljava/util/stream/Sink;->cancellationRequested()Z
+Ljava/util/stream/Sink;->end()V
+Ljava/util/stream/SpinedBuffer$OfDouble;-><init>()V
+Ljava/util/stream/SpinedBuffer$OfDouble;-><init>(I)V
+Ljava/util/stream/SpinedBuffer$OfDouble;->arrayForEach([DIILjava/util/function/DoubleConsumer;)V
+Ljava/util/stream/SpinedBuffer$OfDouble;->arrayLength([D)I
+Ljava/util/stream/SpinedBuffer$OfDouble;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/SpinedBuffer$OfDouble;->get(J)D
+Ljava/util/stream/SpinedBuffer$OfDouble;->newArray(I)[D
+Ljava/util/stream/SpinedBuffer$OfDouble;->newArrayArray(I)[[D
+Ljava/util/stream/SpinedBuffer$OfInt;-><init>()V
+Ljava/util/stream/SpinedBuffer$OfInt;-><init>(I)V
+Ljava/util/stream/SpinedBuffer$OfInt;->arrayForEach([IIILjava/util/function/IntConsumer;)V
+Ljava/util/stream/SpinedBuffer$OfInt;->arrayLength([I)I
+Ljava/util/stream/SpinedBuffer$OfInt;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/SpinedBuffer$OfInt;->get(J)I
+Ljava/util/stream/SpinedBuffer$OfInt;->newArray(I)[I
+Ljava/util/stream/SpinedBuffer$OfInt;->newArrayArray(I)[[I
+Ljava/util/stream/SpinedBuffer$OfLong;-><init>()V
+Ljava/util/stream/SpinedBuffer$OfLong;-><init>(I)V
+Ljava/util/stream/SpinedBuffer$OfLong;->arrayForEach([JIILjava/util/function/LongConsumer;)V
+Ljava/util/stream/SpinedBuffer$OfLong;->arrayLength([J)I
+Ljava/util/stream/SpinedBuffer$OfLong;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/SpinedBuffer$OfLong;->get(J)J
+Ljava/util/stream/SpinedBuffer$OfLong;->newArray(I)[J
+Ljava/util/stream/SpinedBuffer$OfLong;->newArrayArray(I)[[J
+Ljava/util/stream/SpinedBuffer$OfPrimitive$BaseSpliterator;->arrayForOne(Ljava/lang/Object;ILjava/lang/Object;)V
+Ljava/util/stream/SpinedBuffer$OfPrimitive$BaseSpliterator;->arraySpliterator(Ljava/lang/Object;II)Ljava/util/Spliterator$OfPrimitive;
+Ljava/util/stream/SpinedBuffer$OfPrimitive$BaseSpliterator;->lastSpineElementFence:I
+Ljava/util/stream/SpinedBuffer$OfPrimitive$BaseSpliterator;->lastSpineIndex:I
+Ljava/util/stream/SpinedBuffer$OfPrimitive$BaseSpliterator;->newSpliterator(IIII)Ljava/util/Spliterator$OfPrimitive;
+Ljava/util/stream/SpinedBuffer$OfPrimitive$BaseSpliterator;->splChunk:Ljava/lang/Object;
+Ljava/util/stream/SpinedBuffer$OfPrimitive$BaseSpliterator;->splElementIndex:I
+Ljava/util/stream/SpinedBuffer$OfPrimitive$BaseSpliterator;->splSpineIndex:I
+Ljava/util/stream/SpinedBuffer$OfPrimitive;-><init>()V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;-><init>(I)V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->arrayForEach(Ljava/lang/Object;IILjava/lang/Object;)V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->arrayLength(Ljava/lang/Object;)I
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->asPrimitiveArray()Ljava/lang/Object;
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->capacity()J
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->chunkFor(J)I
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->clear()V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->copyInto(Ljava/lang/Object;I)V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->curChunk:Ljava/lang/Object;
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->ensureCapacity(J)V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->forEach(Ljava/lang/Object;)V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->increaseCapacity()V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->inflateSpine()V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->newArray(I)Ljava/lang/Object;
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->newArrayArray(I)[Ljava/lang/Object;
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->preAccept()V
+Ljava/util/stream/SpinedBuffer$OfPrimitive;->spine:[Ljava/lang/Object;
+Ljava/util/stream/SpinedBuffer;-><init>()V
+Ljava/util/stream/SpinedBuffer;-><init>(I)V
+Ljava/util/stream/SpinedBuffer;->accept(Ljava/lang/Object;)V
+Ljava/util/stream/SpinedBuffer;->asArray(Ljava/util/function/IntFunction;)[Ljava/lang/Object;
+Ljava/util/stream/SpinedBuffer;->capacity()J
+Ljava/util/stream/SpinedBuffer;->clear()V
+Ljava/util/stream/SpinedBuffer;->copyInto([Ljava/lang/Object;I)V
+Ljava/util/stream/SpinedBuffer;->curChunk:[Ljava/lang/Object;
+Ljava/util/stream/SpinedBuffer;->ensureCapacity(J)V
+Ljava/util/stream/SpinedBuffer;->forEach(Ljava/util/function/Consumer;)V
+Ljava/util/stream/SpinedBuffer;->get(J)Ljava/lang/Object;
+Ljava/util/stream/SpinedBuffer;->increaseCapacity()V
+Ljava/util/stream/SpinedBuffer;->inflateSpine()V
+Ljava/util/stream/SpinedBuffer;->spine:[[Ljava/lang/Object;
+Ljava/util/stream/SpinedBuffer;->SPLITERATOR_CHARACTERISTICS:I
+Ljava/util/stream/StreamOpFlag$MaskBuilder;-><init>(Ljava/util/Map;)V
+Ljava/util/stream/StreamOpFlag$MaskBuilder;->build()Ljava/util/Map;
+Ljava/util/stream/StreamOpFlag$MaskBuilder;->clear(Ljava/util/stream/StreamOpFlag$Type;)Ljava/util/stream/StreamOpFlag$MaskBuilder;
+Ljava/util/stream/StreamOpFlag$MaskBuilder;->map:Ljava/util/Map;
+Ljava/util/stream/StreamOpFlag$MaskBuilder;->mask(Ljava/util/stream/StreamOpFlag$Type;Ljava/lang/Integer;)Ljava/util/stream/StreamOpFlag$MaskBuilder;
+Ljava/util/stream/StreamOpFlag$MaskBuilder;->set(Ljava/util/stream/StreamOpFlag$Type;)Ljava/util/stream/StreamOpFlag$MaskBuilder;
+Ljava/util/stream/StreamOpFlag$MaskBuilder;->setAndClear(Ljava/util/stream/StreamOpFlag$Type;)Ljava/util/stream/StreamOpFlag$MaskBuilder;
+Ljava/util/stream/StreamOpFlag$Type;->OP:Ljava/util/stream/StreamOpFlag$Type;
+Ljava/util/stream/StreamOpFlag$Type;->SPLITERATOR:Ljava/util/stream/StreamOpFlag$Type;
+Ljava/util/stream/StreamOpFlag$Type;->STREAM:Ljava/util/stream/StreamOpFlag$Type;
+Ljava/util/stream/StreamOpFlag$Type;->TERMINAL_OP:Ljava/util/stream/StreamOpFlag$Type;
+Ljava/util/stream/StreamOpFlag$Type;->UPSTREAM_TERMINAL_OP:Ljava/util/stream/StreamOpFlag$Type;
+Ljava/util/stream/StreamOpFlag$Type;->valueOf(Ljava/lang/String;)Ljava/util/stream/StreamOpFlag$Type;
+Ljava/util/stream/StreamOpFlag$Type;->values()[Ljava/util/stream/StreamOpFlag$Type;
+Ljava/util/stream/StreamOpFlag;->bitPosition:I
+Ljava/util/stream/StreamOpFlag;->canSet(Ljava/util/stream/StreamOpFlag$Type;)Z
+Ljava/util/stream/StreamOpFlag;->clear()I
+Ljava/util/stream/StreamOpFlag;->clear:I
+Ljava/util/stream/StreamOpFlag;->CLEAR_BITS:I
+Ljava/util/stream/StreamOpFlag;->combineOpFlags(II)I
+Ljava/util/stream/StreamOpFlag;->createFlagMask()I
+Ljava/util/stream/StreamOpFlag;->createMask(Ljava/util/stream/StreamOpFlag$Type;)I
+Ljava/util/stream/StreamOpFlag;->DISTINCT:Ljava/util/stream/StreamOpFlag;
+Ljava/util/stream/StreamOpFlag;->FLAG_MASK:I
+Ljava/util/stream/StreamOpFlag;->FLAG_MASK_IS:I
+Ljava/util/stream/StreamOpFlag;->FLAG_MASK_NOT:I
+Ljava/util/stream/StreamOpFlag;->fromCharacteristics(I)I
+Ljava/util/stream/StreamOpFlag;->fromCharacteristics(Ljava/util/Spliterator;)I
+Ljava/util/stream/StreamOpFlag;->getMask(I)I
+Ljava/util/stream/StreamOpFlag;->INITIAL_OPS_VALUE:I
+Ljava/util/stream/StreamOpFlag;->isCleared(I)Z
+Ljava/util/stream/StreamOpFlag;->isKnown(I)Z
+Ljava/util/stream/StreamOpFlag;->isPreserved(I)Z
+Ljava/util/stream/StreamOpFlag;->isStreamFlag()Z
+Ljava/util/stream/StreamOpFlag;->IS_DISTINCT:I
+Ljava/util/stream/StreamOpFlag;->IS_ORDERED:I
+Ljava/util/stream/StreamOpFlag;->IS_SHORT_CIRCUIT:I
+Ljava/util/stream/StreamOpFlag;->IS_SIZED:I
+Ljava/util/stream/StreamOpFlag;->IS_SORTED:I
+Ljava/util/stream/StreamOpFlag;->maskTable:Ljava/util/Map;
+Ljava/util/stream/StreamOpFlag;->NOT_DISTINCT:I
+Ljava/util/stream/StreamOpFlag;->NOT_ORDERED:I
+Ljava/util/stream/StreamOpFlag;->NOT_SIZED:I
+Ljava/util/stream/StreamOpFlag;->NOT_SORTED:I
+Ljava/util/stream/StreamOpFlag;->OP_MASK:I
+Ljava/util/stream/StreamOpFlag;->ORDERED:Ljava/util/stream/StreamOpFlag;
+Ljava/util/stream/StreamOpFlag;->preserve:I
+Ljava/util/stream/StreamOpFlag;->PRESERVE_BITS:I
+Ljava/util/stream/StreamOpFlag;->set()I
+Ljava/util/stream/StreamOpFlag;->set(Ljava/util/stream/StreamOpFlag$Type;)Ljava/util/stream/StreamOpFlag$MaskBuilder;
+Ljava/util/stream/StreamOpFlag;->set:I
+Ljava/util/stream/StreamOpFlag;->SET_BITS:I
+Ljava/util/stream/StreamOpFlag;->SHORT_CIRCUIT:Ljava/util/stream/StreamOpFlag;
+Ljava/util/stream/StreamOpFlag;->SIZED:Ljava/util/stream/StreamOpFlag;
+Ljava/util/stream/StreamOpFlag;->SORTED:Ljava/util/stream/StreamOpFlag;
+Ljava/util/stream/StreamOpFlag;->SPLITERATOR_CHARACTERISTICS_MASK:I
+Ljava/util/stream/StreamOpFlag;->STREAM_MASK:I
+Ljava/util/stream/StreamOpFlag;->TERMINAL_OP_MASK:I
+Ljava/util/stream/StreamOpFlag;->toCharacteristics(I)I
+Ljava/util/stream/StreamOpFlag;->toStreamFlags(I)I
+Ljava/util/stream/StreamOpFlag;->UPSTREAM_TERMINAL_OP_MASK:I
+Ljava/util/stream/StreamOpFlag;->valueOf(Ljava/lang/String;)Ljava/util/stream/StreamOpFlag;
+Ljava/util/stream/StreamOpFlag;->values()[Ljava/util/stream/StreamOpFlag;
+Ljava/util/stream/StreamShape;->DOUBLE_VALUE:Ljava/util/stream/StreamShape;
+Ljava/util/stream/StreamShape;->INT_VALUE:Ljava/util/stream/StreamShape;
+Ljava/util/stream/StreamShape;->LONG_VALUE:Ljava/util/stream/StreamShape;
+Ljava/util/stream/StreamShape;->REFERENCE:Ljava/util/stream/StreamShape;
+Ljava/util/stream/StreamShape;->valueOf(Ljava/lang/String;)Ljava/util/stream/StreamShape;
+Ljava/util/stream/StreamShape;->values()[Ljava/util/stream/StreamShape;
+Ljava/util/stream/StreamSupport;-><init>()V
+Ljava/util/stream/TerminalOp;->evaluateParallel(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;)Ljava/lang/Object;
+Ljava/util/stream/TerminalOp;->evaluateSequential(Ljava/util/stream/PipelineHelper;Ljava/util/Spliterator;)Ljava/lang/Object;
+Ljava/util/stream/TerminalOp;->getOpFlags()I
+Ljava/util/stream/TerminalOp;->inputShape()Ljava/util/stream/StreamShape;
+Ljava/util/StringJoiner;->delimiter:Ljava/lang/String;
+Ljava/util/StringJoiner;->emptyValue:Ljava/lang/String;
+Ljava/util/StringJoiner;->prefix:Ljava/lang/String;
+Ljava/util/StringJoiner;->prepareBuilder()Ljava/lang/StringBuilder;
+Ljava/util/StringJoiner;->suffix:Ljava/lang/String;
+Ljava/util/StringJoiner;->value:Ljava/lang/StringBuilder;
+Ljava/util/StringTokenizer;->currentPosition:I
+Ljava/util/StringTokenizer;->delimiterCodePoints:[I
+Ljava/util/StringTokenizer;->delimiters:Ljava/lang/String;
+Ljava/util/StringTokenizer;->delimsChanged:Z
+Ljava/util/StringTokenizer;->hasSurrogates:Z
+Ljava/util/StringTokenizer;->isDelimiter(I)Z
+Ljava/util/StringTokenizer;->maxDelimCodePoint:I
+Ljava/util/StringTokenizer;->maxPosition:I
+Ljava/util/StringTokenizer;->newPosition:I
+Ljava/util/StringTokenizer;->retDelims:Z
+Ljava/util/StringTokenizer;->scanToken(I)I
+Ljava/util/StringTokenizer;->setMaxDelimCodePoint()V
+Ljava/util/StringTokenizer;->skipDelimiters(I)I
+Ljava/util/StringTokenizer;->str:Ljava/lang/String;
+Ljava/util/TaskQueue;-><init>()V
+Ljava/util/TaskQueue;->add(Ljava/util/TimerTask;)V
+Ljava/util/TaskQueue;->clear()V
+Ljava/util/TaskQueue;->fixDown(I)V
+Ljava/util/TaskQueue;->fixUp(I)V
+Ljava/util/TaskQueue;->get(I)Ljava/util/TimerTask;
+Ljava/util/TaskQueue;->getMin()Ljava/util/TimerTask;
+Ljava/util/TaskQueue;->heapify()V
+Ljava/util/TaskQueue;->isEmpty()Z
+Ljava/util/TaskQueue;->queue:[Ljava/util/TimerTask;
+Ljava/util/TaskQueue;->quickRemove(I)V
+Ljava/util/TaskQueue;->removeMin()V
+Ljava/util/TaskQueue;->rescheduleMin(J)V
+Ljava/util/TaskQueue;->size()I
+Ljava/util/TaskQueue;->size:I
+Ljava/util/Timer;->nextSerialNumber:Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/util/Timer;->queue:Ljava/util/TaskQueue;
+Ljava/util/Timer;->sched(Ljava/util/TimerTask;JJ)V
+Ljava/util/Timer;->serialNumber()I
+Ljava/util/Timer;->thread:Ljava/util/TimerThread;
+Ljava/util/Timer;->threadReaper:Ljava/lang/Object;
+Ljava/util/TimerTask;->CANCELLED:I
+Ljava/util/TimerTask;->EXECUTED:I
+Ljava/util/TimerTask;->lock:Ljava/lang/Object;
+Ljava/util/TimerTask;->nextExecutionTime:J
+Ljava/util/TimerTask;->SCHEDULED:I
+Ljava/util/TimerTask;->state:I
+Ljava/util/TimerTask;->VIRGIN:I
+Ljava/util/TimerThread;-><init>(Ljava/util/TaskQueue;)V
+Ljava/util/TimerThread;->mainLoop()V
+Ljava/util/TimerThread;->newTasksMayBeScheduled:Z
+Ljava/util/TimerThread;->queue:Ljava/util/TaskQueue;
+Ljava/util/TimeZone$NoImagePreloadHolder;-><init>()V
+Ljava/util/TimeZone$NoImagePreloadHolder;->CUSTOM_ZONE_ID_PATTERN:Ljava/util/regex/Pattern;
+Ljava/util/TimeZone;->appendNumber(Ljava/lang/StringBuilder;II)V
+Ljava/util/TimeZone;->createGmtOffsetString(ZZI)Ljava/lang/String;
+Ljava/util/TimeZone;->defaultTimeZone:Ljava/util/TimeZone;
+Ljava/util/TimeZone;->getCustomTimeZone(Ljava/lang/String;)Ljava/util/TimeZone;
+Ljava/util/TimeZone;->getDefaultRef()Ljava/util/TimeZone;
+Ljava/util/TimeZone;->getOffsets(J[I)I
+Ljava/util/TimeZone;->getSystemGMTOffsetID()Ljava/lang/String;
+Ljava/util/TimeZone;->getSystemTimeZoneID(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Ljava/util/TimeZone;->GMT:Ljava/util/TimeZone;
+Ljava/util/TimeZone;->ID:Ljava/lang/String;
+Ljava/util/TimeZone;->NO_TIMEZONE:Ljava/util/TimeZone;
+Ljava/util/TimeZone;->UTC:Ljava/util/TimeZone;
+Ljava/util/TreeMap$AscendingSubMap;-><init>(Ljava/util/TreeMap;ZLjava/lang/Object;ZZLjava/lang/Object;Z)V
+Ljava/util/TreeMap$AscendingSubMap;->descendingKeyIterator()Ljava/util/Iterator;
+Ljava/util/TreeMap$AscendingSubMap;->keyIterator()Ljava/util/Iterator;
+Ljava/util/TreeMap$AscendingSubMap;->keySpliterator()Ljava/util/Spliterator;
+Ljava/util/TreeMap$AscendingSubMap;->subCeiling(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$AscendingSubMap;->subFloor(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$AscendingSubMap;->subHigher(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$AscendingSubMap;->subHighest()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$AscendingSubMap;->subLower(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$AscendingSubMap;->subLowest()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$DescendingKeySpliterator;-><init>(Ljava/util/TreeMap;Ljava/util/TreeMap$TreeMapEntry;Ljava/util/TreeMap$TreeMapEntry;III)V
+Ljava/util/TreeMap$DescendingKeySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/TreeMap$DescendingKeySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/TreeMap$DescendingSubMap;-><init>(Ljava/util/TreeMap;ZLjava/lang/Object;ZZLjava/lang/Object;Z)V
+Ljava/util/TreeMap$DescendingSubMap;->descendingKeyIterator()Ljava/util/Iterator;
+Ljava/util/TreeMap$DescendingSubMap;->keyIterator()Ljava/util/Iterator;
+Ljava/util/TreeMap$DescendingSubMap;->keySpliterator()Ljava/util/Spliterator;
+Ljava/util/TreeMap$DescendingSubMap;->reverseComparator:Ljava/util/Comparator;
+Ljava/util/TreeMap$DescendingSubMap;->subCeiling(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$DescendingSubMap;->subFloor(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$DescendingSubMap;->subHigher(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$DescendingSubMap;->subHighest()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$DescendingSubMap;->subLower(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$DescendingSubMap;->subLowest()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$EntrySpliterator;-><init>(Ljava/util/TreeMap;Ljava/util/TreeMap$TreeMapEntry;Ljava/util/TreeMap$TreeMapEntry;III)V
+Ljava/util/TreeMap$EntrySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/TreeMap$EntrySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/TreeMap$KeySet;-><init>(Ljava/util/NavigableMap;)V
+Ljava/util/TreeMap$KeySet;->m:Ljava/util/NavigableMap;
+Ljava/util/TreeMap$KeySpliterator;-><init>(Ljava/util/TreeMap;Ljava/util/TreeMap$TreeMapEntry;Ljava/util/TreeMap$TreeMapEntry;III)V
+Ljava/util/TreeMap$KeySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/TreeMap$KeySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/TreeMap$NavigableSubMap$DescendingSubMapKeyIterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/TreeMap$NavigableSubMap$DescendingSubMapKeyIterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/TreeMap$NavigableSubMap$EntrySetView;->size:I
+Ljava/util/TreeMap$NavigableSubMap$EntrySetView;->sizeModCount:I
+Ljava/util/TreeMap$NavigableSubMap$SubMapIterator;->expectedModCount:I
+Ljava/util/TreeMap$NavigableSubMap$SubMapIterator;->fenceKey:Ljava/lang/Object;
+Ljava/util/TreeMap$NavigableSubMap$SubMapIterator;->lastReturned:Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap$SubMapIterator;->next:Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap$SubMapIterator;->nextEntry()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap$SubMapIterator;->prevEntry()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap$SubMapIterator;->removeAscending()V
+Ljava/util/TreeMap$NavigableSubMap$SubMapIterator;->removeDescending()V
+Ljava/util/TreeMap$NavigableSubMap$SubMapKeyIterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/TreeMap$NavigableSubMap$SubMapKeyIterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/TreeMap$NavigableSubMap;-><init>(Ljava/util/TreeMap;ZLjava/lang/Object;ZZLjava/lang/Object;Z)V
+Ljava/util/TreeMap$NavigableSubMap;->absCeiling(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->absFloor(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->absHigher(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->absHighest()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->absHighFence()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->absLower(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->absLowest()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->absLowFence()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->descendingKeyIterator()Ljava/util/Iterator;
+Ljava/util/TreeMap$NavigableSubMap;->descendingMapView:Ljava/util/NavigableMap;
+Ljava/util/TreeMap$NavigableSubMap;->entrySetView:Ljava/util/TreeMap$NavigableSubMap$EntrySetView;
+Ljava/util/TreeMap$NavigableSubMap;->fromStart:Z
+Ljava/util/TreeMap$NavigableSubMap;->hi:Ljava/lang/Object;
+Ljava/util/TreeMap$NavigableSubMap;->hiInclusive:Z
+Ljava/util/TreeMap$NavigableSubMap;->inClosedRange(Ljava/lang/Object;)Z
+Ljava/util/TreeMap$NavigableSubMap;->inRange(Ljava/lang/Object;)Z
+Ljava/util/TreeMap$NavigableSubMap;->inRange(Ljava/lang/Object;Z)Z
+Ljava/util/TreeMap$NavigableSubMap;->keyIterator()Ljava/util/Iterator;
+Ljava/util/TreeMap$NavigableSubMap;->keySpliterator()Ljava/util/Spliterator;
+Ljava/util/TreeMap$NavigableSubMap;->lo:Ljava/lang/Object;
+Ljava/util/TreeMap$NavigableSubMap;->loInclusive:Z
+Ljava/util/TreeMap$NavigableSubMap;->m:Ljava/util/TreeMap;
+Ljava/util/TreeMap$NavigableSubMap;->navigableKeySetView:Ljava/util/TreeMap$KeySet;
+Ljava/util/TreeMap$NavigableSubMap;->subCeiling(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->subFloor(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->subHigher(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->subHighest()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->subLower(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->subLowest()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$NavigableSubMap;->toEnd:Z
+Ljava/util/TreeMap$NavigableSubMap;->tooHigh(Ljava/lang/Object;)Z
+Ljava/util/TreeMap$NavigableSubMap;->tooLow(Ljava/lang/Object;)Z
+Ljava/util/TreeMap$PrivateEntryIterator;->expectedModCount:I
+Ljava/util/TreeMap$PrivateEntryIterator;->lastReturned:Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$PrivateEntryIterator;->next:Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$PrivateEntryIterator;->nextEntry()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$PrivateEntryIterator;->prevEntry()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$SubMap;->fromKey:Ljava/lang/Object;
+Ljava/util/TreeMap$SubMap;->fromStart:Z
+Ljava/util/TreeMap$SubMap;->toEnd:Z
+Ljava/util/TreeMap$SubMap;->toKey:Ljava/lang/Object;
+Ljava/util/TreeMap$TreeMapEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/TreeMap$TreeMapEntry;)V
+Ljava/util/TreeMap$TreeMapEntry;->color:Z
+Ljava/util/TreeMap$TreeMapEntry;->key:Ljava/lang/Object;
+Ljava/util/TreeMap$TreeMapEntry;->left:Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$TreeMapEntry;->parent:Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$TreeMapEntry;->right:Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$TreeMapEntry;->value:Ljava/lang/Object;
+Ljava/util/TreeMap$TreeMapSpliterator;-><init>(Ljava/util/TreeMap;Ljava/util/TreeMap$TreeMapEntry;Ljava/util/TreeMap$TreeMapEntry;III)V
+Ljava/util/TreeMap$TreeMapSpliterator;->current:Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$TreeMapSpliterator;->est:I
+Ljava/util/TreeMap$TreeMapSpliterator;->estimateSize()J
+Ljava/util/TreeMap$TreeMapSpliterator;->expectedModCount:I
+Ljava/util/TreeMap$TreeMapSpliterator;->fence:Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$TreeMapSpliterator;->getEstimate()I
+Ljava/util/TreeMap$TreeMapSpliterator;->side:I
+Ljava/util/TreeMap$TreeMapSpliterator;->tree:Ljava/util/TreeMap;
+Ljava/util/TreeMap$ValueSpliterator;-><init>(Ljava/util/TreeMap;Ljava/util/TreeMap$TreeMapEntry;Ljava/util/TreeMap$TreeMapEntry;III)V
+Ljava/util/TreeMap$ValueSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/TreeMap$ValueSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/TreeMap;->addAllForTreeSet(Ljava/util/SortedSet;Ljava/lang/Object;)V
+Ljava/util/TreeMap;->BLACK:Z
+Ljava/util/TreeMap;->buildFromSorted(IIIILjava/util/Iterator;Ljava/io/ObjectInputStream;Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->buildFromSorted(ILjava/util/Iterator;Ljava/io/ObjectInputStream;Ljava/lang/Object;)V
+Ljava/util/TreeMap;->colorOf(Ljava/util/TreeMap$TreeMapEntry;)Z
+Ljava/util/TreeMap;->comparator:Ljava/util/Comparator;
+Ljava/util/TreeMap;->compare(Ljava/lang/Object;Ljava/lang/Object;)I
+Ljava/util/TreeMap;->computeRedLevel(I)I
+Ljava/util/TreeMap;->deleteEntry(Ljava/util/TreeMap$TreeMapEntry;)V
+Ljava/util/TreeMap;->descendingKeyIterator()Ljava/util/Iterator;
+Ljava/util/TreeMap;->descendingKeySpliterator()Ljava/util/Spliterator;
+Ljava/util/TreeMap;->descendingMap:Ljava/util/NavigableMap;
+Ljava/util/TreeMap;->entrySet:Ljava/util/TreeMap$EntrySet;
+Ljava/util/TreeMap;->exportEntry(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/Map$Entry;
+Ljava/util/TreeMap;->fixAfterDeletion(Ljava/util/TreeMap$TreeMapEntry;)V
+Ljava/util/TreeMap;->fixAfterInsertion(Ljava/util/TreeMap$TreeMapEntry;)V
+Ljava/util/TreeMap;->getCeilingEntry(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->getEntry(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->getEntryUsingComparator(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->getFirstEntry()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->getFloorEntry(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->getHigherEntry(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->getLastEntry()Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->getLowerEntry(Ljava/lang/Object;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->key(Ljava/util/TreeMap$TreeMapEntry;)Ljava/lang/Object;
+Ljava/util/TreeMap;->keyIterator()Ljava/util/Iterator;
+Ljava/util/TreeMap;->keyOrNull(Ljava/util/TreeMap$TreeMapEntry;)Ljava/lang/Object;
+Ljava/util/TreeMap;->keySpliterator()Ljava/util/Spliterator;
+Ljava/util/TreeMap;->keySpliteratorFor(Ljava/util/NavigableMap;)Ljava/util/Spliterator;
+Ljava/util/TreeMap;->leftOf(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->modCount:I
+Ljava/util/TreeMap;->navigableKeySet:Ljava/util/TreeMap$KeySet;
+Ljava/util/TreeMap;->parentOf(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->predecessor(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->readTreeSet(ILjava/io/ObjectInputStream;Ljava/lang/Object;)V
+Ljava/util/TreeMap;->RED:Z
+Ljava/util/TreeMap;->rightOf(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->root:Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->rotateLeft(Ljava/util/TreeMap$TreeMapEntry;)V
+Ljava/util/TreeMap;->rotateRight(Ljava/util/TreeMap$TreeMapEntry;)V
+Ljava/util/TreeMap;->setColor(Ljava/util/TreeMap$TreeMapEntry;Z)V
+Ljava/util/TreeMap;->size:I
+Ljava/util/TreeMap;->successor(Ljava/util/TreeMap$TreeMapEntry;)Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap;->UNBOUNDED:Ljava/lang/Object;
+Ljava/util/TreeMap;->valEquals(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/TreeSet;-><init>(Ljava/util/NavigableMap;)V
+Ljava/util/TreeSet;->m:Ljava/util/NavigableMap;
+Ljava/util/TreeSet;->PRESENT:Ljava/lang/Object;
+Ljava/util/UnknownFormatConversionException;->s:Ljava/lang/String;
+Ljava/util/UnknownFormatFlagsException;->flags:Ljava/lang/String;
+Ljava/util/UUID$Holder;-><init>()V
+Ljava/util/UUID$Holder;->numberGenerator:Ljava/security/SecureRandom;
+Ljava/util/UUID;-><init>([B)V
+Ljava/util/UUID;->digits(JI)Ljava/lang/String;
+Ljava/util/Vector$Itr;->checkForComodification()V
+Ljava/util/Vector$Itr;->cursor:I
+Ljava/util/Vector$Itr;->expectedModCount:I
+Ljava/util/Vector$Itr;->lastRet:I
+Ljava/util/Vector$Itr;->limit:I
+Ljava/util/Vector$VectorSpliterator;-><init>(Ljava/util/Vector;[Ljava/lang/Object;III)V
+Ljava/util/Vector$VectorSpliterator;->array:[Ljava/lang/Object;
+Ljava/util/Vector$VectorSpliterator;->expectedModCount:I
+Ljava/util/Vector$VectorSpliterator;->fence:I
+Ljava/util/Vector$VectorSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/Vector$VectorSpliterator;->getFence()I
+Ljava/util/Vector$VectorSpliterator;->index:I
+Ljava/util/Vector$VectorSpliterator;->list:Ljava/util/Vector;
+Ljava/util/Vector$VectorSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/Vector;->ensureCapacityHelper(I)V
+Ljava/util/Vector;->grow(I)V
+Ljava/util/Vector;->hugeCapacity(I)I
+Ljava/util/Vector;->MAX_ARRAY_SIZE:I
+Ljava/util/WeakHashMap$Entry;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;ILjava/util/WeakHashMap$Entry;)V
+Ljava/util/WeakHashMap$Entry;->hash:I
+Ljava/util/WeakHashMap$Entry;->next:Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap$Entry;->value:Ljava/lang/Object;
+Ljava/util/WeakHashMap$EntrySet;->deepCopy()Ljava/util/List;
+Ljava/util/WeakHashMap$EntrySpliterator;-><init>(Ljava/util/WeakHashMap;IIII)V
+Ljava/util/WeakHashMap$EntrySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/WeakHashMap$EntrySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/WeakHashMap$HashIterator;->currentKey:Ljava/lang/Object;
+Ljava/util/WeakHashMap$HashIterator;->entry:Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap$HashIterator;->expectedModCount:I
+Ljava/util/WeakHashMap$HashIterator;->index:I
+Ljava/util/WeakHashMap$HashIterator;->lastReturned:Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap$HashIterator;->nextEntry()Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap$HashIterator;->nextKey:Ljava/lang/Object;
+Ljava/util/WeakHashMap$KeySpliterator;-><init>(Ljava/util/WeakHashMap;IIII)V
+Ljava/util/WeakHashMap$KeySpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/WeakHashMap$KeySpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/WeakHashMap$ValueSpliterator;-><init>(Ljava/util/WeakHashMap;IIII)V
+Ljava/util/WeakHashMap$ValueSpliterator;->forEachRemaining(Ljava/util/function/Consumer;)V
+Ljava/util/WeakHashMap$ValueSpliterator;->tryAdvance(Ljava/util/function/Consumer;)Z
+Ljava/util/WeakHashMap$WeakHashMapSpliterator;-><init>(Ljava/util/WeakHashMap;IIII)V
+Ljava/util/WeakHashMap$WeakHashMapSpliterator;->current:Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap$WeakHashMapSpliterator;->est:I
+Ljava/util/WeakHashMap$WeakHashMapSpliterator;->estimateSize()J
+Ljava/util/WeakHashMap$WeakHashMapSpliterator;->expectedModCount:I
+Ljava/util/WeakHashMap$WeakHashMapSpliterator;->fence:I
+Ljava/util/WeakHashMap$WeakHashMapSpliterator;->getFence()I
+Ljava/util/WeakHashMap$WeakHashMapSpliterator;->index:I
+Ljava/util/WeakHashMap$WeakHashMapSpliterator;->map:Ljava/util/WeakHashMap;
+Ljava/util/WeakHashMap;->containsNullValue()Z
+Ljava/util/WeakHashMap;->DEFAULT_INITIAL_CAPACITY:I
+Ljava/util/WeakHashMap;->DEFAULT_LOAD_FACTOR:F
+Ljava/util/WeakHashMap;->entrySet:Ljava/util/Set;
+Ljava/util/WeakHashMap;->eq(Ljava/lang/Object;Ljava/lang/Object;)Z
+Ljava/util/WeakHashMap;->expungeStaleEntries()V
+Ljava/util/WeakHashMap;->getEntry(Ljava/lang/Object;)Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap;->getTable()[Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap;->hash(Ljava/lang/Object;)I
+Ljava/util/WeakHashMap;->indexFor(II)I
+Ljava/util/WeakHashMap;->loadFactor:F
+Ljava/util/WeakHashMap;->maskNull(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/WeakHashMap;->MAXIMUM_CAPACITY:I
+Ljava/util/WeakHashMap;->modCount:I
+Ljava/util/WeakHashMap;->newTable(I)[Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap;->NULL_KEY:Ljava/lang/Object;
+Ljava/util/WeakHashMap;->queue:Ljava/lang/ref/ReferenceQueue;
+Ljava/util/WeakHashMap;->removeMapping(Ljava/lang/Object;)Z
+Ljava/util/WeakHashMap;->resize(I)V
+Ljava/util/WeakHashMap;->size:I
+Ljava/util/WeakHashMap;->table:[Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap;->threshold:I
+Ljava/util/WeakHashMap;->transfer([Ljava/util/WeakHashMap$Entry;[Ljava/util/WeakHashMap$Entry;)V
+Ljava/util/WeakHashMap;->unmaskNull(Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/util/zip/Adler32;->adler:I
+Ljava/util/zip/Adler32;->updateByteBuffer(IJII)I
+Ljava/util/zip/Adler32;->updateBytes(I[BII)I
+Ljava/util/zip/CheckedInputStream;->cksum:Ljava/util/zip/Checksum;
+Ljava/util/zip/CheckedOutputStream;->cksum:Ljava/util/zip/Checksum;
+Ljava/util/zip/CRC32;->crc:I
+Ljava/util/zip/CRC32;->updateByteBuffer(IJII)I
+Ljava/util/zip/CRC32;->updateBytes(I[BII)I
+Ljava/util/zip/Deflater;->bytesRead:J
+Ljava/util/zip/Deflater;->bytesWritten:J
+Ljava/util/zip/Deflater;->deflateBytes(J[BIII)I
+Ljava/util/zip/Deflater;->end(J)V
+Ljava/util/zip/Deflater;->ensureOpen()V
+Ljava/util/zip/Deflater;->getAdler(J)I
+Ljava/util/zip/Deflater;->guard:Ldalvik/system/CloseGuard;
+Ljava/util/zip/Deflater;->init(IIZ)J
+Ljava/util/zip/Deflater;->reset(J)V
+Ljava/util/zip/Deflater;->setDictionary(J[BII)V
+Ljava/util/zip/Deflater;->zsRef:Ljava/util/zip/ZStreamRef;
+Ljava/util/zip/DeflaterInputStream;->ensureOpen()V
+Ljava/util/zip/DeflaterInputStream;->rbuf:[B
+Ljava/util/zip/DeflaterInputStream;->reachEOF:Z
+Ljava/util/zip/DeflaterInputStream;->usesDefaultDeflater:Z
+Ljava/util/zip/DeflaterOutputStream;->closed:Z
+Ljava/util/zip/DeflaterOutputStream;->syncFlush:Z
+Ljava/util/zip/DeflaterOutputStream;->usesDefaultDeflater:Z
+Ljava/util/zip/GZIPInputStream;->closed:Z
+Ljava/util/zip/GZIPInputStream;->ensureOpen()V
+Ljava/util/zip/GZIPInputStream;->FCOMMENT:I
+Ljava/util/zip/GZIPInputStream;->FEXTRA:I
+Ljava/util/zip/GZIPInputStream;->FHCRC:I
+Ljava/util/zip/GZIPInputStream;->FNAME:I
+Ljava/util/zip/GZIPInputStream;->FTEXT:I
+Ljava/util/zip/GZIPInputStream;->readHeader(Ljava/io/InputStream;)I
+Ljava/util/zip/GZIPInputStream;->readTrailer()Z
+Ljava/util/zip/GZIPInputStream;->readUByte(Ljava/io/InputStream;)I
+Ljava/util/zip/GZIPInputStream;->readUInt(Ljava/io/InputStream;)J
+Ljava/util/zip/GZIPInputStream;->readUShort(Ljava/io/InputStream;)I
+Ljava/util/zip/GZIPInputStream;->skipBytes(Ljava/io/InputStream;I)V
+Ljava/util/zip/GZIPInputStream;->tmpbuf:[B
+Ljava/util/zip/GZIPOutputStream;->GZIP_MAGIC:I
+Ljava/util/zip/GZIPOutputStream;->TRAILER_SIZE:I
+Ljava/util/zip/GZIPOutputStream;->writeHeader()V
+Ljava/util/zip/GZIPOutputStream;->writeInt(I[BI)V
+Ljava/util/zip/GZIPOutputStream;->writeShort(I[BI)V
+Ljava/util/zip/GZIPOutputStream;->writeTrailer([BI)V
+Ljava/util/zip/Inflater;->bytesRead:J
+Ljava/util/zip/Inflater;->bytesWritten:J
+Ljava/util/zip/Inflater;->defaultBuf:[B
+Ljava/util/zip/Inflater;->end(J)V
+Ljava/util/zip/Inflater;->ended()Z
+Ljava/util/zip/Inflater;->ensureOpen()V
+Ljava/util/zip/Inflater;->getAdler(J)I
+Ljava/util/zip/Inflater;->guard:Ldalvik/system/CloseGuard;
+Ljava/util/zip/Inflater;->inflateBytes(J[BII)I
+Ljava/util/zip/Inflater;->init(Z)J
+Ljava/util/zip/Inflater;->reset(J)V
+Ljava/util/zip/Inflater;->setDictionary(J[BII)V
+Ljava/util/zip/Inflater;->zsRef:Ljava/util/zip/ZStreamRef;
+Ljava/util/zip/InflaterInputStream;->b:[B
+Ljava/util/zip/InflaterInputStream;->ensureOpen()V
+Ljava/util/zip/InflaterInputStream;->reachEOF:Z
+Ljava/util/zip/InflaterInputStream;->singleByteBuf:[B
+Ljava/util/zip/InflaterOutputStream;->closed:Z
+Ljava/util/zip/InflaterOutputStream;->ensureOpen()V
+Ljava/util/zip/InflaterOutputStream;->usesDefaultInflater:Z
+Ljava/util/zip/InflaterOutputStream;->wbuf:[B
+Ljava/util/zip/ZipCoder;-><init>(Ljava/nio/charset/Charset;)V
+Ljava/util/zip/ZipCoder;->cs:Ljava/nio/charset/Charset;
+Ljava/util/zip/ZipCoder;->dec:Ljava/nio/charset/CharsetDecoder;
+Ljava/util/zip/ZipCoder;->decoder()Ljava/nio/charset/CharsetDecoder;
+Ljava/util/zip/ZipCoder;->enc:Ljava/nio/charset/CharsetEncoder;
+Ljava/util/zip/ZipCoder;->encoder()Ljava/nio/charset/CharsetEncoder;
+Ljava/util/zip/ZipCoder;->get(Ljava/nio/charset/Charset;)Ljava/util/zip/ZipCoder;
+Ljava/util/zip/ZipCoder;->getBytes(Ljava/lang/String;)[B
+Ljava/util/zip/ZipCoder;->getBytesUTF8(Ljava/lang/String;)[B
+Ljava/util/zip/ZipCoder;->isUTF8()Z
+Ljava/util/zip/ZipCoder;->isUTF8:Z
+Ljava/util/zip/ZipCoder;->toString([B)Ljava/lang/String;
+Ljava/util/zip/ZipCoder;->toString([BI)Ljava/lang/String;
+Ljava/util/zip/ZipCoder;->toStringUTF8([BI)Ljava/lang/String;
+Ljava/util/zip/ZipCoder;->utf8:Ljava/util/zip/ZipCoder;
+Ljava/util/zip/ZipEntry;-><init>()V
+Ljava/util/zip/ZipEntry;->atime:Ljava/nio/file/attribute/FileTime;
+Ljava/util/zip/ZipEntry;->comment:Ljava/lang/String;
+Ljava/util/zip/ZipEntry;->crc:J
+Ljava/util/zip/ZipEntry;->csize:J
+Ljava/util/zip/ZipEntry;->ctime:Ljava/nio/file/attribute/FileTime;
+Ljava/util/zip/ZipEntry;->dataOffset:J
+Ljava/util/zip/ZipEntry;->DOSTIME_BEFORE_1980:J
+Ljava/util/zip/ZipEntry;->extra:[B
+Ljava/util/zip/ZipEntry;->flag:I
+Ljava/util/zip/ZipEntry;->getDataOffset()J
+Ljava/util/zip/ZipEntry;->mtime:Ljava/nio/file/attribute/FileTime;
+Ljava/util/zip/ZipEntry;->name:Ljava/lang/String;
+Ljava/util/zip/ZipEntry;->setExtra0([BZ)V
+Ljava/util/zip/ZipEntry;->size:J
+Ljava/util/zip/ZipEntry;->UPPER_DOSTIME_BOUND:J
+Ljava/util/zip/ZipEntry;->xdostime:J
+Ljava/util/zip/ZipFile$ZipEntryIterator;->i:I
+Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;->closeRequested:Z
+Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;->eof:Z
+Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;->zfin:Ljava/util/zip/ZipFile$ZipFileInputStream;
+Ljava/util/zip/ZipFile$ZipFileInputStream;->jzentry:J
+Ljava/util/zip/ZipFile$ZipFileInputStream;->pos:J
+Ljava/util/zip/ZipFile$ZipFileInputStream;->rem:J
+Ljava/util/zip/ZipFile$ZipFileInputStream;->size()J
+Ljava/util/zip/ZipFile$ZipFileInputStream;->size:J
+Ljava/util/zip/ZipFile$ZipFileInputStream;->zfisCloseRequested:Z
+Ljava/util/zip/ZipFile;->closeRequested:Z
+Ljava/util/zip/ZipFile;->DEFLATED:I
+Ljava/util/zip/ZipFile;->ensureOpen()V
+Ljava/util/zip/ZipFile;->ensureOpenOrZipException()V
+Ljava/util/zip/ZipFile;->fileToRemoveOnClose:Ljava/io/File;
+Ljava/util/zip/ZipFile;->freeEntry(JJ)V
+Ljava/util/zip/ZipFile;->getCommentBytes(J)[B
+Ljava/util/zip/ZipFile;->getEntryBytes(JI)[B
+Ljava/util/zip/ZipFile;->getEntryCrc(J)J
+Ljava/util/zip/ZipFile;->getEntryCSize(J)J
+Ljava/util/zip/ZipFile;->getEntryFlag(J)I
+Ljava/util/zip/ZipFile;->getEntryMethod(J)I
+Ljava/util/zip/ZipFile;->getEntrySize(J)J
+Ljava/util/zip/ZipFile;->getEntryTime(J)J
+Ljava/util/zip/ZipFile;->getFileDescriptor()I
+Ljava/util/zip/ZipFile;->getFileDescriptor(J)I
+Ljava/util/zip/ZipFile;->getInflater()Ljava/util/zip/Inflater;
+Ljava/util/zip/ZipFile;->getNextEntry(JI)J
+Ljava/util/zip/ZipFile;->getTotal(J)I
+Ljava/util/zip/ZipFile;->getZipEntry(Ljava/lang/String;J)Ljava/util/zip/ZipEntry;
+Ljava/util/zip/ZipFile;->getZipMessage(J)Ljava/lang/String;
+Ljava/util/zip/ZipFile;->guard:Ldalvik/system/CloseGuard;
+Ljava/util/zip/ZipFile;->inflaterCache:Ljava/util/Deque;
+Ljava/util/zip/ZipFile;->JZENTRY_COMMENT:I
+Ljava/util/zip/ZipFile;->JZENTRY_EXTRA:I
+Ljava/util/zip/ZipFile;->JZENTRY_NAME:I
+Ljava/util/zip/ZipFile;->locsig:Z
+Ljava/util/zip/ZipFile;->name:Ljava/lang/String;
+Ljava/util/zip/ZipFile;->open(Ljava/lang/String;IJZ)J
+Ljava/util/zip/ZipFile;->read(JJJ[BII)I
+Ljava/util/zip/ZipFile;->releaseInflater(Ljava/util/zip/Inflater;)V
+Ljava/util/zip/ZipFile;->startsWithLOC(J)Z
+Ljava/util/zip/ZipFile;->startsWithLocHeader()Z
+Ljava/util/zip/ZipFile;->STORED:I
+Ljava/util/zip/ZipFile;->streams:Ljava/util/Map;
+Ljava/util/zip/ZipFile;->total:I
+Ljava/util/zip/ZipFile;->usemmap:Z
+Ljava/util/zip/ZipFile;->zc:Ljava/util/zip/ZipCoder;
+Ljava/util/zip/ZipInputStream;->b:[B
+Ljava/util/zip/ZipInputStream;->closed:Z
+Ljava/util/zip/ZipInputStream;->crc:Ljava/util/zip/CRC32;
+Ljava/util/zip/ZipInputStream;->DEFLATED:I
+Ljava/util/zip/ZipInputStream;->ensureOpen()V
+Ljava/util/zip/ZipInputStream;->entry:Ljava/util/zip/ZipEntry;
+Ljava/util/zip/ZipInputStream;->entryEOF:Z
+Ljava/util/zip/ZipInputStream;->readEnd(Ljava/util/zip/ZipEntry;)V
+Ljava/util/zip/ZipInputStream;->readFully([BII)V
+Ljava/util/zip/ZipInputStream;->readLOC()Ljava/util/zip/ZipEntry;
+Ljava/util/zip/ZipInputStream;->remaining:J
+Ljava/util/zip/ZipInputStream;->STORED:I
+Ljava/util/zip/ZipInputStream;->zc:Ljava/util/zip/ZipCoder;
+Ljava/util/zip/ZipOutputStream$XEntry;-><init>(Ljava/util/zip/ZipEntry;J)V
+Ljava/util/zip/ZipOutputStream$XEntry;->entry:Ljava/util/zip/ZipEntry;
+Ljava/util/zip/ZipOutputStream$XEntry;->offset:J
+Ljava/util/zip/ZipOutputStream;->closed:Z
+Ljava/util/zip/ZipOutputStream;->comment:[B
+Ljava/util/zip/ZipOutputStream;->crc:Ljava/util/zip/CRC32;
+Ljava/util/zip/ZipOutputStream;->current:Ljava/util/zip/ZipOutputStream$XEntry;
+Ljava/util/zip/ZipOutputStream;->ensureOpen()V
+Ljava/util/zip/ZipOutputStream;->finished:Z
+Ljava/util/zip/ZipOutputStream;->getExtraLen([B)I
+Ljava/util/zip/ZipOutputStream;->inhibitZip64:Z
+Ljava/util/zip/ZipOutputStream;->locoff:J
+Ljava/util/zip/ZipOutputStream;->version(Ljava/util/zip/ZipEntry;)I
+Ljava/util/zip/ZipOutputStream;->writeByte(I)V
+Ljava/util/zip/ZipOutputStream;->writeBytes([BII)V
+Ljava/util/zip/ZipOutputStream;->writeCEN(Ljava/util/zip/ZipOutputStream$XEntry;)V
+Ljava/util/zip/ZipOutputStream;->writeEND(JJ)V
+Ljava/util/zip/ZipOutputStream;->writeEXT(Ljava/util/zip/ZipEntry;)V
+Ljava/util/zip/ZipOutputStream;->writeExtra([B)V
+Ljava/util/zip/ZipOutputStream;->writeInt(J)V
+Ljava/util/zip/ZipOutputStream;->writeLOC(Ljava/util/zip/ZipOutputStream$XEntry;)V
+Ljava/util/zip/ZipOutputStream;->writeLong(J)V
+Ljava/util/zip/ZipOutputStream;->writeShort(I)V
+Ljava/util/zip/ZipOutputStream;->xentries:Ljava/util/Vector;
+Ljava/util/zip/ZipOutputStream;->zc:Ljava/util/zip/ZipCoder;
+Ljava/util/zip/ZStreamRef;-><init>(J)V
+Ljava/util/zip/ZStreamRef;->address()J
+Ljava/util/zip/ZStreamRef;->address:J
+Ljava/util/zip/ZStreamRef;->clear()V
+Ljavax/crypto/Cipher$CipherSpiAndProvider;-><init>(Ljavax/crypto/CipherSpi;Ljava/security/Provider;)V
+Ljavax/crypto/Cipher$CipherSpiAndProvider;->cipherSpi:Ljavax/crypto/CipherSpi;
+Ljavax/crypto/Cipher$CipherSpiAndProvider;->provider:Ljava/security/Provider;
+Ljavax/crypto/Cipher$InitParams;-><init>(Ljavax/crypto/Cipher$InitType;ILjava/security/Key;Ljava/security/SecureRandom;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/AlgorithmParameters;)V
+Ljavax/crypto/Cipher$InitParams;->initType:Ljavax/crypto/Cipher$InitType;
+Ljavax/crypto/Cipher$InitParams;->key:Ljava/security/Key;
+Ljavax/crypto/Cipher$InitParams;->opmode:I
+Ljavax/crypto/Cipher$InitParams;->params:Ljava/security/AlgorithmParameters;
+Ljavax/crypto/Cipher$InitParams;->random:Ljava/security/SecureRandom;
+Ljavax/crypto/Cipher$InitParams;->spec:Ljava/security/spec/AlgorithmParameterSpec;
+Ljavax/crypto/Cipher$InitType;->ALGORITHM_PARAMS:Ljavax/crypto/Cipher$InitType;
+Ljavax/crypto/Cipher$InitType;->ALGORITHM_PARAM_SPEC:Ljavax/crypto/Cipher$InitType;
+Ljavax/crypto/Cipher$InitType;->KEY:Ljavax/crypto/Cipher$InitType;
+Ljavax/crypto/Cipher$InitType;->valueOf(Ljava/lang/String;)Ljavax/crypto/Cipher$InitType;
+Ljavax/crypto/Cipher$InitType;->values()[Ljavax/crypto/Cipher$InitType;
+Ljavax/crypto/Cipher$NeedToSet;->BOTH:Ljavax/crypto/Cipher$NeedToSet;
+Ljavax/crypto/Cipher$NeedToSet;->MODE:Ljavax/crypto/Cipher$NeedToSet;
+Ljavax/crypto/Cipher$NeedToSet;->NONE:Ljavax/crypto/Cipher$NeedToSet;
+Ljavax/crypto/Cipher$NeedToSet;->PADDING:Ljavax/crypto/Cipher$NeedToSet;
+Ljavax/crypto/Cipher$NeedToSet;->valueOf(Ljava/lang/String;)Ljavax/crypto/Cipher$NeedToSet;
+Ljavax/crypto/Cipher$NeedToSet;->values()[Ljavax/crypto/Cipher$NeedToSet;
+Ljavax/crypto/Cipher$SpiAndProviderUpdater;->getCurrentSpi(Ljavax/crypto/CipherSpi;)Ljavax/crypto/CipherSpi;
+Ljavax/crypto/Cipher$SpiAndProviderUpdater;->initSpiLock:Ljava/lang/Object;
+Ljavax/crypto/Cipher$SpiAndProviderUpdater;->setCipherSpiImplAndProvider(Ljavax/crypto/CipherSpi;Ljava/security/Provider;)V
+Ljavax/crypto/Cipher$SpiAndProviderUpdater;->specifiedProvider:Ljava/security/Provider;
+Ljavax/crypto/Cipher$SpiAndProviderUpdater;->specifiedSpi:Ljavax/crypto/CipherSpi;
+Ljavax/crypto/Cipher$SpiAndProviderUpdater;->updateAndGetSpiAndProvider(Ljavax/crypto/Cipher$InitParams;Ljavax/crypto/CipherSpi;Ljava/security/Provider;)Ljavax/crypto/Cipher$CipherSpiAndProvider;
+Ljavax/crypto/Cipher$SpiAndProviderUpdater;->updateAndGetSpiAndProvider(Ljavax/crypto/CipherSpi;Ljava/security/Provider;)Ljavax/crypto/Cipher$CipherSpiAndProvider;
+Ljavax/crypto/Cipher$Transform;-><init>(Ljava/lang/String;Ljavax/crypto/Cipher$NeedToSet;)V
+Ljavax/crypto/Cipher$Transform;->name:Ljava/lang/String;
+Ljavax/crypto/Cipher$Transform;->needToSet:Ljavax/crypto/Cipher$NeedToSet;
+Ljavax/crypto/Cipher;-><init>(Ljavax/crypto/CipherSpi;Ljava/security/Provider;Ljava/lang/String;[Ljava/lang/String;)V
+Ljavax/crypto/Cipher;->ATTRIBUTE_MODES:Ljava/lang/String;
+Ljavax/crypto/Cipher;->ATTRIBUTE_PADDINGS:Ljava/lang/String;
+Ljavax/crypto/Cipher;->checkCipherState()V
+Ljavax/crypto/Cipher;->checkOpmode(I)V
+Ljavax/crypto/Cipher;->chooseProvider(Ljavax/crypto/Cipher$InitType;ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/AlgorithmParameters;Ljava/security/SecureRandom;)V
+Ljavax/crypto/Cipher;->createCipher(Ljava/lang/String;Ljava/security/Provider;)Ljavax/crypto/Cipher;
+Ljavax/crypto/Cipher;->exmech:Ljavax/crypto/ExemptionMechanism;
+Ljavax/crypto/Cipher;->getAlgorithmParameterSpec(Ljava/security/AlgorithmParameters;)Ljava/security/spec/AlgorithmParameterSpec;
+Ljavax/crypto/Cipher;->getCurrentSpi()Ljavax/crypto/CipherSpi;
+Ljavax/crypto/Cipher;->getOpmodeString(I)Ljava/lang/String;
+Ljavax/crypto/Cipher;->initialized:Z
+Ljavax/crypto/Cipher;->KEY_USAGE_EXTENSION_OID:Ljava/lang/String;
+Ljavax/crypto/Cipher;->matchAttribute(Ljava/security/Provider$Service;Ljava/lang/String;Ljava/lang/String;)Z
+Ljavax/crypto/Cipher;->opmode:I
+Ljavax/crypto/Cipher;->provider:Ljava/security/Provider;
+Ljavax/crypto/Cipher;->spi:Ljavax/crypto/CipherSpi;
+Ljavax/crypto/Cipher;->spiAndProviderUpdater:Ljavax/crypto/Cipher$SpiAndProviderUpdater;
+Ljavax/crypto/Cipher;->tokenizedTransformation:[Ljava/lang/String;
+Ljavax/crypto/Cipher;->tokenizeTransformation(Ljava/lang/String;)[Ljava/lang/String;
+Ljavax/crypto/Cipher;->transformation:Ljava/lang/String;
+Ljavax/crypto/Cipher;->tryCombinations(Ljavax/crypto/Cipher$InitParams;Ljava/security/Provider;[Ljava/lang/String;)Ljavax/crypto/Cipher$CipherSpiAndProvider;
+Ljavax/crypto/Cipher;->tryTransformWithProvider(Ljavax/crypto/Cipher$InitParams;[Ljava/lang/String;Ljavax/crypto/Cipher$NeedToSet;Ljava/security/Provider$Service;)Ljavax/crypto/Cipher$CipherSpiAndProvider;
+Ljavax/crypto/Cipher;->updateProviderIfNeeded()V
+Ljavax/crypto/CipherInputStream;->cipher:Ljavax/crypto/Cipher;
+Ljavax/crypto/CipherInputStream;->closed:Z
+Ljavax/crypto/CipherInputStream;->done:Z
+Ljavax/crypto/CipherInputStream;->getMoreData()I
+Ljavax/crypto/CipherInputStream;->ibuffer:[B
+Ljavax/crypto/CipherInputStream;->input:Ljava/io/InputStream;
+Ljavax/crypto/CipherInputStream;->obuffer:[B
+Ljavax/crypto/CipherInputStream;->ofinish:I
+Ljavax/crypto/CipherInputStream;->ostart:I
+Ljavax/crypto/CipherOutputStream;->cipher:Ljavax/crypto/Cipher;
+Ljavax/crypto/CipherOutputStream;->closed:Z
+Ljavax/crypto/CipherOutputStream;->ibuffer:[B
+Ljavax/crypto/CipherOutputStream;->obuffer:[B
+Ljavax/crypto/CipherOutputStream;->output:Ljava/io/OutputStream;
+Ljavax/crypto/CipherSpi;->bufferCrypt(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;Z)I
+Ljavax/crypto/CipherSpi;->getTempArraySize(I)I
+Ljavax/crypto/EncryptedPrivateKeyInfo;->algid:Lsun/security/x509/AlgorithmId;
+Ljavax/crypto/EncryptedPrivateKeyInfo;->checkPKCS8Encoding([B)V
+Ljavax/crypto/EncryptedPrivateKeyInfo;->checkTag(Lsun/security/util/DerValue;BLjava/lang/String;)V
+Ljavax/crypto/EncryptedPrivateKeyInfo;->encoded:[B
+Ljavax/crypto/EncryptedPrivateKeyInfo;->encryptedData:[B
+Ljavax/crypto/EncryptedPrivateKeyInfo;->getKeySpecImpl(Ljava/security/Key;Ljava/security/Provider;)Ljava/security/spec/PKCS8EncodedKeySpec;
+Ljavax/crypto/ExemptionMechanism;->done:Z
+Ljavax/crypto/ExemptionMechanism;->exmechSpi:Ljavax/crypto/ExemptionMechanismSpi;
+Ljavax/crypto/ExemptionMechanism;->initialized:Z
+Ljavax/crypto/ExemptionMechanism;->keyStored:Ljava/security/Key;
+Ljavax/crypto/ExemptionMechanism;->mechanism:Ljava/lang/String;
+Ljavax/crypto/ExemptionMechanism;->provider:Ljava/security/Provider;
+Ljavax/crypto/KeyAgreement;-><init>(Ljava/lang/String;)V
+Ljavax/crypto/KeyAgreement;->algorithm:Ljava/lang/String;
+Ljavax/crypto/KeyAgreement;->chooseFirstProvider()V
+Ljavax/crypto/KeyAgreement;->chooseProvider(ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)V
+Ljavax/crypto/KeyAgreement;->implInit(Ljavax/crypto/KeyAgreementSpi;ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)V
+Ljavax/crypto/KeyAgreement;->I_NO_PARAMS:I
+Ljavax/crypto/KeyAgreement;->I_PARAMS:I
+Ljavax/crypto/KeyAgreement;->lock:Ljava/lang/Object;
+Ljavax/crypto/KeyAgreement;->provider:Ljava/security/Provider;
+Ljavax/crypto/KeyAgreement;->spi:Ljavax/crypto/KeyAgreementSpi;
+Ljavax/crypto/KeyAgreement;->warnCount:I
+Ljavax/crypto/KeyGenerator;-><init>(Ljava/lang/String;)V
+Ljavax/crypto/KeyGenerator;->algorithm:Ljava/lang/String;
+Ljavax/crypto/KeyGenerator;->disableFailover()V
+Ljavax/crypto/KeyGenerator;->initKeySize:I
+Ljavax/crypto/KeyGenerator;->initParams:Ljava/security/spec/AlgorithmParameterSpec;
+Ljavax/crypto/KeyGenerator;->initRandom:Ljava/security/SecureRandom;
+Ljavax/crypto/KeyGenerator;->initType:I
+Ljavax/crypto/KeyGenerator;->I_NONE:I
+Ljavax/crypto/KeyGenerator;->I_PARAMS:I
+Ljavax/crypto/KeyGenerator;->I_RANDOM:I
+Ljavax/crypto/KeyGenerator;->I_SIZE:I
+Ljavax/crypto/KeyGenerator;->lock:Ljava/lang/Object;
+Ljavax/crypto/KeyGenerator;->nextSpi(Ljavax/crypto/KeyGeneratorSpi;Z)Ljavax/crypto/KeyGeneratorSpi;
+Ljavax/crypto/KeyGenerator;->provider:Ljava/security/Provider;
+Ljavax/crypto/KeyGenerator;->serviceIterator:Ljava/util/Iterator;
+Ljavax/crypto/KeyGenerator;->spi:Ljavax/crypto/KeyGeneratorSpi;
+Ljavax/crypto/Mac;-><init>(Ljava/lang/String;)V
+Ljavax/crypto/Mac;->algorithm:Ljava/lang/String;
+Ljavax/crypto/Mac;->chooseFirstProvider()V
+Ljavax/crypto/Mac;->chooseProvider(Ljava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;)V
+Ljavax/crypto/Mac;->getCurrentSpi()Ljavax/crypto/MacSpi;
+Ljavax/crypto/Mac;->initialized:Z
+Ljavax/crypto/Mac;->lock:Ljava/lang/Object;
+Ljavax/crypto/Mac;->provider:Ljava/security/Provider;
+Ljavax/crypto/Mac;->spi:Ljavax/crypto/MacSpi;
+Ljavax/crypto/Mac;->warnCount:I
+Ljavax/crypto/SealedObject;->encryptedContent:[B
+Ljavax/crypto/SealedObject;->paramsAlg:Ljava/lang/String;
+Ljavax/crypto/SealedObject;->sealAlg:Ljava/lang/String;
+Ljavax/crypto/SealedObject;->unseal(Ljava/security/Key;Ljava/lang/String;)Ljava/lang/Object;
+Ljavax/crypto/SecretKeyFactory;-><init>(Ljava/lang/String;)V
+Ljavax/crypto/SecretKeyFactory;->algorithm:Ljava/lang/String;
+Ljavax/crypto/SecretKeyFactory;->lock:Ljava/lang/Object;
+Ljavax/crypto/SecretKeyFactory;->nextSpi(Ljavax/crypto/SecretKeyFactorySpi;)Ljavax/crypto/SecretKeyFactorySpi;
+Ljavax/crypto/SecretKeyFactory;->provider:Ljava/security/Provider;
+Ljavax/crypto/SecretKeyFactory;->serviceIterator:Ljava/util/Iterator;
+Ljavax/crypto/SecretKeyFactory;->spi:Ljavax/crypto/SecretKeyFactorySpi;
+Ljavax/crypto/spec/DESedeKeySpec;->key:[B
+Ljavax/crypto/spec/DESKeySpec;->key:[B
+Ljavax/crypto/spec/DESKeySpec;->WEAK_KEYS:[[B
+Ljavax/crypto/spec/DHGenParameterSpec;->exponentSize:I
+Ljavax/crypto/spec/DHGenParameterSpec;->primeSize:I
+Ljavax/crypto/spec/DHParameterSpec;->g:Ljava/math/BigInteger;
+Ljavax/crypto/spec/DHParameterSpec;->l:I
+Ljavax/crypto/spec/DHParameterSpec;->p:Ljava/math/BigInteger;
+Ljavax/crypto/spec/DHPrivateKeySpec;->g:Ljava/math/BigInteger;
+Ljavax/crypto/spec/DHPrivateKeySpec;->p:Ljava/math/BigInteger;
+Ljavax/crypto/spec/DHPrivateKeySpec;->x:Ljava/math/BigInteger;
+Ljavax/crypto/spec/DHPublicKeySpec;->g:Ljava/math/BigInteger;
+Ljavax/crypto/spec/DHPublicKeySpec;->p:Ljava/math/BigInteger;
+Ljavax/crypto/spec/DHPublicKeySpec;->y:Ljava/math/BigInteger;
+Ljavax/crypto/spec/GCMParameterSpec;->init(I[BII)V
+Ljavax/crypto/spec/GCMParameterSpec;->iv:[B
+Ljavax/crypto/spec/GCMParameterSpec;->tLen:I
+Ljavax/crypto/spec/IvParameterSpec;->iv:[B
+Ljavax/crypto/spec/OAEPParameterSpec;-><init>()V
+Ljavax/crypto/spec/OAEPParameterSpec;->mdName:Ljava/lang/String;
+Ljavax/crypto/spec/OAEPParameterSpec;->mgfName:Ljava/lang/String;
+Ljavax/crypto/spec/OAEPParameterSpec;->mgfSpec:Ljava/security/spec/AlgorithmParameterSpec;
+Ljavax/crypto/spec/OAEPParameterSpec;->pSrc:Ljavax/crypto/spec/PSource;
+Ljavax/crypto/spec/PBEKeySpec;->iterationCount:I
+Ljavax/crypto/spec/PBEKeySpec;->keyLength:I
+Ljavax/crypto/spec/PBEKeySpec;->password:[C
+Ljavax/crypto/spec/PBEKeySpec;->salt:[B
+Ljavax/crypto/spec/PBEParameterSpec;->iterationCount:I
+Ljavax/crypto/spec/PBEParameterSpec;->paramSpec:Ljava/security/spec/AlgorithmParameterSpec;
+Ljavax/crypto/spec/PBEParameterSpec;->salt:[B
+Ljavax/crypto/spec/PSource$PSpecified;->p:[B
+Ljavax/crypto/spec/PSource;->pSrcName:Ljava/lang/String;
+Ljavax/crypto/spec/RC2ParameterSpec;->effectiveKeyBits:I
+Ljavax/crypto/spec/RC2ParameterSpec;->iv:[B
+Ljavax/crypto/spec/RC5ParameterSpec;->iv:[B
+Ljavax/crypto/spec/RC5ParameterSpec;->rounds:I
+Ljavax/crypto/spec/RC5ParameterSpec;->version:I
+Ljavax/crypto/spec/RC5ParameterSpec;->wordSize:I
+Ljavax/crypto/spec/SecretKeySpec;->algorithm:Ljava/lang/String;
+Ljavax/crypto/spec/SecretKeySpec;->key:[B
+Ljavax/microedition/khronos/egl/EGLContext;->EGL_INSTANCE:Ljavax/microedition/khronos/egl/EGL;
+Ljavax/net/ServerSocketFactory;->theFactory:Ljavax/net/ServerSocketFactory;
+Ljavax/net/SocketFactory;->setDefault(Ljavax/net/SocketFactory;)V
+Ljavax/net/SocketFactory;->theFactory:Ljavax/net/SocketFactory;
+Ljavax/net/ssl/CertPathTrustManagerParameters;->parameters:Ljava/security/cert/CertPathParameters;
+Ljavax/net/ssl/HandshakeCompletedEvent;->session:Ljavax/net/ssl/SSLSession;
+Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder;-><init>()V
+Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder;->defaultHostnameVerifier:Ljavax/net/ssl/HostnameVerifier;
+Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder;->originalDefaultHostnameVerifierClass:Ljava/lang/Class;
+Ljavax/net/ssl/HttpsURLConnection;->defaultSSLSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
+Ljavax/net/ssl/HttpsURLConnection;->sslSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
+Ljavax/net/ssl/KeyManagerFactory;->algorithm:Ljava/lang/String;
+Ljavax/net/ssl/KeyManagerFactory;->factorySpi:Ljavax/net/ssl/KeyManagerFactorySpi;
+Ljavax/net/ssl/KeyManagerFactory;->provider:Ljava/security/Provider;
+Ljavax/net/ssl/KeyStoreBuilderParameters;->parameters:Ljava/util/List;
+Ljavax/net/ssl/SNIHostName$SNIHostNameMatcher;-><init>(Ljava/lang/String;)V
+Ljavax/net/ssl/SNIHostName$SNIHostNameMatcher;->pattern:Ljava/util/regex/Pattern;
+Ljavax/net/ssl/SNIHostName;->checkHostName()V
+Ljavax/net/ssl/SNIHostName;->hostname:Ljava/lang/String;
+Ljavax/net/ssl/SNIMatcher;->type:I
+Ljavax/net/ssl/SNIServerName;->encoded:[B
+Ljavax/net/ssl/SNIServerName;->HEXES:[C
+Ljavax/net/ssl/SNIServerName;->toHexString([B)Ljava/lang/String;
+Ljavax/net/ssl/SNIServerName;->type:I
+Ljavax/net/ssl/SSLContext;->contextSpi:Ljavax/net/ssl/SSLContextSpi;
+Ljavax/net/ssl/SSLContext;->defaultContext:Ljavax/net/ssl/SSLContext;
+Ljavax/net/ssl/SSLContext;->protocol:Ljava/lang/String;
+Ljavax/net/ssl/SSLContext;->provider:Ljava/security/Provider;
+Ljavax/net/ssl/SSLContextSpi;->getDefaultSocket()Ljavax/net/ssl/SSLSocket;
+Ljavax/net/ssl/SSLEngine;->peerHost:Ljava/lang/String;
+Ljavax/net/ssl/SSLEngine;->peerPort:I
+Ljavax/net/ssl/SSLEngineResult;->bytesConsumed:I
+Ljavax/net/ssl/SSLEngineResult;->bytesProduced:I
+Ljavax/net/ssl/SSLEngineResult;->handshakeStatus:Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;
+Ljavax/net/ssl/SSLEngineResult;->status:Ljavax/net/ssl/SSLEngineResult$Status;
+Ljavax/net/ssl/SSLParameters;->algorithmConstraints:Ljava/security/AlgorithmConstraints;
+Ljavax/net/ssl/SSLParameters;->cipherSuites:[Ljava/lang/String;
+Ljavax/net/ssl/SSLParameters;->clone([Ljava/lang/String;)[Ljava/lang/String;
+Ljavax/net/ssl/SSLParameters;->identificationAlgorithm:Ljava/lang/String;
+Ljavax/net/ssl/SSLParameters;->needClientAuth:Z
+Ljavax/net/ssl/SSLParameters;->preferLocalCipherSuites:Z
+Ljavax/net/ssl/SSLParameters;->protocols:[Ljava/lang/String;
+Ljavax/net/ssl/SSLParameters;->sniMatchers:Ljava/util/Map;
+Ljavax/net/ssl/SSLParameters;->sniNames:Ljava/util/Map;
+Ljavax/net/ssl/SSLParameters;->wantClientAuth:Z
+Ljavax/net/ssl/SSLServerSocketFactory;->lastVersion:I
+Ljavax/net/ssl/SSLServerSocketFactory;->log(Ljava/lang/String;)V
+Ljavax/net/ssl/SSLSessionBindingEvent;->name:Ljava/lang/String;
+Ljavax/net/ssl/SSLSocketFactory;->DEBUG:Z
+Ljavax/net/ssl/SSLSocketFactory;->getSecurityProperty(Ljava/lang/String;)Ljava/lang/String;
+Ljavax/net/ssl/SSLSocketFactory;->lastVersion:I
+Ljavax/net/ssl/SSLSocketFactory;->log(Ljava/lang/String;)V
+Ljavax/net/ssl/StandardConstants;-><init>()V
+Ljavax/net/ssl/TrustManagerFactory;->algorithm:Ljava/lang/String;
+Ljavax/net/ssl/TrustManagerFactory;->factorySpi:Ljavax/net/ssl/TrustManagerFactorySpi;
+Ljavax/net/ssl/TrustManagerFactory;->provider:Ljava/security/Provider;
+Ljavax/security/auth/callback/PasswordCallback;->echoOn:Z
+Ljavax/security/auth/callback/PasswordCallback;->inputPassword:[C
+Ljavax/security/auth/callback/PasswordCallback;->prompt:Ljava/lang/String;
+Ljavax/security/auth/callback/UnsupportedCallbackException;->callback:Ljavax/security/auth/callback/Callback;
+Ljavax/security/auth/PrivateCredentialPermission;-><init>(Ljava/lang/String;Ljava/util/Set;)V
+Ljavax/security/auth/Subject$AuthPermissionHolder;-><init>()V
+Ljavax/security/auth/Subject$AuthPermissionHolder;->DO_AS_PERMISSION:Ljavax/security/auth/AuthPermission;
+Ljavax/security/auth/Subject$AuthPermissionHolder;->DO_AS_PRIVILEGED_PERMISSION:Ljavax/security/auth/AuthPermission;
+Ljavax/security/auth/Subject$AuthPermissionHolder;->GET_SUBJECT_PERMISSION:Ljavax/security/auth/AuthPermission;
+Ljavax/security/auth/Subject$AuthPermissionHolder;->MODIFY_PRINCIPALS_PERMISSION:Ljavax/security/auth/AuthPermission;
+Ljavax/security/auth/Subject$AuthPermissionHolder;->MODIFY_PRIVATE_CREDENTIALS_PERMISSION:Ljavax/security/auth/AuthPermission;
+Ljavax/security/auth/Subject$AuthPermissionHolder;->MODIFY_PUBLIC_CREDENTIALS_PERMISSION:Ljavax/security/auth/AuthPermission;
+Ljavax/security/auth/Subject$AuthPermissionHolder;->SET_READ_ONLY_PERMISSION:Ljavax/security/auth/AuthPermission;
+Ljavax/security/auth/Subject$ClassSet;->add(Ljava/lang/Object;)Z
+Ljavax/security/auth/Subject$ClassSet;->c:Ljava/lang/Class;
+Ljavax/security/auth/Subject$ClassSet;->populateSet()V
+Ljavax/security/auth/Subject$ClassSet;->set:Ljava/util/Set;
+Ljavax/security/auth/Subject$ClassSet;->which:I
+Ljavax/security/auth/Subject$SecureSet;-><init>(Ljavax/security/auth/Subject;I)V
+Ljavax/security/auth/Subject$SecureSet;-><init>(Ljavax/security/auth/Subject;ILjava/util/Set;)V
+Ljavax/security/auth/Subject$SecureSet;->elements:Ljava/util/LinkedList;
+Ljavax/security/auth/Subject$SecureSet;->subject:Ljavax/security/auth/Subject;
+Ljavax/security/auth/Subject$SecureSet;->which:I
+Ljavax/security/auth/Subject;->createContext(Ljavax/security/auth/Subject;Ljava/security/AccessControlContext;)Ljava/security/AccessControlContext;
+Ljavax/security/auth/Subject;->getCredHashCode(Ljava/lang/Object;)I
+Ljavax/security/auth/Subject;->NULL_PD_ARRAY:[Ljava/security/ProtectionDomain;
+Ljavax/security/auth/Subject;->principals:Ljava/util/Set;
+Ljavax/security/auth/Subject;->PRINCIPAL_SET:I
+Ljavax/security/auth/Subject;->privCredentials:Ljava/util/Set;
+Ljavax/security/auth/Subject;->PRIV_CREDENTIAL_SET:I
+Ljavax/security/auth/Subject;->pubCredentials:Ljava/util/Set;
+Ljavax/security/auth/Subject;->PUB_CREDENTIAL_SET:I
+Ljavax/security/auth/Subject;->readOnly:Z
+Ljavax/security/auth/Subject;->toString(Z)Ljava/lang/String;
+Ljavax/security/auth/x500/X500Principal;-><init>(Lsun/security/x509/X500Name;)V
+Ljavax/security/auth/x500/X500Principal;->thisX500Name:Lsun/security/x509/X500Name;
+Ljavax/security/cert/X509Certificate;->DEFAULT_X509_CERT_CLASS:Ljava/lang/String;
+Ljavax/security/cert/X509Certificate;->getInst(Ljava/lang/Object;)Ljavax/security/cert/X509Certificate;
+Ljavax/security/cert/X509Certificate;->X509Provider:Ljava/lang/String;
+Ljavax/security/cert/X509Certificate;->X509_PROVIDER:Ljava/lang/String;
+Ljavax/sql/ConnectionEvent;->ex:Ljava/sql/SQLException;
+Ljavax/sql/StatementEvent;->exception:Ljava/sql/SQLException;
+Ljavax/sql/StatementEvent;->statement:Ljava/sql/PreparedStatement;
+Ljavax/xml/datatype/DatatypeConfigurationException;->causeOnJDK13OrBelow:Ljava/lang/Throwable;
+Ljavax/xml/datatype/DatatypeConfigurationException;->initCauseByReflection(Ljava/lang/Throwable;)V
+Ljavax/xml/datatype/DatatypeConfigurationException;->isJDK14OrAbove:Z
+Ljavax/xml/datatype/DatatypeConfigurationException;->printStackTrace0(Ljava/io/PrintWriter;)V
+Ljavax/xml/datatype/DatatypeConstants$Field;-><init>(Ljava/lang/String;I)V
+Ljavax/xml/datatype/DatatypeConstants$Field;->id:I
+Ljavax/xml/datatype/DatatypeConstants$Field;->str:Ljava/lang/String;
+Ljavax/xml/datatype/DatatypeConstants;-><init>()V
+Ljavax/xml/datatype/Duration;->getCalendarTimeInMillis(Ljava/util/Calendar;)J
+Ljavax/xml/datatype/Duration;->getFieldValueAsInt(Ljavax/xml/datatype/DatatypeConstants$Field;)I
+Ljavax/xml/datatype/Duration;->toString(Ljava/math/BigDecimal;)Ljava/lang/String;
+Ljavax/xml/namespace/QName;->compatibilitySerialVersionUID:J
+Ljavax/xml/namespace/QName;->defaultSerialVersionUID:J
+Ljavax/xml/namespace/QName;->localPart:Ljava/lang/String;
+Ljavax/xml/namespace/QName;->namespaceURI:Ljava/lang/String;
+Ljavax/xml/namespace/QName;->prefix:Ljava/lang/String;
+Ljavax/xml/namespace/QName;->qNameAsString:Ljava/lang/String;
+Ljavax/xml/parsers/DocumentBuilder;->DEBUG:Z
+Ljavax/xml/parsers/DocumentBuilderFactory;->coalescing:Z
+Ljavax/xml/parsers/DocumentBuilderFactory;->expandEntityRef:Z
+Ljavax/xml/parsers/DocumentBuilderFactory;->ignoreComments:Z
+Ljavax/xml/parsers/DocumentBuilderFactory;->namespaceAware:Z
+Ljavax/xml/parsers/DocumentBuilderFactory;->validating:Z
+Ljavax/xml/parsers/DocumentBuilderFactory;->whitespace:Z
+Ljavax/xml/parsers/FactoryConfigurationError;->exception:Ljava/lang/Exception;
+Ljavax/xml/parsers/SAXParser;->DEBUG:Z
+Ljavax/xml/parsers/SAXParserFactory;->namespaceAware:Z
+Ljavax/xml/parsers/SAXParserFactory;->validating:Z
+Ljavax/xml/transform/dom/DOMResult;->nextSibling:Lorg/w3c/dom/Node;
+Ljavax/xml/transform/dom/DOMResult;->node:Lorg/w3c/dom/Node;
+Ljavax/xml/transform/dom/DOMResult;->systemId:Ljava/lang/String;
+Ljavax/xml/transform/dom/DOMSource;->node:Lorg/w3c/dom/Node;
+Ljavax/xml/transform/dom/DOMSource;->systemID:Ljava/lang/String;
+Ljavax/xml/transform/OutputKeys;-><init>()V
+Ljavax/xml/transform/sax/SAXResult;->handler:Lorg/xml/sax/ContentHandler;
+Ljavax/xml/transform/sax/SAXResult;->lexhandler:Lorg/xml/sax/ext/LexicalHandler;
+Ljavax/xml/transform/sax/SAXResult;->systemId:Ljava/lang/String;
+Ljavax/xml/transform/sax/SAXSource;->inputSource:Lorg/xml/sax/InputSource;
+Ljavax/xml/transform/sax/SAXSource;->reader:Lorg/xml/sax/XMLReader;
+Ljavax/xml/transform/stream/StreamResult;->outputStream:Ljava/io/OutputStream;
+Ljavax/xml/transform/stream/StreamResult;->systemId:Ljava/lang/String;
+Ljavax/xml/transform/stream/StreamResult;->writer:Ljava/io/Writer;
+Ljavax/xml/transform/stream/StreamSource;->inputStream:Ljava/io/InputStream;
+Ljavax/xml/transform/stream/StreamSource;->publicId:Ljava/lang/String;
+Ljavax/xml/transform/stream/StreamSource;->reader:Ljava/io/Reader;
+Ljavax/xml/transform/stream/StreamSource;->systemId:Ljava/lang/String;
+Ljavax/xml/transform/TransformerException;->containedException:Ljava/lang/Throwable;
+Ljavax/xml/transform/TransformerException;->locator:Ljavax/xml/transform/SourceLocator;
+Ljavax/xml/transform/TransformerFactoryConfigurationError;->exception:Ljava/lang/Exception;
+Ljavax/xml/XMLConstants;-><init>()V
+Ljavax/xml/xpath/XPathConstants;-><init>()V
+Ljavax/xml/xpath/XPathException;->cause:Ljava/lang/Throwable;
+Llibcore/util/BasicLruCache;->maxSize:I
+Llibcore/util/BasicLruCache;->trimToSize(I)V
+Llibcore/util/NativeAllocationRegistry$CleanerRunner;-><init>(Lsun/misc/Cleaner;)V
+Llibcore/util/NativeAllocationRegistry$CleanerRunner;->cleaner:Lsun/misc/Cleaner;
+Llibcore/util/NativeAllocationRegistry$CleanerThunk;->nativePtr:J
+Llibcore/util/NativeAllocationRegistry$CleanerThunk;->setNativePtr(J)V
+Llibcore/util/NativeAllocationRegistry;->classLoader:Ljava/lang/ClassLoader;
+Llibcore/util/NativeAllocationRegistry;->freeFunction:J
+Llibcore/util/NativeAllocationRegistry;->registerNativeAllocation(J)V
+Llibcore/util/NativeAllocationRegistry;->registerNativeFree(J)V
+Llibcore/util/NativeAllocationRegistry;->size:J
+Llibcore/util/ZoneInfo$CheckedArithmeticException;-><init>()V
+Llibcore/util/ZoneInfo$OffsetInterval;-><init>(IIII)V
+Llibcore/util/ZoneInfo$OffsetInterval;->containsWallTime(J)Z
+Llibcore/util/ZoneInfo$OffsetInterval;->create(Llibcore/util/ZoneInfo;I)Llibcore/util/ZoneInfo$OffsetInterval;
+Llibcore/util/ZoneInfo$OffsetInterval;->endWallTimeSeconds:I
+Llibcore/util/ZoneInfo$OffsetInterval;->getEndWallTimeSeconds()J
+Llibcore/util/ZoneInfo$OffsetInterval;->getIsDst()I
+Llibcore/util/ZoneInfo$OffsetInterval;->getStartWallTimeSeconds()J
+Llibcore/util/ZoneInfo$OffsetInterval;->getTotalOffsetSeconds()I
+Llibcore/util/ZoneInfo$OffsetInterval;->isDst:I
+Llibcore/util/ZoneInfo$OffsetInterval;->startWallTimeSeconds:I
+Llibcore/util/ZoneInfo$OffsetInterval;->totalOffsetSeconds:I
+Llibcore/util/ZoneInfo$WallTime;->calendar:Ljava/util/GregorianCalendar;
+Llibcore/util/ZoneInfo$WallTime;->copyFieldsFromCalendar()V
+Llibcore/util/ZoneInfo$WallTime;->copyFieldsToCalendar()V
+Llibcore/util/ZoneInfo$WallTime;->doWallTimeSearch(Llibcore/util/ZoneInfo;IIZ)Ljava/lang/Integer;
+Llibcore/util/ZoneInfo$WallTime;->getOffsetsOfType(Llibcore/util/ZoneInfo;II)[I
+Llibcore/util/ZoneInfo$WallTime;->gmtOffsetSeconds:I
+Llibcore/util/ZoneInfo$WallTime;->hour:I
+Llibcore/util/ZoneInfo$WallTime;->isDst:I
+Llibcore/util/ZoneInfo$WallTime;->minute:I
+Llibcore/util/ZoneInfo$WallTime;->month:I
+Llibcore/util/ZoneInfo$WallTime;->monthDay:I
+Llibcore/util/ZoneInfo$WallTime;->second:I
+Llibcore/util/ZoneInfo$WallTime;->tryOffsetAdjustments(Llibcore/util/ZoneInfo;ILlibcore/util/ZoneInfo$OffsetInterval;II)Ljava/lang/Integer;
+Llibcore/util/ZoneInfo$WallTime;->weekDay:I
+Llibcore/util/ZoneInfo$WallTime;->year:I
+Llibcore/util/ZoneInfo$WallTime;->yearDay:I
+Llibcore/util/ZoneInfo;-><init>(Ljava/lang/String;[J[B[I[BJ)V
+Llibcore/util/ZoneInfo;->checkedAdd(JI)I
+Llibcore/util/ZoneInfo;->checkedSubtract(II)I
+Llibcore/util/ZoneInfo;->findOffsetIndexForTimeInMilliseconds(J)I
+Llibcore/util/ZoneInfo;->findOffsetIndexForTimeInSeconds(J)I
+Llibcore/util/ZoneInfo;->LEAP:[I
+Llibcore/util/ZoneInfo;->mDstSavings:I
+Llibcore/util/ZoneInfo;->mEarliestRawOffset:I
+Llibcore/util/ZoneInfo;->MILLISECONDS_PER_400_YEARS:J
+Llibcore/util/ZoneInfo;->MILLISECONDS_PER_DAY:J
+Llibcore/util/ZoneInfo;->mIsDsts:[B
+Llibcore/util/ZoneInfo;->mOffsets:[I
+Llibcore/util/ZoneInfo;->mRawOffset:I
+Llibcore/util/ZoneInfo;->mTypes:[B
+Llibcore/util/ZoneInfo;->mUseDst:Z
+Llibcore/util/ZoneInfo;->NORMAL:[I
+Llibcore/util/ZoneInfo;->roundDownMillisToSeconds(J)J
+Llibcore/util/ZoneInfo;->roundUpMillisToSeconds(J)J
+Llibcore/util/ZoneInfo;->UNIX_OFFSET:J
+Lorg/json/JSONArray;->checkedPut(Ljava/lang/Object;)V
+Lorg/json/JSONStringer$Scope;->DANGLING_KEY:Lorg/json/JSONStringer$Scope;
+Lorg/json/JSONStringer$Scope;->EMPTY_ARRAY:Lorg/json/JSONStringer$Scope;
+Lorg/json/JSONStringer$Scope;->EMPTY_OBJECT:Lorg/json/JSONStringer$Scope;
+Lorg/json/JSONStringer$Scope;->NONEMPTY_ARRAY:Lorg/json/JSONStringer$Scope;
+Lorg/json/JSONStringer$Scope;->NONEMPTY_OBJECT:Lorg/json/JSONStringer$Scope;
+Lorg/json/JSONStringer$Scope;->NULL:Lorg/json/JSONStringer$Scope;
+Lorg/json/JSONStringer$Scope;->valueOf(Ljava/lang/String;)Lorg/json/JSONStringer$Scope;
+Lorg/json/JSONStringer$Scope;->values()[Lorg/json/JSONStringer$Scope;
+Lorg/w3c/dom/ls/LSSerializer;->getFilter()Lorg/w3c/dom/ls/LSSerializerFilter;
+Lorg/w3c/dom/ls/LSSerializer;->setFilter(Lorg/w3c/dom/ls/LSSerializerFilter;)V
+Lorg/w3c/dom/traversal/NodeFilter;->FILTER_ACCEPT:S
+Lorg/w3c/dom/traversal/NodeFilter;->FILTER_REJECT:S
+Lorg/w3c/dom/traversal/NodeFilter;->FILTER_SKIP:S
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_ALL:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_ATTRIBUTE:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_CDATA_SECTION:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_COMMENT:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_DOCUMENT:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_DOCUMENT_FRAGMENT:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_DOCUMENT_TYPE:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_ELEMENT:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_ENTITY:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_ENTITY_REFERENCE:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_NOTATION:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_PROCESSING_INSTRUCTION:I
+Lorg/w3c/dom/traversal/NodeFilter;->SHOW_TEXT:I
+Lorg/w3c/dom/traversal/NodeIterator;->getExpandEntityReferences()Z
+Lorg/w3c/dom/traversal/NodeIterator;->getFilter()Lorg/w3c/dom/traversal/NodeFilter;
+Lorg/w3c/dom/traversal/NodeIterator;->getRoot()Lorg/w3c/dom/Node;
+Lorg/w3c/dom/traversal/NodeIterator;->getWhatToShow()I
+Lorg/w3c/dom/traversal/NodeIterator;->previousNode()Lorg/w3c/dom/Node;
+Lorg/xml/sax/helpers/AttributeListImpl;->names:Ljava/util/ArrayList;
+Lorg/xml/sax/helpers/AttributeListImpl;->types:Ljava/util/ArrayList;
+Lorg/xml/sax/helpers/AttributeListImpl;->values:Ljava/util/ArrayList;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->attributeNameTable:Ljava/util/Hashtable;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->clear()V
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->copyTables()V
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->declarations:Ljava/util/ArrayList;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->declarePrefix(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->declSeen:Z
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->declsOK:Z
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->defaultNS:Ljava/lang/String;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->elementNameTable:Ljava/util/Hashtable;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->getDeclaredPrefixes()Ljava/util/Enumeration;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->getPrefix(Ljava/lang/String;)Ljava/lang/String;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->getPrefixes()Ljava/util/Enumeration;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->getURI(Ljava/lang/String;)Ljava/lang/String;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->parent:Lorg/xml/sax/helpers/NamespaceSupport$Context;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->prefixTable:Ljava/util/Hashtable;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->processName(Ljava/lang/String;Z)[Ljava/lang/String;
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->setParent(Lorg/xml/sax/helpers/NamespaceSupport$Context;)V
+Lorg/xml/sax/helpers/NamespaceSupport$Context;->uriTable:Ljava/util/Hashtable;
+Lorg/xml/sax/helpers/ParserAdapter$AttributeListAdapter;->qAtts:Lorg/xml/sax/AttributeList;
+Lorg/xml/sax/helpers/ParserAdapter$AttributeListAdapter;->setAttributeList(Lorg/xml/sax/AttributeList;)V
+Lorg/xml/sax/helpers/ParserAdapter;->FEATURES:Ljava/lang/String;
+Lorg/xml/sax/helpers/ParserAdapter;->NAMESPACES:Ljava/lang/String;
+Lorg/xml/sax/helpers/ParserAdapter;->NAMESPACE_PREFIXES:Ljava/lang/String;
+Lorg/xml/sax/helpers/ParserAdapter;->XMLNS_URIs:Ljava/lang/String;
+Lorg/xml/sax/helpers/ParserFactory;-><init>()V
+Lorg/xml/sax/helpers/XMLReaderAdapter$AttributesAdapter;-><init>()V
+Lorg/xml/sax/helpers/XMLReaderAdapter$AttributesAdapter;->attributes:Lorg/xml/sax/Attributes;
+Lorg/xml/sax/helpers/XMLReaderAdapter$AttributesAdapter;->setAttributes(Lorg/xml/sax/Attributes;)V
+Lorg/xml/sax/helpers/XMLReaderFactory;-><init>()V
+Lorg/xml/sax/helpers/XMLReaderFactory;->property:Ljava/lang/String;
+Lorg/xmlpull/v1/XmlPullParserFactory;->getParserInstance()Lorg/xmlpull/v1/XmlPullParser;
+Lorg/xmlpull/v1/XmlPullParserFactory;->getSerializerInstance()Lorg/xmlpull/v1/XmlSerializer;
+Lorg/xmlpull/v1/XmlPullParserFactory;->newInstantiationException(Ljava/lang/String;Ljava/util/ArrayList;)Lorg/xmlpull/v1/XmlPullParserException;
+Lsun/misc/Cleaner;-><init>(Ljava/lang/Object;Ljava/lang/Runnable;)V
+Lsun/misc/Cleaner;->add(Lsun/misc/Cleaner;)Lsun/misc/Cleaner;
+Lsun/misc/Cleaner;->dummyQueue:Ljava/lang/ref/ReferenceQueue;
+Lsun/misc/Cleaner;->first:Lsun/misc/Cleaner;
+Lsun/misc/Cleaner;->next:Lsun/misc/Cleaner;
+Lsun/misc/Cleaner;->prev:Lsun/misc/Cleaner;
+Lsun/misc/Cleaner;->remove(Lsun/misc/Cleaner;)Z
+Lsun/misc/Cleaner;->thunk:Ljava/lang/Runnable;
+Lsun/misc/JarIndex;->addMapping(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/misc/JarIndex;->addToList(Ljava/lang/String;Ljava/lang/String;Ljava/util/HashMap;)V
+Lsun/misc/JarIndex;->indexMap:Ljava/util/HashMap;
+Lsun/misc/JarIndex;->jarFiles:[Ljava/lang/String;
+Lsun/misc/JarIndex;->jarMap:Ljava/util/HashMap;
+Lsun/misc/JarIndex;->metaInfFilenames:Z
+Lsun/misc/JarIndex;->parseJars([Ljava/lang/String;)V
+Lsun/misc/LRUCache;->oa:[Ljava/lang/Object;
+Lsun/misc/LRUCache;->size:I
+Lsun/misc/MetaIndex;-><init>(Ljava/util/List;Z)V
+Lsun/misc/MetaIndex;->contents:[Ljava/lang/String;
+Lsun/misc/MetaIndex;->getJarMap()Ljava/util/Map;
+Lsun/misc/MetaIndex;->isClassOnlyJar:Z
+Lsun/misc/MetaIndex;->jarMap:Ljava/util/Map;
+Lsun/misc/Resource;->cachedInputStream()Ljava/io/InputStream;
+Lsun/misc/Resource;->cis:Ljava/io/InputStream;
+Lsun/misc/Unsafe;-><init>()V
+Lsun/misc/Unsafe;->getArrayBaseOffsetForComponentType(Ljava/lang/Class;)I
+Lsun/misc/Unsafe;->getArrayIndexScaleForComponentType(Ljava/lang/Class;)I
+Lsun/misc/URLClassPath$FileLoader;-><init>(Ljava/net/URL;)V
+Lsun/misc/URLClassPath$FileLoader;->dir:Ljava/io/File;
+Lsun/misc/URLClassPath$FileLoader;->findResource(Ljava/lang/String;Z)Ljava/net/URL;
+Lsun/misc/URLClassPath$FileLoader;->getResource(Ljava/lang/String;Z)Lsun/misc/Resource;
+Lsun/misc/URLClassPath$JarLoader;-><init>(Ljava/net/URL;Ljava/net/URLStreamHandler;Ljava/util/HashMap;Ljava/security/AccessControlContext;)V
+Lsun/misc/URLClassPath$JarLoader;->acc:Ljava/security/AccessControlContext;
+Lsun/misc/URLClassPath$JarLoader;->checkJar(Ljava/util/jar/JarFile;)Ljava/util/jar/JarFile;
+Lsun/misc/URLClassPath$JarLoader;->checkResource(Ljava/lang/String;ZLjava/util/jar/JarEntry;)Lsun/misc/Resource;
+Lsun/misc/URLClassPath$JarLoader;->closed:Z
+Lsun/misc/URLClassPath$JarLoader;->csu:Ljava/net/URL;
+Lsun/misc/URLClassPath$JarLoader;->ensureOpen()V
+Lsun/misc/URLClassPath$JarLoader;->findResource(Ljava/lang/String;Z)Ljava/net/URL;
+Lsun/misc/URLClassPath$JarLoader;->getClassPath()[Ljava/net/URL;
+Lsun/misc/URLClassPath$JarLoader;->getIndex()Lsun/misc/JarIndex;
+Lsun/misc/URLClassPath$JarLoader;->getJarFile(Ljava/net/URL;)Ljava/util/jar/JarFile;
+Lsun/misc/URLClassPath$JarLoader;->getResource(Ljava/lang/String;Z)Lsun/misc/Resource;
+Lsun/misc/URLClassPath$JarLoader;->getResource(Ljava/lang/String;ZLjava/util/Set;)Lsun/misc/Resource;
+Lsun/misc/URLClassPath$JarLoader;->handler:Ljava/net/URLStreamHandler;
+Lsun/misc/URLClassPath$JarLoader;->index:Lsun/misc/JarIndex;
+Lsun/misc/URLClassPath$JarLoader;->isOptimizable(Ljava/net/URL;)Z
+Lsun/misc/URLClassPath$JarLoader;->jar:Ljava/util/jar/JarFile;
+Lsun/misc/URLClassPath$JarLoader;->lmap:Ljava/util/HashMap;
+Lsun/misc/URLClassPath$JarLoader;->metaIndex:Lsun/misc/MetaIndex;
+Lsun/misc/URLClassPath$JarLoader;->parseClassPath(Ljava/net/URL;Ljava/lang/String;)[Ljava/net/URL;
+Lsun/misc/URLClassPath$JarLoader;->parseExtensionsDependencies()V
+Lsun/misc/URLClassPath$JarLoader;->validIndex(Ljava/lang/String;)Z
+Lsun/misc/URLClassPath$Loader;-><init>(Ljava/net/URL;)V
+Lsun/misc/URLClassPath$Loader;->base:Ljava/net/URL;
+Lsun/misc/URLClassPath$Loader;->findResource(Ljava/lang/String;Z)Ljava/net/URL;
+Lsun/misc/URLClassPath$Loader;->getBaseURL()Ljava/net/URL;
+Lsun/misc/URLClassPath$Loader;->getClassPath()[Ljava/net/URL;
+Lsun/misc/URLClassPath$Loader;->getResource(Ljava/lang/String;)Lsun/misc/Resource;
+Lsun/misc/URLClassPath$Loader;->getResource(Ljava/lang/String;Z)Lsun/misc/Resource;
+Lsun/misc/URLClassPath$Loader;->jarfile:Ljava/util/jar/JarFile;
+Lsun/misc/URLClassPath;->acc:Ljava/security/AccessControlContext;
+Lsun/misc/URLClassPath;->check(Ljava/net/URL;)V
+Lsun/misc/URLClassPath;->closed:Z
+Lsun/misc/URLClassPath;->DEBUG:Z
+Lsun/misc/URLClassPath;->DEBUG_LOOKUP_CACHE:Z
+Lsun/misc/URLClassPath;->disableAllLookupCaches()V
+Lsun/misc/URLClassPath;->DISABLE_ACC_CHECKING:Z
+Lsun/misc/URLClassPath;->DISABLE_JAR_CHECKING:Z
+Lsun/misc/URLClassPath;->ensureLoaderOpened(I)Z
+Lsun/misc/URLClassPath;->getLoader(I)Lsun/misc/URLClassPath$Loader;
+Lsun/misc/URLClassPath;->getLoader(Ljava/net/URL;)Lsun/misc/URLClassPath$Loader;
+Lsun/misc/URLClassPath;->getLookupCache(Ljava/lang/String;)[I
+Lsun/misc/URLClassPath;->getLookupCacheForClassLoader(Ljava/lang/ClassLoader;Ljava/lang/String;)[I
+Lsun/misc/URLClassPath;->getLookupCacheURLs(Ljava/lang/ClassLoader;)[Ljava/net/URL;
+Lsun/misc/URLClassPath;->getNextLoader([II)Lsun/misc/URLClassPath$Loader;
+Lsun/misc/URLClassPath;->initLookupCache(Ljava/lang/ClassLoader;)V
+Lsun/misc/URLClassPath;->jarHandler:Ljava/net/URLStreamHandler;
+Lsun/misc/URLClassPath;->JAVA_VERSION:Ljava/lang/String;
+Lsun/misc/URLClassPath;->knownToNotExist(Ljava/lang/String;)Z
+Lsun/misc/URLClassPath;->knownToNotExist0(Ljava/lang/ClassLoader;Ljava/lang/String;)Z
+Lsun/misc/URLClassPath;->lookupCacheEnabled:Z
+Lsun/misc/URLClassPath;->lookupCacheLoader:Ljava/lang/ClassLoader;
+Lsun/misc/URLClassPath;->lookupCacheURLs:[Ljava/net/URL;
+Lsun/misc/URLClassPath;->path:Ljava/util/ArrayList;
+Lsun/misc/URLClassPath;->push([Ljava/net/URL;)V
+Lsun/misc/URLClassPath;->USER_AGENT_JAVA_VERSION:Ljava/lang/String;
+Lsun/misc/URLClassPath;->validateLookupCache(ILjava/lang/String;)V
+Lsun/security/pkcs/ContentInfo;->content:Lsun/security/util/DerValue;
+Lsun/security/pkcs/ContentInfo;->contentType:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/ContentInfo;->crdata:[I
+Lsun/security/pkcs/ContentInfo;->data:[I
+Lsun/security/pkcs/ContentInfo;->ddata:[I
+Lsun/security/pkcs/ContentInfo;->edata:[I
+Lsun/security/pkcs/ContentInfo;->nsdata:[I
+Lsun/security/pkcs/ContentInfo;->OLD_DATA:[I
+Lsun/security/pkcs/ContentInfo;->OLD_SDATA:[I
+Lsun/security/pkcs/ContentInfo;->pkcs7:[I
+Lsun/security/pkcs/ContentInfo;->sdata:[I
+Lsun/security/pkcs/ContentInfo;->sedata:[I
+Lsun/security/pkcs/ContentInfo;->tstInfo:[I
+Lsun/security/pkcs/PKCS7$VerbatimX509Certificate;-><init>(Ljava/security/cert/X509Certificate;[B)V
+Lsun/security/pkcs/PKCS7$VerbatimX509Certificate;->encodedVerbatim:[B
+Lsun/security/pkcs/PKCS7$WrappedX509Certificate;-><init>(Ljava/security/cert/X509Certificate;)V
+Lsun/security/pkcs/PKCS7$WrappedX509Certificate;->wrapped:Ljava/security/cert/X509Certificate;
+Lsun/security/pkcs/PKCS7;->certificates:[Ljava/security/cert/X509Certificate;
+Lsun/security/pkcs/PKCS7;->certIssuerNames:[Ljava/security/Principal;
+Lsun/security/pkcs/PKCS7;->contentInfo:Lsun/security/pkcs/ContentInfo;
+Lsun/security/pkcs/PKCS7;->contentType:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS7;->crls:[Ljava/security/cert/X509CRL;
+Lsun/security/pkcs/PKCS7;->digestAlgorithmIds:[Lsun/security/x509/AlgorithmId;
+Lsun/security/pkcs/PKCS7;->oldStyle:Z
+Lsun/security/pkcs/PKCS7;->parse(Lsun/security/util/DerInputStream;)V
+Lsun/security/pkcs/PKCS7;->parse(Lsun/security/util/DerInputStream;Z)V
+Lsun/security/pkcs/PKCS7;->parseNetscapeCertChain(Lsun/security/util/DerValue;)V
+Lsun/security/pkcs/PKCS7;->parseOldSignedData(Lsun/security/util/DerValue;)V
+Lsun/security/pkcs/PKCS7;->parseSignedData(Lsun/security/util/DerValue;)V
+Lsun/security/pkcs/PKCS7;->populateCertIssuerNames()V
+Lsun/security/pkcs/PKCS7;->signerInfos:[Lsun/security/pkcs/SignerInfo;
+Lsun/security/pkcs/PKCS7;->version:Ljava/math/BigInteger;
+Lsun/security/pkcs/PKCS9Attribute;->BYTE_ARRAY_CLASS:Ljava/lang/Class;
+Lsun/security/pkcs/PKCS9Attribute;->debug:Lsun/security/util/Debug;
+Lsun/security/pkcs/PKCS9Attribute;->index:I
+Lsun/security/pkcs/PKCS9Attribute;->indexOf(Ljava/lang/Object;[Ljava/lang/Object;I)I
+Lsun/security/pkcs/PKCS9Attribute;->init(Lsun/security/util/ObjectIdentifier;Ljava/lang/Object;)V
+Lsun/security/pkcs/PKCS9Attribute;->NAME_OID_TABLE:Ljava/util/Hashtable;
+Lsun/security/pkcs/PKCS9Attribute;->oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attribute;->OID_NAME_TABLE:Ljava/util/Hashtable;
+Lsun/security/pkcs/PKCS9Attribute;->PKCS9_OIDS:[Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attribute;->PKCS9_VALUE_TAGS:[[Ljava/lang/Byte;
+Lsun/security/pkcs/PKCS9Attribute;->RSA_PROPRIETARY_STR:Ljava/lang/String;
+Lsun/security/pkcs/PKCS9Attribute;->SINGLE_VALUED:[Z
+Lsun/security/pkcs/PKCS9Attribute;->SMIME_SIGNING_DESC_STR:Ljava/lang/String;
+Lsun/security/pkcs/PKCS9Attribute;->throwSingleValuedException()V
+Lsun/security/pkcs/PKCS9Attribute;->throwTagException(Ljava/lang/Byte;)V
+Lsun/security/pkcs/PKCS9Attribute;->value:Ljava/lang/Object;
+Lsun/security/pkcs/PKCS9Attribute;->VALUE_CLASSES:[Ljava/lang/Class;
+Lsun/security/pkcs/PKCS9Attributes;->attributes:Ljava/util/Hashtable;
+Lsun/security/pkcs/PKCS9Attributes;->castToDerEncoder([Ljava/lang/Object;)[Lsun/security/util/DerEncoder;
+Lsun/security/pkcs/PKCS9Attributes;->decode(Lsun/security/util/DerInputStream;)[B
+Lsun/security/pkcs/PKCS9Attributes;->derEncoding:[B
+Lsun/security/pkcs/PKCS9Attributes;->generateDerEncoding()[B
+Lsun/security/pkcs/PKCS9Attributes;->ignoreUnsupportedAttributes:Z
+Lsun/security/pkcs/PKCS9Attributes;->permittedAttributes:Ljava/util/Hashtable;
+Lsun/security/pkcs/SignerInfo;->authenticatedAttributes:Lsun/security/pkcs/PKCS9Attributes;
+Lsun/security/pkcs/SignerInfo;->certificateSerialNumber:Ljava/math/BigInteger;
+Lsun/security/pkcs/SignerInfo;->digestAlgorithmId:Lsun/security/x509/AlgorithmId;
+Lsun/security/pkcs/SignerInfo;->digestEncryptionAlgorithmId:Lsun/security/x509/AlgorithmId;
+Lsun/security/pkcs/SignerInfo;->DIGEST_PRIMITIVE_SET:Ljava/util/Set;
+Lsun/security/pkcs/SignerInfo;->encryptedDigest:[B
+Lsun/security/pkcs/SignerInfo;->hasTimestamp:Z
+Lsun/security/pkcs/SignerInfo;->issuerName:Lsun/security/x509/X500Name;
+Lsun/security/pkcs/SignerInfo;->JAR_DISABLED_CHECK:Lsun/security/util/DisabledAlgorithmConstraints;
+Lsun/security/pkcs/SignerInfo;->SIG_PRIMITIVE_SET:Ljava/util/Set;
+Lsun/security/pkcs/SignerInfo;->timestamp:Ljava/security/Timestamp;
+Lsun/security/pkcs/SignerInfo;->unauthenticatedAttributes:Lsun/security/pkcs/PKCS9Attributes;
+Lsun/security/pkcs/SignerInfo;->verify(Lsun/security/pkcs/PKCS7;)Lsun/security/pkcs/SignerInfo;
+Lsun/security/pkcs/SignerInfo;->verify(Lsun/security/pkcs/PKCS7;Ljava/io/InputStream;)Lsun/security/pkcs/SignerInfo;
+Lsun/security/pkcs/SignerInfo;->verify(Lsun/security/pkcs/PKCS7;[B)Lsun/security/pkcs/SignerInfo;
+Lsun/security/pkcs/SignerInfo;->verifyTimestamp(Lsun/security/timestamp/TimestampToken;)V
+Lsun/security/pkcs/SignerInfo;->version:Ljava/math/BigInteger;
+Lsun/security/util/AbstractAlgorithmConstraints;->checkAlgorithm([Ljava/lang/String;Ljava/lang/String;Lsun/security/util/AlgorithmDecomposer;)Z
+Lsun/security/util/AbstractAlgorithmConstraints;->getAlgorithms(Ljava/lang/String;)[Ljava/lang/String;
+Lsun/security/util/AlgorithmDecomposer;->decomposeImpl(Ljava/lang/String;)Ljava/util/Set;
+Lsun/security/util/AlgorithmDecomposer;->hasLoop(Ljava/util/Set;Ljava/lang/String;Ljava/lang/String;)V
+Lsun/security/util/AlgorithmDecomposer;->pattern:Ljava/util/regex/Pattern;
+Lsun/security/util/AlgorithmDecomposer;->transPattern:Ljava/util/regex/Pattern;
+Lsun/security/util/BitArray;-><init>(Lsun/security/util/BitArray;)V
+Lsun/security/util/BitArray;->BITS_PER_UNIT:I
+Lsun/security/util/BitArray;->BYTES_PER_LINE:I
+Lsun/security/util/BitArray;->length:I
+Lsun/security/util/BitArray;->NYBBLE:[[B
+Lsun/security/util/BitArray;->position(I)I
+Lsun/security/util/BitArray;->repn:[B
+Lsun/security/util/BitArray;->subscript(I)I
+Lsun/security/util/CertConstraintParameters;->cert:Ljava/security/cert/X509Certificate;
+Lsun/security/util/CertConstraintParameters;->trustedMatch:Z
+Lsun/security/util/Debug;->args:Ljava/lang/String;
+Lsun/security/util/Debug;->hexDigits:[C
+Lsun/security/util/Debug;->marshal(Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/util/Debug;->prefix:Ljava/lang/String;
+Lsun/security/util/DerInputBuffer;-><init>([B)V
+Lsun/security/util/DerInputBuffer;-><init>([BII)V
+Lsun/security/util/DerInputBuffer;->dup()Lsun/security/util/DerInputBuffer;
+Lsun/security/util/DerInputBuffer;->equals(Lsun/security/util/DerInputBuffer;)Z
+Lsun/security/util/DerInputBuffer;->getBigInteger(IZ)Ljava/math/BigInteger;
+Lsun/security/util/DerInputBuffer;->getBitString()[B
+Lsun/security/util/DerInputBuffer;->getBitString(I)[B
+Lsun/security/util/DerInputBuffer;->getGeneralizedTime(I)Ljava/util/Date;
+Lsun/security/util/DerInputBuffer;->getInteger(I)I
+Lsun/security/util/DerInputBuffer;->getPos()I
+Lsun/security/util/DerInputBuffer;->getSlice(II)[B
+Lsun/security/util/DerInputBuffer;->getTime(IZ)Ljava/util/Date;
+Lsun/security/util/DerInputBuffer;->getUnalignedBitString()Lsun/security/util/BitArray;
+Lsun/security/util/DerInputBuffer;->getUTCTime(I)Ljava/util/Date;
+Lsun/security/util/DerInputBuffer;->peek()I
+Lsun/security/util/DerInputBuffer;->toByteArray()[B
+Lsun/security/util/DerInputBuffer;->truncate(I)V
+Lsun/security/util/DerInputStream;-><init>(Lsun/security/util/DerInputBuffer;)V
+Lsun/security/util/DerInputStream;->buffer:Lsun/security/util/DerInputBuffer;
+Lsun/security/util/DerInputStream;->getByte()I
+Lsun/security/util/DerInputStream;->getLength()I
+Lsun/security/util/DerInputStream;->getLength(ILjava/io/InputStream;)I
+Lsun/security/util/DerInputStream;->getLength(Ljava/io/InputStream;)I
+Lsun/security/util/DerInputStream;->init([BIIZ)V
+Lsun/security/util/DerInputStream;->readString(BLjava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/util/DerOutputStream;->lexOrder:Lsun/security/util/ByteArrayLexOrder;
+Lsun/security/util/DerOutputStream;->putIntegerContents(I)V
+Lsun/security/util/DerOutputStream;->putOrderedSet(B[Lsun/security/util/DerEncoder;Ljava/util/Comparator;)V
+Lsun/security/util/DerOutputStream;->putTime(Ljava/util/Date;B)V
+Lsun/security/util/DerOutputStream;->tagOrder:Lsun/security/util/ByteArrayTagOrder;
+Lsun/security/util/DerOutputStream;->writeString(Ljava/lang/String;BLjava/lang/String;)V
+Lsun/security/util/DerValue;-><init>(Lsun/security/util/DerInputBuffer;Z)V
+Lsun/security/util/DerValue;->append([B[B)[B
+Lsun/security/util/DerValue;->doEquals(Lsun/security/util/DerValue;Lsun/security/util/DerValue;)Z
+Lsun/security/util/DerValue;->init(BLjava/lang/String;)Lsun/security/util/DerInputStream;
+Lsun/security/util/DerValue;->init(ZLjava/io/InputStream;)Lsun/security/util/DerInputStream;
+Lsun/security/util/DerValue;->isPrivate()Z
+Lsun/security/util/DerValue;->length:I
+Lsun/security/util/DerValue;->originalEncodedForm:[B
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;->EQ:Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;->GE:Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;->GT:Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;->LE:Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;->LT:Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;->NE:Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;->of(Ljava/lang/String;)Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;->valueOf(Ljava/lang/String;)Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;->values()[Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint;-><init>()V
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint;->algorithm:Ljava/lang/String;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint;->nextConstraint:Lsun/security/util/DisabledAlgorithmConstraints$Constraint;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint;->permits(Ljava/security/Key;)Z
+Lsun/security/util/DisabledAlgorithmConstraints$Constraint;->permits(Lsun/security/util/CertConstraintParameters;)V
+Lsun/security/util/DisabledAlgorithmConstraints$Constraints;-><init>([Ljava/lang/String;)V
+Lsun/security/util/DisabledAlgorithmConstraints$Constraints;->constraintsMap:Ljava/util/Map;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraints;->getConstraints(Ljava/lang/String;)Ljava/util/Set;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraints;->keySizePattern:Ljava/util/regex/Pattern;
+Lsun/security/util/DisabledAlgorithmConstraints$Constraints;->permits(Ljava/security/Key;)Z
+Lsun/security/util/DisabledAlgorithmConstraints$Constraints;->permits(Lsun/security/util/CertConstraintParameters;)V
+Lsun/security/util/DisabledAlgorithmConstraints$jdkCAConstraint;-><init>(Ljava/lang/String;)V
+Lsun/security/util/DisabledAlgorithmConstraints$jdkCAConstraint;->permits(Lsun/security/util/CertConstraintParameters;)V
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;-><init>(Ljava/lang/String;Lsun/security/util/DisabledAlgorithmConstraints$Constraint$Operator;I)V
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;->maxSize:I
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;->minSize:I
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;->permits(Ljava/security/Key;)Z
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;->permits(Lsun/security/util/CertConstraintParameters;)V
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;->permitsImpl(Ljava/security/Key;)Z
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;->prohibitedSize:I
+Lsun/security/util/DisabledAlgorithmConstraints;->algorithmConstraints:Lsun/security/util/DisabledAlgorithmConstraints$Constraints;
+Lsun/security/util/DisabledAlgorithmConstraints;->checkConstraints(Ljava/util/Set;Ljava/lang/String;Ljava/security/Key;Ljava/security/AlgorithmParameters;)Z
+Lsun/security/util/DisabledAlgorithmConstraints;->checkConstraints(Ljava/util/Set;Lsun/security/util/CertConstraintParameters;)V
+Lsun/security/util/DisabledAlgorithmConstraints;->debug:Lsun/security/util/Debug;
+Lsun/security/util/DisabledAlgorithmConstraints;->disabledAlgorithms:[Ljava/lang/String;
+Lsun/security/util/ManifestDigester$Entry;->doOldStyle(Ljava/security/MessageDigest;[BII)V
+Lsun/security/util/ManifestDigester$Entry;->length:I
+Lsun/security/util/ManifestDigester$Entry;->lengthWithBlankLine:I
+Lsun/security/util/ManifestDigester$Entry;->offset:I
+Lsun/security/util/ManifestDigester$Entry;->oldStyle:Z
+Lsun/security/util/ManifestDigester$Entry;->rawBytes:[B
+Lsun/security/util/ManifestDigester$Position;-><init>()V
+Lsun/security/util/ManifestDigester$Position;->endOfFirstLine:I
+Lsun/security/util/ManifestDigester$Position;->endOfSection:I
+Lsun/security/util/ManifestDigester$Position;->startOfNext:I
+Lsun/security/util/ManifestDigester;->entries:Ljava/util/HashMap;
+Lsun/security/util/ManifestDigester;->findSection(ILsun/security/util/ManifestDigester$Position;)Z
+Lsun/security/util/ManifestDigester;->isNameAttr([BI)Z
+Lsun/security/util/ManifestDigester;->rawBytes:[B
+Lsun/security/util/ManifestEntryVerifier$SunProviderHolder;-><init>()V
+Lsun/security/util/ManifestEntryVerifier$SunProviderHolder;->instance:Ljava/security/Provider;
+Lsun/security/util/ManifestEntryVerifier;->createdDigests:Ljava/util/HashMap;
+Lsun/security/util/ManifestEntryVerifier;->debug:Lsun/security/util/Debug;
+Lsun/security/util/ManifestEntryVerifier;->digests:Ljava/util/ArrayList;
+Lsun/security/util/ManifestEntryVerifier;->entry:Ljava/util/jar/JarEntry;
+Lsun/security/util/ManifestEntryVerifier;->hexc:[C
+Lsun/security/util/ManifestEntryVerifier;->man:Ljava/util/jar/Manifest;
+Lsun/security/util/ManifestEntryVerifier;->manifestHashes:Ljava/util/ArrayList;
+Lsun/security/util/ManifestEntryVerifier;->name:Ljava/lang/String;
+Lsun/security/util/ManifestEntryVerifier;->signers:[Ljava/security/CodeSigner;
+Lsun/security/util/ManifestEntryVerifier;->skip:Z
+Lsun/security/util/ManifestEntryVerifier;->toHex([B)Ljava/lang/String;
+Lsun/security/util/ObjectIdentifier$HugeOidNotSupportedByOldJDK;-><init>()V
+Lsun/security/util/ObjectIdentifier$HugeOidNotSupportedByOldJDK;->theOne:Lsun/security/util/ObjectIdentifier$HugeOidNotSupportedByOldJDK;
+Lsun/security/util/ObjectIdentifier;-><init>(Lsun/security/util/DerInputBuffer;)V
+Lsun/security/util/ObjectIdentifier;->check([B)V
+Lsun/security/util/ObjectIdentifier;->checkCount(I)V
+Lsun/security/util/ObjectIdentifier;->checkFirstComponent(I)V
+Lsun/security/util/ObjectIdentifier;->checkFirstComponent(Ljava/math/BigInteger;)V
+Lsun/security/util/ObjectIdentifier;->checkOtherComponent(II)V
+Lsun/security/util/ObjectIdentifier;->checkOtherComponent(ILjava/math/BigInteger;)V
+Lsun/security/util/ObjectIdentifier;->checkSecondComponent(II)V
+Lsun/security/util/ObjectIdentifier;->checkSecondComponent(ILjava/math/BigInteger;)V
+Lsun/security/util/ObjectIdentifier;->componentLen:I
+Lsun/security/util/ObjectIdentifier;->components:Ljava/lang/Object;
+Lsun/security/util/ObjectIdentifier;->componentsCalculated:Z
+Lsun/security/util/ObjectIdentifier;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/util/ObjectIdentifier;->encoding:[B
+Lsun/security/util/ObjectIdentifier;->init([II)V
+Lsun/security/util/ObjectIdentifier;->pack([BIIII)[B
+Lsun/security/util/ObjectIdentifier;->pack7Oid(I[BI)I
+Lsun/security/util/ObjectIdentifier;->pack7Oid(Ljava/math/BigInteger;[BI)I
+Lsun/security/util/ObjectIdentifier;->pack7Oid([BII[BI)I
+Lsun/security/util/ObjectIdentifier;->pack8([BII[BI)I
+Lsun/security/util/ObjectIdentifier;->stringForm:Ljava/lang/String;
+Lsun/security/util/SignatureFileVerifier;->ATTR_DIGEST:Ljava/lang/String;
+Lsun/security/util/SignatureFileVerifier;->block:Lsun/security/pkcs/PKCS7;
+Lsun/security/util/SignatureFileVerifier;->certificateFactory:Ljava/security/cert/CertificateFactory;
+Lsun/security/util/SignatureFileVerifier;->contains([Ljava/security/CodeSigner;Ljava/security/CodeSigner;)Z
+Lsun/security/util/SignatureFileVerifier;->createdDigests:Ljava/util/HashMap;
+Lsun/security/util/SignatureFileVerifier;->debug:Lsun/security/util/Debug;
+Lsun/security/util/SignatureFileVerifier;->DIGEST_PRIMITIVE_SET:Ljava/util/Set;
+Lsun/security/util/SignatureFileVerifier;->getDigest(Ljava/lang/String;)Ljava/security/MessageDigest;
+Lsun/security/util/SignatureFileVerifier;->getSigners([Lsun/security/pkcs/SignerInfo;Lsun/security/pkcs/PKCS7;)[Ljava/security/CodeSigner;
+Lsun/security/util/SignatureFileVerifier;->hexc:[C
+Lsun/security/util/SignatureFileVerifier;->isSubSet([Ljava/security/CodeSigner;[Ljava/security/CodeSigner;)Z
+Lsun/security/util/SignatureFileVerifier;->JAR_DISABLED_CHECK:Lsun/security/util/DisabledAlgorithmConstraints;
+Lsun/security/util/SignatureFileVerifier;->matches([Ljava/security/CodeSigner;[Ljava/security/CodeSigner;[Ljava/security/CodeSigner;)Z
+Lsun/security/util/SignatureFileVerifier;->md:Lsun/security/util/ManifestDigester;
+Lsun/security/util/SignatureFileVerifier;->name:Ljava/lang/String;
+Lsun/security/util/SignatureFileVerifier;->processImpl(Ljava/util/Hashtable;Ljava/util/List;)V
+Lsun/security/util/SignatureFileVerifier;->sfBytes:[B
+Lsun/security/util/SignatureFileVerifier;->signerCache:Ljava/util/ArrayList;
+Lsun/security/util/SignatureFileVerifier;->toHex([B)Ljava/lang/String;
+Lsun/security/util/SignatureFileVerifier;->updateSigners([Ljava/security/CodeSigner;Ljava/util/Hashtable;Ljava/lang/String;)V
+Lsun/security/util/SignatureFileVerifier;->verifyManifestHash(Ljava/util/jar/Manifest;Lsun/security/util/ManifestDigester;Ljava/util/List;)Z
+Lsun/security/util/SignatureFileVerifier;->verifyManifestMainAttrs(Ljava/util/jar/Manifest;Lsun/security/util/ManifestDigester;)Z
+Lsun/security/util/SignatureFileVerifier;->verifySection(Ljava/util/jar/Attributes;Ljava/lang/String;Lsun/security/util/ManifestDigester;)Z
+Lsun/security/util/SignatureFileVerifier;->workaround:Z
+Lsun/security/x509/AlgorithmId;-><init>(Lsun/security/util/ObjectIdentifier;Lsun/security/util/DerValue;)V
+Lsun/security/x509/AlgorithmId;->algid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->algOID(Ljava/lang/String;)Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->algParams:Ljava/security/AlgorithmParameters;
+Lsun/security/x509/AlgorithmId;->constructedFromDer:Z
+Lsun/security/x509/AlgorithmId;->DH_data:[I
+Lsun/security/x509/AlgorithmId;->DH_PKIX_data:[I
+Lsun/security/x509/AlgorithmId;->dsaWithSHA1_PKIX_data:[I
+Lsun/security/x509/AlgorithmId;->DSA_OIW_data:[I
+Lsun/security/x509/AlgorithmId;->DSA_PKIX_data:[I
+Lsun/security/x509/AlgorithmId;->initOidTableVersion:I
+Lsun/security/x509/AlgorithmId;->md2WithRSAEncryption_data:[I
+Lsun/security/x509/AlgorithmId;->md5WithRSAEncryption_data:[I
+Lsun/security/x509/AlgorithmId;->nameTable:Ljava/util/Map;
+Lsun/security/x509/AlgorithmId;->oidTable:Ljava/util/Map;
+Lsun/security/x509/AlgorithmId;->reinitializeMappingTableLocked()V
+Lsun/security/x509/AlgorithmId;->RSAEncryption_data:[I
+Lsun/security/x509/AlgorithmId;->RSA_data:[I
+Lsun/security/x509/AlgorithmId;->sha1WithDSA_OIW_data:[I
+Lsun/security/x509/AlgorithmId;->sha1WithRSAEncryption_data:[I
+Lsun/security/x509/AlgorithmId;->sha1WithRSAEncryption_OIW_data:[I
+Lsun/security/x509/AlgorithmId;->sha224WithRSAEncryption_data:[I
+Lsun/security/x509/AlgorithmId;->sha256WithRSAEncryption_data:[I
+Lsun/security/x509/AlgorithmId;->sha384WithRSAEncryption_data:[I
+Lsun/security/x509/AlgorithmId;->sha512WithRSAEncryption_data:[I
+Lsun/security/x509/AlgorithmId;->shaWithDSA_OIW_data:[I
+Lsun/security/x509/AVA;-><init>(Ljava/io/Reader;)V
+Lsun/security/x509/AVA;-><init>(Ljava/io/Reader;I)V
+Lsun/security/x509/AVA;-><init>(Ljava/io/Reader;ILjava/util/Map;)V
+Lsun/security/x509/AVA;-><init>(Ljava/io/Reader;Ljava/util/Map;)V
+Lsun/security/x509/AVA;-><init>(Lsun/security/util/DerInputStream;)V
+Lsun/security/x509/AVA;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/AVA;->debug:Lsun/security/util/Debug;
+Lsun/security/x509/AVA;->DEFAULT:I
+Lsun/security/x509/AVA;->escapedDefault:Ljava/lang/String;
+Lsun/security/x509/AVA;->getEmbeddedHexPair(ILjava/io/Reader;)Ljava/lang/Byte;
+Lsun/security/x509/AVA;->getEmbeddedHexString(Ljava/util/List;)Ljava/lang/String;
+Lsun/security/x509/AVA;->hexDigits:Ljava/lang/String;
+Lsun/security/x509/AVA;->isDerString(Lsun/security/util/DerValue;Z)Z
+Lsun/security/x509/AVA;->isTerminator(II)Z
+Lsun/security/x509/AVA;->oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AVA;->parseHexString(Ljava/io/Reader;I)Lsun/security/util/DerValue;
+Lsun/security/x509/AVA;->parseQuotedString(Ljava/io/Reader;Ljava/lang/StringBuilder;)Lsun/security/util/DerValue;
+Lsun/security/x509/AVA;->parseString(Ljava/io/Reader;IILjava/lang/StringBuilder;)Lsun/security/util/DerValue;
+Lsun/security/x509/AVA;->PRESERVE_OLD_DC_ENCODING:Z
+Lsun/security/x509/AVA;->readChar(Ljava/io/Reader;Ljava/lang/String;)I
+Lsun/security/x509/AVA;->RFC1779:I
+Lsun/security/x509/AVA;->RFC2253:I
+Lsun/security/x509/AVA;->specialChars1779:Ljava/lang/String;
+Lsun/security/x509/AVA;->specialChars2253:Ljava/lang/String;
+Lsun/security/x509/AVA;->specialCharsDefault:Ljava/lang/String;
+Lsun/security/x509/AVA;->toKeyword(ILjava/util/Map;)Ljava/lang/String;
+Lsun/security/x509/AVA;->toKeywordValueString(Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/x509/AVA;->trailingSpace(Ljava/io/Reader;)Z
+Lsun/security/x509/AVA;->value:Lsun/security/util/DerValue;
+Lsun/security/x509/CertificatePolicyId;->id:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/CertificatePolicySet;->ids:Ljava/util/Vector;
+Lsun/security/x509/Extension;->hashMagic:I
+Lsun/security/x509/GeneralName;->name:Lsun/security/x509/GeneralNameInterface;
+Lsun/security/x509/GeneralSubtree;->maximum:I
+Lsun/security/x509/GeneralSubtree;->minimum:I
+Lsun/security/x509/GeneralSubtree;->MIN_DEFAULT:I
+Lsun/security/x509/GeneralSubtree;->myhash:I
+Lsun/security/x509/GeneralSubtree;->name:Lsun/security/x509/GeneralName;
+Lsun/security/x509/GeneralSubtree;->TAG_MAX:B
+Lsun/security/x509/GeneralSubtree;->TAG_MIN:B
+Lsun/security/x509/GeneralSubtrees;-><init>(Lsun/security/x509/GeneralSubtrees;)V
+Lsun/security/x509/GeneralSubtrees;->createWidestSubtree(Lsun/security/x509/GeneralNameInterface;)Lsun/security/x509/GeneralSubtree;
+Lsun/security/x509/GeneralSubtrees;->getGeneralNameInterface(I)Lsun/security/x509/GeneralNameInterface;
+Lsun/security/x509/GeneralSubtrees;->getGeneralNameInterface(Lsun/security/x509/GeneralSubtree;)Lsun/security/x509/GeneralNameInterface;
+Lsun/security/x509/GeneralSubtrees;->minimize()V
+Lsun/security/x509/GeneralSubtrees;->NAME_DIFF_TYPE:I
+Lsun/security/x509/GeneralSubtrees;->NAME_MATCH:I
+Lsun/security/x509/GeneralSubtrees;->NAME_NARROWS:I
+Lsun/security/x509/GeneralSubtrees;->NAME_SAME_TYPE:I
+Lsun/security/x509/GeneralSubtrees;->NAME_WIDENS:I
+Lsun/security/x509/GeneralSubtrees;->trees:Ljava/util/List;
+Lsun/security/x509/NameConstraintsExtension;->calcMinMax()V
+Lsun/security/x509/NameConstraintsExtension;->encodeThis()V
+Lsun/security/x509/NameConstraintsExtension;->excluded:Lsun/security/x509/GeneralSubtrees;
+Lsun/security/x509/NameConstraintsExtension;->hasMax:Z
+Lsun/security/x509/NameConstraintsExtension;->hasMin:Z
+Lsun/security/x509/NameConstraintsExtension;->minMaxValid:Z
+Lsun/security/x509/NameConstraintsExtension;->permitted:Lsun/security/x509/GeneralSubtrees;
+Lsun/security/x509/NameConstraintsExtension;->TAG_EXCLUDED:B
+Lsun/security/x509/NameConstraintsExtension;->TAG_PERMITTED:B
+Lsun/security/x509/RDN;-><init>(I)V
+Lsun/security/x509/RDN;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/security/x509/RDN;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)V
+Lsun/security/x509/RDN;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/RDN;->assertion:[Lsun/security/x509/AVA;
+Lsun/security/x509/RDN;->avaList:Ljava/util/List;
+Lsun/security/x509/RDN;->canonicalString:Ljava/lang/String;
+Lsun/security/x509/RDN;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/x509/RDN;->findAttribute(Lsun/security/util/ObjectIdentifier;)Lsun/security/util/DerValue;
+Lsun/security/x509/RDN;->toRFC2253StringInternal(ZLjava/util/Map;)Ljava/lang/String;
+Lsun/security/x509/X500Name;->allAvaList:Ljava/util/List;
+Lsun/security/x509/X500Name;->canonicalDn:Ljava/lang/String;
+Lsun/security/x509/X500Name;->checkNoNewLinesNorTabsAtBeginningOfDN(Ljava/lang/String;)V
+Lsun/security/x509/X500Name;->commonName_data:[I
+Lsun/security/x509/X500Name;->countQuotes(Ljava/lang/String;II)I
+Lsun/security/x509/X500Name;->countryName_data:[I
+Lsun/security/x509/X500Name;->dn:Ljava/lang/String;
+Lsun/security/x509/X500Name;->DNQUALIFIER_DATA:[I
+Lsun/security/x509/X500Name;->DOMAIN_COMPONENT_DATA:[I
+Lsun/security/x509/X500Name;->encoded:[B
+Lsun/security/x509/X500Name;->escaped(IILjava/lang/String;)Z
+Lsun/security/x509/X500Name;->findAttribute(Lsun/security/util/ObjectIdentifier;)Lsun/security/util/DerValue;
+Lsun/security/x509/X500Name;->generateDN()V
+Lsun/security/x509/X500Name;->generateRFC1779DN(Ljava/util/Map;)Ljava/lang/String;
+Lsun/security/x509/X500Name;->generateRFC2253DN(Ljava/util/Map;)Ljava/lang/String;
+Lsun/security/x509/X500Name;->GENERATIONQUALIFIER_DATA:[I
+Lsun/security/x509/X500Name;->getString(Lsun/security/util/DerValue;)Ljava/lang/String;
+Lsun/security/x509/X500Name;->GIVENNAME_DATA:[I
+Lsun/security/x509/X500Name;->INITIALS_DATA:[I
+Lsun/security/x509/X500Name;->intern(Lsun/security/util/ObjectIdentifier;)Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->internedOIDs:Ljava/util/Map;
+Lsun/security/x509/X500Name;->ipAddress_data:[I
+Lsun/security/x509/X500Name;->isWithinSubtree(Lsun/security/x509/X500Name;)Z
+Lsun/security/x509/X500Name;->localityName_data:[I
+Lsun/security/x509/X500Name;->names:[Lsun/security/x509/RDN;
+Lsun/security/x509/X500Name;->orgName_data:[I
+Lsun/security/x509/X500Name;->orgUnitName_data:[I
+Lsun/security/x509/X500Name;->parseDER(Lsun/security/util/DerInputStream;)V
+Lsun/security/x509/X500Name;->parseDN(Ljava/lang/String;Ljava/util/Map;)V
+Lsun/security/x509/X500Name;->parseRFC2253DN(Ljava/lang/String;)V
+Lsun/security/x509/X500Name;->principalConstructor:Ljava/lang/reflect/Constructor;
+Lsun/security/x509/X500Name;->principalField:Ljava/lang/reflect/Field;
+Lsun/security/x509/X500Name;->rdnList:Ljava/util/List;
+Lsun/security/x509/X500Name;->rfc1779Dn:Ljava/lang/String;
+Lsun/security/x509/X500Name;->rfc2253Dn:Ljava/lang/String;
+Lsun/security/x509/X500Name;->SERIALNUMBER_DATA:[I
+Lsun/security/x509/X500Name;->stateName_data:[I
+Lsun/security/x509/X500Name;->streetAddress_data:[I
+Lsun/security/x509/X500Name;->SURNAME_DATA:[I
+Lsun/security/x509/X500Name;->title_data:[I
+Lsun/security/x509/X500Name;->userid_data:[I
+Lsun/security/x509/X500Name;->x500Principal:Ljavax/security/auth/x500/X500Principal;
+Lsun/util/locale/BaseLocale$Cache;-><init>()V
+Lsun/util/locale/BaseLocale$Cache;->createObject(Ljava/lang/Object;)Ljava/lang/Object;
+Lsun/util/locale/BaseLocale$Cache;->createObject(Lsun/util/locale/BaseLocale$Key;)Lsun/util/locale/BaseLocale;
+Lsun/util/locale/BaseLocale$Cache;->normalizeKey(Ljava/lang/Object;)Ljava/lang/Object;
+Lsun/util/locale/BaseLocale$Cache;->normalizeKey(Lsun/util/locale/BaseLocale$Key;)Lsun/util/locale/BaseLocale$Key;
+Lsun/util/locale/BaseLocale$Key;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/util/locale/BaseLocale$Key;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lsun/util/locale/BaseLocale$Key;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
+Lsun/util/locale/BaseLocale$Key;->hash:I
+Lsun/util/locale/BaseLocale$Key;->lang:Ljava/lang/ref/SoftReference;
+Lsun/util/locale/BaseLocale$Key;->normalize(Lsun/util/locale/BaseLocale$Key;)Lsun/util/locale/BaseLocale$Key;
+Lsun/util/locale/BaseLocale$Key;->normalized:Z
+Lsun/util/locale/BaseLocale$Key;->regn:Ljava/lang/ref/SoftReference;
+Lsun/util/locale/BaseLocale$Key;->scrt:Ljava/lang/ref/SoftReference;
+Lsun/util/locale/BaseLocale$Key;->vart:Ljava/lang/ref/SoftReference;
+Lsun/util/locale/BaseLocale;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/util/locale/BaseLocale;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lsun/util/locale/BaseLocale;->CACHE:Lsun/util/locale/BaseLocale$Cache;
+Lsun/util/locale/BaseLocale;->hash:I
+Lsun/util/locale/BaseLocale;->language:Ljava/lang/String;
+Lsun/util/locale/BaseLocale;->region:Ljava/lang/String;
+Lsun/util/locale/BaseLocale;->script:Ljava/lang/String;
+Lsun/util/locale/BaseLocale;->variant:Ljava/lang/String;
+Lsun/util/locale/Extension;-><init>(C)V
+Lsun/util/locale/Extension;-><init>(CLjava/lang/String;)V
+Lsun/util/locale/Extension;->getID()Ljava/lang/String;
+Lsun/util/locale/Extension;->getKey()C
+Lsun/util/locale/Extension;->getValue()Ljava/lang/String;
+Lsun/util/locale/Extension;->id:Ljava/lang/String;
+Lsun/util/locale/Extension;->key:C
+Lsun/util/locale/Extension;->setValue(Ljava/lang/String;)V
+Lsun/util/locale/Extension;->value:Ljava/lang/String;
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveChar;-><init>(C)V
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveChar;-><init>(Ljava/lang/String;)V
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveChar;->ch:C
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveChar;->lowerCh:C
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveChar;->value()C
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveString;-><init>(Ljava/lang/String;)V
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveString;->lowerStr:Ljava/lang/String;
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveString;->str:Ljava/lang/String;
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveString;->value()Ljava/lang/String;
+Lsun/util/locale/InternalLocaleBuilder;->checkVariants(Ljava/lang/String;Ljava/lang/String;)I
+Lsun/util/locale/InternalLocaleBuilder;->extensions:Ljava/util/Map;
+Lsun/util/locale/InternalLocaleBuilder;->language:Ljava/lang/String;
+Lsun/util/locale/InternalLocaleBuilder;->PRIVATEUSE_KEY:Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveChar;
+Lsun/util/locale/InternalLocaleBuilder;->region:Ljava/lang/String;
+Lsun/util/locale/InternalLocaleBuilder;->removePrivateuseVariant(Ljava/lang/String;)Ljava/lang/String;
+Lsun/util/locale/InternalLocaleBuilder;->script:Ljava/lang/String;
+Lsun/util/locale/InternalLocaleBuilder;->setExtensions(Ljava/util/List;Ljava/lang/String;)Lsun/util/locale/InternalLocaleBuilder;
+Lsun/util/locale/InternalLocaleBuilder;->setUnicodeLocaleExtension(Ljava/lang/String;)V
+Lsun/util/locale/InternalLocaleBuilder;->uattributes:Ljava/util/Set;
+Lsun/util/locale/InternalLocaleBuilder;->ukeywords:Ljava/util/Map;
+Lsun/util/locale/InternalLocaleBuilder;->variant:Ljava/lang/String;
+Lsun/util/locale/LanguageTag;-><init>()V
+Lsun/util/locale/LanguageTag;->extensions:Ljava/util/List;
+Lsun/util/locale/LanguageTag;->extlangs:Ljava/util/List;
+Lsun/util/locale/LanguageTag;->GRANDFATHERED:Ljava/util/Map;
+Lsun/util/locale/LanguageTag;->language:Ljava/lang/String;
+Lsun/util/locale/LanguageTag;->parseExtensions(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z
+Lsun/util/locale/LanguageTag;->parseExtlangs(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z
+Lsun/util/locale/LanguageTag;->parseLanguage(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z
+Lsun/util/locale/LanguageTag;->parsePrivateuse(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z
+Lsun/util/locale/LanguageTag;->parseRegion(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z
+Lsun/util/locale/LanguageTag;->parseScript(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z
+Lsun/util/locale/LanguageTag;->parseVariants(Lsun/util/locale/StringTokenIterator;Lsun/util/locale/ParseStatus;)Z
+Lsun/util/locale/LanguageTag;->privateuse:Ljava/lang/String;
+Lsun/util/locale/LanguageTag;->region:Ljava/lang/String;
+Lsun/util/locale/LanguageTag;->script:Ljava/lang/String;
+Lsun/util/locale/LanguageTag;->variants:Ljava/util/List;
+Lsun/util/locale/LocaleExtensions;-><init>(Ljava/lang/String;Ljava/lang/Character;Lsun/util/locale/Extension;)V
+Lsun/util/locale/LocaleExtensions;-><init>(Ljava/util/Map;Ljava/util/Set;Ljava/util/Map;)V
+Lsun/util/locale/LocaleExtensions;->extensionMap:Ljava/util/Map;
+Lsun/util/locale/LocaleExtensions;->id:Ljava/lang/String;
+Lsun/util/locale/LocaleExtensions;->toID(Ljava/util/SortedMap;)Ljava/lang/String;
+Lsun/util/locale/LocaleObjectCache$CacheEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V
+Lsun/util/locale/LocaleObjectCache$CacheEntry;->getKey()Ljava/lang/Object;
+Lsun/util/locale/LocaleObjectCache$CacheEntry;->key:Ljava/lang/Object;
+Lsun/util/locale/LocaleObjectCache;->cleanStaleEntries()V
+Lsun/util/locale/LocaleObjectCache;->map:Ljava/util/concurrent/ConcurrentMap;
+Lsun/util/locale/LocaleObjectCache;->queue:Ljava/lang/ref/ReferenceQueue;
+Lsun/util/locale/LocaleSyntaxException;->index:I
+Lsun/util/locale/ParseStatus;->errorIndex:I
+Lsun/util/locale/ParseStatus;->errorMsg:Ljava/lang/String;
+Lsun/util/locale/ParseStatus;->parseLength:I
+Lsun/util/locale/StringTokenIterator;->delimiterChar:C
+Lsun/util/locale/StringTokenIterator;->dlms:Ljava/lang/String;
+Lsun/util/locale/StringTokenIterator;->done:Z
+Lsun/util/locale/StringTokenIterator;->end:I
+Lsun/util/locale/StringTokenIterator;->nextDelimiter(I)I
+Lsun/util/locale/StringTokenIterator;->start:I
+Lsun/util/locale/StringTokenIterator;->text:Ljava/lang/String;
+Lsun/util/locale/StringTokenIterator;->token:Ljava/lang/String;
diff --git a/build/boot/hiddenapi/hiddenapi-unsupported-packages.txt b/build/boot/hiddenapi/hiddenapi-unsupported-packages.txt
new file mode 100644
index 0000000..7a66b4b
--- /dev/null
+++ b/build/boot/hiddenapi/hiddenapi-unsupported-packages.txt
@@ -0,0 +1,28 @@
+org.apache.xalan
+org.apache.xalan.extensions
+org.apache.xalan.processor
+org.apache.xalan.res
+org.apache.xalan.serialize
+org.apache.xalan.templates
+org.apache.xalan.transformer
+org.apache.xalan.xslt
+org.apache.xml.dtm
+org.apache.xml.dtm.ref
+org.apache.xml.dtm.ref.dom2dtm
+org.apache.xml.dtm.ref.sax2dtm
+org.apache.xml.res
+org.apache.xml.serializer
+org.apache.xml.serializer.dom3
+org.apache.xml.serializer.utils
+org.apache.xml.utils
+org.apache.xml.utils.res
+org.apache.xpath
+org.apache.xpath.axes
+org.apache.xpath.compiler
+org.apache.xpath.domapi
+org.apache.xpath.functions
+org.apache.xpath.jaxp
+org.apache.xpath.objects
+org.apache.xpath.operations
+org.apache.xpath.patterns
+org.apache.xpath.res
diff --git a/build/boot/preloaded-classes b/build/boot/preloaded-classes
new file mode 100644
index 0000000..cf82bd6
--- /dev/null
+++ b/build/boot/preloaded-classes
@@ -0,0 +1,2455 @@
+#
+# Copyright (C) 2017 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.
+#
+# Preloaded-classes filter file for phones.
+#
+# Classes in this file will be allocated into the boot image, and forcibly initialized in
+# the zygote during initialization. This is a trade-off, using virtual address space to share
+# common heap between apps.
+#
+# This file has been derived for mainline phone (and tablet) usage.
+#
+android.compat.Compatibility$ChangeConfig
+android.compat.Compatibility
+android.system.ErrnoException
+android.system.GaiException
+android.system.Int32Ref
+android.system.Int64Ref
+android.system.NetlinkSocketAddress
+android.system.Os
+android.system.OsConstants
+android.system.PacketSocketAddress
+android.system.StructAddrinfo
+android.system.StructCapUserData
+android.system.StructCapUserHeader
+android.system.StructGroupReq
+android.system.StructIfaddrs
+android.system.StructLinger
+android.system.StructPasswd
+android.system.StructPollfd
+android.system.StructRlimit
+android.system.StructStat
+android.system.StructStatVfs
+android.system.StructTimespec
+android.system.StructTimeval
+android.system.StructUcred
+android.system.StructUtsname
+android.system.UnixSocketAddress
+com.android.okhttp.Address
+com.android.okhttp.AndroidShimResponseCache
+com.android.okhttp.Authenticator
+com.android.okhttp.Cache$1
+com.android.okhttp.Cache$CacheResponseBody$1
+com.android.okhttp.Cache$CacheResponseBody
+com.android.okhttp.Cache$Entry
+com.android.okhttp.Cache
+com.android.okhttp.CacheControl$Builder
+com.android.okhttp.CacheControl
+com.android.okhttp.CertificatePinner$Builder
+com.android.okhttp.CertificatePinner
+com.android.okhttp.CipherSuite
+com.android.okhttp.ConfigAwareConnectionPool$1
+com.android.okhttp.ConfigAwareConnectionPool
+com.android.okhttp.Connection
+com.android.okhttp.ConnectionPool$1
+com.android.okhttp.ConnectionPool
+com.android.okhttp.ConnectionSpec$Builder
+com.android.okhttp.ConnectionSpec
+com.android.okhttp.ConnectionSpecs
+com.android.okhttp.Dispatcher
+com.android.okhttp.Dns$1
+com.android.okhttp.Dns
+com.android.okhttp.Handshake
+com.android.okhttp.Headers$Builder
+com.android.okhttp.Headers
+com.android.okhttp.HttpHandler$CleartextURLFilter
+com.android.okhttp.HttpHandler
+com.android.okhttp.HttpUrl$1
+com.android.okhttp.HttpUrl$Builder$ParseResult
+com.android.okhttp.HttpUrl$Builder
+com.android.okhttp.HttpUrl
+com.android.okhttp.HttpsHandler
+com.android.okhttp.OkCacheContainer
+com.android.okhttp.OkHttpClient$1
+com.android.okhttp.OkHttpClient
+com.android.okhttp.OkUrlFactories
+com.android.okhttp.OkUrlFactory
+com.android.okhttp.Protocol
+com.android.okhttp.Request$Builder
+com.android.okhttp.Request
+com.android.okhttp.RequestBody$2
+com.android.okhttp.RequestBody
+com.android.okhttp.Response$Builder
+com.android.okhttp.Response
+com.android.okhttp.ResponseBody
+com.android.okhttp.Route
+com.android.okhttp.TlsVersion
+com.android.okhttp.internal.ConnectionSpecSelector
+com.android.okhttp.internal.DiskLruCache$1
+com.android.okhttp.internal.DiskLruCache$4
+com.android.okhttp.internal.DiskLruCache$Editor
+com.android.okhttp.internal.DiskLruCache$Entry
+com.android.okhttp.internal.DiskLruCache
+com.android.okhttp.internal.FaultHidingSink
+com.android.okhttp.internal.Internal
+com.android.okhttp.internal.InternalCache
+com.android.okhttp.internal.OptionalMethod
+com.android.okhttp.internal.Platform
+com.android.okhttp.internal.RouteDatabase
+com.android.okhttp.internal.URLFilter
+com.android.okhttp.internal.Util$1
+com.android.okhttp.internal.Util
+com.android.okhttp.internal.http.AuthenticatorAdapter
+com.android.okhttp.internal.http.CacheStrategy$Factory
+com.android.okhttp.internal.http.CacheStrategy
+com.android.okhttp.internal.http.HeaderParser
+com.android.okhttp.internal.http.Http1xStream$AbstractSource
+com.android.okhttp.internal.http.Http1xStream$ChunkedSink
+com.android.okhttp.internal.http.Http1xStream$ChunkedSource
+com.android.okhttp.internal.http.Http1xStream$FixedLengthSink
+com.android.okhttp.internal.http.Http1xStream$FixedLengthSource
+com.android.okhttp.internal.http.Http1xStream
+com.android.okhttp.internal.http.HttpDate$1
+com.android.okhttp.internal.http.HttpDate
+com.android.okhttp.internal.http.HttpEngine$1
+com.android.okhttp.internal.http.HttpEngine
+com.android.okhttp.internal.http.HttpMethod
+com.android.okhttp.internal.http.HttpStream
+com.android.okhttp.internal.http.OkHeaders$1
+com.android.okhttp.internal.http.OkHeaders
+com.android.okhttp.internal.http.RealResponseBody
+com.android.okhttp.internal.http.RequestException
+com.android.okhttp.internal.http.RequestLine
+com.android.okhttp.internal.http.RetryableSink
+com.android.okhttp.internal.http.RouteException
+com.android.okhttp.internal.http.RouteSelector
+com.android.okhttp.internal.http.StatusLine
+com.android.okhttp.internal.http.StreamAllocation
+com.android.okhttp.internal.huc.DelegatingHttpsURLConnection
+com.android.okhttp.internal.huc.HttpURLConnectionImpl
+com.android.okhttp.internal.huc.HttpsURLConnectionImpl
+com.android.okhttp.internal.io.FileSystem$1
+com.android.okhttp.internal.io.FileSystem
+com.android.okhttp.internal.io.RealConnection
+com.android.okhttp.internal.tls.OkHostnameVerifier
+com.android.okhttp.internal.tls.RealTrustRootIndex
+com.android.okhttp.internal.tls.TrustRootIndex
+com.android.okhttp.internalandroidapi.AndroidResponseCacheAdapter
+com.android.okhttp.internalandroidapi.Dns
+com.android.okhttp.internalandroidapi.HasCacheHolder$CacheHolder
+com.android.okhttp.internalandroidapi.HasCacheHolder
+com.android.okhttp.internalandroidapi.HttpURLConnectionFactory$DnsAdapter
+com.android.okhttp.internalandroidapi.HttpURLConnectionFactory
+com.android.okhttp.okio.AsyncTimeout$1
+com.android.okhttp.okio.AsyncTimeout$2
+com.android.okhttp.okio.AsyncTimeout$Watchdog
+com.android.okhttp.okio.AsyncTimeout
+com.android.okhttp.okio.Buffer
+com.android.okhttp.okio.BufferedSink
+com.android.okhttp.okio.BufferedSource
+com.android.okhttp.okio.ByteString
+com.android.okhttp.okio.ForwardingSink
+com.android.okhttp.okio.ForwardingSource
+com.android.okhttp.okio.ForwardingTimeout
+com.android.okhttp.okio.GzipSource
+com.android.okhttp.okio.InflaterSource
+com.android.okhttp.okio.Okio$1
+com.android.okhttp.okio.Okio$2
+com.android.okhttp.okio.Okio$3
+com.android.okhttp.okio.Okio
+com.android.okhttp.okio.RealBufferedSink$1
+com.android.okhttp.okio.RealBufferedSink
+com.android.okhttp.okio.RealBufferedSource$1
+com.android.okhttp.okio.RealBufferedSource
+com.android.okhttp.okio.Segment
+com.android.okhttp.okio.SegmentPool
+com.android.okhttp.okio.Sink
+com.android.okhttp.okio.Source
+com.android.okhttp.okio.Timeout$1
+com.android.okhttp.okio.Timeout
+com.android.okhttp.okio.Util
+com.android.org.bouncycastle.asn1.ASN1BitString
+com.android.org.bouncycastle.asn1.ASN1Choice
+com.android.org.bouncycastle.asn1.ASN1Encodable
+com.android.org.bouncycastle.asn1.ASN1EncodableVector
+com.android.org.bouncycastle.asn1.ASN1InputStream
+com.android.org.bouncycastle.asn1.ASN1Integer
+com.android.org.bouncycastle.asn1.ASN1Null
+com.android.org.bouncycastle.asn1.ASN1Object
+com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier$OidHandle
+com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier
+com.android.org.bouncycastle.asn1.ASN1OutputStream
+com.android.org.bouncycastle.asn1.ASN1Primitive
+com.android.org.bouncycastle.asn1.ASN1Sequence
+com.android.org.bouncycastle.asn1.ASN1SequenceParser
+com.android.org.bouncycastle.asn1.ASN1Set
+com.android.org.bouncycastle.asn1.ASN1String
+com.android.org.bouncycastle.asn1.ASN1TaggedObject
+com.android.org.bouncycastle.asn1.ASN1TaggedObjectParser
+com.android.org.bouncycastle.asn1.BERTags
+com.android.org.bouncycastle.asn1.DERBitString
+com.android.org.bouncycastle.asn1.DERFactory
+com.android.org.bouncycastle.asn1.DERInteger
+com.android.org.bouncycastle.asn1.DERNull
+com.android.org.bouncycastle.asn1.DEROutputStream
+com.android.org.bouncycastle.asn1.DERSequence
+com.android.org.bouncycastle.asn1.DERSet
+com.android.org.bouncycastle.asn1.DERTaggedObject
+com.android.org.bouncycastle.asn1.DLSequence
+com.android.org.bouncycastle.asn1.DefiniteLengthInputStream
+com.android.org.bouncycastle.asn1.InMemoryRepresentable
+com.android.org.bouncycastle.asn1.IndefiniteLengthInputStream
+com.android.org.bouncycastle.asn1.LimitedInputStream
+com.android.org.bouncycastle.asn1.OIDTokenizer
+com.android.org.bouncycastle.asn1.StreamUtil
+com.android.org.bouncycastle.asn1.bc.BCObjectIdentifiers
+com.android.org.bouncycastle.asn1.iana.IANAObjectIdentifiers
+com.android.org.bouncycastle.asn1.misc.MiscObjectIdentifiers
+com.android.org.bouncycastle.asn1.nist.NISTObjectIdentifiers
+com.android.org.bouncycastle.asn1.oiw.OIWObjectIdentifiers
+com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers
+com.android.org.bouncycastle.asn1.x500.X500Name
+com.android.org.bouncycastle.asn1.x500.X500NameStyle
+com.android.org.bouncycastle.asn1.x500.style.AbstractX500NameStyle
+com.android.org.bouncycastle.asn1.x500.style.BCStyle
+com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier
+com.android.org.bouncycastle.asn1.x509.Certificate
+com.android.org.bouncycastle.asn1.x509.DSAParameter
+com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
+com.android.org.bouncycastle.asn1.x509.Time
+com.android.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator
+com.android.org.bouncycastle.asn1.x509.X509ExtensionsGenerator
+com.android.org.bouncycastle.asn1.x509.X509Name
+com.android.org.bouncycastle.asn1.x509.X509ObjectIdentifiers
+com.android.org.bouncycastle.asn1.x9.X9ECParameters
+com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers
+com.android.org.bouncycastle.crypto.BlockCipher
+com.android.org.bouncycastle.crypto.BufferedBlockCipher
+com.android.org.bouncycastle.crypto.CipherParameters
+com.android.org.bouncycastle.crypto.CryptoException
+com.android.org.bouncycastle.crypto.CryptoServicesPermission
+com.android.org.bouncycastle.crypto.CryptoServicesRegistrar$Property
+com.android.org.bouncycastle.crypto.CryptoServicesRegistrar
+com.android.org.bouncycastle.crypto.DataLengthException
+com.android.org.bouncycastle.crypto.Digest
+com.android.org.bouncycastle.crypto.ExtendedDigest
+com.android.org.bouncycastle.crypto.InvalidCipherTextException
+com.android.org.bouncycastle.crypto.OutputLengthException
+com.android.org.bouncycastle.crypto.PBEParametersGenerator
+com.android.org.bouncycastle.crypto.RuntimeCryptoException
+com.android.org.bouncycastle.crypto.digests.AndroidDigestFactory
+com.android.org.bouncycastle.crypto.digests.AndroidDigestFactoryBouncyCastle
+com.android.org.bouncycastle.crypto.digests.AndroidDigestFactoryInterface
+com.android.org.bouncycastle.crypto.digests.AndroidDigestFactoryOpenSSL
+com.android.org.bouncycastle.crypto.digests.OpenSSLDigest$MD5
+com.android.org.bouncycastle.crypto.digests.OpenSSLDigest
+com.android.org.bouncycastle.crypto.engines.AESEngine
+com.android.org.bouncycastle.crypto.paddings.BlockCipherPadding
+com.android.org.bouncycastle.crypto.paddings.PKCS7Padding
+com.android.org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher
+com.android.org.bouncycastle.crypto.params.AsymmetricKeyParameter
+com.android.org.bouncycastle.crypto.params.DHParameters
+com.android.org.bouncycastle.crypto.params.DHValidationParameters
+com.android.org.bouncycastle.crypto.params.DSAKeyParameters
+com.android.org.bouncycastle.crypto.params.DSAParameters
+com.android.org.bouncycastle.crypto.params.DSAPublicKeyParameters
+com.android.org.bouncycastle.crypto.params.DSAValidationParameters
+com.android.org.bouncycastle.crypto.params.KeyParameter
+com.android.org.bouncycastle.crypto.params.ParametersWithIV
+com.android.org.bouncycastle.crypto.params.ParametersWithRandom
+com.android.org.bouncycastle.jcajce.PBKDFKey
+com.android.org.bouncycastle.jcajce.PKCS12Key
+com.android.org.bouncycastle.jcajce.provider.asymmetric.DH$Mappings
+com.android.org.bouncycastle.jcajce.provider.asymmetric.DH
+com.android.org.bouncycastle.jcajce.provider.asymmetric.DSA$Mappings
+com.android.org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings
+com.android.org.bouncycastle.jcajce.provider.asymmetric.EC
+com.android.org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings
+com.android.org.bouncycastle.jcajce.provider.asymmetric.RSA
+com.android.org.bouncycastle.jcajce.provider.asymmetric.X509$Mappings
+com.android.org.bouncycastle.jcajce.provider.asymmetric.dh.KeyFactorySpi
+com.android.org.bouncycastle.jcajce.provider.asymmetric.dsa.BCDSAPublicKey
+com.android.org.bouncycastle.jcajce.provider.asymmetric.dsa.DSAUtil
+com.android.org.bouncycastle.jcajce.provider.asymmetric.dsa.KeyFactorySpi
+com.android.org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi$EC
+com.android.org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi
+com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$NoPadding
+com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi
+com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyFactorySpi
+com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.RSAUtil
+com.android.org.bouncycastle.jcajce.provider.asymmetric.util.BaseCipherSpi
+com.android.org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi
+com.android.org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil
+com.android.org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory
+com.android.org.bouncycastle.jcajce.provider.asymmetric.x509.PEMUtil
+com.android.org.bouncycastle.jcajce.provider.config.ConfigurableProvider
+com.android.org.bouncycastle.jcajce.provider.config.ProviderConfiguration
+com.android.org.bouncycastle.jcajce.provider.config.ProviderConfigurationPermission
+com.android.org.bouncycastle.jcajce.provider.digest.DigestAlgorithmProvider
+com.android.org.bouncycastle.jcajce.provider.digest.MD5$Mappings
+com.android.org.bouncycastle.jcajce.provider.digest.MD5
+com.android.org.bouncycastle.jcajce.provider.digest.SHA1$Mappings
+com.android.org.bouncycastle.jcajce.provider.digest.SHA1
+com.android.org.bouncycastle.jcajce.provider.digest.SHA224$Mappings
+com.android.org.bouncycastle.jcajce.provider.digest.SHA224
+com.android.org.bouncycastle.jcajce.provider.digest.SHA256$Mappings
+com.android.org.bouncycastle.jcajce.provider.digest.SHA256
+com.android.org.bouncycastle.jcajce.provider.digest.SHA384$Mappings
+com.android.org.bouncycastle.jcajce.provider.digest.SHA384
+com.android.org.bouncycastle.jcajce.provider.digest.SHA512$Mappings
+com.android.org.bouncycastle.jcajce.provider.digest.SHA512
+com.android.org.bouncycastle.jcajce.provider.keystore.BC$Mappings
+com.android.org.bouncycastle.jcajce.provider.keystore.PKCS12$Mappings
+com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi$Std
+com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi$StoreEntry
+com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi
+com.android.org.bouncycastle.jcajce.provider.symmetric.AES$ECB$1
+com.android.org.bouncycastle.jcajce.provider.symmetric.AES$ECB
+com.android.org.bouncycastle.jcajce.provider.symmetric.AES$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.AES
+com.android.org.bouncycastle.jcajce.provider.symmetric.ARC4$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.ARC4
+com.android.org.bouncycastle.jcajce.provider.symmetric.Blowfish$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.Blowfish
+com.android.org.bouncycastle.jcajce.provider.symmetric.DES$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.DES
+com.android.org.bouncycastle.jcajce.provider.symmetric.DESede$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.DESede
+com.android.org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF2$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF2
+com.android.org.bouncycastle.jcajce.provider.symmetric.PBEPKCS12$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.PBEPKCS12
+com.android.org.bouncycastle.jcajce.provider.symmetric.PBES2AlgorithmParameters$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.PBES2AlgorithmParameters
+com.android.org.bouncycastle.jcajce.provider.symmetric.RC2$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.RC2
+com.android.org.bouncycastle.jcajce.provider.symmetric.SymmetricAlgorithmProvider
+com.android.org.bouncycastle.jcajce.provider.symmetric.Twofish$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.Twofish
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$AEADGenericBlockCipher
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$BufferedGenericBlockCipher
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$GenericBlockCipher
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseWrapCipher
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.ClassUtil
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.PBE$Util
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.PBE
+com.android.org.bouncycastle.jcajce.provider.util.AlgorithmProvider
+com.android.org.bouncycastle.jcajce.provider.util.AsymmetricAlgorithmProvider
+com.android.org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter
+com.android.org.bouncycastle.jcajce.provider.util.DigestFactory
+com.android.org.bouncycastle.jcajce.spec.AEADParameterSpec
+com.android.org.bouncycastle.jcajce.util.BCJcaJceHelper
+com.android.org.bouncycastle.jcajce.util.DefaultJcaJceHelper
+com.android.org.bouncycastle.jcajce.util.JcaJceHelper
+com.android.org.bouncycastle.jcajce.util.ProviderJcaJceHelper
+com.android.org.bouncycastle.jce.X509Principal
+com.android.org.bouncycastle.jce.interfaces.BCKeyStore
+com.android.org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier
+com.android.org.bouncycastle.jce.provider.BouncyCastleProvider$1
+com.android.org.bouncycastle.jce.provider.BouncyCastleProvider
+com.android.org.bouncycastle.jce.provider.BouncyCastleProviderConfiguration
+com.android.org.bouncycastle.jce.provider.CertStoreCollectionSpi
+com.android.org.bouncycastle.jce.provider.X509CertificateObject
+com.android.org.bouncycastle.jce.spec.ECKeySpec
+com.android.org.bouncycastle.jce.spec.ECPublicKeySpec
+com.android.org.bouncycastle.util.Arrays
+com.android.org.bouncycastle.util.Encodable
+com.android.org.bouncycastle.util.Integers
+com.android.org.bouncycastle.util.Iterable
+com.android.org.bouncycastle.util.Pack
+com.android.org.bouncycastle.util.Properties$1
+com.android.org.bouncycastle.util.Properties
+com.android.org.bouncycastle.util.Strings$1
+com.android.org.bouncycastle.util.Strings
+com.android.org.bouncycastle.util.encoders.Encoder
+com.android.org.bouncycastle.util.encoders.Hex
+com.android.org.bouncycastle.util.encoders.HexEncoder
+com.android.org.bouncycastle.util.io.Streams
+com.android.org.bouncycastle.x509.X509V3CertificateGenerator
+com.android.org.kxml2.io.KXmlParser$ContentSource
+com.android.org.kxml2.io.KXmlParser$ValueContext
+com.android.org.kxml2.io.KXmlParser
+com.android.org.kxml2.io.KXmlSerializer
+com.sun.security.cert.internal.x509.X509V1CertImpl
+dalvik.annotation.optimization.CriticalNative
+dalvik.annotation.optimization.FastNative
+dalvik.system.BaseDexClassLoader$Reporter
+dalvik.system.BaseDexClassLoader
+dalvik.system.BlockGuard$1
+dalvik.system.BlockGuard$2
+dalvik.system.BlockGuard$3
+dalvik.system.BlockGuard$BlockGuardPolicyException
+dalvik.system.BlockGuard$Policy
+dalvik.system.BlockGuard$VmPolicy
+dalvik.system.BlockGuard
+dalvik.system.ClassExt
+dalvik.system.CloseGuard$DefaultReporter
+dalvik.system.CloseGuard$Reporter
+dalvik.system.CloseGuard$Tracker
+dalvik.system.CloseGuard
+dalvik.system.DelegateLastClassLoader
+dalvik.system.DexClassLoader
+dalvik.system.DexFile$1
+dalvik.system.DexFile$DFEnum
+dalvik.system.DexFile$OptimizationInfo
+dalvik.system.DexFile
+dalvik.system.DexPathList$Element
+dalvik.system.DexPathList$NativeLibraryElement
+dalvik.system.DexPathList
+dalvik.system.EmulatedStackFrame$Range
+dalvik.system.EmulatedStackFrame
+dalvik.system.InMemoryDexClassLoader
+dalvik.system.PathClassLoader
+dalvik.system.RuntimeHooks
+dalvik.system.SocketTagger$1
+dalvik.system.SocketTagger
+dalvik.system.VMDebug
+dalvik.system.VMRuntime$HiddenApiUsageLogger
+dalvik.system.VMRuntime
+dalvik.system.VMStack
+dalvik.system.ZygoteHooks
+java.io.Bits
+java.io.BufferedInputStream
+java.io.BufferedOutputStream
+java.io.BufferedReader
+java.io.BufferedWriter
+java.io.ByteArrayInputStream
+java.io.ByteArrayOutputStream
+java.io.CharArrayReader
+java.io.CharArrayWriter
+java.io.Closeable
+java.io.Console
+java.io.DataInput
+java.io.DataInputStream
+java.io.DataOutput
+java.io.DataOutputStream
+java.io.DefaultFileSystem
+java.io.EOFException
+java.io.ExpiringCache$1
+java.io.ExpiringCache
+java.io.Externalizable
+java.io.File$PathStatus
+java.io.File$TempDirectory
+java.io.File
+java.io.FileDescriptor$1
+java.io.FileDescriptor
+java.io.FileFilter
+java.io.FileInputStream$UseManualSkipException
+java.io.FileInputStream
+java.io.FileNotFoundException
+java.io.FileOutputStream
+java.io.FileReader
+java.io.FileSystem
+java.io.FileWriter
+java.io.FilenameFilter
+java.io.FilterInputStream
+java.io.FilterOutputStream
+java.io.FilterReader
+java.io.Flushable
+java.io.IOException
+java.io.InputStream
+java.io.InputStreamReader
+java.io.InterruptedIOException
+java.io.InvalidClassException
+java.io.InvalidObjectException
+java.io.LineNumberReader
+java.io.NotSerializableException
+java.io.ObjectInput
+java.io.ObjectInputStream$BlockDataInputStream
+java.io.ObjectInputStream$GetField
+java.io.ObjectInputStream$HandleTable$HandleList
+java.io.ObjectInputStream$HandleTable
+java.io.ObjectInputStream$PeekInputStream
+java.io.ObjectInputStream$ValidationList
+java.io.ObjectInputStream
+java.io.ObjectOutput
+java.io.ObjectOutputStream$BlockDataOutputStream
+java.io.ObjectOutputStream$HandleTable
+java.io.ObjectOutputStream$PutField
+java.io.ObjectOutputStream$ReplaceTable
+java.io.ObjectOutputStream
+java.io.ObjectStreamClass$1
+java.io.ObjectStreamClass$2
+java.io.ObjectStreamClass$3
+java.io.ObjectStreamClass$4
+java.io.ObjectStreamClass$5
+java.io.ObjectStreamClass$Caches
+java.io.ObjectStreamClass$ClassDataSlot
+java.io.ObjectStreamClass$DefaultSUIDCompatibilityListener
+java.io.ObjectStreamClass$EntryFuture
+java.io.ObjectStreamClass$ExceptionInfo
+java.io.ObjectStreamClass$FieldReflector
+java.io.ObjectStreamClass$FieldReflectorKey
+java.io.ObjectStreamClass$MemberSignature
+java.io.ObjectStreamClass$WeakClassKey
+java.io.ObjectStreamClass
+java.io.ObjectStreamConstants
+java.io.ObjectStreamException
+java.io.ObjectStreamField
+java.io.OptionalDataException
+java.io.OutputStream
+java.io.OutputStreamWriter
+java.io.PrintStream
+java.io.PrintWriter
+java.io.PushbackInputStream
+java.io.PushbackReader
+java.io.RandomAccessFile
+java.io.Reader
+java.io.SequenceInputStream
+java.io.SerialCallbackContext
+java.io.Serializable
+java.io.SerializablePermission
+java.io.StreamCorruptedException
+java.io.StringBufferInputStream
+java.io.StringReader
+java.io.StringWriter
+java.io.UTFDataFormatException
+java.io.UncheckedIOException
+java.io.UnixFileSystem
+java.io.UnsupportedEncodingException
+java.io.Writer
+java.lang.AbstractMethodError
+java.lang.AbstractStringBuilder
+java.lang.AndroidHardcodedSystemProperties
+java.lang.Appendable
+java.lang.ArithmeticException
+java.lang.ArrayIndexOutOfBoundsException
+java.lang.ArrayStoreException
+java.lang.AssertionError
+java.lang.AutoCloseable
+java.lang.Boolean
+java.lang.BootClassLoader
+java.lang.Byte$ByteCache
+java.lang.Byte
+java.lang.CaseMapper$1
+java.lang.CaseMapper
+java.lang.CharSequence$1CharIterator
+java.lang.CharSequence$1CodePointIterator
+java.lang.CharSequence
+java.lang.Character$CharacterCache
+java.lang.Character$Subset
+java.lang.Character$UnicodeBlock
+java.lang.Character
+java.lang.Class$Caches
+java.lang.Class
+java.lang.ClassCastException
+java.lang.ClassFormatError
+java.lang.ClassLoader$SystemClassLoader
+java.lang.ClassLoader
+java.lang.ClassNotFoundException
+java.lang.CloneNotSupportedException
+java.lang.Cloneable
+java.lang.Comparable
+java.lang.Daemons$Daemon
+java.lang.Daemons$FinalizerDaemon
+java.lang.Daemons$FinalizerWatchdogDaemon
+java.lang.Daemons$HeapTaskDaemon
+java.lang.Daemons$ReferenceQueueDaemon
+java.lang.Daemons
+java.lang.Deprecated
+java.lang.DexCache
+java.lang.Double
+java.lang.Enum$1
+java.lang.Enum
+java.lang.EnumConstantNotPresentException
+java.lang.Error
+java.lang.Exception
+java.lang.ExceptionInInitializerError
+java.lang.Float
+java.lang.IllegalAccessError
+java.lang.IllegalAccessException
+java.lang.IllegalArgumentException
+java.lang.IllegalMonitorStateException
+java.lang.IllegalStateException
+java.lang.IllegalThreadStateException
+java.lang.IncompatibleClassChangeError
+java.lang.IndexOutOfBoundsException
+java.lang.InheritableThreadLocal
+java.lang.InstantiationError
+java.lang.InstantiationException
+java.lang.Integer$IntegerCache
+java.lang.Integer
+java.lang.InternalError
+java.lang.InterruptedException
+java.lang.Iterable
+java.lang.LinkageError
+java.lang.Long$LongCache
+java.lang.Long
+java.lang.Math$RandomNumberGeneratorHolder
+java.lang.Math
+java.lang.NegativeArraySizeException
+java.lang.NoClassDefFoundError
+java.lang.NoSuchFieldError
+java.lang.NoSuchFieldException
+java.lang.NoSuchMethodError
+java.lang.NoSuchMethodException
+java.lang.NullPointerException
+java.lang.Number
+java.lang.NumberFormatException
+java.lang.Object
+java.lang.OutOfMemoryError
+java.lang.Package
+java.lang.Process
+java.lang.ProcessBuilder$NullInputStream
+java.lang.ProcessBuilder$NullOutputStream
+java.lang.ProcessBuilder
+java.lang.ProcessEnvironment$ExternalData
+java.lang.ProcessEnvironment$StringEnvironment
+java.lang.ProcessEnvironment$Value
+java.lang.ProcessEnvironment$Variable
+java.lang.ProcessEnvironment
+java.lang.ProcessImpl
+java.lang.Readable
+java.lang.ReflectiveOperationException
+java.lang.Runnable
+java.lang.Runtime
+java.lang.RuntimeException
+java.lang.RuntimePermission
+java.lang.SecurityException
+java.lang.SecurityManager
+java.lang.Short$ShortCache
+java.lang.Short
+java.lang.StackOverflowError
+java.lang.StackTraceElement
+java.lang.StrictMath
+java.lang.String$1
+java.lang.String$CaseInsensitiveComparator
+java.lang.String
+java.lang.StringBuffer
+java.lang.StringBuilder
+java.lang.StringFactory
+java.lang.StringIndexOutOfBoundsException
+java.lang.System$PropertiesWithNonOverrideableDefaults
+java.lang.System
+java.lang.Thread$1
+java.lang.Thread$Caches
+java.lang.Thread$State
+java.lang.Thread$UncaughtExceptionHandler
+java.lang.Thread$WeakClassKey
+java.lang.Thread
+java.lang.ThreadDeath
+java.lang.ThreadGroup
+java.lang.ThreadLocal$SuppliedThreadLocal
+java.lang.ThreadLocal$ThreadLocalMap$Entry
+java.lang.ThreadLocal$ThreadLocalMap
+java.lang.ThreadLocal
+java.lang.Throwable$PrintStreamOrWriter
+java.lang.Throwable$SentinelHolder
+java.lang.Throwable$WrappedPrintStream
+java.lang.Throwable$WrappedPrintWriter
+java.lang.Throwable
+java.lang.TypeNotPresentException
+java.lang.UNIXProcess$1
+java.lang.UNIXProcess$2
+java.lang.UNIXProcess$3
+java.lang.UNIXProcess$ProcessPipeInputStream
+java.lang.UNIXProcess$ProcessPipeOutputStream
+java.lang.UNIXProcess$ProcessReaperThreadFactory$1
+java.lang.UNIXProcess$ProcessReaperThreadFactory
+java.lang.UNIXProcess
+java.lang.UnsatisfiedLinkError
+java.lang.UnsupportedOperationException
+java.lang.VMClassLoader
+java.lang.VerifyError
+java.lang.VirtualMachineError
+java.lang.Void
+java.lang.annotation.Annotation
+java.lang.annotation.AnnotationTypeMismatchException
+java.lang.annotation.Documented
+java.lang.annotation.IncompleteAnnotationException
+java.lang.annotation.Inherited
+java.lang.annotation.Retention
+java.lang.annotation.Target
+java.lang.invoke.ArrayElementVarHandle
+java.lang.invoke.ByteArrayViewVarHandle
+java.lang.invoke.ByteBufferViewVarHandle
+java.lang.invoke.CallSite
+java.lang.invoke.ConstantCallSite
+java.lang.invoke.FieldVarHandle
+java.lang.invoke.MethodHandle
+java.lang.invoke.MethodHandleImpl$HandleInfo
+java.lang.invoke.MethodHandleImpl
+java.lang.invoke.MethodHandleInfo
+java.lang.invoke.MethodHandleStatics
+java.lang.invoke.MethodHandles$Lookup
+java.lang.invoke.MethodHandles
+java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry
+java.lang.invoke.MethodType$ConcurrentWeakInternSet
+java.lang.invoke.MethodType
+java.lang.invoke.MethodTypeForm
+java.lang.invoke.SerializedLambda
+java.lang.invoke.Transformers$AlwaysThrow
+java.lang.invoke.Transformers$BindTo
+java.lang.invoke.Transformers$CatchException
+java.lang.invoke.Transformers$CollectArguments
+java.lang.invoke.Transformers$Collector
+java.lang.invoke.Transformers$Constant
+java.lang.invoke.Transformers$Construct
+java.lang.invoke.Transformers$DropArguments
+java.lang.invoke.Transformers$ExplicitCastArguments
+java.lang.invoke.Transformers$FilterArguments
+java.lang.invoke.Transformers$FilterReturnValue
+java.lang.invoke.Transformers$FoldArguments
+java.lang.invoke.Transformers$GuardWithTest
+java.lang.invoke.Transformers$InsertArguments
+java.lang.invoke.Transformers$Invoker
+java.lang.invoke.Transformers$PermuteArguments
+java.lang.invoke.Transformers$ReferenceArrayElementGetter
+java.lang.invoke.Transformers$ReferenceArrayElementSetter
+java.lang.invoke.Transformers$ReferenceIdentity
+java.lang.invoke.Transformers$Spreader
+java.lang.invoke.Transformers$Transformer
+java.lang.invoke.Transformers$VarargsCollector
+java.lang.invoke.VarHandle$1
+java.lang.invoke.VarHandle$AccessMode
+java.lang.invoke.VarHandle$AccessType
+java.lang.invoke.VarHandle
+java.lang.invoke.WrongMethodTypeException
+java.lang.ref.FinalizerReference$1
+java.lang.ref.FinalizerReference$Sentinel
+java.lang.ref.FinalizerReference
+java.lang.ref.PhantomReference
+java.lang.ref.Reference$SinkHolder$1
+java.lang.ref.Reference$SinkHolder
+java.lang.ref.Reference
+java.lang.ref.ReferenceQueue
+java.lang.ref.SoftReference
+java.lang.ref.WeakReference
+java.lang.reflect.AccessibleObject
+java.lang.reflect.AnnotatedElement
+java.lang.reflect.Array
+java.lang.reflect.Constructor
+java.lang.reflect.Executable$GenericInfo
+java.lang.reflect.Executable
+java.lang.reflect.Field
+java.lang.reflect.GenericArrayType
+java.lang.reflect.GenericDeclaration
+java.lang.reflect.GenericSignatureFormatError
+java.lang.reflect.InvocationHandler
+java.lang.reflect.InvocationTargetException
+java.lang.reflect.MalformedParametersException
+java.lang.reflect.Member
+java.lang.reflect.Method$1
+java.lang.reflect.Method
+java.lang.reflect.Modifier
+java.lang.reflect.Parameter
+java.lang.reflect.ParameterizedType
+java.lang.reflect.Proxy$1
+java.lang.reflect.Proxy$Key1
+java.lang.reflect.Proxy$Key2
+java.lang.reflect.Proxy$KeyFactory
+java.lang.reflect.Proxy$KeyX
+java.lang.reflect.Proxy$ProxyClassFactory
+java.lang.reflect.Proxy
+java.lang.reflect.Type
+java.lang.reflect.TypeVariable
+java.lang.reflect.UndeclaredThrowableException
+java.lang.reflect.WeakCache$CacheKey
+java.lang.reflect.WeakCache$CacheValue
+java.lang.reflect.WeakCache$Factory
+java.lang.reflect.WeakCache$LookupValue
+java.lang.reflect.WeakCache$Value
+java.lang.reflect.WeakCache
+java.lang.reflect.WildcardType
+java.math.BigDecimal$1
+java.math.BigDecimal
+java.math.BigInteger
+java.math.MathContext
+java.math.RoundingMode
+java.net.AbstractPlainDatagramSocketImpl
+java.net.AbstractPlainSocketImpl
+java.net.AddressCache$AddressCacheEntry
+java.net.AddressCache$AddressCacheKey
+java.net.AddressCache
+java.net.Authenticator$RequestorType
+java.net.Authenticator
+java.net.ConnectException
+java.net.CookieHandler
+java.net.CookieManager$CookiePathComparator
+java.net.CookieManager
+java.net.CookiePolicy$1
+java.net.CookiePolicy$2
+java.net.CookiePolicy$3
+java.net.CookiePolicy
+java.net.CookieStore
+java.net.DatagramPacket
+java.net.DatagramSocket$1
+java.net.DatagramSocket
+java.net.DatagramSocketImpl
+java.net.DefaultDatagramSocketImplFactory
+java.net.DefaultInterface
+java.net.HttpCookie$10
+java.net.HttpCookie$11
+java.net.HttpCookie$1
+java.net.HttpCookie$2
+java.net.HttpCookie$3
+java.net.HttpCookie$4
+java.net.HttpCookie$5
+java.net.HttpCookie$6
+java.net.HttpCookie$7
+java.net.HttpCookie$8
+java.net.HttpCookie$9
+java.net.HttpCookie$CookieAttributeAssignor
+java.net.HttpCookie
+java.net.HttpRetryException
+java.net.HttpURLConnection
+java.net.IDN
+java.net.InMemoryCookieStore
+java.net.Inet4Address
+java.net.Inet6Address$Inet6AddressHolder
+java.net.Inet6Address
+java.net.Inet6AddressImpl
+java.net.InetAddress$1
+java.net.InetAddress$InetAddressHolder
+java.net.InetAddress
+java.net.InetAddressImpl
+java.net.InetSocketAddress$InetSocketAddressHolder
+java.net.InetSocketAddress
+java.net.InterfaceAddress
+java.net.JarURLConnection
+java.net.MalformedURLException
+java.net.MulticastSocket
+java.net.NetPermission
+java.net.NetworkInterface$1checkedAddresses
+java.net.NetworkInterface
+java.net.NoRouteToHostException
+java.net.Parts
+java.net.PasswordAuthentication
+java.net.PlainDatagramSocketImpl
+java.net.PlainSocketImpl
+java.net.PortUnreachableException
+java.net.ProtocolException
+java.net.ProtocolFamily
+java.net.Proxy$Type
+java.net.Proxy
+java.net.ProxySelector
+java.net.ResponseCache
+java.net.ServerSocket
+java.net.Socket$1
+java.net.Socket$2
+java.net.Socket$3
+java.net.Socket
+java.net.SocketAddress
+java.net.SocketException
+java.net.SocketImpl
+java.net.SocketImplFactory
+java.net.SocketInputStream
+java.net.SocketOptions
+java.net.SocketOutputStream
+java.net.SocketPermission
+java.net.SocketTimeoutException
+java.net.SocksConsts
+java.net.SocksSocketImpl
+java.net.StandardProtocolFamily
+java.net.URI$Parser
+java.net.URI
+java.net.URISyntaxException
+java.net.URL
+java.net.URLConnection
+java.net.URLDecoder
+java.net.URLEncoder
+java.net.URLStreamHandler
+java.net.URLStreamHandlerFactory
+java.net.UnknownHostException
+java.net.UnknownServiceException
+java.nio.Bits
+java.nio.Buffer
+java.nio.BufferOverflowException
+java.nio.BufferUnderflowException
+java.nio.ByteBuffer
+java.nio.ByteBufferAsCharBuffer
+java.nio.ByteBufferAsDoubleBuffer
+java.nio.ByteBufferAsFloatBuffer
+java.nio.ByteBufferAsIntBuffer
+java.nio.ByteBufferAsLongBuffer
+java.nio.ByteBufferAsShortBuffer
+java.nio.ByteOrder
+java.nio.CharBuffer
+java.nio.DirectByteBuffer$MemoryRef
+java.nio.DirectByteBuffer
+java.nio.DoubleBuffer
+java.nio.FloatBuffer
+java.nio.HeapByteBuffer
+java.nio.HeapCharBuffer
+java.nio.IntBuffer
+java.nio.InvalidMarkException
+java.nio.LongBuffer
+java.nio.MappedByteBuffer
+java.nio.NIOAccess
+java.nio.NioUtils
+java.nio.ReadOnlyBufferException
+java.nio.ShortBuffer
+java.nio.StringCharBuffer
+java.nio.channels.AsynchronousCloseException
+java.nio.channels.ByteChannel
+java.nio.channels.Channel
+java.nio.channels.Channels$1
+java.nio.channels.Channels
+java.nio.channels.ClosedByInterruptException
+java.nio.channels.ClosedChannelException
+java.nio.channels.DatagramChannel
+java.nio.channels.FileChannel$MapMode
+java.nio.channels.FileChannel
+java.nio.channels.FileLock
+java.nio.channels.GatheringByteChannel
+java.nio.channels.InterruptibleChannel
+java.nio.channels.MulticastChannel
+java.nio.channels.NetworkChannel
+java.nio.channels.OverlappingFileLockException
+java.nio.channels.ReadableByteChannel
+java.nio.channels.ScatteringByteChannel
+java.nio.channels.SeekableByteChannel
+java.nio.channels.SelectableChannel
+java.nio.channels.SelectionKey
+java.nio.channels.Selector
+java.nio.channels.ServerSocketChannel
+java.nio.channels.SocketChannel
+java.nio.channels.WritableByteChannel
+java.nio.channels.spi.AbstractInterruptibleChannel$1
+java.nio.channels.spi.AbstractInterruptibleChannel
+java.nio.channels.spi.AbstractSelectableChannel
+java.nio.channels.spi.AbstractSelectionKey
+java.nio.channels.spi.AbstractSelector$1
+java.nio.channels.spi.AbstractSelector
+java.nio.channels.spi.SelectorProvider$1
+java.nio.channels.spi.SelectorProvider
+java.nio.charset.CharacterCodingException
+java.nio.charset.Charset
+java.nio.charset.CharsetDecoder
+java.nio.charset.CharsetEncoder
+java.nio.charset.CoderMalfunctionError
+java.nio.charset.CoderResult$1
+java.nio.charset.CoderResult$2
+java.nio.charset.CoderResult$Cache
+java.nio.charset.CoderResult
+java.nio.charset.CodingErrorAction
+java.nio.charset.IllegalCharsetNameException
+java.nio.charset.StandardCharsets
+java.nio.charset.UnsupportedCharsetException
+java.nio.file.AccessMode
+java.nio.file.CopyMoveHelper
+java.nio.file.CopyOption
+java.nio.file.DirectoryStream$Filter
+java.nio.file.DirectoryStream
+java.nio.file.FileAlreadyExistsException
+java.nio.file.FileSystem
+java.nio.file.FileSystemException
+java.nio.file.FileSystems$DefaultFileSystemHolder$1
+java.nio.file.FileSystems$DefaultFileSystemHolder
+java.nio.file.FileSystems
+java.nio.file.Files$AcceptAllFilter
+java.nio.file.Files
+java.nio.file.InvalidPathException
+java.nio.file.LinkOption
+java.nio.file.NoSuchFileException
+java.nio.file.OpenOption
+java.nio.file.Path
+java.nio.file.Paths
+java.nio.file.StandardCopyOption
+java.nio.file.StandardOpenOption
+java.nio.file.Watchable
+java.nio.file.attribute.AttributeView
+java.nio.file.attribute.BasicFileAttributeView
+java.nio.file.attribute.BasicFileAttributes
+java.nio.file.attribute.FileAttribute
+java.nio.file.attribute.FileAttributeView
+java.nio.file.attribute.FileTime
+java.nio.file.attribute.PosixFileAttributes
+java.nio.file.spi.FileSystemProvider
+java.security.AccessControlContext
+java.security.AccessControlException
+java.security.AccessController
+java.security.AlgorithmConstraints
+java.security.AlgorithmParameters
+java.security.AlgorithmParametersSpi
+java.security.AllPermission
+java.security.BasicPermission
+java.security.CodeSigner
+java.security.CryptoPrimitive
+java.security.DigestException
+java.security.GeneralSecurityException
+java.security.Guard
+java.security.InvalidAlgorithmParameterException
+java.security.InvalidKeyException
+java.security.InvalidParameterException
+java.security.Key
+java.security.KeyException
+java.security.KeyFactory
+java.security.KeyFactorySpi
+java.security.KeyManagementException
+java.security.KeyPair
+java.security.KeyPairGenerator$Delegate
+java.security.KeyPairGenerator
+java.security.KeyPairGeneratorSpi
+java.security.KeyStore$1
+java.security.KeyStore$Entry
+java.security.KeyStore$LoadStoreParameter
+java.security.KeyStore$PasswordProtection
+java.security.KeyStore$PrivateKeyEntry
+java.security.KeyStore$ProtectionParameter
+java.security.KeyStore$SecretKeyEntry
+java.security.KeyStore$TrustedCertificateEntry
+java.security.KeyStore
+java.security.KeyStoreException
+java.security.KeyStoreSpi
+java.security.MessageDigest$Delegate
+java.security.MessageDigest
+java.security.MessageDigestSpi
+java.security.NoSuchAlgorithmException
+java.security.NoSuchProviderException
+java.security.Permission
+java.security.PermissionCollection
+java.security.Permissions
+java.security.Principal
+java.security.PrivateKey
+java.security.PrivilegedAction
+java.security.PrivilegedActionException
+java.security.PrivilegedExceptionAction
+java.security.ProtectionDomain
+java.security.Provider$EngineDescription
+java.security.Provider$Service
+java.security.Provider$ServiceKey
+java.security.Provider$UString
+java.security.Provider
+java.security.ProviderException
+java.security.PublicKey
+java.security.SecureRandom
+java.security.SecureRandomSpi
+java.security.Security
+java.security.SecurityPermission
+java.security.Signature$Delegate
+java.security.Signature
+java.security.SignatureException
+java.security.SignatureSpi
+java.security.UnrecoverableEntryException
+java.security.UnrecoverableKeyException
+java.security.cert.CRL
+java.security.cert.CRLException
+java.security.cert.CRLReason
+java.security.cert.CertPath
+java.security.cert.CertPathBuilderException
+java.security.cert.CertPathChecker
+java.security.cert.CertPathHelperImpl
+java.security.cert.CertPathParameters
+java.security.cert.CertPathValidator
+java.security.cert.CertPathValidatorException
+java.security.cert.CertPathValidatorResult
+java.security.cert.CertPathValidatorSpi
+java.security.cert.CertSelector
+java.security.cert.CertStore
+java.security.cert.CertStoreException
+java.security.cert.CertStoreParameters
+java.security.cert.CertStoreSpi
+java.security.cert.Certificate
+java.security.cert.CertificateEncodingException
+java.security.cert.CertificateException
+java.security.cert.CertificateExpiredException
+java.security.cert.CertificateFactory
+java.security.cert.CertificateFactorySpi
+java.security.cert.CertificateNotYetValidException
+java.security.cert.CertificateParsingException
+java.security.cert.CollectionCertStoreParameters
+java.security.cert.Extension
+java.security.cert.PKIXCertPathChecker
+java.security.cert.PKIXCertPathValidatorResult
+java.security.cert.PKIXParameters
+java.security.cert.PKIXRevocationChecker$Option
+java.security.cert.PKIXRevocationChecker
+java.security.cert.PolicyNode
+java.security.cert.PolicyQualifierInfo
+java.security.cert.TrustAnchor
+java.security.cert.X509CRL
+java.security.cert.X509CRLEntry
+java.security.cert.X509CertSelector
+java.security.cert.X509Certificate
+java.security.cert.X509Extension
+java.security.interfaces.DSAKey
+java.security.interfaces.DSAParams
+java.security.interfaces.DSAPublicKey
+java.security.interfaces.ECKey
+java.security.interfaces.ECPrivateKey
+java.security.interfaces.ECPublicKey
+java.security.interfaces.RSAKey
+java.security.interfaces.RSAPrivateCrtKey
+java.security.interfaces.RSAPrivateKey
+java.security.interfaces.RSAPublicKey
+java.security.spec.AlgorithmParameterSpec
+java.security.spec.DSAParameterSpec
+java.security.spec.DSAPublicKeySpec
+java.security.spec.ECField
+java.security.spec.ECFieldFp
+java.security.spec.ECGenParameterSpec
+java.security.spec.ECParameterSpec
+java.security.spec.ECPoint
+java.security.spec.ECPrivateKeySpec
+java.security.spec.ECPublicKeySpec
+java.security.spec.EllipticCurve
+java.security.spec.EncodedKeySpec
+java.security.spec.InvalidKeySpecException
+java.security.spec.InvalidParameterSpecException
+java.security.spec.KeySpec
+java.security.spec.MGF1ParameterSpec
+java.security.spec.PKCS8EncodedKeySpec
+java.security.spec.PSSParameterSpec
+java.security.spec.RSAKeyGenParameterSpec
+java.security.spec.RSAPrivateCrtKeySpec
+java.security.spec.RSAPrivateKeySpec
+java.security.spec.RSAPublicKeySpec
+java.security.spec.X509EncodedKeySpec
+java.sql.Date
+java.sql.SQLException
+java.sql.Time
+java.sql.Timestamp
+java.text.AttributedCharacterIterator$Attribute
+java.text.AttributedCharacterIterator
+java.text.AttributedString
+java.text.Bidi
+java.text.BreakIterator
+java.text.CalendarBuilder
+java.text.CharacterIterator
+java.text.CharacterIteratorFieldDelegate
+java.text.CollationElementIterator
+java.text.CollationKey
+java.text.Collator
+java.text.DateFormat$Field
+java.text.DateFormat
+java.text.DateFormatSymbols
+java.text.DecimalFormat$1
+java.text.DecimalFormat
+java.text.DecimalFormatSymbols
+java.text.DontCareFieldPosition$1
+java.text.DontCareFieldPosition
+java.text.FieldPosition$Delegate
+java.text.FieldPosition
+java.text.Format$Field
+java.text.Format$FieldDelegate
+java.text.Format
+java.text.IcuIteratorWrapper
+java.text.MessageFormat$Field
+java.text.MessageFormat
+java.text.Normalizer$Form
+java.text.Normalizer
+java.text.NumberFormat$Field
+java.text.NumberFormat
+java.text.ParseException
+java.text.ParsePosition
+java.text.RuleBasedCollator
+java.text.SimpleDateFormat
+java.text.StringCharacterIterator
+java.time.Clock$SystemClock
+java.time.Clock
+java.time.DateTimeException
+java.time.DayOfWeek
+java.time.Duration
+java.time.Instant$1
+java.time.Instant
+java.time.LocalDate$1
+java.time.LocalDate
+java.time.LocalDateTime
+java.time.LocalTime
+java.time.Month
+java.time.Period
+java.time.ZoneId
+java.time.ZoneOffset
+java.time.ZoneRegion
+java.time.ZonedDateTime
+java.time.chrono.AbstractChronology
+java.time.chrono.ChronoLocalDate
+java.time.chrono.ChronoLocalDateTime
+java.time.chrono.ChronoPeriod
+java.time.chrono.ChronoZonedDateTime
+java.time.chrono.Chronology
+java.time.chrono.IsoChronology
+java.time.format.DateTimeFormatter
+java.time.format.DateTimeFormatterBuilder$1
+java.time.format.DateTimeFormatterBuilder$2
+java.time.format.DateTimeFormatterBuilder$CharLiteralPrinterParser
+java.time.format.DateTimeFormatterBuilder$CompositePrinterParser
+java.time.format.DateTimeFormatterBuilder$DateTimePrinterParser
+java.time.format.DateTimeFormatterBuilder$FractionPrinterParser
+java.time.format.DateTimeFormatterBuilder$InstantPrinterParser
+java.time.format.DateTimeFormatterBuilder$NumberPrinterParser
+java.time.format.DateTimeFormatterBuilder$OffsetIdPrinterParser
+java.time.format.DateTimeFormatterBuilder$SettingsParser
+java.time.format.DateTimeFormatterBuilder$StringLiteralPrinterParser
+java.time.format.DateTimeFormatterBuilder$TextPrinterParser
+java.time.format.DateTimeFormatterBuilder$ZoneIdPrinterParser
+java.time.format.DateTimeFormatterBuilder
+java.time.format.DateTimeParseContext
+java.time.format.DateTimeParseException
+java.time.format.DateTimeTextProvider$1
+java.time.format.DateTimeTextProvider$LocaleStore
+java.time.format.DateTimeTextProvider
+java.time.format.DecimalStyle
+java.time.format.Parsed
+java.time.format.ResolverStyle
+java.time.format.SignStyle
+java.time.format.TextStyle
+java.time.temporal.ChronoField
+java.time.temporal.ChronoUnit
+java.time.temporal.IsoFields$Field$1
+java.time.temporal.IsoFields$Field$2
+java.time.temporal.IsoFields$Field$3
+java.time.temporal.IsoFields$Field$4
+java.time.temporal.IsoFields$Field
+java.time.temporal.IsoFields$Unit
+java.time.temporal.IsoFields
+java.time.temporal.JulianFields
+java.time.temporal.Temporal
+java.time.temporal.TemporalAccessor
+java.time.temporal.TemporalAdjuster
+java.time.temporal.TemporalAdjusters
+java.time.temporal.TemporalAmount
+java.time.temporal.TemporalField
+java.time.temporal.TemporalQueries
+java.time.temporal.TemporalQuery
+java.time.temporal.TemporalUnit
+java.time.temporal.UnsupportedTemporalTypeException
+java.time.temporal.ValueRange
+java.time.zone.IcuZoneRulesProvider$ZoneRulesCache
+java.time.zone.IcuZoneRulesProvider
+java.time.zone.ZoneOffsetTransition
+java.time.zone.ZoneOffsetTransitionRule$1
+java.time.zone.ZoneOffsetTransitionRule$TimeDefinition
+java.time.zone.ZoneOffsetTransitionRule
+java.time.zone.ZoneRules
+java.time.zone.ZoneRulesException
+java.time.zone.ZoneRulesProvider
+java.util.AbstractCollection
+java.util.AbstractList$1
+java.util.AbstractList$Itr
+java.util.AbstractList$ListItr
+java.util.AbstractList$RandomAccessSpliterator
+java.util.AbstractList$RandomAccessSubList
+java.util.AbstractList$SubList
+java.util.AbstractList
+java.util.AbstractMap$1
+java.util.AbstractMap$2
+java.util.AbstractMap$SimpleEntry
+java.util.AbstractMap$SimpleImmutableEntry
+java.util.AbstractMap
+java.util.AbstractQueue
+java.util.AbstractSequentialList
+java.util.AbstractSet
+java.util.ArrayDeque$DeqIterator
+java.util.ArrayDeque
+java.util.ArrayList$1
+java.util.ArrayList$ArrayListSpliterator
+java.util.ArrayList$Itr
+java.util.ArrayList$ListItr
+java.util.ArrayList$SubList$1
+java.util.ArrayList$SubList
+java.util.ArrayList
+java.util.ArrayPrefixHelpers$CumulateTask
+java.util.ArrayPrefixHelpers$DoubleCumulateTask
+java.util.ArrayPrefixHelpers$IntCumulateTask
+java.util.ArrayPrefixHelpers$LongCumulateTask
+java.util.Arrays$ArrayList
+java.util.Arrays$NaturalOrder
+java.util.Arrays
+java.util.ArraysParallelSortHelpers$FJByte$Sorter
+java.util.ArraysParallelSortHelpers$FJChar$Sorter
+java.util.ArraysParallelSortHelpers$FJDouble$Sorter
+java.util.ArraysParallelSortHelpers$FJFloat$Sorter
+java.util.ArraysParallelSortHelpers$FJInt$Sorter
+java.util.ArraysParallelSortHelpers$FJLong$Sorter
+java.util.ArraysParallelSortHelpers$FJObject$Sorter
+java.util.ArraysParallelSortHelpers$FJShort$Sorter
+java.util.Base64$Decoder
+java.util.Base64$Encoder
+java.util.Base64
+java.util.BitSet
+java.util.Calendar$Builder
+java.util.Calendar
+java.util.Collection
+java.util.Collections$1
+java.util.Collections$2
+java.util.Collections$3
+java.util.Collections$AsLIFOQueue
+java.util.Collections$CheckedCollection
+java.util.Collections$CheckedList
+java.util.Collections$CheckedMap
+java.util.Collections$CheckedNavigableMap
+java.util.Collections$CheckedNavigableSet
+java.util.Collections$CheckedQueue
+java.util.Collections$CheckedRandomAccessList
+java.util.Collections$CheckedSet
+java.util.Collections$CheckedSortedMap
+java.util.Collections$CheckedSortedSet
+java.util.Collections$CopiesList
+java.util.Collections$EmptyEnumeration
+java.util.Collections$EmptyIterator
+java.util.Collections$EmptyList
+java.util.Collections$EmptyListIterator
+java.util.Collections$EmptyMap
+java.util.Collections$EmptySet
+java.util.Collections$ReverseComparator2
+java.util.Collections$ReverseComparator
+java.util.Collections$SetFromMap
+java.util.Collections$SingletonList
+java.util.Collections$SingletonMap
+java.util.Collections$SingletonSet
+java.util.Collections$SynchronizedCollection
+java.util.Collections$SynchronizedList
+java.util.Collections$SynchronizedMap
+java.util.Collections$SynchronizedNavigableMap
+java.util.Collections$SynchronizedNavigableSet
+java.util.Collections$SynchronizedRandomAccessList
+java.util.Collections$SynchronizedSet
+java.util.Collections$SynchronizedSortedMap
+java.util.Collections$SynchronizedSortedSet
+java.util.Collections$UnmodifiableCollection$1
+java.util.Collections$UnmodifiableCollection
+java.util.Collections$UnmodifiableList$1
+java.util.Collections$UnmodifiableList
+java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$1
+java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry
+java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet
+java.util.Collections$UnmodifiableMap
+java.util.Collections$UnmodifiableNavigableMap$EmptyNavigableMap
+java.util.Collections$UnmodifiableNavigableMap
+java.util.Collections$UnmodifiableNavigableSet$EmptyNavigableSet
+java.util.Collections$UnmodifiableNavigableSet
+java.util.Collections$UnmodifiableRandomAccessList
+java.util.Collections$UnmodifiableSet
+java.util.Collections$UnmodifiableSortedMap
+java.util.Collections$UnmodifiableSortedSet
+java.util.Collections
+java.util.ComparableTimSort
+java.util.Comparator
+java.util.Comparators$NaturalOrderComparator
+java.util.Comparators$NullComparator
+java.util.ConcurrentModificationException
+java.util.Currency
+java.util.Date
+java.util.Deque
+java.util.Dictionary
+java.util.DualPivotQuicksort
+java.util.DuplicateFormatFlagsException
+java.util.EnumMap$1
+java.util.EnumMap$EntryIterator$Entry
+java.util.EnumMap$EntryIterator
+java.util.EnumMap$EntrySet
+java.util.EnumMap$EnumMapIterator
+java.util.EnumMap$KeyIterator
+java.util.EnumMap$KeySet
+java.util.EnumMap$ValueIterator
+java.util.EnumMap$Values
+java.util.EnumMap
+java.util.EnumSet$SerializationProxy
+java.util.EnumSet
+java.util.Enumeration
+java.util.EventListener
+java.util.EventObject
+java.util.FormatFlagsConversionMismatchException
+java.util.Formattable
+java.util.Formatter$Conversion
+java.util.Formatter$DateTime
+java.util.Formatter$FixedString
+java.util.Formatter$Flags
+java.util.Formatter$FormatSpecifier
+java.util.Formatter$FormatSpecifierParser
+java.util.Formatter$FormatString
+java.util.Formatter
+java.util.FormatterClosedException
+java.util.GregorianCalendar
+java.util.HashMap$EntryIterator
+java.util.HashMap$EntrySet
+java.util.HashMap$HashIterator
+java.util.HashMap$HashMapSpliterator
+java.util.HashMap$KeyIterator
+java.util.HashMap$KeySet
+java.util.HashMap$KeySpliterator
+java.util.HashMap$Node
+java.util.HashMap$TreeNode
+java.util.HashMap$ValueIterator
+java.util.HashMap$ValueSpliterator
+java.util.HashMap$Values
+java.util.HashMap
+java.util.HashSet
+java.util.Hashtable$EntrySet
+java.util.Hashtable$Enumerator
+java.util.Hashtable$HashtableEntry
+java.util.Hashtable$KeySet
+java.util.Hashtable$ValueCollection
+java.util.Hashtable
+java.util.IdentityHashMap$EntryIterator$Entry
+java.util.IdentityHashMap$EntryIterator
+java.util.IdentityHashMap$EntrySet
+java.util.IdentityHashMap$IdentityHashMapIterator
+java.util.IdentityHashMap$KeyIterator
+java.util.IdentityHashMap$KeySet
+java.util.IdentityHashMap$ValueIterator
+java.util.IdentityHashMap$Values
+java.util.IdentityHashMap
+java.util.IllegalFormatException
+java.util.IllegalFormatPrecisionException
+java.util.IllformedLocaleException
+java.util.ImmutableCollections$AbstractImmutableList
+java.util.ImmutableCollections$AbstractImmutableMap
+java.util.ImmutableCollections$AbstractImmutableSet
+java.util.ImmutableCollections$ListN
+java.util.ImmutableCollections$Map0
+java.util.ImmutableCollections$Map1
+java.util.ImmutableCollections$MapN
+java.util.ImmutableCollections$Set0
+java.util.ImmutableCollections$Set1
+java.util.ImmutableCollections$Set2
+java.util.ImmutableCollections$SetN
+java.util.Iterator
+java.util.JumboEnumSet$EnumSetIterator
+java.util.JumboEnumSet
+java.util.KeyValueHolder
+java.util.LinkedHashMap$LinkedEntryIterator
+java.util.LinkedHashMap$LinkedEntrySet
+java.util.LinkedHashMap$LinkedHashIterator
+java.util.LinkedHashMap$LinkedHashMapEntry
+java.util.LinkedHashMap$LinkedKeyIterator
+java.util.LinkedHashMap$LinkedKeySet
+java.util.LinkedHashMap$LinkedValueIterator
+java.util.LinkedHashMap$LinkedValues
+java.util.LinkedHashMap
+java.util.LinkedHashSet
+java.util.LinkedList$ListItr
+java.util.LinkedList$Node
+java.util.LinkedList
+java.util.List
+java.util.ListIterator
+java.util.ListResourceBundle
+java.util.Locale$1
+java.util.Locale$Builder
+java.util.Locale$Cache
+java.util.Locale$Category
+java.util.Locale$FilteringMode
+java.util.Locale$LanguageRange
+java.util.Locale$LocaleKey
+java.util.Locale$NoImagePreloadHolder
+java.util.Locale
+java.util.Map$Entry
+java.util.Map
+java.util.MissingFormatArgumentException
+java.util.MissingFormatWidthException
+java.util.MissingResourceException
+java.util.NavigableMap
+java.util.NavigableSet
+java.util.NoSuchElementException
+java.util.Objects
+java.util.Observable
+java.util.Observer
+java.util.Optional
+java.util.PrimitiveIterator$OfInt
+java.util.PrimitiveIterator
+java.util.PriorityQueue$Itr
+java.util.PriorityQueue
+java.util.Properties$LineReader
+java.util.Properties
+java.util.PropertyPermission
+java.util.PropertyResourceBundle
+java.util.Queue
+java.util.Random
+java.util.RandomAccess
+java.util.RegularEnumSet$EnumSetIterator
+java.util.RegularEnumSet
+java.util.ResourceBundle$1
+java.util.ResourceBundle$BundleReference
+java.util.ResourceBundle$CacheKey
+java.util.ResourceBundle$CacheKeyReference
+java.util.ResourceBundle$Control$1
+java.util.ResourceBundle$Control$CandidateListCache
+java.util.ResourceBundle$Control
+java.util.ResourceBundle$LoaderReference
+java.util.ResourceBundle
+java.util.Scanner$1
+java.util.Scanner
+java.util.ServiceConfigurationError
+java.util.ServiceLoader$1
+java.util.ServiceLoader$LazyIterator
+java.util.ServiceLoader
+java.util.Set
+java.util.SimpleTimeZone
+java.util.SortedMap
+java.util.SortedSet
+java.util.Spliterator$OfDouble
+java.util.Spliterator$OfInt
+java.util.Spliterator$OfLong
+java.util.Spliterator$OfPrimitive
+java.util.Spliterator
+java.util.Spliterators$ArraySpliterator
+java.util.Spliterators$EmptySpliterator$OfDouble
+java.util.Spliterators$EmptySpliterator$OfInt
+java.util.Spliterators$EmptySpliterator$OfLong
+java.util.Spliterators$EmptySpliterator$OfRef
+java.util.Spliterators$EmptySpliterator
+java.util.Spliterators$IntArraySpliterator
+java.util.Spliterators$IteratorSpliterator
+java.util.Spliterators
+java.util.Stack
+java.util.StringJoiner
+java.util.StringTokenizer
+java.util.TaskQueue
+java.util.TimSort
+java.util.TimeZone
+java.util.Timer$1
+java.util.Timer
+java.util.TimerTask
+java.util.TimerThread
+java.util.TreeMap$AscendingSubMap$AscendingEntrySetView
+java.util.TreeMap$AscendingSubMap
+java.util.TreeMap$DescendingSubMap
+java.util.TreeMap$EntryIterator
+java.util.TreeMap$EntrySet
+java.util.TreeMap$KeyIterator
+java.util.TreeMap$KeySet
+java.util.TreeMap$NavigableSubMap$EntrySetView
+java.util.TreeMap$NavigableSubMap$SubMapEntryIterator
+java.util.TreeMap$NavigableSubMap$SubMapIterator
+java.util.TreeMap$NavigableSubMap$SubMapKeyIterator
+java.util.TreeMap$NavigableSubMap
+java.util.TreeMap$PrivateEntryIterator
+java.util.TreeMap$TreeMapEntry
+java.util.TreeMap$ValueIterator
+java.util.TreeMap$Values
+java.util.TreeMap
+java.util.TreeSet
+java.util.UUID$Holder
+java.util.UUID
+java.util.UnknownFormatConversionException
+java.util.Vector$1
+java.util.Vector$Itr
+java.util.Vector
+java.util.WeakHashMap$1
+java.util.WeakHashMap$Entry
+java.util.WeakHashMap$EntryIterator
+java.util.WeakHashMap$EntrySet
+java.util.WeakHashMap$HashIterator
+java.util.WeakHashMap$KeyIterator
+java.util.WeakHashMap$KeySet
+java.util.WeakHashMap$ValueIterator
+java.util.WeakHashMap$Values
+java.util.WeakHashMap
+java.util.concurrent.AbstractExecutorService
+java.util.concurrent.ArrayBlockingQueue
+java.util.concurrent.BlockingDeque
+java.util.concurrent.BlockingQueue
+java.util.concurrent.Callable
+java.util.concurrent.CancellationException
+java.util.concurrent.CompletableFuture$AltResult
+java.util.concurrent.CompletableFuture$AsynchronousCompletionTask
+java.util.concurrent.CompletableFuture$Completion
+java.util.concurrent.CompletableFuture$Signaller
+java.util.concurrent.CompletableFuture$UniCompletion
+java.util.concurrent.CompletableFuture$UniWhenComplete
+java.util.concurrent.CompletableFuture
+java.util.concurrent.CompletionStage
+java.util.concurrent.ConcurrentHashMap$BaseIterator
+java.util.concurrent.ConcurrentHashMap$BulkTask
+java.util.concurrent.ConcurrentHashMap$CollectionView
+java.util.concurrent.ConcurrentHashMap$CounterCell
+java.util.concurrent.ConcurrentHashMap$EntryIterator
+java.util.concurrent.ConcurrentHashMap$EntrySetView
+java.util.concurrent.ConcurrentHashMap$ForEachEntryTask
+java.util.concurrent.ConcurrentHashMap$ForEachKeyTask
+java.util.concurrent.ConcurrentHashMap$ForEachMappingTask
+java.util.concurrent.ConcurrentHashMap$ForEachTransformedEntryTask
+java.util.concurrent.ConcurrentHashMap$ForEachTransformedKeyTask
+java.util.concurrent.ConcurrentHashMap$ForEachTransformedMappingTask
+java.util.concurrent.ConcurrentHashMap$ForEachTransformedValueTask
+java.util.concurrent.ConcurrentHashMap$ForEachValueTask
+java.util.concurrent.ConcurrentHashMap$ForwardingNode
+java.util.concurrent.ConcurrentHashMap$KeyIterator
+java.util.concurrent.ConcurrentHashMap$KeySetView
+java.util.concurrent.ConcurrentHashMap$MapEntry
+java.util.concurrent.ConcurrentHashMap$MapReduceEntriesTask
+java.util.concurrent.ConcurrentHashMap$MapReduceEntriesToDoubleTask
+java.util.concurrent.ConcurrentHashMap$MapReduceEntriesToIntTask
+java.util.concurrent.ConcurrentHashMap$MapReduceEntriesToLongTask
+java.util.concurrent.ConcurrentHashMap$MapReduceKeysTask
+java.util.concurrent.ConcurrentHashMap$MapReduceKeysToDoubleTask
+java.util.concurrent.ConcurrentHashMap$MapReduceKeysToIntTask
+java.util.concurrent.ConcurrentHashMap$MapReduceKeysToLongTask
+java.util.concurrent.ConcurrentHashMap$MapReduceMappingsTask
+java.util.concurrent.ConcurrentHashMap$MapReduceMappingsToDoubleTask
+java.util.concurrent.ConcurrentHashMap$MapReduceMappingsToIntTask
+java.util.concurrent.ConcurrentHashMap$MapReduceMappingsToLongTask
+java.util.concurrent.ConcurrentHashMap$MapReduceValuesTask
+java.util.concurrent.ConcurrentHashMap$MapReduceValuesToDoubleTask
+java.util.concurrent.ConcurrentHashMap$MapReduceValuesToIntTask
+java.util.concurrent.ConcurrentHashMap$MapReduceValuesToLongTask
+java.util.concurrent.ConcurrentHashMap$Node
+java.util.concurrent.ConcurrentHashMap$ReduceEntriesTask
+java.util.concurrent.ConcurrentHashMap$ReduceKeysTask
+java.util.concurrent.ConcurrentHashMap$ReduceValuesTask
+java.util.concurrent.ConcurrentHashMap$ReservationNode
+java.util.concurrent.ConcurrentHashMap$SearchEntriesTask
+java.util.concurrent.ConcurrentHashMap$SearchKeysTask
+java.util.concurrent.ConcurrentHashMap$SearchMappingsTask
+java.util.concurrent.ConcurrentHashMap$SearchValuesTask
+java.util.concurrent.ConcurrentHashMap$Segment
+java.util.concurrent.ConcurrentHashMap$TableStack
+java.util.concurrent.ConcurrentHashMap$Traverser
+java.util.concurrent.ConcurrentHashMap$TreeBin
+java.util.concurrent.ConcurrentHashMap$TreeNode
+java.util.concurrent.ConcurrentHashMap$ValueIterator
+java.util.concurrent.ConcurrentHashMap$ValuesView
+java.util.concurrent.ConcurrentHashMap
+java.util.concurrent.ConcurrentLinkedDeque$Node
+java.util.concurrent.ConcurrentLinkedDeque
+java.util.concurrent.ConcurrentLinkedQueue$Itr
+java.util.concurrent.ConcurrentLinkedQueue$Node
+java.util.concurrent.ConcurrentLinkedQueue
+java.util.concurrent.ConcurrentMap
+java.util.concurrent.ConcurrentNavigableMap
+java.util.concurrent.ConcurrentSkipListMap$HeadIndex
+java.util.concurrent.ConcurrentSkipListMap$Index
+java.util.concurrent.ConcurrentSkipListMap$Iter
+java.util.concurrent.ConcurrentSkipListMap$KeySet
+java.util.concurrent.ConcurrentSkipListMap$Node
+java.util.concurrent.ConcurrentSkipListMap$ValueIterator
+java.util.concurrent.ConcurrentSkipListMap$Values
+java.util.concurrent.ConcurrentSkipListMap
+java.util.concurrent.ConcurrentSkipListSet
+java.util.concurrent.CopyOnWriteArrayList$COWIterator
+java.util.concurrent.CopyOnWriteArrayList
+java.util.concurrent.CopyOnWriteArraySet
+java.util.concurrent.CountDownLatch$Sync
+java.util.concurrent.CountDownLatch
+java.util.concurrent.CountedCompleter
+java.util.concurrent.DelayQueue
+java.util.concurrent.Delayed
+java.util.concurrent.ExecutionException
+java.util.concurrent.Executor
+java.util.concurrent.ExecutorService
+java.util.concurrent.Executors$DefaultThreadFactory
+java.util.concurrent.Executors$DelegatedExecutorService
+java.util.concurrent.Executors$DelegatedScheduledExecutorService
+java.util.concurrent.Executors$FinalizableDelegatedExecutorService
+java.util.concurrent.Executors$RunnableAdapter
+java.util.concurrent.Executors
+java.util.concurrent.ForkJoinPool$1
+java.util.concurrent.ForkJoinPool$DefaultForkJoinWorkerThreadFactory
+java.util.concurrent.ForkJoinPool$ForkJoinWorkerThreadFactory
+java.util.concurrent.ForkJoinPool$ManagedBlocker
+java.util.concurrent.ForkJoinPool
+java.util.concurrent.ForkJoinTask$ExceptionNode
+java.util.concurrent.ForkJoinTask
+java.util.concurrent.ForkJoinWorkerThread
+java.util.concurrent.Future
+java.util.concurrent.FutureTask$WaitNode
+java.util.concurrent.FutureTask
+java.util.concurrent.LinkedBlockingDeque$Node
+java.util.concurrent.LinkedBlockingDeque
+java.util.concurrent.LinkedBlockingQueue$Itr
+java.util.concurrent.LinkedBlockingQueue$Node
+java.util.concurrent.LinkedBlockingQueue
+java.util.concurrent.PriorityBlockingQueue
+java.util.concurrent.RejectedExecutionException
+java.util.concurrent.RejectedExecutionHandler
+java.util.concurrent.RunnableFuture
+java.util.concurrent.RunnableScheduledFuture
+java.util.concurrent.ScheduledExecutorService
+java.util.concurrent.ScheduledFuture
+java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue$Itr
+java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue
+java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask
+java.util.concurrent.ScheduledThreadPoolExecutor
+java.util.concurrent.Semaphore$FairSync
+java.util.concurrent.Semaphore$NonfairSync
+java.util.concurrent.Semaphore$Sync
+java.util.concurrent.Semaphore
+java.util.concurrent.SynchronousQueue$TransferStack$SNode
+java.util.concurrent.SynchronousQueue$TransferStack
+java.util.concurrent.SynchronousQueue$Transferer
+java.util.concurrent.SynchronousQueue
+java.util.concurrent.ThreadFactory
+java.util.concurrent.ThreadLocalRandom$1
+java.util.concurrent.ThreadLocalRandom
+java.util.concurrent.ThreadPoolExecutor$AbortPolicy
+java.util.concurrent.ThreadPoolExecutor$DiscardPolicy
+java.util.concurrent.ThreadPoolExecutor$Worker
+java.util.concurrent.ThreadPoolExecutor
+java.util.concurrent.TimeUnit$1
+java.util.concurrent.TimeUnit$2
+java.util.concurrent.TimeUnit$3
+java.util.concurrent.TimeUnit$4
+java.util.concurrent.TimeUnit$5
+java.util.concurrent.TimeUnit$6
+java.util.concurrent.TimeUnit$7
+java.util.concurrent.TimeUnit
+java.util.concurrent.TimeoutException
+java.util.concurrent.atomic.AtomicBoolean
+java.util.concurrent.atomic.AtomicInteger
+java.util.concurrent.atomic.AtomicIntegerArray
+java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl
+java.util.concurrent.atomic.AtomicIntegerFieldUpdater
+java.util.concurrent.atomic.AtomicLong
+java.util.concurrent.atomic.AtomicLongArray
+java.util.concurrent.atomic.AtomicLongFieldUpdater$CASUpdater
+java.util.concurrent.atomic.AtomicLongFieldUpdater
+java.util.concurrent.atomic.AtomicReference
+java.util.concurrent.atomic.AtomicReferenceArray
+java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl
+java.util.concurrent.atomic.AtomicReferenceFieldUpdater
+java.util.concurrent.atomic.LongAdder
+java.util.concurrent.atomic.Striped64
+java.util.concurrent.locks.AbstractOwnableSynchronizer
+java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject
+java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
+java.util.concurrent.locks.AbstractQueuedSynchronizer
+java.util.concurrent.locks.Condition
+java.util.concurrent.locks.Lock
+java.util.concurrent.locks.LockSupport
+java.util.concurrent.locks.ReadWriteLock
+java.util.concurrent.locks.ReentrantLock$FairSync
+java.util.concurrent.locks.ReentrantLock$NonfairSync
+java.util.concurrent.locks.ReentrantLock$Sync
+java.util.concurrent.locks.ReentrantLock
+java.util.concurrent.locks.ReentrantReadWriteLock$FairSync
+java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync
+java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock
+java.util.concurrent.locks.ReentrantReadWriteLock$Sync$HoldCounter
+java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter
+java.util.concurrent.locks.ReentrantReadWriteLock$Sync
+java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock
+java.util.concurrent.locks.ReentrantReadWriteLock
+java.util.function.BiConsumer
+java.util.function.BiFunction
+java.util.function.BiPredicate
+java.util.function.BinaryOperator
+java.util.function.BooleanSupplier
+java.util.function.Consumer
+java.util.function.DoubleBinaryOperator
+java.util.function.DoubleSupplier
+java.util.function.DoubleUnaryOperator
+java.util.function.Function
+java.util.function.IntBinaryOperator
+java.util.function.IntConsumer
+java.util.function.IntFunction
+java.util.function.IntPredicate
+java.util.function.IntSupplier
+java.util.function.IntToDoubleFunction
+java.util.function.IntToLongFunction
+java.util.function.IntUnaryOperator
+java.util.function.LongBinaryOperator
+java.util.function.LongConsumer
+java.util.function.LongSupplier
+java.util.function.LongUnaryOperator
+java.util.function.Predicate
+java.util.function.Supplier
+java.util.function.ToDoubleBiFunction
+java.util.function.ToDoubleFunction
+java.util.function.ToIntBiFunction
+java.util.function.ToIntFunction
+java.util.function.ToLongBiFunction
+java.util.function.ToLongFunction
+java.util.function.UnaryOperator
+java.util.jar.Attributes$Name
+java.util.jar.Attributes
+java.util.jar.JarEntry
+java.util.jar.JarFile$JarEntryIterator
+java.util.jar.JarFile$JarFileEntry
+java.util.jar.JarFile
+java.util.jar.JarVerifier$3
+java.util.jar.JarVerifier$VerifierStream
+java.util.jar.JarVerifier
+java.util.jar.Manifest$FastInputStream
+java.util.jar.Manifest
+java.util.logging.ErrorManager
+java.util.logging.FileHandler$MeteredStream
+java.util.logging.Formatter
+java.util.logging.Handler
+java.util.logging.Level$KnownLevel
+java.util.logging.Level
+java.util.logging.LogManager$1
+java.util.logging.LogManager$2
+java.util.logging.LogManager$3
+java.util.logging.LogManager$5
+java.util.logging.LogManager$Cleaner
+java.util.logging.LogManager$LogNode
+java.util.logging.LogManager$LoggerContext$1
+java.util.logging.LogManager$LoggerContext
+java.util.logging.LogManager$LoggerWeakRef
+java.util.logging.LogManager$RootLogger
+java.util.logging.LogManager$SystemLoggerContext
+java.util.logging.LogManager
+java.util.logging.LogRecord
+java.util.logging.Logger$1
+java.util.logging.Logger$LoggerBundle
+java.util.logging.Logger$SystemLoggerHelper$1
+java.util.logging.Logger$SystemLoggerHelper
+java.util.logging.Logger
+java.util.logging.LoggingPermission
+java.util.logging.LoggingProxyImpl
+java.util.logging.StreamHandler
+java.util.prefs.AbstractPreferences
+java.util.prefs.BackingStoreException
+java.util.prefs.FileSystemPreferences$3
+java.util.prefs.FileSystemPreferences
+java.util.prefs.FileSystemPreferencesFactory
+java.util.prefs.Preferences
+java.util.prefs.PreferencesFactory
+java.util.regex.MatchResult
+java.util.regex.Matcher
+java.util.regex.Pattern
+java.util.regex.PatternSyntaxException
+java.util.stream.AbstractPipeline
+java.util.stream.AbstractSpinedBuffer
+java.util.stream.BaseStream
+java.util.stream.Collector$Characteristics
+java.util.stream.Collector
+java.util.stream.Collectors$CollectorImpl
+java.util.stream.Collectors
+java.util.stream.DistinctOps$1$2
+java.util.stream.DistinctOps$1
+java.util.stream.DistinctOps
+java.util.stream.DoubleStream
+java.util.stream.FindOps$FindOp
+java.util.stream.FindOps$FindSink$OfRef
+java.util.stream.FindOps$FindSink
+java.util.stream.FindOps
+java.util.stream.ForEachOps$ForEachOp$OfRef
+java.util.stream.ForEachOps$ForEachOp
+java.util.stream.ForEachOps
+java.util.stream.IntPipeline$4$1
+java.util.stream.IntPipeline$4
+java.util.stream.IntPipeline$Head
+java.util.stream.IntPipeline$StatelessOp
+java.util.stream.IntPipeline
+java.util.stream.IntStream
+java.util.stream.LongPipeline$StatelessOp
+java.util.stream.LongPipeline
+java.util.stream.LongStream
+java.util.stream.MatchOps$1MatchSink
+java.util.stream.MatchOps$BooleanTerminalSink
+java.util.stream.MatchOps$MatchKind
+java.util.stream.MatchOps$MatchOp
+java.util.stream.MatchOps
+java.util.stream.Node$Builder$OfInt
+java.util.stream.Node$Builder
+java.util.stream.Node$OfDouble
+java.util.stream.Node$OfInt
+java.util.stream.Node$OfLong
+java.util.stream.Node$OfPrimitive
+java.util.stream.Node
+java.util.stream.Nodes$ArrayNode
+java.util.stream.Nodes$EmptyNode$OfDouble
+java.util.stream.Nodes$EmptyNode$OfInt
+java.util.stream.Nodes$EmptyNode$OfLong
+java.util.stream.Nodes$EmptyNode$OfRef
+java.util.stream.Nodes$EmptyNode
+java.util.stream.Nodes$FixedNodeBuilder
+java.util.stream.Nodes$IntArrayNode
+java.util.stream.Nodes$IntFixedNodeBuilder
+java.util.stream.Nodes$IntSpinedNodeBuilder
+java.util.stream.Nodes
+java.util.stream.PipelineHelper
+java.util.stream.ReduceOps$1
+java.util.stream.ReduceOps$1ReducingSink
+java.util.stream.ReduceOps$3
+java.util.stream.ReduceOps$3ReducingSink
+java.util.stream.ReduceOps$5
+java.util.stream.ReduceOps$5ReducingSink
+java.util.stream.ReduceOps$8
+java.util.stream.ReduceOps$8ReducingSink
+java.util.stream.ReduceOps$AccumulatingSink
+java.util.stream.ReduceOps$Box
+java.util.stream.ReduceOps$ReduceOp
+java.util.stream.ReduceOps
+java.util.stream.ReferencePipeline$2$1
+java.util.stream.ReferencePipeline$2
+java.util.stream.ReferencePipeline$3$1
+java.util.stream.ReferencePipeline$3
+java.util.stream.ReferencePipeline$4$1
+java.util.stream.ReferencePipeline$4
+java.util.stream.ReferencePipeline$5$1
+java.util.stream.ReferencePipeline$5
+java.util.stream.ReferencePipeline$Head
+java.util.stream.ReferencePipeline$StatefulOp
+java.util.stream.ReferencePipeline$StatelessOp
+java.util.stream.ReferencePipeline
+java.util.stream.Sink$ChainedInt
+java.util.stream.Sink$ChainedReference
+java.util.stream.Sink$OfInt
+java.util.stream.Sink$OfLong
+java.util.stream.Sink
+java.util.stream.SliceOps$1$1
+java.util.stream.SliceOps$1
+java.util.stream.SliceOps
+java.util.stream.SpinedBuffer$OfInt
+java.util.stream.SpinedBuffer$OfPrimitive
+java.util.stream.Stream
+java.util.stream.StreamOpFlag$MaskBuilder
+java.util.stream.StreamOpFlag$Type
+java.util.stream.StreamOpFlag
+java.util.stream.StreamShape
+java.util.stream.StreamSpliterators$InfiniteSupplyingSpliterator$OfRef
+java.util.stream.StreamSpliterators$InfiniteSupplyingSpliterator
+java.util.stream.StreamSupport
+java.util.stream.Streams$2
+java.util.stream.Streams$ConcatSpliterator$OfRef
+java.util.stream.Streams$ConcatSpliterator
+java.util.stream.Streams$RangeIntSpliterator
+java.util.stream.Streams
+java.util.stream.TerminalOp
+java.util.stream.TerminalSink
+java.util.zip.Adler32
+java.util.zip.CRC32
+java.util.zip.CheckedInputStream
+java.util.zip.Checksum
+java.util.zip.DataFormatException
+java.util.zip.Deflater
+java.util.zip.DeflaterOutputStream
+java.util.zip.GZIPInputStream$1
+java.util.zip.GZIPInputStream
+java.util.zip.GZIPOutputStream
+java.util.zip.Inflater
+java.util.zip.InflaterInputStream
+java.util.zip.ZStreamRef
+java.util.zip.ZipCoder
+java.util.zip.ZipConstants
+java.util.zip.ZipEntry
+java.util.zip.ZipError
+java.util.zip.ZipException
+java.util.zip.ZipFile$ZipEntryIterator
+java.util.zip.ZipFile$ZipFileInflaterInputStream
+java.util.zip.ZipFile$ZipFileInputStream
+java.util.zip.ZipFile
+java.util.zip.ZipInputStream
+java.util.zip.ZipOutputStream
+java.util.zip.ZipUtils
+javax.crypto.AEADBadTagException
+javax.crypto.BadPaddingException
+javax.crypto.Cipher$1
+javax.crypto.Cipher$CipherSpiAndProvider
+javax.crypto.Cipher$InitParams
+javax.crypto.Cipher$InitType
+javax.crypto.Cipher$NeedToSet
+javax.crypto.Cipher$SpiAndProviderUpdater
+javax.crypto.Cipher$Transform
+javax.crypto.Cipher
+javax.crypto.CipherOutputStream
+javax.crypto.CipherSpi
+javax.crypto.IllegalBlockSizeException
+javax.crypto.JceSecurity
+javax.crypto.KeyAgreementSpi
+javax.crypto.KeyGenerator
+javax.crypto.KeyGeneratorSpi
+javax.crypto.Mac
+javax.crypto.MacSpi
+javax.crypto.NoSuchPaddingException
+javax.crypto.NullCipher
+javax.crypto.SecretKey
+javax.crypto.SecretKeyFactory
+javax.crypto.SecretKeyFactorySpi
+javax.crypto.ShortBufferException
+javax.crypto.interfaces.PBEKey
+javax.crypto.spec.DESedeKeySpec
+javax.crypto.spec.GCMParameterSpec
+javax.crypto.spec.IvParameterSpec
+javax.crypto.spec.OAEPParameterSpec
+javax.crypto.spec.PBEKeySpec
+javax.crypto.spec.PBEParameterSpec
+javax.crypto.spec.PSource$PSpecified
+javax.crypto.spec.PSource
+javax.crypto.spec.SecretKeySpec
+javax.net.DefaultSocketFactory
+javax.net.ServerSocketFactory
+javax.net.SocketFactory
+javax.net.ssl.ExtendedSSLSession
+javax.net.ssl.HandshakeCompletedEvent
+javax.net.ssl.HandshakeCompletedListener
+javax.net.ssl.HostnameVerifier
+javax.net.ssl.HttpsURLConnection
+javax.net.ssl.KeyManager
+javax.net.ssl.KeyManagerFactory$1
+javax.net.ssl.KeyManagerFactory
+javax.net.ssl.KeyManagerFactorySpi
+javax.net.ssl.ManagerFactoryParameters
+javax.net.ssl.SNIHostName
+javax.net.ssl.SNIMatcher
+javax.net.ssl.SNIServerName
+javax.net.ssl.SSLContext
+javax.net.ssl.SSLContextSpi
+javax.net.ssl.SSLEngine
+javax.net.ssl.SSLEngineResult$HandshakeStatus
+javax.net.ssl.SSLEngineResult$Status
+javax.net.ssl.SSLEngineResult
+javax.net.ssl.SSLException
+javax.net.ssl.SSLHandshakeException
+javax.net.ssl.SSLParameters
+javax.net.ssl.SSLPeerUnverifiedException
+javax.net.ssl.SSLProtocolException
+javax.net.ssl.SSLServerSocket
+javax.net.ssl.SSLServerSocketFactory
+javax.net.ssl.SSLSession
+javax.net.ssl.SSLSessionBindingEvent
+javax.net.ssl.SSLSessionBindingListener
+javax.net.ssl.SSLSessionContext
+javax.net.ssl.SSLSocket
+javax.net.ssl.SSLSocketFactory$1
+javax.net.ssl.SSLSocketFactory
+javax.net.ssl.TrustManager
+javax.net.ssl.TrustManagerFactory$1
+javax.net.ssl.TrustManagerFactory
+javax.net.ssl.TrustManagerFactorySpi
+javax.net.ssl.X509ExtendedKeyManager
+javax.net.ssl.X509ExtendedTrustManager
+javax.net.ssl.X509KeyManager
+javax.net.ssl.X509TrustManager
+javax.security.auth.Destroyable
+javax.security.auth.callback.UnsupportedCallbackException
+javax.security.auth.x500.X500Principal
+javax.security.cert.Certificate
+javax.security.cert.CertificateEncodingException
+javax.security.cert.CertificateException
+javax.security.cert.X509Certificate$1
+javax.security.cert.X509Certificate
+javax.xml.parsers.DocumentBuilder
+javax.xml.parsers.DocumentBuilderFactory
+javax.xml.parsers.ParserConfigurationException
+javax.xml.parsers.SAXParser
+javax.xml.parsers.SAXParserFactory
+jdk.internal.util.Preconditions
+libcore.content.type.MimeMap$Builder
+libcore.content.type.MimeMap$MemoizingSupplier
+libcore.content.type.MimeMap
+libcore.icu.CollationKeyICU
+libcore.icu.DateIntervalFormat
+libcore.icu.DateUtilsBridge
+libcore.icu.ICU
+libcore.icu.LocaleData
+libcore.icu.TimeZoneNames$1
+libcore.icu.TimeZoneNames$ZoneStringsCache
+libcore.icu.TimeZoneNames
+libcore.internal.StringPool
+libcore.io.AsynchronousCloseMonitor
+libcore.io.BlockGuardOs
+libcore.io.BufferIterator
+libcore.io.ClassPathURLStreamHandler$ClassPathURLConnection$1
+libcore.io.ClassPathURLStreamHandler$ClassPathURLConnection
+libcore.io.ClassPathURLStreamHandler
+libcore.io.ForwardingOs
+libcore.io.IoBridge
+libcore.io.IoTracker$Mode
+libcore.io.IoTracker
+libcore.io.IoUtils$FileReader
+libcore.io.IoUtils
+libcore.io.Libcore
+libcore.io.Linux
+libcore.io.Memory
+libcore.io.MemoryMappedFile
+libcore.io.NioBufferIterator
+libcore.io.Os
+libcore.io.Streams
+libcore.math.MathUtils
+libcore.math.NativeBN
+libcore.net.InetAddressUtils
+libcore.net.NetworkSecurityPolicy$DefaultNetworkSecurityPolicy
+libcore.net.NetworkSecurityPolicy
+libcore.net.event.NetworkEventDispatcher
+libcore.net.event.NetworkEventListener
+libcore.net.http.HttpDate$1
+libcore.net.http.HttpDate
+libcore.reflect.AnnotatedElements
+libcore.reflect.AnnotationFactory
+libcore.reflect.AnnotationMember$DefaultValues
+libcore.reflect.AnnotationMember
+libcore.reflect.GenericArrayTypeImpl
+libcore.reflect.GenericSignatureParser
+libcore.reflect.ListOfTypes
+libcore.reflect.ListOfVariables
+libcore.reflect.ParameterizedTypeImpl
+libcore.reflect.TypeVariableImpl
+libcore.reflect.Types
+libcore.reflect.WildcardTypeImpl
+libcore.util.ArrayUtils
+libcore.util.BasicLruCache
+libcore.util.CharsetUtils
+libcore.util.CollectionUtils
+libcore.util.EmptyArray
+libcore.util.FP16
+libcore.util.HexEncoding
+libcore.util.NativeAllocationRegistry$CleanerRunner
+libcore.util.NativeAllocationRegistry$CleanerThunk
+libcore.util.NativeAllocationRegistry
+libcore.util.Objects
+libcore.util.SneakyThrow
+libcore.util.XmlObjectFactory
+libcore.util.ZoneInfo
+org.apache.harmony.dalvik.ddmc.Chunk
+org.apache.harmony.dalvik.ddmc.ChunkHandler
+org.apache.harmony.dalvik.ddmc.DdmServer
+org.apache.harmony.dalvik.ddmc.DdmVmInternal
+org.apache.harmony.xml.ExpatAttributes
+org.apache.harmony.xml.ExpatException
+org.apache.harmony.xml.ExpatParser$CurrentAttributes
+org.apache.harmony.xml.ExpatParser$ExpatLocator
+org.apache.harmony.xml.ExpatParser
+org.apache.harmony.xml.ExpatReader
+org.apache.harmony.xml.dom.CharacterDataImpl
+org.apache.harmony.xml.dom.DocumentImpl
+org.apache.harmony.xml.dom.ElementImpl
+org.apache.harmony.xml.dom.InnerNodeImpl
+org.apache.harmony.xml.dom.LeafNodeImpl
+org.apache.harmony.xml.dom.NodeImpl$1
+org.apache.harmony.xml.dom.NodeImpl
+org.apache.harmony.xml.dom.NodeListImpl
+org.apache.harmony.xml.dom.TextImpl
+org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl
+org.apache.harmony.xml.parsers.SAXParserFactoryImpl
+org.apache.harmony.xml.parsers.SAXParserImpl
+org.json.JSON
+org.json.JSONArray
+org.json.JSONException
+org.json.JSONObject$1
+org.json.JSONObject
+org.json.JSONStringer$Scope
+org.json.JSONStringer
+org.json.JSONTokener
+org.w3c.dom.CharacterData
+org.w3c.dom.DOMImplementation
+org.w3c.dom.Document
+org.w3c.dom.Element
+org.w3c.dom.Node
+org.w3c.dom.NodeList
+org.w3c.dom.Text
+org.w3c.dom.TypeInfo
+org.xml.sax.AttributeList
+org.xml.sax.Attributes
+org.xml.sax.ContentHandler
+org.xml.sax.DTDHandler
+org.xml.sax.EntityResolver
+org.xml.sax.ErrorHandler
+org.xml.sax.InputSource
+org.xml.sax.Locator
+org.xml.sax.Parser
+org.xml.sax.SAXException
+org.xml.sax.SAXNotRecognizedException
+org.xml.sax.SAXNotSupportedException
+org.xml.sax.XMLFilter
+org.xml.sax.XMLReader
+org.xml.sax.ext.DeclHandler
+org.xml.sax.ext.DefaultHandler2
+org.xml.sax.ext.EntityResolver2
+org.xml.sax.ext.LexicalHandler
+org.xml.sax.helpers.DefaultHandler
+org.xml.sax.helpers.XMLFilterImpl
+org.xmlpull.v1.XmlPullParser
+org.xmlpull.v1.XmlPullParserException
+org.xmlpull.v1.XmlPullParserFactory
+org.xmlpull.v1.XmlSerializer
+sun.invoke.util.BytecodeDescriptor
+sun.invoke.util.VerifyAccess
+sun.invoke.util.Wrapper$Format
+sun.invoke.util.Wrapper
+sun.misc.ASCIICaseInsensitiveComparator
+sun.misc.Cleaner$1
+sun.misc.Cleaner
+sun.misc.CompoundEnumeration
+sun.misc.FDBigInteger
+sun.misc.FloatingDecimal$1
+sun.misc.FloatingDecimal$ASCIIToBinaryBuffer
+sun.misc.FloatingDecimal$ASCIIToBinaryConverter
+sun.misc.FloatingDecimal$BinaryToASCIIBuffer
+sun.misc.FloatingDecimal$BinaryToASCIIConverter
+sun.misc.FloatingDecimal$ExceptionalBinaryToASCIIBuffer
+sun.misc.FloatingDecimal$PreparedASCIIToBinaryBuffer
+sun.misc.FloatingDecimal
+sun.misc.FormattedFloatingDecimal$1
+sun.misc.FormattedFloatingDecimal$2
+sun.misc.FormattedFloatingDecimal$Form
+sun.misc.FormattedFloatingDecimal
+sun.misc.IOUtils
+sun.misc.JavaIOFileDescriptorAccess
+sun.misc.LRUCache
+sun.misc.SharedSecrets
+sun.misc.Unsafe
+sun.misc.VM
+sun.misc.Version
+sun.net.ConnectionResetException
+sun.net.NetHooks
+sun.net.NetProperties$1
+sun.net.NetProperties
+sun.net.ResourceManager
+sun.net.spi.DefaultProxySelector$1
+sun.net.spi.DefaultProxySelector$NonProxyInfo
+sun.net.spi.DefaultProxySelector
+sun.net.spi.nameservice.NameService
+sun.net.util.IPAddressUtil
+sun.net.www.ParseUtil
+sun.net.www.protocol.file.Handler
+sun.net.www.protocol.jar.Handler
+sun.nio.ch.AbstractPollArrayWrapper
+sun.nio.ch.AbstractPollSelectorImpl
+sun.nio.ch.AllocatedNativeObject
+sun.nio.ch.ChannelInputStream
+sun.nio.ch.DatagramChannelImpl
+sun.nio.ch.DatagramDispatcher
+sun.nio.ch.DefaultSelectorProvider
+sun.nio.ch.DirectBuffer
+sun.nio.ch.FileChannelImpl$Unmapper
+sun.nio.ch.FileChannelImpl
+sun.nio.ch.FileDescriptorHolderSocketImpl
+sun.nio.ch.FileDispatcher
+sun.nio.ch.FileDispatcherImpl
+sun.nio.ch.FileKey
+sun.nio.ch.FileLockImpl
+sun.nio.ch.FileLockTable
+sun.nio.ch.IOStatus
+sun.nio.ch.IOUtil
+sun.nio.ch.Interruptible
+sun.nio.ch.NativeDispatcher
+sun.nio.ch.NativeObject
+sun.nio.ch.NativeThread
+sun.nio.ch.NativeThreadSet
+sun.nio.ch.Net$1
+sun.nio.ch.Net$3
+sun.nio.ch.Net
+sun.nio.ch.PollArrayWrapper
+sun.nio.ch.PollSelectorImpl
+sun.nio.ch.PollSelectorProvider
+sun.nio.ch.SelChImpl
+sun.nio.ch.SelectionKeyImpl
+sun.nio.ch.SelectorImpl
+sun.nio.ch.SelectorProviderImpl
+sun.nio.ch.ServerSocketChannelImpl
+sun.nio.ch.SharedFileLockTable$FileLockReference
+sun.nio.ch.SharedFileLockTable
+sun.nio.ch.SocketAdaptor$1
+sun.nio.ch.SocketAdaptor$2
+sun.nio.ch.SocketAdaptor$SocketInputStream
+sun.nio.ch.SocketAdaptor
+sun.nio.ch.SocketChannelImpl
+sun.nio.ch.SocketDispatcher
+sun.nio.ch.Util$1
+sun.nio.ch.Util$2
+sun.nio.ch.Util$3
+sun.nio.ch.Util$BufferCache
+sun.nio.ch.Util
+sun.nio.cs.ArrayDecoder
+sun.nio.cs.ArrayEncoder
+sun.nio.cs.StreamDecoder
+sun.nio.cs.StreamEncoder
+sun.nio.cs.ThreadLocalCoders$1
+sun.nio.cs.ThreadLocalCoders$2
+sun.nio.cs.ThreadLocalCoders$Cache
+sun.nio.cs.ThreadLocalCoders
+sun.nio.fs.AbstractBasicFileAttributeView
+sun.nio.fs.AbstractFileSystemProvider
+sun.nio.fs.AbstractPath
+sun.nio.fs.DefaultFileSystemProvider
+sun.nio.fs.DynamicFileAttributeView
+sun.nio.fs.LinuxFileSystem
+sun.nio.fs.LinuxFileSystemProvider
+sun.nio.fs.NativeBuffer$Deallocator
+sun.nio.fs.NativeBuffer
+sun.nio.fs.NativeBuffers
+sun.nio.fs.UnixChannelFactory$Flags
+sun.nio.fs.UnixConstants
+sun.nio.fs.UnixException
+sun.nio.fs.UnixFileAttributeViews$Basic
+sun.nio.fs.UnixFileAttributeViews
+sun.nio.fs.UnixFileAttributes$UnixAsBasicFileAttributes
+sun.nio.fs.UnixFileAttributes
+sun.nio.fs.UnixFileModeAttribute
+sun.nio.fs.UnixFileStoreAttributes
+sun.nio.fs.UnixFileSystem
+sun.nio.fs.UnixFileSystemProvider
+sun.nio.fs.UnixMountEntry
+sun.nio.fs.UnixNativeDispatcher
+sun.nio.fs.UnixPath
+sun.nio.fs.Util
+sun.reflect.Reflection
+sun.reflect.misc.ReflectUtil
+sun.security.action.GetBooleanAction
+sun.security.action.GetIntegerAction
+sun.security.action.GetPropertyAction
+sun.security.jca.GetInstance$Instance
+sun.security.jca.GetInstance
+sun.security.jca.JCAUtil$CachedSecureRandomHolder
+sun.security.jca.JCAUtil
+sun.security.jca.ProviderConfig$2
+sun.security.jca.ProviderConfig
+sun.security.jca.ProviderList$1
+sun.security.jca.ProviderList$2
+sun.security.jca.ProviderList$3
+sun.security.jca.ProviderList$ServiceList$1
+sun.security.jca.ProviderList$ServiceList
+sun.security.jca.ProviderList
+sun.security.jca.Providers
+sun.security.jca.ServiceId
+sun.security.pkcs.ContentInfo
+sun.security.pkcs.PKCS7$VerbatimX509Certificate
+sun.security.pkcs.PKCS7$WrappedX509Certificate
+sun.security.pkcs.PKCS7
+sun.security.pkcs.PKCS9Attribute
+sun.security.pkcs.SignerInfo
+sun.security.provider.CertPathProvider
+sun.security.provider.X509Factory
+sun.security.provider.certpath.AdaptableX509CertSelector
+sun.security.provider.certpath.AlgorithmChecker
+sun.security.provider.certpath.BasicChecker
+sun.security.provider.certpath.CertId
+sun.security.provider.certpath.CertPathHelper
+sun.security.provider.certpath.ConstraintsChecker
+sun.security.provider.certpath.KeyChecker
+sun.security.provider.certpath.OCSP$RevocationStatus$CertStatus
+sun.security.provider.certpath.OCSP$RevocationStatus
+sun.security.provider.certpath.OCSPResponse$1
+sun.security.provider.certpath.OCSPResponse$ResponseStatus
+sun.security.provider.certpath.OCSPResponse$SingleResponse
+sun.security.provider.certpath.OCSPResponse
+sun.security.provider.certpath.PKIX$ValidatorParams
+sun.security.provider.certpath.PKIX
+sun.security.provider.certpath.PKIXCertPathValidator
+sun.security.provider.certpath.PKIXMasterCertPathValidator
+sun.security.provider.certpath.PolicyChecker
+sun.security.provider.certpath.PolicyNodeImpl
+sun.security.provider.certpath.RevocationChecker$1
+sun.security.provider.certpath.RevocationChecker$2
+sun.security.provider.certpath.RevocationChecker$Mode
+sun.security.provider.certpath.RevocationChecker$RevocationProperties
+sun.security.provider.certpath.RevocationChecker
+sun.security.util.AbstractAlgorithmConstraints$1
+sun.security.util.AbstractAlgorithmConstraints
+sun.security.util.AlgorithmDecomposer
+sun.security.util.BitArray
+sun.security.util.ByteArrayLexOrder
+sun.security.util.ByteArrayTagOrder
+sun.security.util.Cache$EqualByteArray
+sun.security.util.Cache
+sun.security.util.CertConstraintParameters
+sun.security.util.Debug
+sun.security.util.DerEncoder
+sun.security.util.DerIndefLenConverter
+sun.security.util.DerInputBuffer
+sun.security.util.DerInputStream
+sun.security.util.DerOutputStream
+sun.security.util.DerValue
+sun.security.util.DisabledAlgorithmConstraints$1
+sun.security.util.DisabledAlgorithmConstraints$Constraint$Operator
+sun.security.util.DisabledAlgorithmConstraints$Constraint
+sun.security.util.DisabledAlgorithmConstraints$Constraints
+sun.security.util.DisabledAlgorithmConstraints$KeySizeConstraint
+sun.security.util.DisabledAlgorithmConstraints
+sun.security.util.KeyUtil
+sun.security.util.Length
+sun.security.util.ManifestDigester$Entry
+sun.security.util.ManifestDigester$Position
+sun.security.util.ManifestDigester
+sun.security.util.ManifestEntryVerifier$SunProviderHolder
+sun.security.util.ManifestEntryVerifier
+sun.security.util.MemoryCache$CacheEntry
+sun.security.util.MemoryCache$SoftCacheEntry
+sun.security.util.MemoryCache
+sun.security.util.ObjectIdentifier
+sun.security.util.SecurityConstants
+sun.security.util.SignatureFileVerifier
+sun.security.x509.AVA
+sun.security.x509.AVAKeyword
+sun.security.x509.AccessDescription
+sun.security.x509.AlgorithmId
+sun.security.x509.AuthorityInfoAccessExtension
+sun.security.x509.AuthorityKeyIdentifierExtension
+sun.security.x509.BasicConstraintsExtension
+sun.security.x509.CRLDistributionPointsExtension
+sun.security.x509.CRLNumberExtension
+sun.security.x509.CRLReasonCodeExtension
+sun.security.x509.CertAttrSet
+sun.security.x509.CertificateAlgorithmId
+sun.security.x509.CertificateExtensions
+sun.security.x509.CertificateIssuerExtension
+sun.security.x509.CertificatePoliciesExtension
+sun.security.x509.CertificatePolicyId
+sun.security.x509.CertificateSerialNumber
+sun.security.x509.CertificateValidity
+sun.security.x509.CertificateVersion
+sun.security.x509.CertificateX509Key
+sun.security.x509.DNSName
+sun.security.x509.DeltaCRLIndicatorExtension
+sun.security.x509.DistributionPoint
+sun.security.x509.ExtendedKeyUsageExtension
+sun.security.x509.Extension
+sun.security.x509.FreshestCRLExtension
+sun.security.x509.GeneralName
+sun.security.x509.GeneralNameInterface
+sun.security.x509.GeneralNames
+sun.security.x509.InhibitAnyPolicyExtension
+sun.security.x509.IssuerAlternativeNameExtension
+sun.security.x509.IssuingDistributionPointExtension
+sun.security.x509.KeyIdentifier
+sun.security.x509.KeyUsageExtension
+sun.security.x509.NameConstraintsExtension
+sun.security.x509.NetscapeCertTypeExtension$MapEntry
+sun.security.x509.NetscapeCertTypeExtension
+sun.security.x509.OCSPNoCheckExtension
+sun.security.x509.OIDMap$OIDInfo
+sun.security.x509.OIDMap
+sun.security.x509.PKIXExtensions
+sun.security.x509.PolicyConstraintsExtension
+sun.security.x509.PolicyInformation
+sun.security.x509.PolicyMappingsExtension
+sun.security.x509.PrivateKeyUsageExtension
+sun.security.x509.RDN
+sun.security.x509.SerialNumber
+sun.security.x509.SubjectAlternativeNameExtension
+sun.security.x509.SubjectInfoAccessExtension
+sun.security.x509.SubjectKeyIdentifierExtension
+sun.security.x509.URIName
+sun.security.x509.X500Name$1
+sun.security.x509.X500Name
+sun.security.x509.X509AttributeName
+sun.security.x509.X509CertImpl
+sun.security.x509.X509CertInfo
+sun.security.x509.X509Key
+sun.util.calendar.AbstractCalendar
+sun.util.calendar.BaseCalendar$Date
+sun.util.calendar.BaseCalendar
+sun.util.calendar.CalendarDate
+sun.util.calendar.CalendarSystem
+sun.util.calendar.CalendarUtils
+sun.util.calendar.Era
+sun.util.calendar.Gregorian$Date
+sun.util.calendar.Gregorian
+sun.util.calendar.ImmutableGregorianDate
+sun.util.calendar.JulianCalendar
+sun.util.calendar.LocalGregorianCalendar
+sun.util.locale.BaseLocale$Cache
+sun.util.locale.BaseLocale$Key
+sun.util.locale.BaseLocale
+sun.util.locale.Extension
+sun.util.locale.InternalLocaleBuilder$CaseInsensitiveChar
+sun.util.locale.InternalLocaleBuilder
+sun.util.locale.LanguageTag
+sun.util.locale.LocaleExtensions
+sun.util.locale.LocaleMatcher
+sun.util.locale.LocaleObjectCache$CacheEntry
+sun.util.locale.LocaleObjectCache
+sun.util.locale.LocaleSyntaxException
+sun.util.locale.LocaleUtils
+sun.util.locale.ParseStatus
+sun.util.locale.StringTokenIterator
+sun.util.locale.UnicodeLocaleExtension
+sun.util.logging.LoggingProxy
+sun.util.logging.LoggingSupport$1
+sun.util.logging.LoggingSupport
+sun.util.logging.PlatformLogger$1
+sun.util.logging.PlatformLogger$JavaLoggerProxy
+sun.util.logging.PlatformLogger$Level
+sun.util.logging.PlatformLogger$LoggerProxy
+sun.util.logging.PlatformLogger
diff --git a/build/build-art-module.sh b/build/build-art-module.sh
new file mode 100755
index 0000000..bc6f266
--- /dev/null
+++ b/build/build-art-module.sh
@@ -0,0 +1,129 @@
+#!/bin/bash -e
+
+# This script builds the APEX modules, SDKs and module exports that the ART
+# Module provides.
+
+if [ ! -e build/make/core/Makefile ]; then
+  echo "$0 must be run from the top of the tree"
+  exit 1
+fi
+
+skip_apex=
+skip_module_sdk=
+build_args=()
+for arg; do
+  case "$arg" in
+    --skip-apex) skip_apex=true ;;
+    --skip-module-sdk) skip_module_sdk=true ;;
+    *) build_args+=("$arg") ;;
+  esac
+  shift
+done
+
+MAINLINE_MODULES=()
+if [ -z "$skip_apex" ]; then
+  # Take the list of modules from MAINLINE_MODULES.
+  if [ -n "${MAINLINE_MODULES}" ]; then
+    read -r -a MAINLINE_MODULES <<< "${MAINLINE_MODULES}"
+  else
+    MAINLINE_MODULES=(
+      com.android.art
+      com.android.art.debug
+    )
+  fi
+fi
+
+# Take the list of products to build the modules for from
+# MAINLINE_MODULE_PRODUCTS.
+if [ -n "${MAINLINE_MODULE_PRODUCTS}" ]; then
+  read -r -a MAINLINE_MODULE_PRODUCTS <<< "${MAINLINE_MODULE_PRODUCTS}"
+else
+  # The default products are the same as in
+  # build/soong/scripts/build-mainline-modules.sh.
+  MAINLINE_MODULE_PRODUCTS=(
+    art_module_arm
+    art_module_arm64
+    art_module_x86
+    art_module_x86_64
+  )
+fi
+
+MODULE_SDKS_AND_EXPORTS=()
+if [ -z "$skip_module_sdk" ]; then
+  MODULE_SDKS_AND_EXPORTS=(
+    art-module-sdk
+    art-module-host-exports
+    art-module-test-exports
+  )
+fi
+
+echo_and_run() {
+  echo "$*"
+  "$@"
+}
+
+export OUT_DIR=${OUT_DIR:-out}
+export DIST_DIR=${DIST_DIR:-${OUT_DIR}/dist}
+
+# Use same build settings as build_unbundled_mainline_module.sh, for build
+# consistency.
+# TODO(mast): Call out to a common script for building APEXes.
+export UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true
+export TARGET_BUILD_VARIANT=${TARGET_BUILD_VARIANT:-"user"}
+export TARGET_BUILD_DENSITY=alldpi
+export TARGET_BUILD_TYPE=release
+
+if [ ! -d frameworks/base ]; then
+  # Configure the build system for the reduced manifest branch.
+  export SOONG_ALLOW_MISSING_DEPENDENCIES=true
+fi
+
+if [ ${#MAINLINE_MODULES[*]} -gt 0 ]; then
+  (
+    export TARGET_BUILD_APPS="${MAINLINE_MODULES[*]}"
+
+    # We require .apex files here, so ensure we get them regardless of product
+    # settings.
+    export OVERRIDE_TARGET_FLATTEN_APEX=false
+
+    for product in ${MAINLINE_MODULE_PRODUCTS[*]}; do
+      echo_and_run build/soong/soong_ui.bash --make-mode \
+        TARGET_PRODUCT=${product} "${build_args[@]}" ${MAINLINE_MODULES[*]}
+
+      vars="$(TARGET_PRODUCT=${product} build/soong/soong_ui.bash \
+              --dumpvars-mode --vars="PRODUCT_OUT TARGET_ARCH")"
+      # Assign to a variable and eval that, since bash ignores any error status
+      # from the command substitution if it's directly on the eval line.
+      eval $vars
+
+      mkdir -p ${DIST_DIR}/${TARGET_ARCH}
+      for module in ${MAINLINE_MODULES[*]}; do
+        echo_and_run cp ${PRODUCT_OUT}/system/apex/${module}.apex \
+          ${DIST_DIR}/${TARGET_ARCH}/
+      done
+    done
+  )
+fi
+
+if [ ${#MODULE_SDKS_AND_EXPORTS[*]} -gt 0 ]; then
+  # Create multi-arch SDKs in a different out directory. The multi-arch script
+  # uses Soong in --skip-make mode which cannot use the same directory as normal
+  # mode with make.
+  export OUT_DIR=${OUT_DIR}/aml
+
+  # Put the build system in apps building mode so we don't trip on platform
+  # dependencies, but there are no actual apps to build here.
+  export TARGET_BUILD_APPS=none
+
+  # We use force building LLVM components flag (even though we actually don't
+  # compile them) because we don't have bionic host prebuilts
+  # for them.
+  export FORCE_BUILD_LLVM_COMPONENTS=true
+
+  echo_and_run build/soong/scripts/build-aml-prebuilts.sh \
+    TARGET_PRODUCT=mainline_sdk "${build_args[@]}" ${MODULE_SDKS_AND_EXPORTS[*]}
+
+  rm -rf ${DIST_DIR}/mainline-sdks
+  mkdir -p ${DIST_DIR}
+  echo_and_run cp -r ${OUT_DIR}/soong/mainline-sdks ${DIST_DIR}/
+fi
diff --git a/build/codegen.go b/build/codegen.go
index bc7dc42..96dd223 100644
--- a/build/codegen.go
+++ b/build/codegen.go
@@ -102,6 +102,13 @@
 			}
 		}
 
+		type libraryProps struct {
+			Target struct {
+				Android *CodegenLibraryArchProperties
+				Host    *CodegenLibraryArchProperties
+			}
+		}
+
 		type sharedLibraryProps struct {
 			Target struct {
 				Android *CodegenLibraryArchSharedProperties
@@ -119,20 +126,24 @@
 		arch := getCodegenArchProperties(archName)
 
 		cp := &commonProps{}
+		lp := &libraryProps{}
 		sharedLP := &sharedLibraryProps{}
 		staticLP := &staticLibraryProps{}
 		if host {
 			cp.Target.Host = &arch.CodegenCommonArchProperties
+			lp.Target.Host = &arch.CodegenLibraryArchProperties
 			sharedLP.Target.Host = &arch.CodegenLibraryArchSharedProperties
 			staticLP.Target.Host = &arch.CodegenLibraryArchStaticProperties
 		} else {
 			cp.Target.Android = &arch.CodegenCommonArchProperties
+			lp.Target.Android = &arch.CodegenLibraryArchProperties
 			sharedLP.Target.Android = &arch.CodegenLibraryArchSharedProperties
 			staticLP.Target.Android = &arch.CodegenLibraryArchStaticProperties
 		}
 
 		ctx.AppendProperties(cp)
 		if t.library {
+			ctx.AppendProperties(lp)
 			if t.static {
 				ctx.AppendProperties(staticLP)
 			}
@@ -167,6 +178,11 @@
 	Cppflags []string
 }
 
+type CodegenLibraryArchProperties struct {
+	Static_libs               []string
+	Export_static_lib_headers []string
+}
+
 type CodegenLibraryArchStaticProperties struct {
 	Static struct {
 		Whole_static_libs []string
@@ -182,6 +198,7 @@
 type codegenArchProperties struct {
 	CodegenSourceArchProperties
 	CodegenCommonArchProperties
+	CodegenLibraryArchProperties
 	CodegenLibraryArchStaticProperties
 	CodegenLibraryArchSharedProperties
 }
diff --git a/build/makevars.go b/build/makevars.go
index 1faa0f6..1965b5d 100644
--- a/build/makevars.go
+++ b/build/makevars.go
@@ -15,18 +15,32 @@
 package art
 
 import (
+	"path/filepath"
 	"sort"
 	"strings"
 
 	"android/soong/android"
+	"android/soong/cc/config"
 )
 
 var (
 	pctx = android.NewPackageContext("android/soong/art")
+
+	// Copy the following prebuilts to the testcases directory.
+	// The original prebuilts directory is not accessible when running tests remotely.
+	prebuiltToolsForTests = []string{
+		"bin/clang",
+		"bin/clang.real",
+		"bin/llvm-addr2line",
+		"bin/llvm-dwarfdump",
+		"bin/llvm-objdump",
+		"lib64/libc++.so.1",
+	}
 )
 
 func init() {
 	android.RegisterMakeVarsProvider(pctx, makeVarsProvider)
+	pctx.Import("android/soong/cc/config")
 }
 
 func makeVarsProvider(ctx android.MakeVarsContext) {
@@ -44,4 +58,21 @@
 	for _, name := range testNames {
 		ctx.Strict("ART_TEST_LIST_"+name, strings.Join(testMap[name], " "))
 	}
+
+	// Create list of copy commands to install the content of the testcases directory.
+	testcasesContent := testcasesContent(ctx.Config())
+	copy_cmds := []string{}
+	for _, key := range android.SortedStringKeys(testcasesContent) {
+		copy_cmds = append(copy_cmds, testcasesContent[key]+":"+key)
+	}
+	ctx.Strict("ART_TESTCASES_CONTENT", strings.Join(copy_cmds, " "))
+
+	// Add prebuilt tools.
+	clang_path := filepath.Join(config.ClangDefaultBase, ctx.Config().PrebuiltOS(), config.ClangDefaultVersion)
+	copy_cmds = []string{}
+	for _, tool := range prebuiltToolsForTests {
+		src := filepath.Join(clang_path, "/", tool)
+		copy_cmds = append(copy_cmds, src+":"+src)
+	}
+	ctx.Strict("ART_TESTCASES_PREBUILT_CONTENT", strings.Join(copy_cmds, " "))
 }
diff --git a/build/sdk/Android.bp b/build/sdk/Android.bp
index ed9a4fe..33a98ff 100644
--- a/build/sdk/Android.bp
+++ b/build/sdk/Android.bp
@@ -12,42 +12,257 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+soong_config_module_type_import {
+    from: "art/build/SoongConfig.bp",
+    module_types: [
+        "art_module_sdk",
+        "art_module_exports",
+    ],
+}
+
+// Additional visibility to add to the prebuilt modules that are part of
+// the snapshots of the ART sdk/module_exports to ensure that they are
+// visible to each other.
+prebuilt_visibility = [
+    // TODO(b/155921753): Restrict this when prebuilts are in their proper
+    // locations.
+    "//prebuilts:__subpackages__",
+]
+
 // The SDK for the art module apex.
-sdk {
+art_module_sdk {
     name: "art-module-sdk",
-    java_system_modules: [
-        "art-module-public-api-stubs-system-modules",
-        "art-module-intra-core-api-stubs-system-modules",
-        "art-module-platform-api-stubs-system-modules",
-    ],
-    native_static_libs: [
-        "libartimagevalues",
-    ],
+    host_supported: true,
+
+    // Enable if SOONG_CONFIG_art_module_source_build is true.
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+
+    prebuilt_visibility: prebuilt_visibility,
+
+    target: {
+        // Both android and host linux but not windows or darwin.
+        linux: {
+            native_header_libs: [
+                "jni_headers",
+                "libartpalette-headers",
+                "libnativehelper_header_only",
+                "libopenjdkjvmti_headers",
+            ],
+
+            native_shared_libs: [
+                "libandroidio",
+                "libdexfile",
+                "libnativebridge",
+                "libnativehelper",
+                "libnativeloader",
+                "libsigchain",
+            ],
+
+            native_static_libs: [
+                "libdexfile_support",
+                "libdexfile_static",
+                "libnativehelper_lazy",
+            ],
+        },
+
+        android: {
+            bootclasspath_fragments: [
+                // Adds the fragment and its contents to the sdk.
+                "art-bootclasspath-fragment",
+            ],
+
+            compat_configs: [
+                "libcore-platform-compat-config",
+            ],
+
+            java_header_libs: [
+                // Needed by any module that builds against any non-numeric
+                // sdk_version other than "none".
+                //
+                // This is actually only used for compiling Java 8 and kotlin.
+                // Java 9 uses system modules which encapsulates this
+                // internally.
+                "core-lambda-stubs",
+
+                // Needed by any module that builds against any non-numeric
+                // sdk_version other than "none" or "core_platform".
+                //
+                // This is actually only used for compiling Java 8 and kotlin.
+                // Java 9 uses system modules which encapsulates this
+                // internally.
+                "core.current.stubs",
+
+                // Needed by any module that builds against an sdk_version of
+                // "core_platform".
+                //
+                // This is actually only used for compiling Java 8 and kotlin.
+                // Java 9 uses system modules which encapsulates this
+                // internally.
+                "legacy.core.platform.api.stubs",
+                "stable.core.platform.api.stubs",
+            ],
+
+            java_sdk_libs: [
+                "art.module.public.api",
+            ],
+
+            java_system_modules: [
+                "art-module-public-api-stubs-system-modules",
+                "art-module-lib-api-stubs-system-modules",
+                "art-module-intra-core-api-stubs-system-modules",
+                "core-current-stubs-system-modules",
+                "core-module-lib-stubs-system-modules",
+                "legacy-core-platform-api-stubs-system-modules",
+                "stable-core-platform-api-stubs-system-modules",
+            ],
+            native_header_libs: [
+                "libnativeloader-headers",
+            ],
+            native_shared_libs: [
+                "libnativebridge_lazy",
+                "libnativehelper_compat_libc++",
+                "libnativeloader_lazy",
+            ],
+        },
+
+        linux_bionic: {
+            enabled: false,
+        },
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 // Exported host tools and libraries.
-module_exports {
+art_module_exports {
     name: "art-module-host-exports",
     host_supported: true,
-    device_supported: false,
-    java_libs: [
-        "timezone-host",
-    ],
+
+    // Enable if SOONG_CONFIG_art_module_source_build is true.
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+
+    prebuilt_visibility: prebuilt_visibility,
+
+    target: {
+        host: {
+            // Set in target.host because the top level compile_multilib
+            // property is fixed to "both" in the sdk/module_exports
+            // implementation and cannot be overridden any other way.
+            compile_multilib: "64",
+
+            java_libs: [
+                "art.module.api.annotations",
+
+                // Needed for grpc-grpc-java
+                "okhttp-norepackage",
+            ],
+            native_binaries: [
+                "dex2oat",
+                "dex2oatd",
+                "dexdump",
+                "hiddenapi",
+                "oatdump",
+                "profman",
+                "veridex",
+            ],
+            native_libs: [
+                "libartpalette", // libdexfile dependency
+                "libartbase", // libdexfile dependency
+            ],
+        },
+
+        linux_bionic: {
+            enabled: false,
+        },
+        darwin: {
+            enabled: false,
+        },
+        windows: {
+            enabled: false,
+        },
+    },
 }
 
 // Exported tests and supporting libraries
-module_exports {
+art_module_exports {
     name: "art-module-test-exports",
+
+    // Enable if SOONG_CONFIG_art_module_source_build is true.
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+
+    prebuilt_visibility: prebuilt_visibility,
+
     java_libs: [
         "core-compat-test-rules",
         "core-test-rules",
         "core-tests-support",
         "okhttp-tests-nojarjar",
+
+        // Needed for CtsJvmtiDeviceRunTestAppBase.
+        "art_cts_jvmti_test_library",
+        "expected_cts_outputs",
+
+        // Needed for robolectric.
+        "core-libart-for-host",
+        "okhttp-for-host",
+
+        // Needed for CtsLibcore...TestCases
+        "libcore-expectations-knownfailures-jar",
+        "libcore-expectations-virtualdeviceknownfailures-jar",
+
+        // Needed for CtsLibcoreOkHttpTestCases
+        "okhttp-nojarjar",
     ],
+
     java_tests: [
+        // Needed for CtsJdwpTestCases.
+        "apache-harmony-jdwp-tests",
+
         "libcore-crypto-tests",
+
+        // Needed for CtsLibcoreOjTestCases
+        "core-ojtests-public",
+
+        // Needed for CtsLibcoreJsr166TestCases
+        "jsr166-tests",
+
+        // Needed for CtsLibcoreTestCases
+        "apache-harmony-tests",
+        "core-tests",
     ],
+
     native_shared_libs: [
         "libjavacoretests",
     ],
+    native_static_libs: [
+        // TODO(b/187288515): Providing this as a prebuilt introduces an issue
+        // with sdk_version propagation. Temporarily use the source library
+        // instead.
+        //"libctstiagent",
+    ],
 }
diff --git a/cmdline/Android.bp b/cmdline/Android.bp
index 3eac0ed..fdc762c 100644
--- a/cmdline/Android.bp
+++ b/cmdline/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // TODO: this header library depends on libart. Find a way to express that.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_library_headers {
     name: "art_cmdlineparser_headers",
     host_supported: true,
@@ -22,14 +31,31 @@
 
     apex_available: [
         "com.android.art.debug",
-        "com.android.art.release",
+        "com.android.art",
     ],
+    min_sdk_version: "S",
 }
 
+art_cc_defaults {
+    name: "art_cmdline_tests_defaults",
+    srcs: ["cmdline_parser_test.cc"],
+}
+
+// Version of ART gtest `art_cmdline_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
 art_cc_test {
     name: "art_cmdline_tests",
     defaults: [
         "art_gtest_defaults",
+        "art_cmdline_tests_defaults",
     ],
-    srcs: ["cmdline_parser_test.cc"],
+}
+
+// Standalone version of ART gtest `art_cmdline_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_cmdline_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_cmdline_tests_defaults",
+    ],
 }
diff --git a/cmdline/cmdline_parser.h b/cmdline/cmdline_parser.h
index 952be44..7e343f8 100644
--- a/cmdline/cmdline_parser.h
+++ b/cmdline/cmdline_parser.h
@@ -19,21 +19,26 @@
 
 #define CMDLINE_NDEBUG 1  // Do not output any debugging information for parsing.
 
-#include "detail/cmdline_debug_detail.h"
-#include "detail/cmdline_parse_argument_detail.h"
-#include "detail/cmdline_parser_detail.h"
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <tuple>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
 
+#include "base/indenter.h"
+#include "base/variant_map.h"
 #include "cmdline_parse_result.h"
 #include "cmdline_result.h"
 #include "cmdline_type_parser.h"
 #include "cmdline_types.h"
+#include "detail/cmdline_debug_detail.h"
+#include "detail/cmdline_parse_argument_detail.h"
+#include "detail/cmdline_parser_detail.h"
 #include "token_range.h"
 
-#include "base/variant_map.h"
-
-#include <memory>
-#include <vector>
-
 namespace art {
 // Build a parser for command line arguments with a small domain specific language.
 // Each parsed type must have a specialized CmdlineType<T> in order to do the string->T parsing.
@@ -165,6 +170,16 @@
       return *this;
     }
 
+    ArgumentBuilder<TArg>& WithMetavar(const char* sv) {
+      argument_info_.metavar_ = sv;
+      return *this;
+    }
+
+    ArgumentBuilder<TArg>& WithHelp(const char* sv) {
+      argument_info_.help_ = sv;
+      return *this;
+    }
+
     // Convenience type alias for the variant map key type definition.
     using MapKey = TVariantMapKey<TArg>;
 
@@ -195,6 +210,24 @@
       return parent_;
     }
 
+    // Write the results of this argument into a variable pointed to by destination.
+    // An optional is used to tell whether the command line argument was present.
+    CmdlineParser::Builder& IntoLocation(std::optional<TArg>* destination) {
+      save_value_ = [destination](TArg& value) {
+        *destination = value;
+      };
+
+      load_value_ = [destination]() -> TArg& {
+        return destination->value();
+      };
+
+      save_value_specified_ = true;
+      load_value_specified_ = true;
+
+      CompleteArgument();
+      return parent_;
+    }
+
     // Ensure we always move this when returning a new builder.
     ArgumentBuilder(ArgumentBuilder&&) = default;
 
@@ -231,6 +264,17 @@
       argument_info_.names_ = names;
     }
 
+    void SetHelp(std::optional<const char*>&& val) {
+      argument_info_.help_ = val;
+    }
+
+    void SetCategory(std::optional<const char*>&& val) {
+      argument_info_.category_ = val;
+    }
+    void SetMetavar(std::optional<const char*>&& val) {
+      argument_info_.metavar_ = val;
+    }
+
    private:
     // Copying is bad. Move only.
     ArgumentBuilder(const ArgumentBuilder&) = delete;
@@ -291,6 +335,21 @@
       return CreateTypedBuilder<TArg>();
     }
 
+    UntypedArgumentBuilder& WithHelp(const char* sv) {
+      SetHelp(sv);
+      return *this;
+    }
+
+    UntypedArgumentBuilder& WithCategory(const char* sv) {
+      SetCategory(sv);
+      return *this;
+    }
+
+    UntypedArgumentBuilder& WithMetavar(const char* sv) {
+      SetMetavar(sv);
+      return *this;
+    }
+
     // When used with multiple aliases, map the position of the alias to the value position.
     template <typename TArg>
     ArgumentBuilder<TArg> WithValues(std::initializer_list<TArg> values) {
@@ -324,6 +383,18 @@
       names_ = names;
     }
 
+    void SetHelp(std::optional<const char*> sv) {
+      help_.swap(sv);
+    }
+
+    void SetMetavar(std::optional<const char*> sv) {
+      metavar_.swap(sv);
+    }
+
+    void SetCategory(std::optional<const char*> sv) {
+      category_.swap(sv);
+    }
+
    private:
     // No copying. Move instead.
     UntypedArgumentBuilder(const UntypedArgumentBuilder&) = delete;
@@ -333,6 +404,9 @@
       auto&& b = CreateArgumentBuilder<TArg>(parent_);
       InitializeTypedBuilder(&b);  // Type-specific initialization
       b.SetNames(std::move(names_));
+      b.SetHelp(std::move(help_));
+      b.SetCategory(std::move(category_));
+      b.SetMetavar(std::move(metavar_));
       return std::move(b);
     }
 
@@ -356,6 +430,9 @@
 
     CmdlineParser::Builder& parent_;
     std::vector<const char*> names_;
+    std::optional<const char*> category_;
+    std::optional<const char*> help_;
+    std::optional<const char*> metavar_;
   };
 
   // Build a new parser given a chain of calls to define arguments.
@@ -367,10 +444,26 @@
       return Define({name});
     }
 
+    Builder& ClearCategory() {
+      default_category_.reset();
+      return *this;
+    }
+
+    Builder& SetCategory(const char* sv) {
+      default_category_ = sv;
+      return *this;
+    }
+
+    Builder& OrderCategories(std::vector<const char*> categories) {
+      category_order_.swap(categories);
+      return *this;
+    }
+
     // Define a single argument with multiple aliases.
     UntypedArgumentBuilder Define(std::initializer_list<const char*> names) {
       auto&& b = UntypedArgumentBuilder(*this);
       b.SetNames(names);
+      b.SetCategory(default_category_);
       return std::move(b);
     }
 
@@ -382,6 +475,8 @@
 
     // Provide a list of arguments to ignore for backwards compatibility.
     Builder& Ignore(std::initializer_list<const char*> ignore_list) {
+      auto current_cat = default_category_;
+      default_category_ = "Ignored";
       for (auto&& ignore_name : ignore_list) {
         std::string ign = ignore_name;
 
@@ -403,11 +498,12 @@
         }
       }
       ignore_list_ = ignore_list;
+      default_category_ = current_cat;
       return *this;
     }
 
-    // Finish building the parser; performs sanity checks. Return value is moved, not copied.
-    // Do not call this more than once.
+    // Finish building the parser; performs a check of the validity. Return value is moved, not
+    // copied. Do not call this more than once.
     CmdlineParser Build() {
       assert(!built_);
       built_ = true;
@@ -415,7 +511,8 @@
       auto&& p = CmdlineParser(ignore_unrecognized_,
                                std::move(ignore_list_),
                                save_destination_,
-                               std::move(completed_arguments_));
+                               std::move(completed_arguments_),
+                               std::move(category_order_));
 
       return std::move(p);
     }
@@ -439,10 +536,14 @@
     bool ignore_unrecognized_ = false;
     std::vector<const char*> ignore_list_;
     std::shared_ptr<SaveDestination> save_destination_;
+    std::optional<const char*> default_category_;
+    std::vector<const char*> category_order_;
 
     std::vector<std::unique_ptr<detail::CmdlineParseArgumentAny>> completed_arguments_;
   };
 
+  void DumpHelp(VariableIndentationOutputStream& vios);
+
   CmdlineResult Parse(const std::string& argv) {
     std::vector<std::string> tokenized;
     Split(argv, ' ', &tokenized);
@@ -500,11 +601,13 @@
   CmdlineParser(bool ignore_unrecognized,
                 std::vector<const char*>&& ignore_list,
                 std::shared_ptr<SaveDestination> save_destination,
-                std::vector<std::unique_ptr<detail::CmdlineParseArgumentAny>>&& completed_arguments)
+                std::vector<std::unique_ptr<detail::CmdlineParseArgumentAny>>&& completed_arguments,
+                std::vector<const char*>&& category_order)
     : ignore_unrecognized_(ignore_unrecognized),
       ignore_list_(std::move(ignore_list)),
       save_destination_(save_destination),
-      completed_arguments_(std::move(completed_arguments)) {
+      completed_arguments_(std::move(completed_arguments)),
+      category_order_(category_order) {
     assert(save_destination != nullptr);
   }
 
@@ -606,6 +709,7 @@
   std::vector<const char*> ignore_list_;
   std::shared_ptr<SaveDestination> save_destination_;
   std::vector<std::unique_ptr<detail::CmdlineParseArgumentAny>> completed_arguments_;
+  std::vector<const char*> category_order_;
 };
 
 // This has to be defined after everything else, since we want the builders to call this.
@@ -628,6 +732,56 @@
   builder.AppendCompletedArgument(arg);
 }
 
+template <typename TVariantMap,
+          template <typename TKeyValue> class TVariantMapKey>
+void CmdlineParser<TVariantMap, TVariantMapKey>::DumpHelp(VariableIndentationOutputStream& vios) {
+  std::vector<detail::CmdlineParseArgumentAny*> uncat;
+  std::unordered_map<std::string, std::vector<detail::CmdlineParseArgumentAny*>> args;
+  for (const std::unique_ptr<detail::CmdlineParseArgumentAny>& it : completed_arguments_) {
+    auto cat = it->GetCategory();
+    if (cat) {
+      if (args.find(cat.value()) == args.end()) {
+        args[cat.value()] = {};
+      }
+      args.at(cat.value()).push_back(it.get());
+    } else {
+      uncat.push_back(it.get());
+    }
+  }
+  args.erase("Ignored");
+  for (auto arg : uncat) {
+    arg->DumpHelp(vios);
+    vios.Stream();
+  }
+  for (auto it : category_order_) {
+    auto cur = args.find(it);
+    if (cur != args.end() && !cur->second.empty()) {
+      vios.Stream() << "The following " << it << " arguments are supported:" << std::endl;
+      ScopedIndentation si(&vios);
+      for (detail::CmdlineParseArgumentAny* arg : cur->second) {
+        arg->DumpHelp(vios);
+        vios.Stream();
+      }
+      args.erase(cur->first);
+    }
+  }
+  for (auto [cat, lst] : args) {
+    vios.Stream() << "The following " << cat << " arguments are supported:" << std::endl;
+    ScopedIndentation si(&vios);
+    for (auto& arg : completed_arguments_) {
+      arg->DumpHelp(vios);
+      vios.Stream();
+    }
+  }
+  if (!ignore_list_.empty()) {
+    vios.Stream() << "The following arguments are ignored for compatibility:" << std::endl;
+    ScopedIndentation si(&vios);
+    for (auto ign : ignore_list_) {
+      vios.Stream() << ign << std::endl;
+    }
+  }
+}
+
 }  // namespace art
 
 #endif  // ART_CMDLINE_CMDLINE_PARSER_H_
diff --git a/cmdline/cmdline_parser_test.cc b/cmdline/cmdline_parser_test.cc
index 37dcd16..c5a2008 100644
--- a/cmdline/cmdline_parser_test.cc
+++ b/cmdline/cmdline_parser_test.cc
@@ -236,7 +236,6 @@
   EXPECT_SINGLE_PARSE_VALUE(false, "-XX:DisableHSpaceCompactForOOM", M::EnableHSpaceCompactForOOM);
   EXPECT_SINGLE_PARSE_VALUE(0.5, "-XX:HeapTargetUtilization=0.5", M::HeapTargetUtilization);
   EXPECT_SINGLE_PARSE_VALUE(5u, "-XX:ParallelGCThreads=5", M::ParallelGCThreads);
-  EXPECT_SINGLE_PARSE_EXISTS("-Xno-dex-file-fallback", M::NoDexFileFallback);
 }  // TEST_F
 
 TEST_F(CmdlineParserTest, TestSimpleFailures) {
@@ -488,17 +487,18 @@
 * -Xps-*
 */
 TEST_F(CmdlineParserTest, ProfileSaverOptions) {
-  ProfileSaverOptions opt = ProfileSaverOptions(true, 1, 2, 3, 4, 5, 6, 7, "abc", true);
+  ProfileSaverOptions opt = ProfileSaverOptions(true, 1, 2, 3, 4, 5, 6, 7, 8, "abc", true);
 
   EXPECT_SINGLE_PARSE_VALUE(opt,
                             "-Xjitsaveprofilinginfo "
                             "-Xps-min-save-period-ms:1 "
-                            "-Xps-save-resolved-classes-delay-ms:2 "
-                            "-Xps-hot-startup-method-samples:3 "
-                            "-Xps-min-methods-to-save:4 "
-                            "-Xps-min-classes-to-save:5 "
-                            "-Xps-min-notification-before-wake:6 "
-                            "-Xps-max-notification-before-wake:7 "
+                            "-Xps-min-first-save-ms:2 "
+                            "-Xps-save-resolved-classes-delay-ms:3 "
+                            "-Xps-hot-startup-method-samples:4 "
+                            "-Xps-min-methods-to-save:5 "
+                            "-Xps-min-classes-to-save:6 "
+                            "-Xps-min-notification-before-wake:7 "
+                            "-Xps-max-notification-before-wake:8 "
                             "-Xps-profile-path:abc "
                             "-Xps-profile-boot-class-path",
                             M::ProfileSaverOpts);
diff --git a/cmdline/cmdline_type_parser.h b/cmdline/cmdline_type_parser.h
index fa5cdaf..82a76f4 100644
--- a/cmdline/cmdline_type_parser.h
+++ b/cmdline/cmdline_type_parser.h
@@ -54,6 +54,7 @@
 
   // Runtime type name of T, so that we can print more useful error messages.
   static const char* Name() { assert(false); return "UnspecializedType"; }
+  static const char* DescribeType() { assert(false); return "UnspecializedType"; }
 
   // Whether or not your type can parse argument definitions defined without a "_"
   // e.g. -Xenable-profiler just mutates the existing profiler struct in-place
diff --git a/cmdline/cmdline_types.h b/cmdline/cmdline_types.h
index 25902f1..78cdcad 100644
--- a/cmdline/cmdline_types.h
+++ b/cmdline/cmdline_types.h
@@ -19,7 +19,10 @@
 #define CMDLINE_NDEBUG 1  // Do not output any debugging information for parsing.
 
 #include <list>
+#include <ostream>
 
+#include "android-base/parsebool.h"
+#include "android-base/stringprintf.h"
 #include "cmdline_type_parser.h"
 #include "detail/cmdline_debug_detail.h"
 #include "memory_representation.h"
@@ -65,6 +68,22 @@
 };
 
 template <>
+struct CmdlineType<bool> : CmdlineTypeParser<bool> {
+  Result Parse(const std::string& args) {
+    switch (::android::base::ParseBool(args)) {
+      case ::android::base::ParseBoolResult::kError:
+        return Result::Failure("Could not parse '" + args + "' as boolean");
+      case ::android::base::ParseBoolResult::kTrue:
+        return Result::Success(true);
+      case ::android::base::ParseBoolResult::kFalse:
+        return Result::Success(false);
+    }
+  }
+
+  static const char* DescribeType() { return "true|false|1|0|y|n|yes|no|on|off"; }
+};
+
+template <>
 struct CmdlineType<JdwpProvider> : CmdlineTypeParser<JdwpProvider> {
   /*
    * Handle a single JDWP provider name. Must be either 'internal', 'default', or the file name of
@@ -87,6 +106,7 @@
     }
   }
   static const char* Name() { return "JdwpProvider"; }
+  static const char* DescribeType() { return "none|adbconnection|default"; }
 };
 
 template <size_t Divisor>
@@ -173,6 +193,13 @@
   }
 
   static const char* Name() { return Memory<Divisor>::Name(); }
+  static const char* DescribeType() {
+    static std::string str;
+    if (str.empty()) {
+      str = "Memory with granularity of " + std::to_string(Divisor) + " bytes";
+    }
+    return str.c_str();
+  }
 };
 
 template <>
@@ -194,6 +221,7 @@
   }
 
   static const char* Name() { return "double"; }
+  static const char* DescribeType() { return "double value"; }
 };
 
 template <typename T>
@@ -226,6 +254,7 @@
   }
 
   static const char* Name() { return "unsigned integer"; }
+  static const char* DescribeType() { return "unsigned integer value"; }
 };
 
 template <>
@@ -235,6 +264,7 @@
   }
 
   static const char* Name() { return "integer"; }
+  static const char* DescribeType() { return "integer value"; }
 };
 
 // Lightweight nanosecond value type. Allows parser to convert user-input from milliseconds
@@ -289,6 +319,7 @@
   }
 
   static const char* Name() { return "MillisecondsToNanoseconds"; }
+  static const char* DescribeType() { return "millisecond value"; }
 };
 
 template <>
@@ -307,6 +338,7 @@
     }
     return Result::SuccessNoValue();
   }
+  static const char* DescribeType() { return "string value"; }
 };
 
 template <>
@@ -323,6 +355,7 @@
   }
 
   static const char* Name() { return "std::vector<Plugin>"; }
+  static const char* DescribeType() { return "/path/to/libplugin.so"; }
 };
 
 template <>
@@ -339,6 +372,7 @@
   }
 
   static const char* Name() { return "std::list<ti::AgentSpec>"; }
+  static const char* DescribeType() { return "/path/to/libagent.so=options"; }
 };
 
 template <>
@@ -355,6 +389,7 @@
   }
 
   static const char* Name() { return "std::vector<std::string>"; }
+  static const char* DescribeType() { return "string value"; }
 };
 
 template <char Separator>
@@ -400,6 +435,13 @@
   }
 
   static const char* Name() { return "ParseStringList<Separator>"; }
+  static const char* DescribeType() {
+    static std::string str;
+    if (str.empty()) {
+      str = android::base::StringPrintf("list separated by '%c'", Separator);
+    }
+    return str.c_str();
+  }
 };
 
 template <>
@@ -433,6 +475,7 @@
   }
 
   static const char* Name() { return "std::vector<int32_t>"; }
+  static const char* DescribeType() { return "unsigned integer value"; }
 };
 
 static gc::CollectorType ParseCollectorType(const std::string& option) {
@@ -534,6 +577,11 @@
   }
 
   static const char* Name() { return "XgcOption"; }
+  static const char* DescribeType() {
+    return "MS|nonconccurent|concurrent|CMS|SS|CC|[no]preverify[_rosalloc]|"
+           "[no]presweepingverify[_rosalloc]|[no]generation_cc|[no]postverify[_rosalloc]|"
+           "[no]gcstress|measure|[no]precisce|[no]verifycardtable";
+  }
 };
 
 struct BackgroundGcOption {
@@ -573,6 +621,9 @@
   }
 
   static const char* Name() { return "BackgroundGcOption"; }
+  static const char* DescribeType() {
+    return "HSpaceCompact|MS|nonconccurent|CMS|concurrent|SS|CC";
+  }
 };
 
 template <>
@@ -642,6 +693,11 @@
   }
 
   static const char* Name() { return "LogVerbosity"; }
+  static const char* DescribeType() {
+    return "class|collector|compiler|deopt|gc|heap|interpreter|jdwp|jit|jni|monitor|oat|profiler|"
+           "signals|simulator|startup|third-party-jni|threads|verifier|verifier-debug|image|"
+           "systrace-locks|plugin|agents|dex";
+  }
 };
 
 template <>
@@ -709,6 +765,12 @@
              &ProfileSaverOptions::min_save_period_ms_,
              type_parser.Parse(suffix));
     }
+    if (android::base::StartsWith(option, "min-first-save-ms:")) {
+      CmdlineType<unsigned int> type_parser;
+      return ParseInto(existing,
+             &ProfileSaverOptions::min_first_save_ms_,
+             type_parser.Parse(suffix));
+    }
     if (android::base::StartsWith(option, "save-resolved-classes-delay-ms:")) {
       CmdlineType<unsigned int> type_parser;
       return ParseInto(existing,
@@ -754,6 +816,7 @@
   }
 
   static const char* Name() { return "ProfileSaverOptions"; }
+  static const char* DescribeType() { return "string|unsigned integer"; }
   static constexpr bool kCanParseBlankless = true;
 };
 
@@ -769,6 +832,7 @@
   }
 
   static const char* Name() { return "ExperimentalFlags"; }
+  static const char* DescribeType() { return "none"; }
 };
 }  // namespace art
 #endif  // ART_CMDLINE_CMDLINE_TYPES_H_
diff --git a/cmdline/detail/cmdline_parse_argument_detail.h b/cmdline/detail/cmdline_parse_argument_detail.h
index 2155435..0f73a76 100644
--- a/cmdline/detail/cmdline_parse_argument_detail.h
+++ b/cmdline/detail/cmdline_parse_argument_detail.h
@@ -22,11 +22,13 @@
 #include <functional>
 #include <memory>
 #include <numeric>
+#include <string_view>
 #include <type_traits>
 #include <vector>
 
 #include "android-base/strings.h"
 
+#include "base/indenter.h"
 #include "cmdline_parse_result.h"
 #include "cmdline_types.h"
 #include "token_range.h"
@@ -35,6 +37,7 @@
 namespace art {
 // Implementation details for the parser. Do not look inside if you hate templates.
 namespace detail {
+
 // A non-templated base class for argument parsers. Used by the general parser
 // to parse arguments, without needing to know the argument type at compile time.
 //
@@ -77,6 +80,10 @@
   // Returns how many tokens were either matched (or ignored because there was a
   // wildcard present). 0 means no match. If the Size() tokens are returned.
   virtual size_t MaybeMatches(const TokenRange& tokens) = 0;
+
+  virtual void DumpHelp(VariableIndentationOutputStream& os) = 0;
+
+  virtual const std::optional<const char*>& GetCategory() = 0;
 };
 
 template <typename T>
@@ -136,10 +143,55 @@
     return std::make_pair(best_match_ptr, best_match);
   }
 
+  template <typename T = TArg>  // Necessary to get SFINAE to kick in.
+  void DumpHelp(VariableIndentationOutputStream& vios) {
+    // Separate arguments
+    vios.Stream() << std::endl;
+    for (auto cname : names_) {
+      std::string_view name = cname;
+      auto& os = vios.Stream();
+      std::function<void()> print_once;
+      if (using_blanks_) {
+        std::string_view nblank = name.substr(0, name.find("_"));
+        print_once = [&]() {
+          os << nblank;
+          if (has_value_map_) {
+            bool first = true;
+            for (auto [val, unused] : value_map_) {
+              os << (first ? "{" : "|") << val;
+              first = false;
+            }
+            os << "}";
+          } else if (metavar_) {
+            os << metavar_.value();
+          } else {
+            os << "{" << CmdlineType<T>::DescribeType() << "}";
+          }
+        };
+      } else {
+        print_once = [&]() {
+          os << name;
+        };
+      }
+      print_once();
+      if (appending_values_) {
+        os << " [";
+        print_once();
+        os << "...]";
+      }
+      os << std::endl;
+    }
+    if (help_) {
+      ScopedIndentation si(&vios);
+      vios.Stream() << help_.value() << std::endl;
+    }
+  }
+
+
   // Mark the argument definition as completed, do not mutate the object anymore after this
   // call is done.
   //
-  // Performs several sanity checks and token calculations.
+  // Performs several checks of the validity and token calculations.
   void CompleteArgument() {
     assert(names_.size() >= 1);
     assert(!is_completed_);
@@ -279,6 +331,10 @@
   bool has_value_list_ = false;
   std::vector<TArg> value_list_;
 
+  std::optional<const char*> help_;
+  std::optional<const char*> category_;
+  std::optional<const char*> metavar_;
+
   // Make sure there's a default constructor.
   CmdlineParserArgumentInfo() = default;
 
@@ -380,6 +436,14 @@
     return ParseArgumentSingle(blank_value);
   }
 
+  virtual void DumpHelp(VariableIndentationOutputStream& os) {
+    argument_info_.DumpHelp(os);
+  }
+
+  virtual const std::optional<const char*>& GetCategory() {
+    return argument_info_.category_;
+  }
+
  private:
   virtual CmdlineResult ParseArgumentSingle(const std::string& argument) {
     // TODO: refactor to use LookupValue for the value lists/maps
diff --git a/compiler/Android.bp b/compiler/Android.bp
index cbfff89..6b74f77 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -19,6 +19,15 @@
 // 64bit variant. It also might be good to allow one to compile only the 64bit variant without the
 // 32bit one.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 art_cc_defaults {
     name: "libart-compiler-defaults",
     defaults: ["art_defaults"],
@@ -37,6 +46,7 @@
         "jni/quick/calling_convention.cc",
         "jni/quick/jni_compiler.cc",
         "optimizing/block_builder.cc",
+        "optimizing/block_namer.cc",
         "optimizing/bounds_check_elimination.cc",
         "optimizing/builder.cc",
         "optimizing/cha_guard_optimization.cc",
@@ -48,6 +58,7 @@
         "optimizing/data_type.cc",
         "optimizing/dead_code_elimination.cc",
         "optimizing/escape.cc",
+        "optimizing/execution_subgraph.cc",
         "optimizing/graph_checker.cc",
         "optimizing/graph_visualizer.cc",
         "optimizing/gvn.cc",
@@ -97,6 +108,7 @@
                 "jni/quick/arm/calling_convention_arm.cc",
                 "optimizing/code_generator_arm_vixl.cc",
                 "optimizing/code_generator_vector_arm_vixl.cc",
+                "optimizing/critical_native_abi_fixup_arm.cc",
                 "optimizing/instruction_simplifier_arm.cc",
                 "optimizing/instruction_simplifier_shared.cc",
                 "optimizing/intrinsics_arm_vixl.cc",
@@ -112,7 +124,8 @@
             srcs: [
                 "jni/quick/arm64/calling_convention_arm64.cc",
                 "optimizing/code_generator_arm64.cc",
-                "optimizing/code_generator_vector_arm64.cc",
+                "optimizing/code_generator_vector_arm64_neon.cc",
+                "optimizing/code_generator_vector_arm64_sve.cc",
                 "optimizing/scheduler_arm64.cc",
                 "optimizing/instruction_simplifier_arm64.cc",
                 "optimizing/intrinsics_arm64.cc",
@@ -149,9 +162,13 @@
             ],
         },
     },
+    static: {
+        cflags: ["-DART_STATIC_LIBART_COMPILER"],
+    },
     generated_sources: ["art_compiler_operator_srcs"],
     shared_libs: [
         "libbase",
+        "liblzma", // libelffile(d) dependency; must be repeated here since it's a static lib.
     ],
     header_libs: [
         "art_cmdlineparser_headers", // For compiler_options.
@@ -164,7 +181,7 @@
 
 cc_defaults {
     name: "libart-compiler_static_base_defaults",
-    static_libs: [
+    whole_static_libs: [
         "libbase",
     ],
 }
@@ -174,9 +191,9 @@
     cmd: "$(location generate_operator_out) art/compiler $(in) > $(out)",
     tools: ["generate_operator_out"],
     srcs: [
-        "driver/compiler_options.h",
         "linker/linker_patch.h",
         "optimizing/locations.h",
+        "optimizing/nodes.h",
         "optimizing/optimizing_compiler_stats.h",
 
         "utils/arm/constants_arm.h",
@@ -189,41 +206,20 @@
     defaults: [
         "libart-compiler-defaults",
         "dex2oat-pgo-defaults",
+        "art_hugepage_defaults",
     ],
     codegen: {
         arm: {
             // VIXL assembly support for ARM targets.
-            static: {
-                whole_static_libs: [
-                    "libvixl",
-                ],
-            },
-            shared: {
-                shared_libs: [
-                    "libvixl",
-                ],
-                // Export vixl headers as they are included in this library's exported headers.
-                export_shared_lib_headers: [
-                    "libvixl",
-                ],
-            },
+            static_libs: [
+                "libvixl",
+            ],
         },
         arm64: {
             // VIXL assembly support for ARM64 targets.
-            static: {
-                whole_static_libs: [
-                    "libvixl",
-                ],
-            },
-            shared: {
-                shared_libs: [
-                    "libvixl",
-                ],
-                // Export vixl headers as they are included in this library's exported headers.
-                export_shared_lib_headers: [
-                    "libvixl",
-                ],
-            },
+            static_libs: [
+                "libvixl",
+            ],
         },
     },
     shared_libs: [
@@ -248,7 +244,7 @@
         },
     },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -257,12 +253,13 @@
     name: "libart-compiler_static_defaults",
     defaults: [
         "libart-compiler_static_base_defaults",
+        "libart-disassembler_static_defaults",
         "libart_static_defaults",
         "libartbase_static_defaults",
         "libdexfile_static_defaults",
         "libprofile_static_defaults",
     ],
-    static_libs: ["libart-compiler"],
+    whole_static_libs: ["libart-compiler"],
 }
 
 art_cc_library {
@@ -274,37 +271,23 @@
     codegen: {
         arm: {
             // VIXL assembly support for ARM targets.
-            static: {
-                whole_static_libs: [
-                    "libvixld",
-                ],
-            },
-            shared: {
-                shared_libs: [
-                    "libvixld",
-                ],
-                // Export vixl headers as they are included in this library's exported headers.
-                export_shared_lib_headers: [
-                    "libvixld",
-                ],
-            },
+            static_libs: [
+                "libvixld",
+            ],
+            // Export vixl headers as they are included in this library's headers used by tests.
+            export_static_lib_headers: [
+                "libvixld",
+            ],
         },
         arm64: {
             // VIXL assembly support for ARM64 targets.
-            static: {
-                whole_static_libs: [
-                    "libvixld",
-                ],
-            },
-            shared: {
-                shared_libs: [
-                    "libvixld",
-                ],
-                // Export vixl headers as they are included in this library's exported headers.
-                export_shared_lib_headers: [
-                    "libvixld",
-                ],
-            },
+            static_libs: [
+                "libvixld",
+            ],
+            // Export vixl headers as they are included in this library's headers used by tests.
+            export_static_lib_headers: [
+                "libvixld",
+            ],
         },
     },
     shared_libs: [
@@ -323,6 +306,10 @@
 
     apex_available: [
         "com.android.art.debug",
+        // TODO(b/183882457): This lib doesn't go into com.android.art, but
+        // apex_available lists need to be the same for internal libs to avoid
+        // stubs, and this depends on libdexfiled.
+        "com.android.art",
     ],
 }
 
@@ -330,33 +317,60 @@
     name: "libartd-compiler_static_defaults",
     defaults: [
         "libart-compiler_static_base_defaults",
-        "libartd_static_defaults",
         "libartbased_static_defaults",
+        "libartd-disassembler_static_defaults",
+        "libartd_static_defaults",
         "libdexfiled_static_defaults",
         "libprofiled_static_defaults",
     ],
-    static_libs: ["libartd-compiler"],
+    whole_static_libs: ["libartd-compiler"],
 }
 
-art_cc_library {
-    name: "libart-compiler-gtest",
-    defaults: ["libart-gtest-defaults"],
+// Properties common to `libart-compiler-gtest` and `libartd-compiler-gtest`.
+art_cc_defaults {
+    name: "libart-compiler-gtest-common",
     srcs: [
         "common_compiler_test.cc",
     ],
     shared_libs: [
-        "libartd-compiler",
-        "libartd-disassembler",
-        "libartbase-art-gtest",
-        "libart-runtime-gtest",
         "libbase",
     ],
 }
 
-art_cc_test {
-    name: "art_compiler_tests",
+art_cc_library {
+    name: "libart-compiler-gtest",
     defaults: [
-        "art_gtest_defaults",
+        "libart-gtest-defaults",
+        "libart-compiler-gtest-common",
+    ],
+    shared_libs: [
+        "libart-compiler",
+        "libart-disassembler",
+        "libartbase-art-gtest",
+        "libart-runtime-gtest",
+    ],
+}
+
+art_cc_library {
+    name: "libartd-compiler-gtest",
+    defaults: [
+        "libartd-gtest-defaults",
+        "libart-compiler-gtest-common",
+    ],
+    shared_libs: [
+        "libartd-compiler",
+        "libartd-disassembler",
+        "libartbased-art-gtest",
+        "libartd-runtime-gtest",
+    ],
+}
+
+art_cc_defaults {
+    name: "art_compiler_tests_defaults",
+    data: [
+        ":art-gtest-jars-ExceptionHandle",
+        ":art-gtest-jars-Interfaces",
+        ":art-gtest-jars-MyClassNatives",
     ],
     srcs: [
         "debug/dwarf/dwarf_test.cc",
@@ -367,8 +381,9 @@
         "linker/linker_patch_test.cc",
         "linker/output_stream_test.cc",
         "optimizing/bounds_check_elimination_test.cc",
-        "optimizing/superblock_cloner_test.cc",
+        "optimizing/constant_folding_test.cc",
         "optimizing/data_type_test.cc",
+        "optimizing/dead_code_elimination_test.cc",
         "optimizing/dominator_test.cc",
         "optimizing/find_loops_test.cc",
         "optimizing/graph_checker_test.cc",
@@ -377,7 +392,10 @@
         "optimizing/induction_var_analysis_test.cc",
         "optimizing/induction_var_range_test.cc",
         "optimizing/licm_test.cc",
+        "optimizing/linearize_test.cc",
         "optimizing/live_interval_test.cc",
+        "optimizing/live_ranges_test.cc",
+        "optimizing/liveness_test.cc",
         "optimizing/loop_optimization_test.cc",
         "optimizing/nodes_test.cc",
         "optimizing/nodes_vector_test.cc",
@@ -389,6 +407,7 @@
         "optimizing/ssa_liveness_analysis_test.cc",
         "optimizing/ssa_test.cc",
         "optimizing/stack_map_test.cc",
+        "optimizing/superblock_cloner_test.cc",
         "optimizing/suspend_check_test.cc",
         "utils/atomic_dex_ref_map_test.cc",
         "utils/dedupe_set_test.cc",
@@ -396,6 +415,8 @@
 
         "jni/jni_cfi_test.cc",
         "optimizing/codegen_test.cc",
+        "optimizing/execution_subgraph_test.cc",
+        "optimizing/instruction_simplifier_test.cc",
         "optimizing/load_store_analysis_test.cc",
         "optimizing/load_store_elimination_test.cc",
         "optimizing/optimizing_cfi_test.cc",
@@ -417,14 +438,8 @@
             srcs: [
                 "utils/x86/managed_register_x86_test.cc",
 
-                // These tests are testing architecture-independent
-                // functionality, but happen to use x86 codegen as part of the
-                // test.
-                "optimizing/constant_folding_test.cc",
-                "optimizing/dead_code_elimination_test.cc",
-                "optimizing/linearize_test.cc",
-                "optimizing/live_ranges_test.cc",
-                "optimizing/liveness_test.cc",
+                // This test is testing architecture-independent functionality,
+                // but happens to use x86 codegen as part of the test.
                 "optimizing/register_allocator_test.cc",
             ],
         },
@@ -442,11 +457,6 @@
     ],
 
     shared_libs: [
-        "libprofiled",
-        "libartd-compiler",
-        "libartd-simulator-container",
-        "libvixld",
-
         "libbacktrace",
         "libnativeloader",
     ],
@@ -460,6 +470,47 @@
     },
 }
 
+// Version of ART gtest `art_compiler_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
+art_cc_test {
+    name: "art_compiler_tests",
+    defaults: [
+        "art_gtest_defaults",
+        "art_compiler_tests_defaults",
+    ],
+    shared_libs: [
+        "libprofiled",
+        "libartd-compiler",
+        "libartd-simulator-container",
+    ],
+    static_libs: [
+        "libvixld",
+    ],
+}
+
+// Standalone version of ART gtest `art_compiler_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_compiler_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_compiler_tests_defaults",
+    ],
+    shared_libs: [
+        "libprofile",
+        "libart-compiler",
+    ],
+    static_libs: [
+        // For now, link `libart-simulator-container` statically for simplicity,
+        // to save the added complexity to package it in test suites (along with
+        // other test artifacts) and install it on device during tests.
+        // TODO(b/192070541): Consider linking `libart-simulator-container`
+        // dynamically.
+        "libart-simulator-container",
+        "libvixl",
+    ],
+    test_config: "art_standalone_compiler_tests.xml",
+}
+
 art_cc_test {
     name: "art_compiler_host_tests",
     device_supported: false,
@@ -485,6 +536,8 @@
     },
     shared_libs: [
         "libartd-compiler",
+    ],
+    static_libs: [
         "libvixld",
     ],
 }
diff --git a/compiler/art_standalone_compiler_tests.xml b/compiler/art_standalone_compiler_tests.xml
new file mode 100644
index 0000000..bf450a5
--- /dev/null
+++ b/compiler/art_standalone_compiler_tests.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs art_standalone_compiler_tests.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art_standalone_compiler_tests->/data/local/tmp/nativetest/art_standalone_compiler_tests" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art-gtest-jars-ExceptionHandle.jar->/data/local/tmp/nativetest/art-gtest-jars-ExceptionHandle.jar" />
+        <option name="push" value="art-gtest-jars-Interfaces.jar->/data/local/tmp/nativetest/art-gtest-jars-Interfaces.jar" />
+        <option name="push" value="art-gtest-jars-MyClassNatives.jar->/data/local/tmp/nativetest/art-gtest-jars-MyClassNatives.jar" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/nativetest" />
+        <option name="module-name" value="art_standalone_compiler_tests" />
+        <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+        <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index aec6646..9170a85 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -16,6 +16,7 @@
 
 #include "common_compiler_test.h"
 
+#include <android-base/unique_fd.h>
 #include <type_traits>
 
 #include "arch/instruction_set_features.h"
@@ -24,6 +25,7 @@
 #include "base/callee_save_type.h"
 #include "base/casts.h"
 #include "base/enums.h"
+#include "base/memfd.h"
 #include "base/utils.h"
 #include "class_linker.h"
 #include "compiled_method-inl.h"
@@ -44,82 +46,141 @@
 
 namespace art {
 
-CommonCompilerTest::CommonCompilerTest() {}
-CommonCompilerTest::~CommonCompilerTest() {}
+class CommonCompilerTestImpl::CodeAndMetadata {
+ public:
+  CodeAndMetadata(CodeAndMetadata&& other) = default;
 
-void CommonCompilerTest::MakeExecutable(ArtMethod* method, const CompiledMethod* compiled_method) {
+  CodeAndMetadata(ArrayRef<const uint8_t> code,
+                  ArrayRef<const uint8_t> vmap_table,
+                  InstructionSet instruction_set) {
+    const uint32_t code_size = code.size();
+    CHECK_NE(code_size, 0u);
+    const uint32_t vmap_table_offset = vmap_table.empty() ? 0u
+        : sizeof(OatQuickMethodHeader) + vmap_table.size();
+    OatQuickMethodHeader method_header(vmap_table_offset);
+    const size_t code_alignment = GetInstructionSetAlignment(instruction_set);
+    DCHECK_ALIGNED_PARAM(kPageSize, code_alignment);
+    code_offset_ = RoundUp(vmap_table.size() + sizeof(method_header), code_alignment);
+    const uint32_t capacity = RoundUp(code_offset_ + code_size, kPageSize);
+
+    // Create a memfd handle with sufficient capacity.
+    android::base::unique_fd mem_fd(art::memfd_create_compat("test code", /*flags=*/ 0));
+    CHECK_GE(mem_fd.get(), 0);
+    int err = ftruncate(mem_fd, capacity);
+    CHECK_EQ(err, 0);
+
+    // Map the memfd contents for read/write.
+    std::string error_msg;
+    rw_map_ = MemMap::MapFile(capacity,
+                              PROT_READ | PROT_WRITE,
+                              MAP_SHARED,
+                              mem_fd,
+                              /*start=*/ 0,
+                              /*low_4gb=*/ false,
+                              /*filename=*/ "test code",
+                              &error_msg);
+    CHECK(rw_map_.IsValid()) << error_msg;
+
+    // Store data.
+    uint8_t* code_addr = rw_map_.Begin() + code_offset_;
+    CHECK_ALIGNED_PARAM(code_addr, code_alignment);
+    CHECK_LE(vmap_table_offset, code_offset_);
+    memcpy(code_addr - vmap_table_offset, vmap_table.data(), vmap_table.size());
+    static_assert(std::is_trivially_copyable<OatQuickMethodHeader>::value, "Cannot use memcpy");
+    CHECK_LE(sizeof(method_header), code_offset_);
+    memcpy(code_addr - sizeof(method_header), &method_header, sizeof(method_header));
+    CHECK_LE(code_size, static_cast<size_t>(rw_map_.End() - code_addr));
+    memcpy(code_addr, code.data(), code_size);
+
+    // Sync data.
+    bool success = rw_map_.Sync();
+    CHECK(success);
+    success = FlushCpuCaches(rw_map_.Begin(), rw_map_.End());
+    CHECK(success);
+
+    // Map the data as read/executable.
+    rx_map_ = MemMap::MapFile(capacity,
+                              PROT_READ | PROT_EXEC,
+                              MAP_SHARED,
+                              mem_fd,
+                              /*start=*/ 0,
+                              /*low_4gb=*/ false,
+                              /*filename=*/ "test code",
+                              &error_msg);
+    CHECK(rx_map_.IsValid()) << error_msg;
+  }
+
+  const void* GetCodePointer() const {
+    DCHECK(rx_map_.IsValid());
+    DCHECK_LE(code_offset_, rx_map_.Size());
+    return rx_map_.Begin() + code_offset_;
+  }
+
+ private:
+  MemMap rw_map_;
+  MemMap rx_map_;
+  uint32_t code_offset_;
+
+  DISALLOW_COPY_AND_ASSIGN(CodeAndMetadata);
+};
+
+std::unique_ptr<CompilerOptions> CommonCompilerTestImpl::CreateCompilerOptions(
+    InstructionSet instruction_set, const std::string& variant) {
+  std::unique_ptr<CompilerOptions> compiler_options = std::make_unique<CompilerOptions>();
+  compiler_options->instruction_set_ = instruction_set;
+  std::string error_msg;
+  compiler_options->instruction_set_features_ =
+      InstructionSetFeatures::FromVariant(instruction_set, variant, &error_msg);
+  CHECK(compiler_options->instruction_set_features_ != nullptr) << error_msg;
+  return compiler_options;
+}
+
+CommonCompilerTestImpl::CommonCompilerTestImpl() {}
+CommonCompilerTestImpl::~CommonCompilerTestImpl() {}
+
+const void* CommonCompilerTestImpl::MakeExecutable(ArrayRef<const uint8_t> code,
+                                                   ArrayRef<const uint8_t> vmap_table,
+                                                   InstructionSet instruction_set) {
+  CHECK_NE(code.size(), 0u);
+  code_and_metadata_.emplace_back(code, vmap_table, instruction_set);
+  return code_and_metadata_.back().GetCodePointer();
+}
+
+void CommonCompilerTestImpl::MakeExecutable(ArtMethod* method,
+                                            const CompiledMethod* compiled_method) {
   CHECK(method != nullptr);
   // If the code size is 0 it means the method was skipped due to profile guided compilation.
   if (compiled_method != nullptr && compiled_method->GetQuickCode().size() != 0u) {
-    ArrayRef<const uint8_t> code = compiled_method->GetQuickCode();
-    const uint32_t code_size = code.size();
-    ArrayRef<const uint8_t> vmap_table = compiled_method->GetVmapTable();
-    const uint32_t vmap_table_offset = vmap_table.empty() ? 0u
-        : sizeof(OatQuickMethodHeader) + vmap_table.size();
-    OatQuickMethodHeader method_header(vmap_table_offset, code_size);
-
-    header_code_and_maps_chunks_.push_back(std::vector<uint8_t>());
-    std::vector<uint8_t>* chunk = &header_code_and_maps_chunks_.back();
-    const size_t max_padding = GetInstructionSetAlignment(compiled_method->GetInstructionSet());
-    const size_t size = vmap_table.size() + sizeof(method_header) + code_size;
-    chunk->reserve(size + max_padding);
-    chunk->resize(sizeof(method_header));
-    static_assert(std::is_trivially_copyable<OatQuickMethodHeader>::value, "Cannot use memcpy");
-    memcpy(&(*chunk)[0], &method_header, sizeof(method_header));
-    chunk->insert(chunk->begin(), vmap_table.begin(), vmap_table.end());
-    chunk->insert(chunk->end(), code.begin(), code.end());
-    CHECK_EQ(chunk->size(), size);
-    const void* unaligned_code_ptr = chunk->data() + (size - code_size);
-    size_t offset = dchecked_integral_cast<size_t>(reinterpret_cast<uintptr_t>(unaligned_code_ptr));
-    size_t padding = compiled_method->AlignCode(offset) - offset;
-    // Make sure no resizing takes place.
-    CHECK_GE(chunk->capacity(), chunk->size() + padding);
-    chunk->insert(chunk->begin(), padding, 0);
-    const void* code_ptr = reinterpret_cast<const uint8_t*>(unaligned_code_ptr) + padding;
-    CHECK_EQ(code_ptr, static_cast<const void*>(chunk->data() + (chunk->size() - code_size)));
-    MakeExecutable(code_ptr, code.size());
-    const void* method_code = CompiledMethod::CodePointer(code_ptr,
-                                                          compiled_method->GetInstructionSet());
+    const void* code_ptr = MakeExecutable(compiled_method->GetQuickCode(),
+                                          compiled_method->GetVmapTable(),
+                                          compiled_method->GetInstructionSet());
+    const void* method_code =
+        CompiledMethod::CodePointer(code_ptr, compiled_method->GetInstructionSet());
     LOG(INFO) << "MakeExecutable " << method->PrettyMethod() << " code=" << method_code;
     method->SetEntryPointFromQuickCompiledCode(method_code);
   } else {
     // No code? You must mean to go into the interpreter.
     // Or the generic JNI...
-    class_linker_->SetEntryPointsToInterpreter(method);
+    GetClassLinker()->SetEntryPointsToInterpreter(method);
   }
 }
 
-void CommonCompilerTest::MakeExecutable(const void* code_start, size_t code_length) {
-  CHECK(code_start != nullptr);
-  CHECK_NE(code_length, 0U);
-  uintptr_t data = reinterpret_cast<uintptr_t>(code_start);
-  uintptr_t base = RoundDown(data, kPageSize);
-  uintptr_t limit = RoundUp(data + code_length, kPageSize);
-  uintptr_t len = limit - base;
-  // Remove hwasan tag.  This is done in kernel in newer versions.  This supports older kernels.
-  void* base_ptr = HWASanUntag(reinterpret_cast<void*>(base));
-  int result = mprotect(base_ptr, len, PROT_READ | PROT_WRITE | PROT_EXEC);
-  CHECK_EQ(result, 0);
-
-  CHECK(FlushCpuCaches(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len)));
-}
-
-void CommonCompilerTest::SetUp() {
-  CommonRuntimeTest::SetUp();
+void CommonCompilerTestImpl::SetUp() {
   {
     ScopedObjectAccess soa(Thread::Current());
 
-    runtime_->SetInstructionSet(instruction_set_);
+    Runtime* runtime = GetRuntime();
+    runtime->SetInstructionSet(instruction_set_);
     for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); ++i) {
       CalleeSaveType type = CalleeSaveType(i);
-      if (!runtime_->HasCalleeSaveMethod(type)) {
-        runtime_->SetCalleeSaveMethod(runtime_->CreateCalleeSaveMethod(), type);
+      if (!runtime->HasCalleeSaveMethod(type)) {
+        runtime->SetCalleeSaveMethod(runtime->CreateCalleeSaveMethod(), type);
       }
     }
   }
 }
 
-void CommonCompilerTest::ApplyInstructionSet() {
+void CommonCompilerTestImpl::ApplyInstructionSet() {
   // Copy local instruction_set_ and instruction_set_features_ to *compiler_options_;
   CHECK(instruction_set_features_ != nullptr);
   if (instruction_set_ == InstructionSet::kThumb2) {
@@ -133,8 +194,8 @@
   CHECK(compiler_options_->instruction_set_features_->Equals(instruction_set_features_.get()));
 }
 
-void CommonCompilerTest::OverrideInstructionSetFeatures(InstructionSet instruction_set,
-                                                        const std::string& variant) {
+void CommonCompilerTestImpl::OverrideInstructionSetFeatures(InstructionSet instruction_set,
+                                                            const std::string& variant) {
   instruction_set_ = instruction_set;
   std::string error_msg;
   instruction_set_features_ =
@@ -146,33 +207,30 @@
   }
 }
 
-void CommonCompilerTest::SetUpRuntimeOptions(RuntimeOptions* options) {
-  CommonRuntimeTest::SetUpRuntimeOptions(options);
-
+void CommonCompilerTestImpl::SetUpRuntimeOptionsImpl() {
   compiler_options_.reset(new CompilerOptions);
   verification_results_.reset(new VerificationResults(compiler_options_.get()));
 
   ApplyInstructionSet();
 }
 
-Compiler::Kind CommonCompilerTest::GetCompilerKind() const {
+Compiler::Kind CommonCompilerTestImpl::GetCompilerKind() const {
   return compiler_kind_;
 }
 
-void CommonCompilerTest::SetCompilerKind(Compiler::Kind compiler_kind) {
+void CommonCompilerTestImpl::SetCompilerKind(Compiler::Kind compiler_kind) {
   compiler_kind_ = compiler_kind;
 }
 
-void CommonCompilerTest::TearDown() {
+void CommonCompilerTestImpl::TearDown() {
+  code_and_metadata_.clear();
   verification_results_.reset();
   compiler_options_.reset();
-
-  CommonRuntimeTest::TearDown();
 }
 
-void CommonCompilerTest::CompileMethod(ArtMethod* method) {
+void CommonCompilerTestImpl::CompileMethod(ArtMethod* method) {
   CHECK(method != nullptr);
-  TimingLogger timings("CommonCompilerTest::CompileMethod", false, false);
+  TimingLogger timings("CommonCompilerTestImpl::CompileMethod", false, false);
   TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
   CompiledMethodStorage storage(/*swap_fd=*/ -1);
   CompiledMethod* compiled_method = nullptr;
@@ -183,7 +241,8 @@
     std::unique_ptr<Compiler> compiler(
         Compiler::Create(*compiler_options_, &storage, compiler_kind_));
     const DexFile& dex_file = *method->GetDexFile();
-    Handle<mirror::DexCache> dex_cache = hs.NewHandle(class_linker_->FindDexCache(self, dex_file));
+    Handle<mirror::DexCache> dex_cache =
+        hs.NewHandle(GetClassLinker()->FindDexCache(self, dex_file));
     Handle<mirror::ClassLoader> class_loader = hs.NewHandle(method->GetClassLoader());
     compiler_options_->verification_results_ = verification_results_.get();
     if (method->IsNative()) {
@@ -214,37 +273,41 @@
   CompiledMethod::ReleaseSwapAllocatedCompiledMethod(&storage, compiled_method);
 }
 
-void CommonCompilerTest::CompileDirectMethod(Handle<mirror::ClassLoader> class_loader,
-                                             const char* class_name, const char* method_name,
-                                             const char* signature) {
+void CommonCompilerTestImpl::CompileDirectMethod(Handle<mirror::ClassLoader> class_loader,
+                                                 const char* class_name,
+                                                 const char* method_name,
+                                                 const char* signature) {
   std::string class_descriptor(DotToDescriptor(class_name));
   Thread* self = Thread::Current();
+  ClassLinker* class_linker = GetClassLinker();
   ObjPtr<mirror::Class> klass =
-      class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
+      class_linker->FindClass(self, class_descriptor.c_str(), class_loader);
   CHECK(klass != nullptr) << "Class not found " << class_name;
-  auto pointer_size = class_linker_->GetImagePointerSize();
+  auto pointer_size = class_linker->GetImagePointerSize();
   ArtMethod* method = klass->FindClassMethod(method_name, signature, pointer_size);
   CHECK(method != nullptr && method->IsDirect()) << "Direct method not found: "
       << class_name << "." << method_name << signature;
   CompileMethod(method);
 }
 
-void CommonCompilerTest::CompileVirtualMethod(Handle<mirror::ClassLoader> class_loader,
-                                              const char* class_name, const char* method_name,
-                                              const char* signature) {
+void CommonCompilerTestImpl::CompileVirtualMethod(Handle<mirror::ClassLoader> class_loader,
+                                                  const char* class_name,
+                                                  const char* method_name,
+                                                  const char* signature) {
   std::string class_descriptor(DotToDescriptor(class_name));
   Thread* self = Thread::Current();
+  ClassLinker* class_linker = GetClassLinker();
   ObjPtr<mirror::Class> klass =
-      class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
+      class_linker->FindClass(self, class_descriptor.c_str(), class_loader);
   CHECK(klass != nullptr) << "Class not found " << class_name;
-  auto pointer_size = class_linker_->GetImagePointerSize();
+  auto pointer_size = class_linker->GetImagePointerSize();
   ArtMethod* method = klass->FindClassMethod(method_name, signature, pointer_size);
   CHECK(method != nullptr && !method->IsDirect()) << "Virtual method not found: "
       << class_name << "." << method_name << signature;
   CompileMethod(method);
 }
 
-void CommonCompilerTest::ClearBootImageOption() {
+void CommonCompilerTestImpl::ClearBootImageOption() {
   compiler_options_->image_type_ = CompilerOptions::ImageType::kNone;
 }
 
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 4f4e49a..89cc1fa 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -42,20 +42,26 @@
 
 template<class T> class Handle;
 
-class CommonCompilerTest : public CommonRuntimeTest {
+class CommonCompilerTestImpl {
  public:
-  CommonCompilerTest();
-  ~CommonCompilerTest();
+  static std::unique_ptr<CompilerOptions> CreateCompilerOptions(InstructionSet instruction_set,
+                                                                const std::string& variant);
+
+  CommonCompilerTestImpl();
+  virtual ~CommonCompilerTestImpl();
+
+  // Create an executable copy of the code with given metadata.
+  const void* MakeExecutable(ArrayRef<const uint8_t> code,
+                             ArrayRef<const uint8_t> vmap_table,
+                             InstructionSet instruction_set);
 
   void MakeExecutable(ArtMethod* method, const CompiledMethod* compiled_method)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  static void MakeExecutable(const void* code_start, size_t code_length);
-
  protected:
-  void SetUp() override;
+  void SetUp();
 
-  void SetUpRuntimeOptions(RuntimeOptions* options) override;
+  void SetUpRuntimeOptionsImpl();
 
   Compiler::Kind GetCompilerKind() const;
   void SetCompilerKind(Compiler::Kind compiler_kind);
@@ -64,7 +70,7 @@
     return CompilerFilter::kDefaultCompilerFilter;
   }
 
-  void TearDown() override;
+  void TearDown();
 
   void CompileMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -92,11 +98,46 @@
   std::unique_ptr<CompilerOptions> compiler_options_;
   std::unique_ptr<VerificationResults> verification_results_;
 
+ protected:
+  virtual ClassLinker* GetClassLinker() = 0;
+  virtual Runtime* GetRuntime() = 0;
+
  private:
-  // Chunks must not move their storage after being created - use the node-based std::list.
-  std::list<std::vector<uint8_t>> header_code_and_maps_chunks_;
+  class CodeAndMetadata;
+  std::vector<CodeAndMetadata> code_and_metadata_;
 };
 
+template <typename RuntimeBase>
+class CommonCompilerTestBase : public CommonCompilerTestImpl, public RuntimeBase {
+ public:
+  void SetUp() override {
+    RuntimeBase::SetUp();
+    CommonCompilerTestImpl::SetUp();
+  }
+  void SetUpRuntimeOptions(RuntimeOptions* options) override {
+    RuntimeBase::SetUpRuntimeOptions(options);
+    CommonCompilerTestImpl::SetUpRuntimeOptionsImpl();
+  }
+  void TearDown() override {
+    CommonCompilerTestImpl::TearDown();
+    RuntimeBase::TearDown();
+  }
+
+ protected:
+  ClassLinker* GetClassLinker() override {
+    return RuntimeBase::class_linker_;
+  }
+  Runtime* GetRuntime() override {
+    return RuntimeBase::runtime_.get();
+  }
+};
+
+class CommonCompilerTest : public CommonCompilerTestBase<CommonRuntimeTest> {};
+
+template <typename Param>
+class CommonCompilerTestWithParam
+    : public CommonCompilerTestBase<CommonRuntimeTestWithParam<Param>> {};
+
 }  // namespace art
 
 #endif  // ART_COMPILER_COMMON_COMPILER_TEST_H_
diff --git a/compiler/compiler.h b/compiler/compiler.h
index e363e70..afa0dba 100644
--- a/compiler/compiler.h
+++ b/compiler/compiler.h
@@ -19,6 +19,7 @@
 
 #include "base/mutex.h"
 #include "base/os.h"
+#include "compilation_kind.h"
 #include "dex/invoke_type.h"
 
 namespace art {
@@ -75,8 +76,7 @@
                           jit::JitCodeCache* code_cache ATTRIBUTE_UNUSED,
                           jit::JitMemoryRegion* region ATTRIBUTE_UNUSED,
                           ArtMethod* method ATTRIBUTE_UNUSED,
-                          bool baseline ATTRIBUTE_UNUSED,
-                          bool osr ATTRIBUTE_UNUSED,
+                          CompilationKind compilation_kind ATTRIBUTE_UNUSED,
                           jit::JitLogger* jit_logger ATTRIBUTE_UNUSED)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     return false;
diff --git a/compiler/debug/dwarf/dwarf_test.cc b/compiler/debug/dwarf/dwarf_test.cc
index 5946af8..8897e45 100644
--- a/compiler/debug/dwarf/dwarf_test.cc
+++ b/compiler/debug/dwarf/dwarf_test.cc
@@ -36,86 +36,88 @@
   const int offset = 40000;
   ASSERT_EQ(UnsignedLeb128Size(offset / 4), 2u);
   ASSERT_EQ(SignedLeb128Size(offset / 4), 3u);
-  DW_CHECK("Data alignment factor: -4");
   const Reg reg(6);
 
   // Test the opcodes in the order mentioned in the spec.
   // There are usually several encoding variations of each opcode.
   DebugFrameOpCodeWriter<> opcodes;
+  DW_CHECK(".debug_frame contents:");
   DW_CHECK("FDE");
+  DW_CHECK_NEXT("DWARF32");
+  DW_CHECK_NEXT("DW_CFA_nop:");  // TODO: Why is a nop here.
   int pc = 0;
   for (int i : {0, 1, 0x3F, 0x40, 0xFF, 0x100, 0xFFFF, 0x10000}) {
     pc += i;
     opcodes.AdvancePC(pc);
   }
-  DW_CHECK_NEXT("DW_CFA_advance_loc: 1 to 01000001");
-  DW_CHECK_NEXT("DW_CFA_advance_loc: 63 to 01000040");
-  DW_CHECK_NEXT("DW_CFA_advance_loc1: 64 to 01000080");
-  DW_CHECK_NEXT("DW_CFA_advance_loc1: 255 to 0100017f");
-  DW_CHECK_NEXT("DW_CFA_advance_loc2: 256 to 0100027f");
-  DW_CHECK_NEXT("DW_CFA_advance_loc2: 65535 to 0101027e");
-  DW_CHECK_NEXT("DW_CFA_advance_loc4: 65536 to 0102027e");
+  DW_CHECK_NEXT("DW_CFA_advance_loc: 1");
+  DW_CHECK_NEXT("DW_CFA_advance_loc: 63");
+  DW_CHECK_NEXT("DW_CFA_advance_loc1: 64");
+  DW_CHECK_NEXT("DW_CFA_advance_loc1: 255");
+  DW_CHECK_NEXT("DW_CFA_advance_loc2: 256");
+  DW_CHECK_NEXT("DW_CFA_advance_loc2: 65535");
+  DW_CHECK_NEXT("DW_CFA_advance_loc4: 65536");
   opcodes.DefCFA(reg, offset);
-  DW_CHECK_NEXT("DW_CFA_def_cfa: r6 (esi) ofs 40000");
+  DW_CHECK_NEXT("DW_CFA_def_cfa: ESI +40000");
   opcodes.DefCFA(reg, -offset);
-  DW_CHECK_NEXT("DW_CFA_def_cfa_sf: r6 (esi) ofs -40000");
+  DW_CHECK_NEXT("DW_CFA_def_cfa_sf: ESI -40000");
   opcodes.DefCFARegister(reg);
-  DW_CHECK_NEXT("DW_CFA_def_cfa_register: r6 (esi)");
+  DW_CHECK_NEXT("DW_CFA_def_cfa_register: ESI");
   opcodes.DefCFAOffset(offset);
-  DW_CHECK_NEXT("DW_CFA_def_cfa_offset: 40000");
+  DW_CHECK_NEXT("DW_CFA_def_cfa_offset: +40000");
   opcodes.DefCFAOffset(-offset);
   DW_CHECK_NEXT("DW_CFA_def_cfa_offset_sf: -40000");
-  uint8_t expr[] = { 0 };
+  uint8_t expr[] = { /*nop*/ 0x96 };
   opcodes.DefCFAExpression(expr, arraysize(expr));
-  DW_CHECK_NEXT("DW_CFA_def_cfa_expression");
+  DW_CHECK_NEXT("DW_CFA_def_cfa_expression: DW_OP_nop");
   opcodes.Undefined(reg);
-  DW_CHECK_NEXT("DW_CFA_undefined: r6 (esi)");
+  DW_CHECK_NEXT("DW_CFA_undefined: ESI");
   opcodes.SameValue(reg);
-  DW_CHECK_NEXT("DW_CFA_same_value: r6 (esi)");
+  DW_CHECK_NEXT("DW_CFA_same_value: ESI");
   opcodes.Offset(Reg(0x3F), -offset);
-  DW_CHECK_NEXT("DW_CFA_offset: r63 at cfa-40000");
+  DW_CHECK_NEXT("DW_CFA_offset: reg63 -40000");
   opcodes.Offset(Reg(0x40), -offset);
-  DW_CHECK_NEXT("DW_CFA_offset_extended: r64 at cfa-40000");
+  DW_CHECK_NEXT("DW_CFA_offset_extended: reg64 -40000");
   opcodes.Offset(Reg(0x40), offset);
-  DW_CHECK_NEXT("DW_CFA_offset_extended_sf: r64 at cfa+40000");
+  DW_CHECK_NEXT("DW_CFA_offset_extended_sf: reg64 40000");
   opcodes.ValOffset(reg, -offset);
-  DW_CHECK_NEXT("DW_CFA_val_offset: r6 (esi) at cfa-40000");
+  DW_CHECK_NEXT("DW_CFA_val_offset: ESI -40000");
   opcodes.ValOffset(reg, offset);
-  DW_CHECK_NEXT("DW_CFA_val_offset_sf: r6 (esi) at cfa+40000");
+  DW_CHECK_NEXT("DW_CFA_val_offset_sf: ESI 40000");
   opcodes.Register(reg, Reg(1));
-  DW_CHECK_NEXT("DW_CFA_register: r6 (esi) in r1 (ecx)");
+  DW_CHECK_NEXT("DW_CFA_register: ESI ECX");
   opcodes.Expression(reg, expr, arraysize(expr));
-  DW_CHECK_NEXT("DW_CFA_expression: r6 (esi)");
+  DW_CHECK_NEXT("DW_CFA_expression: ESI DW_OP_nop");
   opcodes.ValExpression(reg, expr, arraysize(expr));
-  DW_CHECK_NEXT("DW_CFA_val_expression: r6 (esi)");
+  DW_CHECK_NEXT("DW_CFA_val_expression: ESI DW_OP_nop");
   opcodes.Restore(Reg(0x3F));
-  DW_CHECK_NEXT("DW_CFA_restore: bad register: r63");
+  DW_CHECK_NEXT("DW_CFA_restore: reg63");
   opcodes.Restore(Reg(0x40));
-  DW_CHECK_NEXT("DW_CFA_restore_extended: bad register: r64");
+  DW_CHECK_NEXT("DW_CFA_restore_extended: reg64");
   opcodes.Restore(reg);
-  DW_CHECK_NEXT("DW_CFA_restore: r6 (esi)");
+  DW_CHECK_NEXT("DW_CFA_restore: ESI");
   opcodes.RememberState();
-  DW_CHECK_NEXT("DW_CFA_remember_state");
+  DW_CHECK_NEXT("DW_CFA_remember_state:");
   opcodes.RestoreState();
-  DW_CHECK_NEXT("DW_CFA_restore_state");
+  DW_CHECK_NEXT("DW_CFA_restore_state:");
   opcodes.Nop();
-  DW_CHECK_NEXT("DW_CFA_nop");
+  DW_CHECK_NEXT("DW_CFA_nop:");
 
   // Also test helpers.
   opcodes.DefCFA(Reg(4), 100);  // ESP
-  DW_CHECK_NEXT("DW_CFA_def_cfa: r4 (esp) ofs 100");
+  DW_CHECK_NEXT("DW_CFA_def_cfa: ESP +100");
   opcodes.AdjustCFAOffset(8);
-  DW_CHECK_NEXT("DW_CFA_def_cfa_offset: 108");
+  DW_CHECK_NEXT("DW_CFA_def_cfa_offset: +108");
   opcodes.RelOffset(Reg(0), 0);  // push R0
-  DW_CHECK_NEXT("DW_CFA_offset: r0 (eax) at cfa-108");
+  DW_CHECK_NEXT("DW_CFA_offset: EAX -108");
   opcodes.RelOffset(Reg(1), 4);  // push R1
-  DW_CHECK_NEXT("DW_CFA_offset: r1 (ecx) at cfa-104");
+  DW_CHECK_NEXT("DW_CFA_offset: ECX -104");
   opcodes.RelOffsetForMany(Reg(2), 8, 1 | (1 << 3), 4);  // push R2 and R5
-  DW_CHECK_NEXT("DW_CFA_offset: r2 (edx) at cfa-100");
-  DW_CHECK_NEXT("DW_CFA_offset: r5 (ebp) at cfa-96");
+  DW_CHECK_NEXT("DW_CFA_offset: EDX -100");
+  DW_CHECK_NEXT("DW_CFA_offset: EBP -96");
   opcodes.RestoreMany(Reg(2), 1 | (1 << 3));  // pop R2 and R5
-  DW_CHECK_NEXT("DW_CFA_restore: r2 (edx)");
-  DW_CHECK_NEXT("DW_CFA_restore: r5 (ebp)");
+  DW_CHECK_NEXT("DW_CFA_restore: EDX");
+  DW_CHECK_NEXT("DW_CFA_restore: EBP");
 
   DebugFrameOpCodeWriter<> initial_opcodes;
   WriteCIE(is64bit, Reg(is64bit ? 16 : 8), initial_opcodes, &debug_frame_data_);
@@ -126,7 +128,7 @@
            ArrayRef<const uint8_t>(*opcodes.data()),
            &debug_frame_data_);
 
-  CheckObjdumpOutput(is64bit, "-W");
+  CheckObjdumpOutput(is64bit, "-debug-frame");
 }
 
 TEST_F(DwarfTest, DISABLED_DebugFrame64) {
@@ -134,6 +136,7 @@
   DebugFrameOpCodeWriter<> initial_opcodes;
   WriteCIE(is64bit, Reg(16), initial_opcodes, &debug_frame_data_);
   DebugFrameOpCodeWriter<> opcodes;
+  DW_CHECK(".debug_frame contents:");
   WriteFDE(is64bit,
            /* cie_pointer= */ 0,
            0x0100000000000000,
@@ -142,34 +145,38 @@
            &debug_frame_data_);
   DW_CHECK("FDE cie=00000000 pc=100000000000000..300000000000000");
 
-  CheckObjdumpOutput(is64bit, "-W");
+  CheckObjdumpOutput(is64bit, "-debug-frame");
 }
 
 // Test x86_64 register mapping. It is the only non-trivial architecture.
-// ARM, X86, and Mips have: dwarf_reg = art_reg + constant.
+// ARM and X86 have: dwarf_reg = art_reg + constant.
 TEST_F(DwarfTest, x86_64_RegisterMapping) {
   constexpr bool is64bit = true;
   DebugFrameOpCodeWriter<> opcodes;
+  DW_CHECK(".debug_frame contents:");
   for (int i = 0; i < 16; i++) {
     opcodes.RelOffset(Reg::X86_64Core(i), 0);
   }
   DW_CHECK("FDE");
-  DW_CHECK_NEXT("DW_CFA_offset: r0 (rax)");
-  DW_CHECK_NEXT("DW_CFA_offset: r2 (rcx)");
-  DW_CHECK_NEXT("DW_CFA_offset: r1 (rdx)");
-  DW_CHECK_NEXT("DW_CFA_offset: r3 (rbx)");
-  DW_CHECK_NEXT("DW_CFA_offset: r7 (rsp)");
-  DW_CHECK_NEXT("DW_CFA_offset: r6 (rbp)");
-  DW_CHECK_NEXT("DW_CFA_offset: r4 (rsi)");
-  DW_CHECK_NEXT("DW_CFA_offset: r5 (rdi)");
-  DW_CHECK_NEXT("DW_CFA_offset: r8 (r8)");
-  DW_CHECK_NEXT("DW_CFA_offset: r9 (r9)");
-  DW_CHECK_NEXT("DW_CFA_offset: r10 (r10)");
-  DW_CHECK_NEXT("DW_CFA_offset: r11 (r11)");
-  DW_CHECK_NEXT("DW_CFA_offset: r12 (r12)");
-  DW_CHECK_NEXT("DW_CFA_offset: r13 (r13)");
-  DW_CHECK_NEXT("DW_CFA_offset: r14 (r14)");
-  DW_CHECK_NEXT("DW_CFA_offset: r15 (r15)");
+  DW_CHECK_NEXT("DWARF32");
+  DW_CHECK_NEXT("DW_CFA_nop:");  // TODO: Why is a nop here.
+  DW_CHECK_NEXT("DW_CFA_offset: RAX 0");
+  DW_CHECK_NEXT("DW_CFA_offset: RCX 0");
+  DW_CHECK_NEXT("DW_CFA_offset: RDX 0");
+  DW_CHECK_NEXT("DW_CFA_offset: RBX 0");
+  DW_CHECK_NEXT("DW_CFA_offset: RSP 0");
+  DW_CHECK_NEXT("DW_CFA_offset: RBP 0");
+  DW_CHECK_NEXT("DW_CFA_offset: RSI 0");
+  DW_CHECK_NEXT("DW_CFA_offset: RDI 0");
+  DW_CHECK_NEXT("DW_CFA_offset: R8 0");
+  DW_CHECK_NEXT("DW_CFA_offset: R9 0");
+  DW_CHECK_NEXT("DW_CFA_offset: R10 0");
+  DW_CHECK_NEXT("DW_CFA_offset: R11 0");
+  DW_CHECK_NEXT("DW_CFA_offset: R12 0");
+  DW_CHECK_NEXT("DW_CFA_offset: R13 0");
+  DW_CHECK_NEXT("DW_CFA_offset: R14 0");
+  DW_CHECK_NEXT("DW_CFA_offset: R15 0");
+
   DebugFrameOpCodeWriter<> initial_opcodes;
   WriteCIE(is64bit, Reg(16), initial_opcodes, &debug_frame_data_);
   WriteFDE(is64bit,
@@ -179,62 +186,62 @@
            ArrayRef<const uint8_t>(*opcodes.data()),
            &debug_frame_data_);
 
-  CheckObjdumpOutput(is64bit, "-W");
+  CheckObjdumpOutput(is64bit, "-debug-frame");
 }
 
-TEST_F(DwarfTest, DISABLED_DebugLine) {
+TEST_F(DwarfTest, DebugLine) {
   const bool is64bit = false;
   const int code_factor_bits = 1;
   DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits);
+  DW_CHECK(".debug_line contents:");
 
   std::vector<std::string> include_directories;
   include_directories.push_back("/path/to/source");
-  DW_CHECK("/path/to/source");
+  DW_CHECK("include_directories[  1] = \"/path/to/source\"");
 
   std::vector<FileEntry> files {
     { "file0.c", 0, 1000, 2000 },
     { "file1.c", 1, 1000, 2000 },
     { "file2.c", 1, 1000, 2000 },
   };
-  DW_CHECK("1\t0\t1000\t2000\tfile0.c");
-  DW_CHECK_NEXT("2\t1\t1000\t2000\tfile1.c");
-  DW_CHECK_NEXT("3\t1\t1000\t2000\tfile2.c");
+  DW_CHECK_NEXT("file_names[  1]:");
+  DW_CHECK_NEXT("           name: \"file0.c\"");
+  DW_CHECK_NEXT("      dir_index: 0");
+  DW_CHECK_NEXT("       mod_time: 0x000003e8");
+  DW_CHECK_NEXT("         length: 0x000007d0");
+  DW_CHECK_NEXT("file_names[  2]:");
+  DW_CHECK_NEXT("           name: \"file1.c\"");
+  DW_CHECK_NEXT("      dir_index: 1");
+  DW_CHECK_NEXT("       mod_time: 0x000003e8");
+  DW_CHECK_NEXT("         length: 0x000007d0");
+  DW_CHECK_NEXT("file_names[  3]:");
+  DW_CHECK_NEXT("           name: \"file2.c\"");
+  DW_CHECK_NEXT("      dir_index: 1");
+  DW_CHECK_NEXT("       mod_time: 0x000003e8");
+  DW_CHECK_NEXT("         length: 0x000007d0");
 
-  DW_CHECK("Line Number Statements");
   opcodes.SetAddress(0x01000000);
-  DW_CHECK_NEXT("Extended opcode 2: set Address to 0x1000000");
-  opcodes.AddRow();
-  DW_CHECK_NEXT("Copy");
-  opcodes.AdvancePC(0x01000100);
-  DW_CHECK_NEXT("Advance PC by 256 to 0x1000100");
-  opcodes.SetFile(2);
-  DW_CHECK_NEXT("Set File Name to entry 2 in the File Name Table");
-  opcodes.AdvanceLine(3);
-  DW_CHECK_NEXT("Advance Line by 2 to 3");
-  opcodes.SetColumn(4);
-  DW_CHECK_NEXT("Set column to 4");
   opcodes.SetIsStmt(true);
-  DW_CHECK_NEXT("Set is_stmt to 1");
+  opcodes.AddRow();
+  opcodes.AdvancePC(0x01000100);
+  opcodes.SetFile(2);
+  opcodes.AdvanceLine(3);
+  opcodes.SetColumn(4);
   opcodes.SetIsStmt(false);
-  DW_CHECK_NEXT("Set is_stmt to 0");
   opcodes.SetBasicBlock();
-  DW_CHECK_NEXT("Set basic block");
   opcodes.SetPrologueEnd();
-  DW_CHECK_NEXT("Set prologue_end to true");
   opcodes.SetEpilogueBegin();
-  DW_CHECK_NEXT("Set epilogue_begin to true");
   opcodes.SetISA(5);
-  DW_CHECK_NEXT("Set ISA to 5");
   opcodes.EndSequence();
-  DW_CHECK_NEXT("Extended opcode 1: End of Sequence");
   opcodes.DefineFile("file.c", 0, 1000, 2000);
-  DW_CHECK_NEXT("Extended opcode 3: define new File Table entry");
-  DW_CHECK_NEXT("Entry\tDir\tTime\tSize\tName");
-  DW_CHECK_NEXT("1\t0\t1000\t2000\tfile.c");
+  DW_CHECK_NEXT("Address            Line   Column File   ISA Discriminator Flags");
+  DW_CHECK_NEXT("------------------ ------ ------ ------ --- ------------- -------------");
+  DW_CHECK_NEXT("0x0000000001000000      1      0      1   0             0  is_stmt");
+  DW_CHECK_NEXT("0x0000000001000100      3      4      2   5             0  basic_block prologue_end epilogue_begin end_sequence");
 
   WriteDebugLineTable(include_directories, files, opcodes, &debug_line_data_);
 
-  CheckObjdumpOutput(is64bit, "-W");
+  CheckObjdumpOutput(is64bit, "-debug-line");
 }
 
 // DWARF has special one byte codes which advance PC and line at the same time.
@@ -246,11 +253,11 @@
   DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits);
   opcodes.SetAddress(pc);
   size_t num_rows = 0;
-  DW_CHECK("Line Number Statements:");
-  DW_CHECK("Special opcode");
-  DW_CHECK("Advance PC by constant");
-  DW_CHECK("Decoded dump of debug contents of section .debug_line:");
-  DW_CHECK("Line number    Starting address");
+  DW_CHECK(".debug_line contents:");
+  DW_CHECK("file_names[  1]:");
+  DW_CHECK("           name: \"file.c\"");
+  DW_CHECK("Address            Line   Column File   ISA Discriminator Flags");
+  DW_CHECK("------------------ ------ ------ ------ --- ------------- -------------");
   for (int addr_delta = 0; addr_delta < 80; addr_delta += 2) {
     for (int line_delta = 16; line_delta >= -16; --line_delta) {
       pc += addr_delta;
@@ -260,71 +267,74 @@
       ASSERT_EQ(opcodes.CurrentAddress(), pc);
       ASSERT_EQ(opcodes.CurrentLine(), line);
       char expected[1024];
-      sprintf(expected, "%i           0x%x", line, pc);
+      sprintf(expected, "0x%016x %6i      0      1   0             0", pc, line);
       DW_CHECK_NEXT(expected);
     }
   }
+  opcodes.EndSequence();
   EXPECT_LT(opcodes.data()->size(), num_rows * 3);
 
   std::vector<std::string> directories;
   std::vector<FileEntry> files = { { "file.c", 0, 1000, 2000 } };
   WriteDebugLineTable(directories, files, opcodes, &debug_line_data_);
 
-  CheckObjdumpOutput(is64bit, "-W -WL");
+  CheckObjdumpOutput(is64bit, "-debug-line");
 }
 
 TEST_F(DwarfTest, DebugInfo) {
   constexpr bool is64bit = false;
+
   DebugAbbrevWriter<> debug_abbrev(&debug_abbrev_data_);
+  DW_CHECK(".debug_abbrev contents:");
+  DW_CHECK_NEXT("Abbrev table for offset: 0x00000000");
+  DW_CHECK_NEXT("[1] DW_TAG_compile_unit DW_CHILDREN_yes");
+  DW_CHECK_NEXT(" DW_AT_producer DW_FORM_strp");
+  DW_CHECK_NEXT(" DW_AT_low_pc DW_FORM_addr");
+  DW_CHECK_NEXT(" DW_AT_high_pc DW_FORM_addr");
+  DW_CHECK_NEXT("[2] DW_TAG_subprogram DW_CHILDREN_no");
+  DW_CHECK_NEXT(" DW_AT_name DW_FORM_strp");
+  DW_CHECK_NEXT(" DW_AT_low_pc DW_FORM_addr");
+  DW_CHECK_NEXT(" DW_AT_high_pc DW_FORM_addr");
+  DW_CHECK_NEXT("[3] DW_TAG_compile_unit DW_CHILDREN_no");
+
   DebugInfoEntryWriter<> info(is64bit, &debug_abbrev);
-  DW_CHECK("Contents of the .debug_info section:");
+  DW_CHECK(".debug_info contents:");
   info.StartTag(dwarf::DW_TAG_compile_unit);
-  DW_CHECK("Abbrev Number: 1 (DW_TAG_compile_unit)");
+  DW_CHECK_NEXT("Compile Unit: length = 0x00000030, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x04");
+  DW_CHECK_NEXT("DW_TAG_compile_unit");
   info.WriteStrp(dwarf::DW_AT_producer, "Compiler name", &debug_str_data_);
-  DW_CHECK_NEXT("DW_AT_producer    : (indirect string, offset: 0x0): Compiler name");
+  DW_CHECK_NEXT("  DW_AT_producer (\"Compiler name\")");
   info.WriteAddr(dwarf::DW_AT_low_pc, 0x01000000);
-  DW_CHECK_NEXT("DW_AT_low_pc      : 0x1000000");
+  DW_CHECK_NEXT("  DW_AT_low_pc (0x01000000)");
   info.WriteAddr(dwarf::DW_AT_high_pc, 0x02000000);
-  DW_CHECK_NEXT("DW_AT_high_pc     : 0x2000000");
+  DW_CHECK_NEXT("  DW_AT_high_pc (0x02000000)");
   info.StartTag(dwarf::DW_TAG_subprogram);
-  DW_CHECK("Abbrev Number: 2 (DW_TAG_subprogram)");
+  DW_CHECK_NEXT("  DW_TAG_subprogram");
   info.WriteStrp(dwarf::DW_AT_name, "Foo", &debug_str_data_);
-  DW_CHECK_NEXT("DW_AT_name        : (indirect string, offset: 0xe): Foo");
+  DW_CHECK_NEXT("    DW_AT_name (\"Foo\")");
   info.WriteAddr(dwarf::DW_AT_low_pc, 0x01010000);
-  DW_CHECK_NEXT("DW_AT_low_pc      : 0x1010000");
+  DW_CHECK_NEXT("    DW_AT_low_pc (0x01010000)");
   info.WriteAddr(dwarf::DW_AT_high_pc, 0x01020000);
-  DW_CHECK_NEXT("DW_AT_high_pc     : 0x1020000");
+  DW_CHECK_NEXT("    DW_AT_high_pc (0x01020000)");
   info.EndTag();  // DW_TAG_subprogram
   info.StartTag(dwarf::DW_TAG_subprogram);
-  DW_CHECK("Abbrev Number: 2 (DW_TAG_subprogram)");
+  DW_CHECK_NEXT("  DW_TAG_subprogram");
   info.WriteStrp(dwarf::DW_AT_name, "Bar", &debug_str_data_);
-  DW_CHECK_NEXT("DW_AT_name        : (indirect string, offset: 0x12): Bar");
+  DW_CHECK_NEXT("    DW_AT_name (\"Bar\")");
   info.WriteAddr(dwarf::DW_AT_low_pc, 0x01020000);
-  DW_CHECK_NEXT("DW_AT_low_pc      : 0x1020000");
+  DW_CHECK_NEXT("    DW_AT_low_pc (0x01020000)");
   info.WriteAddr(dwarf::DW_AT_high_pc, 0x01030000);
-  DW_CHECK_NEXT("DW_AT_high_pc     : 0x1030000");
+  DW_CHECK_NEXT("    DW_AT_high_pc (0x01030000)");
   info.EndTag();  // DW_TAG_subprogram
   info.EndTag();  // DW_TAG_compile_unit
+  DW_CHECK_NEXT("  NULL");
   // Test that previous list was properly terminated and empty children.
   info.StartTag(dwarf::DW_TAG_compile_unit);
   info.EndTag();  // DW_TAG_compile_unit
 
-  // The abbrev table is just side product, but check it as well.
-  DW_CHECK("Abbrev Number: 3 (DW_TAG_compile_unit)");
-  DW_CHECK("Contents of the .debug_abbrev section:");
-  DW_CHECK("1      DW_TAG_compile_unit    [has children]");
-  DW_CHECK_NEXT("DW_AT_producer     DW_FORM_strp");
-  DW_CHECK_NEXT("DW_AT_low_pc       DW_FORM_addr");
-  DW_CHECK_NEXT("DW_AT_high_pc      DW_FORM_addr");
-  DW_CHECK("2      DW_TAG_subprogram    [no children]");
-  DW_CHECK_NEXT("DW_AT_name         DW_FORM_strp");
-  DW_CHECK_NEXT("DW_AT_low_pc       DW_FORM_addr");
-  DW_CHECK_NEXT("DW_AT_high_pc      DW_FORM_addr");
-  DW_CHECK("3      DW_TAG_compile_unit    [no children]");
-
   dwarf::WriteDebugInfoCU(/* debug_abbrev_offset= */ 0, info, &debug_info_data_);
 
-  CheckObjdumpOutput(is64bit, "-W");
+  CheckObjdumpOutput(is64bit, "-debug-info -debug-abbrev");
 }
 
 #endif  // ART_TARGET_ANDROID
diff --git a/compiler/debug/dwarf/dwarf_test.h b/compiler/debug/dwarf/dwarf_test.h
index e51f807..bad986a 100644
--- a/compiler/debug/dwarf/dwarf_test.h
+++ b/compiler/debug/dwarf/dwarf_test.h
@@ -86,8 +86,8 @@
 
     // Read the elf file back using objdump.
     std::vector<std::string> lines;
-    std::string cmd = GetAndroidHostToolsDir();
-    cmd = cmd + "objdump " + args + " " + file.GetFilename() + " 2>&1";
+    std::string cmd = GetAndroidTool("llvm-dwarfdump");
+    cmd = cmd + " " + args + " " + file.GetFilename() + " 2>&1";
     FILE* output = popen(cmd.data(), "r");
     char buffer[1024];
     const char* line;
@@ -96,12 +96,13 @@
         printf("%s", line);
       }
       if (line[0] != '\0' && line[0] != '\n') {
-        EXPECT_TRUE(strstr(line, "objdump: Error:") == nullptr) << line;
-        EXPECT_TRUE(strstr(line, "objdump: Warning:") == nullptr) << line;
+        EXPECT_TRUE(strstr(line, "error:") == nullptr) << line;
+        EXPECT_TRUE(strstr(line, "warning:") == nullptr) << line;
         std::string str(line);
         if (str.back() == '\n') {
           str.pop_back();
         }
+        std::replace(str.begin(), str.end(), '\t', ' ');
         lines.push_back(str);
       }
     }
@@ -121,38 +122,27 @@
   void CheckObjdumpOutput(bool is64bit, const char* args) {
     std::vector<std::string> actual_lines = Objdump(is64bit, args);
     auto actual_line = actual_lines.begin();
-    for (const ExpectedLine& expected_line : expected_lines_) {
-      const std::string& substring = expected_line.substring;
-      if (actual_line == actual_lines.end()) {
-        ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) <<
-            "Expected '" << substring << "'.\n" <<
-            "Seen end of output.";
-      } else if (expected_line.next) {
-        if (actual_line->find(substring) == std::string::npos) {
-          ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) <<
-            "Expected '" << substring << "'.\n" <<
-            "Seen '" << actual_line->data() << "'.";
-        } else {
-          // printf("Found '%s' in '%s'.\n", substring.data(), actual_line->data());
-        }
-        actual_line++;
+    bool failed = false;
+    for (const ExpectedLine& expected : expected_lines_) {
+      const std::string& substring = expected.substring;
+      auto it = std::find_if(actual_line, actual_lines.end(),
+          [&](const std::string& line) { return line.find(substring) != std::string::npos; });
+      if (it == actual_lines.end()) {
+        failed = true;
+        ADD_FAILURE_AT(expected.at_file, expected.at_line) << "'" << substring << "' not found.";
       } else {
-        bool found = false;
-        for (auto it = actual_line; it < actual_lines.end(); it++) {
-          if (it->find(substring) != std::string::npos) {
-            actual_line = it;
-            found = true;
-            break;
-          }
+        if (expected.next && it != actual_line) {
+          failed = true;
+          ADD_FAILURE_AT(expected.at_file, expected.at_line)
+              << "'" << substring << "' found, but not on the immediate next line as expected.";
         }
-        if (!found) {
-          ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) <<
-            "Expected '" << substring << "'.\n" <<
-            "Not found anywhere in the rest of the output.";
-        } else {
-          // printf("Found '%s' in '%s'.\n", substring.data(), actual_line->data());
-          actual_line++;
-        }
+        actual_line = ++it;
+      }
+    }
+    if (failed) {
+      LOG(ERROR) << "objdump output:";
+      for (const std::string& it : actual_lines) {
+        LOG(ERROR) << it;
       }
     }
   }
diff --git a/compiler/debug/elf_debug_frame_writer.h b/compiler/debug/elf_debug_frame_writer.h
index f41db07..094e887 100644
--- a/compiler/debug/elf_debug_frame_writer.h
+++ b/compiler/debug/elf_debug_frame_writer.h
@@ -150,8 +150,6 @@
 template<typename ElfTypes>
 void WriteCFISection(ElfBuilder<ElfTypes>* builder,
                      const ArrayRef<const MethodDebugInfo>& method_infos) {
-  typedef typename ElfTypes::Addr Elf_Addr;
-
   // The methods can be written in any order.
   // Let's therefore sort them in the lexicographical order of the opcodes.
   // This has no effect on its own. However, if the final .debug_frame section is
@@ -176,7 +174,8 @@
       });
 
   std::vector<uint32_t> binary_search_table;
-  if (kWriteDebugFrameHdr) {
+  bool binary_search_table_is_valid = kWriteDebugFrameHdr;
+  if (binary_search_table_is_valid) {
     binary_search_table.reserve(2 * sorted_method_infos.size());
   }
 
@@ -192,10 +191,13 @@
     for (const MethodDebugInfo* mi : sorted_method_infos) {
       DCHECK(!mi->deduped);
       DCHECK(!mi->cfi.empty());
-      const Elf_Addr code_address = mi->code_address +
+      uint64_t code_address = mi->code_address +
           (mi->is_code_address_text_relative ? builder->GetText()->GetAddress() : 0);
       if (kWriteDebugFrameHdr) {
-        binary_search_table.push_back(dchecked_integral_cast<uint32_t>(code_address));
+        // Defensively check that the code address really fits.
+        DCHECK_LE(code_address, std::numeric_limits<uint32_t>::max());
+        binary_search_table_is_valid &= code_address <= std::numeric_limits<uint32_t>::max();
+        binary_search_table.push_back(static_cast<uint32_t>(code_address));
         binary_search_table.push_back(cfi_section->GetPosition());
       }
       dwarf::WriteFDE(is64bit,
@@ -210,7 +212,7 @@
     cfi_section->End();
   }
 
-  if (kWriteDebugFrameHdr && method_infos.size() > kMinDebugFrameHdrEntries) {
+  if (binary_search_table_is_valid && method_infos.size() >= kMinDebugFrameHdrEntries) {
     std::sort(binary_search_table.begin(), binary_search_table.end());
 
     // Custom Android section. It is very similar to the official .eh_frame_hdr format.
@@ -225,7 +227,8 @@
     auto* header_section = builder->GetDebugFrameHdr();
     header_section->Start();
     header_section->WriteFully(header_buffer.data(), header_buffer.size());
-    header_section->WriteFully(binary_search_table.data(), binary_search_table.size());
+    header_section->WriteFully(binary_search_table.data(),
+                               binary_search_table.size() * sizeof(binary_search_table[0]));
     header_section->End();
   }
 }
diff --git a/compiler/debug/elf_symtab_writer.h b/compiler/debug/elf_symtab_writer.h
index 2ed3a4b..410f704 100644
--- a/compiler/debug/elf_symtab_writer.h
+++ b/compiler/debug/elf_symtab_writer.h
@@ -19,12 +19,14 @@
 
 #include <map>
 #include <unordered_set>
+#include <unordered_map>
 
 #include "base/utils.h"
 #include "debug/debug_info.h"
 #include "debug/method_debug_info.h"
-#include "dex/dex_file-inl.h"
 #include "dex/code_item_accessors.h"
+#include "dex/descriptors_names.h"
+#include "dex/dex_file-inl.h"
 #include "elf/elf_builder.h"
 
 namespace art {
@@ -40,10 +42,48 @@
 // Note that ARM's Streamline requires it to match function symbol.
 constexpr bool kGenerateArmMappingSymbol = true;
 
+// Create magic symbol to let libunwindstack know that symtab is sorted by address.
+constexpr bool kGenerateSortedSymbol = true;
+constexpr const char kSortedSymbolName[] = "$android.symtab.sorted";
+constexpr size_t kSortedSymbolMinCount = 100;  // Don't bother if the table is very small (JIT).
+
 // Magic name for .symtab symbols which enumerate dex files used
 // by this ELF file (currently mmapped inside the .dex section).
 constexpr const char* kDexFileSymbolName = "$dexfile";
 
+// Return common parts of method names; shared by all methods in the given set.
+// (e.g. "[DEDUPED] ?.<init>" or "com.android.icu.charset.CharsetEncoderICU.?")
+static void GetDedupedName(const std::vector<const MethodDebugInfo*>& methods, std::string* out) {
+  DCHECK(!methods.empty());
+  const MethodDebugInfo* first = methods.front();
+  auto is_same_class = [&first](const MethodDebugInfo* mi) {
+    DCHECK(mi->dex_file != nullptr);
+    return mi->dex_file == first->dex_file && mi->class_def_index == first->class_def_index;
+  };
+  auto is_same_method_name = [&first](const MethodDebugInfo* mi) {
+    return strcmp(mi->dex_file->GetMethodName(mi->dex_method_index),
+                  first->dex_file->GetMethodName(first->dex_method_index)) == 0;
+  };
+  bool all_same_class = std::all_of(methods.begin(), methods.end(), is_same_class);
+  bool all_same_method_name = std::all_of(methods.begin(), methods.end(), is_same_method_name);
+  *out = "[DEDUPED]";
+  if (all_same_class || all_same_method_name) {
+    *out += ' ';
+    if (all_same_class) {
+      auto& dex_class_def = first->dex_file->GetClassDef(first->class_def_index);
+      AppendPrettyDescriptor(first->dex_file->GetClassDescriptor(dex_class_def), &*out);
+    } else {
+      *out += '?';
+    }
+    *out += '.';
+    if (all_same_method_name) {
+      *out += first->dex_file->GetMethodName(first->dex_method_index);
+    } else {
+      *out += '?';
+    }
+  }
+}
+
 template <typename ElfTypes>
 static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
                               bool mini_debug_info,
@@ -71,11 +111,24 @@
     }
   }
 
+  // Create list of deduped methods per function address.
+  // We have to do it separately since the first method does not have the deduped flag.
+  std::unordered_map<uint64_t, std::vector<const MethodDebugInfo*>> deduped_methods;
+  for (const MethodDebugInfo& info : debug_info.compiled_methods) {
+    if (deduped_addresses.find(info.code_address) != deduped_addresses.end()) {
+      deduped_methods[info.code_address].push_back(&info);
+    }
+  }
+
   strtab->Start();
-  strtab->Write("");  // strtab should start with empty string.
+  // Generate marker to annotate the symbol table as sorted (guaranteed by the ElfBuilder).
+  // Note that LOCAL symbols are sorted before GLOBAL ones, so don't mix the two types.
+  if (kGenerateSortedSymbol && debug_info.compiled_methods.size() >= kSortedSymbolMinCount) {
+    symtab->Add(strtab->Write(kSortedSymbolName), nullptr, 0, 0, STB_GLOBAL, STT_NOTYPE);
+  }
   // Generate ARM mapping symbols. ELF local symbols must be added first.
   if (mapping_symbol_address != std::numeric_limits<uint64_t>::max()) {
-    symtab->Add(strtab->Write("$t"), text, mapping_symbol_address, 0, STB_LOCAL, STT_NOTYPE);
+    symtab->Add(strtab->Write("$t"), text, mapping_symbol_address, 0, STB_GLOBAL, STT_NOTYPE);
   }
   // Add symbols for compiled methods.
   for (const MethodDebugInfo& info : debug_info.compiled_methods) {
@@ -89,7 +142,10 @@
       DCHECK(info.dex_file != nullptr);
       std::string name = info.dex_file->PrettyMethod(info.dex_method_index, !mini_debug_info);
       if (deduped_addresses.find(info.code_address) != deduped_addresses.end()) {
-        name += " [DEDUPED]";
+        // Create method name common to all the deduped methods if possible.
+        // Around half of the time, there is either common class or method name.
+        // NB: We used to return one method at random with tag, but developers found it confusing.
+        GetDedupedName(deduped_methods[info.code_address], &name);
       }
       name_offset = strtab->Write(name);
     }
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc
index e7a3817..6241ff3 100644
--- a/compiler/dex/verification_results.cc
+++ b/compiler/dex/verification_results.cc
@@ -82,14 +82,6 @@
   } else {
     // TODO: Investigate why are we doing the work again for this method and try to avoid it.
     LOG(WARNING) << "Method processed more than once: " << ref.PrettyMethod();
-    if (!Runtime::Current()->UseJitCompilation()) {
-      if (kIsDebugBuild) {
-        auto ex_set = existing->GetSafeCastSet();
-        auto ve_set = verified_method->GetSafeCastSet();
-        CHECK_EQ(ex_set == nullptr, ve_set == nullptr);
-        CHECK((ex_set == nullptr) || (ex_set->size() == ve_set->size()));
-      }
-    }
     // Let the unique_ptr delete the new verified method since there was already an existing one
     // registered. It is unsafe to replace the existing one since the JIT may be using it to
     // generate a native GC map.
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index 172ec6b..04f7215 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -43,69 +43,7 @@
       new VerifiedMethod(method_verifier->GetEncounteredFailureTypes(),
                          method_verifier->HasInstructionThatWillThrow()));
 
-  if (method_verifier->HasCheckCasts()) {
-    verified_method->GenerateSafeCastSet(method_verifier);
-  }
-
   return verified_method.release();
 }
 
-bool VerifiedMethod::IsSafeCast(uint32_t pc) const {
-  if (safe_cast_set_ == nullptr) {
-    return false;
-  }
-  return std::binary_search(safe_cast_set_->begin(), safe_cast_set_->end(), pc);
-}
-
-void VerifiedMethod::GenerateSafeCastSet(verifier::MethodVerifier* method_verifier) {
-  /*
-   * Walks over the method code and adds any cast instructions in which
-   * the type cast is implicit to a set, which is used in the code generation
-   * to elide these casts.
-   */
-  if (method_verifier->HasFailures()) {
-    return;
-  }
-  for (const DexInstructionPcPair& pair : method_verifier->CodeItem()) {
-    const Instruction& inst = pair.Inst();
-    const Instruction::Code code = inst.Opcode();
-    if (code == Instruction::CHECK_CAST) {
-      const uint32_t dex_pc = pair.DexPc();
-      if (!method_verifier->GetInstructionFlags(dex_pc).IsVisited()) {
-        // Do not attempt to quicken this instruction, it's unreachable anyway.
-        continue;
-      }
-      const verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
-      DCHECK(line != nullptr) << "Did not have line for dex pc 0x" << std::hex << dex_pc;
-      const verifier::RegType& reg_type(line->GetRegisterType(method_verifier,
-                                                              inst.VRegA_21c()));
-      const verifier::RegType& cast_type =
-          method_verifier->ResolveCheckedClass(dex::TypeIndex(inst.VRegB_21c()));
-      // Pass null for the method verifier to not record the VerifierDeps dependency
-      // if the types are not assignable.
-      if (cast_type.IsStrictlyAssignableFrom(reg_type, /* verifier= */ nullptr)) {
-        // The types are assignable, we record that dependency in the VerifierDeps so
-        // that if this changes after OTA, we will re-verify again.
-        // We check if reg_type has a class, as the verifier may have inferred it's
-        // 'null'.
-        if (reg_type.HasClass()) {
-          DCHECK(cast_type.HasClass());
-          verifier::VerifierDeps::MaybeRecordAssignability(method_verifier->GetDexFile(),
-                                                           cast_type.GetClass(),
-                                                           reg_type.GetClass(),
-                                                           /* is_strict= */ true,
-                                                           /* is_assignable= */ true);
-        }
-        if (safe_cast_set_ == nullptr) {
-          safe_cast_set_.reset(new SafeCastSet());
-        }
-        // Verify ordering for push_back() to the sorted vector.
-        DCHECK(safe_cast_set_->empty() || safe_cast_set_->back() < dex_pc);
-        safe_cast_set_->push_back(dex_pc);
-      }
-    }
-  }
-  DCHECK(safe_cast_set_ == nullptr || !safe_cast_set_->empty());
-}
-
 }  // namespace art
diff --git a/compiler/dex/verified_method.h b/compiler/dex/verified_method.h
index f04392d..f100f78 100644
--- a/compiler/dex/verified_method.h
+++ b/compiler/dex/verified_method.h
@@ -34,23 +34,10 @@
  public:
   VerifiedMethod(uint32_t encountered_error_types, bool has_runtime_throw);
 
-  // Cast elision set type.
-  // Since we're adding the dex PCs to the set in increasing order, a sorted vector
-  // is better for performance (not just memory usage), especially for large sets.
-  typedef std::vector<uint32_t> SafeCastSet;
-
   static const VerifiedMethod* Create(verifier::MethodVerifier* method_verifier)
       REQUIRES_SHARED(Locks::mutator_lock_);
   ~VerifiedMethod() = default;
 
-  const SafeCastSet* GetSafeCastSet() const {
-    return safe_cast_set_.get();
-  }
-
-  // Returns true if the cast can statically be verified to be redundant
-  // by using the check-cast elision peephole optimization in the verifier.
-  bool IsSafeCast(uint32_t pc) const;
-
   // Returns true if there were any errors during verification.
   bool HasVerificationFailures() const {
     return encountered_error_types_ != 0;
@@ -65,12 +52,6 @@
   }
 
  private:
-  // Generate safe case set into safe_cast_set_.
-  void GenerateSafeCastSet(verifier::MethodVerifier* method_verifier)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  std::unique_ptr<SafeCastSet> safe_cast_set_;
-
   const uint32_t encountered_error_types_;
   const bool has_runtime_throw_;
 };
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index cde6ae9..a5805f9 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -50,8 +50,9 @@
       dex_files_for_oat_file_(),
       image_classes_(),
       verification_results_(nullptr),
+      compiler_type_(CompilerType::kAotCompiler),
       image_type_(ImageType::kNone),
-      compiling_with_core_image_(false),
+      compile_art_test_(false),
       baseline_(false),
       debuggable_(false),
       generate_debug_info_(kDefaultGenerateDebugInfo),
@@ -73,6 +74,8 @@
       dump_cfg_file_name_(""),
       dump_cfg_append_(false),
       force_determinism_(false),
+      check_linkage_conditions_(false),
+      crash_on_linkage_violation_(false),
       deduplicate_code_(true),
       count_hotness_in_compiled_code_(false),
       resolve_startup_const_strings_(false),
@@ -184,24 +187,4 @@
   return is_system_class;
 }
 
-bool CompilerOptions::IsCoreImageFilename(const std::string& boot_image_filename) {
-  std::string_view filename(boot_image_filename);
-  size_t colon_pos = filename.find(':');
-  if (colon_pos != std::string_view::npos) {
-    filename = filename.substr(0u, colon_pos);
-  }
-  // Look for "core.art" or "core-*.art".
-  if (EndsWith(filename, "core.art")) {
-    return true;
-  }
-  if (!EndsWith(filename, ".art")) {
-    return false;
-  }
-  size_t slash_pos = filename.rfind('/');
-  if (slash_pos == std::string::npos) {
-    return StartsWith(filename, "core-");
-  }
-  return filename.compare(slash_pos + 1, 5u, "core-") == 0;
-}
-
 }  // namespace art
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 79ba1c2..da75d37 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -22,11 +22,11 @@
 #include <string>
 #include <vector>
 
+#include "base/compiler_filter.h"
 #include "base/globals.h"
 #include "base/hash_set.h"
 #include "base/macros.h"
 #include "base/utils.h"
-#include "compiler_filter.h"
 #include "optimizing/register_allocator.h"
 
 namespace art {
@@ -65,10 +65,17 @@
   static const size_t kDefaultNumDexMethodsThreshold = 900;
   static constexpr double kDefaultTopKProfileThreshold = 90.0;
   static const bool kDefaultGenerateDebugInfo = false;
-  static const bool kDefaultGenerateMiniDebugInfo = false;
+  static const bool kDefaultGenerateMiniDebugInfo = true;
   static const size_t kDefaultInlineMaxCodeUnits = 32;
   static constexpr size_t kUnsetInlineMaxCodeUnits = -1;
 
+  enum class CompilerType : uint8_t {
+    kAotCompiler,             // AOT compiler.
+    kJitCompiler,             // Normal JIT compiler.
+    kSharedCodeJitCompiler,   // Zygote JIT producing code in the shared region area, putting
+                              // restrictions on, for example, how literals are being generated.
+  };
+
   enum class ImageType : uint8_t {
     kNone,                    // JIT or AOT app compilation producing only an oat file but no image.
     kBootImage,               // Creating boot image.
@@ -95,10 +102,6 @@
     return CompilerFilter::IsJniCompilationEnabled(compiler_filter_);
   }
 
-  bool IsQuickeningCompilationEnabled() const {
-    return CompilerFilter::IsQuickeningCompilationEnabled(compiler_filter_);
-  }
-
   bool IsVerificationEnabled() const {
     return CompilerFilter::IsVerificationEnabled(compiler_filter_);
   }
@@ -191,6 +194,19 @@
     return implicit_so_checks_;
   }
 
+  bool IsAotCompiler() const {
+    return compiler_type_ == CompilerType::kAotCompiler;
+  }
+
+  bool IsJitCompiler() const {
+    return compiler_type_ == CompilerType::kJitCompiler ||
+           compiler_type_ == CompilerType::kSharedCodeJitCompiler;
+  }
+
+  bool IsJitCompilerForSharedCode() const {
+    return compiler_type_ == CompilerType::kSharedCodeJitCompiler;
+  }
+
   bool GetImplicitSuspendChecks() const {
     return implicit_suspend_checks_;
   }
@@ -218,11 +234,10 @@
     return image_type_ == ImageType::kAppImage;
   }
 
-  // Returns whether we are compiling against a "core" image, which
-  // is an indicative we are running tests. The compiler will use that
-  // information for checking invariants.
-  bool CompilingWithCoreImage() const {
-    return compiling_with_core_image_;
+  // Returns whether we are running ART tests.
+  // The compiler will use that information for checking invariants.
+  bool CompileArtTest() const {
+    return compile_art_test_;
   }
 
   // Should the code be compiled as position independent?
@@ -311,6 +326,14 @@
     return force_determinism_;
   }
 
+  bool IsCheckLinkageConditions() const {
+    return check_linkage_conditions_;
+  }
+
+  bool IsCrashOnLinkageViolation() const {
+    return crash_on_linkage_violation_;
+  }
+
   bool DeduplicateCode() const {
     return deduplicate_code_;
   }
@@ -359,10 +382,6 @@
     return initialize_app_image_classes_;
   }
 
-  // Is `boot_image_filename` the name of a core image (small boot
-  // image used for ART testing only)?
-  static bool IsCoreImageFilename(const std::string& boot_image_filename);
-
  private:
   bool ParseDumpInitFailures(const std::string& option, std::string* error_msg);
   bool ParseRegisterAllocationStrategy(const std::string& option, std::string* error_msg);
@@ -391,8 +410,9 @@
   // Results of AOT verification.
   const VerificationResults* verification_results_;
 
+  CompilerType compiler_type_;
   ImageType image_type_;
-  bool compiling_with_core_image_;
+  bool compile_art_test_;
   bool baseline_;
   bool debuggable_;
   bool generate_debug_info_;
@@ -431,6 +451,13 @@
   // outcomes.
   bool force_determinism_;
 
+  // Whether the compiler should check for violation of the conditions required to perform AOT
+  // "linkage".
+  bool check_linkage_conditions_;
+  // Whether the compiler should crash when encountering a violation of one of
+  // the conditions required to perform AOT "linkage".
+  bool crash_on_linkage_violation_;
+
   // Whether code should be deduplicated.
   bool deduplicate_code_;
 
@@ -465,7 +492,7 @@
   friend class Dex2Oat;
   friend class DexToDexDecompilerTest;
   friend class CommonCompilerDriverTest;
-  friend class CommonCompilerTest;
+  friend class CommonCompilerTestImpl;
   friend class jit::JitCompiler;
   friend class verifier::VerifierDepsTest;
   friend class linker::Arm64RelativePatcherTest;
diff --git a/compiler/driver/compiler_options_map-inl.h b/compiler/driver/compiler_options_map-inl.h
index e8a425d..fcbc0f2 100644
--- a/compiler/driver/compiler_options_map-inl.h
+++ b/compiler/driver/compiler_options_map-inl.h
@@ -31,18 +31,31 @@
 
 namespace art {
 
+template <>
+struct CmdlineType<CompilerFilter::Filter> : CmdlineTypeParser<CompilerFilter::Filter> {
+  Result Parse(const std::string& option) {
+    CompilerFilter::Filter compiler_filter;
+    if (!CompilerFilter::ParseCompilerFilter(option.c_str(), &compiler_filter)) {
+      return Result::Failure(
+          android::base::StringPrintf("Unknown --compiler-filter value %s", option.c_str()));
+    }
+    return Result::Success(compiler_filter);
+  }
+
+  static const char* Name() {
+    return "CompilerFilter";
+  }
+  static const char* DescribeType() {
+    return CompilerFilter::DescribeOptions();
+  }
+};
+
 template <class Base>
 inline bool ReadCompilerOptions(Base& map, CompilerOptions* options, std::string* error_msg) {
   if (map.Exists(Base::CompilerFilter)) {
-    CompilerFilter::Filter compiler_filter;
-    if (!CompilerFilter::ParseCompilerFilter(map.Get(Base::CompilerFilter)->c_str(),
-                                             &compiler_filter)) {
-      *error_msg = android::base::StringPrintf("Unknown --compiler-filter value %s",
-                                               map.Get(Base::CompilerFilter)->c_str());
-      return false;
-    }
-    options->SetCompilerFilter(compiler_filter);
+    options->SetCompilerFilter(*map.Get(Base::CompilerFilter));
   }
+  map.AssignIfExists(Base::CompileArtTest, &options->compile_art_test_);
   map.AssignIfExists(Base::HugeMethodMaxThreshold, &options->huge_method_threshold_);
   map.AssignIfExists(Base::LargeMethodMaxThreshold, &options->large_method_threshold_);
   map.AssignIfExists(Base::NumDexMethodsThreshold, &options->num_dex_methods_threshold_);
@@ -107,36 +120,59 @@
 inline void AddCompilerOptionsArgumentParserOptions(Builder& b) {
   b.
       Define("--compiler-filter=_")
-          .template WithType<std::string>()
+          .template WithType<CompilerFilter::Filter>()
+          .WithHelp("Select compiler filter\n"
+                    "Default: speed-profile if profile provided, speed otherwise")
           .IntoKey(Map::CompilerFilter)
 
+      .Define({"--compile-art-test", "--no-compile-art-test"})
+          .WithValues({true, false})
+          .IntoKey(Map::CompileArtTest)
       .Define("--huge-method-max=_")
           .template WithType<unsigned int>()
+          .WithHelp("threshold size for a huge method for compiler filter tuning.")
           .IntoKey(Map::HugeMethodMaxThreshold)
       .Define("--large-method-max=_")
           .template WithType<unsigned int>()
+          .WithHelp("threshold size for a large method for compiler filter tuning.")
           .IntoKey(Map::LargeMethodMaxThreshold)
       .Define("--num-dex-methods=_")
           .template WithType<unsigned int>()
+          .WithHelp("threshold size for a small dex file for compiler filter tuning. If the input\n"
+                    "has fewer than this many methods and the filter is not interpret-only or\n"
+                    "verify-none or verify-at-runtime, overrides the filter to use speed")
           .IntoKey(Map::NumDexMethodsThreshold)
       .Define("--inline-max-code-units=_")
           .template WithType<unsigned int>()
+          .WithHelp("the maximum code units that a methodcan have to be considered for inlining.\n"
+                    "A zero value will disable inlining. Honored only by Optimizing. Has priority\n"
+                    "over the --compiler-filter option. Intended for development/experimental use.")
           .IntoKey(Map::InlineMaxCodeUnitsThreshold)
 
       .Define({"--generate-debug-info", "-g", "--no-generate-debug-info"})
           .WithValues({true, true, false})
+          .WithHelp("Generate (or don't generate) debug information for native debugging, such as\n"
+                    "stack unwinding information, ELF symbols and dwarf sections. If used without\n"
+                    "--debuggable it will be best effort only. Does not affect the generated\n"
+                    "code. Disabled by default.")
           .IntoKey(Map::GenerateDebugInfo)
       .Define({"--generate-mini-debug-info", "--no-generate-mini-debug-info"})
           .WithValues({true, false})
+          .WithHelp("Whether or not to generate minimal amount of LZMA-compressed debug\n"
+                    "information necessary to print backtraces (disabled by default).")
           .IntoKey(Map::GenerateMiniDebugInfo)
 
       .Define({"--generate-build-id", "--no-generate-build-id"})
           .WithValues({true, false})
+          .WithHelp("Generate GNU-compatible linker build ID ELF section with SHA-1 of the file\n"
+                    "content (and thus stable across identical builds)")
           .IntoKey(Map::GenerateBuildID)
 
       .Define({"--deduplicate-code=_"})
           .template WithType<bool>()
           .WithValueMap({{"false", false}, {"true", true}})
+          .WithHelp("enable|disable code deduplication. Deduplicated code will have an arbitrary\n"
+                    "symbol tagged with [DEDUPED].")
           .IntoKey(Map::DeduplicateCode)
 
       .Define({"--count-hotness-in-compiled-code"})
@@ -149,18 +185,24 @@
           .IntoKey(Map::CheckProfiledMethods)
 
       .Define({"--dump-timings"})
+          .WithHelp("Display a breakdown of where time was spent.")
           .IntoKey(Map::DumpTimings)
 
       .Define({"--dump-pass-timings"})
+          .WithHelp("Display a breakdown time spent in optimization passes for each compiled"
+                    " method.")
           .IntoKey(Map::DumpPassTimings)
 
       .Define({"--dump-stats"})
+          .WithHelp("Display overall compilation statistics.")
           .IntoKey(Map::DumpStats)
 
       .Define("--debuggable")
+          .WithHelp("Produce code debuggable with a java-debugger.")
           .IntoKey(Map::Debuggable)
 
       .Define("--baseline")
+          .WithHelp("Produce code using the baseline compilation")
           .IntoKey(Map::Baseline)
 
       .Define("--top-k-profile-threshold=_")
@@ -180,8 +222,12 @@
 
       .Define("--dump-cfg=_")
           .template WithType<std::string>()
+          .WithHelp("Dump control-flow graphs (CFGs) to specified file.")
           .IntoKey(Map::DumpCFG)
       .Define("--dump-cfg-append")
+          .WithHelp("when dumping CFGs to an existing file, append new CFG data to existing data\n"
+                    "(instead of overwriting existing data with new data, which is the default\n"
+                    "behavior). This option is only meaningful when used with --dump-cfg.")
           .IntoKey(Map::DumpCFGAppend)
 
       .Define("--register-allocation-strategy=_")
@@ -191,6 +237,8 @@
       .Define("--resolve-startup-const-strings=_")
           .template WithType<bool>()
           .WithValueMap({{"false", false}, {"true", true}})
+          .WithHelp("If true, the compiler eagerly resolves strings referenced from const-string\n"
+                    "of startup methods.")
           .IntoKey(Map::ResolveStartupConstStrings)
 
       .Define("--initialize-app-image-classes=_")
@@ -200,10 +248,13 @@
 
       .Define("--verbose-methods=_")
           .template WithType<ParseStringList<','>>()
+          .WithHelp("Restrict the dumped CFG data to methods whose name is listed.\n"
+                    "Eg: --verbose-methods=toString,hashCode")
           .IntoKey(Map::VerboseMethods)
 
       .Define("--max-image-block-size=_")
           .template WithType<unsigned int>()
+          .WithHelp("Maximum solid block size for compressed images.")
           .IntoKey(Map::MaxImageBlockSize);
 }
 
diff --git a/compiler/driver/compiler_options_map.def b/compiler/driver/compiler_options_map.def
index df06bd8..b1398c9 100644
--- a/compiler/driver/compiler_options_map.def
+++ b/compiler/driver/compiler_options_map.def
@@ -36,7 +36,8 @@
 // Parse-able keys from the command line.
 
 // TODO: Add type parser.
-COMPILER_OPTIONS_KEY (std::string,                 CompilerFilter)
+COMPILER_OPTIONS_KEY (CompilerFilter::Filter,      CompilerFilter)
+COMPILER_OPTIONS_KEY (bool,                        CompileArtTest)
 COMPILER_OPTIONS_KEY (Unit,                        PIC)
 COMPILER_OPTIONS_KEY (unsigned int,                HugeMethodMaxThreshold)
 COMPILER_OPTIONS_KEY (unsigned int,                LargeMethodMaxThreshold)
diff --git a/compiler/driver/compiler_options_map.h b/compiler/driver/compiler_options_map.h
index af212d6..7e2f846 100644
--- a/compiler/driver/compiler_options_map.h
+++ b/compiler/driver/compiler_options_map.h
@@ -20,6 +20,7 @@
 #include <string>
 #include <vector>
 
+#include "base/compiler_filter.h"
 #include "base/variant_map.h"
 #include "cmdline_types.h"
 
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
index 633e124..495398b 100644
--- a/compiler/exception_test.cc
+++ b/compiler/exception_test.cc
@@ -17,6 +17,7 @@
 #include <memory>
 #include <type_traits>
 
+#include "art_method-inl.h"
 #include "base/arena_allocator.h"
 #include "base/callee_save_type.h"
 #include "base/enums.h"
@@ -80,7 +81,7 @@
     stack_maps.BeginMethod(4 * sizeof(void*), 0u, 0u, 0u);
     stack_maps.BeginStackMapEntry(kDexPc, native_pc_offset);
     stack_maps.EndStackMapEntry();
-    stack_maps.EndMethod();
+    stack_maps.EndMethod(code_size);
     ScopedArenaVector<uint8_t> stack_map = stack_maps.Encode();
 
     const size_t stack_maps_size = stack_map.size();
@@ -93,7 +94,7 @@
       AlignUp(&fake_header_code_and_maps_[stack_maps_size + header_size], code_alignment);
 
     memcpy(&fake_header_code_and_maps_[0], stack_map.data(), stack_maps_size);
-    OatQuickMethodHeader method_header(code_ptr - fake_header_code_and_maps_.data(), code_size);
+    OatQuickMethodHeader method_header(code_ptr - fake_header_code_and_maps_.data());
     static_assert(std::is_trivially_copyable<OatQuickMethodHeader>::value, "Cannot use memcpy");
     memcpy(code_ptr - header_size, &method_header, header_size);
     memcpy(code_ptr, fake_code_.data(), fake_code_.size());
@@ -128,7 +129,7 @@
 
 TEST_F(ExceptionTest, FindCatchHandler) {
   ScopedObjectAccess soa(Thread::Current());
-  CodeItemDataAccessor accessor(*dex_, dex_->GetCodeItem(method_f_->GetCodeItemOffset()));
+  CodeItemDataAccessor accessor(*dex_, method_f_->GetCodeItem());
 
   ASSERT_TRUE(accessor.HasCodeItem());
 
@@ -213,7 +214,7 @@
   // Set up thread to appear as if we called out of method_g_ at given pc dex.
   thread->SetTopOfStack(reinterpret_cast<ArtMethod**>(&fake_stack[0]));
 
-  jobject internal = thread->CreateInternalStackTrace<false>(soa);
+  jobject internal = thread->CreateInternalStackTrace(soa);
   ASSERT_TRUE(internal != nullptr);
   jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(soa, internal);
   ASSERT_TRUE(ste_array != nullptr);
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 0f12457..f819cd8 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -55,6 +55,10 @@
       UNREACHABLE();
     }
   }
+  // Set to appropriate JIT compiler type.
+  compiler_options_->compiler_type_ = runtime->IsZygote()
+      ? CompilerOptions::CompilerType::kSharedCodeJitCompiler
+      : CompilerOptions::CompilerType::kJitCompiler;
   // JIT is never PIC, no matter what the runtime compiler options specify.
   compiler_options_->SetNonPic();
 
@@ -106,8 +110,6 @@
     instruction_set_features = InstructionSetFeatures::FromCppDefines();
   }
   compiler_options_->instruction_set_features_ = std::move(instruction_set_features);
-  compiler_options_->compiling_with_core_image_ =
-      CompilerOptions::IsCoreImageFilename(runtime->GetImageLocation());
 
   if (compiler_options_->GetGenerateDebugInfo()) {
     jit_logger_.reset(new JitLogger());
@@ -163,10 +165,10 @@
 }
 
 bool JitCompiler::CompileMethod(
-    Thread* self, JitMemoryRegion* region, ArtMethod* method, bool baseline, bool osr) {
+    Thread* self, JitMemoryRegion* region, ArtMethod* method, CompilationKind compilation_kind) {
   SCOPED_TRACE << "JIT compiling "
                << method->PrettyMethod()
-               << " (baseline=" << baseline << ", osr=" << osr << ")";
+               << " (kind=" << compilation_kind << ")";
 
   DCHECK(!method->IsProxyMethod());
   DCHECK(method->GetDeclaringClass()->IsResolved());
@@ -179,16 +181,20 @@
   // Do the compilation.
   bool success = false;
   {
-    TimingLogger::ScopedTiming t2("Compiling", &logger);
+    TimingLogger::ScopedTiming t2(compilation_kind == CompilationKind::kOsr
+                                      ? "Compiling OSR"
+                                      : compilation_kind == CompilationKind::kOptimized
+                                          ? "Compiling optimized"
+                                          : "Compiling baseline",
+                                  &logger);
     JitCodeCache* const code_cache = runtime->GetJit()->GetCodeCache();
-    uint64_t start_ns = NanoTime();
+    metrics::AutoTimer timer{runtime->GetMetrics()->JitMethodCompileTotalTime()};
     success = compiler_->JitCompile(
-        self, code_cache, region, method, baseline, osr, jit_logger_.get());
-    uint64_t duration_ns = NanoTime() - start_ns;
-    VLOG(jit) << "Compilation of "
-              << method->PrettyMethod()
-              << " took "
-              << PrettyDuration(duration_ns);
+        self, code_cache, region, method, compilation_kind, jit_logger_.get());
+    uint64_t duration_us = timer.Stop();
+    VLOG(jit) << "Compilation of " << method->PrettyMethod() << " took "
+              << PrettyDuration(UsToNs(duration_us));
+    runtime->GetMetrics()->JitMethodCompileCount()->AddOne();
   }
 
   // Trim maps to reduce memory usage.
diff --git a/compiler/jit/jit_compiler.h b/compiler/jit/jit_compiler.h
index 09de1f8..9dd84f0 100644
--- a/compiler/jit/jit_compiler.h
+++ b/compiler/jit/jit_compiler.h
@@ -18,6 +18,7 @@
 #define ART_COMPILER_JIT_JIT_COMPILER_H_
 
 #include "base/mutex.h"
+#include "compilation_kind.h"
 
 #include "jit/jit.h"
 
@@ -40,7 +41,7 @@
 
   // Compilation entrypoint. Returns whether the compilation succeeded.
   bool CompileMethod(
-      Thread* self, JitMemoryRegion* region, ArtMethod* method, bool baseline, bool osr)
+      Thread* self, JitMemoryRegion* region, ArtMethod* method, CompilationKind kind)
       REQUIRES_SHARED(Locks::mutator_lock_) override;
 
   const CompilerOptions& GetCompilerOptions() const {
diff --git a/compiler/jni/jni_cfi_test.cc b/compiler/jni/jni_cfi_test.cc
index cec94c9..7980e18 100644
--- a/compiler/jni/jni_cfi_test.cc
+++ b/compiler/jni/jni_cfi_test.cc
@@ -82,8 +82,15 @@
     std::unique_ptr<JNIMacroAssembler<kPointerSize>> jni_asm(
         JNIMacroAssembler<kPointerSize>::Create(&allocator, isa));
     jni_asm->cfi().SetEnabled(true);
-    jni_asm->BuildFrame(frame_size, mr_conv->MethodRegister(),
-                        callee_save_regs, mr_conv->EntrySpills());
+    jni_asm->BuildFrame(frame_size, mr_conv->MethodRegister(), callee_save_regs);
+    // Spill arguments.
+    mr_conv->ResetIterator(FrameOffset(frame_size));
+    for (; mr_conv->HasNext(); mr_conv->Next()) {
+      if (mr_conv->IsCurrentParamInRegister()) {
+        size_t size = mr_conv->IsCurrentParamALongOrDouble() ? 8u : 4u;
+        jni_asm->Store(mr_conv->CurrentParamStackOffset(), mr_conv->CurrentParamRegister(), size);
+      }
+    }
     jni_asm->IncreaseFrameSize(32);
     jni_asm->DecreaseFrameSize(32);
     jni_asm->RemoveFrame(frame_size, callee_save_regs, /* may_suspend= */ true);
diff --git a/compiler/jni/jni_cfi_test_expected.inc b/compiler/jni/jni_cfi_test_expected.inc
index 489ae00..20dc399 100644
--- a/compiler/jni/jni_cfi_test_expected.inc
+++ b/compiler/jni/jni_cfi_test_expected.inc
@@ -1,8 +1,9 @@
+// TODO These arrays should be generated automatically or have instructions for re-creation.
 static constexpr uint8_t expected_asm_kThumb2[] = {
-    0x2D, 0xE9, 0xE0, 0x4D, 0x2D, 0xED, 0x10, 0x8A, 0x89, 0xB0, 0x00, 0x90,
-    0x21, 0x91, 0x8D, 0xED, 0x22, 0x0A, 0x23, 0x92, 0x24, 0x93, 0x88, 0xB0,
-    0x08, 0xB0, 0x09, 0xB0, 0xBD, 0xEC, 0x10, 0x8A, 0xBD, 0xE8, 0xE0, 0x4D,
-    0xD9, 0xF8, 0x34, 0x80, 0x70, 0x47,
+    0x2D, 0xE9, 0xE0, 0x4D, 0x2D, 0xED, 0x10, 0x8A, 0x85, 0xB0, 0x00, 0x90,
+    0x1D, 0x91, 0x8D, 0xED, 0x1E, 0x0A, 0x1F, 0x92, 0x20, 0x93, 0x88, 0xB0,
+    0x08, 0xB0, 0x05, 0xB0, 0xBD, 0xEC, 0x10, 0x8A, 0xBD, 0xE8, 0xE0, 0x4D,
+    0xD9, 0xF8, 0x30, 0x80, 0x70, 0x47,
 };
 static constexpr uint8_t expected_cfi_kThumb2[] = {
     0x44, 0x0E, 0x1C, 0x85, 0x07, 0x86, 0x06, 0x87, 0x05, 0x88, 0x04, 0x8A,
@@ -10,12 +11,12 @@
     0x51, 0x16, 0x05, 0x52, 0x15, 0x05, 0x53, 0x14, 0x05, 0x54, 0x13, 0x05,
     0x55, 0x12, 0x05, 0x56, 0x11, 0x05, 0x57, 0x10, 0x05, 0x58, 0x0F, 0x05,
     0x59, 0x0E, 0x05, 0x5A, 0x0D, 0x05, 0x5B, 0x0C, 0x05, 0x5C, 0x0B, 0x05,
-    0x5D, 0x0A, 0x05, 0x5E, 0x09, 0x05, 0x5F, 0x08, 0x42, 0x0E, 0x80, 0x01,
-    0x4E, 0x0E, 0xA0, 0x01, 0x42, 0x0E, 0x80, 0x01, 0x0A, 0x42, 0x0E, 0x5C,
-    0x44, 0x0E, 0x1C, 0x06, 0x50, 0x06, 0x51, 0x06, 0x52, 0x06, 0x53, 0x06,
-    0x54, 0x06, 0x55, 0x06, 0x56, 0x06, 0x57, 0x06, 0x58, 0x06, 0x59, 0x06,
-    0x5A, 0x06, 0x5B, 0x06, 0x5C, 0x06, 0x5D, 0x06, 0x5E, 0x06, 0x5F, 0x4A,
-    0x0B, 0x0E, 0x80, 0x01,
+    0x5D, 0x0A, 0x05, 0x5E, 0x09, 0x05, 0x5F, 0x08, 0x42, 0x0E, 0x70, 0x4E,
+    0x0E, 0x90, 0x01, 0x42, 0x0E, 0x70, 0x0A, 0x42, 0x0E, 0x5C, 0x44, 0x0E,
+    0x1C, 0x06, 0x50, 0x06, 0x51, 0x06, 0x52, 0x06, 0x53, 0x06, 0x54, 0x06,
+    0x55, 0x06, 0x56, 0x06, 0x57, 0x06, 0x58, 0x06, 0x59, 0x06, 0x5A, 0x06,
+    0x5B, 0x06, 0x5C, 0x06, 0x5D, 0x06, 0x5E, 0x06, 0x5F, 0x44, 0x0E, 0x00,
+    0xC5, 0xC6, 0xC7, 0xC8, 0xCA, 0xCB, 0xCE, 0x46, 0x0B, 0x0E, 0x70,
 };
 // 0x00000000: push {r5,r6,r7,r8,r10,r11,lr}
 // 0x00000004: .cfi_def_cfa_offset: 28
@@ -44,19 +45,19 @@
 // 0x00000008: .cfi_offset_extended: r93 at cfa-40
 // 0x00000008: .cfi_offset_extended: r94 at cfa-36
 // 0x00000008: .cfi_offset_extended: r95 at cfa-32
-// 0x00000008: sub sp, #36
-// 0x0000000a: .cfi_def_cfa_offset: 128
+// 0x00000008: sub sp, #20
+// 0x0000000a: .cfi_def_cfa_offset: 112
 // 0x0000000a: str r0, [sp]
-// 0x0000000c: str r1, [sp, #132]
-// 0x0000000e: vstr s0, [sp, #136]
-// 0x00000012: str r2, [sp, #140]
-// 0x00000014: str r3, [sp, #144]
+// 0x0000000c: str r1, [sp, #116]
+// 0x0000000e: vstr s0, [sp, #120]
+// 0x00000012: str r2, [sp, #124]
+// 0x00000014: str r3, [sp, #128]
 // 0x00000016: sub sp, #32
-// 0x00000018: .cfi_def_cfa_offset: 160
+// 0x00000018: .cfi_def_cfa_offset: 144
 // 0x00000018: add sp, #32
-// 0x0000001a: .cfi_def_cfa_offset: 128
+// 0x0000000a: .cfi_def_cfa_offset: 112
 // 0x0000001a: .cfi_remember_state
-// 0x0000001a: add sp, #36
+// 0x0000001a: add sp, #20
 // 0x0000001c: .cfi_def_cfa_offset: 92
 // 0x0000001c: vpop {s16-s31}
 // 0x00000020: .cfi_def_cfa_offset: 28
@@ -77,126 +78,134 @@
 // 0x00000020: .cfi_restore_extended: r94
 // 0x00000020: .cfi_restore_extended: r95
 // 0x00000020: pop {r5,r6,r7,r8,r10,r11,lr}
-// 0x00000024: ldr r8, [tr, #52] ; is_gc_marking
+// 0x00000024: .cfi_def_cfa_offset: 0
+// 0x00000024: .cfi_restore: r5
+// 0x00000024: .cfi_restore: r6
+// 0x00000024: .cfi_restore: r7
+// 0x00000024: .cfi_restore: r8
+// 0x00000024: .cfi_restore: r10
+// 0x00000024: .cfi_restore: r11
+// 0x00000024: .cfi_restore: r14
+// 0x00000024: ldr r8, [tr, #48] ; is_gc_marking
 // 0x00000028: bx lr
 // 0x0000002a: .cfi_restore_state
-// 0x0000002a: .cfi_def_cfa_offset: 128
+// 0x0000002a: .cfi_def_cfa_offset: 112
 
 static constexpr uint8_t expected_asm_kArm64[] = {
-    0xFF, 0x03, 0x03, 0xD1, 0xF3, 0x53, 0x06, 0xA9, 0xF5, 0x5B, 0x07, 0xA9,
-    0xF7, 0x63, 0x08, 0xA9, 0xF9, 0x6B, 0x09, 0xA9, 0xFB, 0x73, 0x0A, 0xA9,
-    0xFD, 0x7B, 0x0B, 0xA9, 0xE8, 0x27, 0x02, 0x6D, 0xEA, 0x2F, 0x03, 0x6D,
-    0xEC, 0x37, 0x04, 0x6D, 0xEE, 0x3F, 0x05, 0x6D, 0xE0, 0x03, 0x00, 0xF9,
-    0xE1, 0xCB, 0x00, 0xB9, 0xE0, 0xCF, 0x00, 0xBD, 0xE2, 0xD3, 0x00, 0xB9,
-    0xE3, 0xD7, 0x00, 0xB9, 0xFF, 0x83, 0x00, 0xD1, 0xFF, 0x83, 0x00, 0x91,
-    0xF3, 0x53, 0x46, 0xA9, 0xF5, 0x5B, 0x47, 0xA9, 0xF7, 0x63, 0x48, 0xA9,
-    0xF9, 0x6B, 0x49, 0xA9, 0xFB, 0x73, 0x4A, 0xA9, 0xFD, 0x7B, 0x4B, 0xA9,
-    0xE8, 0x27, 0x42, 0x6D, 0xEA, 0x2F, 0x43, 0x6D, 0xEC, 0x37, 0x44, 0x6D,
-    0xEE, 0x3F, 0x45, 0x6D, 0x74, 0x36, 0x40, 0xB9, 0xFF, 0x03, 0x03, 0x91,
+    0xFF, 0xC3, 0x02, 0xD1, 0xF3, 0x53, 0x05, 0xA9, 0xF5, 0x5B, 0x06, 0xA9,
+    0xF7, 0x63, 0x07, 0xA9, 0xF9, 0x6B, 0x08, 0xA9, 0xFB, 0x73, 0x09, 0xA9,
+    0xFD, 0x7B, 0x0A, 0xA9, 0xE8, 0x27, 0x01, 0x6D, 0xEA, 0x2F, 0x02, 0x6D,
+    0xEC, 0x37, 0x03, 0x6D, 0xEE, 0x3F, 0x04, 0x6D, 0xE0, 0x03, 0x00, 0xF9,
+    0xE1, 0xBB, 0x00, 0xB9, 0xE0, 0xBF, 0x00, 0xBD, 0xE2, 0xC3, 0x00, 0xB9,
+    0xE3, 0xC7, 0x00, 0xB9, 0xFF, 0x83, 0x00, 0xD1, 0xFF, 0x83, 0x00, 0x91,
+    0xF3, 0x53, 0x45, 0xA9, 0xF5, 0x5B, 0x46, 0xA9, 0xF7, 0x63, 0x47, 0xA9,
+    0xF9, 0x6B, 0x48, 0xA9, 0xFB, 0x73, 0x49, 0xA9, 0xFD, 0x7B, 0x4A, 0xA9,
+    0xE8, 0x27, 0x41, 0x6D, 0xEA, 0x2F, 0x42, 0x6D, 0xEC, 0x37, 0x43, 0x6D,
+    0xEE, 0x3F, 0x44, 0x6D, 0x74, 0x32, 0x40, 0xB9, 0xFF, 0xC3, 0x02, 0x91,
     0xC0, 0x03, 0x5F, 0xD6,
 };
 static constexpr uint8_t expected_cfi_kArm64[] = {
-    0x44, 0x0E, 0xC0, 0x01, 0x44, 0x93, 0x18, 0x94, 0x16, 0x44, 0x95, 0x14,
+    0x44, 0x0E, 0xB0, 0x01, 0x44, 0x93, 0x18, 0x94, 0x16, 0x44, 0x95, 0x14,
     0x96, 0x12, 0x44, 0x97, 0x10, 0x98, 0x0E, 0x44, 0x99, 0x0C, 0x9A, 0x0A,
     0x44, 0x9B, 0x08, 0x9C, 0x06, 0x44, 0x9D, 0x04, 0x9E, 0x02, 0x44, 0x05,
     0x48, 0x28, 0x05, 0x49, 0x26, 0x44, 0x05, 0x4A, 0x24, 0x05, 0x4B, 0x22,
     0x44, 0x05, 0x4C, 0x20, 0x05, 0x4D, 0x1E, 0x44, 0x05, 0x4E, 0x1C, 0x05,
-    0x4F, 0x1A, 0x58, 0x0E, 0xE0, 0x01, 0x44, 0x0E, 0xC0, 0x01, 0x0A, 0x44,
+    0x4F, 0x1A, 0x58, 0x0E, 0xD0, 0x01, 0x44, 0x0E, 0xB0, 0x01, 0x0A, 0x44,
     0xD3, 0xD4, 0x44, 0xD5, 0xD6, 0x44, 0xD7, 0xD8, 0x44, 0xD9, 0xDA, 0x44,
     0xDB, 0xDC, 0x44, 0xDD, 0xDE, 0x44, 0x06, 0x48, 0x06, 0x49, 0x44, 0x06,
     0x4A, 0x06, 0x4B, 0x44, 0x06, 0x4C, 0x06, 0x4D, 0x44, 0x06, 0x4E, 0x06,
-    0x4F, 0x48, 0x0E, 0x00, 0x44, 0x0B, 0x0E, 0xC0, 0x01,
+    0x4F, 0x48, 0x0E, 0x00, 0x44, 0x0B, 0x0E, 0xB0, 0x01,
 };
-// 0x00000000: sub sp, sp, #0xc0 (192)
-// 0x00000004: .cfi_def_cfa_offset: 192
-// 0x00000004: stp tr, x20, [sp, #96]
+// 0x00000000: sub sp, sp, #0xb0 (176)
+// 0x00000004: .cfi_def_cfa_offset: 176
+// 0x00000004: stp tr, x20, [sp, #80]
 // 0x00000008: .cfi_offset: r19 at cfa-96
 // 0x00000008: .cfi_offset: r20 at cfa-88
-// 0x00000008: stp x21, x22, [sp, #112]
+// 0x00000008: stp x21, x22, [sp, #96]
 // 0x0000000c: .cfi_offset: r21 at cfa-80
 // 0x0000000c: .cfi_offset: r22 at cfa-72
-// 0x0000000c: stp x23, x24, [sp, #128]
+// 0x0000000c: stp x23, x24, [sp, #112]
 // 0x00000010: .cfi_offset: r23 at cfa-64
 // 0x00000010: .cfi_offset: r24 at cfa-56
-// 0x00000010: stp x25, x26, [sp, #144]
+// 0x00000010: stp x25, x26, [sp, #128]
 // 0x00000014: .cfi_offset: r25 at cfa-48
 // 0x00000014: .cfi_offset: r26 at cfa-40
-// 0x00000014: stp x27, x28, [sp, #160]
+// 0x00000014: stp x27, x28, [sp, #144]
 // 0x00000018: .cfi_offset: r27 at cfa-32
 // 0x00000018: .cfi_offset: r28 at cfa-24
-// 0x00000018: stp x29, lr, [sp, #176]
+// 0x00000018: stp x29, lr, [sp, #160]
 // 0x0000001c: .cfi_offset: r29 at cfa-16
 // 0x0000001c: .cfi_offset: r30 at cfa-8
-// 0x0000001c: stp d8, d9, [sp, #32]
+// 0x0000001c: stp d8, d9, [sp, #16]
 // 0x00000020: .cfi_offset_extended: r72 at cfa-160
 // 0x00000020: .cfi_offset_extended: r73 at cfa-152
-// 0x00000020: stp d10, d11, [sp, #48]
+// 0x00000020: stp d10, d11, [sp, #32]
 // 0x00000024: .cfi_offset_extended: r74 at cfa-144
 // 0x00000024: .cfi_offset_extended: r75 at cfa-136
-// 0x00000024: stp d12, d13, [sp, #64]
+// 0x00000024: stp d12, d13, [sp, #48]
 // 0x00000028: .cfi_offset_extended: r76 at cfa-128
 // 0x00000028: .cfi_offset_extended: r77 at cfa-120
-// 0x00000028: stp d14, d15, [sp, #80]
+// 0x00000028: stp d14, d15, [sp, #64]
 // 0x0000002c: .cfi_offset_extended: r78 at cfa-112
 // 0x0000002c: .cfi_offset_extended: r79 at cfa-104
 // 0x0000002c: str x0, [sp]
-// 0x00000030: str w1, [sp, #200]
-// 0x00000034: str s0, [sp, #204]
-// 0x00000038: str w2, [sp, #208]
-// 0x0000003c: str w3, [sp, #212]
+// 0x00000030: str w1, [sp, #184]
+// 0x00000034: str s0, [sp, #188]
+// 0x00000038: str w2, [sp, #192]
+// 0x0000003c: str w3, [sp, #196]
 // 0x00000040: sub sp, sp, #0x20 (32)
-// 0x00000044: .cfi_def_cfa_offset: 224
+// 0x00000044: .cfi_def_cfa_offset: 208
 // 0x00000044: add sp, sp, #0x20 (32)
-// 0x00000048: .cfi_def_cfa_offset: 192
+// 0x00000048: .cfi_def_cfa_offset: 176
 // 0x00000048: .cfi_remember_state
-// 0x00000048: ldp tr, x20, [sp, #96]
+// 0x00000048: ldp tr, x20, [sp, #80]
 // 0x0000004c: .cfi_restore: r19
 // 0x0000004c: .cfi_restore: r20
-// 0x0000004c: ldp x21, x22, [sp, #112]
+// 0x0000004c: ldp x21, x22, [sp, #96]
 // 0x00000050: .cfi_restore: r21
 // 0x00000050: .cfi_restore: r22
-// 0x00000050: ldp x23, x24, [sp, #128]
+// 0x00000050: ldp x23, x24, [sp, #112]
 // 0x00000054: .cfi_restore: r23
 // 0x00000054: .cfi_restore: r24
-// 0x00000054: ldp x25, x26, [sp, #144]
+// 0x00000054: ldp x25, x26, [sp, #128]
 // 0x00000058: .cfi_restore: r25
 // 0x00000058: .cfi_restore: r26
-// 0x00000058: ldp x27, x28, [sp, #160]
+// 0x00000058: ldp x27, x28, [sp, #144]
 // 0x0000005c: .cfi_restore: r27
 // 0x0000005c: .cfi_restore: r28
-// 0x0000005c: ldp x29, lr, [sp, #176]
+// 0x0000005c: ldp x29, lr, [sp, #160]
 // 0x00000060: .cfi_restore: r29
 // 0x00000060: .cfi_restore: r30
-// 0x00000060: ldp d8, d9, [sp, #32]
+// 0x00000060: ldp d8, d9, [sp, #16]
 // 0x00000064: .cfi_restore_extended: r72
 // 0x00000064: .cfi_restore_extended: r73
-// 0x00000064: ldp d10, d11, [sp, #48]
+// 0x00000064: ldp d10, d11, [sp, #32]
 // 0x00000068: .cfi_restore_extended: r74
 // 0x00000068: .cfi_restore_extended: r75
-// 0x00000068: ldp d12, d13, [sp, #64]
+// 0x00000068: ldp d12, d13, [sp, #48]
 // 0x0000006c: .cfi_restore_extended: r76
 // 0x0000006c: .cfi_restore_extended: r77
-// 0x0000006c: ldp d14, d15, [sp, #80]
+// 0x0000006c: ldp d14, d15, [sp, #64]
 // 0x00000070: .cfi_restore_extended: r78
 // 0x00000070: .cfi_restore_extended: r79
-// 0x00000070: ldr w20, [tr, #52] ; is_gc_marking
-// 0x00000074: add sp, sp, #0xc0 (192)
+// 0x00000070: ldr w20, [tr, #48] ; is_gc_marking
+// 0x00000074: add sp, sp, #0xb0 (176)
 // 0x00000078: .cfi_def_cfa_offset: 0
 // 0x00000078: ret
 // 0x0000007c: .cfi_restore_state
-// 0x0000007c: .cfi_def_cfa_offset: 192
+// 0x0000007c: .cfi_def_cfa_offset: 176
 
 static constexpr uint8_t expected_asm_kX86[] = {
-    0x57, 0x56, 0x55, 0x83, 0xC4, 0xE4, 0x50, 0x89, 0x4C, 0x24, 0x34, 0xF3,
-    0x0F, 0x11, 0x44, 0x24, 0x38, 0x89, 0x54, 0x24, 0x3C, 0x89, 0x5C, 0x24,
-    0x40, 0x83, 0xC4, 0xE0, 0x83, 0xC4, 0x20, 0x83, 0xC4, 0x20, 0x5D, 0x5E,
+    0x57, 0x56, 0x55, 0x83, 0xC4, 0xF4, 0x50, 0x89, 0x4C, 0x24, 0x24, 0xF3,
+    0x0F, 0x11, 0x44, 0x24, 0x28, 0x89, 0x54, 0x24, 0x2C, 0x89, 0x5C, 0x24,
+    0x30, 0x83, 0xC4, 0xE0, 0x83, 0xC4, 0x20, 0x83, 0xC4, 0x10, 0x5D, 0x5E,
     0x5F, 0xC3,
 };
 static constexpr uint8_t expected_cfi_kX86[] = {
     0x41, 0x0E, 0x08, 0x87, 0x02, 0x41, 0x0E, 0x0C, 0x86, 0x03, 0x41, 0x0E,
-    0x10, 0x85, 0x04, 0x43, 0x0E, 0x2C, 0x41, 0x0E, 0x30, 0x55, 0x0E, 0x50,
-    0x43, 0x0E, 0x30, 0x0A, 0x43, 0x0E, 0x10, 0x41, 0x0E, 0x0C, 0xC5, 0x41,
-    0x0E, 0x08, 0xC6, 0x41, 0x0E, 0x04, 0xC7, 0x41, 0x0B, 0x0E, 0x30,
+    0x10, 0x85, 0x04, 0x43, 0x0E, 0x1C, 0x41, 0x0E, 0x20, 0x55, 0x0E, 0x40,
+    0x43, 0x0E, 0x20, 0x0A, 0x43, 0x0E, 0x10, 0x41, 0x0E, 0x0C, 0xC5, 0x41,
+    0x0E, 0x08, 0xC6, 0x41, 0x0E, 0x04, 0xC7, 0x41, 0x0B, 0x0E, 0x20,
 };
 // 0x00000000: push edi
 // 0x00000001: .cfi_def_cfa_offset: 8
@@ -207,20 +216,20 @@
 // 0x00000002: push ebp
 // 0x00000003: .cfi_def_cfa_offset: 16
 // 0x00000003: .cfi_offset: r5 at cfa-16
-// 0x00000003: add esp, -28
-// 0x00000006: .cfi_def_cfa_offset: 44
+// 0x00000003: add esp, -12
+// 0x00000006: .cfi_def_cfa_offset: 28
 // 0x00000006: push eax
-// 0x00000007: .cfi_def_cfa_offset: 48
-// 0x00000007: mov [esp + 52], ecx
-// 0x0000000b: movss [esp + 56], xmm0
-// 0x00000011: mov [esp + 60], edx
-// 0x00000015: mov [esp + 64], ebx
+// 0x00000007: .cfi_def_cfa_offset: 32
+// 0x00000007: mov [esp + 36], ecx
+// 0x0000000b: movss [esp + 40], xmm0
+// 0x00000011: mov [esp + 44], edx
+// 0x00000015: mov [esp + 48], ebx
 // 0x00000019: add esp, -32
-// 0x0000001c: .cfi_def_cfa_offset: 80
+// 0x0000001c: .cfi_def_cfa_offset: 64
 // 0x0000001c: add esp, 32
-// 0x0000001f: .cfi_def_cfa_offset: 48
+// 0x0000001f: .cfi_def_cfa_offset: 32
 // 0x0000001f: .cfi_remember_state
-// 0x0000001f: add esp, 32
+// 0x0000001f: add esp, 16
 // 0x00000022: .cfi_def_cfa_offset: 16
 // 0x00000022: pop ebp
 // 0x00000023: .cfi_def_cfa_offset: 12
@@ -233,30 +242,30 @@
 // 0x00000025: .cfi_restore: r7
 // 0x00000025: ret
 // 0x00000026: .cfi_restore_state
-// 0x00000026: .cfi_def_cfa_offset: 48
+// 0x00000026: .cfi_def_cfa_offset: 32
 
 static constexpr uint8_t expected_asm_kX86_64[] = {
     0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, 0x54, 0x55, 0x53, 0x48, 0x83,
-    0xEC, 0x48, 0xF2, 0x44, 0x0F, 0x11, 0x7C, 0x24, 0x40, 0xF2, 0x44, 0x0F,
-    0x11, 0x74, 0x24, 0x38, 0xF2, 0x44, 0x0F, 0x11, 0x6C, 0x24, 0x30, 0xF2,
-    0x44, 0x0F, 0x11, 0x64, 0x24, 0x28, 0x48, 0x89, 0x3C, 0x24, 0x89, 0xB4,
-    0x24, 0x88, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x11, 0x84, 0x24, 0x8C, 0x00,
-    0x00, 0x00, 0x89, 0x94, 0x24, 0x90, 0x00, 0x00, 0x00, 0x89, 0x8C, 0x24,
-    0x94, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0xE0, 0x48, 0x83, 0xC4, 0x20,
-    0xF2, 0x44, 0x0F, 0x10, 0x64, 0x24, 0x28, 0xF2, 0x44, 0x0F, 0x10, 0x6C,
-    0x24, 0x30, 0xF2, 0x44, 0x0F, 0x10, 0x74, 0x24, 0x38, 0xF2, 0x44, 0x0F,
-    0x10, 0x7C, 0x24, 0x40, 0x48, 0x83, 0xC4, 0x48, 0x5B, 0x5D, 0x41, 0x5C,
-    0x41, 0x5D, 0x41, 0x5E, 0x41, 0x5F, 0xC3,
+    0xEC, 0x38, 0xF2, 0x44, 0x0F, 0x11, 0x7C, 0x24, 0x30, 0xF2, 0x44, 0x0F,
+    0x11, 0x74, 0x24, 0x28, 0xF2, 0x44, 0x0F, 0x11, 0x6C, 0x24, 0x20, 0xF2,
+    0x44, 0x0F, 0x11, 0x64, 0x24, 0x18, 0x48, 0x89, 0x3C, 0x24, 0x89, 0x74,
+    0x24, 0x78, 0xF3, 0x0F, 0x11, 0x44, 0x24, 0x7C, 0x89, 0x94, 0x24, 0x80,
+    0x00, 0x00, 0x00, 0x89, 0x8C, 0x24, 0x84, 0x00, 0x00, 0x00, 0x48, 0x83,
+    0xC4, 0xE0, 0x48, 0x83, 0xC4, 0x20, 0xF2, 0x44, 0x0F, 0x10, 0x64, 0x24,
+    0x18, 0xF2, 0x44, 0x0F, 0x10, 0x6C, 0x24, 0x20, 0xF2, 0x44, 0x0F, 0x10,
+    0x74, 0x24, 0x28, 0xF2, 0x44, 0x0F, 0x10, 0x7C, 0x24, 0x30, 0x48, 0x83,
+    0xC4, 0x38, 0x5B, 0x5D, 0x41, 0x5C, 0x41, 0x5D, 0x41, 0x5E, 0x41, 0x5F,
+    0xC3,
 };
 static constexpr uint8_t expected_cfi_kX86_64[] = {
     0x42, 0x0E, 0x10, 0x8F, 0x04, 0x42, 0x0E, 0x18, 0x8E, 0x06, 0x42, 0x0E,
     0x20, 0x8D, 0x08, 0x42, 0x0E, 0x28, 0x8C, 0x0A, 0x41, 0x0E, 0x30, 0x86,
-    0x0C, 0x41, 0x0E, 0x38, 0x83, 0x0E, 0x44, 0x0E, 0x80, 0x01, 0x47, 0xA0,
-    0x10, 0x47, 0x9F, 0x12, 0x47, 0x9E, 0x14, 0x47, 0x9D, 0x16, 0x66, 0x0E,
-    0xA0, 0x01, 0x44, 0x0E, 0x80, 0x01, 0x0A, 0x47, 0xDD, 0x47, 0xDE, 0x47,
-    0xDF, 0x47, 0xE0, 0x44, 0x0E, 0x38, 0x41, 0x0E, 0x30, 0xC3, 0x41, 0x0E,
-    0x28, 0xC6, 0x42, 0x0E, 0x20, 0xCC, 0x42, 0x0E, 0x18, 0xCD, 0x42, 0x0E,
-    0x10, 0xCE, 0x42, 0x0E, 0x08, 0xCF, 0x41, 0x0B, 0x0E, 0x80, 0x01,
+    0x0C, 0x41, 0x0E, 0x38, 0x83, 0x0E, 0x44, 0x0E, 0x70, 0x47, 0xA0, 0x10,
+    0x47, 0x9F, 0x12, 0x47, 0x9E, 0x14, 0x47, 0x9D, 0x16, 0x60, 0x0E, 0x90,
+    0x01, 0x44, 0x0E, 0x70, 0x0A, 0x47, 0xDD, 0x47, 0xDE, 0x47, 0xDF, 0x47,
+    0xE0, 0x44, 0x0E, 0x38, 0x41, 0x0E, 0x30, 0xC3, 0x41, 0x0E, 0x28, 0xC6,
+    0x42, 0x0E, 0x20, 0xCC, 0x42, 0x0E, 0x18, 0xCD, 0x42, 0x0E, 0x10, 0xCE,
+    0x42, 0x0E, 0x08, 0xCF, 0x41, 0x0B, 0x0E, 0x70,
 };
 // 0x00000000: push r15
 // 0x00000002: .cfi_def_cfa_offset: 16
@@ -276,55 +285,55 @@
 // 0x00000009: push rbx
 // 0x0000000a: .cfi_def_cfa_offset: 56
 // 0x0000000a: .cfi_offset: r3 at cfa-56
-// 0x0000000a: subq rsp, 72
-// 0x0000000e: .cfi_def_cfa_offset: 128
-// 0x0000000e: movsd [rsp + 64], xmm15
+// 0x0000000a: subq rsp, 56
+// 0x0000000e: .cfi_def_cfa_offset: 112
+// 0x0000000e: movsd [rsp + 48], xmm15
 // 0x00000015: .cfi_offset: r32 at cfa-64
-// 0x00000015: movsd [rsp + 56], xmm14
+// 0x00000015: movsd [rsp + 40], xmm14
 // 0x0000001c: .cfi_offset: r31 at cfa-72
-// 0x0000001c: movsd [rsp + 48], xmm13
+// 0x0000001c: movsd [rsp + 32], xmm13
 // 0x00000023: .cfi_offset: r30 at cfa-80
-// 0x00000023: movsd [rsp + 40], xmm12
+// 0x00000023: movsd [rsp + 24], xmm12
 // 0x0000002a: .cfi_offset: r29 at cfa-88
 // 0x0000002a: movq [rsp], rdi
-// 0x0000002e: mov [rsp + 136], esi
-// 0x00000035: movss [rsp + 140], xmm0
-// 0x0000003e: mov [rsp + 144], edx
-// 0x00000045: mov [rsp + 148], ecx
-// 0x0000004c: addq rsp, -32
-// 0x00000050: .cfi_def_cfa_offset: 160
-// 0x00000050: addq rsp, 32
-// 0x00000054: .cfi_def_cfa_offset: 128
-// 0x00000054: .cfi_remember_state
-// 0x00000054: movsd xmm12, [rsp + 40]
-// 0x0000005b: .cfi_restore: r29
-// 0x0000005b: movsd xmm13, [rsp + 48]
-// 0x00000062: .cfi_restore: r30
-// 0x00000062: movsd xmm14, [rsp + 56]
-// 0x00000069: .cfi_restore: r31
-// 0x00000069: movsd xmm15, [rsp + 64]
-// 0x00000070: .cfi_restore: r32
-// 0x00000070: addq rsp, 72
-// 0x00000074: .cfi_def_cfa_offset: 56
-// 0x00000074: pop rbx
-// 0x00000075: .cfi_def_cfa_offset: 48
-// 0x00000075: .cfi_restore: r3
-// 0x00000075: pop rbp
-// 0x00000076: .cfi_def_cfa_offset: 40
-// 0x00000076: .cfi_restore: r6
-// 0x00000076: pop r12
-// 0x00000078: .cfi_def_cfa_offset: 32
-// 0x00000078: .cfi_restore: r12
-// 0x00000078: pop r13
-// 0x0000007a: .cfi_def_cfa_offset: 24
-// 0x0000007a: .cfi_restore: r13
-// 0x0000007a: pop r14
-// 0x0000007c: .cfi_def_cfa_offset: 16
-// 0x0000007c: .cfi_restore: r14
-// 0x0000007c: pop r15
-// 0x0000007e: .cfi_def_cfa_offset: 8
-// 0x0000007e: .cfi_restore: r15
-// 0x0000007e: ret
-// 0x0000007f: .cfi_restore_state
-// 0x0000007f: .cfi_def_cfa_offset: 128
+// 0x0000002e: mov [rsp + 120], esi
+// 0x00000032: movss [rsp + 124], xmm0
+// 0x00000038: mov [rsp + 128], edx
+// 0x0000003f: mov [rsp + 132], ecx
+// 0x00000046: addq rsp, -32
+// 0x0000004a: .cfi_def_cfa_offset: 144
+// 0x0000004a: addq rsp, 32
+// 0x0000004e: .cfi_def_cfa_offset: 112
+// 0x0000004e: .cfi_remember_state
+// 0x0000004e: movsd xmm12, [rsp + 24]
+// 0x00000055: .cfi_restore: r29
+// 0x00000055: movsd xmm13, [rsp + 32]
+// 0x0000005c: .cfi_restore: r30
+// 0x0000005c: movsd xmm14, [rsp + 40]
+// 0x00000063: .cfi_restore: r31
+// 0x00000063: movsd xmm15, [rsp + 48]
+// 0x0000006a: .cfi_restore: r32
+// 0x0000006a: addq rsp, 56
+// 0x0000006e: .cfi_def_cfa_offset: 56
+// 0x0000006e: pop rbx
+// 0x0000006f: .cfi_def_cfa_offset: 48
+// 0x0000006f: .cfi_restore: r3
+// 0x0000006f: pop rbp
+// 0x00000070: .cfi_def_cfa_offset: 40
+// 0x00000070: .cfi_restore: r6
+// 0x00000070: pop r12
+// 0x00000072: .cfi_def_cfa_offset: 32
+// 0x00000072: .cfi_restore: r12
+// 0x00000072: pop r13
+// 0x00000074: .cfi_def_cfa_offset: 24
+// 0x00000074: .cfi_restore: r13
+// 0x00000074: pop r14
+// 0x00000076: .cfi_def_cfa_offset: 16
+// 0x00000076: .cfi_restore: r14
+// 0x00000076: pop r15
+// 0x00000078: .cfi_def_cfa_offset: 8
+// 0x00000078: .cfi_restore: r15
+// 0x00000078: ret
+// 0x00000079: .cfi_restore_state
+// 0x00000079: .cfi_def_cfa_offset: 112
 
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index 405c9ec..dc5304c 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -21,6 +21,7 @@
 
 #include "art_method-inl.h"
 #include "base/bit_utils.h"
+#include "base/casts.h"
 #include "base/mem_map.h"
 #include "class_linker.h"
 #include "common_compiler_test.h"
@@ -28,6 +29,7 @@
 #include "dex/dex_file.h"
 #include "gtest/gtest.h"
 #include "indirect_reference_table.h"
+#include "java_frame_root_info.h"
 #include "jni/java_vm_ext.h"
 #include "jni/jni_internal.h"
 #include "mirror/class-inl.h"
@@ -119,12 +121,12 @@
   }
 }
 
-// Dummy values passed to our JNI handlers when we enter @CriticalNative.
+// Fake values passed to our JNI handlers when we enter @CriticalNative.
 // Normally @CriticalNative calling convention strips out the "JNIEnv*, jclass" parameters.
 // However to avoid duplicating every single test method we have a templated handler
-// that inserts dummy parameters (0,1) to make it compatible with a regular JNI handler.
-static JNIEnv* const kCriticalDummyJniEnv = reinterpret_cast<JNIEnv*>(0xDEADFEAD);
-static jclass const kCriticalDummyJniClass = reinterpret_cast<jclass>(0xBEAFBEEF);
+// that inserts fake parameters (0,1) to make it compatible with a regular JNI handler.
+static JNIEnv* const kCriticalFakeJniEnv = reinterpret_cast<JNIEnv*>(0xDEADFEAD);
+static jclass const kCriticalFakeJniClass = reinterpret_cast<jclass>(0xBEAFBEEF);
 
 // Type trait. Returns true if "T" is the same type as one of the types in Args...
 //
@@ -154,19 +156,6 @@
                 jcharArray, jfloatArray, jshortArray, jdoubleArray, jlongArray>::value;
 };
 
-template <typename ... Args>
-struct count_refs_helper {
-  using value_type = size_t;
-  static constexpr const size_t value = 0;
-};
-
-template <typename Arg, typename ... Args>
-struct count_refs_helper<Arg, Args ...> {
-  using value_type = size_t;
-  static constexpr size_t value =
-      (jni_type_traits<Arg>::is_ref ? 1 : 0) + count_refs_helper<Args ...>::value;
-};
-
 // Base case: No parameters = 0 refs.
 size_t count_nonnull_refs_helper() {
   return 0;
@@ -212,8 +201,8 @@
 struct remove_extra_parameters_helper<R(Arg1, Arg2, Args...), fn> {
   // Note: Do not use Args&& here to maintain C-style parameter types.
   static R apply(Args... args) {
-    JNIEnv* env = kCriticalDummyJniEnv;
-    jclass kls = kCriticalDummyJniClass;
+    JNIEnv* env = kCriticalFakeJniEnv;
+    jclass kls = kCriticalFakeJniClass;
     return fn(env, kls, args...);
   }
 };
@@ -246,15 +235,23 @@
                       const char* method_name,
                       const char* method_sig) {
     ScopedObjectAccess soa(Thread::Current());
-    StackHandleScope<1> hs(soa.Self());
+    StackHandleScope<2> hs(soa.Self());
     Handle<mirror::ClassLoader> loader(
         hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
     // Compile the native method before starting the runtime
-    ObjPtr<mirror::Class> c = class_linker_->FindClass(soa.Self(), "LMyClassNatives;", loader);
+    Handle<mirror::Class> c =
+        hs.NewHandle(class_linker_->FindClass(soa.Self(), "LMyClassNatives;", loader));
     const auto pointer_size = class_linker_->GetImagePointerSize();
     ArtMethod* method = c->FindClassMethod(method_name, method_sig, pointer_size);
     ASSERT_TRUE(method != nullptr) << method_name << " " << method_sig;
     ASSERT_EQ(direct, method->IsDirect()) << method_name << " " << method_sig;
+    if (direct) {
+      // Class initialization could replace the entrypoint, so force
+      // the initialization before we set up the entrypoint below.
+      class_linker_->EnsureInitialized(
+          soa.Self(), c, /*can_init_fields=*/ true, /*can_init_parents=*/ true);
+      class_linker_->MakeInitializedClassesVisiblyInitialized(soa.Self(), /*wait=*/ true);
+    }
     if (check_generic_jni_) {
       method->SetEntryPointFromQuickCompiledCode(class_linker_->GetRuntimeQuickGenericJniStub());
     } else {
@@ -314,6 +311,12 @@
     }
     ASSERT_TRUE(jmethod_ != nullptr) << method_name << " " << method_sig;
 
+    // Make sure the test class is visibly initialized so that the RegisterNatives() below
+    // sets the JNI entrypoint rather than leaving it as null (this test pretends to be an
+    // AOT compiler and therefore the ClassLinker skips entrypoint initialization). Even
+    // if the ClassLinker initialized it with a stub, we would not want to test that here.
+    class_linker_->MakeInitializedClassesVisiblyInitialized(Thread::Current(), /*wait=*/ true);
+
     if (native_fnptr != nullptr) {
       JNINativeMethod methods[] = { { method_name, method_sig, native_fnptr } };
       ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1))
@@ -385,12 +388,89 @@
   jmethodID jmethod_;
 
  private:
+  class ScopedSynchronizedEntryPointOverrides {
+   public:
+    ScopedSynchronizedEntryPointOverrides() {
+      QuickEntryPoints* qpoints = &Thread::Current()->tlsPtr_.quick_entrypoints;
+      jni_method_start_synchronized_original_ = qpoints->pJniMethodStartSynchronized;
+      qpoints->pJniMethodStartSynchronized = JniMethodStartSynchronizedOverride;
+      jni_method_end_synchronized_original_ = qpoints->pJniMethodEndSynchronized;
+      qpoints->pJniMethodEndSynchronized = JniMethodEndSynchronizedOverride;
+      jni_method_end_with_reference_synchronized_original_ =
+          qpoints->pJniMethodEndWithReferenceSynchronized;
+      qpoints->pJniMethodEndWithReferenceSynchronized =
+          JniMethodEndWithReferenceSynchronizedOverride;
+    }
+
+    ~ScopedSynchronizedEntryPointOverrides() {
+      QuickEntryPoints* qpoints = &Thread::Current()->tlsPtr_.quick_entrypoints;
+      qpoints->pJniMethodStartSynchronized = jni_method_start_synchronized_original_;
+      qpoints->pJniMethodEndSynchronized = jni_method_end_synchronized_original_;
+      qpoints->pJniMethodEndWithReferenceSynchronized =
+          jni_method_end_with_reference_synchronized_original_;
+    }
+  };
+
+  static uint32_t JniMethodStartSynchronizedOverride(jobject to_lock, Thread* self);
+  static void JniMethodEndSynchronizedOverride(uint32_t saved_local_ref_cookie,
+                                               jobject locked,
+                                               Thread* self);
+  static mirror::Object* JniMethodEndWithReferenceSynchronizedOverride(
+      jobject result,
+      uint32_t saved_local_ref_cookie,
+      jobject locked,
+      Thread* self);
+
+  using StartSynchronizedType = uint32_t (*)(jobject, Thread*);
+  using EndSynchronizedType = void (*)(uint32_t, jobject, Thread*);
+  using EndWithReferenceSynchronizedType = mirror::Object* (*)(jobject, uint32_t, jobject, Thread*);
+
+  static StartSynchronizedType jni_method_start_synchronized_original_;
+  static EndSynchronizedType jni_method_end_synchronized_original_;
+  static EndWithReferenceSynchronizedType jni_method_end_with_reference_synchronized_original_;
+  static uint32_t saved_local_ref_cookie_;
+  static jobject locked_object_;
+
   bool check_generic_jni_;
 };
 
 jclass JniCompilerTest::jklass_;
 jobject JniCompilerTest::jobj_;
 jobject JniCompilerTest::class_loader_;
+JniCompilerTest::StartSynchronizedType JniCompilerTest::jni_method_start_synchronized_original_;
+JniCompilerTest::EndSynchronizedType JniCompilerTest::jni_method_end_synchronized_original_;
+JniCompilerTest::EndWithReferenceSynchronizedType
+    JniCompilerTest::jni_method_end_with_reference_synchronized_original_;
+uint32_t JniCompilerTest::saved_local_ref_cookie_;
+jobject JniCompilerTest::locked_object_;
+
+uint32_t JniCompilerTest::JniMethodStartSynchronizedOverride(jobject to_lock, Thread* self) {
+  locked_object_ = to_lock;
+  uint32_t cookie = jni_method_start_synchronized_original_(to_lock, self);
+  saved_local_ref_cookie_ = cookie;
+  return cookie;
+}
+
+void JniCompilerTest::JniMethodEndSynchronizedOverride(uint32_t saved_local_ref_cookie,
+                                                       jobject locked,
+                                                       Thread* self) {
+  EXPECT_EQ(saved_local_ref_cookie_, saved_local_ref_cookie);
+  EXPECT_EQ(locked_object_, locked);
+  jni_method_end_synchronized_original_(saved_local_ref_cookie, locked, self);
+}
+
+mirror::Object* JniCompilerTest::JniMethodEndWithReferenceSynchronizedOverride(
+    jobject result,
+    uint32_t saved_local_ref_cookie,
+    jobject locked,
+    Thread* self) {
+  EXPECT_EQ(saved_local_ref_cookie_, saved_local_ref_cookie);
+  EXPECT_EQ(locked_object_, locked);
+  return jni_method_end_with_reference_synchronized_original_(result,
+                                                              saved_local_ref_cookie,
+                                                              locked,
+                                                              self);
+}
 
 // Test the normal compiler and normal generic JNI only.
 // The following features are unsupported in @FastNative:
@@ -496,8 +576,8 @@
                                   static_cast<jobject>(kls)));
   } else {
     // This is pretty much vacuously true but catch any testing setup mistakes.
-    EXPECT_EQ(env, kCriticalDummyJniEnv);
-    EXPECT_EQ(kls, kCriticalDummyJniClass);
+    EXPECT_EQ(env, kCriticalFakeJniEnv);
+    EXPECT_EQ(kls, kCriticalFakeJniClass);
   }
 }
 
@@ -505,7 +585,7 @@
 // that the jclass we got in the JNI handler is the same one as the class the method was looked
 // up for.
 //
-// (Checks are skipped for @CriticalNative since the two values are dummy).
+// (Checks are skipped for @CriticalNative since the two values are fake).
 #define EXPECT_JNI_ENV_AND_CLASS_FOR_CURRENT_JNI(env, kls) expectValidJniEnvAndClass(env, kls)
 
 // Temporarily disable the EXPECT_NUM_STACK_REFERENCES check (for a single test).
@@ -539,42 +619,56 @@
   BaseHandleScope* const handle_scope_;
 };
 
-// Number of references allocated in JNI ShadowFrames on the given thread.
-static size_t NumJniShadowFrameReferences(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
-  return self->GetManagedStack()->NumJniShadowFrameReferences();
-}
-
-// Number of references in handle scope on the given thread.
-static size_t NumHandleReferences(Thread* self) {
-  size_t count = 0;
-  for (BaseHandleScope* cur = self->GetTopHandleScope(); cur != nullptr; cur = cur->GetLink()) {
-    count += cur->NumberOfReferences();
+class CountReferencesVisitor : public RootVisitor {
+ public:
+  void VisitRoots(mirror::Object*** roots ATTRIBUTE_UNUSED,
+                  size_t count,
+                  const RootInfo& info) override
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (info.GetType() == art::RootType::kRootJavaFrame) {
+      const JavaFrameRootInfo& jrfi = static_cast<const JavaFrameRootInfo&>(info);
+      if (jrfi.GetVReg() == JavaFrameRootInfo::kNativeReferenceArgument) {
+        DCHECK_EQ(count, 1u);
+        num_references_ += count;
+      }
+    }
   }
-  return count;
-}
+
+  void VisitRoots(mirror::CompressedReference<mirror::Object>** roots ATTRIBUTE_UNUSED,
+                  size_t count ATTRIBUTE_UNUSED,
+                  const RootInfo& info) override
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    CHECK_NE(info.GetType(), art::RootType::kRootJavaFrame);
+  }
+
+  size_t NumReferences() const {
+    return num_references_;
+  }
+
+ private:
+  size_t num_references_ = 0u;
+};
 
 // Number of references allocated in handle scopes & JNI shadow frames on this thread.
 static size_t NumStackReferences(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
-  return NumHandleReferences(self) + NumJniShadowFrameReferences(self);
+  CountReferencesVisitor visitor;
+  self->VisitRoots(&visitor, kVisitRootFlagAllRoots);
+  return visitor.NumReferences();
 }
 
-static void expectNumStackReferences(size_t val1, size_t val2) {
+static void expectNumStackReferences(size_t expected) {
   // In rare cases when JNI functions call themselves recursively,
   // disable this test because it will have a false negative.
   if (!IsCurrentJniCritical() && ScopedDisableCheckNumStackReferences::sCheckNumStackReferences) {
     /* @CriticalNative doesn't build a HandleScope, so this test is meaningless then. */
     ScopedObjectAccess soa(Thread::Current());
 
-    size_t actual_num = NumStackReferences(Thread::Current());
-    // XX: Not too sure what's going on.
-    // Sometimes null references get placed and sometimes they don't?
-    EXPECT_TRUE(val1 == actual_num || val2 == actual_num)
-      << "expected either " << val1 << " or " << val2
-      << " number of stack references, but got: " << actual_num;
+    size_t num_references = NumStackReferences(Thread::Current());
+    EXPECT_EQ(expected, num_references);
   }
 }
 
-#define EXPECT_NUM_STACK_REFERENCES(val1, val2) expectNumStackReferences(val1, val2)
+#define EXPECT_NUM_STACK_REFERENCES(expected) expectNumStackReferences(expected)
 
 template <typename T, T* fn>
 struct make_jni_test_decorator;
@@ -586,9 +680,9 @@
     EXPECT_THREAD_STATE_FOR_CURRENT_JNI();
     EXPECT_MUTATOR_LOCK_FOR_CURRENT_JNI();
     EXPECT_JNI_ENV_AND_CLASS_FOR_CURRENT_JNI(env, kls);
-    // All incoming parameters + the jclass get put into the transition's StackHandleScope.
-    EXPECT_NUM_STACK_REFERENCES(count_nonnull_refs(kls, args...),
-                                (count_refs_helper<jclass, Args...>::value));
+    // All incoming parameters get spilled into the JNI transition frame.
+    // The `jclass` is just a reference to the method's declaring class field.
+    EXPECT_NUM_STACK_REFERENCES(count_nonnull_refs(args...));
 
     return fn(env, kls, args...);
   }
@@ -601,9 +695,8 @@
     EXPECT_THREAD_STATE_FOR_CURRENT_JNI();
     EXPECT_MUTATOR_LOCK_FOR_CURRENT_JNI();
     EXPECT_JNI_ENV_AND_OBJECT_FOR_CURRENT_JNI(env, thisObj);
-    // All incoming parameters + the implicit 'this' get put into the transition's StackHandleScope.
-    EXPECT_NUM_STACK_REFERENCES(count_nonnull_refs(thisObj, args...),
-                                (count_refs_helper<jobject, Args...>::value));
+    // All incoming parameters + the implicit 'this' get spilled into the JNI transition frame.
+    EXPECT_NUM_STACK_REFERENCES(count_nonnull_refs(thisObj, args...));
 
     return fn(env, thisObj, args...);
   }
@@ -790,6 +883,7 @@
 void JniCompilerTest::CompileAndRun_fooJJ_synchronizedImpl() {
   SetUpForTest(false, "fooJJ_synchronized", "(JJ)J",
                CURRENT_JNI_WRAPPER(Java_MyClassNatives_fooJJ_synchronized));
+  ScopedSynchronizedEntryPointOverrides ssepo;
 
   EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_synchronized_calls[gCurrentJni]);
   jlong a = 0x1000000020000000ULL;
@@ -1089,6 +1183,7 @@
   SetUpForTest(true, "fooSSIOO",
                "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
                CURRENT_JNI_WRAPPER(Java_MyClassNatives_fooSSIOO));
+  ScopedSynchronizedEntryPointOverrides ssepo;
 
   EXPECT_EQ(0, gJava_MyClassNatives_fooSSIOO_calls[gCurrentJni]);
   jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, nullptr, nullptr);
@@ -1178,7 +1273,7 @@
     ScopedObjectAccess soa(env);
 
     // Build stack trace
-    jobject internal = Thread::Current()->CreateInternalStackTrace<false>(soa);
+    jobject internal = Thread::Current()->CreateInternalStackTrace(soa);
     jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(soa, internal);
     ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> trace_array =
         soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>>(ste_array);
@@ -1329,6 +1424,7 @@
 void JniCompilerTest::GetSinkPropertiesNativeImpl() {
   SetUpForTest(false, "getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;",
                CURRENT_JNI_WRAPPER(Java_MyClassNatives_GetSinkProperties));
+  ScopedSynchronizedEntryPointOverrides ssepo;
 
   EXPECT_EQ(0, gJava_MyClassNatives_GetSinkProperties_calls[gCurrentJni]);
   jarray result = down_cast<jarray>(
diff --git a/compiler/jni/quick/arm/calling_convention_arm.cc b/compiler/jni/quick/arm/calling_convention_arm.cc
index e06c914..d849c28 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.cc
+++ b/compiler/jni/quick/arm/calling_convention_arm.cc
@@ -21,14 +21,11 @@
 #include "arch/arm/jni_frame_arm.h"
 #include "arch/instruction_set.h"
 #include "base/macros.h"
-#include "handle_scope-inl.h"
 #include "utils/arm/managed_register_arm.h"
 
 namespace art {
 namespace arm {
 
-static_assert(kArmPointerSize == PointerSize::k32, "Unexpected ARM pointer size");
-
 //
 // JNI calling convention constants.
 //
@@ -49,18 +46,21 @@
 static const Register kHFCoreArgumentRegisters[] = {
   R0, R1, R2, R3
 };
+static constexpr size_t kHFCoreArgumentRegistersCount = arraysize(kHFCoreArgumentRegisters);
 
 // (VFP single-precision registers.)
 static const SRegister kHFSArgumentRegisters[] = {
   S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15
 };
+static constexpr size_t kHFSArgumentRegistersCount = arraysize(kHFSArgumentRegisters);
 
 // (VFP double-precision registers.)
 static const DRegister kHFDArgumentRegisters[] = {
   D0, D1, D2, D3, D4, D5, D6, D7
 };
+static constexpr size_t kHFDArgumentRegistersCount = arraysize(kHFDArgumentRegisters);
 
-static_assert(arraysize(kHFDArgumentRegisters) * 2 == arraysize(kHFSArgumentRegisters),
+static_assert(kHFDArgumentRegistersCount * 2 == kHFSArgumentRegistersCount,
     "ks d argument registers mismatch");
 
 //
@@ -159,14 +159,6 @@
 
 // Calling convention
 
-ManagedRegister ArmManagedRuntimeCallingConvention::InterproceduralScratchRegister() const {
-  return ArmManagedRegister::FromCoreRegister(IP);  // R12
-}
-
-ManagedRegister ArmJniCallingConvention::InterproceduralScratchRegister() const {
-  return ArmManagedRegister::FromCoreRegister(IP);  // R12
-}
-
 ManagedRegister ArmManagedRuntimeCallingConvention::ReturnRegister() {
   switch (GetShorty()[0]) {
     case 'V':
@@ -204,93 +196,93 @@
   return ArmManagedRegister::FromCoreRegister(R0);
 }
 
+void ArmManagedRuntimeCallingConvention::ResetIterator(FrameOffset displacement) {
+  ManagedRuntimeCallingConvention::ResetIterator(displacement);
+  gpr_index_ = 1u;  // Skip r0 for ArtMethod*
+  float_index_ = 0u;
+  double_index_ = 0u;
+}
+
+void ArmManagedRuntimeCallingConvention::Next() {
+  if (IsCurrentParamAFloatOrDouble()) {
+    if (float_index_ % 2 == 0) {
+      // The register for the current float is the same as the first register for double.
+      DCHECK_EQ(float_index_, double_index_ * 2u);
+    } else {
+      // There is a space for an extra float before space for a double.
+      DCHECK_LT(float_index_, double_index_ * 2u);
+    }
+    if (IsCurrentParamADouble()) {
+      double_index_ += 1u;
+      if (float_index_ % 2 == 0) {
+        float_index_ = double_index_ * 2u;
+      }
+    } else {
+      if (float_index_ % 2 == 0) {
+        float_index_ += 1u;
+        double_index_ += 1u;  // Leaves space for one more float before the next double.
+      } else {
+        float_index_ = double_index_ * 2u;
+      }
+    }
+  } else {  // Not a float/double.
+    if (IsCurrentParamALong()) {
+      // Note that the alignment to even register is done lazily.
+      gpr_index_ = RoundUp(gpr_index_, 2u) + 2u;
+    } else {
+      gpr_index_ += 1u;
+    }
+  }
+  ManagedRuntimeCallingConvention::Next();
+}
+
 bool ArmManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
-  return false;  // Everything moved to stack on entry.
+  if (IsCurrentParamAFloatOrDouble()) {
+    if (IsCurrentParamADouble()) {
+      return double_index_ < kHFDArgumentRegistersCount;
+    } else {
+      return float_index_ < kHFSArgumentRegistersCount;
+    }
+  } else {
+    if (IsCurrentParamALong()) {
+      // Round up to even register and do not split a long between the last register and the stack.
+      return RoundUp(gpr_index_, 2u) + 1u < kHFCoreArgumentRegistersCount;
+    } else {
+      return gpr_index_ < kHFCoreArgumentRegistersCount;
+    }
+  }
 }
 
 bool ArmManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
-  return true;
+  return !IsCurrentParamInRegister();
 }
 
 ManagedRegister ArmManagedRuntimeCallingConvention::CurrentParamRegister() {
-  LOG(FATAL) << "Should not reach here";
-  UNREACHABLE();
+  DCHECK(IsCurrentParamInRegister());
+  if (IsCurrentParamAFloatOrDouble()) {
+    if (IsCurrentParamADouble()) {
+      return ArmManagedRegister::FromDRegister(kHFDArgumentRegisters[double_index_]);
+    } else {
+      return ArmManagedRegister::FromSRegister(kHFSArgumentRegisters[float_index_]);
+    }
+  } else {
+    if (IsCurrentParamALong()) {
+      // Currently the only register pair for a long parameter is r2-r3.
+      // Note that the alignment to even register is done lazily.
+      CHECK_EQ(RoundUp(gpr_index_, 2u), 2u);
+      return ArmManagedRegister::FromRegisterPair(R2_R3);
+    } else {
+      return ArmManagedRegister::FromCoreRegister(kHFCoreArgumentRegisters[gpr_index_]);
+    }
+  }
 }
 
 FrameOffset ArmManagedRuntimeCallingConvention::CurrentParamStackOffset() {
-  CHECK(IsCurrentParamOnStack());
   return FrameOffset(displacement_.Int32Value() +        // displacement
                      kFramePointerSize +                 // Method*
                      (itr_slots_ * kFramePointerSize));  // offset into in args
 }
 
-const ManagedRegisterEntrySpills& ArmManagedRuntimeCallingConvention::EntrySpills() {
-  // We spill the argument registers on ARM to free them up for scratch use, we then assume
-  // all arguments are on the stack.
-  if ((entry_spills_.size() == 0) && (NumArgs() > 0)) {
-    uint32_t gpr_index = 1;  // R0 ~ R3. Reserve r0 for ArtMethod*.
-    uint32_t fpr_index = 0;  // S0 ~ S15.
-    uint32_t fpr_double_index = 0;  // D0 ~ D7.
-
-    ResetIterator(FrameOffset(0));
-    while (HasNext()) {
-      if (IsCurrentParamAFloatOrDouble()) {
-        if (IsCurrentParamADouble()) {  // Double.
-          // Double should not overlap with float.
-          fpr_double_index = (std::max(fpr_double_index * 2, RoundUp(fpr_index, 2))) / 2;
-          if (fpr_double_index < arraysize(kHFDArgumentRegisters)) {
-            entry_spills_.push_back(
-                ArmManagedRegister::FromDRegister(kHFDArgumentRegisters[fpr_double_index++]));
-          } else {
-            entry_spills_.push_back(ManagedRegister::NoRegister(), 8);
-          }
-        } else {  // Float.
-          // Float should not overlap with double.
-          if (fpr_index % 2 == 0) {
-            fpr_index = std::max(fpr_double_index * 2, fpr_index);
-          }
-          if (fpr_index < arraysize(kHFSArgumentRegisters)) {
-            entry_spills_.push_back(
-                ArmManagedRegister::FromSRegister(kHFSArgumentRegisters[fpr_index++]));
-          } else {
-            entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
-          }
-        }
-      } else {
-        // FIXME: Pointer this returns as both reference and long.
-        if (IsCurrentParamALong() && !IsCurrentParamAReference()) {  // Long.
-          if (gpr_index < arraysize(kHFCoreArgumentRegisters) - 1) {
-            // Skip R1, and use R2_R3 if the long is the first parameter.
-            if (gpr_index == 1) {
-              gpr_index++;
-            }
-          }
-
-          // If it spans register and memory, we must use the value in memory.
-          if (gpr_index < arraysize(kHFCoreArgumentRegisters) - 1) {
-            entry_spills_.push_back(
-                ArmManagedRegister::FromCoreRegister(kHFCoreArgumentRegisters[gpr_index++]));
-          } else if (gpr_index == arraysize(kHFCoreArgumentRegisters) - 1) {
-            gpr_index++;
-            entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
-          } else {
-            entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
-          }
-        }
-        // High part of long or 32-bit argument.
-        if (gpr_index < arraysize(kHFCoreArgumentRegisters)) {
-          entry_spills_.push_back(
-              ArmManagedRegister::FromCoreRegister(kHFCoreArgumentRegisters[gpr_index++]));
-        } else {
-          entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
-        }
-      }
-      Next();
-    }
-  }
-  return entry_spills_;
-}
-
 // JNI calling convention
 
 ArmJniCallingConvention::ArmJniCallingConvention(bool is_static,
@@ -393,6 +385,13 @@
   return is_critical_native_ ? 0u : kFpCalleeSpillMask;
 }
 
+ManagedRegister ArmJniCallingConvention::SavedLocalReferenceCookieRegister() const {
+  // The r5 is callee-save register in both managed and native ABIs.
+  // It is saved in the stack frame and it has no special purpose like `tr`.
+  static_assert((kCoreCalleeSpillMask & (1u << R5)) != 0u);  // Managed callee save register.
+  return ArmManagedRegister::FromCoreRegister(R5);
+}
+
 ManagedRegister ArmJniCallingConvention::ReturnScratchRegister() const {
   return ArmManagedRegister::FromCoreRegister(R2);
 }
@@ -401,33 +400,36 @@
   if (UNLIKELY(is_critical_native_)) {
     CHECK(!SpillsMethod());
     CHECK(!HasLocalReferenceSegmentState());
-    CHECK(!HasHandleScope());
     CHECK(!SpillsReturnValue());
     return 0u;  // There is no managed frame for @CriticalNative.
   }
 
   // Method*, callee save area size, local reference segment state
-  CHECK(SpillsMethod());
+  DCHECK(SpillsMethod());
   const size_t method_ptr_size = static_cast<size_t>(kArmPointerSize);
   const size_t callee_save_area_size = CalleeSaveRegisters().size() * kFramePointerSize;
   size_t total_size = method_ptr_size + callee_save_area_size;
 
-  CHECK(HasLocalReferenceSegmentState());
-  // local reference segment state
-  total_size += kFramePointerSize;
-  // TODO: Probably better to use sizeof(IRTSegmentState) here...
-
-  CHECK(HasHandleScope());
-  total_size += HandleScope::SizeOf(kArmPointerSize, ReferenceCount());
+  DCHECK(HasLocalReferenceSegmentState());
+  // Cookie is saved in one of the spilled registers.
 
   // Plus return value spill area size
-  CHECK(SpillsReturnValue());
-  total_size += SizeOfReturnValue();
+  if (SpillsReturnValue()) {
+    // For 64-bit return values there shall be a 4B alignment gap between
+    // the method pointer and the saved return value.
+    size_t padding = ReturnValueSaveLocation().SizeValue() - method_ptr_size;
+    DCHECK_EQ(padding,
+              (GetReturnType() == Primitive::kPrimLong || GetReturnType() == Primitive::kPrimDouble)
+                  ? 4u
+                  : 0u);
+    total_size += padding;
+    total_size += SizeOfReturnValue();
+  }
 
   return RoundUp(total_size, kStackAlignment);
 }
 
-size_t ArmJniCallingConvention::OutArgSize() const {
+size_t ArmJniCallingConvention::OutFrameSize() const {
   // Count param args, including JNIEnv* and jclass*; count 8-byte args twice.
   size_t all_args = NumberOfExtraArgumentsForJni() + NumArgs() + NumLongOrDoubleArgs();
   // Account for arguments passed through r0-r3. (No FP args, AAPCS32 is soft-float.)
@@ -447,7 +449,7 @@
   }
   size_t out_args_size = RoundUp(size, kAapcsStackAlignment);
   if (UNLIKELY(IsCriticalNative())) {
-    DCHECK_EQ(out_args_size, GetCriticalNativeOutArgsSize(GetShorty(), NumArgs() + 1u));
+    DCHECK_EQ(out_args_size, GetCriticalNativeStubFrameSize(GetShorty(), NumArgs() + 1u));
   }
   return out_args_size;
 }
@@ -519,9 +521,9 @@
   CHECK_GE(itr_slots_, kJniArgumentRegisterCount);
   size_t offset =
       displacement_.Int32Value()
-          - OutArgSize()
+          - OutFrameSize()
           + ((itr_slots_ - kJniArgumentRegisterCount) * kFramePointerSize);
-  CHECK_LT(offset, OutArgSize());
+  CHECK_LT(offset, OutFrameSize());
   return FrameOffset(offset);
 }
 
@@ -538,14 +540,13 @@
   DCHECK(std::none_of(kJniArgumentRegisters,
                       kJniArgumentRegisters + std::size(kJniArgumentRegisters),
                       [](Register reg) { return reg == R4; }));
-  DCHECK(!InterproceduralScratchRegister().Equals(ArmManagedRegister::FromCoreRegister(R4)));
   return ArmManagedRegister::FromCoreRegister(R4);
 }
 
 // Whether to use tail call (used only for @CriticalNative).
 bool ArmJniCallingConvention::UseTailCall() const {
   CHECK(IsCriticalNative());
-  return OutArgSize() == 0u;
+  return OutFrameSize() == 0u;
 }
 
 }  // namespace arm
diff --git a/compiler/jni/quick/arm/calling_convention_arm.h b/compiler/jni/quick/arm/calling_convention_arm.h
index e4b86fa..985d971 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.h
+++ b/compiler/jni/quick/arm/calling_convention_arm.h
@@ -29,22 +29,26 @@
       : ManagedRuntimeCallingConvention(is_static,
                                         is_synchronized,
                                         shorty,
-                                        PointerSize::k32) {}
+                                        PointerSize::k32),
+        gpr_index_(1u),  // Skip r0 for ArtMethod*
+        float_index_(0u),
+        double_index_(0u) {}
   ~ArmManagedRuntimeCallingConvention() override {}
   // Calling convention
   ManagedRegister ReturnRegister() override;
-  ManagedRegister InterproceduralScratchRegister() const override;
+  void ResetIterator(FrameOffset displacement) override;
   // Managed runtime calling convention
   ManagedRegister MethodRegister() override;
+  void Next() override;
   bool IsCurrentParamInRegister() override;
   bool IsCurrentParamOnStack() override;
   ManagedRegister CurrentParamRegister() override;
   FrameOffset CurrentParamStackOffset() override;
-  const ManagedRegisterEntrySpills& EntrySpills() override;
 
  private:
-  ManagedRegisterEntrySpills entry_spills_;
-
+  size_t gpr_index_;
+  size_t float_index_;
+  size_t double_index_;
   DISALLOW_COPY_AND_ASSIGN(ArmManagedRuntimeCallingConvention);
 };
 
@@ -58,12 +62,12 @@
   // Calling convention
   ManagedRegister ReturnRegister() override;
   ManagedRegister IntReturnRegister() override;
-  ManagedRegister InterproceduralScratchRegister() const override;
   // JNI calling convention
   void Next() override;  // Override default behavior for AAPCS
   size_t FrameSize() const override;
-  size_t OutArgSize() const override;
+  size_t OutFrameSize() const override;
   ArrayRef<const ManagedRegister> CalleeSaveRegisters() const override;
+  ManagedRegister SavedLocalReferenceCookieRegister() const override;
   ManagedRegister ReturnScratchRegister() const override;
   uint32_t CoreSpillMask() const override;
   uint32_t FpSpillMask() const override;
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.cc b/compiler/jni/quick/arm64/calling_convention_arm64.cc
index 231e140..1a13689 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.cc
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.cc
@@ -20,14 +20,11 @@
 
 #include "arch/arm64/jni_frame_arm64.h"
 #include "arch/instruction_set.h"
-#include "handle_scope-inl.h"
 #include "utils/arm64/managed_register_arm64.h"
 
 namespace art {
 namespace arm64 {
 
-static_assert(kArm64PointerSize == PointerSize::k64, "Unexpected ARM64 pointer size");
-
 static const XRegister kXArgumentRegisters[] = {
   X0, X1, X2, X3, X4, X5, X6, X7
 };
@@ -143,14 +140,6 @@
     CalculateFpCalleeSpillMask(kAapcs64CalleeSaveRegisters);
 
 // Calling convention
-ManagedRegister Arm64ManagedRuntimeCallingConvention::InterproceduralScratchRegister() const {
-  return Arm64ManagedRegister::FromXRegister(IP0);  // X16
-}
-
-ManagedRegister Arm64JniCallingConvention::InterproceduralScratchRegister() const {
-  return Arm64ManagedRegister::FromXRegister(IP0);  // X16
-}
-
 static ManagedRegister ReturnRegisterForShorty(const char* shorty) {
   if (shorty[0] == 'F') {
     return Arm64ManagedRegister::FromSRegister(S0);
@@ -184,73 +173,44 @@
 }
 
 bool Arm64ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
-  return false;  // Everything moved to stack on entry.
+  if (IsCurrentParamAFloatOrDouble()) {
+    return itr_float_and_doubles_ < kMaxFloatOrDoubleRegisterArguments;
+  } else {
+    size_t non_fp_arg_number = itr_args_ - itr_float_and_doubles_;
+    return /* method */ 1u + non_fp_arg_number < kMaxIntLikeRegisterArguments;
+  }
 }
 
 bool Arm64ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
-  return true;
+  return !IsCurrentParamInRegister();
 }
 
 ManagedRegister Arm64ManagedRuntimeCallingConvention::CurrentParamRegister() {
-  LOG(FATAL) << "Should not reach here";
-  UNREACHABLE();
+  DCHECK(IsCurrentParamInRegister());
+  if (IsCurrentParamAFloatOrDouble()) {
+    if (IsCurrentParamADouble()) {
+      return Arm64ManagedRegister::FromDRegister(kDArgumentRegisters[itr_float_and_doubles_]);
+    } else {
+      return Arm64ManagedRegister::FromSRegister(kSArgumentRegisters[itr_float_and_doubles_]);
+    }
+  } else {
+    size_t non_fp_arg_number = itr_args_ - itr_float_and_doubles_;
+    if (IsCurrentParamALong()) {
+      XRegister x_reg = kXArgumentRegisters[/* method */ 1u + non_fp_arg_number];
+      return Arm64ManagedRegister::FromXRegister(x_reg);
+    } else {
+      WRegister w_reg = kWArgumentRegisters[/* method */ 1u + non_fp_arg_number];
+      return Arm64ManagedRegister::FromWRegister(w_reg);
+    }
+  }
 }
 
 FrameOffset Arm64ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
-  CHECK(IsCurrentParamOnStack());
   return FrameOffset(displacement_.Int32Value() +  // displacement
                      kFramePointerSize +  // Method ref
                      (itr_slots_ * sizeof(uint32_t)));  // offset into in args
 }
 
-const ManagedRegisterEntrySpills& Arm64ManagedRuntimeCallingConvention::EntrySpills() {
-  // We spill the argument registers on ARM64 to free them up for scratch use, we then assume
-  // all arguments are on the stack.
-  if ((entry_spills_.size() == 0) && (NumArgs() > 0)) {
-    int gp_reg_index = 1;   // we start from X1/W1, X0 holds ArtMethod*.
-    int fp_reg_index = 0;   // D0/S0.
-
-    // We need to choose the correct register (D/S or X/W) since the managed
-    // stack uses 32bit stack slots.
-    ResetIterator(FrameOffset(0));
-    while (HasNext()) {
-      if (IsCurrentParamAFloatOrDouble()) {  // FP regs.
-          if (fp_reg_index < 8) {
-            if (!IsCurrentParamADouble()) {
-              entry_spills_.push_back(Arm64ManagedRegister::FromSRegister(kSArgumentRegisters[fp_reg_index]));
-            } else {
-              entry_spills_.push_back(Arm64ManagedRegister::FromDRegister(kDArgumentRegisters[fp_reg_index]));
-            }
-            fp_reg_index++;
-          } else {  // just increase the stack offset.
-            if (!IsCurrentParamADouble()) {
-              entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
-            } else {
-              entry_spills_.push_back(ManagedRegister::NoRegister(), 8);
-            }
-          }
-      } else {  // GP regs.
-        if (gp_reg_index < 8) {
-          if (IsCurrentParamALong() && (!IsCurrentParamAReference())) {
-            entry_spills_.push_back(Arm64ManagedRegister::FromXRegister(kXArgumentRegisters[gp_reg_index]));
-          } else {
-            entry_spills_.push_back(Arm64ManagedRegister::FromWRegister(kWArgumentRegisters[gp_reg_index]));
-          }
-          gp_reg_index++;
-        } else {  // just increase the stack offset.
-          if (IsCurrentParamALong() && (!IsCurrentParamAReference())) {
-              entry_spills_.push_back(ManagedRegister::NoRegister(), 8);
-          } else {
-              entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
-          }
-        }
-      }
-      Next();
-    }
-  }
-  return entry_spills_;
-}
-
 // JNI calling convention
 
 Arm64JniCallingConvention::Arm64JniCallingConvention(bool is_static,
@@ -272,6 +232,13 @@
   return is_critical_native_ ? 0u : kFpCalleeSpillMask;
 }
 
+ManagedRegister Arm64JniCallingConvention::SavedLocalReferenceCookieRegister() const {
+  // The w21 is callee-save register in both managed and native ABIs.
+  // It is saved in the stack frame and it has no special purpose like `tr`.
+  static_assert((kCoreCalleeSpillMask & (1u << W21)) != 0u);  // Managed callee save register.
+  return Arm64ManagedRegister::FromWRegister(W21);
+}
+
 ManagedRegister Arm64JniCallingConvention::ReturnScratchRegister() const {
   return ManagedRegister::NoRegister();
 }
@@ -280,44 +247,37 @@
   if (is_critical_native_) {
     CHECK(!SpillsMethod());
     CHECK(!HasLocalReferenceSegmentState());
-    CHECK(!HasHandleScope());
     CHECK(!SpillsReturnValue());
     return 0u;  // There is no managed frame for @CriticalNative.
   }
 
   // Method*, callee save area size, local reference segment state
-  CHECK(SpillsMethod());
+  DCHECK(SpillsMethod());
   size_t method_ptr_size = static_cast<size_t>(kFramePointerSize);
   size_t callee_save_area_size = CalleeSaveRegisters().size() * kFramePointerSize;
   size_t total_size = method_ptr_size + callee_save_area_size;
 
-  CHECK(HasLocalReferenceSegmentState());
-  total_size += sizeof(uint32_t);
-
-  CHECK(HasHandleScope());
-  total_size += HandleScope::SizeOf(kArm64PointerSize, ReferenceCount());
+  DCHECK(HasLocalReferenceSegmentState());
+  // Cookie is saved in one of the spilled registers.
 
   // Plus return value spill area size
-  CHECK(SpillsReturnValue());
-  total_size += SizeOfReturnValue();
+  if (SpillsReturnValue()) {
+    // No padding between the method pointer and the return value on arm64.
+    DCHECK_EQ(ReturnValueSaveLocation().SizeValue(), method_ptr_size);
+    total_size += SizeOfReturnValue();
+  }
 
   return RoundUp(total_size, kStackAlignment);
 }
 
-size_t Arm64JniCallingConvention::OutArgSize() const {
+size_t Arm64JniCallingConvention::OutFrameSize() const {
   // Count param args, including JNIEnv* and jclass*.
   size_t all_args = NumberOfExtraArgumentsForJni() + NumArgs();
   size_t num_fp_args = NumFloatOrDoubleArgs();
   DCHECK_GE(all_args, num_fp_args);
   size_t num_non_fp_args = all_args - num_fp_args;
-  // Account for FP arguments passed through v0-v7.
-  size_t num_stack_fp_args =
-      num_fp_args - std::min(kMaxFloatOrDoubleRegisterArguments, num_fp_args);
-  // Account for other (integer and pointer) arguments passed through GPR (x0-x7).
-  size_t num_stack_non_fp_args =
-      num_non_fp_args - std::min(kMaxIntLikeRegisterArguments, num_non_fp_args);
   // The size of outgoing arguments.
-  size_t size = (num_stack_fp_args + num_stack_non_fp_args) * kFramePointerSize;
+  size_t size = GetNativeOutArgsSize(num_fp_args, num_non_fp_args);
 
   // @CriticalNative can use tail call as all managed callee saves are preserved by AAPCS64.
   static_assert((kCoreCalleeSpillMask & ~kAapcs64CoreCalleeSpillMask) == 0u);
@@ -330,7 +290,7 @@
   }
   size_t out_args_size = RoundUp(size, kAapcs64StackAlignment);
   if (UNLIKELY(IsCriticalNative())) {
-    DCHECK_EQ(out_args_size, GetCriticalNativeOutArgsSize(GetShorty(), NumArgs() + 1u));
+    DCHECK_EQ(out_args_size, GetCriticalNativeStubFrameSize(GetShorty(), NumArgs() + 1u));
   }
   return out_args_size;
 }
@@ -394,8 +354,8 @@
                              static_cast<size_t>(itr_float_and_doubles_))
                   - std::min(kMaxIntLikeRegisterArguments,
                              static_cast<size_t>(itr_args_ - itr_float_and_doubles_));
-  size_t offset = displacement_.Int32Value() - OutArgSize() + (args_on_stack * kFramePointerSize);
-  CHECK_LT(offset, OutArgSize());
+  size_t offset = displacement_.Int32Value() - OutFrameSize() + (args_on_stack * kFramePointerSize);
+  CHECK_LT(offset, OutFrameSize());
   return FrameOffset(offset);
 }
 
@@ -411,14 +371,13 @@
   DCHECK(std::none_of(kXArgumentRegisters,
                       kXArgumentRegisters + std::size(kXArgumentRegisters),
                       [](XRegister reg) { return reg == X15; }));
-  DCHECK(!InterproceduralScratchRegister().Equals(Arm64ManagedRegister::FromXRegister(X15)));
   return Arm64ManagedRegister::FromXRegister(X15);
 }
 
 // Whether to use tail call (used only for @CriticalNative).
 bool Arm64JniCallingConvention::UseTailCall() const {
   CHECK(IsCriticalNative());
-  return OutArgSize() == 0u;
+  return OutFrameSize() == 0u;
 }
 
 }  // namespace arm64
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.h b/compiler/jni/quick/arm64/calling_convention_arm64.h
index 64b29f1..e1e9407 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.h
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.h
@@ -33,18 +33,14 @@
   ~Arm64ManagedRuntimeCallingConvention() override {}
   // Calling convention
   ManagedRegister ReturnRegister() override;
-  ManagedRegister InterproceduralScratchRegister() const override;
   // Managed runtime calling convention
   ManagedRegister MethodRegister() override;
   bool IsCurrentParamInRegister() override;
   bool IsCurrentParamOnStack() override;
   ManagedRegister CurrentParamRegister() override;
   FrameOffset CurrentParamStackOffset() override;
-  const ManagedRegisterEntrySpills& EntrySpills() override;
 
  private:
-  ManagedRegisterEntrySpills entry_spills_;
-
   DISALLOW_COPY_AND_ASSIGN(Arm64ManagedRuntimeCallingConvention);
 };
 
@@ -58,11 +54,11 @@
   // Calling convention
   ManagedRegister ReturnRegister() override;
   ManagedRegister IntReturnRegister() override;
-  ManagedRegister InterproceduralScratchRegister() const override;
   // JNI calling convention
   size_t FrameSize() const override;
-  size_t OutArgSize() const override;
+  size_t OutFrameSize() const override;
   ArrayRef<const ManagedRegister> CalleeSaveRegisters() const override;
+  ManagedRegister SavedLocalReferenceCookieRegister() const override;
   ManagedRegister ReturnScratchRegister() const override;
   uint32_t CoreSpillMask() const override;
   uint32_t FpSpillMask() const override;
diff --git a/compiler/jni/quick/calling_convention.cc b/compiler/jni/quick/calling_convention.cc
index 1943756..fd05941 100644
--- a/compiler/jni/quick/calling_convention.cc
+++ b/compiler/jni/quick/calling_convention.cc
@@ -19,6 +19,7 @@
 #include <android-base/logging.h>
 
 #include "arch/instruction_set.h"
+#include "indirect_reference_table.h"
 
 #ifdef ART_ENABLE_CODEGEN_arm
 #include "jni/quick/arm/calling_convention_arm.h"
@@ -172,26 +173,17 @@
   return NumReferenceArgs() + (IsStatic() ? 1 : 0);
 }
 
-FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
-  size_t references_size = handle_scope_pointer_size_ * ReferenceCount();  // size excluding header
-  return FrameOffset(HandleReferencesOffset().Int32Value() + references_size);
-}
-
 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
-  if (LIKELY(HasHandleScope())) {
-    // Initial offset already includes the displacement.
-    // -- Remove the additional local reference cookie offset if we don't have a handle scope.
-    const size_t saved_local_reference_cookie_offset =
-        SavedLocalReferenceCookieOffset().Int32Value();
-    // Segment state is 4 bytes long
-    const size_t segment_state_size = 4;
-    return FrameOffset(saved_local_reference_cookie_offset + segment_state_size);
-  } else {
-    // Include only the initial Method* as part of the offset.
-    CHECK_LT(displacement_.SizeValue(),
-             static_cast<size_t>(std::numeric_limits<int32_t>::max()));
-    return FrameOffset(displacement_.Int32Value() + static_cast<size_t>(frame_pointer_size_));
+  // The saved return value goes at a properly aligned slot after the method pointer.
+  DCHECK(SpillsReturnValue());
+  size_t return_value_offset = static_cast<size_t>(frame_pointer_size_);
+  const size_t return_value_size = SizeOfReturnValue();
+  DCHECK(return_value_size == 4u || return_value_size == 8u) << return_value_size;
+  DCHECK_ALIGNED(return_value_offset, 4u);
+  if (return_value_size == 8u) {
+    return_value_offset = RoundUp(return_value_offset, 8u);
   }
+  return FrameOffset(displacement_.SizeValue() + return_value_offset);
 }
 
 bool JniCallingConvention::HasNext() {
@@ -285,16 +277,6 @@
   }
 }
 
-// Return position of handle scope entry holding reference at the current iterator
-// position
-FrameOffset JniCallingConvention::CurrentParamHandleScopeEntryOffset() {
-  CHECK(IsCurrentParamAReference());
-  CHECK_LT(HandleScopeLinkOffset(), HandleScopeNumRefsOffset());
-  int result = HandleReferencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_;
-  CHECK_GT(result, HandleScopeNumRefsOffset().Int32Value());
-  return FrameOffset(result);
-}
-
 size_t JniCallingConvention::CurrentParamSize() const {
   if (IsCurrentArgExtraForJni()) {
     return static_cast<size_t>(frame_pointer_size_);  // JNIEnv or jobject/jclass
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h
index 3d4cefe..c11e09d 100644
--- a/compiler/jni/quick/calling_convention.h
+++ b/compiler/jni/quick/calling_convention.h
@@ -21,7 +21,6 @@
 #include "base/array_ref.h"
 #include "base/enums.h"
 #include "dex/primitive.h"
-#include "handle_scope.h"
 #include "thread.h"
 #include "utils/managed_register.h"
 
@@ -48,15 +47,13 @@
 
   // Register that holds result of this method invocation.
   virtual ManagedRegister ReturnRegister() = 0;
-  // Register reserved for scratch usage during procedure calls.
-  virtual ManagedRegister InterproceduralScratchRegister() const = 0;
 
   // Iterator interface
 
   // Place iterator at start of arguments. The displacement is applied to
   // frame offset methods to account for frames which may be on the stack
   // below the one being iterated over.
-  void ResetIterator(FrameOffset displacement) {
+  virtual void ResetIterator(FrameOffset displacement) {
     displacement_ = displacement;
     itr_slots_ = 0;
     itr_args_ = 0;
@@ -83,7 +80,6 @@
       : itr_slots_(0), itr_refs_(0), itr_args_(0), itr_longs_and_doubles_(0),
         itr_float_and_doubles_(0), displacement_(0),
         frame_pointer_size_(frame_pointer_size),
-        handle_scope_pointer_size_(sizeof(StackReference<mirror::Object>)),
         is_static_(is_static), is_synchronized_(is_synchronized),
         shorty_(shorty) {
     num_args_ = (is_static ? 0 : 1) + strlen(shorty) - 1;
@@ -213,8 +209,6 @@
   FrameOffset displacement_;
   // The size of a pointer.
   const PointerSize frame_pointer_size_;
-  // The size of a reference entry within the handle scope.
-  const size_t handle_scope_pointer_size_;
 
  private:
   const bool is_static_;
@@ -252,11 +246,14 @@
 
   // Iterator interface
   bool HasNext();
-  void Next();
+  virtual void Next();
   bool IsCurrentParamAReference();
   bool IsCurrentParamAFloatOrDouble();
   bool IsCurrentParamADouble();
   bool IsCurrentParamALong();
+  bool IsCurrentParamALongOrDouble() {
+    return IsCurrentParamALong() || IsCurrentParamADouble();
+  }
   bool IsCurrentArgExplicit();  // ie a non-implict argument such as this
   bool IsCurrentArgPossiblyNull();
   size_t CurrentParamSize();
@@ -267,9 +264,6 @@
 
   virtual ~ManagedRuntimeCallingConvention() {}
 
-  // Registers to spill to caller's out registers on entry.
-  virtual const ManagedRegisterEntrySpills& EntrySpills() = 0;
-
  protected:
   ManagedRuntimeCallingConvention(bool is_static,
                                   bool is_synchronized,
@@ -305,13 +299,11 @@
   // always at the bottom of a frame, but this doesn't work for outgoing
   // native args). Includes alignment.
   virtual size_t FrameSize() const = 0;
-  // Size of outgoing arguments (stack portion), including alignment.
+  // Size of outgoing frame, i.e. stack arguments, @CriticalNative return PC if needed, alignment.
   // -- Arguments that are passed via registers are excluded from this size.
-  virtual size_t OutArgSize() const = 0;
+  virtual size_t OutFrameSize() const = 0;
   // Number of references in stack indirect reference table
   size_t ReferenceCount() const;
-  // Location where the segment state of the local indirect reference table is saved
-  FrameOffset SavedLocalReferenceCookieOffset() const;
   // Location where the return value of a call can be squirreled if another
   // call is made following the native call
   FrameOffset ReturnValueSaveLocation() const;
@@ -323,13 +315,17 @@
   // Callee save registers to spill prior to native code (which may clobber)
   virtual ArrayRef<const ManagedRegister> CalleeSaveRegisters() const = 0;
 
-  // Spill mask values
-  virtual uint32_t CoreSpillMask() const = 0;
-  virtual uint32_t FpSpillMask() const = 0;
+  // Register where the segment state of the local indirect reference table is saved.
+  // This must be a native callee-save register without another special purpose.
+  virtual ManagedRegister SavedLocalReferenceCookieRegister() const = 0;
 
   // An extra scratch register live after the call
   virtual ManagedRegister ReturnScratchRegister() const = 0;
 
+  // Spill mask values
+  virtual uint32_t CoreSpillMask() const = 0;
+  virtual uint32_t FpSpillMask() const = 0;
+
   // Iterator interface
   bool HasNext();
   virtual void Next();
@@ -347,32 +343,12 @@
   virtual ManagedRegister CurrentParamRegister() = 0;
   virtual FrameOffset CurrentParamStackOffset() = 0;
 
-  // Iterator interface extension for JNI
-  FrameOffset CurrentParamHandleScopeEntryOffset();
-
-  // Position of handle scope and interior fields
-  FrameOffset HandleScopeOffset() const {
-    return FrameOffset(this->displacement_.Int32Value() + static_cast<size_t>(frame_pointer_size_));
-    // above Method reference
-  }
-
-  FrameOffset HandleScopeLinkOffset() const {
-    return FrameOffset(HandleScopeOffset().Int32Value() +
-                       HandleScope::LinkOffset(frame_pointer_size_));
-  }
-
-  FrameOffset HandleScopeNumRefsOffset() const {
-    return FrameOffset(HandleScopeOffset().Int32Value() +
-                       HandleScope::NumberOfReferencesOffset(frame_pointer_size_));
-  }
-
-  FrameOffset HandleReferencesOffset() const {
-    return FrameOffset(HandleScopeOffset().Int32Value() +
-                       HandleScope::ReferencesOffset(frame_pointer_size_));
-  }
-
   virtual ~JniCallingConvention() {}
 
+  static constexpr size_t SavedLocalReferenceCookieSize() {
+    return 4u;
+  }
+
   bool IsCriticalNative() const {
     return is_critical_native_;
   }
@@ -399,6 +375,13 @@
            return_type == Primitive::kPrimChar;
   }
 
+  // Does the transition back spill the return value in the stack frame?
+  bool SpillsReturnValue() const {
+    // Exclude return value for @CriticalNative methods for optimization speed.
+    // References are passed directly to the "end method" and there is nothing to save for `void`.
+    return !IsCriticalNative() && !IsReturnAReference() && SizeOfReturnValue() != 0u;
+  }
+
  protected:
   // Named iterator positions
   enum IteratorPos {
@@ -417,24 +400,12 @@
  protected:
   size_t NumberOfExtraArgumentsForJni() const;
 
-  // Does the transition have a StackHandleScope?
-  bool HasHandleScope() const {
-    // Exclude HandleScope for @CriticalNative methods for optimization speed.
-    return !IsCriticalNative();
-  }
-
   // Does the transition have a local reference segment state?
   bool HasLocalReferenceSegmentState() const {
     // Exclude local reference segment states for @CriticalNative methods for optimization speed.
     return !IsCriticalNative();
   }
 
-  // Does the transition back spill the return value in the stack frame?
-  bool SpillsReturnValue() const {
-    // Exclude return value for @CriticalNative methods for optimization speed.
-    return !IsCriticalNative();
-  }
-
   // Are there extra JNI arguments (JNIEnv* and maybe jclass)?
   bool HasExtraArgumentsForJni() const {
     // @CriticalNative jni implementations exclude both JNIEnv* and the jclass/jobject parameters.
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index c2db73a..cdd0263 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -24,6 +24,7 @@
 
 #include "art_method.h"
 #include "base/arena_allocator.h"
+#include "base/arena_containers.h"
 #include "base/enums.h"
 #include "base/logging.h"  // For VLOG.
 #include "base/macros.h"
@@ -219,84 +220,27 @@
   // 1. Build the frame saving all callee saves, Method*, and PC return address.
   //    For @CriticalNative, this includes space for out args, otherwise just the managed frame.
   const size_t managed_frame_size = main_jni_conv->FrameSize();
-  const size_t main_out_arg_size = main_jni_conv->OutArgSize();
+  const size_t main_out_arg_size = main_jni_conv->OutFrameSize();
   size_t current_frame_size = is_critical_native ? main_out_arg_size : managed_frame_size;
   ManagedRegister method_register =
       is_critical_native ? ManagedRegister::NoRegister() : mr_conv->MethodRegister();
   ArrayRef<const ManagedRegister> callee_save_regs = main_jni_conv->CalleeSaveRegisters();
-  __ BuildFrame(current_frame_size, method_register, callee_save_regs, mr_conv->EntrySpills());
+  __ BuildFrame(current_frame_size, method_register, callee_save_regs);
   DCHECK_EQ(jni_asm->cfi().GetCurrentCFAOffset(), static_cast<int>(current_frame_size));
 
   if (LIKELY(!is_critical_native)) {
-    // NOTE: @CriticalNative methods don't have a HandleScope
-    //       because they can't have any reference parameters or return values.
-
-    // 2. Set up the HandleScope
+    // Spill all register arguments.
+    // TODO: Pass these in a single call to let the assembler use multi-register stores.
+    // TODO: Spill native stack args straight to their stack locations (adjust SP earlier).
     mr_conv->ResetIterator(FrameOffset(current_frame_size));
-    main_jni_conv->ResetIterator(FrameOffset(0));
-    __ StoreImmediateToFrame(main_jni_conv->HandleScopeNumRefsOffset(),
-                             main_jni_conv->ReferenceCount(),
-                             mr_conv->InterproceduralScratchRegister());
-
-    __ CopyRawPtrFromThread(main_jni_conv->HandleScopeLinkOffset(),
-                            Thread::TopHandleScopeOffset<kPointerSize>(),
-                            mr_conv->InterproceduralScratchRegister());
-    __ StoreStackOffsetToThread(Thread::TopHandleScopeOffset<kPointerSize>(),
-                                main_jni_conv->HandleScopeOffset(),
-                                mr_conv->InterproceduralScratchRegister());
-
-    // 3. Place incoming reference arguments into handle scope
-    main_jni_conv->Next();  // Skip JNIEnv*
-    // 3.5. Create Class argument for static methods out of passed method
-    if (is_static) {
-      FrameOffset handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset();
-      // Check handle scope offset is within frame
-      CHECK_LT(handle_scope_offset.Uint32Value(), current_frame_size);
-      // Note this LoadRef() doesn't need heap unpoisoning since it's from the ArtMethod.
-      // Note this LoadRef() does not include read barrier. It will be handled below.
-      //
-      // scratchRegister = *method[DeclaringClassOffset()];
-      __ LoadRef(main_jni_conv->InterproceduralScratchRegister(),
-                 mr_conv->MethodRegister(), ArtMethod::DeclaringClassOffset(), false);
-      __ VerifyObject(main_jni_conv->InterproceduralScratchRegister(), false);
-      // *handleScopeOffset = scratchRegister
-      __ StoreRef(handle_scope_offset, main_jni_conv->InterproceduralScratchRegister());
-      main_jni_conv->Next();  // in handle scope so move to next argument
-    }
-    // Place every reference into the handle scope (ignore other parameters).
-    while (mr_conv->HasNext()) {
-      CHECK(main_jni_conv->HasNext());
-      bool ref_param = main_jni_conv->IsCurrentParamAReference();
-      CHECK(!ref_param || mr_conv->IsCurrentParamAReference());
-      // References need placing in handle scope and the entry value passing
-      if (ref_param) {
-        // Compute handle scope entry, note null is placed in the handle scope but its boxed value
-        // must be null.
-        FrameOffset handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset();
-        // Check handle scope offset is within frame and doesn't run into the saved segment state.
-        CHECK_LT(handle_scope_offset.Uint32Value(), current_frame_size);
-        CHECK_NE(handle_scope_offset.Uint32Value(),
-                 main_jni_conv->SavedLocalReferenceCookieOffset().Uint32Value());
-        bool input_in_reg = mr_conv->IsCurrentParamInRegister();
-        bool input_on_stack = mr_conv->IsCurrentParamOnStack();
-        CHECK(input_in_reg || input_on_stack);
-
-        if (input_in_reg) {
-          ManagedRegister in_reg  =  mr_conv->CurrentParamRegister();
-          __ VerifyObject(in_reg, mr_conv->IsCurrentArgPossiblyNull());
-          __ StoreRef(handle_scope_offset, in_reg);
-        } else if (input_on_stack) {
-          FrameOffset in_off  = mr_conv->CurrentParamStackOffset();
-          __ VerifyObject(in_off, mr_conv->IsCurrentArgPossiblyNull());
-          __ CopyRef(handle_scope_offset, in_off,
-                     mr_conv->InterproceduralScratchRegister());
-        }
+    for (; mr_conv->HasNext(); mr_conv->Next()) {
+      if (mr_conv->IsCurrentParamInRegister()) {
+        size_t size = mr_conv->IsCurrentParamALongOrDouble() ? 8u : 4u;
+        __ Store(mr_conv->CurrentParamStackOffset(), mr_conv->CurrentParamRegister(), size);
       }
-      mr_conv->Next();
-      main_jni_conv->Next();
     }
 
-    // 4. Write out the end of the quick frames.
+    // 2. Write out the end of the quick frames.
     __ StoreStackPointerToThread(Thread::TopOfManagedStackOffset<kPointerSize>());
 
     // NOTE: @CriticalNative does not need to store the stack pointer to the thread
@@ -305,88 +249,37 @@
     //       (TODO: We could probably disable it for @FastNative too).
   }  // if (!is_critical_native)
 
-  // 5. Move frame down to allow space for out going args.
+  // 3. Move frame down to allow space for out going args.
   size_t current_out_arg_size = main_out_arg_size;
   if (UNLIKELY(is_critical_native)) {
     DCHECK_EQ(main_out_arg_size, current_frame_size);
-    // Move the method pointer to the hidden argument register.
-    __ Move(main_jni_conv->HiddenArgumentRegister(),
-            mr_conv->MethodRegister(),
-            static_cast<size_t>(main_jni_conv->GetFramePointerSize()));
   } else {
     __ IncreaseFrameSize(main_out_arg_size);
     current_frame_size += main_out_arg_size;
   }
 
-  // Call the read barrier for the declaring class loaded from the method for a static call.
-  // Skip this for @CriticalNative because we didn't build a HandleScope to begin with.
-  // Note that we always have outgoing param space available for at least two params.
+  // 4. Check if we need to go to the slow path to emit the read barrier for the declaring class
+  //    in the method for a static call.
+  //    Skip this for @CriticalNative because we're not passing a `jclass` to the native method.
+  std::unique_ptr<JNIMacroLabel> jclass_read_barrier_slow_path;
+  std::unique_ptr<JNIMacroLabel> jclass_read_barrier_return;
   if (kUseReadBarrier && is_static && !is_critical_native) {
-    const bool kReadBarrierFastPath = true;  // Always true after Mips codegen was removed.
-    std::unique_ptr<JNIMacroLabel> skip_cold_path_label;
-    if (kReadBarrierFastPath) {
-      skip_cold_path_label = __ CreateLabel();
-      // Fast path for supported targets.
-      //
-      // Check if gc_is_marking is set -- if it's not, we don't need
-      // a read barrier so skip it.
-      __ LoadFromThread(main_jni_conv->InterproceduralScratchRegister(),
-                        Thread::IsGcMarkingOffset<kPointerSize>(),
-                        Thread::IsGcMarkingSize());
-      // Jump over the slow path if gc is marking is false.
-      __ Jump(skip_cold_path_label.get(),
-              JNIMacroUnaryCondition::kZero,
-              main_jni_conv->InterproceduralScratchRegister());
-    }
+    jclass_read_barrier_slow_path = __ CreateLabel();
+    jclass_read_barrier_return = __ CreateLabel();
 
-    // Construct slow path for read barrier:
-    //
-    // Call into the runtime's ReadBarrierJni and have it fix up
-    // the object address if it was moved.
+    // Check if gc_is_marking is set -- if it's not, we don't need a read barrier.
+    __ TestGcMarking(jclass_read_barrier_slow_path.get(), JNIMacroUnaryCondition::kNotZero);
 
-    ThreadOffset<kPointerSize> read_barrier = QUICK_ENTRYPOINT_OFFSET(kPointerSize,
-                                                                      pReadBarrierJni);
-    main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
-    main_jni_conv->Next();  // Skip JNIEnv.
-    FrameOffset class_handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset();
-    main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
-    // Pass the handle for the class as the first argument.
-    if (main_jni_conv->IsCurrentParamOnStack()) {
-      FrameOffset out_off = main_jni_conv->CurrentParamStackOffset();
-      __ CreateHandleScopeEntry(out_off, class_handle_scope_offset,
-                         mr_conv->InterproceduralScratchRegister(),
-                         false);
-    } else {
-      ManagedRegister out_reg = main_jni_conv->CurrentParamRegister();
-      __ CreateHandleScopeEntry(out_reg, class_handle_scope_offset,
-                         ManagedRegister::NoRegister(), false);
-    }
-    main_jni_conv->Next();
-    // Pass the current thread as the second argument and call.
-    if (main_jni_conv->IsCurrentParamInRegister()) {
-      __ GetCurrentThread(main_jni_conv->CurrentParamRegister());
-      __ Call(main_jni_conv->CurrentParamRegister(),
-              Offset(read_barrier),
-              main_jni_conv->InterproceduralScratchRegister());
-    } else {
-      __ GetCurrentThread(main_jni_conv->CurrentParamStackOffset(),
-                          main_jni_conv->InterproceduralScratchRegister());
-      __ CallFromThread(read_barrier, main_jni_conv->InterproceduralScratchRegister());
-    }
-    main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));  // Reset.
-
-    if (kReadBarrierFastPath) {
-      __ Bind(skip_cold_path_label.get());
-    }
+    // If marking, the slow path returns after the check.
+    __ Bind(jclass_read_barrier_return.get());
   }
 
-  // 6. Call into appropriate JniMethodStart passing Thread* so that transition out of Runnable
+  // 5. Call into appropriate JniMethodStart passing Thread* so that transition out of Runnable
   //    can occur. The result is the saved JNI local state that is restored by the exit call. We
   //    abuse the JNI calling convention here, that is guaranteed to support passing 2 pointer
   //    arguments.
-  FrameOffset locked_object_handle_scope_offset(0xBEEFDEAD);
-  FrameOffset saved_cookie_offset(
-      FrameOffset(0xDEADBEEFu));  // @CriticalNative - use obviously bad value for debugging
+  constexpr size_t cookie_size = JniCallingConvention::SavedLocalReferenceCookieSize();
+  ManagedRegister saved_cookie_register = ManagedRegister::NoRegister();
   if (LIKELY(!is_critical_native)) {
     // Skip this for @CriticalNative methods. They do not call JniMethodStart.
     ThreadOffset<kPointerSize> jni_start(
@@ -395,112 +288,139 @@
                                                    is_synchronized,
                                                    is_fast_native).SizeValue());
     main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
-    locked_object_handle_scope_offset = FrameOffset(0);
     if (is_synchronized) {
       // Pass object for locking.
-      main_jni_conv->Next();  // Skip JNIEnv.
-      locked_object_handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset();
-      main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
-      if (main_jni_conv->IsCurrentParamOnStack()) {
-        FrameOffset out_off = main_jni_conv->CurrentParamStackOffset();
-        __ CreateHandleScopeEntry(out_off, locked_object_handle_scope_offset,
-                                  mr_conv->InterproceduralScratchRegister(), false);
+      if (is_static) {
+        // Pass the pointer to the method's declaring class as the first argument.
+        DCHECK_EQ(ArtMethod::DeclaringClassOffset().SizeValue(), 0u);
+        SetNativeParameter(jni_asm.get(), main_jni_conv.get(), method_register);
       } else {
-        ManagedRegister out_reg = main_jni_conv->CurrentParamRegister();
-        __ CreateHandleScopeEntry(out_reg, locked_object_handle_scope_offset,
-                                  ManagedRegister::NoRegister(), false);
+        // TODO: Use the register that still holds the `this` reference.
+        mr_conv->ResetIterator(FrameOffset(current_frame_size));
+        FrameOffset this_offset = mr_conv->CurrentParamStackOffset();
+        if (main_jni_conv->IsCurrentParamOnStack()) {
+          FrameOffset out_off = main_jni_conv->CurrentParamStackOffset();
+          __ CreateJObject(out_off, this_offset, /*null_allowed=*/ false);
+        } else {
+          ManagedRegister out_reg = main_jni_conv->CurrentParamRegister();
+          __ CreateJObject(out_reg,
+                           this_offset,
+                           ManagedRegister::NoRegister(),
+                           /*null_allowed=*/ false);
+        }
       }
       main_jni_conv->Next();
     }
     if (main_jni_conv->IsCurrentParamInRegister()) {
       __ GetCurrentThread(main_jni_conv->CurrentParamRegister());
-      __ Call(main_jni_conv->CurrentParamRegister(),
-              Offset(jni_start),
-              main_jni_conv->InterproceduralScratchRegister());
+      __ Call(main_jni_conv->CurrentParamRegister(), Offset(jni_start));
     } else {
-      __ GetCurrentThread(main_jni_conv->CurrentParamStackOffset(),
-                          main_jni_conv->InterproceduralScratchRegister());
-      __ CallFromThread(jni_start, main_jni_conv->InterproceduralScratchRegister());
+      __ GetCurrentThread(main_jni_conv->CurrentParamStackOffset());
+      __ CallFromThread(jni_start);
     }
+    method_register = ManagedRegister::NoRegister();  // Method register is clobbered.
     if (is_synchronized) {  // Check for exceptions from monitor enter.
-      __ ExceptionPoll(main_jni_conv->InterproceduralScratchRegister(), main_out_arg_size);
+      __ ExceptionPoll(main_out_arg_size);
     }
 
     // Store into stack_frame[saved_cookie_offset] the return value of JniMethodStart.
-    saved_cookie_offset = main_jni_conv->SavedLocalReferenceCookieOffset();
-    __ Store(saved_cookie_offset, main_jni_conv->IntReturnRegister(), 4 /* sizeof cookie */);
+    saved_cookie_register = main_jni_conv->SavedLocalReferenceCookieRegister();
+    __ Move(saved_cookie_register, main_jni_conv->IntReturnRegister(), cookie_size);
   }
 
-  // 7. Iterate over arguments placing values from managed calling convention in
-  //    to the convention required for a native call (shuffling). For references
-  //    place an index/pointer to the reference after checking whether it is
-  //    null (which must be encoded as null).
-  //    Note: we do this prior to materializing the JNIEnv* and static's jclass to
-  //    give as many free registers for the shuffle as possible.
-  mr_conv->ResetIterator(FrameOffset(current_frame_size));
-  uint32_t args_count = 0;
-  while (mr_conv->HasNext()) {
-    args_count++;
-    mr_conv->Next();
-  }
-
-  // Do a backward pass over arguments, so that the generated code will be "mov
-  // R2, R3; mov R1, R2" instead of "mov R1, R2; mov R2, R3."
-  // TODO: A reverse iterator to improve readability.
-  // TODO: This is currently useless as all archs spill args when building the frame.
-  //       To avoid the full spilling, we would have to do one pass before the BuildFrame()
-  //       to determine which arg registers are clobbered before they are needed.
-  // TODO: For @CriticalNative, do a forward pass because there are no JNIEnv* and jclass* args.
-  for (uint32_t i = 0; i < args_count; ++i) {
+  // 6. Fill arguments.
+  if (UNLIKELY(is_critical_native)) {
+    ArenaVector<ArgumentLocation> src_args(allocator.Adapter());
+    ArenaVector<ArgumentLocation> dest_args(allocator.Adapter());
+    // Move the method pointer to the hidden argument register.
+    size_t pointer_size = static_cast<size_t>(kPointerSize);
+    dest_args.push_back(ArgumentLocation(main_jni_conv->HiddenArgumentRegister(), pointer_size));
+    src_args.push_back(ArgumentLocation(mr_conv->MethodRegister(), pointer_size));
+    // Move normal arguments to their locations.
     mr_conv->ResetIterator(FrameOffset(current_frame_size));
     main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
+    for (; mr_conv->HasNext(); mr_conv->Next(), main_jni_conv->Next()) {
+      DCHECK(main_jni_conv->HasNext());
+      size_t size = mr_conv->IsCurrentParamALongOrDouble() ? 8u : 4u;
+      src_args.push_back(mr_conv->IsCurrentParamInRegister()
+          ? ArgumentLocation(mr_conv->CurrentParamRegister(), size)
+          : ArgumentLocation(mr_conv->CurrentParamStackOffset(), size));
+      dest_args.push_back(main_jni_conv->IsCurrentParamInRegister()
+          ? ArgumentLocation(main_jni_conv->CurrentParamRegister(), size)
+          : ArgumentLocation(main_jni_conv->CurrentParamStackOffset(), size));
+    }
+    DCHECK(!main_jni_conv->HasNext());
+    __ MoveArguments(ArrayRef<ArgumentLocation>(dest_args), ArrayRef<ArgumentLocation>(src_args));
+  } else {
+    // Iterate over arguments placing values from managed calling convention in
+    // to the convention required for a native call (shuffling). For references
+    // place an index/pointer to the reference after checking whether it is
+    // null (which must be encoded as null).
+    // Note: we do this prior to materializing the JNIEnv* and static's jclass to
+    // give as many free registers for the shuffle as possible.
+    mr_conv->ResetIterator(FrameOffset(current_frame_size));
+    uint32_t args_count = 0;
+    while (mr_conv->HasNext()) {
+      args_count++;
+      mr_conv->Next();
+    }
 
-    // Skip the extra JNI parameters for now.
-    if (LIKELY(!is_critical_native)) {
+    // Do a backward pass over arguments, so that the generated code will be "mov
+    // R2, R3; mov R1, R2" instead of "mov R1, R2; mov R2, R3."
+    // TODO: A reverse iterator to improve readability.
+    // TODO: This is currently useless as all archs spill args when building the frame.
+    //       To avoid the full spilling, we would have to do one pass before the BuildFrame()
+    //       to determine which arg registers are clobbered before they are needed.
+    for (uint32_t i = 0; i < args_count; ++i) {
+      mr_conv->ResetIterator(FrameOffset(current_frame_size));
+      main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
+
+      // Skip the extra JNI parameters for now.
       main_jni_conv->Next();    // Skip JNIEnv*.
       if (is_static) {
         main_jni_conv->Next();  // Skip Class for now.
       }
+      // Skip to the argument we're interested in.
+      for (uint32_t j = 0; j < args_count - i - 1; ++j) {
+        mr_conv->Next();
+        main_jni_conv->Next();
+      }
+      CopyParameter(jni_asm.get(), mr_conv.get(), main_jni_conv.get());
     }
-    // Skip to the argument we're interested in.
-    for (uint32_t j = 0; j < args_count - i - 1; ++j) {
-      mr_conv->Next();
-      main_jni_conv->Next();
-    }
-    CopyParameter(jni_asm.get(), mr_conv.get(), main_jni_conv.get());
-  }
-  if (is_static && !is_critical_native) {
-    // Create argument for Class
-    mr_conv->ResetIterator(FrameOffset(current_frame_size));
-    main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
-    main_jni_conv->Next();  // Skip JNIEnv*
-    FrameOffset handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset();
-    if (main_jni_conv->IsCurrentParamOnStack()) {
-      FrameOffset out_off = main_jni_conv->CurrentParamStackOffset();
-      __ CreateHandleScopeEntry(out_off, handle_scope_offset,
-                         mr_conv->InterproceduralScratchRegister(),
-                         false);
-    } else {
-      ManagedRegister out_reg = main_jni_conv->CurrentParamRegister();
-      __ CreateHandleScopeEntry(out_reg, handle_scope_offset,
-                         ManagedRegister::NoRegister(), false);
-    }
-  }
 
-  // Set the iterator back to the incoming Method*.
-  main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
-  if (LIKELY(!is_critical_native)) {
+    // 7. For static method, create jclass argument as a pointer to the method's declaring class.
+    if (is_static) {
+      main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
+      main_jni_conv->Next();  // Skip JNIEnv*
+      // Load reference to the method's declaring class. The method register has been
+      // clobbered by the above call, so we need to load the method from the stack.
+      FrameOffset method_offset =
+          FrameOffset(current_out_arg_size + mr_conv->MethodStackOffset().SizeValue());
+      DCHECK_EQ(ArtMethod::DeclaringClassOffset().SizeValue(), 0u);
+      if (main_jni_conv->IsCurrentParamOnStack()) {
+        FrameOffset out_off = main_jni_conv->CurrentParamStackOffset();
+        __ Copy(out_off, method_offset, static_cast<size_t>(kPointerSize));
+        // TODO(x86): Get hold of the register used to copy the method pointer,
+        // so that we can use it also for loading the method entrypoint below.
+      } else {
+        ManagedRegister out_reg = main_jni_conv->CurrentParamRegister();
+        __ Load(out_reg, method_offset, static_cast<size_t>(kPointerSize));
+        // Reuse the register also for loading the method entrypoint below.
+        method_register = out_reg;
+      }
+    }
+
+    // Set the iterator back to the incoming Method*.
+    main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
+
     // 8. Create 1st argument, the JNI environment ptr.
     // Register that will hold local indirect reference table
     if (main_jni_conv->IsCurrentParamInRegister()) {
       ManagedRegister jni_env = main_jni_conv->CurrentParamRegister();
-      DCHECK(!jni_env.Equals(main_jni_conv->InterproceduralScratchRegister()));
       __ LoadRawPtrFromThread(jni_env, Thread::JniEnvOffset<kPointerSize>());
     } else {
       FrameOffset jni_env = main_jni_conv->CurrentParamStackOffset();
-      __ CopyRawPtrFromThread(jni_env,
-                              Thread::JniEnvOffset<kPointerSize>(),
-                              main_jni_conv->InterproceduralScratchRegister());
+      __ CopyRawPtrFromThread(jni_env, Thread::JniEnvOffset<kPointerSize>());
     }
   }
 
@@ -509,18 +429,17 @@
       ArtMethod::EntryPointFromJniOffset(InstructionSetPointerSize(instruction_set));
   if (UNLIKELY(is_critical_native)) {
     if (main_jni_conv->UseTailCall()) {
-      __ Jump(main_jni_conv->HiddenArgumentRegister(),
-              jni_entrypoint_offset,
-              main_jni_conv->InterproceduralScratchRegister());
+      __ Jump(main_jni_conv->HiddenArgumentRegister(), jni_entrypoint_offset);
     } else {
-      __ Call(main_jni_conv->HiddenArgumentRegister(),
-              jni_entrypoint_offset,
-              main_jni_conv->InterproceduralScratchRegister());
+      __ Call(main_jni_conv->HiddenArgumentRegister(), jni_entrypoint_offset);
     }
   } else {
-    __ Call(FrameOffset(main_out_arg_size + mr_conv->MethodStackOffset().SizeValue()),
-            jni_entrypoint_offset,
-            main_jni_conv->InterproceduralScratchRegister());
+    if (method_register.IsRegister()) {
+      __ Call(method_register, jni_entrypoint_offset);
+    } else {
+      __ Call(FrameOffset(current_out_arg_size + mr_conv->MethodStackOffset().SizeValue()),
+              jni_entrypoint_offset);
+    }
   }
 
   // 10. Fix differences in result widths.
@@ -540,49 +459,47 @@
   }
 
   // 11. Process return value
-  FrameOffset return_save_location = main_jni_conv->ReturnValueSaveLocation();
-  if (main_jni_conv->SizeOfReturnValue() != 0 && !reference_return) {
-    if (LIKELY(!is_critical_native)) {
-      // For normal JNI, store the return value on the stack because the call to
-      // JniMethodEnd will clobber the return value. It will be restored in (13).
-      CHECK_LT(return_save_location.Uint32Value(), current_frame_size);
-      __ Store(return_save_location,
-               main_jni_conv->ReturnRegister(),
-               main_jni_conv->SizeOfReturnValue());
-    } else {
-      // For @CriticalNative only,
-      // move the JNI return register into the managed return register (if they don't match).
-      ManagedRegister jni_return_reg = main_jni_conv->ReturnRegister();
-      ManagedRegister mr_return_reg = mr_conv->ReturnRegister();
+  bool spill_return_value = main_jni_conv->SpillsReturnValue();
+  FrameOffset return_save_location =
+      spill_return_value ? main_jni_conv->ReturnValueSaveLocation() : FrameOffset(0);
+  if (spill_return_value) {
+    DCHECK(!is_critical_native);
+    // For normal JNI, store the return value on the stack because the call to
+    // JniMethodEnd will clobber the return value. It will be restored in (13).
+    CHECK_LT(return_save_location.Uint32Value(), current_frame_size);
+    __ Store(return_save_location,
+             main_jni_conv->ReturnRegister(),
+             main_jni_conv->SizeOfReturnValue());
+  } else if (UNLIKELY(is_critical_native) && main_jni_conv->SizeOfReturnValue() != 0) {
+    // For @CriticalNative only,
+    // move the JNI return register into the managed return register (if they don't match).
+    ManagedRegister jni_return_reg = main_jni_conv->ReturnRegister();
+    ManagedRegister mr_return_reg = mr_conv->ReturnRegister();
 
-      // Check if the JNI return register matches the managed return register.
-      // If they differ, only then do we have to do anything about it.
-      // Otherwise the return value is already in the right place when we return.
-      if (!jni_return_reg.Equals(mr_return_reg)) {
-        CHECK(!main_jni_conv->UseTailCall());
-        // This is typically only necessary on ARM32 due to native being softfloat
-        // while managed is hardfloat.
-        // -- For example VMOV {r0, r1} -> D0; VMOV r0 -> S0.
-        __ Move(mr_return_reg, jni_return_reg, main_jni_conv->SizeOfReturnValue());
-      } else if (jni_return_reg.IsNoRegister() && mr_return_reg.IsNoRegister()) {
-        // Sanity check: If the return value is passed on the stack for some reason,
-        // then make sure the size matches.
-        CHECK_EQ(main_jni_conv->SizeOfReturnValue(), mr_conv->SizeOfReturnValue());
-      }
+    // Check if the JNI return register matches the managed return register.
+    // If they differ, only then do we have to do anything about it.
+    // Otherwise the return value is already in the right place when we return.
+    if (!jni_return_reg.Equals(mr_return_reg)) {
+      CHECK(!main_jni_conv->UseTailCall());
+      // This is typically only necessary on ARM32 due to native being softfloat
+      // while managed is hardfloat.
+      // -- For example VMOV {r0, r1} -> D0; VMOV r0 -> S0.
+      __ Move(mr_return_reg, jni_return_reg, main_jni_conv->SizeOfReturnValue());
+    } else if (jni_return_reg.IsNoRegister() && mr_return_reg.IsNoRegister()) {
+      // Check that if the return value is passed on the stack for some reason,
+      // that the size matches.
+      CHECK_EQ(main_jni_conv->SizeOfReturnValue(), mr_conv->SizeOfReturnValue());
     }
   }
 
   if (LIKELY(!is_critical_native)) {
     // Increase frame size for out args if needed by the end_jni_conv.
-    const size_t end_out_arg_size = end_jni_conv->OutArgSize();
+    const size_t end_out_arg_size = end_jni_conv->OutFrameSize();
     if (end_out_arg_size > current_out_arg_size) {
       size_t out_arg_size_diff = end_out_arg_size - current_out_arg_size;
       current_out_arg_size = end_out_arg_size;
       __ IncreaseFrameSize(out_arg_size_diff);
       current_frame_size += out_arg_size_diff;
-      saved_cookie_offset = FrameOffset(saved_cookie_offset.SizeValue() + out_arg_size_diff);
-      locked_object_handle_scope_offset =
-          FrameOffset(locked_object_handle_scope_offset.SizeValue() + out_arg_size_diff);
       return_save_location = FrameOffset(return_save_location.SizeValue() + out_arg_size_diff);
     }
     end_jni_conv->ResetIterator(FrameOffset(end_out_arg_size));
@@ -601,43 +518,54 @@
     // Pass saved local reference state.
     if (end_jni_conv->IsCurrentParamOnStack()) {
       FrameOffset out_off = end_jni_conv->CurrentParamStackOffset();
-      __ Copy(out_off, saved_cookie_offset, end_jni_conv->InterproceduralScratchRegister(), 4);
+      __ Store(out_off, saved_cookie_register, cookie_size);
     } else {
       ManagedRegister out_reg = end_jni_conv->CurrentParamRegister();
-      __ Load(out_reg, saved_cookie_offset, 4);
+      __ Move(out_reg, saved_cookie_register, cookie_size);
     }
     end_jni_conv->Next();
     if (is_synchronized) {
       // Pass object for unlocking.
-      if (end_jni_conv->IsCurrentParamOnStack()) {
-        FrameOffset out_off = end_jni_conv->CurrentParamStackOffset();
-        __ CreateHandleScopeEntry(out_off, locked_object_handle_scope_offset,
-                           end_jni_conv->InterproceduralScratchRegister(),
-                           false);
+      if (is_static) {
+        // Load reference to the method's declaring class. The method register has been
+        // clobbered by the above call, so we need to load the method from the stack.
+        FrameOffset method_offset =
+            FrameOffset(current_out_arg_size + mr_conv->MethodStackOffset().SizeValue());
+        DCHECK_EQ(ArtMethod::DeclaringClassOffset().SizeValue(), 0u);
+        if (end_jni_conv->IsCurrentParamOnStack()) {
+          FrameOffset out_off = end_jni_conv->CurrentParamStackOffset();
+          __ Copy(out_off, method_offset, static_cast<size_t>(kPointerSize));
+        } else {
+          ManagedRegister out_reg = end_jni_conv->CurrentParamRegister();
+          __ Load(out_reg, method_offset, static_cast<size_t>(kPointerSize));
+        }
       } else {
-        ManagedRegister out_reg = end_jni_conv->CurrentParamRegister();
-        __ CreateHandleScopeEntry(out_reg, locked_object_handle_scope_offset,
-                           ManagedRegister::NoRegister(), false);
+        mr_conv->ResetIterator(FrameOffset(current_frame_size));
+        FrameOffset this_offset = mr_conv->CurrentParamStackOffset();
+        if (end_jni_conv->IsCurrentParamOnStack()) {
+          FrameOffset out_off = end_jni_conv->CurrentParamStackOffset();
+          __ CreateJObject(out_off, this_offset, /*null_allowed=*/ false);
+        } else {
+          ManagedRegister out_reg = end_jni_conv->CurrentParamRegister();
+          __ CreateJObject(out_reg,
+                           this_offset,
+                           ManagedRegister::NoRegister(),
+                           /*null_allowed=*/ false);
+        }
       }
       end_jni_conv->Next();
     }
     if (end_jni_conv->IsCurrentParamInRegister()) {
       __ GetCurrentThread(end_jni_conv->CurrentParamRegister());
-      __ Call(end_jni_conv->CurrentParamRegister(),
-              Offset(jni_end),
-              end_jni_conv->InterproceduralScratchRegister());
+      __ Call(end_jni_conv->CurrentParamRegister(), Offset(jni_end));
     } else {
-      __ GetCurrentThread(end_jni_conv->CurrentParamStackOffset(),
-                          end_jni_conv->InterproceduralScratchRegister());
-      __ CallFromThread(jni_end, end_jni_conv->InterproceduralScratchRegister());
+      __ GetCurrentThread(end_jni_conv->CurrentParamStackOffset());
+      __ CallFromThread(jni_end);
     }
 
     // 13. Reload return value
-    if (main_jni_conv->SizeOfReturnValue() != 0 && !reference_return) {
+    if (spill_return_value) {
       __ Load(mr_conv->ReturnRegister(), return_save_location, mr_conv->SizeOfReturnValue());
-      // NIT: If it's @CriticalNative then we actually only need to do this IF
-      // the calling convention's native return register doesn't match the managed convention's
-      // return register.
     }
   }  // if (!is_critical_native)
 
@@ -651,7 +579,7 @@
   // 15. Process pending exceptions from JNI call or monitor exit.
   //     @CriticalNative methods do not need exception poll in the stub.
   if (LIKELY(!is_critical_native)) {
-    __ ExceptionPoll(main_jni_conv->InterproceduralScratchRegister(), 0 /* stack_adjust= */);
+    __ ExceptionPoll(/* stack_adjust= */ 0);
   }
 
   // 16. Remove activation - need to restore callee save registers since the GC may have changed
@@ -665,7 +593,63 @@
     DCHECK_EQ(jni_asm->cfi().GetCurrentCFAOffset(), static_cast<int>(current_frame_size));
   }
 
-  // 17. Finalize code generation
+  // 17. Read barrier slow path for the declaring class in the method for a static call.
+  //     Skip this for @CriticalNative because we're not passing a `jclass` to the native method.
+  if (kUseReadBarrier && is_static && !is_critical_native) {
+    __ Bind(jclass_read_barrier_slow_path.get());
+
+    // We do the marking check after adjusting for outgoing arguments. That ensures that
+    // we have space available for at least two params in case we need to pass the read
+    // barrier parameters on stack (only x86). But that means we must adjust the CFI
+    // offset accordingly as it does not include the outgoing args after `RemoveFrame().
+    if (main_out_arg_size != 0) {
+      // Note: The DW_CFA_def_cfa_offset emitted by `RemoveFrame()` above
+      // is useless when it is immediatelly overridden here but avoiding
+      // it adds a lot of code complexity for minimal gain.
+      jni_asm->cfi().AdjustCFAOffset(main_out_arg_size);
+    }
+
+    // We enter the slow path with the method register unclobbered.
+    method_register = mr_conv->MethodRegister();
+
+    // Construct slow path for read barrier:
+    //
+    // Call into the runtime's ReadBarrierJni and have it fix up
+    // the object address if it was moved.
+
+    ThreadOffset<kPointerSize> read_barrier = QUICK_ENTRYPOINT_OFFSET(kPointerSize,
+                                                                      pReadBarrierJni);
+    main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
+    // Pass the pointer to the method's declaring class as the first argument.
+    DCHECK_EQ(ArtMethod::DeclaringClassOffset().SizeValue(), 0u);
+    SetNativeParameter(jni_asm.get(), main_jni_conv.get(), method_register);
+    main_jni_conv->Next();
+    // Pass the current thread as the second argument and call.
+    if (main_jni_conv->IsCurrentParamInRegister()) {
+      __ GetCurrentThread(main_jni_conv->CurrentParamRegister());
+      __ Call(main_jni_conv->CurrentParamRegister(), Offset(read_barrier));
+    } else {
+      __ GetCurrentThread(main_jni_conv->CurrentParamStackOffset());
+      __ CallFromThread(read_barrier);
+    }
+    if (is_synchronized) {
+      // Reload the method pointer in the slow path because it is needed
+      // as an argument for the `JniMethodStartSynchronized`.
+      __ Load(method_register,
+              FrameOffset(main_out_arg_size + mr_conv->MethodStackOffset().SizeValue()),
+              static_cast<size_t>(kPointerSize));
+    }
+
+    // Return to main path.
+    __ Jump(jclass_read_barrier_return.get());
+
+    // Undo the CFI offset adjustment at the start of the slow path.
+    if (main_out_arg_size != 0) {
+      jni_asm->cfi().AdjustCFAOffset(-main_out_arg_size);
+    }
+  }
+
+  // 18. Finalize code generation
   __ FinalizeCode();
   size_t cs = __ CodeSize();
   std::vector<uint8_t> managed_code(cs);
@@ -685,34 +669,34 @@
 static void CopyParameter(JNIMacroAssembler<kPointerSize>* jni_asm,
                           ManagedRuntimeCallingConvention* mr_conv,
                           JniCallingConvention* jni_conv) {
-  bool input_in_reg = mr_conv->IsCurrentParamInRegister();
+  // We spilled all registers, so use stack locations.
+  // TODO: Move args in registers for @CriticalNative.
+  bool input_in_reg = false;  // mr_conv->IsCurrentParamInRegister();
   bool output_in_reg = jni_conv->IsCurrentParamInRegister();
-  FrameOffset handle_scope_offset(0);
+  FrameOffset spilled_reference_offset(0);
   bool null_allowed = false;
   bool ref_param = jni_conv->IsCurrentParamAReference();
   CHECK(!ref_param || mr_conv->IsCurrentParamAReference());
-  // input may be in register, on stack or both - but not none!
-  CHECK(input_in_reg || mr_conv->IsCurrentParamOnStack());
   if (output_in_reg) {  // output shouldn't straddle registers and stack
     CHECK(!jni_conv->IsCurrentParamOnStack());
   } else {
     CHECK(jni_conv->IsCurrentParamOnStack());
   }
-  // References need placing in handle scope and the entry address passing.
+  // References are spilled to caller's reserved out vreg area.
   if (ref_param) {
     null_allowed = mr_conv->IsCurrentArgPossiblyNull();
-    // Compute handle scope offset. Note null is placed in the handle scope but the jobject
-    // passed to the native code must be null (not a pointer into the handle scope
+    // Compute spilled reference offset. Note that null is spilled but the jobject
+    // passed to the native code must be null (not a pointer into the spilled value
     // as with regular references).
-    handle_scope_offset = jni_conv->CurrentParamHandleScopeEntryOffset();
-    // Check handle scope offset is within frame.
-    CHECK_LT(handle_scope_offset.Uint32Value(), mr_conv->GetDisplacement().Uint32Value());
+    spilled_reference_offset = mr_conv->CurrentParamStackOffset();
+    // Check that spilled reference offset is in the spill area in the caller's frame.
+    CHECK_GT(spilled_reference_offset.Uint32Value(), mr_conv->GetDisplacement().Uint32Value());
   }
   if (input_in_reg && output_in_reg) {
     ManagedRegister in_reg = mr_conv->CurrentParamRegister();
     ManagedRegister out_reg = jni_conv->CurrentParamRegister();
     if (ref_param) {
-      __ CreateHandleScopeEntry(out_reg, handle_scope_offset, in_reg, null_allowed);
+      __ CreateJObject(out_reg, spilled_reference_offset, in_reg, null_allowed);
     } else {
       if (!mr_conv->IsCurrentParamOnStack()) {
         // regular non-straddling move
@@ -724,13 +708,12 @@
   } else if (!input_in_reg && !output_in_reg) {
     FrameOffset out_off = jni_conv->CurrentParamStackOffset();
     if (ref_param) {
-      __ CreateHandleScopeEntry(out_off, handle_scope_offset, mr_conv->InterproceduralScratchRegister(),
-                         null_allowed);
+      __ CreateJObject(out_off, spilled_reference_offset, null_allowed);
     } else {
       FrameOffset in_off = mr_conv->CurrentParamStackOffset();
       size_t param_size = mr_conv->CurrentParamSize();
       CHECK_EQ(param_size, jni_conv->CurrentParamSize());
-      __ Copy(out_off, in_off, mr_conv->InterproceduralScratchRegister(), param_size);
+      __ Copy(out_off, in_off, param_size);
     }
   } else if (!input_in_reg && output_in_reg) {
     FrameOffset in_off = mr_conv->CurrentParamStackOffset();
@@ -738,7 +721,10 @@
     // Check that incoming stack arguments are above the current stack frame.
     CHECK_GT(in_off.Uint32Value(), mr_conv->GetDisplacement().Uint32Value());
     if (ref_param) {
-      __ CreateHandleScopeEntry(out_reg, handle_scope_offset, ManagedRegister::NoRegister(), null_allowed);
+      __ CreateJObject(out_reg,
+                       spilled_reference_offset,
+                       ManagedRegister::NoRegister(),
+                       null_allowed);
     } else {
       size_t param_size = mr_conv->CurrentParamSize();
       CHECK_EQ(param_size, jni_conv->CurrentParamSize());
@@ -751,9 +737,8 @@
     // Check outgoing argument is within frame part dedicated to out args.
     CHECK_LT(out_off.Uint32Value(), jni_conv->GetDisplacement().Uint32Value());
     if (ref_param) {
-      // TODO: recycle value in in_reg rather than reload from handle scope
-      __ CreateHandleScopeEntry(out_off, handle_scope_offset, mr_conv->InterproceduralScratchRegister(),
-                         null_allowed);
+      // TODO: recycle value in in_reg rather than reload from spill slot.
+      __ CreateJObject(out_off, spilled_reference_offset, null_allowed);
     } else {
       size_t param_size = mr_conv->CurrentParamSize();
       CHECK_EQ(param_size, jni_conv->CurrentParamSize());
@@ -764,7 +749,7 @@
         // store where input straddles registers and stack
         CHECK_EQ(param_size, 8u);
         FrameOffset in_off = mr_conv->CurrentParamStackOffset();
-        __ StoreSpanning(out_off, in_reg, in_off, mr_conv->InterproceduralScratchRegister());
+        __ StoreSpanning(out_off, in_reg, in_off);
       }
     }
   }
diff --git a/compiler/jni/quick/x86/calling_convention_x86.cc b/compiler/jni/quick/x86/calling_convention_x86.cc
index 4e643ba..1baffc5 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.cc
+++ b/compiler/jni/quick/x86/calling_convention_x86.cc
@@ -20,13 +20,17 @@
 
 #include "arch/instruction_set.h"
 #include "arch/x86/jni_frame_x86.h"
-#include "handle_scope-inl.h"
 #include "utils/x86/managed_register_x86.h"
 
 namespace art {
 namespace x86 {
 
-static_assert(kX86PointerSize == PointerSize::k32, "Unexpected x86 pointer size");
+static constexpr Register kManagedCoreArgumentRegisters[] = {
+    EAX, ECX, EDX, EBX
+};
+static constexpr size_t kManagedCoreArgumentRegistersCount =
+    arraysize(kManagedCoreArgumentRegisters);
+static constexpr size_t kManagedFpArgumentRegistersCount = 4u;
 
 static constexpr ManagedRegister kCalleeSaveRegisters[] = {
     // Core registers.
@@ -67,12 +71,11 @@
 
 // Calling convention
 
-ManagedRegister X86ManagedRuntimeCallingConvention::InterproceduralScratchRegister() const {
-  return X86ManagedRegister::FromCpuRegister(ECX);
-}
-
-ManagedRegister X86JniCallingConvention::InterproceduralScratchRegister() const {
-  return X86ManagedRegister::FromCpuRegister(ECX);
+ManagedRegister X86JniCallingConvention::SavedLocalReferenceCookieRegister() const {
+  // The EBP is callee-save register in both managed and native ABIs.
+  // It is saved in the stack frame and it has no special purpose like `tr` on arm/arm64.
+  static_assert((kCoreCalleeSpillMask & (1u << EBP)) != 0u);  // Managed callee save register.
+  return X86ManagedRegister::FromCpuRegister(EBP);
 }
 
 ManagedRegister X86JniCallingConvention::ReturnScratchRegister() const {
@@ -113,49 +116,58 @@
   return X86ManagedRegister::FromCpuRegister(EAX);
 }
 
+void X86ManagedRuntimeCallingConvention::ResetIterator(FrameOffset displacement) {
+  ManagedRuntimeCallingConvention::ResetIterator(displacement);
+  gpr_arg_count_ = 1u;  // Skip EAX for ArtMethod*
+}
+
+void X86ManagedRuntimeCallingConvention::Next() {
+  if (!IsCurrentParamAFloatOrDouble()) {
+    gpr_arg_count_ += IsCurrentParamALong() ? 2u : 1u;
+  }
+  ManagedRuntimeCallingConvention::Next();
+}
+
 bool X86ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
-  return false;  // Everything is passed by stack
+  if (IsCurrentParamAFloatOrDouble()) {
+    return itr_float_and_doubles_ < kManagedFpArgumentRegistersCount;
+  } else {
+    // Don't split a long between the last register and the stack.
+    size_t extra_regs = IsCurrentParamALong() ? 1u : 0u;
+    return gpr_arg_count_ + extra_regs < kManagedCoreArgumentRegistersCount;
+  }
 }
 
 bool X86ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
-  // We assume all parameters are on stack, args coming via registers are spilled as entry_spills.
-  return true;
+  return !IsCurrentParamInRegister();
 }
 
 ManagedRegister X86ManagedRuntimeCallingConvention::CurrentParamRegister() {
-  ManagedRegister res = ManagedRegister::NoRegister();
-  if (!IsCurrentParamAFloatOrDouble()) {
-    switch (gpr_arg_count_) {
-      case 0:
-        res = X86ManagedRegister::FromCpuRegister(ECX);
-        break;
-      case 1:
-        res = X86ManagedRegister::FromCpuRegister(EDX);
-        break;
-      case 2:
-        // Don't split a long between the last register and the stack.
-        if (IsCurrentParamALong()) {
-          return ManagedRegister::NoRegister();
-        }
-        res = X86ManagedRegister::FromCpuRegister(EBX);
-        break;
-    }
-  } else if (itr_float_and_doubles_ < 4) {
+  DCHECK(IsCurrentParamInRegister());
+  if (IsCurrentParamAFloatOrDouble()) {
     // First four float parameters are passed via XMM0..XMM3
-    res = X86ManagedRegister::FromXmmRegister(
-                                 static_cast<XmmRegister>(XMM0 + itr_float_and_doubles_));
+    XmmRegister reg = static_cast<XmmRegister>(XMM0 + itr_float_and_doubles_);
+    return X86ManagedRegister::FromXmmRegister(reg);
+  } else {
+    if (IsCurrentParamALong()) {
+      switch (gpr_arg_count_) {
+        case 1:
+          static_assert(kManagedCoreArgumentRegisters[1] == ECX);
+          static_assert(kManagedCoreArgumentRegisters[2] == EDX);
+          return X86ManagedRegister::FromRegisterPair(ECX_EDX);
+        case 2:
+          static_assert(kManagedCoreArgumentRegisters[2] == EDX);
+          static_assert(kManagedCoreArgumentRegisters[3] == EBX);
+          return X86ManagedRegister::FromRegisterPair(EDX_EBX);
+        default:
+          LOG(FATAL) << "UNREACHABLE";
+          UNREACHABLE();
+      }
+    } else {
+      Register core_reg = kManagedCoreArgumentRegisters[gpr_arg_count_];
+      return X86ManagedRegister::FromCpuRegister(core_reg);
+    }
   }
-  return res;
-}
-
-ManagedRegister X86ManagedRuntimeCallingConvention::CurrentParamHighLongRegister() {
-  ManagedRegister res = ManagedRegister::NoRegister();
-  DCHECK(IsCurrentParamALong());
-  switch (gpr_arg_count_) {
-    case 0: res = X86ManagedRegister::FromCpuRegister(EDX); break;
-    case 1: res = X86ManagedRegister::FromCpuRegister(EBX); break;
-  }
-  return res;
 }
 
 FrameOffset X86ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
@@ -164,48 +176,6 @@
                      (itr_slots_ * kFramePointerSize));  // offset into in args
 }
 
-const ManagedRegisterEntrySpills& X86ManagedRuntimeCallingConvention::EntrySpills() {
-  // We spill the argument registers on X86 to free them up for scratch use, we then assume
-  // all arguments are on the stack.
-  if (entry_spills_.size() == 0) {
-    ResetIterator(FrameOffset(0));
-    while (HasNext()) {
-      ManagedRegister in_reg = CurrentParamRegister();
-      bool is_long = IsCurrentParamALong();
-      if (!in_reg.IsNoRegister()) {
-        int32_t size = IsParamADouble(itr_args_) ? 8 : 4;
-        int32_t spill_offset = CurrentParamStackOffset().Uint32Value();
-        ManagedRegisterSpill spill(in_reg, size, spill_offset);
-        entry_spills_.push_back(spill);
-        if (is_long) {
-          // special case, as we need a second register here.
-          in_reg = CurrentParamHighLongRegister();
-          DCHECK(!in_reg.IsNoRegister());
-          // We have to spill the second half of the long.
-          ManagedRegisterSpill spill2(in_reg, size, spill_offset + 4);
-          entry_spills_.push_back(spill2);
-        }
-
-        // Keep track of the number of GPRs allocated.
-        if (!IsCurrentParamAFloatOrDouble()) {
-          if (is_long) {
-            // Long was allocated in 2 registers.
-            gpr_arg_count_ += 2;
-          } else {
-            gpr_arg_count_++;
-          }
-        }
-      } else if (is_long) {
-        // We need to skip the unused last register, which is empty.
-        // If we are already out of registers, this is harmless.
-        gpr_arg_count_ += 2;
-      }
-      Next();
-    }
-  }
-  return entry_spills_;
-}
-
 // JNI calling convention
 
 X86JniCallingConvention::X86JniCallingConvention(bool is_static,
@@ -231,36 +201,40 @@
   if (is_critical_native_) {
     CHECK(!SpillsMethod());
     CHECK(!HasLocalReferenceSegmentState());
-    CHECK(!HasHandleScope());
     CHECK(!SpillsReturnValue());
     return 0u;  // There is no managed frame for @CriticalNative.
   }
 
   // Method*, PC return address and callee save area size, local reference segment state
-  CHECK(SpillsMethod());
+  DCHECK(SpillsMethod());
   const size_t method_ptr_size = static_cast<size_t>(kX86PointerSize);
   const size_t pc_return_addr_size = kFramePointerSize;
   const size_t callee_save_area_size = CalleeSaveRegisters().size() * kFramePointerSize;
   size_t total_size = method_ptr_size + pc_return_addr_size + callee_save_area_size;
 
-  CHECK(HasLocalReferenceSegmentState());
-  total_size += kFramePointerSize;
-
-  CHECK(HasHandleScope());
-  total_size += HandleScope::SizeOf(kX86_64PointerSize, ReferenceCount());
+  DCHECK(HasLocalReferenceSegmentState());
+  // Cookie is saved in one of the spilled registers.
 
   // Plus return value spill area size
-  CHECK(SpillsReturnValue());
-  total_size += SizeOfReturnValue();
+  if (SpillsReturnValue()) {
+    // For 64-bit return values there shall be a 4B alignment gap between
+    // the method pointer and the saved return value.
+    size_t padding = ReturnValueSaveLocation().SizeValue() - method_ptr_size;
+    DCHECK_EQ(padding,
+              (GetReturnType() == Primitive::kPrimLong || GetReturnType() == Primitive::kPrimDouble)
+                  ? 4u
+                  : 0u);
+    total_size += padding;
+    total_size += SizeOfReturnValue();
+  }
 
   return RoundUp(total_size, kStackAlignment);
 }
 
-size_t X86JniCallingConvention::OutArgSize() const {
-  // Count param args, including JNIEnv* and jclass*; count 8-byte args twice.
-  size_t all_args = NumberOfExtraArgumentsForJni() + NumArgs() + NumLongOrDoubleArgs();
-  // The size of outgoiong arguments.
-  size_t size = all_args * kFramePointerSize;
+size_t X86JniCallingConvention::OutFrameSize() const {
+  // The size of outgoing arguments.
+  size_t size = GetNativeOutArgsSize(/*num_args=*/ NumberOfExtraArgumentsForJni() + NumArgs(),
+                                     NumLongOrDoubleArgs());
 
   // @CriticalNative can use tail call as all managed callee saves are preserved by AAPCS.
   static_assert((kCoreCalleeSpillMask & ~kNativeCoreCalleeSpillMask) == 0u);
@@ -280,14 +254,16 @@
     if (return_type_ok && size == kFramePointerSize) {
       // Note: This is not aligned to kNativeStackAlignment but that's OK for tail call.
       static_assert(kFramePointerSize < kNativeStackAlignment);
-      DCHECK_EQ(kFramePointerSize, GetCriticalNativeOutArgsSize(GetShorty(), NumArgs() + 1u));
+      // The stub frame size is considered 0 in the callee where the return PC is a part of
+      // the callee frame but it is kPointerSize in the compiled stub before the tail call.
+      DCHECK_EQ(0u, GetCriticalNativeStubFrameSize(GetShorty(), NumArgs() + 1u));
       return kFramePointerSize;
     }
   }
 
   size_t out_args_size = RoundUp(size, kNativeStackAlignment);
   if (UNLIKELY(IsCriticalNative())) {
-    DCHECK_EQ(out_args_size, GetCriticalNativeOutArgsSize(GetShorty(), NumArgs() + 1u));
+    DCHECK_EQ(out_args_size, GetCriticalNativeStubFrameSize(GetShorty(), NumArgs() + 1u));
   }
   return out_args_size;
 }
@@ -315,7 +291,8 @@
 }
 
 FrameOffset X86JniCallingConvention::CurrentParamStackOffset() {
-  return FrameOffset(displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kFramePointerSize));
+  return
+      FrameOffset(displacement_.Int32Value() - OutFrameSize() + (itr_slots_ * kFramePointerSize));
 }
 
 ManagedRegister X86JniCallingConvention::HiddenArgumentRegister() const {
@@ -326,13 +303,12 @@
                       [](ManagedRegister callee_save) constexpr {
                         return callee_save.Equals(X86ManagedRegister::FromCpuRegister(EAX));
                       }));
-  DCHECK(!InterproceduralScratchRegister().Equals(X86ManagedRegister::FromCpuRegister(EAX)));
   return X86ManagedRegister::FromCpuRegister(EAX);
 }
 
 bool X86JniCallingConvention::UseTailCall() const {
   CHECK(IsCriticalNative());
-  return OutArgSize() == kFramePointerSize;
+  return OutFrameSize() == kFramePointerSize;
 }
 
 }  // namespace x86
diff --git a/compiler/jni/quick/x86/calling_convention_x86.h b/compiler/jni/quick/x86/calling_convention_x86.h
index 1273e8d..cbb362c 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.h
+++ b/compiler/jni/quick/x86/calling_convention_x86.h
@@ -30,23 +30,21 @@
                                         is_synchronized,
                                         shorty,
                                         PointerSize::k32),
-        gpr_arg_count_(0) {}
+        gpr_arg_count_(1u) {}  // Skip EAX for ArtMethod*
   ~X86ManagedRuntimeCallingConvention() override {}
   // Calling convention
   ManagedRegister ReturnRegister() override;
-  ManagedRegister InterproceduralScratchRegister() const override;
+  void ResetIterator(FrameOffset displacement) override;
   // Managed runtime calling convention
   ManagedRegister MethodRegister() override;
+  void Next() override;
   bool IsCurrentParamInRegister() override;
   bool IsCurrentParamOnStack() override;
   ManagedRegister CurrentParamRegister() override;
   FrameOffset CurrentParamStackOffset() override;
-  const ManagedRegisterEntrySpills& EntrySpills() override;
 
  private:
   int gpr_arg_count_;
-  ManagedRegister CurrentParamHighLongRegister();
-  ManagedRegisterEntrySpills entry_spills_;
   DISALLOW_COPY_AND_ASSIGN(X86ManagedRuntimeCallingConvention);
 };
 
@@ -61,11 +59,11 @@
   // Calling convention
   ManagedRegister ReturnRegister() override;
   ManagedRegister IntReturnRegister() override;
-  ManagedRegister InterproceduralScratchRegister() const override;
   // JNI calling convention
   size_t FrameSize() const override;
-  size_t OutArgSize() const override;
+  size_t OutFrameSize() const override;
   ArrayRef<const ManagedRegister> CalleeSaveRegisters() const override;
+  ManagedRegister SavedLocalReferenceCookieRegister() const override;
   ManagedRegister ReturnScratchRegister() const override;
   uint32_t CoreSpillMask() const override;
   uint32_t FpSpillMask() const override;
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 9013b02..33a921b 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
@@ -21,12 +21,16 @@
 #include "arch/instruction_set.h"
 #include "arch/x86_64/jni_frame_x86_64.h"
 #include "base/bit_utils.h"
-#include "handle_scope-inl.h"
 #include "utils/x86_64/managed_register_x86_64.h"
 
 namespace art {
 namespace x86_64 {
 
+static constexpr Register kCoreArgumentRegisters[] = {
+    RDI, RSI, RDX, RCX, R8, R9
+};
+static_assert(kMaxIntLikeRegisterArguments == arraysize(kCoreArgumentRegisters));
+
 static constexpr ManagedRegister kCalleeSaveRegisters[] = {
     // Core registers.
     X86_64ManagedRegister::FromCpuRegister(RBX),
@@ -87,12 +91,11 @@
 
 // Calling convention
 
-ManagedRegister X86_64ManagedRuntimeCallingConvention::InterproceduralScratchRegister() const {
-  return X86_64ManagedRegister::FromCpuRegister(RAX);
-}
-
-ManagedRegister X86_64JniCallingConvention::InterproceduralScratchRegister() const {
-  return X86_64ManagedRegister::FromCpuRegister(RAX);
+ManagedRegister X86_64JniCallingConvention::SavedLocalReferenceCookieRegister() const {
+  // The RBX is callee-save register in both managed and native ABIs.
+  // It is saved in the stack frame and it has no special purpose like `tr` on arm/arm64.
+  static_assert((kCoreCalleeSpillMask & (1u << RBX)) != 0u);  // Managed callee save register.
+  return X86_64ManagedRegister::FromCpuRegister(RBX);
 }
 
 ManagedRegister X86_64JniCallingConvention::ReturnScratchRegister() const {
@@ -130,58 +133,37 @@
 }
 
 bool X86_64ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
-  return !IsCurrentParamOnStack();
+  if (IsCurrentParamAFloatOrDouble()) {
+    return itr_float_and_doubles_ < kMaxFloatOrDoubleRegisterArguments;
+  } else {
+    size_t non_fp_arg_number = itr_args_ - itr_float_and_doubles_;
+    return /* method */ 1u + non_fp_arg_number < kMaxIntLikeRegisterArguments;
+  }
 }
 
 bool X86_64ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
-  // We assume all parameters are on stack, args coming via registers are spilled as entry_spills
-  return true;
+  return !IsCurrentParamInRegister();
 }
 
 ManagedRegister X86_64ManagedRuntimeCallingConvention::CurrentParamRegister() {
-  ManagedRegister res = ManagedRegister::NoRegister();
-  if (!IsCurrentParamAFloatOrDouble()) {
-    switch (itr_args_ - itr_float_and_doubles_) {
-    case 0: res = X86_64ManagedRegister::FromCpuRegister(RSI); break;
-    case 1: res = X86_64ManagedRegister::FromCpuRegister(RDX); break;
-    case 2: res = X86_64ManagedRegister::FromCpuRegister(RCX); break;
-    case 3: res = X86_64ManagedRegister::FromCpuRegister(R8); break;
-    case 4: res = X86_64ManagedRegister::FromCpuRegister(R9); break;
-    }
-  } else if (itr_float_and_doubles_ < kMaxFloatOrDoubleRegisterArguments) {
+  DCHECK(IsCurrentParamInRegister());
+  if (IsCurrentParamAFloatOrDouble()) {
     // First eight float parameters are passed via XMM0..XMM7
-    res = X86_64ManagedRegister::FromXmmRegister(
-                                 static_cast<FloatRegister>(XMM0 + itr_float_and_doubles_));
+    FloatRegister fp_reg = static_cast<FloatRegister>(XMM0 + itr_float_and_doubles_);
+    return X86_64ManagedRegister::FromXmmRegister(fp_reg);
+  } else {
+    size_t non_fp_arg_number = itr_args_ - itr_float_and_doubles_;
+    Register core_reg = kCoreArgumentRegisters[/* method */ 1u + non_fp_arg_number];
+    return X86_64ManagedRegister::FromCpuRegister(core_reg);
   }
-  return res;
 }
 
 FrameOffset X86_64ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
-  CHECK(IsCurrentParamOnStack());
   return FrameOffset(displacement_.Int32Value() +  // displacement
                      static_cast<size_t>(kX86_64PointerSize) +  // Method ref
                      itr_slots_ * sizeof(uint32_t));  // offset into in args
 }
 
-const ManagedRegisterEntrySpills& X86_64ManagedRuntimeCallingConvention::EntrySpills() {
-  // We spill the argument registers on X86 to free them up for scratch use, we then assume
-  // all arguments are on the stack.
-  if (entry_spills_.size() == 0) {
-    ResetIterator(FrameOffset(0));
-    while (HasNext()) {
-      ManagedRegister in_reg = CurrentParamRegister();
-      if (!in_reg.IsNoRegister()) {
-        int32_t size = IsParamALongOrDouble(itr_args_) ? 8 : 4;
-        int32_t spill_offset = CurrentParamStackOffset().Uint32Value();
-        ManagedRegisterSpill spill(in_reg, size, spill_offset);
-        entry_spills_.push_back(spill);
-      }
-      Next();
-    }
-  }
-  return entry_spills_;
-}
-
 // JNI calling convention
 
 X86_64JniCallingConvention::X86_64JniCallingConvention(bool is_static,
@@ -207,46 +189,38 @@
   if (is_critical_native_) {
     CHECK(!SpillsMethod());
     CHECK(!HasLocalReferenceSegmentState());
-    CHECK(!HasHandleScope());
     CHECK(!SpillsReturnValue());
     return 0u;  // There is no managed frame for @CriticalNative.
   }
 
   // Method*, PC return address and callee save area size, local reference segment state
-  CHECK(SpillsMethod());
+  DCHECK(SpillsMethod());
   const size_t method_ptr_size = static_cast<size_t>(kX86_64PointerSize);
   const size_t pc_return_addr_size = kFramePointerSize;
   const size_t callee_save_area_size = CalleeSaveRegisters().size() * kFramePointerSize;
   size_t total_size = method_ptr_size + pc_return_addr_size + callee_save_area_size;
 
-  CHECK(HasLocalReferenceSegmentState());
-  total_size += kFramePointerSize;
-
-  CHECK(HasHandleScope());
-  total_size += HandleScope::SizeOf(kX86_64PointerSize, ReferenceCount());
+  DCHECK(HasLocalReferenceSegmentState());
+  // Cookie is saved in one of the spilled registers.
 
   // Plus return value spill area size
-  CHECK(SpillsReturnValue());
-  total_size += SizeOfReturnValue();
+  if (SpillsReturnValue()) {
+    // No padding between the method pointer and the return value on arm64.
+    DCHECK_EQ(ReturnValueSaveLocation().SizeValue(), method_ptr_size);
+    total_size += SizeOfReturnValue();
+  }
 
   return RoundUp(total_size, kStackAlignment);
 }
 
-size_t X86_64JniCallingConvention::OutArgSize() const {
+size_t X86_64JniCallingConvention::OutFrameSize() const {
   // Count param args, including JNIEnv* and jclass*.
   size_t all_args = NumberOfExtraArgumentsForJni() + NumArgs();
   size_t num_fp_args = NumFloatOrDoubleArgs();
   DCHECK_GE(all_args, num_fp_args);
   size_t num_non_fp_args = all_args - num_fp_args;
-  // Account for FP arguments passed through Xmm0..Xmm7.
-  size_t num_stack_fp_args =
-      num_fp_args - std::min(kMaxFloatOrDoubleRegisterArguments, num_fp_args);
-  // Account for other (integer) arguments passed through GPR (RDI, RSI, RDX, RCX, R8, R9).
-  size_t num_stack_non_fp_args =
-      num_non_fp_args - std::min(kMaxIntLikeRegisterArguments, num_non_fp_args);
   // The size of outgoing arguments.
-  static_assert(kFramePointerSize == kMmxSpillSize);
-  size_t size = (num_stack_fp_args + num_stack_non_fp_args) * kFramePointerSize;
+  size_t size = GetNativeOutArgsSize(num_fp_args, num_non_fp_args);
 
   if (UNLIKELY(IsCriticalNative())) {
     // We always need to spill xmm12-xmm15 as they are managed callee-saves
@@ -263,7 +237,7 @@
 
   size_t out_args_size = RoundUp(size, kNativeStackAlignment);
   if (UNLIKELY(IsCriticalNative())) {
-    DCHECK_EQ(out_args_size, GetCriticalNativeOutArgsSize(GetShorty(), NumArgs() + 1u));
+    DCHECK_EQ(out_args_size, GetCriticalNativeStubFrameSize(GetShorty(), NumArgs() + 1u));
   }
   return out_args_size;
 }
@@ -321,21 +295,20 @@
       - std::min(kMaxIntLikeRegisterArguments,
                  static_cast<size_t>(itr_args_ - itr_float_and_doubles_));
           // Integer arguments passed through GPR
-  size_t offset = displacement_.Int32Value() - OutArgSize() + (args_on_stack * kFramePointerSize);
-  CHECK_LT(offset, OutArgSize());
+  size_t offset = displacement_.Int32Value() - OutFrameSize() + (args_on_stack * kFramePointerSize);
+  CHECK_LT(offset, OutFrameSize());
   return FrameOffset(offset);
 }
 
 ManagedRegister X86_64JniCallingConvention::HiddenArgumentRegister() const {
   CHECK(IsCriticalNative());
-  // R11 is neither managed callee-save, nor argument register, nor scratch register.
+  // RAX is neither managed callee-save, nor argument register, nor scratch register.
   DCHECK(std::none_of(kCalleeSaveRegisters,
                       kCalleeSaveRegisters + std::size(kCalleeSaveRegisters),
                       [](ManagedRegister callee_save) constexpr {
-                        return callee_save.Equals(X86_64ManagedRegister::FromCpuRegister(R11));
+                        return callee_save.Equals(X86_64ManagedRegister::FromCpuRegister(RAX));
                       }));
-  DCHECK(!InterproceduralScratchRegister().Equals(X86_64ManagedRegister::FromCpuRegister(R11)));
-  return X86_64ManagedRegister::FromCpuRegister(R11);
+  return X86_64ManagedRegister::FromCpuRegister(RAX);
 }
 
 // Whether to use tail call (used only for @CriticalNative).
diff --git a/compiler/jni/quick/x86_64/calling_convention_x86_64.h b/compiler/jni/quick/x86_64/calling_convention_x86_64.h
index 37b5978..f9d6fc0 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.h
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.h
@@ -33,16 +33,14 @@
   ~X86_64ManagedRuntimeCallingConvention() override {}
   // Calling convention
   ManagedRegister ReturnRegister() override;
-  ManagedRegister InterproceduralScratchRegister() const override;
   // Managed runtime calling convention
   ManagedRegister MethodRegister() override;
   bool IsCurrentParamInRegister() override;
   bool IsCurrentParamOnStack() override;
   ManagedRegister CurrentParamRegister() override;
   FrameOffset CurrentParamStackOffset() override;
-  const ManagedRegisterEntrySpills& EntrySpills() override;
+
  private:
-  ManagedRegisterEntrySpills entry_spills_;
   DISALLOW_COPY_AND_ASSIGN(X86_64ManagedRuntimeCallingConvention);
 };
 
@@ -56,11 +54,11 @@
   // Calling convention
   ManagedRegister ReturnRegister() override;
   ManagedRegister IntReturnRegister() override;
-  ManagedRegister InterproceduralScratchRegister() const override;
   // JNI calling convention
   size_t FrameSize() const override;
-  size_t OutArgSize() const override;
+  size_t OutFrameSize() const override;
   ArrayRef<const ManagedRegister> CalleeSaveRegisters() const override;
+  ManagedRegister SavedLocalReferenceCookieRegister() const override;
   ManagedRegister ReturnScratchRegister() const override;
   uint32_t CoreSpillMask() const override;
   uint32_t FpSpillMask() const override;
diff --git a/compiler/linker/linker_patch.h b/compiler/linker/linker_patch.h
index 1c523de..7da1e82 100644
--- a/compiler/linker/linker_patch.h
+++ b/compiler/linker/linker_patch.h
@@ -47,9 +47,12 @@
     kDataBimgRelRo,
     kMethodRelative,
     kMethodBssEntry,
+    kJniEntrypointRelative,
     kCallRelative,
     kTypeRelative,
     kTypeBssEntry,
+    kPublicTypeBssEntry,
+    kPackageTypeBssEntry,
     kStringRelative,
     kStringBssEntry,
     kCallEntrypoint,
@@ -94,6 +97,16 @@
     return patch;
   }
 
+  static LinkerPatch RelativeJniEntrypointPatch(size_t literal_offset,
+                                                const DexFile* target_dex_file,
+                                                uint32_t pc_insn_offset,
+                                                uint32_t target_method_idx) {
+    LinkerPatch patch(literal_offset, Type::kJniEntrypointRelative, target_dex_file);
+    patch.method_idx_ = target_method_idx;
+    patch.pc_insn_offset_ = pc_insn_offset;
+    return patch;
+  }
+
   static LinkerPatch RelativeCodePatch(size_t literal_offset,
                                        const DexFile* target_dex_file,
                                        uint32_t target_method_idx) {
@@ -122,6 +135,26 @@
     return patch;
   }
 
+  static LinkerPatch PublicTypeBssEntryPatch(size_t literal_offset,
+                                             const DexFile* target_dex_file,
+                                             uint32_t pc_insn_offset,
+                                             uint32_t target_type_idx) {
+    LinkerPatch patch(literal_offset, Type::kPublicTypeBssEntry, target_dex_file);
+    patch.type_idx_ = target_type_idx;
+    patch.pc_insn_offset_ = pc_insn_offset;
+    return patch;
+  }
+
+  static LinkerPatch PackageTypeBssEntryPatch(size_t literal_offset,
+                                              const DexFile* target_dex_file,
+                                              uint32_t pc_insn_offset,
+                                              uint32_t target_type_idx) {
+    LinkerPatch patch(literal_offset, Type::kPackageTypeBssEntry, target_dex_file);
+    patch.type_idx_ = target_type_idx;
+    patch.pc_insn_offset_ = pc_insn_offset;
+    return patch;
+  }
+
   static LinkerPatch RelativeStringPatch(size_t literal_offset,
                                          const DexFile* target_dex_file,
                                          uint32_t pc_insn_offset,
@@ -186,19 +219,24 @@
   MethodReference TargetMethod() const {
     DCHECK(patch_type_ == Type::kMethodRelative ||
            patch_type_ == Type::kMethodBssEntry ||
+           patch_type_ == Type::kJniEntrypointRelative ||
            patch_type_ == Type::kCallRelative);
     return MethodReference(target_dex_file_, method_idx_);
   }
 
   const DexFile* TargetTypeDexFile() const {
     DCHECK(patch_type_ == Type::kTypeRelative ||
-           patch_type_ == Type::kTypeBssEntry);
+           patch_type_ == Type::kTypeBssEntry ||
+           patch_type_ == Type::kPublicTypeBssEntry ||
+           patch_type_ == Type::kPackageTypeBssEntry);
     return target_dex_file_;
   }
 
   dex::TypeIndex TargetTypeIndex() const {
     DCHECK(patch_type_ == Type::kTypeRelative ||
-           patch_type_ == Type::kTypeBssEntry);
+           patch_type_ == Type::kTypeBssEntry ||
+           patch_type_ == Type::kPublicTypeBssEntry ||
+           patch_type_ == Type::kPackageTypeBssEntry);
     return dex::TypeIndex(type_idx_);
   }
 
@@ -219,8 +257,11 @@
            patch_type_ == Type::kDataBimgRelRo ||
            patch_type_ == Type::kMethodRelative ||
            patch_type_ == Type::kMethodBssEntry ||
+           patch_type_ == Type::kJniEntrypointRelative ||
            patch_type_ == Type::kTypeRelative ||
            patch_type_ == Type::kTypeBssEntry ||
+           patch_type_ == Type::kPublicTypeBssEntry ||
+           patch_type_ == Type::kPackageTypeBssEntry ||
            patch_type_ == Type::kStringRelative ||
            patch_type_ == Type::kStringBssEntry);
     return pc_insn_offset_;
@@ -287,7 +328,7 @@
   friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs);
   friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs);
 };
-std::ostream& operator<<(std::ostream& os, const LinkerPatch::Type& type);
+std::ostream& operator<<(std::ostream& os, LinkerPatch::Type type);
 
 inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) {
   return lhs.literal_offset_ == rhs.literal_offset_ &&
diff --git a/compiler/linker/output_stream_test.cc b/compiler/linker/output_stream_test.cc
index 00231b1..f1af4cb 100644
--- a/compiler/linker/output_stream_test.cc
+++ b/compiler/linker/output_stream_test.cc
@@ -103,7 +103,7 @@
 TEST_F(OutputStreamTest, BufferedFlush) {
   struct CheckingOutputStream : OutputStream {
     CheckingOutputStream()
-        : OutputStream("dummy"),
+        : OutputStream("fake-location"),
           flush_called(false) { }
     ~CheckingOutputStream() override {}
 
diff --git a/compiler/optimizing/block_namer.cc b/compiler/optimizing/block_namer.cc
new file mode 100644
index 0000000..d30448c
--- /dev/null
+++ b/compiler/optimizing/block_namer.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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 "block_namer.h"
+
+#include "nodes.h"
+
+namespace art {
+
+std::ostream& BlockNamer::PrintName(std::ostream& os, HBasicBlock* blk) const {
+  os << "B";
+  if (blk != nullptr) {
+    os << blk->GetBlockId();
+  } else {
+    os << "<none>";
+  }
+  return os;
+}
+
+}  // namespace art
diff --git a/compiler/optimizing/block_namer.h b/compiler/optimizing/block_namer.h
new file mode 100644
index 0000000..ed396b9
--- /dev/null
+++ b/compiler/optimizing/block_namer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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_COMPILER_OPTIMIZING_BLOCK_NAMER_H_
+#define ART_COMPILER_OPTIMIZING_BLOCK_NAMER_H_
+
+#include <ostream>
+
+namespace art {
+class HBasicBlock;
+
+struct BlockNamer {
+ public:
+  struct NameWrapper {
+    HBasicBlock* blk_;
+    const BlockNamer& namer_;
+  };
+  virtual ~BlockNamer() {}
+  virtual std::ostream& PrintName(std::ostream& os, HBasicBlock* blk) const;
+  NameWrapper GetName(HBasicBlock* blk) const {
+    return NameWrapper{blk, *this};
+  }
+};
+
+inline std::ostream& operator<<(std::ostream& os, const BlockNamer::NameWrapper& blk) {
+  return blk.namer_.PrintName(os, blk.blk_);
+}
+
+}  // namespace art
+
+#endif  // ART_COMPILER_OPTIMIZING_BLOCK_NAMER_H_
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index e35d502..a8149f9 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -1001,6 +1001,103 @@
     }
   }
 
+  // Check whether HSub is a result of the HRem optimization of:
+  //   q = Div(dividend, const_divisor)
+  //   r = Rem(dividend, const_divisor)
+  // into
+  //   q = Div(dividend, const_divisor)
+  //   t = Mul(q, const_divisor)
+  //   r = Sub(dividend, t)
+  // or for divisors 2^n + 1 into
+  //   q  = Div(dividend, const_divisor)
+  //   t1 = Shl(q, n)
+  //   t2 = Add(q, t1)
+  //   r  = Sub(dividend, t2)
+  // or for divisors 2^n - 1 into
+  //   q  = Div(dividend, const_divisor)
+  //   t1 = Shl(q, n)
+  //   t2 = Sub(t1, q)
+  //   r  = Sub(dividend, t2)
+  //
+  // If it is the case, the value range for the instruction is
+  // [1 - abs(const_divisor), abs(const_divisor) - 1] merged with
+  // the range of the left input is assigned and true is returned. Otherwise,
+  // no range is assigned and false is returned.
+  bool TryToAssignRangeIfOptimizedRemWithConstantDivisor(HSub* instruction) {
+    if (instruction->GetResultType() != DataType::Type::kInt32) {
+      return false;
+    }
+
+    auto is_needed_shl = [](HShl* shl) {
+      return shl != nullptr && shl->GetRight()->IsConstant() && shl->GetLeft()->IsDiv();
+    };
+
+    HDiv* div = nullptr;
+    int64_t const_divisor = 0;
+    if (HMul* mul = instruction->GetRight()->AsMul()) {
+      if (!mul->GetLeft()->IsDiv() || !mul->GetRight()->IsConstant()) {
+        return false;
+      }
+      div = mul->GetLeft()->AsDiv();
+      const_divisor = Int64FromConstant(mul->GetRight()->AsConstant());
+    } else if (HAdd* add = instruction->GetRight()->AsAdd()) {
+      HShl* shl = add->GetRight()->AsShl();
+      if (!is_needed_shl(shl)) {
+        return false;
+      }
+
+      div = shl->GetLeft()->AsDiv();
+      if (add->GetLeft() != div) {
+        return false;
+      }
+
+      int32_t n = shl->GetRight()->AsIntConstant()->GetValue();
+      if (n == BitSizeOf<int32_t>() - 1) {
+        // 2^n + 1 will be negative.
+        return false;
+      }
+      const_divisor = (1LL << n) + 1;
+    } else if (HSub* sub = instruction->GetRight()->AsSub()) {
+      HShl* shl = sub->GetLeft()->AsShl();
+      if (!is_needed_shl(shl)) {
+        return false;
+      }
+
+      div = shl->GetLeft()->AsDiv();
+      if (sub->GetRight() != div) {
+        return false;
+      }
+
+      int32_t n = shl->GetRight()->AsIntConstant()->GetValue();
+      const_divisor = (1LL << n) - 1;
+    }
+
+    if (div == nullptr || !IsInt64Value(div->GetRight(), const_divisor) ||
+        div->GetLeft() != instruction->GetLeft()) {
+      return false;
+    }
+
+    ValueRange* range = nullptr;
+    if (const_divisor == DataType::MinValueOfIntegralType(DataType::Type::kInt32)) {
+      range = new (&allocator_) ValueRange(&allocator_,
+          ValueBound(nullptr, DataType::MinValueOfIntegralType(DataType::Type::kInt32) + 1),
+          ValueBound(nullptr, DataType::MaxValueOfIntegralType(DataType::Type::kInt32)));
+    } else {
+      DCHECK_GT(const_divisor, DataType::MinValueOfIntegralType(DataType::Type::kInt32));
+      DCHECK_LE(const_divisor, DataType::MaxValueOfIntegralType(DataType::Type::kInt32));
+      int32_t abs_const_divisor = static_cast<int32_t>(std::abs(const_divisor));
+      range = new (&allocator_) ValueRange(&allocator_,
+                                           ValueBound(nullptr, 1 - abs_const_divisor),
+                                           ValueBound(nullptr, abs_const_divisor - 1));
+    }
+    HBasicBlock* basic_block = instruction->GetBlock();
+    if (ValueRange* left_range = LookupValueRange(instruction->GetLeft(), basic_block)) {
+      range = range->Narrow(left_range);
+    }
+    AssignRange(basic_block, instruction, range);
+    return true;
+  }
+
   void VisitAdd(HAdd* add) override {
     HInstruction* right = add->GetRight();
     if (right->IsIntConstant()) {
@@ -1016,6 +1113,10 @@
   }
 
   void VisitSub(HSub* sub) override {
+    if (TryToAssignRangeIfOptimizedRemWithConstantDivisor(sub)) {
+      return;
+    }
+
     HInstruction* left = sub->GetLeft();
     HInstruction* right = sub->GetRight();
     if (right->IsIntConstant()) {
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 64aa1b9..3263e9c 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -33,7 +33,6 @@
 #include "optimizing_compiler_stats.h"
 #include "ssa_builder.h"
 #include "thread.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
 
 namespace art {
 
@@ -42,9 +41,7 @@
                              const DexCompilationUnit* dex_compilation_unit,
                              const DexCompilationUnit* outer_compilation_unit,
                              CodeGenerator* code_generator,
-                             OptimizingCompilerStats* compiler_stats,
-                             ArrayRef<const uint8_t> interpreter_metadata,
-                             VariableSizedHandleScope* handles)
+                             OptimizingCompilerStats* compiler_stats)
     : graph_(graph),
       dex_file_(&graph->GetDexFile()),
       code_item_accessor_(accessor),
@@ -52,14 +49,11 @@
       outer_compilation_unit_(outer_compilation_unit),
       code_generator_(code_generator),
       compilation_stats_(compiler_stats),
-      interpreter_metadata_(interpreter_metadata),
-      handles_(handles),
       return_type_(DataType::FromShorty(dex_compilation_unit_->GetShorty()[0])) {}
 
 HGraphBuilder::HGraphBuilder(HGraph* graph,
                              const DexCompilationUnit* dex_compilation_unit,
                              const CodeItemDebugInfoAccessor& accessor,
-                             VariableSizedHandleScope* handles,
                              DataType::Type return_type)
     : graph_(graph),
       dex_file_(&graph->GetDexFile()),
@@ -68,7 +62,6 @@
       outer_compilation_unit_(nullptr),
       code_generator_(nullptr),
       compilation_stats_(nullptr),
-      handles_(handles),
       return_type_(return_type) {}
 
 bool HGraphBuilder::SkipCompilation(size_t number_of_branches) {
@@ -119,7 +112,6 @@
   SsaBuilder ssa_builder(graph_,
                          dex_compilation_unit_->GetClassLoader(),
                          dex_compilation_unit_->GetDexCache(),
-                         handles_,
                          &local_allocator);
   HInstructionBuilder instruction_builder(graph_,
                                           &block_builder,
@@ -130,9 +122,7 @@
                                           dex_compilation_unit_,
                                           outer_compilation_unit_,
                                           code_generator_,
-                                          interpreter_metadata_,
                                           compilation_stats_,
-                                          handles_,
                                           &local_allocator);
 
   // 1) Create basic blocks and link them together. Basic blocks are left
@@ -190,7 +180,6 @@
   SsaBuilder ssa_builder(graph_,
                          dex_compilation_unit_->GetClassLoader(),
                          dex_compilation_unit_->GetDexCache(),
-                         handles_,
                          &local_allocator);
   HInstructionBuilder instruction_builder(graph_,
                                           &block_builder,
@@ -201,9 +190,7 @@
                                           dex_compilation_unit_,
                                           outer_compilation_unit_,
                                           code_generator_,
-                                          interpreter_metadata_,
                                           compilation_stats_,
-                                          handles_,
                                           &local_allocator);
 
   // 1) Create basic blocks for the intrinsic and link them together.
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index 6152740..580769e 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -38,15 +38,12 @@
                 const DexCompilationUnit* dex_compilation_unit,
                 const DexCompilationUnit* outer_compilation_unit,
                 CodeGenerator* code_generator,
-                OptimizingCompilerStats* compiler_stats,
-                ArrayRef<const uint8_t> interpreter_metadata,
-                VariableSizedHandleScope* handles);
+                OptimizingCompilerStats* compiler_stats);
 
   // Only for unit testing.
   HGraphBuilder(HGraph* graph,
                 const DexCompilationUnit* dex_compilation_unit,
                 const CodeItemDebugInfoAccessor& accessor,
-                VariableSizedHandleScope* handles,
                 DataType::Type return_type = DataType::Type::kInt32);
 
   GraphAnalysisResult BuildGraph();
@@ -71,8 +68,6 @@
   CodeGenerator* const code_generator_;
 
   OptimizingCompilerStats* const compilation_stats_;
-  const ArrayRef<const uint8_t> interpreter_metadata_;
-  VariableSizedHandleScope* const handles_;
   const DataType::Type return_type_;
 
   DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index cfd9ea6..886cabb 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -32,11 +32,13 @@
 #include "code_generator_x86_64.h"
 #endif
 
+#include "art_method-inl.h"
 #include "base/bit_utils.h"
 #include "base/bit_utils_iterator.h"
 #include "base/casts.h"
 #include "base/leb128.h"
 #include "class_linker.h"
+#include "class_root-inl.h"
 #include "compiled_method.h"
 #include "dex/bytecode_utils.h"
 #include "dex/code_item_accessors-inl.h"
@@ -433,7 +435,7 @@
   // Finalize instructions in assember;
   Finalize(allocator);
 
-  GetStackMapStream()->EndMethod();
+  GetStackMapStream()->EndMethod(GetAssembler()->CodeSize());
 }
 
 void CodeGenerator::Finalize(CodeAllocator* allocator) {
@@ -503,26 +505,77 @@
 
   if (invoke->IsInvokeStaticOrDirect()) {
     HInvokeStaticOrDirect* call = invoke->AsInvokeStaticOrDirect();
-    switch (call->GetMethodLoadKind()) {
-      case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
-        locations->SetInAt(call->GetSpecialInputIndex(), visitor->GetMethodLocation());
-        break;
-      case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall:
-        locations->AddTemp(visitor->GetMethodLocation());
-        locations->SetInAt(call->GetSpecialInputIndex(), Location::RequiresRegister());
-        break;
-      default:
-        locations->AddTemp(visitor->GetMethodLocation());
-        break;
+    MethodLoadKind method_load_kind = call->GetMethodLoadKind();
+    CodePtrLocation code_ptr_location = call->GetCodePtrLocation();
+    if (code_ptr_location == CodePtrLocation::kCallCriticalNative) {
+      locations->AddTemp(Location::RequiresRegister());  // For target method.
+    }
+    if (code_ptr_location == CodePtrLocation::kCallCriticalNative ||
+        method_load_kind == MethodLoadKind::kRecursive) {
+      // For `kCallCriticalNative` we need the current method as the hidden argument
+      // if we reach the dlsym lookup stub for @CriticalNative.
+      locations->SetInAt(call->GetCurrentMethodIndex(), visitor->GetMethodLocation());
+    } else {
+      locations->AddTemp(visitor->GetMethodLocation());
+      if (method_load_kind == MethodLoadKind::kRuntimeCall) {
+        locations->SetInAt(call->GetCurrentMethodIndex(), Location::RequiresRegister());
+      }
     }
   } else if (!invoke->IsInvokePolymorphic()) {
     locations->AddTemp(visitor->GetMethodLocation());
   }
 }
 
+void CodeGenerator::PrepareCriticalNativeArgumentMoves(
+    HInvokeStaticOrDirect* invoke,
+    /*inout*/InvokeDexCallingConventionVisitor* visitor,
+    /*out*/HParallelMove* parallel_move) {
+  LocationSummary* locations = invoke->GetLocations();
+  for (size_t i = 0, num = invoke->GetNumberOfArguments(); i != num; ++i) {
+    Location in_location = locations->InAt(i);
+    DataType::Type type = invoke->InputAt(i)->GetType();
+    DCHECK_NE(type, DataType::Type::kReference);
+    Location out_location = visitor->GetNextLocation(type);
+    if (out_location.IsStackSlot() || out_location.IsDoubleStackSlot()) {
+      // Stack arguments will need to be moved after adjusting the SP.
+      parallel_move->AddMove(in_location, out_location, type, /*instruction=*/ nullptr);
+    } else {
+      // Register arguments should have been assigned their final locations for register allocation.
+      DCHECK(out_location.Equals(in_location)) << in_location << " -> " << out_location;
+    }
+  }
+}
+
+void CodeGenerator::FinishCriticalNativeFrameSetup(size_t out_frame_size,
+                                                   /*inout*/HParallelMove* parallel_move) {
+  DCHECK_NE(out_frame_size, 0u);
+  IncreaseFrame(out_frame_size);
+  // Adjust the source stack offsets by `out_frame_size`, i.e. the additional
+  // frame size needed for outgoing stack arguments.
+  for (size_t i = 0, num = parallel_move->NumMoves(); i != num; ++i) {
+    MoveOperands* operands = parallel_move->MoveOperandsAt(i);
+    Location source = operands->GetSource();
+    if (operands->GetSource().IsStackSlot()) {
+      operands->SetSource(Location::StackSlot(source.GetStackIndex() +  out_frame_size));
+    } else if (operands->GetSource().IsDoubleStackSlot()) {
+      operands->SetSource(Location::DoubleStackSlot(source.GetStackIndex() +  out_frame_size));
+    }
+  }
+  // Emit the moves.
+  GetMoveResolver()->EmitNativeCode(parallel_move);
+}
+
+const char* CodeGenerator::GetCriticalNativeShorty(HInvokeStaticOrDirect* invoke,
+                                                   uint32_t* shorty_len) {
+  ScopedObjectAccess soa(Thread::Current());
+  DCHECK(invoke->GetResolvedMethod()->IsCriticalNative());
+  return invoke->GetResolvedMethod()->GetShorty(shorty_len);
+}
+
 void CodeGenerator::GenerateInvokeStaticOrDirectRuntimeCall(
     HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
-  MoveConstant(temp, invoke->GetDexMethodIndex());
+  MethodReference method_reference(invoke->GetMethodReference());
+  MoveConstant(temp, method_reference.index);
 
   // The access check is unnecessary but we do not want to introduce
   // extra entrypoints for the codegens that do not support some
@@ -551,7 +604,8 @@
   InvokeRuntime(entrypoint, invoke, invoke->GetDexPc(), slow_path);
 }
 void CodeGenerator::GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke) {
-  MoveConstant(invoke->GetLocations()->GetTemp(0), invoke->GetDexMethodIndex());
+  MethodReference method_reference(invoke->GetMethodReference());
+  MoveConstant(invoke->GetLocations()->GetTemp(0), method_reference.index);
 
   // Initialize to anything to silent compiler warnings.
   QuickEntrypointEnum entrypoint = kQuickInvokeStaticTrampolineWithAccessCheck;
@@ -579,12 +633,13 @@
   InvokeRuntime(entrypoint, invoke, invoke->GetDexPc(), nullptr);
 }
 
-void CodeGenerator::GenerateInvokePolymorphicCall(HInvokePolymorphic* invoke) {
+void CodeGenerator::GenerateInvokePolymorphicCall(HInvokePolymorphic* invoke,
+                                                  SlowPathCode* slow_path) {
   // invoke-polymorphic does not use a temporary to convey any additional information (e.g. a
   // method index) since it requires multiple info from the instruction (registers A, B, H). Not
   // using the reservation has no effect on the registers used in the runtime call.
   QuickEntrypointEnum entrypoint = kQuickInvokePolymorphic;
-  InvokeRuntime(entrypoint, invoke, invoke->GetDexPc(), nullptr);
+  InvokeRuntime(entrypoint, invoke, invoke->GetDexPc(), slow_path);
 }
 
 void CodeGenerator::GenerateInvokeCustomCall(HInvokeCustom* invoke) {
@@ -837,7 +892,6 @@
 
 static uint32_t GetBootImageOffsetImpl(const void* object, ImageHeader::ImageSections section) {
   Runtime* runtime = Runtime::Current();
-  DCHECK(runtime->IsAotCompiler());
   const std::vector<gc::space::ImageSpace*>& boot_image_spaces =
       runtime->GetHeap()->GetBootImageSpaces();
   // Check that the `object` is in the expected section of one of the boot image files.
@@ -853,6 +907,10 @@
   return dchecked_integral_cast<uint32_t>(offset);
 }
 
+uint32_t CodeGenerator::GetBootImageOffset(ObjPtr<mirror::Object> object) {
+  return GetBootImageOffsetImpl(object.Ptr(), ImageHeader::kSectionObjects);
+}
+
 // NO_THREAD_SAFETY_ANALYSIS: Avoid taking the mutator lock, boot image classes are non-moveable.
 uint32_t CodeGenerator::GetBootImageOffset(HLoadClass* load_class) NO_THREAD_SAFETY_ANALYSIS {
   DCHECK_EQ(load_class->GetLoadKind(), HLoadClass::LoadKind::kBootImageRelRo);
@@ -869,13 +927,28 @@
   return GetBootImageOffsetImpl(string.Ptr(), ImageHeader::kSectionObjects);
 }
 
-uint32_t CodeGenerator::GetBootImageOffset(HInvokeStaticOrDirect* invoke) {
-  DCHECK_EQ(invoke->GetMethodLoadKind(), HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo);
+uint32_t CodeGenerator::GetBootImageOffset(HInvoke* invoke) {
   ArtMethod* method = invoke->GetResolvedMethod();
   DCHECK(method != nullptr);
   return GetBootImageOffsetImpl(method, ImageHeader::kSectionArtMethods);
 }
 
+// NO_THREAD_SAFETY_ANALYSIS: Avoid taking the mutator lock, boot image objects are non-moveable.
+uint32_t CodeGenerator::GetBootImageOffset(ClassRoot class_root) NO_THREAD_SAFETY_ANALYSIS {
+  ObjPtr<mirror::Class> klass = GetClassRoot<kWithoutReadBarrier>(class_root);
+  return GetBootImageOffsetImpl(klass.Ptr(), ImageHeader::kSectionObjects);
+}
+
+// NO_THREAD_SAFETY_ANALYSIS: Avoid taking the mutator lock, boot image classes are non-moveable.
+uint32_t CodeGenerator::GetBootImageOffsetOfIntrinsicDeclaringClass(HInvoke* invoke)
+    NO_THREAD_SAFETY_ANALYSIS {
+  DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
+  ArtMethod* method = invoke->GetResolvedMethod();
+  DCHECK(method != nullptr);
+  ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass<kWithoutReadBarrier>();
+  return GetBootImageOffsetImpl(declaring_class.Ptr(), ImageHeader::kSectionObjects);
+}
+
 void CodeGenerator::BlockIfInRegister(Location location, bool is_out) const {
   // The DCHECKS below check that a register is not specified twice in
   // the summary. The out location can overlap with an input, so we need
@@ -1594,6 +1667,7 @@
              (kEmitCompilerReadBarrier &&
               !kUseBakerReadBarrier &&
               (instruction->IsInstanceFieldGet() ||
+               instruction->IsPredicatedInstanceFieldGet() ||
                instruction->IsStaticFieldGet() ||
                instruction->IsArrayGet() ||
                instruction->IsLoadClass() ||
@@ -1604,7 +1678,8 @@
           << "instruction->DebugName()=" << instruction->DebugName()
           << " instruction->GetSideEffects().ToString()="
           << instruction->GetSideEffects().ToString()
-          << " slow_path->GetDescription()=" << slow_path->GetDescription();
+          << " slow_path->GetDescription()=" << slow_path->GetDescription() << std::endl
+          << "Instruction and args: " << instruction->DumpWithArgs();
     }
   } else {
     // The GC side effect is not required for the instruction. But the instruction might still have
@@ -1629,6 +1704,7 @@
   // PC-related information.
   DCHECK(kUseBakerReadBarrier);
   DCHECK(instruction->IsInstanceFieldGet() ||
+         instruction->IsPredicatedInstanceFieldGet() ||
          instruction->IsStaticFieldGet() ||
          instruction->IsArrayGet() ||
          instruction->IsArraySet() ||
@@ -1636,8 +1712,7 @@
          instruction->IsLoadString() ||
          instruction->IsInstanceOf() ||
          instruction->IsCheckCast() ||
-         (instruction->IsInvokeVirtual() && instruction->GetLocations()->Intrinsified()) ||
-         (instruction->IsInvokeStaticOrDirect() && instruction->GetLocations()->Intrinsified()))
+         (instruction->IsInvoke() && instruction->GetLocations()->Intrinsified()))
       << "instruction->DebugName()=" << instruction->DebugName()
       << " slow_path->GetDescription()=" << slow_path->GetDescription();
 }
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 9e3e454..338aac0 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -27,6 +27,7 @@
 #include "base/enums.h"
 #include "base/globals.h"
 #include "base/memory_region.h"
+#include "class_root.h"
 #include "dex/string_reference.h"
 #include "dex/type_reference.h"
 #include "graph_visualizer.h"
@@ -223,6 +224,9 @@
   virtual const Assembler& GetAssembler() const = 0;
   virtual size_t GetWordSize() const = 0;
 
+  // Returns whether the target supports predicated SIMD instructions.
+  virtual bool SupportsPredicatedSIMD() const { return false; }
+
   // Get FP register width in bytes for spilling/restoring in the slow paths.
   //
   // Note: In SIMD graphs this should return SIMD register width as all FP and SIMD registers
@@ -235,6 +239,8 @@
   // Get FP register width required to be preserved by the target ABI.
   virtual size_t GetCalleePreservedFPWidth() const  = 0;
 
+  // Get the size of the target SIMD register in bytes.
+  virtual size_t GetSIMDRegisterWidth() const = 0;
   virtual uintptr_t GetAddressOf(HBasicBlock* block) = 0;
   void InitializeCodeGeneration(size_t number_of_spill_slots,
                                 size_t maximum_safepoint_spill_size,
@@ -565,12 +571,34 @@
   static void CreateCommonInvokeLocationSummary(
       HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor);
 
+  template <typename CriticalNativeCallingConventionVisitor,
+            size_t kNativeStackAlignment,
+            size_t GetCriticalNativeDirectCallFrameSize(const char* shorty, uint32_t shorty_len)>
+  size_t PrepareCriticalNativeCall(HInvokeStaticOrDirect* invoke) {
+      DCHECK(!invoke->GetLocations()->Intrinsified());
+      CriticalNativeCallingConventionVisitor calling_convention_visitor(
+          /*for_register_allocation=*/ false);
+      HParallelMove parallel_move(GetGraph()->GetAllocator());
+      PrepareCriticalNativeArgumentMoves(invoke, &calling_convention_visitor, &parallel_move);
+      size_t out_frame_size =
+          RoundUp(calling_convention_visitor.GetStackOffset(), kNativeStackAlignment);
+      if (kIsDebugBuild) {
+        uint32_t shorty_len;
+        const char* shorty = GetCriticalNativeShorty(invoke, &shorty_len);
+        DCHECK_EQ(GetCriticalNativeDirectCallFrameSize(shorty, shorty_len), out_frame_size);
+      }
+      if (out_frame_size != 0u) {
+        FinishCriticalNativeFrameSetup(out_frame_size, &parallel_move);
+      }
+      return out_frame_size;
+  }
+
   void GenerateInvokeStaticOrDirectRuntimeCall(
       HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path);
 
   void GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke);
 
-  void GenerateInvokePolymorphicCall(HInvokePolymorphic* invoke);
+  void GenerateInvokePolymorphicCall(HInvokePolymorphic* invoke, SlowPathCode* slow_path = nullptr);
 
   void GenerateInvokeCustomCall(HInvokeCustom* invoke);
 
@@ -603,9 +631,13 @@
                                                              Location runtime_return_location);
   void GenerateLoadMethodTypeRuntimeCall(HLoadMethodType* method_type);
 
-  uint32_t GetBootImageOffset(HLoadClass* load_class);
-  uint32_t GetBootImageOffset(HLoadString* load_string);
-  uint32_t GetBootImageOffset(HInvokeStaticOrDirect* invoke);
+  static uint32_t GetBootImageOffset(ObjPtr<mirror::Object> object)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  static uint32_t GetBootImageOffset(HLoadClass* load_class);
+  static uint32_t GetBootImageOffset(HLoadString* load_string);
+  static uint32_t GetBootImageOffset(HInvoke* invoke);
+  static uint32_t GetBootImageOffset(ClassRoot class_root);
+  static uint32_t GetBootImageOffsetOfIntrinsicDeclaringClass(HInvoke* invoke);
 
   static void CreateSystemArrayCopyLocationSummary(HInvoke* invoke);
 
@@ -663,6 +695,9 @@
   // Copy the result of a call into the given target.
   virtual void MoveFromReturnRegister(Location trg, DataType::Type type) = 0;
 
+  virtual void IncreaseFrame(size_t adjustment) = 0;
+  virtual void DecreaseFrame(size_t adjustment) = 0;
+
   virtual void GenerateNop() = 0;
 
   static QuickEntrypointEnum GetArrayAllocationEntrypoint(HNewArray* new_array);
@@ -794,6 +829,15 @@
                        bool needs_vreg_info = true);
   void EmitVRegInfo(HEnvironment* environment, SlowPathCode* slow_path);
 
+  static void PrepareCriticalNativeArgumentMoves(
+      HInvokeStaticOrDirect* invoke,
+      /*inout*/InvokeDexCallingConventionVisitor* visitor,
+      /*out*/HParallelMove* parallel_move);
+
+  void FinishCriticalNativeFrameSetup(size_t out_frame_size, /*inout*/HParallelMove* parallel_move);
+
+  static const char* GetCriticalNativeShorty(HInvokeStaticOrDirect* invoke, uint32_t* shorty_len);
+
   OptimizingCompilerStats* stats_;
 
   HGraph* const graph_;
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 7d1b0ea..e1a4718 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -16,11 +16,15 @@
 
 #include "code_generator_arm64.h"
 
+#include "aarch64/assembler-aarch64.h"
+#include "aarch64/registers-aarch64.h"
 #include "arch/arm64/asm_support_arm64.h"
 #include "arch/arm64/instruction_set_features_arm64.h"
+#include "arch/arm64/jni_frame_arm64.h"
 #include "art_method-inl.h"
 #include "base/bit_utils.h"
 #include "base/bit_utils_iterator.h"
+#include "class_root-inl.h"
 #include "class_table.h"
 #include "code_generator_utils.h"
 #include "compiled_method.h"
@@ -29,13 +33,16 @@
 #include "gc/accounting/card_table.h"
 #include "gc/space/image_space.h"
 #include "heap_poisoning.h"
+#include "interpreter/mterp/nterp.h"
 #include "intrinsics.h"
 #include "intrinsics_arm64.h"
 #include "linker/linker_patch.h"
 #include "lock_word.h"
 #include "mirror/array-inl.h"
 #include "mirror/class-inl.h"
+#include "mirror/var_handle.h"
 #include "offsets.h"
+#include "optimizing/common_arm64.h"
 #include "thread.h"
 #include "utils/arm64/assembler_arm64.h"
 #include "utils/assembler.h"
@@ -75,7 +82,6 @@
 using helpers::OutputCPURegister;
 using helpers::OutputFPRegister;
 using helpers::OutputRegister;
-using helpers::QRegisterFrom;
 using helpers::RegisterFrom;
 using helpers::StackOperandFrom;
 using helpers::VIXLRegCodeFromART;
@@ -163,53 +169,6 @@
 #define __ down_cast<CodeGeneratorARM64*>(codegen)->GetVIXLAssembler()->  // NOLINT
 #define QUICK_ENTRY_POINT(x) QUICK_ENTRYPOINT_OFFSET(kArm64PointerSize, x).Int32Value()
 
-// Calculate memory accessing operand for save/restore live registers.
-static void SaveRestoreLiveRegistersHelper(CodeGenerator* codegen,
-                                           LocationSummary* locations,
-                                           int64_t spill_offset,
-                                           bool is_save) {
-  const uint32_t core_spills = codegen->GetSlowPathSpills(locations, /* core_registers= */ true);
-  const uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers= */ false);
-  DCHECK(ArtVixlRegCodeCoherentForRegSet(core_spills,
-                                         codegen->GetNumberOfCoreRegisters(),
-                                         fp_spills,
-                                         codegen->GetNumberOfFloatingPointRegisters()));
-
-  CPURegList core_list = CPURegList(CPURegister::kRegister, kXRegSize, core_spills);
-  unsigned v_reg_size = codegen->GetGraph()->HasSIMD() ? kQRegSize : kDRegSize;
-  CPURegList fp_list = CPURegList(CPURegister::kVRegister, v_reg_size, fp_spills);
-
-  MacroAssembler* masm = down_cast<CodeGeneratorARM64*>(codegen)->GetVIXLAssembler();
-  UseScratchRegisterScope temps(masm);
-
-  Register base = masm->StackPointer();
-  int64_t core_spill_size = core_list.GetTotalSizeInBytes();
-  int64_t fp_spill_size = fp_list.GetTotalSizeInBytes();
-  int64_t reg_size = kXRegSizeInBytes;
-  int64_t max_ls_pair_offset = spill_offset + core_spill_size + fp_spill_size - 2 * reg_size;
-  uint32_t ls_access_size = WhichPowerOf2(reg_size);
-  if (((core_list.GetCount() > 1) || (fp_list.GetCount() > 1)) &&
-      !masm->IsImmLSPair(max_ls_pair_offset, ls_access_size)) {
-    // If the offset does not fit in the instruction's immediate field, use an alternate register
-    // to compute the base address(float point registers spill base address).
-    Register new_base = temps.AcquireSameSizeAs(base);
-    __ Add(new_base, base, Operand(spill_offset + core_spill_size));
-    base = new_base;
-    spill_offset = -core_spill_size;
-    int64_t new_max_ls_pair_offset = fp_spill_size - 2 * reg_size;
-    DCHECK(masm->IsImmLSPair(spill_offset, ls_access_size));
-    DCHECK(masm->IsImmLSPair(new_max_ls_pair_offset, ls_access_size));
-  }
-
-  if (is_save) {
-    __ StoreCPURegList(core_list, MemOperand(base, spill_offset));
-    __ StoreCPURegList(fp_list, MemOperand(base, spill_offset + core_spill_size));
-  } else {
-    __ LoadCPURegList(core_list, MemOperand(base, spill_offset));
-    __ LoadCPURegList(fp_list, MemOperand(base, spill_offset + core_spill_size));
-  }
-}
-
 void SlowPathCodeARM64::SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) {
   size_t stack_offset = codegen->GetFirstRegisterSlotInSlowPath();
   const uint32_t core_spills = codegen->GetSlowPathSpills(locations, /* core_registers= */ true);
@@ -224,7 +183,7 @@
     stack_offset += kXRegSizeInBytes;
   }
 
-  const size_t fp_reg_size = codegen->GetGraph()->HasSIMD() ? kQRegSizeInBytes : kDRegSizeInBytes;
+  const size_t fp_reg_size = codegen->GetSlowPathFPWidth();
   const uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers= */ false);
   for (uint32_t i : LowToHighBits(fp_spills)) {
     DCHECK_LT(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
@@ -233,15 +192,15 @@
     stack_offset += fp_reg_size;
   }
 
-  SaveRestoreLiveRegistersHelper(codegen,
-                                 locations,
-                                 codegen->GetFirstRegisterSlotInSlowPath(), /* is_save= */ true);
+  InstructionCodeGeneratorARM64* visitor =
+      down_cast<CodeGeneratorARM64*>(codegen)->GetInstructionCodeGeneratorArm64();
+  visitor->SaveLiveRegistersHelper(locations, codegen->GetFirstRegisterSlotInSlowPath());
 }
 
 void SlowPathCodeARM64::RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) {
-  SaveRestoreLiveRegistersHelper(codegen,
-                                 locations,
-                                 codegen->GetFirstRegisterSlotInSlowPath(), /* is_save= */ false);
+  InstructionCodeGeneratorARM64* visitor =
+      down_cast<CodeGeneratorARM64*>(codegen)->GetInstructionCodeGeneratorArm64();
+  visitor->RestoreLiveRegistersHelper(locations, codegen->GetFirstRegisterSlotInSlowPath());
 }
 
 class BoundsCheckSlowPathARM64 : public SlowPathCodeARM64 {
@@ -325,8 +284,13 @@
       DCHECK(IsSameDexFile(cls_->GetDexFile(), arm64_codegen->GetGraph()->GetDexFile()));
       dex::TypeIndex type_index = cls_->GetTypeIndex();
       __ Mov(calling_convention.GetRegisterAt(0).W(), type_index.index_);
-      arm64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
-      CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+      if (cls_->NeedsAccessCheck()) {
+        CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>();
+        arm64_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this);
+      } else {
+        CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+        arm64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
+      }
       // If we also must_do_clinit, the resolved type is now in the correct register.
     } else {
       DCHECK(must_do_clinit);
@@ -426,10 +390,10 @@
     LocationSummary* locations = instruction_->GetLocations();
     CodeGeneratorARM64* arm64_codegen = down_cast<CodeGeneratorARM64*>(codegen);
     __ Bind(GetEntryLabel());
-    SaveLiveRegisters(codegen, locations);  // Only saves live 128-bit regs for SIMD.
+    SaveLiveRegisters(codegen, locations);  // Only saves live vector regs for SIMD.
     arm64_codegen->InvokeRuntime(kQuickTestSuspend, instruction_, instruction_->GetDexPc(), this);
     CheckEntrypointTypes<kQuickTestSuspend, void, void>();
-    RestoreLiveRegisters(codegen, locations);  // Only restores live 128-bit regs for SIMD.
+    RestoreLiveRegisters(codegen, locations);  // Only restores live vector regs for SIMD.
     if (successor_ == nullptr) {
       __ B(GetReturnLabel());
     } else {
@@ -636,11 +600,12 @@
     DCHECK(locations->CanCall());
     DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(out_.reg()));
     DCHECK(instruction_->IsInstanceFieldGet() ||
+           instruction_->IsPredicatedInstanceFieldGet() ||
            instruction_->IsStaticFieldGet() ||
            instruction_->IsArrayGet() ||
            instruction_->IsInstanceOf() ||
            instruction_->IsCheckCast() ||
-           (instruction_->IsInvokeVirtual() && instruction_->GetLocations()->Intrinsified()))
+           (instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
         << "Unexpected instruction in read barrier for heap reference slow path: "
         << instruction_->DebugName();
     // The read barrier instrumentation of object ArrayGet
@@ -706,14 +671,24 @@
             "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes.");
         __ Add(index_reg, index_reg, Operand(offset_));
       } else {
-        // In the case of the UnsafeGetObject/UnsafeGetObjectVolatile
+        // In the case of the UnsafeGetObject/UnsafeGetObjectVolatile/VarHandleGet
         // intrinsics, `index_` is not shifted by a scale factor of 2
         // (as in the case of ArrayGet), as it is actually an offset
         // to an object field within an object.
         DCHECK(instruction_->IsInvoke()) << instruction_->DebugName();
         DCHECK(instruction_->GetLocations()->Intrinsified());
-        DCHECK((instruction_->AsInvoke()->GetIntrinsic() == Intrinsics::kUnsafeGetObject) ||
-               (instruction_->AsInvoke()->GetIntrinsic() == Intrinsics::kUnsafeGetObjectVolatile))
+        Intrinsics intrinsic = instruction_->AsInvoke()->GetIntrinsic();
+        DCHECK(intrinsic == Intrinsics::kUnsafeGetObject ||
+               intrinsic == Intrinsics::kUnsafeGetObjectVolatile ||
+               intrinsic == Intrinsics::kUnsafeCASObject ||
+               mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) ==
+                   mirror::VarHandle::AccessModeTemplate::kGet ||
+               mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) ==
+                   mirror::VarHandle::AccessModeTemplate::kCompareAndSet ||
+               mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) ==
+                   mirror::VarHandle::AccessModeTemplate::kCompareAndExchange ||
+               mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) ==
+                   mirror::VarHandle::AccessModeTemplate::kGetAndUpdate)
             << instruction_->AsInvoke()->GetIntrinsic();
         DCHECK_EQ(offset_, 0u);
         DCHECK(index_.IsRegister());
@@ -800,7 +775,9 @@
     DataType::Type type = DataType::Type::kReference;
     DCHECK(locations->CanCall());
     DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(out_.reg()));
-    DCHECK(instruction_->IsLoadClass() || instruction_->IsLoadString())
+    DCHECK(instruction_->IsLoadClass() ||
+           instruction_->IsLoadString() ||
+           (instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
         << "Unexpected instruction in read barrier for GC root slow path: "
         << instruction_->DebugName();
 
@@ -870,6 +847,49 @@
   return LocationFrom(kArtMethodRegister);
 }
 
+Location CriticalNativeCallingConventionVisitorARM64::GetNextLocation(DataType::Type type) {
+  DCHECK_NE(type, DataType::Type::kReference);
+
+  Location location = Location::NoLocation();
+  if (DataType::IsFloatingPointType(type)) {
+    if (fpr_index_ < kParameterFPRegistersLength) {
+      location = LocationFrom(kParameterFPRegisters[fpr_index_]);
+      ++fpr_index_;
+    }
+  } else {
+    // Native ABI uses the same registers as managed, except that the method register x0
+    // is a normal argument.
+    if (gpr_index_ < 1u + kParameterCoreRegistersLength) {
+      location = LocationFrom(gpr_index_ == 0u ? x0 : kParameterCoreRegisters[gpr_index_ - 1u]);
+      ++gpr_index_;
+    }
+  }
+  if (location.IsInvalid()) {
+    if (DataType::Is64BitType(type)) {
+      location = Location::DoubleStackSlot(stack_offset_);
+    } else {
+      location = Location::StackSlot(stack_offset_);
+    }
+    stack_offset_ += kFramePointerSize;
+
+    if (for_register_allocation_) {
+      location = Location::Any();
+    }
+  }
+  return location;
+}
+
+Location CriticalNativeCallingConventionVisitorARM64::GetReturnLocation(DataType::Type type) const {
+  // We perform conversion to the managed ABI return register after the call if needed.
+  InvokeDexCallingConventionVisitorARM64 dex_calling_convention;
+  return dex_calling_convention.GetReturnLocation(type);
+}
+
+Location CriticalNativeCallingConventionVisitorARM64::GetMethodLocation() const {
+  // Pass the method in the hidden argument x15.
+  return Location::RegisterLocation(x15.GetCode());
+}
+
 CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph,
                                        const CompilerOptions& compiler_options,
                                        OptimizingCompilerStats* stats)
@@ -883,8 +903,10 @@
                     stats),
       block_labels_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       jump_tables_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
-      location_builder_(graph, this),
-      instruction_visitor_(graph, this),
+      location_builder_neon_(graph, this),
+      instruction_visitor_neon_(graph, this),
+      location_builder_sve_(graph, this),
+      instruction_visitor_sve_(graph, this),
       move_resolver_(graph->GetAllocator(), this),
       assembler_(graph->GetAllocator(),
                  compiler_options.GetInstructionSetFeatures()->AsArm64InstructionSetFeatures()),
@@ -892,8 +914,11 @@
       method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      boot_image_jni_entrypoint_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       call_entrypoint_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       baker_read_barrier_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -909,6 +934,25 @@
                                          graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)) {
   // Save the link register (containing the return address) to mimic Quick.
   AddAllocatedRegister(LocationFrom(lr));
+
+  bool use_sve = ShouldUseSVE();
+  if (use_sve) {
+    location_builder_ = &location_builder_sve_;
+    instruction_visitor_ = &instruction_visitor_sve_;
+  } else {
+    location_builder_ = &location_builder_neon_;
+    instruction_visitor_ = &instruction_visitor_neon_;
+  }
+}
+
+bool CodeGeneratorARM64::ShouldUseSVE() const {
+  return GetInstructionSetFeatures().HasSVE();
+}
+
+size_t CodeGeneratorARM64::GetSIMDRegisterWidth() const {
+  return SupportsPredicatedSIMD()
+      ? GetInstructionSetFeatures().GetSVEVectorLength() / kBitsPerByte
+      : vixl::aarch64::kQRegSizeInBytes;
 }
 
 #define __ GetVIXLAssembler()->
@@ -923,7 +967,7 @@
   EmitJumpTables();
 
   // Emit JIT baker read barrier slow paths.
-  DCHECK(Runtime::Current()->UseJitCompilation() || jit_baker_read_barrier_slow_paths_.empty());
+  DCHECK(GetCompilerOptions().IsJitCompiler() || jit_baker_read_barrier_slow_paths_.empty());
   for (auto& entry : jit_baker_read_barrier_slow_paths_) {
     uint32_t encoded_data = entry.first;
     vixl::aarch64::Label* slow_path_entry = &entry.second.label;
@@ -989,7 +1033,7 @@
           uint32_t prev_insn = GetInsn(literal_offset - 4u);
           const uint32_t root_reg = BakerReadBarrierFirstRegField::Decode(encoded_data);
           // Usually LDR (immediate) with correct root_reg but
-          // we may have a "MOV marked, old_value" for UnsafeCASObject.
+          // we may have a "MOV marked, old_value" for intrinsic CAS.
           if ((prev_insn & 0xffe0ffff) != (0x2a0003e0 | root_reg)) {    // MOV?
             CHECK_EQ(prev_insn & 0xffc0001fu, 0xb9400000u | root_reg);  // LDR?
           }
@@ -1038,9 +1082,9 @@
     scratch = LocationFrom(vixl_temps_.AcquireX());
   } else {
     DCHECK_EQ(kind, Location::kFpuRegister);
-    scratch = LocationFrom(codegen_->GetGraph()->HasSIMD()
-        ? vixl_temps_.AcquireVRegisterOfSize(kQRegSize)
-        : vixl_temps_.AcquireD());
+    scratch = codegen_->GetGraph()->HasSIMD()
+        ? codegen_->GetInstructionCodeGeneratorArm64()->AllocateSIMDScratchLocation(&vixl_temps_)
+        : LocationFrom(vixl_temps_.AcquireD());
   }
   AddScratchLocation(scratch);
   return scratch;
@@ -1051,7 +1095,11 @@
     vixl_temps_.Release(XRegisterFrom(loc));
   } else {
     DCHECK(loc.IsFpuRegister());
-    vixl_temps_.Release(codegen_->GetGraph()->HasSIMD() ? QRegisterFrom(loc) : DRegisterFrom(loc));
+    if (codegen_->GetGraph()->HasSIMD()) {
+      codegen_->GetInstructionCodeGeneratorArm64()->FreeSIMDScratchLocation(loc, &vixl_temps_);
+    } else {
+      vixl_temps_.Release(DRegisterFrom(loc));
+    }
   }
   RemoveScratchLocation(loc);
 }
@@ -1078,8 +1126,9 @@
   }
 
   if (GetGraph()->IsCompilingBaseline() && !Runtime::Current()->IsAotCompiler()) {
-    ScopedObjectAccess soa(Thread::Current());
-    ProfilingInfo* info = GetGraph()->GetArtMethod()->GetProfilingInfo(kRuntimePointerSize);
+    ScopedProfilingInfoUse spiu(
+        Runtime::Current()->GetJit(), GetGraph()->GetArtMethod(), Thread::Current());
+    ProfilingInfo* info = spiu.GetProfilingInfo();
     if (info != nullptr) {
       uint64_t address = reinterpret_cast64<uint64_t>(info);
       vixl::aarch64::Label done;
@@ -1089,14 +1138,14 @@
       __ Mov(temp, address);
       __ Ldrh(counter, MemOperand(temp, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()));
       __ Add(counter, counter, 1);
+      __ And(counter, counter, interpreter::kTieredHotnessMask);
       __ Strh(counter, MemOperand(temp, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()));
-      __ Tst(counter, 0xffff);
-      __ B(ne, &done);
+      __ Cbnz(counter, &done);
       if (is_frame_entry) {
         if (HasEmptyFrame()) {
-          // The entyrpoint expects the method at the bottom of the stack. We
+          // The entrypoint expects the method at the bottom of the stack. We
           // claim stack space necessary for alignment.
-          __ Claim(kStackAlignment);
+          IncreaseFrame(kStackAlignment);
           __ Stp(kArtMethodRegister, lr, MemOperand(sp, 0));
         } else if (!RequiresCurrentMethod()) {
           __ Str(kArtMethodRegister, MemOperand(sp, 0));
@@ -1113,7 +1162,7 @@
       if (HasEmptyFrame()) {
         CHECK(is_frame_entry);
         __ Ldr(lr, MemOperand(sp, 8));
-        __ Drop(kStackAlignment);
+        DecreaseFrame(kStackAlignment);
       }
       __ Bind(&done);
     }
@@ -1434,7 +1483,7 @@
       DCHECK(dst.Is64Bits() == source.IsDoubleStackSlot());
       __ Ldr(dst, StackOperandFrom(source));
     } else if (source.IsSIMDStackSlot()) {
-      __ Ldr(QRegisterFrom(destination), StackOperandFrom(source));
+      GetInstructionCodeGeneratorArm64()->LoadSIMDRegFromStack(destination, source);
     } else if (source.IsConstant()) {
       DCHECK(CoherentConstantAndType(source, dst_type));
       MoveConstant(dst, source.GetConstant());
@@ -1458,30 +1507,14 @@
       } else {
         DCHECK(destination.IsFpuRegister());
         if (GetGraph()->HasSIMD()) {
-          __ Mov(QRegisterFrom(destination), QRegisterFrom(source));
+          GetInstructionCodeGeneratorArm64()->MoveSIMDRegToSIMDReg(destination, source);
         } else {
           __ Fmov(VRegister(dst), FPRegisterFrom(source, dst_type));
         }
       }
     }
   } else if (destination.IsSIMDStackSlot()) {
-    if (source.IsFpuRegister()) {
-      __ Str(QRegisterFrom(source), StackOperandFrom(destination));
-    } else {
-      DCHECK(source.IsSIMDStackSlot());
-      UseScratchRegisterScope temps(GetVIXLAssembler());
-      if (GetVIXLAssembler()->GetScratchVRegisterList()->IsEmpty()) {
-        Register temp = temps.AcquireX();
-        __ Ldr(temp, MemOperand(sp, source.GetStackIndex()));
-        __ Str(temp, MemOperand(sp, destination.GetStackIndex()));
-        __ Ldr(temp, MemOperand(sp, source.GetStackIndex() + kArm64WordSize));
-        __ Str(temp, MemOperand(sp, destination.GetStackIndex() + kArm64WordSize));
-      } else {
-        VRegister temp = temps.AcquireVRegisterOfSize(kQRegSize);
-        __ Ldr(temp, StackOperandFrom(source));
-        __ Str(temp, StackOperandFrom(destination));
-      }
-    }
+    GetInstructionCodeGeneratorArm64()->MoveToSIMDStackSlot(destination, source);
   } else {  // The destination is not a register. It must be a stack slot.
     DCHECK(destination.IsStackSlot() || destination.IsDoubleStackSlot());
     if (source.IsRegister() || source.IsFpuRegister()) {
@@ -1582,13 +1615,13 @@
 }
 
 void CodeGeneratorARM64::LoadAcquire(HInstruction* instruction,
+                                     DataType::Type type,
                                      CPURegister dst,
                                      const MemOperand& src,
                                      bool needs_null_check) {
   MacroAssembler* masm = GetVIXLAssembler();
   UseScratchRegisterScope temps(masm);
   Register temp_base = temps.AcquireX();
-  DataType::Type type = instruction->GetType();
 
   DCHECK(!src.IsPreIndex());
   DCHECK(!src.IsPostIndex());
@@ -1779,7 +1812,7 @@
   // Reduce code size for AOT by using shared trampolines for slow path runtime calls across the
   // entire oat file. This adds an extra branch and we do not want to slow down the main path.
   // For JIT, thunk sharing is per-method, so the gains would be smaller or even negative.
-  if (slow_path == nullptr || Runtime::Current()->UseJitCompilation()) {
+  if (slow_path == nullptr || GetCompilerOptions().IsJitCompiler()) {
     __ Ldr(lr, MemOperand(tr, entrypoint_offset.Int32Value()));
     // Ensure the pc position is recorded immediately after the `blr` instruction.
     ExactAssemblyScope eas(GetVIXLAssembler(), kInstructionSize, CodeBufferCheckScope::kExactSize);
@@ -1931,7 +1964,11 @@
 
 void LocationsBuilderARM64::HandleFieldGet(HInstruction* instruction,
                                            const FieldInfo& field_info) {
-  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
+  DCHECK(instruction->IsInstanceFieldGet() ||
+         instruction->IsStaticFieldGet() ||
+         instruction->IsPredicatedInstanceFieldGet());
+
+  bool is_predicated = instruction->IsPredicatedInstanceFieldGet();
 
   bool object_field_get_with_read_barrier =
       kEmitCompilerReadBarrier && (instruction->GetType() == DataType::Type::kReference);
@@ -1950,29 +1987,45 @@
       locations->AddTemp(FixedTempLocation());
     }
   }
-  locations->SetInAt(0, Location::RequiresRegister());
+  // Input for object receiver.
+  locations->SetInAt(is_predicated ? 1 : 0, Location::RequiresRegister());
   if (DataType::IsFloatingPointType(instruction->GetType())) {
-    locations->SetOut(Location::RequiresFpuRegister());
+    if (is_predicated) {
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+    } else {
+      locations->SetOut(Location::RequiresFpuRegister());
+    }
   } else {
-    // The output overlaps for an object field get when read barriers
-    // are enabled: we do not want the load to overwrite the object's
-    // location, as we need it to emit the read barrier.
-    locations->SetOut(
-        Location::RequiresRegister(),
-        object_field_get_with_read_barrier ? Location::kOutputOverlap : Location::kNoOutputOverlap);
+    if (is_predicated) {
+      locations->SetInAt(0, Location::RequiresRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+    } else {
+      // The output overlaps for an object field get when read barriers
+      // are enabled: we do not want the load to overwrite the object's
+      // location, as we need it to emit the read barrier.
+      locations->SetOut(Location::RequiresRegister(),
+                        object_field_get_with_read_barrier ? Location::kOutputOverlap
+                                                           : Location::kNoOutputOverlap);
+    }
   }
 }
 
 void InstructionCodeGeneratorARM64::HandleFieldGet(HInstruction* instruction,
                                                    const FieldInfo& field_info) {
-  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
+  DCHECK(instruction->IsInstanceFieldGet() ||
+         instruction->IsStaticFieldGet() ||
+         instruction->IsPredicatedInstanceFieldGet());
+  bool is_predicated = instruction->IsPredicatedInstanceFieldGet();
   LocationSummary* locations = instruction->GetLocations();
-  Location base_loc = locations->InAt(0);
+  uint32_t receiver_input = is_predicated ? 1 : 0;
+  Location base_loc = locations->InAt(receiver_input);
   Location out = locations->Out();
   uint32_t offset = field_info.GetFieldOffset().Uint32Value();
   DCHECK_EQ(DataType::Size(field_info.GetFieldType()), DataType::Size(instruction->GetType()));
   DataType::Type load_type = instruction->GetType();
-  MemOperand field = HeapOperand(InputRegisterAt(instruction, 0), field_info.GetFieldOffset());
+  MemOperand field =
+      HeapOperand(InputRegisterAt(instruction, receiver_input), field_info.GetFieldOffset());
 
   if (kEmitCompilerReadBarrier && kUseBakerReadBarrier &&
       load_type == DataType::Type::kReference) {
@@ -1997,8 +2050,11 @@
       // Note that a potential implicit null check is handled in this
       // CodeGeneratorARM64::LoadAcquire call.
       // NB: LoadAcquire will record the pc info if needed.
-      codegen_->LoadAcquire(
-          instruction, OutputCPURegister(instruction), field, /* needs_null_check= */ true);
+      codegen_->LoadAcquire(instruction,
+                            load_type,
+                            OutputCPURegister(instruction),
+                            field,
+                            /* needs_null_check= */ true);
     } else {
       // Ensure that between load and MaybeRecordImplicitNullCheck there are no pools emitted.
       EmissionCheckScope guard(GetVIXLAssembler(), kMaxMacroInstructionSizeInBytes);
@@ -2031,12 +2087,19 @@
                                                    const FieldInfo& field_info,
                                                    bool value_can_be_null) {
   DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
+  bool is_predicated =
+      instruction->IsInstanceFieldSet() && instruction->AsInstanceFieldSet()->GetIsPredicatedSet();
 
   Register obj = InputRegisterAt(instruction, 0);
   CPURegister value = InputCPURegisterOrZeroRegAt(instruction, 1);
   CPURegister source = value;
   Offset offset = field_info.GetFieldOffset();
   DataType::Type field_type = field_info.GetFieldType();
+  std::optional<vixl::aarch64::Label> pred_is_null;
+  if (is_predicated) {
+    pred_is_null.emplace();
+    __ Cbz(obj, &*pred_is_null);
+  }
 
   {
     // We use a block to end the scratch scope before the write barrier, thus
@@ -2065,6 +2128,10 @@
   if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
     codegen_->MarkGCCard(obj, Register(value), value_can_be_null);
   }
+
+  if (is_predicated) {
+    __ Bind(&*pred_is_null);
+  }
 }
 
 void InstructionCodeGeneratorARM64::HandleBinaryOp(HBinaryOperation* instr) {
@@ -3013,27 +3080,149 @@
   Register out = OutputRegister(instruction);
   Register dividend = InputRegisterAt(instruction, 0);
 
-  if (abs_imm == 2) {
-    int bits = DataType::Size(instruction->GetResultType()) * kBitsPerByte;
-    __ Add(out, dividend, Operand(dividend, LSR, bits - 1));
+  Register final_dividend;
+  if (HasNonNegativeOrMinIntInputAt(instruction, 0)) {
+    // No need to adjust the result for non-negative dividends or the INT32_MIN/INT64_MIN dividends.
+    // NOTE: The generated code for HDiv correctly works for the INT32_MIN/INT64_MIN dividends:
+    //   imm == 2
+    //     add out, dividend(0x80000000), dividend(0x80000000), lsr #31 => out = 0x80000001
+    //     asr out, out(0x80000001), #1 => out = 0xc0000000
+    //     This is the same as 'asr out, 0x80000000, #1'
+    //
+    //   imm > 2
+    //     add temp, dividend(0x80000000), imm - 1 => temp = 0b10..01..1, where the number
+    //         of the rightmost 1s is ctz_imm.
+    //     cmp dividend(0x80000000), 0 => N = 1, V = 0 (lt is true)
+    //     csel out, temp(0b10..01..1), dividend(0x80000000), lt => out = 0b10..01..1
+    //     asr out, out(0b10..01..1), #ctz_imm => out = 0b1..10..0, where the number of the
+    //         leftmost 1s is ctz_imm + 1.
+    //     This is the same as 'asr out, dividend(0x80000000), #ctz_imm'.
+    //
+    //   imm == INT32_MIN
+    //     add tmp, dividend(0x80000000), #0x7fffffff => tmp = -1
+    //     cmp dividend(0x80000000), 0 => N = 1, V = 0 (lt is true)
+    //     csel out, temp(-1), dividend(0x80000000), lt => out = -1
+    //     neg out, out(-1), asr #31 => out = 1
+    //     This is the same as 'neg out, dividend(0x80000000), asr #31'.
+    final_dividend = dividend;
   } else {
-    UseScratchRegisterScope temps(GetVIXLAssembler());
-    Register temp = temps.AcquireSameSizeAs(out);
-    __ Add(temp, dividend, abs_imm - 1);
-    __ Cmp(dividend, 0);
-    __ Csel(out, temp, dividend, lt);
+    if (abs_imm == 2) {
+      int bits = DataType::Size(instruction->GetResultType()) * kBitsPerByte;
+      __ Add(out, dividend, Operand(dividend, LSR, bits - 1));
+    } else {
+      UseScratchRegisterScope temps(GetVIXLAssembler());
+      Register temp = temps.AcquireSameSizeAs(out);
+      __ Add(temp, dividend, abs_imm - 1);
+      __ Cmp(dividend, 0);
+      __ Csel(out, temp, dividend, lt);
+    }
+    final_dividend = out;
   }
 
   int ctz_imm = CTZ(abs_imm);
   if (imm > 0) {
-    __ Asr(out, out, ctz_imm);
+    __ Asr(out, final_dividend, ctz_imm);
   } else {
-    __ Neg(out, Operand(out, ASR, ctz_imm));
+    __ Neg(out, Operand(final_dividend, ASR, ctz_imm));
   }
 }
 
-void InstructionCodeGeneratorARM64::GenerateDivRemWithAnyConstant(HBinaryOperation* instruction) {
+// Return true if the magic number was modified by subtracting 2^32(Int32 div) or 2^64(Int64 div).
+// So dividend needs to be added.
+static inline bool NeedToAddDividend(int64_t magic_number, int64_t divisor) {
+  return divisor > 0 && magic_number < 0;
+}
+
+// Return true if the magic number was modified by adding 2^32(Int32 div) or 2^64(Int64 div).
+// So dividend needs to be subtracted.
+static inline bool NeedToSubDividend(int64_t magic_number, int64_t divisor) {
+  return divisor < 0 && magic_number > 0;
+}
+
+// Generate code which increments the value in register 'in' by 1 if the value is negative.
+// It is done with 'add out, in, in, lsr #31 or #63'.
+// If the value is a result of an operation setting the N flag, CINC MI can be used
+// instead of ADD. 'use_cond_inc' controls this.
+void InstructionCodeGeneratorARM64::GenerateIncrementNegativeByOne(
+    Register out,
+    Register in,
+    bool use_cond_inc) {
+  if (use_cond_inc) {
+    __ Cinc(out, in, mi);
+  } else {
+    __ Add(out, in, Operand(in, LSR, in.GetSizeInBits() - 1));
+  }
+}
+
+// Helper to generate code producing the result of HRem with a constant divisor.
+void InstructionCodeGeneratorARM64::GenerateResultRemWithAnyConstant(
+    Register out,
+    Register dividend,
+    Register quotient,
+    int64_t divisor,
+    UseScratchRegisterScope* temps_scope) {
+  Register temp_imm = temps_scope->AcquireSameSizeAs(out);
+  __ Mov(temp_imm, divisor);
+  __ Msub(out, quotient, temp_imm, dividend);
+}
+
+// Helper to generate code for HDiv/HRem instructions when a dividend is non-negative and
+// a divisor is a positive constant, not power of 2.
+void InstructionCodeGeneratorARM64::GenerateInt64UnsignedDivRemWithAnyPositiveConstant(
+    HBinaryOperation* instruction) {
   DCHECK(instruction->IsDiv() || instruction->IsRem());
+  DCHECK(instruction->GetResultType() == DataType::Type::kInt64);
+
+  LocationSummary* locations = instruction->GetLocations();
+  Location second = locations->InAt(1);
+  DCHECK(second.IsConstant());
+
+  Register out = OutputRegister(instruction);
+  Register dividend = InputRegisterAt(instruction, 0);
+  int64_t imm = Int64FromConstant(second.GetConstant());
+  DCHECK_GT(imm, 0);
+
+  int64_t magic;
+  int shift;
+  CalculateMagicAndShiftForDivRem(imm, /* is_long= */ true, &magic, &shift);
+
+  UseScratchRegisterScope temps(GetVIXLAssembler());
+  Register temp = temps.AcquireSameSizeAs(out);
+
+  auto generate_unsigned_div_code = [this, magic, shift](Register out,
+                                                         Register dividend,
+                                                         Register temp) {
+    // temp = get_high(dividend * magic)
+    __ Mov(temp, magic);
+    if (magic > 0 && shift == 0) {
+      __ Smulh(out, dividend, temp);
+    } else {
+      __ Smulh(temp, dividend, temp);
+      if (magic < 0) {
+        // The negative magic means that the multiplier m is greater than INT64_MAX.
+        // In such a case shift is never 0. See the proof in
+        // InstructionCodeGeneratorARMVIXL::GenerateDivRemWithAnyConstant.
+        __ Add(temp, temp, dividend);
+      }
+      DCHECK_NE(shift, 0);
+      __ Lsr(out, temp, shift);
+    }
+  };
+
+  if (instruction->IsDiv()) {
+    generate_unsigned_div_code(out, dividend, temp);
+  } else {
+    generate_unsigned_div_code(temp, dividend, temp);
+    GenerateResultRemWithAnyConstant(out, dividend, temp, imm, &temps);
+  }
+}
+
+// Helper to generate code for HDiv/HRem instructions for any dividend and a constant divisor
+// (not power of 2).
+void InstructionCodeGeneratorARM64::GenerateInt64DivRemWithAnyConstant(
+    HBinaryOperation* instruction) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+  DCHECK(instruction->GetResultType() == DataType::Type::kInt64);
 
   LocationSummary* locations = instruction->GetLocations();
   Location second = locations->InAt(1);
@@ -3043,44 +3232,123 @@
   Register dividend = InputRegisterAt(instruction, 0);
   int64_t imm = Int64FromConstant(second.GetConstant());
 
-  DataType::Type type = instruction->GetResultType();
-  DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64);
-
   int64_t magic;
   int shift;
-  CalculateMagicAndShiftForDivRem(
-      imm, /* is_long= */ type == DataType::Type::kInt64, &magic, &shift);
+  CalculateMagicAndShiftForDivRem(imm, /* is_long= */ true, &magic, &shift);
 
   UseScratchRegisterScope temps(GetVIXLAssembler());
   Register temp = temps.AcquireSameSizeAs(out);
 
   // temp = get_high(dividend * magic)
   __ Mov(temp, magic);
-  if (type == DataType::Type::kInt64) {
-    __ Smulh(temp, dividend, temp);
-  } else {
-    __ Smull(temp.X(), dividend, temp);
-    __ Lsr(temp.X(), temp.X(), 32);
-  }
+  __ Smulh(temp, dividend, temp);
 
-  if (imm > 0 && magic < 0) {
-    __ Add(temp, temp, dividend);
-  } else if (imm < 0 && magic > 0) {
-    __ Sub(temp, temp, dividend);
+  // The multiplication result might need some corrections to be finalized.
+  // The last correction is to increment by 1, if the result is negative.
+  // Currently it is done with 'add result, temp_result, temp_result, lsr #31 or #63'.
+  // Such ADD usually has latency 2, e.g. on Cortex-A55.
+  // However if one of the corrections is ADD or SUB, the sign can be detected
+  // with ADDS/SUBS. They set the N flag if the result is negative.
+  // This allows to use CINC MI which has latency 1.
+  bool use_cond_inc = false;
+
+  // Some combinations of magic_number and the divisor require to correct the result.
+  // Check whether the correction is needed.
+  if (NeedToAddDividend(magic, imm)) {
+    __ Adds(temp, temp, dividend);
+    use_cond_inc = true;
+  } else if (NeedToSubDividend(magic, imm)) {
+    __ Subs(temp, temp, dividend);
+    use_cond_inc = true;
   }
 
   if (shift != 0) {
     __ Asr(temp, temp, shift);
   }
 
-  if (instruction->IsDiv()) {
-    __ Sub(out, temp, Operand(temp, ASR, type == DataType::Type::kInt64 ? 63 : 31));
+  if (instruction->IsRem()) {
+    GenerateIncrementNegativeByOne(temp, temp, use_cond_inc);
+    GenerateResultRemWithAnyConstant(out, dividend, temp, imm, &temps);
   } else {
-    __ Sub(temp, temp, Operand(temp, ASR, type == DataType::Type::kInt64 ? 63 : 31));
-    // TODO: Strength reduction for msub.
-    Register temp_imm = temps.AcquireSameSizeAs(out);
-    __ Mov(temp_imm, imm);
-    __ Msub(out, temp, temp_imm, dividend);
+    GenerateIncrementNegativeByOne(out, temp, use_cond_inc);
+  }
+}
+
+void InstructionCodeGeneratorARM64::GenerateInt32DivRemWithAnyConstant(
+    HBinaryOperation* instruction) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+  DCHECK(instruction->GetResultType() == DataType::Type::kInt32);
+
+  LocationSummary* locations = instruction->GetLocations();
+  Location second = locations->InAt(1);
+  DCHECK(second.IsConstant());
+
+  Register out = OutputRegister(instruction);
+  Register dividend = InputRegisterAt(instruction, 0);
+  int64_t imm = Int64FromConstant(second.GetConstant());
+
+  int64_t magic;
+  int shift;
+  CalculateMagicAndShiftForDivRem(imm, /* is_long= */ false, &magic, &shift);
+  UseScratchRegisterScope temps(GetVIXLAssembler());
+  Register temp = temps.AcquireSameSizeAs(out);
+
+  // temp = get_high(dividend * magic)
+  __ Mov(temp, magic);
+  __ Smull(temp.X(), dividend, temp);
+
+  // The multiplication result might need some corrections to be finalized.
+  // The last correction is to increment by 1, if the result is negative.
+  // Currently it is done with 'add result, temp_result, temp_result, lsr #31 or #63'.
+  // Such ADD usually has latency 2, e.g. on Cortex-A55.
+  // However if one of the corrections is ADD or SUB, the sign can be detected
+  // with ADDS/SUBS. They set the N flag if the result is negative.
+  // This allows to use CINC MI which has latency 1.
+  bool use_cond_inc = false;
+
+  // ADD/SUB correction is performed in the high 32 bits
+  // as high 32 bits are ignored because type are kInt32.
+  if (NeedToAddDividend(magic, imm)) {
+    __ Adds(temp.X(), temp.X(), Operand(dividend.X(), LSL, 32));
+    use_cond_inc = true;
+  } else if (NeedToSubDividend(magic, imm)) {
+    __ Subs(temp.X(), temp.X(), Operand(dividend.X(), LSL, 32));
+    use_cond_inc = true;
+  }
+
+  // Extract the result from the high 32 bits and apply the final right shift.
+  DCHECK_LT(shift, 32);
+  if (imm > 0 && HasNonNegativeInputAt(instruction, 0)) {
+    // No need to adjust the result for a non-negative dividend and a positive divisor.
+    if (instruction->IsDiv()) {
+      __ Lsr(out.X(), temp.X(), 32 + shift);
+    } else {
+      __ Lsr(temp.X(), temp.X(), 32 + shift);
+      GenerateResultRemWithAnyConstant(out, dividend, temp, imm, &temps);
+    }
+  } else {
+    __ Asr(temp.X(), temp.X(), 32 + shift);
+
+    if (instruction->IsRem()) {
+      GenerateIncrementNegativeByOne(temp, temp, use_cond_inc);
+      GenerateResultRemWithAnyConstant(out, dividend, temp, imm, &temps);
+    } else {
+      GenerateIncrementNegativeByOne(out, temp, use_cond_inc);
+    }
+  }
+}
+
+void InstructionCodeGeneratorARM64::GenerateDivRemWithAnyConstant(HBinaryOperation* instruction,
+                                                                  int64_t divisor) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+  if (instruction->GetResultType() == DataType::Type::kInt64) {
+    if (divisor > 0 && HasNonNegativeInputAt(instruction, 0)) {
+      GenerateInt64UnsignedDivRemWithAnyPositiveConstant(instruction);
+    } else {
+      GenerateInt64DivRemWithAnyConstant(instruction);
+    }
+  } else {
+    GenerateInt32DivRemWithAnyConstant(instruction);
   }
 }
 
@@ -3097,7 +3365,7 @@
   } else {
     // Cases imm == -1 or imm == 1 are handled by InstructionSimplifier.
     DCHECK(imm < -2 || imm > 2) << imm;
-    GenerateDivRemWithAnyConstant(instruction);
+    GenerateDivRemWithAnyConstant(instruction, imm);
   }
 }
 
@@ -3505,14 +3773,37 @@
   // MaybeRecordNativeDebugInfo is already called implicitly in CodeGenerator::Compile.
 }
 
+void CodeGeneratorARM64::IncreaseFrame(size_t adjustment) {
+  __ Claim(adjustment);
+  GetAssembler()->cfi().AdjustCFAOffset(adjustment);
+}
+
+void CodeGeneratorARM64::DecreaseFrame(size_t adjustment) {
+  __ Drop(adjustment);
+  GetAssembler()->cfi().AdjustCFAOffset(-adjustment);
+}
+
 void CodeGeneratorARM64::GenerateNop() {
   __ Nop();
 }
 
+void LocationsBuilderARM64::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* instruction) {
+  HandleFieldGet(instruction, instruction->GetFieldInfo());
+}
+
 void LocationsBuilderARM64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
   HandleFieldGet(instruction, instruction->GetFieldInfo());
 }
 
+void InstructionCodeGeneratorARM64::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* instruction) {
+  vixl::aarch64::Label finish;
+  __ Cbz(InputRegisterAt(instruction, 1), &finish);
+  HandleFieldGet(instruction, instruction->GetFieldInfo());
+  __ Bind(&finish);
+}
+
 void InstructionCodeGeneratorARM64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
   HandleFieldGet(instruction, instruction->GetFieldInfo());
 }
@@ -4078,6 +4369,10 @@
 
 void LocationsBuilderARM64::VisitInvokeInterface(HInvokeInterface* invoke) {
   HandleInvoke(invoke);
+  if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive) {
+    // We cannot request ip1 as it's blocked by the register allocator.
+    invoke->GetLocations()->SetInAt(invoke->GetNumberOfArguments() - 1, Location::Any());
+  }
 }
 
 void CodeGeneratorARM64::MaybeGenerateInlineCacheCheck(HInstruction* instruction,
@@ -4089,8 +4384,9 @@
       GetGraph()->IsCompilingBaseline() &&
       !Runtime::Current()->IsAotCompiler()) {
     DCHECK(!instruction->GetEnvironment()->IsFromInlinedInvoke());
-    ScopedObjectAccess soa(Thread::Current());
-    ProfilingInfo* info = GetGraph()->GetArtMethod()->GetProfilingInfo(kRuntimePointerSize);
+    ScopedProfilingInfoUse spiu(
+        Runtime::Current()->GetJit(), GetGraph()->GetArtMethod(), Thread::Current());
+    ProfilingInfo* info = spiu.GetProfilingInfo();
     if (info != nullptr) {
       InlineCache* cache = info->GetInlineCache(instruction->GetDexPc());
       uint64_t address = reinterpret_cast64<uint64_t>(cache);
@@ -4147,7 +4443,21 @@
   MacroAssembler* masm = GetVIXLAssembler();
   UseScratchRegisterScope scratch_scope(masm);
   scratch_scope.Exclude(ip1);
-  __ Mov(ip1, invoke->GetDexMethodIndex());
+  if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive) {
+    Location interface_method = locations->InAt(invoke->GetNumberOfArguments() - 1);
+    if (interface_method.IsStackSlot()) {
+      __ Ldr(ip1, StackOperandFrom(interface_method));
+    } else {
+      __ Mov(ip1, XRegisterFrom(interface_method));
+    }
+  // If the load kind is through a runtime call, we will pass the method we
+  // fetch the IMT, which will either be a no-op if we don't hit the conflict
+  // stub, or will make us always go through the trampoline when there is a
+  // conflict.
+  } else if (invoke->GetHiddenArgumentLoadKind() != MethodLoadKind::kRuntimeCall) {
+    codegen_->LoadMethod(
+        invoke->GetHiddenArgumentLoadKind(), Location::RegisterLocation(ip1.GetCode()), invoke);
+  }
 
   __ Ldr(temp,
       MemOperand(temp, mirror::Class::ImtPtrOffset(kArm64PointerSize).Uint32Value()));
@@ -4155,6 +4465,11 @@
       invoke->GetImtIndex(), kArm64PointerSize));
   // temp = temp->GetImtEntryAt(method_offset);
   __ Ldr(temp, MemOperand(temp, method_offset));
+  if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRuntimeCall) {
+    // We pass the method from the IMT in case of a conflict. This will ensure
+    // we go into the runtime to resolve the actual method.
+    __ Mov(ip1, temp);
+  }
   // lr = temp->GetEntryPoint();
   __ Ldr(lr, MemOperand(temp, entry_point.Int32Value()));
 
@@ -4190,7 +4505,13 @@
     return;
   }
 
-  HandleInvoke(invoke);
+  if (invoke->GetCodePtrLocation() == CodePtrLocation::kCallCriticalNative) {
+    CriticalNativeCallingConventionVisitorARM64 calling_convention_visitor(
+        /*for_register_allocation=*/ true);
+    CodeGenerator::CreateCommonInvokeLocationSummary(invoke, &calling_convention_visitor);
+  } else {
+    HandleInvoke(invoke);
+  }
 }
 
 static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorARM64* codegen) {
@@ -4209,33 +4530,21 @@
   return desired_dispatch_info;
 }
 
-void CodeGeneratorARM64::GenerateStaticOrDirectCall(
-    HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
-  // Make sure that ArtMethod* is passed in kArtMethodRegister as per the calling convention.
-  Location callee_method = temp;  // For all kinds except kRecursive, callee will be in temp.
-  switch (invoke->GetMethodLoadKind()) {
-    case HInvokeStaticOrDirect::MethodLoadKind::kStringInit: {
-      uint32_t offset =
-          GetThreadOffset<kArm64PointerSize>(invoke->GetStringInitEntryPoint()).Int32Value();
-      // temp = thread->string_init_entrypoint
-      __ Ldr(XRegisterFrom(temp), MemOperand(tr, offset));
-      break;
-    }
-    case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
-      callee_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
-      break;
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative: {
+void CodeGeneratorARM64::LoadMethod(MethodLoadKind load_kind, Location temp, HInvoke* invoke) {
+  switch (load_kind) {
+    case MethodLoadKind::kBootImageLinkTimePcRelative: {
       DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
       // Add ADRP with its PC-relative method patch.
-      vixl::aarch64::Label* adrp_label = NewBootImageMethodPatch(invoke->GetTargetMethod());
+      vixl::aarch64::Label* adrp_label =
+          NewBootImageMethodPatch(invoke->GetResolvedMethodReference());
       EmitAdrpPlaceholder(adrp_label, XRegisterFrom(temp));
       // Add ADD with its PC-relative method patch.
       vixl::aarch64::Label* add_label =
-          NewBootImageMethodPatch(invoke->GetTargetMethod(), adrp_label);
+          NewBootImageMethodPatch(invoke->GetResolvedMethodReference(), adrp_label);
       EmitAddPlaceholder(add_label, XRegisterFrom(temp), XRegisterFrom(temp));
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
+    case MethodLoadKind::kBootImageRelRo: {
       // Add ADRP with its PC-relative .data.bimg.rel.ro patch.
       uint32_t boot_image_offset = GetBootImageOffset(invoke);
       vixl::aarch64::Label* adrp_label = NewBootImageRelRoPatch(boot_image_offset);
@@ -4246,30 +4555,86 @@
       EmitLdrOffsetPlaceholder(ldr_label, WRegisterFrom(temp), XRegisterFrom(temp));
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
+    case MethodLoadKind::kBssEntry: {
       // Add ADRP with its PC-relative .bss entry patch.
-      MethodReference target_method(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex());
-      vixl::aarch64::Label* adrp_label = NewMethodBssEntryPatch(target_method);
+      vixl::aarch64::Label* adrp_label = NewMethodBssEntryPatch(invoke->GetMethodReference());
       EmitAdrpPlaceholder(adrp_label, XRegisterFrom(temp));
       // Add LDR with its PC-relative .bss entry patch.
       vixl::aarch64::Label* ldr_label =
-          NewMethodBssEntryPatch(target_method, adrp_label);
+          NewMethodBssEntryPatch(invoke->GetMethodReference(), adrp_label);
       // All aligned loads are implicitly atomic consume operations on ARM64.
       EmitLdrOffsetPlaceholder(ldr_label, XRegisterFrom(temp), XRegisterFrom(temp));
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+    case MethodLoadKind::kJitDirectAddress: {
       // Load method address from literal pool.
-      __ Ldr(XRegisterFrom(temp), DeduplicateUint64Literal(invoke->GetMethodAddress()));
+      __ Ldr(XRegisterFrom(temp),
+             DeduplicateUint64Literal(reinterpret_cast<uint64_t>(invoke->GetResolvedMethod())));
       break;
-    case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+    }
+    case MethodLoadKind::kRuntimeCall: {
+      // Test situation, don't do anything.
+      break;
+    }
+    default: {
+      LOG(FATAL) << "Load kind should have already been handled " << load_kind;
+      UNREACHABLE();
+    }
+  }
+}
+
+void CodeGeneratorARM64::GenerateStaticOrDirectCall(
+    HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
+  // Make sure that ArtMethod* is passed in kArtMethodRegister as per the calling convention.
+  Location callee_method = temp;  // For all kinds except kRecursive, callee will be in temp.
+  switch (invoke->GetMethodLoadKind()) {
+    case MethodLoadKind::kStringInit: {
+      uint32_t offset =
+          GetThreadOffset<kArm64PointerSize>(invoke->GetStringInitEntryPoint()).Int32Value();
+      // temp = thread->string_init_entrypoint
+      __ Ldr(XRegisterFrom(temp), MemOperand(tr, offset));
+      break;
+    }
+    case MethodLoadKind::kRecursive: {
+      callee_method = invoke->GetLocations()->InAt(invoke->GetCurrentMethodIndex());
+      break;
+    }
+    case MethodLoadKind::kRuntimeCall: {
       GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
       return;  // No code pointer retrieval; the runtime performs the call directly.
     }
+    case MethodLoadKind::kBootImageLinkTimePcRelative:
+      DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
+      if (invoke->GetCodePtrLocation() == CodePtrLocation::kCallCriticalNative) {
+        // Do not materialize the method pointer, load directly the entrypoint.
+        // Add ADRP with its PC-relative JNI entrypoint patch.
+        vixl::aarch64::Label* adrp_label =
+            NewBootImageJniEntrypointPatch(invoke->GetResolvedMethodReference());
+        EmitAdrpPlaceholder(adrp_label, lr);
+        // Add the LDR with its PC-relative method patch.
+        vixl::aarch64::Label* add_label =
+            NewBootImageJniEntrypointPatch(invoke->GetResolvedMethodReference(), adrp_label);
+        EmitLdrOffsetPlaceholder(add_label, lr, lr);
+        break;
+      }
+      FALLTHROUGH_INTENDED;
+    default: {
+      LoadMethod(invoke->GetMethodLoadKind(), temp, invoke);
+      break;
+    }
   }
 
+  auto call_lr = [&]() {
+    // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
+    ExactAssemblyScope eas(GetVIXLAssembler(),
+                           kInstructionSize,
+                           CodeBufferCheckScope::kExactSize);
+    // lr()
+    __ blr(lr);
+    RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+  };
   switch (invoke->GetCodePtrLocation()) {
-    case HInvokeStaticOrDirect::CodePtrLocation::kCallSelf:
+    case CodePtrLocation::kCallSelf:
       {
         // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
         ExactAssemblyScope eas(GetVIXLAssembler(),
@@ -4279,21 +4644,57 @@
         RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
       }
       break;
-    case HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod:
-      // LR = callee_method->entry_point_from_quick_compiled_code_;
-      __ Ldr(lr, MemOperand(
-          XRegisterFrom(callee_method),
-          ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64PointerSize).Int32Value()));
-      {
-        // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
-        ExactAssemblyScope eas(GetVIXLAssembler(),
-                               kInstructionSize,
-                               CodeBufferCheckScope::kExactSize);
+    case CodePtrLocation::kCallCriticalNative: {
+      size_t out_frame_size =
+          PrepareCriticalNativeCall<CriticalNativeCallingConventionVisitorARM64,
+                                    kAapcs64StackAlignment,
+                                    GetCriticalNativeDirectCallFrameSize>(invoke);
+      if (invoke->GetMethodLoadKind() == MethodLoadKind::kBootImageLinkTimePcRelative) {
+        call_lr();
+      } else {
+        // LR = callee_method->ptr_sized_fields_.data_;  // EntryPointFromJni
+        MemberOffset offset = ArtMethod::EntryPointFromJniOffset(kArm64PointerSize);
+        __ Ldr(lr, MemOperand(XRegisterFrom(callee_method), offset.Int32Value()));
         // lr()
-        __ blr(lr);
-        RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+        call_lr();
+      }
+      // Zero-/sign-extend the result when needed due to native and managed ABI mismatch.
+      switch (invoke->GetType()) {
+        case DataType::Type::kBool:
+          __ Ubfx(w0, w0, 0, 8);
+          break;
+        case DataType::Type::kInt8:
+          __ Sbfx(w0, w0, 0, 8);
+          break;
+        case DataType::Type::kUint16:
+          __ Ubfx(w0, w0, 0, 16);
+          break;
+        case DataType::Type::kInt16:
+          __ Sbfx(w0, w0, 0, 16);
+          break;
+        case DataType::Type::kInt32:
+        case DataType::Type::kInt64:
+        case DataType::Type::kFloat32:
+        case DataType::Type::kFloat64:
+        case DataType::Type::kVoid:
+          break;
+        default:
+          DCHECK(false) << invoke->GetType();
+          break;
+      }
+      if (out_frame_size != 0u) {
+        DecreaseFrame(out_frame_size);
       }
       break;
+    }
+    case CodePtrLocation::kCallArtMethod: {
+      // LR = callee_method->ptr_sized_fields_.entry_point_from_quick_compiled_code_;
+      MemberOffset offset = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64PointerSize);
+      __ Ldr(lr, MemOperand(XRegisterFrom(callee_method), offset.Int32Value()));
+      // lr()
+      call_lr();
+      break;
+    }
   }
 
   DCHECK(!IsLeafMethod());
@@ -4346,11 +4747,38 @@
   }
 }
 
+void CodeGeneratorARM64::MoveFromReturnRegister(Location trg, DataType::Type type) {
+  if (!trg.IsValid()) {
+    DCHECK(type == DataType::Type::kVoid);
+    return;
+  }
+
+  DCHECK_NE(type, DataType::Type::kVoid);
+
+  if (DataType::IsIntegralType(type) || type == DataType::Type::kReference) {
+    Register trg_reg = RegisterFrom(trg, type);
+    Register res_reg = RegisterFrom(ARM64ReturnLocation(type), type);
+    __ Mov(trg_reg, res_reg, kDiscardForSameWReg);
+  } else {
+    VRegister trg_reg = FPRegisterFrom(trg, type);
+    VRegister res_reg = FPRegisterFrom(ARM64ReturnLocation(type), type);
+    __ Fmov(trg_reg, res_reg);
+  }
+}
+
 void LocationsBuilderARM64::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
+  IntrinsicLocationsBuilderARM64 intrinsic(GetGraph()->GetAllocator(), codegen_);
+  if (intrinsic.TryDispatch(invoke)) {
+    return;
+  }
   HandleInvoke(invoke);
 }
 
 void InstructionCodeGeneratorARM64::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
+  if (TryGenerateIntrinsicCode(invoke, codegen_)) {
+    codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ __LINE__);
+    return;
+  }
   codegen_->GenerateInvokePolymorphicCall(invoke);
   codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ __LINE__);
 }
@@ -4400,10 +4828,26 @@
 }
 
 vixl::aarch64::Label* CodeGeneratorARM64::NewBssEntryTypePatch(
-    const DexFile& dex_file,
-    dex::TypeIndex type_index,
+    HLoadClass* load_class,
     vixl::aarch64::Label* adrp_label) {
-  return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, &type_bss_entry_patches_);
+  const DexFile& dex_file = load_class->GetDexFile();
+  dex::TypeIndex type_index = load_class->GetTypeIndex();
+  ArenaDeque<PcRelativePatchInfo>* patches = nullptr;
+  switch (load_class->GetLoadKind()) {
+    case HLoadClass::LoadKind::kBssEntry:
+      patches = &type_bss_entry_patches_;
+      break;
+    case HLoadClass::LoadKind::kBssEntryPublic:
+      patches = &public_type_bss_entry_patches_;
+      break;
+    case HLoadClass::LoadKind::kBssEntryPackage:
+      patches = &package_type_bss_entry_patches_;
+      break;
+    default:
+      LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind();
+      UNREACHABLE();
+  }
+  return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, patches);
 }
 
 vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageStringPatch(
@@ -4421,9 +4865,16 @@
   return NewPcRelativePatch(&dex_file, string_index.index_, adrp_label, &string_bss_entry_patches_);
 }
 
+vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageJniEntrypointPatch(
+    MethodReference target_method,
+    vixl::aarch64::Label* adrp_label) {
+  return NewPcRelativePatch(
+      target_method.dex_file, target_method.index, adrp_label, &boot_image_jni_entrypoint_patches_);
+}
+
 void CodeGeneratorARM64::EmitEntrypointThunkCall(ThreadOffset64 entrypoint_offset) {
   DCHECK(!__ AllowMacroInstructions());  // In ExactAssemblyScope.
-  DCHECK(!Runtime::Current()->UseJitCompilation());
+  DCHECK(!GetCompilerOptions().IsJitCompiler());
   call_entrypoint_patches_.emplace_back(/*dex_file*/ nullptr, entrypoint_offset.Uint32Value());
   vixl::aarch64::Label* bl_label = &call_entrypoint_patches_.back().label;
   __ bind(bl_label);
@@ -4432,7 +4883,7 @@
 
 void CodeGeneratorARM64::EmitBakerReadBarrierCbnz(uint32_t custom_data) {
   DCHECK(!__ AllowMacroInstructions());  // In ExactAssemblyScope.
-  if (Runtime::Current()->UseJitCompilation()) {
+  if (GetCompilerOptions().IsJitCompiler()) {
     auto it = jit_baker_read_barrier_slow_paths_.FindOrAdd(custom_data);
     vixl::aarch64::Label* slow_path_entry = &it->second.label;
     __ cbnz(mr, slow_path_entry);
@@ -4523,7 +4974,7 @@
     vixl::aarch64::Label* ldr_label = NewBootImageRelRoPatch(boot_image_reference, adrp_label);
     EmitLdrOffsetPlaceholder(ldr_label, reg.W(), reg.X());
   } else {
-    DCHECK(Runtime::Current()->UseJitCompilation());
+    DCHECK(GetCompilerOptions().IsJitCompiler());
     gc::Heap* heap = Runtime::Current()->GetHeap();
     DCHECK(!heap->GetBootImageSpaces().empty());
     const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -4531,28 +4982,43 @@
   }
 }
 
-void CodeGeneratorARM64::AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke,
-                                                      uint32_t boot_image_offset) {
-  DCHECK(invoke->IsStatic());
-  InvokeRuntimeCallingConvention calling_convention;
-  Register argument = calling_convention.GetRegisterAt(0);
+void CodeGeneratorARM64::LoadTypeForBootImageIntrinsic(vixl::aarch64::Register reg,
+                                                       TypeReference target_type) {
+  // Load the class the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
+  DCHECK(GetCompilerOptions().IsBootImage());
+  // Add ADRP with its PC-relative type patch.
+  vixl::aarch64::Label* adrp_label =
+      NewBootImageTypePatch(*target_type.dex_file, target_type.TypeIndex());
+  EmitAdrpPlaceholder(adrp_label, reg.X());
+  // Add ADD with its PC-relative type patch.
+  vixl::aarch64::Label* add_label =
+      NewBootImageTypePatch(*target_type.dex_file, target_type.TypeIndex(), adrp_label);
+  EmitAddPlaceholder(add_label, reg.X(), reg.X());
+}
+
+void CodeGeneratorARM64::LoadIntrinsicDeclaringClass(vixl::aarch64::Register reg, HInvoke* invoke) {
+  DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
   if (GetCompilerOptions().IsBootImage()) {
-    DCHECK_EQ(boot_image_offset, IntrinsicVisitor::IntegerValueOfInfo::kInvalidReference);
-    // Load the class the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
-    MethodReference target_method = invoke->GetTargetMethod();
+    MethodReference target_method = invoke->GetResolvedMethodReference();
     dex::TypeIndex type_idx = target_method.dex_file->GetMethodId(target_method.index).class_idx_;
-    // Add ADRP with its PC-relative type patch.
-    vixl::aarch64::Label* adrp_label = NewBootImageTypePatch(*target_method.dex_file, type_idx);
-    EmitAdrpPlaceholder(adrp_label, argument.X());
-    // Add ADD with its PC-relative type patch.
-    vixl::aarch64::Label* add_label =
-        NewBootImageTypePatch(*target_method.dex_file, type_idx, adrp_label);
-    EmitAddPlaceholder(add_label, argument.X(), argument.X());
+    LoadTypeForBootImageIntrinsic(reg, TypeReference(target_method.dex_file, type_idx));
   } else {
-    LoadBootImageAddress(argument, boot_image_offset);
+    uint32_t boot_image_offset = GetBootImageOffsetOfIntrinsicDeclaringClass(invoke);
+    LoadBootImageAddress(reg, boot_image_offset);
   }
-  InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
-  CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
+}
+
+void CodeGeneratorARM64::LoadClassRootForIntrinsic(vixl::aarch64::Register reg,
+                                                   ClassRoot class_root) {
+  if (GetCompilerOptions().IsBootImage()) {
+    ScopedObjectAccess soa(Thread::Current());
+    ObjPtr<mirror::Class> klass = GetClassRoot(class_root);
+    TypeReference target_type(&klass->GetDexFile(), klass->GetDexTypeIndex());
+    LoadTypeForBootImageIntrinsic(reg, target_type);
+  } else {
+    uint32_t boot_image_offset = GetBootImageOffset(class_root);
+    LoadBootImageAddress(reg, boot_image_offset);
+  }
 }
 
 template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)>
@@ -4583,8 +5049,11 @@
       method_bss_entry_patches_.size() +
       boot_image_type_patches_.size() +
       type_bss_entry_patches_.size() +
+      public_type_bss_entry_patches_.size() +
+      package_type_bss_entry_patches_.size() +
       boot_image_string_patches_.size() +
       string_bss_entry_patches_.size() +
+      boot_image_jni_entrypoint_patches_.size() +
       boot_image_other_patches_.size() +
       call_entrypoint_patches_.size() +
       baker_read_barrier_patches_.size();
@@ -4612,8 +5081,14 @@
       method_bss_entry_patches_, linker_patches);
   EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>(
       type_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>(
+      public_type_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>(
+      package_type_bss_entry_patches_, linker_patches);
   EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>(
       string_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeJniEntrypointPatch>(
+      boot_image_jni_entrypoint_patches_, linker_patches);
   for (const PatchInfo<vixl::aarch64::Label>& info : call_entrypoint_patches_) {
     DCHECK(info.target_dex_file == nullptr);
     linker_patches->push_back(linker::LinkerPatch::CallEntrypointPatch(
@@ -4643,7 +5118,7 @@
       Offset offset(ArtMethod::EntryPointFromQuickCompiledCodeOffset(
           kArm64PointerSize).Int32Value());
       assembler.JumpTo(ManagedRegister(arm64::X0), offset, ManagedRegister(arm64::IP0));
-      if (GetCompilerOptions().GenerateAnyDebugInfo()) {
+      if (debug_name != nullptr && GetCompilerOptions().GenerateAnyDebugInfo()) {
         *debug_name = "MethodCallThunk";
       }
       break;
@@ -4651,7 +5126,7 @@
     case linker::LinkerPatch::Type::kCallEntrypoint: {
       Offset offset(patch.EntrypointOffset());
       assembler.JumpTo(ManagedRegister(arm64::TR), offset, ManagedRegister(arm64::IP0));
-      if (GetCompilerOptions().GenerateAnyDebugInfo()) {
+      if (debug_name != nullptr && GetCompilerOptions().GenerateAnyDebugInfo()) {
         *debug_name = "EntrypointCallThunk_" + std::to_string(offset.Uint32Value());
       }
       break;
@@ -4695,14 +5170,9 @@
     return;
   }
 
-  {
-    // Ensure that between the BLR (emitted by GenerateStaticOrDirectCall) and RecordPcInfo there
-    // are no pools emitted.
-    EmissionCheckScope guard(GetVIXLAssembler(), kInvokeCodeMarginSizeInBytes);
-    LocationSummary* locations = invoke->GetLocations();
-    codegen_->GenerateStaticOrDirectCall(
-        invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
-  }
+  LocationSummary* locations = invoke->GetLocations();
+  codegen_->GenerateStaticOrDirectCall(
+      invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
 
   codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ __LINE__);
 }
@@ -4735,11 +5205,13 @@
     case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadClass::LoadKind::kBootImageRelRo:
     case HLoadClass::LoadKind::kBssEntry:
-      DCHECK(!Runtime::Current()->UseJitCompilation());
+    case HLoadClass::LoadKind::kBssEntryPublic:
+    case HLoadClass::LoadKind::kBssEntryPackage:
+      DCHECK(!GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadClass::LoadKind::kJitBootImageAddress:
     case HLoadClass::LoadKind::kJitTableAddress:
-      DCHECK(Runtime::Current()->UseJitCompilation());
+      DCHECK(GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadClass::LoadKind::kRuntimeCall:
       break;
@@ -4758,7 +5230,9 @@
     DCHECK(calling_convention.GetRegisterAt(0).Is(vixl::aarch64::x0));
     return;
   }
-  DCHECK(!cls->NeedsAccessCheck());
+  DCHECK_EQ(cls->NeedsAccessCheck(),
+            load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+                load_kind == HLoadClass::LoadKind::kBssEntryPackage);
 
   const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage();
   LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier)
@@ -4792,7 +5266,9 @@
     codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ __LINE__);
     return;
   }
-  DCHECK(!cls->NeedsAccessCheck());
+  DCHECK_EQ(cls->NeedsAccessCheck(),
+            load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+                load_kind == HLoadClass::LoadKind::kBssEntryPackage);
 
   Location out_loc = cls->GetLocations()->Out();
   Register out = OutputRegister(cls);
@@ -4832,7 +5308,7 @@
     }
     case HLoadClass::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
-      uint32_t boot_image_offset = codegen_->GetBootImageOffset(cls);
+      uint32_t boot_image_offset = CodeGenerator::GetBootImageOffset(cls);
       // Add ADRP with its PC-relative .data.bimg.rel.ro patch.
       vixl::aarch64::Label* adrp_label = codegen_->NewBootImageRelRoPatch(boot_image_offset);
       codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
@@ -4842,16 +5318,15 @@
       codegen_->EmitLdrOffsetPlaceholder(ldr_label, out.W(), out.X());
       break;
     }
-    case HLoadClass::LoadKind::kBssEntry: {
+    case HLoadClass::LoadKind::kBssEntry:
+    case HLoadClass::LoadKind::kBssEntryPublic:
+    case HLoadClass::LoadKind::kBssEntryPackage: {
       // Add ADRP with its PC-relative Class .bss entry patch.
-      const DexFile& dex_file = cls->GetDexFile();
-      dex::TypeIndex type_index = cls->GetTypeIndex();
       vixl::aarch64::Register temp = XRegisterFrom(out_loc);
-      vixl::aarch64::Label* adrp_label = codegen_->NewBssEntryTypePatch(dex_file, type_index);
+      vixl::aarch64::Label* adrp_label = codegen_->NewBssEntryTypePatch(cls);
       codegen_->EmitAdrpPlaceholder(adrp_label, temp);
       // Add LDR with its PC-relative Class .bss entry patch.
-      vixl::aarch64::Label* ldr_label =
-          codegen_->NewBssEntryTypePatch(dex_file, type_index, adrp_label);
+      vixl::aarch64::Label* ldr_label = codegen_->NewBssEntryTypePatch(cls, adrp_label);
       // /* GcRoot<mirror::Class> */ out = *(base_address + offset)  /* PC-relative */
       // All aligned loads are implicitly atomic consume operations on ARM64.
       codegen_->GenerateGcRootFieldLoad(cls,
@@ -4954,11 +5429,11 @@
     case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadString::LoadKind::kBootImageRelRo:
     case HLoadString::LoadKind::kBssEntry:
-      DCHECK(!Runtime::Current()->UseJitCompilation());
+      DCHECK(!GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadString::LoadKind::kJitBootImageAddress:
     case HLoadString::LoadKind::kJitTableAddress:
-      DCHECK(Runtime::Current()->UseJitCompilation());
+      DCHECK(GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadString::LoadKind::kRuntimeCall:
       break;
@@ -5009,7 +5484,7 @@
     case HLoadString::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       // Add ADRP with its PC-relative .data.bimg.rel.ro patch.
-      uint32_t boot_image_offset = codegen_->GetBootImageOffset(load);
+      uint32_t boot_image_offset = CodeGenerator::GetBootImageOffset(load);
       vixl::aarch64::Label* adrp_label = codegen_->NewBootImageRelRoPatch(boot_image_offset);
       codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
       // Add LDR with its PC-relative .data.bimg.rel.ro patch.
@@ -5372,18 +5847,27 @@
   Register out = OutputRegister(instruction);
   Register dividend = InputRegisterAt(instruction, 0);
 
-  if (abs_imm == 2) {
-    __ Cmp(dividend, 0);
-    __ And(out, dividend, 1);
-    __ Csneg(out, out, out, ge);
-  } else {
-    UseScratchRegisterScope temps(GetVIXLAssembler());
-    Register temp = temps.AcquireSameSizeAs(out);
-
-    __ Negs(temp, dividend);
+  if (HasNonNegativeOrMinIntInputAt(instruction, 0)) {
+    // No need to adjust the result for non-negative dividends or the INT32_MIN/INT64_MIN dividends.
+    // NOTE: The generated code for HRem correctly works for the INT32_MIN/INT64_MIN dividends.
+    // INT*_MIN % imm must be 0 for any imm of power 2. 'and' works only with bits
+    // 0..30 (Int32 case)/0..62 (Int64 case) of a dividend. For INT32_MIN/INT64_MIN they are zeros.
+    // So 'and' always produces zero.
     __ And(out, dividend, abs_imm - 1);
-    __ And(temp, temp, abs_imm - 1);
-    __ Csneg(out, out, temp, mi);
+  } else {
+    if (abs_imm == 2) {
+      __ Cmp(dividend, 0);
+      __ And(out, dividend, 1);
+      __ Csneg(out, out, out, ge);
+    } else {
+      UseScratchRegisterScope temps(GetVIXLAssembler());
+      Register temp = temps.AcquireSameSizeAs(out);
+
+      __ Negs(temp, dividend);
+      __ And(out, dividend, abs_imm - 1);
+      __ And(temp, temp, abs_imm - 1);
+      __ Csneg(out, out, temp, mi);
+    }
   }
 }
 
@@ -5405,7 +5889,7 @@
     GenerateIntRemForPower2Denom(instruction);
   } else {
     DCHECK(imm < -2 || imm > 2) << imm;
-    GenerateDivRemWithAnyConstant(instruction);
+    GenerateDivRemWithAnyConstant(instruction, imm);
   }
 }
 
@@ -6050,21 +6534,21 @@
   MaybeGenerateMarkingRegisterCheck(/* code= */ __LINE__);
 }
 
-void CodeGeneratorARM64::GenerateUnsafeCasOldValueMovWithBakerReadBarrier(
-    vixl::aarch64::Register marked,
+void CodeGeneratorARM64::GenerateIntrinsicCasMoveWithBakerReadBarrier(
+    vixl::aarch64::Register marked_old_value,
     vixl::aarch64::Register old_value) {
   DCHECK(kEmitCompilerReadBarrier);
   DCHECK(kUseBakerReadBarrier);
 
   // Similar to the Baker RB path in GenerateGcRootFieldLoad(), with a MOV instead of LDR.
-  uint32_t custom_data = EncodeBakerReadBarrierGcRootData(marked.GetCode());
+  uint32_t custom_data = EncodeBakerReadBarrierGcRootData(marked_old_value.GetCode());
 
   ExactAssemblyScope guard(GetVIXLAssembler(), 3 * vixl::aarch64::kInstructionSize);
   vixl::aarch64::Label return_address;
   __ adr(lr, &return_address);
   static_assert(BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_OFFSET == -8,
                 "GC root LDR must be 2 instructions (8B) before the return address label.");
-  __ mov(marked, old_value);
+  __ mov(marked_old_value, old_value);
   EmitBakerReadBarrierCbnz(custom_data);
   __ bind(&return_address);
 }
@@ -6260,6 +6744,18 @@
   }
 }
 
+SlowPathCodeARM64* CodeGeneratorARM64::AddReadBarrierSlowPath(HInstruction* instruction,
+                                                              Location out,
+                                                              Location ref,
+                                                              Location obj,
+                                                              uint32_t offset,
+                                                              Location index) {
+  SlowPathCodeARM64* slow_path = new (GetScopedAllocator())
+      ReadBarrierForHeapReferenceSlowPathARM64(instruction, out, ref, obj, offset, index);
+  AddSlowPath(slow_path);
+  return slow_path;
+}
+
 void CodeGeneratorARM64::GenerateReadBarrierSlow(HInstruction* instruction,
                                                  Location out,
                                                  Location ref,
@@ -6279,9 +6775,7 @@
   // not used by the artReadBarrierSlow entry point.
   //
   // TODO: Unpoison `ref` when it is used by artReadBarrierSlow.
-  SlowPathCodeARM64* slow_path = new (GetScopedAllocator())
-      ReadBarrierForHeapReferenceSlowPathARM64(instruction, out, ref, obj, offset, index);
-  AddSlowPath(slow_path);
+  SlowPathCodeARM64* slow_path = AddReadBarrierSlowPath(instruction, out, ref, obj, offset, index);
 
   __ B(slow_path->GetEntryLabel());
   __ Bind(slow_path->GetExitLabel());
@@ -6372,6 +6866,64 @@
   }
 }
 
+MemOperand InstructionCodeGeneratorARM64::VecNEONAddress(
+    HVecMemoryOperation* instruction,
+    UseScratchRegisterScope* temps_scope,
+    size_t size,
+    bool is_string_char_at,
+    /*out*/ Register* scratch) {
+  LocationSummary* locations = instruction->GetLocations();
+  Register base = InputRegisterAt(instruction, 0);
+
+  if (instruction->InputAt(1)->IsIntermediateAddressIndex()) {
+    DCHECK(!is_string_char_at);
+    return MemOperand(base.X(), InputRegisterAt(instruction, 1).X());
+  }
+
+  Location index = locations->InAt(1);
+  uint32_t offset = is_string_char_at
+      ? mirror::String::ValueOffset().Uint32Value()
+      : mirror::Array::DataOffset(size).Uint32Value();
+  size_t shift = ComponentSizeShiftWidth(size);
+
+  // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
+  DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
+
+  if (index.IsConstant()) {
+    offset += Int64FromLocation(index) << shift;
+    return HeapOperand(base, offset);
+  } else {
+    *scratch = temps_scope->AcquireSameSizeAs(base);
+    __ Add(*scratch, base, Operand(WRegisterFrom(index), LSL, shift));
+    return HeapOperand(*scratch, offset);
+  }
+}
+
+SVEMemOperand InstructionCodeGeneratorARM64::VecSVEAddress(
+    HVecMemoryOperation* instruction,
+    UseScratchRegisterScope* temps_scope,
+    size_t size,
+    bool is_string_char_at,
+    /*out*/ Register* scratch) {
+  LocationSummary* locations = instruction->GetLocations();
+  Register base = InputRegisterAt(instruction, 0);
+  Location index = locations->InAt(1);
+
+  // TODO: Support intermediate address sharing for SVE accesses.
+  DCHECK(!instruction->InputAt(1)->IsIntermediateAddressIndex());
+  DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
+  DCHECK(!index.IsConstant());
+
+  uint32_t offset = is_string_char_at
+      ? mirror::String::ValueOffset().Uint32Value()
+      : mirror::Array::DataOffset(size).Uint32Value();
+  size_t shift = ComponentSizeShiftWidth(size);
+
+  *scratch = temps_scope->AcquireSameSizeAs(base);
+  __ Add(*scratch, base, offset);
+  return SVEMemOperand(scratch->X(), XRegisterFrom(index), LSL, shift);
+}
+
 #undef __
 #undef QUICK_ENTRY_POINT
 
@@ -6425,11 +6977,11 @@
   switch (kind) {
     case BakerReadBarrierKind::kField:
     case BakerReadBarrierKind::kAcquire: {
-      auto base_reg =
-          Register::GetXRegFromCode(BakerReadBarrierFirstRegField::Decode(encoded_data));
+      Register base_reg =
+          vixl::aarch64::XRegister(BakerReadBarrierFirstRegField::Decode(encoded_data));
       CheckValidReg(base_reg.GetCode());
-      auto holder_reg =
-          Register::GetXRegFromCode(BakerReadBarrierSecondRegField::Decode(encoded_data));
+      Register holder_reg =
+          vixl::aarch64::XRegister(BakerReadBarrierSecondRegField::Decode(encoded_data));
       CheckValidReg(holder_reg.GetCode());
       UseScratchRegisterScope temps(assembler.GetVIXLAssembler());
       temps.Exclude(ip0, ip1);
@@ -6475,8 +7027,8 @@
       break;
     }
     case BakerReadBarrierKind::kArray: {
-      auto base_reg =
-          Register::GetXRegFromCode(BakerReadBarrierFirstRegField::Decode(encoded_data));
+      Register base_reg =
+          vixl::aarch64::XRegister(BakerReadBarrierFirstRegField::Decode(encoded_data));
       CheckValidReg(base_reg.GetCode());
       DCHECK_EQ(kBakerReadBarrierInvalidEncodedReg,
                 BakerReadBarrierSecondRegField::Decode(encoded_data));
@@ -6504,8 +7056,8 @@
       // and it does not have a forwarding address), call the correct introspection entrypoint;
       // otherwise return the reference (or the extracted forwarding address).
       // There is no gray bit check for GC roots.
-      auto root_reg =
-          Register::GetWRegFromCode(BakerReadBarrierFirstRegField::Decode(encoded_data));
+      Register root_reg =
+          vixl::aarch64::WRegister(BakerReadBarrierFirstRegField::Decode(encoded_data));
       CheckValidReg(root_reg.GetCode());
       DCHECK_EQ(kBakerReadBarrierInvalidEncodedReg,
                 BakerReadBarrierSecondRegField::Decode(encoded_data));
@@ -6538,10 +7090,8 @@
   }
 
   // For JIT, the slow path is considered part of the compiled method,
-  // so JIT should pass null as `debug_name`. Tests may not have a runtime.
-  DCHECK(Runtime::Current() == nullptr ||
-         !Runtime::Current()->UseJitCompilation() ||
-         debug_name == nullptr);
+  // so JIT should pass null as `debug_name`.
+  DCHECK(!GetCompilerOptions().IsJitCompiler() || debug_name == nullptr);
   if (debug_name != nullptr && GetCompilerOptions().GenerateAnyDebugInfo()) {
     std::ostringstream oss;
     oss << "BakerReadBarrierThunk";
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 6b2c805..d4546e5 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -18,6 +18,7 @@
 #define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_
 
 #include "base/bit_field.h"
+#include "class_root.h"
 #include "code_generator.h"
 #include "common_arm64.h"
 #include "dex/dex_file_types.h"
@@ -228,6 +229,31 @@
   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorARM64);
 };
 
+class CriticalNativeCallingConventionVisitorARM64 : public InvokeDexCallingConventionVisitor {
+ public:
+  explicit CriticalNativeCallingConventionVisitorARM64(bool for_register_allocation)
+      : for_register_allocation_(for_register_allocation) {}
+
+  virtual ~CriticalNativeCallingConventionVisitorARM64() {}
+
+  Location GetNextLocation(DataType::Type type) override;
+  Location GetReturnLocation(DataType::Type type) const override;
+  Location GetMethodLocation() const override;
+
+  size_t GetStackOffset() const { return stack_offset_; }
+
+ private:
+  // Register allocator does not support adjusting frame size, so we cannot provide final locations
+  // of stack arguments for register allocation. We ask the register allocator for any location and
+  // move these arguments to the right place after adjusting the SP when generating the call.
+  const bool for_register_allocation_;
+  size_t gpr_index_ = 0u;
+  size_t fpr_index_ = 0u;
+  size_t stack_offset_ = 0u;
+
+  DISALLOW_COPY_AND_ASSIGN(CriticalNativeCallingConventionVisitorARM64);
+};
+
 class FieldAccessCallingConventionARM64 : public FieldAccessCallingConvention {
  public:
   FieldAccessCallingConventionARM64() {}
@@ -262,7 +288,7 @@
 #define DECLARE_VISIT_INSTRUCTION(name, super) \
   void Visit##name(H##name* instr) override;
 
-  FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION)
+  FOR_EACH_CONCRETE_INSTRUCTION_SCALAR_COMMON(DECLARE_VISIT_INSTRUCTION)
   FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION)
   FOR_EACH_CONCRETE_INSTRUCTION_SHARED(DECLARE_VISIT_INSTRUCTION)
 
@@ -276,7 +302,19 @@
   Arm64Assembler* GetAssembler() const { return assembler_; }
   vixl::aarch64::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->GetVIXLAssembler(); }
 
- private:
+  // SIMD helpers.
+  virtual Location AllocateSIMDScratchLocation(vixl::aarch64::UseScratchRegisterScope* scope) = 0;
+  virtual void FreeSIMDScratchLocation(Location loc,
+                                       vixl::aarch64::UseScratchRegisterScope* scope)  = 0;
+  virtual void LoadSIMDRegFromStack(Location destination, Location source) = 0;
+  virtual void MoveSIMDRegToSIMDReg(Location destination, Location source) = 0;
+  virtual void MoveToSIMDStackSlot(Location destination, Location source) = 0;
+  virtual void SaveLiveRegistersHelper(LocationSummary* locations,
+                                       int64_t spill_offset) = 0;
+  virtual void RestoreLiveRegistersHelper(LocationSummary* locations,
+                                          int64_t spill_offset) = 0;
+
+ protected:
   void GenerateClassInitializationCheck(SlowPathCodeARM64* slow_path,
                                         vixl::aarch64::Register class_reg);
   void GenerateBitstringTypeCheckCompare(HTypeCheckInstruction* check,
@@ -331,7 +369,18 @@
                              vixl::aarch64::Label* false_target);
   void DivRemOneOrMinusOne(HBinaryOperation* instruction);
   void DivRemByPowerOfTwo(HBinaryOperation* instruction);
-  void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction);
+  void GenerateIncrementNegativeByOne(vixl::aarch64::Register out,
+                                      vixl::aarch64::Register in, bool use_cond_inc);
+  void GenerateResultRemWithAnyConstant(vixl::aarch64::Register out,
+                                        vixl::aarch64::Register dividend,
+                                        vixl::aarch64::Register quotient,
+                                        int64_t divisor,
+                                        // This function may acquire a scratch register.
+                                        vixl::aarch64::UseScratchRegisterScope* temps_scope);
+  void GenerateInt64UnsignedDivRemWithAnyPositiveConstant(HBinaryOperation* instruction);
+  void GenerateInt64DivRemWithAnyConstant(HBinaryOperation* instruction);
+  void GenerateInt32DivRemWithAnyConstant(HBinaryOperation* instruction);
+  void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction, int64_t divisor);
   void GenerateIntDiv(HDiv* instruction);
   void GenerateIntDivForConstDenom(HDiv *instruction);
   void GenerateIntDivForPower2Denom(HDiv *instruction);
@@ -340,7 +389,19 @@
   void GenerateIntRemForPower2Denom(HRem *instruction);
   void HandleGoto(HInstruction* got, HBasicBlock* successor);
 
-  vixl::aarch64::MemOperand VecAddress(
+  // Helpers to set up locations for vector memory operations. Returns the memory operand and,
+  // if used, sets the output parameter scratch to a temporary register used in this operand,
+  // so that the client can release it right after the memory operand use.
+  // Neon version.
+  vixl::aarch64::MemOperand VecNEONAddress(
+      HVecMemoryOperation* instruction,
+      // This function may acquire a scratch register.
+      vixl::aarch64::UseScratchRegisterScope* temps_scope,
+      size_t size,
+      bool is_string_char_at,
+      /*out*/ vixl::aarch64::Register* scratch);
+  // SVE version.
+  vixl::aarch64::SVEMemOperand VecSVEAddress(
       HVecMemoryOperation* instruction,
       // This function may acquire a scratch register.
       vixl::aarch64::UseScratchRegisterScope* temps_scope,
@@ -362,7 +423,7 @@
 #define DECLARE_VISIT_INSTRUCTION(name, super) \
   void Visit##name(H##name* instr) override;
 
-  FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION)
+  FOR_EACH_CONCRETE_INSTRUCTION_SCALAR_COMMON(DECLARE_VISIT_INSTRUCTION)
   FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION)
   FOR_EACH_CONCRETE_INSTRUCTION_SHARED(DECLARE_VISIT_INSTRUCTION)
 
@@ -373,7 +434,7 @@
                << " (id " << instruction->GetId() << ")";
   }
 
- private:
+ protected:
   void HandleBinaryOp(HBinaryOperation* instr);
   void HandleFieldSet(HInstruction* instruction);
   void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
@@ -387,6 +448,89 @@
   DISALLOW_COPY_AND_ASSIGN(LocationsBuilderARM64);
 };
 
+class InstructionCodeGeneratorARM64Neon : public InstructionCodeGeneratorARM64 {
+ public:
+  InstructionCodeGeneratorARM64Neon(HGraph* graph, CodeGeneratorARM64* codegen) :
+      InstructionCodeGeneratorARM64(graph, codegen) {}
+
+#define DECLARE_VISIT_INSTRUCTION(name, super) \
+  void Visit##name(H##name* instr) override;
+
+  FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(DECLARE_VISIT_INSTRUCTION)
+
+#undef DECLARE_VISIT_INSTRUCTION
+
+  Location AllocateSIMDScratchLocation(vixl::aarch64::UseScratchRegisterScope* scope) override;
+  void FreeSIMDScratchLocation(Location loc,
+                               vixl::aarch64::UseScratchRegisterScope* scope) override;
+  void LoadSIMDRegFromStack(Location destination, Location source) override;
+  void MoveSIMDRegToSIMDReg(Location destination, Location source) override;
+  void MoveToSIMDStackSlot(Location destination, Location source) override;
+  void SaveLiveRegistersHelper(LocationSummary* locations, int64_t spill_offset) override;
+  void RestoreLiveRegistersHelper(LocationSummary* locations, int64_t spill_offset) override;
+};
+
+class LocationsBuilderARM64Neon : public LocationsBuilderARM64 {
+ public:
+  LocationsBuilderARM64Neon(HGraph* graph, CodeGeneratorARM64* codegen) :
+      LocationsBuilderARM64(graph, codegen) {}
+
+#define DECLARE_VISIT_INSTRUCTION(name, super) \
+  void Visit##name(H##name* instr) override;
+
+  FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(DECLARE_VISIT_INSTRUCTION)
+
+#undef DECLARE_VISIT_INSTRUCTION
+};
+
+class InstructionCodeGeneratorARM64Sve : public InstructionCodeGeneratorARM64 {
+ public:
+  InstructionCodeGeneratorARM64Sve(HGraph* graph, CodeGeneratorARM64* codegen) :
+      InstructionCodeGeneratorARM64(graph, codegen) {}
+
+#define DECLARE_VISIT_INSTRUCTION(name, super) \
+  void Visit##name(H##name* instr) override;
+
+  FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(DECLARE_VISIT_INSTRUCTION)
+
+#undef DECLARE_VISIT_INSTRUCTION
+
+  Location AllocateSIMDScratchLocation(vixl::aarch64::UseScratchRegisterScope* scope) override;
+  void FreeSIMDScratchLocation(Location loc,
+                               vixl::aarch64::UseScratchRegisterScope* scope) override;
+  void LoadSIMDRegFromStack(Location destination, Location source) override;
+  void MoveSIMDRegToSIMDReg(Location destination, Location source) override;
+  void MoveToSIMDStackSlot(Location destination, Location source) override;
+  void SaveLiveRegistersHelper(LocationSummary* locations, int64_t spill_offset) override;
+  void RestoreLiveRegistersHelper(LocationSummary* locations, int64_t spill_offset) override;
+
+ private:
+  // Validate that instruction vector length and packed type are compliant with the SIMD
+  // register size (full SIMD register is used).
+  void ValidateVectorLength(HVecOperation* instr) const;
+
+  // Returns default predicate register which is used as governing vector predicate
+  // to implement predicated loop execution.
+  //
+  // TODO: This is a hack to be addressed when register allocator supports SIMD types.
+  static vixl::aarch64::PRegister LoopPReg() {
+    return vixl::aarch64::p0;
+  }
+};
+
+class LocationsBuilderARM64Sve : public LocationsBuilderARM64 {
+ public:
+  LocationsBuilderARM64Sve(HGraph* graph, CodeGeneratorARM64* codegen) :
+      LocationsBuilderARM64(graph, codegen) {}
+
+#define DECLARE_VISIT_INSTRUCTION(name, super) \
+  void Visit##name(H##name* instr) override;
+
+  FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(DECLARE_VISIT_INSTRUCTION)
+
+#undef DECLARE_VISIT_INSTRUCTION
+};
+
 class ParallelMoveResolverARM64 : public ParallelMoveResolverNoSwap {
  public:
   ParallelMoveResolverARM64(ArenaAllocator* allocator, CodeGeneratorARM64* codegen)
@@ -435,9 +579,11 @@
     return kArm64WordSize;
   }
 
+  bool SupportsPredicatedSIMD() const override { return ShouldUseSVE(); }
+
   size_t GetSlowPathFPWidth() const override {
     return GetGraph()->HasSIMD()
-        ? vixl::aarch64::kQRegSizeInBytes
+        ? GetSIMDRegisterWidth()
         : vixl::aarch64::kDRegSizeInBytes;
   }
 
@@ -445,14 +591,19 @@
     return vixl::aarch64::kDRegSizeInBytes;
   }
 
+  size_t GetSIMDRegisterWidth() const override;
+
   uintptr_t GetAddressOf(HBasicBlock* block) override {
     vixl::aarch64::Label* block_entry_label = GetLabelOf(block);
     DCHECK(block_entry_label->IsBound());
     return block_entry_label->GetLocation();
   }
 
-  HGraphVisitor* GetLocationBuilder() override { return &location_builder_; }
-  HGraphVisitor* GetInstructionVisitor() override { return &instruction_visitor_; }
+  HGraphVisitor* GetLocationBuilder() override { return location_builder_; }
+  InstructionCodeGeneratorARM64* GetInstructionCodeGeneratorArm64() {
+    return instruction_visitor_;
+  }
+  HGraphVisitor* GetInstructionVisitor() override { return GetInstructionCodeGeneratorArm64(); }
   Arm64Assembler* GetAssembler() override { return &assembler_; }
   const Arm64Assembler& GetAssembler() const override { return assembler_; }
   vixl::aarch64::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->GetVIXLAssembler(); }
@@ -520,6 +671,7 @@
              vixl::aarch64::CPURegister src,
              const vixl::aarch64::MemOperand& dst);
   void LoadAcquire(HInstruction* instruction,
+                   DataType::Type type,
                    vixl::aarch64::CPURegister dst,
                    const vixl::aarch64::MemOperand& src,
                    bool needs_null_check);
@@ -563,15 +715,13 @@
       const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
       ArtMethod* method) override;
 
+  void LoadMethod(MethodLoadKind load_kind, Location temp, HInvoke* invoke);
   void GenerateStaticOrDirectCall(
       HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
   void GenerateVirtualCall(
       HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
 
-  void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED,
-                              DataType::Type type ATTRIBUTE_UNUSED) override {
-    UNIMPLEMENTED(FATAL);
-  }
+  void MoveFromReturnRegister(Location trg, DataType::Type type) override;
 
   // Add a new boot image intrinsic patch for an instruction and return the label
   // to be bound before the instruction. The instruction will be either the
@@ -613,8 +763,7 @@
   // to be bound before the instruction. The instruction will be either the
   // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
   // to the associated ADRP patch label).
-  vixl::aarch64::Label* NewBssEntryTypePatch(const DexFile& dex_file,
-                                             dex::TypeIndex type_index,
+  vixl::aarch64::Label* NewBssEntryTypePatch(HLoadClass* load_class,
                                              vixl::aarch64::Label* adrp_label = nullptr);
 
   // Add a new boot image string patch for an instruction and return the label
@@ -633,6 +782,13 @@
                                                dex::StringIndex string_index,
                                                vixl::aarch64::Label* adrp_label = nullptr);
 
+  // Add a new boot image JNI entrypoint patch for an instruction and return the label
+  // to be bound before the instruction. The instruction will be either the
+  // ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label` pointing
+  // to the associated ADRP patch label).
+  vixl::aarch64::Label* NewBootImageJniEntrypointPatch(MethodReference target_method,
+                                                       vixl::aarch64::Label* adrp_label = nullptr);
+
   // Emit the BL instruction for entrypoint thunk call and record the associated patch for AOT.
   void EmitEntrypointThunkCall(ThreadOffset64 entrypoint_offset);
 
@@ -657,7 +813,9 @@
                                 vixl::aarch64::Register base);
 
   void LoadBootImageAddress(vixl::aarch64::Register reg, uint32_t boot_image_reference);
-  void AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke, uint32_t boot_image_offset);
+  void LoadTypeForBootImageIntrinsic(vixl::aarch64::Register reg, TypeReference type_reference);
+  void LoadIntrinsicDeclaringClass(vixl::aarch64::Register reg, HInvoke* invoke);
+  void LoadClassRootForIntrinsic(vixl::aarch64::Register reg, ClassRoot class_root);
 
   void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) override;
   bool NeedsThunkCode(const linker::LinkerPatch& patch) const override;
@@ -678,9 +836,9 @@
                                uint32_t offset,
                                vixl::aarch64::Label* fixup_label,
                                ReadBarrierOption read_barrier_option);
-  // Generate MOV for the `old_value` in UnsafeCASObject and mark it with Baker read barrier.
-  void GenerateUnsafeCasOldValueMovWithBakerReadBarrier(vixl::aarch64::Register marked,
-                                                        vixl::aarch64::Register old_value);
+  // Generate MOV for the `old_value` in intrinsic CAS and mark it with Baker read barrier.
+  void GenerateIntrinsicCasMoveWithBakerReadBarrier(vixl::aarch64::Register marked_old_value,
+                                                    vixl::aarch64::Register old_value);
   // Fast path implementation of ReadBarrier::Barrier for a heap
   // reference field load when Baker's read barriers are used.
   // Overload suitable for Unsafe.getObject/-Volatile() intrinsic.
@@ -724,6 +882,18 @@
   virtual void MaybeGenerateMarkingRegisterCheck(int code,
                                                  Location temp_loc = Location::NoLocation());
 
+  // Create slow path for a read barrier for a heap reference within `instruction`.
+  //
+  // This is a helper function for GenerateReadBarrierSlow() that has the same
+  // arguments. The creation and adding of the slow path is exposed for intrinsics
+  // that cannot use GenerateReadBarrierSlow() from their own slow paths.
+  SlowPathCodeARM64* AddReadBarrierSlowPath(HInstruction* instruction,
+                                            Location out,
+                                            Location ref,
+                                            Location obj,
+                                            uint32_t offset,
+                                            Location index);
+
   // Generate a read barrier for a heap reference within `instruction`
   // using a slow path.
   //
@@ -772,6 +942,9 @@
   // artReadBarrierForRootSlow.
   void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root);
 
+  void IncreaseFrame(size_t adjustment) override;
+  void DecreaseFrame(size_t adjustment) override;
+
   void GenerateNop() override;
 
   void GenerateImplicitNullCheck(HNullCheck* instruction) override;
@@ -895,14 +1068,22 @@
   static void EmitPcRelativeLinkerPatches(const ArenaDeque<PcRelativePatchInfo>& infos,
                                           ArenaVector<linker::LinkerPatch>* linker_patches);
 
+  // Returns whether SVE features are supported and should be used.
+  bool ShouldUseSVE() const;
+
   // Labels for each block that will be compiled.
   // We use a deque so that the `vixl::aarch64::Label` objects do not move in memory.
   ArenaDeque<vixl::aarch64::Label> block_labels_;  // Indexed by block id.
   vixl::aarch64::Label frame_entry_label_;
   ArenaVector<std::unique_ptr<JumpTableARM64>> jump_tables_;
 
-  LocationsBuilderARM64 location_builder_;
-  InstructionCodeGeneratorARM64 instruction_visitor_;
+  LocationsBuilderARM64Neon location_builder_neon_;
+  InstructionCodeGeneratorARM64Neon instruction_visitor_neon_;
+  LocationsBuilderARM64Sve location_builder_sve_;
+  InstructionCodeGeneratorARM64Sve instruction_visitor_sve_;
+
+  LocationsBuilderARM64* location_builder_;
+  InstructionCodeGeneratorARM64* instruction_visitor_;
   ParallelMoveResolverARM64 move_resolver_;
   Arm64Assembler assembler_;
 
@@ -914,10 +1095,16 @@
   ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
   // PC-relative type patch info for kBssEntry.
   ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
+  // PC-relative public type patch info for kBssEntryPublic.
+  ArenaDeque<PcRelativePatchInfo> public_type_bss_entry_patches_;
+  // PC-relative package type patch info for kBssEntryPackage.
+  ArenaDeque<PcRelativePatchInfo> package_type_bss_entry_patches_;
   // PC-relative String patch info for kBootImageLinkTimePcRelative.
   ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_;
   // PC-relative String patch info for kBssEntry.
   ArenaDeque<PcRelativePatchInfo> string_bss_entry_patches_;
+  // PC-relative method patch info for kBootImageLinkTimePcRelative+kCallCriticalNative.
+  ArenaDeque<PcRelativePatchInfo> boot_image_jni_entrypoint_patches_;
   // PC-relative patch info for IntrinsicObjects for the boot image,
   // and for method/type/string patches for kBootImageRelRo otherwise.
   ArenaDeque<PcRelativePatchInfo> boot_image_other_patches_;
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 3a2cf40..bca0936 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -18,9 +18,11 @@
 
 #include "arch/arm/asm_support_arm.h"
 #include "arch/arm/instruction_set_features_arm.h"
+#include "arch/arm/jni_frame_arm.h"
 #include "art_method-inl.h"
 #include "base/bit_utils.h"
 #include "base/bit_utils_iterator.h"
+#include "class_root-inl.h"
 #include "class_table.h"
 #include "code_generator_utils.h"
 #include "common_arm.h"
@@ -29,11 +31,13 @@
 #include "gc/accounting/card_table.h"
 #include "gc/space/image_space.h"
 #include "heap_poisoning.h"
+#include "interpreter/mterp/nterp.h"
 #include "intrinsics.h"
 #include "intrinsics_arm_vixl.h"
 #include "linker/linker_patch.h"
 #include "mirror/array-inl.h"
 #include "mirror/class-inl.h"
+#include "mirror/var_handle.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread.h"
 #include "utils/arm/assembler_arm_vixl.h"
@@ -528,8 +532,13 @@
       DCHECK(IsSameDexFile(cls_->GetDexFile(), arm_codegen->GetGraph()->GetDexFile()));
       dex::TypeIndex type_index = cls_->GetTypeIndex();
       __ Mov(calling_convention.GetRegisterAt(0), type_index.index_);
-      arm_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
-      CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+      if (cls_->NeedsAccessCheck()) {
+        CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>();
+        arm_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this);
+      } else {
+        CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+        arm_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
+      }
       // If we also must_do_clinit, the resolved type is now in the correct register.
     } else {
       DCHECK(must_do_clinit);
@@ -752,11 +761,12 @@
     DCHECK(locations->CanCall());
     DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(reg_out.GetCode()));
     DCHECK(instruction_->IsInstanceFieldGet() ||
+           instruction_->IsPredicatedInstanceFieldGet() ||
            instruction_->IsStaticFieldGet() ||
            instruction_->IsArrayGet() ||
            instruction_->IsInstanceOf() ||
            instruction_->IsCheckCast() ||
-           (instruction_->IsInvokeVirtual() && instruction_->GetLocations()->Intrinsified()))
+           (instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
         << "Unexpected instruction in read barrier for heap reference slow path: "
         << instruction_->DebugName();
     // The read barrier instrumentation of object ArrayGet
@@ -827,14 +837,24 @@
         // to an object field within an object.
         DCHECK(instruction_->IsInvoke()) << instruction_->DebugName();
         DCHECK(instruction_->GetLocations()->Intrinsified());
-        DCHECK((instruction_->AsInvoke()->GetIntrinsic() == Intrinsics::kUnsafeGetObject) ||
-               (instruction_->AsInvoke()->GetIntrinsic() == Intrinsics::kUnsafeGetObjectVolatile))
+        Intrinsics intrinsic = instruction_->AsInvoke()->GetIntrinsic();
+        DCHECK(intrinsic == Intrinsics::kUnsafeGetObject ||
+               intrinsic == Intrinsics::kUnsafeGetObjectVolatile ||
+               mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) ==
+                   mirror::VarHandle::AccessModeTemplate::kGet ||
+               mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) ==
+                   mirror::VarHandle::AccessModeTemplate::kCompareAndSet ||
+               mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) ==
+                   mirror::VarHandle::AccessModeTemplate::kCompareAndExchange ||
+               mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) ==
+                   mirror::VarHandle::AccessModeTemplate::kGetAndUpdate)
             << instruction_->AsInvoke()->GetIntrinsic();
         DCHECK_EQ(offset_, 0U);
-        DCHECK(index_.IsRegisterPair());
-        // UnsafeGet's offset location is a register pair, the low
-        // part contains the correct offset.
-        index = index_.ToLow();
+        // Though UnsafeGet's offset location is a register pair, we only pass the low
+        // part (high part is irrelevant for 32-bit addresses) to the slow path.
+        // For VarHandle intrinsics, the index is always just a register.
+        DCHECK(index_.IsRegister());
+        index = index_;
       }
     }
 
@@ -916,7 +936,9 @@
     vixl32::Register reg_out = RegisterFrom(out_);
     DCHECK(locations->CanCall());
     DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(reg_out.GetCode()));
-    DCHECK(instruction_->IsLoadClass() || instruction_->IsLoadString())
+    DCHECK(instruction_->IsLoadClass() ||
+           instruction_->IsLoadString() ||
+           (instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
         << "Unexpected instruction in read barrier for GC root slow path: "
         << instruction_->DebugName();
 
@@ -1861,6 +1883,8 @@
       method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -1931,7 +1955,7 @@
   FixJumpTables();
 
   // Emit JIT baker read barrier slow paths.
-  DCHECK(Runtime::Current()->UseJitCompilation() || jit_baker_read_barrier_slow_paths_.empty());
+  DCHECK(GetCompilerOptions().IsJitCompiler() || jit_baker_read_barrier_slow_paths_.empty());
   for (auto& entry : jit_baker_read_barrier_slow_paths_) {
     uint32_t encoded_data = entry.first;
     vixl::aarch32::Label* slow_path_entry = &entry.second.label;
@@ -2003,18 +2027,22 @@
           } else {
             DCHECK_GE(literal_offset, 2u);
             uint32_t prev_insn = GetInsn16(literal_offset - 2u);
-            // LDR (immediate), encoding T1, with correct root_reg.
             const uint32_t root_reg = BakerReadBarrierFirstRegField::Decode(encoded_data);
-            CHECK_EQ(prev_insn & 0xf807u, 0x6800u | root_reg);
+            // Usually LDR (immediate), encoding T1, with correct root_reg but we may have
+            // a `MOV marked, old_value` for intrinsic CAS where `marked` is a low register.
+            if ((prev_insn & 0xff87u) != (0x4600 | root_reg)) {
+              CHECK_EQ(prev_insn & 0xf807u, 0x6800u | root_reg);
+            }
           }
           break;
         }
-        case BakerReadBarrierKind::kUnsafeCas: {
+        case BakerReadBarrierKind::kIntrinsicCas: {
           DCHECK_GE(literal_offset, 4u);
           uint32_t prev_insn = GetInsn32(literal_offset - 4u);
-          // ADD (register), encoding T3, with correct root_reg.
+          // MOV (register), encoding T3, with correct root_reg.
           const uint32_t root_reg = BakerReadBarrierFirstRegField::Decode(encoded_data);
-          CHECK_EQ(prev_insn & 0xfff0fff0u, 0xeb000000u | (root_reg << 8));
+          DCHECK_GE(root_reg, 8u);  // Used only for high registers.
+          CHECK_EQ(prev_insn & 0xfffffff0u, 0xea4f0000u | (root_reg << 8));
           break;
         }
         default:
@@ -2087,6 +2115,7 @@
     static_assert(ArtMethod::MaxCounter() == 0xFFFF, "asm is probably wrong");
     if (!is_frame_entry) {
       __ Push(vixl32::Register(kMethodRegister));
+      GetAssembler()->cfi().AdjustCFAOffset(kArmWordSize);
       GetAssembler()->LoadFromOffset(kLoadWord, kMethodRegister, sp, kArmWordSize);
     }
     // Load with zero extend to clear the high bits for integer overflow check.
@@ -2097,12 +2126,14 @@
     __ Strh(temp, MemOperand(kMethodRegister, ArtMethod::HotnessCountOffset().Int32Value()));
     if (!is_frame_entry) {
       __ Pop(vixl32::Register(kMethodRegister));
+      GetAssembler()->cfi().AdjustCFAOffset(-static_cast<int>(kArmWordSize));
     }
   }
 
   if (GetGraph()->IsCompilingBaseline() && !Runtime::Current()->IsAotCompiler()) {
-    ScopedObjectAccess soa(Thread::Current());
-    ProfilingInfo* info = GetGraph()->GetArtMethod()->GetProfilingInfo(kRuntimePointerSize);
+    ScopedProfilingInfoUse spiu(
+        Runtime::Current()->GetJit(), GetGraph()->GetArtMethod(), Thread::Current());
+    ProfilingInfo* info = spiu.GetProfilingInfo();
     if (info != nullptr) {
       uint32_t address = reinterpret_cast32<uint32_t>(info);
       vixl::aarch32::Label done;
@@ -2110,13 +2141,16 @@
       temps.Exclude(ip);
       if (!is_frame_entry) {
         __ Push(r4);  // Will be used as temporary. For frame entry, r4 is always available.
+        GetAssembler()->cfi().AdjustCFAOffset(kArmWordSize);
       }
       __ Mov(r4, address);
       __ Ldrh(ip, MemOperand(r4, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()));
       __ Add(ip, ip, 1);
+      instruction_visitor_.GenerateAndConst(ip, ip, interpreter::kTieredHotnessMask);
       __ Strh(ip, MemOperand(r4, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()));
       if (!is_frame_entry) {
         __ Pop(r4);
+        GetAssembler()->cfi().AdjustCFAOffset(-static_cast<int>(kArmWordSize));
       }
       __ Lsls(ip, ip, 16);
       __ B(ne, &done);
@@ -2129,9 +2163,12 @@
         uint32_t core_spill_mask =
             (1 << lr.GetCode()) | (1 << r0.GetCode()) | (1 << r1.GetCode()) | (1 << r2.GetCode());
         __ Push(RegisterList(core_spill_mask));
+        GetAssembler()->cfi().AdjustCFAOffset(kArmWordSize * POPCOUNT(core_spill_mask));
         __ Ldr(lr, MemOperand(tr, entry_point_offset));
         __ Blx(lr);
         __ Pop(RegisterList(core_spill_mask));
+        GetAssembler()->cfi().AdjustCFAOffset(
+            -static_cast<int>(kArmWordSize) * POPCOUNT(core_spill_mask));
       } else {
         if (!RequiresCurrentMethod()) {
           CHECK(is_frame_entry);
@@ -2239,8 +2276,7 @@
       __ Push(RegisterList(MaxInt<uint32_t>(fp_spills_offset / kArmWordSize)));
       GetAssembler()->cfi().AdjustCFAOffset(fp_spills_offset);
     } else {
-      __ Sub(sp, sp, dchecked_integral_cast<int32_t>(fp_spills_offset));
-      GetAssembler()->cfi().AdjustCFAOffset(fp_spills_offset);
+      IncreaseFrame(fp_spills_offset);
       if (RequiresCurrentMethod()) {
         GetAssembler()->StoreToOffset(kStoreWord, kMethodRegister, sp, 0);
       }
@@ -2296,8 +2332,7 @@
     }
   } else {
     GetAssembler()->cfi().RememberState();
-    __ Add(sp, sp, fp_spills_offset);
-    GetAssembler()->cfi().AdjustCFAOffset(-dchecked_integral_cast<int32_t>(fp_spills_offset));
+    DecreaseFrame(fp_spills_offset);
     if (fpu_spill_mask_ != 0) {
       uint32_t first = LeastSignificantBit(fpu_spill_mask_);
 
@@ -2435,6 +2470,54 @@
   return LocationFrom(kMethodRegister);
 }
 
+Location CriticalNativeCallingConventionVisitorARMVIXL::GetNextLocation(DataType::Type type) {
+  DCHECK_NE(type, DataType::Type::kReference);
+
+  // Native ABI uses the same registers as managed, except that the method register r0
+  // is a normal argument.
+  Location location = Location::NoLocation();
+  if (DataType::Is64BitType(type)) {
+    gpr_index_ = RoundUp(gpr_index_, 2u);
+    stack_offset_ = RoundUp(stack_offset_, 2 * kFramePointerSize);
+    if (gpr_index_ < 1u + kParameterCoreRegistersLengthVIXL) {
+      location = LocationFrom(gpr_index_ == 0u ? r0 : kParameterCoreRegistersVIXL[gpr_index_ - 1u],
+                              kParameterCoreRegistersVIXL[gpr_index_]);
+      gpr_index_ += 2u;
+    }
+  } else {
+    if (gpr_index_ < 1u + kParameterCoreRegistersLengthVIXL) {
+      location = LocationFrom(gpr_index_ == 0u ? r0 : kParameterCoreRegistersVIXL[gpr_index_ - 1u]);
+      ++gpr_index_;
+    }
+  }
+  if (location.IsInvalid()) {
+    if (DataType::Is64BitType(type)) {
+      location = Location::DoubleStackSlot(stack_offset_);
+      stack_offset_ += 2 * kFramePointerSize;
+    } else {
+      location = Location::StackSlot(stack_offset_);
+      stack_offset_ += kFramePointerSize;
+    }
+
+    if (for_register_allocation_) {
+      location = Location::Any();
+    }
+  }
+  return location;
+}
+
+Location CriticalNativeCallingConventionVisitorARMVIXL::GetReturnLocation(DataType::Type type)
+    const {
+  // We perform conversion to the managed ABI return register after the call if needed.
+  InvokeDexCallingConventionVisitorARMVIXL dex_calling_convention;
+  return dex_calling_convention.GetReturnLocation(type);
+}
+
+Location CriticalNativeCallingConventionVisitorARMVIXL::GetMethodLocation() const {
+  // Pass the method in the hidden argument R4.
+  return Location::RegisterLocation(R4);
+}
+
 void CodeGeneratorARMVIXL::Move32(Location destination, Location source) {
   if (source.Equals(destination)) {
     return;
@@ -2511,7 +2594,7 @@
   // Reduce code size for AOT by using shared trampolines for slow path runtime calls across the
   // entire oat file. This adds an extra branch and we do not want to slow down the main path.
   // For JIT, thunk sharing is per-method, so the gains would be smaller or even negative.
-  if (slow_path == nullptr || Runtime::Current()->UseJitCompilation()) {
+  if (slow_path == nullptr || GetCompilerOptions().IsJitCompiler()) {
     __ Ldr(lr, MemOperand(tr, entrypoint_offset.Int32Value()));
     // Ensure the pc position is recorded immediately after the `blx` instruction.
     // blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
@@ -2946,6 +3029,16 @@
   // MaybeRecordNativeDebugInfo is already called implicitly in CodeGenerator::Compile.
 }
 
+void CodeGeneratorARMVIXL::IncreaseFrame(size_t adjustment) {
+  __ Claim(adjustment);
+  GetAssembler()->cfi().AdjustCFAOffset(adjustment);
+}
+
+void CodeGeneratorARMVIXL::DecreaseFrame(size_t adjustment) {
+  __ Drop(adjustment);
+  GetAssembler()->cfi().AdjustCFAOffset(-adjustment);
+}
+
 void CodeGeneratorARMVIXL::GenerateNop() {
   __ Nop();
 }
@@ -3294,7 +3387,13 @@
     return;
   }
 
-  HandleInvoke(invoke);
+  if (invoke->GetCodePtrLocation() == CodePtrLocation::kCallCriticalNative) {
+    CriticalNativeCallingConventionVisitorARMVIXL calling_convention_visitor(
+        /*for_register_allocation=*/ true);
+    CodeGenerator::CreateCommonInvokeLocationSummary(invoke, &calling_convention_visitor);
+  } else {
+    HandleInvoke(invoke);
+  }
 }
 
 static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorARMVIXL* codegen) {
@@ -3352,7 +3451,10 @@
 void LocationsBuilderARMVIXL::VisitInvokeInterface(HInvokeInterface* invoke) {
   HandleInvoke(invoke);
   // Add the hidden argument.
-  invoke->GetLocations()->AddTemp(LocationFrom(r12));
+  if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive) {
+    // We cannot request r12 as it's blocked by the register allocator.
+    invoke->GetLocations()->SetInAt(invoke->GetNumberOfArguments() - 1, Location::Any());
+  }
 }
 
 void CodeGeneratorARMVIXL::MaybeGenerateInlineCacheCheck(HInstruction* instruction,
@@ -3364,8 +3466,9 @@
       GetGraph()->IsCompilingBaseline() &&
       !Runtime::Current()->IsAotCompiler()) {
     DCHECK(!instruction->GetEnvironment()->IsFromInlinedInvoke());
-    ScopedObjectAccess soa(Thread::Current());
-    ProfilingInfo* info = GetGraph()->GetArtMethod()->GetProfilingInfo(kRuntimePointerSize);
+    ScopedProfilingInfoUse spiu(
+        Runtime::Current()->GetJit(), GetGraph()->GetArtMethod(), Thread::Current());
+    ProfilingInfo* info = spiu.GetProfilingInfo();
     if (info != nullptr) {
       InlineCache* cache = info->GetInlineCache(instruction->GetDexPc());
       uint32_t address = reinterpret_cast32<uint32_t>(cache);
@@ -3387,7 +3490,6 @@
   // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError.
   LocationSummary* locations = invoke->GetLocations();
   vixl32::Register temp = RegisterFrom(locations->GetTemp(0));
-  vixl32::Register hidden_reg = RegisterFrom(locations->GetTemp(1));
   Location receiver = locations->InAt(0);
   uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
 
@@ -3428,11 +3530,10 @@
   // LR = temp->GetEntryPoint();
   GetAssembler()->LoadFromOffset(kLoadWord, lr, temp, entry_point);
 
-  // Set the hidden (in r12) argument. It is done here, right before a BLX to prevent other
-  // instruction from clobbering it as they might use r12 as a scratch register.
-  DCHECK(hidden_reg.Is(r12));
-
   {
+    // Set the hidden (in r12) argument. It is done here, right before a BLX to prevent other
+    // instruction from clobbering it as they might use r12 as a scratch register.
+    Location hidden_reg = Location::RegisterLocation(r12.GetCode());
     // The VIXL macro assembler may clobber any of the scratch registers that are available to it,
     // so it checks if the application is using them (by passing them to the macro assembler
     // methods). The following application of UseScratchRegisterScope corrects VIXL's notion of
@@ -3442,8 +3543,23 @@
     // (to materialize the constant), since the destination register becomes available for such use
     // internally for the duration of the macro instruction.
     UseScratchRegisterScope temps(GetVIXLAssembler());
-    temps.Exclude(hidden_reg);
-    __ Mov(hidden_reg, invoke->GetDexMethodIndex());
+    temps.Exclude(RegisterFrom(hidden_reg));
+    if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive) {
+      Location current_method = locations->InAt(invoke->GetNumberOfArguments() - 1);
+      if (current_method.IsStackSlot()) {
+        GetAssembler()->LoadFromOffset(
+            kLoadWord, RegisterFrom(hidden_reg), sp, current_method.GetStackIndex());
+      } else {
+        __ Mov(RegisterFrom(hidden_reg), RegisterFrom(current_method));
+      }
+    } else if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRuntimeCall) {
+      // We pass the method from the IMT in case of a conflict. This will ensure
+      // we go into the runtime to resolve the actual method.
+      CHECK_NE(temp.GetCode(), lr.GetCode());
+      __ Mov(RegisterFrom(hidden_reg), temp);
+    } else {
+      codegen_->LoadMethod(invoke->GetHiddenArgumentLoadKind(), hidden_reg, invoke);
+    }
   }
   {
     // Ensure the pc position is recorded immediately after the `blx` instruction.
@@ -3461,12 +3577,20 @@
 }
 
 void LocationsBuilderARMVIXL::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
+  IntrinsicLocationsBuilderARMVIXL intrinsic(codegen_);
+  if (intrinsic.TryDispatch(invoke)) {
+    return;
+  }
   HandleInvoke(invoke);
 }
 
 void InstructionCodeGeneratorARMVIXL::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
+  if (TryGenerateIntrinsicCode(invoke, codegen_)) {
+    codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 9);
+    return;
+  }
   codegen_->GenerateInvokePolymorphicCall(invoke);
-  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 9);
+  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 10);
 }
 
 void LocationsBuilderARMVIXL::VisitInvokeCustom(HInvokeCustom* invoke) {
@@ -3475,7 +3599,7 @@
 
 void InstructionCodeGeneratorARMVIXL::VisitInvokeCustom(HInvokeCustom* invoke) {
   codegen_->GenerateInvokeCustomCall(invoke);
-  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 10);
+  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 11);
 }
 
 void LocationsBuilderARMVIXL::VisitNeg(HNeg* neg) {
@@ -4152,27 +4276,73 @@
 
   vixl32::Register out = OutputRegister(instruction);
   vixl32::Register dividend = InputRegisterAt(instruction, 0);
-  vixl32::Register temp = RegisterFrom(locations->GetTemp(0));
   int32_t imm = Int32ConstantFrom(second);
   uint32_t abs_imm = static_cast<uint32_t>(AbsOrMin(imm));
   int ctz_imm = CTZ(abs_imm);
 
-  if (ctz_imm == 1) {
-    __ Lsr(temp, dividend, 32 - ctz_imm);
-  } else {
-    __ Asr(temp, dividend, 31);
-    __ Lsr(temp, temp, 32 - ctz_imm);
-  }
-  __ Add(out, temp, dividend);
-
-  if (instruction->IsDiv()) {
-    __ Asr(out, out, ctz_imm);
+  auto generate_div_code = [this, imm, ctz_imm](vixl32::Register out, vixl32::Register in) {
+    __ Asr(out, in, ctz_imm);
     if (imm < 0) {
       __ Rsb(out, out, 0);
     }
+  };
+
+  if (HasNonNegativeOrMinIntInputAt(instruction, 0)) {
+    // No need to adjust the result for non-negative dividends or the INT32_MIN dividend.
+    // NOTE: The generated code for HDiv/HRem correctly works for the INT32_MIN dividend:
+    //   imm == 2
+    //     HDiv
+    //      add out, dividend(0x80000000), dividend(0x80000000), lsr #31 => out = 0x80000001
+    //      asr out, out(0x80000001), #1 => out = 0xc0000000
+    //      This is the same as 'asr out, dividend(0x80000000), #1'
+    //
+    //   imm > 2
+    //     HDiv
+    //      asr out, dividend(0x80000000), #31 => out = -1
+    //      add out, dividend(0x80000000), out(-1), lsr #(32 - ctz_imm) => out = 0b10..01..1,
+    //          where the number of the rightmost 1s is ctz_imm.
+    //      asr out, out(0b10..01..1), #ctz_imm => out = 0b1..10..0, where the number of the
+    //          leftmost 1s is ctz_imm + 1.
+    //      This is the same as 'asr out, dividend(0x80000000), #ctz_imm'.
+    //
+    //   imm == INT32_MIN
+    //     HDiv
+    //      asr out, dividend(0x80000000), #31 => out = -1
+    //      add out, dividend(0x80000000), out(-1), lsr #1 => out = 0xc0000000
+    //      asr out, out(0xc0000000), #31 => out = -1
+    //      rsb out, out(-1), #0 => out = 1
+    //      This is the same as
+    //        asr out, dividend(0x80000000), #31
+    //        rsb out, out, #0
+    //
+    //
+    //   INT_MIN % imm must be 0 for any imm of power 2. 'and' and 'ubfx' work only with bits
+    //   0..30 of a dividend. For INT32_MIN those bits are zeros. So 'and' and 'ubfx' always
+    //   produce zero.
+    if (instruction->IsDiv()) {
+      generate_div_code(out, dividend);
+    } else {
+      if (GetVIXLAssembler()->IsModifiedImmediate(abs_imm - 1)) {
+        __ And(out, dividend, abs_imm - 1);
+      } else {
+        __ Ubfx(out, dividend, 0, ctz_imm);
+      }
+      return;
+    }
   } else {
-    __ Ubfx(out, out, 0, ctz_imm);
-    __ Sub(out, out, temp);
+    vixl32::Register add_right_input = dividend;
+    if (ctz_imm > 1) {
+      __ Asr(out, dividend, 31);
+      add_right_input = out;
+    }
+    __ Add(out, dividend, Operand(add_right_input, vixl32::LSR, 32 - ctz_imm));
+
+    if (instruction->IsDiv()) {
+      generate_div_code(out, out);
+    } else {
+      __ Bfc(out, 0, ctz_imm);
+      __ Sub(out, dividend, out);
+    }
   }
 }
 
@@ -4194,27 +4364,70 @@
   int shift;
   CalculateMagicAndShiftForDivRem(imm, /* is_long= */ false, &magic, &shift);
 
-  // TODO(VIXL): Change the static cast to Operand::From() after VIXL is fixed.
-  __ Mov(temp1, static_cast<int32_t>(magic));
-  __ Smull(temp2, temp1, dividend, temp1);
+  auto generate_unsigned_div_code =[this, magic, shift](vixl32::Register out,
+                                                        vixl32::Register dividend,
+                                                        vixl32::Register temp1,
+                                                        vixl32::Register temp2) {
+    // TODO(VIXL): Change the static cast to Operand::From() after VIXL is fixed.
+    __ Mov(temp1, static_cast<int32_t>(magic));
+    if (magic > 0 && shift == 0) {
+      __ Smull(temp2, out, dividend, temp1);
+    } else {
+      __ Smull(temp2, temp1, dividend, temp1);
+      if (magic < 0) {
+        // The negative magic M = static_cast<int>(m) means that the multiplier m is greater
+        // than INT32_MAX. In such a case shift is never 0.
+        // Proof:
+        //   m = (2^p + d - 2^p % d) / d, where p = 32 + shift, d > 2
+        //
+        //   If shift == 0, m = (2^32 + d - 2^32 % d) / d =
+        //   = (2^32 + d - (2^32 - (2^32 / d) * d)) / d =
+        //   = (d + (2^32 / d) * d) / d = 1 + (2^32 / d), here '/' is the integer division.
+        //
+        //   1 + (2^32 / d) is decreasing when d is increasing.
+        //   The maximum is 1 431 655 766, when d == 3. This value is less than INT32_MAX.
+        //   the minimum is 3, when d = 2^31 -1.
+        //   So for all values of d in [3, INT32_MAX] m with p == 32 is in [3, INT32_MAX) and
+        //   is never less than 0.
+        __ Add(temp1, temp1, dividend);
+      }
+      DCHECK_NE(shift, 0);
+      __ Lsr(out, temp1, shift);
+    }
+  };
 
-  if (imm > 0 && magic < 0) {
-    __ Add(temp1, temp1, dividend);
-  } else if (imm < 0 && magic > 0) {
-    __ Sub(temp1, temp1, dividend);
-  }
-
-  if (shift != 0) {
-    __ Asr(temp1, temp1, shift);
-  }
-
-  if (instruction->IsDiv()) {
-    __ Sub(out, temp1, Operand(temp1, vixl32::Shift(ASR), 31));
+  if (imm > 0 && HasNonNegativeInputAt(instruction, 0)) {
+    // No need to adjust the result for a non-negative dividend and a positive divisor.
+    if (instruction->IsDiv()) {
+      generate_unsigned_div_code(out, dividend, temp1, temp2);
+    } else {
+      generate_unsigned_div_code(temp1, dividend, temp1, temp2);
+      __ Mov(temp2, imm);
+      __ Mls(out, temp1, temp2, dividend);
+    }
   } else {
-    __ Sub(temp1, temp1, Operand(temp1, vixl32::Shift(ASR), 31));
-    // TODO: Strength reduction for mls.
-    __ Mov(temp2, imm);
-    __ Mls(out, temp1, temp2, dividend);
+    // TODO(VIXL): Change the static cast to Operand::From() after VIXL is fixed.
+    __ Mov(temp1, static_cast<int32_t>(magic));
+    __ Smull(temp2, temp1, dividend, temp1);
+
+    if (imm > 0 && magic < 0) {
+      __ Add(temp1, temp1, dividend);
+    } else if (imm < 0 && magic > 0) {
+      __ Sub(temp1, temp1, dividend);
+    }
+
+    if (shift != 0) {
+      __ Asr(temp1, temp1, shift);
+    }
+
+    if (instruction->IsDiv()) {
+      __ Sub(out, temp1, Operand(temp1, vixl32::Shift(ASR), 31));
+    } else {
+      __ Sub(temp1, temp1, Operand(temp1, vixl32::Shift(ASR), 31));
+      // TODO: Strength reduction for mls.
+      __ Mov(temp2, imm);
+      __ Mls(out, temp1, temp2, dividend);
+    }
   }
 }
 
@@ -4259,16 +4472,20 @@
       if (div->InputAt(1)->IsConstant()) {
         locations->SetInAt(0, Location::RequiresRegister());
         locations->SetInAt(1, Location::ConstantLocation(div->InputAt(1)->AsConstant()));
-        locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
         int32_t value = Int32ConstantFrom(div->InputAt(1));
+        Location::OutputOverlap out_overlaps = Location::kNoOutputOverlap;
         if (value == 1 || value == 0 || value == -1) {
           // No temp register required.
+        } else if (IsPowerOfTwo(AbsOrMin(value)) &&
+                   value != 2 &&
+                   value != -2 &&
+                   !HasNonNegativeOrMinIntInputAt(div, 0)) {
+          // The "out" register is used as a temporary, so it overlaps with the inputs.
+          out_overlaps = Location::kOutputOverlap;
         } else {
-          locations->AddTemp(Location::RequiresRegister());
-          if (!IsPowerOfTwo(AbsOrMin(value))) {
-            locations->AddTemp(Location::RequiresRegister());
-          }
+          locations->AddRegisterTemps(2);
         }
+        locations->SetOut(Location::RequiresRegister(), out_overlaps);
       } else if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
         locations->SetInAt(0, Location::RequiresRegister());
         locations->SetInAt(1, Location::RequiresRegister());
@@ -4372,16 +4589,17 @@
       if (rem->InputAt(1)->IsConstant()) {
         locations->SetInAt(0, Location::RequiresRegister());
         locations->SetInAt(1, Location::ConstantLocation(rem->InputAt(1)->AsConstant()));
-        locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
         int32_t value = Int32ConstantFrom(rem->InputAt(1));
+        Location::OutputOverlap out_overlaps = Location::kNoOutputOverlap;
         if (value == 1 || value == 0 || value == -1) {
           // No temp register required.
+        } else if (IsPowerOfTwo(AbsOrMin(value)) && !HasNonNegativeOrMinIntInputAt(rem, 0)) {
+          // The "out" register is used as a temporary, so it overlaps with the inputs.
+          out_overlaps = Location::kOutputOverlap;
         } else {
-          locations->AddTemp(Location::RequiresRegister());
-          if (!IsPowerOfTwo(AbsOrMin(value))) {
-            locations->AddTemp(Location::RequiresRegister());
-          }
+          locations->AddRegisterTemps(2);
         }
+        locations->SetOut(Location::RequiresRegister(), out_overlaps);
       } else if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
         locations->SetInAt(0, Location::RequiresRegister());
         locations->SetInAt(1, Location::RequiresRegister());
@@ -5212,7 +5430,7 @@
 void InstructionCodeGeneratorARMVIXL::VisitNewInstance(HNewInstance* instruction) {
   codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
   CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
-  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 11);
+  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 12);
 }
 
 void LocationsBuilderARMVIXL::VisitNewArray(HNewArray* instruction) {
@@ -5230,7 +5448,7 @@
   codegen_->InvokeRuntime(entrypoint, instruction, instruction->GetDexPc());
   CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>();
   DCHECK(!codegen_->IsLeafMethod());
-  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 12);
+  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 13);
 }
 
 void LocationsBuilderARMVIXL::VisitParameterValue(HParameterValue* instruction) {
@@ -5516,7 +5734,10 @@
   LocationSummary* locations = instruction->GetLocations();
   vixl32::Register base = InputRegisterAt(instruction, 0);
   Location value = locations->InAt(1);
+  std::optional<vixl::aarch32::Label> pred_is_null;
 
+  bool is_predicated =
+      instruction->IsInstanceFieldSet() && instruction->AsInstanceFieldSet()->GetIsPredicatedSet();
   bool is_volatile = field_info.IsVolatile();
   bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
   DataType::Type field_type = field_info.GetFieldType();
@@ -5524,6 +5745,11 @@
   bool needs_write_barrier =
       CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1));
 
+  if (is_predicated) {
+    pred_is_null.emplace();
+    __ CompareAndBranchIfZero(base, &*pred_is_null, /* is_far_target= */ false);
+  }
+
   if (is_volatile) {
     codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
   }
@@ -5627,14 +5853,21 @@
   if (is_volatile) {
     codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
   }
+
+  if (is_predicated) {
+    __ Bind(&*pred_is_null);
+  }
 }
 
 void LocationsBuilderARMVIXL::HandleFieldGet(HInstruction* instruction,
                                              const FieldInfo& field_info) {
-  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
+  DCHECK(instruction->IsInstanceFieldGet() ||
+         instruction->IsStaticFieldGet() ||
+         instruction->IsPredicatedInstanceFieldGet());
 
   bool object_field_get_with_read_barrier =
       kEmitCompilerReadBarrier && (field_info.GetFieldType() == DataType::Type::kReference);
+  bool is_predicated = instruction->IsPredicatedInstanceFieldGet();
   LocationSummary* locations =
       new (GetGraph()->GetAllocator()) LocationSummary(instruction,
                                                        object_field_get_with_read_barrier
@@ -5643,7 +5876,8 @@
   if (object_field_get_with_read_barrier && kUseBakerReadBarrier) {
     locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty());  // No caller-save registers.
   }
-  locations->SetInAt(0, Location::RequiresRegister());
+  // Input for object receiver.
+  locations->SetInAt(is_predicated ? 1 : 0, Location::RequiresRegister());
 
   bool volatile_for_double = field_info.IsVolatile()
       && (field_info.GetFieldType() == DataType::Type::kFloat64)
@@ -5658,10 +5892,20 @@
       object_field_get_with_read_barrier;
 
   if (DataType::IsFloatingPointType(instruction->GetType())) {
-    locations->SetOut(Location::RequiresFpuRegister());
+    if (is_predicated) {
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+    } else {
+      locations->SetOut(Location::RequiresFpuRegister());
+    }
   } else {
-    locations->SetOut(Location::RequiresRegister(),
-                      (overlap ? Location::kOutputOverlap : Location::kNoOutputOverlap));
+    if (is_predicated) {
+      locations->SetInAt(0, Location::RequiresRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+    } else {
+      locations->SetOut(Location::RequiresRegister(),
+                        (overlap ? Location::kOutputOverlap : Location::kNoOutputOverlap));
+    }
   }
   if (volatile_for_double) {
     // ARM encoding have some additional constraints for ldrexd/strexd:
@@ -5762,10 +6006,13 @@
 
 void InstructionCodeGeneratorARMVIXL::HandleFieldGet(HInstruction* instruction,
                                                      const FieldInfo& field_info) {
-  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
+  DCHECK(instruction->IsInstanceFieldGet() ||
+         instruction->IsStaticFieldGet() ||
+         instruction->IsPredicatedInstanceFieldGet());
 
   LocationSummary* locations = instruction->GetLocations();
-  vixl32::Register base = InputRegisterAt(instruction, 0);
+  uint32_t receiver_input = instruction->IsPredicatedInstanceFieldGet() ? 1 : 0;
+  vixl32::Register base = InputRegisterAt(instruction, receiver_input);
   Location out = locations->Out();
   bool is_volatile = field_info.IsVolatile();
   bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
@@ -5812,7 +6059,8 @@
         // If read barriers are enabled, emit read barriers other than
         // Baker's using a slow path (and also unpoison the loaded
         // reference, if heap poisoning is enabled).
-        codegen_->MaybeGenerateReadBarrierSlow(instruction, out, out, locations->InAt(0), offset);
+        codegen_->MaybeGenerateReadBarrierSlow(
+            instruction, out, out, locations->InAt(receiver_input), offset);
       }
       break;
     }
@@ -5883,6 +6131,19 @@
   HandleFieldGet(instruction, instruction->GetFieldInfo());
 }
 
+void LocationsBuilderARMVIXL::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* instruction) {
+  HandleFieldGet(instruction, instruction->GetFieldInfo());
+}
+
+void InstructionCodeGeneratorARMVIXL::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* instruction) {
+  vixl::aarch32::Label finish;
+  __ CompareAndBranchIfZero(InputRegisterAt(instruction, 1), &finish, false);
+  HandleFieldGet(instruction, instruction->GetFieldInfo());
+  __ Bind(&finish);
+}
+
 void InstructionCodeGeneratorARMVIXL::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
   HandleFieldGet(instruction, instruction->GetFieldInfo());
 }
@@ -6535,7 +6796,7 @@
         }
       }
 
-      codegen_->MarkGCCard(temp1, temp2, array, value, /* can_be_null= */ false);
+      codegen_->MarkGCCard(temp1, temp2, array, value, /* value_can_be_null= */ false);
 
       if (can_value_be_null) {
         DCHECK(do_store.IsReferenced());
@@ -6766,10 +7027,10 @@
                                       vixl32::Register card,
                                       vixl32::Register object,
                                       vixl32::Register value,
-                                      bool can_be_null) {
+                                      bool value_can_be_null) {
   vixl32::Label is_null;
-  if (can_be_null) {
-    __ CompareAndBranchIfZero(value, &is_null);
+  if (value_can_be_null) {
+    __ CompareAndBranchIfZero(value, &is_null, /* is_far_target=*/ false);
   }
   // Load the address of the card table into `card`.
   GetAssembler()->LoadFromOffset(
@@ -6791,7 +7052,7 @@
   // of the card to mark; and 2. to load the `kCardDirty` value) saves a load
   // (no need to explicitly load `kCardDirty` as an immediate value).
   __ Strb(card, MemOperand(card, temp));
-  if (can_be_null) {
+  if (value_can_be_null) {
     __ Bind(&is_null);
   }
 }
@@ -6829,7 +7090,7 @@
     return;
   }
   GenerateSuspendCheck(instruction, nullptr);
-  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 13);
+  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 14);
 }
 
 void InstructionCodeGeneratorARMVIXL::GenerateSuspendCheck(HSuspendCheck* instruction,
@@ -7123,11 +7384,13 @@
     case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadClass::LoadKind::kBootImageRelRo:
     case HLoadClass::LoadKind::kBssEntry:
-      DCHECK(!Runtime::Current()->UseJitCompilation());
+    case HLoadClass::LoadKind::kBssEntryPublic:
+    case HLoadClass::LoadKind::kBssEntryPackage:
+      DCHECK(!GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadClass::LoadKind::kJitBootImageAddress:
     case HLoadClass::LoadKind::kJitTableAddress:
-      DCHECK(Runtime::Current()->UseJitCompilation());
+      DCHECK(GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadClass::LoadKind::kRuntimeCall:
       break;
@@ -7146,7 +7409,9 @@
     DCHECK(calling_convention.GetRegisterAt(0).Is(r0));
     return;
   }
-  DCHECK(!cls->NeedsAccessCheck());
+  DCHECK_EQ(cls->NeedsAccessCheck(),
+            load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+                load_kind == HLoadClass::LoadKind::kBssEntryPackage);
 
   const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage();
   LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier)
@@ -7177,10 +7442,12 @@
   HLoadClass::LoadKind load_kind = cls->GetLoadKind();
   if (load_kind == HLoadClass::LoadKind::kRuntimeCall) {
     codegen_->GenerateLoadClassRuntimeCall(cls);
-    codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 14);
+    codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 15);
     return;
   }
-  DCHECK(!cls->NeedsAccessCheck());
+  DCHECK_EQ(cls->NeedsAccessCheck(),
+            load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+                load_kind == HLoadClass::LoadKind::kBssEntryPackage);
 
   LocationSummary* locations = cls->GetLocations();
   Location out_loc = locations->Out();
@@ -7215,14 +7482,15 @@
     case HLoadClass::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
-          codegen_->NewBootImageRelRoPatch(codegen_->GetBootImageOffset(cls));
+          codegen_->NewBootImageRelRoPatch(CodeGenerator::GetBootImageOffset(cls));
       codegen_->EmitMovwMovtPlaceholder(labels, out);
       __ Ldr(out, MemOperand(out, /* offset= */ 0));
       break;
     }
-    case HLoadClass::LoadKind::kBssEntry: {
-      CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
-          codegen_->NewTypeBssEntryPatch(cls->GetDexFile(), cls->GetTypeIndex());
+    case HLoadClass::LoadKind::kBssEntry:
+    case HLoadClass::LoadKind::kBssEntryPublic:
+    case HLoadClass::LoadKind::kBssEntryPackage: {
+      CodeGeneratorARMVIXL::PcRelativePatchInfo* labels = codegen_->NewTypeBssEntryPatch(cls);
       codegen_->EmitMovwMovtPlaceholder(labels, out);
       // All aligned loads are implicitly atomic consume operations on ARM.
       codegen_->GenerateGcRootFieldLoad(cls, out_loc, out, /* offset= */ 0, read_barrier_option);
@@ -7263,7 +7531,7 @@
     } else {
       __ Bind(slow_path->GetExitLabel());
     }
-    codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 15);
+    codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 16);
   }
 }
 
@@ -7388,11 +7656,11 @@
     case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadString::LoadKind::kBootImageRelRo:
     case HLoadString::LoadKind::kBssEntry:
-      DCHECK(!Runtime::Current()->UseJitCompilation());
+      DCHECK(!GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadString::LoadKind::kJitBootImageAddress:
     case HLoadString::LoadKind::kJitTableAddress:
-      DCHECK(Runtime::Current()->UseJitCompilation());
+      DCHECK(GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadString::LoadKind::kRuntimeCall:
       break;
@@ -7439,7 +7707,7 @@
     case HLoadString::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
-          codegen_->NewBootImageRelRoPatch(codegen_->GetBootImageOffset(load));
+          codegen_->NewBootImageRelRoPatch(CodeGenerator::GetBootImageOffset(load));
       codegen_->EmitMovwMovtPlaceholder(labels, out);
       __ Ldr(out, MemOperand(out, /* offset= */ 0));
       return;
@@ -7456,7 +7724,7 @@
       codegen_->AddSlowPath(slow_path);
       __ CompareAndBranchIfZero(out, slow_path->GetEntryLabel());
       __ Bind(slow_path->GetExitLabel());
-      codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 16);
+      codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 17);
       return;
     }
     case HLoadString::LoadKind::kJitBootImageAddress: {
@@ -7484,7 +7752,7 @@
   __ Mov(calling_convention.GetRegisterAt(0), load->GetStringIndex().index_);
   codegen_->InvokeRuntime(kQuickResolveString, load, load->GetDexPc());
   CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
-  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 17);
+  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 18);
 }
 
 static int32_t GetExceptionTlsOffset() {
@@ -8114,7 +8382,7 @@
   } else {
     CheckEntrypointTypes<kQuickUnlockObject, void, mirror::Object*>();
   }
-  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 18);
+  codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 19);
 }
 
 void LocationsBuilderARMVIXL::VisitAnd(HAnd* instruction) {
@@ -8585,21 +8853,25 @@
     // Note that GC roots are not affected by heap poisoning, thus we
     // do not have to unpoison `root_reg` here.
   }
-  MaybeGenerateMarkingRegisterCheck(/* code= */ 19);
+  MaybeGenerateMarkingRegisterCheck(/* code= */ 20);
 }
 
-void CodeGeneratorARMVIXL::GenerateUnsafeCasOldValueAddWithBakerReadBarrier(
-    vixl::aarch32::Register old_value,
-    vixl::aarch32::Register adjusted_old_value,
-    vixl::aarch32::Register expected) {
+void CodeGeneratorARMVIXL::GenerateIntrinsicCasMoveWithBakerReadBarrier(
+    vixl::aarch32::Register marked_old_value,
+    vixl::aarch32::Register old_value) {
   DCHECK(kEmitCompilerReadBarrier);
   DCHECK(kUseBakerReadBarrier);
 
-  // Similar to the Baker RB path in GenerateGcRootFieldLoad(), with an ADD instead of LDR.
-  uint32_t custom_data = EncodeBakerReadBarrierUnsafeCasData(old_value.GetCode());
+  // Similar to the Baker RB path in GenerateGcRootFieldLoad(), with a MOV instead of LDR.
+  // For low registers, we can reuse the GC root narrow entrypoint, for high registers
+  // we use a specialized entrypoint because the register bits are 8-11 instead of 12-15.
+  bool narrow_mov = marked_old_value.IsLow();
+  uint32_t custom_data = narrow_mov
+      ? EncodeBakerReadBarrierGcRootData(marked_old_value.GetCode(), /*narrow=*/ true)
+      : EncodeBakerReadBarrierIntrinsicCasData(marked_old_value.GetCode());
 
-  size_t narrow_instructions = /* CMP */ (mr.IsLow() ? 1u : 0u);
-  size_t wide_instructions = /* ADR+CMP+ADD+BNE */ 4u - narrow_instructions;
+  size_t narrow_instructions = /* CMP */ (mr.IsLow() ? 1u : 0u) + /* MOV */ (narrow_mov ? 1u : 0u);
+  size_t wide_instructions = /* ADR+CMP+MOV+BNE */ 4u - narrow_instructions;
   size_t exact_size = wide_instructions * vixl32::k32BitT32InstructionSizeInBytes +
                       narrow_instructions * vixl32::k16BitT32InstructionSizeInBytes;
   ExactAssemblyScope guard(GetVIXLAssembler(), exact_size);
@@ -8607,11 +8879,13 @@
   EmitAdrCode adr(GetVIXLAssembler(), lr, &return_address);
   __ cmp(mr, Operand(0));
   ptrdiff_t old_offset = GetVIXLAssembler()->GetBuffer()->GetCursorOffset();
-  __ add(EncodingSize(Wide), old_value, adjusted_old_value, Operand(expected));  // Preserves flags.
+  __ mov(EncodingSize(narrow_mov ? Narrow : Wide), marked_old_value, old_value);
   EmitBakerReadBarrierBne(custom_data);
   __ bind(&return_address);
   DCHECK_EQ(old_offset - GetVIXLAssembler()->GetBuffer()->GetCursorOffset(),
-            BAKER_MARK_INTROSPECTION_UNSAFE_CAS_ADD_OFFSET);
+            narrow_mov
+                ? BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_NARROW_OFFSET
+                : BAKER_MARK_INTROSPECTION_INTRINSIC_CAS_MOV_OFFSET);
 }
 
 void CodeGeneratorARMVIXL::GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction,
@@ -8685,19 +8959,19 @@
               narrow ? BAKER_MARK_INTROSPECTION_FIELD_LDR_NARROW_OFFSET
                      : BAKER_MARK_INTROSPECTION_FIELD_LDR_WIDE_OFFSET);
   }
-  MaybeGenerateMarkingRegisterCheck(/* code= */ 20, /* temp_loc= */ LocationFrom(ip));
+  MaybeGenerateMarkingRegisterCheck(/* code= */ 21, /* temp_loc= */ LocationFrom(ip));
 }
 
 void CodeGeneratorARMVIXL::GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction,
                                                                  Location ref,
                                                                  vixl32::Register obj,
                                                                  uint32_t offset,
-                                                                 Location temp,
+                                                                 Location maybe_temp,
                                                                  bool needs_null_check) {
   DCHECK_ALIGNED(offset, sizeof(mirror::HeapReference<mirror::Object>));
   vixl32::Register base = obj;
   if (offset >= kReferenceLoadMinFarOffset) {
-    base = RegisterFrom(temp);
+    base = RegisterFrom(maybe_temp);
     static_assert(IsPowerOfTwo(kReferenceLoadMinFarOffset), "Expecting a power of 2.");
     __ Add(base, obj, Operand(offset & ~(kReferenceLoadMinFarOffset - 1u)));
     offset &= (kReferenceLoadMinFarOffset - 1u);
@@ -8773,7 +9047,7 @@
     DCHECK_EQ(old_offset - GetVIXLAssembler()->GetBuffer()->GetCursorOffset(),
               BAKER_MARK_INTROSPECTION_ARRAY_LDR_OFFSET);
   }
-  MaybeGenerateMarkingRegisterCheck(/* code= */ 21, /* temp_loc= */ LocationFrom(ip));
+  MaybeGenerateMarkingRegisterCheck(/* code= */ 22, /* temp_loc= */ LocationFrom(ip));
 }
 
 void CodeGeneratorARMVIXL::MaybeGenerateMarkingRegisterCheck(int code, Location temp_loc) {
@@ -8790,6 +9064,18 @@
   }
 }
 
+SlowPathCodeARMVIXL* CodeGeneratorARMVIXL::AddReadBarrierSlowPath(HInstruction* instruction,
+                                                                  Location out,
+                                                                  Location ref,
+                                                                  Location obj,
+                                                                  uint32_t offset,
+                                                                  Location index) {
+  SlowPathCodeARMVIXL* slow_path = new (GetScopedAllocator())
+      ReadBarrierForHeapReferenceSlowPathARMVIXL(instruction, out, ref, obj, offset, index);
+  AddSlowPath(slow_path);
+  return slow_path;
+}
+
 void CodeGeneratorARMVIXL::GenerateReadBarrierSlow(HInstruction* instruction,
                                                    Location out,
                                                    Location ref,
@@ -8809,9 +9095,8 @@
   // not used by the artReadBarrierSlow entry point.
   //
   // TODO: Unpoison `ref` when it is used by artReadBarrierSlow.
-  SlowPathCodeARMVIXL* slow_path = new (GetScopedAllocator())
-      ReadBarrierForHeapReferenceSlowPathARMVIXL(instruction, out, ref, obj, offset, index);
-  AddSlowPath(slow_path);
+  SlowPathCodeARMVIXL* slow_path =
+      AddReadBarrierSlowPath(instruction, out, ref, obj, offset, index);
 
   __ B(slow_path->GetEntryLabel());
   __ Bind(slow_path->GetExitLabel());
@@ -8856,57 +9141,40 @@
 // otherwise return a fall-back info that should be used instead.
 HInvokeStaticOrDirect::DispatchInfo CodeGeneratorARMVIXL::GetSupportedInvokeStaticOrDirectDispatch(
     const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
-    ArtMethod* method ATTRIBUTE_UNUSED) {
+    ArtMethod* method) {
+  if (method->IsIntrinsic() &&
+      desired_dispatch_info.code_ptr_location == CodePtrLocation::kCallCriticalNative) {
+    // As a work-around for soft-float native ABI interfering with type checks, we are
+    // inserting fake calls to Float.floatToRawIntBits() or Double.doubleToRawLongBits()
+    // when a float or double argument is passed in core registers but we cannot do that
+    // for actual intrinsic implementations that expect them in FP registers. Therefore
+    // we do not use `kCallCriticalNative` for intrinsics with FP arguments; if they are
+    // properly intrinsified, the dispatch type does not matter anyway.
+    ScopedObjectAccess soa(Thread::Current());
+    uint32_t shorty_len;
+    const char* shorty = method->GetShorty(&shorty_len);
+    for (uint32_t i = 1; i != shorty_len; ++i) {
+      if (shorty[i] == 'D' || shorty[i] == 'F') {
+        HInvokeStaticOrDirect::DispatchInfo dispatch_info = desired_dispatch_info;
+        dispatch_info.code_ptr_location = CodePtrLocation::kCallArtMethod;
+        return dispatch_info;
+      }
+    }
+  }
   return desired_dispatch_info;
 }
 
-vixl32::Register CodeGeneratorARMVIXL::GetInvokeStaticOrDirectExtraParameter(
-    HInvokeStaticOrDirect* invoke, vixl32::Register temp) {
-  DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
-  Location location = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
-  if (!invoke->GetLocations()->Intrinsified()) {
-    return RegisterFrom(location);
-  }
-  // For intrinsics we allow any location, so it may be on the stack.
-  if (!location.IsRegister()) {
-    GetAssembler()->LoadFromOffset(kLoadWord, temp, sp, location.GetStackIndex());
-    return temp;
-  }
-  // For register locations, check if the register was saved. If so, get it from the stack.
-  // Note: There is a chance that the register was saved but not overwritten, so we could
-  // save one load. However, since this is just an intrinsic slow path we prefer this
-  // simple and more robust approach rather that trying to determine if that's the case.
-  SlowPathCode* slow_path = GetCurrentSlowPath();
-  if (slow_path != nullptr && slow_path->IsCoreRegisterSaved(RegisterFrom(location).GetCode())) {
-    int stack_offset = slow_path->GetStackOffsetOfCoreRegister(RegisterFrom(location).GetCode());
-    GetAssembler()->LoadFromOffset(kLoadWord, temp, sp, stack_offset);
-    return temp;
-  }
-  return RegisterFrom(location);
-}
 
-void CodeGeneratorARMVIXL::GenerateStaticOrDirectCall(
-    HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
-  Location callee_method = temp;  // For all kinds except kRecursive, callee will be in temp.
-  switch (invoke->GetMethodLoadKind()) {
-    case HInvokeStaticOrDirect::MethodLoadKind::kStringInit: {
-      uint32_t offset =
-          GetThreadOffset<kArmPointerSize>(invoke->GetStringInitEntryPoint()).Int32Value();
-      // temp = thread->string_init_entrypoint
-      GetAssembler()->LoadFromOffset(kLoadWord, RegisterFrom(temp), tr, offset);
-      break;
-    }
-    case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
-      callee_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
-      break;
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative: {
+void CodeGeneratorARMVIXL::LoadMethod(MethodLoadKind load_kind, Location temp, HInvoke* invoke) {
+  switch (load_kind) {
+    case MethodLoadKind::kBootImageLinkTimePcRelative: {
       DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
-      PcRelativePatchInfo* labels = NewBootImageMethodPatch(invoke->GetTargetMethod());
+      PcRelativePatchInfo* labels = NewBootImageMethodPatch(invoke->GetResolvedMethodReference());
       vixl32::Register temp_reg = RegisterFrom(temp);
       EmitMovwMovtPlaceholder(labels, temp_reg);
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
+    case MethodLoadKind::kBootImageRelRo: {
       uint32_t boot_image_offset = GetBootImageOffset(invoke);
       PcRelativePatchInfo* labels = NewBootImageRelRoPatch(boot_image_offset);
       vixl32::Register temp_reg = RegisterFrom(temp);
@@ -8914,26 +9182,76 @@
       GetAssembler()->LoadFromOffset(kLoadWord, temp_reg, temp_reg, /* offset*/ 0);
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
-      PcRelativePatchInfo* labels = NewMethodBssEntryPatch(
-          MethodReference(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex()));
+    case MethodLoadKind::kBssEntry: {
+      PcRelativePatchInfo* labels = NewMethodBssEntryPatch(invoke->GetMethodReference());
       vixl32::Register temp_reg = RegisterFrom(temp);
       EmitMovwMovtPlaceholder(labels, temp_reg);
       // All aligned loads are implicitly atomic consume operations on ARM.
       GetAssembler()->LoadFromOffset(kLoadWord, temp_reg, temp_reg, /* offset*/ 0);
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
-      __ Mov(RegisterFrom(temp), Operand::From(invoke->GetMethodAddress()));
+    case MethodLoadKind::kJitDirectAddress: {
+      __ Mov(RegisterFrom(temp), Operand::From(invoke->GetResolvedMethod()));
       break;
-    case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+    }
+    case MethodLoadKind::kRuntimeCall: {
+      // Test situation, don't do anything.
+      break;
+    }
+    default: {
+      LOG(FATAL) << "Load kind should have already been handled " << load_kind;
+      UNREACHABLE();
+    }
+  }
+}
+
+void CodeGeneratorARMVIXL::GenerateStaticOrDirectCall(
+    HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
+  Location callee_method = temp;  // For all kinds except kRecursive, callee will be in temp.
+  switch (invoke->GetMethodLoadKind()) {
+    case MethodLoadKind::kStringInit: {
+      uint32_t offset =
+          GetThreadOffset<kArmPointerSize>(invoke->GetStringInitEntryPoint()).Int32Value();
+      // temp = thread->string_init_entrypoint
+      GetAssembler()->LoadFromOffset(kLoadWord, RegisterFrom(temp), tr, offset);
+      break;
+    }
+    case MethodLoadKind::kRecursive: {
+      callee_method = invoke->GetLocations()->InAt(invoke->GetCurrentMethodIndex());
+      break;
+    }
+    case MethodLoadKind::kRuntimeCall: {
       GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
       return;  // No code pointer retrieval; the runtime performs the call directly.
     }
+    case MethodLoadKind::kBootImageLinkTimePcRelative:
+      // Note: Unlike arm64, x86 and x86-64, we do not avoid the materialization of method
+      // pointer for kCallCriticalNative because it would not save us an instruction from
+      // the current sequence MOVW+MOVT+ADD(pc)+LDR+BL. The ADD(pc) separates the patched
+      // offset instructions MOVW+MOVT from the entrypoint load, so they cannot be fused.
+      FALLTHROUGH_INTENDED;
+    default: {
+      LoadMethod(invoke->GetMethodLoadKind(), temp, invoke);
+      break;
+    }
   }
 
+  auto call_code_pointer_member = [&](MemberOffset offset) {
+    // LR = callee_method->member;
+    GetAssembler()->LoadFromOffset(kLoadWord, lr, RegisterFrom(callee_method), offset.Int32Value());
+    {
+      // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
+      // blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
+      ExactAssemblyScope aas(GetVIXLAssembler(),
+                             vixl32::k16BitT32InstructionSizeInBytes,
+                             CodeBufferCheckScope::kExactSize);
+      // LR()
+      __ blx(lr);
+      RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+    }
+  };
   switch (invoke->GetCodePtrLocation()) {
-    case HInvokeStaticOrDirect::CodePtrLocation::kCallSelf:
+    case CodePtrLocation::kCallSelf:
       {
         // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
         ExactAssemblyScope aas(GetVIXLAssembler(),
@@ -8943,23 +9261,39 @@
         RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
       }
       break;
-    case HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod:
-      // LR = callee_method->entry_point_from_quick_compiled_code_
-      GetAssembler()->LoadFromOffset(
-            kLoadWord,
-            lr,
-            RegisterFrom(callee_method),
-            ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArmPointerSize).Int32Value());
-      {
-        // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
-        // blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
-        ExactAssemblyScope aas(GetVIXLAssembler(),
-                               vixl32::k16BitT32InstructionSizeInBytes,
-                               CodeBufferCheckScope::kExactSize);
-        // LR()
-        __ blx(lr);
-        RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+    case CodePtrLocation::kCallCriticalNative: {
+      size_t out_frame_size =
+          PrepareCriticalNativeCall<CriticalNativeCallingConventionVisitorARMVIXL,
+                                    kAapcsStackAlignment,
+                                    GetCriticalNativeDirectCallFrameSize>(invoke);
+      call_code_pointer_member(ArtMethod::EntryPointFromJniOffset(kArmPointerSize));
+      // Move the result when needed due to native and managed ABI mismatch.
+      switch (invoke->GetType()) {
+        case DataType::Type::kFloat32:
+          __ Vmov(s0, r0);
+          break;
+        case DataType::Type::kFloat64:
+          __ Vmov(d0, r0, r1);
+          break;
+        case DataType::Type::kBool:
+        case DataType::Type::kInt8:
+        case DataType::Type::kUint16:
+        case DataType::Type::kInt16:
+        case DataType::Type::kInt32:
+        case DataType::Type::kInt64:
+        case DataType::Type::kVoid:
+          break;
+        default:
+          DCHECK(false) << invoke->GetType();
+          break;
       }
+      if (out_frame_size != 0u) {
+        DecreaseFrame(out_frame_size);
+      }
+      break;
+    }
+    case CodePtrLocation::kCallArtMethod:
+      call_code_pointer_member(ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArmPointerSize));
       break;
   }
 
@@ -9048,8 +9382,25 @@
 }
 
 CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewTypeBssEntryPatch(
-    const DexFile& dex_file, dex::TypeIndex type_index) {
-  return NewPcRelativePatch(&dex_file, type_index.index_, &type_bss_entry_patches_);
+    HLoadClass* load_class) {
+  const DexFile& dex_file = load_class->GetDexFile();
+  dex::TypeIndex type_index = load_class->GetTypeIndex();
+  ArenaDeque<PcRelativePatchInfo>* patches = nullptr;
+  switch (load_class->GetLoadKind()) {
+    case HLoadClass::LoadKind::kBssEntry:
+      patches = &type_bss_entry_patches_;
+      break;
+    case HLoadClass::LoadKind::kBssEntryPublic:
+      patches = &public_type_bss_entry_patches_;
+      break;
+    case HLoadClass::LoadKind::kBssEntryPackage:
+      patches = &package_type_bss_entry_patches_;
+      break;
+    default:
+      LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind();
+      UNREACHABLE();
+  }
+  return NewPcRelativePatch(&dex_file, type_index.index_, patches);
 }
 
 CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewBootImageStringPatch(
@@ -9070,7 +9421,7 @@
 
 void CodeGeneratorARMVIXL::EmitEntrypointThunkCall(ThreadOffset32 entrypoint_offset) {
   DCHECK(!__ AllowMacroInstructions());  // In ExactAssemblyScope.
-  DCHECK(!Runtime::Current()->UseJitCompilation());
+  DCHECK(!GetCompilerOptions().IsJitCompiler());
   call_entrypoint_patches_.emplace_back(/*dex_file*/ nullptr, entrypoint_offset.Uint32Value());
   vixl::aarch32::Label* bl_label = &call_entrypoint_patches_.back().label;
   __ bind(bl_label);
@@ -9081,7 +9432,7 @@
 
 void CodeGeneratorARMVIXL::EmitBakerReadBarrierBne(uint32_t custom_data) {
   DCHECK(!__ AllowMacroInstructions());  // In ExactAssemblyScope.
-  if (Runtime::Current()->UseJitCompilation()) {
+  if (GetCompilerOptions().IsJitCompiler()) {
     auto it = jit_baker_read_barrier_slow_paths_.FindOrAdd(custom_data);
     vixl::aarch32::Label* slow_path_entry = &it->second.label;
     __ b(ne, EncodingSize(Wide), slow_path_entry);
@@ -9134,7 +9485,7 @@
     EmitMovwMovtPlaceholder(labels, reg);
     __ Ldr(reg, MemOperand(reg, /* offset= */ 0));
   } else {
-    DCHECK(Runtime::Current()->UseJitCompilation());
+    DCHECK(GetCompilerOptions().IsJitCompiler());
     gc::Heap* heap = Runtime::Current()->GetHeap();
     DCHECK(!heap->GetBootImageSpaces().empty());
     uintptr_t address =
@@ -9143,23 +9494,38 @@
   }
 }
 
-void CodeGeneratorARMVIXL::AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke,
-                                                        uint32_t boot_image_offset) {
-  DCHECK(invoke->IsStatic());
-  InvokeRuntimeCallingConventionARMVIXL calling_convention;
-  vixl32::Register argument = calling_convention.GetRegisterAt(0);
+void CodeGeneratorARMVIXL::LoadTypeForBootImageIntrinsic(vixl::aarch32::Register reg,
+                                                         TypeReference target_type) {
+  // Load the class the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
+  DCHECK(GetCompilerOptions().IsBootImage());
+  PcRelativePatchInfo* labels =
+      NewBootImageTypePatch(*target_type.dex_file, target_type.TypeIndex());
+  EmitMovwMovtPlaceholder(labels, reg);
+}
+
+void CodeGeneratorARMVIXL::LoadIntrinsicDeclaringClass(vixl32::Register reg, HInvoke* invoke) {
+  DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
   if (GetCompilerOptions().IsBootImage()) {
-    DCHECK_EQ(boot_image_offset, IntrinsicVisitor::IntegerValueOfInfo::kInvalidReference);
-    // Load the class the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
-    MethodReference target_method = invoke->GetTargetMethod();
+    MethodReference target_method = invoke->GetResolvedMethodReference();
     dex::TypeIndex type_idx = target_method.dex_file->GetMethodId(target_method.index).class_idx_;
-    PcRelativePatchInfo* labels = NewBootImageTypePatch(*target_method.dex_file, type_idx);
-    EmitMovwMovtPlaceholder(labels, argument);
+    LoadTypeForBootImageIntrinsic(reg, TypeReference(target_method.dex_file, type_idx));
   } else {
-    LoadBootImageAddress(argument, boot_image_offset);
+    uint32_t boot_image_offset = GetBootImageOffsetOfIntrinsicDeclaringClass(invoke);
+    LoadBootImageAddress(reg, boot_image_offset);
   }
-  InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
-  CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
+}
+
+void CodeGeneratorARMVIXL::LoadClassRootForIntrinsic(vixl::aarch32::Register reg,
+                                                     ClassRoot class_root) {
+  if (GetCompilerOptions().IsBootImage()) {
+    ScopedObjectAccess soa(Thread::Current());
+    ObjPtr<mirror::Class> klass = GetClassRoot(class_root);
+    TypeReference target_type(&klass->GetDexFile(), klass->GetDexTypeIndex());
+    LoadTypeForBootImageIntrinsic(reg, target_type);
+  } else {
+    uint32_t boot_image_offset = GetBootImageOffset(class_root);
+    LoadBootImageAddress(reg, boot_image_offset);
+  }
 }
 
 template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)>
@@ -9198,6 +9564,8 @@
       /* MOVW+MOVT for each entry */ 2u * method_bss_entry_patches_.size() +
       /* MOVW+MOVT for each entry */ 2u * boot_image_type_patches_.size() +
       /* MOVW+MOVT for each entry */ 2u * type_bss_entry_patches_.size() +
+      /* MOVW+MOVT for each entry */ 2u * public_type_bss_entry_patches_.size() +
+      /* MOVW+MOVT for each entry */ 2u * package_type_bss_entry_patches_.size() +
       /* MOVW+MOVT for each entry */ 2u * boot_image_string_patches_.size() +
       /* MOVW+MOVT for each entry */ 2u * string_bss_entry_patches_.size() +
       /* MOVW+MOVT for each entry */ 2u * boot_image_other_patches_.size() +
@@ -9227,6 +9595,10 @@
       method_bss_entry_patches_, linker_patches);
   EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>(
       type_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>(
+      public_type_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>(
+      package_type_bss_entry_patches_, linker_patches);
   EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>(
       string_bss_entry_patches_, linker_patches);
   for (const PatchInfo<vixl32::Label>& info : call_entrypoint_patches_) {
@@ -9258,7 +9630,7 @@
       MemberOffset offset = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArmPointerSize);
       assembler.LoadFromOffset(arm::kLoadWord, vixl32::pc, vixl32::r0, offset.Int32Value());
       assembler.GetVIXLAssembler()->Bkpt(0);
-      if (GetCompilerOptions().GenerateAnyDebugInfo()) {
+      if (debug_name != nullptr && GetCompilerOptions().GenerateAnyDebugInfo()) {
         *debug_name = "MethodCallThunk";
       }
       break;
@@ -9266,7 +9638,7 @@
     case linker::LinkerPatch::Type::kCallEntrypoint: {
       assembler.LoadFromOffset(arm::kLoadWord, vixl32::pc, tr, patch.EntrypointOffset());
       assembler.GetVIXLAssembler()->Bkpt(0);
-      if (GetCompilerOptions().GenerateAnyDebugInfo()) {
+      if (debug_name != nullptr && GetCompilerOptions().GenerateAnyDebugInfo()) {
         *debug_name = "EntrypointCallThunk_" + std::to_string(patch.EntrypointOffset());
       }
       break;
@@ -9443,18 +9815,10 @@
     return;
   }
 
-  // TODO: Consider pairs in the parallel move resolver, then this could be nicely merged
-  //       with the last branch.
-  if (type == DataType::Type::kInt64) {
-    TODO_VIXL32(FATAL);
-  } else if (type == DataType::Type::kFloat64) {
-    TODO_VIXL32(FATAL);
-  } else {
-    // Let the parallel move resolver take care of all of this.
-    HParallelMove parallel_move(GetGraph()->GetAllocator());
-    parallel_move.AddMove(return_loc, trg, type, nullptr);
-    GetMoveResolver()->EmitNativeCode(&parallel_move);
-  }
+  // Let the parallel move resolver take care of all of this.
+  HParallelMove parallel_move(GetGraph()->GetAllocator());
+  parallel_move.AddMove(return_loc, trg, type, nullptr);
+  GetMoveResolver()->EmitNativeCode(&parallel_move);
 }
 
 void LocationsBuilderARMVIXL::VisitClassTableGet(HClassTableGet* instruction) {
@@ -9660,7 +10024,7 @@
       break;
     }
     case BakerReadBarrierKind::kGcRoot:
-    case BakerReadBarrierKind::kUnsafeCas: {
+    case BakerReadBarrierKind::kIntrinsicCas: {
       // Check if the reference needs to be marked and if so (i.e. not null, not marked yet
       // and it does not have a forwarding address), call the correct introspection entrypoint;
       // otherwise return the reference (or the extracted forwarding address).
@@ -9687,15 +10051,19 @@
       __ Cmp(ip, Operand(0xc0000000));
       __ B(hs, &forwarding_address);
       vixl32::Register ep_reg = LoadReadBarrierMarkIntrospectionEntrypoint(assembler);
-      // Adjust the art_quick_read_barrier_mark_introspection address in kBakerCcEntrypointRegister
-      // to one of art_quick_read_barrier_mark_introspection_{gc_roots_{wide,narrow},unsafe_cas}.
-      DCHECK(kind != BakerReadBarrierKind::kUnsafeCas || width == BakerReadBarrierWidth::kWide);
+      // Adjust the art_quick_read_barrier_mark_introspection address
+      // in kBakerCcEntrypointRegister to one of
+      //     art_quick_read_barrier_mark_introspection_{gc_roots_{wide,narrow},intrinsic_cas}.
+      if (kind == BakerReadBarrierKind::kIntrinsicCas) {
+        DCHECK(width == BakerReadBarrierWidth::kWide);
+        DCHECK(!root_reg.IsLow());
+      }
       int32_t entrypoint_offset =
           (kind == BakerReadBarrierKind::kGcRoot)
               ? (width == BakerReadBarrierWidth::kWide)
                   ? BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_WIDE_ENTRYPOINT_OFFSET
                   : BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_NARROW_ENTRYPOINT_OFFSET
-              : BAKER_MARK_INTROSPECTION_UNSAFE_CAS_ENTRYPOINT_OFFSET;
+              : BAKER_MARK_INTROSPECTION_INTRINSIC_CAS_ENTRYPOINT_OFFSET;
       __ Add(ep_reg, ep_reg, Operand(entrypoint_offset));
       __ Mov(ip, root_reg);
       __ Bx(ep_reg);
@@ -9710,10 +10078,8 @@
   }
 
   // For JIT, the slow path is considered part of the compiled method,
-  // so JIT should pass null as `debug_name`. Tests may not have a runtime.
-  DCHECK(Runtime::Current() == nullptr ||
-         !Runtime::Current()->UseJitCompilation() ||
-         debug_name == nullptr);
+  // so JIT should pass null as `debug_name`.
+  DCHECK(!GetCompilerOptions().IsJitCompiler() || debug_name == nullptr);
   if (debug_name != nullptr && GetCompilerOptions().GenerateAnyDebugInfo()) {
     std::ostringstream oss;
     oss << "BakerReadBarrierThunk";
@@ -9741,8 +10107,8 @@
         DCHECK_EQ(kBakerReadBarrierInvalidEncodedReg,
                   BakerReadBarrierSecondRegField::Decode(encoded_data));
         break;
-      case BakerReadBarrierKind::kUnsafeCas:
-        oss << "UnsafeCas_r" << BakerReadBarrierFirstRegField::Decode(encoded_data);
+      case BakerReadBarrierKind::kIntrinsicCas:
+        oss << "IntrinsicCas_r" << BakerReadBarrierFirstRegField::Decode(encoded_data);
         DCHECK_EQ(kBakerReadBarrierInvalidEncodedReg,
                   BakerReadBarrierSecondRegField::Decode(encoded_data));
         DCHECK(BakerReadBarrierWidthField::Decode(encoded_data) == BakerReadBarrierWidth::kWide);
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 48fb082..b797c30 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -18,6 +18,7 @@
 #define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM_VIXL_H_
 
 #include "base/enums.h"
+#include "class_root.h"
 #include "code_generator.h"
 #include "common_arm.h"
 #include "dex/string_reference.h"
@@ -187,6 +188,30 @@
   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorARMVIXL);
 };
 
+class CriticalNativeCallingConventionVisitorARMVIXL : public InvokeDexCallingConventionVisitor {
+ public:
+  explicit CriticalNativeCallingConventionVisitorARMVIXL(bool for_register_allocation)
+      : for_register_allocation_(for_register_allocation) {}
+
+  virtual ~CriticalNativeCallingConventionVisitorARMVIXL() {}
+
+  Location GetNextLocation(DataType::Type type) override;
+  Location GetReturnLocation(DataType::Type type) const override;
+  Location GetMethodLocation() const override;
+
+  size_t GetStackOffset() const { return stack_offset_; }
+
+ private:
+  // Register allocator does not support adjusting frame size, so we cannot provide final locations
+  // of stack arguments for register allocation. We ask the register allocator for any location and
+  // move these arguments to the right place after adjusting the SP when generating the call.
+  const bool for_register_allocation_;
+  size_t gpr_index_ = 0u;
+  size_t stack_offset_ = 0u;
+
+  DISALLOW_COPY_AND_ASSIGN(CriticalNativeCallingConventionVisitorARMVIXL);
+};
+
 class FieldAccessCallingConventionARMVIXL : public FieldAccessCallingConvention {
  public:
   FieldAccessCallingConventionARMVIXL() {}
@@ -318,6 +343,8 @@
   ArmVIXLAssembler* GetAssembler() const { return assembler_; }
   ArmVIXLMacroAssembler* GetVIXLAssembler() { return GetAssembler()->GetVIXLAssembler(); }
 
+  void GenerateAndConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value);
+
  private:
   // Generate code for the given suspend check. If not null, `successor`
   // is the block to branch to if the suspend check is not needed, and after
@@ -328,7 +355,6 @@
   void GenerateBitstringTypeCheckCompare(HTypeCheckInstruction* check,
                                          vixl::aarch32::Register temp,
                                          vixl::aarch32::FlagsUpdate flags_update);
-  void GenerateAndConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value);
   void GenerateOrrConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value);
   void GenerateEorConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value);
   void GenerateAddLongConst(Location out, Location first, uint64_t value);
@@ -450,6 +476,13 @@
     return vixl::aarch32::kSRegSizeInBytes;
   }
 
+  size_t GetSIMDRegisterWidth() const override {
+    // ARM 32-bit backend doesn't support Q registers in vectorizer, only D
+    // registers (due to register allocator restrictions: overlapping s/d/q
+    // registers).
+    return vixl::aarch32::kDRegSizeInBytes;
+  }
+
   HGraphVisitor* GetLocationBuilder() override { return &location_builder_; }
 
   HGraphVisitor* GetInstructionVisitor() override { return &instruction_visitor_; }
@@ -508,7 +541,7 @@
                   vixl::aarch32::Register card,
                   vixl::aarch32::Register object,
                   vixl::aarch32::Register value,
-                  bool can_be_null);
+                  bool value_can_be_null);
 
   void GenerateMemoryBarrier(MemBarrierKind kind);
 
@@ -549,6 +582,7 @@
       const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
       ArtMethod* method) override;
 
+  void LoadMethod(MethodLoadKind load_kind, Location temp, HInvoke* invoke);
   void GenerateStaticOrDirectCall(
       HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
   void GenerateVirtualCall(
@@ -583,7 +617,7 @@
   PcRelativePatchInfo* NewBootImageMethodPatch(MethodReference target_method);
   PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method);
   PcRelativePatchInfo* NewBootImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
-  PcRelativePatchInfo* NewTypeBssEntryPatch(const DexFile& dex_file, dex::TypeIndex type_index);
+  PcRelativePatchInfo* NewTypeBssEntryPatch(HLoadClass* load_class);
   PcRelativePatchInfo* NewBootImageStringPatch(const DexFile& dex_file,
                                                dex::StringIndex string_index);
   PcRelativePatchInfo* NewStringBssEntryPatch(const DexFile& dex_file,
@@ -605,7 +639,9 @@
                                                 Handle<mirror::Class> handle);
 
   void LoadBootImageAddress(vixl::aarch32::Register reg, uint32_t boot_image_reference);
-  void AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke, uint32_t boot_image_offset);
+  void LoadTypeForBootImageIntrinsic(vixl::aarch32::Register reg, TypeReference type_reference);
+  void LoadIntrinsicDeclaringClass(vixl::aarch32::Register reg, HInvoke* invoke);
+  void LoadClassRootForIntrinsic(vixl::aarch32::Register reg, ClassRoot class_root);
 
   void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) override;
   bool NeedsThunkCode(const linker::LinkerPatch& patch) const override;
@@ -625,11 +661,9 @@
                                vixl::aarch32::Register obj,
                                uint32_t offset,
                                ReadBarrierOption read_barrier_option);
-  // Generate ADD for UnsafeCASObject to reconstruct the old value from
-  // `old_value - expected` and mark it with Baker read barrier.
-  void GenerateUnsafeCasOldValueAddWithBakerReadBarrier(vixl::aarch32::Register old_value,
-                                                        vixl::aarch32::Register adjusted_old_value,
-                                                        vixl::aarch32::Register expected);
+  // Generate MOV for an intrinsic CAS to mark the old value with Baker read barrier.
+  void GenerateIntrinsicCasMoveWithBakerReadBarrier(vixl::aarch32::Register marked_old_value,
+                                                    vixl::aarch32::Register old_value);
   // Fast path implementation of ReadBarrier::Barrier for a heap
   // reference field load when Baker's read barriers are used.
   // Overload suitable for Unsafe.getObject/-Volatile() intrinsic.
@@ -644,7 +678,7 @@
                                              Location ref,
                                              vixl::aarch32::Register obj,
                                              uint32_t offset,
-                                             Location temp,
+                                             Location maybe_temp,
                                              bool needs_null_check);
   // Fast path implementation of ReadBarrier::Barrier for a heap
   // reference array load when Baker's read barriers are used.
@@ -677,6 +711,18 @@
   virtual void MaybeGenerateMarkingRegisterCheck(int code,
                                                  Location temp_loc = Location::NoLocation());
 
+  // Create slow path for a read barrier for a heap reference within `instruction`.
+  //
+  // This is a helper function for GenerateReadBarrierSlow() that has the same
+  // arguments. The creation and adding of the slow path is exposed for intrinsics
+  // that cannot use GenerateReadBarrierSlow() from their own slow paths.
+  SlowPathCodeARMVIXL* AddReadBarrierSlowPath(HInstruction* instruction,
+                                              Location out,
+                                              Location ref,
+                                              Location obj,
+                                              uint32_t offset,
+                                              Location index);
+
   // Generate a read barrier for a heap reference within `instruction`
   // using a slow path.
   //
@@ -725,6 +771,9 @@
   // artReadBarrierForRootSlow.
   void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root);
 
+  void IncreaseFrame(size_t adjustment) override;
+  void DecreaseFrame(size_t adjustment) override;
+
   void GenerateNop() override;
 
   void GenerateImplicitNullCheck(HNullCheck* instruction) override;
@@ -763,11 +812,11 @@
   // Encoding of thunk type and data for link-time generated thunks for Baker read barriers.
 
   enum class BakerReadBarrierKind : uint8_t {
-    kField,       // Field get or array get with constant offset (i.e. constant index).
-    kArray,       // Array get with index in register.
-    kGcRoot,      // GC root load.
-    kUnsafeCas,   // UnsafeCASObject intrinsic.
-    kLast = kUnsafeCas
+    kField,         // Field get or array get with constant offset (i.e. constant index).
+    kArray,         // Array get with index in register.
+    kGcRoot,        // GC root load.
+    kIntrinsicCas,  // Unsafe/VarHandle CAS intrinsic.
+    kLast = kIntrinsicCas
   };
 
   enum class BakerReadBarrierWidth : uint8_t {
@@ -834,9 +883,9 @@
            BakerReadBarrierWidthField::Encode(width);
   }
 
-  static uint32_t EncodeBakerReadBarrierUnsafeCasData(uint32_t root_reg) {
+  static uint32_t EncodeBakerReadBarrierIntrinsicCasData(uint32_t root_reg) {
     CheckValidReg(root_reg);
-    return BakerReadBarrierKindField::Encode(BakerReadBarrierKind::kUnsafeCas) |
+    return BakerReadBarrierKindField::Encode(BakerReadBarrierKind::kIntrinsicCas) |
            BakerReadBarrierFirstRegField::Encode(root_reg) |
            BakerReadBarrierSecondRegField::Encode(kBakerReadBarrierInvalidEncodedReg) |
            BakerReadBarrierWidthField::Encode(BakerReadBarrierWidth::kWide);
@@ -846,9 +895,6 @@
                                     uint32_t encoded_data,
                                     /*out*/ std::string* debug_name);
 
-  vixl::aarch32::Register GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke,
-                                                                vixl::aarch32::Register temp);
-
   using Uint32ToLiteralMap = ArenaSafeMap<uint32_t, VIXLUInt32Literal*>;
   using StringToLiteralMap = ArenaSafeMap<StringReference,
                                           VIXLUInt32Literal*,
@@ -892,6 +938,10 @@
   ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
   // PC-relative type patch info for kBssEntry.
   ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
+  // PC-relative public type patch info for kBssEntryPublic.
+  ArenaDeque<PcRelativePatchInfo> public_type_bss_entry_patches_;
+  // PC-relative package type patch info for kBssEntryPackage.
+  ArenaDeque<PcRelativePatchInfo> package_type_bss_entry_patches_;
   // PC-relative String patch info for kBootImageLinkTimePcRelative.
   ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_;
   // PC-relative String patch info for kBssEntry.
diff --git a/compiler/optimizing/code_generator_utils.cc b/compiler/optimizing/code_generator_utils.cc
index dd47a1f..abec264 100644
--- a/compiler/optimizing/code_generator_utils.cc
+++ b/compiler/optimizing/code_generator_utils.cc
@@ -100,4 +100,156 @@
   return !cond_input->IsCondition() || !cond_input->IsEmittedAtUseSite();
 }
 
+// A helper class to group functions analyzing if values are non-negative
+// at the point of use. The class keeps some context used by the functions.
+// The class is not supposed to be used directly or its instances to be kept.
+// The main function using it is HasNonNegativeInputAt.
+// If you want to use the class methods you need to become a friend of the class.
+class UnsignedUseAnalyzer {
+ private:
+  explicit UnsignedUseAnalyzer(ArenaAllocator* allocator)
+      : seen_values_(allocator->Adapter(kArenaAllocCodeGenerator)) {
+  }
+
+  bool IsNonNegativeUse(HInstruction* target_user, HInstruction* value);
+  bool IsComparedValueNonNegativeInBlock(HInstruction* value,
+                                         HCondition* cond,
+                                         HBasicBlock* target_block);
+
+  ArenaSet<HInstruction*> seen_values_;
+
+  friend bool HasNonNegativeInputAt(HInstruction* instr, size_t i);
+};
+
+// Check that the value compared with a non-negavite value is
+// non-negative in the specified basic block.
+bool UnsignedUseAnalyzer::IsComparedValueNonNegativeInBlock(HInstruction* value,
+                                                            HCondition* cond,
+                                                            HBasicBlock* target_block) {
+  DCHECK(cond->HasInput(value));
+
+  // To simplify analysis, we require:
+  // 1. The condition basic block and target_block to be different.
+  // 2. The condition basic block to end with HIf.
+  // 3. HIf to use the condition.
+  if (cond->GetBlock() == target_block ||
+      !cond->GetBlock()->EndsWithIf() ||
+      cond->GetBlock()->GetLastInstruction()->InputAt(0) != cond) {
+    return false;
+  }
+
+  // We need to find a successor basic block of HIf for the case when instr is non-negative.
+  // If the successor dominates target_block, instructions in target_block see a non-negative value.
+  HIf* if_instr = cond->GetBlock()->GetLastInstruction()->AsIf();
+  HBasicBlock* successor = nullptr;
+  switch (cond->GetCondition()) {
+    case kCondGT:
+    case kCondGE: {
+      if (cond->GetLeft() == value) {
+        // The expression is v > A or v >= A.
+        // If A is non-negative, we need the true successor.
+        if (IsNonNegativeUse(cond, cond->GetRight())) {
+          successor = if_instr->IfTrueSuccessor();
+        } else {
+          return false;
+        }
+      } else {
+        DCHECK_EQ(cond->GetRight(), value);
+        // The expression is A > v or A >= v.
+        // If A is non-negative, we need the false successor.
+        if (IsNonNegativeUse(cond, cond->GetLeft())) {
+          successor = if_instr->IfFalseSuccessor();
+        } else {
+          return false;
+        }
+      }
+      break;
+    }
+
+    case kCondLT:
+    case kCondLE: {
+      if (cond->GetLeft() == value) {
+        // The expression is v < A or v <= A.
+        // If A is non-negative, we need the false successor.
+        if (IsNonNegativeUse(cond, cond->GetRight())) {
+          successor = if_instr->IfFalseSuccessor();
+        } else {
+          return false;
+        }
+      } else {
+        DCHECK_EQ(cond->GetRight(), value);
+        // The expression is A < v or A <= v.
+        // If A is non-negative, we need the true successor.
+        if (IsNonNegativeUse(cond, cond->GetLeft())) {
+          successor = if_instr->IfTrueSuccessor();
+        } else {
+          return false;
+        }
+      }
+      break;
+    }
+
+    default:
+      return false;
+  }
+  DCHECK_NE(successor, nullptr);
+
+  return successor->Dominates(target_block);
+}
+
+// Check the value used by target_user is non-negative.
+bool UnsignedUseAnalyzer::IsNonNegativeUse(HInstruction* target_user, HInstruction* value) {
+  DCHECK(target_user->HasInput(value));
+
+  // Prevent infinitive recursion which can happen when the value is an induction variable.
+  if (!seen_values_.insert(value).second) {
+    return false;
+  }
+
+  // Check if the value is always non-negative.
+  if (IsGEZero(value)) {
+    return true;
+  }
+
+  for (const HUseListNode<HInstruction*>& use : value->GetUses()) {
+    HInstruction* user = use.GetUser();
+    if (user == target_user) {
+      continue;
+    }
+
+    // If the value is compared with some non-negative value, this can guarantee the value to be
+    // non-negative at its use.
+    // JFYI: We're not using HTypeConversion to bind the new information because it would
+    // increase the complexity of optimizations: HTypeConversion can create a dependency
+    // which does not exist in the input program, for example:
+    // between two uses, 1st - cmp, 2nd - target_user.
+    if (user->IsCondition()) {
+      // The condition must dominate target_user to guarantee that the value is always checked
+      // before it is used by target_user.
+      if (user->GetBlock()->Dominates(target_user->GetBlock()) &&
+          IsComparedValueNonNegativeInBlock(value, user->AsCondition(), target_user->GetBlock())) {
+        return true;
+      }
+    }
+
+    // TODO The value is non-negative if it is used as an array index before.
+    // TODO The value is non-negative if it is initialized by a positive number and all of its
+    //      modifications keep the value non-negative, for example the division operation.
+  }
+
+  return false;
+}
+
+bool HasNonNegativeInputAt(HInstruction* instr, size_t i) {
+  UnsignedUseAnalyzer analyzer(instr->GetBlock()->GetGraph()->GetAllocator());
+  return analyzer.IsNonNegativeUse(instr, instr->InputAt(i));
+}
+
+bool HasNonNegativeOrMinIntInputAt(HInstruction* instr, size_t i) {
+  HInstruction* input = instr->InputAt(i);
+  return input->IsAbs() ||
+         IsInt64Value(input, DataType::MinValueOfIntegralType(input->GetType())) ||
+         HasNonNegativeInputAt(instr, i);
+}
+
 }  // namespace art
diff --git a/compiler/optimizing/code_generator_utils.h b/compiler/optimizing/code_generator_utils.h
index a6b41c0..64665ad 100644
--- a/compiler/optimizing/code_generator_utils.h
+++ b/compiler/optimizing/code_generator_utils.h
@@ -40,6 +40,12 @@
       : std::abs(value);
 }
 
+// Check whether the i-th operand of instr is non-negative.
+bool HasNonNegativeInputAt(HInstruction* instr, size_t i);
+
+// Check whether the i-th operand of instr is non-negative or the minimum integer value.
+bool HasNonNegativeOrMinIntInputAt(HInstruction* instr, size_t i);
+
 }  // namespace art
 
 #endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_UTILS_H_
diff --git a/compiler/optimizing/code_generator_vector_arm64.cc b/compiler/optimizing/code_generator_vector_arm64.cc
deleted file mode 100644
index df95c88..0000000
--- a/compiler/optimizing/code_generator_vector_arm64.cc
+++ /dev/null
@@ -1,1523 +0,0 @@
-/*
- * Copyright (C) 2017 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 "code_generator_arm64.h"
-
-#include "arch/arm64/instruction_set_features_arm64.h"
-#include "mirror/array-inl.h"
-#include "mirror/string.h"
-
-using namespace vixl::aarch64;  // NOLINT(build/namespaces)
-
-namespace art {
-namespace arm64 {
-
-using helpers::ARM64EncodableConstantOrRegister;
-using helpers::Arm64CanEncodeConstantAsImmediate;
-using helpers::DRegisterFrom;
-using helpers::HeapOperand;
-using helpers::InputRegisterAt;
-using helpers::Int64FromLocation;
-using helpers::OutputRegister;
-using helpers::VRegisterFrom;
-using helpers::WRegisterFrom;
-using helpers::XRegisterFrom;
-
-#define __ GetVIXLAssembler()->
-
-// Build-time switch for Armv8.4-a dot product instructions.
-// TODO: Enable dot product when there is a device to test it on.
-static constexpr bool kArm64EmitDotProdInstructions = false;
-
-// Returns whether dot product instructions should be emitted.
-static bool ShouldEmitDotProductInstructions(const CodeGeneratorARM64* codegen_) {
-  return kArm64EmitDotProdInstructions && codegen_->GetInstructionSetFeatures().HasDotProd();
-}
-
-void LocationsBuilderARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
-  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
-  HInstruction* input = instruction->InputAt(0);
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-      locations->SetInAt(0, ARM64EncodableConstantOrRegister(input, instruction));
-      locations->SetOut(Location::RequiresFpuRegister());
-      break;
-    case DataType::Type::kFloat32:
-    case DataType::Type::kFloat64:
-      if (input->IsConstant() &&
-          Arm64CanEncodeConstantAsImmediate(input->AsConstant(), instruction)) {
-        locations->SetInAt(0, Location::ConstantLocation(input->AsConstant()));
-        locations->SetOut(Location::RequiresFpuRegister());
-      } else {
-        locations->SetInAt(0, Location::RequiresFpuRegister());
-        locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
-      }
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  Location src_loc = locations->InAt(0);
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      if (src_loc.IsConstant()) {
-        __ Movi(dst.V16B(), Int64FromLocation(src_loc));
-      } else {
-        __ Dup(dst.V16B(), InputRegisterAt(instruction, 0));
-      }
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      if (src_loc.IsConstant()) {
-        __ Movi(dst.V8H(), Int64FromLocation(src_loc));
-      } else {
-        __ Dup(dst.V8H(), InputRegisterAt(instruction, 0));
-      }
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      if (src_loc.IsConstant()) {
-        __ Movi(dst.V4S(), Int64FromLocation(src_loc));
-      } else {
-        __ Dup(dst.V4S(), InputRegisterAt(instruction, 0));
-      }
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      if (src_loc.IsConstant()) {
-        __ Movi(dst.V2D(), Int64FromLocation(src_loc));
-      } else {
-        __ Dup(dst.V2D(), XRegisterFrom(src_loc));
-      }
-      break;
-    case DataType::Type::kFloat32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      if (src_loc.IsConstant()) {
-        __ Fmov(dst.V4S(), src_loc.GetConstant()->AsFloatConstant()->GetValue());
-      } else {
-        __ Dup(dst.V4S(), VRegisterFrom(src_loc).V4S(), 0);
-      }
-      break;
-    case DataType::Type::kFloat64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      if (src_loc.IsConstant()) {
-        __ Fmov(dst.V2D(), src_loc.GetConstant()->AsDoubleConstant()->GetValue());
-      } else {
-        __ Dup(dst.V2D(), VRegisterFrom(src_loc).V2D(), 0);
-      }
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
-  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresRegister());
-      break;
-    case DataType::Type::kFloat32:
-    case DataType::Type::kFloat64:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetOut(Location::SameAsFirstInput());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void InstructionCodeGeneratorARM64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister src = VRegisterFrom(locations->InAt(0));
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Umov(OutputRegister(instruction), src.V4S(), 0);
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Umov(OutputRegister(instruction), src.V2D(), 0);
-      break;
-    case DataType::Type::kFloat32:
-    case DataType::Type::kFloat64:
-      DCHECK_LE(2u, instruction->GetVectorLength());
-      DCHECK_LE(instruction->GetVectorLength(), 4u);
-      DCHECK(locations->InAt(0).Equals(locations->Out()));  // no code required
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-// Helper to set up locations for vector unary operations.
-static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
-  LocationSummary* locations = new (allocator) LocationSummary(instruction);
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresFpuRegister(),
-                        instruction->IsVecNot() ? Location::kOutputOverlap
-                                                : Location::kNoOutputOverlap);
-      break;
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-    case DataType::Type::kFloat32:
-    case DataType::Type::kFloat64:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecReduce(HVecReduce* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecReduce(HVecReduce* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister src = VRegisterFrom(locations->InAt(0));
-  VRegister dst = DRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      switch (instruction->GetReductionKind()) {
-        case HVecReduce::kSum:
-          __ Addv(dst.S(), src.V4S());
-          break;
-        case HVecReduce::kMin:
-          __ Sminv(dst.S(), src.V4S());
-          break;
-        case HVecReduce::kMax:
-          __ Smaxv(dst.S(), src.V4S());
-          break;
-      }
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      switch (instruction->GetReductionKind()) {
-        case HVecReduce::kSum:
-          __ Addp(dst.D(), src.V2D());
-          break;
-        default:
-          LOG(FATAL) << "Unsupported SIMD min/max";
-          UNREACHABLE();
-      }
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecCnv(HVecCnv* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecCnv(HVecCnv* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister src = VRegisterFrom(locations->InAt(0));
-  VRegister dst = VRegisterFrom(locations->Out());
-  DataType::Type from = instruction->GetInputType();
-  DataType::Type to = instruction->GetResultType();
-  if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
-    DCHECK_EQ(4u, instruction->GetVectorLength());
-    __ Scvtf(dst.V4S(), src.V4S());
-  } else {
-    LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecNeg(HVecNeg* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecNeg(HVecNeg* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister src = VRegisterFrom(locations->InAt(0));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Neg(dst.V16B(), src.V16B());
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Neg(dst.V8H(), src.V8H());
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Neg(dst.V4S(), src.V4S());
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Neg(dst.V2D(), src.V2D());
-      break;
-    case DataType::Type::kFloat32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Fneg(dst.V4S(), src.V4S());
-      break;
-    case DataType::Type::kFloat64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Fneg(dst.V2D(), src.V2D());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecAbs(HVecAbs* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecAbs(HVecAbs* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister src = VRegisterFrom(locations->InAt(0));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Abs(dst.V16B(), src.V16B());
-      break;
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Abs(dst.V8H(), src.V8H());
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Abs(dst.V4S(), src.V4S());
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Abs(dst.V2D(), src.V2D());
-      break;
-    case DataType::Type::kFloat32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Fabs(dst.V4S(), src.V4S());
-      break;
-    case DataType::Type::kFloat64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Fabs(dst.V2D(), src.V2D());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecNot(HVecNot* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister src = VRegisterFrom(locations->InAt(0));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:  // special case boolean-not
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Movi(dst.V16B(), 1);
-      __ Eor(dst.V16B(), dst.V16B(), src.V16B());
-      break;
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-      __ Not(dst.V16B(), src.V16B());  // lanes do not matter
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-// Helper to set up locations for vector binary operations.
-static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
-  LocationSummary* locations = new (allocator) LocationSummary(instruction);
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-    case DataType::Type::kFloat32:
-    case DataType::Type::kFloat64:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetInAt(1, Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecAdd(HVecAdd* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecAdd(HVecAdd* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Add(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Add(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Add(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Add(dst.V2D(), lhs.V2D(), rhs.V2D());
-      break;
-    case DataType::Type::kFloat32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Fadd(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kFloat64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Fadd(dst.V2D(), lhs.V2D(), rhs.V2D());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Uqadd(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Sqadd(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kUint16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Uqadd(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Sqadd(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      instruction->IsRounded()
-          ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
-          : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      instruction->IsRounded()
-          ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
-          : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kUint16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      instruction->IsRounded()
-          ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
-          : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      instruction->IsRounded()
-          ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
-          : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecSub(HVecSub* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecSub(HVecSub* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Sub(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Sub(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Sub(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Sub(dst.V2D(), lhs.V2D(), rhs.V2D());
-      break;
-    case DataType::Type::kFloat32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kFloat64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Fsub(dst.V2D(), lhs.V2D(), rhs.V2D());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecSaturationSub(HVecSaturationSub* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecSaturationSub(HVecSaturationSub* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Uqsub(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Sqsub(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kUint16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Uqsub(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Sqsub(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecMul(HVecMul* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecMul(HVecMul* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kFloat32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kFloat64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Fmul(dst.V2D(), lhs.V2D(), rhs.V2D());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecDiv(HVecDiv* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecDiv(HVecDiv* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kFloat32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kFloat64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Fdiv(dst.V2D(), lhs.V2D(), rhs.V2D());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecMin(HVecMin* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kUint16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    case DataType::Type::kUint32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Umin(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Smin(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kFloat32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Fmin(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kFloat64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Fmin(dst.V2D(), lhs.V2D(), rhs.V2D());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecMax(HVecMax* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
-      break;
-    case DataType::Type::kUint16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
-      break;
-    case DataType::Type::kUint32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Umax(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Smax(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kFloat32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Fmax(dst.V4S(), lhs.V4S(), rhs.V4S());
-      break;
-    case DataType::Type::kFloat64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Fmax(dst.V2D(), lhs.V2D(), rhs.V2D());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
-  // TODO: Allow constants supported by BIC (vector, immediate).
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-    case DataType::Type::kFloat32:
-    case DataType::Type::kFloat64:
-      __ And(dst.V16B(), lhs.V16B(), rhs.V16B());  // lanes do not matter
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecAndNot(HVecAndNot* instruction) {
-  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
-}
-
-void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
-  // TODO: Use BIC (vector, register).
-  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
-}
-
-void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-    case DataType::Type::kFloat32:
-    case DataType::Type::kFloat64:
-      __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B());  // lanes do not matter
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
-  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister rhs = VRegisterFrom(locations->InAt(1));
-  VRegister dst = VRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-    case DataType::Type::kFloat32:
-    case DataType::Type::kFloat64:
-      __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B());  // lanes do not matter
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-// Helper to set up locations for vector shift operations.
-static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
-  LocationSummary* locations = new (allocator) LocationSummary(instruction);
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
-      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
-  CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister dst = VRegisterFrom(locations->Out());
-  int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Shl(dst.V16B(), lhs.V16B(), value);
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Shl(dst.V8H(), lhs.V8H(), value);
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Shl(dst.V4S(), lhs.V4S(), value);
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Shl(dst.V2D(), lhs.V2D(), value);
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
-  CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister dst = VRegisterFrom(locations->Out());
-  int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Sshr(dst.V16B(), lhs.V16B(), value);
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Sshr(dst.V8H(), lhs.V8H(), value);
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Sshr(dst.V4S(), lhs.V4S(), value);
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Sshr(dst.V2D(), lhs.V2D(), value);
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
-  CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister lhs = VRegisterFrom(locations->InAt(0));
-  VRegister dst = VRegisterFrom(locations->Out());
-  int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Ushr(dst.V16B(), lhs.V16B(), value);
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Ushr(dst.V8H(), lhs.V8H(), value);
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Ushr(dst.V4S(), lhs.V4S(), value);
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Ushr(dst.V2D(), lhs.V2D(), value);
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
-
-  DCHECK_EQ(1u, instruction->InputCount());  // only one input currently implemented
-
-  HInstruction* input = instruction->InputAt(0);
-  bool is_zero = IsZeroBitPattern(input);
-
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
-      break;
-    case DataType::Type::kFloat32:
-    case DataType::Type::kFloat64:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister dst = VRegisterFrom(locations->Out());
-
-  DCHECK_EQ(1u, instruction->InputCount());  // only one input currently implemented
-
-  // Zero out all other elements first.
-  __ Movi(dst.V16B(), 0);
-
-  // Shorthand for any type of zero.
-  if (IsZeroBitPattern(instruction->InputAt(0))) {
-    return;
-  }
-
-  // Set required elements.
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Mov(dst.V16B(), 0, InputRegisterAt(instruction, 0));
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Mov(dst.V8H(), 0, InputRegisterAt(instruction, 0));
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Mov(dst.V4S(), 0, InputRegisterAt(instruction, 0));
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Mov(dst.V2D(), 0, InputRegisterAt(instruction, 0));
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-// Helper to set up locations for vector accumulations.
-static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
-  LocationSummary* locations = new (allocator) LocationSummary(instruction);
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetInAt(1, Location::RequiresFpuRegister());
-      locations->SetInAt(2, Location::RequiresFpuRegister());
-      locations->SetOut(Location::SameAsFirstInput());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
-  CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
-}
-
-// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
-// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
-// However vector MultiplyAccumulate instruction is not affected.
-void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister acc = VRegisterFrom(locations->InAt(0));
-  VRegister left = VRegisterFrom(locations->InAt(1));
-  VRegister right = VRegisterFrom(locations->InAt(2));
-
-  DCHECK(locations->InAt(0).Equals(locations->Out()));
-
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      if (instruction->GetOpKind() == HInstruction::kAdd) {
-        __ Mla(acc.V16B(), left.V16B(), right.V16B());
-      } else {
-        __ Mls(acc.V16B(), left.V16B(), right.V16B());
-      }
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      if (instruction->GetOpKind() == HInstruction::kAdd) {
-        __ Mla(acc.V8H(), left.V8H(), right.V8H());
-      } else {
-        __ Mls(acc.V8H(), left.V8H(), right.V8H());
-      }
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      if (instruction->GetOpKind() == HInstruction::kAdd) {
-        __ Mla(acc.V4S(), left.V4S(), right.V4S());
-      } else {
-        __ Mls(acc.V4S(), left.V4S(), right.V4S());
-      }
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
-  CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
-  // Some conversions require temporary registers.
-  LocationSummary* locations = instruction->GetLocations();
-  HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
-  HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
-  DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
-            HVecOperation::ToSignedType(b->GetPackedType()));
-  switch (a->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      switch (instruction->GetPackedType()) {
-        case DataType::Type::kInt64:
-          locations->AddTemp(Location::RequiresFpuRegister());
-          locations->AddTemp(Location::RequiresFpuRegister());
-          FALLTHROUGH_INTENDED;
-        case DataType::Type::kInt32:
-          locations->AddTemp(Location::RequiresFpuRegister());
-          locations->AddTemp(Location::RequiresFpuRegister());
-          break;
-        default:
-          break;
-      }
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      if (instruction->GetPackedType() == DataType::Type::kInt64) {
-        locations->AddTemp(Location::RequiresFpuRegister());
-        locations->AddTemp(Location::RequiresFpuRegister());
-      }
-      break;
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-      if (instruction->GetPackedType() == a->GetPackedType()) {
-        locations->AddTemp(Location::RequiresFpuRegister());
-      }
-      break;
-    default:
-      break;
-  }
-}
-
-void InstructionCodeGeneratorARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister acc = VRegisterFrom(locations->InAt(0));
-  VRegister left = VRegisterFrom(locations->InAt(1));
-  VRegister right = VRegisterFrom(locations->InAt(2));
-
-  DCHECK(locations->InAt(0).Equals(locations->Out()));
-
-  // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
-  HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
-  HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
-  DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
-            HVecOperation::ToSignedType(b->GetPackedType()));
-  switch (a->GetPackedType()) {
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-      DCHECK_EQ(16u, a->GetVectorLength());
-      switch (instruction->GetPackedType()) {
-        case DataType::Type::kInt16:
-          DCHECK_EQ(8u, instruction->GetVectorLength());
-          __ Sabal(acc.V8H(), left.V8B(), right.V8B());
-          __ Sabal2(acc.V8H(), left.V16B(), right.V16B());
-          break;
-        case DataType::Type::kInt32: {
-          DCHECK_EQ(4u, instruction->GetVectorLength());
-          VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
-          VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
-          __ Sxtl(tmp1.V8H(), left.V8B());
-          __ Sxtl(tmp2.V8H(), right.V8B());
-          __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
-          __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
-          __ Sxtl2(tmp1.V8H(), left.V16B());
-          __ Sxtl2(tmp2.V8H(), right.V16B());
-          __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
-          __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
-          break;
-        }
-        case DataType::Type::kInt64: {
-          DCHECK_EQ(2u, instruction->GetVectorLength());
-          VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
-          VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
-          VRegister tmp3 = VRegisterFrom(locations->GetTemp(2));
-          VRegister tmp4 = VRegisterFrom(locations->GetTemp(3));
-          __ Sxtl(tmp1.V8H(), left.V8B());
-          __ Sxtl(tmp2.V8H(), right.V8B());
-          __ Sxtl(tmp3.V4S(), tmp1.V4H());
-          __ Sxtl(tmp4.V4S(), tmp2.V4H());
-          __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
-          __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
-          __ Sxtl2(tmp3.V4S(), tmp1.V8H());
-          __ Sxtl2(tmp4.V4S(), tmp2.V8H());
-          __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
-          __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
-          __ Sxtl2(tmp1.V8H(), left.V16B());
-          __ Sxtl2(tmp2.V8H(), right.V16B());
-          __ Sxtl(tmp3.V4S(), tmp1.V4H());
-          __ Sxtl(tmp4.V4S(), tmp2.V4H());
-          __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
-          __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
-          __ Sxtl2(tmp3.V4S(), tmp1.V8H());
-          __ Sxtl2(tmp4.V4S(), tmp2.V8H());
-          __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
-          __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
-          break;
-        }
-        default:
-          LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-          UNREACHABLE();
-      }
-      break;
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-      DCHECK_EQ(8u, a->GetVectorLength());
-      switch (instruction->GetPackedType()) {
-        case DataType::Type::kInt32:
-          DCHECK_EQ(4u, instruction->GetVectorLength());
-          __ Sabal(acc.V4S(), left.V4H(), right.V4H());
-          __ Sabal2(acc.V4S(), left.V8H(), right.V8H());
-          break;
-        case DataType::Type::kInt64: {
-          DCHECK_EQ(2u, instruction->GetVectorLength());
-          VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
-          VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
-          __ Sxtl(tmp1.V4S(), left.V4H());
-          __ Sxtl(tmp2.V4S(), right.V4H());
-          __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
-          __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
-          __ Sxtl2(tmp1.V4S(), left.V8H());
-          __ Sxtl2(tmp2.V4S(), right.V8H());
-          __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
-          __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
-          break;
-        }
-        default:
-          LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-          UNREACHABLE();
-      }
-      break;
-    case DataType::Type::kInt32:
-      DCHECK_EQ(4u, a->GetVectorLength());
-      switch (instruction->GetPackedType()) {
-        case DataType::Type::kInt32: {
-          DCHECK_EQ(4u, instruction->GetVectorLength());
-          VRegister tmp = VRegisterFrom(locations->GetTemp(0));
-          __ Sub(tmp.V4S(), left.V4S(), right.V4S());
-          __ Abs(tmp.V4S(), tmp.V4S());
-          __ Add(acc.V4S(), acc.V4S(), tmp.V4S());
-          break;
-        }
-        case DataType::Type::kInt64:
-          DCHECK_EQ(2u, instruction->GetVectorLength());
-          __ Sabal(acc.V2D(), left.V2S(), right.V2S());
-          __ Sabal2(acc.V2D(), left.V4S(), right.V4S());
-          break;
-        default:
-          LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-          UNREACHABLE();
-      }
-      break;
-    case DataType::Type::kInt64:
-      DCHECK_EQ(2u, a->GetVectorLength());
-      switch (instruction->GetPackedType()) {
-        case DataType::Type::kInt64: {
-          DCHECK_EQ(2u, instruction->GetVectorLength());
-          VRegister tmp = VRegisterFrom(locations->GetTemp(0));
-          __ Sub(tmp.V2D(), left.V2D(), right.V2D());
-          __ Abs(tmp.V2D(), tmp.V2D());
-          __ Add(acc.V2D(), acc.V2D(), tmp.V2D());
-          break;
-        }
-        default:
-          LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-          UNREACHABLE();
-      }
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecDotProd(HVecDotProd* instruction) {
-  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
-  DCHECK(instruction->GetPackedType() == DataType::Type::kInt32);
-  locations->SetInAt(0, Location::RequiresFpuRegister());
-  locations->SetInAt(1, Location::RequiresFpuRegister());
-  locations->SetInAt(2, Location::RequiresFpuRegister());
-  locations->SetOut(Location::SameAsFirstInput());
-
-  // For Int8 and Uint8 general case we need a temp register.
-  if ((DataType::Size(instruction->InputAt(1)->AsVecOperation()->GetPackedType()) == 1) &&
-      !ShouldEmitDotProductInstructions(codegen_)) {
-    locations->AddTemp(Location::RequiresFpuRegister());
-  }
-}
-
-void InstructionCodeGeneratorARM64::VisitVecDotProd(HVecDotProd* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  DCHECK(locations->InAt(0).Equals(locations->Out()));
-  VRegister acc = VRegisterFrom(locations->InAt(0));
-  VRegister left = VRegisterFrom(locations->InAt(1));
-  VRegister right = VRegisterFrom(locations->InAt(2));
-  HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
-  HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
-  DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
-            HVecOperation::ToSignedType(b->GetPackedType()));
-  DCHECK_EQ(instruction->GetPackedType(), DataType::Type::kInt32);
-  DCHECK_EQ(4u, instruction->GetVectorLength());
-
-  size_t inputs_data_size = DataType::Size(a->GetPackedType());
-  switch (inputs_data_size) {
-    case 1u: {
-      DCHECK_EQ(16u, a->GetVectorLength());
-      if (instruction->IsZeroExtending()) {
-        if (ShouldEmitDotProductInstructions(codegen_)) {
-          __ Udot(acc.V4S(), left.V16B(), right.V16B());
-        } else {
-          VRegister tmp = VRegisterFrom(locations->GetTemp(0));
-          __ Umull(tmp.V8H(), left.V8B(), right.V8B());
-          __ Uaddw(acc.V4S(), acc.V4S(), tmp.V4H());
-          __ Uaddw2(acc.V4S(), acc.V4S(), tmp.V8H());
-
-          __ Umull2(tmp.V8H(), left.V16B(), right.V16B());
-          __ Uaddw(acc.V4S(), acc.V4S(), tmp.V4H());
-          __ Uaddw2(acc.V4S(), acc.V4S(), tmp.V8H());
-        }
-      } else {
-        if (ShouldEmitDotProductInstructions(codegen_)) {
-          __ Sdot(acc.V4S(), left.V16B(), right.V16B());
-        } else {
-          VRegister tmp = VRegisterFrom(locations->GetTemp(0));
-          __ Smull(tmp.V8H(), left.V8B(), right.V8B());
-          __ Saddw(acc.V4S(), acc.V4S(), tmp.V4H());
-          __ Saddw2(acc.V4S(), acc.V4S(), tmp.V8H());
-
-          __ Smull2(tmp.V8H(), left.V16B(), right.V16B());
-          __ Saddw(acc.V4S(), acc.V4S(), tmp.V4H());
-          __ Saddw2(acc.V4S(), acc.V4S(), tmp.V8H());
-        }
-      }
-      break;
-    }
-    case 2u:
-      DCHECK_EQ(8u, a->GetVectorLength());
-      if (instruction->IsZeroExtending()) {
-        __ Umlal(acc.V4S(), left.V4H(), right.V4H());
-        __ Umlal2(acc.V4S(), left.V8H(), right.V8H());
-      } else {
-        __ Smlal(acc.V4S(), left.V4H(), right.V4H());
-        __ Smlal2(acc.V4S(), left.V8H(), right.V8H());
-      }
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type size: " << inputs_data_size;
-  }
-}
-
-// Helper to set up locations for vector memory operations.
-static void CreateVecMemLocations(ArenaAllocator* allocator,
-                                  HVecMemoryOperation* instruction,
-                                  bool is_load) {
-  LocationSummary* locations = new (allocator) LocationSummary(instruction);
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-    case DataType::Type::kFloat32:
-    case DataType::Type::kFloat64:
-      locations->SetInAt(0, Location::RequiresRegister());
-      locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
-      if (is_load) {
-        locations->SetOut(Location::RequiresFpuRegister());
-      } else {
-        locations->SetInAt(2, Location::RequiresFpuRegister());
-      }
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-// Helper to set up locations for vector memory operations. Returns the memory operand and,
-// if used, sets the output parameter scratch to a temporary register used in this operand,
-// so that the client can release it right after the memory operand use.
-MemOperand InstructionCodeGeneratorARM64::VecAddress(
-    HVecMemoryOperation* instruction,
-    UseScratchRegisterScope* temps_scope,
-    size_t size,
-    bool is_string_char_at,
-    /*out*/ Register* scratch) {
-  LocationSummary* locations = instruction->GetLocations();
-  Register base = InputRegisterAt(instruction, 0);
-
-  if (instruction->InputAt(1)->IsIntermediateAddressIndex()) {
-    DCHECK(!is_string_char_at);
-    return MemOperand(base.X(), InputRegisterAt(instruction, 1).X());
-  }
-
-  Location index = locations->InAt(1);
-  uint32_t offset = is_string_char_at
-      ? mirror::String::ValueOffset().Uint32Value()
-      : mirror::Array::DataOffset(size).Uint32Value();
-  size_t shift = ComponentSizeShiftWidth(size);
-
-  // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
-  DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
-
-  if (index.IsConstant()) {
-    offset += Int64FromLocation(index) << shift;
-    return HeapOperand(base, offset);
-  } else {
-    *scratch = temps_scope->AcquireSameSizeAs(base);
-    __ Add(*scratch, base, Operand(WRegisterFrom(index), LSL, shift));
-    return HeapOperand(*scratch, offset);
-  }
-}
-
-void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
-  CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  size_t size = DataType::Size(instruction->GetPackedType());
-  VRegister reg = VRegisterFrom(locations->Out());
-  UseScratchRegisterScope temps(GetVIXLAssembler());
-  Register scratch;
-
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kInt16:  // (short) s.charAt(.) can yield HVecLoad/Int16/StringCharAt.
-    case DataType::Type::kUint16:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      // Special handling of compressed/uncompressed string load.
-      if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
-        vixl::aarch64::Label uncompressed_load, done;
-        // Test compression bit.
-        static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
-                      "Expecting 0=compressed, 1=uncompressed");
-        uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
-        Register length = temps.AcquireW();
-        __ Ldr(length, HeapOperand(InputRegisterAt(instruction, 0), count_offset));
-        __ Tbnz(length.W(), 0, &uncompressed_load);
-        temps.Release(length);  // no longer needed
-        // Zero extend 8 compressed bytes into 8 chars.
-        __ Ldr(DRegisterFrom(locations->Out()).V8B(),
-               VecAddress(instruction, &temps, 1, /*is_string_char_at*/ true, &scratch));
-        __ Uxtl(reg.V8H(), reg.V8B());
-        __ B(&done);
-        if (scratch.IsValid()) {
-          temps.Release(scratch);  // if used, no longer needed
-        }
-        // Load 8 direct uncompressed chars.
-        __ Bind(&uncompressed_load);
-        __ Ldr(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ true, &scratch));
-        __ Bind(&done);
-        return;
-      }
-      FALLTHROUGH_INTENDED;
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kInt32:
-    case DataType::Type::kFloat32:
-    case DataType::Type::kInt64:
-    case DataType::Type::kFloat64:
-      DCHECK_LE(2u, instruction->GetVectorLength());
-      DCHECK_LE(instruction->GetVectorLength(), 16u);
-      __ Ldr(reg, VecAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch));
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
-  CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  size_t size = DataType::Size(instruction->GetPackedType());
-  VRegister reg = VRegisterFrom(locations->InAt(2));
-  UseScratchRegisterScope temps(GetVIXLAssembler());
-  Register scratch;
-
-  switch (instruction->GetPackedType()) {
-    case DataType::Type::kBool:
-    case DataType::Type::kUint8:
-    case DataType::Type::kInt8:
-    case DataType::Type::kUint16:
-    case DataType::Type::kInt16:
-    case DataType::Type::kInt32:
-    case DataType::Type::kFloat32:
-    case DataType::Type::kInt64:
-    case DataType::Type::kFloat64:
-      DCHECK_LE(2u, instruction->GetVectorLength());
-      DCHECK_LE(instruction->GetVectorLength(), 16u);
-      __ Str(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
-      UNREACHABLE();
-  }
-}
-
-#undef __
-
-}  // namespace arm64
-}  // namespace art
diff --git a/compiler/optimizing/code_generator_vector_arm64_neon.cc b/compiler/optimizing/code_generator_vector_arm64_neon.cc
new file mode 100644
index 0000000..0fe9898
--- /dev/null
+++ b/compiler/optimizing/code_generator_vector_arm64_neon.cc
@@ -0,0 +1,1655 @@
+/*
+ * Copyright (C) 2017 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 "code_generator_arm64.h"
+
+#include "arch/arm64/instruction_set_features_arm64.h"
+#include "base/bit_utils_iterator.h"
+#include "mirror/array-inl.h"
+#include "mirror/string.h"
+
+using namespace vixl::aarch64;  // NOLINT(build/namespaces)
+
+namespace art {
+namespace arm64 {
+
+using helpers::DRegisterFrom;
+using helpers::HeapOperand;
+using helpers::InputRegisterAt;
+using helpers::Int64FromLocation;
+using helpers::LocationFrom;
+using helpers::OutputRegister;
+using helpers::QRegisterFrom;
+using helpers::StackOperandFrom;
+using helpers::VRegisterFrom;
+using helpers::XRegisterFrom;
+
+#define __ GetVIXLAssembler()->
+
+// Returns whether the value of the constant can be directly encoded into the instruction as
+// immediate.
+inline bool NEONCanEncodeConstantAsImmediate(HConstant* constant, HInstruction* instr) {
+  // TODO: Improve this when IsSIMDConstantEncodable method is implemented in VIXL.
+  if (instr->IsVecReplicateScalar()) {
+    if (constant->IsLongConstant()) {
+      return false;
+    } else if (constant->IsFloatConstant()) {
+      return vixl::aarch64::Assembler::IsImmFP32(constant->AsFloatConstant()->GetValue());
+    } else if (constant->IsDoubleConstant()) {
+      return vixl::aarch64::Assembler::IsImmFP64(constant->AsDoubleConstant()->GetValue());
+    }
+    int64_t value = CodeGenerator::GetInt64ValueOf(constant);
+    return IsUint<8>(value);
+  }
+  return false;
+}
+
+// Returns
+//  - constant location - if 'constant' is an actual constant and its value can be
+//    encoded into the instruction.
+//  - register location otherwise.
+inline Location NEONEncodableConstantOrRegister(HInstruction* constant,
+                                                HInstruction* instr) {
+  if (constant->IsConstant()
+      && NEONCanEncodeConstantAsImmediate(constant->AsConstant(), instr)) {
+    return Location::ConstantLocation(constant->AsConstant());
+  }
+
+  return Location::RequiresRegister();
+}
+
+// Returns whether dot product instructions should be emitted.
+static bool ShouldEmitDotProductInstructions(const CodeGeneratorARM64* codegen_) {
+  return codegen_->GetInstructionSetFeatures().HasDotProd();
+}
+
+void LocationsBuilderARM64Neon::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+  HInstruction* input = instruction->InputAt(0);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      locations->SetInAt(0, NEONEncodableConstantOrRegister(input, instruction));
+      locations->SetOut(Location::RequiresFpuRegister());
+      break;
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      if (input->IsConstant() &&
+          NEONCanEncodeConstantAsImmediate(input->AsConstant(), instruction)) {
+        locations->SetInAt(0, Location::ConstantLocation(input->AsConstant()));
+        locations->SetOut(Location::RequiresFpuRegister());
+      } else {
+        locations->SetInAt(0, Location::RequiresFpuRegister());
+        locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  Location src_loc = locations->InAt(0);
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      if (src_loc.IsConstant()) {
+        __ Movi(dst.V16B(), Int64FromLocation(src_loc));
+      } else {
+        __ Dup(dst.V16B(), InputRegisterAt(instruction, 0));
+      }
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      if (src_loc.IsConstant()) {
+        __ Movi(dst.V8H(), Int64FromLocation(src_loc));
+      } else {
+        __ Dup(dst.V8H(), InputRegisterAt(instruction, 0));
+      }
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      if (src_loc.IsConstant()) {
+        __ Movi(dst.V4S(), Int64FromLocation(src_loc));
+      } else {
+        __ Dup(dst.V4S(), InputRegisterAt(instruction, 0));
+      }
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      if (src_loc.IsConstant()) {
+        __ Movi(dst.V2D(), Int64FromLocation(src_loc));
+      } else {
+        __ Dup(dst.V2D(), XRegisterFrom(src_loc));
+      }
+      break;
+    case DataType::Type::kFloat32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      if (src_loc.IsConstant()) {
+        __ Fmov(dst.V4S(), src_loc.GetConstant()->AsFloatConstant()->GetValue());
+      } else {
+        __ Dup(dst.V4S(), VRegisterFrom(src_loc).V4S(), 0);
+      }
+      break;
+    case DataType::Type::kFloat64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      if (src_loc.IsConstant()) {
+        __ Fmov(dst.V2D(), src_loc.GetConstant()->AsDoubleConstant()->GetValue());
+      } else {
+        __ Dup(dst.V2D(), VRegisterFrom(src_loc).V2D(), 0);
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecExtractScalar(HVecExtractScalar* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresRegister());
+      break;
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecExtractScalar(HVecExtractScalar* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister src = VRegisterFrom(locations->InAt(0));
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Umov(OutputRegister(instruction), src.V4S(), 0);
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Umov(OutputRegister(instruction), src.V2D(), 0);
+      break;
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      DCHECK_LE(2u, instruction->GetVectorLength());
+      DCHECK_LE(instruction->GetVectorLength(), 4u);
+      DCHECK(locations->InAt(0).Equals(locations->Out()));  // no code required
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+// Helper to set up locations for vector unary operations.
+static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
+  LocationSummary* locations = new (allocator) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister(),
+                        instruction->IsVecNot() ? Location::kOutputOverlap
+                                                : Location::kNoOutputOverlap);
+      break;
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecReduce(HVecReduce* instruction) {
+  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecReduce(HVecReduce* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister src = VRegisterFrom(locations->InAt(0));
+  VRegister dst = DRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      switch (instruction->GetReductionKind()) {
+        case HVecReduce::kSum:
+          __ Addv(dst.S(), src.V4S());
+          break;
+        case HVecReduce::kMin:
+          __ Sminv(dst.S(), src.V4S());
+          break;
+        case HVecReduce::kMax:
+          __ Smaxv(dst.S(), src.V4S());
+          break;
+      }
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      switch (instruction->GetReductionKind()) {
+        case HVecReduce::kSum:
+          __ Addp(dst.D(), src.V2D());
+          break;
+        default:
+          LOG(FATAL) << "Unsupported SIMD min/max";
+          UNREACHABLE();
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecCnv(HVecCnv* instruction) {
+  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecCnv(HVecCnv* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister src = VRegisterFrom(locations->InAt(0));
+  VRegister dst = VRegisterFrom(locations->Out());
+  DataType::Type from = instruction->GetInputType();
+  DataType::Type to = instruction->GetResultType();
+  if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
+    DCHECK_EQ(4u, instruction->GetVectorLength());
+    __ Scvtf(dst.V4S(), src.V4S());
+  } else {
+    LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecNeg(HVecNeg* instruction) {
+  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecNeg(HVecNeg* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister src = VRegisterFrom(locations->InAt(0));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Neg(dst.V16B(), src.V16B());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Neg(dst.V8H(), src.V8H());
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Neg(dst.V4S(), src.V4S());
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Neg(dst.V2D(), src.V2D());
+      break;
+    case DataType::Type::kFloat32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Fneg(dst.V4S(), src.V4S());
+      break;
+    case DataType::Type::kFloat64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Fneg(dst.V2D(), src.V2D());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecAbs(HVecAbs* instruction) {
+  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecAbs(HVecAbs* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister src = VRegisterFrom(locations->InAt(0));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Abs(dst.V16B(), src.V16B());
+      break;
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Abs(dst.V8H(), src.V8H());
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Abs(dst.V4S(), src.V4S());
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Abs(dst.V2D(), src.V2D());
+      break;
+    case DataType::Type::kFloat32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Fabs(dst.V4S(), src.V4S());
+      break;
+    case DataType::Type::kFloat64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Fabs(dst.V2D(), src.V2D());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecNot(HVecNot* instruction) {
+  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecNot(HVecNot* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister src = VRegisterFrom(locations->InAt(0));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:  // special case boolean-not
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Movi(dst.V16B(), 1);
+      __ Eor(dst.V16B(), dst.V16B(), src.V16B());
+      break;
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      __ Not(dst.V16B(), src.V16B());  // lanes do not matter
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+// Helper to set up locations for vector binary operations.
+static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
+  LocationSummary* locations = new (allocator) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetInAt(1, Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecAdd(HVecAdd* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecAdd(HVecAdd* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Add(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Add(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Add(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Add(dst.V2D(), lhs.V2D(), rhs.V2D());
+      break;
+    case DataType::Type::kFloat32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Fadd(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kFloat64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Fadd(dst.V2D(), lhs.V2D(), rhs.V2D());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Uqadd(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Sqadd(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kUint16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Uqadd(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Sqadd(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      instruction->IsRounded()
+          ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
+          : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      instruction->IsRounded()
+          ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
+          : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kUint16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      instruction->IsRounded()
+          ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
+          : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      instruction->IsRounded()
+          ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
+          : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecSub(HVecSub* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecSub(HVecSub* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Sub(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Sub(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Sub(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Sub(dst.V2D(), lhs.V2D(), rhs.V2D());
+      break;
+    case DataType::Type::kFloat32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kFloat64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Fsub(dst.V2D(), lhs.V2D(), rhs.V2D());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecSaturationSub(HVecSaturationSub* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecSaturationSub(HVecSaturationSub* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Uqsub(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Sqsub(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kUint16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Uqsub(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Sqsub(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecMul(HVecMul* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecMul(HVecMul* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kFloat32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kFloat64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Fmul(dst.V2D(), lhs.V2D(), rhs.V2D());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecDiv(HVecDiv* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecDiv(HVecDiv* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kFloat32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kFloat64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Fdiv(dst.V2D(), lhs.V2D(), rhs.V2D());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecMin(HVecMin* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecMin(HVecMin* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kUint16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    case DataType::Type::kUint32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Umin(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Smin(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kFloat32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Fmin(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kFloat64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Fmin(dst.V2D(), lhs.V2D(), rhs.V2D());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecMax(HVecMax* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecMax(HVecMax* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
+      break;
+    case DataType::Type::kUint16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
+      break;
+    case DataType::Type::kUint32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Umax(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Smax(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kFloat32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Fmax(dst.V4S(), lhs.V4S(), rhs.V4S());
+      break;
+    case DataType::Type::kFloat64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Fmax(dst.V2D(), lhs.V2D(), rhs.V2D());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecAnd(HVecAnd* instruction) {
+  // TODO: Allow constants supported by BIC (vector, immediate).
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecAnd(HVecAnd* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      __ And(dst.V16B(), lhs.V16B(), rhs.V16B());  // lanes do not matter
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecAndNot(HVecAndNot* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecAndNot(HVecAndNot* instruction) {
+  // TODO: Use BIC (vector, register).
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+}
+
+void LocationsBuilderARM64Neon::VisitVecOr(HVecOr* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecOr(HVecOr* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B());  // lanes do not matter
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecXor(HVecXor* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecXor(HVecXor* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister rhs = VRegisterFrom(locations->InAt(1));
+  VRegister dst = VRegisterFrom(locations->Out());
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B());  // lanes do not matter
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+// Helper to set up locations for vector shift operations.
+static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
+  LocationSummary* locations = new (allocator) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
+      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecShl(HVecShl* instruction) {
+  CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecShl(HVecShl* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister dst = VRegisterFrom(locations->Out());
+  int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Shl(dst.V16B(), lhs.V16B(), value);
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Shl(dst.V8H(), lhs.V8H(), value);
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Shl(dst.V4S(), lhs.V4S(), value);
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Shl(dst.V2D(), lhs.V2D(), value);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecShr(HVecShr* instruction) {
+  CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecShr(HVecShr* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister dst = VRegisterFrom(locations->Out());
+  int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Sshr(dst.V16B(), lhs.V16B(), value);
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Sshr(dst.V8H(), lhs.V8H(), value);
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Sshr(dst.V4S(), lhs.V4S(), value);
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Sshr(dst.V2D(), lhs.V2D(), value);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecUShr(HVecUShr* instruction) {
+  CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecUShr(HVecUShr* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister lhs = VRegisterFrom(locations->InAt(0));
+  VRegister dst = VRegisterFrom(locations->Out());
+  int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Ushr(dst.V16B(), lhs.V16B(), value);
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Ushr(dst.V8H(), lhs.V8H(), value);
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Ushr(dst.V4S(), lhs.V4S(), value);
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Ushr(dst.V2D(), lhs.V2D(), value);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+
+  DCHECK_EQ(1u, instruction->InputCount());  // only one input currently implemented
+
+  HInstruction* input = instruction->InputAt(0);
+  bool is_zero = IsZeroBitPattern(input);
+
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
+                                    : Location::RequiresRegister());
+      locations->SetOut(Location::RequiresFpuRegister());
+      break;
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
+                                    : Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister dst = VRegisterFrom(locations->Out());
+
+  DCHECK_EQ(1u, instruction->InputCount());  // only one input currently implemented
+
+  // Zero out all other elements first.
+  __ Movi(dst.V16B(), 0);
+
+  // Shorthand for any type of zero.
+  if (IsZeroBitPattern(instruction->InputAt(0))) {
+    return;
+  }
+
+  // Set required elements.
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      __ Mov(dst.V16B(), 0, InputRegisterAt(instruction, 0));
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      __ Mov(dst.V8H(), 0, InputRegisterAt(instruction, 0));
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      __ Mov(dst.V4S(), 0, InputRegisterAt(instruction, 0));
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, instruction->GetVectorLength());
+      __ Mov(dst.V2D(), 0, InputRegisterAt(instruction, 0));
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+// Helper to set up locations for vector accumulations.
+static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
+  LocationSummary* locations = new (allocator) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetInAt(1, Location::RequiresFpuRegister());
+      locations->SetInAt(2, Location::RequiresFpuRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
+  CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
+// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
+// However vector MultiplyAccumulate instruction is not affected.
+void InstructionCodeGeneratorARM64Neon::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister acc = VRegisterFrom(locations->InAt(0));
+  VRegister left = VRegisterFrom(locations->InAt(1));
+  VRegister right = VRegisterFrom(locations->InAt(2));
+
+  DCHECK(locations->InAt(0).Equals(locations->Out()));
+
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, instruction->GetVectorLength());
+      if (instruction->GetOpKind() == HInstruction::kAdd) {
+        __ Mla(acc.V16B(), left.V16B(), right.V16B());
+      } else {
+        __ Mls(acc.V16B(), left.V16B(), right.V16B());
+      }
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      if (instruction->GetOpKind() == HInstruction::kAdd) {
+        __ Mla(acc.V8H(), left.V8H(), right.V8H());
+      } else {
+        __ Mls(acc.V8H(), left.V8H(), right.V8H());
+      }
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, instruction->GetVectorLength());
+      if (instruction->GetOpKind() == HInstruction::kAdd) {
+        __ Mla(acc.V4S(), left.V4S(), right.V4S());
+      } else {
+        __ Mls(acc.V4S(), left.V4S(), right.V4S());
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
+  CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
+  // Some conversions require temporary registers.
+  LocationSummary* locations = instruction->GetLocations();
+  HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
+  HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
+  DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
+            HVecOperation::ToSignedType(b->GetPackedType()));
+  switch (a->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      switch (instruction->GetPackedType()) {
+        case DataType::Type::kInt64:
+          locations->AddTemp(Location::RequiresFpuRegister());
+          locations->AddTemp(Location::RequiresFpuRegister());
+          FALLTHROUGH_INTENDED;
+        case DataType::Type::kInt32:
+          locations->AddTemp(Location::RequiresFpuRegister());
+          locations->AddTemp(Location::RequiresFpuRegister());
+          break;
+        default:
+          break;
+      }
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      if (instruction->GetPackedType() == DataType::Type::kInt64) {
+        locations->AddTemp(Location::RequiresFpuRegister());
+        locations->AddTemp(Location::RequiresFpuRegister());
+      }
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      if (instruction->GetPackedType() == a->GetPackedType()) {
+        locations->AddTemp(Location::RequiresFpuRegister());
+      }
+      break;
+    default:
+      break;
+  }
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  VRegister acc = VRegisterFrom(locations->InAt(0));
+  VRegister left = VRegisterFrom(locations->InAt(1));
+  VRegister right = VRegisterFrom(locations->InAt(2));
+
+  DCHECK(locations->InAt(0).Equals(locations->Out()));
+
+  // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
+  HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
+  HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
+  DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
+            HVecOperation::ToSignedType(b->GetPackedType()));
+  switch (a->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      DCHECK_EQ(16u, a->GetVectorLength());
+      switch (instruction->GetPackedType()) {
+        case DataType::Type::kInt16:
+          DCHECK_EQ(8u, instruction->GetVectorLength());
+          __ Sabal(acc.V8H(), left.V8B(), right.V8B());
+          __ Sabal2(acc.V8H(), left.V16B(), right.V16B());
+          break;
+        case DataType::Type::kInt32: {
+          DCHECK_EQ(4u, instruction->GetVectorLength());
+          VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
+          VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
+          __ Sxtl(tmp1.V8H(), left.V8B());
+          __ Sxtl(tmp2.V8H(), right.V8B());
+          __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
+          __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
+          __ Sxtl2(tmp1.V8H(), left.V16B());
+          __ Sxtl2(tmp2.V8H(), right.V16B());
+          __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H());
+          __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H());
+          break;
+        }
+        case DataType::Type::kInt64: {
+          DCHECK_EQ(2u, instruction->GetVectorLength());
+          VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
+          VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
+          VRegister tmp3 = VRegisterFrom(locations->GetTemp(2));
+          VRegister tmp4 = VRegisterFrom(locations->GetTemp(3));
+          __ Sxtl(tmp1.V8H(), left.V8B());
+          __ Sxtl(tmp2.V8H(), right.V8B());
+          __ Sxtl(tmp3.V4S(), tmp1.V4H());
+          __ Sxtl(tmp4.V4S(), tmp2.V4H());
+          __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
+          __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
+          __ Sxtl2(tmp3.V4S(), tmp1.V8H());
+          __ Sxtl2(tmp4.V4S(), tmp2.V8H());
+          __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
+          __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
+          __ Sxtl2(tmp1.V8H(), left.V16B());
+          __ Sxtl2(tmp2.V8H(), right.V16B());
+          __ Sxtl(tmp3.V4S(), tmp1.V4H());
+          __ Sxtl(tmp4.V4S(), tmp2.V4H());
+          __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
+          __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
+          __ Sxtl2(tmp3.V4S(), tmp1.V8H());
+          __ Sxtl2(tmp4.V4S(), tmp2.V8H());
+          __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S());
+          __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S());
+          break;
+        }
+        default:
+          LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+          UNREACHABLE();
+      }
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      DCHECK_EQ(8u, a->GetVectorLength());
+      switch (instruction->GetPackedType()) {
+        case DataType::Type::kInt32:
+          DCHECK_EQ(4u, instruction->GetVectorLength());
+          __ Sabal(acc.V4S(), left.V4H(), right.V4H());
+          __ Sabal2(acc.V4S(), left.V8H(), right.V8H());
+          break;
+        case DataType::Type::kInt64: {
+          DCHECK_EQ(2u, instruction->GetVectorLength());
+          VRegister tmp1 = VRegisterFrom(locations->GetTemp(0));
+          VRegister tmp2 = VRegisterFrom(locations->GetTemp(1));
+          __ Sxtl(tmp1.V4S(), left.V4H());
+          __ Sxtl(tmp2.V4S(), right.V4H());
+          __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
+          __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
+          __ Sxtl2(tmp1.V4S(), left.V8H());
+          __ Sxtl2(tmp2.V4S(), right.V8H());
+          __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S());
+          __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S());
+          break;
+        }
+        default:
+          LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+          UNREACHABLE();
+      }
+      break;
+    case DataType::Type::kInt32:
+      DCHECK_EQ(4u, a->GetVectorLength());
+      switch (instruction->GetPackedType()) {
+        case DataType::Type::kInt32: {
+          DCHECK_EQ(4u, instruction->GetVectorLength());
+          VRegister tmp = VRegisterFrom(locations->GetTemp(0));
+          __ Sub(tmp.V4S(), left.V4S(), right.V4S());
+          __ Abs(tmp.V4S(), tmp.V4S());
+          __ Add(acc.V4S(), acc.V4S(), tmp.V4S());
+          break;
+        }
+        case DataType::Type::kInt64:
+          DCHECK_EQ(2u, instruction->GetVectorLength());
+          __ Sabal(acc.V2D(), left.V2S(), right.V2S());
+          __ Sabal2(acc.V2D(), left.V4S(), right.V4S());
+          break;
+        default:
+          LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+          UNREACHABLE();
+      }
+      break;
+    case DataType::Type::kInt64:
+      DCHECK_EQ(2u, a->GetVectorLength());
+      switch (instruction->GetPackedType()) {
+        case DataType::Type::kInt64: {
+          DCHECK_EQ(2u, instruction->GetVectorLength());
+          VRegister tmp = VRegisterFrom(locations->GetTemp(0));
+          __ Sub(tmp.V2D(), left.V2D(), right.V2D());
+          __ Abs(tmp.V2D(), tmp.V2D());
+          __ Add(acc.V2D(), acc.V2D(), tmp.V2D());
+          break;
+        }
+        default:
+          LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+          UNREACHABLE();
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecDotProd(HVecDotProd* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+  DCHECK(instruction->GetPackedType() == DataType::Type::kInt32);
+  locations->SetInAt(0, Location::RequiresFpuRegister());
+  locations->SetInAt(1, Location::RequiresFpuRegister());
+  locations->SetInAt(2, Location::RequiresFpuRegister());
+  locations->SetOut(Location::SameAsFirstInput());
+
+  // For Int8 and Uint8 general case we need a temp register.
+  if ((DataType::Size(instruction->InputAt(1)->AsVecOperation()->GetPackedType()) == 1) &&
+      !ShouldEmitDotProductInstructions(codegen_)) {
+    locations->AddTemp(Location::RequiresFpuRegister());
+  }
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecDotProd(HVecDotProd* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  DCHECK(locations->InAt(0).Equals(locations->Out()));
+  VRegister acc = VRegisterFrom(locations->InAt(0));
+  VRegister left = VRegisterFrom(locations->InAt(1));
+  VRegister right = VRegisterFrom(locations->InAt(2));
+  HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
+  HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
+  DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
+            HVecOperation::ToSignedType(b->GetPackedType()));
+  DCHECK_EQ(instruction->GetPackedType(), DataType::Type::kInt32);
+  DCHECK_EQ(4u, instruction->GetVectorLength());
+
+  size_t inputs_data_size = DataType::Size(a->GetPackedType());
+  switch (inputs_data_size) {
+    case 1u: {
+      DCHECK_EQ(16u, a->GetVectorLength());
+      if (instruction->IsZeroExtending()) {
+        if (ShouldEmitDotProductInstructions(codegen_)) {
+          __ Udot(acc.V4S(), left.V16B(), right.V16B());
+        } else {
+          VRegister tmp = VRegisterFrom(locations->GetTemp(0));
+          __ Umull(tmp.V8H(), left.V8B(), right.V8B());
+          __ Uaddw(acc.V4S(), acc.V4S(), tmp.V4H());
+          __ Uaddw2(acc.V4S(), acc.V4S(), tmp.V8H());
+
+          __ Umull2(tmp.V8H(), left.V16B(), right.V16B());
+          __ Uaddw(acc.V4S(), acc.V4S(), tmp.V4H());
+          __ Uaddw2(acc.V4S(), acc.V4S(), tmp.V8H());
+        }
+      } else {
+        if (ShouldEmitDotProductInstructions(codegen_)) {
+          __ Sdot(acc.V4S(), left.V16B(), right.V16B());
+        } else {
+          VRegister tmp = VRegisterFrom(locations->GetTemp(0));
+          __ Smull(tmp.V8H(), left.V8B(), right.V8B());
+          __ Saddw(acc.V4S(), acc.V4S(), tmp.V4H());
+          __ Saddw2(acc.V4S(), acc.V4S(), tmp.V8H());
+
+          __ Smull2(tmp.V8H(), left.V16B(), right.V16B());
+          __ Saddw(acc.V4S(), acc.V4S(), tmp.V4H());
+          __ Saddw2(acc.V4S(), acc.V4S(), tmp.V8H());
+        }
+      }
+      break;
+    }
+    case 2u:
+      DCHECK_EQ(8u, a->GetVectorLength());
+      if (instruction->IsZeroExtending()) {
+        __ Umlal(acc.V4S(), left.V4H(), right.V4H());
+        __ Umlal2(acc.V4S(), left.V8H(), right.V8H());
+      } else {
+        __ Smlal(acc.V4S(), left.V4H(), right.V4H());
+        __ Smlal2(acc.V4S(), left.V8H(), right.V8H());
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type size: " << inputs_data_size;
+  }
+}
+
+// Helper to set up locations for vector memory operations.
+static void CreateVecMemLocations(ArenaAllocator* allocator,
+                                  HVecMemoryOperation* instruction,
+                                  bool is_load) {
+  LocationSummary* locations = new (allocator) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      locations->SetInAt(0, Location::RequiresRegister());
+      locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
+      if (is_load) {
+        locations->SetOut(Location::RequiresFpuRegister());
+      } else {
+        locations->SetInAt(2, Location::RequiresFpuRegister());
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecLoad(HVecLoad* instruction) {
+  CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecLoad(HVecLoad* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  size_t size = DataType::Size(instruction->GetPackedType());
+  VRegister reg = VRegisterFrom(locations->Out());
+  UseScratchRegisterScope temps(GetVIXLAssembler());
+  Register scratch;
+
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kInt16:  // (short) s.charAt(.) can yield HVecLoad/Int16/StringCharAt.
+    case DataType::Type::kUint16:
+      DCHECK_EQ(8u, instruction->GetVectorLength());
+      // Special handling of compressed/uncompressed string load.
+      if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
+        vixl::aarch64::Label uncompressed_load, done;
+        // Test compression bit.
+        static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
+                      "Expecting 0=compressed, 1=uncompressed");
+        uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
+        Register length = temps.AcquireW();
+        __ Ldr(length, HeapOperand(InputRegisterAt(instruction, 0), count_offset));
+        __ Tbnz(length.W(), 0, &uncompressed_load);
+        temps.Release(length);  // no longer needed
+        // Zero extend 8 compressed bytes into 8 chars.
+        __ Ldr(DRegisterFrom(locations->Out()).V8B(),
+               VecNEONAddress(instruction, &temps, 1, /*is_string_char_at*/ true, &scratch));
+        __ Uxtl(reg.V8H(), reg.V8B());
+        __ B(&done);
+        if (scratch.IsValid()) {
+          temps.Release(scratch);  // if used, no longer needed
+        }
+        // Load 8 direct uncompressed chars.
+        __ Bind(&uncompressed_load);
+        __ Ldr(reg,
+               VecNEONAddress(instruction, &temps, size, /*is_string_char_at*/ true, &scratch));
+        __ Bind(&done);
+        return;
+      }
+      FALLTHROUGH_INTENDED;
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kInt32:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat64:
+      DCHECK_LE(2u, instruction->GetVectorLength());
+      DCHECK_LE(instruction->GetVectorLength(), 16u);
+      __ Ldr(reg,
+             VecNEONAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch));
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecStore(HVecStore* instruction) {
+  CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecStore(HVecStore* instruction) {
+  LocationSummary* locations = instruction->GetLocations();
+  size_t size = DataType::Size(instruction->GetPackedType());
+  VRegister reg = VRegisterFrom(locations->InAt(2));
+  UseScratchRegisterScope temps(GetVIXLAssembler());
+  Register scratch;
+
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat64:
+      DCHECK_LE(2u, instruction->GetVectorLength());
+      DCHECK_LE(instruction->GetVectorLength(), 16u);
+      __ Str(reg,
+             VecNEONAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Neon::VisitVecPredSetAll(HVecPredSetAll* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+  DCHECK(instruction->InputAt(0)->IsIntConstant());
+  locations->SetInAt(0, Location::NoLocation());
+  locations->SetOut(Location::NoLocation());
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecPredSetAll(HVecPredSetAll*) {
+}
+
+void LocationsBuilderARM64Neon::VisitVecPredWhile(HVecPredWhile* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecPredWhile(HVecPredWhile* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderARM64Neon::VisitVecPredCondition(HVecPredCondition* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARM64Neon::VisitVecPredCondition(HVecPredCondition* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+Location InstructionCodeGeneratorARM64Neon::AllocateSIMDScratchLocation(
+    vixl::aarch64::UseScratchRegisterScope* scope) {
+  DCHECK_EQ(codegen_->GetSIMDRegisterWidth(), kQRegSizeInBytes);
+  return LocationFrom(scope->AcquireVRegisterOfSize(kQRegSize));
+}
+
+void InstructionCodeGeneratorARM64Neon::FreeSIMDScratchLocation(Location loc,
+    vixl::aarch64::UseScratchRegisterScope* scope) {
+  DCHECK_EQ(codegen_->GetSIMDRegisterWidth(), kQRegSizeInBytes);
+  scope->Release(QRegisterFrom(loc));
+}
+
+void InstructionCodeGeneratorARM64Neon::LoadSIMDRegFromStack(Location destination,
+                                                             Location source) {
+  DCHECK_EQ(codegen_->GetSIMDRegisterWidth(), kQRegSizeInBytes);
+  __ Ldr(QRegisterFrom(destination), StackOperandFrom(source));
+}
+
+void InstructionCodeGeneratorARM64Neon::MoveSIMDRegToSIMDReg(Location destination,
+                                                             Location source) {
+  DCHECK_EQ(codegen_->GetSIMDRegisterWidth(), kQRegSizeInBytes);
+  __ Mov(QRegisterFrom(destination), QRegisterFrom(source));
+}
+
+void InstructionCodeGeneratorARM64Neon::MoveToSIMDStackSlot(Location destination,
+                                                            Location source) {
+  DCHECK(destination.IsSIMDStackSlot());
+  DCHECK_EQ(codegen_->GetSIMDRegisterWidth(), kQRegSizeInBytes);
+
+  if (source.IsFpuRegister()) {
+    __ Str(QRegisterFrom(source), StackOperandFrom(destination));
+  } else {
+    DCHECK(source.IsSIMDStackSlot());
+    UseScratchRegisterScope temps(GetVIXLAssembler());
+    if (GetVIXLAssembler()->GetScratchVRegisterList()->IsEmpty()) {
+      Register temp = temps.AcquireX();
+      __ Ldr(temp, MemOperand(sp, source.GetStackIndex()));
+      __ Str(temp, MemOperand(sp, destination.GetStackIndex()));
+      __ Ldr(temp, MemOperand(sp, source.GetStackIndex() + kArm64WordSize));
+      __ Str(temp, MemOperand(sp, destination.GetStackIndex() + kArm64WordSize));
+    } else {
+      VRegister temp = temps.AcquireVRegisterOfSize(kQRegSize);
+      __ Ldr(temp, StackOperandFrom(source));
+      __ Str(temp, StackOperandFrom(destination));
+    }
+  }
+}
+
+// Calculate memory accessing operand for save/restore live registers.
+template <bool is_save>
+void SaveRestoreLiveRegistersHelperNeonImpl(CodeGeneratorARM64* codegen,
+                                            LocationSummary* locations,
+                                            int64_t spill_offset) {
+  const uint32_t core_spills = codegen->GetSlowPathSpills(locations, /* core_registers= */ true);
+  const uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers= */ false);
+  DCHECK(helpers::ArtVixlRegCodeCoherentForRegSet(core_spills,
+                                                  codegen->GetNumberOfCoreRegisters(),
+                                                  fp_spills,
+                                                  codegen->GetNumberOfFloatingPointRegisters()));
+
+  CPURegList core_list = CPURegList(CPURegister::kRegister, kXRegSize, core_spills);
+  const unsigned v_reg_size_in_bits = codegen->GetSlowPathFPWidth() * 8;
+  DCHECK_LE(codegen->GetSIMDRegisterWidth(), kQRegSizeInBytes);
+  CPURegList fp_list = CPURegList(CPURegister::kVRegister, v_reg_size_in_bits, fp_spills);
+
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  UseScratchRegisterScope temps(masm);
+
+  Register base = masm->StackPointer();
+  int64_t core_spill_size = core_list.GetTotalSizeInBytes();
+  int64_t fp_spill_size = fp_list.GetTotalSizeInBytes();
+  int64_t reg_size = kXRegSizeInBytes;
+  int64_t max_ls_pair_offset = spill_offset + core_spill_size + fp_spill_size - 2 * reg_size;
+  uint32_t ls_access_size = WhichPowerOf2(reg_size);
+  if (((core_list.GetCount() > 1) || (fp_list.GetCount() > 1)) &&
+      !masm->IsImmLSPair(max_ls_pair_offset, ls_access_size)) {
+    // If the offset does not fit in the instruction's immediate field, use an alternate register
+    // to compute the base address(float point registers spill base address).
+    Register new_base = temps.AcquireSameSizeAs(base);
+    masm->Add(new_base, base, Operand(spill_offset + core_spill_size));
+    base = new_base;
+    spill_offset = -core_spill_size;
+    int64_t new_max_ls_pair_offset = fp_spill_size - 2 * reg_size;
+    DCHECK(masm->IsImmLSPair(spill_offset, ls_access_size));
+    DCHECK(masm->IsImmLSPair(new_max_ls_pair_offset, ls_access_size));
+  }
+
+  if (is_save) {
+    masm->StoreCPURegList(core_list, MemOperand(base, spill_offset));
+    masm->StoreCPURegList(fp_list, MemOperand(base, spill_offset + core_spill_size));
+  } else {
+    masm->LoadCPURegList(core_list, MemOperand(base, spill_offset));
+    masm->LoadCPURegList(fp_list, MemOperand(base, spill_offset + core_spill_size));
+  }
+}
+
+void InstructionCodeGeneratorARM64Neon::SaveLiveRegistersHelper(LocationSummary* locations,
+                                                                int64_t spill_offset) {
+  SaveRestoreLiveRegistersHelperNeonImpl</* is_save= */ true>(codegen_, locations, spill_offset);
+}
+
+void InstructionCodeGeneratorARM64Neon::RestoreLiveRegistersHelper(LocationSummary* locations,
+                                                                   int64_t spill_offset) {
+  SaveRestoreLiveRegistersHelperNeonImpl</* is_save= */ false>(codegen_, locations, spill_offset);
+}
+
+#undef __
+
+}  // namespace arm64
+}  // namespace art
diff --git a/compiler/optimizing/code_generator_vector_arm64_sve.cc b/compiler/optimizing/code_generator_vector_arm64_sve.cc
new file mode 100644
index 0000000..824b6c9
--- /dev/null
+++ b/compiler/optimizing/code_generator_vector_arm64_sve.cc
@@ -0,0 +1,1388 @@
+/*
+ * Copyright (C) 2020 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 "code_generator_arm64.h"
+
+#include "arch/arm64/instruction_set_features_arm64.h"
+#include "base/bit_utils_iterator.h"
+#include "mirror/array-inl.h"
+#include "mirror/string.h"
+
+using namespace vixl::aarch64;  // NOLINT(build/namespaces)
+
+namespace art {
+namespace arm64 {
+
+using helpers::DRegisterFrom;
+using helpers::HeapOperand;
+using helpers::InputRegisterAt;
+using helpers::Int64FromLocation;
+using helpers::LocationFrom;
+using helpers::OutputRegister;
+using helpers::QRegisterFrom;
+using helpers::StackOperandFrom;
+using helpers::SveStackOperandFrom;
+using helpers::VRegisterFrom;
+using helpers::ZRegisterFrom;
+using helpers::XRegisterFrom;
+
+#define __ GetVIXLAssembler()->
+
+// Returns whether the value of the constant can be directly encoded into the instruction as
+// immediate.
+static bool SVECanEncodeConstantAsImmediate(HConstant* constant, HInstruction* instr) {
+  if (instr->IsVecReplicateScalar()) {
+    if (constant->IsLongConstant()) {
+      return false;
+    } else if (constant->IsFloatConstant()) {
+      return vixl::aarch64::Assembler::IsImmFP32(constant->AsFloatConstant()->GetValue());
+    } else if (constant->IsDoubleConstant()) {
+      return vixl::aarch64::Assembler::IsImmFP64(constant->AsDoubleConstant()->GetValue());
+    }
+    // TODO: Make use of shift part of DUP instruction.
+    int64_t value = CodeGenerator::GetInt64ValueOf(constant);
+    return IsInt<8>(value);
+  }
+
+  return false;
+}
+
+// Returns
+//  - constant location - if 'constant' is an actual constant and its value can be
+//    encoded into the instruction.
+//  - register location otherwise.
+inline Location SVEEncodableConstantOrRegister(HInstruction* constant, HInstruction* instr) {
+  if (constant->IsConstant()
+      && SVECanEncodeConstantAsImmediate(constant->AsConstant(), instr)) {
+    return Location::ConstantLocation(constant->AsConstant());
+  }
+
+  return Location::RequiresRegister();
+}
+
+void InstructionCodeGeneratorARM64Sve::ValidateVectorLength(HVecOperation* instr) const {
+  DCHECK_EQ(DataType::Size(instr->GetPackedType()) * instr->GetVectorLength(),
+            codegen_->GetSIMDRegisterWidth());
+}
+
+void LocationsBuilderARM64Sve::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+  HInstruction* input = instruction->InputAt(0);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      locations->SetInAt(0, SVEEncodableConstantOrRegister(input, instruction));
+      locations->SetOut(Location::RequiresFpuRegister());
+      break;
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      if (input->IsConstant() &&
+          SVECanEncodeConstantAsImmediate(input->AsConstant(), instruction)) {
+        locations->SetInAt(0, Location::ConstantLocation(input->AsConstant()));
+        locations->SetOut(Location::RequiresFpuRegister());
+      } else {
+        locations->SetInAt(0, Location::RequiresFpuRegister());
+        locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  Location src_loc = locations->InAt(0);
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      if (src_loc.IsConstant()) {
+        __ Dup(dst.VnB(), Int64FromLocation(src_loc));
+      } else {
+        __ Dup(dst.VnB(), InputRegisterAt(instruction, 0));
+      }
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      if (src_loc.IsConstant()) {
+        __ Dup(dst.VnH(), Int64FromLocation(src_loc));
+      } else {
+        __ Dup(dst.VnH(), InputRegisterAt(instruction, 0));
+      }
+      break;
+    case DataType::Type::kInt32:
+      if (src_loc.IsConstant()) {
+        __ Dup(dst.VnS(), Int64FromLocation(src_loc));
+      } else {
+        __ Dup(dst.VnS(), InputRegisterAt(instruction, 0));
+      }
+      break;
+    case DataType::Type::kInt64:
+      if (src_loc.IsConstant()) {
+        __ Dup(dst.VnD(), Int64FromLocation(src_loc));
+      } else {
+        __ Dup(dst.VnD(), XRegisterFrom(src_loc));
+      }
+      break;
+    case DataType::Type::kFloat32:
+      if (src_loc.IsConstant()) {
+        __ Fdup(dst.VnS(), src_loc.GetConstant()->AsFloatConstant()->GetValue());
+      } else {
+        __ Dup(dst.VnS(), ZRegisterFrom(src_loc).VnS(), 0);
+      }
+      break;
+    case DataType::Type::kFloat64:
+      if (src_loc.IsConstant()) {
+        __ Fdup(dst.VnD(), src_loc.GetConstant()->AsDoubleConstant()->GetValue());
+      } else {
+        __ Dup(dst.VnD(), ZRegisterFrom(src_loc).VnD(), 0);
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecExtractScalar(HVecExtractScalar* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresRegister());
+      break;
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecExtractScalar(HVecExtractScalar* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const VRegister src = VRegisterFrom(locations->InAt(0));
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kInt32:
+      __ Umov(OutputRegister(instruction), src.V4S(), 0);
+      break;
+    case DataType::Type::kInt64:
+      __ Umov(OutputRegister(instruction), src.V2D(), 0);
+      break;
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      DCHECK(locations->InAt(0).Equals(locations->Out()));  // no code required
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+// Helper to set up locations for vector unary operations.
+static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
+  LocationSummary* locations = new (allocator) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister(),
+                        instruction->IsVecNot() ? Location::kOutputOverlap
+                                                : Location::kNoOutputOverlap);
+      break;
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecReduce(HVecReduce* instruction) {
+  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecReduce(HVecReduce* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister src = ZRegisterFrom(locations->InAt(0));
+  const VRegister dst = DRegisterFrom(locations->Out());
+  const PRegister p_reg = LoopPReg();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kInt32:
+      switch (instruction->GetReductionKind()) {
+        case HVecReduce::kSum:
+          __ Saddv(dst.S(), p_reg, src.VnS());
+          break;
+        default:
+          LOG(FATAL) << "Unsupported SIMD instruction";
+          UNREACHABLE();
+      }
+      break;
+    case DataType::Type::kInt64:
+      switch (instruction->GetReductionKind()) {
+        case HVecReduce::kSum:
+          __ Uaddv(dst.D(), p_reg, src.VnD());
+          break;
+        default:
+          LOG(FATAL) << "Unsupported SIMD instruction";
+          UNREACHABLE();
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecCnv(HVecCnv* instruction) {
+  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecCnv(HVecCnv* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister src = ZRegisterFrom(locations->InAt(0));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  DataType::Type from = instruction->GetInputType();
+  DataType::Type to = instruction->GetResultType();
+  ValidateVectorLength(instruction);
+  if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
+    __ Scvtf(dst.VnS(), p_reg, src.VnS());
+  } else {
+    LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecNeg(HVecNeg* instruction) {
+  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecNeg(HVecNeg* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister src = ZRegisterFrom(locations->InAt(0));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Neg(dst.VnB(), p_reg, src.VnB());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Neg(dst.VnH(), p_reg, src.VnH());
+      break;
+    case DataType::Type::kInt32:
+      __ Neg(dst.VnS(), p_reg, src.VnS());
+      break;
+    case DataType::Type::kInt64:
+      __ Neg(dst.VnD(), p_reg, src.VnD());
+      break;
+    case DataType::Type::kFloat32:
+      __ Fneg(dst.VnS(), p_reg, src.VnS());
+      break;
+    case DataType::Type::kFloat64:
+      __ Fneg(dst.VnD(), p_reg, src.VnD());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecAbs(HVecAbs* instruction) {
+  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecAbs(HVecAbs* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister src = ZRegisterFrom(locations->InAt(0));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kInt8:
+      __ Abs(dst.VnB(), p_reg, src.VnB());
+      break;
+    case DataType::Type::kInt16:
+      __ Abs(dst.VnH(), p_reg, src.VnH());
+      break;
+    case DataType::Type::kInt32:
+      __ Abs(dst.VnS(), p_reg, src.VnS());
+      break;
+    case DataType::Type::kInt64:
+      __ Abs(dst.VnD(), p_reg, src.VnD());
+      break;
+    case DataType::Type::kFloat32:
+      __ Fabs(dst.VnS(), p_reg, src.VnS());
+      break;
+    case DataType::Type::kFloat64:
+      __ Fabs(dst.VnD(), p_reg, src.VnD());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecNot(HVecNot* instruction) {
+  CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecNot(HVecNot* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister src = ZRegisterFrom(locations->InAt(0));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:  // special case boolean-not
+      __ Dup(dst.VnB(), 1);
+      __ Eor(dst.VnB(), p_reg, dst.VnB(), src.VnB());
+      break;
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Not(dst.VnB(), p_reg, src.VnB());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Not(dst.VnH(), p_reg, src.VnH());
+      break;
+    case DataType::Type::kInt32:
+      __ Not(dst.VnS(), p_reg, src.VnS());
+      break;
+    case DataType::Type::kInt64:
+      __ Not(dst.VnD(), p_reg, src.VnD());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+// Helper to set up locations for vector binary operations.
+static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
+  LocationSummary* locations = new (allocator) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetInAt(1, Location::RequiresFpuRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecAdd(HVecAdd* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecAdd(HVecAdd* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister lhs = ZRegisterFrom(locations->InAt(0));
+  const ZRegister rhs = ZRegisterFrom(locations->InAt(1));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Add(dst.VnB(), p_reg, lhs.VnB(), rhs.VnB());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Add(dst.VnH(), p_reg, lhs.VnH(), rhs.VnH());
+      break;
+    case DataType::Type::kInt32:
+      __ Add(dst.VnS(), p_reg, lhs.VnS(), rhs.VnS());
+      break;
+    case DataType::Type::kInt64:
+      __ Add(dst.VnD(), p_reg, lhs.VnD(), rhs.VnD());
+      break;
+    case DataType::Type::kFloat32:
+      __ Fadd(dst.VnS(), p_reg, lhs.VnS(), rhs.VnS(), StrictNaNPropagation);
+      break;
+    case DataType::Type::kFloat64:
+      __ Fadd(dst.VnD(), p_reg, lhs.VnD(), rhs.VnD(), StrictNaNPropagation);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderARM64Sve::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderARM64Sve::VisitVecSub(HVecSub* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecSub(HVecSub* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister lhs = ZRegisterFrom(locations->InAt(0));
+  const ZRegister rhs = ZRegisterFrom(locations->InAt(1));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Sub(dst.VnB(), p_reg, lhs.VnB(), rhs.VnB());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Sub(dst.VnH(), p_reg, lhs.VnH(), rhs.VnH());
+      break;
+    case DataType::Type::kInt32:
+      __ Sub(dst.VnS(), p_reg, lhs.VnS(), rhs.VnS());
+      break;
+    case DataType::Type::kInt64:
+      __ Sub(dst.VnD(), p_reg, lhs.VnD(), rhs.VnD());
+      break;
+    case DataType::Type::kFloat32:
+      __ Fsub(dst.VnS(), p_reg, lhs.VnS(), rhs.VnS());
+      break;
+    case DataType::Type::kFloat64:
+      __ Fsub(dst.VnD(), p_reg, lhs.VnD(), rhs.VnD());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecSaturationSub(HVecSaturationSub* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecSaturationSub(HVecSaturationSub* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderARM64Sve::VisitVecMul(HVecMul* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecMul(HVecMul* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister lhs = ZRegisterFrom(locations->InAt(0));
+  const ZRegister rhs = ZRegisterFrom(locations->InAt(1));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Mul(dst.VnB(), p_reg, lhs.VnB(), rhs.VnB());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Mul(dst.VnH(), p_reg, lhs.VnH(), rhs.VnH());
+      break;
+    case DataType::Type::kInt32:
+      __ Mul(dst.VnS(), p_reg, lhs.VnS(), rhs.VnS());
+      break;
+    case DataType::Type::kInt64:
+      __ Mul(dst.VnD(), p_reg, lhs.VnD(), rhs.VnD());
+      break;
+    case DataType::Type::kFloat32:
+      __ Fmul(dst.VnS(), p_reg, lhs.VnS(), rhs.VnS(), StrictNaNPropagation);
+      break;
+    case DataType::Type::kFloat64:
+      __ Fmul(dst.VnD(), p_reg, lhs.VnD(), rhs.VnD(), StrictNaNPropagation);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecDiv(HVecDiv* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecDiv(HVecDiv* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister lhs = ZRegisterFrom(locations->InAt(0));
+  const ZRegister rhs = ZRegisterFrom(locations->InAt(1));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  ValidateVectorLength(instruction);
+
+  // Note: VIXL guarantees StrictNaNPropagation for Fdiv.
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kFloat32:
+      __ Fdiv(dst.VnS(), p_reg, lhs.VnS(), rhs.VnS());
+      break;
+    case DataType::Type::kFloat64:
+      __ Fdiv(dst.VnD(), p_reg, lhs.VnD(), rhs.VnD());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecMin(HVecMin* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecMin(HVecMin* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderARM64Sve::VisitVecMax(HVecMax* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecMax(HVecMax* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderARM64Sve::VisitVecAnd(HVecAnd* instruction) {
+  // TODO: Allow constants supported by BIC (vector, immediate).
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecAnd(HVecAnd* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister lhs = ZRegisterFrom(locations->InAt(0));
+  const ZRegister rhs = ZRegisterFrom(locations->InAt(1));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ And(dst.VnB(), p_reg, lhs.VnB(), rhs.VnB());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ And(dst.VnH(), p_reg, lhs.VnH(), rhs.VnH());
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kFloat32:
+      __ And(dst.VnS(), p_reg, lhs.VnS(), rhs.VnS());
+      break;
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat64:
+      __ And(dst.VnD(), p_reg, lhs.VnD(), rhs.VnD());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecAndNot(HVecAndNot* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecAndNot(HVecAndNot* instruction) {
+  // TODO: Use BIC (vector, register).
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+}
+
+void LocationsBuilderARM64Sve::VisitVecOr(HVecOr* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecOr(HVecOr* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister lhs = ZRegisterFrom(locations->InAt(0));
+  const ZRegister rhs = ZRegisterFrom(locations->InAt(1));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Orr(dst.VnB(), p_reg, lhs.VnB(), rhs.VnB());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Orr(dst.VnH(), p_reg, lhs.VnH(), rhs.VnH());
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kFloat32:
+      __ Orr(dst.VnS(), p_reg, lhs.VnS(), rhs.VnS());
+      break;
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat64:
+      __ Orr(dst.VnD(), p_reg, lhs.VnD(), rhs.VnD());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecXor(HVecXor* instruction) {
+  CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecXor(HVecXor* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister lhs = ZRegisterFrom(locations->InAt(0));
+  const ZRegister rhs = ZRegisterFrom(locations->InAt(1));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Eor(dst.VnB(), p_reg, lhs.VnB(), rhs.VnB());
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Eor(dst.VnH(), p_reg, lhs.VnH(), rhs.VnH());
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kFloat32:
+      __ Eor(dst.VnS(), p_reg, lhs.VnS(), rhs.VnS());
+      break;
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat64:
+      __ Eor(dst.VnD(), p_reg, lhs.VnD(), rhs.VnD());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+// Helper to set up locations for vector shift operations.
+static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
+  LocationSummary* locations = new (allocator) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
+      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecShl(HVecShl* instruction) {
+  CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecShl(HVecShl* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister lhs = ZRegisterFrom(locations->InAt(0));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Lsl(dst.VnB(), p_reg, lhs.VnB(), value);
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Lsl(dst.VnH(), p_reg, lhs.VnH(), value);
+      break;
+    case DataType::Type::kInt32:
+      __ Lsl(dst.VnS(), p_reg, lhs.VnS(), value);
+      break;
+    case DataType::Type::kInt64:
+      __ Lsl(dst.VnD(), p_reg, lhs.VnD(), value);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecShr(HVecShr* instruction) {
+  CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecShr(HVecShr* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister lhs = ZRegisterFrom(locations->InAt(0));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Asr(dst.VnB(), p_reg, lhs.VnB(), value);
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Asr(dst.VnH(), p_reg, lhs.VnH(), value);
+      break;
+    case DataType::Type::kInt32:
+      __ Asr(dst.VnS(), p_reg, lhs.VnS(), value);
+      break;
+    case DataType::Type::kInt64:
+      __ Asr(dst.VnD(), p_reg, lhs.VnD(), value);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecUShr(HVecUShr* instruction) {
+  CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecUShr(HVecUShr* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister lhs = ZRegisterFrom(locations->InAt(0));
+  const ZRegister dst = ZRegisterFrom(locations->Out());
+  const PRegisterM p_reg = LoopPReg().Merging();
+  int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
+  ValidateVectorLength(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Lsr(dst.VnB(), p_reg, lhs.VnB(), value);
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Lsr(dst.VnH(), p_reg, lhs.VnH(), value);
+      break;
+    case DataType::Type::kInt32:
+      __ Lsr(dst.VnS(), p_reg, lhs.VnS(), value);
+      break;
+    case DataType::Type::kInt64:
+      __ Lsr(dst.VnD(), p_reg, lhs.VnD(), value);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+
+  DCHECK_EQ(2u, instruction->InputCount());  // only one input currently implemented + predicate.
+
+  HInstruction* input = instruction->InputAt(0);
+  bool is_zero = IsZeroBitPattern(input);
+
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
+                                    : Location::RequiresRegister());
+      locations->SetOut(Location::RequiresFpuRegister());
+      break;
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
+                                    : Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecSetScalars(HVecSetScalars* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister z_dst = ZRegisterFrom(locations->Out());
+
+  DCHECK_EQ(2u, instruction->InputCount());  // only one input currently implemented + predicate.
+
+  // Zero out all other elements first.
+  __ Dup(z_dst.VnB(), 0);
+
+  const VRegister dst = VRegisterFrom(locations->Out());
+  // Shorthand for any type of zero.
+  if (IsZeroBitPattern(instruction->InputAt(0))) {
+    return;
+  }
+  ValidateVectorLength(instruction);
+
+  // Set required elements.
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Mov(dst.V16B(), 0, InputRegisterAt(instruction, 0));
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Mov(dst.V8H(), 0, InputRegisterAt(instruction, 0));
+      break;
+    case DataType::Type::kInt32:
+      __ Mov(dst.V4S(), 0, InputRegisterAt(instruction, 0));
+      break;
+    case DataType::Type::kInt64:
+      __ Mov(dst.V2D(), 0, InputRegisterAt(instruction, 0));
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+// Helper to set up locations for vector accumulations.
+static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
+  LocationSummary* locations = new (allocator) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetInAt(1, Location::RequiresFpuRegister());
+      locations->SetInAt(2, Location::RequiresFpuRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
+  CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
+}
+
+// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
+// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
+// However vector MultiplyAccumulate instruction is not affected.
+void InstructionCodeGeneratorARM64Sve::VisitVecMultiplyAccumulate(
+    HVecMultiplyAccumulate* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  const ZRegister acc = ZRegisterFrom(locations->InAt(0));
+  const ZRegister left = ZRegisterFrom(locations->InAt(1));
+  const ZRegister right = ZRegisterFrom(locations->InAt(2));
+  const PRegisterM p_reg = LoopPReg().Merging();
+
+  DCHECK(locations->InAt(0).Equals(locations->Out()));
+  ValidateVectorLength(instruction);
+
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      if (instruction->GetOpKind() == HInstruction::kAdd) {
+        __ Mla(acc.VnB(), p_reg, acc.VnB(), left.VnB(), right.VnB());
+      } else {
+        __ Mls(acc.VnB(), p_reg, acc.VnB(), left.VnB(), right.VnB());
+      }
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      if (instruction->GetOpKind() == HInstruction::kAdd) {
+        __ Mla(acc.VnH(), p_reg, acc.VnB(), left.VnH(), right.VnH());
+      } else {
+        __ Mls(acc.VnH(), p_reg, acc.VnB(), left.VnH(), right.VnH());
+      }
+      break;
+    case DataType::Type::kInt32:
+      if (instruction->GetOpKind() == HInstruction::kAdd) {
+        __ Mla(acc.VnS(), p_reg, acc.VnB(), left.VnS(), right.VnS());
+      } else {
+        __ Mls(acc.VnS(), p_reg, acc.VnB(), left.VnS(), right.VnS());
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderARM64Sve::VisitVecDotProd(HVecDotProd* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+  DCHECK(instruction->GetPackedType() == DataType::Type::kInt32);
+  locations->SetInAt(0, Location::RequiresFpuRegister());
+  locations->SetInAt(1, Location::RequiresFpuRegister());
+  locations->SetInAt(2, Location::RequiresFpuRegister());
+  locations->SetOut(Location::SameAsFirstInput());
+
+  locations->AddTemp(Location::RequiresFpuRegister());
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecDotProd(HVecDotProd* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  DCHECK(locations->InAt(0).Equals(locations->Out()));
+  const ZRegister acc = ZRegisterFrom(locations->InAt(0));
+  const ZRegister left = ZRegisterFrom(locations->InAt(1));
+  const ZRegister right = ZRegisterFrom(locations->InAt(2));
+  const PRegisterM p_reg = LoopPReg().Merging();
+  HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
+  HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
+  DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
+            HVecOperation::ToSignedType(b->GetPackedType()));
+  DCHECK_EQ(instruction->GetPackedType(), DataType::Type::kInt32);
+  ValidateVectorLength(instruction);
+
+  size_t inputs_data_size = DataType::Size(a->GetPackedType());
+  switch (inputs_data_size) {
+    case 1u: {
+      UseScratchRegisterScope temps(GetVIXLAssembler());
+      const ZRegister tmp0 = temps.AcquireZ();
+      const ZRegister tmp1 = ZRegisterFrom(locations->GetTemp(0));
+
+      __ Dup(tmp1.VnB(), 0u);
+      __ Sel(tmp0.VnB(), p_reg, left.VnB(), tmp1.VnB());
+      __ Sel(tmp1.VnB(), p_reg, right.VnB(), tmp1.VnB());
+      if (instruction->IsZeroExtending()) {
+        __ Udot(acc.VnS(), acc.VnS(), tmp0.VnB(), tmp1.VnB());
+      } else {
+        __ Sdot(acc.VnS(), acc.VnS(), tmp0.VnB(), tmp1.VnB());
+      }
+      break;
+    }
+    default:
+      LOG(FATAL) << "Unsupported SIMD type size: " << inputs_data_size;
+  }
+}
+
+// Helper to set up locations for vector memory operations.
+static void CreateVecMemLocations(ArenaAllocator* allocator,
+                                  HVecMemoryOperation* instruction,
+                                  bool is_load) {
+  LocationSummary* locations = new (allocator) LocationSummary(instruction);
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat32:
+    case DataType::Type::kFloat64:
+      locations->SetInAt(0, Location::RequiresRegister());
+      locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
+      if (is_load) {
+        locations->SetOut(Location::RequiresFpuRegister());
+      } else {
+        locations->SetInAt(2, Location::RequiresFpuRegister());
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecLoad(HVecLoad* instruction) {
+  CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecLoad(HVecLoad* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  size_t size = DataType::Size(instruction->GetPackedType());
+  const ZRegister reg = ZRegisterFrom(locations->Out());
+  UseScratchRegisterScope temps(GetVIXLAssembler());
+  Register scratch;
+  const PRegisterZ p_reg = LoopPReg().Zeroing();
+  ValidateVectorLength(instruction);
+
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kInt16:  // (short) s.charAt(.) can yield HVecLoad/Int16/StringCharAt.
+    case DataType::Type::kUint16:
+      __ Ld1h(reg.VnH(), p_reg,
+              VecSVEAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
+      break;
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Ld1b(reg.VnB(), p_reg,
+              VecSVEAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kFloat32:
+      __ Ld1w(reg.VnS(), p_reg,
+              VecSVEAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
+      break;
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat64:
+      __ Ld1d(reg.VnD(), p_reg,
+              VecSVEAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecStore(HVecStore* instruction) {
+  CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecStore(HVecStore* instruction) {
+  DCHECK(instruction->IsPredicated());
+  LocationSummary* locations = instruction->GetLocations();
+  size_t size = DataType::Size(instruction->GetPackedType());
+  const ZRegister reg = ZRegisterFrom(locations->InAt(2));
+  UseScratchRegisterScope temps(GetVIXLAssembler());
+  Register scratch;
+  const PRegisterZ p_reg = LoopPReg().Zeroing();
+  ValidateVectorLength(instruction);
+
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ St1b(reg.VnB(), p_reg,
+          VecSVEAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ St1h(reg.VnH(), p_reg,
+          VecSVEAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kFloat32:
+      __ St1w(reg.VnS(), p_reg,
+          VecSVEAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
+      break;
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat64:
+      __ St1d(reg.VnD(), p_reg,
+          VecSVEAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecPredSetAll(HVecPredSetAll* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+  DCHECK(instruction->InputAt(0)->IsIntConstant());
+  locations->SetInAt(0, Location::NoLocation());
+  locations->SetOut(Location::NoLocation());
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecPredSetAll(HVecPredSetAll* instruction) {
+  // Instruction is not predicated, see nodes_vector.h
+  DCHECK(!instruction->IsPredicated());
+  const PRegister p_reg = LoopPReg();
+
+  switch (instruction->GetPackedType()) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      __ Ptrue(p_reg.VnB(), vixl::aarch64::SVE_ALL);
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Ptrue(p_reg.VnH(), vixl::aarch64::SVE_ALL);
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kFloat32:
+      __ Ptrue(p_reg.VnS(), vixl::aarch64::SVE_ALL);
+      break;
+    case DataType::Type::kInt64:
+    case DataType::Type::kFloat64:
+      __ Ptrue(p_reg.VnD(), vixl::aarch64::SVE_ALL);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecPredWhile(HVecPredWhile* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+  locations->SetInAt(0, Location::RequiresRegister());
+  locations->SetInAt(1, Location::RequiresRegister());
+  // The instruction doesn't really need a core register as out location; this is a hack
+  // to workaround absence of support for vector predicates in register allocation.
+  //
+  // Semantically, the out location of this instruction and predicate inputs locations of
+  // its users should be a fixed predicate register (similar to
+  // Location::RegisterLocation(int reg)). But the register allocator (RA) doesn't support
+  // SIMD regs (e.g. predicate), so LoopPReg() is used explicitly without exposing it
+  // to the RA.
+  //
+  // To make the RA happy Location::NoLocation() was used for all the vector instructions
+  // predicate inputs; but for the PredSetOperations (e.g. VecPredWhile) Location::NoLocation()
+  // can't be used without changes to RA - "ssa_liveness_analysis.cc] Check failed:
+  // input->IsEmittedAtUseSite()" would fire.
+  //
+  // Using a core register as a hack is the easiest way to tackle this problem. The RA will
+  // block one core register for the loop without actually using it; this should not be
+  // a performance issue as a SIMD loop operates mainly on SIMD registers.
+  //
+  // TODO: Support SIMD types in register allocator.
+  locations->SetOut(Location::RequiresRegister());
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecPredWhile(HVecPredWhile* instruction) {
+  // Instruction is not predicated, see nodes_vector.h
+  DCHECK(!instruction->IsPredicated());
+  // Current implementation of predicated loop execution only supports kLO condition.
+  DCHECK(instruction->GetCondKind() == HVecPredWhile::CondKind::kLO);
+  Register left = InputRegisterAt(instruction, 0);
+  Register right = InputRegisterAt(instruction, 1);
+
+  DCHECK_EQ(codegen_->GetSIMDRegisterWidth() % instruction->GetVectorLength(), 0u);
+
+  switch (codegen_->GetSIMDRegisterWidth() / instruction->GetVectorLength()) {
+    case 1u:
+      __ Whilelo(LoopPReg().VnB(), left, right);
+      break;
+    case 2u:
+      __ Whilelo(LoopPReg().VnH(), left, right);
+      break;
+    case 4u:
+      __ Whilelo(LoopPReg().VnS(), left, right);
+      break;
+    case 8u:
+      __ Whilelo(LoopPReg().VnD(), left, right);
+      break;
+    default:
+      LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
+      UNREACHABLE();
+  }
+}
+
+void LocationsBuilderARM64Sve::VisitVecPredCondition(HVecPredCondition* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+  locations->SetInAt(0, Location::NoLocation());
+  // Result of the operation - a boolean value in a core register.
+  locations->SetOut(Location::RequiresRegister());
+}
+
+void InstructionCodeGeneratorARM64Sve::VisitVecPredCondition(HVecPredCondition* instruction) {
+  // Instruction is not predicated, see nodes_vector.h
+  DCHECK(!instruction->IsPredicated());
+  Register reg = OutputRegister(instruction);
+  // Currently VecPredCondition is only used as part of vectorized loop check condition
+  // evaluation.
+  DCHECK(instruction->GetPCondKind() == HVecPredCondition::PCondKind::kNFirst);
+  __ Cset(reg, pl);
+}
+
+Location InstructionCodeGeneratorARM64Sve::AllocateSIMDScratchLocation(
+    vixl::aarch64::UseScratchRegisterScope* scope) {
+  return LocationFrom(scope->AcquireZ());
+}
+
+void InstructionCodeGeneratorARM64Sve::FreeSIMDScratchLocation(Location loc,
+    vixl::aarch64::UseScratchRegisterScope* scope) {
+  scope->Release(ZRegisterFrom(loc));
+}
+
+void InstructionCodeGeneratorARM64Sve::LoadSIMDRegFromStack(Location destination,
+                                                            Location source) {
+  __ Ldr(ZRegisterFrom(destination), SveStackOperandFrom(source));
+}
+
+void InstructionCodeGeneratorARM64Sve::MoveSIMDRegToSIMDReg(Location destination,
+                                                            Location source) {
+  __ Mov(ZRegisterFrom(destination), ZRegisterFrom(source));
+}
+
+void InstructionCodeGeneratorARM64Sve::MoveToSIMDStackSlot(Location destination,
+                                                           Location source) {
+  DCHECK(destination.IsSIMDStackSlot());
+
+  if (source.IsFpuRegister()) {
+    __ Str(ZRegisterFrom(source), SveStackOperandFrom(destination));
+  } else {
+    DCHECK(source.IsSIMDStackSlot());
+    UseScratchRegisterScope temps(GetVIXLAssembler());
+    if (GetVIXLAssembler()->GetScratchVRegisterList()->IsEmpty()) {
+      // Very rare situation, only when there are cycles in ParallelMoveResolver graph.
+      const Register temp = temps.AcquireX();
+      DCHECK_EQ(codegen_->GetSIMDRegisterWidth() % kArm64WordSize, 0u);
+      // Emit a number of LDR/STR (XRegister, 64-bit) to cover the whole SIMD register size
+      // when copying a stack slot.
+      for (size_t offset = 0, e = codegen_->GetSIMDRegisterWidth();
+           offset < e;
+           offset += kArm64WordSize) {
+        __ Ldr(temp, MemOperand(sp, source.GetStackIndex() + offset));
+        __ Str(temp, MemOperand(sp, destination.GetStackIndex() + offset));
+      }
+    } else {
+      const ZRegister temp = temps.AcquireZ();
+      __ Ldr(temp, SveStackOperandFrom(source));
+      __ Str(temp, SveStackOperandFrom(destination));
+    }
+  }
+}
+
+template <bool is_save>
+void SaveRestoreLiveRegistersHelperSveImpl(CodeGeneratorARM64* codegen,
+                                           LocationSummary* locations,
+                                           int64_t spill_offset) {
+  const uint32_t core_spills = codegen->GetSlowPathSpills(locations, /* core_registers= */ true);
+  const uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers= */ false);
+  DCHECK(helpers::ArtVixlRegCodeCoherentForRegSet(core_spills,
+                                                  codegen->GetNumberOfCoreRegisters(),
+                                                  fp_spills,
+                                                  codegen->GetNumberOfFloatingPointRegisters()));
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  Register base = masm->StackPointer();
+
+  CPURegList core_list = CPURegList(CPURegister::kRegister, kXRegSize, core_spills);
+  int64_t core_spill_size = core_list.GetTotalSizeInBytes();
+  int64_t fp_spill_offset = spill_offset + core_spill_size;
+
+  if (codegen->GetGraph()->HasSIMD()) {
+    if (is_save) {
+      masm->StoreCPURegList(core_list, MemOperand(base, spill_offset));
+    } else {
+      masm->LoadCPURegList(core_list, MemOperand(base, spill_offset));
+    }
+    codegen->GetAssembler()->SaveRestoreZRegisterList<is_save>(fp_spills, fp_spill_offset);
+    return;
+  }
+
+  // Case when we only need to restore D-registers.
+  DCHECK(!codegen->GetGraph()->HasSIMD());
+  DCHECK_LE(codegen->GetSlowPathFPWidth(), kDRegSizeInBytes);
+  CPURegList fp_list = CPURegList(CPURegister::kVRegister, kDRegSize, fp_spills);
+  if (is_save) {
+    masm->StoreCPURegList(core_list, MemOperand(base, spill_offset));
+    masm->StoreCPURegList(fp_list, MemOperand(base, fp_spill_offset));
+  } else {
+    masm->LoadCPURegList(core_list, MemOperand(base, spill_offset));
+    masm->LoadCPURegList(fp_list, MemOperand(base, fp_spill_offset));
+  }
+}
+
+void InstructionCodeGeneratorARM64Sve::SaveLiveRegistersHelper(LocationSummary* locations,
+                                                               int64_t spill_offset) {
+  SaveRestoreLiveRegistersHelperSveImpl</* is_save= */ true>(codegen_, locations, spill_offset);
+}
+
+void InstructionCodeGeneratorARM64Sve::RestoreLiveRegistersHelper(LocationSummary* locations,
+                                                                  int64_t spill_offset) {
+  SaveRestoreLiveRegistersHelperSveImpl</* is_save= */ false>(codegen_, locations, spill_offset);
+}
+
+#undef __
+
+}  // namespace arm64
+}  // namespace art
diff --git a/compiler/optimizing/code_generator_vector_arm_vixl.cc b/compiler/optimizing/code_generator_vector_arm_vixl.cc
index b092961..33f2491 100644
--- a/compiler/optimizing/code_generator_vector_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_vector_arm_vixl.cc
@@ -1048,6 +1048,36 @@
   }
 }
 
+void LocationsBuilderARMVIXL::VisitVecPredSetAll(HVecPredSetAll* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARMVIXL::VisitVecPredSetAll(HVecPredSetAll* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderARMVIXL::VisitVecPredWhile(HVecPredWhile* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARMVIXL::VisitVecPredWhile(HVecPredWhile* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderARMVIXL::VisitVecPredCondition(HVecPredCondition* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorARMVIXL::VisitVecPredCondition(HVecPredCondition* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
 #undef __
 
 }  // namespace arm
diff --git a/compiler/optimizing/code_generator_vector_x86.cc b/compiler/optimizing/code_generator_vector_x86.cc
index 1390af2..9c837dd 100644
--- a/compiler/optimizing/code_generator_vector_x86.cc
+++ b/compiler/optimizing/code_generator_vector_x86.cc
@@ -1381,6 +1381,36 @@
   }
 }
 
+void LocationsBuilderX86::VisitVecPredSetAll(HVecPredSetAll* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorX86::VisitVecPredSetAll(HVecPredSetAll* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderX86::VisitVecPredWhile(HVecPredWhile* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorX86::VisitVecPredWhile(HVecPredWhile* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderX86::VisitVecPredCondition(HVecPredCondition* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorX86::VisitVecPredCondition(HVecPredCondition* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
 #undef __
 
 }  // namespace x86
diff --git a/compiler/optimizing/code_generator_vector_x86_64.cc b/compiler/optimizing/code_generator_vector_x86_64.cc
index 7fac44d..330bf76 100644
--- a/compiler/optimizing/code_generator_vector_x86_64.cc
+++ b/compiler/optimizing/code_generator_vector_x86_64.cc
@@ -1354,6 +1354,36 @@
   }
 }
 
+void LocationsBuilderX86_64::VisitVecPredSetAll(HVecPredSetAll* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorX86_64::VisitVecPredSetAll(HVecPredSetAll* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderX86_64::VisitVecPredWhile(HVecPredWhile* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorX86_64::VisitVecPredWhile(HVecPredWhile* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void LocationsBuilderX86_64::VisitVecPredCondition(HVecPredCondition* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
+void InstructionCodeGeneratorX86_64::VisitVecPredCondition(HVecPredCondition* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+  UNREACHABLE();
+}
+
 #undef __
 
 }  // namespace x86_64
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index ed1a536..4fc29fc 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -16,6 +16,7 @@
 
 #include "code_generator_x86.h"
 
+#include "arch/x86/jni_frame_x86.h"
 #include "art_method-inl.h"
 #include "class_table.h"
 #include "code_generator_utils.h"
@@ -25,6 +26,7 @@
 #include "gc/accounting/card_table.h"
 #include "gc/space/image_space.h"
 #include "heap_poisoning.h"
+#include "interpreter/mterp/nterp.h"
 #include "intrinsics.h"
 #include "intrinsics_x86.h"
 #include "jit/profiling_info.h"
@@ -32,6 +34,7 @@
 #include "lock_word.h"
 #include "mirror/array-inl.h"
 #include "mirror/class-inl.h"
+#include "mirror/var_handle.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread.h"
 #include "utils/assembler.h"
@@ -288,8 +291,13 @@
       DCHECK(IsSameDexFile(cls_->GetDexFile(), x86_codegen->GetGraph()->GetDexFile()));
       dex::TypeIndex type_index = cls_->GetTypeIndex();
       __ movl(calling_convention.GetRegisterAt(0), Immediate(type_index.index_));
-      x86_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
-      CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+      if (cls_->NeedsAccessCheck()) {
+        CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>();
+        x86_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this);
+      } else {
+        CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+        x86_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
+      }
       // If we also must_do_clinit, the resolved type is now in the correct register.
     } else {
       DCHECK(must_do_clinit);
@@ -481,6 +489,7 @@
     DCHECK(locations->CanCall());
     DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(ref_reg)) << ref_reg;
     DCHECK(instruction_->IsInstanceFieldGet() ||
+           instruction_->IsPredicatedInstanceFieldGet() ||
            instruction_->IsStaticFieldGet() ||
            instruction_->IsArrayGet() ||
            instruction_->IsArraySet() ||
@@ -488,8 +497,7 @@
            instruction_->IsLoadString() ||
            instruction_->IsInstanceOf() ||
            instruction_->IsCheckCast() ||
-           (instruction_->IsInvokeVirtual() && instruction_->GetLocations()->Intrinsified()) ||
-           (instruction_->IsInvokeStaticOrDirect() && instruction_->GetLocations()->Intrinsified()))
+           (instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
         << "Unexpected instruction in read barrier marking slow path: "
         << instruction_->DebugName();
 
@@ -568,11 +576,20 @@
     DCHECK(locations->CanCall());
     DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(ref_reg)) << ref_reg;
     // This slow path is only used by the UnsafeCASObject intrinsic.
-    DCHECK((instruction_->IsInvokeVirtual() && instruction_->GetLocations()->Intrinsified()))
+    DCHECK((instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
         << "Unexpected instruction in read barrier marking and field updating slow path: "
         << instruction_->DebugName();
     DCHECK(instruction_->GetLocations()->Intrinsified());
-    DCHECK_EQ(instruction_->AsInvoke()->GetIntrinsic(), Intrinsics::kUnsafeCASObject);
+    Intrinsics intrinsic = instruction_->AsInvoke()->GetIntrinsic();
+    static constexpr auto kVarHandleCAS = mirror::VarHandle::AccessModeTemplate::kCompareAndSet;
+    static constexpr auto kVarHandleGetAndSet =
+        mirror::VarHandle::AccessModeTemplate::kGetAndUpdate;
+    static constexpr auto kVarHandleCAX =
+        mirror::VarHandle::AccessModeTemplate::kCompareAndExchange;
+    DCHECK(intrinsic == Intrinsics::kUnsafeCASObject ||
+           mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) == kVarHandleCAS ||
+           mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) == kVarHandleGetAndSet ||
+           mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) == kVarHandleCAX);
 
     __ Bind(GetEntryLabel());
     if (unpoison_ref_before_marking_) {
@@ -733,11 +750,12 @@
     DCHECK(locations->CanCall());
     DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(reg_out));
     DCHECK(instruction_->IsInstanceFieldGet() ||
+           instruction_->IsPredicatedInstanceFieldGet() ||
            instruction_->IsStaticFieldGet() ||
            instruction_->IsArrayGet() ||
            instruction_->IsInstanceOf() ||
            instruction_->IsCheckCast() ||
-           (instruction_->IsInvokeVirtual() && instruction_->GetLocations()->Intrinsified()))
+           (instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
         << "Unexpected instruction in read barrier for heap reference slow path: "
         << instruction_->DebugName();
 
@@ -1045,8 +1063,11 @@
       method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      boot_image_jni_entrypoint_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       jit_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       jit_class_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -1079,6 +1100,7 @@
       reg = kMethodRegisterArgument;
     } else {
       __ pushl(EAX);
+      __ cfi().AdjustCFAOffset(4);
       __ movl(EAX, Address(ESP, kX86WordSize));
     }
     NearLabel overflow;
@@ -1090,27 +1112,30 @@
     __ Bind(&overflow);
     if (!is_frame_entry) {
       __ popl(EAX);
+      __ cfi().AdjustCFAOffset(-4);
     }
   }
 
   if (GetGraph()->IsCompilingBaseline() && !Runtime::Current()->IsAotCompiler()) {
-    ScopedObjectAccess soa(Thread::Current());
-    ProfilingInfo* info = GetGraph()->GetArtMethod()->GetProfilingInfo(kRuntimePointerSize);
+    ScopedProfilingInfoUse spiu(
+        Runtime::Current()->GetJit(), GetGraph()->GetArtMethod(), Thread::Current());
+    ProfilingInfo* info = spiu.GetProfilingInfo();
     if (info != nullptr) {
       uint32_t address = reinterpret_cast32<uint32_t>(info);
       NearLabel done;
       if (HasEmptyFrame()) {
         CHECK(is_frame_entry);
         // Alignment
-        __ subl(ESP, Immediate(8));
-        __ cfi().AdjustCFAOffset(8);
+        IncreaseFrame(8);
         // We need a temporary. The stub also expects the method at bottom of stack.
         __ pushl(EAX);
         __ cfi().AdjustCFAOffset(4);
         __ movl(EAX, Immediate(address));
         __ addw(Address(EAX, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()),
                 Immediate(1));
-        __ j(kCarryClear, &done);
+        __ andw(Address(EAX, ProfilingInfo::BaselineHotnessCountOffset().Int32Value()),
+                Immediate(interpreter::kTieredHotnessMask));
+        __ j(kNotZero, &done);
         GenerateInvokeRuntime(
             GetThreadOffset<kX86PointerSize>(kQuickCompileOptimized).Int32Value());
         __ Bind(&done);
@@ -1118,8 +1143,7 @@
         // code easier to reason about.
         __ popl(EAX);
         __ cfi().AdjustCFAOffset(-4);
-        __ addl(ESP, Immediate(8));
-        __ cfi().AdjustCFAOffset(-8);
+        DecreaseFrame(8);
       } else {
         if (!RequiresCurrentMethod()) {
           CHECK(is_frame_entry);
@@ -1166,8 +1190,7 @@
     }
 
     int adjust = GetFrameSize() - FrameEntrySpillSize();
-    __ subl(ESP, Immediate(adjust));
-    __ cfi().AdjustCFAOffset(adjust);
+    IncreaseFrame(adjust);
     // Save the current method if we need it. Note that we do not
     // do this in HCurrentMethod, as the instruction might have been removed
     // in the SSA graph.
@@ -1188,8 +1211,7 @@
   __ cfi().RememberState();
   if (!HasEmptyFrame()) {
     int adjust = GetFrameSize() - FrameEntrySpillSize();
-    __ addl(ESP, Immediate(adjust));
-    __ cfi().AdjustCFAOffset(-adjust);
+    DecreaseFrame(adjust);
 
     for (size_t i = 0; i < arraysize(kCoreCalleeSaves); ++i) {
       Register reg = kCoreCalleeSaves[i];
@@ -1300,6 +1322,34 @@
   return Location::NoLocation();
 }
 
+Location CriticalNativeCallingConventionVisitorX86::GetNextLocation(DataType::Type type) {
+  DCHECK_NE(type, DataType::Type::kReference);
+
+  Location location;
+  if (DataType::Is64BitType(type)) {
+    location = Location::DoubleStackSlot(stack_offset_);
+    stack_offset_ += 2 * kFramePointerSize;
+  } else {
+    location = Location::StackSlot(stack_offset_);
+    stack_offset_ += kFramePointerSize;
+  }
+  if (for_register_allocation_) {
+    location = Location::Any();
+  }
+  return location;
+}
+
+Location CriticalNativeCallingConventionVisitorX86::GetReturnLocation(DataType::Type type) const {
+  // We perform conversion to the managed ABI return register after the call if needed.
+  InvokeDexCallingConventionVisitorX86 dex_calling_convention;
+  return dex_calling_convention.GetReturnLocation(type);
+}
+
+Location CriticalNativeCallingConventionVisitorX86::GetMethodLocation() const {
+  // Pass the method in the hidden argument EAX.
+  return Location::RegisterLocation(EAX);
+}
+
 void CodeGeneratorX86::Move32(Location destination, Location source) {
   if (source.Equals(destination)) {
     return;
@@ -1309,6 +1359,9 @@
       __ movl(destination.AsRegister<Register>(), source.AsRegister<Register>());
     } else if (source.IsFpuRegister()) {
       __ movd(destination.AsRegister<Register>(), source.AsFpuRegister<XmmRegister>());
+    } else if (source.IsConstant()) {
+      int32_t value = GetInt32ValueOf(source.GetConstant());
+      __ movl(destination.AsRegister<Register>(), Immediate(value));
     } else {
       DCHECK(source.IsStackSlot());
       __ movl(destination.AsRegister<Register>(), Address(ESP, source.GetStackIndex()));
@@ -1372,13 +1425,14 @@
       __ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, source.GetStackIndex()));
     } else if (source.IsRegisterPair()) {
       size_t elem_size = DataType::Size(DataType::Type::kInt32);
-      // Create stack space for 2 elements.
-      __ subl(ESP, Immediate(2 * elem_size));
-      __ movl(Address(ESP, 0), source.AsRegisterPairLow<Register>());
-      __ movl(Address(ESP, elem_size), source.AsRegisterPairHigh<Register>());
+      // Push the 2 source registers to the stack.
+      __ pushl(source.AsRegisterPairHigh<Register>());
+      __ cfi().AdjustCFAOffset(elem_size);
+      __ pushl(source.AsRegisterPairLow<Register>());
+      __ cfi().AdjustCFAOffset(elem_size);
       __ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, 0));
       // And remove the temporary stack space we allocated.
-      __ addl(ESP, Immediate(2 * elem_size));
+      DecreaseFrame(2 * elem_size);
     } else {
       LOG(FATAL) << "Unimplemented";
     }
@@ -1411,6 +1465,146 @@
   }
 }
 
+static Address CreateAddress(Register base,
+                             Register index = Register::kNoRegister,
+                             ScaleFactor scale = TIMES_1,
+                             int32_t disp = 0) {
+  if (index == Register::kNoRegister) {
+    return Address(base, disp);
+  }
+
+  return Address(base, index, scale, disp);
+}
+
+void CodeGeneratorX86::LoadFromMemoryNoBarrier(DataType::Type dst_type,
+                                               Location dst,
+                                               Address src,
+                                               XmmRegister temp,
+                                               bool is_atomic_load) {
+  switch (dst_type) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+      __ movzxb(dst.AsRegister<Register>(), src);
+      break;
+    case DataType::Type::kInt8:
+      __ movsxb(dst.AsRegister<Register>(), src);
+      break;
+    case DataType::Type::kInt16:
+      __ movsxw(dst.AsRegister<Register>(), src);
+      break;
+    case DataType::Type::kUint16:
+      __ movzxw(dst.AsRegister<Register>(), src);
+      break;
+    case DataType::Type::kInt32:
+      __ movl(dst.AsRegister<Register>(), src);
+      break;
+    case DataType::Type::kInt64: {
+      if (is_atomic_load) {
+        __ movsd(temp, src);
+        __ movd(dst.AsRegisterPairLow<Register>(), temp);
+        __ psrlq(temp, Immediate(32));
+        __ movd(dst.AsRegisterPairHigh<Register>(), temp);
+      } else {
+        DCHECK_NE(src.GetBaseRegister(), dst.AsRegisterPairLow<Register>());
+        Address src_high = src.displaceBy(kX86WordSize);
+        __ movl(dst.AsRegisterPairLow<Register>(), src);
+        __ movl(dst.AsRegisterPairHigh<Register>(), src_high);
+      }
+      break;
+    }
+    case DataType::Type::kFloat32:
+      __ movss(dst.AsFpuRegister<XmmRegister>(), src);
+      break;
+    case DataType::Type::kFloat64:
+      __ movsd(dst.AsFpuRegister<XmmRegister>(), src);
+      break;
+    case DataType::Type::kReference:
+      __ movl(dst.AsRegister<Register>(), src);
+      __ MaybeUnpoisonHeapReference(dst.AsRegister<Register>());
+      break;
+    default:
+      LOG(FATAL) << "Unreachable type " << dst_type;
+  }
+}
+
+void CodeGeneratorX86::MoveToMemory(DataType::Type src_type,
+                                    Location src,
+                                    Register dst_base,
+                                    Register dst_index,
+                                    ScaleFactor dst_scale,
+                                    int32_t dst_disp) {
+  DCHECK(dst_base != Register::kNoRegister);
+  Address dst = CreateAddress(dst_base, dst_index, dst_scale, dst_disp);
+
+  switch (src_type) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8: {
+      if (src.IsConstant()) {
+        __ movb(dst, Immediate(CodeGenerator::GetInt8ValueOf(src.GetConstant())));
+      } else {
+        __ movb(dst, src.AsRegister<ByteRegister>());
+      }
+      break;
+    }
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16: {
+      if (src.IsConstant()) {
+        __ movw(dst, Immediate(CodeGenerator::GetInt16ValueOf(src.GetConstant())));
+      } else {
+        __ movw(dst, src.AsRegister<Register>());
+      }
+      break;
+    }
+    case DataType::Type::kUint32:
+    case DataType::Type::kInt32: {
+      if (src.IsConstant()) {
+        int32_t v = CodeGenerator::GetInt32ValueOf(src.GetConstant());
+        __ movl(dst, Immediate(v));
+      } else {
+        __ movl(dst, src.AsRegister<Register>());
+      }
+      break;
+    }
+    case DataType::Type::kUint64:
+    case DataType::Type::kInt64: {
+      Address dst_next_4_bytes = CreateAddress(dst_base, dst_index, dst_scale, dst_disp + 4);
+      if (src.IsConstant()) {
+        int64_t v = CodeGenerator::GetInt64ValueOf(src.GetConstant());
+        __ movl(dst, Immediate(Low32Bits(v)));
+        __ movl(dst_next_4_bytes, Immediate(High32Bits(v)));
+      } else {
+        __ movl(dst, src.AsRegisterPairLow<Register>());
+        __ movl(dst_next_4_bytes, src.AsRegisterPairHigh<Register>());
+      }
+      break;
+    }
+    case DataType::Type::kFloat32: {
+      if (src.IsConstant()) {
+        int32_t v = CodeGenerator::GetInt32ValueOf(src.GetConstant());
+        __ movl(dst, Immediate(v));
+      } else {
+        __ movss(dst, src.AsFpuRegister<XmmRegister>());
+      }
+      break;
+    }
+    case DataType::Type::kFloat64: {
+      Address dst_next_4_bytes = CreateAddress(dst_base, dst_index, dst_scale, dst_disp + 4);
+      if (src.IsConstant()) {
+        int64_t v = CodeGenerator::GetInt64ValueOf(src.GetConstant());
+        __ movl(dst, Immediate(Low32Bits(v)));
+        __ movl(dst_next_4_bytes, Immediate(High32Bits(v)));
+      } else {
+        __ movsd(dst, src.AsFpuRegister<XmmRegister>());
+      }
+      break;
+    }
+    case DataType::Type::kVoid:
+    case DataType::Type::kReference:
+      LOG(FATAL) << "Unreachable type " << src_type;
+  }
+}
+
 void CodeGeneratorX86::MoveConstant(Location location, int32_t value) {
   DCHECK(location.IsRegister());
   __ movl(location.AsRegister<Register>(), Immediate(value));
@@ -1939,6 +2133,16 @@
   // MaybeRecordNativeDebugInfo is already called implicitly in CodeGenerator::Compile.
 }
 
+void CodeGeneratorX86::IncreaseFrame(size_t adjustment) {
+  __ subl(ESP, Immediate(adjustment));
+  __ cfi().AdjustCFAOffset(adjustment);
+}
+
+void CodeGeneratorX86::DecreaseFrame(size_t adjustment) {
+  __ addl(ESP, Immediate(adjustment));
+  __ cfi().AdjustCFAOffset(-adjustment);
+}
+
 void CodeGeneratorX86::GenerateNop() {
   __ nop();
 }
@@ -2286,9 +2490,15 @@
     return;
   }
 
-  HandleInvoke(invoke);
+  if (invoke->GetCodePtrLocation() == CodePtrLocation::kCallCriticalNative) {
+    CriticalNativeCallingConventionVisitorX86 calling_convention_visitor(
+        /*for_register_allocation=*/ true);
+    CodeGenerator::CreateCommonInvokeLocationSummary(invoke, &calling_convention_visitor);
+  } else {
+    HandleInvoke(invoke);
+  }
 
-  // For PC-relative dex cache the invoke has an extra input, the PC-relative address base.
+  // For PC-relative load kinds the invoke has an extra input, the PC-relative address base.
   if (invoke->HasPcRelativeMethodLoadKind()) {
     invoke->GetLocations()->SetInAt(invoke->GetSpecialInputIndex(), Location::RequiresRegister());
   }
@@ -2357,6 +2567,16 @@
     // Add one temporary for inline cache update.
     invoke->GetLocations()->AddTemp(Location::RegisterLocation(EBP));
   }
+
+  // For PC-relative load kinds the invoke has an extra input, the PC-relative address base.
+  if (IsPcRelativeMethodLoadKind(invoke->GetHiddenArgumentLoadKind())) {
+    invoke->GetLocations()->SetInAt(invoke->GetSpecialInputIndex(), Location::RequiresRegister());
+  }
+
+  if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive) {
+    invoke->GetLocations()->SetInAt(invoke->GetNumberOfArguments() - 1,
+                                    Location::RequiresRegister());
+  }
 }
 
 void CodeGeneratorX86::MaybeGenerateInlineCacheCheck(HInstruction* instruction, Register klass) {
@@ -2368,8 +2588,9 @@
       GetGraph()->IsCompilingBaseline() &&
       !Runtime::Current()->IsAotCompiler()) {
     DCHECK(!instruction->GetEnvironment()->IsFromInlinedInvoke());
-    ScopedObjectAccess soa(Thread::Current());
-    ProfilingInfo* info = GetGraph()->GetArtMethod()->GetProfilingInfo(kRuntimePointerSize);
+    ScopedProfilingInfoUse spiu(
+        Runtime::Current()->GetJit(), GetGraph()->GetArtMethod(), Thread::Current());
+    ProfilingInfo* info = spiu.GetProfilingInfo();
     if (info != nullptr) {
       InlineCache* cache = info->GetInlineCache(instruction->GetDexPc());
       uint32_t address = reinterpret_cast32<uint32_t>(cache);
@@ -2400,8 +2621,12 @@
   // Set the hidden argument. This is safe to do this here, as XMM7
   // won't be modified thereafter, before the `call` instruction.
   DCHECK_EQ(XMM7, hidden_reg);
-  __ movl(temp, Immediate(invoke->GetDexMethodIndex()));
-  __ movd(hidden_reg, temp);
+  if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive) {
+    __ movd(hidden_reg, locations->InAt(invoke->GetNumberOfArguments() - 1).AsRegister<Register>());
+  } else if (invoke->GetHiddenArgumentLoadKind() != MethodLoadKind::kRuntimeCall) {
+    codegen_->LoadMethod(invoke->GetHiddenArgumentLoadKind(), locations->GetTemp(0), invoke);
+    __ movd(hidden_reg, temp);
+  }
 
   if (receiver.IsStackSlot()) {
     __ movl(temp, Address(ESP, receiver.GetStackIndex()));
@@ -2430,6 +2655,11 @@
   uint32_t method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement(
       invoke->GetImtIndex(), kX86PointerSize));
   __ movl(temp, Address(temp, method_offset));
+  if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRuntimeCall) {
+    // We pass the method from the IMT in case of a conflict. This will ensure
+    // we go into the runtime to resolve the actual method.
+    __ movd(hidden_reg, temp);
+  }
   // call temp->GetEntryPoint();
   __ call(Address(temp,
                   ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86PointerSize).Int32Value()));
@@ -2439,10 +2669,17 @@
 }
 
 void LocationsBuilderX86::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
+  IntrinsicLocationsBuilderX86 intrinsic(codegen_);
+  if (intrinsic.TryDispatch(invoke)) {
+    return;
+  }
   HandleInvoke(invoke);
 }
 
 void InstructionCodeGeneratorX86::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
+  if (TryGenerateIntrinsicCode(invoke, codegen_)) {
+    return;
+  }
   codegen_->GenerateInvokePolymorphicCall(invoke);
 }
 
@@ -2988,7 +3225,7 @@
           // TODO: enhance register allocator to ask for stack temporaries.
           if (!in.IsDoubleStackSlot() || !out.IsStackSlot()) {
             adjustment = DataType::Size(DataType::Type::kInt64);
-            __ subl(ESP, Immediate(adjustment));
+            codegen_->IncreaseFrame(adjustment);
           }
 
           // Load the value to the FP stack, using temporaries if needed.
@@ -3004,7 +3241,7 @@
 
           // Remove the temporary stack space we allocated.
           if (adjustment != 0) {
-            __ addl(ESP, Immediate(adjustment));
+            codegen_->DecreaseFrame(adjustment);
           }
           break;
         }
@@ -3038,7 +3275,7 @@
           // TODO: enhance register allocator to ask for stack temporaries.
           if (!in.IsDoubleStackSlot() || !out.IsDoubleStackSlot()) {
             adjustment = DataType::Size(DataType::Type::kInt64);
-            __ subl(ESP, Immediate(adjustment));
+            codegen_->IncreaseFrame(adjustment);
           }
 
           // Load the value to the FP stack, using temporaries if needed.
@@ -3054,7 +3291,7 @@
 
           // Remove the temporary stack space we allocated.
           if (adjustment != 0) {
-            __ addl(ESP, Immediate(adjustment));
+            codegen_->DecreaseFrame(adjustment);
           }
           break;
         }
@@ -3550,7 +3787,7 @@
 
   // Create stack space for 2 elements.
   // TODO: enhance register allocator to ask for stack temporaries.
-  __ subl(ESP, Immediate(2 * elem_size));
+  codegen_->IncreaseFrame(2 * elem_size);
 
   // Load the values to the FP stack in reverse order, using temporaries if needed.
   const bool is_wide = !is_float;
@@ -3590,7 +3827,7 @@
   }
 
   // And remove the temporary stack space we allocated.
-  __ addl(ESP, Immediate(2 * elem_size));
+  codegen_->DecreaseFrame(2 * elem_size);
 }
 
 
@@ -4932,9 +5169,18 @@
   return desired_dispatch_info;
 }
 
+Register CodeGeneratorX86::GetInvokeExtraParameter(HInvoke* invoke, Register temp) {
+  if (invoke->IsInvokeStaticOrDirect()) {
+    return GetInvokeStaticOrDirectExtraParameter(invoke->AsInvokeStaticOrDirect(), temp);
+  }
+  DCHECK(invoke->IsInvokeInterface());
+  Location location =
+      invoke->GetLocations()->InAt(invoke->AsInvokeInterface()->GetSpecialInputIndex());
+  return location.AsRegister<Register>();
+}
+
 Register CodeGeneratorX86::GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke,
                                                                  Register temp) {
-  DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
   Location location = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
   if (!invoke->GetLocations()->Intrinsified()) {
     return location.AsRegister<Register>();
@@ -4958,66 +5204,149 @@
   return location.AsRegister<Register>();
 }
 
+void CodeGeneratorX86::LoadMethod(MethodLoadKind load_kind, Location temp, HInvoke* invoke) {
+  switch (load_kind) {
+    case MethodLoadKind::kBootImageLinkTimePcRelative: {
+      DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
+      Register base_reg = GetInvokeExtraParameter(invoke, temp.AsRegister<Register>());
+      __ leal(temp.AsRegister<Register>(),
+              Address(base_reg, CodeGeneratorX86::kPlaceholder32BitOffset));
+      RecordBootImageMethodPatch(invoke);
+      break;
+    }
+    case MethodLoadKind::kBootImageRelRo: {
+      size_t index = invoke->IsInvokeInterface()
+          ? invoke->AsInvokeInterface()->GetSpecialInputIndex()
+          : invoke->AsInvokeStaticOrDirect()->GetSpecialInputIndex();
+      Register base_reg = GetInvokeExtraParameter(invoke, temp.AsRegister<Register>());
+      __ movl(temp.AsRegister<Register>(), Address(base_reg, kPlaceholder32BitOffset));
+      RecordBootImageRelRoPatch(
+          invoke->InputAt(index)->AsX86ComputeBaseMethodAddress(),
+          GetBootImageOffset(invoke));
+      break;
+    }
+    case MethodLoadKind::kBssEntry: {
+      Register base_reg = GetInvokeExtraParameter(invoke, temp.AsRegister<Register>());
+      __ movl(temp.AsRegister<Register>(), Address(base_reg, kPlaceholder32BitOffset));
+      RecordMethodBssEntryPatch(invoke);
+      // No need for memory fence, thanks to the x86 memory model.
+      break;
+    }
+    case MethodLoadKind::kJitDirectAddress: {
+      __ movl(temp.AsRegister<Register>(),
+              Immediate(reinterpret_cast32<uint32_t>(invoke->GetResolvedMethod())));
+      break;
+    }
+    case MethodLoadKind::kRuntimeCall: {
+      // Test situation, don't do anything.
+      break;
+    }
+    default: {
+      LOG(FATAL) << "Load kind should have already been handled " << load_kind;
+      UNREACHABLE();
+    }
+  }
+}
+
 void CodeGeneratorX86::GenerateStaticOrDirectCall(
     HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
   Location callee_method = temp;  // For all kinds except kRecursive, callee will be in temp.
   switch (invoke->GetMethodLoadKind()) {
-    case HInvokeStaticOrDirect::MethodLoadKind::kStringInit: {
+    case MethodLoadKind::kStringInit: {
       // temp = thread->string_init_entrypoint
       uint32_t offset =
           GetThreadOffset<kX86PointerSize>(invoke->GetStringInitEntryPoint()).Int32Value();
       __ fs()->movl(temp.AsRegister<Register>(), Address::Absolute(offset));
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
-      callee_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
-      break;
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative: {
-      DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
-      Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke,
-                                                                temp.AsRegister<Register>());
-      __ leal(temp.AsRegister<Register>(), Address(base_reg, CodeGeneratorX86::kDummy32BitOffset));
-      RecordBootImageMethodPatch(invoke);
+    case MethodLoadKind::kRecursive: {
+      callee_method = invoke->GetLocations()->InAt(invoke->GetCurrentMethodIndex());
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
-      Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke,
-                                                                temp.AsRegister<Register>());
-      __ movl(temp.AsRegister<Register>(), Address(base_reg, kDummy32BitOffset));
-      RecordBootImageRelRoPatch(
-          invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress(),
-          GetBootImageOffset(invoke));
-      break;
-    }
-    case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
-      Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke,
-                                                                temp.AsRegister<Register>());
-      __ movl(temp.AsRegister<Register>(), Address(base_reg, kDummy32BitOffset));
-      RecordMethodBssEntryPatch(invoke);
-      // No need for memory fence, thanks to the x86 memory model.
-      break;
-    }
-    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
-      __ movl(temp.AsRegister<Register>(), Immediate(invoke->GetMethodAddress()));
-      break;
-    case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+    case MethodLoadKind::kRuntimeCall: {
       GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
       return;  // No code pointer retrieval; the runtime performs the call directly.
     }
+    case MethodLoadKind::kBootImageLinkTimePcRelative:
+      // For kCallCriticalNative we skip loading the method and do the call directly.
+      if (invoke->GetCodePtrLocation() == CodePtrLocation::kCallCriticalNative) {
+        break;
+      }
+      FALLTHROUGH_INTENDED;
+    default: {
+      LoadMethod(invoke->GetMethodLoadKind(), callee_method, invoke);
+    }
   }
 
   switch (invoke->GetCodePtrLocation()) {
-    case HInvokeStaticOrDirect::CodePtrLocation::kCallSelf:
+    case CodePtrLocation::kCallSelf:
       __ call(GetFrameEntryLabel());
+      RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
       break;
-    case HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod:
+    case CodePtrLocation::kCallCriticalNative: {
+      size_t out_frame_size =
+          PrepareCriticalNativeCall<CriticalNativeCallingConventionVisitorX86,
+                                    kNativeStackAlignment,
+                                    GetCriticalNativeDirectCallFrameSize>(invoke);
+      if (invoke->GetMethodLoadKind() == MethodLoadKind::kBootImageLinkTimePcRelative) {
+        DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
+        Register base_reg = GetInvokeExtraParameter(invoke, temp.AsRegister<Register>());
+        __ call(Address(base_reg, CodeGeneratorX86::kPlaceholder32BitOffset));
+        RecordBootImageJniEntrypointPatch(invoke);
+      } else {
+        // (callee_method + offset_of_jni_entry_point)()
+        __ call(Address(callee_method.AsRegister<Register>(),
+                        ArtMethod::EntryPointFromJniOffset(kX86PointerSize).Int32Value()));
+      }
+      RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+      if (out_frame_size == 0u && DataType::IsFloatingPointType(invoke->GetType())) {
+        // Create space for conversion.
+        out_frame_size = 8u;
+        IncreaseFrame(out_frame_size);
+      }
+      // Zero-/sign-extend or move the result when needed due to native and managed ABI mismatch.
+      switch (invoke->GetType()) {
+        case DataType::Type::kBool:
+          __ movzxb(EAX, AL);
+          break;
+        case DataType::Type::kInt8:
+          __ movsxb(EAX, AL);
+          break;
+        case DataType::Type::kUint16:
+          __ movzxw(EAX, EAX);
+          break;
+        case DataType::Type::kInt16:
+          __ movsxw(EAX, EAX);
+          break;
+        case DataType::Type::kFloat32:
+          __ fstps(Address(ESP, 0));
+          __ movss(XMM0, Address(ESP, 0));
+          break;
+        case DataType::Type::kFloat64:
+          __ fstpl(Address(ESP, 0));
+          __ movsd(XMM0, Address(ESP, 0));
+          break;
+        case DataType::Type::kInt32:
+        case DataType::Type::kInt64:
+        case DataType::Type::kVoid:
+          break;
+        default:
+          DCHECK(false) << invoke->GetType();
+          break;
+      }
+      if (out_frame_size != 0u) {
+        DecreaseFrame(out_frame_size);
+      }
+      break;
+    }
+    case CodePtrLocation::kCallArtMethod:
       // (callee_method + offset_of_quick_compiled_code)()
       __ call(Address(callee_method.AsRegister<Register>(),
                       ArtMethod::EntryPointFromQuickCompiledCodeOffset(
                           kX86PointerSize).Int32Value()));
+      RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
       break;
   }
-  RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
 
   DCHECK(!IsLeafMethod());
 }
@@ -5071,22 +5400,31 @@
   __ Bind(&boot_image_other_patches_.back().label);
 }
 
-void CodeGeneratorX86::RecordBootImageMethodPatch(HInvokeStaticOrDirect* invoke) {
-  DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
+void CodeGeneratorX86::RecordBootImageMethodPatch(HInvoke* invoke) {
+  size_t index = invoke->IsInvokeInterface()
+      ? invoke->AsInvokeInterface()->GetSpecialInputIndex()
+      : invoke->AsInvokeStaticOrDirect()->GetSpecialInputIndex();
   HX86ComputeBaseMethodAddress* method_address =
-      invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
+      invoke->InputAt(index)->AsX86ComputeBaseMethodAddress();
   boot_image_method_patches_.emplace_back(
-      method_address, invoke->GetTargetMethod().dex_file, invoke->GetTargetMethod().index);
+      method_address,
+      invoke->GetResolvedMethodReference().dex_file,
+      invoke->GetResolvedMethodReference().index);
   __ Bind(&boot_image_method_patches_.back().label);
 }
 
-void CodeGeneratorX86::RecordMethodBssEntryPatch(HInvokeStaticOrDirect* invoke) {
-  DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
+void CodeGeneratorX86::RecordMethodBssEntryPatch(HInvoke* invoke) {
+  size_t index = invoke->IsInvokeInterface()
+      ? invoke->AsInvokeInterface()->GetSpecialInputIndex()
+      : invoke->AsInvokeStaticOrDirect()->GetSpecialInputIndex();
+  DCHECK(IsSameDexFile(GetGraph()->GetDexFile(), *invoke->GetMethodReference().dex_file));
   HX86ComputeBaseMethodAddress* method_address =
-      invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
+      invoke->InputAt(index)->AsX86ComputeBaseMethodAddress();
   // Add the patch entry and bind its label at the end of the instruction.
   method_bss_entry_patches_.emplace_back(
-      method_address, &GetGraph()->GetDexFile(), invoke->GetDexMethodIndex());
+      method_address,
+      invoke->GetMethodReference().dex_file,
+      invoke->GetMethodReference().index);
   __ Bind(&method_bss_entry_patches_.back().label);
 }
 
@@ -5101,9 +5439,24 @@
 Label* CodeGeneratorX86::NewTypeBssEntryPatch(HLoadClass* load_class) {
   HX86ComputeBaseMethodAddress* method_address =
       load_class->InputAt(0)->AsX86ComputeBaseMethodAddress();
-  type_bss_entry_patches_.emplace_back(
+  ArenaDeque<X86PcRelativePatchInfo>* patches = nullptr;
+  switch (load_class->GetLoadKind()) {
+    case HLoadClass::LoadKind::kBssEntry:
+      patches = &type_bss_entry_patches_;
+      break;
+    case HLoadClass::LoadKind::kBssEntryPublic:
+      patches = &public_type_bss_entry_patches_;
+      break;
+    case HLoadClass::LoadKind::kBssEntryPackage:
+      patches = &package_type_bss_entry_patches_;
+      break;
+    default:
+      LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind();
+      UNREACHABLE();
+  }
+  patches->emplace_back(
       method_address, &load_class->GetDexFile(), load_class->GetTypeIndex().index_);
-  return &type_bss_entry_patches_.back().label;
+  return &patches->back().label;
 }
 
 void CodeGeneratorX86::RecordBootImageStringPatch(HLoadString* load_string) {
@@ -5122,29 +5475,37 @@
   return &string_bss_entry_patches_.back().label;
 }
 
+void CodeGeneratorX86::RecordBootImageJniEntrypointPatch(HInvokeStaticOrDirect* invoke) {
+  HX86ComputeBaseMethodAddress* method_address =
+      invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
+  boot_image_jni_entrypoint_patches_.emplace_back(
+      method_address,
+      invoke->GetResolvedMethodReference().dex_file,
+      invoke->GetResolvedMethodReference().index);
+  __ Bind(&boot_image_jni_entrypoint_patches_.back().label);
+}
+
 void CodeGeneratorX86::LoadBootImageAddress(Register reg,
                                             uint32_t boot_image_reference,
                                             HInvokeStaticOrDirect* invoke) {
   if (GetCompilerOptions().IsBootImage()) {
-    DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
     HX86ComputeBaseMethodAddress* method_address =
         invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
     DCHECK(method_address != nullptr);
     Register method_address_reg =
         invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex()).AsRegister<Register>();
-    __ leal(reg, Address(method_address_reg, CodeGeneratorX86::kDummy32BitOffset));
+    __ leal(reg, Address(method_address_reg, CodeGeneratorX86::kPlaceholder32BitOffset));
     RecordBootImageIntrinsicPatch(method_address, boot_image_reference);
   } else if (GetCompilerOptions().GetCompilePic()) {
-    DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
     HX86ComputeBaseMethodAddress* method_address =
         invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
     DCHECK(method_address != nullptr);
     Register method_address_reg =
         invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex()).AsRegister<Register>();
-    __ movl(reg, Address(method_address_reg, CodeGeneratorX86::kDummy32BitOffset));
+    __ movl(reg, Address(method_address_reg, CodeGeneratorX86::kPlaceholder32BitOffset));
     RecordBootImageRelRoPatch(method_address, boot_image_reference);
   } else {
-    DCHECK(Runtime::Current()->UseJitCompilation());
+    DCHECK(GetCompilerOptions().IsJitCompiler());
     gc::Heap* heap = Runtime::Current()->GetHeap();
     DCHECK(!heap->GetBootImageSpaces().empty());
     const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -5152,30 +5513,24 @@
   }
 }
 
-void CodeGeneratorX86::AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke,
-                                                    uint32_t boot_image_offset) {
-  DCHECK(invoke->IsStatic());
-  InvokeRuntimeCallingConvention calling_convention;
-  Register argument = calling_convention.GetRegisterAt(0);
+void CodeGeneratorX86::LoadIntrinsicDeclaringClass(Register reg, HInvokeStaticOrDirect* invoke) {
+  DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
   if (GetCompilerOptions().IsBootImage()) {
-    DCHECK_EQ(boot_image_offset, IntrinsicVisitor::IntegerValueOfInfo::kInvalidReference);
     // Load the class the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
-    DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
     HX86ComputeBaseMethodAddress* method_address =
         invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
     DCHECK(method_address != nullptr);
     Register method_address_reg =
         invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex()).AsRegister<Register>();
-    __ leal(argument, Address(method_address_reg, CodeGeneratorX86::kDummy32BitOffset));
-    MethodReference target_method = invoke->GetTargetMethod();
+    __ leal(reg, Address(method_address_reg, CodeGeneratorX86::kPlaceholder32BitOffset));
+    MethodReference target_method = invoke->GetResolvedMethodReference();
     dex::TypeIndex type_idx = target_method.dex_file->GetMethodId(target_method.index).class_idx_;
     boot_image_type_patches_.emplace_back(method_address, target_method.dex_file, type_idx.index_);
     __ Bind(&boot_image_type_patches_.back().label);
   } else {
-    LoadBootImageAddress(argument, boot_image_offset, invoke);
+    uint32_t boot_image_offset = GetBootImageOffsetOfIntrinsicDeclaringClass(invoke);
+    LoadBootImageAddress(reg, boot_image_offset, invoke);
   }
-  InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
-  CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
 }
 
 // The label points to the end of the "movl" or another instruction but the literal offset
@@ -5211,8 +5566,11 @@
       method_bss_entry_patches_.size() +
       boot_image_type_patches_.size() +
       type_bss_entry_patches_.size() +
+      public_type_bss_entry_patches_.size() +
+      package_type_bss_entry_patches_.size() +
       boot_image_string_patches_.size() +
       string_bss_entry_patches_.size() +
+      boot_image_jni_entrypoint_patches_.size() +
       boot_image_other_patches_.size();
   linker_patches->reserve(size);
   if (GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension()) {
@@ -5238,8 +5596,14 @@
       method_bss_entry_patches_, linker_patches);
   EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>(
       type_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>(
+      public_type_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>(
+      package_type_bss_entry_patches_, linker_patches);
   EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>(
       string_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeJniEntrypointPatch>(
+      boot_image_jni_entrypoint_patches_, linker_patches);
   DCHECK_EQ(size, linker_patches->size());
 }
 
@@ -5280,10 +5644,13 @@
 }
 
 void LocationsBuilderX86::HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info) {
-  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
+  DCHECK(instruction->IsInstanceFieldGet() ||
+         instruction->IsStaticFieldGet() ||
+         instruction->IsPredicatedInstanceFieldGet());
 
   bool object_field_get_with_read_barrier =
       kEmitCompilerReadBarrier && (instruction->GetType() == DataType::Type::kReference);
+  bool is_predicated = instruction->IsPredicatedInstanceFieldGet();
   LocationSummary* locations =
       new (GetGraph()->GetAllocator()) LocationSummary(instruction,
                                                        kEmitCompilerReadBarrier
@@ -5292,21 +5659,30 @@
   if (object_field_get_with_read_barrier && kUseBakerReadBarrier) {
     locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty());  // No caller-save registers.
   }
-  locations->SetInAt(0, Location::RequiresRegister());
-
+  // receiver_input
+  locations->SetInAt(is_predicated ? 1 : 0, Location::RequiresRegister());
+  if (is_predicated) {
+    if (DataType::IsFloatingPointType(instruction->GetType())) {
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+    } else {
+      locations->SetInAt(0, Location::RequiresRegister());
+    }
+  }
   if (DataType::IsFloatingPointType(instruction->GetType())) {
-    locations->SetOut(Location::RequiresFpuRegister());
+    locations->SetOut(is_predicated ? Location::SameAsFirstInput()
+                                    : Location::RequiresFpuRegister());
   } else {
     // The output overlaps in case of long: we don't want the low move
     // to overwrite the object's location.  Likewise, in the case of
     // an object field get with read barriers enabled, we do not want
     // the move to overwrite the object's location, as we need it to emit
     // the read barrier.
-    locations->SetOut(
-        Location::RequiresRegister(),
-        (object_field_get_with_read_barrier || instruction->GetType() == DataType::Type::kInt64) ?
-            Location::kOutputOverlap :
-            Location::kNoOutputOverlap);
+    locations->SetOut(is_predicated ? Location::SameAsFirstInput() : Location::RequiresRegister(),
+                      (object_field_get_with_read_barrier ||
+                       instruction->GetType() == DataType::Type::kInt64 ||
+                       is_predicated)
+                          ? Location::kOutputOverlap
+                          : Location::kNoOutputOverlap);
   }
 
   if (field_info.IsVolatile() && (field_info.GetFieldType() == DataType::Type::kInt64)) {
@@ -5320,10 +5696,12 @@
 
 void InstructionCodeGeneratorX86::HandleFieldGet(HInstruction* instruction,
                                                  const FieldInfo& field_info) {
-  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
+  DCHECK(instruction->IsInstanceFieldGet() ||
+         instruction->IsStaticFieldGet() ||
+         instruction->IsPredicatedInstanceFieldGet());
 
   LocationSummary* locations = instruction->GetLocations();
-  Location base_loc = locations->InAt(0);
+  Location base_loc = locations->InAt(instruction->IsPredicatedInstanceFieldGet() ? 1 : 0);
   Register base = base_loc.AsRegister<Register>();
   Location out = locations->Out();
   bool is_volatile = field_info.IsVolatile();
@@ -5478,18 +5856,16 @@
 }
 
 void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction,
-                                                 const FieldInfo& field_info,
+                                                 uint32_t value_index,
+                                                 DataType::Type field_type,
+                                                 Address field_addr,
+                                                 Register base,
+                                                 bool is_volatile,
                                                  bool value_can_be_null) {
-  DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
-
   LocationSummary* locations = instruction->GetLocations();
-  Register base = locations->InAt(0).AsRegister<Register>();
-  Location value = locations->InAt(1);
-  bool is_volatile = field_info.IsVolatile();
-  DataType::Type field_type = field_info.GetFieldType();
-  uint32_t offset = field_info.GetFieldOffset().Uint32Value();
+  Location value = locations->InAt(value_index);
   bool needs_write_barrier =
-      CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1));
+      CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(value_index));
 
   if (is_volatile) {
     codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
@@ -5501,17 +5877,20 @@
     case DataType::Type::kBool:
     case DataType::Type::kUint8:
     case DataType::Type::kInt8: {
-      __ movb(Address(base, offset), value.AsRegister<ByteRegister>());
+      if (value.IsConstant()) {
+        __ movb(field_addr, Immediate(CodeGenerator::GetInt8ValueOf(value.GetConstant())));
+      } else {
+        __ movb(field_addr, value.AsRegister<ByteRegister>());
+      }
       break;
     }
 
     case DataType::Type::kUint16:
     case DataType::Type::kInt16: {
       if (value.IsConstant()) {
-        __ movw(Address(base, offset),
-                Immediate(CodeGenerator::GetInt16ValueOf(value.GetConstant())));
+        __ movw(field_addr, Immediate(CodeGenerator::GetInt16ValueOf(value.GetConstant())));
       } else {
-        __ movw(Address(base, offset), value.AsRegister<Register>());
+        __ movw(field_addr, value.AsRegister<Register>());
       }
       break;
     }
@@ -5526,13 +5905,13 @@
         Register temp = locations->GetTemp(0).AsRegister<Register>();
         __ movl(temp, value.AsRegister<Register>());
         __ PoisonHeapReference(temp);
-        __ movl(Address(base, offset), temp);
+        __ movl(field_addr, temp);
       } else if (value.IsConstant()) {
         int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
-        __ movl(Address(base, offset), Immediate(v));
+        __ movl(field_addr, Immediate(v));
       } else {
         DCHECK(value.IsRegister()) << value;
-        __ movl(Address(base, offset), value.AsRegister<Register>());
+        __ movl(field_addr, value.AsRegister<Register>());
       }
       break;
     }
@@ -5544,17 +5923,17 @@
         __ movd(temp1, value.AsRegisterPairLow<Register>());
         __ movd(temp2, value.AsRegisterPairHigh<Register>());
         __ punpckldq(temp1, temp2);
-        __ movsd(Address(base, offset), temp1);
+        __ movsd(field_addr, temp1);
         codegen_->MaybeRecordImplicitNullCheck(instruction);
       } else if (value.IsConstant()) {
         int64_t v = CodeGenerator::GetInt64ValueOf(value.GetConstant());
-        __ movl(Address(base, offset), Immediate(Low32Bits(v)));
+        __ movl(field_addr, Immediate(Low32Bits(v)));
         codegen_->MaybeRecordImplicitNullCheck(instruction);
-        __ movl(Address(base, kX86WordSize + offset), Immediate(High32Bits(v)));
+        __ movl(field_addr.displaceBy(kX86WordSize), Immediate(High32Bits(v)));
       } else {
-        __ movl(Address(base, offset), value.AsRegisterPairLow<Register>());
+        __ movl(field_addr, value.AsRegisterPairLow<Register>());
         codegen_->MaybeRecordImplicitNullCheck(instruction);
-        __ movl(Address(base, kX86WordSize + offset), value.AsRegisterPairHigh<Register>());
+        __ movl(field_addr.displaceBy(kX86WordSize), value.AsRegisterPairHigh<Register>());
       }
       maybe_record_implicit_null_check_done = true;
       break;
@@ -5563,22 +5942,23 @@
     case DataType::Type::kFloat32: {
       if (value.IsConstant()) {
         int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
-        __ movl(Address(base, offset), Immediate(v));
+        __ movl(field_addr, Immediate(v));
       } else {
-        __ movss(Address(base, offset), value.AsFpuRegister<XmmRegister>());
+        __ movss(field_addr, value.AsFpuRegister<XmmRegister>());
       }
       break;
     }
 
     case DataType::Type::kFloat64: {
       if (value.IsConstant()) {
+        DCHECK(!is_volatile);
         int64_t v = CodeGenerator::GetInt64ValueOf(value.GetConstant());
-        __ movl(Address(base, offset), Immediate(Low32Bits(v)));
+        __ movl(field_addr, Immediate(Low32Bits(v)));
         codegen_->MaybeRecordImplicitNullCheck(instruction);
-        __ movl(Address(base, kX86WordSize + offset), Immediate(High32Bits(v)));
+        __ movl(field_addr.displaceBy(kX86WordSize), Immediate(High32Bits(v)));
         maybe_record_implicit_null_check_done = true;
       } else {
-        __ movsd(Address(base, offset), value.AsFpuRegister<XmmRegister>());
+        __ movsd(field_addr, value.AsFpuRegister<XmmRegister>());
       }
       break;
     }
@@ -5605,6 +5985,40 @@
   }
 }
 
+void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction,
+                                                 const FieldInfo& field_info,
+                                                 bool value_can_be_null) {
+  DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
+
+  LocationSummary* locations = instruction->GetLocations();
+  Register base = locations->InAt(0).AsRegister<Register>();
+  bool is_volatile = field_info.IsVolatile();
+  DataType::Type field_type = field_info.GetFieldType();
+  uint32_t offset = field_info.GetFieldOffset().Uint32Value();
+  bool is_predicated =
+      instruction->IsInstanceFieldSet() && instruction->AsInstanceFieldSet()->GetIsPredicatedSet();
+
+  Address field_addr(base, offset);
+
+  NearLabel pred_is_null;
+  if (is_predicated) {
+    __ testl(base, base);
+    __ j(kEqual, &pred_is_null);
+  }
+
+  HandleFieldSet(instruction,
+                 /* value_index= */ 1,
+                 field_type,
+                 field_addr,
+                 base,
+                 is_volatile,
+                 value_can_be_null);
+
+  if (is_predicated) {
+    __ Bind(&pred_is_null);
+  }
+}
+
 void LocationsBuilderX86::VisitStaticFieldGet(HStaticFieldGet* instruction) {
   HandleFieldGet(instruction, instruction->GetFieldInfo());
 }
@@ -5629,10 +6043,25 @@
   HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
 }
 
+void LocationsBuilderX86::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* instruction) {
+  HandleFieldGet(instruction, instruction->GetFieldInfo());
+}
+
 void LocationsBuilderX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
   HandleFieldGet(instruction, instruction->GetFieldInfo());
 }
 
+void InstructionCodeGeneratorX86::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* instruction) {
+  NearLabel finish;
+  LocationSummary* locations = instruction->GetLocations();
+  Register recv = locations->InAt(1).AsRegister<Register>();
+  __ testl(recv, recv);
+  __ j(kZero, &finish);
+  HandleFieldGet(instruction, instruction->GetFieldInfo());
+  __ Bind(&finish);
+}
 void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
   HandleFieldGet(instruction, instruction->GetFieldInfo());
 }
@@ -6365,24 +6794,43 @@
       __ movl(Address(ESP, destination.GetStackIndex()), source.AsRegister<Register>());
     }
   } else if (source.IsRegisterPair()) {
+    if (destination.IsRegisterPair()) {
+      __ movl(destination.AsRegisterPairLow<Register>(), source.AsRegisterPairLow<Register>());
+      DCHECK_NE(destination.AsRegisterPairLow<Register>(), source.AsRegisterPairHigh<Register>());
+      __ movl(destination.AsRegisterPairHigh<Register>(), source.AsRegisterPairHigh<Register>());
+    } else if (destination.IsFpuRegister()) {
       size_t elem_size = DataType::Size(DataType::Type::kInt32);
-      // Create stack space for 2 elements.
-      __ subl(ESP, Immediate(2 * elem_size));
-      __ movl(Address(ESP, 0), source.AsRegisterPairLow<Register>());
-      __ movl(Address(ESP, elem_size), source.AsRegisterPairHigh<Register>());
+      // Push the 2 source registers to the stack.
+      __ pushl(source.AsRegisterPairHigh<Register>());
+      __ cfi().AdjustCFAOffset(elem_size);
+      __ pushl(source.AsRegisterPairLow<Register>());
+      __ cfi().AdjustCFAOffset(elem_size);
+      // Load the destination register.
       __ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, 0));
       // And remove the temporary stack space we allocated.
-      __ addl(ESP, Immediate(2 * elem_size));
+      codegen_->DecreaseFrame(2 * elem_size);
+    } else {
+      DCHECK(destination.IsDoubleStackSlot());
+      __ movl(Address(ESP, destination.GetStackIndex()), source.AsRegisterPairLow<Register>());
+      __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
+              source.AsRegisterPairHigh<Register>());
+    }
   } else if (source.IsFpuRegister()) {
     if (destination.IsRegister()) {
       __ movd(destination.AsRegister<Register>(), source.AsFpuRegister<XmmRegister>());
     } else if (destination.IsFpuRegister()) {
       __ movaps(destination.AsFpuRegister<XmmRegister>(), source.AsFpuRegister<XmmRegister>());
     } else if (destination.IsRegisterPair()) {
-      XmmRegister src_reg = source.AsFpuRegister<XmmRegister>();
-      __ movd(destination.AsRegisterPairLow<Register>(), src_reg);
-      __ psrlq(src_reg, Immediate(32));
-      __ movd(destination.AsRegisterPairHigh<Register>(), src_reg);
+      size_t elem_size = DataType::Size(DataType::Type::kInt32);
+      // Create stack space for 2 elements.
+      codegen_->IncreaseFrame(2 * elem_size);
+      // Store the source register.
+      __ movsd(Address(ESP, 0), source.AsFpuRegister<XmmRegister>());
+      // And pop the values into destination registers.
+      __ popl(destination.AsRegisterPairLow<Register>());
+      __ cfi().AdjustCFAOffset(-elem_size);
+      __ popl(destination.AsRegisterPairHigh<Register>());
+      __ cfi().AdjustCFAOffset(-elem_size);
     } else if (destination.IsStackSlot()) {
       __ movss(Address(ESP, destination.GetStackIndex()), source.AsFpuRegister<XmmRegister>());
     } else if (destination.IsDoubleStackSlot()) {
@@ -6480,9 +6928,11 @@
           __ xorpd(dest, dest);
         } else {
           __ pushl(high);
+          __ cfi().AdjustCFAOffset(4);
           __ pushl(low);
+          __ cfi().AdjustCFAOffset(4);
           __ movsd(dest, Address(ESP, 0));
-          __ addl(ESP, Immediate(8));
+          codegen_->DecreaseFrame(8);
         }
       } else {
         DCHECK(destination.IsDoubleStackSlot()) << destination;
@@ -6519,11 +6969,11 @@
 
 void ParallelMoveResolverX86::Exchange128(XmmRegister reg, int mem) {
   size_t extra_slot = 4 * kX86WordSize;
-  __ subl(ESP, Immediate(extra_slot));
+  codegen_->IncreaseFrame(extra_slot);
   __ movups(Address(ESP, 0), XmmRegister(reg));
   ExchangeMemory(0, mem + extra_slot, 4);
   __ movups(XmmRegister(reg), Address(ESP, 0));
-  __ addl(ESP, Immediate(extra_slot));
+  codegen_->DecreaseFrame(extra_slot);
 }
 
 void ParallelMoveResolverX86::ExchangeMemory(int mem1, int mem2, int number_of_words) {
@@ -6630,11 +7080,13 @@
     case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadClass::LoadKind::kBootImageRelRo:
     case HLoadClass::LoadKind::kBssEntry:
-      DCHECK(!Runtime::Current()->UseJitCompilation());
+    case HLoadClass::LoadKind::kBssEntryPublic:
+    case HLoadClass::LoadKind::kBssEntryPackage:
+      DCHECK(!GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadClass::LoadKind::kJitBootImageAddress:
     case HLoadClass::LoadKind::kJitTableAddress:
-      DCHECK(Runtime::Current()->UseJitCompilation());
+      DCHECK(GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadClass::LoadKind::kRuntimeCall:
       break;
@@ -6653,7 +7105,9 @@
     DCHECK_EQ(calling_convention.GetRegisterAt(0), EAX);
     return;
   }
-  DCHECK(!cls->NeedsAccessCheck());
+  DCHECK_EQ(cls->NeedsAccessCheck(),
+            load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+                load_kind == HLoadClass::LoadKind::kBssEntryPackage);
 
   const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage();
   LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier)
@@ -6664,14 +7118,11 @@
     locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty());  // No caller-save registers.
   }
 
-  if (load_kind == HLoadClass::LoadKind::kReferrersClass ||
-      load_kind == HLoadClass::LoadKind::kBootImageLinkTimePcRelative ||
-      load_kind == HLoadClass::LoadKind::kBootImageRelRo ||
-      load_kind == HLoadClass::LoadKind::kBssEntry) {
+  if (load_kind == HLoadClass::LoadKind::kReferrersClass || cls->HasPcRelativeLoadKind()) {
     locations->SetInAt(0, Location::RequiresRegister());
   }
   locations->SetOut(Location::RequiresRegister());
-  if (load_kind == HLoadClass::LoadKind::kBssEntry) {
+  if (call_kind == LocationSummary::kCallOnSlowPath && cls->HasPcRelativeLoadKind()) {
     if (!kUseReadBarrier || kUseBakerReadBarrier) {
       // Rely on the type resolution and/or initialization to save everything.
       locations->SetCustomSlowPathCallerSaves(OneRegInReferenceOutSaveEverythingCallerSaves());
@@ -6699,7 +7150,9 @@
     codegen_->GenerateLoadClassRuntimeCall(cls);
     return;
   }
-  DCHECK(!cls->NeedsAccessCheck());
+  DCHECK_EQ(cls->NeedsAccessCheck(),
+            load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+                load_kind == HLoadClass::LoadKind::kBssEntryPackage);
 
   LocationSummary* locations = cls->GetLocations();
   Location out_loc = locations->Out();
@@ -6728,21 +7181,23 @@
              codegen_->GetCompilerOptions().IsBootImageExtension());
       DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
       Register method_address = locations->InAt(0).AsRegister<Register>();
-      __ leal(out, Address(method_address, CodeGeneratorX86::kDummy32BitOffset));
+      __ leal(out, Address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset));
       codegen_->RecordBootImageTypePatch(cls);
       break;
     }
     case HLoadClass::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       Register method_address = locations->InAt(0).AsRegister<Register>();
-      __ movl(out, Address(method_address, CodeGeneratorX86::kDummy32BitOffset));
+      __ movl(out, Address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset));
       codegen_->RecordBootImageRelRoPatch(cls->InputAt(0)->AsX86ComputeBaseMethodAddress(),
-                                          codegen_->GetBootImageOffset(cls));
+                                          CodeGenerator::GetBootImageOffset(cls));
       break;
     }
-    case HLoadClass::LoadKind::kBssEntry: {
+    case HLoadClass::LoadKind::kBssEntry:
+    case HLoadClass::LoadKind::kBssEntryPublic:
+    case HLoadClass::LoadKind::kBssEntryPackage: {
       Register method_address = locations->InAt(0).AsRegister<Register>();
-      Address address(method_address, CodeGeneratorX86::kDummy32BitOffset);
+      Address address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset);
       Label* fixup_label = codegen_->NewTypeBssEntryPatch(cls);
       GenerateGcRootFieldLoad(cls, out_loc, address, fixup_label, read_barrier_option);
       // No need for memory fence, thanks to the x86 memory model.
@@ -6757,7 +7212,7 @@
       break;
     }
     case HLoadClass::LoadKind::kJitTableAddress: {
-      Address address = Address::Absolute(CodeGeneratorX86::kDummy32BitOffset);
+      Address address = Address::Absolute(CodeGeneratorX86::kPlaceholder32BitOffset);
       Label* fixup_label = codegen_->NewJitRootClassPatch(
           cls->GetDexFile(), cls->GetTypeIndex(), cls->GetClass());
       // /* GcRoot<mirror::Class> */ out = *address
@@ -6867,11 +7322,11 @@
     case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadString::LoadKind::kBootImageRelRo:
     case HLoadString::LoadKind::kBssEntry:
-      DCHECK(!Runtime::Current()->UseJitCompilation());
+      DCHECK(!GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadString::LoadKind::kJitBootImageAddress:
     case HLoadString::LoadKind::kJitTableAddress:
-      DCHECK(Runtime::Current()->UseJitCompilation());
+      DCHECK(GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadString::LoadKind::kRuntimeCall:
       break;
@@ -6925,21 +7380,21 @@
       DCHECK(codegen_->GetCompilerOptions().IsBootImage() ||
              codegen_->GetCompilerOptions().IsBootImageExtension());
       Register method_address = locations->InAt(0).AsRegister<Register>();
-      __ leal(out, Address(method_address, CodeGeneratorX86::kDummy32BitOffset));
+      __ leal(out, Address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset));
       codegen_->RecordBootImageStringPatch(load);
       return;
     }
     case HLoadString::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       Register method_address = locations->InAt(0).AsRegister<Register>();
-      __ movl(out, Address(method_address, CodeGeneratorX86::kDummy32BitOffset));
+      __ movl(out, Address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset));
       codegen_->RecordBootImageRelRoPatch(load->InputAt(0)->AsX86ComputeBaseMethodAddress(),
-                                          codegen_->GetBootImageOffset(load));
+                                          CodeGenerator::GetBootImageOffset(load));
       return;
     }
     case HLoadString::LoadKind::kBssEntry: {
       Register method_address = locations->InAt(0).AsRegister<Register>();
-      Address address = Address(method_address, CodeGeneratorX86::kDummy32BitOffset);
+      Address address = Address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset);
       Label* fixup_label = codegen_->NewStringBssEntryPatch(load);
       // /* GcRoot<mirror::String> */ out = *address  /* PC-relative */
       GenerateGcRootFieldLoad(load, out_loc, address, fixup_label, kCompilerReadBarrierOption);
@@ -6958,7 +7413,7 @@
       return;
     }
     case HLoadString::LoadKind::kJitTableAddress: {
-      Address address = Address::Absolute(CodeGeneratorX86::kDummy32BitOffset);
+      Address address = Address::Absolute(CodeGeneratorX86::kPlaceholder32BitOffset);
       Label* fixup_label = codegen_->NewJitRootStringPatch(
           load->GetDexFile(), load->GetStringIndex(), load->GetString());
       // /* GcRoot<mirror::String> */ out = *address
@@ -8402,7 +8857,7 @@
                                                Register reg) {
   AssemblerFixup* fixup =
       new (GetGraph()->GetAllocator()) RIPFixup(*this, method_base, __ AddDouble(v));
-  return Address(reg, kDummy32BitOffset, fixup);
+  return Address(reg, kPlaceholder32BitOffset, fixup);
 }
 
 Address CodeGeneratorX86::LiteralFloatAddress(float v,
@@ -8410,7 +8865,7 @@
                                               Register reg) {
   AssemblerFixup* fixup =
       new (GetGraph()->GetAllocator()) RIPFixup(*this, method_base, __ AddFloat(v));
-  return Address(reg, kDummy32BitOffset, fixup);
+  return Address(reg, kPlaceholder32BitOffset, fixup);
 }
 
 Address CodeGeneratorX86::LiteralInt32Address(int32_t v,
@@ -8418,7 +8873,7 @@
                                               Register reg) {
   AssemblerFixup* fixup =
       new (GetGraph()->GetAllocator()) RIPFixup(*this, method_base, __ AddInt32(v));
-  return Address(reg, kDummy32BitOffset, fixup);
+  return Address(reg, kPlaceholder32BitOffset, fixup);
 }
 
 Address CodeGeneratorX86::LiteralInt64Address(int64_t v,
@@ -8426,7 +8881,7 @@
                                               Register reg) {
   AssemblerFixup* fixup =
       new (GetGraph()->GetAllocator()) RIPFixup(*this, method_base, __ AddInt64(v));
-  return Address(reg, kDummy32BitOffset, fixup);
+  return Address(reg, kPlaceholder32BitOffset, fixup);
 }
 
 void CodeGeneratorX86::Load32BitValue(Register dest, int32_t value) {
@@ -8481,7 +8936,7 @@
   fixups_to_jump_tables_.push_back(table_fixup);
 
   // We want a scaled address, as we are extracting the correct offset from the table.
-  return Address(reg, value, TIMES_4, kDummy32BitOffset, table_fixup);
+  return Address(reg, value, TIMES_4, kPlaceholder32BitOffset, table_fixup);
 }
 
 // TODO: target as memory.
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 16446ce..b024eeb 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -93,6 +93,29 @@
   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorX86);
 };
 
+class CriticalNativeCallingConventionVisitorX86 : public InvokeDexCallingConventionVisitor {
+ public:
+  explicit CriticalNativeCallingConventionVisitorX86(bool for_register_allocation)
+      : for_register_allocation_(for_register_allocation) {}
+
+  virtual ~CriticalNativeCallingConventionVisitorX86() {}
+
+  Location GetNextLocation(DataType::Type type) override;
+  Location GetReturnLocation(DataType::Type type) const override;
+  Location GetMethodLocation() const override;
+
+  size_t GetStackOffset() const { return stack_offset_; }
+
+ private:
+  // Register allocator does not support adjusting frame size, so we cannot provide final locations
+  // of stack arguments for register allocation. We ask the register allocator for any location and
+  // move these arguments to the right place after adjusting the SP when generating the call.
+  const bool for_register_allocation_;
+  size_t stack_offset_ = 0u;
+
+  DISALLOW_COPY_AND_ASSIGN(CriticalNativeCallingConventionVisitorX86);
+};
+
 class FieldAccessCallingConventionX86 : public FieldAccessCallingConvention {
  public:
   FieldAccessCallingConventionX86() {}
@@ -209,6 +232,25 @@
   // generates less code/data with a small num_entries.
   static constexpr uint32_t kPackedSwitchJumpTableThreshold = 5;
 
+  // Generate a GC root reference load:
+  //
+  //   root <- *address
+  //
+  // while honoring read barriers based on read_barrier_option.
+  void GenerateGcRootFieldLoad(HInstruction* instruction,
+                               Location root,
+                               const Address& address,
+                               Label* fixup_label,
+                               ReadBarrierOption read_barrier_option);
+
+  void HandleFieldSet(HInstruction* instruction,
+                      uint32_t value_index,
+                      DataType::Type type,
+                      Address field_addr,
+                      Register base,
+                      bool is_volatile,
+                      bool value_can_be_null);
+
  private:
   // Generate code for the given suspend check. If not null, `successor`
   // is the block to branch to if the suspend check is not needed, and after
@@ -269,16 +311,6 @@
                                          Location obj,
                                          uint32_t offset,
                                          ReadBarrierOption read_barrier_option);
-  // Generate a GC root reference load:
-  //
-  //   root <- *address
-  //
-  // while honoring read barriers based on read_barrier_option.
-  void GenerateGcRootFieldLoad(HInstruction* instruction,
-                               Location root,
-                               const Address& address,
-                               Label* fixup_label,
-                               ReadBarrierOption read_barrier_option);
 
   // Push value to FPU stack. `is_fp` specifies whether the value is floating point or not.
   // `is_wide` specifies whether it is long/double or not.
@@ -359,7 +391,7 @@
 
   size_t GetSlowPathFPWidth() const override {
     return GetGraph()->HasSIMD()
-        ? 4 * kX86WordSize   // 16 bytes == 4 words for each spill
+        ? GetSIMDRegisterWidth()
         : 2 * kX86WordSize;  //  8 bytes == 2 words for each spill
   }
 
@@ -367,6 +399,10 @@
     return 2 * kX86WordSize;
   }
 
+  size_t GetSIMDRegisterWidth() const override {
+    return 4 * kX86WordSize;
+  }
+
   HGraphVisitor* GetLocationBuilder() override {
     return &location_builder_;
   }
@@ -406,6 +442,19 @@
   void Move32(Location destination, Location source);
   // Helper method to move a 64bits value between two locations.
   void Move64(Location destination, Location source);
+  // Helper method to load a value from an address to a register.
+  void LoadFromMemoryNoBarrier(DataType::Type dst_type,
+                               Location dst,
+                               Address src,
+                               XmmRegister temp = kNoXmmRegister,
+                               bool is_atomic_load = false);
+  // Helper method to move a primitive value from a location to an address.
+  void MoveToMemory(DataType::Type src_type,
+                    Location src,
+                    Register dst_base,
+                    Register dst_index = Register::kNoRegister,
+                    ScaleFactor dst_scale = TIMES_1,
+                    int32_t dst_disp = 0);
 
   // Check if the desired_string_load_kind is supported. If it is, return it,
   // otherwise return a fall-back kind that should be used instead.
@@ -423,6 +472,7 @@
       const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
       ArtMethod* method) override;
 
+  void LoadMethod(MethodLoadKind load_kind, Location temp, HInvoke* invoke);
   // Generate a call to a static or direct method.
   void GenerateStaticOrDirectCall(
       HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
@@ -434,17 +484,18 @@
                                      uint32_t intrinsic_data);
   void RecordBootImageRelRoPatch(HX86ComputeBaseMethodAddress* method_address,
                                  uint32_t boot_image_offset);
-  void RecordBootImageMethodPatch(HInvokeStaticOrDirect* invoke);
-  void RecordMethodBssEntryPatch(HInvokeStaticOrDirect* invoke);
+  void RecordBootImageMethodPatch(HInvoke* invoke);
+  void RecordMethodBssEntryPatch(HInvoke* invoke);
   void RecordBootImageTypePatch(HLoadClass* load_class);
   Label* NewTypeBssEntryPatch(HLoadClass* load_class);
   void RecordBootImageStringPatch(HLoadString* load_string);
   Label* NewStringBssEntryPatch(HLoadString* load_string);
+  void RecordBootImageJniEntrypointPatch(HInvokeStaticOrDirect* invoke);
 
   void LoadBootImageAddress(Register reg,
                             uint32_t boot_image_reference,
                             HInvokeStaticOrDirect* invoke);
-  void AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke, uint32_t boot_image_offset);
+  void LoadIntrinsicDeclaringClass(Register reg, HInvokeStaticOrDirect* invoke);
 
   Label* NewJitRootStringPatch(const DexFile& dex_file,
                                dex::StringIndex string_index,
@@ -620,6 +671,9 @@
     }
   }
 
+  void IncreaseFrame(size_t adjustment) override;
+  void DecreaseFrame(size_t adjustment) override;
+
   void GenerateNop() override;
   void GenerateImplicitNullCheck(HNullCheck* instruction) override;
   void GenerateExplicitNullCheck(HNullCheck* instruction) override;
@@ -627,9 +681,9 @@
   void MaybeGenerateInlineCacheCheck(HInstruction* instruction, Register klass);
   void MaybeIncrementHotness(bool is_frame_entry);
 
-  // When we don't know the proper offset for the value, we use kDummy32BitOffset.
+  // When we don't know the proper offset for the value, we use kPlaceholder32BitOffset.
   // The correct value will be inserted when processing Assembler fixups.
-  static constexpr int32_t kDummy32BitOffset = 256;
+  static constexpr int32_t kPlaceholder32BitOffset = 256;
 
  private:
   struct X86PcRelativePatchInfo : PatchInfo<Label> {
@@ -645,6 +699,7 @@
   void EmitPcRelativeLinkerPatches(const ArenaDeque<X86PcRelativePatchInfo>& infos,
                                    ArenaVector<linker::LinkerPatch>* linker_patches);
 
+  Register GetInvokeExtraParameter(HInvoke* invoke, Register temp);
   Register GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke, Register temp);
 
   // Labels for each block that will be compiled.
@@ -663,10 +718,16 @@
   ArenaDeque<X86PcRelativePatchInfo> boot_image_type_patches_;
   // PC-relative type patch info for kBssEntry.
   ArenaDeque<X86PcRelativePatchInfo> type_bss_entry_patches_;
+  // PC-relative public type patch info for kBssEntryPublic.
+  ArenaDeque<X86PcRelativePatchInfo> public_type_bss_entry_patches_;
+  // PC-relative package type patch info for kBssEntryPackage.
+  ArenaDeque<X86PcRelativePatchInfo> package_type_bss_entry_patches_;
   // PC-relative String patch info for kBootImageLinkTimePcRelative.
   ArenaDeque<X86PcRelativePatchInfo> boot_image_string_patches_;
   // PC-relative String patch info for kBssEntry.
   ArenaDeque<X86PcRelativePatchInfo> string_bss_entry_patches_;
+  // PC-relative method patch info for kBootImageLinkTimePcRelative+kCallCriticalNative.
+  ArenaDeque<X86PcRelativePatchInfo> boot_image_jni_entrypoint_patches_;
   // PC-relative patch info for IntrinsicObjects for the boot image,
   // and for method/type/string patches for kBootImageRelRo otherwise.
   ArenaDeque<X86PcRelativePatchInfo> boot_image_other_patches_;
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 8518b6d..d54484c 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -16,6 +16,7 @@
 
 #include "code_generator_x86_64.h"
 
+#include "arch/x86_64/jni_frame_x86_64.h"
 #include "art_method-inl.h"
 #include "class_table.h"
 #include "code_generator_utils.h"
@@ -24,6 +25,7 @@
 #include "gc/accounting/card_table.h"
 #include "gc/space/image_space.h"
 #include "heap_poisoning.h"
+#include "interpreter/mterp/nterp.h"
 #include "intrinsics.h"
 #include "intrinsics_x86_64.h"
 #include "jit/profiling_info.h"
@@ -37,6 +39,7 @@
 #include "utils/assembler.h"
 #include "utils/stack_checks.h"
 #include "utils/x86_64/assembler_x86_64.h"
+#include "utils/x86_64/constants_x86_64.h"
 #include "utils/x86_64/managed_register_x86_64.h"
 
 namespace art {
@@ -270,8 +273,13 @@
       DCHECK(IsSameDexFile(cls_->GetDexFile(), x86_64_codegen->GetGraph()->GetDexFile()));
       dex::TypeIndex type_index = cls_->GetTypeIndex();
       __ movl(CpuRegister(RAX), Immediate(type_index.index_));
-      x86_64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
-      CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+      if (cls_->NeedsAccessCheck()) {
+        CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>();
+        x86_64_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this);
+      } else {
+        CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
+        x86_64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
+      }
       // If we also must_do_clinit, the resolved type is now in the correct register.
     } else {
       DCHECK(must_do_clinit);
@@ -493,6 +501,7 @@
     DCHECK(locations->CanCall());
     DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(ref_reg)) << ref_reg;
     DCHECK(instruction_->IsInstanceFieldGet() ||
+           instruction_->IsPredicatedInstanceFieldGet() ||
            instruction_->IsStaticFieldGet() ||
            instruction_->IsArrayGet() ||
            instruction_->IsArraySet() ||
@@ -754,11 +763,12 @@
     DCHECK(locations->CanCall());
     DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(reg_out.AsRegister())) << out_;
     DCHECK(instruction_->IsInstanceFieldGet() ||
+           instruction_->IsPredicatedInstanceFieldGet() ||
            instruction_->IsStaticFieldGet() ||
            instruction_->IsArrayGet() ||
            instruction_->IsInstanceOf() ||
            instruction_->IsCheckCast() ||
-           (instruction_->IsInvokeVirtual() && instruction_->GetLocations()->Intrinsified()))
+           (instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
         << "Unexpected instruction in read barrier for heap reference slow path: "
         << instruction_->DebugName();
 
@@ -978,69 +988,150 @@
   UNREACHABLE();
 }
 
+void CodeGeneratorX86_64::BlockNonVolatileXmmRegisters(LocationSummary* locations) {
+  // We have to ensure that the native code we call directly (such as @CriticalNative
+  // or some intrinsic helpers, say Math.sin()) doesn't clobber the XMM registers
+  // which are non-volatile for ART, but volatile for Native calls.  This will ensure
+  // that they are saved in the prologue and properly restored.
+  for (FloatRegister fp_reg : non_volatile_xmm_regs) {
+    locations->AddTemp(Location::FpuRegisterLocation(fp_reg));
+  }
+}
+
 HInvokeStaticOrDirect::DispatchInfo CodeGeneratorX86_64::GetSupportedInvokeStaticOrDirectDispatch(
       const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
       ArtMethod* method ATTRIBUTE_UNUSED) {
   return desired_dispatch_info;
 }
 
+void CodeGeneratorX86_64::LoadMethod(MethodLoadKind load_kind, Location temp, HInvoke* invoke) {
+  switch (load_kind) {
+    case MethodLoadKind::kBootImageLinkTimePcRelative:
+      DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
+      __ leal(temp.AsRegister<CpuRegister>(),
+              Address::Absolute(kPlaceholder32BitOffset, /* no_rip= */ false));
+      RecordBootImageMethodPatch(invoke);
+      break;
+    case MethodLoadKind::kBootImageRelRo: {
+      // Note: Boot image is in the low 4GiB and the entry is 32-bit, so emit a 32-bit load.
+      __ movl(temp.AsRegister<CpuRegister>(),
+              Address::Absolute(kPlaceholder32BitOffset, /* no_rip= */ false));
+      RecordBootImageRelRoPatch(GetBootImageOffset(invoke));
+      break;
+    }
+    case MethodLoadKind::kBssEntry: {
+      __ movq(temp.AsRegister<CpuRegister>(),
+              Address::Absolute(kPlaceholder32BitOffset, /* no_rip= */ false));
+      RecordMethodBssEntryPatch(invoke);
+      // No need for memory fence, thanks to the x86-64 memory model.
+      break;
+    }
+    case MethodLoadKind::kJitDirectAddress: {
+      Load64BitValue(temp.AsRegister<CpuRegister>(),
+                     reinterpret_cast<int64_t>(invoke->GetResolvedMethod()));
+      break;
+    }
+    case MethodLoadKind::kRuntimeCall: {
+      // Test situation, don't do anything.
+      break;
+    }
+    default: {
+      LOG(FATAL) << "Load kind should have already been handled " << load_kind;
+      UNREACHABLE();
+    }
+  }
+}
+
 void CodeGeneratorX86_64::GenerateStaticOrDirectCall(
     HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
   // All registers are assumed to be correctly set up.
 
   Location callee_method = temp;  // For all kinds except kRecursive, callee will be in temp.
   switch (invoke->GetMethodLoadKind()) {
-    case HInvokeStaticOrDirect::MethodLoadKind::kStringInit: {
+    case MethodLoadKind::kStringInit: {
       // temp = thread->string_init_entrypoint
       uint32_t offset =
           GetThreadOffset<kX86_64PointerSize>(invoke->GetStringInitEntryPoint()).Int32Value();
       __ gs()->movq(temp.AsRegister<CpuRegister>(), Address::Absolute(offset, /* no_rip= */ true));
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
-      callee_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
-      break;
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative:
-      DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
-      __ leal(temp.AsRegister<CpuRegister>(),
-              Address::Absolute(kDummy32BitOffset, /* no_rip= */ false));
-      RecordBootImageMethodPatch(invoke);
-      break;
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
-      // Note: Boot image is in the low 4GiB and the entry is 32-bit, so emit a 32-bit load.
-      __ movl(temp.AsRegister<CpuRegister>(),
-              Address::Absolute(kDummy32BitOffset, /* no_rip= */ false));
-      RecordBootImageRelRoPatch(GetBootImageOffset(invoke));
+    case MethodLoadKind::kRecursive: {
+      callee_method = invoke->GetLocations()->InAt(invoke->GetCurrentMethodIndex());
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
-      __ movq(temp.AsRegister<CpuRegister>(),
-              Address::Absolute(kDummy32BitOffset, /* no_rip= */ false));
-      RecordMethodBssEntryPatch(invoke);
-      // No need for memory fence, thanks to the x86-64 memory model.
-      break;
-    }
-    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
-      Load64BitValue(temp.AsRegister<CpuRegister>(), invoke->GetMethodAddress());
-      break;
-    case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+    case MethodLoadKind::kRuntimeCall: {
       GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
       return;  // No code pointer retrieval; the runtime performs the call directly.
     }
+    case MethodLoadKind::kBootImageLinkTimePcRelative:
+      // For kCallCriticalNative we skip loading the method and do the call directly.
+      if (invoke->GetCodePtrLocation() == CodePtrLocation::kCallCriticalNative) {
+        break;
+      }
+      FALLTHROUGH_INTENDED;
+    default: {
+      LoadMethod(invoke->GetMethodLoadKind(), temp, invoke);
+      break;
+    }
   }
 
   switch (invoke->GetCodePtrLocation()) {
-    case HInvokeStaticOrDirect::CodePtrLocation::kCallSelf:
+    case CodePtrLocation::kCallSelf:
       __ call(&frame_entry_label_);
+      RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
       break;
-    case HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod:
+    case CodePtrLocation::kCallCriticalNative: {
+      size_t out_frame_size =
+          PrepareCriticalNativeCall<CriticalNativeCallingConventionVisitorX86_64,
+                                    kNativeStackAlignment,
+                                    GetCriticalNativeDirectCallFrameSize>(invoke);
+      if (invoke->GetMethodLoadKind() == MethodLoadKind::kBootImageLinkTimePcRelative) {
+        DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
+        __ call(Address::Absolute(kPlaceholder32BitOffset, /* no_rip= */ false));
+        RecordBootImageJniEntrypointPatch(invoke);
+      } else {
+        // (callee_method + offset_of_jni_entry_point)()
+        __ call(Address(callee_method.AsRegister<CpuRegister>(),
+                         ArtMethod::EntryPointFromJniOffset(kX86_64PointerSize).SizeValue()));
+      }
+      RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+      // Zero-/sign-extend the result when needed due to native and managed ABI mismatch.
+      switch (invoke->GetType()) {
+        case DataType::Type::kBool:
+          __ movzxb(CpuRegister(RAX), CpuRegister(RAX));
+          break;
+        case DataType::Type::kInt8:
+          __ movsxb(CpuRegister(RAX), CpuRegister(RAX));
+          break;
+        case DataType::Type::kUint16:
+          __ movzxw(CpuRegister(RAX), CpuRegister(RAX));
+          break;
+        case DataType::Type::kInt16:
+          __ movsxw(CpuRegister(RAX), CpuRegister(RAX));
+          break;
+        case DataType::Type::kInt32:
+        case DataType::Type::kInt64:
+        case DataType::Type::kFloat32:
+        case DataType::Type::kFloat64:
+        case DataType::Type::kVoid:
+          break;
+        default:
+          DCHECK(false) << invoke->GetType();
+          break;
+      }
+      if (out_frame_size != 0u) {
+        DecreaseFrame(out_frame_size);
+      }
+      break;
+    }
+    case CodePtrLocation::kCallArtMethod:
       // (callee_method + offset_of_quick_compiled_code)()
       __ call(Address(callee_method.AsRegister<CpuRegister>(),
                       ArtMethod::EntryPointFromQuickCompiledCodeOffset(
                           kX86_64PointerSize).SizeValue()));
+      RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
       break;
   }
-  RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
 
   DCHECK(!IsLeafMethod());
 }
@@ -1091,14 +1182,16 @@
   __ Bind(&boot_image_other_patches_.back().label);
 }
 
-void CodeGeneratorX86_64::RecordBootImageMethodPatch(HInvokeStaticOrDirect* invoke) {
-  boot_image_method_patches_.emplace_back(
-      invoke->GetTargetMethod().dex_file, invoke->GetTargetMethod().index);
+void CodeGeneratorX86_64::RecordBootImageMethodPatch(HInvoke* invoke) {
+  boot_image_method_patches_.emplace_back(invoke->GetResolvedMethodReference().dex_file,
+                                          invoke->GetResolvedMethodReference().index);
   __ Bind(&boot_image_method_patches_.back().label);
 }
 
-void CodeGeneratorX86_64::RecordMethodBssEntryPatch(HInvokeStaticOrDirect* invoke) {
-  method_bss_entry_patches_.emplace_back(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex());
+void CodeGeneratorX86_64::RecordMethodBssEntryPatch(HInvoke* invoke) {
+  DCHECK(IsSameDexFile(GetGraph()->GetDexFile(), *invoke->GetMethodReference().dex_file));
+  method_bss_entry_patches_.emplace_back(invoke->GetMethodReference().dex_file,
+                                         invoke->GetMethodReference().index);
   __ Bind(&method_bss_entry_patches_.back().label);
 }
 
@@ -1109,9 +1202,23 @@
 }
 
 Label* CodeGeneratorX86_64::NewTypeBssEntryPatch(HLoadClass* load_class) {
-  type_bss_entry_patches_.emplace_back(
-      &load_class->GetDexFile(), load_class->GetTypeIndex().index_);
-  return &type_bss_entry_patches_.back().label;
+  ArenaDeque<PatchInfo<Label>>* patches = nullptr;
+  switch (load_class->GetLoadKind()) {
+    case HLoadClass::LoadKind::kBssEntry:
+      patches = &type_bss_entry_patches_;
+      break;
+    case HLoadClass::LoadKind::kBssEntryPublic:
+      patches = &public_type_bss_entry_patches_;
+      break;
+    case HLoadClass::LoadKind::kBssEntryPackage:
+      patches = &package_type_bss_entry_patches_;
+      break;
+    default:
+      LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind();
+      UNREACHABLE();
+  }
+  patches->emplace_back(&load_class->GetDexFile(), load_class->GetTypeIndex().index_);
+  return &patches->back().label;
 }
 
 void CodeGeneratorX86_64::RecordBootImageStringPatch(HLoadString* load_string) {
@@ -1126,15 +1233,23 @@
   return &string_bss_entry_patches_.back().label;
 }
 
+void CodeGeneratorX86_64::RecordBootImageJniEntrypointPatch(HInvokeStaticOrDirect* invoke) {
+  boot_image_jni_entrypoint_patches_.emplace_back(invoke->GetResolvedMethodReference().dex_file,
+                                                  invoke->GetResolvedMethodReference().index);
+  __ Bind(&boot_image_jni_entrypoint_patches_.back().label);
+}
+
 void CodeGeneratorX86_64::LoadBootImageAddress(CpuRegister reg, uint32_t boot_image_reference) {
   if (GetCompilerOptions().IsBootImage()) {
-    __ leal(reg, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip= */ false));
+    __ leal(reg,
+            Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
     RecordBootImageIntrinsicPatch(boot_image_reference);
   } else if (GetCompilerOptions().GetCompilePic()) {
-    __ movl(reg, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip= */ false));
+    __ movl(reg,
+            Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
     RecordBootImageRelRoPatch(boot_image_reference);
   } else {
-    DCHECK(Runtime::Current()->UseJitCompilation());
+    DCHECK(GetCompilerOptions().IsJitCompiler());
     gc::Heap* heap = Runtime::Current()->GetHeap();
     DCHECK(!heap->GetBootImageSpaces().empty());
     const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -1142,25 +1257,20 @@
   }
 }
 
-void CodeGeneratorX86_64::AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke,
-                                                       uint32_t boot_image_offset) {
-  DCHECK(invoke->IsStatic());
-  InvokeRuntimeCallingConvention calling_convention;
-  CpuRegister argument = CpuRegister(calling_convention.GetRegisterAt(0));
+void CodeGeneratorX86_64::LoadIntrinsicDeclaringClass(CpuRegister reg, HInvoke* invoke) {
+  DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
   if (GetCompilerOptions().IsBootImage()) {
-    DCHECK_EQ(boot_image_offset, IntrinsicVisitor::IntegerValueOfInfo::kInvalidReference);
     // Load the class the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
-    __ leal(argument,
-            Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip= */ false));
-    MethodReference target_method = invoke->GetTargetMethod();
+    __ leal(reg,
+            Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
+    MethodReference target_method = invoke->GetResolvedMethodReference();
     dex::TypeIndex type_idx = target_method.dex_file->GetMethodId(target_method.index).class_idx_;
     boot_image_type_patches_.emplace_back(target_method.dex_file, type_idx.index_);
     __ Bind(&boot_image_type_patches_.back().label);
   } else {
-    LoadBootImageAddress(argument, boot_image_offset);
+    uint32_t boot_image_offset = GetBootImageOffsetOfIntrinsicDeclaringClass(invoke);
+    LoadBootImageAddress(reg, boot_image_offset);
   }
-  InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
-  CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
 }
 
 // The label points to the end of the "movl" or another instruction but the literal offset
@@ -1194,8 +1304,11 @@
       method_bss_entry_patches_.size() +
       boot_image_type_patches_.size() +
       type_bss_entry_patches_.size() +
+      public_type_bss_entry_patches_.size() +
+      package_type_bss_entry_patches_.size() +
       boot_image_string_patches_.size() +
       string_bss_entry_patches_.size() +
+      boot_image_jni_entrypoint_patches_.size() +
       boot_image_other_patches_.size();
   linker_patches->reserve(size);
   if (GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension()) {
@@ -1221,8 +1334,14 @@
       method_bss_entry_patches_, linker_patches);
   EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>(
       type_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>(
+      public_type_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>(
+      package_type_bss_entry_patches_, linker_patches);
   EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>(
       string_bss_entry_patches_, linker_patches);
+  EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeJniEntrypointPatch>(
+      boot_image_jni_entrypoint_patches_, linker_patches);
   DCHECK_EQ(size, linker_patches->size());
 }
 
@@ -1294,33 +1413,36 @@
 CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph,
                                          const CompilerOptions& compiler_options,
                                          OptimizingCompilerStats* stats)
-      : CodeGenerator(graph,
-                      kNumberOfCpuRegisters,
-                      kNumberOfFloatRegisters,
-                      kNumberOfCpuRegisterPairs,
-                      ComputeRegisterMask(reinterpret_cast<const int*>(kCoreCalleeSaves),
-                                          arraysize(kCoreCalleeSaves))
-                          | (1 << kFakeReturnRegister),
-                      ComputeRegisterMask(reinterpret_cast<const int*>(kFpuCalleeSaves),
-                                          arraysize(kFpuCalleeSaves)),
-                      compiler_options,
-                      stats),
-        block_labels_(nullptr),
-        location_builder_(graph, this),
-        instruction_visitor_(graph, this),
-        move_resolver_(graph->GetAllocator(), this),
-        assembler_(graph->GetAllocator()),
-        constant_area_start_(0),
-        boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
-        method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
-        boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
-        type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
-        boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
-        string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
-        boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
-        jit_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
-        jit_class_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
-        fixups_to_jump_tables_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)) {
+    : CodeGenerator(graph,
+                    kNumberOfCpuRegisters,
+                    kNumberOfFloatRegisters,
+                    kNumberOfCpuRegisterPairs,
+                    ComputeRegisterMask(reinterpret_cast<const int*>(kCoreCalleeSaves),
+                                        arraysize(kCoreCalleeSaves))
+                        | (1 << kFakeReturnRegister),
+                    ComputeRegisterMask(reinterpret_cast<const int*>(kFpuCalleeSaves),
+                                        arraysize(kFpuCalleeSaves)),
+                    compiler_options,
+                    stats),
+      block_labels_(nullptr),
+      location_builder_(graph, this),
+      instruction_visitor_(graph, this),
+      move_resolver_(graph->GetAllocator(), this),
+      assembler_(graph->GetAllocator()),
+      constant_area_start_(0),
+      boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      boot_image_jni_entrypoint_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      jit_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      jit_class_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+      fixups_to_jump_tables_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)) {
   AddAllocatedRegister(Location::RegisterLocation(kFakeReturnRegister));
 }
 
@@ -1364,15 +1486,18 @@
   }
 
   if (GetGraph()->IsCompilingBaseline() && !Runtime::Current()->IsAotCompiler()) {
-    ScopedObjectAccess soa(Thread::Current());
-    ProfilingInfo* info = GetGraph()->GetArtMethod()->GetProfilingInfo(kRuntimePointerSize);
+    ScopedProfilingInfoUse spiu(
+        Runtime::Current()->GetJit(), GetGraph()->GetArtMethod(), Thread::Current());
+    ProfilingInfo* info = spiu.GetProfilingInfo();
     if (info != nullptr) {
       uint64_t address = reinterpret_cast64<uint64_t>(info);
       NearLabel done;
       __ movq(CpuRegister(TMP), Immediate(address));
       __ addw(Address(CpuRegister(TMP), ProfilingInfo::BaselineHotnessCountOffset().Int32Value()),
               Immediate(1));
-      __ j(kCarryClear, &done);
+      __ andw(Address(CpuRegister(TMP), ProfilingInfo::BaselineHotnessCountOffset().Int32Value()),
+              Immediate(interpreter::kTieredHotnessMask));
+      __ j(kNotZero, &done);
       if (HasEmptyFrame()) {
         CHECK(is_frame_entry);
         // Frame alignment, and the stub expects the method on the stack.
@@ -1420,8 +1545,7 @@
     }
 
     int adjust = GetFrameSize() - GetCoreSpillSize();
-    __ subq(CpuRegister(RSP), Immediate(adjust));
-    __ cfi().AdjustCFAOffset(adjust);
+    IncreaseFrame(adjust);
     uint32_t xmm_spill_location = GetFpuSpillStart();
     size_t xmm_spill_slot_size = GetCalleePreservedFPWidth();
 
@@ -1466,8 +1590,7 @@
     }
 
     int adjust = GetFrameSize() - GetCoreSpillSize();
-    __ addq(CpuRegister(RSP), Immediate(adjust));
-    __ cfi().AdjustCFAOffset(-adjust);
+    DecreaseFrame(adjust);
 
     for (size_t i = 0; i < arraysize(kCoreCalleeSaves); ++i) {
       Register reg = kCoreCalleeSaves[i];
@@ -1988,6 +2111,16 @@
   // MaybeRecordNativeDebugInfo is already called implicitly in CodeGenerator::Compile.
 }
 
+void CodeGeneratorX86_64::IncreaseFrame(size_t adjustment) {
+  __ subq(CpuRegister(RSP), Immediate(adjustment));
+  __ cfi().AdjustCFAOffset(adjustment);
+}
+
+void CodeGeneratorX86_64::DecreaseFrame(size_t adjustment) {
+  __ addq(CpuRegister(RSP), Immediate(adjustment));
+  __ cfi().AdjustCFAOffset(-adjustment);
+}
+
 void CodeGeneratorX86_64::GenerateNop() {
   __ nop();
 }
@@ -2493,6 +2626,51 @@
   return Location::NoLocation();
 }
 
+Location CriticalNativeCallingConventionVisitorX86_64::GetNextLocation(DataType::Type type) {
+  DCHECK_NE(type, DataType::Type::kReference);
+
+  Location location = Location::NoLocation();
+  if (DataType::IsFloatingPointType(type)) {
+    if (fpr_index_ < kParameterFloatRegistersLength) {
+      location = Location::FpuRegisterLocation(kParameterFloatRegisters[fpr_index_]);
+      ++fpr_index_;
+    }
+  } else {
+    // Native ABI uses the same registers as managed, except that the method register RDI
+    // is a normal argument.
+    if (gpr_index_ < 1u + kParameterCoreRegistersLength) {
+      location = Location::RegisterLocation(
+          gpr_index_ == 0u ? RDI : kParameterCoreRegisters[gpr_index_ - 1u]);
+      ++gpr_index_;
+    }
+  }
+  if (location.IsInvalid()) {
+    if (DataType::Is64BitType(type)) {
+      location = Location::DoubleStackSlot(stack_offset_);
+    } else {
+      location = Location::StackSlot(stack_offset_);
+    }
+    stack_offset_ += kFramePointerSize;
+
+    if (for_register_allocation_) {
+      location = Location::Any();
+    }
+  }
+  return location;
+}
+
+Location CriticalNativeCallingConventionVisitorX86_64::GetReturnLocation(DataType::Type type)
+    const {
+  // We perform conversion to the managed ABI return register after the call if needed.
+  InvokeDexCallingConventionVisitorX86_64 dex_calling_convention;
+  return dex_calling_convention.GetReturnLocation(type);
+}
+
+Location CriticalNativeCallingConventionVisitorX86_64::GetMethodLocation() const {
+  // Pass the method in the hidden argument RAX.
+  return Location::RegisterLocation(RAX);
+}
+
 void LocationsBuilderX86_64::VisitInvokeUnresolved(HInvokeUnresolved* invoke) {
   // The trampoline uses the same calling convention as dex calling conventions,
   // except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
@@ -2514,7 +2692,14 @@
     return;
   }
 
-  HandleInvoke(invoke);
+  if (invoke->GetCodePtrLocation() == CodePtrLocation::kCallCriticalNative) {
+    CriticalNativeCallingConventionVisitorX86_64 calling_convention_visitor(
+        /*for_register_allocation=*/ true);
+    CodeGenerator::CreateCommonInvokeLocationSummary(invoke, &calling_convention_visitor);
+    CodeGeneratorX86_64::BlockNonVolatileXmmRegisters(invoke->GetLocations());
+  } else {
+    HandleInvoke(invoke);
+  }
 }
 
 static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorX86_64* codegen) {
@@ -2566,6 +2751,10 @@
 void LocationsBuilderX86_64::VisitInvokeInterface(HInvokeInterface* invoke) {
   HandleInvoke(invoke);
   // Add the hidden argument.
+  if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive) {
+    invoke->GetLocations()->SetInAt(invoke->GetNumberOfArguments() - 1,
+                                    Location::RegisterLocation(RAX));
+  }
   invoke->GetLocations()->AddTemp(Location::RegisterLocation(RAX));
 }
 
@@ -2577,8 +2766,9 @@
   if (!instruction->GetLocations()->Intrinsified() &&
       GetGraph()->IsCompilingBaseline() &&
       !Runtime::Current()->IsAotCompiler()) {
-    ScopedObjectAccess soa(Thread::Current());
-    ProfilingInfo* info = GetGraph()->GetArtMethod()->GetProfilingInfo(kRuntimePointerSize);
+    ScopedProfilingInfoUse spiu(
+        Runtime::Current()->GetJit(), GetGraph()->GetArtMethod(), Thread::Current());
+    ProfilingInfo* info = spiu.GetProfilingInfo();
     if (info != nullptr) {
       InlineCache* cache = info->GetInlineCache(instruction->GetDexPc());
       uint64_t address = reinterpret_cast64<uint64_t>(cache);
@@ -2598,7 +2788,6 @@
   // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError.
   LocationSummary* locations = invoke->GetLocations();
   CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
-  CpuRegister hidden_reg = locations->GetTemp(1).AsRegister<CpuRegister>();
   Location receiver = locations->InAt(0);
   size_t class_offset = mirror::Object::ClassOffset().SizeValue();
 
@@ -2622,11 +2811,15 @@
 
   codegen_->MaybeGenerateInlineCacheCheck(invoke, temp);
 
-  // Set the hidden argument. This is safe to do this here, as RAX
-  // won't be modified thereafter, before the `call` instruction.
-  // We also di it after MaybeGenerateInlineCache that may use RAX.
-  DCHECK_EQ(RAX, hidden_reg.AsRegister());
-  codegen_->Load64BitValue(hidden_reg, invoke->GetDexMethodIndex());
+  if (invoke->GetHiddenArgumentLoadKind() != MethodLoadKind::kRecursive &&
+      invoke->GetHiddenArgumentLoadKind() != MethodLoadKind::kRuntimeCall) {
+    Location hidden_reg = locations->GetTemp(1);
+    // Set the hidden argument. This is safe to do this here, as RAX
+    // won't be modified thereafter, before the `call` instruction.
+    // We also do it after MaybeGenerateInlineCache that may use RAX.
+    DCHECK_EQ(RAX, hidden_reg.AsRegister<Register>());
+    codegen_->LoadMethod(invoke->GetHiddenArgumentLoadKind(), hidden_reg, invoke);
+  }
 
   // temp = temp->GetAddressOfIMT()
   __ movq(temp,
@@ -2636,6 +2829,12 @@
       invoke->GetImtIndex(), kX86_64PointerSize));
   // temp = temp->GetImtEntryAt(method_offset);
   __ movq(temp, Address(temp, method_offset));
+  if (invoke->GetHiddenArgumentLoadKind() == MethodLoadKind::kRuntimeCall) {
+    // We pass the method from the IMT in case of a conflict. This will ensure
+    // we go into the runtime to resolve the actual method.
+    Location hidden_reg = locations->GetTemp(1);
+    __ movq(hidden_reg.AsRegister<CpuRegister>(), temp);
+  }
   // call temp->GetEntryPoint();
   __ call(Address(
       temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86_64PointerSize).SizeValue()));
@@ -2645,10 +2844,17 @@
 }
 
 void LocationsBuilderX86_64::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
+  IntrinsicLocationsBuilderX86_64 intrinsic(codegen_);
+  if (intrinsic.TryDispatch(invoke)) {
+    return;
+  }
   HandleInvoke(invoke);
 }
 
 void InstructionCodeGeneratorX86_64::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
+  if (TryGenerateIntrinsicCode(invoke, codegen_)) {
+    return;
+  }
   codegen_->GenerateInvokePolymorphicCall(invoke);
 }
 
@@ -4653,10 +4859,13 @@
 }
 
 void LocationsBuilderX86_64::HandleFieldGet(HInstruction* instruction) {
-  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
+  DCHECK(instruction->IsInstanceFieldGet() ||
+         instruction->IsStaticFieldGet() ||
+         instruction->IsPredicatedInstanceFieldGet());
 
   bool object_field_get_with_read_barrier =
       kEmitCompilerReadBarrier && (instruction->GetType() == DataType::Type::kReference);
+  bool is_predicated = instruction->IsPredicatedInstanceFieldGet();
   LocationSummary* locations =
       new (GetGraph()->GetAllocator()) LocationSummary(instruction,
                                                        object_field_get_with_read_barrier
@@ -4665,25 +4874,38 @@
   if (object_field_get_with_read_barrier && kUseBakerReadBarrier) {
     locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty());  // No caller-save registers.
   }
-  locations->SetInAt(0, Location::RequiresRegister());
+  // receiver_input
+  locations->SetInAt(is_predicated ? 1 : 0, Location::RequiresRegister());
+  if (is_predicated) {
+    if (DataType::IsFloatingPointType(instruction->GetType())) {
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+    } else {
+      locations->SetInAt(0, Location::RequiresRegister());
+    }
+  }
   if (DataType::IsFloatingPointType(instruction->GetType())) {
-    locations->SetOut(Location::RequiresFpuRegister());
+    locations->SetOut(is_predicated ? Location::SameAsFirstInput()
+                                    : Location::RequiresFpuRegister());
   } else {
-    // The output overlaps for an object field get when read barriers
-    // are enabled: we do not want the move to overwrite the object's
-    // location, as we need it to emit the read barrier.
-    locations->SetOut(
-        Location::RequiresRegister(),
-        object_field_get_with_read_barrier ? Location::kOutputOverlap : Location::kNoOutputOverlap);
+    // The output overlaps for an object field get when read barriers are
+    // enabled: we do not want the move to overwrite the object's location, as
+    // we need it to emit the read barrier. For predicated instructions we can
+    // always overlap since the output is SameAsFirst and the default value.
+    locations->SetOut(is_predicated ? Location::SameAsFirstInput() : Location::RequiresRegister(),
+                      object_field_get_with_read_barrier || is_predicated
+                          ? Location::kOutputOverlap
+                          : Location::kNoOutputOverlap);
   }
 }
 
 void InstructionCodeGeneratorX86_64::HandleFieldGet(HInstruction* instruction,
                                                     const FieldInfo& field_info) {
-  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
+  DCHECK(instruction->IsInstanceFieldGet() ||
+         instruction->IsStaticFieldGet() ||
+         instruction->IsPredicatedInstanceFieldGet());
 
   LocationSummary* locations = instruction->GetLocations();
-  Location base_loc = locations->InAt(0);
+  Location base_loc = locations->InAt(instruction->IsPredicatedInstanceFieldGet() ? 1 : 0);
   CpuRegister base = base_loc.AsRegister<CpuRegister>();
   Location out = locations->Out();
   bool is_volatile = field_info.IsVolatile();
@@ -4829,6 +5051,8 @@
   bool is_volatile = field_info.IsVolatile();
   DataType::Type field_type = field_info.GetFieldType();
   uint32_t offset = field_info.GetFieldOffset().Uint32Value();
+  bool is_predicated =
+      instruction->IsInstanceFieldSet() && instruction->AsInstanceFieldSet()->GetIsPredicatedSet();
 
   if (is_volatile) {
     codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
@@ -4836,6 +5060,12 @@
 
   bool maybe_record_implicit_null_check_done = false;
 
+  NearLabel pred_is_null;
+  if (is_predicated) {
+    __ testl(base, base);
+    __ j(kZero, &pred_is_null);
+  }
+
   switch (field_type) {
     case DataType::Type::kBool:
     case DataType::Type::kUint8:
@@ -4942,6 +5172,10 @@
   if (is_volatile) {
     codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
   }
+
+  if (is_predicated) {
+    __ Bind(&pred_is_null);
+  }
 }
 
 void LocationsBuilderX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
@@ -4952,10 +5186,26 @@
   HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
 }
 
+void LocationsBuilderX86_64::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* instruction) {
+  HandleFieldGet(instruction);
+}
+
 void LocationsBuilderX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
   HandleFieldGet(instruction);
 }
 
+void InstructionCodeGeneratorX86_64::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* instruction) {
+  NearLabel finish;
+  LocationSummary* locations = instruction->GetLocations();
+  CpuRegister target = locations->InAt(1).AsRegister<CpuRegister>();
+  __ testl(target, target);
+  __ j(kZero, &finish);
+  HandleFieldGet(instruction, instruction->GetFieldInfo());
+  __ Bind(&finish);
+}
+
 void InstructionCodeGeneratorX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
   HandleFieldGet(instruction, instruction->GetFieldInfo());
 }
@@ -5966,11 +6216,13 @@
     case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadClass::LoadKind::kBootImageRelRo:
     case HLoadClass::LoadKind::kBssEntry:
-      DCHECK(!Runtime::Current()->UseJitCompilation());
+    case HLoadClass::LoadKind::kBssEntryPublic:
+    case HLoadClass::LoadKind::kBssEntryPackage:
+      DCHECK(!GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadClass::LoadKind::kJitBootImageAddress:
     case HLoadClass::LoadKind::kJitTableAddress:
-      DCHECK(Runtime::Current()->UseJitCompilation());
+      DCHECK(GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadClass::LoadKind::kRuntimeCall:
       break;
@@ -5988,7 +6240,9 @@
         Location::RegisterLocation(RAX));
     return;
   }
-  DCHECK(!cls->NeedsAccessCheck());
+  DCHECK_EQ(cls->NeedsAccessCheck(),
+            load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+                load_kind == HLoadClass::LoadKind::kBssEntryPackage);
 
   const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage();
   LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier)
@@ -6031,7 +6285,9 @@
     codegen_->GenerateLoadClassRuntimeCall(cls);
     return;
   }
-  DCHECK(!cls->NeedsAccessCheck());
+  DCHECK_EQ(cls->NeedsAccessCheck(),
+            load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+                load_kind == HLoadClass::LoadKind::kBssEntryPackage);
 
   LocationSummary* locations = cls->GetLocations();
   Location out_loc = locations->Out();
@@ -6059,17 +6315,21 @@
       DCHECK(codegen_->GetCompilerOptions().IsBootImage() ||
              codegen_->GetCompilerOptions().IsBootImageExtension());
       DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
-      __ leal(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip= */ false));
+      __ leal(out,
+              Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
       codegen_->RecordBootImageTypePatch(cls);
       break;
     case HLoadClass::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
-      __ movl(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip= */ false));
-      codegen_->RecordBootImageRelRoPatch(codegen_->GetBootImageOffset(cls));
+      __ movl(out,
+              Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
+      codegen_->RecordBootImageRelRoPatch(CodeGenerator::GetBootImageOffset(cls));
       break;
     }
-    case HLoadClass::LoadKind::kBssEntry: {
-      Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset,
+    case HLoadClass::LoadKind::kBssEntry:
+    case HLoadClass::LoadKind::kBssEntryPublic:
+    case HLoadClass::LoadKind::kBssEntryPackage: {
+      Address address = Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset,
                                           /* no_rip= */ false);
       Label* fixup_label = codegen_->NewTypeBssEntryPatch(cls);
       // /* GcRoot<mirror::Class> */ out = *address  /* PC-relative */
@@ -6086,7 +6346,7 @@
       break;
     }
     case HLoadClass::LoadKind::kJitTableAddress: {
-      Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset,
+      Address address = Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset,
                                           /* no_rip= */ true);
       Label* fixup_label =
           codegen_->NewJitRootClassPatch(cls->GetDexFile(), cls->GetTypeIndex(), cls->GetClass());
@@ -6162,11 +6422,11 @@
     case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadString::LoadKind::kBootImageRelRo:
     case HLoadString::LoadKind::kBssEntry:
-      DCHECK(!Runtime::Current()->UseJitCompilation());
+      DCHECK(!GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadString::LoadKind::kJitBootImageAddress:
     case HLoadString::LoadKind::kJitTableAddress:
-      DCHECK(Runtime::Current()->UseJitCompilation());
+      DCHECK(GetCompilerOptions().IsJitCompiler());
       break;
     case HLoadString::LoadKind::kRuntimeCall:
       break;
@@ -6213,18 +6473,20 @@
     case HLoadString::LoadKind::kBootImageLinkTimePcRelative: {
       DCHECK(codegen_->GetCompilerOptions().IsBootImage() ||
              codegen_->GetCompilerOptions().IsBootImageExtension());
-      __ leal(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip= */ false));
+      __ leal(out,
+              Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
       codegen_->RecordBootImageStringPatch(load);
       return;
     }
     case HLoadString::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
-      __ movl(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip= */ false));
-      codegen_->RecordBootImageRelRoPatch(codegen_->GetBootImageOffset(load));
+      __ movl(out,
+              Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
+      codegen_->RecordBootImageRelRoPatch(CodeGenerator::GetBootImageOffset(load));
       return;
     }
     case HLoadString::LoadKind::kBssEntry: {
-      Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset,
+      Address address = Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset,
                                           /* no_rip= */ false);
       Label* fixup_label = codegen_->NewStringBssEntryPatch(load);
       // /* GcRoot<mirror::Class> */ out = *address  /* PC-relative */
@@ -6244,7 +6506,7 @@
       return;
     }
     case HLoadString::LoadKind::kJitTableAddress: {
-      Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset,
+      Address address = Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset,
                                           /* no_rip= */ true);
       Label* fixup_label = codegen_->NewJitRootStringPatch(
           load->GetDexFile(), load->GetStringIndex(), load->GetString());
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 2e8d9b3..6038223 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -79,6 +79,31 @@
   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
 };
 
+class CriticalNativeCallingConventionVisitorX86_64 : public InvokeDexCallingConventionVisitor {
+ public:
+  explicit CriticalNativeCallingConventionVisitorX86_64(bool for_register_allocation)
+      : for_register_allocation_(for_register_allocation) {}
+
+  virtual ~CriticalNativeCallingConventionVisitorX86_64() {}
+
+  Location GetNextLocation(DataType::Type type) override;
+  Location GetReturnLocation(DataType::Type type) const override;
+  Location GetMethodLocation() const override;
+
+  size_t GetStackOffset() const { return stack_offset_; }
+
+ private:
+  // Register allocator does not support adjusting frame size, so we cannot provide final locations
+  // of stack arguments for register allocation. We ask the register allocator for any location and
+  // move these arguments to the right place after adjusting the SP when generating the call.
+  const bool for_register_allocation_;
+  size_t gpr_index_ = 0u;
+  size_t fpr_index_ = 0u;
+  size_t stack_offset_ = 0u;
+
+  DISALLOW_COPY_AND_ASSIGN(CriticalNativeCallingConventionVisitorX86_64);
+};
+
 class FieldAccessCallingConventionX86_64 : public FieldAccessCallingConvention {
  public:
   FieldAccessCallingConventionX86_64() {}
@@ -340,7 +365,7 @@
 
   size_t GetSlowPathFPWidth() const override {
     return GetGraph()->HasSIMD()
-        ? 2 * kX86_64WordSize   // 16 bytes == 2 x86_64 words for each spill
+        ? GetSIMDRegisterWidth()
         : 1 * kX86_64WordSize;  //  8 bytes == 1 x86_64 words for each spill
   }
 
@@ -348,6 +373,10 @@
     return 1 * kX86_64WordSize;
   }
 
+  size_t GetSIMDRegisterWidth() const override {
+    return 2 * kX86_64WordSize;
+  }
+
   HGraphVisitor* GetLocationBuilder() override {
     return &location_builder_;
   }
@@ -423,6 +452,7 @@
       const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
       ArtMethod* method) override;
 
+  void LoadMethod(MethodLoadKind load_kind, Location temp, HInvoke* invoke);
   void GenerateStaticOrDirectCall(
       HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
   void GenerateVirtualCall(
@@ -430,12 +460,13 @@
 
   void RecordBootImageIntrinsicPatch(uint32_t intrinsic_data);
   void RecordBootImageRelRoPatch(uint32_t boot_image_offset);
-  void RecordBootImageMethodPatch(HInvokeStaticOrDirect* invoke);
-  void RecordMethodBssEntryPatch(HInvokeStaticOrDirect* invoke);
+  void RecordBootImageMethodPatch(HInvoke* invoke);
+  void RecordMethodBssEntryPatch(HInvoke* invoke);
   void RecordBootImageTypePatch(HLoadClass* load_class);
   Label* NewTypeBssEntryPatch(HLoadClass* load_class);
   void RecordBootImageStringPatch(HLoadString* load_string);
   Label* NewStringBssEntryPatch(HLoadString* load_string);
+  void RecordBootImageJniEntrypointPatch(HInvokeStaticOrDirect* invoke);
   Label* NewJitRootStringPatch(const DexFile& dex_file,
                                dex::StringIndex string_index,
                                Handle<mirror::String> handle);
@@ -444,7 +475,7 @@
                               Handle<mirror::Class> handle);
 
   void LoadBootImageAddress(CpuRegister reg, uint32_t boot_image_reference);
-  void AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke, uint32_t boot_image_offset);
+  void LoadIntrinsicDeclaringClass(CpuRegister reg, HInvoke* invoke);
 
   void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) override;
 
@@ -597,6 +628,9 @@
     }
   }
 
+  void IncreaseFrame(size_t adjustment) override;
+  void DecreaseFrame(size_t adjustment) override;
+
   void GenerateNop() override;
   void GenerateImplicitNullCheck(HNullCheck* instruction) override;
   void GenerateExplicitNullCheck(HNullCheck* instruction) override;
@@ -605,9 +639,11 @@
 
   void MaybeIncrementHotness(bool is_frame_entry);
 
-  // When we don't know the proper offset for the value, we use kDummy32BitOffset.
+  static void BlockNonVolatileXmmRegisters(LocationSummary* locations);
+
+  // When we don't know the proper offset for the value, we use kPlaceholder32BitOffset.
   // We will fix this up in the linker later to have the right value.
-  static constexpr int32_t kDummy32BitOffset = 256;
+  static constexpr int32_t kPlaceholder32BitOffset = 256;
 
  private:
   template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)>
@@ -634,10 +670,16 @@
   ArenaDeque<PatchInfo<Label>> boot_image_type_patches_;
   // PC-relative type patch info for kBssEntry.
   ArenaDeque<PatchInfo<Label>> type_bss_entry_patches_;
+  // PC-relative public type patch info for kBssEntryPublic.
+  ArenaDeque<PatchInfo<Label>> public_type_bss_entry_patches_;
+  // PC-relative package type patch info for kBssEntryPackage.
+  ArenaDeque<PatchInfo<Label>> package_type_bss_entry_patches_;
   // PC-relative String patch info for kBootImageLinkTimePcRelative.
   ArenaDeque<PatchInfo<Label>> boot_image_string_patches_;
   // PC-relative String patch info for kBssEntry.
   ArenaDeque<PatchInfo<Label>> string_bss_entry_patches_;
+  // PC-relative method patch info for kBootImageLinkTimePcRelative+kCallCriticalNative.
+  ArenaDeque<PatchInfo<Label>> boot_image_jni_entrypoint_patches_;
   // PC-relative patch info for IntrinsicObjects for the boot image,
   // and for method/type/string patches for kBootImageRelRo otherwise.
   ArenaDeque<PatchInfo<Label>> boot_image_other_patches_;
diff --git a/compiler/optimizing/code_sinking.cc b/compiler/optimizing/code_sinking.cc
index f406983..49acab6 100644
--- a/compiler/optimizing/code_sinking.cc
+++ b/compiler/optimizing/code_sinking.cc
@@ -58,8 +58,8 @@
     }
   }
 
-  // Check allocations first, as they can throw, but it is safe to move them.
-  if (instruction->IsNewInstance() || instruction->IsNewArray()) {
+  // Check allocations and strings first, as they can throw, but it is safe to move them.
+  if (instruction->IsNewInstance() || instruction->IsNewArray() || instruction->IsLoadString()) {
     return true;
   }
 
@@ -107,6 +107,7 @@
   // hard to test, as LSE removes them.
   if (instruction->IsStaticFieldGet() ||
       instruction->IsInstanceFieldGet() ||
+      instruction->IsPredicatedInstanceFieldGet() ||
       instruction->IsArrayGet()) {
     return false;
   }
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index d9b4f79..c0441b0 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -81,8 +81,9 @@
     HGraph* graph = CreateCFG(data);
     // Remove suspend checks, they cannot be executed in this context.
     RemoveSuspendChecks(graph);
-    OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
-    RunCode(target_config, *compiler_options_, graph, [](HGraph*) {}, has_result, expected);
+    std::unique_ptr<CompilerOptions> compiler_options =
+        CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
+    RunCode(target_config, *compiler_options, graph, [](HGraph*) {}, has_result, expected);
   }
 }
 
@@ -93,8 +94,9 @@
     HGraph* graph = CreateCFG(data, DataType::Type::kInt64);
     // Remove suspend checks, they cannot be executed in this context.
     RemoveSuspendChecks(graph);
-    OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
-    RunCode(target_config, *compiler_options_, graph, [](HGraph*) {}, has_result, expected);
+    std::unique_ptr<CompilerOptions> compiler_options =
+        CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
+    RunCode(target_config, *compiler_options, graph, [](HGraph*) {}, has_result, expected);
   }
 }
 
@@ -445,7 +447,9 @@
 
     ASSERT_FALSE(equal->IsEmittedAtUseSite());
     graph->BuildDominatorTree();
-    PrepareForRegisterAllocation(graph, *compiler_options_).Run();
+    std::unique_ptr<CompilerOptions> compiler_options =
+        CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
+    PrepareForRegisterAllocation(graph, *compiler_options).Run();
     ASSERT_TRUE(equal->IsEmittedAtUseSite());
 
     auto hook_before_codegen = [](HGraph* graph_in) {
@@ -454,8 +458,7 @@
       block->InsertInstructionBefore(move, block->GetLastInstruction());
     };
 
-    OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
-    RunCode(target_config, *compiler_options_, graph, hook_before_codegen, true, 0);
+    RunCode(target_config, *compiler_options, graph, hook_before_codegen, true, 0);
   }
 }
 
@@ -501,8 +504,9 @@
             new (graph_in->GetAllocator()) HParallelMove(graph_in->GetAllocator());
         block->InsertInstructionBefore(move, block->GetLastInstruction());
       };
-      OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
-      RunCode(target_config, *compiler_options_, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
+      std::unique_ptr<CompilerOptions> compiler_options =
+          CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
+      RunCode(target_config, *compiler_options, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
     }
   }
 }
@@ -548,7 +552,7 @@
       HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]);
       HLessThan cmp_lt(cst_lhs, cst_rhs);
       if_block->AddInstruction(&cmp_lt);
-      // We insert a dummy instruction to separate the HIf from the HLessThan
+      // We insert a fake instruction to separate the HIf from the HLessThan
       // and force the materialization of the condition.
       HMemoryBarrier force_materialization(MemBarrierKind::kAnyAny, 0);
       if_block->AddInstruction(&force_materialization);
@@ -569,8 +573,9 @@
             new (graph_in->GetAllocator()) HParallelMove(graph_in->GetAllocator());
         block->InsertInstructionBefore(move, block->GetLastInstruction());
       };
-      OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
-      RunCode(target_config, *compiler_options_, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
+      std::unique_ptr<CompilerOptions> compiler_options =
+          CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
+      RunCode(target_config, *compiler_options, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
     }
   }
 }
@@ -679,8 +684,9 @@
   block->AddInstruction(new (GetAllocator()) HReturn(comparison));
 
   graph->BuildDominatorTree();
-  OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
-  RunCode(target_config, *compiler_options_, graph, [](HGraph*) {}, true, expected_result);
+  std::unique_ptr<CompilerOptions> compiler_options =
+      CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
+  RunCode(target_config, *compiler_options, graph, [](HGraph*) {}, true, expected_result);
 }
 
 TEST_F(CodegenTest, ComparisonsInt) {
@@ -711,9 +717,10 @@
 
 #ifdef ART_ENABLE_CODEGEN_arm
 TEST_F(CodegenTest, ARMVIXLParallelMoveResolver) {
-  OverrideInstructionSetFeatures(InstructionSet::kThumb2, "default");
+  std::unique_ptr<CompilerOptions> compiler_options =
+      CommonCompilerTest::CreateCompilerOptions(InstructionSet::kThumb2, "default");
   HGraph* graph = CreateGraph();
-  arm::CodeGeneratorARMVIXL codegen(graph, *compiler_options_);
+  arm::CodeGeneratorARMVIXL codegen(graph, *compiler_options);
 
   codegen.Initialize();
 
@@ -734,9 +741,10 @@
 #ifdef ART_ENABLE_CODEGEN_arm64
 // Regression test for b/34760542.
 TEST_F(CodegenTest, ARM64ParallelMoveResolverB34760542) {
-  OverrideInstructionSetFeatures(InstructionSet::kArm64, "default");
+  std::unique_ptr<CompilerOptions> compiler_options =
+      CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default");
   HGraph* graph = CreateGraph();
-  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options_);
+  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
 
   codegen.Initialize();
 
@@ -783,9 +791,10 @@
 
 // Check that ParallelMoveResolver works fine for ARM64 for both cases when SIMD is on and off.
 TEST_F(CodegenTest, ARM64ParallelMoveResolverSIMD) {
-  OverrideInstructionSetFeatures(InstructionSet::kArm64, "default");
+  std::unique_ptr<CompilerOptions> compiler_options =
+      CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default");
   HGraph* graph = CreateGraph();
-  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options_);
+  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
 
   codegen.Initialize();
 
@@ -818,9 +827,10 @@
 
 // Check that ART ISA Features are propagated to VIXL for arm64 (using cortex-a75 as example).
 TEST_F(CodegenTest, ARM64IsaVIXLFeaturesA75) {
-  OverrideInstructionSetFeatures(InstructionSet::kArm64, "cortex-a75");
+  std::unique_ptr<CompilerOptions> compiler_options =
+      CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "cortex-a75");
   HGraph* graph = CreateGraph();
-  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options_);
+  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
   vixl::CPUFeatures* features = codegen.GetVIXLAssembler()->GetCPUFeatures();
 
   EXPECT_TRUE(features->Has(vixl::CPUFeatures::kCRC32));
@@ -832,9 +842,10 @@
 
 // Check that ART ISA Features are propagated to VIXL for arm64 (using cortex-a53 as example).
 TEST_F(CodegenTest, ARM64IsaVIXLFeaturesA53) {
-  OverrideInstructionSetFeatures(InstructionSet::kArm64, "cortex-a53");
+  std::unique_ptr<CompilerOptions> compiler_options =
+      CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "cortex-a53");
   HGraph* graph = CreateGraph();
-  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options_);
+  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
   vixl::CPUFeatures* features = codegen.GetVIXLAssembler()->GetCPUFeatures();
 
   EXPECT_TRUE(features->Has(vixl::CPUFeatures::kCRC32));
@@ -850,9 +861,10 @@
 // allocated on stack per callee-saved FP register to be preserved in the frame entry as
 // ABI states.
 TEST_F(CodegenTest, ARM64FrameSizeSIMD) {
-  OverrideInstructionSetFeatures(InstructionSet::kArm64, "default");
+  std::unique_ptr<CompilerOptions> compiler_options =
+      CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default");
   HGraph* graph = CreateGraph();
-  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options_);
+  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
 
   codegen.Initialize();
   graph->SetHasSIMD(true);
@@ -869,9 +881,10 @@
 }
 
 TEST_F(CodegenTest, ARM64FrameSizeNoSIMD) {
-  OverrideInstructionSetFeatures(InstructionSet::kArm64, "default");
+  std::unique_ptr<CompilerOptions> compiler_options =
+      CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default");
   HGraph* graph = CreateGraph();
-  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options_);
+  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
 
   codegen.Initialize();
   graph->SetHasSIMD(false);
diff --git a/compiler/optimizing/codegen_test_utils.h b/compiler/optimizing/codegen_test_utils.h
index 9fbd7d6..397e601 100644
--- a/compiler/optimizing/codegen_test_utils.h
+++ b/compiler/optimizing/codegen_test_utils.h
@@ -248,9 +248,17 @@
                 Expected expected) {
   InstructionSet target_isa = codegen.GetInstructionSet();
 
+  struct CodeHolder : CommonCompilerTestImpl {
+   protected:
+    ClassLinker* GetClassLinker() override { return nullptr; }
+    Runtime* GetRuntime() override { return nullptr; }
+  };
+  CodeHolder code_holder;
+  const void* code_ptr =
+      code_holder.MakeExecutable(allocator.GetMemory(), ArrayRef<const uint8_t>(), target_isa);
+
   typedef Expected (*fptr)();
-  CommonCompilerTest::MakeExecutable(allocator.GetMemory().data(), allocator.GetMemory().size());
-  fptr f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(allocator.GetMemory().data()));
+  fptr f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(code_ptr));
   if (target_isa == InstructionSet::kThumb2) {
     // For thumb we need the bottom bit set.
     f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(f) + 1);
@@ -313,25 +321,25 @@
 }
 
 #ifdef ART_ENABLE_CODEGEN_arm
-CodeGenerator* create_codegen_arm_vixl32(HGraph* graph, const CompilerOptions& compiler_options) {
+inline CodeGenerator* create_codegen_arm_vixl32(HGraph* graph, const CompilerOptions& compiler_options) {
   return new (graph->GetAllocator()) TestCodeGeneratorARMVIXL(graph, compiler_options);
 }
 #endif
 
 #ifdef ART_ENABLE_CODEGEN_arm64
-CodeGenerator* create_codegen_arm64(HGraph* graph, const CompilerOptions& compiler_options) {
+inline CodeGenerator* create_codegen_arm64(HGraph* graph, const CompilerOptions& compiler_options) {
   return new (graph->GetAllocator()) TestCodeGeneratorARM64(graph, compiler_options);
 }
 #endif
 
 #ifdef ART_ENABLE_CODEGEN_x86
-CodeGenerator* create_codegen_x86(HGraph* graph, const CompilerOptions& compiler_options) {
+inline CodeGenerator* create_codegen_x86(HGraph* graph, const CompilerOptions& compiler_options) {
   return new (graph->GetAllocator()) TestCodeGeneratorX86(graph, compiler_options);
 }
 #endif
 
 #ifdef ART_ENABLE_CODEGEN_x86_64
-CodeGenerator* create_codegen_x86_64(HGraph* graph, const CompilerOptions& compiler_options) {
+inline CodeGenerator* create_codegen_x86_64(HGraph* graph, const CompilerOptions& compiler_options) {
   return new (graph->GetAllocator()) x86_64::CodeGeneratorX86_64(graph, compiler_options);
 }
 #endif
diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h
index 41f284f..81c6561 100644
--- a/compiler/optimizing/common_arm64.h
+++ b/compiler/optimizing/common_arm64.h
@@ -65,12 +65,12 @@
 
 inline vixl::aarch64::Register XRegisterFrom(Location location) {
   DCHECK(location.IsRegister()) << location;
-  return vixl::aarch64::Register::GetXRegFromCode(VIXLRegCodeFromART(location.reg()));
+  return vixl::aarch64::XRegister(VIXLRegCodeFromART(location.reg()));
 }
 
 inline vixl::aarch64::Register WRegisterFrom(Location location) {
   DCHECK(location.IsRegister()) << location;
-  return vixl::aarch64::Register::GetWRegFromCode(VIXLRegCodeFromART(location.reg()));
+  return vixl::aarch64::WRegister(VIXLRegCodeFromART(location.reg()));
 }
 
 inline vixl::aarch64::Register RegisterFrom(Location location, DataType::Type type) {
@@ -89,27 +89,32 @@
 
 inline vixl::aarch64::VRegister DRegisterFrom(Location location) {
   DCHECK(location.IsFpuRegister()) << location;
-  return vixl::aarch64::VRegister::GetDRegFromCode(location.reg());
+  return vixl::aarch64::DRegister(location.reg());
 }
 
 inline vixl::aarch64::VRegister QRegisterFrom(Location location) {
   DCHECK(location.IsFpuRegister()) << location;
-  return vixl::aarch64::VRegister::GetQRegFromCode(location.reg());
+  return vixl::aarch64::QRegister(location.reg());
 }
 
 inline vixl::aarch64::VRegister VRegisterFrom(Location location) {
   DCHECK(location.IsFpuRegister()) << location;
-  return vixl::aarch64::VRegister::GetVRegFromCode(location.reg());
+  return vixl::aarch64::VRegister(location.reg());
+}
+
+inline vixl::aarch64::ZRegister ZRegisterFrom(Location location) {
+  DCHECK(location.IsFpuRegister()) << location;
+  return vixl::aarch64::ZRegister(location.reg());
 }
 
 inline vixl::aarch64::VRegister SRegisterFrom(Location location) {
   DCHECK(location.IsFpuRegister()) << location;
-  return vixl::aarch64::VRegister::GetSRegFromCode(location.reg());
+  return vixl::aarch64::SRegister(location.reg());
 }
 
 inline vixl::aarch64::VRegister HRegisterFrom(Location location) {
   DCHECK(location.IsFpuRegister()) << location;
-  return vixl::aarch64::VRegister::GetHRegFromCode(location.reg());
+  return vixl::aarch64::HRegister(location.reg());
 }
 
 inline vixl::aarch64::VRegister FPRegisterFrom(Location location, DataType::Type type) {
@@ -177,6 +182,10 @@
   return vixl::aarch64::MemOperand(vixl::aarch64::sp, location.GetStackIndex());
 }
 
+inline vixl::aarch64::SVEMemOperand SveStackOperandFrom(Location location) {
+  return vixl::aarch64::SVEMemOperand(vixl::aarch64::sp, location.GetStackIndex());
+}
+
 inline vixl::aarch64::MemOperand HeapOperand(const vixl::aarch64::Register& base,
                                                     size_t offset = 0) {
   // A heap reference must be 32bit, so fit in a W register.
@@ -210,6 +219,10 @@
   return Location::FpuRegisterLocation(fpreg.GetCode());
 }
 
+inline Location LocationFrom(const vixl::aarch64::ZRegister& zreg) {
+  return Location::FpuRegisterLocation(zreg.GetCode());
+}
+
 inline vixl::aarch64::Operand OperandFromMemOperand(
     const vixl::aarch64::MemOperand& mem_op) {
   if (mem_op.IsImmediateOffset()) {
@@ -298,7 +311,7 @@
 }
 
 inline Location ARM64EncodableConstantOrRegister(HInstruction* constant,
-                                                        HInstruction* instr) {
+                                                 HInstruction* instr) {
   if (constant->IsConstant()
       && Arm64CanEncodeConstantAsImmediate(constant->AsConstant(), instr)) {
     return Location::ConstantLocation(constant->AsConstant());
diff --git a/compiler/optimizing/critical_native_abi_fixup_arm.cc b/compiler/optimizing/critical_native_abi_fixup_arm.cc
new file mode 100644
index 0000000..3c4db4b
--- /dev/null
+++ b/compiler/optimizing/critical_native_abi_fixup_arm.cc
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 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 "critical_native_abi_fixup_arm.h"
+
+#include "art_method-inl.h"
+#include "intrinsics.h"
+#include "jni/jni_internal.h"
+#include "nodes.h"
+#include "scoped_thread_state_change-inl.h"
+#include "well_known_classes.h"
+
+namespace art {
+namespace arm {
+
+// Fix up FP arguments passed in core registers for call to @CriticalNative by inserting fake calls
+// to Float.floatToRawIntBits() or Double.doubleToRawLongBits() to satisfy type consistency checks.
+static void FixUpArguments(HInvokeStaticOrDirect* invoke) {
+  DCHECK_EQ(invoke->GetCodePtrLocation(), CodePtrLocation::kCallCriticalNative);
+  size_t reg = 0u;
+  for (size_t i = 0, num_args = invoke->GetNumberOfArguments(); i != num_args; ++i) {
+    HInstruction* input = invoke->InputAt(i);
+    DataType::Type input_type = input->GetType();
+    size_t next_reg = reg + 1u;
+    if (DataType::Is64BitType(input_type)) {
+      reg = RoundUp(reg, 2u);
+      next_reg = reg + 2u;
+    }
+    if (reg == 4u) {
+      break;  // Remaining arguments are passed on stack.
+    }
+    if (DataType::IsFloatingPointType(input_type)) {
+      bool is_double = (input_type == DataType::Type::kFloat64);
+      DataType::Type converted_type = is_double ? DataType::Type::kInt64 : DataType::Type::kInt32;
+      jmethodID known_method = is_double ? WellKnownClasses::java_lang_Double_doubleToRawLongBits
+                                         : WellKnownClasses::java_lang_Float_floatToRawIntBits;
+      ArtMethod* resolved_method = jni::DecodeArtMethod(known_method);
+      DCHECK(resolved_method != nullptr);
+      DCHECK(resolved_method->IsIntrinsic());
+      MethodReference target_method(nullptr, 0);
+      {
+        ScopedObjectAccess soa(Thread::Current());
+        target_method =
+            MethodReference(resolved_method->GetDexFile(), resolved_method->GetDexMethodIndex());
+      }
+      // Use arbitrary dispatch info that does not require the method argument.
+      HInvokeStaticOrDirect::DispatchInfo dispatch_info = {
+          MethodLoadKind::kBssEntry,
+          CodePtrLocation::kCallArtMethod,
+          /*method_load_data=*/ 0u
+      };
+      HBasicBlock* block = invoke->GetBlock();
+      ArenaAllocator* allocator = block->GetGraph()->GetAllocator();
+      HInvokeStaticOrDirect* new_input = new (allocator) HInvokeStaticOrDirect(
+          allocator,
+          /*number_of_arguments=*/ 1u,
+          converted_type,
+          invoke->GetDexPc(),
+          /*method_reference=*/ MethodReference(nullptr, dex::kDexNoIndex),
+          resolved_method,
+          dispatch_info,
+          kStatic,
+          target_method,
+          HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+      // The intrinsic has no side effects and does not need environment or dex cache on ARM.
+      new_input->SetSideEffects(SideEffects::None());
+      IntrinsicOptimizations opt(new_input);
+      opt.SetDoesNotNeedEnvironment();
+      new_input->SetRawInputAt(0u, input);
+      block->InsertInstructionBefore(new_input, invoke);
+      invoke->ReplaceInput(new_input, i);
+    }
+    reg = next_reg;
+  }
+}
+
+bool CriticalNativeAbiFixupArm::Run() {
+  if (!graph_->HasDirectCriticalNativeCall()) {
+    return false;
+  }
+
+  for (HBasicBlock* block : graph_->GetReversePostOrder()) {
+    for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
+      HInstruction* instruction = it.Current();
+      if (instruction->IsInvokeStaticOrDirect() &&
+          instruction->AsInvokeStaticOrDirect()->GetCodePtrLocation() ==
+              CodePtrLocation::kCallCriticalNative) {
+        FixUpArguments(instruction->AsInvokeStaticOrDirect());
+      }
+    }
+  }
+  return true;
+}
+
+}  // namespace arm
+}  // namespace art
diff --git a/compiler/optimizing/critical_native_abi_fixup_arm.h b/compiler/optimizing/critical_native_abi_fixup_arm.h
new file mode 100644
index 0000000..faa3c7a
--- /dev/null
+++ b/compiler/optimizing/critical_native_abi_fixup_arm.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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_COMPILER_OPTIMIZING_CRITICAL_NATIVE_ABI_FIXUP_ARM_H_
+#define ART_COMPILER_OPTIMIZING_CRITICAL_NATIVE_ABI_FIXUP_ARM_H_
+
+#include "nodes.h"
+#include "optimization.h"
+
+namespace art {
+namespace arm {
+
+class CriticalNativeAbiFixupArm : public HOptimization {
+ public:
+  CriticalNativeAbiFixupArm(HGraph* graph, OptimizingCompilerStats* stats)
+      : HOptimization(graph, kCriticalNativeAbiFixupArmPassName, stats) {}
+
+  static constexpr const char* kCriticalNativeAbiFixupArmPassName =
+      "critical_native_abi_fixup_arm";
+
+  bool Run() override;
+};
+
+}  // namespace arm
+}  // namespace art
+
+#endif  // ART_COMPILER_OPTIMIZING_CRITICAL_NATIVE_ABI_FIXUP_ARM_H_
diff --git a/compiler/optimizing/data_type-inl.h b/compiler/optimizing/data_type-inl.h
index 94807e8..1b33b77 100644
--- a/compiler/optimizing/data_type-inl.h
+++ b/compiler/optimizing/data_type-inl.h
@@ -40,6 +40,25 @@
   UNREACHABLE();
 }
 
+// Note: Not declared in data_type.h to avoid pulling in "primitive.h".
+constexpr Primitive::Type DataTypeToPrimitive(DataType::Type type) {
+  switch (type) {
+    case DataType::Type::kReference: return Primitive::kPrimNot;
+    case DataType::Type::kBool: return Primitive::kPrimBoolean;
+    case DataType::Type::kInt8: return Primitive::kPrimByte;
+    case DataType::Type::kUint16: return Primitive::kPrimChar;
+    case DataType::Type::kInt16: return Primitive::kPrimShort;
+    case DataType::Type::kInt32: return Primitive::kPrimInt;
+    case DataType::Type::kInt64: return Primitive::kPrimLong;
+    case DataType::Type::kFloat32: return Primitive::kPrimFloat;
+    case DataType::Type::kFloat64: return Primitive::kPrimDouble;
+    case DataType::Type::kVoid: return Primitive::kPrimVoid;
+    default:
+      LOG(FATAL) << "Unexpected type " << type;
+      UNREACHABLE();
+  }
+}
+
 constexpr DataType::Type DataType::FromShorty(char type) {
   return DataTypeFromPrimitive(Primitive::GetType(type));
 }
diff --git a/compiler/optimizing/data_type.h b/compiler/optimizing/data_type.h
index 3cbcc9e..ec6ca7a 100644
--- a/compiler/optimizing/data_type.h
+++ b/compiler/optimizing/data_type.h
@@ -131,6 +131,10 @@
     return type == Type::kUint64 || type == Type::kInt64 || type == Type::kFloat64;
   }
 
+  static bool Is8BitType(Type type) {
+    return type == Type::kInt8 || type == Type::kUint8 || type == Type::kBool;
+  }
+
   static bool IsUnsignedType(Type type) {
     return type == Type::kBool || type == Type::kUint8 || type == Type::kUint16 ||
         type == Type::kUint32 || type == Type::kUint64;
diff --git a/compiler/optimizing/escape.cc b/compiler/optimizing/escape.cc
index 2b578c1..617833c 100644
--- a/compiler/optimizing/escape.cc
+++ b/compiler/optimizing/escape.cc
@@ -20,8 +20,76 @@
 
 namespace art {
 
+void VisitEscapes(HInstruction* reference, EscapeVisitor& escape_visitor) {
+  // References not allocated in the method are intrinsically escaped.
+  // Finalizable references are always escaping since they end up in FinalizerQueues.
+  if ((!reference->IsNewInstance() && !reference->IsNewArray()) ||
+      (reference->IsNewInstance() && reference->AsNewInstance()->IsFinalizable())) {
+    if (!escape_visitor(reference)) {
+      return;
+    }
+  }
+
+  // Visit all uses to determine if this reference can escape into the heap,
+  // a method call, an alias, etc.
+  for (const HUseListNode<HInstruction*>& use : reference->GetUses()) {
+    HInstruction* user = use.GetUser();
+    if (user->IsBoundType() || user->IsNullCheck()) {
+      // BoundType shouldn't normally be necessary for an allocation. Just be conservative
+      // for the uncommon cases. Similarly, null checks are eventually eliminated for explicit
+      // allocations, but if we see one before it is simplified, assume an alias.
+      if (!escape_visitor(user)) {
+        return;
+      }
+    } else if (user->IsCheckCast() || user->IsInstanceOf()) {
+      // TODO Currently we'll just be conservative for Partial LSE and avoid
+      // optimizing check-cast things since we'd need to add blocks otherwise.
+      // Normally the simplifier should be able to just get rid of them
+      if (!escape_visitor(user)) {
+        return;
+      }
+    } else if (user->IsPhi() ||
+               user->IsSelect() ||
+               (user->IsInvoke() && user->GetSideEffects().DoesAnyWrite()) ||
+               (user->IsInstanceFieldSet() && (reference == user->InputAt(1))) ||
+               (user->IsUnresolvedInstanceFieldSet() && (reference == user->InputAt(1))) ||
+               (user->IsStaticFieldSet() && (reference == user->InputAt(1))) ||
+               (user->IsUnresolvedStaticFieldSet() && (reference == user->InputAt(0))) ||
+               (user->IsArraySet() && (reference == user->InputAt(2)))) {
+      // The reference is merged to HPhi/HSelect, passed to a callee, or stored to heap.
+      // Hence, the reference is no longer the only name that can refer to its value.
+      if (!escape_visitor(user)) {
+        return;
+      }
+    } else if ((user->IsUnresolvedInstanceFieldGet() && (reference == user->InputAt(0))) ||
+               (user->IsUnresolvedInstanceFieldSet() && (reference == user->InputAt(0)))) {
+      // The field is accessed in an unresolved way. We mark the object as a non-singleton.
+      // Note that we could optimize this case and still perform some optimizations until
+      // we hit the unresolved access, but the conservative assumption is the simplest.
+      if (!escape_visitor(user)) {
+        return;
+      }
+    } else if (user->IsReturn()) {
+      if (!escape_visitor(user)) {
+        return;
+      }
+    }
+  }
+
+  // Look at the environment uses if it's for HDeoptimize. Other environment uses are fine,
+  // as long as client optimizations that rely on this information are disabled for debuggable.
+  for (const HUseListNode<HEnvironment*>& use : reference->GetEnvUses()) {
+    HEnvironment* user = use.GetUser();
+    if (user->GetHolder()->IsDeoptimize()) {
+      if (!escape_visitor(user->GetHolder())) {
+        return;
+      }
+    }
+  }
+}
+
 void CalculateEscape(HInstruction* reference,
-                     bool (*no_escape)(HInstruction*, HInstruction*),
+                     NoEscapeCheck& no_escape,
                      /*out*/ bool* is_singleton,
                      /*out*/ bool* is_singleton_and_not_returned,
                      /*out*/ bool* is_singleton_and_not_deopt_visible) {
@@ -42,61 +110,35 @@
     *is_singleton_and_not_returned = false;
   }
 
-  // Visit all uses to determine if this reference can escape into the heap,
-  // a method call, an alias, etc.
-  for (const HUseListNode<HInstruction*>& use : reference->GetUses()) {
-    HInstruction* user = use.GetUser();
-    if (no_escape != nullptr && (*no_escape)(reference, user)) {
-      // Client supplied analysis says there is no escape.
-      continue;
-    } else if (user->IsBoundType() || user->IsNullCheck()) {
-      // BoundType shouldn't normally be necessary for an allocation. Just be conservative
-      // for the uncommon cases. Similarly, null checks are eventually eliminated for explicit
-      // allocations, but if we see one before it is simplified, assume an alias.
+  LambdaEscapeVisitor visitor([&](HInstruction* escape) -> bool {
+    if (escape == reference || no_escape(reference, escape)) {
+      // Ignore already known inherent escapes and escapes client supplied
+      // analysis knows is safe. Continue on.
+      return true;
+    } else if (escape->IsInstanceOf() || escape->IsCheckCast()) {
+      // Ignore since these are not relevant for regular LSE.
+      return true;
+    } else if (escape->IsReturn()) {
+      // value is returned but might still be singleton. Continue on.
+      *is_singleton_and_not_returned = false;
+      return true;
+    } else if (escape->IsDeoptimize()) {
+      // value escapes through deopt but might still be singleton. Continue on.
+      *is_singleton_and_not_deopt_visible = false;
+      return true;
+    } else {
+      // Real escape. All knowledge about what happens to the value lost. We can
+      // stop here.
       *is_singleton = false;
       *is_singleton_and_not_returned = false;
       *is_singleton_and_not_deopt_visible = false;
-      return;
-    } else if (user->IsPhi() ||
-               user->IsSelect() ||
-               (user->IsInvoke() && user->GetSideEffects().DoesAnyWrite()) ||
-               (user->IsInstanceFieldSet() && (reference == user->InputAt(1))) ||
-               (user->IsUnresolvedInstanceFieldSet() && (reference == user->InputAt(1))) ||
-               (user->IsStaticFieldSet() && (reference == user->InputAt(1))) ||
-               (user->IsUnresolvedStaticFieldSet() && (reference == user->InputAt(0))) ||
-               (user->IsArraySet() && (reference == user->InputAt(2)))) {
-      // The reference is merged to HPhi/HSelect, passed to a callee, or stored to heap.
-      // Hence, the reference is no longer the only name that can refer to its value.
-      *is_singleton = false;
-      *is_singleton_and_not_returned = false;
-      *is_singleton_and_not_deopt_visible = false;
-      return;
-    } else if ((user->IsUnresolvedInstanceFieldGet() && (reference == user->InputAt(0))) ||
-               (user->IsUnresolvedInstanceFieldSet() && (reference == user->InputAt(0)))) {
-      // The field is accessed in an unresolved way. We mark the object as a non-singleton.
-      // Note that we could optimize this case and still perform some optimizations until
-      // we hit the unresolved access, but the conservative assumption is the simplest.
-      *is_singleton = false;
-      *is_singleton_and_not_returned = false;
-      *is_singleton_and_not_deopt_visible = false;
-      return;
-    } else if (user->IsReturn()) {
-      *is_singleton_and_not_returned = false;
+      return false;
     }
-  }
-
-  // Look at the environment uses if it's for HDeoptimize. Other environment uses are fine,
-  // as long as client optimizations that rely on this information are disabled for debuggable.
-  for (const HUseListNode<HEnvironment*>& use : reference->GetEnvUses()) {
-    HEnvironment* user = use.GetUser();
-    if (user->GetHolder()->IsDeoptimize()) {
-      *is_singleton_and_not_deopt_visible = false;
-      break;
-    }
-  }
+  });
+  VisitEscapes(reference, visitor);
 }
 
-bool DoesNotEscape(HInstruction* reference, bool (*no_escape)(HInstruction*, HInstruction*)) {
+bool DoesNotEscape(HInstruction* reference, NoEscapeCheck& no_escape) {
   bool is_singleton = false;
   bool is_singleton_and_not_returned = false;
   bool is_singleton_and_not_deopt_visible = false;  // not relevant for escape
diff --git a/compiler/optimizing/escape.h b/compiler/optimizing/escape.h
index 75e37b0..5402cb1 100644
--- a/compiler/optimizing/escape.h
+++ b/compiler/optimizing/escape.h
@@ -26,6 +26,59 @@
  * allocation is visible outside ('escapes') its immediate method context.
  */
 
+// A visitor for seeing all instructions escape analysis considers escaping.
+// Called with each user of the reference passed to 'VisitEscapes'. Return true
+// to continue iteration and false to stop.
+class EscapeVisitor {
+ public:
+  virtual ~EscapeVisitor() {}
+  virtual bool Visit(HInstruction* escape) = 0;
+  bool operator()(HInstruction* user) {
+    return Visit(user);
+  }
+};
+
+// An explicit EscapeVisitor for lambdas
+template <typename F>
+class LambdaEscapeVisitor final : public EscapeVisitor {
+ public:
+  explicit LambdaEscapeVisitor(F f) : func_(f) {}
+  bool Visit(HInstruction* escape) override {
+    return func_(escape);
+  }
+
+ private:
+  F func_;
+};
+
+// This functor is used with the escape-checking functions. If the NoEscape
+// function returns true escape analysis will consider 'user' to not have
+// escaped 'reference'. This allows clients with additional information to
+// supplement the escape-analysis. If the NoEscape function returns false then
+// the normal escape-checking code will be used to determine whether or not
+// 'reference' escapes.
+class NoEscapeCheck {
+ public:
+  virtual ~NoEscapeCheck() {}
+  virtual bool NoEscape(HInstruction* reference, HInstruction* user) = 0;
+  bool operator()(HInstruction* ref, HInstruction* user) {
+    return NoEscape(ref, user);
+  }
+};
+
+// An explicit NoEscapeCheck for use with c++ lambdas.
+template <typename F>
+class LambdaNoEscapeCheck final : public NoEscapeCheck {
+ public:
+  explicit LambdaNoEscapeCheck(F f) : func_(f) {}
+  bool NoEscape(HInstruction* ref, HInstruction* user) override {
+    return func_(ref, user);
+  }
+
+ private:
+  F func_;
+};
+
 /*
  * Performs escape analysis on the given instruction, typically a reference to an
  * allocation. The method assigns true to parameter 'is_singleton' if the reference
@@ -52,16 +105,44 @@
  * analysis is applied to the user instead.
  */
 void CalculateEscape(HInstruction* reference,
-                     bool (*no_escape)(HInstruction*, HInstruction*),
+                     NoEscapeCheck& no_escape,
                      /*out*/ bool* is_singleton,
                      /*out*/ bool* is_singleton_and_not_returned,
                      /*out*/ bool* is_singleton_and_not_deopt_visible);
 
+inline void CalculateEscape(HInstruction* reference,
+                            bool (*no_escape_fn)(HInstruction*, HInstruction*),
+                            /*out*/ bool* is_singleton,
+                            /*out*/ bool* is_singleton_and_not_returned,
+                            /*out*/ bool* is_singleton_and_not_deopt_visible) {
+  LambdaNoEscapeCheck esc(no_escape_fn);
+  LambdaNoEscapeCheck noop_esc([](HInstruction*, HInstruction*) { return false; });
+  CalculateEscape(reference,
+                  no_escape_fn == nullptr ? static_cast<NoEscapeCheck&>(noop_esc) : esc,
+                  is_singleton,
+                  is_singleton_and_not_returned,
+                  is_singleton_and_not_deopt_visible);
+}
+
+/*
+ * Performs escape analysis and visits each escape of the reference. Does not try to calculate any
+ * overall information about the method. Escapes are calculated in the same way as CalculateEscape.
+ *
+ * The escape_visitor should return true to continue visiting, false otherwise.
+ */
+void VisitEscapes(HInstruction* reference, EscapeVisitor& escape_visitor);
+
 /*
  * Convenience method for testing the singleton and not returned properties at once.
  * Callers should be aware that this method invokes the full analysis at each call.
  */
-bool DoesNotEscape(HInstruction* reference, bool (*no_escape)(HInstruction*, HInstruction*));
+bool DoesNotEscape(HInstruction* reference, NoEscapeCheck& no_escape);
+
+inline bool DoesNotEscape(HInstruction* reference,
+                          bool (*no_escape_fn)(HInstruction*, HInstruction*)) {
+  LambdaNoEscapeCheck<typeof(no_escape_fn)> esc(no_escape_fn);
+  return DoesNotEscape(reference, esc);
+}
 
 }  // namespace art
 
diff --git a/compiler/optimizing/execution_subgraph.cc b/compiler/optimizing/execution_subgraph.cc
new file mode 100644
index 0000000..6d10566
--- /dev/null
+++ b/compiler/optimizing/execution_subgraph.cc
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2020 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 "execution_subgraph.h"
+
+#include <algorithm>
+#include <unordered_set>
+
+#include "android-base/macros.h"
+#include "base/arena_allocator.h"
+#include "base/arena_bit_vector.h"
+#include "base/globals.h"
+#include "base/scoped_arena_allocator.h"
+#include "nodes.h"
+
+namespace art {
+
+ExecutionSubgraph::ExecutionSubgraph(HGraph* graph, ScopedArenaAllocator* allocator)
+    : graph_(graph),
+      allocator_(allocator),
+      allowed_successors_(graph_->GetBlocks().size(),
+                          ~(std::bitset<kMaxFilterableSuccessors> {}),
+                          allocator_->Adapter(kArenaAllocLSA)),
+      unreachable_blocks_(
+          allocator_, graph_->GetBlocks().size(), /*expandable=*/ false, kArenaAllocLSA),
+      valid_(true),
+      needs_prune_(false),
+      finalized_(false) {
+  if (valid_) {
+    DCHECK(std::all_of(graph->GetBlocks().begin(), graph->GetBlocks().end(), [](HBasicBlock* it) {
+      return it == nullptr || it->GetSuccessors().size() <= kMaxFilterableSuccessors;
+    }));
+  }
+}
+
+void ExecutionSubgraph::RemoveBlock(const HBasicBlock* to_remove) {
+  if (!valid_) {
+    return;
+  }
+  uint32_t id = to_remove->GetBlockId();
+  if (unreachable_blocks_.IsBitSet(id)) {
+    if (kIsDebugBuild) {
+      // This isn't really needed but it's good to have this so it functions as
+      // a DCHECK that we always call Prune after removing any block.
+      needs_prune_ = true;
+    }
+    return;
+  }
+  unreachable_blocks_.SetBit(id);
+  for (HBasicBlock* pred : to_remove->GetPredecessors()) {
+    std::bitset<kMaxFilterableSuccessors> allowed_successors {};
+    // ZipCount iterates over both the successors and the index of them at the same time.
+    for (auto [succ, i] : ZipCount(MakeIterationRange(pred->GetSuccessors()))) {
+      if (succ != to_remove) {
+        allowed_successors.set(i);
+      }
+    }
+    LimitBlockSuccessors(pred, allowed_successors);
+  }
+}
+
+// Removes sink nodes.
+void ExecutionSubgraph::Prune() {
+  if (UNLIKELY(!valid_)) {
+    return;
+  }
+  needs_prune_ = false;
+  // This is the record of the edges that were both (1) explored and (2) reached
+  // the exit node.
+  {
+    // Allocator for temporary values.
+    ScopedArenaAllocator temporaries(graph_->GetArenaStack());
+    ScopedArenaVector<std::bitset<kMaxFilterableSuccessors>> results(
+        graph_->GetBlocks().size(), temporaries.Adapter(kArenaAllocLSA));
+    unreachable_blocks_.ClearAllBits();
+    // TODO We should support infinite loops as well.
+    if (UNLIKELY(graph_->GetExitBlock() == nullptr)) {
+      // Infinite loop
+      valid_ = false;
+      return;
+    }
+    // Fills up the 'results' map with what we need to add to update
+    // allowed_successors in order to prune sink nodes.
+    bool start_reaches_end = false;
+    // This is basically a DFS of the graph with some edges skipped.
+    {
+      const size_t num_blocks = graph_->GetBlocks().size();
+      constexpr ssize_t kUnvisitedSuccIdx = -1;
+      ArenaBitVector visiting(&temporaries, num_blocks, false, kArenaAllocLSA);
+      // How many of the successors of each block we have already examined. This
+      // has three states.
+      // (1) kUnvisitedSuccIdx: we have not examined any edges,
+      // (2) 0 <= val < # of successors: we have examined 'val' successors/are
+      // currently examining successors_[val],
+      // (3) kMaxFilterableSuccessors: We have examined all of the successors of
+      // the block (the 'result' is final).
+      ScopedArenaVector<ssize_t> last_succ_seen(
+          num_blocks, kUnvisitedSuccIdx, temporaries.Adapter(kArenaAllocLSA));
+      // A stack of which blocks we are visiting in this DFS traversal. Does not
+      // include the current-block. Used with last_succ_seen to figure out which
+      // bits to set if we find a path to the end/loop.
+      ScopedArenaVector<uint32_t> current_path(temporaries.Adapter(kArenaAllocLSA));
+      // Just ensure we have enough space. The allocator will be cleared shortly
+      // anyway so this is fast.
+      current_path.reserve(num_blocks);
+      // Current block we are examining. Modified only by 'push_block' and 'pop_block'
+      const HBasicBlock* cur_block = graph_->GetEntryBlock();
+      // Used to note a recur where we will start iterating on 'blk' and save
+      // where we are. We must 'continue' immediately after this.
+      auto push_block = [&](const HBasicBlock* blk) {
+        DCHECK(std::find(current_path.cbegin(), current_path.cend(), cur_block->GetBlockId()) ==
+               current_path.end());
+        if (kIsDebugBuild) {
+          std::for_each(current_path.cbegin(), current_path.cend(), [&](auto id) {
+            DCHECK_GT(last_succ_seen[id], kUnvisitedSuccIdx) << id;
+            DCHECK_LT(last_succ_seen[id], static_cast<ssize_t>(kMaxFilterableSuccessors)) << id;
+          });
+        }
+        current_path.push_back(cur_block->GetBlockId());
+        visiting.SetBit(cur_block->GetBlockId());
+        cur_block = blk;
+      };
+      // Used to note that we have fully explored a block and should return back
+      // up. Sets cur_block appropriately. We must 'continue' immediately after
+      // calling this.
+      auto pop_block = [&]() {
+        if (UNLIKELY(current_path.empty())) {
+          // Should only happen if entry-blocks successors are exhausted.
+          DCHECK_GE(last_succ_seen[graph_->GetEntryBlock()->GetBlockId()],
+                    static_cast<ssize_t>(graph_->GetEntryBlock()->GetSuccessors().size()));
+          cur_block = nullptr;
+        } else {
+          const HBasicBlock* last = graph_->GetBlocks()[current_path.back()];
+          visiting.ClearBit(current_path.back());
+          current_path.pop_back();
+          cur_block = last;
+        }
+      };
+      // Mark the current path as a path to the end. This is in contrast to paths
+      // that end in (eg) removed blocks.
+      auto propagate_true = [&]() {
+        for (uint32_t id : current_path) {
+          DCHECK_GT(last_succ_seen[id], kUnvisitedSuccIdx);
+          DCHECK_LT(last_succ_seen[id], static_cast<ssize_t>(kMaxFilterableSuccessors));
+          results[id].set(last_succ_seen[id]);
+        }
+      };
+      ssize_t num_entry_succ = graph_->GetEntryBlock()->GetSuccessors().size();
+      // As long as the entry-block has not explored all successors we still have
+      // work to do.
+      const uint32_t entry_block_id = graph_->GetEntryBlock()->GetBlockId();
+      while (num_entry_succ > last_succ_seen[entry_block_id]) {
+        DCHECK(cur_block != nullptr);
+        uint32_t id = cur_block->GetBlockId();
+        DCHECK((current_path.empty() && cur_block == graph_->GetEntryBlock()) ||
+               current_path.front() == graph_->GetEntryBlock()->GetBlockId())
+            << "current path size: " << current_path.size()
+            << " cur_block id: " << cur_block->GetBlockId() << " entry id "
+            << graph_->GetEntryBlock()->GetBlockId();
+        DCHECK(!visiting.IsBitSet(id))
+            << "Somehow ended up in a loop! This should have been caught before now! " << id;
+        std::bitset<kMaxFilterableSuccessors>& result = results[id];
+        if (cur_block == graph_->GetExitBlock()) {
+          start_reaches_end = true;
+          propagate_true();
+          pop_block();
+          continue;
+        } else if (last_succ_seen[id] == kMaxFilterableSuccessors) {
+          // Already fully explored.
+          if (result.any()) {
+            propagate_true();
+          }
+          pop_block();
+          continue;
+        }
+        // NB This is a pointer. Modifications modify the last_succ_seen.
+        ssize_t* cur_succ = &last_succ_seen[id];
+        std::bitset<kMaxFilterableSuccessors> succ_bitmap = GetAllowedSuccessors(cur_block);
+        // Get next successor allowed.
+        while (++(*cur_succ) < static_cast<ssize_t>(kMaxFilterableSuccessors) &&
+               !succ_bitmap.test(*cur_succ)) {
+          DCHECK_GE(*cur_succ, 0);
+        }
+        if (*cur_succ >= static_cast<ssize_t>(cur_block->GetSuccessors().size())) {
+          // No more successors. Mark that we've checked everything. Later visits
+          // to this node can use the existing data.
+          DCHECK_LE(*cur_succ, static_cast<ssize_t>(kMaxFilterableSuccessors));
+          *cur_succ = kMaxFilterableSuccessors;
+          pop_block();
+          continue;
+        }
+        const HBasicBlock* nxt = cur_block->GetSuccessors()[*cur_succ];
+        DCHECK(nxt != nullptr) << "id: " << *cur_succ
+                               << " max: " << cur_block->GetSuccessors().size();
+        if (visiting.IsBitSet(nxt->GetBlockId())) {
+          // This is a loop. Mark it and continue on. Mark allowed-successor on
+          // this block's results as well.
+          result.set(*cur_succ);
+          propagate_true();
+        } else {
+          // Not a loop yet. Recur.
+          push_block(nxt);
+        }
+      }
+    }
+    // If we can't reach the end then there is no path through the graph without
+    // hitting excluded blocks
+    if (UNLIKELY(!start_reaches_end)) {
+      valid_ = false;
+      return;
+    }
+    // Mark blocks we didn't see in the ReachesEnd flood-fill
+    for (const HBasicBlock* blk : graph_->GetBlocks()) {
+      if (blk != nullptr &&
+          results[blk->GetBlockId()].none() &&
+          blk != graph_->GetExitBlock() &&
+          blk != graph_->GetEntryBlock()) {
+        // We never visited this block, must be unreachable.
+        unreachable_blocks_.SetBit(blk->GetBlockId());
+      }
+    }
+    // write the new data.
+    memcpy(allowed_successors_.data(),
+           results.data(),
+           results.size() * sizeof(std::bitset<kMaxFilterableSuccessors>));
+  }
+  RecalculateExcludedCohort();
+}
+
+void ExecutionSubgraph::RemoveConcavity() {
+  if (UNLIKELY(!valid_)) {
+    return;
+  }
+  DCHECK(!needs_prune_);
+  for (const HBasicBlock* blk : graph_->GetBlocks()) {
+    if (blk == nullptr || unreachable_blocks_.IsBitSet(blk->GetBlockId())) {
+      continue;
+    }
+    uint32_t blkid = blk->GetBlockId();
+    if (std::any_of(unreachable_blocks_.Indexes().begin(),
+                    unreachable_blocks_.Indexes().end(),
+                    [&](uint32_t skipped) { return graph_->PathBetween(skipped, blkid); }) &&
+        std::any_of(unreachable_blocks_.Indexes().begin(),
+                    unreachable_blocks_.Indexes().end(),
+                    [&](uint32_t skipped) { return graph_->PathBetween(blkid, skipped); })) {
+      RemoveBlock(blk);
+    }
+  }
+  Prune();
+}
+
+void ExecutionSubgraph::RecalculateExcludedCohort() {
+  DCHECK(!needs_prune_);
+  excluded_list_.emplace(allocator_->Adapter(kArenaAllocLSA));
+  ScopedArenaVector<ExcludedCohort>& res = excluded_list_.value();
+  // Make a copy of unreachable_blocks_;
+  ArenaBitVector unreachable(allocator_, graph_->GetBlocks().size(), false, kArenaAllocLSA);
+  unreachable.Copy(&unreachable_blocks_);
+  // Split cohorts with union-find
+  while (unreachable.IsAnyBitSet()) {
+    res.emplace_back(allocator_, graph_);
+    ExcludedCohort& cohort = res.back();
+    // We don't allocate except for the queue beyond here so create another arena to save memory.
+    ScopedArenaAllocator alloc(graph_->GetArenaStack());
+    ScopedArenaQueue<const HBasicBlock*> worklist(alloc.Adapter(kArenaAllocLSA));
+    // Select an arbitrary node
+    const HBasicBlock* first = graph_->GetBlocks()[unreachable.GetHighestBitSet()];
+    worklist.push(first);
+    do {
+      // Flood-fill both forwards and backwards.
+      const HBasicBlock* cur = worklist.front();
+      worklist.pop();
+      if (!unreachable.IsBitSet(cur->GetBlockId())) {
+        // Already visited or reachable somewhere else.
+        continue;
+      }
+      unreachable.ClearBit(cur->GetBlockId());
+      cohort.blocks_.SetBit(cur->GetBlockId());
+      // don't bother filtering here, it's done next go-around
+      for (const HBasicBlock* pred : cur->GetPredecessors()) {
+        worklist.push(pred);
+      }
+      for (const HBasicBlock* succ : cur->GetSuccessors()) {
+        worklist.push(succ);
+      }
+    } while (!worklist.empty());
+  }
+  // Figure out entry & exit nodes.
+  for (ExcludedCohort& cohort : res) {
+    DCHECK(cohort.blocks_.IsAnyBitSet());
+    auto is_external = [&](const HBasicBlock* ext) -> bool {
+      return !cohort.blocks_.IsBitSet(ext->GetBlockId());
+    };
+    for (const HBasicBlock* blk : cohort.Blocks()) {
+      const auto& preds = blk->GetPredecessors();
+      const auto& succs = blk->GetSuccessors();
+      if (std::any_of(preds.cbegin(), preds.cend(), is_external)) {
+        cohort.entry_blocks_.SetBit(blk->GetBlockId());
+      }
+      if (std::any_of(succs.cbegin(), succs.cend(), is_external)) {
+        cohort.exit_blocks_.SetBit(blk->GetBlockId());
+      }
+    }
+  }
+}
+
+std::ostream& operator<<(std::ostream& os, const ExecutionSubgraph::ExcludedCohort& ex) {
+  ex.Dump(os);
+  return os;
+}
+
+void ExecutionSubgraph::ExcludedCohort::Dump(std::ostream& os) const {
+  auto dump = [&](BitVecBlockRange arr) {
+    os << "[";
+    bool first = true;
+    for (const HBasicBlock* b : arr) {
+      if (!first) {
+        os << ", ";
+      }
+      first = false;
+      os << b->GetBlockId();
+    }
+    os << "]";
+  };
+  auto dump_blocks = [&]() {
+    os << "[";
+    bool first = true;
+    for (const HBasicBlock* b : Blocks()) {
+      if (!entry_blocks_.IsBitSet(b->GetBlockId()) && !exit_blocks_.IsBitSet(b->GetBlockId())) {
+        if (!first) {
+          os << ", ";
+        }
+        first = false;
+        os << b->GetBlockId();
+      }
+    }
+    os << "]";
+  };
+
+  os << "{ entry: ";
+  dump(EntryBlocks());
+  os << ", interior: ";
+  dump_blocks();
+  os << ", exit: ";
+  dump(ExitBlocks());
+  os << "}";
+}
+
+}  // namespace art
diff --git a/compiler/optimizing/execution_subgraph.h b/compiler/optimizing/execution_subgraph.h
new file mode 100644
index 0000000..05855c3
--- /dev/null
+++ b/compiler/optimizing/execution_subgraph.h
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2020 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_COMPILER_OPTIMIZING_EXECUTION_SUBGRAPH_H_
+#define ART_COMPILER_OPTIMIZING_EXECUTION_SUBGRAPH_H_
+
+#include <algorithm>
+#include <sstream>
+
+#include "base/arena_allocator.h"
+#include "base/arena_bit_vector.h"
+#include "base/arena_containers.h"
+#include "base/array_ref.h"
+#include "base/bit_vector-inl.h"
+#include "base/globals.h"
+#include "base/iteration_range.h"
+#include "base/mutex.h"
+#include "base/scoped_arena_allocator.h"
+#include "base/scoped_arena_containers.h"
+#include "base/stl_util.h"
+#include "base/transform_iterator.h"
+#include "nodes.h"
+
+namespace art {
+
+// Helper for transforming blocks to block_ids.
+class BlockToBlockIdTransformer {
+ public:
+  BlockToBlockIdTransformer(BlockToBlockIdTransformer&&) = default;
+  BlockToBlockIdTransformer(const BlockToBlockIdTransformer&) = default;
+  BlockToBlockIdTransformer() {}
+
+  inline uint32_t operator()(const HBasicBlock* b) const {
+    return b->GetBlockId();
+  }
+};
+
+// Helper for transforming block ids to blocks.
+class BlockIdToBlockTransformer {
+ public:
+  BlockIdToBlockTransformer(BlockIdToBlockTransformer&&) = default;
+  BlockIdToBlockTransformer(const BlockIdToBlockTransformer&) = default;
+  explicit BlockIdToBlockTransformer(const HGraph* graph) : graph_(graph) {}
+
+  inline const HGraph* GetGraph() const {
+    return graph_;
+  }
+
+  inline HBasicBlock* GetBlock(uint32_t id) const {
+    DCHECK_LT(id, graph_->GetBlocks().size()) << graph_->PrettyMethod();
+    HBasicBlock* blk = graph_->GetBlocks()[id];
+    DCHECK(blk != nullptr);
+    return blk;
+  }
+
+  inline HBasicBlock* operator()(uint32_t id) const {
+    return GetBlock(id);
+  }
+
+ private:
+  const HGraph* const graph_;
+};
+
+class BlockIdFilterThunk {
+ public:
+  explicit BlockIdFilterThunk(const BitVector& i) : inner_(i) {}
+  BlockIdFilterThunk(BlockIdFilterThunk&& other) noexcept = default;
+  BlockIdFilterThunk(const BlockIdFilterThunk&) = default;
+
+  bool operator()(const HBasicBlock* b) const {
+    return inner_.IsBitSet(b->GetBlockId());
+  }
+
+ private:
+  const BitVector& inner_;
+};
+
+// A representation of a particular section of the graph. The graph is split
+// into an excluded and included area and is used to track escapes.
+//
+// This object is a view of the graph and is not updated as the graph is
+// changed.
+//
+// This is implemented by removing various escape points from the subgraph using
+// the 'RemoveBlock' function. Once all required blocks are removed one will
+// 'Finalize' the subgraph. This will extend the removed area to include:
+// (1) Any block which inevitably leads to (post-dominates) a removed block
+// (2) any block which is between 2 removed blocks
+//
+// This allows us to create a set of 'ExcludedCohorts' which are the
+// well-connected subsets of the graph made up of removed blocks. These cohorts
+// have a set of entry and exit blocks which act as the boundary of the cohort.
+// Since we removed blocks between 2 excluded blocks it is impossible for any
+// cohort-exit block to reach any cohort-entry block. This means we can use the
+// boundary between the cohort and the rest of the graph to insert
+// materialization blocks for partial LSE.
+//
+// TODO We really should expand this to take into account where the object
+// allocation takes place directly. Currently we always act as though it were
+// allocated in the entry block. This is a massively simplifying assumption but
+// means we can't partially remove objects that are repeatedly allocated in a
+// loop.
+class ExecutionSubgraph : public DeletableArenaObject<kArenaAllocLSA> {
+ public:
+  using BitVecBlockRange =
+      IterationRange<TransformIterator<BitVector::IndexIterator, BlockIdToBlockTransformer>>;
+  using FilteredBitVecBlockRange = IterationRange<
+      FilterIterator<ArenaVector<HBasicBlock*>::const_iterator, BlockIdFilterThunk>>;
+
+  // A set of connected blocks which are connected and removed from the
+  // ExecutionSubgraph. See above comment for explanation.
+  class ExcludedCohort : public ArenaObject<kArenaAllocLSA> {
+   public:
+    ExcludedCohort(ExcludedCohort&&) = default;
+    ExcludedCohort(const ExcludedCohort&) = delete;
+    explicit ExcludedCohort(ScopedArenaAllocator* allocator, HGraph* graph)
+        : graph_(graph),
+          entry_blocks_(allocator, graph_->GetBlocks().size(), false, kArenaAllocLSA),
+          exit_blocks_(allocator, graph_->GetBlocks().size(), false, kArenaAllocLSA),
+          blocks_(allocator, graph_->GetBlocks().size(), false, kArenaAllocLSA) {}
+
+    ~ExcludedCohort() = default;
+
+    // All blocks in the cohort.
+    BitVecBlockRange Blocks() const {
+      return BlockIterRange(blocks_);
+    }
+
+    // Blocks that have predecessors outside of the cohort. These blocks will
+    // need to have PHIs/control-flow added to create the escaping value.
+    BitVecBlockRange EntryBlocks() const {
+      return BlockIterRange(entry_blocks_);
+    }
+
+    FilteredBitVecBlockRange EntryBlocksReversePostOrder() const {
+      return Filter(MakeIterationRange(graph_->GetReversePostOrder()),
+                    BlockIdFilterThunk(entry_blocks_));
+    }
+
+    bool IsEntryBlock(const HBasicBlock* blk) const {
+      return entry_blocks_.IsBitSet(blk->GetBlockId());
+    }
+
+    // Blocks that have successors outside of the cohort. The successors of
+    // these blocks will need to have PHI's to restore state.
+    BitVecBlockRange ExitBlocks() const {
+      return BlockIterRange(exit_blocks_);
+    }
+
+    bool operator==(const ExcludedCohort& other) const {
+      return blocks_.Equal(&other.blocks_);
+    }
+
+    bool ContainsBlock(const HBasicBlock* blk) const {
+      return blocks_.IsBitSet(blk->GetBlockId());
+    }
+
+    // Returns true if there is a path from 'blk' to any block in this cohort.
+    // NB blocks contained within the cohort are not considered to be succeeded
+    // by the cohort (i.e. this function will return false).
+    bool SucceedsBlock(const HBasicBlock* blk) const {
+      if (ContainsBlock(blk)) {
+        return false;
+      }
+      auto idxs = entry_blocks_.Indexes();
+      return std::any_of(idxs.begin(), idxs.end(), [&](uint32_t entry) -> bool {
+        return blk->GetGraph()->PathBetween(blk->GetBlockId(), entry);
+      });
+    }
+
+    // Returns true if there is a path from any block in this cohort to 'blk'.
+    // NB blocks contained within the cohort are not considered to be preceded
+    // by the cohort (i.e. this function will return false).
+    bool PrecedesBlock(const HBasicBlock* blk) const {
+      if (ContainsBlock(blk)) {
+        return false;
+      }
+      auto idxs = exit_blocks_.Indexes();
+      return std::any_of(idxs.begin(), idxs.end(), [&](uint32_t exit) -> bool {
+        return blk->GetGraph()->PathBetween(exit, blk->GetBlockId());
+      });
+    }
+
+    void Dump(std::ostream& os) const;
+
+   private:
+    BitVecBlockRange BlockIterRange(const ArenaBitVector& bv) const {
+      auto indexes = bv.Indexes();
+      BitVecBlockRange res = MakeTransformRange(indexes, BlockIdToBlockTransformer(graph_));
+      return res;
+    }
+
+    ExcludedCohort() = delete;
+
+    HGraph* graph_;
+    ArenaBitVector entry_blocks_;
+    ArenaBitVector exit_blocks_;
+    ArenaBitVector blocks_;
+
+    friend class ExecutionSubgraph;
+    friend class LoadStoreAnalysisTest;
+  };
+
+  // The number of successors we can track on a single block. Graphs which
+  // contain a block with a branching factor greater than this will not be
+  // analysed. This is used to both limit the memory usage of analysis to
+  // reasonable levels and ensure that the analysis will complete in a
+  // reasonable amount of time. It also simplifies the implementation somewhat
+  // to have a constant branching factor.
+  static constexpr uint32_t kMaxFilterableSuccessors = 8;
+
+  // Instantiate a subgraph. The subgraph can be instantiated only if partial-escape
+  // analysis is desired (eg not when being used for instruction scheduling) and
+  // when the branching factor in the graph is not too high. These conditions
+  // are determined once and passed down for performance reasons.
+  ExecutionSubgraph(HGraph* graph, ScopedArenaAllocator* allocator);
+
+  void Invalidate() {
+    valid_ = false;
+  }
+
+  // A block is contained by the ExecutionSubgraph if it is reachable. This
+  // means it has not been removed explicitly or via pruning/concavity removal.
+  // Finalization is needed to call this function.
+  // See RemoveConcavity and Prune for more information.
+  bool ContainsBlock(const HBasicBlock* blk) const {
+    DCHECK(!finalized_ || !needs_prune_) << "finalized: " << finalized_;
+    if (!valid_) {
+      return false;
+    }
+    return !unreachable_blocks_.IsBitSet(blk->GetBlockId());
+  }
+
+  // Mark the block as removed from the subgraph.
+  void RemoveBlock(const HBasicBlock* to_remove);
+
+  // Called when no more updates will be done to the subgraph. Calculate the
+  // final subgraph
+  void Finalize() {
+    Prune();
+    RemoveConcavity();
+    finalized_ = true;
+  }
+
+  BitVecBlockRange UnreachableBlocks() const {
+    auto idxs = unreachable_blocks_.Indexes();
+    return MakeTransformRange(idxs, BlockIdToBlockTransformer(graph_));
+  }
+
+  // Returns true if all allowed execution paths from start eventually reach the
+  // graph's exit block (or diverge).
+  bool IsValid() const {
+    return valid_;
+  }
+
+  ArrayRef<const ExcludedCohort> GetExcludedCohorts() const {
+    DCHECK(!valid_ || !needs_prune_);
+    if (!valid_ || !unreachable_blocks_.IsAnyBitSet()) {
+      return ArrayRef<const ExcludedCohort>();
+    } else {
+      return ArrayRef<const ExcludedCohort>(*excluded_list_);
+    }
+  }
+
+  // Helper class to create reachable blocks iterator.
+  class ContainsFunctor {
+   public:
+    bool operator()(HBasicBlock* blk) const {
+      return subgraph_->ContainsBlock(blk);
+    }
+
+   private:
+    explicit ContainsFunctor(const ExecutionSubgraph* subgraph) : subgraph_(subgraph) {}
+    const ExecutionSubgraph* const subgraph_;
+    friend class ExecutionSubgraph;
+  };
+  // Returns an iterator over reachable blocks (filtered as we go). This is primarilly for testing.
+  IterationRange<
+      FilterIterator<typename ArenaVector<HBasicBlock*>::const_iterator, ContainsFunctor>>
+  ReachableBlocks() const {
+    return Filter(MakeIterationRange(graph_->GetBlocks()), ContainsFunctor(this));
+  }
+
+  static bool CanAnalyse(HGraph* graph) {
+    // If there are any blocks with more than kMaxFilterableSuccessors we can't
+    // analyse the graph. We avoid this case to prevent excessive memory and
+    // time usage while allowing a simpler algorithm with a fixed-width
+    // branching factor.
+    return std::all_of(graph->GetBlocks().begin(), graph->GetBlocks().end(), [](HBasicBlock* blk) {
+      return blk == nullptr || blk->GetSuccessors().size() <= kMaxFilterableSuccessors;
+    });
+  }
+
+ private:
+  std::bitset<kMaxFilterableSuccessors> GetAllowedSuccessors(const HBasicBlock* blk) const {
+    DCHECK(valid_);
+    return allowed_successors_[blk->GetBlockId()];
+  }
+
+  void LimitBlockSuccessors(const HBasicBlock* block,
+                            std::bitset<kMaxFilterableSuccessors> allowed) {
+    needs_prune_ = true;
+    allowed_successors_[block->GetBlockId()] &= allowed;
+  }
+
+  // Remove nodes which both precede and follow any exclusions. This ensures we don't need to deal
+  // with only conditionally materializing objects depending on if we already materialized them
+  // Ensure that for all blocks A, B, C: Unreachable(A) && Unreachable(C) && PathBetween(A, B) &&
+  // PathBetween(A, C) implies Unreachable(B). This simplifies later transforms since it ensures
+  // that no execution can leave and then re-enter any exclusion.
+  void RemoveConcavity();
+
+  // Removes sink nodes. Sink nodes are nodes where there is no execution which
+  // avoids all removed nodes.
+  void Prune();
+
+  void RecalculateExcludedCohort();
+
+  HGraph* graph_;
+  ScopedArenaAllocator* allocator_;
+  // The map from block_id -> allowed-successors.
+  // This is the canonical representation of this subgraph. If a bit in the
+  // bitset is not set then the corresponding outgoing edge of that block is not
+  // considered traversable.
+  ScopedArenaVector<std::bitset<kMaxFilterableSuccessors>> allowed_successors_;
+  // Helper that holds which blocks we are able to reach. Only valid if
+  // 'needs_prune_ == false'.
+  ArenaBitVector unreachable_blocks_;
+  // A list of the excluded-cohorts of this subgraph. This is only valid when
+  // 'needs_prune_ == false'
+  std::optional<ScopedArenaVector<ExcludedCohort>> excluded_list_;
+  // Bool to hold if there is at least one known path from the start block to
+  // the end in this graph. Used to short-circuit computation.
+  bool valid_;
+  // True if the subgraph is consistent and can be queried. Modifying the
+  // subgraph clears this and requires a prune to restore.
+  bool needs_prune_;
+  // True if no more modification of the subgraph is permitted.
+  bool finalized_;
+
+  friend class ExecutionSubgraphTest;
+  friend class LoadStoreAnalysisTest;
+
+  DISALLOW_COPY_AND_ASSIGN(ExecutionSubgraph);
+};
+
+std::ostream& operator<<(std::ostream& os, const ExecutionSubgraph::ExcludedCohort& ex);
+
+}  // namespace art
+
+#endif  // ART_COMPILER_OPTIMIZING_EXECUTION_SUBGRAPH_H_
diff --git a/compiler/optimizing/execution_subgraph_test.cc b/compiler/optimizing/execution_subgraph_test.cc
new file mode 100644
index 0000000..74c243b
--- /dev/null
+++ b/compiler/optimizing/execution_subgraph_test.cc
@@ -0,0 +1,975 @@
+/*
+ * Copyright (C) 2020 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 "execution_subgraph_test.h"
+
+#include <array>
+#include <sstream>
+#include <string_view>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "base/scoped_arena_allocator.h"
+#include "base/stl_util.h"
+#include "class_root.h"
+#include "dex/dex_file_types.h"
+#include "dex/method_reference.h"
+#include "entrypoints/quick/quick_entrypoints_enum.h"
+#include "execution_subgraph.h"
+#include "gtest/gtest.h"
+#include "handle.h"
+#include "handle_scope.h"
+#include "nodes.h"
+#include "optimizing/data_type.h"
+#include "optimizing_unit_test.h"
+#include "scoped_thread_state_change.h"
+
+namespace art {
+
+using BlockSet = std::unordered_set<const HBasicBlock*>;
+
+// Helper that checks validity directly.
+bool ExecutionSubgraphTestHelper::CalculateValidity(HGraph* graph, const ExecutionSubgraph* esg) {
+  bool reached_end = false;
+  std::queue<const HBasicBlock*> worklist;
+  std::unordered_set<const HBasicBlock*> visited;
+  worklist.push(graph->GetEntryBlock());
+  while (!worklist.empty()) {
+    const HBasicBlock* cur = worklist.front();
+    worklist.pop();
+    if (visited.find(cur) != visited.end()) {
+      continue;
+    } else {
+      visited.insert(cur);
+    }
+    if (cur == graph->GetExitBlock()) {
+      reached_end = true;
+      continue;
+    }
+    bool has_succ = false;
+    for (const HBasicBlock* succ : cur->GetSuccessors()) {
+      DCHECK(succ != nullptr) << "Bad successors on block " << cur->GetBlockId();
+      if (!esg->ContainsBlock(succ)) {
+        continue;
+      }
+      has_succ = true;
+      worklist.push(succ);
+    }
+    if (!has_succ) {
+      // We aren't at the end and have nowhere to go so fail.
+      return false;
+    }
+  }
+  return reached_end;
+}
+
+class ExecutionSubgraphTest : public OptimizingUnitTest {
+ public:
+  ExecutionSubgraphTest() : graph_(CreateGraph()) {}
+
+  AdjacencyListGraph SetupFromAdjacencyList(const std::string_view entry_name,
+                                            const std::string_view exit_name,
+                                            const std::vector<AdjacencyListGraph::Edge>& adj) {
+    return AdjacencyListGraph(graph_, GetAllocator(), entry_name, exit_name, adj);
+  }
+
+  bool IsValidSubgraph(const ExecutionSubgraph* esg) {
+    return ExecutionSubgraphTestHelper::CalculateValidity(graph_, esg);
+  }
+
+  bool IsValidSubgraph(const ExecutionSubgraph& esg) {
+    return ExecutionSubgraphTestHelper::CalculateValidity(graph_, &esg);
+  }
+
+  HGraph* graph_;
+};
+
+// Some comparators used by these tests to avoid having to deal with various set types.
+template <typename BLKS, typename = std::enable_if_t<!std::is_same_v<BlockSet, BLKS>>>
+bool operator==(const BlockSet& bs, const BLKS& sas) {
+  std::unordered_set<const HBasicBlock*> us(sas.begin(), sas.end());
+  return bs == us;
+}
+template <typename BLKS, typename = std::enable_if_t<!std::is_same_v<BlockSet, BLKS>>>
+bool operator==(const BLKS& sas, const BlockSet& bs) {
+  return bs == sas;
+}
+template <typename BLKS, typename = std::enable_if_t<!std::is_same_v<BlockSet, BLKS>>>
+bool operator!=(const BlockSet& bs, const BLKS& sas) {
+  return !(bs == sas);
+}
+template <typename BLKS, typename = std::enable_if_t<!std::is_same_v<BlockSet, BLKS>>>
+bool operator!=(const BLKS& sas, const BlockSet& bs) {
+  return !(bs == sas);
+}
+
+// +-------+       +-------+
+// | right | <--   | entry |
+// +-------+       +-------+
+//   |               |
+//   |               |
+//   |               v
+//   |           + - - - - - +
+//   |           '  removed  '
+//   |           '           '
+//   |           ' +-------+ '
+//   |           ' | left  | '
+//   |           ' +-------+ '
+//   |           '           '
+//   |           + - - - - - +
+//   |               |
+//   |               |
+//   |               v
+//   |             +-------+
+//   +--------->   | exit  |
+//                 +-------+
+TEST_F(ExecutionSubgraphTest, Basic) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("left"));
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+  ASSERT_TRUE(contents.find(blks.Get("left")) == contents.end());
+
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+  esg.RemoveBlock(blks.Get("right"));
+  esg.Finalize();
+  std::unordered_set<const HBasicBlock*> contents_2(esg.ReachableBlocks().begin(),
+                                                    esg.ReachableBlocks().end());
+  ASSERT_EQ(contents_2.size(), 0u);
+}
+
+//                   +-------+         +-------+
+//                   | right |   <--   | entry |
+//                   +-------+         +-------+
+//                     |                 |
+//                     |                 |
+//                     |                 v
+//                     |             + - - - - - - - - - - - - - - - - - - - -+
+//                     |             '             indirectly_removed         '
+//                     |             '                                        '
+//                     |             ' +-------+                      +-----+ '
+//                     |             ' |  l1   | -------------------> | l1r | '
+//                     |             ' +-------+                      +-----+ '
+//                     |             '   |                              |     '
+//                     |             '   |                              |     '
+//                     |             '   v                              |     '
+//                     |             ' +-------+                        |     '
+//                     |             ' |  l1l  |                        |     '
+//                     |             ' +-------+                        |     '
+//                     |             '   |                              |     '
+//                     |             '   |                              |     '
+//                     |             '   |                              |     '
+// + - - - - - - - -+  |      +- - -     |                              |     '
+// '                '  |      +-         v                              |     '
+// ' +-----+           |               +----------------+               |     '
+// ' | l2r | <---------+-------------- |  l2 (removed)  | <-------------+     '
+// ' +-----+           |               +----------------+                     '
+// '   |            '  |      +-         |                                    '
+// '   |       - - -+  |      +- - -     |         - - - - - - - - - - - - - -+
+// '   |     '         |             '   |       '
+// '   |     '         |             '   |       '
+// '   |     '         |             '   v       '
+// '   |     '         |             ' +-------+ '
+// '   |     '         |             ' |  l2l  | '
+// '   |     '         |             ' +-------+ '
+// '   |     '         |             '   |       '
+// '   |     '         |             '   |       '
+// '   |     '         |             '   |       '
+// '   |       - - -+  |      +- - -     |       '
+// '   |            '  |      +-         v       '
+// '   |               |               +-------+ '
+// '   +---------------+-------------> |  l3   | '
+// '                   |               +-------+ '
+// '                '  |      +-                 '
+// + - - - - - - - -+  |      +- - - - - - - - - +
+//                     |                 |
+//                     |                 |
+//                     |                 v
+//                     |               +-------+
+//                     +----------->   | exit  |
+//                                     +-------+
+TEST_F(ExecutionSubgraphTest, Propagation) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 { { "entry", "l1" },
+                                                   { "l1", "l1l" },
+                                                   { "l1", "l1r" },
+                                                   { "l1l", "l2" },
+                                                   { "l1r", "l2" },
+                                                   { "l2", "l2l" },
+                                                   { "l2", "l2r" },
+                                                   { "l2l", "l3" },
+                                                   { "l2r", "l3" },
+                                                   { "l3", "exit" },
+                                                   { "entry", "right" },
+                                                   { "right", "exit" } }));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("l2"));
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  // ASSERT_EQ(contents.size(), 3u);
+  // Not present, no path through.
+  ASSERT_TRUE(contents.find(blks.Get("l1")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l2")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l3")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1l")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1r")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l2l")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l2r")) == contents.end());
+
+  // present, path through.
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+// +------------------------------------+
+// |                                    |
+// |  +-------+       +-------+         |
+// |  | right | <--   | entry |         |
+// |  +-------+       +-------+         |
+// |    |               |               |
+// |    |               |               |
+// |    |               v               |
+// |    |             +-------+       +--------+
+// +----+--------->   |  l1   |   --> | l1loop |
+//      |             +-------+       +--------+
+//      |               |
+//      |               |
+//      |               v
+//      |           +- - - - - -+
+//      |           '  removed  '
+//      |           '           '
+//      |           ' +-------+ '
+//      |           ' |  l2   | '
+//      |           ' +-------+ '
+//      |           '           '
+//      |           +- - - - - -+
+//      |               |
+//      |               |
+//      |               v
+//      |             +-------+
+//      +--------->   | exit  |
+//                    +-------+
+TEST_F(ExecutionSubgraphTest, PropagationLoop) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 { { "entry", "l1" },
+                                                   { "l1", "l2" },
+                                                   { "l1", "l1loop" },
+                                                   { "l1loop", "l1" },
+                                                   { "l2", "exit" },
+                                                   { "entry", "right" },
+                                                   { "right", "exit" } }));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("l2"));
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 5u);
+
+  // Not present, no path through.
+  ASSERT_TRUE(contents.find(blks.Get("l2")) == contents.end());
+
+  // present, path through.
+  // Since the loop can diverge we should leave it in the execution subgraph.
+  ASSERT_TRUE(contents.find(blks.Get("l1")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1loop")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+// +--------------------------------+
+// |                                |
+// |  +-------+     +-------+       |
+// |  | right | <-- | entry |       |
+// |  +-------+     +-------+       |
+// |    |             |             |
+// |    |             |             |
+// |    |             v             |
+// |    |           +-------+     +--------+
+// +----+---------> |  l1   | --> | l1loop |
+//      |           +-------+     +--------+
+//      |             |
+//      |             |
+//      |             v
+//      |           +-------+
+//      |           |  l2   |
+//      |           +-------+
+//      |             |
+//      |             |
+//      |             v
+//      |           +-------+
+//      +---------> | exit  |
+//                  +-------+
+TEST_F(ExecutionSubgraphTest, PropagationLoop2) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 { { "entry", "l1" },
+                                                   { "l1", "l2" },
+                                                   { "l1", "l1loop" },
+                                                   { "l1loop", "l1" },
+                                                   { "l2", "exit" },
+                                                   { "entry", "right" },
+                                                   { "right", "exit" } }));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("l1"));
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+
+  // Not present, no path through.
+  ASSERT_TRUE(contents.find(blks.Get("l1")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1loop")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l2")) == contents.end());
+
+  // present, path through.
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+// +--------------------------------+
+// |                                |
+// |  +-------+     +-------+       |
+// |  | right | <-- | entry |       |
+// |  +-------+     +-------+       |
+// |    |             |             |
+// |    |             |             |
+// |    |             v             |
+// |    |           +-------+     +--------+
+// +----+---------> |  l1   | --> | l1loop |
+//      |           +-------+     +--------+
+//      |             |
+//      |             |
+//      |             v
+//      |           +-------+
+//      |           |  l2   |
+//      |           +-------+
+//      |             |
+//      |             |
+//      |             v
+//      |           +-------+
+//      +---------> | exit  |
+//                  +-------+
+TEST_F(ExecutionSubgraphTest, PropagationLoop3) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 { { "entry", "l1" },
+                                                   { "l1", "l2" },
+                                                   { "l1", "l1loop" },
+                                                   { "l1loop", "l1" },
+                                                   { "l2", "exit" },
+                                                   { "entry", "right" },
+                                                   { "right", "exit" } }));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("l1loop"));
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+
+  // Not present, no path through. If we got to l1 loop then we must merge back
+  // with l1 and l2 so they're bad too.
+  ASSERT_TRUE(contents.find(blks.Get("l1loop")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l2")) == contents.end());
+
+  // present, path through.
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+//            ┌───────┐       ┌──────────────┐
+//            │ right │ ◀──   │    entry     │
+//            └───────┘       └──────────────┘
+//              │               │
+//              │               │
+//              ▼               ▼
+// ┌────┐     ┌───────┐       ┌──────────────┐
+// │ l2 │ ──▶ │ exit  │  ┌─   │      l1      │   ◀┐
+// └────┘     └───────┘  │    └──────────────┘    │
+//   ▲                   │      │                 │
+//   └───────────────────┘      │                 │
+//                              ▼                 │
+//                            ┌──────────────┐    │  ┌──────────────┐
+//                       ┌─   │    l1loop    │    │  │ l1loop_right │ ◀┐
+//                       │    └──────────────┘    │  └──────────────┘  │
+//                       │      │                 │    │               │
+//                       │      │                 │    │               │
+//                       │      ▼                 │    │               │
+//                       │  ┌−−−−−−−−−−−−−−−−−−┐  │    │               │
+//                       │  ╎     removed      ╎  │    │               │
+//                       │  ╎                  ╎  │    │               │
+//                       │  ╎ ┌──────────────┐ ╎  │    │               │
+//                       │  ╎ │ l1loop_left  │ ╎  │    │               │
+//                       │  ╎ └──────────────┘ ╎  │    │               │
+//                       │  ╎                  ╎  │    │               │
+//                       │  └−−−−−−−−−−−−−−−−−−┘  │    │               │
+//                       │      │                 │    │               │
+//                       │      │                 │    │               │
+//                       │      ▼                 │    │               │
+//                       │    ┌──────────────┐    │    │               │
+//                       │    │ l1loop_merge │   ─┘    │               │
+//                       │    └──────────────┘         │               │
+//                       │      ▲                      │               │
+//                       │      └──────────────────────┘               │
+//                       │                                             │
+//                       │                                             │
+//                       └─────────────────────────────────────────────┘
+
+TEST_F(ExecutionSubgraphTest, PropagationLoop4) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "l1"},
+                                                  {"l1", "l2"},
+                                                  {"l1", "l1loop"},
+                                                  {"l1loop", "l1loop_left"},
+                                                  {"l1loop", "l1loop_right"},
+                                                  {"l1loop_left", "l1loop_merge"},
+                                                  {"l1loop_right", "l1loop_merge"},
+                                                  {"l1loop_merge", "l1"},
+                                                  {"l2", "exit"},
+                                                  {"entry", "right"},
+                                                  {"right", "exit"}}));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("l1loop_left"));
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+
+  // Not present, no path through. If we got to l1 loop then we must merge back
+  // with l1 and l2 so they're bad too.
+  ASSERT_TRUE(contents.find(blks.Get("l1loop")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1loop_left")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1loop_right")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1loop_merge")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l2")) == contents.end());
+
+  // present, path through.
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+// +------------------------------------------------------+
+// |                                                      |
+// |  +--------------+       +-------------+              |
+// |  |    right     | <--   |    entry    |              |
+// |  +--------------+       +-------------+              |
+// |    |                      |                          |
+// |    |                      |                          |
+// |    v                      v                          |
+// |  +--------------+       +--------------------+     +----+
+// +> |     exit     |  +>   |         l1         | --> | l2 |
+//    +--------------+  |    +--------------------+     +----+
+//                      |      |                ^
+//      +---------------+      |                |
+//      |                      v                |
+//    +--------------+       +-------------+    |
+//    | l1loop_right | <--   |   l1loop    |    |
+//    +--------------+       +-------------+    |
+//                             |                |
+//                             |                |
+//                             v                |
+//                         + - - - - - - - - +  |
+//                         '     removed     '  |
+//                         '                 '  |
+//                         ' +-------------+ '  |
+//                         ' | l1loop_left | ' -+
+//                         ' +-------------+ '
+//                         '                 '
+//                         + - - - - - - - - +
+TEST_F(ExecutionSubgraphTest, PropagationLoop5) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "l1"},
+                                                  {"l1", "l2"},
+                                                  {"l1", "l1loop"},
+                                                  {"l1loop", "l1loop_left"},
+                                                  {"l1loop", "l1loop_right"},
+                                                  {"l1loop_left", "l1"},
+                                                  {"l1loop_right", "l1"},
+                                                  {"l2", "exit"},
+                                                  {"entry", "right"},
+                                                  {"right", "exit"}}));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("l1loop_left"));
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+
+  // Not present, no path through. If we got to l1 loop then we must merge back
+  // with l1 and l2 so they're bad too.
+  ASSERT_TRUE(contents.find(blks.Get("l1loop")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1loop_left")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l1loop_right")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("l2")) == contents.end());
+
+  // present, path through.
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+TEST_F(ExecutionSubgraphTest, Invalid) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("left"));
+  esg.RemoveBlock(blks.Get("right"));
+  esg.Finalize();
+
+  ASSERT_FALSE(esg.IsValid());
+  ASSERT_FALSE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 0u);
+}
+// Sibling branches are disconnected.
+TEST_F(ExecutionSubgraphTest, Exclusions) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 { { "entry", "a" },
+                                                   { "entry", "b" },
+                                                   { "entry", "c" },
+                                                   { "a", "exit" },
+                                                   { "b", "exit" },
+                                                   { "c", "exit" } }));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("a"));
+  esg.RemoveBlock(blks.Get("c"));
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+  // Not present, no path through.
+  ASSERT_TRUE(contents.find(blks.Get("a")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("c")) == contents.end());
+
+  // present, path through.
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("b")) != contents.end());
+
+  ArrayRef<const ExecutionSubgraph::ExcludedCohort> exclusions(esg.GetExcludedCohorts());
+  ASSERT_EQ(exclusions.size(), 2u);
+  std::unordered_set<const HBasicBlock*> exclude_a({ blks.Get("a") });
+  std::unordered_set<const HBasicBlock*> exclude_c({ blks.Get("c") });
+  ASSERT_TRUE(std::find_if(exclusions.cbegin(),
+                           exclusions.cend(),
+                           [&](const ExecutionSubgraph::ExcludedCohort& it) {
+                             return it.Blocks() == exclude_a;
+                           }) != exclusions.cend());
+  ASSERT_TRUE(std::find_if(exclusions.cbegin(),
+                           exclusions.cend(),
+                           [&](const ExecutionSubgraph::ExcludedCohort& it) {
+                             return it.Blocks() == exclude_c;
+                           }) != exclusions.cend());
+}
+
+// Sibling branches are disconnected.
+//                                      +- - - - - - - - - - - - - - - - - - - - - - +
+//                                      '                      remove_c              '
+//                                      '                                            '
+//                                      ' +-----------+                              '
+//                                      ' | c_begin_2 | -------------------------+   '
+//                                      ' +-----------+                          |   '
+//                                      '                                        |   '
+//                                      +- - - - - - - - - - - - - - - - - -     |   '
+//                                          ^                                '   |   '
+//                                          |                                '   |   '
+//                                          |                                '   |   '
+//                   + - - - - - -+                                          '   |   '
+//                   '  remove_a  '                                          '   |   '
+//                   '            '                                          '   |   '
+//                   ' +--------+ '       +-----------+                 +---+'   |   '
+//                   ' | **a**  | ' <--   |   entry   |   -->           | b |'   |   '
+//                   ' +--------+ '       +-----------+                 +---+'   |   '
+//                   '            '                                          '   |   '
+//                   + - - - - - -+                                          '   |   '
+//                       |                  |                             |  '   |   '
+//                       |                  |                             |  '   |   '
+//                       |                  v                             |  '   |   '
+//                       |              +- - - - - - - -+                 |  '   |   '
+//                       |              '               '                 |  '   |   '
+//                       |              ' +-----------+ '                 |  '   |   '
+//                       |              ' | c_begin_1 | '                 |  '   |   '
+//                       |              ' +-----------+ '                 |  '   |   '
+//                       |              '   |           '                 |  '   |   '
+//                       |              '   |           '                 |  '   |   '
+//                       |              '   |           '                 |  '   |   '
+// + - - - - - - - - -+  |       + - - -    |            - - - - - - - +  |  '   |   '
+// '                  '  |       +          v                          '  |  +   |   '
+// ' +---------+         |                +-----------+                   |      |   '
+// ' | c_end_2 | <-------+--------------- | **c_mid** | <-----------------+------+   '
+// ' +---------+         |                +-----------+                   |          '
+// '                  '  |       +          |                          '  |  +       '
+// + - - - - - - - - -+  |       + - - -    |            - - - - - - - +  |  + - - - +
+//     |                 |              '   |           '                 |
+//     |                 |              '   |           '                 |
+//     |                 |              '   v           '                 |
+//     |                 |              ' +-----------+ '                 |
+//     |                 |              ' |  c_end_1  | '                 |
+//     |                 |              ' +-----------+ '                 |
+//     |                 |              '               '                 |
+//     |                 |              +- - - - - - - -+                 |
+//     |                 |                  |                             |
+//     |                 |                  |                             |
+//     |                 |                  v                             v
+//     |                 |                +---------------------------------+
+//     |                 +------------>   |              exit               |
+//     |                                  +---------------------------------+
+//     |                                    ^
+//     +------------------------------------+
+TEST_F(ExecutionSubgraphTest, ExclusionExtended) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 { { "entry", "a" },
+                                                   { "entry", "b" },
+                                                   { "entry", "c_begin_1" },
+                                                   { "entry", "c_begin_2" },
+                                                   { "c_begin_1", "c_mid" },
+                                                   { "c_begin_2", "c_mid" },
+                                                   { "c_mid", "c_end_1" },
+                                                   { "c_mid", "c_end_2" },
+                                                   { "a", "exit" },
+                                                   { "b", "exit" },
+                                                   { "c_end_1", "exit" },
+                                                   { "c_end_2", "exit" } }));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("a"));
+  esg.RemoveBlock(blks.Get("c_mid"));
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+  // Not present, no path through.
+  ASSERT_TRUE(contents.find(blks.Get("a")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("c_begin_1")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("c_begin_2")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("c_mid")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("c_end_1")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("c_end_2")) == contents.end());
+
+  // present, path through.
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("b")) != contents.end());
+
+  ArrayRef<const ExecutionSubgraph::ExcludedCohort> exclusions(esg.GetExcludedCohorts());
+  ASSERT_EQ(exclusions.size(), 2u);
+  BlockSet exclude_a({ blks.Get("a") });
+  BlockSet exclude_c({ blks.Get("c_begin_1"),
+                       blks.Get("c_begin_2"),
+                       blks.Get("c_mid"),
+                       blks.Get("c_end_1"),
+                       blks.Get("c_end_2") });
+  ASSERT_TRUE(std::find_if(exclusions.cbegin(),
+                           exclusions.cend(),
+                           [&](const ExecutionSubgraph::ExcludedCohort& it) {
+                             return it.Blocks() == exclude_a;
+                           }) != exclusions.cend());
+  ASSERT_TRUE(
+      std::find_if(
+          exclusions.cbegin(), exclusions.cend(), [&](const ExecutionSubgraph::ExcludedCohort& it) {
+            return it.Blocks() == exclude_c &&
+                   BlockSet({ blks.Get("c_begin_1"), blks.Get("c_begin_2") }) == it.EntryBlocks() &&
+                   BlockSet({ blks.Get("c_end_1"), blks.Get("c_end_2") }) == it.ExitBlocks();
+          }) != exclusions.cend());
+}
+
+//    ┌───────┐     ┌────────────┐
+// ┌─ │ right │ ◀── │   entry    │
+// │  └───────┘     └────────────┘
+// │                  │
+// │                  │
+// │                  ▼
+// │                ┌────────────┐
+// │                │  esc_top   │
+// │                └────────────┘
+// │                  │
+// │                  │
+// │                  ▼
+// │                ┌────────────┐
+// └──────────────▶ │   middle   │ ─┐
+//                  └────────────┘  │
+//                    │             │
+//                    │             │
+//                    ▼             │
+//                  ┌────────────┐  │
+//                  │ esc_bottom │  │
+//                  └────────────┘  │
+//                    │             │
+//                    │             │
+//                    ▼             │
+//                  ┌────────────┐  │
+//                  │    exit    │ ◀┘
+//                  └────────────┘
+TEST_F(ExecutionSubgraphTest, InAndOutEscape) {
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 { { "entry", "esc_top" },
+                                                   { "entry", "right" },
+                                                   { "esc_top", "middle" },
+                                                   { "right", "middle" },
+                                                   { "middle", "exit" },
+                                                   { "middle", "esc_bottom" },
+                                                   { "esc_bottom", "exit" } }));
+
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("esc_top"));
+  esg.RemoveBlock(blks.Get("esc_bottom"));
+  esg.Finalize();
+
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+  ASSERT_EQ(contents.size(), 0u);
+  ASSERT_FALSE(esg.IsValid());
+  ASSERT_FALSE(IsValidSubgraph(esg));
+
+  ASSERT_EQ(contents.size(), 0u);
+}
+
+// Test with max number of successors and no removals.
+TEST_F(ExecutionSubgraphTest, BigNodes) {
+  std::vector<std::string> mid_blocks;
+  for (auto i : Range(ExecutionSubgraph::kMaxFilterableSuccessors)) {
+    std::ostringstream oss;
+    oss << "blk" << i;
+    mid_blocks.push_back(oss.str().c_str());
+  }
+  ASSERT_EQ(mid_blocks.size(), ExecutionSubgraph::kMaxFilterableSuccessors);
+  std::vector<AdjacencyListGraph::Edge> edges;
+  for (const auto& mid : mid_blocks) {
+    edges.emplace_back("entry", mid);
+    edges.emplace_back(mid, "exit");
+  }
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry", "exit", edges));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  for (const auto& mid : mid_blocks) {
+    EXPECT_TRUE(contents.find(blks.Get(mid)) != contents.end()) << mid;
+  }
+  // + 2 for entry and exit nodes.
+  ASSERT_EQ(contents.size(), ExecutionSubgraph::kMaxFilterableSuccessors + 2);
+}
+
+// Test with max number of successors and some removals.
+TEST_F(ExecutionSubgraphTest, BigNodesMissing) {
+  std::vector<std::string> mid_blocks;
+  for (auto i : Range(ExecutionSubgraph::kMaxFilterableSuccessors)) {
+    std::ostringstream oss;
+    oss << "blk" << i;
+    mid_blocks.push_back(oss.str());
+  }
+  std::vector<AdjacencyListGraph::Edge> edges;
+  for (const auto& mid : mid_blocks) {
+    edges.emplace_back("entry", mid);
+    edges.emplace_back(mid, "exit");
+  }
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry", "exit", edges));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.RemoveBlock(blks.Get("blk2"));
+  esg.RemoveBlock(blks.Get("blk4"));
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), ExecutionSubgraph::kMaxFilterableSuccessors + 2 - 2);
+
+  // Not present, no path through.
+  ASSERT_TRUE(contents.find(blks.Get("blk2")) == contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("blk4")) == contents.end());
+}
+
+// Test with max number of successors and all successors removed.
+TEST_F(ExecutionSubgraphTest, BigNodesNoPath) {
+  std::vector<std::string> mid_blocks;
+  for (auto i : Range(ExecutionSubgraph::kMaxFilterableSuccessors)) {
+    std::ostringstream oss;
+    oss << "blk" << i;
+    mid_blocks.push_back(oss.str());
+  }
+  std::vector<AdjacencyListGraph::Edge> edges;
+  for (const auto& mid : mid_blocks) {
+    edges.emplace_back("entry", mid);
+    edges.emplace_back(mid, "exit");
+  }
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry", "exit", edges));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  for (const auto& mid : mid_blocks) {
+    esg.RemoveBlock(blks.Get(mid));
+  }
+  esg.Finalize();
+  ASSERT_FALSE(esg.IsValid());
+  ASSERT_FALSE(IsValidSubgraph(esg));
+}
+
+// Test with max number of successors
+TEST_F(ExecutionSubgraphTest, CanAnalyseBig) {
+  // Make an absurdly huge and well connected graph. This should be pretty worst-case scenario.
+  constexpr size_t kNumBlocks = ExecutionSubgraph::kMaxFilterableSuccessors + 1000;
+  std::vector<std::string> mid_blocks;
+  for (auto i : Range(kNumBlocks)) {
+    std::ostringstream oss;
+    oss << "blk" << i;
+    mid_blocks.push_back(oss.str());
+  }
+  std::vector<AdjacencyListGraph::Edge> edges;
+  for (auto cur : Range(kNumBlocks)) {
+    for (auto nxt :
+         Range(cur + 1,
+               std::min(cur + ExecutionSubgraph::kMaxFilterableSuccessors + 1, kNumBlocks))) {
+      edges.emplace_back(mid_blocks[cur], mid_blocks[nxt]);
+    }
+  }
+  AdjacencyListGraph blks(SetupFromAdjacencyList(mid_blocks.front(), mid_blocks.back(), edges));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  esg.Finalize();
+  ASSERT_TRUE(esg.IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), kNumBlocks);
+}
+
+// Test with many successors
+TEST_F(ExecutionSubgraphTest, CanAnalyseBig2) {
+  // Make an absurdly huge and well connected graph. This should be pretty worst-case scenario.
+  constexpr size_t kNumBlocks = ExecutionSubgraph::kMaxFilterableSuccessors + 1000;
+  constexpr size_t kTestMaxSuccessors = ExecutionSubgraph::kMaxFilterableSuccessors - 1;
+  std::vector<std::string> mid_blocks;
+  for (auto i : Range(kNumBlocks)) {
+    std::ostringstream oss;
+    oss << "blk" << i;
+    mid_blocks.push_back(oss.str());
+  }
+  std::vector<AdjacencyListGraph::Edge> edges;
+  for (auto cur : Range(kNumBlocks)) {
+    for (auto nxt : Range(cur + 1, std::min(cur + 1 + kTestMaxSuccessors, kNumBlocks))) {
+      edges.emplace_back(mid_blocks[cur], mid_blocks[nxt]);
+    }
+  }
+  edges.emplace_back(mid_blocks.front(), mid_blocks.back());
+  AdjacencyListGraph blks(SetupFromAdjacencyList(mid_blocks.front(), mid_blocks.back(), edges));
+  ASSERT_TRUE(ExecutionSubgraph::CanAnalyse(graph_));
+  ExecutionSubgraph esg(graph_, GetScopedAllocator());
+  constexpr size_t kToRemoveIdx = kNumBlocks / 2;
+  HBasicBlock* remove_implicit = blks.Get(mid_blocks[kToRemoveIdx]);
+  for (HBasicBlock* pred : remove_implicit->GetPredecessors()) {
+    esg.RemoveBlock(pred);
+  }
+  esg.Finalize();
+  EXPECT_TRUE(esg.IsValid());
+  EXPECT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg.ReachableBlocks().begin(),
+                                                  esg.ReachableBlocks().end());
+
+  // Only entry and exit. The middle ones should eliminate everything else.
+  EXPECT_EQ(contents.size(), 2u);
+  EXPECT_TRUE(contents.find(remove_implicit) == contents.end());
+  EXPECT_TRUE(contents.find(blks.Get(mid_blocks.front())) != contents.end());
+  EXPECT_TRUE(contents.find(blks.Get(mid_blocks.back())) != contents.end());
+}
+
+// Test with too many successors
+TEST_F(ExecutionSubgraphTest, CanNotAnalyseBig) {
+  std::vector<std::string> mid_blocks;
+  for (auto i : Range(ExecutionSubgraph::kMaxFilterableSuccessors + 4)) {
+    std::ostringstream oss;
+    oss << "blk" << i;
+    mid_blocks.push_back(oss.str());
+  }
+  std::vector<AdjacencyListGraph::Edge> edges;
+  for (const auto& mid : mid_blocks) {
+    edges.emplace_back("entry", mid);
+    edges.emplace_back(mid, "exit");
+  }
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry", "exit", edges));
+  ASSERT_FALSE(ExecutionSubgraph::CanAnalyse(graph_));
+}
+}  // namespace art
diff --git a/compiler/optimizing/execution_subgraph_test.h b/compiler/optimizing/execution_subgraph_test.h
new file mode 100644
index 0000000..13cb2bc
--- /dev/null
+++ b/compiler/optimizing/execution_subgraph_test.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 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_COMPILER_OPTIMIZING_EXECUTION_SUBGRAPH_TEST_H_
+#define ART_COMPILER_OPTIMIZING_EXECUTION_SUBGRAPH_TEST_H_
+
+#include "android-base/macros.h"
+
+namespace art {
+
+class HGraph;
+class ExecutionSubgraph;
+
+class ExecutionSubgraphTestHelper {
+ public:
+  static bool CalculateValidity(HGraph* graph, const ExecutionSubgraph* subgraph);
+
+ private:
+  ExecutionSubgraphTestHelper() = delete;
+
+  DISALLOW_COPY_AND_ASSIGN(ExecutionSubgraphTestHelper);
+};
+}  // namespace art
+
+#endif  // ART_COMPILER_OPTIMIZING_EXECUTION_SUBGRAPH_TEST_H_
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index 95cfe3e..d1769ce 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -25,6 +25,7 @@
 #include "base/bit_vector-inl.h"
 #include "base/scoped_arena_allocator.h"
 #include "base/scoped_arena_containers.h"
+#include "code_generator.h"
 #include "handle.h"
 #include "mirror/class.h"
 #include "obj_ptr-inl.h"
@@ -62,7 +63,7 @@
 size_t GraphChecker::Run(bool pass_change, size_t last_size) {
   size_t current_size = GetGraph()->GetReversePostOrder().size();
   if (!pass_change) {
-    // Nothing changed for certain. Do a quick sanity check on that assertion
+    // Nothing changed for certain. Do a quick check of the validity on that assertion
     // for anything other than the first call (when last size was still 0).
     if (last_size != 0) {
       if (current_size != last_size) {
@@ -506,7 +507,12 @@
     }
   }
 
-  if (instruction->CanThrowIntoCatchBlock()) {
+  if (instruction->CanThrow() && !instruction->HasEnvironment()) {
+    AddError(StringPrintf("Throwing instruction %s:%d in block %d does not have an environment.",
+                          instruction->DebugName(),
+                          instruction->GetId(),
+                          current_block_->GetBlockId()));
+  } else if (instruction->CanThrowIntoCatchBlock()) {
     // Find the top-level environment. This corresponds to the environment of
     // the catch block since we do not inline methods with try/catch.
     HEnvironment* environment = instruction->GetEnvironment();
@@ -1141,4 +1147,26 @@
   }
 }
 
+void GraphChecker::VisitVecOperation(HVecOperation* instruction) {
+  VisitInstruction(instruction);
+  if (codegen_ == nullptr) {
+    return;
+  }
+
+  if (!codegen_->SupportsPredicatedSIMD() && instruction->IsPredicated()) {
+    AddError(StringPrintf(
+             "%s %d must not be predicated.",
+             instruction->DebugName(),
+             instruction->GetId()));
+  }
+
+  if (codegen_->SupportsPredicatedSIMD() &&
+      (instruction->MustBePredicatedInPredicatedSIMDMode() != instruction->IsPredicated())) {
+    AddError(StringPrintf(
+             "%s %d predication mode is incorrect; see HVecOperation::MustBePredicated.",
+             instruction->DebugName(),
+             instruction->GetId()));
+  }
+}
+
 }  // namespace art
diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h
index 564b137..04c8d21 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -26,15 +26,20 @@
 
 namespace art {
 
+class CodeGenerator;
+
 // A control-flow graph visitor performing various checks.
 class GraphChecker : public HGraphDelegateVisitor {
  public:
-  explicit GraphChecker(HGraph* graph, const char* dump_prefix = "art::GraphChecker: ")
+  explicit GraphChecker(HGraph* graph,
+                        CodeGenerator* codegen = nullptr,
+                        const char* dump_prefix = "art::GraphChecker: ")
     : HGraphDelegateVisitor(graph),
       errors_(graph->GetAllocator()->Adapter(kArenaAllocGraphChecker)),
       dump_prefix_(dump_prefix),
       allocator_(graph->GetArenaStack()),
-      seen_ids_(&allocator_, graph->GetCurrentInstructionId(), false, kArenaAllocGraphChecker) {
+      seen_ids_(&allocator_, graph->GetCurrentInstructionId(), false, kArenaAllocGraphChecker),
+      codegen_(codegen) {
     seen_ids_.ClearAllBits();
   }
 
@@ -69,6 +74,8 @@
   void VisitTryBoundary(HTryBoundary* try_boundary) override;
   void VisitTypeConversion(HTypeConversion* instruction) override;
 
+  void VisitVecOperation(HVecOperation* instruction) override;
+
   void CheckTypeCheckBitstringInput(HTypeCheckInstruction* check,
                                     size_t input_pos,
                                     bool check_value,
@@ -125,6 +132,9 @@
   // The default value is true.
   bool check_reference_type_info_ = true;
 
+  // Used to access target information.
+  CodeGenerator* codegen_;
+
   DISALLOW_COPY_AND_ASSIGN(GraphChecker);
 };
 
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index d94c1fa..716fee4 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -19,9 +19,12 @@
 #include <dlfcn.h>
 
 #include <cctype>
+#include <ios>
 #include <sstream>
 
+#include "android-base/stringprintf.h"
 #include "art_method.h"
+#include "art_method-inl.h"
 #include "base/intrusive_forward_list.h"
 #include "bounds_check_elimination.h"
 #include "builder.h"
@@ -42,6 +45,12 @@
 
 namespace art {
 
+// Unique pass-name to identify that the dump is for printing to log.
+constexpr const char* kDebugDumpName = "debug";
+constexpr const char* kDebugDumpGraphName = "debug_graph";
+
+using android::base::StringPrintf;
+
 static bool HasWhitespace(const char* str) {
   DCHECK(str != nullptr);
   while (str[0] != 0) {
@@ -106,13 +115,17 @@
   }
 }
 
+#ifndef ART_STATIC_LIBART_COMPILER
 using create_disasm_prototype = Disassembler*(InstructionSet, DisassemblerOptions*);
+#endif
+
 class HGraphVisualizerDisassembler {
  public:
   HGraphVisualizerDisassembler(InstructionSet instruction_set,
                                const uint8_t* base_address,
                                const uint8_t* end_address)
       : instruction_set_(instruction_set), disassembler_(nullptr) {
+#ifndef ART_STATIC_LIBART_COMPILER
     constexpr const char* libart_disassembler_so_name =
         kIsDebugBuild ? "libartd-disassembler.so" : "libart-disassembler.so";
     libart_disassembler_handle_ = dlopen(libart_disassembler_so_name, RTLD_NOW);
@@ -128,10 +141,11 @@
                  << libart_disassembler_so_name << ": " << dlerror();
       return;
     }
+#endif
     // Reading the disassembly from 0x0 is easier, so we print relative
     // addresses. We will only disassemble the code once everything has
     // been generated, so we can read data in literal pools.
-    disassembler_ = std::unique_ptr<Disassembler>((*create_disassembler)(
+    disassembler_ = std::unique_ptr<Disassembler>(create_disassembler(
             instruction_set,
             new DisassemblerOptions(/* absolute_addresses= */ false,
                                     base_address,
@@ -145,9 +159,11 @@
   ~HGraphVisualizerDisassembler() {
     // We need to call ~Disassembler() before we close the library.
     disassembler_.reset();
+#ifndef ART_STATIC_LIBART_COMPILER
     if (libart_disassembler_handle_ != nullptr) {
       dlclose(libart_disassembler_handle_);
     }
+#endif
   }
 
   void Disassemble(std::ostream& output, size_t start, size_t end) const {
@@ -168,7 +184,9 @@
   InstructionSet instruction_set_;
   std::unique_ptr<Disassembler> disassembler_;
 
+#ifndef ART_STATIC_LIBART_COMPILER
   void* libart_disassembler_handle_;
+#endif
 };
 
 
@@ -182,7 +200,8 @@
                           const char* pass_name,
                           bool is_after_pass,
                           bool graph_in_bad_state,
-                          const CodeGenerator& codegen,
+                          const CodeGenerator* codegen,
+                          const BlockNamer& namer,
                           const DisassemblyInformation* disasm_info = nullptr)
       : HGraphDelegateVisitor(graph),
         output_(output),
@@ -191,12 +210,13 @@
         graph_in_bad_state_(graph_in_bad_state),
         codegen_(codegen),
         disasm_info_(disasm_info),
+        namer_(namer),
         disassembler_(disasm_info_ != nullptr
                       ? new HGraphVisualizerDisassembler(
-                            codegen_.GetInstructionSet(),
-                            codegen_.GetAssembler().CodeBufferBaseAddress(),
-                            codegen_.GetAssembler().CodeBufferBaseAddress()
-                                + codegen_.GetAssembler().CodeSize())
+                            codegen_->GetInstructionSet(),
+                            codegen_->GetAssembler().CodeBufferBaseAddress(),
+                            codegen_->GetAssembler().CodeBufferBaseAddress()
+                                + codegen_->GetAssembler().CodeSize())
                       : nullptr),
         indent_(0) {}
 
@@ -218,6 +238,11 @@
     output_ << "end_" << name << "\n";
   }
 
+  void PrintProperty(const char* name, HBasicBlock* blk) {
+    AddIndent();
+    output_ << name << " \"" << namer_.GetName(blk) << "\"\n";
+  }
+
   void PrintProperty(const char* name, const char* property) {
     AddIndent();
     output_ << name << " \"" << property << "\"\n";
@@ -253,7 +278,7 @@
     AddIndent();
     output_ << "predecessors";
     for (HBasicBlock* predecessor : block->GetPredecessors()) {
-      output_ << " \"B" << predecessor->GetBlockId() << "\" ";
+      output_ << " \"" << namer_.GetName(predecessor) << "\" ";
     }
     if (block->IsEntryBlock() && (disasm_info_ != nullptr)) {
       output_ << " \"" << kDisassemblyBlockFrameEntry << "\" ";
@@ -265,30 +290,35 @@
     AddIndent();
     output_ << "successors";
     for (HBasicBlock* successor : block->GetNormalSuccessors()) {
-      output_ << " \"B" << successor->GetBlockId() << "\" ";
+      output_ << " \"" << namer_.GetName(successor) << "\" ";
     }
     output_<< "\n";
   }
 
   void PrintExceptionHandlers(HBasicBlock* block) {
+    bool has_slow_paths = block->IsExitBlock() &&
+                          (disasm_info_ != nullptr) &&
+                          !disasm_info_->GetSlowPathIntervals().empty();
+    if (IsDebugDump() && block->GetExceptionalSuccessors().empty() && !has_slow_paths) {
+      return;
+    }
     AddIndent();
     output_ << "xhandlers";
     for (HBasicBlock* handler : block->GetExceptionalSuccessors()) {
-      output_ << " \"B" << handler->GetBlockId() << "\" ";
+      output_ << " \"" << namer_.GetName(handler) << "\" ";
     }
-    if (block->IsExitBlock() &&
-        (disasm_info_ != nullptr) &&
-        !disasm_info_->GetSlowPathIntervals().empty()) {
+    if (has_slow_paths) {
       output_ << " \"" << kDisassemblyBlockSlowPaths << "\" ";
     }
     output_<< "\n";
   }
 
   void DumpLocation(std::ostream& stream, const Location& location) {
+    DCHECK(codegen_ != nullptr);
     if (location.IsRegister()) {
-      codegen_.DumpCoreRegister(stream, location.reg());
+      codegen_->DumpCoreRegister(stream, location.reg());
     } else if (location.IsFpuRegister()) {
-      codegen_.DumpFloatingPointRegister(stream, location.reg());
+      codegen_->DumpFloatingPointRegister(stream, location.reg());
     } else if (location.IsConstant()) {
       stream << "#";
       HConstant* constant = location.GetConstant();
@@ -308,13 +338,13 @@
     } else if (location.IsStackSlot()) {
       stream << location.GetStackIndex() << "(sp)";
     } else if (location.IsFpuRegisterPair()) {
-      codegen_.DumpFloatingPointRegister(stream, location.low());
+      codegen_->DumpFloatingPointRegister(stream, location.low());
       stream << "|";
-      codegen_.DumpFloatingPointRegister(stream, location.high());
+      codegen_->DumpFloatingPointRegister(stream, location.high());
     } else if (location.IsRegisterPair()) {
-      codegen_.DumpCoreRegister(stream, location.low());
+      codegen_->DumpCoreRegister(stream, location.low());
       stream << "|";
-      codegen_.DumpCoreRegister(stream, location.high());
+      codegen_->DumpCoreRegister(stream, location.high());
     } else if (location.IsUnallocated()) {
       stream << "unallocated";
     } else if (location.IsDoubleStackSlot()) {
@@ -379,11 +409,10 @@
 
   void VisitLoadClass(HLoadClass* load_class) override {
     StartAttributeStream("load_kind") << load_class->GetLoadKind();
-    const char* descriptor = load_class->GetDexFile().GetTypeDescriptor(
-        load_class->GetDexFile().GetTypeId(load_class->GetTypeIndex()));
-    StartAttributeStream("class_name") << PrettyDescriptor(descriptor);
-    StartAttributeStream("gen_clinit_check") << std::boolalpha
-        << load_class->MustGenerateClinitCheck() << std::noboolalpha;
+    StartAttributeStream("class_name")
+        << load_class->GetDexFile().PrettyType(load_class->GetTypeIndex());
+    StartAttributeStream("gen_clinit_check")
+        << std::boolalpha << load_class->MustGenerateClinitCheck() << std::noboolalpha;
     StartAttributeStream("needs_access_check") << std::boolalpha
         << load_class->NeedsAccessCheck() << std::noboolalpha;
   }
@@ -396,8 +425,13 @@
   void VisitLoadMethodType(HLoadMethodType* load_method_type) override {
     StartAttributeStream("load_kind") << "RuntimeCall";
     const DexFile& dex_file = load_method_type->GetDexFile();
-    const dex::ProtoId& proto_id = dex_file.GetProtoId(load_method_type->GetProtoIndex());
-    StartAttributeStream("method_type") << dex_file.GetProtoSignature(proto_id);
+    if (dex_file.NumProtoIds() >= load_method_type->GetProtoIndex().index_) {
+      const dex::ProtoId& proto_id = dex_file.GetProtoId(load_method_type->GetProtoIndex());
+      StartAttributeStream("method_type") << dex_file.GetProtoSignature(proto_id);
+    } else {
+      StartAttributeStream("method_type")
+          << "<<Unknown proto-idx: " << load_method_type->GetProtoIndex() << ">>";
+    }
   }
 
   void VisitLoadString(HLoadString* load_string) override {
@@ -449,14 +483,11 @@
   }
 
   void VisitCompare(HCompare* compare) override {
-    ComparisonBias bias = compare->GetBias();
-    StartAttributeStream("bias") << (bias == ComparisonBias::kGtBias
-                                     ? "gt"
-                                     : (bias == ComparisonBias::kLtBias ? "lt" : "none"));
+    StartAttributeStream("bias") << compare->GetBias();
   }
 
   void VisitInvoke(HInvoke* invoke) override {
-    StartAttributeStream("dex_file_index") << invoke->GetDexMethodIndex();
+    StartAttributeStream("dex_file_index") << invoke->GetMethodReference().index;
     ArtMethod* method = invoke->GetResolvedMethod();
     // We don't print signatures, which conflict with c1visualizer format.
     static constexpr bool kWithSignature = false;
@@ -464,12 +495,15 @@
     // other invokes might be coming from inlined methods.
     ScopedObjectAccess soa(Thread::Current());
     std::string method_name = (method == nullptr)
-        ? GetGraph()->GetDexFile().PrettyMethod(invoke->GetDexMethodIndex(), kWithSignature)
+        ? invoke->GetMethodReference().PrettyMethod(kWithSignature)
         : method->PrettyMethod(kWithSignature);
     StartAttributeStream("method_name") << method_name;
     StartAttributeStream("always_throws") << std::boolalpha
                                           << invoke->AlwaysThrows()
                                           << std::noboolalpha;
+    if (method != nullptr) {
+      StartAttributeStream("method_index") << method->GetMethodIndex();
+    }
   }
 
   void VisitInvokeUnresolved(HInvokeUnresolved* invoke) override {
@@ -496,6 +530,13 @@
     StartAttributeStream("invoke_type") << "InvokePolymorphic";
   }
 
+  void VisitPredicatedInstanceFieldGet(HPredicatedInstanceFieldGet* iget) override {
+    StartAttributeStream("field_name") <<
+        iget->GetFieldInfo().GetDexFile().PrettyField(iget->GetFieldInfo().GetFieldIndex(),
+                                                      /* with type */ false);
+    StartAttributeStream("field_type") << iget->GetFieldType();
+  }
+
   void VisitInstanceFieldGet(HInstanceFieldGet* iget) override {
     StartAttributeStream("field_name") <<
         iget->GetFieldInfo().GetDexFile().PrettyField(iget->GetFieldInfo().GetFieldIndex(),
@@ -508,6 +549,7 @@
         iset->GetFieldInfo().GetDexFile().PrettyField(iset->GetFieldInfo().GetFieldIndex(),
                                                       /* with type */ false);
     StartAttributeStream("field_type") << iset->GetFieldType();
+    StartAttributeStream("predicated") << std::boolalpha << iset->GetIsPredicatedSet();
   }
 
   void VisitStaticFieldGet(HStaticFieldGet* sget) override {
@@ -595,6 +637,10 @@
     return strcmp(pass_name_, name) == 0;
   }
 
+  bool IsDebugDump() {
+    return IsPass(kDebugDumpGraphName) || IsPass(kDebugDumpName);
+  }
+
   void PrintInstruction(HInstruction* instruction) {
     output_ << instruction->DebugName();
     HConstInputsRef inputs = instruction->GetInputs();
@@ -610,6 +656,11 @@
     } else {
       StartAttributeStream("dex_pc") << "n/a";
     }
+    HBasicBlock* block = instruction->GetBlock();
+    if (IsPass(kDebugDumpName)) {
+      // Include block name for logcat use.
+      StartAttributeStream("block") << namer_.GetName(block);
+    }
     instruction->Accept(this);
     if (instruction->HasEnvironment()) {
       StringList envs;
@@ -660,14 +711,14 @@
       }
     }
 
-    HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
+    HLoopInformation* loop_info = (block != nullptr) ? block->GetLoopInformation() : nullptr;
     if (loop_info == nullptr) {
       StartAttributeStream("loop") << "none";
     } else {
-      StartAttributeStream("loop") << "B" << loop_info->GetHeader()->GetBlockId();
+      StartAttributeStream("loop") << namer_.GetName(loop_info->GetHeader());
       HLoopInformation* outer = loop_info->GetPreHeader()->GetLoopInformation();
       if (outer != nullptr) {
-        StartAttributeStream("outer_loop") << "B" << outer->GetHeader()->GetBlockId();
+        StartAttributeStream("outer_loop") << namer_.GetName(outer->GetHeader());
       } else {
         StartAttributeStream("outer_loop") << "none";
       }
@@ -678,7 +729,8 @@
     // For the builder and the inliner, we want to add extra information on HInstructions
     // that have reference types, and also HInstanceOf/HCheckcast.
     if ((IsPass(HGraphBuilder::kBuilderPassName)
-        || IsPass(HInliner::kInlinerPassName))
+        || IsPass(HInliner::kInlinerPassName)
+        || IsDebugDump())
         && (instruction->GetType() == DataType::Type::kReference ||
             instruction->IsInstanceOf() ||
             instruction->IsCheckCast())) {
@@ -708,6 +760,7 @@
         // doesn't run or doesn't inline anything, the NullConstant remains untyped.
         // So we should check NullConstants for validity only after reference type propagation.
         DCHECK(graph_in_bad_state_ ||
+               IsDebugDump() ||
                (!is_after_pass_ && IsPass(HGraphBuilder::kBuilderPassName)))
             << instruction->DebugName() << instruction->GetId() << " has invalid rti "
             << (is_after_pass_ ? "after" : "before") << " pass " << pass_name_;
@@ -807,12 +860,13 @@
 
   void Run() {
     StartTag("cfg");
-    std::string pass_desc = std::string(pass_name_)
-                          + " ("
-                          + (is_after_pass_ ? "after" : "before")
-                          + (graph_in_bad_state_ ? ", bad_state" : "")
-                          + ")";
-    PrintProperty("name", pass_desc.c_str());
+    std::ostringstream oss;
+    oss << pass_name_;
+    if (!IsDebugDump()) {
+      oss << " (" << (is_after_pass_ ? "after" : "before")
+          << (graph_in_bad_state_ ? ", bad_state" : "") << ")";
+    }
+    PrintProperty("name", oss.str().c_str());
     if (disasm_info_ != nullptr) {
       DumpDisassemblyBlockForFrameEntry();
     }
@@ -824,14 +878,21 @@
     Flush();
   }
 
+  void Run(HInstruction* instruction) {
+    output_ << DataType::TypeId(instruction->GetType()) << instruction->GetId() << " ";
+    PrintInstruction(instruction);
+    Flush();
+  }
+
   void VisitBasicBlock(HBasicBlock* block) override {
     StartTag("block");
-    PrintProperty("name", "B", block->GetBlockId());
+    PrintProperty("name", block);
     if (block->GetLifetimeStart() != kNoLifetime) {
       // Piggy back on these fields to show the lifetime of the block.
       PrintInt("from_bci", block->GetLifetimeStart());
       PrintInt("to_bci", block->GetLifetimeEnd());
-    } else {
+    } else if (!IsDebugDump()) {
+      // Don't print useless information to logcat.
       PrintInt("from_bci", -1);
       PrintInt("to_bci", -1);
     }
@@ -841,30 +902,33 @@
 
     if (block->IsCatchBlock()) {
       PrintProperty("flags", "catch_block");
-    } else {
+    } else if (!IsDebugDump()) {
+      // Don't print useless information to logcat
       PrintEmptyProperty("flags");
     }
 
     if (block->GetDominator() != nullptr) {
-      PrintProperty("dominator", "B", block->GetDominator()->GetBlockId());
+      PrintProperty("dominator", block->GetDominator());
     }
 
-    StartTag("states");
-    StartTag("locals");
-    PrintInt("size", 0);
-    PrintProperty("method", "None");
-    for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
-      AddIndent();
-      HInstruction* instruction = it.Current();
-      output_ << instruction->GetId() << " " << DataType::TypeId(instruction->GetType())
-              << instruction->GetId() << "[ ";
-      for (const HInstruction* input : instruction->GetInputs()) {
-        output_ << input->GetId() << " ";
+    if (!IsDebugDump() || !block->GetPhis().IsEmpty()) {
+      StartTag("states");
+      StartTag("locals");
+      PrintInt("size", 0);
+      PrintProperty("method", "None");
+      for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
+        AddIndent();
+        HInstruction* instruction = it.Current();
+        output_ << instruction->GetId() << " " << DataType::TypeId(instruction->GetType())
+                << instruction->GetId() << "[ ";
+        for (const HInstruction* input : instruction->GetInputs()) {
+          output_ << input->GetId() << " ";
+        }
+        output_ << "]\n";
       }
-      output_ << "]\n";
+      EndTag("locals");
+      EndTag("states");
     }
-    EndTag("locals");
-    EndTag("states");
 
     StartTag("HIR");
     PrintInstructions(block->GetPhis());
@@ -882,22 +946,33 @@
   const char* pass_name_;
   const bool is_after_pass_;
   const bool graph_in_bad_state_;
-  const CodeGenerator& codegen_;
+  const CodeGenerator* codegen_;
   const DisassemblyInformation* disasm_info_;
+  const BlockNamer& namer_;
   std::unique_ptr<HGraphVisualizerDisassembler> disassembler_;
   size_t indent_;
 
   DISALLOW_COPY_AND_ASSIGN(HGraphVisualizerPrinter);
 };
 
+std::ostream& HGraphVisualizer::OptionalDefaultNamer::PrintName(std::ostream& os,
+                                                                HBasicBlock* blk) const {
+  if (namer_) {
+    return namer_->get().PrintName(os, blk);
+  } else {
+    return BlockNamer::PrintName(os, blk);
+  }
+}
+
 HGraphVisualizer::HGraphVisualizer(std::ostream* output,
                                    HGraph* graph,
-                                   const CodeGenerator& codegen)
-  : output_(output), graph_(graph), codegen_(codegen) {}
+                                   const CodeGenerator* codegen,
+                                   std::optional<std::reference_wrapper<const BlockNamer>> namer)
+    : output_(output), graph_(graph), codegen_(codegen), namer_(namer) {}
 
 void HGraphVisualizer::PrintHeader(const char* method_name) const {
   DCHECK(output_ != nullptr);
-  HGraphVisualizerPrinter printer(graph_, *output_, "", true, false, codegen_);
+  HGraphVisualizerPrinter printer(graph_, *output_, "", true, false, codegen_, namer_);
   printer.StartTag("compilation");
   printer.PrintProperty("name", method_name);
   printer.PrintProperty("method", method_name);
@@ -906,6 +981,25 @@
   printer.Flush();
 }
 
+std::string HGraphVisualizer::InsertMetaDataAsCompilationBlock(const std::string& meta_data) {
+  std::string time_str = std::to_string(time(nullptr));
+  std::string quoted_meta_data = "\"" + meta_data + "\"";
+  return StringPrintf("begin_compilation\n"
+                      "  name %s\n"
+                      "  method %s\n"
+                      "  date %s\n"
+                      "end_compilation\n",
+                      quoted_meta_data.c_str(),
+                      quoted_meta_data.c_str(),
+                      time_str.c_str());
+}
+
+void HGraphVisualizer::DumpGraphDebug() const {
+  DumpGraph(/* pass_name= */ kDebugDumpGraphName,
+            /* is_after_pass= */ false,
+            /* graph_in_bad_state= */ true);
+}
+
 void HGraphVisualizer::DumpGraph(const char* pass_name,
                                  bool is_after_pass,
                                  bool graph_in_bad_state) const {
@@ -916,7 +1010,8 @@
                                     pass_name,
                                     is_after_pass,
                                     graph_in_bad_state,
-                                    codegen_);
+                                    codegen_,
+                                    namer_);
     printer.Run();
   }
 }
@@ -930,9 +1025,24 @@
                                     /* is_after_pass= */ true,
                                     /* graph_in_bad_state= */ false,
                                     codegen_,
-                                    codegen_.GetDisassemblyInformation());
+                                    namer_,
+                                    codegen_->GetDisassemblyInformation());
     printer.Run();
   }
 }
 
+void HGraphVisualizer::DumpInstruction(std::ostream* output,
+                                       HGraph* graph,
+                                       HInstruction* instruction) {
+  BlockNamer namer;
+  HGraphVisualizerPrinter printer(graph,
+                                  *output,
+                                  /* pass_name= */ kDebugDumpName,
+                                  /* is_after_pass= */ false,
+                                  /* graph_in_bad_state= */ false,
+                                  /* codegen= */ nullptr,
+                                  /* namer= */ namer);
+  printer.Run(instruction);
+}
+
 }  // namespace art
diff --git a/compiler/optimizing/graph_visualizer.h b/compiler/optimizing/graph_visualizer.h
index 66588f6..3429c11 100644
--- a/compiler/optimizing/graph_visualizer.h
+++ b/compiler/optimizing/graph_visualizer.h
@@ -17,11 +17,13 @@
 #ifndef ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
 #define ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
 
+#include <functional>
 #include <ostream>
 
 #include "arch/instruction_set.h"
 #include "base/arena_containers.h"
 #include "base/value_object.h"
+#include "block_namer.h"
 
 namespace art {
 
@@ -101,16 +103,37 @@
  public:
   HGraphVisualizer(std::ostream* output,
                    HGraph* graph,
-                   const CodeGenerator& codegen);
+                   const CodeGenerator* codegen,
+                   std::optional<std::reference_wrapper<const BlockNamer>> namer = std::nullopt);
 
   void PrintHeader(const char* method_name) const;
   void DumpGraph(const char* pass_name, bool is_after_pass, bool graph_in_bad_state) const;
+  void DumpGraphDebug() const;
   void DumpGraphWithDisassembly() const;
 
+  // C1visualizer file format does not support inserting arbitrary metadata into a cfg
+  // file. As a workaround a fake compilation block with the metadata in the name and the
+  // method attributes is used. Such empty blocks don't break the c1visualizer parser.
+  static std::string InsertMetaDataAsCompilationBlock(const std::string& meta_data);
+
+  static void DumpInstruction(std::ostream* output, HGraph* graph, HInstruction* instruction);
+
  private:
+  class OptionalDefaultNamer final : public BlockNamer {
+   public:
+    explicit OptionalDefaultNamer(std::optional<std::reference_wrapper<const BlockNamer>> inner)
+        : namer_(inner) {}
+
+    std::ostream& PrintName(std::ostream& os, HBasicBlock* blk) const override;
+
+   private:
+    std::optional<std::reference_wrapper<const BlockNamer>> namer_;
+  };
+
   std::ostream* const output_;
   HGraph* const graph_;
-  const CodeGenerator& codegen_;
+  const CodeGenerator* codegen_;
+  OptionalDefaultNamer namer_;
 
   DISALLOW_COPY_AND_ASSIGN(HGraphVisualizer);
 };
diff --git a/compiler/optimizing/gvn.cc b/compiler/optimizing/gvn.cc
index e8460a8..c7cd223 100644
--- a/compiler/optimizing/gvn.cc
+++ b/compiler/optimizing/gvn.cc
@@ -126,7 +126,7 @@
   // Removes all instructions in the set affected by the given side effects.
   void Kill(SideEffects side_effects) {
     DeleteAllImpureWhich([side_effects](Node* node) {
-      return node->GetInstruction()->GetSideEffects().MayDependOn(side_effects);
+      return node->GetSideEffects().MayDependOn(side_effects);
     });
   }
 
@@ -197,6 +197,21 @@
       return new (allocator) Node(instruction_, hash_code_, new_next);
     }
 
+    SideEffects GetSideEffects() const {
+      // Deoptimize is a weird instruction since it's predicated and
+      // never-return. Its side-effects are to prevent the splitting of dex
+      // instructions across it (which could cause inconsistencies once we begin
+      // interpreting again). In the context of GVN the 'perform-deopt' branch is not
+      // relevant and we only need to care about the no-op case, in which case there are
+      // no side-effects. By doing this we are able to eliminate redundant (i.e.
+      // dominated deopts with GVNd conditions) deoptimizations.
+      if (instruction_->IsDeoptimize()) {
+        return SideEffects::None();
+      } else {
+        return instruction_->GetSideEffects();
+      }
+    }
+
    private:
     HInstruction* const instruction_;
     const size_t hash_code_;
@@ -479,7 +494,10 @@
     //
     // BoundType is a special case example of an instruction which shouldn't be moved but can be
     // GVN'ed.
-    if (current->CanBeMoved() || current->IsBoundType()) {
+    //
+    // Deoptimize is a special case since even though we don't want to move it we can still remove
+    // it for GVN.
+    if (current->CanBeMoved() || current->IsBoundType() || current->IsDeoptimize()) {
       if (current->IsBinaryOperation() && current->AsBinaryOperation()->IsCommutative()) {
         // For commutative ops, (x op y) will be treated the same as (y op x)
         // after fixed ordering.
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc
index 4c78fa8..72c2064 100644
--- a/compiler/optimizing/induction_var_range.cc
+++ b/compiler/optimizing/induction_var_range.cc
@@ -70,28 +70,6 @@
   return pow;
 }
 
-/**
- * Detects an instruction that is >= 0. As long as the value is carried by
- * a single instruction, arithmetic wrap-around cannot occur.
- */
-static bool IsGEZero(HInstruction* instruction) {
-  DCHECK(instruction != nullptr);
-  if (instruction->IsArrayLength()) {
-    return true;
-  } else if (instruction->IsMin()) {
-    // Instruction MIN(>=0, >=0) is >= 0.
-    return IsGEZero(instruction->InputAt(0)) &&
-           IsGEZero(instruction->InputAt(1));
-  } else if (instruction->IsAbs()) {
-    // Instruction ABS(>=0) is >= 0.
-    // NOTE: ABS(minint) = minint prevents assuming
-    //       >= 0 without looking at the argument.
-    return IsGEZero(instruction->InputAt(0));
-  }
-  int64_t value = -1;
-  return IsInt64AndGet(instruction, &value) && value >= 0;
-}
-
 /** Hunts "under the hood" for a suitable instruction at the hint. */
 static bool IsMaxAtHint(
     HInstruction* instruction, HInstruction* hint, /*out*/HInstruction** suitable) {
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 24d6e65..1d9520d 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -21,7 +21,7 @@
 #include "base/logging.h"
 #include "builder.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "constant_folding.h"
 #include "data_type-inl.h"
 #include "dead_code_elimination.h"
@@ -148,15 +148,14 @@
   DCHECK_NE(total_number_of_instructions_, 0u);
   DCHECK_NE(inlining_budget_, 0u);
 
-  // If we're compiling with a core image (which is only used for
-  // test purposes), honor inlining directives in method names:
+  // If we're compiling tests, honor inlining directives in method names:
   // - if a method's name contains the substring "$noinline$", do not
   //   inline that method;
   // - if a method's name contains the substring "$inline$", ensure
   //   that this method is actually inlined.
   // We limit the latter to AOT compilation, as the JIT may or may not inline
   // depending on the state of classes at runtime.
-  const bool honor_noinline_directives = codegen_->GetCompilerOptions().CompilingWithCoreImage();
+  const bool honor_noinline_directives = codegen_->GetCompilerOptions().CompileArtTest();
   const bool honor_inline_directives =
       honor_noinline_directives && Runtime::Current()->IsAotCompiler();
 
@@ -174,8 +173,8 @@
       if (call != nullptr && call->GetIntrinsic() == Intrinsics::kNone) {
         if (honor_noinline_directives) {
           // Debugging case: directives in method names control or assert on inlining.
-          std::string callee_name = outer_compilation_unit_.GetDexFile()->PrettyMethod(
-              call->GetDexMethodIndex(), /* with_signature= */ false);
+          std::string callee_name =
+              call->GetMethodReference().PrettyMethod(/* with_signature= */ false);
           // Tests prevent inlining by having $noinline$ in their method names.
           if (callee_name.find("$noinline$") == std::string::npos) {
             if (TryInline(call)) {
@@ -210,8 +209,9 @@
  * the actual runtime target of an interface or virtual call.
  * Return nullptr if the runtime target cannot be proven.
  */
-static ArtMethod* FindVirtualOrInterfaceTarget(HInvoke* invoke, ArtMethod* resolved_method)
+static ArtMethod* FindVirtualOrInterfaceTarget(HInvoke* invoke)
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  ArtMethod* resolved_method = invoke->GetResolvedMethod();
   if (IsMethodOrDeclaringClassFinal(resolved_method)) {
     // No need to lookup further, the resolved method will be the target.
     return resolved_method;
@@ -320,43 +320,10 @@
   return index;
 }
 
-class ScopedProfilingInfoInlineUse {
- public:
-  explicit ScopedProfilingInfoInlineUse(ArtMethod* method, Thread* self)
-      : method_(method),
-        self_(self),
-        // Fetch the profiling info ahead of using it. If it's null when fetching,
-        // we should not call JitCodeCache::DoneInlining.
-        profiling_info_(
-            Runtime::Current()->GetJit()->GetCodeCache()->NotifyCompilerUse(method, self)) {
-  }
-
-  ~ScopedProfilingInfoInlineUse() {
-    if (profiling_info_ != nullptr) {
-      PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
-      DCHECK_EQ(profiling_info_, method_->GetProfilingInfo(pointer_size));
-      Runtime::Current()->GetJit()->GetCodeCache()->DoneCompilerUse(method_, self_);
-    }
-  }
-
-  ProfilingInfo* GetProfilingInfo() const { return profiling_info_; }
-
- private:
-  ArtMethod* const method_;
-  Thread* const self_;
-  ProfilingInfo* const profiling_info_;
-};
-
 HInliner::InlineCacheType HInliner::GetInlineCacheType(
-    const Handle<mirror::ObjectArray<mirror::Class>>& classes)
-  REQUIRES_SHARED(Locks::mutator_lock_) {
-  uint8_t number_of_types = 0;
-  for (; number_of_types < InlineCache::kIndividualCacheSize; ++number_of_types) {
-    if (classes->Get(number_of_types) == nullptr) {
-      break;
-    }
-  }
-
+    const StackHandleScope<InlineCache::kIndividualCacheSize>& classes) {
+  DCHECK_EQ(classes.NumberOfReferences(), InlineCache::kIndividualCacheSize);
+  uint8_t number_of_types = InlineCache::kIndividualCacheSize - classes.RemainingSlots();
   if (number_of_types == 0) {
     return kInlineCacheUninitialized;
   } else if (number_of_types == 1) {
@@ -368,13 +335,14 @@
   }
 }
 
-static ObjPtr<mirror::Class> GetMonomorphicType(Handle<mirror::ObjectArray<mirror::Class>> classes)
+static inline ObjPtr<mirror::Class> GetMonomorphicType(
+    const StackHandleScope<InlineCache::kIndividualCacheSize>& classes)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  DCHECK(classes->Get(0) != nullptr);
-  return classes->Get(0);
+  DCHECK(classes.GetReference(0) != nullptr);
+  return classes.GetReference(0)->AsClass();
 }
 
-ArtMethod* HInliner::TryCHADevirtualization(ArtMethod* resolved_method) {
+ArtMethod* HInliner::FindMethodFromCHA(ArtMethod* resolved_method) {
   if (!resolved_method->HasSingleImplementation()) {
     return nullptr;
   }
@@ -415,7 +383,7 @@
 static bool IsMethodUnverified(const CompilerOptions& compiler_options, ArtMethod* method)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   if (!method->GetDeclaringClass()->IsVerified()) {
-    if (Runtime::Current()->UseJitCompilation()) {
+    if (compiler_options.IsJitCompiler()) {
       // We're at runtime, we know this is cold code if the class
       // is not verified, so don't bother analyzing.
       return true;
@@ -453,7 +421,6 @@
       case Instruction::RETURN_VOID:
       case Instruction::RETURN_WIDE:
       case Instruction::RETURN_OBJECT:
-      case Instruction::RETURN_VOID_NO_BARRIER:
         return false;  // found regular control flow back
       case Instruction::THROW:
         throw_seen = true;
@@ -465,42 +432,24 @@
   return throw_seen;
 }
 
-ArtMethod* HInliner::FindActualCallTarget(HInvoke* invoke_instruction, bool* cha_devirtualize) {
-  ArtMethod* resolved_method = invoke_instruction->GetResolvedMethod();
-  DCHECK(resolved_method != nullptr);
-
-  ArtMethod* actual_method = nullptr;
-  if (invoke_instruction->IsInvokeStaticOrDirect()) {
-    actual_method = resolved_method;
-  } else {
-    // Check if we can statically find the method.
-    actual_method = FindVirtualOrInterfaceTarget(invoke_instruction, resolved_method);
-  }
-
-  if (actual_method == nullptr) {
-    ArtMethod* method = TryCHADevirtualization(resolved_method);
-    if (method != nullptr) {
-      *cha_devirtualize = true;
-      actual_method = method;
-      LOG_NOTE() << "Try CHA-based inlining of " << actual_method->PrettyMethod();
-    }
-  }
-
-  return actual_method;
-}
-
 bool HInliner::TryInline(HInvoke* invoke_instruction) {
-  if (invoke_instruction->IsInvokeUnresolved() ||
-      invoke_instruction->IsInvokePolymorphic() ||
-      invoke_instruction->IsInvokeCustom()) {
-    return false;  // Don't bother to move further if we know the method is unresolved or the
-                   // invocation is polymorphic (invoke-{polymorphic,custom}).
+  MaybeRecordStat(stats_, MethodCompilationStat::kTryInline);
+
+  // Don't bother to move further if we know the method is unresolved or the invocation is
+  // polymorphic (invoke-{polymorphic,custom}).
+  if (invoke_instruction->IsInvokeUnresolved()) {
+    MaybeRecordStat(stats_, MethodCompilationStat::kNotInlinedUnresolved);
+    return false;
+  } else if (invoke_instruction->IsInvokePolymorphic()) {
+    MaybeRecordStat(stats_, MethodCompilationStat::kNotInlinedPolymorphic);
+    return false;
+  } else if (invoke_instruction->IsInvokeCustom()) {
+    MaybeRecordStat(stats_, MethodCompilationStat::kNotInlinedCustom);
+    return false;
   }
 
   ScopedObjectAccess soa(Thread::Current());
-  uint32_t method_index = invoke_instruction->GetDexMethodIndex();
-  const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
-  LOG_TRY() << caller_dex_file.PrettyMethod(method_index);
+  LOG_TRY() << invoke_instruction->GetMethodReference().PrettyMethod();
 
   ArtMethod* resolved_method = invoke_instruction->GetResolvedMethod();
   if (resolved_method == nullptr) {
@@ -510,61 +459,66 @@
     return false;
   }
 
-  bool cha_devirtualize = false;
-  ArtMethod* actual_method = FindActualCallTarget(invoke_instruction, &cha_devirtualize);
+  ArtMethod* actual_method = invoke_instruction->IsInvokeStaticOrDirect()
+      ? invoke_instruction->GetResolvedMethod()
+      : FindVirtualOrInterfaceTarget(invoke_instruction);
 
-  // If we didn't find a method, see if we can inline from the inline caches.
-  if (actual_method == nullptr) {
-    DCHECK(!invoke_instruction->IsInvokeStaticOrDirect());
-
-    return TryInlineFromInlineCache(caller_dex_file, invoke_instruction, resolved_method);
-  }
-
-  // Single target.
-  bool result = TryInlineAndReplace(invoke_instruction,
-                                    actual_method,
-                                    ReferenceTypeInfo::CreateInvalid(),
-                                    /* do_rtp= */ true,
-                                    cha_devirtualize);
-  if (result) {
-    // Successfully inlined.
-    if (!invoke_instruction->IsInvokeStaticOrDirect()) {
-      if (cha_devirtualize) {
-        // Add dependency due to devirtualization. We've assumed resolved_method
-        // has single implementation.
-        outermost_graph_->AddCHASingleImplementationDependency(resolved_method);
-        MaybeRecordStat(stats_, MethodCompilationStat::kCHAInline);
+  if (actual_method != nullptr) {
+    // Single target.
+    bool result = TryInlineAndReplace(invoke_instruction,
+                                      actual_method,
+                                      ReferenceTypeInfo::CreateInvalid(),
+                                      /* do_rtp= */ true);
+    if (result) {
+      MaybeRecordStat(stats_, MethodCompilationStat::kInlinedInvokeVirtualOrInterface);
+    } else {
+      HInvoke* invoke_to_analyze = nullptr;
+      if (TryDevirtualize(invoke_instruction, actual_method, &invoke_to_analyze)) {
+        // Consider devirtualization as inlining.
+        result = true;
+        MaybeRecordStat(stats_, MethodCompilationStat::kDevirtualized);
       } else {
-        MaybeRecordStat(stats_, MethodCompilationStat::kInlinedInvokeVirtualOrInterface);
+        invoke_to_analyze = invoke_instruction;
+      }
+      // Set always throws property for non-inlined method call with single
+      // target.
+      if (AlwaysThrows(codegen_->GetCompilerOptions(), actual_method)) {
+        invoke_to_analyze->SetAlwaysThrows(true);
       }
     }
-  } else if (!cha_devirtualize && AlwaysThrows(codegen_->GetCompilerOptions(), actual_method)) {
-    // Set always throws property for non-inlined method call with single target
-    // (unless it was obtained through CHA, because that would imply we have
-    // to add the CHA dependency, which seems not worth it).
-    invoke_instruction->SetAlwaysThrows(true);
+    return result;
   }
-  return result;
+
+  DCHECK(!invoke_instruction->IsInvokeStaticOrDirect());
+
+  if (TryInlineFromCHA(invoke_instruction)) {
+    return true;
+  }
+  return TryInlineFromInlineCache(invoke_instruction);
 }
 
-static Handle<mirror::ObjectArray<mirror::Class>> AllocateInlineCacheHolder(
-    const DexCompilationUnit& compilation_unit,
-    StackHandleScope<1>* hs)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  Thread* self = Thread::Current();
-  ClassLinker* class_linker = compilation_unit.GetClassLinker();
-  Handle<mirror::ObjectArray<mirror::Class>> inline_cache = hs->NewHandle(
-      mirror::ObjectArray<mirror::Class>::Alloc(
-          self,
-          GetClassRoot<mirror::ObjectArray<mirror::Class>>(class_linker),
-          InlineCache::kIndividualCacheSize));
-  if (inline_cache == nullptr) {
-    // We got an OOME. Just clear the exception, and don't inline.
-    DCHECK(self->IsExceptionPending());
-    self->ClearException();
-    VLOG(compiler) << "Out of memory in the compiler when trying to inline";
+bool HInliner::TryInlineFromCHA(HInvoke* invoke_instruction) {
+  ArtMethod* method = FindMethodFromCHA(invoke_instruction->GetResolvedMethod());
+  if (method == nullptr) {
+    return false;
   }
-  return inline_cache;
+  LOG_NOTE() << "Try CHA-based inlining of " << method->PrettyMethod();
+
+  uint32_t dex_pc = invoke_instruction->GetDexPc();
+  HInstruction* cursor = invoke_instruction->GetPrevious();
+  HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
+  if (!TryInlineAndReplace(invoke_instruction,
+                           method,
+                           ReferenceTypeInfo::CreateInvalid(),
+                           /* do_rtp= */ true)) {
+    return false;
+  }
+  AddCHAGuard(invoke_instruction, dex_pc, cursor, bb_cursor);
+  // Add dependency due to devirtualization: we are assuming the resolved method
+  // has a single implementation.
+  outermost_graph_->AddCHASingleImplementationDependency(invoke_instruction->GetResolvedMethod());
+  MaybeRecordStat(stats_, MethodCompilationStat::kCHAInline);
+  return true;
 }
 
 bool HInliner::UseOnlyPolymorphicInliningWithNoDeopt() {
@@ -594,35 +548,32 @@
   //     We may come from the interpreter and it may have seen different receiver types.
   return Runtime::Current()->IsAotCompiler() || outermost_graph_->IsCompilingOsr();
 }
-bool HInliner::TryInlineFromInlineCache(const DexFile& caller_dex_file,
-                                        HInvoke* invoke_instruction,
-                                        ArtMethod* resolved_method)
+bool HInliner::TryInlineFromInlineCache(HInvoke* invoke_instruction)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   if (Runtime::Current()->IsAotCompiler() && !kUseAOTInlineCaches) {
     return false;
   }
 
-  StackHandleScope<1> hs(Thread::Current());
-  Handle<mirror::ObjectArray<mirror::Class>> inline_cache;
+  StackHandleScope<InlineCache::kIndividualCacheSize> classes(Thread::Current());
   // The Zygote JIT compiles based on a profile, so we shouldn't use runtime inline caches
   // for it.
   InlineCacheType inline_cache_type =
       (Runtime::Current()->IsAotCompiler() || Runtime::Current()->IsZygote())
-          ? GetInlineCacheAOT(caller_dex_file, invoke_instruction, &hs, &inline_cache)
-          : GetInlineCacheJIT(invoke_instruction, &hs, &inline_cache);
+          ? GetInlineCacheAOT(invoke_instruction, &classes)
+          : GetInlineCacheJIT(invoke_instruction, &classes);
 
   switch (inline_cache_type) {
     case kInlineCacheNoData: {
       LOG_FAIL_NO_STAT()
           << "No inline cache information for call to "
-          << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex());
+          << invoke_instruction->GetMethodReference().PrettyMethod();
       return false;
     }
 
     case kInlineCacheUninitialized: {
       LOG_FAIL_NO_STAT()
           << "Interface or virtual call to "
-          << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex())
+          << invoke_instruction->GetMethodReference().PrettyMethod()
           << " is not hit and not inlined";
       return false;
     }
@@ -630,21 +581,21 @@
     case kInlineCacheMonomorphic: {
       MaybeRecordStat(stats_, MethodCompilationStat::kMonomorphicCall);
       if (UseOnlyPolymorphicInliningWithNoDeopt()) {
-        return TryInlinePolymorphicCall(invoke_instruction, resolved_method, inline_cache);
+        return TryInlinePolymorphicCall(invoke_instruction, classes);
       } else {
-        return TryInlineMonomorphicCall(invoke_instruction, resolved_method, inline_cache);
+        return TryInlineMonomorphicCall(invoke_instruction, classes);
       }
     }
 
     case kInlineCachePolymorphic: {
       MaybeRecordStat(stats_, MethodCompilationStat::kPolymorphicCall);
-      return TryInlinePolymorphicCall(invoke_instruction, resolved_method, inline_cache);
+      return TryInlinePolymorphicCall(invoke_instruction, classes);
     }
 
     case kInlineCacheMegamorphic: {
       LOG_FAIL_NO_STAT()
           << "Interface or virtual call to "
-          << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex())
+          << invoke_instruction->GetMethodReference().PrettyMethod()
           << " is megamorphic and not inlined";
       MaybeRecordStat(stats_, MethodCompilationStat::kMegamorphicCall);
       return false;
@@ -653,7 +604,7 @@
     case kInlineCacheMissingTypes: {
       LOG_FAIL_NO_STAT()
           << "Interface or virtual call to "
-          << caller_dex_file.PrettyMethod(invoke_instruction->GetDexMethodIndex())
+          << invoke_instruction->GetMethodReference().PrettyMethod()
           << " is missing types and not inlined";
       return false;
     }
@@ -663,133 +614,78 @@
 
 HInliner::InlineCacheType HInliner::GetInlineCacheJIT(
     HInvoke* invoke_instruction,
-    StackHandleScope<1>* hs,
-    /*out*/Handle<mirror::ObjectArray<mirror::Class>>* inline_cache)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  DCHECK(Runtime::Current()->UseJitCompilation());
+    /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes) {
+  DCHECK(codegen_->GetCompilerOptions().IsJitCompiler());
 
   ArtMethod* caller = graph_->GetArtMethod();
   // Under JIT, we should always know the caller.
   DCHECK(caller != nullptr);
-  ScopedProfilingInfoInlineUse spiis(caller, Thread::Current());
-  ProfilingInfo* profiling_info = spiis.GetProfilingInfo();
+  ScopedProfilingInfoUse spiu(Runtime::Current()->GetJit(), caller, Thread::Current());
+  ProfilingInfo* profiling_info = spiu.GetProfilingInfo();
 
   if (profiling_info == nullptr) {
     return kInlineCacheNoData;
   }
 
-  *inline_cache = AllocateInlineCacheHolder(caller_compilation_unit_, hs);
-  if (inline_cache->Get() == nullptr) {
-    // We can't extract any data if we failed to allocate;
-    return kInlineCacheNoData;
-  } else {
-    Runtime::Current()->GetJit()->GetCodeCache()->CopyInlineCacheInto(
-        *profiling_info->GetInlineCache(invoke_instruction->GetDexPc()),
-        *inline_cache);
-    return GetInlineCacheType(*inline_cache);
-  }
+  Runtime::Current()->GetJit()->GetCodeCache()->CopyInlineCacheInto(
+      *profiling_info->GetInlineCache(invoke_instruction->GetDexPc()),
+      classes);
+  return GetInlineCacheType(*classes);
 }
 
 HInliner::InlineCacheType HInliner::GetInlineCacheAOT(
-    const DexFile& caller_dex_file,
     HInvoke* invoke_instruction,
-    StackHandleScope<1>* hs,
-    /*out*/Handle<mirror::ObjectArray<mirror::Class>>* inline_cache)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
+    /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes) {
+  DCHECK_EQ(classes->NumberOfReferences(), InlineCache::kIndividualCacheSize);
+  DCHECK_EQ(classes->RemainingSlots(), InlineCache::kIndividualCacheSize);
+
   const ProfileCompilationInfo* pci = codegen_->GetCompilerOptions().GetProfileCompilationInfo();
   if (pci == nullptr) {
     return kInlineCacheNoData;
   }
 
-  std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> offline_profile =
-      pci->GetHotMethodInfo(MethodReference(
-          &caller_dex_file, caller_compilation_unit_.GetDexMethodIndex()));
-  if (offline_profile == nullptr) {
+  ProfileCompilationInfo::MethodHotness hotness = pci->GetMethodHotness(MethodReference(
+      caller_compilation_unit_.GetDexFile(), caller_compilation_unit_.GetDexMethodIndex()));
+  if (!hotness.IsHot()) {
     return kInlineCacheNoData;  // no profile information for this invocation.
   }
 
-  *inline_cache = AllocateInlineCacheHolder(caller_compilation_unit_, hs);
-  if (inline_cache == nullptr) {
-    // We can't extract any data if we failed to allocate;
-    return kInlineCacheNoData;
-  } else {
-    return ExtractClassesFromOfflineProfile(invoke_instruction,
-                                            *(offline_profile.get()),
-                                            *inline_cache);
-  }
-}
-
-HInliner::InlineCacheType HInliner::ExtractClassesFromOfflineProfile(
-    const HInvoke* invoke_instruction,
-    const ProfileCompilationInfo::OfflineProfileMethodInfo& offline_profile,
-    /*out*/Handle<mirror::ObjectArray<mirror::Class>> inline_cache)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  const auto it = offline_profile.inline_caches->find(invoke_instruction->GetDexPc());
-  if (it == offline_profile.inline_caches->end()) {
+  const ProfileCompilationInfo::InlineCacheMap* inline_caches = hotness.GetInlineCacheMap();
+  DCHECK(inline_caches != nullptr);
+  const auto it = inline_caches->find(invoke_instruction->GetDexPc());
+  if (it == inline_caches->end()) {
     return kInlineCacheUninitialized;
   }
 
   const ProfileCompilationInfo::DexPcData& dex_pc_data = it->second;
-
   if (dex_pc_data.is_missing_types) {
     return kInlineCacheMissingTypes;
   }
   if (dex_pc_data.is_megamorphic) {
     return kInlineCacheMegamorphic;
   }
-
   DCHECK_LE(dex_pc_data.classes.size(), InlineCache::kIndividualCacheSize);
-  Thread* self = Thread::Current();
-  // We need to resolve the class relative to the containing dex file.
-  // So first, build a mapping from the index of dex file in the profile to
-  // its dex cache. This will avoid repeating the lookup when walking over
-  // the inline cache types.
-  std::vector<ObjPtr<mirror::DexCache>> dex_profile_index_to_dex_cache(
-        offline_profile.dex_references.size());
-  for (size_t i = 0; i < offline_profile.dex_references.size(); i++) {
-    bool found = false;
-    for (const DexFile* dex_file : codegen_->GetCompilerOptions().GetDexFilesForOatFile()) {
-      if (offline_profile.dex_references[i].MatchesDex(dex_file)) {
-        dex_profile_index_to_dex_cache[i] =
-            caller_compilation_unit_.GetClassLinker()->FindDexCache(self, *dex_file);
-        found = true;
-      }
-    }
-    if (!found) {
-      VLOG(compiler) << "Could not find profiled dex file: " << offline_profile.dex_references[i];
+
+  // Walk over the class descriptors and look up the actual classes.
+  // If we cannot find a type we return kInlineCacheMissingTypes.
+  ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
+  for (const dex::TypeIndex& type_index : dex_pc_data.classes) {
+    const DexFile* dex_file = caller_compilation_unit_.GetDexFile();
+    const char* descriptor = pci->GetTypeDescriptor(dex_file, type_index);
+    ObjPtr<mirror::ClassLoader> class_loader = caller_compilation_unit_.GetClassLoader().Get();
+    ObjPtr<mirror::Class> clazz = class_linker->LookupResolvedType(descriptor, class_loader);
+    if (clazz == nullptr) {
+      VLOG(compiler) << "Could not find class from inline cache in AOT mode "
+          << invoke_instruction->GetMethodReference().PrettyMethod()
+          << " : "
+          << descriptor;
       return kInlineCacheMissingTypes;
     }
+    DCHECK_NE(classes->RemainingSlots(), 0u);
+    classes->NewHandle(clazz);
   }
 
-  // Walk over the classes and resolve them. If we cannot find a type we return
-  // kInlineCacheMissingTypes.
-  int ic_index = 0;
-  for (const ProfileCompilationInfo::ClassReference& class_ref : dex_pc_data.classes) {
-    ObjPtr<mirror::DexCache> dex_cache =
-        dex_profile_index_to_dex_cache[class_ref.dex_profile_index];
-    DCHECK(dex_cache != nullptr);
-
-    if (!dex_cache->GetDexFile()->IsTypeIndexValid(class_ref.type_index)) {
-      VLOG(compiler) << "Profile data corrupt: type index " << class_ref.type_index
-            << "is invalid in location" << dex_cache->GetDexFile()->GetLocation();
-      return kInlineCacheNoData;
-    }
-    ObjPtr<mirror::Class> clazz = caller_compilation_unit_.GetClassLinker()->LookupResolvedType(
-          class_ref.type_index,
-          dex_cache,
-          caller_compilation_unit_.GetClassLoader().Get());
-    if (clazz != nullptr) {
-      inline_cache->Set(ic_index++, clazz);
-    } else {
-      VLOG(compiler) << "Could not resolve class from inline cache in AOT mode "
-          << caller_compilation_unit_.GetDexFile()->PrettyMethod(
-              invoke_instruction->GetDexMethodIndex()) << " : "
-          << caller_compilation_unit_
-              .GetDexFile()->StringByTypeIdx(class_ref.type_index);
-      return kInlineCacheMissingTypes;
-    }
-  }
-  return GetInlineCacheType(inline_cache);
+  return GetInlineCacheType(*classes);
 }
 
 HInstanceFieldGet* HInliner::BuildGetReceiverClass(ClassLinker* class_linker,
@@ -813,10 +709,10 @@
 }
 
 static ArtMethod* ResolveMethodFromInlineCache(Handle<mirror::Class> klass,
-                                               ArtMethod* resolved_method,
-                                               HInstruction* invoke_instruction,
+                                               HInvoke* invoke_instruction,
                                                PointerSize pointer_size)
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  ArtMethod* resolved_method = invoke_instruction->GetResolvedMethod();
   if (Runtime::Current()->IsAotCompiler()) {
     // We can get unrelated types when working with profiles (corruption,
     // systme updates, or anyone can write to it). So first check if the class
@@ -834,13 +730,17 @@
     DCHECK(invoke_instruction->IsInvokeVirtual());
     resolved_method = klass->FindVirtualMethodForVirtual(resolved_method, pointer_size);
   }
-  DCHECK(resolved_method != nullptr);
+  // Even if the class exists we can still not have the function the
+  // inline-cache targets if the profile is from far enough in the past/future.
+  // We need to allow this since we don't update boot-profiles very often. This
+  // can occur in boot-profiles with inline-caches.
+  DCHECK(Runtime::Current()->IsAotCompiler() || resolved_method != nullptr);
   return resolved_method;
 }
 
-bool HInliner::TryInlineMonomorphicCall(HInvoke* invoke_instruction,
-                                        ArtMethod* resolved_method,
-                                        Handle<mirror::ObjectArray<mirror::Class>> classes) {
+bool HInliner::TryInlineMonomorphicCall(
+    HInvoke* invoke_instruction,
+    const StackHandleScope<InlineCache::kIndividualCacheSize>& classes) {
   DCHECK(invoke_instruction->IsInvokeVirtual() || invoke_instruction->IsInvokeInterface())
       << invoke_instruction->DebugName();
 
@@ -848,7 +748,7 @@
       GetMonomorphicType(classes), caller_compilation_unit_);
   if (!class_index.IsValid()) {
     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedDexCache)
-        << "Call to " << ArtMethod::PrettyMethod(resolved_method)
+        << "Call to " << ArtMethod::PrettyMethod(invoke_instruction->GetResolvedMethod())
         << " from inline cache is not inlined because its class is not"
         << " accessible to the caller";
     return false;
@@ -856,25 +756,24 @@
 
   ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
   PointerSize pointer_size = class_linker->GetImagePointerSize();
-  Handle<mirror::Class> monomorphic_type = handles_->NewHandle(GetMonomorphicType(classes));
-  resolved_method = ResolveMethodFromInlineCache(
-      monomorphic_type, resolved_method, invoke_instruction, pointer_size);
-
-  LOG_NOTE() << "Try inline monomorphic call to " << resolved_method->PrettyMethod();
+  Handle<mirror::Class> monomorphic_type =
+      graph_->GetHandleCache()->NewHandle(GetMonomorphicType(classes));
+  ArtMethod* resolved_method = ResolveMethodFromInlineCache(
+      monomorphic_type, invoke_instruction, pointer_size);
   if (resolved_method == nullptr) {
     // Bogus AOT profile, bail.
     DCHECK(Runtime::Current()->IsAotCompiler());
     return false;
   }
 
+  LOG_NOTE() << "Try inline monomorphic call to " << resolved_method->PrettyMethod();
   HInstruction* receiver = invoke_instruction->InputAt(0);
   HInstruction* cursor = invoke_instruction->GetPrevious();
   HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
   if (!TryInlineAndReplace(invoke_instruction,
                            resolved_method,
                            ReferenceTypeInfo::Create(monomorphic_type, /* is_exact= */ true),
-                           /* do_rtp= */ false,
-                           /* cha_devirtualize= */ false)) {
+                           /* do_rtp= */ false)) {
     return false;
   }
 
@@ -892,7 +791,6 @@
   ReferenceTypePropagation rtp_fixup(graph_,
                                      outer_compilation_unit_.GetClassLoader(),
                                      outer_compilation_unit_.GetDexCache(),
-                                     handles_,
                                      /* is_first_run= */ false);
   rtp_fixup.Run();
 
@@ -999,13 +897,21 @@
   return compare;
 }
 
-bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction,
-                                        ArtMethod* resolved_method,
-                                        Handle<mirror::ObjectArray<mirror::Class>> classes) {
+static void MaybeReplaceAndRemove(HInstruction* new_instruction, HInstruction* old_instruction) {
+  DCHECK(new_instruction != old_instruction);
+  if (new_instruction != nullptr) {
+    old_instruction->ReplaceWith(new_instruction);
+  }
+  old_instruction->GetBlock()->RemoveInstruction(old_instruction);
+}
+
+bool HInliner::TryInlinePolymorphicCall(
+    HInvoke* invoke_instruction,
+    const StackHandleScope<InlineCache::kIndividualCacheSize>& classes) {
   DCHECK(invoke_instruction->IsInvokeVirtual() || invoke_instruction->IsInvokeInterface())
       << invoke_instruction->DebugName();
 
-  if (TryInlinePolymorphicCallToSameTarget(invoke_instruction, resolved_method, classes)) {
+  if (TryInlinePolymorphicCallToSameTarget(invoke_instruction, classes)) {
     return true;
   }
 
@@ -1014,15 +920,13 @@
 
   bool all_targets_inlined = true;
   bool one_target_inlined = false;
-  for (size_t i = 0; i < InlineCache::kIndividualCacheSize; ++i) {
-    if (classes->Get(i) == nullptr) {
-      break;
-    }
-    ArtMethod* method = nullptr;
-
-    Handle<mirror::Class> handle = handles_->NewHandle(classes->Get(i));
-    method = ResolveMethodFromInlineCache(
-        handle, resolved_method, invoke_instruction, pointer_size);
+  DCHECK_EQ(classes.NumberOfReferences(), InlineCache::kIndividualCacheSize);
+  uint8_t number_of_types = InlineCache::kIndividualCacheSize - classes.RemainingSlots();
+  for (size_t i = 0; i != number_of_types; ++i) {
+    DCHECK(classes.GetReference(i) != nullptr);
+    Handle<mirror::Class> handle =
+        graph_->GetHandleCache()->NewHandle(classes.GetReference(i)->AsClass());
+    ArtMethod* method = ResolveMethodFromInlineCache(handle, invoke_instruction, pointer_size);
     if (method == nullptr) {
       DCHECK(Runtime::Current()->IsAotCompiler());
       // AOT profile is bogus. This loop expects to iterate over all entries,
@@ -1047,15 +951,15 @@
     } else {
       one_target_inlined = true;
 
-      LOG_SUCCESS() << "Polymorphic call to " << ArtMethod::PrettyMethod(resolved_method)
+      LOG_SUCCESS() << "Polymorphic call to "
+                    << invoke_instruction->GetMethodReference().PrettyMethod()
                     << " has inlined " << ArtMethod::PrettyMethod(method);
 
       // If we have inlined all targets before, and this receiver is the last seen,
       // we deoptimize instead of keeping the original invoke instruction.
       bool deoptimize = !UseOnlyPolymorphicInliningWithNoDeopt() &&
           all_targets_inlined &&
-          (i != InlineCache::kIndividualCacheSize - 1) &&
-          (classes->Get(i + 1) == nullptr);
+          (i + 1 == number_of_types);
 
       HInstruction* compare = AddTypeGuard(receiver,
                                            cursor,
@@ -1065,13 +969,7 @@
                                            invoke_instruction,
                                            deoptimize);
       if (deoptimize) {
-        if (return_replacement != nullptr) {
-          invoke_instruction->ReplaceWith(return_replacement);
-        }
-        invoke_instruction->GetBlock()->RemoveInstruction(invoke_instruction);
-        // Because the inline cache data can be populated concurrently, we force the end of the
-        // iteration. Otherwise, we could see a new receiver type.
-        break;
+        MaybeReplaceAndRemove(return_replacement, invoke_instruction);
       } else {
         CreateDiamondPatternForPolymorphicInline(compare, return_replacement, invoke_instruction);
       }
@@ -1080,7 +978,7 @@
 
   if (!one_target_inlined) {
     LOG_FAIL_NO_STAT()
-        << "Call to " << ArtMethod::PrettyMethod(resolved_method)
+        << "Call to " << invoke_instruction->GetMethodReference().PrettyMethod()
         << " from inline cache is not inlined because none"
         << " of its targets could be inlined";
     return false;
@@ -1092,7 +990,6 @@
   ReferenceTypePropagation rtp_fixup(graph_,
                                      outer_compilation_unit_.GetClassLoader(),
                                      outer_compilation_unit_.GetDexCache(),
-                                     handles_,
                                      /* is_first_run= */ false);
   rtp_fixup.Run();
   return true;
@@ -1176,17 +1073,15 @@
 
 bool HInliner::TryInlinePolymorphicCallToSameTarget(
     HInvoke* invoke_instruction,
-    ArtMethod* resolved_method,
-    Handle<mirror::ObjectArray<mirror::Class>> classes) {
+    const StackHandleScope<InlineCache::kIndividualCacheSize>& classes) {
   // This optimization only works under JIT for now.
-  if (!Runtime::Current()->UseJitCompilation()) {
+  if (!codegen_->GetCompilerOptions().IsJitCompiler()) {
     return false;
   }
 
   ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
   PointerSize pointer_size = class_linker->GetImagePointerSize();
 
-  DCHECK(resolved_method != nullptr);
   ArtMethod* actual_method = nullptr;
   size_t method_index = invoke_instruction->IsInvokeVirtual()
       ? invoke_instruction->AsInvokeVirtual()->GetVTableIndex()
@@ -1194,13 +1089,13 @@
 
   // Check whether we are actually calling the same method among
   // the different types seen.
-  for (size_t i = 0; i < InlineCache::kIndividualCacheSize; ++i) {
-    if (classes->Get(i) == nullptr) {
-      break;
-    }
+  DCHECK_EQ(classes.NumberOfReferences(), InlineCache::kIndividualCacheSize);
+  uint8_t number_of_types = InlineCache::kIndividualCacheSize - classes.RemainingSlots();
+  for (size_t i = 0; i != number_of_types; ++i) {
+    DCHECK(classes.GetReference(i) != nullptr);
     ArtMethod* new_method = nullptr;
     if (invoke_instruction->IsInvokeInterface()) {
-      new_method = classes->Get(i)->GetImt(pointer_size)->Get(
+      new_method = classes.GetReference(i)->AsClass()->GetImt(pointer_size)->Get(
           method_index, pointer_size);
       if (new_method->IsRuntimeMethod()) {
         // Bail out as soon as we see a conflict trampoline in one of the target's
@@ -1209,7 +1104,8 @@
       }
     } else {
       DCHECK(invoke_instruction->IsInvokeVirtual());
-      new_method = classes->Get(i)->GetEmbeddedVTableEntry(method_index, pointer_size);
+      new_method =
+          classes.GetReference(i)->AsClass()->GetEmbeddedVTableEntry(method_index, pointer_size);
     }
     DCHECK(new_method != nullptr);
     if (actual_method == nullptr) {
@@ -1276,11 +1172,8 @@
         invoke_instruction->GetDexPc());
     bb_cursor->InsertInstructionAfter(deoptimize, compare);
     deoptimize->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
-    if (return_replacement != nullptr) {
-      invoke_instruction->ReplaceWith(return_replacement);
-    }
+    MaybeReplaceAndRemove(return_replacement, invoke_instruction);
     receiver->ReplaceUsesDominatedBy(deoptimize, deoptimize);
-    invoke_instruction->GetBlock()->RemoveInstruction(invoke_instruction);
     deoptimize->SetReferenceTypeInfo(receiver->GetReferenceTypeInfo());
   }
 
@@ -1288,7 +1181,6 @@
   ReferenceTypePropagation rtp_fixup(graph_,
                                      outer_compilation_unit_.GetClassLoader(),
                                      outer_compilation_unit_.GetDexCache(),
-                                     handles_,
                                      /* is_first_run= */ false);
   rtp_fixup.Run();
 
@@ -1298,123 +1190,109 @@
   return true;
 }
 
-bool HInliner::TryInlineAndReplace(HInvoke* invoke_instruction,
-                                   ArtMethod* method,
-                                   ReferenceTypeInfo receiver_type,
-                                   bool do_rtp,
-                                   bool cha_devirtualize) {
-  DCHECK(!invoke_instruction->IsIntrinsic());
-  HInstruction* return_replacement = nullptr;
-  uint32_t dex_pc = invoke_instruction->GetDexPc();
-  HInstruction* cursor = invoke_instruction->GetPrevious();
-  HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
-  bool should_remove_invoke_instruction = false;
-
-  // If invoke_instruction is devirtualized to a different method, give intrinsics
-  // another chance before we try to inline it.
-  if (invoke_instruction->GetResolvedMethod() != method && method->IsIntrinsic()) {
-    MaybeRecordStat(stats_, MethodCompilationStat::kIntrinsicRecognized);
-    if (invoke_instruction->IsInvokeInterface()) {
-      // We don't intrinsify an invoke-interface directly.
-      // Replace the invoke-interface with an invoke-virtual.
-      HInvokeVirtual* new_invoke = new (graph_->GetAllocator()) HInvokeVirtual(
-          graph_->GetAllocator(),
-          invoke_instruction->GetNumberOfArguments(),
-          invoke_instruction->GetType(),
-          invoke_instruction->GetDexPc(),
-          invoke_instruction->GetDexMethodIndex(),  // Use interface method's dex method index.
-          method,
-          method->GetMethodIndex());
-      DCHECK_NE(new_invoke->GetIntrinsic(), Intrinsics::kNone);
-      HInputsRef inputs = invoke_instruction->GetInputs();
-      for (size_t index = 0; index != inputs.size(); ++index) {
-        new_invoke->SetArgumentAt(index, inputs[index]);
-      }
-      invoke_instruction->GetBlock()->InsertInstructionBefore(new_invoke, invoke_instruction);
-      new_invoke->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
-      if (invoke_instruction->GetType() == DataType::Type::kReference) {
-        new_invoke->SetReferenceTypeInfo(invoke_instruction->GetReferenceTypeInfo());
-      }
-      return_replacement = new_invoke;
-      // invoke_instruction is replaced with new_invoke.
-      should_remove_invoke_instruction = true;
-    } else {
-      invoke_instruction->SetResolvedMethod(method);
-    }
-  } else if (!TryBuildAndInline(invoke_instruction, method, receiver_type, &return_replacement)) {
-    if (invoke_instruction->IsInvokeInterface()) {
-      DCHECK(!method->IsProxyMethod());
-      // Turn an invoke-interface into an invoke-virtual. An invoke-virtual is always
-      // better than an invoke-interface because:
-      // 1) In the best case, the interface call has one more indirection (to fetch the IMT).
-      // 2) We will not go to the conflict trampoline with an invoke-virtual.
-      // TODO: Consider sharpening once it is not dependent on the compiler driver.
-
-      if (method->IsDefault() && !method->IsCopied()) {
-        // Changing to invoke-virtual cannot be done on an original default method
-        // since it's not in any vtable. Devirtualization by exact type/inline-cache
-        // always uses a method in the iftable which is never an original default
-        // method.
-        // On the other hand, inlining an original default method by CHA is fine.
-        DCHECK(cha_devirtualize);
-        return false;
-      }
-
-      const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
-      uint32_t dex_method_index = FindMethodIndexIn(
-          method, caller_dex_file, invoke_instruction->GetDexMethodIndex());
-      if (dex_method_index == dex::kDexNoIndex) {
-        return false;
-      }
-      HInvokeVirtual* new_invoke = new (graph_->GetAllocator()) HInvokeVirtual(
-          graph_->GetAllocator(),
-          invoke_instruction->GetNumberOfArguments(),
-          invoke_instruction->GetType(),
-          invoke_instruction->GetDexPc(),
-          dex_method_index,
-          method,
-          method->GetMethodIndex());
-      HInputsRef inputs = invoke_instruction->GetInputs();
-      for (size_t index = 0; index != inputs.size(); ++index) {
-        new_invoke->SetArgumentAt(index, inputs[index]);
-      }
-      invoke_instruction->GetBlock()->InsertInstructionBefore(new_invoke, invoke_instruction);
-      new_invoke->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
-      if (invoke_instruction->GetType() == DataType::Type::kReference) {
-        new_invoke->SetReferenceTypeInfo(invoke_instruction->GetReferenceTypeInfo());
-      }
-      return_replacement = new_invoke;
-      // invoke_instruction is replaced with new_invoke.
-      should_remove_invoke_instruction = true;
-    } else {
-      // TODO: Consider sharpening an invoke virtual once it is not dependent on the
-      // compiler driver.
-      return false;
-    }
-  } else {
-    // invoke_instruction is inlined.
-    should_remove_invoke_instruction = true;
-  }
-
-  if (cha_devirtualize) {
-    AddCHAGuard(invoke_instruction, dex_pc, cursor, bb_cursor);
-  }
-  if (return_replacement != nullptr) {
-    invoke_instruction->ReplaceWith(return_replacement);
-  }
-  if (should_remove_invoke_instruction) {
-    invoke_instruction->GetBlock()->RemoveInstruction(invoke_instruction);
-  }
-  FixUpReturnReferenceType(method, return_replacement);
-  if (do_rtp && ReturnTypeMoreSpecific(invoke_instruction, return_replacement)) {
+void HInliner::MaybeRunReferenceTypePropagation(HInstruction* replacement,
+                                                HInvoke* invoke_instruction) {
+  if (ReturnTypeMoreSpecific(replacement, invoke_instruction)) {
     // Actual return value has a more specific type than the method's declared
     // return type. Run RTP again on the outer graph to propagate it.
     ReferenceTypePropagation(graph_,
                              outer_compilation_unit_.GetClassLoader(),
                              outer_compilation_unit_.GetDexCache(),
-                             handles_,
                              /* is_first_run= */ false).Run();
   }
+}
+
+bool HInliner::TryDevirtualize(HInvoke* invoke_instruction,
+                               ArtMethod* method,
+                               HInvoke** replacement) {
+  DCHECK(invoke_instruction != *replacement);
+  if (!invoke_instruction->IsInvokeInterface() && !invoke_instruction->IsInvokeVirtual()) {
+    return false;
+  }
+
+  // Don't bother trying to call directly a default conflict method. It
+  // doesn't have a proper MethodReference, but also `GetCanonicalMethod`
+  // will return an actual default implementation.
+  if (method->IsDefaultConflicting()) {
+    return false;
+  }
+  DCHECK(!method->IsProxyMethod());
+  ClassLinker* cl = Runtime::Current()->GetClassLinker();
+  PointerSize pointer_size = cl->GetImagePointerSize();
+  // The sharpening logic assumes the caller isn't passing a copied method.
+  method = method->GetCanonicalMethod(pointer_size);
+  uint32_t dex_method_index = FindMethodIndexIn(
+      method,
+      *invoke_instruction->GetMethodReference().dex_file,
+      invoke_instruction->GetMethodReference().index);
+  if (dex_method_index == dex::kDexNoIndex) {
+    return false;
+  }
+  HInvokeStaticOrDirect::DispatchInfo dispatch_info =
+      HSharpening::SharpenLoadMethod(method,
+                                     /* has_method_id= */ true,
+                                     /* for_interface_call= */ false,
+                                     codegen_);
+  DCHECK_NE(dispatch_info.code_ptr_location, CodePtrLocation::kCallCriticalNative);
+  if (dispatch_info.method_load_kind == MethodLoadKind::kRuntimeCall) {
+    // If sharpening returns that we need to load the method at runtime, keep
+    // the virtual/interface call which will be faster.
+    // Also, the entrypoints for runtime calls do not handle devirtualized
+    // calls.
+    return false;
+  }
+
+  HInvokeStaticOrDirect* new_invoke = new (graph_->GetAllocator()) HInvokeStaticOrDirect(
+      graph_->GetAllocator(),
+      invoke_instruction->GetNumberOfArguments(),
+      invoke_instruction->GetType(),
+      invoke_instruction->GetDexPc(),
+      MethodReference(invoke_instruction->GetMethodReference().dex_file, dex_method_index),
+      method,
+      dispatch_info,
+      kDirect,
+      MethodReference(method->GetDexFile(), method->GetDexMethodIndex()),
+      HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInputsRef inputs = invoke_instruction->GetInputs();
+  DCHECK_EQ(inputs.size(), invoke_instruction->GetNumberOfArguments());
+  for (size_t index = 0; index != inputs.size(); ++index) {
+    new_invoke->SetArgumentAt(index, inputs[index]);
+  }
+  if (HInvokeStaticOrDirect::NeedsCurrentMethodInput(dispatch_info)) {
+    new_invoke->SetRawInputAt(new_invoke->GetCurrentMethodIndexUnchecked(),
+                              graph_->GetCurrentMethod());
+  }
+  invoke_instruction->GetBlock()->InsertInstructionBefore(new_invoke, invoke_instruction);
+  new_invoke->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
+  if (invoke_instruction->GetType() == DataType::Type::kReference) {
+    new_invoke->SetReferenceTypeInfo(invoke_instruction->GetReferenceTypeInfo());
+  }
+  *replacement = new_invoke;
+
+  MaybeReplaceAndRemove(*replacement, invoke_instruction);
+  // No need to call MaybeRunReferenceTypePropagation, as we know the return type
+  // cannot be more specific.
+  DCHECK(!ReturnTypeMoreSpecific(*replacement, invoke_instruction));
+  return true;
+}
+
+
+bool HInliner::TryInlineAndReplace(HInvoke* invoke_instruction,
+                                   ArtMethod* method,
+                                   ReferenceTypeInfo receiver_type,
+                                   bool do_rtp) {
+  DCHECK(!invoke_instruction->IsIntrinsic());
+  HInstruction* return_replacement = nullptr;
+
+  if (!TryBuildAndInline(invoke_instruction, method, receiver_type, &return_replacement)) {
+    return false;
+  }
+
+  MaybeReplaceAndRemove(return_replacement, invoke_instruction);
+  FixUpReturnReferenceType(method, return_replacement);
+  if (do_rtp) {
+    MaybeRunReferenceTypePropagation(return_replacement, invoke_instruction);
+  }
   return true;
 }
 
@@ -1531,6 +1409,35 @@
                                  ArtMethod* method,
                                  ReferenceTypeInfo receiver_type,
                                  HInstruction** return_replacement) {
+  // If invoke_instruction is devirtualized to a different method, give intrinsics
+  // another chance before we try to inline it.
+  if (invoke_instruction->GetResolvedMethod() != method && method->IsIntrinsic()) {
+    MaybeRecordStat(stats_, MethodCompilationStat::kIntrinsicRecognized);
+    // For simplicity, always create a new instruction to replace the existing
+    // invoke.
+    HInvokeVirtual* new_invoke = new (graph_->GetAllocator()) HInvokeVirtual(
+        graph_->GetAllocator(),
+        invoke_instruction->GetNumberOfArguments(),
+        invoke_instruction->GetType(),
+        invoke_instruction->GetDexPc(),
+        invoke_instruction->GetMethodReference(),  // Use existing invoke's method's reference.
+        method,
+        MethodReference(method->GetDexFile(), method->GetDexMethodIndex()),
+        method->GetMethodIndex());
+    DCHECK_NE(new_invoke->GetIntrinsic(), Intrinsics::kNone);
+    HInputsRef inputs = invoke_instruction->GetInputs();
+    for (size_t index = 0; index != inputs.size(); ++index) {
+      new_invoke->SetArgumentAt(index, inputs[index]);
+    }
+    invoke_instruction->GetBlock()->InsertInstructionBefore(new_invoke, invoke_instruction);
+    new_invoke->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
+    if (invoke_instruction->GetType() == DataType::Type::kReference) {
+      new_invoke->SetReferenceTypeInfo(invoke_instruction->GetReferenceTypeInfo());
+    }
+    *return_replacement = new_invoke;
+    return true;
+  }
+
   // Check whether we're allowed to inline. The outermost compilation unit is the relevant
   // dex file here (though the transitivity of an inline chain would allow checking the caller).
   if (!MayInline(codegen_->GetCompilerOptions(),
@@ -1591,10 +1498,10 @@
 
 // Try to recognize known simple patterns and replace invoke call with appropriate instructions.
 bool HInliner::TryPatternSubstitution(HInvoke* invoke_instruction,
-                                      ArtMethod* resolved_method,
+                                      ArtMethod* method,
                                       HInstruction** return_replacement) {
   InlineMethod inline_method;
-  if (!InlineMethodAnalyser::AnalyseMethodCode(resolved_method, &inline_method)) {
+  if (!InlineMethodAnalyser::AnalyseMethodCode(method, &inline_method)) {
     return false;
   }
 
@@ -1608,7 +1515,7 @@
                                                           inline_method.d.return_data.arg);
       break;
     case kInlineOpNonWideConst:
-      if (resolved_method->GetShorty()[0] == 'L') {
+      if (method->GetShorty()[0] == 'L') {
         DCHECK_EQ(inline_method.d.data, 0u);
         *return_replacement = graph_->GetNullConstant();
       } else {
@@ -1622,7 +1529,7 @@
         return false;
       }
       HInstruction* obj = GetInvokeInputForArgVRegIndex(invoke_instruction, data.object_arg);
-      HInstanceFieldGet* iget = CreateInstanceFieldGet(data.field_idx, resolved_method, obj);
+      HInstanceFieldGet* iget = CreateInstanceFieldGet(data.field_idx, method, obj);
       DCHECK_EQ(iget->GetFieldOffset().Uint32Value(), data.field_offset);
       DCHECK_EQ(iget->IsVolatile() ? 1u : 0u, data.is_volatile);
       invoke_instruction->GetBlock()->InsertInstructionBefore(iget, invoke_instruction);
@@ -1637,7 +1544,7 @@
       }
       HInstruction* obj = GetInvokeInputForArgVRegIndex(invoke_instruction, data.object_arg);
       HInstruction* value = GetInvokeInputForArgVRegIndex(invoke_instruction, data.src_arg);
-      HInstanceFieldSet* iput = CreateInstanceFieldSet(data.field_idx, resolved_method, obj, value);
+      HInstanceFieldSet* iput = CreateInstanceFieldSet(data.field_idx, method, obj, value);
       DCHECK_EQ(iput->GetFieldOffset().Uint32Value(), data.field_offset);
       DCHECK_EQ(iput->IsVolatile() ? 1u : 0u, data.is_volatile);
       invoke_instruction->GetBlock()->InsertInstructionBefore(iput, invoke_instruction);
@@ -1680,7 +1587,7 @@
           uint16_t field_index = iput_field_indexes[i];
           bool is_final;
           HInstanceFieldSet* iput =
-              CreateInstanceFieldSet(field_index, resolved_method, obj, value, &is_final);
+              CreateInstanceFieldSet(field_index, method, obj, value, &is_final);
           invoke_instruction->GetBlock()->InsertInstructionBefore(iput, invoke_instruction);
 
           // Check whether the field is final. If it is, we need to add a barrier.
@@ -1730,11 +1637,11 @@
       /* dex_pc= */ 0);
   if (iget->GetType() == DataType::Type::kReference) {
     // Use the same dex_cache that we used for field lookup as the hint_dex_cache.
-    Handle<mirror::DexCache> dex_cache = handles_->NewHandle(referrer->GetDexCache());
+    Handle<mirror::DexCache> dex_cache =
+        graph_->GetHandleCache()->NewHandle(referrer->GetDexCache());
     ReferenceTypePropagation rtp(graph_,
                                  outer_compilation_unit_.GetClassLoader(),
                                  dex_cache,
-                                 handles_,
                                  /* is_first_run= */ false);
     rtp.Visit(iget);
   }
@@ -1773,11 +1680,9 @@
 }
 
 template <typename T>
-static inline Handle<T> NewHandleIfDifferent(ObjPtr<T> object,
-                                             Handle<T> hint,
-                                             VariableSizedHandleScope* handles)
+static inline Handle<T> NewHandleIfDifferent(ObjPtr<T> object, Handle<T> hint, HGraph* graph)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  return (object != hint.Get()) ? handles->NewHandle(object) : hint;
+  return (object != hint.Get()) ? graph->GetHandleCache()->NewHandle(object) : hint;
 }
 
 static bool CanEncodeInlinedMethodInStackMap(const DexFile& caller_dex_file, ArtMethod* callee)
@@ -1840,7 +1745,6 @@
     ReferenceTypePropagation(callee_graph,
                              outer_compilation_unit_.GetClassLoader(),
                              dex_compilation_unit.GetDexCache(),
-                             handles_,
                              /* is_first_run= */ false).Run();
   }
 }
@@ -1855,16 +1759,12 @@
 bool HInliner::CanInlineBody(const HGraph* callee_graph,
                              const HBasicBlock* target_block,
                              size_t* out_number_of_instructions) const {
-  const DexFile& callee_dex_file = callee_graph->GetDexFile();
   ArtMethod* const resolved_method = callee_graph->GetArtMethod();
-  const uint32_t method_index = resolved_method->GetMethodIndex();
-  const bool same_dex_file =
-      IsSameDexFile(*outer_compilation_unit_.GetDexFile(), *resolved_method->GetDexFile());
 
   HBasicBlock* exit_block = callee_graph->GetExitBlock();
   if (exit_block == nullptr) {
     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedInfiniteLoop)
-        << "Method " << callee_dex_file.PrettyMethod(method_index)
+        << "Method " << resolved_method->PrettyMethod()
         << " could not be inlined because it has an infinite loop";
     return false;
   }
@@ -1875,21 +1775,21 @@
       if (target_block->IsTryBlock()) {
         // TODO(ngeoffray): Support adding HTryBoundary in Hgraph::InlineInto.
         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedTryCatch)
-            << "Method " << callee_dex_file.PrettyMethod(method_index)
+            << "Method " << resolved_method->PrettyMethod()
             << " could not be inlined because one branch always throws and"
             << " caller is in a try/catch block";
         return false;
       } else if (graph_->GetExitBlock() == nullptr) {
         // TODO(ngeoffray): Support adding HExit in the caller graph.
         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedInfiniteLoop)
-            << "Method " << callee_dex_file.PrettyMethod(method_index)
+            << "Method " << resolved_method->PrettyMethod()
             << " could not be inlined because one branch always throws and"
             << " caller does not have an exit block";
         return false;
       } else if (graph_->HasIrreducibleLoops()) {
         // TODO(ngeoffray): Support re-computing loop information to graphs with
         // irreducible loops?
-        VLOG(compiler) << "Method " << callee_dex_file.PrettyMethod(method_index)
+        VLOG(compiler) << "Method " << resolved_method->PrettyMethod()
                        << " could not be inlined because one branch always throws and"
                        << " caller has irreducible loops";
         return false;
@@ -1901,7 +1801,7 @@
 
   if (!has_one_return) {
     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedAlwaysThrows)
-        << "Method " << callee_dex_file.PrettyMethod(method_index)
+        << "Method " << resolved_method->PrettyMethod()
         << " could not be inlined because it always throws";
     return false;
   }
@@ -1914,7 +1814,7 @@
         // Don't inline methods with irreducible loops, they could prevent some
         // optimizations to run.
         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedIrreducibleLoop)
-            << "Method " << callee_dex_file.PrettyMethod(method_index)
+            << "Method " << resolved_method->PrettyMethod()
             << " could not be inlined because it contains an irreducible loop";
         return false;
       }
@@ -1923,7 +1823,7 @@
         // loop information to be computed incorrectly when updating after
         // inlining.
         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedLoopWithoutExit)
-            << "Method " << callee_dex_file.PrettyMethod(method_index)
+            << "Method " << resolved_method->PrettyMethod()
             << " could not be inlined because it contains a loop with no exit";
         return false;
       }
@@ -1932,18 +1832,18 @@
     for (HInstructionIterator instr_it(block->GetInstructions());
          !instr_it.Done();
          instr_it.Advance()) {
-      if (++number_of_instructions >= inlining_budget_) {
+      if (++number_of_instructions > inlining_budget_) {
         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedInstructionBudget)
-            << "Method " << callee_dex_file.PrettyMethod(method_index)
+            << "Method " << resolved_method->PrettyMethod()
             << " is not inlined because the outer method has reached"
             << " its instruction budget limit.";
         return false;
       }
       HInstruction* current = instr_it.Current();
       if (current->NeedsEnvironment() &&
-          (total_number_of_dex_registers_ >= kMaximumNumberOfCumulatedDexRegisters)) {
+          (total_number_of_dex_registers_ > kMaximumNumberOfCumulatedDexRegisters)) {
         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedEnvironmentBudget)
-            << "Method " << callee_dex_file.PrettyMethod(method_index)
+            << "Method " << resolved_method->PrettyMethod()
             << " is not inlined because its caller has reached"
             << " its environment budget limit.";
         return false;
@@ -1953,28 +1853,20 @@
           !CanEncodeInlinedMethodInStackMap(*caller_compilation_unit_.GetDexFile(),
                                             resolved_method)) {
         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedStackMaps)
-            << "Method " << callee_dex_file.PrettyMethod(method_index)
+            << "Method " << resolved_method->PrettyMethod()
             << " could not be inlined because " << current->DebugName()
             << " needs an environment, is in a different dex file"
             << ", and cannot be encoded in the stack maps.";
         return false;
       }
 
-      if (!same_dex_file && current->NeedsDexCacheOfDeclaringClass()) {
-        LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedDexCache)
-            << "Method " << callee_dex_file.PrettyMethod(method_index)
-            << " could not be inlined because " << current->DebugName()
-            << " it is in a different dex file and requires access to the dex cache";
-        return false;
-      }
-
       if (current->IsUnresolvedStaticFieldGet() ||
           current->IsUnresolvedInstanceFieldGet() ||
           current->IsUnresolvedStaticFieldSet() ||
           current->IsUnresolvedInstanceFieldSet()) {
         // Entrypoint for unresolved fields does not handle inlined frames.
         LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedUnresolvedEntrypoint)
-            << "Method " << callee_dex_file.PrettyMethod(method_index)
+            << "Method " << resolved_method->PrettyMethod()
             << " could not be inlined because it is using an unresolved"
             << " entrypoint";
         return false;
@@ -1998,13 +1890,14 @@
   ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
   Handle<mirror::DexCache> dex_cache = NewHandleIfDifferent(resolved_method->GetDexCache(),
                                                             caller_compilation_unit_.GetDexCache(),
-                                                            handles_);
+                                                            graph_);
   Handle<mirror::ClassLoader> class_loader =
       NewHandleIfDifferent(resolved_method->GetDeclaringClass()->GetClassLoader(),
                            caller_compilation_unit_.GetClassLoader(),
-                           handles_);
+                           graph_);
 
-  Handle<mirror::Class> compiling_class = handles_->NewHandle(resolved_method->GetDeclaringClass());
+  Handle<mirror::Class> compiling_class =
+      graph_->GetHandleCache()->NewHandle(resolved_method->GetDeclaringClass());
   DexCompilationUnit dex_compilation_unit(
       class_loader,
       class_linker,
@@ -2036,15 +1929,14 @@
   HGraph* callee_graph = new (graph_->GetAllocator()) HGraph(
       graph_->GetAllocator(),
       graph_->GetArenaStack(),
+      graph_->GetHandleCache()->GetHandles(),
       callee_dex_file,
       method_index,
       codegen_->GetCompilerOptions().GetInstructionSet(),
       invoke_type,
       callee_dead_reference_safe,
       graph_->IsDebuggable(),
-      /* osr= */ false,
-      /* is_shared_jit_code= */ graph_->IsCompilingForSharedJitCode(),
-      /* baseline= */ graph_->IsCompilingBaseline(),
+      graph_->GetCompilationKind(),
       /* start_instruction_id= */ caller_instruction_counter);
   callee_graph->SetArtMethod(resolved_method);
 
@@ -2066,9 +1958,7 @@
                         &dex_compilation_unit,
                         &outer_compilation_unit_,
                         codegen_,
-                        inline_stats_,
-                        resolved_method->GetQuickenedInfo(),
-                        handles_);
+                        inline_stats_);
 
   if (builder.BuildGraph() != kAnalysisSuccess) {
     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedCannotBuild)
@@ -2137,7 +2027,7 @@
 
   // Bail early for pathological cases on the environment (for example recursive calls,
   // or too large environment).
-  if (total_number_of_dex_registers_ >= kMaximumNumberOfCumulatedDexRegisters) {
+  if (total_number_of_dex_registers_ > kMaximumNumberOfCumulatedDexRegisters) {
     LOG_NOTE() << "Calls in " << callee_graph->GetArtMethod()->PrettyMethod()
              << " will not be inlined because the outer method has reached"
              << " its environment budget limit.";
@@ -2159,7 +2049,6 @@
                    codegen_,
                    outer_compilation_unit_,
                    dex_compilation_unit,
-                   handles_,
                    inline_stats_,
                    total_number_of_dex_registers_ + accessor.RegistersSize(),
                    total_number_of_instructions_ + number_of_instructions,
@@ -2168,7 +2057,8 @@
   inliner.Run();
 }
 
-static bool IsReferenceTypeRefinement(ReferenceTypeInfo declared_rti,
+static bool IsReferenceTypeRefinement(ObjPtr<mirror::Class> declared_class,
+                                      bool declared_is_exact,
                                       bool declared_can_be_null,
                                       HInstruction* actual_obj)
     REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -2177,22 +2067,29 @@
   }
 
   ReferenceTypeInfo actual_rti = actual_obj->GetReferenceTypeInfo();
-  return (actual_rti.IsExact() && !declared_rti.IsExact()) ||
-          declared_rti.IsStrictSupertypeOf(actual_rti);
+  ObjPtr<mirror::Class> actual_class = actual_rti.GetTypeHandle().Get();
+  return (actual_rti.IsExact() && !declared_is_exact) ||
+         (declared_class != actual_class && declared_class->IsAssignableFrom(actual_class));
 }
 
-ReferenceTypeInfo HInliner::GetClassRTI(ObjPtr<mirror::Class> klass) {
-  return ReferenceTypePropagation::IsAdmissible(klass)
-      ? ReferenceTypeInfo::Create(handles_->NewHandle(klass))
-      : graph_->GetInexactObjectRti();
+static bool IsReferenceTypeRefinement(ObjPtr<mirror::Class> declared_class,
+                                      bool declared_can_be_null,
+                                      HInstruction* actual_obj)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  bool admissible = ReferenceTypePropagation::IsAdmissible(declared_class);
+  return IsReferenceTypeRefinement(
+      admissible ? declared_class : GetClassRoot<mirror::Class>(),
+      /*declared_is_exact=*/ admissible && declared_class->CannotBeAssignedFromOtherTypes(),
+      declared_can_be_null,
+      actual_obj);
 }
 
 bool HInliner::ArgumentTypesMoreSpecific(HInvoke* invoke_instruction, ArtMethod* resolved_method) {
   // If this is an instance call, test whether the type of the `this` argument
   // is more specific than the class which declares the method.
   if (!resolved_method->IsStatic()) {
-    if (IsReferenceTypeRefinement(GetClassRTI(resolved_method->GetDeclaringClass()),
-                                  /* declared_can_be_null= */ false,
+    if (IsReferenceTypeRefinement(resolved_method->GetDeclaringClass(),
+                                  /*declared_can_be_null=*/ false,
                                   invoke_instruction->InputAt(0u))) {
       return true;
     }
@@ -2211,9 +2108,7 @@
     if (input->GetType() == DataType::Type::kReference) {
       ObjPtr<mirror::Class> param_cls = resolved_method->LookupResolvedClassFromTypeIndex(
           param_list->GetTypeItem(param_idx).type_idx_);
-      if (IsReferenceTypeRefinement(GetClassRTI(param_cls),
-                                    /* declared_can_be_null= */ true,
-                                    input)) {
+      if (IsReferenceTypeRefinement(param_cls, /*declared_can_be_null=*/ true, input)) {
         return true;
       }
     }
@@ -2222,14 +2117,16 @@
   return false;
 }
 
-bool HInliner::ReturnTypeMoreSpecific(HInvoke* invoke_instruction,
-                                      HInstruction* return_replacement) {
+bool HInliner::ReturnTypeMoreSpecific(HInstruction* return_replacement,
+                                      HInvoke* invoke_instruction) {
   // Check the integrity of reference types and run another type propagation if needed.
   if (return_replacement != nullptr) {
     if (return_replacement->GetType() == DataType::Type::kReference) {
       // Test if the return type is a refinement of the declared return type.
-      if (IsReferenceTypeRefinement(invoke_instruction->GetReferenceTypeInfo(),
-                                    /* declared_can_be_null= */ true,
+      ReferenceTypeInfo invoke_rti = invoke_instruction->GetReferenceTypeInfo();
+      if (IsReferenceTypeRefinement(invoke_rti.GetTypeHandle().Get(),
+                                    invoke_rti.IsExact(),
+                                    /*declared_can_be_null=*/ true,
                                     return_replacement)) {
         return true;
       } else if (return_replacement->IsInstanceFieldGet()) {
@@ -2259,7 +2156,10 @@
         // some functionality from the reference type propagation.
         DCHECK(return_replacement->IsPhi());
         ObjPtr<mirror::Class> cls = resolved_method->LookupResolvedReturnType();
-        return_replacement->SetReferenceTypeInfo(GetClassRTI(cls));
+        ReferenceTypeInfo rti = ReferenceTypePropagation::IsAdmissible(cls)
+            ? ReferenceTypeInfo::Create(graph_->GetHandleCache()->NewHandle(cls))
+            : graph_->GetInexactObjectRti();
+        return_replacement->SetReferenceTypeInfo(rti);
       }
     }
   }
diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h
index 882ba4e..e98a66b 100644
--- a/compiler/optimizing/inliner.h
+++ b/compiler/optimizing/inliner.h
@@ -19,6 +19,7 @@
 
 #include "dex/dex_file_types.h"
 #include "dex/invoke_type.h"
+#include "jit/profiling_info.h"
 #include "optimization.h"
 #include "profile/profile_compilation_info.h"
 
@@ -37,7 +38,6 @@
            CodeGenerator* codegen,
            const DexCompilationUnit& outer_compilation_unit,
            const DexCompilationUnit& caller_compilation_unit,
-           VariableSizedHandleScope* handles,
            OptimizingCompilerStats* stats,
            size_t total_number_of_dex_registers,
            size_t total_number_of_instructions,
@@ -54,7 +54,6 @@
         parent_(parent),
         depth_(depth),
         inlining_budget_(0),
-        handles_(handles),
         inline_stats_(nullptr) {}
 
   bool Run() override;
@@ -73,24 +72,13 @@
 
   bool TryInline(HInvoke* invoke_instruction);
 
-  // Attempt to resolve the target of the invoke instruction to an acutal call
-  // target.
-  //
-  // Returns the target directly in the case of static or direct invokes.
-  // Otherwise, uses CHA devirtualization or other methods to try to find the
-  // call target.
-  ArtMethod* FindActualCallTarget(HInvoke* invoke_instruction, bool* cha_devirtualize)
-    REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Try to inline `resolved_method` in place of `invoke_instruction`. `do_rtp` is whether
   // reference type propagation can run after the inlining. If the inlining is successful, this
-  // method will replace and remove the `invoke_instruction`. If `cha_devirtualize` is true,
-  // a CHA guard needs to be added for the inlining.
+  // method will replace and remove the `invoke_instruction`.
   bool TryInlineAndReplace(HInvoke* invoke_instruction,
                            ArtMethod* resolved_method,
                            ReferenceTypeInfo receiver_type,
-                           bool do_rtp,
-                           bool cha_devirtualize)
+                           bool do_rtp)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
   bool TryBuildAndInline(HInvoke* invoke_instruction,
@@ -120,7 +108,7 @@
 
   // Try to recognize known simple patterns and replace invoke call with appropriate instructions.
   bool TryPatternSubstitution(HInvoke* invoke_instruction,
-                              ArtMethod* resolved_method,
+                              ArtMethod* method,
                               HInstruction** return_replacement)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -168,10 +156,18 @@
                                             bool* is_final = nullptr);
 
   // Try inlining the invoke instruction using inline caches.
-  bool TryInlineFromInlineCache(
-      const DexFile& caller_dex_file,
-      HInvoke* invoke_instruction,
-      ArtMethod* resolved_method)
+  bool TryInlineFromInlineCache(HInvoke* invoke_instruction)
+    REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Try inlining the invoke instruction using CHA.
+  bool TryInlineFromCHA(HInvoke* invoke_instruction)
+    REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // When we fail inlining `invoke_instruction`, we will try to devirtualize the
+  // call.
+  bool TryDevirtualize(HInvoke* invoke_instruction,
+                       ArtMethod* method,
+                       HInvoke** replacement)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Try getting the inline cache from JIT code cache.
@@ -179,31 +175,20 @@
   // invoke info was found in the profile info.
   InlineCacheType GetInlineCacheJIT(
       HInvoke* invoke_instruction,
-      StackHandleScope<1>* hs,
-      /*out*/Handle<mirror::ObjectArray<mirror::Class>>* inline_cache)
+      /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Try getting the inline cache from AOT offline profile.
   // Return true if the inline cache was successfully allocated and the
   // invoke info was found in the profile info.
-  InlineCacheType GetInlineCacheAOT(const DexFile& caller_dex_file,
+  InlineCacheType GetInlineCacheAOT(
       HInvoke* invoke_instruction,
-      StackHandleScope<1>* hs,
-      /*out*/Handle<mirror::ObjectArray<mirror::Class>>* inline_cache)
-    REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Extract the mirror classes from the offline profile and add them to the `inline_cache`.
-  // Note that even if we have profile data for the invoke the inline_cache might contain
-  // only null entries if the types cannot be resolved.
-  InlineCacheType ExtractClassesFromOfflineProfile(
-      const HInvoke* invoke_instruction,
-      const ProfileCompilationInfo::OfflineProfileMethodInfo& offline_profile,
-      /*out*/Handle<mirror::ObjectArray<mirror::Class>> inline_cache)
+      /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Compute the inline cache type.
-  InlineCacheType GetInlineCacheType(
-      const Handle<mirror::ObjectArray<mirror::Class>>& classes)
+  static InlineCacheType GetInlineCacheType(
+      const StackHandleScope<InlineCache::kIndividualCacheSize>& classes)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Try to inline the target of a monomorphic call. If successful, the code
@@ -211,19 +196,17 @@
   // if (receiver.getClass() != ic.GetMonomorphicType()) deopt
   // ... // inlined code
   bool TryInlineMonomorphicCall(HInvoke* invoke_instruction,
-                                ArtMethod* resolved_method,
-                                Handle<mirror::ObjectArray<mirror::Class>> classes)
+                                const StackHandleScope<InlineCache::kIndividualCacheSize>& classes)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Try to inline targets of a polymorphic call.
   bool TryInlinePolymorphicCall(HInvoke* invoke_instruction,
-                                ArtMethod* resolved_method,
-                                Handle<mirror::ObjectArray<mirror::Class>> classes)
+                                const StackHandleScope<InlineCache::kIndividualCacheSize>& classes)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-  bool TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction,
-                                            ArtMethod* resolved_method,
-                                            Handle<mirror::ObjectArray<mirror::Class>> classes)
+  bool TryInlinePolymorphicCallToSameTarget(
+      HInvoke* invoke_instruction,
+      const StackHandleScope<InlineCache::kIndividualCacheSize>& classes)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Returns whether or not we should use only polymorphic inlining with no deoptimizations.
@@ -232,7 +215,7 @@
   // Try CHA-based devirtualization to change virtual method calls into
   // direct calls.
   // Returns the actual method that resolved_method can be devirtualized to.
-  ArtMethod* TryCHADevirtualization(ArtMethod* resolved_method)
+  ArtMethod* FindMethodFromCHA(ArtMethod* resolved_method)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Add a CHA guard for a CHA-based devirtualized call. A CHA guard checks a
@@ -247,18 +230,17 @@
                                            uint32_t dex_pc) const
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void FixUpReturnReferenceType(ArtMethod* resolved_method, HInstruction* return_replacement)
+  void MaybeRunReferenceTypePropagation(HInstruction* replacement,
+                                        HInvoke* invoke_instruction)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Creates an instance of ReferenceTypeInfo from `klass` if `klass` is
-  // admissible (see ReferenceTypePropagation::IsAdmissible for details).
-  // Otherwise returns inexact Object RTI.
-  ReferenceTypeInfo GetClassRTI(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
+  void FixUpReturnReferenceType(ArtMethod* resolved_method, HInstruction* return_replacement)
+    REQUIRES_SHARED(Locks::mutator_lock_);
 
   bool ArgumentTypesMoreSpecific(HInvoke* invoke_instruction, ArtMethod* resolved_method)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-  bool ReturnTypeMoreSpecific(HInvoke* invoke_instruction, HInstruction* return_replacement)
+  bool ReturnTypeMoreSpecific(HInstruction* return_replacement, HInvoke* invoke_instruction)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Add a type guard on the given `receiver`. This will add to the graph:
@@ -335,7 +317,6 @@
 
   // The budget left for inlining, in number of instructions.
   size_t inlining_budget_;
-  VariableSizedHandleScope* const handles_;
 
   // Used to record stats about optimizations on the inlined graph.
   // If the inlining is successful, these stats are merged to the caller graph's stats.
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 1e7b48e..4364d39 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -29,11 +29,13 @@
 #include "driver/dex_compilation_unit.h"
 #include "driver/compiler_options.h"
 #include "imtable-inl.h"
+#include "intrinsics.h"
+#include "intrinsics_utils.h"
 #include "jit/jit.h"
 #include "mirror/dex_cache.h"
 #include "oat_file.h"
 #include "optimizing_compiler_stats.h"
-#include "quicken_info.h"
+#include "reflective_handle_scope-inl.h"
 #include "scoped_thread_state_change-inl.h"
 #include "sharpening.h"
 #include "ssa_builder.h"
@@ -41,6 +43,44 @@
 
 namespace art {
 
+namespace {
+
+class SamePackageCompare {
+ public:
+  explicit SamePackageCompare(const DexCompilationUnit& dex_compilation_unit)
+      : dex_compilation_unit_(dex_compilation_unit) {}
+
+  bool operator()(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (klass->GetClassLoader() != dex_compilation_unit_.GetClassLoader().Get()) {
+      return false;
+    }
+    if (referrers_descriptor_ == nullptr) {
+      const DexFile* dex_file = dex_compilation_unit_.GetDexFile();
+      uint32_t referrers_method_idx = dex_compilation_unit_.GetDexMethodIndex();
+      referrers_descriptor_ =
+          dex_file->StringByTypeIdx(dex_file->GetMethodId(referrers_method_idx).class_idx_);
+      referrers_package_length_ = PackageLength(referrers_descriptor_);
+    }
+    std::string temp;
+    const char* klass_descriptor = klass->GetDescriptor(&temp);
+    size_t klass_package_length = PackageLength(klass_descriptor);
+    return (referrers_package_length_ == klass_package_length) &&
+           memcmp(referrers_descriptor_, klass_descriptor, referrers_package_length_) == 0;
+  };
+
+ private:
+  static size_t PackageLength(const char* descriptor) {
+    const char* slash_pos = strrchr(descriptor, '/');
+    return (slash_pos != nullptr) ? static_cast<size_t>(slash_pos - descriptor) : 0u;
+  }
+
+  const DexCompilationUnit& dex_compilation_unit_;
+  const char* referrers_descriptor_ = nullptr;
+  size_t referrers_package_length_ = 0u;
+};
+
+}  // anonymous namespace
+
 HInstructionBuilder::HInstructionBuilder(HGraph* graph,
                                          HBasicBlockBuilder* block_builder,
                                          SsaBuilder* ssa_builder,
@@ -50,13 +90,10 @@
                                          const DexCompilationUnit* dex_compilation_unit,
                                          const DexCompilationUnit* outer_compilation_unit,
                                          CodeGenerator* code_generator,
-                                         ArrayRef<const uint8_t> interpreter_metadata,
                                          OptimizingCompilerStats* compiler_stats,
-                                         VariableSizedHandleScope* handles,
                                          ScopedArenaAllocator* local_allocator)
     : allocator_(graph->GetAllocator()),
       graph_(graph),
-      handles_(handles),
       dex_file_(dex_file),
       code_item_accessor_(accessor),
       return_type_(return_type),
@@ -65,7 +102,6 @@
       code_generator_(code_generator),
       dex_compilation_unit_(dex_compilation_unit),
       outer_compilation_unit_(outer_compilation_unit),
-      quicken_info_(interpreter_metadata),
       compilation_stats_(compiler_stats),
       local_allocator_(local_allocator),
       locals_for_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
@@ -357,11 +393,6 @@
 
     DCHECK(!IsBlockPopulated(current_block_));
 
-    uint32_t quicken_index = 0;
-    if (CanDecodeQuickenedInfo()) {
-      quicken_index = block_builder_->GetQuickenIndex(block_dex_pc);
-    }
-
     for (const DexInstructionPcPair& pair : code_item_accessor_.InstructionsFrom(block_dex_pc)) {
       if (current_block_ == nullptr) {
         // The previous instruction ended this block.
@@ -382,13 +413,16 @@
         AppendInstruction(new (allocator_) HNativeDebugInfo(dex_pc));
       }
 
-      if (!ProcessDexInstruction(pair.Inst(), dex_pc, quicken_index)) {
+      // Note: There may be no Thread for gtests.
+      DCHECK(Thread::Current() == nullptr || !Thread::Current()->IsExceptionPending())
+          << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
+          << " " << pair.Inst().Name() << "@" << dex_pc;
+      if (!ProcessDexInstruction(pair.Inst(), dex_pc)) {
         return false;
       }
-
-      if (QuickenInfoTable::NeedsIndexForInstruction(&pair.Inst())) {
-        ++quicken_index;
-      }
+      DCHECK(Thread::Current() == nullptr || !Thread::Current()->IsExceptionPending())
+          << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
+          << " " << pair.Inst().Name() << "@" << dex_pc;
     }
 
     if (current_block_ != nullptr) {
@@ -408,6 +442,10 @@
 void HInstructionBuilder::BuildIntrinsic(ArtMethod* method) {
   DCHECK(!code_item_accessor_.HasCodeItem());
   DCHECK(method->IsIntrinsic());
+  if (kIsDebugBuild) {
+    ScopedObjectAccess soa(Thread::Current());
+    CHECK(!method->IsSignaturePolymorphic());
+  }
 
   locals_for_.resize(
       graph_->GetBlocks().size(),
@@ -425,38 +463,43 @@
   InitializeBlockLocals();
   DCHECK(!IsBlockPopulated(current_block_));
 
-  // Add the invoke and return instruction. Use HInvokeStaticOrDirect even
-  // for methods that would normally use an HInvokeVirtual (sharpen the call).
+  // Add the intermediate representation, if available, or invoke instruction.
   size_t in_vregs = graph_->GetNumberOfInVRegs();
   size_t number_of_arguments =
       in_vregs - std::count(current_locals_->end() - in_vregs, current_locals_->end(), nullptr);
   uint32_t method_idx = dex_compilation_unit_->GetDexMethodIndex();
-  MethodReference target_method(dex_file_, method_idx);
-  HInvokeStaticOrDirect::DispatchInfo dispatch_info = {
-      HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall,
-      HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod,
-      /* method_load_data= */ 0u
-  };
-  InvokeType invoke_type = dex_compilation_unit_->IsStatic() ? kStatic : kDirect;
-  HInvokeStaticOrDirect* invoke = new (allocator_) HInvokeStaticOrDirect(
-      allocator_,
-      number_of_arguments,
-      return_type_,
-      kNoDexPc,
-      method_idx,
-      method,
-      dispatch_info,
-      invoke_type,
-      target_method,
-      HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  const char* shorty = dex_file_->GetMethodShorty(method_idx);
   RangeInstructionOperands operands(graph_->GetNumberOfVRegs() - in_vregs, in_vregs);
-  HandleInvoke(invoke, operands, dex_file_->GetMethodShorty(method_idx), /* is_unresolved= */ false);
+  if (!BuildSimpleIntrinsic(method, kNoDexPc, operands, shorty)) {
+    // Some intrinsics without intermediate representation still yield a leaf method,
+    // so build the invoke. Use HInvokeStaticOrDirect even for methods that would
+    // normally use an HInvokeVirtual (sharpen the call).
+    MethodReference target_method(dex_file_, method_idx);
+    HInvokeStaticOrDirect::DispatchInfo dispatch_info = {
+        MethodLoadKind::kRuntimeCall,
+        CodePtrLocation::kCallArtMethod,
+        /* method_load_data= */ 0u
+    };
+    InvokeType invoke_type = dex_compilation_unit_->IsStatic() ? kStatic : kDirect;
+    HInvokeStaticOrDirect* invoke = new (allocator_) HInvokeStaticOrDirect(
+        allocator_,
+        number_of_arguments,
+        return_type_,
+        kNoDexPc,
+        target_method,
+        method,
+        dispatch_info,
+        invoke_type,
+        target_method,
+        HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+    HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
+  }
 
   // Add the return instruction.
   if (return_type_ == DataType::Type::kVoid) {
     AppendInstruction(new (allocator_) HReturnVoid());
   } else {
-    AppendInstruction(new (allocator_) HReturn(invoke));
+    AppendInstruction(new (allocator_) HReturn(latest_result_));
   }
 
   // Fill the exit block.
@@ -797,9 +840,7 @@
     case Instruction::INVOKE_DIRECT_RANGE:
       return kDirect;
     case Instruction::INVOKE_VIRTUAL:
-    case Instruction::INVOKE_VIRTUAL_QUICK:
     case Instruction::INVOKE_VIRTUAL_RANGE:
-    case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
       return kVirtual;
     case Instruction::INVOKE_INTERFACE:
     case Instruction::INVOKE_INTERFACE_RANGE:
@@ -813,32 +854,64 @@
   }
 }
 
-ArtMethod* HInstructionBuilder::ResolveMethod(uint16_t method_idx, InvokeType invoke_type) {
+// Try to resolve a method using the class linker. Return null if a method could
+// not be resolved or the resolved method cannot be used for some reason.
+// Also retrieve method data needed for creating the invoke intermediate
+// representation while we hold the mutator lock here.
+static ArtMethod* ResolveMethod(uint16_t method_idx,
+                                ArtMethod* referrer,
+                                const DexCompilationUnit& dex_compilation_unit,
+                                /*inout*/InvokeType* invoke_type,
+                                /*out*/MethodReference* resolved_method_info,
+                                /*out*/uint16_t* imt_or_vtable_index,
+                                /*out*/bool* is_string_constructor) {
   ScopedObjectAccess soa(Thread::Current());
 
-  ClassLinker* class_linker = dex_compilation_unit_->GetClassLinker();
-  Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader();
+  ClassLinker* class_linker = dex_compilation_unit.GetClassLinker();
+  Handle<mirror::ClassLoader> class_loader = dex_compilation_unit.GetClassLoader();
 
   ArtMethod* resolved_method =
       class_linker->ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
           method_idx,
-          dex_compilation_unit_->GetDexCache(),
+          dex_compilation_unit.GetDexCache(),
           class_loader,
-          graph_->GetArtMethod(),
-          invoke_type);
+          referrer,
+          *invoke_type);
 
   if (UNLIKELY(resolved_method == nullptr)) {
     // Clean up any exception left by type resolution.
     soa.Self()->ClearException();
     return nullptr;
   }
+  DCHECK(!soa.Self()->IsExceptionPending());
 
   // The referrer may be unresolved for AOT if we're compiling a class that cannot be
   // resolved because, for example, we don't find a superclass in the classpath.
-  if (graph_->GetArtMethod() == nullptr) {
+  if (referrer == nullptr) {
     // The class linker cannot check access without a referrer, so we have to do it.
-    // Fall back to HInvokeUnresolved if the method isn't public.
-    if (!resolved_method->IsPublic()) {
+    // Check if the declaring class or referencing class is accessible.
+    SamePackageCompare same_package(dex_compilation_unit);
+    ObjPtr<mirror::Class> declaring_class = resolved_method->GetDeclaringClass();
+    bool declaring_class_accessible = declaring_class->IsPublic() || same_package(declaring_class);
+    if (!declaring_class_accessible) {
+      // It is possible to access members from an inaccessible superclass
+      // by referencing them through an accessible subclass.
+      ObjPtr<mirror::Class> referenced_class = class_linker->LookupResolvedType(
+          dex_compilation_unit.GetDexFile()->GetMethodId(method_idx).class_idx_,
+          dex_compilation_unit.GetDexCache().Get(),
+          class_loader.Get());
+      DCHECK(referenced_class != nullptr);  // Must have been resolved when resolving the method.
+      if (!referenced_class->IsPublic() && !same_package(referenced_class)) {
+        return nullptr;
+      }
+    }
+    // Check whether the method itself is accessible.
+    // Since the referrer is unresolved but the method is resolved, it cannot be
+    // inside the same class, so a private method is known to be inaccessible.
+    // And without a resolved referrer, we cannot check for protected member access
+    // in superlass, so we handle only access to public member or within the package.
+    if (resolved_method->IsPrivate() ||
+        (!resolved_method->IsPublic() && !declaring_class_accessible)) {
       return nullptr;
     }
   }
@@ -847,16 +920,16 @@
   // We need to look at the referrer's super class vtable. We need to do this to know if we need to
   // make this an invoke-unresolved to handle cross-dex invokes or abstract super methods, both of
   // which require runtime handling.
-  if (invoke_type == kSuper) {
-    ObjPtr<mirror::Class> compiling_class = dex_compilation_unit_->GetCompilingClass().Get();
+  if (*invoke_type == kSuper) {
+    ObjPtr<mirror::Class> compiling_class = dex_compilation_unit.GetCompilingClass().Get();
     if (compiling_class == nullptr) {
       // We could not determine the method's class we need to wait until runtime.
       DCHECK(Runtime::Current()->IsAotCompiler());
       return nullptr;
     }
     ObjPtr<mirror::Class> referenced_class = class_linker->LookupResolvedType(
-        dex_compilation_unit_->GetDexFile()->GetMethodId(method_idx).class_idx_,
-        dex_compilation_unit_->GetDexCache().Get(),
+        dex_compilation_unit.GetDexFile()->GetMethodId(method_idx).class_idx_,
+        dex_compilation_unit.GetDexCache().Get(),
         class_loader.Get());
     DCHECK(referenced_class != nullptr);  // We have already resolved a method from this class.
     if (!referenced_class->IsAssignableFrom(compiling_class)) {
@@ -870,35 +943,48 @@
           resolved_method, class_linker->GetImagePointerSize());
     } else {
       uint16_t vtable_index = resolved_method->GetMethodIndex();
+      if (vtable_index >= static_cast<uint32_t>(
+              compiling_class->GetSuperClass()->GetVTableLength())) {
+        // No super method. The runtime will throw a NoSuchMethodError.
+        return nullptr;
+      }
       actual_method = compiling_class->GetSuperClass()->GetVTableEntry(
           vtable_index, class_linker->GetImagePointerSize());
     }
-    if (actual_method != resolved_method &&
-        !IsSameDexFile(*actual_method->GetDexFile(), *dex_compilation_unit_->GetDexFile())) {
-      // The back-end code generator relies on this check in order to ensure that it will not
-      // attempt to read the dex_cache with a dex_method_index that is not from the correct
-      // dex_file. If we didn't do this check then the dex_method_index will not be updated in the
-      // builder, which means that the code-generator (and sharpening and inliner, maybe)
-      // might invoke an incorrect method.
-      // TODO: The actual method could still be referenced in the current dex file, so we
-      //       could try locating it.
-      // TODO: Remove the dex_file restriction.
-      return nullptr;
-    }
     if (!actual_method->IsInvokable()) {
       // Fail if the actual method cannot be invoked. Otherwise, the runtime resolution stub
       // could resolve the callee to the wrong method.
       return nullptr;
     }
-    resolved_method = actual_method;
+    // Call GetCanonicalMethod in case the resolved method is a copy: for super calls, the encoding
+    // of ArtMethod in BSS relies on not having copies there.
+    resolved_method = actual_method->GetCanonicalMethod(class_linker->GetImagePointerSize());
   }
 
-  return resolved_method;
-}
+  if (*invoke_type == kInterface) {
+    if (resolved_method->GetDeclaringClass()->IsObjectClass()) {
+      // If the resolved method is from j.l.Object, emit a virtual call instead.
+      // The IMT conflict stub only handles interface methods.
+      *invoke_type = kVirtual;
+    } else {
+      DCHECK(resolved_method->GetDeclaringClass()->IsInterface());
+    }
+  }
 
-static bool IsStringConstructor(ArtMethod* method) {
-  ScopedObjectAccess soa(Thread::Current());
-  return method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
+  *resolved_method_info =
+        MethodReference(resolved_method->GetDexFile(), resolved_method->GetDexMethodIndex());
+  if (*invoke_type == kVirtual) {
+    // For HInvokeVirtual we need the vtable index.
+    *imt_or_vtable_index = resolved_method->GetVtableIndex();
+  } else if (*invoke_type == kInterface) {
+    // For HInvokeInterface we need the IMT index.
+    *imt_or_vtable_index = ImTable::GetImtIndex(resolved_method);
+  }
+
+  *is_string_constructor =
+      resolved_method->IsConstructor() && resolved_method->GetDeclaringClass()->IsStringClass();
+
+  return resolved_method;
 }
 
 bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
@@ -916,31 +1002,39 @@
     number_of_arguments++;
   }
 
-  ArtMethod* resolved_method = ResolveMethod(method_idx, invoke_type);
+  MethodReference resolved_method_reference(nullptr, 0u);
+  bool is_string_constructor = false;
+  uint16_t imt_or_vtable_index = DexFile::kDexNoIndex16;
+  ArtMethod* resolved_method = ResolveMethod(method_idx,
+                                             graph_->GetArtMethod(),
+                                             *dex_compilation_unit_,
+                                             &invoke_type,
+                                             &resolved_method_reference,
+                                             &imt_or_vtable_index,
+                                             &is_string_constructor);
 
+  MethodReference method_reference(&graph_->GetDexFile(), method_idx);
   if (UNLIKELY(resolved_method == nullptr)) {
+    DCHECK(!Thread::Current()->IsExceptionPending());
     MaybeRecordStat(compilation_stats_,
                     MethodCompilationStat::kUnresolvedMethod);
     HInvoke* invoke = new (allocator_) HInvokeUnresolved(allocator_,
                                                          number_of_arguments,
                                                          return_type,
                                                          dex_pc,
-                                                         method_idx,
+                                                         method_reference,
                                                          invoke_type);
     return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ true);
   }
 
   // Replace calls to String.<init> with StringFactory.
-  if (IsStringConstructor(resolved_method)) {
+  if (is_string_constructor) {
     uint32_t string_init_entry_point = WellKnownClasses::StringInitToEntryPoint(resolved_method);
     HInvokeStaticOrDirect::DispatchInfo dispatch_info = {
-        HInvokeStaticOrDirect::MethodLoadKind::kStringInit,
-        HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod,
+        MethodLoadKind::kStringInit,
+        CodePtrLocation::kCallArtMethod,
         dchecked_integral_cast<uint64_t>(string_init_entry_point)
     };
-    ScopedObjectAccess soa(Thread::Current());
-    MethodReference target_method(resolved_method->GetDexFile(),
-                                  resolved_method->GetDexMethodIndex());
     // We pass null for the resolved_method to ensure optimizations
     // don't rely on it.
     HInvoke* invoke = new (allocator_) HInvokeStaticOrDirect(
@@ -948,83 +1042,130 @@
         number_of_arguments - 1,
         /* return_type= */ DataType::Type::kReference,
         dex_pc,
-        method_idx,
+        method_reference,
         /* resolved_method= */ nullptr,
         dispatch_info,
         invoke_type,
-        target_method,
+        resolved_method_reference,
         HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit);
     return HandleStringInit(invoke, operands, shorty);
   }
 
   // Potential class initialization check, in the case of a static method call.
+  HInvokeStaticOrDirect::ClinitCheckRequirement clinit_check_requirement =
+      HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
   HClinitCheck* clinit_check = nullptr;
+  if (invoke_type == kStatic) {
+    clinit_check = ProcessClinitCheckForInvoke(dex_pc, resolved_method, &clinit_check_requirement);
+  }
+
+  // Try to build an HIR replacement for the intrinsic.
+  if (UNLIKELY(resolved_method->IsIntrinsic())) {
+    // All intrinsics are in the primary boot image, so their class can always be referenced
+    // and we do not need to rely on the implicit class initialization check. The class should
+    // be initialized but we do not require that here.
+    DCHECK_NE(clinit_check_requirement, HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit);
+    if (BuildSimpleIntrinsic(resolved_method, dex_pc, operands, shorty)) {
+      return true;
+    }
+  }
+
   HInvoke* invoke = nullptr;
   if (invoke_type == kDirect || invoke_type == kStatic || invoke_type == kSuper) {
-    // By default, consider that the called method implicitly requires
-    // an initialization check of its declaring method.
-    HInvokeStaticOrDirect::ClinitCheckRequirement clinit_check_requirement
-        = HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit;
-    ScopedObjectAccess soa(Thread::Current());
-    if (invoke_type == kStatic) {
-      clinit_check =
-          ProcessClinitCheckForInvoke(dex_pc, resolved_method, &clinit_check_requirement);
-    } else if (invoke_type == kSuper) {
-      if (IsSameDexFile(*resolved_method->GetDexFile(), *dex_compilation_unit_->GetDexFile())) {
+    // For sharpening, we create another MethodReference, to account for the
+    // kSuper case below where we cannot find a dex method index.
+    bool has_method_id = true;
+    if (invoke_type == kSuper) {
+      uint32_t dex_method_index = method_reference.index;
+      if (IsSameDexFile(*resolved_method_reference.dex_file,
+                        *dex_compilation_unit_->GetDexFile())) {
         // Update the method index to the one resolved. Note that this may be a no-op if
         // we resolved to the method referenced by the instruction.
-        method_idx = resolved_method->GetDexMethodIndex();
+        dex_method_index = resolved_method_reference.index;
+      } else {
+        // Try to find a dex method index in this caller's dex file.
+        ScopedObjectAccess soa(Thread::Current());
+        dex_method_index = resolved_method->FindDexMethodIndexInOtherDexFile(
+            *dex_compilation_unit_->GetDexFile(), method_idx);
+      }
+      if (dex_method_index == dex::kDexNoIndex) {
+        has_method_id = false;
+      } else {
+        method_reference.index = dex_method_index;
       }
     }
-
     HInvokeStaticOrDirect::DispatchInfo dispatch_info =
-        HSharpening::SharpenInvokeStaticOrDirect(resolved_method, code_generator_);
-    MethodReference target_method(resolved_method->GetDexFile(),
-                                  resolved_method->GetDexMethodIndex());
+        HSharpening::SharpenLoadMethod(resolved_method,
+                                       has_method_id,
+                                       /* for_interface_call= */ false,
+                                       code_generator_);
+    if (dispatch_info.code_ptr_location == CodePtrLocation::kCallCriticalNative) {
+      graph_->SetHasDirectCriticalNativeCall(true);
+    }
     invoke = new (allocator_) HInvokeStaticOrDirect(allocator_,
                                                     number_of_arguments,
                                                     return_type,
                                                     dex_pc,
-                                                    method_idx,
+                                                    method_reference,
                                                     resolved_method,
                                                     dispatch_info,
                                                     invoke_type,
-                                                    target_method,
+                                                    resolved_method_reference,
                                                     clinit_check_requirement);
+    if (clinit_check != nullptr) {
+      // Add the class initialization check as last input of `invoke`.
+      DCHECK_EQ(clinit_check_requirement, HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit);
+      size_t clinit_check_index = invoke->InputCount() - 1u;
+      DCHECK(invoke->InputAt(clinit_check_index) == nullptr);
+      invoke->SetArgumentAt(clinit_check_index, clinit_check);
+    }
   } else if (invoke_type == kVirtual) {
-    ScopedObjectAccess soa(Thread::Current());  // Needed for the method index
     invoke = new (allocator_) HInvokeVirtual(allocator_,
                                              number_of_arguments,
                                              return_type,
                                              dex_pc,
-                                             method_idx,
+                                             method_reference,
                                              resolved_method,
-                                             resolved_method->GetMethodIndex());
+                                             resolved_method_reference,
+                                             /*vtable_index=*/ imt_or_vtable_index);
   } else {
     DCHECK_EQ(invoke_type, kInterface);
-    ScopedObjectAccess soa(Thread::Current());  // Needed for the IMT index and class check below.
-    if (resolved_method->GetDeclaringClass()->IsObjectClass()) {
-      // If the resolved method is from j.l.Object, emit a virtual call instead.
-      // The IMT conflict stub only handles interface methods.
-      invoke = new (allocator_) HInvokeVirtual(allocator_,
+    if (kIsDebugBuild) {
+      ScopedObjectAccess soa(Thread::Current());
+      DCHECK(resolved_method->GetDeclaringClass()->IsInterface());
+    }
+    MethodLoadKind load_kind = HSharpening::SharpenLoadMethod(
+        resolved_method,
+        /* has_method_id= */ true,
+        /* for_interface_call= */ true,
+        code_generator_)
+            .method_load_kind;
+    invoke = new (allocator_) HInvokeInterface(allocator_,
                                                number_of_arguments,
                                                return_type,
                                                dex_pc,
-                                               method_idx,
+                                               method_reference,
                                                resolved_method,
-                                               resolved_method->GetMethodIndex());
-    } else {
-      DCHECK(resolved_method->GetDeclaringClass()->IsInterface());
-      invoke = new (allocator_) HInvokeInterface(allocator_,
-                                                 number_of_arguments,
-                                                 return_type,
-                                                 dex_pc,
-                                                 method_idx,
-                                                 resolved_method,
-                                                 ImTable::GetImtIndex(resolved_method));
-    }
+                                               resolved_method_reference,
+                                               /*imt_index=*/ imt_or_vtable_index,
+                                               load_kind);
   }
-  return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false, clinit_check);
+  return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
+}
+
+static bool VarHandleAccessorNeedsReturnTypeCheck(HInvoke* invoke, DataType::Type return_type) {
+  mirror::VarHandle::AccessModeTemplate access_mode_template =
+      mirror::VarHandle::GetAccessModeTemplateByIntrinsic(invoke->GetIntrinsic());
+
+  switch (access_mode_template) {
+    case mirror::VarHandle::AccessModeTemplate::kGet:
+    case mirror::VarHandle::AccessModeTemplate::kGetAndUpdate:
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndExchange:
+      return return_type == DataType::Type::kReference;
+    case mirror::VarHandle::AccessModeTemplate::kSet:
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndSet:
+      return false;
+  }
 }
 
 bool HInstructionBuilder::BuildInvokePolymorphic(uint32_t dex_pc,
@@ -1035,12 +1176,48 @@
   DCHECK_EQ(1 + ArtMethod::NumArgRegisters(shorty), operands.GetNumberOfOperands());
   DataType::Type return_type = DataType::FromShorty(shorty[0]);
   size_t number_of_arguments = strlen(shorty);
+  // We use ResolveMethod which is also used in BuildInvoke in order to
+  // not duplicate code. As such, we need to provide is_string_constructor
+  // even if we don't need it afterwards.
+  InvokeType invoke_type = InvokeType::kPolymorphic;
+  bool is_string_constructor = false;
+  uint16_t imt_or_vtable_index = DexFile::kDexNoIndex16;
+  MethodReference resolved_method_reference(nullptr, 0u);
+  ArtMethod* resolved_method = ResolveMethod(method_idx,
+                                            graph_->GetArtMethod(),
+                                            *dex_compilation_unit_,
+                                            &invoke_type,
+                                            &resolved_method_reference,
+                                            &imt_or_vtable_index,
+                                            &is_string_constructor);
+
+  MethodReference method_reference(&graph_->GetDexFile(), method_idx);
   HInvoke* invoke = new (allocator_) HInvokePolymorphic(allocator_,
                                                         number_of_arguments,
                                                         return_type,
                                                         dex_pc,
-                                                        method_idx);
-  return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
+                                                        method_reference,
+                                                        resolved_method,
+                                                        resolved_method_reference,
+                                                        proto_idx);
+  if (!HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false)) {
+    return false;
+  }
+
+  if (invoke->GetIntrinsic() != Intrinsics::kMethodHandleInvoke &&
+      invoke->GetIntrinsic() != Intrinsics::kMethodHandleInvokeExact &&
+      VarHandleAccessorNeedsReturnTypeCheck(invoke, return_type)) {
+    // Type check is needed because VarHandle intrinsics do not type check the retrieved reference.
+    ScopedObjectAccess soa(Thread::Current());
+    ArtMethod* referrer = graph_->GetArtMethod();
+    dex::TypeIndex return_type_index =
+        referrer->GetDexFile()->GetProtoId(proto_idx).return_type_idx_;
+
+    BuildTypeCheck(/* is_instance_of= */ false, invoke, return_type_index, dex_pc);
+    latest_result_ = current_block_->GetLastInstruction();
+  }
+
+  return true;
 }
 
 
@@ -1051,11 +1228,14 @@
   const char* shorty = dex_file_->GetShorty(proto_idx);
   DataType::Type return_type = DataType::FromShorty(shorty[0]);
   size_t number_of_arguments = strlen(shorty) - 1;
+  // HInvokeCustom takes a DexNoNoIndex method reference.
+  MethodReference method_reference(&graph_->GetDexFile(), dex::kDexNoIndex);
   HInvoke* invoke = new (allocator_) HInvokeCustom(allocator_,
                                                    number_of_arguments,
                                                    call_site_idx,
                                                    return_type,
-                                                   dex_pc);
+                                                   dex_pc,
+                                                   method_reference);
   return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
 }
 
@@ -1067,7 +1247,7 @@
   HInstruction* cls = load_class;
   Handle<mirror::Class> klass = load_class->GetClass();
 
-  if (!IsInitialized(klass)) {
+  if (!IsInitialized(klass.Get())) {
     cls = new (allocator_) HClinitCheck(load_class, dex_pc);
     AppendInstruction(cls);
   }
@@ -1076,7 +1256,11 @@
   // need access checks, then we haven't resolved the method and the class may
   // again be finalizable.
   QuickEntrypointEnum entrypoint = kQuickAllocObjectInitialized;
-  if (load_class->NeedsAccessCheck() || klass->IsFinalizable() || !klass->IsInstantiable()) {
+  if (load_class->NeedsAccessCheck() ||
+      klass == nullptr ||  // Finalizable/instantiable is unknown.
+      klass->IsFinalizable() ||
+      klass.Get() == klass->GetClass() ||  // Classes cannot be allocated in code
+      !klass->IsInstantiable()) {
     entrypoint = kQuickAllocObjectWithChecks;
   }
   // We will always be able to resolve the string class since it is in the BCP.
@@ -1224,7 +1408,6 @@
           // Primitive, null or j.l.String initialization is permitted.
           break;
         case Instruction::RETURN_VOID:
-        case Instruction::RETURN_VOID_NO_BARRIER:
           break;
         case Instruction::SPUT:
         case Instruction::SPUT_WIDE:
@@ -1299,25 +1482,25 @@
   return true;
 }
 
-bool HInstructionBuilder::IsInitialized(Handle<mirror::Class> cls) const {
+bool HInstructionBuilder::IsInitialized(ObjPtr<mirror::Class> cls) const {
   if (cls == nullptr) {
     return false;
   }
 
   // Check if the class will be initialized at runtime.
   if (cls->IsInitialized()) {
-    Runtime* runtime = Runtime::Current();
-    if (runtime->IsAotCompiler()) {
+    const CompilerOptions& compiler_options = code_generator_->GetCompilerOptions();
+    if (compiler_options.IsAotCompiler()) {
       // Assume loaded only if klass is in the boot image. App classes cannot be assumed
       // loaded because we don't even know what class loader will be used to load them.
-      if (IsInBootImage(cls.Get(), code_generator_->GetCompilerOptions())) {
+      if (IsInBootImage(cls, compiler_options)) {
         return true;
       }
     } else {
-      DCHECK(runtime->UseJitCompilation());
+      DCHECK(compiler_options.IsJitCompiler());
       if (Runtime::Current()->GetJit()->CanAssumeInitialized(
-              cls.Get(),
-              graph_->IsCompilingForSharedJitCode())) {
+              cls,
+              compiler_options.IsJitCompilerForSharedCode())) {
         // For JIT, the class cannot revert to an uninitialized state.
         return true;
       }
@@ -1335,7 +1518,7 @@
   auto is_static_method_or_constructor_of_cls = [cls](const DexCompilationUnit& compilation_unit)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     return (compilation_unit.GetAccessFlags() & (kAccStatic | kAccConstructor)) != 0u &&
-           compilation_unit.GetCompilingClass().Get() == cls.Get();
+           compilation_unit.GetCompilingClass().Get() == cls;
   };
   if (is_static_method_or_constructor_of_cls(*outer_compilation_unit_) ||
       // Check also the innermost method. Though excessive copies of ClinitCheck can be
@@ -1366,12 +1549,12 @@
   // TODO: We should walk over the entire inlined methods chain, but we don't pass that
   // information to the builder. (We could also check if we're guaranteed a non-null instance
   // of `cls` at this location but that's outside the scope of the instruction builder.)
-  bool is_subclass = IsSubClass(outer_compilation_unit_->GetCompilingClass().Get(), cls.Get());
+  bool is_subclass = IsSubClass(outer_compilation_unit_->GetCompilingClass().Get(), cls);
   if (dex_compilation_unit_ != outer_compilation_unit_) {
     is_subclass = is_subclass ||
-                  IsSubClass(dex_compilation_unit_->GetCompilingClass().Get(), cls.Get());
+                  IsSubClass(dex_compilation_unit_->GetCompilingClass().Get(), cls);
   }
-  if (is_subclass && HasTrivialInitialization(cls.Get(), code_generator_->GetCompilerOptions())) {
+  if (is_subclass && HasTrivialInitialization(cls, code_generator_->GetCompilerOptions())) {
     return true;
   }
 
@@ -1382,74 +1565,117 @@
     uint32_t dex_pc,
     ArtMethod* resolved_method,
     HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement) {
-  Handle<mirror::Class> klass = handles_->NewHandle(resolved_method->GetDeclaringClass());
+  ScopedObjectAccess soa(Thread::Current());
+  ObjPtr<mirror::Class> klass = resolved_method->GetDeclaringClass();
 
   HClinitCheck* clinit_check = nullptr;
   if (IsInitialized(klass)) {
     *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
   } else {
-    HLoadClass* cls = BuildLoadClass(klass->GetDexTypeIndex(),
-                                     klass->GetDexFile(),
-                                     klass,
+    Handle<mirror::Class> h_klass = graph_->GetHandleCache()->NewHandle(klass);
+    HLoadClass* cls = BuildLoadClass(h_klass->GetDexTypeIndex(),
+                                     h_klass->GetDexFile(),
+                                     h_klass,
                                      dex_pc,
                                      /* needs_access_check= */ false);
     if (cls != nullptr) {
       *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
       clinit_check = new (allocator_) HClinitCheck(cls, dex_pc);
       AppendInstruction(clinit_check);
+    } else {
+      // Let the invoke handle this with an implicit class initialization check.
+      *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit;
     }
   }
   return clinit_check;
 }
 
-bool HInstructionBuilder::SetupInvokeArguments(HInvoke* invoke,
+bool HInstructionBuilder::SetupInvokeArguments(HInstruction* invoke,
                                                const InstructionOperands& operands,
                                                const char* shorty,
-                                               size_t start_index,
-                                               size_t* argument_index) {
+                                               ReceiverArg receiver_arg) {
+  // Note: The `invoke` can be an intrinsic replacement, so not necessaritly HInvoke.
+  // In that case, do not log errors, they shall be reported when we try to build the HInvoke.
   uint32_t shorty_index = 1;  // Skip the return type.
   const size_t number_of_operands = operands.GetNumberOfOperands();
-  for (size_t i = start_index;
-       // Make sure we don't go over the expected arguments or over the number of
-       // dex registers given. If the instruction was seen as dead by the verifier,
-       // it hasn't been properly checked.
-       (i < number_of_operands) && (*argument_index < invoke->GetNumberOfArguments());
-       i++, (*argument_index)++) {
+  bool argument_length_error = false;
+
+  size_t start_index = 0u;
+  size_t argument_index = 0u;
+  if (receiver_arg != ReceiverArg::kNone) {
+    if (number_of_operands == 0u) {
+      argument_length_error = true;
+    } else {
+      start_index = 1u;
+      if (receiver_arg != ReceiverArg::kIgnored) {
+        uint32_t obj_reg = operands.GetOperand(0u);
+        HInstruction* arg = (receiver_arg == ReceiverArg::kPlainArg)
+            ? LoadLocal(obj_reg, DataType::Type::kReference)
+            : LoadNullCheckedLocal(obj_reg, invoke->GetDexPc());
+        if (receiver_arg != ReceiverArg::kNullCheckedOnly) {
+          invoke->SetRawInputAt(0u, arg);
+          argument_index = 1u;
+        }
+      }
+    }
+  }
+
+  for (size_t i = start_index; i < number_of_operands; ++i, ++argument_index) {
+    // Make sure we don't go over the expected arguments or over the number of
+    // dex registers given. If the instruction was seen as dead by the verifier,
+    // it hasn't been properly checked.
+    if (UNLIKELY(shorty[shorty_index] == 0)) {
+      argument_length_error = true;
+      break;
+    }
     DataType::Type type = DataType::FromShorty(shorty[shorty_index++]);
     bool is_wide = (type == DataType::Type::kInt64) || (type == DataType::Type::kFloat64);
     if (is_wide && ((i + 1 == number_of_operands) ||
                     (operands.GetOperand(i) + 1 != operands.GetOperand(i + 1)))) {
-      // Longs and doubles should be in pairs, that is, sequential registers. The verifier should
-      // reject any class where this is violated. However, the verifier only does these checks
-      // on non trivially dead instructions, so we just bailout the compilation.
-      VLOG(compiler) << "Did not compile "
-                     << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
-                     << " because of non-sequential dex register pair in wide argument";
-      MaybeRecordStat(compilation_stats_,
-                      MethodCompilationStat::kNotCompiledMalformedOpcode);
+      if (invoke->IsInvoke()) {
+        // Longs and doubles should be in pairs, that is, sequential registers. The verifier should
+        // reject any class where this is violated. However, the verifier only does these checks
+        // on non trivially dead instructions, so we just bailout the compilation.
+        VLOG(compiler) << "Did not compile "
+                       << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
+                       << " because of non-sequential dex register pair in wide argument";
+        MaybeRecordStat(compilation_stats_,
+                        MethodCompilationStat::kNotCompiledMalformedOpcode);
+      }
       return false;
     }
     HInstruction* arg = LoadLocal(operands.GetOperand(i), type);
-    invoke->SetArgumentAt(*argument_index, arg);
+    DCHECK(invoke->InputAt(argument_index) == nullptr);
+    invoke->SetRawInputAt(argument_index, arg);
     if (is_wide) {
-      i++;
+      ++i;
     }
   }
 
-  if (*argument_index != invoke->GetNumberOfArguments()) {
-    VLOG(compiler) << "Did not compile "
-                   << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
-                   << " because of wrong number of arguments in invoke instruction";
-    MaybeRecordStat(compilation_stats_,
-                    MethodCompilationStat::kNotCompiledMalformedOpcode);
+  argument_length_error = argument_length_error || shorty[shorty_index] != 0;
+  if (argument_length_error) {
+    if (invoke->IsInvoke()) {
+      VLOG(compiler) << "Did not compile "
+                     << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
+                     << " because of wrong number of arguments in invoke instruction";
+      MaybeRecordStat(compilation_stats_,
+                      MethodCompilationStat::kNotCompiledMalformedOpcode);
+    }
     return false;
   }
 
   if (invoke->IsInvokeStaticOrDirect() &&
       HInvokeStaticOrDirect::NeedsCurrentMethodInput(
-          invoke->AsInvokeStaticOrDirect()->GetMethodLoadKind())) {
-    invoke->SetArgumentAt(*argument_index, graph_->GetCurrentMethod());
-    (*argument_index)++;
+          invoke->AsInvokeStaticOrDirect()->GetDispatchInfo())) {
+    DCHECK_EQ(argument_index, invoke->AsInvokeStaticOrDirect()->GetCurrentMethodIndex());
+    DCHECK(invoke->InputAt(argument_index) == nullptr);
+    invoke->SetRawInputAt(argument_index, graph_->GetCurrentMethod());
+  }
+
+  if (invoke->IsInvokeInterface() &&
+      (invoke->AsInvokeInterface()->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive)) {
+    invoke->SetRawInputAt(invoke->AsInvokeInterface()->GetNumberOfArguments() - 1,
+                          graph_->GetCurrentMethod());
   }
 
   return true;
@@ -1458,50 +1684,212 @@
 bool HInstructionBuilder::HandleInvoke(HInvoke* invoke,
                                        const InstructionOperands& operands,
                                        const char* shorty,
-                                       bool is_unresolved,
-                                       HClinitCheck* clinit_check) {
+                                       bool is_unresolved) {
   DCHECK(!invoke->IsInvokeStaticOrDirect() || !invoke->AsInvokeStaticOrDirect()->IsStringInit());
 
-  size_t start_index = 0;
-  size_t argument_index = 0;
-  if (invoke->GetInvokeType() != InvokeType::kStatic) {  // Instance call.
-    uint32_t obj_reg = operands.GetOperand(0);
-    HInstruction* arg = is_unresolved
-        ? LoadLocal(obj_reg, DataType::Type::kReference)
-        : LoadNullCheckedLocal(obj_reg, invoke->GetDexPc());
-    invoke->SetArgumentAt(0, arg);
-    start_index = 1;
-    argument_index = 1;
-  }
-
-  if (!SetupInvokeArguments(invoke, operands, shorty, start_index, &argument_index)) {
+  ReceiverArg receiver_arg = (invoke->GetInvokeType() == InvokeType::kStatic)
+      ? ReceiverArg::kNone
+      : (is_unresolved ? ReceiverArg::kPlainArg : ReceiverArg::kNullCheckedArg);
+  if (!SetupInvokeArguments(invoke, operands, shorty, receiver_arg)) {
     return false;
   }
 
-  if (clinit_check != nullptr) {
-    // Add the class initialization check as last input of `invoke`.
-    DCHECK(invoke->IsInvokeStaticOrDirect());
-    DCHECK(invoke->AsInvokeStaticOrDirect()->GetClinitCheckRequirement()
-        == HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit);
-    invoke->SetArgumentAt(argument_index, clinit_check);
-    argument_index++;
-  }
-
   AppendInstruction(invoke);
   latest_result_ = invoke;
 
   return true;
 }
 
+bool HInstructionBuilder::BuildSimpleIntrinsic(ArtMethod* method,
+                                               uint32_t dex_pc,
+                                               const InstructionOperands& operands,
+                                               const char* shorty) {
+  Intrinsics intrinsic = static_cast<Intrinsics>(method->GetIntrinsic());
+  DCHECK_NE(intrinsic, Intrinsics::kNone);
+  constexpr DataType::Type kInt32 = DataType::Type::kInt32;
+  constexpr DataType::Type kInt64 = DataType::Type::kInt64;
+  constexpr DataType::Type kFloat32 = DataType::Type::kFloat32;
+  constexpr DataType::Type kFloat64 = DataType::Type::kFloat64;
+  ReceiverArg receiver_arg = method->IsStatic() ? ReceiverArg::kNone : ReceiverArg::kNullCheckedArg;
+  HInstruction* instruction = nullptr;
+  switch (intrinsic) {
+    case Intrinsics::kIntegerRotateRight:
+    case Intrinsics::kIntegerRotateLeft:
+      // For rotate left, we negate the distance below.
+      instruction = new (allocator_) HRor(kInt32, /*value=*/ nullptr, /*distance=*/ nullptr);
+      break;
+    case Intrinsics::kLongRotateRight:
+    case Intrinsics::kLongRotateLeft:
+      // For rotate left, we negate the distance below.
+      instruction = new (allocator_) HRor(kInt64, /*value=*/ nullptr, /*distance=*/ nullptr);
+      break;
+    case Intrinsics::kIntegerCompare:
+      instruction = new (allocator_) HCompare(
+          kInt32, /*first=*/ nullptr, /*second=*/ nullptr, ComparisonBias::kNoBias, dex_pc);
+      break;
+    case Intrinsics::kLongCompare:
+      instruction = new (allocator_) HCompare(
+          kInt64, /*first=*/ nullptr, /*second=*/ nullptr, ComparisonBias::kNoBias, dex_pc);
+      break;
+    case Intrinsics::kIntegerSignum:
+      instruction = new (allocator_) HCompare(
+          kInt32, /*first=*/ nullptr, graph_->GetIntConstant(0), ComparisonBias::kNoBias, dex_pc);
+      break;
+    case Intrinsics::kLongSignum:
+      instruction = new (allocator_) HCompare(
+          kInt64, /*first=*/ nullptr, graph_->GetLongConstant(0), ComparisonBias::kNoBias, dex_pc);
+      break;
+    case Intrinsics::kFloatIsNaN:
+    case Intrinsics::kDoubleIsNaN: {
+      // IsNaN(x) is the same as x != x.
+      instruction = new (allocator_) HNotEqual(/*first=*/ nullptr, /*second=*/ nullptr, dex_pc);
+      instruction->AsCondition()->SetBias(ComparisonBias::kLtBias);
+      break;
+    }
+    case Intrinsics::kStringCharAt:
+      // We treat String as an array to allow DCE and BCE to seamlessly work on strings.
+      instruction = new (allocator_) HArrayGet(/*array=*/ nullptr,
+                                               /*index=*/ nullptr,
+                                               DataType::Type::kUint16,
+                                               SideEffects::None(),  // Strings are immutable.
+                                               dex_pc,
+                                               /*is_string_char_at=*/ true);
+      break;
+    case Intrinsics::kStringIsEmpty:
+    case Intrinsics::kStringLength:
+      // We treat String as an array to allow DCE and BCE to seamlessly work on strings.
+      // For String.isEmpty(), we add a comparison with 0 below.
+      instruction =
+          new (allocator_) HArrayLength(/*array=*/ nullptr, dex_pc, /* is_string_length= */ true);
+      break;
+    case Intrinsics::kUnsafeLoadFence:
+      receiver_arg = ReceiverArg::kNullCheckedOnly;
+      instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kLoadAny, dex_pc);
+      break;
+    case Intrinsics::kUnsafeStoreFence:
+      receiver_arg = ReceiverArg::kNullCheckedOnly;
+      instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kAnyStore, dex_pc);
+      break;
+    case Intrinsics::kUnsafeFullFence:
+      receiver_arg = ReceiverArg::kNullCheckedOnly;
+      instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kAnyAny, dex_pc);
+      break;
+    case Intrinsics::kVarHandleFullFence:
+      instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kAnyAny, dex_pc);
+      break;
+    case Intrinsics::kVarHandleAcquireFence:
+      instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kLoadAny, dex_pc);
+      break;
+    case Intrinsics::kVarHandleReleaseFence:
+      instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kAnyStore, dex_pc);
+      break;
+    case Intrinsics::kVarHandleLoadLoadFence:
+      instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kLoadAny, dex_pc);
+      break;
+    case Intrinsics::kVarHandleStoreStoreFence:
+      instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kStoreStore, dex_pc);
+      break;
+    case Intrinsics::kMathMinIntInt:
+      instruction = new (allocator_) HMin(kInt32, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathMinLongLong:
+      instruction = new (allocator_) HMin(kInt64, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathMinFloatFloat:
+      instruction = new (allocator_) HMin(kFloat32, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathMinDoubleDouble:
+      instruction = new (allocator_) HMin(kFloat64, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathMaxIntInt:
+      instruction = new (allocator_) HMax(kInt32, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathMaxLongLong:
+      instruction = new (allocator_) HMax(kInt64, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathMaxFloatFloat:
+      instruction = new (allocator_) HMax(kFloat32, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathMaxDoubleDouble:
+      instruction = new (allocator_) HMax(kFloat64, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathAbsInt:
+      instruction = new (allocator_) HAbs(kInt32, /*input=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathAbsLong:
+      instruction = new (allocator_) HAbs(kInt64, /*input=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathAbsFloat:
+      instruction = new (allocator_) HAbs(kFloat32, /*input=*/ nullptr, dex_pc);
+      break;
+    case Intrinsics::kMathAbsDouble:
+      instruction = new (allocator_) HAbs(kFloat64, /*input=*/ nullptr, dex_pc);
+      break;
+    default:
+      // We do not have intermediate representation for other intrinsics.
+      return false;
+  }
+  DCHECK(instruction != nullptr);
+  if (!SetupInvokeArguments(instruction, operands, shorty, receiver_arg)) {
+    return false;
+  }
+
+  switch (intrinsic) {
+    case Intrinsics::kIntegerRotateLeft:
+    case Intrinsics::kLongRotateLeft: {
+      // Negate the distance value for rotate left.
+      DCHECK(instruction->IsRor());
+      HNeg* neg = new (allocator_) HNeg(kInt32, instruction->InputAt(1u));
+      AppendInstruction(neg);
+      instruction->SetRawInputAt(1u, neg);
+      break;
+    }
+    case Intrinsics::kFloatIsNaN:
+    case Intrinsics::kDoubleIsNaN:
+      // Set the second input to be the same as first.
+      DCHECK(instruction->IsNotEqual());
+      DCHECK(instruction->InputAt(1u) == nullptr);
+      instruction->SetRawInputAt(1u, instruction->InputAt(0u));
+      break;
+    case Intrinsics::kStringCharAt: {
+      // Add bounds check.
+      HInstruction* array = instruction->InputAt(0u);
+      HInstruction* index = instruction->InputAt(1u);
+      HInstruction* length =
+          new (allocator_) HArrayLength(array, dex_pc, /*is_string_length=*/ true);
+      AppendInstruction(length);
+      HBoundsCheck* bounds_check =
+          new (allocator_) HBoundsCheck(index, length, dex_pc, /*is_string_char_at=*/ true);
+      AppendInstruction(bounds_check);
+      graph_->SetHasBoundsChecks(true);
+      instruction->SetRawInputAt(1u, bounds_check);
+      break;
+    }
+    case Intrinsics::kStringIsEmpty: {
+      // Compare the length with 0.
+      DCHECK(instruction->IsArrayLength());
+      AppendInstruction(instruction);
+      HEqual* equal = new (allocator_) HEqual(instruction, graph_->GetIntConstant(0), dex_pc);
+      instruction = equal;
+      break;
+    }
+    default:
+      break;
+  }
+
+  AppendInstruction(instruction);
+  latest_result_ = instruction;
+
+  return true;
+}
+
 bool HInstructionBuilder::HandleStringInit(HInvoke* invoke,
                                            const InstructionOperands& operands,
                                            const char* shorty) {
   DCHECK(invoke->IsInvokeStaticOrDirect());
   DCHECK(invoke->AsInvokeStaticOrDirect()->IsStringInit());
 
-  size_t start_index = 1;
-  size_t argument_index = 0;
-  if (!SetupInvokeArguments(invoke, operands, shorty, start_index, &argument_index)) {
+  if (!SetupInvokeArguments(invoke, operands, shorty, ReceiverArg::kIgnored)) {
     return false;
   }
 
@@ -1544,21 +1932,10 @@
 
 bool HInstructionBuilder::BuildInstanceFieldAccess(const Instruction& instruction,
                                                    uint32_t dex_pc,
-                                                   bool is_put,
-                                                   size_t quicken_index) {
+                                                   bool is_put) {
   uint32_t source_or_dest_reg = instruction.VRegA_22c();
   uint32_t obj_reg = instruction.VRegB_22c();
-  uint16_t field_index;
-  if (instruction.IsQuickened()) {
-    if (!CanDecodeQuickenedInfo()) {
-      VLOG(compiler) << "Not compiled: Could not decode quickened instruction "
-                     << instruction.Opcode();
-      return false;
-    }
-    field_index = LookupQuickenedInfo(quicken_index);
-  } else {
-    field_index = instruction.VRegC_22c();
-  }
+  uint16_t field_index = instruction.VRegC_22c();
 
   ScopedObjectAccess soa(Thread::Current());
   ArtField* resolved_field = ResolveField(field_index, /* is_static= */ false, is_put);
@@ -1647,19 +2024,20 @@
   ClassLinker* class_linker = dex_compilation_unit_->GetClassLinker();
   Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader();
 
-  ArtField* resolved_field = class_linker->ResolveField(field_idx,
-                                                        dex_compilation_unit_->GetDexCache(),
-                                                        class_loader,
-                                                        is_static);
-  DCHECK_EQ(resolved_field == nullptr, soa.Self()->IsExceptionPending());
+  ArtField* resolved_field = class_linker->ResolveFieldJLS(field_idx,
+                                                           dex_compilation_unit_->GetDexCache(),
+                                                           class_loader);
+  DCHECK_EQ(resolved_field == nullptr, soa.Self()->IsExceptionPending())
+      << "field="
+      << ((resolved_field == nullptr) ? "null" : resolved_field->PrettyField())
+      << ", exception="
+      << (soa.Self()->IsExceptionPending() ? soa.Self()->GetException()->Dump() : "null");
   if (UNLIKELY(resolved_field == nullptr)) {
     // Clean up any exception left by field resolution.
     soa.Self()->ClearException();
     return nullptr;
   }
 
-  // Check static/instance. The class linker has a fast path for looking into the dex cache
-  // and does not check static/instance if it hits it.
   if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
     return nullptr;
   }
@@ -1667,7 +2045,29 @@
   // Check access.
   Handle<mirror::Class> compiling_class = dex_compilation_unit_->GetCompilingClass();
   if (compiling_class == nullptr) {
-    if (!resolved_field->IsPublic()) {
+    // Check if the declaring class or referencing class is accessible.
+    SamePackageCompare same_package(*dex_compilation_unit_);
+    ObjPtr<mirror::Class> declaring_class = resolved_field->GetDeclaringClass();
+    bool declaring_class_accessible = declaring_class->IsPublic() || same_package(declaring_class);
+    if (!declaring_class_accessible) {
+      // It is possible to access members from an inaccessible superclass
+      // by referencing them through an accessible subclass.
+      ObjPtr<mirror::Class> referenced_class = class_linker->LookupResolvedType(
+          dex_compilation_unit_->GetDexFile()->GetFieldId(field_idx).class_idx_,
+          dex_compilation_unit_->GetDexCache().Get(),
+          class_loader.Get());
+      DCHECK(referenced_class != nullptr);  // Must have been resolved when resolving the field.
+      if (!referenced_class->IsPublic() && !same_package(referenced_class)) {
+        return nullptr;
+      }
+    }
+    // Check whether the field itself is accessible.
+    // Since the referrer is unresolved but the field is resolved, it cannot be
+    // inside the same class, so a private field is known to be inaccessible.
+    // And without a resolved referrer, we cannot check for protected member access
+    // in superlass, so we handle only access to public member or within the package.
+    if (resolved_field->IsPrivate() ||
+        (!resolved_field->IsPublic() && !declaring_class_accessible)) {
       return nullptr;
     }
   } else if (!compiling_class->CanAccessResolvedField(resolved_field->GetDeclaringClass(),
@@ -1685,7 +2085,14 @@
     return nullptr;
   }
 
-  return resolved_field;
+  StackArtFieldHandleScope<1> rhs(soa.Self());
+  ReflectiveHandle<ArtField> resolved_field_handle(rhs.NewHandle(resolved_field));
+  if (resolved_field->ResolveType().IsNull()) {
+    // ArtField::ResolveType() may fail as evidenced with a dexing bug (b/78788577).
+    soa.Self()->ClearException();
+    return nullptr;  // Failure
+  }
+  return resolved_field_handle.Get();
 }
 
 void HInstructionBuilder::BuildStaticFieldAccess(const Instruction& instruction,
@@ -1707,7 +2114,8 @@
 
   DataType::Type field_type = GetFieldAccessType(*dex_file_, field_index);
 
-  Handle<mirror::Class> klass = handles_->NewHandle(resolved_field->GetDeclaringClass());
+  Handle<mirror::Class> klass =
+      graph_->GetHandleCache()->NewHandle(resolved_field->GetDeclaringClass());
   HLoadClass* constant = BuildLoadClass(klass->GetDexTypeIndex(),
                                         klass->GetDexFile(),
                                         klass,
@@ -1724,7 +2132,7 @@
   }
 
   HInstruction* cls = constant;
-  if (!IsInitialized(klass)) {
+  if (!IsInitialized(klass.Get())) {
     cls = new (allocator_) HClinitCheck(constant, dex_pc);
     AppendInstruction(cls);
   }
@@ -1957,7 +2365,7 @@
   HSharpening::ProcessLoadString(load_string,
                                  code_generator_,
                                  *dex_compilation_unit_,
-                                 handles_);
+                                 graph_->GetHandleCache()->GetHandles());
   AppendInstruction(load_string);
 }
 
@@ -1965,7 +2373,7 @@
   ScopedObjectAccess soa(Thread::Current());
   const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
   Handle<mirror::Class> klass = ResolveClass(soa, type_index);
-  bool needs_access_check = LoadClassNeedsAccessCheck(klass);
+  bool needs_access_check = LoadClassNeedsAccessCheck(type_index, klass.Get());
   return BuildLoadClass(type_index, dex_file, klass, dex_pc, needs_access_check);
 }
 
@@ -1985,9 +2393,15 @@
     }
   }
 
-  // Note: `klass` must be from `handles_`.
+  // We cannot use the referrer's class load kind if we need to do an access check.
+  // If the `klass` is unresolved, we need access check with the exception of the referrer's
+  // class, see LoadClassNeedsAccessCheck(), so the `!needs_access_check` check is enough.
+  // Otherwise, also check if the `klass` is the same as the compiling class, which also
+  // conveniently rejects the case of unresolved compiling class.
   bool is_referrers_class =
-      (klass != nullptr) && (outer_compilation_unit_->GetCompilingClass().Get() == klass.Get());
+    !needs_access_check &&
+    (klass == nullptr || outer_compilation_unit_->GetCompilingClass().Get() == klass.Get());
+  // Note: `klass` must be from `graph_->GetHandleCache()`.
   HLoadClass* load_class = new (allocator_) HLoadClass(
       graph_->GetCurrentMethod(),
       type_index,
@@ -2023,19 +2437,68 @@
   DCHECK_EQ(klass == nullptr, soa.Self()->IsExceptionPending());
   soa.Self()->ClearException();  // Clean up the exception left by type resolution if any.
 
-  Handle<mirror::Class> h_klass = handles_->NewHandle(klass);
+  Handle<mirror::Class> h_klass = graph_->GetHandleCache()->NewHandle(klass);
   class_cache_.Put(type_index, h_klass);
   return h_klass;
 }
 
-bool HInstructionBuilder::LoadClassNeedsAccessCheck(Handle<mirror::Class> klass) {
+bool HInstructionBuilder::LoadClassNeedsAccessCheck(dex::TypeIndex type_index,
+                                                    ObjPtr<mirror::Class> klass) {
   if (klass == nullptr) {
-    return true;
+    // If the class is unresolved, we can avoid access checks only for references to
+    // the compiling class as determined by checking the descriptor and ClassLoader.
+    if (outer_compilation_unit_->GetCompilingClass() != nullptr) {
+      // Compiling class is resolved, so different from the unresolved class.
+      return true;
+    }
+    if (dex_compilation_unit_->GetClassLoader().Get() !=
+            outer_compilation_unit_->GetClassLoader().Get()) {
+      // Resolving the same descriptor in a different ClassLoader than the
+      // defining loader of the compiling class shall either fail to find
+      // the class definition, or find a different one.
+      // (Assuming no custom ClassLoader hierarchy with circular delegation.)
+      return true;
+    }
+    // Check if the class is the outer method's class.
+    // For the same dex file compare type indexes, otherwise descriptors.
+    const DexFile* outer_dex_file = outer_compilation_unit_->GetDexFile();
+    const DexFile* inner_dex_file = dex_compilation_unit_->GetDexFile();
+    const dex::ClassDef& outer_class_def =
+        outer_dex_file->GetClassDef(outer_compilation_unit_->GetClassDefIndex());
+    if (IsSameDexFile(*inner_dex_file, *outer_dex_file)) {
+      if (type_index != outer_class_def.class_idx_) {
+        return true;
+      }
+    } else {
+      uint32_t outer_utf16_length;
+      const char* outer_descriptor =
+          outer_dex_file->StringByTypeIdx(outer_class_def.class_idx_, &outer_utf16_length);
+      uint32_t target_utf16_length;
+      const char* target_descriptor =
+          inner_dex_file->StringByTypeIdx(type_index, &target_utf16_length);
+      if (outer_utf16_length != target_utf16_length ||
+          strcmp(outer_descriptor, target_descriptor) != 0) {
+        return true;
+      }
+    }
+    // For inlined methods we also need to check if the compiling class
+    // is public or in the same package as the inlined method's class.
+    if (dex_compilation_unit_ != outer_compilation_unit_ &&
+        (outer_class_def.access_flags_ & kAccPublic) == 0) {
+      DCHECK(dex_compilation_unit_->GetCompilingClass() != nullptr);
+      SamePackageCompare same_package(*outer_compilation_unit_);
+      if (!same_package(dex_compilation_unit_->GetCompilingClass().Get())) {
+        return true;
+      }
+    }
+    return false;
   } else if (klass->IsPublic()) {
     return false;
+  } else if (dex_compilation_unit_->GetCompilingClass() != nullptr) {
+    return !dex_compilation_unit_->GetCompilingClass()->CanAccess(klass);
   } else {
-    ObjPtr<mirror::Class> compiling_class = dex_compilation_unit_->GetCompilingClass().Get();
-    return compiling_class == nullptr || !compiling_class->CanAccess(klass.Get());
+    SamePackageCompare same_package(*dex_compilation_unit_);
+    return !same_package(klass);
   }
 }
 
@@ -2053,17 +2516,14 @@
   AppendInstruction(load_method_type);
 }
 
-void HInstructionBuilder::BuildTypeCheck(const Instruction& instruction,
-                                         uint8_t destination,
-                                         uint8_t reference,
+void HInstructionBuilder::BuildTypeCheck(bool is_instance_of,
+                                         HInstruction* object,
                                          dex::TypeIndex type_index,
                                          uint32_t dex_pc) {
-  HInstruction* object = LoadLocal(reference, DataType::Type::kReference);
-
   ScopedObjectAccess soa(Thread::Current());
   const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
   Handle<mirror::Class> klass = ResolveClass(soa, type_index);
-  bool needs_access_check = LoadClassNeedsAccessCheck(klass);
+  bool needs_access_check = LoadClassNeedsAccessCheck(type_index, klass.Get());
   TypeCheckKind check_kind = HSharpening::ComputeTypeCheckKind(
       klass.Get(), code_generator_, needs_access_check);
 
@@ -2085,7 +2545,7 @@
   }
   DCHECK(class_or_null != nullptr);
 
-  if (instruction.Opcode() == Instruction::INSTANCE_OF) {
+  if (is_instance_of) {
     AppendInstruction(new (allocator_) HInstanceOf(object,
                                                    class_or_null,
                                                    check_kind,
@@ -2094,9 +2554,7 @@
                                                    allocator_,
                                                    bitstring_path_to_root,
                                                    bitstring_mask));
-    UpdateLocal(destination, current_block_->GetLastInstruction());
   } else {
-    DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST);
     // We emit a CheckCast followed by a BoundType. CheckCast is a statement
     // which may throw. If it succeeds BoundType sets the new type of `object`
     // for all subsequent uses.
@@ -2110,22 +2568,28 @@
                                     bitstring_path_to_root,
                                     bitstring_mask));
     AppendInstruction(new (allocator_) HBoundType(object, dex_pc));
+  }
+}
+
+void HInstructionBuilder::BuildTypeCheck(const Instruction& instruction,
+                                         uint8_t destination,
+                                         uint8_t reference,
+                                         dex::TypeIndex type_index,
+                                         uint32_t dex_pc) {
+  HInstruction* object = LoadLocal(reference, DataType::Type::kReference);
+  bool is_instance_of = instruction.Opcode() == Instruction::INSTANCE_OF;
+
+  BuildTypeCheck(is_instance_of, object, type_index, dex_pc);
+
+  if (is_instance_of) {
+    UpdateLocal(destination, current_block_->GetLastInstruction());
+  } else {
+    DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST);
     UpdateLocal(reference, current_block_->GetLastInstruction());
   }
 }
 
-bool HInstructionBuilder::CanDecodeQuickenedInfo() const {
-  return !quicken_info_.IsNull();
-}
-
-uint16_t HInstructionBuilder::LookupQuickenedInfo(uint32_t quicken_index) {
-  DCHECK(CanDecodeQuickenedInfo());
-  return quicken_info_.GetData(quicken_index);
-}
-
-bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction,
-                                                uint32_t dex_pc,
-                                                size_t quicken_index) {
+bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, uint32_t dex_pc) {
   switch (instruction.Opcode()) {
     case Instruction::CONST_4: {
       int32_t register_index = instruction.VRegA();
@@ -2232,7 +2696,6 @@
       break;
     }
 
-    case Instruction::RETURN_VOID_NO_BARRIER:
     case Instruction::RETURN_VOID: {
       BuildReturn(instruction, DataType::Type::kVoid, dex_pc);
       break;
@@ -2276,19 +2739,8 @@
     case Instruction::INVOKE_INTERFACE:
     case Instruction::INVOKE_STATIC:
     case Instruction::INVOKE_SUPER:
-    case Instruction::INVOKE_VIRTUAL:
-    case Instruction::INVOKE_VIRTUAL_QUICK: {
-      uint16_t method_idx;
-      if (instruction.Opcode() == Instruction::INVOKE_VIRTUAL_QUICK) {
-        if (!CanDecodeQuickenedInfo()) {
-          VLOG(compiler) << "Not compiled: Could not decode quickened instruction "
-                         << instruction.Opcode();
-          return false;
-        }
-        method_idx = LookupQuickenedInfo(quicken_index);
-      } else {
-        method_idx = instruction.VRegB_35c();
-      }
+    case Instruction::INVOKE_VIRTUAL: {
+      uint16_t method_idx = instruction.VRegB_35c();
       uint32_t args[5];
       uint32_t number_of_vreg_arguments = instruction.GetVarArgs(args);
       VarArgsInstructionOperands operands(args, number_of_vreg_arguments);
@@ -2302,19 +2754,8 @@
     case Instruction::INVOKE_INTERFACE_RANGE:
     case Instruction::INVOKE_STATIC_RANGE:
     case Instruction::INVOKE_SUPER_RANGE:
-    case Instruction::INVOKE_VIRTUAL_RANGE:
-    case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
-      uint16_t method_idx;
-      if (instruction.Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK) {
-        if (!CanDecodeQuickenedInfo()) {
-          VLOG(compiler) << "Not compiled: Could not decode quickened instruction "
-                         << instruction.Opcode();
-          return false;
-        }
-        method_idx = LookupQuickenedInfo(quicken_index);
-      } else {
-        method_idx = instruction.VRegB_3rc();
-      }
+    case Instruction::INVOKE_VIRTUAL_RANGE: {
+      uint16_t method_idx = instruction.VRegB_3rc();
       RangeInstructionOperands operands(instruction.VRegC(), instruction.VRegA_3rc());
       if (!BuildInvoke(instruction, dex_pc, method_idx, operands)) {
         return false;
@@ -2955,40 +3396,26 @@
       break;
 
     case Instruction::IGET:
-    case Instruction::IGET_QUICK:
     case Instruction::IGET_WIDE:
-    case Instruction::IGET_WIDE_QUICK:
     case Instruction::IGET_OBJECT:
-    case Instruction::IGET_OBJECT_QUICK:
     case Instruction::IGET_BOOLEAN:
-    case Instruction::IGET_BOOLEAN_QUICK:
     case Instruction::IGET_BYTE:
-    case Instruction::IGET_BYTE_QUICK:
     case Instruction::IGET_CHAR:
-    case Instruction::IGET_CHAR_QUICK:
-    case Instruction::IGET_SHORT:
-    case Instruction::IGET_SHORT_QUICK: {
-      if (!BuildInstanceFieldAccess(instruction, dex_pc, /* is_put= */ false, quicken_index)) {
+    case Instruction::IGET_SHORT: {
+      if (!BuildInstanceFieldAccess(instruction, dex_pc, /* is_put= */ false)) {
         return false;
       }
       break;
     }
 
     case Instruction::IPUT:
-    case Instruction::IPUT_QUICK:
     case Instruction::IPUT_WIDE:
-    case Instruction::IPUT_WIDE_QUICK:
     case Instruction::IPUT_OBJECT:
-    case Instruction::IPUT_OBJECT_QUICK:
     case Instruction::IPUT_BOOLEAN:
-    case Instruction::IPUT_BOOLEAN_QUICK:
     case Instruction::IPUT_BYTE:
-    case Instruction::IPUT_BYTE_QUICK:
     case Instruction::IPUT_CHAR:
-    case Instruction::IPUT_CHAR_QUICK:
-    case Instruction::IPUT_SHORT:
-    case Instruction::IPUT_SHORT_QUICK: {
-      if (!BuildInstanceFieldAccess(instruction, dex_pc, /* is_put= */ true, quicken_index)) {
+    case Instruction::IPUT_SHORT: {
+      if (!BuildInstanceFieldAccess(instruction, dex_pc, /* is_put= */ true)) {
         return false;
       }
       break;
@@ -3131,21 +3558,11 @@
       break;
     }
 
-    case Instruction::UNUSED_3E:
-    case Instruction::UNUSED_3F:
-    case Instruction::UNUSED_40:
-    case Instruction::UNUSED_41:
-    case Instruction::UNUSED_42:
-    case Instruction::UNUSED_43:
+    case Instruction::UNUSED_3E ... Instruction::UNUSED_43:
+    case Instruction::UNUSED_73:
     case Instruction::UNUSED_79:
     case Instruction::UNUSED_7A:
-    case Instruction::UNUSED_F3:
-    case Instruction::UNUSED_F4:
-    case Instruction::UNUSED_F5:
-    case Instruction::UNUSED_F6:
-    case Instruction::UNUSED_F7:
-    case Instruction::UNUSED_F8:
-    case Instruction::UNUSED_F9: {
+    case Instruction::UNUSED_E3 ... Instruction::UNUSED_F9: {
       VLOG(compiler) << "Did not compile "
                      << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
                      << " because of unhandled instruction "
diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h
index d701445..817fbaa 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -26,7 +26,6 @@
 #include "dex/dex_file_types.h"
 #include "handle.h"
 #include "nodes.h"
-#include "quicken_info.h"
 
 namespace art {
 
@@ -41,7 +40,6 @@
 class OptimizingCompilerStats;
 class ScopedObjectAccess;
 class SsaBuilder;
-class VariableSizedHandleScope;
 
 namespace mirror {
 class Class;
@@ -59,9 +57,7 @@
                       const DexCompilationUnit* dex_compilation_unit,
                       const DexCompilationUnit* outer_compilation_unit,
                       CodeGenerator* code_generator,
-                      ArrayRef<const uint8_t> interpreter_metadata,
                       OptimizingCompilerStats* compiler_stats,
-                      VariableSizedHandleScope* handles,
                       ScopedArenaAllocator* local_allocator);
 
   bool Build();
@@ -72,12 +68,9 @@
   void PropagateLocalsToCatchBlocks();
   void SetLoopHeaderPhiInputs();
 
-  bool ProcessDexInstruction(const Instruction& instruction, uint32_t dex_pc, size_t quicken_index);
+  bool ProcessDexInstruction(const Instruction& instruction, uint32_t dex_pc);
   ArenaBitVector* FindNativeDebugInfoLocations();
 
-  bool CanDecodeQuickenedInfo() const;
-  uint16_t LookupQuickenedInfo(uint32_t quicken_index);
-
   HBasicBlock* FindBlockStartingAt(uint32_t dex_pc) const;
 
   ScopedArenaVector<HInstruction*>* GetLocalsFor(HBasicBlock* block);
@@ -143,8 +136,7 @@
   // Builds an instance field access node and returns whether the instruction is supported.
   bool BuildInstanceFieldAccess(const Instruction& instruction,
                                 uint32_t dex_pc,
-                                bool is_put,
-                                size_t quicken_index);
+                                bool is_put);
 
   void BuildUnresolvedStaticFieldAccess(const Instruction& instruction,
                                         uint32_t dex_pc,
@@ -205,6 +197,10 @@
                               uint32_t dex_pc);
 
   // Builds a `HInstanceOf`, or a `HCheckCast` instruction.
+  void BuildTypeCheck(bool is_instance_of,
+                      HInstruction* object,
+                      dex::TypeIndex type_index,
+                      uint32_t dex_pc);
   void BuildTypeCheck(const Instruction& instruction,
                       uint8_t destination,
                       uint8_t reference,
@@ -230,7 +226,7 @@
   Handle<mirror::Class> ResolveClass(ScopedObjectAccess& soa, dex::TypeIndex type_index)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  bool LoadClassNeedsAccessCheck(Handle<mirror::Class> klass)
+  bool LoadClassNeedsAccessCheck(dex::TypeIndex type_index, ObjPtr<mirror::Class> klass)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Builds a `HLoadMethodHandle` loading the given `method_handle_index`.
@@ -243,17 +239,22 @@
                                      uint32_t dex_pc,
                                      HInvoke* invoke);
 
-  bool SetupInvokeArguments(HInvoke* invoke,
+  enum class ReceiverArg {
+    kNone,             // No receiver, static method.
+    kNullCheckedArg,   // Normal instance invoke, null check and pass the argument.
+    kNullCheckedOnly,  // Null check but do not use the arg, used for intrinsic replacements.
+    kPlainArg,         // Do not null check but pass the argument, used for unresolved methods.
+    kIgnored,          // No receiver despite allocated vreg, used for String.<init>.
+  };
+  bool SetupInvokeArguments(HInstruction* invoke,
                             const InstructionOperands& operands,
                             const char* shorty,
-                            size_t start_index,
-                            size_t* argument_index);
+                            ReceiverArg receiver_arg);
 
   bool HandleInvoke(HInvoke* invoke,
                     const InstructionOperands& operands,
                     const char* shorty,
-                    bool is_unresolved,
-                    HClinitCheck* clinit_check = nullptr);
+                    bool is_unresolved);
 
   bool HandleStringInit(HInvoke* invoke,
                         const InstructionOperands& operands,
@@ -263,8 +264,15 @@
   HClinitCheck* ProcessClinitCheckForInvoke(
       uint32_t dex_pc,
       ArtMethod* method,
-      HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement)
-      REQUIRES_SHARED(Locks::mutator_lock_);
+      HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement);
+
+  // Try to build a replacement for an intrinsic invoke. Returns true on success,
+  // false on failure. Failure can be either lack of replacement HIR classes, or
+  // input register mismatch.
+  bool BuildSimpleIntrinsic(ArtMethod* method,
+                            uint32_t dex_pc,
+                            const InstructionOperands& operands,
+                            const char* shorty);
 
   // Build a HNewInstance instruction.
   HNewInstance* BuildNewInstance(dex::TypeIndex type_index, uint32_t dex_pc);
@@ -274,13 +282,9 @@
   void BuildConstructorFenceForAllocation(HInstruction* allocation);
 
   // Return whether the compiler can assume `cls` is initialized.
-  bool IsInitialized(Handle<mirror::Class> cls) const
+  bool IsInitialized(ObjPtr<mirror::Class> cls) const
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Try to resolve a method using the class linker. Return null if a method could
-  // not be resolved.
-  ArtMethod* ResolveMethod(uint16_t method_idx, InvokeType invoke_type);
-
   // Try to resolve a field using the class linker. Return null if it could not
   // be found.
   ArtField* ResolveField(uint16_t field_idx, bool is_static, bool is_put);
@@ -293,7 +297,6 @@
 
   ArenaAllocator* const allocator_;
   HGraph* const graph_;
-  VariableSizedHandleScope* const handles_;
 
   // The dex file where the method being compiled is, and the bytecode data.
   const DexFile* const dex_file_;
@@ -316,9 +319,6 @@
   // methods.
   const DexCompilationUnit* const outer_compilation_unit_;
 
-  // Original values kept after instruction quickening.
-  QuickenInfoTable quicken_info_;
-
   OptimizingCompilerStats* const compilation_stats_;
 
   ScopedArenaAllocator* const local_allocator_;
@@ -335,7 +335,7 @@
   ScopedArenaVector<HBasicBlock*> loop_headers_;
 
   // Cached resolved types for the current compilation unit's DexFile.
-  // Handle<>s reference entries in the `handles_`.
+  // Handle<>s reference entries in the `graph_->GetHandleCache()`.
   ScopedArenaSafeMap<dex::TypeIndex, Handle<mirror::Class>> class_cache_;
 
   static constexpr int kDefaultNumberOfLoops = 2;
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 84297ec..a6104ef 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -18,11 +18,12 @@
 
 #include "art_method-inl.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "data_type-inl.h"
 #include "escape.h"
 #include "intrinsics.h"
 #include "mirror/class-inl.h"
+#include "optimizing/nodes.h"
 #include "scoped_thread_state_change-inl.h"
 #include "sharpening.h"
 #include "string_builder_append.h"
@@ -37,10 +38,12 @@
  public:
   InstructionSimplifierVisitor(HGraph* graph,
                                CodeGenerator* codegen,
-                               OptimizingCompilerStats* stats)
+                               OptimizingCompilerStats* stats,
+                               bool be_loop_friendly)
       : HGraphDelegateVisitor(graph),
         codegen_(codegen),
-        stats_(stats) {}
+        stats_(stats),
+        be_loop_friendly_(be_loop_friendly) {}
 
   bool Run();
 
@@ -65,6 +68,7 @@
   bool TryHandleAssociativeAndCommutativeOperation(HBinaryOperation* instruction);
   bool TrySubtractionChainSimplification(HBinaryOperation* instruction);
   bool TryCombineVecMultiplyAccumulate(HVecMul* mul);
+  void TryToReuseDiv(HRem* rem);
 
   void VisitShift(HBinaryOperation* shift);
   void VisitEqual(HEqual* equal) override;
@@ -90,6 +94,7 @@
   void VisitAbove(HAbove* condition) override;
   void VisitAboveOrEqual(HAboveOrEqual* condition) override;
   void VisitDiv(HDiv* instruction) override;
+  void VisitRem(HRem* instruction) override;
   void VisitMul(HMul* instruction) override;
   void VisitNeg(HNeg* instruction) override;
   void VisitNot(HNot* instruction) override;
@@ -105,30 +110,31 @@
   void VisitInvoke(HInvoke* invoke) override;
   void VisitDeoptimize(HDeoptimize* deoptimize) override;
   void VisitVecMul(HVecMul* instruction) override;
+  void VisitPredicatedInstanceFieldGet(HPredicatedInstanceFieldGet* instruction) override;
 
   bool CanEnsureNotNullAt(HInstruction* instr, HInstruction* at) const;
 
-  void SimplifyRotate(HInvoke* invoke, bool is_left, DataType::Type type);
   void SimplifySystemArrayCopy(HInvoke* invoke);
   void SimplifyStringEquals(HInvoke* invoke);
-  void SimplifyCompare(HInvoke* invoke, bool is_signum, DataType::Type type);
-  void SimplifyIsNaN(HInvoke* invoke);
   void SimplifyFP2Int(HInvoke* invoke);
   void SimplifyStringCharAt(HInvoke* invoke);
-  void SimplifyStringIsEmptyOrLength(HInvoke* invoke);
+  void SimplifyStringLength(HInvoke* invoke);
   void SimplifyStringIndexOf(HInvoke* invoke);
   void SimplifyNPEOnArgN(HInvoke* invoke, size_t);
   void SimplifyReturnThis(HInvoke* invoke);
   void SimplifyAllocationIntrinsic(HInvoke* invoke);
-  void SimplifyMemBarrier(HInvoke* invoke, MemBarrierKind barrier_kind);
-  void SimplifyMin(HInvoke* invoke, DataType::Type type);
-  void SimplifyMax(HInvoke* invoke, DataType::Type type);
-  void SimplifyAbs(HInvoke* invoke, DataType::Type type);
 
   CodeGenerator* codegen_;
   OptimizingCompilerStats* stats_;
   bool simplification_occurred_ = false;
   int simplifications_at_current_position_ = 0;
+  // Prohibit optimizations which can affect HInductionVarAnalysis/HLoopOptimization
+  // and prevent loop optimizations:
+  //   true - avoid such optimizations.
+  //   false - allow such optimizations.
+  // Checked by the following optimizations:
+  //   - TryToReuseDiv: simplification of Div+Rem into Div+Mul+Sub.
+  bool be_loop_friendly_;
   // We ensure we do not loop infinitely. The value should not be too high, since that
   // would allow looping around the same basic block too many times. The value should
   // not be too low either, however, since we want to allow revisiting a basic block
@@ -142,7 +148,9 @@
     visitor.VisitReversePostOrder();
   }
 
-  InstructionSimplifierVisitor visitor(graph_, codegen_, stats_);
+  bool be_loop_friendly = (use_all_optimizations_ == false);
+
+  InstructionSimplifierVisitor visitor(graph_, codegen_, stats_, be_loop_friendly);
   return visitor.Run();
 }
 
@@ -281,56 +289,72 @@
   }
 
   ArenaAllocator* allocator = mul->GetBlock()->GetGraph()->GetAllocator();
-
-  if (mul->HasOnlyOneNonEnvironmentUse()) {
-    HInstruction* use = mul->GetUses().front().GetUser();
-    if (use->IsVecAdd() || use->IsVecSub()) {
-      // Replace code looking like
-      //    VECMUL tmp, x, y
-      //    VECADD/SUB dst, acc, tmp
-      // with
-      //    VECMULACC dst, acc, x, y
-      // Note that we do not want to (unconditionally) perform the merge when the
-      // multiplication has multiple uses and it can be merged in all of them.
-      // Multiple uses could happen on the same control-flow path, and we would
-      // then increase the amount of work. In the future we could try to evaluate
-      // whether all uses are on different control-flow paths (using dominance and
-      // reverse-dominance information) and only perform the merge when they are.
-      HInstruction* accumulator = nullptr;
-      HVecBinaryOperation* binop = use->AsVecBinaryOperation();
-      HInstruction* binop_left = binop->GetLeft();
-      HInstruction* binop_right = binop->GetRight();
-      // This is always true since the `HVecMul` has only one use (which is checked above).
-      DCHECK_NE(binop_left, binop_right);
-      if (binop_right == mul) {
-        accumulator = binop_left;
-      } else if (use->IsVecAdd()) {
-        DCHECK_EQ(binop_left, mul);
-        accumulator = binop_right;
-      }
-
-      HInstruction::InstructionKind kind =
-          use->IsVecAdd() ? HInstruction::kAdd : HInstruction::kSub;
-      if (accumulator != nullptr) {
-        HVecMultiplyAccumulate* mulacc =
-            new (allocator) HVecMultiplyAccumulate(allocator,
-                                                   kind,
-                                                   accumulator,
-                                                   mul->GetLeft(),
-                                                   mul->GetRight(),
-                                                   binop->GetPackedType(),
-                                                   binop->GetVectorLength(),
-                                                   binop->GetDexPc());
-
-        binop->GetBlock()->ReplaceAndRemoveInstructionWith(binop, mulacc);
-        DCHECK(!mul->HasUses());
-        mul->GetBlock()->RemoveInstruction(mul);
-        return true;
-      }
-    }
+  if (!mul->HasOnlyOneNonEnvironmentUse()) {
+    return false;
+  }
+  HInstruction* binop = mul->GetUses().front().GetUser();
+  if (!binop->IsVecAdd() && !binop->IsVecSub()) {
+    return false;
   }
 
-  return false;
+  // Replace code looking like
+  //    VECMUL tmp, x, y
+  //    VECADD/SUB dst, acc, tmp
+  // with
+  //    VECMULACC dst, acc, x, y
+  // Note that we do not want to (unconditionally) perform the merge when the
+  // multiplication has multiple uses and it can be merged in all of them.
+  // Multiple uses could happen on the same control-flow path, and we would
+  // then increase the amount of work. In the future we could try to evaluate
+  // whether all uses are on different control-flow paths (using dominance and
+  // reverse-dominance information) and only perform the merge when they are.
+  HInstruction* accumulator = nullptr;
+  HVecBinaryOperation* vec_binop = binop->AsVecBinaryOperation();
+  HInstruction* binop_left = vec_binop->GetLeft();
+  HInstruction* binop_right = vec_binop->GetRight();
+  // This is always true since the `HVecMul` has only one use (which is checked above).
+  DCHECK_NE(binop_left, binop_right);
+  if (binop_right == mul) {
+    accumulator = binop_left;
+  } else {
+    DCHECK_EQ(binop_left, mul);
+    // Only addition is commutative.
+    if (!binop->IsVecAdd()) {
+      return false;
+    }
+    accumulator = binop_right;
+  }
+
+  DCHECK(accumulator != nullptr);
+  HInstruction::InstructionKind kind =
+      binop->IsVecAdd() ? HInstruction::kAdd : HInstruction::kSub;
+
+  bool predicated_simd = vec_binop->IsPredicated();
+  if (predicated_simd && !HVecOperation::HaveSamePredicate(vec_binop, mul)) {
+    return false;
+  }
+
+  HVecMultiplyAccumulate* mulacc =
+      new (allocator) HVecMultiplyAccumulate(allocator,
+                                             kind,
+                                             accumulator,
+                                             mul->GetLeft(),
+                                             mul->GetRight(),
+                                             vec_binop->GetPackedType(),
+                                             vec_binop->GetVectorLength(),
+                                             vec_binop->GetDexPc());
+
+
+
+  vec_binop->GetBlock()->ReplaceAndRemoveInstructionWith(vec_binop, mulacc);
+  if (predicated_simd) {
+    mulacc->SetGoverningPredicate(vec_binop->GetGoverningPredicate(),
+                                  vec_binop->GetPredicationKind());
+  }
+
+  DCHECK(!mul->HasUses());
+  mul->GetBlock()->RemoveInstruction(mul);
+  return true;
 }
 
 void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) {
@@ -587,7 +611,16 @@
 
   if (!class_rti.IsValid()) {
     // Happens when the loaded class is unresolved.
-    return false;
+    if (obj_rti.IsExact()) {
+      // outcome == 'true' && obj_rti is valid implies that class_rti is valid.
+      // Since that's a contradiction we must not pass this check.
+      *outcome = false;
+      return true;
+    } else {
+      // We aren't able to say anything in particular since we don't know the
+      // exact type of the object.
+      return false;
+    }
   }
   DCHECK(class_rti.IsExact());
   if (class_rti.IsSupertypeOf(obj_rti)) {
@@ -609,12 +642,6 @@
 
 void InstructionSimplifierVisitor::VisitCheckCast(HCheckCast* check_cast) {
   HInstruction* object = check_cast->InputAt(0);
-  if (check_cast->GetTypeCheckKind() != TypeCheckKind::kBitstringCheck &&
-      check_cast->GetTargetClass()->NeedsAccessCheck()) {
-    // If we need to perform an access check we cannot remove the instruction.
-    return;
-  }
-
   if (CanEnsureNotNullAt(object, check_cast)) {
     check_cast->ClearMustDoNullCheck();
   }
@@ -625,6 +652,11 @@
     return;
   }
 
+  // Minor correctness check.
+  DCHECK(check_cast->GetTargetClass()->StrictlyDominates(check_cast))
+      << "Illegal graph!\n"
+      << check_cast->DumpWithArgs();
+
   // Historical note: The `outcome` was initialized to please Valgrind - the compiler can reorder
   // the return value check with the `outcome` check, b/27651442.
   bool outcome = false;
@@ -634,27 +666,23 @@
       MaybeRecordStat(stats_, MethodCompilationStat::kRemovedCheckedCast);
       if (check_cast->GetTypeCheckKind() != TypeCheckKind::kBitstringCheck) {
         HLoadClass* load_class = check_cast->GetTargetClass();
-        if (!load_class->HasUses()) {
+        if (!load_class->HasUses() && !load_class->NeedsAccessCheck()) {
           // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
-          // However, here we know that it cannot because the checkcast was successfull, hence
+          // However, here we know that it cannot because the checkcast was successful, hence
           // the class was already loaded.
           load_class->GetBlock()->RemoveInstruction(load_class);
         }
       }
     } else {
-      // Don't do anything for exceptional cases for now. Ideally we should remove
-      // all instructions and blocks this instruction dominates.
+      // TODO Don't do anything for exceptional cases for now. Ideally we should
+      // remove all instructions and blocks this instruction dominates and
+      // replace it with a manual throw.
     }
   }
 }
 
 void InstructionSimplifierVisitor::VisitInstanceOf(HInstanceOf* instruction) {
   HInstruction* object = instruction->InputAt(0);
-  if (instruction->GetTypeCheckKind() != TypeCheckKind::kBitstringCheck &&
-      instruction->GetTargetClass()->NeedsAccessCheck()) {
-    // If we need to perform an access check we cannot remove the instruction.
-    return;
-  }
 
   bool can_be_null = true;
   if (CanEnsureNotNullAt(object, instruction)) {
@@ -671,6 +699,11 @@
     return;
   }
 
+  // Minor correctness check.
+  DCHECK(instruction->GetTargetClass()->StrictlyDominates(instruction))
+      << "Illegal graph!\n"
+      << instruction->DumpWithArgs();
+
   // Historical note: The `outcome` was initialized to please Valgrind - the compiler can reorder
   // the return value check with the `outcome` check, b/27651442.
   bool outcome = false;
@@ -689,10 +722,11 @@
     instruction->GetBlock()->RemoveInstruction(instruction);
     if (outcome && instruction->GetTypeCheckKind() != TypeCheckKind::kBitstringCheck) {
       HLoadClass* load_class = instruction->GetTargetClass();
-      if (!load_class->HasUses()) {
-        // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
-        // However, here we know that it cannot because the instanceof check was successfull, hence
-        // the class was already loaded.
+      if (!load_class->HasUses() && !load_class->NeedsAccessCheck()) {
+        // We cannot rely on DCE to remove the class because the `HLoadClass`
+        // thinks it can throw. However, here we know that it cannot because the
+        // instanceof check was successful and we don't need to check the
+        // access, hence the class was already loaded.
         load_class->GetBlock()->RemoveInstruction(load_class);
       }
     }
@@ -909,6 +943,67 @@
   return nullptr;
 }
 
+// TODO This should really be done by LSE itself since there is significantly
+// more information available there.
+void InstructionSimplifierVisitor::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* pred_get) {
+  HInstruction* target = pred_get->GetTarget();
+  HInstruction* default_val = pred_get->GetDefaultValue();
+  if (target->IsNullConstant()) {
+    pred_get->ReplaceWith(default_val);
+    pred_get->GetBlock()->RemoveInstruction(pred_get);
+    RecordSimplification();
+    return;
+  } else if (!target->CanBeNull()) {
+    HInstruction* replace_with = new (GetGraph()->GetAllocator())
+        HInstanceFieldGet(pred_get->GetTarget(),
+                          pred_get->GetFieldInfo().GetField(),
+                          pred_get->GetFieldType(),
+                          pred_get->GetFieldOffset(),
+                          pred_get->IsVolatile(),
+                          pred_get->GetFieldInfo().GetFieldIndex(),
+                          pred_get->GetFieldInfo().GetDeclaringClassDefIndex(),
+                          pred_get->GetFieldInfo().GetDexFile(),
+                          pred_get->GetDexPc());
+    if (pred_get->GetType() == DataType::Type::kReference) {
+      replace_with->SetReferenceTypeInfo(pred_get->GetReferenceTypeInfo());
+    }
+    pred_get->GetBlock()->InsertInstructionBefore(replace_with, pred_get);
+    pred_get->ReplaceWith(replace_with);
+    pred_get->GetBlock()->RemoveInstruction(pred_get);
+    RecordSimplification();
+    return;
+  }
+  if (!target->IsPhi() || !default_val->IsPhi() || default_val->GetBlock() != target->GetBlock()) {
+    // The iget has already been reduced. We know the target or the phi
+    // selection will differ between the target and default.
+    return;
+  }
+  DCHECK_EQ(default_val->InputCount(), target->InputCount());
+  // In the same block both phis only one non-null we can remove the phi from default_val.
+  HInstruction* single_value = nullptr;
+  auto inputs = target->GetInputs();
+  for (auto [input, idx] : ZipCount(MakeIterationRange(inputs))) {
+    if (input->CanBeNull()) {
+      if (single_value == nullptr) {
+        single_value = default_val->InputAt(idx);
+      } else if (single_value != default_val->InputAt(idx) &&
+                 !single_value->Equals(default_val->InputAt(idx))) {
+        // Multiple values are associated with potential nulls, can't combine.
+        return;
+      }
+    }
+  }
+  DCHECK(single_value != nullptr) << "All target values are non-null but the phi as a whole still"
+                                  << " can be null? This should not be possible." << std::endl
+                                  << pred_get->DumpWithArgs();
+  if (single_value->StrictlyDominates(pred_get)) {
+    // Combine all the maybe null values into one.
+    pred_get->ReplaceInput(single_value, 0);
+    RecordSimplification();
+  }
+}
+
 void InstructionSimplifierVisitor::VisitSelect(HSelect* select) {
   HInstruction* replace_with = nullptr;
   HInstruction* condition = select->GetCondition();
@@ -1092,6 +1187,9 @@
   if (maybe_get->IsInstanceFieldGet()) {
     maybe_get->AsInstanceFieldGet()->SetType(new_type);
     return true;
+  } else if (maybe_get->IsPredicatedInstanceFieldGet()) {
+    maybe_get->AsPredicatedInstanceFieldGet()->SetType(new_type);
+    return true;
   } else if (maybe_get->IsStaticFieldGet()) {
     maybe_get->AsStaticFieldGet()->SetType(new_type);
     return true;
@@ -1698,6 +1796,71 @@
   }
 }
 
+
+// Search HDiv having the specified dividend and divisor which is in the specified basic block.
+// Return nullptr if nothing has been found.
+static HInstruction* FindDivWithInputsInBasicBlock(HInstruction* dividend,
+                                                   HInstruction* divisor,
+                                                   HBasicBlock* basic_block) {
+  for (const HUseListNode<HInstruction*>& use : dividend->GetUses()) {
+    HInstruction* user = use.GetUser();
+    if (user->GetBlock() == basic_block && user->IsDiv() && user->InputAt(1) == divisor) {
+      return user;
+    }
+  }
+  return nullptr;
+}
+
+// If there is Div with the same inputs as Rem and in the same basic block, it can be reused.
+// Rem is replaced with Mul+Sub which use the found Div.
+void InstructionSimplifierVisitor::TryToReuseDiv(HRem* rem) {
+  // As the optimization replaces Rem with Mul+Sub they prevent some loop optimizations
+  // if the Rem is in a loop.
+  // Check if it is allowed to optimize such Rems.
+  if (rem->IsInLoop() && be_loop_friendly_) {
+    return;
+  }
+  DataType::Type type = rem->GetResultType();
+  if (!DataType::IsIntOrLongType(type)) {
+    return;
+  }
+
+  HBasicBlock* basic_block = rem->GetBlock();
+  HInstruction* dividend = rem->GetLeft();
+  HInstruction* divisor = rem->GetRight();
+
+  if (divisor->IsConstant()) {
+    HConstant* input_cst = rem->GetConstantRight();
+    DCHECK(input_cst->IsIntConstant() || input_cst->IsLongConstant());
+    int64_t cst_value = Int64FromConstant(input_cst);
+    if (cst_value == std::numeric_limits<int64_t>::min() || IsPowerOfTwo(std::abs(cst_value))) {
+      // Such cases are usually handled in the code generator because they don't need Div at all.
+      return;
+    }
+  }
+
+  HInstruction* quotient = FindDivWithInputsInBasicBlock(dividend, divisor, basic_block);
+  if (quotient == nullptr) {
+    return;
+  }
+  if (!quotient->StrictlyDominates(rem)) {
+    quotient->MoveBefore(rem);
+  }
+
+  ArenaAllocator* allocator = GetGraph()->GetAllocator();
+  HInstruction* mul = new (allocator) HMul(type, quotient, divisor);
+  basic_block->InsertInstructionBefore(mul, rem);
+  HInstruction* sub = new (allocator) HSub(type, dividend, mul);
+  basic_block->InsertInstructionBefore(sub, rem);
+  rem->ReplaceWith(sub);
+  basic_block->RemoveInstruction(rem);
+  RecordSimplification();
+}
+
+void InstructionSimplifierVisitor::VisitRem(HRem* rem) {
+  TryToReuseDiv(rem);
+}
+
 void InstructionSimplifierVisitor::VisitMul(HMul* instruction) {
   HConstant* input_cst = instruction->GetConstantRight();
   HInstruction* input_other = instruction->GetLeastConstantLeft();
@@ -2127,34 +2290,6 @@
   }
 }
 
-void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke,
-                                                  bool is_left,
-                                                  DataType::Type type) {
-  DCHECK(invoke->IsInvokeStaticOrDirect());
-  DCHECK_EQ(invoke->GetInvokeType(), InvokeType::kStatic);
-  HInstruction* value = invoke->InputAt(0);
-  HInstruction* distance = invoke->InputAt(1);
-  // Replace the invoke with an HRor.
-  if (is_left) {
-    // Unconditionally set the type of the negated distance to `int`,
-    // as shift and rotate operations expect a 32-bit (or narrower)
-    // value for their distance input.
-    distance = new (GetGraph()->GetAllocator()) HNeg(DataType::Type::kInt32, distance);
-    invoke->GetBlock()->InsertInstructionBefore(distance, invoke);
-  }
-  HRor* ror = new (GetGraph()->GetAllocator()) HRor(type, value, distance);
-  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, ror);
-  // Remove ClinitCheck and LoadClass, if possible.
-  HInstruction* clinit = invoke->GetInputs().back();
-  if (clinit->IsClinitCheck() && !clinit->HasUses()) {
-    clinit->GetBlock()->RemoveInstruction(clinit);
-    HInstruction* ldclass = clinit->InputAt(0);
-    if (ldclass->IsLoadClass() && !ldclass->HasUses()) {
-      ldclass->GetBlock()->RemoveInstruction(ldclass);
-    }
-  }
-}
-
 static bool IsArrayLengthOf(HInstruction* potential_length, HInstruction* potential_array) {
   if (potential_length->IsArrayLength()) {
     return potential_length->InputAt(0) == potential_array;
@@ -2267,40 +2402,15 @@
       // the invoke, as we would need to look it up in the current dex file, and it
       // is unlikely that it exists. The most usual situation for such typed
       // arraycopy methods is a direct pointer to the boot image.
-      invoke->SetDispatchInfo(HSharpening::SharpenInvokeStaticOrDirect(method, codegen_));
+      invoke->SetDispatchInfo(HSharpening::SharpenLoadMethod(
+          method,
+          /* has_method_id= */ true,
+          /* for_interface_call= */ false,
+          codegen_));
     }
   }
 }
 
-void InstructionSimplifierVisitor::SimplifyCompare(HInvoke* invoke,
-                                                   bool is_signum,
-                                                   DataType::Type type) {
-  DCHECK(invoke->IsInvokeStaticOrDirect());
-  uint32_t dex_pc = invoke->GetDexPc();
-  HInstruction* left = invoke->InputAt(0);
-  HInstruction* right;
-  if (!is_signum) {
-    right = invoke->InputAt(1);
-  } else if (type == DataType::Type::kInt64) {
-    right = GetGraph()->GetLongConstant(0);
-  } else {
-    right = GetGraph()->GetIntConstant(0);
-  }
-  HCompare* compare = new (GetGraph()->GetAllocator())
-      HCompare(type, left, right, ComparisonBias::kNoBias, dex_pc);
-  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, compare);
-}
-
-void InstructionSimplifierVisitor::SimplifyIsNaN(HInvoke* invoke) {
-  DCHECK(invoke->IsInvokeStaticOrDirect());
-  uint32_t dex_pc = invoke->GetDexPc();
-  // IsNaN(x) is the same as x != x.
-  HInstruction* x = invoke->InputAt(0);
-  HCondition* condition = new (GetGraph()->GetAllocator()) HNotEqual(x, x, dex_pc);
-  condition->SetBias(ComparisonBias::kLtBias);
-  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, condition);
-}
-
 void InstructionSimplifierVisitor::SimplifyFP2Int(HInvoke* invoke) {
   DCHECK(invoke->IsInvokeStaticOrDirect());
   uint32_t dex_pc = invoke->GetDexPc();
@@ -2311,14 +2421,14 @@
   if (type == DataType::Type::kFloat64) {
     nan = GetGraph()->GetLongConstant(0x7ff8000000000000L);
     invoke->SetIntrinsic(Intrinsics::kDoubleDoubleToRawLongBits,
-                         kNeedsEnvironmentOrCache,
+                         kNeedsEnvironment,
                          kNoSideEffects,
                          kNoThrow);
   } else {
     DCHECK_EQ(type, DataType::Type::kFloat32);
     nan = GetGraph()->GetIntConstant(0x7fc00000);
     invoke->SetIntrinsic(Intrinsics::kFloatFloatToRawIntBits,
-                         kNeedsEnvironmentOrCache,
+                         kNeedsEnvironment,
                          kNoSideEffects,
                          kNoThrow);
   }
@@ -2355,25 +2465,14 @@
   GetGraph()->SetHasBoundsChecks(true);
 }
 
-void InstructionSimplifierVisitor::SimplifyStringIsEmptyOrLength(HInvoke* invoke) {
+void InstructionSimplifierVisitor::SimplifyStringLength(HInvoke* invoke) {
   HInstruction* str = invoke->InputAt(0);
   uint32_t dex_pc = invoke->GetDexPc();
   // We treat String as an array to allow DCE and BCE to seamlessly work on strings,
   // so create the HArrayLength.
   HArrayLength* length =
       new (GetGraph()->GetAllocator()) HArrayLength(str, dex_pc, /* is_string_length= */ true);
-  HInstruction* replacement;
-  if (invoke->GetIntrinsic() == Intrinsics::kStringIsEmpty) {
-    // For String.isEmpty(), create the `HEqual` representing the `length == 0`.
-    invoke->GetBlock()->InsertInstructionBefore(length, invoke);
-    HIntConstant* zero = GetGraph()->GetIntConstant(0);
-    HEqual* equal = new (GetGraph()->GetAllocator()) HEqual(length, zero, dex_pc);
-    replacement = equal;
-  } else {
-    DCHECK_EQ(invoke->GetIntrinsic(), Intrinsics::kStringLength);
-    replacement = length;
-  }
-  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, replacement);
+  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, length);
 }
 
 void InstructionSimplifierVisitor::SimplifyStringIndexOf(HInvoke* invoke) {
@@ -2663,35 +2762,6 @@
   }
 }
 
-void InstructionSimplifierVisitor::SimplifyMemBarrier(HInvoke* invoke,
-                                                      MemBarrierKind barrier_kind) {
-  uint32_t dex_pc = invoke->GetDexPc();
-  HMemoryBarrier* mem_barrier =
-      new (GetGraph()->GetAllocator()) HMemoryBarrier(barrier_kind, dex_pc);
-  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, mem_barrier);
-}
-
-void InstructionSimplifierVisitor::SimplifyMin(HInvoke* invoke, DataType::Type type) {
-  DCHECK(invoke->IsInvokeStaticOrDirect());
-  HMin* min = new (GetGraph()->GetAllocator())
-      HMin(type, invoke->InputAt(0), invoke->InputAt(1), invoke->GetDexPc());
-  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, min);
-}
-
-void InstructionSimplifierVisitor::SimplifyMax(HInvoke* invoke, DataType::Type type) {
-  DCHECK(invoke->IsInvokeStaticOrDirect());
-  HMax* max = new (GetGraph()->GetAllocator())
-      HMax(type, invoke->InputAt(0), invoke->InputAt(1), invoke->GetDexPc());
-  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, max);
-}
-
-void InstructionSimplifierVisitor::SimplifyAbs(HInvoke* invoke, DataType::Type type) {
-  DCHECK(invoke->IsInvokeStaticOrDirect());
-  HAbs* abs = new (GetGraph()->GetAllocator())
-      HAbs(type, invoke->InputAt(0), invoke->GetDexPc());
-  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, abs);
-}
-
 void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) {
   switch (instruction->GetIntrinsic()) {
     case Intrinsics::kStringEquals:
@@ -2700,44 +2770,19 @@
     case Intrinsics::kSystemArrayCopy:
       SimplifySystemArrayCopy(instruction);
       break;
-    case Intrinsics::kIntegerRotateRight:
-      SimplifyRotate(instruction, /* is_left= */ false, DataType::Type::kInt32);
-      break;
-    case Intrinsics::kLongRotateRight:
-      SimplifyRotate(instruction, /* is_left= */ false, DataType::Type::kInt64);
-      break;
-    case Intrinsics::kIntegerRotateLeft:
-      SimplifyRotate(instruction, /* is_left= */ true, DataType::Type::kInt32);
-      break;
-    case Intrinsics::kLongRotateLeft:
-      SimplifyRotate(instruction, /* is_left= */ true, DataType::Type::kInt64);
-      break;
-    case Intrinsics::kIntegerCompare:
-      SimplifyCompare(instruction, /* is_signum= */ false, DataType::Type::kInt32);
-      break;
-    case Intrinsics::kLongCompare:
-      SimplifyCompare(instruction, /* is_signum= */ false, DataType::Type::kInt64);
-      break;
-    case Intrinsics::kIntegerSignum:
-      SimplifyCompare(instruction, /* is_signum= */ true, DataType::Type::kInt32);
-      break;
-    case Intrinsics::kLongSignum:
-      SimplifyCompare(instruction, /* is_signum= */ true, DataType::Type::kInt64);
-      break;
-    case Intrinsics::kFloatIsNaN:
-    case Intrinsics::kDoubleIsNaN:
-      SimplifyIsNaN(instruction);
-      break;
     case Intrinsics::kFloatFloatToIntBits:
     case Intrinsics::kDoubleDoubleToLongBits:
       SimplifyFP2Int(instruction);
       break;
     case Intrinsics::kStringCharAt:
+      // Instruction builder creates intermediate representation directly
+      // but the inliner can sharpen CharSequence.charAt() to String.charAt().
       SimplifyStringCharAt(instruction);
       break;
-    case Intrinsics::kStringIsEmpty:
     case Intrinsics::kStringLength:
-      SimplifyStringIsEmptyOrLength(instruction);
+      // Instruction builder creates intermediate representation directly
+      // but the inliner can sharpen CharSequence.length() to String.length().
+      SimplifyStringLength(instruction);
       break;
     case Intrinsics::kStringIndexOf:
     case Intrinsics::kStringIndexOfAfter:
@@ -2764,66 +2809,40 @@
     case Intrinsics::kStringBuilderToString:
       SimplifyAllocationIntrinsic(instruction);
       break;
+    case Intrinsics::kIntegerRotateRight:
+    case Intrinsics::kLongRotateRight:
+    case Intrinsics::kIntegerRotateLeft:
+    case Intrinsics::kLongRotateLeft:
+    case Intrinsics::kIntegerCompare:
+    case Intrinsics::kLongCompare:
+    case Intrinsics::kIntegerSignum:
+    case Intrinsics::kLongSignum:
+    case Intrinsics::kFloatIsNaN:
+    case Intrinsics::kDoubleIsNaN:
+    case Intrinsics::kStringIsEmpty:
     case Intrinsics::kUnsafeLoadFence:
-      SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny);
-      break;
     case Intrinsics::kUnsafeStoreFence:
-      SimplifyMemBarrier(instruction, MemBarrierKind::kAnyStore);
-      break;
     case Intrinsics::kUnsafeFullFence:
-      SimplifyMemBarrier(instruction, MemBarrierKind::kAnyAny);
-      break;
     case Intrinsics::kVarHandleFullFence:
-      SimplifyMemBarrier(instruction, MemBarrierKind::kAnyAny);
-      break;
     case Intrinsics::kVarHandleAcquireFence:
-      SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny);
-      break;
     case Intrinsics::kVarHandleReleaseFence:
-      SimplifyMemBarrier(instruction, MemBarrierKind::kAnyStore);
-      break;
     case Intrinsics::kVarHandleLoadLoadFence:
-      SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny);
-      break;
     case Intrinsics::kVarHandleStoreStoreFence:
-      SimplifyMemBarrier(instruction, MemBarrierKind::kStoreStore);
-      break;
     case Intrinsics::kMathMinIntInt:
-      SimplifyMin(instruction, DataType::Type::kInt32);
-      break;
     case Intrinsics::kMathMinLongLong:
-      SimplifyMin(instruction, DataType::Type::kInt64);
-      break;
     case Intrinsics::kMathMinFloatFloat:
-      SimplifyMin(instruction, DataType::Type::kFloat32);
-      break;
     case Intrinsics::kMathMinDoubleDouble:
-      SimplifyMin(instruction, DataType::Type::kFloat64);
-      break;
     case Intrinsics::kMathMaxIntInt:
-      SimplifyMax(instruction, DataType::Type::kInt32);
-      break;
     case Intrinsics::kMathMaxLongLong:
-      SimplifyMax(instruction, DataType::Type::kInt64);
-      break;
     case Intrinsics::kMathMaxFloatFloat:
-      SimplifyMax(instruction, DataType::Type::kFloat32);
-      break;
     case Intrinsics::kMathMaxDoubleDouble:
-      SimplifyMax(instruction, DataType::Type::kFloat64);
-      break;
     case Intrinsics::kMathAbsInt:
-      SimplifyAbs(instruction, DataType::Type::kInt32);
-      break;
     case Intrinsics::kMathAbsLong:
-      SimplifyAbs(instruction, DataType::Type::kInt64);
-      break;
     case Intrinsics::kMathAbsFloat:
-      SimplifyAbs(instruction, DataType::Type::kFloat32);
-      break;
     case Intrinsics::kMathAbsDouble:
-      SimplifyAbs(instruction, DataType::Type::kFloat64);
-      break;
+      // These are replaced by intermediate representation in the instruction builder.
+      LOG(FATAL) << "Unexpected " << static_cast<Intrinsics>(instruction->GetIntrinsic());
+      UNREACHABLE();
     default:
       break;
   }
diff --git a/compiler/optimizing/instruction_simplifier.h b/compiler/optimizing/instruction_simplifier.h
index 982a24a..feea771 100644
--- a/compiler/optimizing/instruction_simplifier.h
+++ b/compiler/optimizing/instruction_simplifier.h
@@ -40,9 +40,11 @@
   InstructionSimplifier(HGraph* graph,
                         CodeGenerator* codegen,
                         OptimizingCompilerStats* stats = nullptr,
-                        const char* name = kInstructionSimplifierPassName)
+                        const char* name = kInstructionSimplifierPassName,
+                        bool use_all_optimizations = false)
       : HOptimization(graph, name, stats),
-        codegen_(codegen) {}
+        codegen_(codegen),
+        use_all_optimizations_(use_all_optimizations) {}
 
   static constexpr const char* kInstructionSimplifierPassName = "instruction_simplifier";
 
@@ -51,6 +53,9 @@
  private:
   CodeGenerator* codegen_;
 
+  // Use all optimizations without restrictions.
+  bool use_all_optimizations_;
+
   DISALLOW_COPY_AND_ASSIGN(InstructionSimplifier);
 };
 
diff --git a/compiler/optimizing/instruction_simplifier_arm.cc b/compiler/optimizing/instruction_simplifier_arm.cc
index 01e9cff..1371ea7 100644
--- a/compiler/optimizing/instruction_simplifier_arm.cc
+++ b/compiler/optimizing/instruction_simplifier_arm.cc
@@ -27,6 +27,7 @@
 
 using helpers::CanFitInShifterOperand;
 using helpers::HasShifterOperand;
+using helpers::IsSubRightSubLeftShl;
 
 namespace arm {
 
@@ -73,6 +74,7 @@
   void VisitOr(HOr* instruction) override;
   void VisitShl(HShl* instruction) override;
   void VisitShr(HShr* instruction) override;
+  void VisitSub(HSub* instruction) override;
   void VisitTypeConversion(HTypeConversion* instruction) override;
   void VisitUShr(HUShr* instruction) override;
 
@@ -268,6 +270,15 @@
   }
 }
 
+void InstructionSimplifierArmVisitor::VisitSub(HSub* instruction) {
+  if (IsSubRightSubLeftShl(instruction)) {
+    HInstruction* shl = instruction->GetRight()->InputAt(0);
+    if (shl->InputAt(1)->IsConstant() && TryReplaceSubSubWithSubAdd(instruction)) {
+      TryMergeIntoUsersShifterOperand(shl);
+    }
+  }
+}
+
 void InstructionSimplifierArmVisitor::VisitTypeConversion(HTypeConversion* instruction) {
   DataType::Type result_type = instruction->GetResultType();
   DataType::Type input_type = instruction->GetInputType();
diff --git a/compiler/optimizing/instruction_simplifier_arm64.cc b/compiler/optimizing/instruction_simplifier_arm64.cc
index e23decb..ff0859b 100644
--- a/compiler/optimizing/instruction_simplifier_arm64.cc
+++ b/compiler/optimizing/instruction_simplifier_arm64.cc
@@ -25,6 +25,7 @@
 
 using helpers::CanFitInShifterOperand;
 using helpers::HasShifterOperand;
+using helpers::IsSubRightSubLeftShl;
 
 namespace arm64 {
 
@@ -76,6 +77,7 @@
   void VisitOr(HOr* instruction) override;
   void VisitShl(HShl* instruction) override;
   void VisitShr(HShr* instruction) override;
+  void VisitSub(HSub* instruction) override;
   void VisitTypeConversion(HTypeConversion* instruction) override;
   void VisitUShr(HUShr* instruction) override;
   void VisitXor(HXor* instruction) override;
@@ -239,6 +241,15 @@
   }
 }
 
+void InstructionSimplifierArm64Visitor::VisitSub(HSub* instruction) {
+  if (IsSubRightSubLeftShl(instruction)) {
+    HInstruction* shl = instruction->GetRight()->InputAt(0);
+    if (shl->InputAt(1)->IsConstant() && TryReplaceSubSubWithSubAdd(instruction)) {
+      TryMergeIntoUsersShifterOperand(shl);
+    }
+  }
+}
+
 void InstructionSimplifierArm64Visitor::VisitTypeConversion(HTypeConversion* instruction) {
   DataType::Type result_type = instruction->GetResultType();
   DataType::Type input_type = instruction->GetInputType();
@@ -266,14 +277,17 @@
 }
 
 void InstructionSimplifierArm64Visitor::VisitVecLoad(HVecLoad* instruction) {
-  if (!instruction->IsStringCharAt()
-      && TryExtractVecArrayAccessAddress(instruction, instruction->GetIndex())) {
+  // TODO: Extract regular HIntermediateAddress.
+  if (!instruction->IsPredicated() && !instruction->IsStringCharAt() &&
+      TryExtractVecArrayAccessAddress(instruction, instruction->GetIndex())) {
     RecordSimplification();
   }
 }
 
 void InstructionSimplifierArm64Visitor::VisitVecStore(HVecStore* instruction) {
-  if (TryExtractVecArrayAccessAddress(instruction, instruction->GetIndex())) {
+  // TODO: Extract regular HIntermediateAddress.
+  if (!instruction->IsPredicated() &&
+      TryExtractVecArrayAccessAddress(instruction, instruction->GetIndex())) {
     RecordSimplification();
   }
 }
diff --git a/compiler/optimizing/instruction_simplifier_shared.cc b/compiler/optimizing/instruction_simplifier_shared.cc
index 0f30f66..dc60ba6 100644
--- a/compiler/optimizing/instruction_simplifier_shared.cc
+++ b/compiler/optimizing/instruction_simplifier_shared.cc
@@ -336,4 +336,26 @@
   return true;
 }
 
+bool TryReplaceSubSubWithSubAdd(HSub* last_sub) {
+  DCHECK(last_sub->GetRight()->IsSub());
+  HBasicBlock* basic_block = last_sub->GetBlock();
+  ArenaAllocator* allocator = basic_block->GetGraph()->GetAllocator();
+  HInstruction* last_sub_right = last_sub->GetRight();
+  HInstruction* last_sub_left = last_sub->GetLeft();
+  if (last_sub_right->GetUses().HasExactlyOneElement()) {
+    // Reorder operands of last_sub_right: Sub(a, b) -> Sub(b, a).
+    HInstruction* a = last_sub_right->InputAt(0);
+    HInstruction* b = last_sub_right->InputAt(1);
+    last_sub_right->ReplaceInput(b, 0);
+    last_sub_right->ReplaceInput(a, 1);
+
+    // Replace Sub(c, Sub(a, b)) with Add(c, Sub(b, a).
+    HAdd* add = new (allocator) HAdd(last_sub->GetType(), last_sub_left, last_sub_right);
+    basic_block->ReplaceAndRemoveInstructionWith(last_sub, add);
+    return true;
+  } else {
+    return false;
+  }
+}
+
 }  // namespace art
diff --git a/compiler/optimizing/instruction_simplifier_shared.h b/compiler/optimizing/instruction_simplifier_shared.h
index 758fc76..876ed21 100644
--- a/compiler/optimizing/instruction_simplifier_shared.h
+++ b/compiler/optimizing/instruction_simplifier_shared.h
@@ -47,6 +47,15 @@
   return res;
 }
 
+// Check the specified sub is the last operation of the sequence:
+//   t1 = Shl
+//   t2 = Sub(t1, *)
+//   t3 = Sub(*, t2)
+inline bool IsSubRightSubLeftShl(HSub *sub) {
+  HInstruction* right = sub->GetRight();
+  return right->IsSub() && right->AsSub()->GetLeft()->IsShl();;
+}
+
 }  // namespace helpers
 
 bool TryCombineMultiplyAccumulate(HMul* mul, InstructionSet isa);
@@ -61,6 +70,12 @@
 
 bool TryExtractVecArrayAccessAddress(HVecMemoryOperation* access, HInstruction* index);
 
+// Try to replace
+//   Sub(c, Sub(a, b))
+// with
+//   Add(c, Sub(b, a))
+bool TryReplaceSubSubWithSubAdd(HSub* last_sub);
+
 }  // namespace art
 
 #endif  // ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_SHARED_H_
diff --git a/compiler/optimizing/instruction_simplifier_test.cc b/compiler/optimizing/instruction_simplifier_test.cc
new file mode 100644
index 0000000..2063eed
--- /dev/null
+++ b/compiler/optimizing/instruction_simplifier_test.cc
@@ -0,0 +1,561 @@
+/*
+ * Copyright (C) 2021 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 "instruction_simplifier.h"
+
+#include <initializer_list>
+#include <tuple>
+
+#include "gtest/gtest.h"
+
+#include "class_root-inl.h"
+#include "nodes.h"
+#include "optimizing/data_type.h"
+#include "optimizing_unit_test.h"
+
+namespace art {
+
+namespace mirror {
+class ClassExt;
+class Throwable;
+}  // namespace mirror
+
+template<typename SuperClass>
+class InstructionSimplifierTestBase : public SuperClass, public OptimizingUnitTestHelper {
+ public:
+  void SetUp() override {
+    SuperClass::SetUp();
+    gLogVerbosity.compiler = true;
+  }
+
+  void TearDown() override {
+    SuperClass::TearDown();
+    gLogVerbosity.compiler = false;
+  }
+};
+
+class InstructionSimplifierTest : public InstructionSimplifierTestBase<CommonCompilerTest> {};
+
+// Various configs we can use for testing. Currently used in PartialComparison tests.
+enum class InstanceOfKind {
+  kSelf,
+  kUnrelatedLoaded,
+  kUnrelatedUnloaded,
+  kSupertype,
+};
+
+std::ostream& operator<<(std::ostream& os, const InstanceOfKind& comp) {
+  switch (comp) {
+    case InstanceOfKind::kSupertype:
+      return os << "kSupertype";
+    case InstanceOfKind::kSelf:
+      return os << "kSelf";
+    case InstanceOfKind::kUnrelatedLoaded:
+      return os << "kUnrelatedLoaded";
+    case InstanceOfKind::kUnrelatedUnloaded:
+      return os << "kUnrelatedUnloaded";
+  }
+}
+
+class InstanceOfInstructionSimplifierTestGroup
+    : public InstructionSimplifierTestBase<CommonCompilerTestWithParam<InstanceOfKind>> {
+ public:
+  bool GetConstantResult() const {
+    switch (GetParam()) {
+      case InstanceOfKind::kSupertype:
+      case InstanceOfKind::kSelf:
+        return true;
+      case InstanceOfKind::kUnrelatedLoaded:
+      case InstanceOfKind::kUnrelatedUnloaded:
+        return false;
+    }
+  }
+
+  std::pair<HLoadClass*, HLoadClass*> GetLoadClasses(VariableSizedHandleScope* vshs) {
+    InstanceOfKind kind = GetParam();
+    ScopedObjectAccess soa(Thread::Current());
+    // New inst always needs to have a valid rti since we dcheck that.
+    HLoadClass* new_inst = MakeClassLoad(
+        /* ti= */ std::nullopt, vshs->NewHandle<mirror::Class>(GetClassRoot<mirror::ClassExt>()));
+    new_inst->SetValidLoadedClassRTI();
+    if (kind == InstanceOfKind::kSelf) {
+      return {new_inst, new_inst};
+    }
+    if (kind == InstanceOfKind::kUnrelatedUnloaded) {
+      HLoadClass* target_class = MakeClassLoad();
+      EXPECT_FALSE(target_class->GetLoadedClassRTI().IsValid());
+      return {new_inst, target_class};
+    }
+    // Force both classes to be a real classes.
+    // For simplicity we use class-roots as the types. The new-inst will always
+    // be a ClassExt, unrelated-loaded will always be Throwable and super will
+    // always be Object
+    HLoadClass* target_class = MakeClassLoad(
+        /* ti= */ std::nullopt,
+        vshs->NewHandle<mirror::Class>(kind == InstanceOfKind::kSupertype ?
+                                           GetClassRoot<mirror::Object>() :
+                                           GetClassRoot<mirror::Throwable>()));
+    target_class->SetValidLoadedClassRTI();
+    EXPECT_TRUE(target_class->GetLoadedClassRTI().IsValid());
+    return {new_inst, target_class};
+  }
+};
+
+// // ENTRY
+// switch (param) {
+// case 1:
+//   obj1 = param2; break;
+// case 2:
+//   obj1 = param3; break;
+// default:
+//   obj2 = new Obj();
+// }
+// val_phi = PHI[3,4,10]
+// target_phi = PHI[param2, param3, obj2]
+// return PredFieldGet[val_phi, target_phi] => PredFieldGet[val_phi, target_phi]
+TEST_F(InstructionSimplifierTest, SimplifyPredicatedFieldGetNoMerge) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "case1"},
+                                                  {"entry", "case2"},
+                                                  {"entry", "case3"},
+                                                  {"case1", "breturn"},
+                                                  {"case2", "breturn"},
+                                                  {"case3", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(case1);
+  GET_BLOCK(case2);
+  GET_BLOCK(case3);
+  GET_BLOCK(breturn);
+#undef GET_BLOCK
+
+  HInstruction* bool_value = MakeParam(DataType::Type::kInt32);
+  HInstruction* obj1_param = MakeParam(DataType::Type::kReference);
+  HInstruction* obj2_param = MakeParam(DataType::Type::kReference);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c4 = graph_->GetIntConstant(4);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* switch_inst = new (GetAllocator()) HPackedSwitch(0, 2, bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(switch_inst);
+  ManuallyBuildEnvFor(cls, {});
+
+  HInstruction* goto_c1 = new (GetAllocator()) HGoto();
+  case1->AddInstruction(goto_c1);
+
+  HInstruction* goto_c2 = new (GetAllocator()) HGoto();
+  case2->AddInstruction(goto_c2);
+
+  HInstruction* obj3 = MakeNewInstance(cls);
+  HInstruction* goto_c3 = new (GetAllocator()) HGoto();
+  case3->AddInstruction(obj3);
+  case3->AddInstruction(goto_c3);
+
+  HPhi* val_phi = MakePhi({c3, c4, c10});
+  HPhi* obj_phi = MakePhi({obj1_param, obj2_param, obj3});
+  HPredicatedInstanceFieldGet* read_end =
+      new (GetAllocator()) HPredicatedInstanceFieldGet(obj_phi,
+                                                       nullptr,
+                                                       val_phi,
+                                                       val_phi->GetType(),
+                                                       MemberOffset(10),
+                                                       false,
+                                                       42,
+                                                       0,
+                                                       graph_->GetDexFile(),
+                                                       0);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_end);
+  breturn->AddPhi(val_phi);
+  breturn->AddPhi(obj_phi);
+  breturn->AddInstruction(read_end);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  LOG(INFO) << "Pre simplification " << blks;
+  graph_->ClearDominanceInformation();
+  graph_->BuildDominatorTree();
+  InstructionSimplifier simp(graph_, /*codegen=*/nullptr);
+  simp.Run();
+
+  LOG(INFO) << "Post simplify " << blks;
+
+  EXPECT_INS_RETAINED(read_end);
+
+  EXPECT_INS_EQ(read_end->GetTarget(), obj_phi);
+  EXPECT_INS_EQ(read_end->GetDefaultValue(), val_phi);
+}
+
+// // ENTRY
+// switch (param) {
+// case 1:
+//   obj1 = param2; break;
+// case 2:
+//   obj1 = param3; break;
+// default:
+//   obj2 = new Obj();
+// }
+// val_phi = PHI[3,3,10]
+// target_phi = PHI[param2, param3, obj2]
+// return PredFieldGet[val_phi, target_phi] => PredFieldGet[3, target_phi]
+TEST_F(InstructionSimplifierTest, SimplifyPredicatedFieldGetMerge) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "case1"},
+                                                  {"entry", "case2"},
+                                                  {"entry", "case3"},
+                                                  {"case1", "breturn"},
+                                                  {"case2", "breturn"},
+                                                  {"case3", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(case1);
+  GET_BLOCK(case2);
+  GET_BLOCK(case3);
+  GET_BLOCK(breturn);
+#undef GET_BLOCK
+
+  HInstruction* bool_value = MakeParam(DataType::Type::kInt32);
+  HInstruction* obj1_param = MakeParam(DataType::Type::kReference);
+  HInstruction* obj2_param = MakeParam(DataType::Type::kReference);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* switch_inst = new (GetAllocator()) HPackedSwitch(0, 2, bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(switch_inst);
+  ManuallyBuildEnvFor(cls, {});
+
+  HInstruction* goto_c1 = new (GetAllocator()) HGoto();
+  case1->AddInstruction(goto_c1);
+
+  HInstruction* goto_c2 = new (GetAllocator()) HGoto();
+  case2->AddInstruction(goto_c2);
+
+  HInstruction* obj3 = MakeNewInstance(cls);
+  HInstruction* goto_c3 = new (GetAllocator()) HGoto();
+  case3->AddInstruction(obj3);
+  case3->AddInstruction(goto_c3);
+
+  HPhi* val_phi = MakePhi({c3, c3, c10});
+  HPhi* obj_phi = MakePhi({obj1_param, obj2_param, obj3});
+  HPredicatedInstanceFieldGet* read_end =
+      new (GetAllocator()) HPredicatedInstanceFieldGet(obj_phi,
+                                                       nullptr,
+                                                       val_phi,
+                                                       val_phi->GetType(),
+                                                       MemberOffset(10),
+                                                       false,
+                                                       42,
+                                                       0,
+                                                       graph_->GetDexFile(),
+                                                       0);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_end);
+  breturn->AddPhi(val_phi);
+  breturn->AddPhi(obj_phi);
+  breturn->AddInstruction(read_end);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  LOG(INFO) << "Pre simplification " << blks;
+  graph_->ClearDominanceInformation();
+  graph_->BuildDominatorTree();
+  InstructionSimplifier simp(graph_, /*codegen=*/nullptr);
+  simp.Run();
+
+  LOG(INFO) << "Post simplify " << blks;
+
+  EXPECT_FALSE(obj3->CanBeNull());
+  EXPECT_INS_RETAINED(read_end);
+
+  EXPECT_INS_EQ(read_end->GetTarget(), obj_phi);
+  EXPECT_INS_EQ(read_end->GetDefaultValue(), c3);
+}
+
+// // ENTRY
+// if (param) {
+//   obj1 = new Obj();
+// } else {
+//   obj2 = new Obj();
+// }
+// val_phi = PHI[3,10]
+// target_phi = PHI[obj1, obj2]
+// return PredFieldGet[val_phi, target_phi] => FieldGet[target_phi]
+TEST_F(InstructionSimplifierTest, SimplifyPredicatedFieldGetNoNull) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(breturn);
+#undef GET_BLOCK
+
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+
+  HInstruction* obj1 = MakeNewInstance(cls);
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(obj1);
+  left->AddInstruction(goto_left);
+
+  HInstruction* obj2 = MakeNewInstance(cls);
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(obj2);
+  right->AddInstruction(goto_right);
+
+  HPhi* val_phi = MakePhi({c3, c10});
+  HPhi* obj_phi = MakePhi({obj1, obj2});
+  obj_phi->SetCanBeNull(false);
+  HInstruction* read_end = new (GetAllocator()) HPredicatedInstanceFieldGet(obj_phi,
+                                                                            nullptr,
+                                                                            val_phi,
+                                                                            val_phi->GetType(),
+                                                                            MemberOffset(10),
+                                                                            false,
+                                                                            42,
+                                                                            0,
+                                                                            graph_->GetDexFile(),
+                                                                            0);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_end);
+  breturn->AddPhi(val_phi);
+  breturn->AddPhi(obj_phi);
+  breturn->AddInstruction(read_end);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  LOG(INFO) << "Pre simplification " << blks;
+  graph_->ClearDominanceInformation();
+  graph_->BuildDominatorTree();
+  InstructionSimplifier simp(graph_, /*codegen=*/nullptr);
+  simp.Run();
+
+  LOG(INFO) << "Post simplify " << blks;
+
+  EXPECT_FALSE(obj1->CanBeNull());
+  EXPECT_FALSE(obj2->CanBeNull());
+  EXPECT_INS_REMOVED(read_end);
+
+  HInstanceFieldGet* ifget = FindSingleInstruction<HInstanceFieldGet>(graph_, breturn);
+  ASSERT_NE(ifget, nullptr);
+  EXPECT_INS_EQ(ifget->InputAt(0), obj_phi);
+}
+
+// // ENTRY
+// obj = new Obj();
+// // Make sure this graph isn't broken
+// if (obj instanceof <other>) {
+//   // LEFT
+// } else {
+//   // RIGHT
+// }
+// EXIT
+// return obj.field
+TEST_P(InstanceOfInstructionSimplifierTestGroup, ExactClassInstanceOfOther) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  InitGraph(/*handles=*/&vshs);
+
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+  HInstruction* test_res = graph_->GetIntConstant(GetConstantResult() ? 1 : 0);
+
+  auto [new_inst_klass, target_klass] = GetLoadClasses(&vshs);
+  HInstruction* new_inst = MakeNewInstance(new_inst_klass);
+  new_inst->SetReferenceTypeInfo(
+      ReferenceTypeInfo::Create(new_inst_klass->GetClass(), /*is_exact=*/true));
+  HInstanceOf* instance_of = new (GetAllocator()) HInstanceOf(new_inst,
+                                                              target_klass,
+                                                              TypeCheckKind::kClassHierarchyCheck,
+                                                              target_klass->GetClass(),
+                                                              0u,
+                                                              GetAllocator(),
+                                                              nullptr,
+                                                              nullptr);
+  if (target_klass->GetLoadedClassRTI().IsValid()) {
+    instance_of->SetValidTargetClassRTI();
+  }
+  HInstruction* if_inst = new (GetAllocator()) HIf(instance_of);
+  entry->AddInstruction(new_inst_klass);
+  if (new_inst_klass != target_klass) {
+    entry->AddInstruction(target_klass);
+  }
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(instance_of);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(new_inst_klass, {});
+  if (new_inst_klass != target_klass) {
+    target_klass->CopyEnvironmentFrom(new_inst_klass->GetEnvironment());
+  }
+  new_inst->CopyEnvironmentFrom(new_inst_klass->GetEnvironment());
+
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(goto_left);
+
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+
+  LOG(INFO) << "Pre simplification " << blks;
+  graph_->ClearDominanceInformation();
+  graph_->BuildDominatorTree();
+  InstructionSimplifier simp(graph_, /*codegen=*/nullptr);
+  simp.Run();
+
+  LOG(INFO) << "Post simplify " << blks;
+
+  if (!GetConstantResult() || GetParam() == InstanceOfKind::kSelf) {
+    EXPECT_INS_RETAINED(target_klass);
+  } else {
+    EXPECT_INS_REMOVED(target_klass);
+  }
+  EXPECT_INS_REMOVED(instance_of);
+  EXPECT_INS_EQ(if_inst->InputAt(0), test_res);
+}
+
+// // ENTRY
+// obj = new Obj();
+// (<other>)obj;
+// // Make sure this graph isn't broken
+// EXIT
+// return obj
+TEST_P(InstanceOfInstructionSimplifierTestGroup, ExactClassCheckCastOther) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  InitGraph(/*handles=*/&vshs);
+
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry", "exit", {{"entry", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+
+  auto [new_inst_klass, target_klass] = GetLoadClasses(&vshs);
+  HInstruction* new_inst = MakeNewInstance(new_inst_klass);
+  new_inst->SetReferenceTypeInfo(
+      ReferenceTypeInfo::Create(new_inst_klass->GetClass(), /*is_exact=*/true));
+  HCheckCast* check_cast = new (GetAllocator()) HCheckCast(new_inst,
+                                                           target_klass,
+                                                           TypeCheckKind::kClassHierarchyCheck,
+                                                           target_klass->GetClass(),
+                                                           0u,
+                                                           GetAllocator(),
+                                                           nullptr,
+                                                           nullptr);
+  if (target_klass->GetLoadedClassRTI().IsValid()) {
+    check_cast->SetValidTargetClassRTI();
+  }
+  HInstruction* entry_return = new (GetAllocator()) HReturn(new_inst);
+  entry->AddInstruction(new_inst_klass);
+  if (new_inst_klass != target_klass) {
+    entry->AddInstruction(target_klass);
+  }
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(check_cast);
+  entry->AddInstruction(entry_return);
+  ManuallyBuildEnvFor(new_inst_klass, {});
+  if (new_inst_klass != target_klass) {
+    target_klass->CopyEnvironmentFrom(new_inst_klass->GetEnvironment());
+  }
+  new_inst->CopyEnvironmentFrom(new_inst_klass->GetEnvironment());
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+
+  LOG(INFO) << "Pre simplification " << blks;
+  graph_->ClearDominanceInformation();
+  graph_->BuildDominatorTree();
+  InstructionSimplifier simp(graph_, /*codegen=*/nullptr);
+  simp.Run();
+
+  LOG(INFO) << "Post simplify " << blks;
+
+  if (!GetConstantResult() || GetParam() == InstanceOfKind::kSelf) {
+    EXPECT_INS_RETAINED(target_klass);
+  } else {
+    EXPECT_INS_REMOVED(target_klass);
+  }
+  if (GetConstantResult()) {
+    EXPECT_INS_REMOVED(check_cast);
+  } else {
+    EXPECT_INS_RETAINED(check_cast);
+  }
+}
+
+INSTANTIATE_TEST_SUITE_P(InstructionSimplifierTest,
+                         InstanceOfInstructionSimplifierTestGroup,
+                         testing::Values(InstanceOfKind::kSelf,
+                                         InstanceOfKind::kUnrelatedLoaded,
+                                         InstanceOfKind::kUnrelatedUnloaded,
+                                         InstanceOfKind::kSupertype));
+
+}  // namespace art
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index d940105..16c3029 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -20,7 +20,8 @@
 #include "art_method-inl.h"
 #include "base/utils.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
+#include "code_generator.h"
 #include "dex/invoke_type.h"
 #include "driver/compiler_options.h"
 #include "gc/space/image_space.h"
@@ -145,6 +146,22 @@
   return true;
 }
 
+static bool CanReferenceBootImageObjects(HInvoke* invoke, const CompilerOptions& compiler_options) {
+  // Piggyback on the method load kind to determine whether we can use PC-relative addressing
+  // for AOT. This should cover both the testing config (non-PIC boot image) and codegens that
+  // reject PC-relative load kinds and fall back to the runtime call.
+  if (compiler_options.IsAotCompiler() &&
+      !invoke->AsInvokeStaticOrDirect()->HasPcRelativeMethodLoadKind()) {
+    return false;
+  }
+  if (!compiler_options.IsBootImage() &&
+      Runtime::Current()->GetHeap()->GetBootImageSpaces().empty()) {
+    DCHECK(compiler_options.IsJitCompiler());
+    return false;  // Running without boot image, cannot use required boot image objects.
+  }
+  return true;
+}
+
 void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke,
                                                       CodeGenerator* codegen,
                                                       Location return_location,
@@ -152,13 +169,10 @@
   // The intrinsic will call if it needs to allocate a j.l.Integer.
   LocationSummary::CallKind call_kind = LocationSummary::kCallOnMainOnly;
   const CompilerOptions& compiler_options = codegen->GetCompilerOptions();
+  if (!CanReferenceBootImageObjects(invoke, compiler_options)) {
+    return;
+  }
   if (compiler_options.IsBootImage()) {
-    // Piggyback on the method load kind to determine whether we can use PC-relative addressing.
-    // This should cover both the testing config (non-PIC boot image) and codegens that reject
-    // PC-relative load kinds and fall back to the runtime call.
-    if (!invoke->AsInvokeStaticOrDirect()->HasPcRelativeMethodLoadKind()) {
-      return;
-    }
     if (!compiler_options.IsImageClass(kIntegerCacheDescriptor) ||
         !compiler_options.IsImageClass(kIntegerDescriptor)) {
       return;
@@ -204,9 +218,6 @@
     }
   } else {
     Runtime* runtime = Runtime::Current();
-    if (runtime->GetHeap()->GetBootImageSpaces().empty()) {
-      return;  // Running without boot image, cannot use required boot image objects.
-    }
     Thread* self = Thread::Current();
     ScopedObjectAccess soa(self);
     ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects = GetBootImageLiveObjects();
@@ -215,12 +226,12 @@
     if (cache == nullptr) {
       return;  // No cache in the boot image.
     }
-    if (runtime->UseJitCompilation()) {
+    if (compiler_options.IsJitCompiler()) {
       if (!CheckIntegerCache(self, runtime->GetClassLinker(), boot_image_live_objects, cache)) {
         return;  // The cache was somehow messed up, probably by using reflection.
       }
     } else {
-      DCHECK(runtime->IsAotCompiler());
+      DCHECK(compiler_options.IsAotCompiler());
       DCHECK(CheckIntegerCache(self, runtime->GetClassLinker(), boot_image_live_objects, cache));
       if (invoke->InputAt(0)->IsIntConstant()) {
         int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
@@ -242,7 +253,7 @@
     }
   }
 
-  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  ArenaAllocator* allocator = codegen->GetGraph()->GetAllocator();
   LocationSummary* locations = new (allocator) LocationSummary(invoke, call_kind, kIntrinsified);
   if (call_kind == LocationSummary::kCallOnMainOnly) {
     locations->SetInAt(0, Location::RegisterOrConstant(invoke->InputAt(0)));
@@ -261,18 +272,10 @@
   return GetIntegerCacheField(cache_class, kLowFieldName);
 }
 
-static uint32_t CalculateBootImageOffset(ObjPtr<mirror::Object> object)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  gc::Heap* heap = Runtime::Current()->GetHeap();
-  DCHECK(heap->ObjectIsInBootImageSpace(object));
-  return reinterpret_cast<const uint8_t*>(object.Ptr()) - heap->GetBootImageSpaces()[0]->Begin();
-}
-
 inline IntrinsicVisitor::IntegerValueOfInfo::IntegerValueOfInfo()
     : value_offset(0),
       low(0),
       length(0u),
-      integer_boot_image_offset(kInvalidReference),
       value_boot_image_reference(kInvalidReference) {}
 
 IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo(
@@ -287,15 +290,14 @@
   // we need to provide data that shall not lead to a crash even if the fields were
   // modified through reflection since ComputeIntegerValueOfLocations() when JITting.
 
-  Runtime* runtime = Runtime::Current();
-  ClassLinker* class_linker = runtime->GetClassLinker();
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Thread* self = Thread::Current();
   ScopedObjectAccess soa(self);
 
   IntegerValueOfInfo info;
   if (compiler_options.IsBootImage()) {
-    ObjPtr<mirror::Class> integer_class =
-        LookupInitializedClass(self, class_linker, kIntegerDescriptor);
+    ObjPtr<mirror::Class> integer_class = invoke->GetResolvedMethod()->GetDeclaringClass();
+    DCHECK(integer_class->DescriptorEquals(kIntegerDescriptor));
     ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I");
     DCHECK(value_field != nullptr);
     info.value_offset = value_field->GetOffset().Uint32Value();
@@ -305,7 +307,6 @@
     int32_t high = GetIntegerCacheField(cache_class, kHighFieldName);
     info.length = dchecked_integral_cast<uint32_t>(high - info.low + 1);
 
-    info.integer_boot_image_offset = IntegerValueOfInfo::kInvalidReference;
     if (invoke->InputAt(0)->IsIntConstant()) {
       int32_t input_value = invoke->InputAt(0)->AsIntConstant()->GetValue();
       uint32_t index = static_cast<uint32_t>(input_value) - static_cast<uint32_t>(info.low);
@@ -328,7 +329,7 @@
     ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I");
     DCHECK(value_field != nullptr);
     info.value_offset = value_field->GetOffset().Uint32Value();
-    if (runtime->UseJitCompilation()) {
+    if (compiler_options.IsJitCompiler()) {
       // Use the current `IntegerCache.low` for JIT to avoid truly surprising behavior if the
       // code messes up the `value` field in the lowest cached Integer using reflection.
       info.low = GetIntegerCacheLowFromIntegerCache(self, class_linker);
@@ -341,21 +342,20 @@
     info.length = dchecked_integral_cast<uint32_t>(
         IntrinsicObjects::GetIntegerValueOfCache(boot_image_live_objects)->GetLength());
 
-    info.integer_boot_image_offset = CalculateBootImageOffset(integer_class);
     if (invoke->InputAt(0)->IsIntConstant()) {
       int32_t input_value = invoke->InputAt(0)->AsIntConstant()->GetValue();
       uint32_t index = static_cast<uint32_t>(input_value) - static_cast<uint32_t>(info.low);
       if (index < static_cast<uint32_t>(info.length)) {
         ObjPtr<mirror::Object> integer =
             IntrinsicObjects::GetIntegerValueOfObject(boot_image_live_objects, index);
-        info.value_boot_image_reference = CalculateBootImageOffset(integer);
+        info.value_boot_image_reference = CodeGenerator::GetBootImageOffset(integer);
       } else {
         // Not in the cache.
         info.value_boot_image_reference = IntegerValueOfInfo::kInvalidReference;
       }
     } else {
       info.array_data_boot_image_reference =
-          CalculateBootImageOffset(boot_image_live_objects) +
+          CodeGenerator::GetBootImageOffset(boot_image_live_objects) +
           IntrinsicObjects::GetIntegerValueOfArrayDataOffset(boot_image_live_objects).Uint32Value();
     }
   }
@@ -363,10 +363,53 @@
   return info;
 }
 
+MemberOffset IntrinsicVisitor::GetReferenceDisableIntrinsicOffset() {
+  ScopedObjectAccess soa(Thread::Current());
+  // The "disableIntrinsic" is the first static field.
+  ArtField* field = GetClassRoot<mirror::Reference>()->GetStaticField(0);
+  DCHECK_STREQ(field->GetName(), "disableIntrinsic");
+  return field->GetOffset();
+}
+
+MemberOffset IntrinsicVisitor::GetReferenceSlowPathEnabledOffset() {
+  ScopedObjectAccess soa(Thread::Current());
+  // The "slowPathEnabled" is the second static field.
+  ArtField* field = GetClassRoot<mirror::Reference>()->GetStaticField(1);
+  DCHECK_STREQ(field->GetName(), "slowPathEnabled");
+  return field->GetOffset();
+}
+
+void IntrinsicVisitor::CreateReferenceGetReferentLocations(HInvoke* invoke,
+                                                           CodeGenerator* codegen) {
+  if (!CanReferenceBootImageObjects(invoke, codegen->GetCompilerOptions())) {
+    return;
+  }
+
+  ArenaAllocator* allocator = codegen->GetGraph()->GetAllocator();
+  LocationSummary* locations =
+      new (allocator) LocationSummary(invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->SetInAt(0, Location::RequiresRegister());
+  locations->SetOut(Location::RequiresRegister());
+}
+
+void IntrinsicVisitor::CreateReferenceRefersToLocations(HInvoke* invoke) {
+  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+    // Unimplemented for non-Baker read barrier.
+    return;
+  }
+
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations =
+      new (allocator) LocationSummary(invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->SetInAt(0, Location::RequiresRegister());
+  locations->SetInAt(1, Location::RequiresRegister());
+  locations->SetOut(Location::RequiresRegister());
+}
+
 void IntrinsicVisitor::AssertNonMovableStringClass() {
   if (kIsDebugBuild) {
     ScopedObjectAccess soa(Thread::Current());
-    ObjPtr<mirror::Class> string_class = GetClassRoot<art::mirror::String>();
+    ObjPtr<mirror::Class> string_class = GetClassRoot<mirror::String>();
     CHECK(!art::Runtime::Current()->GetHeap()->IsMovableObject(string_class));
   }
 }
diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h
index ab68cce..62b5faa 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -117,9 +117,6 @@
     // The length of the cache array.
     uint32_t length;
 
-    // Boot image offset of java.lang.Integer for allocating an instance.
-    uint32_t integer_boot_image_offset;  // Set to kInvalidReference when compiling the boot image.
-
     // This union contains references to the boot image. For app AOT or JIT compilation,
     // these are the boot image offsets of the target. For boot image compilation, the
     // location shall be known only at link time, so we encode a symbolic reference using
@@ -139,6 +136,11 @@
   static IntegerValueOfInfo ComputeIntegerValueOfInfo(
       HInvoke* invoke, const CompilerOptions& compiler_options);
 
+  static MemberOffset GetReferenceDisableIntrinsicOffset();
+  static MemberOffset GetReferenceSlowPathEnabledOffset();
+  static void CreateReferenceGetReferentLocations(HInvoke* invoke, CodeGenerator* codegen);
+  static void CreateReferenceRefersToLocations(HInvoke* invoke);
+
  protected:
   IntrinsicVisitor() {}
 
@@ -162,9 +164,8 @@
   explicit IntrinsicOptimizations(const HInvoke& invoke)
       : value_(invoke.GetIntrinsicOptimizations()) {}
 
-  static constexpr int kNumberOfGenericOptimizations = 2;
-  GENERIC_OPTIMIZATION(DoesNotNeedDexCache, 0);
-  GENERIC_OPTIMIZATION(DoesNotNeedEnvironment, 1);
+  static constexpr int kNumberOfGenericOptimizations = 1;
+  GENERIC_OPTIMIZATION(DoesNotNeedEnvironment, 0);
 
  protected:
   bool IsBitSet(uint32_t bit) const {
@@ -290,40 +291,7 @@
 UNREACHABLE_INTRINSIC(Arch, VarHandleAcquireFence)              \
 UNREACHABLE_INTRINSIC(Arch, VarHandleReleaseFence)              \
 UNREACHABLE_INTRINSIC(Arch, VarHandleLoadLoadFence)             \
-UNREACHABLE_INTRINSIC(Arch, VarHandleStoreStoreFence)           \
-UNREACHABLE_INTRINSIC(Arch, MethodHandleInvokeExact)            \
-UNREACHABLE_INTRINSIC(Arch, MethodHandleInvoke)                 \
-UNREACHABLE_INTRINSIC(Arch, VarHandleCompareAndExchange)        \
-UNREACHABLE_INTRINSIC(Arch, VarHandleCompareAndExchangeAcquire) \
-UNREACHABLE_INTRINSIC(Arch, VarHandleCompareAndExchangeRelease) \
-UNREACHABLE_INTRINSIC(Arch, VarHandleCompareAndSet)             \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGet)                       \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAcquire)                \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndAdd)                 \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndAddAcquire)          \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndAddRelease)          \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseAnd)          \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseAndAcquire)   \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseAndRelease)   \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseOr)           \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseOrAcquire)    \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseOrRelease)    \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseXor)          \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseXorAcquire)   \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseXorRelease)   \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndSet)                 \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndSetAcquire)          \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetAndSetRelease)          \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetOpaque)                 \
-UNREACHABLE_INTRINSIC(Arch, VarHandleGetVolatile)               \
-UNREACHABLE_INTRINSIC(Arch, VarHandleSet)                       \
-UNREACHABLE_INTRINSIC(Arch, VarHandleSetOpaque)                 \
-UNREACHABLE_INTRINSIC(Arch, VarHandleSetRelease)                \
-UNREACHABLE_INTRINSIC(Arch, VarHandleSetVolatile)               \
-UNREACHABLE_INTRINSIC(Arch, VarHandleWeakCompareAndSet)         \
-UNREACHABLE_INTRINSIC(Arch, VarHandleWeakCompareAndSetAcquire)  \
-UNREACHABLE_INTRINSIC(Arch, VarHandleWeakCompareAndSetPlain)    \
-UNREACHABLE_INTRINSIC(Arch, VarHandleWeakCompareAndSetRelease)
+UNREACHABLE_INTRINSIC(Arch, VarHandleStoreStoreFence)
 
 template <typename IntrinsicLocationsBuilder, typename Codegenerator>
 bool IsCallFreeIntrinsic(HInvoke* invoke, Codegenerator* codegen) {
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index d88e034..d0c64c2 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -16,18 +16,23 @@
 
 #include "intrinsics_arm64.h"
 
+#include "arch/arm64/callee_save_frame_arm64.h"
 #include "arch/arm64/instruction_set_features_arm64.h"
 #include "art_method.h"
+#include "base/bit_utils.h"
 #include "code_generator_arm64.h"
 #include "common_arm64.h"
+#include "data_type-inl.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "heap_poisoning.h"
 #include "intrinsics.h"
+#include "intrinsics_utils.h"
 #include "lock_word.h"
 #include "mirror/array-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/reference.h"
 #include "mirror/string-inl.h"
+#include "mirror/var_handle.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread-current-inl.h"
 #include "utils/arm64/assembler_arm64.h"
@@ -45,10 +50,12 @@
 
 namespace arm64 {
 
+using helpers::CPURegisterFrom;
 using helpers::DRegisterFrom;
-using helpers::FPRegisterFrom;
 using helpers::HeapOperand;
 using helpers::LocationFrom;
+using helpers::InputCPURegisterOrZeroRegAt;
+using helpers::IsConstantZeroBitPattern;
 using helpers::OperandFrom;
 using helpers::RegisterFrom;
 using helpers::SRegisterFrom;
@@ -74,87 +81,12 @@
   return codegen_->GetGraph()->GetAllocator();
 }
 
+using IntrinsicSlowPathARM64 = IntrinsicSlowPath<InvokeDexCallingConventionVisitorARM64,
+                                                 SlowPathCodeARM64,
+                                                 Arm64Assembler>;
+
 #define __ codegen->GetVIXLAssembler()->
 
-static void MoveFromReturnRegister(Location trg,
-                                   DataType::Type type,
-                                   CodeGeneratorARM64* codegen) {
-  if (!trg.IsValid()) {
-    DCHECK(type == DataType::Type::kVoid);
-    return;
-  }
-
-  DCHECK_NE(type, DataType::Type::kVoid);
-
-  if (DataType::IsIntegralType(type) || type == DataType::Type::kReference) {
-    Register trg_reg = RegisterFrom(trg, type);
-    Register res_reg = RegisterFrom(ARM64ReturnLocation(type), type);
-    __ Mov(trg_reg, res_reg, kDiscardForSameWReg);
-  } else {
-    VRegister trg_reg = FPRegisterFrom(trg, type);
-    VRegister res_reg = FPRegisterFrom(ARM64ReturnLocation(type), type);
-    __ Fmov(trg_reg, res_reg);
-  }
-}
-
-static void MoveArguments(HInvoke* invoke, CodeGeneratorARM64* codegen) {
-  InvokeDexCallingConventionVisitorARM64 calling_convention_visitor;
-  IntrinsicVisitor::MoveArguments(invoke, codegen, &calling_convention_visitor);
-}
-
-// Slow-path for fallback (calling the managed code to handle the intrinsic) in an intrinsified
-// call. This will copy the arguments into the positions for a regular call.
-//
-// Note: The actual parameters are required to be in the locations given by the invoke's location
-//       summary. If an intrinsic modifies those locations before a slowpath call, they must be
-//       restored!
-class IntrinsicSlowPathARM64 : public SlowPathCodeARM64 {
- public:
-  explicit IntrinsicSlowPathARM64(HInvoke* invoke)
-      : SlowPathCodeARM64(invoke), invoke_(invoke) { }
-
-  void EmitNativeCode(CodeGenerator* codegen_in) override {
-    CodeGeneratorARM64* codegen = down_cast<CodeGeneratorARM64*>(codegen_in);
-    __ Bind(GetEntryLabel());
-
-    SaveLiveRegisters(codegen, invoke_->GetLocations());
-
-    MoveArguments(invoke_, codegen);
-
-    {
-      // Ensure that between the BLR (emitted by Generate*Call) and RecordPcInfo there
-      // are no pools emitted.
-      vixl::EmissionCheckScope guard(codegen->GetVIXLAssembler(), kInvokeCodeMarginSizeInBytes);
-      if (invoke_->IsInvokeStaticOrDirect()) {
-        codegen->GenerateStaticOrDirectCall(
-            invoke_->AsInvokeStaticOrDirect(), LocationFrom(kArtMethodRegister), this);
-      } else {
-        codegen->GenerateVirtualCall(
-            invoke_->AsInvokeVirtual(), LocationFrom(kArtMethodRegister), this);
-      }
-    }
-
-    // Copy the result back to the expected output.
-    Location out = invoke_->GetLocations()->Out();
-    if (out.IsValid()) {
-      DCHECK(out.IsRegister());  // TODO: Replace this when we support output in memory.
-      DCHECK(!invoke_->GetLocations()->GetLiveRegisters()->ContainsCoreRegister(out.reg()));
-      MoveFromReturnRegister(out, invoke_->GetType(), codegen);
-    }
-
-    RestoreLiveRegisters(codegen, invoke_->GetLocations());
-    __ B(GetExitLabel());
-  }
-
-  const char* GetDescription() const override { return "IntrinsicSlowPathARM64"; }
-
- private:
-  // The instruction where this slow path is happening.
-  HInvoke* const invoke_;
-
-  DISALLOW_COPY_AND_ASSIGN(IntrinsicSlowPathARM64);
-};
-
 // Slow path implementing the SystemArrayCopy intrinsic copy loop with read barriers.
 class ReadBarrierSystemArrayCopySlowPathARM64 : public SlowPathCodeARM64 {
  public:
@@ -308,25 +240,53 @@
   locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
 }
 
+static void CreateIntIntToIntSlowPathCallLocations(ArenaAllocator* allocator, HInvoke* invoke) {
+  LocationSummary* locations =
+      new (allocator) LocationSummary(invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->SetInAt(0, Location::RequiresRegister());
+  locations->SetInAt(1, Location::RequiresRegister());
+  // Force kOutputOverlap; see comments in IntrinsicSlowPath::EmitNativeCode.
+  locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
+}
+
+static void GenerateReverseBytes(MacroAssembler* masm,
+                                 DataType::Type type,
+                                 CPURegister in,
+                                 CPURegister out) {
+  switch (type) {
+    case DataType::Type::kUint16:
+      __ Rev16(out.W(), in.W());
+      break;
+    case DataType::Type::kInt16:
+      __ Rev16(out.W(), in.W());
+      __ Sxth(out.W(), out.W());
+      break;
+    case DataType::Type::kInt32:
+      __ Rev(out.W(), in.W());
+      break;
+    case DataType::Type::kInt64:
+      __ Rev(out.X(), in.X());
+      break;
+    case DataType::Type::kFloat32:
+      __ Rev(in.W(), in.W());  // Note: Clobbers `in`.
+      __ Fmov(out.S(), in.W());
+      break;
+    case DataType::Type::kFloat64:
+      __ Rev(in.X(), in.X());  // Note: Clobbers `in`.
+      __ Fmov(out.D(), in.X());
+      break;
+    default:
+      LOG(FATAL) << "Unexpected type for reverse-bytes: " << type;
+      UNREACHABLE();
+  }
+}
+
 static void GenReverseBytes(LocationSummary* locations,
                             DataType::Type type,
                             MacroAssembler* masm) {
   Location in = locations->InAt(0);
   Location out = locations->Out();
-
-  switch (type) {
-    case DataType::Type::kInt16:
-      __ Rev16(WRegisterFrom(out), WRegisterFrom(in));
-      __ Sxth(WRegisterFrom(out), WRegisterFrom(out));
-      break;
-    case DataType::Type::kInt32:
-    case DataType::Type::kInt64:
-      __ Rev(RegisterFrom(out, type), RegisterFrom(in, type));
-      break;
-    default:
-      LOG(FATAL) << "Unexpected size for reverse-bytes: " << type;
-      UNREACHABLE();
-  }
+  GenerateReverseBytes(masm, type, CPURegisterFrom(in, type), CPURegisterFrom(out, type));
 }
 
 void IntrinsicLocationsBuilderARM64::VisitIntegerReverseBytes(HInvoke* invoke) {
@@ -767,7 +727,7 @@
     // Other cases.
     MemOperand mem_op(base.X(), offset);
     if (is_volatile) {
-      codegen->LoadAcquire(invoke, trg, mem_op, /* needs_null_check= */ true);
+      codegen->LoadAcquire(invoke, type, trg, mem_op, /* needs_null_check= */ true);
     } else {
       codegen->Load(type, trg, mem_op);
     }
@@ -981,11 +941,8 @@
                codegen_);
 }
 
-static void CreateIntIntIntIntIntToInt(ArenaAllocator* allocator,
-                                       HInvoke* invoke,
-                                       DataType::Type type) {
+static void CreateUnsafeCASLocations(ArenaAllocator* allocator, HInvoke* invoke) {
   bool can_call = kEmitCompilerReadBarrier &&
-      kUseBakerReadBarrier &&
       (invoke->GetIntrinsic() == Intrinsics::kUnsafeCASObject);
   LocationSummary* locations =
       new (allocator) LocationSummary(invoke,
@@ -993,7 +950,7 @@
                                           ? LocationSummary::kCallOnSlowPath
                                           : LocationSummary::kNoCall,
                                       kIntrinsified);
-  if (can_call) {
+  if (can_call && kUseBakerReadBarrier) {
     locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty());  // No caller-save registers.
   }
   locations->SetInAt(0, Location::NoLocation());        // Unused receiver.
@@ -1003,19 +960,224 @@
   locations->SetInAt(4, Location::RequiresRegister());
 
   locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
-  if (type == DataType::Type::kReference && kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
-    // We need two non-scratch temporary registers for (Baker) read barrier.
-    locations->AddTemp(Location::RequiresRegister());
-    locations->AddTemp(Location::RequiresRegister());
+}
+
+static void EmitLoadExclusive(CodeGeneratorARM64* codegen,
+                              DataType::Type type,
+                              Register ptr,
+                              Register old_value,
+                              bool use_load_acquire) {
+  Arm64Assembler* assembler = codegen->GetAssembler();
+  MacroAssembler* masm = assembler->GetVIXLAssembler();
+  switch (type) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      if (use_load_acquire) {
+        __ Ldaxrb(old_value, MemOperand(ptr));
+      } else {
+        __ Ldxrb(old_value, MemOperand(ptr));
+      }
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      if (use_load_acquire) {
+        __ Ldaxrh(old_value, MemOperand(ptr));
+      } else {
+        __ Ldxrh(old_value, MemOperand(ptr));
+      }
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kReference:
+      if (use_load_acquire) {
+        __ Ldaxr(old_value, MemOperand(ptr));
+      } else {
+        __ Ldxr(old_value, MemOperand(ptr));
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unexpected type: " << type;
+      UNREACHABLE();
+  }
+  switch (type) {
+    case DataType::Type::kInt8:
+      __ Sxtb(old_value, old_value);
+      break;
+    case DataType::Type::kInt16:
+      __ Sxth(old_value, old_value);
+      break;
+    case DataType::Type::kReference:
+      assembler->MaybeUnpoisonHeapReference(old_value);
+      break;
+    default:
+      break;
   }
 }
 
-class BakerReadBarrierCasSlowPathARM64 : public SlowPathCodeARM64 {
- public:
-  explicit BakerReadBarrierCasSlowPathARM64(HInvoke* invoke)
-      : SlowPathCodeARM64(invoke) {}
+static void EmitStoreExclusive(CodeGeneratorARM64* codegen,
+                               DataType::Type type,
+                               Register ptr,
+                               Register store_result,
+                               Register new_value,
+                               bool use_store_release) {
+  Arm64Assembler* assembler = codegen->GetAssembler();
+  MacroAssembler* masm = assembler->GetVIXLAssembler();
+  if (type == DataType::Type::kReference) {
+    assembler->MaybePoisonHeapReference(new_value);
+  }
+  switch (type) {
+    case DataType::Type::kBool:
+    case DataType::Type::kUint8:
+    case DataType::Type::kInt8:
+      if (use_store_release) {
+        __ Stlxrb(store_result, new_value, MemOperand(ptr));
+      } else {
+        __ Stxrb(store_result, new_value, MemOperand(ptr));
+      }
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      if (use_store_release) {
+        __ Stlxrh(store_result, new_value, MemOperand(ptr));
+      } else {
+        __ Stxrh(store_result, new_value, MemOperand(ptr));
+      }
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kInt64:
+    case DataType::Type::kReference:
+      if (use_store_release) {
+        __ Stlxr(store_result, new_value, MemOperand(ptr));
+      } else {
+        __ Stxr(store_result, new_value, MemOperand(ptr));
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unexpected type: " << type;
+      UNREACHABLE();
+  }
+  if (type == DataType::Type::kReference) {
+    assembler->MaybeUnpoisonHeapReference(new_value);
+  }
+}
 
-  const char* GetDescription() const override { return "BakerReadBarrierCasSlowPathARM64"; }
+static void GenerateCompareAndSet(CodeGeneratorARM64* codegen,
+                                  DataType::Type type,
+                                  std::memory_order order,
+                                  bool strong,
+                                  vixl::aarch64::Label* cmp_failure,
+                                  Register ptr,
+                                  Register new_value,
+                                  Register old_value,
+                                  Register store_result,
+                                  Register expected,
+                                  Register expected2 = Register()) {
+  // The `expected2` is valid only for reference slow path and represents the unmarked old value
+  // from the main path attempt to emit CAS when the marked old value matched `expected`.
+  DCHECK(type == DataType::Type::kReference || !expected2.IsValid());
+
+  DCHECK(ptr.IsX());
+  DCHECK_EQ(new_value.IsX(), type == DataType::Type::kInt64);
+  DCHECK_EQ(old_value.IsX(), type == DataType::Type::kInt64);
+  DCHECK(store_result.IsW());
+  DCHECK_EQ(expected.IsX(), type == DataType::Type::kInt64);
+  DCHECK(!expected2.IsValid() || expected2.IsW());
+
+  Arm64Assembler* assembler = codegen->GetAssembler();
+  MacroAssembler* masm = assembler->GetVIXLAssembler();
+
+  bool use_load_acquire =
+      (order == std::memory_order_acquire) || (order == std::memory_order_seq_cst);
+  bool use_store_release =
+      (order == std::memory_order_release) || (order == std::memory_order_seq_cst);
+  DCHECK(use_load_acquire || use_store_release || order == std::memory_order_relaxed);
+
+  // repeat: {
+  //   old_value = [ptr];  // Load exclusive.
+  //   if (old_value != expected && old_value != expected2) goto cmp_failure;
+  //   store_result = failed([ptr] <- new_value);  // Store exclusive.
+  // }
+  // if (strong) {
+  //   if (store_result) goto repeat;  // Repeat until compare fails or store exclusive succeeds.
+  // } else {
+  //   store_result = store_result ^ 1;  // Report success as 1, failure as 0.
+  // }
+  //
+  // Flag Z indicates whether `old_value == expected || old_value == expected2`.
+  // (Is `expected2` is not valid, the `old_value == expected2` part is not emitted.)
+
+  vixl::aarch64::Label loop_head;
+  if (strong) {
+    __ Bind(&loop_head);
+  }
+  EmitLoadExclusive(codegen, type, ptr, old_value, use_load_acquire);
+  __ Cmp(old_value, expected);
+  if (expected2.IsValid()) {
+    __ Ccmp(old_value, expected2, ZFlag, ne);
+  }
+  // If the comparison failed, the Z flag is cleared as we branch to the `cmp_failure` label.
+  // If the comparison succeeded, the Z flag is set and remains set after the end of the
+  // code emitted here, unless we retry the whole operation.
+  __ B(cmp_failure, ne);
+  EmitStoreExclusive(codegen, type, ptr, store_result, new_value, use_store_release);
+  if (strong) {
+    __ Cbnz(store_result, &loop_head);
+  } else {
+    // Flip the `store_result` register to indicate success by 1 and failure by 0.
+    __ Eor(store_result, store_result, 1);
+  }
+}
+
+class ReadBarrierCasSlowPathARM64 : public SlowPathCodeARM64 {
+ public:
+  ReadBarrierCasSlowPathARM64(HInvoke* invoke,
+                              std::memory_order order,
+                              bool strong,
+                              Register base,
+                              Register offset,
+                              Register expected,
+                              Register new_value,
+                              Register old_value,
+                              Register old_value_temp,
+                              Register store_result,
+                              bool update_old_value,
+                              CodeGeneratorARM64* arm64_codegen)
+      : SlowPathCodeARM64(invoke),
+        order_(order),
+        strong_(strong),
+        base_(base),
+        offset_(offset),
+        expected_(expected),
+        new_value_(new_value),
+        old_value_(old_value),
+        old_value_temp_(old_value_temp),
+        store_result_(store_result),
+        update_old_value_(update_old_value),
+        mark_old_value_slow_path_(nullptr),
+        update_old_value_slow_path_(nullptr) {
+    if (!kUseBakerReadBarrier) {
+      // We need to add the slow path now, it is too late when emitting slow path code.
+      mark_old_value_slow_path_ = arm64_codegen->AddReadBarrierSlowPath(
+          invoke,
+          Location::RegisterLocation(old_value_temp.GetCode()),
+          Location::RegisterLocation(old_value.GetCode()),
+          Location::RegisterLocation(base.GetCode()),
+          /*offset=*/ 0u,
+          /*index=*/ Location::RegisterLocation(offset.GetCode()));
+      if (update_old_value_) {
+        update_old_value_slow_path_ = arm64_codegen->AddReadBarrierSlowPath(
+            invoke,
+            Location::RegisterLocation(old_value.GetCode()),
+            Location::RegisterLocation(old_value_temp.GetCode()),
+            Location::RegisterLocation(base.GetCode()),
+            /*offset=*/ 0u,
+            /*index=*/ Location::RegisterLocation(offset.GetCode()));
+      }
+    }
+  }
+
+  const char* GetDescription() const override { return "ReadBarrierCasSlowPathARM64"; }
 
   void EmitNativeCode(CodeGenerator* codegen) override {
     CodeGeneratorARM64* arm64_codegen = down_cast<CodeGeneratorARM64*>(codegen);
@@ -1023,73 +1185,106 @@
     MacroAssembler* masm = assembler->GetVIXLAssembler();
     __ Bind(GetEntryLabel());
 
-    // Get the locations.
-    LocationSummary* locations = instruction_->GetLocations();
-    Register base = WRegisterFrom(locations->InAt(1));              // Object pointer.
-    Register offset = XRegisterFrom(locations->InAt(2));            // Long offset.
-    Register expected = WRegisterFrom(locations->InAt(3));          // Expected.
-    Register value = WRegisterFrom(locations->InAt(4));             // Value.
-
-    Register old_value = WRegisterFrom(locations->GetTemp(0));      // The old value from main path.
-    Register marked = WRegisterFrom(locations->GetTemp(1));         // The marked old value.
-
-    // Mark the `old_value` from the main path and compare with `expected`. This clobbers the
-    // `tmp_ptr` scratch register but we do not want to allocate another non-scratch temporary.
-    arm64_codegen->GenerateUnsafeCasOldValueMovWithBakerReadBarrier(marked, old_value);
-    __ Cmp(marked, expected);
+    // Mark the `old_value_` from the main path and compare with `expected_`.
+    if (kUseBakerReadBarrier) {
+      DCHECK(mark_old_value_slow_path_ == nullptr);
+      arm64_codegen->GenerateIntrinsicCasMoveWithBakerReadBarrier(old_value_temp_, old_value_);
+    } else {
+      DCHECK(mark_old_value_slow_path_ != nullptr);
+      __ B(mark_old_value_slow_path_->GetEntryLabel());
+      __ Bind(mark_old_value_slow_path_->GetExitLabel());
+    }
+    __ Cmp(old_value_temp_, expected_);
+    if (update_old_value_) {
+      // Update the old value if we're going to return from the slow path.
+      __ Csel(old_value_, old_value_temp_, old_value_, ne);
+    }
     __ B(GetExitLabel(), ne);  // If taken, Z=false indicates failure.
 
-    // The `old_value` we have read did not match `expected` (which is always a to-space reference)
-    // but after the read barrier in GenerateUnsafeCasOldValueMovWithBakerReadBarrier() the marked
-    // to-space value matched, so the `old_value` must be a from-space reference to the same
-    // object. Do the same CAS loop as the main path but check for both `expected` and the unmarked
-    // old value representing the to-space and from-space references for the same object.
+    // The `old_value` we have read did not match `expected` (which is always a to-space
+    // reference) but after the read barrier the marked to-space value matched, so the
+    // `old_value` must be a from-space reference to the same object. Do the same CAS loop
+    // as the main path but check for both `expected` and the unmarked old value
+    // representing the to-space and from-space references for the same object.
 
     UseScratchRegisterScope temps(masm);
+    DCHECK(!store_result_.IsValid() || !temps.IsAvailable(store_result_));
     Register tmp_ptr = temps.AcquireX();
-    Register tmp = temps.AcquireSameSizeAs(value);
+    Register store_result = store_result_.IsValid() ? store_result_ : temps.AcquireW();
 
-    // Recalculate the `tmp_ptr` clobbered above.
-    __ Add(tmp_ptr, base.X(), Operand(offset));
+    // Recalculate the `tmp_ptr` from main path clobbered by the read barrier above.
+    __ Add(tmp_ptr, base_.X(), Operand(offset_));
 
-    // do {
-    //   tmp_value = [tmp_ptr];
-    // } while ((tmp_value == expected || tmp == old_value) && failure([tmp_ptr] <- r_new_value));
-    // result = (tmp_value == expected || tmp == old_value);
+    vixl::aarch64::Label mark_old_value;
+    GenerateCompareAndSet(arm64_codegen,
+                          DataType::Type::kReference,
+                          order_,
+                          strong_,
+                          /*cmp_failure=*/ update_old_value_ ? &mark_old_value : GetExitLabel(),
+                          tmp_ptr,
+                          new_value_,
+                          /*old_value=*/ old_value_temp_,
+                          store_result,
+                          expected_,
+                          /*expected2=*/ old_value_);
+    if (update_old_value_) {
+      // To reach this point, the `old_value_temp_` must be either a from-space or a to-space
+      // reference of the `expected_` object. Update the `old_value_` to the to-space reference.
+      __ Mov(old_value_, expected_);
+    }
 
-    vixl::aarch64::Label loop_head;
-    __ Bind(&loop_head);
-    __ Ldaxr(tmp, MemOperand(tmp_ptr));
-    assembler->MaybeUnpoisonHeapReference(tmp);
-    __ Cmp(tmp, expected);
-    __ Ccmp(tmp, old_value, ZFlag, ne);
-    __ B(GetExitLabel(), ne);  // If taken, Z=false indicates failure.
-    assembler->MaybePoisonHeapReference(value);
-    __ Stlxr(tmp.W(), value, MemOperand(tmp_ptr));
-    assembler->MaybeUnpoisonHeapReference(value);
-    __ Cbnz(tmp.W(), &loop_head);
-
-    // Z=true from the above CMP+CCMP indicates success.
+    // Z=true from the CMP+CCMP in GenerateCompareAndSet() above indicates comparison success.
+    // For strong CAS, that's the overall success. For weak CAS, the code also needs
+    // to check the `store_result` after returning from the slow path.
     __ B(GetExitLabel());
+
+    if (update_old_value_) {
+      __ Bind(&mark_old_value);
+      if (kUseBakerReadBarrier) {
+        DCHECK(update_old_value_slow_path_ == nullptr);
+        arm64_codegen->GenerateIntrinsicCasMoveWithBakerReadBarrier(old_value_, old_value_temp_);
+      } else {
+        // Note: We could redirect the `failure` above directly to the entry label and bind
+        // the exit label in the main path, but the main path would need to access the
+        // `update_old_value_slow_path_`. To keep the code simple, keep the extra jumps.
+        DCHECK(update_old_value_slow_path_ != nullptr);
+        __ B(update_old_value_slow_path_->GetEntryLabel());
+        __ Bind(update_old_value_slow_path_->GetExitLabel());
+      }
+      __ B(GetExitLabel());
+    }
   }
+
+ private:
+  std::memory_order order_;
+  bool strong_;
+  Register base_;
+  Register offset_;
+  Register expected_;
+  Register new_value_;
+  Register old_value_;
+  Register old_value_temp_;
+  Register store_result_;
+  bool update_old_value_;
+  SlowPathCodeARM64* mark_old_value_slow_path_;
+  SlowPathCodeARM64* update_old_value_slow_path_;
 };
 
-static void GenCas(HInvoke* invoke, DataType::Type type, CodeGeneratorARM64* codegen) {
-  Arm64Assembler* assembler = codegen->GetAssembler();
-  MacroAssembler* masm = assembler->GetVIXLAssembler();
+static void GenUnsafeCas(HInvoke* invoke, DataType::Type type, CodeGeneratorARM64* codegen) {
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
   LocationSummary* locations = invoke->GetLocations();
 
   Register out = WRegisterFrom(locations->Out());                 // Boolean result.
   Register base = WRegisterFrom(locations->InAt(1));              // Object pointer.
   Register offset = XRegisterFrom(locations->InAt(2));            // Long offset.
   Register expected = RegisterFrom(locations->InAt(3), type);     // Expected.
-  Register value = RegisterFrom(locations->InAt(4), type);        // Value.
+  Register new_value = RegisterFrom(locations->InAt(4), type);    // New value.
 
   // This needs to be before the temp registers, as MarkGCCard also uses VIXL temps.
   if (type == DataType::Type::kReference) {
     // Mark card for object assuming new value is stored.
-    bool value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MarkGCCard(base, value, value_can_be_null);
+    bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(base, new_value, new_value_can_be_null);
   }
 
   UseScratchRegisterScope temps(masm);
@@ -1098,80 +1293,183 @@
 
   vixl::aarch64::Label exit_loop_label;
   vixl::aarch64::Label* exit_loop = &exit_loop_label;
-  vixl::aarch64::Label* failure = &exit_loop_label;
+  vixl::aarch64::Label* cmp_failure = &exit_loop_label;
 
   if (kEmitCompilerReadBarrier && type == DataType::Type::kReference) {
-    // The only read barrier implementation supporting the
-    // UnsafeCASObject intrinsic is the Baker-style read barriers.
-    DCHECK(kUseBakerReadBarrier);
-
-    BakerReadBarrierCasSlowPathARM64* slow_path =
-        new (codegen->GetScopedAllocator()) BakerReadBarrierCasSlowPathARM64(invoke);
+    // We need to store the `old_value` in a non-scratch register to make sure
+    // the read barrier in the slow path does not clobber it.
+    old_value = WRegisterFrom(locations->GetTemp(0));  // The old value from main path.
+    // The `old_value_temp` is used first for the marked `old_value` and then for the unmarked
+    // reloaded old value for subsequent CAS in the slow path. It cannot be a scratch register.
+    Register old_value_temp = WRegisterFrom(locations->GetTemp(1));
+    ReadBarrierCasSlowPathARM64* slow_path =
+        new (codegen->GetScopedAllocator()) ReadBarrierCasSlowPathARM64(
+            invoke,
+            std::memory_order_seq_cst,
+            /*strong=*/ true,
+            base,
+            offset,
+            expected,
+            new_value,
+            old_value,
+            old_value_temp,
+            /*store_result=*/ Register(),  // Use a scratch register.
+            /*update_old_value=*/ false,
+            codegen);
     codegen->AddSlowPath(slow_path);
     exit_loop = slow_path->GetExitLabel();
-    failure = slow_path->GetEntryLabel();
-    // We need to store the `old_value` in a non-scratch register to make sure
-    // the Baker read barrier in the slow path does not clobber it.
-    old_value = WRegisterFrom(locations->GetTemp(0));
+    cmp_failure = slow_path->GetEntryLabel();
   } else {
-    old_value = temps.AcquireSameSizeAs(value);
+    old_value = temps.AcquireSameSizeAs(new_value);
   }
 
   __ Add(tmp_ptr, base.X(), Operand(offset));
 
-  // do {
-  //   tmp_value = [tmp_ptr];
-  // } while (tmp_value == expected && failure([tmp_ptr] <- r_new_value));
-  // result = tmp_value == expected;
-
-  vixl::aarch64::Label loop_head;
-  __ Bind(&loop_head);
-  __ Ldaxr(old_value, MemOperand(tmp_ptr));
-  if (type == DataType::Type::kReference) {
-    assembler->MaybeUnpoisonHeapReference(old_value);
-  }
-  __ Cmp(old_value, expected);
-  __ B(failure, ne);
-  if (type == DataType::Type::kReference) {
-    assembler->MaybePoisonHeapReference(value);
-  }
-  __ Stlxr(old_value.W(), value, MemOperand(tmp_ptr));  // Reuse `old_value` for STLXR result.
-  if (type == DataType::Type::kReference) {
-    assembler->MaybeUnpoisonHeapReference(value);
-  }
-  __ Cbnz(old_value.W(), &loop_head);
+  GenerateCompareAndSet(codegen,
+                        type,
+                        std::memory_order_seq_cst,
+                        /*strong=*/ true,
+                        cmp_failure,
+                        tmp_ptr,
+                        new_value,
+                        old_value,
+                        /*store_result=*/ old_value.W(),  // Reuse `old_value` for ST*XR* result.
+                        expected);
   __ Bind(exit_loop);
   __ Cset(out, eq);
 }
 
 void IntrinsicLocationsBuilderARM64::VisitUnsafeCASInt(HInvoke* invoke) {
-  CreateIntIntIntIntIntToInt(allocator_, invoke, DataType::Type::kInt32);
+  CreateUnsafeCASLocations(allocator_, invoke);
 }
 void IntrinsicLocationsBuilderARM64::VisitUnsafeCASLong(HInvoke* invoke) {
-  CreateIntIntIntIntIntToInt(allocator_, invoke, DataType::Type::kInt64);
+  CreateUnsafeCASLocations(allocator_, invoke);
 }
 void IntrinsicLocationsBuilderARM64::VisitUnsafeCASObject(HInvoke* invoke) {
   // The only read barrier implementation supporting the
-  // UnsafeCASObject intrinsic is the Baker-style read barriers.
+  // UnsafeCASObject intrinsic is the Baker-style read barriers. b/173104084
   if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
     return;
   }
 
-  CreateIntIntIntIntIntToInt(allocator_, invoke, DataType::Type::kReference);
+  CreateUnsafeCASLocations(allocator_, invoke);
+  if (kEmitCompilerReadBarrier) {
+    // We need two non-scratch temporary registers for read barrier.
+    LocationSummary* locations = invoke->GetLocations();
+    if (kUseBakerReadBarrier) {
+      locations->AddTemp(Location::RequiresRegister());
+      locations->AddTemp(Location::RequiresRegister());
+    } else {
+      // To preserve the old value across the non-Baker read barrier
+      // slow path, use a fixed callee-save register.
+      constexpr int first_callee_save = CTZ(kArm64CalleeSaveRefSpills);
+      locations->AddTemp(Location::RegisterLocation(first_callee_save));
+      // To reduce the number of moves, request x0 as the second temporary.
+      DCHECK(InvokeRuntimeCallingConvention().GetReturnLocation(DataType::Type::kReference).Equals(
+                 Location::RegisterLocation(x0.GetCode())));
+      locations->AddTemp(Location::RegisterLocation(x0.GetCode()));
+    }
+  }
 }
 
 void IntrinsicCodeGeneratorARM64::VisitUnsafeCASInt(HInvoke* invoke) {
-  GenCas(invoke, DataType::Type::kInt32, codegen_);
+  GenUnsafeCas(invoke, DataType::Type::kInt32, codegen_);
 }
 void IntrinsicCodeGeneratorARM64::VisitUnsafeCASLong(HInvoke* invoke) {
-  GenCas(invoke, DataType::Type::kInt64, codegen_);
+  GenUnsafeCas(invoke, DataType::Type::kInt64, codegen_);
 }
 void IntrinsicCodeGeneratorARM64::VisitUnsafeCASObject(HInvoke* invoke) {
-  // The only read barrier implementation supporting the
-  // UnsafeCASObject intrinsic is the Baker-style read barriers.
-  DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
+  GenUnsafeCas(invoke, DataType::Type::kReference, codegen_);
+}
 
-  GenCas(invoke, DataType::Type::kReference, codegen_);
+enum class GetAndUpdateOp {
+  kSet,
+  kAdd,
+  kAddWithByteSwap,
+  kAnd,
+  kOr,
+  kXor
+};
+
+static void GenerateGetAndUpdate(CodeGeneratorARM64* codegen,
+                                 GetAndUpdateOp get_and_update_op,
+                                 DataType::Type load_store_type,
+                                 std::memory_order order,
+                                 Register ptr,
+                                 CPURegister arg,
+                                 CPURegister old_value) {
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  UseScratchRegisterScope temps(masm);
+  Register store_result = temps.AcquireW();
+
+  DCHECK_EQ(old_value.GetSizeInBits(), arg.GetSizeInBits());
+  Register old_value_reg;
+  Register new_value;
+  switch (get_and_update_op) {
+    case GetAndUpdateOp::kSet:
+      old_value_reg = old_value.IsX() ? old_value.X() : old_value.W();
+      new_value = arg.IsX() ? arg.X() : arg.W();
+      break;
+    case GetAndUpdateOp::kAddWithByteSwap:
+    case GetAndUpdateOp::kAdd:
+      if (arg.IsVRegister()) {
+        old_value_reg = arg.IsD() ? temps.AcquireX() : temps.AcquireW();
+        new_value = old_value_reg;  // Use the same temporary.
+        break;
+      }
+      FALLTHROUGH_INTENDED;
+    case GetAndUpdateOp::kAnd:
+    case GetAndUpdateOp::kOr:
+    case GetAndUpdateOp::kXor:
+      old_value_reg = old_value.IsX() ? old_value.X() : old_value.W();
+      new_value = old_value.IsX() ? temps.AcquireX() : temps.AcquireW();
+      break;
+  }
+
+  bool use_load_acquire =
+      (order == std::memory_order_acquire) || (order == std::memory_order_seq_cst);
+  bool use_store_release =
+      (order == std::memory_order_release) || (order == std::memory_order_seq_cst);
+  DCHECK(use_load_acquire || use_store_release);
+
+  vixl::aarch64::Label loop_label;
+  __ Bind(&loop_label);
+  EmitLoadExclusive(codegen, load_store_type, ptr, old_value_reg, use_load_acquire);
+  switch (get_and_update_op) {
+    case GetAndUpdateOp::kSet:
+      break;
+    case GetAndUpdateOp::kAddWithByteSwap:
+      // To avoid unnecessary sign extension before REV16, the caller must specify `kUint16`
+      // instead of `kInt16` and do the sign-extension explicitly afterwards.
+      DCHECK_NE(load_store_type, DataType::Type::kInt16);
+      GenerateReverseBytes(masm, load_store_type, old_value_reg, old_value_reg);
+      FALLTHROUGH_INTENDED;
+    case GetAndUpdateOp::kAdd:
+      if (arg.IsVRegister()) {
+        VRegister old_value_vreg = old_value.IsD() ? old_value.D() : old_value.S();
+        VRegister sum = temps.AcquireSameSizeAs(old_value_vreg);
+        __ Fmov(old_value_vreg, old_value_reg);
+        __ Fadd(sum, old_value_vreg, arg.IsD() ? arg.D() : arg.S());
+        __ Fmov(new_value, sum);
+      } else {
+        __ Add(new_value, old_value_reg, arg.IsX() ? arg.X() : arg.W());
+      }
+      if (get_and_update_op == GetAndUpdateOp::kAddWithByteSwap) {
+        GenerateReverseBytes(masm, load_store_type, new_value, new_value);
+      }
+      break;
+    case GetAndUpdateOp::kAnd:
+      __ And(new_value, old_value_reg, arg.IsX() ? arg.X() : arg.W());
+      break;
+    case GetAndUpdateOp::kOr:
+      __ Orr(new_value, old_value_reg, arg.IsX() ? arg.X() : arg.W());
+      break;
+    case GetAndUpdateOp::kXor:
+      __ Eor(new_value, old_value_reg, arg.IsX() ? arg.X() : arg.W());
+      break;
+  }
+  EmitStoreExclusive(codegen, load_store_type, ptr, store_result, new_value, use_store_release);
+  __ Cbnz(store_result, &loop_label);
 }
 
 void IntrinsicLocationsBuilderARM64::VisitStringCompareTo(HInvoke* invoke) {
@@ -2828,16 +3126,16 @@
 static void GenIsInfinite(LocationSummary* locations,
                           bool is64bit,
                           MacroAssembler* masm) {
-  Operand infinity;
-  Operand tst_mask;
+  Operand infinity(0);
+  Operand tst_mask(0);
   Register out;
 
   if (is64bit) {
-    infinity = kPositiveInfinityDouble;
+    infinity = Operand(kPositiveInfinityDouble);
     tst_mask = MaskLeastSignificant<uint64_t>(63);
     out = XRegisterFrom(locations->Out());
   } else {
-    infinity = kPositiveInfinityFloat;
+    infinity = Operand(kPositiveInfinityFloat);
     tst_mask = MaskLeastSignificant<uint32_t>(31);
     out = WRegisterFrom(locations->Out());
   }
@@ -2885,6 +3183,12 @@
   Register out = RegisterFrom(locations->Out(), DataType::Type::kReference);
   UseScratchRegisterScope temps(masm);
   Register temp = temps.AcquireW();
+  auto allocate_instance = [&]() {
+    DCHECK(out.X().Is(InvokeRuntimeCallingConvention().GetRegisterAt(0)));
+    codegen_->LoadIntrinsicDeclaringClass(out, invoke);
+    codegen_->InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
+    CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
+  };
   if (invoke->InputAt(0)->IsConstant()) {
     int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
     if (static_cast<uint32_t>(value - info.low) < info.length) {
@@ -2896,12 +3200,10 @@
       // Allocate and initialize a new j.l.Integer.
       // TODO: If we JIT, we could allocate the j.l.Integer now, and store it in the
       // JIT object table.
-      codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
-                                             info.integer_boot_image_offset);
+      allocate_instance();
       __ Mov(temp.W(), value);
       __ Str(temp.W(), HeapOperand(out.W(), info.value_offset));
-      // `value` is a final field :-( Ideally, we'd merge this memory barrier with the allocation
-      // one.
+      // Class pointer and `value` final field stores require a barrier before publication.
       codegen_->GenerateMemoryBarrier(MemBarrierKind::kStoreStore);
     }
   } else {
@@ -2921,16 +3223,131 @@
     __ B(&done);
     __ Bind(&allocate);
     // Otherwise allocate and initialize a new j.l.Integer.
-    codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
-                                           info.integer_boot_image_offset);
+    allocate_instance();
     __ Str(in.W(), HeapOperand(out.W(), info.value_offset));
-    // `value` is a final field :-( Ideally, we'd merge this memory barrier with the allocation
-    // one.
+    // Class pointer and `value` final field stores require a barrier before publication.
     codegen_->GenerateMemoryBarrier(MemBarrierKind::kStoreStore);
     __ Bind(&done);
   }
 }
 
+void IntrinsicLocationsBuilderARM64::VisitReferenceGetReferent(HInvoke* invoke) {
+  IntrinsicVisitor::CreateReferenceGetReferentLocations(invoke, codegen_);
+
+  if (kEmitCompilerReadBarrier && kUseBakerReadBarrier && invoke->GetLocations() != nullptr) {
+    invoke->GetLocations()->AddTemp(Location::RequiresRegister());
+  }
+}
+
+void IntrinsicCodeGeneratorARM64::VisitReferenceGetReferent(HInvoke* invoke) {
+  MacroAssembler* masm = GetVIXLAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+
+  Location obj = locations->InAt(0);
+  Location out = locations->Out();
+
+  SlowPathCodeARM64* slow_path = new (GetAllocator()) IntrinsicSlowPathARM64(invoke);
+  codegen_->AddSlowPath(slow_path);
+
+  if (kEmitCompilerReadBarrier) {
+    // Check self->GetWeakRefAccessEnabled().
+    UseScratchRegisterScope temps(masm);
+    Register temp = temps.AcquireW();
+    __ Ldr(temp,
+           MemOperand(tr, Thread::WeakRefAccessEnabledOffset<kArm64PointerSize>().Uint32Value()));
+    __ Cbz(temp, slow_path->GetEntryLabel());
+  }
+
+  {
+    // Load the java.lang.ref.Reference class.
+    UseScratchRegisterScope temps(masm);
+    Register temp = temps.AcquireW();
+    codegen_->LoadIntrinsicDeclaringClass(temp, invoke);
+
+    // Check static fields java.lang.ref.Reference.{disableIntrinsic,slowPathEnabled} together.
+    MemberOffset disable_intrinsic_offset = IntrinsicVisitor::GetReferenceDisableIntrinsicOffset();
+    DCHECK_ALIGNED(disable_intrinsic_offset.Uint32Value(), 2u);
+    DCHECK_EQ(disable_intrinsic_offset.Uint32Value() + 1u,
+              IntrinsicVisitor::GetReferenceSlowPathEnabledOffset().Uint32Value());
+    __ Ldrh(temp, HeapOperand(temp, disable_intrinsic_offset.Uint32Value()));
+    __ Cbnz(temp, slow_path->GetEntryLabel());
+  }
+
+  // Load the value from the field.
+  uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+  if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+    codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+                                                    out,
+                                                    WRegisterFrom(obj),
+                                                    referent_offset,
+                                                    /*maybe_temp=*/ locations->GetTemp(0),
+                                                    /*needs_null_check=*/ true,
+                                                    /*use_load_acquire=*/ true);
+  } else {
+    MemOperand field = HeapOperand(WRegisterFrom(obj), referent_offset);
+    codegen_->LoadAcquire(
+        invoke, DataType::Type::kReference, WRegisterFrom(out), field, /*needs_null_check=*/ true);
+    codegen_->MaybeGenerateReadBarrierSlow(invoke, out, out, obj, referent_offset);
+  }
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderARM64::VisitReferenceRefersTo(HInvoke* invoke) {
+  IntrinsicVisitor::CreateReferenceRefersToLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitReferenceRefersTo(HInvoke* invoke) {
+  LocationSummary* locations = invoke->GetLocations();
+  MacroAssembler* masm = codegen_->GetVIXLAssembler();
+  UseScratchRegisterScope temps(masm);
+
+  Register obj = WRegisterFrom(locations->InAt(0));
+  Register other = WRegisterFrom(locations->InAt(1));
+  Register out = WRegisterFrom(locations->Out());
+  Register tmp = temps.AcquireW();
+
+  uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+  uint32_t monitor_offset = mirror::Object::MonitorOffset().Int32Value();
+
+  MemOperand field = HeapOperand(obj, referent_offset);
+  codegen_->LoadAcquire(invoke, DataType::Type::kReference, tmp, field, /*needs_null_check=*/ true);
+  codegen_->GetAssembler()->MaybeUnpoisonHeapReference(tmp);
+
+  __ Cmp(tmp, other);
+
+  if (kEmitCompilerReadBarrier) {
+    DCHECK(kUseBakerReadBarrier);
+
+    vixl::aarch64::Label calculate_result;
+
+    // If the GC is not marking, the comparison result is final.
+    __ Cbz(mr, &calculate_result);
+
+    __ B(&calculate_result, eq);  // ZF set if taken.
+
+    // Check if the loaded reference is null.
+    __ Cbz(tmp, &calculate_result);  // ZF clear if taken.
+
+    // For correct memory visibility, we need a barrier before loading the lock word.
+    codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
+
+    // Load the lockword and check if it is a forwarding address.
+    static_assert(LockWord::kStateShift == 30u);
+    static_assert(LockWord::kStateForwardingAddress == 3u);
+    __ Ldr(tmp, HeapOperand(tmp, monitor_offset));
+    __ Cmp(tmp, Operand(0xc0000000));
+    __ B(&calculate_result, lo);   // ZF clear if taken.
+
+    // Extract the forwarding address and compare with `other`.
+    __ Cmp(other, Operand(tmp, LSL, LockWord::kForwardingAddressShift));
+
+    __ Bind(&calculate_result);
+  }
+
+  // Convert ZF into the Boolean result.
+  __ Cset(out, eq);
+}
+
 void IntrinsicLocationsBuilderARM64::VisitThreadInterrupted(HInvoke* invoke) {
   LocationSummary* locations =
       new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
@@ -3134,7 +3551,7 @@
   LocationSummary* locations = invoke->GetLocations();
 
   SlowPathCodeARM64* slow_path =
-    new (codegen_->GetScopedAllocator()) IntrinsicSlowPathARM64(invoke);
+      new (codegen_->GetScopedAllocator()) IntrinsicSlowPathARM64(invoke);
   codegen_->AddSlowPath(slow_path);
 
   Register length = WRegisterFrom(locations->InAt(3));
@@ -3402,7 +3819,1544 @@
   GenerateFP16Compare(invoke, codegen_, masm, ls);
 }
 
-UNIMPLEMENTED_INTRINSIC(ARM64, ReferenceGetReferent)
+static void GenerateDivideUnsigned(HInvoke* invoke, CodeGeneratorARM64* codegen) {
+  LocationSummary* locations = invoke->GetLocations();
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  DataType::Type type = invoke->GetType();
+  DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64);
+
+  Register dividend = RegisterFrom(locations->InAt(0), type);
+  Register divisor = RegisterFrom(locations->InAt(1), type);
+  Register out = RegisterFrom(locations->Out(), type);
+
+  // Check if divisor is zero, bail to managed implementation to handle.
+  SlowPathCodeARM64* slow_path =
+      new (codegen->GetScopedAllocator()) IntrinsicSlowPathARM64(invoke);
+  codegen->AddSlowPath(slow_path);
+  __ Cbz(divisor, slow_path->GetEntryLabel());
+
+  __ Udiv(out, dividend, divisor);
+
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderARM64::VisitIntegerDivideUnsigned(HInvoke* invoke) {
+  CreateIntIntToIntSlowPathCallLocations(allocator_, invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitIntegerDivideUnsigned(HInvoke* invoke) {
+  GenerateDivideUnsigned(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitLongDivideUnsigned(HInvoke* invoke) {
+  CreateIntIntToIntSlowPathCallLocations(allocator_, invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitLongDivideUnsigned(HInvoke* invoke) {
+  GenerateDivideUnsigned(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitMathMultiplyHigh(HInvoke* invoke) {
+  CreateIntIntToIntLocations(allocator_, invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitMathMultiplyHigh(HInvoke* invoke) {
+  LocationSummary* locations = invoke->GetLocations();
+  MacroAssembler* masm = codegen_->GetVIXLAssembler();
+  DataType::Type type = invoke->GetType();
+  DCHECK(type == DataType::Type::kInt64);
+
+  Register x = RegisterFrom(locations->InAt(0), type);
+  Register y = RegisterFrom(locations->InAt(1), type);
+  Register out = RegisterFrom(locations->Out(), type);
+
+  __ Smulh(out, x, y);
+}
+
+class VarHandleSlowPathARM64 : public IntrinsicSlowPathARM64 {
+ public:
+  VarHandleSlowPathARM64(HInvoke* invoke, std::memory_order order)
+      : IntrinsicSlowPathARM64(invoke),
+        order_(order),
+        return_success_(false),
+        strong_(false),
+        get_and_update_op_(GetAndUpdateOp::kAdd) {
+  }
+
+  vixl::aarch64::Label* GetByteArrayViewCheckLabel() {
+    return &byte_array_view_check_label_;
+  }
+
+  vixl::aarch64::Label* GetNativeByteOrderLabel() {
+    return &native_byte_order_label_;
+  }
+
+  void SetCompareAndSetOrExchangeArgs(bool return_success, bool strong) {
+    if (return_success) {
+      DCHECK(GetAccessModeTemplate() == mirror::VarHandle::AccessModeTemplate::kCompareAndSet);
+    } else {
+      DCHECK(GetAccessModeTemplate() == mirror::VarHandle::AccessModeTemplate::kCompareAndExchange);
+    }
+    return_success_ = return_success;
+    strong_ = strong;
+  }
+
+  void SetGetAndUpdateOp(GetAndUpdateOp get_and_update_op) {
+    DCHECK(GetAccessModeTemplate() == mirror::VarHandle::AccessModeTemplate::kGetAndUpdate);
+    get_and_update_op_ = get_and_update_op;
+  }
+
+  void EmitNativeCode(CodeGenerator* codegen_in) override {
+    if (GetByteArrayViewCheckLabel()->IsLinked()) {
+      EmitByteArrayViewCode(codegen_in);
+    }
+    IntrinsicSlowPathARM64::EmitNativeCode(codegen_in);
+  }
+
+ private:
+  HInvoke* GetInvoke() const {
+    return GetInstruction()->AsInvoke();
+  }
+
+  mirror::VarHandle::AccessModeTemplate GetAccessModeTemplate() const {
+    return mirror::VarHandle::GetAccessModeTemplateByIntrinsic(GetInvoke()->GetIntrinsic());
+  }
+
+  void EmitByteArrayViewCode(CodeGenerator* codegen_in);
+
+  vixl::aarch64::Label byte_array_view_check_label_;
+  vixl::aarch64::Label native_byte_order_label_;
+  // Shared parameter for all VarHandle intrinsics.
+  std::memory_order order_;
+  // Extra arguments for GenerateVarHandleCompareAndSetOrExchange().
+  bool return_success_;
+  bool strong_;
+  // Extra argument for GenerateVarHandleGetAndUpdate().
+  GetAndUpdateOp get_and_update_op_;
+};
+
+// Generate subtype check without read barriers.
+static void GenerateSubTypeObjectCheckNoReadBarrier(CodeGeneratorARM64* codegen,
+                                                    SlowPathCodeARM64* slow_path,
+                                                    Register object,
+                                                    Register type,
+                                                    bool object_can_be_null = true) {
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+
+  const MemberOffset class_offset = mirror::Object::ClassOffset();
+  const MemberOffset super_class_offset = mirror::Class::SuperClassOffset();
+
+  vixl::aarch64::Label success;
+  if (object_can_be_null) {
+    __ Cbz(object, &success);
+  }
+
+  UseScratchRegisterScope temps(masm);
+  Register temp = temps.AcquireW();
+
+  __ Ldr(temp, HeapOperand(object, class_offset.Int32Value()));
+  codegen->GetAssembler()->MaybeUnpoisonHeapReference(temp);
+  vixl::aarch64::Label loop;
+  __ Bind(&loop);
+  __ Cmp(type, temp);
+  __ B(&success, eq);
+  __ Ldr(temp, HeapOperand(temp, super_class_offset.Int32Value()));
+  codegen->GetAssembler()->MaybeUnpoisonHeapReference(temp);
+  __ Cbz(temp, slow_path->GetEntryLabel());
+  __ B(&loop);
+  __ Bind(&success);
+}
+
+// Check access mode and the primitive type from VarHandle.varType.
+// Check reference arguments against the VarHandle.varType; for references this is a subclass
+// check without read barrier, so it can have false negatives which we handle in the slow path.
+static void GenerateVarHandleAccessModeAndVarTypeChecks(HInvoke* invoke,
+                                                        CodeGeneratorARM64* codegen,
+                                                        SlowPathCodeARM64* slow_path,
+                                                        DataType::Type type) {
+  mirror::VarHandle::AccessMode access_mode =
+      mirror::VarHandle::GetAccessModeByIntrinsic(invoke->GetIntrinsic());
+  Primitive::Type primitive_type = DataTypeToPrimitive(type);
+
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  Register varhandle = InputRegisterAt(invoke, 0);
+
+  const MemberOffset var_type_offset = mirror::VarHandle::VarTypeOffset();
+  const MemberOffset access_mode_bit_mask_offset = mirror::VarHandle::AccessModesBitMaskOffset();
+  const MemberOffset primitive_type_offset = mirror::Class::PrimitiveTypeOffset();
+
+  UseScratchRegisterScope temps(masm);
+  Register var_type_no_rb = temps.AcquireW();
+  Register temp2 = temps.AcquireW();
+
+  // Check that the operation is permitted and the primitive type of varhandle.varType.
+  // We do not need a read barrier when loading a reference only for loading constant
+  // primitive field through the reference. Use LDP to load the fields together.
+  DCHECK_EQ(var_type_offset.Int32Value() + 4, access_mode_bit_mask_offset.Int32Value());
+  __ Ldp(var_type_no_rb, temp2, HeapOperand(varhandle, var_type_offset.Int32Value()));
+  codegen->GetAssembler()->MaybeUnpoisonHeapReference(var_type_no_rb);
+  __ Tbz(temp2, static_cast<uint32_t>(access_mode), slow_path->GetEntryLabel());
+  __ Ldrh(temp2, HeapOperand(var_type_no_rb, primitive_type_offset.Int32Value()));
+  if (primitive_type == Primitive::kPrimNot) {
+    static_assert(Primitive::kPrimNot == 0);
+    __ Cbnz(temp2, slow_path->GetEntryLabel());
+  } else {
+    __ Cmp(temp2, static_cast<uint16_t>(primitive_type));
+    __ B(slow_path->GetEntryLabel(), ne);
+  }
+
+  temps.Release(temp2);
+
+  if (type == DataType::Type::kReference) {
+    // Check reference arguments against the varType.
+    // False negatives due to varType being an interface or array type
+    // or due to the missing read barrier are handled by the slow path.
+    size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+    uint32_t arguments_start = /* VarHandle object */ 1u + expected_coordinates_count;
+    uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+    for (size_t arg_index = arguments_start; arg_index != number_of_arguments; ++arg_index) {
+      HInstruction* arg = invoke->InputAt(arg_index);
+      DCHECK_EQ(arg->GetType(), DataType::Type::kReference);
+      if (!arg->IsNullConstant()) {
+        Register arg_reg = WRegisterFrom(invoke->GetLocations()->InAt(arg_index));
+        GenerateSubTypeObjectCheckNoReadBarrier(codegen, slow_path, arg_reg, var_type_no_rb);
+      }
+    }
+  }
+}
+
+static void GenerateVarHandleStaticFieldCheck(HInvoke* invoke,
+                                              CodeGeneratorARM64* codegen,
+                                              SlowPathCodeARM64* slow_path) {
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  Register varhandle = InputRegisterAt(invoke, 0);
+
+  const MemberOffset coordinate_type0_offset = mirror::VarHandle::CoordinateType0Offset();
+
+  UseScratchRegisterScope temps(masm);
+  Register temp = temps.AcquireW();
+
+  // Check that the VarHandle references a static field by checking that coordinateType0 == null.
+  // Do not emit read barrier (or unpoison the reference) for comparing to null.
+  __ Ldr(temp, HeapOperand(varhandle, coordinate_type0_offset.Int32Value()));
+  __ Cbnz(temp, slow_path->GetEntryLabel());
+}
+
+static void GenerateVarHandleInstanceFieldChecks(HInvoke* invoke,
+                                                 CodeGeneratorARM64* codegen,
+                                                 SlowPathCodeARM64* slow_path) {
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  Register varhandle = InputRegisterAt(invoke, 0);
+  Register object = InputRegisterAt(invoke, 1);
+
+  const MemberOffset coordinate_type0_offset = mirror::VarHandle::CoordinateType0Offset();
+  const MemberOffset coordinate_type1_offset = mirror::VarHandle::CoordinateType1Offset();
+
+  // Null-check the object.
+  __ Cbz(object, slow_path->GetEntryLabel());
+
+  UseScratchRegisterScope temps(masm);
+  Register temp = temps.AcquireW();
+  Register temp2 = temps.AcquireW();
+
+  // Check that the VarHandle references an instance field by checking that
+  // coordinateType1 == null. coordinateType0 should not be null, but this is handled by the
+  // type compatibility check with the source object's type, which will fail for null.
+  DCHECK_EQ(coordinate_type0_offset.Int32Value() + 4, coordinate_type1_offset.Int32Value());
+  __ Ldp(temp, temp2, HeapOperand(varhandle, coordinate_type0_offset.Int32Value()));
+  codegen->GetAssembler()->MaybeUnpoisonHeapReference(temp);
+  // No need for read barrier or unpoisoning of coordinateType1 for comparison with null.
+  __ Cbnz(temp2, slow_path->GetEntryLabel());
+
+  // Check that the object has the correct type.
+  // We deliberately avoid the read barrier, letting the slow path handle the false negatives.
+  temps.Release(temp2);  // Needed by GenerateSubTypeObjectCheckNoReadBarrier().
+  GenerateSubTypeObjectCheckNoReadBarrier(
+      codegen, slow_path, object, temp, /*object_can_be_null=*/ false);
+}
+
+static DataType::Type GetVarHandleExpectedValueType(HInvoke* invoke,
+                                                    size_t expected_coordinates_count) {
+  DCHECK_EQ(expected_coordinates_count, GetExpectedVarHandleCoordinatesCount(invoke));
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  DCHECK_GE(number_of_arguments, /* VarHandle object */ 1u + expected_coordinates_count);
+  if (number_of_arguments == /* VarHandle object */ 1u + expected_coordinates_count) {
+    return invoke->GetType();
+  } else {
+    return GetDataTypeFromShorty(invoke, number_of_arguments - 1u);
+  }
+}
+
+static void GenerateVarHandleArrayChecks(HInvoke* invoke,
+                                         CodeGeneratorARM64* codegen,
+                                         VarHandleSlowPathARM64* slow_path) {
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  Register varhandle = InputRegisterAt(invoke, 0);
+  Register object = InputRegisterAt(invoke, 1);
+  Register index = InputRegisterAt(invoke, 2);
+  DataType::Type value_type =
+      GetVarHandleExpectedValueType(invoke, /*expected_coordinates_count=*/ 2u);
+  Primitive::Type primitive_type = DataTypeToPrimitive(value_type);
+
+  const MemberOffset coordinate_type0_offset = mirror::VarHandle::CoordinateType0Offset();
+  const MemberOffset coordinate_type1_offset = mirror::VarHandle::CoordinateType1Offset();
+  const MemberOffset component_type_offset = mirror::Class::ComponentTypeOffset();
+  const MemberOffset primitive_type_offset = mirror::Class::PrimitiveTypeOffset();
+  const MemberOffset class_offset = mirror::Object::ClassOffset();
+  const MemberOffset array_length_offset = mirror::Array::LengthOffset();
+
+  // Null-check the object.
+  __ Cbz(object, slow_path->GetEntryLabel());
+
+  UseScratchRegisterScope temps(masm);
+  Register temp = temps.AcquireW();
+  Register temp2 = temps.AcquireW();
+
+  // Check that the VarHandle references an array, byte array view or ByteBuffer by checking
+  // that coordinateType1 != null. If that's true, coordinateType1 shall be int.class and
+  // coordinateType0 shall not be null but we do not explicitly verify that.
+  DCHECK_EQ(coordinate_type0_offset.Int32Value() + 4, coordinate_type1_offset.Int32Value());
+  __ Ldp(temp, temp2, HeapOperand(varhandle, coordinate_type0_offset.Int32Value()));
+  codegen->GetAssembler()->MaybeUnpoisonHeapReference(temp);
+  // No need for read barrier or unpoisoning of coordinateType1 for comparison with null.
+  __ Cbz(temp2, slow_path->GetEntryLabel());
+
+  // Check object class against componentType0.
+  //
+  // This is an exact check and we defer other cases to the runtime. This includes
+  // conversion to array of superclass references, which is valid but subsequently
+  // requires all update operations to check that the value can indeed be stored.
+  // We do not want to perform such extra checks in the intrinsified code.
+  //
+  // We do this check without read barrier, so there can be false negatives which we
+  // defer to the slow path. There shall be no false negatives for array classes in the
+  // boot image (including Object[] and primitive arrays) because they are non-movable.
+  __ Ldr(temp2, HeapOperand(object, class_offset.Int32Value()));
+  codegen->GetAssembler()->MaybeUnpoisonHeapReference(temp2);
+  __ Cmp(temp, temp2);
+  __ B(slow_path->GetEntryLabel(), ne);
+
+  // Check that the coordinateType0 is an array type. We do not need a read barrier
+  // for loading constant reference fields (or chains of them) for comparison with null,
+  // nor for finally loading a constant primitive field (primitive type) below.
+  __ Ldr(temp2, HeapOperand(temp, component_type_offset.Int32Value()));
+  codegen->GetAssembler()->MaybeUnpoisonHeapReference(temp2);
+  __ Cbz(temp2, slow_path->GetEntryLabel());
+
+  // Check that the array component type matches the primitive type.
+  __ Ldrh(temp2, HeapOperand(temp2, primitive_type_offset.Int32Value()));
+  if (primitive_type == Primitive::kPrimNot) {
+    static_assert(Primitive::kPrimNot == 0);
+    __ Cbnz(temp2, slow_path->GetEntryLabel());
+  } else {
+    // With the exception of `kPrimNot` (handled above), `kPrimByte` and `kPrimBoolean`,
+    // we shall check for a byte array view in the slow path.
+    // The check requires the ByteArrayViewVarHandle.class to be in the boot image,
+    // so we cannot emit that if we're JITting without boot image.
+    bool boot_image_available =
+        codegen->GetCompilerOptions().IsBootImage() ||
+        !Runtime::Current()->GetHeap()->GetBootImageSpaces().empty();
+    DCHECK(boot_image_available || codegen->GetCompilerOptions().IsJitCompiler());
+    size_t can_be_view = (DataType::Size(value_type) != 1u) && boot_image_available;
+    vixl::aarch64::Label* slow_path_label =
+        can_be_view ? slow_path->GetByteArrayViewCheckLabel() : slow_path->GetEntryLabel();
+    __ Cmp(temp2, static_cast<uint16_t>(primitive_type));
+    __ B(slow_path_label, ne);
+  }
+
+  // Check for array index out of bounds.
+  __ Ldr(temp, HeapOperand(object, array_length_offset.Int32Value()));
+  __ Cmp(index, temp);
+  __ B(slow_path->GetEntryLabel(), hs);
+}
+
+static void GenerateVarHandleCoordinateChecks(HInvoke* invoke,
+                                              CodeGeneratorARM64* codegen,
+                                              VarHandleSlowPathARM64* slow_path) {
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (expected_coordinates_count == 0u) {
+    GenerateVarHandleStaticFieldCheck(invoke, codegen, slow_path);
+  } else if (expected_coordinates_count == 1u) {
+    GenerateVarHandleInstanceFieldChecks(invoke, codegen, slow_path);
+  } else {
+    DCHECK_EQ(expected_coordinates_count, 2u);
+    GenerateVarHandleArrayChecks(invoke, codegen, slow_path);
+  }
+}
+
+static VarHandleSlowPathARM64* GenerateVarHandleChecks(HInvoke* invoke,
+                                                       CodeGeneratorARM64* codegen,
+                                                       std::memory_order order,
+                                                       DataType::Type type) {
+  VarHandleSlowPathARM64* slow_path =
+      new (codegen->GetScopedAllocator()) VarHandleSlowPathARM64(invoke, order);
+  codegen->AddSlowPath(slow_path);
+
+  GenerateVarHandleAccessModeAndVarTypeChecks(invoke, codegen, slow_path, type);
+  GenerateVarHandleCoordinateChecks(invoke, codegen, slow_path);
+
+  return slow_path;
+}
+
+struct VarHandleTarget {
+  Register object;  // The object holding the value to operate on.
+  Register offset;  // The offset of the value to operate on.
+};
+
+static VarHandleTarget GetVarHandleTarget(HInvoke* invoke) {
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  LocationSummary* locations = invoke->GetLocations();
+
+  VarHandleTarget target;
+  // The temporary allocated for loading the offset.
+  target.offset = WRegisterFrom(locations->GetTemp(0u));
+  // The reference to the object that holds the value to operate on.
+  target.object = (expected_coordinates_count == 0u)
+      ? WRegisterFrom(locations->GetTemp(1u))
+      : InputRegisterAt(invoke, 1);
+  return target;
+}
+
+static void GenerateVarHandleTarget(HInvoke* invoke,
+                                    const VarHandleTarget& target,
+                                    CodeGeneratorARM64* codegen) {
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  Register varhandle = InputRegisterAt(invoke, 0);
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+
+  if (expected_coordinates_count <= 1u) {
+    // For static fields, we need to fill the `target.object` with the declaring class,
+    // so we can use `target.object` as temporary for the `ArtMethod*`. For instance fields,
+    // we do not need the declaring class, so we can forget the `ArtMethod*` when
+    // we load the `target.offset`, so use the `target.offset` to hold the `ArtMethod*`.
+    Register method = (expected_coordinates_count == 0) ? target.object : target.offset;
+
+    const MemberOffset art_field_offset = mirror::FieldVarHandle::ArtFieldOffset();
+    const MemberOffset offset_offset = ArtField::OffsetOffset();
+
+    // Load the ArtField, the offset and, if needed, declaring class.
+    __ Ldr(method.X(), HeapOperand(varhandle, art_field_offset.Int32Value()));
+    __ Ldr(target.offset, MemOperand(method.X(), offset_offset.Int32Value()));
+    if (expected_coordinates_count == 0u) {
+      codegen->GenerateGcRootFieldLoad(invoke,
+                                       LocationFrom(target.object),
+                                       method.X(),
+                                       ArtField::DeclaringClassOffset().Int32Value(),
+                                       /*fixup_label=*/ nullptr,
+                                       kCompilerReadBarrierOption);
+    }
+  } else {
+    DCHECK_EQ(expected_coordinates_count, 2u);
+    DataType::Type value_type =
+        GetVarHandleExpectedValueType(invoke, /*expected_coordinates_count=*/ 2u);
+    size_t size_shift = DataType::SizeShift(value_type);
+    MemberOffset data_offset = mirror::Array::DataOffset(DataType::Size(value_type));
+
+    Register index = InputRegisterAt(invoke, 2);
+    Register shifted_index = index;
+    if (size_shift != 0u) {
+      shifted_index = target.offset;
+      __ Lsl(shifted_index, index, size_shift);
+    }
+    __ Add(target.offset, shifted_index, data_offset.Int32Value());
+  }
+}
+
+static bool HasVarHandleIntrinsicImplementation(HInvoke* invoke) {
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (expected_coordinates_count > 2u) {
+    // Invalid coordinate count. This invoke shall throw at runtime.
+    return false;
+  }
+  if (expected_coordinates_count != 0u &&
+      invoke->InputAt(1)->GetType() != DataType::Type::kReference) {
+    // Except for static fields (no coordinates), the first coordinate must be a reference.
+    return false;
+  }
+  if (expected_coordinates_count == 2u) {
+    // For arrays and views, the second coordinate must be convertible to `int`.
+    // In this context, `boolean` is not convertible but we have to look at the shorty
+    // as compiler transformations can give the invoke a valid boolean input.
+    DataType::Type index_type = GetDataTypeFromShorty(invoke, 2);
+    if (index_type == DataType::Type::kBool ||
+        DataType::Kind(index_type) != DataType::Type::kInt32) {
+      return false;
+    }
+  }
+
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  DataType::Type return_type = invoke->GetType();
+  mirror::VarHandle::AccessModeTemplate access_mode_template =
+      mirror::VarHandle::GetAccessModeTemplateByIntrinsic(invoke->GetIntrinsic());
+  switch (access_mode_template) {
+    case mirror::VarHandle::AccessModeTemplate::kGet:
+      // The return type should be the same as varType, so it shouldn't be void.
+      if (return_type == DataType::Type::kVoid) {
+        return false;
+      }
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kSet:
+      if (return_type != DataType::Type::kVoid) {
+        return false;
+      }
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndSet: {
+      if (return_type != DataType::Type::kBool) {
+        return false;
+      }
+      uint32_t expected_value_index = number_of_arguments - 2;
+      uint32_t new_value_index = number_of_arguments - 1;
+      DataType::Type expected_value_type = GetDataTypeFromShorty(invoke, expected_value_index);
+      DataType::Type new_value_type = GetDataTypeFromShorty(invoke, new_value_index);
+      if (expected_value_type != new_value_type) {
+        return false;
+      }
+      break;
+    }
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndExchange: {
+      uint32_t expected_value_index = number_of_arguments - 2;
+      uint32_t new_value_index = number_of_arguments - 1;
+      DataType::Type expected_value_type = GetDataTypeFromShorty(invoke, expected_value_index);
+      DataType::Type new_value_type = GetDataTypeFromShorty(invoke, new_value_index);
+      if (expected_value_type != new_value_type || return_type != expected_value_type) {
+        return false;
+      }
+      break;
+    }
+    case mirror::VarHandle::AccessModeTemplate::kGetAndUpdate: {
+      DataType::Type value_type = GetDataTypeFromShorty(invoke, number_of_arguments - 1);
+      if (IsVarHandleGetAndAdd(invoke) &&
+          (value_type == DataType::Type::kReference || value_type == DataType::Type::kBool)) {
+        // We should only add numerical types.
+        return false;
+      } else if (IsVarHandleGetAndBitwiseOp(invoke) && !DataType::IsIntegralType(value_type)) {
+        // We can only apply operators to bitwise integral types.
+        // Note that bitwise VarHandle operations accept a non-integral boolean type and
+        // perform the appropriate logical operation. However, the result is the same as
+        // using the bitwise operation on our boolean representation and this fits well
+        // with DataType::IsIntegralType() treating the compiler type kBool as integral.
+        return false;
+      }
+      if (value_type != return_type) {
+        return false;
+      }
+      break;
+    }
+  }
+
+  return true;
+}
+
+static LocationSummary* CreateVarHandleCommonLocations(HInvoke* invoke) {
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  DataType::Type return_type = invoke->GetType();
+
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations =
+      new (allocator) LocationSummary(invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->SetInAt(0, Location::RequiresRegister());
+  // Require coordinates in registers. These are the object holding the value
+  // to operate on (except for static fields) and index (for arrays and views).
+  for (size_t i = 0; i != expected_coordinates_count; ++i) {
+    locations->SetInAt(/* VarHandle object */ 1u + i, Location::RequiresRegister());
+  }
+  if (return_type != DataType::Type::kVoid) {
+    if (DataType::IsFloatingPointType(return_type)) {
+      locations->SetOut(Location::RequiresFpuRegister());
+    } else {
+      locations->SetOut(Location::RequiresRegister());
+    }
+  }
+  uint32_t arguments_start = /* VarHandle object */ 1u + expected_coordinates_count;
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  for (size_t arg_index = arguments_start; arg_index != number_of_arguments; ++arg_index) {
+    HInstruction* arg = invoke->InputAt(arg_index);
+    if (IsConstantZeroBitPattern(arg)) {
+      locations->SetInAt(arg_index, Location::ConstantLocation(arg->AsConstant()));
+    } else if (DataType::IsFloatingPointType(arg->GetType())) {
+      locations->SetInAt(arg_index, Location::RequiresFpuRegister());
+    } else {
+      locations->SetInAt(arg_index, Location::RequiresRegister());
+    }
+  }
+
+  // Add a temporary for offset.
+  if ((kEmitCompilerReadBarrier && !kUseBakerReadBarrier) &&
+      GetExpectedVarHandleCoordinatesCount(invoke) == 0u) {  // For static fields.
+    // To preserve the offset value across the non-Baker read barrier slow path
+    // for loading the declaring class, use a fixed callee-save register.
+    constexpr int first_callee_save = CTZ(kArm64CalleeSaveRefSpills);
+    locations->AddTemp(Location::RegisterLocation(first_callee_save));
+  } else {
+    locations->AddTemp(Location::RequiresRegister());
+  }
+  if (expected_coordinates_count == 0u) {
+    // Add a temporary to hold the declaring class.
+    locations->AddTemp(Location::RequiresRegister());
+  }
+
+  return locations;
+}
+
+static void CreateVarHandleGetLocations(HInvoke* invoke) {
+  if (!HasVarHandleIntrinsicImplementation(invoke)) {
+    return;
+  }
+
+  if ((kEmitCompilerReadBarrier && !kUseBakerReadBarrier) &&
+      invoke->GetType() == DataType::Type::kReference &&
+      invoke->GetIntrinsic() != Intrinsics::kVarHandleGet &&
+      invoke->GetIntrinsic() != Intrinsics::kVarHandleGetOpaque) {
+    // Unsupported for non-Baker read barrier because the artReadBarrierSlow() ignores
+    // the passed reference and reloads it from the field. This gets the memory visibility
+    // wrong for Acquire/Volatile operations. b/173104084
+    return;
+  }
+
+  CreateVarHandleCommonLocations(invoke);
+}
+
+static void GenerateVarHandleGet(HInvoke* invoke,
+                                 CodeGeneratorARM64* codegen,
+                                 std::memory_order order,
+                                 bool byte_swap = false) {
+  DataType::Type type = invoke->GetType();
+  DCHECK_NE(type, DataType::Type::kVoid);
+
+  LocationSummary* locations = invoke->GetLocations();
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  CPURegister out = helpers::OutputCPURegister(invoke);
+
+  VarHandleTarget target = GetVarHandleTarget(invoke);
+  VarHandleSlowPathARM64* slow_path = nullptr;
+  if (!byte_swap) {
+    slow_path = GenerateVarHandleChecks(invoke, codegen, order, type);
+    GenerateVarHandleTarget(invoke, target, codegen);
+    __ Bind(slow_path->GetNativeByteOrderLabel());
+  }
+
+  // ARM64 load-acquire instructions are implicitly sequentially consistent.
+  bool use_load_acquire =
+      (order == std::memory_order_acquire) || (order == std::memory_order_seq_cst);
+  DCHECK(use_load_acquire || order == std::memory_order_relaxed);
+
+  // Load the value from the target location.
+  if (type == DataType::Type::kReference && kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+    // Piggy-back on the field load path using introspection for the Baker read barrier.
+    // The `target.offset` is a temporary, use it for field address.
+    Register tmp_ptr = target.offset.X();
+    __ Add(tmp_ptr, target.object.X(), target.offset.X());
+    codegen->GenerateFieldLoadWithBakerReadBarrier(invoke,
+                                                   locations->Out(),
+                                                   target.object,
+                                                   MemOperand(tmp_ptr),
+                                                   /*needs_null_check=*/ false,
+                                                   use_load_acquire);
+    DCHECK(!byte_swap);
+  } else {
+    MemOperand address(target.object.X(), target.offset.X());
+    CPURegister load_reg = out;
+    DataType::Type load_type = type;
+    UseScratchRegisterScope temps(masm);
+    if (byte_swap) {
+      if (type == DataType::Type::kInt16) {
+        // Avoid unnecessary sign extension before REV16.
+        load_type = DataType::Type::kUint16;
+      } else if (type == DataType::Type::kFloat32) {
+        load_type = DataType::Type::kInt32;
+        load_reg = target.offset.W();
+      } else if (type == DataType::Type::kFloat64) {
+        load_type = DataType::Type::kInt64;
+        load_reg = target.offset.X();
+      }
+    }
+    if (use_load_acquire) {
+      codegen->LoadAcquire(invoke, load_type, load_reg, address, /*needs_null_check=*/ false);
+    } else {
+      codegen->Load(load_type, load_reg, address);
+    }
+    if (type == DataType::Type::kReference) {
+      DCHECK(!byte_swap);
+      DCHECK(out.IsW());
+      Location out_loc = locations->Out();
+      Location object_loc = LocationFrom(target.object);
+      Location offset_loc = LocationFrom(target.offset);
+      codegen->MaybeGenerateReadBarrierSlow(invoke, out_loc, out_loc, object_loc, 0u, offset_loc);
+    } else if (byte_swap) {
+      GenerateReverseBytes(masm, type, load_reg, out);
+    }
+  }
+
+  if (!byte_swap) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGet(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGet(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_, std::memory_order_relaxed);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetOpaque(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetOpaque(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_, std::memory_order_relaxed);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAcquire(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAcquire(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetVolatile(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetVolatile(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_, std::memory_order_seq_cst);
+}
+
+static void CreateVarHandleSetLocations(HInvoke* invoke) {
+  if (!HasVarHandleIntrinsicImplementation(invoke)) {
+    return;
+  }
+
+  CreateVarHandleCommonLocations(invoke);
+}
+
+static void GenerateVarHandleSet(HInvoke* invoke,
+                                 CodeGeneratorARM64* codegen,
+                                 std::memory_order order,
+                                 bool byte_swap = false) {
+  uint32_t value_index = invoke->GetNumberOfArguments() - 1;
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, value_index);
+
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  CPURegister value = InputCPURegisterOrZeroRegAt(invoke, value_index);
+
+  VarHandleTarget target = GetVarHandleTarget(invoke);
+  VarHandleSlowPathARM64* slow_path = nullptr;
+  if (!byte_swap) {
+    slow_path = GenerateVarHandleChecks(invoke, codegen, order, value_type);
+    GenerateVarHandleTarget(invoke, target, codegen);
+    __ Bind(slow_path->GetNativeByteOrderLabel());
+  }
+
+  // ARM64 store-release instructions are implicitly sequentially consistent.
+  bool use_store_release =
+      (order == std::memory_order_release) || (order == std::memory_order_seq_cst);
+  DCHECK(use_store_release || order == std::memory_order_relaxed);
+
+  // Store the value to the target location.
+  {
+    CPURegister source = value;
+    UseScratchRegisterScope temps(masm);
+    if (kPoisonHeapReferences && value_type == DataType::Type::kReference) {
+      DCHECK(value.IsW());
+      Register temp = temps.AcquireW();
+      __ Mov(temp, value.W());
+      codegen->GetAssembler()->PoisonHeapReference(temp);
+      source = temp;
+    }
+    if (byte_swap) {
+      DCHECK(!source.IsZero());  // We use the main path for zero as it does not need a byte swap.
+      Register temp = source.Is64Bits() ? temps.AcquireX() : temps.AcquireW();
+      if (value_type == DataType::Type::kInt16) {
+        // Avoid unnecessary sign extension before storing.
+        value_type = DataType::Type::kUint16;
+      } else if (DataType::IsFloatingPointType(value_type)) {
+        __ Fmov(temp, source.Is64Bits() ? source.D() : source.S());
+        value_type = source.Is64Bits() ? DataType::Type::kInt64 : DataType::Type::kInt32;
+        source = temp;  // Source for the `GenerateReverseBytes()` below.
+      }
+      GenerateReverseBytes(masm, value_type, source, temp);
+      source = temp;
+    }
+    MemOperand address(target.object.X(), target.offset.X());
+    if (use_store_release) {
+      codegen->StoreRelease(invoke, value_type, source, address, /*needs_null_check=*/ false);
+    } else {
+      codegen->Store(value_type, source, address);
+    }
+  }
+
+  if (CodeGenerator::StoreNeedsWriteBarrier(value_type, invoke->InputAt(value_index))) {
+    codegen->MarkGCCard(target.object, Register(value), /*value_can_be_null=*/ true);
+  }
+
+  if (!byte_swap) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleSet(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleSet(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_, std::memory_order_relaxed);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleSetOpaque(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleSetOpaque(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_, std::memory_order_relaxed);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleSetRelease(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleSetRelease(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_, std::memory_order_release);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleSetVolatile(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleSetVolatile(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_, std::memory_order_seq_cst);
+}
+
+static void CreateVarHandleCompareAndSetOrExchangeLocations(HInvoke* invoke, bool return_success) {
+  if (!HasVarHandleIntrinsicImplementation(invoke)) {
+    return;
+  }
+
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, number_of_arguments - 1u);
+  if ((kEmitCompilerReadBarrier && !kUseBakerReadBarrier) &&
+      value_type == DataType::Type::kReference) {
+    // Unsupported for non-Baker read barrier because the artReadBarrierSlow() ignores
+    // the passed reference and reloads it from the field. This breaks the read barriers
+    // in slow path in different ways. The marked old value may not actually be a to-space
+    // reference to the same object as `old_value`, breaking slow path assumptions. And
+    // for CompareAndExchange, marking the old value after comparison failure may actually
+    // return the reference to `expected`, erroneously indicating success even though we
+    // did not set the new value. (And it also gets the memory visibility wrong.) b/173104084
+    return;
+  }
+
+  LocationSummary* locations = CreateVarHandleCommonLocations(invoke);
+
+  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+    // We need callee-save registers for both the class object and offset instead of
+    // the temporaries reserved in CreateVarHandleCommonLocations().
+    static_assert(POPCOUNT(kArm64CalleeSaveRefSpills) >= 2u);
+    uint32_t first_callee_save = CTZ(kArm64CalleeSaveRefSpills);
+    uint32_t second_callee_save = CTZ(kArm64CalleeSaveRefSpills ^ (1u << first_callee_save));
+    if (GetExpectedVarHandleCoordinatesCount(invoke) == 0u) {  // For static fields.
+      DCHECK_EQ(locations->GetTempCount(), 2u);
+      DCHECK(locations->GetTemp(0u).Equals(Location::RequiresRegister()));
+      DCHECK(locations->GetTemp(1u).Equals(Location::RegisterLocation(first_callee_save)));
+      locations->SetTempAt(0u, Location::RegisterLocation(second_callee_save));
+    } else {
+      DCHECK_EQ(locations->GetTempCount(), 1u);
+      DCHECK(locations->GetTemp(0u).Equals(Location::RequiresRegister()));
+      locations->SetTempAt(0u, Location::RegisterLocation(first_callee_save));
+    }
+  }
+  size_t old_temp_count = locations->GetTempCount();
+  DCHECK_EQ(old_temp_count, (GetExpectedVarHandleCoordinatesCount(invoke) == 0) ? 2u : 1u);
+  if (!return_success) {
+    if (DataType::IsFloatingPointType(value_type)) {
+      // Add a temporary for old value and exclusive store result if floating point
+      // `expected` and/or `new_value` take scratch registers.
+      size_t available_scratch_registers =
+          (IsConstantZeroBitPattern(invoke->InputAt(number_of_arguments - 1u)) ? 1u : 0u) +
+          (IsConstantZeroBitPattern(invoke->InputAt(number_of_arguments - 2u)) ? 1u : 0u);
+      size_t temps_needed = /* pointer, old value, store result */ 3u - available_scratch_registers;
+      // We can reuse the declaring class (if present) and offset temporary.
+      if (temps_needed > old_temp_count) {
+        locations->AddRegisterTemps(temps_needed - old_temp_count);
+      }
+    } else if ((value_type != DataType::Type::kReference && DataType::Size(value_type) != 1u) &&
+               !IsConstantZeroBitPattern(invoke->InputAt(number_of_arguments - 2u)) &&
+               !IsConstantZeroBitPattern(invoke->InputAt(number_of_arguments - 1u)) &&
+               GetExpectedVarHandleCoordinatesCount(invoke) == 2u) {
+      // Allocate a normal temporary for store result in the non-native byte order path
+      // because scratch registers are used by the byte-swapped `expected` and `new_value`.
+      DCHECK_EQ(old_temp_count, 1u);
+      locations->AddTemp(Location::RequiresRegister());
+    }
+  }
+  if (kEmitCompilerReadBarrier && value_type == DataType::Type::kReference) {
+    // Add a temporary for the `old_value_temp` in slow path.
+    locations->AddTemp(Location::RequiresRegister());
+  }
+}
+
+static Register MoveToTempIfFpRegister(const CPURegister& cpu_reg,
+                                       DataType::Type type,
+                                       MacroAssembler* masm,
+                                       UseScratchRegisterScope* temps) {
+  if (cpu_reg.IsS()) {
+    DCHECK_EQ(type, DataType::Type::kFloat32);
+    Register reg = temps->AcquireW();
+    __ Fmov(reg, cpu_reg.S());
+    return reg;
+  } else if (cpu_reg.IsD()) {
+    DCHECK_EQ(type, DataType::Type::kFloat64);
+    Register reg = temps->AcquireX();
+    __ Fmov(reg, cpu_reg.D());
+    return reg;
+  } else {
+    return DataType::Is64BitType(type) ? cpu_reg.X() : cpu_reg.W();
+  }
+}
+
+static void GenerateVarHandleCompareAndSetOrExchange(HInvoke* invoke,
+                                                     CodeGeneratorARM64* codegen,
+                                                     std::memory_order order,
+                                                     bool return_success,
+                                                     bool strong,
+                                                     bool byte_swap = false) {
+  DCHECK(return_success || strong);
+
+  uint32_t expected_index = invoke->GetNumberOfArguments() - 2;
+  uint32_t new_value_index = invoke->GetNumberOfArguments() - 1;
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, new_value_index);
+  DCHECK_EQ(value_type, GetDataTypeFromShorty(invoke, expected_index));
+
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  CPURegister expected = InputCPURegisterOrZeroRegAt(invoke, expected_index);
+  CPURegister new_value = InputCPURegisterOrZeroRegAt(invoke, new_value_index);
+  CPURegister out = helpers::OutputCPURegister(invoke);
+
+  VarHandleTarget target = GetVarHandleTarget(invoke);
+  VarHandleSlowPathARM64* slow_path = nullptr;
+  if (!byte_swap) {
+    slow_path = GenerateVarHandleChecks(invoke, codegen, order, value_type);
+    slow_path->SetCompareAndSetOrExchangeArgs(return_success, strong);
+    GenerateVarHandleTarget(invoke, target, codegen);
+    __ Bind(slow_path->GetNativeByteOrderLabel());
+  }
+
+  // This needs to be before the temp registers, as MarkGCCard also uses VIXL temps.
+  if (CodeGenerator::StoreNeedsWriteBarrier(value_type, invoke->InputAt(new_value_index))) {
+    // Mark card for object assuming new value is stored.
+    bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(target.object, new_value.W(), new_value_can_be_null);
+  }
+
+  // Reuse the `offset` temporary for the pointer to the target location,
+  // except for references that need the offset for the read barrier.
+  UseScratchRegisterScope temps(masm);
+  Register tmp_ptr = target.offset.X();
+  if (kEmitCompilerReadBarrier && value_type == DataType::Type::kReference) {
+    tmp_ptr = temps.AcquireX();
+  }
+  __ Add(tmp_ptr, target.object.X(), target.offset.X());
+
+  // Move floating point values to scratch registers.
+  // Note that float/double CAS uses bitwise comparison, rather than the operator==.
+  Register expected_reg = MoveToTempIfFpRegister(expected, value_type, masm, &temps);
+  Register new_value_reg = MoveToTempIfFpRegister(new_value, value_type, masm, &temps);
+  bool is_fp = DataType::IsFloatingPointType(value_type);
+  DataType::Type cas_type = is_fp
+      ? ((value_type == DataType::Type::kFloat64) ? DataType::Type::kInt64 : DataType::Type::kInt32)
+      : value_type;
+  // Avoid sign extension in the CAS loop by zero-extending `expected` before the loop. This adds
+  // one instruction for CompareAndExchange as we shall need to sign-extend the returned value.
+  if (value_type == DataType::Type::kInt16 && !expected.IsZero()) {
+    Register temp = temps.AcquireW();
+    __ Uxth(temp, expected_reg);
+    expected_reg = temp;
+    cas_type = DataType::Type::kUint16;
+  } else if (value_type == DataType::Type::kInt8 && !expected.IsZero()) {
+    Register temp = temps.AcquireW();
+    __ Uxtb(temp, expected_reg);
+    expected_reg = temp;
+    cas_type = DataType::Type::kUint8;
+  }
+
+  if (byte_swap) {
+    // Do the byte swap and move values to scratch registers if needed.
+    // Non-zero FP values and non-zero `expected` for `kInt16` are already in scratch registers.
+    DCHECK_NE(value_type, DataType::Type::kInt8);
+    if (!expected.IsZero()) {
+      bool is_scratch = is_fp || (value_type == DataType::Type::kInt16);
+      Register temp = is_scratch ? expected_reg : temps.AcquireSameSizeAs(expected_reg);
+      GenerateReverseBytes(masm, cas_type, expected_reg, temp);
+      expected_reg = temp;
+    }
+    if (!new_value.IsZero()) {
+      Register temp = is_fp ? new_value_reg : temps.AcquireSameSizeAs(new_value_reg);
+      GenerateReverseBytes(masm, cas_type, new_value_reg, temp);
+      new_value_reg = temp;
+    }
+  }
+
+  // Prepare registers for old value and the result of the exclusive store.
+  Register old_value;
+  Register store_result;
+  if (return_success) {
+    // Use the output register for both old value and exclusive store result.
+    old_value = (cas_type == DataType::Type::kInt64) ? out.X() : out.W();
+    store_result = out.W();
+  } else if (DataType::IsFloatingPointType(value_type)) {
+    // We need two temporary registers but we have already used scratch registers for
+    // holding the expected and new value unless they are zero bit pattern (+0.0f or
+    // +0.0). We have allocated sufficient normal temporaries to handle that.
+    size_t next_temp = 1u;
+    if (expected.IsZero()) {
+      old_value = (cas_type == DataType::Type::kInt64) ? temps.AcquireX() : temps.AcquireW();
+    } else {
+      Location temp = locations->GetTemp(next_temp);
+      ++next_temp;
+      old_value = (cas_type == DataType::Type::kInt64) ? XRegisterFrom(temp) : WRegisterFrom(temp);
+    }
+    store_result =
+        new_value.IsZero() ? temps.AcquireW() : WRegisterFrom(locations->GetTemp(next_temp));
+    DCHECK(!old_value.Is(tmp_ptr));
+    DCHECK(!store_result.Is(tmp_ptr));
+  } else {
+    // Use the output register for the old value.
+    old_value = (cas_type == DataType::Type::kInt64) ? out.X() : out.W();
+    // Use scratch register for the store result, except when we have used up
+    // scratch registers for byte-swapped `expected` and `new_value`.
+    // In that case, we have allocated a normal temporary.
+    store_result = (byte_swap && !expected.IsZero() && !new_value.IsZero())
+        ? WRegisterFrom(locations->GetTemp(1))
+        : temps.AcquireW();
+    DCHECK(!store_result.Is(tmp_ptr));
+  }
+
+  vixl::aarch64::Label exit_loop_label;
+  vixl::aarch64::Label* exit_loop = &exit_loop_label;
+  vixl::aarch64::Label* cmp_failure = &exit_loop_label;
+
+  if (kEmitCompilerReadBarrier && value_type == DataType::Type::kReference) {
+    // The `old_value_temp` is used first for the marked `old_value` and then for the unmarked
+    // reloaded old value for subsequent CAS in the slow path. It cannot be a scratch register.
+    size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+    Register old_value_temp =
+        WRegisterFrom(locations->GetTemp((expected_coordinates_count == 0u) ? 2u : 1u));
+    // For strong CAS, use a scratch register for the store result in slow path.
+    // For weak CAS, we need to check the store result, so store it in `store_result`.
+    Register slow_path_store_result = strong ? Register() : store_result;
+    ReadBarrierCasSlowPathARM64* rb_slow_path =
+        new (codegen->GetScopedAllocator()) ReadBarrierCasSlowPathARM64(
+            invoke,
+            order,
+            strong,
+            target.object,
+            target.offset.X(),
+            expected_reg,
+            new_value_reg,
+            old_value,
+            old_value_temp,
+            slow_path_store_result,
+            /*update_old_value=*/ !return_success,
+            codegen);
+    codegen->AddSlowPath(rb_slow_path);
+    exit_loop = rb_slow_path->GetExitLabel();
+    cmp_failure = rb_slow_path->GetEntryLabel();
+  }
+
+  GenerateCompareAndSet(codegen,
+                        cas_type,
+                        order,
+                        strong,
+                        cmp_failure,
+                        tmp_ptr,
+                        new_value_reg,
+                        old_value,
+                        store_result,
+                        expected_reg);
+  __ Bind(exit_loop);
+
+  if (return_success) {
+    if (strong) {
+      __ Cset(out.W(), eq);
+    } else {
+      // On success, the Z flag is set and the store result is 1, see GenerateCompareAndSet().
+      // On failure, either the Z flag is clear or the store result is 0.
+      // Determine the final success value with a CSEL.
+      __ Csel(out.W(), store_result, wzr, eq);
+    }
+  } else if (byte_swap) {
+    // Also handles moving to FP registers.
+    GenerateReverseBytes(masm, value_type, old_value, out);
+  } else if (DataType::IsFloatingPointType(value_type)) {
+    __ Fmov((value_type == DataType::Type::kFloat64) ? out.D() : out.S(), old_value);
+  } else if (value_type == DataType::Type::kInt8) {
+    __ Sxtb(out.W(), old_value);
+  } else if (value_type == DataType::Type::kInt16) {
+    __ Sxth(out.W(), old_value);
+  }
+
+  if (!byte_swap) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleCompareAndExchange(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ false);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleCompareAndExchange(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_seq_cst, /*return_success=*/ false, /*strong=*/ true);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleCompareAndExchangeAcquire(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ false);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleCompareAndExchangeAcquire(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_acquire, /*return_success=*/ false, /*strong=*/ true);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleCompareAndExchangeRelease(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ false);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleCompareAndExchangeRelease(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_release, /*return_success=*/ false, /*strong=*/ true);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleCompareAndSet(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ true);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleCompareAndSet(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_seq_cst, /*return_success=*/ true, /*strong=*/ true);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleWeakCompareAndSet(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ true);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleWeakCompareAndSet(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_seq_cst, /*return_success=*/ true, /*strong=*/ false);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleWeakCompareAndSetAcquire(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ true);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleWeakCompareAndSetAcquire(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_acquire, /*return_success=*/ true, /*strong=*/ false);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleWeakCompareAndSetPlain(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ true);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleWeakCompareAndSetPlain(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_relaxed, /*return_success=*/ true, /*strong=*/ false);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleWeakCompareAndSetRelease(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ true);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleWeakCompareAndSetRelease(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_release, /*return_success=*/ true, /*strong=*/ false);
+}
+
+static void CreateVarHandleGetAndUpdateLocations(HInvoke* invoke,
+                                                 GetAndUpdateOp get_and_update_op) {
+  if (!HasVarHandleIntrinsicImplementation(invoke)) {
+    return;
+  }
+
+  if ((kEmitCompilerReadBarrier && !kUseBakerReadBarrier) &&
+      invoke->GetType() == DataType::Type::kReference) {
+    // Unsupported for non-Baker read barrier because the artReadBarrierSlow() ignores
+    // the passed reference and reloads it from the field, thus seeing the new value
+    // that we have just stored. (And it also gets the memory visibility wrong.) b/173104084
+    return;
+  }
+
+  LocationSummary* locations = CreateVarHandleCommonLocations(invoke);
+
+  size_t old_temp_count = locations->GetTempCount();
+  DCHECK_EQ(old_temp_count, (GetExpectedVarHandleCoordinatesCount(invoke) == 0) ? 2u : 1u);
+  if (DataType::IsFloatingPointType(invoke->GetType())) {
+    if (get_and_update_op == GetAndUpdateOp::kAdd) {
+      // For ADD, do not use ZR for zero bit pattern (+0.0f or +0.0).
+      locations->SetInAt(invoke->GetNumberOfArguments() - 1u, Location::RequiresFpuRegister());
+    } else {
+      DCHECK(get_and_update_op == GetAndUpdateOp::kSet);
+      // We can reuse the declaring class temporary if present.
+      if (old_temp_count == 1u &&
+          !IsConstantZeroBitPattern(invoke->InputAt(invoke->GetNumberOfArguments() - 1u))) {
+        // Add a temporary for `old_value` if floating point `new_value` takes a scratch register.
+        locations->AddTemp(Location::RequiresRegister());
+      }
+    }
+  }
+  // We need a temporary for the byte-swap path for bitwise operations unless the argument is a
+  // zero which does not need a byte-swap. We can reuse the declaring class temporary if present.
+  if (old_temp_count == 1u &&
+      (get_and_update_op != GetAndUpdateOp::kSet && get_and_update_op != GetAndUpdateOp::kAdd) &&
+      GetExpectedVarHandleCoordinatesCount(invoke) == 2u &&
+      !IsConstantZeroBitPattern(invoke->InputAt(invoke->GetNumberOfArguments() - 1u))) {
+    DataType::Type value_type =
+        GetVarHandleExpectedValueType(invoke, /*expected_coordinates_count=*/ 2u);
+    if (value_type != DataType::Type::kReference && DataType::Size(value_type) != 1u) {
+      locations->AddTemp(Location::RequiresRegister());
+    }
+  }
+}
+
+static void GenerateVarHandleGetAndUpdate(HInvoke* invoke,
+                                          CodeGeneratorARM64* codegen,
+                                          GetAndUpdateOp get_and_update_op,
+                                          std::memory_order order,
+                                          bool byte_swap = false) {
+  uint32_t arg_index = invoke->GetNumberOfArguments() - 1;
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, arg_index);
+
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  CPURegister arg = InputCPURegisterOrZeroRegAt(invoke, arg_index);
+  CPURegister out = helpers::OutputCPURegister(invoke);
+
+  VarHandleTarget target = GetVarHandleTarget(invoke);
+  VarHandleSlowPathARM64* slow_path = nullptr;
+  if (!byte_swap) {
+    slow_path = GenerateVarHandleChecks(invoke, codegen, order, value_type);
+    slow_path->SetGetAndUpdateOp(get_and_update_op);
+    GenerateVarHandleTarget(invoke, target, codegen);
+    __ Bind(slow_path->GetNativeByteOrderLabel());
+  }
+
+  // This needs to be before the temp registers, as MarkGCCard also uses VIXL temps.
+  if (CodeGenerator::StoreNeedsWriteBarrier(value_type, invoke->InputAt(arg_index))) {
+    DCHECK(get_and_update_op == GetAndUpdateOp::kSet);
+    // Mark card for object, the new value shall be stored.
+    bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(target.object, arg.W(), new_value_can_be_null);
+  }
+
+  // Reuse the `target.offset` temporary for the pointer to the target location,
+  // except for references that need the offset for the non-Baker read barrier.
+  UseScratchRegisterScope temps(masm);
+  Register tmp_ptr = target.offset.X();
+  if ((kEmitCompilerReadBarrier && !kUseBakerReadBarrier) &&
+      value_type == DataType::Type::kReference) {
+    tmp_ptr = temps.AcquireX();
+  }
+  __ Add(tmp_ptr, target.object.X(), target.offset.X());
+
+  // The load/store type is never floating point.
+  bool is_fp = DataType::IsFloatingPointType(value_type);
+  DataType::Type load_store_type = is_fp
+      ? ((value_type == DataType::Type::kFloat32) ? DataType::Type::kInt32 : DataType::Type::kInt64)
+      : value_type;
+  // Avoid sign extension in the CAS loop. Sign-extend after the loop.
+  // Note: Using unsigned values yields the same value to store (we do not store higher bits).
+  if (value_type == DataType::Type::kInt8) {
+    load_store_type = DataType::Type::kUint8;
+  } else if (value_type == DataType::Type::kInt16) {
+    load_store_type = DataType::Type::kUint16;
+  }
+
+  // Prepare register for old value.
+  CPURegister old_value = out;
+  if (get_and_update_op == GetAndUpdateOp::kSet) {
+    // For floating point GetAndSet, do the GenerateGetAndUpdate() with core registers,
+    // rather than moving between core and FP registers in the loop.
+    arg = MoveToTempIfFpRegister(arg, value_type, masm, &temps);
+    if (DataType::IsFloatingPointType(value_type) && !arg.IsZero()) {
+      // We need a temporary register but we have already used a scratch register for
+      // the new value unless it is zero bit pattern (+0.0f or +0.0) and need another one
+      // in GenerateGetAndUpdate(). We have allocated a normal temporary to handle that.
+      old_value = CPURegisterFrom(locations->GetTemp(1u), load_store_type);
+    } else if ((kEmitCompilerReadBarrier && kUseBakerReadBarrier) &&
+               value_type == DataType::Type::kReference) {
+      // Load the old value initially to a scratch register.
+      // We shall move it to `out` later with a read barrier.
+      old_value = temps.AcquireW();
+    }
+  }
+
+  if (byte_swap) {
+    DCHECK_NE(value_type, DataType::Type::kReference);
+    DCHECK_NE(DataType::Size(value_type), 1u);
+    if (get_and_update_op == GetAndUpdateOp::kAdd) {
+      // We need to do the byte swapping in the CAS loop for GetAndAdd.
+      get_and_update_op = GetAndUpdateOp::kAddWithByteSwap;
+    } else if (!arg.IsZero()) {
+      // For other operations, avoid byte swap inside the CAS loop by providing an adjusted `arg`.
+      // For GetAndSet use a scratch register; FP argument is already in a scratch register.
+      // For bitwise operations GenerateGetAndUpdate() needs both scratch registers;
+      // we have allocated a normal temporary to handle that.
+      CPURegister temp = (get_and_update_op == GetAndUpdateOp::kSet)
+          ? (is_fp ? arg : (arg.Is64Bits() ? temps.AcquireX() : temps.AcquireW()))
+          : CPURegisterFrom(locations->GetTemp(1u), load_store_type);
+      GenerateReverseBytes(masm, load_store_type, arg, temp);
+      arg = temp;
+    }
+  }
+
+  GenerateGetAndUpdate(codegen, get_and_update_op, load_store_type, order, tmp_ptr, arg, old_value);
+
+  if (get_and_update_op == GetAndUpdateOp::kAddWithByteSwap) {
+    // The only adjustment needed is sign-extension for `kInt16`.
+    // Everything else has been done by the `GenerateGetAndUpdate()`.
+    DCHECK(byte_swap);
+    if (value_type == DataType::Type::kInt16) {
+      DCHECK_EQ(load_store_type, DataType::Type::kUint16);
+      __ Sxth(out.W(), old_value.W());
+    }
+  } else if (byte_swap) {
+    // Also handles moving to FP registers.
+    GenerateReverseBytes(masm, value_type, old_value, out);
+  } else if (get_and_update_op == GetAndUpdateOp::kSet && value_type == DataType::Type::kFloat64) {
+    __ Fmov(out.D(), old_value.X());
+  } else if (get_and_update_op == GetAndUpdateOp::kSet && value_type == DataType::Type::kFloat32) {
+    __ Fmov(out.S(), old_value.W());
+  } else if (value_type == DataType::Type::kInt8) {
+    __ Sxtb(out.W(), old_value.W());
+  } else if (value_type == DataType::Type::kInt16) {
+    __ Sxth(out.W(), old_value.W());
+  } else if (kEmitCompilerReadBarrier && value_type == DataType::Type::kReference) {
+    if (kUseBakerReadBarrier) {
+      codegen->GenerateIntrinsicCasMoveWithBakerReadBarrier(out.W(), old_value.W());
+    } else {
+      codegen->GenerateReadBarrierSlow(
+          invoke,
+          Location::RegisterLocation(out.GetCode()),
+          Location::RegisterLocation(old_value.GetCode()),
+          Location::RegisterLocation(target.object.GetCode()),
+          /*offset=*/ 0u,
+          /*index=*/ Location::RegisterLocation(target.offset.GetCode()));
+    }
+  }
+
+  if (!byte_swap) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndSet(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kSet);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndSet(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kSet, std::memory_order_seq_cst);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndSetAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kSet);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndSetAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kSet, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndSetRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kSet);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndSetRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kSet, std::memory_order_release);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndAdd(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAdd);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndAdd(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAdd, std::memory_order_seq_cst);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndAddAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAdd);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndAddAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAdd, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndAddRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAdd);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndAddRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAdd, std::memory_order_release);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndBitwiseAnd(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAnd);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndBitwiseAnd(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAnd, std::memory_order_seq_cst);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndBitwiseAndAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAnd);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndBitwiseAndAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAnd, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndBitwiseAndRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAnd);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndBitwiseAndRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAnd, std::memory_order_release);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndBitwiseOr(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kOr);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndBitwiseOr(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kOr, std::memory_order_seq_cst);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndBitwiseOrAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kOr);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndBitwiseOrAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kOr, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndBitwiseOrRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kOr);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndBitwiseOrRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kOr, std::memory_order_release);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndBitwiseXor(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kXor);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndBitwiseXor(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kXor, std::memory_order_seq_cst);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndBitwiseXorAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kXor);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndBitwiseXorAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kXor, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitVarHandleGetAndBitwiseXorRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kXor);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitVarHandleGetAndBitwiseXorRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kXor, std::memory_order_release);
+}
+
+void VarHandleSlowPathARM64::EmitByteArrayViewCode(CodeGenerator* codegen_in) {
+  DCHECK(GetByteArrayViewCheckLabel()->IsLinked());
+  CodeGeneratorARM64* codegen = down_cast<CodeGeneratorARM64*>(codegen_in);
+  MacroAssembler* masm = codegen->GetVIXLAssembler();
+  HInvoke* invoke = GetInvoke();
+  mirror::VarHandle::AccessModeTemplate access_mode_template = GetAccessModeTemplate();
+  DataType::Type value_type =
+      GetVarHandleExpectedValueType(invoke, /*expected_coordinates_count=*/ 2u);
+  DCHECK_NE(value_type, DataType::Type::kReference);
+  size_t size = DataType::Size(value_type);
+  DCHECK_GT(size, 1u);
+  Register varhandle = InputRegisterAt(invoke, 0);
+  Register object = InputRegisterAt(invoke, 1);
+  Register index = InputRegisterAt(invoke, 2);
+
+  MemberOffset class_offset = mirror::Object::ClassOffset();
+  MemberOffset array_length_offset = mirror::Array::LengthOffset();
+  MemberOffset data_offset = mirror::Array::DataOffset(Primitive::kPrimByte);
+  MemberOffset native_byte_order_offset = mirror::ByteArrayViewVarHandle::NativeByteOrderOffset();
+
+  __ Bind(GetByteArrayViewCheckLabel());
+
+  VarHandleTarget target = GetVarHandleTarget(invoke);
+  {
+    UseScratchRegisterScope temps(masm);
+    Register temp = temps.AcquireW();
+    Register temp2 = temps.AcquireW();
+
+    // The main path checked that the coordinateType0 is an array class that matches
+    // the class of the actual coordinate argument but it does not match the value type.
+    // Check if the `varhandle` references a ByteArrayViewVarHandle instance.
+    __ Ldr(temp, HeapOperand(varhandle, class_offset.Int32Value()));
+    codegen->LoadClassRootForIntrinsic(temp2, ClassRoot::kJavaLangInvokeByteArrayViewVarHandle);
+    __ Cmp(temp, temp2);
+    __ B(GetEntryLabel(), ne);
+
+    // Check for array index out of bounds.
+    __ Ldr(temp, HeapOperand(object, array_length_offset.Int32Value()));
+    __ Subs(temp, temp, index);
+    __ Ccmp(temp, size, NoFlag, hs);  // If SUBS yields LO (C=false), keep the C flag clear.
+    __ B(GetEntryLabel(), lo);
+
+    // Construct the target.
+    __ Add(target.offset, index, data_offset.Int32Value());
+
+    // Alignment check. For unaligned access, go to the runtime.
+    DCHECK(IsPowerOfTwo(size));
+    if (size == 2u) {
+      __ Tbnz(target.offset, 0, GetEntryLabel());
+    } else {
+      __ Tst(target.offset, size - 1u);
+      __ B(GetEntryLabel(), ne);
+    }
+
+    // Byte order check. For native byte order return to the main path.
+    if (access_mode_template == mirror::VarHandle::AccessModeTemplate::kSet &&
+        IsConstantZeroBitPattern(invoke->InputAt(invoke->GetNumberOfArguments() - 1u))) {
+      // There is no reason to differentiate between native byte order and byte-swap
+      // for setting a zero bit pattern. Just return to the main path.
+      __ B(GetNativeByteOrderLabel());
+      return;
+    }
+    __ Ldr(temp, HeapOperand(varhandle, native_byte_order_offset.Int32Value()));
+    __ Cbnz(temp, GetNativeByteOrderLabel());
+  }
+
+  switch (access_mode_template) {
+    case mirror::VarHandle::AccessModeTemplate::kGet:
+      GenerateVarHandleGet(invoke, codegen, order_, /*byte_swap=*/ true);
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kSet:
+      GenerateVarHandleSet(invoke, codegen, order_, /*byte_swap=*/ true);
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndSet:
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndExchange:
+      GenerateVarHandleCompareAndSetOrExchange(
+          invoke, codegen, order_, return_success_, strong_, /*byte_swap=*/ true);
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kGetAndUpdate:
+      GenerateVarHandleGetAndUpdate(
+          invoke, codegen, get_and_update_op_, order_, /*byte_swap=*/ true);
+      break;
+  }
+  __ B(GetExitLabel());
+}
 
 UNIMPLEMENTED_INTRINSIC(ARM64, StringStringIndexOf);
 UNIMPLEMENTED_INTRINSIC(ARM64, StringStringIndexOfAfter);
@@ -3429,6 +5383,9 @@
 UNIMPLEMENTED_INTRINSIC(ARM64, UnsafeGetAndSetLong)
 UNIMPLEMENTED_INTRINSIC(ARM64, UnsafeGetAndSetObject)
 
+UNIMPLEMENTED_INTRINSIC(ARM64, MethodHandleInvokeExact)
+UNIMPLEMENTED_INTRINSIC(ARM64, MethodHandleInvoke)
+
 UNREACHABLE_INTRINSICS(ARM64)
 
 #undef __
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 89e5203..2a2f245 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -16,11 +16,14 @@
 
 #include "intrinsics_arm_vixl.h"
 
+#include "arch/arm/callee_save_frame_arm.h"
 #include "arch/arm/instruction_set_features_arm.h"
 #include "art_method.h"
 #include "code_generator_arm_vixl.h"
 #include "common_arm.h"
 #include "heap_poisoning.h"
+#include "intrinsics.h"
+#include "intrinsics_utils.h"
 #include "lock_word.h"
 #include "mirror/array-inl.h"
 #include "mirror/object_array-inl.h"
@@ -64,61 +67,9 @@
   return codegen_->GetGraph()->GetAllocator();
 }
 
-// Default slow-path for fallback (calling the managed code to handle the intrinsic) in an
-// intrinsified call. This will copy the arguments into the positions for a regular call.
-//
-// Note: The actual parameters are required to be in the locations given by the invoke's location
-//       summary. If an intrinsic modifies those locations before a slowpath call, they must be
-//       restored!
-//
-// Note: If an invoke wasn't sharpened, we will put down an invoke-virtual here. That's potentially
-//       sub-optimal (compared to a direct pointer call), but this is a slow-path.
-
-class IntrinsicSlowPathARMVIXL : public SlowPathCodeARMVIXL {
- public:
-  explicit IntrinsicSlowPathARMVIXL(HInvoke* invoke)
-      : SlowPathCodeARMVIXL(invoke), invoke_(invoke) {}
-
-  Location MoveArguments(CodeGenerator* codegen) {
-    InvokeDexCallingConventionVisitorARMVIXL calling_convention_visitor;
-    IntrinsicVisitor::MoveArguments(invoke_, codegen, &calling_convention_visitor);
-    return calling_convention_visitor.GetMethodLocation();
-  }
-
-  void EmitNativeCode(CodeGenerator* codegen) override {
-    ArmVIXLAssembler* assembler = down_cast<ArmVIXLAssembler*>(codegen->GetAssembler());
-    __ Bind(GetEntryLabel());
-
-    SaveLiveRegisters(codegen, invoke_->GetLocations());
-
-    Location method_loc = MoveArguments(codegen);
-
-    if (invoke_->IsInvokeStaticOrDirect()) {
-      codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), method_loc, this);
-    } else {
-      codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), method_loc, this);
-    }
-
-    // Copy the result back to the expected output.
-    Location out = invoke_->GetLocations()->Out();
-    if (out.IsValid()) {
-      DCHECK(out.IsRegister());  // TODO: Replace this when we support output in memory.
-      DCHECK(!invoke_->GetLocations()->GetLiveRegisters()->ContainsCoreRegister(out.reg()));
-      codegen->MoveFromReturnRegister(out, invoke_->GetType());
-    }
-
-    RestoreLiveRegisters(codegen, invoke_->GetLocations());
-    __ B(GetExitLabel());
-  }
-
-  const char* GetDescription() const override { return "IntrinsicSlowPath"; }
-
- private:
-  // The instruction where this slow path is happening.
-  HInvoke* const invoke_;
-
-  DISALLOW_COPY_AND_ASSIGN(IntrinsicSlowPathARMVIXL);
-};
+using IntrinsicSlowPathARMVIXL = IntrinsicSlowPath<InvokeDexCallingConventionVisitorARMVIXL,
+                                                   SlowPathCodeARMVIXL,
+                                                   ArmVIXLAssembler>;
 
 // Compute base address for the System.arraycopy intrinsic in `base`.
 static void GenSystemArrayCopyBaseAddress(ArmVIXLAssembler* assembler,
@@ -325,6 +276,15 @@
   locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
 }
 
+static void CreateIntIntToIntSlowPathCallLocations(ArenaAllocator* allocator, HInvoke* invoke) {
+  LocationSummary* locations =
+      new (allocator) LocationSummary(invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->SetInAt(0, Location::RequiresRegister());
+  locations->SetInAt(1, Location::RequiresRegister());
+  // Force kOutputOverlap; see comments in IntrinsicSlowPath::EmitNativeCode.
+  locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
+}
+
 static void CreateLongToLongLocationsWithOverlap(ArenaAllocator* allocator, HInvoke* invoke) {
   LocationSummary* locations =
       new (allocator) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
@@ -487,7 +447,7 @@
   __ Vcmp(F32, temp1, temp2);
   __ Vmrs(RegisterOrAPSR_nzcv(kPcCode), FPSCR);
   {
-    // Use ExactAsemblyScope here because we are using IT.
+    // Use ExactAssemblyScope here because we are using IT.
     ExactAssemblyScope it_scope(assembler->GetVIXLAssembler(),
                                 2 * kMaxInstructionSizeInBytes,
                                 CodeBufferCheckScope::kMaximumSize);
@@ -611,535 +571,6 @@
          MemOperand(tr, Thread::PeerOffset<kArmPointerSize>().Int32Value()));
 }
 
-static void GenUnsafeGet(HInvoke* invoke,
-                         DataType::Type type,
-                         bool is_volatile,
-                         CodeGeneratorARMVIXL* codegen) {
-  LocationSummary* locations = invoke->GetLocations();
-  ArmVIXLAssembler* assembler = codegen->GetAssembler();
-  Location base_loc = locations->InAt(1);
-  vixl32::Register base = InputRegisterAt(invoke, 1);     // Object pointer.
-  Location offset_loc = locations->InAt(2);
-  vixl32::Register offset = LowRegisterFrom(offset_loc);  // Long offset, lo part only.
-  Location trg_loc = locations->Out();
-
-  switch (type) {
-    case DataType::Type::kInt32: {
-      vixl32::Register trg = RegisterFrom(trg_loc);
-      __ Ldr(trg, MemOperand(base, offset));
-      if (is_volatile) {
-        __ Dmb(vixl32::ISH);
-      }
-      break;
-    }
-
-    case DataType::Type::kReference: {
-      vixl32::Register trg = RegisterFrom(trg_loc);
-      if (kEmitCompilerReadBarrier) {
-        if (kUseBakerReadBarrier) {
-          Location temp = locations->GetTemp(0);
-          // Piggy-back on the field load path using introspection for the Baker read barrier.
-          __ Add(RegisterFrom(temp), base, Operand(offset));
-          MemOperand src(RegisterFrom(temp), 0);
-          codegen->GenerateFieldLoadWithBakerReadBarrier(
-              invoke, trg_loc, base, src, /* needs_null_check= */ false);
-          if (is_volatile) {
-            __ Dmb(vixl32::ISH);
-          }
-        } else {
-          __ Ldr(trg, MemOperand(base, offset));
-          if (is_volatile) {
-            __ Dmb(vixl32::ISH);
-          }
-          codegen->GenerateReadBarrierSlow(invoke, trg_loc, trg_loc, base_loc, 0U, offset_loc);
-        }
-      } else {
-        __ Ldr(trg, MemOperand(base, offset));
-        if (is_volatile) {
-          __ Dmb(vixl32::ISH);
-        }
-        assembler->MaybeUnpoisonHeapReference(trg);
-      }
-      break;
-    }
-
-    case DataType::Type::kInt64: {
-      vixl32::Register trg_lo = LowRegisterFrom(trg_loc);
-      vixl32::Register trg_hi = HighRegisterFrom(trg_loc);
-      if (is_volatile && !codegen->GetInstructionSetFeatures().HasAtomicLdrdAndStrd()) {
-        UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
-        const vixl32::Register temp_reg = temps.Acquire();
-        __ Add(temp_reg, base, offset);
-        __ Ldrexd(trg_lo, trg_hi, MemOperand(temp_reg));
-      } else {
-        __ Ldrd(trg_lo, trg_hi, MemOperand(base, offset));
-      }
-      if (is_volatile) {
-        __ Dmb(vixl32::ISH);
-      }
-      break;
-    }
-
-    default:
-      LOG(FATAL) << "Unexpected type " << type;
-      UNREACHABLE();
-  }
-}
-
-static void CreateIntIntIntToIntLocations(ArenaAllocator* allocator,
-                                          HInvoke* invoke,
-                                          DataType::Type type) {
-  bool can_call = kEmitCompilerReadBarrier &&
-      (invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObject ||
-       invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObjectVolatile);
-  LocationSummary* locations =
-      new (allocator) LocationSummary(invoke,
-                                      can_call
-                                          ? LocationSummary::kCallOnSlowPath
-                                          : LocationSummary::kNoCall,
-                                      kIntrinsified);
-  if (can_call && kUseBakerReadBarrier) {
-    locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty());  // No caller-save registers.
-  }
-  locations->SetInAt(0, Location::NoLocation());        // Unused receiver.
-  locations->SetInAt(1, Location::RequiresRegister());
-  locations->SetInAt(2, Location::RequiresRegister());
-  locations->SetOut(Location::RequiresRegister(),
-                    (can_call ? Location::kOutputOverlap : Location::kNoOutputOverlap));
-  if (type == DataType::Type::kReference && kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
-    // We need a temporary register for the read barrier marking slow
-    // path in CodeGeneratorARMVIXL::GenerateReferenceLoadWithBakerReadBarrier.
-    locations->AddTemp(Location::RequiresRegister());
-  }
-}
-
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGet(HInvoke* invoke) {
-  CreateIntIntIntToIntLocations(allocator_, invoke, DataType::Type::kInt32);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetVolatile(HInvoke* invoke) {
-  CreateIntIntIntToIntLocations(allocator_, invoke, DataType::Type::kInt32);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetLong(HInvoke* invoke) {
-  CreateIntIntIntToIntLocations(allocator_, invoke, DataType::Type::kInt64);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetLongVolatile(HInvoke* invoke) {
-  CreateIntIntIntToIntLocations(allocator_, invoke, DataType::Type::kInt64);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetObject(HInvoke* invoke) {
-  CreateIntIntIntToIntLocations(allocator_, invoke, DataType::Type::kReference);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetObjectVolatile(HInvoke* invoke) {
-  CreateIntIntIntToIntLocations(allocator_, invoke, DataType::Type::kReference);
-}
-
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGet(HInvoke* invoke) {
-  GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile= */ false, codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetVolatile(HInvoke* invoke) {
-  GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile= */ true, codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetLong(HInvoke* invoke) {
-  GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile= */ false, codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetLongVolatile(HInvoke* invoke) {
-  GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile= */ true, codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetObject(HInvoke* invoke) {
-  GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile= */ false, codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetObjectVolatile(HInvoke* invoke) {
-  GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile= */ true, codegen_);
-}
-
-static void CreateIntIntIntIntToVoid(ArenaAllocator* allocator,
-                                     const ArmInstructionSetFeatures& features,
-                                     DataType::Type type,
-                                     bool is_volatile,
-                                     HInvoke* invoke) {
-  LocationSummary* locations =
-      new (allocator) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
-  locations->SetInAt(0, Location::NoLocation());        // Unused receiver.
-  locations->SetInAt(1, Location::RequiresRegister());
-  locations->SetInAt(2, Location::RequiresRegister());
-  locations->SetInAt(3, Location::RequiresRegister());
-
-  if (type == DataType::Type::kInt64) {
-    // Potentially need temps for ldrexd-strexd loop.
-    if (is_volatile && !features.HasAtomicLdrdAndStrd()) {
-      locations->AddTemp(Location::RequiresRegister());  // Temp_lo.
-      locations->AddTemp(Location::RequiresRegister());  // Temp_hi.
-    }
-  } else if (type == DataType::Type::kReference) {
-    // Temps for card-marking.
-    locations->AddTemp(Location::RequiresRegister());  // Temp.
-    locations->AddTemp(Location::RequiresRegister());  // Card.
-  }
-}
-
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePut(HInvoke* invoke) {
-  CreateIntIntIntIntToVoid(
-      allocator_, features_, DataType::Type::kInt32, /* is_volatile= */ false, invoke);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutOrdered(HInvoke* invoke) {
-  CreateIntIntIntIntToVoid(
-      allocator_, features_, DataType::Type::kInt32, /* is_volatile= */ false, invoke);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutVolatile(HInvoke* invoke) {
-  CreateIntIntIntIntToVoid(
-      allocator_, features_, DataType::Type::kInt32, /* is_volatile= */ true, invoke);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutObject(HInvoke* invoke) {
-  CreateIntIntIntIntToVoid(
-      allocator_, features_, DataType::Type::kReference, /* is_volatile= */ false, invoke);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutObjectOrdered(HInvoke* invoke) {
-  CreateIntIntIntIntToVoid(
-      allocator_, features_, DataType::Type::kReference, /* is_volatile= */ false, invoke);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutObjectVolatile(HInvoke* invoke) {
-  CreateIntIntIntIntToVoid(
-      allocator_, features_, DataType::Type::kReference, /* is_volatile= */ true, invoke);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutLong(HInvoke* invoke) {
-  CreateIntIntIntIntToVoid(
-      allocator_, features_, DataType::Type::kInt64, /* is_volatile= */ false, invoke);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutLongOrdered(HInvoke* invoke) {
-  CreateIntIntIntIntToVoid(
-      allocator_, features_, DataType::Type::kInt64, /* is_volatile= */ false, invoke);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutLongVolatile(HInvoke* invoke) {
-  CreateIntIntIntIntToVoid(
-      allocator_, features_, DataType::Type::kInt64, /* is_volatile= */ true, invoke);
-}
-
-static void GenUnsafePut(LocationSummary* locations,
-                         DataType::Type type,
-                         bool is_volatile,
-                         bool is_ordered,
-                         CodeGeneratorARMVIXL* codegen) {
-  ArmVIXLAssembler* assembler = codegen->GetAssembler();
-
-  vixl32::Register base = RegisterFrom(locations->InAt(1));       // Object pointer.
-  vixl32::Register offset = LowRegisterFrom(locations->InAt(2));  // Long offset, lo part only.
-  vixl32::Register value;
-
-  if (is_volatile || is_ordered) {
-    __ Dmb(vixl32::ISH);
-  }
-
-  if (type == DataType::Type::kInt64) {
-    vixl32::Register value_lo = LowRegisterFrom(locations->InAt(3));
-    vixl32::Register value_hi = HighRegisterFrom(locations->InAt(3));
-    value = value_lo;
-    if (is_volatile && !codegen->GetInstructionSetFeatures().HasAtomicLdrdAndStrd()) {
-      vixl32::Register temp_lo = RegisterFrom(locations->GetTemp(0));
-      vixl32::Register temp_hi = RegisterFrom(locations->GetTemp(1));
-      UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
-      const vixl32::Register temp_reg = temps.Acquire();
-
-      __ Add(temp_reg, base, offset);
-      vixl32::Label loop_head;
-      __ Bind(&loop_head);
-      __ Ldrexd(temp_lo, temp_hi, MemOperand(temp_reg));
-      __ Strexd(temp_lo, value_lo, value_hi, MemOperand(temp_reg));
-      __ Cmp(temp_lo, 0);
-      __ B(ne, &loop_head, /* is_far_target= */ false);
-    } else {
-      __ Strd(value_lo, value_hi, MemOperand(base, offset));
-    }
-  } else {
-    value = RegisterFrom(locations->InAt(3));
-    vixl32::Register source = value;
-    if (kPoisonHeapReferences && type == DataType::Type::kReference) {
-      vixl32::Register temp = RegisterFrom(locations->GetTemp(0));
-      __ Mov(temp, value);
-      assembler->PoisonHeapReference(temp);
-      source = temp;
-    }
-    __ Str(source, MemOperand(base, offset));
-  }
-
-  if (is_volatile) {
-    __ Dmb(vixl32::ISH);
-  }
-
-  if (type == DataType::Type::kReference) {
-    vixl32::Register temp = RegisterFrom(locations->GetTemp(0));
-    vixl32::Register card = RegisterFrom(locations->GetTemp(1));
-    bool value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MarkGCCard(temp, card, base, value, value_can_be_null);
-  }
-}
-
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePut(HInvoke* invoke) {
-  GenUnsafePut(invoke->GetLocations(),
-               DataType::Type::kInt32,
-               /* is_volatile= */ false,
-               /* is_ordered= */ false,
-               codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutOrdered(HInvoke* invoke) {
-  GenUnsafePut(invoke->GetLocations(),
-               DataType::Type::kInt32,
-               /* is_volatile= */ false,
-               /* is_ordered= */ true,
-               codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutVolatile(HInvoke* invoke) {
-  GenUnsafePut(invoke->GetLocations(),
-               DataType::Type::kInt32,
-               /* is_volatile= */ true,
-               /* is_ordered= */ false,
-               codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutObject(HInvoke* invoke) {
-  GenUnsafePut(invoke->GetLocations(),
-               DataType::Type::kReference,
-               /* is_volatile= */ false,
-               /* is_ordered= */ false,
-               codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutObjectOrdered(HInvoke* invoke) {
-  GenUnsafePut(invoke->GetLocations(),
-               DataType::Type::kReference,
-               /* is_volatile= */ false,
-               /* is_ordered= */ true,
-               codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutObjectVolatile(HInvoke* invoke) {
-  GenUnsafePut(invoke->GetLocations(),
-               DataType::Type::kReference,
-               /* is_volatile= */ true,
-               /* is_ordered= */ false,
-               codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutLong(HInvoke* invoke) {
-  GenUnsafePut(invoke->GetLocations(),
-               DataType::Type::kInt64,
-               /* is_volatile= */ false,
-               /* is_ordered= */ false,
-               codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutLongOrdered(HInvoke* invoke) {
-  GenUnsafePut(invoke->GetLocations(),
-               DataType::Type::kInt64,
-               /* is_volatile= */ false,
-               /* is_ordered= */ true,
-               codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutLongVolatile(HInvoke* invoke) {
-  GenUnsafePut(invoke->GetLocations(),
-               DataType::Type::kInt64,
-               /* is_volatile= */ true,
-               /* is_ordered= */ false,
-               codegen_);
-}
-
-static void CreateIntIntIntIntIntToIntPlusTemps(ArenaAllocator* allocator, HInvoke* invoke) {
-  bool can_call = kEmitCompilerReadBarrier &&
-      kUseBakerReadBarrier &&
-      (invoke->GetIntrinsic() == Intrinsics::kUnsafeCASObject);
-  LocationSummary* locations =
-      new (allocator) LocationSummary(invoke,
-                                      can_call
-                                          ? LocationSummary::kCallOnSlowPath
-                                          : LocationSummary::kNoCall,
-                                      kIntrinsified);
-  if (can_call) {
-    locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty());  // No caller-save registers.
-  }
-  locations->SetInAt(0, Location::NoLocation());        // Unused receiver.
-  locations->SetInAt(1, Location::RequiresRegister());
-  locations->SetInAt(2, Location::RequiresRegister());
-  locations->SetInAt(3, Location::RequiresRegister());
-  locations->SetInAt(4, Location::RequiresRegister());
-
-  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
-
-  // Temporary registers used in CAS. In the object case
-  // (UnsafeCASObject intrinsic), these are also used for
-  // card-marking, and possibly for (Baker) read barrier.
-  locations->AddTemp(Location::RequiresRegister());  // Pointer.
-  locations->AddTemp(Location::RequiresRegister());  // Temp 1.
-}
-
-class BakerReadBarrierCasSlowPathARMVIXL : public SlowPathCodeARMVIXL {
- public:
-  explicit BakerReadBarrierCasSlowPathARMVIXL(HInvoke* invoke)
-      : SlowPathCodeARMVIXL(invoke) {}
-
-  const char* GetDescription() const override { return "BakerReadBarrierCasSlowPathARMVIXL"; }
-
-  void EmitNativeCode(CodeGenerator* codegen) override {
-    CodeGeneratorARMVIXL* arm_codegen = down_cast<CodeGeneratorARMVIXL*>(codegen);
-    ArmVIXLAssembler* assembler = arm_codegen->GetAssembler();
-    __ Bind(GetEntryLabel());
-
-    LocationSummary* locations = instruction_->GetLocations();
-    vixl32::Register base = InputRegisterAt(instruction_, 1);           // Object pointer.
-    vixl32::Register offset = LowRegisterFrom(locations->InAt(2));      // Offset (discard high 4B).
-    vixl32::Register expected = InputRegisterAt(instruction_, 3);       // Expected.
-    vixl32::Register value = InputRegisterAt(instruction_, 4);          // Value.
-
-    vixl32::Register tmp_ptr = RegisterFrom(locations->GetTemp(0));     // Pointer to actual memory.
-    vixl32::Register tmp = RegisterFrom(locations->GetTemp(1));         // Temporary.
-
-    // The `tmp` is initialized to `[tmp_ptr] - expected` in the main path. Reconstruct
-    // and mark the old value and compare with `expected`. We clobber `tmp_ptr` in the
-    // process due to lack of other temps suitable for the read barrier.
-    arm_codegen->GenerateUnsafeCasOldValueAddWithBakerReadBarrier(tmp_ptr, tmp, expected);
-    __ Cmp(tmp_ptr, expected);
-    __ B(ne, GetExitLabel());
-
-    // The old value we have read did not match `expected` (which is always a to-space reference)
-    // but after the read barrier in GenerateUnsafeCasOldValueAddWithBakerReadBarrier() the marked
-    // to-space value matched, so the old value must be a from-space reference to the same object.
-    // Do the same CAS loop as the main path but check for both `expected` and the unmarked
-    // old value representing the to-space and from-space references for the same object.
-
-    UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
-    vixl32::Register adjusted_old_value = temps.Acquire();      // For saved `tmp` from main path.
-
-    // Recalculate the `tmp_ptr` clobbered above and store the `adjusted_old_value`, i.e. IP.
-    __ Add(tmp_ptr, base, offset);
-    __ Mov(adjusted_old_value, tmp);
-
-    // do {
-    //   tmp = [r_ptr] - expected;
-    // } while ((tmp == 0 || tmp == adjusted_old_value) && failure([r_ptr] <- r_new_value));
-    // result = (tmp == 0 || tmp == adjusted_old_value);
-
-    vixl32::Label loop_head;
-    __ Bind(&loop_head);
-    __ Ldrex(tmp, MemOperand(tmp_ptr));  // This can now load null stored by another thread.
-    assembler->MaybeUnpoisonHeapReference(tmp);
-    __ Subs(tmp, tmp, expected);         // Use SUBS to get non-zero value if both compares fail.
-    {
-      // If the newly loaded value did not match `expected`, compare with `adjusted_old_value`.
-      ExactAssemblyScope aas(assembler->GetVIXLAssembler(), 2 * k16BitT32InstructionSizeInBytes);
-      __ it(ne);
-      __ cmp(ne, tmp, adjusted_old_value);
-    }
-    __ B(ne, GetExitLabel());
-    assembler->MaybePoisonHeapReference(value);
-    __ Strex(tmp, value, MemOperand(tmp_ptr));
-    assembler->MaybeUnpoisonHeapReference(value);
-    __ Cmp(tmp, 0);
-    __ B(ne, &loop_head, /* is_far_target= */ false);
-    __ B(GetExitLabel());
-  }
-};
-
-static void GenCas(HInvoke* invoke, DataType::Type type, CodeGeneratorARMVIXL* codegen) {
-  DCHECK_NE(type, DataType::Type::kInt64);
-
-  ArmVIXLAssembler* assembler = codegen->GetAssembler();
-  LocationSummary* locations = invoke->GetLocations();
-
-  vixl32::Register out = OutputRegister(invoke);                      // Boolean result.
-
-  vixl32::Register base = InputRegisterAt(invoke, 1);                 // Object pointer.
-  vixl32::Register offset = LowRegisterFrom(locations->InAt(2));      // Offset (discard high 4B).
-  vixl32::Register expected = InputRegisterAt(invoke, 3);             // Expected.
-  vixl32::Register value = InputRegisterAt(invoke, 4);                // Value.
-
-  vixl32::Register tmp_ptr = RegisterFrom(locations->GetTemp(0));     // Pointer to actual memory.
-  vixl32::Register tmp = RegisterFrom(locations->GetTemp(1));         // Temporary.
-
-  vixl32::Label loop_exit_label;
-  vixl32::Label* loop_exit = &loop_exit_label;
-  vixl32::Label* failure = &loop_exit_label;
-
-  if (type == DataType::Type::kReference) {
-    // The only read barrier implementation supporting the
-    // UnsafeCASObject intrinsic is the Baker-style read barriers.
-    DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
-
-    // Mark card for object assuming new value is stored. Worst case we will mark an unchanged
-    // object and scan the receiver at the next GC for nothing.
-    bool value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MarkGCCard(tmp_ptr, tmp, base, value, value_can_be_null);
-
-    if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
-      // If marking, check if the stored reference is a from-space reference to the same
-      // object as the to-space reference `expected`. If so, perform a custom CAS loop.
-      BakerReadBarrierCasSlowPathARMVIXL* slow_path =
-          new (codegen->GetScopedAllocator()) BakerReadBarrierCasSlowPathARMVIXL(invoke);
-      codegen->AddSlowPath(slow_path);
-      failure = slow_path->GetEntryLabel();
-      loop_exit = slow_path->GetExitLabel();
-    }
-  }
-
-  // Prevent reordering with prior memory operations.
-  // Emit a DMB ISH instruction instead of an DMB ISHST one, as the
-  // latter allows a preceding load to be delayed past the STREX
-  // instruction below.
-  __ Dmb(vixl32::ISH);
-
-  __ Add(tmp_ptr, base, offset);
-
-  // do {
-  //   tmp = [r_ptr] - expected;
-  // } while (tmp == 0 && failure([r_ptr] <- r_new_value));
-  // result = tmp == 0;
-
-  vixl32::Label loop_head;
-  __ Bind(&loop_head);
-  __ Ldrex(tmp, MemOperand(tmp_ptr));
-  if (type == DataType::Type::kReference) {
-    assembler->MaybeUnpoisonHeapReference(tmp);
-  }
-  __ Subs(tmp, tmp, expected);
-  static_cast<vixl32::MacroAssembler*>(assembler->GetVIXLAssembler())->
-      B(ne, failure, /* hint= */ (failure == loop_exit) ? kNear : kBranchWithoutHint);
-  if (type == DataType::Type::kReference) {
-    assembler->MaybePoisonHeapReference(value);
-  }
-  __ Strex(tmp, value, MemOperand(tmp_ptr));
-  if (type == DataType::Type::kReference) {
-    assembler->MaybeUnpoisonHeapReference(value);
-  }
-  __ Cmp(tmp, 0);
-  __ B(ne, &loop_head, /* is_far_target= */ false);
-
-  __ Bind(loop_exit);
-
-  __ Dmb(vixl32::ISH);
-
-  // out = tmp == 0.
-  __ Clz(out, tmp);
-  __ Lsr(out, out, WhichPowerOf2(out.GetSizeInBits()));
-
-  if (type == DataType::Type::kReference) {
-    codegen->MaybeGenerateMarkingRegisterCheck(/* code= */ 128);
-  }
-}
-
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeCASInt(HInvoke* invoke) {
-  CreateIntIntIntIntIntToIntPlusTemps(allocator_, invoke);
-}
-void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeCASObject(HInvoke* invoke) {
-  // The only read barrier implementation supporting the
-  // UnsafeCASObject intrinsic is the Baker-style read barriers.
-  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
-    return;
-  }
-
-  CreateIntIntIntIntIntToIntPlusTemps(allocator_, invoke);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeCASInt(HInvoke* invoke) {
-  GenCas(invoke, DataType::Type::kInt32, codegen_);
-}
-void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeCASObject(HInvoke* invoke) {
-  // The only read barrier implementation supporting the
-  // UnsafeCASObject intrinsic is the Baker-style read barriers.
-  DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
-
-  GenCas(invoke, DataType::Type::kReference, codegen_);
-}
-
 void IntrinsicLocationsBuilderARMVIXL::VisitStringCompareTo(HInvoke* invoke) {
   // The inputs plus one temp.
   LocationSummary* locations =
@@ -1267,9 +698,9 @@
 }
 
 static void GenerateStringCompareToLoop(ArmVIXLAssembler* assembler,
-                                                  HInvoke* invoke,
-                                                  vixl32::Label* end,
-                                                  vixl32::Label* different_compression) {
+                                        HInvoke* invoke,
+                                        vixl32::Label* end,
+                                        vixl32::Label* different_compression) {
   LocationSummary* locations = invoke->GetLocations();
 
   const vixl32::Register str = InputRegisterAt(invoke, 0);
@@ -2292,7 +1723,7 @@
   }
 
   // We only need one card marking on the destination array.
-  codegen_->MarkGCCard(temp1, temp2, dest, NoReg, /* can_be_null= */ false);
+  codegen_->MarkGCCard(temp1, temp2, dest, NoReg, /* value_can_be_null= */ false);
 
   __ Bind(intrinsic_slow_path->GetExitLabel());
 }
@@ -2562,13 +1993,53 @@
   __ Rbit(out_reg_hi, in_reg_lo);
 }
 
+static void GenerateReverseBytesInPlaceForEachWord(ArmVIXLAssembler* assembler, Location pair) {
+  DCHECK(pair.IsRegisterPair());
+  __ Rev(LowRegisterFrom(pair), LowRegisterFrom(pair));
+  __ Rev(HighRegisterFrom(pair), HighRegisterFrom(pair));
+}
+
+static void GenerateReverseBytes(ArmVIXLAssembler* assembler,
+                                 DataType::Type type,
+                                 Location in,
+                                 Location out) {
+  switch (type) {
+    case DataType::Type::kUint16:
+      __ Rev16(RegisterFrom(out), RegisterFrom(in));
+      break;
+    case DataType::Type::kInt16:
+      __ Revsh(RegisterFrom(out), RegisterFrom(in));
+      break;
+    case DataType::Type::kInt32:
+      __ Rev(RegisterFrom(out), RegisterFrom(in));
+      break;
+    case DataType::Type::kInt64:
+      DCHECK(!LowRegisterFrom(out).Is(LowRegisterFrom(in)));
+      __ Rev(LowRegisterFrom(out), HighRegisterFrom(in));
+      __ Rev(HighRegisterFrom(out), LowRegisterFrom(in));
+      break;
+    case DataType::Type::kFloat32:
+      __ Rev(RegisterFrom(in), RegisterFrom(in));  // Note: Clobbers `in`.
+      __ Vmov(SRegisterFrom(out), RegisterFrom(in));
+      break;
+    case DataType::Type::kFloat64:
+      GenerateReverseBytesInPlaceForEachWord(assembler, in);  // Note: Clobbers `in`.
+      __ Vmov(DRegisterFrom(out), HighRegisterFrom(in), LowRegisterFrom(in));  // Swap high/low.
+      break;
+    default:
+      LOG(FATAL) << "Unexpected type for reverse-bytes: " << type;
+      UNREACHABLE();
+  }
+}
+
 void IntrinsicLocationsBuilderARMVIXL::VisitIntegerReverseBytes(HInvoke* invoke) {
   CreateIntToIntLocations(allocator_, invoke);
 }
 
 void IntrinsicCodeGeneratorARMVIXL::VisitIntegerReverseBytes(HInvoke* invoke) {
   ArmVIXLAssembler* assembler = GetAssembler();
-  __ Rev(OutputRegister(invoke), InputRegisterAt(invoke, 0));
+  LocationSummary* locations = invoke->GetLocations();
+  GenerateReverseBytes(assembler, DataType::Type::kInt32, locations->InAt(0), locations->Out());
 }
 
 void IntrinsicLocationsBuilderARMVIXL::VisitLongReverseBytes(HInvoke* invoke) {
@@ -2578,14 +2049,7 @@
 void IntrinsicCodeGeneratorARMVIXL::VisitLongReverseBytes(HInvoke* invoke) {
   ArmVIXLAssembler* assembler = GetAssembler();
   LocationSummary* locations = invoke->GetLocations();
-
-  vixl32::Register in_reg_lo  = LowRegisterFrom(locations->InAt(0));
-  vixl32::Register in_reg_hi  = HighRegisterFrom(locations->InAt(0));
-  vixl32::Register out_reg_lo = LowRegisterFrom(locations->Out());
-  vixl32::Register out_reg_hi = HighRegisterFrom(locations->Out());
-
-  __ Rev(out_reg_lo, in_reg_hi);
-  __ Rev(out_reg_hi, in_reg_lo);
+  GenerateReverseBytes(assembler, DataType::Type::kInt64, locations->InAt(0), locations->Out());
 }
 
 void IntrinsicLocationsBuilderARMVIXL::VisitShortReverseBytes(HInvoke* invoke) {
@@ -2594,7 +2058,8 @@
 
 void IntrinsicCodeGeneratorARMVIXL::VisitShortReverseBytes(HInvoke* invoke) {
   ArmVIXLAssembler* assembler = GetAssembler();
-  __ Revsh(OutputRegister(invoke), InputRegisterAt(invoke, 0));
+  LocationSummary* locations = invoke->GetLocations();
+  GenerateReverseBytes(assembler, DataType::Type::kInt16, locations->InAt(0), locations->Out());
 }
 
 static void GenBitCount(HInvoke* instr, DataType::Type type, ArmVIXLAssembler* assembler) {
@@ -2986,6 +2451,12 @@
   vixl32::Register out = RegisterFrom(locations->Out());
   UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
   vixl32::Register temp = temps.Acquire();
+  auto allocate_instance = [&]() {
+    DCHECK(out.Is(InvokeRuntimeCallingConventionARMVIXL().GetRegisterAt(0)));
+    codegen_->LoadIntrinsicDeclaringClass(out, invoke);
+    codegen_->InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
+    CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
+  };
   if (invoke->InputAt(0)->IsConstant()) {
     int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
     if (static_cast<uint32_t>(value - info.low) < info.length) {
@@ -2997,12 +2468,10 @@
       // Allocate and initialize a new j.l.Integer.
       // TODO: If we JIT, we could allocate the j.l.Integer now, and store it in the
       // JIT object table.
-      codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
-                                             info.integer_boot_image_offset);
+      allocate_instance();
       __ Mov(temp, value);
       assembler->StoreToOffset(kStoreWord, temp, out, info.value_offset);
-      // `value` is a final field :-( Ideally, we'd merge this memory barrier with the allocation
-      // one.
+      // Class pointer and `value` final field stores require a barrier before publication.
       codegen_->GenerateMemoryBarrier(MemBarrierKind::kStoreStore);
     }
   } else {
@@ -3020,16 +2489,139 @@
     __ B(&done);
     __ Bind(&allocate);
     // Otherwise allocate and initialize a new j.l.Integer.
-    codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
-                                           info.integer_boot_image_offset);
+    allocate_instance();
     assembler->StoreToOffset(kStoreWord, in, out, info.value_offset);
-    // `value` is a final field :-( Ideally, we'd merge this memory barrier with the allocation
-    // one.
+    // Class pointer and `value` final field stores require a barrier before publication.
     codegen_->GenerateMemoryBarrier(MemBarrierKind::kStoreStore);
     __ Bind(&done);
   }
 }
 
+void IntrinsicLocationsBuilderARMVIXL::VisitReferenceGetReferent(HInvoke* invoke) {
+  IntrinsicVisitor::CreateReferenceGetReferentLocations(invoke, codegen_);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitReferenceGetReferent(HInvoke* invoke) {
+  ArmVIXLAssembler* assembler = GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+
+  Location obj = locations->InAt(0);
+  Location out = locations->Out();
+
+  SlowPathCodeARMVIXL* slow_path = new (GetAllocator()) IntrinsicSlowPathARMVIXL(invoke);
+  codegen_->AddSlowPath(slow_path);
+
+  if (kEmitCompilerReadBarrier) {
+    // Check self->GetWeakRefAccessEnabled().
+    UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+    vixl32::Register temp = temps.Acquire();
+    __ Ldr(temp,
+           MemOperand(tr, Thread::WeakRefAccessEnabledOffset<kArmPointerSize>().Uint32Value()));
+    __ Cmp(temp, 0);
+    __ B(eq, slow_path->GetEntryLabel());
+  }
+
+  {
+    // Load the java.lang.ref.Reference class.
+    UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+    vixl32::Register temp = temps.Acquire();
+    codegen_->LoadIntrinsicDeclaringClass(temp, invoke);
+
+    // Check static fields java.lang.ref.Reference.{disableIntrinsic,slowPathEnabled} together.
+    MemberOffset disable_intrinsic_offset = IntrinsicVisitor::GetReferenceDisableIntrinsicOffset();
+    DCHECK_ALIGNED(disable_intrinsic_offset.Uint32Value(), 2u);
+    DCHECK_EQ(disable_intrinsic_offset.Uint32Value() + 1u,
+              IntrinsicVisitor::GetReferenceSlowPathEnabledOffset().Uint32Value());
+    __ Ldrh(temp, MemOperand(temp, disable_intrinsic_offset.Uint32Value()));
+    __ Cmp(temp, 0);
+    __ B(ne, slow_path->GetEntryLabel());
+  }
+
+  // Load the value from the field.
+  uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+  if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+    codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+                                                    out,
+                                                    RegisterFrom(obj),
+                                                    referent_offset,
+                                                    /*maybe_temp=*/ Location::NoLocation(),
+                                                    /*needs_null_check=*/ true);
+    codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);  // `referent` is volatile.
+  } else {
+    {
+      vixl::EmissionCheckScope guard(codegen_->GetVIXLAssembler(), kMaxMacroInstructionSizeInBytes);
+      __ Ldr(RegisterFrom(out), MemOperand(RegisterFrom(obj), referent_offset));
+      codegen_->MaybeRecordImplicitNullCheck(invoke);
+    }
+    codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);  // `referent` is volatile.
+    codegen_->MaybeGenerateReadBarrierSlow(invoke, out, out, obj, referent_offset);
+  }
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitReferenceRefersTo(HInvoke* invoke) {
+  IntrinsicVisitor::CreateReferenceRefersToLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitReferenceRefersTo(HInvoke* invoke) {
+  LocationSummary* locations = invoke->GetLocations();
+  ArmVIXLAssembler* assembler = GetAssembler();
+  UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+
+  vixl32::Register obj = RegisterFrom(locations->InAt(0));
+  vixl32::Register other = RegisterFrom(locations->InAt(1));
+  vixl32::Register out = RegisterFrom(locations->Out());
+  vixl32::Register tmp = temps.Acquire();
+
+  uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+  uint32_t monitor_offset = mirror::Object::MonitorOffset().Int32Value();
+
+  {
+    // Ensure that between load and MaybeRecordImplicitNullCheck there are no pools emitted.
+    // Loading scratch register always uses 32-bit encoding.
+    vixl::ExactAssemblyScope eas(assembler->GetVIXLAssembler(),
+                                 vixl32::k32BitT32InstructionSizeInBytes);
+    __ ldr(tmp, MemOperand(obj, referent_offset));
+    codegen_->MaybeRecordImplicitNullCheck(invoke);
+  }
+  assembler->MaybeUnpoisonHeapReference(tmp);
+  codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);  // `referent` is volatile.
+
+  if (kEmitCompilerReadBarrier) {
+    DCHECK(kUseBakerReadBarrier);
+
+    vixl32::Label calculate_result;
+    __ Subs(out, tmp, other);
+    __ B(eq, &calculate_result);  // `out` is 0 if taken.
+
+    // Check if the loaded reference is null.
+    __ Cmp(tmp, 0);
+    __ B(eq, &calculate_result);  // `out` is not 0 if taken.
+
+    // For correct memory visibility, we need a barrier before loading the lock word
+    // but we already have the barrier emitted for volatile load above which is sufficient.
+
+    // Load the lockword and check if it is a forwarding address.
+    static_assert(LockWord::kStateShift == 30u);
+    static_assert(LockWord::kStateForwardingAddress == 3u);
+    __ Ldr(tmp, MemOperand(tmp, monitor_offset));
+    __ Cmp(tmp, Operand(0xc0000000));
+    __ B(lo, &calculate_result);   // `out` is not 0 if taken.
+
+    // Extract the forwarding address and subtract from `other`.
+    __ Sub(out, other, Operand(tmp, LSL, LockWord::kForwardingAddressShift));
+
+    __ Bind(&calculate_result);
+  } else {
+    DCHECK(!kEmitCompilerReadBarrier);
+    __ Sub(out, tmp, other);
+  }
+
+  // Convert 0 to 1 and non-zero to 0 for the Boolean result (`out = (out == 0)`).
+  __ Clz(out, out);
+  __ Lsr(out, out, WhichPowerOf2(out.GetSizeInBits()));
+}
+
 void IntrinsicLocationsBuilderARMVIXL::VisitThreadInterrupted(HInvoke* invoke) {
   LocationSummary* locations =
       new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
@@ -3063,10 +2655,2710 @@
 
 void IntrinsicCodeGeneratorARMVIXL::VisitReachabilityFence(HInvoke* invoke ATTRIBUTE_UNUSED) { }
 
+void IntrinsicLocationsBuilderARMVIXL::VisitIntegerDivideUnsigned(HInvoke* invoke) {
+  CreateIntIntToIntSlowPathCallLocations(allocator_, invoke);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitIntegerDivideUnsigned(HInvoke* invoke) {
+  ArmVIXLAssembler* assembler = GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  vixl32::Register dividend = RegisterFrom(locations->InAt(0));
+  vixl32::Register divisor = RegisterFrom(locations->InAt(1));
+  vixl32::Register out = RegisterFrom(locations->Out());
+
+  // Check if divisor is zero, bail to managed implementation to handle.
+  SlowPathCodeARMVIXL* slow_path =
+      new (codegen_->GetScopedAllocator()) IntrinsicSlowPathARMVIXL(invoke);
+  codegen_->AddSlowPath(slow_path);
+  __ CompareAndBranchIfZero(divisor, slow_path->GetEntryLabel());
+
+  __ Udiv(out, dividend, divisor);
+
+  __ Bind(slow_path->GetExitLabel());
+}
+
+static inline bool Use64BitExclusiveLoadStore(bool atomic, CodeGeneratorARMVIXL* codegen) {
+  return atomic && !codegen->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
+}
+
+static void GenerateIntrinsicGet(HInvoke* invoke,
+                                 CodeGeneratorARMVIXL* codegen,
+                                 DataType::Type type,
+                                 std::memory_order order,
+                                 bool atomic,
+                                 vixl32::Register base,
+                                 vixl32::Register offset,
+                                 Location out,
+                                 Location maybe_temp,
+                                 Location maybe_temp2,
+                                 Location maybe_temp3) {
+  bool seq_cst_barrier = (order == std::memory_order_seq_cst);
+  bool acquire_barrier = seq_cst_barrier || (order == std::memory_order_acquire);
+  DCHECK(acquire_barrier || order == std::memory_order_relaxed);
+  DCHECK(atomic || order == std::memory_order_relaxed);
+
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  MemOperand address(base, offset);
+  switch (type) {
+    case DataType::Type::kBool:
+      __ Ldrb(RegisterFrom(out), address);
+      break;
+    case DataType::Type::kInt8:
+      __ Ldrsb(RegisterFrom(out), address);
+      break;
+    case DataType::Type::kUint16:
+      __ Ldrh(RegisterFrom(out), address);
+      break;
+    case DataType::Type::kInt16:
+      __ Ldrsh(RegisterFrom(out), address);
+      break;
+    case DataType::Type::kInt32:
+      __ Ldr(RegisterFrom(out), address);
+      break;
+    case DataType::Type::kInt64:
+      if (Use64BitExclusiveLoadStore(atomic, codegen)) {
+        vixl32::Register strexd_tmp = RegisterFrom(maybe_temp);
+        UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+        const vixl32::Register temp_reg = temps.Acquire();
+        __ Add(temp_reg, base, offset);
+        vixl32::Label loop;
+        __ Bind(&loop);
+        __ Ldrexd(LowRegisterFrom(out), HighRegisterFrom(out), MemOperand(temp_reg));
+        __ Strexd(strexd_tmp, LowRegisterFrom(out), HighRegisterFrom(out), MemOperand(temp_reg));
+        __ Cmp(strexd_tmp, 0);
+        __ B(ne, &loop);
+      } else {
+        __ Ldrd(LowRegisterFrom(out), HighRegisterFrom(out), address);
+      }
+      break;
+    case DataType::Type::kReference:
+      if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+        // Piggy-back on the field load path using introspection for the Baker read barrier.
+        vixl32::Register temp = RegisterFrom(maybe_temp);
+        __ Add(temp, base, offset);
+        codegen->GenerateFieldLoadWithBakerReadBarrier(
+            invoke, out, base, MemOperand(temp), /* needs_null_check= */ false);
+      } else {
+        __ Ldr(RegisterFrom(out), address);
+      }
+      break;
+    case DataType::Type::kFloat32: {
+      UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+      const vixl32::Register temp_reg = temps.Acquire();
+      __ Add(temp_reg, base, offset);
+      __ Vldr(SRegisterFrom(out), MemOperand(temp_reg));
+      break;
+    }
+    case DataType::Type::kFloat64: {
+      UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+      const vixl32::Register temp_reg = temps.Acquire();
+      __ Add(temp_reg, base, offset);
+      if (Use64BitExclusiveLoadStore(atomic, codegen)) {
+        vixl32::Register lo = RegisterFrom(maybe_temp);
+        vixl32::Register hi = RegisterFrom(maybe_temp2);
+        vixl32::Register strexd_tmp = RegisterFrom(maybe_temp3);
+        vixl32::Label loop;
+        __ Bind(&loop);
+        __ Ldrexd(lo, hi, MemOperand(temp_reg));
+        __ Strexd(strexd_tmp, lo, hi, MemOperand(temp_reg));
+        __ Cmp(strexd_tmp, 0);
+        __ B(ne, &loop);
+        __ Vmov(DRegisterFrom(out), lo, hi);
+      } else {
+        __ Vldr(DRegisterFrom(out), MemOperand(temp_reg));
+      }
+      break;
+    }
+    default:
+      LOG(FATAL) << "Unexpected type " << type;
+      UNREACHABLE();
+  }
+  if (acquire_barrier) {
+    codegen->GenerateMemoryBarrier(
+        seq_cst_barrier ? MemBarrierKind::kAnyAny : MemBarrierKind::kLoadAny);
+  }
+  if (type == DataType::Type::kReference && !(kEmitCompilerReadBarrier && kUseBakerReadBarrier)) {
+    Location base_loc = LocationFrom(base);
+    Location index_loc = LocationFrom(offset);
+    codegen->MaybeGenerateReadBarrierSlow(invoke, out, out, base_loc, /* offset=*/ 0u, index_loc);
+  }
+}
+
+static void CreateUnsafeGetLocations(HInvoke* invoke,
+                                     CodeGeneratorARMVIXL* codegen,
+                                     DataType::Type type,
+                                     bool atomic) {
+  bool can_call = kEmitCompilerReadBarrier &&
+      (invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObject ||
+       invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObjectVolatile);
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations =
+      new (allocator) LocationSummary(invoke,
+                                      can_call
+                                          ? LocationSummary::kCallOnSlowPath
+                                          : LocationSummary::kNoCall,
+                                      kIntrinsified);
+  if (can_call && kUseBakerReadBarrier) {
+    locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty());  // No caller-save registers.
+  }
+  locations->SetInAt(0, Location::NoLocation());        // Unused receiver.
+  locations->SetInAt(1, Location::RequiresRegister());
+  locations->SetInAt(2, Location::RequiresRegister());
+  locations->SetOut(Location::RequiresRegister(),
+                    (can_call ? Location::kOutputOverlap : Location::kNoOutputOverlap));
+  if ((kEmitCompilerReadBarrier && kUseBakerReadBarrier && type == DataType::Type::kReference) ||
+      (type == DataType::Type::kInt64 && Use64BitExclusiveLoadStore(atomic, codegen))) {
+    // We need a temporary register for the read barrier marking slow
+    // path in CodeGeneratorARMVIXL::GenerateReferenceLoadWithBakerReadBarrier,
+    // or the STREXD result for LDREXD/STREXD sequence when LDRD is non-atomic.
+    locations->AddTemp(Location::RequiresRegister());
+  }
+}
+
+static void GenUnsafeGet(HInvoke* invoke,
+                         CodeGeneratorARMVIXL* codegen,
+                         DataType::Type type,
+                         std::memory_order order,
+                         bool atomic) {
+  LocationSummary* locations = invoke->GetLocations();
+  vixl32::Register base = InputRegisterAt(invoke, 1);     // Object pointer.
+  vixl32::Register offset = LowRegisterFrom(locations->InAt(2));  // Long offset, lo part only.
+  Location out = locations->Out();
+  Location maybe_temp = Location::NoLocation();
+  if ((kEmitCompilerReadBarrier && kUseBakerReadBarrier && type == DataType::Type::kReference) ||
+      (type == DataType::Type::kInt64 && Use64BitExclusiveLoadStore(atomic, codegen))) {
+    maybe_temp = locations->GetTemp(0);
+  }
+  GenerateIntrinsicGet(invoke,
+                       codegen,
+                       type,
+                       order,
+                       atomic,
+                       base,
+                       offset,
+                       out,
+                       maybe_temp,
+                       /*maybe_temp2=*/ Location::NoLocation(),
+                       /*maybe_temp3=*/ Location::NoLocation());
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGet(HInvoke* invoke) {
+  CreateUnsafeGetLocations(invoke, codegen_, DataType::Type::kInt32, /*atomic=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGet(HInvoke* invoke) {
+  GenUnsafeGet(
+      invoke, codegen_, DataType::Type::kInt32, std::memory_order_relaxed, /*atomic=*/ false);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetVolatile(HInvoke* invoke) {
+  CreateUnsafeGetLocations(invoke, codegen_, DataType::Type::kInt32, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetVolatile(HInvoke* invoke) {
+  GenUnsafeGet(
+      invoke, codegen_, DataType::Type::kInt32, std::memory_order_seq_cst, /*atomic=*/ true);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetLong(HInvoke* invoke) {
+  CreateUnsafeGetLocations(invoke, codegen_, DataType::Type::kInt64, /*atomic=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetLong(HInvoke* invoke) {
+  GenUnsafeGet(
+      invoke, codegen_, DataType::Type::kInt64, std::memory_order_relaxed, /*atomic=*/ false);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetLongVolatile(HInvoke* invoke) {
+  CreateUnsafeGetLocations(invoke, codegen_, DataType::Type::kInt64, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetLongVolatile(HInvoke* invoke) {
+  GenUnsafeGet(
+      invoke, codegen_, DataType::Type::kInt64, std::memory_order_seq_cst, /*atomic=*/ true);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetObject(HInvoke* invoke) {
+  CreateUnsafeGetLocations(invoke, codegen_, DataType::Type::kReference, /*atomic=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetObject(HInvoke* invoke) {
+  GenUnsafeGet(
+      invoke, codegen_, DataType::Type::kReference, std::memory_order_relaxed, /*atomic=*/ false);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetObjectVolatile(HInvoke* invoke) {
+  CreateUnsafeGetLocations(invoke, codegen_, DataType::Type::kReference, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetObjectVolatile(HInvoke* invoke) {
+  GenUnsafeGet(
+      invoke, codegen_, DataType::Type::kReference, std::memory_order_seq_cst, /*atomic=*/ true);
+}
+
+static void GenerateIntrinsicSet(CodeGeneratorARMVIXL* codegen,
+                                 DataType::Type type,
+                                 std::memory_order order,
+                                 bool atomic,
+                                 vixl32::Register base,
+                                 vixl32::Register offset,
+                                 Location value,
+                                 Location maybe_temp,
+                                 Location maybe_temp2,
+                                 Location maybe_temp3) {
+  bool seq_cst_barrier = (order == std::memory_order_seq_cst);
+  bool release_barrier = seq_cst_barrier || (order == std::memory_order_release);
+  DCHECK(release_barrier || order == std::memory_order_relaxed);
+  DCHECK(atomic || order == std::memory_order_relaxed);
+
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  if (release_barrier) {
+    codegen->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
+  }
+  UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+  if (kPoisonHeapReferences && type == DataType::Type::kReference) {
+    vixl32::Register temp = temps.Acquire();
+    __ Mov(temp, RegisterFrom(value));
+    assembler->PoisonHeapReference(temp);
+    value = LocationFrom(temp);
+  }
+  MemOperand address = offset.IsValid() ? MemOperand(base, offset) : MemOperand(base);
+  if (offset.IsValid() && (DataType::Is64BitType(type) || type == DataType::Type::kFloat32)) {
+    const vixl32::Register temp_reg = temps.Acquire();
+    __ Add(temp_reg, base, offset);
+    address = MemOperand(temp_reg);
+  }
+  switch (type) {
+    case DataType::Type::kBool:
+    case DataType::Type::kInt8:
+      __ Strb(RegisterFrom(value), address);
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Strh(RegisterFrom(value), address);
+      break;
+    case DataType::Type::kReference:
+    case DataType::Type::kInt32:
+      __ Str(RegisterFrom(value), address);
+      break;
+    case DataType::Type::kInt64:
+      if (Use64BitExclusiveLoadStore(atomic, codegen)) {
+        vixl32::Register lo_tmp = RegisterFrom(maybe_temp);
+        vixl32::Register hi_tmp = RegisterFrom(maybe_temp2);
+        vixl32::Label loop;
+        __ Bind(&loop);
+        __ Ldrexd(lo_tmp, hi_tmp, address);  // Ignore the retrieved value.
+        __ Strexd(lo_tmp, LowRegisterFrom(value), HighRegisterFrom(value), address);
+        __ Cmp(lo_tmp, 0);
+        __ B(ne, &loop);
+      } else {
+        __ Strd(LowRegisterFrom(value), HighRegisterFrom(value), address);
+      }
+      break;
+    case DataType::Type::kFloat32:
+      __ Vstr(SRegisterFrom(value), address);
+      break;
+    case DataType::Type::kFloat64:
+      if (Use64BitExclusiveLoadStore(atomic, codegen)) {
+        vixl32::Register lo_tmp = RegisterFrom(maybe_temp);
+        vixl32::Register hi_tmp = RegisterFrom(maybe_temp2);
+        vixl32::Register strexd_tmp = RegisterFrom(maybe_temp3);
+        vixl32::Label loop;
+        __ Bind(&loop);
+        __ Ldrexd(lo_tmp, hi_tmp, address);  // Ignore the retrieved value.
+        __ Vmov(lo_tmp, hi_tmp, DRegisterFrom(value));
+        __ Strexd(strexd_tmp, lo_tmp, hi_tmp, address);
+        __ Cmp(strexd_tmp, 0);
+        __ B(ne, &loop);
+      } else {
+        __ Vstr(DRegisterFrom(value), address);
+      }
+      break;
+    default:
+      LOG(FATAL) << "Unexpected type " << type;
+      UNREACHABLE();
+  }
+  if (seq_cst_barrier) {
+    codegen->GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
+  }
+}
+
+static void CreateUnsafePutLocations(HInvoke* invoke,
+                                     CodeGeneratorARMVIXL* codegen,
+                                     DataType::Type type,
+                                     bool atomic) {
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations =
+      new (allocator) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+  locations->SetInAt(0, Location::NoLocation());        // Unused receiver.
+  locations->SetInAt(1, Location::RequiresRegister());
+  locations->SetInAt(2, Location::RequiresRegister());
+  locations->SetInAt(3, Location::RequiresRegister());
+
+  if (type == DataType::Type::kInt64) {
+    // Potentially need temps for ldrexd-strexd loop.
+    if (Use64BitExclusiveLoadStore(atomic, codegen)) {
+      locations->AddTemp(Location::RequiresRegister());  // Temp_lo.
+      locations->AddTemp(Location::RequiresRegister());  // Temp_hi.
+    }
+  } else if (type == DataType::Type::kReference) {
+    // Temp for card-marking.
+    locations->AddTemp(Location::RequiresRegister());  // Temp.
+  }
+}
+
+static void GenUnsafePut(HInvoke* invoke,
+                         DataType::Type type,
+                         std::memory_order order,
+                         bool atomic,
+                         CodeGeneratorARMVIXL* codegen) {
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+
+  LocationSummary* locations = invoke->GetLocations();
+  vixl32::Register base = RegisterFrom(locations->InAt(1));       // Object pointer.
+  vixl32::Register offset = LowRegisterFrom(locations->InAt(2));  // Long offset, lo part only.
+  Location value = locations->InAt(3);
+  Location maybe_temp = Location::NoLocation();
+  Location maybe_temp2 = Location::NoLocation();
+  if (type == DataType::Type::kInt64 && Use64BitExclusiveLoadStore(atomic, codegen)) {
+    maybe_temp = locations->GetTemp(0);
+    maybe_temp2 = locations->GetTemp(1);
+  }
+
+  GenerateIntrinsicSet(codegen,
+                       type,
+                       order,
+                       atomic,
+                       base,
+                       offset,
+                       value,
+                       maybe_temp,
+                       maybe_temp2,
+                       /*maybe_temp3=*/ Location::NoLocation());
+
+  if (type == DataType::Type::kReference) {
+    vixl32::Register temp = RegisterFrom(locations->GetTemp(0));
+    UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+    vixl32::Register card = temps.Acquire();
+    bool value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(temp, card, base, RegisterFrom(value), value_can_be_null);
+  }
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePut(HInvoke* invoke) {
+  CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kInt32, /*atomic=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePut(HInvoke* invoke) {
+  GenUnsafePut(invoke,
+               DataType::Type::kInt32,
+               std::memory_order_relaxed,
+               /*atomic=*/ false,
+               codegen_);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutOrdered(HInvoke* invoke) {
+  CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kInt32, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutOrdered(HInvoke* invoke) {
+  GenUnsafePut(invoke,
+               DataType::Type::kInt32,
+               std::memory_order_release,
+               /*atomic=*/ true,
+               codegen_);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutVolatile(HInvoke* invoke) {
+  CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kInt32, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutVolatile(HInvoke* invoke) {
+  GenUnsafePut(invoke,
+               DataType::Type::kInt32,
+               std::memory_order_seq_cst,
+               /*atomic=*/ true,
+               codegen_);
+}
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutObject(HInvoke* invoke) {
+  CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kReference, /*atomic=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutObject(HInvoke* invoke) {
+  GenUnsafePut(invoke,
+               DataType::Type::kReference,
+               std::memory_order_relaxed,
+               /*atomic=*/ false,
+               codegen_);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutObjectOrdered(HInvoke* invoke) {
+  CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kReference, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutObjectOrdered(HInvoke* invoke) {
+  GenUnsafePut(invoke,
+               DataType::Type::kReference,
+               std::memory_order_release,
+               /*atomic=*/ true,
+               codegen_);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutObjectVolatile(HInvoke* invoke) {
+  CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kReference, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutObjectVolatile(HInvoke* invoke) {
+  GenUnsafePut(invoke,
+               DataType::Type::kReference,
+               std::memory_order_seq_cst,
+               /*atomic=*/ true,
+               codegen_);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutLong(HInvoke* invoke) {
+  CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kInt64, /*atomic=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutLong(HInvoke* invoke) {
+  GenUnsafePut(invoke,
+               DataType::Type::kInt64,
+               std::memory_order_relaxed,
+               /*atomic=*/ false,
+               codegen_);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutLongOrdered(HInvoke* invoke) {
+  CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kInt64, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutLongOrdered(HInvoke* invoke) {
+  GenUnsafePut(invoke,
+               DataType::Type::kInt64,
+               std::memory_order_release,
+               /*atomic=*/ true,
+               codegen_);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutLongVolatile(HInvoke* invoke) {
+  CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kInt64, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutLongVolatile(HInvoke* invoke) {
+  GenUnsafePut(invoke,
+               DataType::Type::kInt64,
+               std::memory_order_seq_cst,
+               /*atomic=*/ true,
+               codegen_);
+}
+
+static void EmitLoadExclusive(CodeGeneratorARMVIXL* codegen,
+                              DataType::Type type,
+                              vixl32::Register ptr,
+                              Location old_value) {
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  switch (type) {
+    case DataType::Type::kBool:
+    case DataType::Type::kInt8:
+      __ Ldrexb(RegisterFrom(old_value), MemOperand(ptr));
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Ldrexh(RegisterFrom(old_value), MemOperand(ptr));
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kReference:
+      __ Ldrex(RegisterFrom(old_value), MemOperand(ptr));
+      break;
+    case DataType::Type::kInt64:
+      __ Ldrexd(LowRegisterFrom(old_value), HighRegisterFrom(old_value), MemOperand(ptr));
+      break;
+    default:
+      LOG(FATAL) << "Unexpected type: " << type;
+      UNREACHABLE();
+  }
+  switch (type) {
+    case DataType::Type::kInt8:
+      __ Sxtb(RegisterFrom(old_value), RegisterFrom(old_value));
+      break;
+    case DataType::Type::kInt16:
+      __ Sxth(RegisterFrom(old_value), RegisterFrom(old_value));
+      break;
+    case DataType::Type::kReference:
+      assembler->MaybeUnpoisonHeapReference(RegisterFrom(old_value));
+      break;
+    default:
+      break;
+  }
+}
+
+static void EmitStoreExclusive(CodeGeneratorARMVIXL* codegen,
+                               DataType::Type type,
+                               vixl32::Register ptr,
+                               vixl32::Register store_result,
+                               Location new_value) {
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  if (type == DataType::Type::kReference) {
+    assembler->MaybePoisonHeapReference(RegisterFrom(new_value));
+  }
+  switch (type) {
+    case DataType::Type::kBool:
+    case DataType::Type::kInt8:
+      __ Strexb(store_result, RegisterFrom(new_value), MemOperand(ptr));
+      break;
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt16:
+      __ Strexh(store_result, RegisterFrom(new_value), MemOperand(ptr));
+      break;
+    case DataType::Type::kInt32:
+    case DataType::Type::kReference:
+      __ Strex(store_result, RegisterFrom(new_value), MemOperand(ptr));
+      break;
+    case DataType::Type::kInt64:
+      __ Strexd(
+          store_result, LowRegisterFrom(new_value), HighRegisterFrom(new_value), MemOperand(ptr));
+      break;
+    default:
+      LOG(FATAL) << "Unexpected type: " << type;
+      UNREACHABLE();
+  }
+  if (type == DataType::Type::kReference) {
+    assembler->MaybeUnpoisonHeapReference(RegisterFrom(new_value));
+  }
+}
+
+static void GenerateCompareAndSet(CodeGeneratorARMVIXL* codegen,
+                                  DataType::Type type,
+                                  bool strong,
+                                  vixl32::Label* cmp_failure,
+                                  bool cmp_failure_is_far_target,
+                                  vixl32::Register ptr,
+                                  Location expected,
+                                  Location new_value,
+                                  Location old_value,
+                                  vixl32::Register store_result,
+                                  vixl32::Register success) {
+  // For kReference, the `expected` shall be a register pair when called from a read barrier
+  // slow path, specifying both the original `expected` as well as the unmarked old value from
+  // the main path attempt to emit CAS when it matched `expected` after marking.
+  // Otherwise the type of `expected` shall match the type of `new_value` and `old_value`.
+  if (type == DataType::Type::kInt64) {
+    DCHECK(expected.IsRegisterPair());
+    DCHECK(new_value.IsRegisterPair());
+    DCHECK(old_value.IsRegisterPair());
+  } else {
+    DCHECK(expected.IsRegister() ||
+           (type == DataType::Type::kReference && expected.IsRegisterPair()));
+    DCHECK(new_value.IsRegister());
+    DCHECK(old_value.IsRegister());
+  }
+
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+
+  // do {
+  //   old_value = [ptr];  // Load exclusive.
+  //   if (old_value != expected) goto cmp_failure;
+  //   store_result = failed([ptr] <- new_value);  // Store exclusive.
+  // } while (strong && store_result);
+  //
+  // If `success` is a valid register, there are additional instructions in the above code
+  // to report success with value 1 and failure with value 0 in that register.
+
+  vixl32::Label loop_head;
+  if (strong) {
+    __ Bind(&loop_head);
+  }
+  EmitLoadExclusive(codegen, type, ptr, old_value);
+  // We do not need to initialize the failure code for comparison failure if the
+  // branch goes to the read barrier slow path that clobbers `success` anyway.
+  bool init_failure_for_cmp =
+      success.IsValid() &&
+      !(kEmitCompilerReadBarrier && type == DataType::Type::kReference && expected.IsRegister());
+  // Instruction scheduling: Loading a constant between LDREX* and using the loaded value
+  // is essentially free, so prepare the failure value here if we can.
+  bool init_failure_for_cmp_early =
+      init_failure_for_cmp && !old_value.Contains(LocationFrom(success));
+  if (init_failure_for_cmp_early) {
+    __ Mov(success, 0);  // Indicate failure if the comparison fails.
+  }
+  if (type == DataType::Type::kInt64) {
+    __ Cmp(LowRegisterFrom(old_value), LowRegisterFrom(expected));
+    ExactAssemblyScope aas(assembler->GetVIXLAssembler(), 2 * k16BitT32InstructionSizeInBytes);
+    __ it(eq);
+    __ cmp(eq, HighRegisterFrom(old_value), HighRegisterFrom(expected));
+  } else if (expected.IsRegisterPair()) {
+    DCHECK_EQ(type, DataType::Type::kReference);
+    // Check if the loaded value matches any of the two registers in `expected`.
+    __ Cmp(RegisterFrom(old_value), LowRegisterFrom(expected));
+    ExactAssemblyScope aas(assembler->GetVIXLAssembler(), 2 * k16BitT32InstructionSizeInBytes);
+    __ it(ne);
+    __ cmp(ne, RegisterFrom(old_value), HighRegisterFrom(expected));
+  } else {
+    __ Cmp(RegisterFrom(old_value), RegisterFrom(expected));
+  }
+  if (init_failure_for_cmp && !init_failure_for_cmp_early) {
+    __ Mov(LeaveFlags, success, 0);  // Indicate failure if the comparison fails.
+  }
+  __ B(ne, cmp_failure, /*is_far_target=*/ cmp_failure_is_far_target);
+  EmitStoreExclusive(codegen, type, ptr, store_result, new_value);
+  if (strong) {
+    // Instruction scheduling: Loading a constant between STREX* and using its result
+    // is essentially free, so prepare the success value here if needed.
+    if (success.IsValid()) {
+      DCHECK(!success.Is(store_result));
+      __ Mov(success, 1);  // Indicate success if the store succeeds.
+    }
+    __ Cmp(store_result, 0);
+    __ B(ne, &loop_head, /*is_far_target=*/ false);
+  } else {
+    // Weak CAS (VarHandle.CompareAndExchange variants) always indicates success.
+    DCHECK(success.IsValid());
+    // Flip the `store_result` to indicate success by 1 and failure by 0.
+    __ Eor(success, store_result, 1);
+  }
+}
+
+class ReadBarrierCasSlowPathARMVIXL : public SlowPathCodeARMVIXL {
+ public:
+  explicit ReadBarrierCasSlowPathARMVIXL(HInvoke* invoke,
+                                         bool strong,
+                                         vixl32::Register base,
+                                         vixl32::Register offset,
+                                         vixl32::Register expected,
+                                         vixl32::Register new_value,
+                                         vixl32::Register old_value,
+                                         vixl32::Register old_value_temp,
+                                         vixl32::Register store_result,
+                                         vixl32::Register success,
+                                         CodeGeneratorARMVIXL* arm_codegen)
+      : SlowPathCodeARMVIXL(invoke),
+        strong_(strong),
+        base_(base),
+        offset_(offset),
+        expected_(expected),
+        new_value_(new_value),
+        old_value_(old_value),
+        old_value_temp_(old_value_temp),
+        store_result_(store_result),
+        success_(success),
+        mark_old_value_slow_path_(nullptr),
+        update_old_value_slow_path_(nullptr) {
+    if (!kUseBakerReadBarrier) {
+      // We need to add the slow path now, it is too late when emitting slow path code.
+      mark_old_value_slow_path_ = arm_codegen->AddReadBarrierSlowPath(
+          invoke,
+          Location::RegisterLocation(old_value_temp.GetCode()),
+          Location::RegisterLocation(old_value.GetCode()),
+          Location::RegisterLocation(base.GetCode()),
+          /*offset=*/ 0u,
+          /*index=*/ Location::RegisterLocation(offset.GetCode()));
+      if (!success.IsValid()) {
+        update_old_value_slow_path_ = arm_codegen->AddReadBarrierSlowPath(
+            invoke,
+            Location::RegisterLocation(old_value.GetCode()),
+            Location::RegisterLocation(old_value_temp.GetCode()),
+            Location::RegisterLocation(base.GetCode()),
+            /*offset=*/ 0u,
+            /*index=*/ Location::RegisterLocation(offset.GetCode()));
+      }
+    }
+  }
+
+  const char* GetDescription() const override { return "ReadBarrierCasSlowPathARMVIXL"; }
+
+  void EmitNativeCode(CodeGenerator* codegen) override {
+    CodeGeneratorARMVIXL* arm_codegen = down_cast<CodeGeneratorARMVIXL*>(codegen);
+    ArmVIXLAssembler* assembler = arm_codegen->GetAssembler();
+    __ Bind(GetEntryLabel());
+
+    // Mark the `old_value_` from the main path and compare with `expected_`.
+    if (kUseBakerReadBarrier) {
+      DCHECK(mark_old_value_slow_path_ == nullptr);
+      arm_codegen->GenerateIntrinsicCasMoveWithBakerReadBarrier(old_value_temp_, old_value_);
+    } else {
+      DCHECK(mark_old_value_slow_path_ != nullptr);
+      __ B(mark_old_value_slow_path_->GetEntryLabel());
+      __ Bind(mark_old_value_slow_path_->GetExitLabel());
+    }
+    __ Cmp(old_value_temp_, expected_);
+    if (success_.IsValid()) {
+      __ Mov(LeaveFlags, success_, 0);  // Indicate failure if we take the branch out.
+    } else {
+      // In case of failure, update the `old_value_` with the marked reference.
+      ExactAssemblyScope aas(assembler->GetVIXLAssembler(), 2 * k16BitT32InstructionSizeInBytes);
+      __ it(ne);
+      __ mov(ne, old_value_, old_value_temp_);
+    }
+    __ B(ne, GetExitLabel());
+
+    // The old value we have read did not match `expected` (which is always a to-space
+    // reference) but after the read barrier the marked to-space value matched, so the
+    // old value must be a from-space reference to the same object. Do the same CAS loop
+    // as the main path but check for both `expected` and the unmarked old value
+    // representing the to-space and from-space references for the same object.
+
+    UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+    vixl32::Register tmp_ptr = temps.Acquire();
+
+    // Recalculate the `tmp_ptr` clobbered above.
+    __ Add(tmp_ptr, base_, offset_);
+
+    vixl32::Label mark_old_value;
+    GenerateCompareAndSet(arm_codegen,
+                          DataType::Type::kReference,
+                          strong_,
+                          /*cmp_failure=*/ success_.IsValid() ? GetExitLabel() : &mark_old_value,
+                          /*cmp_failure_is_far_target=*/ success_.IsValid(),
+                          tmp_ptr,
+                          /*expected=*/ LocationFrom(expected_, old_value_),
+                          /*new_value=*/ LocationFrom(new_value_),
+                          /*old_value=*/ LocationFrom(old_value_temp_),
+                          store_result_,
+                          success_);
+    if (!success_.IsValid()) {
+      // To reach this point, the `old_value_temp_` must be either a from-space or a to-space
+      // reference of the `expected_` object. Update the `old_value_` to the to-space reference.
+      __ Mov(old_value_, expected_);
+    }
+
+    __ B(GetExitLabel());
+
+    if (!success_.IsValid()) {
+      __ Bind(&mark_old_value);
+      if (kUseBakerReadBarrier) {
+        DCHECK(update_old_value_slow_path_ == nullptr);
+        arm_codegen->GenerateIntrinsicCasMoveWithBakerReadBarrier(old_value_, old_value_temp_);
+      } else {
+        // Note: We could redirect the `failure` above directly to the entry label and bind
+        // the exit label in the main path, but the main path would need to access the
+        // `update_old_value_slow_path_`. To keep the code simple, keep the extra jumps.
+        DCHECK(update_old_value_slow_path_ != nullptr);
+        __ B(update_old_value_slow_path_->GetEntryLabel());
+        __ Bind(update_old_value_slow_path_->GetExitLabel());
+      }
+      __ B(GetExitLabel());
+    }
+  }
+
+ private:
+  bool strong_;
+  vixl32::Register base_;
+  vixl32::Register offset_;
+  vixl32::Register expected_;
+  vixl32::Register new_value_;
+  vixl32::Register old_value_;
+  vixl32::Register old_value_temp_;
+  vixl32::Register store_result_;
+  vixl32::Register success_;
+  SlowPathCodeARMVIXL* mark_old_value_slow_path_;
+  SlowPathCodeARMVIXL* update_old_value_slow_path_;
+};
+
+static void CreateUnsafeCASLocations(ArenaAllocator* allocator, HInvoke* invoke) {
+  bool can_call = kEmitCompilerReadBarrier &&
+      (invoke->GetIntrinsic() == Intrinsics::kUnsafeCASObject);
+  LocationSummary* locations =
+      new (allocator) LocationSummary(invoke,
+                                      can_call
+                                          ? LocationSummary::kCallOnSlowPath
+                                          : LocationSummary::kNoCall,
+                                      kIntrinsified);
+  if (can_call && kUseBakerReadBarrier) {
+    locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty());  // No caller-save registers.
+  }
+  locations->SetInAt(0, Location::NoLocation());        // Unused receiver.
+  locations->SetInAt(1, Location::RequiresRegister());
+  locations->SetInAt(2, Location::RequiresRegister());
+  locations->SetInAt(3, Location::RequiresRegister());
+  locations->SetInAt(4, Location::RequiresRegister());
+
+  locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
+
+  // Temporary register used in CAS. In the object case (UnsafeCASObject intrinsic),
+  // this is also used for card-marking, and possibly for read barrier.
+  locations->AddTemp(Location::RequiresRegister());
+}
+
+static void GenUnsafeCas(HInvoke* invoke, DataType::Type type, CodeGeneratorARMVIXL* codegen) {
+  DCHECK_NE(type, DataType::Type::kInt64);
+
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+
+  vixl32::Register out = OutputRegister(invoke);                      // Boolean result.
+  vixl32::Register base = InputRegisterAt(invoke, 1);                 // Object pointer.
+  vixl32::Register offset = LowRegisterFrom(locations->InAt(2));      // Offset (discard high 4B).
+  vixl32::Register expected = InputRegisterAt(invoke, 3);             // Expected.
+  vixl32::Register new_value = InputRegisterAt(invoke, 4);            // New value.
+
+  vixl32::Register tmp = RegisterFrom(locations->GetTemp(0));         // Temporary.
+
+  UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+  vixl32::Register tmp_ptr = temps.Acquire();
+
+  if (type == DataType::Type::kReference) {
+    // Mark card for object assuming new value is stored. Worst case we will mark an unchanged
+    // object and scan the receiver at the next GC for nothing.
+    bool value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(tmp_ptr, tmp, base, new_value, value_can_be_null);
+  }
+
+  vixl32::Label exit_loop_label;
+  vixl32::Label* exit_loop = &exit_loop_label;
+  vixl32::Label* cmp_failure = &exit_loop_label;
+
+  if (kEmitCompilerReadBarrier && type == DataType::Type::kReference) {
+    // If marking, check if the stored reference is a from-space reference to the same
+    // object as the to-space reference `expected`. If so, perform a custom CAS loop.
+    ReadBarrierCasSlowPathARMVIXL* slow_path =
+        new (codegen->GetScopedAllocator()) ReadBarrierCasSlowPathARMVIXL(
+            invoke,
+            /*strong=*/ true,
+            base,
+            offset,
+            expected,
+            new_value,
+            /*old_value=*/ tmp,
+            /*old_value_temp=*/ out,
+            /*store_result=*/ tmp,
+            /*success=*/ out,
+            codegen);
+    codegen->AddSlowPath(slow_path);
+    exit_loop = slow_path->GetExitLabel();
+    cmp_failure = slow_path->GetEntryLabel();
+  }
+
+  // Unsafe CAS operations have std::memory_order_seq_cst semantics.
+  codegen->GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
+  __ Add(tmp_ptr, base, offset);
+  GenerateCompareAndSet(codegen,
+                        type,
+                        /*strong=*/ true,
+                        cmp_failure,
+                        /*cmp_failure_is_far_target=*/ cmp_failure != &exit_loop_label,
+                        tmp_ptr,
+                        /*expected=*/ LocationFrom(expected),  // TODO: Int64
+                        /*new_value=*/ LocationFrom(new_value),  // TODO: Int64
+                        /*old_value=*/ LocationFrom(tmp),  // TODO: Int64
+                        /*store_result=*/ tmp,
+                        /*success=*/ out);
+  __ Bind(exit_loop);
+  codegen->GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
+
+  if (type == DataType::Type::kReference) {
+    codegen->MaybeGenerateMarkingRegisterCheck(/*code=*/ 128, /*temp_loc=*/ LocationFrom(tmp_ptr));
+  }
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeCASInt(HInvoke* invoke) {
+  CreateUnsafeCASLocations(allocator_, invoke);
+}
+void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeCASObject(HInvoke* invoke) {
+  // The only read barrier implementation supporting the
+  // UnsafeCASObject intrinsic is the Baker-style read barriers. b/173104084
+  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+    return;
+  }
+
+  CreateUnsafeCASLocations(allocator_, invoke);
+}
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeCASInt(HInvoke* invoke) {
+  GenUnsafeCas(invoke, DataType::Type::kInt32, codegen_);
+}
+void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeCASObject(HInvoke* invoke) {
+  GenUnsafeCas(invoke, DataType::Type::kReference, codegen_);
+}
+
+enum class GetAndUpdateOp {
+  kSet,
+  kAdd,
+  kAddWithByteSwap,
+  kAnd,
+  kOr,
+  kXor
+};
+
+static void GenerateGetAndUpdate(CodeGeneratorARMVIXL* codegen,
+                                 GetAndUpdateOp get_and_update_op,
+                                 DataType::Type load_store_type,
+                                 vixl32::Register ptr,
+                                 Location arg,
+                                 Location old_value,
+                                 vixl32::Register store_result,
+                                 Location maybe_temp,
+                                 Location maybe_vreg_temp) {
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+
+  Location loaded_value;
+  Location new_value;
+  switch (get_and_update_op) {
+    case GetAndUpdateOp::kSet:
+      loaded_value = old_value;
+      new_value = arg;
+      break;
+    case GetAndUpdateOp::kAddWithByteSwap:
+      if (old_value.IsRegisterPair()) {
+        // To avoid register overlap when reversing bytes, load into temps.
+        DCHECK(maybe_temp.IsRegisterPair());
+        loaded_value = maybe_temp;
+        new_value = loaded_value;  // Use the same temporaries for the new value.
+        break;
+      }
+      FALLTHROUGH_INTENDED;
+    case GetAndUpdateOp::kAdd:
+      if (old_value.IsFpuRegisterPair()) {
+        DCHECK(maybe_temp.IsRegisterPair());
+        loaded_value = maybe_temp;
+        new_value = loaded_value;  // Use the same temporaries for the new value.
+        break;
+      }
+      if (old_value.IsFpuRegister()) {
+        DCHECK(maybe_temp.IsRegister());
+        loaded_value = maybe_temp;
+        new_value = loaded_value;  // Use the same temporary for the new value.
+        break;
+      }
+      FALLTHROUGH_INTENDED;
+    case GetAndUpdateOp::kAnd:
+    case GetAndUpdateOp::kOr:
+    case GetAndUpdateOp::kXor:
+      loaded_value = old_value;
+      new_value = maybe_temp;
+      break;
+  }
+
+  vixl32::Label loop_label;
+  __ Bind(&loop_label);
+  EmitLoadExclusive(codegen, load_store_type, ptr, loaded_value);
+  switch (get_and_update_op) {
+    case GetAndUpdateOp::kSet:
+      break;
+    case GetAndUpdateOp::kAddWithByteSwap:
+      if (arg.IsFpuRegisterPair()) {
+        GenerateReverseBytes(assembler, DataType::Type::kFloat64, loaded_value, old_value);
+        vixl32::DRegister sum = DRegisterFrom(maybe_vreg_temp);
+        __ Vadd(sum, DRegisterFrom(old_value), DRegisterFrom(arg));
+        __ Vmov(HighRegisterFrom(new_value), LowRegisterFrom(new_value), sum);  // Swap low/high.
+      } else if (arg.IsFpuRegister()) {
+        GenerateReverseBytes(assembler, DataType::Type::kFloat32, loaded_value, old_value);
+        vixl32::SRegister sum = LowSRegisterFrom(maybe_vreg_temp);  // The temporary is a pair.
+        __ Vadd(sum, SRegisterFrom(old_value), SRegisterFrom(arg));
+        __ Vmov(RegisterFrom(new_value), sum);
+      } else if (load_store_type == DataType::Type::kInt64) {
+        GenerateReverseBytes(assembler, DataType::Type::kInt64, loaded_value, old_value);
+        // Swap low/high registers for the addition results.
+        __ Adds(HighRegisterFrom(new_value), LowRegisterFrom(old_value), LowRegisterFrom(arg));
+        __ Adc(LowRegisterFrom(new_value), HighRegisterFrom(old_value), HighRegisterFrom(arg));
+      } else {
+        GenerateReverseBytes(assembler, DataType::Type::kInt32, loaded_value, old_value);
+        __ Add(RegisterFrom(new_value), RegisterFrom(old_value), RegisterFrom(arg));
+      }
+      if (load_store_type == DataType::Type::kInt64) {
+        // The `new_value` already has the high and low word swapped. Reverse bytes in each.
+        GenerateReverseBytesInPlaceForEachWord(assembler, new_value);
+      } else {
+        GenerateReverseBytes(assembler, load_store_type, new_value, new_value);
+      }
+      break;
+    case GetAndUpdateOp::kAdd:
+      if (arg.IsFpuRegisterPair()) {
+        vixl32::DRegister old_value_vreg = DRegisterFrom(old_value);
+        vixl32::DRegister sum = DRegisterFrom(maybe_vreg_temp);
+        __ Vmov(old_value_vreg, LowRegisterFrom(loaded_value), HighRegisterFrom(loaded_value));
+        __ Vadd(sum, old_value_vreg, DRegisterFrom(arg));
+        __ Vmov(LowRegisterFrom(new_value), HighRegisterFrom(new_value), sum);
+      } else if (arg.IsFpuRegister()) {
+        vixl32::SRegister old_value_vreg = SRegisterFrom(old_value);
+        vixl32::SRegister sum = LowSRegisterFrom(maybe_vreg_temp);  // The temporary is a pair.
+        __ Vmov(old_value_vreg, RegisterFrom(loaded_value));
+        __ Vadd(sum, old_value_vreg, SRegisterFrom(arg));
+        __ Vmov(RegisterFrom(new_value), sum);
+      } else if (load_store_type == DataType::Type::kInt64) {
+        __ Adds(LowRegisterFrom(new_value), LowRegisterFrom(loaded_value), LowRegisterFrom(arg));
+        __ Adc(HighRegisterFrom(new_value), HighRegisterFrom(loaded_value), HighRegisterFrom(arg));
+      } else {
+        __ Add(RegisterFrom(new_value), RegisterFrom(loaded_value), RegisterFrom(arg));
+      }
+      break;
+    case GetAndUpdateOp::kAnd:
+      if (load_store_type == DataType::Type::kInt64) {
+        __ And(LowRegisterFrom(new_value), LowRegisterFrom(loaded_value), LowRegisterFrom(arg));
+        __ And(HighRegisterFrom(new_value), HighRegisterFrom(loaded_value), HighRegisterFrom(arg));
+      } else {
+        __ And(RegisterFrom(new_value), RegisterFrom(loaded_value), RegisterFrom(arg));
+      }
+      break;
+    case GetAndUpdateOp::kOr:
+      if (load_store_type == DataType::Type::kInt64) {
+        __ Orr(LowRegisterFrom(new_value), LowRegisterFrom(loaded_value), LowRegisterFrom(arg));
+        __ Orr(HighRegisterFrom(new_value), HighRegisterFrom(loaded_value), HighRegisterFrom(arg));
+      } else {
+        __ Orr(RegisterFrom(new_value), RegisterFrom(loaded_value), RegisterFrom(arg));
+      }
+      break;
+    case GetAndUpdateOp::kXor:
+      if (load_store_type == DataType::Type::kInt64) {
+        __ Eor(LowRegisterFrom(new_value), LowRegisterFrom(loaded_value), LowRegisterFrom(arg));
+        __ Eor(HighRegisterFrom(new_value), HighRegisterFrom(loaded_value), HighRegisterFrom(arg));
+      } else {
+        __ Eor(RegisterFrom(new_value), RegisterFrom(loaded_value), RegisterFrom(arg));
+      }
+      break;
+  }
+  EmitStoreExclusive(codegen, load_store_type, ptr, store_result, new_value);
+  __ Cmp(store_result, 0);
+  __ B(ne, &loop_label);
+}
+
+class VarHandleSlowPathARMVIXL : public IntrinsicSlowPathARMVIXL {
+ public:
+  VarHandleSlowPathARMVIXL(HInvoke* invoke, std::memory_order order)
+      : IntrinsicSlowPathARMVIXL(invoke),
+        order_(order),
+        atomic_(false),
+        return_success_(false),
+        strong_(false),
+        get_and_update_op_(GetAndUpdateOp::kAdd) {
+  }
+
+  vixl32::Label* GetByteArrayViewCheckLabel() {
+    return &byte_array_view_check_label_;
+  }
+
+  vixl32::Label* GetNativeByteOrderLabel() {
+    return &native_byte_order_label_;
+  }
+
+  void SetAtomic(bool atomic) {
+    DCHECK(GetAccessModeTemplate() == mirror::VarHandle::AccessModeTemplate::kGet ||
+           GetAccessModeTemplate() == mirror::VarHandle::AccessModeTemplate::kSet);
+    atomic_ = atomic;
+  }
+
+  void SetCompareAndSetOrExchangeArgs(bool return_success, bool strong) {
+    if (return_success) {
+      DCHECK(GetAccessModeTemplate() == mirror::VarHandle::AccessModeTemplate::kCompareAndSet);
+    } else {
+      DCHECK(GetAccessModeTemplate() == mirror::VarHandle::AccessModeTemplate::kCompareAndExchange);
+    }
+    return_success_ = return_success;
+    strong_ = strong;
+  }
+
+  void SetGetAndUpdateOp(GetAndUpdateOp get_and_update_op) {
+    DCHECK(GetAccessModeTemplate() == mirror::VarHandle::AccessModeTemplate::kGetAndUpdate);
+    get_and_update_op_ = get_and_update_op;
+  }
+
+  void EmitNativeCode(CodeGenerator* codegen_in) override {
+    if (GetByteArrayViewCheckLabel()->IsReferenced()) {
+      EmitByteArrayViewCode(codegen_in);
+    }
+    IntrinsicSlowPathARMVIXL::EmitNativeCode(codegen_in);
+  }
+
+ private:
+  HInvoke* GetInvoke() const {
+    return GetInstruction()->AsInvoke();
+  }
+
+  mirror::VarHandle::AccessModeTemplate GetAccessModeTemplate() const {
+    return mirror::VarHandle::GetAccessModeTemplateByIntrinsic(GetInvoke()->GetIntrinsic());
+  }
+
+  void EmitByteArrayViewCode(CodeGenerator* codegen_in);
+
+  vixl32::Label byte_array_view_check_label_;
+  vixl32::Label native_byte_order_label_;
+  // Shared parameter for all VarHandle intrinsics.
+  std::memory_order order_;
+  // Extra argument for GenerateVarHandleGet() and GenerateVarHandleSet().
+  bool atomic_;
+  // Extra arguments for GenerateVarHandleCompareAndSetOrExchange().
+  bool return_success_;
+  bool strong_;
+  // Extra argument for GenerateVarHandleGetAndUpdate().
+  GetAndUpdateOp get_and_update_op_;
+};
+
+// Generate subtype check without read barriers.
+static void GenerateSubTypeObjectCheckNoReadBarrier(CodeGeneratorARMVIXL* codegen,
+                                                    SlowPathCodeARMVIXL* slow_path,
+                                                    vixl32::Register object,
+                                                    vixl32::Register type,
+                                                    bool object_can_be_null = true) {
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+
+  const MemberOffset class_offset = mirror::Object::ClassOffset();
+  const MemberOffset super_class_offset = mirror::Class::SuperClassOffset();
+
+  vixl32::Label success;
+  if (object_can_be_null) {
+    __ CompareAndBranchIfZero(object, &success, /*is_far_target=*/ false);
+  }
+
+  UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+  vixl32::Register temp = temps.Acquire();
+
+  __ Ldr(temp, MemOperand(object, class_offset.Int32Value()));
+  assembler->MaybeUnpoisonHeapReference(temp);
+  vixl32::Label loop;
+  __ Bind(&loop);
+  __ Cmp(type, temp);
+  __ B(eq, &success, /*is_far_target=*/ false);
+  __ Ldr(temp, MemOperand(temp, super_class_offset.Int32Value()));
+  assembler->MaybeUnpoisonHeapReference(temp);
+  __ Cmp(temp, 0);
+  __ B(eq, slow_path->GetEntryLabel());
+  __ B(&loop);
+  __ Bind(&success);
+}
+
+// Check access mode and the primitive type from VarHandle.varType.
+// Check reference arguments against the VarHandle.varType; for references this is a subclass
+// check without read barrier, so it can have false negatives which we handle in the slow path.
+static void GenerateVarHandleAccessModeAndVarTypeChecks(HInvoke* invoke,
+                                                        CodeGeneratorARMVIXL* codegen,
+                                                        SlowPathCodeARMVIXL* slow_path,
+                                                        DataType::Type type) {
+  mirror::VarHandle::AccessMode access_mode =
+      mirror::VarHandle::GetAccessModeByIntrinsic(invoke->GetIntrinsic());
+  Primitive::Type primitive_type = DataTypeToPrimitive(type);
+
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  vixl32::Register varhandle = InputRegisterAt(invoke, 0);
+
+  const MemberOffset var_type_offset = mirror::VarHandle::VarTypeOffset();
+  const MemberOffset access_mode_bit_mask_offset = mirror::VarHandle::AccessModesBitMaskOffset();
+  const MemberOffset primitive_type_offset = mirror::Class::PrimitiveTypeOffset();
+
+  // Use the temporary register reserved for offset. It is not used yet at this point.
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  vixl32::Register var_type_no_rb =
+      RegisterFrom(invoke->GetLocations()->GetTemp(expected_coordinates_count == 0u ? 1u : 0u));
+
+  // Check that the operation is permitted and the primitive type of varhandle.varType.
+  // We do not need a read barrier when loading a reference only for loading constant
+  // primitive field through the reference. Use LDRD to load the fields together.
+  {
+    UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+    vixl32::Register temp2 = temps.Acquire();
+    DCHECK_EQ(var_type_offset.Int32Value() + 4, access_mode_bit_mask_offset.Int32Value());
+    __ Ldrd(var_type_no_rb, temp2, MemOperand(varhandle, var_type_offset.Int32Value()));
+    assembler->MaybeUnpoisonHeapReference(var_type_no_rb);
+    __ Tst(temp2, 1u << static_cast<uint32_t>(access_mode));
+    __ B(eq, slow_path->GetEntryLabel());
+    __ Ldrh(temp2, MemOperand(var_type_no_rb, primitive_type_offset.Int32Value()));
+    __ Cmp(temp2, static_cast<uint16_t>(primitive_type));
+    __ B(ne, slow_path->GetEntryLabel());
+  }
+
+  if (type == DataType::Type::kReference) {
+    // Check reference arguments against the varType.
+    // False negatives due to varType being an interface or array type
+    // or due to the missing read barrier are handled by the slow path.
+    uint32_t arguments_start = /* VarHandle object */ 1u + expected_coordinates_count;
+    uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+    for (size_t arg_index = arguments_start; arg_index != number_of_arguments; ++arg_index) {
+      HInstruction* arg = invoke->InputAt(arg_index);
+      DCHECK_EQ(arg->GetType(), DataType::Type::kReference);
+      if (!arg->IsNullConstant()) {
+        vixl32::Register arg_reg = RegisterFrom(invoke->GetLocations()->InAt(arg_index));
+        GenerateSubTypeObjectCheckNoReadBarrier(codegen, slow_path, arg_reg, var_type_no_rb);
+      }
+    }
+  }
+}
+
+static void GenerateVarHandleStaticFieldCheck(HInvoke* invoke,
+                                              CodeGeneratorARMVIXL* codegen,
+                                              SlowPathCodeARMVIXL* slow_path) {
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  vixl32::Register varhandle = InputRegisterAt(invoke, 0);
+
+  const MemberOffset coordinate_type0_offset = mirror::VarHandle::CoordinateType0Offset();
+
+  UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+  vixl32::Register temp = temps.Acquire();
+
+  // Check that the VarHandle references a static field by checking that coordinateType0 == null.
+  // Do not emit read barrier (or unpoison the reference) for comparing to null.
+  __ Ldr(temp, MemOperand(varhandle, coordinate_type0_offset.Int32Value()));
+  __ Cmp(temp, 0);
+  __ B(ne, slow_path->GetEntryLabel());
+}
+
+static void GenerateVarHandleInstanceFieldChecks(HInvoke* invoke,
+                                                 CodeGeneratorARMVIXL* codegen,
+                                                 SlowPathCodeARMVIXL* slow_path) {
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  vixl32::Register varhandle = InputRegisterAt(invoke, 0);
+  vixl32::Register object = InputRegisterAt(invoke, 1);
+
+  const MemberOffset coordinate_type0_offset = mirror::VarHandle::CoordinateType0Offset();
+  const MemberOffset coordinate_type1_offset = mirror::VarHandle::CoordinateType1Offset();
+
+  // Null-check the object.
+  __ Cmp(object, 0);
+  __ B(eq, slow_path->GetEntryLabel());
+
+  // Use the first temporary register, whether it's for the declaring class or the offset.
+  // It is not used yet at this point.
+  vixl32::Register temp = RegisterFrom(invoke->GetLocations()->GetTemp(0u));
+
+  // Check that the VarHandle references an instance field by checking that
+  // coordinateType1 == null. coordinateType0 should not be null, but this is handled by the
+  // type compatibility check with the source object's type, which will fail for null.
+  {
+    UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+    vixl32::Register temp2 = temps.Acquire();
+    DCHECK_EQ(coordinate_type0_offset.Int32Value() + 4, coordinate_type1_offset.Int32Value());
+    __ Ldrd(temp, temp2, MemOperand(varhandle, coordinate_type0_offset.Int32Value()));
+    assembler->MaybeUnpoisonHeapReference(temp);
+    // No need for read barrier or unpoisoning of coordinateType1 for comparison with null.
+    __ Cmp(temp2, 0);
+    __ B(ne, slow_path->GetEntryLabel());
+  }
+
+  // Check that the object has the correct type.
+  // We deliberately avoid the read barrier, letting the slow path handle the false negatives.
+  GenerateSubTypeObjectCheckNoReadBarrier(
+      codegen, slow_path, object, temp, /*object_can_be_null=*/ false);
+}
+
+static DataType::Type GetVarHandleExpectedValueType(HInvoke* invoke,
+                                                    size_t expected_coordinates_count) {
+  DCHECK_EQ(expected_coordinates_count, GetExpectedVarHandleCoordinatesCount(invoke));
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  DCHECK_GE(number_of_arguments, /* VarHandle object */ 1u + expected_coordinates_count);
+  if (number_of_arguments == /* VarHandle object */ 1u + expected_coordinates_count) {
+    return invoke->GetType();
+  } else {
+    return GetDataTypeFromShorty(invoke, number_of_arguments - 1u);
+  }
+}
+
+static void GenerateVarHandleArrayChecks(HInvoke* invoke,
+                                         CodeGeneratorARMVIXL* codegen,
+                                         VarHandleSlowPathARMVIXL* slow_path) {
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  vixl32::Register varhandle = InputRegisterAt(invoke, 0);
+  vixl32::Register object = InputRegisterAt(invoke, 1);
+  vixl32::Register index = InputRegisterAt(invoke, 2);
+  DataType::Type value_type =
+      GetVarHandleExpectedValueType(invoke, /*expected_coordinates_count=*/ 2u);
+  Primitive::Type primitive_type = DataTypeToPrimitive(value_type);
+
+  const MemberOffset coordinate_type0_offset = mirror::VarHandle::CoordinateType0Offset();
+  const MemberOffset coordinate_type1_offset = mirror::VarHandle::CoordinateType1Offset();
+  const MemberOffset component_type_offset = mirror::Class::ComponentTypeOffset();
+  const MemberOffset primitive_type_offset = mirror::Class::PrimitiveTypeOffset();
+  const MemberOffset class_offset = mirror::Object::ClassOffset();
+  const MemberOffset array_length_offset = mirror::Array::LengthOffset();
+
+  // Null-check the object.
+  __ Cmp(object, 0);
+  __ B(eq, slow_path->GetEntryLabel());
+
+  // Use the offset temporary register. It is not used yet at this point.
+  vixl32::Register temp = RegisterFrom(invoke->GetLocations()->GetTemp(0u));
+
+  UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+  vixl32::Register temp2 = temps.Acquire();
+
+  // Check that the VarHandle references an array, byte array view or ByteBuffer by checking
+  // that coordinateType1 != null. If that's true, coordinateType1 shall be int.class and
+  // coordinateType0 shall not be null but we do not explicitly verify that.
+  DCHECK_EQ(coordinate_type0_offset.Int32Value() + 4, coordinate_type1_offset.Int32Value());
+  __ Ldrd(temp, temp2, MemOperand(varhandle, coordinate_type0_offset.Int32Value()));
+  codegen->GetAssembler()->MaybeUnpoisonHeapReference(temp);
+  // No need for read barrier or unpoisoning of coordinateType1 for comparison with null.
+  __ Cmp(temp2, 0);
+  __ B(eq, slow_path->GetEntryLabel());
+
+  // Check object class against componentType0.
+  //
+  // This is an exact check and we defer other cases to the runtime. This includes
+  // conversion to array of superclass references, which is valid but subsequently
+  // requires all update operations to check that the value can indeed be stored.
+  // We do not want to perform such extra checks in the intrinsified code.
+  //
+  // We do this check without read barrier, so there can be false negatives which we
+  // defer to the slow path. There shall be no false negatives for array classes in the
+  // boot image (including Object[] and primitive arrays) because they are non-movable.
+  __ Ldr(temp2, MemOperand(object, class_offset.Int32Value()));
+  codegen->GetAssembler()->MaybeUnpoisonHeapReference(temp2);
+  __ Cmp(temp, temp2);
+  __ B(ne, slow_path->GetEntryLabel());
+
+  // Check that the coordinateType0 is an array type. We do not need a read barrier
+  // for loading constant reference fields (or chains of them) for comparison with null,
+  // nor for finally loading a constant primitive field (primitive type) below.
+  __ Ldr(temp2, MemOperand(temp, component_type_offset.Int32Value()));
+  codegen->GetAssembler()->MaybeUnpoisonHeapReference(temp2);
+  __ Cmp(temp2, 0);
+  __ B(eq, slow_path->GetEntryLabel());
+
+  // Check that the array component type matches the primitive type.
+  // With the exception of `kPrimNot`, `kPrimByte` and `kPrimBoolean`,
+  // we shall check for a byte array view in the slow path.
+  // The check requires the ByteArrayViewVarHandle.class to be in the boot image,
+  // so we cannot emit that if we're JITting without boot image.
+  bool boot_image_available =
+      codegen->GetCompilerOptions().IsBootImage() ||
+      !Runtime::Current()->GetHeap()->GetBootImageSpaces().empty();
+  DCHECK(boot_image_available || codegen->GetCompilerOptions().IsJitCompiler());
+  size_t can_be_view =
+      ((value_type != DataType::Type::kReference) && (DataType::Size(value_type) != 1u)) &&
+      boot_image_available;
+  vixl32::Label* slow_path_label =
+      can_be_view ? slow_path->GetByteArrayViewCheckLabel() : slow_path->GetEntryLabel();
+  __ Ldrh(temp2, MemOperand(temp2, primitive_type_offset.Int32Value()));
+  __ Cmp(temp2, static_cast<uint16_t>(primitive_type));
+  __ B(ne, slow_path_label);
+
+  // Check for array index out of bounds.
+  __ Ldr(temp, MemOperand(object, array_length_offset.Int32Value()));
+  __ Cmp(index, temp);
+  __ B(hs, slow_path->GetEntryLabel());
+}
+
+static void GenerateVarHandleCoordinateChecks(HInvoke* invoke,
+                                              CodeGeneratorARMVIXL* codegen,
+                                              VarHandleSlowPathARMVIXL* slow_path) {
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (expected_coordinates_count == 0u) {
+    GenerateVarHandleStaticFieldCheck(invoke, codegen, slow_path);
+  } else if (expected_coordinates_count == 1u) {
+    GenerateVarHandleInstanceFieldChecks(invoke, codegen, slow_path);
+  } else {
+    DCHECK_EQ(expected_coordinates_count, 2u);
+    GenerateVarHandleArrayChecks(invoke, codegen, slow_path);
+  }
+}
+
+static VarHandleSlowPathARMVIXL* GenerateVarHandleChecks(HInvoke* invoke,
+                                                         CodeGeneratorARMVIXL* codegen,
+                                                         std::memory_order order,
+                                                         DataType::Type type) {
+  VarHandleSlowPathARMVIXL* slow_path =
+      new (codegen->GetScopedAllocator()) VarHandleSlowPathARMVIXL(invoke, order);
+  codegen->AddSlowPath(slow_path);
+
+  GenerateVarHandleAccessModeAndVarTypeChecks(invoke, codegen, slow_path, type);
+  GenerateVarHandleCoordinateChecks(invoke, codegen, slow_path);
+
+  return slow_path;
+}
+
+struct VarHandleTarget {
+  vixl32::Register object;  // The object holding the value to operate on.
+  vixl32::Register offset;  // The offset of the value to operate on.
+};
+
+static VarHandleTarget GetVarHandleTarget(HInvoke* invoke) {
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  LocationSummary* locations = invoke->GetLocations();
+
+  VarHandleTarget target;
+  // The temporary allocated for loading the offset.
+  target.offset = RegisterFrom(locations->GetTemp(0u));
+  // The reference to the object that holds the value to operate on.
+  target.object = (expected_coordinates_count == 0u)
+      ? RegisterFrom(locations->GetTemp(1u))
+      : InputRegisterAt(invoke, 1);
+  return target;
+}
+
+static void GenerateVarHandleTarget(HInvoke* invoke,
+                                    const VarHandleTarget& target,
+                                    CodeGeneratorARMVIXL* codegen) {
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  vixl32::Register varhandle = InputRegisterAt(invoke, 0);
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+
+  if (expected_coordinates_count <= 1u) {
+    // For static fields, we need to fill the `target.object` with the declaring class,
+    // so we can use `target.object` as temporary for the `ArtMethod*`. For instance fields,
+    // we do not need the declaring class, so we can forget the `ArtMethod*` when
+    // we load the `target.offset`, so use the `target.offset` to hold the `ArtMethod*`.
+    vixl32::Register method = (expected_coordinates_count == 0) ? target.object : target.offset;
+
+    const MemberOffset art_field_offset = mirror::FieldVarHandle::ArtFieldOffset();
+    const MemberOffset offset_offset = ArtField::OffsetOffset();
+
+    // Load the ArtField, the offset and, if needed, declaring class.
+    __ Ldr(method, MemOperand(varhandle, art_field_offset.Int32Value()));
+    __ Ldr(target.offset, MemOperand(method, offset_offset.Int32Value()));
+    if (expected_coordinates_count == 0u) {
+      codegen->GenerateGcRootFieldLoad(invoke,
+                                       LocationFrom(target.object),
+                                       method,
+                                       ArtField::DeclaringClassOffset().Int32Value(),
+                                       kCompilerReadBarrierOption);
+    }
+  } else {
+    DCHECK_EQ(expected_coordinates_count, 2u);
+    DataType::Type value_type =
+        GetVarHandleExpectedValueType(invoke, /*expected_coordinates_count=*/ 2u);
+    uint32_t size_shift = DataType::SizeShift(value_type);
+    MemberOffset data_offset = mirror::Array::DataOffset(DataType::Size(value_type));
+
+    vixl32::Register index = InputRegisterAt(invoke, 2);
+    vixl32::Register shifted_index = index;
+    if (size_shift != 0u) {
+      shifted_index = target.offset;
+      __ Lsl(shifted_index, index, size_shift);
+    }
+    __ Add(target.offset, shifted_index, data_offset.Int32Value());
+  }
+}
+
+static bool HasVarHandleIntrinsicImplementation(HInvoke* invoke) {
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (expected_coordinates_count > 2u) {
+    // Invalid coordinate count. This invoke shall throw at runtime.
+    return false;
+  }
+  if (expected_coordinates_count != 0u &&
+      invoke->InputAt(1)->GetType() != DataType::Type::kReference) {
+    // Except for static fields (no coordinates), the first coordinate must be a reference.
+    return false;
+  }
+  if (expected_coordinates_count == 2u) {
+    // For arrays and views, the second coordinate must be convertible to `int`.
+    // In this context, `boolean` is not convertible but we have to look at the shorty
+    // as compiler transformations can give the invoke a valid boolean input.
+    DataType::Type index_type = GetDataTypeFromShorty(invoke, 2);
+    if (index_type == DataType::Type::kBool ||
+        DataType::Kind(index_type) != DataType::Type::kInt32) {
+      return false;
+    }
+  }
+
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  DataType::Type return_type = invoke->GetType();
+  mirror::VarHandle::AccessModeTemplate access_mode_template =
+      mirror::VarHandle::GetAccessModeTemplateByIntrinsic(invoke->GetIntrinsic());
+  switch (access_mode_template) {
+    case mirror::VarHandle::AccessModeTemplate::kGet:
+      // The return type should be the same as varType, so it shouldn't be void.
+      if (return_type == DataType::Type::kVoid) {
+        return false;
+      }
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kSet:
+      if (return_type != DataType::Type::kVoid) {
+        return false;
+      }
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndSet: {
+      if (return_type != DataType::Type::kBool) {
+        return false;
+      }
+      uint32_t expected_value_index = number_of_arguments - 2;
+      uint32_t new_value_index = number_of_arguments - 1;
+      DataType::Type expected_value_type = GetDataTypeFromShorty(invoke, expected_value_index);
+      DataType::Type new_value_type = GetDataTypeFromShorty(invoke, new_value_index);
+      if (expected_value_type != new_value_type) {
+        return false;
+      }
+      break;
+    }
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndExchange: {
+      uint32_t expected_value_index = number_of_arguments - 2;
+      uint32_t new_value_index = number_of_arguments - 1;
+      DataType::Type expected_value_type = GetDataTypeFromShorty(invoke, expected_value_index);
+      DataType::Type new_value_type = GetDataTypeFromShorty(invoke, new_value_index);
+      if (expected_value_type != new_value_type || return_type != expected_value_type) {
+        return false;
+      }
+      break;
+    }
+    case mirror::VarHandle::AccessModeTemplate::kGetAndUpdate: {
+      DataType::Type value_type = GetDataTypeFromShorty(invoke, number_of_arguments - 1);
+      if (IsVarHandleGetAndAdd(invoke) &&
+          (value_type == DataType::Type::kReference || value_type == DataType::Type::kBool)) {
+        // We should only add numerical types.
+        return false;
+      } else if (IsVarHandleGetAndBitwiseOp(invoke) && !DataType::IsIntegralType(value_type)) {
+        // We can only apply operators to bitwise integral types.
+        // Note that bitwise VarHandle operations accept a non-integral boolean type and
+        // perform the appropriate logical operation. However, the result is the same as
+        // using the bitwise operation on our boolean representation and this fits well
+        // with DataType::IsIntegralType() treating the compiler type kBool as integral.
+        return false;
+      }
+      if (value_type != return_type) {
+        return false;
+      }
+      break;
+    }
+  }
+
+  return true;
+}
+
+static LocationSummary* CreateVarHandleCommonLocations(HInvoke* invoke) {
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  DataType::Type return_type = invoke->GetType();
+
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations =
+      new (allocator) LocationSummary(invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->SetInAt(0, Location::RequiresRegister());
+  // Require coordinates in registers. These are the object holding the value
+  // to operate on (except for static fields) and index (for arrays and views).
+  for (size_t i = 0; i != expected_coordinates_count; ++i) {
+    locations->SetInAt(/* VarHandle object */ 1u + i, Location::RequiresRegister());
+  }
+  if (return_type != DataType::Type::kVoid) {
+    if (DataType::IsFloatingPointType(return_type)) {
+      locations->SetOut(Location::RequiresFpuRegister());
+    } else {
+      locations->SetOut(Location::RequiresRegister());
+    }
+  }
+  uint32_t arguments_start = /* VarHandle object */ 1u + expected_coordinates_count;
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  for (size_t arg_index = arguments_start; arg_index != number_of_arguments; ++arg_index) {
+    HInstruction* arg = invoke->InputAt(arg_index);
+    if (DataType::IsFloatingPointType(arg->GetType())) {
+      locations->SetInAt(arg_index, Location::RequiresFpuRegister());
+    } else {
+      locations->SetInAt(arg_index, Location::RequiresRegister());
+    }
+  }
+
+  // Add a temporary for offset.
+  if ((kEmitCompilerReadBarrier && !kUseBakerReadBarrier) &&
+      GetExpectedVarHandleCoordinatesCount(invoke) == 0u) {  // For static fields.
+    // To preserve the offset value across the non-Baker read barrier slow path
+    // for loading the declaring class, use a fixed callee-save register.
+    constexpr int first_callee_save = CTZ(kArmCalleeSaveRefSpills);
+    locations->AddTemp(Location::RegisterLocation(first_callee_save));
+  } else {
+    locations->AddTemp(Location::RequiresRegister());
+  }
+  if (expected_coordinates_count == 0u) {
+    // Add a temporary to hold the declaring class.
+    locations->AddTemp(Location::RequiresRegister());
+  }
+
+  return locations;
+}
+
+static void CreateVarHandleGetLocations(HInvoke* invoke,
+                                        CodeGeneratorARMVIXL* codegen,
+                                        bool atomic) {
+  if (!HasVarHandleIntrinsicImplementation(invoke)) {
+    return;
+  }
+
+  if ((kEmitCompilerReadBarrier && !kUseBakerReadBarrier) &&
+      invoke->GetType() == DataType::Type::kReference &&
+      invoke->GetIntrinsic() != Intrinsics::kVarHandleGet &&
+      invoke->GetIntrinsic() != Intrinsics::kVarHandleGetOpaque) {
+    // Unsupported for non-Baker read barrier because the artReadBarrierSlow() ignores
+    // the passed reference and reloads it from the field. This gets the memory visibility
+    // wrong for Acquire/Volatile operations. b/173104084
+    return;
+  }
+
+  LocationSummary* locations = CreateVarHandleCommonLocations(invoke);
+
+  DataType::Type type = invoke->GetType();
+  if (type == DataType::Type::kFloat64 && Use64BitExclusiveLoadStore(atomic, codegen)) {
+    // We need 3 temporaries for GenerateIntrinsicGet() but we can reuse the
+    // declaring class (if present) and offset temporary.
+    DCHECK_EQ(locations->GetTempCount(),
+              (GetExpectedVarHandleCoordinatesCount(invoke) == 0) ? 2u : 1u);
+    locations->AddRegisterTemps(3u - locations->GetTempCount());
+  }
+}
+
+static void GenerateVarHandleGet(HInvoke* invoke,
+                                 CodeGeneratorARMVIXL* codegen,
+                                 std::memory_order order,
+                                 bool atomic,
+                                 bool byte_swap = false) {
+  DataType::Type type = invoke->GetType();
+  DCHECK_NE(type, DataType::Type::kVoid);
+
+  LocationSummary* locations = invoke->GetLocations();
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  Location out = locations->Out();
+
+  VarHandleTarget target = GetVarHandleTarget(invoke);
+  VarHandleSlowPathARMVIXL* slow_path = nullptr;
+  if (!byte_swap) {
+    slow_path = GenerateVarHandleChecks(invoke, codegen, order, type);
+    slow_path->SetAtomic(atomic);
+    GenerateVarHandleTarget(invoke, target, codegen);
+    __ Bind(slow_path->GetNativeByteOrderLabel());
+  }
+
+  Location maybe_temp = Location::NoLocation();
+  Location maybe_temp2 = Location::NoLocation();
+  Location maybe_temp3 = Location::NoLocation();
+  if (kEmitCompilerReadBarrier && kUseBakerReadBarrier && type == DataType::Type::kReference) {
+    // Reuse the offset temporary.
+    maybe_temp = LocationFrom(target.offset);
+  } else if (DataType::Is64BitType(type) && Use64BitExclusiveLoadStore(atomic, codegen)) {
+    // Reuse the offset temporary and declaring class (if present).
+    // The address shall be constructed in the scratch register before they are clobbered.
+    maybe_temp = LocationFrom(target.offset);
+    DCHECK(maybe_temp.Equals(locations->GetTemp(0)));
+    if (type == DataType::Type::kFloat64) {
+      maybe_temp2 = locations->GetTemp(1);
+      maybe_temp3 = locations->GetTemp(2);
+    }
+  }
+
+  UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+  Location loaded_value = out;
+  DataType::Type load_type = type;
+  if (byte_swap) {
+    if (type == DataType::Type::kFloat64) {
+      if (Use64BitExclusiveLoadStore(atomic, codegen)) {
+        // Change load type to Int64 and promote `maybe_temp2` and `maybe_temp3` to `loaded_value`.
+        loaded_value = LocationFrom(RegisterFrom(maybe_temp2), RegisterFrom(maybe_temp3));
+        maybe_temp2 = Location::NoLocation();
+        maybe_temp3 = Location::NoLocation();
+      } else {
+        // Use the offset temporary and the scratch register.
+        loaded_value = LocationFrom(target.offset, temps.Acquire());
+      }
+      load_type = DataType::Type::kInt64;
+    } else if (type == DataType::Type::kFloat32) {
+      // Reuse the offset temporary.
+      loaded_value = LocationFrom(target.offset);
+      load_type = DataType::Type::kInt32;
+    } else if (type == DataType::Type::kInt64) {
+      // Swap the high and low registers and reverse the bytes in each after the load.
+      loaded_value = LocationFrom(HighRegisterFrom(out), LowRegisterFrom(out));
+    }
+  }
+
+  GenerateIntrinsicGet(invoke,
+                       codegen,
+                       load_type,
+                       order,
+                       atomic,
+                       target.object,
+                       target.offset,
+                       loaded_value,
+                       maybe_temp,
+                       maybe_temp2,
+                       maybe_temp3);
+  if (byte_swap) {
+    if (type == DataType::Type::kInt64) {
+      GenerateReverseBytesInPlaceForEachWord(assembler, loaded_value);
+    } else {
+      GenerateReverseBytes(assembler, type, loaded_value, out);
+    }
+  }
+
+  if (!byte_swap) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGet(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke, codegen_, /*atomic=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGet(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_, std::memory_order_relaxed, /*atomic=*/ false);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetOpaque(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke, codegen_, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetOpaque(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_, std::memory_order_relaxed, /*atomic=*/ true);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAcquire(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke, codegen_, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAcquire(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_, std::memory_order_acquire, /*atomic=*/ true);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetVolatile(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke, codegen_, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetVolatile(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_, std::memory_order_seq_cst, /*atomic=*/ true);
+}
+
+static void CreateVarHandleSetLocations(HInvoke* invoke,
+                                        CodeGeneratorARMVIXL* codegen,
+                                        bool atomic) {
+  if (!HasVarHandleIntrinsicImplementation(invoke)) {
+    return;
+  }
+
+  LocationSummary* locations = CreateVarHandleCommonLocations(invoke);
+
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, number_of_arguments - 1u);
+  if (DataType::Is64BitType(value_type)) {
+    size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+    DCHECK_EQ(locations->GetTempCount(), (expected_coordinates_count == 0) ? 2u : 1u);
+    HInstruction* arg = invoke->InputAt(number_of_arguments - 1u);
+    bool has_reverse_bytes_slow_path =
+        (expected_coordinates_count == 2u) &&
+        !(arg->IsConstant() && arg->AsConstant()->IsZeroBitPattern());
+    if (Use64BitExclusiveLoadStore(atomic, codegen)) {
+      // We need 4 temporaries in the byte array view slow path. Otherwise, we need
+      // 2 or 3 temporaries for GenerateIntrinsicSet() depending on the value type.
+      // We can reuse the offset temporary and declaring class (if present).
+      size_t temps_needed = has_reverse_bytes_slow_path
+          ? 4u
+          : ((value_type == DataType::Type::kFloat64) ? 3u : 2u);
+      locations->AddRegisterTemps(temps_needed - locations->GetTempCount());
+    } else if (has_reverse_bytes_slow_path) {
+      // We need 2 temps for the value with reversed bytes in the byte array view slow path.
+      // We can reuse the offset temporary.
+      DCHECK_EQ(locations->GetTempCount(), 1u);
+      locations->AddTemp(Location::RequiresRegister());
+    }
+  }
+}
+
+static void GenerateVarHandleSet(HInvoke* invoke,
+                                 CodeGeneratorARMVIXL* codegen,
+                                 std::memory_order order,
+                                 bool atomic,
+                                 bool byte_swap = false) {
+  uint32_t value_index = invoke->GetNumberOfArguments() - 1;
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, value_index);
+
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  Location value = locations->InAt(value_index);
+
+  VarHandleTarget target = GetVarHandleTarget(invoke);
+  VarHandleSlowPathARMVIXL* slow_path = nullptr;
+  if (!byte_swap) {
+    slow_path = GenerateVarHandleChecks(invoke, codegen, order, value_type);
+    slow_path->SetAtomic(atomic);
+    GenerateVarHandleTarget(invoke, target, codegen);
+    __ Bind(slow_path->GetNativeByteOrderLabel());
+  }
+
+  Location maybe_temp = Location::NoLocation();
+  Location maybe_temp2 = Location::NoLocation();
+  Location maybe_temp3 = Location::NoLocation();
+  if (DataType::Is64BitType(value_type) && Use64BitExclusiveLoadStore(atomic, codegen)) {
+    // Reuse the offset temporary and declaring class (if present).
+    // The address shall be constructed in the scratch register before they are clobbered.
+    maybe_temp = locations->GetTemp(0);
+    maybe_temp2 = locations->GetTemp(1);
+    if (value_type == DataType::Type::kFloat64) {
+      maybe_temp3 = locations->GetTemp(2);
+    }
+  }
+
+  UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+  if (byte_swap) {
+    if (DataType::Is64BitType(value_type) || value_type == DataType::Type::kFloat32) {
+      // Calculate the address in scratch register, so that we can use the offset temporary.
+      vixl32::Register base = temps.Acquire();
+      __ Add(base, target.object, target.offset);
+      target.object = base;
+      target.offset = vixl32::Register();
+    }
+    Location original_value = value;
+    if (DataType::Is64BitType(value_type)) {
+      size_t temp_start = 0u;
+      if (Use64BitExclusiveLoadStore(atomic, codegen)) {
+        // Clear `maybe_temp3` which was initialized above for Float64.
+        DCHECK(value_type != DataType::Type::kFloat64 || maybe_temp3.Equals(locations->GetTemp(2)));
+        maybe_temp3 = Location::NoLocation();
+        temp_start = 2u;
+      }
+      value = LocationFrom(RegisterFrom(locations->GetTemp(temp_start)),
+                           RegisterFrom(locations->GetTemp(temp_start + 1u)));
+      if (value_type == DataType::Type::kFloat64) {
+        __ Vmov(HighRegisterFrom(value), LowRegisterFrom(value), DRegisterFrom(original_value));
+        GenerateReverseBytesInPlaceForEachWord(assembler, value);
+        value_type = DataType::Type::kInt64;
+      } else {
+        GenerateReverseBytes(assembler, value_type, original_value, value);
+      }
+    } else if (value_type == DataType::Type::kFloat32) {
+      value = locations->GetTemp(0);  // Use the offset temporary which was freed above.
+      __ Vmov(RegisterFrom(value), SRegisterFrom(original_value));
+      GenerateReverseBytes(assembler, DataType::Type::kInt32, value, value);
+      value_type = DataType::Type::kInt32;
+    } else {
+      value = LocationFrom(temps.Acquire());
+      GenerateReverseBytes(assembler, value_type, original_value, value);
+    }
+  }
+
+  GenerateIntrinsicSet(codegen,
+                       value_type,
+                       order,
+                       atomic,
+                       target.object,
+                       target.offset,
+                       value,
+                       maybe_temp,
+                       maybe_temp2,
+                       maybe_temp3);
+
+  if (CodeGenerator::StoreNeedsWriteBarrier(value_type, invoke->InputAt(value_index))) {
+    // Reuse the offset temporary for MarkGCCard.
+    vixl32::Register temp = target.offset;
+    vixl32::Register card = temps.Acquire();
+    vixl32::Register value_reg = RegisterFrom(value);
+    codegen->MarkGCCard(temp, card, target.object, value_reg, /*value_can_be_null=*/ true);
+  }
+
+  if (!byte_swap) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleSet(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke, codegen_, /*atomic=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleSet(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_, std::memory_order_relaxed, /*atomic=*/ false);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleSetOpaque(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke, codegen_, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleSetOpaque(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_, std::memory_order_relaxed, /*atomic=*/ true);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleSetRelease(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke, codegen_, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleSetRelease(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_, std::memory_order_release, /*atomic=*/ true);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleSetVolatile(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke, codegen_, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleSetVolatile(HInvoke* invoke) {
+  // ARM store-release instructions are implicitly sequentially consistent.
+  GenerateVarHandleSet(invoke, codegen_, std::memory_order_seq_cst, /*atomic=*/ true);
+}
+
+static void CreateVarHandleCompareAndSetOrExchangeLocations(HInvoke* invoke, bool return_success) {
+  if (!HasVarHandleIntrinsicImplementation(invoke)) {
+    return;
+  }
+
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, number_of_arguments - 1u);
+  if ((kEmitCompilerReadBarrier && !kUseBakerReadBarrier) &&
+      value_type == DataType::Type::kReference) {
+    // Unsupported for non-Baker read barrier because the artReadBarrierSlow() ignores
+    // the passed reference and reloads it from the field. This breaks the read barriers
+    // in slow path in different ways. The marked old value may not actually be a to-space
+    // reference to the same object as `old_value`, breaking slow path assumptions. And
+    // for CompareAndExchange, marking the old value after comparison failure may actually
+    // return the reference to `expected`, erroneously indicating success even though we
+    // did not set the new value. (And it also gets the memory visibility wrong.) b/173104084
+    return;
+  }
+
+  LocationSummary* locations = CreateVarHandleCommonLocations(invoke);
+
+  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+    // We need callee-save registers for both the class object and offset instead of
+    // the temporaries reserved in CreateVarHandleCommonLocations().
+    static_assert(POPCOUNT(kArmCalleeSaveRefSpills) >= 2u);
+    constexpr int first_callee_save = CTZ(kArmCalleeSaveRefSpills);
+    constexpr int second_callee_save = CTZ(kArmCalleeSaveRefSpills ^ (1u << first_callee_save));
+    if (GetExpectedVarHandleCoordinatesCount(invoke) == 0u) {  // For static fields.
+      DCHECK_EQ(locations->GetTempCount(), 2u);
+      DCHECK(locations->GetTemp(0u).Equals(Location::RequiresRegister()));
+      DCHECK(locations->GetTemp(1u).Equals(Location::RegisterLocation(first_callee_save)));
+      locations->SetTempAt(0u, Location::RegisterLocation(second_callee_save));
+    } else {
+      DCHECK_EQ(locations->GetTempCount(), 1u);
+      DCHECK(locations->GetTemp(0u).Equals(Location::RequiresRegister()));
+      locations->SetTempAt(0u, Location::RegisterLocation(first_callee_save));
+    }
+  }
+
+  if (DataType::IsFloatingPointType(value_type)) {
+    // We can reuse the declaring class (if present) and offset temporary.
+    DCHECK_EQ(locations->GetTempCount(),
+              (GetExpectedVarHandleCoordinatesCount(invoke) == 0) ? 2u : 1u);
+    size_t temps_needed = (value_type == DataType::Type::kFloat64)
+        ? (return_success ? 5u : 7u)
+        : (return_success ? 3u : 4u);
+    locations->AddRegisterTemps(temps_needed - locations->GetTempCount());
+  } else if (GetExpectedVarHandleCoordinatesCount(invoke) == 2u) {
+    // Add temps for the byte-reversed `expected` and `new_value` in the byte array view slow path.
+    DCHECK_EQ(locations->GetTempCount(), 1u);
+    if (value_type == DataType::Type::kInt64) {
+      // We would ideally add 4 temps for Int64 but that would simply run out of registers,
+      // so we instead need to reverse bytes in actual arguments and undo it at the end.
+    } else {
+      locations->AddRegisterTemps(2u);
+    }
+  }
+  if (kEmitCompilerReadBarrier && value_type == DataType::Type::kReference) {
+    // Add a temporary for store result, also used for the `old_value_temp` in slow path.
+    locations->AddTemp(Location::RequiresRegister());
+  }
+}
+
+static void GenerateVarHandleCompareAndSetOrExchange(HInvoke* invoke,
+                                                     CodeGeneratorARMVIXL* codegen,
+                                                     std::memory_order order,
+                                                     bool return_success,
+                                                     bool strong,
+                                                     bool byte_swap = false) {
+  DCHECK(return_success || strong);
+
+  uint32_t expected_index = invoke->GetNumberOfArguments() - 2;
+  uint32_t new_value_index = invoke->GetNumberOfArguments() - 1;
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, new_value_index);
+  DCHECK_EQ(value_type, GetDataTypeFromShorty(invoke, expected_index));
+
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  Location expected = locations->InAt(expected_index);
+  Location new_value = locations->InAt(new_value_index);
+  Location out = locations->Out();
+
+  VarHandleTarget target = GetVarHandleTarget(invoke);
+  VarHandleSlowPathARMVIXL* slow_path = nullptr;
+  if (!byte_swap) {
+    slow_path = GenerateVarHandleChecks(invoke, codegen, order, value_type);
+    slow_path->SetCompareAndSetOrExchangeArgs(return_success, strong);
+    GenerateVarHandleTarget(invoke, target, codegen);
+    __ Bind(slow_path->GetNativeByteOrderLabel());
+  }
+
+  bool seq_cst_barrier = (order == std::memory_order_seq_cst);
+  bool release_barrier = seq_cst_barrier || (order == std::memory_order_release);
+  bool acquire_barrier = seq_cst_barrier || (order == std::memory_order_acquire);
+  DCHECK(release_barrier || acquire_barrier || order == std::memory_order_relaxed);
+
+  if (release_barrier) {
+    codegen->GenerateMemoryBarrier(
+        seq_cst_barrier ? MemBarrierKind::kAnyAny : MemBarrierKind::kAnyStore);
+  }
+
+  // Calculate the pointer to the value.
+  UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+  vixl32::Register tmp_ptr = temps.Acquire();
+  __ Add(tmp_ptr, target.object, target.offset);
+
+  // Move floating point values to temporaries and prepare output registers.
+  // Note that float/double CAS uses bitwise comparison, rather than the operator==.
+  // Reuse the declaring class (if present) and offset temporary for non-reference types,
+  // the address has already been constructed in the scratch register. We are more careful
+  // for references due to read and write barrier, see below.
+  Location old_value;
+  vixl32::Register store_result;
+  vixl32::Register success = return_success ? RegisterFrom(out) : vixl32::Register();
+  DataType::Type cas_type = value_type;
+  if (value_type == DataType::Type::kFloat64) {
+    vixl32::DRegister expected_vreg = DRegisterFrom(expected);
+    vixl32::DRegister new_value_vreg = DRegisterFrom(new_value);
+    expected =
+        LocationFrom(RegisterFrom(locations->GetTemp(0)), RegisterFrom(locations->GetTemp(1)));
+    new_value =
+        LocationFrom(RegisterFrom(locations->GetTemp(2)), RegisterFrom(locations->GetTemp(3)));
+    store_result = RegisterFrom(locations->GetTemp(4));
+    old_value = return_success
+        ? LocationFrom(success, store_result)
+        : LocationFrom(RegisterFrom(locations->GetTemp(5)), RegisterFrom(locations->GetTemp(6)));
+    if (byte_swap) {
+      __ Vmov(HighRegisterFrom(expected), LowRegisterFrom(expected), expected_vreg);
+      __ Vmov(HighRegisterFrom(new_value), LowRegisterFrom(new_value), new_value_vreg);
+      GenerateReverseBytesInPlaceForEachWord(assembler, expected);
+      GenerateReverseBytesInPlaceForEachWord(assembler, new_value);
+    } else {
+      __ Vmov(LowRegisterFrom(expected), HighRegisterFrom(expected), expected_vreg);
+      __ Vmov(LowRegisterFrom(new_value), HighRegisterFrom(new_value), new_value_vreg);
+    }
+    cas_type = DataType::Type::kInt64;
+  } else if (value_type == DataType::Type::kFloat32) {
+    vixl32::SRegister expected_vreg = SRegisterFrom(expected);
+    vixl32::SRegister new_value_vreg = SRegisterFrom(new_value);
+    expected = locations->GetTemp(0);
+    new_value = locations->GetTemp(1);
+    store_result = RegisterFrom(locations->GetTemp(2));
+    old_value = return_success ? LocationFrom(store_result) : locations->GetTemp(3);
+    __ Vmov(RegisterFrom(expected), expected_vreg);
+    __ Vmov(RegisterFrom(new_value), new_value_vreg);
+    if (byte_swap) {
+      GenerateReverseBytes(assembler, DataType::Type::kInt32, expected, expected);
+      GenerateReverseBytes(assembler, DataType::Type::kInt32, new_value, new_value);
+    }
+    cas_type = DataType::Type::kInt32;
+  } else if (value_type == DataType::Type::kInt64) {
+    store_result = RegisterFrom(locations->GetTemp(0));
+    old_value = return_success
+        ? LocationFrom(success, store_result)
+        // If swapping bytes, swap the high/low regs and reverse the bytes in each after the load.
+        : byte_swap ? LocationFrom(HighRegisterFrom(out), LowRegisterFrom(out)) : out;
+    if (byte_swap) {
+      // Due to lack of registers, reverse bytes in `expected` and `new_value` and undo that later.
+      GenerateReverseBytesInPlaceForEachWord(assembler, expected);
+      expected = LocationFrom(HighRegisterFrom(expected), LowRegisterFrom(expected));
+      GenerateReverseBytesInPlaceForEachWord(assembler, new_value);
+      new_value = LocationFrom(HighRegisterFrom(new_value), LowRegisterFrom(new_value));
+    }
+  } else {
+    // Use the last temp. For references with read barriers, this is an extra temporary
+    // allocated to avoid overwriting the temporaries for declaring class (if present)
+    // and offset as they are needed in the slow path. Otherwise, this is the offset
+    // temporary which also works for references without read barriers that need the
+    // object register preserved for the write barrier.
+    store_result = RegisterFrom(locations->GetTemp(locations->GetTempCount() - 1u));
+    old_value = return_success ? LocationFrom(store_result) : out;
+    if (byte_swap) {
+      DCHECK_EQ(locations->GetTempCount(), 3u);
+      Location original_expected = expected;
+      Location original_new_value = new_value;
+      expected = locations->GetTemp(0);
+      new_value = locations->GetTemp(1);
+      GenerateReverseBytes(assembler, value_type, original_expected, expected);
+      GenerateReverseBytes(assembler, value_type, original_new_value, new_value);
+    }
+  }
+
+  vixl32::Label exit_loop_label;
+  vixl32::Label* exit_loop = &exit_loop_label;
+  vixl32::Label* cmp_failure = &exit_loop_label;
+
+  if (kEmitCompilerReadBarrier && value_type == DataType::Type::kReference) {
+    // The `old_value_temp` is used first for the marked `old_value` and then for the unmarked
+    // reloaded old value for subsequent CAS in the slow path.
+    vixl32::Register old_value_temp = store_result;
+    ReadBarrierCasSlowPathARMVIXL* rb_slow_path =
+        new (codegen->GetScopedAllocator()) ReadBarrierCasSlowPathARMVIXL(
+            invoke,
+            strong,
+            target.object,
+            target.offset,
+            RegisterFrom(expected),
+            RegisterFrom(new_value),
+            RegisterFrom(old_value),
+            old_value_temp,
+            store_result,
+            success,
+            codegen);
+    codegen->AddSlowPath(rb_slow_path);
+    exit_loop = rb_slow_path->GetExitLabel();
+    cmp_failure = rb_slow_path->GetEntryLabel();
+  }
+
+  GenerateCompareAndSet(codegen,
+                        cas_type,
+                        strong,
+                        cmp_failure,
+                        /*cmp_failure_is_far_target=*/ cmp_failure != &exit_loop_label,
+                        tmp_ptr,
+                        expected,
+                        new_value,
+                        old_value,
+                        store_result,
+                        success);
+  __ Bind(exit_loop);
+
+  if (acquire_barrier) {
+    codegen->GenerateMemoryBarrier(
+        seq_cst_barrier ? MemBarrierKind::kAnyAny : MemBarrierKind::kLoadAny);
+  }
+
+  if (!return_success) {
+    if (byte_swap) {
+      if (value_type == DataType::Type::kInt64) {
+        GenerateReverseBytesInPlaceForEachWord(assembler, old_value);
+        // Undo byte swapping in `expected` and `new_value`. We do not have the
+        // information whether the value in these registers shall be needed later.
+        GenerateReverseBytesInPlaceForEachWord(assembler, expected);
+        GenerateReverseBytesInPlaceForEachWord(assembler, new_value);
+      } else {
+        GenerateReverseBytes(assembler, value_type, old_value, out);
+      }
+    } else if (value_type == DataType::Type::kFloat64) {
+      __ Vmov(DRegisterFrom(out), LowRegisterFrom(old_value), HighRegisterFrom(old_value));
+    } else if (value_type == DataType::Type::kFloat32) {
+      __ Vmov(SRegisterFrom(out), RegisterFrom(old_value));
+    }
+  }
+
+  if (CodeGenerator::StoreNeedsWriteBarrier(value_type, invoke->InputAt(new_value_index))) {
+    // Reuse the offset temporary and scratch register for MarkGCCard.
+    vixl32::Register temp = target.offset;
+    vixl32::Register card = tmp_ptr;
+    // Mark card for object assuming new value is stored.
+    bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(temp, card, target.object, RegisterFrom(new_value), new_value_can_be_null);
+  }
+
+  if (!byte_swap) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleCompareAndExchange(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleCompareAndExchange(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_seq_cst, /*return_success=*/ false, /*strong=*/ true);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleCompareAndExchangeAcquire(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleCompareAndExchangeAcquire(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_acquire, /*return_success=*/ false, /*strong=*/ true);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleCompareAndExchangeRelease(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ false);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleCompareAndExchangeRelease(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_release, /*return_success=*/ false, /*strong=*/ true);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleCompareAndSet(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleCompareAndSet(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_seq_cst, /*return_success=*/ true, /*strong=*/ true);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleWeakCompareAndSet(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleWeakCompareAndSet(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_seq_cst, /*return_success=*/ true, /*strong=*/ false);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleWeakCompareAndSetAcquire(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleWeakCompareAndSetAcquire(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_acquire, /*return_success=*/ true, /*strong=*/ false);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleWeakCompareAndSetPlain(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleWeakCompareAndSetPlain(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_relaxed, /*return_success=*/ true, /*strong=*/ false);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleWeakCompareAndSetRelease(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke, /*return_success=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleWeakCompareAndSetRelease(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(
+      invoke, codegen_, std::memory_order_release, /*return_success=*/ true, /*strong=*/ false);
+}
+
+static void CreateVarHandleGetAndUpdateLocations(HInvoke* invoke,
+                                                 GetAndUpdateOp get_and_update_op) {
+  if (!HasVarHandleIntrinsicImplementation(invoke)) {
+    return;
+  }
+
+  if ((kEmitCompilerReadBarrier && !kUseBakerReadBarrier) &&
+      invoke->GetType() == DataType::Type::kReference) {
+    // Unsupported for non-Baker read barrier because the artReadBarrierSlow() ignores
+    // the passed reference and reloads it from the field, thus seeing the new value
+    // that we have just stored. (And it also gets the memory visibility wrong.) b/173104084
+    return;
+  }
+
+  LocationSummary* locations = CreateVarHandleCommonLocations(invoke);
+
+  // We can reuse the declaring class (if present) and offset temporary, except for
+  // non-Baker read barriers that need them for the slow path.
+  DCHECK_EQ(locations->GetTempCount(),
+            (GetExpectedVarHandleCoordinatesCount(invoke) == 0) ? 2u : 1u);
+
+  DataType::Type value_type = invoke->GetType();
+  if (get_and_update_op == GetAndUpdateOp::kSet) {
+    if (DataType::IsFloatingPointType(value_type)) {
+      // Add temps needed to do the GenerateGetAndUpdate() with core registers.
+      size_t temps_needed = (value_type == DataType::Type::kFloat64) ? 5u : 3u;
+      locations->AddRegisterTemps(temps_needed - locations->GetTempCount());
+    } else if ((kEmitCompilerReadBarrier && !kUseBakerReadBarrier) &&
+               value_type == DataType::Type::kReference) {
+      // We need to preserve the declaring class (if present) and offset for read barrier
+      // slow paths, so we must use a separate temporary for the exclusive store result.
+      locations->AddTemp(Location::RequiresRegister());
+    } else if (GetExpectedVarHandleCoordinatesCount(invoke) == 2u) {
+      // Add temps for the byte-reversed `arg` in the byte array view slow path.
+      DCHECK_EQ(locations->GetTempCount(), 1u);
+      locations->AddRegisterTemps((value_type == DataType::Type::kInt64) ? 2u : 1u);
+    }
+  } else {
+    // We need temporaries for the new value and exclusive store result.
+    size_t temps_needed = DataType::Is64BitType(value_type) ? 3u : 2u;
+    if (get_and_update_op != GetAndUpdateOp::kAdd &&
+        GetExpectedVarHandleCoordinatesCount(invoke) == 2u) {
+      // Add temps for the byte-reversed `arg` in the byte array view slow path.
+      if (value_type == DataType::Type::kInt64) {
+        // We would ideally add 2 temps for Int64 but that would simply run out of registers,
+        // so we instead need to reverse bytes in the actual argument and undo it at the end.
+      } else {
+        temps_needed += 1u;
+      }
+    }
+    locations->AddRegisterTemps(temps_needed - locations->GetTempCount());
+    if (DataType::IsFloatingPointType(value_type)) {
+      // Note: This shall allocate a D register. There is no way to request an S register.
+      locations->AddTemp(Location::RequiresFpuRegister());
+    }
+  }
+}
+
+static void GenerateVarHandleGetAndUpdate(HInvoke* invoke,
+                                          CodeGeneratorARMVIXL* codegen,
+                                          GetAndUpdateOp get_and_update_op,
+                                          std::memory_order order,
+                                          bool byte_swap = false) {
+  uint32_t arg_index = invoke->GetNumberOfArguments() - 1;
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, arg_index);
+
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  Location arg = locations->InAt(arg_index);
+  Location out = locations->Out();
+
+  VarHandleTarget target = GetVarHandleTarget(invoke);
+  VarHandleSlowPathARMVIXL* slow_path = nullptr;
+  if (!byte_swap) {
+    slow_path = GenerateVarHandleChecks(invoke, codegen, order, value_type);
+    slow_path->SetGetAndUpdateOp(get_and_update_op);
+    GenerateVarHandleTarget(invoke, target, codegen);
+    __ Bind(slow_path->GetNativeByteOrderLabel());
+  }
+
+  bool seq_cst_barrier = (order == std::memory_order_seq_cst);
+  bool release_barrier = seq_cst_barrier || (order == std::memory_order_release);
+  bool acquire_barrier = seq_cst_barrier || (order == std::memory_order_acquire);
+  DCHECK(release_barrier || acquire_barrier || order == std::memory_order_relaxed);
+
+  if (release_barrier) {
+    codegen->GenerateMemoryBarrier(
+        seq_cst_barrier ? MemBarrierKind::kAnyAny : MemBarrierKind::kAnyStore);
+  }
+
+  // Use the scratch register for the pointer to the target location.
+  UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+  vixl32::Register tmp_ptr = temps.Acquire();
+  __ Add(tmp_ptr, target.object, target.offset);
+
+  // Use the offset temporary for the exclusive store result.
+  vixl32::Register store_result = target.offset;
+
+  // The load/store type is never floating point.
+  DataType::Type load_store_type = DataType::IsFloatingPointType(value_type)
+      ? ((value_type == DataType::Type::kFloat32) ? DataType::Type::kInt32 : DataType::Type::kInt64)
+      : value_type;
+
+  // Prepare register for old value and temporaries if any.
+  Location old_value = out;
+  Location maybe_temp = Location::NoLocation();
+  Location maybe_vreg_temp = Location::NoLocation();
+  if (get_and_update_op == GetAndUpdateOp::kSet) {
+    // For floating point GetAndSet, do the GenerateGetAndUpdate() with core registers,
+    // rather than moving between core and FP registers in the loop.
+    if (value_type == DataType::Type::kFloat64) {
+      vixl32::DRegister arg_vreg = DRegisterFrom(arg);
+      DCHECK_EQ(locations->GetTempCount(), 5u);  // `store_result` and the four here.
+      old_value =
+          LocationFrom(RegisterFrom(locations->GetTemp(1)), RegisterFrom(locations->GetTemp(2)));
+      arg = LocationFrom(RegisterFrom(locations->GetTemp(3)), RegisterFrom(locations->GetTemp(4)));
+      if (byte_swap) {
+        __ Vmov(HighRegisterFrom(arg), LowRegisterFrom(arg), arg_vreg);
+        GenerateReverseBytesInPlaceForEachWord(assembler, arg);
+      } else {
+        __ Vmov(LowRegisterFrom(arg), HighRegisterFrom(arg), arg_vreg);
+      }
+    } else if (value_type == DataType::Type::kFloat32) {
+      vixl32::SRegister arg_vreg = SRegisterFrom(arg);
+      DCHECK_EQ(locations->GetTempCount(), 3u);  // `store_result` and the two here.
+      old_value = locations->GetTemp(1);
+      arg = locations->GetTemp(2);
+      __ Vmov(RegisterFrom(arg), arg_vreg);
+      if (byte_swap) {
+        GenerateReverseBytes(assembler, DataType::Type::kInt32, arg, arg);
+      }
+    } else if (kEmitCompilerReadBarrier && value_type == DataType::Type::kReference) {
+      if (kUseBakerReadBarrier) {
+        // Load the old value initially to a temporary register.
+        // We shall move it to `out` later with a read barrier.
+        old_value = LocationFrom(store_result);
+        store_result = RegisterFrom(out);  // Use the `out` for the exclusive store result.
+      } else {
+        // The store_result is a separate temporary.
+        DCHECK(!store_result.Is(target.object));
+        DCHECK(!store_result.Is(target.offset));
+      }
+    } else if (byte_swap) {
+      Location original_arg = arg;
+      arg = locations->GetTemp(1);
+      if (value_type == DataType::Type::kInt64) {
+        arg = LocationFrom(RegisterFrom(arg), RegisterFrom(locations->GetTemp(2)));
+        // Swap the high/low regs and reverse the bytes in each after the load.
+        old_value = LocationFrom(HighRegisterFrom(out), LowRegisterFrom(out));
+      }
+      GenerateReverseBytes(assembler, value_type, original_arg, arg);
+    }
+  } else {
+    maybe_temp = DataType::Is64BitType(value_type)
+        ? LocationFrom(RegisterFrom(locations->GetTemp(1)), RegisterFrom(locations->GetTemp(2)))
+        : locations->GetTemp(1);
+    DCHECK(!maybe_temp.Contains(LocationFrom(store_result)));
+    if (DataType::IsFloatingPointType(value_type)) {
+      maybe_vreg_temp = locations->GetTemp(locations->GetTempCount() - 1u);
+      DCHECK(maybe_vreg_temp.IsFpuRegisterPair());
+    }
+    if (byte_swap) {
+      if (get_and_update_op == GetAndUpdateOp::kAdd) {
+        // We need to do the byte swapping in the CAS loop for GetAndAdd.
+        get_and_update_op = GetAndUpdateOp::kAddWithByteSwap;
+      } else if (value_type == DataType::Type::kInt64) {
+        // Swap the high/low regs and reverse the bytes in each after the load.
+        old_value = LocationFrom(HighRegisterFrom(out), LowRegisterFrom(out));
+        // Due to lack of registers, reverse bytes in `arg` and undo that later.
+        GenerateReverseBytesInPlaceForEachWord(assembler, arg);
+        arg = LocationFrom(HighRegisterFrom(arg), LowRegisterFrom(arg));
+      } else {
+        DCHECK(!DataType::IsFloatingPointType(value_type));
+        Location original_arg = arg;
+        arg = locations->GetTemp(2);
+        DCHECK(!arg.Contains(LocationFrom(store_result)));
+        GenerateReverseBytes(assembler, value_type, original_arg, arg);
+      }
+    }
+  }
+
+  GenerateGetAndUpdate(codegen,
+                       get_and_update_op,
+                       load_store_type,
+                       tmp_ptr,
+                       arg,
+                       old_value,
+                       store_result,
+                       maybe_temp,
+                       maybe_vreg_temp);
+
+  if (acquire_barrier) {
+    codegen->GenerateMemoryBarrier(
+        seq_cst_barrier ? MemBarrierKind::kAnyAny : MemBarrierKind::kLoadAny);
+  }
+
+  if (byte_swap && get_and_update_op != GetAndUpdateOp::kAddWithByteSwap) {
+    if (value_type == DataType::Type::kInt64) {
+      GenerateReverseBytesInPlaceForEachWord(assembler, old_value);
+      if (get_and_update_op != GetAndUpdateOp::kSet) {
+        // Undo byte swapping in `arg`. We do not have the information
+        // whether the value in these registers shall be needed later.
+        GenerateReverseBytesInPlaceForEachWord(assembler, arg);
+      }
+    } else {
+      GenerateReverseBytes(assembler, value_type, old_value, out);
+    }
+  } else if (get_and_update_op == GetAndUpdateOp::kSet &&
+             DataType::IsFloatingPointType(value_type)) {
+    if (value_type == DataType::Type::kFloat64) {
+      __ Vmov(DRegisterFrom(out), LowRegisterFrom(old_value), HighRegisterFrom(old_value));
+    } else {
+      __ Vmov(SRegisterFrom(out), RegisterFrom(old_value));
+    }
+  } else if (kEmitCompilerReadBarrier && value_type == DataType::Type::kReference) {
+    if (kUseBakerReadBarrier) {
+      codegen->GenerateIntrinsicCasMoveWithBakerReadBarrier(RegisterFrom(out),
+                                                            RegisterFrom(old_value));
+    } else {
+      codegen->GenerateReadBarrierSlow(
+          invoke,
+          Location::RegisterLocation(RegisterFrom(out).GetCode()),
+          Location::RegisterLocation(RegisterFrom(old_value).GetCode()),
+          Location::RegisterLocation(target.object.GetCode()),
+          /*offset=*/ 0u,
+          /*index=*/ Location::RegisterLocation(target.offset.GetCode()));
+    }
+  }
+
+  if (CodeGenerator::StoreNeedsWriteBarrier(value_type, invoke->InputAt(arg_index))) {
+    // Reuse the offset temporary and scratch register for MarkGCCard.
+    vixl32::Register temp = target.offset;
+    vixl32::Register card = tmp_ptr;
+    // Mark card for object assuming new value is stored.
+    bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(temp, card, target.object, RegisterFrom(arg), new_value_can_be_null);
+  }
+
+  if (!byte_swap) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndSet(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kSet);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndSet(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kSet, std::memory_order_seq_cst);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndSetAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kSet);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndSetAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kSet, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndSetRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kSet);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndSetRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kSet, std::memory_order_release);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndAdd(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAdd);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndAdd(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAdd, std::memory_order_seq_cst);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndAddAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAdd);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndAddAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAdd, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndAddRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAdd);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndAddRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAdd, std::memory_order_release);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndBitwiseAnd(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAnd);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndBitwiseAnd(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAnd, std::memory_order_seq_cst);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndBitwiseAndAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAnd);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndBitwiseAndAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAnd, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndBitwiseAndRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kAnd);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndBitwiseAndRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kAnd, std::memory_order_release);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndBitwiseOr(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kOr);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndBitwiseOr(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kOr, std::memory_order_seq_cst);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndBitwiseOrAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kOr);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndBitwiseOrAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kOr, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndBitwiseOrRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kOr);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndBitwiseOrRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kOr, std::memory_order_release);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndBitwiseXor(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kXor);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndBitwiseXor(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kXor, std::memory_order_seq_cst);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndBitwiseXorAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kXor);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndBitwiseXorAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kXor, std::memory_order_acquire);
+}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitVarHandleGetAndBitwiseXorRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndUpdateLocations(invoke, GetAndUpdateOp::kXor);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitVarHandleGetAndBitwiseXorRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndUpdate(invoke, codegen_, GetAndUpdateOp::kXor, std::memory_order_release);
+}
+
+void VarHandleSlowPathARMVIXL::EmitByteArrayViewCode(CodeGenerator* codegen_in) {
+  DCHECK(GetByteArrayViewCheckLabel()->IsReferenced());
+  CodeGeneratorARMVIXL* codegen = down_cast<CodeGeneratorARMVIXL*>(codegen_in);
+  ArmVIXLAssembler* assembler = codegen->GetAssembler();
+  HInvoke* invoke = GetInvoke();
+  mirror::VarHandle::AccessModeTemplate access_mode_template = GetAccessModeTemplate();
+  DataType::Type value_type =
+      GetVarHandleExpectedValueType(invoke, /*expected_coordinates_count=*/ 2u);
+  DCHECK_NE(value_type, DataType::Type::kReference);
+  size_t size = DataType::Size(value_type);
+  DCHECK_GT(size, 1u);
+  vixl32::Operand size_operand(dchecked_integral_cast<int32_t>(size));
+  vixl32::Register varhandle = InputRegisterAt(invoke, 0);
+  vixl32::Register object = InputRegisterAt(invoke, 1);
+  vixl32::Register index = InputRegisterAt(invoke, 2);
+
+  MemberOffset class_offset = mirror::Object::ClassOffset();
+  MemberOffset array_length_offset = mirror::Array::LengthOffset();
+  MemberOffset data_offset = mirror::Array::DataOffset(Primitive::kPrimByte);
+  MemberOffset native_byte_order_offset = mirror::ByteArrayViewVarHandle::NativeByteOrderOffset();
+
+  __ Bind(GetByteArrayViewCheckLabel());
+
+  VarHandleTarget target = GetVarHandleTarget(invoke);
+  {
+    // Use the offset temporary register. It is not used yet at this point.
+    vixl32::Register temp = RegisterFrom(invoke->GetLocations()->GetTemp(0u));
+
+    UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+    vixl32::Register temp2 = temps.Acquire();
+
+    // The main path checked that the coordinateType0 is an array class that matches
+    // the class of the actual coordinate argument but it does not match the value type.
+    // Check if the `varhandle` references a ByteArrayViewVarHandle instance.
+    __ Ldr(temp, MemOperand(varhandle, class_offset.Int32Value()));
+    codegen->LoadClassRootForIntrinsic(temp2, ClassRoot::kJavaLangInvokeByteArrayViewVarHandle);
+    __ Cmp(temp, temp2);
+    __ B(ne, GetEntryLabel());
+
+    // Check for array index out of bounds.
+    __ Ldr(temp, MemOperand(object, array_length_offset.Int32Value()));
+    if (!temp.IsLow()) {
+      // Avoid using the 32-bit `cmp temp, #imm` in IT block by loading `size` into `temp2`.
+      __ Mov(temp2, size_operand);
+    }
+    __ Subs(temp, temp, index);
+    {
+      // Use ExactAssemblyScope here because we are using IT.
+      ExactAssemblyScope it_scope(assembler->GetVIXLAssembler(),
+                                  2 * k16BitT32InstructionSizeInBytes);
+      __ it(hs);
+      if (temp.IsLow()) {
+        __ cmp(hs, temp, size_operand);
+      } else {
+        __ cmp(hs, temp, temp2);
+      }
+    }
+    __ B(lo, GetEntryLabel());
+
+    // Construct the target.
+    __ Add(target.offset, index, data_offset.Int32Value());  // Note: `temp` cannot be used below.
+
+    // Alignment check. For unaligned access, go to the runtime.
+    DCHECK(IsPowerOfTwo(size));
+    __ Tst(target.offset, dchecked_integral_cast<int32_t>(size - 1u));
+    __ B(ne, GetEntryLabel());
+
+    // Byte order check. For native byte order return to the main path.
+    if (access_mode_template == mirror::VarHandle::AccessModeTemplate::kSet) {
+      HInstruction* arg = invoke->InputAt(invoke->GetNumberOfArguments() - 1u);
+      if (arg->IsConstant() && arg->AsConstant()->IsZeroBitPattern()) {
+        // There is no reason to differentiate between native byte order and byte-swap
+        // for setting a zero bit pattern. Just return to the main path.
+        __ B(GetNativeByteOrderLabel());
+        return;
+      }
+    }
+    __ Ldr(temp2, MemOperand(varhandle, native_byte_order_offset.Int32Value()));
+    __ Cmp(temp2, 0);
+    __ B(ne, GetNativeByteOrderLabel());
+  }
+
+  switch (access_mode_template) {
+    case mirror::VarHandle::AccessModeTemplate::kGet:
+      GenerateVarHandleGet(invoke, codegen, order_, atomic_, /*byte_swap=*/ true);
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kSet:
+      GenerateVarHandleSet(invoke, codegen, order_, atomic_, /*byte_swap=*/ true);
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndSet:
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndExchange:
+      GenerateVarHandleCompareAndSetOrExchange(
+          invoke, codegen, order_, return_success_, strong_, /*byte_swap=*/ true);
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kGetAndUpdate:
+      GenerateVarHandleGetAndUpdate(
+          invoke, codegen, get_and_update_op_, order_, /*byte_swap=*/ true);
+      break;
+  }
+  __ B(GetExitLabel());
+}
+
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathRoundDouble)   // Could be done by changing rounding mode, maybe?
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, UnsafeCASLong)     // High register pressure.
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, SystemArrayCopyChar)
-UNIMPLEMENTED_INTRINSIC(ARMVIXL, ReferenceGetReferent)
+UNIMPLEMENTED_INTRINSIC(ARMVIXL, LongDivideUnsigned)
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, CRC32Update)
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, CRC32UpdateBytes)
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, CRC32UpdateByteBuffer)
@@ -3079,6 +5371,7 @@
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, FP16GreaterEquals)
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, FP16Less)
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, FP16LessEquals)
+UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathMultiplyHigh)
 
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, StringStringIndexOf);
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, StringStringIndexOfAfter);
@@ -3105,6 +5398,9 @@
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, UnsafeGetAndSetLong)
 UNIMPLEMENTED_INTRINSIC(ARMVIXL, UnsafeGetAndSetObject)
 
+UNIMPLEMENTED_INTRINSIC(ARMVIXL, MethodHandleInvokeExact)
+UNIMPLEMENTED_INTRINSIC(ARMVIXL, MethodHandleInvoke)
+
 UNREACHABLE_INTRINSICS(ARMVIXL)
 
 #undef __
diff --git a/compiler/optimizing/intrinsics_arm_vixl.h b/compiler/optimizing/intrinsics_arm_vixl.h
index 1fea776..3103cec 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.h
+++ b/compiler/optimizing/intrinsics_arm_vixl.h
@@ -47,7 +47,7 @@
 
  private:
   ArenaAllocator* const allocator_;
-  CodeGenerator* const codegen_;
+  CodeGeneratorARMVIXL* const codegen_;
   ArmVIXLAssembler* const assembler_;
   const ArmInstructionSetFeatures& features_;
 
diff --git a/compiler/optimizing/intrinsics_utils.h b/compiler/optimizing/intrinsics_utils.h
index 41947f1..3349c52 100644
--- a/compiler/optimizing/intrinsics_utils.h
+++ b/compiler/optimizing/intrinsics_utils.h
@@ -17,9 +17,13 @@
 #ifndef ART_COMPILER_OPTIMIZING_INTRINSICS_UTILS_H_
 #define ART_COMPILER_OPTIMIZING_INTRINSICS_UTILS_H_
 
+#include "base/casts.h"
 #include "base/macros.h"
 #include "code_generator.h"
+#include "data_type-inl.h"
+#include "dex/dex_file-inl.h"
 #include "locations.h"
+#include "mirror/var_handle.h"
 #include "nodes.h"
 #include "utils/assembler.h"
 #include "utils/label.h"
@@ -36,10 +40,12 @@
 // Note: If an invoke wasn't sharpened, we will put down an invoke-virtual here. That's potentially
 //       sub-optimal (compared to a direct pointer call), but this is a slow-path.
 
-template <typename TDexCallingConvention>
-class IntrinsicSlowPath : public SlowPathCode {
+template <typename TDexCallingConvention,
+          typename TSlowPathCode = SlowPathCode,
+          typename TAssembler = Assembler>
+class IntrinsicSlowPath : public TSlowPathCode {
  public:
-  explicit IntrinsicSlowPath(HInvoke* invoke) : SlowPathCode(invoke), invoke_(invoke) { }
+  explicit IntrinsicSlowPath(HInvoke* invoke) : TSlowPathCode(invoke), invoke_(invoke) { }
 
   Location MoveArguments(CodeGenerator* codegen) {
     TDexCallingConvention calling_convention_visitor;
@@ -48,29 +54,41 @@
   }
 
   void EmitNativeCode(CodeGenerator* codegen) override {
-    Assembler* assembler = codegen->GetAssembler();
-    assembler->Bind(GetEntryLabel());
+    TAssembler* assembler = down_cast<TAssembler*>(codegen->GetAssembler());
+    assembler->Bind(this->GetEntryLabel());
 
-    SaveLiveRegisters(codegen, invoke_->GetLocations());
+    this->SaveLiveRegisters(codegen, invoke_->GetLocations());
 
     Location method_loc = MoveArguments(codegen);
 
     if (invoke_->IsInvokeStaticOrDirect()) {
-      codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), method_loc, this);
-    } else {
+      HInvokeStaticOrDirect* invoke_static_or_direct = invoke_->AsInvokeStaticOrDirect();
+      DCHECK_NE(invoke_static_or_direct->GetMethodLoadKind(), MethodLoadKind::kRecursive);
+      DCHECK_NE(invoke_static_or_direct->GetCodePtrLocation(),
+                CodePtrLocation::kCallCriticalNative);
+      codegen->GenerateStaticOrDirectCall(invoke_static_or_direct, method_loc, this);
+    } else if (invoke_->IsInvokeVirtual()) {
       codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), method_loc, this);
+    } else {
+      DCHECK(invoke_->IsInvokePolymorphic());
+      codegen->GenerateInvokePolymorphicCall(invoke_->AsInvokePolymorphic(), this);
     }
 
     // Copy the result back to the expected output.
     Location out = invoke_->GetLocations()->Out();
     if (out.IsValid()) {
-      DCHECK(out.IsRegister());  // TODO: Replace this when we support output in memory.
-      DCHECK(!invoke_->GetLocations()->GetLiveRegisters()->ContainsCoreRegister(out.reg()));
+      DCHECK(out.IsRegisterKind());  // TODO: Replace this when we support output in memory.
+      // We want to double-check that we don't overwrite a live register with the return
+      // value.
+      // Note: For the possible kNoOutputOverlap case we can't simply remove the OUT register
+      // from the GetLiveRegisters() - theoretically it might be needed after the return from
+      // the slow path.
+      DCHECK(!invoke_->GetLocations()->GetLiveRegisters()->OverlapsRegisters(out));
       codegen->MoveFromReturnRegister(out, invoke_->GetType());
     }
 
-    RestoreLiveRegisters(codegen, invoke_->GetLocations());
-    assembler->Jump(GetExitLabel());
+    this->RestoreLiveRegisters(codegen, invoke_->GetLocations());
+    assembler->Jump(this->GetExitLabel());
   }
 
   const char* GetDescription() const override { return "IntrinsicSlowPath"; }
@@ -82,6 +100,52 @@
   DISALLOW_COPY_AND_ASSIGN(IntrinsicSlowPath);
 };
 
+static inline size_t GetExpectedVarHandleCoordinatesCount(HInvoke *invoke) {
+  mirror::VarHandle::AccessModeTemplate access_mode_template =
+      mirror::VarHandle::GetAccessModeTemplateByIntrinsic(invoke->GetIntrinsic());
+  size_t var_type_count = mirror::VarHandle::GetNumberOfVarTypeParameters(access_mode_template);
+  size_t accessor_argument_count = invoke->GetNumberOfArguments() - 1;
+
+  return accessor_argument_count - var_type_count;
+}
+
+static inline DataType::Type GetDataTypeFromShorty(HInvoke* invoke, uint32_t index) {
+  DCHECK(invoke->IsInvokePolymorphic());
+  const DexFile& dex_file = invoke->GetBlock()->GetGraph()->GetDexFile();
+  const char* shorty = dex_file.GetShorty(invoke->AsInvokePolymorphic()->GetProtoIndex());
+  DCHECK_LT(index, strlen(shorty));
+
+  return DataType::FromShorty(shorty[index]);
+}
+
+static inline bool IsVarHandleGetAndBitwiseOp(HInvoke* invoke) {
+  switch (invoke->GetIntrinsic()) {
+    case Intrinsics::kVarHandleGetAndBitwiseOr:
+    case Intrinsics::kVarHandleGetAndBitwiseOrAcquire:
+    case Intrinsics::kVarHandleGetAndBitwiseOrRelease:
+    case Intrinsics::kVarHandleGetAndBitwiseXor:
+    case Intrinsics::kVarHandleGetAndBitwiseXorAcquire:
+    case Intrinsics::kVarHandleGetAndBitwiseXorRelease:
+    case Intrinsics::kVarHandleGetAndBitwiseAnd:
+    case Intrinsics::kVarHandleGetAndBitwiseAndAcquire:
+    case Intrinsics::kVarHandleGetAndBitwiseAndRelease:
+      return true;
+    default:
+      return false;
+  }
+}
+
+static inline bool IsVarHandleGetAndAdd(HInvoke* invoke) {
+  switch (invoke->GetIntrinsic()) {
+    case Intrinsics::kVarHandleGetAndAdd:
+    case Intrinsics::kVarHandleGetAndAddAcquire:
+    case Intrinsics::kVarHandleGetAndAddRelease:
+      return true;
+    default:
+      return false;
+  }
+}
+
 }  // namespace art
 
 #endif  // ART_COMPILER_OPTIMIZING_INTRINSICS_UTILS_H_
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 6d7462e..b0c4b57 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -22,6 +22,7 @@
 #include "art_method.h"
 #include "base/bit_utils.h"
 #include "code_generator_x86.h"
+#include "data_type-inl.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "heap_poisoning.h"
 #include "intrinsics.h"
@@ -31,6 +32,7 @@
 #include "mirror/object_array-inl.h"
 #include "mirror/reference.h"
 #include "mirror/string.h"
+#include "mirror/var_handle.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread-current-inl.h"
 #include "utils/x86/assembler_x86.h"
@@ -63,11 +65,6 @@
   return res->Intrinsified();
 }
 
-static void MoveArguments(HInvoke* invoke, CodeGeneratorX86* codegen) {
-  InvokeDexCallingConventionVisitorX86 calling_convention_visitor;
-  IntrinsicVisitor::MoveArguments(invoke, codegen, &calling_convention_visitor);
-}
-
 using IntrinsicSlowPathX86 = IntrinsicSlowPath<InvokeDexCallingConventionVisitorX86>;
 
 // NOLINT on __ macro to suppress wrong warning/fix (misc-macro-parentheses) from clang-tidy.
@@ -347,52 +344,23 @@
   GetAssembler()->sqrtsd(out, in);
 }
 
-static void InvokeOutOfLineIntrinsic(CodeGeneratorX86* codegen, HInvoke* invoke) {
-  MoveArguments(invoke, codegen);
-
-  DCHECK(invoke->IsInvokeStaticOrDirect());
-  codegen->GenerateStaticOrDirectCall(invoke->AsInvokeStaticOrDirect(),
-                                      Location::RegisterLocation(EAX));
-
-  // Copy the result back to the expected output.
-  Location out = invoke->GetLocations()->Out();
-  if (out.IsValid()) {
-    DCHECK(out.IsRegister());
-    codegen->MoveFromReturnRegister(out, invoke->GetType());
-  }
-}
-
 static void CreateSSE41FPToFPLocations(ArenaAllocator* allocator,
                                        HInvoke* invoke,
                                        CodeGeneratorX86* codegen) {
   // Do we have instruction support?
-  if (codegen->GetInstructionSetFeatures().HasSSE4_1()) {
-    CreateFPToFPLocations(allocator, invoke);
+  if (!codegen->GetInstructionSetFeatures().HasSSE4_1()) {
     return;
   }
 
-  // We have to fall back to a call to the intrinsic.
-  LocationSummary* locations =
-      new (allocator) LocationSummary(invoke, LocationSummary::kCallOnMainOnly);
-  InvokeRuntimeCallingConvention calling_convention;
-  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetFpuRegisterAt(0)));
-  locations->SetOut(Location::FpuRegisterLocation(XMM0));
-  // Needs to be EAX for the invoke.
-  locations->AddTemp(Location::RegisterLocation(EAX));
+  CreateFPToFPLocations(allocator, invoke);
 }
 
-static void GenSSE41FPToFPIntrinsic(CodeGeneratorX86* codegen,
-                                   HInvoke* invoke,
-                                   X86Assembler* assembler,
-                                   int round_mode) {
+static void GenSSE41FPToFPIntrinsic(HInvoke* invoke, X86Assembler* assembler, int round_mode) {
   LocationSummary* locations = invoke->GetLocations();
-  if (locations->WillCall()) {
-    InvokeOutOfLineIntrinsic(codegen, invoke);
-  } else {
-    XmmRegister in = locations->InAt(0).AsFpuRegister<XmmRegister>();
-    XmmRegister out = locations->Out().AsFpuRegister<XmmRegister>();
-    __ roundsd(out, in, Immediate(round_mode));
-  }
+  DCHECK(!locations->WillCall());
+  XmmRegister in = locations->InAt(0).AsFpuRegister<XmmRegister>();
+  XmmRegister out = locations->Out().AsFpuRegister<XmmRegister>();
+  __ roundsd(out, in, Immediate(round_mode));
 }
 
 void IntrinsicLocationsBuilderX86::VisitMathCeil(HInvoke* invoke) {
@@ -400,7 +368,7 @@
 }
 
 void IntrinsicCodeGeneratorX86::VisitMathCeil(HInvoke* invoke) {
-  GenSSE41FPToFPIntrinsic(codegen_, invoke, GetAssembler(), 2);
+  GenSSE41FPToFPIntrinsic(invoke, GetAssembler(), 2);
 }
 
 void IntrinsicLocationsBuilderX86::VisitMathFloor(HInvoke* invoke) {
@@ -408,7 +376,7 @@
 }
 
 void IntrinsicCodeGeneratorX86::VisitMathFloor(HInvoke* invoke) {
-  GenSSE41FPToFPIntrinsic(codegen_, invoke, GetAssembler(), 1);
+  GenSSE41FPToFPIntrinsic(invoke, GetAssembler(), 1);
 }
 
 void IntrinsicLocationsBuilderX86::VisitMathRint(HInvoke* invoke) {
@@ -416,44 +384,33 @@
 }
 
 void IntrinsicCodeGeneratorX86::VisitMathRint(HInvoke* invoke) {
-  GenSSE41FPToFPIntrinsic(codegen_, invoke, GetAssembler(), 0);
+  GenSSE41FPToFPIntrinsic(invoke, GetAssembler(), 0);
 }
 
 void IntrinsicLocationsBuilderX86::VisitMathRoundFloat(HInvoke* invoke) {
   // Do we have instruction support?
-  if (codegen_->GetInstructionSetFeatures().HasSSE4_1()) {
-    HInvokeStaticOrDirect* static_or_direct = invoke->AsInvokeStaticOrDirect();
-    DCHECK(static_or_direct != nullptr);
-    LocationSummary* locations =
-        new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
-    locations->SetInAt(0, Location::RequiresFpuRegister());
-    if (static_or_direct->HasSpecialInput() &&
-        invoke->InputAt(
-            static_or_direct->GetSpecialInputIndex())->IsX86ComputeBaseMethodAddress()) {
-      locations->SetInAt(1, Location::RequiresRegister());
-    }
-    locations->SetOut(Location::RequiresRegister());
-    locations->AddTemp(Location::RequiresFpuRegister());
-    locations->AddTemp(Location::RequiresFpuRegister());
+  if (!codegen_->GetInstructionSetFeatures().HasSSE4_1()) {
     return;
   }
 
-  // We have to fall back to a call to the intrinsic.
+  HInvokeStaticOrDirect* static_or_direct = invoke->AsInvokeStaticOrDirect();
+  DCHECK(static_or_direct != nullptr);
   LocationSummary* locations =
-      new (allocator_) LocationSummary(invoke, LocationSummary::kCallOnMainOnly);
-  InvokeRuntimeCallingConvention calling_convention;
-  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetFpuRegisterAt(0)));
-  locations->SetOut(Location::RegisterLocation(EAX));
-  // Needs to be EAX for the invoke.
-  locations->AddTemp(Location::RegisterLocation(EAX));
+      new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+  locations->SetInAt(0, Location::RequiresFpuRegister());
+  if (static_or_direct->HasSpecialInput() &&
+      invoke->InputAt(
+          static_or_direct->GetSpecialInputIndex())->IsX86ComputeBaseMethodAddress()) {
+    locations->SetInAt(1, Location::RequiresRegister());
+  }
+  locations->SetOut(Location::RequiresRegister());
+  locations->AddTemp(Location::RequiresFpuRegister());
+  locations->AddTemp(Location::RequiresFpuRegister());
 }
 
 void IntrinsicCodeGeneratorX86::VisitMathRoundFloat(HInvoke* invoke) {
   LocationSummary* locations = invoke->GetLocations();
-  if (locations->WillCall()) {  // TODO: can we reach this?
-    InvokeOutOfLineIntrinsic(codegen_, invoke);
-    return;
-  }
+  DCHECK(!locations->WillCall());
 
   XmmRegister in = locations->InAt(0).AsFpuRegister<XmmRegister>();
   XmmRegister t1 = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
@@ -2005,122 +1962,223 @@
   CreateIntIntIntIntIntToInt(allocator_, DataType::Type::kReference, invoke);
 }
 
-static void GenCAS(DataType::Type type, HInvoke* invoke, CodeGeneratorX86* codegen) {
+static void GenPrimitiveLockedCmpxchg(DataType::Type type,
+                                      CodeGeneratorX86* codegen,
+                                      Location expected_value,
+                                      Location new_value,
+                                      Register base,
+                                      Register offset,
+                                      // Only necessary for floating point
+                                      Register temp = Register::kNoRegister) {
   X86Assembler* assembler = down_cast<X86Assembler*>(codegen->GetAssembler());
+
+  if (DataType::Kind(type) == DataType::Type::kInt32) {
+    DCHECK_EQ(expected_value.AsRegister<Register>(), EAX);
+  }
+
+  // The address of the field within the holding object.
+  Address field_addr(base, offset, TIMES_1, 0);
+
+  switch (type) {
+    case DataType::Type::kBool:
+    case DataType::Type::kInt8:
+      __ LockCmpxchgb(field_addr, new_value.AsRegister<ByteRegister>());
+      break;
+    case DataType::Type::kInt16:
+    case DataType::Type::kUint16:
+      __ LockCmpxchgw(field_addr, new_value.AsRegister<Register>());
+      break;
+    case DataType::Type::kInt32:
+      __ LockCmpxchgl(field_addr, new_value.AsRegister<Register>());
+      break;
+    case DataType::Type::kFloat32: {
+      // cmpxchg requires the expected value to be in EAX so the new value must be elsewhere.
+      DCHECK_NE(temp, EAX);
+      // EAX is both an input and an output for cmpxchg
+      codegen->Move32(Location::RegisterLocation(EAX), expected_value);
+      codegen->Move32(Location::RegisterLocation(temp), new_value);
+      __ LockCmpxchgl(field_addr, temp);
+      break;
+    }
+    case DataType::Type::kInt64:
+      // Ensure the expected value is in EAX:EDX and that the new
+      // value is in EBX:ECX (required by the CMPXCHG8B instruction).
+      DCHECK_EQ(expected_value.AsRegisterPairLow<Register>(), EAX);
+      DCHECK_EQ(expected_value.AsRegisterPairHigh<Register>(), EDX);
+      DCHECK_EQ(new_value.AsRegisterPairLow<Register>(), EBX);
+      DCHECK_EQ(new_value.AsRegisterPairHigh<Register>(), ECX);
+      __ LockCmpxchg8b(field_addr);
+      break;
+    default:
+      LOG(FATAL) << "Unexpected CAS type " << type;
+  }
+  // LOCK CMPXCHG/LOCK CMPXCHG8B have full barrier semantics, and we
+  // don't need scheduling barriers at this time.
+}
+
+static void GenPrimitiveCAS(DataType::Type type,
+                            CodeGeneratorX86* codegen,
+                            Location expected_value,
+                            Location new_value,
+                            Register base,
+                            Register offset,
+                            Location out,
+                            // Only necessary for floating point
+                            Register temp = Register::kNoRegister,
+                            bool is_cmpxchg = false) {
+  X86Assembler* assembler = down_cast<X86Assembler*>(codegen->GetAssembler());
+
+  if (!is_cmpxchg || DataType::Kind(type) == DataType::Type::kInt32) {
+    DCHECK_EQ(out.AsRegister<Register>(), EAX);
+  }
+
+  GenPrimitiveLockedCmpxchg(type, codegen, expected_value, new_value, base, offset, temp);
+
+  if (is_cmpxchg) {
+    // Sign-extend, zero-extend or move the result if necessary
+    switch (type) {
+      case DataType::Type::kBool:
+        __ movzxb(out.AsRegister<Register>(), out.AsRegister<ByteRegister>());
+        break;
+      case DataType::Type::kInt8:
+        __ movsxb(out.AsRegister<Register>(), out.AsRegister<ByteRegister>());
+        break;
+      case DataType::Type::kInt16:
+        __ movsxw(out.AsRegister<Register>(), out.AsRegister<Register>());
+        break;
+      case DataType::Type::kUint16:
+        __ movzxw(out.AsRegister<Register>(), out.AsRegister<Register>());
+        break;
+      case DataType::Type::kFloat32:
+        __ movd(out.AsFpuRegister<XmmRegister>(), EAX);
+        break;
+      default:
+        // Nothing to do
+        break;
+    }
+  } else {
+    // Convert ZF into the Boolean result.
+    __ setb(kZero, out.AsRegister<Register>());
+    __ movzxb(out.AsRegister<Register>(), out.AsRegister<ByteRegister>());
+  }
+}
+
+static void GenReferenceCAS(HInvoke* invoke,
+                            CodeGeneratorX86* codegen,
+                            Location expected_value,
+                            Location new_value,
+                            Register base,
+                            Register offset,
+                            Register temp,
+                            Register temp2,
+                            bool is_cmpxchg = false) {
+  X86Assembler* assembler = down_cast<X86Assembler*>(codegen->GetAssembler());
+  LocationSummary* locations = invoke->GetLocations();
+  Location out = locations->Out();
+
+  // The address of the field within the holding object.
+  Address field_addr(base, offset, TIMES_1, 0);
+
+  Register value = new_value.AsRegister<Register>();
+  Register expected = expected_value.AsRegister<Register>();
+  DCHECK_EQ(expected, EAX);
+  DCHECK_NE(temp, temp2);
+
+  if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+    // Need to make sure the reference stored in the field is a to-space
+    // one before attempting the CAS or the CAS could fail incorrectly.
+    codegen->GenerateReferenceLoadWithBakerReadBarrier(
+        invoke,
+        // Unused, used only as a "temporary" within the read barrier.
+        Location::RegisterLocation(temp),
+        base,
+        field_addr,
+        /* needs_null_check= */ false,
+        /* always_update_field= */ true,
+        &temp2);
+  }
+  bool base_equals_value = (base == value);
+  if (kPoisonHeapReferences) {
+    if (base_equals_value) {
+      // If `base` and `value` are the same register location, move
+      // `value` to a temporary register.  This way, poisoning
+      // `value` won't invalidate `base`.
+      value = temp;
+      __ movl(value, base);
+    }
+
+    // Check that the register allocator did not assign the location
+    // of `expected` (EAX) to `value` nor to `base`, so that heap
+    // poisoning (when enabled) works as intended below.
+    // - If `value` were equal to `expected`, both references would
+    //   be poisoned twice, meaning they would not be poisoned at
+    //   all, as heap poisoning uses address negation.
+    // - If `base` were equal to `expected`, poisoning `expected`
+    //   would invalidate `base`.
+    DCHECK_NE(value, expected);
+    DCHECK_NE(base, expected);
+    __ PoisonHeapReference(expected);
+    __ PoisonHeapReference(value);
+  }
+  __ LockCmpxchgl(field_addr, value);
+
+  // LOCK CMPXCHG has full barrier semantics, and we don't need
+  // scheduling barriers at this time.
+
+  if (is_cmpxchg) {
+    DCHECK_EQ(out.AsRegister<Register>(), EAX);
+    __ MaybeUnpoisonHeapReference(out.AsRegister<Register>());
+  } else {
+    // Convert ZF into the Boolean result.
+    __ setb(kZero, out.AsRegister<Register>());
+    __ movzxb(out.AsRegister<Register>(), out.AsRegister<ByteRegister>());
+  }
+
+  // Mark card for object if the new value is stored.
+  bool value_can_be_null = true;  // TODO: Worth finding out this information?
+  NearLabel skip_mark_gc_card;
+  __ j(kNotZero, &skip_mark_gc_card);
+  codegen->MarkGCCard(temp, temp2, base, value, value_can_be_null);
+  __ Bind(&skip_mark_gc_card);
+
+  // If heap poisoning is enabled, we need to unpoison the values
+  // that were poisoned earlier.
+  if (kPoisonHeapReferences) {
+    if (base_equals_value) {
+      // `value` has been moved to a temporary register, no need to
+      // unpoison it.
+    } else {
+      // Ensure `value` is different from `out`, so that unpoisoning
+      // the former does not invalidate the latter.
+      DCHECK_NE(value, out.AsRegister<Register>());
+      __ UnpoisonHeapReference(value);
+    }
+  }
+  // Do not unpoison the reference contained in register
+  // `expected`, as it is the same as register `out` (EAX).
+}
+
+static void GenCAS(DataType::Type type, HInvoke* invoke, CodeGeneratorX86* codegen) {
   LocationSummary* locations = invoke->GetLocations();
 
   Register base = locations->InAt(1).AsRegister<Register>();
   Register offset = locations->InAt(2).AsRegisterPairLow<Register>();
+  Location expected_value = locations->InAt(3);
+  Location new_value = locations->InAt(4);
   Location out = locations->Out();
   DCHECK_EQ(out.AsRegister<Register>(), EAX);
 
-  // The address of the field within the holding object.
-  Address field_addr(base, offset, ScaleFactor::TIMES_1, 0);
-
   if (type == DataType::Type::kReference) {
     // The only read barrier implementation supporting the
     // UnsafeCASObject intrinsic is the Baker-style read barriers.
     DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
 
-    Location temp1_loc = locations->GetTemp(0);
-    Register temp1 = temp1_loc.AsRegister<Register>();
+    Register temp = locations->GetTemp(0).AsRegister<Register>();
     Register temp2 = locations->GetTemp(1).AsRegister<Register>();
-
-    Register expected = locations->InAt(3).AsRegister<Register>();
-    // Ensure `expected` is in EAX (required by the CMPXCHG instruction).
-    DCHECK_EQ(expected, EAX);
-    Register value = locations->InAt(4).AsRegister<Register>();
-
-    // Mark card for object assuming new value is stored.
-    bool value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MarkGCCard(temp1, temp2, base, value, value_can_be_null);
-
-    if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
-      // Need to make sure the reference stored in the field is a to-space
-      // one before attempting the CAS or the CAS could fail incorrectly.
-      codegen->GenerateReferenceLoadWithBakerReadBarrier(
-          invoke,
-          temp1_loc,  // Unused, used only as a "temporary" within the read barrier.
-          base,
-          field_addr,
-          /* needs_null_check= */ false,
-          /* always_update_field= */ true,
-          &temp2);
-    }
-
-    bool base_equals_value = (base == value);
-    if (kPoisonHeapReferences) {
-      if (base_equals_value) {
-        // If `base` and `value` are the same register location, move
-        // `value` to a temporary register.  This way, poisoning
-        // `value` won't invalidate `base`.
-        value = temp1;
-        __ movl(value, base);
-      }
-
-      // Check that the register allocator did not assign the location
-      // of `expected` (EAX) to `value` nor to `base`, so that heap
-      // poisoning (when enabled) works as intended below.
-      // - If `value` were equal to `expected`, both references would
-      //   be poisoned twice, meaning they would not be poisoned at
-      //   all, as heap poisoning uses address negation.
-      // - If `base` were equal to `expected`, poisoning `expected`
-      //   would invalidate `base`.
-      DCHECK_NE(value, expected);
-      DCHECK_NE(base, expected);
-
-      __ PoisonHeapReference(expected);
-      __ PoisonHeapReference(value);
-    }
-
-    __ LockCmpxchgl(field_addr, value);
-
-    // LOCK CMPXCHG has full barrier semantics, and we don't need
-    // scheduling barriers at this time.
-
-    // Convert ZF into the Boolean result.
-    __ setb(kZero, out.AsRegister<Register>());
-    __ movzxb(out.AsRegister<Register>(), out.AsRegister<ByteRegister>());
-
-    // If heap poisoning is enabled, we need to unpoison the values
-    // that were poisoned earlier.
-    if (kPoisonHeapReferences) {
-      if (base_equals_value) {
-        // `value` has been moved to a temporary register, no need to
-        // unpoison it.
-      } else {
-        // Ensure `value` is different from `out`, so that unpoisoning
-        // the former does not invalidate the latter.
-        DCHECK_NE(value, out.AsRegister<Register>());
-        __ UnpoisonHeapReference(value);
-      }
-      // Do not unpoison the reference contained in register
-      // `expected`, as it is the same as register `out` (EAX).
-    }
+    GenReferenceCAS(invoke, codegen, expected_value, new_value, base, offset, temp, temp2);
   } else {
-    if (type == DataType::Type::kInt32) {
-      // Ensure the expected value is in EAX (required by the CMPXCHG
-      // instruction).
-      DCHECK_EQ(locations->InAt(3).AsRegister<Register>(), EAX);
-      __ LockCmpxchgl(field_addr, locations->InAt(4).AsRegister<Register>());
-    } else if (type == DataType::Type::kInt64) {
-      // Ensure the expected value is in EAX:EDX and that the new
-      // value is in EBX:ECX (required by the CMPXCHG8B instruction).
-      DCHECK_EQ(locations->InAt(3).AsRegisterPairLow<Register>(), EAX);
-      DCHECK_EQ(locations->InAt(3).AsRegisterPairHigh<Register>(), EDX);
-      DCHECK_EQ(locations->InAt(4).AsRegisterPairLow<Register>(), EBX);
-      DCHECK_EQ(locations->InAt(4).AsRegisterPairHigh<Register>(), ECX);
-      __ LockCmpxchg8b(field_addr);
-    } else {
-      LOG(FATAL) << "Unexpected CAS type " << type;
-    }
-
-    // LOCK CMPXCHG/LOCK CMPXCHG8B have full barrier semantics, and we
-    // don't need scheduling barriers at this time.
-
-    // Convert ZF into the Boolean result.
-    __ setb(kZero, out.AsRegister<Register>());
-    __ movzxb(out.AsRegister<Register>(), out.AsRegister<ByteRegister>());
+    DCHECK(!DataType::IsFloatingPointType(type));
+    GenPrimitiveCAS(type, codegen, expected_value, new_value, base, offset, out);
   }
 }
 
@@ -2956,6 +3014,21 @@
   __ Bind(intrinsic_slow_path->GetExitLabel());
 }
 
+static void RequestBaseMethodAddressInRegister(HInvoke* invoke) {
+  LocationSummary* locations = invoke->GetLocations();
+  if (locations != nullptr) {
+    HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect();
+    // Note: The base method address is not present yet when this is called from the
+    // PCRelativeHandlerVisitor via IsCallFreeIntrinsic() to determine whether to insert it.
+    if (invoke_static_or_direct->HasSpecialInput()) {
+      DCHECK(invoke_static_or_direct->InputAt(invoke_static_or_direct->GetSpecialInputIndex())
+                 ->IsX86ComputeBaseMethodAddress());
+      locations->SetInAt(invoke_static_or_direct->GetSpecialInputIndex(),
+                         Location::RequiresRegister());
+    }
+  }
+}
+
 void IntrinsicLocationsBuilderX86::VisitIntegerValueOf(HInvoke* invoke) {
   DCHECK(invoke->IsInvokeStaticOrDirect());
   InvokeRuntimeCallingConvention calling_convention;
@@ -2964,17 +3037,7 @@
       codegen_,
       Location::RegisterLocation(EAX),
       Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
-
-  LocationSummary* locations = invoke->GetLocations();
-  if (locations != nullptr) {
-    HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect();
-    if (invoke_static_or_direct->HasSpecialInput() &&
-        invoke->InputAt(invoke_static_or_direct->GetSpecialInputIndex())
-            ->IsX86ComputeBaseMethodAddress()) {
-      locations->SetInAt(invoke_static_or_direct->GetSpecialInputIndex(),
-                         Location::RequiresRegister());
-    }
-  }
+  RequestBaseMethodAddressInRegister(invoke);
 }
 
 void IntrinsicCodeGeneratorX86::VisitIntegerValueOf(HInvoke* invoke) {
@@ -2985,7 +3048,12 @@
   X86Assembler* assembler = GetAssembler();
 
   Register out = locations->Out().AsRegister<Register>();
-  InvokeRuntimeCallingConvention calling_convention;
+  auto allocate_instance = [&]() {
+    DCHECK_EQ(out, InvokeRuntimeCallingConvention().GetRegisterAt(0));
+    codegen_->LoadIntrinsicDeclaringClass(out, invoke->AsInvokeStaticOrDirect());
+    codegen_->InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
+    CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
+  };
   if (invoke->InputAt(0)->IsConstant()) {
     int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
     if (static_cast<uint32_t>(value - info.low) < info.length) {
@@ -2998,8 +3066,7 @@
       // Allocate and initialize a new j.l.Integer.
       // TODO: If we JIT, we could allocate the j.l.Integer now, and store it in the
       // JIT object table.
-      codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
-                                             info.integer_boot_image_offset);
+      allocate_instance();
       __ movl(Address(out, info.value_offset), Immediate(value));
     }
   } else {
@@ -3022,7 +3089,8 @@
       DCHECK(method_address != nullptr);
       Register method_address_reg =
           invoke->GetLocations()->InAt(method_address_index).AsRegister<Register>();
-      __ movl(out, Address(method_address_reg, out, TIMES_4, CodeGeneratorX86::kDummy32BitOffset));
+      __ movl(out,
+              Address(method_address_reg, out, TIMES_4, CodeGeneratorX86::kPlaceholder32BitOffset));
       codegen_->RecordBootImageIntrinsicPatch(method_address, info.array_data_boot_image_reference);
     } else {
       // Note: We're about to clobber the index in `out`, so we need to use `in` and
@@ -3038,13 +3106,128 @@
     __ jmp(&done);
     __ Bind(&allocate);
     // Otherwise allocate and initialize a new j.l.Integer.
-    codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
-                                           info.integer_boot_image_offset);
+    allocate_instance();
     __ movl(Address(out, info.value_offset), in);
     __ Bind(&done);
   }
 }
 
+void IntrinsicLocationsBuilderX86::VisitReferenceGetReferent(HInvoke* invoke) {
+  IntrinsicVisitor::CreateReferenceGetReferentLocations(invoke, codegen_);
+  RequestBaseMethodAddressInRegister(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitReferenceGetReferent(HInvoke* invoke) {
+  X86Assembler* assembler = GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+
+  Location obj = locations->InAt(0);
+  Location out = locations->Out();
+
+  SlowPathCode* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(invoke);
+  codegen_->AddSlowPath(slow_path);
+
+  if (kEmitCompilerReadBarrier) {
+    // Check self->GetWeakRefAccessEnabled().
+    ThreadOffset32 offset = Thread::WeakRefAccessEnabledOffset<kX86PointerSize>();
+    __ fs()->cmpl(Address::Absolute(offset), Immediate(0));
+    __ j(kEqual, slow_path->GetEntryLabel());
+  }
+
+  // Load the java.lang.ref.Reference class, use the output register as a temporary.
+  codegen_->LoadIntrinsicDeclaringClass(out.AsRegister<Register>(),
+                                        invoke->AsInvokeStaticOrDirect());
+
+  // Check static fields java.lang.ref.Reference.{disableIntrinsic,slowPathEnabled} together.
+  MemberOffset disable_intrinsic_offset = IntrinsicVisitor::GetReferenceDisableIntrinsicOffset();
+  DCHECK_ALIGNED(disable_intrinsic_offset.Uint32Value(), 2u);
+  DCHECK_EQ(disable_intrinsic_offset.Uint32Value() + 1u,
+            IntrinsicVisitor::GetReferenceSlowPathEnabledOffset().Uint32Value());
+  __ cmpw(Address(out.AsRegister<Register>(), disable_intrinsic_offset.Uint32Value()),
+          Immediate(0));
+  __ j(kNotEqual, slow_path->GetEntryLabel());
+
+  // Load the value from the field.
+  uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+  if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+    codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+                                                    out,
+                                                    obj.AsRegister<Register>(),
+                                                    referent_offset,
+                                                    /*needs_null_check=*/ true);
+    // Note that the fence is a no-op, thanks to the x86 memory model.
+    codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);  // `referent` is volatile.
+  } else {
+    __ movl(out.AsRegister<Register>(), Address(obj.AsRegister<Register>(), referent_offset));
+    codegen_->MaybeRecordImplicitNullCheck(invoke);
+    // Note that the fence is a no-op, thanks to the x86 memory model.
+    codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);  // `referent` is volatile.
+    codegen_->MaybeGenerateReadBarrierSlow(invoke, out, out, obj, referent_offset);
+  }
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderX86::VisitReferenceRefersTo(HInvoke* invoke) {
+  IntrinsicVisitor::CreateReferenceRefersToLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitReferenceRefersTo(HInvoke* invoke) {
+  X86Assembler* assembler = GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+
+  Register obj = locations->InAt(0).AsRegister<Register>();
+  Register other = locations->InAt(1).AsRegister<Register>();
+  Register out = locations->Out().AsRegister<Register>();
+
+  uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+  uint32_t monitor_offset = mirror::Object::MonitorOffset().Int32Value();
+
+  __ movl(out, Address(obj, referent_offset));
+  codegen_->MaybeRecordImplicitNullCheck(invoke);
+  __ MaybeUnpoisonHeapReference(out);
+  // Note that the fence is a no-op, thanks to the x86 memory model.
+  codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);  // `referent` is volatile.
+
+  NearLabel end, return_true, return_false;
+  __ cmpl(out, other);
+
+  if (kEmitCompilerReadBarrier) {
+    DCHECK(kUseBakerReadBarrier);
+
+    __ j(kEqual, &return_true);
+
+    // Check if the loaded reference is null.
+    __ testl(out, out);
+    __ j(kZero, &return_false);
+
+    // For correct memory visibility, we need a barrier before loading the lock word
+    // but we already have the barrier emitted for volatile load above which is sufficient.
+
+    // Load the lockword and check if it is a forwarding address.
+    static_assert(LockWord::kStateShift == 30u);
+    static_assert(LockWord::kStateForwardingAddress == 3u);
+    __ movl(out, Address(out, monitor_offset));
+    __ cmpl(out, Immediate(static_cast<int32_t>(0xc0000000)));
+    __ j(kBelow, &return_false);
+
+    // Extract the forwarding address and compare with `other`.
+    __ shll(out, Immediate(LockWord::kForwardingAddressShift));
+    __ cmpl(out, other);
+  }
+
+  __ j(kNotEqual, &return_false);
+
+  // Return true and exit the function.
+  __ Bind(&return_true);
+  __ movl(out, Immediate(1));
+  __ jmp(&end);
+
+  // Return false and exit the function.
+  __ Bind(&return_false);
+  __ xorl(out, out);
+  __ Bind(&end);
+}
+
 void IntrinsicLocationsBuilderX86::VisitThreadInterrupted(HInvoke* invoke) {
   LocationSummary* locations =
       new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
@@ -3072,12 +3255,1352 @@
 
 void IntrinsicCodeGeneratorX86::VisitReachabilityFence(HInvoke* invoke ATTRIBUTE_UNUSED) { }
 
+void IntrinsicLocationsBuilderX86::VisitIntegerDivideUnsigned(HInvoke* invoke) {
+  LocationSummary* locations = new (allocator_) LocationSummary(invoke,
+                                                                LocationSummary::kCallOnSlowPath,
+                                                                kIntrinsified);
+  locations->SetInAt(0, Location::RegisterLocation(EAX));
+  locations->SetInAt(1, Location::RequiresRegister());
+  locations->SetOut(Location::SameAsFirstInput());
+  // Intel uses edx:eax as the dividend.
+  locations->AddTemp(Location::RegisterLocation(EDX));
+}
+
+void IntrinsicCodeGeneratorX86::VisitIntegerDivideUnsigned(HInvoke* invoke) {
+  X86Assembler* assembler = GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  Location out = locations->Out();
+  Location first = locations->InAt(0);
+  Location second = locations->InAt(1);
+  Register edx = locations->GetTemp(0).AsRegister<Register>();
+  Register second_reg = second.AsRegister<Register>();
+
+  DCHECK_EQ(EAX, first.AsRegister<Register>());
+  DCHECK_EQ(EAX, out.AsRegister<Register>());
+  DCHECK_EQ(EDX, edx);
+
+  // Check if divisor is zero, bail to managed implementation to handle.
+  __ testl(second_reg, second_reg);
+  SlowPathCode* slow_path = new (codegen_->GetScopedAllocator()) IntrinsicSlowPathX86(invoke);
+  codegen_->AddSlowPath(slow_path);
+  __ j(kEqual, slow_path->GetEntryLabel());
+
+  __ xorl(edx, edx);
+  __ divl(second_reg);
+
+  __ Bind(slow_path->GetExitLabel());
+}
+
+static bool IsValidFieldVarHandleExpected(HInvoke* invoke) {
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (expected_coordinates_count > 1u) {
+    // Only static and instance fields VarHandle are supported now.
+    return false;
+  }
+
+  if (expected_coordinates_count == 1u &&
+      invoke->InputAt(1)->GetType() != DataType::Type::kReference) {
+    // For instance fields, the source object must be a reference
+    return false;
+  }
+
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  DataType::Type return_type = invoke->GetType();
+  mirror::VarHandle::AccessModeTemplate access_mode_template =
+      mirror::VarHandle::GetAccessModeTemplateByIntrinsic(invoke->GetIntrinsic());
+  switch (access_mode_template) {
+    case mirror::VarHandle::AccessModeTemplate::kGet:
+      // The return type should be the same as varType, so it shouldn't be void.
+      if (return_type == DataType::Type::kVoid) {
+        return false;
+      }
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kSet:
+      if (return_type != DataType::Type::kVoid) {
+        return false;
+      }
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndSet: {
+      if (return_type != DataType::Type::kBool) {
+        return false;
+      }
+      uint32_t expected_value_index = number_of_arguments - 2;
+      uint32_t new_value_index = number_of_arguments - 1;
+      DataType::Type expected_value_type = GetDataTypeFromShorty(invoke, expected_value_index);
+      DataType::Type new_value_type = GetDataTypeFromShorty(invoke, new_value_index);
+
+      if (expected_value_type != new_value_type) {
+        return false;
+      }
+      break;
+    }
+    case mirror::VarHandle::AccessModeTemplate::kGetAndUpdate: {
+      DataType::Type value_type = GetDataTypeFromShorty(invoke, number_of_arguments - 1);
+      if (IsVarHandleGetAndAdd(invoke) &&
+          (value_type == DataType::Type::kReference || value_type == DataType::Type::kBool)) {
+        // We should only add numerical types.
+        return false;
+      } else if (IsVarHandleGetAndBitwiseOp(invoke) && !DataType::IsIntegralType(value_type)) {
+        // We can only apply operators to bitwise integral types.
+        // Note that bitwise VarHandle operations accept a non-integral boolean type and
+        // perform the appropriate logical operation. However, the result is the same as
+        // using the bitwise operation on our boolean representation and this fits well
+        // with DataType::IsIntegralType() treating the compiler type kBool as integral.
+        return false;
+      }
+      if (value_type != return_type) {
+        return false;
+      }
+      break;
+    }
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndExchange: {
+      uint32_t expected_value_index = number_of_arguments - 2;
+      uint32_t new_value_index = number_of_arguments - 1;
+      DataType::Type expected_value_type = GetDataTypeFromShorty(invoke, expected_value_index);
+      DataType::Type new_value_type = GetDataTypeFromShorty(invoke, new_value_index);
+
+      if (expected_value_type != new_value_type || return_type != expected_value_type) {
+        return false;
+      }
+      break;
+    }
+  }
+
+  return true;
+}
+
+static void GenerateVarHandleAccessModeCheck(Register varhandle_object,
+                                             mirror::VarHandle::AccessMode access_mode,
+                                             SlowPathCode* slow_path,
+                                             X86Assembler* assembler) {
+  const uint32_t access_modes_bitmask_offset =
+      mirror::VarHandle::AccessModesBitMaskOffset().Uint32Value();
+  const uint32_t access_mode_bit = 1u << static_cast<uint32_t>(access_mode);
+
+  // If the access mode is not supported, bail to runtime implementation to handle
+  __ testl(Address(varhandle_object, access_modes_bitmask_offset), Immediate(access_mode_bit));
+  __ j(kZero, slow_path->GetEntryLabel());
+}
+
+static void GenerateVarHandleStaticFieldCheck(Register varhandle_object,
+                                              SlowPathCode* slow_path,
+                                              X86Assembler* assembler) {
+  const uint32_t coordtype0_offset = mirror::VarHandle::CoordinateType0Offset().Uint32Value();
+
+  // Check that the VarHandle references a static field by checking that coordinateType0 == null.
+  // Do not emit read barrier (or unpoison the reference) for comparing to null.
+  __ cmpl(Address(varhandle_object, coordtype0_offset), Immediate(0));
+  __ j(kNotEqual, slow_path->GetEntryLabel());
+}
+
+static void GenerateSubTypeObjectCheck(Register object,
+                                       Register temp,
+                                       Address type_address,
+                                       SlowPathCode* slow_path,
+                                       X86Assembler* assembler,
+                                       bool object_can_be_null = true) {
+  const uint32_t class_offset = mirror::Object::ClassOffset().Uint32Value();
+  const uint32_t super_class_offset = mirror::Class::SuperClassOffset().Uint32Value();
+  NearLabel check_type_compatibility, type_matched;
+
+  // If the object is null, there is no need to check the type
+  if (object_can_be_null) {
+    __ testl(object, object);
+    __ j(kZero, &type_matched);
+  }
+
+  // Do not unpoison for in-memory comparison.
+  // We deliberately avoid the read barrier, letting the slow path handle the false negatives.
+  __ movl(temp, Address(object, class_offset));
+  __ Bind(&check_type_compatibility);
+  __ cmpl(temp, type_address);
+  __ j(kEqual, &type_matched);
+  // Load the super class.
+  __ MaybeUnpoisonHeapReference(temp);
+  __ movl(temp, Address(temp, super_class_offset));
+  // If the super class is null, we reached the root of the hierarchy without a match.
+  // We let the slow path handle uncovered cases (e.g. interfaces).
+  __ testl(temp, temp);
+  __ j(kEqual, slow_path->GetEntryLabel());
+  __ jmp(&check_type_compatibility);
+  __ Bind(&type_matched);
+}
+
+static void GenerateVarHandleInstanceFieldObjectCheck(Register varhandle_object,
+                                                      Register object,
+                                                      Register temp,
+                                                      SlowPathCode* slow_path,
+                                                      X86Assembler* assembler) {
+  const uint32_t coordtype0_offset = mirror::VarHandle::CoordinateType0Offset().Uint32Value();
+  const uint32_t coordtype1_offset = mirror::VarHandle::CoordinateType1Offset().Uint32Value();
+
+  // Check that the VarHandle references an instance field by checking that
+  // coordinateType1 == null. coordinateType0 should be not null, but this is handled by the
+  // type compatibility check with the source object's type, which will fail for null.
+  __ cmpl(Address(varhandle_object, coordtype1_offset), Immediate(0));
+  __ j(kNotEqual, slow_path->GetEntryLabel());
+
+  // Check if the object is null
+  __ testl(object, object);
+  __ j(kZero, slow_path->GetEntryLabel());
+
+  // Check the object's class against coordinateType0.
+  GenerateSubTypeObjectCheck(object,
+                             temp,
+                             Address(varhandle_object, coordtype0_offset),
+                             slow_path,
+                             assembler,
+                             /* object_can_be_null= */ false);
+}
+
+static void GenerateVarTypePrimitiveTypeCheck(Register varhandle_object,
+                                              Register temp,
+                                              DataType::Type type,
+                                              SlowPathCode* slow_path,
+                                              X86Assembler* assembler) {
+  const uint32_t var_type_offset = mirror::VarHandle::VarTypeOffset().Uint32Value();
+  const uint32_t primitive_type_offset = mirror::Class::PrimitiveTypeOffset().Uint32Value();
+  const uint32_t primitive_type = static_cast<uint32_t>(DataTypeToPrimitive(type));
+
+  // We do not need a read barrier when loading a reference only for loading a constant field
+  // through the reference.
+  __ movl(temp, Address(varhandle_object, var_type_offset));
+  __ MaybeUnpoisonHeapReference(temp);
+  __ cmpw(Address(temp, primitive_type_offset), Immediate(primitive_type));
+  __ j(kNotEqual, slow_path->GetEntryLabel());
+}
+
+static void GenerateVarHandleCommonChecks(HInvoke *invoke,
+                                          Register temp,
+                                          SlowPathCode* slow_path,
+                                          X86Assembler* assembler) {
+  LocationSummary* locations = invoke->GetLocations();
+  Register vh_object = locations->InAt(0).AsRegister<Register>();
+  mirror::VarHandle::AccessMode access_mode =
+      mirror::VarHandle::GetAccessModeByIntrinsic(invoke->GetIntrinsic());
+
+  GenerateVarHandleAccessModeCheck(vh_object,
+                                   access_mode,
+                                   slow_path,
+                                   assembler);
+
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  switch (expected_coordinates_count) {
+    case 0u:
+      GenerateVarHandleStaticFieldCheck(vh_object, slow_path, assembler);
+      break;
+    case 1u: {
+      Register object = locations->InAt(1).AsRegister<Register>();
+      GenerateVarHandleInstanceFieldObjectCheck(vh_object, object, temp, slow_path, assembler);
+      break;
+    }
+    default:
+      // Unimplemented
+      UNREACHABLE();
+  }
+
+  // Check the return type and varType parameters.
+  mirror::VarHandle::AccessModeTemplate access_mode_template =
+      mirror::VarHandle::GetAccessModeTemplate(access_mode);
+  DataType::Type type = invoke->GetType();
+
+  switch (access_mode_template) {
+    case mirror::VarHandle::AccessModeTemplate::kGet:
+      // Check the varType.primitiveType against the type we're trying to retrieve. Reference types
+      // are also checked later by a HCheckCast node as an additional check.
+      GenerateVarTypePrimitiveTypeCheck(vh_object, temp, type, slow_path, assembler);
+      break;
+    case mirror::VarHandle::AccessModeTemplate::kSet:
+    case mirror::VarHandle::AccessModeTemplate::kGetAndUpdate: {
+      uint32_t value_index = invoke->GetNumberOfArguments() - 1;
+      DataType::Type value_type = GetDataTypeFromShorty(invoke, value_index);
+
+      // Check the varType.primitiveType against the type of the value we're trying to set.
+      GenerateVarTypePrimitiveTypeCheck(vh_object, temp, value_type, slow_path, assembler);
+      if (value_type == DataType::Type::kReference) {
+        const uint32_t var_type_offset = mirror::VarHandle::VarTypeOffset().Uint32Value();
+
+        // If the value type is a reference, check it against the varType.
+        GenerateSubTypeObjectCheck(locations->InAt(value_index).AsRegister<Register>(),
+                                   temp,
+                                   Address(vh_object, var_type_offset),
+                                   slow_path,
+                                   assembler);
+      }
+      break;
+    }
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndSet:
+    case mirror::VarHandle::AccessModeTemplate::kCompareAndExchange: {
+      uint32_t new_value_index = invoke->GetNumberOfArguments() - 1;
+      uint32_t expected_value_index = invoke->GetNumberOfArguments() - 2;
+      DataType::Type value_type = GetDataTypeFromShorty(invoke, new_value_index);
+      DCHECK_EQ(value_type, GetDataTypeFromShorty(invoke, expected_value_index));
+
+      // Check the varType.primitiveType against the type of the expected value.
+      GenerateVarTypePrimitiveTypeCheck(vh_object, temp, value_type, slow_path, assembler);
+      if (value_type == DataType::Type::kReference) {
+        const uint32_t var_type_offset = mirror::VarHandle::VarTypeOffset().Uint32Value();
+
+        // If the value type is a reference, check both the expected and the new value against
+        // the varType.
+        GenerateSubTypeObjectCheck(locations->InAt(new_value_index).AsRegister<Register>(),
+                                   temp,
+                                   Address(vh_object, var_type_offset),
+                                   slow_path,
+                                   assembler);
+        GenerateSubTypeObjectCheck(locations->InAt(expected_value_index).AsRegister<Register>(),
+                                   temp,
+                                   Address(vh_object, var_type_offset),
+                                   slow_path,
+                                   assembler);
+      }
+      break;
+    }
+  }
+}
+
+// This method loads the field's address referred by a field VarHandle (base + offset).
+// The return value is the register containing object's reference (in case of an instance field)
+// or the declaring class (in case of a static field). The declaring class is stored in temp
+// register. Field's offset is loaded to the `offset` register.
+static Register GenerateVarHandleFieldReference(HInvoke* invoke,
+                                                CodeGeneratorX86* codegen,
+                                                Register temp,
+                                                /*out*/ Register offset) {
+  X86Assembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  const uint32_t artfield_offset = mirror::FieldVarHandle::ArtFieldOffset().Uint32Value();
+  const uint32_t offset_offset = ArtField::OffsetOffset().Uint32Value();
+  const uint32_t declaring_class_offset = ArtField::DeclaringClassOffset().Uint32Value();
+  Register varhandle_object = locations->InAt(0).AsRegister<Register>();
+
+  // Load the ArtField and the offset
+  __ movl(temp, Address(varhandle_object, artfield_offset));
+  __ movl(offset, Address(temp, offset_offset));
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (expected_coordinates_count == 0) {
+    // For static fields, load the declaring class
+    InstructionCodeGeneratorX86* instr_codegen =
+        down_cast<InstructionCodeGeneratorX86*>(codegen->GetInstructionVisitor());
+    instr_codegen->GenerateGcRootFieldLoad(invoke,
+                                           Location::RegisterLocation(temp),
+                                           Address(temp, declaring_class_offset),
+                                           /* fixup_label= */ nullptr,
+                                           kCompilerReadBarrierOption);
+    return temp;
+  }
+
+  // For instance fields, return the register containing the object.
+  DCHECK_EQ(expected_coordinates_count, 1u);
+
+  return locations->InAt(1).AsRegister<Register>();
+}
+
+static void CreateVarHandleGetLocations(HInvoke* invoke) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+    return;
+  }
+
+  if (!IsValidFieldVarHandleExpected(invoke)) {
+    return;
+  }
+
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations = new (allocator) LocationSummary(
+      invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->SetInAt(0, Location::RequiresRegister());
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (expected_coordinates_count == 1u) {
+    // For instance fields, this is the source object.
+    locations->SetInAt(1, Location::RequiresRegister());
+  }
+  locations->AddTemp(Location::RequiresRegister());
+
+  DataType::Type type = invoke->GetType();
+  switch (DataType::Kind(type)) {
+    case DataType::Type::kInt64:
+      locations->AddTemp(Location::RequiresRegister());
+      if (invoke->GetIntrinsic() != Intrinsics::kVarHandleGet) {
+        // We need an XmmRegister for Int64 to ensure an atomic load
+        locations->AddTemp(Location::RequiresFpuRegister());
+      }
+      FALLTHROUGH_INTENDED;
+    case DataType::Type::kInt32:
+    case DataType::Type::kReference:
+      locations->SetOut(Location::RequiresRegister());
+      break;
+    default:
+      DCHECK(DataType::IsFloatingPointType(type));
+      locations->AddTemp(Location::RequiresRegister());
+      locations->SetOut(Location::RequiresFpuRegister());
+  }
+}
+
+static void GenerateVarHandleGet(HInvoke* invoke, CodeGeneratorX86* codegen) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
+
+  X86Assembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  DataType::Type type = invoke->GetType();
+  DCHECK_NE(type, DataType::Type::kVoid);
+  Register temp = locations->GetTemp(0).AsRegister<Register>();
+  SlowPathCode* slow_path = new (codegen->GetScopedAllocator()) IntrinsicSlowPathX86(invoke);
+  codegen->AddSlowPath(slow_path);
+
+  GenerateVarHandleCommonChecks(invoke, temp, slow_path, assembler);
+
+  Location out = locations->Out();
+  // Use 'out' as a temporary register if it's a core register
+  Register offset =
+      out.IsRegister() ? out.AsRegister<Register>() : locations->GetTemp(1).AsRegister<Register>();
+
+  // Get the field referred by the VarHandle. The returned register contains the object reference
+  // or the declaring class. The field offset will be placed in 'offset'. For static fields, the
+  // declaring class will be placed in 'temp' register.
+  Register ref = GenerateVarHandleFieldReference(invoke, codegen, temp, offset);
+  Address field_addr(ref, offset, TIMES_1, 0);
+
+  // Load the value from the field
+  if (type == DataType::Type::kReference && kCompilerReadBarrierOption == kWithReadBarrier) {
+    codegen->GenerateReferenceLoadWithBakerReadBarrier(
+        invoke, out, ref, field_addr, /* needs_null_check= */ false);
+  } else if (type == DataType::Type::kInt64 &&
+             invoke->GetIntrinsic() != Intrinsics::kVarHandleGet) {
+    XmmRegister xmm_temp = locations->GetTemp(2).AsFpuRegister<XmmRegister>();
+    codegen->LoadFromMemoryNoBarrier(type, out, field_addr, xmm_temp, /* is_atomic_load= */ true);
+  } else {
+    codegen->LoadFromMemoryNoBarrier(type, out, field_addr);
+  }
+
+  if (invoke->GetIntrinsic() == Intrinsics::kVarHandleGetVolatile ||
+      invoke->GetIntrinsic() == Intrinsics::kVarHandleGetAcquire) {
+    // Load fence to prevent load-load reordering.
+    // Note that this is a no-op, thanks to the x86 memory model.
+    codegen->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
+  }
+
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGet(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGet(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetVolatile(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetVolatile(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAcquire(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAcquire(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetOpaque(HInvoke* invoke) {
+  CreateVarHandleGetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetOpaque(HInvoke* invoke) {
+  GenerateVarHandleGet(invoke, codegen_);
+}
+
+static void CreateVarHandleSetLocations(HInvoke* invoke) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+    return;
+  }
+
+  if (!IsValidFieldVarHandleExpected(invoke)) {
+    return;
+  }
+
+  // The last argument should be the value we intend to set.
+  uint32_t value_index = invoke->GetNumberOfArguments() - 1;
+  HInstruction* value = invoke->InputAt(value_index);
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, value_index);
+  bool needs_atomicity = invoke->GetIntrinsic() != Intrinsics::kVarHandleSet;
+  if (value_type == DataType::Type::kInt64 && (!value->IsConstant() || needs_atomicity)) {
+    // We avoid the case of a non-constant (or volatile) Int64 value because we would need to
+    // place it in a register pair. If the slow path is taken, the ParallelMove might fail to move
+    // the pair according to the X86DexCallingConvention in case of an overlap (e.g., move the
+    // int64 value from <EAX, EBX> to <EBX, ECX>). (Bug: b/168687887)
+    return;
+  }
+
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations = new (allocator) LocationSummary(
+      invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->SetInAt(0, Location::RequiresRegister());
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (expected_coordinates_count == 1u) {
+    // For instance fields, this is the source object
+    locations->SetInAt(1, Location::RequiresRegister());
+  }
+
+  switch (value_type) {
+    case DataType::Type::kBool:
+    case DataType::Type::kInt8:
+    case DataType::Type::kUint8:
+      // Ensure the value is in a byte register
+      locations->SetInAt(value_index, Location::ByteRegisterOrConstant(EBX, value));
+      break;
+    case DataType::Type::kInt16:
+    case DataType::Type::kUint16:
+    case DataType::Type::kInt32:
+      locations->SetInAt(value_index, Location::RegisterOrConstant(value));
+      break;
+    case DataType::Type::kInt64:
+      // We only handle constant non-atomic int64 values.
+      DCHECK(value->IsConstant());
+      locations->SetInAt(value_index, Location::ConstantLocation(value->AsConstant()));
+      break;
+    case DataType::Type::kReference:
+      locations->SetInAt(value_index, Location::RequiresRegister());
+      break;
+    default:
+      DCHECK(DataType::IsFloatingPointType(value_type));
+      if (needs_atomicity && value_type == DataType::Type::kFloat64) {
+        locations->SetInAt(value_index, Location::RequiresFpuRegister());
+      } else {
+        locations->SetInAt(value_index, Location::FpuRegisterOrConstant(value));
+      }
+  }
+
+  locations->AddTemp(Location::RequiresRegister());
+  // This temporary register is also used for card for MarkGCCard. Make sure it's a byte register
+  locations->AddTemp(Location::RegisterLocation(EAX));
+  if (expected_coordinates_count == 0 && value_type == DataType::Type::kReference) {
+    // For static reference fields, we need another temporary for the declaring class. We set it
+    // last because we want to make sure that the first 2 temps are reserved for HandleFieldSet.
+    locations->AddTemp(Location::RequiresRegister());
+  }
+}
+
+static void GenerateVarHandleSet(HInvoke* invoke, CodeGeneratorX86* codegen) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
+
+  X86Assembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  // The value we want to set is the last argument
+  uint32_t value_index = invoke->GetNumberOfArguments() - 1;
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, value_index);
+  Register temp = locations->GetTemp(0).AsRegister<Register>();
+  Register temp2 = locations->GetTemp(1).AsRegister<Register>();
+  SlowPathCode* slow_path = new (codegen->GetScopedAllocator()) IntrinsicSlowPathX86(invoke);
+  codegen->AddSlowPath(slow_path);
+
+  GenerateVarHandleCommonChecks(invoke, temp, slow_path, assembler);
+
+  // For static reference fields, we need another temporary for the declaring class. But since
+  // for instance fields the object is in a separate register, it is safe to use the first
+  // temporary register for GenerateVarHandleFieldReference.
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (value_type == DataType::Type::kReference && expected_coordinates_count == 0) {
+    temp = locations->GetTemp(2).AsRegister<Register>();
+  }
+
+  Register offset = temp2;
+  // Get the field referred by the VarHandle. The returned register contains the object reference
+  // or the declaring class. The field offset will be placed in 'offset'. For static fields, the
+  // declaring class will be placed in 'temp' register.
+  Register reference = GenerateVarHandleFieldReference(invoke, codegen, temp, offset);
+
+  bool is_volatile = false;
+  switch (invoke->GetIntrinsic()) {
+    case Intrinsics::kVarHandleSet:
+    case Intrinsics::kVarHandleSetOpaque:
+      // The only constraint for setOpaque is to ensure bitwise atomicity (atomically set 64 bit
+      // values), but we don't treat Int64 values because we would need to place it in a register
+      // pair. If the slow path is taken, the Parallel move might fail to move the register pair
+      // in case of an overlap (e.g., move from <EAX, EBX> to <EBX, ECX>). (Bug: b/168687887)
+      break;
+    case Intrinsics::kVarHandleSetRelease:
+      // setRelease needs to ensure atomicity too. See the above comment.
+      codegen->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
+      break;
+    case Intrinsics::kVarHandleSetVolatile:
+      is_volatile = true;
+      break;
+    default:
+      LOG(FATAL) << "GenerateVarHandleSet received non-set intrinsic " << invoke->GetIntrinsic();
+  }
+
+  InstructionCodeGeneratorX86* instr_codegen =
+        down_cast<InstructionCodeGeneratorX86*>(codegen->GetInstructionVisitor());
+  // Store the value to the field
+  instr_codegen->HandleFieldSet(invoke,
+                                value_index,
+                                value_type,
+                                Address(reference, offset, TIMES_1, 0),
+                                reference,
+                                is_volatile,
+                                /* value_can_be_null */ true);
+
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleSet(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleSet(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleSetVolatile(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleSetVolatile(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleSetRelease(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleSetRelease(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleSetOpaque(HInvoke* invoke) {
+  CreateVarHandleSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleSetOpaque(HInvoke* invoke) {
+  GenerateVarHandleSet(invoke, codegen_);
+}
+
+static void CreateVarHandleGetAndSetLocations(HInvoke* invoke) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+    return;
+  }
+
+  if (!IsValidFieldVarHandleExpected(invoke)) {
+    return;
+  }
+
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  uint32_t value_index = number_of_arguments - 1;
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, value_index);
+
+  if (DataType::Is64BitType(value_type)) {
+    // We avoid the case of an Int64/Float64 value because we would need to place it in a register
+    // pair. If the slow path is taken, the ParallelMove might fail to move the pair according to
+    // the X86DexCallingConvention in case of an overlap (e.g., move the 64 bit value from
+    // <EAX, EBX> to <EBX, ECX>).
+    return;
+  }
+
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations = new (allocator) LocationSummary(
+      invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->AddTemp(Location::RequiresRegister());
+  locations->AddTemp(Location::RequiresRegister());
+  // We use this temporary for the card, so we need a byte register
+  locations->AddTemp(Location::RegisterLocation(EBX));
+  locations->SetInAt(0, Location::RequiresRegister());
+  if (GetExpectedVarHandleCoordinatesCount(invoke) == 1u) {
+    // For instance fields, this is the source object
+    locations->SetInAt(1, Location::RequiresRegister());
+  } else {
+    // For static fields, we need another temp because one will be busy with the declaring class.
+    locations->AddTemp(Location::RequiresRegister());
+  }
+  if (value_type == DataType::Type::kFloat32) {
+    locations->AddTemp(Location::RegisterLocation(EAX));
+    locations->SetInAt(value_index, Location::FpuRegisterOrConstant(invoke->InputAt(value_index)));
+    locations->SetOut(Location::RequiresFpuRegister());
+  } else {
+    locations->SetInAt(value_index, Location::RegisterLocation(EAX));
+    locations->SetOut(Location::RegisterLocation(EAX));
+  }
+}
+
+static void GenerateVarHandleGetAndSet(HInvoke* invoke, CodeGeneratorX86* codegen) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
+
+  X86Assembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  // The value we want to set is the last argument
+  uint32_t value_index = invoke->GetNumberOfArguments() - 1;
+  Location value = locations->InAt(value_index);
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, value_index);
+  Register temp = locations->GetTemp(1).AsRegister<Register>();
+  Register temp2 = locations->GetTemp(2).AsRegister<Register>();
+  SlowPathCode* slow_path = new (codegen->GetScopedAllocator()) IntrinsicSlowPathX86(invoke);
+  codegen->AddSlowPath(slow_path);
+
+  GenerateVarHandleCommonChecks(invoke, temp, slow_path, assembler);
+
+  Register offset = locations->GetTemp(0).AsRegister<Register>();
+  // Get the field referred by the VarHandle. The returned register contains the object reference
+  // or the declaring class. The field offset will be placed in 'offset'. For static fields, the
+  // declaring class will be placed in 'temp' register.
+  Register reference = GenerateVarHandleFieldReference(invoke, codegen, temp, offset);
+  Address field_addr(reference, offset, TIMES_1, 0);
+
+  if (invoke->GetIntrinsic() == Intrinsics::kVarHandleGetAndSetRelease) {
+    codegen->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
+  }
+
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  // For static fields, we need another temporary for the declaring class. But since for instance
+  // fields the object is in a separate register, it is safe to use the first temporary register.
+  temp = expected_coordinates_count == 1u ? temp : locations->GetTemp(3).AsRegister<Register>();
+  // No need for a lock prefix. `xchg` has an implicit lock when it is used with an address.
+  switch (value_type) {
+    case DataType::Type::kBool:
+      __ xchgb(value.AsRegister<ByteRegister>(), field_addr);
+      __ movzxb(locations->Out().AsRegister<Register>(),
+                locations->Out().AsRegister<ByteRegister>());
+      break;
+    case DataType::Type::kInt8:
+      __ xchgb(value.AsRegister<ByteRegister>(), field_addr);
+      __ movsxb(locations->Out().AsRegister<Register>(),
+                locations->Out().AsRegister<ByteRegister>());
+      break;
+    case DataType::Type::kUint16:
+      __ xchgw(value.AsRegister<Register>(), field_addr);
+      __ movzxw(locations->Out().AsRegister<Register>(), locations->Out().AsRegister<Register>());
+      break;
+    case DataType::Type::kInt16:
+      __ xchgw(value.AsRegister<Register>(), field_addr);
+      __ movsxw(locations->Out().AsRegister<Register>(), locations->Out().AsRegister<Register>());
+      break;
+    case DataType::Type::kInt32:
+      __ xchgl(value.AsRegister<Register>(), field_addr);
+      break;
+    case DataType::Type::kFloat32:
+      codegen->Move32(Location::RegisterLocation(EAX), value);
+      __ xchgl(EAX, field_addr);
+      __ movd(locations->Out().AsFpuRegister<XmmRegister>(), EAX);
+      break;
+    case DataType::Type::kReference: {
+      if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+        // Need to make sure the reference stored in the field is a to-space
+        // one before attempting the CAS or the CAS could fail incorrectly.
+        codegen->GenerateReferenceLoadWithBakerReadBarrier(
+            invoke,
+            // Unused, used only as a "temporary" within the read barrier.
+            Location::RegisterLocation(temp),
+            reference,
+            field_addr,
+            /* needs_null_check= */ false,
+            /* always_update_field= */ true,
+            &temp2);
+      }
+      codegen->MarkGCCard(
+          temp, temp2, reference, value.AsRegister<Register>(), /* value_can_be_null= */ false);
+      if (kPoisonHeapReferences) {
+        __ movl(temp, value.AsRegister<Register>());
+        __ PoisonHeapReference(temp);
+        __ xchgl(temp, field_addr);
+        __ UnpoisonHeapReference(temp);
+        __ movl(locations->Out().AsRegister<Register>(), temp);
+      } else {
+        __ xchgl(locations->Out().AsRegister<Register>(), field_addr);
+      }
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+
+  if (invoke->GetIntrinsic() == Intrinsics::kVarHandleGetAndSetAcquire) {
+    codegen->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
+  }
+
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndSet(HInvoke* invoke) {
+  CreateVarHandleGetAndSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndSet(HInvoke* invoke) {
+  GenerateVarHandleGetAndSet(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndSetAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndSetAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndSet(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndSetRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndSetLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndSetRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndSet(invoke, codegen_);
+}
+
+static void CreateVarHandleCompareAndSetOrExchangeLocations(HInvoke* invoke) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+    return;
+  }
+
+  if (!IsValidFieldVarHandleExpected(invoke)) {
+    return;
+  }
+
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  uint32_t expected_value_index = number_of_arguments - 2;
+  uint32_t new_value_index = number_of_arguments - 1;
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, expected_value_index);
+  DCHECK_EQ(value_type, GetDataTypeFromShorty(invoke, new_value_index));
+
+  if (DataType::Is64BitType(value_type)) {
+    // We avoid the case of an Int64/Float64 value because we would need to place it in a register
+    // pair. If the slow path is taken, the ParallelMove might fail to move the pair according to
+    // the X86DexCallingConvention in case of an overlap (e.g., move the 64 bit value from
+    // <EAX, EBX> to <EBX, ECX>).
+    return;
+  }
+
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations = new (allocator) LocationSummary(
+      invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->AddTemp(Location::RequiresRegister());
+  locations->AddTemp(Location::RequiresRegister());
+  // We use this temporary for the card, so we need a byte register
+  locations->AddTemp(Location::RegisterLocation(EBX));
+  locations->SetInAt(0, Location::RequiresRegister());
+  if (GetExpectedVarHandleCoordinatesCount(invoke) == 1u) {
+    // For instance fields, this is the source object
+    locations->SetInAt(1, Location::RequiresRegister());
+  } else {
+    // For static fields, we need another temp because one will be busy with the declaring class.
+    locations->AddTemp(Location::RequiresRegister());
+  }
+  if (DataType::IsFloatingPointType(value_type)) {
+    // We need EAX for placing the expected value
+    locations->AddTemp(Location::RegisterLocation(EAX));
+    locations->SetInAt(new_value_index,
+                       Location::FpuRegisterOrConstant(invoke->InputAt(new_value_index)));
+    locations->SetInAt(expected_value_index,
+                       Location::FpuRegisterOrConstant(invoke->InputAt(expected_value_index)));
+  } else {
+    // Ensure it's in a byte register
+    locations->SetInAt(new_value_index, Location::RegisterLocation(ECX));
+    locations->SetInAt(expected_value_index, Location::RegisterLocation(EAX));
+  }
+
+  mirror::VarHandle::AccessModeTemplate access_mode_template =
+      mirror::VarHandle::GetAccessModeTemplateByIntrinsic(invoke->GetIntrinsic());
+
+  if (access_mode_template == mirror::VarHandle::AccessModeTemplate::kCompareAndExchange &&
+      value_type == DataType::Type::kFloat32) {
+    locations->SetOut(Location::RequiresFpuRegister());
+  } else {
+    locations->SetOut(Location::RegisterLocation(EAX));
+  }
+}
+
+static void GenerateVarHandleCompareAndSetOrExchange(HInvoke* invoke, CodeGeneratorX86* codegen) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
+
+  X86Assembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  uint32_t expected_value_index = number_of_arguments - 2;
+  uint32_t new_value_index = number_of_arguments - 1;
+  DataType::Type type = GetDataTypeFromShorty(invoke, expected_value_index);
+  DCHECK_EQ(type, GetDataTypeFromShorty(invoke, new_value_index));
+  Location expected_value = locations->InAt(expected_value_index);
+  Location new_value = locations->InAt(new_value_index);
+  Register offset = locations->GetTemp(0).AsRegister<Register>();
+  Register temp = locations->GetTemp(1).AsRegister<Register>();
+  Register temp2 = locations->GetTemp(2).AsRegister<Register>();
+  SlowPathCode* slow_path = new (codegen->GetScopedAllocator()) IntrinsicSlowPathX86(invoke);
+  codegen->AddSlowPath(slow_path);
+
+  GenerateVarHandleCommonChecks(invoke, temp, slow_path, assembler);
+
+  // Get the field referred by the VarHandle. The returned register contains the object reference
+  // or the declaring class. The field offset will be placed in 'offset'. For static fields, the
+  // declaring class will be placed in 'temp' register.
+  Register reference = GenerateVarHandleFieldReference(invoke, codegen, temp, offset);
+
+  uint32_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  // For generating the compare and exchange, we need 2 temporaries. In case of a static field, the
+  // first temporary contains the declaring class so we need another temporary. In case of an
+  // instance field, the object comes in a separate register so it's safe to use the first temp.
+  temp = (expected_coordinates_count == 1u) ? temp : locations->GetTemp(3).AsRegister<Register>();
+  DCHECK_NE(temp, reference);
+
+  // We are using `lock cmpxchg` in all cases because there is no CAS equivalent that has weak
+  // failure semantics. `lock cmpxchg` has full barrier semantics, and we don't need scheduling
+  // barriers at this time.
+
+  mirror::VarHandle::AccessModeTemplate access_mode_template =
+      mirror::VarHandle::GetAccessModeTemplateByIntrinsic(invoke->GetIntrinsic());
+  bool is_cmpxchg =
+      access_mode_template == mirror::VarHandle::AccessModeTemplate::kCompareAndExchange;
+
+  if (type == DataType::Type::kReference) {
+    GenReferenceCAS(
+        invoke, codegen, expected_value, new_value, reference, offset, temp, temp2, is_cmpxchg);
+  } else {
+    Location out = locations->Out();
+    GenPrimitiveCAS(
+        type, codegen, expected_value, new_value, reference, offset, out, temp, is_cmpxchg);
+  }
+
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleCompareAndSet(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleCompareAndSet(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleWeakCompareAndSet(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleWeakCompareAndSet(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleWeakCompareAndSetPlain(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleWeakCompareAndSetPlain(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleWeakCompareAndSetAcquire(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleWeakCompareAndSetAcquire(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleWeakCompareAndSetRelease(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleWeakCompareAndSetRelease(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleCompareAndExchange(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleCompareAndExchange(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleCompareAndExchangeAcquire(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleCompareAndExchangeAcquire(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleCompareAndExchangeRelease(HInvoke* invoke) {
+  CreateVarHandleCompareAndSetOrExchangeLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleCompareAndExchangeRelease(HInvoke* invoke) {
+  GenerateVarHandleCompareAndSetOrExchange(invoke, codegen_);
+}
+
+static void CreateVarHandleGetAndAddLocations(HInvoke* invoke) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+    return;
+  }
+
+  if (!IsValidFieldVarHandleExpected(invoke)) {
+    return;
+  }
+
+  // The last argument should be the value we intend to set.
+  uint32_t value_index = invoke->GetNumberOfArguments() - 1;
+  DataType::Type value_type = GetDataTypeFromShorty(invoke, value_index);
+  if (DataType::Is64BitType(value_type)) {
+    // We avoid the case of an Int64/Float64 value because we would need to place it in a register
+    // pair. If the slow path is taken, the ParallelMove might fail to move the pair according to
+    // the X86DexCallingConvention in case of an overlap (e.g., move the 64 bit value from
+    // <EAX, EBX> to <EBX, ECX>). (Bug: b/168687887)
+    return;
+  }
+
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations = new (allocator) LocationSummary(
+      invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->AddTemp(Location::RequiresRegister());
+  locations->AddTemp(Location::RequiresRegister());
+  locations->SetInAt(0, Location::RequiresRegister());
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (expected_coordinates_count == 1u) {
+    // For instance fields, this is the source object
+    locations->SetInAt(1, Location::RequiresRegister());
+  } else {
+    // For static fields, we need another temp because one will be busy with the declaring class.
+    locations->AddTemp(Location::RequiresRegister());
+  }
+
+  if (DataType::IsFloatingPointType(value_type)) {
+    locations->AddTemp(Location::RequiresFpuRegister());
+    locations->AddTemp(Location::RegisterLocation(EAX));
+    locations->SetInAt(value_index, Location::RequiresFpuRegister());
+    locations->SetOut(Location::RequiresFpuRegister());
+  } else {
+    // xadd updates the register argument with the old value. ByteRegister required for xaddb.
+    locations->SetInAt(value_index, Location::RegisterLocation(EAX));
+    locations->SetOut(Location::RegisterLocation(EAX));
+  }
+}
+
+static void GenerateVarHandleGetAndAdd(HInvoke* invoke, CodeGeneratorX86* codegen) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
+
+  X86Assembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  uint32_t number_of_arguments = invoke->GetNumberOfArguments();
+  uint32_t value_index = number_of_arguments - 1;
+  DataType::Type type = GetDataTypeFromShorty(invoke, value_index);
+  DCHECK_EQ(type, invoke->GetType());
+  Location value_loc = locations->InAt(value_index);
+  Register temp = locations->GetTemp(0).AsRegister<Register>();
+  SlowPathCode* slow_path = new (codegen->GetScopedAllocator()) IntrinsicSlowPathX86(invoke);
+  codegen->AddSlowPath(slow_path);
+
+  GenerateVarHandleCommonChecks(invoke, temp, slow_path, assembler);
+
+  Register offset = locations->GetTemp(1).AsRegister<Register>();
+  // Get the field referred by the VarHandle. The returned register contains the object reference
+  // or the declaring class. The field offset will be placed in 'offset'. For static fields, the
+  // declaring class will be placed in 'temp' register.
+  Register reference = GenerateVarHandleFieldReference(invoke, codegen, temp, offset);
+
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  temp = (expected_coordinates_count == 1u) ? temp : locations->GetTemp(2).AsRegister<Register>();
+  DCHECK_NE(temp, reference);
+  Address field_addr(reference, offset, TIMES_1, 0);
+
+  switch (type) {
+    case DataType::Type::kInt8:
+      __ LockXaddb(field_addr, value_loc.AsRegister<ByteRegister>());
+      __ movsxb(locations->Out().AsRegister<Register>(),
+                locations->Out().AsRegister<ByteRegister>());
+      break;
+    case DataType::Type::kInt16:
+      __ LockXaddw(field_addr, value_loc.AsRegister<Register>());
+      __ movsxw(locations->Out().AsRegister<Register>(), locations->Out().AsRegister<Register>());
+      break;
+    case DataType::Type::kUint16:
+      __ LockXaddw(field_addr, value_loc.AsRegister<Register>());
+      __ movzxw(locations->Out().AsRegister<Register>(), locations->Out().AsRegister<Register>());
+      break;
+    case DataType::Type::kInt32:
+      __ LockXaddl(field_addr, value_loc.AsRegister<Register>());
+      break;
+    case DataType::Type::kFloat32: {
+      Location temp_float =
+          (expected_coordinates_count == 1u) ? locations->GetTemp(2) : locations->GetTemp(3);
+      DCHECK(temp_float.IsFpuRegister());
+      Location eax = Location::RegisterLocation(EAX);
+      NearLabel try_again;
+      __ Bind(&try_again);
+      __ movss(temp_float.AsFpuRegister<XmmRegister>(), field_addr);
+      __ movd(EAX, temp_float.AsFpuRegister<XmmRegister>());
+      __ addss(temp_float.AsFpuRegister<XmmRegister>(),
+               value_loc.AsFpuRegister<XmmRegister>());
+      GenPrimitiveLockedCmpxchg(type,
+                                codegen,
+                                /* expected_value= */ eax,
+                                /* new_value= */ temp_float,
+                                reference,
+                                offset,
+                                temp);
+      __ j(kNotZero, &try_again);
+
+      // The old value is present in EAX.
+      codegen->Move32(locations->Out(), eax);
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndAdd(HInvoke* invoke) {
+  CreateVarHandleGetAndAddLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndAdd(HInvoke* invoke) {
+  GenerateVarHandleGetAndAdd(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndAddAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndAddLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndAddAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndAdd(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndAddRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndAddLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndAddRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndAdd(invoke, codegen_);
+}
+
+static void CreateVarHandleGetAndBitwiseOpLocations(HInvoke* invoke) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+    return;
+  }
+
+  if (!IsValidFieldVarHandleExpected(invoke)) {
+    return;
+  }
+
+  // The last argument should be the value we intend to set.
+  uint32_t value_index = invoke->GetNumberOfArguments() - 1;
+  if (DataType::Is64BitType(GetDataTypeFromShorty(invoke, value_index))) {
+    // We avoid the case of an Int64 value because we would need to place it in a register pair.
+    // If the slow path is taken, the ParallelMove might fail to move the pair according to the
+    // X86DexCallingConvention in case of an overlap (e.g., move the 64 bit value from
+    // <EAX, EBX> to <EBX, ECX>). (Bug: b/168687887)
+    return;
+  }
+
+  ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+  LocationSummary* locations = new (allocator) LocationSummary(
+      invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  // We need a byte register temp to store the result of the bitwise operation
+  locations->AddTemp(Location::RegisterLocation(EBX));
+  locations->AddTemp(Location::RequiresRegister());
+  locations->SetInAt(0, Location::RequiresRegister());
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  if (expected_coordinates_count == 1u) {
+    // For instance fields, this is the source object
+    locations->SetInAt(1, Location::RequiresRegister());
+  } else {
+    // For static fields, we need another temp because one will be busy with the declaring class.
+    locations->AddTemp(Location::RequiresRegister());
+  }
+
+  locations->SetInAt(value_index, Location::RegisterOrConstant(invoke->InputAt(value_index)));
+  locations->SetOut(Location::RegisterLocation(EAX));
+}
+
+static void GenerateBitwiseOp(HInvoke* invoke,
+                              CodeGeneratorX86* codegen,
+                              Register left,
+                              Register right) {
+  X86Assembler* assembler = codegen->GetAssembler();
+
+  switch (invoke->GetIntrinsic()) {
+    case Intrinsics::kVarHandleGetAndBitwiseOr:
+    case Intrinsics::kVarHandleGetAndBitwiseOrAcquire:
+    case Intrinsics::kVarHandleGetAndBitwiseOrRelease:
+      __ orl(left, right);
+      break;
+    case Intrinsics::kVarHandleGetAndBitwiseXor:
+    case Intrinsics::kVarHandleGetAndBitwiseXorAcquire:
+    case Intrinsics::kVarHandleGetAndBitwiseXorRelease:
+      __ xorl(left, right);
+      break;
+    case Intrinsics::kVarHandleGetAndBitwiseAnd:
+    case Intrinsics::kVarHandleGetAndBitwiseAndAcquire:
+    case Intrinsics::kVarHandleGetAndBitwiseAndRelease:
+      __ andl(left, right);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+static void GenerateVarHandleGetAndBitwiseOp(HInvoke* invoke, CodeGeneratorX86* codegen) {
+  // The only read barrier implementation supporting the
+  // VarHandleGet intrinsic is the Baker-style read barriers.
+  DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
+
+  X86Assembler* assembler = codegen->GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  uint32_t value_index = invoke->GetNumberOfArguments() - 1;
+  DataType::Type type = GetDataTypeFromShorty(invoke, value_index);
+  DCHECK_EQ(type, invoke->GetType());
+  Register temp = locations->GetTemp(0).AsRegister<Register>();
+  SlowPathCode* slow_path = new (codegen->GetScopedAllocator()) IntrinsicSlowPathX86(invoke);
+  codegen->AddSlowPath(slow_path);
+
+  GenerateVarHandleCommonChecks(invoke, temp, slow_path, assembler);
+
+  Register offset = locations->GetTemp(1).AsRegister<Register>();
+  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+  // For static field, we need another temporary because the first one contains the declaring class
+  Register reference =
+      (expected_coordinates_count == 1u) ? temp : locations->GetTemp(2).AsRegister<Register>();
+  // Get the field referred by the VarHandle. The returned register contains the object reference
+  // or the declaring class. The field offset will be placed in 'offset'. For static fields, the
+  // declaring class will be placed in 'reference' register.
+  reference = GenerateVarHandleFieldReference(invoke, codegen, reference, offset);
+  DCHECK_NE(temp, reference);
+  Address field_addr(reference, offset, TIMES_1, 0);
+
+  Register out = locations->Out().AsRegister<Register>();
+  DCHECK_EQ(out, EAX);
+
+  if (invoke->GetIntrinsic() == Intrinsics::kVarHandleGetAndBitwiseOrRelease ||
+      invoke->GetIntrinsic() == Intrinsics::kVarHandleGetAndBitwiseXorRelease ||
+      invoke->GetIntrinsic() == Intrinsics::kVarHandleGetAndBitwiseAndRelease) {
+    codegen->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
+  }
+
+  NearLabel try_again;
+  __ Bind(&try_again);
+  // Place the expected value in EAX for cmpxchg
+  codegen->LoadFromMemoryNoBarrier(type, locations->Out(), field_addr);
+  codegen->Move32(locations->GetTemp(0), locations->InAt(value_index));
+  GenerateBitwiseOp(invoke, codegen, temp, out);
+  GenPrimitiveLockedCmpxchg(type,
+                            codegen,
+                            /* expected_value= */ locations->Out(),
+                            /* new_value= */ locations->GetTemp(0),
+                            reference,
+                            offset);
+  // If the cmpxchg failed, another thread changed the value so try again.
+  __ j(kNotZero, &try_again);
+
+  // The old value is present in EAX.
+
+  if (invoke->GetIntrinsic() == Intrinsics::kVarHandleGetAndBitwiseOrAcquire ||
+      invoke->GetIntrinsic() == Intrinsics::kVarHandleGetAndBitwiseXorAcquire ||
+      invoke->GetIntrinsic() == Intrinsics::kVarHandleGetAndBitwiseAndAcquire) {
+    codegen->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
+  }
+
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndBitwiseOr(HInvoke* invoke) {
+  CreateVarHandleGetAndBitwiseOpLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndBitwiseOr(HInvoke* invoke) {
+  GenerateVarHandleGetAndBitwiseOp(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndBitwiseOrAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndBitwiseOpLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndBitwiseOrAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndBitwiseOp(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndBitwiseOrRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndBitwiseOpLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndBitwiseOrRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndBitwiseOp(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndBitwiseXor(HInvoke* invoke) {
+  CreateVarHandleGetAndBitwiseOpLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndBitwiseXor(HInvoke* invoke) {
+  GenerateVarHandleGetAndBitwiseOp(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndBitwiseXorAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndBitwiseOpLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndBitwiseXorAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndBitwiseOp(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndBitwiseXorRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndBitwiseOpLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndBitwiseXorRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndBitwiseOp(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndBitwiseAnd(HInvoke* invoke) {
+  CreateVarHandleGetAndBitwiseOpLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndBitwiseAnd(HInvoke* invoke) {
+  GenerateVarHandleGetAndBitwiseOp(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndBitwiseAndAcquire(HInvoke* invoke) {
+  CreateVarHandleGetAndBitwiseOpLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndBitwiseAndAcquire(HInvoke* invoke) {
+  GenerateVarHandleGetAndBitwiseOp(invoke, codegen_);
+}
+
+void IntrinsicLocationsBuilderX86::VisitVarHandleGetAndBitwiseAndRelease(HInvoke* invoke) {
+  CreateVarHandleGetAndBitwiseOpLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitVarHandleGetAndBitwiseAndRelease(HInvoke* invoke) {
+  GenerateVarHandleGetAndBitwiseOp(invoke, codegen_);
+}
+
 UNIMPLEMENTED_INTRINSIC(X86, MathRoundDouble)
-UNIMPLEMENTED_INTRINSIC(X86, ReferenceGetReferent)
 UNIMPLEMENTED_INTRINSIC(X86, FloatIsInfinite)
 UNIMPLEMENTED_INTRINSIC(X86, DoubleIsInfinite)
 UNIMPLEMENTED_INTRINSIC(X86, IntegerHighestOneBit)
 UNIMPLEMENTED_INTRINSIC(X86, LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(X86, LongDivideUnsigned)
 UNIMPLEMENTED_INTRINSIC(X86, CRC32Update)
 UNIMPLEMENTED_INTRINSIC(X86, CRC32UpdateBytes)
 UNIMPLEMENTED_INTRINSIC(X86, CRC32UpdateByteBuffer)
@@ -3090,6 +4613,7 @@
 UNIMPLEMENTED_INTRINSIC(X86, FP16GreaterEquals)
 UNIMPLEMENTED_INTRINSIC(X86, FP16Less)
 UNIMPLEMENTED_INTRINSIC(X86, FP16LessEquals)
+UNIMPLEMENTED_INTRINSIC(X86, MathMultiplyHigh)
 
 UNIMPLEMENTED_INTRINSIC(X86, StringStringIndexOf);
 UNIMPLEMENTED_INTRINSIC(X86, StringStringIndexOfAfter);
@@ -3116,6 +4640,9 @@
 UNIMPLEMENTED_INTRINSIC(X86, UnsafeGetAndSetLong)
 UNIMPLEMENTED_INTRINSIC(X86, UnsafeGetAndSetObject)
 
+UNIMPLEMENTED_INTRINSIC(X86, MethodHandleInvokeExact)
+UNIMPLEMENTED_INTRINSIC(X86, MethodHandleInvoke)
+
 UNREACHABLE_INTRINSICS(X86)
 
 #undef __
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 0f6b006..6351181 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -61,11 +61,6 @@
   return res->Intrinsified();
 }
 
-static void MoveArguments(HInvoke* invoke, CodeGeneratorX86_64* codegen) {
-  InvokeDexCallingConventionVisitorX86_64 calling_convention_visitor;
-  IntrinsicVisitor::MoveArguments(invoke, codegen, &calling_convention_visitor);
-}
-
 using IntrinsicSlowPathX86_64 = IntrinsicSlowPath<InvokeDexCallingConventionVisitorX86_64>;
 
 // NOLINT on __ macro to suppress wrong warning/fix (misc-macro-parentheses) from clang-tidy.
@@ -255,52 +250,23 @@
   GetAssembler()->sqrtsd(out, in);
 }
 
-static void InvokeOutOfLineIntrinsic(CodeGeneratorX86_64* codegen, HInvoke* invoke) {
-  MoveArguments(invoke, codegen);
-
-  DCHECK(invoke->IsInvokeStaticOrDirect());
-  codegen->GenerateStaticOrDirectCall(
-      invoke->AsInvokeStaticOrDirect(), Location::RegisterLocation(RDI));
-
-  // Copy the result back to the expected output.
-  Location out = invoke->GetLocations()->Out();
-  if (out.IsValid()) {
-    DCHECK(out.IsRegister());
-    codegen->MoveFromReturnRegister(out, invoke->GetType());
-  }
-}
-
 static void CreateSSE41FPToFPLocations(ArenaAllocator* allocator,
                                        HInvoke* invoke,
                                        CodeGeneratorX86_64* codegen) {
   // Do we have instruction support?
-  if (codegen->GetInstructionSetFeatures().HasSSE4_1()) {
-    CreateFPToFPLocations(allocator, invoke);
+  if (!codegen->GetInstructionSetFeatures().HasSSE4_1()) {
     return;
   }
 
-  // We have to fall back to a call to the intrinsic.
-  LocationSummary* locations =
-      new (allocator) LocationSummary(invoke, LocationSummary::kCallOnMainOnly);
-  InvokeRuntimeCallingConvention calling_convention;
-  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetFpuRegisterAt(0)));
-  locations->SetOut(Location::FpuRegisterLocation(XMM0));
-  // Needs to be RDI for the invoke.
-  locations->AddTemp(Location::RegisterLocation(RDI));
+  CreateFPToFPLocations(allocator, invoke);
 }
 
-static void GenSSE41FPToFPIntrinsic(CodeGeneratorX86_64* codegen,
-                                   HInvoke* invoke,
-                                   X86_64Assembler* assembler,
-                                   int round_mode) {
+static void GenSSE41FPToFPIntrinsic(HInvoke* invoke, X86_64Assembler* assembler, int round_mode) {
   LocationSummary* locations = invoke->GetLocations();
-  if (locations->WillCall()) {
-    InvokeOutOfLineIntrinsic(codegen, invoke);
-  } else {
-    XmmRegister in = locations->InAt(0).AsFpuRegister<XmmRegister>();
-    XmmRegister out = locations->Out().AsFpuRegister<XmmRegister>();
-    __ roundsd(out, in, Immediate(round_mode));
-  }
+  DCHECK(!locations->WillCall());
+  XmmRegister in = locations->InAt(0).AsFpuRegister<XmmRegister>();
+  XmmRegister out = locations->Out().AsFpuRegister<XmmRegister>();
+  __ roundsd(out, in, Immediate(round_mode));
 }
 
 void IntrinsicLocationsBuilderX86_64::VisitMathCeil(HInvoke* invoke) {
@@ -308,7 +274,7 @@
 }
 
 void IntrinsicCodeGeneratorX86_64::VisitMathCeil(HInvoke* invoke) {
-  GenSSE41FPToFPIntrinsic(codegen_, invoke, GetAssembler(), 2);
+  GenSSE41FPToFPIntrinsic(invoke, GetAssembler(), 2);
 }
 
 void IntrinsicLocationsBuilderX86_64::VisitMathFloor(HInvoke* invoke) {
@@ -316,7 +282,7 @@
 }
 
 void IntrinsicCodeGeneratorX86_64::VisitMathFloor(HInvoke* invoke) {
-  GenSSE41FPToFPIntrinsic(codegen_, invoke, GetAssembler(), 1);
+  GenSSE41FPToFPIntrinsic(invoke, GetAssembler(), 1);
 }
 
 void IntrinsicLocationsBuilderX86_64::VisitMathRint(HInvoke* invoke) {
@@ -324,31 +290,23 @@
 }
 
 void IntrinsicCodeGeneratorX86_64::VisitMathRint(HInvoke* invoke) {
-  GenSSE41FPToFPIntrinsic(codegen_, invoke, GetAssembler(), 0);
+  GenSSE41FPToFPIntrinsic(invoke, GetAssembler(), 0);
 }
 
 static void CreateSSE41FPToIntLocations(ArenaAllocator* allocator,
                                         HInvoke* invoke,
                                         CodeGeneratorX86_64* codegen) {
   // Do we have instruction support?
-  if (codegen->GetInstructionSetFeatures().HasSSE4_1()) {
-    LocationSummary* locations =
-        new (allocator) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
-    locations->SetInAt(0, Location::RequiresFpuRegister());
-    locations->SetOut(Location::RequiresRegister());
-    locations->AddTemp(Location::RequiresFpuRegister());
-    locations->AddTemp(Location::RequiresFpuRegister());
+  if (!codegen->GetInstructionSetFeatures().HasSSE4_1()) {
     return;
   }
 
-  // We have to fall back to a call to the intrinsic.
   LocationSummary* locations =
-      new (allocator) LocationSummary(invoke, LocationSummary::kCallOnMainOnly);
-  InvokeRuntimeCallingConvention calling_convention;
-  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetFpuRegisterAt(0)));
-  locations->SetOut(Location::RegisterLocation(RAX));
-  // Needs to be RDI for the invoke.
-  locations->AddTemp(Location::RegisterLocation(RDI));
+      new (allocator) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+  locations->SetInAt(0, Location::RequiresFpuRegister());
+  locations->SetOut(Location::RequiresRegister());
+  locations->AddTemp(Location::RequiresFpuRegister());
+  locations->AddTemp(Location::RequiresFpuRegister());
 }
 
 void IntrinsicLocationsBuilderX86_64::VisitMathRoundFloat(HInvoke* invoke) {
@@ -357,10 +315,7 @@
 
 void IntrinsicCodeGeneratorX86_64::VisitMathRoundFloat(HInvoke* invoke) {
   LocationSummary* locations = invoke->GetLocations();
-  if (locations->WillCall()) {
-    InvokeOutOfLineIntrinsic(codegen_, invoke);
-    return;
-  }
+  DCHECK(!locations->WillCall());
 
   XmmRegister in = locations->InAt(0).AsFpuRegister<XmmRegister>();
   CpuRegister out = locations->Out().AsRegister<CpuRegister>();
@@ -401,10 +356,7 @@
 
 void IntrinsicCodeGeneratorX86_64::VisitMathRoundDouble(HInvoke* invoke) {
   LocationSummary* locations = invoke->GetLocations();
-  if (locations->WillCall()) {
-    InvokeOutOfLineIntrinsic(codegen_, invoke);
-    return;
-  }
+  DCHECK(!locations->WillCall());
 
   XmmRegister in = locations->InAt(0).AsFpuRegister<XmmRegister>();
   CpuRegister out = locations->Out().AsRegister<CpuRegister>();
@@ -446,12 +398,7 @@
   locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0)));
   locations->SetOut(Location::FpuRegisterLocation(XMM0));
 
-  // We have to ensure that the native code doesn't clobber the XMM registers which are
-  // non-volatile for ART, but volatile for Native calls.  This will ensure that they are
-  // saved in the prologue and properly restored.
-  for (FloatRegister fp_reg : non_volatile_xmm_regs) {
-    locations->AddTemp(Location::FpuRegisterLocation(fp_reg));
-  }
+  CodeGeneratorX86_64::BlockNonVolatileXmmRegisters(locations);
 }
 
 static void GenFPToFPCall(HInvoke* invoke, CodeGeneratorX86_64* codegen,
@@ -583,12 +530,7 @@
   locations->SetInAt(1, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(1)));
   locations->SetOut(Location::FpuRegisterLocation(XMM0));
 
-  // We have to ensure that the native code doesn't clobber the XMM registers which are
-  // non-volatile for ART, but volatile for Native calls.  This will ensure that they are
-  // saved in the prologue and properly restored.
-  for (FloatRegister fp_reg : non_volatile_xmm_regs) {
-    locations->AddTemp(Location::FpuRegisterLocation(fp_reg));
-  }
+  CodeGeneratorX86_64::BlockNonVolatileXmmRegisters(locations);
 }
 
 void IntrinsicLocationsBuilderX86_64::VisitMathAtan2(HInvoke* invoke) {
@@ -2674,6 +2616,11 @@
   CpuRegister out = locations->Out().AsRegister<CpuRegister>();
   InvokeRuntimeCallingConvention calling_convention;
   CpuRegister argument = CpuRegister(calling_convention.GetRegisterAt(0));
+  auto allocate_instance = [&]() {
+    codegen_->LoadIntrinsicDeclaringClass(argument, invoke);
+    codegen_->InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
+    CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
+  };
   if (invoke->InputAt(0)->IsIntConstant()) {
     int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
     if (static_cast<uint32_t>(value - info.low) < info.length) {
@@ -2685,8 +2632,7 @@
       // Allocate and initialize a new j.l.Integer.
       // TODO: If we JIT, we could allocate the j.l.Integer now, and store it in the
       // JIT object table.
-      codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
-                                             info.integer_boot_image_offset);
+      allocate_instance();
       __ movl(Address(out, info.value_offset), Immediate(value));
     }
   } else {
@@ -2707,13 +2653,120 @@
     __ jmp(&done);
     __ Bind(&allocate);
     // Otherwise allocate and initialize a new j.l.Integer.
-    codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
-                                           info.integer_boot_image_offset);
+    allocate_instance();
     __ movl(Address(out, info.value_offset), in);
     __ Bind(&done);
   }
 }
 
+void IntrinsicLocationsBuilderX86_64::VisitReferenceGetReferent(HInvoke* invoke) {
+  IntrinsicVisitor::CreateReferenceGetReferentLocations(invoke, codegen_);
+}
+
+void IntrinsicCodeGeneratorX86_64::VisitReferenceGetReferent(HInvoke* invoke) {
+  X86_64Assembler* assembler = GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+
+  Location obj = locations->InAt(0);
+  Location out = locations->Out();
+
+  SlowPathCode* slow_path = new (GetAllocator()) IntrinsicSlowPathX86_64(invoke);
+  codegen_->AddSlowPath(slow_path);
+
+  if (kEmitCompilerReadBarrier) {
+    // Check self->GetWeakRefAccessEnabled().
+    ThreadOffset64 offset = Thread::WeakRefAccessEnabledOffset<kX86_64PointerSize>();
+    __ gs()->cmpl(Address::Absolute(offset, /* no_rip= */ true), Immediate(0));
+    __ j(kEqual, slow_path->GetEntryLabel());
+  }
+
+  // Load the java.lang.ref.Reference class, use the output register as a temporary.
+  codegen_->LoadIntrinsicDeclaringClass(out.AsRegister<CpuRegister>(), invoke);
+
+  // Check static fields java.lang.ref.Reference.{disableIntrinsic,slowPathEnabled} together.
+  MemberOffset disable_intrinsic_offset = IntrinsicVisitor::GetReferenceDisableIntrinsicOffset();
+  DCHECK_ALIGNED(disable_intrinsic_offset.Uint32Value(), 2u);
+  DCHECK_EQ(disable_intrinsic_offset.Uint32Value() + 1u,
+            IntrinsicVisitor::GetReferenceSlowPathEnabledOffset().Uint32Value());
+  __ cmpw(Address(out.AsRegister<CpuRegister>(), disable_intrinsic_offset.Uint32Value()),
+          Immediate(0));
+  __ j(kNotEqual, slow_path->GetEntryLabel());
+
+  // Load the value from the field.
+  uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+  if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+    codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+                                                    out,
+                                                    obj.AsRegister<CpuRegister>(),
+                                                    referent_offset,
+                                                    /*needs_null_check=*/ true);
+    // Note that the fence is a no-op, thanks to the x86-64 memory model.
+    codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);  // `referent` is volatile.
+  } else {
+    __ movl(out.AsRegister<CpuRegister>(), Address(obj.AsRegister<CpuRegister>(), referent_offset));
+    codegen_->MaybeRecordImplicitNullCheck(invoke);
+    // Note that the fence is a no-op, thanks to the x86-64 memory model.
+    codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);  // `referent` is volatile.
+    codegen_->MaybeGenerateReadBarrierSlow(invoke, out, out, obj, referent_offset);
+  }
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderX86_64::VisitReferenceRefersTo(HInvoke* invoke) {
+  IntrinsicVisitor::CreateReferenceRefersToLocations(invoke);
+}
+
+void IntrinsicCodeGeneratorX86_64::VisitReferenceRefersTo(HInvoke* invoke) {
+  X86_64Assembler* assembler = GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+
+  CpuRegister obj = locations->InAt(0).AsRegister<CpuRegister>();
+  CpuRegister other = locations->InAt(1).AsRegister<CpuRegister>();
+  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
+
+  uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+  uint32_t monitor_offset = mirror::Object::MonitorOffset().Int32Value();
+
+  __ movl(out, Address(obj, referent_offset));
+  codegen_->MaybeRecordImplicitNullCheck(invoke);
+  __ MaybeUnpoisonHeapReference(out);
+  // Note that the fence is a no-op, thanks to the x86-64 memory model.
+  codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);  // `referent` is volatile.
+
+  __ cmpl(out, other);
+
+  if (kEmitCompilerReadBarrier) {
+    DCHECK(kUseBakerReadBarrier);
+
+    NearLabel calculate_result;
+    __ j(kEqual, &calculate_result);  // ZF set if taken.
+
+    // Check if the loaded reference is null in a way that leaves ZF clear for null.
+    __ cmpl(out, Immediate(1));
+    __ j(kBelow, &calculate_result);  // ZF clear if taken.
+
+    // For correct memory visibility, we need a barrier before loading the lock word
+    // but we already have the barrier emitted for volatile load above which is sufficient.
+
+    // Load the lockword and check if it is a forwarding address.
+    static_assert(LockWord::kStateShift == 30u);
+    static_assert(LockWord::kStateForwardingAddress == 3u);
+    __ movl(out, Address(out, monitor_offset));
+    __ cmpl(out, Immediate(static_cast<int32_t>(0xc0000000)));
+    __ j(kBelow, &calculate_result);   // ZF clear if taken.
+
+    // Extract the forwarding address and compare with `other`.
+    __ shll(out, Immediate(LockWord::kForwardingAddressShift));
+    __ cmpl(out, other);
+
+    __ Bind(&calculate_result);
+  }
+
+  // Convert ZF into the Boolean result.
+  __ setcc(kEqual, out);
+  __ movzxb(out, out);
+}
+
 void IntrinsicLocationsBuilderX86_64::VisitThreadInterrupted(HInvoke* invoke) {
   LocationSummary* locations =
       new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
@@ -2742,7 +2795,63 @@
 
 void IntrinsicCodeGeneratorX86_64::VisitReachabilityFence(HInvoke* invoke ATTRIBUTE_UNUSED) { }
 
-UNIMPLEMENTED_INTRINSIC(X86_64, ReferenceGetReferent)
+void IntrinsicLocationsBuilderX86_64::VisitIntegerDivideUnsigned(HInvoke* invoke) {
+  LocationSummary* locations =
+      new (allocator_) LocationSummary(invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+  locations->SetInAt(0, Location::RegisterLocation(RAX));
+  locations->SetInAt(1, Location::RequiresRegister());
+  locations->SetOut(Location::SameAsFirstInput());
+  // Intel uses edx:eax as the dividend.
+  locations->AddTemp(Location::RegisterLocation(RDX));
+}
+
+void IntrinsicCodeGeneratorX86_64::VisitIntegerDivideUnsigned(HInvoke* invoke) {
+  X86_64Assembler* assembler = GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+  Location out = locations->Out();
+  Location first = locations->InAt(0);
+  Location second = locations->InAt(1);
+  CpuRegister rdx = locations->GetTemp(0).AsRegister<CpuRegister>();
+  CpuRegister second_reg = second.AsRegister<CpuRegister>();
+
+  DCHECK_EQ(RAX, first.AsRegister<Register>());
+  DCHECK_EQ(RAX, out.AsRegister<Register>());
+  DCHECK_EQ(RDX, rdx.AsRegister());
+
+  // Check if divisor is zero, bail to managed implementation to handle.
+  __ testl(second_reg, second_reg);
+  SlowPathCode* slow_path = new (codegen_->GetScopedAllocator()) IntrinsicSlowPathX86_64(invoke);
+  codegen_->AddSlowPath(slow_path);
+  __ j(kEqual, slow_path->GetEntryLabel());
+
+  __ xorl(rdx, rdx);
+  __ divl(second_reg);
+
+  __ Bind(slow_path->GetExitLabel());
+}
+
+void IntrinsicLocationsBuilderX86_64::VisitMathMultiplyHigh(HInvoke* invoke) {
+  LocationSummary* locations =
+      new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+  locations->SetInAt(0, Location::RegisterLocation(RAX));
+  locations->SetInAt(1, Location::RequiresRegister());
+  locations->SetOut(Location::RegisterLocation(RDX));
+  locations->AddTemp(Location::RegisterLocation(RAX));
+}
+
+void IntrinsicCodeGeneratorX86_64::VisitMathMultiplyHigh(HInvoke* invoke) {
+  X86_64Assembler* assembler = GetAssembler();
+  LocationSummary* locations = invoke->GetLocations();
+
+  CpuRegister y = locations->InAt(1).AsRegister<CpuRegister>();
+
+  DCHECK_EQ(locations->InAt(0).AsRegister<Register>(), RAX);
+  DCHECK_EQ(locations->Out().AsRegister<Register>(), RDX);
+
+  __ imulq(y);
+}
+
+
 UNIMPLEMENTED_INTRINSIC(X86_64, FloatIsInfinite)
 UNIMPLEMENTED_INTRINSIC(X86_64, DoubleIsInfinite)
 UNIMPLEMENTED_INTRINSIC(X86_64, CRC32Update)
@@ -2757,6 +2866,7 @@
 UNIMPLEMENTED_INTRINSIC(X86_64, FP16GreaterEquals)
 UNIMPLEMENTED_INTRINSIC(X86_64, FP16Less)
 UNIMPLEMENTED_INTRINSIC(X86_64, FP16LessEquals)
+UNIMPLEMENTED_INTRINSIC(X86_64, LongDivideUnsigned)
 
 UNIMPLEMENTED_INTRINSIC(X86_64, StringStringIndexOf);
 UNIMPLEMENTED_INTRINSIC(X86_64, StringStringIndexOfAfter);
@@ -2783,6 +2893,40 @@
 UNIMPLEMENTED_INTRINSIC(X86_64, UnsafeGetAndSetLong)
 UNIMPLEMENTED_INTRINSIC(X86_64, UnsafeGetAndSetObject)
 
+UNIMPLEMENTED_INTRINSIC(X86_64, MethodHandleInvokeExact)
+UNIMPLEMENTED_INTRINSIC(X86_64, MethodHandleInvoke)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleCompareAndExchange)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleCompareAndExchangeAcquire)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleCompareAndExchangeRelease)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleCompareAndSet)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGet)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAcquire)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndAdd)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndAddAcquire)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndAddRelease)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndBitwiseAnd)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndBitwiseAndAcquire)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndBitwiseAndRelease)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndBitwiseOr)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndBitwiseOrAcquire)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndBitwiseOrRelease)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndBitwiseXor)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndBitwiseXorAcquire)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndBitwiseXorRelease)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndSet)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndSetAcquire)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetAndSetRelease)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetOpaque)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleGetVolatile)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleSet)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleSetOpaque)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleSetRelease)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleSetVolatile)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleWeakCompareAndSet)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleWeakCompareAndSetAcquire)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleWeakCompareAndSetPlain)
+UNIMPLEMENTED_INTRINSIC(X86_64, VarHandleWeakCompareAndSetRelease)
+
 UNREACHABLE_INTRINSICS(X86_64)
 
 #undef __
diff --git a/compiler/optimizing/linearize_test.cc b/compiler/optimizing/linearize_test.cc
index 50bfe84..d56ae11 100644
--- a/compiler/optimizing/linearize_test.cc
+++ b/compiler/optimizing/linearize_test.cc
@@ -41,7 +41,9 @@
 void LinearizeTest::TestCode(const std::vector<uint16_t>& data,
                              const uint32_t (&expected_order)[number_of_blocks]) {
   HGraph* graph = CreateCFG(data);
-  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
+  std::unique_ptr<CompilerOptions> compiler_options =
+      CommonCompilerTest::CreateCompilerOptions(kRuntimeISA, "default");
+  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options);
   SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
   liveness.Analyze();
 
diff --git a/compiler/optimizing/live_ranges_test.cc b/compiler/optimizing/live_ranges_test.cc
index 60f513c..bb8a4dc 100644
--- a/compiler/optimizing/live_ranges_test.cc
+++ b/compiler/optimizing/live_ranges_test.cc
@@ -28,12 +28,15 @@
 namespace art {
 
 class LiveRangesTest : public OptimizingUnitTest {
- public:
+ protected:
   HGraph* BuildGraph(const std::vector<uint16_t>& data);
+
+  std::unique_ptr<CompilerOptions> compiler_options_;
 };
 
 HGraph* LiveRangesTest::BuildGraph(const std::vector<uint16_t>& data) {
   HGraph* graph = CreateCFG(data);
+  compiler_options_ = CommonCompilerTest::CreateCompilerOptions(kRuntimeISA, "default");
   // Suspend checks implementation may change in the future, and this test relies
   // on how instructions are ordered.
   RemoveSuspendChecks(graph);
diff --git a/compiler/optimizing/liveness_test.cc b/compiler/optimizing/liveness_test.cc
index f11f7a9..ba3787e 100644
--- a/compiler/optimizing/liveness_test.cc
+++ b/compiler/optimizing/liveness_test.cc
@@ -47,8 +47,10 @@
 void LivenessTest::TestCode(const std::vector<uint16_t>& data, const char* expected) {
   HGraph* graph = CreateCFG(data);
   // `Inline` conditions into ifs.
-  PrepareForRegisterAllocation(graph, *compiler_options_).Run();
-  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
+  std::unique_ptr<CompilerOptions> compiler_options =
+      CommonCompilerTest::CreateCompilerOptions(kRuntimeISA, "default");
+  PrepareForRegisterAllocation(graph, *compiler_options).Run();
+  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options);
   SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
   liveness.Analyze();
 
diff --git a/compiler/optimizing/load_store_analysis.cc b/compiler/optimizing/load_store_analysis.cc
index 7d7bb94..3fe42af 100644
--- a/compiler/optimizing/load_store_analysis.cc
+++ b/compiler/optimizing/load_store_analysis.cc
@@ -16,6 +16,9 @@
 
 #include "load_store_analysis.h"
 
+#include "base/scoped_arena_allocator.h"
+#include "optimizing/escape.h"
+
 namespace art {
 
 // A cap for the number of heap locations to prevent pathological time/space consumption.
@@ -30,10 +33,6 @@
   return std::max(l1, l2) <= std::min(h1, h2);
 }
 
-static bool IsAddOrSub(const HInstruction* instruction) {
-  return instruction->IsAdd() || instruction->IsSub();
-}
-
 static bool CanBinaryOpAndIndexAlias(const HBinaryOperation* idx1,
                                      const size_t vector_length1,
                                      const HInstruction* idx2,
@@ -92,6 +91,123 @@
   return CanIntegerRangesOverlap(l1, h1, l2, h2);
 }
 
+// Make sure we mark any writes/potential writes to heap-locations within partially
+// escaped values as escaping.
+void ReferenceInfo::PrunePartialEscapeWrites() {
+  DCHECK(subgraph_ != nullptr);
+  if (!subgraph_->IsValid()) {
+    // All paths escape.
+    return;
+  }
+  HGraph* graph = reference_->GetBlock()->GetGraph();
+  ArenaBitVector additional_exclusions(
+      allocator_, graph->GetBlocks().size(), false, kArenaAllocLSA);
+  for (const HUseListNode<HInstruction*>& use : reference_->GetUses()) {
+    const HInstruction* user = use.GetUser();
+    if (!additional_exclusions.IsBitSet(user->GetBlock()->GetBlockId()) &&
+        subgraph_->ContainsBlock(user->GetBlock()) &&
+        (user->IsUnresolvedInstanceFieldSet() || user->IsUnresolvedStaticFieldSet() ||
+         user->IsInstanceFieldSet() || user->IsStaticFieldSet() || user->IsArraySet()) &&
+        (reference_ == user->InputAt(0)) &&
+        std::any_of(subgraph_->UnreachableBlocks().begin(),
+                    subgraph_->UnreachableBlocks().end(),
+                    [&](const HBasicBlock* excluded) -> bool {
+                      return reference_->GetBlock()->GetGraph()->PathBetween(excluded,
+                                                                             user->GetBlock());
+                    })) {
+      // This object had memory written to it somewhere, if it escaped along
+      // some paths prior to the current block this write also counts as an
+      // escape.
+      additional_exclusions.SetBit(user->GetBlock()->GetBlockId());
+    }
+  }
+  if (UNLIKELY(additional_exclusions.IsAnyBitSet())) {
+    for (uint32_t exc : additional_exclusions.Indexes()) {
+      subgraph_->RemoveBlock(graph->GetBlocks()[exc]);
+    }
+  }
+}
+
+bool HeapLocationCollector::InstructionEligibleForLSERemoval(HInstruction* inst) const {
+  if (inst->IsNewInstance()) {
+    return !inst->AsNewInstance()->NeedsChecks();
+  } else if (inst->IsNewArray()) {
+    HInstruction* array_length = inst->AsNewArray()->GetLength();
+    bool known_array_length =
+        array_length->IsIntConstant() && array_length->AsIntConstant()->GetValue() >= 0;
+    return known_array_length &&
+           std::all_of(inst->GetUses().cbegin(),
+                       inst->GetUses().cend(),
+                       [&](const HUseListNode<HInstruction*>& user) {
+                         if (user.GetUser()->IsArrayGet() || user.GetUser()->IsArraySet()) {
+                           return user.GetUser()->InputAt(1)->IsIntConstant();
+                         }
+                         return true;
+                       });
+  } else {
+    return false;
+  }
+}
+
+void ReferenceInfo::CollectPartialEscapes(HGraph* graph) {
+  ScopedArenaAllocator saa(graph->GetArenaStack());
+  ArenaBitVector seen_instructions(&saa, graph->GetCurrentInstructionId(), false, kArenaAllocLSA);
+  // Get regular escapes.
+  ScopedArenaVector<HInstruction*> additional_escape_vectors(saa.Adapter(kArenaAllocLSA));
+  LambdaEscapeVisitor scan_instructions([&](HInstruction* escape) -> bool {
+    HandleEscape(escape);
+    // LSE can't track heap-locations through Phi and Select instructions so we
+    // need to assume all escapes from these are escapes for the base reference.
+    if ((escape->IsPhi() || escape->IsSelect()) && !seen_instructions.IsBitSet(escape->GetId())) {
+      seen_instructions.SetBit(escape->GetId());
+      additional_escape_vectors.push_back(escape);
+    }
+    return true;
+  });
+  additional_escape_vectors.push_back(reference_);
+  while (!additional_escape_vectors.empty()) {
+    HInstruction* ref = additional_escape_vectors.back();
+    additional_escape_vectors.pop_back();
+    DCHECK(ref == reference_ || ref->IsPhi() || ref->IsSelect()) << *ref;
+    VisitEscapes(ref, scan_instructions);
+  }
+
+  // Mark irreducible loop headers as escaping since they cannot be tracked through.
+  for (HBasicBlock* blk : graph->GetActiveBlocks()) {
+    if (blk->IsLoopHeader() && blk->GetLoopInformation()->IsIrreducible()) {
+      HandleEscape(blk);
+    }
+  }
+}
+
+void HeapLocationCollector::DumpReferenceStats(OptimizingCompilerStats* stats) {
+  if (stats == nullptr) {
+    return;
+  }
+  std::vector<bool> seen_instructions(GetGraph()->GetCurrentInstructionId(), false);
+  for (auto hl : heap_locations_) {
+    auto ri = hl->GetReferenceInfo();
+    if (ri == nullptr || seen_instructions[ri->GetReference()->GetId()]) {
+      continue;
+    }
+    auto instruction = ri->GetReference();
+    seen_instructions[instruction->GetId()] = true;
+    if (ri->IsSingletonAndRemovable()) {
+      if (InstructionEligibleForLSERemoval(instruction)) {
+        MaybeRecordStat(stats, MethodCompilationStat::kFullLSEPossible);
+      }
+    }
+    // TODO This is an estimate of the number of allocations we will be able
+    // to (partially) remove. As additional work is done this can be refined.
+    if (ri->IsPartialSingleton() && instruction->IsNewInstance() &&
+        ri->GetNoEscapeSubgraph()->ContainsBlock(instruction->GetBlock()) &&
+        !ri->GetNoEscapeSubgraph()->GetExcludedCohorts().empty() &&
+        InstructionEligibleForLSERemoval(instruction)) {
+      MaybeRecordStat(stats, MethodCompilationStat::kPartialLSEPossible);
+    }
+  }
+}
+
 bool HeapLocationCollector::CanArrayElementsAlias(const HInstruction* idx1,
                                                   const size_t vector_length1,
                                                   const HInstruction* idx2,
@@ -176,6 +292,7 @@
   }
 
   heap_location_collector_.BuildAliasingMatrix();
+  heap_location_collector_.DumpReferenceStats(stats_);
   return true;
 }
 
diff --git a/compiler/optimizing/load_store_analysis.h b/compiler/optimizing/load_store_analysis.h
index 08d9309..4975bae 100644
--- a/compiler/optimizing/load_store_analysis.h
+++ b/compiler/optimizing/load_store_analysis.h
@@ -17,27 +17,72 @@
 #ifndef ART_COMPILER_OPTIMIZING_LOAD_STORE_ANALYSIS_H_
 #define ART_COMPILER_OPTIMIZING_LOAD_STORE_ANALYSIS_H_
 
+#include "base/arena_allocator.h"
+#include "base/arena_bit_vector.h"
+#include "base/bit_vector-inl.h"
+#include "base/scoped_arena_allocator.h"
+#include "base/scoped_arena_containers.h"
+#include "base/stl_util.h"
 #include "escape.h"
+#include "execution_subgraph.h"
 #include "nodes.h"
-#include "optimization.h"
+#include "optimizing/optimizing_compiler_stats.h"
 
 namespace art {
 
+enum class LoadStoreAnalysisType {
+  kBasic,
+  kNoPredicatedInstructions,
+  kFull,
+};
+
 // A ReferenceInfo contains additional info about a reference such as
 // whether it's a singleton, returned, etc.
-class ReferenceInfo : public ArenaObject<kArenaAllocLSA> {
+class ReferenceInfo : public DeletableArenaObject<kArenaAllocLSA> {
  public:
-  ReferenceInfo(HInstruction* reference, size_t pos)
+  ReferenceInfo(HInstruction* reference,
+                ScopedArenaAllocator* allocator,
+                size_t pos,
+                LoadStoreAnalysisType elimination_type)
       : reference_(reference),
         position_(pos),
         is_singleton_(true),
         is_singleton_and_not_returned_(true),
-        is_singleton_and_not_deopt_visible_(true) {
+        is_singleton_and_not_deopt_visible_(true),
+        allocator_(allocator),
+        subgraph_(nullptr) {
+    // TODO We can do this in one pass.
+    // TODO NewArray is possible but will need to get a handle on how to deal with the dynamic loads
+    // for now just ignore it.
+    bool can_be_partial = elimination_type != LoadStoreAnalysisType::kBasic &&
+                          (/* reference_->IsNewArray() || */ reference_->IsNewInstance());
+    if (can_be_partial) {
+      subgraph_.reset(
+          new (allocator) ExecutionSubgraph(reference->GetBlock()->GetGraph(), allocator));
+      CollectPartialEscapes(reference_->GetBlock()->GetGraph());
+    }
     CalculateEscape(reference_,
                     nullptr,
                     &is_singleton_,
                     &is_singleton_and_not_returned_,
                     &is_singleton_and_not_deopt_visible_);
+    if (can_be_partial) {
+      if (elimination_type == LoadStoreAnalysisType::kNoPredicatedInstructions) {
+        // This is to mark writes to partially escaped values as also part of the escaped subset.
+        // TODO We can avoid this if we have a 'ConditionalWrite' instruction. Will require testing
+        //      to see if the additional branches are worth it.
+        PrunePartialEscapeWrites();
+      }
+      DCHECK(subgraph_ != nullptr);
+      subgraph_->Finalize();
+    } else {
+      DCHECK(subgraph_ == nullptr);
+    }
+  }
+
+  const ExecutionSubgraph* GetNoEscapeSubgraph() const {
+    DCHECK(IsPartialSingleton());
+    return subgraph_.get();
   }
 
   HInstruction* GetReference() const {
@@ -55,6 +100,16 @@
     return is_singleton_;
   }
 
+  // This is a singleton and there are paths that don't escape the method
+  bool IsPartialSingleton() const {
+    auto ref = GetReference();
+    // TODO NewArray is possible but will need to get a handle on how to deal with the dynamic loads
+    // for now just ignore it.
+    return (/* ref->IsNewArray() || */ ref->IsNewInstance()) &&
+           subgraph_ != nullptr &&
+           subgraph_->IsValid();
+  }
+
   // Returns true if reference_ is a singleton and not returned to the caller or
   // used as an environment local of an HDeoptimize instruction.
   // The allocation and stores into reference_ may be eliminated for such cases.
@@ -70,6 +125,19 @@
   }
 
  private:
+  void CollectPartialEscapes(HGraph* graph);
+  void HandleEscape(HBasicBlock* escape) {
+    DCHECK(subgraph_ != nullptr);
+    subgraph_->RemoveBlock(escape);
+  }
+  void HandleEscape(HInstruction* escape) {
+    HandleEscape(escape->GetBlock());
+  }
+
+  // Make sure we mark any writes/potential writes to heap-locations within partially
+  // escaped values as escaping.
+  void PrunePartialEscapeWrites();
+
   HInstruction* const reference_;
   const size_t position_;  // position in HeapLocationCollector's ref_info_array_.
 
@@ -80,6 +148,10 @@
   // Is singleton and not used as an environment local of HDeoptimize.
   bool is_singleton_and_not_deopt_visible_;
 
+  ScopedArenaAllocator* allocator_;
+
+  std::unique_ptr<ExecutionSubgraph> subgraph_;
+
   DISALLOW_COPY_AND_ASSIGN(ReferenceInfo);
 };
 
@@ -105,16 +177,10 @@
         index_(index),
         vector_length_(vector_length),
         declaring_class_def_index_(declaring_class_def_index),
-        value_killed_by_loop_side_effects_(true),
         has_aliased_locations_(false) {
     DCHECK(ref_info != nullptr);
     DCHECK((offset == kInvalidFieldOffset && index != nullptr) ||
            (offset != kInvalidFieldOffset && index == nullptr));
-    if (ref_info->IsSingleton() && !IsArray()) {
-      // Assume this location's value cannot be killed by loop side effects
-      // until proven otherwise.
-      value_killed_by_loop_side_effects_ = false;
-    }
   }
 
   ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
@@ -133,14 +199,6 @@
     return index_ != nullptr;
   }
 
-  bool IsValueKilledByLoopSideEffects() const {
-    return value_killed_by_loop_side_effects_;
-  }
-
-  void SetValueKilledByLoopSideEffects(bool val) {
-    value_killed_by_loop_side_effects_ = val;
-  }
-
   bool HasAliasedLocations() const {
     return has_aliased_locations_;
   }
@@ -169,12 +227,6 @@
   // Invalid when this HeapLocation is not field access.
   const int16_t declaring_class_def_index_;
 
-  // Value of this location may be killed by loop side effects
-  // because this location is stored into inside a loop.
-  // This gives better info on whether a singleton's location
-  // value may be killed by loop side effects.
-  bool value_killed_by_loop_side_effects_;
-
   // Has aliased heap locations in the method, due to either the
   // reference is aliased or the array element is aliased via different
   // index names.
@@ -192,23 +244,37 @@
   // aliasing matrix of 8 heap locations.
   static constexpr uint32_t kInitialAliasingMatrixBitVectorSize = 32;
 
-  explicit HeapLocationCollector(HGraph* graph)
+  HeapLocationCollector(HGraph* graph,
+                        ScopedArenaAllocator* allocator,
+                        LoadStoreAnalysisType lse_type)
       : HGraphVisitor(graph),
-        ref_info_array_(graph->GetAllocator()->Adapter(kArenaAllocLSA)),
-        heap_locations_(graph->GetAllocator()->Adapter(kArenaAllocLSA)),
-        aliasing_matrix_(graph->GetAllocator(),
-                         kInitialAliasingMatrixBitVectorSize,
-                         true,
-                         kArenaAllocLSA),
+        allocator_(allocator),
+        ref_info_array_(allocator->Adapter(kArenaAllocLSA)),
+        heap_locations_(allocator->Adapter(kArenaAllocLSA)),
+        aliasing_matrix_(allocator, kInitialAliasingMatrixBitVectorSize, true, kArenaAllocLSA),
         has_heap_stores_(false),
         has_volatile_(false),
-        has_monitor_operations_(false) {}
+        has_monitor_operations_(false),
+        lse_type_(lse_type) {
+    aliasing_matrix_.ClearAllBits();
+  }
+
+  ~HeapLocationCollector() {
+    CleanUp();
+  }
 
   void CleanUp() {
     heap_locations_.clear();
+    STLDeleteContainerPointers(ref_info_array_.begin(), ref_info_array_.end());
     ref_info_array_.clear();
   }
 
+  size_t CountPartialSingletons() const {
+    return std::count_if(ref_info_array_.begin(),
+                         ref_info_array_.end(),
+                         [](ReferenceInfo* ri) { return ri->IsPartialSingleton(); });
+  }
+
   size_t GetNumberOfHeapLocations() const {
     return heap_locations_.size();
   }
@@ -217,6 +283,11 @@
     return heap_locations_[index];
   }
 
+  size_t GetHeapLocationIndex(const HeapLocation* hl) const {
+    auto res = std::find(heap_locations_.cbegin(), heap_locations_.cend(), hl);
+    return std::distance(heap_locations_.cbegin(), res);
+  }
+
   HInstruction* HuntForOriginalReference(HInstruction* ref) const {
     // An original reference can be transformed by instructions like:
     //   i0 NewArray
@@ -318,6 +389,11 @@
     return kHeapLocationNotFound;
   }
 
+  bool InstructionEligibleForLSERemoval(HInstruction* inst) const;
+
+  // Get some estimated statistics based on our analysis.
+  void DumpReferenceStats(OptimizingCompilerStats* stats);
+
   // Returns true if heap_locations_[index1] and heap_locations_[index2] may alias.
   bool MayAlias(size_t index1, size_t index2) const {
     if (index1 < index2) {
@@ -348,20 +424,7 @@
     }
   }
 
- private:
-  // An allocation cannot alias with a name which already exists at the point
-  // of the allocation, such as a parameter or a load happening before the allocation.
-  bool MayAliasWithPreexistenceChecking(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
-    if (ref_info1->GetReference()->IsNewInstance() || ref_info1->GetReference()->IsNewArray()) {
-      // Any reference that can alias with the allocation must appear after it in the block/in
-      // the block's successors. In reverse post order, those instructions will be visited after
-      // the allocation.
-      return ref_info2->GetPosition() >= ref_info1->GetPosition();
-    }
-    return true;
-  }
-
-  bool CanReferencesAlias(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
+  static bool CanReferencesAlias(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) {
     if (ref_info1 == ref_info2) {
       return true;
     } else if (ref_info1->IsSingleton()) {
@@ -375,6 +438,19 @@
     return true;
   }
 
+ private:
+  // An allocation cannot alias with a name which already exists at the point
+  // of the allocation, such as a parameter or a load happening before the allocation.
+  static bool MayAliasWithPreexistenceChecking(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) {
+    if (ref_info1->GetReference()->IsNewInstance() || ref_info1->GetReference()->IsNewArray()) {
+      // Any reference that can alias with the allocation must appear after it in the block/in
+      // the block's successors. In reverse post order, those instructions will be visited after
+      // the allocation.
+      return ref_info2->GetPosition() >= ref_info1->GetPosition();
+    }
+    return true;
+  }
+
   bool CanArrayElementsAlias(const HInstruction* idx1,
                              const size_t vector_length1,
                              const HInstruction* idx2,
@@ -432,7 +508,7 @@
     ReferenceInfo* ref_info = FindReferenceInfoOf(instruction);
     if (ref_info == nullptr) {
       size_t pos = ref_info_array_.size();
-      ref_info = new (GetGraph()->GetAllocator()) ReferenceInfo(instruction, pos);
+      ref_info = new (allocator_) ReferenceInfo(instruction, allocator_, pos, lse_type_);
       ref_info_array_.push_back(ref_info);
     }
     return ref_info;
@@ -446,45 +522,43 @@
     GetOrCreateReferenceInfo(instruction);
   }
 
-  HeapLocation* GetOrCreateHeapLocation(HInstruction* ref,
-                                        DataType::Type type,
-                                        size_t offset,
-                                        HInstruction* index,
-                                        size_t vector_length,
-                                        int16_t declaring_class_def_index) {
+  void MaybeCreateHeapLocation(HInstruction* ref,
+                               DataType::Type type,
+                               size_t offset,
+                               HInstruction* index,
+                               size_t vector_length,
+                               int16_t declaring_class_def_index) {
     HInstruction* original_ref = HuntForOriginalReference(ref);
     ReferenceInfo* ref_info = GetOrCreateReferenceInfo(original_ref);
     size_t heap_location_idx = FindHeapLocationIndex(
         ref_info, type, offset, index, vector_length, declaring_class_def_index);
     if (heap_location_idx == kHeapLocationNotFound) {
-      HeapLocation* heap_loc = new (GetGraph()->GetAllocator())
+      HeapLocation* heap_loc = new (allocator_)
           HeapLocation(ref_info, type, offset, index, vector_length, declaring_class_def_index);
       heap_locations_.push_back(heap_loc);
-      return heap_loc;
     }
-    return heap_locations_[heap_location_idx];
   }
 
-  HeapLocation* VisitFieldAccess(HInstruction* ref, const FieldInfo& field_info) {
+  void VisitFieldAccess(HInstruction* ref, const FieldInfo& field_info) {
     if (field_info.IsVolatile()) {
       has_volatile_ = true;
     }
     DataType::Type type = field_info.GetFieldType();
     const uint16_t declaring_class_def_index = field_info.GetDeclaringClassDefIndex();
     const size_t offset = field_info.GetFieldOffset().SizeValue();
-    return GetOrCreateHeapLocation(ref,
-                                   type,
-                                   offset,
-                                   nullptr,
-                                   HeapLocation::kScalar,
-                                   declaring_class_def_index);
+    MaybeCreateHeapLocation(ref,
+                            type,
+                            offset,
+                            nullptr,
+                            HeapLocation::kScalar,
+                            declaring_class_def_index);
   }
 
   void VisitArrayAccess(HInstruction* array,
                         HInstruction* index,
                         DataType::Type type,
                         size_t vector_length) {
-    GetOrCreateHeapLocation(array,
+    MaybeCreateHeapLocation(array,
                             type,
                             HeapLocation::kInvalidFieldOffset,
                             index,
@@ -492,35 +566,18 @@
                             HeapLocation::kDeclaringClassDefIndexForArrays);
   }
 
+  void VisitPredicatedInstanceFieldGet(HPredicatedInstanceFieldGet* instruction) override {
+    VisitFieldAccess(instruction->GetTarget(), instruction->GetFieldInfo());
+    CreateReferenceInfoForReferenceType(instruction);
+  }
   void VisitInstanceFieldGet(HInstanceFieldGet* instruction) override {
     VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
     CreateReferenceInfoForReferenceType(instruction);
   }
 
   void VisitInstanceFieldSet(HInstanceFieldSet* instruction) override {
-    HeapLocation* location = VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
+    VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
     has_heap_stores_ = true;
-    if (location->GetReferenceInfo()->IsSingleton()) {
-      // A singleton's location value may be killed by loop side effects if it's
-      // defined before that loop, and it's stored into inside that loop.
-      HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
-      if (loop_info != nullptr) {
-        HInstruction* ref = location->GetReferenceInfo()->GetReference();
-        DCHECK(ref->IsNewInstance());
-        if (loop_info->IsDefinedOutOfTheLoop(ref)) {
-          // ref's location value may be killed by this loop's side effects.
-          location->SetValueKilledByLoopSideEffects(true);
-        } else {
-          // ref is defined inside this loop so this loop's side effects cannot
-          // kill its location value at the loop header since ref/its location doesn't
-          // exist yet at the loop header.
-        }
-      }
-    } else {
-      // For non-singletons, value_killed_by_loop_side_effects_ is inited to
-      // true.
-      DCHECK_EQ(location->IsValueKilledByLoopSideEffects(), true);
-    }
   }
 
   void VisitStaticFieldGet(HStaticFieldGet* instruction) override {
@@ -584,32 +641,43 @@
     has_monitor_operations_ = true;
   }
 
-  ArenaVector<ReferenceInfo*> ref_info_array_;   // All references used for heap accesses.
-  ArenaVector<HeapLocation*> heap_locations_;    // All heap locations.
+  ScopedArenaAllocator* allocator_;
+  ScopedArenaVector<ReferenceInfo*> ref_info_array_;   // All references used for heap accesses.
+  ScopedArenaVector<HeapLocation*> heap_locations_;    // All heap locations.
   ArenaBitVector aliasing_matrix_;    // aliasing info between each pair of locations.
   bool has_heap_stores_;    // If there is no heap stores, LSE acts as GVN with better
                             // alias analysis and won't be as effective.
   bool has_volatile_;       // If there are volatile field accesses.
   bool has_monitor_operations_;    // If there are monitor operations.
+  LoadStoreAnalysisType lse_type_;
 
   DISALLOW_COPY_AND_ASSIGN(HeapLocationCollector);
 };
 
-class LoadStoreAnalysis : public HOptimization {
+class LoadStoreAnalysis {
  public:
-  explicit LoadStoreAnalysis(HGraph* graph, const char* name = kLoadStoreAnalysisPassName)
-    : HOptimization(graph, name),
-      heap_location_collector_(graph) {}
+  // for_elimination controls whether we should keep track of escapes at a per-block level for
+  // partial LSE.
+  explicit LoadStoreAnalysis(HGraph* graph,
+                             OptimizingCompilerStats* stats,
+                             ScopedArenaAllocator* local_allocator,
+                             LoadStoreAnalysisType lse_type)
+      : graph_(graph),
+        stats_(stats),
+        heap_location_collector_(
+            graph,
+            local_allocator,
+            ExecutionSubgraph::CanAnalyse(graph_) ? lse_type : LoadStoreAnalysisType::kBasic) {}
 
   const HeapLocationCollector& GetHeapLocationCollector() const {
     return heap_location_collector_;
   }
 
-  bool Run() override;
-
-  static constexpr const char* kLoadStoreAnalysisPassName = "load_store_analysis";
+  bool Run();
 
  private:
+  HGraph* graph_;
+  OptimizingCompilerStats* stats_;
   HeapLocationCollector heap_location_collector_;
 
   DISALLOW_COPY_AND_ASSIGN(LoadStoreAnalysis);
diff --git a/compiler/optimizing/load_store_analysis_test.cc b/compiler/optimizing/load_store_analysis_test.cc
index d725aba..c6d2208 100644
--- a/compiler/optimizing/load_store_analysis_test.cc
+++ b/compiler/optimizing/load_store_analysis_test.cc
@@ -15,21 +15,53 @@
  */
 
 #include "load_store_analysis.h"
-#include "nodes.h"
-#include "optimizing_unit_test.h"
 
+#include <array>
+#include <string_view>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "base/scoped_arena_allocator.h"
+#include "class_root.h"
+#include "dex/dex_file_types.h"
+#include "dex/method_reference.h"
+#include "entrypoints/quick/quick_entrypoints_enum.h"
+#include "execution_subgraph.h"
+#include "execution_subgraph_test.h"
 #include "gtest/gtest.h"
+#include "handle.h"
+#include "handle_scope.h"
+#include "nodes.h"
+#include "optimizing/data_type.h"
+#include "optimizing_unit_test.h"
+#include "scoped_thread_state_change.h"
 
 namespace art {
 
-class LoadStoreAnalysisTest : public OptimizingUnitTest {
+class LoadStoreAnalysisTest : public CommonCompilerTest, public OptimizingUnitTestHelper {
  public:
-  LoadStoreAnalysisTest() : graph_(CreateGraph()) { }
+  LoadStoreAnalysisTest() {}
 
-  HGraph* graph_;
+  AdjacencyListGraph SetupFromAdjacencyList(
+      const std::string_view entry_name,
+      const std::string_view exit_name,
+      const std::vector<AdjacencyListGraph::Edge>& adj) {
+    return AdjacencyListGraph(graph_, GetAllocator(), entry_name, exit_name, adj);
+  }
+
+  bool IsValidSubgraph(const ExecutionSubgraph* esg) {
+    return ExecutionSubgraphTestHelper::CalculateValidity(graph_, esg);
+  }
+
+  bool IsValidSubgraph(const ExecutionSubgraph& esg) {
+    return ExecutionSubgraphTestHelper::CalculateValidity(graph_, &esg);
+  }
+  void CheckReachability(const AdjacencyListGraph& adj,
+                         const std::vector<AdjacencyListGraph::Edge>& reach);
 };
 
 TEST_F(LoadStoreAnalysisTest, ArrayHeapLocations) {
+  CreateGraph();
   HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_);
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
@@ -66,7 +98,8 @@
 
   // Test HeapLocationCollector initialization.
   // Should be no heap locations, no operations on the heap.
-  HeapLocationCollector heap_location_collector(graph_);
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  HeapLocationCollector heap_location_collector(graph_, &allocator, LoadStoreAnalysisType::kFull);
   ASSERT_EQ(heap_location_collector.GetNumberOfHeapLocations(), 0U);
   ASSERT_FALSE(heap_location_collector.HasHeapStores());
 
@@ -111,6 +144,7 @@
 }
 
 TEST_F(LoadStoreAnalysisTest, FieldHeapLocations) {
+  CreateGraph();
   HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_);
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
@@ -131,7 +165,7 @@
                                                                           c1,
                                                                           nullptr,
                                                                           DataType::Type::kInt32,
-                                                                          MemberOffset(10),
+                                                                          MemberOffset(32),
                                                                           false,
                                                                           kUnknownFieldIndex,
                                                                           kUnknownClassDefIndex,
@@ -140,7 +174,7 @@
   HInstanceFieldGet* get_field10 = new (GetAllocator()) HInstanceFieldGet(object,
                                                                           nullptr,
                                                                           DataType::Type::kInt32,
-                                                                          MemberOffset(10),
+                                                                          MemberOffset(32),
                                                                           false,
                                                                           kUnknownFieldIndex,
                                                                           kUnknownClassDefIndex,
@@ -162,7 +196,8 @@
 
   // Test HeapLocationCollector initialization.
   // Should be no heap locations, no operations on the heap.
-  HeapLocationCollector heap_location_collector(graph_);
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  HeapLocationCollector heap_location_collector(graph_, &allocator, LoadStoreAnalysisType::kFull);
   ASSERT_EQ(heap_location_collector.GetNumberOfHeapLocations(), 0U);
   ASSERT_FALSE(heap_location_collector.HasHeapStores());
 
@@ -190,6 +225,7 @@
 }
 
 TEST_F(LoadStoreAnalysisTest, ArrayIndexAliasingTest) {
+  CreateGraph();
   HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_);
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
@@ -241,7 +277,8 @@
   entry->AddInstruction(arr_set7);  // array[1-i] = c0
   entry->AddInstruction(arr_set8);  // array[i-(-1)] = c0
 
-  LoadStoreAnalysis lsa(graph_);
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kBasic);
   lsa.Run();
   const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
 
@@ -282,6 +319,7 @@
 }
 
 TEST_F(LoadStoreAnalysisTest, ArrayAliasingTest) {
+  CreateGraph();
   HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_);
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
@@ -407,7 +445,8 @@
   entry->AddInstruction(vstore_i_add8);
   entry->AddInstruction(vstore_i_add6_vlen2);
 
-  LoadStoreAnalysis lsa(graph_);
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kBasic);
   lsa.Run();
   const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
 
@@ -492,6 +531,7 @@
 }
 
 TEST_F(LoadStoreAnalysisTest, ArrayIndexCalculationOverflowTest) {
+  CreateGraph();
   HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_);
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
@@ -565,7 +605,8 @@
   entry->AddInstruction(arr_set_7);
   entry->AddInstruction(arr_set_8);
 
-  LoadStoreAnalysis lsa(graph_);
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kBasic);
   lsa.Run();
   const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
 
@@ -609,6 +650,7 @@
 }
 
 TEST_F(LoadStoreAnalysisTest, TestHuntOriginalRef) {
+  CreateGraph();
   HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_);
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
@@ -654,7 +696,8 @@
   entry->AddInstruction(inter_addr);
   entry->AddInstruction(array_get4);
 
-  HeapLocationCollector heap_location_collector(graph_);
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  HeapLocationCollector heap_location_collector(graph_, &allocator, LoadStoreAnalysisType::kFull);
   heap_location_collector.VisitBasicBlock(entry);
 
   // Test that the HeapLocationCollector should be able to tell
@@ -672,4 +715,1346 @@
   ASSERT_EQ(loc1, loc4);
 }
 
+void LoadStoreAnalysisTest::CheckReachability(const AdjacencyListGraph& adj,
+                                              const std::vector<AdjacencyListGraph::Edge>& reach) {
+  uint32_t cnt = 0;
+  for (HBasicBlock* blk : graph_->GetBlocks()) {
+    if (adj.HasBlock(blk)) {
+      for (HBasicBlock* other : graph_->GetBlocks()) {
+        if (other == nullptr) {
+          continue;
+        }
+        if (adj.HasBlock(other)) {
+          bool contains_edge =
+              std::find(reach.begin(),
+                        reach.end(),
+                        AdjacencyListGraph::Edge { adj.GetName(blk), adj.GetName(other) }) !=
+              reach.end();
+          if (graph_->PathBetween(blk, other)) {
+            cnt++;
+            EXPECT_TRUE(contains_edge) << "Unexpected edge found between " << adj.GetName(blk)
+                                       << " and " << adj.GetName(other);
+          } else {
+            EXPECT_FALSE(contains_edge) << "Expected edge not found between " << adj.GetName(blk)
+                                        << " and " << adj.GetName(other);
+          }
+        } else if (graph_->PathBetween(blk, other)) {
+          ADD_FAILURE() << "block " << adj.GetName(blk)
+                        << " has path to non-adjacency-graph block id: " << other->GetBlockId();
+        }
+      }
+    } else {
+      for (HBasicBlock* other : graph_->GetBlocks()) {
+        if (other == nullptr) {
+          continue;
+        }
+        EXPECT_FALSE(graph_->PathBetween(blk, other))
+            << "Reachable blocks outside of adjacency-list";
+      }
+    }
+  }
+  EXPECT_EQ(cnt, reach.size());
+}
+
+TEST_F(LoadStoreAnalysisTest, ReachabilityTest1) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
+  CheckReachability(blks,
+                    {
+                        { "entry", "left" },
+                        { "entry", "right" },
+                        { "entry", "exit" },
+                        { "right", "exit" },
+                        { "left", "exit" },
+                    });
+}
+
+TEST_F(LoadStoreAnalysisTest, ReachabilityTest2) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "loop-header" }, { "loop-header", "loop" }, { "loop", "loop-header" } }));
+  CheckReachability(blks,
+                    {
+                        { "entry", "loop-header" },
+                        { "entry", "loop" },
+                        { "loop-header", "loop-header" },
+                        { "loop-header", "loop" },
+                        { "loop", "loop-header" },
+                        { "loop", "loop" },
+                    });
+}
+
+TEST_F(LoadStoreAnalysisTest, ReachabilityTest3) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 { { "entry", "loop-header" },
+                                                   { "loop-header", "loop" },
+                                                   { "loop", "loop-header" },
+                                                   { "entry", "right" },
+                                                   { "right", "exit" } }));
+  CheckReachability(blks,
+                    {
+                        { "entry", "loop-header" },
+                        { "entry", "loop" },
+                        { "entry", "right" },
+                        { "entry", "exit" },
+                        { "loop-header", "loop-header" },
+                        { "loop-header", "loop" },
+                        { "loop", "loop-header" },
+                        { "loop", "loop" },
+                        { "right", "exit" },
+                    });
+}
+
+static bool AreExclusionsIndependent(HGraph* graph, const ExecutionSubgraph* esg) {
+  auto excluded = esg->GetExcludedCohorts();
+  if (excluded.size() < 2) {
+    return true;
+  }
+  for (auto first = excluded.begin(); first != excluded.end(); ++first) {
+    for (auto second = excluded.begin(); second != excluded.end(); ++second) {
+      if (first == second) {
+        continue;
+      }
+      for (const HBasicBlock* entry : first->EntryBlocks()) {
+        for (const HBasicBlock* exit : second->ExitBlocks()) {
+          if (graph->PathBetween(exit, entry)) {
+            return false;
+          }
+        }
+      }
+    }
+  }
+  return true;
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   call_func(obj);
+// } else {
+//   // RIGHT
+//   obj.field = 1;
+// }
+// // EXIT
+// obj.field;
+TEST_F(LoadStoreAnalysisTest, PartialEscape) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right = blks.Get("right");
+  HBasicBlock* exit = blks.Get("exit");
+
+  HInstruction* bool_value = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                                      dex::TypeIndex(10),
+                                                      graph_->GetDexFile(),
+                                                      ScopedNullHandle<mirror::Class>(),
+                                                      false,
+                                                      0,
+                                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+
+  HInstruction* call_left = new (GetAllocator())
+      HInvokeStaticOrDirect(GetAllocator(),
+                            1,
+                            DataType::Type::kVoid,
+                            0,
+                            { nullptr, 0 },
+                            nullptr,
+                            {},
+                            InvokeType::kStatic,
+                            { nullptr, 0 },
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  call_left->AsInvoke()->SetRawInputAt(0, new_inst);
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+
+  HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c0,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(32),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_final = new (GetAllocator()) HInstanceFieldGet(new_inst,
+                                                                    nullptr,
+                                                                    DataType::Type::kInt32,
+                                                                    MemberOffset(32),
+                                                                    false,
+                                                                    0,
+                                                                    0,
+                                                                    graph_->GetDexFile(),
+                                                                    0);
+  exit->AddInstruction(read_final);
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kFull);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_TRUE(info->IsPartialSingleton());
+  const ExecutionSubgraph* esg = info->GetNoEscapeSubgraph();
+
+  ASSERT_TRUE(esg->IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  ASSERT_TRUE(AreExclusionsIndependent(graph_, esg));
+  std::unordered_set<const HBasicBlock*> contents(esg->ReachableBlocks().begin(),
+                                                  esg->ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+  ASSERT_TRUE(contents.find(blks.Get("left")) == contents.end());
+
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   call_func(obj);
+// } else {
+//   // RIGHT
+//   obj.field = 1;
+// }
+// // EXIT
+// obj.field2;
+TEST_F(LoadStoreAnalysisTest, PartialEscape2) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right = blks.Get("right");
+  HBasicBlock* exit = blks.Get("exit");
+
+  HInstruction* bool_value = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                                      dex::TypeIndex(10),
+                                                      graph_->GetDexFile(),
+                                                      ScopedNullHandle<mirror::Class>(),
+                                                      false,
+                                                      0,
+                                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+
+  HInstruction* call_left = new (GetAllocator())
+      HInvokeStaticOrDirect(GetAllocator(),
+                            1,
+                            DataType::Type::kVoid,
+                            0,
+                            { nullptr, 0 },
+                            nullptr,
+                            {},
+                            InvokeType::kStatic,
+                            { nullptr, 0 },
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  call_left->AsInvoke()->SetRawInputAt(0, new_inst);
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+
+  HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c0,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(32),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_final = new (GetAllocator()) HInstanceFieldGet(new_inst,
+                                                                    nullptr,
+                                                                    DataType::Type::kInt32,
+                                                                    MemberOffset(16),
+                                                                    false,
+                                                                    0,
+                                                                    0,
+                                                                    graph_->GetDexFile(),
+                                                                    0);
+  exit->AddInstruction(read_final);
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kFull);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_TRUE(info->IsPartialSingleton());
+  const ExecutionSubgraph* esg = info->GetNoEscapeSubgraph();
+
+  ASSERT_TRUE(esg->IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  ASSERT_TRUE(AreExclusionsIndependent(graph_, esg));
+  std::unordered_set<const HBasicBlock*> contents(esg->ReachableBlocks().begin(),
+                                                  esg->ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+  ASSERT_TRUE(contents.find(blks.Get("left")) == contents.end());
+
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+// // ENTRY
+// obj = new Obj();
+// obj.field = 10;
+// if (parameter_value) {
+//   // LEFT
+//   call_func(obj);
+// } else {
+//   // RIGHT
+//   obj.field = 20;
+// }
+// // EXIT
+// obj.field;
+TEST_F(LoadStoreAnalysisTest, PartialEscape3) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right = blks.Get("right");
+  HBasicBlock* exit = blks.Get("exit");
+
+  HInstruction* bool_value = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+  HInstruction* c20 = graph_->GetIntConstant(20);
+  HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                                      dex::TypeIndex(10),
+                                                      graph_->GetDexFile(),
+                                                      ScopedNullHandle<mirror::Class>(),
+                                                      false,
+                                                      0,
+                                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+
+  HInstruction* write_entry = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c10,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(32),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(if_inst);
+
+  HInstruction* call_left = new (GetAllocator())
+      HInvokeStaticOrDirect(GetAllocator(),
+                            1,
+                            DataType::Type::kVoid,
+                            0,
+                            { nullptr, 0 },
+                            nullptr,
+                            {},
+                            InvokeType::kStatic,
+                            { nullptr, 0 },
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  call_left->AsInvoke()->SetRawInputAt(0, new_inst);
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+
+  HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c20,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(32),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_final = new (GetAllocator()) HInstanceFieldGet(new_inst,
+                                                                    nullptr,
+                                                                    DataType::Type::kInt32,
+                                                                    MemberOffset(32),
+                                                                    false,
+                                                                    0,
+                                                                    0,
+                                                                    graph_->GetDexFile(),
+                                                                    0);
+  exit->AddInstruction(read_final);
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kFull);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_TRUE(info->IsPartialSingleton());
+  const ExecutionSubgraph* esg = info->GetNoEscapeSubgraph();
+
+  ASSERT_TRUE(esg->IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  ASSERT_TRUE(AreExclusionsIndependent(graph_, esg));
+  std::unordered_set<const HBasicBlock*> contents(esg->ReachableBlocks().begin(),
+                                                  esg->ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+  ASSERT_TRUE(contents.find(blks.Get("left")) == contents.end());
+
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+// For simplicity Partial LSE considers check-casts to escape. It means we don't
+// need to worry about inserting throws.
+// // ENTRY
+// obj = new Obj();
+// obj.field = 10;
+// if (parameter_value) {
+//   // LEFT
+//   (Foo)obj;
+// } else {
+//   // RIGHT
+//   obj.field = 20;
+// }
+// // EXIT
+// obj.field;
+TEST_F(LoadStoreAnalysisTest, PartialEscape4) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right = blks.Get("right");
+  HBasicBlock* exit = blks.Get("exit");
+
+  HInstruction* bool_value = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+  HInstruction* c20 = graph_->GetIntConstant(20);
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c10, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(if_inst);
+
+  ScopedNullHandle<mirror::Class> null_klass_;
+  HInstruction* cls2 = MakeClassLoad();
+  HInstruction* check_cast = new (GetAllocator()) HCheckCast(
+      new_inst, cls2, TypeCheckKind::kExactCheck, null_klass_, 0, GetAllocator(), nullptr, nullptr);
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(cls2);
+  left->AddInstruction(check_cast);
+  left->AddInstruction(goto_left);
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c20, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_final = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  exit->AddInstruction(read_final);
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kFull);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_TRUE(info->IsPartialSingleton());
+  const ExecutionSubgraph* esg = info->GetNoEscapeSubgraph();
+
+  ASSERT_TRUE(esg->IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  ASSERT_TRUE(AreExclusionsIndependent(graph_, esg));
+  std::unordered_set<const HBasicBlock*> contents(esg->ReachableBlocks().begin(),
+                                                  esg->ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+  ASSERT_TRUE(contents.find(blks.Get("left")) == contents.end());
+
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+// For simplicity Partial LSE considers instance-ofs with bitvectors to escape.
+// // ENTRY
+// obj = new Obj();
+// obj.field = 10;
+// if (parameter_value) {
+//   // LEFT
+//   obj instanceof /*bitvector*/ Foo;
+// } else {
+//   // RIGHT
+//   obj.field = 20;
+// }
+// // EXIT
+// obj.field;
+TEST_F(LoadStoreAnalysisTest, PartialEscape5) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right = blks.Get("right");
+  HBasicBlock* exit = blks.Get("exit");
+
+  HInstruction* bool_value = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+  HInstruction* c20 = graph_->GetIntConstant(20);
+  HIntConstant* bs1 = graph_->GetIntConstant(0xffff);
+  HIntConstant* bs2 = graph_->GetIntConstant(0x00ff);
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* null_const = graph_->GetNullConstant();
+  HInstruction* new_inst = MakeNewInstance(cls);
+
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c10, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(if_inst);
+
+  ScopedNullHandle<mirror::Class> null_klass_;
+  HInstruction* instanceof = new (GetAllocator()) HInstanceOf(new_inst,
+                                                              null_const,
+                                                              TypeCheckKind::kBitstringCheck,
+                                                              null_klass_,
+                                                              0,
+                                                              GetAllocator(),
+                                                              bs1,
+                                                              bs2);
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(instanceof);
+  left->AddInstruction(goto_left);
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c20, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_final = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  exit->AddInstruction(read_final);
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kFull);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_TRUE(info->IsPartialSingleton());
+  const ExecutionSubgraph* esg = info->GetNoEscapeSubgraph();
+
+  ASSERT_TRUE(esg->IsValid());
+  ASSERT_TRUE(IsValidSubgraph(esg));
+  ASSERT_TRUE(AreExclusionsIndependent(graph_, esg));
+  std::unordered_set<const HBasicBlock*> contents(esg->ReachableBlocks().begin(),
+                                                  esg->ReachableBlocks().end());
+
+  ASSERT_EQ(contents.size(), 3u);
+  ASSERT_TRUE(contents.find(blks.Get("left")) == contents.end());
+
+  ASSERT_TRUE(contents.find(blks.Get("right")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("entry")) != contents.end());
+  ASSERT_TRUE(contents.find(blks.Get("exit")) != contents.end());
+}
+
+// before we had predicated-set we needed to be able to remove the store as
+// well. This test makes sure that still works.
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   call_func(obj);
+// } else {
+//   // RIGHT
+//   obj.f1 = 0;
+// }
+// // EXIT
+// // call_func prevents the elimination of this store.
+// obj.f2 = 0;
+TEST_F(LoadStoreAnalysisTest, TotalEscapeAdjacentNoPredicated) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      {{"entry", "left"}, {"entry", "right"}, {"left", "exit"}, {"right", "exit"}}));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right = blks.Get("right");
+  HBasicBlock* exit = blks.Get("exit");
+
+  HInstruction* bool_value = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                                      dex::TypeIndex(10),
+                                                      graph_->GetDexFile(),
+                                                      ScopedNullHandle<mirror::Class>(),
+                                                      false,
+                                                      0,
+                                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+
+  HInstruction* call_left = new (GetAllocator())
+      HInvokeStaticOrDirect(GetAllocator(),
+                            1,
+                            DataType::Type::kVoid,
+                            0,
+                            {nullptr, 0},
+                            nullptr,
+                            {},
+                            InvokeType::kStatic,
+                            {nullptr, 0},
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  call_left->AsInvoke()->SetRawInputAt(0, new_inst);
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+
+  HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c0,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(32),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* write_final = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c0,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(16),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  exit->AddInstruction(write_final);
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  graph_->ClearDominanceInformation();
+  graph_->BuildDominatorTree();
+  LoadStoreAnalysis lsa(
+      graph_, nullptr, &allocator, LoadStoreAnalysisType::kNoPredicatedInstructions);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_FALSE(info->IsPartialSingleton());
+}
+
+// With predicated-set we can (partially) remove the store as well.
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   call_func(obj);
+// } else {
+//   // RIGHT
+//   obj.f1 = 0;
+// }
+// // EXIT
+// // call_func prevents the elimination of this store.
+// obj.f2 = 0;
+TEST_F(LoadStoreAnalysisTest, TotalEscapeAdjacent) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right = blks.Get("right");
+  HBasicBlock* exit = blks.Get("exit");
+
+  HInstruction* bool_value = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                                      dex::TypeIndex(10),
+                                                      graph_->GetDexFile(),
+                                                      ScopedNullHandle<mirror::Class>(),
+                                                      false,
+                                                      0,
+                                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+
+  HInstruction* call_left = new (GetAllocator())
+      HInvokeStaticOrDirect(GetAllocator(),
+                            1,
+                            DataType::Type::kVoid,
+                            0,
+                            { nullptr, 0 },
+                            nullptr,
+                            {},
+                            InvokeType::kStatic,
+                            { nullptr, 0 },
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  call_left->AsInvoke()->SetRawInputAt(0, new_inst);
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+
+  HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c0,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(32),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* write_final = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c0,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(16),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  exit->AddInstruction(write_final);
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  graph_->ClearDominanceInformation();
+  graph_->BuildDominatorTree();
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kFull);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_TRUE(info->IsPartialSingleton());
+  const ExecutionSubgraph* esg = info->GetNoEscapeSubgraph();
+
+  EXPECT_TRUE(esg->IsValid()) << esg->GetExcludedCohorts();
+  EXPECT_TRUE(IsValidSubgraph(esg));
+  std::unordered_set<const HBasicBlock*> contents(esg->ReachableBlocks().begin(),
+                                                  esg->ReachableBlocks().end());
+
+  EXPECT_EQ(contents.size(), 3u);
+  EXPECT_TRUE(contents.find(blks.Get("left")) == contents.end());
+  EXPECT_FALSE(contents.find(blks.Get("right")) == contents.end());
+  EXPECT_FALSE(contents.find(blks.Get("entry")) == contents.end());
+  EXPECT_FALSE(contents.find(blks.Get("exit")) == contents.end());
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   call_func(obj);
+// } else {
+//   // RIGHT
+//   obj.f0 = 0;
+//   call_func2(obj);
+// }
+// // EXIT
+// obj.f0;
+TEST_F(LoadStoreAnalysisTest, TotalEscape) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right = blks.Get("right");
+  HBasicBlock* exit = blks.Get("exit");
+
+  HInstruction* bool_value = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                                      dex::TypeIndex(10),
+                                                      graph_->GetDexFile(),
+                                                      ScopedNullHandle<mirror::Class>(),
+                                                      false,
+                                                      0,
+                                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+
+  HInstruction* call_left = new (GetAllocator())
+      HInvokeStaticOrDirect(GetAllocator(),
+                            1,
+                            DataType::Type::kVoid,
+                            0,
+                            { nullptr, 0 },
+                            nullptr,
+                            {},
+                            InvokeType::kStatic,
+                            { nullptr, 0 },
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  call_left->AsInvoke()->SetRawInputAt(0, new_inst);
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+
+  HInstruction* call_right = new (GetAllocator())
+      HInvokeStaticOrDirect(GetAllocator(),
+                            1,
+                            DataType::Type::kVoid,
+                            0,
+                            { nullptr, 0 },
+                            nullptr,
+                            {},
+                            InvokeType::kStatic,
+                            { nullptr, 0 },
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c0,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(32),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  call_right->AsInvoke()->SetRawInputAt(0, new_inst);
+  right->AddInstruction(write_right);
+  right->AddInstruction(call_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_final = new (GetAllocator()) HInstanceFieldGet(new_inst,
+                                                                    nullptr,
+                                                                    DataType::Type::kInt32,
+                                                                    MemberOffset(32),
+                                                                    false,
+                                                                    0,
+                                                                    0,
+                                                                    graph_->GetDexFile(),
+                                                                    0);
+  exit->AddInstruction(read_final);
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kFull);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_FALSE(info->IsPartialSingleton());
+}
+
+// // ENTRY
+// obj = new Obj();
+// obj.foo = 0;
+// // EXIT
+// return obj;
+TEST_F(LoadStoreAnalysisTest, TotalEscape2) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry", "exit", { { "entry", "exit" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* exit = blks.Get("exit");
+
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                                      dex::TypeIndex(10),
+                                                      graph_->GetDexFile(),
+                                                      ScopedNullHandle<mirror::Class>(),
+                                                      false,
+                                                      0,
+                                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+
+  HInstruction* write_start = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c0,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(32),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  HInstruction* goto_inst = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_start);
+  entry->AddInstruction(goto_inst);
+
+  HInstruction* return_final = new (GetAllocator()) HReturn(new_inst);
+  exit->AddInstruction(return_final);
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kFull);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_FALSE(info->IsPartialSingleton());
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // HIGH_LEFT
+//   call_func(obj);
+// } else {
+//   // HIGH_RIGHT
+//   obj.f0 = 1;
+// }
+// // MID
+// obj.f0 *= 2;
+// if (parameter_value2) {
+//   // LOW_LEFT
+//   call_func(obj);
+// } else {
+//   // LOW_RIGHT
+//   obj.f0 = 1;
+// }
+// // EXIT
+// obj.f0
+TEST_F(LoadStoreAnalysisTest, DoubleDiamondEscape) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 { { "entry", "high_left" },
+                                                   { "entry", "high_right" },
+                                                   { "low_left", "exit" },
+                                                   { "low_right", "exit" },
+                                                   { "high_right", "mid" },
+                                                   { "high_left", "mid" },
+                                                   { "mid", "low_left" },
+                                                   { "mid", "low_right" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* high_left = blks.Get("high_left");
+  HBasicBlock* high_right = blks.Get("high_right");
+  HBasicBlock* mid = blks.Get("mid");
+  HBasicBlock* low_left = blks.Get("low_left");
+  HBasicBlock* low_right = blks.Get("low_right");
+  HBasicBlock* exit = blks.Get("exit");
+
+  HInstruction* bool_value1 = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
+  HInstruction* bool_value2 = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 2, DataType::Type::kBool);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                                      dex::TypeIndex(10),
+                                                      graph_->GetDexFile(),
+                                                      ScopedNullHandle<mirror::Class>(),
+                                                      false,
+                                                      0,
+                                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value1);
+  entry->AddInstruction(bool_value1);
+  entry->AddInstruction(bool_value2);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+
+  HInstruction* call_left = new (GetAllocator())
+      HInvokeStaticOrDirect(GetAllocator(),
+                            1,
+                            DataType::Type::kVoid,
+                            0,
+                            { nullptr, 0 },
+                            nullptr,
+                            {},
+                            InvokeType::kStatic,
+                            { nullptr, 0 },
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  call_left->AsInvoke()->SetRawInputAt(0, new_inst);
+  high_left->AddInstruction(call_left);
+  high_left->AddInstruction(goto_left);
+
+  HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                     c0,
+                                                                     nullptr,
+                                                                     DataType::Type::kInt32,
+                                                                     MemberOffset(32),
+                                                                     false,
+                                                                     0,
+                                                                     0,
+                                                                     graph_->GetDexFile(),
+                                                                     0);
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  high_right->AddInstruction(write_right);
+  high_right->AddInstruction(goto_right);
+
+  HInstruction* read_mid = new (GetAllocator()) HInstanceFieldGet(new_inst,
+                                                                  nullptr,
+                                                                  DataType::Type::kInt32,
+                                                                  MemberOffset(32),
+                                                                  false,
+                                                                  0,
+                                                                  0,
+                                                                  graph_->GetDexFile(),
+                                                                  0);
+  HInstruction* mul_mid = new (GetAllocator()) HMul(DataType::Type::kInt32, read_mid, c2);
+  HInstruction* write_mid = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                   mul_mid,
+                                                                   nullptr,
+                                                                   DataType::Type::kInt32,
+                                                                   MemberOffset(32),
+                                                                   false,
+                                                                   0,
+                                                                   0,
+                                                                   graph_->GetDexFile(),
+                                                                   0);
+  HInstruction* if_mid = new (GetAllocator()) HIf(bool_value2);
+  mid->AddInstruction(read_mid);
+  mid->AddInstruction(mul_mid);
+  mid->AddInstruction(write_mid);
+  mid->AddInstruction(if_mid);
+
+  HInstruction* call_low_left = new (GetAllocator())
+      HInvokeStaticOrDirect(GetAllocator(),
+                            1,
+                            DataType::Type::kVoid,
+                            0,
+                            { nullptr, 0 },
+                            nullptr,
+                            {},
+                            InvokeType::kStatic,
+                            { nullptr, 0 },
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInstruction* goto_low_left = new (GetAllocator()) HGoto();
+  call_low_left->AsInvoke()->SetRawInputAt(0, new_inst);
+  low_left->AddInstruction(call_low_left);
+  low_left->AddInstruction(goto_low_left);
+
+  HInstruction* write_low_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                                         c0,
+                                                                         nullptr,
+                                                                         DataType::Type::kInt32,
+                                                                         MemberOffset(32),
+                                                                         false,
+                                                                         0,
+                                                                         0,
+                                                                         graph_->GetDexFile(),
+                                                                         0);
+  HInstruction* goto_low_right = new (GetAllocator()) HGoto();
+  low_right->AddInstruction(write_low_right);
+  low_right->AddInstruction(goto_low_right);
+
+  HInstruction* read_final = new (GetAllocator()) HInstanceFieldGet(new_inst,
+                                                                    nullptr,
+                                                                    DataType::Type::kInt32,
+                                                                    MemberOffset(32),
+                                                                    false,
+                                                                    0,
+                                                                    0,
+                                                                    graph_->GetDexFile(),
+                                                                    0);
+  exit->AddInstruction(read_final);
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kFull);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_FALSE(info->IsPartialSingleton());
+}
+
+// // ENTRY
+// Obj new_inst = new Obj();
+// new_inst.foo = 12;
+// Obj obj;
+// Obj out;
+// if (param1) {
+//   // LEFT_START
+//   if (param2) {
+//     // LEFT_LEFT
+//     obj = new_inst;
+//   } else {
+//     // LEFT_RIGHT
+//     obj = obj_param;
+//   }
+//   // LEFT_MERGE
+//   // technically the phi is enough to cause an escape but might as well be
+//   // thorough.
+//   // obj = phi[new_inst, param]
+//   escape(obj);
+//   out = obj;
+// } else {
+//   // RIGHT
+//   out = obj_param;
+// }
+// // EXIT
+// // Can't do anything with this since we don't have good tracking for the heap-locations
+// // out = phi[param, phi[new_inst, param]]
+// return out.foo
+TEST_F(LoadStoreAnalysisTest, PartialPhiPropagation1) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "left_left"},
+                                                  {"left", "left_right"},
+                                                  {"left_left", "left_merge"},
+                                                  {"left_right", "left_merge"},
+                                                  {"left_merge", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(left_left);
+  GET_BLOCK(left_right);
+  GET_BLOCK(left_merge);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left_merge, right});
+  EnsurePredecessorOrder(left_merge, {left_left, left_right});
+  HInstruction* param1 = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
+  HInstruction* param2 = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 2, DataType::Type::kBool);
+  HInstruction* obj_param = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(10), 3, DataType::Type::kReference);
+  HInstruction* c12 = graph_->GetIntConstant(12);
+  HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                                      dex::TypeIndex(10),
+                                                      graph_->GetDexFile(),
+                                                      ScopedNullHandle<mirror::Class>(),
+                                                      false,
+                                                      0,
+                                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+  HInstruction* store = new (GetAllocator()) HInstanceFieldSet(new_inst,
+                                                               c12,
+                                                               nullptr,
+                                                               DataType::Type::kInt32,
+                                                               MemberOffset(32),
+                                                               false,
+                                                               0,
+                                                               0,
+                                                               graph_->GetDexFile(),
+                                                               0);
+  HInstruction* if_param1 = new (GetAllocator()) HIf(param1);
+  entry->AddInstruction(param1);
+  entry->AddInstruction(param2);
+  entry->AddInstruction(obj_param);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(store);
+  entry->AddInstruction(if_param1);
+  ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction));
+  ManuallyBuildEnvFor(cls, &current_locals);
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* if_left = new (GetAllocator()) HIf(param2);
+  left->AddInstruction(if_left);
+
+  HInstruction* goto_left_left = new (GetAllocator()) HGoto();
+  left_left->AddInstruction(goto_left_left);
+
+  HInstruction* goto_left_right = new (GetAllocator()) HGoto();
+  left_right->AddInstruction(goto_left_right);
+
+  HPhi* left_phi =
+      new (GetAllocator()) HPhi(GetAllocator(), kNoRegNumber, 2, DataType::Type::kReference);
+  HInstruction* call_left = new (GetAllocator())
+      HInvokeStaticOrDirect(GetAllocator(),
+                            1,
+                            DataType::Type::kVoid,
+                            0,
+                            {nullptr, 0},
+                            nullptr,
+                            {},
+                            InvokeType::kStatic,
+                            {nullptr, 0},
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+  HInstruction* goto_left_merge = new (GetAllocator()) HGoto();
+  left_phi->SetRawInputAt(0, obj_param);
+  left_phi->SetRawInputAt(1, new_inst);
+  call_left->AsInvoke()->SetRawInputAt(0, left_phi);
+  left_merge->AddPhi(left_phi);
+  left_merge->AddInstruction(call_left);
+  left_merge->AddInstruction(goto_left_merge);
+  left_phi->SetCanBeNull(true);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(goto_right);
+
+  HPhi* return_phi =
+      new (GetAllocator()) HPhi(GetAllocator(), kNoRegNumber, 2, DataType::Type::kReference);
+  HInstruction* read_exit = new (GetAllocator()) HInstanceFieldGet(return_phi,
+                                                                   nullptr,
+                                                                   DataType::Type::kReference,
+                                                                   MemberOffset(32),
+                                                                   false,
+                                                                   0,
+                                                                   0,
+                                                                   graph_->GetDexFile(),
+                                                                   0);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_exit);
+  return_phi->SetRawInputAt(0, left_phi);
+  return_phi->SetRawInputAt(1, obj_param);
+  breturn->AddPhi(return_phi);
+  breturn->AddInstruction(read_exit);
+  breturn->AddInstruction(return_exit);
+
+  HInstruction* exit_instruction = new (GetAllocator()) HExit();
+  exit->AddInstruction(exit_instruction);
+
+  graph_->ClearDominanceInformation();
+  graph_->BuildDominatorTree();
+
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_, nullptr, &allocator, LoadStoreAnalysisType::kFull);
+  lsa.Run();
+
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
+  ReferenceInfo* info = heap_location_collector.FindReferenceInfoOf(new_inst);
+  ASSERT_FALSE(info->IsPartialSingleton());
+}
 }  // namespace art
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index 4c150da..722cc83 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -16,316 +16,814 @@
 
 #include "load_store_elimination.h"
 
+#include <algorithm>
+#include <optional>
+#include <sstream>
+#include <variant>
+
+#include "base/arena_allocator.h"
+#include "base/arena_bit_vector.h"
 #include "base/array_ref.h"
+#include "base/bit_vector-inl.h"
+#include "base/bit_vector.h"
+#include "base/globals.h"
+#include "base/indenter.h"
+#include "base/iteration_range.h"
 #include "base/scoped_arena_allocator.h"
 #include "base/scoped_arena_containers.h"
+#include "base/transform_iterator.h"
 #include "escape.h"
+#include "execution_subgraph.h"
+#include "handle.h"
 #include "load_store_analysis.h"
+#include "mirror/class_loader.h"
+#include "mirror/dex_cache.h"
+#include "nodes.h"
+#include "optimizing/execution_subgraph.h"
+#include "optimizing_compiler_stats.h"
+#include "reference_type_propagation.h"
 #include "side_effects_analysis.h"
+#include "stack_map.h"
 
 /**
  * The general algorithm of load-store elimination (LSE).
- * Load-store analysis in the previous pass collects a list of heap locations
- * and does alias analysis of those heap locations.
- * LSE keeps track of a list of heap values corresponding to the heap
- * locations. It visits basic blocks in reverse post order and for
- * each basic block, visits instructions sequentially, and processes
- * instructions as follows:
- * - If the instruction is a load, and the heap location for that load has a
- *   valid heap value, the load can be eliminated. In order to maintain the
- *   validity of all heap locations during the optimization phase, the real
- *   elimination is delayed till the end of LSE.
- * - If the instruction is a store, it updates the heap value for the heap
- *   location of the store with the store instruction. The real heap value
- *   can be fetched from the store instruction. Heap values are invalidated
- *   for heap locations that may alias with the store instruction's heap
- *   location. The store instruction can be eliminated unless the value stored
- *   is later needed e.g. by a load from the same/aliased heap location or
- *   the heap location persists at method return/deoptimization.
- *   The store instruction is also needed if it's not used to track the heap
- *   value anymore, e.g. when it fails to merge with the heap values from other
- *   predecessors.
- * - A store that stores the same value as the heap value is eliminated.
- * - The list of heap values are merged at basic block entry from the basic
- *   block's predecessors. The algorithm is single-pass, so loop side-effects is
- *   used as best effort to decide if a heap location is stored inside the loop.
- * - A special type of objects called singletons are instantiated in the method
- *   and have a single name, i.e. no aliases. Singletons have exclusive heap
- *   locations since they have no aliases. Singletons are helpful in narrowing
- *   down the life span of a heap location such that they do not always
- *   need to participate in merging heap values. Allocation of a singleton
- *   can be eliminated if that singleton is not used and does not persist
- *   at method return/deoptimization.
- * - For newly instantiated instances, their heap values are initialized to
- *   language defined default values.
- * - Some instructions such as invokes are treated as loading and invalidating
- *   all the heap values, depending on the instruction's side effects.
- * - Finalizable objects are considered as persisting at method
- *   return/deoptimization.
- * - SIMD graphs (with VecLoad and VecStore instructions) are also handled. Any
- *   partial overlap access among ArrayGet/ArraySet/VecLoad/Store is seen as
- *   alias and no load/store is eliminated in such case.
- * - Currently this LSE algorithm doesn't handle graph with try-catch, due to
- *   the special block merging structure.
+ *
+ * We use load-store analysis to collect a list of heap locations and perform
+ * alias analysis of those heap locations. LSE then keeps track of a list of
+ * heap values corresponding to the heap locations and stores that put those
+ * values in these locations.
+ *  - In phase 1, we visit basic blocks in reverse post order and for each basic
+ *    block, visit instructions sequentially, recording heap values and looking
+ *    for loads and stores to eliminate without relying on loop Phis.
+ *  - In phase 2, we look for loads that can be replaced by creating loop Phis
+ *    or using a loop-invariant value.
+ *  - In phase 3, we determine which stores are dead and can be eliminated and
+ *    based on that information we re-evaluate whether some kept stores are
+ *    storing the same value as the value in the heap location; such stores are
+ *    also marked for elimination.
+ *  - In phase 4, we commit the changes, replacing loads marked for elimination
+ *    in previous processing and removing stores not marked for keeping. We also
+ *    remove allocations that are no longer needed.
+ *  - In phase 5, we move allocations which only escape along some executions
+ *    closer to their escape points and fixup non-escaping paths with their actual
+ *    values, creating PHIs when needed.
+ *
+ * 1. Walk over blocks and their instructions.
+ *
+ * The initial set of heap values for a basic block is
+ *  - For a loop header of an irreducible loop, all heap values are unknown.
+ *  - For a loop header of a normal loop, all values unknown at the end of the
+ *    preheader are initialized to unknown, other heap values are set to Phi
+ *    placeholders as we cannot determine yet whether these values are known on
+ *    all back-edges. We use Phi placeholders also for array heap locations with
+ *    index defined inside the loop but this helps only when the value remains
+ *    zero from the array allocation throughout the loop.
+ *  - For other basic blocks, we merge incoming values from the end of all
+ *    predecessors. If any incoming value is unknown, the start value for this
+ *    block is also unknown. Otherwise, if all the incoming values are the same
+ *    (including the case of a single predecessor), the incoming value is used.
+ *    Otherwise, we use a Phi placeholder to indicate different incoming values.
+ *    We record whether such Phi placeholder depends on a loop Phi placeholder.
+ *
+ * For each instruction in the block
+ *  - If the instruction is a load from a heap location with a known value not
+ *    dependent on a loop Phi placeholder, the load can be eliminated, either by
+ *    using an existing instruction or by creating new Phi(s) instead. In order
+ *    to maintain the validity of all heap locations during the optimization
+ *    phase, we only record substitutes at this phase and the real elimination
+ *    is delayed till the end of LSE. Loads that require a loop Phi placeholder
+ *    replacement are recorded for processing later. We also keep track of the
+ *    heap-value at the start load so that later partial-LSE can predicate the
+ *    load.
+ *  - If the instruction is a store, it updates the heap value for the heap
+ *    location with the stored value and records the store itself so that we can
+ *    mark it for keeping if the value becomes observable. Heap values are
+ *    invalidated for heap locations that may alias with the store instruction's
+ *    heap location and their recorded stores are marked for keeping as they are
+ *    now potentially observable. The store instruction can be eliminated unless
+ *    the value stored is later needed e.g. by a load from the same/aliased heap
+ *    location or the heap location persists at method return/deoptimization.
+ *  - A store that stores the same value as the heap value is eliminated.
+ *  - For newly instantiated instances, their heap values are initialized to
+ *    language defined default values.
+ *  - Finalizable objects are considered as persisting at method
+ *    return/deoptimization.
+ *  - Some instructions such as invokes are treated as loading and invalidating
+ *    all the heap values, depending on the instruction's side effects.
+ *  - SIMD graphs (with VecLoad and VecStore instructions) are also handled. Any
+ *    partial overlap access among ArrayGet/ArraySet/VecLoad/Store is seen as
+ *    alias and no load/store is eliminated in such case.
+ *  - Currently this LSE algorithm doesn't handle graph with try-catch, due to
+ *    the special block merging structure.
+ *
+ * The time complexity of the initial phase has several components. The total
+ * time for the initialization of heap values for all blocks is
+ *    O(heap_locations * edges)
+ * and the time complexity for simple instruction processing is
+ *    O(instructions).
+ * See the description of phase 3 for additional complexity due to matching of
+ * existing Phis for replacing loads.
+ *
+ * 2. Process loads that depend on loop Phi placeholders.
+ *
+ * We go over these loads to determine whether they can be eliminated. We look
+ * for the set of all Phi placeholders that feed the load and depend on a loop
+ * Phi placeholder and, if we find no unknown value, we construct the necessary
+ * Phi(s) or, if all other inputs are identical, i.e. the location does not
+ * change in the loop, just use that input. If we do find an unknown input, this
+ * must be from a loop back-edge and we replace the loop Phi placeholder with
+ * unknown value and re-process loads and stores that previously depended on
+ * loop Phi placeholders. This shall find at least one load of an unknown value
+ * which is now known to be unreplaceable or a new unknown value on a back-edge
+ * and we repeat this process until each load is either marked for replacement
+ * or found to be unreplaceable. As we mark at least one additional loop Phi
+ * placeholder as unreplacable in each iteration, this process shall terminate.
+ *
+ * The depth-first search for Phi placeholders in FindLoopPhisToMaterialize()
+ * is limited by the number of Phi placeholders and their dependencies we need
+ * to search with worst-case time complexity
+ *    O(phi_placeholder_dependencies) .
+ * The dependencies are usually just the Phi placeholders' potential inputs,
+ * but if we use TryReplacingLoopPhiPlaceholderWithDefault() for default value
+ * replacement search, there are additional dependencies to consider, see below.
+ *
+ * In the successful case (no unknown inputs found) we use the Floyd-Warshall
+ * algorithm to determine transitive closures for each found Phi placeholder,
+ * and then match or materialize Phis from the smallest transitive closure,
+ * so that we can determine if such subset has a single other input. This has
+ * time complexity
+ *    O(phi_placeholders_found^3) .
+ * Note that successful TryReplacingLoopPhiPlaceholderWithDefault() does not
+ * contribute to this as such Phi placeholders are replaced immediately.
+ * The total time of all such successful cases has time complexity
+ *    O(phi_placeholders^3)
+ * because the found sets are disjoint and `Sum(n_i^3) <= Sum(n_i)^3`. Similar
+ * argument applies to the searches used to find all successful cases, so their
+ * total contribution is also just an insignificant
+ *    O(phi_placeholder_dependencies) .
+ * The materialization of Phis has an insignificant total time complexity
+ *    O(phi_placeholders * edges) .
+ *
+ * If we find an unknown input, we re-process heap values and loads with a time
+ * complexity that's the same as the phase 1 in the worst case. Adding this to
+ * the depth-first search time complexity yields
+ *    O(phi_placeholder_dependencies + heap_locations * edges + instructions)
+ * for a single iteration. We can ignore the middle term as it's proprotional
+ * to the number of Phi placeholder inputs included in the first term. Using
+ * the upper limit of number of such iterations, the total time complexity is
+ *    O((phi_placeholder_dependencies + instructions) * phi_placeholders) .
+ *
+ * The upper bound of Phi placeholder inputs is
+ *    heap_locations * edges
+ * but if we use TryReplacingLoopPhiPlaceholderWithDefault(), the dependencies
+ * include other heap locations in predecessor blocks with the upper bound of
+ *    heap_locations^2 * edges .
+ * Using the estimate
+ *    edges <= blocks^2
+ * and
+ *    phi_placeholders <= heap_locations * blocks ,
+ * the worst-case time complexity of the
+ *    O(phi_placeholder_dependencies * phi_placeholders)
+ * term from unknown input cases is actually
+ *    O(heap_locations^3 * blocks^3) ,
+ * exactly as the estimate for the Floyd-Warshall parts of successful cases.
+ * Adding the other term from the unknown input cases (to account for the case
+ * with significantly more instructions than blocks and heap locations), the
+ * phase 2 time complexity is
+ *    O(heap_locations^3 * blocks^3 + heap_locations * blocks * instructions) .
+ *
+ * See the description of phase 3 for additional complexity due to matching of
+ * existing Phis for replacing loads.
+ *
+ * 3. Determine which stores to keep and which to eliminate.
+ *
+ * During instruction processing in phase 1 and re-processing in phase 2, we are
+ * keeping a record of the stores and Phi placeholders that become observable
+ * and now propagate the observable Phi placeholders to all actual stores that
+ * feed them. Having determined observable stores, we look for stores that just
+ * overwrite the old value with the same. Since ignoring non-observable stores
+ * actually changes the old values in heap locations, we need to recalculate
+ * Phi placeholder replacements but we proceed similarly to the previous phase.
+ * We look for the set of all Phis that feed the old value replaced by the store
+ * (but ignoring whether they depend on a loop Phi) and, if we find no unknown
+ * value, we try to match existing Phis (we do not create new Phis anymore) or,
+ * if all other inputs are identical, i.e. the location does not change in the
+ * loop, just use that input. If this succeeds and the old value is identical to
+ * the value we're storing, such store shall be eliminated.
+ *
+ * The work is similar to the phase 2, except that we're not re-processing loads
+ * and stores anymore, so the time complexity of phase 3 is
+ *    O(heap_locations^3 * blocks^3) .
+ *
+ * There is additional complexity in matching existing Phis shared between the
+ * phases 1, 2 and 3. We are never trying to match two or more Phis at the same
+ * time (this could be difficult and slow), so each matching attempt is just
+ * looking at Phis in the block (both old Phis and newly created Phis) and their
+ * inputs. As we create at most `heap_locations` Phis in each block, the upper
+ * bound on the number of Phis we look at is
+ *    heap_locations * (old_phis + heap_locations)
+ * and the worst-case time complexity is
+ *    O(heap_locations^2 * edges + heap_locations * old_phis * edges) .
+ * The first term is lower than one term in phase 2, so the relevant part is
+ *    O(heap_locations * old_phis * edges) .
+ *
+ * 4. Replace loads and remove unnecessary stores and singleton allocations.
+ *
+ * A special type of objects called singletons are instantiated in the method
+ * and have a single name, i.e. no aliases. Singletons have exclusive heap
+ * locations since they have no aliases. Singletons are helpful in narrowing
+ * down the life span of a heap location such that they do not always need to
+ * participate in merging heap values. Allocation of a singleton can be
+ * eliminated if that singleton is not used and does not persist at method
+ * return/deoptimization.
+ *
+ * The time complexity of this phase is
+ *    O(instructions + instruction_uses) .
+ *
+ * 5. Partial LSE
+ *
+ * Move allocations closer to their escapes and remove/predicate loads and
+ * stores as required.
+ *
+ * Partial singletons are objects which only escape from the function or have
+ * multiple names along certain execution paths. In cases where we recognize
+ * these partial singletons we can move the allocation and initialization
+ * closer to the actual escape(s). We can then perform a simplified version of
+ * LSE step 2 to determine the unescaped value of any reads performed after the
+ * object may have escaped. These are used to replace these reads with
+ * 'predicated-read' instructions where the value is only read if the object
+ * has actually escaped. We use the existence of the object itself as the
+ * marker of whether escape has occurred.
+ *
+ * There are several steps in this sub-pass
+ *
+ * 5.1 Group references
+ *
+ * Since all heap-locations for a single reference escape at the same time, we
+ * need to group the heap-locations by reference and process them at the same
+ * time.
+ *
+ *    O(heap_locations).
+ *
+ * FIXME: The time complexity above assumes we can bucket the heap-locations in
+ * O(1) which is not true since we just perform a linear-scan of the heap-ref
+ * list. Since there are generally only a small number of heap-references which
+ * are partial-singletons this is fine and lower real overhead than a hash map.
+ *
+ * 5.2 Generate materializations
+ *
+ * Once we have the references we add new 'materialization blocks' on the edges
+ * where escape becomes inevitable. This information is calculated by the
+ * execution-subgraphs created during load-store-analysis. We create new
+ * 'materialization's in these blocks and initialize them with the value of
+ * each heap-location ignoring side effects (since the object hasn't escaped
+ * yet). Worst case this is the same time-complexity as step 3 since we may
+ * need to materialize phis.
+ *
+ *    O(heap_locations^2 * materialization_edges)
+ *
+ * 5.3 Propagate materializations
+ *
+ * Since we use the materialization as the marker for escape we need to
+ * propagate it throughout the graph. Since the subgraph analysis considers any
+ * lifetime that escapes a loop (and hence would require a loop-phi) to be
+ * escaping at the loop-header we do not need to create any loop-phis to do
+ * this.
+ *
+ *    O(edges)
+ *
+ * NB: Currently the subgraph analysis considers all objects to have their
+ * lifetimes start at the entry block. This simplifies that analysis enormously
+ * but means that we cannot distinguish between an escape in a loop where the
+ * lifetime does not escape the loop (in which case this pass could optimize)
+ * and one where it does escape the loop (in which case the whole loop is
+ * escaping). This is a shortcoming that would be good to fix at some point.
+ *
+ * 5.4 Propagate partial values
+ *
+ * We need to replace loads and stores to the partial reference with predicated
+ * ones that have default non-escaping values. Again this is the same as step 3.
+ *
+ *   O(heap_locations^2 * edges)
+ *
+ * 5.5 Final fixup
+ *
+ * Now all we need to do is replace and remove uses of the old reference with the
+ * appropriate materialization.
+ *
+ *   O(instructions + uses)
+ *
+ * FIXME: The time complexities described above assumes that the
+ * HeapLocationCollector finds a heap location for an instruction in O(1)
+ * time but it is currently O(heap_locations); this can be fixed by adding
+ * a hash map to the HeapLocationCollector.
  */
 
 namespace art {
 
-// An unknown heap value. Loads with such a value in the heap location cannot be eliminated.
-// A heap location can be set to kUnknownHeapValue when:
-// - initially set a value.
-// - killed due to aliasing, merging, invocation, or loop side effects.
-static HInstruction* const kUnknownHeapValue =
-    reinterpret_cast<HInstruction*>(static_cast<uintptr_t>(-1));
+#define LSE_VLOG \
+  if (::art::LoadStoreElimination::kVerboseLoggingMode && VLOG_IS_ON(compiler)) LOG(INFO)
 
-// Default heap value after an allocation.
-// A heap location can be set to that value right after an allocation.
-static HInstruction* const kDefaultHeapValue =
-    reinterpret_cast<HInstruction*>(static_cast<uintptr_t>(-2));
+class PartialLoadStoreEliminationHelper;
+class HeapRefHolder;
 
 // Use HGraphDelegateVisitor for which all VisitInvokeXXX() delegate to VisitInvoke().
-class LSEVisitor : public HGraphDelegateVisitor {
+class LSEVisitor final : private HGraphDelegateVisitor {
  public:
   LSEVisitor(HGraph* graph,
-             const HeapLocationCollector& heap_locations_collector,
-             const SideEffectsAnalysis& side_effects,
-             OptimizingCompilerStats* stats)
-      : HGraphDelegateVisitor(graph, stats),
-        heap_location_collector_(heap_locations_collector),
-        side_effects_(side_effects),
-        allocator_(graph->GetArenaStack()),
-        heap_values_for_(graph->GetBlocks().size(),
-                         ScopedArenaVector<HInstruction*>(heap_locations_collector.
-                                                          GetNumberOfHeapLocations(),
-                                                          kUnknownHeapValue,
-                                                          allocator_.Adapter(kArenaAllocLSE)),
-                         allocator_.Adapter(kArenaAllocLSE)),
-        removed_loads_(allocator_.Adapter(kArenaAllocLSE)),
-        substitute_instructions_for_loads_(allocator_.Adapter(kArenaAllocLSE)),
-        possibly_removed_stores_(allocator_.Adapter(kArenaAllocLSE)),
-        singleton_new_instances_(allocator_.Adapter(kArenaAllocLSE)) {
+             const HeapLocationCollector& heap_location_collector,
+             bool perform_partial_lse,
+             OptimizingCompilerStats* stats);
+
+  void Run();
+
+ private:
+  class PhiPlaceholder {
+   public:
+    constexpr PhiPlaceholder() : block_id_(-1), heap_location_(-1) {}
+    constexpr PhiPlaceholder(uint32_t block_id, size_t heap_location)
+        : block_id_(block_id), heap_location_(dchecked_integral_cast<uint32_t>(heap_location)) {}
+
+    constexpr PhiPlaceholder(const PhiPlaceholder& p) = default;
+    constexpr PhiPlaceholder(PhiPlaceholder&& p) = default;
+    constexpr PhiPlaceholder& operator=(const PhiPlaceholder& p) = default;
+    constexpr PhiPlaceholder& operator=(PhiPlaceholder&& p) = default;
+
+    constexpr uint32_t GetBlockId() const {
+      return block_id_;
+    }
+
+    constexpr size_t GetHeapLocation() const {
+      return heap_location_;
+    }
+
+    constexpr bool Equals(const PhiPlaceholder& p2) const {
+      return block_id_ == p2.block_id_ && heap_location_ == p2.heap_location_;
+    }
+
+    void Dump(std::ostream& oss) const {
+      oss << "PhiPlaceholder[blk: " << block_id_ << ", heap_location_: " << heap_location_ << "]";
+    }
+
+   private:
+    uint32_t block_id_;
+    uint32_t heap_location_;
+  };
+
+  struct Marker {};
+
+  class Value;
+
+  class PriorValueHolder {
+   public:
+    constexpr explicit PriorValueHolder(Value prior);
+
+    constexpr bool IsInstruction() const {
+      return std::holds_alternative<HInstruction*>(value_);
+    }
+    constexpr bool IsPhi() const {
+      return std::holds_alternative<PhiPlaceholder>(value_);
+    }
+    constexpr bool IsDefault() const {
+      return std::holds_alternative<Marker>(value_);
+    }
+    constexpr PhiPlaceholder GetPhiPlaceholder() const {
+      DCHECK(IsPhi());
+      return std::get<PhiPlaceholder>(value_);
+    }
+    constexpr HInstruction* GetInstruction() const {
+      DCHECK(IsInstruction());
+      return std::get<HInstruction*>(value_);
+    }
+
+    Value ToValue() const;
+    void Dump(std::ostream& oss) const;
+
+    constexpr bool Equals(PriorValueHolder other) const {
+      return value_ == other.value_;
+    }
+
+   private:
+    std::variant<Marker, HInstruction*, PhiPlaceholder> value_;
+  };
+
+  friend constexpr bool operator==(const Marker&, const Marker&);
+  friend constexpr bool operator==(const PriorValueHolder& p1, const PriorValueHolder& p2);
+  friend constexpr bool operator==(const PhiPlaceholder& p1, const PhiPlaceholder& p2);
+  friend std::ostream& operator<<(std::ostream& oss, const PhiPlaceholder& p2);
+
+  class Value {
+   public:
+    enum class ValuelessType {
+      kInvalid,
+      kPureUnknown,
+      kDefault,
+    };
+    struct MergedUnknownMarker {
+      PhiPlaceholder phi_;
+    };
+    struct NeedsNonLoopPhiMarker {
+      PhiPlaceholder phi_;
+    };
+    struct NeedsLoopPhiMarker {
+      PhiPlaceholder phi_;
+    };
+
+    static constexpr Value Invalid() {
+      return Value(ValuelessType::kInvalid);
+    }
+
+    // An unknown heap value. Loads with such a value in the heap location cannot be eliminated.
+    // A heap location can be set to an unknown heap value when:
+    // - it is coming from outside the method,
+    // - it is killed due to aliasing, or side effects, or merging with an unknown value.
+    static constexpr Value PureUnknown() {
+      return Value(ValuelessType::kPureUnknown);
+    }
+
+    static constexpr Value PartialUnknown(Value old_value) {
+      if (old_value.IsInvalid() || old_value.IsPureUnknown()) {
+        return PureUnknown();
+      } else {
+        return Value(PriorValueHolder(old_value));
+      }
+    }
+
+    static constexpr Value MergedUnknown(PhiPlaceholder phi_placeholder) {
+      return Value(MergedUnknownMarker{phi_placeholder});
+    }
+
+    // Default heap value after an allocation.
+    // A heap location can be set to that value right after an allocation.
+    static constexpr Value Default() {
+      return Value(ValuelessType::kDefault);
+    }
+
+    static constexpr Value ForInstruction(HInstruction* instruction) {
+      return Value(instruction);
+    }
+
+    static constexpr Value ForNonLoopPhiPlaceholder(PhiPlaceholder phi_placeholder) {
+      return Value(NeedsNonLoopPhiMarker{phi_placeholder});
+    }
+
+    static constexpr Value ForLoopPhiPlaceholder(PhiPlaceholder phi_placeholder) {
+      return Value(NeedsLoopPhiMarker{phi_placeholder});
+    }
+
+    static constexpr Value ForPhiPlaceholder(PhiPlaceholder phi_placeholder, bool needs_loop_phi) {
+      return needs_loop_phi ? ForLoopPhiPlaceholder(phi_placeholder)
+                            : ForNonLoopPhiPlaceholder(phi_placeholder);
+    }
+
+    constexpr bool IsValid() const {
+      return !IsInvalid();
+    }
+
+    constexpr bool IsInvalid() const {
+      return std::holds_alternative<ValuelessType>(value_) &&
+             GetValuelessType() == ValuelessType::kInvalid;
+    }
+
+    bool IsPartialUnknown() const {
+      return std::holds_alternative<PriorValueHolder>(value_);
+    }
+
+    bool IsMergedUnknown() const {
+      return std::holds_alternative<MergedUnknownMarker>(value_);
+    }
+
+    bool IsPureUnknown() const {
+      return std::holds_alternative<ValuelessType>(value_) &&
+             GetValuelessType() == ValuelessType::kPureUnknown;
+    }
+
+    bool IsUnknown() const {
+      return IsPureUnknown() || IsMergedUnknown() || IsPartialUnknown();
+    }
+
+    bool IsDefault() const {
+      return std::holds_alternative<ValuelessType>(value_) &&
+             GetValuelessType() == ValuelessType::kDefault;
+    }
+
+    bool IsInstruction() const {
+      return std::holds_alternative<HInstruction*>(value_);
+    }
+
+    bool NeedsNonLoopPhi() const {
+      return std::holds_alternative<NeedsNonLoopPhiMarker>(value_);
+    }
+
+    bool NeedsLoopPhi() const {
+      return std::holds_alternative<NeedsLoopPhiMarker>(value_);
+    }
+
+    bool NeedsPhi() const {
+      return NeedsNonLoopPhi() || NeedsLoopPhi();
+    }
+
+    HInstruction* GetInstruction() const {
+      DCHECK(IsInstruction()) << *this;
+      return std::get<HInstruction*>(value_);
+    }
+
+    PriorValueHolder GetPriorValue() const {
+      DCHECK(IsPartialUnknown());
+      return std::get<PriorValueHolder>(value_);
+    }
+
+    PhiPlaceholder GetPhiPlaceholder() const {
+      DCHECK(NeedsPhi() || IsMergedUnknown());
+      if (NeedsNonLoopPhi()) {
+        return std::get<NeedsNonLoopPhiMarker>(value_).phi_;
+      } else if (NeedsLoopPhi()) {
+        return std::get<NeedsLoopPhiMarker>(value_).phi_;
+      } else {
+        return std::get<MergedUnknownMarker>(value_).phi_;
+      }
+    }
+
+    uint32_t GetMergeBlockId() const {
+      DCHECK(IsMergedUnknown()) << this;
+      return std::get<MergedUnknownMarker>(value_).phi_.GetBlockId();
+    }
+
+    HBasicBlock* GetMergeBlock(const HGraph* graph) const {
+      DCHECK(IsMergedUnknown()) << *this;
+      return graph->GetBlocks()[GetMergeBlockId()];
+    }
+
+    size_t GetHeapLocation() const {
+      DCHECK(IsMergedUnknown() || NeedsPhi()) << this;
+      return GetPhiPlaceholder().GetHeapLocation();
+    }
+
+    constexpr bool ExactEquals(Value other) const;
+
+    constexpr bool Equals(Value other) const;
+
+    constexpr bool Equals(HInstruction* instruction) const {
+      return Equals(ForInstruction(instruction));
+    }
+
+    std::ostream& Dump(std::ostream& os) const;
+
+    // Public for use with lists.
+    constexpr Value() : value_(ValuelessType::kInvalid) {}
+
+   private:
+    using ValueHolder = std::variant<ValuelessType,
+                                     HInstruction*,
+                                     MergedUnknownMarker,
+                                     NeedsNonLoopPhiMarker,
+                                     NeedsLoopPhiMarker,
+                                     PriorValueHolder>;
+    constexpr ValuelessType GetValuelessType() const {
+      return std::get<ValuelessType>(value_);
+    }
+
+    constexpr explicit Value(ValueHolder v) : value_(v) {}
+
+    friend std::ostream& operator<<(std::ostream& os, const Value& v);
+
+    ValueHolder value_;
+
+    static_assert(std::is_move_assignable<PhiPlaceholder>::value);
+  };
+
+  friend constexpr bool operator==(const Value::NeedsLoopPhiMarker& p1,
+                                   const Value::NeedsLoopPhiMarker& p2);
+  friend constexpr bool operator==(const Value::NeedsNonLoopPhiMarker& p1,
+                                   const Value::NeedsNonLoopPhiMarker& p2);
+  friend constexpr bool operator==(const Value::MergedUnknownMarker& p1,
+                                   const Value::MergedUnknownMarker& p2);
+
+  // Get Phi placeholder index for access to `phi_placeholder_replacements_`
+  // and "visited" bit vectors during depth-first searches.
+  size_t PhiPlaceholderIndex(PhiPlaceholder phi_placeholder) const {
+    size_t res =
+        phi_placeholder.GetBlockId() * heap_location_collector_.GetNumberOfHeapLocations() +
+        phi_placeholder.GetHeapLocation();
+    DCHECK_EQ(phi_placeholder, GetPhiPlaceholderAt(res))
+        << res << "blks: " << GetGraph()->GetBlocks().size()
+        << " hls: " << heap_location_collector_.GetNumberOfHeapLocations();
+    return res;
   }
 
-  void VisitBasicBlock(HBasicBlock* block) override {
-    // Populate the heap_values array for this block.
-    // TODO: try to reuse the heap_values array from one predecessor if possible.
-    if (block->IsLoopHeader()) {
-      HandleLoopSideEffects(block);
+  size_t PhiPlaceholderIndex(Value phi_placeholder) const {
+    return PhiPlaceholderIndex(phi_placeholder.GetPhiPlaceholder());
+  }
+
+  bool IsPartialNoEscape(HBasicBlock* blk, size_t idx) {
+    auto* ri = heap_location_collector_.GetHeapLocation(idx)->GetReferenceInfo();
+    if (!ri->IsPartialSingleton()) {
+      return false;
+    }
+    ArrayRef<const ExecutionSubgraph::ExcludedCohort> cohorts =
+        ri->GetNoEscapeSubgraph()->GetExcludedCohorts();
+    return std::none_of(cohorts.cbegin(),
+                        cohorts.cend(),
+                        [&](const ExecutionSubgraph::ExcludedCohort& ex) -> bool {
+                          // Make sure we haven't yet and never will escape.
+                          return ex.PrecedesBlock(blk) ||
+                                 ex.ContainsBlock(blk) ||
+                                 ex.SucceedsBlock(blk);
+                        });
+  }
+
+  PhiPlaceholder GetPhiPlaceholderAt(size_t off) const {
+    DCHECK_LT(off, num_phi_placeholders_);
+    size_t id = off % heap_location_collector_.GetNumberOfHeapLocations();
+    // Technically this should be (off - id) / NumberOfHeapLocations
+    // but due to truncation it's all the same.
+    size_t blk_id = off / heap_location_collector_.GetNumberOfHeapLocations();
+    return GetPhiPlaceholder(blk_id, id);
+  }
+
+  PhiPlaceholder GetPhiPlaceholder(uint32_t block_id, size_t idx) const {
+    DCHECK(GetGraph()->GetBlocks()[block_id] != nullptr) << block_id;
+    return PhiPlaceholder(block_id, idx);
+  }
+
+  Value Replacement(Value value) const {
+    DCHECK(value.NeedsPhi() ||
+           (current_phase_ == Phase::kPartialElimination && value.IsMergedUnknown()))
+        << value << " phase: " << current_phase_;
+    Value replacement = phi_placeholder_replacements_[PhiPlaceholderIndex(value)];
+    DCHECK(replacement.IsUnknown() || replacement.IsInstruction());
+    DCHECK(replacement.IsUnknown() ||
+           FindSubstitute(replacement.GetInstruction()) == replacement.GetInstruction());
+    return replacement;
+  }
+
+  Value ReplacementOrValue(Value value) const {
+    if (current_phase_ == Phase::kPartialElimination) {
+      // In this phase we are materializing the default values which are used
+      // only if the partial singleton did not escape, so we can replace
+      // a partial unknown with the prior value.
+      if (value.IsPartialUnknown()) {
+        value = value.GetPriorValue().ToValue();
+      }
+      if ((value.IsMergedUnknown() || value.NeedsPhi()) &&
+          phi_placeholder_replacements_[PhiPlaceholderIndex(value)].IsValid()) {
+        value = phi_placeholder_replacements_[PhiPlaceholderIndex(value)];
+        DCHECK(!value.IsMergedUnknown());
+        DCHECK(!value.NeedsPhi());
+      } else if (value.IsMergedUnknown()) {
+        return Value::ForLoopPhiPlaceholder(value.GetPhiPlaceholder());
+      }
+      if (value.IsInstruction() && value.GetInstruction()->IsInstanceFieldGet()) {
+        DCHECK_LT(static_cast<size_t>(value.GetInstruction()->GetId()),
+                  substitute_instructions_for_loads_.size());
+        HInstruction* substitute =
+            substitute_instructions_for_loads_[value.GetInstruction()->GetId()];
+        if (substitute != nullptr) {
+          DCHECK(substitute->IsPredicatedInstanceFieldGet());
+          return Value::ForInstruction(substitute);
+        }
+      }
+      DCHECK(!value.IsInstruction() ||
+             FindSubstitute(value.GetInstruction()) == value.GetInstruction());
+      return value;
+    }
+    if (value.NeedsPhi() && phi_placeholder_replacements_[PhiPlaceholderIndex(value)].IsValid()) {
+      return Replacement(value);
     } else {
-      MergePredecessorValues(block);
+      DCHECK(!value.IsInstruction() ||
+             FindSubstitute(value.GetInstruction()) == value.GetInstruction());
+      return value;
     }
-    HGraphVisitor::VisitBasicBlock(block);
   }
 
-  HTypeConversion* AddTypeConversionIfNecessary(HInstruction* instruction,
-                                                HInstruction* value,
-                                                DataType::Type expected_type) {
-    HTypeConversion* type_conversion = nullptr;
+  // The record of a heap value and instruction(s) that feed that value.
+  struct ValueRecord {
+    Value value;
+    Value stored_by;
+  };
+
+  HTypeConversion* FindOrAddTypeConversionIfNecessary(HInstruction* instruction,
+                                                      HInstruction* value,
+                                                      DataType::Type expected_type) {
     // Should never add type conversion into boolean value.
-    if (expected_type != DataType::Type::kBool &&
-        !DataType::IsTypeConversionImplicit(value->GetType(), expected_type)) {
-      type_conversion = new (GetGraph()->GetAllocator()) HTypeConversion(
-          expected_type, value, instruction->GetDexPc());
-      instruction->GetBlock()->InsertInstructionBefore(type_conversion, instruction);
+    if (expected_type == DataType::Type::kBool ||
+        DataType::IsTypeConversionImplicit(value->GetType(), expected_type) ||
+        // TODO: This prevents type conversion of default values but we can still insert
+        // type conversion of other constants and there is no constant folding pass after LSE.
+        IsZeroBitPattern(value)) {
+      return nullptr;
     }
+
+    // Check if there is already a suitable TypeConversion we can reuse.
+    for (const HUseListNode<HInstruction*>& use : value->GetUses()) {
+      if (use.GetUser()->IsTypeConversion() &&
+          use.GetUser()->GetType() == expected_type &&
+          // TODO: We could move the TypeConversion to a common dominator
+          // if it does not cross irreducible loop header.
+          use.GetUser()->GetBlock()->Dominates(instruction->GetBlock()) &&
+          // Don't share across irreducible loop headers.
+          // TODO: can be more fine-grained than this by testing each dominator.
+          (use.GetUser()->GetBlock() == instruction->GetBlock() ||
+           !GetGraph()->HasIrreducibleLoops())) {
+        if (use.GetUser()->GetBlock() == instruction->GetBlock() &&
+            use.GetUser()->GetBlock()->GetInstructions().FoundBefore(instruction, use.GetUser())) {
+          // Move the TypeConversion before the instruction.
+          use.GetUser()->MoveBefore(instruction);
+        }
+        DCHECK(use.GetUser()->StrictlyDominates(instruction));
+        return use.GetUser()->AsTypeConversion();
+      }
+    }
+
+    // We must create a new TypeConversion instruction.
+    HTypeConversion* type_conversion = new (GetGraph()->GetAllocator()) HTypeConversion(
+          expected_type, value, instruction->GetDexPc());
+    instruction->GetBlock()->InsertInstructionBefore(type_conversion, instruction);
     return type_conversion;
   }
 
   // Find an instruction's substitute if it's a removed load.
   // Return the same instruction if it should not be removed.
-  HInstruction* FindSubstitute(HInstruction* instruction) {
-    if (!IsLoad(instruction)) {
+  HInstruction* FindSubstitute(HInstruction* instruction) const {
+    size_t id = static_cast<size_t>(instruction->GetId());
+    if (id >= substitute_instructions_for_loads_.size()) {
+      // New Phi (may not be in the graph yet), default value or PredicatedInstanceFieldGet.
+      DCHECK(!IsLoad(instruction) || instruction->IsPredicatedInstanceFieldGet());
       return instruction;
     }
-    size_t size = removed_loads_.size();
-    for (size_t i = 0; i < size; i++) {
-      if (removed_loads_[i] == instruction) {
-        HInstruction* substitute = substitute_instructions_for_loads_[i];
-        // The substitute list is a flat hierarchy.
-        DCHECK_EQ(FindSubstitute(substitute), substitute);
-        return substitute;
-      }
-    }
-    return instruction;
+    HInstruction* substitute = substitute_instructions_for_loads_[id];
+    DCHECK(substitute == nullptr || IsLoad(instruction));
+    return (substitute != nullptr) ? substitute : instruction;
   }
 
   void AddRemovedLoad(HInstruction* load, HInstruction* heap_value) {
     DCHECK(IsLoad(load));
+    DCHECK_EQ(FindSubstitute(load), load);
     DCHECK_EQ(FindSubstitute(heap_value), heap_value) <<
         "Unexpected heap_value that has a substitute " << heap_value->DebugName();
-    removed_loads_.push_back(load);
-    substitute_instructions_for_loads_.push_back(heap_value);
+
+    // The load expects to load the heap value as type load->GetType().
+    // However the tracked heap value may not be of that type. An explicit
+    // type conversion may be needed.
+    // There are actually three types involved here:
+    // (1) tracked heap value's type (type A)
+    // (2) heap location (field or element)'s type (type B)
+    // (3) load's type (type C)
+    // We guarantee that type A stored as type B and then fetched out as
+    // type C is the same as casting from type A to type C directly, since
+    // type B and type C will have the same size which is guaranteed in
+    // HInstanceFieldGet/HStaticFieldGet/HArrayGet/HVecLoad's SetType().
+    // So we only need one type conversion from type A to type C.
+    HTypeConversion* type_conversion = FindOrAddTypeConversionIfNecessary(
+        load, heap_value, load->GetType());
+
+    substitute_instructions_for_loads_[load->GetId()] =
+        type_conversion != nullptr ? type_conversion : heap_value;
   }
 
-  // Scan the list of removed loads to see if we can reuse `type_conversion`, if
-  // the other removed load has the same substitute and type and is dominated
-  // by `type_conversion`.
-  void TryToReuseTypeConversion(HInstruction* type_conversion, size_t index) {
-    size_t size = removed_loads_.size();
-    HInstruction* load = removed_loads_[index];
-    HInstruction* substitute = substitute_instructions_for_loads_[index];
-    for (size_t j = index + 1; j < size; j++) {
-      HInstruction* load2 = removed_loads_[j];
-      HInstruction* substitute2 = substitute_instructions_for_loads_[j];
-      if (load2 == nullptr) {
-        DCHECK(substitute2->IsTypeConversion());
-        continue;
-      }
-      DCHECK(IsLoad(load2));
-      DCHECK(substitute2 != nullptr);
-      if (substitute2 == substitute &&
-          load2->GetType() == load->GetType() &&
-          type_conversion->GetBlock()->Dominates(load2->GetBlock()) &&
-          // Don't share across irreducible loop headers.
-          // TODO: can be more fine-grained than this by testing each dominator.
-          (load2->GetBlock() == type_conversion->GetBlock() ||
-           !GetGraph()->HasIrreducibleLoops())) {
-        // The removed_loads_ are added in reverse post order.
-        DCHECK(type_conversion->StrictlyDominates(load2));
-        load2->ReplaceWith(type_conversion);
-        load2->GetBlock()->RemoveInstruction(load2);
-        removed_loads_[j] = nullptr;
-        substitute_instructions_for_loads_[j] = type_conversion;
-      }
-    }
-  }
-
-  // Remove recorded instructions that should be eliminated.
-  void RemoveInstructions() {
-    size_t size = removed_loads_.size();
-    DCHECK_EQ(size, substitute_instructions_for_loads_.size());
-    for (size_t i = 0; i < size; i++) {
-      HInstruction* load = removed_loads_[i];
-      if (load == nullptr) {
-        // The load has been handled in the scan for type conversion below.
-        DCHECK(substitute_instructions_for_loads_[i]->IsTypeConversion());
-        continue;
-      }
-      DCHECK(IsLoad(load));
-      HInstruction* substitute = substitute_instructions_for_loads_[i];
-      DCHECK(substitute != nullptr);
-      // We proactively retrieve the substitute for a removed load, so
-      // a load that has a substitute should not be observed as a heap
-      // location value.
-      DCHECK_EQ(FindSubstitute(substitute), substitute);
-
-      // The load expects to load the heap value as type load->GetType().
-      // However the tracked heap value may not be of that type. An explicit
-      // type conversion may be needed.
-      // There are actually three types involved here:
-      // (1) tracked heap value's type (type A)
-      // (2) heap location (field or element)'s type (type B)
-      // (3) load's type (type C)
-      // We guarantee that type A stored as type B and then fetched out as
-      // type C is the same as casting from type A to type C directly, since
-      // type B and type C will have the same size which is guarenteed in
-      // HInstanceFieldGet/HStaticFieldGet/HArrayGet/HVecLoad's SetType().
-      // So we only need one type conversion from type A to type C.
-      HTypeConversion* type_conversion = AddTypeConversionIfNecessary(
-          load, substitute, load->GetType());
-      if (type_conversion != nullptr) {
-        TryToReuseTypeConversion(type_conversion, i);
-        load->ReplaceWith(type_conversion);
-        substitute_instructions_for_loads_[i] = type_conversion;
-      } else {
-        load->ReplaceWith(substitute);
-      }
-      load->GetBlock()->RemoveInstruction(load);
-    }
-
-    // At this point, stores in possibly_removed_stores_ can be safely removed.
-    for (HInstruction* store : possibly_removed_stores_) {
-      DCHECK(IsStore(store));
-      store->GetBlock()->RemoveInstruction(store);
-    }
-
-    // Eliminate singleton-classified instructions:
-    //   * - Constructor fences (they never escape this thread).
-    //   * - Allocations (if they are unused).
-    for (HInstruction* new_instance : singleton_new_instances_) {
-      size_t removed = HConstructorFence::RemoveConstructorFences(new_instance);
-      MaybeRecordStat(stats_,
-                      MethodCompilationStat::kConstructorFenceRemovedLSE,
-                      removed);
-
-      if (!new_instance->HasNonEnvironmentUses()) {
-        new_instance->RemoveEnvironmentUsers();
-        new_instance->GetBlock()->RemoveInstruction(new_instance);
-      }
-    }
-  }
-
- private:
-  static bool IsLoad(const HInstruction* instruction) {
-    if (instruction == kUnknownHeapValue || instruction == kDefaultHeapValue) {
-      return false;
-    }
+  static bool IsLoad(HInstruction* instruction) {
     // Unresolved load is not treated as a load.
     return instruction->IsInstanceFieldGet() ||
-        instruction->IsStaticFieldGet() ||
-        instruction->IsVecLoad() ||
-        instruction->IsArrayGet();
+           instruction->IsPredicatedInstanceFieldGet() ||
+           instruction->IsStaticFieldGet() ||
+           instruction->IsVecLoad() ||
+           instruction->IsArrayGet();
   }
 
-  static bool IsStore(const HInstruction* instruction) {
-    if (instruction == kUnknownHeapValue || instruction == kDefaultHeapValue) {
-      return false;
-    }
+  static bool IsStore(HInstruction* instruction) {
     // Unresolved store is not treated as a store.
     return instruction->IsInstanceFieldSet() ||
-        instruction->IsArraySet() ||
-        instruction->IsVecStore() ||
-        instruction->IsStaticFieldSet();
+           instruction->IsArraySet() ||
+           instruction->IsVecStore() ||
+           instruction->IsStaticFieldSet();
   }
 
-  // Check if it is allowed to use default values for the specified load.
-  static bool IsDefaultAllowedForLoad(const HInstruction* load) {
-    DCHECK(IsLoad(load));
+  // Check if it is allowed to use default values or Phis for the specified load.
+  static bool IsDefaultOrPhiAllowedForLoad(HInstruction* instruction) {
+    DCHECK(IsLoad(instruction));
     // Using defaults for VecLoads requires to create additional vector operations.
     // As there are some issues with scheduling vector operations it is better to avoid creating
     // them.
-    return !load->IsVecOperation();
+    return !instruction->IsVecOperation();
   }
 
-  // Returns the real heap value by finding its substitute or by "peeling"
-  // a store instruction.
-  HInstruction* GetRealHeapValue(HInstruction* heap_value) {
-    if (IsLoad(heap_value)) {
-      return FindSubstitute(heap_value);
-    }
-    if (!IsStore(heap_value)) {
-      return heap_value;
-    }
-
-    // We keep track of store instructions as the heap values which might be
-    // eliminated if the stores are later found not necessary. The real stored
-    // value needs to be fetched from the store instruction.
-    if (heap_value->IsInstanceFieldSet()) {
-      heap_value = heap_value->AsInstanceFieldSet()->GetValue();
-    } else if (heap_value->IsStaticFieldSet()) {
-      heap_value = heap_value->AsStaticFieldSet()->GetValue();
-    } else if (heap_value->IsVecStore()) {
-      heap_value = heap_value->AsVecStore()->GetValue();
-    } else {
-      DCHECK(heap_value->IsArraySet());
-      heap_value = heap_value->AsArraySet()->GetValue();
-    }
-    // heap_value may already be a removed load.
-    return FindSubstitute(heap_value);
-  }
-
-  // If heap_value is a store, need to keep the store.
-  // This is necessary if a heap value is killed or replaced by another value,
-  // so that the store is no longer used to track heap value.
-  void KeepIfIsStore(HInstruction* heap_value) {
-    if (!IsStore(heap_value)) {
+  // Keep the store referenced by the instruction, or all stores that feed a Phi placeholder.
+  // This is necessary if the stored heap value can be observed.
+  void KeepStores(Value value) {
+    if (value.IsPureUnknown() || value.IsPartialUnknown()) {
       return;
     }
-    auto idx = std::find(possibly_removed_stores_.begin(),
-        possibly_removed_stores_.end(), heap_value);
-    if (idx != possibly_removed_stores_.end()) {
-      // Make sure the store is kept.
-      possibly_removed_stores_.erase(idx);
+    if (value.IsMergedUnknown()) {
+      kept_merged_unknowns_.SetBit(PhiPlaceholderIndex(value));
+      phi_placeholders_to_search_for_kept_stores_.SetBit(PhiPlaceholderIndex(value));
+      return;
+    }
+    if (value.NeedsPhi()) {
+      phi_placeholders_to_search_for_kept_stores_.SetBit(PhiPlaceholderIndex(value));
+    } else {
+      HInstruction* instruction = value.GetInstruction();
+      DCHECK(IsStore(instruction));
+      kept_stores_.SetBit(instruction->GetId());
     }
   }
 
@@ -333,183 +831,21 @@
   // and heap_values of that heap location X holds a store, keep that store.
   // It's needed for a dependent load that's not eliminated since any store
   // that may put value into the load's heap location needs to be kept.
-  void KeepStoresIfAliasedToLocation(ScopedArenaVector<HInstruction*>& heap_values,
+  void KeepStoresIfAliasedToLocation(ScopedArenaVector<ValueRecord>& heap_values,
                                      size_t loc_index) {
-    for (size_t i = 0; i < heap_values.size(); i++) {
-      if ((i == loc_index) || heap_location_collector_.MayAlias(i, loc_index)) {
-        KeepIfIsStore(heap_values[i]);
-      }
-    }
-  }
-
-  void HandleLoopSideEffects(HBasicBlock* block) {
-    DCHECK(block->IsLoopHeader());
-    int block_id = block->GetBlockId();
-    ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[block_id];
-    HBasicBlock* pre_header = block->GetLoopInformation()->GetPreHeader();
-    ScopedArenaVector<HInstruction*>& pre_header_heap_values =
-        heap_values_for_[pre_header->GetBlockId()];
-
-    // Don't eliminate loads in irreducible loops.
-    // Also keep the stores before the loop.
-    if (block->GetLoopInformation()->IsIrreducible()) {
-      if (kIsDebugBuild) {
-        for (size_t i = 0; i < heap_values.size(); i++) {
-          DCHECK_EQ(heap_values[i], kUnknownHeapValue);
-        }
-      }
-      for (size_t i = 0; i < heap_values.size(); i++) {
-        KeepIfIsStore(pre_header_heap_values[i]);
-      }
-      return;
-    }
-
-    // Inherit the values from pre-header.
-    for (size_t i = 0; i < heap_values.size(); i++) {
-      heap_values[i] = pre_header_heap_values[i];
-    }
-
-    // We do a single pass in reverse post order. For loops, use the side effects as a hint
-    // to see if the heap values should be killed.
-    if (side_effects_.GetLoopEffects(block).DoesAnyWrite()) {
-      for (size_t i = 0; i < heap_values.size(); i++) {
-        HeapLocation* location = heap_location_collector_.GetHeapLocation(i);
-        ReferenceInfo* ref_info = location->GetReferenceInfo();
-        if (ref_info->IsSingleton() && !location->IsValueKilledByLoopSideEffects()) {
-          // A singleton's field that's not stored into inside a loop is
-          // invariant throughout the loop. Nothing to do.
-        } else {
-          // heap value is killed by loop side effects.
-          KeepIfIsStore(pre_header_heap_values[i]);
-          heap_values[i] = kUnknownHeapValue;
-        }
-      }
-    } else {
-      // The loop doesn't kill any value.
-    }
-  }
-
-  void MergePredecessorValues(HBasicBlock* block) {
-    ArrayRef<HBasicBlock* const> predecessors(block->GetPredecessors());
-    if (predecessors.size() == 0) {
-      return;
-    }
-    if (block->IsExitBlock()) {
-      // Exit block doesn't really merge values since the control flow ends in
-      // its predecessors. Each predecessor needs to make sure stores are kept
-      // if necessary.
-      return;
-    }
-
-    ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[block->GetBlockId()];
-    for (size_t i = 0; i < heap_values.size(); i++) {
-      HInstruction* merged_value = nullptr;
-      // If we can merge the store itself from the predecessors, we keep
-      // the store as the heap value as long as possible. In case we cannot
-      // merge the store, we try to merge the values of the stores.
-      HInstruction* merged_store_value = nullptr;
-      // Whether merged_value is a result that's merged from all predecessors.
-      bool from_all_predecessors = true;
-      ReferenceInfo* ref_info = heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo();
-      HInstruction* ref = ref_info->GetReference();
-      HInstruction* singleton_ref = nullptr;
-      if (ref_info->IsSingleton()) {
-        // We do more analysis based on singleton's liveness when merging
-        // heap values for such cases.
-        singleton_ref = ref;
-      }
-
-      for (HBasicBlock* predecessor : predecessors) {
-        HInstruction* pred_value = heap_values_for_[predecessor->GetBlockId()][i];
-        if (!IsStore(pred_value)) {
-          pred_value = FindSubstitute(pred_value);
-        }
-        DCHECK(pred_value != nullptr);
-        HInstruction* pred_store_value = GetRealHeapValue(pred_value);
-        if ((singleton_ref != nullptr) &&
-            !singleton_ref->GetBlock()->Dominates(predecessor)) {
-          // singleton_ref is not live in this predecessor. No need to merge
-          // since singleton_ref is not live at the beginning of this block.
-          DCHECK_EQ(pred_value, kUnknownHeapValue);
-          from_all_predecessors = false;
-          break;
-        }
-        if (merged_value == nullptr) {
-          // First seen heap value.
-          DCHECK(pred_value != nullptr);
-          merged_value = pred_value;
-        } else if (pred_value != merged_value) {
-          // There are conflicting values.
-          merged_value = kUnknownHeapValue;
-          // We may still be able to merge store values.
-        }
-
-        // Conflicting stores may be storing the same value. We do another merge
-        // of real stored values.
-        if (merged_store_value == nullptr) {
-          // First seen store value.
-          DCHECK(pred_store_value != nullptr);
-          merged_store_value = pred_store_value;
-        } else if (pred_store_value != merged_store_value) {
-          // There are conflicting store values.
-          merged_store_value = kUnknownHeapValue;
-          // There must be conflicting stores also.
-          DCHECK_EQ(merged_value, kUnknownHeapValue);
-          // No need to merge anymore.
-          break;
-        }
-      }
-
-      if (merged_value == nullptr) {
-        DCHECK(!from_all_predecessors);
-        DCHECK(singleton_ref != nullptr);
-      }
-      if (from_all_predecessors) {
-        if (ref_info->IsSingletonAndRemovable() &&
-            (block->IsSingleReturnOrReturnVoidAllowingPhis() ||
-             (block->EndsWithReturn() && (merged_value != kUnknownHeapValue ||
-                                          merged_store_value != kUnknownHeapValue)))) {
-          // Values in the singleton are not needed anymore:
-          // (1) if this block consists of a sole return, or
-          // (2) if this block returns and a usable merged value is obtained
-          //     (loads prior to the return will always use that value).
-        } else if (!IsStore(merged_value)) {
-          // We don't track merged value as a store anymore. We have to
-          // hold the stores in predecessors live here.
-          for (HBasicBlock* predecessor : predecessors) {
-            ScopedArenaVector<HInstruction*>& pred_values =
-                heap_values_for_[predecessor->GetBlockId()];
-            KeepIfIsStore(pred_values[i]);
-          }
-        }
-      } else {
-        DCHECK(singleton_ref != nullptr);
-        // singleton_ref is non-existing at the beginning of the block. There is
-        // no need to keep the stores.
-      }
-
-      if (!from_all_predecessors) {
-        DCHECK(singleton_ref != nullptr);
-        DCHECK((singleton_ref->GetBlock() == block) ||
-               !singleton_ref->GetBlock()->Dominates(block))
-            << "method: " << GetGraph()->GetMethodName();
-        // singleton_ref is not defined before block or defined only in some of its
-        // predecessors, so block doesn't really have the location at its entry.
-        heap_values[i] = kUnknownHeapValue;
-      } else if (predecessors.size() == 1) {
-        // Inherit heap value from the single predecessor.
-        DCHECK_EQ(heap_values_for_[predecessors[0]->GetBlockId()][i], merged_value);
-        heap_values[i] = merged_value;
-      } else {
-        DCHECK(merged_value == kUnknownHeapValue ||
-               merged_value == kDefaultHeapValue ||
-               merged_value->GetBlock()->Dominates(block));
-        if (merged_value != kUnknownHeapValue) {
-          heap_values[i] = merged_value;
-        } else {
-          // Stores in different predecessors may be storing the same value.
-          heap_values[i] = merged_store_value;
-        }
+    for (size_t i = 0u, size = heap_values.size(); i != size; ++i) {
+      if (i == loc_index) {
+        // We use this function when reading a location with unknown value and
+        // therefore we cannot know what exact store wrote that unknown value.
+        // But we can have a phi placeholder here marking multiple stores to keep.
+        DCHECK(
+            !heap_values[i].stored_by.IsInstruction() ||
+            heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo()->IsPartialSingleton());
+        KeepStores(heap_values[i].stored_by);
+        heap_values[i].stored_by = Value::PureUnknown();
+      } else if (heap_location_collector_.MayAlias(i, loc_index)) {
+        KeepStores(heap_values[i].stored_by);
+        heap_values[i].stored_by = Value::PureUnknown();
       }
     }
   }
@@ -555,55 +891,7 @@
     }
   }
 
-  void VisitGetLocation(HInstruction* instruction, size_t idx) {
-    DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound);
-    ScopedArenaVector<HInstruction*>& heap_values =
-        heap_values_for_[instruction->GetBlock()->GetBlockId()];
-    HInstruction* heap_value = heap_values[idx];
-    if (heap_value == kDefaultHeapValue) {
-      if (IsDefaultAllowedForLoad(instruction)) {
-        HInstruction* constant = GetDefaultValue(instruction->GetType());
-        AddRemovedLoad(instruction, constant);
-        heap_values[idx] = constant;
-        return;
-      } else {
-        heap_values[idx] = kUnknownHeapValue;
-        heap_value = kUnknownHeapValue;
-      }
-    }
-    heap_value = GetRealHeapValue(heap_value);
-    if (heap_value == kUnknownHeapValue) {
-      // Load isn't eliminated. Put the load as the value into the HeapLocation.
-      // This acts like GVN but with better aliasing analysis.
-      heap_values[idx] = instruction;
-      KeepStoresIfAliasedToLocation(heap_values, idx);
-    } else {
-      // Load is eliminated.
-      AddRemovedLoad(instruction, heap_value);
-      TryRemovingNullCheck(instruction);
-    }
-  }
-
-  bool Equal(HInstruction* heap_value, HInstruction* value) {
-    DCHECK(!IsStore(value)) << value->DebugName();
-    if (heap_value == kUnknownHeapValue) {
-      // Don't compare kUnknownHeapValue with other values.
-      return false;
-    }
-    if (heap_value == value) {
-      return true;
-    }
-    if (heap_value == kDefaultHeapValue && GetDefaultValue(value->GetType()) == value) {
-      return true;
-    }
-    HInstruction* real_heap_value = GetRealHeapValue(heap_value);
-    if (real_heap_value != heap_value) {
-      return Equal(real_heap_value, value);
-    }
-    return false;
-  }
-
-  bool CanValueBeKeptIfSameAsNew(HInstruction* value,
+  bool CanValueBeKeptIfSameAsNew(Value value,
                                  HInstruction* new_value,
                                  HInstruction* new_value_set_instr) {
     // For field/array set location operations, if the value is the same as the new_value
@@ -629,66 +917,75 @@
       return false;
     }
 
-    return Equal(value, new_value);
+    return value.Equals(new_value);
   }
 
-  void VisitSetLocation(HInstruction* instruction, size_t idx, HInstruction* value) {
-    DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound);
-    DCHECK(!IsStore(value)) << value->DebugName();
-    // value may already have a substitute.
-    value = FindSubstitute(value);
-    ScopedArenaVector<HInstruction*>& heap_values =
-        heap_values_for_[instruction->GetBlock()->GetBlockId()];
-    HInstruction* heap_value = heap_values[idx];
-    bool possibly_redundant = false;
+  Value PrepareLoopValue(HBasicBlock* block, size_t idx);
+  Value PrepareLoopStoredBy(HBasicBlock* block, size_t idx);
+  void PrepareLoopRecords(HBasicBlock* block);
+  Value MergePredecessorValues(HBasicBlock* block, size_t idx);
+  void MergePredecessorRecords(HBasicBlock* block);
 
-    if (Equal(heap_value, value)) {
-      // Store into the heap location with the same value.
-      // This store can be eliminated right away.
-      instruction->GetBlock()->RemoveInstruction(instruction);
-      return;
-    } else {
-      HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
-      if (loop_info == nullptr) {
-        // Store is not in a loop. We try to precisely track the heap value by
-        // the store.
-        possibly_redundant = true;
-      } else if (!loop_info->IsIrreducible()) {
-        // instruction is a store in the loop so the loop must do write.
-        DCHECK(side_effects_.GetLoopEffects(loop_info->GetHeader()).DoesAnyWrite());
-        ReferenceInfo* ref_info = heap_location_collector_.GetHeapLocation(idx)->GetReferenceInfo();
-        if (ref_info->IsSingleton() && !loop_info->IsDefinedOutOfTheLoop(ref_info->GetReference())) {
-          // original_ref is created inside the loop. Value stored to it isn't needed at
-          // the loop header. This is true for outer loops also.
-          possibly_redundant = true;
-        } else {
-          // Keep the store since its value may be needed at the loop header.
-        }
-      } else {
-        // Keep the store inside irreducible loops.
-      }
-    }
-    if (possibly_redundant) {
-      possibly_removed_stores_.push_back(instruction);
-    }
+  void MaterializeNonLoopPhis(PhiPlaceholder phi_placeholder, DataType::Type type);
 
-    // Put the store as the heap value. If the value is loaded or needed after
-    // return/deoptimization later, this store isn't really redundant.
-    heap_values[idx] = instruction;
+  void VisitGetLocation(HInstruction* instruction, size_t idx);
+  void VisitSetLocation(HInstruction* instruction, size_t idx, HInstruction* value);
+  void RecordFieldInfo(const FieldInfo* info, size_t heap_loc) {
+    field_infos_[heap_loc] = info;
+  }
 
-    // This store may kill values in other heap locations due to aliasing.
-    for (size_t i = 0; i < heap_values.size(); i++) {
-      if (i == idx ||
-          heap_values[i] == kUnknownHeapValue ||
-          CanValueBeKeptIfSameAsNew(heap_values[i], value, instruction) ||
-          !heap_location_collector_.MayAlias(i, idx)) {
-        continue;
-      }
-      // Kill heap locations that may alias and as a result if the heap value
-      // is a store, the store needs to be kept.
-      KeepIfIsStore(heap_values[i]);
-      heap_values[i] = kUnknownHeapValue;
-    }
+  void VisitBasicBlock(HBasicBlock* block) override;
+
+  enum class Phase {
+    kLoadElimination,
+    kStoreElimination,
+    kPartialElimination,
+  };
+
+  bool MayAliasOnBackEdge(HBasicBlock* loop_header, size_t idx1, size_t idx2) const;
+
+  bool TryReplacingLoopPhiPlaceholderWithDefault(
+      PhiPlaceholder phi_placeholder,
+      DataType::Type type,
+      /*inout*/ ArenaBitVector* phi_placeholders_to_materialize);
+  bool TryReplacingLoopPhiPlaceholderWithSingleInput(
+      PhiPlaceholder phi_placeholder,
+      /*inout*/ ArenaBitVector* phi_placeholders_to_materialize);
+  std::optional<PhiPlaceholder> FindLoopPhisToMaterialize(
+      PhiPlaceholder phi_placeholder,
+      /*out*/ ArenaBitVector* phi_placeholders_to_materialize,
+      DataType::Type type,
+      bool can_use_default_or_phi);
+  bool MaterializeLoopPhis(const ScopedArenaVector<size_t>& phi_placeholder_indexes,
+                           DataType::Type type);
+  bool MaterializeLoopPhis(ArrayRef<const size_t> phi_placeholder_indexes, DataType::Type type);
+  bool MaterializeLoopPhis(const ArenaBitVector& phi_placeholders_to_materialize,
+                           DataType::Type type);
+  bool FullyMaterializePhi(PhiPlaceholder phi_placeholder, DataType::Type type);
+  std::optional<PhiPlaceholder> TryToMaterializeLoopPhis(PhiPlaceholder phi_placeholder,
+                                                         HInstruction* load);
+  void ProcessLoopPhiWithUnknownInput(PhiPlaceholder loop_phi_with_unknown_input);
+  void ProcessLoadsRequiringLoopPhis();
+
+  void SearchPhiPlaceholdersForKeptStores();
+  void UpdateValueRecordForStoreElimination(/*inout*/ValueRecord* value_record);
+  void FindOldValueForPhiPlaceholder(PhiPlaceholder phi_placeholder, DataType::Type type);
+  void FindStoresWritingOldValues();
+  void FinishFullLSE();
+  void PrepareForPartialPhiComputation();
+  // Create materialization block and materialization object for the given predecessor of entry.
+  HInstruction* SetupPartialMaterialization(PartialLoadStoreEliminationHelper& helper,
+                                            HeapRefHolder&& holder,
+                                            size_t pred_idx,
+                                            HBasicBlock* blk);
+  // Returns the value that would be read by the 'read' instruction on
+  // 'orig_new_inst' if 'orig_new_inst' has not escaped.
+  HInstruction* GetPartialValueAt(HNewInstance* orig_new_inst, HInstruction* read);
+  void MovePartialEscapes();
+
+  void VisitPredicatedInstanceFieldGet(HPredicatedInstanceFieldGet* instruction) override {
+    LOG(FATAL) << "Visited instruction " << instruction->DumpWithoutArgs()
+               << " but LSE should be the only source of predicated-ifield-gets!";
   }
 
   void VisitInstanceFieldGet(HInstanceFieldGet* instruction) override {
@@ -714,8 +1011,9 @@
   void VisitStaticFieldSet(HStaticFieldSet* instruction) override {
     HInstruction* cls = instruction->InputAt(0);
     const FieldInfo& field = instruction->GetFieldInfo();
+    HInstruction* value = instruction->InputAt(1);
     size_t idx = heap_location_collector_.GetFieldHeapLocation(cls, &field);
-    VisitSetLocation(instruction, idx, instruction->InputAt(1));
+    VisitSetLocation(instruction, idx, value);
   }
 
   void VisitArrayGet(HArrayGet* instruction) override {
@@ -737,52 +1035,48 @@
   }
 
   void VisitDeoptimize(HDeoptimize* instruction) override {
-    const ScopedArenaVector<HInstruction*>& heap_values =
+    ScopedArenaVector<ValueRecord>& heap_values =
         heap_values_for_[instruction->GetBlock()->GetBlockId()];
-    for (HInstruction* heap_value : heap_values) {
-      // A store is kept as the heap value for possibly removed stores.
-      // That value stored is generally observeable after deoptimization, except
-      // for singletons that don't escape after deoptimization.
-      if (IsStore(heap_value)) {
-        if (heap_value->IsStaticFieldSet()) {
-          KeepIfIsStore(heap_value);
-          continue;
-        }
-        HInstruction* reference = heap_value->InputAt(0);
-        if (heap_location_collector_.FindReferenceInfoOf(reference)->IsSingleton()) {
-          if (reference->IsNewInstance() && reference->AsNewInstance()->IsFinalizable()) {
-            // Finalizable objects alway escape.
-            KeepIfIsStore(heap_value);
-            continue;
-          }
+    for (size_t i = 0u, size = heap_values.size(); i != size; ++i) {
+      Value* stored_by = &heap_values[i].stored_by;
+      if (stored_by->IsUnknown()) {
+        continue;
+      }
+      // Stores are generally observeable after deoptimization, except
+      // for singletons that don't escape in the deoptimization environment.
+      bool observable = true;
+      ReferenceInfo* info = heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo();
+      if (info->IsSingleton()) {
+        HInstruction* reference = info->GetReference();
+        // Finalizable objects always escape.
+        if (!reference->IsNewInstance() || !reference->AsNewInstance()->IsFinalizable()) {
           // Check whether the reference for a store is used by an environment local of
-          // HDeoptimize. If not, the singleton is not observed after
-          // deoptimizion.
-          for (const HUseListNode<HEnvironment*>& use : reference->GetEnvUses()) {
-            HEnvironment* user = use.GetUser();
-            if (user->GetHolder() == instruction) {
-              // The singleton for the store is visible at this deoptimization
-              // point. Need to keep the store so that the heap value is
-              // seen by the interpreter.
-              KeepIfIsStore(heap_value);
-            }
-          }
-        } else {
-          KeepIfIsStore(heap_value);
+          // the HDeoptimize. If not, the singleton is not observed after deoptimization.
+          const HUseList<HEnvironment*>& env_uses = reference->GetEnvUses();
+          observable = std::any_of(
+              env_uses.begin(),
+              env_uses.end(),
+              [instruction](const HUseListNode<HEnvironment*>& use) {
+                return use.GetUser()->GetHolder() == instruction;
+              });
         }
       }
+      if (observable) {
+        KeepStores(*stored_by);
+        *stored_by = Value::PureUnknown();
+      }
     }
   }
 
   // Keep necessary stores before exiting a method via return/throw.
   void HandleExit(HBasicBlock* block) {
-    const ScopedArenaVector<HInstruction*>& heap_values =
-        heap_values_for_[block->GetBlockId()];
-    for (size_t i = 0; i < heap_values.size(); i++) {
-      HInstruction* heap_value = heap_values[i];
+    ScopedArenaVector<ValueRecord>& heap_values = heap_values_for_[block->GetBlockId()];
+    for (size_t i = 0u, size = heap_values.size(); i != size; ++i) {
       ReferenceInfo* ref_info = heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo();
-      if (!ref_info->IsSingletonAndRemovable()) {
-        KeepIfIsStore(heap_value);
+      if (!ref_info->IsSingletonAndRemovable() &&
+          !(ref_info->IsPartialSingleton() && IsPartialNoEscape(block, i))) {
+        KeepStores(heap_values[i].stored_by);
+        heap_values[i].stored_by = Value::PureUnknown();
       }
     }
   }
@@ -801,21 +1095,43 @@
 
   void HandleInvoke(HInstruction* instruction) {
     SideEffects side_effects = instruction->GetSideEffects();
-    ScopedArenaVector<HInstruction*>& heap_values =
+    ScopedArenaVector<ValueRecord>& heap_values =
         heap_values_for_[instruction->GetBlock()->GetBlockId()];
-    for (size_t i = 0; i < heap_values.size(); i++) {
+    for (size_t i = 0u, size = heap_values.size(); i != size; ++i) {
       ReferenceInfo* ref_info = heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo();
-      if (ref_info->IsSingleton()) {
+      HBasicBlock* blk = instruction->GetBlock();
+      // We don't need to do anything if the reference has not escaped at this point.
+      // This is true if either we (1) never escape or (2) sometimes escape but
+      // there is no possible execution where we have done so at this time. NB
+      // We count being in the excluded cohort as escaping. Technically, this is
+      // a bit over-conservative (since we can have multiple non-escaping calls
+      // before a single escaping one) but this simplifies everything greatly.
+      auto partial_singleton_did_not_escape = [](ReferenceInfo* ref_info, HBasicBlock* blk) {
+        DCHECK(ref_info->IsPartialSingleton());
+        if (!ref_info->GetNoEscapeSubgraph()->ContainsBlock(blk)) {
+          return false;
+        }
+        ArrayRef<const ExecutionSubgraph::ExcludedCohort> cohorts =
+            ref_info->GetNoEscapeSubgraph()->GetExcludedCohorts();
+        return std::none_of(cohorts.begin(),
+                            cohorts.end(),
+                            [&](const ExecutionSubgraph::ExcludedCohort& cohort) {
+                              return cohort.PrecedesBlock(blk);
+                            });
+      };
+      if (ref_info->IsSingleton() ||
+          // partial and we aren't currently escaping and we haven't escaped yet.
+          (ref_info->IsPartialSingleton() && partial_singleton_did_not_escape(ref_info, blk))) {
         // Singleton references cannot be seen by the callee.
       } else {
-        if (side_effects.DoesAnyRead()) {
-          // Invocation may read the heap value.
-          KeepIfIsStore(heap_values[i]);
+        if (side_effects.DoesAnyRead() || side_effects.DoesAnyWrite()) {
+          // Previous stores may become visible (read) and/or impossible for LSE to track (write).
+          KeepStores(heap_values[i].stored_by);
+          heap_values[i].stored_by = Value::PureUnknown();
         }
         if (side_effects.DoesAnyWrite()) {
-          // Keep the store since it's not used to track the heap value anymore.
-          KeepIfIsStore(heap_values[i]);
-          heap_values[i] = kUnknownHeapValue;
+          // The value may be clobbered.
+          heap_values[i].value = Value::PartialUnknown(heap_values[i].value);
         }
       }
     }
@@ -826,6 +1142,7 @@
   }
 
   void VisitClinitCheck(HClinitCheck* clinit) override {
+    // Class initialization check can result in class initializer calling arbitrary methods.
     HandleInvoke(clinit);
   }
 
@@ -860,15 +1177,24 @@
       // new_instance can potentially be eliminated.
       singleton_new_instances_.push_back(new_instance);
     }
-    ScopedArenaVector<HInstruction*>& heap_values =
+    ScopedArenaVector<ValueRecord>& heap_values =
         heap_values_for_[new_instance->GetBlock()->GetBlockId()];
-    for (size_t i = 0; i < heap_values.size(); i++) {
+    for (size_t i = 0u, size = heap_values.size(); i != size; ++i) {
       HInstruction* ref =
           heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo()->GetReference();
       size_t offset = heap_location_collector_.GetHeapLocation(i)->GetOffset();
-      if (ref == new_instance && offset >= mirror::kObjectHeaderSize) {
-        // Instance fields except the header fields are set to default heap values.
-        heap_values[i] = kDefaultHeapValue;
+      if (ref == new_instance) {
+        if (offset >= mirror::kObjectHeaderSize ||
+            MemberOffset(offset) == mirror::Object::MonitorOffset()) {
+          // Instance fields except the header fields are set to default heap values.
+          // The shadow$_monitor_ field is set to the default value however.
+          heap_values[i].value = Value::Default();
+          heap_values[i].stored_by = Value::PureUnknown();
+        } else if (MemberOffset(offset) == mirror::Object::ClassOffset()) {
+          // The shadow$_klass_ field is special and has an actual value however.
+          heap_values[i].value = Value::ForInstruction(new_instance->GetLoadClass());
+          heap_values[i].stored_by = Value::PureUnknown();
+        }
       }
     }
   }
@@ -888,61 +1214,2695 @@
         // new_array may throw NegativeArraySizeException. Keep it.
       }
     }
-    ScopedArenaVector<HInstruction*>& heap_values =
+    ScopedArenaVector<ValueRecord>& heap_values =
         heap_values_for_[new_array->GetBlock()->GetBlockId()];
-    for (size_t i = 0; i < heap_values.size(); i++) {
+    for (size_t i = 0u, size = heap_values.size(); i != size; ++i) {
       HeapLocation* location = heap_location_collector_.GetHeapLocation(i);
       HInstruction* ref = location->GetReferenceInfo()->GetReference();
       if (ref == new_array && location->GetIndex() != nullptr) {
         // Array elements are set to default heap values.
-        heap_values[i] = kDefaultHeapValue;
+        heap_values[i].value = Value::Default();
+        heap_values[i].stored_by = Value::PureUnknown();
       }
     }
   }
 
+  bool ShouldPerformPartialLSE() const {
+    return perform_partial_lse_ && !GetGraph()->IsCompilingOsr();
+  }
+
+  bool perform_partial_lse_;
+
   const HeapLocationCollector& heap_location_collector_;
-  const SideEffectsAnalysis& side_effects_;
 
   // Use local allocator for allocating memory.
   ScopedArenaAllocator allocator_;
 
-  // One array of heap values for each block.
-  ScopedArenaVector<ScopedArenaVector<HInstruction*>> heap_values_for_;
+  // The number of unique phi_placeholders there possibly are
+  size_t num_phi_placeholders_;
 
-  // We record the instructions that should be eliminated but may be
-  // used by heap locations. They'll be removed in the end.
-  ScopedArenaVector<HInstruction*> removed_loads_;
+  // One array of heap value records for each block.
+  ScopedArenaVector<ScopedArenaVector<ValueRecord>> heap_values_for_;
+
+  // We record loads and stores for re-processing when we find a loop Phi placeholder
+  // with unknown value from a predecessor, and also for removing stores that are
+  // found to be dead, i.e. not marked in `kept_stores_` at the end.
+  struct LoadStoreRecord {
+    HInstruction* load_or_store;
+    size_t heap_location_index;
+  };
+  ScopedArenaVector<LoadStoreRecord> loads_and_stores_;
+
+  // We record the substitute instructions for loads that should be
+  // eliminated but may be used by heap locations. They'll be removed
+  // in the end. These are indexed by the load's id.
   ScopedArenaVector<HInstruction*> substitute_instructions_for_loads_;
 
-  // Stores in this list may be removed from the list later when it's
-  // found that the store cannot be eliminated.
-  ScopedArenaVector<HInstruction*> possibly_removed_stores_;
+  // Value at the start of the given instruction for instructions which directly
+  // read from a heap-location (i.e. FieldGet). The mapping to heap-location is
+  // implicit through the fact that each instruction can only directly refer to
+  // a single heap-location.
+  ScopedArenaHashMap<HInstruction*, Value> intermediate_values_;
+
+  // Record stores to keep in a bit vector indexed by instruction ID.
+  ArenaBitVector kept_stores_;
+  // When we need to keep all stores that feed a Phi placeholder, we just record the
+  // index of that placeholder for processing after graph traversal.
+  ArenaBitVector phi_placeholders_to_search_for_kept_stores_;
+
+  // Loads that would require a loop Phi to replace are recorded for processing
+  // later as we do not have enough information from back-edges to determine if
+  // a suitable Phi can be found or created when we visit these loads.
+  ScopedArenaHashMap<HInstruction*, ValueRecord> loads_requiring_loop_phi_;
+
+  // For stores, record the old value records that were replaced and the stored values.
+  struct StoreRecord {
+    ValueRecord old_value_record;
+    HInstruction* stored_value;
+  };
+  // Small pre-allocated initial buffer avoids initializing a large one until it's really needed.
+  static constexpr size_t kStoreRecordsInitialBufferSize = 16;
+  std::pair<HInstruction*, StoreRecord> store_records_buffer_[kStoreRecordsInitialBufferSize];
+  ScopedArenaHashMap<HInstruction*, StoreRecord> store_records_;
+
+  // Replacements for Phi placeholders.
+  // The invalid heap value is used to mark Phi placeholders that cannot be replaced.
+  ScopedArenaVector<Value> phi_placeholder_replacements_;
+
+  // Merged-unknowns that must have their predecessor values kept to ensure
+  // partially escaped values are written
+  ArenaBitVector kept_merged_unknowns_;
 
   ScopedArenaVector<HInstruction*> singleton_new_instances_;
 
+  // The field infos for each heap location (if relevant).
+  ScopedArenaVector<const FieldInfo*> field_infos_;
+
+  Phase current_phase_;
+
+  friend class PartialLoadStoreEliminationHelper;
+  friend struct ScopedRestoreHeapValues;
+
+  friend std::ostream& operator<<(std::ostream& os, const Value& v);
+  friend std::ostream& operator<<(std::ostream& os, const PriorValueHolder& v);
+  friend std::ostream& operator<<(std::ostream& oss, const LSEVisitor::Phase& phase);
+
   DISALLOW_COPY_AND_ASSIGN(LSEVisitor);
 };
 
-bool LoadStoreElimination::Run() {
+std::ostream& operator<<(std::ostream& oss, const LSEVisitor::PriorValueHolder& p) {
+  p.Dump(oss);
+  return oss;
+}
+
+std::ostream& operator<<(std::ostream& oss, const LSEVisitor::Phase& phase) {
+  switch (phase) {
+    case LSEVisitor::Phase::kLoadElimination:
+      return oss << "kLoadElimination";
+    case LSEVisitor::Phase::kStoreElimination:
+      return oss << "kStoreElimination";
+    case LSEVisitor::Phase::kPartialElimination:
+      return oss << "kPartialElimination";
+  }
+}
+
+void LSEVisitor::PriorValueHolder::Dump(std::ostream& oss) const {
+  if (IsDefault()) {
+    oss << "Default";
+  } else if (IsPhi()) {
+    oss << "Phi: " << GetPhiPlaceholder();
+  } else {
+    oss << "Instruction: " << *GetInstruction();
+  }
+}
+
+constexpr LSEVisitor::PriorValueHolder::PriorValueHolder(Value val)
+    : value_(Marker{}) {
+  DCHECK(!val.IsInvalid() && !val.IsPureUnknown());
+  if (val.IsPartialUnknown()) {
+    value_ = val.GetPriorValue().value_;
+  } else if (val.IsMergedUnknown() || val.NeedsPhi()) {
+    value_ = val.GetPhiPlaceholder();
+  } else if (val.IsInstruction()) {
+    value_ = val.GetInstruction();
+  } else {
+    DCHECK(val.IsDefault());
+  }
+}
+
+constexpr bool operator==(const LSEVisitor::Marker&, const LSEVisitor::Marker&) {
+  return true;
+}
+
+constexpr bool operator==(const LSEVisitor::PriorValueHolder& p1,
+                          const LSEVisitor::PriorValueHolder& p2) {
+  return p1.Equals(p2);
+}
+
+constexpr bool operator==(const LSEVisitor::PhiPlaceholder& p1,
+                          const LSEVisitor::PhiPlaceholder& p2) {
+  return p1.Equals(p2);
+}
+
+constexpr bool operator==(const LSEVisitor::Value::NeedsLoopPhiMarker& p1,
+                          const LSEVisitor::Value::NeedsLoopPhiMarker& p2) {
+  return p1.phi_ == p2.phi_;
+}
+
+constexpr bool operator==(const LSEVisitor::Value::NeedsNonLoopPhiMarker& p1,
+                          const LSEVisitor::Value::NeedsNonLoopPhiMarker& p2) {
+  return p1.phi_ == p2.phi_;
+}
+
+constexpr bool operator==(const LSEVisitor::Value::MergedUnknownMarker& p1,
+                          const LSEVisitor::Value::MergedUnknownMarker& p2) {
+  return p1.phi_ == p2.phi_;
+}
+
+std::ostream& operator<<(std::ostream& oss, const LSEVisitor::PhiPlaceholder& p) {
+  p.Dump(oss);
+  return oss;
+}
+
+LSEVisitor::Value LSEVisitor::PriorValueHolder::ToValue() const {
+  if (IsDefault()) {
+    return Value::Default();
+  } else if (IsPhi()) {
+    return Value::ForLoopPhiPlaceholder(GetPhiPlaceholder());
+  } else {
+    return Value::ForInstruction(GetInstruction());
+  }
+}
+
+constexpr bool LSEVisitor::Value::ExactEquals(LSEVisitor::Value other) const {
+  return value_ == other.value_;
+}
+
+constexpr bool LSEVisitor::Value::Equals(LSEVisitor::Value other) const {
+  // Only valid values can be compared.
+  DCHECK(IsValid());
+  DCHECK(other.IsValid());
+  if (value_ == other.value_) {
+    // Note: Two unknown values are considered different.
+    return !IsUnknown();
+  } else {
+    // Default is considered equal to zero-bit-pattern instructions.
+    return (IsDefault() && other.IsInstruction() && IsZeroBitPattern(other.GetInstruction())) ||
+            (other.IsDefault() && IsInstruction() && IsZeroBitPattern(GetInstruction()));
+  }
+}
+
+std::ostream& LSEVisitor::Value::Dump(std::ostream& os) const {
+  if (std::holds_alternative<LSEVisitor::Value::ValuelessType>(value_)) {
+    switch (GetValuelessType()) {
+      case ValuelessType::kDefault:
+        return os << "Default";
+      case ValuelessType::kPureUnknown:
+        return os << "PureUnknown";
+      case ValuelessType::kInvalid:
+        return os << "Invalid";
+    }
+  } else if (IsPartialUnknown()) {
+    return os << "PartialUnknown[" << GetPriorValue() << "]";
+  } else if (IsInstruction()) {
+    return os << "Instruction[id: " << GetInstruction()->GetId()
+              << ", block: " << GetInstruction()->GetBlock()->GetBlockId() << "]";
+  } else if (IsMergedUnknown()) {
+    return os << "MergedUnknown[block: " << GetPhiPlaceholder().GetBlockId()
+              << ", heap_loc: " << GetPhiPlaceholder().GetHeapLocation() << "]";
+
+  } else if (NeedsLoopPhi()) {
+    return os << "NeedsLoopPhi[block: " << GetPhiPlaceholder().GetBlockId()
+              << ", heap_loc: " << GetPhiPlaceholder().GetHeapLocation() << "]";
+  } else {
+    return os << "NeedsNonLoopPhi[block: " << GetPhiPlaceholder().GetBlockId()
+              << ", heap_loc: " << GetPhiPlaceholder().GetHeapLocation() << "]";
+  }
+}
+
+std::ostream& operator<<(std::ostream& os, const LSEVisitor::Value& v) {
+  return v.Dump(os);
+}
+
+LSEVisitor::LSEVisitor(HGraph* graph,
+                       const HeapLocationCollector& heap_location_collector,
+                       bool perform_partial_lse,
+                       OptimizingCompilerStats* stats)
+    : HGraphDelegateVisitor(graph, stats),
+      perform_partial_lse_(perform_partial_lse),
+      heap_location_collector_(heap_location_collector),
+      allocator_(graph->GetArenaStack()),
+      num_phi_placeholders_(GetGraph()->GetBlocks().size() *
+                            heap_location_collector_.GetNumberOfHeapLocations()),
+      heap_values_for_(graph->GetBlocks().size(),
+                       ScopedArenaVector<ValueRecord>(allocator_.Adapter(kArenaAllocLSE)),
+                       allocator_.Adapter(kArenaAllocLSE)),
+      loads_and_stores_(allocator_.Adapter(kArenaAllocLSE)),
+      // We may add new instructions (default values, Phis) but we're not adding loads
+      // or stores, so we shall not need to resize following vector and BitVector.
+      substitute_instructions_for_loads_(graph->GetCurrentInstructionId(),
+                                         nullptr,
+                                         allocator_.Adapter(kArenaAllocLSE)),
+      intermediate_values_(allocator_.Adapter(kArenaAllocLSE)),
+      kept_stores_(&allocator_,
+                   /*start_bits=*/graph->GetCurrentInstructionId(),
+                   /*expandable=*/false,
+                   kArenaAllocLSE),
+      phi_placeholders_to_search_for_kept_stores_(&allocator_,
+                                                  num_phi_placeholders_,
+                                                  /*expandable=*/false,
+                                                  kArenaAllocLSE),
+      loads_requiring_loop_phi_(allocator_.Adapter(kArenaAllocLSE)),
+      store_records_(store_records_buffer_,
+                     kStoreRecordsInitialBufferSize,
+                     allocator_.Adapter(kArenaAllocLSE)),
+      phi_placeholder_replacements_(num_phi_placeholders_,
+                                    Value::Invalid(),
+                                    allocator_.Adapter(kArenaAllocLSE)),
+      kept_merged_unknowns_(&allocator_,
+                            /*start_bits=*/num_phi_placeholders_,
+                            /*expandable=*/false,
+                            kArenaAllocLSE),
+      singleton_new_instances_(allocator_.Adapter(kArenaAllocLSE)),
+      field_infos_(heap_location_collector_.GetNumberOfHeapLocations(),
+                   allocator_.Adapter(kArenaAllocLSE)),
+      current_phase_(Phase::kLoadElimination) {
+  // Clear bit vectors.
+  phi_placeholders_to_search_for_kept_stores_.ClearAllBits();
+  kept_stores_.ClearAllBits();
+}
+
+LSEVisitor::Value LSEVisitor::PrepareLoopValue(HBasicBlock* block, size_t idx) {
+  // If the pre-header value is known (which implies that the reference dominates this
+  // block), use a Phi placeholder for the value in the loop header. If all predecessors
+  // are later found to have a known value, we can replace loads from this location,
+  // either with the pre-header value or with a new Phi. For array locations, the index
+  // may be defined inside the loop but the only known value in that case should be the
+  // default value or a Phi placeholder that can be replaced only with the default value.
+  HLoopInformation* loop_info = block->GetLoopInformation();
+  uint32_t pre_header_block_id = loop_info->GetPreHeader()->GetBlockId();
+  Value pre_header_value = ReplacementOrValue(heap_values_for_[pre_header_block_id][idx].value);
+  if (pre_header_value.IsUnknown()) {
+    return pre_header_value;
+  }
+  if (kIsDebugBuild) {
+    // Check that the reference indeed dominates this loop.
+    HeapLocation* location = heap_location_collector_.GetHeapLocation(idx);
+    HInstruction* ref = location->GetReferenceInfo()->GetReference();
+    CHECK(ref->GetBlock() != block && ref->GetBlock()->Dominates(block))
+        << GetGraph()->PrettyMethod();
+    // Check that the index, if defined inside the loop, tracks a default value
+    // or a Phi placeholder requiring a loop Phi.
+    HInstruction* index = location->GetIndex();
+    if (index != nullptr && loop_info->Contains(*index->GetBlock())) {
+      CHECK(pre_header_value.NeedsLoopPhi() || pre_header_value.Equals(Value::Default()))
+          << GetGraph()->PrettyMethod() << " blk: " << block->GetBlockId() << " "
+          << pre_header_value;
+    }
+  }
+  PhiPlaceholder phi_placeholder = GetPhiPlaceholder(block->GetBlockId(), idx);
+  return ReplacementOrValue(Value::ForLoopPhiPlaceholder(phi_placeholder));
+}
+
+LSEVisitor::Value LSEVisitor::PrepareLoopStoredBy(HBasicBlock* block, size_t idx) {
+  // Use the Phi placeholder for `stored_by` to make sure all incoming stores are kept
+  // if the value in the location escapes. This is not applicable to singletons that are
+  // defined inside the loop as they shall be dead in the loop header.
+  ReferenceInfo* ref_info = heap_location_collector_.GetHeapLocation(idx)->GetReferenceInfo();
+  if (ref_info->IsSingleton() &&
+      block->GetLoopInformation()->Contains(*ref_info->GetReference()->GetBlock())) {
+    return Value::PureUnknown();
+  }
+  PhiPlaceholder phi_placeholder = GetPhiPlaceholder(block->GetBlockId(), idx);
+  return Value::ForLoopPhiPlaceholder(phi_placeholder);
+}
+
+void LSEVisitor::PrepareLoopRecords(HBasicBlock* block) {
+  DCHECK(block->IsLoopHeader());
+  int block_id = block->GetBlockId();
+  HBasicBlock* pre_header = block->GetLoopInformation()->GetPreHeader();
+  ScopedArenaVector<ValueRecord>& pre_header_heap_values =
+      heap_values_for_[pre_header->GetBlockId()];
+  size_t num_heap_locations = heap_location_collector_.GetNumberOfHeapLocations();
+  DCHECK_EQ(num_heap_locations, pre_header_heap_values.size());
+  ScopedArenaVector<ValueRecord>& heap_values = heap_values_for_[block_id];
+  DCHECK(heap_values.empty());
+
+  // Don't eliminate loads in irreducible loops.
+  if (block->GetLoopInformation()->IsIrreducible()) {
+    heap_values.resize(num_heap_locations,
+                       {/*value=*/Value::Invalid(), /*stored_by=*/Value::PureUnknown()});
+    // Also keep the stores before the loop header, including in blocks that were not visited yet.
+    bool is_osr = GetGraph()->IsCompilingOsr();
+    for (size_t idx = 0u; idx != num_heap_locations; ++idx) {
+      heap_values[idx].value =
+          is_osr ? Value::PureUnknown()
+                 : Value::MergedUnknown(GetPhiPlaceholder(block->GetBlockId(), idx));
+      KeepStores(Value::ForLoopPhiPlaceholder(GetPhiPlaceholder(block->GetBlockId(), idx)));
+    }
+    return;
+  }
+
+  // Fill `heap_values` based on values from pre-header.
+  heap_values.reserve(num_heap_locations);
+  for (size_t idx = 0u; idx != num_heap_locations; ++idx) {
+    heap_values.push_back({ PrepareLoopValue(block, idx), PrepareLoopStoredBy(block, idx) });
+  }
+}
+
+LSEVisitor::Value LSEVisitor::MergePredecessorValues(HBasicBlock* block, size_t idx) {
+  ArrayRef<HBasicBlock* const> predecessors(block->GetPredecessors());
+  DCHECK(!predecessors.empty());
+  Value merged_value =
+      ReplacementOrValue(heap_values_for_[predecessors[0]->GetBlockId()][idx].value);
+  for (size_t i = 1u, size = predecessors.size(); i != size; ++i) {
+    Value pred_value =
+        ReplacementOrValue(heap_values_for_[predecessors[i]->GetBlockId()][idx].value);
+    if (pred_value.Equals(merged_value)) {
+      // Value is the same. No need to update our merged value.
+      continue;
+    } else if (pred_value.IsUnknown() || merged_value.IsUnknown()) {
+      // If one is unknown and the other is a different type of unknown
+      PhiPlaceholder phi_placeholder = GetPhiPlaceholder(block->GetBlockId(), idx);
+      merged_value = Value::MergedUnknown(phi_placeholder);
+      // We know that at least one of the merge points is unknown (and both are
+      // not pure-unknowns since that's captured above). This means that the
+      // overall value needs to be a MergedUnknown. Just return that.
+      break;
+    } else {
+      // There are conflicting known values. We may still be able to replace loads with a Phi.
+      PhiPlaceholder phi_placeholder = GetPhiPlaceholder(block->GetBlockId(), idx);
+      // Propagate the need for a new loop Phi from all predecessors.
+      bool needs_loop_phi = merged_value.NeedsLoopPhi() || pred_value.NeedsLoopPhi();
+      merged_value = ReplacementOrValue(Value::ForPhiPlaceholder(phi_placeholder, needs_loop_phi));
+    }
+  }
+  DCHECK(!merged_value.IsPureUnknown() || block->GetPredecessors().size() <= 1)
+      << merged_value << " in " << GetGraph()->PrettyMethod();
+  return merged_value;
+}
+
+void LSEVisitor::MergePredecessorRecords(HBasicBlock* block) {
+  if (block->IsExitBlock()) {
+    // Exit block doesn't really merge values since the control flow ends in
+    // its predecessors. Each predecessor needs to make sure stores are kept
+    // if necessary.
+    return;
+  }
+
+  ScopedArenaVector<ValueRecord>& heap_values = heap_values_for_[block->GetBlockId()];
+  DCHECK(heap_values.empty());
+  size_t num_heap_locations = heap_location_collector_.GetNumberOfHeapLocations();
+  if (block->GetPredecessors().empty()) {
+    DCHECK(block->IsEntryBlock());
+    heap_values.resize(num_heap_locations,
+                       {/*value=*/Value::PureUnknown(), /*stored_by=*/Value::PureUnknown()});
+    return;
+  }
+
+  heap_values.reserve(num_heap_locations);
+  for (size_t idx = 0u; idx != num_heap_locations; ++idx) {
+    Value merged_value = MergePredecessorValues(block, idx);
+    if (kIsDebugBuild) {
+      if (merged_value.NeedsPhi()) {
+        uint32_t block_id = merged_value.GetPhiPlaceholder().GetBlockId();
+        CHECK(GetGraph()->GetBlocks()[block_id]->Dominates(block));
+      } else if (merged_value.IsInstruction()) {
+        CHECK(merged_value.GetInstruction()->GetBlock()->Dominates(block));
+      }
+    }
+    ArrayRef<HBasicBlock* const> predecessors(block->GetPredecessors());
+    Value merged_stored_by = heap_values_for_[predecessors[0]->GetBlockId()][idx].stored_by;
+    for (size_t predecessor_idx = 1u; predecessor_idx != predecessors.size(); ++predecessor_idx) {
+      uint32_t predecessor_block_id = predecessors[predecessor_idx]->GetBlockId();
+      Value stored_by = heap_values_for_[predecessor_block_id][idx].stored_by;
+      if ((!stored_by.IsUnknown() || !merged_stored_by.IsUnknown()) &&
+          !merged_stored_by.Equals(stored_by)) {
+        // Use the Phi placeholder to track that we need to keep stores from all predecessors.
+        PhiPlaceholder phi_placeholder = GetPhiPlaceholder(block->GetBlockId(), idx);
+        merged_stored_by = Value::ForNonLoopPhiPlaceholder(phi_placeholder);
+        break;
+      }
+    }
+    heap_values.push_back({ merged_value, merged_stored_by });
+  }
+}
+
+static HInstruction* FindOrConstructNonLoopPhi(
+    HBasicBlock* block,
+    const ScopedArenaVector<HInstruction*>& phi_inputs,
+    DataType::Type type) {
+  for (HInstructionIterator phi_it(block->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
+    HInstruction* phi = phi_it.Current();
+    DCHECK_EQ(phi->InputCount(), phi_inputs.size());
+    auto cmp = [](HInstruction* lhs, const HUserRecord<HInstruction*>& rhs) {
+      return lhs == rhs.GetInstruction();
+    };
+    if (std::equal(phi_inputs.begin(), phi_inputs.end(), phi->GetInputRecords().begin(), cmp)) {
+      return phi;
+    }
+  }
+  ArenaAllocator* allocator = block->GetGraph()->GetAllocator();
+  HPhi* phi = new (allocator) HPhi(allocator, kNoRegNumber, phi_inputs.size(), type);
+  for (size_t i = 0, size = phi_inputs.size(); i != size; ++i) {
+    DCHECK_NE(phi_inputs[i]->GetType(), DataType::Type::kVoid) << phi_inputs[i]->DebugName();
+    phi->SetRawInputAt(i, phi_inputs[i]);
+  }
+  block->AddPhi(phi);
+  if (type == DataType::Type::kReference) {
+    // Update reference type information. Pass invalid handles, these are not used for Phis.
+    ReferenceTypePropagation rtp_fixup(block->GetGraph(),
+                                       Handle<mirror::ClassLoader>(),
+                                       Handle<mirror::DexCache>(),
+                                       /* is_first_run= */ false);
+    rtp_fixup.Visit(phi);
+  }
+  return phi;
+}
+
+void LSEVisitor::MaterializeNonLoopPhis(PhiPlaceholder phi_placeholder, DataType::Type type) {
+  DCHECK(phi_placeholder_replacements_[PhiPlaceholderIndex(phi_placeholder)].IsInvalid());
+  const ArenaVector<HBasicBlock*>& blocks = GetGraph()->GetBlocks();
+  size_t idx = phi_placeholder.GetHeapLocation();
+
+  // Use local allocator to reduce peak memory usage.
+  ScopedArenaAllocator allocator(allocator_.GetArenaStack());
+  // Reuse the same vector for collecting phi inputs.
+  ScopedArenaVector<HInstruction*> phi_inputs(allocator.Adapter(kArenaAllocLSE));
+
+  ScopedArenaVector<PhiPlaceholder> work_queue(allocator.Adapter(kArenaAllocLSE));
+  work_queue.push_back(phi_placeholder);
+  while (!work_queue.empty()) {
+    PhiPlaceholder current_phi_placeholder = work_queue.back();
+    if (phi_placeholder_replacements_[PhiPlaceholderIndex(current_phi_placeholder)].IsValid()) {
+      // This Phi placeholder was pushed to the `work_queue` followed by another Phi placeholder
+      // that directly or indirectly depends on it, so it was already processed as part of the
+      // other Phi placeholder's dependencies before this one got back to the top of the stack.
+      work_queue.pop_back();
+      continue;
+    }
+    uint32_t current_block_id = current_phi_placeholder.GetBlockId();
+    HBasicBlock* current_block = blocks[current_block_id];
+    DCHECK_GE(current_block->GetPredecessors().size(), 2u);
+
+    // Non-loop Phis cannot depend on a loop Phi, so we should not see any loop header here.
+    // And the only way for such merged value to reach a different heap location is through
+    // a load at which point we materialize the Phi. Therefore all non-loop Phi placeholders
+    // seen here are tied to one heap location.
+    DCHECK(!current_block->IsLoopHeader())
+        << current_phi_placeholder << " phase: " << current_phase_;
+    DCHECK_EQ(current_phi_placeholder.GetHeapLocation(), idx);
+
+    phi_inputs.clear();
+    for (HBasicBlock* predecessor : current_block->GetPredecessors()) {
+      Value pred_value = ReplacementOrValue(heap_values_for_[predecessor->GetBlockId()][idx].value);
+      DCHECK(!pred_value.IsPureUnknown()) << pred_value << " block " << current_block->GetBlockId()
+                                          << " pred: " << predecessor->GetBlockId();
+      if (pred_value.NeedsNonLoopPhi() ||
+          (current_phase_ == Phase::kPartialElimination && pred_value.IsMergedUnknown())) {
+        // We need to process the Phi placeholder first.
+        work_queue.push_back(pred_value.GetPhiPlaceholder());
+      } else if (pred_value.IsDefault()) {
+        phi_inputs.push_back(GetDefaultValue(type));
+      } else {
+        DCHECK(pred_value.IsInstruction()) << pred_value << " block " << current_block->GetBlockId()
+                                           << " pred: " << predecessor->GetBlockId();
+        phi_inputs.push_back(pred_value.GetInstruction());
+      }
+    }
+    if (phi_inputs.size() == current_block->GetPredecessors().size()) {
+      // All inputs are available. Find or construct the Phi replacement.
+      phi_placeholder_replacements_[PhiPlaceholderIndex(current_phi_placeholder)] =
+          Value::ForInstruction(FindOrConstructNonLoopPhi(current_block, phi_inputs, type));
+      // Remove the block from the queue.
+      DCHECK_EQ(current_phi_placeholder, work_queue.back());
+      work_queue.pop_back();
+    }
+  }
+}
+
+void LSEVisitor::VisitGetLocation(HInstruction* instruction, size_t idx) {
+  DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound);
+  uint32_t block_id = instruction->GetBlock()->GetBlockId();
+  ScopedArenaVector<ValueRecord>& heap_values = heap_values_for_[block_id];
+  ValueRecord& record = heap_values[idx];
+  if (instruction->IsFieldAccess()) {
+    RecordFieldInfo(&instruction->GetFieldInfo(), idx);
+  }
+  DCHECK(record.value.IsUnknown() || record.value.Equals(ReplacementOrValue(record.value)));
+  // If we are unknown, we either come from somewhere untracked or we can reconstruct the partial
+  // value.
+  DCHECK(!record.value.IsPureUnknown() ||
+         heap_location_collector_.GetHeapLocation(idx)->GetReferenceInfo() == nullptr ||
+         !heap_location_collector_.GetHeapLocation(idx)->GetReferenceInfo()->IsPartialSingleton())
+         << "In " << GetGraph()->PrettyMethod() << ": " << record.value << " for " << *instruction;
+  intermediate_values_.insert({instruction, record.value});
+  loads_and_stores_.push_back({ instruction, idx });
+  if ((record.value.IsDefault() || record.value.NeedsNonLoopPhi()) &&
+      !IsDefaultOrPhiAllowedForLoad(instruction)) {
+    record.value = Value::PureUnknown();
+  }
+  if (record.value.IsDefault()) {
+    KeepStores(record.stored_by);
+    HInstruction* constant = GetDefaultValue(instruction->GetType());
+    AddRemovedLoad(instruction, constant);
+    record.value = Value::ForInstruction(constant);
+  } else if (record.value.IsUnknown()) {
+    // Load isn't eliminated. Put the load as the value into the HeapLocation.
+    // This acts like GVN but with better aliasing analysis.
+    Value old_value = record.value;
+    record.value = Value::ForInstruction(instruction);
+    KeepStoresIfAliasedToLocation(heap_values, idx);
+    KeepStores(old_value);
+  } else if (record.value.NeedsLoopPhi()) {
+    // We do not know yet if the value is known for all back edges. Record for future processing.
+    loads_requiring_loop_phi_.insert(std::make_pair(instruction, record));
+  } else {
+    // This load can be eliminated but we may need to construct non-loop Phis.
+    if (record.value.NeedsNonLoopPhi()) {
+      MaterializeNonLoopPhis(record.value.GetPhiPlaceholder(), instruction->GetType());
+      record.value = Replacement(record.value);
+    }
+    HInstruction* heap_value = FindSubstitute(record.value.GetInstruction());
+    AddRemovedLoad(instruction, heap_value);
+    TryRemovingNullCheck(instruction);
+  }
+}
+
+void LSEVisitor::VisitSetLocation(HInstruction* instruction, size_t idx, HInstruction* value) {
+  DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound);
+  DCHECK(!IsStore(value)) << value->DebugName();
+  if (instruction->IsFieldAccess()) {
+    RecordFieldInfo(&instruction->GetFieldInfo(), idx);
+  }
+  // value may already have a substitute.
+  value = FindSubstitute(value);
+  HBasicBlock* block = instruction->GetBlock();
+  ScopedArenaVector<ValueRecord>& heap_values = heap_values_for_[block->GetBlockId()];
+  ValueRecord& record = heap_values[idx];
+  DCHECK(!record.value.IsInstruction() ||
+         FindSubstitute(record.value.GetInstruction()) == record.value.GetInstruction());
+
+  if (record.value.Equals(value)) {
+    // Store into the heap location with the same value.
+    // This store can be eliminated right away.
+    block->RemoveInstruction(instruction);
+    return;
+  }
+
+  store_records_.insert(std::make_pair(instruction, StoreRecord{record, value}));
+  loads_and_stores_.push_back({ instruction, idx });
+
+  // If the `record.stored_by` specified a store from this block, it shall be removed
+  // at the end, except for throwing ArraySet; it cannot be marked for keeping in
+  // `kept_stores_` anymore after we update the `record.stored_by` below.
+  DCHECK(!record.stored_by.IsInstruction() ||
+         record.stored_by.GetInstruction()->GetBlock() != block ||
+         record.stored_by.GetInstruction()->CanThrow() ||
+         !kept_stores_.IsBitSet(record.stored_by.GetInstruction()->GetId()));
+
+  if (instruction->CanThrow()) {
+    // Previous stores can become visible.
+    HandleExit(instruction->GetBlock());
+    // We cannot remove a possibly throwing store.
+    // After marking it as kept, it does not matter if we track it in `stored_by` or not.
+    kept_stores_.SetBit(instruction->GetId());
+  }
+
+  // Update the record.
+  auto it = loads_requiring_loop_phi_.find(value);
+  if (it != loads_requiring_loop_phi_.end()) {
+    // Propapate the Phi placeholder to the record.
+    record.value = it->second.value;
+    DCHECK(record.value.NeedsLoopPhi());
+  } else {
+    record.value = Value::ForInstruction(value);
+  }
+  // Track the store in the value record. If the value is loaded or needed after
+  // return/deoptimization later, this store isn't really redundant.
+  record.stored_by = Value::ForInstruction(instruction);
+
+  // This store may kill values in other heap locations due to aliasing.
+  for (size_t i = 0u, size = heap_values.size(); i != size; ++i) {
+    if (i == idx ||
+        heap_values[i].value.IsUnknown() ||
+        CanValueBeKeptIfSameAsNew(heap_values[i].value, value, instruction) ||
+        !heap_location_collector_.MayAlias(i, idx)) {
+      continue;
+    }
+    // Kill heap locations that may alias and keep previous stores to these locations.
+    KeepStores(heap_values[i].stored_by);
+    heap_values[i].stored_by = Value::PureUnknown();
+    heap_values[i].value = Value::PartialUnknown(heap_values[i].value);
+  }
+}
+
+void LSEVisitor::VisitBasicBlock(HBasicBlock* block) {
+  // Populate the heap_values array for this block.
+  // TODO: try to reuse the heap_values array from one predecessor if possible.
+  if (block->IsLoopHeader()) {
+    PrepareLoopRecords(block);
+  } else {
+    MergePredecessorRecords(block);
+  }
+  // Visit instructions.
+  HGraphVisitor::VisitBasicBlock(block);
+}
+
+bool LSEVisitor::MayAliasOnBackEdge(HBasicBlock* loop_header, size_t idx1, size_t idx2) const {
+  DCHECK_NE(idx1, idx2);
+  DCHECK(loop_header->IsLoopHeader());
+  if (heap_location_collector_.MayAlias(idx1, idx2)) {
+    return true;
+  }
+  // For array locations with index defined inside the loop, include
+  // all other locations in the array, even those that LSA declares
+  // non-aliasing, such as `a[i]` and `a[i + 1]`, as they may actually
+  // refer to the same locations for different iterations. (LSA's
+  // `ComputeMayAlias()` does not consider different loop iterations.)
+  HeapLocation* loc1 = heap_location_collector_.GetHeapLocation(idx1);
+  HeapLocation* loc2 = heap_location_collector_.GetHeapLocation(idx2);
+  if (loc1->IsArray() &&
+      loc2->IsArray() &&
+      HeapLocationCollector::CanReferencesAlias(loc1->GetReferenceInfo(),
+                                                loc2->GetReferenceInfo())) {
+    HLoopInformation* loop_info = loop_header->GetLoopInformation();
+    if (loop_info->Contains(*loc1->GetIndex()->GetBlock()) ||
+        loop_info->Contains(*loc2->GetIndex()->GetBlock())) {
+      // Consider the locations aliasing. Do not optimize the case where both indexes
+      // are loop invariants defined inside the loop, rely on LICM to pull them out.
+      return true;
+    }
+  }
+  return false;
+}
+
+bool LSEVisitor::TryReplacingLoopPhiPlaceholderWithDefault(
+    PhiPlaceholder phi_placeholder,
+    DataType::Type type,
+    /*inout*/ ArenaBitVector* phi_placeholders_to_materialize) {
+  // Use local allocator to reduce peak memory usage.
+  ScopedArenaAllocator allocator(allocator_.GetArenaStack());
+  ArenaBitVector visited(&allocator,
+                         /*start_bits=*/ num_phi_placeholders_,
+                         /*expandable=*/ false,
+                         kArenaAllocLSE);
+  visited.ClearAllBits();
+  ScopedArenaVector<PhiPlaceholder> work_queue(allocator.Adapter(kArenaAllocLSE));
+
+  // Use depth first search to check if any non-Phi input is unknown.
+  const ArenaVector<HBasicBlock*>& blocks = GetGraph()->GetBlocks();
+  size_t num_heap_locations = heap_location_collector_.GetNumberOfHeapLocations();
+  visited.SetBit(PhiPlaceholderIndex(phi_placeholder));
+  work_queue.push_back(phi_placeholder);
+  while (!work_queue.empty()) {
+    PhiPlaceholder current_phi_placeholder = work_queue.back();
+    work_queue.pop_back();
+    HBasicBlock* block = blocks[current_phi_placeholder.GetBlockId()];
+    DCHECK_GE(block->GetPredecessors().size(), 2u);
+    size_t idx = current_phi_placeholder.GetHeapLocation();
+    for (HBasicBlock* predecessor : block->GetPredecessors()) {
+      Value value = ReplacementOrValue(heap_values_for_[predecessor->GetBlockId()][idx].value);
+      if (value.NeedsPhi()) {
+        // Visit the predecessor Phi placeholder if it's not visited yet.
+        if (!visited.IsBitSet(PhiPlaceholderIndex(value))) {
+          visited.SetBit(PhiPlaceholderIndex(value));
+          work_queue.push_back(value.GetPhiPlaceholder());
+        }
+      } else if (!value.Equals(Value::Default())) {
+        return false;  // Report failure.
+      }
+    }
+    if (block->IsLoopHeader()) {
+      // For back-edges we need to check all locations that write to the same array,
+      // even those that LSA declares non-aliasing, such as `a[i]` and `a[i + 1]`
+      // as they may actually refer to the same locations for different iterations.
+      for (size_t i = 0; i != num_heap_locations; ++i) {
+        if (i == idx ||
+            heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo() !=
+                heap_location_collector_.GetHeapLocation(idx)->GetReferenceInfo()) {
+          continue;
+        }
+        for (HBasicBlock* predecessor : block->GetPredecessors()) {
+          // Check if there were any writes to this location.
+          // Note: We could simply process the values but due to the vector operation
+          // carve-out (see `IsDefaultOrPhiAllowedForLoad()`), a vector load can cause
+          // the value to change and not be equal to default. To work around this and
+          // allow replacing the non-vector load of loop-invariant default values
+          // anyway, skip over paths that do not have any writes.
+          ValueRecord record = heap_values_for_[predecessor->GetBlockId()][i];
+          while (record.stored_by.NeedsLoopPhi() &&
+                 blocks[record.stored_by.GetPhiPlaceholder().GetBlockId()]->IsLoopHeader()) {
+            HLoopInformation* loop_info =
+                blocks[record.stored_by.GetPhiPlaceholder().GetBlockId()]->GetLoopInformation();
+            record = heap_values_for_[loop_info->GetPreHeader()->GetBlockId()][i];
+          }
+          Value value = ReplacementOrValue(record.value);
+          if (value.NeedsPhi()) {
+            // Visit the predecessor Phi placeholder if it's not visited yet.
+            if (!visited.IsBitSet(PhiPlaceholderIndex(value))) {
+              visited.SetBit(PhiPlaceholderIndex(value));
+              work_queue.push_back(value.GetPhiPlaceholder());
+            }
+          } else if (!value.Equals(Value::Default())) {
+            return false;  // Report failure.
+          }
+        }
+      }
+    }
+  }
+
+  // Record replacement and report success.
+  HInstruction* replacement = GetDefaultValue(type);
+  for (uint32_t phi_placeholder_index : visited.Indexes()) {
+    DCHECK(phi_placeholder_replacements_[phi_placeholder_index].IsInvalid());
+    phi_placeholder_replacements_[phi_placeholder_index] = Value::ForInstruction(replacement);
+  }
+  phi_placeholders_to_materialize->Subtract(&visited);
+  return true;
+}
+
+bool LSEVisitor::TryReplacingLoopPhiPlaceholderWithSingleInput(
+    PhiPlaceholder phi_placeholder,
+    /*inout*/ ArenaBitVector* phi_placeholders_to_materialize) {
+  // Use local allocator to reduce peak memory usage.
+  ScopedArenaAllocator allocator(allocator_.GetArenaStack());
+  ArenaBitVector visited(&allocator,
+                         /*start_bits=*/ num_phi_placeholders_,
+                         /*expandable=*/ false,
+                         kArenaAllocLSE);
+  visited.ClearAllBits();
+  ScopedArenaVector<PhiPlaceholder> work_queue(allocator.Adapter(kArenaAllocLSE));
+
+  // Use depth first search to check if any non-Phi input is unknown.
+  HInstruction* replacement = nullptr;
+  const ArenaVector<HBasicBlock*>& blocks = GetGraph()->GetBlocks();
+  visited.SetBit(PhiPlaceholderIndex(phi_placeholder));
+  work_queue.push_back(phi_placeholder);
+  while (!work_queue.empty()) {
+    PhiPlaceholder current_phi_placeholder = work_queue.back();
+    work_queue.pop_back();
+    HBasicBlock* current_block = blocks[current_phi_placeholder.GetBlockId()];
+    DCHECK_GE(current_block->GetPredecessors().size(), 2u);
+    size_t idx = current_phi_placeholder.GetHeapLocation();
+    for (HBasicBlock* predecessor : current_block->GetPredecessors()) {
+      Value value = ReplacementOrValue(heap_values_for_[predecessor->GetBlockId()][idx].value);
+      if (value.NeedsPhi()) {
+        // Visit the predecessor Phi placeholder if it's not visited yet.
+        if (!visited.IsBitSet(PhiPlaceholderIndex(value))) {
+          visited.SetBit(PhiPlaceholderIndex(value));
+          work_queue.push_back(value.GetPhiPlaceholder());
+        }
+      } else {
+        if (!value.IsInstruction() ||
+            (replacement != nullptr && replacement != value.GetInstruction())) {
+          return false;  // Report failure.
+        }
+        replacement = value.GetInstruction();
+      }
+    }
+    // While `TryReplacingLoopPhiPlaceholderWithDefault()` has special treatment
+    // for back-edges, it is not needed here. When looking for a single input
+    // instruction coming from before the loop, the array index must also be
+    // defined before the loop and the aliasing analysis done by LSA is sufficient.
+    // Any writes of a different value with an index that is not loop invariant
+    // would invalidate the heap location in `VisitSetLocation()`.
+  }
+
+  // Record replacement and report success.
+  DCHECK(replacement != nullptr);
+  for (uint32_t phi_placeholder_index : visited.Indexes()) {
+    DCHECK(phi_placeholder_replacements_[phi_placeholder_index].IsInvalid());
+    phi_placeholder_replacements_[phi_placeholder_index] = Value::ForInstruction(replacement);
+  }
+  phi_placeholders_to_materialize->Subtract(&visited);
+  return true;
+}
+
+std::optional<LSEVisitor::PhiPlaceholder> LSEVisitor::FindLoopPhisToMaterialize(
+    PhiPlaceholder phi_placeholder,
+    /*inout*/ ArenaBitVector* phi_placeholders_to_materialize,
+    DataType::Type type,
+    bool can_use_default_or_phi) {
+  DCHECK(phi_placeholder_replacements_[PhiPlaceholderIndex(phi_placeholder)].IsInvalid());
+
+  // Use local allocator to reduce peak memory usage.
+  ScopedArenaAllocator allocator(allocator_.GetArenaStack());
+  ScopedArenaVector<PhiPlaceholder> work_queue(allocator.Adapter(kArenaAllocLSE));
+
+  // Use depth first search to check if any non-Phi input is unknown.
+  const ArenaVector<HBasicBlock*>& blocks = GetGraph()->GetBlocks();
+  phi_placeholders_to_materialize->ClearAllBits();
+  phi_placeholders_to_materialize->SetBit(PhiPlaceholderIndex(phi_placeholder));
+  work_queue.push_back(phi_placeholder);
+  while (!work_queue.empty()) {
+    PhiPlaceholder current_phi_placeholder = work_queue.back();
+    work_queue.pop_back();
+    if (!phi_placeholders_to_materialize->IsBitSet(PhiPlaceholderIndex(current_phi_placeholder))) {
+      // Replaced by `TryReplacingLoopPhiPlaceholderWith{Default,SingleInput}()`.
+      DCHECK(phi_placeholder_replacements_[PhiPlaceholderIndex(current_phi_placeholder)].Equals(
+                 Value::Default()));
+      continue;
+    }
+    HBasicBlock* current_block = blocks[current_phi_placeholder.GetBlockId()];
+    DCHECK_GE(current_block->GetPredecessors().size(), 2u);
+    size_t idx = current_phi_placeholder.GetHeapLocation();
+    if (current_block->IsLoopHeader()) {
+      // If the index is defined inside the loop, it may reference different elements of the
+      // array on each iteration. Since we do not track if all elements of an array are set
+      // to the same value explicitly, the only known value in pre-header can be the default
+      // value from NewArray or a Phi placeholder depending on a default value from some outer
+      // loop pre-header. This Phi placeholder can be replaced only by the default value.
+      HInstruction* index = heap_location_collector_.GetHeapLocation(idx)->GetIndex();
+      if (index != nullptr && current_block->GetLoopInformation()->Contains(*index->GetBlock())) {
+        if (can_use_default_or_phi &&
+            TryReplacingLoopPhiPlaceholderWithDefault(current_phi_placeholder,
+                                                      type,
+                                                      phi_placeholders_to_materialize)) {
+          continue;
+        } else {
+          return current_phi_placeholder;  // Report the loop Phi placeholder.
+        }
+      }
+      // A similar situation arises with the index defined outside the loop if we cannot use
+      // default values or Phis, i.e. for vector loads, as we can only replace the Phi
+      // placeholder with a single instruction defined before the loop.
+      if (!can_use_default_or_phi) {
+        DCHECK(index != nullptr);  // Vector operations are array operations.
+        if (TryReplacingLoopPhiPlaceholderWithSingleInput(current_phi_placeholder,
+                                                          phi_placeholders_to_materialize)) {
+          continue;
+        } else {
+          return current_phi_placeholder;  // Report the loop Phi placeholder.
+        }
+      }
+    }
+    for (HBasicBlock* predecessor : current_block->GetPredecessors()) {
+      ScopedArenaVector<ValueRecord>& heap_values = heap_values_for_[predecessor->GetBlockId()];
+      Value value = ReplacementOrValue(heap_values[idx].value);
+      if (value.IsUnknown()) {
+        // We cannot create a Phi for this loop Phi placeholder.
+        return current_phi_placeholder;  // Report the loop Phi placeholder.
+      }
+      // For arrays, the location may have been clobbered by writes to other locations
+      // in a loop that LSA does not consider aliasing, such as `a[i]` and `a[i + 1]`.
+      if (current_block->IsLoopHeader() &&
+          predecessor != current_block->GetLoopInformation()->GetPreHeader() &&
+          heap_location_collector_.GetHeapLocation(idx)->GetIndex() != nullptr) {
+        for (size_t i = 0, size = heap_values.size(); i != size; ++i) {
+          if (i != idx &&
+              !heap_values[i].stored_by.IsUnknown() &&
+              MayAliasOnBackEdge(current_block, idx, i)) {
+            // We cannot create a Phi for this loop Phi placeholder.
+            return current_phi_placeholder;
+          }
+        }
+      }
+      if (value.NeedsLoopPhi()) {
+        // Visit the predecessor Phi placeholder if it's not visited yet.
+        if (!phi_placeholders_to_materialize->IsBitSet(PhiPlaceholderIndex(value))) {
+          phi_placeholders_to_materialize->SetBit(PhiPlaceholderIndex(value));
+          work_queue.push_back(value.GetPhiPlaceholder());
+          LSE_VLOG << "For materialization of " << phi_placeholder
+                   << " we need to materialize " << value;
+        }
+      }
+    }
+  }
+
+  // There are no unknown values feeding this Phi, so we can construct the Phis if needed.
+  return std::nullopt;
+}
+
+bool LSEVisitor::MaterializeLoopPhis(const ScopedArenaVector<size_t>& phi_placeholder_indexes,
+                                     DataType::Type type) {
+  return MaterializeLoopPhis(ArrayRef<const size_t>(phi_placeholder_indexes), type);
+}
+
+bool LSEVisitor::MaterializeLoopPhis(ArrayRef<const size_t> phi_placeholder_indexes,
+                                     DataType::Type type) {
+  // Materialize all predecessors that do not need a loop Phi and determine if all inputs
+  // other than loop Phis are the same.
+  const ArenaVector<HBasicBlock*>& blocks = GetGraph()->GetBlocks();
+  std::optional<Value> other_value = std::nullopt;
+  for (size_t phi_placeholder_index : phi_placeholder_indexes) {
+    PhiPlaceholder phi_placeholder = GetPhiPlaceholderAt(phi_placeholder_index);
+    HBasicBlock* block = blocks[phi_placeholder.GetBlockId()];
+    DCHECK_GE(block->GetPredecessors().size(), 2u);
+    size_t idx = phi_placeholder.GetHeapLocation();
+    for (HBasicBlock* predecessor : block->GetPredecessors()) {
+      Value value = ReplacementOrValue(heap_values_for_[predecessor->GetBlockId()][idx].value);
+      if (value.NeedsNonLoopPhi()) {
+        DCHECK(current_phase_ == Phase::kLoadElimination ||
+               current_phase_ == Phase::kPartialElimination)
+            << current_phase_;
+        MaterializeNonLoopPhis(value.GetPhiPlaceholder(), type);
+        value = Replacement(value);
+      }
+      if (!value.NeedsLoopPhi()) {
+        if (!other_value) {
+          // The first other value we found.
+          other_value = value;
+        } else if (!other_value->IsInvalid()) {
+          // Check if the current `value` differs from the previous `other_value`.
+          if (!value.Equals(*other_value)) {
+            other_value = Value::Invalid();
+          }
+        }
+      }
+    }
+  }
+
+  DCHECK(other_value.has_value());
+  if (!other_value->IsInvalid()) {
+    HInstruction* replacement =
+        (other_value->IsDefault()) ? GetDefaultValue(type) : other_value->GetInstruction();
+    for (size_t phi_placeholder_index : phi_placeholder_indexes) {
+      phi_placeholder_replacements_[phi_placeholder_index] = Value::ForInstruction(replacement);
+    }
+    return true;
+  }
+
+  // If we're materializing only a single Phi, try to match it with an existing Phi.
+  // (Matching multiple Phis would need investigation. It may be prohibitively slow.)
+  // This also covers the case when after replacing a previous set of Phi placeholders,
+  // we continue with a Phi placeholder that does not really need a loop Phi anymore.
+  if (phi_placeholder_indexes.size() == 1u) {
+    PhiPlaceholder phi_placeholder = GetPhiPlaceholderAt(phi_placeholder_indexes[0]);
+    size_t idx = phi_placeholder.GetHeapLocation();
+    HBasicBlock* block = GetGraph()->GetBlocks()[phi_placeholder.GetBlockId()];
+    ArrayRef<HBasicBlock* const> predecessors(block->GetPredecessors());
+    for (HInstructionIterator phi_it(block->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
+      HInstruction* phi = phi_it.Current();
+      DCHECK_EQ(phi->InputCount(), predecessors.size());
+      ArrayRef<HUserRecord<HInstruction*>> phi_inputs = phi->GetInputRecords();
+      auto cmp = [=](const HUserRecord<HInstruction*>& lhs, HBasicBlock* rhs) {
+        Value value = ReplacementOrValue(heap_values_for_[rhs->GetBlockId()][idx].value);
+        if (value.NeedsPhi()) {
+          DCHECK(value.GetPhiPlaceholder() == phi_placeholder);
+          return lhs.GetInstruction() == phi;
+        } else {
+          DCHECK(value.IsDefault() || value.IsInstruction());
+          return value.Equals(lhs.GetInstruction());
+        }
+      };
+      if (std::equal(phi_inputs.begin(), phi_inputs.end(), predecessors.begin(), cmp)) {
+        phi_placeholder_replacements_[phi_placeholder_indexes[0]] = Value::ForInstruction(phi);
+        return true;
+      }
+    }
+  }
+
+  if (current_phase_ == Phase::kStoreElimination) {
+    // We're not creating Phis during the final store elimination phase.
+    return false;
+  }
+
+  // There are different inputs to the Phi chain. Create the Phis.
+  ArenaAllocator* allocator = GetGraph()->GetAllocator();
+  for (size_t phi_placeholder_index : phi_placeholder_indexes) {
+    PhiPlaceholder phi_placeholder = GetPhiPlaceholderAt(phi_placeholder_index);
+    HBasicBlock* block = blocks[phi_placeholder.GetBlockId()];
+    CHECK_GE(block->GetPredecessors().size(), 2u);
+    phi_placeholder_replacements_[phi_placeholder_index] = Value::ForInstruction(
+        new (allocator) HPhi(allocator, kNoRegNumber, block->GetPredecessors().size(), type));
+  }
+  // Fill the Phi inputs.
+  for (size_t phi_placeholder_index : phi_placeholder_indexes) {
+    PhiPlaceholder phi_placeholder = GetPhiPlaceholderAt(phi_placeholder_index);
+    HBasicBlock* block = blocks[phi_placeholder.GetBlockId()];
+    size_t idx = phi_placeholder.GetHeapLocation();
+    HInstruction* phi = phi_placeholder_replacements_[phi_placeholder_index].GetInstruction();
+    DCHECK(DataType::IsTypeConversionImplicit(type, phi->GetType()))
+        << "type=" << type << " vs phi-type=" << phi->GetType();
+    for (size_t i = 0, size = block->GetPredecessors().size(); i != size; ++i) {
+      HBasicBlock* predecessor = block->GetPredecessors()[i];
+      Value value = ReplacementOrValue(heap_values_for_[predecessor->GetBlockId()][idx].value);
+      HInstruction* input = value.IsDefault() ? GetDefaultValue(type) : value.GetInstruction();
+      DCHECK_NE(input->GetType(), DataType::Type::kVoid);
+      phi->SetRawInputAt(i, input);
+      DCHECK(DataType::IsTypeConversionImplicit(input->GetType(), phi->GetType()))
+          << " input: " << input->GetType() << value << " phi: " << phi->GetType()
+          << " request: " << type;
+    }
+  }
+  // Add the Phis to their blocks.
+  for (size_t phi_placeholder_index : phi_placeholder_indexes) {
+    PhiPlaceholder phi_placeholder = GetPhiPlaceholderAt(phi_placeholder_index);
+    HBasicBlock* block = blocks[phi_placeholder.GetBlockId()];
+    block->AddPhi(phi_placeholder_replacements_[phi_placeholder_index].GetInstruction()->AsPhi());
+  }
+  if (type == DataType::Type::kReference) {
+    ScopedArenaAllocator local_allocator(allocator_.GetArenaStack());
+    ScopedArenaVector<HInstruction*> phis(local_allocator.Adapter(kArenaAllocLSE));
+    for (size_t phi_placeholder_index : phi_placeholder_indexes) {
+      phis.push_back(phi_placeholder_replacements_[phi_placeholder_index].GetInstruction());
+    }
+    // Update reference type information. Pass invalid handles, these are not used for Phis.
+    ReferenceTypePropagation rtp_fixup(GetGraph(),
+                                       Handle<mirror::ClassLoader>(),
+                                       Handle<mirror::DexCache>(),
+                                       /* is_first_run= */ false);
+    rtp_fixup.Visit(ArrayRef<HInstruction* const>(phis));
+  }
+
+  return true;
+}
+
+bool LSEVisitor::MaterializeLoopPhis(const ArenaBitVector& phi_placeholders_to_materialize,
+                                     DataType::Type type) {
+  // Use local allocator to reduce peak memory usage.
+  ScopedArenaAllocator allocator(allocator_.GetArenaStack());
+
+  // We want to recognize when a subset of these loop Phis that do not need other
+  // loop Phis, i.e. a transitive closure, has only one other instruction as an input,
+  // i.e. that instruction can be used instead of each Phi in the set. See for example
+  // Main.testLoop{5,6,7,8}() in the test 530-checker-lse. To do that, we shall
+  // materialize these loop Phis from the smallest transitive closure.
+
+  // Construct a matrix of loop phi placeholder dependencies. To reduce the memory usage,
+  // assign new indexes to the Phi placeholders, making the matrix dense.
+  ScopedArenaVector<size_t> matrix_indexes(num_phi_placeholders_,
+                                           static_cast<size_t>(-1),  // Invalid.
+                                           allocator.Adapter(kArenaAllocLSE));
+  ScopedArenaVector<size_t> phi_placeholder_indexes(allocator.Adapter(kArenaAllocLSE));
+  size_t num_phi_placeholders = phi_placeholders_to_materialize.NumSetBits();
+  phi_placeholder_indexes.reserve(num_phi_placeholders);
+  for (uint32_t marker_index : phi_placeholders_to_materialize.Indexes()) {
+    matrix_indexes[marker_index] = phi_placeholder_indexes.size();
+    phi_placeholder_indexes.push_back(marker_index);
+  }
+  const ArenaVector<HBasicBlock*>& blocks = GetGraph()->GetBlocks();
+  ScopedArenaVector<ArenaBitVector*> dependencies(allocator.Adapter(kArenaAllocLSE));
+  dependencies.reserve(num_phi_placeholders);
+  for (size_t matrix_index = 0; matrix_index != num_phi_placeholders; ++matrix_index) {
+    static constexpr bool kExpandable = false;
+    dependencies.push_back(
+        ArenaBitVector::Create(&allocator, num_phi_placeholders, kExpandable, kArenaAllocLSE));
+    ArenaBitVector* current_dependencies = dependencies.back();
+    current_dependencies->ClearAllBits();
+    current_dependencies->SetBit(matrix_index);  // Count the Phi placeholder as its own dependency.
+    PhiPlaceholder current_phi_placeholder =
+        GetPhiPlaceholderAt(phi_placeholder_indexes[matrix_index]);
+    HBasicBlock* current_block = blocks[current_phi_placeholder.GetBlockId()];
+    DCHECK_GE(current_block->GetPredecessors().size(), 2u);
+    size_t idx = current_phi_placeholder.GetHeapLocation();
+    for (HBasicBlock* predecessor : current_block->GetPredecessors()) {
+      Value pred_value = ReplacementOrValue(heap_values_for_[predecessor->GetBlockId()][idx].value);
+      if (pred_value.NeedsLoopPhi()) {
+        size_t pred_value_index = PhiPlaceholderIndex(pred_value);
+        DCHECK(phi_placeholder_replacements_[pred_value_index].IsInvalid());
+        DCHECK_NE(matrix_indexes[pred_value_index], static_cast<size_t>(-1));
+        current_dependencies->SetBit(matrix_indexes[PhiPlaceholderIndex(pred_value)]);
+      }
+    }
+  }
+
+  // Use the Floyd-Warshall algorithm to determine all transitive dependencies.
+  for (size_t k = 0; k != num_phi_placeholders; ++k) {
+    for (size_t i = 0; i != num_phi_placeholders; ++i) {
+      for (size_t j = 0; j != num_phi_placeholders; ++j) {
+        if (dependencies[i]->IsBitSet(k) && dependencies[k]->IsBitSet(j)) {
+          dependencies[i]->SetBit(j);
+        }
+      }
+    }
+  }
+
+  // Count the number of transitive dependencies for each replaceable Phi placeholder.
+  ScopedArenaVector<size_t> num_dependencies(allocator.Adapter(kArenaAllocLSE));
+  num_dependencies.reserve(num_phi_placeholders);
+  for (size_t matrix_index = 0; matrix_index != num_phi_placeholders; ++matrix_index) {
+    num_dependencies.push_back(dependencies[matrix_index]->NumSetBits());
+  }
+
+  // Pick a Phi placeholder with the smallest number of transitive dependencies and
+  // materialize it and its dependencies. Repeat until we have materialized all.
+  ScopedArenaVector<size_t> current_subset(allocator.Adapter(kArenaAllocLSE));
+  current_subset.reserve(num_phi_placeholders);
+  size_t remaining_phi_placeholders = num_phi_placeholders;
+  while (remaining_phi_placeholders != 0u) {
+    auto it = std::min_element(num_dependencies.begin(), num_dependencies.end());
+    DCHECK_LE(*it, remaining_phi_placeholders);
+    size_t current_matrix_index = std::distance(num_dependencies.begin(), it);
+    ArenaBitVector* current_dependencies = dependencies[current_matrix_index];
+    size_t current_num_dependencies = num_dependencies[current_matrix_index];
+    current_subset.clear();
+    for (uint32_t matrix_index : current_dependencies->Indexes()) {
+      current_subset.push_back(phi_placeholder_indexes[matrix_index]);
+    }
+    if (!MaterializeLoopPhis(current_subset, type)) {
+      DCHECK_EQ(current_phase_, Phase::kStoreElimination);
+      // This is the final store elimination phase and we shall not be able to eliminate any
+      // stores that depend on the current subset, so mark these Phi placeholders unreplaceable.
+      for (uint32_t matrix_index = 0; matrix_index != num_phi_placeholders; ++matrix_index) {
+        if (dependencies[matrix_index]->IsBitSet(current_matrix_index)) {
+          DCHECK(phi_placeholder_replacements_[phi_placeholder_indexes[matrix_index]].IsInvalid());
+          phi_placeholder_replacements_[phi_placeholder_indexes[matrix_index]] =
+              Value::PureUnknown();
+        }
+      }
+      return false;
+    }
+    for (uint32_t matrix_index = 0; matrix_index != num_phi_placeholders; ++matrix_index) {
+      if (current_dependencies->IsBitSet(matrix_index)) {
+        // Mark all dependencies as done by incrementing their `num_dependencies[.]`,
+        // so that they shall never be the minimum again.
+        num_dependencies[matrix_index] = num_phi_placeholders;
+      } else if (dependencies[matrix_index]->IsBitSet(current_matrix_index)) {
+        // Remove dependencies from other Phi placeholders.
+        dependencies[matrix_index]->Subtract(current_dependencies);
+        num_dependencies[matrix_index] -= current_num_dependencies;
+      }
+    }
+    remaining_phi_placeholders -= current_num_dependencies;
+  }
+  return true;
+}
+
+bool LSEVisitor::FullyMaterializePhi(PhiPlaceholder phi_placeholder, DataType::Type type) {
+  ScopedArenaAllocator saa(GetGraph()->GetArenaStack());
+  ArenaBitVector abv(&saa, num_phi_placeholders_, false, ArenaAllocKind::kArenaAllocLSE);
+  auto res =
+      FindLoopPhisToMaterialize(phi_placeholder, &abv, type, /* can_use_default_or_phi=*/true);
+  CHECK(!res.has_value()) << *res;
+  return MaterializeLoopPhis(abv, type);
+}
+
+std::optional<LSEVisitor::PhiPlaceholder> LSEVisitor::TryToMaterializeLoopPhis(
+    PhiPlaceholder phi_placeholder, HInstruction* load) {
+  DCHECK(phi_placeholder_replacements_[PhiPlaceholderIndex(phi_placeholder)].IsInvalid());
+
+  // Use local allocator to reduce peak memory usage.
+  ScopedArenaAllocator allocator(allocator_.GetArenaStack());
+
+  // Find Phi placeholders to materialize.
+  ArenaBitVector phi_placeholders_to_materialize(
+      &allocator, num_phi_placeholders_, /*expandable=*/ false, kArenaAllocLSE);
+  phi_placeholders_to_materialize.ClearAllBits();
+  DataType::Type type = load->GetType();
+  bool can_use_default_or_phi = IsDefaultOrPhiAllowedForLoad(load);
+  std::optional<PhiPlaceholder> loop_phi_with_unknown_input = FindLoopPhisToMaterialize(
+      phi_placeholder, &phi_placeholders_to_materialize, type, can_use_default_or_phi);
+  if (loop_phi_with_unknown_input) {
+    DCHECK_GE(GetGraph()
+                  ->GetBlocks()[loop_phi_with_unknown_input->GetBlockId()]
+                  ->GetPredecessors()
+                  .size(),
+              2u);
+    return loop_phi_with_unknown_input;  // Return failure.
+  }
+
+  DCHECK_EQ(current_phase_, Phase::kLoadElimination);
+  bool success = MaterializeLoopPhis(phi_placeholders_to_materialize, type);
+  DCHECK(success);
+
+  // Report success.
+  return std::nullopt;
+}
+
+// Re-process loads and stores in successors from the `loop_phi_with_unknown_input`. This may
+// find one or more loads from `loads_requiring_loop_phi_` which cannot be replaced by Phis and
+// propagate the load(s) as the new value(s) to successors; this may uncover new elimination
+// opportunities. If we find no such load, we shall at least propagate an unknown value to some
+// heap location that is needed by another loop Phi placeholder.
+void LSEVisitor::ProcessLoopPhiWithUnknownInput(PhiPlaceholder loop_phi_with_unknown_input) {
+  size_t loop_phi_with_unknown_input_index = PhiPlaceholderIndex(loop_phi_with_unknown_input);
+  DCHECK(phi_placeholder_replacements_[loop_phi_with_unknown_input_index].IsInvalid());
+  phi_placeholder_replacements_[loop_phi_with_unknown_input_index] =
+      Value::MergedUnknown(loop_phi_with_unknown_input);
+
+  uint32_t block_id = loop_phi_with_unknown_input.GetBlockId();
+  const ArenaVector<HBasicBlock*> reverse_post_order = GetGraph()->GetReversePostOrder();
+  size_t reverse_post_order_index = 0;
+  size_t reverse_post_order_size = reverse_post_order.size();
+  size_t loads_and_stores_index = 0u;
+  size_t loads_and_stores_size = loads_and_stores_.size();
+
+  // Skip blocks and instructions before the block containing the loop phi with unknown input.
+  DCHECK_NE(reverse_post_order_index, reverse_post_order_size);
+  while (reverse_post_order[reverse_post_order_index]->GetBlockId() != block_id) {
+    HBasicBlock* block = reverse_post_order[reverse_post_order_index];
+    while (loads_and_stores_index != loads_and_stores_size &&
+           loads_and_stores_[loads_and_stores_index].load_or_store->GetBlock() == block) {
+      ++loads_and_stores_index;
+    }
+    ++reverse_post_order_index;
+    DCHECK_NE(reverse_post_order_index, reverse_post_order_size);
+  }
+
+  // Use local allocator to reduce peak memory usage.
+  ScopedArenaAllocator allocator(allocator_.GetArenaStack());
+  // Reuse one temporary vector for all remaining blocks.
+  size_t num_heap_locations = heap_location_collector_.GetNumberOfHeapLocations();
+  ScopedArenaVector<Value> local_heap_values(allocator.Adapter(kArenaAllocLSE));
+
+  auto get_initial_value = [this](HBasicBlock* block, size_t idx) {
+    Value value;
+    if (block->IsLoopHeader()) {
+      if (block->GetLoopInformation()->IsIrreducible()) {
+        PhiPlaceholder placeholder = GetPhiPlaceholder(block->GetBlockId(), idx);
+        value = Value::MergedUnknown(placeholder);
+      } else {
+        value = PrepareLoopValue(block, idx);
+      }
+    } else {
+      value = MergePredecessorValues(block, idx);
+    }
+    DCHECK(value.IsUnknown() || ReplacementOrValue(value).Equals(value));
+    return value;
+  };
+
+  // Process remaining blocks and instructions.
+  bool found_unreplaceable_load = false;
+  bool replaced_heap_value_with_unknown = false;
+  for (; reverse_post_order_index != reverse_post_order_size; ++reverse_post_order_index) {
+    HBasicBlock* block = reverse_post_order[reverse_post_order_index];
+    if (block->IsExitBlock()) {
+      continue;
+    }
+
+    // We shall reconstruct only the heap values that we need for processing loads and stores.
+    local_heap_values.clear();
+    local_heap_values.resize(num_heap_locations, Value::Invalid());
+
+    for (; loads_and_stores_index != loads_and_stores_size; ++loads_and_stores_index) {
+      HInstruction* load_or_store = loads_and_stores_[loads_and_stores_index].load_or_store;
+      size_t idx = loads_and_stores_[loads_and_stores_index].heap_location_index;
+      if (load_or_store->GetBlock() != block) {
+        break;  // End of instructions from the current block.
+      }
+      bool is_store = load_or_store->GetSideEffects().DoesAnyWrite();
+      DCHECK_EQ(is_store, IsStore(load_or_store));
+      HInstruction* stored_value = nullptr;
+      if (is_store) {
+        auto it = store_records_.find(load_or_store);
+        DCHECK(it != store_records_.end());
+        stored_value = it->second.stored_value;
+      }
+      auto it = loads_requiring_loop_phi_.find(
+          stored_value != nullptr ? stored_value : load_or_store);
+      if (it == loads_requiring_loop_phi_.end()) {
+        continue;  // This load or store never needed a loop Phi.
+      }
+      ValueRecord& record = it->second;
+      if (is_store) {
+        // Process the store by updating `local_heap_values[idx]`. The last update shall
+        // be propagated to the `heap_values[idx].value` if it previously needed a loop Phi
+        // at the end of the block.
+        Value replacement = ReplacementOrValue(record.value);
+        if (replacement.NeedsLoopPhi()) {
+          // No replacement yet, use the Phi placeholder from the load.
+          DCHECK(record.value.NeedsLoopPhi());
+          local_heap_values[idx] = record.value;
+        } else {
+          // If the load fetched a known value, use it, otherwise use the load.
+          local_heap_values[idx] = Value::ForInstruction(
+              replacement.IsUnknown() ? stored_value : replacement.GetInstruction());
+        }
+      } else {
+        // Process the load unless it has previously been marked unreplaceable.
+        if (record.value.NeedsLoopPhi()) {
+          if (local_heap_values[idx].IsInvalid()) {
+            local_heap_values[idx] = get_initial_value(block, idx);
+          }
+          if (local_heap_values[idx].IsUnknown()) {
+            // This load cannot be replaced. Keep stores that feed the Phi placeholder
+            // (no aliasing since then, otherwise the Phi placeholder would not have been
+            // propagated as a value to this load) and store the load as the new heap value.
+            found_unreplaceable_load = true;
+            KeepStores(record.value);
+            record.value = Value::MergedUnknown(record.value.GetPhiPlaceholder());
+            local_heap_values[idx] = Value::ForInstruction(load_or_store);
+          } else if (local_heap_values[idx].NeedsLoopPhi()) {
+            // The load may still be replaced with a Phi later.
+            DCHECK(local_heap_values[idx].Equals(record.value));
+          } else {
+            // This load can be eliminated but we may need to construct non-loop Phis.
+            if (local_heap_values[idx].NeedsNonLoopPhi()) {
+              MaterializeNonLoopPhis(local_heap_values[idx].GetPhiPlaceholder(),
+                                     load_or_store->GetType());
+              local_heap_values[idx] = Replacement(local_heap_values[idx]);
+            }
+            record.value = local_heap_values[idx];
+            HInstruction* heap_value = local_heap_values[idx].GetInstruction();
+            AddRemovedLoad(load_or_store, heap_value);
+            TryRemovingNullCheck(load_or_store);
+          }
+        }
+      }
+    }
+
+    // All heap values that previously needed a loop Phi at the end of the block
+    // need to be updated for processing successors.
+    ScopedArenaVector<ValueRecord>& heap_values = heap_values_for_[block->GetBlockId()];
+    for (size_t idx = 0; idx != num_heap_locations; ++idx) {
+      if (heap_values[idx].value.NeedsLoopPhi()) {
+        if (local_heap_values[idx].IsValid()) {
+          heap_values[idx].value = local_heap_values[idx];
+        } else {
+          heap_values[idx].value = get_initial_value(block, idx);
+        }
+        if (heap_values[idx].value.IsUnknown()) {
+          replaced_heap_value_with_unknown = true;
+        }
+      }
+    }
+  }
+  DCHECK(found_unreplaceable_load || replaced_heap_value_with_unknown);
+}
+
+void LSEVisitor::ProcessLoadsRequiringLoopPhis() {
+  // Note: The vector operations carve-out (see `IsDefaultOrPhiAllowedForLoad()`) can possibly
+  // make the result of the processing depend on the order in which we process these loads.
+  // To make sure the result is deterministic, iterate over `loads_and_stores_` instead of the
+  // `loads_requiring_loop_phi_` indexed by non-deterministic pointers.
+  for (const LoadStoreRecord& load_store_record : loads_and_stores_) {
+    auto it = loads_requiring_loop_phi_.find(load_store_record.load_or_store);
+    if (it == loads_requiring_loop_phi_.end()) {
+      continue;
+    }
+    HInstruction* load = it->first;
+    ValueRecord& record = it->second;
+    while (record.value.NeedsLoopPhi() &&
+           phi_placeholder_replacements_[PhiPlaceholderIndex(record.value)].IsInvalid()) {
+      std::optional<PhiPlaceholder> loop_phi_with_unknown_input =
+          TryToMaterializeLoopPhis(record.value.GetPhiPlaceholder(), load);
+      DCHECK_EQ(loop_phi_with_unknown_input.has_value(),
+                phi_placeholder_replacements_[PhiPlaceholderIndex(record.value)].IsInvalid());
+      if (loop_phi_with_unknown_input) {
+        DCHECK_GE(GetGraph()
+                      ->GetBlocks()[loop_phi_with_unknown_input->GetBlockId()]
+                      ->GetPredecessors()
+                      .size(),
+                  2u);
+        ProcessLoopPhiWithUnknownInput(*loop_phi_with_unknown_input);
+      }
+    }
+    // The load could have been marked as unreplaceable (and stores marked for keeping)
+    // or marked for replacement with an instruction in ProcessLoopPhiWithUnknownInput().
+    DCHECK(record.value.IsUnknown() || record.value.IsInstruction() || record.value.NeedsLoopPhi());
+    if (record.value.NeedsLoopPhi()) {
+      record.value = Replacement(record.value);
+      HInstruction* heap_value = record.value.GetInstruction();
+      AddRemovedLoad(load, heap_value);
+      TryRemovingNullCheck(load);
+    }
+  }
+}
+
+void LSEVisitor::SearchPhiPlaceholdersForKeptStores() {
+  ScopedArenaVector<uint32_t> work_queue(allocator_.Adapter(kArenaAllocLSE));
+  size_t start_size = phi_placeholders_to_search_for_kept_stores_.NumSetBits();
+  work_queue.reserve(((start_size * 3u) + 1u) / 2u);  // Reserve 1.5x start size, rounded up.
+  for (uint32_t index : phi_placeholders_to_search_for_kept_stores_.Indexes()) {
+    work_queue.push_back(index);
+  }
+  const ArenaVector<HBasicBlock*>& blocks = GetGraph()->GetBlocks();
+  std::optional<ArenaBitVector> not_kept_stores;
+  if (stats_) {
+    not_kept_stores.emplace(GetGraph()->GetAllocator(),
+                            kept_stores_.GetBitSizeOf(),
+                            false,
+                            ArenaAllocKind::kArenaAllocLSE);
+  }
+  while (!work_queue.empty()) {
+    uint32_t cur_phi_idx = work_queue.back();
+    PhiPlaceholder phi_placeholder = GetPhiPlaceholderAt(cur_phi_idx);
+    // Only writes to partial-escapes need to be specifically kept.
+    bool is_partial_kept_merged_unknown =
+        kept_merged_unknowns_.IsBitSet(cur_phi_idx) &&
+        heap_location_collector_.GetHeapLocation(phi_placeholder.GetHeapLocation())
+            ->GetReferenceInfo()
+            ->IsPartialSingleton();
+    work_queue.pop_back();
+    size_t idx = phi_placeholder.GetHeapLocation();
+    HBasicBlock* block = blocks[phi_placeholder.GetBlockId()];
+    DCHECK(block != nullptr) << cur_phi_idx << " phi: " << phi_placeholder
+                             << " (blocks: " << blocks.size() << ")";
+    for (HBasicBlock* predecessor : block->GetPredecessors()) {
+      ScopedArenaVector<ValueRecord>& heap_values = heap_values_for_[predecessor->GetBlockId()];
+      // For loop back-edges we must also preserve all stores to locations that
+      // may alias with the location `idx`.
+      // TODO: Add tests cases around this.
+      bool is_back_edge =
+          block->IsLoopHeader() && predecessor != block->GetLoopInformation()->GetPreHeader();
+      size_t start = is_back_edge ? 0u : idx;
+      size_t end = is_back_edge ? heap_values.size() : idx + 1u;
+      for (size_t i = start; i != end; ++i) {
+        Value stored_by = heap_values[i].stored_by;
+        if (!stored_by.IsUnknown() && (i == idx || MayAliasOnBackEdge(block, idx, i))) {
+          if (stored_by.NeedsPhi()) {
+            size_t phi_placeholder_index = PhiPlaceholderIndex(stored_by);
+            if (is_partial_kept_merged_unknown) {
+              // Propagate merged-unknown keep since otherwise this might look
+              // like a partial escape we can remove.
+              kept_merged_unknowns_.SetBit(phi_placeholder_index);
+            }
+            if (!phi_placeholders_to_search_for_kept_stores_.IsBitSet(phi_placeholder_index)) {
+              phi_placeholders_to_search_for_kept_stores_.SetBit(phi_placeholder_index);
+              work_queue.push_back(phi_placeholder_index);
+            }
+          } else {
+            DCHECK(IsStore(stored_by.GetInstruction()));
+            ReferenceInfo* ri = heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo();
+            DCHECK(ri != nullptr) << "No heap value for " << stored_by.GetInstruction()->DebugName()
+                                  << " id: " << stored_by.GetInstruction()->GetId() << " block: "
+                                  << stored_by.GetInstruction()->GetBlock()->GetBlockId();
+            if (!is_partial_kept_merged_unknown && IsPartialNoEscape(predecessor, idx)) {
+              if (not_kept_stores) {
+                not_kept_stores->SetBit(stored_by.GetInstruction()->GetId());
+              }
+            } else {
+              kept_stores_.SetBit(stored_by.GetInstruction()->GetId());
+            }
+          }
+        }
+      }
+    }
+  }
+  if (not_kept_stores) {
+    // a - b := (a & ~b)
+    not_kept_stores->Subtract(&kept_stores_);
+    auto num_removed = not_kept_stores->NumSetBits();
+    MaybeRecordStat(stats_, MethodCompilationStat::kPartialStoreRemoved, num_removed);
+  }
+}
+
+void LSEVisitor::UpdateValueRecordForStoreElimination(/*inout*/ValueRecord* value_record) {
+  while (value_record->stored_by.IsInstruction() &&
+         !kept_stores_.IsBitSet(value_record->stored_by.GetInstruction()->GetId())) {
+    auto it = store_records_.find(value_record->stored_by.GetInstruction());
+    DCHECK(it != store_records_.end());
+    *value_record = it->second.old_value_record;
+  }
+  if (value_record->stored_by.NeedsPhi() &&
+      !phi_placeholders_to_search_for_kept_stores_.IsBitSet(
+           PhiPlaceholderIndex(value_record->stored_by))) {
+    // Some stores feeding this heap location may have been eliminated. Use the `stored_by`
+    // Phi placeholder to recalculate the actual value.
+    value_record->value = value_record->stored_by;
+  }
+  value_record->value = ReplacementOrValue(value_record->value);
+  if (value_record->value.NeedsNonLoopPhi()) {
+    // Treat all Phi placeholders as requiring loop Phis at this point.
+    // We do not want MaterializeLoopPhis() to call MaterializeNonLoopPhis().
+    value_record->value = Value::ForLoopPhiPlaceholder(value_record->value.GetPhiPlaceholder());
+  }
+}
+
+void LSEVisitor::FindOldValueForPhiPlaceholder(PhiPlaceholder phi_placeholder,
+                                               DataType::Type type) {
+  DCHECK(phi_placeholder_replacements_[PhiPlaceholderIndex(phi_placeholder)].IsInvalid());
+
+  // Use local allocator to reduce peak memory usage.
+  ScopedArenaAllocator allocator(allocator_.GetArenaStack());
+  ArenaBitVector visited(&allocator,
+                         /*start_bits=*/ num_phi_placeholders_,
+                         /*expandable=*/ false,
+                         kArenaAllocLSE);
+  visited.ClearAllBits();
+
+  // Find Phi placeholders to try and match against existing Phis or other replacement values.
+  ArenaBitVector phi_placeholders_to_materialize(
+      &allocator, num_phi_placeholders_, /*expandable=*/ false, kArenaAllocLSE);
+  phi_placeholders_to_materialize.ClearAllBits();
+  std::optional<PhiPlaceholder> loop_phi_with_unknown_input = FindLoopPhisToMaterialize(
+      phi_placeholder, &phi_placeholders_to_materialize, type, /*can_use_default_or_phi=*/true);
+  if (loop_phi_with_unknown_input) {
+    DCHECK_GE(GetGraph()
+                  ->GetBlocks()[loop_phi_with_unknown_input->GetBlockId()]
+                  ->GetPredecessors()
+                  .size(),
+              2u);
+    // Mark the unreplacable placeholder as well as the input Phi placeholder as unreplaceable.
+    phi_placeholder_replacements_[PhiPlaceholderIndex(phi_placeholder)] = Value::PureUnknown();
+    phi_placeholder_replacements_[PhiPlaceholderIndex(*loop_phi_with_unknown_input)] =
+        Value::PureUnknown();
+    return;
+  }
+
+  DCHECK_EQ(current_phase_, Phase::kStoreElimination);
+  bool success = MaterializeLoopPhis(phi_placeholders_to_materialize, type);
+  DCHECK(phi_placeholder_replacements_[PhiPlaceholderIndex(phi_placeholder)].IsValid());
+  DCHECK_EQ(phi_placeholder_replacements_[PhiPlaceholderIndex(phi_placeholder)].IsUnknown(),
+            !success);
+}
+
+struct ScopedRestoreHeapValues {
+ public:
+  ScopedRestoreHeapValues(ArenaStack* alloc,
+                          size_t num_heap_locs,
+                          ScopedArenaVector<ScopedArenaVector<LSEVisitor::ValueRecord>>& to_restore)
+      : alloc_(alloc),
+        updated_values_(alloc_.Adapter(kArenaAllocLSE)),
+        to_restore_(to_restore) {
+    updated_values_.reserve(num_heap_locs * to_restore_.size());
+  }
+
+  ~ScopedRestoreHeapValues() {
+    for (const auto& rec : updated_values_) {
+      to_restore_[rec.blk_id][rec.heap_loc].value = rec.val_;
+    }
+  }
+
+  template<typename Func>
+  void ForEachRecord(Func func) {
+    for (size_t blk_id : Range(to_restore_.size())) {
+      for (size_t heap_loc : Range(to_restore_[blk_id].size())) {
+        LSEVisitor::ValueRecord* vr = &to_restore_[blk_id][heap_loc];
+        LSEVisitor::Value initial = vr->value;
+        func(vr);
+        if (!vr->value.ExactEquals(initial)) {
+          updated_values_.push_back({blk_id, heap_loc, initial});
+        }
+      }
+    }
+  }
+
+ private:
+  struct UpdateRecord {
+    size_t blk_id;
+    size_t heap_loc;
+    LSEVisitor::Value val_;
+  };
+  ScopedArenaAllocator alloc_;
+  ScopedArenaVector<UpdateRecord> updated_values_;
+  ScopedArenaVector<ScopedArenaVector<LSEVisitor::ValueRecord>>& to_restore_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedRestoreHeapValues);
+};
+
+void LSEVisitor::FindStoresWritingOldValues() {
+  // Partial LSE relies on knowing the real heap-values not the
+  // store-replacement versions so we need to restore the map after removing
+  // stores.
+  ScopedRestoreHeapValues heap_vals(allocator_.GetArenaStack(),
+                                    heap_location_collector_.GetNumberOfHeapLocations(),
+                                    heap_values_for_);
+  // The Phi placeholder replacements have so far been used for eliminating loads,
+  // tracking values that would be stored if all stores were kept. As we want to
+  // compare actual old values after removing unmarked stores, prune the Phi
+  // placeholder replacements that can be fed by values we may not actually store.
+  // Replacements marked as unknown can be kept as they are fed by some unknown
+  // value and would end up as unknown again if we recalculated them.
+  for (size_t i = 0, size = phi_placeholder_replacements_.size(); i != size; ++i) {
+    if (!phi_placeholder_replacements_[i].IsUnknown() &&
+        !phi_placeholders_to_search_for_kept_stores_.IsBitSet(i)) {
+      phi_placeholder_replacements_[i] = Value::Invalid();
+    }
+  }
+
+  // Update heap values at end of blocks.
+  heap_vals.ForEachRecord([&](ValueRecord* rec) {
+    UpdateValueRecordForStoreElimination(rec);
+  });
+
+  if (kIsDebugBuild) {
+    heap_vals.ForEachRecord([](ValueRecord* rec) {
+      DCHECK(!rec->value.NeedsNonLoopPhi()) << rec->value;
+    });
+  }
+
+  // Use local allocator to reduce peak memory usage.
+  ScopedArenaAllocator allocator(allocator_.GetArenaStack());
+  // Mark the stores we want to eliminate in a separate bit vector.
+  ArenaBitVector eliminated_stores(&allocator,
+                                   /*start_bits=*/ GetGraph()->GetCurrentInstructionId(),
+                                   /*expandable=*/ false,
+                                   kArenaAllocLSE);
+  eliminated_stores.ClearAllBits();
+
+  for (auto& entry : store_records_) {
+    HInstruction* store = entry.first;
+    StoreRecord& store_record = entry.second;
+    if (!kept_stores_.IsBitSet(store->GetId())) {
+      continue;  // Ignore stores that are not kept.
+    }
+    UpdateValueRecordForStoreElimination(&store_record.old_value_record);
+    if (store_record.old_value_record.value.NeedsPhi()) {
+      DataType::Type type = store_record.stored_value->GetType();
+      FindOldValueForPhiPlaceholder(store_record.old_value_record.value.GetPhiPlaceholder(), type);
+      store_record.old_value_record.value = ReplacementOrValue(store_record.old_value_record.value);
+    }
+    DCHECK(!store_record.old_value_record.value.NeedsPhi());
+    HInstruction* stored_value = FindSubstitute(store_record.stored_value);
+    if (store_record.old_value_record.value.Equals(stored_value)) {
+      eliminated_stores.SetBit(store->GetId());
+    }
+  }
+
+  // Commit the stores to eliminate by removing them from `kept_stores_`.
+  kept_stores_.Subtract(&eliminated_stores);
+}
+
+void LSEVisitor::Run() {
+  // 1. Process blocks and instructions in reverse post order.
+  for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
+    VisitBasicBlock(block);
+  }
+
+  // 2. Process loads that require loop Phis, trying to find/create replacements.
+  current_phase_ = Phase::kLoadElimination;
+  ProcessLoadsRequiringLoopPhis();
+
+  // 3. Determine which stores to keep and which to eliminate.
+  current_phase_ = Phase::kStoreElimination;
+  // Finish marking stores for keeping.
+  SearchPhiPlaceholdersForKeptStores();
+
+  // Find stores that write the same value as is already present in the location.
+  FindStoresWritingOldValues();
+
+  // 4. Replace loads and remove unnecessary stores and singleton allocations.
+  FinishFullLSE();
+
+  // 5. Move partial escapes down and fixup with PHIs.
+  current_phase_ = Phase::kPartialElimination;
+  MovePartialEscapes();
+}
+
+// Clear unknown loop-phi results. Here we'll be able to use partial-unknowns so we need to
+// retry all of them with more information about where they come from.
+void LSEVisitor::PrepareForPartialPhiComputation() {
+  std::replace_if(
+      phi_placeholder_replacements_.begin(),
+      phi_placeholder_replacements_.end(),
+      [](const Value& val) { return !val.IsDefault() && !val.IsInstruction(); },
+      Value::Invalid());
+}
+
+class PartialLoadStoreEliminationHelper {
+ public:
+  PartialLoadStoreEliminationHelper(LSEVisitor* lse, ScopedArenaAllocator* alloc)
+      : lse_(lse),
+        alloc_(alloc),
+        new_ref_phis_(alloc_->Adapter(kArenaAllocLSE)),
+        heap_refs_(alloc_->Adapter(kArenaAllocLSE)),
+        max_preds_per_block_((*std::max_element(GetGraph()->GetActiveBlocks().begin(),
+                                                GetGraph()->GetActiveBlocks().end(),
+                                                [](HBasicBlock* a, HBasicBlock* b) {
+                                                  return a->GetNumberOfPredecessors() <
+                                                         b->GetNumberOfPredecessors();
+                                                }))
+                                 ->GetNumberOfPredecessors()),
+        materialization_blocks_(GetGraph()->GetBlocks().size() * max_preds_per_block_,
+                                nullptr,
+                                alloc_->Adapter(kArenaAllocLSE)),
+        first_materialization_block_id_(GetGraph()->GetBlocks().size()) {
+    size_t num_partial_singletons = lse_->heap_location_collector_.CountPartialSingletons();
+    heap_refs_.reserve(num_partial_singletons);
+    new_ref_phis_.reserve(num_partial_singletons * GetGraph()->GetBlocks().size());
+    CollectInterestingHeapRefs();
+  }
+
+  ~PartialLoadStoreEliminationHelper() {
+    if (heap_refs_.empty()) {
+      return;
+    }
+    ReferenceTypePropagation rtp_fixup(GetGraph(),
+                                       Handle<mirror::ClassLoader>(),
+                                       Handle<mirror::DexCache>(),
+                                       /* is_first_run= */ false);
+    rtp_fixup.Visit(ArrayRef<HInstruction* const>(new_ref_phis_));
+    GetGraph()->ClearLoopInformation();
+    GetGraph()->ClearDominanceInformation();
+    GetGraph()->ClearReachabilityInformation();
+    GetGraph()->BuildDominatorTree();
+    GetGraph()->ComputeReachabilityInformation();
+  }
+
+  class IdxToHeapLoc {
+   public:
+    explicit IdxToHeapLoc(const HeapLocationCollector* hlc) : collector_(hlc) {}
+    HeapLocation* operator()(size_t idx) const {
+      return collector_->GetHeapLocation(idx);
+    }
+
+   private:
+    const HeapLocationCollector* collector_;
+  };
+
+
+  class HeapReferenceData {
+   public:
+    using LocIterator = IterationRange<TransformIterator<BitVector::IndexIterator, IdxToHeapLoc>>;
+    HeapReferenceData(PartialLoadStoreEliminationHelper* helper,
+                      HNewInstance* new_inst,
+                      const ExecutionSubgraph* subgraph,
+                      ScopedArenaAllocator* alloc)
+        : new_instance_(new_inst),
+          helper_(helper),
+          heap_locs_(alloc,
+                     helper->lse_->heap_location_collector_.GetNumberOfHeapLocations(),
+                     /* expandable= */ false,
+                     kArenaAllocLSE),
+          materializations_(
+              // We generally won't need to create too many materialization blocks and we can expand
+              // this as needed so just start off with 2x.
+              2 * helper->lse_->GetGraph()->GetBlocks().size(),
+              nullptr,
+              alloc->Adapter(kArenaAllocLSE)),
+          collector_(helper->lse_->heap_location_collector_),
+          subgraph_(subgraph) {}
+
+    LocIterator IterateLocations() {
+      auto idxs = heap_locs_.Indexes();
+      return MakeTransformRange(idxs, IdxToHeapLoc(&collector_));
+    }
+
+    void AddHeapLocation(size_t idx) {
+      heap_locs_.SetBit(idx);
+    }
+
+    const ExecutionSubgraph* GetNoEscapeSubgraph() const {
+      return subgraph_;
+    }
+
+    bool IsPostEscape(HBasicBlock* blk) {
+      return std::any_of(
+          subgraph_->GetExcludedCohorts().cbegin(),
+          subgraph_->GetExcludedCohorts().cend(),
+          [&](const ExecutionSubgraph::ExcludedCohort& ec) { return ec.PrecedesBlock(blk); });
+    }
+
+    bool InEscapeCohort(HBasicBlock* blk) {
+      return std::any_of(
+          subgraph_->GetExcludedCohorts().cbegin(),
+          subgraph_->GetExcludedCohorts().cend(),
+          [&](const ExecutionSubgraph::ExcludedCohort& ec) { return ec.ContainsBlock(blk); });
+    }
+
+    bool BeforeAllEscapes(HBasicBlock* b) {
+      return std::none_of(subgraph_->GetExcludedCohorts().cbegin(),
+                          subgraph_->GetExcludedCohorts().cend(),
+                          [&](const ExecutionSubgraph::ExcludedCohort& ec) {
+                            return ec.PrecedesBlock(b) || ec.ContainsBlock(b);
+                          });
+    }
+
+    HNewInstance* OriginalNewInstance() const {
+      return new_instance_;
+    }
+
+    // Collect and replace all uses. We need to perform this twice since we will
+    // generate PHIs and additional uses as we create the default-values for
+    // pred-gets. These values might be other references that are also being
+    // partially eliminated. By running just the replacement part again we are
+    // able to avoid having to keep another whole in-progress partial map
+    // around. Since we will have already handled all the other uses in the
+    // first pass the second one will be quite fast.
+    void FixupUses(bool first_pass) {
+      ScopedArenaAllocator saa(GetGraph()->GetArenaStack());
+      // Replace uses with materialized values.
+      ScopedArenaVector<InstructionUse<HInstruction>> to_replace(saa.Adapter(kArenaAllocLSE));
+      ScopedArenaVector<HInstruction*> to_remove(saa.Adapter(kArenaAllocLSE));
+      // Do we need to add a constructor-fence.
+      ScopedArenaVector<InstructionUse<HConstructorFence>> constructor_fences(
+          saa.Adapter(kArenaAllocLSE));
+      ScopedArenaVector<InstructionUse<HInstruction>> to_predicate(saa.Adapter(kArenaAllocLSE));
+
+      CollectReplacements(to_replace, to_remove, constructor_fences, to_predicate);
+
+      if (!first_pass) {
+        // If another partial creates new references they can only be in Phis or pred-get defaults
+        // so they must be in the to_replace group.
+        DCHECK(to_predicate.empty());
+        DCHECK(constructor_fences.empty());
+        DCHECK(to_remove.empty());
+      }
+
+      ReplaceInput(to_replace);
+      RemoveAndReplaceInputs(to_remove);
+      CreateConstructorFences(constructor_fences);
+      PredicateInstructions(to_predicate);
+
+      CHECK(OriginalNewInstance()->GetUses().empty())
+          << OriginalNewInstance()->GetUses() << ", " << OriginalNewInstance()->GetEnvUses();
+    }
+
+    void AddMaterialization(HBasicBlock* blk, HInstruction* ins) {
+      if (blk->GetBlockId() >= materializations_.size()) {
+        // Make sure the materialization array is large enough, try to avoid
+        // re-sizing too many times by giving extra space.
+        materializations_.resize(blk->GetBlockId() * 2, nullptr);
+      }
+      DCHECK(materializations_[blk->GetBlockId()] == nullptr)
+          << "Already have a materialization in block " << blk->GetBlockId() << ": "
+          << *materializations_[blk->GetBlockId()] << " when trying to set materialization to "
+          << *ins;
+      materializations_[blk->GetBlockId()] = ins;
+      LSE_VLOG << "In  block " << blk->GetBlockId() << " materialization is " << *ins;
+      helper_->NotifyNewMaterialization(ins);
+    }
+
+    bool HasMaterialization(HBasicBlock* blk) const {
+      return blk->GetBlockId() < materializations_.size() &&
+             materializations_[blk->GetBlockId()] != nullptr;
+    }
+
+    HInstruction* GetMaterialization(HBasicBlock* blk) const {
+      if (materializations_.size() <= blk->GetBlockId() ||
+          materializations_[blk->GetBlockId()] == nullptr) {
+        // This must be a materialization block added after the partial LSE of
+        // the current reference finished. Since every edge can only have at
+        // most one materialization block added to it we can just check the
+        // blocks predecessor.
+        DCHECK(helper_->IsMaterializationBlock(blk));
+        blk = helper_->FindDominatingNonMaterializationBlock(blk);
+        DCHECK(!helper_->IsMaterializationBlock(blk));
+      }
+      DCHECK_GT(materializations_.size(), blk->GetBlockId());
+      DCHECK(materializations_[blk->GetBlockId()] != nullptr);
+      return materializations_[blk->GetBlockId()];
+    }
+
+    void GenerateMaterializationValueFromPredecessors(HBasicBlock* blk) {
+      DCHECK(std::none_of(GetNoEscapeSubgraph()->GetExcludedCohorts().begin(),
+                          GetNoEscapeSubgraph()->GetExcludedCohorts().end(),
+                          [&](const ExecutionSubgraph::ExcludedCohort& cohort) {
+                            return cohort.IsEntryBlock(blk);
+                          }));
+      DCHECK(!HasMaterialization(blk));
+      if (blk->IsExitBlock()) {
+        return;
+      } else if (blk->IsLoopHeader()) {
+        // See comment in execution_subgraph.h. Currently we act as though every
+        // allocation for partial elimination takes place in the entry block.
+        // This simplifies the analysis by making it so any escape cohort
+        // expands to contain any loops it is a part of. This is something that
+        // we should rectify at some point. In either case however we can still
+        // special case the loop-header since (1) currently the loop can't have
+        // any merges between different cohort entries since the pre-header will
+        // be the earliest place entry can happen and (2) even if the analysis
+        // is improved to consider lifetime of the object WRT loops any values
+        // which would require loop-phis would have to make the whole loop
+        // escape anyway.
+        // This all means we can always use value from the pre-header when the
+        // block is the loop-header and we didn't already create a
+        // materialization block. (NB when we do improve the analysis we will
+        // need to modify the materialization creation code to deal with this
+        // correctly.)
+        HInstruction* pre_header_val =
+            GetMaterialization(blk->GetLoopInformation()->GetPreHeader());
+        AddMaterialization(blk, pre_header_val);
+        return;
+      }
+      ScopedArenaAllocator saa(GetGraph()->GetArenaStack());
+      ScopedArenaVector<HInstruction*> pred_vals(saa.Adapter(kArenaAllocLSE));
+      pred_vals.reserve(blk->GetNumberOfPredecessors());
+      for (HBasicBlock* pred : blk->GetPredecessors()) {
+        DCHECK(HasMaterialization(pred));
+        pred_vals.push_back(GetMaterialization(pred));
+      }
+      GenerateMaterializationValueFromPredecessorsDirect(blk, pred_vals);
+    }
+
+    void GenerateMaterializationValueFromPredecessorsForEntry(
+        HBasicBlock* entry, const ScopedArenaVector<HInstruction*>& pred_vals) {
+      DCHECK(std::any_of(GetNoEscapeSubgraph()->GetExcludedCohorts().begin(),
+                         GetNoEscapeSubgraph()->GetExcludedCohorts().end(),
+                         [&](const ExecutionSubgraph::ExcludedCohort& cohort) {
+                           return cohort.IsEntryBlock(entry);
+                         }));
+      GenerateMaterializationValueFromPredecessorsDirect(entry, pred_vals);
+    }
+
+   private:
+    template <typename InstructionType>
+    struct InstructionUse {
+      InstructionType* instruction_;
+      size_t index_;
+    };
+
+    void ReplaceInput(const ScopedArenaVector<InstructionUse<HInstruction>>& to_replace) {
+      for (auto& [ins, idx] : to_replace) {
+        HInstruction* merged_inst = GetMaterialization(ins->GetBlock());
+        if (ins->IsPhi() && merged_inst->IsPhi() && ins->GetBlock() == merged_inst->GetBlock()) {
+          // Phis we just pass through the appropriate inputs.
+          ins->ReplaceInput(merged_inst->InputAt(idx), idx);
+        } else {
+          ins->ReplaceInput(merged_inst, idx);
+        }
+      }
+    }
+
+    void RemoveAndReplaceInputs(const ScopedArenaVector<HInstruction*>& to_remove) {
+      for (HInstruction* ins : to_remove) {
+        if (ins->GetBlock() == nullptr) {
+          // Already dealt with.
+          continue;
+        }
+        DCHECK(BeforeAllEscapes(ins->GetBlock())) << *ins;
+        if (ins->IsInstanceFieldGet() || ins->IsInstanceFieldSet()) {
+          bool instruction_has_users =
+              ins->IsInstanceFieldGet() && (!ins->GetUses().empty() || !ins->GetEnvUses().empty());
+          if (instruction_has_users) {
+            // Make sure any remaining users of read are replaced.
+            HInstruction* replacement =
+                helper_->lse_->GetPartialValueAt(OriginalNewInstance(), ins);
+            // NB ReplaceInput will remove a use from the list so this is
+            // guaranteed to finish eventually.
+            while (!ins->GetUses().empty()) {
+              const HUseListNode<HInstruction*>& use = ins->GetUses().front();
+              use.GetUser()->ReplaceInput(replacement, use.GetIndex());
+            }
+            while (!ins->GetEnvUses().empty()) {
+              const HUseListNode<HEnvironment*>& use = ins->GetEnvUses().front();
+              use.GetUser()->ReplaceInput(replacement, use.GetIndex());
+            }
+          } else {
+            DCHECK(ins->GetUses().empty())
+                << "Instruction has users!\n"
+                << ins->DumpWithArgs() << "\nUsers are " << ins->GetUses();
+            DCHECK(ins->GetEnvUses().empty())
+                << "Instruction has users!\n"
+                << ins->DumpWithArgs() << "\nUsers are " << ins->GetEnvUses();
+          }
+          ins->GetBlock()->RemoveInstruction(ins);
+        } else {
+          // Can only be obj == other, obj != other, obj == obj (!?) or, obj != obj (!?)
+          // Since PHIs are escapes as far as LSE is concerned and we are before
+          // any escapes these are the only 4 options.
+          DCHECK(ins->IsEqual() || ins->IsNotEqual()) << *ins;
+          HInstruction* replacement;
+          if (UNLIKELY(ins->InputAt(0) == ins->InputAt(1))) {
+            replacement = ins->IsEqual() ? GetGraph()->GetIntConstant(1)
+                                         : GetGraph()->GetIntConstant(0);
+          } else {
+            replacement = ins->IsEqual() ? GetGraph()->GetIntConstant(0)
+                                         : GetGraph()->GetIntConstant(1);
+          }
+          ins->ReplaceWith(replacement);
+          ins->GetBlock()->RemoveInstruction(ins);
+        }
+      }
+    }
+
+    void CreateConstructorFences(
+        const ScopedArenaVector<InstructionUse<HConstructorFence>>& constructor_fences) {
+      if (!constructor_fences.empty()) {
+        uint32_t pc = constructor_fences.front().instruction_->GetDexPc();
+        for (auto& [cf, idx] : constructor_fences) {
+          if (cf->GetInputs().size() == 1) {
+            cf->GetBlock()->RemoveInstruction(cf);
+          } else {
+            cf->RemoveInputAt(idx);
+          }
+        }
+        for (const ExecutionSubgraph::ExcludedCohort& ec :
+            GetNoEscapeSubgraph()->GetExcludedCohorts()) {
+          for (HBasicBlock* blk : ec.EntryBlocks()) {
+            for (HBasicBlock* materializer :
+                Filter(MakeIterationRange(blk->GetPredecessors()),
+                        [&](HBasicBlock* blk) { return helper_->IsMaterializationBlock(blk); })) {
+              HInstruction* new_cf = new (GetGraph()->GetAllocator()) HConstructorFence(
+                  GetMaterialization(materializer), pc, GetGraph()->GetAllocator());
+              materializer->InsertInstructionBefore(new_cf, materializer->GetLastInstruction());
+            }
+          }
+        }
+      }
+    }
+
+    void PredicateInstructions(
+        const ScopedArenaVector<InstructionUse<HInstruction>>& to_predicate) {
+      for (auto& [ins, idx] : to_predicate) {
+        if (UNLIKELY(ins->GetBlock() == nullptr)) {
+          // Already handled due to obj == obj;
+          continue;
+        } else if (ins->IsInstanceFieldGet()) {
+          // IFieldGet[obj] => PredicatedIFieldGet[PartialValue, obj]
+          HInstruction* new_fget = new (GetGraph()->GetAllocator()) HPredicatedInstanceFieldGet(
+              ins->AsInstanceFieldGet(),
+              GetMaterialization(ins->GetBlock()),
+              helper_->lse_->GetPartialValueAt(OriginalNewInstance(), ins));
+          MaybeRecordStat(helper_->lse_->stats_, MethodCompilationStat::kPredicatedLoadAdded);
+          ins->GetBlock()->InsertInstructionBefore(new_fget, ins);
+          if (ins->GetType() == DataType::Type::kReference) {
+            // Reference info is the same
+            new_fget->SetReferenceTypeInfo(ins->GetReferenceTypeInfo());
+          }
+          // In this phase, substitute instructions are used only for the predicated get
+          // default values which are used only if the partial singleton did not escape,
+          // so the out value of the `new_fget` for the relevant cases is the same as
+          // the default value.
+          // TODO: Use the default value for materializing default values used by
+          // other predicated loads to avoid some unnecessary Phis. (This shall
+          // complicate the search for replacement in `ReplacementOrValue()`.)
+          DCHECK(helper_->lse_->substitute_instructions_for_loads_[ins->GetId()] == nullptr);
+          helper_->lse_->substitute_instructions_for_loads_[ins->GetId()] = new_fget;
+          ins->ReplaceWith(new_fget);
+          ins->ReplaceEnvUsesDominatedBy(ins, new_fget);
+          CHECK(ins->GetEnvUses().empty() && ins->GetUses().empty())
+              << "Instruction: " << *ins << " uses: " << ins->GetUses()
+              << ", env: " << ins->GetEnvUses();
+          ins->GetBlock()->RemoveInstruction(ins);
+        } else if (ins->IsInstanceFieldSet()) {
+          // Any predicated sets shouldn't require movement.
+          ins->AsInstanceFieldSet()->SetIsPredicatedSet();
+          MaybeRecordStat(helper_->lse_->stats_, MethodCompilationStat::kPredicatedStoreAdded);
+          HInstruction* merged_inst = GetMaterialization(ins->GetBlock());
+          ins->ReplaceInput(merged_inst, idx);
+        } else {
+          // comparisons need to be split into 2.
+          DCHECK(ins->IsEqual() || ins->IsNotEqual()) << "bad instruction " << *ins;
+          bool this_is_first = idx == 0;
+          if (ins->InputAt(0) == ins->InputAt(1)) {
+            // This is a obj == obj or obj != obj.
+            // No idea why anyone would do this but whatever.
+            ins->ReplaceWith(GetGraph()->GetIntConstant(ins->IsEqual() ? 1 : 0));
+            ins->GetBlock()->RemoveInstruction(ins);
+            continue;
+          } else {
+            HInstruction* is_escaped = new (GetGraph()->GetAllocator())
+                HNotEqual(GetMaterialization(ins->GetBlock()), GetGraph()->GetNullConstant());
+            HInstruction* combine_inst =
+                ins->IsEqual() ? static_cast<HInstruction*>(new (GetGraph()->GetAllocator()) HAnd(
+                                     DataType::Type::kBool, is_escaped, ins))
+                               : static_cast<HInstruction*>(new (GetGraph()->GetAllocator()) HOr(
+                                     DataType::Type::kBool, is_escaped, ins));
+            ins->ReplaceInput(GetMaterialization(ins->GetBlock()), this_is_first ? 0 : 1);
+            ins->GetBlock()->InsertInstructionBefore(is_escaped, ins);
+            ins->GetBlock()->InsertInstructionAfter(combine_inst, ins);
+            ins->ReplaceWith(combine_inst);
+            combine_inst->ReplaceInput(ins, 1);
+          }
+        }
+      }
+    }
+
+    // Figure out all the instructions we need to
+    // fixup/replace/remove/duplicate. Since this requires an iteration of an
+    // intrusive linked list we want to do it only once and collect all the data
+    // here.
+    void CollectReplacements(
+        ScopedArenaVector<InstructionUse<HInstruction>>& to_replace,
+        ScopedArenaVector<HInstruction*>& to_remove,
+        ScopedArenaVector<InstructionUse<HConstructorFence>>& constructor_fences,
+        ScopedArenaVector<InstructionUse<HInstruction>>& to_predicate) {
+      size_t size = new_instance_->GetUses().SizeSlow();
+      to_replace.reserve(size);
+      to_remove.reserve(size);
+      constructor_fences.reserve(size);
+      to_predicate.reserve(size);
+      for (auto& use : new_instance_->GetUses()) {
+        HBasicBlock* blk =
+            helper_->FindDominatingNonMaterializationBlock(use.GetUser()->GetBlock());
+        if (InEscapeCohort(blk)) {
+          LSE_VLOG << "Replacing " << *new_instance_ << " use in " << *use.GetUser() << " with "
+                   << *GetMaterialization(blk);
+          to_replace.push_back({use.GetUser(), use.GetIndex()});
+        } else if (IsPostEscape(blk)) {
+          LSE_VLOG << "User " << *use.GetUser() << " after escapes!";
+          // The fields + cmp are normal uses. Phi can only be here if it was
+          // generated by full LSE so whatever store+load that created the phi
+          // is the escape.
+          if (use.GetUser()->IsPhi()) {
+            to_replace.push_back({use.GetUser(), use.GetIndex()});
+          } else {
+            DCHECK(use.GetUser()->IsFieldAccess() ||
+                   use.GetUser()->IsEqual() ||
+                   use.GetUser()->IsNotEqual())
+                << *use.GetUser() << "@" << use.GetIndex();
+            to_predicate.push_back({use.GetUser(), use.GetIndex()});
+          }
+        } else if (use.GetUser()->IsConstructorFence()) {
+          LSE_VLOG << "User " << *use.GetUser() << " being moved to materialization!";
+          constructor_fences.push_back({use.GetUser()->AsConstructorFence(), use.GetIndex()});
+        } else {
+          LSE_VLOG << "User " << *use.GetUser() << " not contained in cohort!";
+          to_remove.push_back(use.GetUser());
+        }
+      }
+      DCHECK_EQ(
+          to_replace.size() + to_remove.size() + constructor_fences.size() + to_predicate.size(),
+          size);
+    }
+
+    void GenerateMaterializationValueFromPredecessorsDirect(
+        HBasicBlock* blk, const ScopedArenaVector<HInstruction*>& pred_vals) {
+      DCHECK(!pred_vals.empty());
+      bool all_equal = std::all_of(pred_vals.begin() + 1, pred_vals.end(), [&](HInstruction* val) {
+        return val == pred_vals.front();
+      });
+      if (LIKELY(all_equal)) {
+        AddMaterialization(blk, pred_vals.front());
+      } else {
+        // Make a PHI for the predecessors.
+        HPhi* phi = new (GetGraph()->GetAllocator()) HPhi(
+            GetGraph()->GetAllocator(), kNoRegNumber, pred_vals.size(), DataType::Type::kReference);
+        for (const auto& [ins, off] : ZipCount(MakeIterationRange(pred_vals))) {
+          phi->SetRawInputAt(off, ins);
+        }
+        blk->AddPhi(phi);
+        AddMaterialization(blk, phi);
+      }
+    }
+
+    HGraph* GetGraph() const {
+      return helper_->GetGraph();
+    }
+
+    HNewInstance* new_instance_;
+    PartialLoadStoreEliminationHelper* helper_;
+    ArenaBitVector heap_locs_;
+    ScopedArenaVector<HInstruction*> materializations_;
+    const HeapLocationCollector& collector_;
+    const ExecutionSubgraph* subgraph_;
+  };
+
+  ArrayRef<HeapReferenceData> GetHeapRefs() {
+    return ArrayRef<HeapReferenceData>(heap_refs_);
+  }
+
+  bool IsMaterializationBlock(HBasicBlock* blk) const {
+    return blk->GetBlockId() >= first_materialization_block_id_;
+  }
+
+  HBasicBlock* GetOrCreateMaterializationBlock(HBasicBlock* entry, size_t pred_num) {
+    size_t idx = GetMaterializationBlockIndex(entry, pred_num);
+    HBasicBlock* blk = materialization_blocks_[idx];
+    if (blk == nullptr) {
+      blk = new (GetGraph()->GetAllocator()) HBasicBlock(GetGraph());
+      GetGraph()->AddBlock(blk);
+      LSE_VLOG << "creating materialization block " << blk->GetBlockId() << " on edge "
+               << entry->GetPredecessors()[pred_num]->GetBlockId() << "->" << entry->GetBlockId();
+      blk->AddInstruction(new (GetGraph()->GetAllocator()) HGoto());
+      materialization_blocks_[idx] = blk;
+    }
+    return blk;
+  }
+
+  HBasicBlock* GetMaterializationBlock(HBasicBlock* entry, size_t pred_num) {
+    HBasicBlock* out = materialization_blocks_[GetMaterializationBlockIndex(entry, pred_num)];
+    DCHECK(out != nullptr) << "No materialization block for edge " << entry->GetBlockId() << "->"
+                           << entry->GetPredecessors()[pred_num]->GetBlockId();
+    return out;
+  }
+
+  IterationRange<ArenaVector<HBasicBlock*>::const_iterator> IterateMaterializationBlocks() {
+    return MakeIterationRange(GetGraph()->GetBlocks().begin() + first_materialization_block_id_,
+                              GetGraph()->GetBlocks().end());
+  }
+
+  void FixupPartialObjectUsers() {
+    for (PartialLoadStoreEliminationHelper::HeapReferenceData& ref_data : GetHeapRefs()) {
+      // Use the materialized instances to replace original instance
+      ref_data.FixupUses(/*first_pass=*/true);
+      CHECK(ref_data.OriginalNewInstance()->GetUses().empty())
+          << ref_data.OriginalNewInstance()->GetUses() << ", "
+          << ref_data.OriginalNewInstance()->GetEnvUses();
+    }
+    // This can cause new uses to be created due to the creation of phis/pred-get defaults
+    for (PartialLoadStoreEliminationHelper::HeapReferenceData& ref_data : GetHeapRefs()) {
+      // Only need to handle new phis/pred-get defaults. DCHECK that's all we find.
+      ref_data.FixupUses(/*first_pass=*/false);
+      CHECK(ref_data.OriginalNewInstance()->GetUses().empty())
+          << ref_data.OriginalNewInstance()->GetUses() << ", "
+          << ref_data.OriginalNewInstance()->GetEnvUses();
+    }
+  }
+
+  // Finds the first block which either is or dominates the given block which is
+  // not a materialization block
+  HBasicBlock* FindDominatingNonMaterializationBlock(HBasicBlock* blk) {
+    if (LIKELY(!IsMaterializationBlock(blk))) {
+      // Not a materialization block so itself.
+      return blk;
+    } else if (blk->GetNumberOfPredecessors() != 0) {
+      // We're far enough along that the materialization blocks have been
+      // inserted into the graph so no need to go searching.
+      return blk->GetSinglePredecessor();
+    }
+    // Search through the materialization blocks to find where it will be
+    // inserted.
+    for (auto [mat, idx] : ZipCount(MakeIterationRange(materialization_blocks_))) {
+      if (mat == blk) {
+        size_t cur_pred_idx = idx % max_preds_per_block_;
+        HBasicBlock* entry = GetGraph()->GetBlocks()[idx / max_preds_per_block_];
+        return entry->GetPredecessors()[cur_pred_idx];
+      }
+    }
+    LOG(FATAL) << "Unable to find materialization block position for " << blk->GetBlockId() << "!";
+    return nullptr;
+  }
+
+  void InsertMaterializationBlocks() {
+    for (auto [mat, idx] : ZipCount(MakeIterationRange(materialization_blocks_))) {
+      if (mat == nullptr) {
+        continue;
+      }
+      size_t cur_pred_idx = idx % max_preds_per_block_;
+      HBasicBlock* entry = GetGraph()->GetBlocks()[idx / max_preds_per_block_];
+      HBasicBlock* pred = entry->GetPredecessors()[cur_pred_idx];
+      mat->InsertBetween(pred, entry);
+      LSE_VLOG << "Adding materialization block " << mat->GetBlockId() << " on edge "
+               << pred->GetBlockId() << "->" << entry->GetBlockId();
+    }
+  }
+
+  // Replace any env-uses remaining of the partial singletons with the
+  // appropriate phis and remove the instructions.
+  void RemoveReplacedInstructions() {
+    for (HeapReferenceData& ref_data : GetHeapRefs()) {
+      CHECK(ref_data.OriginalNewInstance()->GetUses().empty())
+          << ref_data.OriginalNewInstance()->GetUses() << ", "
+          << ref_data.OriginalNewInstance()->GetEnvUses()
+          << " inst is: " << ref_data.OriginalNewInstance();
+      const auto& env_uses = ref_data.OriginalNewInstance()->GetEnvUses();
+      while (!env_uses.empty()) {
+        const HUseListNode<HEnvironment*>& use = env_uses.front();
+        HInstruction* merged_inst =
+            ref_data.GetMaterialization(use.GetUser()->GetHolder()->GetBlock());
+        LSE_VLOG << "Replacing env use of " << *use.GetUser()->GetHolder() << "@" << use.GetIndex()
+                 << " with " << *merged_inst;
+        use.GetUser()->ReplaceInput(merged_inst, use.GetIndex());
+      }
+      ref_data.OriginalNewInstance()->GetBlock()->RemoveInstruction(ref_data.OriginalNewInstance());
+    }
+  }
+
+  // We need to make sure any allocations dominate their environment uses.
+  // Technically we could probably remove the env-uses and be fine but this is easy.
+  void ReorderMaterializationsForEnvDominance() {
+    for (HBasicBlock* blk : IterateMaterializationBlocks()) {
+      ScopedArenaAllocator alloc(alloc_->GetArenaStack());
+      ArenaBitVector still_unsorted(
+          &alloc, GetGraph()->GetCurrentInstructionId(), false, kArenaAllocLSE);
+      // This is guaranteed to be very short (since we will abandon LSE if there
+      // are >= kMaxNumberOfHeapLocations (32) heap locations so that is the
+      // absolute maximum size this list can be) so doing a selection sort is
+      // fine. This avoids the need to do a complicated recursive check to
+      // ensure transitivity for std::sort.
+      ScopedArenaVector<HNewInstance*> materializations(alloc.Adapter(kArenaAllocLSE));
+      materializations.reserve(GetHeapRefs().size());
+      for (HInstruction* ins :
+           MakeSTLInstructionIteratorRange(HInstructionIterator(blk->GetInstructions()))) {
+        if (ins->IsNewInstance()) {
+          materializations.push_back(ins->AsNewInstance());
+          still_unsorted.SetBit(ins->GetId());
+        }
+      }
+      using Iter = ScopedArenaVector<HNewInstance*>::iterator;
+      Iter unsorted_start = materializations.begin();
+      Iter unsorted_end = materializations.end();
+      // selection sort. Required since the only check we can easily perform a
+      // is-before-all-unsorted check.
+      while (unsorted_start != unsorted_end) {
+        bool found_instruction = false;
+        for (Iter candidate = unsorted_start; candidate != unsorted_end; ++candidate) {
+          HNewInstance* ni = *candidate;
+          if (std::none_of(ni->GetAllEnvironments().cbegin(),
+                           ni->GetAllEnvironments().cend(),
+                           [&](const HEnvironment* env) {
+                             return std::any_of(
+                                 env->GetEnvInputs().cbegin(),
+                                 env->GetEnvInputs().cend(),
+                                 [&](const HInstruction* env_element) {
+                                   return env_element != nullptr &&
+                                          still_unsorted.IsBitSet(env_element->GetId());
+                                 });
+                           })) {
+            still_unsorted.ClearBit(ni->GetId());
+            std::swap(*unsorted_start, *candidate);
+            ++unsorted_start;
+            found_instruction = true;
+            break;
+          }
+        }
+        CHECK(found_instruction) << "Unable to select next materialization instruction."
+                                 << " Environments have a dependency loop!";
+      }
+      // Reverse so we as we prepend them we end up with the correct order.
+      auto reverse_iter = MakeIterationRange(materializations.rbegin(), materializations.rend());
+      for (HNewInstance* ins : reverse_iter) {
+        if (blk->GetFirstInstruction() != ins) {
+          // Don't do checks since that makes sure the move is safe WRT
+          // ins->CanBeMoved which for NewInstance is false.
+          ins->MoveBefore(blk->GetFirstInstruction(), /*do_checks=*/false);
+        }
+      }
+    }
+  }
+
+ private:
+  void CollectInterestingHeapRefs() {
+    // Get all the partials we need to move around.
+    for (size_t i = 0; i < lse_->heap_location_collector_.GetNumberOfHeapLocations(); ++i) {
+      ReferenceInfo* ri = lse_->heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo();
+      if (ri->IsPartialSingleton() &&
+          ri->GetReference()->GetBlock() != nullptr &&
+          ri->GetNoEscapeSubgraph()->ContainsBlock(ri->GetReference()->GetBlock())) {
+        RecordHeapRefField(ri->GetReference()->AsNewInstance(), i);
+      }
+    }
+  }
+
+  void RecordHeapRefField(HNewInstance* ni, size_t loc) {
+    DCHECK(ni != nullptr);
+    // This is likely to be very short so just do a linear search.
+    auto it = std::find_if(heap_refs_.begin(), heap_refs_.end(), [&](HeapReferenceData& data) {
+      return data.OriginalNewInstance() == ni;
+    });
+    HeapReferenceData& cur_ref =
+        (it == heap_refs_.end())
+            ? heap_refs_.emplace_back(this,
+                                      ni,
+                                      lse_->heap_location_collector_.GetHeapLocation(loc)
+                                          ->GetReferenceInfo()
+                                          ->GetNoEscapeSubgraph(),
+                                      alloc_)
+            : *it;
+    cur_ref.AddHeapLocation(loc);
+  }
+
+
+  void NotifyNewMaterialization(HInstruction* ins) {
+    if (ins->IsPhi()) {
+      new_ref_phis_.push_back(ins->AsPhi());
+    }
+  }
+
+  size_t GetMaterializationBlockIndex(HBasicBlock* blk, size_t pred_num) const {
+    DCHECK_LT(blk->GetBlockId(), first_materialization_block_id_)
+        << "block is a materialization block!";
+    DCHECK_LT(pred_num, max_preds_per_block_);
+    return blk->GetBlockId() * max_preds_per_block_ + pred_num;
+  }
+
+  HGraph* GetGraph() const {
+    return lse_->GetGraph();
+  }
+
+  LSEVisitor* lse_;
+  ScopedArenaAllocator* alloc_;
+  ScopedArenaVector<HInstruction*> new_ref_phis_;
+  ScopedArenaVector<HeapReferenceData> heap_refs_;
+  size_t max_preds_per_block_;
+  // An array of (# of non-materialization blocks) * max_preds_per_block
+  // arranged in block-id major order. Since we can only have at most one
+  // materialization block on each edge this is the maximum possible number of
+  // materialization blocks.
+  ScopedArenaVector<HBasicBlock*> materialization_blocks_;
+  size_t first_materialization_block_id_;
+
+  friend void LSEVisitor::MovePartialEscapes();
+};
+
+// Work around c++ type checking annoyances with not being able to forward-declare inner types.
+class HeapRefHolder
+    : public std::reference_wrapper<PartialLoadStoreEliminationHelper::HeapReferenceData> {};
+
+HInstruction* LSEVisitor::SetupPartialMaterialization(PartialLoadStoreEliminationHelper& helper,
+                                                      HeapRefHolder&& holder,
+                                                      size_t pred_idx,
+                                                      HBasicBlock* entry) {
+  PartialLoadStoreEliminationHelper::HeapReferenceData& ref_data = holder.get();
+  HBasicBlock* old_pred = entry->GetPredecessors()[pred_idx];
+  HInstruction* new_inst = ref_data.OriginalNewInstance();
+  if (UNLIKELY(!new_inst->GetBlock()->Dominates(entry))) {
+    LSE_VLOG << "Initial materialization in non-dominating block " << entry->GetBlockId()
+             << " is null!";
+    return GetGraph()->GetNullConstant();
+  }
+  HBasicBlock* bb = helper.GetOrCreateMaterializationBlock(entry, pred_idx);
+  CHECK(bb != nullptr) << "entry " << entry->GetBlockId() << " -> " << old_pred->GetBlockId();
+  HNewInstance* repl_create = new_inst->Clone(GetGraph()->GetAllocator())->AsNewInstance();
+  repl_create->SetPartialMaterialization();
+  bb->InsertInstructionBefore(repl_create, bb->GetLastInstruction());
+  repl_create->CopyEnvironmentFrom(new_inst->GetEnvironment());
+  MaybeRecordStat(stats_, MethodCompilationStat::kPartialAllocationMoved);
+  LSE_VLOG << "In blk " << bb->GetBlockId() << " initial materialization is " << *repl_create;
+  ref_data.AddMaterialization(bb, repl_create);
+  const FieldInfo* info = nullptr;
+  for (const HeapLocation* loc : ref_data.IterateLocations()) {
+    size_t loc_off = heap_location_collector_.GetHeapLocationIndex(loc);
+    info = field_infos_[loc_off];
+    DCHECK(loc->GetIndex() == nullptr);
+    Value value = ReplacementOrValue(heap_values_for_[old_pred->GetBlockId()][loc_off].value);
+    if (value.NeedsLoopPhi() || value.IsMergedUnknown()) {
+      Value repl = phi_placeholder_replacements_[PhiPlaceholderIndex(value.GetPhiPlaceholder())];
+      DCHECK(repl.IsDefault() || repl.IsInvalid() || repl.IsInstruction())
+          << repl << " from " << value << " pred is " << old_pred->GetBlockId();
+      if (!repl.IsInvalid()) {
+        value = repl;
+      } else {
+        FullyMaterializePhi(value.GetPhiPlaceholder(), info->GetFieldType());
+        value = phi_placeholder_replacements_[PhiPlaceholderIndex(value.GetPhiPlaceholder())];
+      }
+    } else if (value.NeedsNonLoopPhi()) {
+      Value repl = phi_placeholder_replacements_[PhiPlaceholderIndex(value.GetPhiPlaceholder())];
+      DCHECK(repl.IsDefault() || repl.IsInvalid() || repl.IsInstruction())
+          << repl << " from " << value << " pred is " << old_pred->GetBlockId();
+      if (!repl.IsInvalid()) {
+        value = repl;
+      } else {
+        MaterializeNonLoopPhis(value.GetPhiPlaceholder(), info->GetFieldType());
+        value = phi_placeholder_replacements_[PhiPlaceholderIndex(value.GetPhiPlaceholder())];
+      }
+    }
+    DCHECK(value.IsDefault() || value.IsInstruction())
+        << GetGraph()->PrettyMethod() << ": " << value;
+
+    if (!value.IsDefault() &&
+        // shadow$_klass_ doesn't need to be manually initialized.
+        MemberOffset(loc->GetOffset()) != mirror::Object::ClassOffset()) {
+      CHECK(info != nullptr);
+      HInstruction* set_value =
+          new (GetGraph()->GetAllocator()) HInstanceFieldSet(repl_create,
+                                                             value.GetInstruction(),
+                                                             field_infos_[loc_off]->GetField(),
+                                                             loc->GetType(),
+                                                             MemberOffset(loc->GetOffset()),
+                                                             false,
+                                                             field_infos_[loc_off]->GetFieldIndex(),
+                                                             loc->GetDeclaringClassDefIndex(),
+                                                             field_infos_[loc_off]->GetDexFile(),
+                                                             0u);
+      bb->InsertInstructionAfter(set_value, repl_create);
+      LSE_VLOG << "Adding " << *set_value << " for materialization setup!";
+    }
+  }
+  return repl_create;
+}
+
+HInstruction* LSEVisitor::GetPartialValueAt(HNewInstance* orig_new_inst, HInstruction* read) {
+  size_t loc = heap_location_collector_.GetFieldHeapLocation(orig_new_inst, &read->GetFieldInfo());
+  Value pred = ReplacementOrValue(intermediate_values_.find(read)->second);
+  LSE_VLOG << "using " << pred << " as default value for " << *read;
+  if (pred.IsInstruction()) {
+    return pred.GetInstruction();
+  } else if (pred.IsMergedUnknown() || pred.NeedsPhi()) {
+    FullyMaterializePhi(pred.GetPhiPlaceholder(),
+                        heap_location_collector_.GetHeapLocation(loc)->GetType());
+    HInstruction* res = Replacement(pred).GetInstruction();
+    LSE_VLOG << pred << " materialized to " << res->DumpWithArgs();
+    return res;
+  } else if (pred.IsDefault()) {
+    HInstruction* res = GetDefaultValue(read->GetType());
+    LSE_VLOG << pred << " materialized to " << res->DumpWithArgs();
+    return res;
+  }
+  LOG(FATAL) << "Unable to find unescaped value at " << read->DumpWithArgs()
+             << "! This should be impossible! Value is " << pred;
+  UNREACHABLE();
+}
+
+void LSEVisitor::MovePartialEscapes() {
+  if (!ShouldPerformPartialLSE()) {
+    return;
+  }
+
+  ScopedArenaAllocator saa(allocator_.GetArenaStack());
+  PartialLoadStoreEliminationHelper helper(this, &saa);
+
+  // Since for PHIs we now will have more information (since we know the object
+  // hasn't escaped) we need to clear the old phi-replacements where we weren't
+  // able to find the value.
+  PrepareForPartialPhiComputation();
+
+  for (PartialLoadStoreEliminationHelper::HeapReferenceData& ref_data : helper.GetHeapRefs()) {
+    LSE_VLOG << "Creating materializations for " << *ref_data.OriginalNewInstance();
+    // Setup entry and exit blocks.
+    for (const auto& excluded_cohort : ref_data.GetNoEscapeSubgraph()->GetExcludedCohorts()) {
+      // Setup materialization blocks.
+      for (HBasicBlock* entry : excluded_cohort.EntryBlocksReversePostOrder()) {
+        // Setup entries.
+        // TODO Assuming we correctly break critical edges every entry block
+        // must have only a single predecessor so we could just put all this
+        // stuff in there. OTOH simplifier can do it for us and this is simpler
+        // to implement - giving clean separation between the original graph and
+        // materialization blocks - so for now we might as well have these new
+        // blocks.
+        ScopedArenaAllocator pred_alloc(saa.GetArenaStack());
+        ScopedArenaVector<HInstruction*> pred_vals(pred_alloc.Adapter(kArenaAllocLSE));
+        pred_vals.reserve(entry->GetNumberOfPredecessors());
+        for (const auto& [pred, pred_idx] :
+             ZipCount(MakeIterationRange(entry->GetPredecessors()))) {
+          DCHECK(!helper.IsMaterializationBlock(pred));
+          if (excluded_cohort.IsEntryBlock(pred)) {
+            pred_vals.push_back(ref_data.GetMaterialization(pred));
+            continue;
+          } else {
+            pred_vals.push_back(SetupPartialMaterialization(helper, {ref_data}, pred_idx, entry));
+          }
+        }
+        ref_data.GenerateMaterializationValueFromPredecessorsForEntry(entry, pred_vals);
+      }
+
+      // Setup exit block heap-values for later phi-generation.
+      for (HBasicBlock* exit : excluded_cohort.ExitBlocks()) {
+        // mark every exit of cohorts as having a value so we can easily
+        // materialize the PHIs.
+        // TODO By setting this we can easily use the normal MaterializeLoopPhis
+        //      (via FullyMaterializePhis) in order to generate the default-values
+        //      for predicated-gets. This has the unfortunate side effect of creating
+        //      somewhat more phis than are really needed (in some cases). We really
+        //      should try to eventually know that we can lower these PHIs to only
+        //      the non-escaping value in cases where it is possible. Currently this
+        //      is done to some extent in instruction_simplifier but we have more
+        //      information here to do the right thing.
+        for (const HeapLocation* loc : ref_data.IterateLocations()) {
+          size_t loc_off = heap_location_collector_.GetHeapLocationIndex(loc);
+          // This Value::Default() is only used to fill in PHIs used as the
+          // default value for PredicatedInstanceFieldGets. The actual value
+          // stored there is meaningless since the Predicated-iget will use the
+          // actual field value instead on these paths.
+          heap_values_for_[exit->GetBlockId()][loc_off].value = Value::Default();
+        }
+      }
+    }
+
+    // string materialization through the graph.
+    // // Visit RPO to PHI the materialized object through the cohort.
+    for (HBasicBlock* blk : GetGraph()->GetReversePostOrder()) {
+      // NB This doesn't include materialization blocks.
+      DCHECK(!helper.IsMaterializationBlock(blk))
+          << "Materialization blocks should not be in RPO yet.";
+      if (ref_data.HasMaterialization(blk)) {
+        continue;
+      } else if (ref_data.BeforeAllEscapes(blk)) {
+        ref_data.AddMaterialization(blk, GetGraph()->GetNullConstant());
+        continue;
+      } else {
+        ref_data.GenerateMaterializationValueFromPredecessors(blk);
+      }
+    }
+  }
+
+  // Once we've generated all the materializations we can update the users.
+  helper.FixupPartialObjectUsers();
+
+  // Actually put materialization blocks into the graph
+  helper.InsertMaterializationBlocks();
+
+  // Get rid of the original instructions.
+  helper.RemoveReplacedInstructions();
+
+  // Ensure everything is ordered correctly in the materialization blocks. This
+  // involves moving every NewInstance to the top and ordering them so that any
+  // required env-uses are correctly ordered.
+  helper.ReorderMaterializationsForEnvDominance();
+}
+
+void LSEVisitor::FinishFullLSE() {
+  // Remove recorded load instructions that should be eliminated.
+  for (const LoadStoreRecord& record : loads_and_stores_) {
+    size_t id = dchecked_integral_cast<size_t>(record.load_or_store->GetId());
+    HInstruction* substitute = substitute_instructions_for_loads_[id];
+    if (substitute == nullptr) {
+      continue;
+    }
+    HInstruction* load = record.load_or_store;
+    DCHECK(load != nullptr);
+    DCHECK(IsLoad(load));
+    DCHECK(load->GetBlock() != nullptr) << load->DebugName() << "@" << load->GetDexPc();
+    // We proactively retrieve the substitute for a removed load, so
+    // a load that has a substitute should not be observed as a heap
+    // location value.
+    DCHECK_EQ(FindSubstitute(substitute), substitute);
+
+    load->ReplaceWith(substitute);
+    load->GetBlock()->RemoveInstruction(load);
+  }
+
+  // Remove all the stores we can.
+  for (const LoadStoreRecord& record : loads_and_stores_) {
+    bool is_store = record.load_or_store->GetSideEffects().DoesAnyWrite();
+    DCHECK_EQ(is_store, IsStore(record.load_or_store));
+    if (is_store && !kept_stores_.IsBitSet(record.load_or_store->GetId())) {
+      record.load_or_store->GetBlock()->RemoveInstruction(record.load_or_store);
+    }
+  }
+
+  // Eliminate singleton-classified instructions:
+  //   * - Constructor fences (they never escape this thread).
+  //   * - Allocations (if they are unused).
+  for (HInstruction* new_instance : singleton_new_instances_) {
+    size_t removed = HConstructorFence::RemoveConstructorFences(new_instance);
+    MaybeRecordStat(stats_,
+                    MethodCompilationStat::kConstructorFenceRemovedLSE,
+                    removed);
+
+    if (!new_instance->HasNonEnvironmentUses()) {
+      new_instance->RemoveEnvironmentUsers();
+      new_instance->GetBlock()->RemoveInstruction(new_instance);
+      MaybeRecordStat(stats_, MethodCompilationStat::kFullLSEAllocationRemoved);
+    }
+  }
+}
+
+// The LSEVisitor is a ValueObject (indirectly through base classes) and therefore
+// cannot be directly allocated with an arena allocator, so we need to wrap it.
+class LSEVisitorWrapper : public DeletableArenaObject<kArenaAllocLSE> {
+ public:
+  LSEVisitorWrapper(HGraph* graph,
+                    const HeapLocationCollector& heap_location_collector,
+                    bool perform_partial_lse,
+                    OptimizingCompilerStats* stats)
+      : lse_visitor_(graph, heap_location_collector, perform_partial_lse, stats) {}
+
+  void Run() {
+    lse_visitor_.Run();
+  }
+
+ private:
+  LSEVisitor lse_visitor_;
+};
+
+bool LoadStoreElimination::Run(bool enable_partial_lse) {
   if (graph_->IsDebuggable() || graph_->HasTryCatch()) {
     // Debugger may set heap values or trigger deoptimization of callers.
     // Try/catch support not implemented yet.
     // Skip this optimization.
     return false;
   }
-  const HeapLocationCollector& heap_location_collector = lsa_.GetHeapLocationCollector();
+  // We need to be able to determine reachability. Clear it just to be safe but
+  // this should initially be empty.
+  graph_->ClearReachabilityInformation();
+  // This is O(blocks^3) time complexity. It means we can query reachability in
+  // O(1) though.
+  graph_->ComputeReachabilityInformation();
+  ScopedArenaAllocator allocator(graph_->GetArenaStack());
+  LoadStoreAnalysis lsa(graph_,
+                        stats_,
+                        &allocator,
+                        enable_partial_lse ? LoadStoreAnalysisType::kFull
+                                           : LoadStoreAnalysisType::kNoPredicatedInstructions);
+  lsa.Run();
+  const HeapLocationCollector& heap_location_collector = lsa.GetHeapLocationCollector();
   if (heap_location_collector.GetNumberOfHeapLocations() == 0) {
     // No HeapLocation information from LSA, skip this optimization.
     return false;
   }
 
-  LSEVisitor lse_visitor(graph_, heap_location_collector, side_effects_, stats_);
-  for (HBasicBlock* block : graph_->GetReversePostOrder()) {
-    lse_visitor.VisitBasicBlock(block);
-  }
-  lse_visitor.RemoveInstructions();
-
+  std::unique_ptr<LSEVisitorWrapper> lse_visitor(new (&allocator) LSEVisitorWrapper(
+      graph_, heap_location_collector, enable_partial_lse, stats_));
+  lse_visitor->Run();
   return true;
 }
 
+#undef LSE_VLOG
+
 }  // namespace art
diff --git a/compiler/optimizing/load_store_elimination.h b/compiler/optimizing/load_store_elimination.h
index f7ba41a..e73ef5e 100644
--- a/compiler/optimizing/load_store_elimination.h
+++ b/compiler/optimizing/load_store_elimination.h
@@ -22,27 +22,31 @@
 namespace art {
 
 class SideEffectsAnalysis;
-class LoadStoreAnalysis;
 
 class LoadStoreElimination : public HOptimization {
  public:
+  // Whether or not we should attempt partial Load-store-elimination which
+  // requires additional blocks and predicated instructions.
+  static constexpr bool kEnablePartialLSE = true;
+
+  // Controls whether to enable VLOG(compiler) logs explaining the transforms taking place.
+  static constexpr bool kVerboseLoggingMode = false;
+
   LoadStoreElimination(HGraph* graph,
-                       const SideEffectsAnalysis& side_effects,
-                       const LoadStoreAnalysis& lsa,
                        OptimizingCompilerStats* stats,
                        const char* name = kLoadStoreEliminationPassName)
-      : HOptimization(graph, name, stats),
-        side_effects_(side_effects),
-        lsa_(lsa) {}
+      : HOptimization(graph, name, stats) {}
 
-  bool Run() override;
+  bool Run() override {
+    return Run(kEnablePartialLSE);
+  }
+
+  // Exposed for testing.
+  bool Run(bool enable_partial_lse);
 
   static constexpr const char* kLoadStoreEliminationPassName = "load_store_elimination";
 
  private:
-  const SideEffectsAnalysis& side_effects_;
-  const LoadStoreAnalysis& lsa_;
-
   DISALLOW_COPY_AND_ASSIGN(LoadStoreElimination);
 };
 
diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc
index 7380378..812a32a 100644
--- a/compiler/optimizing/load_store_elimination_test.cc
+++ b/compiler/optimizing/load_store_elimination_test.cc
@@ -14,29 +14,64 @@
  * limitations under the License.
  */
 
-#include <tuple>
-
-#include "load_store_analysis.h"
 #include "load_store_elimination.h"
-#include "nodes.h"
-#include "optimizing_unit_test.h"
-#include "side_effects_analysis.h"
 
+#include <initializer_list>
+#include <memory>
+#include <tuple>
+#include <variant>
+
+#include "base/iteration_range.h"
+#include "compilation_kind.h"
+#include "dex/dex_file_types.h"
+#include "entrypoints/quick/quick_entrypoints.h"
+#include "entrypoints/quick/quick_entrypoints_enum.h"
 #include "gtest/gtest.h"
+#include "handle_scope.h"
+#include "load_store_analysis.h"
+#include "nodes.h"
+#include "optimizing/data_type.h"
+#include "optimizing/instruction_simplifier.h"
+#include "optimizing/optimizing_compiler_stats.h"
+#include "optimizing_unit_test.h"
+#include "scoped_thread_state_change.h"
 
 namespace art {
 
-class LoadStoreEliminationTest : public ImprovedOptimizingUnitTest {
+#define CHECK_SUBROUTINE_FAILURE() \
+  do {                             \
+    if (HasFatalFailure()) {       \
+      return;                      \
+    }                              \
+  } while (false)
+
+template <typename SuperTest>
+class LoadStoreEliminationTestBase : public SuperTest, public OptimizingUnitTestHelper {
  public:
-  void PerformLSE() {
+  void SetUp() override {
+    SuperTest::SetUp();
+    gLogVerbosity.compiler = true;
+  }
+
+  void TearDown() override {
+    SuperTest::TearDown();
+    gLogVerbosity.compiler = false;
+  }
+
+  void PerformLSE(bool with_partial = true) {
     graph_->BuildDominatorTree();
-    SideEffectsAnalysis side_effects(graph_);
-    side_effects.Run();
-    LoadStoreAnalysis lsa(graph_);
-    lsa.Run();
-    LoadStoreElimination lse(graph_, side_effects, lsa, nullptr);
-    lse.Run();
-    EXPECT_TRUE(CheckGraphSkipRefTypeInfoChecks());
+    LoadStoreElimination lse(graph_, /*stats=*/nullptr);
+    lse.Run(with_partial);
+    std::ostringstream oss;
+    EXPECT_TRUE(CheckGraphSkipRefTypeInfoChecks(oss)) << oss.str();
+  }
+
+  void PerformLSEWithPartial() {
+    PerformLSE(true);
+  }
+
+  void PerformLSENoPartial() {
+    PerformLSE(false);
   }
 
   // Create instructions shared among tests.
@@ -61,11 +96,9 @@
   //      |
   //     exit
   void CreateTestControlFlowGraph() {
-    pre_header_ = new (GetAllocator()) HBasicBlock(graph_);
-    loop_ = new (GetAllocator()) HBasicBlock(graph_);
-
-    graph_->AddBlock(pre_header_);
-    graph_->AddBlock(loop_);
+    InitGraphAndParameters();
+    pre_header_ = AddNewBlock();
+    loop_ = AddNewBlock();
 
     entry_block_->ReplaceSuccessor(return_block_, pre_header_);
     pre_header_->AddSuccessor(loop_);
@@ -103,9 +136,7 @@
   }
 
   void CreateEnvForSuspendCheck() {
-    ArenaVector<HInstruction*> current_locals({array_, i_, j_},
-                                              GetAllocator()->Adapter(kArenaAllocInstruction));
-    ManuallyBuildEnvFor(suspend_check_, &current_locals);
+    ManuallyBuildEnvFor(suspend_check_, {array_, i_, j_});
   }
 
   // Create the diamond-shaped CFG:
@@ -117,15 +148,12 @@
   //
   // Return: the basic blocks forming the CFG in the following order {upper, left, right, down}.
   std::tuple<HBasicBlock*, HBasicBlock*, HBasicBlock*, HBasicBlock*> CreateDiamondShapedCFG() {
+    InitGraphAndParameters();
     CreateEntryBlockInstructions();
 
-    HBasicBlock* upper = new (GetAllocator()) HBasicBlock(graph_);
-    HBasicBlock* left = new (GetAllocator()) HBasicBlock(graph_);
-    HBasicBlock* right = new (GetAllocator()) HBasicBlock(graph_);
-
-    graph_->AddBlock(upper);
-    graph_->AddBlock(left);
-    graph_->AddBlock(right);
+    HBasicBlock* upper = AddNewBlock();
+    HBasicBlock* left = AddNewBlock();
+    HBasicBlock* right = AddNewBlock();
 
     entry_block_->ReplaceSuccessor(return_block_, upper);
     upper->AddSuccessor(left);
@@ -151,15 +179,15 @@
     DCHECK(block != nullptr);
     DCHECK(array != nullptr);
     DCHECK(index != nullptr);
-    HInstruction* vload = new (GetAllocator()) HVecLoad(
-        GetAllocator(),
-        array,
-        index,
-        DataType::Type::kInt32,
-        SideEffects::ArrayReadOfType(DataType::Type::kInt32),
-        4,
-        /*is_string_char_at*/ false,
-        kNoDexPc);
+    HInstruction* vload =
+        new (GetAllocator()) HVecLoad(GetAllocator(),
+                                      array,
+                                      index,
+                                      DataType::Type::kInt32,
+                                      SideEffects::ArrayReadOfType(DataType::Type::kInt32),
+                                      4,
+                                      /*is_string_char_at*/ false,
+                                      kNoDexPc);
     block->InsertInstructionBefore(vload, block->GetLastInstruction());
     return vload;
   }
@@ -177,22 +205,19 @@
     DCHECK(index != nullptr);
     if (vdata == nullptr) {
       HInstruction* c1 = graph_->GetIntConstant(1);
-      vdata = new (GetAllocator()) HVecReplicateScalar(GetAllocator(),
-                                                       c1,
-                                                       DataType::Type::kInt32,
-                                                       4,
-                                                       kNoDexPc);
+      vdata = new (GetAllocator())
+          HVecReplicateScalar(GetAllocator(), c1, DataType::Type::kInt32, 4, kNoDexPc);
       block->InsertInstructionBefore(vdata, block->GetLastInstruction());
     }
-    HInstruction* vstore = new (GetAllocator()) HVecStore(
-        GetAllocator(),
-        array,
-        index,
-        vdata,
-        DataType::Type::kInt32,
-        SideEffects::ArrayWriteOfType(DataType::Type::kInt32),
-        4,
-        kNoDexPc);
+    HInstruction* vstore =
+        new (GetAllocator()) HVecStore(GetAllocator(),
+                                       array,
+                                       index,
+                                       vdata,
+                                       DataType::Type::kInt32,
+                                       SideEffects::ArrayWriteOfType(DataType::Type::kInt32),
+                                       4,
+                                       kNoDexPc);
     block->InsertInstructionBefore(vstore, block->GetLastInstruction());
     return vstore;
   }
@@ -223,30 +248,22 @@
     if (data == nullptr) {
       data = graph_->GetIntConstant(1);
     }
-    HInstruction* store = new (GetAllocator()) HArraySet(array,
-                                                         index,
-                                                         data,
-                                                         DataType::Type::kInt32,
-                                                         0);
+    HInstruction* store =
+        new (GetAllocator()) HArraySet(array, index, data, DataType::Type::kInt32, 0);
     block->InsertInstructionBefore(store, block->GetLastInstruction());
     return store;
   }
 
-  void CreateParameters() override {
-    parameters_.push_back(new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
-                                                               dex::TypeIndex(0),
-                                                               0,
-                                                               DataType::Type::kInt32));
+  void InitGraphAndParameters() {
+    InitGraph();
+    AddParameter(new (GetAllocator()) HParameterValue(
+        graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32));
     array_ = parameters_.back();
-    parameters_.push_back(new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
-                                                               dex::TypeIndex(1),
-                                                               1,
-                                                               DataType::Type::kInt32));
+    AddParameter(new (GetAllocator()) HParameterValue(
+        graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kInt32));
     i_ = parameters_.back();
-    parameters_.push_back(new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
-                                                               dex::TypeIndex(1),
-                                                               2,
-                                                               DataType::Type::kInt32));
+    AddParameter(new (GetAllocator()) HParameterValue(
+        graph_->GetDexFile(), dex::TypeIndex(1), 2, DataType::Type::kInt32));
     j_ = parameters_.back();
   }
 
@@ -263,8 +280,203 @@
   HPhi* phi_;
 };
 
+class LoadStoreEliminationTest : public LoadStoreEliminationTestBase<CommonCompilerTest> {};
+
+enum class TestOrder { kSameAsAlloc, kReverseOfAlloc };
+std::ostream& operator<<(std::ostream& os, const TestOrder& ord) {
+  switch (ord) {
+    case TestOrder::kSameAsAlloc:
+      return os << "SameAsAlloc";
+    case TestOrder::kReverseOfAlloc:
+      return os << "ReverseOfAlloc";
+  }
+}
+
+class OrderDependentTestGroup
+    : public LoadStoreEliminationTestBase<CommonCompilerTestWithParam<TestOrder>> {};
+
+// Various configs we can use for testing. Currently used in PartialComparison tests.
+struct PartialComparisonKind {
+ public:
+  enum class Type : uint8_t { kEquals, kNotEquals };
+  enum class Target : uint8_t { kNull, kValue, kSelf };
+  enum class Position : uint8_t { kLeft, kRight };
+
+  const Type type_;
+  const Target target_;
+  const Position position_;
+
+  bool IsDefinitelyFalse() const {
+    return !IsPossiblyTrue();
+  }
+  bool IsPossiblyFalse() const {
+    return !IsDefinitelyTrue();
+  }
+  bool IsDefinitelyTrue() const {
+    if (target_ == Target::kSelf) {
+      return type_ == Type::kEquals;
+    } else if (target_ == Target::kNull) {
+      return type_ == Type::kNotEquals;
+    } else {
+      return false;
+    }
+  }
+  bool IsPossiblyTrue() const {
+    if (target_ == Target::kSelf) {
+      return type_ == Type::kEquals;
+    } else if (target_ == Target::kNull) {
+      return type_ == Type::kNotEquals;
+    } else {
+      return true;
+    }
+  }
+  std::ostream& Dump(std::ostream& os) const {
+    os << "PartialComparisonKind{" << (type_ == Type::kEquals ? "kEquals" : "kNotEquals") << ", "
+       << (target_ == Target::kNull ? "kNull" : (target_ == Target::kSelf ? "kSelf" : "kValue"))
+       << ", " << (position_ == Position::kLeft ? "kLeft" : "kRight") << "}";
+    return os;
+  }
+};
+
+std::ostream& operator<<(std::ostream& os, const PartialComparisonKind& comp) {
+  return comp.Dump(os);
+}
+
+class PartialComparisonTestGroup
+    : public LoadStoreEliminationTestBase<CommonCompilerTestWithParam<PartialComparisonKind>> {
+ public:
+  enum class ComparisonPlacement {
+    kBeforeEscape,
+    kInEscape,
+    kAfterEscape,
+  };
+  void CheckFinalInstruction(HInstruction* ins, ComparisonPlacement placement) {
+    using Target = PartialComparisonKind::Target;
+    using Type = PartialComparisonKind::Type;
+    using Position = PartialComparisonKind::Position;
+    PartialComparisonKind kind = GetParam();
+    if (ins->IsIntConstant()) {
+      if (kind.IsDefinitelyTrue()) {
+        EXPECT_TRUE(ins->AsIntConstant()->IsTrue()) << kind << " " << *ins;
+      } else if (kind.IsDefinitelyFalse()) {
+        EXPECT_TRUE(ins->AsIntConstant()->IsFalse()) << kind << " " << *ins;
+      } else {
+        EXPECT_EQ(placement, ComparisonPlacement::kBeforeEscape);
+        EXPECT_EQ(kind.target_, Target::kValue);
+        // We are before escape so value is not the object
+        if (kind.type_ == Type::kEquals) {
+          EXPECT_TRUE(ins->AsIntConstant()->IsFalse()) << kind << " " << *ins;
+        } else {
+          EXPECT_TRUE(ins->AsIntConstant()->IsTrue()) << kind << " " << *ins;
+        }
+      }
+      return;
+    }
+    EXPECT_NE(placement, ComparisonPlacement::kBeforeEscape)
+        << "For comparisons before escape we should always be able to transform into a constant."
+        << " Instead we got:" << std::endl << ins->DumpWithArgs();
+    if (placement == ComparisonPlacement::kInEscape) {
+      // Should be the same type.
+      ASSERT_TRUE(ins->IsEqual() || ins->IsNotEqual()) << *ins;
+      HInstruction* other = kind.position_ == Position::kLeft ? ins->AsBinaryOperation()->GetRight()
+                                                              : ins->AsBinaryOperation()->GetLeft();
+      if (kind.target_ == Target::kSelf) {
+        EXPECT_INS_EQ(ins->AsBinaryOperation()->GetLeft(), ins->AsBinaryOperation()->GetRight())
+            << " ins is: " << *ins;
+      } else if (kind.target_ == Target::kNull) {
+        EXPECT_INS_EQ(other, graph_->GetNullConstant()) << " ins is: " << *ins;
+      } else {
+        EXPECT_TRUE(other->IsStaticFieldGet()) << " ins is: " << *ins;
+      }
+      if (kind.type_ == Type::kEquals) {
+        EXPECT_TRUE(ins->IsEqual()) << *ins;
+      } else {
+        EXPECT_TRUE(ins->IsNotEqual()) << *ins;
+      }
+    } else {
+      ASSERT_EQ(placement, ComparisonPlacement::kAfterEscape);
+      if (kind.type_ == Type::kEquals) {
+        // obj == <anything> can only be true if (1) it's obj == obj or (2) obj has escaped.
+        ASSERT_TRUE(ins->IsAnd()) << ins->DumpWithArgs();
+        EXPECT_TRUE(ins->InputAt(1)->IsEqual()) << ins->DumpWithArgs();
+      } else {
+        // obj != <anything> is true if (2) obj has escaped.
+        ASSERT_TRUE(ins->IsOr()) << ins->DumpWithArgs();
+        EXPECT_TRUE(ins->InputAt(1)->IsNotEqual()) << ins->DumpWithArgs();
+      }
+      // Check the first part of AND is the obj-has-escaped
+      ASSERT_TRUE(ins->InputAt(0)->IsNotEqual()) << ins->DumpWithArgs();
+      EXPECT_TRUE(ins->InputAt(0)->InputAt(0)->IsPhi()) << ins->DumpWithArgs();
+      EXPECT_TRUE(ins->InputAt(0)->InputAt(1)->IsNullConstant()) << ins->DumpWithArgs();
+      // Check the second part of AND is the eq other
+      EXPECT_INS_EQ(ins->InputAt(1)->InputAt(kind.position_ == Position::kLeft ? 0 : 1),
+                    ins->InputAt(0)->InputAt(0))
+          << ins->DumpWithArgs();
+    }
+  }
+
+  struct ComparisonInstructions {
+    void AddSetup(HBasicBlock* blk) const {
+      for (HInstruction* i : setup_instructions_) {
+        blk->AddInstruction(i);
+      }
+    }
+
+    void AddEnvironment(HEnvironment* env) const {
+      for (HInstruction* i : setup_instructions_) {
+        if (i->NeedsEnvironment()) {
+          i->CopyEnvironmentFrom(env);
+        }
+      }
+    }
+
+    const std::vector<HInstruction*> setup_instructions_;
+    HInstruction* const cmp_;
+  };
+
+  ComparisonInstructions GetComparisonInstructions(HInstruction* partial) {
+    PartialComparisonKind kind = GetParam();
+    std::vector<HInstruction*> setup;
+    HInstruction* target_other;
+    switch (kind.target_) {
+      case PartialComparisonKind::Target::kSelf:
+        target_other = partial;
+        break;
+      case PartialComparisonKind::Target::kNull:
+        target_other = graph_->GetNullConstant();
+        break;
+      case PartialComparisonKind::Target::kValue: {
+        HInstruction* cls = MakeClassLoad();
+        HInstruction* static_read =
+            new (GetAllocator()) HStaticFieldGet(cls,
+                                                 /* field= */ nullptr,
+                                                 DataType::Type::kReference,
+                                                 /* field_offset= */ MemberOffset(40),
+                                                 /* is_volatile= */ false,
+                                                 /* field_idx= */ 0,
+                                                 /* declaring_class_def_index= */ 0,
+                                                 graph_->GetDexFile(),
+                                                 /* dex_pc= */ 0);
+        setup.push_back(cls);
+        setup.push_back(static_read);
+        target_other = static_read;
+        break;
+      }
+    }
+    HInstruction* target_left;
+    HInstruction* target_right;
+    std::tie(target_left, target_right) = kind.position_ == PartialComparisonKind::Position::kLeft
+                                              ? std::pair{partial, target_other}
+                                              : std::pair{target_other, partial};
+    HInstruction* cmp =
+        kind.type_ == PartialComparisonKind::Type::kEquals
+            ? static_cast<HInstruction*>(new (GetAllocator()) HEqual(target_left, target_right))
+            : static_cast<HInstruction*>(new (GetAllocator()) HNotEqual(target_left, target_right));
+    return {setup, cmp};
+  }
+};
+
 TEST_F(LoadStoreEliminationTest, ArrayGetSetElimination) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c1 = graph_->GetIntConstant(1);
@@ -293,7 +505,6 @@
 }
 
 TEST_F(LoadStoreEliminationTest, SameHeapValue1) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c1 = graph_->GetIntConstant(1);
@@ -316,7 +527,6 @@
 }
 
 TEST_F(LoadStoreEliminationTest, SameHeapValue2) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   // Test LSE handling same value stores on vector.
@@ -334,7 +544,6 @@
 }
 
 TEST_F(LoadStoreEliminationTest, SameHeapValue3) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   // VecStore array[i...] = vdata;
@@ -350,7 +559,6 @@
 }
 
 TEST_F(LoadStoreEliminationTest, OverlappingLoadStore) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c1 = graph_->GetIntConstant(1);
@@ -408,7 +616,6 @@
 // }
 // a[j] = 1;
 TEST_F(LoadStoreEliminationTest, StoreAfterLoopWithoutSideEffects) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c1 = graph_->GetIntConstant(1);
@@ -438,7 +645,6 @@
 //   a[j] = 0;
 // }
 TEST_F(LoadStoreEliminationTest, StoreAfterSIMDLoopWithSideEffects) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -477,7 +683,6 @@
 //   x = a[j];
 // }
 TEST_F(LoadStoreEliminationTest, LoadAfterSIMDLoopWithSideEffects) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -521,8 +726,6 @@
 //   'vstore3' is not removed.
 //   'vstore4' is not removed. Such cases are not supported at the moment.
 TEST_F(LoadStoreEliminationTest, MergePredecessorVecStores) {
-  InitGraph();
-
   HBasicBlock* upper;
   HBasicBlock* left;
   HBasicBlock* right;
@@ -564,8 +767,6 @@
 //   'store2' is not removed.
 //   'store3' is removed.
 TEST_F(LoadStoreEliminationTest, MergePredecessorStores) {
-  InitGraph();
-
   HBasicBlock* upper;
   HBasicBlock* left;
   HBasicBlock* right;
@@ -599,12 +800,14 @@
 //     vstore2: b[i,... i + 3] = x
 //     vstore3: a[i,... i + 3] = [1,...1]
 //
+// Return 'a' from the method to make it escape.
+//
 // Expected:
 //   'vstore1' is not removed.
 //   'vload' is removed.
+//   'vstore2' is removed because 'b' does not escape.
 //   'vstore3' is removed.
 TEST_F(LoadStoreEliminationTest, RedundantVStoreVLoadInLoop) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -614,6 +817,10 @@
   pre_header_->InsertInstructionBefore(array_a, pre_header_->GetLastInstruction());
   array_a->CopyEnvironmentFrom(suspend_check_->GetEnvironment());
 
+  ASSERT_TRUE(return_block_->GetLastInstruction()->IsReturnVoid());
+  HInstruction* ret = new (GetAllocator()) HReturn(array_a);
+  return_block_->ReplaceAndRemoveInstructionWith(return_block_->GetLastInstruction(), ret);
+
   HInstruction* array_b = new (GetAllocator()) HNewArray(c0, c128, 0, 0);
   pre_header_->InsertInstructionBefore(array_b, pre_header_->GetLastInstruction());
   array_b->CopyEnvironmentFrom(suspend_check_->GetEnvironment());
@@ -625,21 +832,19 @@
   //    a[i,... i + 3] = [1,...1]
   HInstruction* vstore1 = AddVecStore(loop_, array_a, phi_);
   HInstruction* vload = AddVecLoad(loop_, array_a, phi_);
-  AddVecStore(loop_, array_b, phi_, vload->AsVecLoad());
+  HInstruction* vstore2 = AddVecStore(loop_, array_b, phi_, vload->AsVecLoad());
   HInstruction* vstore3 = AddVecStore(loop_, array_a, phi_, vstore1->InputAt(2));
 
   PerformLSE();
 
   ASSERT_FALSE(IsRemoved(vstore1));
   ASSERT_TRUE(IsRemoved(vload));
+  ASSERT_TRUE(IsRemoved(vstore2));
   ASSERT_TRUE(IsRemoved(vstore3));
 }
 
-// Loop write side effects invalidate all stores.
-// This causes stores after such loops not to be removed, even
-// their values are known.
+// Loop writes invalidate only possibly aliased heap locations.
 TEST_F(LoadStoreEliminationTest, StoreAfterLoopWithSideEffects) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -650,26 +855,58 @@
   // loop:
   //   b[i] = array[i]
   // array[0] = 2
-  AddArraySet(entry_block_, array_, c0, c2);
+  HInstruction* store1 = AddArraySet(entry_block_, array_, c0, c2);
 
   HInstruction* array_b = new (GetAllocator()) HNewArray(c0, c128, 0, 0);
   pre_header_->InsertInstructionBefore(array_b, pre_header_->GetLastInstruction());
   array_b->CopyEnvironmentFrom(suspend_check_->GetEnvironment());
 
   HInstruction* load = AddArrayGet(loop_, array_, phi_);
-  AddArraySet(loop_, array_b, phi_, load);
+  HInstruction* store2 = AddArraySet(loop_, array_b, phi_, load);
 
-  HInstruction* store = AddArraySet(return_block_, array_, c0, c2);
+  HInstruction* store3 = AddArraySet(return_block_, array_, c0, c2);
 
   PerformLSE();
 
-  ASSERT_FALSE(IsRemoved(store));
+  ASSERT_FALSE(IsRemoved(store1));
+  ASSERT_TRUE(IsRemoved(store2));
+  ASSERT_TRUE(IsRemoved(store3));
+}
+
+// Loop writes invalidate only possibly aliased heap locations.
+TEST_F(LoadStoreEliminationTest, StoreAfterLoopWithSideEffects2) {
+  CreateTestControlFlowGraph();
+
+  // Add another array parameter that may alias with `array_`.
+  // Note: We're not adding it to the suspend check environment.
+  AddParameter(new (GetAllocator()) HParameterValue(
+      graph_->GetDexFile(), dex::TypeIndex(0), 3, DataType::Type::kInt32));
+  HInstruction* array2 = parameters_.back();
+
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+
+  // array[0] = 2;
+  // loop:
+  //   array2[i] = array[i]
+  // array[0] = 2
+  HInstruction* store1 = AddArraySet(entry_block_, array_, c0, c2);
+
+  HInstruction* load = AddArrayGet(loop_, array_, phi_);
+  HInstruction* store2 = AddArraySet(loop_, array2, phi_, load);
+
+  HInstruction* store3 = AddArraySet(return_block_, array_, c0, c2);
+
+  PerformLSE();
+
+  ASSERT_FALSE(IsRemoved(store1));
+  ASSERT_FALSE(IsRemoved(store2));
+  ASSERT_FALSE(IsRemoved(store3));
 }
 
 // As it is not allowed to use defaults for VecLoads, check if there is a new created array
 // a VecLoad used in a loop and after it is not replaced with a default.
 TEST_F(LoadStoreEliminationTest, VLoadDefaultValueInLoopWithoutWriteSideEffects) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -694,7 +931,6 @@
 // As it is not allowed to use defaults for VecLoads, check if there is a new created array
 // a VecLoad is not replaced with a default.
 TEST_F(LoadStoreEliminationTest, VLoadDefaultValue) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -718,7 +954,6 @@
 // As it is allowed to use defaults for ordinary loads, check if there is a new created array
 // a load used in a loop and after it is replaced with a default.
 TEST_F(LoadStoreEliminationTest, LoadDefaultValueInLoopWithoutWriteSideEffects) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -743,7 +978,6 @@
 // As it is allowed to use defaults for ordinary loads, check if there is a new created array
 // a load is replaced with a default.
 TEST_F(LoadStoreEliminationTest, LoadDefaultValue) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -768,7 +1002,6 @@
 // check if there is a new created array, a VecLoad and a load used in a loop and after it,
 // VecLoad is not replaced with a default but the load is.
 TEST_F(LoadStoreEliminationTest, VLoadAndLoadDefaultValueInLoopWithoutWriteSideEffects) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -800,7 +1033,6 @@
 // check if there is a new created array, a VecLoad and a load,
 // VecLoad is not replaced with a default but the load is.
 TEST_F(LoadStoreEliminationTest, VLoadAndLoadDefaultValue) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -831,7 +1063,6 @@
 // loads getting the same value.
 // Check a load getting a known value is eliminated (a loop test case).
 TEST_F(LoadStoreEliminationTest, VLoadDefaultValueAndVLoadInLoopWithoutWriteSideEffects) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -863,7 +1094,6 @@
 // loads getting the same value.
 // Check a load getting a known value is eliminated.
 TEST_F(LoadStoreEliminationTest, VLoadDefaultValueAndVLoad) {
-  InitGraph();
   CreateTestControlFlowGraph();
 
   HInstruction* c0 = graph_->GetIntConstant(0);
@@ -890,4 +1120,7697 @@
   ASSERT_FALSE(IsRemoved(vstore2));
 }
 
+// Object o = new Obj();
+// // Needed because otherwise we short-circuit LSA since GVN would get almost
+// // everything other than this. Also since this isn't expected to be a very
+// // common pattern it's not worth changing the LSA logic.
+// o.foo = 3;
+// return o.shadow$_klass_;
+TEST_F(LoadStoreEliminationTest, DefaultShadowClass) {
+  CreateGraph();
+  AdjacencyListGraph blocks(
+      graph_, GetAllocator(), "entry", "exit", {{"entry", "main"}, {"main", "exit"}});
+#define GET_BLOCK(name) HBasicBlock* name = blocks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(main);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+
+  HInstruction* suspend_check = new (GetAllocator()) HSuspendCheck();
+  entry->AddInstruction(suspend_check);
+  entry->AddInstruction(new (GetAllocator()) HGoto());
+  ManuallyBuildEnvFor(suspend_check, {});
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* const_fence = new (GetAllocator()) HConstructorFence(new_inst, 0, GetAllocator());
+  HInstruction* set_field = MakeIFieldSet(new_inst, graph_->GetIntConstant(33), MemberOffset(32));
+  HInstruction* get_field =
+      MakeIFieldGet(new_inst, DataType::Type::kReference, mirror::Object::ClassOffset());
+  HInstruction* return_val = new (GetAllocator()) HReturn(get_field);
+  main->AddInstruction(cls);
+  main->AddInstruction(new_inst);
+  main->AddInstruction(const_fence);
+  main->AddInstruction(set_field);
+  main->AddInstruction(get_field);
+  main->AddInstruction(return_val);
+  cls->CopyEnvironmentFrom(suspend_check->GetEnvironment());
+  new_inst->CopyEnvironmentFrom(suspend_check->GetEnvironment());
+
+  SetupExit(exit);
+
+  graph_->ClearDominanceInformation();
+  PerformLSE();
+
+  EXPECT_INS_REMOVED(new_inst);
+  EXPECT_INS_REMOVED(const_fence);
+  EXPECT_INS_REMOVED(get_field);
+  EXPECT_INS_REMOVED(set_field);
+  EXPECT_INS_RETAINED(cls);
+  EXPECT_INS_EQ(cls, return_val->InputAt(0));
+}
+
+// Object o = new Obj();
+// // Needed because otherwise we short-circuit LSA since GVN would get almost
+// // everything other than this. Also since this isn't expected to be a very
+// // common pattern (only a single java function, Object.identityHashCode,
+// // ever reads this field) it's not worth changing the LSA logic.
+// o.foo = 3;
+// return o.shadow$_monitor_;
+TEST_F(LoadStoreEliminationTest, DefaultShadowMonitor) {
+  CreateGraph();
+  AdjacencyListGraph blocks(
+      graph_, GetAllocator(), "entry", "exit", {{"entry", "main"}, {"main", "exit"}});
+#define GET_BLOCK(name) HBasicBlock* name = blocks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(main);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+
+  HInstruction* suspend_check = new (GetAllocator()) HSuspendCheck();
+  entry->AddInstruction(suspend_check);
+  entry->AddInstruction(new (GetAllocator()) HGoto());
+  ManuallyBuildEnvFor(suspend_check, {});
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* const_fence = new (GetAllocator()) HConstructorFence(new_inst, 0, GetAllocator());
+  HInstruction* set_field = MakeIFieldSet(new_inst, graph_->GetIntConstant(33), MemberOffset(32));
+  HInstruction* get_field =
+      MakeIFieldGet(new_inst, DataType::Type::kInt32, mirror::Object::MonitorOffset());
+  HInstruction* return_val = new (GetAllocator()) HReturn(get_field);
+  main->AddInstruction(cls);
+  main->AddInstruction(new_inst);
+  main->AddInstruction(const_fence);
+  main->AddInstruction(set_field);
+  main->AddInstruction(get_field);
+  main->AddInstruction(return_val);
+  cls->CopyEnvironmentFrom(suspend_check->GetEnvironment());
+  new_inst->CopyEnvironmentFrom(suspend_check->GetEnvironment());
+
+  SetupExit(exit);
+
+  graph_->ClearDominanceInformation();
+  PerformLSE();
+
+  EXPECT_INS_REMOVED(new_inst);
+  EXPECT_INS_REMOVED(const_fence);
+  EXPECT_INS_REMOVED(get_field);
+  EXPECT_INS_REMOVED(set_field);
+  EXPECT_INS_RETAINED(cls);
+  EXPECT_INS_EQ(graph_->GetIntConstant(0), return_val->InputAt(0));
+}
+
+// void DO_CAL() {
+//   int i = 1;
+//   int[] w = new int[80];
+//   int t = 0;
+//   while (i < 80) {
+//     w[i] = PLEASE_INTERLEAVE(w[i - 1], 1)
+//     t = PLEASE_SELECT(w[i], t);
+//     i++;
+//   }
+//   return t;
+// }
+TEST_F(LoadStoreEliminationTest, ArrayLoopOverlap) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blocks(graph_,
+                            GetAllocator(),
+                            "entry",
+                            "exit",
+                            { { "entry", "loop_pre_header" },
+                              { "loop_pre_header", "loop_entry" },
+                              { "loop_entry", "loop_body" },
+                              { "loop_entry", "loop_post" },
+                              { "loop_body", "loop_entry" },
+                              { "loop_post", "exit" } });
+#define GET_BLOCK(name) HBasicBlock* name = blocks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(loop_pre_header);
+  GET_BLOCK(loop_entry);
+  GET_BLOCK(loop_body);
+  GET_BLOCK(loop_post);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+
+  HInstruction* zero_const = graph_->GetConstant(DataType::Type::kInt32, 0);
+  HInstruction* one_const = graph_->GetConstant(DataType::Type::kInt32, 1);
+  HInstruction* eighty_const = graph_->GetConstant(DataType::Type::kInt32, 80);
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(entry_goto);
+
+  HInstruction* alloc_w = new (GetAllocator()) HNewArray(zero_const, eighty_const, 0, 0);
+  HInstruction* pre_header_goto = new (GetAllocator()) HGoto();
+  loop_pre_header->AddInstruction(alloc_w);
+  loop_pre_header->AddInstruction(pre_header_goto);
+  // environment
+  ManuallyBuildEnvFor(alloc_w, {});
+
+  // loop-start
+  HPhi* i_phi = new (GetAllocator()) HPhi(GetAllocator(), 0, 0, DataType::Type::kInt32);
+  HPhi* t_phi = new (GetAllocator()) HPhi(GetAllocator(), 1, 0, DataType::Type::kInt32);
+  HInstruction* suspend = new (GetAllocator()) HSuspendCheck();
+  HInstruction* i_cmp_top = new (GetAllocator()) HGreaterThanOrEqual(i_phi, eighty_const);
+  HInstruction* loop_start_branch = new (GetAllocator()) HIf(i_cmp_top);
+  loop_entry->AddPhi(i_phi);
+  loop_entry->AddPhi(t_phi);
+  loop_entry->AddInstruction(suspend);
+  loop_entry->AddInstruction(i_cmp_top);
+  loop_entry->AddInstruction(loop_start_branch);
+  CHECK_EQ(loop_entry->GetSuccessors().size(), 2u);
+  if (loop_entry->GetNormalSuccessors()[1] != loop_body) {
+    loop_entry->SwapSuccessors();
+  }
+  CHECK_EQ(loop_entry->GetPredecessors().size(), 2u);
+  if (loop_entry->GetPredecessors()[0] != loop_pre_header) {
+    loop_entry->SwapPredecessors();
+  }
+  i_phi->AddInput(one_const);
+  t_phi->AddInput(zero_const);
+
+  // environment
+  ManuallyBuildEnvFor(suspend, { alloc_w, i_phi, t_phi });
+
+  // BODY
+  HInstruction* last_i = new (GetAllocator()) HSub(DataType::Type::kInt32, i_phi, one_const);
+  HInstruction* last_get =
+      new (GetAllocator()) HArrayGet(alloc_w, last_i, DataType::Type::kInt32, 0);
+  HInvoke* body_value = MakeInvoke(DataType::Type::kInt32, { last_get, one_const });
+  HInstruction* body_set =
+      new (GetAllocator()) HArraySet(alloc_w, i_phi, body_value, DataType::Type::kInt32, 0);
+  HInstruction* body_get =
+      new (GetAllocator()) HArrayGet(alloc_w, i_phi, DataType::Type::kInt32, 0);
+  HInvoke* t_next = MakeInvoke(DataType::Type::kInt32, { body_get, t_phi });
+  HInstruction* i_next = new (GetAllocator()) HAdd(DataType::Type::kInt32, i_phi, one_const);
+  HInstruction* body_goto = new (GetAllocator()) HGoto();
+  loop_body->AddInstruction(last_i);
+  loop_body->AddInstruction(last_get);
+  loop_body->AddInstruction(body_value);
+  loop_body->AddInstruction(body_set);
+  loop_body->AddInstruction(body_get);
+  loop_body->AddInstruction(t_next);
+  loop_body->AddInstruction(i_next);
+  loop_body->AddInstruction(body_goto);
+  body_value->CopyEnvironmentFrom(suspend->GetEnvironment());
+
+  i_phi->AddInput(i_next);
+  t_phi->AddInput(t_next);
+  t_next->CopyEnvironmentFrom(suspend->GetEnvironment());
+
+  // loop-post
+  HInstruction* return_inst = new (GetAllocator()) HReturn(t_phi);
+  loop_post->AddInstruction(return_inst);
+
+  // exit
+  SetupExit(exit);
+
+  graph_->ClearDominanceInformation();
+  graph_->ClearLoopInformation();
+  PerformLSE();
+
+  // TODO Technically this is optimizable. LSE just needs to add phis to keep
+  // track of the last `N` values set where `N` is how many locations we can go
+  // back into the array.
+  if (IsRemoved(last_get)) {
+    // If we were able to remove the previous read the entire array should be removable.
+    EXPECT_INS_REMOVED(body_set);
+    EXPECT_INS_REMOVED(alloc_w);
+  } else {
+    // This is the branch we actually take for now. If we rely on being able to
+    // read the array we'd better remember to write to it as well.
+    EXPECT_INS_RETAINED(body_set);
+  }
+  // The last 'get' should always be removable.
+  EXPECT_INS_REMOVED(body_get);
+}
+
+// void DO_CAL2() {
+//   int i = 1;
+//   int[] w = new int[80];
+//   int t = 0;
+//   while (i < 80) {
+//     w[i] = PLEASE_INTERLEAVE(w[i - 1], 1) // <-- removed
+//     t = PLEASE_SELECT(w[i], t);
+//     w[i] = PLEASE_INTERLEAVE(w[i - 1], 1) // <-- removed
+//     t = PLEASE_SELECT(w[i], t);
+//     w[i] = PLEASE_INTERLEAVE(w[i - 1], 1) // <-- kept
+//     t = PLEASE_SELECT(w[i], t);
+//     i++;
+//   }
+//   return t;
+// }
+TEST_F(LoadStoreEliminationTest, ArrayLoopOverlap2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blocks(graph_,
+                            GetAllocator(),
+                            "entry",
+                            "exit",
+                            { { "entry", "loop_pre_header" },
+                              { "loop_pre_header", "loop_entry" },
+                              { "loop_entry", "loop_body" },
+                              { "loop_entry", "loop_post" },
+                              { "loop_body", "loop_entry" },
+                              { "loop_post", "exit" } });
+#define GET_BLOCK(name) HBasicBlock* name = blocks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(loop_pre_header);
+  GET_BLOCK(loop_entry);
+  GET_BLOCK(loop_body);
+  GET_BLOCK(loop_post);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+
+  HInstruction* zero_const = graph_->GetConstant(DataType::Type::kInt32, 0);
+  HInstruction* one_const = graph_->GetConstant(DataType::Type::kInt32, 1);
+  HInstruction* eighty_const = graph_->GetConstant(DataType::Type::kInt32, 80);
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(entry_goto);
+
+  HInstruction* alloc_w = new (GetAllocator()) HNewArray(zero_const, eighty_const, 0, 0);
+  HInstruction* pre_header_goto = new (GetAllocator()) HGoto();
+  loop_pre_header->AddInstruction(alloc_w);
+  loop_pre_header->AddInstruction(pre_header_goto);
+  // environment
+  ManuallyBuildEnvFor(alloc_w, {});
+
+  // loop-start
+  HPhi* i_phi = new (GetAllocator()) HPhi(GetAllocator(), 0, 0, DataType::Type::kInt32);
+  HPhi* t_phi = new (GetAllocator()) HPhi(GetAllocator(), 1, 0, DataType::Type::kInt32);
+  HInstruction* suspend = new (GetAllocator()) HSuspendCheck();
+  HInstruction* i_cmp_top = new (GetAllocator()) HGreaterThanOrEqual(i_phi, eighty_const);
+  HInstruction* loop_start_branch = new (GetAllocator()) HIf(i_cmp_top);
+  loop_entry->AddPhi(i_phi);
+  loop_entry->AddPhi(t_phi);
+  loop_entry->AddInstruction(suspend);
+  loop_entry->AddInstruction(i_cmp_top);
+  loop_entry->AddInstruction(loop_start_branch);
+  CHECK_EQ(loop_entry->GetSuccessors().size(), 2u);
+  if (loop_entry->GetNormalSuccessors()[1] != loop_body) {
+    loop_entry->SwapSuccessors();
+  }
+  CHECK_EQ(loop_entry->GetPredecessors().size(), 2u);
+  if (loop_entry->GetPredecessors()[0] != loop_pre_header) {
+    loop_entry->SwapPredecessors();
+  }
+  i_phi->AddInput(one_const);
+  t_phi->AddInput(zero_const);
+
+  // environment
+  ManuallyBuildEnvFor(suspend, { alloc_w, i_phi, t_phi });
+
+  // BODY
+  HInstruction* last_i = new (GetAllocator()) HSub(DataType::Type::kInt32, i_phi, one_const);
+  HInstruction *last_get_1, *last_get_2, *last_get_3;
+  HInstruction *body_value_1, *body_value_2, *body_value_3;
+  HInstruction *body_set_1, *body_set_2, *body_set_3;
+  HInstruction *body_get_1, *body_get_2, *body_get_3;
+  HInstruction *t_next_1, *t_next_2, *t_next_3;
+  auto make_instructions = [&](HInstruction* last_t_value) {
+    HInstruction* last_get =
+        new (GetAllocator()) HArrayGet(alloc_w, last_i, DataType::Type::kInt32, 0);
+    HInvoke* body_value = MakeInvoke(DataType::Type::kInt32, { last_get, one_const });
+    HInstruction* body_set =
+        new (GetAllocator()) HArraySet(alloc_w, i_phi, body_value, DataType::Type::kInt32, 0);
+    HInstruction* body_get =
+        new (GetAllocator()) HArrayGet(alloc_w, i_phi, DataType::Type::kInt32, 0);
+    HInvoke* t_next = MakeInvoke(DataType::Type::kInt32, { body_get, last_t_value });
+    loop_body->AddInstruction(last_get);
+    loop_body->AddInstruction(body_value);
+    loop_body->AddInstruction(body_set);
+    loop_body->AddInstruction(body_get);
+    loop_body->AddInstruction(t_next);
+    return std::make_tuple(last_get, body_value, body_set, body_get, t_next);
+  };
+  std::tie(last_get_1, body_value_1, body_set_1, body_get_1, t_next_1) = make_instructions(t_phi);
+  std::tie(last_get_2, body_value_2, body_set_2, body_get_2, t_next_2) =
+      make_instructions(t_next_1);
+  std::tie(last_get_3, body_value_3, body_set_3, body_get_3, t_next_3) =
+      make_instructions(t_next_2);
+  HInstruction* i_next = new (GetAllocator()) HAdd(DataType::Type::kInt32, i_phi, one_const);
+  HInstruction* body_goto = new (GetAllocator()) HGoto();
+  loop_body->InsertInstructionBefore(last_i, last_get_1);
+  loop_body->AddInstruction(i_next);
+  loop_body->AddInstruction(body_goto);
+  body_value_1->CopyEnvironmentFrom(suspend->GetEnvironment());
+  body_value_2->CopyEnvironmentFrom(suspend->GetEnvironment());
+  body_value_3->CopyEnvironmentFrom(suspend->GetEnvironment());
+
+  i_phi->AddInput(i_next);
+  t_phi->AddInput(t_next_3);
+  t_next_1->CopyEnvironmentFrom(suspend->GetEnvironment());
+  t_next_2->CopyEnvironmentFrom(suspend->GetEnvironment());
+  t_next_3->CopyEnvironmentFrom(suspend->GetEnvironment());
+
+  // loop-post
+  HInstruction* return_inst = new (GetAllocator()) HReturn(t_phi);
+  loop_post->AddInstruction(return_inst);
+
+  // exit
+  SetupExit(exit);
+
+  graph_->ClearDominanceInformation();
+  graph_->ClearLoopInformation();
+  PerformLSE();
+
+  // TODO Technically this is optimizable. LSE just needs to add phis to keep
+  // track of the last `N` values set where `N` is how many locations we can go
+  // back into the array.
+  if (IsRemoved(last_get_1)) {
+    // If we were able to remove the previous read the entire array should be removable.
+    EXPECT_INS_REMOVED(body_set_1);
+    EXPECT_INS_REMOVED(body_set_2);
+    EXPECT_INS_REMOVED(body_set_3);
+    EXPECT_INS_REMOVED(last_get_1);
+    EXPECT_INS_REMOVED(last_get_2);
+    EXPECT_INS_REMOVED(alloc_w);
+  } else {
+    // This is the branch we actually take for now. If we rely on being able to
+    // read the array we'd better remember to write to it as well.
+    EXPECT_INS_RETAINED(body_set_3);
+  }
+  // The last 'get' should always be removable.
+  EXPECT_INS_REMOVED(body_get_1);
+  EXPECT_INS_REMOVED(body_get_2);
+  EXPECT_INS_REMOVED(body_get_3);
+  // shadowed writes should always be removed
+  EXPECT_INS_REMOVED(body_set_1);
+  EXPECT_INS_REMOVED(body_set_2);
+}
+
+TEST_F(LoadStoreEliminationTest, ArrayNonLoopPhi) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blocks(graph_,
+                            GetAllocator(),
+                            "entry",
+                            "exit",
+                            { { "entry", "start" },
+                              { "start", "left" },
+                              { "start", "right" },
+                              { "left", "ret" },
+                              { "right", "ret" },
+                              { "ret", "exit" } });
+#define GET_BLOCK(name) HBasicBlock* name = blocks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(start);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(ret);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+
+  HInstruction* zero_const = graph_->GetConstant(DataType::Type::kInt32, 0);
+  HInstruction* one_const = graph_->GetConstant(DataType::Type::kInt32, 1);
+  HInstruction* two_const = graph_->GetConstant(DataType::Type::kInt32, 2);
+  HInstruction* param = MakeParam(DataType::Type::kBool);
+
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(entry_goto);
+
+  HInstruction* alloc_w = new (GetAllocator()) HNewArray(zero_const, two_const, 0, 0);
+  HInstruction* branch = new (GetAllocator()) HIf(param);
+  start->AddInstruction(alloc_w);
+  start->AddInstruction(branch);
+  // environment
+  ManuallyBuildEnvFor(alloc_w, {});
+
+  // left
+  HInvoke* left_value = MakeInvoke(DataType::Type::kInt32, { zero_const });
+  HInstruction* left_set_1 =
+      new (GetAllocator()) HArraySet(alloc_w, zero_const, left_value, DataType::Type::kInt32, 0);
+  HInstruction* left_set_2 =
+      new (GetAllocator()) HArraySet(alloc_w, one_const, zero_const, DataType::Type::kInt32, 0);
+  HInstruction* left_goto = new (GetAllocator()) HGoto();
+  left->AddInstruction(left_value);
+  left->AddInstruction(left_set_1);
+  left->AddInstruction(left_set_2);
+  left->AddInstruction(left_goto);
+  ManuallyBuildEnvFor(left_value, { alloc_w });
+
+  // right
+  HInvoke* right_value = MakeInvoke(DataType::Type::kInt32, { one_const });
+  HInstruction* right_set_1 =
+      new (GetAllocator()) HArraySet(alloc_w, zero_const, right_value, DataType::Type::kInt32, 0);
+  HInstruction* right_set_2 =
+      new (GetAllocator()) HArraySet(alloc_w, one_const, zero_const, DataType::Type::kInt32, 0);
+  HInstruction* right_goto = new (GetAllocator()) HGoto();
+  right->AddInstruction(right_value);
+  right->AddInstruction(right_set_1);
+  right->AddInstruction(right_set_2);
+  right->AddInstruction(right_goto);
+  ManuallyBuildEnvFor(right_value, { alloc_w });
+
+  // ret
+  HInstruction* read_1 =
+      new (GetAllocator()) HArrayGet(alloc_w, zero_const, DataType::Type::kInt32, 0);
+  HInstruction* read_2 =
+      new (GetAllocator()) HArrayGet(alloc_w, one_const, DataType::Type::kInt32, 0);
+  HInstruction* add = new (GetAllocator()) HAdd(DataType::Type::kInt32, read_1, read_2);
+  HInstruction* return_inst = new (GetAllocator()) HReturn(add);
+  ret->AddInstruction(read_1);
+  ret->AddInstruction(read_2);
+  ret->AddInstruction(add);
+  ret->AddInstruction(return_inst);
+
+  // exit
+  SetupExit(exit);
+
+  graph_->ClearDominanceInformation();
+  graph_->ClearLoopInformation();
+  PerformLSE();
+
+  EXPECT_INS_REMOVED(read_1);
+  EXPECT_INS_REMOVED(read_2);
+  EXPECT_INS_REMOVED(left_set_1);
+  EXPECT_INS_REMOVED(left_set_2);
+  EXPECT_INS_REMOVED(right_set_1);
+  EXPECT_INS_REMOVED(right_set_2);
+  EXPECT_INS_REMOVED(alloc_w);
+
+  EXPECT_INS_RETAINED(left_value);
+  EXPECT_INS_RETAINED(right_value);
+}
+
+TEST_F(LoadStoreEliminationTest, ArrayMergeDefault) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blocks(graph_,
+                            GetAllocator(),
+                            "entry",
+                            "exit",
+                            { { "entry", "start" },
+                              { "start", "left" },
+                              { "start", "right" },
+                              { "left", "ret" },
+                              { "right", "ret" },
+                              { "ret", "exit" } });
+#define GET_BLOCK(name) HBasicBlock* name = blocks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(start);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(ret);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+
+  HInstruction* zero_const = graph_->GetConstant(DataType::Type::kInt32, 0);
+  HInstruction* one_const = graph_->GetConstant(DataType::Type::kInt32, 1);
+  HInstruction* two_const = graph_->GetConstant(DataType::Type::kInt32, 2);
+  HInstruction* param = MakeParam(DataType::Type::kBool);
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+
+  entry->AddInstruction(entry_goto);
+
+  HInstruction* alloc_w = new (GetAllocator()) HNewArray(zero_const, two_const, 0, 0);
+  HInstruction* branch = new (GetAllocator()) HIf(param);
+  start->AddInstruction(alloc_w);
+  start->AddInstruction(branch);
+  // environment
+  ArenaVector<HInstruction*> alloc_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction));
+  ManuallyBuildEnvFor(alloc_w, {});
+
+  // left
+  HInstruction* left_set_1 =
+      new (GetAllocator()) HArraySet(alloc_w, zero_const, one_const, DataType::Type::kInt32, 0);
+  HInstruction* left_set_2 =
+      new (GetAllocator()) HArraySet(alloc_w, zero_const, zero_const, DataType::Type::kInt32, 0);
+  HInstruction* left_goto = new (GetAllocator()) HGoto();
+  left->AddInstruction(left_set_1);
+  left->AddInstruction(left_set_2);
+  left->AddInstruction(left_goto);
+
+  // right
+  HInstruction* right_set_1 =
+      new (GetAllocator()) HArraySet(alloc_w, one_const, one_const, DataType::Type::kInt32, 0);
+  HInstruction* right_set_2 =
+      new (GetAllocator()) HArraySet(alloc_w, one_const, zero_const, DataType::Type::kInt32, 0);
+  HInstruction* right_goto = new (GetAllocator()) HGoto();
+  right->AddInstruction(right_set_1);
+  right->AddInstruction(right_set_2);
+  right->AddInstruction(right_goto);
+
+  // ret
+  HInstruction* read_1 =
+      new (GetAllocator()) HArrayGet(alloc_w, zero_const, DataType::Type::kInt32, 0);
+  HInstruction* read_2 =
+      new (GetAllocator()) HArrayGet(alloc_w, one_const, DataType::Type::kInt32, 0);
+  HInstruction* add = new (GetAllocator()) HAdd(DataType::Type::kInt32, read_1, read_2);
+  HInstruction* return_inst = new (GetAllocator()) HReturn(add);
+  ret->AddInstruction(read_1);
+  ret->AddInstruction(read_2);
+  ret->AddInstruction(add);
+  ret->AddInstruction(return_inst);
+
+  // exit
+  SetupExit(exit);
+
+  graph_->ClearDominanceInformation();
+  graph_->ClearLoopInformation();
+  PerformLSE();
+
+  EXPECT_INS_REMOVED(read_1);
+  EXPECT_INS_REMOVED(read_2);
+  EXPECT_INS_REMOVED(left_set_1);
+  EXPECT_INS_REMOVED(left_set_2);
+  EXPECT_INS_REMOVED(right_set_1);
+  EXPECT_INS_REMOVED(right_set_2);
+  EXPECT_INS_REMOVED(alloc_w);
+}
+
+// Regression test for b/187487955.
+// We previusly failed to consider aliasing between an array location
+// with index `idx` defined in the loop (such as a loop Phi) and another
+// array location with index `idx + constant`. This could have led to
+// replacing the load with, for example, the default value 0.
+TEST_F(LoadStoreEliminationTest, ArrayLoopAliasing1) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blocks(graph_,
+                            GetAllocator(),
+                            "entry",
+                            "exit",
+                            { { "entry", "preheader" },
+                              { "preheader", "loop" },
+                              { "loop", "body" },
+                              { "body", "loop" },
+                              { "loop", "ret" },
+                              { "ret", "exit" } });
+#define GET_BLOCK(name) HBasicBlock* name = blocks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(preheader);
+  GET_BLOCK(loop);
+  GET_BLOCK(body);
+  GET_BLOCK(ret);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+  HInstruction* n = MakeParam(DataType::Type::kInt32);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+
+  // entry
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* array = new (GetAllocator()) HNewArray(
+      cls, n, /*dex_pc=*/ 0u, DataType::SizeShift(DataType::Type::kInt32));
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(array);
+  entry->AddInstruction(entry_goto);
+  ManuallyBuildEnvFor(cls, {});
+  ManuallyBuildEnvFor(array, {});
+
+  HInstruction* preheader_goto = new (GetAllocator()) HGoto();
+  preheader->AddInstruction(preheader_goto);
+
+  // loop
+  HPhi* i_phi = new (GetAllocator()) HPhi(GetAllocator(), 0, 0, DataType::Type::kInt32);
+  HInstruction* loop_suspend_check = new (GetAllocator()) HSuspendCheck();
+  HInstruction* loop_cond = new (GetAllocator()) HLessThan(i_phi, n);
+  HIf* loop_if = new (GetAllocator()) HIf(loop_cond);
+  loop->AddPhi(i_phi);
+  loop->AddInstruction(loop_suspend_check);
+  loop->AddInstruction(loop_cond);
+  loop->AddInstruction(loop_if);
+  CHECK(loop_if->IfTrueSuccessor() == body);
+  ManuallyBuildEnvFor(loop_suspend_check, {});
+
+  // body
+  HInstruction* body_set =
+      new (GetAllocator()) HArraySet(array, i_phi, i_phi, DataType::Type::kInt32, /*dex_pc=*/ 0u);
+  HInstruction* body_add = new (GetAllocator()) HAdd(DataType::Type::kInt32, i_phi, c1);
+  HInstruction* body_goto = new (GetAllocator()) HGoto();
+  body->AddInstruction(body_set);
+  body->AddInstruction(body_add);
+  body->AddInstruction(body_goto);
+
+  // i_phi inputs
+  i_phi->AddInput(c0);
+  i_phi->AddInput(body_add);
+
+  // ret
+  HInstruction* ret_sub = new (GetAllocator()) HSub(DataType::Type::kInt32, i_phi, c1);
+  HInstruction* ret_get =
+      new (GetAllocator()) HArrayGet(array, ret_sub, DataType::Type::kInt32, /*dex_pc=*/ 0);
+  HInstruction* ret_return = new (GetAllocator()) HReturn(ret_get);
+  ret->AddInstruction(ret_sub);
+  ret->AddInstruction(ret_get);
+  ret->AddInstruction(ret_return);
+
+  // exit
+  SetupExit(exit);
+
+  graph_->ClearDominanceInformation();
+  graph_->ClearLoopInformation();
+  PerformLSE();
+
+  EXPECT_INS_RETAINED(cls);
+  EXPECT_INS_RETAINED(array);
+  EXPECT_INS_RETAINED(body_set);
+  EXPECT_INS_RETAINED(ret_get);
+}
+
+// Regression test for b/187487955.
+// Similar to the `ArrayLoopAliasing1` test above but with additional load
+// that marks a loop Phi placeholder as kept which used to trigger a DCHECK().
+// There is also an LSE run-test for this but it relies on BCE eliminating
+// BoundsCheck instructions and adds extra code in loop body to avoid
+// loop unrolling. This gtest does not need to jump through those hoops
+// as we do not unnecessarily run those optimization passes.
+TEST_F(LoadStoreEliminationTest, ArrayLoopAliasing2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blocks(graph_,
+                            GetAllocator(),
+                            "entry",
+                            "exit",
+                            { { "entry", "preheader" },
+                              { "preheader", "loop" },
+                              { "loop", "body" },
+                              { "body", "loop" },
+                              { "loop", "ret" },
+                              { "ret", "exit" } });
+#define GET_BLOCK(name) HBasicBlock* name = blocks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(preheader);
+  GET_BLOCK(loop);
+  GET_BLOCK(body);
+  GET_BLOCK(ret);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+  HInstruction* n = MakeParam(DataType::Type::kInt32);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+
+  // entry
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* array = new (GetAllocator()) HNewArray(
+      cls, n, /*dex_pc=*/ 0u, DataType::SizeShift(DataType::Type::kInt32));
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(array);
+  entry->AddInstruction(entry_goto);
+  ManuallyBuildEnvFor(cls, {});
+  ManuallyBuildEnvFor(array, {});
+
+  HInstruction* preheader_goto = new (GetAllocator()) HGoto();
+  preheader->AddInstruction(preheader_goto);
+
+  // loop
+  HPhi* i_phi = new (GetAllocator()) HPhi(GetAllocator(), 0, 0, DataType::Type::kInt32);
+  HInstruction* loop_suspend_check = new (GetAllocator()) HSuspendCheck();
+  HInstruction* loop_cond = new (GetAllocator()) HLessThan(i_phi, n);
+  HIf* loop_if = new (GetAllocator()) HIf(loop_cond);
+  loop->AddPhi(i_phi);
+  loop->AddInstruction(loop_suspend_check);
+  loop->AddInstruction(loop_cond);
+  loop->AddInstruction(loop_if);
+  CHECK(loop_if->IfTrueSuccessor() == body);
+  ManuallyBuildEnvFor(loop_suspend_check, {});
+
+  // body
+  HInstruction* body_set =
+      new (GetAllocator()) HArraySet(array, i_phi, i_phi, DataType::Type::kInt32, /*dex_pc=*/ 0u);
+  HInstruction* body_add = new (GetAllocator()) HAdd(DataType::Type::kInt32, i_phi, c1);
+  HInstruction* body_goto = new (GetAllocator()) HGoto();
+  body->AddInstruction(body_set);
+  body->AddInstruction(body_add);
+  body->AddInstruction(body_goto);
+
+  // i_phi inputs
+  i_phi->AddInput(c0);
+  i_phi->AddInput(body_add);
+
+  // ret
+  HInstruction* ret_sub = new (GetAllocator()) HSub(DataType::Type::kInt32, i_phi, c1);
+  HInstruction* ret_get1 =
+      new (GetAllocator()) HArrayGet(array, ret_sub, DataType::Type::kInt32, /*dex_pc=*/ 0);
+  HInstruction* ret_get2 =
+      new (GetAllocator()) HArrayGet(array, i_phi, DataType::Type::kInt32, /*dex_pc=*/ 0);
+  HInstruction* ret_add = new (GetAllocator()) HAdd(DataType::Type::kInt32, ret_get1, ret_get2);
+  HInstruction* ret_return = new (GetAllocator()) HReturn(ret_add);
+  ret->AddInstruction(ret_sub);
+  ret->AddInstruction(ret_get1);
+  ret->AddInstruction(ret_get2);
+  ret->AddInstruction(ret_add);
+  ret->AddInstruction(ret_return);
+
+  // exit
+  SetupExit(exit);
+
+  graph_->ClearDominanceInformation();
+  graph_->ClearLoopInformation();
+  PerformLSE();
+
+  EXPECT_INS_RETAINED(cls);
+  EXPECT_INS_RETAINED(array);
+  EXPECT_INS_RETAINED(body_set);
+  EXPECT_INS_RETAINED(ret_get1);
+  EXPECT_INS_RETAINED(ret_get2);
+}
+
+// // ENTRY
+// obj = new Obj();
+// // ALL should be kept
+// switch (parameter_value) {
+//   case 1:
+//     // Case1
+//     obj.field = 1;
+//     call_func(obj);
+//     break;
+//   case 2:
+//     // Case2
+//     obj.field = 2;
+//     call_func(obj);
+//     // We don't know what obj.field is now we aren't able to eliminate the read below!
+//     break;
+//   default:
+//     // Case3
+//     // TODO This only happens because of limitations on our LSE which is unable
+//     //      to materialize co-dependent loop and non-loop phis.
+//     // Ideally we'd want to generate
+//     // P1 = PHI[3, loop_val]
+//     // while (test()) {
+//     //   if (test2()) { goto; } else { goto; }
+//     //   loop_val = [P1, 5]
+//     // }
+//     // Currently we aren't able to unfortunately.
+//     obj.field = 3;
+//     while (test()) {
+//       if (test2()) { } else { obj.field = 5; }
+//     }
+//     break;
+// }
+// EXIT
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialUnknownMerge) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "bswitch"},
+                                                  {"bswitch", "case1"},
+                                                  {"bswitch", "case2"},
+                                                  {"bswitch", "case3"},
+                                                  {"case1", "breturn"},
+                                                  {"case2", "breturn"},
+                                                  {"case3", "loop_pre_header"},
+                                                  {"loop_pre_header", "loop_header"},
+                                                  {"loop_header", "loop_body"},
+                                                  {"loop_body", "loop_if_left"},
+                                                  {"loop_body", "loop_if_right"},
+                                                  {"loop_if_left", "loop_end"},
+                                                  {"loop_if_right", "loop_end"},
+                                                  {"loop_end", "loop_header"},
+                                                  {"loop_header", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(bswitch);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(case1);
+  GET_BLOCK(case2);
+  GET_BLOCK(case3);
+
+  GET_BLOCK(loop_pre_header);
+  GET_BLOCK(loop_header);
+  GET_BLOCK(loop_body);
+  GET_BLOCK(loop_if_left);
+  GET_BLOCK(loop_if_right);
+  GET_BLOCK(loop_end);
+#undef GET_BLOCK
+  HInstruction* switch_val = MakeParam(DataType::Type::kInt32);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(entry_goto);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* switch_inst = new (GetAllocator()) HPackedSwitch(0, 2, switch_val);
+  bswitch->AddInstruction(switch_inst);
+
+  HInstruction* write_c1 = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* call_c1 = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_c1 = new (GetAllocator()) HGoto();
+  case1->AddInstruction(write_c1);
+  case1->AddInstruction(call_c1);
+  case1->AddInstruction(goto_c1);
+  call_c1->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_c2 = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* call_c2 = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_c2 = new (GetAllocator()) HGoto();
+  case2->AddInstruction(write_c2);
+  case2->AddInstruction(call_c2);
+  case2->AddInstruction(goto_c2);
+  call_c2->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_c3 = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* goto_c3 = new (GetAllocator()) HGoto();
+  case3->AddInstruction(write_c3);
+  case3->AddInstruction(goto_c3);
+
+  HInstruction* goto_preheader = new (GetAllocator()) HGoto();
+  loop_pre_header->AddInstruction(goto_preheader);
+
+  HInstruction* suspend_check_header = new (GetAllocator()) HSuspendCheck();
+  HInstruction* call_loop_header = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_loop_header = new (GetAllocator()) HIf(call_loop_header);
+  loop_header->AddInstruction(suspend_check_header);
+  loop_header->AddInstruction(call_loop_header);
+  loop_header->AddInstruction(if_loop_header);
+  call_loop_header->CopyEnvironmentFrom(cls->GetEnvironment());
+  suspend_check_header->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_loop_body = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_loop_body = new (GetAllocator()) HIf(call_loop_body);
+  loop_body->AddInstruction(call_loop_body);
+  loop_body->AddInstruction(if_loop_body);
+  call_loop_body->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_loop_left = new (GetAllocator()) HGoto();
+  loop_if_left->AddInstruction(goto_loop_left);
+
+  HInstruction* write_loop_right = MakeIFieldSet(new_inst, c5, MemberOffset(32));
+  HInstruction* goto_loop_right = new (GetAllocator()) HGoto();
+  loop_if_right->AddInstruction(write_loop_right);
+  loop_if_right->AddInstruction(goto_loop_right);
+
+  HInstruction* goto_loop_end = new (GetAllocator()) HGoto();
+  loop_end->AddInstruction(goto_loop_end);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSENoPartial();
+
+  EXPECT_INS_RETAINED(read_bottom);
+  EXPECT_INS_RETAINED(write_c1);
+  EXPECT_INS_RETAINED(write_c2);
+  EXPECT_INS_RETAINED(write_c3);
+  EXPECT_INS_RETAINED(write_loop_right);
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   obj.field = 1;
+//   call_func(obj);
+//   foo_r = obj.field
+// } else {
+//   // TO BE ELIMINATED
+//   obj.field = 2;
+//   // RIGHT
+//   // TO BE ELIMINATED
+//   foo_l = obj.field;
+// }
+// EXIT
+// return PHI(foo_l, foo_r)
+TEST_F(LoadStoreEliminationTest, PartialLoadElimination) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit_REAL",
+                                                 { { "entry", "left" },
+                                                   { "entry", "right" },
+                                                   { "left", "exit" },
+                                                   { "right", "exit" },
+                                                   { "exit", "exit_REAL" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right = blks.Get("right");
+  HBasicBlock* exit = blks.Get("exit");
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_left = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* read_left = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(16));
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(write_left);
+  left->AddInstruction(call_left);
+  left->AddInstruction(read_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(16));
+  HInstruction* read_right = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(16));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(read_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* phi_final = MakePhi({read_left, read_right});
+  HInstruction* return_exit = new (GetAllocator()) HReturn(phi_final);
+  exit->AddPhi(phi_final->AsPhi());
+  exit->AddInstruction(return_exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSE();
+
+  ASSERT_TRUE(IsRemoved(read_right));
+  ASSERT_FALSE(IsRemoved(read_left));
+  ASSERT_FALSE(IsRemoved(phi_final));
+  ASSERT_TRUE(phi_final->GetInputs()[1] == c2);
+  ASSERT_TRUE(phi_final->GetInputs()[0] == read_left);
+  ASSERT_TRUE(IsRemoved(write_right));
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   obj.field = 1;
+//   call_func(obj);
+//   // We don't know what obj.field is now we aren't able to eliminate the read below!
+// } else {
+//   // DO NOT ELIMINATE
+//   obj.field = 2;
+//   // RIGHT
+// }
+// EXIT
+// return obj.field
+// This test runs with partial LSE disabled.
+TEST_F(LoadStoreEliminationTest, PartialLoadPreserved) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit_REAL",
+                                                 { { "entry", "left" },
+                                                   { "entry", "right" },
+                                                   { "left", "exit" },
+                                                   { "right", "exit" },
+                                                   { "exit", "exit_REAL" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right = blks.Get("right");
+  HBasicBlock* exit = blks.Get("exit");
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_left = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(write_left);
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  exit->AddInstruction(read_bottom);
+  exit->AddInstruction(return_exit);
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSENoPartial();
+
+  EXPECT_INS_RETAINED(read_bottom) << *read_bottom;
+  EXPECT_INS_RETAINED(write_right) << *write_right;
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   obj.field = 1;
+//   call_func(obj);
+//   // We don't know what obj.field is now we aren't able to eliminate the read below!
+// } else {
+//   // DO NOT ELIMINATE
+//   if (param2) {
+//     obj.field = 2;
+//   } else {
+//     obj.field = 3;
+//   }
+//   // RIGHT
+// }
+// EXIT
+// return obj.field
+// NB This test is for non-partial LSE flow. Normally the obj.field writes will be removed
+TEST_F(LoadStoreEliminationTest, PartialLoadPreserved2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit_REAL",
+                                                 { { "entry", "left" },
+                                                   { "entry", "right_start" },
+                                                   { "left", "exit" },
+                                                   { "right_start", "right_first" },
+                                                   { "right_start", "right_second" },
+                                                   { "right_first", "right_end" },
+                                                   { "right_second", "right_end" },
+                                                   { "right_end", "exit" },
+                                                   { "exit", "exit_REAL" } }));
+  HBasicBlock* entry = blks.Get("entry");
+  HBasicBlock* left = blks.Get("left");
+  HBasicBlock* right_start = blks.Get("right_start");
+  HBasicBlock* right_first = blks.Get("right_first");
+  HBasicBlock* right_second = blks.Get("right_second");
+  HBasicBlock* right_end = blks.Get("right_end");
+  HBasicBlock* exit = blks.Get("exit");
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* bool_value_2 = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_left = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(write_left);
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* right_if = new (GetAllocator()) HIf(bool_value_2);
+  right_start->AddInstruction(right_if);
+
+  HInstruction* write_right_first = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right_first = new (GetAllocator()) HGoto();
+  right_first->AddInstruction(write_right_first);
+  right_first->AddInstruction(goto_right_first);
+
+  HInstruction* write_right_second = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* goto_right_second = new (GetAllocator()) HGoto();
+  right_second->AddInstruction(write_right_second);
+  right_second->AddInstruction(goto_right_second);
+
+  HInstruction* goto_right_end = new (GetAllocator()) HGoto();
+  right_end->AddInstruction(goto_right_end);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  exit->AddInstruction(read_bottom);
+  exit->AddInstruction(return_exit);
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSENoPartial();
+
+  EXPECT_INS_RETAINED(read_bottom);
+  EXPECT_INS_RETAINED(write_right_first);
+  EXPECT_INS_RETAINED(write_right_second);
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   escape(obj);
+//   obj.field = 1;
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// EXIT
+// ELIMINATE
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialLoadElimination2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* write_left = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(write_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSE();
+
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_RETAINED(write_left);
+  EXPECT_INS_RETAINED(call_left);
+}
+
+template<typename Iter, typename Func>
+typename Iter::value_type FindOrNull(Iter begin, Iter end, Func func) {
+  static_assert(std::is_pointer_v<typename Iter::value_type>);
+  auto it = std::find_if(begin, end, func);
+  if (it == end) {
+    return nullptr;
+  } else {
+    return *it;
+  }
+}
+
+// // ENTRY
+// Obj new_inst = new Obj();
+// new_inst.foo = 12;
+// Obj obj;
+// Obj out;
+// int first;
+// if (param0) {
+//   // ESCAPE_ROUTE
+//   if (param1) {
+//     // LEFT_START
+//     if (param2) {
+//       // LEFT_LEFT
+//       obj = new_inst;
+//     } else {
+//       // LEFT_RIGHT
+//       obj = obj_param;
+//     }
+//     // LEFT_MERGE
+//     // technically the phi is enough to cause an escape but might as well be
+//     // thorough.
+//     // obj = phi[new_inst, param]
+//     escape(obj);
+//     out = obj;
+//   } else {
+//     // RIGHT
+//     out = obj_param;
+//   }
+//   // EXIT
+//   // Can't do anything with this since we don't have good tracking for the heap-locations
+//   // out = phi[param, phi[new_inst, param]]
+//   first = out.foo
+// } else {
+//   new_inst.foo = 15;
+//   first = 13;
+// }
+// // first = phi[out.foo, 13]
+// return first + new_inst.foo;
+TEST_F(LoadStoreEliminationTest, PartialPhiPropagation) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "escape_route"},
+                                                  {"entry", "noescape_route"},
+                                                  {"escape_route", "left"},
+                                                  {"escape_route", "right"},
+                                                  {"left", "left_left"},
+                                                  {"left", "left_right"},
+                                                  {"left_left", "left_merge"},
+                                                  {"left_right", "left_merge"},
+                                                  {"left_merge", "escape_end"},
+                                                  {"right", "escape_end"},
+                                                  {"escape_end", "breturn"},
+                                                  {"noescape_route", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(left_left);
+  GET_BLOCK(left_right);
+  GET_BLOCK(left_merge);
+  GET_BLOCK(escape_end);
+  GET_BLOCK(escape_route);
+  GET_BLOCK(noescape_route);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(escape_end, {left_merge, right});
+  EnsurePredecessorOrder(left_merge, {left_left, left_right});
+  EnsurePredecessorOrder(breturn, {escape_end, noescape_route});
+  HInstruction* param0 = MakeParam(DataType::Type::kBool);
+  HInstruction* param1 = MakeParam(DataType::Type::kBool);
+  HInstruction* param2 = MakeParam(DataType::Type::kBool);
+  HInstruction* obj_param = MakeParam(DataType::Type::kReference);
+  HInstruction* c12 = graph_->GetIntConstant(12);
+  HInstruction* c13 = graph_->GetIntConstant(13);
+  HInstruction* c15 = graph_->GetIntConstant(15);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* store = MakeIFieldSet(new_inst, c12, MemberOffset(32));
+  HInstruction* if_param0 = new (GetAllocator()) HIf(param0);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(store);
+  entry->AddInstruction(if_param0);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* store_noescape = MakeIFieldSet(new_inst, c15, MemberOffset(32));
+  noescape_route->AddInstruction(store_noescape);
+  noescape_route->AddInstruction(new (GetAllocator()) HGoto());
+
+  escape_route->AddInstruction(new (GetAllocator()) HIf(param1));
+
+  HInstruction* if_left = new (GetAllocator()) HIf(param2);
+  left->AddInstruction(if_left);
+
+  HInstruction* goto_left_left = new (GetAllocator()) HGoto();
+  left_left->AddInstruction(goto_left_left);
+
+  HInstruction* goto_left_right = new (GetAllocator()) HGoto();
+  left_right->AddInstruction(goto_left_right);
+
+  HPhi* left_phi = MakePhi({obj_param, new_inst});
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { left_phi });
+  HInstruction* goto_left_merge = new (GetAllocator()) HGoto();
+  left_merge->AddPhi(left_phi);
+  left_merge->AddInstruction(call_left);
+  left_merge->AddInstruction(goto_left_merge);
+  left_phi->SetCanBeNull(true);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(goto_right);
+
+  HPhi* escape_end_phi = MakePhi({left_phi, obj_param});
+  HInstruction* read_escape_end =
+      MakeIFieldGet(escape_end_phi, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* goto_escape_end = new (GetAllocator()) HGoto();
+  escape_end->AddPhi(escape_end_phi);
+  escape_end->AddInstruction(read_escape_end);
+  escape_end->AddInstruction(goto_escape_end);
+
+  HPhi* return_phi = MakePhi({read_escape_end, c13});
+  HInstruction* read_exit = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* add_exit = new (GetAllocator()) HAdd(DataType::Type::kInt32, return_phi, read_exit);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(add_exit);
+  breturn->AddPhi(return_phi);
+  breturn->AddInstruction(read_exit);
+  breturn->AddInstruction(add_exit);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_);
+  std::vector<HPhi*> all_return_phis;
+  std::tie(all_return_phis) = FindAllInstructions<HPhi>(graph_, breturn);
+  EXPECT_EQ(all_return_phis.size(), 3u);
+  EXPECT_INS_RETAINED(return_phi);
+  EXPECT_TRUE(std::find(all_return_phis.begin(), all_return_phis.end(), return_phi) !=
+              all_return_phis.end());
+  HPhi* instance_phi =
+      FindOrNull(all_return_phis.begin(), all_return_phis.end(), [&](HPhi* phi) {
+        return phi != return_phi && phi->GetType() == DataType::Type::kReference;
+      });
+  ASSERT_NE(instance_phi, nullptr);
+  HPhi* value_phi = FindOrNull(all_return_phis.begin(), all_return_phis.end(), [&](HPhi* phi) {
+    return phi != return_phi && phi->GetType() == DataType::Type::kInt32;
+  });
+  ASSERT_NE(value_phi, nullptr);
+  EXPECT_INS_EQ(
+      instance_phi->InputAt(0),
+      FindSingleInstruction<HNewInstance>(graph_, escape_route->GetSinglePredecessor()));
+  // Check materialize block
+  EXPECT_INS_EQ(FindSingleInstruction<HInstanceFieldSet>(
+                    graph_, escape_route->GetSinglePredecessor())
+                    ->InputAt(1),
+                c12);
+
+  EXPECT_INS_EQ(instance_phi->InputAt(1), graph_->GetNullConstant());
+  EXPECT_INS_EQ(value_phi->InputAt(0), graph_->GetIntConstant(0));
+  EXPECT_INS_EQ(value_phi->InputAt(1), c15);
+  EXPECT_INS_REMOVED(store_noescape);
+  EXPECT_INS_EQ(pred_get->GetTarget(), instance_phi);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), value_phi);
+}
+
+// // ENTRY
+// // To be moved
+// // NB Order important. By having alloc and store of obj1 before obj2 that
+// // ensure we'll build the materialization for obj1 first (just due to how
+// // we iterate.)
+// obj1 = new Obj();
+// obj2 = new Obj(); // has env[obj1]
+// // Swap the order of these
+// obj1.foo = param_obj1;
+// obj2.foo = param_obj2;
+// if (param1) {
+//   // LEFT
+//   obj2.foo = obj1;
+//   if (param2) {
+//     // LEFT_LEFT
+//     escape(obj2);
+//   } else {}
+// } else {}
+// return select(param3, obj1.foo, obj2.foo);
+// EXIT
+TEST_P(OrderDependentTestGroup, PredicatedUse) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "left_left"},
+                                                  {"left", "left_right"},
+                                                  {"left_left", "left_end"},
+                                                  {"left_right", "left_end"},
+                                                  {"left_end", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(right);
+  GET_BLOCK(left);
+  GET_BLOCK(left_left);
+  GET_BLOCK(left_right);
+  GET_BLOCK(left_end);
+#undef GET_BLOCK
+  TestOrder order = GetParam();
+  EnsurePredecessorOrder(breturn, {left_end, right});
+  EnsurePredecessorOrder(left_end, {left_left, left_right});
+  HInstruction* param1 = MakeParam(DataType::Type::kBool);
+  HInstruction* param2 = MakeParam(DataType::Type::kBool);
+  HInstruction* param3 = MakeParam(DataType::Type::kBool);
+  HInstruction* param_obj1 = MakeParam(DataType::Type::kReference);
+  HInstruction* param_obj2 = MakeParam(DataType::Type::kReference);
+
+  HInstruction* cls1 = MakeClassLoad();
+  HInstruction* cls2 = MakeClassLoad();
+  HInstruction* new_inst1 = MakeNewInstance(cls1);
+  HInstruction* new_inst2 = MakeNewInstance(cls2);
+  HInstruction* store1 = MakeIFieldSet(new_inst1, param_obj1, MemberOffset(32));
+  HInstruction* store2 = MakeIFieldSet(new_inst2, param_obj2, MemberOffset(32));
+  HInstruction* null_const = graph_->GetNullConstant();
+  HInstruction* if_inst = new (GetAllocator()) HIf(param1);
+  entry->AddInstruction(cls1);
+  entry->AddInstruction(cls2);
+  entry->AddInstruction(new_inst1);
+  entry->AddInstruction(new_inst2);
+  if (order == TestOrder::kSameAsAlloc) {
+    entry->AddInstruction(store1);
+    entry->AddInstruction(store2);
+  } else {
+    entry->AddInstruction(store2);
+    entry->AddInstruction(store1);
+  }
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls1, {});
+  cls2->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst1->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst2->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  // This is the escape of new_inst1
+  HInstruction* store_left = MakeIFieldSet(new_inst2, new_inst1, MemberOffset(32));
+  HInstruction* if_left = new (GetAllocator()) HIf(param2);
+  left->AddInstruction(store_left);
+  left->AddInstruction(if_left);
+
+  HInstruction* call_left_left = MakeInvoke(DataType::Type::kVoid, { new_inst2 });
+  HInstruction* goto_left_left = new (GetAllocator()) HGoto();
+  left_left->AddInstruction(call_left_left);
+  left_left->AddInstruction(goto_left_left);
+  call_left_left->CopyEnvironmentFrom(new_inst2->GetEnvironment());
+
+  left_right->AddInstruction(new (GetAllocator()) HGoto());
+  left_end->AddInstruction(new (GetAllocator()) HGoto());
+
+  right->AddInstruction(new (GetAllocator()) HGoto());
+
+  // Used to distinguish the pred-gets without having to dig through the
+  // multiple phi layers.
+  constexpr uint32_t kRead1DexPc = 10;
+  constexpr uint32_t kRead2DexPc = 20;
+  HInstruction* read1 =
+      MakeIFieldGet(new_inst1, DataType::Type::kReference, MemberOffset(32), kRead1DexPc);
+  read1->SetReferenceTypeInfo(
+      ReferenceTypeInfo::CreateUnchecked(graph_->GetHandleCache()->GetObjectClassHandle(), false));
+  HInstruction* read2 =
+      MakeIFieldGet(new_inst2, DataType::Type::kReference, MemberOffset(32), kRead2DexPc);
+  read2->SetReferenceTypeInfo(
+      ReferenceTypeInfo::CreateUnchecked(graph_->GetHandleCache()->GetObjectClassHandle(), false));
+  HInstruction* sel_return = new (GetAllocator()) HSelect(param3, read1, read2, 0);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(sel_return);
+  breturn->AddInstruction(read1);
+  breturn->AddInstruction(read2);
+  breturn->AddInstruction(sel_return);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_RETAINED(call_left_left);
+  EXPECT_INS_REMOVED(read1);
+  EXPECT_INS_REMOVED(read2);
+  EXPECT_INS_REMOVED(new_inst1);
+  EXPECT_INS_REMOVED(new_inst2);
+  EXPECT_TRUE(new_inst1->GetUses().empty()) << *new_inst1 << " " << new_inst1->GetUses();
+  EXPECT_TRUE(new_inst2->GetUses().empty()) << *new_inst2 << " " << new_inst2->GetUses();
+  EXPECT_INS_RETAINED(sel_return);
+  // Make sure the selector is the same
+  EXPECT_INS_EQ(sel_return->InputAt(2), param3);
+  std::vector<HPredicatedInstanceFieldGet*> pred_gets;
+  std::tie(pred_gets) = FindAllInstructions<HPredicatedInstanceFieldGet>(graph_, breturn);
+  HPredicatedInstanceFieldGet* pred1 = FindOrNull(pred_gets.begin(), pred_gets.end(), [&](auto i) {
+    return i->GetDexPc() == kRead1DexPc;
+  });
+  HPredicatedInstanceFieldGet* pred2 = FindOrNull(pred_gets.begin(), pred_gets.end(), [&](auto i) {
+    return i->GetDexPc() == kRead2DexPc;
+  });
+  ASSERT_NE(pred1, nullptr);
+  ASSERT_NE(pred2, nullptr);
+  EXPECT_INS_EQ(sel_return->InputAt(0), pred2);
+  EXPECT_INS_EQ(sel_return->InputAt(1), pred1);
+  // Check targets
+  EXPECT_TRUE(pred1->GetTarget()->IsPhi()) << pred1->DumpWithArgs();
+  EXPECT_TRUE(pred2->GetTarget()->IsPhi()) << pred2->DumpWithArgs();
+  HInstruction* mat1 = FindSingleInstruction<HNewInstance>(graph_, left->GetSinglePredecessor());
+  HInstruction* mat2 =
+      FindSingleInstruction<HNewInstance>(graph_, left_left->GetSinglePredecessor());
+  EXPECT_INS_EQ(pred1->GetTarget()->InputAt(0), mat1);
+  EXPECT_INS_EQ(pred1->GetTarget()->InputAt(1), null_const);
+  EXPECT_TRUE(pred2->GetTarget()->InputAt(0)->IsPhi()) << pred2->DumpWithArgs();
+  EXPECT_INS_EQ(pred2->GetTarget()->InputAt(0)->InputAt(0), mat2);
+  EXPECT_INS_EQ(pred2->GetTarget()->InputAt(0)->InputAt(1), null_const);
+  EXPECT_INS_EQ(pred2->GetTarget()->InputAt(1), null_const);
+  // Check default values.
+  EXPECT_TRUE(pred1->GetDefaultValue()->IsPhi()) << pred1->DumpWithArgs();
+  EXPECT_TRUE(pred2->GetDefaultValue()->IsPhi()) << pred2->DumpWithArgs();
+  EXPECT_INS_EQ(pred1->GetDefaultValue()->InputAt(0), null_const);
+  EXPECT_INS_EQ(pred1->GetDefaultValue()->InputAt(1), param_obj1);
+  EXPECT_TRUE(pred2->GetDefaultValue()->InputAt(0)->IsPhi()) << pred2->DumpWithArgs();
+  EXPECT_INS_EQ(pred2->GetDefaultValue()->InputAt(0)->InputAt(0), null_const);
+  EXPECT_INS_EQ(pred2->GetDefaultValue()->InputAt(0)->InputAt(1), mat1);
+  EXPECT_INS_EQ(pred2->GetDefaultValue()->InputAt(1), param_obj2);
+}
+
+// // ENTRY
+// // To be moved
+// // NB Order important. By having alloc and store of obj1 before obj2 that
+// // ensure we'll build the materialization for obj1 first (just due to how
+// // we iterate.)
+// obj1 = new Obj();
+// obj.foo = 12;
+// obj2 = new Obj(); // has env[obj1]
+// obj2.foo = 15;
+// if (param1) {
+//   // LEFT
+//   // Need to update env to nullptr
+//   escape(obj1/2);
+//   if (param2) {
+//     // LEFT_LEFT
+//     escape(obj2/1);
+//   } else {}
+// } else {}
+// return obj1.foo + obj2.foo;
+// EXIT
+TEST_P(OrderDependentTestGroup, PredicatedEnvUse) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "left_left"},
+                                                  {"left", "left_right"},
+                                                  {"left_left", "left_end"},
+                                                  {"left_right", "left_end"},
+                                                  {"left_end", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(right);
+  GET_BLOCK(left);
+  GET_BLOCK(left_left);
+  GET_BLOCK(left_right);
+  GET_BLOCK(left_end);
+#undef GET_BLOCK
+  TestOrder order = GetParam();
+  EnsurePredecessorOrder(breturn, {left_end, right});
+  EnsurePredecessorOrder(left_end, {left_left, left_right});
+  HInstruction* param1 = MakeParam(DataType::Type::kBool);
+  HInstruction* param2 = MakeParam(DataType::Type::kBool);
+  HInstruction* c12 = graph_->GetIntConstant(12);
+  HInstruction* c15 = graph_->GetIntConstant(15);
+
+  HInstruction* cls1 = MakeClassLoad();
+  HInstruction* cls2 = MakeClassLoad();
+  HInstruction* new_inst1 = MakeNewInstance(cls1);
+  HInstruction* store1 = MakeIFieldSet(new_inst1, c12, MemberOffset(32));
+  HInstruction* new_inst2 = MakeNewInstance(cls2);
+  HInstruction* store2 = MakeIFieldSet(new_inst2, c15, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(param1);
+  entry->AddInstruction(cls1);
+  entry->AddInstruction(cls2);
+  entry->AddInstruction(new_inst1);
+  entry->AddInstruction(store1);
+  entry->AddInstruction(new_inst2);
+  entry->AddInstruction(store2);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls1, {});
+  cls2->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst1->CopyEnvironmentFrom(cls1->GetEnvironment());
+  ManuallyBuildEnvFor(new_inst2, {new_inst1});
+
+  HInstruction* first_inst = new_inst1;
+  HInstruction* second_inst = new_inst2;
+
+  if (order == TestOrder::kReverseOfAlloc) {
+    std::swap(first_inst, second_inst);
+  }
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { first_inst });
+  HInstruction* if_left = new (GetAllocator()) HIf(param2);
+  left->AddInstruction(call_left);
+  left->AddInstruction(if_left);
+  call_left->CopyEnvironmentFrom(new_inst2->GetEnvironment());
+
+  HInstruction* call_left_left = MakeInvoke(DataType::Type::kVoid, { second_inst });
+  HInstruction* goto_left_left = new (GetAllocator()) HGoto();
+  left_left->AddInstruction(call_left_left);
+  left_left->AddInstruction(goto_left_left);
+  call_left_left->CopyEnvironmentFrom(new_inst2->GetEnvironment());
+
+  left_right->AddInstruction(new (GetAllocator()) HGoto());
+  left_end->AddInstruction(new (GetAllocator()) HGoto());
+
+  right->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* read1 = MakeIFieldGet(new_inst1, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* read2 = MakeIFieldGet(new_inst2, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* add_return = new (GetAllocator()) HAdd(DataType::Type::kInt32, read1, read2);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(add_return);
+  breturn->AddInstruction(read1);
+  breturn->AddInstruction(read2);
+  breturn->AddInstruction(add_return);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HNewInstance* moved_new_inst1;
+  HInstanceFieldSet* moved_set1;
+  HNewInstance* moved_new_inst2;
+  HInstanceFieldSet* moved_set2;
+  HBasicBlock* first_mat_block = left->GetSinglePredecessor();
+  HBasicBlock* second_mat_block = left_left->GetSinglePredecessor();
+  if (order == TestOrder::kReverseOfAlloc) {
+    std::swap(first_mat_block, second_mat_block);
+  }
+  std::tie(moved_new_inst1, moved_set1) =
+      FindSingleInstructions<HNewInstance, HInstanceFieldSet>(graph_, first_mat_block);
+  std::tie(moved_new_inst2, moved_set2) =
+      FindSingleInstructions<HNewInstance, HInstanceFieldSet>(graph_, second_mat_block);
+  std::vector<HPredicatedInstanceFieldGet*> pred_gets;
+  std::vector<HPhi*> phis;
+  std::tie(pred_gets, phis) = FindAllInstructions<HPredicatedInstanceFieldGet, HPhi>(graph_);
+  EXPECT_NE(moved_new_inst1, nullptr);
+  EXPECT_NE(moved_new_inst2, nullptr);
+  EXPECT_NE(moved_set1, nullptr);
+  EXPECT_NE(moved_set2, nullptr);
+  EXPECT_INS_EQ(moved_set1->InputAt(1), c12);
+  EXPECT_INS_EQ(moved_set2->InputAt(1), c15);
+  EXPECT_INS_RETAINED(call_left);
+  EXPECT_INS_RETAINED(call_left_left);
+  EXPECT_INS_REMOVED(store1);
+  EXPECT_INS_REMOVED(store2);
+  EXPECT_INS_REMOVED(read1);
+  EXPECT_INS_REMOVED(read2);
+  EXPECT_INS_EQ(moved_new_inst2->GetEnvironment()->GetInstructionAt(0),
+                order == TestOrder::kSameAsAlloc
+                    ? moved_new_inst1
+                    : static_cast<HInstruction*>(graph_->GetNullConstant()));
+}
+
+// // ENTRY
+// obj1 = new Obj1();
+// obj2 = new Obj2();
+// val1 = 3;
+// val2 = 13;
+// // The exact order the stores are written affects what the order we perform
+// // partial LSE on the values
+// obj1/2.field = val1/2;
+// obj2/1.field = val2/1;
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj1);
+//   escape(obj2);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj1.field = 2;
+//   obj2.field = 12;
+// }
+// EXIT
+// predicated-ELIMINATE
+// return obj1.field + obj2.field
+TEST_P(OrderDependentTestGroup, FieldSetOrderEnv) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  TestOrder order = GetParam();
+  EnsurePredecessorOrder(breturn, {left, right});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c12 = graph_->GetIntConstant(12);
+  HInstruction* c13 = graph_->GetIntConstant(13);
+
+  HInstruction* cls1 = MakeClassLoad();
+  HInstruction* cls2 = MakeClassLoad();
+  HInstruction* new_inst1 = MakeNewInstance(cls1);
+  HInstruction* new_inst2 = MakeNewInstance(cls2);
+  HInstruction* write_entry1 = MakeIFieldSet(new_inst1, c3, MemberOffset(32));
+  HInstruction* write_entry2 = MakeIFieldSet(new_inst2, c13, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls1);
+  entry->AddInstruction(cls2);
+  entry->AddInstruction(new_inst1);
+  entry->AddInstruction(new_inst2);
+  if (order == TestOrder::kSameAsAlloc) {
+    entry->AddInstruction(write_entry1);
+    entry->AddInstruction(write_entry2);
+  } else {
+    entry->AddInstruction(write_entry2);
+    entry->AddInstruction(write_entry1);
+  }
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls1, {});
+  cls2->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst1->CopyEnvironmentFrom(cls1->GetEnvironment());
+  ManuallyBuildEnvFor(new_inst2, {new_inst1});
+
+  HInstruction* call_left1 = MakeInvoke(DataType::Type::kVoid, { new_inst1 });
+  HInstruction* call_left2 = MakeInvoke(DataType::Type::kVoid, { new_inst2 });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left1);
+  left->AddInstruction(call_left2);
+  left->AddInstruction(goto_left);
+  call_left1->CopyEnvironmentFrom(cls1->GetEnvironment());
+  call_left2->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  HInstruction* write_right1 = MakeIFieldSet(new_inst1, c2, MemberOffset(32));
+  HInstruction* write_right2 = MakeIFieldSet(new_inst2, c12, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right1);
+  right->AddInstruction(write_right2);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom1 = MakeIFieldGet(new_inst1, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* read_bottom2 = MakeIFieldGet(new_inst2, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* combine =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, read_bottom1, read_bottom2);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(combine);
+  breturn->AddInstruction(read_bottom1);
+  breturn->AddInstruction(read_bottom2);
+  breturn->AddInstruction(combine);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(write_entry1);
+  EXPECT_INS_REMOVED(write_entry2);
+  EXPECT_INS_REMOVED(read_bottom1);
+  EXPECT_INS_REMOVED(read_bottom2);
+  EXPECT_INS_REMOVED(write_right1);
+  EXPECT_INS_REMOVED(write_right2);
+  EXPECT_INS_RETAINED(call_left1);
+  EXPECT_INS_RETAINED(call_left2);
+  std::vector<HPhi*> merges;
+  std::vector<HPredicatedInstanceFieldGet*> pred_gets;
+  std::vector<HNewInstance*> materializations;
+  std::tie(merges, pred_gets) =
+      FindAllInstructions<HPhi, HPredicatedInstanceFieldGet>(graph_, breturn);
+  std::tie(materializations) = FindAllInstructions<HNewInstance>(graph_);
+  ASSERT_EQ(merges.size(), 4u);
+  ASSERT_EQ(pred_gets.size(), 2u);
+  ASSERT_EQ(materializations.size(), 2u);
+  HPhi* merge_value_return1 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->InputAt(1) == c2;
+  });
+  HPhi* merge_value_return2 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->InputAt(1) == c12;
+  });
+  HNewInstance* mat_alloc1 = FindOrNull(materializations.begin(),
+                                        materializations.end(),
+                                        [&](HNewInstance* n) { return n->InputAt(0) == cls1; });
+  HNewInstance* mat_alloc2 = FindOrNull(materializations.begin(),
+                                        materializations.end(),
+                                        [&](HNewInstance* n) { return n->InputAt(0) == cls2; });
+  ASSERT_NE(mat_alloc1, nullptr);
+  ASSERT_NE(mat_alloc2, nullptr);
+  HPhi* merge_alloc1 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference && p->InputAt(0) == mat_alloc1;
+  });
+  HPhi* merge_alloc2 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference && p->InputAt(0) == mat_alloc2;
+  });
+  ASSERT_NE(merge_alloc1, nullptr);
+  HPredicatedInstanceFieldGet* pred_get1 =
+      FindOrNull(pred_gets.begin(), pred_gets.end(), [&](HPredicatedInstanceFieldGet* pg) {
+        return pg->GetTarget() == merge_alloc1;
+      });
+  ASSERT_NE(merge_alloc2, nullptr);
+  HPredicatedInstanceFieldGet* pred_get2 =
+      FindOrNull(pred_gets.begin(), pred_gets.end(), [&](HPredicatedInstanceFieldGet* pg) {
+        return pg->GetTarget() == merge_alloc2;
+      });
+  ASSERT_NE(merge_value_return1, nullptr);
+  ASSERT_NE(merge_value_return2, nullptr);
+  EXPECT_INS_EQ(merge_alloc1->InputAt(1), graph_->GetNullConstant());
+  EXPECT_INS_EQ(merge_alloc2->InputAt(1), graph_->GetNullConstant());
+  ASSERT_NE(pred_get1, nullptr);
+  EXPECT_INS_EQ(pred_get1->GetTarget(), merge_alloc1);
+  EXPECT_INS_EQ(pred_get1->GetDefaultValue(), merge_value_return1)
+      << " pred-get is: " << *pred_get1;
+  EXPECT_INS_EQ(merge_value_return1->InputAt(0), graph_->GetIntConstant(0))
+      << " merge val is: " << *merge_value_return1;
+  EXPECT_INS_EQ(merge_value_return1->InputAt(1), c2) << " merge val is: " << *merge_value_return1;
+  ASSERT_NE(pred_get2, nullptr);
+  EXPECT_INS_EQ(pred_get2->GetTarget(), merge_alloc2);
+  EXPECT_INS_EQ(pred_get2->GetDefaultValue(), merge_value_return2)
+      << " pred-get is: " << *pred_get2;
+  EXPECT_INS_EQ(merge_value_return2->InputAt(0), graph_->GetIntConstant(0))
+      << " merge val is: " << *merge_value_return1;
+  EXPECT_INS_EQ(merge_value_return2->InputAt(1), c12) << " merge val is: " << *merge_value_return1;
+  EXPECT_INS_EQ(mat_alloc2->GetEnvironment()->GetInstructionAt(0), mat_alloc1);
+}
+
+// // TODO We can compile this better if we are better able to understand lifetimes.
+// // ENTRY
+// obj1 = new Obj1();
+// obj2 = new Obj2();
+// // The exact order the stores are written affects what the order we perform
+// // partial LSE on the values
+// obj{1,2}.var = param_obj;
+// obj{2,1}.var = param_obj;
+// if (param_1) {
+//   // EARLY_RETURN
+//   return;
+// }
+// // escape of obj1
+// obj2.var = obj1;
+// if (param_2) {
+//   // escape of obj2 with a materialization that uses obj1
+//   escape(obj2);
+// }
+// // EXIT
+// return;
+TEST_P(OrderDependentTestGroup, MaterializationMovedUse) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "early_return"},
+                                                  {"early_return", "exit"},
+                                                  {"entry", "escape_1"},
+                                                  {"escape_1", "escape_2"},
+                                                  {"escape_1", "escape_1_crit_break"},
+                                                  {"escape_1_crit_break", "exit"},
+                                                  {"escape_2", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(early_return);
+  GET_BLOCK(escape_1);
+  GET_BLOCK(escape_1_crit_break);
+  GET_BLOCK(escape_2);
+#undef GET_BLOCK
+  TestOrder order = GetParam();
+  HInstruction* param_1 = MakeParam(DataType::Type::kBool);
+  HInstruction* param_2 = MakeParam(DataType::Type::kBool);
+  HInstruction* param_obj = MakeParam(DataType::Type::kReference);
+
+  HInstruction* cls1 = MakeClassLoad();
+  HInstruction* cls2 = MakeClassLoad();
+  HInstruction* new_inst1 = MakeNewInstance(cls1);
+  HInstruction* new_inst2 = MakeNewInstance(cls2);
+  HInstruction* write_entry1 = MakeIFieldSet(new_inst1, param_obj, MemberOffset(32));
+  HInstruction* write_entry2 = MakeIFieldSet(new_inst2, param_obj, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(param_1);
+  entry->AddInstruction(cls1);
+  entry->AddInstruction(cls2);
+  entry->AddInstruction(new_inst1);
+  entry->AddInstruction(new_inst2);
+  if (order == TestOrder::kSameAsAlloc) {
+    entry->AddInstruction(write_entry1);
+    entry->AddInstruction(write_entry2);
+  } else {
+    entry->AddInstruction(write_entry2);
+    entry->AddInstruction(write_entry1);
+  }
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls1, {});
+  cls2->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst1->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst2->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  early_return->AddInstruction(new (GetAllocator()) HReturnVoid());
+
+  HInstruction* escape_1_set = MakeIFieldSet(new_inst2, new_inst1, MemberOffset(32));
+  HInstruction* escape_1_if = new (GetAllocator()) HIf(param_2);
+  escape_1->AddInstruction(escape_1_set);
+  escape_1->AddInstruction(escape_1_if);
+
+  escape_1_crit_break->AddInstruction(new (GetAllocator()) HReturnVoid());
+
+  HInstruction* escape_2_call = MakeInvoke(DataType::Type::kVoid, {new_inst2});
+  HInstruction* escape_2_return = new (GetAllocator()) HReturnVoid();
+  escape_2->AddInstruction(escape_2_call);
+  escape_2->AddInstruction(escape_2_return);
+  escape_2_call->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(new_inst1);
+  EXPECT_INS_REMOVED(new_inst2);
+  EXPECT_INS_REMOVED(write_entry1);
+  EXPECT_INS_REMOVED(write_entry2);
+  EXPECT_INS_REMOVED(escape_1_set);
+  EXPECT_INS_RETAINED(escape_2_call);
+
+  HInstruction* obj1_mat =
+      FindSingleInstruction<HNewInstance>(graph_, escape_1->GetSinglePredecessor());
+  HInstruction* obj1_set =
+      FindSingleInstruction<HInstanceFieldSet>(graph_, escape_1->GetSinglePredecessor());
+  HInstruction* obj2_mat =
+      FindSingleInstruction<HNewInstance>(graph_, escape_2->GetSinglePredecessor());
+  HInstruction* obj2_set =
+      FindSingleInstruction<HInstanceFieldSet>(graph_, escape_2->GetSinglePredecessor());
+  ASSERT_TRUE(obj1_mat != nullptr);
+  ASSERT_TRUE(obj2_mat != nullptr);
+  ASSERT_TRUE(obj1_set != nullptr);
+  ASSERT_TRUE(obj2_set != nullptr);
+  EXPECT_INS_EQ(obj1_set->InputAt(0), obj1_mat);
+  EXPECT_INS_EQ(obj1_set->InputAt(1), param_obj);
+  EXPECT_INS_EQ(obj2_set->InputAt(0), obj2_mat);
+  EXPECT_INS_EQ(obj2_set->InputAt(1), obj1_mat);
+}
+
+INSTANTIATE_TEST_SUITE_P(LoadStoreEliminationTest,
+                         OrderDependentTestGroup,
+                         testing::Values(TestOrder::kSameAsAlloc, TestOrder::kReverseOfAlloc));
+
+// // ENTRY
+// // To be moved
+// obj = new Obj();
+// obj.foo = 12;
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj);
+// } else {}
+// EXIT
+TEST_F(LoadStoreEliminationTest, MovePredicatedAlloc) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"right", "breturn"},
+                                                  {"left", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c12 = graph_->GetIntConstant(12);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* store = MakeIFieldSet(new_inst, c12, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(store);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  right->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* return_exit = new (GetAllocator()) HReturnVoid();
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HNewInstance* moved_new_inst = nullptr;
+  HInstanceFieldSet* moved_set = nullptr;
+  std::tie(moved_new_inst, moved_set) =
+      FindSingleInstructions<HNewInstance, HInstanceFieldSet>(graph_);
+  EXPECT_NE(moved_new_inst, nullptr);
+  EXPECT_NE(moved_set, nullptr);
+  EXPECT_INS_RETAINED(call_left);
+  // store removed or moved.
+  EXPECT_NE(store->GetBlock(), entry);
+  // New-inst removed or moved.
+  EXPECT_NE(new_inst->GetBlock(), entry);
+  EXPECT_INS_EQ(moved_set->InputAt(0), moved_new_inst);
+  EXPECT_INS_EQ(moved_set->InputAt(1), c12);
+}
+
+// // ENTRY
+// // To be moved
+// obj = new Obj();
+// obj.foo = 12;
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj);
+// }
+// EXIT
+// int a = obj.foo;
+// obj.foo = 13;
+// noescape();
+// int b = obj.foo;
+// obj.foo = 14;
+// noescape();
+// int c = obj.foo;
+// obj.foo = 15;
+// noescape();
+// return a + b + c
+TEST_F(LoadStoreEliminationTest, MutiPartialLoadStore) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"right", "breturn"},
+                                                  {"left", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c12 = graph_->GetIntConstant(12);
+  HInstruction* c13 = graph_->GetIntConstant(13);
+  HInstruction* c14 = graph_->GetIntConstant(14);
+  HInstruction* c15 = graph_->GetIntConstant(15);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* store = MakeIFieldSet(new_inst, c12, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(store);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(goto_right);
+
+  HInstruction* a_val = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* a_reset = MakeIFieldSet(new_inst, c13, MemberOffset(32));
+  HInstruction* a_noescape = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* b_val = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* b_reset = MakeIFieldSet(new_inst, c14, MemberOffset(32));
+  HInstruction* b_noescape = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* c_val = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* c_reset = MakeIFieldSet(new_inst, c15, MemberOffset(32));
+  HInstruction* c_noescape = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* add_1_exit = new (GetAllocator()) HAdd(DataType::Type::kInt32, a_val, b_val);
+  HInstruction* add_2_exit = new (GetAllocator()) HAdd(DataType::Type::kInt32, c_val, add_1_exit);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(add_2_exit);
+  breturn->AddInstruction(a_val);
+  breturn->AddInstruction(a_reset);
+  breturn->AddInstruction(a_noescape);
+  breturn->AddInstruction(b_val);
+  breturn->AddInstruction(b_reset);
+  breturn->AddInstruction(b_noescape);
+  breturn->AddInstruction(c_val);
+  breturn->AddInstruction(c_reset);
+  breturn->AddInstruction(c_noescape);
+  breturn->AddInstruction(add_1_exit);
+  breturn->AddInstruction(add_2_exit);
+  breturn->AddInstruction(return_exit);
+  ManuallyBuildEnvFor(a_noescape, {new_inst, a_val});
+  ManuallyBuildEnvFor(b_noescape, {new_inst, a_val, b_val});
+  ManuallyBuildEnvFor(c_noescape, {new_inst, a_val, b_val, c_val});
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HNewInstance* moved_new_inst = nullptr;
+  HInstanceFieldSet* moved_set = nullptr;
+  std::tie(moved_new_inst, moved_set) =
+      FindSingleInstructions<HNewInstance, HInstanceFieldSet>(graph_, left->GetSinglePredecessor());
+  std::vector<HPredicatedInstanceFieldGet*> pred_gets;
+  std::vector<HInstanceFieldSet*> pred_sets;
+  std::vector<HPhi*> return_phis;
+  std::tie(return_phis, pred_gets, pred_sets) =
+      FindAllInstructions<HPhi, HPredicatedInstanceFieldGet, HInstanceFieldSet>(graph_, breturn);
+  ASSERT_EQ(return_phis.size(), 2u);
+  HPhi* inst_phi = return_phis[0];
+  HPhi* val_phi = return_phis[1];
+  if (inst_phi->GetType() != DataType::Type::kReference) {
+    std::swap(inst_phi, val_phi);
+  }
+  ASSERT_NE(moved_new_inst, nullptr);
+  EXPECT_INS_EQ(inst_phi->InputAt(0), moved_new_inst);
+  EXPECT_INS_EQ(inst_phi->InputAt(1), graph_->GetNullConstant());
+  EXPECT_INS_EQ(val_phi->InputAt(0), graph_->GetIntConstant(0));
+  EXPECT_EQ(val_phi->InputAt(1), c12);
+  ASSERT_EQ(pred_gets.size(), 3u);
+  ASSERT_EQ(pred_gets.size(), pred_sets.size());
+  std::vector<HInstruction*> set_values{c13, c14, c15};
+  std::vector<HInstruction*> get_values{val_phi, c13, c14};
+  ASSERT_NE(moved_set, nullptr);
+  EXPECT_INS_EQ(moved_set->InputAt(0), moved_new_inst);
+  EXPECT_INS_EQ(moved_set->InputAt(1), c12);
+  EXPECT_INS_RETAINED(call_left);
+  // store removed or moved.
+  EXPECT_NE(store->GetBlock(), entry);
+  // New-inst removed or moved.
+  EXPECT_NE(new_inst->GetBlock(), entry);
+  for (auto [get, val] : ZipLeft(MakeIterationRange(pred_gets), MakeIterationRange(get_values))) {
+    EXPECT_INS_EQ(get->GetDefaultValue(), val);
+  }
+  for (auto [set, val] : ZipLeft(MakeIterationRange(pred_sets), MakeIterationRange(set_values))) {
+    EXPECT_INS_EQ(set->InputAt(1), val);
+    EXPECT_TRUE(set->GetIsPredicatedSet()) << *set;
+  }
+  EXPECT_INS_RETAINED(a_noescape);
+  EXPECT_INS_RETAINED(b_noescape);
+  EXPECT_INS_RETAINED(c_noescape);
+  EXPECT_INS_EQ(add_1_exit->InputAt(0), pred_gets[0]);
+  EXPECT_INS_EQ(add_1_exit->InputAt(1), pred_gets[1]);
+  EXPECT_INS_EQ(add_2_exit->InputAt(0), pred_gets[2]);
+
+  EXPECT_EQ(a_noescape->GetEnvironment()->Size(), 2u);
+  EXPECT_INS_EQ(a_noescape->GetEnvironment()->GetInstructionAt(0), inst_phi);
+  EXPECT_INS_EQ(a_noescape->GetEnvironment()->GetInstructionAt(1), pred_gets[0]);
+  EXPECT_EQ(b_noescape->GetEnvironment()->Size(), 3u);
+  EXPECT_INS_EQ(b_noescape->GetEnvironment()->GetInstructionAt(0), inst_phi);
+  EXPECT_INS_EQ(b_noescape->GetEnvironment()->GetInstructionAt(1), pred_gets[0]);
+  EXPECT_INS_EQ(b_noescape->GetEnvironment()->GetInstructionAt(2), pred_gets[1]);
+  EXPECT_EQ(c_noescape->GetEnvironment()->Size(), 4u);
+  EXPECT_INS_EQ(c_noescape->GetEnvironment()->GetInstructionAt(0), inst_phi);
+  EXPECT_INS_EQ(c_noescape->GetEnvironment()->GetInstructionAt(1), pred_gets[0]);
+  EXPECT_INS_EQ(c_noescape->GetEnvironment()->GetInstructionAt(2), pred_gets[1]);
+  EXPECT_INS_EQ(c_noescape->GetEnvironment()->GetInstructionAt(3), pred_gets[2]);
+}
+
+// // ENTRY
+// // To be moved
+// obj = new Obj();
+// obj.foo = 12;
+// int a = obj.foo;
+// obj.foo = 13;
+// noescape();
+// int b = obj.foo;
+// obj.foo = 14;
+// noescape();
+// int c = obj.foo;
+// obj.foo = 15;
+// noescape();
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj);
+// }
+// EXIT
+// return a + b + c + obj.foo
+TEST_F(LoadStoreEliminationTest, MutiPartialLoadStore2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  // Need to have an actual entry block since we check env-layout and the way we
+  // add constants would screw this up otherwise.
+  AdjacencyListGraph blks(SetupFromAdjacencyList("start",
+                                                 "exit",
+                                                 {{"start", "entry"},
+                                                  {"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"right", "breturn"},
+                                                  {"left", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(start);
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c12 = graph_->GetIntConstant(12);
+  HInstruction* c13 = graph_->GetIntConstant(13);
+  HInstruction* c14 = graph_->GetIntConstant(14);
+  HInstruction* c15 = graph_->GetIntConstant(15);
+
+  HInstruction* start_suspend = new (GetAllocator()) HSuspendCheck();
+  HInstruction* start_goto = new (GetAllocator()) HGoto();
+
+  start->AddInstruction(start_suspend);
+  start->AddInstruction(start_goto);
+  ManuallyBuildEnvFor(start_suspend, {});
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* store = MakeIFieldSet(new_inst, c12, MemberOffset(32));
+
+  HInstruction* a_val = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* a_reset = MakeIFieldSet(new_inst, c13, MemberOffset(32));
+  HInstruction* a_noescape = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* b_val = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* b_reset = MakeIFieldSet(new_inst, c14, MemberOffset(32));
+  HInstruction* b_noescape = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* c_val = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* c_reset = MakeIFieldSet(new_inst, c15, MemberOffset(32));
+  HInstruction* c_noescape = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(store);
+  entry->AddInstruction(a_val);
+  entry->AddInstruction(a_reset);
+  entry->AddInstruction(a_noescape);
+  entry->AddInstruction(b_val);
+  entry->AddInstruction(b_reset);
+  entry->AddInstruction(b_noescape);
+  entry->AddInstruction(c_val);
+  entry->AddInstruction(c_reset);
+  entry->AddInstruction(c_noescape);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+  ManuallyBuildEnvFor(a_noescape, {new_inst, a_val});
+  ManuallyBuildEnvFor(b_noescape, {new_inst, a_val, b_val});
+  ManuallyBuildEnvFor(c_noescape, {new_inst, a_val, b_val, c_val});
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(c_noescape->GetEnvironment());
+
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(goto_right);
+
+  HInstruction* val_exit = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* add_1_exit = new (GetAllocator()) HAdd(DataType::Type::kInt32, a_val, b_val);
+  HInstruction* add_2_exit = new (GetAllocator()) HAdd(DataType::Type::kInt32, c_val, add_1_exit);
+  HInstruction* add_3_exit =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, val_exit, add_2_exit);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(add_3_exit);
+  breturn->AddInstruction(val_exit);
+  breturn->AddInstruction(add_1_exit);
+  breturn->AddInstruction(add_2_exit);
+  breturn->AddInstruction(add_3_exit);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HNewInstance* moved_new_inst = nullptr;
+  HInstanceFieldSet* moved_set = nullptr;
+  std::tie(moved_new_inst, moved_set) =
+      FindSingleInstructions<HNewInstance, HInstanceFieldSet>(graph_, left->GetSinglePredecessor());
+  std::vector<HPredicatedInstanceFieldGet*> pred_gets;
+  std::vector<HInstanceFieldSet*> pred_sets;
+  std::vector<HPhi*> return_phis;
+  std::tie(return_phis, pred_gets, pred_sets) =
+      FindAllInstructions<HPhi, HPredicatedInstanceFieldGet, HInstanceFieldSet>(graph_, breturn);
+  ASSERT_EQ(return_phis.size(), 2u);
+  HPhi* inst_phi = return_phis[0];
+  HPhi* val_phi = return_phis[1];
+  if (inst_phi->GetType() != DataType::Type::kReference) {
+    std::swap(inst_phi, val_phi);
+  }
+  ASSERT_NE(moved_new_inst, nullptr);
+  EXPECT_INS_EQ(inst_phi->InputAt(0), moved_new_inst);
+  EXPECT_INS_EQ(inst_phi->InputAt(1), graph_->GetNullConstant());
+  EXPECT_INS_EQ(val_phi->InputAt(0), graph_->GetIntConstant(0));
+  EXPECT_INS_EQ(val_phi->InputAt(1), c15);
+  ASSERT_EQ(pred_gets.size(), 1u);
+  ASSERT_EQ(pred_sets.size(), 0u);
+  ASSERT_NE(moved_set, nullptr);
+  EXPECT_INS_EQ(moved_set->InputAt(0), moved_new_inst);
+  EXPECT_INS_EQ(moved_set->InputAt(1), c15);
+  EXPECT_INS_RETAINED(call_left);
+  // store removed or moved.
+  EXPECT_NE(store->GetBlock(), entry);
+  // New-inst removed or moved.
+  EXPECT_NE(new_inst->GetBlock(), entry);
+  EXPECT_INS_REMOVED(a_val);
+  EXPECT_INS_REMOVED(b_val);
+  EXPECT_INS_REMOVED(c_val);
+  EXPECT_INS_RETAINED(a_noescape);
+  EXPECT_INS_RETAINED(b_noescape);
+  EXPECT_INS_RETAINED(c_noescape);
+  EXPECT_INS_EQ(add_1_exit->InputAt(0), c12);
+  EXPECT_INS_EQ(add_1_exit->InputAt(1), c13);
+  EXPECT_INS_EQ(add_2_exit->InputAt(0), c14);
+  EXPECT_INS_EQ(add_2_exit->InputAt(1), add_1_exit);
+  EXPECT_INS_EQ(add_3_exit->InputAt(0), pred_gets[0]);
+  EXPECT_INS_EQ(pred_gets[0]->GetDefaultValue(), val_phi);
+  EXPECT_INS_EQ(add_3_exit->InputAt(1), add_2_exit);
+  EXPECT_EQ(a_noescape->GetEnvironment()->Size(), 2u);
+  EXPECT_INS_EQ(a_noescape->GetEnvironment()->GetInstructionAt(0), graph_->GetNullConstant());
+  EXPECT_INS_EQ(a_noescape->GetEnvironment()->GetInstructionAt(1), c12);
+  EXPECT_EQ(b_noescape->GetEnvironment()->Size(), 3u);
+  EXPECT_INS_EQ(b_noescape->GetEnvironment()->GetInstructionAt(0), graph_->GetNullConstant());
+  EXPECT_INS_EQ(b_noescape->GetEnvironment()->GetInstructionAt(1), c12);
+  EXPECT_INS_EQ(b_noescape->GetEnvironment()->GetInstructionAt(2), c13);
+  EXPECT_EQ(c_noescape->GetEnvironment()->Size(), 4u);
+  EXPECT_INS_EQ(c_noescape->GetEnvironment()->GetInstructionAt(0), graph_->GetNullConstant());
+  EXPECT_INS_EQ(c_noescape->GetEnvironment()->GetInstructionAt(1), c12);
+  EXPECT_INS_EQ(c_noescape->GetEnvironment()->GetInstructionAt(2), c13);
+  EXPECT_INS_EQ(c_noescape->GetEnvironment()->GetInstructionAt(3), c14);
+}
+
+// // ENTRY
+// // To be moved
+// obj = new Obj();
+// // Transforms required for creation non-trivial and unimportant
+// if (parameter_value) {
+//   obj.foo = 10
+// } else {
+//   obj.foo = 12;
+// }
+// if (parameter_value_2) {
+//   escape(obj);
+// }
+// EXIT
+TEST_F(LoadStoreEliminationTest, MovePredicatedAlloc2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left_set"},
+                                                  {"entry", "right_set"},
+                                                  {"left_set", "merge_crit_break"},
+                                                  {"right_set", "merge_crit_break"},
+                                                  {"merge_crit_break", "merge"},
+                                                  {"merge", "escape"},
+                                                  {"escape", "breturn"},
+                                                  {"merge", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left_set);
+  GET_BLOCK(right_set);
+  GET_BLOCK(merge);
+  GET_BLOCK(merge_crit_break);
+  GET_BLOCK(escape);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {merge, escape});
+  EnsurePredecessorOrder(merge_crit_break, {left_set, right_set});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* bool_value_2 = MakeParam(DataType::Type::kBool);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+  HInstruction* c12 = graph_->GetIntConstant(12);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* store_left = MakeIFieldSet(new_inst, c10, MemberOffset(32));
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left_set->AddInstruction(store_left);
+  left_set->AddInstruction(goto_left);
+
+  HInstruction* store_right = MakeIFieldSet(new_inst, c12, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right_set->AddInstruction(store_right);
+  right_set->AddInstruction(goto_right);
+
+  merge_crit_break->AddInstruction(new (GetAllocator()) HGoto());
+  HInstruction* if_merge = new (GetAllocator()) HIf(bool_value_2);
+  merge->AddInstruction(if_merge);
+
+  HInstruction* escape_instruction = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* escape_goto = new (GetAllocator()) HGoto();
+  escape->AddInstruction(escape_instruction);
+  escape->AddInstruction(escape_goto);
+  escape_instruction->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* return_exit = new (GetAllocator()) HReturnVoid();
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HNewInstance* moved_new_inst;
+  HInstanceFieldSet* moved_set;
+  std::tie(moved_new_inst, moved_set) =
+      FindSingleInstructions<HNewInstance, HInstanceFieldSet>(graph_);
+  HPhi* merge_phi = FindSingleInstruction<HPhi>(graph_, merge_crit_break);
+  HPhi* alloc_phi = FindSingleInstruction<HPhi>(graph_, breturn);
+  EXPECT_INS_EQ(moved_new_inst, moved_set->InputAt(0));
+  ASSERT_NE(alloc_phi, nullptr);
+  EXPECT_EQ(alloc_phi->InputAt(0), graph_->GetNullConstant())
+      << alloc_phi->GetBlock()->GetPredecessors()[0]->GetBlockId() << " " << *alloc_phi;
+  EXPECT_TRUE(alloc_phi->InputAt(1)->IsNewInstance()) << *alloc_phi;
+  ASSERT_NE(merge_phi, nullptr);
+  EXPECT_EQ(merge_phi->InputCount(), 2u);
+  EXPECT_INS_EQ(merge_phi->InputAt(0), c10);
+  EXPECT_INS_EQ(merge_phi->InputAt(1), c12);
+  EXPECT_TRUE(merge_phi->GetUses().HasExactlyOneElement());
+  EXPECT_INS_EQ(merge_phi->GetUses().front().GetUser(), moved_set);
+  EXPECT_INS_RETAINED(escape_instruction);
+  EXPECT_INS_EQ(escape_instruction->InputAt(0), moved_new_inst);
+  // store removed or moved.
+  EXPECT_NE(store_left->GetBlock(), left_set);
+  EXPECT_NE(store_right->GetBlock(), left_set);
+  // New-inst removed or moved.
+  EXPECT_NE(new_inst->GetBlock(), entry);
+}
+
+// // ENTRY
+// // To be moved
+// obj = new Obj();
+// switch(args) {
+//   default:
+//     return obj.a;
+//   case b:
+//     obj.a = 5; break;
+//   case c:
+//     obj.b = 4; break;
+// }
+// escape(obj);
+// return obj.a;
+// EXIT
+TEST_F(LoadStoreEliminationTest, MovePredicatedAlloc3) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "early_return"},
+                                                  {"entry", "set_one"},
+                                                  {"entry", "set_two"},
+                                                  {"early_return", "exit"},
+                                                  {"set_one", "escape"},
+                                                  {"set_two", "escape"},
+                                                  {"escape", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(escape);
+  GET_BLOCK(early_return);
+  GET_BLOCK(set_one);
+  GET_BLOCK(set_two);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(escape, {set_one, set_two});
+  HInstruction* int_val = MakeParam(DataType::Type::kInt32);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* c4 = graph_->GetIntConstant(4);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* switch_inst = new (GetAllocator()) HPackedSwitch(0, 2, int_val);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(switch_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* store_one = MakeIFieldSet(new_inst, c4, MemberOffset(32));
+  HInstruction* goto_one = new (GetAllocator()) HGoto();
+  set_one->AddInstruction(store_one);
+  set_one->AddInstruction(goto_one);
+
+  HInstruction* store_two = MakeIFieldSet(new_inst, c5, MemberOffset(32));
+  HInstruction* goto_two = new (GetAllocator()) HGoto();
+  set_two->AddInstruction(store_two);
+  set_two->AddInstruction(goto_two);
+
+  HInstruction* read_early = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_early = new (GetAllocator()) HReturn(read_early);
+  early_return->AddInstruction(read_early);
+  early_return->AddInstruction(return_early);
+
+  HInstruction* escape_instruction = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* read_escape = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_escape = new (GetAllocator()) HReturn(read_escape);
+  escape->AddInstruction(escape_instruction);
+  escape->AddInstruction(read_escape);
+  escape->AddInstruction(return_escape);
+  escape_instruction->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  // Each escaping switch path gets its own materialization block.
+  // Blocks:
+  //   early_return(5) -> [exit(4)]
+  //   entry(3) -> [early_return(5), <Unnamed>(9), <Unnamed>(10)]
+  //   escape(8) -> [exit(4)]
+  //   exit(4) -> []
+  //   set_one(6) -> [escape(8)]
+  //   set_two(7) -> [escape(8)]
+  //   <Unnamed>(10) -> [set_two(7)]
+  //   <Unnamed>(9) -> [set_one(6)]
+  HBasicBlock* materialize_one = set_one->GetSinglePredecessor();
+  HBasicBlock* materialize_two = set_two->GetSinglePredecessor();
+  HNewInstance* materialization_ins_one =
+      FindSingleInstruction<HNewInstance>(graph_, materialize_one);
+  HNewInstance* materialization_ins_two =
+      FindSingleInstruction<HNewInstance>(graph_, materialize_two);
+  HPhi* new_phi = FindSingleInstruction<HPhi>(graph_, escape);
+  EXPECT_NE(materialization_ins_one, nullptr);
+  EXPECT_NE(materialization_ins_two, nullptr);
+  EXPECT_EQ(materialization_ins_one, new_phi->InputAt(0))
+      << *materialization_ins_one << " vs " << *new_phi;
+  EXPECT_EQ(materialization_ins_two, new_phi->InputAt(1))
+      << *materialization_ins_two << " vs " << *new_phi;
+
+  EXPECT_INS_RETAINED(escape_instruction);
+  EXPECT_INS_RETAINED(read_escape);
+  EXPECT_EQ(read_escape->InputAt(0), new_phi) << *new_phi << " vs " << *read_escape->InputAt(0);
+  EXPECT_EQ(store_one->InputAt(0), materialization_ins_one);
+  EXPECT_EQ(store_two->InputAt(0), materialization_ins_two);
+  EXPECT_EQ(escape_instruction->InputAt(0), new_phi);
+  EXPECT_INS_REMOVED(read_early);
+  EXPECT_EQ(return_early->InputAt(0), c0);
+}
+
+// // ENTRY
+// // To be moved
+// obj = new Obj();
+// switch(args) {
+//   case a:
+//     // set_one_and_escape
+//     obj.a = 5;
+//     escape(obj);
+//     // FALLTHROUGH
+//   case c:
+//     // set_two
+//     obj.a = 4; break;
+//   default:
+//     return obj.a;
+// }
+// escape(obj);
+// return obj.a;
+// EXIT
+TEST_F(LoadStoreEliminationTest, MovePredicatedAlloc4) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  // Break the critical edge between entry and set_two with the
+  // set_two_critical_break node. Graph simplification would do this for us if
+  // we didn't do it manually. This way we have a nice-name for debugging and
+  // testing.
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "early_return"},
+                                                  {"entry", "set_one_and_escape"},
+                                                  {"entry", "set_two_critical_break"},
+                                                  {"set_two_critical_break", "set_two"},
+                                                  {"early_return", "exit"},
+                                                  {"set_one_and_escape", "set_two"},
+                                                  {"set_two", "escape"},
+                                                  {"escape", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(escape);
+  GET_BLOCK(early_return);
+  GET_BLOCK(set_one_and_escape);
+  GET_BLOCK(set_two);
+  GET_BLOCK(set_two_critical_break);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(set_two, {set_one_and_escape, set_two_critical_break});
+  HInstruction* int_val = MakeParam(DataType::Type::kInt32);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* c4 = graph_->GetIntConstant(4);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* switch_inst = new (GetAllocator()) HPackedSwitch(0, 2, int_val);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(switch_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* store_one = MakeIFieldSet(new_inst, c4, MemberOffset(32));
+  HInstruction* escape_one = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_one = new (GetAllocator()) HGoto();
+  set_one_and_escape->AddInstruction(store_one);
+  set_one_and_escape->AddInstruction(escape_one);
+  set_one_and_escape->AddInstruction(goto_one);
+  escape_one->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_crit_break = new (GetAllocator()) HGoto();
+  set_two_critical_break->AddInstruction(goto_crit_break);
+
+  HInstruction* store_two = MakeIFieldSet(new_inst, c5, MemberOffset(32));
+  HInstruction* goto_two = new (GetAllocator()) HGoto();
+  set_two->AddInstruction(store_two);
+  set_two->AddInstruction(goto_two);
+
+  HInstruction* read_early = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_early = new (GetAllocator()) HReturn(read_early);
+  early_return->AddInstruction(read_early);
+  early_return->AddInstruction(return_early);
+
+  HInstruction* escape_instruction = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* read_escape = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_escape = new (GetAllocator()) HReturn(read_escape);
+  escape->AddInstruction(escape_instruction);
+  escape->AddInstruction(read_escape);
+  escape->AddInstruction(return_escape);
+  escape_instruction->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(read_early);
+  EXPECT_EQ(return_early->InputAt(0), c0);
+  // Each escaping switch path gets its own materialization block.
+  // Blocks:
+  //   early_return(5) -> [exit(4)]
+  //   entry(3) -> [early_return(5), <Unnamed>(10), <Unnamed>(11)]
+  //   escape(9) -> [exit(4)]
+  //   exit(4) -> []
+  //   set_one_and_escape(6) -> [set_two(8)]
+  //   set_two(8) -> [escape(9)]
+  //   set_two_critical_break(7) -> [set_two(8)]
+  //   <Unnamed>(11) -> [set_two_critical_break(7)]
+  //   <Unnamed>(10) -> [set_one_and_escape(6)]
+  HBasicBlock* materialize_one = set_one_and_escape->GetSinglePredecessor();
+  HBasicBlock* materialize_two = set_two_critical_break->GetSinglePredecessor();
+  HNewInstance* materialization_ins_one =
+      FindSingleInstruction<HNewInstance>(graph_, materialize_one);
+  HNewInstance* materialization_ins_two =
+      FindSingleInstruction<HNewInstance>(graph_, materialize_two);
+  HPhi* new_phi = FindSingleInstruction<HPhi>(graph_, set_two);
+  ASSERT_NE(new_phi, nullptr);
+  ASSERT_NE(materialization_ins_one, nullptr);
+  ASSERT_NE(materialization_ins_two, nullptr);
+  EXPECT_INS_EQ(materialization_ins_one, new_phi->InputAt(0));
+  EXPECT_INS_EQ(materialization_ins_two, new_phi->InputAt(1));
+
+  EXPECT_INS_EQ(store_one->InputAt(0), materialization_ins_one);
+  EXPECT_INS_EQ(store_two->InputAt(0), new_phi) << *store_two << " vs " << *new_phi;
+  EXPECT_INS_EQ(escape_instruction->InputAt(0), new_phi);
+  EXPECT_INS_RETAINED(escape_one);
+  EXPECT_INS_EQ(escape_one->InputAt(0), materialization_ins_one);
+  EXPECT_INS_RETAINED(escape_instruction);
+  EXPECT_INS_RETAINED(read_escape);
+  EXPECT_EQ(read_escape->InputAt(0), new_phi) << *new_phi << " vs " << *read_escape->InputAt(0);
+}
+
+// // ENTRY
+// // To be moved
+// obj = new Obj();
+// switch(args) {
+//   case a:
+//     // set_one
+//     obj.a = 5;
+//     // nb passthrough
+//   case c:
+//     // set_two_and_escape
+//     obj.a += 4;
+//     escape(obj);
+//     break;
+//   default:
+//     obj.a = 10;
+// }
+// return obj.a;
+// EXIT
+TEST_F(LoadStoreEliminationTest, MovePredicatedAlloc5) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  // Break the critical edge between entry and set_two with the
+  // set_two_critical_break node. Graph simplification would do this for us if
+  // we didn't do it manually. This way we have a nice-name for debugging and
+  // testing.
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "set_noescape"},
+                                                  {"entry", "set_one"},
+                                                  {"entry", "set_two_critical_break"},
+                                                  {"set_two_critical_break", "set_two_and_escape"},
+                                                  {"set_noescape", "breturn"},
+                                                  {"set_one", "set_two_and_escape"},
+                                                  {"set_two_and_escape", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(set_noescape);
+  GET_BLOCK(set_one);
+  GET_BLOCK(set_two_and_escape);
+  GET_BLOCK(set_two_critical_break);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(set_two_and_escape, {set_one, set_two_critical_break});
+  EnsurePredecessorOrder(breturn, {set_two_and_escape, set_noescape});
+  HInstruction* int_val = MakeParam(DataType::Type::kInt32);
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* c4 = graph_->GetIntConstant(4);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* switch_inst = new (GetAllocator()) HPackedSwitch(0, 2, int_val);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(switch_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* store_one = MakeIFieldSet(new_inst, c5, MemberOffset(32));
+  HInstruction* goto_one = new (GetAllocator()) HGoto();
+  set_one->AddInstruction(store_one);
+  set_one->AddInstruction(goto_one);
+
+  HInstruction* goto_crit_break = new (GetAllocator()) HGoto();
+  set_two_critical_break->AddInstruction(goto_crit_break);
+
+  HInstruction* get_two = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* add_two = new (GetAllocator()) HAdd(DataType::Type::kInt32, get_two, c4);
+  HInstruction* store_two = MakeIFieldSet(new_inst, add_two, MemberOffset(32));
+  HInstruction* escape_two = MakeInvoke(DataType::Type::kVoid, {new_inst});
+  HInstruction* goto_two = new (GetAllocator()) HGoto();
+  set_two_and_escape->AddInstruction(get_two);
+  set_two_and_escape->AddInstruction(add_two);
+  set_two_and_escape->AddInstruction(store_two);
+  set_two_and_escape->AddInstruction(escape_two);
+  set_two_and_escape->AddInstruction(goto_two);
+  escape_two->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* store_noescape = MakeIFieldSet(new_inst, c10, MemberOffset(32));
+  HInstruction* goto_noescape = new (GetAllocator()) HGoto();
+  set_noescape->AddInstruction(store_noescape);
+  set_noescape->AddInstruction(goto_noescape);
+
+  HInstruction* read_breturn = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_breturn = new (GetAllocator()) HReturn(read_breturn);
+  breturn->AddInstruction(read_breturn);
+  breturn->AddInstruction(return_breturn);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  // Normal LSE can get rid of these two.
+  EXPECT_INS_REMOVED(store_one);
+  EXPECT_INS_REMOVED(get_two);
+  EXPECT_INS_RETAINED(add_two);
+  EXPECT_TRUE(add_two->InputAt(0)->IsPhi());
+  EXPECT_INS_EQ(add_two->InputAt(0)->InputAt(0), c5);
+  EXPECT_INS_EQ(add_two->InputAt(0)->InputAt(1), c0);
+  EXPECT_INS_EQ(add_two->InputAt(1), c4);
+
+  HBasicBlock* materialize_one = set_one->GetSinglePredecessor();
+  HBasicBlock* materialize_two = set_two_critical_break->GetSinglePredecessor();
+  HNewInstance* materialization_ins_one =
+      FindSingleInstruction<HNewInstance>(graph_, materialize_one);
+  HNewInstance* materialization_ins_two =
+      FindSingleInstruction<HNewInstance>(graph_, materialize_two);
+  std::vector<HPhi*> phis;
+  std::tie(phis) = FindAllInstructions<HPhi>(graph_, set_two_and_escape);
+  HPhi* new_phi = FindOrNull(
+      phis.begin(), phis.end(), [&](auto p) { return p->GetType() == DataType::Type::kReference; });
+  ASSERT_NE(new_phi, nullptr);
+  ASSERT_NE(materialization_ins_one, nullptr);
+  ASSERT_NE(materialization_ins_two, nullptr);
+  EXPECT_INS_EQ(materialization_ins_one, new_phi->InputAt(0));
+  EXPECT_INS_EQ(materialization_ins_two, new_phi->InputAt(1));
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  EXPECT_TRUE(pred_get->GetTarget()->IsPhi());
+  EXPECT_INS_EQ(pred_get->GetTarget()->InputAt(0), new_phi);
+  EXPECT_INS_EQ(pred_get->GetTarget()->InputAt(1), graph_->GetNullConstant());
+
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(0), c0);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(1), c10);
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   obj.field = 1;
+//   escape(obj);
+//   return obj.field;
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+//   return obj.field;
+// }
+// EXIT
+TEST_F(LoadStoreEliminationTest, PartialLoadElimination3) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList(
+      "entry",
+      "exit",
+      {{"entry", "left"}, {"entry", "right"}, {"left", "exit"}, {"right", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_left = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* read_left = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_left = new (GetAllocator()) HReturn(read_left);
+  left->AddInstruction(write_left);
+  left->AddInstruction(call_left);
+  left->AddInstruction(read_left);
+  left->AddInstruction(return_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* read_right = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_right = new (GetAllocator()) HReturn(read_right);
+  right->AddInstruction(write_right);
+  right->AddInstruction(read_right);
+  right->AddInstruction(return_right);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSE();
+
+  EXPECT_INS_REMOVED(read_right);
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_RETAINED(write_left);
+  EXPECT_INS_RETAINED(call_left);
+  EXPECT_INS_RETAINED(read_left);
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   obj.field = 1;
+//   while (true) {
+//     bool esc = escape(obj);
+//     // DO NOT ELIMINATE
+//     obj.field = 3;
+//     if (esc) break;
+//   }
+//   // ELIMINATE.
+//   return obj.field;
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+//   return obj.field;
+// }
+// EXIT
+TEST_F(LoadStoreEliminationTest, PartialLoadElimination4) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "entry_post"},
+                                                  {"entry_post", "right"},
+                                                  {"right", "exit"},
+                                                  {"entry_post", "left_pre"},
+                                                  {"left_pre", "left_loop"},
+                                                  {"left_loop", "left_loop"},
+                                                  {"left_loop", "left_finish"},
+                                                  {"left_finish", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(entry_post);
+  GET_BLOCK(exit);
+  GET_BLOCK(left_pre);
+  GET_BLOCK(left_loop);
+  GET_BLOCK(left_finish);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  // Left-loops first successor is the break.
+  if (left_loop->GetSuccessors()[0] != left_finish) {
+    left_loop->SwapSuccessors();
+  }
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* goto_entry = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(goto_entry);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry_post->AddInstruction(if_inst);
+
+  HInstruction* write_left_pre = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* goto_left_pre = new (GetAllocator()) HGoto();
+  left_pre->AddInstruction(write_left_pre);
+  left_pre->AddInstruction(goto_left_pre);
+
+  HInstruction* suspend_left_loop = new (GetAllocator()) HSuspendCheck();
+  HInstruction* call_left_loop = MakeInvoke(DataType::Type::kBool, { new_inst });
+  HInstruction* write_left_loop = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_left_loop = new (GetAllocator()) HIf(call_left_loop);
+  left_loop->AddInstruction(suspend_left_loop);
+  left_loop->AddInstruction(call_left_loop);
+  left_loop->AddInstruction(write_left_loop);
+  left_loop->AddInstruction(if_left_loop);
+  suspend_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
+  call_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* read_left_end = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_left_end = new (GetAllocator()) HReturn(read_left_end);
+  left_finish->AddInstruction(read_left_end);
+  left_finish->AddInstruction(return_left_end);
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* read_right = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_right = new (GetAllocator()) HReturn(read_right);
+  right->AddInstruction(write_right);
+  right->AddInstruction(read_right);
+  right->AddInstruction(return_right);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSE();
+
+  EXPECT_INS_RETAINED(write_left_pre);
+  EXPECT_INS_REMOVED(read_right);
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_RETAINED(write_left_loop);
+  EXPECT_INS_RETAINED(call_left_loop);
+  EXPECT_INS_REMOVED(read_left_end);
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   escape(obj);
+//   obj.field = 1;
+// } else {
+//   // RIGHT
+//   // obj hasn't escaped so it's invisible.
+//   // ELIMINATE
+//   obj.field = 2;
+//   noescape();
+// }
+// EXIT
+// ELIMINATE
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialLoadElimination5) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* write_left = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(write_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* call_right = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(call_right);
+  right->AddInstruction(goto_right);
+  call_right->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSE();
+
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_RETAINED(write_left);
+  EXPECT_INS_RETAINED(call_left);
+  EXPECT_INS_RETAINED(call_right);
+}
+
+// // ENTRY
+// obj = new Obj();
+// // Eliminate this one. Object hasn't escaped yet so it's safe.
+// obj.field = 3;
+// noescape();
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   obj.field = 5;
+//   escape(obj);
+//   obj.field = 1;
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// EXIT
+// ELIMINATE
+// return obj.fid
+TEST_F(LoadStoreEliminationTest, PartialLoadElimination6) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* call_entry = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(call_entry);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+  call_entry->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_left_start = MakeIFieldSet(new_inst, c5, MemberOffset(32));
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* write_left = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(write_left_start);
+  left->AddInstruction(call_left);
+  left->AddInstruction(write_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSE();
+
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_REMOVED(write_entry);
+  EXPECT_INS_RETAINED(write_left_start);
+  EXPECT_INS_RETAINED(write_left);
+  EXPECT_INS_RETAINED(call_left);
+  EXPECT_INS_RETAINED(call_entry);
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   obj.field = 1;
+//   while (true) {
+//     bool esc = escape(obj);
+//     if (esc) break;
+//     // DO NOT ELIMINATE
+//     obj.field = 3;
+//   }
+// } else {
+//   // RIGHT
+//   // DO NOT ELIMINATE
+//   obj.field = 2;
+// }
+// // DO NOT ELIMINATE
+// return obj.field;
+// EXIT
+TEST_F(LoadStoreEliminationTest, PartialLoadPreserved3) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "entry_post"},
+                                                  {"entry_post", "right"},
+                                                  {"right", "return_block"},
+                                                  {"entry_post", "left_pre"},
+                                                  {"left_pre", "left_loop"},
+                                                  {"left_loop", "left_loop_post"},
+                                                  {"left_loop_post", "left_loop"},
+                                                  {"left_loop", "return_block"},
+                                                  {"return_block", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(entry_post);
+  GET_BLOCK(exit);
+  GET_BLOCK(return_block);
+  GET_BLOCK(left_pre);
+  GET_BLOCK(left_loop);
+  GET_BLOCK(left_loop_post);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  // Left-loops first successor is the break.
+  if (left_loop->GetSuccessors()[0] != return_block) {
+    left_loop->SwapSuccessors();
+  }
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* goto_entry = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(goto_entry);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry_post->AddInstruction(if_inst);
+
+  HInstruction* write_left_pre = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* goto_left_pre = new (GetAllocator()) HGoto();
+  left_pre->AddInstruction(write_left_pre);
+  left_pre->AddInstruction(goto_left_pre);
+
+  HInstruction* suspend_left_loop = new (GetAllocator()) HSuspendCheck();
+  HInstruction* call_left_loop = MakeInvoke(DataType::Type::kBool, { new_inst });
+  HInstruction* if_left_loop = new (GetAllocator()) HIf(call_left_loop);
+  left_loop->AddInstruction(suspend_left_loop);
+  left_loop->AddInstruction(call_left_loop);
+  left_loop->AddInstruction(if_left_loop);
+  suspend_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
+  call_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_left_loop = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* goto_left_loop = new (GetAllocator()) HGoto();
+  left_loop_post->AddInstruction(write_left_loop);
+  left_loop_post->AddInstruction(goto_left_loop);
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_return = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_final = new (GetAllocator()) HReturn(read_return);
+  return_block->AddInstruction(read_return);
+  return_block->AddInstruction(return_final);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSENoPartial();
+
+  EXPECT_INS_RETAINED(write_left_pre) << *write_left_pre;
+  EXPECT_INS_RETAINED(read_return) << *read_return;
+  EXPECT_INS_RETAINED(write_right) << *write_right;
+  EXPECT_INS_RETAINED(write_left_loop) << *write_left_loop;
+  EXPECT_INS_RETAINED(call_left_loop) << *call_left_loop;
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   // ELIMINATE (not visible since always overridden by obj.field = 3)
+//   obj.field = 1;
+//   while (true) {
+//     bool stop = should_stop();
+//     // DO NOT ELIMINATE (visible by read at end)
+//     obj.field = 3;
+//     if (stop) break;
+//   }
+// } else {
+//   // RIGHT
+//   // DO NOT ELIMINATE
+//   obj.field = 2;
+//   escape(obj);
+// }
+// // DO NOT ELIMINATE
+// return obj.field;
+// EXIT
+TEST_F(LoadStoreEliminationTest, PartialLoadPreserved4) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "entry_post"},
+                                                  {"entry_post", "right"},
+                                                  {"right", "return_block"},
+                                                  {"entry_post", "left_pre"},
+                                                  {"left_pre", "left_loop"},
+                                                  {"left_loop", "left_loop"},
+                                                  {"left_loop", "return_block"},
+                                                  {"return_block", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(entry_post);
+  GET_BLOCK(exit);
+  GET_BLOCK(return_block);
+  GET_BLOCK(left_pre);
+  GET_BLOCK(left_loop);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  // Left-loops first successor is the break.
+  if (left_loop->GetSuccessors()[0] != return_block) {
+    left_loop->SwapSuccessors();
+  }
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* goto_entry = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(goto_entry);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry_post->AddInstruction(if_inst);
+
+  HInstruction* write_left_pre = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* goto_left_pre = new (GetAllocator()) HGoto();
+  left_pre->AddInstruction(write_left_pre);
+  left_pre->AddInstruction(goto_left_pre);
+
+  HInstruction* suspend_left_loop = new (GetAllocator()) HSuspendCheck();
+  HInstruction* call_left_loop = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* write_left_loop = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_left_loop = new (GetAllocator()) HIf(call_left_loop);
+  left_loop->AddInstruction(suspend_left_loop);
+  left_loop->AddInstruction(call_left_loop);
+  left_loop->AddInstruction(write_left_loop);
+  left_loop->AddInstruction(if_left_loop);
+  suspend_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
+  call_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* call_right = MakeInvoke(DataType::Type::kBool, { new_inst });
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(call_right);
+  right->AddInstruction(goto_right);
+  call_right->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* read_return = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_final = new (GetAllocator()) HReturn(read_return);
+  return_block->AddInstruction(read_return);
+  return_block->AddInstruction(return_final);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSENoPartial();
+
+  EXPECT_INS_RETAINED(read_return);
+  EXPECT_INS_RETAINED(write_right);
+  EXPECT_INS_RETAINED(write_left_loop);
+  EXPECT_INS_RETAINED(call_left_loop);
+  EXPECT_INS_REMOVED(write_left_pre);
+  EXPECT_INS_RETAINED(call_right);
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   escape(obj);
+//   obj.field = 1;
+//   // obj has already escaped so can't use field = 1 for value
+//   noescape();
+// } else {
+//   // RIGHT
+//   // obj is needed for read since we don't know what the left value is
+//   // DO NOT ELIMINATE
+//   obj.field = 2;
+//   noescape();
+// }
+// EXIT
+// ELIMINATE
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialLoadPreserved5) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* write_left = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* call2_left = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(write_left);
+  left->AddInstruction(call2_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+  call2_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* call_right = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(call_right);
+  right->AddInstruction(goto_right);
+  call_right->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  PerformLSENoPartial();
+
+  EXPECT_INS_RETAINED(read_bottom);
+  EXPECT_INS_RETAINED(write_right);
+  EXPECT_INS_RETAINED(write_left);
+  EXPECT_INS_RETAINED(call_left);
+  EXPECT_INS_RETAINED(call_right);
+}
+
+// // ENTRY
+// obj = new Obj();
+// DO NOT ELIMINATE. Kept by escape.
+// obj.field = 3;
+// noescape();
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   escape(obj);
+//   obj.field = 1;
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// EXIT
+// ELIMINATE
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialLoadPreserved6) {
+  CreateGraph();
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* call_entry = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(call_entry);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+  call_entry->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* write_left = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(write_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSENoPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_RETAINED(write_entry);
+  EXPECT_INS_RETAINED(write_left);
+  EXPECT_INS_RETAINED(call_left);
+  EXPECT_INS_RETAINED(call_entry);
+}
+
+// // ENTRY
+// // MOVED TO MATERIALIZATION BLOCK
+// obj = new Obj();
+// ELIMINATE, moved to materialization block. Kept by escape.
+// obj.field = 3;
+// // Make sure this graph isn't broken
+// if (obj ==/!= (STATIC.VALUE|obj|null)) {
+//   // partial_BLOCK
+//   // REMOVE (either from unreachable or normal PHI creation)
+//   obj.field = 4;
+// }
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   escape(obj);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// EXIT
+// PREDICATED GET
+// return obj.field
+TEST_P(PartialComparisonTestGroup, PartialComparisonBeforeCohort) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "critical_break"},
+                                                  {"entry", "partial"},
+                                                  {"partial", "merge"},
+                                                  {"critical_break", "merge"},
+                                                  {"merge", "left"},
+                                                  {"merge", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(merge);
+  GET_BLOCK(partial);
+  GET_BLOCK(critical_break);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c4 = graph_->GetIntConstant(4);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  ComparisonInstructions cmp_instructions = GetComparisonInstructions(new_inst);
+  HInstruction* if_inst = new (GetAllocator()) HIf(cmp_instructions.cmp_);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  cmp_instructions.AddSetup(entry);
+  entry->AddInstruction(cmp_instructions.cmp_);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  cmp_instructions.AddEnvironment(cls->GetEnvironment());
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_partial = MakeIFieldSet(new_inst, c4, MemberOffset(32));
+  HInstruction* goto_partial = new (GetAllocator()) HGoto();
+  partial->AddInstruction(write_partial);
+  partial->AddInstruction(goto_partial);
+
+  HInstruction* goto_crit_break = new (GetAllocator()) HGoto();
+  critical_break->AddInstruction(goto_crit_break);
+
+  HInstruction* if_merge = new (GetAllocator()) HIf(bool_value);
+  merge->AddInstruction(if_merge);
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  std::vector<HPhi*> merges;
+  HPredicatedInstanceFieldGet* pred_get;
+  HInstanceFieldSet* init_set;
+  std::tie(pred_get, init_set) =
+      FindSingleInstructions<HPredicatedInstanceFieldGet, HInstanceFieldSet>(graph_);
+  std::tie(merges) = FindAllInstructions<HPhi>(graph_);
+  ASSERT_EQ(merges.size(), 3u);
+  HPhi* merge_value_return = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->GetBlock() == breturn;
+  });
+  HPhi* merge_value_top = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->GetBlock() != breturn;
+  });
+  HPhi* merge_alloc = FindOrNull(merges.begin(), merges.end(), [](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference;
+  });
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_entry);
+  EXPECT_INS_REMOVED(write_partial);
+  EXPECT_INS_RETAINED(call_left);
+  CheckFinalInstruction(if_inst->InputAt(0), ComparisonPlacement::kBeforeEscape);
+  EXPECT_INS_EQ(init_set->InputAt(1), merge_value_top);
+  EXPECT_INS_EQ(pred_get->GetTarget(), merge_alloc);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), merge_value_return);
+}
+
+// // ENTRY
+// // MOVED TO MATERIALIZATION BLOCK
+// obj = new Obj();
+// ELIMINATE, moved to materialization block. Kept by escape.
+// obj.field = 3;
+// // Make sure this graph isn't broken
+// if (parameter_value) {
+//   if (obj ==/!= (STATIC.VALUE|obj|null)) {
+//     // partial_BLOCK
+//     obj.field = 4;
+//   }
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   escape(obj);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// EXIT
+// PREDICATED GET
+// return obj.field
+TEST_P(PartialComparisonTestGroup, PartialComparisonInCohortBeforeEscape) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left_begin"},
+                                                  {"left_begin", "partial"},
+                                                  {"left_begin", "left_crit_break"},
+                                                  {"left_crit_break", "left"},
+                                                  {"partial", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(partial);
+  GET_BLOCK(left_begin);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(left_crit_break);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(left, {left_crit_break, partial});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c4 = graph_->GetIntConstant(4);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  ComparisonInstructions cmp_instructions = GetComparisonInstructions(new_inst);
+  HInstruction* if_left_begin = new (GetAllocator()) HIf(cmp_instructions.cmp_);
+  cmp_instructions.AddSetup(left_begin);
+  left_begin->AddInstruction(cmp_instructions.cmp_);
+  left_begin->AddInstruction(if_left_begin);
+  cmp_instructions.AddEnvironment(cls->GetEnvironment());
+
+  left_crit_break->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* write_partial = MakeIFieldSet(new_inst, c4, MemberOffset(32));
+  HInstruction* goto_partial = new (GetAllocator()) HGoto();
+  partial->AddInstruction(write_partial);
+  partial->AddInstruction(goto_partial);
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  std::vector<HPhi*> merges;
+  HInstanceFieldSet* init_set =
+      FindSingleInstruction<HInstanceFieldSet>(graph_, left_begin->GetSinglePredecessor());
+  HInstanceFieldSet* partial_set = FindSingleInstruction<HInstanceFieldSet>(graph_, partial);
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_);
+  std::tie(merges) = FindAllInstructions<HPhi>(graph_);
+  ASSERT_EQ(merges.size(), 2u);
+  HPhi* merge_value_return = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32;
+  });
+  HPhi* merge_alloc = FindOrNull(merges.begin(), merges.end(), [](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference;
+  });
+  EXPECT_EQ(merge_value_return->GetBlock(), breturn)
+      << blks.GetName(merge_value_return->GetBlock());
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_entry);
+  EXPECT_INS_RETAINED(write_partial);
+  EXPECT_INS_RETAINED(call_left);
+  CheckFinalInstruction(if_left_begin->InputAt(0), ComparisonPlacement::kInEscape);
+  EXPECT_INS_EQ(init_set->InputAt(1), c3);
+  EXPECT_INS_EQ(partial_set->InputAt(0), init_set->InputAt(0));
+  EXPECT_INS_EQ(partial_set->InputAt(1), c4);
+  EXPECT_INS_EQ(pred_get->GetTarget(), merge_alloc);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), merge_value_return);
+}
+
+// // ENTRY
+// // MOVED TO MATERIALIZATION BLOCK
+// obj = new Obj();
+// ELIMINATE, moved to materialization block. Kept by escape.
+// obj.field = 3;
+// // Make sure this graph isn't broken
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   escape(obj);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// if (obj ==/!= (STATIC.VALUE|obj|null)) {
+//   // partial_BLOCK
+//   obj.field = 4;
+// }
+// EXIT
+// PREDICATED GET
+// return obj.field
+TEST_P(PartialComparisonTestGroup, PartialComparisonAfterCohort) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "merge"},
+                                                  {"right", "merge"},
+                                                  {"merge", "critical_break"},
+                                                  {"critical_break", "breturn"},
+                                                  {"merge", "partial"},
+                                                  {"partial", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(partial);
+  GET_BLOCK(critical_break);
+  GET_BLOCK(merge);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {critical_break, partial});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c4 = graph_->GetIntConstant(4);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  ComparisonInstructions cmp_instructions = GetComparisonInstructions(new_inst);
+  HInstruction* if_merge = new (GetAllocator()) HIf(cmp_instructions.cmp_);
+  cmp_instructions.AddSetup(merge);
+  merge->AddInstruction(cmp_instructions.cmp_);
+  merge->AddInstruction(if_merge);
+  cmp_instructions.AddEnvironment(cls->GetEnvironment());
+
+  HInstanceFieldSet* write_partial = MakeIFieldSet(new_inst, c4, MemberOffset(32));
+  HInstruction* goto_partial = new (GetAllocator()) HGoto();
+  partial->AddInstruction(write_partial);
+  partial->AddInstruction(goto_partial);
+
+  HInstruction* goto_crit_break = new (GetAllocator()) HGoto();
+  critical_break->AddInstruction(goto_crit_break);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  std::vector<HPhi*> merges;
+  HInstanceFieldSet* init_set =
+      FindSingleInstruction<HInstanceFieldSet>(graph_, left->GetSinglePredecessor());
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_);
+  std::tie(merges) = FindAllInstructions<HPhi>(graph_);
+  ASSERT_EQ(merges.size(), 3u);
+  HPhi* merge_value_return = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->GetBlock() == breturn;
+  });
+  HPhi* merge_alloc = FindOrNull(merges.begin(), merges.end(), [](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference;
+  });
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_entry);
+  EXPECT_INS_RETAINED(write_partial);
+  EXPECT_TRUE(write_partial->GetIsPredicatedSet());
+  EXPECT_INS_RETAINED(call_left);
+  CheckFinalInstruction(if_merge->InputAt(0), ComparisonPlacement::kAfterEscape);
+  EXPECT_INS_EQ(init_set->InputAt(1), c3);
+  ASSERT_TRUE(write_partial->InputAt(0)->IsPhi());
+  EXPECT_INS_EQ(write_partial->InputAt(0)->AsPhi()->InputAt(0), init_set->InputAt(0));
+  EXPECT_INS_EQ(write_partial->InputAt(1), c4);
+  EXPECT_INS_EQ(pred_get->GetTarget(), merge_alloc);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), merge_value_return);
+}
+
+// // ENTRY
+// // MOVED TO MATERIALIZATION BLOCK
+// obj = new Obj();
+// ELIMINATE, moved to materialization block. Kept by escape.
+// obj.field = 3;
+// // Make sure this graph isn't broken
+// if (parameter_value) {
+//   // LEFT
+//   // DO NOT ELIMINATE
+//   escape(obj);
+//   if (obj ==/!= (STATIC.VALUE|obj|null)) {
+//     // partial_BLOCK
+//     obj.field = 4;
+//   }
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// EXIT
+// PREDICATED GET
+// return obj.field
+TEST_P(PartialComparisonTestGroup, PartialComparisonInCohortAfterEscape) {
+  PartialComparisonKind kind = GetParam();
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"left", "partial"},
+                                                  {"partial", "left_end"},
+                                                  {"left", "left_crit_break"},
+                                                  {"left_crit_break", "left_end"},
+                                                  {"left_end", "breturn"},
+                                                  {"entry", "right"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(partial);
+  GET_BLOCK(left_end);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(left_crit_break);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c4 = graph_->GetIntConstant(4);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  ComparisonInstructions cmp_instructions = GetComparisonInstructions(new_inst);
+  HInstruction* if_left = new (GetAllocator()) HIf(cmp_instructions.cmp_);
+  left->AddInstruction(call_left);
+  cmp_instructions.AddSetup(left);
+  left->AddInstruction(cmp_instructions.cmp_);
+  left->AddInstruction(if_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+  cmp_instructions.AddEnvironment(cls->GetEnvironment());
+  if (if_left->AsIf()->IfTrueSuccessor() != partial) {
+    left->SwapSuccessors();
+  }
+
+  HInstruction* write_partial = MakeIFieldSet(new_inst, c4, MemberOffset(32));
+  HInstruction* goto_partial = new (GetAllocator()) HGoto();
+  partial->AddInstruction(write_partial);
+  partial->AddInstruction(goto_partial);
+
+  HInstruction* goto_left_crit_break = new (GetAllocator()) HGoto();
+  left_crit_break->AddInstruction(goto_left_crit_break);
+
+  HInstruction* goto_left_end = new (GetAllocator()) HGoto();
+  left_end->AddInstruction(goto_left_end);
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  std::vector<HPhi*> merges;
+  std::vector<HInstanceFieldSet*> sets;
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_);
+  std::tie(merges, sets) = FindAllInstructions<HPhi, HInstanceFieldSet>(graph_);
+  ASSERT_EQ(merges.size(), 2u);
+  ASSERT_EQ(sets.size(), 2u);
+  HInstanceFieldSet* init_set = FindOrNull(sets.begin(), sets.end(), [&](HInstanceFieldSet* s) {
+    return s->GetBlock()->GetSingleSuccessor() == left;
+  });
+  EXPECT_INS_EQ(init_set->InputAt(1), c3);
+  HPhi* merge_value_return = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->GetBlock() == breturn;
+  });
+  HPhi* merge_alloc = FindOrNull(merges.begin(), merges.end(), [](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference;
+  });
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_entry);
+  if (kind.IsPossiblyTrue()) {
+    EXPECT_INS_RETAINED(write_partial);
+    EXPECT_TRUE(std::find(sets.begin(), sets.end(), write_partial) != sets.end());
+  }
+  EXPECT_INS_RETAINED(call_left);
+  CheckFinalInstruction(if_left->InputAt(0), ComparisonPlacement::kInEscape);
+  EXPECT_INS_EQ(pred_get->GetTarget(), merge_alloc);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), merge_value_return);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    LoadStoreEliminationTest,
+    PartialComparisonTestGroup,
+    testing::Values(PartialComparisonKind{PartialComparisonKind::Type::kEquals,
+                                          PartialComparisonKind::Target::kNull,
+                                          PartialComparisonKind::Position::kLeft},
+                    PartialComparisonKind{PartialComparisonKind::Type::kEquals,
+                                          PartialComparisonKind::Target::kNull,
+                                          PartialComparisonKind::Position::kRight},
+                    PartialComparisonKind{PartialComparisonKind::Type::kEquals,
+                                          PartialComparisonKind::Target::kValue,
+                                          PartialComparisonKind::Position::kLeft},
+                    PartialComparisonKind{PartialComparisonKind::Type::kEquals,
+                                          PartialComparisonKind::Target::kValue,
+                                          PartialComparisonKind::Position::kRight},
+                    PartialComparisonKind{PartialComparisonKind::Type::kEquals,
+                                          PartialComparisonKind::Target::kSelf,
+                                          PartialComparisonKind::Position::kLeft},
+                    PartialComparisonKind{PartialComparisonKind::Type::kNotEquals,
+                                          PartialComparisonKind::Target::kNull,
+                                          PartialComparisonKind::Position::kLeft},
+                    PartialComparisonKind{PartialComparisonKind::Type::kNotEquals,
+                                          PartialComparisonKind::Target::kNull,
+                                          PartialComparisonKind::Position::kRight},
+                    PartialComparisonKind{PartialComparisonKind::Type::kNotEquals,
+                                          PartialComparisonKind::Target::kSelf,
+                                          PartialComparisonKind::Position::kLeft},
+                    PartialComparisonKind{PartialComparisonKind::Type::kNotEquals,
+                                          PartialComparisonKind::Target::kValue,
+                                          PartialComparisonKind::Position::kLeft},
+                    PartialComparisonKind{PartialComparisonKind::Type::kNotEquals,
+                                          PartialComparisonKind::Target::kValue,
+                                          PartialComparisonKind::Position::kRight}));
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// EXIT
+// predicated-ELIMINATE
+// obj.field = 3;
+TEST_F(LoadStoreEliminationTest, PredicatedStore1) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  InitGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* null_const = graph_->GetNullConstant();
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* write_bottom = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturnVoid();
+  breturn->AddInstruction(write_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_RETAINED(write_bottom);
+  EXPECT_TRUE(write_bottom->AsInstanceFieldSet()->GetIsPredicatedSet());
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_RETAINED(call_left);
+  HPhi* merge_alloc = FindSingleInstruction<HPhi>(graph_, breturn);
+  ASSERT_NE(merge_alloc, nullptr);
+  EXPECT_TRUE(merge_alloc->InputAt(0)->IsNewInstance()) << *merge_alloc;
+  EXPECT_EQ(merge_alloc->InputAt(0)->InputAt(0), cls) << *merge_alloc << " cls? " << *cls;
+  EXPECT_EQ(merge_alloc->InputAt(1), null_const);
+}
+
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// // MERGE
+// if (second_param) {
+//   // NON_ESCAPE
+//   obj.field = 1;
+//   noescape();
+// }
+// EXIT
+// predicated-ELIMINATE
+// obj.field = 4;
+TEST_F(LoadStoreEliminationTest, PredicatedStore2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "merge"},
+                                                  {"right", "merge"},
+                                                  {"merge", "non_escape"},
+                                                  {"non_escape", "breturn"},
+                                                  {"merge", "merge_crit_break"},
+                                                  {"merge_crit_break", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(merge);
+  GET_BLOCK(merge_crit_break);
+  GET_BLOCK(non_escape);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(merge, {left, right});
+  EnsurePredecessorOrder(breturn, {merge_crit_break, non_escape});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* bool_value2 = MakeParam(DataType::Type::kBool);
+  HInstruction* null_const = graph_->GetNullConstant();
+  HInstruction* c1 = graph_->GetIntConstant(3);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c4 = graph_->GetIntConstant(4);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* merge_if = new (GetAllocator()) HIf(bool_value2);
+  merge->AddInstruction(merge_if);
+
+  merge_crit_break->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* write_non_escape = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* non_escape_call = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* non_escape_goto = new (GetAllocator()) HGoto();
+  non_escape->AddInstruction(write_non_escape);
+  non_escape->AddInstruction(non_escape_call);
+  non_escape->AddInstruction(non_escape_goto);
+  non_escape_call->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_bottom = MakeIFieldSet(new_inst, c4, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturnVoid();
+  breturn->AddInstruction(write_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_RETAINED(write_bottom);
+  EXPECT_TRUE(write_bottom->AsInstanceFieldSet()->GetIsPredicatedSet()) << *write_bottom;
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_RETAINED(call_left);
+  HInstanceFieldSet* pred_set = FindSingleInstruction<HInstanceFieldSet>(graph_, breturn);
+  HPhi* merge_alloc = FindSingleInstruction<HPhi>(graph_);
+  ASSERT_NE(merge_alloc, nullptr);
+  EXPECT_TRUE(merge_alloc->InputAt(0)->IsNewInstance()) << *merge_alloc;
+  EXPECT_INS_EQ(merge_alloc->InputAt(0)->InputAt(0), cls) << " phi is: " << *merge_alloc;
+  EXPECT_INS_EQ(merge_alloc->InputAt(1), null_const);
+  ASSERT_NE(pred_set, nullptr);
+  EXPECT_TRUE(pred_set->GetIsPredicatedSet()) << *pred_set;
+  EXPECT_INS_EQ(pred_set->InputAt(0), merge_alloc);
+}
+
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// EXIT
+// predicated-ELIMINATE
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PredicatedLoad1) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* null_const = graph_->GetNullConstant();
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_RETAINED(call_left);
+  std::vector<HPhi*> merges;
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  std::tie(merges) = FindAllInstructions<HPhi>(graph_, breturn);
+  ASSERT_EQ(merges.size(), 2u);
+  HPhi* merge_value_return = FindOrNull(
+      merges.begin(), merges.end(), [](HPhi* p) { return p->GetType() == DataType::Type::kInt32; });
+  HPhi* merge_alloc = FindOrNull(merges.begin(), merges.end(), [](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference;
+  });
+  ASSERT_NE(merge_alloc, nullptr);
+  EXPECT_TRUE(merge_alloc->InputAt(0)->IsNewInstance()) << *merge_alloc;
+  EXPECT_EQ(merge_alloc->InputAt(0)->InputAt(0), cls) << *merge_alloc << " cls? " << *cls;
+  EXPECT_EQ(merge_alloc->InputAt(1), null_const);
+  ASSERT_NE(pred_get, nullptr);
+  EXPECT_INS_EQ(pred_get->GetTarget(), merge_alloc);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), merge_value_return) << " pred-get is: " << *pred_get;
+  EXPECT_INS_EQ(merge_value_return->InputAt(0), graph_->GetIntConstant(0))
+      << " merge val is: " << *merge_value_return;
+  EXPECT_INS_EQ(merge_value_return->InputAt(1), c2) << " merge val is: " << *merge_value_return;
+}
+
+// // ENTRY
+// obj1 = new Obj1();
+// obj2 = new Obj2();
+// obj1.field = 3;
+// obj2.field = 13;
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj1);
+//   escape(obj2);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj1.field = 2;
+//   obj2.field = 12;
+// }
+// EXIT
+// predicated-ELIMINATE
+// return obj1.field + obj2.field
+TEST_F(LoadStoreEliminationTest, MultiPredicatedLoad1) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c12 = graph_->GetIntConstant(12);
+  HInstruction* c13 = graph_->GetIntConstant(13);
+
+  HInstruction* cls1 = MakeClassLoad();
+  HInstruction* cls2 = MakeClassLoad();
+  HInstruction* new_inst1 = MakeNewInstance(cls1);
+  HInstruction* new_inst2 = MakeNewInstance(cls2);
+  HInstruction* write_entry1 = MakeIFieldSet(new_inst1, c3, MemberOffset(32));
+  HInstruction* write_entry2 = MakeIFieldSet(new_inst2, c13, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls1);
+  entry->AddInstruction(cls2);
+  entry->AddInstruction(new_inst1);
+  entry->AddInstruction(new_inst2);
+  entry->AddInstruction(write_entry1);
+  entry->AddInstruction(write_entry2);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls1, {});
+  cls2->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst1->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst2->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  HInstruction* call_left1 = MakeInvoke(DataType::Type::kVoid, { new_inst1 });
+  HInstruction* call_left2 = MakeInvoke(DataType::Type::kVoid, { new_inst2 });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left1);
+  left->AddInstruction(call_left2);
+  left->AddInstruction(goto_left);
+  call_left1->CopyEnvironmentFrom(cls1->GetEnvironment());
+  call_left2->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  HInstruction* write_right1 = MakeIFieldSet(new_inst1, c2, MemberOffset(32));
+  HInstruction* write_right2 = MakeIFieldSet(new_inst2, c12, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right1);
+  right->AddInstruction(write_right2);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom1 = MakeIFieldGet(new_inst1, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* read_bottom2 = MakeIFieldGet(new_inst2, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* combine =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, read_bottom1, read_bottom2);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(combine);
+  breturn->AddInstruction(read_bottom1);
+  breturn->AddInstruction(read_bottom2);
+  breturn->AddInstruction(combine);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(read_bottom1);
+  EXPECT_INS_REMOVED(read_bottom2);
+  EXPECT_INS_REMOVED(write_right1);
+  EXPECT_INS_REMOVED(write_right2);
+  EXPECT_INS_RETAINED(call_left1);
+  EXPECT_INS_RETAINED(call_left2);
+  std::vector<HPhi*> merges;
+  std::vector<HPredicatedInstanceFieldGet*> pred_gets;
+  std::tie(merges, pred_gets) =
+      FindAllInstructions<HPhi, HPredicatedInstanceFieldGet>(graph_, breturn);
+  ASSERT_EQ(merges.size(), 4u);
+  ASSERT_EQ(pred_gets.size(), 2u);
+  HPhi* merge_value_return1 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->InputAt(1) == c2;
+  });
+  HPhi* merge_value_return2 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->InputAt(1) == c12;
+  });
+  HPhi* merge_alloc1 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference &&
+           p->InputAt(0)->IsNewInstance() &&
+           p->InputAt(0)->InputAt(0) == cls1;
+  });
+  HPhi* merge_alloc2 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference &&
+           p->InputAt(0)->IsNewInstance() &&
+           p->InputAt(0)->InputAt(0) == cls2;
+  });
+  ASSERT_NE(merge_alloc1, nullptr);
+  ASSERT_NE(merge_alloc2, nullptr);
+  EXPECT_EQ(merge_alloc1->InputAt(1), graph_->GetNullConstant());
+  EXPECT_EQ(merge_alloc2->InputAt(1), graph_->GetNullConstant());
+  HPredicatedInstanceFieldGet* pred_get1 =
+      FindOrNull(pred_gets.begin(), pred_gets.end(), [&](HPredicatedInstanceFieldGet* pg) {
+        return pg->GetTarget() == merge_alloc1;
+      });
+  HPredicatedInstanceFieldGet* pred_get2 =
+      FindOrNull(pred_gets.begin(), pred_gets.end(), [&](HPredicatedInstanceFieldGet* pg) {
+        return pg->GetTarget() == merge_alloc2;
+      });
+  ASSERT_NE(pred_get1, nullptr);
+  EXPECT_INS_EQ(pred_get1->GetTarget(), merge_alloc1);
+  EXPECT_INS_EQ(pred_get1->GetDefaultValue(), merge_value_return1)
+      << " pred-get is: " << *pred_get1;
+  EXPECT_INS_EQ(merge_value_return1->InputAt(0), graph_->GetIntConstant(0))
+      << " merge val is: " << *merge_value_return1;
+  EXPECT_INS_EQ(merge_value_return1->InputAt(1), c2) << " merge val is: " << *merge_value_return1;
+  ASSERT_NE(pred_get2, nullptr);
+  EXPECT_INS_EQ(pred_get2->GetTarget(), merge_alloc2);
+  EXPECT_INS_EQ(pred_get2->GetDefaultValue(), merge_value_return2)
+      << " pred-get is: " << *pred_get2;
+  EXPECT_INS_EQ(merge_value_return2->InputAt(0), graph_->GetIntConstant(0))
+      << " merge val is: " << *merge_value_return1;
+  EXPECT_INS_EQ(merge_value_return2->InputAt(1), c12) << " merge val is: " << *merge_value_return1;
+}
+
+// // ENTRY
+// obj1 = new Obj1();
+// obj2 = new Obj2();
+// obj1.field = 3;
+// obj2.field = 13;
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj1);
+//   // ELIMINATE
+//   obj2.field = 12;
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj1.field = 2;
+//   escape(obj2);
+// }
+// EXIT
+// predicated-ELIMINATE
+// return obj1.field + obj2.field
+TEST_F(LoadStoreEliminationTest, MultiPredicatedLoad2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c12 = graph_->GetIntConstant(12);
+  HInstruction* c13 = graph_->GetIntConstant(13);
+
+  HInstruction* cls1 = MakeClassLoad();
+  HInstruction* cls2 = MakeClassLoad();
+  HInstruction* new_inst1 = MakeNewInstance(cls1);
+  HInstruction* new_inst2 = MakeNewInstance(cls2);
+  HInstruction* write_entry1 = MakeIFieldSet(new_inst1, c3, MemberOffset(32));
+  HInstruction* write_entry2 = MakeIFieldSet(new_inst2, c13, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls1);
+  entry->AddInstruction(cls2);
+  entry->AddInstruction(new_inst1);
+  entry->AddInstruction(new_inst2);
+  entry->AddInstruction(write_entry1);
+  entry->AddInstruction(write_entry2);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls1, {});
+  cls2->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst1->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst2->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  HInstruction* call_left1 = MakeInvoke(DataType::Type::kVoid, { new_inst1 });
+  HInstruction* write_left2 = MakeIFieldSet(new_inst2, c12, MemberOffset(32));
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left1);
+  left->AddInstruction(write_left2);
+  left->AddInstruction(goto_left);
+  call_left1->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  HInstruction* write_right1 = MakeIFieldSet(new_inst1, c2, MemberOffset(32));
+  HInstruction* call_right2 = MakeInvoke(DataType::Type::kVoid, { new_inst2 });
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right1);
+  right->AddInstruction(call_right2);
+  right->AddInstruction(goto_right);
+  call_right2->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  HInstruction* read_bottom1 = MakeIFieldGet(new_inst1, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* read_bottom2 = MakeIFieldGet(new_inst2, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* combine =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, read_bottom1, read_bottom2);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(combine);
+  breturn->AddInstruction(read_bottom1);
+  breturn->AddInstruction(read_bottom2);
+  breturn->AddInstruction(combine);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(read_bottom1);
+  EXPECT_INS_REMOVED(read_bottom2);
+  EXPECT_INS_REMOVED(write_right1);
+  EXPECT_INS_REMOVED(write_left2);
+  EXPECT_INS_RETAINED(call_left1);
+  EXPECT_INS_RETAINED(call_right2);
+  std::vector<HPhi*> merges;
+  std::vector<HPredicatedInstanceFieldGet*> pred_gets;
+  std::tie(merges, pred_gets) =
+      FindAllInstructions<HPhi, HPredicatedInstanceFieldGet>(graph_, breturn);
+  ASSERT_EQ(merges.size(), 4u);
+  ASSERT_EQ(pred_gets.size(), 2u);
+  HPhi* merge_value_return1 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->InputAt(1) == c2;
+  });
+  HPhi* merge_value_return2 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->InputAt(0) == c12;
+  });
+  HPhi* merge_alloc1 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference && p->InputAt(1)->IsNullConstant();
+  });
+  HPhi* merge_alloc2 = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference && p->InputAt(0)->IsNullConstant();
+  });
+  ASSERT_NE(merge_alloc1, nullptr);
+  ASSERT_NE(merge_alloc2, nullptr);
+  EXPECT_TRUE(merge_alloc1->InputAt(0)->IsNewInstance()) << *merge_alloc1;
+  EXPECT_INS_EQ(merge_alloc1->InputAt(0)->InputAt(0), cls1) << *merge_alloc1;
+  EXPECT_INS_EQ(merge_alloc1->InputAt(1), graph_->GetNullConstant());
+  EXPECT_TRUE(merge_alloc2->InputAt(1)->IsNewInstance()) << *merge_alloc2;
+  EXPECT_INS_EQ(merge_alloc2->InputAt(1)->InputAt(0), cls2) << *merge_alloc2;
+  EXPECT_INS_EQ(merge_alloc2->InputAt(0), graph_->GetNullConstant());
+  HPredicatedInstanceFieldGet* pred_get1 =
+      FindOrNull(pred_gets.begin(), pred_gets.end(), [&](HPredicatedInstanceFieldGet* pg) {
+        return pg->GetTarget() == merge_alloc1;
+      });
+  HPredicatedInstanceFieldGet* pred_get2 =
+      FindOrNull(pred_gets.begin(), pred_gets.end(), [&](HPredicatedInstanceFieldGet* pg) {
+        return pg->GetTarget() == merge_alloc2;
+      });
+  ASSERT_NE(pred_get1, nullptr);
+  EXPECT_INS_EQ(pred_get1->GetTarget(), merge_alloc1);
+  EXPECT_INS_EQ(pred_get1->GetDefaultValue(), merge_value_return1)
+      << " pred-get is: " << *pred_get1;
+  EXPECT_INS_EQ(merge_value_return1->InputAt(0), graph_->GetIntConstant(0))
+      << " merge val is: " << *merge_value_return1;
+  EXPECT_INS_EQ(merge_value_return1->InputAt(1), c2) << " merge val is: " << *merge_value_return1;
+  ASSERT_NE(pred_get2, nullptr);
+  EXPECT_INS_EQ(pred_get2->GetTarget(), merge_alloc2);
+  EXPECT_INS_EQ(pred_get2->GetDefaultValue(), merge_value_return2)
+      << " pred-get is: " << *pred_get2;
+  EXPECT_INS_EQ(merge_value_return2->InputAt(1), graph_->GetIntConstant(0))
+      << " merge val is: " << *merge_value_return1;
+  EXPECT_INS_EQ(merge_value_return2->InputAt(0), c12) << " merge val is: " << *merge_value_return1;
+}
+
+// Based on structure seen in `java.util.List
+// java.util.Collections.checkedList(java.util.List, java.lang.Class)`
+// Incorrect accounting would cause attempts to materialize both obj1 and obj2
+// in each of the materialization blocks.
+// // ENTRY
+// Obj obj;
+// if (param1) {
+//   // needs to be moved after param2 check
+//   obj1 = new Obj1();
+//   obj1.foo = 33;
+//   if (param2) {
+//     return obj1.foo;
+//   }
+//   obj = obj1;
+// } else {
+//   obj2 = new Obj2();
+//   obj2.foo = 44;
+//   if (param2) {
+//     return obj2.foo;
+//   }
+//   obj = obj2;
+// }
+// EXIT
+// // obj = PHI[obj1, obj2]
+// // NB The phi acts as an escape for both obj1 and obj2 meaning as far as the
+// // LSA is concerned the escape frontier is left_crit_break->breturn and
+// // right_crit_break->breturn for both even though only one of the objects is
+// // actually live at each edge.
+// // TODO In the future we really should track liveness through PHIs which would
+// // allow us to entirely remove the allocation in this test.
+// return obj.foo;
+TEST_F(LoadStoreEliminationTest, MultiPredicatedLoad3) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"left", "left_end"},
+                                                  {"left_end", "breturn"},
+                                                  {"left", "left_exit_early"},
+                                                  {"left_exit_early", "exit"},
+                                                  {"entry", "right"},
+                                                  {"right", "right_end"},
+                                                  {"right_end", "breturn"},
+                                                  {"right", "right_exit_early"},
+                                                  {"right_exit_early", "exit"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(left_end);
+  GET_BLOCK(left_exit_early);
+  GET_BLOCK(right);
+  GET_BLOCK(right_end);
+  GET_BLOCK(right_exit_early);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left_end, right_end});
+  HInstruction* param1 = MakeParam(DataType::Type::kBool);
+  HInstruction* param2 = MakeParam(DataType::Type::kBool);
+  HInstruction* c33 = graph_->GetIntConstant(33);
+  HInstruction* c44 = graph_->GetIntConstant(44);
+
+  HInstruction* if_inst = new (GetAllocator()) HIf(param1);
+  entry->AddInstruction(if_inst);
+
+  HInstruction* cls1 = MakeClassLoad();
+  HInstruction* new_inst1 = MakeNewInstance(cls1);
+  HInstruction* write1 = MakeIFieldSet(new_inst1, c33, MemberOffset(32));
+  HInstruction* if_left = new (GetAllocator()) HIf(param2);
+  left->AddInstruction(cls1);
+  left->AddInstruction(new_inst1);
+  left->AddInstruction(write1);
+  left->AddInstruction(if_left);
+  ManuallyBuildEnvFor(cls1, {});
+  new_inst1->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  left_end->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* early_exit_left_read =
+      MakeIFieldGet(new_inst1, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* early_exit_left_return = new (GetAllocator()) HReturn(early_exit_left_read);
+  left_exit_early->AddInstruction(early_exit_left_read);
+  left_exit_early->AddInstruction(early_exit_left_return);
+
+  HInstruction* cls2 = MakeClassLoad();
+  HInstruction* new_inst2 = MakeNewInstance(cls2);
+  HInstruction* write2 = MakeIFieldSet(new_inst2, c44, MemberOffset(32));
+  HInstruction* if_right = new (GetAllocator()) HIf(param2);
+  right->AddInstruction(cls2);
+  right->AddInstruction(new_inst2);
+  right->AddInstruction(write2);
+  right->AddInstruction(if_right);
+  cls2->CopyEnvironmentFrom(cls1->GetEnvironment());
+  new_inst2->CopyEnvironmentFrom(cls2->GetEnvironment());
+
+  right_end->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* early_exit_right_read =
+      MakeIFieldGet(new_inst2, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* early_exit_right_return = new (GetAllocator()) HReturn(early_exit_right_read);
+  right_exit_early->AddInstruction(early_exit_right_read);
+  right_exit_early->AddInstruction(early_exit_right_return);
+
+  HPhi* bottom_phi = MakePhi({new_inst1, new_inst2});
+  HInstruction* read_bottom = MakeIFieldGet(bottom_phi, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddPhi(bottom_phi);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(early_exit_left_read);
+  EXPECT_INS_REMOVED(early_exit_right_read);
+  EXPECT_INS_RETAINED(bottom_phi);
+  EXPECT_INS_RETAINED(read_bottom);
+  EXPECT_INS_EQ(early_exit_left_return->InputAt(0), c33);
+  EXPECT_INS_EQ(early_exit_right_return->InputAt(0), c44);
+  // These assert there is only 1 HNewInstance in the given blocks.
+  HNewInstance* moved_ni1 =
+      FindSingleInstruction<HNewInstance>(graph_, left_end->GetSinglePredecessor());
+  HNewInstance* moved_ni2 =
+      FindSingleInstruction<HNewInstance>(graph_, right_end->GetSinglePredecessor());
+  ASSERT_NE(moved_ni1, nullptr);
+  ASSERT_NE(moved_ni2, nullptr);
+  EXPECT_INS_EQ(bottom_phi->InputAt(0), moved_ni1);
+  EXPECT_INS_EQ(bottom_phi->InputAt(1), moved_ni2);
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (param1) {
+//   obj.field = 3;
+//   noescape();
+// } else {
+//   obj.field = 2;
+//   noescape();
+// }
+// int abc;
+// if (parameter_value) {
+//   // LEFT
+//   abc = 4;
+//   escape(obj);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   noescape();
+//   abc = obj.field + 4;
+// }
+// abc = phi
+// EXIT
+// predicated-ELIMINATE
+// return obj.field + abc
+TEST_F(LoadStoreEliminationTest, PredicatedLoad4) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "start_left"},
+                                                  {"entry", "start_right"},
+                                                  {"start_left", "mid"},
+                                                  {"start_right", "mid"},
+                                                  {"mid", "left"},
+                                                  {"mid", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(mid);
+  GET_BLOCK(start_left);
+  GET_BLOCK(start_right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+  EnsurePredecessorOrder(mid, {start_left, start_right});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* bool_value2 = MakeParam(DataType::Type::kBool);
+  HInstruction* null_const = graph_->GetNullConstant();
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c4 = graph_->GetIntConstant(4);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_start_left = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* call_start_left = MakeInvoke(DataType::Type::kVoid, { });
+  start_left->AddInstruction(write_start_left);
+  start_left->AddInstruction(call_start_left);
+  start_left->AddInstruction(new (GetAllocator()) HGoto());
+  call_start_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_start_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* call_start_right = MakeInvoke(DataType::Type::kVoid, { });
+  start_right->AddInstruction(write_start_right);
+  start_right->AddInstruction(call_start_right);
+  start_right->AddInstruction(new (GetAllocator()) HGoto());
+  call_start_right->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  mid->AddInstruction(new (GetAllocator()) HIf(bool_value2));
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_right = MakeInvoke(DataType::Type::kVoid, { });
+  HInstruction* read_right = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* add_right = new (GetAllocator()) HAdd(DataType::Type::kInt32, read_right, c4);
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(call_right);
+  right->AddInstruction(read_right);
+  right->AddInstruction(add_right);
+  right->AddInstruction(goto_right);
+  call_right->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HPhi* phi_bottom = MakePhi({c4, add_right});
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* add_bottom =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, read_bottom, phi_bottom);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(add_bottom);
+  breturn->AddPhi(phi_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(add_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(read_right);
+  EXPECT_INS_RETAINED(call_left);
+  EXPECT_INS_RETAINED(call_right);
+  EXPECT_INS_RETAINED(call_start_left);
+  EXPECT_INS_RETAINED(call_start_right);
+  std::vector<HPhi*> merges;
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  std::tie(merges) = FindAllInstructions<HPhi>(graph_, breturn);
+  ASSERT_EQ(merges.size(), 3u);
+  HPhi* merge_value_return = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p != phi_bottom && p->GetType() == DataType::Type::kInt32;
+  });
+  HPhi* merge_alloc = FindOrNull(merges.begin(), merges.end(), [](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference;
+  });
+  ASSERT_NE(merge_alloc, nullptr);
+  EXPECT_TRUE(merge_alloc->InputAt(0)->IsNewInstance()) << *merge_alloc;
+  EXPECT_EQ(merge_alloc->InputAt(0)->InputAt(0), cls) << *merge_alloc << " cls? " << *cls;
+  EXPECT_EQ(merge_alloc->InputAt(1), null_const);
+  ASSERT_NE(pred_get, nullptr);
+  EXPECT_INS_EQ(pred_get->GetTarget(), merge_alloc);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), merge_value_return) << " pred-get is: " << *pred_get;
+  EXPECT_INS_EQ(merge_value_return->InputAt(0), graph_->GetIntConstant(0))
+      << " merge val is: " << *merge_value_return;
+  EXPECT_INS_EQ(merge_value_return->InputAt(1), FindSingleInstruction<HPhi>(graph_, mid))
+      << " merge val is: " << *merge_value_return;
+}
+
+// Based on structure seen in `java.util.Set java.util.Collections$UnmodifiableMap.entrySet()`
+// We end up having to update a PHI generated by normal LSE.
+// // ENTRY
+// Obj obj_init = param_obj.BAR;
+// if (param1) {
+//   Obj other = new Obj();
+//   other.foo = 42;
+//   if (param2) {
+//     return other.foo;
+//   } else {
+//     param_obj.BAR = other;
+//   }
+// } else { }
+// EXIT
+// LSE Turns this into PHI[obj_init, other]
+// read_bottom = param_obj.BAR;
+// // won't be changed. The escape happens with .BAR set so this is in escaping cohort.
+// return read_bottom.foo;
+TEST_F(LoadStoreEliminationTest, MultiPredicatedLoad4) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"left", "left_early_return"},
+                                                  {"left_early_return", "exit"},
+                                                  {"left", "left_write_escape"},
+                                                  {"left_write_escape", "breturn"},
+                                                  {"entry", "right"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(left_early_return);
+  GET_BLOCK(left_write_escape);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  MemberOffset foo_offset = MemberOffset(32);
+  MemberOffset bar_offset = MemberOffset(20);
+  EnsurePredecessorOrder(breturn, {left_write_escape, right});
+  HInstruction* c42 = graph_->GetIntConstant(42);
+  HInstruction* param1 = MakeParam(DataType::Type::kBool);
+  HInstruction* param2 = MakeParam(DataType::Type::kBool);
+  HInstruction* param_obj = MakeParam(DataType::Type::kReference);
+
+  HInstruction* get_initial = MakeIFieldGet(param_obj, DataType::Type::kReference, bar_offset);
+  HInstruction* if_inst = new (GetAllocator()) HIf(param1);
+  entry->AddInstruction(get_initial);
+  entry->AddInstruction(if_inst);
+
+  HInstruction* cls1 = MakeClassLoad();
+  HInstruction* new_inst1 = MakeNewInstance(cls1);
+  HInstruction* write1 = MakeIFieldSet(new_inst1, c42, foo_offset);
+  HInstruction* if_left = new (GetAllocator()) HIf(param2);
+  left->AddInstruction(cls1);
+  left->AddInstruction(new_inst1);
+  left->AddInstruction(write1);
+  left->AddInstruction(if_left);
+  ManuallyBuildEnvFor(cls1, {});
+  new_inst1->CopyEnvironmentFrom(cls1->GetEnvironment());
+
+  HInstruction* read_early_return = MakeIFieldGet(new_inst1, DataType::Type::kInt32, foo_offset);
+  HInstruction* return_early = new (GetAllocator()) HReturn(read_early_return);
+  left_early_return->AddInstruction(read_early_return);
+  left_early_return->AddInstruction(return_early);
+
+  HInstruction* write_escape = MakeIFieldSet(param_obj, new_inst1, bar_offset);
+  HInstruction* write_goto = new (GetAllocator()) HGoto();
+  left_write_escape->AddInstruction(write_escape);
+  left_write_escape->AddInstruction(write_goto);
+
+  right->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* read_bottom = MakeIFieldGet(param_obj, DataType::Type::kReference, bar_offset);
+  HInstruction* final_read = MakeIFieldGet(read_bottom, DataType::Type::kInt32, foo_offset);
+  HInstruction* return_exit = new (GetAllocator()) HReturn(final_read);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(final_read);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(read_early_return);
+  EXPECT_INS_EQ(return_early->InputAt(0), c42);
+  EXPECT_INS_RETAINED(final_read);
+  HNewInstance* moved_ni =
+      FindSingleInstruction<HNewInstance>(graph_, left_write_escape->GetSinglePredecessor());
+  EXPECT_TRUE(final_read->InputAt(0)->IsPhi());
+  EXPECT_INS_EQ(final_read->InputAt(0)->InputAt(0), moved_ni);
+  EXPECT_INS_EQ(final_read->InputAt(0)->InputAt(1), get_initial);
+}
+
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// // MERGE
+// if (second_param) {
+//   // NON_ESCAPE
+//   obj.field = 1;
+//   noescape();
+// }
+// EXIT
+// predicated-ELIMINATE
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PredicatedLoad2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "merge"},
+                                                  {"right", "merge"},
+                                                  {"merge", "non_escape"},
+                                                  {"non_escape", "breturn"},
+                                                  {"merge", "crit_break"},
+                                                  {"crit_break", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(merge);
+  GET_BLOCK(non_escape);
+  GET_BLOCK(crit_break);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(merge, {left, right});
+  EnsurePredecessorOrder(breturn, {crit_break, non_escape});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* bool_value2 = MakeParam(DataType::Type::kBool);
+  HInstruction* null_const = graph_->GetNullConstant();
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* merge_if = new (GetAllocator()) HIf(bool_value2);
+  merge->AddInstruction(merge_if);
+
+  crit_break->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* write_non_escape = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* non_escape_call = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* non_escape_goto = new (GetAllocator()) HGoto();
+  non_escape->AddInstruction(write_non_escape);
+  non_escape->AddInstruction(non_escape_call);
+  non_escape->AddInstruction(non_escape_goto);
+  non_escape_call->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_RETAINED(call_left);
+  std::vector<HPhi*> merges;
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  std::tie(merges) = FindAllInstructions<HPhi>(graph_);
+  ASSERT_EQ(merges.size(), 3u);
+  HPhi* merge_value_return = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->GetBlock() == breturn;
+  });
+  HPhi* merge_value_merge = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->GetBlock() != breturn;
+  });
+  HPhi* merge_alloc = FindOrNull(merges.begin(), merges.end(), [](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference;
+  });
+  ASSERT_NE(merge_alloc, nullptr);
+  EXPECT_TRUE(merge_alloc->InputAt(0)->IsNewInstance()) << *merge_alloc;
+  EXPECT_INS_EQ(merge_alloc->InputAt(0)->InputAt(0), cls)
+      << " phi is: " << merge_alloc->DumpWithArgs();
+  EXPECT_INS_EQ(merge_alloc->InputAt(1), null_const);
+  ASSERT_NE(pred_get, nullptr);
+  EXPECT_INS_EQ(pred_get->GetTarget(), merge_alloc);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), merge_value_return)
+      << "get is " << pred_get->DumpWithArgs();
+  EXPECT_INS_EQ(merge_value_return->InputAt(0), merge_value_merge)
+      << " phi is: " << *merge_value_return;
+  EXPECT_INS_EQ(merge_value_return->InputAt(1), c1)
+      << " phi is: " << merge_value_return->DumpWithArgs();
+  EXPECT_INS_EQ(merge_value_merge->InputAt(0), graph_->GetIntConstant(0))
+      << " phi is: " << *merge_value_merge;
+  EXPECT_INS_EQ(merge_value_merge->InputAt(1), c2)
+      << " phi is: " << merge_value_merge->DumpWithArgs();
+}
+
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// if (parameter_value) {
+//   // LEFT
+//   escape(obj);
+// } else {
+//   // RIGHT
+//   // ELIMINATE
+//   obj.field = 2;
+// }
+// // MERGE
+// if (second_param) {
+//   // NON_ESCAPE
+//   obj.field = 1;
+// }
+// noescape();
+// EXIT
+// predicated-ELIMINATE
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PredicatedLoad3) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "merge"},
+                                                  {"right", "merge"},
+                                                  {"merge", "non_escape"},
+                                                  {"non_escape", "breturn"},
+                                                  {"merge", "crit_break"},
+                                                  {"crit_break", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(merge);
+  GET_BLOCK(crit_break);
+  GET_BLOCK(non_escape);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(merge, {left, right});
+  EnsurePredecessorOrder(breturn, {crit_break, non_escape});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* bool_value2 = MakeParam(DataType::Type::kBool);
+  HInstruction* null_const = graph_->GetNullConstant();
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* merge_if = new (GetAllocator()) HIf(bool_value2);
+  merge->AddInstruction(merge_if);
+
+  HInstruction* write_non_escape = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* non_escape_goto = new (GetAllocator()) HGoto();
+  non_escape->AddInstruction(write_non_escape);
+  non_escape->AddInstruction(non_escape_goto);
+
+  crit_break->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* bottom_call = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(bottom_call);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+  bottom_call->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_RETAINED(call_left);
+  std::vector<HPhi*> merges;
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  std::tie(merges) = FindAllInstructions<HPhi>(graph_);
+  ASSERT_EQ(merges.size(), 3u);
+  HPhi* merge_value_return = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->GetBlock() == breturn;
+  });
+  HPhi* merge_value_merge = FindOrNull(merges.begin(), merges.end(), [&](HPhi* p) {
+    return p->GetType() == DataType::Type::kInt32 && p->GetBlock() != breturn;
+  });
+  HPhi* merge_alloc = FindOrNull(merges.begin(), merges.end(), [](HPhi* p) {
+    return p->GetType() == DataType::Type::kReference;
+  });
+  ASSERT_NE(merge_alloc, nullptr);
+  EXPECT_TRUE(merge_alloc->InputAt(0)->IsNewInstance()) << merge_alloc->DumpWithArgs();
+  EXPECT_INS_EQ(merge_alloc->InputAt(0)->InputAt(0), cls)
+      << " phi is: " << merge_alloc->DumpWithArgs();
+  EXPECT_INS_EQ(merge_alloc->InputAt(1), null_const);
+  ASSERT_NE(pred_get, nullptr);
+  EXPECT_INS_EQ(pred_get->GetTarget(), merge_alloc);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), merge_value_return)
+      << "get is " << pred_get->DumpWithArgs();
+  EXPECT_INS_EQ(merge_value_return->InputAt(0), merge_value_merge)
+      << " phi is: " << *merge_value_return;
+  EXPECT_INS_EQ(merge_value_return->InputAt(1), c1) << " phi is: " << *merge_value_return;
+  EXPECT_INS_EQ(merge_value_merge->InputAt(0), graph_->GetIntConstant(0))
+      << " phi is: " << *merge_value_merge;
+  EXPECT_INS_EQ(merge_value_merge->InputAt(1), c2) << " phi is: " << *merge_value_merge;
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   // LEFT
+//   obj.field = 3;
+//   escape(obj);
+// } else {
+//   // RIGHT - Leave it as default value
+// }
+// EXIT
+// predicated-ELIMINATE
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PredicatedLoadDefaultValue) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* null_const = graph_->GetNullConstant();
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_left = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(write_left);
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(read_bottom);
+  EXPECT_INS_RETAINED(write_left);
+  EXPECT_INS_RETAINED(call_left);
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  HPhi* merge_alloc = FindSingleInstruction<HPhi>(graph_, breturn);
+  ASSERT_NE(merge_alloc, nullptr);
+  EXPECT_TRUE(merge_alloc->InputAt(0)->IsNewInstance()) << *merge_alloc;
+  EXPECT_EQ(merge_alloc->InputAt(0)->InputAt(0), cls) << *merge_alloc << " cls? " << *cls;
+  EXPECT_EQ(merge_alloc->InputAt(1), null_const);
+  ASSERT_NE(pred_get, nullptr);
+  EXPECT_INS_EQ(pred_get->GetTarget(), merge_alloc);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), c0) << " pred-get is: " << *pred_get;
+}
+
+// // ENTRY
+// obj = new Obj();
+// // ALL should be kept
+// switch (parameter_value) {
+//   case 1:
+//     // Case1
+//     obj.field = 1;
+//     call_func(obj);
+//     break;
+//   case 2:
+//     // Case2
+//     obj.field = 2;
+//     call_func(obj);
+//     break;
+//   default:
+//     // Case3
+//     obj.field = 3;
+//     do {
+//       if (test2()) { } else { obj.field = 5; }
+//     } while (test());
+//     break;
+// }
+// EXIT
+// // predicated-ELIMINATE
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialLoopPhis1) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "bswitch"},
+                                                  {"bswitch", "case1"},
+                                                  {"bswitch", "case2"},
+                                                  {"bswitch", "case3"},
+                                                  {"case1", "breturn"},
+                                                  {"case2", "breturn"},
+                                                  {"case3", "loop_pre_header"},
+                                                  {"loop_pre_header", "loop_header"},
+                                                  {"loop_header", "loop_body"},
+                                                  {"loop_body", "loop_if_left"},
+                                                  {"loop_body", "loop_if_right"},
+                                                  {"loop_if_left", "loop_merge"},
+                                                  {"loop_if_right", "loop_merge"},
+                                                  {"loop_merge", "loop_end"},
+                                                  {"loop_end", "loop_header"},
+                                                  {"loop_end", "critical_break"},
+                                                  {"critical_break", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(bswitch);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(case1);
+  GET_BLOCK(case2);
+  GET_BLOCK(case3);
+
+  GET_BLOCK(loop_pre_header);
+  GET_BLOCK(loop_header);
+  GET_BLOCK(loop_body);
+  GET_BLOCK(loop_if_left);
+  GET_BLOCK(loop_if_right);
+  GET_BLOCK(loop_merge);
+  GET_BLOCK(loop_end);
+  GET_BLOCK(critical_break);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {case1, case2, critical_break});
+  EnsurePredecessorOrder(loop_header, {loop_pre_header, loop_end});
+  EnsurePredecessorOrder(loop_merge, {loop_if_left, loop_if_right});
+  CHECK_SUBROUTINE_FAILURE();
+  HInstruction* switch_val = MakeParam(DataType::Type::kInt32);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(entry_goto);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* switch_inst = new (GetAllocator()) HPackedSwitch(0, 2, switch_val);
+  bswitch->AddInstruction(switch_inst);
+
+  HInstruction* write_c1 = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* call_c1 = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_c1 = new (GetAllocator()) HGoto();
+  case1->AddInstruction(write_c1);
+  case1->AddInstruction(call_c1);
+  case1->AddInstruction(goto_c1);
+  call_c1->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_c2 = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* call_c2 = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_c2 = new (GetAllocator()) HGoto();
+  case2->AddInstruction(write_c2);
+  case2->AddInstruction(call_c2);
+  case2->AddInstruction(goto_c2);
+  call_c2->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_c3 = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* goto_c3 = new (GetAllocator()) HGoto();
+  case3->AddInstruction(write_c3);
+  case3->AddInstruction(goto_c3);
+
+  HInstruction* goto_preheader = new (GetAllocator()) HGoto();
+  loop_pre_header->AddInstruction(goto_preheader);
+
+  HInstruction* suspend_check_header = new (GetAllocator()) HSuspendCheck();
+  HInstruction* goto_header = new (GetAllocator()) HGoto();
+  loop_header->AddInstruction(suspend_check_header);
+  loop_header->AddInstruction(goto_header);
+  suspend_check_header->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_loop_body = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_loop_body = new (GetAllocator()) HIf(call_loop_body);
+  loop_body->AddInstruction(call_loop_body);
+  loop_body->AddInstruction(if_loop_body);
+  call_loop_body->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_loop_left = new (GetAllocator()) HGoto();
+  loop_if_left->AddInstruction(goto_loop_left);
+
+  HInstruction* write_loop_right = MakeIFieldSet(new_inst, c5, MemberOffset(32));
+  HInstruction* goto_loop_right = new (GetAllocator()) HGoto();
+  loop_if_right->AddInstruction(write_loop_right);
+  loop_if_right->AddInstruction(goto_loop_right);
+
+  HInstruction* goto_loop_merge = new (GetAllocator()) HGoto();
+  loop_merge->AddInstruction(goto_loop_merge);
+
+  HInstruction* call_end = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_end = new (GetAllocator()) HIf(call_end);
+  loop_end->AddInstruction(call_end);
+  loop_end->AddInstruction(if_end);
+  call_end->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_critical_break = new (GetAllocator()) HGoto();
+  critical_break->AddInstruction(goto_critical_break);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  EXPECT_INS_REMOVED(read_bottom) << *read_bottom;
+  ASSERT_TRUE(pred_get != nullptr);
+  HPhi* inst_return_phi = pred_get->GetTarget()->AsPhi();
+  ASSERT_TRUE(inst_return_phi != nullptr) << pred_get->GetTarget()->DumpWithArgs();
+  EXPECT_INS_EQ(inst_return_phi->InputAt(0),
+                FindSingleInstruction<HNewInstance>(graph_, case1->GetSinglePredecessor()));
+  EXPECT_INS_EQ(inst_return_phi->InputAt(1),
+                FindSingleInstruction<HNewInstance>(graph_, case2->GetSinglePredecessor()));
+  EXPECT_INS_EQ(inst_return_phi->InputAt(2), graph_->GetNullConstant());
+  HPhi* inst_value_phi = pred_get->GetDefaultValue()->AsPhi();
+  ASSERT_TRUE(inst_value_phi != nullptr) << pred_get->GetDefaultValue()->DumpWithArgs();
+  EXPECT_INS_EQ(inst_value_phi->InputAt(0), graph_->GetIntConstant(0));
+  EXPECT_INS_EQ(inst_value_phi->InputAt(1), graph_->GetIntConstant(0));
+  HPhi* loop_merge_phi = FindSingleInstruction<HPhi>(graph_, loop_merge);
+  ASSERT_TRUE(loop_merge_phi != nullptr);
+  HPhi* loop_header_phi = FindSingleInstruction<HPhi>(graph_, loop_header);
+  ASSERT_TRUE(loop_header_phi != nullptr);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(0), c3);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(1), loop_merge_phi);
+  EXPECT_INS_EQ(loop_merge_phi->InputAt(0), loop_header_phi);
+  EXPECT_INS_EQ(loop_merge_phi->InputAt(1), c5);
+  EXPECT_INS_EQ(inst_value_phi->InputAt(2), loop_merge_phi);
+  EXPECT_INS_RETAINED(write_c1) << *write_c1;
+  EXPECT_INS_RETAINED(write_c2) << *write_c2;
+  EXPECT_INS_REMOVED(write_c3) << *write_c3;
+  EXPECT_INS_REMOVED(write_loop_right) << *write_loop_right;
+}
+
+// // ENTRY
+// obj = new Obj();
+// switch (parameter_value) {
+//   case 1:
+//     // Case1
+//     obj.field = 1;
+//     call_func(obj);
+//     break;
+//   case 2:
+//     // Case2
+//     obj.field = 2;
+//     call_func(obj);
+//     break;
+//   default:
+//     // Case3
+//     obj.field = 3;
+//     while (!test()) {
+//       if (test2()) { } else { obj.field = 5; }
+//     }
+//     break;
+// }
+// EXIT
+// // predicated-ELIMINATE
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialLoopPhis2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "bswitch"},
+                                                  {"bswitch", "case1"},
+                                                  {"bswitch", "case2"},
+                                                  {"bswitch", "case3"},
+                                                  {"case1", "breturn"},
+                                                  {"case2", "breturn"},
+                                                  {"case3", "loop_pre_header"},
+
+                                                  {"loop_pre_header", "loop_header"},
+                                                  {"loop_header", "critical_break"},
+                                                  {"loop_header", "loop_body"},
+                                                  {"loop_body", "loop_if_left"},
+                                                  {"loop_body", "loop_if_right"},
+                                                  {"loop_if_left", "loop_merge"},
+                                                  {"loop_if_right", "loop_merge"},
+                                                  {"loop_merge", "loop_header"},
+
+                                                  {"critical_break", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(bswitch);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(case1);
+  GET_BLOCK(case2);
+  GET_BLOCK(case3);
+
+  GET_BLOCK(loop_pre_header);
+  GET_BLOCK(loop_header);
+  GET_BLOCK(loop_body);
+  GET_BLOCK(loop_if_left);
+  GET_BLOCK(loop_if_right);
+  GET_BLOCK(loop_merge);
+  GET_BLOCK(critical_break);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {case1, case2, critical_break});
+  EnsurePredecessorOrder(loop_header, {loop_pre_header, loop_merge});
+  EnsurePredecessorOrder(loop_merge, {loop_if_left, loop_if_right});
+  CHECK_SUBROUTINE_FAILURE();
+  HInstruction* switch_val = MakeParam(DataType::Type::kInt32);
+  HInstruction* c1 = graph_->GetIntConstant(1);
+  HInstruction* c2 = graph_->GetIntConstant(2);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(entry_goto);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* switch_inst = new (GetAllocator()) HPackedSwitch(0, 2, switch_val);
+  bswitch->AddInstruction(switch_inst);
+
+  HInstruction* write_c1 = MakeIFieldSet(new_inst, c1, MemberOffset(32));
+  HInstruction* call_c1 = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_c1 = new (GetAllocator()) HGoto();
+  case1->AddInstruction(write_c1);
+  case1->AddInstruction(call_c1);
+  case1->AddInstruction(goto_c1);
+  call_c1->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_c2 = MakeIFieldSet(new_inst, c2, MemberOffset(32));
+  HInstruction* call_c2 = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_c2 = new (GetAllocator()) HGoto();
+  case2->AddInstruction(write_c2);
+  case2->AddInstruction(call_c2);
+  case2->AddInstruction(goto_c2);
+  call_c2->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_c3 = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* goto_c3 = new (GetAllocator()) HGoto();
+  case3->AddInstruction(write_c3);
+  case3->AddInstruction(goto_c3);
+
+  HInstruction* goto_preheader = new (GetAllocator()) HGoto();
+  loop_pre_header->AddInstruction(goto_preheader);
+
+  HInstruction* suspend_check_header = new (GetAllocator()) HSuspendCheck();
+  HInstruction* call_header = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_header = new (GetAllocator()) HIf(call_header);
+  loop_header->AddInstruction(suspend_check_header);
+  loop_header->AddInstruction(call_header);
+  loop_header->AddInstruction(if_header);
+  call_header->CopyEnvironmentFrom(cls->GetEnvironment());
+  suspend_check_header->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_loop_body = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_loop_body = new (GetAllocator()) HIf(call_loop_body);
+  loop_body->AddInstruction(call_loop_body);
+  loop_body->AddInstruction(if_loop_body);
+  call_loop_body->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_loop_left = new (GetAllocator()) HGoto();
+  loop_if_left->AddInstruction(goto_loop_left);
+
+  HInstruction* write_loop_right = MakeIFieldSet(new_inst, c5, MemberOffset(32));
+  HInstruction* goto_loop_right = new (GetAllocator()) HGoto();
+  loop_if_right->AddInstruction(write_loop_right);
+  loop_if_right->AddInstruction(goto_loop_right);
+
+  HInstruction* goto_loop_merge = new (GetAllocator()) HGoto();
+  loop_merge->AddInstruction(goto_loop_merge);
+
+  HInstruction* goto_critical_break = new (GetAllocator()) HGoto();
+  critical_break->AddInstruction(goto_critical_break);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  EXPECT_INS_REMOVED(read_bottom) << *read_bottom;
+  ASSERT_TRUE(pred_get != nullptr);
+  HPhi* inst_return_phi = pred_get->GetTarget()->AsPhi();
+  ASSERT_TRUE(inst_return_phi != nullptr) << pred_get->GetTarget()->DumpWithArgs();
+  EXPECT_INS_EQ(inst_return_phi->InputAt(0),
+                FindSingleInstruction<HNewInstance>(graph_, case1->GetSinglePredecessor()));
+  EXPECT_INS_EQ(inst_return_phi->InputAt(1),
+                FindSingleInstruction<HNewInstance>(graph_, case2->GetSinglePredecessor()));
+  EXPECT_INS_EQ(inst_return_phi->InputAt(2), graph_->GetNullConstant());
+  HPhi* inst_value_phi = pred_get->GetDefaultValue()->AsPhi();
+  ASSERT_TRUE(inst_value_phi != nullptr) << pred_get->GetDefaultValue()->DumpWithArgs();
+  EXPECT_INS_EQ(inst_value_phi->InputAt(0), graph_->GetIntConstant(0));
+  EXPECT_INS_EQ(inst_value_phi->InputAt(1), graph_->GetIntConstant(0));
+  HPhi* loop_merge_phi = FindSingleInstruction<HPhi>(graph_, loop_merge);
+  ASSERT_TRUE(loop_merge_phi != nullptr);
+  HPhi* loop_header_phi = FindSingleInstruction<HPhi>(graph_, loop_header);
+  ASSERT_TRUE(loop_header_phi != nullptr);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(0), c3);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(1), loop_merge_phi);
+  EXPECT_INS_EQ(loop_merge_phi->InputAt(0), loop_header_phi);
+  EXPECT_INS_EQ(loop_merge_phi->InputAt(1), c5);
+  EXPECT_INS_EQ(inst_value_phi->InputAt(2), loop_header_phi);
+  EXPECT_INS_RETAINED(write_c1) << *write_c1;
+  EXPECT_INS_RETAINED(write_c2) << *write_c2;
+  EXPECT_INS_REMOVED(write_c3) << *write_c3;
+  EXPECT_INS_REMOVED(write_loop_right) << *write_loop_right;
+}
+
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// while (!test()) {
+//   if (test2()) { } else { obj.field = 5; }
+// }
+// if (parameter_value) {
+//   escape(obj);
+// }
+// EXIT
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialLoopPhis3) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "loop_pre_header"},
+
+                                                  {"loop_pre_header", "loop_header"},
+                                                  {"loop_header", "escape_check"},
+                                                  {"loop_header", "loop_body"},
+                                                  {"loop_body", "loop_if_left"},
+                                                  {"loop_body", "loop_if_right"},
+                                                  {"loop_if_left", "loop_merge"},
+                                                  {"loop_if_right", "loop_merge"},
+                                                  {"loop_merge", "loop_header"},
+
+                                                  {"escape_check", "escape"},
+                                                  {"escape_check", "no_escape"},
+                                                  {"no_escape", "breturn"},
+                                                  {"escape", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(no_escape);
+  GET_BLOCK(escape);
+  GET_BLOCK(escape_check);
+
+  GET_BLOCK(loop_pre_header);
+  GET_BLOCK(loop_header);
+  GET_BLOCK(loop_body);
+  GET_BLOCK(loop_if_left);
+  GET_BLOCK(loop_if_right);
+  GET_BLOCK(loop_merge);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {no_escape, escape});
+  EnsurePredecessorOrder(loop_header, {loop_pre_header, loop_merge});
+  EnsurePredecessorOrder(loop_merge, {loop_if_left, loop_if_right});
+  CHECK_SUBROUTINE_FAILURE();
+  HInstruction* bool_val = MakeParam(DataType::Type::kBool);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(entry_goto);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_pre_header = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* goto_preheader = new (GetAllocator()) HGoto();
+  loop_pre_header->AddInstruction(write_pre_header);
+  loop_pre_header->AddInstruction(goto_preheader);
+
+  HInstruction* suspend_check_header = new (GetAllocator()) HSuspendCheck();
+  HInstruction* call_header = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_header = new (GetAllocator()) HIf(call_header);
+  loop_header->AddInstruction(suspend_check_header);
+  loop_header->AddInstruction(call_header);
+  loop_header->AddInstruction(if_header);
+  call_header->CopyEnvironmentFrom(cls->GetEnvironment());
+  suspend_check_header->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_loop_body = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_loop_body = new (GetAllocator()) HIf(call_loop_body);
+  loop_body->AddInstruction(call_loop_body);
+  loop_body->AddInstruction(if_loop_body);
+  call_loop_body->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_loop_left = new (GetAllocator()) HGoto();
+  loop_if_left->AddInstruction(goto_loop_left);
+
+  HInstruction* write_loop_right = MakeIFieldSet(new_inst, c5, MemberOffset(32));
+  HInstruction* goto_loop_right = new (GetAllocator()) HGoto();
+  loop_if_right->AddInstruction(write_loop_right);
+  loop_if_right->AddInstruction(goto_loop_right);
+
+  HInstruction* goto_loop_merge = new (GetAllocator()) HGoto();
+  loop_merge->AddInstruction(goto_loop_merge);
+
+  HInstruction* if_esc_check = new (GetAllocator()) HIf(bool_val);
+  escape_check->AddInstruction(if_esc_check);
+
+  HInstruction* call_escape = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_escape = new (GetAllocator()) HGoto();
+  escape->AddInstruction(call_escape);
+  escape->AddInstruction(goto_escape);
+  call_escape->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_no_escape = new (GetAllocator()) HGoto();
+  no_escape->AddInstruction(goto_no_escape);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  EXPECT_INS_REMOVED(read_bottom) << *read_bottom;
+  ASSERT_TRUE(pred_get != nullptr);
+  HPhi* inst_return_phi = pred_get->GetTarget()->AsPhi();
+  ASSERT_TRUE(inst_return_phi != nullptr) << pred_get->GetTarget()->DumpWithArgs();
+  EXPECT_INS_EQ(inst_return_phi->InputAt(0), graph_->GetNullConstant());
+  EXPECT_INS_EQ(inst_return_phi->InputAt(1),
+                FindSingleInstruction<HNewInstance>(graph_, escape->GetSinglePredecessor()));
+  HPhi* inst_value_phi = pred_get->GetDefaultValue()->AsPhi();
+  ASSERT_TRUE(inst_value_phi != nullptr) << pred_get->GetDefaultValue()->DumpWithArgs();
+  HPhi* loop_header_phi = FindSingleInstruction<HPhi>(graph_, loop_header);
+  HPhi* loop_merge_phi = FindSingleInstruction<HPhi>(graph_, loop_merge);
+  EXPECT_INS_EQ(inst_value_phi->InputAt(0), loop_header_phi);
+  EXPECT_INS_EQ(inst_value_phi->InputAt(1), graph_->GetIntConstant(0));
+  EXPECT_INS_EQ(loop_header_phi->InputAt(0), c3);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(1), loop_merge_phi);
+  EXPECT_INS_EQ(loop_merge_phi->InputAt(0), loop_header_phi);
+  EXPECT_INS_EQ(loop_merge_phi->InputAt(1), c5);
+  HInstanceFieldSet* mat_set =
+      FindSingleInstruction<HInstanceFieldSet>(graph_, escape->GetSinglePredecessor());
+  ASSERT_NE(mat_set, nullptr);
+  EXPECT_INS_EQ(mat_set->InputAt(1), loop_header_phi);
+  EXPECT_INS_REMOVED(write_loop_right) << *write_loop_right;
+  EXPECT_INS_REMOVED(write_pre_header) << *write_pre_header;
+}
+
+// // ENTRY
+// obj = new Obj();
+// if (parameter_value) {
+//   escape(obj);
+// }
+// obj.field = 3;
+// while (!test()) {
+//   if (test2()) { } else { obj.field = 5; }
+// }
+// EXIT
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialLoopPhis4) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "escape_check"},
+                                                  {"escape_check", "escape"},
+                                                  {"escape_check", "no_escape"},
+                                                  {"no_escape", "loop_pre_header"},
+                                                  {"escape", "loop_pre_header"},
+
+                                                  {"loop_pre_header", "loop_header"},
+                                                  {"loop_header", "breturn"},
+                                                  {"loop_header", "loop_body"},
+                                                  {"loop_body", "loop_if_left"},
+                                                  {"loop_body", "loop_if_right"},
+                                                  {"loop_if_left", "loop_merge"},
+                                                  {"loop_if_right", "loop_merge"},
+                                                  {"loop_merge", "loop_header"},
+
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(no_escape);
+  GET_BLOCK(escape);
+  GET_BLOCK(escape_check);
+
+  GET_BLOCK(loop_pre_header);
+  GET_BLOCK(loop_header);
+  GET_BLOCK(loop_body);
+  GET_BLOCK(loop_if_left);
+  GET_BLOCK(loop_if_right);
+  GET_BLOCK(loop_merge);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(loop_pre_header, {no_escape, escape});
+  EnsurePredecessorOrder(loop_header, {loop_pre_header, loop_merge});
+  EnsurePredecessorOrder(loop_merge, {loop_if_left, loop_if_right});
+  CHECK_SUBROUTINE_FAILURE();
+  HInstruction* bool_val = MakeParam(DataType::Type::kBool);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(entry_goto);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* if_esc_check = new (GetAllocator()) HIf(bool_val);
+  escape_check->AddInstruction(if_esc_check);
+
+  HInstruction* call_escape = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_escape = new (GetAllocator()) HGoto();
+  escape->AddInstruction(call_escape);
+  escape->AddInstruction(goto_escape);
+  call_escape->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_no_escape = new (GetAllocator()) HGoto();
+  no_escape->AddInstruction(goto_no_escape);
+
+  HInstruction* write_pre_header = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* goto_preheader = new (GetAllocator()) HGoto();
+  loop_pre_header->AddInstruction(write_pre_header);
+  loop_pre_header->AddInstruction(goto_preheader);
+
+  HInstruction* suspend_check_header = new (GetAllocator()) HSuspendCheck();
+  HInstruction* call_header = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_header = new (GetAllocator()) HIf(call_header);
+  loop_header->AddInstruction(suspend_check_header);
+  loop_header->AddInstruction(call_header);
+  loop_header->AddInstruction(if_header);
+  call_header->CopyEnvironmentFrom(cls->GetEnvironment());
+  suspend_check_header->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_loop_body = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_loop_body = new (GetAllocator()) HIf(call_loop_body);
+  loop_body->AddInstruction(call_loop_body);
+  loop_body->AddInstruction(if_loop_body);
+  call_loop_body->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_loop_left = new (GetAllocator()) HGoto();
+  loop_if_left->AddInstruction(goto_loop_left);
+
+  HInstruction* write_loop_right = MakeIFieldSet(new_inst, c5, MemberOffset(32));
+  HInstruction* goto_loop_right = new (GetAllocator()) HGoto();
+  loop_if_right->AddInstruction(write_loop_right);
+  loop_if_right->AddInstruction(goto_loop_right);
+
+  HInstruction* goto_loop_merge = new (GetAllocator()) HGoto();
+  loop_merge->AddInstruction(goto_loop_merge);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  EXPECT_INS_REMOVED(read_bottom) << *read_bottom;
+  ASSERT_TRUE(pred_get != nullptr);
+  HPhi* inst_return_phi = pred_get->GetTarget()->AsPhi();
+  ASSERT_TRUE(inst_return_phi != nullptr) << pred_get->GetTarget()->DumpWithArgs();
+  EXPECT_INS_EQ(inst_return_phi->InputAt(0), graph_->GetNullConstant());
+  EXPECT_INS_EQ(inst_return_phi->InputAt(1),
+                FindSingleInstruction<HNewInstance>(graph_, escape->GetSinglePredecessor()));
+  HPhi* inst_value_phi = pred_get->GetDefaultValue()->AsPhi();
+  ASSERT_TRUE(inst_value_phi != nullptr) << pred_get->GetDefaultValue()->DumpWithArgs();
+  HPhi* loop_header_phi = FindSingleInstruction<HPhi>(graph_, loop_header);
+  HPhi* loop_merge_phi = FindSingleInstruction<HPhi>(graph_, loop_merge);
+  EXPECT_INS_EQ(inst_value_phi, loop_header_phi);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(0), c3);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(1), loop_merge_phi);
+  EXPECT_INS_EQ(loop_merge_phi->InputAt(0), loop_header_phi);
+  EXPECT_INS_EQ(loop_merge_phi->InputAt(1), c5);
+  EXPECT_INS_RETAINED(write_loop_right) << *write_loop_right;
+  EXPECT_TRUE(write_loop_right->AsInstanceFieldSet()->GetIsPredicatedSet()) << *write_loop_right;
+  EXPECT_INS_RETAINED(write_pre_header) << *write_pre_header;
+  EXPECT_TRUE(write_pre_header->AsInstanceFieldSet()->GetIsPredicatedSet()) << *write_pre_header;
+}
+
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// while (!test()) {
+//   if (test2()) { } else { obj.field += 5; }
+// }
+// if (parameter_value) {
+//   escape(obj);
+// }
+// EXIT
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialLoopPhis5) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "loop_pre_header"},
+                                                  {"loop_pre_header", "loop_header"},
+                                                  {"loop_header", "escape_check"},
+                                                  {"loop_header", "loop_body"},
+                                                  {"loop_body", "loop_if_left"},
+                                                  {"loop_body", "loop_if_right"},
+                                                  {"loop_if_left", "loop_merge"},
+                                                  {"loop_if_right", "loop_merge"},
+                                                  {"loop_merge", "loop_header"},
+                                                  {"escape_check", "escape"},
+                                                  {"escape_check", "no_escape"},
+                                                  {"no_escape", "breturn"},
+                                                  {"escape", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(no_escape);
+  GET_BLOCK(escape);
+  GET_BLOCK(escape_check);
+
+  GET_BLOCK(loop_pre_header);
+  GET_BLOCK(loop_header);
+  GET_BLOCK(loop_body);
+  GET_BLOCK(loop_if_left);
+  GET_BLOCK(loop_if_right);
+  GET_BLOCK(loop_merge);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {no_escape, escape});
+  EnsurePredecessorOrder(loop_header, {loop_pre_header, loop_merge});
+  EnsurePredecessorOrder(loop_merge, {loop_if_left, loop_if_right});
+  CHECK_SUBROUTINE_FAILURE();
+  HInstruction* bool_val = MakeParam(DataType::Type::kBool);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(entry_goto);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_pre_header = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* goto_preheader = new (GetAllocator()) HGoto();
+  loop_pre_header->AddInstruction(write_pre_header);
+  loop_pre_header->AddInstruction(goto_preheader);
+
+  HInstruction* suspend_check_header = new (GetAllocator()) HSuspendCheck();
+  HInstruction* call_header = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_header = new (GetAllocator()) HIf(call_header);
+  loop_header->AddInstruction(suspend_check_header);
+  loop_header->AddInstruction(call_header);
+  loop_header->AddInstruction(if_header);
+  call_header->CopyEnvironmentFrom(cls->GetEnvironment());
+  suspend_check_header->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_loop_body = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_loop_body = new (GetAllocator()) HIf(call_loop_body);
+  loop_body->AddInstruction(call_loop_body);
+  loop_body->AddInstruction(if_loop_body);
+  call_loop_body->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_loop_left = new (GetAllocator()) HGoto();
+  loop_if_left->AddInstruction(goto_loop_left);
+
+  HInstruction* read_loop_right = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* add_loop_right =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, read_loop_right, c5);
+  HInstruction* write_loop_right = MakeIFieldSet(new_inst, add_loop_right, MemberOffset(32));
+  HInstruction* goto_loop_right = new (GetAllocator()) HGoto();
+  loop_if_right->AddInstruction(read_loop_right);
+  loop_if_right->AddInstruction(add_loop_right);
+  loop_if_right->AddInstruction(write_loop_right);
+  loop_if_right->AddInstruction(goto_loop_right);
+
+  HInstruction* goto_loop_merge = new (GetAllocator()) HGoto();
+  loop_merge->AddInstruction(goto_loop_merge);
+
+  HInstruction* if_esc_check = new (GetAllocator()) HIf(bool_val);
+  escape_check->AddInstruction(if_esc_check);
+
+  HInstruction* call_escape = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_escape = new (GetAllocator()) HGoto();
+  escape->AddInstruction(call_escape);
+  escape->AddInstruction(goto_escape);
+  call_escape->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_no_escape = new (GetAllocator()) HGoto();
+  no_escape->AddInstruction(goto_no_escape);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  EXPECT_INS_REMOVED(read_bottom) << *read_bottom;
+  ASSERT_TRUE(pred_get != nullptr);
+  HPhi* inst_return_phi = pred_get->GetTarget()->AsPhi();
+  ASSERT_TRUE(inst_return_phi != nullptr) << pred_get->GetTarget()->DumpWithArgs();
+  EXPECT_INS_EQ(inst_return_phi->InputAt(0), graph_->GetNullConstant());
+  EXPECT_INS_EQ(inst_return_phi->InputAt(1),
+                FindSingleInstruction<HNewInstance>(graph_, escape->GetSinglePredecessor()));
+  HPhi* inst_value_phi = pred_get->GetDefaultValue()->AsPhi();
+  ASSERT_TRUE(inst_value_phi != nullptr) << pred_get->GetDefaultValue()->DumpWithArgs();
+  HPhi* loop_header_phi = FindSingleInstruction<HPhi>(graph_, loop_header);
+  HPhi* loop_merge_phi = FindSingleInstruction<HPhi>(graph_, loop_merge);
+  EXPECT_INS_EQ(inst_value_phi->InputAt(0), loop_header_phi);
+  EXPECT_INS_EQ(inst_value_phi->InputAt(1), graph_->GetIntConstant(0));
+  EXPECT_INS_EQ(loop_header_phi->InputAt(0), c3);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(1), loop_merge_phi);
+  EXPECT_INS_EQ(loop_merge_phi->InputAt(0), loop_header_phi);
+  EXPECT_INS_EQ(loop_merge_phi->InputAt(1), add_loop_right);
+  EXPECT_INS_EQ(add_loop_right->InputAt(0), loop_header_phi);
+  EXPECT_INS_EQ(add_loop_right->InputAt(1), c5);
+  HInstanceFieldSet* mat_set =
+      FindSingleInstruction<HInstanceFieldSet>(graph_, escape->GetSinglePredecessor());
+  ASSERT_NE(mat_set, nullptr);
+  EXPECT_INS_EQ(mat_set->InputAt(1), loop_header_phi);
+  EXPECT_INS_REMOVED(write_loop_right) << *write_loop_right;
+  EXPECT_INS_REMOVED(write_pre_header) << *write_pre_header;
+}
+
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// if (param) {
+//   while (!test()) {
+//     if (test2()) {
+//       noescape();
+//     } else {
+//       abc = obj.field;
+//       obj.field = abc + 5;
+//       noescape();
+//     }
+//   }
+//   escape(obj);
+// } else {
+// }
+// return obj.field
+TEST_F(LoadStoreEliminationTest, PartialLoopPhis6) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(/*handles=*/&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "start"},
+                                                  {"start", "left"},
+                                                  {"start", "right"},
+                                                  {"left", "loop_pre_header"},
+
+                                                  {"loop_pre_header", "loop_header"},
+                                                  {"loop_header", "escape"},
+                                                  {"loop_header", "loop_body"},
+                                                  {"loop_body", "loop_if_left"},
+                                                  {"loop_body", "loop_if_right"},
+                                                  {"loop_if_left", "loop_header"},
+                                                  {"loop_if_right", "loop_header"},
+
+                                                  {"escape", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(start);
+  GET_BLOCK(escape);
+
+  GET_BLOCK(loop_pre_header);
+  GET_BLOCK(loop_header);
+  GET_BLOCK(loop_body);
+  GET_BLOCK(loop_if_left);
+  GET_BLOCK(loop_if_right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {escape, right});
+  EnsurePredecessorOrder(loop_header, {loop_pre_header, loop_if_left, loop_if_right});
+  CHECK_SUBROUTINE_FAILURE();
+  HInstruction* bool_val = MakeParam(DataType::Type::kBool);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c5 = graph_->GetIntConstant(5);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_entry = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* entry_goto = new (GetAllocator()) HGoto();
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_entry);
+  entry->AddInstruction(entry_goto);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  start->AddInstruction(new (GetAllocator()) HIf(bool_val));
+
+  HInstruction* left_goto = new (GetAllocator()) HGoto();
+  left->AddInstruction(left_goto);
+
+  HInstruction* goto_preheader = new (GetAllocator()) HGoto();
+  loop_pre_header->AddInstruction(goto_preheader);
+
+  HInstruction* suspend_check_header = new (GetAllocator()) HSuspendCheck();
+  HInstruction* call_header = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_header = new (GetAllocator()) HIf(call_header);
+  loop_header->AddInstruction(suspend_check_header);
+  loop_header->AddInstruction(call_header);
+  loop_header->AddInstruction(if_header);
+  call_header->CopyEnvironmentFrom(cls->GetEnvironment());
+  suspend_check_header->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_loop_body = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* if_loop_body = new (GetAllocator()) HIf(call_loop_body);
+  loop_body->AddInstruction(call_loop_body);
+  loop_body->AddInstruction(if_loop_body);
+  call_loop_body->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_loop_left = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* goto_loop_left = new (GetAllocator()) HGoto();
+  loop_if_left->AddInstruction(call_loop_left);
+  loop_if_left->AddInstruction(goto_loop_left);
+  call_loop_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* read_loop_right = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* add_loop_right =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, c5, read_loop_right);
+  HInstruction* write_loop_right = MakeIFieldSet(new_inst, add_loop_right, MemberOffset(32));
+  HInstruction* call_loop_right = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* goto_loop_right = new (GetAllocator()) HGoto();
+  loop_if_right->AddInstruction(read_loop_right);
+  loop_if_right->AddInstruction(add_loop_right);
+  loop_if_right->AddInstruction(write_loop_right);
+  loop_if_right->AddInstruction(call_loop_right);
+  loop_if_right->AddInstruction(goto_loop_right);
+  call_loop_right->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_escape = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_escape = new (GetAllocator()) HGoto();
+  escape->AddInstruction(call_escape);
+  escape->AddInstruction(goto_escape);
+  call_escape->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
+  breturn->AddInstruction(read_bottom);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSEWithPartial();
+  LOG(INFO) << "Post LSE " << blks;
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  EXPECT_INS_REMOVED(read_bottom) << *read_bottom;
+  ASSERT_TRUE(pred_get != nullptr);
+  HPhi* inst_return_phi = pred_get->GetTarget()->AsPhi();
+  ASSERT_TRUE(inst_return_phi != nullptr) << pred_get->GetTarget()->DumpWithArgs();
+  EXPECT_INS_EQ(inst_return_phi->InputAt(0),
+                FindSingleInstruction<HNewInstance>(graph_, escape->GetSinglePredecessor()));
+  EXPECT_INS_EQ(inst_return_phi->InputAt(1), graph_->GetNullConstant());
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(0), graph_->GetIntConstant(0));
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(1), c3);
+  HPhi* loop_header_phi = FindSingleInstruction<HPhi>(graph_, loop_header);
+  ASSERT_NE(loop_header_phi, nullptr);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(0), c3);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(1), loop_header_phi);
+  EXPECT_INS_EQ(loop_header_phi->InputAt(2), add_loop_right);
+  EXPECT_INS_EQ(add_loop_right->InputAt(0), c5);
+  EXPECT_INS_EQ(add_loop_right->InputAt(1), loop_header_phi);
+  HInstanceFieldSet* mat_set =
+      FindSingleInstruction<HInstanceFieldSet>(graph_, escape->GetSinglePredecessor());
+  ASSERT_NE(mat_set, nullptr);
+  EXPECT_INS_EQ(mat_set->InputAt(1), loop_header_phi);
+  EXPECT_INS_REMOVED(write_loop_right);
+  EXPECT_INS_REMOVED(write_entry);
+  EXPECT_INS_RETAINED(call_header);
+  EXPECT_INS_RETAINED(call_loop_left);
+  EXPECT_INS_RETAINED(call_loop_right);
+}
+
+// TODO This should really be in an Instruction simplifier Gtest but (1) that
+// doesn't exist and (2) we should move this simplification to directly in the
+// LSE pass since there is more information then.
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// if (param) {
+//   escape(obj);
+// } else {
+//   obj.field = 10;
+// }
+// return obj.field;
+TEST_F(LoadStoreEliminationTest, SimplifyTest) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_start = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_start);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_right = MakeIFieldSet(new_inst, c10, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+
+  HInstruction* read_end = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_end);
+  breturn->AddInstruction(read_end);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSE();
+
+  // Run the code-simplifier too
+  LOG(INFO) << "Pre simplification " << blks;
+  InstructionSimplifier simp(graph_, /*codegen=*/nullptr);
+  simp.Run();
+
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_REMOVED(write_start);
+  EXPECT_INS_REMOVED(read_end);
+  EXPECT_INS_RETAINED(call_left);
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  ASSERT_NE(pred_get, nullptr);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), c10);
+}
+
+
+// TODO This should really be in an Instruction simplifier Gtest but (1) that
+// doesn't exist and (2) we should move this simplification to directly in the
+// LSE pass since there is more information then.
+//
+// This checks that we don't replace phis when the replacement isn't valid at
+// that point (i.e. it doesn't dominate)
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// if (param) {
+//   escape(obj);
+// } else {
+//   obj.field = noescape();
+// }
+// return obj.field;
+TEST_F(LoadStoreEliminationTest, SimplifyTest2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+                                                  {"right", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, right});
+
+  HInstruction* bool_value = MakeParam(DataType::Type::kBool);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_start = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_start);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, {new_inst});
+  HInstruction* goto_left = new (GetAllocator()) HGoto();
+  left->AddInstruction(call_left);
+  left->AddInstruction(goto_left);
+  call_left->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_right = MakeInvoke(DataType::Type::kInt32, {});
+  HInstruction* write_right = MakeIFieldSet(new_inst, call_right, MemberOffset(32));
+  HInstruction* goto_right = new (GetAllocator()) HGoto();
+  right->AddInstruction(call_right);
+  right->AddInstruction(write_right);
+  right->AddInstruction(goto_right);
+  call_right->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* read_end = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_end);
+  breturn->AddInstruction(read_end);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSE();
+
+  // Run the code-simplifier too
+  LOG(INFO) << "Pre simplification " << blks;
+  InstructionSimplifier simp(graph_, /*codegen=*/nullptr);
+  simp.Run();
+
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(write_right);
+  EXPECT_INS_REMOVED(write_start);
+  EXPECT_INS_REMOVED(read_end);
+  EXPECT_INS_RETAINED(call_left);
+  EXPECT_INS_RETAINED(call_right);
+  EXPECT_EQ(call_right->GetBlock(), right);
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  ASSERT_NE(pred_get, nullptr);
+  EXPECT_TRUE(pred_get->GetDefaultValue()->IsPhi()) << pred_get->DumpWithArgs();
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(0), graph_->GetIntConstant(0))
+      << pred_get->DumpWithArgs();
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(1), call_right) << pred_get->DumpWithArgs();
+}
+
+// TODO This should really be in an Instruction simplifier Gtest but (1) that
+// doesn't exist and (2) we should move this simplification to directly in the
+// LSE pass since there is more information then.
+//
+// This checks that we replace phis even when there are multiple replacements as
+// long as they are equal
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// switch (param) {
+//   case 1:
+//     escape(obj);
+//     break;
+//   case 2:
+//     obj.field = 10;
+//     break;
+//   case 3:
+//     obj.field = 10;
+//     break;
+// }
+// return obj.field;
+TEST_F(LoadStoreEliminationTest, SimplifyTest3) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "case1"},
+                                                  {"entry", "case2"},
+                                                  {"entry", "case3"},
+                                                  {"case1", "breturn"},
+                                                  {"case2", "breturn"},
+                                                  {"case3", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(case1);
+  GET_BLOCK(case2);
+  GET_BLOCK(case3);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {case1, case2, case3});
+
+  HInstruction* int_val = MakeParam(DataType::Type::kInt32);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_start = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* switch_inst = new (GetAllocator()) HPackedSwitch(0, 2, int_val);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_start);
+  entry->AddInstruction(switch_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_case1 = MakeInvoke(DataType::Type::kVoid, {new_inst});
+  HInstruction* goto_case1 = new (GetAllocator()) HGoto();
+  case1->AddInstruction(call_case1);
+  case1->AddInstruction(goto_case1);
+  call_case1->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_case2 = MakeIFieldSet(new_inst, c10, MemberOffset(32));
+  HInstruction* goto_case2 = new (GetAllocator()) HGoto();
+  case2->AddInstruction(write_case2);
+  case2->AddInstruction(goto_case2);
+
+  HInstruction* write_case3 = MakeIFieldSet(new_inst, c10, MemberOffset(32));
+  HInstruction* goto_case3 = new (GetAllocator()) HGoto();
+  case3->AddInstruction(write_case3);
+  case3->AddInstruction(goto_case3);
+
+  HInstruction* read_end = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_end);
+  breturn->AddInstruction(read_end);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSE();
+
+  // Run the code-simplifier too
+  LOG(INFO) << "Pre simplification " << blks;
+  InstructionSimplifier simp(graph_, /*codegen=*/nullptr);
+  simp.Run();
+
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(write_case2);
+  EXPECT_INS_REMOVED(write_case3);
+  EXPECT_INS_REMOVED(write_start);
+  EXPECT_INS_REMOVED(read_end);
+  EXPECT_INS_RETAINED(call_case1);
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  ASSERT_NE(pred_get, nullptr);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue(), c10)
+      << pred_get->DumpWithArgs();
+}
+
+// TODO This should really be in an Instruction simplifier Gtest but (1) that
+// doesn't exist and (2) we should move this simplification to directly in the
+// LSE pass since there is more information then.
+//
+// This checks that we don't replace phis even when there are multiple
+// replacements if they are not equal
+// // ENTRY
+// obj = new Obj();
+// obj.field = 3;
+// switch (param) {
+//   case 1:
+//     escape(obj);
+//     break;
+//   case 2:
+//     obj.field = 10;
+//     break;
+//   case 3:
+//     obj.field = 20;
+//     break;
+// }
+// return obj.field;
+TEST_F(LoadStoreEliminationTest, SimplifyTest4) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "case1"},
+                                                  {"entry", "case2"},
+                                                  {"entry", "case3"},
+                                                  {"case1", "breturn"},
+                                                  {"case2", "breturn"},
+                                                  {"case3", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(case1);
+  GET_BLOCK(case2);
+  GET_BLOCK(case3);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {case1, case2, case3});
+
+  HInstruction* int_val = MakeParam(DataType::Type::kInt32);
+  HInstruction* c3 = graph_->GetIntConstant(3);
+  HInstruction* c10 = graph_->GetIntConstant(10);
+  HInstruction* c20 = graph_->GetIntConstant(20);
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_start = MakeIFieldSet(new_inst, c3, MemberOffset(32));
+  HInstruction* switch_inst = new (GetAllocator()) HPackedSwitch(0, 2, int_val);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_start);
+  entry->AddInstruction(switch_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* call_case1 = MakeInvoke(DataType::Type::kVoid, {new_inst});
+  HInstruction* goto_case1 = new (GetAllocator()) HGoto();
+  case1->AddInstruction(call_case1);
+  case1->AddInstruction(goto_case1);
+  call_case1->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* write_case2 = MakeIFieldSet(new_inst, c10, MemberOffset(32));
+  HInstruction* goto_case2 = new (GetAllocator()) HGoto();
+  case2->AddInstruction(write_case2);
+  case2->AddInstruction(goto_case2);
+
+  HInstruction* write_case3 = MakeIFieldSet(new_inst, c20, MemberOffset(32));
+  HInstruction* goto_case3 = new (GetAllocator()) HGoto();
+  case3->AddInstruction(write_case3);
+  case3->AddInstruction(goto_case3);
+
+  HInstruction* read_end = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_end);
+  breturn->AddInstruction(read_end);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSE();
+
+  // Run the code-simplifier too
+  LOG(INFO) << "Pre simplification " << blks;
+  InstructionSimplifier simp(graph_, /*codegen=*/nullptr);
+  simp.Run();
+
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_REMOVED(write_case2);
+  EXPECT_INS_REMOVED(write_case3);
+  EXPECT_INS_REMOVED(write_start);
+  EXPECT_INS_REMOVED(read_end);
+  EXPECT_INS_RETAINED(call_case1);
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  ASSERT_NE(pred_get, nullptr);
+  EXPECT_TRUE(pred_get->GetDefaultValue()->IsPhi())
+      << pred_get->DumpWithArgs();
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(0), graph_->GetIntConstant(0));
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(1), c10);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(2), c20);
+}
+
+// Make sure that irreducible loops don't screw up Partial LSE. We can't pull
+// phis through them so we need to treat them as escapes.
+// TODO We should be able to do better than this? Need to do some research.
+// // ENTRY
+// obj = new Obj();
+// obj.foo = 11;
+// if (param1) {
+// } else {
+//   // irreducible loop here. NB the objdoesn't actually escape
+//   obj.foo = 33;
+//   if (param2) {
+//     goto inner;
+//   } else {
+//     while (test()) {
+//       if (test()) {
+//         obj.foo = 66;
+//       } else {
+//       }
+//       inner:
+//     }
+//   }
+// }
+// return obj.foo;
+TEST_F(LoadStoreEliminationTest, PartialIrreducibleLoop) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("start",
+                                                 "exit",
+                                                 {{"start", "entry"},
+                                                  {"entry", "left"},
+                                                  {"entry", "right"},
+                                                  {"left", "breturn"},
+
+                                                  {"right", "right_crit_break_loop"},
+                                                  {"right_crit_break_loop", "loop_header"},
+                                                  {"right", "right_crit_break_end"},
+                                                  {"right_crit_break_end", "loop_end"},
+
+                                                  {"loop_header", "loop_body"},
+                                                  {"loop_body", "loop_left"},
+                                                  {"loop_body", "loop_right"},
+                                                  {"loop_left", "loop_end"},
+                                                  {"loop_right", "loop_end"},
+                                                  {"loop_end", "loop_header"},
+                                                  {"loop_header", "loop_header_crit_break"},
+                                                  {"loop_header_crit_break", "breturn"},
+
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(start);
+  GET_BLOCK(entry);
+  GET_BLOCK(exit);
+  GET_BLOCK(breturn);
+  GET_BLOCK(left);
+  GET_BLOCK(right);
+  GET_BLOCK(right_crit_break_end);
+  GET_BLOCK(right_crit_break_loop);
+  GET_BLOCK(loop_header);
+  GET_BLOCK(loop_header_crit_break);
+  GET_BLOCK(loop_body);
+  GET_BLOCK(loop_left);
+  GET_BLOCK(loop_right);
+  GET_BLOCK(loop_end);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(breturn, {left, loop_header_crit_break});
+  HInstruction* c11 = graph_->GetIntConstant(11);
+  HInstruction* c33 = graph_->GetIntConstant(33);
+  HInstruction* c66 = graph_->GetIntConstant(66);
+  HInstruction* param1 = MakeParam(DataType::Type::kBool);
+  HInstruction* param2 = MakeParam(DataType::Type::kBool);
+
+  HInstruction* suspend = new (GetAllocator()) HSuspendCheck();
+  HInstruction* start_goto = new (GetAllocator()) HGoto();
+  start->AddInstruction(suspend);
+  start->AddInstruction(start_goto);
+  ManuallyBuildEnvFor(suspend, {});
+
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* write_start = MakeIFieldSet(new_inst, c11, MemberOffset(32));
+  HInstruction* if_inst = new (GetAllocator()) HIf(param1);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(write_start);
+  entry->AddInstruction(if_inst);
+  ManuallyBuildEnvFor(cls, {});
+  new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  left->AddInstruction(new (GetAllocator()) HGoto());
+
+  right->AddInstruction(MakeIFieldSet(new_inst, c33, MemberOffset(32)));
+  right->AddInstruction(new (GetAllocator()) HIf(param2));
+
+  right_crit_break_end->AddInstruction(new (GetAllocator()) HGoto());
+  right_crit_break_loop->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* header_suspend = new (GetAllocator()) HSuspendCheck();
+  HInstruction* header_invoke = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* header_if = new (GetAllocator()) HIf(header_invoke);
+  loop_header->AddInstruction(header_suspend);
+  loop_header->AddInstruction(header_invoke);
+  loop_header->AddInstruction(header_if);
+  header_suspend->CopyEnvironmentFrom(cls->GetEnvironment());
+  header_invoke->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* body_invoke = MakeInvoke(DataType::Type::kBool, {});
+  HInstruction* body_if = new (GetAllocator()) HIf(body_invoke);
+  loop_body->AddInstruction(body_invoke);
+  loop_body->AddInstruction(body_if);
+  body_invoke->CopyEnvironmentFrom(cls->GetEnvironment());
+
+  HInstruction* left_set = MakeIFieldSet(new_inst, c66, MemberOffset(32));
+  HInstruction* left_goto = MakeIFieldSet(new_inst, c66, MemberOffset(32));
+  loop_left->AddInstruction(left_set);
+  loop_left->AddInstruction(left_goto);
+
+  loop_right->AddInstruction(new (GetAllocator()) HGoto());
+
+  loop_end->AddInstruction(new (GetAllocator()) HGoto());
+
+  HInstruction* read_end = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* return_exit = new (GetAllocator()) HReturn(read_end);
+  breturn->AddInstruction(read_end);
+  breturn->AddInstruction(return_exit);
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSE();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_TRUE(loop_header->IsLoopHeader());
+  EXPECT_TRUE(loop_header->GetLoopInformation()->IsIrreducible());
+
+  EXPECT_INS_RETAINED(left_set);
+  EXPECT_INS_REMOVED(write_start);
+  EXPECT_INS_REMOVED(read_end);
+
+  HPredicatedInstanceFieldGet* pred_get =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  ASSERT_NE(pred_get, nullptr);
+  ASSERT_TRUE(pred_get->GetDefaultValue()->IsPhi()) << pred_get->DumpWithArgs();
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(0), c11);
+  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(1), graph_->GetIntConstant(0));
+  ASSERT_TRUE(pred_get->GetTarget()->IsPhi()) << pred_get->DumpWithArgs();
+  EXPECT_INS_EQ(pred_get->GetTarget()->InputAt(0), graph_->GetNullConstant());
+  HNewInstance* mat = FindSingleInstruction<HNewInstance>(graph_, right->GetSinglePredecessor());
+  ASSERT_NE(mat, nullptr);
+  EXPECT_INS_EQ(pred_get->GetTarget()->InputAt(1), mat);
+}
+
+enum class UsesOrder { kDefaultOrder, kReverseOrder };
+std::ostream& operator<<(std::ostream& os, const UsesOrder& ord) {
+  switch (ord) {
+    case UsesOrder::kDefaultOrder:
+      return os << "DefaultOrder";
+    case UsesOrder::kReverseOrder:
+      return os << "ReverseOrder";
+  }
+}
+
+class UsesOrderDependentTestGroup
+    : public LoadStoreEliminationTestBase<CommonCompilerTestWithParam<UsesOrder>> {};
+
+// Make sure that we record replacements by predicated loads and use them
+// instead of constructing Phis with inputs removed from the graph. Bug: 183897743
+// Note that the bug was hit only for a certain ordering of the NewInstance
+// uses, so we test both orderings.
+// // ENTRY
+// obj = new Obj();
+// obj.foo = 11;
+// if (param1) {
+//   // LEFT1
+//   escape(obj);
+// } else {
+//   // RIGHT1
+// }
+// // MIDDLE
+// a = obj.foo;
+// if (param2) {
+//   // LEFT2
+//   obj.foo = 33;
+// } else {
+//   // RIGHT2
+// }
+// // BRETURN
+// no_escape()  // If `obj` escaped, the field value can change. (Avoid non-partial LSE.)
+// b = obj.foo;
+// return a + b;
+TEST_P(UsesOrderDependentTestGroup, RecordPredicatedReplacements1) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left1"},
+                                                  {"entry", "right1"},
+                                                  {"left1", "middle"},
+                                                  {"right1", "middle"},
+                                                  {"middle", "left2"},
+                                                  {"middle", "right2"},
+                                                  {"left2", "breturn"},
+                                                  {"right2", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(left1);
+  GET_BLOCK(right1);
+  GET_BLOCK(middle);
+  GET_BLOCK(left2);
+  GET_BLOCK(right2);
+  GET_BLOCK(breturn);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(middle, {left1, right1});
+  EnsurePredecessorOrder(breturn, {left2, right2});
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* cnull = graph_->GetNullConstant();
+  HInstruction* c11 = graph_->GetIntConstant(11);
+  HInstruction* c33 = graph_->GetIntConstant(33);
+  HInstruction* param1 = MakeParam(DataType::Type::kBool);
+  HInstruction* param2 = MakeParam(DataType::Type::kBool);
+
+  HInstruction* suspend = new (GetAllocator()) HSuspendCheck();
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* entry_write = MakeIFieldSet(new_inst, c11, MemberOffset(32));
+  HInstruction* entry_if = new (GetAllocator()) HIf(param1);
+  entry->AddInstruction(suspend);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(entry_write);
+  entry->AddInstruction(entry_if);
+  ManuallyBuildEnvFor(suspend, {});
+  ManuallyBuildEnvFor(cls, {});
+  ManuallyBuildEnvFor(new_inst, {});
+
+  HInstruction* left1_call = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* left1_goto = new (GetAllocator()) HGoto();
+  left1->AddInstruction(left1_call);
+  left1->AddInstruction(left1_goto);
+  ManuallyBuildEnvFor(left1_call, {});
+
+  HInstruction* right1_goto = new (GetAllocator()) HGoto();
+  right1->AddInstruction(right1_goto);
+
+  HInstruction* middle_read = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* middle_if = new (GetAllocator()) HIf(param2);
+  if (GetParam() == UsesOrder::kDefaultOrder) {
+    middle->AddInstruction(middle_read);
+  }
+  middle->AddInstruction(middle_if);
+
+  HInstanceFieldSet* left2_write = MakeIFieldSet(new_inst, c33, MemberOffset(32));
+  HInstruction* left2_goto = new (GetAllocator()) HGoto();
+  left2->AddInstruction(left2_write);
+  left2->AddInstruction(left2_goto);
+
+  HInstruction* right2_goto = new (GetAllocator()) HGoto();
+  right2->AddInstruction(right2_goto);
+
+  HInstruction* breturn_call = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* breturn_read = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* breturn_add =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, middle_read, breturn_read);
+  HInstruction* breturn_return = new (GetAllocator()) HReturn(breturn_add);
+  breturn->AddInstruction(breturn_call);
+  breturn->AddInstruction(breturn_read);
+  breturn->AddInstruction(breturn_add);
+  breturn->AddInstruction(breturn_return);
+  ManuallyBuildEnvFor(breturn_call, {});
+
+  if (GetParam() == UsesOrder::kReverseOrder) {
+    // Insert `middle_read` in the same position as for the `kDefaultOrder` case.
+    // The only difference is the order of entries in `new_inst->GetUses()` which
+    // is used by `HeapReferenceData::CollectReplacements()` and defines the order
+    // of instructions to process for `HeapReferenceData::PredicateInstructions()`.
+    middle->InsertInstructionBefore(middle_read, middle_if);
+  }
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSE();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_RETAINED(cls);
+  EXPECT_INS_REMOVED(new_inst);
+  HNewInstance* replacement_new_inst = FindSingleInstruction<HNewInstance>(graph_);
+  ASSERT_NE(replacement_new_inst, nullptr);
+  EXPECT_INS_REMOVED(entry_write);
+  std::vector<HInstanceFieldSet*> all_writes;
+  std::tie(all_writes) = FindAllInstructions<HInstanceFieldSet>(graph_);
+  ASSERT_EQ(2u, all_writes.size());
+  ASSERT_NE(all_writes[0] == left2_write, all_writes[1] == left2_write);
+  HInstanceFieldSet* replacement_write = all_writes[(all_writes[0] == left2_write) ? 1u : 0u];
+  ASSERT_FALSE(replacement_write->GetIsPredicatedSet());
+  ASSERT_INS_EQ(replacement_write->InputAt(0), replacement_new_inst);
+  ASSERT_INS_EQ(replacement_write->InputAt(1), c11);
+
+  EXPECT_INS_RETAINED(left1_call);
+
+  EXPECT_INS_REMOVED(middle_read);
+  HPredicatedInstanceFieldGet* replacement_middle_read =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, middle);
+  ASSERT_NE(replacement_middle_read, nullptr);
+  ASSERT_TRUE(replacement_middle_read->GetTarget()->IsPhi());
+  ASSERT_EQ(2u, replacement_middle_read->GetTarget()->AsPhi()->InputCount());
+  ASSERT_INS_EQ(replacement_middle_read->GetTarget()->AsPhi()->InputAt(0), replacement_new_inst);
+  ASSERT_INS_EQ(replacement_middle_read->GetTarget()->AsPhi()->InputAt(1), cnull);
+  ASSERT_TRUE(replacement_middle_read->GetDefaultValue()->IsPhi());
+  ASSERT_EQ(2u, replacement_middle_read->GetDefaultValue()->AsPhi()->InputCount());
+  ASSERT_INS_EQ(replacement_middle_read->GetDefaultValue()->AsPhi()->InputAt(0), c0);
+  ASSERT_INS_EQ(replacement_middle_read->GetDefaultValue()->AsPhi()->InputAt(1), c11);
+
+  EXPECT_INS_RETAINED(left2_write);
+  ASSERT_TRUE(left2_write->GetIsPredicatedSet());
+
+  EXPECT_INS_REMOVED(breturn_read);
+  HPredicatedInstanceFieldGet* replacement_breturn_read =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  ASSERT_NE(replacement_breturn_read, nullptr);
+  ASSERT_INS_EQ(replacement_breturn_read->GetTarget(), replacement_middle_read->GetTarget());
+  ASSERT_TRUE(replacement_breturn_read->GetDefaultValue()->IsPhi());
+  ASSERT_EQ(2u, replacement_breturn_read->GetDefaultValue()->AsPhi()->InputCount());
+  ASSERT_INS_EQ(replacement_breturn_read->GetDefaultValue()->AsPhi()->InputAt(0), c33);
+  HInstruction* other_input = replacement_breturn_read->GetDefaultValue()->AsPhi()->InputAt(1);
+  ASSERT_NE(other_input->GetBlock(), nullptr) << GetParam();
+  ASSERT_INS_EQ(other_input, replacement_middle_read);
+}
+
+// Regression test for a bad DCHECK() found while trying to write a test for b/188188275.
+// // ENTRY
+// obj = new Obj();
+// obj.foo = 11;
+// if (param1) {
+//   // LEFT1
+//   escape(obj);
+// } else {
+//   // RIGHT1
+// }
+// // MIDDLE
+// a = obj.foo;
+// if (param2) {
+//   // LEFT2
+//   no_escape();
+// } else {
+//   // RIGHT2
+// }
+// // BRETURN
+// b = obj.foo;
+// return a + b;
+TEST_P(UsesOrderDependentTestGroup, RecordPredicatedReplacements2) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left1"},
+                                                  {"entry", "right1"},
+                                                  {"left1", "middle"},
+                                                  {"right1", "middle"},
+                                                  {"middle", "left2"},
+                                                  {"middle", "right2"},
+                                                  {"left2", "breturn"},
+                                                  {"right2", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(left1);
+  GET_BLOCK(right1);
+  GET_BLOCK(middle);
+  GET_BLOCK(left2);
+  GET_BLOCK(right2);
+  GET_BLOCK(breturn);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(middle, {left1, right1});
+  EnsurePredecessorOrder(breturn, {left2, right2});
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* cnull = graph_->GetNullConstant();
+  HInstruction* c11 = graph_->GetIntConstant(11);
+  HInstruction* param1 = MakeParam(DataType::Type::kBool);
+  HInstruction* param2 = MakeParam(DataType::Type::kBool);
+
+  HInstruction* suspend = new (GetAllocator()) HSuspendCheck();
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* entry_write = MakeIFieldSet(new_inst, c11, MemberOffset(32));
+  HInstruction* entry_if = new (GetAllocator()) HIf(param1);
+  entry->AddInstruction(suspend);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(entry_write);
+  entry->AddInstruction(entry_if);
+  ManuallyBuildEnvFor(suspend, {});
+  ManuallyBuildEnvFor(cls, {});
+  ManuallyBuildEnvFor(new_inst, {});
+
+  HInstruction* left1_call = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* left1_goto = new (GetAllocator()) HGoto();
+  left1->AddInstruction(left1_call);
+  left1->AddInstruction(left1_goto);
+  ManuallyBuildEnvFor(left1_call, {});
+
+  HInstruction* right1_goto = new (GetAllocator()) HGoto();
+  right1->AddInstruction(right1_goto);
+
+  HInstruction* middle_read = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* middle_if = new (GetAllocator()) HIf(param2);
+  if (GetParam() == UsesOrder::kDefaultOrder) {
+    middle->AddInstruction(middle_read);
+  }
+  middle->AddInstruction(middle_if);
+
+  HInstruction* left2_call = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* left2_goto = new (GetAllocator()) HGoto();
+  left2->AddInstruction(left2_call);
+  left2->AddInstruction(left2_goto);
+  ManuallyBuildEnvFor(left2_call, {});
+
+  HInstruction* right2_goto = new (GetAllocator()) HGoto();
+  right2->AddInstruction(right2_goto);
+
+  HInstruction* breturn_read = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* breturn_add =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, middle_read, breturn_read);
+  HInstruction* breturn_return = new (GetAllocator()) HReturn(breturn_add);
+  breturn->AddInstruction(breturn_read);
+  breturn->AddInstruction(breturn_add);
+  breturn->AddInstruction(breturn_return);
+
+  if (GetParam() == UsesOrder::kReverseOrder) {
+    // Insert `middle_read` in the same position as for the `kDefaultOrder` case.
+    // The only difference is the order of entries in `new_inst->GetUses()` which
+    // is used by `HeapReferenceData::CollectReplacements()` and defines the order
+    // of instructions to process for `HeapReferenceData::PredicateInstructions()`.
+    middle->InsertInstructionBefore(middle_read, middle_if);
+  }
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSE();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_RETAINED(cls);
+  EXPECT_INS_REMOVED(new_inst);
+  HNewInstance* replacement_new_inst = FindSingleInstruction<HNewInstance>(graph_);
+  ASSERT_NE(replacement_new_inst, nullptr);
+  EXPECT_INS_REMOVED(entry_write);
+  HInstanceFieldSet* replacement_write = FindSingleInstruction<HInstanceFieldSet>(graph_);
+  ASSERT_NE(replacement_write, nullptr);
+  ASSERT_FALSE(replacement_write->GetIsPredicatedSet());
+  ASSERT_INS_EQ(replacement_write->InputAt(0), replacement_new_inst);
+  ASSERT_INS_EQ(replacement_write->InputAt(1), c11);
+
+  EXPECT_INS_RETAINED(left1_call);
+
+  EXPECT_INS_REMOVED(middle_read);
+  HPredicatedInstanceFieldGet* replacement_middle_read =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, middle);
+  ASSERT_NE(replacement_middle_read, nullptr);
+  ASSERT_TRUE(replacement_middle_read->GetTarget()->IsPhi());
+  ASSERT_EQ(2u, replacement_middle_read->GetTarget()->AsPhi()->InputCount());
+  ASSERT_INS_EQ(replacement_middle_read->GetTarget()->AsPhi()->InputAt(0), replacement_new_inst);
+  ASSERT_INS_EQ(replacement_middle_read->GetTarget()->AsPhi()->InputAt(1), cnull);
+  ASSERT_TRUE(replacement_middle_read->GetDefaultValue()->IsPhi());
+  ASSERT_EQ(2u, replacement_middle_read->GetDefaultValue()->AsPhi()->InputCount());
+  ASSERT_INS_EQ(replacement_middle_read->GetDefaultValue()->AsPhi()->InputAt(0), c0);
+  ASSERT_INS_EQ(replacement_middle_read->GetDefaultValue()->AsPhi()->InputAt(1), c11);
+
+  EXPECT_INS_RETAINED(left2_call);
+
+  EXPECT_INS_REMOVED(breturn_read);
+  HPredicatedInstanceFieldGet* replacement_breturn_read =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  ASSERT_NE(replacement_breturn_read, nullptr);
+  ASSERT_INS_EQ(replacement_breturn_read->GetTarget(), replacement_middle_read->GetTarget());
+  ASSERT_INS_EQ(replacement_breturn_read->GetDefaultValue(), replacement_middle_read);
+}
+
+INSTANTIATE_TEST_SUITE_P(LoadStoreEliminationTest,
+                         UsesOrderDependentTestGroup,
+                         testing::Values(UsesOrder::kDefaultOrder, UsesOrder::kReverseOrder));
+
+// The parameter is the number of times we call `std::next_permutation` (from 0 to 5)
+// so that we test all 6 permutation of three items.
+class UsesOrderDependentTestGroupForThreeItems
+    : public LoadStoreEliminationTestBase<CommonCompilerTestWithParam<size_t>> {};
+
+// Make sure that after we record replacements by predicated loads, we correctly
+// use that predicated load for Phi placeholders that were previously marked as
+// replaced by the now removed unpredicated load. (The fix for bug 183897743 was
+// not good enough.) Bug: 188188275
+// // ENTRY
+// obj = new Obj();
+// obj.foo = 11;
+// if (param1) {
+//   // LEFT1
+//   escape(obj);
+// } else {
+//   // RIGHT1
+// }
+// // MIDDLE1
+// a = obj.foo;
+// if (param2) {
+//   // LEFT2
+//   no_escape1();
+// } else {
+//   // RIGHT2
+// }
+// // MIDDLE2
+// if (param3) {
+//   // LEFT3
+//   x = obj.foo;
+//   no_escape2();
+// } else {
+//   // RIGHT3
+//   x = 0;
+// }
+// // BRETURN
+// b = obj.foo;
+// return a + b + x;
+TEST_P(UsesOrderDependentTestGroupForThreeItems, RecordPredicatedReplacements3) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope vshs(soa.Self());
+  CreateGraph(&vshs);
+  AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
+                                                 "exit",
+                                                 {{"entry", "left1"},
+                                                  {"entry", "right1"},
+                                                  {"left1", "middle1"},
+                                                  {"right1", "middle1"},
+                                                  {"middle1", "left2"},
+                                                  {"middle1", "right2"},
+                                                  {"left2", "middle2"},
+                                                  {"right2", "middle2"},
+                                                  {"middle2", "left3"},
+                                                  {"middle2", "right3"},
+                                                  {"left3", "breturn"},
+                                                  {"right3", "breturn"},
+                                                  {"breturn", "exit"}}));
+#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
+  GET_BLOCK(entry);
+  GET_BLOCK(left1);
+  GET_BLOCK(right1);
+  GET_BLOCK(middle1);
+  GET_BLOCK(left2);
+  GET_BLOCK(right2);
+  GET_BLOCK(middle2);
+  GET_BLOCK(left3);
+  GET_BLOCK(right3);
+  GET_BLOCK(breturn);
+  GET_BLOCK(exit);
+#undef GET_BLOCK
+  EnsurePredecessorOrder(middle1, {left1, right1});
+  EnsurePredecessorOrder(middle2, {left2, right2});
+  EnsurePredecessorOrder(breturn, {left3, right3});
+  HInstruction* c0 = graph_->GetIntConstant(0);
+  HInstruction* cnull = graph_->GetNullConstant();
+  HInstruction* c11 = graph_->GetIntConstant(11);
+  HInstruction* param1 = MakeParam(DataType::Type::kBool);
+  HInstruction* param2 = MakeParam(DataType::Type::kBool);
+  HInstruction* param3 = MakeParam(DataType::Type::kBool);
+
+  HInstruction* suspend = new (GetAllocator()) HSuspendCheck();
+  HInstruction* cls = MakeClassLoad();
+  HInstruction* new_inst = MakeNewInstance(cls);
+  HInstruction* entry_write = MakeIFieldSet(new_inst, c11, MemberOffset(32));
+  HInstruction* entry_if = new (GetAllocator()) HIf(param1);
+  entry->AddInstruction(suspend);
+  entry->AddInstruction(cls);
+  entry->AddInstruction(new_inst);
+  entry->AddInstruction(entry_write);
+  entry->AddInstruction(entry_if);
+  ManuallyBuildEnvFor(suspend, {});
+  ManuallyBuildEnvFor(cls, {});
+  ManuallyBuildEnvFor(new_inst, {});
+
+  HInstruction* left1_call = MakeInvoke(DataType::Type::kVoid, { new_inst });
+  HInstruction* left1_goto = new (GetAllocator()) HGoto();
+  left1->AddInstruction(left1_call);
+  left1->AddInstruction(left1_goto);
+  ManuallyBuildEnvFor(left1_call, {});
+
+  HInstruction* right1_goto = new (GetAllocator()) HGoto();
+  right1->AddInstruction(right1_goto);
+
+  HInstruction* middle1_read = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* middle1_if = new (GetAllocator()) HIf(param2);
+  // Delay inserting `middle1_read`, do that later with ordering based on `GetParam()`.
+  middle1->AddInstruction(middle1_if);
+
+  HInstruction* left2_call = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* left2_goto = new (GetAllocator()) HGoto();
+  left2->AddInstruction(left2_call);
+  left2->AddInstruction(left2_goto);
+  ManuallyBuildEnvFor(left2_call, {});
+
+  HInstruction* right2_goto = new (GetAllocator()) HGoto();
+  right2->AddInstruction(right2_goto);
+
+  HInstruction* middle2_if = new (GetAllocator()) HIf(param3);
+  middle2->AddInstruction(middle2_if);
+
+  HInstruction* left3_read = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* left3_call = MakeInvoke(DataType::Type::kVoid, {});
+  HInstruction* left3_goto = new (GetAllocator()) HGoto();
+  // Delay inserting `left3_read`, do that later with ordering based on `GetParam()`.
+  left3->AddInstruction(left3_call);
+  left3->AddInstruction(left3_goto);
+  ManuallyBuildEnvFor(left3_call, {});
+
+  HInstruction* right3_goto = new (GetAllocator()) HGoto();
+  right3->AddInstruction(right3_goto);
+
+  HPhi* breturn_phi = MakePhi({left3_read, c0});
+  HInstruction* breturn_read = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32));
+  HInstruction* breturn_add1 =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, middle1_read, breturn_read);
+  HInstruction* breturn_add2 =
+      new (GetAllocator()) HAdd(DataType::Type::kInt32, breturn_add1, breturn_phi);
+  HInstruction* breturn_return = new (GetAllocator()) HReturn(breturn_add2);
+  breturn->AddPhi(breturn_phi);
+  // Delay inserting `breturn_read`, do that later with ordering based on `GetParam()`.
+  breturn->AddInstruction(breturn_add1);
+  breturn->AddInstruction(breturn_add2);
+  breturn->AddInstruction(breturn_return);
+
+  // Insert reads in the same positions but in different insertion orders.
+  // The only difference is the order of entries in `new_inst->GetUses()` which
+  // is used by `HeapReferenceData::CollectReplacements()` and defines the order
+  // of instructions to process for `HeapReferenceData::PredicateInstructions()`.
+  std::tuple<size_t, HInstruction*, HInstruction*> read_insertions[] = {
+      { 0u, middle1_read, middle1_if },
+      { 1u, left3_read, left3_call },
+      { 2u, breturn_read, breturn_add1 },
+  };
+  for (size_t i = 0, num = GetParam(); i != num; ++i) {
+    std::next_permutation(read_insertions, read_insertions + std::size(read_insertions));
+  }
+  for (auto [order, read, cursor] : read_insertions) {
+    cursor->GetBlock()->InsertInstructionBefore(read, cursor);
+  }
+
+  SetupExit(exit);
+
+  // PerformLSE expects this to be empty.
+  graph_->ClearDominanceInformation();
+  LOG(INFO) << "Pre LSE " << blks;
+  PerformLSE();
+  LOG(INFO) << "Post LSE " << blks;
+
+  EXPECT_INS_RETAINED(cls);
+  EXPECT_INS_REMOVED(new_inst);
+  HNewInstance* replacement_new_inst = FindSingleInstruction<HNewInstance>(graph_);
+  ASSERT_NE(replacement_new_inst, nullptr);
+  EXPECT_INS_REMOVED(entry_write);
+  HInstanceFieldSet* replacement_write = FindSingleInstruction<HInstanceFieldSet>(graph_);
+  ASSERT_NE(replacement_write, nullptr);
+  ASSERT_FALSE(replacement_write->GetIsPredicatedSet());
+  ASSERT_INS_EQ(replacement_write->InputAt(0), replacement_new_inst);
+  ASSERT_INS_EQ(replacement_write->InputAt(1), c11);
+
+  EXPECT_INS_RETAINED(left1_call);
+
+  EXPECT_INS_REMOVED(middle1_read);
+  HPredicatedInstanceFieldGet* replacement_middle1_read =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, middle1);
+  ASSERT_NE(replacement_middle1_read, nullptr);
+  ASSERT_TRUE(replacement_middle1_read->GetTarget()->IsPhi());
+  ASSERT_EQ(2u, replacement_middle1_read->GetTarget()->AsPhi()->InputCount());
+  ASSERT_INS_EQ(replacement_middle1_read->GetTarget()->AsPhi()->InputAt(0), replacement_new_inst);
+  ASSERT_INS_EQ(replacement_middle1_read->GetTarget()->AsPhi()->InputAt(1), cnull);
+  ASSERT_TRUE(replacement_middle1_read->GetDefaultValue()->IsPhi());
+  ASSERT_EQ(2u, replacement_middle1_read->GetDefaultValue()->AsPhi()->InputCount());
+  ASSERT_INS_EQ(replacement_middle1_read->GetDefaultValue()->AsPhi()->InputAt(0), c0);
+  ASSERT_INS_EQ(replacement_middle1_read->GetDefaultValue()->AsPhi()->InputAt(1), c11);
+
+  EXPECT_INS_RETAINED(left2_call);
+
+  EXPECT_INS_REMOVED(left3_read);
+  HPredicatedInstanceFieldGet* replacement_left3_read =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, left3);
+  ASSERT_NE(replacement_left3_read, nullptr);
+  ASSERT_TRUE(replacement_left3_read->GetTarget()->IsPhi());
+  ASSERT_INS_EQ(replacement_left3_read->GetTarget(), replacement_middle1_read->GetTarget());
+  ASSERT_INS_EQ(replacement_left3_read->GetDefaultValue(), replacement_middle1_read);
+  EXPECT_INS_RETAINED(left3_call);
+
+  EXPECT_INS_RETAINED(breturn_phi);
+  EXPECT_INS_REMOVED(breturn_read);
+  HPredicatedInstanceFieldGet* replacement_breturn_read =
+      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
+  ASSERT_NE(replacement_breturn_read, nullptr);
+  ASSERT_INS_EQ(replacement_breturn_read->GetTarget(), replacement_middle1_read->GetTarget());
+  ASSERT_EQ(2u, replacement_breturn_read->GetDefaultValue()->AsPhi()->InputCount());
+  ASSERT_INS_EQ(replacement_breturn_read->GetDefaultValue()->AsPhi()->InputAt(0),
+                replacement_left3_read);
+  ASSERT_INS_EQ(replacement_breturn_read->GetDefaultValue()->AsPhi()->InputAt(1),
+                replacement_middle1_read);
+  EXPECT_INS_RETAINED(breturn_add1);
+  ASSERT_INS_EQ(breturn_add1->InputAt(0), replacement_middle1_read);
+  ASSERT_INS_EQ(breturn_add1->InputAt(1), replacement_breturn_read);
+  EXPECT_INS_RETAINED(breturn_add2);
+  ASSERT_INS_EQ(breturn_add2->InputAt(0), breturn_add1);
+  ASSERT_INS_EQ(breturn_add2->InputAt(1), breturn_phi);
+  EXPECT_INS_RETAINED(breturn_return);
+}
+
+INSTANTIATE_TEST_SUITE_P(LoadStoreEliminationTest,
+                         UsesOrderDependentTestGroupForThreeItems,
+                         testing::Values(0u, 1u, 2u, 3u, 4u, 5u));
+
 }  // namespace art
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index d56c151..2a09921 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -281,6 +281,19 @@
     return GetKind() == kSIMDStackSlot;
   }
 
+  static Location StackSlotByNumOfSlots(size_t num_of_slots, int spill_slot) {
+    DCHECK_NE(num_of_slots, 0u);
+    switch (num_of_slots) {
+      case 1u:
+        return Location::StackSlot(spill_slot);
+      case 2u:
+        return Location::DoubleStackSlot(spill_slot);
+      default:
+        // Assume all other stack slot sizes correspond to SIMD slot size.
+        return Location::SIMDStackSlot(spill_slot);
+    }
+  }
+
   intptr_t GetStackIndex() const {
     DCHECK(IsStackSlot() || IsDoubleStackSlot() || IsSIMDStackSlot());
     // Decode stack index manually to preserve sign.
@@ -427,8 +440,8 @@
   // way that none of them can be interpreted as a kConstant tag.
   uintptr_t value_;
 };
-std::ostream& operator<<(std::ostream& os, const Location::Kind& rhs);
-std::ostream& operator<<(std::ostream& os, const Location::Policy& rhs);
+std::ostream& operator<<(std::ostream& os, Location::Kind rhs);
+std::ostream& operator<<(std::ostream& os, Location::Policy rhs);
 
 class RegisterSet : public ValueObject {
  public:
@@ -465,6 +478,23 @@
     return (register_set & (1 << reg)) != 0;
   }
 
+  bool OverlapsRegisters(Location out) {
+    DCHECK(out.IsRegisterKind());
+    switch (out.GetKind()) {
+      case Location::Kind::kRegister:
+        return ContainsCoreRegister(out.reg());
+      case Location::Kind::kFpuRegister:
+        return ContainsFloatingPointRegister(out.reg());
+      case Location::Kind::kRegisterPair:
+        return ContainsCoreRegister(out.low()) || ContainsCoreRegister(out.high());
+      case Location::Kind::kFpuRegisterPair:
+        return ContainsFloatingPointRegister(out.low()) ||
+               ContainsFloatingPointRegister(out.high());
+      default:
+        return false;
+    }
+  }
+
   size_t GetNumberOfRegisters() const {
     return POPCOUNT(core_registers_) + POPCOUNT(floating_point_registers_);
   }
diff --git a/compiler/optimizing/loop_analysis.cc b/compiler/optimizing/loop_analysis.cc
index 7850517..76bd849 100644
--- a/compiler/optimizing/loop_analysis.cc
+++ b/compiler/optimizing/loop_analysis.cc
@@ -17,6 +17,7 @@
 #include "loop_analysis.h"
 
 #include "base/bit_vector-inl.h"
+#include "code_generator.h"
 #include "induction_var_range.h"
 
 namespace art {
@@ -76,6 +77,7 @@
 // is provided. Enables scalar loop peeling and unrolling with the most conservative heuristics.
 class ArchDefaultLoopHelper : public ArchNoOptsLoopHelper {
  public:
+  explicit ArchDefaultLoopHelper(const CodeGenerator& codegen) : ArchNoOptsLoopHelper(codegen) {}
   // Scalar loop unrolling parameters and heuristics.
   //
   // Maximum possible unrolling factor.
@@ -132,6 +134,7 @@
 // peeling and unrolling and supports SIMD loop unrolling.
 class Arm64LoopHelper : public ArchDefaultLoopHelper {
  public:
+  explicit Arm64LoopHelper(const CodeGenerator& codegen) : ArchDefaultLoopHelper(codegen) {}
   // SIMD loop unrolling parameters and heuristics.
   //
   // Maximum possible unrolling factor.
@@ -157,6 +160,10 @@
     // Don't unroll with insufficient iterations.
     // TODO: Unroll loops with unknown trip count.
     DCHECK_NE(vector_length, 0u);
+    // TODO: Unroll loops in predicated vectorization mode.
+    if (codegen_.SupportsPredicatedSIMD()) {
+      return LoopAnalysisInfo::kNoUnrollingFactor;
+    }
     if (trip_count < (2 * vector_length + max_peel)) {
       return LoopAnalysisInfo::kNoUnrollingFactor;
     }
@@ -214,6 +221,9 @@
         return 3;
       case HInstruction::InstructionKind::kIf:
         return 2;
+      case HInstruction::InstructionKind::kPredicatedInstanceFieldGet:
+        // test + cond-jump + IFieldGet
+        return 4;
       case HInstruction::InstructionKind::kInstanceFieldGet:
         return 2;
       case HInstruction::InstructionKind::kInstanceFieldSet:
@@ -306,6 +316,8 @@
   uint32_t GetUnrollingFactor(HLoopInformation* loop_info, HBasicBlock* header) const;
 
  public:
+  explicit X86_64LoopHelper(const CodeGenerator& codegen) : ArchDefaultLoopHelper(codegen) {}
+
   uint32_t GetSIMDUnrollingFactor(HBasicBlock* block,
                                   int64_t trip_count,
                                   uint32_t max_peel,
@@ -395,17 +407,18 @@
   return (1 << unrolling_factor);
 }
 
-ArchNoOptsLoopHelper* ArchNoOptsLoopHelper::Create(InstructionSet isa,
+ArchNoOptsLoopHelper* ArchNoOptsLoopHelper::Create(const CodeGenerator& codegen,
                                                    ArenaAllocator* allocator) {
+  InstructionSet isa = codegen.GetInstructionSet();
   switch (isa) {
     case InstructionSet::kArm64: {
-      return new (allocator) Arm64LoopHelper;
+      return new (allocator) Arm64LoopHelper(codegen);
     }
     case InstructionSet::kX86_64: {
-      return new (allocator) X86_64LoopHelper;
+      return new (allocator) X86_64LoopHelper(codegen);
     }
     default: {
-      return new (allocator) ArchDefaultLoopHelper;
+      return new (allocator) ArchDefaultLoopHelper(codegen);
     }
   }
 }
diff --git a/compiler/optimizing/loop_analysis.h b/compiler/optimizing/loop_analysis.h
index 57509ee..fbf1516 100644
--- a/compiler/optimizing/loop_analysis.h
+++ b/compiler/optimizing/loop_analysis.h
@@ -21,6 +21,7 @@
 
 namespace art {
 
+class CodeGenerator;
 class InductionVarRange;
 class LoopAnalysis;
 
@@ -132,11 +133,12 @@
 //
 class ArchNoOptsLoopHelper : public ArenaObject<kArenaAllocOptimization> {
  public:
+  explicit ArchNoOptsLoopHelper(const CodeGenerator& codegen) : codegen_(codegen) {}
   virtual ~ArchNoOptsLoopHelper() {}
 
   // Creates an instance of specialised helper for the target or default helper if the target
   // doesn't support loop peeling and unrolling.
-  static ArchNoOptsLoopHelper* Create(InstructionSet isa, ArenaAllocator* allocator);
+  static ArchNoOptsLoopHelper* Create(const CodeGenerator& codegen, ArenaAllocator* allocator);
 
   // Returns whether the loop is not beneficial for loop peeling/unrolling.
   //
@@ -176,6 +178,9 @@
                                           uint32_t vector_length ATTRIBUTE_UNUSED) const {
     return LoopAnalysisInfo::kNoUnrollingFactor;
   }
+
+ protected:
+  const CodeGenerator& codegen_;
 };
 
 }  // namespace art
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 5784707..02ee4ec 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -21,6 +21,7 @@
 #include "arch/instruction_set.h"
 #include "arch/x86/instruction_set_features_x86.h"
 #include "arch/x86_64/instruction_set_features_x86_64.h"
+#include "code_generator.h"
 #include "driver/compiler_options.h"
 #include "linear_order.h"
 #include "mirror/array-inl.h"
@@ -305,7 +306,8 @@
                         /*out*/ HInstruction** a,
                         /*out*/ HInstruction** b,
                         /*out*/ int64_t* c) {
-  if (IsAddConst(instruction, a, b, c) && *a != nullptr) {
+  // We want an actual add/sub and not the trivial case where {b: 0, c: 0}.
+  if (IsAddOrSub(instruction) && IsAddConst(instruction, a, b, c) && *a != nullptr) {
     if (*b == nullptr) {
       // Constant is usually already present, unless accumulated.
       *b = graph->GetConstant(instruction->GetType(), (*c));
@@ -429,7 +431,7 @@
                         InductionVarRange* induction_range) {
   for (int i = 0; i < count; i++) {
     // Perform peeling.
-    PeelUnrollSimpleHelper helper(loop_info, induction_range);
+    LoopClonerSimpleHelper helper(loop_info, induction_range);
     helper.DoPeeling();
   }
 }
@@ -456,12 +458,13 @@
 //
 
 HLoopOptimization::HLoopOptimization(HGraph* graph,
-                                     const CompilerOptions* compiler_options,
+                                     const CodeGenerator& codegen,
                                      HInductionVarAnalysis* induction_analysis,
                                      OptimizingCompilerStats* stats,
                                      const char* name)
     : HOptimization(graph, name, stats),
-      compiler_options_(compiler_options),
+      compiler_options_(&codegen.GetCompilerOptions()),
+      simd_register_size_(codegen.GetSIMDRegisterWidth()),
       induction_range_(induction_analysis),
       loop_allocator_(nullptr),
       global_allocator_(graph_->GetAllocator()),
@@ -470,6 +473,7 @@
       iset_(nullptr),
       reductions_(nullptr),
       simplified_(false),
+      predicated_vectorization_mode_(codegen.SupportsPredicatedSIMD()),
       vector_length_(0),
       vector_refs_(nullptr),
       vector_static_peeling_factor_(0),
@@ -483,10 +487,7 @@
       vector_header_(nullptr),
       vector_body_(nullptr),
       vector_index_(nullptr),
-      arch_loop_helper_(ArchNoOptsLoopHelper::Create(compiler_options_ != nullptr
-                                                          ? compiler_options_->GetInstructionSet()
-                                                          : InstructionSet::kNone,
-                                                      global_allocator_)) {
+      arch_loop_helper_(ArchNoOptsLoopHelper::Create(codegen, global_allocator_)) {
 }
 
 bool HLoopOptimization::Run() {
@@ -804,7 +805,7 @@
 
     // Perform unrolling.
     HLoopInformation* loop_info = analysis_info->GetLoopInfo();
-    PeelUnrollSimpleHelper helper(loop_info, &induction_range_);
+    LoopClonerSimpleHelper helper(loop_info, &induction_range_);
     helper.DoUnrolling();
 
     // Remove the redundant loop check after unrolling.
@@ -829,7 +830,7 @@
 
   if (generate_code) {
     // Perform peeling.
-    PeelUnrollSimpleHelper helper(loop_info, &induction_range_);
+    LoopClonerSimpleHelper helper(loop_info, &induction_range_);
     helper.DoPeeling();
 
     // Statically evaluate loop check after peeling for loop invariant condition.
@@ -885,12 +886,6 @@
 }
 
 bool HLoopOptimization::TryPeelingAndUnrolling(LoopNode* node) {
-  // Don't run peeling/unrolling if compiler_options_ is nullptr (i.e., running under tests)
-  // as InstructionSet is needed.
-  if (compiler_options_ == nullptr) {
-    return false;
-  }
-
   HLoopInformation* loop_info = node->loop_info;
   int64_t trip_count = LoopAnalysis::GetLoopTripCount(loop_info, &induction_range_);
   LoopAnalysisInfo analysis_info(loop_info);
@@ -908,7 +903,7 @@
   }
 
   // Run 'IsLoopClonable' the last as it might be time-consuming.
-  if (!PeelUnrollHelper::IsLoopClonable(loop_info)) {
+  if (!LoopClonerHelper::IsLoopClonable(loop_info)) {
     return false;
   }
 
@@ -951,9 +946,10 @@
   //     make one particular reference aligned), never to exceed (1).
   // (3) variable to record how many references share same alignment.
   // (4) variable to record suitable candidate for dynamic loop peeling.
-  uint32_t desired_alignment = GetVectorSizeInBytes();
-  DCHECK_LE(desired_alignment, 16u);
-  uint32_t peeling_votes[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+  size_t desired_alignment = GetVectorSizeInBytes();
+  ScopedArenaVector<uint32_t> peeling_votes(desired_alignment, 0u,
+      loop_allocator_->Adapter(kArenaAllocLoopOptimization));
+
   uint32_t max_num_same_alignment = 0;
   const ArrayReference* peeling_candidate = nullptr;
 
@@ -1027,8 +1023,10 @@
     }
   }  // for i
 
-  // Find a suitable alignment strategy.
-  SetAlignmentStrategy(peeling_votes, peeling_candidate);
+  if (!IsInPredicatedVectorizationMode()) {
+    // Find a suitable alignment strategy.
+    SetAlignmentStrategy(peeling_votes, peeling_candidate);
+  }
 
   // Does vectorization seem profitable?
   if (!IsVectorizationProfitable(trip_count)) {
@@ -1055,8 +1053,8 @@
 
   // A cleanup loop is needed, at least, for any unknown trip count or
   // for a known trip count with remainder iterations after vectorization.
-  bool needs_cleanup = trip_count == 0 ||
-      ((trip_count - vector_static_peeling_factor_) % chunk) != 0;
+  bool needs_cleanup = !IsInPredicatedVectorizationMode() &&
+      (trip_count == 0 || ((trip_count - vector_static_peeling_factor_) % chunk) != 0);
 
   // Adjust vector bookkeeping.
   HPhi* main_phi = nullptr;
@@ -1074,11 +1072,13 @@
   // ptc = <peeling factor>;
   HInstruction* ptc = nullptr;
   if (vector_static_peeling_factor_ != 0) {
+    DCHECK(!IsInPredicatedVectorizationMode());
     // Static loop peeling for SIMD alignment (using the most suitable
     // fixed peeling factor found during prior alignment analysis).
     DCHECK(vector_dynamic_peeling_candidate_ == nullptr);
     ptc = graph_->GetConstant(induc_type, vector_static_peeling_factor_);
   } else if (vector_dynamic_peeling_candidate_ != nullptr) {
+    DCHECK(!IsInPredicatedVectorizationMode());
     // Dynamic loop peeling for SIMD alignment (using the most suitable
     // candidate found during prior alignment analysis):
     // rem = offset % ALIGN;    // adjusted as #elements
@@ -1109,6 +1109,7 @@
   HInstruction* stc = induction_range_.GenerateTripCount(node->loop_info, graph_, preheader);
   HInstruction* vtc = stc;
   if (needs_cleanup) {
+    DCHECK(!IsInPredicatedVectorizationMode());
     DCHECK(IsPowerOfTwo(chunk));
     HInstruction* diff = stc;
     if (ptc != nullptr) {
@@ -1146,6 +1147,7 @@
   //       moved around during suspend checks, since all analysis was based on
   //       nothing more than the Android runtime alignment conventions.
   if (ptc != nullptr) {
+    DCHECK(!IsInPredicatedVectorizationMode());
     vector_mode_ = kSequential;
     GenerateNewLoop(node,
                     block,
@@ -1173,6 +1175,7 @@
   // for ( ; i < stc; i += 1)
   //    <loop-body>
   if (needs_cleanup) {
+    DCHECK(!IsInPredicatedVectorizationMode() || vector_runtime_test_a_ != nullptr);
     vector_mode_ = kSequential;
     GenerateNewLoop(node,
                     block,
@@ -1230,9 +1233,35 @@
   // Generate header and prepare body.
   // for (i = lo; i < hi; i += step)
   //    <loop-body>
-  HInstruction* cond = new (global_allocator_) HAboveOrEqual(phi, hi);
-  vector_header_->AddPhi(phi);
-  vector_header_->AddInstruction(cond);
+  HInstruction* cond = nullptr;
+  HInstruction* set_pred = nullptr;
+  if (IsInPredicatedVectorizationMode()) {
+    HVecPredWhile* pred_while =
+        new (global_allocator_) HVecPredWhile(global_allocator_,
+                                              phi,
+                                              hi,
+                                              HVecPredWhile::CondKind::kLO,
+                                              DataType::Type::kInt32,
+                                              vector_length_,
+                                              0u);
+
+    cond = new (global_allocator_) HVecPredCondition(global_allocator_,
+                                                     pred_while,
+                                                     HVecPredCondition::PCondKind::kNFirst,
+                                                     DataType::Type::kInt32,
+                                                     vector_length_,
+                                                     0u);
+
+    vector_header_->AddPhi(phi);
+    vector_header_->AddInstruction(pred_while);
+    vector_header_->AddInstruction(cond);
+    set_pred = pred_while;
+  } else {
+    cond = new (global_allocator_) HAboveOrEqual(phi, hi);
+    vector_header_->AddPhi(phi);
+    vector_header_->AddInstruction(cond);
+  }
+
   vector_header_->AddInstruction(new (global_allocator_) HIf(cond));
   vector_index_ = phi;
   vector_permanent_map_->clear();  // preserved over unrolling
@@ -1249,6 +1278,10 @@
       auto i = vector_map_->find(it.Current());
       if (i != vector_map_->end() && !i->second->IsInBlock()) {
         Insert(vector_body_, i->second);
+        if (IsInPredicatedVectorizationMode() && i->second->IsVecOperation()) {
+          HVecOperation* op = i->second->AsVecOperation();
+          op->SetMergingGoverningPredicate(set_pred);
+        }
         // Deal with instructions that need an environment, such as the scalar intrinsics.
         if (i->second->NeedsEnvironment()) {
           i->second->CopyEnvironmentFromWithLoopPhiAdjustment(env, vector_header_);
@@ -1363,7 +1396,10 @@
   } else if (instruction->IsArrayGet()) {
     // Deal with vector restrictions.
     bool is_string_char_at = instruction->AsArrayGet()->IsStringCharAt();
-    if (is_string_char_at && HasVectorRestrictions(restrictions, kNoStringCharAt)) {
+
+    if (is_string_char_at && (HasVectorRestrictions(restrictions, kNoStringCharAt) ||
+                              IsInPredicatedVectorizationMode())) {
+      // TODO: Support CharAt for predicated mode.
       return false;
     }
     // Accept a right-hand-side array base[index] for
@@ -1542,13 +1578,7 @@
 }
 
 uint32_t HLoopOptimization::GetVectorSizeInBytes() {
-  switch (compiler_options_->GetInstructionSet()) {
-    case InstructionSet::kArm:
-    case InstructionSet::kThumb2:
-      return 8;  // 64-bit SIMD
-    default:
-      return 16;  // 128-bit SIMD
-  }
+  return simd_register_size_;
 }
 
 bool HLoopOptimization::TrySetVectorType(DataType::Type type, uint64_t* restrictions) {
@@ -1563,45 +1593,88 @@
         case DataType::Type::kUint8:
         case DataType::Type::kInt8:
           *restrictions |= kNoDiv | kNoReduction | kNoDotProd;
-          return TrySetVectorLength(8);
+          return TrySetVectorLength(type, 8);
         case DataType::Type::kUint16:
         case DataType::Type::kInt16:
           *restrictions |= kNoDiv | kNoStringCharAt | kNoReduction | kNoDotProd;
-          return TrySetVectorLength(4);
+          return TrySetVectorLength(type, 4);
         case DataType::Type::kInt32:
           *restrictions |= kNoDiv | kNoWideSAD;
-          return TrySetVectorLength(2);
+          return TrySetVectorLength(type, 2);
         default:
           break;
       }
       return false;
     case InstructionSet::kArm64:
-      // Allow vectorization for all ARM devices, because Android assumes that
-      // ARMv8 AArch64 always supports advanced SIMD (128-bit SIMD).
-      switch (type) {
-        case DataType::Type::kBool:
-        case DataType::Type::kUint8:
-        case DataType::Type::kInt8:
-          *restrictions |= kNoDiv;
-          return TrySetVectorLength(16);
-        case DataType::Type::kUint16:
-        case DataType::Type::kInt16:
-          *restrictions |= kNoDiv;
-          return TrySetVectorLength(8);
-        case DataType::Type::kInt32:
-          *restrictions |= kNoDiv;
-          return TrySetVectorLength(4);
-        case DataType::Type::kInt64:
-          *restrictions |= kNoDiv | kNoMul;
-          return TrySetVectorLength(2);
-        case DataType::Type::kFloat32:
-          *restrictions |= kNoReduction;
-          return TrySetVectorLength(4);
-        case DataType::Type::kFloat64:
-          *restrictions |= kNoReduction;
-          return TrySetVectorLength(2);
-        default:
-          return false;
+      if (IsInPredicatedVectorizationMode()) {
+        // SVE vectorization.
+        CHECK(features->AsArm64InstructionSetFeatures()->HasSVE());
+        size_t vector_length = simd_register_size_ / DataType::Size(type);
+        DCHECK_EQ(simd_register_size_ % DataType::Size(type), 0u);
+        switch (type) {
+          case DataType::Type::kBool:
+          case DataType::Type::kUint8:
+          case DataType::Type::kInt8:
+            *restrictions |= kNoDiv |
+                             kNoSignedHAdd |
+                             kNoUnsignedHAdd |
+                             kNoUnroundedHAdd |
+                             kNoSAD;
+            return TrySetVectorLength(type, vector_length);
+          case DataType::Type::kUint16:
+          case DataType::Type::kInt16:
+            *restrictions |= kNoDiv |
+                             kNoSignedHAdd |
+                             kNoUnsignedHAdd |
+                             kNoUnroundedHAdd |
+                             kNoSAD |
+                             kNoDotProd;
+            return TrySetVectorLength(type, vector_length);
+          case DataType::Type::kInt32:
+            *restrictions |= kNoDiv | kNoSAD;
+            return TrySetVectorLength(type, vector_length);
+          case DataType::Type::kInt64:
+            *restrictions |= kNoDiv | kNoSAD;
+            return TrySetVectorLength(type, vector_length);
+          case DataType::Type::kFloat32:
+            *restrictions |= kNoReduction;
+            return TrySetVectorLength(type, vector_length);
+          case DataType::Type::kFloat64:
+            *restrictions |= kNoReduction;
+            return TrySetVectorLength(type, vector_length);
+          default:
+            break;
+        }
+        return false;
+      } else {
+        // Allow vectorization for all ARM devices, because Android assumes that
+        // ARMv8 AArch64 always supports advanced SIMD (128-bit SIMD).
+        switch (type) {
+          case DataType::Type::kBool:
+          case DataType::Type::kUint8:
+          case DataType::Type::kInt8:
+            *restrictions |= kNoDiv;
+            return TrySetVectorLength(type, 16);
+          case DataType::Type::kUint16:
+          case DataType::Type::kInt16:
+            *restrictions |= kNoDiv;
+            return TrySetVectorLength(type, 8);
+          case DataType::Type::kInt32:
+            *restrictions |= kNoDiv;
+            return TrySetVectorLength(type, 4);
+          case DataType::Type::kInt64:
+            *restrictions |= kNoDiv | kNoMul;
+            return TrySetVectorLength(type, 2);
+          case DataType::Type::kFloat32:
+            *restrictions |= kNoReduction;
+            return TrySetVectorLength(type, 4);
+          case DataType::Type::kFloat64:
+            *restrictions |= kNoReduction;
+            return TrySetVectorLength(type, 2);
+          default:
+            break;
+        }
+        return false;
       }
     case InstructionSet::kX86:
     case InstructionSet::kX86_64:
@@ -1619,7 +1692,7 @@
                              kNoUnroundedHAdd |
                              kNoSAD |
                              kNoDotProd;
-            return TrySetVectorLength(16);
+            return TrySetVectorLength(type, 16);
           case DataType::Type::kUint16:
             *restrictions |= kNoDiv |
                              kNoAbs |
@@ -1627,26 +1700,26 @@
                              kNoUnroundedHAdd |
                              kNoSAD |
                              kNoDotProd;
-            return TrySetVectorLength(8);
+            return TrySetVectorLength(type, 8);
           case DataType::Type::kInt16:
             *restrictions |= kNoDiv |
                              kNoAbs |
                              kNoSignedHAdd |
                              kNoUnroundedHAdd |
                              kNoSAD;
-            return TrySetVectorLength(8);
+            return TrySetVectorLength(type, 8);
           case DataType::Type::kInt32:
             *restrictions |= kNoDiv | kNoSAD;
-            return TrySetVectorLength(4);
+            return TrySetVectorLength(type, 4);
           case DataType::Type::kInt64:
             *restrictions |= kNoMul | kNoDiv | kNoShr | kNoAbs | kNoSAD;
-            return TrySetVectorLength(2);
+            return TrySetVectorLength(type, 2);
           case DataType::Type::kFloat32:
             *restrictions |= kNoReduction;
-            return TrySetVectorLength(4);
+            return TrySetVectorLength(type, 4);
           case DataType::Type::kFloat64:
             *restrictions |= kNoReduction;
-            return TrySetVectorLength(2);
+            return TrySetVectorLength(type, 2);
           default:
             break;
         }  // switch type
@@ -1657,7 +1730,7 @@
   }  // switch instruction set
 }
 
-bool HLoopOptimization::TrySetVectorLength(uint32_t length) {
+bool HLoopOptimization::TrySetVectorLengthImpl(uint32_t length) {
   DCHECK(IsPowerOfTwo(length) && length >= 2u);
   // First time set?
   if (vector_length_ == 0) {
@@ -1694,6 +1767,15 @@
       vector = new (global_allocator_)
           HVecReplicateScalar(global_allocator_, input, type, vector_length_, kNoDexPc);
       vector_permanent_map_->Put(org, Insert(vector_preheader_, vector));
+      if (IsInPredicatedVectorizationMode()) {
+        HVecPredSetAll* set_pred = new (global_allocator_) HVecPredSetAll(global_allocator_,
+                                                                          graph_->GetIntConstant(1),
+                                                                          type,
+                                                                          vector_length_,
+                                                                          0u);
+        vector_preheader_->InsertInstructionBefore(set_pred, vector);
+        vector->AsVecOperation()->SetMergingGoverningPredicate(set_pred);
+      }
     }
     vector_map_->Put(org, vector);
   }
@@ -1822,6 +1904,15 @@
                                                                     vector_length,
                                                                     kNoDexPc));
     }
+    if (IsInPredicatedVectorizationMode()) {
+      HVecPredSetAll* set_pred = new (global_allocator_) HVecPredSetAll(global_allocator_,
+                                                                        graph_->GetIntConstant(1),
+                                                                        type,
+                                                                        vector_length,
+                                                                        0u);
+      vector_preheader_->InsertInstructionBefore(set_pred, new_init);
+      new_init->AsVecOperation()->SetMergingGoverningPredicate(set_pred);
+    }
   } else {
     new_init = ReduceAndExtractIfNeeded(new_init);
   }
@@ -1853,6 +1944,17 @@
       instruction = new (global_allocator_) HVecExtractScalar(
           global_allocator_, reduce, type, vector_length, 0, kNoDexPc);
       exit->InsertInstructionAfter(instruction, reduce);
+
+      if (IsInPredicatedVectorizationMode()) {
+        HVecPredSetAll* set_pred = new (global_allocator_) HVecPredSetAll(global_allocator_,
+                                                                          graph_->GetIntConstant(1),
+                                                                          type,
+                                                                          vector_length,
+                                                                          0u);
+        exit->InsertInstructionBefore(set_pred, reduce);
+        reduce->AsVecOperation()->SetMergingGoverningPredicate(set_pred);
+        instruction->AsVecOperation()->SetMergingGoverningPredicate(set_pred);
+      }
     }
   }
   return instruction;
@@ -1992,7 +2094,8 @@
         return false;
       }
       // Deal with vector restrictions.
-      if ((!is_unsigned && HasVectorRestrictions(restrictions, kNoSignedHAdd)) ||
+      if ((is_unsigned && HasVectorRestrictions(restrictions, kNoUnsignedHAdd)) ||
+          (!is_unsigned && HasVectorRestrictions(restrictions, kNoSignedHAdd)) ||
           (!is_rounded && HasVectorRestrictions(restrictions, kNoUnroundedHAdd))) {
         return false;
       }
@@ -2044,13 +2147,13 @@
       (reduction_type != DataType::Type::kInt32 && reduction_type != DataType::Type::kInt64)) {
     return false;
   }
-  HInstruction* q = instruction->InputAt(0);
-  HInstruction* v = instruction->InputAt(1);
+  HInstruction* acc = instruction->InputAt(0);
+  HInstruction* abs = instruction->InputAt(1);
   HInstruction* a = nullptr;
   HInstruction* b = nullptr;
-  if (v->IsAbs() &&
-      v->GetType() == reduction_type &&
-      IsSubConst2(graph_, v->InputAt(0), /*out*/ &a, /*out*/ &b)) {
+  if (abs->IsAbs() &&
+      abs->GetType() == reduction_type &&
+      IsSubConst2(graph_, abs->InputAt(0), /*out*/ &a, /*out*/ &b)) {
     DCHECK(a != nullptr && b != nullptr);
   } else {
     return false;
@@ -2076,16 +2179,16 @@
   // idiomatic operation. Sequential code uses the original scalar expressions.
   DCHECK(r != nullptr && s != nullptr);
   if (generate_code && vector_mode_ != kVector) {  // de-idiom
-    r = s = v->InputAt(0);
+    r = s = abs->InputAt(0);
   }
-  if (VectorizeUse(node, q, generate_code, sub_type, restrictions) &&
+  if (VectorizeUse(node, acc, generate_code, sub_type, restrictions) &&
       VectorizeUse(node, r, generate_code, sub_type, restrictions) &&
       VectorizeUse(node, s, generate_code, sub_type, restrictions)) {
     if (generate_code) {
       if (vector_mode_ == kVector) {
         vector_map_->Put(instruction, new (global_allocator_) HVecSADAccumulate(
             global_allocator_,
-            vector_map_->Get(q),
+            vector_map_->Get(acc),
             vector_map_->Get(r),
             vector_map_->Get(s),
             HVecOperation::ToProperType(reduction_type, is_unsigned),
@@ -2093,8 +2196,14 @@
             kNoDexPc));
         MaybeRecordStat(stats_, MethodCompilationStat::kLoopVectorizedIdiom);
       } else {
-        GenerateVecOp(v, vector_map_->Get(r), nullptr, reduction_type);
-        GenerateVecOp(instruction, vector_map_->Get(q), vector_map_->Get(v), reduction_type);
+        // "GenerateVecOp()" must not be called more than once for each original loop body
+        // instruction. As the SAD idiom processes both "current" instruction ("instruction")
+        // and its ABS input in one go, we must check that for the scalar case the ABS instruction
+        // has not yet been processed.
+        if (vector_map_->find(abs) == vector_map_->end()) {
+          GenerateVecOp(abs, vector_map_->Get(r), nullptr, reduction_type);
+        }
+        GenerateVecOp(instruction, vector_map_->Get(acc), vector_map_->Get(abs), reduction_type);
       }
     }
     return true;
@@ -2116,20 +2225,20 @@
     return false;
   }
 
-  HInstruction* q = instruction->InputAt(0);
-  HInstruction* v = instruction->InputAt(1);
-  if (!v->IsMul() || v->GetType() != reduction_type) {
+  HInstruction* const acc = instruction->InputAt(0);
+  HInstruction* const mul = instruction->InputAt(1);
+  if (!mul->IsMul() || mul->GetType() != reduction_type) {
     return false;
   }
 
-  HInstruction* a = v->InputAt(0);
-  HInstruction* b = v->InputAt(1);
-  HInstruction* r = a;
-  HInstruction* s = b;
-  DataType::Type op_type = GetNarrowerType(a, b);
+  HInstruction* const mul_left = mul->InputAt(0);
+  HInstruction* const mul_right = mul->InputAt(1);
+  HInstruction* r = mul_left;
+  HInstruction* s = mul_right;
+  DataType::Type op_type = GetNarrowerType(mul_left, mul_right);
   bool is_unsigned = false;
 
-  if (!IsNarrowerOperands(a, b, op_type, &r, &s, &is_unsigned)) {
+  if (!IsNarrowerOperands(mul_left, mul_right, op_type, &r, &s, &is_unsigned)) {
     return false;
   }
   op_type = HVecOperation::ToProperType(op_type, is_unsigned);
@@ -2143,17 +2252,17 @@
   // Accept dot product idiom for vectorizable operands. Vectorized code uses the shorthand
   // idiomatic operation. Sequential code uses the original scalar expressions.
   if (generate_code && vector_mode_ != kVector) {  // de-idiom
-    r = a;
-    s = b;
+    r = mul_left;
+    s = mul_right;
   }
-  if (VectorizeUse(node, q, generate_code, op_type, restrictions) &&
+  if (VectorizeUse(node, acc, generate_code, op_type, restrictions) &&
       VectorizeUse(node, r, generate_code, op_type, restrictions) &&
       VectorizeUse(node, s, generate_code, op_type, restrictions)) {
     if (generate_code) {
       if (vector_mode_ == kVector) {
         vector_map_->Put(instruction, new (global_allocator_) HVecDotProd(
             global_allocator_,
-            vector_map_->Get(q),
+            vector_map_->Get(acc),
             vector_map_->Get(r),
             vector_map_->Get(s),
             reduction_type,
@@ -2162,8 +2271,14 @@
             kNoDexPc));
         MaybeRecordStat(stats_, MethodCompilationStat::kLoopVectorizedIdiom);
       } else {
-        GenerateVecOp(v, vector_map_->Get(r), vector_map_->Get(s), reduction_type);
-        GenerateVecOp(instruction, vector_map_->Get(q), vector_map_->Get(v), reduction_type);
+        // "GenerateVecOp()" must not be called more than once for each original loop body
+        // instruction. As the DotProd idiom processes both "current" instruction ("instruction")
+        // and its MUL input in one go, we must check that for the scalar case the MUL instruction
+        // has not yet been processed.
+        if (vector_map_->find(mul) == vector_map_->end()) {
+          GenerateVecOp(mul, vector_map_->Get(r), vector_map_->Get(s), reduction_type);
+        }
+        GenerateVecOp(instruction, vector_map_->Get(acc), vector_map_->Get(mul), reduction_type);
       }
     }
     return true;
@@ -2191,12 +2306,12 @@
   return Alignment(DataType::Size(type), 0);
 }
 
-void HLoopOptimization::SetAlignmentStrategy(uint32_t peeling_votes[],
+void HLoopOptimization::SetAlignmentStrategy(const ScopedArenaVector<uint32_t>& peeling_votes,
                                              const ArrayReference* peeling_candidate) {
   // Current heuristic: pick the best static loop peeling factor, if any,
   // or otherwise use dynamic loop peeling on suggested peeling candidate.
   uint32_t max_vote = 0;
-  for (int32_t i = 0; i < 16; i++) {
+  for (size_t i = 0; i < peeling_votes.size(); i++) {
     if (peeling_votes[i] > max_vote) {
       max_vote = peeling_votes[i];
       vector_static_peeling_factor_ = i;
diff --git a/compiler/optimizing/loop_optimization.h b/compiler/optimizing/loop_optimization.h
index 1a842c4..d3583ed 100644
--- a/compiler/optimizing/loop_optimization.h
+++ b/compiler/optimizing/loop_optimization.h
@@ -38,7 +38,7 @@
 class HLoopOptimization : public HOptimization {
  public:
   HLoopOptimization(HGraph* graph,
-                    const CompilerOptions* compiler_options,
+                    const CodeGenerator& codegen,    // Needs info about the target.
                     HInductionVarAnalysis* induction_analysis,
                     OptimizingCompilerStats* stats,
                     const char* name = kLoopOptimizationPassName);
@@ -76,13 +76,14 @@
     kNoShr           = 1 << 3,   // no arithmetic shift right
     kNoHiBits        = 1 << 4,   // "wider" operations cannot bring in higher order bits
     kNoSignedHAdd    = 1 << 5,   // no signed halving add
-    kNoUnroundedHAdd = 1 << 6,   // no unrounded halving add
-    kNoAbs           = 1 << 7,   // no absolute value
-    kNoStringCharAt  = 1 << 8,   // no StringCharAt
-    kNoReduction     = 1 << 9,   // no reduction
-    kNoSAD           = 1 << 10,  // no sum of absolute differences (SAD)
-    kNoWideSAD       = 1 << 11,  // no sum of absolute differences (SAD) with operand widening
-    kNoDotProd       = 1 << 12,  // no dot product
+    kNoUnsignedHAdd  = 1 << 6,   // no unsigned halving add
+    kNoUnroundedHAdd = 1 << 7,   // no unrounded halving add
+    kNoAbs           = 1 << 8,   // no absolute value
+    kNoStringCharAt  = 1 << 9,   // no StringCharAt
+    kNoReduction     = 1 << 10,  // no reduction
+    kNoSAD           = 1 << 11,  // no sum of absolute differences (SAD)
+    kNoWideSAD       = 1 << 12,  // no sum of absolute differences (SAD) with operand widening
+    kNoDotProd       = 1 << 13,  // no dot product
   };
 
   /*
@@ -186,7 +187,15 @@
                     uint64_t restrictions);
   uint32_t GetVectorSizeInBytes();
   bool TrySetVectorType(DataType::Type type, /*out*/ uint64_t* restrictions);
-  bool TrySetVectorLength(uint32_t length);
+  bool TrySetVectorLengthImpl(uint32_t length);
+
+  bool TrySetVectorLength(DataType::Type type, uint32_t length) {
+    bool res = TrySetVectorLengthImpl(length);
+    // Currently the vectorizer supports only the mode when full SIMD registers are used.
+    DCHECK(!res || (DataType::Size(type) * length == GetVectorSizeInBytes()));
+    return res;
+  }
+
   void GenerateVecInv(HInstruction* org, DataType::Type type);
   void GenerateVecSub(HInstruction* org, HInstruction* offset);
   void GenerateVecMem(HInstruction* org,
@@ -229,7 +238,7 @@
                              DataType::Type type,
                              bool is_string_char_at,
                              uint32_t peeling = 0);
-  void SetAlignmentStrategy(uint32_t peeling_votes[],
+  void SetAlignmentStrategy(const ScopedArenaVector<uint32_t>& peeling_votes,
                             const ArrayReference* peeling_candidate);
   uint32_t MaxNumberPeeled();
   bool IsVectorizationProfitable(int64_t trip_count);
@@ -262,9 +271,14 @@
   void RemoveDeadInstructions(const HInstructionList& list);
   bool CanRemoveCycle();  // Whether the current 'iset_' is removable.
 
+  bool IsInPredicatedVectorizationMode() const { return predicated_vectorization_mode_; }
+
   // Compiler options (to query ISA features).
   const CompilerOptions* compiler_options_;
 
+  // Cached target SIMD vector register size in bytes.
+  const size_t simd_register_size_;
+
   // Range information based on prior induction variable analysis.
   InductionVarRange induction_range_;
 
@@ -294,6 +308,9 @@
   // Flag that tracks if any simplifications have occurred.
   bool simplified_;
 
+  // Whether to use predicated loop vectorization (e.g. for arm64 SVE target).
+  bool predicated_vectorization_mode_;
+
   // Number of "lanes" for selected packed type.
   uint32_t vector_length_;
 
diff --git a/compiler/optimizing/loop_optimization_test.cc b/compiler/optimizing/loop_optimization_test.cc
index 310d98b..bda2528 100644
--- a/compiler/optimizing/loop_optimization_test.cc
+++ b/compiler/optimizing/loop_optimization_test.cc
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "code_generator.h"
+#include "driver/compiler_options.h"
 #include "loop_optimization.h"
 #include "optimizing_unit_test.h"
 
@@ -25,16 +27,30 @@
  * through the checker tests.
  */
 class LoopOptimizationTest : public OptimizingUnitTest {
- public:
-  LoopOptimizationTest()
-      : graph_(CreateGraph()),
-        iva_(new (GetAllocator()) HInductionVarAnalysis(graph_)),
-        loop_opt_(new (GetAllocator()) HLoopOptimization(
-            graph_, /* compiler_options= */ nullptr, iva_, /* stats= */ nullptr)) {
+ protected:
+  void SetUp() override {
+    OptimizingUnitTest::SetUp();
+
+    graph_ = CreateGraph();
     BuildGraph();
+    iva_  = new (GetAllocator()) HInductionVarAnalysis(graph_);
+    compiler_options_ = CommonCompilerTest::CreateCompilerOptions(kRuntimeISA, "default");
+    DCHECK(compiler_options_ != nullptr);
+    codegen_ = CodeGenerator::Create(graph_, *compiler_options_);
+    DCHECK(codegen_.get() != nullptr);
+    loop_opt_ = new (GetAllocator()) HLoopOptimization(
+        graph_, *codegen_.get(), iva_, /* stats= */ nullptr);
   }
 
-  ~LoopOptimizationTest() { }
+  void TearDown() override {
+    codegen_.reset();
+    compiler_options_.reset();
+    graph_ = nullptr;
+    ResetPoolAndAllocator();
+    OptimizingUnitTest::TearDown();
+  }
+
+  virtual ~LoopOptimizationTest() {}
 
   /** Constructs bare minimum graph. */
   void BuildGraph() {
@@ -102,6 +118,9 @@
 
   // General building fields.
   HGraph* graph_;
+
+  std::unique_ptr<CompilerOptions> compiler_options_;
+  std::unique_ptr<CodeGenerator> codegen_;
   HInductionVarAnalysis* iva_;
   HLoopOptimization* loop_opt_;
 
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 810871c..17080f0 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -15,15 +15,24 @@
  */
 #include "nodes.h"
 
+#include <algorithm>
 #include <cfloat>
+#include <functional>
 
 #include "art_method-inl.h"
+#include "base/arena_allocator.h"
+#include "base/arena_bit_vector.h"
 #include "base/bit_utils.h"
 #include "base/bit_vector-inl.h"
+#include "base/bit_vector.h"
+#include "base/iteration_range.h"
 #include "base/logging.h"
+#include "base/malloc_arena_pool.h"
+#include "base/scoped_arena_allocator.h"
+#include "base/scoped_arena_containers.h"
 #include "base/stl_util.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "code_generator.h"
 #include "common_dominator.h"
 #include "intrinsics.h"
@@ -39,12 +48,11 @@
 // double).
 static constexpr bool kEnableFloatingPointStaticEvaluation = (FLT_EVAL_METHOD == 0);
 
-void HGraph::InitializeInexactObjectRTI(VariableSizedHandleScope* handles) {
+ReferenceTypeInfo::TypeHandle HandleCache::CreateRootHandle(VariableSizedHandleScope* handles,
+                                                            ClassRoot class_root) {
+  // Mutator lock is required for NewHandle and GetClassRoot().
   ScopedObjectAccess soa(Thread::Current());
-  // Create the inexact Object reference type and store it in the HGraph.
-  inexact_object_rti_ = ReferenceTypeInfo::Create(
-      handles->NewHandle(GetClassRoot<mirror::Object>()),
-      /* is_exact= */ false);
+  return handles->NewHandle(GetClassRoot(class_root));
 }
 
 void HGraph::AddBlock(HBasicBlock* block) {
@@ -222,7 +230,7 @@
 }
 
 void HGraph::ClearDominanceInformation() {
-  for (HBasicBlock* block : GetReversePostOrder()) {
+  for (HBasicBlock* block : GetActiveBlocks()) {
     block->ClearDominanceInformation();
   }
   reverse_post_order_.clear();
@@ -230,7 +238,7 @@
 
 void HGraph::ClearLoopInformation() {
   SetHasIrreducibleLoops(false);
-  for (HBasicBlock* block : GetReversePostOrder()) {
+  for (HBasicBlock* block : GetActiveBlocks()) {
     block->SetLoopInformation(nullptr);
   }
 }
@@ -264,6 +272,171 @@
   }
 }
 
+// TODO Consider moving this entirely into LoadStoreAnalysis/Elimination.
+bool HGraph::PathBetween(uint32_t source_idx, uint32_t dest_idx) const {
+  DCHECK_LT(source_idx, blocks_.size()) << "source not present in graph!";
+  DCHECK_LT(dest_idx, blocks_.size()) << "dest not present in graph!";
+  DCHECK(blocks_[source_idx] != nullptr);
+  DCHECK(blocks_[dest_idx] != nullptr);
+  return reachability_graph_.IsBitSet(source_idx, dest_idx);
+}
+
+bool HGraph::PathBetween(const HBasicBlock* source, const HBasicBlock* dest) const {
+  if (source == nullptr || dest == nullptr) {
+    return false;
+  }
+  size_t source_idx = source->GetBlockId();
+  size_t dest_idx = dest->GetBlockId();
+  return PathBetween(source_idx, dest_idx);
+}
+
+// This function/struct calculates the reachability of every node from every
+// other node by iteratively using DFS to find reachability of each individual
+// block.
+//
+// This is in practice faster then the simpler Floyd-Warshall since while that
+// is O(N**3) this is O(N*(E + N)) where N is the number of blocks and E is the
+// number of edges. Since in practice each block only has a few outgoing edges
+// we can confidently say that E ~ B*N where B is a small number (~3). We also
+// memoize the results as we go allowing us to (potentially) avoid walking the
+// entire graph for every node. To make best use of this memoization we
+// calculate the reachability of blocks in PostOrder. This means that
+// (generally) blocks that are dominated by many other blocks and dominate few
+// blocks themselves will be examined first. This makes it more likely we can
+// use our memoized results.
+class ReachabilityAnalysisHelper {
+ public:
+  ReachabilityAnalysisHelper(const HGraph* graph,
+                             ArenaBitVectorArray* reachability_graph,
+                             ArenaStack* arena_stack)
+      : graph_(graph),
+        reachability_graph_(reachability_graph),
+        arena_stack_(arena_stack),
+        temporaries_(arena_stack_),
+        block_size_(RoundUp(graph_->GetBlocks().size(), BitVector::kWordBits)),
+        all_visited_nodes_(
+            &temporaries_, graph_->GetBlocks().size(), false, kArenaAllocReachabilityGraph),
+        not_post_order_visited_(
+            &temporaries_, graph_->GetBlocks().size(), false, kArenaAllocReachabilityGraph) {
+    // We can't adjust the size of reachability graph any more without breaking
+    // our allocator invariants so it had better be large enough.
+    CHECK_GE(reachability_graph_->NumRows(), graph_->GetBlocks().size());
+    CHECK_GE(reachability_graph_->NumColumns(), graph_->GetBlocks().size());
+    not_post_order_visited_.SetInitialBits(graph_->GetBlocks().size());
+  }
+
+  void CalculateReachability() {
+    // Calculate what blocks connect using repeated DFS
+    //
+    // Going in PostOrder should generally give memoization a good shot of
+    // hitting.
+    for (const HBasicBlock* blk : graph_->GetPostOrder()) {
+      if (blk == nullptr) {
+        continue;
+      }
+      not_post_order_visited_.ClearBit(blk->GetBlockId());
+      CalculateConnectednessOn(blk);
+      all_visited_nodes_.SetBit(blk->GetBlockId());
+    }
+    // Get all other bits
+    for (auto idx : not_post_order_visited_.Indexes()) {
+      const HBasicBlock* blk = graph_->GetBlocks()[idx];
+      if (blk == nullptr) {
+        continue;
+      }
+      CalculateConnectednessOn(blk);
+      all_visited_nodes_.SetBit(blk->GetBlockId());
+    }
+  }
+
+ private:
+  void AddEdge(uint32_t source, const HBasicBlock* dest) {
+    reachability_graph_->SetBit(source, dest->GetBlockId());
+  }
+
+  // Union the reachability of 'idx' into 'update_block_idx'. This is done to
+  // implement memoization. In order to improve performance we do this in 4-byte
+  // blocks. Clang should be able to optimize this to larger blocks if possible.
+  void UnionBlock(size_t update_block_idx, size_t idx) {
+    reachability_graph_->UnionRows(update_block_idx, idx);
+  }
+
+  // Single DFS to get connectedness of a single block
+  void CalculateConnectednessOn(const HBasicBlock* const target_block) {
+    const uint32_t target_idx = target_block->GetBlockId();
+    ScopedArenaAllocator connectedness_temps(arena_stack_);
+    // What nodes we have already discovered and either have processed or are
+    // already on the queue.
+    ArenaBitVector discovered(
+        &connectedness_temps, graph_->GetBlocks().size(), false, kArenaAllocReachabilityGraph);
+    // The work stack. What blocks we still need to process.
+    ScopedArenaVector<const HBasicBlock*> work_stack(
+        connectedness_temps.Adapter(kArenaAllocReachabilityGraph));
+    // Known max size since otherwise we'd have blocks multiple times. Avoids
+    // re-allocation
+    work_stack.reserve(graph_->GetBlocks().size());
+    discovered.SetBit(target_idx);
+    work_stack.push_back(target_block);
+    // Main DFS Loop.
+    while (!work_stack.empty()) {
+      const HBasicBlock* cur = work_stack.back();
+      work_stack.pop_back();
+      // Memoization of previous runs.
+      if (all_visited_nodes_.IsBitSet(cur->GetBlockId())) {
+        DCHECK_NE(target_block, cur);
+        // Already explored from here. Just use that data.
+        UnionBlock(target_idx, cur->GetBlockId());
+        continue;
+      }
+      for (const HBasicBlock* succ : cur->GetSuccessors()) {
+        AddEdge(target_idx, succ);
+        if (!discovered.IsBitSet(succ->GetBlockId())) {
+          work_stack.push_back(succ);
+          discovered.SetBit(succ->GetBlockId());
+        }
+      }
+    }
+  }
+
+  const HGraph* graph_;
+  // The graph's reachability_graph_ on the main allocator.
+  ArenaBitVectorArray* reachability_graph_;
+  ArenaStack* arena_stack_;
+  // An allocator for temporary bit-vectors used by this algorithm. The
+  // 'SetBit,ClearBit' on reachability_graph_ prior to the construction of this
+  // object should be the only allocation on the main allocator so it's safe to
+  // make a sub-allocator here.
+  ScopedArenaAllocator temporaries_;
+  // number of columns
+  const size_t block_size_;
+  // Where we've already completely calculated connectedness.
+  ArenaBitVector all_visited_nodes_;
+  // What we never visited and need to do later
+  ArenaBitVector not_post_order_visited_;
+
+  DISALLOW_COPY_AND_ASSIGN(ReachabilityAnalysisHelper);
+};
+
+void HGraph::ComputeReachabilityInformation() {
+  DCHECK_EQ(reachability_graph_.GetRawData().NumSetBits(), 0u);
+  DCHECK(reachability_graph_.IsExpandable());
+  // Reserve all the bits we'll need. This is the only allocation on the
+  // standard allocator we do here, enabling us to create a new ScopedArena for
+  // use with temporaries.
+  //
+  // reachability_graph_ acts as |N| x |N| graph for PathBetween. Array is
+  // padded so each row starts on an BitVector::kWordBits-bit alignment for
+  // simplicity and performance, allowing us to union blocks together without
+  // going bit-by-bit.
+  reachability_graph_.Resize(blocks_.size(), blocks_.size(), /*clear=*/false);
+  ReachabilityAnalysisHelper helper(this, &reachability_graph_, GetArenaStack());
+  helper.CalculateReachability();
+}
+
+void HGraph::ClearReachabilityInformation() {
+  reachability_graph_.Clear();
+}
+
 void HGraph::ComputeDominanceInformation() {
   DCHECK(reverse_post_order_.empty());
   reverse_post_order_.reserve(blocks_.size());
@@ -662,7 +835,7 @@
   // id and/or any invariants the graph is assuming when adding new instructions.
   if ((cached_null_constant_ == nullptr) || (cached_null_constant_->GetBlock() == nullptr)) {
     cached_null_constant_ = new (allocator_) HNullConstant(dex_pc);
-    cached_null_constant_->SetReferenceTypeInfo(inexact_object_rti_);
+    cached_null_constant_->SetReferenceTypeInfo(GetInexactObjectRti());
     InsertConstant(cached_null_constant_);
   }
   if (kIsDebugBuild) {
@@ -1141,6 +1314,55 @@
   orig_instr->FixUpUserRecordsAfterEnvUseRemoval(before_use_node);
 }
 
+std::ostream& HInstruction::Dump(std::ostream& os, bool dump_args) {
+  // Note: Handle the case where the instruction has been removed from
+  // the graph to support debugging output for failed gtests.
+  HGraph* graph = (GetBlock() != nullptr) ? GetBlock()->GetGraph() : nullptr;
+  HGraphVisualizer::DumpInstruction(&os, graph, this);
+  if (dump_args) {
+    // Allocate memory from local ScopedArenaAllocator.
+    std::optional<MallocArenaPool> local_arena_pool;
+    std::optional<ArenaStack> local_arena_stack;
+    if (UNLIKELY(graph == nullptr)) {
+      local_arena_pool.emplace();
+      local_arena_stack.emplace(&local_arena_pool.value());
+    }
+    ScopedArenaAllocator allocator(
+        graph != nullptr ? graph->GetArenaStack() : &local_arena_stack.value());
+    // Instructions that we already visited. We print each instruction only once.
+    ArenaBitVector visited(&allocator,
+                           (graph != nullptr) ? graph->GetCurrentInstructionId() : 0u,
+                           /* expandable= */ (graph == nullptr),
+                           kArenaAllocMisc);
+    visited.ClearAllBits();
+    visited.SetBit(GetId());
+    // Keep a queue of instructions with their indentations.
+    ScopedArenaDeque<std::pair<HInstruction*, size_t>> queue(allocator.Adapter(kArenaAllocMisc));
+    auto add_args = [&queue](HInstruction* instruction, size_t indentation) {
+      for (HInstruction* arg : ReverseRange(instruction->GetInputs())) {
+        queue.emplace_front(arg, indentation);
+      }
+    };
+    add_args(this, /*indentation=*/ 1u);
+    while (!queue.empty()) {
+      HInstruction* instruction;
+      size_t indentation;
+      std::tie(instruction, indentation) = queue.front();
+      queue.pop_front();
+      if (!visited.IsBitSet(instruction->GetId())) {
+        visited.SetBit(instruction->GetId());
+        os << '\n';
+        for (size_t i = 0; i != indentation; ++i) {
+          os << "  ";
+        }
+        HGraphVisualizer::DumpInstruction(&os, graph, instruction);
+        add_args(instruction, indentation + 1u);
+      }
+    }
+  }
+  return os;
+}
+
 HInstruction* HInstruction::GetNextDisregardingMoves() const {
   HInstruction* next = GetNext();
   while (next != nullptr && next->IsParallelMove()) {
@@ -1523,11 +1745,8 @@
 #undef DEFINE_ACCEPT
 
 void HGraphVisitor::VisitInsertionOrder() {
-  const ArenaVector<HBasicBlock*>& blocks = graph_->GetBlocks();
-  for (HBasicBlock* block : blocks) {
-    if (block != nullptr) {
-      VisitBasicBlock(block);
-    }
+  for (HBasicBlock* block : graph_->GetActiveBlocks()) {
+    VisitBasicBlock(block);
   }
 }
 
@@ -1703,14 +1922,15 @@
   }
 }
 
-std::ostream& operator<<(std::ostream& os, const ComparisonBias& rhs) {
+std::ostream& operator<<(std::ostream& os, ComparisonBias rhs) {
+  // TODO: Replace with auto-generated operator<<.
   switch (rhs) {
     case ComparisonBias::kNoBias:
-      return os << "no_bias";
+      return os << "none";
     case ComparisonBias::kGtBias:
-      return os << "gt_bias";
+      return os << "gt";
     case ComparisonBias::kLtBias:
-      return os << "lt_bias";
+      return os << "lt";
     default:
       LOG(FATAL) << "Unknown ComparisonBias: " << static_cast<int>(rhs);
       UNREACHABLE();
@@ -1736,7 +1956,7 @@
   return true;
 }
 
-std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs) {
+std::ostream& operator<<(std::ostream& os, HInstruction::InstructionKind rhs) {
 #define DECLARE_CASE(type, super) case HInstruction::k##type: os << #type; break;
   switch (rhs) {
     FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_CASE)
@@ -1748,6 +1968,58 @@
   return os;
 }
 
+std::ostream& operator<<(std::ostream& os, const HInstruction::NoArgsDump rhs) {
+  // TODO Really this should be const but that would require const-ifying
+  // graph-visualizer and HGraphVisitor which are tangled up everywhere.
+  return const_cast<HInstruction*>(rhs.ins)->Dump(os, /* dump_args= */ false);
+}
+
+std::ostream& operator<<(std::ostream& os, const HInstruction::ArgsDump rhs) {
+  // TODO Really this should be const but that would require const-ifying
+  // graph-visualizer and HGraphVisitor which are tangled up everywhere.
+  return const_cast<HInstruction*>(rhs.ins)->Dump(os, /* dump_args= */ true);
+}
+
+std::ostream& operator<<(std::ostream& os, const HInstruction& rhs) {
+  return os << rhs.DumpWithoutArgs();
+}
+
+std::ostream& operator<<(std::ostream& os, const HUseList<HInstruction*>& lst) {
+  os << "Instructions[";
+  bool first = true;
+  for (const auto& hi : lst) {
+    if (!first) {
+      os << ", ";
+    }
+    first = false;
+    os << hi.GetUser()->DebugName() << "[id: " << hi.GetUser()->GetId()
+       << ", blk: " << hi.GetUser()->GetBlock()->GetBlockId() << "]@" << hi.GetIndex();
+  }
+  os << "]";
+  return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const HUseList<HEnvironment*>& lst) {
+  os << "Environments[";
+  bool first = true;
+  for (const auto& hi : lst) {
+    if (!first) {
+      os << ", ";
+    }
+    first = false;
+    os << *hi.GetUser()->GetHolder() << "@" << hi.GetIndex();
+  }
+  os << "]";
+  return os;
+}
+
+std::ostream& HGraph::Dump(std::ostream& os,
+                           std::optional<std::reference_wrapper<const BlockNamer>> namer) {
+  HGraphVisualizer vis(&os, this, nullptr, namer);
+  vis.DumpGraphDebug();
+  return os;
+}
+
 void HInstruction::MoveBefore(HInstruction* cursor, bool do_checks) {
   if (do_checks) {
     DCHECK(!IsPhi());
@@ -2450,6 +2722,9 @@
   if (HasIrreducibleLoops()) {
     outer_graph->SetHasIrreducibleLoops(true);
   }
+  if (HasDirectCriticalNativeCall()) {
+    outer_graph->SetHasDirectCriticalNativeCall(true);
+  }
   if (HasTryCatch()) {
     outer_graph->SetHasTryCatch(true);
   }
@@ -2878,7 +3153,7 @@
 }
 
 void HInvoke::SetIntrinsic(Intrinsics intrinsic,
-                           IntrinsicNeedsEnvironmentOrCache needs_env_or_cache,
+                           IntrinsicNeedsEnvironment needs_env,
                            IntrinsicSideEffects side_effects,
                            IntrinsicExceptions exceptions) {
   intrinsic_ = intrinsic;
@@ -2892,8 +3167,7 @@
     case kAllSideEffects: SetSideEffects(SideEffects::AllExceptGCDependency()); break;
   }
 
-  if (needs_env_or_cache == kNoEnvironmentOrCache) {
-    opt.SetDoesNotNeedDexCache();
+  if (needs_env == kNoEnvironment) {
     opt.SetDoesNotNeedEnvironment();
   } else {
     // If we need an environment, that means there will be a call, which can trigger GC.
@@ -2923,39 +3197,6 @@
   return caller == nullptr ? GetBlock()->GetGraph()->GetDexFile() : *caller->GetDexFile();
 }
 
-bool HInvokeStaticOrDirect::NeedsDexCacheOfDeclaringClass() const {
-  if (GetMethodLoadKind() != MethodLoadKind::kRuntimeCall) {
-    return false;
-  }
-  if (!IsIntrinsic()) {
-    return true;
-  }
-  IntrinsicOptimizations opt(*this);
-  return !opt.GetDoesNotNeedDexCache();
-}
-
-std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs) {
-  switch (rhs) {
-    case HInvokeStaticOrDirect::MethodLoadKind::kStringInit:
-      return os << "StringInit";
-    case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
-      return os << "Recursive";
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative:
-      return os << "BootImageLinkTimePcRelative";
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo:
-      return os << "BootImageRelRo";
-    case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry:
-      return os << "BssEntry";
-    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
-      return os << "JitDirectAddress";
-    case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall:
-      return os << "RuntimeCall";
-    default:
-      LOG(FATAL) << "Unknown MethodLoadKind: " << static_cast<int>(rhs);
-      UNREACHABLE();
-  }
-}
-
 std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckRequirement rhs) {
   switch (rhs) {
     case HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit:
@@ -2970,6 +3211,21 @@
   }
 }
 
+bool HInvokeVirtual::CanDoImplicitNullCheckOn(HInstruction* obj) const {
+  if (obj != InputAt(0)) {
+    return false;
+  }
+  switch (GetIntrinsic()) {
+    case Intrinsics::kNone:
+      return true;
+    case Intrinsics::kReferenceRefersTo:
+      return true;
+    default:
+      // TODO: Add implicit null checks in more intrinsics.
+      return false;
+  }
+}
+
 bool HLoadClass::InstructionDataEquals(const HInstruction* other) const {
   const HLoadClass* other_load_class = other->AsLoadClass();
   // TODO: To allow GVN for HLoadClass from different dex files, we should compare the type
@@ -2991,28 +3247,6 @@
   }
 }
 
-std::ostream& operator<<(std::ostream& os, HLoadClass::LoadKind rhs) {
-  switch (rhs) {
-    case HLoadClass::LoadKind::kReferrersClass:
-      return os << "ReferrersClass";
-    case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
-      return os << "BootImageLinkTimePcRelative";
-    case HLoadClass::LoadKind::kBootImageRelRo:
-      return os << "BootImageRelRo";
-    case HLoadClass::LoadKind::kBssEntry:
-      return os << "BssEntry";
-    case HLoadClass::LoadKind::kJitBootImageAddress:
-      return os << "JitBootImageAddress";
-    case HLoadClass::LoadKind::kJitTableAddress:
-      return os << "JitTableAddress";
-    case HLoadClass::LoadKind::kRuntimeCall:
-      return os << "RuntimeCall";
-    default:
-      LOG(FATAL) << "Unknown HLoadClass::LoadKind: " << static_cast<int>(rhs);
-      UNREACHABLE();
-  }
-}
-
 bool HLoadString::InstructionDataEquals(const HInstruction* other) const {
   const HLoadString* other_load_string = other->AsLoadString();
   // TODO: To allow GVN for HLoadString from different dex files, we should compare the strings
@@ -3033,26 +3267,6 @@
   }
 }
 
-std::ostream& operator<<(std::ostream& os, HLoadString::LoadKind rhs) {
-  switch (rhs) {
-    case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
-      return os << "BootImageLinkTimePcRelative";
-    case HLoadString::LoadKind::kBootImageRelRo:
-      return os << "BootImageRelRo";
-    case HLoadString::LoadKind::kBssEntry:
-      return os << "BssEntry";
-    case HLoadString::LoadKind::kJitBootImageAddress:
-      return os << "JitBootImageAddress";
-    case HLoadString::LoadKind::kJitTableAddress:
-      return os << "JitTableAddress";
-    case HLoadString::LoadKind::kRuntimeCall:
-      return os << "RuntimeCall";
-    default:
-      LOG(FATAL) << "Unknown HLoadString::LoadKind: " << static_cast<int>(rhs);
-      UNREACHABLE();
-  }
-}
-
 void HInstruction::RemoveEnvironmentUsers() {
   for (const HUseListNode<HEnvironment*>& use : GetEnvUses()) {
     HEnvironment* user = use.GetUser();
@@ -3164,25 +3378,6 @@
   }
 }
 
-std::ostream& operator<<(std::ostream& os, const MemBarrierKind& kind) {
-  switch (kind) {
-    case MemBarrierKind::kAnyStore:
-      return os << "AnyStore";
-    case MemBarrierKind::kLoadAny:
-      return os << "LoadAny";
-    case MemBarrierKind::kStoreStore:
-      return os << "StoreStore";
-    case MemBarrierKind::kAnyAny:
-      return os << "AnyAny";
-    case MemBarrierKind::kNTStoreStore:
-      return os << "NTStoreStore";
-
-    default:
-      LOG(FATAL) << "Unknown MemBarrierKind: " << static_cast<int>(kind);
-      UNREACHABLE();
-  }
-}
-
 // Check that intrinsic enum values fit within space set aside in ArtMethod modifier flags.
 #define CHECK_INTRINSICS_ENUM_VALUES(Name, InvokeType, _, SideEffects, Exceptions, ...) \
   static_assert( \
@@ -3194,19 +3389,19 @@
 #undef CHECK_INTRINSICS_ENUM_VALUES
 
 // Function that returns whether an intrinsic needs an environment or not.
-static inline IntrinsicNeedsEnvironmentOrCache NeedsEnvironmentOrCacheIntrinsic(Intrinsics i) {
+static inline IntrinsicNeedsEnvironment NeedsEnvironmentIntrinsic(Intrinsics i) {
   switch (i) {
     case Intrinsics::kNone:
-      return kNeedsEnvironmentOrCache;  // Non-sensical for intrinsic.
-#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnvOrCache, SideEffects, Exceptions, ...) \
+      return kNeedsEnvironment;  // Non-sensical for intrinsic.
+#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnv, SideEffects, Exceptions, ...) \
     case Intrinsics::k ## Name: \
-      return NeedsEnvOrCache;
+      return NeedsEnv;
 #include "intrinsics_list.h"
       INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
 #undef INTRINSICS_LIST
 #undef OPTIMIZING_INTRINSICS
   }
-  return kNeedsEnvironmentOrCache;
+  return kNeedsEnvironment;
 }
 
 // Function that returns whether an intrinsic has side effects.
@@ -3214,7 +3409,7 @@
   switch (i) {
     case Intrinsics::kNone:
       return kAllSideEffects;
-#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnvOrCache, SideEffects, Exceptions, ...) \
+#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnv, SideEffects, Exceptions, ...) \
     case Intrinsics::k ## Name: \
       return SideEffects;
 #include "intrinsics_list.h"
@@ -3230,7 +3425,7 @@
   switch (i) {
     case Intrinsics::kNone:
       return kCanThrow;
-#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnvOrCache, SideEffects, Exceptions, ...) \
+#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnv, SideEffects, Exceptions, ...) \
     case Intrinsics::k ## Name: \
       return Exceptions;
 #include "intrinsics_list.h"
@@ -3242,18 +3437,32 @@
 }
 
 void HInvoke::SetResolvedMethod(ArtMethod* method) {
-  // TODO: b/65872996 The intent is that polymorphic signature methods should
-  // be compiler intrinsics. At present, they are only interpreter intrinsics.
-  if (method != nullptr &&
-      method->IsIntrinsic() &&
-      !method->IsPolymorphicSignature()) {
+  if (method != nullptr && method->IsIntrinsic()) {
     Intrinsics intrinsic = static_cast<Intrinsics>(method->GetIntrinsic());
     SetIntrinsic(intrinsic,
-                 NeedsEnvironmentOrCacheIntrinsic(intrinsic),
+                 NeedsEnvironmentIntrinsic(intrinsic),
                  GetSideEffectsIntrinsic(intrinsic),
                  GetExceptionsIntrinsic(intrinsic));
   }
   resolved_method_ = method;
 }
 
+bool IsGEZero(HInstruction* instruction) {
+  DCHECK(instruction != nullptr);
+  if (instruction->IsArrayLength()) {
+    return true;
+  } else if (instruction->IsMin()) {
+    // Instruction MIN(>=0, >=0) is >= 0.
+    return IsGEZero(instruction->InputAt(0)) &&
+           IsGEZero(instruction->InputAt(1));
+  } else if (instruction->IsAbs()) {
+    // Instruction ABS(>=0) is >= 0.
+    // NOTE: ABS(minint) = minint prevents assuming
+    //       >= 0 without looking at the argument.
+    return IsGEZero(instruction->InputAt(0));
+  }
+  int64_t value = -1;
+  return IsInt64AndGet(instruction, &value) && value >= 0;
+}
+
 }  // namespace art
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 7ed5bca..939c49f 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -21,6 +21,7 @@
 #include <array>
 #include <type_traits>
 
+#include "base/arena_allocator.h"
 #include "base/arena_bit_vector.h"
 #include "base/arena_containers.h"
 #include "base/arena_object.h"
@@ -32,6 +33,9 @@
 #include "base/stl_util.h"
 #include "base/transform_array_ref.h"
 #include "art_method.h"
+#include "block_namer.h"
+#include "class_root.h"
+#include "compilation_kind.h"
 #include "data_type.h"
 #include "deoptimization_kind.h"
 #include "dex/dex_file.h"
@@ -68,6 +72,7 @@
 class HPhi;
 class HSuspendCheck;
 class HTryBoundary;
+class FieldInfo;
 class LiveInterval;
 class LocationSummary;
 class SlowPathCode;
@@ -272,13 +277,6 @@
     return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
   }
 
-  bool IsStrictSupertypeOf(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(IsValid());
-    DCHECK(rti.IsValid());
-    return GetTypeHandle().Get() != rti.GetTypeHandle().Get() &&
-        GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
-  }
-
   // Returns true if the type information provide the same amount of details.
   // Note that it does not mean that the instructions have the same actual type
   // (because the type can be the result of a merge).
@@ -309,26 +307,90 @@
 
 std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs);
 
+class HandleCache {
+ public:
+  explicit HandleCache(VariableSizedHandleScope* handles) : handles_(handles) { }
+
+  VariableSizedHandleScope* GetHandles() { return handles_; }
+
+  template <typename T>
+  MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_) {
+    return handles_->NewHandle(object);
+  }
+
+  template <typename T>
+  MutableHandle<T> NewHandle(ObjPtr<T> object) REQUIRES_SHARED(Locks::mutator_lock_) {
+    return handles_->NewHandle(object);
+  }
+
+  ReferenceTypeInfo::TypeHandle GetObjectClassHandle() {
+    return GetRootHandle(ClassRoot::kJavaLangObject, &object_class_handle_);
+  }
+
+  ReferenceTypeInfo::TypeHandle GetClassClassHandle() {
+    return GetRootHandle(ClassRoot::kJavaLangClass, &class_class_handle_);
+  }
+
+  ReferenceTypeInfo::TypeHandle GetMethodHandleClassHandle() {
+    return GetRootHandle(ClassRoot::kJavaLangInvokeMethodHandleImpl, &method_handle_class_handle_);
+  }
+
+  ReferenceTypeInfo::TypeHandle GetMethodTypeClassHandle() {
+    return GetRootHandle(ClassRoot::kJavaLangInvokeMethodType, &method_type_class_handle_);
+  }
+
+  ReferenceTypeInfo::TypeHandle GetStringClassHandle() {
+    return GetRootHandle(ClassRoot::kJavaLangString, &string_class_handle_);
+  }
+
+  ReferenceTypeInfo::TypeHandle GetThrowableClassHandle() {
+    return GetRootHandle(ClassRoot::kJavaLangThrowable, &throwable_class_handle_);
+  }
+
+
+ private:
+  inline ReferenceTypeInfo::TypeHandle GetRootHandle(ClassRoot class_root,
+                                                     ReferenceTypeInfo::TypeHandle* cache) {
+    if (UNLIKELY(!ReferenceTypeInfo::IsValidHandle(*cache))) {
+      *cache = CreateRootHandle(handles_, class_root);
+    }
+    return *cache;
+  }
+
+  static ReferenceTypeInfo::TypeHandle CreateRootHandle(VariableSizedHandleScope* handles,
+                                                        ClassRoot class_root);
+
+  VariableSizedHandleScope* handles_;
+
+  ReferenceTypeInfo::TypeHandle object_class_handle_;
+  ReferenceTypeInfo::TypeHandle class_class_handle_;
+  ReferenceTypeInfo::TypeHandle method_handle_class_handle_;
+  ReferenceTypeInfo::TypeHandle method_type_class_handle_;
+  ReferenceTypeInfo::TypeHandle string_class_handle_;
+  ReferenceTypeInfo::TypeHandle throwable_class_handle_;
+};
+
 // Control-flow graph of a method. Contains a list of basic blocks.
 class HGraph : public ArenaObject<kArenaAllocGraph> {
  public:
   HGraph(ArenaAllocator* allocator,
          ArenaStack* arena_stack,
+         VariableSizedHandleScope* handles,
          const DexFile& dex_file,
          uint32_t method_idx,
          InstructionSet instruction_set,
          InvokeType invoke_type = kInvalidInvokeType,
          bool dead_reference_safe = false,
          bool debuggable = false,
-         bool osr = false,
-         bool is_shared_jit_code = false,
-         bool baseline = false,
+         CompilationKind compilation_kind = CompilationKind::kOptimized,
          int start_instruction_id = 0)
       : allocator_(allocator),
         arena_stack_(arena_stack),
+        handle_cache_(handles),
         blocks_(allocator->Adapter(kArenaAllocBlockList)),
         reverse_post_order_(allocator->Adapter(kArenaAllocReversePostOrder)),
         linear_order_(allocator->Adapter(kArenaAllocLinearOrder)),
+        reachability_graph_(allocator, 0, 0, true, kArenaAllocReachabilityGraph),
         entry_block_(nullptr),
         exit_block_(nullptr),
         maximum_number_of_out_vregs_(0),
@@ -341,6 +403,7 @@
         has_simd_(false),
         has_loops_(false),
         has_irreducible_loops_(false),
+        has_direct_critical_native_call_(false),
         dead_reference_safe_(dead_reference_safe),
         debuggable_(debuggable),
         current_instruction_id_(start_instruction_id),
@@ -357,21 +420,28 @@
         cached_double_constants_(std::less<int64_t>(), allocator->Adapter(kArenaAllocConstantsMap)),
         cached_current_method_(nullptr),
         art_method_(nullptr),
-        inexact_object_rti_(ReferenceTypeInfo::CreateInvalid()),
-        osr_(osr),
-        baseline_(baseline),
-        cha_single_implementation_list_(allocator->Adapter(kArenaAllocCHA)),
-        is_shared_jit_code_(is_shared_jit_code) {
+        compilation_kind_(compilation_kind),
+        cha_single_implementation_list_(allocator->Adapter(kArenaAllocCHA)) {
     blocks_.reserve(kDefaultNumberOfBlocks);
   }
 
-  // Acquires and stores RTI of inexact Object to be used when creating HNullConstant.
-  void InitializeInexactObjectRTI(VariableSizedHandleScope* handles);
+  std::ostream& Dump(std::ostream& os,
+                     std::optional<std::reference_wrapper<const BlockNamer>> namer = std::nullopt);
 
   ArenaAllocator* GetAllocator() const { return allocator_; }
   ArenaStack* GetArenaStack() const { return arena_stack_; }
+
+  HandleCache* GetHandleCache() { return &handle_cache_; }
+
   const ArenaVector<HBasicBlock*>& GetBlocks() const { return blocks_; }
 
+  // An iterator to only blocks that are still actually in the graph (when
+  // blocks are removed they are replaced with 'nullptr' in GetBlocks to
+  // simplify block-id assignment and avoid memmoves in the block-list).
+  IterationRange<FilterNull<ArenaVector<HBasicBlock*>::const_iterator>> GetActiveBlocks() const {
+    return FilterOutNull(MakeIterationRange(GetBlocks()));
+  }
+
   bool IsInSsaForm() const { return in_ssa_form_; }
   void SetInSsaForm() { in_ssa_form_ = true; }
 
@@ -386,6 +456,8 @@
 
   void ComputeDominanceInformation();
   void ClearDominanceInformation();
+  void ComputeReachabilityInformation();
+  void ClearReachabilityInformation();
   void ClearLoopInformation();
   void FindBackEdges(ArenaBitVector* visited);
   GraphAnalysisResult BuildDominatorTree();
@@ -534,6 +606,10 @@
     has_bounds_checks_ = value;
   }
 
+  // Returns true if dest is reachable from source, using either blocks or block-ids.
+  bool PathBetween(const HBasicBlock* source, const HBasicBlock* dest) const;
+  bool PathBetween(uint32_t source_id, uint32_t dest_id) const;
+
   // Is the code known to be robust against eliminating dead references
   // and the effects of early finalization?
   bool IsDeadReferenceSafe() const { return dead_reference_safe_; }
@@ -589,13 +665,11 @@
     return instruction_set_;
   }
 
-  bool IsCompilingOsr() const { return osr_; }
+  bool IsCompilingOsr() const { return compilation_kind_ == CompilationKind::kOsr; }
 
-  bool IsCompilingBaseline() const { return baseline_; }
+  bool IsCompilingBaseline() const { return compilation_kind_ == CompilationKind::kBaseline; }
 
-  bool IsCompilingForSharedJitCode() const {
-    return is_shared_jit_code_;
-  }
+  CompilationKind GetCompilationKind() const { return compilation_kind_; }
 
   ArenaSet<ArtMethod*>& GetCHASingleImplementationList() {
     return cha_single_implementation_list_;
@@ -624,6 +698,9 @@
   bool HasIrreducibleLoops() const { return has_irreducible_loops_; }
   void SetHasIrreducibleLoops(bool value) { has_irreducible_loops_ = value; }
 
+  bool HasDirectCriticalNativeCall() const { return has_direct_critical_native_call_; }
+  void SetHasDirectCriticalNativeCall(bool value) { has_direct_critical_native_call_ = value; }
+
   ArtMethod* GetArtMethod() const { return art_method_; }
   void SetArtMethod(ArtMethod* method) { art_method_ = method; }
 
@@ -632,7 +709,9 @@
   // before cursor.
   HInstruction* InsertOppositeCondition(HInstruction* cond, HInstruction* cursor);
 
-  ReferenceTypeInfo GetInexactObjectRti() const { return inexact_object_rti_; }
+  ReferenceTypeInfo GetInexactObjectRti() {
+    return ReferenceTypeInfo::Create(handle_cache_.GetObjectClassHandle(), /* is_exact= */ false);
+  }
 
   uint32_t GetNumberOfCHAGuards() { return number_of_cha_guards_; }
   void SetNumberOfCHAGuards(uint32_t num) { number_of_cha_guards_ = num; }
@@ -675,6 +754,8 @@
   ArenaAllocator* const allocator_;
   ArenaStack* const arena_stack_;
 
+  HandleCache handle_cache_;
+
   // List of blocks in insertion order.
   ArenaVector<HBasicBlock*> blocks_;
 
@@ -685,6 +766,10 @@
   // post order, this order is not incrementally kept up-to-date.
   ArenaVector<HBasicBlock*> linear_order_;
 
+  // Reachability graph for checking connectedness between nodes. Acts as a partitioned vector where
+  // each RoundUp(blocks_.size(), BitVector::kWordBits) is the reachability of each node.
+  ArenaBitVectorArray reachability_graph_;
+
   HBasicBlock* entry_block_;
   HBasicBlock* exit_block_;
 
@@ -731,6 +816,10 @@
   // so there might be false positives.
   bool has_irreducible_loops_;
 
+  // Flag whether there are any direct calls to native code registered
+  // for @CriticalNative methods.
+  bool has_direct_critical_native_call_;
+
   // Is the code known to be robust against eliminating dead references
   // and the effects of early finalization? If false, dead reference variables
   // are kept if they might be visible to the garbage collector.
@@ -781,26 +870,15 @@
   // (such as when the superclass could not be found).
   ArtMethod* art_method_;
 
-  // Keep the RTI of inexact Object to avoid having to pass stack handle
-  // collection pointer to passes which may create NullConstant.
-  ReferenceTypeInfo inexact_object_rti_;
-
-  // Whether we are compiling this graph for on stack replacement: this will
-  // make all loops seen as irreducible and emit special stack maps to mark
-  // compiled code entries which the interpreter can directly jump to.
-  const bool osr_;
-
-  // Whether we are compiling baseline (not running optimizations). This affects
-  // the code being generated.
-  const bool baseline_;
+  // How we are compiling the graph: either optimized, osr, or baseline.
+  // For osr, we will make all loops seen as irreducible and emit special
+  // stack maps to mark compiled code entries which the interpreter can
+  // directly jump to.
+  const CompilationKind compilation_kind_;
 
   // List of methods that are assumed to have single implementation.
   ArenaSet<ArtMethod*> cha_single_implementation_list_;
 
-  // Whether we are JIT compiling in the shared region area, putting
-  // restrictions on, for example, how literals are being generated.
-  bool is_shared_jit_code_;
-
   friend class SsaBuilder;           // For caching constants.
   friend class SsaLivenessAnalysis;  // For the linear order.
   friend class HInliner;             // For the reverse post order.
@@ -808,6 +886,10 @@
   DISALLOW_COPY_AND_ASSIGN(HGraph);
 };
 
+inline std::ostream& operator<<(std::ostream& os, HGraph& graph) {
+  return graph.Dump(os);
+}
+
 class HLoopInformation : public ArenaObject<kArenaAllocLoopInfo> {
  public:
   HLoopInformation(HBasicBlock* header, HGraph* graph)
@@ -1016,6 +1098,10 @@
     return predecessors_;
   }
 
+  size_t GetNumberOfPredecessors() const {
+    return GetPredecessors().size();
+  }
+
   const ArenaVector<HBasicBlock*>& GetSuccessors() const {
     return successors_;
   }
@@ -1358,6 +1444,8 @@
 
   friend class HGraph;
   friend class HInstruction;
+  // Allow manual control of the ordering of predecessors/successors
+  friend class OptimizingUnitTestHelper;
 
   DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
 };
@@ -1387,7 +1475,7 @@
   DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator);
 };
 
-#define FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M)                         \
+#define FOR_EACH_CONCRETE_INSTRUCTION_SCALAR_COMMON(M)                  \
   M(Above, Condition)                                                   \
   M(AboveOrEqual, Condition)                                            \
   M(Abs, UnaryOperation)                                                \
@@ -1422,6 +1510,7 @@
   M(If, Instruction)                                                    \
   M(InstanceFieldGet, Instruction)                                      \
   M(InstanceFieldSet, Instruction)                                      \
+  M(PredicatedInstanceFieldGet, Instruction)                            \
   M(InstanceOf, Instruction)                                            \
   M(IntConstant, Constant)                                              \
   M(IntermediateAddress, Instruction)                                   \
@@ -1477,7 +1566,9 @@
   M(TryBoundary, Instruction)                                           \
   M(TypeConversion, Instruction)                                        \
   M(UShr, BinaryOperation)                                              \
-  M(Xor, BinaryOperation)                                               \
+  M(Xor, BinaryOperation)
+
+#define FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(M)                  \
   M(VecReplicateScalar, VecUnaryOperation)                              \
   M(VecExtractScalar, VecUnaryOperation)                                \
   M(VecReduce, VecUnaryOperation)                                       \
@@ -1507,6 +1598,13 @@
   M(VecDotProd, VecOperation)                                           \
   M(VecLoad, VecMemoryOperation)                                        \
   M(VecStore, VecMemoryOperation)                                       \
+  M(VecPredSetAll, VecPredSetOperation)                                 \
+  M(VecPredWhile, VecPredSetOperation)                                  \
+  M(VecPredCondition, VecOperation)                                     \
+
+#define FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M)                         \
+  FOR_EACH_CONCRETE_INSTRUCTION_SCALAR_COMMON(M)                        \
+  FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(M)
 
 /*
  * Instructions, shared across several (not all) architectures.
@@ -1563,7 +1661,8 @@
   M(VecOperation, Instruction)                                          \
   M(VecUnaryOperation, VecOperation)                                    \
   M(VecBinaryOperation, VecOperation)                                   \
-  M(VecMemoryOperation, VecOperation)
+  M(VecMemoryOperation, VecOperation)                                   \
+  M(VecPredSetOperation, VecOperation)
 
 #define FOR_EACH_INSTRUCTION(M)                                         \
   FOR_EACH_CONCRETE_INSTRUCTION(M)                                      \
@@ -1589,8 +1688,7 @@
   H##type& operator=(const H##type&) = delete;                          \
   public:
 
-#define DEFAULT_COPY_CONSTRUCTOR(type)                                  \
-  explicit H##type(const H##type& other) = default;
+#define DEFAULT_COPY_CONSTRUCTOR(type) H##type(const H##type& other) = default;
 
 template <typename T>
 class HUseListNode : public ArenaObject<kArenaAllocUseListNode>,
@@ -2014,6 +2112,23 @@
     return GetParent() != nullptr;
   }
 
+  class EnvInputSelector {
+   public:
+    explicit EnvInputSelector(const HEnvironment* e) : env_(e) {}
+    HInstruction* operator()(size_t s) const {
+      return env_->GetInstructionAt(s);
+    }
+   private:
+    const HEnvironment* env_;
+  };
+
+  using HConstEnvInputRef = TransformIterator<CountIter, EnvInputSelector>;
+  IterationRange<HConstEnvInputRef> GetEnvInputs() const {
+    IterationRange<CountIter> range(Range(Size()));
+    return MakeIterationRange(MakeTransformIterator(range.begin(), EnvInputSelector(this)),
+                              MakeTransformIterator(range.end(), EnvInputSelector(this)));
+  }
+
  private:
   ArenaVector<HUserRecord<HEnvironment*>> vregs_;
   ArenaVector<Location> locations_;
@@ -2029,10 +2144,46 @@
   DISALLOW_COPY_AND_ASSIGN(HEnvironment);
 };
 
+std::ostream& operator<<(std::ostream& os, const HInstruction& rhs);
+
+// Iterates over the Environments
+class HEnvironmentIterator : public ValueObject,
+                             public std::iterator<std::forward_iterator_tag, HEnvironment*> {
+ public:
+  explicit HEnvironmentIterator(HEnvironment* cur) : cur_(cur) {}
+
+  HEnvironment* operator*() const {
+    return cur_;
+  }
+
+  HEnvironmentIterator& operator++() {
+    DCHECK(cur_ != nullptr);
+    cur_ = cur_->GetParent();
+    return *this;
+  }
+
+  HEnvironmentIterator operator++(int) {
+    HEnvironmentIterator prev(*this);
+    ++(*this);
+    return prev;
+  }
+
+  bool operator==(const HEnvironmentIterator& other) const {
+    return other.cur_ == cur_;
+  }
+
+  bool operator!=(const HEnvironmentIterator& other) const {
+    return !(*this == other);
+  }
+
+ private:
+  HEnvironment* cur_;
+};
+
 class HInstruction : public ArenaObject<kArenaAllocInstruction> {
  public:
 #define DECLARE_KIND(type, super) k##type,
-  enum InstructionKind {
+  enum InstructionKind {  // private marker to avoid generate-operator-out.py from processing.
     FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_KIND)
     kLastInstructionKind
   };
@@ -2062,6 +2213,22 @@
 
   virtual ~HInstruction() {}
 
+  std::ostream& Dump(std::ostream& os, bool dump_args = false);
+
+  // Helper for dumping without argument information using operator<<
+  struct NoArgsDump {
+    const HInstruction* ins;
+  };
+  NoArgsDump DumpWithoutArgs() const {
+    return NoArgsDump{this};
+  }
+  // Helper for dumping with argument information using operator<<
+  struct ArgsDump {
+    const HInstruction* ins;
+  };
+  ArgsDump DumpWithArgs() const {
+    return ArgsDump{this};
+  }
 
   HInstruction* GetNext() const { return next_; }
   HInstruction* GetPrevious() const { return previous_; }
@@ -2131,6 +2298,10 @@
 
   // Does the instruction always throw an exception unconditionally?
   virtual bool AlwaysThrows() const { return false; }
+  // Will this instruction only cause async exceptions if it causes any at all?
+  virtual bool OnlyThrowsAsyncExceptions() const {
+    return false;
+  }
 
   bool CanThrowIntoCatchBlock() const { return CanThrow() && block_->IsTryBlock(); }
 
@@ -2179,8 +2350,9 @@
     DCHECK(user != nullptr);
     // Note: fixup_end remains valid across push_front().
     auto fixup_end = uses_.empty() ? uses_.begin() : ++uses_.begin();
+    ArenaAllocator* allocator = user->GetBlock()->GetGraph()->GetAllocator();
     HUseListNode<HInstruction*>* new_node =
-        new (GetBlock()->GetGraph()->GetAllocator()) HUseListNode<HInstruction*>(user, index);
+        new (allocator) HUseListNode<HInstruction*>(user, index);
     uses_.push_front(*new_node);
     FixUpUserRecordsAfterUseInsertion(fixup_end);
   }
@@ -2251,6 +2423,10 @@
 
   bool HasEnvironment() const { return environment_ != nullptr; }
   HEnvironment* GetEnvironment() const { return environment_; }
+  IterationRange<HEnvironmentIterator> GetAllEnvironments() const {
+    return MakeIterationRange(HEnvironmentIterator(GetEnvironment()),
+                              HEnvironmentIterator(nullptr));
+  }
   // Set the `environment_` field. Raw because this method does not
   // update the uses lists.
   void SetRawEnvironment(HEnvironment* environment) {
@@ -2351,6 +2527,17 @@
     UNREACHABLE();
   }
 
+  virtual bool IsFieldAccess() const {
+    return false;
+  }
+
+  virtual const FieldInfo& GetFieldInfo() const {
+    CHECK(IsFieldAccess()) << "Only callable on field accessors not " << DebugName() << " "
+                           << *this;
+    LOG(FATAL) << "Must be overridden by field accessors. Not implemented by " << *this;
+    UNREACHABLE();
+  }
+
   // Return whether instruction can be cloned (copied).
   virtual bool IsClonable() const { return false; }
 
@@ -2403,10 +2590,6 @@
     return NeedsEnvironment() || IsCurrentMethod();
   }
 
-  // Returns whether the code generation of the instruction will require to have access
-  // to the dex cache of the current method's declaring class via the current method.
-  virtual bool NeedsDexCacheOfDeclaringClass() const { return false; }
-
   // Does this instruction have any use in an environment before
   // control flow hits 'other'?
   bool HasAnyEnvironmentUseBefore(HInstruction* other);
@@ -2590,7 +2773,15 @@
   friend class HGraph;
   friend class HInstructionList;
 };
-std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs);
+
+std::ostream& operator<<(std::ostream& os, HInstruction::InstructionKind rhs);
+std::ostream& operator<<(std::ostream& os, const HInstruction::NoArgsDump rhs);
+std::ostream& operator<<(std::ostream& os, const HInstruction::ArgsDump rhs);
+std::ostream& operator<<(std::ostream& os, const HUseList<HInstruction*>& lst);
+std::ostream& operator<<(std::ostream& os, const HUseList<HEnvironment*>& lst);
+
+// Forward declarations for friends
+template <typename InnerIter> struct HSTLInstructionIterator;
 
 // Iterates over the instructions, while preserving the next instruction
 // in case the current instruction gets removed from the list by the user
@@ -2610,10 +2801,12 @@
   }
 
  private:
+  HInstructionIterator() : instruction_(nullptr), next_(nullptr) {}
+
   HInstruction* instruction_;
   HInstruction* next_;
 
-  DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
+  friend struct HSTLInstructionIterator<HInstructionIterator>;
 };
 
 // Iterates over the instructions without saving the next instruction,
@@ -2632,9 +2825,11 @@
   }
 
  private:
+  HInstructionIteratorHandleChanges() : instruction_(nullptr) {}
+
   HInstruction* instruction_;
 
-  DISALLOW_COPY_AND_ASSIGN(HInstructionIteratorHandleChanges);
+  friend struct HSTLInstructionIterator<HInstructionIteratorHandleChanges>;
 };
 
 
@@ -2653,12 +2848,63 @@
   }
 
  private:
+  HBackwardInstructionIterator() : instruction_(nullptr), next_(nullptr) {}
+
   HInstruction* instruction_;
   HInstruction* next_;
 
-  DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
+  friend struct HSTLInstructionIterator<HBackwardInstructionIterator>;
 };
 
+template <typename InnerIter>
+struct HSTLInstructionIterator : public ValueObject,
+                                 public std::iterator<std::forward_iterator_tag, HInstruction*> {
+ public:
+  static_assert(std::is_same_v<InnerIter, HBackwardInstructionIterator> ||
+                    std::is_same_v<InnerIter, HInstructionIterator> ||
+                    std::is_same_v<InnerIter, HInstructionIteratorHandleChanges>,
+                "Unknown wrapped iterator!");
+
+  explicit HSTLInstructionIterator(InnerIter inner) : inner_(inner) {}
+  HInstruction* operator*() const {
+    DCHECK(inner_.Current() != nullptr);
+    return inner_.Current();
+  }
+
+  HSTLInstructionIterator<InnerIter>& operator++() {
+    DCHECK(*this != HSTLInstructionIterator<InnerIter>::EndIter());
+    inner_.Advance();
+    return *this;
+  }
+
+  HSTLInstructionIterator<InnerIter> operator++(int) {
+    HSTLInstructionIterator<InnerIter> prev(*this);
+    ++(*this);
+    return prev;
+  }
+
+  bool operator==(const HSTLInstructionIterator<InnerIter>& other) const {
+    return inner_.Current() == other.inner_.Current();
+  }
+
+  bool operator!=(const HSTLInstructionIterator<InnerIter>& other) const {
+    return !(*this == other);
+  }
+
+  static HSTLInstructionIterator<InnerIter> EndIter() {
+    return HSTLInstructionIterator<InnerIter>(InnerIter());
+  }
+
+ private:
+  InnerIter inner_;
+};
+
+template <typename InnerIter>
+IterationRange<HSTLInstructionIterator<InnerIter>> MakeSTLInstructionIteratorRange(InnerIter iter) {
+  return MakeIterationRange(HSTLInstructionIterator<InnerIter>(iter),
+                            HSTLInstructionIterator<InnerIter>::EndIter());
+}
+
 class HVariableInputSizeInstruction : public HInstruction {
  public:
   using HInstruction::GetInputRecords;  // Keep the const version visible.
@@ -3615,14 +3861,14 @@
 
 // The comparison bias applies for floating point operations and indicates how NaN
 // comparisons are treated:
-enum class ComparisonBias {
+enum class ComparisonBias {  // private marker to avoid generate-operator-out.py from processing.
   kNoBias,  // bias is not applicable (i.e. for long operation)
   kGtBias,  // return 1 for NaN comparisons
   kLtBias,  // return -1 for NaN comparisons
   kLast = kLtBias
 };
 
-std::ostream& operator<<(std::ostream& os, const ComparisonBias& rhs);
+std::ostream& operator<<(std::ostream& os, ComparisonBias rhs);
 
 class HCondition : public HBinaryOperation {
  public:
@@ -4149,8 +4395,6 @@
                          SideEffectsForArchRuntimeCalls(comparison_type),
                          dex_pc) {
     SetPackedField<ComparisonBiasField>(bias);
-    DCHECK_EQ(comparison_type, DataType::Kind(first->GetType()));
-    DCHECK_EQ(comparison_type, DataType::Kind(second->GetType()));
   }
 
   template <typename T>
@@ -4237,11 +4481,16 @@
         dex_file_(dex_file),
         entrypoint_(entrypoint) {
     SetPackedFlag<kFlagFinalizable>(finalizable);
+    SetPackedFlag<kFlagPartialMaterialization>(false);
     SetRawInputAt(0, cls);
   }
 
   bool IsClonable() const override { return true; }
 
+  void SetPartialMaterialization() {
+    SetPackedFlag<kFlagPartialMaterialization>(true);
+  }
+
   dex::TypeIndex GetTypeIndex() const { return type_index_; }
   const DexFile& GetDexFile() const { return dex_file_; }
 
@@ -4250,6 +4499,9 @@
 
   // Can throw errors when out-of-memory or if it's not instantiable/accessible.
   bool CanThrow() const override { return true; }
+  bool OnlyThrowsAsyncExceptions() const override {
+    return !IsFinalizable() && !NeedsChecks();
+  }
 
   bool NeedsChecks() const {
     return entrypoint_ == kQuickAllocObjectWithChecks;
@@ -4259,6 +4511,10 @@
 
   bool CanBeNull() const override { return false; }
 
+  bool IsPartialMaterialization() const {
+    return GetPackedFlag<kFlagPartialMaterialization>();
+  }
+
   QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
 
   void SetEntrypoint(QuickEntrypointEnum entrypoint) {
@@ -4283,7 +4539,8 @@
 
  private:
   static constexpr size_t kFlagFinalizable = kNumberOfGenericPackedBits;
-  static constexpr size_t kNumberOfNewInstancePackedBits = kFlagFinalizable + 1;
+  static constexpr size_t kFlagPartialMaterialization = kFlagFinalizable + 1;
+  static constexpr size_t kNumberOfNewInstancePackedBits = kFlagPartialMaterialization + 1;
   static_assert(kNumberOfNewInstancePackedBits <= kMaxNumberOfPackedBits,
                 "Too many packed fields.");
 
@@ -4292,9 +4549,9 @@
   QuickEntrypointEnum entrypoint_;
 };
 
-enum IntrinsicNeedsEnvironmentOrCache {
-  kNoEnvironmentOrCache,        // Intrinsic does not require an environment or dex cache.
-  kNeedsEnvironmentOrCache      // Intrinsic requires an environment or requires a dex cache.
+enum IntrinsicNeedsEnvironment {
+  kNoEnvironment,        // Intrinsic does not require an environment.
+  kNeedsEnvironment      // Intrinsic requires an environment.
 };
 
 enum IntrinsicSideEffects {
@@ -4309,6 +4566,57 @@
   kCanThrow  // Intrinsic may throw exceptions.
 };
 
+// Determines how to load an ArtMethod*.
+enum class MethodLoadKind {
+  // Use a String init ArtMethod* loaded from Thread entrypoints.
+  kStringInit,
+
+  // Use the method's own ArtMethod* loaded by the register allocator.
+  kRecursive,
+
+  // Use PC-relative boot image ArtMethod* address that will be known at link time.
+  // Used for boot image methods referenced by boot image code.
+  kBootImageLinkTimePcRelative,
+
+  // Load from an entry in the .data.bimg.rel.ro using a PC-relative load.
+  // Used for app->boot calls with relocatable image.
+  kBootImageRelRo,
+
+  // Load from an entry in the .bss section using a PC-relative load.
+  // Used for methods outside boot image referenced by AOT-compiled app and boot image code.
+  kBssEntry,
+
+  // Use ArtMethod* at a known address, embed the direct address in the code.
+  // Used for for JIT-compiled calls.
+  kJitDirectAddress,
+
+  // Make a runtime call to resolve and call the method. This is the last-resort-kind
+  // used when other kinds are unimplemented on a particular architecture.
+  kRuntimeCall,
+};
+
+// Determines the location of the code pointer of an invoke.
+enum class CodePtrLocation {
+  // Recursive call, use local PC-relative call instruction.
+  kCallSelf,
+
+  // Use native pointer from the Artmethod*.
+  // Used for @CriticalNative to avoid going through the compiled stub. This call goes through
+  // a special resolution stub if the class is not initialized or no native code is registered.
+  kCallCriticalNative,
+
+  // Use code pointer from the ArtMethod*.
+  // Used when we don't know the target code. This is also the last-resort-kind used when
+  // other kinds are unimplemented or impractical (i.e. slow) on a particular architecture.
+  kCallArtMethod,
+};
+
+static inline bool IsPcRelativeMethodLoadKind(MethodLoadKind load_kind) {
+  return load_kind == MethodLoadKind::kBootImageLinkTimePcRelative ||
+         load_kind == MethodLoadKind::kBootImageRelRo ||
+         load_kind == MethodLoadKind::kBssEntry;
+}
+
 class HInvoke : public HVariableInputSizeInstruction {
  public:
   bool NeedsEnvironment() const override;
@@ -4323,8 +4631,6 @@
   // inputs at the end of their list of inputs.
   uint32_t GetNumberOfArguments() const { return number_of_arguments_; }
 
-  uint32_t GetDexMethodIndex() const { return dex_method_index_; }
-
   InvokeType GetInvokeType() const {
     return GetPackedField<InvokeTypeField>();
   }
@@ -4334,7 +4640,7 @@
   }
 
   void SetIntrinsic(Intrinsics intrinsic,
-                    IntrinsicNeedsEnvironmentOrCache needs_env_or_cache,
+                    IntrinsicNeedsEnvironment needs_env,
                     IntrinsicSideEffects side_effects,
                     IntrinsicExceptions exceptions);
 
@@ -4367,7 +4673,13 @@
   bool IsIntrinsic() const { return intrinsic_ != Intrinsics::kNone; }
 
   ArtMethod* GetResolvedMethod() const { return resolved_method_; }
-  void SetResolvedMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
+  void SetResolvedMethod(ArtMethod* method);
+
+  MethodReference GetMethodReference() const { return method_reference_; }
+
+  const MethodReference GetResolvedMethodReference() const {
+    return resolved_method_reference_;
+  }
 
   DECLARE_ABSTRACT_INSTRUCTION(Invoke);
 
@@ -4387,8 +4699,9 @@
           uint32_t number_of_other_inputs,
           DataType::Type return_type,
           uint32_t dex_pc,
-          uint32_t dex_method_index,
+          MethodReference method_reference,
           ArtMethod* resolved_method,
+          MethodReference resolved_method_reference,
           InvokeType invoke_type)
     : HVariableInputSizeInstruction(
           kind,
@@ -4399,13 +4712,12 @@
           number_of_arguments + number_of_other_inputs,
           kArenaAllocInvokeInputs),
       number_of_arguments_(number_of_arguments),
-      dex_method_index_(dex_method_index),
+      method_reference_(method_reference),
+      resolved_method_reference_(resolved_method_reference),
       intrinsic_(Intrinsics::kNone),
       intrinsic_optimizations_(0) {
     SetPackedField<InvokeTypeField>(invoke_type);
     SetPackedFlag<kFlagCanThrow>(true);
-    // Check mutator lock, constructors lack annotalysis support.
-    Locks::mutator_lock_->AssertNotExclusiveHeld(Thread::Current());
     SetResolvedMethod(resolved_method);
   }
 
@@ -4413,7 +4725,9 @@
 
   uint32_t number_of_arguments_;
   ArtMethod* resolved_method_;
-  const uint32_t dex_method_index_;
+  const MethodReference method_reference_;
+  // Cached values of the resolved method, to avoid needing the mutator lock.
+  const MethodReference resolved_method_reference_;
   Intrinsics intrinsic_;
 
   // A magic word holding optimizations for intrinsics. See intrinsics.h.
@@ -4426,7 +4740,7 @@
                     uint32_t number_of_arguments,
                     DataType::Type return_type,
                     uint32_t dex_pc,
-                    uint32_t dex_method_index,
+                    MethodReference method_reference,
                     InvokeType invoke_type)
       : HInvoke(kInvokeUnresolved,
                 allocator,
@@ -4434,8 +4748,9 @@
                 /* number_of_other_inputs= */ 0u,
                 return_type,
                 dex_pc,
-                dex_method_index,
+                method_reference,
                 nullptr,
+                MethodReference(nullptr, 0u),
                 invoke_type) {
   }
 
@@ -4453,23 +4768,34 @@
                      uint32_t number_of_arguments,
                      DataType::Type return_type,
                      uint32_t dex_pc,
-                     uint32_t dex_method_index)
+                     MethodReference method_reference,
+                     // resolved_method is the ArtMethod object corresponding to the polymorphic
+                     // method (e.g. VarHandle.get), resolved using the class linker. It is needed
+                     // to pass intrinsic information to the HInvokePolymorphic node.
+                     ArtMethod* resolved_method,
+                     MethodReference resolved_method_reference,
+                     dex::ProtoIndex proto_idx)
       : HInvoke(kInvokePolymorphic,
                 allocator,
                 number_of_arguments,
                 /* number_of_other_inputs= */ 0u,
                 return_type,
                 dex_pc,
-                dex_method_index,
-                nullptr,
-                kVirtual) {
+                method_reference,
+                resolved_method,
+                resolved_method_reference,
+                kPolymorphic),
+        proto_idx_(proto_idx) {
   }
 
   bool IsClonable() const override { return true; }
 
+  dex::ProtoIndex GetProtoIndex() { return proto_idx_; }
+
   DECLARE_INSTRUCTION(InvokePolymorphic);
 
  protected:
+  dex::ProtoIndex proto_idx_;
   DEFAULT_COPY_CONSTRUCTOR(InvokePolymorphic);
 };
 
@@ -4479,15 +4805,17 @@
                 uint32_t number_of_arguments,
                 uint32_t call_site_index,
                 DataType::Type return_type,
-                uint32_t dex_pc)
+                uint32_t dex_pc,
+                MethodReference method_reference)
       : HInvoke(kInvokeCustom,
                 allocator,
                 number_of_arguments,
                 /* number_of_other_inputs= */ 0u,
                 return_type,
                 dex_pc,
-                /* dex_method_index= */ dex::kDexNoIndex,
+                method_reference,
                 /* resolved_method= */ nullptr,
+                MethodReference(nullptr, 0u),
                 kStatic),
       call_site_index_(call_site_index) {
   }
@@ -4509,53 +4837,13 @@
  public:
   // Requirements of this method call regarding the class
   // initialization (clinit) check of its declaring class.
-  enum class ClinitCheckRequirement {
+  enum class ClinitCheckRequirement {  // private marker to avoid generate-operator-out.py from processing.
     kNone,      // Class already initialized.
     kExplicit,  // Static call having explicit clinit check as last input.
     kImplicit,  // Static call implicitly requiring a clinit check.
     kLast = kImplicit
   };
 
-  // Determines how to load the target ArtMethod*.
-  enum class MethodLoadKind {
-    // Use a String init ArtMethod* loaded from Thread entrypoints.
-    kStringInit,
-
-    // Use the method's own ArtMethod* loaded by the register allocator.
-    kRecursive,
-
-    // Use PC-relative boot image ArtMethod* address that will be known at link time.
-    // Used for boot image methods referenced by boot image code.
-    kBootImageLinkTimePcRelative,
-
-    // Load from an entry in the .data.bimg.rel.ro using a PC-relative load.
-    // Used for app->boot calls with relocatable image.
-    kBootImageRelRo,
-
-    // Load from an entry in the .bss section using a PC-relative load.
-    // Used for methods outside boot image referenced by AOT-compiled app and boot image code.
-    kBssEntry,
-
-    // Use ArtMethod* at a known address, embed the direct address in the code.
-    // Used for for JIT-compiled calls.
-    kJitDirectAddress,
-
-    // Make a runtime call to resolve and call the method. This is the last-resort-kind
-    // used when other kinds are unimplemented on a particular architecture.
-    kRuntimeCall,
-  };
-
-  // Determines the location of the code pointer.
-  enum class CodePtrLocation {
-    // Recursive call, use local PC-relative call instruction.
-    kCallSelf,
-
-    // Use code pointer from the ArtMethod*.
-    // Used when we don't know the target code. This is also the last-resort-kind used when
-    // other kinds are unimplemented or impractical (i.e. slow) on a particular architecture.
-    kCallArtMethod,
-  };
-
   struct DispatchInfo {
     MethodLoadKind method_load_kind;
     CodePtrLocation code_ptr_location;
@@ -4570,42 +4858,42 @@
                         uint32_t number_of_arguments,
                         DataType::Type return_type,
                         uint32_t dex_pc,
-                        uint32_t method_index,
+                        MethodReference method_reference,
                         ArtMethod* resolved_method,
                         DispatchInfo dispatch_info,
                         InvokeType invoke_type,
-                        MethodReference target_method,
+                        MethodReference resolved_method_reference,
                         ClinitCheckRequirement clinit_check_requirement)
       : HInvoke(kInvokeStaticOrDirect,
                 allocator,
                 number_of_arguments,
-                // There is potentially one extra argument for the HCurrentMethod node, and
-                // potentially one other if the clinit check is explicit.
-                (NeedsCurrentMethodInput(dispatch_info.method_load_kind) ? 1u : 0u) +
+                // There is potentially one extra argument for the HCurrentMethod input,
+                // and one other if the clinit check is explicit. These can be removed later.
+                (NeedsCurrentMethodInput(dispatch_info) ? 1u : 0u) +
                     (clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u),
                 return_type,
                 dex_pc,
-                method_index,
+                method_reference,
                 resolved_method,
+                resolved_method_reference,
                 invoke_type),
-        target_method_(target_method),
         dispatch_info_(dispatch_info) {
     SetPackedField<ClinitCheckRequirementField>(clinit_check_requirement);
   }
 
   bool IsClonable() const override { return true; }
 
-  void SetDispatchInfo(const DispatchInfo& dispatch_info) {
+  void SetDispatchInfo(DispatchInfo dispatch_info) {
     bool had_current_method_input = HasCurrentMethodInput();
-    bool needs_current_method_input = NeedsCurrentMethodInput(dispatch_info.method_load_kind);
+    bool needs_current_method_input = NeedsCurrentMethodInput(dispatch_info);
 
     // Using the current method is the default and once we find a better
     // method load kind, we should not go back to using the current method.
     DCHECK(had_current_method_input || !needs_current_method_input);
 
     if (had_current_method_input && !needs_current_method_input) {
-      DCHECK_EQ(InputAt(GetSpecialInputIndex()), GetBlock()->GetGraph()->GetCurrentMethod());
-      RemoveInputAt(GetSpecialInputIndex());
+      DCHECK_EQ(InputAt(GetCurrentMethodIndex()), GetBlock()->GetGraph()->GetCurrentMethod());
+      RemoveInputAt(GetCurrentMethodIndex());
     }
     dispatch_info_ = dispatch_info;
   }
@@ -4614,14 +4902,6 @@
     return dispatch_info_;
   }
 
-  void AddSpecialInput(HInstruction* input) {
-    // We allow only one special input.
-    DCHECK(!IsStringInit() && !HasCurrentMethodInput());
-    DCHECK(InputCount() == GetSpecialInputIndex() ||
-           (InputCount() == GetSpecialInputIndex() + 1 && IsStaticWithExplicitClinitCheck()));
-    InsertInputAt(GetSpecialInputIndex(), input);
-  }
-
   using HInstruction::GetInputRecords;  // Keep the const version visible.
   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() override {
     ArrayRef<HUserRecord<HInstruction*>> input_records = HInvoke::GetInputRecords();
@@ -4642,7 +4922,7 @@
   }
 
   bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const override {
-    // We access the method via the dex cache so we can't do an implicit null check.
+    // We do not access the method via object reference, so we cannot do an implicit null check.
     // TODO: for intrinsics we can generate implicit null checks.
     return false;
   }
@@ -4651,35 +4931,13 @@
     return GetType() == DataType::Type::kReference && !IsStringInit();
   }
 
-  // Get the index of the special input, if any.
-  //
-  // If the invoke HasCurrentMethodInput(), the "special input" is the current
-  // method pointer; otherwise there may be one platform-specific special input,
-  // such as PC-relative addressing base.
-  uint32_t GetSpecialInputIndex() const { return GetNumberOfArguments(); }
-  bool HasSpecialInput() const { return GetNumberOfArguments() != InputCount(); }
-
   MethodLoadKind GetMethodLoadKind() const { return dispatch_info_.method_load_kind; }
   CodePtrLocation GetCodePtrLocation() const { return dispatch_info_.code_ptr_location; }
   bool IsRecursive() const { return GetMethodLoadKind() == MethodLoadKind::kRecursive; }
-  bool NeedsDexCacheOfDeclaringClass() const override;
   bool IsStringInit() const { return GetMethodLoadKind() == MethodLoadKind::kStringInit; }
   bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kJitDirectAddress; }
   bool HasPcRelativeMethodLoadKind() const {
-    return GetMethodLoadKind() == MethodLoadKind::kBootImageLinkTimePcRelative ||
-           GetMethodLoadKind() == MethodLoadKind::kBootImageRelRo ||
-           GetMethodLoadKind() == MethodLoadKind::kBssEntry;
-  }
-  bool HasCurrentMethodInput() const {
-    // This function can be called only after the invoke has been fully initialized by the builder.
-    if (NeedsCurrentMethodInput(GetMethodLoadKind())) {
-      DCHECK(InputAt(GetSpecialInputIndex())->IsCurrentMethod());
-      return true;
-    } else {
-      DCHECK(InputCount() == GetSpecialInputIndex() ||
-             !InputAt(GetSpecialInputIndex())->IsCurrentMethod());
-      return false;
-    }
+    return IsPcRelativeMethodLoadKind(GetMethodLoadKind());
   }
 
   QuickEntrypointEnum GetStringInitEntryPoint() const {
@@ -4703,8 +4961,58 @@
     return GetInvokeType() == kStatic;
   }
 
-  MethodReference GetTargetMethod() const {
-    return target_method_;
+  // Does this method load kind need the current method as an input?
+  static bool NeedsCurrentMethodInput(DispatchInfo dispatch_info) {
+    return dispatch_info.method_load_kind == MethodLoadKind::kRecursive ||
+           dispatch_info.method_load_kind == MethodLoadKind::kRuntimeCall ||
+           dispatch_info.code_ptr_location == CodePtrLocation::kCallCriticalNative;
+  }
+
+  // Get the index of the current method input.
+  size_t GetCurrentMethodIndex() const {
+    DCHECK(HasCurrentMethodInput());
+    return GetCurrentMethodIndexUnchecked();
+  }
+  size_t GetCurrentMethodIndexUnchecked() const {
+    return GetNumberOfArguments();
+  }
+
+  // Check if the method has a current method input.
+  bool HasCurrentMethodInput() const {
+    if (NeedsCurrentMethodInput(GetDispatchInfo())) {
+      DCHECK(InputAt(GetCurrentMethodIndexUnchecked()) == nullptr ||  // During argument setup.
+             InputAt(GetCurrentMethodIndexUnchecked())->IsCurrentMethod());
+      return true;
+    } else {
+      DCHECK(InputCount() == GetCurrentMethodIndexUnchecked() ||
+             InputAt(GetCurrentMethodIndexUnchecked()) == nullptr ||  // During argument setup.
+             !InputAt(GetCurrentMethodIndexUnchecked())->IsCurrentMethod());
+      return false;
+    }
+  }
+
+  // Get the index of the special input.
+  size_t GetSpecialInputIndex() const {
+    DCHECK(HasSpecialInput());
+    return GetSpecialInputIndexUnchecked();
+  }
+  size_t GetSpecialInputIndexUnchecked() const {
+    return GetNumberOfArguments() + (HasCurrentMethodInput() ? 1u : 0u);
+  }
+
+  // Check if the method has a special input.
+  bool HasSpecialInput() const {
+    size_t other_inputs =
+        GetSpecialInputIndexUnchecked() + (IsStaticWithExplicitClinitCheck() ? 1u : 0u);
+    size_t input_count = InputCount();
+    DCHECK_LE(input_count - other_inputs, 1u) << other_inputs << " " << input_count;
+    return other_inputs != input_count;
+  }
+
+  void AddSpecialInput(HInstruction* input) {
+    // We allow only one special input.
+    DCHECK(!HasSpecialInput());
+    InsertInputAt(GetSpecialInputIndexUnchecked(), input);
   }
 
   // Remove the HClinitCheck or the replacement HLoadClass (set as last input by
@@ -4734,11 +5042,6 @@
     return IsStatic() && (GetClinitCheckRequirement() == ClinitCheckRequirement::kImplicit);
   }
 
-  // Does this method load kind need the current method as an input?
-  static bool NeedsCurrentMethodInput(MethodLoadKind kind) {
-    return kind == MethodLoadKind::kRecursive || kind == MethodLoadKind::kRuntimeCall;
-  }
-
   DECLARE_INSTRUCTION(InvokeStaticOrDirect);
 
  protected:
@@ -4756,11 +5059,10 @@
                                                kFieldClinitCheckRequirement,
                                                kFieldClinitCheckRequirementSize>;
 
-  // Cached values of the resolved method, to avoid needing the mutator lock.
-  const MethodReference target_method_;
   DispatchInfo dispatch_info_;
 };
-std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs);
+std::ostream& operator<<(std::ostream& os, MethodLoadKind rhs);
+std::ostream& operator<<(std::ostream& os, CodePtrLocation rhs);
 std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckRequirement rhs);
 
 class HInvokeVirtual final : public HInvoke {
@@ -4769,8 +5071,9 @@
                  uint32_t number_of_arguments,
                  DataType::Type return_type,
                  uint32_t dex_pc,
-                 uint32_t dex_method_index,
+                 MethodReference method_reference,
                  ArtMethod* resolved_method,
+                 MethodReference resolved_method_reference,
                  uint32_t vtable_index)
       : HInvoke(kInvokeVirtual,
                 allocator,
@@ -4778,8 +5081,9 @@
                 0u,
                 return_type,
                 dex_pc,
-                dex_method_index,
+                method_reference,
                 resolved_method,
+                resolved_method_reference,
                 kVirtual),
         vtable_index_(vtable_index) {
   }
@@ -4808,10 +5112,7 @@
     }
   }
 
-  bool CanDoImplicitNullCheckOn(HInstruction* obj) const override {
-    // TODO: Add implicit null checks in intrinsics.
-    return (obj == InputAt(0)) && !IsIntrinsic();
-  }
+  bool CanDoImplicitNullCheckOn(HInstruction* obj) const override;
 
   uint32_t GetVTableIndex() const { return vtable_index_; }
 
@@ -4831,19 +5132,27 @@
                    uint32_t number_of_arguments,
                    DataType::Type return_type,
                    uint32_t dex_pc,
-                   uint32_t dex_method_index,
+                   MethodReference method_reference,
                    ArtMethod* resolved_method,
-                   uint32_t imt_index)
+                   MethodReference resolved_method_reference,
+                   uint32_t imt_index,
+                   MethodLoadKind load_kind)
       : HInvoke(kInvokeInterface,
                 allocator,
-                number_of_arguments,
+                number_of_arguments + (NeedsCurrentMethod(load_kind) ? 1 : 0),
                 0u,
                 return_type,
                 dex_pc,
-                dex_method_index,
+                method_reference,
                 resolved_method,
+                resolved_method_reference,
                 kInterface),
-        imt_index_(imt_index) {
+        imt_index_(imt_index),
+        hidden_argument_load_kind_(load_kind) {
+  }
+
+  static bool NeedsCurrentMethod(MethodLoadKind load_kind) {
+    return load_kind == MethodLoadKind::kRecursive;
   }
 
   bool IsClonable() const override { return true; }
@@ -4853,12 +5162,16 @@
     return (obj == InputAt(0)) && !IsIntrinsic();
   }
 
-  bool NeedsDexCacheOfDeclaringClass() const override {
-    // The assembly stub currently needs it.
-    return true;
+  size_t GetSpecialInputIndex() const {
+    return GetNumberOfArguments();
+  }
+
+  void AddSpecialInput(HInstruction* input) {
+    InsertInputAt(GetSpecialInputIndex(), input);
   }
 
   uint32_t GetImtIndex() const { return imt_index_; }
+  MethodLoadKind GetHiddenArgumentLoadKind() const { return hidden_argument_load_kind_; }
 
   DECLARE_INSTRUCTION(InvokeInterface);
 
@@ -4868,6 +5181,9 @@
  private:
   // Cached value of the resolved method, to avoid needing the mutator lock.
   const uint32_t imt_index_;
+
+  // How the hidden argument (the interface method) is being loaded.
+  const MethodLoadKind hidden_argument_load_kind_;
 };
 
 class HNeg final : public HUnaryOperation {
@@ -5542,8 +5858,6 @@
  public:
   HRor(DataType::Type result_type, HInstruction* value, HInstruction* distance)
       : HBinaryOperation(kRor, result_type, value, distance) {
-    DCHECK_EQ(result_type, DataType::Kind(value->GetType()));
-    DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType()));
   }
 
   template <typename T>
@@ -5797,6 +6111,23 @@
   const DexFile& GetDexFile() const { return dex_file_; }
   bool IsVolatile() const { return is_volatile_; }
 
+  bool Equals(const FieldInfo& other) const {
+    return field_ == other.field_ &&
+           field_offset_ == other.field_offset_ &&
+           field_type_ == other.field_type_ &&
+           is_volatile_ == other.is_volatile_ &&
+           index_ == other.index_ &&
+           declaring_class_def_index_ == other.declaring_class_def_index_ &&
+           &dex_file_ == &other.dex_file_;
+  }
+
+  std::ostream& Dump(std::ostream& os) const {
+    os << field_ << ", off: " << field_offset_ << ", type: " << field_type_
+       << ", volatile: " << std::boolalpha << is_volatile_ << ", index_: " << std::dec << index_
+       << ", declaring_class: " << declaring_class_def_index_ << ", dex: " << dex_file_;
+    return os;
+  }
+
  private:
   ArtField* const field_;
   const MemberOffset field_offset_;
@@ -5807,6 +6138,14 @@
   const DexFile& dex_file_;
 };
 
+inline bool operator==(const FieldInfo& a, const FieldInfo& b) {
+  return a.Equals(b);
+}
+
+inline std::ostream& operator<<(std::ostream& os, const FieldInfo& a) {
+  return a.Dump(os);
+}
+
 class HInstanceFieldGet final : public HExpression<1> {
  public:
   HInstanceFieldGet(HInstruction* value,
@@ -5848,7 +6187,8 @@
     return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
   }
 
-  const FieldInfo& GetFieldInfo() const { return field_info_; }
+  bool IsFieldAccess() const override { return true; }
+  const FieldInfo& GetFieldInfo() const override { return field_info_; }
   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
   DataType::Type GetFieldType() const { return field_info_.GetFieldType(); }
   bool IsVolatile() const { return field_info_.IsVolatile(); }
@@ -5869,6 +6209,96 @@
   const FieldInfo field_info_;
 };
 
+class HPredicatedInstanceFieldGet final : public HExpression<2> {
+ public:
+  HPredicatedInstanceFieldGet(HInstanceFieldGet* orig,
+                              HInstruction* target,
+                              HInstruction* default_val)
+      : HExpression(kPredicatedInstanceFieldGet,
+                    orig->GetFieldType(),
+                    orig->GetSideEffects(),
+                    orig->GetDexPc()),
+        field_info_(orig->GetFieldInfo()) {
+    // NB Default-val is at 0 so we can avoid doing a move.
+    SetRawInputAt(1, target);
+    SetRawInputAt(0, default_val);
+  }
+
+  HPredicatedInstanceFieldGet(HInstruction* value,
+                              ArtField* field,
+                              HInstruction* default_value,
+                              DataType::Type field_type,
+                              MemberOffset field_offset,
+                              bool is_volatile,
+                              uint32_t field_idx,
+                              uint16_t declaring_class_def_index,
+                              const DexFile& dex_file,
+                              uint32_t dex_pc)
+      : HExpression(kPredicatedInstanceFieldGet,
+                    field_type,
+                    SideEffects::FieldReadOfType(field_type, is_volatile),
+                    dex_pc),
+        field_info_(field,
+                    field_offset,
+                    field_type,
+                    is_volatile,
+                    field_idx,
+                    declaring_class_def_index,
+                    dex_file) {
+    SetRawInputAt(1, value);
+    SetRawInputAt(0, default_value);
+  }
+
+  bool IsClonable() const override {
+    return true;
+  }
+  bool CanBeMoved() const override {
+    return !IsVolatile();
+  }
+
+  HInstruction* GetDefaultValue() const {
+    return InputAt(0);
+  }
+  HInstruction* GetTarget() const {
+    return InputAt(1);
+  }
+
+  bool InstructionDataEquals(const HInstruction* other) const override {
+    const HPredicatedInstanceFieldGet* other_get = other->AsPredicatedInstanceFieldGet();
+    return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue() &&
+           GetDefaultValue() == other_get->GetDefaultValue();
+  }
+
+  bool CanDoImplicitNullCheckOn(HInstruction* obj) const override {
+    return (obj == InputAt(0)) && art::CanDoImplicitNullCheckOn(GetFieldOffset().Uint32Value());
+  }
+
+  size_t ComputeHashCode() const override {
+    return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
+  }
+
+  bool IsFieldAccess() const override { return true; }
+  const FieldInfo& GetFieldInfo() const override { return field_info_; }
+  MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
+  DataType::Type GetFieldType() const { return field_info_.GetFieldType(); }
+  bool IsVolatile() const { return field_info_.IsVolatile(); }
+
+  void SetType(DataType::Type new_type) {
+    DCHECK(DataType::IsIntegralType(GetType()));
+    DCHECK(DataType::IsIntegralType(new_type));
+    DCHECK_EQ(DataType::Size(GetType()), DataType::Size(new_type));
+    SetPackedField<TypeField>(new_type);
+  }
+
+  DECLARE_INSTRUCTION(PredicatedInstanceFieldGet);
+
+ protected:
+  DEFAULT_COPY_CONSTRUCTOR(PredicatedInstanceFieldGet);
+
+ private:
+  const FieldInfo field_info_;
+};
+
 class HInstanceFieldSet final : public HExpression<2> {
  public:
   HInstanceFieldSet(HInstruction* object,
@@ -5892,6 +6322,7 @@
                     declaring_class_def_index,
                     dex_file) {
     SetPackedFlag<kFlagValueCanBeNull>(true);
+    SetPackedFlag<kFlagIsPredicatedSet>(false);
     SetRawInputAt(0, object);
     SetRawInputAt(1, value);
   }
@@ -5902,13 +6333,16 @@
     return (obj == InputAt(0)) && art::CanDoImplicitNullCheckOn(GetFieldOffset().Uint32Value());
   }
 
-  const FieldInfo& GetFieldInfo() const { return field_info_; }
+  bool IsFieldAccess() const override { return true; }
+  const FieldInfo& GetFieldInfo() const override { return field_info_; }
   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
   DataType::Type GetFieldType() const { return field_info_.GetFieldType(); }
   bool IsVolatile() const { return field_info_.IsVolatile(); }
   HInstruction* GetValue() const { return InputAt(1); }
   bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); }
   void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); }
+  bool GetIsPredicatedSet() const { return GetPackedFlag<kFlagIsPredicatedSet>(); }
+  void SetIsPredicatedSet(bool value = true) { SetPackedFlag<kFlagIsPredicatedSet>(value); }
 
   DECLARE_INSTRUCTION(InstanceFieldSet);
 
@@ -5917,7 +6351,8 @@
 
  private:
   static constexpr size_t kFlagValueCanBeNull = kNumberOfGenericPackedBits;
-  static constexpr size_t kNumberOfInstanceFieldSetPackedBits = kFlagValueCanBeNull + 1;
+  static constexpr size_t kFlagIsPredicatedSet = kFlagValueCanBeNull + 1;
+  static constexpr size_t kNumberOfInstanceFieldSetPackedBits = kFlagIsPredicatedSet + 1;
   static_assert(kNumberOfInstanceFieldSetPackedBits <= kMaxNumberOfPackedBits,
                 "Too many packed fields.");
 
@@ -6284,6 +6719,21 @@
     // Used for classes outside boot image referenced by AOT-compiled app and boot image code.
     kBssEntry,
 
+    // Load from an entry for public class in the .bss section using a PC-relative load.
+    // Used for classes that were unresolved during AOT-compilation outside the literal
+    // package of the compiling class. Such classes are accessible only if they are public
+    // and the .bss entry shall therefore be filled only if the resolved class is public.
+    kBssEntryPublic,
+
+    // Load from an entry for package class in the .bss section using a PC-relative load.
+    // Used for classes that were unresolved during AOT-compilation but within the literal
+    // package of the compiling class. Such classes are accessible if they are public or
+    // in the same package which, given the literal package match, requires only matching
+    // defining class loader and the .bss entry shall therefore be filled only if at least
+    // one of those conditions holds. Note that all code in an oat file belongs to classes
+    // with the same defining class loader.
+    kBssEntryPackage,
+
     // Use a known boot image Class* address, embedded in the code by the codegen.
     // Used for boot image classes referenced by apps in JIT-compiled code.
     kJitBootImageAddress,
@@ -6336,7 +6786,9 @@
   bool HasPcRelativeLoadKind() const {
     return GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
            GetLoadKind() == LoadKind::kBootImageRelRo ||
-           GetLoadKind() == LoadKind::kBssEntry;
+           GetLoadKind() == LoadKind::kBssEntry ||
+           GetLoadKind() == LoadKind::kBssEntryPublic ||
+           GetLoadKind() == LoadKind::kBssEntryPackage;
   }
 
   bool CanBeMoved() const override { return true; }
@@ -6352,9 +6804,6 @@
   }
 
   void SetMustGenerateClinitCheck(bool generate_clinit_check) {
-    // The entrypoint the code generator is going to call does not do
-    // clinit of the class.
-    DCHECK(!NeedsAccessCheck());
     SetPackedFlag<kFlagGenerateClInitCheck>(generate_clinit_check);
   }
 
@@ -6384,7 +6833,7 @@
   }
 
   // Loaded class RTI is marked as valid by RTP if the klass_ is admissible.
-  void SetValidLoadedClassRTI() REQUIRES_SHARED(Locks::mutator_lock_) {
+  void SetValidLoadedClassRTI() {
     DCHECK(klass_ != nullptr);
     SetPackedFlag<kFlagValidLoadedClassRTI>(true);
   }
@@ -6392,10 +6841,6 @@
   dex::TypeIndex GetTypeIndex() const { return type_index_; }
   const DexFile& GetDexFile() const { return dex_file_; }
 
-  bool NeedsDexCacheOfDeclaringClass() const override {
-    return GetLoadKind() == LoadKind::kRuntimeCall;
-  }
-
   static SideEffects SideEffectsForArchRuntimeCalls() {
     return SideEffects::CanTriggerGC();
   }
@@ -6407,9 +6852,14 @@
 
   bool MustResolveTypeOnSlowPath() const {
     // Check that this instruction has a slow path.
-    DCHECK(GetLoadKind() != LoadKind::kRuntimeCall);  // kRuntimeCall calls on main path.
-    DCHECK(GetLoadKind() == LoadKind::kBssEntry || MustGenerateClinitCheck());
-    return GetLoadKind() == LoadKind::kBssEntry;
+    LoadKind load_kind = GetLoadKind();
+    DCHECK(load_kind != LoadKind::kRuntimeCall);  // kRuntimeCall calls on main path.
+    bool must_resolve_type_on_slow_path =
+       load_kind == LoadKind::kBssEntry ||
+       load_kind == LoadKind::kBssEntryPublic ||
+       load_kind == LoadKind::kBssEntryPackage;
+    DCHECK(must_resolve_type_on_slow_path || MustGenerateClinitCheck());
+    return must_resolve_type_on_slow_path;
   }
 
   void MarkInBootImage() {
@@ -6451,6 +6901,8 @@
     return load_kind == LoadKind::kReferrersClass ||
         load_kind == LoadKind::kBootImageLinkTimePcRelative ||
         load_kind == LoadKind::kBssEntry ||
+        load_kind == LoadKind::kBssEntryPublic ||
+        load_kind == LoadKind::kBssEntryPackage ||
         load_kind == LoadKind::kRuntimeCall;
   }
 
@@ -6458,14 +6910,14 @@
 
   // The special input is the HCurrentMethod for kRuntimeCall or kReferrersClass.
   // For other load kinds it's empty or possibly some architecture-specific instruction
-  // for PC-relative loads, i.e. kBssEntry or kBootImageLinkTimePcRelative.
+  // for PC-relative loads, i.e. kBssEntry* or kBootImageLinkTimePcRelative.
   HUserRecord<HInstruction*> special_input_;
 
   // A type index and dex file where the class can be accessed. The dex file can be:
   // - The compiling method's dex file if the class is defined there too.
   // - The compiling method's dex file if the class is referenced there.
   // - The dex file where the class is defined. When the load kind can only be
-  //   kBssEntry or kRuntimeCall, we cannot emit code for this `HLoadClass`.
+  //   kBssEntry* or kRuntimeCall, we cannot emit code for this `HLoadClass`.
   const dex::TypeIndex type_index_;
   const DexFile& dex_file_;
 
@@ -6494,6 +6946,8 @@
   DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
          GetLoadKind() == LoadKind::kBootImageRelRo ||
          GetLoadKind() == LoadKind::kBssEntry ||
+         GetLoadKind() == LoadKind::kBssEntryPublic ||
+         GetLoadKind() == LoadKind::kBssEntryPackage ||
          GetLoadKind() == LoadKind::kJitBootImageAddress) << GetLoadKind();
   DCHECK(special_input_.GetInstruction() == nullptr);
   special_input_ = HUserRecord<HInstruction*>(special_input);
@@ -6593,10 +7047,6 @@
     return true;
   }
 
-  bool NeedsDexCacheOfDeclaringClass() const override {
-    return GetLoadKind() == LoadKind::kRuntimeCall;
-  }
-
   bool CanBeNull() const override { return false; }
   bool CanThrow() const override { return NeedsEnvironment(); }
 
@@ -6833,7 +7283,8 @@
     return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
   }
 
-  const FieldInfo& GetFieldInfo() const { return field_info_; }
+  bool IsFieldAccess() const override { return true; }
+  const FieldInfo& GetFieldInfo() const override { return field_info_; }
   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
   DataType::Type GetFieldType() const { return field_info_.GetFieldType(); }
   bool IsVolatile() const { return field_info_.IsVolatile(); }
@@ -6882,7 +7333,8 @@
   }
 
   bool IsClonable() const override { return true; }
-  const FieldInfo& GetFieldInfo() const { return field_info_; }
+  bool IsFieldAccess() const override { return true; }
+  const FieldInfo& GetFieldInfo() const override { return field_info_; }
   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
   DataType::Type GetFieldType() const { return field_info_.GetFieldType(); }
   bool IsVolatile() const { return field_info_.IsVolatile(); }
@@ -7146,7 +7598,7 @@
  * Implementation strategies for the code generator of a HInstanceOf
  * or `HCheckCast`.
  */
-enum class TypeCheckKind {
+enum class TypeCheckKind {  // private marker to avoid generate-operator-out.py from processing.
   kUnresolvedCheck,       // Check against an unresolved type.
   kExactCheck,            // Can do a single class compare.
   kClassHierarchyCheck,   // Can just walk the super class chain.
@@ -7244,7 +7696,7 @@
   }
 
   // Target class RTI is marked as valid by RTP if the klass_ is admissible.
-  void SetValidTargetClassRTI() REQUIRES_SHARED(Locks::mutator_lock_) {
+  void SetValidTargetClassRTI() {
     DCHECK(klass_ != nullptr);
     SetPackedFlag<kFlagValidTargetClassRTI>(true);
   }
@@ -7420,7 +7872,7 @@
   kNTStoreStore,
   kLastBarrierKind = kNTStoreStore
 };
-std::ostream& operator<<(std::ostream& os, const MemBarrierKind& kind);
+std::ostream& operator<<(std::ostream& os, MemBarrierKind kind);
 
 class HMemoryBarrier final : public HExpression<0> {
  public:
@@ -7801,7 +8253,7 @@
         DCHECK(!destination.OverlapsWith(move.GetDestination()))
             << "Overlapped destination for two moves in a parallel move: "
             << move.GetSource() << " ==> " << move.GetDestination() << " and "
-            << source << " ==> " << destination;
+            << source << " ==> " << destination << " for " << SafePrint(instruction);
       }
     }
     moves_.emplace_back(source, destination, type, instruction);
@@ -8121,10 +8573,18 @@
   return instruction;
 }
 
+inline bool IsAddOrSub(const HInstruction* instruction) {
+  return instruction->IsAdd() || instruction->IsSub();
+}
+
 void RemoveEnvironmentUses(HInstruction* instruction);
 bool HasEnvironmentUsedByOthers(HInstruction* instruction);
 void ResetEnvironmentInputRecords(HInstruction* instruction);
 
+// Detects an instruction that is >= 0. As long as the value is carried by
+// a single instruction, arithmetic wrap-around cannot occur.
+bool IsGEZero(HInstruction* instruction);
+
 }  // namespace art
 
 #endif  // ART_COMPILER_OPTIMIZING_NODES_H_
diff --git a/compiler/optimizing/nodes_shared.cc b/compiler/optimizing/nodes_shared.cc
index 2f971b9..eca97d7 100644
--- a/compiler/optimizing/nodes_shared.cc
+++ b/compiler/optimizing/nodes_shared.cc
@@ -21,7 +21,7 @@
 
 #include "nodes_shared.h"
 
-#include "common_arm64.h"
+#include "instruction_simplifier_shared.h"
 
 namespace art {
 
diff --git a/compiler/optimizing/nodes_test.cc b/compiler/optimizing/nodes_test.cc
index 9bfd250..34f0e9b 100644
--- a/compiler/optimizing/nodes_test.cc
+++ b/compiler/optimizing/nodes_test.cc
@@ -26,6 +26,118 @@
 class NodeTest : public OptimizingUnitTest {};
 
 /**
+ * Test that we can clear loop and dominator information in either order.
+ * Code is:
+ * while (true) {
+ *   if (foobar) { break; }
+ *   if (baz) { xyz; } else { abc; }
+ * }
+ * dosomething();
+ */
+TEST_F(NodeTest, ClearLoopThenDominanceInformation) {
+  CreateGraph();
+  AdjacencyListGraph alg(graph_,
+                         GetAllocator(),
+                         "entry",
+                         "exit",
+                         {{"entry", "loop_pre_header"},
+
+                          {"loop_pre_header", "loop_header"},
+                          {"loop_header", "critical_break"},
+                          {"loop_header", "loop_body"},
+                          {"loop_body", "loop_if_left"},
+                          {"loop_body", "loop_if_right"},
+                          {"loop_if_left", "loop_merge"},
+                          {"loop_if_right", "loop_merge"},
+                          {"loop_merge", "loop_header"},
+
+                          {"critical_break", "breturn"},
+                          {"breturn", "exit"}});
+  graph_->ClearDominanceInformation();
+  graph_->BuildDominatorTree();
+
+  // Test
+  EXPECT_TRUE(
+      std::all_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
+        return b == graph_->GetEntryBlock() || b == nullptr || b->GetDominator() != nullptr;
+      }));
+  EXPECT_TRUE(
+      std::any_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
+        return b != nullptr && b->GetLoopInformation() != nullptr;
+      }));
+
+  // Clear
+  graph_->ClearLoopInformation();
+  graph_->ClearDominanceInformation();
+
+  // Test
+  EXPECT_TRUE(
+      std::none_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
+        return b != nullptr && b->GetDominator() != nullptr;
+      }));
+  EXPECT_TRUE(
+      std::all_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
+        return b == nullptr || b->GetLoopInformation() == nullptr;
+      }));
+}
+
+/**
+ * Test that we can clear loop and dominator information in either order.
+ * Code is:
+ * while (true) {
+ *   if (foobar) { break; }
+ *   if (baz) { xyz; } else { abc; }
+ * }
+ * dosomething();
+ */
+TEST_F(NodeTest, ClearDominanceThenLoopInformation) {
+  CreateGraph();
+  AdjacencyListGraph alg(graph_,
+                         GetAllocator(),
+                         "entry",
+                         "exit",
+                         {{"entry", "loop_pre_header"},
+
+                          {"loop_pre_header", "loop_header"},
+                          {"loop_header", "critical_break"},
+                          {"loop_header", "loop_body"},
+                          {"loop_body", "loop_if_left"},
+                          {"loop_body", "loop_if_right"},
+                          {"loop_if_left", "loop_merge"},
+                          {"loop_if_right", "loop_merge"},
+                          {"loop_merge", "loop_header"},
+
+                          {"critical_break", "breturn"},
+                          {"breturn", "exit"}});
+  graph_->ClearDominanceInformation();
+  graph_->BuildDominatorTree();
+
+  // Test
+  EXPECT_TRUE(
+      std::all_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
+        return b == graph_->GetEntryBlock() || b == nullptr || b->GetDominator() != nullptr;
+      }));
+  EXPECT_TRUE(
+      std::any_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
+        return b != nullptr && b->GetLoopInformation() != nullptr;
+      }));
+
+  // Clear
+  graph_->ClearDominanceInformation();
+  graph_->ClearLoopInformation();
+
+  // Test
+  EXPECT_TRUE(
+      std::none_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
+        return b != nullptr && b->GetDominator() != nullptr;
+      }));
+  EXPECT_TRUE(
+      std::all_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
+        return b == nullptr || b->GetLoopInformation() == nullptr;
+      }));
+}
+
+/**
  * Test that removing instruction from the graph removes itself from user lists
  * and environment lists.
  */
diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h
index e817048..a2cd86d 100644
--- a/compiler/optimizing/nodes_vector.h
+++ b/compiler/optimizing/nodes_vector.h
@@ -87,9 +87,73 @@
                                       kArenaAllocVectorNode),
         vector_length_(vector_length) {
     SetPackedField<PackedTypeField>(packed_type);
+    // By default vector operations are not predicated.
+    SetPackedField<PredicationKindField>(PredicationKind::kNotPredicated);
     DCHECK_LT(1u, vector_length);
   }
 
+  // Predicated instructions execute a corresponding operation only on vector elements which are
+  // active (governing predicate is true for that element); the following modes determine what
+  // is happening with inactive elements.
+  //
+  // See HVecPredSetOperation.
+  enum class PredicationKind {
+    kNotPredicated,        // Instruction doesn't take any predicate as an input.
+    kZeroingForm,          // Inactive elements are reset to zero.
+    kMergingForm,          // Inactive elements keep their value.
+    kLast = kMergingForm,
+  };
+
+  PredicationKind GetPredicationKind() const { return GetPackedField<PredicationKindField>(); }
+
+  // Returns whether the vector operation must be predicated in predicated SIMD mode
+  // (see CodeGenerator::SupportsPredicatedSIMD). The method reflects semantics of
+  // the instruction class rather than the state of a particular instruction instance.
+  //
+  // This property is introduced for robustness purpose - to maintain and check the invariant:
+  // all instructions of the same vector operation class must be either all predicated or all
+  // not predicated (depending on the predicated SIMD support) in a correct graph.
+  virtual bool MustBePredicatedInPredicatedSIMDMode() {
+    return true;
+  }
+
+  bool IsPredicated() const {
+    return GetPredicationKind() != PredicationKind::kNotPredicated;
+  }
+
+  // See HVecPredSetOperation.
+  void SetGoverningPredicate(HInstruction* input, PredicationKind pred_kind) {
+    DCHECK(!IsPredicated());
+    DCHECK(input->IsVecPredSetOperation());
+    AddInput(input);
+    SetPackedField<PredicationKindField>(pred_kind);
+    DCHECK(IsPredicated());
+  }
+
+  void SetMergingGoverningPredicate(HInstruction* input) {
+    SetGoverningPredicate(input, PredicationKind::kMergingForm);
+  }
+  void SetZeroingGoverningPredicate(HInstruction* input) {
+    SetGoverningPredicate(input, PredicationKind::kZeroingForm);
+  }
+
+  // See HVecPredSetOperation.
+  HVecPredSetOperation* GetGoverningPredicate() const {
+    DCHECK(IsPredicated());
+    HInstruction* pred_input = InputAt(InputCount() - 1);
+    DCHECK(pred_input->IsVecPredSetOperation());
+    return pred_input->AsVecPredSetOperation();
+  }
+
+  // Returns whether two vector operations are predicated by the same vector predicate
+  // with the same predication type.
+  static bool HaveSamePredicate(HVecOperation* instr0, HVecOperation* instr1) {
+    HVecPredSetOperation* instr0_predicate = instr0->GetGoverningPredicate();
+    HVecOperation::PredicationKind instr0_predicate_kind = instr0->GetPredicationKind();
+    return instr1->GetGoverningPredicate() == instr0_predicate &&
+           instr1->GetPredicationKind() == instr0_predicate_kind;
+  }
+
   // Returns the number of elements packed in a vector.
   size_t GetVectorLength() const {
     return vector_length_;
@@ -181,12 +245,16 @@
 
  protected:
   // Additional packed bits.
-  static constexpr size_t kFieldPackedType = HInstruction::kNumberOfGenericPackedBits;
+  static constexpr size_t kPredicationKind = HInstruction::kNumberOfGenericPackedBits;
+  static constexpr size_t kPredicationKindSize =
+      MinimumBitsToStore(static_cast<size_t>(PredicationKind::kLast));
+  static constexpr size_t kFieldPackedType = kPredicationKind + kPredicationKindSize;
   static constexpr size_t kFieldPackedTypeSize =
       MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
   static constexpr size_t kNumberOfVectorOpPackedBits = kFieldPackedType + kFieldPackedTypeSize;
   static_assert(kNumberOfVectorOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
   using PackedTypeField = BitField<DataType::Type, kFieldPackedType, kFieldPackedTypeSize>;
+  using PredicationKindField = BitField<PredicationKind, kPredicationKind, kPredicationKindSize>;
 
   DEFAULT_COPY_CONSTRUCTOR(VecOperation);
 
@@ -1163,6 +1231,237 @@
   DEFAULT_COPY_CONSTRUCTOR(VecStore)
 };
 
+//
+// 'Predicate-setting' instructions.
+//
+
+// An abstract class for instructions for which the output value is a vector predicate -
+// a special kind of vector value:
+//
+//    viz. [ p1, .. , pn ], where p_i is from { 0, 1 }.
+//
+// A VecOperation OP executes the same operation (e.g. ADD) on multiple elements of the vector.
+// It can be either unpredicated (operation is done on ALL of the elements) or predicated (only
+// on SOME elements, determined by a special extra input - vector predicate).
+// Implementations can vary depending on the ISA; the general idea is that for each element of the
+// regular vector a vector predicate has a corresponding element with either 0 or 1.
+// The value determines whether a vector element will be involved in OP calculations or not
+// (active or inactive). A vector predicate is referred as governing one if it is used to
+// control the execution of a predicated instruction.
+//
+// Note: vector predicate value type is introduced alongside existing vectors of booleans and
+// vectors of bytes to reflect their special semantics.
+//
+// TODO: we could introduce SIMD types in HIR.
+class HVecPredSetOperation : public HVecOperation {
+ public:
+  // A vector predicate-setting operation looks like a Int64 location.
+  // TODO: we could introduce vector types in HIR.
+  static constexpr DataType::Type kSIMDPredType = DataType::Type::kInt64;
+
+  HVecPredSetOperation(InstructionKind kind,
+                       ArenaAllocator* allocator,
+                       DataType::Type packed_type,
+                       SideEffects side_effects,
+                       size_t number_of_inputs,
+                       size_t vector_length,
+                       uint32_t dex_pc)
+      : HVecOperation(kind,
+                      allocator,
+                      packed_type,
+                      side_effects,
+                      number_of_inputs,
+                      vector_length,
+                      dex_pc) {
+    // Overrides the kSIMDType set by the VecOperation constructor.
+    SetPackedField<TypeField>(kSIMDPredType);
+  }
+
+  bool CanBeMoved() const override { return true; }
+
+  DECLARE_ABSTRACT_INSTRUCTION(VecPredSetOperation);
+
+ protected:
+  DEFAULT_COPY_CONSTRUCTOR(VecPredSetOperation);
+};
+
+// Sets all the vector predicate elements as active or inactive.
+//
+// viz. [ p1, .. , pn ]  = [ val, .. , val ] where val is from { 1, 0 }.
+class HVecPredSetAll final : public HVecPredSetOperation {
+ public:
+  HVecPredSetAll(ArenaAllocator* allocator,
+                 HInstruction* input,
+                 DataType::Type packed_type,
+                 size_t vector_length,
+                 uint32_t dex_pc) :
+      HVecPredSetOperation(kVecPredSetAll,
+                           allocator,
+                           packed_type,
+                           SideEffects::None(),
+                           /* number_of_inputs= */ 1,
+                           vector_length,
+                           dex_pc) {
+    DCHECK(input->IsIntConstant());
+    SetRawInputAt(0, input);
+    MarkEmittedAtUseSite();
+  }
+
+  // Having governing predicate doesn't make sense for set all TRUE/FALSE instruction.
+  bool MustBePredicatedInPredicatedSIMDMode() override { return false; }
+
+  bool IsSetTrue() const { return InputAt(0)->AsIntConstant()->IsTrue(); }
+
+  // Vector predicates are not kept alive across vector loop boundaries.
+  bool CanBeMoved() const override { return false; }
+
+  DECLARE_INSTRUCTION(VecPredSetAll);
+
+ protected:
+  DEFAULT_COPY_CONSTRUCTOR(VecPredSetAll);
+};
+
+//
+// Arm64 SVE-specific instructions.
+//
+// Classes of instructions which are specific to Arm64 SVE (though could be adopted
+// by other targets, possibly being lowered to a number of ISA instructions) and
+// implement SIMD loop predicated execution idiom.
+//
+
+// Takes two scalar values x and y, creates a vector S: s(n) = x + n, compares (OP) each s(n)
+// with y and set the corresponding element of the predicate register to the result of the
+// comparison.
+//
+// viz. [ p1, .. , pn ]  = [ x OP y , (x + 1) OP y, .. , (x + n) OP y ] where OP is CondKind
+// condition.
+class HVecPredWhile final : public HVecPredSetOperation {
+ public:
+  enum class CondKind {
+    kLE,   // signed less than or equal.
+    kLO,   // unsigned lower.
+    kLS,   // unsigned lower or same.
+    kLT,   // signed less.
+    kLast = kLT,
+  };
+
+  HVecPredWhile(ArenaAllocator* allocator,
+                HInstruction* left,
+                HInstruction* right,
+                CondKind cond,
+                DataType::Type packed_type,
+                size_t vector_length,
+                uint32_t dex_pc) :
+      HVecPredSetOperation(kVecPredWhile,
+                           allocator,
+                           packed_type,
+                           SideEffects::None(),
+                           /* number_of_inputs= */ 2,
+                           vector_length,
+                           dex_pc) {
+    DCHECK(!left->IsVecOperation());
+    DCHECK(!left->IsVecPredSetOperation());
+    DCHECK(!right->IsVecOperation());
+    DCHECK(!right->IsVecPredSetOperation());
+    DCHECK(DataType::IsIntegralType(left->GetType()));
+    DCHECK(DataType::IsIntegralType(right->GetType()));
+    SetRawInputAt(0, left);
+    SetRawInputAt(1, right);
+    SetPackedField<CondKindField>(cond);
+  }
+
+  // This is a special loop control instruction which must not be predicated.
+  bool MustBePredicatedInPredicatedSIMDMode() override { return false; }
+
+  CondKind GetCondKind() const {
+    return GetPackedField<CondKindField>();
+  }
+
+  DECLARE_INSTRUCTION(VecPredWhile);
+
+ protected:
+  // Additional packed bits.
+  static constexpr size_t kCondKind = HVecOperation::kNumberOfVectorOpPackedBits;
+  static constexpr size_t kCondKindSize =
+      MinimumBitsToStore(static_cast<size_t>(CondKind::kLast));
+  static constexpr size_t kNumberOfVecPredConditionPackedBits = kCondKind + kCondKindSize;
+  static_assert(kNumberOfVecPredConditionPackedBits <= kMaxNumberOfPackedBits,
+                "Too many packed fields.");
+  using CondKindField = BitField<CondKind, kCondKind, kCondKindSize>;
+
+  DEFAULT_COPY_CONSTRUCTOR(VecPredWhile);
+};
+
+// Evaluates the predicate condition (PCondKind) for a vector predicate; outputs
+// a scalar boolean value result.
+//
+// Note: as VecPredCondition can be also predicated, only active elements (determined by the
+// instruction's governing predicate) of the input vector predicate are used for condition
+// evaluation.
+//
+// Note: this instruction is currently used as a workaround for the fact that IR instructions
+// can't have more than one output.
+class HVecPredCondition final : public HVecOperation {
+ public:
+  // To get more info on the condition kinds please see "2.2 Process state, PSTATE" section of
+  // "ARM Architecture Reference Manual Supplement. The Scalable Vector Extension (SVE),
+  // for ARMv8-A".
+  enum class PCondKind {
+    kNone,    // No active elements were TRUE.
+    kAny,     // An active element was TRUE.
+    kNLast,   // The last active element was not TRUE.
+    kLast,    // The last active element was TRUE.
+    kFirst,   // The first active element was TRUE.
+    kNFirst,  // The first active element was not TRUE.
+    kPMore,   // An active element was TRUE but not the last active element.
+    kPLast,   // The last active element was TRUE or no active elements were TRUE.
+    kEnumLast = kPLast
+  };
+
+  HVecPredCondition(ArenaAllocator* allocator,
+                    HInstruction* input,
+                    PCondKind pred_cond,
+                    DataType::Type packed_type,
+                    size_t vector_length,
+                    uint32_t dex_pc)
+      : HVecOperation(kVecPredCondition,
+                      allocator,
+                      packed_type,
+                      SideEffects::None(),
+                      /* number_of_inputs */ 1,
+                      vector_length,
+                      dex_pc) {
+    DCHECK(input->IsVecPredSetOperation());
+    SetRawInputAt(0, input);
+    // Overrides the kSIMDType set by the VecOperation constructor.
+    SetPackedField<TypeField>(DataType::Type::kBool);
+    SetPackedField<CondKindField>(pred_cond);
+  }
+
+  // This instruction is currently used only as a special loop control instruction
+  // which must not be predicated.
+  // TODO: Remove the constraint.
+  bool MustBePredicatedInPredicatedSIMDMode() override { return false; }
+
+  PCondKind GetPCondKind() const {
+    return GetPackedField<CondKindField>();
+  }
+
+  DECLARE_INSTRUCTION(VecPredCondition);
+
+ protected:
+  // Additional packed bits.
+  static constexpr size_t kCondKind = HVecOperation::kNumberOfVectorOpPackedBits;
+  static constexpr size_t kCondKindSize =
+      MinimumBitsToStore(static_cast<size_t>(PCondKind::kEnumLast));
+  static constexpr size_t kNumberOfVecPredConditionPackedBits = kCondKind + kCondKindSize;
+  static_assert(kNumberOfVecPredConditionPackedBits <= kMaxNumberOfPackedBits,
+                "Too many packed fields.");
+  using CondKindField = BitField<PCondKind, kCondKind, kCondKindSize>;
+
+  DEFAULT_COPY_CONSTRUCTOR(VecPredCondition);
+};
+
 }  // namespace art
 
 #endif  // ART_COMPILER_OPTIMIZING_NODES_VECTOR_H_
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index 7024660..2cac38b 100644
--- a/compiler/optimizing/optimization.cc
+++ b/compiler/optimizing/optimization.cc
@@ -17,6 +17,7 @@
 #include "optimization.h"
 
 #ifdef ART_ENABLE_CODEGEN_arm
+#include "critical_native_abi_fixup_arm.h"
 #include "instruction_simplifier_arm.h"
 #endif
 #ifdef ART_ENABLE_CODEGEN_arm64
@@ -48,7 +49,6 @@
 #include "instruction_simplifier.h"
 #include "intrinsics.h"
 #include "licm.h"
-#include "load_store_analysis.h"
 #include "load_store_elimination.h"
 #include "loop_optimization.h"
 #include "scheduler.h"
@@ -66,8 +66,6 @@
       return SideEffectsAnalysis::kSideEffectsAnalysisPassName;
     case OptimizationPass::kInductionVarAnalysis:
       return HInductionVarAnalysis::kInductionPassName;
-    case OptimizationPass::kLoadStoreAnalysis:
-      return LoadStoreAnalysis::kLoadStoreAnalysisPassName;
     case OptimizationPass::kGlobalValueNumbering:
       return GVNOptimization::kGlobalValueNumberingPassName;
     case OptimizationPass::kInvariantCodeMotion:
@@ -86,6 +84,7 @@
       return HInliner::kInlinerPassName;
     case OptimizationPass::kSelectGenerator:
       return HSelectGenerator::kSelectGeneratorPassName;
+    case OptimizationPass::kAggressiveInstructionSimplifier:
     case OptimizationPass::kInstructionSimplifier:
       return InstructionSimplifier::kInstructionSimplifierPassName;
     case OptimizationPass::kCHAGuardOptimization:
@@ -99,6 +98,8 @@
 #ifdef ART_ENABLE_CODEGEN_arm
     case OptimizationPass::kInstructionSimplifierArm:
       return arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName;
+    case OptimizationPass::kCriticalNativeAbiFixupArm:
+      return arm::CriticalNativeAbiFixupArm::kCriticalNativeAbiFixupArmPassName;
 #endif
 #ifdef ART_ENABLE_CODEGEN_arm64
     case OptimizationPass::kInstructionSimplifierArm64:
@@ -138,7 +139,6 @@
   X(OptimizationPass::kInliner);
   X(OptimizationPass::kInstructionSimplifier);
   X(OptimizationPass::kInvariantCodeMotion);
-  X(OptimizationPass::kLoadStoreAnalysis);
   X(OptimizationPass::kLoadStoreElimination);
   X(OptimizationPass::kLoopOptimization);
   X(OptimizationPass::kScheduling);
@@ -146,6 +146,7 @@
   X(OptimizationPass::kSideEffectsAnalysis);
 #ifdef ART_ENABLE_CODEGEN_arm
   X(OptimizationPass::kInstructionSimplifierArm);
+  X(OptimizationPass::kCriticalNativeAbiFixupArm);
 #endif
 #ifdef ART_ENABLE_CODEGEN_arm64
   X(OptimizationPass::kInstructionSimplifierArm64);
@@ -167,8 +168,7 @@
     HGraph* graph,
     OptimizingCompilerStats* stats,
     CodeGenerator* codegen,
-    const DexCompilationUnit& dex_compilation_unit,
-    VariableSizedHandleScope* handles) {
+    const DexCompilationUnit& dex_compilation_unit) {
   ArenaVector<HOptimization*> optimizations(allocator->Adapter());
 
   // Some optimizations require SideEffectsAnalysis or HInductionVarAnalysis
@@ -176,7 +176,6 @@
   // name list or fails fatally if no such analysis can be found.
   SideEffectsAnalysis* most_recent_side_effects = nullptr;
   HInductionVarAnalysis* most_recent_induction = nullptr;
-  LoadStoreAnalysis* most_recent_lsa = nullptr;
 
   // Loop over the requested optimizations.
   for (size_t i = 0; i < length; i++) {
@@ -197,9 +196,6 @@
       case OptimizationPass::kInductionVarAnalysis:
         opt = most_recent_induction = new (allocator) HInductionVarAnalysis(graph, pass_name);
         break;
-      case OptimizationPass::kLoadStoreAnalysis:
-        opt = most_recent_lsa = new (allocator) LoadStoreAnalysis(graph, pass_name);
-        break;
       //
       // Passes that need prior analysis.
       //
@@ -214,18 +210,13 @@
       case OptimizationPass::kLoopOptimization:
         CHECK(most_recent_induction != nullptr);
         opt = new (allocator) HLoopOptimization(
-            graph, &codegen->GetCompilerOptions(), most_recent_induction, stats, pass_name);
+            graph, *codegen, most_recent_induction, stats, pass_name);
         break;
       case OptimizationPass::kBoundsCheckElimination:
         CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
         opt = new (allocator) BoundsCheckElimination(
             graph, *most_recent_side_effects, most_recent_induction, pass_name);
         break;
-      case OptimizationPass::kLoadStoreElimination:
-        CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
-        opt = new (allocator) LoadStoreElimination(
-            graph, *most_recent_side_effects, *most_recent_lsa, stats, pass_name);
-        break;
       //
       // Regular passes.
       //
@@ -243,7 +234,6 @@
                                        codegen,
                                        dex_compilation_unit,    // outer_compilation_unit
                                        dex_compilation_unit,    // outermost_compilation_unit
-                                       handles,
                                        stats,
                                        accessor.RegistersSize(),
                                        /* total_number_of_instructions= */ 0,
@@ -253,11 +243,18 @@
         break;
       }
       case OptimizationPass::kSelectGenerator:
-        opt = new (allocator) HSelectGenerator(graph, handles, stats, pass_name);
+        opt = new (allocator) HSelectGenerator(graph, stats, pass_name);
         break;
       case OptimizationPass::kInstructionSimplifier:
         opt = new (allocator) InstructionSimplifier(graph, codegen, stats, pass_name);
         break;
+      case OptimizationPass::kAggressiveInstructionSimplifier:
+        opt = new (allocator) InstructionSimplifier(graph,
+                                                    codegen,
+                                                    stats,
+                                                    pass_name,
+                                                    /* use_all_optimizations_ = */ true);
+        break;
       case OptimizationPass::kCHAGuardOptimization:
         opt = new (allocator) CHAGuardOptimization(graph, pass_name);
         break;
@@ -267,6 +264,9 @@
       case OptimizationPass::kConstructorFenceRedundancyElimination:
         opt = new (allocator) ConstructorFenceRedundancyElimination(graph, stats, pass_name);
         break;
+      case OptimizationPass::kLoadStoreElimination:
+        opt = new (allocator) LoadStoreElimination(graph, stats, pass_name);
+        break;
       case OptimizationPass::kScheduling:
         opt = new (allocator) HInstructionScheduling(
             graph, codegen->GetCompilerOptions().GetInstructionSet(), codegen, pass_name);
@@ -279,6 +279,10 @@
         DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
         opt = new (allocator) arm::InstructionSimplifierArm(graph, stats);
         break;
+      case OptimizationPass::kCriticalNativeAbiFixupArm:
+        DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
+        opt = new (allocator) arm::CriticalNativeAbiFixupArm(graph, stats);
+        break;
 #endif
 #ifdef ART_ENABLE_CODEGEN_arm64
       case OptimizationPass::kInstructionSimplifierArm64:
@@ -311,7 +315,7 @@
 
     // Add each next optimization to result vector.
     CHECK(opt != nullptr);
-    DCHECK_STREQ(pass_name, opt->GetPassName());  // sanity
+    DCHECK_STREQ(pass_name, opt->GetPassName());  // Consistency check.
     optimizations.push_back(opt);
   }
 
diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h
index f4777ad..2113df0 100644
--- a/compiler/optimizing/optimization.h
+++ b/compiler/optimizing/optimization.h
@@ -66,6 +66,7 @@
 // field is preferred over a string lookup at places where performance matters.
 // TODO: generate this table and lookup methods below automatically?
 enum class OptimizationPass {
+  kAggressiveInstructionSimplifier,
   kBoundsCheckElimination,
   kCHAGuardOptimization,
   kCodeSinking,
@@ -77,7 +78,6 @@
   kInliner,
   kInstructionSimplifier,
   kInvariantCodeMotion,
-  kLoadStoreAnalysis,
   kLoadStoreElimination,
   kLoopOptimization,
   kScheduling,
@@ -85,6 +85,7 @@
   kSideEffectsAnalysis,
 #ifdef ART_ENABLE_CODEGEN_arm
   kInstructionSimplifierArm,
+  kCriticalNativeAbiFixupArm,
 #endif
 #ifdef ART_ENABLE_CODEGEN_arm64
   kInstructionSimplifierArm64,
@@ -142,8 +143,7 @@
     HGraph* graph,
     OptimizingCompilerStats* stats,
     CodeGenerator* codegen,
-    const DexCompilationUnit& dex_compilation_unit,
-    VariableSizedHandleScope* handles);
+    const DexCompilationUnit& dex_compilation_unit);
 
 }  // namespace art
 
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 9978a6f..b6ab9fb 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -32,7 +32,6 @@
 #include "base/scoped_arena_allocator.h"
 #include "base/timing_logger.h"
 #include "builder.h"
-#include "class_root.h"
 #include "code_generator.h"
 #include "compiled_method.h"
 #include "compiler.h"
@@ -118,7 +117,8 @@
         visualizer_oss_(),
         visualizer_output_(visualizer_output),
         visualizer_enabled_(!compiler_options.GetDumpCfgFileName().empty()),
-        visualizer_(&visualizer_oss_, graph, *codegen),
+        visualizer_(&visualizer_oss_, graph, codegen),
+        codegen_(codegen),
         visualizer_dump_mutex_(dump_mutex),
         graph_in_bad_state_(false) {
     if (timing_logger_enabled_ || visualizer_enabled_) {
@@ -191,10 +191,12 @@
     // Validate the HGraph if running in debug mode.
     if (kIsDebugBuild) {
       if (!graph_in_bad_state_) {
-        GraphChecker checker(graph_);
+        GraphChecker checker(graph_, codegen_);
         last_seen_graph_size_ = checker.Run(pass_change, last_seen_graph_size_);
         if (!checker.IsValid()) {
-          LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable<GraphChecker>(checker);
+          LOG(FATAL_WITHOUT_ABORT) << "Error after " << pass_name << "(" << graph_->PrettyMethod()
+                                   << "): " << *graph_;
+          LOG(FATAL) << "(" << pass_name <<  "): " << Dumpable<GraphChecker>(checker);
         }
       }
     }
@@ -231,6 +233,7 @@
   std::ostream* visualizer_output_;
   bool visualizer_enabled_;
   HGraphVisualizer visualizer_;
+  CodeGenerator* codegen_;
   Mutex& visualizer_dump_mutex_;
 
   // Flag to be set by the compiler if the pass failed and the graph is not
@@ -297,8 +300,7 @@
                   jit::JitCodeCache* code_cache,
                   jit::JitMemoryRegion* region,
                   ArtMethod* method,
-                  bool baseline,
-                  bool osr,
+                  CompilationKind compilation_kind,
                   jit::JitLogger* jit_logger)
       override
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -308,7 +310,6 @@
                         CodeGenerator* codegen,
                         const DexCompilationUnit& dex_compilation_unit,
                         PassObserver* pass_observer,
-                        VariableSizedHandleScope* handles,
                         const OptimizationDef definitions[],
                         size_t length) const {
     // Convert definitions to optimization passes.
@@ -319,8 +320,7 @@
         graph,
         compilation_stats_.get(),
         codegen,
-        dex_compilation_unit,
-        handles);
+        dex_compilation_unit);
     DCHECK_EQ(length, optimizations.size());
     // Run the optimization passes one by one. Any "depends_on" pass refers back to
     // the most recent occurrence of that pass, skipped or executed.
@@ -351,17 +351,15 @@
       CodeGenerator* codegen,
       const DexCompilationUnit& dex_compilation_unit,
       PassObserver* pass_observer,
-      VariableSizedHandleScope* handles,
       const OptimizationDef (&definitions)[length]) const {
     return RunOptimizations(
-        graph, codegen, dex_compilation_unit, pass_observer, handles, definitions, length);
+        graph, codegen, dex_compilation_unit, pass_observer, definitions, length);
   }
 
   void RunOptimizations(HGraph* graph,
                         CodeGenerator* codegen,
                         const DexCompilationUnit& dex_compilation_unit,
-                        PassObserver* pass_observer,
-                        VariableSizedHandleScope* handles) const;
+                        PassObserver* pass_observer) const;
 
  private:
   // Create a 'CompiledMethod' for an optimized graph.
@@ -382,9 +380,7 @@
                             CodeVectorAllocator* code_allocator,
                             const DexCompilationUnit& dex_compilation_unit,
                             ArtMethod* method,
-                            bool baseline,
-                            bool osr,
-                            bool is_shared_jit_code,
+                            CompilationKind compilation_kind,
                             VariableSizedHandleScope* handles) const;
 
   CodeGenerator* TryCompileIntrinsic(ArenaAllocator* allocator,
@@ -397,16 +393,17 @@
   bool RunArchOptimizations(HGraph* graph,
                             CodeGenerator* codegen,
                             const DexCompilationUnit& dex_compilation_unit,
-                            PassObserver* pass_observer,
-                            VariableSizedHandleScope* handles) const;
+                            PassObserver* pass_observer) const;
 
   bool RunBaselineOptimizations(HGraph* graph,
                                 CodeGenerator* codegen,
                                 const DexCompilationUnit& dex_compilation_unit,
-                                PassObserver* pass_observer,
-                                VariableSizedHandleScope* handles) const;
+                                PassObserver* pass_observer) const;
 
-  void GenerateJitDebugInfo(const debug::MethodDebugInfo& method_debug_info);
+  std::vector<uint8_t> GenerateJitDebugInfo(const debug::MethodDebugInfo& method_debug_info);
+
+  // This must be called before any other function that dumps data to the cfg
+  void DumpInstructionSetFeaturesToCfg() const;
 
   std::unique_ptr<OptimizingCompilerStats> compilation_stats_;
 
@@ -429,6 +426,7 @@
     std::ios_base::openmode cfg_file_mode =
         compiler_options.GetDumpCfgAppend() ? std::ofstream::app : std::ofstream::out;
     visualizer_output_.reset(new std::ofstream(cfg_file_name, cfg_file_mode));
+    DumpInstructionSetFeaturesToCfg();
   }
   if (compiler_options.GetDumpStats()) {
     compilation_stats_.reset(new OptimizingCompilerStats());
@@ -441,6 +439,19 @@
   }
 }
 
+void OptimizingCompiler::DumpInstructionSetFeaturesToCfg() const {
+  const CompilerOptions& compiler_options = GetCompilerOptions();
+  const InstructionSetFeatures* features = compiler_options.GetInstructionSetFeatures();
+  std::string isa_string =
+      std::string("isa:") + GetInstructionSetString(features->GetInstructionSet());
+  std::string features_string = "isa_features:" + features->GetFeatureString();
+  // It is assumed that visualizer_output_ is empty when calling this function, hence the fake
+  // compilation block containing the ISA features will be printed at the beginning of the .cfg
+  // file.
+  *visualizer_output_
+      << HGraphVisualizer::InsertMetaDataAsCompilationBlock(isa_string + ' ' + features_string);
+}
+
 bool OptimizingCompiler::CanCompileMethod(uint32_t method_idx ATTRIBUTE_UNUSED,
                                           const DexFile& dex_file ATTRIBUTE_UNUSED) const {
   return true;
@@ -457,9 +468,21 @@
 bool OptimizingCompiler::RunBaselineOptimizations(HGraph* graph,
                                                   CodeGenerator* codegen,
                                                   const DexCompilationUnit& dex_compilation_unit,
-                                                  PassObserver* pass_observer,
-                                                  VariableSizedHandleScope* handles) const {
+                                                  PassObserver* pass_observer) const {
   switch (codegen->GetCompilerOptions().GetInstructionSet()) {
+#if defined(ART_ENABLE_CODEGEN_arm)
+    case InstructionSet::kThumb2:
+    case InstructionSet::kArm: {
+      OptimizationDef arm_optimizations[] = {
+        OptDef(OptimizationPass::kCriticalNativeAbiFixupArm),
+      };
+      return RunOptimizations(graph,
+                              codegen,
+                              dex_compilation_unit,
+                              pass_observer,
+                              arm_optimizations);
+    }
+#endif
 #ifdef ART_ENABLE_CODEGEN_x86
     case InstructionSet::kX86: {
       OptimizationDef x86_optimizations[] = {
@@ -469,7 +492,6 @@
                               codegen,
                               dex_compilation_unit,
                               pass_observer,
-                              handles,
                               x86_optimizations);
     }
 #endif
@@ -478,7 +500,6 @@
       UNUSED(codegen);
       UNUSED(dex_compilation_unit);
       UNUSED(pass_observer);
-      UNUSED(handles);
       return false;
   }
 }
@@ -486,8 +507,7 @@
 bool OptimizingCompiler::RunArchOptimizations(HGraph* graph,
                                               CodeGenerator* codegen,
                                               const DexCompilationUnit& dex_compilation_unit,
-                                              PassObserver* pass_observer,
-                                              VariableSizedHandleScope* handles) const {
+                                              PassObserver* pass_observer) const {
   switch (codegen->GetCompilerOptions().GetInstructionSet()) {
 #if defined(ART_ENABLE_CODEGEN_arm)
     case InstructionSet::kThumb2:
@@ -496,13 +516,13 @@
         OptDef(OptimizationPass::kInstructionSimplifierArm),
         OptDef(OptimizationPass::kSideEffectsAnalysis),
         OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"),
+        OptDef(OptimizationPass::kCriticalNativeAbiFixupArm),
         OptDef(OptimizationPass::kScheduling)
       };
       return RunOptimizations(graph,
                               codegen,
                               dex_compilation_unit,
                               pass_observer,
-                              handles,
                               arm_optimizations);
     }
 #endif
@@ -518,7 +538,6 @@
                               codegen,
                               dex_compilation_unit,
                               pass_observer,
-                              handles,
                               arm64_optimizations);
     }
 #endif
@@ -535,7 +554,6 @@
                               codegen,
                               dex_compilation_unit,
                               pass_observer,
-                              handles,
                               x86_optimizations);
     }
 #endif
@@ -551,7 +569,6 @@
                               codegen,
                               dex_compilation_unit,
                               pass_observer,
-                              handles,
                               x86_64_optimizations);
     }
 #endif
@@ -596,8 +613,7 @@
 void OptimizingCompiler::RunOptimizations(HGraph* graph,
                                           CodeGenerator* codegen,
                                           const DexCompilationUnit& dex_compilation_unit,
-                                          PassObserver* pass_observer,
-                                          VariableSizedHandleScope* handles) const {
+                                          PassObserver* pass_observer) const {
   const std::vector<std::string>* pass_names = GetCompilerOptions().GetPassesToRun();
   if (pass_names != nullptr) {
     // If passes were defined on command-line, build the optimization
@@ -613,7 +629,6 @@
                      codegen,
                      dex_compilation_unit,
                      pass_observer,
-                     handles,
                      optimizations.data(),
                      length);
     return;
@@ -659,12 +674,9 @@
     // Simplification.
     OptDef(OptimizationPass::kConstantFolding,
            "constant_folding$after_bce"),
-    OptDef(OptimizationPass::kInstructionSimplifier,
+    OptDef(OptimizationPass::kAggressiveInstructionSimplifier,
            "instruction_simplifier$after_bce"),
     // Other high-level optimizations.
-    OptDef(OptimizationPass::kSideEffectsAnalysis,
-           "side_effects$before_lse"),
-    OptDef(OptimizationPass::kLoadStoreAnalysis),
     OptDef(OptimizationPass::kLoadStoreElimination),
     OptDef(OptimizationPass::kCHAGuardOptimization),
     OptDef(OptimizationPass::kDeadCodeElimination,
@@ -673,7 +685,7 @@
     // The codegen has a few assumptions that only the instruction simplifier
     // can satisfy. For example, the code generator does not expect to see a
     // HTypeConversion from a type to the same type.
-    OptDef(OptimizationPass::kInstructionSimplifier,
+    OptDef(OptimizationPass::kAggressiveInstructionSimplifier,
            "instruction_simplifier$before_codegen"),
     // Eliminate constructor fences after code sinking to avoid
     // complicated sinking logic to split a fence with many inputs.
@@ -683,10 +695,9 @@
                    codegen,
                    dex_compilation_unit,
                    pass_observer,
-                   handles,
                    optimizations);
 
-  RunArchOptimizations(graph, codegen, dex_compilation_unit, pass_observer, handles);
+  RunArchOptimizations(graph, codegen, dex_compilation_unit, pass_observer);
 }
 
 static ArenaVector<linker::LinkerPatch> EmitAndSortLinkerPatches(CodeGenerator* codegen) {
@@ -735,9 +746,7 @@
                                               CodeVectorAllocator* code_allocator,
                                               const DexCompilationUnit& dex_compilation_unit,
                                               ArtMethod* method,
-                                              bool baseline,
-                                              bool osr,
-                                              bool is_shared_jit_code,
+                                              CompilationKind compilation_kind,
                                               VariableSizedHandleScope* handles) const {
   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kAttemptBytecodeCompilation);
   const CompilerOptions& compiler_options = GetCompilerOptions();
@@ -775,7 +784,6 @@
   CodeItemDebugInfoAccessor code_item_accessor(dex_file, code_item, method_idx);
 
   bool dead_reference_safe;
-  ArrayRef<const uint8_t> interpreter_metadata;
   // For AOT compilation, we may not get a method, for example if its class is erroneous,
   // possibly due to an unavailable superclass.  JIT should always have a method.
   DCHECK(Runtime::Current()->IsAotCompiler() || method != nullptr);
@@ -784,7 +792,6 @@
     {
       ScopedObjectAccess soa(Thread::Current());
       containing_class = &method->GetClassDef();
-      interpreter_metadata = method->GetQuickenedInfo();
     }
     // MethodContainsRSensitiveAccess is currently slow, but HasDeadReferenceSafeAnnotation()
     // is currently rarely true.
@@ -799,15 +806,14 @@
   HGraph* graph = new (allocator) HGraph(
       allocator,
       arena_stack,
+      handles,
       dex_file,
       method_idx,
       compiler_options.GetInstructionSet(),
       kInvalidInvokeType,
       dead_reference_safe,
       compiler_options.GetDebuggable(),
-      /* osr= */ osr,
-      /* is_shared_jit_code= */ is_shared_jit_code,
-      /* baseline= */ baseline);
+      compilation_kind);
 
   if (method != nullptr) {
     graph->SetArtMethod(method);
@@ -837,9 +843,7 @@
                           &dex_compilation_unit,
                           &dex_compilation_unit,
                           codegen.get(),
-                          compilation_stats_.get(),
-                          interpreter_metadata,
-                          handles);
+                          compilation_stats_.get());
     GraphAnalysisResult result = builder.BuildGraph();
     if (result != kAnalysisSuccess) {
       switch (result) {
@@ -881,10 +885,10 @@
     }
   }
 
-  if (baseline) {
-    RunBaselineOptimizations(graph, codegen.get(), dex_compilation_unit, &pass_observer, handles);
+  if (compilation_kind == CompilationKind::kBaseline) {
+    RunBaselineOptimizations(graph, codegen.get(), dex_compilation_unit, &pass_observer);
   } else {
-    RunOptimizations(graph, codegen.get(), dex_compilation_unit, &pass_observer, handles);
+    RunOptimizations(graph, codegen.get(), dex_compilation_unit, &pass_observer);
   }
 
   RegisterAllocator::Strategy regalloc_strategy =
@@ -927,13 +931,14 @@
   HGraph* graph = new (allocator) HGraph(
       allocator,
       arena_stack,
+      handles,
       dex_file,
       method_idx,
       compiler_options.GetInstructionSet(),
       kInvalidInvokeType,
       /* dead_reference_safe= */ true,  // Intrinsics don't affect dead reference safety.
       compiler_options.GetDebuggable(),
-      /* osr= */ false);
+      CompilationKind::kOptimized);
 
   DCHECK(Runtime::Current()->IsAotCompiler());
   DCHECK(method != nullptr);
@@ -962,9 +967,7 @@
                           &dex_compilation_unit,
                           &dex_compilation_unit,
                           codegen.get(),
-                          compilation_stats_.get(),
-                          /* interpreter_metadata= */ ArrayRef<const uint8_t>(),
-                          handles);
+                          compilation_stats_.get());
     builder.BuildIntrinsicGraph(method);
   }
 
@@ -977,10 +980,9 @@
                    codegen.get(),
                    dex_compilation_unit,
                    &pass_observer,
-                   handles,
                    optimizations);
 
-  RunArchOptimizations(graph, codegen.get(), dex_compilation_unit, &pass_observer, handles);
+  RunArchOptimizations(graph, codegen.get(), dex_compilation_unit, &pass_observer);
 
   AllocateRegisters(graph,
                     codegen.get(),
@@ -1011,6 +1013,7 @@
                                             const DexFile& dex_file,
                                             Handle<mirror::DexCache> dex_cache) const {
   const CompilerOptions& compiler_options = GetCompilerOptions();
+  DCHECK(compiler_options.IsAotCompiler());
   CompiledMethod* compiled_method = nullptr;
   Runtime* runtime = Runtime::Current();
   DCHECK(runtime->IsAotCompiler());
@@ -1045,8 +1048,11 @@
           /*verified_method=*/ nullptr,  // Not needed by the Optimizing compiler.
           dex_cache,
           compiling_class);
+      // All signature polymorphic methods are native.
+      DCHECK(method == nullptr || !method->IsSignaturePolymorphic());
       // Go to native so that we don't block GC during compilation.
       ScopedThreadSuspension sts(soa.Self(), kNative);
+      // Try to compile a fully intrinsified implementation.
       if (method != nullptr && UNLIKELY(method->IsIntrinsic())) {
         DCHECK(compiler_options.IsBootImage());
         codegen.reset(
@@ -1067,9 +1073,9 @@
                        &code_allocator,
                        dex_compilation_unit,
                        method,
-                       compiler_options.IsBaseline(),
-                       /* osr= */ false,
-                       /* is_shared_jit_code= */ false,
+                       compiler_options.IsBaseline()
+                          ? CompilationKind::kBaseline
+                          : CompilationKind::kOptimized,
                        &handles));
       }
     }
@@ -1106,7 +1112,7 @@
   }
 
   if (kIsDebugBuild &&
-      compiler_options.CompilingWithCoreImage() &&
+      compiler_options.CompileArtTest() &&
       IsInstructionSetSupported(compiler_options.GetInstructionSet())) {
     // For testing purposes, we put a special marker on method names
     // that should be compiled with this compiler (when the
@@ -1121,7 +1127,8 @@
 }
 
 static ScopedArenaVector<uint8_t> CreateJniStackMap(ScopedArenaAllocator* allocator,
-                                                    const JniCompiledMethod& jni_compiled_method) {
+                                                    const JniCompiledMethod& jni_compiled_method,
+                                                    size_t code_size) {
   // StackMapStream is quite large, so allocate it using the ScopedArenaAllocator
   // to stay clear of the frame size limit.
   std::unique_ptr<StackMapStream> stack_map_stream(
@@ -1132,7 +1139,7 @@
       jni_compiled_method.GetFpSpillMask(),
       /* num_dex_registers= */ 0,
       /* baseline= */ false);
-  stack_map_stream->EndMethod();
+  stack_map_stream->EndMethod(code_size);
   return stack_map_stream->Encode();
 }
 
@@ -1149,7 +1156,10 @@
     ScopedObjectAccess soa(Thread::Current());
     ArtMethod* method = runtime->GetClassLinker()->LookupResolvedMethod(
         method_idx, dex_cache.Get(), /*class_loader=*/ nullptr);
-    if (method != nullptr && UNLIKELY(method->IsIntrinsic())) {
+    // Try to compile a fully intrinsified implementation. Do not try to do this for
+    // signature polymorphic methods as the InstructionBuilder cannot handle them;
+    // and it would be useless as they always have a slow path for type conversions.
+    if (method != nullptr && UNLIKELY(method->IsIntrinsic()) && !method->IsSignaturePolymorphic()) {
       VariableSizedHandleScope handles(soa.Self());
       ScopedNullHandle<mirror::ClassLoader> class_loader;  // null means boot class path loader.
       Handle<mirror::Class> compiling_class = handles.NewHandle(method->GetDeclaringClass());
@@ -1190,8 +1200,8 @@
   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kCompiledNativeStub);
 
   ScopedArenaAllocator stack_map_allocator(&arena_stack);  // Will hold the stack map.
-  ScopedArenaVector<uint8_t> stack_map = CreateJniStackMap(&stack_map_allocator,
-                                                           jni_compiled_method);
+  ScopedArenaVector<uint8_t> stack_map = CreateJniStackMap(
+      &stack_map_allocator, jni_compiled_method, jni_compiled_method.GetCode().size());
   return CompiledMethod::SwapAllocCompiledMethod(
       GetCompiledMethodStorage(),
       jni_compiled_method.GetInstructionSet(),
@@ -1215,9 +1225,16 @@
                                     jit::JitCodeCache* code_cache,
                                     jit::JitMemoryRegion* region,
                                     ArtMethod* method,
-                                    bool baseline,
-                                    bool osr,
+                                    CompilationKind compilation_kind,
                                     jit::JitLogger* jit_logger) {
+  const CompilerOptions& compiler_options = GetCompilerOptions();
+  // If the baseline flag was explicitly passed, change the compilation kind
+  // from optimized to baseline.
+  if (compiler_options.IsBaseline() && compilation_kind == CompilationKind::kOptimized) {
+    compilation_kind = CompilationKind::kBaseline;
+  }
+  DCHECK(compiler_options.IsJitCompiler());
+  DCHECK_EQ(compiler_options.IsJitCompilerForSharedCode(), code_cache->IsSharedRegion(*region));
   StackHandleScope<3> hs(self);
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
       method->GetDeclaringClass()->GetClassLoader()));
@@ -1226,7 +1243,7 @@
 
   const DexFile* dex_file = method->GetDexFile();
   const uint16_t class_def_idx = method->GetClassDefIndex();
-  const dex::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
+  const dex::CodeItem* code_item = method->GetCodeItem();
   const uint32_t method_idx = method->GetDexMethodIndex();
   const uint32_t access_flags = method->GetAccessFlags();
 
@@ -1234,7 +1251,6 @@
   ArenaAllocator allocator(runtime->GetJitArenaPool());
 
   if (UNLIKELY(method->IsNative())) {
-    const CompilerOptions& compiler_options = GetCompilerOptions();
     JniCompiledMethod jni_compiled_method = ArtQuickJniCompileMethod(
         compiler_options, access_flags, method_idx, *dex_file);
     std::vector<Handle<mirror::Object>> roots;
@@ -1243,8 +1259,8 @@
     ArenaStack arena_stack(runtime->GetJitArenaPool());
     // StackMapStream is large and it does not fit into this frame, so we need helper method.
     ScopedArenaAllocator stack_map_allocator(&arena_stack);  // Will hold the stack map.
-    ScopedArenaVector<uint8_t> stack_map = CreateJniStackMap(&stack_map_allocator,
-                                                             jni_compiled_method);
+    ScopedArenaVector<uint8_t> stack_map = CreateJniStackMap(
+        &stack_map_allocator, jni_compiled_method, jni_compiled_method.GetCode().size());
 
     ArrayRef<const uint8_t> reserved_code;
     ArrayRef<const uint8_t> reserved_data;
@@ -1262,8 +1278,10 @@
     const uint8_t* code = reserved_code.data() + OatQuickMethodHeader::InstructionAlignedSize();
 
     // Add debug info after we know the code location but before we update entry-point.
+    std::vector<uint8_t> debug_info;
     if (compiler_options.GenerateAnyDebugInfo()) {
       debug::MethodDebugInfo info = {};
+      // Simpleperf relies on art_jni_trampoline to detect jni methods.
       info.custom_name = "art_jni_trampoline";
       info.dex_file = dex_file;
       info.class_def_index = class_def_idx;
@@ -1280,7 +1298,7 @@
       info.frame_size_in_bytes = jni_compiled_method.GetFrameSize();
       info.code_info = nullptr;
       info.cfi = jni_compiled_method.GetCfi();
-      GenerateJitDebugInfo(info);
+      debug_info = GenerateJitDebugInfo(info);
     }
 
     if (!code_cache->Commit(self,
@@ -1291,7 +1309,9 @@
                             reserved_data,
                             roots,
                             ArrayRef<const uint8_t>(stack_map),
-                            osr,
+                            debug_info,
+                            /* is_full_debug_info= */ compiler_options.GetGenerateDebugInfo(),
+                            compilation_kind,
                             /* has_should_deoptimize_flag= */ false,
                             cha_single_implementation_list)) {
       code_cache->Free(self, region, reserved_code.data(), reserved_data.data());
@@ -1332,9 +1352,7 @@
                    &code_allocator,
                    dex_compilation_unit,
                    method,
-                   baseline || GetCompilerOptions().IsBaseline(),
-                   osr,
-                   /* is_shared_jit_code= */ code_cache->IsSharedRegion(*region),
+                   compilation_kind,
                    &handles));
     if (codegen.get() == nullptr) {
       return false;
@@ -1369,7 +1387,7 @@
                      }));
 
   // Add debug info after we know the code location but before we update entry-point.
-  const CompilerOptions& compiler_options = GetCompilerOptions();
+  std::vector<uint8_t> debug_info;
   if (compiler_options.GenerateAnyDebugInfo()) {
     debug::MethodDebugInfo info = {};
     DCHECK(info.custom_name.empty());
@@ -1388,7 +1406,7 @@
     info.frame_size_in_bytes = codegen->GetFrameSize();
     info.code_info = stack_map.size() == 0 ? nullptr : stack_map.data();
     info.cfi = ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data());
-    GenerateJitDebugInfo(info);
+    debug_info = GenerateJitDebugInfo(info);
   }
 
   if (!code_cache->Commit(self,
@@ -1399,7 +1417,9 @@
                           reserved_data,
                           roots,
                           ArrayRef<const uint8_t>(stack_map),
-                          osr,
+                          debug_info,
+                          /* is_full_debug_info= */ compiler_options.GetGenerateDebugInfo(),
+                          compilation_kind,
                           codegen->GetGraph()->HasShouldDeoptimizeFlag(),
                           codegen->GetGraph()->GetCHASingleImplementationList())) {
     code_cache->Free(self, region, reserved_code.data(), reserved_data.data());
@@ -1427,7 +1447,7 @@
   return true;
 }
 
-void OptimizingCompiler::GenerateJitDebugInfo(const debug::MethodDebugInfo& info) {
+std::vector<uint8_t> OptimizingCompiler::GenerateJitDebugInfo(const debug::MethodDebugInfo& info) {
   const CompilerOptions& compiler_options = GetCompilerOptions();
   if (compiler_options.GenerateAnyDebugInfo()) {
     // If both flags are passed, generate full debug info.
@@ -1436,13 +1456,9 @@
     // Create entry for the single method that we just compiled.
     InstructionSet isa = compiler_options.GetInstructionSet();
     const InstructionSetFeatures* features = compiler_options.GetInstructionSetFeatures();
-    std::vector<uint8_t> elf = debug::MakeElfFileForJIT(isa, features, mini_debug_info, info);
-
-    // NB: Don't allow packing of full info since it would remove non-backtrace data.
-    MutexLock mu(Thread::Current(), *Locks::jit_lock_);
-    const void* code_ptr = reinterpret_cast<const void*>(info.code_address);
-    AddNativeDebugInfoForJit(code_ptr, elf, /*allow_packing=*/ mini_debug_info);
+    return debug::MakeElfFileForJIT(isa, features, mini_debug_info, info);
   }
+  return std::vector<uint8_t>();
 }
 
 }  // namespace art
diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h
index 83dbef7..3d0815f 100644
--- a/compiler/optimizing/optimizing_compiler_stats.h
+++ b/compiler/optimizing/optimizing_compiler_stats.h
@@ -97,6 +97,10 @@
   kNotInlinedWont,
   kNotInlinedRecursiveBudget,
   kNotInlinedProxy,
+  kNotInlinedUnresolved,
+  kNotInlinedPolymorphic,
+  kNotInlinedCustom,
+  kTryInline,
   kConstructorFenceGeneratedNew,
   kConstructorFenceGeneratedFinal,
   kConstructorFenceRemovedLSE,
@@ -104,9 +108,18 @@
   kConstructorFenceRemovedCFRE,
   kBitstringTypeCheck,
   kJitOutOfMemoryForCommit,
+  kFullLSEAllocationRemoved,
+  kFullLSEPossible,
+  kNonPartialLoadRemoved,
+  kPartialLSEPossible,
+  kPartialStoreRemoved,
+  kPartialAllocationMoved,
+  kPredicatedLoadAdded,
+  kPredicatedStoreAdded,
+  kDevirtualized,
   kLastStat
 };
-std::ostream& operator<<(std::ostream& os, const MethodCompilationStat& rhs);
+std::ostream& operator<<(std::ostream& os, MethodCompilationStat rhs);
 
 class OptimizingCompilerStats {
  public:
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index eb262bc..6600ff3 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -18,8 +18,14 @@
 #define ART_COMPILER_OPTIMIZING_OPTIMIZING_UNIT_TEST_H_
 
 #include <memory>
+#include <ostream>
+#include <string_view>
+#include <string>
+#include <tuple>
 #include <vector>
+#include <variant>
 
+#include "base/indenter.h"
 #include "base/malloc_arena_pool.h"
 #include "base/scoped_arena_allocator.h"
 #include "builder.h"
@@ -30,7 +36,9 @@
 #include "dex/standard_dex_file.h"
 #include "driver/dex_compilation_unit.h"
 #include "graph_checker.h"
+#include "gtest/gtest.h"
 #include "handle_scope-inl.h"
+#include "handle_scope.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache.h"
 #include "nodes.h"
@@ -38,8 +46,6 @@
 #include "ssa_builder.h"
 #include "ssa_liveness_analysis.h"
 
-#include "gtest/gtest.h"
-
 namespace art {
 
 #define NUM_INSTRUCTIONS(...)  \
@@ -56,11 +62,38 @@
 #define FIVE_REGISTERS_CODE_ITEM(...)  N_REGISTERS_CODE_ITEM(5, __VA_ARGS__)
 #define SIX_REGISTERS_CODE_ITEM(...)   N_REGISTERS_CODE_ITEM(6, __VA_ARGS__)
 
-LiveInterval* BuildInterval(const size_t ranges[][2],
-                            size_t number_of_ranges,
-                            ScopedArenaAllocator* allocator,
-                            int reg = -1,
-                            HInstruction* defined_by = nullptr) {
+struct InstructionDumper {
+ public:
+  HInstruction* ins_;
+};
+
+inline bool operator==(const InstructionDumper& a, const InstructionDumper& b) {
+  return a.ins_ == b.ins_;
+}
+inline bool operator!=(const InstructionDumper& a, const InstructionDumper& b) {
+  return !(a == b);
+}
+
+inline std::ostream& operator<<(std::ostream& os, const InstructionDumper& id) {
+  if (id.ins_ == nullptr) {
+    return os << "NULL";
+  } else {
+    return os << "(" << id.ins_ << "): " << id.ins_->DumpWithArgs();
+  }
+}
+
+#define EXPECT_INS_EQ(a, b) EXPECT_EQ(InstructionDumper{a}, InstructionDumper{b})
+#define EXPECT_INS_REMOVED(a) EXPECT_TRUE(IsRemoved(a)) << "Not removed: " << (InstructionDumper{a})
+#define EXPECT_INS_RETAINED(a) EXPECT_FALSE(IsRemoved(a)) << "Removed: " << (InstructionDumper{a})
+#define ASSERT_INS_EQ(a, b) ASSERT_EQ(InstructionDumper{a}, InstructionDumper{b})
+#define ASSERT_INS_REMOVED(a) ASSERT_TRUE(IsRemoved(a)) << "Not removed: " << (InstructionDumper{a})
+#define ASSERT_INS_RETAINED(a) ASSERT_FALSE(IsRemoved(a)) << "Removed: " << (InstructionDumper{a})
+
+inline LiveInterval* BuildInterval(const size_t ranges[][2],
+                                   size_t number_of_ranges,
+                                   ScopedArenaAllocator* allocator,
+                                   int reg = -1,
+                                   HInstruction* defined_by = nullptr) {
   LiveInterval* interval =
       LiveInterval::MakeInterval(allocator, DataType::Type::kInt32, defined_by);
   if (defined_by != nullptr) {
@@ -73,7 +106,7 @@
   return interval;
 }
 
-void RemoveSuspendChecks(HGraph* graph) {
+inline void RemoveSuspendChecks(HGraph* graph) {
   for (HBasicBlock* block : graph->GetBlocks()) {
     if (block != nullptr) {
       if (block->GetLoopInformation() != nullptr) {
@@ -105,11 +138,90 @@
   ScopedArenaAllocator scoped_allocator_;
 };
 
+class AdjacencyListGraph {
+ public:
+  using Edge = std::pair<const std::string_view, const std::string_view>;
+  AdjacencyListGraph(
+      HGraph* graph,
+      ArenaAllocator* alloc,
+      const std::string_view entry_name,
+      const std::string_view exit_name,
+      const std::vector<Edge>& adj) : graph_(graph) {
+    auto create_block = [&]() {
+      HBasicBlock* blk = new (alloc) HBasicBlock(graph_);
+      graph_->AddBlock(blk);
+      return blk;
+    };
+    HBasicBlock* entry = create_block();
+    HBasicBlock* exit = create_block();
+    graph_->SetEntryBlock(entry);
+    graph_->SetExitBlock(exit);
+    name_to_block_.Put(entry_name, entry);
+    name_to_block_.Put(exit_name, exit);
+    for (const auto& [src, dest] : adj) {
+      HBasicBlock* src_blk = name_to_block_.GetOrCreate(src, create_block);
+      HBasicBlock* dest_blk = name_to_block_.GetOrCreate(dest, create_block);
+      src_blk->AddSuccessor(dest_blk);
+    }
+    graph_->ClearReachabilityInformation();
+    graph_->ComputeDominanceInformation();
+    graph_->ComputeReachabilityInformation();
+    for (auto [name, blk] : name_to_block_) {
+      block_to_name_.Put(blk, name);
+    }
+  }
+
+  bool HasBlock(const HBasicBlock* blk) const {
+    return block_to_name_.find(blk) != block_to_name_.end();
+  }
+
+  std::string_view GetName(const HBasicBlock* blk) const {
+    return block_to_name_.Get(blk);
+  }
+
+  HBasicBlock* Get(const std::string_view& sv) const {
+    return name_to_block_.Get(sv);
+  }
+
+  AdjacencyListGraph(AdjacencyListGraph&&) = default;
+  AdjacencyListGraph(const AdjacencyListGraph&) = default;
+  AdjacencyListGraph& operator=(AdjacencyListGraph&&) = default;
+  AdjacencyListGraph& operator=(const AdjacencyListGraph&) = default;
+
+  std::ostream& Dump(std::ostream& os) const {
+    struct Namer : public BlockNamer {
+     public:
+      explicit Namer(const AdjacencyListGraph& alg) : BlockNamer(), alg_(alg) {}
+      std::ostream& PrintName(std::ostream& os, HBasicBlock* blk) const override {
+        if (alg_.HasBlock(blk)) {
+          return os << alg_.GetName(blk) << " (" << blk->GetBlockId() << ")";
+        } else {
+          return os << "<Unnamed B" << blk->GetBlockId() << ">";
+        }
+      }
+
+      const AdjacencyListGraph& alg_;
+    };
+    Namer namer(*this);
+    return graph_->Dump(os, namer);
+  }
+
+ private:
+  HGraph* graph_;
+  SafeMap<const std::string_view, HBasicBlock*> name_to_block_;
+  SafeMap<const HBasicBlock*, const std::string_view> block_to_name_;
+};
+
 // Have a separate helper so the OptimizingCFITest can inherit it without causing
 // multiple inheritance errors from having two gtest as a parent twice.
 class OptimizingUnitTestHelper {
  public:
-  OptimizingUnitTestHelper() : pool_and_allocator_(new ArenaPoolAndAllocator()) { }
+  OptimizingUnitTestHelper()
+      : pool_and_allocator_(new ArenaPoolAndAllocator()),
+        graph_(nullptr),
+        entry_block_(nullptr),
+        return_block_(nullptr),
+        exit_block_(nullptr) { }
 
   ArenaAllocator* GetAllocator() { return pool_and_allocator_->GetAllocator(); }
   ArenaStack* GetArenaStack() { return pool_and_allocator_->GetArenaStack(); }
@@ -117,10 +229,9 @@
 
   void ResetPoolAndAllocator() {
     pool_and_allocator_.reset(new ArenaPoolAndAllocator());
-    handles_.reset();  // When getting rid of the old HGraph, we can also reset handles_.
   }
 
-  HGraph* CreateGraph() {
+  HGraph* CreateGraph(VariableSizedHandleScope* handles = nullptr) {
     ArenaAllocator* const allocator = pool_and_allocator_->GetAllocator();
 
     // Reserve a big array of 0s so the dex file constructor can offsets from the header.
@@ -137,18 +248,21 @@
         /*oat_dex_file*/ nullptr,
         /*container*/ nullptr));
 
-    return new (allocator) HGraph(
+    graph_ = new (allocator) HGraph(
         allocator,
         pool_and_allocator_->GetArenaStack(),
+        handles,
         *dex_files_.back(),
         /*method_idx*/-1,
         kRuntimeISA);
+    return graph_;
   }
 
   // Create a control-flow graph from Dex instructions.
   HGraph* CreateCFG(const std::vector<uint16_t>& data,
-                    DataType::Type return_type = DataType::Type::kInt32) {
-    HGraph* graph = CreateGraph();
+                    DataType::Type return_type = DataType::Type::kInt32,
+                    VariableSizedHandleScope* handles = nullptr) {
+    HGraph* graph = CreateGraph(handles);
 
     // The code item data might not aligned to 4 bytes, copy it to ensure that.
     const size_t code_item_size = data.size() * sizeof(data.front());
@@ -158,13 +272,9 @@
     const dex::CodeItem* code_item = reinterpret_cast<const dex::CodeItem*>(aligned_data);
 
     {
-      ScopedObjectAccess soa(Thread::Current());
-      if (handles_ == nullptr) {
-        handles_.reset(new VariableSizedHandleScope(soa.Self()));
-      }
       const DexCompilationUnit* dex_compilation_unit =
           new (graph->GetAllocator()) DexCompilationUnit(
-              handles_->NewHandle<mirror::ClassLoader>(nullptr),
+              /* class_loader= */ Handle<mirror::ClassLoader>(),  // Invalid handle.
               /* class_linker= */ nullptr,
               graph->GetDexFile(),
               code_item,
@@ -172,84 +282,61 @@
               /* method_idx= */ dex::kDexNoIndex,
               /* access_flags= */ 0u,
               /* verified_method= */ nullptr,
-              handles_->NewHandle<mirror::DexCache>(nullptr));
+              /* dex_cache= */ Handle<mirror::DexCache>());  // Invalid handle.
       CodeItemDebugInfoAccessor accessor(graph->GetDexFile(), code_item, /*dex_method_idx*/ 0u);
-      HGraphBuilder builder(graph, dex_compilation_unit, accessor, handles_.get(), return_type);
+      HGraphBuilder builder(graph, dex_compilation_unit, accessor, return_type);
       bool graph_built = (builder.BuildGraph() == kAnalysisSuccess);
       return graph_built ? graph : nullptr;
     }
   }
 
-  // Run GraphChecker with all checks.
-  //
-  // Return: the status whether the run is successful.
-  bool CheckGraph(HGraph* graph) {
-    return CheckGraph(graph, /*check_ref_type_info=*/true);
-  }
+  void InitGraph(VariableSizedHandleScope* handles = nullptr) {
+    CreateGraph(handles);
+    entry_block_ = AddNewBlock();
+    return_block_ = AddNewBlock();
+    exit_block_ = AddNewBlock();
 
-  // Run GraphChecker with all checks except reference type information checks.
-  //
-  // Return: the status whether the run is successful.
-  bool CheckGraphSkipRefTypeInfoChecks(HGraph* graph) {
-    return CheckGraph(graph, /*check_ref_type_info=*/false);
-  }
-
- private:
-  bool CheckGraph(HGraph* graph, bool check_ref_type_info) {
-    GraphChecker checker(graph);
-    checker.SetRefTypeInfoCheckEnabled(check_ref_type_info);
-    checker.Run();
-    checker.Dump(std::cerr);
-    return checker.IsValid();
-  }
-
-  std::vector<std::unique_ptr<const StandardDexFile>> dex_files_;
-  std::unique_ptr<ArenaPoolAndAllocator> pool_and_allocator_;
-  std::unique_ptr<VariableSizedHandleScope> handles_;
-};
-
-class OptimizingUnitTest : public CommonCompilerTest, public OptimizingUnitTestHelper {};
-
-// OptimizingUnitTest with some handy functions to ease the graph creation.
-class ImprovedOptimizingUnitTest : public OptimizingUnitTest {
- public:
-  ImprovedOptimizingUnitTest() : graph_(CreateGraph()),
-                                 entry_block_(nullptr),
-                                 return_block_(nullptr),
-                                 exit_block_(nullptr) {}
-
-  virtual ~ImprovedOptimizingUnitTest() {}
-
-  void InitGraph() {
-    entry_block_ = new (GetAllocator()) HBasicBlock(graph_);
-    graph_->AddBlock(entry_block_);
     graph_->SetEntryBlock(entry_block_);
-
-    return_block_ = new (GetAllocator()) HBasicBlock(graph_);
-    graph_->AddBlock(return_block_);
-
-    exit_block_ = new (GetAllocator()) HBasicBlock(graph_);
-    graph_->AddBlock(exit_block_);
     graph_->SetExitBlock(exit_block_);
 
     entry_block_->AddSuccessor(return_block_);
     return_block_->AddSuccessor(exit_block_);
 
-    CreateParameters();
-    for (HInstruction* parameter : parameters_) {
-      entry_block_->AddInstruction(parameter);
-    }
-
     return_block_->AddInstruction(new (GetAllocator()) HReturnVoid());
     exit_block_->AddInstruction(new (GetAllocator()) HExit());
   }
 
-  bool CheckGraph() {
-    return OptimizingUnitTestHelper::CheckGraph(graph_);
+  void AddParameter(HInstruction* parameter) {
+    entry_block_->AddInstruction(parameter);
+    parameters_.push_back(parameter);
   }
 
-  bool CheckGraphSkipRefTypeInfoChecks() {
-    return OptimizingUnitTestHelper::CheckGraphSkipRefTypeInfoChecks(graph_);
+  HBasicBlock* AddNewBlock() {
+    HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph_);
+    graph_->AddBlock(block);
+    return block;
+  }
+
+  // Run GraphChecker with all checks.
+  //
+  // Return: the status whether the run is successful.
+  bool CheckGraph(HGraph* graph, std::ostream& oss = std::cerr) {
+    return CheckGraph(graph, /*check_ref_type_info=*/true, oss);
+  }
+
+  bool CheckGraph(std::ostream& oss = std::cerr) {
+    return CheckGraph(graph_, oss);
+  }
+
+  // Run GraphChecker with all checks except reference type information checks.
+  //
+  // Return: the status whether the run is successful.
+  bool CheckGraphSkipRefTypeInfoChecks(HGraph* graph, std::ostream& oss = std::cerr) {
+    return CheckGraph(graph, /*check_ref_type_info=*/false, oss);
+  }
+
+  bool CheckGraphSkipRefTypeInfoChecks(std::ostream& oss = std::cerr) {
+    return CheckGraphSkipRefTypeInfoChecks(graph_, oss);
   }
 
   HEnvironment* ManuallyBuildEnvFor(HInstruction* instruction,
@@ -266,20 +353,211 @@
     return environment;
   }
 
+  void EnsurePredecessorOrder(HBasicBlock* target, std::initializer_list<HBasicBlock*> preds) {
+    // Make sure the given preds and block predecessors have the same blocks.
+    BitVector bv(preds.size(), false, Allocator::GetMallocAllocator());
+    auto preds_and_idx = ZipCount(MakeIterationRange(target->GetPredecessors()));
+    bool correct_preds = preds.size() == target->GetPredecessors().size() &&
+                         std::all_of(preds.begin(), preds.end(), [&](HBasicBlock* pred) {
+                           return std::any_of(preds_and_idx.begin(),
+                                              preds_and_idx.end(),
+                                              // Make sure every target predecessor is used only
+                                              // once.
+                                              [&](std::pair<HBasicBlock*, uint32_t> cur) {
+                                                if (cur.first == pred && !bv.IsBitSet(cur.second)) {
+                                                  bv.SetBit(cur.second);
+                                                  return true;
+                                                } else {
+                                                  return false;
+                                                }
+                                              });
+                         }) &&
+                         bv.NumSetBits() == preds.size();
+    auto dump_list = [](auto it) {
+      std::ostringstream oss;
+      oss << "[";
+      bool first = true;
+      for (HBasicBlock* b : it) {
+        if (!first) {
+          oss << ", ";
+        }
+        first = false;
+        oss << b->GetBlockId();
+      }
+      oss << "]";
+      return oss.str();
+    };
+    ASSERT_TRUE(correct_preds) << "Predecessors of " << target->GetBlockId() << " are "
+                               << dump_list(target->GetPredecessors()) << " not "
+                               << dump_list(preds);
+    if (correct_preds) {
+      std::copy(preds.begin(), preds.end(), target->predecessors_.begin());
+    }
+  }
+
+  AdjacencyListGraph SetupFromAdjacencyList(const std::string_view entry_name,
+                                            const std::string_view exit_name,
+                                            const std::vector<AdjacencyListGraph::Edge>& adj) {
+    return AdjacencyListGraph(graph_, GetAllocator(), entry_name, exit_name, adj);
+  }
+
+  void ManuallyBuildEnvFor(HInstruction* ins, const std::initializer_list<HInstruction*>& env) {
+    ArenaVector<HInstruction*> current_locals(env, GetAllocator()->Adapter(kArenaAllocInstruction));
+    OptimizingUnitTestHelper::ManuallyBuildEnvFor(ins, &current_locals);
+  }
+
+  HLoadClass* MakeClassLoad(std::optional<dex::TypeIndex> ti = std::nullopt,
+                            std::optional<Handle<mirror::Class>> klass = std::nullopt) {
+    return new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                           ti ? *ti : dex::TypeIndex(class_idx_++),
+                                           graph_->GetDexFile(),
+                                           /* klass= */ klass ? *klass : null_klass_,
+                                           /* is_referrers_class= */ false,
+                                           /* dex_pc= */ 0,
+                                           /* needs_access_check= */ false);
+  }
+
+  HNewInstance* MakeNewInstance(HInstruction* cls, uint32_t dex_pc = 0u) {
+    EXPECT_TRUE(cls->IsLoadClass() || cls->IsClinitCheck()) << *cls;
+    HLoadClass* load =
+        cls->IsLoadClass() ? cls->AsLoadClass() : cls->AsClinitCheck()->GetLoadClass();
+    return new (GetAllocator()) HNewInstance(cls,
+                                             dex_pc,
+                                             load->GetTypeIndex(),
+                                             graph_->GetDexFile(),
+                                             /* finalizable= */ false,
+                                             QuickEntrypointEnum::kQuickAllocObjectInitialized);
+  }
+
+  HInstanceFieldSet* MakeIFieldSet(HInstruction* inst,
+                                   HInstruction* data,
+                                   MemberOffset off,
+                                   uint32_t dex_pc = 0u) {
+    return new (GetAllocator()) HInstanceFieldSet(inst,
+                                                  data,
+                                                  /* field= */ nullptr,
+                                                  /* field_type= */ data->GetType(),
+                                                  /* field_offset= */ off,
+                                                  /* is_volatile= */ false,
+                                                  /* field_idx= */ 0,
+                                                  /* declaring_class_def_index= */ 0,
+                                                  graph_->GetDexFile(),
+                                                  dex_pc);
+  }
+
+  HInstanceFieldGet* MakeIFieldGet(HInstruction* inst,
+                                   DataType::Type type,
+                                   MemberOffset off,
+                                   uint32_t dex_pc = 0u) {
+    return new (GetAllocator()) HInstanceFieldGet(inst,
+                                                  /* field= */ nullptr,
+                                                  /* field_type= */ type,
+                                                  /* field_offset= */ off,
+                                                  /* is_volatile= */ false,
+                                                  /* field_idx= */ 0,
+                                                  /* declaring_class_def_index= */ 0,
+                                                  graph_->GetDexFile(),
+                                                  dex_pc);
+  }
+
+  HInvokeStaticOrDirect* MakeInvoke(DataType::Type return_type,
+                                    const std::vector<HInstruction*>& args) {
+    MethodReference method_reference{/* file= */ &graph_->GetDexFile(), /* index= */ method_idx_++};
+    HInvokeStaticOrDirect* res = new (GetAllocator())
+        HInvokeStaticOrDirect(GetAllocator(),
+                              args.size(),
+                              return_type,
+                              /* dex_pc= */ 0,
+                              method_reference,
+                              /* resolved_method= */ nullptr,
+                              HInvokeStaticOrDirect::DispatchInfo{},
+                              InvokeType::kStatic,
+                              /* resolved_method_reference= */ method_reference,
+                              HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+    for (auto [ins, idx] : ZipCount(MakeIterationRange(args))) {
+      res->SetRawInputAt(idx, ins);
+    }
+    return res;
+  }
+
+  HPhi* MakePhi(const std::vector<HInstruction*>& ins) {
+    EXPECT_GE(ins.size(), 2u) << "Phi requires at least 2 inputs";
+    HPhi* phi =
+        new (GetAllocator()) HPhi(GetAllocator(), kNoRegNumber, ins.size(), ins[0]->GetType());
+    for (auto [i, idx] : ZipCount(MakeIterationRange(ins))) {
+      phi->SetRawInputAt(idx, i);
+    }
+    return phi;
+  }
+
+  void SetupExit(HBasicBlock* exit) {
+    exit->AddInstruction(new (GetAllocator()) HExit());
+  }
+
+  dex::TypeIndex DefaultTypeIndexForType(DataType::Type type) {
+    switch (type) {
+      case DataType::Type::kBool:
+        return dex::TypeIndex(1);
+      case DataType::Type::kUint8:
+      case DataType::Type::kInt8:
+        return dex::TypeIndex(2);
+      case DataType::Type::kUint16:
+      case DataType::Type::kInt16:
+        return dex::TypeIndex(3);
+      case DataType::Type::kUint32:
+      case DataType::Type::kInt32:
+        return dex::TypeIndex(4);
+      case DataType::Type::kUint64:
+      case DataType::Type::kInt64:
+        return dex::TypeIndex(5);
+      case DataType::Type::kReference:
+        return dex::TypeIndex(6);
+      case DataType::Type::kFloat32:
+        return dex::TypeIndex(7);
+      case DataType::Type::kFloat64:
+        return dex::TypeIndex(8);
+      case DataType::Type::kVoid:
+        EXPECT_TRUE(false) << "No type for void!";
+        return dex::TypeIndex(1000);
+    }
+  }
+
+  // Creates a parameter. The instruction is automatically added to the entry-block
+  HParameterValue* MakeParam(DataType::Type type, std::optional<dex::TypeIndex> ti = std::nullopt) {
+    HParameterValue* val = new (GetAllocator()) HParameterValue(
+        graph_->GetDexFile(), ti ? *ti : DefaultTypeIndexForType(type), param_count_++, type);
+    graph_->GetEntryBlock()->AddInstruction(val);
+    return val;
+  }
+
  protected:
-  // Create parameters to be added to the graph entry block.
-  // Subclasses can override it to create parameters they need.
-  virtual void CreateParameters() { /* do nothing */ }
+  bool CheckGraph(HGraph* graph, bool check_ref_type_info, std::ostream& oss) {
+    GraphChecker checker(graph);
+    checker.SetRefTypeInfoCheckEnabled(check_ref_type_info);
+    checker.Run();
+    checker.Dump(oss);
+    return checker.IsValid();
+  }
+
+  std::vector<std::unique_ptr<const StandardDexFile>> dex_files_;
+  std::unique_ptr<ArenaPoolAndAllocator> pool_and_allocator_;
 
   HGraph* graph_;
-
   HBasicBlock* entry_block_;
   HBasicBlock* return_block_;
   HBasicBlock* exit_block_;
 
   std::vector<HInstruction*> parameters_;
+
+  size_t param_count_ = 0;
+  size_t class_idx_ = 42;
+  uint32_t method_idx_ = 100;
+
+  ScopedNullHandle<mirror::Class> null_klass_;
 };
 
+class OptimizingUnitTest : public CommonArtTest, public OptimizingUnitTestHelper {};
+
 // Naive string diff data type.
 typedef std::list<std::pair<std::string, std::string>> diff_t;
 
@@ -304,6 +582,160 @@
   return instruction->GetBlock() == nullptr;
 }
 
+inline std::ostream& operator<<(std::ostream& oss, const AdjacencyListGraph& alg) {
+  return alg.Dump(oss);
+}
+
+class PatternMatchGraphVisitor : public HGraphVisitor {
+ private:
+  struct HandlerWrapper {
+   public:
+    virtual ~HandlerWrapper() {}
+    virtual void operator()(HInstruction* h) = 0;
+  };
+
+  template <HInstruction::InstructionKind kKind, typename F>
+  struct KindWrapper;
+
+#define GEN_HANDLER(nm, unused)                                                         \
+  template <typename F>                                                                 \
+  struct KindWrapper<HInstruction::InstructionKind::k##nm, F> : public HandlerWrapper { \
+   public:                                                                              \
+    explicit KindWrapper(F f) : f_(f) {}                                                \
+    void operator()(HInstruction* h) override {                                         \
+      if constexpr (std::is_invocable_v<F, H##nm*>) {                                   \
+        f_(h->As##nm());                                                                \
+      } else {                                                                          \
+        LOG(FATAL) << "Incorrect call with " << #nm;                                    \
+      }                                                                                 \
+    }                                                                                   \
+                                                                                        \
+   private:                                                                             \
+    F f_;                                                                               \
+  };
+
+  FOR_EACH_CONCRETE_INSTRUCTION(GEN_HANDLER)
+#undef GEN_HANDLER
+
+  template <typename F>
+  std::unique_ptr<HandlerWrapper> GetWrapper(HInstruction::InstructionKind kind, F f) {
+    switch (kind) {
+#define GEN_GETTER(nm, unused)               \
+  case HInstruction::InstructionKind::k##nm: \
+    return std::unique_ptr<HandlerWrapper>(  \
+        new KindWrapper<HInstruction::InstructionKind::k##nm, F>(f));
+      FOR_EACH_CONCRETE_INSTRUCTION(GEN_GETTER)
+#undef GEN_GETTER
+      default:
+        LOG(FATAL) << "Unable to handle kind " << kind;
+        return nullptr;
+    }
+  }
+
+ public:
+  template <typename... Inst>
+  explicit PatternMatchGraphVisitor(HGraph* graph, Inst... handlers) : HGraphVisitor(graph) {
+    FillHandlers(handlers...);
+  }
+
+  void VisitInstruction(HInstruction* instruction) override {
+    auto& h = handlers_[instruction->GetKind()];
+    if (h.get() != nullptr) {
+      (*h)(instruction);
+    }
+  }
+
+ private:
+  template <typename Func>
+  constexpr HInstruction::InstructionKind GetKind() {
+#define CHECK_INST(nm, unused)                       \
+    if constexpr (std::is_invocable_v<Func, H##nm*>) { \
+      return HInstruction::InstructionKind::k##nm;     \
+    }
+    FOR_EACH_CONCRETE_INSTRUCTION(CHECK_INST);
+#undef CHECK_INST
+    static_assert(!std::is_invocable_v<Func, HInstruction*>,
+                  "Use on generic HInstruction not allowed");
+#define STATIC_ASSERT_ABSTRACT(nm, unused) && !std::is_invocable_v<Func, H##nm*>
+    static_assert(true FOR_EACH_ABSTRACT_INSTRUCTION(STATIC_ASSERT_ABSTRACT),
+                  "Must not be abstract instruction");
+#undef STATIC_ASSERT_ABSTRACT
+#define STATIC_ASSERT_CONCRETE(nm, unused) || std::is_invocable_v<Func, H##nm*>
+    static_assert(false FOR_EACH_CONCRETE_INSTRUCTION(STATIC_ASSERT_CONCRETE),
+                  "Must be a concrete instruction");
+#undef STATIC_ASSERT_CONCRETE
+    return HInstruction::InstructionKind::kLastInstructionKind;
+  }
+  template <typename First>
+  void FillHandlers(First h1) {
+    HInstruction::InstructionKind type = GetKind<First>();
+    CHECK_NE(type, HInstruction::kLastInstructionKind)
+        << "Unknown instruction kind. Only concrete ones please.";
+    handlers_[type] = GetWrapper(type, h1);
+  }
+
+  template <typename First, typename... Inst>
+  void FillHandlers(First h1, Inst... handlers) {
+    FillHandlers(h1);
+    FillHandlers<Inst...>(handlers...);
+  }
+
+  std::array<std::unique_ptr<HandlerWrapper>, HInstruction::InstructionKind::kLastInstructionKind>
+      handlers_;
+};
+
+template <typename... Target>
+std::tuple<std::vector<Target*>...> FindAllInstructions(
+    HGraph* graph,
+    std::variant<std::nullopt_t, HBasicBlock*, std::initializer_list<HBasicBlock*>> blks =
+        std::nullopt) {
+  std::tuple<std::vector<Target*>...> res;
+  PatternMatchGraphVisitor vis(
+      graph, [&](Target* t) { std::get<std::vector<Target*>>(res).push_back(t); }...);
+
+  if (std::holds_alternative<std::initializer_list<HBasicBlock*>>(blks)) {
+    for (HBasicBlock* blk : std::get<std::initializer_list<HBasicBlock*>>(blks)) {
+      vis.VisitBasicBlock(blk);
+    }
+  } else if (std::holds_alternative<std::nullopt_t>(blks)) {
+    vis.VisitInsertionOrder();
+  } else {
+    vis.VisitBasicBlock(std::get<HBasicBlock*>(blks));
+  }
+  return res;
+}
+
+template <typename... Target>
+std::tuple<Target*...> FindSingleInstructions(
+    HGraph* graph,
+    std::variant<std::nullopt_t, HBasicBlock*, std::initializer_list<HBasicBlock*>> blks =
+        std::nullopt) {
+  std::tuple<Target*...> res;
+  PatternMatchGraphVisitor vis(graph, [&](Target* t) {
+    EXPECT_EQ(std::get<Target*>(res), nullptr)
+        << *std::get<Target*>(res) << " already found but found " << *t << "!";
+    std::get<Target*>(res) = t;
+  }...);
+  if (std::holds_alternative<std::initializer_list<HBasicBlock*>>(blks)) {
+    for (HBasicBlock* blk : std::get<std::initializer_list<HBasicBlock*>>(blks)) {
+      vis.VisitBasicBlock(blk);
+    }
+  } else if (std::holds_alternative<std::nullopt_t>(blks)) {
+    vis.VisitInsertionOrder();
+  } else {
+    vis.VisitBasicBlock(std::get<HBasicBlock*>(blks));
+  }
+  return res;
+}
+
+template <typename Target>
+Target* FindSingleInstruction(
+    HGraph* graph,
+    std::variant<std::nullopt_t, HBasicBlock*, std::initializer_list<HBasicBlock*>> blks =
+        std::nullopt) {
+  return std::get<Target*>(FindSingleInstructions<Target>(graph, blks));
+}
+
 }  // namespace art
 
 #endif  // ART_COMPILER_OPTIMIZING_OPTIMIZING_UNIT_TEST_H_
diff --git a/compiler/optimizing/pc_relative_fixups_x86.cc b/compiler/optimizing/pc_relative_fixups_x86.cc
index 1d8d1a6..17f37f0 100644
--- a/compiler/optimizing/pc_relative_fixups_x86.cc
+++ b/compiler/optimizing/pc_relative_fixups_x86.cc
@@ -195,15 +195,6 @@
   void HandleInvoke(HInvoke* invoke) {
     HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect();
 
-    // We can't add the method address if we already have a current method pointer.
-    // This may arise when sharpening doesn't remove the current method pointer from the invoke.
-    if (invoke_static_or_direct != nullptr && invoke_static_or_direct->HasCurrentMethodInput()) {
-      // Note: This happens only for recursive calls (including compiling an intrinsic
-      // by faking a call to itself; we use kRuntimeCall for this case).
-      DCHECK(!invoke_static_or_direct->HasPcRelativeMethodLoadKind());
-      return;
-    }
-
     // If this is an invoke-static/-direct with PC-relative addressing (within boot image
     // or using .bss or .data.bimg.rel.ro), we need the PC-relative address base.
     bool base_added = false;
@@ -216,6 +207,15 @@
       base_added = true;
     }
 
+    HInvokeInterface* invoke_interface = invoke->AsInvokeInterface();
+    if (invoke_interface != nullptr &&
+        IsPcRelativeMethodLoadKind(invoke_interface->GetHiddenArgumentLoadKind())) {
+      HX86ComputeBaseMethodAddress* method_address = GetPCRelativeBasePointer(invoke);
+      // Add the extra parameter.
+      invoke_interface->AddSpecialInput(method_address);
+      base_added = true;
+    }
+
     // Ensure that we can load FP arguments from the constant area.
     HInputsRef inputs = invoke->GetInputs();
     for (size_t i = 0; i < inputs.size(); i++) {
@@ -226,6 +226,15 @@
     }
 
     switch (invoke->GetIntrinsic()) {
+      case Intrinsics::kMathAbsDouble:
+      case Intrinsics::kMathAbsFloat:
+      case Intrinsics::kMathMaxDoubleDouble:
+      case Intrinsics::kMathMaxFloatFloat:
+      case Intrinsics::kMathMinDoubleDouble:
+      case Intrinsics::kMathMinFloatFloat:
+        LOG(FATAL) << "Unreachable min/max/abs: intrinsics should have been lowered "
+                      "to IR nodes by instruction simplifier";
+        UNREACHABLE();
       case Intrinsics::kIntegerValueOf:
         // This intrinsic can be call free if it loads the address of the boot image object.
         // If we're compiling PIC, we need the address base for loading from .data.bimg.rel.ro.
@@ -237,7 +246,6 @@
         // This intrinsic needs the constant area.
         if (!base_added) {
           DCHECK(invoke_static_or_direct != nullptr);
-          DCHECK(!invoke_static_or_direct->HasCurrentMethodInput());
           HX86ComputeBaseMethodAddress* method_address = GetPCRelativeBasePointer(invoke);
           invoke_static_or_direct->AddSpecialInput(method_address);
         }
diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc
index 8c4615d..c2f3d0e 100644
--- a/compiler/optimizing/prepare_for_register_allocation.cc
+++ b/compiler/optimizing/prepare_for_register_allocation.cc
@@ -166,7 +166,6 @@
     }
   } else if (can_merge_with_load_class &&
              load_class->GetLoadKind() != HLoadClass::LoadKind::kRuntimeCall) {
-    DCHECK(!load_class->NeedsAccessCheck());
     // Pass the initialization duty to the `HLoadClass` instruction,
     // and remove the instruction from the graph.
     DCHECK(load_class->HasEnvironment());
@@ -269,6 +268,10 @@
     return false;
   }
 
+  if (user->IsNewInstance() && user->AsNewInstance()->IsPartialMaterialization()) {
+    return false;
+  }
+
   // Now do a thorough environment check that this is really coming from the same instruction in
   // the same inlined graph. Unfortunately, we have to go through the whole environment chain.
   HEnvironment* user_environment = user->GetEnvironment();
@@ -297,8 +300,8 @@
   if (kIsDebugBuild) {
     for (HInstruction* between = input->GetNext(); between != user; between = between->GetNext()) {
       CHECK(between != nullptr);  // User must be after input in the same block.
-      CHECK(!between->CanThrow());
-      CHECK(!between->HasSideEffects());
+      CHECK(!between->CanThrow()) << *between << " User: " << *user;
+      CHECK(!between->HasSideEffects()) << *between << " User: " << *user;
     }
   }
   return true;
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 4929e0a..1b2f71f 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -18,11 +18,12 @@
 
 #include "art_field-inl.h"
 #include "art_method-inl.h"
+#include "base/arena_allocator.h"
+#include "base/enums.h"
 #include "base/scoped_arena_allocator.h"
 #include "base/scoped_arena_containers.h"
-#include "base/enums.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "handle_scope-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
@@ -40,54 +41,15 @@
   }
 }
 
-static inline ReferenceTypeInfo::TypeHandle GetRootHandle(VariableSizedHandleScope* handles,
-                                                          ClassRoot class_root,
-                                                          ReferenceTypeInfo::TypeHandle* cache) {
-  if (!ReferenceTypeInfo::IsValidHandle(*cache)) {
-    // Mutator lock is required for NewHandle.
-    ScopedObjectAccess soa(Thread::Current());
-    *cache = handles->NewHandle(GetClassRoot(class_root));
-  }
-  return *cache;
-}
-
-ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetObjectClassHandle() {
-  return GetRootHandle(handles_, ClassRoot::kJavaLangObject, &object_class_handle_);
-}
-
-ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetClassClassHandle() {
-  return GetRootHandle(handles_, ClassRoot::kJavaLangClass, &class_class_handle_);
-}
-
-ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetMethodHandleClassHandle() {
-  return GetRootHandle(handles_,
-                       ClassRoot::kJavaLangInvokeMethodHandleImpl,
-                       &method_handle_class_handle_);
-}
-
-ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetMethodTypeClassHandle() {
-  return GetRootHandle(handles_, ClassRoot::kJavaLangInvokeMethodType, &method_type_class_handle_);
-}
-
-ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetStringClassHandle() {
-  return GetRootHandle(handles_, ClassRoot::kJavaLangString, &string_class_handle_);
-}
-
-ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetThrowableClassHandle() {
-  return GetRootHandle(handles_, ClassRoot::kJavaLangThrowable, &throwable_class_handle_);
-}
-
 class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor {
  public:
   RTPVisitor(HGraph* graph,
              Handle<mirror::ClassLoader> class_loader,
              Handle<mirror::DexCache> hint_dex_cache,
-             HandleCache* handle_cache,
              bool is_first_run)
     : HGraphDelegateVisitor(graph),
       class_loader_(class_loader),
       hint_dex_cache_(hint_dex_cache),
-      handle_cache_(handle_cache),
       allocator_(graph->GetArenaStack()),
       worklist_(allocator_.Adapter(kArenaAllocReferenceTypePropagation)),
       is_first_run_(is_first_run) {
@@ -105,6 +67,7 @@
   void VisitLoadException(HLoadException* instr) override;
   void VisitNewArray(HNewArray* instr) override;
   void VisitParameterValue(HParameterValue* instr) override;
+  void VisitPredicatedInstanceFieldGet(HPredicatedInstanceFieldGet* instr) override;
   void VisitInstanceFieldGet(HInstanceFieldGet* instr) override;
   void VisitStaticFieldGet(HStaticFieldGet* instr) override;
   void VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet* instr) override;
@@ -135,37 +98,43 @@
                                const DexFile& dex_file,
                                bool is_exact);
 
+  // Returns true if this is an instruction we might need to recursively update.
+  // The types are (live) Phi, BoundType, ArrayGet, and NullCheck
+  static constexpr bool IsUpdateable(const HInstruction* instr);
   void AddToWorklist(HInstruction* instruction);
   void AddDependentInstructionsToWorklist(HInstruction* instruction);
 
+  HandleCache* GetHandleCache() {
+    return GetGraph()->GetHandleCache();
+  }
+
   static constexpr size_t kDefaultWorklistSize = 8;
 
   Handle<mirror::ClassLoader> class_loader_;
   Handle<mirror::DexCache> hint_dex_cache_;
-  HandleCache* const handle_cache_;
 
   // Use local allocator for allocating memory.
   ScopedArenaAllocator allocator_;
   ScopedArenaVector<HInstruction*> worklist_;
   const bool is_first_run_;
+
+  friend class ReferenceTypePropagation;
 };
 
 ReferenceTypePropagation::ReferenceTypePropagation(HGraph* graph,
                                                    Handle<mirror::ClassLoader> class_loader,
                                                    Handle<mirror::DexCache> hint_dex_cache,
-                                                   VariableSizedHandleScope* handles,
                                                    bool is_first_run,
                                                    const char* name)
     : HOptimization(graph, name),
       class_loader_(class_loader),
       hint_dex_cache_(hint_dex_cache),
-      handle_cache_(handles),
       is_first_run_(is_first_run) {
 }
 
 void ReferenceTypePropagation::ValidateTypes() {
-  // TODO: move this to the graph checker.
-  if (kIsDebugBuild) {
+  // TODO: move this to the graph checker. Note: There may be no Thread for gtests.
+  if (kIsDebugBuild && Thread::Current() != nullptr) {
     ScopedObjectAccess soa(Thread::Current());
     for (HBasicBlock* block : graph_->GetReversePostOrder()) {
       for (HInstructionIterator iti(block->GetInstructions()); !iti.Done(); iti.Advance()) {
@@ -200,11 +169,32 @@
   RTPVisitor visitor(graph_,
                      class_loader_,
                      hint_dex_cache_,
-                     &handle_cache_,
                      is_first_run_);
   instruction->Accept(&visitor);
 }
 
+void ReferenceTypePropagation::Visit(ArrayRef<HInstruction* const> instructions) {
+  RTPVisitor visitor(graph_,
+                     class_loader_,
+                     hint_dex_cache_,
+                     is_first_run_);
+  for (HInstruction* instruction : instructions) {
+    if (instruction->IsPhi()) {
+      // Need to force phis to recalculate null-ness.
+      instruction->AsPhi()->SetCanBeNull(false);
+    }
+  }
+  for (HInstruction* instruction : instructions) {
+    instruction->Accept(&visitor);
+    // We don't know if the instruction list is ordered in the same way normal
+    // visiting would be so we need to process every instruction manually.
+    if (RTPVisitor::IsUpdateable(instruction)) {
+      visitor.AddToWorklist(instruction);
+    }
+  }
+  visitor.ProcessWorklist();
+}
+
 // Check if we should create a bound type for the given object at the specified
 // position. Because of inlining and the fact we run RTP more than once and we
 // might have a HBoundType already. If we do, we should not create a new one.
@@ -324,10 +314,8 @@
     return;
   }
 
-  HInstanceFieldGet* field_get = (load_class == input_one)
-      ? input_two->AsInstanceFieldGet()
-      : input_one->AsInstanceFieldGet();
-  if (field_get == nullptr) {
+  HInstruction* field_get = (load_class == input_one) ? input_two : input_one;
+  if (!field_get->IsInstanceFieldGet() && !field_get->IsPredicatedInstanceFieldGet()) {
     return;
   }
   HInstruction* receiver = field_get->InputAt(0);
@@ -360,7 +348,7 @@
 }
 
 bool ReferenceTypePropagation::Run() {
-  RTPVisitor visitor(graph_, class_loader_, hint_dex_cache_, &handle_cache_, is_first_run_);
+  RTPVisitor visitor(graph_, class_loader_, hint_dex_cache_, is_first_run_);
 
   // To properly propagate type info we need to visit in the dominator-based order.
   // Reverse post order guarantees a node's dominators are visited first.
@@ -426,8 +414,8 @@
       ? ifInstruction->IfTrueSuccessor()
       : ifInstruction->IfFalseSuccessor();
 
-  ReferenceTypeInfo object_rti = ReferenceTypeInfo::Create(
-      handle_cache_->GetObjectClassHandle(), /* is_exact= */ false);
+  ReferenceTypeInfo object_rti =
+      ReferenceTypeInfo::Create(GetHandleCache()->GetObjectClassHandle(), /* is_exact= */ false);
 
   BoundTypeIn(obj, notNullBlock, /* start_instruction= */ nullptr, object_rti);
 }
@@ -520,7 +508,7 @@
 
   ReferenceTypeInfo class_rti = instanceOf->GetTargetClassRTI();
   if (!class_rti.IsValid()) {
-    // He have loaded an unresolved class. Don't bother bounding the type.
+    // We have loaded an unresolved class. Don't bother bounding the type.
     return;
   }
 
@@ -554,8 +542,8 @@
       ClassLinker* cl = Runtime::Current()->GetClassLinker();
       Thread* self = Thread::Current();
       StackHandleScope<2> hs(self);
-      const DexFile& dex_file = *invoke->GetTargetMethod().dex_file;
-      uint32_t dex_method_index = invoke->GetTargetMethod().index;
+      const DexFile& dex_file = *invoke->GetResolvedMethodReference().dex_file;
+      uint32_t dex_method_index = invoke->GetResolvedMethodReference().index;
       Handle<mirror::DexCache> dex_cache(
           hs.NewHandle(FindDexCacheWithHint(self, dex_file, hint_dex_cache_)));
       // Use a null loader, the target method is in a boot classpath dex file.
@@ -571,13 +559,13 @@
           << "Expected String.<init>: " << method->PrettyMethod();
     }
     instr->SetReferenceTypeInfo(
-        ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact= */ true));
+        ReferenceTypeInfo::Create(GetHandleCache()->GetStringClassHandle(), /* is_exact= */ true));
   } else if (IsAdmissible(klass)) {
-    ReferenceTypeInfo::TypeHandle handle = handle_cache_->NewHandle(klass);
+    ReferenceTypeInfo::TypeHandle handle = GetHandleCache()->NewHandle(klass);
     is_exact = is_exact || handle->CannotBeAssignedFromOtherTypes();
     instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, is_exact));
   } else {
-    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
+    instr->SetReferenceTypeInfo(GetGraph()->GetInexactObjectRti());
   }
 }
 
@@ -635,6 +623,11 @@
   SetClassAsTypeInfo(instr, klass, /* is_exact= */ false);
 }
 
+void ReferenceTypePropagation::RTPVisitor::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* instr) {
+  UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
+}
+
 void ReferenceTypePropagation::RTPVisitor::VisitInstanceFieldGet(HInstanceFieldGet* instr) {
   UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
 }
@@ -647,7 +640,7 @@
     HUnresolvedInstanceFieldGet* instr) {
   // TODO: Use descriptor to get the actual type.
   if (instr->GetFieldType() == DataType::Type::kReference) {
-    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
+    instr->SetReferenceTypeInfo(GetGraph()->GetInexactObjectRti());
   }
 }
 
@@ -655,7 +648,7 @@
     HUnresolvedStaticFieldGet* instr) {
   // TODO: Use descriptor to get the actual type.
   if (instr->GetFieldType() == DataType::Type::kReference) {
-    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
+    instr->SetReferenceTypeInfo(GetGraph()->GetInexactObjectRti());
   }
 }
 
@@ -665,7 +658,7 @@
     instr->SetValidLoadedClassRTI();
   }
   instr->SetReferenceTypeInfo(
-      ReferenceTypeInfo::Create(handle_cache_->GetClassClassHandle(), /* is_exact= */ true));
+      ReferenceTypeInfo::Create(GetHandleCache()->GetClassClassHandle(), /* is_exact= */ true));
 }
 
 void ReferenceTypePropagation::RTPVisitor::VisitInstanceOf(HInstanceOf* instr) {
@@ -681,18 +674,17 @@
 
 void ReferenceTypePropagation::RTPVisitor::VisitLoadMethodHandle(HLoadMethodHandle* instr) {
   instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(
-      handle_cache_->GetMethodHandleClassHandle(),
-      /* is_exact= */ true));
+      GetHandleCache()->GetMethodHandleClassHandle(), /* is_exact= */ true));
 }
 
 void ReferenceTypePropagation::RTPVisitor::VisitLoadMethodType(HLoadMethodType* instr) {
-  instr->SetReferenceTypeInfo(
-      ReferenceTypeInfo::Create(handle_cache_->GetMethodTypeClassHandle(), /* is_exact= */ true));
+  instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(
+      GetHandleCache()->GetMethodTypeClassHandle(), /* is_exact= */ true));
 }
 
 void ReferenceTypePropagation::RTPVisitor::VisitLoadString(HLoadString* instr) {
   instr->SetReferenceTypeInfo(
-      ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact= */ true));
+      ReferenceTypeInfo::Create(GetHandleCache()->GetStringClassHandle(), /* is_exact= */ true));
 }
 
 void ReferenceTypePropagation::RTPVisitor::VisitLoadException(HLoadException* instr) {
@@ -705,8 +697,8 @@
                             catch_info->GetCatchDexFile(),
                             /* is_exact= */ false);
   } else {
-    instr->SetReferenceTypeInfo(
-        ReferenceTypeInfo::Create(handle_cache_->GetThrowableClassHandle(), /* is_exact= */ false));
+    instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(
+        GetHandleCache()->GetThrowableClassHandle(), /* is_exact= */ false));
   }
 }
 
@@ -805,14 +797,13 @@
 }
 
 void ReferenceTypePropagation::FixUpInstructionType(HInstruction* instruction,
-                                                    VariableSizedHandleScope* handle_scope) {
+                                                    HandleCache* handle_cache) {
   if (instruction->IsSelect()) {
     ScopedObjectAccess soa(Thread::Current());
-    HandleCache handle_cache(handle_scope);
     HSelect* select = instruction->AsSelect();
     ReferenceTypeInfo false_rti = select->GetFalseValue()->GetReferenceTypeInfo();
     ReferenceTypeInfo true_rti = select->GetTrueValue()->GetReferenceTypeInfo();
-    select->SetReferenceTypeInfo(MergeTypes(false_rti, true_rti, &handle_cache));
+    select->SetReferenceTypeInfo(MergeTypes(false_rti, true_rti, handle_cache));
   } else {
     LOG(FATAL) << "Invalid instruction in FixUpInstructionType";
   }
@@ -873,12 +864,12 @@
   Handle<mirror::Class> handle = parent_rti.GetTypeHandle();
   if (handle->IsObjectArrayClass() && IsAdmissible(handle->GetComponentType())) {
     ReferenceTypeInfo::TypeHandle component_handle =
-        handle_cache_->NewHandle(handle->GetComponentType());
+        GetHandleCache()->NewHandle(handle->GetComponentType());
     bool is_exact = component_handle->CannotBeAssignedFromOtherTypes();
     instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(component_handle, is_exact));
   } else {
     // We don't know what the parent actually is, so we fallback to object.
-    instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti());
+    instr->SetReferenceTypeInfo(GetGraph()->GetInexactObjectRti());
   }
 }
 
@@ -912,6 +903,8 @@
   }
 
   ScopedObjectAccess soa(Thread::Current());
+  // FIXME: Treat InvokePolymorphic separately, as we can get a more specific return type from
+  // protoId than the one obtained from the resolved method.
   ArtMethod* method = instr->GetResolvedMethod();
   ObjPtr<mirror::Class> klass = (method == nullptr) ? nullptr : method->LookupResolvedReturnType();
   SetClassAsTypeInfo(instr, klass, /* is_exact= */ false);
@@ -981,7 +974,7 @@
     if (inputs[i]->IsNullConstant()) {
       continue;
     }
-    new_rti = MergeTypes(new_rti, inputs[i]->GetReferenceTypeInfo(), handle_cache_);
+    new_rti = MergeTypes(new_rti, inputs[i]->GetReferenceTypeInfo(), GetHandleCache());
     if (new_rti.IsValid() && new_rti.IsObjectClass()) {
       if (!new_rti.IsExact()) {
         break;
@@ -996,13 +989,17 @@
   }
 }
 
+constexpr bool ReferenceTypePropagation::RTPVisitor::IsUpdateable(const HInstruction* instr) {
+  return (instr->IsPhi() && instr->AsPhi()->IsLive()) ||
+         instr->IsBoundType() ||
+         instr->IsNullCheck() ||
+         instr->IsArrayGet();
+}
+
 // Re-computes and updates the nullability of the instruction. Returns whether or
 // not the nullability was changed.
 bool ReferenceTypePropagation::RTPVisitor::UpdateNullability(HInstruction* instr) {
-  DCHECK((instr->IsPhi() && instr->AsPhi()->IsLive())
-      || instr->IsBoundType()
-      || instr->IsNullCheck()
-      || instr->IsArrayGet());
+  DCHECK(IsUpdateable(instr));
 
   if (!instr->IsPhi() && !instr->IsBoundType()) {
     return false;
diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h
index 7c6a048..889a846 100644
--- a/compiler/optimizing/reference_type_propagation.h
+++ b/compiler/optimizing/reference_type_propagation.h
@@ -33,21 +33,27 @@
   ReferenceTypePropagation(HGraph* graph,
                            Handle<mirror::ClassLoader> class_loader,
                            Handle<mirror::DexCache> hint_dex_cache,
-                           VariableSizedHandleScope* handles,
                            bool is_first_run,
                            const char* name = kReferenceTypePropagationPassName);
 
   // Visit a single instruction.
+  // Used when a pass, such as Inliner or LSE, adds a single instruction.
   void Visit(HInstruction* instruction);
 
+  // Visit instructions and process dependencies between them.
+  // Used when a pass, such as LSE, adds multiple dependent instructions, including Phis.
+  void Visit(ArrayRef<HInstruction* const> instructions);
+
   bool Run() override;
 
   // Returns true if klass is admissible to the propagation: non-null and resolved.
   // For an array type, we also check if the component type is admissible.
   static bool IsAdmissible(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
-    return klass != nullptr &&
-           klass->IsResolved() &&
-           (!klass->IsArrayClass() || IsAdmissible(klass->GetComponentType()));
+    while (klass != nullptr && klass->IsArrayClass()) {
+      DCHECK(klass->IsResolved());
+      klass = klass->GetComponentType();
+    }
+    return klass != nullptr && klass->IsResolved();
   }
 
   static constexpr const char* kReferenceTypePropagationPassName = "reference_type_propagation";
@@ -55,42 +61,9 @@
   // Fix the reference type for an instruction whose inputs have changed.
   // For a select instruction, the reference types of the inputs are merged
   // and the resulting reference type is set on the select instruction.
-  static void FixUpInstructionType(HInstruction* instruction,
-                                   VariableSizedHandleScope* handle_scope);
+  static void FixUpInstructionType(HInstruction* instruction, HandleCache* handle_cache);
 
  private:
-  class HandleCache {
-   public:
-    explicit HandleCache(VariableSizedHandleScope* handles) : handles_(handles) { }
-
-    template <typename T>
-    MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_) {
-      return handles_->NewHandle(object);
-    }
-
-    template <typename T>
-    MutableHandle<T> NewHandle(ObjPtr<T> object) REQUIRES_SHARED(Locks::mutator_lock_) {
-      return handles_->NewHandle(object);
-    }
-
-    ReferenceTypeInfo::TypeHandle GetObjectClassHandle();
-    ReferenceTypeInfo::TypeHandle GetClassClassHandle();
-    ReferenceTypeInfo::TypeHandle GetMethodHandleClassHandle();
-    ReferenceTypeInfo::TypeHandle GetMethodTypeClassHandle();
-    ReferenceTypeInfo::TypeHandle GetStringClassHandle();
-    ReferenceTypeInfo::TypeHandle GetThrowableClassHandle();
-
-   private:
-    VariableSizedHandleScope* handles_;
-
-    ReferenceTypeInfo::TypeHandle object_class_handle_;
-    ReferenceTypeInfo::TypeHandle class_class_handle_;
-    ReferenceTypeInfo::TypeHandle method_handle_class_handle_;
-    ReferenceTypeInfo::TypeHandle method_type_class_handle_;
-    ReferenceTypeInfo::TypeHandle string_class_handle_;
-    ReferenceTypeInfo::TypeHandle throwable_class_handle_;
-  };
-
   class RTPVisitor;
 
   static ReferenceTypeInfo MergeTypes(const ReferenceTypeInfo& a,
@@ -106,12 +79,12 @@
   // graph_->GetDexFile(). Since we may look up also in other dex files, it's used only
   // as a hint, to reduce the number of calls to the costly ClassLinker::FindDexCache().
   Handle<mirror::DexCache> hint_dex_cache_;
-  HandleCache handle_cache_;
 
   // Whether this reference type propagation is the first run we are doing.
   const bool is_first_run_;
 
-  friend class ReferenceTypePropagationTest;
+  template<typename T>
+  friend class ReferenceTypePropagationTestBase;
 
   DISALLOW_COPY_AND_ASSIGN(ReferenceTypePropagation);
 };
diff --git a/compiler/optimizing/reference_type_propagation_test.cc b/compiler/optimizing/reference_type_propagation_test.cc
index 028b6d3b7..d90567a 100644
--- a/compiler/optimizing/reference_type_propagation_test.cc
+++ b/compiler/optimizing/reference_type_propagation_test.cc
@@ -16,7 +16,11 @@
 
 #include "reference_type_propagation.h"
 
+#include <random>
+
 #include "base/arena_allocator.h"
+#include "base/transform_array_ref.h"
+#include "base/transform_iterator.h"
 #include "builder.h"
 #include "nodes.h"
 #include "object_lock.h"
@@ -24,22 +28,26 @@
 
 namespace art {
 
+// TODO It would be good to use the following but there is a miniscule amount of
+// chance for flakiness so we'll just use a set seed instead.
+constexpr bool kUseTrueRandomness = false;
+
 /**
  * Fixture class for unit testing the ReferenceTypePropagation phase. Used to verify the
  * functionality of methods and situations that are hard to set up with checker tests.
  */
-class ReferenceTypePropagationTest : public OptimizingUnitTest {
+template<typename SuperTest>
+class ReferenceTypePropagationTestBase : public SuperTest, public OptimizingUnitTestHelper {
  public:
-  ReferenceTypePropagationTest() : graph_(CreateGraph()), propagation_(nullptr) { }
+  ReferenceTypePropagationTestBase() : graph_(nullptr), propagation_(nullptr) { }
 
-  ~ReferenceTypePropagationTest() { }
+  ~ReferenceTypePropagationTestBase() { }
 
   void SetupPropagation(VariableSizedHandleScope* handles) {
-    graph_->InitializeInexactObjectRTI(handles);
+    graph_ = CreateGraph(handles);
     propagation_ = new (GetAllocator()) ReferenceTypePropagation(graph_,
                                                                  Handle<mirror::ClassLoader>(),
                                                                  Handle<mirror::DexCache>(),
-                                                                 handles,
                                                                  true,
                                                                  "test_prop");
   }
@@ -47,7 +55,7 @@
   // Relay method to merge type in reference type propagation.
   ReferenceTypeInfo MergeTypes(const ReferenceTypeInfo& a,
                                const ReferenceTypeInfo& b) REQUIRES_SHARED(Locks::mutator_lock_) {
-    return propagation_->MergeTypes(a, b, &propagation_->handle_cache_);
+    return propagation_->MergeTypes(a, b, graph_->GetHandleCache());
   }
 
   // Helper method to construct an invalid type.
@@ -57,12 +65,12 @@
 
   // Helper method to construct the Object type.
   ReferenceTypeInfo ObjectType(bool is_exact = true) REQUIRES_SHARED(Locks::mutator_lock_) {
-    return ReferenceTypeInfo::Create(propagation_->handle_cache_.GetObjectClassHandle(), is_exact);
+    return ReferenceTypeInfo::Create(graph_->GetHandleCache()->GetObjectClassHandle(), is_exact);
   }
 
   // Helper method to construct the String type.
   ReferenceTypeInfo StringType(bool is_exact = true) REQUIRES_SHARED(Locks::mutator_lock_) {
-    return ReferenceTypeInfo::Create(propagation_->handle_cache_.GetStringClassHandle(), is_exact);
+    return ReferenceTypeInfo::Create(graph_->GetHandleCache()->GetStringClassHandle(), is_exact);
   }
 
   // General building fields.
@@ -71,6 +79,95 @@
   ReferenceTypePropagation* propagation_;
 };
 
+class ReferenceTypePropagationTest : public ReferenceTypePropagationTestBase<CommonCompilerTest> {};
+
+enum class ShuffleOrder {
+  kTopological,
+  kReverseTopological,
+  kAlmostTopological,
+  kTrueRandom,
+  kRandomSetSeed,
+
+  kRandom = kUseTrueRandomness ? kTrueRandom : kRandomSetSeed,
+};
+
+std::ostream& operator<<(std::ostream& os, ShuffleOrder so) {
+  switch (so) {
+    case ShuffleOrder::kAlmostTopological:
+      return os << "AlmostTopological";
+    case ShuffleOrder::kReverseTopological:
+      return os << "ReverseTopological";
+    case ShuffleOrder::kTopological:
+      return os << "Topological";
+    case ShuffleOrder::kTrueRandom:
+      return os << "TrueRandom";
+    case ShuffleOrder::kRandomSetSeed:
+      return os << "RandomSetSeed";
+  }
+}
+
+template <typename Param>
+class ParamReferenceTypePropagationTest
+    : public ReferenceTypePropagationTestBase<CommonCompilerTestWithParam<Param>> {
+ public:
+  void MutateList(std::vector<HInstruction*>& lst, ShuffleOrder type);
+};
+
+class NonLoopReferenceTypePropagationTestGroup
+    : public ParamReferenceTypePropagationTest<ShuffleOrder> {
+ public:
+  template <typename Func>
+  void RunVisitListTest(Func mutator);
+};
+
+enum class InitialNullState {
+  kAllNull,
+  kAllNonNull,
+  kHalfNull,
+  kTrueRandom,
+  kRandomSetSeed,
+
+  kRandom = kUseTrueRandomness ? kTrueRandom : kRandomSetSeed,
+};
+
+std::ostream& operator<<(std::ostream& os, InitialNullState ni) {
+  switch (ni) {
+    case InitialNullState::kAllNull:
+      return os << "AllNull";
+    case InitialNullState::kAllNonNull:
+      return os << "AllNonNull";
+    case InitialNullState::kHalfNull:
+      return os << "HalfNull";
+    case InitialNullState::kTrueRandom:
+      return os << "TrueRandom";
+    case InitialNullState::kRandomSetSeed:
+      return os << "RandomSetSeed";
+  }
+}
+
+struct LoopOptions {
+ public:
+  using GtestParam = std::tuple<ShuffleOrder, ssize_t, size_t, InitialNullState>;
+  explicit LoopOptions(GtestParam in) {
+    std::tie(shuffle_, null_insertion_, null_phi_arg_, initial_null_state_) = in;
+  }
+
+  ShuffleOrder shuffle_;
+  // Where in the list of phis we put the null. -1 if don't insert
+  ssize_t null_insertion_;
+  // Where in the phi arg-list we put the null.
+  size_t null_phi_arg_;
+  // What to set the initial null-state of all the phis to.
+  InitialNullState initial_null_state_;
+};
+
+class LoopReferenceTypePropagationTestGroup
+    : public ParamReferenceTypePropagationTest<LoopOptions::GtestParam> {
+ public:
+  template <typename Func>
+  void RunVisitListTest(Func mutator);
+};
+
 //
 // The actual ReferenceTypePropgation unit tests.
 //
@@ -158,4 +255,269 @@
   EXPECT_TRUE(t7.IsEqual(ObjectType(false)));
 }
 
+// This generates a large graph with a ton of phis including loop-phis. It then
+// calls the 'mutator' function with the list of all the phis and a CanBeNull
+// instruction and then tries to propagate the types. mutator should reorder the
+// list in some way and modify some phis in whatever way it wants. We verify
+// everything worked by making sure every phi has valid type information.
+template <typename Func>
+void LoopReferenceTypePropagationTestGroup::RunVisitListTest(Func mutator) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope handles(soa.Self());
+  SetupPropagation(&handles);
+  // Make a well-connected graph with a lot of edges.
+  constexpr size_t kNumBlocks = 100;
+  constexpr size_t kTestMaxSuccessors = 3;
+  std::vector<std::string> mid_blocks;
+  for (auto i : Range(kNumBlocks)) {
+    std::ostringstream oss;
+    oss << "blk" << i;
+    mid_blocks.push_back(oss.str());
+  }
+  // Create the edge list.
+  std::vector<AdjacencyListGraph::Edge> edges;
+  for (auto cur : Range(kNumBlocks)) {
+    for (auto nxt : Range(cur + 1, std::min(cur + 1 + kTestMaxSuccessors, kNumBlocks))) {
+      edges.emplace_back(mid_blocks[cur], mid_blocks[nxt]);
+    }
+  }
+  // Add a loop.
+  edges.emplace_back("start", mid_blocks.front());
+  edges.emplace_back(mid_blocks.back(), mid_blocks.front());
+  edges.emplace_back(mid_blocks.front(), "exit");
+
+  AdjacencyListGraph alg(graph_, GetAllocator(), "start", "exit", edges);
+  std::unordered_map<HBasicBlock*, HInstruction*> single_value;
+  HInstruction* maybe_null_val = new (GetAllocator())
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kReference);
+  ASSERT_TRUE(maybe_null_val->CanBeNull());
+  // Setup the entry-block with the type to be propagated.
+  HInstruction* cls =
+      new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                      dex::TypeIndex(10),
+                                      graph_->GetDexFile(),
+                                      graph_->GetHandleCache()->GetObjectClassHandle(),
+                                      false,
+                                      0,
+                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+  single_value[alg.Get(mid_blocks.front())] = new_inst;
+  HBasicBlock* start = alg.Get("start");
+  start->AddInstruction(maybe_null_val);
+  start->AddInstruction(cls);
+  start->AddInstruction(new_inst);
+  new_inst->SetReferenceTypeInfo(ObjectType(true));
+  maybe_null_val->SetReferenceTypeInfo(ObjectType(true));
+  single_value[start] = new_inst;
+
+  // Setup all the other blocks with a single PHI
+  auto range = MakeIterationRange(mid_blocks);
+  auto succ_blocks = MakeTransformRange(range, [&](const auto& sv) { return alg.Get(sv); });
+  for (HBasicBlock* blk : succ_blocks) {
+    HPhi* phi_inst = new (GetAllocator()) HPhi(
+        GetAllocator(), kNoRegNumber, blk->GetPredecessors().size(), DataType::Type::kReference);
+    single_value[blk] = phi_inst;
+  }
+  for (HBasicBlock* blk : succ_blocks) {
+    HInstruction* my_val = single_value[blk];
+    for (const auto& [pred, index] : ZipCount(MakeIterationRange(blk->GetPredecessors()))) {
+      CHECK(single_value[pred] != nullptr) << pred->GetBlockId() << " " << alg.GetName(pred);
+      my_val->SetRawInputAt(index, single_value[pred]);
+    }
+  }
+  for (HBasicBlock* blk : succ_blocks) {
+    CHECK(single_value[blk]->IsPhi()) << blk->GetBlockId();
+    blk->AddPhi(single_value[blk]->AsPhi());
+  }
+  auto vals = MakeTransformRange(succ_blocks, [&](HBasicBlock* blk) {
+    DCHECK(single_value[blk]->IsPhi());
+    return single_value[blk];
+  });
+  std::vector<HInstruction*> ins(vals.begin(), vals.end());
+  CHECK(std::none_of(ins.begin(), ins.end(), [](auto x) { return x == nullptr; }));
+  mutator(ins, maybe_null_val);
+  propagation_->Visit(ArrayRef<HInstruction* const>(ins));
+  bool is_nullable = !maybe_null_val->GetUses().empty();
+  for (auto [blk, i] : single_value) {
+    if (blk == start) {
+      continue;
+    }
+    EXPECT_TRUE(i->GetReferenceTypeInfo().IsValid())
+        << i->GetId() << " blk: " << alg.GetName(i->GetBlock());
+    if (is_nullable) {
+      EXPECT_TRUE(i->CanBeNull());
+    } else {
+      EXPECT_FALSE(i->CanBeNull());
+    }
+  }
+}
+
+// This generates a large graph with a ton of phis. It then calls the 'mutator'
+// function with the list of all the phis and then tries to propagate the types.
+// mutator should reorder the list in some way. We verify everything worked by
+// making sure every phi has valid type information.
+template <typename Func>
+void NonLoopReferenceTypePropagationTestGroup::RunVisitListTest(Func mutator) {
+  ScopedObjectAccess soa(Thread::Current());
+  VariableSizedHandleScope handles(soa.Self());
+  SetupPropagation(&handles);
+  // Make a well-connected graph with a lot of edges.
+  constexpr size_t kNumBlocks = 5000;
+  constexpr size_t kTestMaxSuccessors = 2;
+  std::vector<std::string> mid_blocks;
+  for (auto i : Range(kNumBlocks)) {
+    std::ostringstream oss;
+    oss << "blk" << i;
+    mid_blocks.push_back(oss.str());
+  }
+  // Create the edge list.
+  std::vector<AdjacencyListGraph::Edge> edges;
+  for (auto cur : Range(kNumBlocks)) {
+    for (auto nxt : Range(cur + 1, std::min(cur + 1 + kTestMaxSuccessors, kNumBlocks))) {
+      edges.emplace_back(mid_blocks[cur], mid_blocks[nxt]);
+    }
+  }
+  AdjacencyListGraph alg(graph_, GetAllocator(), mid_blocks.front(), mid_blocks.back(), edges);
+  std::unordered_map<HBasicBlock*, HInstruction*> single_value;
+  // Setup the entry-block with the type to be propagated.
+  HInstruction* cls =
+      new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
+                                      dex::TypeIndex(10),
+                                      graph_->GetDexFile(),
+                                      graph_->GetHandleCache()->GetObjectClassHandle(),
+                                      false,
+                                      0,
+                                      false);
+  HInstruction* new_inst =
+      new (GetAllocator()) HNewInstance(cls,
+                                        0,
+                                        dex::TypeIndex(10),
+                                        graph_->GetDexFile(),
+                                        false,
+                                        QuickEntrypointEnum::kQuickAllocObjectInitialized);
+  single_value[alg.Get(mid_blocks.front())] = new_inst;
+  HBasicBlock* start = alg.Get(mid_blocks.front());
+  start->AddInstruction(cls);
+  start->AddInstruction(new_inst);
+  new_inst->SetReferenceTypeInfo(ObjectType(true));
+
+  // Setup all the other blocks with a single PHI
+  auto succ_blk_names = MakeIterationRange(mid_blocks.begin() + 1, mid_blocks.end());
+  auto succ_blocks =
+      MakeTransformRange(succ_blk_names, [&](const auto& sv) { return alg.Get(sv); });
+  for (HBasicBlock* blk : succ_blocks) {
+    HPhi* phi_inst = new (GetAllocator()) HPhi(
+        GetAllocator(), kNoRegNumber, blk->GetPredecessors().size(), DataType::Type::kReference);
+    single_value[blk] = phi_inst;
+  }
+  for (HBasicBlock* blk : succ_blocks) {
+    HInstruction* my_val = single_value[blk];
+    for (const auto& [pred, index] : ZipCount(MakeIterationRange(blk->GetPredecessors()))) {
+      my_val->SetRawInputAt(index, single_value[pred]);
+    }
+    blk->AddPhi(my_val->AsPhi());
+  }
+  auto vals = MakeTransformRange(succ_blocks, [&](HBasicBlock* blk) { return single_value[blk]; });
+  std::vector<HInstruction*> ins(vals.begin(), vals.end());
+  graph_->ClearReachabilityInformation();
+  graph_->ComputeReachabilityInformation();
+  mutator(ins);
+  propagation_->Visit(ArrayRef<HInstruction* const>(ins));
+  for (auto [blk, i] : single_value) {
+    if (blk == start) {
+      continue;
+    }
+    EXPECT_TRUE(i->GetReferenceTypeInfo().IsValid())
+        << i->GetId() << " blk: " << alg.GetName(i->GetBlock());
+  }
+}
+
+template <typename Param>
+void ParamReferenceTypePropagationTest<Param>::MutateList(std::vector<HInstruction*>& lst,
+                                                          ShuffleOrder type) {
+  DCHECK(std::none_of(lst.begin(), lst.end(), [](auto* i) { return i == nullptr; }));
+  std::default_random_engine g(type != ShuffleOrder::kTrueRandom ? 42 : std::rand());
+  switch (type) {
+    case ShuffleOrder::kTopological: {
+      // Input is topologically sorted due to the way we create the phis.
+      break;
+    }
+    case ShuffleOrder::kReverseTopological: {
+      std::reverse(lst.begin(), lst.end());
+      break;
+    }
+    case ShuffleOrder::kAlmostTopological: {
+      std::swap(lst.front(), lst.back());
+      break;
+    }
+    case ShuffleOrder::kRandomSetSeed:
+    case ShuffleOrder::kTrueRandom: {
+      std::shuffle(lst.begin(), lst.end(), g);
+      break;
+    }
+  }
+}
+
+TEST_P(LoopReferenceTypePropagationTestGroup, RunVisitTest) {
+  LoopOptions lo(GetParam());
+  std::default_random_engine g(
+      lo.initial_null_state_ != InitialNullState::kTrueRandom ? 42 : std::rand());
+  std::uniform_int_distribution<bool> uid(false, true);
+  RunVisitListTest([&](std::vector<HInstruction*>& lst, HInstruction* null_input) {
+    auto pred_null = false;
+    auto next_null = [&]() {
+      switch (lo.initial_null_state_) {
+        case InitialNullState::kAllNonNull:
+          return false;
+        case InitialNullState::kAllNull:
+          return true;
+        case InitialNullState::kHalfNull:
+          pred_null = !pred_null;
+          return pred_null;
+        case InitialNullState::kRandomSetSeed:
+        case InitialNullState::kTrueRandom:
+          return uid(g);
+      }
+    };
+    HPhi* nulled_phi = lo.null_insertion_ >= 0 ? lst[lo.null_insertion_]->AsPhi() : nullptr;
+    if (nulled_phi != nullptr) {
+      nulled_phi->ReplaceInput(null_input, lo.null_phi_arg_);
+    }
+    MutateList(lst, lo.shuffle_);
+    std::for_each(lst.begin(), lst.end(), [&](HInstruction* ins) {
+      ins->AsPhi()->SetCanBeNull(next_null());
+    });
+  });
+}
+
+INSTANTIATE_TEST_SUITE_P(ReferenceTypePropagationTest,
+                         LoopReferenceTypePropagationTestGroup,
+                         testing::Combine(testing::Values(ShuffleOrder::kAlmostTopological,
+                                                          ShuffleOrder::kReverseTopological,
+                                                          ShuffleOrder::kTopological,
+                                                          ShuffleOrder::kRandom),
+                                          testing::Values(-1, 10, 40),
+                                          testing::Values(0, 1),
+                                          testing::Values(InitialNullState::kAllNonNull,
+                                                          InitialNullState::kAllNull,
+                                                          InitialNullState::kHalfNull,
+                                                          InitialNullState::kRandom)));
+
+TEST_P(NonLoopReferenceTypePropagationTestGroup, RunVisitTest) {
+  RunVisitListTest([&](std::vector<HInstruction*>& lst) { MutateList(lst, GetParam()); });
+}
+
+INSTANTIATE_TEST_SUITE_P(ReferenceTypePropagationTest,
+                         NonLoopReferenceTypePropagationTestGroup,
+                         testing::Values(ShuffleOrder::kAlmostTopological,
+                                         ShuffleOrder::kReverseTopological,
+                                         ShuffleOrder::kTopological,
+                                         ShuffleOrder::kRandom));
+
 }  // namespace art
diff --git a/compiler/optimizing/register_allocation_resolver.cc b/compiler/optimizing/register_allocation_resolver.cc
index 1786048..670db42 100644
--- a/compiler/optimizing/register_allocation_resolver.cc
+++ b/compiler/optimizing/register_allocation_resolver.cc
@@ -303,12 +303,12 @@
       && !interval->GetDefinedBy()->IsCurrentMethod()) {
     // We spill eagerly, so move must be at definition.
     Location loc;
-    switch (interval->NumberOfSpillSlotsNeeded()) {
-      case 1: loc = Location::StackSlot(interval->GetParent()->GetSpillSlot()); break;
-      case 2: loc = Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot()); break;
-      case 4: loc = Location::SIMDStackSlot(interval->GetParent()->GetSpillSlot()); break;
-      default: LOG(FATAL) << "Unexpected number of spill slots"; UNREACHABLE();
-    }
+    size_t num_of_slots = interval->NumberOfSpillSlotsNeeded();
+    loc = Location::StackSlotByNumOfSlots(num_of_slots, interval->GetParent()->GetSpillSlot());
+
+    CHECK(!loc.IsSIMDStackSlot() ||
+          (codegen_->GetSIMDRegisterWidth() / kVRegSize == num_of_slots)) <<
+          "Unexpected number of spill slots";
     InsertMoveAfter(interval->GetDefinedBy(), interval->ToLocation(), loc);
   }
   UsePositionList::const_iterator use_it = current->GetUses().begin();
@@ -466,12 +466,11 @@
       location_source = defined_by->GetLocations()->Out();
     } else {
       DCHECK(defined_by->IsCurrentMethod());
-      switch (parent->NumberOfSpillSlotsNeeded()) {
-        case 1: location_source = Location::StackSlot(parent->GetSpillSlot()); break;
-        case 2: location_source = Location::DoubleStackSlot(parent->GetSpillSlot()); break;
-        case 4: location_source = Location::SIMDStackSlot(parent->GetSpillSlot()); break;
-        default: LOG(FATAL) << "Unexpected number of spill slots"; UNREACHABLE();
-      }
+      size_t num_of_slots = parent->NumberOfSpillSlotsNeeded();
+      location_source = Location::StackSlotByNumOfSlots(num_of_slots, parent->GetSpillSlot());
+      CHECK(!location_source.IsSIMDStackSlot() ||
+            (codegen_->GetSIMDRegisterWidth() == num_of_slots * kVRegSize)) <<
+            "Unexpected number of spill slots";
     }
   } else {
     DCHECK(source != nullptr);
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index 79eb082..6823155 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -41,9 +41,9 @@
 class RegisterAllocatorTest : public OptimizingUnitTest {
  protected:
   void SetUp() override {
-    // This test is using the x86 ISA.
-    OverrideInstructionSetFeatures(InstructionSet::kX86, "default");
     OptimizingUnitTest::SetUp();
+    // This test is using the x86 ISA.
+    compiler_options_ = CommonCompilerTest::CreateCompilerOptions(InstructionSet::kX86, "default");
   }
 
   // These functions need to access private variables of LocationSummary, so we declare it
@@ -74,6 +74,8 @@
                                                 /* processing_core_registers= */ true,
                                                 /* log_fatal_on_failure= */ false);
   }
+
+  std::unique_ptr<CompilerOptions> compiler_options_;
 };
 
 // This macro should include all register allocation strategies that should be tested.
@@ -683,7 +685,7 @@
         RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
     register_allocator->AllocateRegisters();
 
-    // Sanity check that in normal conditions, the register should be hinted to 0 (EAX).
+    // Check the validity that in normal conditions, the register should be hinted to 0 (EAX).
     ASSERT_EQ(field->GetLiveInterval()->GetRegister(), 0);
   }
 
@@ -751,7 +753,7 @@
         RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
     register_allocator->AllocateRegisters();
 
-    // Sanity check that in normal conditions, the registers are the same.
+    // Check the validity that in normal conditions, the registers are the same.
     ASSERT_EQ(first_sub->GetLiveInterval()->GetRegister(), 1);
     ASSERT_EQ(second_sub->GetLiveInterval()->GetRegister(), 1);
   }
@@ -862,8 +864,8 @@
   // We create a synthesized user requesting a register, to avoid just spilling the
   // intervals.
   HPhi* user = new (GetAllocator()) HPhi(GetAllocator(), 0, 1, DataType::Type::kInt32);
-  user->AddInput(one);
   user->SetBlock(block);
+  user->AddInput(one);
   LocationSummary* locations = new (GetAllocator()) LocationSummary(user, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RequiresRegister());
   static constexpr size_t phi_ranges[][2] = {{20, 30}};
diff --git a/compiler/optimizing/scheduler.cc b/compiler/optimizing/scheduler.cc
index f722cf9..cb340f5 100644
--- a/compiler/optimizing/scheduler.cc
+++ b/compiler/optimizing/scheduler.cc
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-#include <string>
-
 #include "scheduler.h"
 
+#include <string>
+
 #include "base/scoped_arena_allocator.h"
 #include "base/scoped_arena_containers.h"
 #include "data_type-inl.h"
+#include "optimizing/load_store_analysis.h"
 #include "prepare_for_register_allocation.h"
 
 #ifdef ART_ENABLE_CODEGEN_arm64
@@ -107,6 +108,7 @@
 static bool IsInstanceFieldAccess(const HInstruction* instruction) {
   return instruction->IsInstanceFieldGet() ||
          instruction->IsInstanceFieldSet() ||
+         instruction->IsPredicatedInstanceFieldGet() ||
          instruction->IsUnresolvedInstanceFieldGet() ||
          instruction->IsUnresolvedInstanceFieldSet();
 }
@@ -121,6 +123,7 @@
 static bool IsResolvedFieldAccess(const HInstruction* instruction) {
   return instruction->IsInstanceFieldGet() ||
          instruction->IsInstanceFieldSet() ||
+         instruction->IsPredicatedInstanceFieldGet() ||
          instruction->IsStaticFieldGet() ||
          instruction->IsStaticFieldSet();
 }
@@ -137,18 +140,7 @@
 }
 
 static const FieldInfo* GetFieldInfo(const HInstruction* instruction) {
-  if (instruction->IsInstanceFieldGet()) {
-    return &instruction->AsInstanceFieldGet()->GetFieldInfo();
-  } else if (instruction->IsInstanceFieldSet()) {
-    return &instruction->AsInstanceFieldSet()->GetFieldInfo();
-  } else if (instruction->IsStaticFieldGet()) {
-    return &instruction->AsStaticFieldGet()->GetFieldInfo();
-  } else if (instruction->IsStaticFieldSet()) {
-    return &instruction->AsStaticFieldSet()->GetFieldInfo();
-  } else {
-    LOG(FATAL) << "Unexpected field access type";
-    UNREACHABLE();
-  }
+  return &instruction->GetFieldInfo();
 }
 
 size_t SideEffectDependencyAnalysis::MemoryDependencyAnalysis::FieldAccessHeapLocation(
@@ -157,8 +149,10 @@
   DCHECK(GetFieldInfo(instr) != nullptr);
   DCHECK(heap_location_collector_ != nullptr);
 
-  size_t heap_loc = heap_location_collector_->GetFieldHeapLocation(instr->InputAt(0),
-                                                                   GetFieldInfo(instr));
+  HInstruction* ref = instr->IsPredicatedInstanceFieldGet()
+      ? instr->AsPredicatedInstanceFieldGet()->GetTarget()
+      : instr->InputAt(0);
+  size_t heap_loc = heap_location_collector_->GetFieldHeapLocation(ref, GetFieldInfo(instr));
   // This field access should be analyzed and added to HeapLocationCollector before.
   DCHECK(heap_loc != HeapLocationCollector::kHeapLocationNotFound);
 
@@ -559,7 +553,8 @@
   // We run lsa here instead of in a separate pass to better control whether we
   // should run the analysis or not.
   const HeapLocationCollector* heap_location_collector = nullptr;
-  LoadStoreAnalysis lsa(graph);
+  ScopedArenaAllocator allocator(graph->GetArenaStack());
+  LoadStoreAnalysis lsa(graph, /*stats=*/nullptr, &allocator, LoadStoreAnalysisType::kBasic);
   if (!only_optimize_loop_blocks_ || graph->HasLoops()) {
     lsa.Run();
     heap_location_collector = &lsa.GetHeapLocationCollector();
@@ -729,35 +724,37 @@
   // TODO: Some of the instructions above may be safe to schedule (maybe as
   // scheduling barriers).
   return instruction->IsArrayGet() ||
-      instruction->IsArraySet() ||
-      instruction->IsArrayLength() ||
-      instruction->IsBoundType() ||
-      instruction->IsBoundsCheck() ||
-      instruction->IsCheckCast() ||
-      instruction->IsClassTableGet() ||
-      instruction->IsCurrentMethod() ||
-      instruction->IsDivZeroCheck() ||
-      (instruction->IsInstanceFieldGet() && !instruction->AsInstanceFieldGet()->IsVolatile()) ||
-      (instruction->IsInstanceFieldSet() && !instruction->AsInstanceFieldSet()->IsVolatile()) ||
-      instruction->IsInstanceOf() ||
-      instruction->IsInvokeInterface() ||
-      instruction->IsInvokeStaticOrDirect() ||
-      instruction->IsInvokeUnresolved() ||
-      instruction->IsInvokeVirtual() ||
-      instruction->IsLoadString() ||
-      instruction->IsNewArray() ||
-      instruction->IsNewInstance() ||
-      instruction->IsNullCheck() ||
-      instruction->IsPackedSwitch() ||
-      instruction->IsParameterValue() ||
-      instruction->IsPhi() ||
-      instruction->IsReturn() ||
-      instruction->IsReturnVoid() ||
-      instruction->IsSelect() ||
-      (instruction->IsStaticFieldGet() && !instruction->AsStaticFieldGet()->IsVolatile()) ||
-      (instruction->IsStaticFieldSet() && !instruction->AsStaticFieldSet()->IsVolatile()) ||
-      instruction->IsSuspendCheck() ||
-      instruction->IsTypeConversion();
+         instruction->IsArraySet() ||
+         instruction->IsArrayLength() ||
+         instruction->IsBoundType() ||
+         instruction->IsBoundsCheck() ||
+         instruction->IsCheckCast() ||
+         instruction->IsClassTableGet() ||
+         instruction->IsCurrentMethod() ||
+         instruction->IsDivZeroCheck() ||
+         (instruction->IsInstanceFieldGet() && !instruction->AsInstanceFieldGet()->IsVolatile()) ||
+         (instruction->IsPredicatedInstanceFieldGet() &&
+          !instruction->AsPredicatedInstanceFieldGet()->IsVolatile()) ||
+         (instruction->IsInstanceFieldSet() && !instruction->AsInstanceFieldSet()->IsVolatile()) ||
+         instruction->IsInstanceOf() ||
+         instruction->IsInvokeInterface() ||
+         instruction->IsInvokeStaticOrDirect() ||
+         instruction->IsInvokeUnresolved() ||
+         instruction->IsInvokeVirtual() ||
+         instruction->IsLoadString() ||
+         instruction->IsNewArray() ||
+         instruction->IsNewInstance() ||
+         instruction->IsNullCheck() ||
+         instruction->IsPackedSwitch() ||
+         instruction->IsParameterValue() ||
+         instruction->IsPhi() ||
+         instruction->IsReturn() ||
+         instruction->IsReturnVoid() ||
+         instruction->IsSelect() ||
+         (instruction->IsStaticFieldGet() && !instruction->AsStaticFieldGet()->IsVolatile()) ||
+         (instruction->IsStaticFieldSet() && !instruction->AsStaticFieldSet()->IsVolatile()) ||
+         instruction->IsSuspendCheck() ||
+         instruction->IsTypeConversion();
 }
 
 bool HScheduler::IsSchedulable(const HBasicBlock* block) const {
diff --git a/compiler/optimizing/scheduler_arm.cc b/compiler/optimizing/scheduler_arm.cc
index 858a555..f9004d8 100644
--- a/compiler/optimizing/scheduler_arm.cc
+++ b/compiler/optimizing/scheduler_arm.cc
@@ -853,6 +853,11 @@
   }
 }
 
+void SchedulingLatencyVisitorARM::VisitPredicatedInstanceFieldGet(
+    HPredicatedInstanceFieldGet* instruction) {
+  HandleFieldGetLatencies(instruction, instruction->GetFieldInfo());
+}
+
 void SchedulingLatencyVisitorARM::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
   HandleFieldGetLatencies(instruction, instruction->GetFieldInfo());
 }
@@ -913,7 +918,9 @@
 
 void SchedulingLatencyVisitorARM::HandleFieldGetLatencies(HInstruction* instruction,
                                                           const FieldInfo& field_info) {
-  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
+  DCHECK(instruction->IsInstanceFieldGet() ||
+         instruction->IsStaticFieldGet() ||
+         instruction->IsPredicatedInstanceFieldGet());
   DCHECK(codegen_ != nullptr);
   bool is_volatile = field_info.IsVolatile();
   DataType::Type field_type = field_info.GetFieldType();
diff --git a/compiler/optimizing/scheduler_arm.h b/compiler/optimizing/scheduler_arm.h
index 4c7a3bb..d11222d 100644
--- a/compiler/optimizing/scheduler_arm.h
+++ b/compiler/optimizing/scheduler_arm.h
@@ -61,36 +61,37 @@
 
 // We add a second unused parameter to be able to use this macro like the others
 // defined in `nodes.h`.
-#define FOR_EACH_SCHEDULED_ARM_INSTRUCTION(M)    \
-  M(ArrayGet         , unused)                   \
-  M(ArrayLength      , unused)                   \
-  M(ArraySet         , unused)                   \
-  M(Add              , unused)                   \
-  M(Sub              , unused)                   \
-  M(And              , unused)                   \
-  M(Or               , unused)                   \
-  M(Ror              , unused)                   \
-  M(Xor              , unused)                   \
-  M(Shl              , unused)                   \
-  M(Shr              , unused)                   \
-  M(UShr             , unused)                   \
-  M(Mul              , unused)                   \
-  M(Div              , unused)                   \
-  M(Condition        , unused)                   \
-  M(Compare          , unused)                   \
-  M(BoundsCheck      , unused)                   \
-  M(InstanceFieldGet , unused)                   \
-  M(InstanceFieldSet , unused)                   \
-  M(InstanceOf       , unused)                   \
-  M(Invoke           , unused)                   \
-  M(LoadString       , unused)                   \
-  M(NewArray         , unused)                   \
-  M(NewInstance      , unused)                   \
-  M(Rem              , unused)                   \
-  M(StaticFieldGet   , unused)                   \
-  M(StaticFieldSet   , unused)                   \
-  M(SuspendCheck     , unused)                   \
-  M(TypeConversion   , unused)
+#define FOR_EACH_SCHEDULED_ARM_INSTRUCTION(M) \
+  M(ArrayGet, unused)                         \
+  M(ArrayLength, unused)                      \
+  M(ArraySet, unused)                         \
+  M(Add, unused)                              \
+  M(Sub, unused)                              \
+  M(And, unused)                              \
+  M(Or, unused)                               \
+  M(Ror, unused)                              \
+  M(Xor, unused)                              \
+  M(Shl, unused)                              \
+  M(Shr, unused)                              \
+  M(UShr, unused)                             \
+  M(Mul, unused)                              \
+  M(Div, unused)                              \
+  M(Condition, unused)                        \
+  M(Compare, unused)                          \
+  M(BoundsCheck, unused)                      \
+  M(PredicatedInstanceFieldGet, unused)       \
+  M(InstanceFieldGet, unused)                 \
+  M(InstanceFieldSet, unused)                 \
+  M(InstanceOf, unused)                       \
+  M(Invoke, unused)                           \
+  M(LoadString, unused)                       \
+  M(NewArray, unused)                         \
+  M(NewInstance, unused)                      \
+  M(Rem, unused)                              \
+  M(StaticFieldGet, unused)                   \
+  M(StaticFieldSet, unused)                   \
+  M(SuspendCheck, unused)                     \
+  M(TypeConversion, unused)
 
 #define FOR_EACH_SCHEDULED_SHARED_INSTRUCTION(M) \
   M(BitwiseNegatedRight, unused)                 \
diff --git a/compiler/optimizing/scheduler_test.cc b/compiler/optimizing/scheduler_test.cc
index 7835b1d..a1cc202 100644
--- a/compiler/optimizing/scheduler_test.cc
+++ b/compiler/optimizing/scheduler_test.cc
@@ -188,9 +188,10 @@
       HInstructionScheduling scheduling(graph, target_config.GetInstructionSet());
       scheduling.Run(/*only_optimize_loop_blocks*/ false, /*schedule_randomly*/ true);
 
-      OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
+      std::unique_ptr<CompilerOptions> compiler_options =
+          CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
       RunCode(target_config,
-              *compiler_options_,
+              *compiler_options,
               graph,
               [](HGraph* graph_arg) { RemoveSuspendChecks(graph_arg); },
               has_result, expected);
@@ -272,7 +273,8 @@
       entry->AddInstruction(instr);
     }
 
-    HeapLocationCollector heap_location_collector(graph_);
+    HeapLocationCollector heap_location_collector(
+        graph_, GetScopedAllocator(), LoadStoreAnalysisType::kBasic);
     heap_location_collector.VisitBasicBlock(entry);
     heap_location_collector.BuildAliasingMatrix();
     TestSchedulingGraph scheduling_graph(GetScopedAllocator(), &heap_location_collector);
diff --git a/compiler/optimizing/select_generator.cc b/compiler/optimizing/select_generator.cc
index dcc7f77..5405382 100644
--- a/compiler/optimizing/select_generator.cc
+++ b/compiler/optimizing/select_generator.cc
@@ -24,11 +24,9 @@
 static constexpr size_t kMaxInstructionsInBranch = 1u;
 
 HSelectGenerator::HSelectGenerator(HGraph* graph,
-                                   VariableSizedHandleScope* handles,
                                    OptimizingCompilerStats* stats,
                                    const char* name)
-    : HOptimization(graph, name, stats),
-      handle_scope_(handles) {
+    : HOptimization(graph, name, stats) {
 }
 
 // Returns true if `block` has only one predecessor, ends with a Goto
@@ -163,7 +161,7 @@
     if (both_successors_return) {
       if (true_value->GetType() == DataType::Type::kReference) {
         DCHECK(false_value->GetType() == DataType::Type::kReference);
-        ReferenceTypePropagation::FixUpInstructionType(select, handle_scope_);
+        ReferenceTypePropagation::FixUpInstructionType(select, graph_->GetHandleCache());
       }
     } else if (phi->GetType() == DataType::Type::kReference) {
       select->SetReferenceTypeInfo(phi->GetReferenceTypeInfo());
diff --git a/compiler/optimizing/select_generator.h b/compiler/optimizing/select_generator.h
index 2889166..30ac8a8 100644
--- a/compiler/optimizing/select_generator.h
+++ b/compiler/optimizing/select_generator.h
@@ -64,7 +64,6 @@
 class HSelectGenerator : public HOptimization {
  public:
   HSelectGenerator(HGraph* graph,
-                   VariableSizedHandleScope* handles,
                    OptimizingCompilerStats* stats,
                    const char* name = kSelectGeneratorPassName);
 
@@ -73,7 +72,6 @@
   static constexpr const char* kSelectGeneratorPassName = "select_generator";
 
  private:
-  VariableSizedHandleScope* handle_scope_;
   DISALLOW_COPY_AND_ASSIGN(HSelectGenerator);
 };
 
diff --git a/compiler/optimizing/select_generator_test.cc b/compiler/optimizing/select_generator_test.cc
index 6e68c6c..b18d41a 100644
--- a/compiler/optimizing/select_generator_test.cc
+++ b/compiler/optimizing/select_generator_test.cc
@@ -24,24 +24,20 @@
 
 namespace art {
 
-class SelectGeneratorTest : public ImprovedOptimizingUnitTest {
- private:
-  void CreateParameters() override {
-    parameters_.push_back(new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
-                                                               dex::TypeIndex(0),
-                                                               0,
-                                                               DataType::Type::kInt32));
+class SelectGeneratorTest : public OptimizingUnitTest {
+ protected:
+  void InitGraphAndParameters() {
+    InitGraph();
+    AddParameter(new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
+                                                      dex::TypeIndex(0),
+                                                      0,
+                                                      DataType::Type::kInt32));
   }
 
- public:
   void ConstructBasicGraphForSelect(HInstruction* instr) {
-    HBasicBlock* if_block = new (GetAllocator()) HBasicBlock(graph_);
-    HBasicBlock* then_block = new (GetAllocator()) HBasicBlock(graph_);
-    HBasicBlock* else_block = new (GetAllocator()) HBasicBlock(graph_);
-
-    graph_->AddBlock(if_block);
-    graph_->AddBlock(then_block);
-    graph_->AddBlock(else_block);
+    HBasicBlock* if_block = AddNewBlock();
+    HBasicBlock* then_block = AddNewBlock();
+    HBasicBlock* else_block = AddNewBlock();
 
     entry_block_->ReplaceSuccessor(return_block_, if_block);
 
@@ -82,7 +78,7 @@
 
 // HDivZeroCheck might throw and should not be hoisted from the conditional to an unconditional.
 TEST_F(SelectGeneratorTest, testZeroCheck) {
-  InitGraph();
+  InitGraphAndParameters();
   HDivZeroCheck* instr = new (GetAllocator()) HDivZeroCheck(parameters_[0], 0);
   ConstructBasicGraphForSelect(instr);
 
@@ -95,7 +91,7 @@
 
 // Test that SelectGenerator succeeds with HAdd.
 TEST_F(SelectGeneratorTest, testAdd) {
-  InitGraph();
+  InitGraphAndParameters();
   HAdd* instr = new (GetAllocator()) HAdd(DataType::Type::kInt32,
                                           parameters_[0],
                                           parameters_[0], 0);
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index b8471e3..1fd76f7 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -57,16 +57,19 @@
   return compiler_options.IsImageClass(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
 }
 
-HInvokeStaticOrDirect::DispatchInfo HSharpening::SharpenInvokeStaticOrDirect(
-    ArtMethod* callee, CodeGenerator* codegen) {
+HInvokeStaticOrDirect::DispatchInfo HSharpening::SharpenLoadMethod(
+    ArtMethod* callee,
+    bool has_method_id,
+    bool for_interface_call,
+    CodeGenerator* codegen) {
   if (kIsDebugBuild) {
     ScopedObjectAccess soa(Thread::Current());  // Required for GetDeclaringClass below.
     DCHECK(callee != nullptr);
     DCHECK(!(callee->IsConstructor() && callee->GetDeclaringClass()->IsStringClass()));
   }
 
-  HInvokeStaticOrDirect::MethodLoadKind method_load_kind;
-  HInvokeStaticOrDirect::CodePtrLocation code_ptr_location;
+  MethodLoadKind method_load_kind;
+  CodePtrLocation code_ptr_location;
   uint64_t method_load_data = 0u;
 
   // Note: we never call an ArtMethod through a known code pointer, as
@@ -83,51 +86,70 @@
   // We don't optimize for debuggable as it would prevent us from obsoleting the method in some
   // situations.
   const CompilerOptions& compiler_options = codegen->GetCompilerOptions();
-  if (callee == codegen->GetGraph()->GetArtMethod() && !codegen->GetGraph()->IsDebuggable()) {
-    // Recursive call.
-    method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRecursive;
-    code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallSelf;
+  if (callee == codegen->GetGraph()->GetArtMethod() &&
+      !codegen->GetGraph()->IsDebuggable() &&
+      // The runtime expects the canonical interface method being passed as
+      // hidden argument when doing an invokeinterface. Because default methods
+      // can be called through invokevirtual, we may get a copied method if we
+      // load 'recursively'.
+      (!for_interface_call || !callee->IsDefault())) {
+    // Recursive load.
+    method_load_kind = MethodLoadKind::kRecursive;
+    code_ptr_location = CodePtrLocation::kCallSelf;
   } else if (compiler_options.IsBootImage() || compiler_options.IsBootImageExtension()) {
     if (!compiler_options.GetCompilePic()) {
       // Test configuration, do not sharpen.
-      method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall;
+      method_load_kind = MethodLoadKind::kRuntimeCall;
     } else if (IsInBootImage(callee)) {
       DCHECK(compiler_options.IsBootImageExtension());
-      method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo;
+      method_load_kind = MethodLoadKind::kBootImageRelRo;
     } else if (BootImageAOTCanEmbedMethod(callee, compiler_options)) {
-      method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative;
+      method_load_kind = MethodLoadKind::kBootImageLinkTimePcRelative;
+    } else if (!has_method_id) {
+      method_load_kind = MethodLoadKind::kRuntimeCall;
     } else {
+      DCHECK(!callee->IsCopied());
       // Use PC-relative access to the .bss methods array.
-      method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBssEntry;
+      method_load_kind = MethodLoadKind::kBssEntry;
     }
-    code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
-  } else if (Runtime::Current()->UseJitCompilation()) {
+    code_ptr_location = CodePtrLocation::kCallArtMethod;
+  } else if (compiler_options.IsJitCompiler()) {
     ScopedObjectAccess soa(Thread::Current());
     if (Runtime::Current()->GetJit()->CanEncodeMethod(
             callee,
-            codegen->GetGraph()->IsCompilingForSharedJitCode())) {
-      method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress;
+            compiler_options.IsJitCompilerForSharedCode())) {
+      method_load_kind = MethodLoadKind::kJitDirectAddress;
       method_load_data = reinterpret_cast<uintptr_t>(callee);
-      code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
+      code_ptr_location = CodePtrLocation::kCallArtMethod;
     } else {
       // Do not sharpen.
-      method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall;
-      code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
+      method_load_kind = MethodLoadKind::kRuntimeCall;
+      code_ptr_location = CodePtrLocation::kCallArtMethod;
     }
   } else if (IsInBootImage(callee)) {
     // Use PC-relative access to the .data.bimg.rel.ro methods array.
-    method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo;
-    code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
+    method_load_kind = MethodLoadKind::kBootImageRelRo;
+    code_ptr_location = CodePtrLocation::kCallArtMethod;
+  } else if (!has_method_id) {
+    method_load_kind = MethodLoadKind::kRuntimeCall;
+    code_ptr_location = CodePtrLocation::kCallArtMethod;
   } else {
+    DCHECK(!callee->IsCopied());
     // Use PC-relative access to the .bss methods array.
-    method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBssEntry;
-    code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
+    method_load_kind = MethodLoadKind::kBssEntry;
+    code_ptr_location = CodePtrLocation::kCallArtMethod;
+  }
+
+  if (method_load_kind != MethodLoadKind::kRuntimeCall && callee->IsCriticalNative()) {
+    DCHECK_NE(method_load_kind, MethodLoadKind::kRecursive);
+    DCHECK(callee->IsStatic());
+    code_ptr_location = CodePtrLocation::kCallCriticalNative;
   }
 
   if (codegen->GetGraph()->IsDebuggable()) {
     // For debuggable apps always use the code pointer from ArtMethod
     // so that we don't circumvent instrumentation stubs if installed.
-    code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
+    code_ptr_location = CodePtrLocation::kCallArtMethod;
   }
 
   HInvokeStaticOrDirect::DispatchInfo desired_dispatch_info = {
@@ -145,27 +167,58 @@
          load_class->GetLoadKind() == HLoadClass::LoadKind::kReferrersClass)
       << load_class->GetLoadKind();
   DCHECK(!load_class->IsInBootImage()) << "HLoadClass should not be optimized before sharpening.";
+  const DexFile& dex_file = load_class->GetDexFile();
+  dex::TypeIndex type_index = load_class->GetTypeIndex();
+  const CompilerOptions& compiler_options = codegen->GetCompilerOptions();
 
-  HLoadClass::LoadKind load_kind = load_class->GetLoadKind();
+  bool is_in_boot_image = false;
+  HLoadClass::LoadKind desired_load_kind = HLoadClass::LoadKind::kInvalid;
 
-  if (load_class->NeedsAccessCheck()) {
-    // We need to call the runtime anyway, so we simply get the class as that call's return value.
-  } else if (load_kind == HLoadClass::LoadKind::kReferrersClass) {
+  if (load_class->GetLoadKind() == HLoadClass::LoadKind::kReferrersClass) {
+    DCHECK(!load_class->NeedsAccessCheck());
     // Loading from the ArtMethod* is the most efficient retrieval in code size.
     // TODO: This may not actually be true for all architectures and
     // locations of target classes. The additional register pressure
     // for using the ArtMethod* should be considered.
+    desired_load_kind = HLoadClass::LoadKind::kReferrersClass;
+  } else if (load_class->NeedsAccessCheck()) {
+    DCHECK_EQ(load_class->GetLoadKind(), HLoadClass::LoadKind::kRuntimeCall);
+    if (klass != nullptr) {
+      // Resolved class that needs access check must be really inaccessible
+      // and the access check is bound to fail. Just emit the runtime call.
+      desired_load_kind = HLoadClass::LoadKind::kRuntimeCall;
+    } else if (compiler_options.IsJitCompiler()) {
+      // Unresolved class while JITting means that either we never hit this
+      // instruction or it failed. Either way, just emit the runtime call.
+      // (Though we could consider emitting Deoptimize instead and
+      // recompile if the instruction succeeds in interpreter.)
+      desired_load_kind = HLoadClass::LoadKind::kRuntimeCall;
+    } else {
+      // For AOT, check if the class is in the same literal package as the
+      // compiling class and pick an appropriate .bss entry.
+      auto package_length = [](const char* descriptor) {
+        const char* slash_pos = strrchr(descriptor, '/');
+        return (slash_pos != nullptr) ? static_cast<size_t>(slash_pos - descriptor) : 0u;
+      };
+      const char* klass_descriptor = dex_file.StringByTypeIdx(type_index);
+      const uint32_t klass_package_length = package_length(klass_descriptor);
+      const DexFile* referrer_dex_file = dex_compilation_unit.GetDexFile();
+      const dex::TypeIndex referrer_type_index =
+          referrer_dex_file->GetClassDef(dex_compilation_unit.GetClassDefIndex()).class_idx_;
+      const char* referrer_descriptor = referrer_dex_file->StringByTypeIdx(referrer_type_index);
+      const uint32_t referrer_package_length = package_length(referrer_descriptor);
+      bool same_package =
+          (referrer_package_length == klass_package_length) &&
+          memcmp(referrer_descriptor, klass_descriptor, referrer_package_length) == 0;
+      desired_load_kind = same_package
+          ? HLoadClass::LoadKind::kBssEntryPackage
+          : HLoadClass::LoadKind::kBssEntryPublic;
+    }
   } else {
-    const DexFile& dex_file = load_class->GetDexFile();
-    dex::TypeIndex type_index = load_class->GetTypeIndex();
-
-    bool is_in_boot_image = false;
-    HLoadClass::LoadKind desired_load_kind = HLoadClass::LoadKind::kInvalid;
     Runtime* runtime = Runtime::Current();
-    const CompilerOptions& compiler_options = codegen->GetCompilerOptions();
     if (compiler_options.IsBootImage() || compiler_options.IsBootImageExtension()) {
       // Compiling boot image or boot image extension. Check if the class is a boot image class.
-      DCHECK(!runtime->UseJitCompilation());
+      DCHECK(!compiler_options.IsJitCompiler());
       if (!compiler_options.GetCompilePic()) {
         // Test configuration, do not sharpen.
         desired_load_kind = HLoadClass::LoadKind::kRuntimeCall;
@@ -184,14 +237,14 @@
     } else {
       is_in_boot_image = (klass != nullptr) &&
           runtime->GetHeap()->ObjectIsInBootImageSpace(klass.Get());
-      if (runtime->UseJitCompilation()) {
+      if (compiler_options.IsJitCompiler()) {
         DCHECK(!compiler_options.GetCompilePic());
         if (is_in_boot_image) {
           desired_load_kind = HLoadClass::LoadKind::kJitBootImageAddress;
         } else if (klass != nullptr) {
           if (runtime->GetJit()->CanEncodeClass(
                   klass.Get(),
-                  codegen->GetGraph()->IsCompilingForSharedJitCode())) {
+                  compiler_options.IsJitCompilerForSharedCode())) {
             desired_load_kind = HLoadClass::LoadKind::kJitTableAddress;
           } else {
             // Shared JIT code cannot encode a literal that the GC can move.
@@ -214,17 +267,19 @@
         desired_load_kind = HLoadClass::LoadKind::kBssEntry;
       }
     }
-    DCHECK_NE(desired_load_kind, HLoadClass::LoadKind::kInvalid);
-
-    if (is_in_boot_image) {
-      load_class->MarkInBootImage();
-    }
-    load_kind = codegen->GetSupportedLoadClassKind(desired_load_kind);
   }
+  DCHECK_NE(desired_load_kind, HLoadClass::LoadKind::kInvalid);
+
+  if (is_in_boot_image) {
+    load_class->MarkInBootImage();
+  }
+  HLoadClass::LoadKind load_kind = codegen->GetSupportedLoadClassKind(desired_load_kind);
 
   if (!IsSameDexFile(load_class->GetDexFile(), *dex_compilation_unit.GetDexFile())) {
-    if ((load_kind == HLoadClass::LoadKind::kRuntimeCall) ||
-        (load_kind == HLoadClass::LoadKind::kBssEntry)) {
+    if (load_kind == HLoadClass::LoadKind::kRuntimeCall ||
+        load_kind == HLoadClass::LoadKind::kBssEntry ||
+        load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
+        load_kind == HLoadClass::LoadKind::kBssEntryPackage) {
       // We actually cannot reference this class, we're forced to bail.
       // We cannot reference this class with Bss, as the entrypoint will lookup the class
       // in the caller's dex file, but that dex file does not reference the class.
@@ -239,7 +294,8 @@
   DCHECK(!klass->IsProxyClass());
   DCHECK(!klass->IsArrayClass());
 
-  if (Runtime::Current()->UseJitCompilation()) {
+  const CompilerOptions& compiler_options = codegen->GetCompilerOptions();
+  if (compiler_options.IsJitCompiler()) {
     // If we're JITting, try to assign a type check bitstring (fall through).
   } else if (codegen->GetCompilerOptions().IsBootImage()) {
     const char* descriptor = klass->GetDexFile().StringByTypeIdx(klass->GetDexTypeIndex());
@@ -259,8 +315,8 @@
   if ((false) &&  // FIXME: Inliner does not respect CompilerDriver::ShouldCompileMethod()
                   // and we're hitting an unassigned bitstring in dex2oat_image_test. b/26687569
       kIsDebugBuild &&
-      codegen->GetCompilerOptions().IsBootImage() &&
-      codegen->GetCompilerOptions().IsForceDeterminism()) {
+      compiler_options.IsBootImage() &&
+      compiler_options.IsForceDeterminism()) {
     SubtypeCheckInfo::State old_state = SubtypeCheck<ObjPtr<mirror::Class>>::GetState(klass);
     CHECK(old_state == SubtypeCheckInfo::kAssigned || old_state == SubtypeCheckInfo::kOverflowed)
         << klass->PrettyDescriptor() << "/" << old_state
@@ -325,7 +381,7 @@
     if (compiler_options.IsBootImage() || compiler_options.IsBootImageExtension()) {
       // Compiling boot image or boot image extension. Resolve the string and allocate it
       // if needed, to ensure the string will be added to the boot image.
-      DCHECK(!runtime->UseJitCompilation());
+      DCHECK(!compiler_options.IsJitCompiler());
       if (compiler_options.GetCompilePic()) {
         if (compiler_options.IsForceDeterminism()) {
           // Strings for methods we're compiling should be pre-resolved but Strings in inlined
@@ -354,7 +410,7 @@
         // Test configuration, do not sharpen.
         desired_load_kind = HLoadString::LoadKind::kRuntimeCall;
       }
-    } else if (runtime->UseJitCompilation()) {
+    } else if (compiler_options.IsJitCompiler()) {
       DCHECK(!codegen->GetCompilerOptions().GetCompilePic());
       string = class_linker->LookupString(string_index, dex_cache.Get());
       if (string != nullptr) {
@@ -363,7 +419,7 @@
           desired_load_kind = HLoadString::LoadKind::kJitBootImageAddress;
         } else if (runtime->GetJit()->CanEncodeString(
                   string,
-                  codegen->GetGraph()->IsCompilingForSharedJitCode())) {
+                  compiler_options.IsJitCompilerForSharedCode())) {
           desired_load_kind = HLoadString::LoadKind::kJitTableAddress;
         } else {
           // Shared JIT code cannot encode a literal that the GC can move.
diff --git a/compiler/optimizing/sharpening.h b/compiler/optimizing/sharpening.h
index b818672..9753669 100644
--- a/compiler/optimizing/sharpening.h
+++ b/compiler/optimizing/sharpening.h
@@ -30,8 +30,11 @@
 class HSharpening {
  public:
   // Used by the builder and InstructionSimplifier.
-  static HInvokeStaticOrDirect::DispatchInfo SharpenInvokeStaticOrDirect(
-      ArtMethod* callee, CodeGenerator* codegen);
+  static HInvokeStaticOrDirect::DispatchInfo SharpenLoadMethod(
+      ArtMethod* callee,
+      bool has_method_id,
+      bool for_interface_call,
+      CodeGenerator* codegen);
 
   // Used by the builder and the inliner.
   static HLoadClass::LoadKind ComputeLoadClassKind(HLoadClass* load_class,
diff --git a/compiler/optimizing/side_effects_test.cc b/compiler/optimizing/side_effects_test.cc
index cf26e79..268798c 100644
--- a/compiler/optimizing/side_effects_test.cc
+++ b/compiler/optimizing/side_effects_test.cc
@@ -42,7 +42,7 @@
 // Helper methods.
 //
 
-void testWriteAndReadSanity(SideEffects write, SideEffects read) {
+void testWriteAndReadEffects(SideEffects write, SideEffects read) {
   EXPECT_FALSE(write.DoesNothing());
   EXPECT_FALSE(read.DoesNothing());
 
@@ -67,7 +67,7 @@
 }
 
 void testWriteAndReadDependence(SideEffects write, SideEffects read) {
-  testWriteAndReadSanity(write, read);
+  testWriteAndReadEffects(write, read);
 
   // Dependence only in one direction.
   EXPECT_FALSE(write.MayDependOn(read));
@@ -75,7 +75,7 @@
 }
 
 void testNoWriteAndReadDependence(SideEffects write, SideEffects read) {
-  testWriteAndReadSanity(write, read);
+  testWriteAndReadEffects(write, read);
 
   // No dependence in any direction.
   EXPECT_FALSE(write.MayDependOn(read));
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index a5e8ff6..67ee83c 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -540,7 +540,6 @@
   ReferenceTypePropagation(graph_,
                            class_loader_,
                            dex_cache_,
-                           handles_,
                            /* is_first_run= */ true).Run();
 
   // HInstructionBuilder duplicated ArrayGet instructions with ambiguous type
diff --git a/compiler/optimizing/ssa_builder.h b/compiler/optimizing/ssa_builder.h
index bb892c9..a7d4e0e 100644
--- a/compiler/optimizing/ssa_builder.h
+++ b/compiler/optimizing/ssa_builder.h
@@ -51,19 +51,16 @@
   SsaBuilder(HGraph* graph,
              Handle<mirror::ClassLoader> class_loader,
              Handle<mirror::DexCache> dex_cache,
-             VariableSizedHandleScope* handles,
              ScopedArenaAllocator* local_allocator)
       : graph_(graph),
         class_loader_(class_loader),
         dex_cache_(dex_cache),
-        handles_(handles),
         agets_fixed_(false),
         local_allocator_(local_allocator),
         ambiguous_agets_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
         ambiguous_asets_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
         uninitialized_strings_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
         uninitialized_string_phis_(local_allocator->Adapter(kArenaAllocGraphBuilder)) {
-    graph_->InitializeInexactObjectRTI(handles);
   }
 
   GraphAnalysisResult BuildSsa();
@@ -129,7 +126,6 @@
   HGraph* const graph_;
   Handle<mirror::ClassLoader> class_loader_;
   Handle<mirror::DexCache> dex_cache_;
-  VariableSizedHandleScope* const handles_;
 
   // True if types of ambiguous ArrayGets have been resolved.
   bool agets_fixed_;
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 7b2c3a9..18942a1 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -523,12 +523,8 @@
     if (defined_by->IsConstant()) {
       return defined_by->GetLocations()->Out();
     } else if (GetParent()->HasSpillSlot()) {
-      switch (NumberOfSpillSlotsNeeded()) {
-        case 1: return Location::StackSlot(GetParent()->GetSpillSlot());
-        case 2: return Location::DoubleStackSlot(GetParent()->GetSpillSlot());
-        case 4: return Location::SIMDStackSlot(GetParent()->GetSpillSlot());
-        default: LOG(FATAL) << "Unexpected number of spill slots"; UNREACHABLE();
-      }
+      return Location::StackSlotByNumOfSlots(NumberOfSpillSlotsNeeded(),
+                                             GetParent()->GetSpillSlot());
     } else {
       return Location();
     }
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 3ea2815..7f31585 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -873,9 +873,9 @@
   }
 
   // Returns whether an interval, when it is non-split, is using
-  // the same register of one of its input.
+  // the same register of one of its input. This function should
+  // be used only for DCHECKs.
   bool IsUsingInputRegister() const {
-    CHECK(kIsDebugBuild) << "Function should be used only for DCHECKs";
     if (defined_by_ != nullptr && !IsSplit()) {
       for (const HInstruction* input : defined_by_->GetInputs()) {
         LiveInterval* interval = input->GetLiveInterval();
@@ -899,9 +899,9 @@
 
   // Returns whether an interval, when it is non-split, can safely use
   // the same register of one of its input. Note that this method requires
-  // IsUsingInputRegister() to be true.
+  // IsUsingInputRegister() to be true. This function should be used only
+  // for DCHECKs.
   bool CanUseInputRegister() const {
-    CHECK(kIsDebugBuild) << "Function should be used only for DCHECKs";
     DCHECK(IsUsingInputRegister());
     if (defined_by_ != nullptr && !IsSplit()) {
       LocationSummary* locations = defined_by_->GetLocations();
diff --git a/compiler/optimizing/ssa_liveness_analysis_test.cc b/compiler/optimizing/ssa_liveness_analysis_test.cc
index 352c44f..a477893 100644
--- a/compiler/optimizing/ssa_liveness_analysis_test.cc
+++ b/compiler/optimizing/ssa_liveness_analysis_test.cc
@@ -32,8 +32,9 @@
   void SetUp() override {
     OptimizingUnitTest::SetUp();
     graph_ = CreateGraph();
+    compiler_options_ = CommonCompilerTest::CreateCompilerOptions(kRuntimeISA, "default");
     codegen_ = CodeGenerator::Create(graph_, *compiler_options_);
-    CHECK(codegen_ != nullptr) << instruction_set_ << " is not a supported target architecture.";
+    CHECK(codegen_ != nullptr);
     // Create entry block.
     entry_ = new (GetAllocator()) HBasicBlock(graph_);
     graph_->AddBlock(entry_);
@@ -50,6 +51,7 @@
   }
 
   HGraph* graph_;
+  std::unique_ptr<CompilerOptions> compiler_options_;
   std::unique_ptr<CodeGenerator> codegen_;
   HBasicBlock* entry_;
 };
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index dd6d1a2..e52a3ce 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -65,9 +65,10 @@
   }
 }
 
-void StackMapStream::EndMethod() {
+void StackMapStream::EndMethod(size_t code_size) {
   DCHECK(in_method_) << "Mismatched Begin/End calls";
   in_method_ = false;
+  code_size_ = code_size;
 
   // Read the stack masks now. The compiler might have updated them.
   for (size_t i = 0; i < lazy_stack_masks_.size(); i++) {
@@ -77,6 +78,19 @@
           stack_masks_.Dedup(stack_mask->GetRawStorage(), stack_mask->GetNumberOfBits());
     }
   }
+
+  if (kIsDebugBuild) {
+    uint32_t packed_code_size = StackMap::PackNativePc(code_size, instruction_set_);
+    for (size_t i = 0; i < stack_maps_.size(); i++) {
+      DCHECK_LE(stack_maps_[i][StackMap::kPackedNativePc], packed_code_size);
+    }
+  }
+
+  if (kVerifyStackMaps) {
+    dchecks_.emplace_back([=](const CodeInfo& code_info) {
+        CHECK_EQ(code_info.code_size_, code_size);
+    });
+  }
 }
 
 void StackMapStream::BeginStackMapEntry(uint32_t dex_pc,
@@ -302,6 +316,7 @@
 
   uint32_t flags = (inline_infos_.size() > 0) ? CodeInfo::kHasInlineInfo : 0;
   flags |= baseline_ ? CodeInfo::kIsBaseline : 0;
+  DCHECK_LE(flags, kVarintMax);  // Ensure flags can be read directly as byte.
   uint32_t bit_table_flags = 0;
   ForEachBitTable([&bit_table_flags](size_t i, auto bit_table) {
     if (bit_table->size() != 0) {  // Record which bit-tables are stored.
@@ -313,6 +328,7 @@
   BitMemoryWriter<ScopedArenaVector<uint8_t>> out(&buffer);
   out.WriteInterleavedVarints(std::array<uint32_t, CodeInfo::kNumHeaders>{
     flags,
+    code_size_,
     packed_frame_size_,
     core_spill_mask_,
     fp_spill_mask_,
@@ -330,6 +346,8 @@
   CodeInfo code_info(buffer.data(), &number_of_read_bits);
   CHECK_EQ(number_of_read_bits, out.NumberOfWrittenBits());
   CHECK_EQ(code_info.GetNumberOfStackMaps(), stack_maps_.size());
+  CHECK_EQ(CodeInfo::HasInlineInfo(buffer.data()), inline_infos_.size() > 0);
+  CHECK_EQ(CodeInfo::IsBaseline(buffer.data()), baseline_);
 
   // Verify all written data (usually only in debug builds).
   if (kVerifyStackMaps) {
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index 67f716c..3ded07d 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -63,7 +63,7 @@
                    size_t fp_spill_mask,
                    uint32_t num_dex_registers,
                    bool baseline = false);
-  void EndMethod();
+  void EndMethod(size_t code_size);
 
   void BeginStackMapEntry(uint32_t dex_pc,
                           uint32_t native_pc_offset,
@@ -116,6 +116,7 @@
 
   ScopedArenaAllocator* allocator_;
   const InstructionSet instruction_set_;
+  uint32_t code_size_ = 0;
   uint32_t packed_frame_size_ = 0;
   uint32_t core_spill_mask_ = 0;
   uint32_t fp_spill_mask_ = 0;
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index 0dd5773..0158ab5 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -61,7 +61,7 @@
   stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Short location.
   stream.EndStackMapEntry();
 
-  stream.EndMethod();
+  stream.EndMethod(64 * kPcAlign);
   ScopedArenaVector<uint8_t> memory = stream.Encode();
 
   CodeInfo code_info(memory.data());
@@ -147,7 +147,7 @@
   stream.AddDexRegisterEntry(Kind::kInFpuRegisterHigh, 1);  // Short location.
   stream.EndStackMapEntry();
 
-  stream.EndMethod();
+  stream.EndMethod(256 * kPcAlign);
   ScopedArenaVector<uint8_t> memory = stream.Encode();
 
   CodeInfo code_info(memory.data());
@@ -317,7 +317,7 @@
   stream.EndInlineInfoEntry();
   stream.EndStackMapEntry();
 
-  stream.EndMethod();
+  stream.EndMethod(64 * kPcAlign);
   ScopedArenaVector<uint8_t> memory = stream.Encode();
 
   CodeInfo code_info(memory.data());
@@ -372,7 +372,7 @@
   stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Large location.
   stream.EndStackMapEntry();
 
-  stream.EndMethod();
+  stream.EndMethod(64 * kPcAlign);
   ScopedArenaVector<uint8_t> memory = stream.Encode();
 
   CodeInfo code_info(memory.data());
@@ -431,7 +431,7 @@
   stream.AddDexRegisterEntry(Kind::kConstant, -2);   // Large location.
   stream.EndStackMapEntry();
 
-  stream.EndMethod();
+  stream.EndMethod(66 * kPcAlign);
   ScopedArenaVector<uint8_t> memory = stream.Encode();
 
   CodeInfo ci(memory.data());
@@ -479,7 +479,7 @@
   stream.AddDexRegisterEntry(Kind::kNone, 0);
   stream.EndStackMapEntry();
 
-  stream.EndMethod();
+  stream.EndMethod(68 * kPcAlign);
   ScopedArenaVector<uint8_t> memory = stream.Encode();
 
   CodeInfo code_info(memory.data());
@@ -578,7 +578,7 @@
 
   stream.EndStackMapEntry();
 
-  stream.EndMethod();
+  stream.EndMethod(78 * kPcAlign);
   ScopedArenaVector<uint8_t> memory = stream.Encode();
 
   CodeInfo ci(memory.data());
@@ -714,7 +714,7 @@
   stream.BeginStackMapEntry(0, 8 * kPcAlign, 0x3, &sp_mask);
   stream.EndStackMapEntry();
 
-  stream.EndMethod();
+  stream.EndMethod(8 * kPcAlign);
   ScopedArenaVector<uint8_t> memory = stream.Encode();
 
   CodeInfo code_info(memory.data());
@@ -738,7 +738,7 @@
   stream.AddDexRegisterEntry(Kind::kConstant, -2);
   stream.EndStackMapEntry();
 
-  stream.EndMethod();
+  stream.EndMethod(64 * kPcAlign);
   ScopedArenaVector<uint8_t> memory = stream.Encode();
 
   std::vector<uint8_t> out;
diff --git a/compiler/optimizing/superblock_cloner.cc b/compiler/optimizing/superblock_cloner.cc
index dc433fe..b968491 100644
--- a/compiler/optimizing/superblock_cloner.cc
+++ b/compiler/optimizing/superblock_cloner.cc
@@ -20,7 +20,7 @@
 #include "induction_var_range.h"
 #include "graph_checker.h"
 
-#include <iostream>
+#include <sstream>
 
 namespace art {
 
@@ -227,6 +227,40 @@
   }
 }
 
+bool SuperblockCloner::IsRemapInfoForVersioning() const {
+  return remap_incoming_->empty() &&
+         remap_orig_internal_->empty() &&
+         remap_copy_internal_->empty();
+}
+
+void SuperblockCloner::CopyIncomingEdgesForVersioning() {
+  for (uint32_t orig_block_id : orig_bb_set_.Indexes()) {
+    HBasicBlock* orig_block = GetBlockById(orig_block_id);
+    size_t incoming_edge_count = 0;
+    for (HBasicBlock* orig_pred : orig_block->GetPredecessors()) {
+      uint32_t orig_pred_id = orig_pred->GetBlockId();
+      if (IsInOrigBBSet(orig_pred_id)) {
+        continue;
+      }
+
+      HBasicBlock* copy_block = GetBlockCopy(orig_block);
+      // This corresponds to the requirement on the order of predecessors: all the incoming
+      // edges must be seen before the internal ones. This is always true for natural loops.
+      // TODO: remove this requirement.
+      DCHECK_EQ(orig_block->GetPredecessorIndexOf(orig_pred), incoming_edge_count);
+      for (HInstructionIterator it(orig_block->GetPhis()); !it.Done(); it.Advance()) {
+        HPhi* orig_phi = it.Current()->AsPhi();
+        HPhi* copy_phi = GetInstrCopy(orig_phi)->AsPhi();
+        HInstruction* orig_phi_input = orig_phi->InputAt(incoming_edge_count);
+        // Add the corresponding input of the original phi to the copy one.
+        copy_phi->AddInput(orig_phi_input);
+      }
+      copy_block->AddPredecessor(orig_pred);
+      incoming_edge_count++;
+    }
+  }
+}
+
 //
 // Local versions of CF calculation/adjustment routines.
 //
@@ -452,6 +486,12 @@
 }
 
 void SuperblockCloner::RemapEdgesSuccessors() {
+  // By this stage all the blocks have been copied, copy phis - created with no inputs;
+  // no copy edges have been created so far.
+  if (IsRemapInfoForVersioning()) {
+    CopyIncomingEdgesForVersioning();
+  }
+
   // Redirect incoming edges.
   for (HEdge e : *remap_incoming_) {
     HBasicBlock* orig_block = GetBlockById(e.GetFrom());
@@ -646,25 +686,26 @@
     if (bb == nullptr) {
       continue;
     }
-    std::cout << bb->GetBlockId();
-    std::cout << " <- ";
+    std::ostringstream oss;
+    oss << bb->GetBlockId();
+    oss << " <- ";
     for (HBasicBlock* pred : bb->GetPredecessors()) {
-      std::cout << pred->GetBlockId() << " ";
+      oss << pred->GetBlockId() << " ";
     }
-    std::cout << " -> ";
+    oss << " -> ";
     for (HBasicBlock* succ : bb->GetSuccessors()) {
-      std::cout << succ->GetBlockId()  << " ";
+      oss << succ->GetBlockId()  << " ";
     }
 
     if (bb->GetDominator()) {
-      std::cout << " dom " << bb->GetDominator()->GetBlockId();
+      oss << " dom " << bb->GetDominator()->GetBlockId();
     }
 
     if (bb->GetLoopInformation()) {
-      std::cout <<  "\tloop: " << bb->GetLoopInformation()->GetHeader()->GetBlockId();
+      oss <<  "\tloop: " << bb->GetLoopInformation()->GetHeader()->GetBlockId();
     }
 
-    std::cout << std::endl;
+    LOG(INFO) << oss.str();
   }
 }
 
@@ -742,39 +783,40 @@
       DCHECK(it.second->GetBlock() != nullptr);
     }
   }
-
-  GraphChecker checker(graph_);
-  checker.Run();
-  if (!checker.IsValid()) {
-    for (const std::string& error : checker.GetErrors()) {
-      std::cout << error << std::endl;
+  if (kSuperblockClonerVerify) {
+    GraphChecker checker(graph_);
+    checker.Run();
+    if (!checker.IsValid()) {
+      for (const std::string& error : checker.GetErrors()) {
+        LOG(ERROR) << error;
+      }
+      LOG(FATAL) << "GraphChecker failed: superblock cloner";
     }
-    LOG(FATAL) << "GraphChecker failed: superblock cloner\n";
   }
 }
 
 void DumpBBSet(const ArenaBitVector* set) {
   for (uint32_t idx : set->Indexes()) {
-    std::cout << idx << "\n";
+    LOG(INFO) << idx;
   }
 }
 
 void SuperblockCloner::DumpInputSets() {
-  std::cout << "orig_bb_set:\n";
+  LOG(INFO) << "orig_bb_set:";
   for (uint32_t idx : orig_bb_set_.Indexes()) {
-    std::cout << idx << "\n";
+    LOG(INFO) << idx;
   }
-  std::cout << "remap_orig_internal:\n";
+  LOG(INFO) << "remap_orig_internal:";
   for (HEdge e : *remap_orig_internal_) {
-    std::cout << e << "\n";
+    LOG(INFO) << e;
   }
-  std::cout << "remap_copy_internal:\n";
+  LOG(INFO) << "remap_copy_internal:";
   for (auto e : *remap_copy_internal_) {
-    std::cout << e << "\n";
+    LOG(INFO) << e;
   }
-  std::cout << "remap_incoming:\n";
+  LOG(INFO) << "remap_incoming:";
   for (auto e : *remap_incoming_) {
-    std::cout << e << "\n";
+    LOG(INFO) << e;
   }
 }
 
@@ -836,8 +878,8 @@
   return true;
 }
 
+// Checks that loop unrolling/peeling/versioning is being conducted.
 bool SuperblockCloner::IsFastCase() const {
-  // Check that loop unrolling/loop peeling is being conducted.
   // Check that all the basic blocks belong to the same loop.
   bool flag = false;
   HLoopInformation* common_loop_info = nullptr;
@@ -853,11 +895,15 @@
     }
   }
 
-  // Check that orig_bb_set_ corresponds to loop peeling/unrolling.
+  // Check that orig_bb_set_ corresponds to loop peeling/unrolling/versioning.
   if (common_loop_info == nullptr || !orig_bb_set_.SameBitsSet(&common_loop_info->GetBlocks())) {
     return false;
   }
 
+  if (IsRemapInfoForVersioning()) {
+    return true;
+  }
+
   bool peeling_or_unrolling = false;
   HEdgeSet remap_orig_internal(graph_->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
   HEdgeSet remap_copy_internal(graph_->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
@@ -1011,8 +1057,7 @@
     HBasicBlock* copy_block = CloneBasicBlock(orig_block);
     bb_map_->Put(orig_block, copy_block);
     if (kSuperblockClonerLogging) {
-      std::cout << "new block :" << copy_block->GetBlockId() << ": " << orig_block->GetBlockId() <<
-                   std::endl;
+      LOG(INFO) << "new block :" << copy_block->GetBlockId() << ": " << orig_block->GetBlockId();
     }
   }
 }
@@ -1088,14 +1133,14 @@
   return current;
 }
 
-bool PeelUnrollHelper::IsLoopClonable(HLoopInformation* loop_info) {
-  PeelUnrollHelper helper(
+bool LoopClonerHelper::IsLoopClonable(HLoopInformation* loop_info) {
+  LoopClonerHelper helper(
       loop_info, /* bb_map= */ nullptr, /* hir_map= */ nullptr, /* induction_range= */ nullptr);
   return helper.IsLoopClonable();
 }
 
-HBasicBlock* PeelUnrollHelper::DoPeelUnrollImpl(bool to_unroll) {
-  // For now do peeling only for natural loops.
+HBasicBlock* LoopClonerHelper::DoLoopTransformationImpl(TransformationKind transformation) {
+  // For now do transformations only for natural loops.
   DCHECK(!loop_info_->IsIrreducible());
 
   HBasicBlock* loop_header = loop_info_->GetHeader();
@@ -1104,9 +1149,25 @@
   HGraph* graph = loop_header->GetGraph();
 
   if (kSuperblockClonerLogging) {
-    std::cout << "Method: " << graph->PrettyMethod() << std::endl;
-    std::cout << "Scalar loop " << (to_unroll ? "unrolling" : "peeling") <<
-                 " was applied to the loop <" << loop_header->GetBlockId() << ">." << std::endl;
+    LOG(INFO) << "Method: " << graph->PrettyMethod();
+    std::ostringstream oss;
+    oss << "Scalar loop ";
+    switch (transformation) {
+      case TransformationKind::kPeeling:
+        oss << "peeling";
+        break;
+      case TransformationKind::kUnrolling:
+        oss<< "unrolling";
+        break;
+      case TransformationKind::kVersioning:
+        oss << "versioning";
+        break;
+      default:
+        LOG(FATAL) << "Unreachable";
+        UNREACHABLE();
+    }
+    oss << " was applied to the loop <" << loop_header->GetBlockId() << ">.";
+    LOG(INFO) << oss.str();
   }
 
   ArenaAllocator allocator(graph->GetAllocator()->GetArenaPool());
@@ -1115,11 +1176,14 @@
   HEdgeSet remap_copy_internal(graph->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
   HEdgeSet remap_incoming(graph->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
 
-  CollectRemappingInfoForPeelUnroll(to_unroll,
-                                    loop_info_,
-                                    &remap_orig_internal,
-                                    &remap_copy_internal,
-                                    &remap_incoming);
+  // No remapping needed for loop versioning.
+  if (transformation != TransformationKind::kVersioning) {
+    CollectRemappingInfoForPeelUnroll(transformation == TransformationKind::kUnrolling,
+                                      loop_info_,
+                                      &remap_orig_internal,
+                                      &remap_copy_internal,
+                                      &remap_incoming);
+  }
 
   cloner_.SetSuccessorRemappingInfo(&remap_orig_internal, &remap_copy_internal, &remap_incoming);
   cloner_.Run();
@@ -1131,7 +1195,7 @@
   return loop_header;
 }
 
-PeelUnrollSimpleHelper::PeelUnrollSimpleHelper(HLoopInformation* info,
+LoopClonerSimpleHelper::LoopClonerSimpleHelper(HLoopInformation* info,
                                                InductionVarRange* induction_range)
   : bb_map_(std::less<HBasicBlock*>(),
             info->GetHeader()->GetGraph()->GetAllocator()->Adapter(kArenaAllocSuperblockCloner)),
diff --git a/compiler/optimizing/superblock_cloner.h b/compiler/optimizing/superblock_cloner.h
index ece0914..1f6ee74 100644
--- a/compiler/optimizing/superblock_cloner.h
+++ b/compiler/optimizing/superblock_cloner.h
@@ -27,6 +27,7 @@
 class InductionVarRange;
 
 static const bool kSuperblockClonerLogging = false;
+static const bool kSuperblockClonerVerify = false;
 
 // Represents an edge between two HBasicBlocks.
 //
@@ -88,7 +89,8 @@
 // fine grain manipulation with IR; data flow and graph properties are resolved/adjusted
 // automatically. The clone transformation is defined by specifying a set of basic blocks to copy
 // and a set of rules how to treat edges, remap their successors. By using this approach such
-// optimizations as Branch Target Expansion, Loop Peeling, Loop Unrolling can be implemented.
+// optimizations as Branch Target Expansion, Loop Peeling, Loop Unrolling, Loop Versioning can be
+// implemented.
 //
 // The idea of the transformation is based on "Superblock cloning" technique described in the book
 // "Engineering a Compiler. Second Edition", Keith D. Cooper, Linda Torczon, Rice University
@@ -160,7 +162,7 @@
   //
   // TODO: formally describe the criteria.
   //
-  // Loop peeling and unrolling satisfy the criteria.
+  // Loop peeling, unrolling and versioning satisfy the criteria.
   bool IsFastCase() const;
 
   // Runs the copy algorithm according to the description.
@@ -296,6 +298,18 @@
   // Remaps copy internal edge to its origin, adjusts the phi inputs in orig_succ.
   void RemapCopyInternalEdge(HBasicBlock* orig_block, HBasicBlock* orig_succ);
 
+  // Checks whether the edges remapping info corresponds to the subgraph versioning case:
+  //  - none of the incoming edges are to be remapped (they are being duplicated).
+  //  - none of the internal edges are to be remapped.
+  bool IsRemapInfoForVersioning() const;
+
+  // Processes incoming edges for subgraph versioning case: for each incoming edge (X, Y) adds
+  // an edge (X, Y_1) where Y_1 = Copy(Y) and add corresponding phi input to copy phi.
+  //
+  // Note: such node X will now have two successors, its unconditional branch instruction
+  // will be invalid and should be adjusted to some conditional branch by the client code.
+  void CopyIncomingEdgesForVersioning();
+
   //
   // Local versions of control flow calculation/adjustment routines.
   //
@@ -361,19 +375,19 @@
   DISALLOW_COPY_AND_ASSIGN(SuperblockCloner);
 };
 
-// Helper class to perform loop peeling/unrolling.
+// Helper class to perform loop peeling/unrolling/versioning.
 //
 // This helper should be used when correspondence map between original and copied
 // basic blocks/instructions are demanded.
-class PeelUnrollHelper : public ValueObject {
+class LoopClonerHelper : public ValueObject {
  public:
-  PeelUnrollHelper(HLoopInformation* info,
+  LoopClonerHelper(HLoopInformation* info,
                    SuperblockCloner::HBasicBlockMap* bb_map,
                    SuperblockCloner::HInstructionMap* hir_map,
                    InductionVarRange* induction_range) :
       loop_info_(info),
       cloner_(info->GetHeader()->GetGraph(), &info->GetBlocks(), bb_map, hir_map, induction_range) {
-    // For now do peeling/unrolling only for natural loops.
+    // For now do transformations only for natural loops.
     DCHECK(!info->IsIrreducible());
   }
 
@@ -383,33 +397,121 @@
   // Returns whether the loop can be peeled/unrolled.
   bool IsLoopClonable() const { return cloner_.IsSubgraphClonable(); }
 
-  HBasicBlock* DoPeeling() { return DoPeelUnrollImpl(/* to_unroll= */ false); }
-  HBasicBlock* DoUnrolling() { return DoPeelUnrollImpl(/* to_unroll= */ true); }
+  // Perform loop peeling.
+  //
+  // Control flow of an example (ignoring critical edges splitting).
+  //
+  //       Before                    After
+  //
+  //         |B|                      |B|
+  //          |                        |
+  //          v                        v
+  //         |1|                      |1|
+  //          |                        |
+  //          v                        v
+  //         |2|<-\                  |2A|
+  //         / \  /                   / \
+  //        v   v/                   /   v
+  //       |4|  |3|                 /   |3A|
+  //        |                      /     /
+  //        v                     |     v
+  //       |E|                     \   |2|<-\
+  //                                \ / \   /
+  //                                 v   v /
+  //                                |4|  |3|
+  //                                 |
+  //                                 v
+  //                                |E|
+  HBasicBlock* DoPeeling() {
+    return DoLoopTransformationImpl(TransformationKind::kPeeling);
+  }
+
+  // Perform loop unrolling.
+  //
+  // Control flow of an example (ignoring critical edges splitting).
+  //
+  //       Before                    After
+  //
+  //         |B|                      |B|
+  //          |                        |
+  //          v                        v
+  //         |1|                      |1|
+  //          |                        |
+  //          v                        v
+  //         |2|<-\                   |2A|<-\
+  //         / \  /                   / \    \
+  //        v   v/                   /   v    \
+  //       |4|  |3|                 /   |3A|   |
+  //        |                      /     /    /
+  //        v                     |     v    /
+  //       |E|                     \   |2|  /
+  //                                \ / \  /
+  //                                 v   v/
+  //                                |4| |3|
+  //                                 |
+  //                                 v
+  //                                |E|
+  HBasicBlock* DoUnrolling() {
+    return DoLoopTransformationImpl(TransformationKind::kUnrolling);
+  }
+
+  // Perform loop versioning.
+  //
+  // Control flow of an example (ignoring critical edges splitting).
+  //
+  //       Before                    After
+  //
+  //         |B|                      |B|
+  //          |                        |
+  //          v                        v
+  //         |1|                      |1|_________
+  //          |                        |          |
+  //          v                        v          v
+  //         |2|<-\                   |2|<-\     |2A|<-\
+  //         / \  /                   / \  /     /  \  /
+  //        v   v/                   |   v/      |   v/
+  //        |   |3|                  |  |3|      | |3A|
+  //        |                        | __________|
+  //        |                        ||
+  //        v                        vv
+  //       |4|                       |4|
+  //        |                         |
+  //        v                         v
+  //       |E|                       |E|
+  HBasicBlock* DoVersioning() {
+    return DoLoopTransformationImpl(TransformationKind::kVersioning);
+  }
+
   HLoopInformation* GetRegionToBeAdjusted() const { return cloner_.GetRegionToBeAdjusted(); }
 
  protected:
-  // Applies loop peeling/unrolling for the loop specified by 'loop_info'.
-  //
-  // Depending on 'do_unroll' either unrolls loop by 2 or peels one iteration from it.
-  HBasicBlock* DoPeelUnrollImpl(bool to_unroll);
+  enum class TransformationKind {
+    kPeeling,
+    kUnrolling,
+    kVersioning,
+  };
+
+  // Applies a specific loop transformation to the loop.
+  HBasicBlock* DoLoopTransformationImpl(TransformationKind transformation);
 
  private:
   HLoopInformation* loop_info_;
   SuperblockCloner cloner_;
 
-  DISALLOW_COPY_AND_ASSIGN(PeelUnrollHelper);
+  DISALLOW_COPY_AND_ASSIGN(LoopClonerHelper);
 };
 
-// Helper class to perform loop peeling/unrolling.
+// Helper class to perform loop peeling/unrolling/versioning.
 //
 // This helper should be used when there is no need to get correspondence information between
 // original and copied basic blocks/instructions.
-class PeelUnrollSimpleHelper : public ValueObject {
+class LoopClonerSimpleHelper : public ValueObject {
  public:
-  PeelUnrollSimpleHelper(HLoopInformation* info, InductionVarRange* induction_range);
+  LoopClonerSimpleHelper(HLoopInformation* info, InductionVarRange* induction_range);
   bool IsLoopClonable() const { return helper_.IsLoopClonable(); }
   HBasicBlock* DoPeeling() { return helper_.DoPeeling(); }
   HBasicBlock* DoUnrolling() { return helper_.DoUnrolling(); }
+  HBasicBlock* DoVersioning() { return helper_.DoVersioning(); }
   HLoopInformation* GetRegionToBeAdjusted() const { return helper_.GetRegionToBeAdjusted(); }
 
   const SuperblockCloner::HBasicBlockMap* GetBasicBlockMap() const { return &bb_map_; }
@@ -418,9 +520,9 @@
  private:
   SuperblockCloner::HBasicBlockMap bb_map_;
   SuperblockCloner::HInstructionMap hir_map_;
-  PeelUnrollHelper helper_;
+  LoopClonerHelper helper_;
 
-  DISALLOW_COPY_AND_ASSIGN(PeelUnrollSimpleHelper);
+  DISALLOW_COPY_AND_ASSIGN(LoopClonerSimpleHelper);
 };
 
 // Collects edge remapping info for loop peeling/unrolling for the loop specified by loop info.
diff --git a/compiler/optimizing/superblock_cloner_test.cc b/compiler/optimizing/superblock_cloner_test.cc
index ddcf154..d8d68b7 100644
--- a/compiler/optimizing/superblock_cloner_test.cc
+++ b/compiler/optimizing/superblock_cloner_test.cc
@@ -30,27 +30,23 @@
 
 // This class provides methods and helpers for testing various cloning and copying routines:
 // individual instruction cloning and cloning of the more coarse-grain structures.
-class SuperblockClonerTest : public ImprovedOptimizingUnitTest {
- private:
-  void CreateParameters() override {
-    parameters_.push_back(new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
-                                                               dex::TypeIndex(0),
-                                                               0,
-                                                               DataType::Type::kInt32));
+class SuperblockClonerTest : public OptimizingUnitTest {
+ protected:
+  void InitGraphAndParameters() {
+    InitGraph();
+    AddParameter(new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
+                                                      dex::TypeIndex(0),
+                                                      0,
+                                                      DataType::Type::kInt32));
   }
 
- public:
   void CreateBasicLoopControlFlow(HBasicBlock* position,
                                   HBasicBlock* successor,
                                   /* out */ HBasicBlock** header_p,
                                   /* out */ HBasicBlock** body_p) {
-    HBasicBlock* loop_preheader = new (GetAllocator()) HBasicBlock(graph_);
-    HBasicBlock* loop_header = new (GetAllocator()) HBasicBlock(graph_);
-    HBasicBlock* loop_body = new (GetAllocator()) HBasicBlock(graph_);
-
-    graph_->AddBlock(loop_preheader);
-    graph_->AddBlock(loop_header);
-    graph_->AddBlock(loop_body);
+    HBasicBlock* loop_preheader = AddNewBlock();
+    HBasicBlock* loop_header = AddNewBlock();
+    HBasicBlock* loop_body = AddNewBlock();
 
     position->ReplaceSuccessor(successor, loop_preheader);
 
@@ -121,7 +117,7 @@
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
 
-  InitGraph();
+  InitGraphAndParameters();
   CreateBasicLoopControlFlow(entry_block_, return_block_, &header, &loop_body);
   CreateBasicLoopDataFlow(header, loop_body);
   graph_->BuildDominatorTree();
@@ -151,9 +147,9 @@
 TEST_F(SuperblockClonerTest, CloneBasicBlocks) {
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
-  ArenaAllocator* arena = graph_->GetAllocator();
+  ArenaAllocator* arena = GetAllocator();
 
-  InitGraph();
+  InitGraphAndParameters();
   CreateBasicLoopControlFlow(entry_block_, return_block_, &header, &loop_body);
   CreateBasicLoopDataFlow(header, loop_body);
   graph_->BuildDominatorTree();
@@ -232,9 +228,9 @@
 TEST_F(SuperblockClonerTest, AdjustControlFlowInfo) {
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
-  ArenaAllocator* arena = graph_->GetAllocator();
+  ArenaAllocator* arena = GetAllocator();
 
-  InitGraph();
+  InitGraphAndParameters();
   CreateBasicLoopControlFlow(entry_block_, return_block_, &header, &loop_body);
   CreateBasicLoopDataFlow(header, loop_body);
   graph_->BuildDominatorTree();
@@ -271,13 +267,12 @@
 TEST_F(SuperblockClonerTest, IsGraphConnected) {
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
-  ArenaAllocator* arena = graph_->GetAllocator();
+  ArenaAllocator* arena = GetAllocator();
 
-  InitGraph();
+  InitGraphAndParameters();
   CreateBasicLoopControlFlow(entry_block_, return_block_, &header, &loop_body);
   CreateBasicLoopDataFlow(header, loop_body);
-  HBasicBlock* unreachable_block = new (GetAllocator()) HBasicBlock(graph_);
-  graph_->AddBlock(unreachable_block);
+  HBasicBlock* unreachable_block = AddNewBlock();
 
   HBasicBlockSet bb_set(
       arena, graph_->GetBlocks().size(), false, kArenaAllocSuperblockCloner);
@@ -292,34 +287,12 @@
 
 // Tests SuperblockCloner for loop peeling case.
 //
-// Control Flow of the example (ignoring critical edges splitting).
-//
-//       Before                    After
-//
-//         |B|                      |B|
-//          |                        |
-//          v                        v
-//         |1|                      |1|
-//          |                        |
-//          v                        v
-//         |2|<-\              (6) |2A|
-//         / \  /                   / \
-//        v   v/                   /   v
-//       |4|  |3|                 /   |3A| (7)
-//        |                      /     /
-//        v                     |     v
-//       |E|                     \   |2|<-\
-//                                \ / \   /
-//                                 v   v /
-//                                |4|  |3|
-//                                 |
-//                                 v
-//                                |E|
+// See an ASCII graphics example near LoopClonerHelper::DoPeeling.
 TEST_F(SuperblockClonerTest, LoopPeeling) {
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
 
-  InitGraph();
+  InitGraphAndParameters();
   CreateBasicLoopControlFlow(entry_block_, return_block_, &header, &loop_body);
   CreateBasicLoopDataFlow(header, loop_body);
   graph_->BuildDominatorTree();
@@ -331,7 +304,7 @@
       std::less<HInstruction*>(), graph_->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
 
   HLoopInformation* loop_info = header->GetLoopInformation();
-  PeelUnrollHelper helper(loop_info, &bb_map, &hir_map, /* induction_range= */ nullptr);
+  LoopClonerHelper helper(loop_info, &bb_map, &hir_map, /* induction_range= */ nullptr);
   EXPECT_TRUE(helper.IsLoopClonable());
   HBasicBlock* new_header = helper.DoPeeling();
   HLoopInformation* new_loop_info = new_header->GetLoopInformation();
@@ -351,34 +324,12 @@
 
 // Tests SuperblockCloner for loop unrolling case.
 //
-// Control Flow of the example (ignoring critical edges splitting).
-//
-//       Before                    After
-//
-//         |B|                      |B|
-//          |                        |
-//          v                        v
-//         |1|                      |1|
-//          |                        |
-//          v                        v
-//         |2|<-\               (6) |2A|<-\
-//         / \  /                   / \    \
-//        v   v/                   /   v    \
-//       |4|  |3|                 /(7)|3A|   |
-//        |                      /     /    /
-//        v                     |     v    /
-//       |E|                     \   |2|  /
-//                                \ / \  /
-//                                 v   v/
-//                                |4| |3|
-//                                 |
-//                                 v
-//                                |E|
+// See an ASCII graphics example near LoopClonerHelper::DoUnrolling.
 TEST_F(SuperblockClonerTest, LoopUnrolling) {
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
 
-  InitGraph();
+  InitGraphAndParameters();
   CreateBasicLoopControlFlow(entry_block_, return_block_, &header, &loop_body);
   CreateBasicLoopDataFlow(header, loop_body);
   graph_->BuildDominatorTree();
@@ -390,7 +341,7 @@
       std::less<HInstruction*>(), graph_->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
 
   HLoopInformation* loop_info = header->GetLoopInformation();
-  PeelUnrollHelper helper(loop_info, &bb_map, &hir_map, /* induction_range= */ nullptr);
+  LoopClonerHelper helper(loop_info, &bb_map, &hir_map, /* induction_range= */ nullptr);
   EXPECT_TRUE(helper.IsLoopClonable());
   HBasicBlock* new_header = helper.DoUnrolling();
 
@@ -408,22 +359,69 @@
   EXPECT_EQ(loop_info->GetBackEdges()[0], bb_map.Get(loop_body));
 }
 
+// Tests SuperblockCloner for loop versioning case.
+//
+// See an ASCII graphics example near LoopClonerHelper::DoVersioning.
+TEST_F(SuperblockClonerTest, LoopVersioning) {
+  HBasicBlock* header = nullptr;
+  HBasicBlock* loop_body = nullptr;
+
+  InitGraphAndParameters();
+  CreateBasicLoopControlFlow(entry_block_, return_block_, &header, &loop_body);
+  CreateBasicLoopDataFlow(header, loop_body);
+  graph_->BuildDominatorTree();
+  EXPECT_TRUE(CheckGraph());
+
+  HBasicBlockMap bb_map(
+      std::less<HBasicBlock*>(), graph_->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
+  HInstructionMap hir_map(
+      std::less<HInstruction*>(), graph_->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
+
+  HLoopInformation* loop_info = header->GetLoopInformation();
+  HBasicBlock* original_preheader = loop_info->GetPreHeader();
+  LoopClonerHelper helper(loop_info, &bb_map, &hir_map, /* induction_range= */ nullptr);
+  EXPECT_TRUE(helper.IsLoopClonable());
+  HBasicBlock* new_header = helper.DoVersioning();
+  EXPECT_EQ(header, new_header);
+
+  EXPECT_TRUE(CheckGraph());
+
+  HBasicBlock* second_header = bb_map.Get(header);
+  HBasicBlock* second_body = bb_map.Get(loop_body);
+  HLoopInformation* second_loop_info = second_header->GetLoopInformation();
+
+  // Check loop body successors.
+  EXPECT_EQ(loop_body->GetSingleSuccessor(), header);
+  EXPECT_EQ(second_body->GetSingleSuccessor(), second_header);
+
+  // Check loop structure.
+  EXPECT_EQ(loop_info, header->GetLoopInformation());
+  EXPECT_EQ(loop_info->GetHeader(), header);
+  EXPECT_EQ(second_loop_info->GetHeader(), second_header);
+
+  EXPECT_EQ(loop_info->GetBackEdges().size(), 1u);
+  EXPECT_EQ(second_loop_info->GetBackEdges().size(), 1u);
+
+  EXPECT_EQ(loop_info->GetBackEdges()[0], loop_body);
+  EXPECT_EQ(second_loop_info->GetBackEdges()[0], second_body);
+
+  EXPECT_EQ(original_preheader->GetSuccessors().size(), 2u);
+}
+
 // Checks that loop unrolling works fine for a loop with multiple back edges. Tests that after
 // the transformation the loop has a single preheader.
 TEST_F(SuperblockClonerTest, LoopPeelingMultipleBackEdges) {
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
 
-  InitGraph();
+  InitGraphAndParameters();
   CreateBasicLoopControlFlow(entry_block_, return_block_, &header, &loop_body);
   CreateBasicLoopDataFlow(header, loop_body);
 
   // Transform a basic loop to have multiple back edges.
   HBasicBlock* latch = header->GetSuccessors()[1];
-  HBasicBlock* if_block = new (GetAllocator()) HBasicBlock(graph_);
-  HBasicBlock* temp1 = new (GetAllocator()) HBasicBlock(graph_);
-  graph_->AddBlock(if_block);
-  graph_->AddBlock(temp1);
+  HBasicBlock* if_block = AddNewBlock();
+  HBasicBlock* temp1 = AddNewBlock();
   header->ReplaceSuccessor(latch, if_block);
   if_block->AddSuccessor(latch);
   if_block->AddSuccessor(temp1);
@@ -445,7 +443,7 @@
   EXPECT_TRUE(CheckGraph());
 
   HLoopInformation* loop_info = header->GetLoopInformation();
-  PeelUnrollSimpleHelper helper(loop_info, /* induction_range= */ nullptr);
+  LoopClonerSimpleHelper helper(loop_info, /* induction_range= */ nullptr);
   HBasicBlock* new_header = helper.DoPeeling();
   EXPECT_EQ(header, new_header);
 
@@ -469,7 +467,7 @@
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
 
-  InitGraph();
+  InitGraphAndParameters();
 
   // Create the following nested structure of loops
   //   Headers:  1    2 3
@@ -494,7 +492,7 @@
 
   // Check nested loops structure.
   CheckLoopStructureForLoopPeelingNested(loop1_header, loop2_header, loop3_header);
-  PeelUnrollSimpleHelper helper(loop1_header->GetLoopInformation(), /* induction_range= */ nullptr);
+  LoopClonerSimpleHelper helper(loop1_header->GetLoopInformation(), /* induction_range= */ nullptr);
   helper.DoPeeling();
   // Check that nested loops structure has not changed after the transformation.
   CheckLoopStructureForLoopPeelingNested(loop1_header, loop2_header, loop3_header);
@@ -516,7 +514,7 @@
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
 
-  InitGraph();
+  InitGraphAndParameters();
 
   // Create the following nested structure of loops
   //   Headers:  1 2 3        4
@@ -540,7 +538,7 @@
   graph_->BuildDominatorTree();
   EXPECT_TRUE(CheckGraph());
 
-  PeelUnrollSimpleHelper helper(loop3_header->GetLoopInformation(), /* induction_range= */ nullptr);
+  LoopClonerSimpleHelper helper(loop3_header->GetLoopInformation(), /* induction_range= */ nullptr);
   helper.DoPeeling();
   HLoopInformation* loop1 = loop1_header->GetLoopInformation();
   HLoopInformation* loop2 = loop2_header->GetLoopInformation();
@@ -573,7 +571,7 @@
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
 
-  InitGraph();
+  InitGraphAndParameters();
 
   // Create the following nested structure of loops then peel loop3.
   //   Headers:  1 2 3
@@ -592,8 +590,7 @@
   HBasicBlock* loop_body3 = loop_body;
 
   // Change the loop3 - insert an exit which leads to loop1.
-  HBasicBlock* loop3_extra_if_block = new (GetAllocator()) HBasicBlock(graph_);
-  graph_->AddBlock(loop3_extra_if_block);
+  HBasicBlock* loop3_extra_if_block = AddNewBlock();
   loop3_extra_if_block->AddInstruction(new (GetAllocator()) HIf(parameters_[0]));
 
   loop3_header->ReplaceSuccessor(loop_body3, loop3_extra_if_block);
@@ -606,7 +603,7 @@
   HBasicBlock* loop3_long_exit = loop3_extra_if_block->GetSuccessors()[0];
   EXPECT_TRUE(loop1_header->GetLoopInformation()->Contains(*loop3_long_exit));
 
-  PeelUnrollSimpleHelper helper(loop3_header->GetLoopInformation(), /* induction_range= */ nullptr);
+  LoopClonerSimpleHelper helper(loop3_header->GetLoopInformation(), /* induction_range= */ nullptr);
   helper.DoPeeling();
 
   HLoopInformation* loop1 = loop1_header->GetLoopInformation();
@@ -626,9 +623,9 @@
 TEST_F(SuperblockClonerTest, FastCaseCheck) {
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
-  ArenaAllocator* arena = graph_->GetAllocator();
+  ArenaAllocator* arena = GetAllocator();
 
-  InitGraph();
+  InitGraphAndParameters();
   CreateBasicLoopControlFlow(entry_block_, return_block_, &header, &loop_body);
   CreateBasicLoopDataFlow(header, loop_body);
   graph_->BuildDominatorTree();
@@ -683,7 +680,7 @@
   HBasicBlock* header = nullptr;
   HBasicBlock* loop_body = nullptr;
 
-  InitGraph();
+  InitGraphAndParameters();
 
   // Create the following nested structure of loops
   //   Headers:  1 2 3      4      5
diff --git a/compiler/utils/arm/assembler_arm_vixl.h b/compiler/utils/arm/assembler_arm_vixl.h
index 59d7edd..5bc8a70 100644
--- a/compiler/utils/arm/assembler_arm_vixl.h
+++ b/compiler/utils/arm/assembler_arm_vixl.h
@@ -180,10 +180,17 @@
   void FinalizeInstructions(const MemoryRegion& region) override;
 
   void Bind(Label* label ATTRIBUTE_UNUSED) override {
-    UNIMPLEMENTED(FATAL) << "Do not use Bind for ARM";
+    UNIMPLEMENTED(FATAL) << "Do not use Bind(Label*) for ARM";
   }
   void Jump(Label* label ATTRIBUTE_UNUSED) override {
-    UNIMPLEMENTED(FATAL) << "Do not use Jump for ARM";
+    UNIMPLEMENTED(FATAL) << "Do not use Jump(Label*) for ARM";
+  }
+
+  void Bind(vixl::aarch32::Label* label) {
+    vixl_masm_.Bind(label);
+  }
+  void Jump(vixl::aarch32::Label* label) {
+    vixl_masm_.B(label);
   }
 
   //
diff --git a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
index ffb58ac..70a1939 100644
--- a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
+++ b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
@@ -41,6 +41,9 @@
 static constexpr size_t kAapcsStackAlignment = 8u;
 static_assert(kAapcsStackAlignment < kStackAlignment);
 
+// STRD immediate can encode any 4-byte aligned offset smaller than this cutoff.
+static constexpr size_t kStrdOffsetCutoff = 1024u;
+
 vixl::aarch32::Register AsVIXLRegister(ArmManagedRegister reg) {
   CHECK(reg.IsCoreRegister());
   return vixl::aarch32::Register(reg.RegId());
@@ -76,8 +79,7 @@
 
 void ArmVIXLJNIMacroAssembler::BuildFrame(size_t frame_size,
                                           ManagedRegister method_reg,
-                                          ArrayRef<const ManagedRegister> callee_save_regs,
-                                          const ManagedRegisterEntrySpills& entry_spills) {
+                                          ArrayRef<const ManagedRegister> callee_save_regs) {
   // If we're creating an actual frame with the method, enforce managed stack alignment,
   // otherwise only the native stack alignment.
   if (method_reg.IsNoRegister()) {
@@ -96,7 +98,17 @@
       fp_spill_mask |= 1 << reg.AsArm().AsSRegister();
     }
   }
-  if (core_spill_mask != 0u) {
+  if (core_spill_mask == (1u << lr.GetCode()) &&
+      fp_spill_mask == 0u &&
+      frame_size == 2 * kFramePointerSize &&
+      !method_reg.IsRegister()) {
+    // Special case: Only LR to push and one word to skip. Do this with a single
+    // 16-bit PUSH instruction by arbitrarily pushing r3 (without CFI for r3).
+    core_spill_mask |= 1u << r3.GetCode();
+    ___ Push(RegisterList(core_spill_mask));
+    cfi().AdjustCFAOffset(2 * kFramePointerSize);
+    cfi().RelOffset(DWARFReg(lr), kFramePointerSize);
+  } else if (core_spill_mask != 0u) {
     ___ Push(RegisterList(core_spill_mask));
     cfi().AdjustCFAOffset(POPCOUNT(core_spill_mask) * kFramePointerSize);
     cfi().RelOffsetForMany(DWARFReg(r0), 0, core_spill_mask, kFramePointerSize);
@@ -123,32 +135,12 @@
     CHECK(r0.Is(AsVIXLRegister(method_reg.AsArm())));
     asm_.StoreToOffset(kStoreWord, r0, sp, 0);
   }
-
-  // Write out entry spills.
-  int32_t offset = frame_size + kFramePointerSize;
-  for (const ManagedRegisterSpill& spill : entry_spills) {
-    ArmManagedRegister reg = spill.AsArm();
-    if (reg.IsNoRegister()) {
-      // only increment stack offset.
-      offset += spill.getSize();
-    } else if (reg.IsCoreRegister()) {
-      asm_.StoreToOffset(kStoreWord, AsVIXLRegister(reg), sp, offset);
-      offset += 4;
-    } else if (reg.IsSRegister()) {
-      asm_.StoreSToOffset(AsVIXLSRegister(reg), sp, offset);
-      offset += 4;
-    } else if (reg.IsDRegister()) {
-      asm_.StoreDToOffset(AsVIXLDRegister(reg), sp, offset);
-      offset += 8;
-    }
-  }
 }
 
 void ArmVIXLJNIMacroAssembler::RemoveFrame(size_t frame_size,
                                            ArrayRef<const ManagedRegister> callee_save_regs,
                                            bool may_suspend) {
   CHECK_ALIGNED(frame_size, kAapcsStackAlignment);
-  cfi().RememberState();
 
   // Compute callee saves to pop.
   RegList core_spill_mask = 0u;
@@ -161,6 +153,32 @@
     }
   }
 
+  // Pop LR to PC unless we need to emit some read barrier code just before returning.
+  bool emit_code_before_return =
+      (kEmitCompilerReadBarrier && kUseBakerReadBarrier) &&
+      (may_suspend || (kIsDebugBuild && emit_run_time_checks_in_debug_mode_));
+  if ((core_spill_mask & (1u << lr.GetCode())) != 0u && !emit_code_before_return) {
+    DCHECK_EQ(core_spill_mask & (1u << pc.GetCode()), 0u);
+    core_spill_mask ^= (1u << lr.GetCode()) | (1u << pc.GetCode());
+  }
+
+  // If there are no FP registers to pop and we pop PC, we can avoid emitting any CFI.
+  if (fp_spill_mask == 0u && (core_spill_mask & (1u << pc.GetCode())) != 0u) {
+    if (frame_size == POPCOUNT(core_spill_mask) * kFramePointerSize) {
+      // Just pop all registers and avoid CFI.
+      ___ Pop(RegisterList(core_spill_mask));
+      return;
+    } else if (frame_size == 8u && core_spill_mask == (1u << pc.GetCode())) {
+      // Special case: One word to ignore and one to pop to PC. We are free to clobber the
+      // caller-save register r3 on return, so use a 16-bit POP instruction and avoid CFI.
+      ___ Pop(RegisterList((1u << r3.GetCode()) | (1u << pc.GetCode())));
+      return;
+    }
+  }
+
+  // We shall need to adjust CFI and restore it after the frame exit sequence.
+  cfi().RememberState();
+
   // Decrease frame to start of callee saves.
   size_t pop_values = POPCOUNT(core_spill_mask) + POPCOUNT(fp_spill_mask);
   CHECK_GE(frame_size, pop_values * kFramePointerSize);
@@ -177,9 +195,24 @@
     cfi().RestoreMany(DWARFReg(s0), fp_spill_mask);
   }
 
-  // Pop core callee saves and LR.
+  // Pop core callee saves.
   if (core_spill_mask != 0u) {
-    ___ Pop(RegisterList(core_spill_mask));
+    if (IsPowerOfTwo(core_spill_mask) &&
+        core_spill_mask != (1u << pc.GetCode()) &&
+        WhichPowerOf2(core_spill_mask) >= 8) {
+      // FIXME(vixl): vixl fails to transform a pop with single high register
+      // to a post-index STR (also known as POP encoding T3) and emits the LDMIA
+      // (also known as POP encoding T2) which is UNPREDICTABLE for 1 register.
+      // So we have to explicitly do the transformation here. Bug: 178048807
+      vixl32::Register reg(WhichPowerOf2(core_spill_mask));
+      ___ Ldr(reg, MemOperand(sp, kFramePointerSize, PostIndex));
+    } else {
+      ___ Pop(RegisterList(core_spill_mask));
+    }
+    if ((core_spill_mask & (1u << pc.GetCode())) == 0u) {
+      cfi().AdjustCFAOffset(-kFramePointerSize * POPCOUNT(core_spill_mask));
+      cfi().RestoreMany(DWARFReg(r0), core_spill_mask);
+    }
   }
 
   if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
@@ -210,7 +243,9 @@
   }
 
   // Return to LR.
-  ___ Bx(vixl32::lr);
+  if ((core_spill_mask & (1u << pc.GetCode())) == 0u) {
+    ___ Bx(vixl32::lr);
+  }
 
   // The CFI should be restored for any code that follows the exit block.
   cfi().RestoreState();
@@ -243,8 +278,9 @@
     asm_.StoreToOffset(kStoreWord, AsVIXLRegister(src), sp, dest.Int32Value());
   } else if (src.IsRegisterPair()) {
     CHECK_EQ(8u, size);
-    asm_.StoreToOffset(kStoreWord, AsVIXLRegisterPairLow(src),  sp, dest.Int32Value());
-    asm_.StoreToOffset(kStoreWord, AsVIXLRegisterPairHigh(src), sp, dest.Int32Value() + 4);
+    ___ Strd(AsVIXLRegisterPairLow(src),
+             AsVIXLRegisterPairHigh(src),
+             MemOperand(sp, dest.Int32Value()));
   } else if (src.IsSRegister()) {
     CHECK_EQ(4u, size);
     asm_.StoreSToOffset(AsVIXLSRegister(src), sp, dest.Int32Value());
@@ -271,27 +307,35 @@
 
 void ArmVIXLJNIMacroAssembler::StoreSpanning(FrameOffset dest,
                                              ManagedRegister msrc,
-                                             FrameOffset in_off,
-                                             ManagedRegister mscratch) {
+                                             FrameOffset in_off) {
   vixl::aarch32::Register src = AsVIXLRegister(msrc.AsArm());
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
   asm_.StoreToOffset(kStoreWord, src, sp, dest.Int32Value());
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
+  vixl32::Register scratch = temps.Acquire();
   asm_.LoadFromOffset(kLoadWord, scratch, sp, in_off.Int32Value());
   asm_.StoreToOffset(kStoreWord, scratch, sp, dest.Int32Value() + 4);
 }
 
-void ArmVIXLJNIMacroAssembler::CopyRef(FrameOffset dest,
-                                       FrameOffset src,
-                                       ManagedRegister mscratch) {
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
+void ArmVIXLJNIMacroAssembler::CopyRef(FrameOffset dest, FrameOffset src) {
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
+  vixl32::Register scratch = temps.Acquire();
   asm_.LoadFromOffset(kLoadWord, scratch, sp, src.Int32Value());
   asm_.StoreToOffset(kStoreWord, scratch, sp, dest.Int32Value());
 }
 
+void ArmVIXLJNIMacroAssembler::CopyRef(FrameOffset dest,
+                                       ManagedRegister base,
+                                       MemberOffset offs,
+                                       bool unpoison_reference) {
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  vixl32::Register scratch = temps.Acquire();
+  asm_.LoadFromOffset(kLoadWord, scratch, AsVIXLRegister(base.AsArm()), offs.Int32Value());
+  if (unpoison_reference) {
+    asm_.MaybeUnpoisonHeapReference(scratch);
+  }
+  asm_.StoreToOffset(kStoreWord, scratch, sp, dest.Int32Value());
+}
+
 void ArmVIXLJNIMacroAssembler::LoadRef(ManagedRegister mdest,
                                        ManagedRegister mbase,
                                        MemberOffset offs,
@@ -318,12 +362,9 @@
   UNIMPLEMENTED(FATAL);
 }
 
-void ArmVIXLJNIMacroAssembler::StoreImmediateToFrame(FrameOffset dest,
-                                                     uint32_t imm,
-                                                     ManagedRegister mscratch) {
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
+void ArmVIXLJNIMacroAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm) {
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
+  vixl32::Register scratch = temps.Acquire();
   asm_.LoadImmediate(scratch, imm);
   asm_.StoreToOffset(kStoreWord, scratch, sp, dest.Int32Value());
 }
@@ -345,12 +386,9 @@
   asm_.LoadFromOffset(kLoadWord, dest, tr, offs.Int32Value());
 }
 
-void ArmVIXLJNIMacroAssembler::CopyRawPtrFromThread(FrameOffset fr_offs,
-                                                    ThreadOffset32 thr_offs,
-                                                    ManagedRegister mscratch) {
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
+void ArmVIXLJNIMacroAssembler::CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset32 thr_offs) {
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
+  vixl32::Register scratch = temps.Acquire();
   asm_.LoadFromOffset(kLoadWord, scratch, tr, thr_offs.Int32Value());
   asm_.StoreToOffset(kStoreWord, scratch, sp, fr_offs.Int32Value());
 }
@@ -362,11 +400,9 @@
 }
 
 void ArmVIXLJNIMacroAssembler::StoreStackOffsetToThread(ThreadOffset32 thr_offs,
-                                                        FrameOffset fr_offs,
-                                                        ManagedRegister mscratch) {
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
+                                                        FrameOffset fr_offs) {
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
+  vixl32::Register scratch = temps.Acquire();
   asm_.AddConstant(scratch, sp, fr_offs.Int32Value());
   asm_.StoreToOffset(kStoreWord, scratch, tr, thr_offs.Int32Value());
 }
@@ -385,17 +421,338 @@
   UNIMPLEMENTED(FATAL) << "no zero extension necessary for arm";
 }
 
+static inline bool IsCoreRegisterOrPair(ArmManagedRegister reg) {
+  return reg.IsCoreRegister() || reg.IsRegisterPair();
+}
+
+static inline bool NoSpillGap(const ArgumentLocation& loc1, const ArgumentLocation& loc2) {
+  DCHECK(!loc1.IsRegister());
+  DCHECK(!loc2.IsRegister());
+  uint32_t loc1_offset = loc1.GetFrameOffset().Uint32Value();
+  uint32_t loc2_offset = loc2.GetFrameOffset().Uint32Value();
+  DCHECK_LT(loc1_offset, loc2_offset);
+  return loc1_offset + loc1.GetSize() == loc2_offset;
+}
+
+static inline uint32_t GetSRegisterNumber(ArmManagedRegister reg) {
+  if (reg.IsSRegister()) {
+    return static_cast<uint32_t>(reg.AsSRegister());
+  } else {
+    DCHECK(reg.IsDRegister());
+    return 2u * static_cast<uint32_t>(reg.AsDRegister());
+  }
+}
+
+// Get the number of locations to spill together.
+static inline size_t GetSpillChunkSize(ArrayRef<ArgumentLocation> dests,
+                                       ArrayRef<ArgumentLocation> srcs,
+                                       size_t start,
+                                       bool have_extra_temp) {
+  DCHECK_LT(start, dests.size());
+  DCHECK_ALIGNED(dests[start].GetFrameOffset().Uint32Value(), 4u);
+  const ArgumentLocation& first_src = srcs[start];
+  if (!first_src.IsRegister()) {
+    DCHECK_ALIGNED(first_src.GetFrameOffset().Uint32Value(), 4u);
+    // If we have an extra temporary, look for opportunities to move 2 words
+    // at a time with LDRD/STRD when the source types are word-sized.
+    if (have_extra_temp &&
+        start + 1u != dests.size() &&
+        !srcs[start + 1u].IsRegister() &&
+        first_src.GetSize() == 4u &&
+        srcs[start + 1u].GetSize() == 4u &&
+        NoSpillGap(first_src, srcs[start + 1u]) &&
+        NoSpillGap(dests[start], dests[start + 1u]) &&
+        dests[start].GetFrameOffset().Uint32Value() < kStrdOffsetCutoff) {
+      // Note: The source and destination may not be 8B aligned (but they are 4B aligned).
+      return 2u;
+    }
+    return 1u;
+  }
+  ArmManagedRegister first_src_reg = first_src.GetRegister().AsArm();
+  size_t end = start + 1u;
+  if (IsCoreRegisterOrPair(first_src_reg)) {
+    while (end != dests.size() &&
+           NoSpillGap(dests[end - 1u], dests[end]) &&
+           srcs[end].IsRegister() &&
+           IsCoreRegisterOrPair(srcs[end].GetRegister().AsArm())) {
+      ++end;
+    }
+  } else {
+    DCHECK(first_src_reg.IsSRegister() || first_src_reg.IsDRegister());
+    uint32_t next_sreg = GetSRegisterNumber(first_src_reg) + first_src.GetSize() / kSRegSizeInBytes;
+    while (end != dests.size() &&
+           NoSpillGap(dests[end - 1u], dests[end]) &&
+           srcs[end].IsRegister() &&
+           !IsCoreRegisterOrPair(srcs[end].GetRegister().AsArm()) &&
+           GetSRegisterNumber(srcs[end].GetRegister().AsArm()) == next_sreg) {
+      next_sreg += srcs[end].GetSize() / kSRegSizeInBytes;
+      ++end;
+    }
+  }
+  return end - start;
+}
+
+static inline uint32_t GetCoreRegisterMask(ArmManagedRegister reg) {
+  if (reg.IsCoreRegister()) {
+    return 1u << static_cast<size_t>(reg.AsCoreRegister());
+  } else {
+    DCHECK(reg.IsRegisterPair());
+    DCHECK_LT(reg.AsRegisterPairLow(), reg.AsRegisterPairHigh());
+    return (1u << static_cast<size_t>(reg.AsRegisterPairLow())) |
+           (1u << static_cast<size_t>(reg.AsRegisterPairHigh()));
+  }
+}
+
+static inline uint32_t GetCoreRegisterMask(ArrayRef<ArgumentLocation> srcs) {
+  uint32_t mask = 0u;
+  for (const ArgumentLocation& loc : srcs) {
+    DCHECK(loc.IsRegister());
+    mask |= GetCoreRegisterMask(loc.GetRegister().AsArm());
+  }
+  return mask;
+}
+
+static inline bool UseStrdForChunk(ArrayRef<ArgumentLocation> srcs, size_t start, size_t length) {
+  DCHECK_GE(length, 2u);
+  DCHECK(srcs[start].IsRegister());
+  DCHECK(srcs[start + 1u].IsRegister());
+  // The destination may not be 8B aligned (but it is 4B aligned).
+  // Allow arbitrary destination offset, macro assembler will use a temp if needed.
+  // Note: T32 allows unrelated registers in STRD. (A32 does not.)
+  return length == 2u &&
+         srcs[start].GetRegister().AsArm().IsCoreRegister() &&
+         srcs[start + 1u].GetRegister().AsArm().IsCoreRegister();
+}
+
+static inline bool UseVstrForChunk(ArrayRef<ArgumentLocation> srcs, size_t start, size_t length) {
+  DCHECK_GE(length, 2u);
+  DCHECK(srcs[start].IsRegister());
+  DCHECK(srcs[start + 1u].IsRegister());
+  // The destination may not be 8B aligned (but it is 4B aligned).
+  // Allow arbitrary destination offset, macro assembler will use a temp if needed.
+  return length == 2u &&
+         srcs[start].GetRegister().AsArm().IsSRegister() &&
+         srcs[start + 1u].GetRegister().AsArm().IsSRegister() &&
+         IsAligned<2u>(static_cast<size_t>(srcs[start].GetRegister().AsArm().AsSRegister()));
+}
+
+void ArmVIXLJNIMacroAssembler::MoveArguments(ArrayRef<ArgumentLocation> dests,
+                                             ArrayRef<ArgumentLocation> srcs) {
+  DCHECK_EQ(dests.size(), srcs.size());
+
+  // Native ABI is soft-float, so all destinations should be core registers or stack offsets.
+  // And register locations should be first, followed by stack locations with increasing offset.
+  auto is_register = [](const ArgumentLocation& loc) { return loc.IsRegister(); };
+  DCHECK(std::is_partitioned(dests.begin(), dests.end(), is_register));
+  size_t num_reg_dests =
+      std::distance(dests.begin(), std::partition_point(dests.begin(), dests.end(), is_register));
+  DCHECK(std::is_sorted(
+      dests.begin() + num_reg_dests,
+      dests.end(),
+      [](const ArgumentLocation& lhs, const ArgumentLocation& rhs) {
+        return lhs.GetFrameOffset().Uint32Value() < rhs.GetFrameOffset().Uint32Value();
+      }));
+
+  // Collect registers to move. No need to record FP regs as destinations are only core regs.
+  uint32_t src_regs = 0u;
+  uint32_t dest_regs = 0u;
+  for (size_t i = 0; i != num_reg_dests; ++i) {
+    const ArgumentLocation& src = srcs[i];
+    const ArgumentLocation& dest = dests[i];
+    DCHECK(dest.IsRegister() && IsCoreRegisterOrPair(dest.GetRegister().AsArm()));
+    if (src.IsRegister() && IsCoreRegisterOrPair(src.GetRegister().AsArm())) {
+      if (src.GetRegister().Equals(dest.GetRegister())) {
+        continue;
+      }
+      src_regs |= GetCoreRegisterMask(src.GetRegister().AsArm());
+    }
+    dest_regs |= GetCoreRegisterMask(dest.GetRegister().AsArm());
+  }
+
+  // Spill args first. Look for opportunities to spill multiple arguments at once.
+  {
+    UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+    vixl32::Register xtemp;  // Extra temp register;
+    if ((dest_regs & ~src_regs) != 0u) {
+      xtemp = vixl32::Register(CTZ(dest_regs & ~src_regs));
+      DCHECK(!temps.IsAvailable(xtemp));
+    }
+    auto move_two_words = [&](FrameOffset dest_offset, FrameOffset src_offset) {
+      DCHECK(xtemp.IsValid());
+      DCHECK_LT(dest_offset.Uint32Value(), kStrdOffsetCutoff);
+      // VIXL macro assembler can use destination registers for loads from large offsets.
+      UseScratchRegisterScope temps2(asm_.GetVIXLAssembler());
+      vixl32::Register temp2 = temps2.Acquire();
+      ___ Ldrd(xtemp, temp2, MemOperand(sp, src_offset.Uint32Value()));
+      ___ Strd(xtemp, temp2, MemOperand(sp, dest_offset.Uint32Value()));
+    };
+    for (size_t i = num_reg_dests, arg_count = dests.size(); i != arg_count; ) {
+      const ArgumentLocation& src = srcs[i];
+      const ArgumentLocation& dest = dests[i];
+      DCHECK_EQ(src.GetSize(), dest.GetSize());
+      DCHECK(!dest.IsRegister());
+      uint32_t frame_offset = dest.GetFrameOffset().Uint32Value();
+      size_t chunk_size = GetSpillChunkSize(dests, srcs, i, xtemp.IsValid());
+      DCHECK_NE(chunk_size, 0u);
+      if (chunk_size == 1u) {
+        if (src.IsRegister()) {
+          Store(dest.GetFrameOffset(), src.GetRegister(), dest.GetSize());
+        } else if (dest.GetSize() == 8u && xtemp.IsValid() && frame_offset < kStrdOffsetCutoff) {
+          move_two_words(dest.GetFrameOffset(), src.GetFrameOffset());
+        } else {
+          Copy(dest.GetFrameOffset(), src.GetFrameOffset(), dest.GetSize());
+        }
+      } else if (!src.IsRegister()) {
+        DCHECK_EQ(chunk_size, 2u);
+        DCHECK_EQ(dest.GetSize(), 4u);
+        DCHECK_EQ(dests[i + 1u].GetSize(), 4u);
+        move_two_words(dest.GetFrameOffset(), src.GetFrameOffset());
+      } else if (UseStrdForChunk(srcs, i, chunk_size)) {
+        ___ Strd(AsVIXLRegister(srcs[i].GetRegister().AsArm()),
+                 AsVIXLRegister(srcs[i + 1u].GetRegister().AsArm()),
+                 MemOperand(sp, frame_offset));
+      } else if (UseVstrForChunk(srcs, i, chunk_size)) {
+        size_t sreg = GetSRegisterNumber(src.GetRegister().AsArm());
+        DCHECK_ALIGNED(sreg, 2u);
+        ___ Vstr(vixl32::DRegister(sreg / 2u), MemOperand(sp, frame_offset));
+      } else {
+        UseScratchRegisterScope temps2(asm_.GetVIXLAssembler());
+        vixl32::Register base_reg;
+        if (frame_offset == 0u) {
+          base_reg = sp;
+        } else {
+          base_reg = temps2.Acquire();
+          ___ Add(base_reg, sp, frame_offset);
+        }
+
+        ArmManagedRegister src_reg = src.GetRegister().AsArm();
+        if (IsCoreRegisterOrPair(src_reg)) {
+          uint32_t core_reg_mask = GetCoreRegisterMask(srcs.SubArray(i, chunk_size));
+          ___ Stm(base_reg, NO_WRITE_BACK, RegisterList(core_reg_mask));
+        } else {
+          uint32_t start_sreg = GetSRegisterNumber(src_reg);
+          const ArgumentLocation& last_dest = dests[i + chunk_size - 1u];
+          uint32_t total_size =
+              last_dest.GetFrameOffset().Uint32Value() + last_dest.GetSize() - frame_offset;
+          if (IsAligned<2u>(start_sreg) &&
+              IsAligned<kDRegSizeInBytes>(frame_offset) &&
+              IsAligned<kDRegSizeInBytes>(total_size)) {
+            uint32_t dreg_count = total_size / kDRegSizeInBytes;
+            DRegisterList dreg_list(vixl32::DRegister(start_sreg / 2u), dreg_count);
+            ___ Vstm(F64, base_reg, NO_WRITE_BACK, dreg_list);
+          } else {
+            uint32_t sreg_count = total_size / kSRegSizeInBytes;
+            SRegisterList sreg_list(vixl32::SRegister(start_sreg), sreg_count);
+            ___ Vstm(F32, base_reg, NO_WRITE_BACK, sreg_list);
+          }
+        }
+      }
+      i += chunk_size;
+    }
+  }
+
+  // Fill destination registers from source core registers.
+  // There should be no cycles, so this algorithm should make progress.
+  while (src_regs != 0u) {
+    uint32_t old_src_regs = src_regs;
+    for (size_t i = 0; i != num_reg_dests; ++i) {
+      DCHECK(dests[i].IsRegister() && IsCoreRegisterOrPair(dests[i].GetRegister().AsArm()));
+      if (!srcs[i].IsRegister() || !IsCoreRegisterOrPair(srcs[i].GetRegister().AsArm())) {
+        continue;
+      }
+      uint32_t dest_reg_mask = GetCoreRegisterMask(dests[i].GetRegister().AsArm());
+      if ((dest_reg_mask & dest_regs) == 0u) {
+        continue;  // Equals source, or already filled in one of previous iterations.
+      }
+      // There are no partial overlaps of 8-byte arguments, otherwise we would have to
+      // tweak this check; Move() can deal with partial overlap for historical reasons.
+      if ((dest_reg_mask & src_regs) != 0u) {
+        continue;  // Cannot clobber this register yet.
+      }
+      Move(dests[i].GetRegister(), srcs[i].GetRegister(), dests[i].GetSize());
+      uint32_t src_reg_mask = GetCoreRegisterMask(srcs[i].GetRegister().AsArm());
+      DCHECK_EQ(src_regs & src_reg_mask, src_reg_mask);
+      src_regs &= ~src_reg_mask;  // Allow clobbering the source register or pair.
+      dest_regs &= ~dest_reg_mask;  // Destination register or pair was filled.
+    }
+    CHECK_NE(old_src_regs, src_regs);
+    DCHECK_EQ(0u, src_regs & ~old_src_regs);
+  }
+
+  // Now fill destination registers from FP registers or stack slots, looking for
+  // opportunities to use LDRD/VMOV to fill 2 registers with one instruction.
+  for (size_t i = 0, j; i != num_reg_dests; i = j) {
+    j = i + 1u;
+    DCHECK(dests[i].IsRegister() && IsCoreRegisterOrPair(dests[i].GetRegister().AsArm()));
+    if (srcs[i].IsRegister() && IsCoreRegisterOrPair(srcs[i].GetRegister().AsArm())) {
+      DCHECK_EQ(GetCoreRegisterMask(dests[i].GetRegister().AsArm()) & dest_regs, 0u);
+      continue;  // Equals destination or moved above.
+    }
+    DCHECK_NE(GetCoreRegisterMask(dests[i].GetRegister().AsArm()) & dest_regs, 0u);
+    if (dests[i].GetSize() == 4u) {
+      // Find next register to load.
+      while (j != num_reg_dests &&
+             (srcs[j].IsRegister() && IsCoreRegisterOrPair(srcs[j].GetRegister().AsArm()))) {
+        DCHECK_EQ(GetCoreRegisterMask(dests[j].GetRegister().AsArm()) & dest_regs, 0u);
+        ++j;  // Equals destination or moved above.
+      }
+      if (j != num_reg_dests && dests[j].GetSize() == 4u) {
+        if (!srcs[i].IsRegister() && !srcs[j].IsRegister() && NoSpillGap(srcs[i], srcs[j])) {
+          ___ Ldrd(AsVIXLRegister(dests[i].GetRegister().AsArm()),
+                   AsVIXLRegister(dests[j].GetRegister().AsArm()),
+                   MemOperand(sp, srcs[i].GetFrameOffset().Uint32Value()));
+          ++j;
+          continue;
+        }
+        if (srcs[i].IsRegister() && srcs[j].IsRegister()) {
+          uint32_t first_sreg = GetSRegisterNumber(srcs[i].GetRegister().AsArm());
+          if (IsAligned<2u>(first_sreg) &&
+              first_sreg + 1u == GetSRegisterNumber(srcs[j].GetRegister().AsArm())) {
+            ___ Vmov(AsVIXLRegister(dests[i].GetRegister().AsArm()),
+                     AsVIXLRegister(dests[j].GetRegister().AsArm()),
+                     vixl32::DRegister(first_sreg / 2u));
+            ++j;
+            continue;
+          }
+        }
+      }
+    }
+    if (srcs[i].IsRegister()) {
+      Move(dests[i].GetRegister(), srcs[i].GetRegister(), dests[i].GetSize());
+    } else {
+      Load(dests[i].GetRegister(), srcs[i].GetFrameOffset(), dests[i].GetSize());
+    }
+  }
+}
+
 void ArmVIXLJNIMacroAssembler::Move(ManagedRegister mdst,
                                     ManagedRegister msrc,
                                     size_t size  ATTRIBUTE_UNUSED) {
   ArmManagedRegister dst = mdst.AsArm();
+  if (kIsDebugBuild) {
+    // Check that the destination is not a scratch register.
+    UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+    if (dst.IsCoreRegister()) {
+      CHECK(!temps.IsAvailable(AsVIXLRegister(dst)));
+    } else if (dst.IsDRegister()) {
+      CHECK(!temps.IsAvailable(AsVIXLDRegister(dst)));
+    } else if (dst.IsSRegister()) {
+      CHECK(!temps.IsAvailable(AsVIXLSRegister(dst)));
+    } else {
+      CHECK(dst.IsRegisterPair()) << dst;
+      CHECK(!temps.IsAvailable(AsVIXLRegisterPairLow(dst)));
+      CHECK(!temps.IsAvailable(AsVIXLRegisterPairHigh(dst)));
+    }
+  }
   ArmManagedRegister src = msrc.AsArm();
   if (!dst.Equals(src)) {
     if (dst.IsCoreRegister()) {
-      CHECK(src.IsCoreRegister()) << src;
-      UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-      temps.Exclude(AsVIXLRegister(dst));
-      ___ Mov(AsVIXLRegister(dst), AsVIXLRegister(src));
+      if (src.IsCoreRegister()) {
+        ___ Mov(AsVIXLRegister(dst), AsVIXLRegister(src));
+      } else {
+        CHECK(src.IsSRegister()) << src;
+        ___ Vmov(AsVIXLRegister(dst), AsVIXLSRegister(src));
+      }
     } else if (dst.IsDRegister()) {
       if (src.IsDRegister()) {
         ___ Vmov(F64, AsVIXLDRegister(dst), AsVIXLDRegister(src));
@@ -414,27 +771,27 @@
       }
     } else {
       CHECK(dst.IsRegisterPair()) << dst;
-      CHECK(src.IsRegisterPair()) << src;
-      // Ensure that the first move doesn't clobber the input of the second.
-      if (src.AsRegisterPairHigh() != dst.AsRegisterPairLow()) {
-        ___ Mov(AsVIXLRegisterPairLow(dst),  AsVIXLRegisterPairLow(src));
-        ___ Mov(AsVIXLRegisterPairHigh(dst), AsVIXLRegisterPairHigh(src));
+      if (src.IsRegisterPair()) {
+        // Ensure that the first move doesn't clobber the input of the second.
+        if (src.AsRegisterPairHigh() != dst.AsRegisterPairLow()) {
+          ___ Mov(AsVIXLRegisterPairLow(dst),  AsVIXLRegisterPairLow(src));
+          ___ Mov(AsVIXLRegisterPairHigh(dst), AsVIXLRegisterPairHigh(src));
+        } else {
+          ___ Mov(AsVIXLRegisterPairHigh(dst), AsVIXLRegisterPairHigh(src));
+          ___ Mov(AsVIXLRegisterPairLow(dst),  AsVIXLRegisterPairLow(src));
+        }
       } else {
-        ___ Mov(AsVIXLRegisterPairHigh(dst), AsVIXLRegisterPairHigh(src));
-        ___ Mov(AsVIXLRegisterPairLow(dst),  AsVIXLRegisterPairLow(src));
+        CHECK(src.IsDRegister()) << src;
+        ___ Vmov(AsVIXLRegisterPairLow(dst), AsVIXLRegisterPairHigh(dst), AsVIXLDRegister(src));
       }
     }
   }
 }
 
-void ArmVIXLJNIMacroAssembler::Copy(FrameOffset dest,
-                                    FrameOffset src,
-                                    ManagedRegister mscratch,
-                                    size_t size) {
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
-  CHECK(size == 4 || size == 8) << size;
+void ArmVIXLJNIMacroAssembler::Copy(FrameOffset dest, FrameOffset src, size_t size) {
+  DCHECK(size == 4 || size == 8) << size;
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
+  vixl32::Register scratch = temps.Acquire();
   if (size == 4) {
     asm_.LoadFromOffset(kLoadWord, scratch, sp, src.Int32Value());
     asm_.StoreToOffset(kStoreWord, scratch, sp, dest.Int32Value());
@@ -488,87 +845,79 @@
   UNIMPLEMENTED(FATAL);
 }
 
-void ArmVIXLJNIMacroAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
-                                                      FrameOffset handle_scope_offset,
-                                                      ManagedRegister min_reg,
-                                                      bool null_allowed) {
+void ArmVIXLJNIMacroAssembler::CreateJObject(ManagedRegister mout_reg,
+                                             FrameOffset spilled_reference_offset,
+                                             ManagedRegister min_reg,
+                                             bool null_allowed) {
   vixl::aarch32::Register out_reg = AsVIXLRegister(mout_reg.AsArm());
   vixl::aarch32::Register in_reg =
       min_reg.AsArm().IsNoRegister() ? vixl::aarch32::Register() : AsVIXLRegister(min_reg.AsArm());
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
   temps.Exclude(out_reg);
   if (null_allowed) {
-    // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
-    // the address in the handle scope holding the reference.
-    // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
+    // Null values get a jobject value null. Otherwise, the jobject is
+    // the address of the spilled reference.
+    // e.g. out_reg = (handle == 0) ? 0 : (SP+spilled_reference_offset)
     if (!in_reg.IsValid()) {
-      asm_.LoadFromOffset(kLoadWord, out_reg, sp, handle_scope_offset.Int32Value());
+      asm_.LoadFromOffset(kLoadWord, out_reg, sp, spilled_reference_offset.Int32Value());
       in_reg = out_reg;
     }
 
     temps.Exclude(in_reg);
     ___ Cmp(in_reg, 0);
 
-    if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value())) {
+    if (asm_.ShifterOperandCanHold(ADD, spilled_reference_offset.Int32Value())) {
       if (!out_reg.Is(in_reg)) {
         ExactAssemblyScope guard(asm_.GetVIXLAssembler(),
                                  3 * vixl32::kMaxInstructionSizeInBytes,
                                  CodeBufferCheckScope::kMaximumSize);
         ___ it(eq, 0xc);
         ___ mov(eq, out_reg, 0);
-        asm_.AddConstantInIt(out_reg, sp, handle_scope_offset.Int32Value(), ne);
+        asm_.AddConstantInIt(out_reg, sp, spilled_reference_offset.Int32Value(), ne);
       } else {
         ExactAssemblyScope guard(asm_.GetVIXLAssembler(),
                                  2 * vixl32::kMaxInstructionSizeInBytes,
                                  CodeBufferCheckScope::kMaximumSize);
         ___ it(ne, 0x8);
-        asm_.AddConstantInIt(out_reg, sp, handle_scope_offset.Int32Value(), ne);
+        asm_.AddConstantInIt(out_reg, sp, spilled_reference_offset.Int32Value(), ne);
       }
     } else {
       // TODO: Implement this (old arm assembler would have crashed here).
       UNIMPLEMENTED(FATAL);
     }
   } else {
-    asm_.AddConstant(out_reg, sp, handle_scope_offset.Int32Value());
+    asm_.AddConstant(out_reg, sp, spilled_reference_offset.Int32Value());
   }
 }
 
-void ArmVIXLJNIMacroAssembler::CreateHandleScopeEntry(FrameOffset out_off,
-                                                      FrameOffset handle_scope_offset,
-                                                      ManagedRegister mscratch,
-                                                      bool null_allowed) {
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
+void ArmVIXLJNIMacroAssembler::CreateJObject(FrameOffset out_off,
+                                             FrameOffset spilled_reference_offset,
+                                             bool null_allowed) {
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
+  vixl32::Register scratch = temps.Acquire();
   if (null_allowed) {
-    asm_.LoadFromOffset(kLoadWord, scratch, sp, handle_scope_offset.Int32Value());
-    // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
-    // the address in the handle scope holding the reference.
-    // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset)
+    asm_.LoadFromOffset(kLoadWord, scratch, sp, spilled_reference_offset.Int32Value());
+    // Null values get a jobject value null. Otherwise, the jobject is
+    // the address of the spilled reference.
+    // e.g. scratch = (scratch == 0) ? 0 : (SP+spilled_reference_offset)
     ___ Cmp(scratch, 0);
 
-    if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value())) {
+    if (asm_.ShifterOperandCanHold(ADD, spilled_reference_offset.Int32Value())) {
       ExactAssemblyScope guard(asm_.GetVIXLAssembler(),
                                2 * vixl32::kMaxInstructionSizeInBytes,
                                CodeBufferCheckScope::kMaximumSize);
       ___ it(ne, 0x8);
-      asm_.AddConstantInIt(scratch, sp, handle_scope_offset.Int32Value(), ne);
+      asm_.AddConstantInIt(scratch, sp, spilled_reference_offset.Int32Value(), ne);
     } else {
       // TODO: Implement this (old arm assembler would have crashed here).
       UNIMPLEMENTED(FATAL);
     }
   } else {
-    asm_.AddConstant(scratch, sp, handle_scope_offset.Int32Value());
+    asm_.AddConstant(scratch, sp, spilled_reference_offset.Int32Value());
   }
   asm_.StoreToOffset(kStoreWord, scratch, sp, out_off.Int32Value());
 }
 
-void ArmVIXLJNIMacroAssembler::LoadReferenceFromHandleScope(
-    ManagedRegister mout_reg ATTRIBUTE_UNUSED,
-    ManagedRegister min_reg ATTRIBUTE_UNUSED) {
-  UNIMPLEMENTED(FATAL);
-}
-
 void ArmVIXLJNIMacroAssembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,
                                             bool could_be_null ATTRIBUTE_UNUSED) {
   // TODO: not validating references.
@@ -579,63 +928,49 @@
   // TODO: not validating references.
 }
 
-void ArmVIXLJNIMacroAssembler::Jump(ManagedRegister mbase,
-                                    Offset offset,
-                                    ManagedRegister mscratch) {
+void ArmVIXLJNIMacroAssembler::Jump(ManagedRegister mbase, Offset offset) {
   vixl::aarch32::Register base = AsVIXLRegister(mbase.AsArm());
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
+  vixl32::Register scratch = temps.Acquire();
   asm_.LoadFromOffset(kLoadWord, scratch, base, offset.Int32Value());
   ___ Bx(scratch);
 }
 
-void ArmVIXLJNIMacroAssembler::Call(ManagedRegister mbase,
-                                    Offset offset,
-                                    ManagedRegister mscratch) {
+void ArmVIXLJNIMacroAssembler::Call(ManagedRegister mbase, Offset offset) {
   vixl::aarch32::Register base = AsVIXLRegister(mbase.AsArm());
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
-  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
-  asm_.LoadFromOffset(kLoadWord, scratch, base, offset.Int32Value());
-  ___ Blx(scratch);
+  asm_.LoadFromOffset(kLoadWord, lr, base, offset.Int32Value());
+  ___ Blx(lr);
   // TODO: place reference map on call.
 }
 
-void ArmVIXLJNIMacroAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
-  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
+void ArmVIXLJNIMacroAssembler::Call(FrameOffset base, Offset offset) {
   // Call *(*(SP + base) + offset)
-  asm_.LoadFromOffset(kLoadWord, scratch, sp, base.Int32Value());
-  asm_.LoadFromOffset(kLoadWord, scratch, scratch, offset.Int32Value());
-  ___ Blx(scratch);
+  asm_.LoadFromOffset(kLoadWord, lr, sp, base.Int32Value());
+  asm_.LoadFromOffset(kLoadWord, lr, lr, offset.Int32Value());
+  ___ Blx(lr);
   // TODO: place reference map on call
 }
 
-void ArmVIXLJNIMacroAssembler::CallFromThread(ThreadOffset32 offset ATTRIBUTE_UNUSED,
-                                              ManagedRegister scratch ATTRIBUTE_UNUSED) {
+void ArmVIXLJNIMacroAssembler::CallFromThread(ThreadOffset32 offset ATTRIBUTE_UNUSED) {
   UNIMPLEMENTED(FATAL);
 }
 
-void ArmVIXLJNIMacroAssembler::GetCurrentThread(ManagedRegister mtr) {
+void ArmVIXLJNIMacroAssembler::GetCurrentThread(ManagedRegister dest) {
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(AsVIXLRegister(mtr.AsArm()));
-  ___ Mov(AsVIXLRegister(mtr.AsArm()), tr);
+  temps.Exclude(AsVIXLRegister(dest.AsArm()));
+  ___ Mov(AsVIXLRegister(dest.AsArm()), tr);
 }
 
-void ArmVIXLJNIMacroAssembler::GetCurrentThread(FrameOffset dest_offset,
-                                                ManagedRegister scratch ATTRIBUTE_UNUSED) {
+void ArmVIXLJNIMacroAssembler::GetCurrentThread(FrameOffset dest_offset) {
   asm_.StoreToOffset(kStoreWord, tr, sp, dest_offset.Int32Value());
 }
 
-void ArmVIXLJNIMacroAssembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
+void ArmVIXLJNIMacroAssembler::ExceptionPoll(size_t stack_adjust) {
   CHECK_ALIGNED(stack_adjust, kAapcsStackAlignment);
-  vixl::aarch32::Register scratch = AsVIXLRegister(mscratch.AsArm());
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(scratch);
+  vixl32::Register scratch = temps.Acquire();
   exception_blocks_.emplace_back(
-      new ArmVIXLJNIMacroAssembler::ArmException(mscratch.AsArm(), stack_adjust));
+      new ArmVIXLJNIMacroAssembler::ArmException(scratch, stack_adjust));
   asm_.LoadFromOffset(kLoadWord,
                       scratch,
                       tr,
@@ -656,23 +991,33 @@
   ___ B(ArmVIXLJNIMacroLabel::Cast(label)->AsArm());
 }
 
-void ArmVIXLJNIMacroAssembler::Jump(JNIMacroLabel* label,
-                                    JNIMacroUnaryCondition condition,
-                                    ManagedRegister mtest) {
+void ArmVIXLJNIMacroAssembler::TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) {
   CHECK(label != nullptr);
 
-  vixl::aarch32::Register test = AsVIXLRegister(mtest.AsArm());
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(test);
-  switch (condition) {
+  vixl32::Register test_reg;
+  DCHECK_EQ(Thread::IsGcMarkingSize(), 4u);
+  DCHECK(kUseReadBarrier);
+  if (kUseBakerReadBarrier) {
+    // TestGcMarking() is used in the JNI stub entry when the marking register is up to date.
+    if (kIsDebugBuild && emit_run_time_checks_in_debug_mode_) {
+      vixl32::Register temp = temps.Acquire();
+      asm_.GenerateMarkingRegisterCheck(temp);
+    }
+    test_reg = mr;
+  } else {
+    test_reg = temps.Acquire();
+    ___ Ldr(test_reg, MemOperand(tr, Thread::IsGcMarkingOffset<kArmPointerSize>().Int32Value()));
+  }
+  switch (cond) {
     case JNIMacroUnaryCondition::kZero:
-      ___ CompareAndBranchIfZero(test, ArmVIXLJNIMacroLabel::Cast(label)->AsArm());
+      ___ CompareAndBranchIfZero(test_reg, ArmVIXLJNIMacroLabel::Cast(label)->AsArm());
       break;
     case JNIMacroUnaryCondition::kNotZero:
-      ___ CompareAndBranchIfNonZero(test, ArmVIXLJNIMacroLabel::Cast(label)->AsArm());
+      ___ CompareAndBranchIfNonZero(test_reg, ArmVIXLJNIMacroLabel::Cast(label)->AsArm());
       break;
     default:
-      LOG(FATAL) << "Not implemented unary condition: " << static_cast<int>(condition);
+      LOG(FATAL) << "Not implemented unary condition: " << static_cast<int>(cond);
       UNREACHABLE();
   }
 }
@@ -689,19 +1034,16 @@
     DecreaseFrameSize(exception->stack_adjust_);
   }
 
-  vixl::aarch32::Register scratch = AsVIXLRegister(exception->scratch_);
+  vixl32::Register scratch = exception->scratch_;
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
   temps.Exclude(scratch);
   // Pass exception object as argument.
   // Don't care about preserving r0 as this won't return.
   ___ Mov(r0, scratch);
-  temps.Include(scratch);
-  // TODO: check that exception->scratch_ is dead by this point.
-  vixl32::Register temp = temps.Acquire();
-  ___ Ldr(temp,
+  ___ Ldr(lr,
           MemOperand(tr,
               QUICK_ENTRYPOINT_OFFSET(kArmPointerSize, pDeliverException).Int32Value()));
-  ___ Blx(temp);
+  ___ Blx(lr);
 }
 
 void ArmVIXLJNIMacroAssembler::MemoryBarrier(ManagedRegister scratch ATTRIBUTE_UNUSED) {
diff --git a/compiler/utils/arm/jni_macro_assembler_arm_vixl.h b/compiler/utils/arm/jni_macro_assembler_arm_vixl.h
index 1724671..248fc67 100644
--- a/compiler/utils/arm/jni_macro_assembler_arm_vixl.h
+++ b/compiler/utils/arm/jni_macro_assembler_arm_vixl.h
@@ -51,8 +51,7 @@
   // Emit code that will create an activation on the stack.
   void BuildFrame(size_t frame_size,
                   ManagedRegister method_reg,
-                  ArrayRef<const ManagedRegister> callee_save_regs,
-                  const ManagedRegisterEntrySpills& entry_spills) override;
+                  ArrayRef<const ManagedRegister> callee_save_regs) override;
 
   // Emit code that will remove an activation from the stack.
   void RemoveFrame(size_t frame_size,
@@ -67,18 +66,13 @@
   void StoreRef(FrameOffset dest, ManagedRegister src) override;
   void StoreRawPtr(FrameOffset dest, ManagedRegister src) override;
 
-  void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) override;
+  void StoreImmediateToFrame(FrameOffset dest, uint32_t imm) override;
 
-  void StoreStackOffsetToThread(ThreadOffset32 thr_offs,
-                                FrameOffset fr_offs,
-                                ManagedRegister scratch) override;
+  void StoreStackOffsetToThread(ThreadOffset32 thr_offs, FrameOffset fr_offs) override;
 
   void StoreStackPointerToThread(ThreadOffset32 thr_offs) override;
 
-  void StoreSpanning(FrameOffset dest,
-                     ManagedRegister src,
-                     FrameOffset in_off,
-                     ManagedRegister scratch) override;
+  void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off) override;
 
   // Load routines.
   void Load(ManagedRegister dest, FrameOffset src, size_t size) override;
@@ -99,19 +93,23 @@
   void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset32 offs) override;
 
   // Copying routines.
+  void MoveArguments(ArrayRef<ArgumentLocation> dests, ArrayRef<ArgumentLocation> srcs) override;
+
   void Move(ManagedRegister dest, ManagedRegister src, size_t size) override;
 
-  void CopyRawPtrFromThread(FrameOffset fr_offs,
-                            ThreadOffset32 thr_offs,
-                            ManagedRegister scratch) override;
+  void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset32 thr_offs) override;
 
   void CopyRawPtrToThread(ThreadOffset32 thr_offs,
                           FrameOffset fr_offs,
                           ManagedRegister scratch) override;
 
-  void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) override;
+  void CopyRef(FrameOffset dest, FrameOffset src) override;
+  void CopyRef(FrameOffset dest,
+               ManagedRegister base,
+               MemberOffset offs,
+               bool unpoison_reference) override;
 
-  void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) override;
+  void Copy(FrameOffset dest, FrameOffset src, size_t size) override;
 
   void Copy(FrameOffset dest,
             ManagedRegister src_base,
@@ -152,29 +150,23 @@
   void ZeroExtend(ManagedRegister mreg, size_t size) override;
 
   // Exploit fast access in managed code to Thread::Current().
-  void GetCurrentThread(ManagedRegister mtr) override;
-  void GetCurrentThread(FrameOffset dest_offset,
-                        ManagedRegister scratch) override;
+  void GetCurrentThread(ManagedRegister dest) override;
+  void GetCurrentThread(FrameOffset dest_offset) override;
 
-  // Set up out_reg to hold a Object** into the handle scope, or to be null if the
-  // value is null and null_allowed. in_reg holds a possibly stale reference
-  // that can be used to avoid loading the handle scope entry to see if the value is
-  // null.
-  void CreateHandleScopeEntry(ManagedRegister out_reg,
-                              FrameOffset handlescope_offset,
-                              ManagedRegister in_reg,
-                              bool null_allowed) override;
+  // Set up `out_reg` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
+  // or to be null if the value is null and `null_allowed`. `in_reg` holds a possibly
+  // stale reference that can be used to avoid loading the spilled value to
+  // see if the value is null.
+  void CreateJObject(ManagedRegister out_reg,
+                     FrameOffset spilled_reference_offset,
+                     ManagedRegister in_reg,
+                     bool null_allowed) override;
 
-  // Set up out_off to hold a Object** into the handle scope, or to be null if the
-  // value is null and null_allowed.
-  void CreateHandleScopeEntry(FrameOffset out_off,
-                              FrameOffset handlescope_offset,
-                              ManagedRegister scratch,
-                              bool null_allowed) override;
-
-  // src holds a handle scope entry (Object**) load this into dst.
-  void LoadReferenceFromHandleScope(ManagedRegister dst,
-                                    ManagedRegister src) override;
+  // Set up `out_off` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
+  // or to be null if the value is null and `null_allowed`.
+  void CreateJObject(FrameOffset out_off,
+                     FrameOffset spilled_reference_offset,
+                     bool null_allowed) override;
 
   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
   // know that src may not be null.
@@ -182,23 +174,23 @@
   void VerifyObject(FrameOffset src, bool could_be_null) override;
 
   // Jump to address held at [base+offset] (used for tail calls).
-  void Jump(ManagedRegister base, Offset offset, ManagedRegister scratch) override;
+  void Jump(ManagedRegister base, Offset offset) override;
 
   // Call to address held at [base+offset].
-  void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) override;
-  void Call(FrameOffset base, Offset offset, ManagedRegister scratch) override;
-  void CallFromThread(ThreadOffset32 offset, ManagedRegister scratch) override;
+  void Call(ManagedRegister base, Offset offset) override;
+  void Call(FrameOffset base, Offset offset) override;
+  void CallFromThread(ThreadOffset32 offset) override;
 
   // Generate code to check if Thread::Current()->exception_ is non-null
   // and branch to a ExceptionSlowPath if it is.
-  void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) override;
+  void ExceptionPoll(size_t stack_adjust) override;
 
   // Create a new label that can be used with Jump/Bind calls.
   std::unique_ptr<JNIMacroLabel> CreateLabel() override;
   // Emit an unconditional jump to the label.
   void Jump(JNIMacroLabel* label) override;
-  // Emit a conditional jump to the label by applying a unary condition test to the register.
-  void Jump(JNIMacroLabel* label, JNIMacroUnaryCondition cond, ManagedRegister test) override;
+  // Emit a conditional jump to the label by applying a unary condition test to the GC marking flag.
+  void TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) override;
   // Code at this offset will serve as the target for the Jump call.
   void Bind(JNIMacroLabel* label) override;
 
@@ -210,13 +202,13 @@
  private:
   class ArmException {
    private:
-    ArmException(ArmManagedRegister scratch, size_t stack_adjust)
+    ArmException(vixl32::Register scratch, size_t stack_adjust)
         : scratch_(scratch), stack_adjust_(stack_adjust) {}
 
     vixl32::Label* Entry() { return &exception_entry_; }
 
     // Register used for passing Thread::Current()->exception_ .
-    const ArmManagedRegister scratch_;
+    const vixl32::Register scratch_;
 
     // Stack adjust for ExceptionPool.
     const size_t stack_adjust_;
diff --git a/compiler/utils/arm/managed_register_arm.h b/compiler/utils/arm/managed_register_arm.h
index e42572d..6d942fa 100644
--- a/compiler/utils/arm/managed_register_arm.h
+++ b/compiler/utils/arm/managed_register_arm.h
@@ -264,7 +264,7 @@
 
 }  // namespace arm
 
-constexpr inline arm::ArmManagedRegister ManagedRegister::AsArm() const {
+constexpr arm::ArmManagedRegister ManagedRegister::AsArm() const {
   arm::ArmManagedRegister reg(id_);
   CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
   return reg;
diff --git a/compiler/utils/arm64/assembler_arm64.cc b/compiler/utils/arm64/assembler_arm64.cc
index d722e00..6100ed9 100644
--- a/compiler/utils/arm64/assembler_arm64.cc
+++ b/compiler/utils/arm64/assembler_arm64.cc
@@ -16,6 +16,7 @@
 
 #include "arch/arm64/instruction_set_features_arm64.h"
 #include "assembler_arm64.h"
+#include "base/bit_utils_iterator.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "heap_poisoning.h"
 #include "offsets.h"
@@ -54,6 +55,9 @@
   if (art_features->HasLSE()) {
     features->Combine(vixl::CPUFeatures::kAtomics);
   }
+  if (art_features->HasSVE()) {
+    features->Combine(vixl::CPUFeatures::kSVE);
+  }
 }
 
 Arm64Assembler::Arm64Assembler(ArenaAllocator* allocator,
diff --git a/compiler/utils/arm64/assembler_arm64.h b/compiler/utils/arm64/assembler_arm64.h
index fe2f176..b49a13a 100644
--- a/compiler/utils/arm64/assembler_arm64.h
+++ b/compiler/utils/arm64/assembler_arm64.h
@@ -24,6 +24,7 @@
 #include <android-base/logging.h>
 
 #include "base/arena_containers.h"
+#include "base/bit_utils_iterator.h"
 #include "base/macros.h"
 #include "dwarf/register.h"
 #include "offsets.h"
@@ -98,6 +99,28 @@
   void SpillRegisters(vixl::aarch64::CPURegList registers, int offset);
   void UnspillRegisters(vixl::aarch64::CPURegList registers, int offset);
 
+  // A helper to save/restore a list of ZRegisters to a specified stack offset location.
+  template <bool is_save>
+  void SaveRestoreZRegisterList(uint32_t vreg_bit_vector, int64_t stack_offset) {
+    if (vreg_bit_vector == 0) {
+      return;
+    }
+    vixl::aarch64::UseScratchRegisterScope temps(GetVIXLAssembler());
+    vixl::aarch64::Register temp = temps.AcquireX();
+    vixl_masm_.Add(temp, vixl::aarch64::sp, stack_offset);
+    size_t slot_no = 0;
+    for (uint32_t i : LowToHighBits(vreg_bit_vector)) {
+      if (is_save) {
+        vixl_masm_.Str(vixl::aarch64::ZRegister(i),
+                       vixl::aarch64::SVEMemOperand(temp, slot_no, vixl::aarch64::SVE_MUL_VL));
+      } else {
+        vixl_masm_.Ldr(vixl::aarch64::ZRegister(i),
+                       vixl::aarch64::SVEMemOperand(temp, slot_no, vixl::aarch64::SVE_MUL_VL));
+      }
+      slot_no++;
+    }
+  }
+
   // Jump to address (not setting link register)
   void JumpTo(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch);
 
@@ -124,10 +147,17 @@
   void GenerateMarkingRegisterCheck(vixl::aarch64::Register temp, int code = 0);
 
   void Bind(Label* label ATTRIBUTE_UNUSED) override {
-    UNIMPLEMENTED(FATAL) << "Do not use Bind for ARM64";
+    UNIMPLEMENTED(FATAL) << "Do not use Bind(Label*) for ARM64";
   }
   void Jump(Label* label ATTRIBUTE_UNUSED) override {
-    UNIMPLEMENTED(FATAL) << "Do not use Jump for ARM64";
+    UNIMPLEMENTED(FATAL) << "Do not use Jump(Label*) for ARM64";
+  }
+
+  void Bind(vixl::aarch64::Label* label) {
+    vixl_masm_.Bind(label);
+  }
+  void Jump(vixl::aarch64::Label* label) {
+    vixl_masm_.B(label);
   }
 
   static vixl::aarch64::Register reg_x(int code) {
@@ -137,7 +167,7 @@
     } else if (code == XZR) {
       return vixl::aarch64::xzr;
     }
-    return vixl::aarch64::Register::GetXRegFromCode(code);
+    return vixl::aarch64::XRegister(code);
   }
 
   static vixl::aarch64::Register reg_w(int code) {
@@ -147,15 +177,15 @@
     } else if (code == WZR) {
       return vixl::aarch64::wzr;
     }
-    return vixl::aarch64::Register::GetWRegFromCode(code);
+    return vixl::aarch64::WRegister(code);
   }
 
   static vixl::aarch64::VRegister reg_d(int code) {
-    return vixl::aarch64::VRegister::GetDRegFromCode(code);
+    return vixl::aarch64::DRegister(code);
   }
 
   static vixl::aarch64::VRegister reg_s(int code) {
-    return vixl::aarch64::VRegister::GetSRegFromCode(code);
+    return vixl::aarch64::SRegister(code);
   }
 
  private:
diff --git a/compiler/utils/arm64/jni_macro_assembler_arm64.cc b/compiler/utils/arm64/jni_macro_assembler_arm64.cc
index 5b46971..c4dbd3f 100644
--- a/compiler/utils/arm64/jni_macro_assembler_arm64.cc
+++ b/compiler/utils/arm64/jni_macro_assembler_arm64.cc
@@ -51,11 +51,11 @@
   ___ FinalizeCode();
 }
 
-void Arm64JNIMacroAssembler::GetCurrentThread(ManagedRegister tr) {
-  ___ Mov(reg_x(tr.AsArm64().AsXRegister()), reg_x(TR));
+void Arm64JNIMacroAssembler::GetCurrentThread(ManagedRegister dest) {
+  ___ Mov(reg_x(dest.AsArm64().AsXRegister()), reg_x(TR));
 }
 
-void Arm64JNIMacroAssembler::GetCurrentThread(FrameOffset offset, ManagedRegister /* scratch */) {
+void Arm64JNIMacroAssembler::GetCurrentThread(FrameOffset offset) {
   StoreToOffset(TR, SP, offset.Int32Value());
 }
 
@@ -162,41 +162,31 @@
   StoreToOffset(src.AsXRegister(), SP, offs.Int32Value());
 }
 
-void Arm64JNIMacroAssembler::StoreImmediateToFrame(FrameOffset offs,
-                                                   uint32_t imm,
-                                                   ManagedRegister m_scratch) {
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
-  CHECK(scratch.IsXRegister()) << scratch;
-  LoadImmediate(scratch.AsXRegister(), imm);
-  StoreWToOffset(kStoreWord, scratch.AsOverlappingWRegister(), SP,
-                 offs.Int32Value());
+void Arm64JNIMacroAssembler::StoreImmediateToFrame(FrameOffset offs, uint32_t imm) {
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  Register scratch = temps.AcquireW();
+  ___ Mov(scratch, imm);
+  ___ Str(scratch, MEM_OP(reg_x(SP), offs.Int32Value()));
 }
 
-void Arm64JNIMacroAssembler::StoreStackOffsetToThread(ThreadOffset64 tr_offs,
-                                                      FrameOffset fr_offs,
-                                                      ManagedRegister m_scratch) {
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
-  CHECK(scratch.IsXRegister()) << scratch;
-  AddConstant(scratch.AsXRegister(), SP, fr_offs.Int32Value());
-  StoreToOffset(scratch.AsXRegister(), TR, tr_offs.Int32Value());
+void Arm64JNIMacroAssembler::StoreStackOffsetToThread(ThreadOffset64 tr_offs, FrameOffset fr_offs) {
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  Register scratch = temps.AcquireX();
+  ___ Add(scratch, reg_x(SP), fr_offs.Int32Value());
+  ___ Str(scratch, MEM_OP(reg_x(TR), tr_offs.Int32Value()));
 }
 
 void Arm64JNIMacroAssembler::StoreStackPointerToThread(ThreadOffset64 tr_offs) {
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  Register temp = temps.AcquireX();
-  ___ Mov(temp, reg_x(SP));
-  ___ Str(temp, MEM_OP(reg_x(TR), tr_offs.Int32Value()));
+  Register scratch = temps.AcquireX();
+  ___ Mov(scratch, reg_x(SP));
+  ___ Str(scratch, MEM_OP(reg_x(TR), tr_offs.Int32Value()));
 }
 
-void Arm64JNIMacroAssembler::StoreSpanning(FrameOffset dest_off,
-                                           ManagedRegister m_source,
-                                           FrameOffset in_off,
-                                           ManagedRegister m_scratch) {
-  Arm64ManagedRegister source = m_source.AsArm64();
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
-  StoreToOffset(source.AsXRegister(), SP, dest_off.Int32Value());
-  LoadFromOffset(scratch.AsXRegister(), SP, in_off.Int32Value());
-  StoreToOffset(scratch.AsXRegister(), SP, dest_off.Int32Value() + 8);
+void Arm64JNIMacroAssembler::StoreSpanning(FrameOffset dest_off ATTRIBUTE_UNUSED,
+                                           ManagedRegister m_source ATTRIBUTE_UNUSED,
+                                           FrameOffset in_off ATTRIBUTE_UNUSED) {
+  UNIMPLEMENTED(FATAL);  // This case is not applicable to ARM64.
 }
 
 // Load routines.
@@ -336,8 +326,103 @@
 }
 
 // Copying routines.
+void Arm64JNIMacroAssembler::MoveArguments(ArrayRef<ArgumentLocation> dests,
+                                           ArrayRef<ArgumentLocation> srcs) {
+  DCHECK_EQ(dests.size(), srcs.size());
+  auto get_mask = [](ManagedRegister reg) -> uint64_t {
+    Arm64ManagedRegister arm64_reg = reg.AsArm64();
+    if (arm64_reg.IsXRegister()) {
+      size_t core_reg_number = static_cast<size_t>(arm64_reg.AsXRegister());
+      DCHECK_LT(core_reg_number, 31u);  // xSP, xZR not allowed.
+      return UINT64_C(1) << core_reg_number;
+    } else if (arm64_reg.IsWRegister()) {
+      size_t core_reg_number = static_cast<size_t>(arm64_reg.AsWRegister());
+      DCHECK_LT(core_reg_number, 31u);  // wSP, wZR not allowed.
+      return UINT64_C(1) << core_reg_number;
+    } else if (arm64_reg.IsDRegister()) {
+      size_t fp_reg_number = static_cast<size_t>(arm64_reg.AsDRegister());
+      DCHECK_LT(fp_reg_number, 32u);
+      return (UINT64_C(1) << 32u) << fp_reg_number;
+    } else {
+      DCHECK(arm64_reg.IsSRegister());
+      size_t fp_reg_number = static_cast<size_t>(arm64_reg.AsSRegister());
+      DCHECK_LT(fp_reg_number, 32u);
+      return (UINT64_C(1) << 32u) << fp_reg_number;
+    }
+  };
+  // Collect registers to move while storing/copying args to stack slots.
+  // More than 8 core or FP reg args are very rare, so we do not optimize
+  // for that case by using LDP/STP.
+  // TODO: LDP/STP will be useful for normal and @FastNative where we need
+  // to spill even the leading arguments.
+  uint64_t src_regs = 0u;
+  uint64_t dest_regs = 0u;
+  for (size_t i = 0, arg_count = srcs.size(); i != arg_count; ++i) {
+    const ArgumentLocation& src = srcs[i];
+    const ArgumentLocation& dest = dests[i];
+    DCHECK_EQ(src.GetSize(), dest.GetSize());
+    if (dest.IsRegister()) {
+      if (src.IsRegister() && src.GetRegister().Equals(dest.GetRegister())) {
+        // Nothing to do.
+      } else {
+        if (src.IsRegister()) {
+          src_regs |= get_mask(src.GetRegister());
+        }
+        dest_regs |= get_mask(dest.GetRegister());
+      }
+    } else {
+      if (src.IsRegister()) {
+        Store(dest.GetFrameOffset(), src.GetRegister(), dest.GetSize());
+      } else {
+        Copy(dest.GetFrameOffset(), src.GetFrameOffset(), dest.GetSize());
+      }
+    }
+  }
+  // Fill destination registers.
+  // There should be no cycles, so this simple algorithm should make progress.
+  while (dest_regs != 0u) {
+    uint64_t old_dest_regs = dest_regs;
+    for (size_t i = 0, arg_count = srcs.size(); i != arg_count; ++i) {
+      const ArgumentLocation& src = srcs[i];
+      const ArgumentLocation& dest = dests[i];
+      if (!dest.IsRegister()) {
+        continue;  // Stored in first loop above.
+      }
+      uint64_t dest_reg_mask = get_mask(dest.GetRegister());
+      if ((dest_reg_mask & dest_regs) == 0u) {
+        continue;  // Equals source, or already filled in one of previous iterations.
+      }
+      if ((dest_reg_mask & src_regs) != 0u) {
+        continue;  // Cannot clobber this register yet.
+      }
+      if (src.IsRegister()) {
+        Move(dest.GetRegister(), src.GetRegister(), dest.GetSize());
+        src_regs &= ~get_mask(src.GetRegister());  // Allow clobbering source register.
+      } else {
+        Load(dest.GetRegister(), src.GetFrameOffset(), dest.GetSize());
+      }
+      dest_regs &= ~get_mask(dest.GetRegister());  // Destination register was filled.
+    }
+    CHECK_NE(old_dest_regs, dest_regs);
+    DCHECK_EQ(0u, dest_regs & ~old_dest_regs);
+  }
+}
+
 void Arm64JNIMacroAssembler::Move(ManagedRegister m_dst, ManagedRegister m_src, size_t size) {
   Arm64ManagedRegister dst = m_dst.AsArm64();
+  if (kIsDebugBuild) {
+    // Check that the destination is not a scratch register.
+    UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+    if (dst.IsXRegister()) {
+      CHECK(!temps.IsAvailable(reg_x(dst.AsXRegister())));
+    } else if (dst.IsWRegister()) {
+      CHECK(!temps.IsAvailable(reg_w(dst.AsWRegister())));
+    } else if (dst.IsSRegister()) {
+      CHECK(!temps.IsAvailable(reg_s(dst.AsSRegister())));
+    } else {
+      CHECK(!temps.IsAvailable(reg_d(dst.AsDRegister())));
+    }
+  }
   Arm64ManagedRegister src = m_src.AsArm64();
   if (!dst.Equals(src)) {
     if (dst.IsXRegister()) {
@@ -365,13 +450,11 @@
   }
 }
 
-void Arm64JNIMacroAssembler::CopyRawPtrFromThread(FrameOffset fr_offs,
-                                                  ThreadOffset64 tr_offs,
-                                                  ManagedRegister m_scratch) {
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
-  CHECK(scratch.IsXRegister()) << scratch;
-  LoadFromOffset(scratch.AsXRegister(), TR, tr_offs.Int32Value());
-  StoreToOffset(scratch.AsXRegister(), SP, fr_offs.Int32Value());
+void Arm64JNIMacroAssembler::CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset64 tr_offs) {
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  Register scratch = temps.AcquireX();
+  ___ Ldr(scratch, MEM_OP(reg_x(TR), tr_offs.Int32Value()));
+  ___ Str(scratch, MEM_OP(sp, fr_offs.Int32Value()));
 }
 
 void Arm64JNIMacroAssembler::CopyRawPtrToThread(ThreadOffset64 tr_offs,
@@ -383,31 +466,32 @@
   StoreToOffset(scratch.AsXRegister(), TR, tr_offs.Int32Value());
 }
 
-void Arm64JNIMacroAssembler::CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister m_scratch) {
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
-  CHECK(scratch.IsXRegister()) << scratch;
-  LoadWFromOffset(kLoadWord, scratch.AsOverlappingWRegister(),
-                  SP, src.Int32Value());
-  StoreWToOffset(kStoreWord, scratch.AsOverlappingWRegister(),
-                 SP, dest.Int32Value());
+void Arm64JNIMacroAssembler::CopyRef(FrameOffset dest, FrameOffset src) {
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  Register scratch = temps.AcquireW();
+  ___ Ldr(scratch, MEM_OP(reg_x(SP), src.Int32Value()));
+  ___ Str(scratch, MEM_OP(reg_x(SP), dest.Int32Value()));
 }
 
-void Arm64JNIMacroAssembler::Copy(FrameOffset dest,
-                                  FrameOffset src,
-                                  ManagedRegister m_scratch,
-                                  size_t size) {
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
-  CHECK(scratch.IsXRegister()) << scratch;
-  CHECK(size == 4 || size == 8) << size;
-  if (size == 4) {
-    LoadWFromOffset(kLoadWord, scratch.AsOverlappingWRegister(), SP, src.Int32Value());
-    StoreWToOffset(kStoreWord, scratch.AsOverlappingWRegister(), SP, dest.Int32Value());
-  } else if (size == 8) {
-    LoadFromOffset(scratch.AsXRegister(), SP, src.Int32Value());
-    StoreToOffset(scratch.AsXRegister(), SP, dest.Int32Value());
-  } else {
-    UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
+void Arm64JNIMacroAssembler::CopyRef(FrameOffset dest,
+                                     ManagedRegister base,
+                                     MemberOffset offs,
+                                     bool unpoison_reference) {
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  Register scratch = temps.AcquireW();
+  ___ Ldr(scratch, MEM_OP(reg_x(base.AsArm64().AsXRegister()), offs.Int32Value()));
+  if (unpoison_reference) {
+    asm_.MaybeUnpoisonHeapReference(scratch);
   }
+  ___ Str(scratch, MEM_OP(reg_x(SP), dest.Int32Value()));
+}
+
+void Arm64JNIMacroAssembler::Copy(FrameOffset dest, FrameOffset src, size_t size) {
+  DCHECK(size == 4 || size == 8) << size;
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  Register scratch = (size == 8) ? temps.AcquireX() : temps.AcquireW();
+  ___ Ldr(scratch, MEM_OP(reg_x(SP), src.Int32Value()));
+  ___ Str(scratch, MEM_OP(reg_x(SP), dest.Int32Value()));
 }
 
 void Arm64JNIMacroAssembler::Copy(FrameOffset dest,
@@ -539,111 +623,88 @@
   // TODO: not validating references.
 }
 
-void Arm64JNIMacroAssembler::Jump(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch) {
+void Arm64JNIMacroAssembler::Jump(ManagedRegister m_base, Offset offs) {
   Arm64ManagedRegister base = m_base.AsArm64();
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
   CHECK(base.IsXRegister()) << base;
-  CHECK(scratch.IsXRegister()) << scratch;
-  LoadFromOffset(scratch.AsXRegister(), base.AsXRegister(), offs.Int32Value());
-  ___ Br(reg_x(scratch.AsXRegister()));
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  Register scratch = temps.AcquireX();
+  ___ Ldr(scratch, MEM_OP(reg_x(base.AsXRegister()), offs.Int32Value()));
+  ___ Br(scratch);
 }
 
-void Arm64JNIMacroAssembler::Call(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch) {
+void Arm64JNIMacroAssembler::Call(ManagedRegister m_base, Offset offs) {
   Arm64ManagedRegister base = m_base.AsArm64();
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
   CHECK(base.IsXRegister()) << base;
-  CHECK(scratch.IsXRegister()) << scratch;
-  LoadFromOffset(scratch.AsXRegister(), base.AsXRegister(), offs.Int32Value());
-  ___ Blr(reg_x(scratch.AsXRegister()));
+  ___ Ldr(lr, MEM_OP(reg_x(base.AsXRegister()), offs.Int32Value()));
+  ___ Blr(lr);
 }
 
-void Arm64JNIMacroAssembler::Call(FrameOffset base, Offset offs, ManagedRegister m_scratch) {
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
-  CHECK(scratch.IsXRegister()) << scratch;
+void Arm64JNIMacroAssembler::Call(FrameOffset base, Offset offs) {
   // Call *(*(SP + base) + offset)
-  LoadFromOffset(scratch.AsXRegister(), SP, base.Int32Value());
-  LoadFromOffset(scratch.AsXRegister(), scratch.AsXRegister(), offs.Int32Value());
-  ___ Blr(reg_x(scratch.AsXRegister()));
+  ___ Ldr(lr, MEM_OP(reg_x(SP), base.Int32Value()));
+  ___ Ldr(lr, MEM_OP(lr, offs.Int32Value()));
+  ___ Blr(lr);
 }
 
-void Arm64JNIMacroAssembler::CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED,
-                                            ManagedRegister scratch ATTRIBUTE_UNUSED) {
+void Arm64JNIMacroAssembler::CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED) {
   UNIMPLEMENTED(FATAL) << "Unimplemented Call() variant";
 }
 
-void Arm64JNIMacroAssembler::CreateHandleScopeEntry(ManagedRegister m_out_reg,
-                                                    FrameOffset handle_scope_offs,
-                                                    ManagedRegister m_in_reg,
-                                                    bool null_allowed) {
+void Arm64JNIMacroAssembler::CreateJObject(ManagedRegister m_out_reg,
+                                           FrameOffset spilled_reference_offset,
+                                           ManagedRegister m_in_reg,
+                                           bool null_allowed) {
   Arm64ManagedRegister out_reg = m_out_reg.AsArm64();
   Arm64ManagedRegister in_reg = m_in_reg.AsArm64();
   // For now we only hold stale handle scope entries in x registers.
   CHECK(in_reg.IsNoRegister() || in_reg.IsXRegister()) << in_reg;
   CHECK(out_reg.IsXRegister()) << out_reg;
   if (null_allowed) {
-    // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
-    // the address in the handle scope holding the reference.
-    // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
+    // Null values get a jobject value null. Otherwise, the jobject is
+    // the address of the spilled reference.
+    // e.g. out_reg = (in == 0) ? 0 : (SP+spilled_reference_offset)
     if (in_reg.IsNoRegister()) {
       LoadWFromOffset(kLoadWord, out_reg.AsOverlappingWRegister(), SP,
-                      handle_scope_offs.Int32Value());
+                      spilled_reference_offset.Int32Value());
       in_reg = out_reg;
     }
     ___ Cmp(reg_w(in_reg.AsOverlappingWRegister()), 0);
     if (!out_reg.Equals(in_reg)) {
       LoadImmediate(out_reg.AsXRegister(), 0, eq);
     }
-    AddConstant(out_reg.AsXRegister(), SP, handle_scope_offs.Int32Value(), ne);
+    AddConstant(out_reg.AsXRegister(), SP, spilled_reference_offset.Int32Value(), ne);
   } else {
-    AddConstant(out_reg.AsXRegister(), SP, handle_scope_offs.Int32Value(), al);
+    AddConstant(out_reg.AsXRegister(), SP, spilled_reference_offset.Int32Value(), al);
   }
 }
 
-void Arm64JNIMacroAssembler::CreateHandleScopeEntry(FrameOffset out_off,
-                                                    FrameOffset handle_scope_offset,
-                                                    ManagedRegister m_scratch,
-                                                    bool null_allowed) {
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
-  CHECK(scratch.IsXRegister()) << scratch;
+void Arm64JNIMacroAssembler::CreateJObject(FrameOffset out_off,
+                                           FrameOffset spilled_reference_offset,
+                                           bool null_allowed) {
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  Register scratch = temps.AcquireX();
   if (null_allowed) {
-    LoadWFromOffset(kLoadWord, scratch.AsOverlappingWRegister(), SP,
-                    handle_scope_offset.Int32Value());
-    // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
-    // the address in the handle scope holding the reference.
-    // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset)
-    ___ Cmp(reg_w(scratch.AsOverlappingWRegister()), 0);
-    // Move this logic in add constants with flags.
-    AddConstant(scratch.AsXRegister(), SP, handle_scope_offset.Int32Value(), ne);
+    Register scratch2 = temps.AcquireW();
+    ___ Ldr(scratch2, MEM_OP(reg_x(SP), spilled_reference_offset.Int32Value()));
+    ___ Add(scratch, reg_x(SP), spilled_reference_offset.Int32Value());
+    // Null values get a jobject value null. Otherwise, the jobject is
+    // the address of the spilled reference.
+    // e.g. scratch = (scratch == 0) ? 0 : (SP+spilled_reference_offset)
+    ___ Cmp(scratch2, 0);
+    ___ Csel(scratch, scratch, xzr, ne);
   } else {
-    AddConstant(scratch.AsXRegister(), SP, handle_scope_offset.Int32Value(), al);
+    ___ Add(scratch, reg_x(SP), spilled_reference_offset.Int32Value());
   }
-  StoreToOffset(scratch.AsXRegister(), SP, out_off.Int32Value());
+  ___ Str(scratch, MEM_OP(reg_x(SP), out_off.Int32Value()));
 }
 
-void Arm64JNIMacroAssembler::LoadReferenceFromHandleScope(ManagedRegister m_out_reg,
-                                                          ManagedRegister m_in_reg) {
-  Arm64ManagedRegister out_reg = m_out_reg.AsArm64();
-  Arm64ManagedRegister in_reg = m_in_reg.AsArm64();
-  CHECK(out_reg.IsXRegister()) << out_reg;
-  CHECK(in_reg.IsXRegister()) << in_reg;
-  vixl::aarch64::Label exit;
-  if (!out_reg.Equals(in_reg)) {
-    // FIXME: Who sets the flags here?
-    LoadImmediate(out_reg.AsXRegister(), 0, eq);
-  }
-  ___ Cbz(reg_x(in_reg.AsXRegister()), &exit);
-  LoadFromOffset(out_reg.AsXRegister(), in_reg.AsXRegister(), 0);
-  ___ Bind(&exit);
-}
-
-void Arm64JNIMacroAssembler::ExceptionPoll(ManagedRegister m_scratch, size_t stack_adjust) {
+void Arm64JNIMacroAssembler::ExceptionPoll(size_t stack_adjust) {
   CHECK_ALIGNED(stack_adjust, kStackAlignment);
-  Arm64ManagedRegister scratch = m_scratch.AsArm64();
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  Register scratch = temps.AcquireX();
   exception_blocks_.emplace_back(new Arm64Exception(scratch, stack_adjust));
-  LoadFromOffset(scratch.AsXRegister(),
-                 TR,
-                 Thread::ExceptionOffset<kArm64PointerSize>().Int32Value());
-  ___ Cbnz(reg_x(scratch.AsXRegister()), exception_blocks_.back()->Entry());
+  ___ Ldr(scratch, MEM_OP(reg_x(TR), Thread::ExceptionOffset<kArm64PointerSize>().Int32Value()));
+  ___ Cbnz(scratch, exception_blocks_.back()->Entry());
 }
 
 std::unique_ptr<JNIMacroLabel> Arm64JNIMacroAssembler::CreateLabel() {
@@ -655,20 +716,34 @@
   ___ B(Arm64JNIMacroLabel::Cast(label)->AsArm64());
 }
 
-void Arm64JNIMacroAssembler::Jump(JNIMacroLabel* label,
-                                  JNIMacroUnaryCondition condition,
-                                  ManagedRegister test) {
+void Arm64JNIMacroAssembler::TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) {
   CHECK(label != nullptr);
 
-  switch (condition) {
+  UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
+  Register test_reg;
+  DCHECK_EQ(Thread::IsGcMarkingSize(), 4u);
+  DCHECK(kUseReadBarrier);
+  if (kUseBakerReadBarrier) {
+    // TestGcMarking() is used in the JNI stub entry when the marking register is up to date.
+    if (kIsDebugBuild && emit_run_time_checks_in_debug_mode_) {
+      Register temp = temps.AcquireW();
+      asm_.GenerateMarkingRegisterCheck(temp);
+    }
+    test_reg = reg_w(MR);
+  } else {
+    test_reg = temps.AcquireW();
+    int32_t is_gc_marking_offset = Thread::IsGcMarkingOffset<kArm64PointerSize>().Int32Value();
+    ___ Ldr(test_reg, MEM_OP(reg_x(TR), is_gc_marking_offset));
+  }
+  switch (cond) {
     case JNIMacroUnaryCondition::kZero:
-      ___ Cbz(reg_x(test.AsArm64().AsXRegister()), Arm64JNIMacroLabel::Cast(label)->AsArm64());
+      ___ Cbz(test_reg, Arm64JNIMacroLabel::Cast(label)->AsArm64());
       break;
     case JNIMacroUnaryCondition::kNotZero:
-      ___ Cbnz(reg_x(test.AsArm64().AsXRegister()), Arm64JNIMacroLabel::Cast(label)->AsArm64());
+      ___ Cbnz(test_reg, Arm64JNIMacroLabel::Cast(label)->AsArm64());
       break;
     default:
-      LOG(FATAL) << "Not implemented unary condition: " << static_cast<int>(condition);
+      LOG(FATAL) << "Not implemented unary condition: " << static_cast<int>(cond);
       UNREACHABLE();
   }
 }
@@ -680,8 +755,7 @@
 
 void Arm64JNIMacroAssembler::EmitExceptionPoll(Arm64Exception* exception) {
   UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
-  temps.Exclude(reg_x(exception->scratch_.AsXRegister()));
-  Register temp = temps.AcquireX();
+  temps.Exclude(exception->scratch_);
 
   // Bind exception poll entry.
   ___ Bind(exception->Entry());
@@ -690,20 +764,19 @@
   }
   // Pass exception object as argument.
   // Don't care about preserving X0 as this won't return.
-  ___ Mov(reg_x(X0), reg_x(exception->scratch_.AsXRegister()));
-  ___ Ldr(temp,
+  ___ Mov(reg_x(X0), exception->scratch_);
+  ___ Ldr(lr,
           MEM_OP(reg_x(TR),
                  QUICK_ENTRYPOINT_OFFSET(kArm64PointerSize, pDeliverException).Int32Value()));
 
-  ___ Blr(temp);
+  ___ Blr(lr);
   // Call should never return.
   ___ Brk();
 }
 
 void Arm64JNIMacroAssembler::BuildFrame(size_t frame_size,
                                         ManagedRegister method_reg,
-                                        ArrayRef<const ManagedRegister> callee_save_regs,
-                                        const ManagedRegisterEntrySpills& entry_spills) {
+                                        ArrayRef<const ManagedRegister> callee_save_regs) {
   // Setup VIXL CPURegList for callee-saves.
   CPURegList core_reg_list(CPURegister::kRegister, kXRegSize, 0);
   CPURegList fp_reg_list(CPURegister::kVRegister, kDRegSize, 0);
@@ -735,28 +808,6 @@
     DCHECK(X0 == method_reg.AsArm64().AsXRegister());
     StoreToOffset(X0, SP, 0);
   }
-
-  // Write out entry spills
-  int32_t offset = frame_size + static_cast<size_t>(kArm64PointerSize);
-  for (const ManagedRegisterSpill& spill : entry_spills) {
-    Arm64ManagedRegister reg = spill.AsArm64();
-    if (reg.IsNoRegister()) {
-      // only increment stack offset.
-      offset += spill.getSize();
-    } else if (reg.IsXRegister()) {
-      StoreToOffset(reg.AsXRegister(), SP, offset);
-      offset += 8;
-    } else if (reg.IsWRegister()) {
-      StoreWToOffset(kStoreWord, reg.AsWRegister(), SP, offset);
-      offset += 4;
-    } else if (reg.IsDRegister()) {
-      StoreDToOffset(reg.AsDRegister(), SP, offset);
-      offset += 8;
-    } else if (reg.IsSRegister()) {
-      StoreSToOffset(reg.AsSRegister(), SP, offset);
-      offset += 4;
-    }
-  }
 }
 
 void Arm64JNIMacroAssembler::RemoveFrame(size_t frame_size,
diff --git a/compiler/utils/arm64/jni_macro_assembler_arm64.h b/compiler/utils/arm64/jni_macro_assembler_arm64.h
index 54592a3..ad027d3 100644
--- a/compiler/utils/arm64/jni_macro_assembler_arm64.h
+++ b/compiler/utils/arm64/jni_macro_assembler_arm64.h
@@ -54,8 +54,7 @@
   // Emit code that will create an activation on the stack.
   void BuildFrame(size_t frame_size,
                   ManagedRegister method_reg,
-                  ArrayRef<const ManagedRegister> callee_save_regs,
-                  const ManagedRegisterEntrySpills& entry_spills) override;
+                  ArrayRef<const ManagedRegister> callee_save_regs) override;
 
   // Emit code that will remove an activation from the stack.
   void RemoveFrame(size_t frame_size,
@@ -69,15 +68,10 @@
   void Store(FrameOffset offs, ManagedRegister src, size_t size) override;
   void StoreRef(FrameOffset dest, ManagedRegister src) override;
   void StoreRawPtr(FrameOffset dest, ManagedRegister src) override;
-  void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) override;
-  void StoreStackOffsetToThread(ThreadOffset64 thr_offs,
-                                FrameOffset fr_offs,
-                                ManagedRegister scratch) override;
+  void StoreImmediateToFrame(FrameOffset dest, uint32_t imm) override;
+  void StoreStackOffsetToThread(ThreadOffset64 thr_offs, FrameOffset fr_offs) override;
   void StoreStackPointerToThread(ThreadOffset64 thr_offs) override;
-  void StoreSpanning(FrameOffset dest,
-                     ManagedRegister src,
-                     FrameOffset in_off,
-                     ManagedRegister scratch) override;
+  void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off) override;
 
   // Load routines.
   void Load(ManagedRegister dest, FrameOffset src, size_t size) override;
@@ -91,14 +85,17 @@
   void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset64 offs) override;
 
   // Copying routines.
+  void MoveArguments(ArrayRef<ArgumentLocation> dests, ArrayRef<ArgumentLocation> srcs) override;
   void Move(ManagedRegister dest, ManagedRegister src, size_t size) override;
-  void CopyRawPtrFromThread(FrameOffset fr_offs,
-                            ThreadOffset64 thr_offs,
-                            ManagedRegister scratch) override;
+  void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset64 thr_offs) override;
   void CopyRawPtrToThread(ThreadOffset64 thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
       override;
-  void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) override;
-  void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) override;
+  void CopyRef(FrameOffset dest, FrameOffset src) override;
+  void CopyRef(FrameOffset dest,
+               ManagedRegister base,
+               MemberOffset offs,
+               bool unpoison_reference) override;
+  void Copy(FrameOffset dest, FrameOffset src, size_t size) override;
   void Copy(FrameOffset dest,
             ManagedRegister src_base,
             Offset src_offset,
@@ -135,27 +132,23 @@
   void ZeroExtend(ManagedRegister mreg, size_t size) override;
 
   // Exploit fast access in managed code to Thread::Current().
-  void GetCurrentThread(ManagedRegister tr) override;
-  void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) override;
+  void GetCurrentThread(ManagedRegister dest) override;
+  void GetCurrentThread(FrameOffset dest_offset) override;
 
-  // Set up out_reg to hold a Object** into the handle scope, or to be null if the
-  // value is null and null_allowed. in_reg holds a possibly stale reference
-  // that can be used to avoid loading the handle scope entry to see if the value is
-  // null.
-  void CreateHandleScopeEntry(ManagedRegister out_reg,
-                              FrameOffset handlescope_offset,
-                              ManagedRegister in_reg,
-                              bool null_allowed) override;
+  // Set up `out_reg` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
+  // or to be null if the value is null and `null_allowed`. `in_reg` holds a possibly
+  // stale reference that can be used to avoid loading the spilled value to
+  // see if the value is null.
+  void CreateJObject(ManagedRegister out_reg,
+                     FrameOffset spilled_reference_offset,
+                     ManagedRegister in_reg,
+                     bool null_allowed) override;
 
-  // Set up out_off to hold a Object** into the handle scope, or to be null if the
-  // value is null and null_allowed.
-  void CreateHandleScopeEntry(FrameOffset out_off,
-                              FrameOffset handlescope_offset,
-                              ManagedRegister scratch,
-                              bool null_allowed) override;
-
-  // src holds a handle scope entry (Object**) load this into dst.
-  void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) override;
+  // Set up `out_off` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
+  // or to be null if the value is null and `null_allowed`.
+  void CreateJObject(FrameOffset out_off,
+                     FrameOffset spilled_reference_offset,
+                     bool null_allowed) override;
 
   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
   // know that src may not be null.
@@ -163,36 +156,36 @@
   void VerifyObject(FrameOffset src, bool could_be_null) override;
 
   // Jump to address held at [base+offset] (used for tail calls).
-  void Jump(ManagedRegister base, Offset offset, ManagedRegister scratch) override;
+  void Jump(ManagedRegister base, Offset offset) override;
 
   // Call to address held at [base+offset].
-  void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) override;
-  void Call(FrameOffset base, Offset offset, ManagedRegister scratch) override;
-  void CallFromThread(ThreadOffset64 offset, ManagedRegister scratch) override;
+  void Call(ManagedRegister base, Offset offset) override;
+  void Call(FrameOffset base, Offset offset) override;
+  void CallFromThread(ThreadOffset64 offset) override;
 
   // Generate code to check if Thread::Current()->exception_ is non-null
   // and branch to a ExceptionSlowPath if it is.
-  void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) override;
+  void ExceptionPoll(size_t stack_adjust) override;
 
   // Create a new label that can be used with Jump/Bind calls.
   std::unique_ptr<JNIMacroLabel> CreateLabel() override;
   // Emit an unconditional jump to the label.
   void Jump(JNIMacroLabel* label) override;
-  // Emit a conditional jump to the label by applying a unary condition test to the register.
-  void Jump(JNIMacroLabel* label, JNIMacroUnaryCondition cond, ManagedRegister test) override;
+  // Emit a conditional jump to the label by applying a unary condition test to the GC marking flag.
+  void TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) override;
   // Code at this offset will serve as the target for the Jump call.
   void Bind(JNIMacroLabel* label) override;
 
  private:
   class Arm64Exception {
    public:
-    Arm64Exception(Arm64ManagedRegister scratch, size_t stack_adjust)
+    Arm64Exception(vixl::aarch64::Register scratch, size_t stack_adjust)
         : scratch_(scratch), stack_adjust_(stack_adjust) {}
 
     vixl::aarch64::Label* Entry() { return &exception_entry_; }
 
     // Register used for passing Thread::Current()->exception_ .
-    const Arm64ManagedRegister scratch_;
+    const vixl::aarch64::Register scratch_;
 
     // Stack adjust for ExceptionPool.
     const size_t stack_adjust_;
diff --git a/compiler/utils/arm64/managed_register_arm64.h b/compiler/utils/arm64/managed_register_arm64.h
index 0513890..8a06f63 100644
--- a/compiler/utils/arm64/managed_register_arm64.h
+++ b/compiler/utils/arm64/managed_register_arm64.h
@@ -215,7 +215,7 @@
 
 }  // namespace arm64
 
-constexpr inline arm64::Arm64ManagedRegister ManagedRegister::AsArm64() const {
+constexpr arm64::Arm64ManagedRegister ManagedRegister::AsArm64() const {
   arm64::Arm64ManagedRegister reg(id_);
   CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
   return reg;
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h
index 0744aec2..e863b9a 100644
--- a/compiler/utils/assembler.h
+++ b/compiler/utils/assembler.h
@@ -229,7 +229,7 @@
 
   // When building the C++ tests, assertion code is enabled. To allow
   // asserting that the user of the assembler buffer has ensured the
-  // capacity needed for emitting, we add a dummy method in non-debug mode.
+  // capacity needed for emitting, we add a placeholder method in non-debug mode.
   bool HasEnsuredCapacity() const { return true; }
 
 #endif
@@ -371,6 +371,7 @@
   // the instructions that can trigger signals into branch delay slots. Handling
   // signals from instructions in delay slots is a bit problematic and should be
   // avoided.
+  // TODO: Re-evaluate whether we still need this now that MIPS support has been removed.
   virtual size_t CodePosition() { return CodeSize(); }
 
   // Copy instructions out of assembly buffer into the given region of memory
diff --git a/compiler/utils/assembler_test.h b/compiler/utils/assembler_test.h
index 9e23d11..9fffda5 100644
--- a/compiler/utils/assembler_test.h
+++ b/compiler/utils/assembler_test.h
@@ -53,7 +53,7 @@
          typename FPReg,
          typename Imm,
          typename VecReg = NoVectorRegs>
-class AssemblerTest : public testing::Test {
+class AssemblerTest : public AssemblerTestBase {
  public:
   Ass* GetAssembler() {
     return assembler_.get();
@@ -683,11 +683,6 @@
                                                                     bias);
   }
 
-  // This is intended to be run as a test.
-  bool CheckTools() {
-    return test_helper_->CheckTools();
-  }
-
   // The following functions are public so that TestFn can use them...
 
   // Returns a vector of address used by any of the repeat methods
@@ -738,23 +733,14 @@
   AssemblerTest() {}
 
   void SetUp() override {
+    AssemblerTestBase::SetUp();
     allocator_.reset(new ArenaAllocator(&pool_));
     assembler_.reset(CreateAssembler(allocator_.get()));
-    test_helper_.reset(
-        new AssemblerTestInfrastructure(GetArchitectureString(),
-                                        GetAssemblerCmdName(),
-                                        GetAssemblerParameters(),
-                                        GetObjdumpCmdName(),
-                                        GetObjdumpParameters(),
-                                        GetDisassembleCmdName(),
-                                        GetDisassembleParameters(),
-                                        GetAssemblyHeader()));
-
     SetUpHelpers();
   }
 
   void TearDown() override {
-    test_helper_.reset();  // Clean up the helper.
+    AssemblerTestBase::TearDown();
     assembler_.reset();
     allocator_.reset();
   }
@@ -767,38 +753,6 @@
   // Override this to set up any architecture-specific things, e.g., register vectors.
   virtual void SetUpHelpers() {}
 
-  // Get the typically used name for this architecture, e.g., aarch64, x86_64, ...
-  virtual std::string GetArchitectureString() = 0;
-
-  // Get the name of the assembler, e.g., "as" by default.
-  virtual std::string GetAssemblerCmdName() {
-    return "as";
-  }
-
-  // Switches to the assembler command. Default none.
-  virtual std::string GetAssemblerParameters() {
-    return "";
-  }
-
-  // Get the name of the objdump, e.g., "objdump" by default.
-  virtual std::string GetObjdumpCmdName() {
-    return "objdump";
-  }
-
-  // Switches to the objdump command. Default is " -h".
-  virtual std::string GetObjdumpParameters() {
-    return " -h";
-  }
-
-  // Get the name of the objdump, e.g., "objdump" by default.
-  virtual std::string GetDisassembleCmdName() {
-    return "objdump";
-  }
-
-  // Switches to the objdump command. As it's a binary, one needs to push the architecture and
-  // such to objdump, so it's architecture-specific and there is no default.
-  virtual std::string GetDisassembleParameters() = 0;
-
   // Create a couple of immediate values up to the number of bytes given.
   virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
     std::vector<int64_t> res;
@@ -1529,11 +1483,6 @@
     return sreg.str();
   }
 
-  // If the assembly file needs a header, return it in a sub-class.
-  virtual const char* GetAssemblyHeader() {
-    return nullptr;
-  }
-
   void WarnOnCombinations(size_t count) {
     if (count > kWarnManyCombinationsThreshold) {
       GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow.";
@@ -1602,7 +1551,7 @@
     MemoryRegion code(&(*data)[0], data->size());
     assembler_->FinalizeInstructions(code);
     Pad(*data);
-    test_helper_->Driver(*data, assembly_text, test_name);
+    Driver(*data, assembly_text, test_name);
   }
 
   static constexpr size_t kWarnManyCombinationsThreshold = 500;
@@ -1610,7 +1559,6 @@
   MallocArenaPool pool_;
   std::unique_ptr<ArenaAllocator> allocator_;
   std::unique_ptr<Ass> assembler_;
-  std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
 
   DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
 };
diff --git a/compiler/utils/assembler_test_base.h b/compiler/utils/assembler_test_base.h
index 5fa0b3c..b4c0d0c 100644
--- a/compiler/utils/assembler_test_base.h
+++ b/compiler/utils/assembler_test_base.h
@@ -25,453 +25,202 @@
 
 #include "android-base/strings.h"
 
+#include "base/os.h"
 #include "base/utils.h"
-#include "common_runtime_test.h"  // For ScratchFile
+#include "common_runtime_test.h"  // For ScratchDir.
+#include "elf/elf_builder.h"
+#include "elf/elf_debug_reader.h"
 #include "exec_utils.h"
+#include "stream/file_output_stream.h"
 
 namespace art {
 
-// If you want to take a look at the differences between the ART assembler and GCC, set this flag
-// to true. The disassembled files will then remain in the tmp directory.
+// If you want to take a look at the differences between the ART assembler and clang,
+// set this flag to true. The disassembled files will then remain in the tmp directory.
 static constexpr bool kKeepDisassembledFiles = false;
 
-// Use a glocal static variable to keep the same name for all test data. Else we'll just spam the
-// temp directory.
-static std::string tmpnam_;  // NOLINT [runtime/string] [4]
-
 // We put this into a class as gtests are self-contained, so this helper needs to be in an h-file.
-class AssemblerTestInfrastructure {
+class AssemblerTestBase : public testing::Test {
  public:
-  AssemblerTestInfrastructure(std::string architecture,
-                              std::string as,
-                              std::string as_params,
-                              std::string objdump,
-                              std::string objdump_params,
-                              std::string disasm,
-                              std::string disasm_params,
-                              const char* asm_header) :
-      architecture_string_(architecture),
-      asm_header_(asm_header),
-      assembler_cmd_name_(as),
-      assembler_parameters_(as_params),
-      objdump_cmd_name_(objdump),
-      objdump_parameters_(objdump_params),
-      disassembler_cmd_name_(disasm),
-      disassembler_parameters_(disasm_params) {
-    // Fake a runtime test for ScratchFile
+  AssemblerTestBase() {}
+
+  void SetUp() override {
+    // Fake a runtime test for ScratchDir.
+    CommonArtTest::SetUpAndroidRootEnvVars();
     CommonRuntimeTest::SetUpAndroidDataDir(android_data_);
+    scratch_dir_.emplace(/*keep_files=*/ kKeepDisassembledFiles);
   }
 
-  virtual ~AssemblerTestInfrastructure() {
+  void TearDown() override {
     // We leave temporaries in case this failed so we can debug issues.
     CommonRuntimeTest::TearDownAndroidDataDir(android_data_, false);
-    tmpnam_ = "";
   }
 
   // This is intended to be run as a test.
   bool CheckTools() {
-    std::string asm_tool = FindTool(assembler_cmd_name_);
-    if (!FileExists(asm_tool)) {
-      LOG(ERROR) << "Could not find assembler from " << assembler_cmd_name_;
-      LOG(ERROR) << "FindTool returned " << asm_tool;
-      FindToolDump(assembler_cmd_name_);
-      return false;
-    }
-    LOG(INFO) << "Chosen assembler command: " << GetAssemblerCommand();
-
-    std::string objdump_tool = FindTool(objdump_cmd_name_);
-    if (!FileExists(objdump_tool)) {
-      LOG(ERROR) << "Could not find objdump from " << objdump_cmd_name_;
-      LOG(ERROR) << "FindTool returned " << objdump_tool;
-      FindToolDump(objdump_cmd_name_);
-      return false;
-    }
-    LOG(INFO) << "Chosen objdump command: " << GetObjdumpCommand();
-
-    // Disassembly is optional.
-    std::string disassembler = GetDisassembleCommand();
-    if (disassembler.length() != 0) {
-      std::string disassembler_tool = FindTool(disassembler_cmd_name_);
-      if (!FileExists(disassembler_tool)) {
-        LOG(ERROR) << "Could not find disassembler from " << disassembler_cmd_name_;
-        LOG(ERROR) << "FindTool returned " << disassembler_tool;
-        FindToolDump(disassembler_cmd_name_);
+    for (auto cmd : { GetAssemblerCommand()[0], GetDisassemblerCommand()[0] }) {
+      if (!OS::FileExists(cmd.c_str())) {
+        LOG(ERROR) << "Could not find " << cmd;
         return false;
       }
-      LOG(INFO) << "Chosen disassemble command: " << GetDisassembleCommand();
-    } else {
-      LOG(INFO) << "No disassembler given.";
     }
-
     return true;
   }
 
   // Driver() assembles and compares the results. If the results are not equal and we have a
   // disassembler, disassemble both and check whether they have the same mnemonics (in which case
   // we just warn).
-  void Driver(const std::vector<uint8_t>& data,
+  void Driver(const std::vector<uint8_t>& art_code,
               const std::string& assembly_text,
               const std::string& test_name) {
-    EXPECT_NE(assembly_text.length(), 0U) << "Empty assembly";
+    ASSERT_NE(assembly_text.length(), 0U) << "Empty assembly";
+    InstructionSet isa = GetIsa();
+    auto test_path = [&](const char* ext) { return scratch_dir_->GetPath() + test_name + ext; };
 
-    NativeAssemblerResult res;
-    Compile(assembly_text, &res, test_name);
+    // Create file containing the reference source code.
+    std::string ref_asm_file = test_path(".ref.S");
+    WriteFile(ref_asm_file, assembly_text.data(), assembly_text.size());
 
-    EXPECT_TRUE(res.ok) << res.error_msg;
-    if (!res.ok) {
-      // No way of continuing.
-      return;
+    // Assemble reference object file.
+    std::string ref_obj_file = test_path(".ref.o");
+    ASSERT_TRUE(Assemble(ref_asm_file.c_str(), ref_obj_file.c_str()));
+
+    // Read the code produced by assembler from the ELF file.
+    std::vector<uint8_t> ref_code;
+    if (Is64BitInstructionSet(isa)) {
+      ReadElf</*IsElf64=*/true>(ref_obj_file, &ref_code);
+    } else {
+      ReadElf</*IsElf64=*/false>(ref_obj_file, &ref_code);
     }
 
-    if (data == *res.code) {
-      Clean(&res);
+    // Compare the ART generated code to the expected reference code.
+    if (art_code == ref_code) {
+      return;  // Success!
+    }
+
+    // Create ELF file containing the ART code.
+    std::string art_obj_file = test_path(".art.o");
+    if (Is64BitInstructionSet(isa)) {
+      WriteElf</*IsElf64=*/true>(art_obj_file, isa, art_code);
     } else {
-      if (DisassembleBinaries(data, *res.code, test_name)) {
-        if (data.size() > res.code->size()) {
-          // Fail this test with a fancy colored warning being printed.
-          EXPECT_TRUE(false) << "Assembly code is not identical, but disassembly of machine code "
-              "is equal: this implies sub-optimal encoding! Our code size=" << data.size() <<
-              ", gcc size=" << res.code->size();
-        } else {
-          // Otherwise just print an info message and clean up.
-          LOG(INFO) << "GCC chose a different encoding than ours, but the overall length is the "
-              "same.";
-          Clean(&res);
-        }
-      } else {
-        // This will output the assembly.
-        EXPECT_EQ(*res.code, data) << "Outputs (and disassembly) not identical.";
-      }
+      WriteElf</*IsElf64=*/false>(art_obj_file, isa, art_code);
+    }
+
+    // Disassemble both object files, and check that the outputs match.
+    std::string art_disassembly;
+    ASSERT_TRUE(Disassemble(art_obj_file, &art_disassembly));
+    art_disassembly = Replace(art_disassembly, art_obj_file, test_path("<extension-redacted>"));
+    std::string ref_disassembly;
+    ASSERT_TRUE(Disassemble(ref_obj_file, &ref_disassembly));
+    ref_disassembly = Replace(ref_disassembly, ref_obj_file, test_path("<extension-redacted>"));
+    ASSERT_EQ(art_disassembly, ref_disassembly) << "Outputs (and disassembly) not identical.";
+
+    // ART produced different (but valid) code than the reference assembler, report it.
+    if (art_code.size() > ref_code.size()) {
+      EXPECT_TRUE(false) << "ART code is larger then the reference code, but the disassembly"
+          "of machine code is equal: this means that ART is generating sub-optimal encoding! "
+          "ART code size=" << art_code.size() << ", reference code size=" << ref_code.size();
+    } else if (art_code.size() < ref_code.size()) {
+      EXPECT_TRUE(false) << "ART code is smaller than the reference code. Too good to be true?";
+    } else {
+      LOG(INFO) << "Reference assembler chose a different encoding than ART (of the same size)";
     }
   }
 
  protected:
-  // Return the host assembler command for this test.
-  virtual std::string GetAssemblerCommand() {
-    // Already resolved it once?
-    if (resolved_assembler_cmd_.length() != 0) {
-      return resolved_assembler_cmd_;
-    }
+  virtual InstructionSet GetIsa() = 0;
 
-    std::string line = FindTool(assembler_cmd_name_);
-    if (line.length() == 0) {
-      return line;
-    }
-
-    resolved_assembler_cmd_ = line + assembler_parameters_;
-
-    return resolved_assembler_cmd_;
+  std::string FindTool(const std::string& tool_name) {
+    return CommonArtTest::GetAndroidTool(tool_name.c_str(), GetIsa());
   }
 
-  // Return the host objdump command for this test.
-  virtual std::string GetObjdumpCommand() {
-    // Already resolved it once?
-    if (resolved_objdump_cmd_.length() != 0) {
-      return resolved_objdump_cmd_;
-    }
-
-    std::string line = FindTool(objdump_cmd_name_);
-    if (line.length() == 0) {
-      return line;
-    }
-
-    resolved_objdump_cmd_ = line + objdump_parameters_;
-
-    return resolved_objdump_cmd_;
-  }
-
-  // Return the host disassembler command for this test.
-  virtual std::string GetDisassembleCommand() {
-    // Already resolved it once?
-    if (resolved_disassemble_cmd_.length() != 0) {
-      return resolved_disassemble_cmd_;
-    }
-
-    std::string line = FindTool(disassembler_cmd_name_);
-    if (line.length() == 0) {
-      return line;
-    }
-
-    resolved_disassemble_cmd_ = line + disassembler_parameters_;
-
-    return resolved_disassemble_cmd_;
-  }
-
- private:
-  // Structure to store intermediates and results.
-  struct NativeAssemblerResult {
-    bool ok;
-    std::string error_msg;
-    std::string base_name;
-    std::unique_ptr<std::vector<uint8_t>> code;
-    uintptr_t length;
-  };
-
-  // Compile the assembly file from_file to a binary file to_file. Returns true on success.
-  bool Assemble(const char* from_file, const char* to_file, std::string* error_msg) {
-    bool have_assembler = FileExists(FindTool(assembler_cmd_name_));
-    EXPECT_TRUE(have_assembler) << "Cannot find assembler:" << GetAssemblerCommand();
-    if (!have_assembler) {
-      return false;
-    }
-
-    std::vector<std::string> args;
-
-    // Encaspulate the whole command line in a single string passed to
-    // the shell, so that GetAssemblerCommand() may contain arguments
-    // in addition to the program name.
-    args.push_back(GetAssemblerCommand());
-    args.push_back("-o");
-    args.push_back(to_file);
-    args.push_back(from_file);
-    std::string cmd = android::base::Join(args, ' ');
-
-    args.clear();
-    args.push_back("/bin/sh");
-    args.push_back("-c");
-    args.push_back(cmd);
-
-    bool success = Exec(args, error_msg);
-    if (!success) {
-      LOG(ERROR) << "Assembler command line:";
-      for (const std::string& arg : args) {
-        LOG(ERROR) << arg;
-      }
-    }
-    return success;
-  }
-
-  // Runs objdump -h on the binary file and extracts the first line with .text.
-  // Returns "" on failure.
-  std::string Objdump(const std::string& file) {
-    bool have_objdump = FileExists(FindTool(objdump_cmd_name_));
-    EXPECT_TRUE(have_objdump) << "Cannot find objdump: " << GetObjdumpCommand();
-    if (!have_objdump) {
-      return "";
-    }
-
-    std::string error_msg;
-    std::vector<std::string> args;
-
-    // Encaspulate the whole command line in a single string passed to
-    // the shell, so that GetObjdumpCommand() may contain arguments
-    // in addition to the program name.
-    args.push_back(GetObjdumpCommand());
-    args.push_back(file);
-    args.push_back(">");
-    args.push_back(file+".dump");
-    std::string cmd = android::base::Join(args, ' ');
-
-    args.clear();
-    args.push_back("/bin/sh");
-    args.push_back("-c");
-    args.push_back(cmd);
-
-    if (!Exec(args, &error_msg)) {
-      EXPECT_TRUE(false) << error_msg;
-    }
-
-    std::ifstream dump(file+".dump");
-
-    std::string line;
-    bool found = false;
-    while (std::getline(dump, line)) {
-      if (line.find(".text") != line.npos) {
-        found = true;
-        break;
-      }
-    }
-
-    dump.close();
-
-    if (found) {
-      return line;
-    } else {
-      return "";
+  virtual std::vector<std::string> GetAssemblerCommand() {
+    InstructionSet isa = GetIsa();
+    switch (isa) {
+      case InstructionSet::kX86:
+        return {FindTool("clang"), "--compile", "-target", "i386-linux-gnu"};
+      case InstructionSet::kX86_64:
+        return {FindTool("clang"), "--compile", "-target", "x86_64-linux-gnu"};
+      default:
+        LOG(FATAL) << "Unknown instruction set: " << isa;
+        UNREACHABLE();
     }
   }
 
-  // Disassemble both binaries and compare the text.
-  bool DisassembleBinaries(const std::vector<uint8_t>& data,
-                           const std::vector<uint8_t>& as,
-                           const std::string& test_name) {
-    std::string disassembler = GetDisassembleCommand();
-    if (disassembler.length() == 0) {
-      LOG(WARNING) << "No dissassembler command.";
-      return false;
-    }
-
-    std::string data_name = WriteToFile(data, test_name + ".ass");
-    std::string error_msg;
-    if (!DisassembleBinary(data_name, &error_msg)) {
-      LOG(INFO) << "Error disassembling: " << error_msg;
-      std::remove(data_name.c_str());
-      return false;
-    }
-
-    std::string as_name = WriteToFile(as, test_name + ".gcc");
-    if (!DisassembleBinary(as_name, &error_msg)) {
-      LOG(INFO) << "Error disassembling: " << error_msg;
-      std::remove(data_name.c_str());
-      std::remove((data_name + ".dis").c_str());
-      std::remove(as_name.c_str());
-      return false;
-    }
-
-    bool result = CompareFiles(data_name + ".dis", as_name + ".dis");
-
-    if (!kKeepDisassembledFiles) {
-      std::remove(data_name.c_str());
-      std::remove(as_name.c_str());
-      std::remove((data_name + ".dis").c_str());
-      std::remove((as_name + ".dis").c_str());
-    }
-
-    return result;
-  }
-
-  bool DisassembleBinary(const std::string& file, std::string* error_msg) {
-    std::vector<std::string> args;
-
-    // Encaspulate the whole command line in a single string passed to
-    // the shell, so that GetDisassembleCommand() may contain arguments
-    // in addition to the program name.
-    args.push_back(GetDisassembleCommand());
-    args.push_back(file);
-    args.push_back("| sed -n \'/<.data>/,$p\' | sed -e \'s/.*://\'");
-    args.push_back(">");
-    args.push_back(file+".dis");
-    std::string cmd = android::base::Join(args, ' ');
-
-    args.clear();
-    args.push_back("/bin/sh");
-    args.push_back("-c");
-    args.push_back(cmd);
-
-    return Exec(args, error_msg);
-  }
-
-  std::string WriteToFile(const std::vector<uint8_t>& buffer, const std::string& test_name) {
-    std::string file_name = GetTmpnam() + std::string("---") + test_name;
-    const char* data = reinterpret_cast<const char*>(buffer.data());
-    std::ofstream s_out(file_name + ".o");
-    s_out.write(data, buffer.size());
-    s_out.close();
-    return file_name + ".o";
-  }
-
-  bool CompareFiles(const std::string& f1, const std::string& f2) {
-    std::ifstream f1_in(f1);
-    std::ifstream f2_in(f2);
-
-    bool result = std::equal(std::istreambuf_iterator<char>(f1_in),
-                             std::istreambuf_iterator<char>(),
-                             std::istreambuf_iterator<char>(f2_in));
-
-    f1_in.close();
-    f2_in.close();
-
-    return result;
-  }
-
-  // Compile the given assembly code and extract the binary, if possible. Put result into res.
-  bool Compile(const std::string& assembly_code,
-               NativeAssemblerResult* res,
-               const std::string& test_name) {
-    res->ok = false;
-    res->code.reset(nullptr);
-
-    res->base_name = GetTmpnam() + std::string("---") + test_name;
-
-    // TODO: Lots of error checking.
-
-    std::ofstream s_out(res->base_name + ".S");
-    if (asm_header_ != nullptr) {
-      s_out << asm_header_;
-    }
-    s_out << assembly_code;
-    s_out.close();
-
-    if (!Assemble((res->base_name + ".S").c_str(), (res->base_name + ".o").c_str(),
-                  &res->error_msg)) {
-      res->error_msg = "Could not compile.";
-      return false;
-    }
-
-    std::string odump = Objdump(res->base_name + ".o");
-    if (odump.length() == 0) {
-      res->error_msg = "Objdump failed.";
-      return false;
-    }
-
-    std::istringstream iss(odump);
-    std::istream_iterator<std::string> start(iss);
-    std::istream_iterator<std::string> end;
-    std::vector<std::string> tokens(start, end);
-
-    if (tokens.size() < OBJDUMP_SECTION_LINE_MIN_TOKENS) {
-      res->error_msg = "Objdump output not recognized: too few tokens.";
-      return false;
-    }
-
-    if (tokens[1] != ".text") {
-      res->error_msg = "Objdump output not recognized: .text not second token.";
-      return false;
-    }
-
-    std::string lengthToken = "0x" + tokens[2];
-    std::istringstream(lengthToken) >> std::hex >> res->length;
-
-    std::string offsetToken = "0x" + tokens[5];
-    uintptr_t offset;
-    std::istringstream(offsetToken) >> std::hex >> offset;
-
-    std::ifstream obj(res->base_name + ".o");
-    obj.seekg(offset);
-    res->code.reset(new std::vector<uint8_t>(res->length));
-    obj.read(reinterpret_cast<char*>(&(*res->code)[0]), res->length);
-    obj.close();
-
-    res->ok = true;
-    return true;
-  }
-
-  // Remove temporary files.
-  void Clean(const NativeAssemblerResult* res) {
-    std::remove((res->base_name + ".S").c_str());
-    std::remove((res->base_name + ".o").c_str());
-    std::remove((res->base_name + ".o.dump").c_str());
-  }
-
-  // Check whether file exists. Is used for commands, so strips off any parameters: anything after
-  // the first space. We skip to the last slash for this, so it should work with directories with
-  // spaces.
-  static bool FileExists(const std::string& file) {
-    if (file.length() == 0) {
-      return false;
-    }
-
-    // Need to strip any options.
-    size_t last_slash = file.find_last_of('/');
-    if (last_slash == std::string::npos) {
-      // No slash, start looking at the start.
-      last_slash = 0;
-    }
-    size_t space_index = file.find(' ', last_slash);
-
-    if (space_index == std::string::npos) {
-      std::ifstream infile(file.c_str());
-      return infile.good();
-    } else {
-      std::string copy = file.substr(0, space_index - 1);
-
-      struct stat buf;
-      return stat(copy.c_str(), &buf) == 0;
+  virtual std::vector<std::string> GetDisassemblerCommand() {
+    switch (GetIsa()) {
+      case InstructionSet::kThumb2:
+        return {FindTool("llvm-objdump"), "--disassemble", "--triple", "thumbv7a-linux-gnueabi"};
+      default:
+        return {FindTool("llvm-objdump"), "--disassemble", "--no-show-raw-insn"};
     }
   }
 
-  static std::string GetGCCRootPath() {
-    return "prebuilts/gcc/linux-x86";
+  bool Assemble(const std::string& asm_file, const std::string& obj_file) {
+    std::vector<std::string> args = GetAssemblerCommand();
+    args.insert(args.end(), {"-o", obj_file, asm_file});
+    std::string output;
+    bool ok = CommonArtTestImpl::ForkAndExec(args, [](){ return true; }, &output).StandardSuccess();
+    if (!ok) {
+      LOG(ERROR) << "Assembler error:\n" << output;
+    }
+    return ok;
+  }
+
+  bool Disassemble(const std::string& obj_file, std::string* output) {
+    std::vector<std::string> args = GetDisassemblerCommand();
+    args.insert(args.end(), {obj_file});
+    bool ok = CommonArtTestImpl::ForkAndExec(args, [](){ return true; }, output).StandardSuccess();
+    if (!ok) {
+      LOG(ERROR) << "Disassembler error:\n" << *output;
+    }
+    *output = Replace(*output, "\t", " ");
+    return ok;
+  }
+
+  std::vector<uint8_t> ReadFile(const std::string& filename) {
+    std::unique_ptr<File> file(OS::OpenFileForReading(filename.c_str()));
+    CHECK(file.get() != nullptr);
+    std::vector<uint8_t> data(file->GetLength());
+    bool success = file->ReadFully(&data[0], data.size());
+    CHECK(success) << filename;
+    return data;
+  }
+
+  void WriteFile(const std::string& filename, const void* data, size_t size) {
+    std::unique_ptr<File> file(OS::CreateEmptyFile(filename.c_str()));
+    CHECK(file.get() != nullptr);
+    bool success = file->WriteFully(data, size);
+    CHECK(success) << filename;
+    CHECK_EQ(file->FlushClose(), 0);
+  }
+
+  // Helper method which reads the content of .text section from ELF file.
+  template<bool IsElf64>
+  void ReadElf(const std::string& filename, /*out*/ std::vector<uint8_t>* code) {
+    using ElfTypes = typename std::conditional<IsElf64, ElfTypes64, ElfTypes32>::type;
+    std::vector<uint8_t> data = ReadFile(filename);
+    ElfDebugReader<ElfTypes> reader((ArrayRef<const uint8_t>(data)));
+    const typename ElfTypes::Shdr* text = reader.GetSection(".text");
+    CHECK(text != nullptr);
+    *code = std::vector<uint8_t>(&data[text->sh_offset], &data[text->sh_offset + text->sh_size]);
+  }
+
+  // Helper method to create an ELF file containing only the given code in the .text section.
+  template<bool IsElf64>
+  void WriteElf(const std::string& filename, InstructionSet isa, const std::vector<uint8_t>& code) {
+    using ElfTypes = typename std::conditional<IsElf64, ElfTypes64, ElfTypes32>::type;
+    std::unique_ptr<File> file(OS::CreateEmptyFile(filename.c_str()));
+    CHECK(file.get() != nullptr);
+    FileOutputStream out(file.get());
+    std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
+    builder->Start(/* write_program_headers= */ false);
+    builder->GetText()->Start();
+    builder->GetText()->WriteFully(code.data(), code.size());
+    builder->GetText()->End();
+    builder->End();
+    CHECK(builder->Good());
+    CHECK_EQ(file->Close(), 0);
   }
 
   static std::string GetRootPath() {
@@ -486,127 +235,21 @@
     return getcwd(temp, 1024) ? std::string(temp) + "/" : std::string("");
   }
 
-  std::string FindTool(const std::string& tool_name) {
-    // Find the current tool. Wild-card pattern is "arch-string*tool-name".
-    std::string gcc_path = GetRootPath() + GetGCCRootPath();
-    std::vector<std::string> args;
-    args.push_back("find");
-    args.push_back(gcc_path);
-    args.push_back("-name");
-    args.push_back(architecture_string_ + "*" + tool_name);
-    args.push_back("|");
-    args.push_back("sort");
-    args.push_back("|");
-    args.push_back("tail");
-    args.push_back("-n");
-    args.push_back("1");
-    std::string tmp_file = GetTmpnam();
-    args.push_back(">");
-    args.push_back(tmp_file);
-    std::string sh_args = android::base::Join(args, ' ');
-
-    args.clear();
-    args.push_back("/bin/sh");
-    args.push_back("-c");
-    args.push_back(sh_args);
-
-    std::string error_msg;
-    if (!Exec(args, &error_msg)) {
-      EXPECT_TRUE(false) << error_msg;
-      UNREACHABLE();
+  std::string Replace(const std::string& str, const std::string& from, const std::string& to) {
+    std::string output;
+    size_t pos = 0;
+    for (auto match = str.find(from); match != str.npos; match = str.find(from, pos)) {
+      output += str.substr(pos, match - pos);
+      output += to;
+      pos = match + from.size();
     }
-
-    std::ifstream in(tmp_file.c_str());
-    std::string line;
-    if (!std::getline(in, line)) {
-      in.close();
-      std::remove(tmp_file.c_str());
-      return "";
-    }
-    in.close();
-    std::remove(tmp_file.c_str());
-    return line;
+    output += str.substr(pos, str.size() - pos);
+    return output;
   }
 
-  // Helper for below. If name_predicate is empty, search for all files, otherwise use it for the
-  // "-name" option.
-  static void FindToolDumpPrintout(const std::string& name_predicate,
-                                   const std::string& tmp_file) {
-    std::string gcc_path = GetRootPath() + GetGCCRootPath();
-    std::vector<std::string> args;
-    args.push_back("find");
-    args.push_back(gcc_path);
-    if (!name_predicate.empty()) {
-      args.push_back("-name");
-      args.push_back(name_predicate);
-    }
-    args.push_back("|");
-    args.push_back("sort");
-    args.push_back(">");
-    args.push_back(tmp_file);
-    std::string sh_args = android::base::Join(args, ' ');
-
-    args.clear();
-    args.push_back("/bin/sh");
-    args.push_back("-c");
-    args.push_back(sh_args);
-
-    std::string error_msg;
-    if (!Exec(args, &error_msg)) {
-      EXPECT_TRUE(false) << error_msg;
-      UNREACHABLE();
-    }
-
-    LOG(ERROR) << "FindToolDump: gcc_path=" << gcc_path
-               << " cmd=" << sh_args;
-    std::ifstream in(tmp_file.c_str());
-    if (in) {
-      std::string line;
-      while (std::getline(in, line)) {
-        LOG(ERROR) << line;
-      }
-    }
-    in.close();
-    std::remove(tmp_file.c_str());
-  }
-
-  // For debug purposes.
-  void FindToolDump(const std::string& tool_name) {
-    // Check with the tool name.
-    FindToolDumpPrintout(architecture_string_ + "*" + tool_name, GetTmpnam());
-    FindToolDumpPrintout("", GetTmpnam());
-  }
-
-  // Use a consistent tmpnam, so store it.
-  std::string GetTmpnam() {
-    if (tmpnam_.length() == 0) {
-      ScratchFile tmp;
-      tmpnam_ = tmp.GetFilename() + "asm";
-    }
-    return tmpnam_;
-  }
-
-  static constexpr size_t OBJDUMP_SECTION_LINE_MIN_TOKENS = 6;
-
-  std::string architecture_string_;
-  const char* asm_header_;
-
-  std::string assembler_cmd_name_;
-  std::string assembler_parameters_;
-
-  std::string objdump_cmd_name_;
-  std::string objdump_parameters_;
-
-  std::string disassembler_cmd_name_;
-  std::string disassembler_parameters_;
-
-  std::string resolved_assembler_cmd_;
-  std::string resolved_objdump_cmd_;
-  std::string resolved_disassemble_cmd_;
-
+  std::optional<ScratchDir> scratch_dir_;
   std::string android_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(AssemblerTestInfrastructure);
+  DISALLOW_COPY_AND_ASSIGN(AssemblerTestBase);
 };
 
 }  // namespace art
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index c9ece1d..5265152 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -18,13 +18,16 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/types.h>
+
 #include <fstream>
 #include <map>
+#include <regex>
 
 #include "gtest/gtest.h"
 
 #include "jni/quick/calling_convention.h"
 #include "utils/arm/jni_macro_assembler_arm_vixl.h"
+#include "utils/assembler_test_base.h"
 
 #include "base/hex_dump.h"
 #include "base/malloc_arena_pool.h"
@@ -36,170 +39,59 @@
 // Include results file (generated manually)
 #include "assembler_thumb_test_expected.cc.inc"
 
-#ifndef ART_TARGET_ANDROID
-// This controls whether the results are printed to the
-// screen or compared against the expected output.
-// To generate new expected output, set this to true and
-// copy the output into the .cc.inc file in the form
-// of the other results.
-//
-// When this is false, the results are not printed to the
-// output, but are compared against the expected results
-// in the .cc.inc file.
-static constexpr bool kPrintResults = false;
-#endif
-
-void SetAndroidData() {
-  const char* data = getenv("ANDROID_DATA");
-  if (data == nullptr) {
-    setenv("ANDROID_DATA", "/tmp", 1);
-  }
-}
-
-int CompareIgnoringSpace(const char* s1, const char* s2) {
-  while (*s1 != '\0') {
-    while (isspace(*s1)) ++s1;
-    while (isspace(*s2)) ++s2;
-    if (*s1 == '\0' || *s1 != *s2) {
-      break;
-    }
-    ++s1;
-    ++s2;
-  }
-  return *s1 - *s2;
-}
-
-void InitResults() {
-  if (test_results.empty()) {
-    setup_results();
-  }
-}
-
-std::string GetToolsDir() {
-#ifndef ART_TARGET_ANDROID
-  // This will only work on the host.  There is no as, objcopy or objdump on the device.
-  static std::string toolsdir;
-
-  if (toolsdir.empty()) {
-    setup_results();
-    toolsdir = CommonRuntimeTest::GetAndroidTargetToolsDir(InstructionSet::kThumb2);
-    SetAndroidData();
-  }
-
-  return toolsdir;
-#else
-  return std::string();
-#endif
-}
-
-void DumpAndCheck(std::vector<uint8_t>& code, const char* testname, const char* const* results) {
-#ifndef ART_TARGET_ANDROID
-  static std::string toolsdir = GetToolsDir();
-
-  ScratchFile file;
-
-  const char* filename = file.GetFilename().c_str();
-
-  std::ofstream out(filename);
-  if (out) {
-    out << ".section \".text\"\n";
-    out << ".syntax unified\n";
-    out << ".arch armv7-a\n";
-    out << ".thumb\n";
-    out << ".thumb_func\n";
-    out << ".type " << testname << ", #function\n";
-    out << ".global " << testname << "\n";
-    out << testname << ":\n";
-    out << ".fnstart\n";
-
-    for (uint32_t i = 0 ; i < code.size(); ++i) {
-      out << ".byte " << (static_cast<int>(code[i]) & 0xff) << "\n";
-    }
-    out << ".fnend\n";
-    out << ".size " << testname << ", .-" << testname << "\n";
-  }
-  out.close();
-
-  char cmd[1024];
-
-  // Assemble the .S
-  snprintf(cmd, sizeof(cmd), "%sas %s -o %s.o", toolsdir.c_str(), filename, filename);
-  int cmd_result = system(cmd);
-  ASSERT_EQ(cmd_result, 0) << cmd << strerror(errno);
-
-  // Disassemble.
-  snprintf(cmd, sizeof(cmd), "%sobjdump -D -M force-thumb --section=.text %s.o  | grep '^  *[0-9a-f][0-9a-f]*:'",
-    toolsdir.c_str(), filename);
-  if (kPrintResults) {
-    // Print the results only, don't check. This is used to generate new output for inserting
-    // into the .inc file, so let's add the appropriate prefix/suffix needed in the C++ code.
-    strcat(cmd, " | sed '-es/^/  \"/' | sed '-es/$/\\\\n\",/'");
-    int cmd_result3 = system(cmd);
-    ASSERT_EQ(cmd_result3, 0) << strerror(errno);
-  } else {
-    // Check the results match the appropriate results in the .inc file.
-    FILE *fp = popen(cmd, "r");
-    ASSERT_TRUE(fp != nullptr);
-
-    uint32_t lineindex = 0;
-
-    while (!feof(fp)) {
-      char testline[256];
-      char *s = fgets(testline, sizeof(testline), fp);
-      if (s == nullptr) {
-        break;
-      }
-      if (CompareIgnoringSpace(results[lineindex], testline) != 0) {
-        LOG(FATAL) << "Output is not as expected at line: " << lineindex
-          << results[lineindex] << "/" << testline << ", test name: " << testname;
-      }
-      ++lineindex;
-    }
-    // Check that we are at the end.
-    ASSERT_TRUE(results[lineindex] == nullptr);
-    fclose(fp);
-  }
-
-  char buf[FILENAME_MAX];
-  snprintf(buf, sizeof(buf), "%s.o", filename);
-  unlink(buf);
-#endif  // ART_TARGET_ANDROID
-}
-
-class ArmVIXLAssemblerTest : public ::testing::Test {
+class ArmVIXLAssemblerTest : public AssemblerTestBase {
  public:
   ArmVIXLAssemblerTest() : pool(), allocator(&pool), assembler(&allocator) { }
 
+ protected:
+  InstructionSet GetIsa() override { return InstructionSet::kThumb2; }
+
+  void DumpAndCheck(std::vector<uint8_t>& code, const char* testname, const std::string& expected) {
+#ifndef ART_TARGET_ANDROID
+    std::string obj_file = scratch_dir_->GetPath() + testname + ".o";
+    WriteElf</*IsElf64=*/false>(obj_file, InstructionSet::kThumb2, code);
+    std::string disassembly;
+    ASSERT_TRUE(Disassemble(obj_file, &disassembly));
+
+    // objdump on buildbot seems to sometimes add annotation like in "bne #226 <.text+0x1e8>".
+    // It is unclear why it does not reproduce locally. As work-around, remove the annotation.
+    std::regex annotation_re(" <\\.text\\+\\w+>");
+    disassembly = std::regex_replace(disassembly, annotation_re, "");
+
+    std::string expected2 = "\n" +
+        obj_file + ": file format elf32-littlearm\n\n\n"
+        "Disassembly of section .text:\n\n"
+        "00000000 <.text>:\n" +
+        expected;
+    EXPECT_EQ(expected2, disassembly);
+    if (expected2 != disassembly) {
+      std::string out = "  \"" + Replace(disassembly, "\n", "\\n\"\n  \"") + "\"";
+      printf("C++ formatted disassembler output for %s:\n%s\n", testname, out.c_str());
+    }
+#endif  // ART_TARGET_ANDROID
+  }
+
+#define __ assembler.
+
+  void EmitAndCheck(const char* testname, const char* expected) {
+    __ FinalizeCode();
+    size_t cs = __ CodeSize();
+    std::vector<uint8_t> managed_code(cs);
+    MemoryRegion code(&managed_code[0], managed_code.size());
+    __ FinalizeInstructions(code);
+
+    DumpAndCheck(managed_code, testname, expected);
+  }
+
+#undef __
+
+#define __ assembler.
+
   MallocArenaPool pool;
   ArenaAllocator allocator;
   ArmVIXLJNIMacroAssembler assembler;
 };
 
-#define __ assembler->
-
-void EmitAndCheck(ArmVIXLJNIMacroAssembler* assembler, const char* testname,
-                  const char* const* results) {
-  __ FinalizeCode();
-  size_t cs = __ CodeSize();
-  std::vector<uint8_t> managed_code(cs);
-  MemoryRegion code(&managed_code[0], managed_code.size());
-  __ FinalizeInstructions(code);
-
-  DumpAndCheck(managed_code, testname, results);
-}
-
-void EmitAndCheck(ArmVIXLJNIMacroAssembler* assembler, const char* testname) {
-  InitResults();
-  std::map<std::string, const char* const*>::iterator results = test_results.find(testname);
-  ASSERT_NE(results, test_results.end());
-
-  EmitAndCheck(assembler, testname, results->second);
-}
-
-#undef __
-
-#define __ assembler.
-
 TEST_F(ArmVIXLAssemblerTest, VixlJniHelpers) {
   // Run the test only with Baker read barriers, as the expected
   // generated code contains a Marking Register refresh instruction.
@@ -224,9 +116,19 @@
   ArrayRef<const ManagedRegister> callee_save_regs = jni_conv->CalleeSaveRegisters();
 
   const ManagedRegister method_register = ArmManagedRegister::FromCoreRegister(R0);
+  const ManagedRegister hidden_arg_register = ArmManagedRegister::FromCoreRegister(R4);
   const ManagedRegister scratch_register = ArmManagedRegister::FromCoreRegister(R12);
 
-  __ BuildFrame(frame_size, mr_conv->MethodRegister(), callee_save_regs, mr_conv->EntrySpills());
+  __ BuildFrame(frame_size, mr_conv->MethodRegister(), callee_save_regs);
+
+  // Spill arguments.
+  mr_conv->ResetIterator(FrameOffset(frame_size));
+  for (; mr_conv->HasNext(); mr_conv->Next()) {
+    if (mr_conv->IsCurrentParamInRegister()) {
+      size_t size = mr_conv->IsCurrentParamALongOrDouble() ? 8u : 4u;
+      __ Store(mr_conv->CurrentParamStackOffset(), mr_conv->CurrentParamRegister(), size);
+    }
+  }
   __ IncreaseFrameSize(32);
 
   // Loads
@@ -249,33 +151,33 @@
   __ Store(FrameOffset(1024), method_register, 4);
   __ Store(FrameOffset(4092), scratch_register, 4);
   __ Store(FrameOffset(4096), scratch_register, 4);
-  __ StoreImmediateToFrame(FrameOffset(48), 0xFF, scratch_register);
-  __ StoreImmediateToFrame(FrameOffset(48), 0xFFFFFF, scratch_register);
+  __ StoreImmediateToFrame(FrameOffset(48), 0xFF);
+  __ StoreImmediateToFrame(FrameOffset(48), 0xFFFFFF);
   __ StoreRawPtr(FrameOffset(48), scratch_register);
   __ StoreRef(FrameOffset(48), scratch_register);
-  __ StoreSpanning(FrameOffset(48), method_register, FrameOffset(48), scratch_register);
-  __ StoreStackOffsetToThread(ThreadOffset32(512), FrameOffset(4096), scratch_register);
+  __ StoreSpanning(FrameOffset(48), method_register, FrameOffset(48));
+  __ StoreStackOffsetToThread(ThreadOffset32(512), FrameOffset(4096));
   __ StoreStackPointerToThread(ThreadOffset32(512));
 
   // Other
-  __ Call(method_register, FrameOffset(48), scratch_register);
-  __ Copy(FrameOffset(48), FrameOffset(44), scratch_register, 4);
-  __ CopyRawPtrFromThread(FrameOffset(44), ThreadOffset32(512), scratch_register);
-  __ CopyRef(FrameOffset(48), FrameOffset(44), scratch_register);
+  __ Call(method_register, FrameOffset(48));
+  __ Copy(FrameOffset(48), FrameOffset(44), 4);
+  __ CopyRawPtrFromThread(FrameOffset(44), ThreadOffset32(512));
+  __ CopyRef(FrameOffset(48), FrameOffset(44));
   __ GetCurrentThread(method_register);
-  __ GetCurrentThread(FrameOffset(48), scratch_register);
-  __ Move(scratch_register, method_register, 4);
+  __ GetCurrentThread(FrameOffset(48));
+  __ Move(hidden_arg_register, method_register, 4);
   __ VerifyObject(scratch_register, false);
 
-  __ CreateHandleScopeEntry(scratch_register, FrameOffset(48), scratch_register, true);
-  __ CreateHandleScopeEntry(scratch_register, FrameOffset(48), scratch_register, false);
-  __ CreateHandleScopeEntry(method_register, FrameOffset(48), scratch_register, true);
-  __ CreateHandleScopeEntry(FrameOffset(48), FrameOffset(64), scratch_register, true);
-  __ CreateHandleScopeEntry(method_register, FrameOffset(0), scratch_register, true);
-  __ CreateHandleScopeEntry(method_register, FrameOffset(1025), scratch_register, true);
-  __ CreateHandleScopeEntry(scratch_register, FrameOffset(1025), scratch_register, true);
+  __ CreateJObject(scratch_register, FrameOffset(48), scratch_register, true);
+  __ CreateJObject(scratch_register, FrameOffset(48), scratch_register, false);
+  __ CreateJObject(method_register, FrameOffset(48), scratch_register, true);
+  __ CreateJObject(FrameOffset(48), FrameOffset(64), true);
+  __ CreateJObject(method_register, FrameOffset(0), scratch_register, true);
+  __ CreateJObject(method_register, FrameOffset(1025), scratch_register, true);
+  __ CreateJObject(scratch_register, FrameOffset(1025), scratch_register, true);
 
-  __ ExceptionPoll(scratch_register, 0);
+  __ ExceptionPoll(0);
 
   // Push the target out of range of branch emitted by ExceptionPoll.
   for (int i = 0; i < 64; i++) {
@@ -286,7 +188,7 @@
   __ DecreaseFrameSize(32);
   __ RemoveFrame(frame_size, callee_save_regs, /* may_suspend= */ true);
 
-  EmitAndCheck(&assembler, "VixlJniHelpers");
+  EmitAndCheck("VixlJniHelpers", VixlJniHelpersResults);
 }
 
 #undef __
@@ -329,7 +231,7 @@
   __ LoadFromOffset(kLoadUnsignedByte, R2, R4, 12);
   __ LoadFromOffset(kLoadSignedHalfword, R2, R4, 12);
 
-  EmitAndCheck(&assembler, "VixlLoadFromOffset");
+  EmitAndCheck("VixlLoadFromOffset", VixlLoadFromOffsetResults);
 }
 
 TEST_F(ArmVIXLAssemblerTest, VixlStoreToOffset) {
@@ -360,7 +262,7 @@
 
   __ StoreToOffset(kStoreByte, R2, R4, 12);
 
-  EmitAndCheck(&assembler, "VixlStoreToOffset");
+  EmitAndCheck("VixlStoreToOffset", VixlStoreToOffsetResults);
 }
 
 #undef __
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index 6475607..1678f87 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -1,267 +1,258 @@
-const char* const VixlJniHelpersResults[] = {
-  "   0:	e92d 4de0 	stmdb	sp!, {r5, r6, r7, r8, sl, fp, lr}\n",
-  "   4:	ed2d 8a10 	vpush	{s16-s31}\n",
-  "   8:	b089      	sub	sp, #36	; 0x24\n",
-  "   a:	9000      	str	r0, [sp, #0]\n",
-  "   c:	9121      	str	r1, [sp, #132]	; 0x84\n",
-  "   e:	ed8d 0a22 	vstr	s0, [sp, #136]	; 0x88\n",
-  "  12:	9223      	str	r2, [sp, #140]	; 0x8c\n",
-  "  14:	9324      	str	r3, [sp, #144]	; 0x90\n",
-  "  16:	b088      	sub	sp, #32\n",
-  "  18:	f5ad 5d80 	sub.w	sp, sp, #4096	; 0x1000\n",
-  "  1c:	9808      	ldr	r0, [sp, #32]\n",
-  "  1e:	981f      	ldr	r0, [sp, #124]	; 0x7c\n",
-  "  20:	9821      	ldr	r0, [sp, #132]	; 0x84\n",
-  "  22:	98ff      	ldr	r0, [sp, #1020]	; 0x3fc\n",
-  "  24:	f8dd 0400 	ldr.w	r0, [sp, #1024]	; 0x400\n",
-  "  28:	f8dd cffc 	ldr.w	ip, [sp, #4092]	; 0xffc\n",
-  "  2c:	f50d 5c80 	add.w	ip, sp, #4096	; 0x1000\n",
-  "  30:	f8dc c000 	ldr.w	ip, [ip]\n",
-  "  34:	f8d9 c200 	ldr.w	ip, [r9, #512]	; 0x200\n",
-  "  38:	f8dc 0080 	ldr.w	r0, [ip, #128]	; 0x80\n",
-  "  3c:	9008      	str	r0, [sp, #32]\n",
-  "  3e:	901f      	str	r0, [sp, #124]	; 0x7c\n",
-  "  40:	9021      	str	r0, [sp, #132]	; 0x84\n",
-  "  42:	90ff      	str	r0, [sp, #1020]	; 0x3fc\n",
-  "  44:	f8cd 0400 	str.w	r0, [sp, #1024]	; 0x400\n",
-  "  48:	f8cd cffc 	str.w	ip, [sp, #4092]	; 0xffc\n",
-  "  4c:	f84d 5d04 	str.w	r5, [sp, #-4]!\n",
-  "  50:	f50d 5580 	add.w	r5, sp, #4096	; 0x1000\n",
-  "  54:	f8c5 c004 	str.w	ip, [r5, #4]\n",
-  "  58:	f85d 5b04 	ldr.w	r5, [sp], #4\n",
-  "  5c:	f04f 0cff 	mov.w	ip, #255	; 0xff\n",
-  "  60:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  64:	f06f 4c7f 	mvn.w	ip, #4278190080	; 0xff000000\n",
-  "  68:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  6c:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  70:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  74:	900c      	str	r0, [sp, #48]	; 0x30\n",
-  "  76:	f8dd c030 	ldr.w	ip, [sp, #48]	; 0x30\n",
-  "  7a:	f8cd c034 	str.w	ip, [sp, #52]	; 0x34\n",
-  "  7e:	f50d 5c80 	add.w	ip, sp, #4096	; 0x1000\n",
-  "  82:	f8c9 c200 	str.w	ip, [r9, #512]	; 0x200\n",
-  "  86:	f8c9 d200 	str.w	sp, [r9, #512]	; 0x200\n",
-  "  8a:	f8d0 c030 	ldr.w	ip, [r0, #48]	; 0x30\n",
-  "  8e:	47e0      	blx	ip\n",
-  "  90:	f8dd c02c 	ldr.w	ip, [sp, #44]	; 0x2c\n",
-  "  94:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  98:	f8d9 c200 	ldr.w	ip, [r9, #512]	; 0x200\n",
-  "  9c:	f8cd c02c 	str.w	ip, [sp, #44]	; 0x2c\n",
-  "  a0:	f8dd c02c 	ldr.w	ip, [sp, #44]	; 0x2c\n",
-  "  a4:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  a8:	4648      	mov	r0, r9\n",
-  "  aa:	f8cd 9030 	str.w	r9, [sp, #48]	; 0x30\n",
-  "  ae:	4684      	mov	ip, r0\n",
-  "  b0:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  b4:	bf18      	it	ne\n",
-  "  b6:	f10d 0c30 	addne.w	ip, sp, #48	; 0x30\n",
-  "  ba:	f10d 0c30 	add.w	ip, sp, #48	; 0x30\n",
-  "  be:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  c2:	bf0c      	ite	eq\n",
-  "  c4:	2000      	moveq	r0, #0\n",
-  "  c6:	a80c      	addne	r0, sp, #48	; 0x30\n",
-  "  c8:	f8dd c040 	ldr.w	ip, [sp, #64]	; 0x40\n",
-  "  cc:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  d0:	bf18      	it	ne\n",
-  "  d2:	f10d 0c40 	addne.w	ip, sp, #64	; 0x40\n",
-  "  d6:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  da:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  de:	bf0c      	ite	eq\n",
-  "  e0:	2000      	moveq	r0, #0\n",
-  "  e2:	4668      	movne	r0, sp\n",
-  "  e4:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  e8:	bf0c      	ite	eq\n",
-  "  ea:	2000      	moveq	r0, #0\n",
-  "  ec:	f20d 4001 	addwne	r0, sp, #1025	; 0x401\n",
-  "  f0:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  f4:	bf18      	it	ne\n",
-  "  f6:	f20d 4c01 	addwne	ip, sp, #1025	; 0x401\n",
-  "  fa:	f8d9 c0a4 	ldr.w	ip, [r9, #164]	; 0xa4\n",
-  "  fe:	f1bc 0f00 	cmp.w	ip, #0\n",
-  " 102:	d171      	bne.n	1e8 <VixlJniHelpers+0x1e8>\n",
-  " 104:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 108:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 10c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 110:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 114:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 118:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 11c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 120:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 124:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 128:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 12c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 130:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 134:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 138:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 13c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 140:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 144:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 148:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 14c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 150:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 154:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 158:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 15c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 160:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 164:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 168:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 16c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 170:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 174:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 178:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 17c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 180:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 184:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 188:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 18c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 190:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 194:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 198:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 19c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1a0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1a4:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1a8:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1ac:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1b0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1b4:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1b8:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1bc:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1c0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1c4:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1c8:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1cc:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1d0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1d4:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1d8:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1dc:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1e0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1e4:	f000 b802 	b.w	1ec <VixlJniHelpers+0x1ec>\n",
-  " 1e8:	f000 b81b 	b.w	222 <VixlJniHelpers+0x222>\n",
-  " 1ec:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1f0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1f4:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1f8:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1fc:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 200:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 204:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 208:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 20c:	f50d 5d80 	add.w	sp, sp, #4096	; 0x1000\n",
-  " 210:	b008      	add	sp, #32\n",
-  " 212:	b009      	add	sp, #36	; 0x24\n",
-  " 214:	ecbd 8a10 	vpop	{s16-s31}\n",
-  " 218:	e8bd 4de0 	ldmia.w	sp!, {r5, r6, r7, r8, sl, fp, lr}\n",
-  " 21c:	f8d9 8034 	ldr.w	r8, [r9, #52]	; 0x34\n",
-  " 220:	4770      	bx	lr\n",
-  " 222:	4660      	mov	r0, ip\n",
-  " 224:	f8d9 c2e8 	ldr.w	ip, [r9, #744]	; 0x2e8\n",
-  " 228:	47e0      	blx	ip\n",
-  nullptr
+const char* const VixlJniHelpersResults = {
+  "       0: 2d e9 e0 4d   push.w {r5, r6, r7, r8, r10, r11, lr}\n"
+  "       4: 2d ed 10 8a   vpush {s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}\n"
+  "       8: 85 b0         sub sp, #20\n"
+  "       a: 00 90         str r0, [sp]\n"
+  "       c: 1d 91         str r1, [sp, #116]\n"
+  "       e: 8d ed 1e 0a   vstr s0, [sp, #120]\n"
+  "      12: 1f 92         str r2, [sp, #124]\n"
+  "      14: 20 93         str r3, [sp, #128]\n"
+  "      16: 88 b0         sub sp, #32\n"
+  "      18: ad f5 80 5d   sub.w sp, sp, #4096\n"
+  "      1c: 08 98         ldr r0, [sp, #32]\n"
+  "      1e: 1f 98         ldr r0, [sp, #124]\n"
+  "      20: 21 98         ldr r0, [sp, #132]\n"
+  "      22: ff 98         ldr r0, [sp, #1020]\n"
+  "      24: dd f8 00 04   ldr.w r0, [sp, #1024]\n"
+  "      28: dd f8 fc cf   ldr.w r12, [sp, #4092]\n"
+  "      2c: 0d f5 80 5c   add.w r12, sp, #4096\n"
+  "      30: dc f8 00 c0   ldr.w r12, [r12]\n"
+  "      34: d9 f8 00 c2   ldr.w r12, [r9, #512]\n"
+  "      38: dc f8 80 00   ldr.w r0, [r12, #128]\n"
+  "      3c: 08 90         str r0, [sp, #32]\n"
+  "      3e: 1f 90         str r0, [sp, #124]\n"
+  "      40: 21 90         str r0, [sp, #132]\n"
+  "      42: ff 90         str r0, [sp, #1020]\n"
+  "      44: cd f8 00 04   str.w r0, [sp, #1024]\n"
+  "      48: cd f8 fc cf   str.w r12, [sp, #4092]\n"
+  "      4c: 4d f8 04 5d   str r5, [sp, #-4]!\n"
+  "      50: 0d f5 80 55   add.w r5, sp, #4096\n"
+  "      54: c5 f8 04 c0   str.w r12, [r5, #4]\n"
+  "      58: 5d f8 04 5b   ldr r5, [sp], #4\n"
+  "      5c: 4f f0 ff 0c   mov.w r12, #255\n"
+  "      60: cd f8 30 c0   str.w r12, [sp, #48]\n"
+  "      64: 6f f0 7f 4c   mvn r12, #4278190080\n"
+  "      68: cd f8 30 c0   str.w r12, [sp, #48]\n"
+  "      6c: cd f8 30 c0   str.w r12, [sp, #48]\n"
+  "      70: cd f8 30 c0   str.w r12, [sp, #48]\n"
+  "      74: 0c 90         str r0, [sp, #48]\n"
+  "      76: dd f8 30 c0   ldr.w r12, [sp, #48]\n"
+  "      7a: cd f8 34 c0   str.w r12, [sp, #52]\n"
+  "      7e: 0d f5 80 5c   add.w r12, sp, #4096\n"
+  "      82: c9 f8 00 c2   str.w r12, [r9, #512]\n"
+  "      86: c9 f8 00 d2   str.w sp, [r9, #512]\n"
+  "      8a: d0 f8 30 e0   ldr.w lr, [r0, #48]\n"
+  "      8e: f0 47         blx lr\n"
+  "      90: dd f8 2c c0   ldr.w r12, [sp, #44]\n"
+  "      94: cd f8 30 c0   str.w r12, [sp, #48]\n"
+  "      98: d9 f8 00 c2   ldr.w r12, [r9, #512]\n"
+  "      9c: cd f8 2c c0   str.w r12, [sp, #44]\n"
+  "      a0: dd f8 2c c0   ldr.w r12, [sp, #44]\n"
+  "      a4: cd f8 30 c0   str.w r12, [sp, #48]\n"
+  "      a8: 48 46         mov r0, r9\n"
+  "      aa: cd f8 30 90   str.w r9, [sp, #48]\n"
+  "      ae: 04 46         mov r4, r0\n"
+  "      b0: bc f1 00 0f   cmp.w r12, #0\n"
+  "      b4: 18 bf         it ne\n"
+  "      b6: 0d f1 30 0c   addne.w r12, sp, #48\n"
+  "      ba: 0d f1 30 0c   add.w r12, sp, #48\n"
+  "      be: bc f1 00 0f   cmp.w r12, #0\n"
+  "      c2: 0c bf         ite eq\n"
+  "      c4: 00 20         moveq r0, #0\n"
+  "      c6: 0c a8         addne r0, sp, #48\n"
+  "      c8: dd f8 40 c0   ldr.w r12, [sp, #64]\n"
+  "      cc: bc f1 00 0f   cmp.w r12, #0\n"
+  "      d0: 18 bf         it ne\n"
+  "      d2: 0d f1 40 0c   addne.w r12, sp, #64\n"
+  "      d6: cd f8 30 c0   str.w r12, [sp, #48]\n"
+  "      da: bc f1 00 0f   cmp.w r12, #0\n"
+  "      de: 0c bf         ite eq\n"
+  "      e0: 00 20         moveq r0, #0\n"
+  "      e2: 68 46         movne r0, sp\n"
+  "      e4: bc f1 00 0f   cmp.w r12, #0\n"
+  "      e8: 0c bf         ite eq\n"
+  "      ea: 00 20         moveq r0, #0\n"
+  "      ec: 0d f2 01 40   addwne r0, sp, #1025\n"
+  "      f0: bc f1 00 0f   cmp.w r12, #0\n"
+  "      f4: 18 bf         it ne\n"
+  "      f6: 0d f2 01 4c   addwne r12, sp, #1025\n"
+  "      fa: d9 f8 9c c0   ldr.w r12, [r9, #156]\n"
+  "      fe: bc f1 00 0f   cmp.w r12, #0\n"
+  "     102: 71 d1         bne #226\n"
+  "     104: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     108: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     10c: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     110: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     114: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     118: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     11c: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     120: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     124: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     128: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     12c: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     130: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     134: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     138: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     13c: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     140: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     144: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     148: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     14c: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     150: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     154: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     158: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     15c: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     160: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     164: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     168: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     16c: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     170: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     174: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     178: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     17c: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     180: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     184: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     188: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     18c: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     190: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     194: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     198: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     19c: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1a0: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1a4: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1a8: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1ac: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1b0: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1b4: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1b8: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1bc: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1c0: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1c4: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1c8: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1cc: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1d0: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1d4: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1d8: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1dc: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1e0: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1e4: 00 f0 02 b8   b.w #4\n"
+  "     1e8: 00 f0 1b b8   b.w #54\n"
+  "     1ec: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1f0: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1f4: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1f8: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     1fc: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     200: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     204: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     208: cd f8 ff c7   str.w r12, [sp, #2047]\n"
+  "     20c: 0d f5 80 5d   add.w sp, sp, #4096\n"
+  "     210: 08 b0         add sp, #32\n"
+  "     212: 05 b0         add sp, #20\n"
+  "     214: bd ec 10 8a   vpop {s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}\n"
+  "     218: bd e8 e0 4d   pop.w {r5, r6, r7, r8, r10, r11, lr}\n"
+  "     21c: d9 f8 30 80   ldr.w r8, [r9, #48]\n"
+  "     220: 70 47         bx lr\n"
+  "     222: 60 46         mov r0, r12\n"
+  "     224: d9 f8 e0 e2   ldr.w lr, [r9, #736]\n"
+  "     228: f0 47         blx lr\n"
 };
 
-const char* const VixlLoadFromOffsetResults[] = {
-  "   0:  68e2        ldr r2, [r4, #12]\n",
-  "   2:  f8d4 2fff   ldr.w r2, [r4, #4095] ; 0xfff\n",
-  "   6:  f504 5280   add.w r2, r4, #4096 ; 0x1000\n",
-  "   a:  6812        ldr r2, [r2, #0]\n",
-  "   c:  f504 1280   add.w r2, r4, #1048576  ; 0x100000\n",
-  "  10:  f8d2 20a4   ldr.w r2, [r2, #164]  ; 0xa4\n",
-  "  14:  f44f 5280   mov.w r2, #4096 ; 0x1000\n",
-  "  18:  f2c0 0210   movt  r2, #16\n",
-  "  1c:  4422        add r2, r4\n",
-  "  1e:  6812        ldr r2, [r2, #0]\n",
-  "  20:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  24:  f2c0 0c10   movt  ip, #16\n",
-  "  28:  4464        add r4, ip\n",
-  "  2a:  6824        ldr r4, [r4, #0]\n",
-  "  2c:  89a2        ldrh  r2, [r4, #12]\n",
-  "  2e:  f8b4 2fff   ldrh.w  r2, [r4, #4095] ; 0xfff\n",
-  "  32:  f504 5280   add.w r2, r4, #4096 ; 0x1000\n",
-  "  36:  8812        ldrh  r2, [r2, #0]\n",
-  "  38:  f504 1280   add.w r2, r4, #1048576  ; 0x100000\n",
-  "  3c:  f8b2 20a4   ldrh.w  r2, [r2, #164]  ; 0xa4\n",
-  "  40:  f44f 5280   mov.w r2, #4096 ; 0x1000\n",
-  "  44:  f2c0 0210   movt  r2, #16\n",
-  "  48:  4422        add r2, r4\n",
-  "  4a:  8812        ldrh  r2, [r2, #0]\n",
-  "  4c:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  50:  f2c0 0c10   movt  ip, #16\n",
-  "  54:  4464        add r4, ip\n",
-  "  56:  8824        ldrh  r4, [r4, #0]\n",
-  "  58:  e9d4 2303   ldrd  r2, r3, [r4, #12]\n",
-  "  5c:  e9d4 23ff   ldrd  r2, r3, [r4, #1020] ; 0x3fc\n",
-  "  60:  f504 6280   add.w r2, r4, #1024 ; 0x400\n",
-  "  64:  e9d2 2300   ldrd  r2, r3, [r2]\n",
-  "  68:  f504 2280   add.w r2, r4, #262144 ; 0x40000\n",
-  "  6c:  e9d2 2329   ldrd  r2, r3, [r2, #164]  ; 0xa4\n",
-  "  70:  f44f 6280   mov.w r2, #1024 ; 0x400\n",
-  "  74:  f2c0 0204   movt  r2, #4\n",
-  "  78:  4422        add r2, r4\n",
-  "  7a:  e9d2 2300   ldrd  r2, r3, [r2]\n",
-  "  7e:  f44f 6c80   mov.w ip, #1024 ; 0x400\n",
-  "  82:  f2c0 0c04   movt  ip, #4\n",
-  "  86:  4464        add r4, ip\n",
-  "  88:  e9d4 4500   ldrd  r4, r5, [r4]\n",
-  "  8c:  f8dc 000c   ldr.w r0, [ip, #12]\n",
-  "  90:  f5a4 1280   sub.w r2, r4, #1048576  ; 0x100000\n",
-  "  94:  f8d2 20a4   ldr.w r2, [r2, #164]  ; 0xa4\n",
-  "  98:  f994 200c   ldrsb.w r2, [r4, #12]\n",
-  "  9c:  7b22        ldrb  r2, [r4, #12]\n",
-  "  9e:  f9b4 200c   ldrsh.w r2, [r4, #12]\n",
-  nullptr
-};
-const char* const VixlStoreToOffsetResults[] = {
-  "   0:  60e2        str r2, [r4, #12]\n",
-  "   2:  f8c4 2fff   str.w r2, [r4, #4095] ; 0xfff\n",
-  "   6:  f504 5c80   add.w ip, r4, #4096 ; 0x1000\n",
-  "   a:  f8cc 2000   str.w r2, [ip]\n",
-  "   e:  f504 1c80   add.w ip, r4, #1048576  ; 0x100000\n",
-  "  12:  f8cc 20a4   str.w r2, [ip, #164]  ; 0xa4\n",
-  "  16:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  1a:  f2c0 0c10   movt  ip, #16\n",
-  "  1e:  44a4        add ip, r4\n",
-  "  20:  f8cc 2000   str.w r2, [ip]\n",
-  "  24:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  28:  f2c0 0c10   movt  ip, #16\n",
-  "  2c:  44a4        add ip, r4\n",
-  "  2e:  f8cc 4000   str.w r4, [ip]\n",
-  "  32:  81a2        strh  r2, [r4, #12]\n",
-  "  34:  f8a4 2fff   strh.w  r2, [r4, #4095] ; 0xfff\n",
-  "  38:  f504 5c80   add.w ip, r4, #4096 ; 0x1000\n",
-  "  3c:  f8ac 2000   strh.w  r2, [ip]\n",
-  "  40:  f504 1c80   add.w ip, r4, #1048576  ; 0x100000\n",
-  "  44:  f8ac 20a4   strh.w  r2, [ip, #164]  ; 0xa4\n",
-  "  48:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  4c:  f2c0 0c10   movt  ip, #16\n",
-  "  50:  44a4        add ip, r4\n",
-  "  52:  f8ac 2000   strh.w  r2, [ip]\n",
-  "  56:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  5a:  f2c0 0c10   movt  ip, #16\n",
-  "  5e:  44a4        add ip, r4\n",
-  "  60:  f8ac 4000   strh.w  r4, [ip]\n",
-  "  64:  e9c4 2303   strd  r2, r3, [r4, #12]\n",
-  "  68:  e9c4 23ff   strd  r2, r3, [r4, #1020] ; 0x3fc\n",
-  "  6c:  f504 6c80   add.w ip, r4, #1024 ; 0x400\n",
-  "  70:  e9cc 2300   strd  r2, r3, [ip]\n",
-  "  74:  f504 2c80   add.w ip, r4, #262144 ; 0x40000\n",
-  "  78:  e9cc 2329   strd  r2, r3, [ip, #164]  ; 0xa4\n",
-  "  7c:  f44f 6c80   mov.w ip, #1024 ; 0x400\n",
-  "  80:  f2c0 0c04   movt  ip, #4\n",
-  "  84:  44a4        add ip, r4\n",
-  "  86:  e9cc 2300   strd  r2, r3, [ip]\n",
-  "  8a:  f44f 6c80   mov.w ip, #1024 ; 0x400\n",
-  "  8e:  f2c0 0c04   movt  ip, #4\n",
-  "  92:  44a4        add ip, r4\n",
-  "  94:  e9cc 4500   strd  r4, r5, [ip]\n",
-  "  98:  f8cc 000c   str.w r0, [ip, #12]\n",
-  "  9c:  f5a4 1c80   sub.w ip, r4, #1048576  ; 0x100000\n",
-  "  a0:  f8cc 20a4   str.w r2, [ip, #164]  ; 0xa4\n",
-  "  a4:  7322        strb  r2, [r4, #12]\n",
-  nullptr
+const char* const VixlLoadFromOffsetResults = {
+  "       0: e2 68         ldr r2, [r4, #12]\n"
+  "       2: d4 f8 ff 2f   ldr.w r2, [r4, #4095]\n"
+  "       6: 04 f5 80 52   add.w r2, r4, #4096\n"
+  "       a: 12 68         ldr r2, [r2]\n"
+  "       c: 04 f5 80 12   add.w r2, r4, #1048576\n"
+  "      10: d2 f8 a4 20   ldr.w r2, [r2, #164]\n"
+  "      14: 4f f4 80 52   mov.w r2, #4096\n"
+  "      18: c0 f2 10 02   movt r2, #16\n"
+  "      1c: 22 44         add r2, r4\n"
+  "      1e: 12 68         ldr r2, [r2]\n"
+  "      20: 4f f4 80 5c   mov.w r12, #4096\n"
+  "      24: c0 f2 10 0c   movt r12, #16\n"
+  "      28: 64 44         add r4, r12\n"
+  "      2a: 24 68         ldr r4, [r4]\n"
+  "      2c: a2 89         ldrh r2, [r4, #12]\n"
+  "      2e: b4 f8 ff 2f   ldrh.w r2, [r4, #4095]\n"
+  "      32: 04 f5 80 52   add.w r2, r4, #4096\n"
+  "      36: 12 88         ldrh r2, [r2]\n"
+  "      38: 04 f5 80 12   add.w r2, r4, #1048576\n"
+  "      3c: b2 f8 a4 20   ldrh.w r2, [r2, #164]\n"
+  "      40: 4f f4 80 52   mov.w r2, #4096\n"
+  "      44: c0 f2 10 02   movt r2, #16\n"
+  "      48: 22 44         add r2, r4\n"
+  "      4a: 12 88         ldrh r2, [r2]\n"
+  "      4c: 4f f4 80 5c   mov.w r12, #4096\n"
+  "      50: c0 f2 10 0c   movt r12, #16\n"
+  "      54: 64 44         add r4, r12\n"
+  "      56: 24 88         ldrh r4, [r4]\n"
+  "      58: d4 e9 03 23   ldrd r2, r3, [r4, #12]\n"
+  "      5c: d4 e9 ff 23   ldrd r2, r3, [r4, #1020]\n"
+  "      60: 04 f5 80 62   add.w r2, r4, #1024\n"
+  "      64: d2 e9 00 23   ldrd r2, r3, [r2]\n"
+  "      68: 04 f5 80 22   add.w r2, r4, #262144\n"
+  "      6c: d2 e9 29 23   ldrd r2, r3, [r2, #164]\n"
+  "      70: 4f f4 80 62   mov.w r2, #1024\n"
+  "      74: c0 f2 04 02   movt r2, #4\n"
+  "      78: 22 44         add r2, r4\n"
+  "      7a: d2 e9 00 23   ldrd r2, r3, [r2]\n"
+  "      7e: 4f f4 80 6c   mov.w r12, #1024\n"
+  "      82: c0 f2 04 0c   movt r12, #4\n"
+  "      86: 64 44         add r4, r12\n"
+  "      88: d4 e9 00 45   ldrd r4, r5, [r4]\n"
+  "      8c: dc f8 0c 00   ldr.w r0, [r12, #12]\n"
+  "      90: a4 f5 80 12   sub.w r2, r4, #1048576\n"
+  "      94: d2 f8 a4 20   ldr.w r2, [r2, #164]\n"
+  "      98: 94 f9 0c 20   ldrsb.w r2, [r4, #12]\n"
+  "      9c: 22 7b         ldrb r2, [r4, #12]\n"
+  "      9e: b4 f9 0c 20   ldrsh.w r2, [r4, #12]\n"
 };
 
-std::map<std::string, const char* const*> test_results;
-void setup_results() {
-    test_results["VixlJniHelpers"] = VixlJniHelpersResults;
-    test_results["VixlStoreToOffset"] = VixlStoreToOffsetResults;
-    test_results["VixlLoadFromOffset"] = VixlLoadFromOffsetResults;
-}
+const char* const VixlStoreToOffsetResults = {
+  "       0: e2 60         str r2, [r4, #12]\n"
+  "       2: c4 f8 ff 2f   str.w r2, [r4, #4095]\n"
+  "       6: 04 f5 80 5c   add.w r12, r4, #4096\n"
+  "       a: cc f8 00 20   str.w r2, [r12]\n"
+  "       e: 04 f5 80 1c   add.w r12, r4, #1048576\n"
+  "      12: cc f8 a4 20   str.w r2, [r12, #164]\n"
+  "      16: 4f f4 80 5c   mov.w r12, #4096\n"
+  "      1a: c0 f2 10 0c   movt r12, #16\n"
+  "      1e: a4 44         add r12, r4\n"
+  "      20: cc f8 00 20   str.w r2, [r12]\n"
+  "      24: 4f f4 80 5c   mov.w r12, #4096\n"
+  "      28: c0 f2 10 0c   movt r12, #16\n"
+  "      2c: a4 44         add r12, r4\n"
+  "      2e: cc f8 00 40   str.w r4, [r12]\n"
+  "      32: a2 81         strh r2, [r4, #12]\n"
+  "      34: a4 f8 ff 2f   strh.w r2, [r4, #4095]\n"
+  "      38: 04 f5 80 5c   add.w r12, r4, #4096\n"
+  "      3c: ac f8 00 20   strh.w r2, [r12]\n"
+  "      40: 04 f5 80 1c   add.w r12, r4, #1048576\n"
+  "      44: ac f8 a4 20   strh.w r2, [r12, #164]\n"
+  "      48: 4f f4 80 5c   mov.w r12, #4096\n"
+  "      4c: c0 f2 10 0c   movt r12, #16\n"
+  "      50: a4 44         add r12, r4\n"
+  "      52: ac f8 00 20   strh.w r2, [r12]\n"
+  "      56: 4f f4 80 5c   mov.w r12, #4096\n"
+  "      5a: c0 f2 10 0c   movt r12, #16\n"
+  "      5e: a4 44         add r12, r4\n"
+  "      60: ac f8 00 40   strh.w r4, [r12]\n"
+  "      64: c4 e9 03 23   strd r2, r3, [r4, #12]\n"
+  "      68: c4 e9 ff 23   strd r2, r3, [r4, #1020]\n"
+  "      6c: 04 f5 80 6c   add.w r12, r4, #1024\n"
+  "      70: cc e9 00 23   strd r2, r3, [r12]\n"
+  "      74: 04 f5 80 2c   add.w r12, r4, #262144\n"
+  "      78: cc e9 29 23   strd r2, r3, [r12, #164]\n"
+  "      7c: 4f f4 80 6c   mov.w r12, #1024\n"
+  "      80: c0 f2 04 0c   movt r12, #4\n"
+  "      84: a4 44         add r12, r4\n"
+  "      86: cc e9 00 23   strd r2, r3, [r12]\n"
+  "      8a: 4f f4 80 6c   mov.w r12, #1024\n"
+  "      8e: c0 f2 04 0c   movt r12, #4\n"
+  "      92: a4 44         add r12, r4\n"
+  "      94: cc e9 00 45   strd r4, r5, [r12]\n"
+  "      98: cc f8 0c 00   str.w r0, [r12, #12]\n"
+  "      9c: a4 f5 80 1c   sub.w r12, r4, #1048576\n"
+  "      a0: cc f8 a4 20   str.w r2, [r12, #164]\n"
+  "      a4: 22 73         strb r2, [r4, #12]\n"
+};
diff --git a/compiler/utils/jni_macro_assembler.h b/compiler/utils/jni_macro_assembler.h
index bbe0f73..d621122 100644
--- a/compiler/utils/jni_macro_assembler.h
+++ b/compiler/utils/jni_macro_assembler.h
@@ -43,6 +43,40 @@
   kNotZero
 };
 
+class ArgumentLocation {
+ public:
+  ArgumentLocation(ManagedRegister reg, size_t size)
+      : reg_(reg), frame_offset_(0u), size_(size) {
+    DCHECK(reg.IsRegister());
+  }
+
+  ArgumentLocation(FrameOffset frame_offset, size_t size)
+      : reg_(ManagedRegister::NoRegister()), frame_offset_(frame_offset), size_(size) {}
+
+  bool IsRegister() const {
+    return reg_.IsRegister();
+  }
+
+  ManagedRegister GetRegister() const {
+    DCHECK(IsRegister());
+    return reg_;
+  }
+
+  FrameOffset GetFrameOffset() const {
+    DCHECK(!IsRegister());
+    return frame_offset_;
+  }
+
+  size_t GetSize() const {
+    return size_;
+  }
+
+ private:
+  ManagedRegister reg_;
+  FrameOffset frame_offset_;
+  size_t size_;
+};
+
 template <PointerSize kPointerSize>
 class JNIMacroAssembler : public DeletableArenaObject<kArenaAllocAssembler> {
  public:
@@ -63,8 +97,7 @@
   // Emit code that will create an activation on the stack
   virtual void BuildFrame(size_t frame_size,
                           ManagedRegister method_reg,
-                          ArrayRef<const ManagedRegister> callee_save_regs,
-                          const ManagedRegisterEntrySpills& entry_spills) = 0;
+                          ArrayRef<const ManagedRegister> callee_save_regs) = 0;
 
   // Emit code that will remove an activation from the stack
   //
@@ -83,18 +116,16 @@
   virtual void StoreRef(FrameOffset dest, ManagedRegister src) = 0;
   virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src) = 0;
 
-  virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) = 0;
+  virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm) = 0;
 
   virtual void StoreStackOffsetToThread(ThreadOffset<kPointerSize> thr_offs,
-                                        FrameOffset fr_offs,
-                                        ManagedRegister scratch) = 0;
+                                        FrameOffset fr_offs) = 0;
 
   virtual void StoreStackPointerToThread(ThreadOffset<kPointerSize> thr_offs) = 0;
 
   virtual void StoreSpanning(FrameOffset dest,
                              ManagedRegister src,
-                             FrameOffset in_off,
-                             ManagedRegister scratch) = 0;
+                             FrameOffset in_off) = 0;
 
   // Load routines
   virtual void Load(ManagedRegister dest, FrameOffset src, size_t size) = 0;
@@ -115,19 +146,23 @@
   virtual void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset<kPointerSize> offs) = 0;
 
   // Copying routines
+  virtual void MoveArguments(ArrayRef<ArgumentLocation> dests, ArrayRef<ArgumentLocation> srcs) = 0;
+
   virtual void Move(ManagedRegister dest, ManagedRegister src, size_t size) = 0;
 
-  virtual void CopyRawPtrFromThread(FrameOffset fr_offs,
-                                    ThreadOffset<kPointerSize> thr_offs,
-                                    ManagedRegister scratch) = 0;
+  virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset<kPointerSize> thr_offs) = 0;
 
   virtual void CopyRawPtrToThread(ThreadOffset<kPointerSize> thr_offs,
                                   FrameOffset fr_offs,
                                   ManagedRegister scratch) = 0;
 
-  virtual void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) = 0;
+  virtual void CopyRef(FrameOffset dest, FrameOffset src) = 0;
+  virtual void CopyRef(FrameOffset dest,
+                       ManagedRegister base,
+                       MemberOffset offs,
+                       bool unpoison_reference) = 0;
 
-  virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) = 0;
+  virtual void Copy(FrameOffset dest, FrameOffset src, size_t size) = 0;
 
   virtual void Copy(FrameOffset dest,
                     ManagedRegister src_base,
@@ -170,27 +205,23 @@
   virtual void ZeroExtend(ManagedRegister mreg, size_t size) = 0;
 
   // Exploit fast access in managed code to Thread::Current()
-  virtual void GetCurrentThread(ManagedRegister tr) = 0;
-  virtual void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) = 0;
+  virtual void GetCurrentThread(ManagedRegister dest) = 0;
+  virtual void GetCurrentThread(FrameOffset dest_offset) = 0;
 
-  // Set up out_reg to hold a Object** into the handle scope, or to be null if the
-  // value is null and null_allowed. in_reg holds a possibly stale reference
-  // that can be used to avoid loading the handle scope entry to see if the value is
-  // null.
-  virtual void CreateHandleScopeEntry(ManagedRegister out_reg,
-                                      FrameOffset handlescope_offset,
-                                      ManagedRegister in_reg,
-                                      bool null_allowed) = 0;
+  // Set up `out_reg` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
+  // or to be null if the value is null and `null_allowed`. `in_reg` holds a possibly
+  // stale reference that can be used to avoid loading the spilled value to
+  // see if the value is null.
+  virtual void CreateJObject(ManagedRegister out_reg,
+                             FrameOffset spilled_reference_offset,
+                             ManagedRegister in_reg,
+                             bool null_allowed) = 0;
 
-  // Set up out_off to hold a Object** into the handle scope, or to be null if the
-  // value is null and null_allowed.
-  virtual void CreateHandleScopeEntry(FrameOffset out_off,
-                                      FrameOffset handlescope_offset,
-                                      ManagedRegister scratch,
-                                      bool null_allowed) = 0;
-
-  // src holds a handle scope entry (Object**) load this into dst
-  virtual void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) = 0;
+  // Set up `out_off` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
+  // or to be null if the value is null and `null_allowed`.
+  virtual void CreateJObject(FrameOffset out_off,
+                             FrameOffset spilled_reference_offset,
+                             bool null_allowed) = 0;
 
   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
   // know that src may not be null.
@@ -198,23 +229,23 @@
   virtual void VerifyObject(FrameOffset src, bool could_be_null) = 0;
 
   // Jump to address held at [base+offset] (used for tail calls).
-  virtual void Jump(ManagedRegister base, Offset offset, ManagedRegister scratch) = 0;
+  virtual void Jump(ManagedRegister base, Offset offset) = 0;
 
   // Call to address held at [base+offset]
-  virtual void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) = 0;
-  virtual void Call(FrameOffset base, Offset offset, ManagedRegister scratch) = 0;
-  virtual void CallFromThread(ThreadOffset<kPointerSize> offset, ManagedRegister scratch) = 0;
+  virtual void Call(ManagedRegister base, Offset offset) = 0;
+  virtual void Call(FrameOffset base, Offset offset) = 0;
+  virtual void CallFromThread(ThreadOffset<kPointerSize> offset) = 0;
 
   // Generate code to check if Thread::Current()->exception_ is non-null
   // and branch to a ExceptionSlowPath if it is.
-  virtual void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) = 0;
+  virtual void ExceptionPoll(size_t stack_adjust) = 0;
 
   // Create a new label that can be used with Jump/Bind calls.
   virtual std::unique_ptr<JNIMacroLabel> CreateLabel() = 0;
   // Emit an unconditional jump to the label.
   virtual void Jump(JNIMacroLabel* label) = 0;
-  // Emit a conditional jump to the label by applying a unary condition test to the register.
-  virtual void Jump(JNIMacroLabel* label, JNIMacroUnaryCondition cond, ManagedRegister test) = 0;
+  // Emit a conditional jump to the label by applying a unary condition test to the GC marking flag.
+  virtual void TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) = 0;
   // Code at this offset will serve as the target for the Jump call.
   virtual void Bind(JNIMacroLabel* label) = 0;
 
diff --git a/compiler/utils/jni_macro_assembler_test.h b/compiler/utils/jni_macro_assembler_test.h
index 067a595..e77177e 100644
--- a/compiler/utils/jni_macro_assembler_test.h
+++ b/compiler/utils/jni_macro_assembler_test.h
@@ -33,7 +33,7 @@
 namespace art {
 
 template<typename Ass>
-class JNIMacroAssemblerTest : public testing::Test {
+class JNIMacroAssemblerTest : public AssemblerTestBase {
  public:
   Ass* GetAssembler() {
     return assembler_.get();
@@ -50,32 +50,18 @@
     DriverWrapper(assembly_string, test_name);
   }
 
-  // This is intended to be run as a test.
-  bool CheckTools() {
-    return test_helper_->CheckTools();
-  }
-
  protected:
   JNIMacroAssemblerTest() {}
 
   void SetUp() override {
+    AssemblerTestBase::SetUp();
     allocator_.reset(new ArenaAllocator(&pool_));
     assembler_.reset(CreateAssembler(allocator_.get()));
-    test_helper_.reset(
-        new AssemblerTestInfrastructure(GetArchitectureString(),
-                                        GetAssemblerCmdName(),
-                                        GetAssemblerParameters(),
-                                        GetObjdumpCmdName(),
-                                        GetObjdumpParameters(),
-                                        GetDisassembleCmdName(),
-                                        GetDisassembleParameters(),
-                                        GetAssemblyHeader()));
-
     SetUpHelpers();
   }
 
   void TearDown() override {
-    test_helper_.reset();  // Clean up the helper.
+    AssemblerTestBase::TearDown();
     assembler_.reset();
     allocator_.reset();
   }
@@ -88,43 +74,6 @@
   // Override this to set up any architecture-specific things, e.g., register vectors.
   virtual void SetUpHelpers() {}
 
-  // Get the typically used name for this architecture, e.g., aarch64, x86_64, ...
-  virtual std::string GetArchitectureString() = 0;
-
-  // Get the name of the assembler, e.g., "as" by default.
-  virtual std::string GetAssemblerCmdName() {
-    return "as";
-  }
-
-  // Switches to the assembler command. Default none.
-  virtual std::string GetAssemblerParameters() {
-    return "";
-  }
-
-  // Get the name of the objdump, e.g., "objdump" by default.
-  virtual std::string GetObjdumpCmdName() {
-    return "objdump";
-  }
-
-  // Switches to the objdump command. Default is " -h".
-  virtual std::string GetObjdumpParameters() {
-    return " -h";
-  }
-
-  // Get the name of the objdump, e.g., "objdump" by default.
-  virtual std::string GetDisassembleCmdName() {
-    return "objdump";
-  }
-
-  // Switches to the objdump command. As it's a binary, one needs to push the architecture and
-  // such to objdump, so it's architecture-specific and there is no default.
-  virtual std::string GetDisassembleParameters() = 0;
-
-  // If the assembly file needs a header, return it in a sub-class.
-  virtual const char* GetAssemblyHeader() {
-    return nullptr;
-  }
-
  private:
   // Override this to pad the code with NOPs to a certain size if needed.
   virtual void Pad(std::vector<uint8_t>& data ATTRIBUTE_UNUSED) {
@@ -137,13 +86,12 @@
     MemoryRegion code(&(*data)[0], data->size());
     assembler_->FinalizeInstructions(code);
     Pad(*data);
-    test_helper_->Driver(*data, assembly_text, test_name);
+    Driver(*data, assembly_text, test_name);
   }
 
   MallocArenaPool pool_;
   std::unique_ptr<ArenaAllocator> allocator_;
   std::unique_ptr<Ass> assembler_;
-  std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
 
   DISALLOW_COPY_AND_ASSIGN(JNIMacroAssemblerTest);
 };
diff --git a/compiler/utils/managed_register.h b/compiler/utils/managed_register.h
index f20750b..2afdc04 100644
--- a/compiler/utils/managed_register.h
+++ b/compiler/utils/managed_register.h
@@ -84,52 +84,6 @@
 static_assert(std::is_trivially_copyable<ManagedRegister>::value,
               "ManagedRegister should be trivially copyable");
 
-class ManagedRegisterSpill : public ManagedRegister {
- public:
-  // ManagedRegisterSpill contains information about data type size and location in caller frame
-  // These additional attributes could be defined by calling convention (EntrySpills)
-  ManagedRegisterSpill(const ManagedRegister& other, uint32_t size, uint32_t spill_offset)
-      : ManagedRegister(other), size_(size), spill_offset_(spill_offset)  { }
-
-  explicit ManagedRegisterSpill(const ManagedRegister& other)
-      : ManagedRegister(other), size_(-1), spill_offset_(-1) { }
-
-  ManagedRegisterSpill(const ManagedRegister& other, int32_t size)
-      : ManagedRegister(other), size_(size), spill_offset_(-1) { }
-
-  int32_t getSpillOffset() const {
-    return spill_offset_;
-  }
-
-  int32_t getSize() const {
-    return size_;
-  }
-
- private:
-  int32_t size_;
-  int32_t spill_offset_;
-};
-
-class ManagedRegisterEntrySpills : public std::vector<ManagedRegisterSpill> {
- public:
-  // The ManagedRegister does not have information about size and offset.
-  // In this case it's size and offset determined by BuildFrame (assembler)
-  void push_back(ManagedRegister x) {
-    ManagedRegisterSpill spill(x);
-    std::vector<ManagedRegisterSpill>::push_back(spill);
-  }
-
-  void push_back(ManagedRegister x, int32_t size) {
-    ManagedRegisterSpill spill(x, size);
-    std::vector<ManagedRegisterSpill>::push_back(spill);
-  }
-
-  void push_back(ManagedRegisterSpill x) {
-    std::vector<ManagedRegisterSpill>::push_back(x);
-  }
- private:
-};
-
 }  // namespace art
 
 #endif  // ART_COMPILER_UTILS_MANAGED_REGISTER_H_
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index 55f7691..adc7bcc 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -2887,6 +2887,27 @@
 }
 
 
+void X86Assembler::xchgb(Register reg, const Address& address) {
+  // For testing purpose
+  xchgb(static_cast<ByteRegister>(reg), address);
+}
+
+
+void X86Assembler::xchgb(ByteRegister reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x86);
+  EmitOperand(reg, address);
+}
+
+
+void X86Assembler::xchgw(Register reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0x87);
+  EmitOperand(reg, address);
+}
+
+
 void X86Assembler::xchgl(Register dst, Register src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x87);
@@ -3039,6 +3060,14 @@
 }
 
 
+void X86Assembler::andw(const Address& address, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  CHECK(imm.is_uint16() || imm.is_int16()) << imm.value();
+  EmitOperandSizeOverride();
+  EmitComplex(4, address, imm, /* is_16_op= */ true);
+}
+
+
 void X86Assembler::orl(Register dst, Register src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x0B);
@@ -3166,6 +3195,13 @@
 }
 
 
+void X86Assembler::divl(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF7);
+  EmitUint8(0xF0 | reg);
+}
+
+
 void X86Assembler::imull(Register dst, Register src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x0F);
@@ -3587,7 +3623,7 @@
 
 void X86Assembler::repe_cmpsb() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
-  EmitUint8(0xF2);
+  EmitUint8(0xF3);
   EmitUint8(0xA6);
 }
 
@@ -3629,6 +3665,23 @@
 }
 
 
+void X86Assembler::cmpxchgb(const Address& address, ByteRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xB0);
+  EmitOperand(reg, address);
+}
+
+
+void X86Assembler::cmpxchgw(const Address& address, Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0x0F);
+  EmitUint8(0xB1);
+  EmitOperand(reg, address);
+}
+
+
 void X86Assembler::cmpxchgl(const Address& address, Register reg) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x0F);
@@ -3645,6 +3698,29 @@
 }
 
 
+void X86Assembler::xaddb(const Address& address, ByteRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xC0);
+  EmitOperand(reg, address);
+}
+
+void X86Assembler::xaddw(const Address& address, Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0x0F);
+  EmitUint8(0xC1);
+  EmitOperand(reg, address);
+}
+
+void X86Assembler::xaddl(const Address& address, Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xC1);
+  EmitOperand(reg, address);
+}
+
+
 void X86Assembler::mfence() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x0F);
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 27fde26..a9050e6 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -73,6 +73,10 @@
     return static_cast<Register>(encoding_at(1) & 7);
   }
 
+  int32_t disp() const {
+    return disp_;
+  }
+
   int8_t disp8() const {
     CHECK_GE(length_, 2);
     return static_cast<int8_t>(encoding_[length_ - 1]);
@@ -92,7 +96,7 @@
 
  protected:
   // Operand can be sub classed (e.g: Address).
-  Operand() : length_(0), fixup_(nullptr) { }
+  Operand() : length_(0), disp_(0), fixup_(nullptr) { }
 
   void SetModRM(int mod_in, Register rm_in) {
     CHECK_EQ(mod_in & ~3, 0);
@@ -110,6 +114,7 @@
   void SetDisp8(int8_t disp) {
     CHECK(length_ == 1 || length_ == 2);
     encoding_[length_++] = static_cast<uint8_t>(disp);
+    disp_ = disp;
   }
 
   void SetDisp32(int32_t disp) {
@@ -117,6 +122,7 @@
     int disp_size = sizeof(disp);
     memmove(&encoding_[length_], &disp, disp_size);
     length_ += disp_size;
+    disp_ = disp;
   }
 
   AssemblerFixup* GetFixup() const {
@@ -130,12 +136,13 @@
  private:
   uint8_t length_;
   uint8_t encoding_[6];
+  int32_t disp_;
 
   // A fixup can be associated with the operand, in order to be applied after the
   // code has been generated. This is used for constant area fixups.
   AssemblerFixup* fixup_;
 
-  explicit Operand(Register reg) : fixup_(nullptr) { SetModRM(3, reg); }
+  explicit Operand(Register reg) : disp_(0), fixup_(nullptr) { SetModRM(3, reg); }
 
   // Get the operand encoding byte at the given index.
   uint8_t encoding_at(int index_in) const {
@@ -191,6 +198,23 @@
     SetFixup(fixup);
   }
 
+  Address displaceBy(int offset) {
+    if (rm() == ESP) {
+      // SIB addressing mode
+      return Address(base(), index(), scale(), disp() + offset, GetFixup());
+    } else {
+      return Address(rm(), disp() + offset, GetFixup());
+    }
+  }
+
+  Register GetBaseRegister() {
+    if (rm() == ESP) {
+      return base();
+    } else {
+      return rm();
+    }
+  }
+
   static Address Absolute(uintptr_t addr) {
     Address result;
     result.SetModRM(0, EBP);
@@ -671,6 +695,10 @@
   void fptan();
   void fprem();
 
+  void xchgb(ByteRegister reg, const Address& address);
+  void xchgb(Register reg, const Address& address);
+  void xchgw(Register reg, const Address& address);
+
   void xchgl(Register dst, Register src);
   void xchgl(Register reg, const Address& address);
 
@@ -694,6 +722,7 @@
   void andl(Register dst, const Immediate& imm);
   void andl(Register dst, Register src);
   void andl(Register dst, const Address& address);
+  void andw(const Address& address, const Immediate& imm);
 
   void orl(Register dst, const Immediate& imm);
   void orl(Register dst, Register src);
@@ -723,6 +752,7 @@
   void cdq();
 
   void idivl(Register reg);
+  void divl(Register reg);
 
   void imull(Register dst, Register src);
   void imull(Register reg, const Immediate& imm);
@@ -794,9 +824,15 @@
   void rep_movsw();
 
   X86Assembler* lock();
+  void cmpxchgb(const Address& address, ByteRegister reg);
+  void cmpxchgw(const Address& address, Register reg);
   void cmpxchgl(const Address& address, Register reg);
   void cmpxchg8b(const Address& address);
 
+  void xaddb(const Address& address, ByteRegister reg);
+  void xaddw(const Address& address, Register reg);
+  void xaddl(const Address& address, Register reg);
+
   void mfence();
 
   X86Assembler* fs();
@@ -811,6 +847,26 @@
   void LoadLongConstant(XmmRegister dst, int64_t value);
   void LoadDoubleConstant(XmmRegister dst, double value);
 
+  void LockCmpxchgb(const Address& address, Register reg) {
+    // For testing purpose
+    lock()->cmpxchgb(address, static_cast<ByteRegister>(reg));
+  }
+
+  void LockCmpxchgb(const Address& address, ByteRegister reg) {
+    lock()->cmpxchgb(address, reg);
+  }
+
+  void LockCmpxchgw(const Address& address, Register reg) {
+    AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+    // We make sure that the operand size override bytecode is emited before the lock bytecode.
+    // We test against clang which enforces this bytecode order.
+    EmitOperandSizeOverride();
+    EmitUint8(0xF0);
+    EmitUint8(0x0F);
+    EmitUint8(0xB1);
+    EmitOperand(reg, address);
+  }
+
   void LockCmpxchgl(const Address& address, Register reg) {
     lock()->cmpxchgl(address, reg);
   }
@@ -819,6 +875,30 @@
     lock()->cmpxchg8b(address);
   }
 
+  void LockXaddb(const Address& address, Register reg) {
+    // For testing purpose
+    lock()->xaddb(address, static_cast<ByteRegister>(reg));
+  }
+
+  void LockXaddb(const Address& address, ByteRegister reg) {
+    lock()->xaddb(address, reg);
+  }
+
+  void LockXaddw(const Address& address, Register reg) {
+    AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+    // We make sure that the operand size override bytecode is emited before the lock bytecode.
+    // We test against clang which enforces this bytecode order.
+    EmitOperandSizeOverride();
+    EmitUint8(0xF0);
+    EmitUint8(0x0F);
+    EmitUint8(0xC1);
+    EmitOperand(reg, address);
+  }
+
+  void LockXaddl(const Address& address, Register reg) {
+    lock()->xaddl(address, reg);
+  }
+
   //
   // Misc. functionality
   //
diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc
index 9253730..32d138f 100644
--- a/compiler/utils/x86/assembler_x86_test.cc
+++ b/compiler/utils/x86/assembler_x86_test.cc
@@ -34,6 +34,12 @@
   ASSERT_EQ(static_cast<size_t>(5), buffer.Size());
 }
 
+struct X86RegisterCompare {
+    bool operator()(const x86::Register& a, const x86::Register& b) const {
+        return static_cast<int32_t>(a) < static_cast<int32_t>(b);
+    }
+};
+
 //
 // Test fixture.
 //
@@ -51,16 +57,8 @@
                              x86::Immediate>;
 
  protected:
-  std::string GetArchitectureString() override {
-    return "x86";
-  }
-
-  std::string GetAssemblerParameters() override {
-    return " --32";
-  }
-
-  std::string GetDisassembleParameters() override {
-    return " -D -bbinary -mi386 --no-show-raw-insn";
+  InstructionSet GetIsa() override {
+    return InstructionSet::kX86;
   }
 
   void SetUpHelpers() override {
@@ -89,6 +87,7 @@
       addresses_.push_back(x86::Address(x86::ESP, 1));
       addresses_.push_back(x86::Address(x86::ESP, 987654321));
     }
+
     if (registers_.size() == 0) {
       registers_.insert(end(registers_),
                         {
@@ -101,6 +100,25 @@
                           new x86::Register(x86::ESI),
                           new x86::Register(x86::EDI)
                         });
+
+      secondary_register_names_.emplace(x86::Register(x86::EAX), "ax");
+      secondary_register_names_.emplace(x86::Register(x86::EBX), "bx");
+      secondary_register_names_.emplace(x86::Register(x86::ECX), "cx");
+      secondary_register_names_.emplace(x86::Register(x86::EDX), "dx");
+      secondary_register_names_.emplace(x86::Register(x86::EBP), "bp");
+      secondary_register_names_.emplace(x86::Register(x86::ESP), "sp");
+      secondary_register_names_.emplace(x86::Register(x86::ESI), "si");
+      secondary_register_names_.emplace(x86::Register(x86::EDI), "di");
+
+      tertiary_register_names_.emplace(x86::Register(x86::EAX), "al");
+      tertiary_register_names_.emplace(x86::Register(x86::EBX), "bl");
+      tertiary_register_names_.emplace(x86::Register(x86::ECX), "cl");
+      tertiary_register_names_.emplace(x86::Register(x86::EDX), "dl");
+      // FIXME: Refactor RepeatAw() to only use the tertiary for EAX, EBX, ECX, EDX
+      tertiary_register_names_.emplace(x86::Register(x86::EBP), "ch");
+      tertiary_register_names_.emplace(x86::Register(x86::ESP), "ah");
+      tertiary_register_names_.emplace(x86::Register(x86::ESI), "dh");
+      tertiary_register_names_.emplace(x86::Register(x86::EDI), "bh");
     }
 
     if (fp_registers_.size() == 0) {
@@ -140,11 +158,23 @@
     return x86::Immediate(imm_value);
   }
 
+  std::string GetSecondaryRegisterName(const x86::Register& reg) override {
+    CHECK(secondary_register_names_.find(reg) != secondary_register_names_.end());
+    return secondary_register_names_[reg];
+  }
+
+  std::string GetTertiaryRegisterName(const x86::Register& reg) override {
+    CHECK(tertiary_register_names_.find(reg) != tertiary_register_names_.end());
+    return tertiary_register_names_[reg];
+  }
+
   std::vector<x86::Address> addresses_singleton_;
 
  private:
   std::vector<x86::Address> addresses_;
   std::vector<x86::Register*> registers_;
+  std::map<x86::Register, std::string, X86RegisterCompare> secondary_register_names_;
+  std::map<x86::Register, std::string, X86RegisterCompare> tertiary_register_names_;
   std::vector<x86::XmmRegister*> fp_registers_;
 };
 
@@ -275,6 +305,14 @@
   DriverStr(RepeatAI(&x86::X86Assembler::addw, /*imm_bytes*/ 2U, "addw ${imm}, {mem}"), "addw");
 }
 
+TEST_F(AssemblerX86Test, Andw) {
+  DriverStr(RepeatAI(&x86::X86Assembler::andw, /*imm_bytes*/ 2U, "andw ${imm}, {mem}"), "andw");
+}
+
+TEST_F(AssemblerX86Test, MovwStore) {
+  DriverStr(RepeatAr(&x86::X86Assembler::movw, "movw %{reg}, {mem}"), "movw-store");
+}
+
 TEST_F(AssemblerX86Test, MovlStore) {
   DriverStr(RepeatAR(&x86::X86Assembler::movl, "movl %{reg}, {mem}"), "movl-store");
 }
@@ -293,6 +331,31 @@
   DriverStr(expected, "LoadLongConstant");
 }
 
+TEST_F(AssemblerX86Test, Xchgb) {
+  DriverStr(RepeatwA(&x86::X86Assembler::xchgb,
+                     "xchgb {mem}, %{reg}"), "xchgb");
+}
+
+TEST_F(AssemblerX86Test, Xchgw) {
+  DriverStr(RepeatrA(&x86::X86Assembler::xchgw,
+                     "xchgw {mem}, %{reg}"), "xchgw");
+}
+
+TEST_F(AssemblerX86Test, Xchgl) {
+  DriverStr(RepeatRA(&x86::X86Assembler::xchgl,
+                     "xchgl {mem}, %{reg}"), "xchgl");
+}
+
+TEST_F(AssemblerX86Test, LockCmpxchgb) {
+  DriverStr(RepeatAw(&x86::X86Assembler::LockCmpxchgb,
+                     "lock cmpxchgb %{reg}, {mem}"), "lock_cmpxchgb");
+}
+
+TEST_F(AssemblerX86Test, LockCmpxchgw) {
+  DriverStr(RepeatAr(&x86::X86Assembler::LockCmpxchgw,
+                     "lock cmpxchgw %{reg}, {mem}"), "lock_cmpxchgw");
+}
+
 TEST_F(AssemblerX86Test, LockCmpxchgl) {
   DriverStr(RepeatAR(&x86::X86Assembler::LockCmpxchgl,
                      "lock cmpxchgl %{reg}, {mem}"), "lock_cmpxchgl");
@@ -303,6 +366,21 @@
                     "lock cmpxchg8b {mem}"), "lock_cmpxchg8b");
 }
 
+TEST_F(AssemblerX86Test, LockXaddb) {
+  DriverStr(RepeatAw(&x86::X86Assembler::LockXaddb,
+                     "lock xaddb %{reg}, {mem}"), "lock_xaddb");
+}
+
+TEST_F(AssemblerX86Test, LockXaddw) {
+  DriverStr(RepeatAr(&x86::X86Assembler::LockXaddw,
+                     "lock xaddw %{reg}, {mem}"), "lock_xaddw");
+}
+
+TEST_F(AssemblerX86Test, LockXaddl) {
+  DriverStr(RepeatAR(&x86::X86Assembler::LockXaddl,
+                     "lock xaddl %{reg}, {mem}"), "lock_xaddl");
+}
+
 TEST_F(AssemblerX86Test, FPUIntegerLoadS) {
   DriverStr(RepeatA(&x86::X86Assembler::filds, "fildl {mem}"), "fildd");
 }
@@ -1230,4 +1308,20 @@
   DriverStr(RepeatAI(&x86::X86Assembler::cmpw, /*imm_bytes*/ 2U, "cmpw ${imm}, {mem}"), "cmpw");
 }
 
+TEST_F(AssemblerX86Test, Idiv) {
+  DriverStr(RepeatR(&x86::X86Assembler::idivl, "idivl %{reg}"), "idivl");
+}
+
+TEST_F(AssemblerX86Test, Div) {
+  DriverStr(RepeatR(&x86::X86Assembler::divl, "divl %{reg}"), "divl");
+}
+
+TEST_F(AssemblerX86Test, Negl) {
+  DriverStr(RepeatR(&x86::X86Assembler::negl, "negl %{reg}"), "negl");
+}
+
+TEST_F(AssemblerX86Test, Notl) {
+  DriverStr(RepeatR(&x86::X86Assembler::notl, "notl %{reg}"), "notl");
+}
+
 }  // namespace art
diff --git a/compiler/utils/x86/jni_macro_assembler_x86.cc b/compiler/utils/x86/jni_macro_assembler_x86.cc
index f4ea004..2710eb1 100644
--- a/compiler/utils/x86/jni_macro_assembler_x86.cc
+++ b/compiler/utils/x86/jni_macro_assembler_x86.cc
@@ -24,6 +24,12 @@
 namespace art {
 namespace x86 {
 
+static Register GetScratchRegister() {
+  // ECX is an argument register on entry and gets spilled in BuildFrame().
+  // After that, we can use it as a scratch register.
+  return ECX;
+}
+
 // Slowpath entered when Thread::Current()->_exception is non-null
 class X86ExceptionSlowPath final : public SlowPath {
  public:
@@ -46,8 +52,7 @@
 
 void X86JNIMacroAssembler::BuildFrame(size_t frame_size,
                                       ManagedRegister method_reg,
-                                      ArrayRef<const ManagedRegister> spill_regs,
-                                      const ManagedRegisterEntrySpills& entry_spills) {
+                                      ArrayRef<const ManagedRegister> spill_regs) {
   DCHECK_EQ(CodeSize(), 0U);  // Nothing emitted yet.
   cfi().SetCurrentCFAOffset(4);  // Return address on stack.
   if (frame_size == kFramePointerSize) {
@@ -81,21 +86,6 @@
     cfi().AdjustCFAOffset(kFramePointerSize);
   }
   DCHECK_EQ(static_cast<size_t>(cfi().GetCurrentCFAOffset()), frame_size);
-
-  for (const ManagedRegisterSpill& spill : entry_spills) {
-    if (spill.AsX86().IsCpuRegister()) {
-      int offset = frame_size + spill.getSpillOffset();
-      __ movl(Address(ESP, offset), spill.AsX86().AsCpuRegister());
-    } else {
-      DCHECK(spill.AsX86().IsXmmRegister());
-      if (spill.getSize() == 8) {
-        __ movsd(Address(ESP, frame_size + spill.getSpillOffset()), spill.AsX86().AsXmmRegister());
-      } else {
-        CHECK_EQ(spill.getSize(), 4);
-        __ movss(Address(ESP, frame_size + spill.getSpillOffset()), spill.AsX86().AsXmmRegister());
-      }
-    }
-  }
 }
 
 void X86JNIMacroAssembler::RemoveFrame(size_t frame_size,
@@ -180,17 +170,14 @@
   __ movl(Address(ESP, dest), src.AsCpuRegister());
 }
 
-void X86JNIMacroAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister) {
+void X86JNIMacroAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm) {
   __ movl(Address(ESP, dest), Immediate(imm));
 }
 
-void X86JNIMacroAssembler::StoreStackOffsetToThread(ThreadOffset32 thr_offs,
-                                                    FrameOffset fr_offs,
-                                                    ManagedRegister mscratch) {
-  X86ManagedRegister scratch = mscratch.AsX86();
-  CHECK(scratch.IsCpuRegister());
-  __ leal(scratch.AsCpuRegister(), Address(ESP, fr_offs));
-  __ fs()->movl(Address::Absolute(thr_offs), scratch.AsCpuRegister());
+void X86JNIMacroAssembler::StoreStackOffsetToThread(ThreadOffset32 thr_offs, FrameOffset fr_offs) {
+  Register scratch = GetScratchRegister();
+  __ leal(scratch, Address(ESP, fr_offs));
+  __ fs()->movl(Address::Absolute(thr_offs), scratch);
 }
 
 void X86JNIMacroAssembler::StoreStackPointerToThread(ThreadOffset32 thr_offs) {
@@ -199,8 +186,7 @@
 
 void X86JNIMacroAssembler::StoreSpanning(FrameOffset /*dst*/,
                                          ManagedRegister /*src*/,
-                                         FrameOffset /*in_off*/,
-                                         ManagedRegister /*scratch*/) {
+                                         FrameOffset /*in_off*/) {
   UNIMPLEMENTED(FATAL);  // this case only currently exists for ARM
 }
 
@@ -314,7 +300,42 @@
   }
 }
 
+void X86JNIMacroAssembler::MoveArguments(ArrayRef<ArgumentLocation> dests,
+                                         ArrayRef<ArgumentLocation> srcs) {
+  DCHECK_EQ(dests.size(), srcs.size());
+  bool found_hidden_arg = false;
+  for (size_t i = 0, arg_count = srcs.size(); i != arg_count; ++i) {
+    const ArgumentLocation& src = srcs[i];
+    const ArgumentLocation& dest = dests[i];
+    DCHECK_EQ(src.GetSize(), dest.GetSize());
+    if (src.IsRegister()) {
+      if (UNLIKELY(dest.IsRegister())) {
+        // Native ABI has only stack arguments but we may pass one "hidden arg" in register.
+        CHECK(!found_hidden_arg);
+        found_hidden_arg = true;
+        DCHECK(
+            !dest.GetRegister().Equals(X86ManagedRegister::FromCpuRegister(GetScratchRegister())));
+        Move(dest.GetRegister(), src.GetRegister(), dest.GetSize());
+      } else {
+        Store(dest.GetFrameOffset(), src.GetRegister(), dest.GetSize());
+      }
+    } else {
+      // Delay copying until we have spilled all registers, including the scratch register ECX.
+    }
+  }
+  for (size_t i = 0, arg_count = srcs.size(); i != arg_count; ++i) {
+    const ArgumentLocation& src = srcs[i];
+    const ArgumentLocation& dest = dests[i];
+    DCHECK_EQ(src.GetSize(), dest.GetSize());
+    if (!src.IsRegister()) {
+      DCHECK(!dest.IsRegister());
+      Copy(dest.GetFrameOffset(), src.GetFrameOffset(), dest.GetSize());
+    }
+  }
+}
+
 void X86JNIMacroAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
+  DCHECK(!mdest.Equals(X86ManagedRegister::FromCpuRegister(GetScratchRegister())));
   X86ManagedRegister dest = mdest.AsX86();
   X86ManagedRegister src = msrc.AsX86();
   if (!dest.Equals(src)) {
@@ -340,20 +361,28 @@
   }
 }
 
-void X86JNIMacroAssembler::CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) {
-  X86ManagedRegister scratch = mscratch.AsX86();
-  CHECK(scratch.IsCpuRegister());
-  __ movl(scratch.AsCpuRegister(), Address(ESP, src));
-  __ movl(Address(ESP, dest), scratch.AsCpuRegister());
+void X86JNIMacroAssembler::CopyRef(FrameOffset dest, FrameOffset src) {
+  Register scratch = GetScratchRegister();
+  __ movl(scratch, Address(ESP, src));
+  __ movl(Address(ESP, dest), scratch);
 }
 
-void X86JNIMacroAssembler::CopyRawPtrFromThread(FrameOffset fr_offs,
-                                                ThreadOffset32 thr_offs,
-                                                ManagedRegister mscratch) {
-  X86ManagedRegister scratch = mscratch.AsX86();
-  CHECK(scratch.IsCpuRegister());
-  __ fs()->movl(scratch.AsCpuRegister(), Address::Absolute(thr_offs));
-  Store(fr_offs, scratch, 4);
+void X86JNIMacroAssembler::CopyRef(FrameOffset dest,
+                                   ManagedRegister base,
+                                   MemberOffset offs,
+                                   bool unpoison_reference) {
+  Register scratch = GetScratchRegister();
+  __ movl(scratch, Address(base.AsX86().AsCpuRegister(), offs));
+  if (unpoison_reference) {
+    __ MaybeUnpoisonHeapReference(scratch);
+  }
+  __ movl(Address(ESP, dest), scratch);
+}
+
+void X86JNIMacroAssembler::CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset32 thr_offs) {
+  Register scratch = GetScratchRegister();
+  __ fs()->movl(scratch, Address::Absolute(thr_offs));
+  __ movl(Address(ESP, fr_offs), scratch);
 }
 
 void X86JNIMacroAssembler::CopyRawPtrToThread(ThreadOffset32 thr_offs,
@@ -365,18 +394,14 @@
   __ fs()->movl(Address::Absolute(thr_offs), scratch.AsCpuRegister());
 }
 
-void X86JNIMacroAssembler::Copy(FrameOffset dest, FrameOffset src,
-                        ManagedRegister mscratch,
-                        size_t size) {
-  X86ManagedRegister scratch = mscratch.AsX86();
-  if (scratch.IsCpuRegister() && size == 8) {
-    Load(scratch, src, 4);
-    Store(dest, scratch, 4);
-    Load(scratch, FrameOffset(src.Int32Value() + 4), 4);
-    Store(FrameOffset(dest.Int32Value() + 4), scratch, 4);
-  } else {
-    Load(scratch, src, size);
-    Store(dest, scratch, size);
+void X86JNIMacroAssembler::Copy(FrameOffset dest, FrameOffset src, size_t size) {
+  DCHECK(size == 4 || size == 8) << size;
+  Register scratch = GetScratchRegister();
+  __ movl(scratch, Address(ESP, src));
+  __ movl(Address(ESP, dest), scratch);
+  if (size == 8) {
+    __ movl(scratch, Address(ESP, FrameOffset(src.Int32Value() + 4)));
+    __ movl(Address(ESP, FrameOffset(dest.Int32Value() + 4)), scratch);
   }
 }
 
@@ -441,10 +466,10 @@
   __ mfence();
 }
 
-void X86JNIMacroAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
-                                                  FrameOffset handle_scope_offset,
-                                                  ManagedRegister min_reg,
-                                                  bool null_allowed) {
+void X86JNIMacroAssembler::CreateJObject(ManagedRegister mout_reg,
+                                         FrameOffset spilled_reference_offset,
+                                         ManagedRegister min_reg,
+                                         bool null_allowed) {
   X86ManagedRegister out_reg = mout_reg.AsX86();
   X86ManagedRegister in_reg = min_reg.AsX86();
   CHECK(in_reg.IsCpuRegister());
@@ -457,47 +482,28 @@
     }
     __ testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister());
     __ j(kZero, &null_arg);
-    __ leal(out_reg.AsCpuRegister(), Address(ESP, handle_scope_offset));
+    __ leal(out_reg.AsCpuRegister(), Address(ESP, spilled_reference_offset));
     __ Bind(&null_arg);
   } else {
-    __ leal(out_reg.AsCpuRegister(), Address(ESP, handle_scope_offset));
+    __ leal(out_reg.AsCpuRegister(), Address(ESP, spilled_reference_offset));
   }
 }
 
-void X86JNIMacroAssembler::CreateHandleScopeEntry(FrameOffset out_off,
-                                                  FrameOffset handle_scope_offset,
-                                                  ManagedRegister mscratch,
-                                                  bool null_allowed) {
-  X86ManagedRegister scratch = mscratch.AsX86();
-  CHECK(scratch.IsCpuRegister());
+void X86JNIMacroAssembler::CreateJObject(FrameOffset out_off,
+                                         FrameOffset spilled_reference_offset,
+                                         bool null_allowed) {
+  Register scratch = GetScratchRegister();
   if (null_allowed) {
     Label null_arg;
-    __ movl(scratch.AsCpuRegister(), Address(ESP, handle_scope_offset));
-    __ testl(scratch.AsCpuRegister(), scratch.AsCpuRegister());
+    __ movl(scratch, Address(ESP, spilled_reference_offset));
+    __ testl(scratch, scratch);
     __ j(kZero, &null_arg);
-    __ leal(scratch.AsCpuRegister(), Address(ESP, handle_scope_offset));
+    __ leal(scratch, Address(ESP, spilled_reference_offset));
     __ Bind(&null_arg);
   } else {
-    __ leal(scratch.AsCpuRegister(), Address(ESP, handle_scope_offset));
+    __ leal(scratch, Address(ESP, spilled_reference_offset));
   }
-  Store(out_off, scratch, 4);
-}
-
-// Given a handle scope entry, load the associated reference.
-void X86JNIMacroAssembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
-                                                        ManagedRegister min_reg) {
-  X86ManagedRegister out_reg = mout_reg.AsX86();
-  X86ManagedRegister in_reg = min_reg.AsX86();
-  CHECK(out_reg.IsCpuRegister());
-  CHECK(in_reg.IsCpuRegister());
-  Label null_arg;
-  if (!out_reg.Equals(in_reg)) {
-    __ xorl(out_reg.AsCpuRegister(), out_reg.AsCpuRegister());
-  }
-  __ testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister());
-  __ j(kZero, &null_arg);
-  __ movl(out_reg.AsCpuRegister(), Address(in_reg.AsCpuRegister(), 0));
-  __ Bind(&null_arg);
+  __ movl(Address(ESP, out_off), scratch);
 }
 
 void X86JNIMacroAssembler::VerifyObject(ManagedRegister /*src*/, bool /*could_be_null*/) {
@@ -508,42 +514,41 @@
   // TODO: not validating references
 }
 
-void X86JNIMacroAssembler::Jump(ManagedRegister mbase, Offset offset, ManagedRegister) {
+void X86JNIMacroAssembler::Jump(ManagedRegister mbase, Offset offset) {
   X86ManagedRegister base = mbase.AsX86();
   CHECK(base.IsCpuRegister());
   __ jmp(Address(base.AsCpuRegister(), offset.Int32Value()));
 }
 
-void X86JNIMacroAssembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister) {
+void X86JNIMacroAssembler::Call(ManagedRegister mbase, Offset offset) {
   X86ManagedRegister base = mbase.AsX86();
   CHECK(base.IsCpuRegister());
   __ call(Address(base.AsCpuRegister(), offset.Int32Value()));
   // TODO: place reference map on call
 }
 
-void X86JNIMacroAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
-  Register scratch = mscratch.AsX86().AsCpuRegister();
+void X86JNIMacroAssembler::Call(FrameOffset base, Offset offset) {
+  Register scratch = GetScratchRegister();
   __ movl(scratch, Address(ESP, base));
   __ call(Address(scratch, offset));
 }
 
-void X86JNIMacroAssembler::CallFromThread(ThreadOffset32 offset, ManagedRegister /*mscratch*/) {
+void X86JNIMacroAssembler::CallFromThread(ThreadOffset32 offset) {
   __ fs()->call(Address::Absolute(offset));
 }
 
-void X86JNIMacroAssembler::GetCurrentThread(ManagedRegister tr) {
-  __ fs()->movl(tr.AsX86().AsCpuRegister(),
+void X86JNIMacroAssembler::GetCurrentThread(ManagedRegister dest) {
+  __ fs()->movl(dest.AsX86().AsCpuRegister(),
                 Address::Absolute(Thread::SelfOffset<kX86PointerSize>()));
 }
 
-void X86JNIMacroAssembler::GetCurrentThread(FrameOffset offset,
-                                    ManagedRegister mscratch) {
-  X86ManagedRegister scratch = mscratch.AsX86();
-  __ fs()->movl(scratch.AsCpuRegister(), Address::Absolute(Thread::SelfOffset<kX86PointerSize>()));
-  __ movl(Address(ESP, offset), scratch.AsCpuRegister());
+void X86JNIMacroAssembler::GetCurrentThread(FrameOffset offset) {
+  Register scratch = GetScratchRegister();
+  __ fs()->movl(scratch, Address::Absolute(Thread::SelfOffset<kX86PointerSize>()));
+  __ movl(Address(ESP, offset), scratch);
 }
 
-void X86JNIMacroAssembler::ExceptionPoll(ManagedRegister /*scratch*/, size_t stack_adjust) {
+void X86JNIMacroAssembler::ExceptionPoll(size_t stack_adjust) {
   X86ExceptionSlowPath* slow = new (__ GetAllocator()) X86ExceptionSlowPath(stack_adjust);
   __ GetBuffer()->EnqueueSlowPath(slow);
   __ fs()->cmpl(Address::Absolute(Thread::ExceptionOffset<kX86PointerSize>()), Immediate(0));
@@ -559,13 +564,11 @@
   __ jmp(X86JNIMacroLabel::Cast(label)->AsX86());
 }
 
-void X86JNIMacroAssembler::Jump(JNIMacroLabel* label,
-                                JNIMacroUnaryCondition condition,
-                                ManagedRegister test) {
+void X86JNIMacroAssembler::TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) {
   CHECK(label != nullptr);
 
   art::x86::Condition x86_cond;
-  switch (condition) {
+  switch (cond) {
     case JNIMacroUnaryCondition::kZero:
       x86_cond = art::x86::kZero;
       break;
@@ -573,18 +576,15 @@
       x86_cond = art::x86::kNotZero;
       break;
     default:
-      LOG(FATAL) << "Not implemented condition: " << static_cast<int>(condition);
+      LOG(FATAL) << "Not implemented condition: " << static_cast<int>(cond);
       UNREACHABLE();
   }
 
-  // TEST reg, reg
+  // CMP self->tls32_.is_gc_marking, 0
   // Jcc <Offset>
-  __ testl(test.AsX86().AsCpuRegister(), test.AsX86().AsCpuRegister());
+  DCHECK_EQ(Thread::IsGcMarkingSize(), 4u);
+  __ fs()->cmpl(Address::Absolute(Thread::IsGcMarkingOffset<kX86PointerSize>()), Immediate(0));
   __ j(x86_cond, X86JNIMacroLabel::Cast(label)->AsX86());
-
-
-  // X86 also has JCZX, JECZX, however it's not worth it to implement
-  // because we aren't likely to codegen with ECX+kZero check.
 }
 
 void X86JNIMacroAssembler::Bind(JNIMacroLabel* label) {
diff --git a/compiler/utils/x86/jni_macro_assembler_x86.h b/compiler/utils/x86/jni_macro_assembler_x86.h
index 7bf2f98..448a7f4 100644
--- a/compiler/utils/x86/jni_macro_assembler_x86.h
+++ b/compiler/utils/x86/jni_macro_assembler_x86.h
@@ -44,8 +44,7 @@
   // Emit code that will create an activation on the stack
   void BuildFrame(size_t frame_size,
                   ManagedRegister method_reg,
-                  ArrayRef<const ManagedRegister> callee_save_regs,
-                  const ManagedRegisterEntrySpills& entry_spills) override;
+                  ArrayRef<const ManagedRegister> callee_save_regs) override;
 
   // Emit code that will remove an activation from the stack
   void RemoveFrame(size_t frame_size,
@@ -60,16 +59,13 @@
   void StoreRef(FrameOffset dest, ManagedRegister src) override;
   void StoreRawPtr(FrameOffset dest, ManagedRegister src) override;
 
-  void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) override;
+  void StoreImmediateToFrame(FrameOffset dest, uint32_t imm) override;
 
-  void StoreStackOffsetToThread(ThreadOffset32 thr_offs,
-                                FrameOffset fr_offs,
-                                ManagedRegister scratch) override;
+  void StoreStackOffsetToThread(ThreadOffset32 thr_offs, FrameOffset fr_offs) override;
 
   void StoreStackPointerToThread(ThreadOffset32 thr_offs) override;
 
-  void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
-                     ManagedRegister scratch) override;
+  void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off) override;
 
   // Load routines
   void Load(ManagedRegister dest, FrameOffset src, size_t size) override;
@@ -86,18 +82,22 @@
   void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset32 offs) override;
 
   // Copying routines
+  void MoveArguments(ArrayRef<ArgumentLocation> dests, ArrayRef<ArgumentLocation> srcs) override;
+
   void Move(ManagedRegister dest, ManagedRegister src, size_t size) override;
 
-  void CopyRawPtrFromThread(FrameOffset fr_offs,
-                            ThreadOffset32 thr_offs,
-                            ManagedRegister scratch) override;
+  void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset32 thr_offs) override;
 
   void CopyRawPtrToThread(ThreadOffset32 thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
       override;
 
-  void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) override;
+  void CopyRef(FrameOffset dest, FrameOffset src) override;
+  void CopyRef(FrameOffset dest,
+               ManagedRegister base,
+               MemberOffset offs,
+               bool unpoison_reference) override;
 
-  void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) override;
+  void Copy(FrameOffset dest, FrameOffset src, size_t size) override;
 
   void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
             size_t size) override;
@@ -123,23 +123,23 @@
   void ZeroExtend(ManagedRegister mreg, size_t size) override;
 
   // Exploit fast access in managed code to Thread::Current()
-  void GetCurrentThread(ManagedRegister tr) override;
-  void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) override;
+  void GetCurrentThread(ManagedRegister dest) override;
+  void GetCurrentThread(FrameOffset dest_offset) override;
 
-  // Set up out_reg to hold a Object** into the handle scope, or to be null if the
-  // value is null and null_allowed. in_reg holds a possibly stale reference
-  // that can be used to avoid loading the handle scope entry to see if the value is
-  // null.
-  void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
-                              ManagedRegister in_reg, bool null_allowed) override;
+  // Set up `out_reg` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
+  // or to be null if the value is null and `null_allowed`. `in_reg` holds a possibly
+  // stale reference that can be used to avoid loading the spilled value to
+  // see if the value is null.
+  void CreateJObject(ManagedRegister out_reg,
+                     FrameOffset spilled_reference_offset,
+                     ManagedRegister in_reg,
+                     bool null_allowed) override;
 
-  // Set up out_off to hold a Object** into the handle scope, or to be null if the
-  // value is null and null_allowed.
-  void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
-                              ManagedRegister scratch, bool null_allowed) override;
-
-  // src holds a handle scope entry (Object**) load this into dst
-  void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) override;
+  // Set up `out_off` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
+  // or to be null if the value is null and `null_allowed`.
+  void CreateJObject(FrameOffset out_off,
+                     FrameOffset spilled_reference_offset,
+                     bool null_allowed) override;
 
   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
   // know that src may not be null.
@@ -147,23 +147,23 @@
   void VerifyObject(FrameOffset src, bool could_be_null) override;
 
   // Jump to address held at [base+offset] (used for tail calls).
-  void Jump(ManagedRegister base, Offset offset, ManagedRegister scratch) override;
+  void Jump(ManagedRegister base, Offset offset) override;
 
   // Call to address held at [base+offset]
-  void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) override;
-  void Call(FrameOffset base, Offset offset, ManagedRegister scratch) override;
-  void CallFromThread(ThreadOffset32 offset, ManagedRegister scratch) override;
+  void Call(ManagedRegister base, Offset offset) override;
+  void Call(FrameOffset base, Offset offset) override;
+  void CallFromThread(ThreadOffset32 offset) override;
 
   // Generate code to check if Thread::Current()->exception_ is non-null
   // and branch to a ExceptionSlowPath if it is.
-  void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) override;
+  void ExceptionPoll(size_t stack_adjust) override;
 
   // Create a new label that can be used with Jump/Bind calls.
   std::unique_ptr<JNIMacroLabel> CreateLabel() override;
   // Emit an unconditional jump to the label.
   void Jump(JNIMacroLabel* label) override;
-  // Emit a conditional jump to the label by applying a unary condition test to the register.
-  void Jump(JNIMacroLabel* label, JNIMacroUnaryCondition cond, ManagedRegister test) override;
+  // Emit a conditional jump to the label by applying a unary condition test to the GC marking flag.
+  void TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) override;
   // Code at this offset will serve as the target for the Jump call.
   void Bind(JNIMacroLabel* label) override;
 
diff --git a/compiler/utils/x86/managed_register_x86.h b/compiler/utils/x86/managed_register_x86.h
index 8810bfa..27555bf 100644
--- a/compiler/utils/x86/managed_register_x86.h
+++ b/compiler/utils/x86/managed_register_x86.h
@@ -214,7 +214,7 @@
 
 }  // namespace x86
 
-constexpr inline x86::X86ManagedRegister ManagedRegister::AsX86() const {
+constexpr x86::X86ManagedRegister ManagedRegister::AsX86() const {
   x86::X86ManagedRegister reg(id_);
   CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
   return reg;
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 2c5dd9e..7116bf2 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -4096,6 +4096,15 @@
 }
 
 
+void X86_64Assembler::andw(const Address& address, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  CHECK(imm.is_uint16() || imm.is_int16()) << imm.value();
+  EmitUint8(0x66);
+  EmitOptionalRex32(address);
+  EmitComplex(4, address, imm, /* is_16_op= */ true);
+}
+
+
 void X86_64Assembler::orl(CpuRegister dst, CpuRegister src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitOptionalRex32(dst, src);
@@ -4374,6 +4383,22 @@
 }
 
 
+void X86_64Assembler::divl(CpuRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOptionalRex32(reg);
+  EmitUint8(0xF7);
+  EmitUint8(0xF0 | reg.LowBits());
+}
+
+
+void X86_64Assembler::divq(CpuRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitRex64(reg);
+  EmitUint8(0xF7);
+  EmitUint8(0xF0 | reg.LowBits());
+}
+
+
 void X86_64Assembler::imull(CpuRegister dst, CpuRegister src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitOptionalRex32(dst, src);
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 70072d9..e5a9ce4 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -743,6 +743,7 @@
   void andq(CpuRegister dst, const Immediate& imm);
   void andq(CpuRegister dst, CpuRegister src);
   void andq(CpuRegister reg, const Address& address);
+  void andw(const Address& address, const Immediate& imm);
 
   void orl(CpuRegister dst, const Immediate& imm);
   void orl(CpuRegister dst, CpuRegister src);
@@ -782,6 +783,8 @@
 
   void idivl(CpuRegister reg);
   void idivq(CpuRegister reg);
+  void divl(CpuRegister reg);
+  void divq(CpuRegister reg);
 
   void imull(CpuRegister dst, CpuRegister src);
   void imull(CpuRegister reg, const Immediate& imm);
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 993cf95..1efe169 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -144,13 +144,8 @@
                              x86_64::Immediate>;
 
  protected:
-  // Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
-  std::string GetArchitectureString() override {
-    return "x86_64";
-  }
-
-  std::string GetDisassembleParameters() override {
-    return " -D -bbinary -mi386:x86-64 -Mx86-64,addr64,data32 --no-show-raw-insn";
+  InstructionSet GetIsa() override {
+    return InstructionSet::kX86_64;
   }
 
   void SetUpHelpers() override {
@@ -868,6 +863,22 @@
   DriverStr(Repeatrr(&x86_64::X86_64Assembler::testl, "testl %{reg1}, %{reg2}"), "testl");
 }
 
+TEST_F(AssemblerX86_64Test, Idivq) {
+  DriverStr(RepeatR(&x86_64::X86_64Assembler::idivq, "idivq %{reg}"), "idivq");
+}
+
+TEST_F(AssemblerX86_64Test, Idivl) {
+  DriverStr(Repeatr(&x86_64::X86_64Assembler::idivl, "idivl %{reg}"), "idivl");
+}
+
+TEST_F(AssemblerX86_64Test, Divq) {
+  DriverStr(RepeatR(&x86_64::X86_64Assembler::divq, "divq %{reg}"), "divq");
+}
+
+TEST_F(AssemblerX86_64Test, Divl) {
+  DriverStr(Repeatr(&x86_64::X86_64Assembler::divl, "divl %{reg}"), "divl");
+}
+
 TEST_F(AssemblerX86_64Test, Negq) {
   DriverStr(RepeatR(&x86_64::X86_64Assembler::negq, "negq %{reg}"), "negq");
 }
@@ -904,6 +915,11 @@
                      "andl ${imm}, %{reg}"), "andli");
 }
 
+TEST_F(AssemblerX86_64Test, Andw) {
+  DriverStr(
+      RepeatAI(&x86_64::X86_64Assembler::andw, /*imm_bytes*/2U, "andw ${imm}, {mem}"), "andw");
+}
+
 TEST_F(AssemblerX86_64Test, OrqRegs) {
   DriverStr(RepeatRR(&x86_64::X86_64Assembler::orq, "orq %{reg2}, %{reg1}"), "orq");
 }
@@ -936,7 +952,7 @@
 }
 
 TEST_F(AssemblerX86_64Test, Xchgq) {
-  DriverStr(RepeatRR(&x86_64::X86_64Assembler::xchgq, "xchgq %{reg2}, %{reg1}"), "xchgq");
+  DriverStr(RepeatRR(&x86_64::X86_64Assembler::xchgq, "xchgq %{reg1}, %{reg2}"), "xchgq");
 }
 
 TEST_F(AssemblerX86_64Test, Xchgl) {
@@ -1112,7 +1128,7 @@
 }
 
 TEST_F(AssemblerX86_64Test, Movsxd) {
-  DriverStr(RepeatRr(&x86_64::X86_64Assembler::movsxd, "movsxd %{reg2}, %{reg1}"), "movsxd");
+  DriverStr(RepeatRr(&x86_64::X86_64Assembler::movsxd, "movslq %{reg2}, %{reg1}"), "movsxd");
 }
 
 TEST_F(AssemblerX86_64Test, Movaps) {
@@ -2303,13 +2319,8 @@
   using Base = JNIMacroAssemblerTest<x86_64::X86_64JNIMacroAssembler>;
 
  protected:
-  // Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
-  std::string GetArchitectureString() override {
-    return "x86_64";
-  }
-
-  std::string GetDisassembleParameters() override {
-    return " -D -bbinary -mi386:x86-64 -Mx86-64,addr64,data32 --no-show-raw-insn";
+  InstructionSet GetIsa() override {
+    return InstructionSet::kX86_64;
   }
 
  private:
@@ -2334,19 +2345,15 @@
   };
   ArrayRef<const ManagedRegister> spill_regs(raw_spill_regs);
 
-  // Three random entry spills.
-  ManagedRegisterEntrySpills entry_spills;
-  ManagedRegisterSpill spill(ManagedFromCpu(x86_64::RAX), 8, 0);
-  entry_spills.push_back(spill);
-  ManagedRegisterSpill spill2(ManagedFromCpu(x86_64::RBX), 8, 8);
-  entry_spills.push_back(spill2);
-  ManagedRegisterSpill spill3(ManagedFromFpu(x86_64::XMM1), 8, 16);
-  entry_spills.push_back(spill3);
-
   x86_64::X86_64ManagedRegister method_reg = ManagedFromCpu(x86_64::RDI);
 
   size_t frame_size = 10 * kStackAlignment;
-  assembler->BuildFrame(frame_size, method_reg, spill_regs, entry_spills);
+  assembler->BuildFrame(frame_size, method_reg, spill_regs);
+
+  // Three random entry spills.
+  assembler->Store(FrameOffset(frame_size + 0u), ManagedFromCpu(x86_64::RAX), /* size= */ 8u);
+  assembler->Store(FrameOffset(frame_size + 8u), ManagedFromCpu(x86_64::RBX), /* size= */ 8u);
+  assembler->Store(FrameOffset(frame_size + 16u), ManagedFromFpu(x86_64::XMM1), /* size= */ 8u);
 
   // Construct assembly text counterpart.
   std::ostringstream str;
diff --git a/compiler/utils/x86_64/jni_macro_assembler_x86_64.cc b/compiler/utils/x86_64/jni_macro_assembler_x86_64.cc
index ffe9020..b5e17d1 100644
--- a/compiler/utils/x86_64/jni_macro_assembler_x86_64.cc
+++ b/compiler/utils/x86_64/jni_macro_assembler_x86_64.cc
@@ -36,12 +36,15 @@
 static constexpr size_t kNativeStackAlignment = 16;
 static_assert(kNativeStackAlignment == kStackAlignment);
 
+static inline CpuRegister GetScratchRegister() {
+  return CpuRegister(R11);
+}
+
 #define __ asm_.
 
 void X86_64JNIMacroAssembler::BuildFrame(size_t frame_size,
                                          ManagedRegister method_reg,
-                                         ArrayRef<const ManagedRegister> spill_regs,
-                                         const ManagedRegisterEntrySpills& entry_spills) {
+                                         ArrayRef<const ManagedRegister> spill_regs) {
   DCHECK_EQ(CodeSize(), 0U);  // Nothing emitted yet.
   cfi().SetCurrentCFAOffset(8);  // Return address on stack.
   // Note: @CriticalNative tail call is not used (would have frame_size == kFramePointerSize).
@@ -86,28 +89,6 @@
   if (method_reg.IsRegister()) {
     __ movq(Address(CpuRegister(RSP), 0), method_reg.AsX86_64().AsCpuRegister());
   }
-
-  for (const ManagedRegisterSpill& spill : entry_spills) {
-    if (spill.AsX86_64().IsCpuRegister()) {
-      if (spill.getSize() == 8) {
-        __ movq(Address(CpuRegister(RSP), frame_size + spill.getSpillOffset()),
-                spill.AsX86_64().AsCpuRegister());
-      } else {
-        CHECK_EQ(spill.getSize(), 4);
-        __ movl(Address(CpuRegister(RSP), frame_size + spill.getSpillOffset()),
-                spill.AsX86_64().AsCpuRegister());
-      }
-    } else {
-      if (spill.getSize() == 8) {
-        __ movsd(Address(CpuRegister(RSP), frame_size + spill.getSpillOffset()),
-                 spill.AsX86_64().AsXmmRegister());
-      } else {
-        CHECK_EQ(spill.getSize(), 4);
-        __ movss(Address(CpuRegister(RSP), frame_size + spill.getSpillOffset()),
-                 spill.AsX86_64().AsXmmRegister());
-      }
-    }
-  }
 }
 
 void X86_64JNIMacroAssembler::RemoveFrame(size_t frame_size,
@@ -215,19 +196,15 @@
   __ movq(Address(CpuRegister(RSP), dest), src.AsCpuRegister());
 }
 
-void X86_64JNIMacroAssembler::StoreImmediateToFrame(FrameOffset dest,
-                                                    uint32_t imm,
-                                                    ManagedRegister) {
+void X86_64JNIMacroAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm) {
   __ movl(Address(CpuRegister(RSP), dest), Immediate(imm));  // TODO(64) movq?
 }
 
 void X86_64JNIMacroAssembler::StoreStackOffsetToThread(ThreadOffset64 thr_offs,
-                                                       FrameOffset fr_offs,
-                                                       ManagedRegister mscratch) {
-  X86_64ManagedRegister scratch = mscratch.AsX86_64();
-  CHECK(scratch.IsCpuRegister());
-  __ leaq(scratch.AsCpuRegister(), Address(CpuRegister(RSP), fr_offs));
-  __ gs()->movq(Address::Absolute(thr_offs, true), scratch.AsCpuRegister());
+                                                       FrameOffset fr_offs) {
+  CpuRegister scratch = GetScratchRegister();
+  __ leaq(scratch, Address(CpuRegister(RSP), fr_offs));
+  __ gs()->movq(Address::Absolute(thr_offs, true), scratch);
 }
 
 void X86_64JNIMacroAssembler::StoreStackPointerToThread(ThreadOffset64 thr_offs) {
@@ -236,8 +213,7 @@
 
 void X86_64JNIMacroAssembler::StoreSpanning(FrameOffset /*dst*/,
                                             ManagedRegister /*src*/,
-                                            FrameOffset /*in_off*/,
-                                            ManagedRegister /*scratch*/) {
+                                            FrameOffset /*in_off*/) {
   UNIMPLEMENTED(FATAL);  // this case only currently exists for ARM
 }
 
@@ -362,7 +338,78 @@
   }
 }
 
+void X86_64JNIMacroAssembler::MoveArguments(ArrayRef<ArgumentLocation> dests,
+                                            ArrayRef<ArgumentLocation> srcs) {
+  DCHECK_EQ(dests.size(), srcs.size());
+  auto get_mask = [](ManagedRegister reg) -> uint32_t {
+    X86_64ManagedRegister x86_64_reg = reg.AsX86_64();
+    if (x86_64_reg.IsCpuRegister()) {
+      size_t cpu_reg_number = static_cast<size_t>(x86_64_reg.AsCpuRegister().AsRegister());
+      DCHECK_LT(cpu_reg_number, 16u);
+      return 1u << cpu_reg_number;
+    } else {
+      DCHECK(x86_64_reg.IsXmmRegister());
+      size_t xmm_reg_number = static_cast<size_t>(x86_64_reg.AsXmmRegister().AsFloatRegister());
+      DCHECK_LT(xmm_reg_number, 16u);
+      return (1u << 16u) << xmm_reg_number;
+    }
+  };
+  // Collect registers to move while storing/copying args to stack slots.
+  uint32_t src_regs = 0u;
+  uint32_t dest_regs = 0u;
+  for (size_t i = 0, arg_count = srcs.size(); i != arg_count; ++i) {
+    const ArgumentLocation& src = srcs[i];
+    const ArgumentLocation& dest = dests[i];
+    DCHECK_EQ(src.GetSize(), dest.GetSize());
+    if (dest.IsRegister()) {
+      if (src.IsRegister() && src.GetRegister().Equals(dest.GetRegister())) {
+        // Nothing to do.
+      } else {
+        if (src.IsRegister()) {
+          src_regs |= get_mask(src.GetRegister());
+        }
+        dest_regs |= get_mask(dest.GetRegister());
+      }
+    } else {
+      if (src.IsRegister()) {
+        Store(dest.GetFrameOffset(), src.GetRegister(), dest.GetSize());
+      } else {
+        Copy(dest.GetFrameOffset(), src.GetFrameOffset(), dest.GetSize());
+      }
+    }
+  }
+  // Fill destination registers.
+  // There should be no cycles, so this simple algorithm should make progress.
+  while (dest_regs != 0u) {
+    uint32_t old_dest_regs = dest_regs;
+    for (size_t i = 0, arg_count = srcs.size(); i != arg_count; ++i) {
+      const ArgumentLocation& src = srcs[i];
+      const ArgumentLocation& dest = dests[i];
+      if (!dest.IsRegister()) {
+        continue;  // Stored in first loop above.
+      }
+      uint32_t dest_reg_mask = get_mask(dest.GetRegister());
+      if ((dest_reg_mask & dest_regs) == 0u) {
+        continue;  // Equals source, or already filled in one of previous iterations.
+      }
+      if ((dest_reg_mask & src_regs) != 0u) {
+        continue;  // Cannot clobber this register yet.
+      }
+      if (src.IsRegister()) {
+        Move(dest.GetRegister(), src.GetRegister(), dest.GetSize());
+        src_regs &= ~get_mask(src.GetRegister());  // Allow clobbering source register.
+      } else {
+        Load(dest.GetRegister(), src.GetFrameOffset(), dest.GetSize());
+      }
+      dest_regs &= ~get_mask(dest.GetRegister());  // Destination register was filled.
+    }
+    CHECK_NE(old_dest_regs, dest_regs);
+    DCHECK_EQ(0u, dest_regs & ~old_dest_regs);
+  }
+}
+
 void X86_64JNIMacroAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
+  DCHECK(!mdest.Equals(X86_64ManagedRegister::FromCpuRegister(GetScratchRegister().AsRegister())));
   X86_64ManagedRegister dest = mdest.AsX86_64();
   X86_64ManagedRegister src = msrc.AsX86_64();
   if (!dest.Equals(src)) {
@@ -388,20 +435,28 @@
   }
 }
 
-void X86_64JNIMacroAssembler::CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) {
-  X86_64ManagedRegister scratch = mscratch.AsX86_64();
-  CHECK(scratch.IsCpuRegister());
-  __ movl(scratch.AsCpuRegister(), Address(CpuRegister(RSP), src));
-  __ movl(Address(CpuRegister(RSP), dest), scratch.AsCpuRegister());
+void X86_64JNIMacroAssembler::CopyRef(FrameOffset dest, FrameOffset src) {
+  CpuRegister scratch = GetScratchRegister();
+  __ movl(scratch, Address(CpuRegister(RSP), src));
+  __ movl(Address(CpuRegister(RSP), dest), scratch);
 }
 
-void X86_64JNIMacroAssembler::CopyRawPtrFromThread(FrameOffset fr_offs,
-                                                   ThreadOffset64 thr_offs,
-                                                   ManagedRegister mscratch) {
-  X86_64ManagedRegister scratch = mscratch.AsX86_64();
-  CHECK(scratch.IsCpuRegister());
-  __ gs()->movq(scratch.AsCpuRegister(), Address::Absolute(thr_offs, true));
-  Store(fr_offs, scratch, 8);
+void X86_64JNIMacroAssembler::CopyRef(FrameOffset dest,
+                                      ManagedRegister base,
+                                      MemberOffset offs,
+                                      bool unpoison_reference) {
+  CpuRegister scratch = GetScratchRegister();
+  __ movl(scratch, Address(base.AsX86_64().AsCpuRegister(), offs));
+  if (unpoison_reference) {
+    __ MaybeUnpoisonHeapReference(scratch);
+  }
+  __ movl(Address(CpuRegister(RSP), dest), scratch);
+}
+
+void X86_64JNIMacroAssembler::CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset64 thr_offs) {
+  CpuRegister scratch = GetScratchRegister();
+  __ gs()->movq(scratch, Address::Absolute(thr_offs, true));
+  __ movq(Address(CpuRegister(RSP), fr_offs), scratch);
 }
 
 void X86_64JNIMacroAssembler::CopyRawPtrToThread(ThreadOffset64 thr_offs,
@@ -413,19 +468,15 @@
   __ gs()->movq(Address::Absolute(thr_offs, true), scratch.AsCpuRegister());
 }
 
-void X86_64JNIMacroAssembler::Copy(FrameOffset dest,
-                                   FrameOffset src,
-                                   ManagedRegister mscratch,
-                                   size_t size) {
-  X86_64ManagedRegister scratch = mscratch.AsX86_64();
-  if (scratch.IsCpuRegister() && size == 8) {
-    Load(scratch, src, 4);
-    Store(dest, scratch, 4);
-    Load(scratch, FrameOffset(src.Int32Value() + 4), 4);
-    Store(FrameOffset(dest.Int32Value() + 4), scratch, 4);
+void X86_64JNIMacroAssembler::Copy(FrameOffset dest, FrameOffset src, size_t size) {
+  DCHECK(size == 4 || size == 8) << size;
+  CpuRegister scratch = GetScratchRegister();
+  if (size == 8) {
+    __ movq(scratch, Address(CpuRegister(RSP), src));
+    __ movq(Address(CpuRegister(RSP), dest), scratch);
   } else {
-    Load(scratch, src, size);
-    Store(dest, scratch, size);
+    __ movl(scratch, Address(CpuRegister(RSP), src));
+    __ movl(Address(CpuRegister(RSP), dest), scratch);
   }
 }
 
@@ -490,17 +541,17 @@
   __ mfence();
 }
 
-void X86_64JNIMacroAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
-                                                     FrameOffset handle_scope_offset,
-                                                     ManagedRegister min_reg,
-                                                     bool null_allowed) {
+void X86_64JNIMacroAssembler::CreateJObject(ManagedRegister mout_reg,
+                                            FrameOffset spilled_reference_offset,
+                                            ManagedRegister min_reg,
+                                            bool null_allowed) {
   X86_64ManagedRegister out_reg = mout_reg.AsX86_64();
   X86_64ManagedRegister in_reg = min_reg.AsX86_64();
   if (in_reg.IsNoRegister()) {  // TODO(64): && null_allowed
     // Use out_reg as indicator of null.
     in_reg = out_reg;
     // TODO: movzwl
-    __ movl(in_reg.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
+    __ movl(in_reg.AsCpuRegister(), Address(CpuRegister(RSP), spilled_reference_offset));
   }
   CHECK(in_reg.IsCpuRegister());
   CHECK(out_reg.IsCpuRegister());
@@ -512,47 +563,28 @@
     }
     __ testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister());
     __ j(kZero, &null_arg);
-    __ leaq(out_reg.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
+    __ leaq(out_reg.AsCpuRegister(), Address(CpuRegister(RSP), spilled_reference_offset));
     __ Bind(&null_arg);
   } else {
-    __ leaq(out_reg.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
+    __ leaq(out_reg.AsCpuRegister(), Address(CpuRegister(RSP), spilled_reference_offset));
   }
 }
 
-void X86_64JNIMacroAssembler::CreateHandleScopeEntry(FrameOffset out_off,
-                                                     FrameOffset handle_scope_offset,
-                                                     ManagedRegister mscratch,
-                                                     bool null_allowed) {
-  X86_64ManagedRegister scratch = mscratch.AsX86_64();
-  CHECK(scratch.IsCpuRegister());
+void X86_64JNIMacroAssembler::CreateJObject(FrameOffset out_off,
+                                            FrameOffset spilled_reference_offset,
+                                            bool null_allowed) {
+  CpuRegister scratch = GetScratchRegister();
   if (null_allowed) {
     Label null_arg;
-    __ movl(scratch.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
-    __ testl(scratch.AsCpuRegister(), scratch.AsCpuRegister());
+    __ movl(scratch, Address(CpuRegister(RSP), spilled_reference_offset));
+    __ testl(scratch, scratch);
     __ j(kZero, &null_arg);
-    __ leaq(scratch.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
+    __ leaq(scratch, Address(CpuRegister(RSP), spilled_reference_offset));
     __ Bind(&null_arg);
   } else {
-    __ leaq(scratch.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
+    __ leaq(scratch, Address(CpuRegister(RSP), spilled_reference_offset));
   }
-  Store(out_off, scratch, 8);
-}
-
-// Given a handle scope entry, load the associated reference.
-void X86_64JNIMacroAssembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
-                                                           ManagedRegister min_reg) {
-  X86_64ManagedRegister out_reg = mout_reg.AsX86_64();
-  X86_64ManagedRegister in_reg = min_reg.AsX86_64();
-  CHECK(out_reg.IsCpuRegister());
-  CHECK(in_reg.IsCpuRegister());
-  Label null_arg;
-  if (!out_reg.Equals(in_reg)) {
-    __ xorl(out_reg.AsCpuRegister(), out_reg.AsCpuRegister());
-  }
-  __ testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister());
-  __ j(kZero, &null_arg);
-  __ movq(out_reg.AsCpuRegister(), Address(in_reg.AsCpuRegister(), 0));
-  __ Bind(&null_arg);
+  __ movq(Address(CpuRegister(RSP), out_off), scratch);
 }
 
 void X86_64JNIMacroAssembler::VerifyObject(ManagedRegister /*src*/, bool /*could_be_null*/) {
@@ -563,39 +595,38 @@
   // TODO: not validating references
 }
 
-void X86_64JNIMacroAssembler::Jump(ManagedRegister mbase, Offset offset, ManagedRegister) {
+void X86_64JNIMacroAssembler::Jump(ManagedRegister mbase, Offset offset) {
   X86_64ManagedRegister base = mbase.AsX86_64();
   CHECK(base.IsCpuRegister());
   __ jmp(Address(base.AsCpuRegister(), offset.Int32Value()));
 }
 
-void X86_64JNIMacroAssembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister) {
+void X86_64JNIMacroAssembler::Call(ManagedRegister mbase, Offset offset) {
   X86_64ManagedRegister base = mbase.AsX86_64();
   CHECK(base.IsCpuRegister());
   __ call(Address(base.AsCpuRegister(), offset.Int32Value()));
   // TODO: place reference map on call
 }
 
-void X86_64JNIMacroAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
-  CpuRegister scratch = mscratch.AsX86_64().AsCpuRegister();
+void X86_64JNIMacroAssembler::Call(FrameOffset base, Offset offset) {
+  CpuRegister scratch = GetScratchRegister();
   __ movq(scratch, Address(CpuRegister(RSP), base));
   __ call(Address(scratch, offset));
 }
 
-void X86_64JNIMacroAssembler::CallFromThread(ThreadOffset64 offset, ManagedRegister /*mscratch*/) {
+void X86_64JNIMacroAssembler::CallFromThread(ThreadOffset64 offset) {
   __ gs()->call(Address::Absolute(offset, true));
 }
 
-void X86_64JNIMacroAssembler::GetCurrentThread(ManagedRegister tr) {
-  __ gs()->movq(tr.AsX86_64().AsCpuRegister(),
+void X86_64JNIMacroAssembler::GetCurrentThread(ManagedRegister dest) {
+  __ gs()->movq(dest.AsX86_64().AsCpuRegister(),
                 Address::Absolute(Thread::SelfOffset<kX86_64PointerSize>(), true));
 }
 
-void X86_64JNIMacroAssembler::GetCurrentThread(FrameOffset offset, ManagedRegister mscratch) {
-  X86_64ManagedRegister scratch = mscratch.AsX86_64();
-  __ gs()->movq(scratch.AsCpuRegister(),
-                Address::Absolute(Thread::SelfOffset<kX86_64PointerSize>(), true));
-  __ movq(Address(CpuRegister(RSP), offset), scratch.AsCpuRegister());
+void X86_64JNIMacroAssembler::GetCurrentThread(FrameOffset offset) {
+  CpuRegister scratch = GetScratchRegister();
+  __ gs()->movq(scratch, Address::Absolute(Thread::SelfOffset<kX86_64PointerSize>(), true));
+  __ movq(Address(CpuRegister(RSP), offset), scratch);
 }
 
 // Slowpath entered when Thread::Current()->_exception is non-null
@@ -607,7 +638,7 @@
   const size_t stack_adjust_;
 };
 
-void X86_64JNIMacroAssembler::ExceptionPoll(ManagedRegister /*scratch*/, size_t stack_adjust) {
+void X86_64JNIMacroAssembler::ExceptionPoll(size_t stack_adjust) {
   X86_64ExceptionSlowPath* slow = new (__ GetAllocator()) X86_64ExceptionSlowPath(stack_adjust);
   __ GetBuffer()->EnqueueSlowPath(slow);
   __ gs()->cmpl(Address::Absolute(Thread::ExceptionOffset<kX86_64PointerSize>(), true),
@@ -624,13 +655,11 @@
   __ jmp(X86_64JNIMacroLabel::Cast(label)->AsX86_64());
 }
 
-void X86_64JNIMacroAssembler::Jump(JNIMacroLabel* label,
-                                   JNIMacroUnaryCondition condition,
-                                   ManagedRegister test) {
+void X86_64JNIMacroAssembler::TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) {
   CHECK(label != nullptr);
 
   art::x86_64::Condition x86_64_cond;
-  switch (condition) {
+  switch (cond) {
     case JNIMacroUnaryCondition::kZero:
       x86_64_cond = art::x86_64::kZero;
       break;
@@ -638,13 +667,15 @@
       x86_64_cond = art::x86_64::kNotZero;
       break;
     default:
-      LOG(FATAL) << "Not implemented condition: " << static_cast<int>(condition);
+      LOG(FATAL) << "Not implemented condition: " << static_cast<int>(cond);
       UNREACHABLE();
   }
 
-  // TEST reg, reg
+  // CMP self->tls32_.is_gc_marking, 0
   // Jcc <Offset>
-  __ testq(test.AsX86_64().AsCpuRegister(), test.AsX86_64().AsCpuRegister());
+  DCHECK_EQ(Thread::IsGcMarkingSize(), 4u);
+  __ gs()->cmpl(Address::Absolute(Thread::IsGcMarkingOffset<kX86_64PointerSize>(), true),
+                Immediate(0));
   __ j(x86_64_cond, X86_64JNIMacroLabel::Cast(label)->AsX86_64());
 }
 
diff --git a/compiler/utils/x86_64/jni_macro_assembler_x86_64.h b/compiler/utils/x86_64/jni_macro_assembler_x86_64.h
index d3f1fce..a5f7bbb 100644
--- a/compiler/utils/x86_64/jni_macro_assembler_x86_64.h
+++ b/compiler/utils/x86_64/jni_macro_assembler_x86_64.h
@@ -45,8 +45,7 @@
   // Emit code that will create an activation on the stack
   void BuildFrame(size_t frame_size,
                   ManagedRegister method_reg,
-                  ArrayRef<const ManagedRegister> callee_save_regs,
-                  const ManagedRegisterEntrySpills& entry_spills) override;
+                  ArrayRef<const ManagedRegister> callee_save_regs) override;
 
   // Emit code that will remove an activation from the stack
   void RemoveFrame(size_t frame_size,
@@ -61,18 +60,13 @@
   void StoreRef(FrameOffset dest, ManagedRegister src) override;
   void StoreRawPtr(FrameOffset dest, ManagedRegister src) override;
 
-  void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) override;
+  void StoreImmediateToFrame(FrameOffset dest, uint32_t imm) override;
 
-  void StoreStackOffsetToThread(ThreadOffset64 thr_offs,
-                                FrameOffset fr_offs,
-                                ManagedRegister scratch) override;
+  void StoreStackOffsetToThread(ThreadOffset64 thr_offs, FrameOffset fr_offs) override;
 
   void StoreStackPointerToThread(ThreadOffset64 thr_offs) override;
 
-  void StoreSpanning(FrameOffset dest,
-                     ManagedRegister src,
-                     FrameOffset in_off,
-                     ManagedRegister scratch) override;
+  void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off) override;
 
   // Load routines
   void Load(ManagedRegister dest, FrameOffset src, size_t size) override;
@@ -91,18 +85,22 @@
   void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset64 offs) override;
 
   // Copying routines
+  void MoveArguments(ArrayRef<ArgumentLocation> dests, ArrayRef<ArgumentLocation> srcs) override;
+
   void Move(ManagedRegister dest, ManagedRegister src, size_t size) override;
 
-  void CopyRawPtrFromThread(FrameOffset fr_offs,
-                            ThreadOffset64 thr_offs,
-                            ManagedRegister scratch) override;
+  void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset64 thr_offs) override;
 
   void CopyRawPtrToThread(ThreadOffset64 thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
       override;
 
-  void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) override;
+  void CopyRef(FrameOffset dest, FrameOffset src) override;
+  void CopyRef(FrameOffset dest,
+               ManagedRegister base,
+               MemberOffset offs,
+               bool unpoison_reference) override;
 
-  void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) override;
+  void Copy(FrameOffset dest, FrameOffset src, size_t size) override;
 
   void Copy(FrameOffset dest,
             ManagedRegister src_base,
@@ -145,27 +143,23 @@
   void ZeroExtend(ManagedRegister mreg, size_t size) override;
 
   // Exploit fast access in managed code to Thread::Current()
-  void GetCurrentThread(ManagedRegister tr) override;
-  void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) override;
+  void GetCurrentThread(ManagedRegister dest) override;
+  void GetCurrentThread(FrameOffset dest_offset) override;
 
-  // Set up out_reg to hold a Object** into the handle scope, or to be null if the
-  // value is null and null_allowed. in_reg holds a possibly stale reference
-  // that can be used to avoid loading the handle scope entry to see if the value is
-  // null.
-  void CreateHandleScopeEntry(ManagedRegister out_reg,
-                              FrameOffset handlescope_offset,
-                              ManagedRegister in_reg,
-                              bool null_allowed) override;
+  // Set up `out_reg` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
+  // or to be null if the value is null and `null_allowed`. `in_reg` holds a possibly
+  // stale reference that can be used to avoid loading the spilled value to
+  // see if the value is null.
+  void CreateJObject(ManagedRegister out_reg,
+                     FrameOffset spilled_reference_offset,
+                     ManagedRegister in_reg,
+                     bool null_allowed) override;
 
-  // Set up out_off to hold a Object** into the handle scope, or to be null if the
-  // value is null and null_allowed.
-  void CreateHandleScopeEntry(FrameOffset out_off,
-                              FrameOffset handlescope_offset,
-                              ManagedRegister scratch,
-                              bool null_allowed) override;
-
-  // src holds a handle scope entry (Object**) load this into dst
-  void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) override;
+  // Set up `out_off` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
+  // or to be null if the value is null and `null_allowed`.
+  void CreateJObject(FrameOffset out_off,
+                     FrameOffset spilled_reference_offset,
+                     bool null_allowed) override;
 
   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
   // know that src may not be null.
@@ -173,23 +167,23 @@
   void VerifyObject(FrameOffset src, bool could_be_null) override;
 
   // Jump to address held at [base+offset] (used for tail calls).
-  void Jump(ManagedRegister base, Offset offset, ManagedRegister scratch) override;
+  void Jump(ManagedRegister base, Offset offset) override;
 
   // Call to address held at [base+offset]
-  void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) override;
-  void Call(FrameOffset base, Offset offset, ManagedRegister scratch) override;
-  void CallFromThread(ThreadOffset64 offset, ManagedRegister scratch) override;
+  void Call(ManagedRegister base, Offset offset) override;
+  void Call(FrameOffset base, Offset offset) override;
+  void CallFromThread(ThreadOffset64 offset) override;
 
   // Generate code to check if Thread::Current()->exception_ is non-null
   // and branch to a ExceptionSlowPath if it is.
-  void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) override;
+  void ExceptionPoll(size_t stack_adjust) override;
 
   // Create a new label that can be used with Jump/Bind calls.
   std::unique_ptr<JNIMacroLabel> CreateLabel() override;
   // Emit an unconditional jump to the label.
   void Jump(JNIMacroLabel* label) override;
-  // Emit a conditional jump to the label by applying a unary condition test to the register.
-  void Jump(JNIMacroLabel* label, JNIMacroUnaryCondition cond, ManagedRegister test) override;
+  // Emit a conditional jump to the label by applying a unary condition test to the GC marking flag.
+  void TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) override;
   // Code at this offset will serve as the target for the Jump call.
   void Bind(JNIMacroLabel* label) override;
 
diff --git a/compiler/utils/x86_64/managed_register_x86_64.h b/compiler/utils/x86_64/managed_register_x86_64.h
index 6760882..62c0e37 100644
--- a/compiler/utils/x86_64/managed_register_x86_64.h
+++ b/compiler/utils/x86_64/managed_register_x86_64.h
@@ -200,7 +200,7 @@
 
 }  // namespace x86_64
 
-constexpr inline x86_64::X86_64ManagedRegister ManagedRegister::AsX86_64() const {
+constexpr x86_64::X86_64ManagedRegister ManagedRegister::AsX86_64() const {
   x86_64::X86_64ManagedRegister reg(id_);
   CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
   return reg;
diff --git a/dalvikvm/Android.bp b/dalvikvm/Android.bp
index 8cd8819..6e06eba 100644
--- a/dalvikvm/Android.bp
+++ b/dalvikvm/Android.bp
@@ -14,32 +14,42 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 art_cc_binary {
     name: "dalvikvm",
+    defaults: ["art_defaults"],
     host_supported: true,
     compile_multilib: "both",
 
     srcs: ["dalvikvm.cc"],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wextra",
-    ],
     shared_libs: [
+        "liblog",
         "libnativehelper",
     ],
-    whole_static_libs: ["libsigchain"],
+    header_libs: [
+        "art_libartbase_headers", // For base/fast_exit.h
+    ],
     target: {
         android: {
             shared_libs: [
-                "liblog",
+                "libsigchain",
             ],
         },
         linux: {
             ldflags: ["-Wl,--export-dynamic"],
         },
-        darwin: {
-            enabled: false,
+        host: {
+            // TODO(b/183102427): this seems to help asan on host, but libsgichain should
+            // really be in shared_libs.
+            whole_static_libs: ["libsigchain"],
         },
     },
 
@@ -55,7 +65,7 @@
     // Create symlink for the primary version target.
     symlink_preferred_arch: true,
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
diff --git a/dalvikvm/dalvikvm.cc b/dalvikvm/dalvikvm.cc
index 4808a1f..27709fd 100644
--- a/dalvikvm/dalvikvm.cc
+++ b/dalvikvm/dalvikvm.cc
@@ -21,6 +21,7 @@
 #include <algorithm>
 #include <memory>
 
+#include "base/fast_exit.h"
 #include "jni.h"
 #include "nativehelper/JniInvocation.h"
 #include "nativehelper/ScopedLocalRef.h"
@@ -216,5 +217,5 @@
 int main(int argc, char** argv) {
   // Do not allow static destructors to be called, since it's conceivable that
   // daemons may still awaken (literally).
-  _exit(art::dalvikvm(argc, argv));
+  art::FastExit(art::dalvikvm(argc, argv));
 }
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
index fb76dd9..d377bbb 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -14,12 +14,20 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 art_cc_defaults {
     name: "libart-dex2oat-defaults",
     defaults: ["art_defaults"],
     host_supported: true,
     srcs: [
-        "dex/dex_to_dex_compiler.cc",
         "dex/quick_compiler_callbacks.cc",
         "driver/compiler_driver.cc",
         "linker/elf_writer.cc",
@@ -55,33 +63,24 @@
         },
     },
 
-    target: {
-        android: {
-            static_libs: [
-                "libz",
-            ],
-        },
-        host: {
-            shared_libs: [
-                "libz",
-            ],
-        },
-    },
     generated_sources: ["art_dex2oat_operator_srcs"],
     shared_libs: [
         "libbase",
-
-        // For SHA-1 checksumming of build ID
-        "libcrypto",
+        "libcrypto", // For SHA-1 checksumming of build ID
+        "liblog",
+        "liblz4",
+        "libz",
     ],
     export_include_dirs: ["."],
 }
 
 cc_defaults {
     name: "libart-dex2oat_static_base_defaults",
-    static_libs: [
+    whole_static_libs: [
         "libbase",
         "libcrypto",
+        "liblog",
+        "liblz4",
         "libz",
     ],
 }
@@ -91,8 +90,6 @@
     cmd: "$(location generate_operator_out) art/dex2oat $(in) > $(out)",
     tools: ["generate_operator_out"],
     srcs: [
-        "dex/dex_to_dex_compiler.h",
-        "driver/compiler_driver.h",
         "linker/image_writer.h",
     ],
     output_extension: "operator_out.cc",
@@ -109,7 +106,7 @@
         "libprofile",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -121,13 +118,31 @@
         "libart_static_defaults",
         "libprofile_static_defaults",
     ],
-    static_libs: [
+    whole_static_libs: [
         "libart-compiler",
         "libart-dexlayout",
         "libart-dex2oat",
     ],
 }
 
+// Collect all the static defaults and build a host-only static library, which
+// is then used for the (mostly) static host dex2oat binary.
+art_cc_library_static {
+    name: "libdex2oat_static",
+    device_supported: false,
+    host_supported: true,
+    defaults: [
+        "art_defaults",
+        "libart-compiler_static_defaults",
+        "libart-dex2oat_static_defaults",
+        "libart-dexlayout_static_defaults",
+        "libart_static_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+        "libprofile_static_defaults",
+    ],
+}
+
 art_cc_library_static {
     name: "libartd-dex2oat",
     defaults: [
@@ -153,26 +168,27 @@
         "libartd_static_defaults",
         "libprofiled_static_defaults",
     ],
-    static_libs: [
+    whole_static_libs: [
         "libartd-compiler",
         "libartd-dexlayout",
         "libartd-dex2oat",
     ],
 }
 
-cc_library_headers {
-    name: "dex2oat_headers",
-    visibility: [
-        // TODO(b/133140750): Clean this up.
-        "//frameworks/native/cmds/installd",
-    ],
+art_cc_library_static {
+    name: "libdex2oatd_static",
+    device_supported: false,
     host_supported: true,
-    export_include_dirs: ["include"],
-
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.art.release",
-        "com.android.art.debug",
+    defaults: [
+        "art_debug_defaults",
+        "art_defaults",
+        "libartbased_static_defaults",
+        "libartd-compiler_static_defaults",
+        "libartd-dex2oat_static_defaults",
+        "libartd-dexlayout_static_defaults",
+        "libartd_static_defaults",
+        "libdexfiled_static_defaults",
+        "libprofiled_static_defaults",
     ],
 }
 
@@ -180,20 +196,29 @@
     name: "dex2oat-defaults",
     host_supported: true,
     defaults: ["art_defaults"],
+
     srcs: [
         "dex2oat_options.cc",
         "dex2oat.cc",
     ],
+    header_libs: [
+        "art_cmdlineparser_headers",
+    ],
 
     target: {
         android: {
             compile_multilib: "both",
+            shared_libs: [
+                "libartpalette",
+                "libbase",
+                "libcrypto",
+                "liblz4", // libart(d)-dex2oat dependency; must be repeated here since it's a static lib.
+                "liblog",
+                "libsigchain",
+                "libz",
+            ],
         },
     },
-    header_libs: [
-        "dex2oat_headers",
-        "art_cmdlineparser_headers",
-    ],
 }
 
 cc_defaults {
@@ -239,21 +264,6 @@
     // Modules that do dexpreopting, e.g. android_app, depend implicitly on
     // either dex2oat or dex2oatd in ART source builds.
     visibility: ["//visibility:public"],
-    shared_libs: [
-        "libprofile",
-        "libart-compiler",
-        "libart-dexlayout",
-        "libart",
-        "libcrypto",
-        "libdexfile",
-        "libartbase",
-        "libartpalette",
-        "libbase",
-        "libsigchain",
-    ],
-    static_libs: [
-        "libart-dex2oat",
-    ],
 
     multilib: {
         lib32: {
@@ -274,22 +284,31 @@
     },
     target: {
         android: {
+            shared_libs: [
+                "libart",
+                "libart-compiler",
+                "libart-dexlayout",
+                "libartbase",
+                "libdexfile",
+                "libprofile",
+            ],
+            static_libs: [
+                "libart-dex2oat",
+            ],
             lto: {
                 thin: true,
             },
-            static_libs: [
-                "libz",
-            ],
         },
         host: {
-            shared_libs: [
-                "libz",
-            ],
+            // Make the host binary static, except for system libraries. This
+            // avoids having to bundle host dynamic libs in prebuilts.
+            static_libs: ["libdex2oat_static"],
+            stl: "c++_static",
             // Override the prefer32 added by art_cc_binary when
             // HOST_PREFER_32_BIT is in use. Necessary because the logic in
             // Soong for setting ctx.Config().BuildOSTarget (used in
             // dexpreopt.RegisterToolDeps) doesn't take host prefer32 into
-            // account. Note that this override cannot be in cc_default because
+            // account. Note that this override cannot be in cc_defaults because
             // it'd get overridden by the load hook even when it uses
             // PrependProperties.
             compile_multilib: "64",
@@ -297,7 +316,7 @@
         },
     },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -311,36 +330,30 @@
     // Modules that do dexpreopting, e.g. android_app, depend implicitly on
     // either dex2oat or dex2oatd in ART source builds.
     visibility: ["//visibility:public"],
-    shared_libs: [
-        "libprofiled",
-        "libartd-compiler",
-        "libartd-dexlayout",
-        "libartd",
-        "libcrypto",
-        "libdexfiled",
-        "libartbased",
-        "libartpalette",
-        "libbase",
-        "libsigchain",
-    ],
-    static_libs: [
-        "libartd-dex2oat",
-    ],
     target: {
         android: {
+            shared_libs: [
+                "libartbased",
+                "libartd",
+                "libartd-compiler",
+                "libartd-dexlayout",
+                "libdexfiled",
+                "libprofiled",
+            ],
             static_libs: [
-                "libz",
+                "libartd-dex2oat",
             ],
         },
         host: {
-            shared_libs: [
-                "libz",
-            ],
+            // Make the host binary static, except for system libraries. This
+            // avoids having to bundle host dynamic libs in prebuilts.
+            static_libs: ["libdex2oatd_static"],
+            stl: "c++_static",
             // Override the prefer32 added by art_cc_binary when
             // HOST_PREFER_32_BIT is in use. Necessary because the logic in
             // Soong for setting ctx.Config().BuildOSTarget (used in
             // dexpreopt.RegisterToolDeps) doesn't take host prefer32 into
-            // account. Note that this override cannot be in cc_default because
+            // account. Note that this override cannot be in cc_defaults because
             // it'd get overridden by the load hook even when it uses
             // PrependProperties.
             compile_multilib: "64",
@@ -381,25 +394,12 @@
         // Try to get rid of it.
         "-z muldefs",
     ],
-    static_libs: [
-        "libbase",
-        "libsigchain_dummy",
-        "libz",
-    ],
 }
 
 art_cc_binary {
     name: "dex2oats",
-    defaults: [
-        "dex2oats-defaults",
-        "libart_static_defaults",
-        "libart-compiler_static_defaults",
-        "libart-dexlayout_static_defaults",
-        "libartbase_static_defaults",
-        "libdexfile_static_defaults",
-        "libprofile_static_defaults",
-        "libart-dex2oat_static_defaults",
-    ],
+    defaults: ["dex2oats-defaults"],
+    static_libs: ["libdex2oat_static"],
 }
 
 art_cc_binary {
@@ -407,19 +407,8 @@
     defaults: [
         "art_debug_defaults",
         "dex2oats-defaults",
-        "libartd_static_defaults",
-        "libartd-compiler_static_defaults",
-        "libartd-dexlayout_static_defaults",
-        "libartbased_static_defaults",
-        "libdexfiled_static_defaults",
-        "libprofiled_static_defaults",
-        "libartd-dex2oat_static_defaults",
     ],
-    target: {
-        linux_glibc_x86_64: {
-            use_clang_lld: true,
-        },
-    },
+    static_libs: ["libdex2oatd_static"],
 }
 
 art_cc_library_static {
@@ -429,26 +418,72 @@
         "common_compiler_driver_test.cc",
     ],
     shared_libs: [
-        "libartd-compiler",
-        "libartd-disassembler",
         "libart-compiler-gtest",
         "libart-runtime-gtest",
+        "libart-compiler",
+        "libart-disassembler",
         "libbase",
+        "liblz4", // libart-dex2oat dependency; must be repeated here since it's a static lib.
+        "liblog",
+    ],
+    static_libs: [
+        "libart-dex2oat",
+    ],
+}
+
+art_cc_library_static {
+    name: "libartd-dex2oat-gtest",
+    defaults: ["libartd-gtest-defaults"],
+    srcs: [
+        "common_compiler_driver_test.cc",
+    ],
+    shared_libs: [
+        "libartd-compiler-gtest",
+        "libartd-runtime-gtest",
+        "libartd-compiler",
+        "libartd-disassembler",
+        "libbase",
+        "liblz4", // libartd-dex2oat dependency; must be repeated here since it's a static lib.
+        "liblog",
     ],
     static_libs: [
         "libartd-dex2oat",
     ],
 }
 
-art_cc_test {
-    name: "art_dex2oat_tests",
-    defaults: [
-        "art_gtest_defaults",
+art_cc_defaults {
+    name: "art_dex2oat_tests_defaults",
+    data: [
+        ":art-gtest-jars-AbstractMethod",
+        ":art-gtest-jars-DefaultMethods",
+        ":art-gtest-jars-DexToDexDecompiler",
+        ":art-gtest-jars-Dex2oatVdexPublicSdkDex",
+        ":art-gtest-jars-Dex2oatVdexTestDex",
+        ":art-gtest-jars-ImageLayoutA",
+        ":art-gtest-jars-ImageLayoutB",
+        ":art-gtest-jars-LinkageTest",
+        ":art-gtest-jars-Main",
+        ":art-gtest-jars-MainEmptyUncompressed",
+        ":art-gtest-jars-MainEmptyUncompressedAligned",
+        ":art-gtest-jars-MainStripped",
+        ":art-gtest-jars-MainUncompressedAligned",
+        ":art-gtest-jars-ManyMethods",
+        ":art-gtest-jars-MultiDex",
+        ":art-gtest-jars-MultiDexModifiedSecondary",
+        ":art-gtest-jars-MyClassNatives",
+        ":art-gtest-jars-Nested",
+        ":art-gtest-jars-ProfileTestMultiDex",
+        ":art-gtest-jars-StaticLeafMethods",
+        ":art-gtest-jars-Statics",
+        ":art-gtest-jars-StringLiterals",
+        ":art-gtest-jars-VerifierDeps",
+        ":art-gtest-jars-VerifierDepsMulti",
+        ":art-gtest-jars-VerifySoftFailDuringClinit",
     ],
     srcs: [
         "dex2oat_test.cc",
+        "dex2oat_vdex_test.cc",
         "dex2oat_image_test.cc",
-        "dex/dex_to_dex_decompiler_test.cc",
         "driver/compiler_driver_test.cc",
         "linker/elf_writer_test.cc",
         "linker/image_test.cc",
@@ -458,6 +493,11 @@
         "linker/oat_writer_test.cc",
         "verifier_deps_test.cc",
     ],
+    target: {
+        host: {
+            required: ["dex2oatd"],
+        },
+    },
 
     codegen: {
         arm: {
@@ -482,20 +522,55 @@
         },
     },
 
-    header_libs: ["dex2oat_headers"],
+    shared_libs: [
+        "libartpalette",
+        "libbase",
+        "libcrypto",
+        "liblz4", // libart(d)-dex2oat dependency; must be repeated here since it's a static lib.
+        "liblog",
+        "libsigchain",
+        "libziparchive",
+    ],
+}
+
+// Version of ART gtest `art_dex2oat_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
+art_cc_test {
+    name: "art_dex2oat_tests",
+    defaults: [
+        "art_gtest_defaults",
+        "art_dex2oat_tests_defaults",
+    ],
     shared_libs: [
         "libartbased",
         "libartd-compiler",
         "libartd-dexlayout",
-        "libartpalette",
-        "libbase",
-        "libcrypto",
         "libprofiled",
-        "libsigchain",
-        "libziparchive",
+    ],
+    static_libs: [
+        "libartd-dex2oat-gtest",
+        "libartd-dex2oat",
+        "libvixld",
+    ],
+}
+
+// Standalone version of ART gtest `art_dex2oat_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_dex2oat_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_dex2oat_tests_defaults",
+    ],
+    shared_libs: [
+        "libartbase",
+        "libart-compiler",
+        "libart-dexlayout",
+        "libprofile",
     ],
     static_libs: [
         "libart-dex2oat-gtest",
-        "libartd-dex2oat",
+        "libart-dex2oat",
+        "libvixl",
     ],
+    test_config: "art_standalone_dex2oat_tests.xml",
 }
diff --git a/dex2oat/art_standalone_dex2oat_tests.xml b/dex2oat/art_standalone_dex2oat_tests.xml
new file mode 100644
index 0000000..672066a
--- /dev/null
+++ b/dex2oat/art_standalone_dex2oat_tests.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs art_standalone_dex2oat_tests.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art_standalone_dex2oat_tests->/data/local/tmp/nativetest/art_standalone_dex2oat_tests" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art-gtest-jars-AbstractMethod.jar->/data/local/tmp/nativetest/art-gtest-jars-AbstractMethod.jar" />
+        <option name="push" value="art-gtest-jars-DefaultMethods.jar->/data/local/tmp/nativetest/art-gtest-jars-DefaultMethods.jar" />
+        <option name="push" value="art-gtest-jars-DexToDexDecompiler.jar->/data/local/tmp/nativetest/art-gtest-jars-DexToDexDecompiler.jar" />
+        <option name="push" value="art-gtest-jars-Dex2oatVdexPublicSdkDex.dex->/data/local/tmp/nativetest/art-gtest-jars-Dex2oatVdexPublicSdkDex.dex" />
+        <option name="push" value="art-gtest-jars-Dex2oatVdexTestDex.jar->/data/local/tmp/nativetest/art-gtest-jars-Dex2oatVdexTestDex.jar" />
+        <option name="push" value="art-gtest-jars-ImageLayoutA.jar->/data/local/tmp/nativetest/art-gtest-jars-ImageLayoutA.jar" />
+        <option name="push" value="art-gtest-jars-ImageLayoutB.jar->/data/local/tmp/nativetest/art-gtest-jars-ImageLayoutB.jar" />
+        <option name="push" value="art-gtest-jars-LinkageTest.dex->/data/local/tmp/nativetest/art-gtest-jars-LinkageTest.dex" />
+        <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/nativetest/art-gtest-jars-Main.jar" />
+        <option name="push" value="art-gtest-jars-MainEmptyUncompressed.jar->/data/local/tmp/nativetest/art-gtest-jars-MainEmptyUncompressed.jar" />
+        <option name="push" value="art-gtest-jars-MainEmptyUncompressedAligned.jar->/data/local/tmp/nativetest/art-gtest-jars-MainEmptyUncompressedAligned.jar" />
+        <option name="push" value="art-gtest-jars-MainStripped.jar->/data/local/tmp/nativetest/art-gtest-jars-MainStripped.jar" />
+        <option name="push" value="art-gtest-jars-MainUncompressedAligned.jar->/data/local/tmp/nativetest/art-gtest-jars-MainUncompressedAligned.jar" />
+        <option name="push" value="art-gtest-jars-ManyMethods.jar->/data/local/tmp/nativetest/art-gtest-jars-ManyMethods.jar" />
+        <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/nativetest/art-gtest-jars-MultiDex.jar" />
+        <option name="push" value="art-gtest-jars-MultiDexModifiedSecondary.jar->/data/local/tmp/nativetest/art-gtest-jars-MultiDexModifiedSecondary.jar" />
+        <option name="push" value="art-gtest-jars-MyClassNatives.jar->/data/local/tmp/nativetest/art-gtest-jars-MyClassNatives.jar" />
+        <option name="push" value="art-gtest-jars-Nested.jar->/data/local/tmp/nativetest/art-gtest-jars-Nested.jar" />
+        <option name="push" value="art-gtest-jars-ProfileTestMultiDex.jar->/data/local/tmp/nativetest/art-gtest-jars-ProfileTestMultiDex.jar" />
+        <option name="push" value="art-gtest-jars-StaticLeafMethods.jar->/data/local/tmp/nativetest/art-gtest-jars-StaticLeafMethods.jar" />
+        <option name="push" value="art-gtest-jars-Statics.jar->/data/local/tmp/nativetest/art-gtest-jars-Statics.jar" />
+        <option name="push" value="art-gtest-jars-StringLiterals.jar->/data/local/tmp/nativetest/art-gtest-jars-StringLiterals.jar" />
+        <option name="push" value="art-gtest-jars-VerifierDeps.dex->/data/local/tmp/nativetest/art-gtest-jars-VerifierDeps.dex" />
+        <option name="push" value="art-gtest-jars-VerifierDepsMulti.dex->/data/local/tmp/nativetest/art-gtest-jars-VerifierDepsMulti.dex" />
+        <option name="push" value="art-gtest-jars-VerifySoftFailDuringClinit.dex->/data/local/tmp/nativetest/art-gtest-jars-VerifySoftFailDuringClinit.dex" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/nativetest" />
+        <option name="module-name" value="art_standalone_dex2oat_tests" />
+        <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+        <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/dex2oat/common_compiler_driver_test.cc b/dex2oat/common_compiler_driver_test.cc
index db64fe4..1f62cd7 100644
--- a/dex2oat/common_compiler_driver_test.cc
+++ b/dex2oat/common_compiler_driver_test.cc
@@ -59,7 +59,6 @@
 void CommonCompilerDriverTest::SetDexFilesForOatFile(const std::vector<const DexFile*>& dex_files) {
   compiler_options_->dex_files_for_oat_file_ = dex_files;
   compiler_driver_->compiled_classes_.AddDexFiles(dex_files);
-  compiler_driver_->dex_to_dex_compiler_.SetDexFiles(dex_files);
 }
 
 void CommonCompilerDriverTest::ReserveImageSpace() {
diff --git a/dex2oat/dex/dex_to_dex_compiler.cc b/dex2oat/dex/dex_to_dex_compiler.cc
deleted file mode 100644
index de66c1e..0000000
--- a/dex2oat/dex/dex_to_dex_compiler.cc
+++ /dev/null
@@ -1,678 +0,0 @@
-/*
- * 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.
- */
-
-#include "dex_to_dex_compiler.h"
-
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-
-#include "art_field-inl.h"
-#include "art_method-inl.h"
-#include "base/logging.h"  // For VLOG
-#include "base/macros.h"
-#include "base/mutex.h"
-#include "compiled_method.h"
-#include "dex/bytecode_utils.h"
-#include "dex/class_accessor-inl.h"
-#include "dex/dex_file-inl.h"
-#include "dex/dex_instruction-inl.h"
-#include "dex_to_dex_decompiler.h"
-#include "driver/compiler_driver.h"
-#include "driver/compiler_options.h"
-#include "driver/dex_compilation_unit.h"
-#include "mirror/dex_cache.h"
-#include "quicken_info.h"
-#include "thread-current-inl.h"
-
-namespace art {
-namespace optimizer {
-
-using android::base::StringPrintf;
-
-// Controls quickening activation.
-const bool kEnableQuickening = true;
-// Control check-cast elision.
-const bool kEnableCheckCastEllision = true;
-
-// Holds the state for compiling a single method.
-struct DexToDexCompiler::CompilationState {
-  struct QuickenedInfo {
-    QuickenedInfo(uint32_t pc, uint16_t index) : dex_pc(pc), dex_member_index(index) {}
-
-    uint32_t dex_pc;
-    uint16_t dex_member_index;
-  };
-
-  CompilationState(DexToDexCompiler* compiler,
-                   const DexCompilationUnit& unit,
-                   const CompilationLevel compilation_level,
-                   const std::vector<uint8_t>* quicken_data);
-
-  const std::vector<QuickenedInfo>& GetQuickenedInfo() const {
-    return quickened_info_;
-  }
-
-  // Returns the quickening info, or an empty array if it was not quickened.
-  // If already_quickened is true, then don't change anything but still return what the quicken
-  // data would have been.
-  std::vector<uint8_t> Compile();
-
-  const DexFile& GetDexFile() const;
-
-  // Compiles a RETURN-VOID into a RETURN-VOID-BARRIER within a constructor where
-  // a barrier is required.
-  void CompileReturnVoid(Instruction* inst, uint32_t dex_pc);
-
-  // Compiles a CHECK-CAST into 2 NOP instructions if it is known to be safe. In
-  // this case, returns the second NOP instruction pointer. Otherwise, returns
-  // the given "inst".
-  Instruction* CompileCheckCast(Instruction* inst, uint32_t dex_pc);
-
-  // Compiles a field access into a quick field access.
-  // The field index is replaced by an offset within an Object where we can read
-  // from / write to this field. Therefore, this does not involve any resolution
-  // at runtime.
-  // Since the field index is encoded with 16 bits, we can replace it only if the
-  // field offset can be encoded with 16 bits too.
-  void CompileInstanceFieldAccess(Instruction* inst, uint32_t dex_pc,
-                                  Instruction::Code new_opcode, bool is_put);
-
-  // Compiles a virtual method invocation into a quick virtual method invocation.
-  // The method index is replaced by the vtable index where the corresponding
-  // executable can be found. Therefore, this does not involve any resolution
-  // at runtime.
-  // Since the method index is encoded with 16 bits, we can replace it only if the
-  // vtable index can be encoded with 16 bits too.
-  void CompileInvokeVirtual(Instruction* inst, uint32_t dex_pc,
-                            Instruction::Code new_opcode, bool is_range);
-
-  // Return the next index.
-  uint16_t NextIndex();
-
-  // Returns the dequickened index if an instruction is quickened, otherwise return index.
-  uint16_t GetIndexForInstruction(const Instruction* inst, uint32_t index);
-
-  DexToDexCompiler* const compiler_;
-  CompilerDriver& driver_;
-  const DexCompilationUnit& unit_;
-  const CompilationLevel compilation_level_;
-
-  // Filled by the compiler when quickening, in order to encode that information
-  // in the .oat file. The runtime will use that information to get to the original
-  // opcodes.
-  std::vector<QuickenedInfo> quickened_info_;
-
-  // True if we optimized a return void to a return void no barrier.
-  bool optimized_return_void_ = false;
-
-  // If the code item was already quickened previously.
-  const bool already_quickened_;
-  const QuickenInfoTable existing_quicken_info_;
-  uint32_t quicken_index_ = 0u;
-
-  DISALLOW_COPY_AND_ASSIGN(CompilationState);
-};
-
-DexToDexCompiler::DexToDexCompiler(CompilerDriver* driver)
-    : driver_(driver),
-      lock_("Quicken lock", kDexToDexCompilerLock) {
-  DCHECK(driver != nullptr);
-}
-
-void DexToDexCompiler::ClearState() {
-  MutexLock lock(Thread::Current(), lock_);
-  active_dex_file_ = nullptr;
-  active_bit_vector_ = nullptr;
-  should_quicken_.clear();
-  shared_code_item_quicken_info_.clear();
-}
-
-size_t DexToDexCompiler::NumCodeItemsToQuicken(Thread* self) const {
-  MutexLock lock(self, lock_);
-  return num_code_items_;
-}
-
-BitVector* DexToDexCompiler::GetOrAddBitVectorForDex(const DexFile* dex_file) {
-  if (active_dex_file_ != dex_file) {
-    active_dex_file_ = dex_file;
-    auto inserted = should_quicken_.emplace(dex_file,
-                                            BitVector(dex_file->NumMethodIds(),
-                                                      /*expandable*/ false,
-                                                      Allocator::GetMallocAllocator()));
-    active_bit_vector_ = &inserted.first->second;
-  }
-  return active_bit_vector_;
-}
-
-void DexToDexCompiler::MarkForCompilation(Thread* self,
-                                          const MethodReference& method_ref) {
-  MutexLock lock(self, lock_);
-  BitVector* const bitmap = GetOrAddBitVectorForDex(method_ref.dex_file);
-  DCHECK(bitmap != nullptr);
-  DCHECK(!bitmap->IsBitSet(method_ref.index));
-  bitmap->SetBit(method_ref.index);
-  ++num_code_items_;
-}
-
-DexToDexCompiler::CompilationState::CompilationState(DexToDexCompiler* compiler,
-                                                     const DexCompilationUnit& unit,
-                                                     const CompilationLevel compilation_level,
-                                                     const std::vector<uint8_t>* quicken_data)
-    : compiler_(compiler),
-      driver_(*compiler->GetDriver()),
-      unit_(unit),
-      compilation_level_(compilation_level),
-      already_quickened_(quicken_data != nullptr),
-      existing_quicken_info_(already_quickened_
-          ? ArrayRef<const uint8_t>(*quicken_data) : ArrayRef<const uint8_t>()) {}
-
-uint16_t DexToDexCompiler::CompilationState::NextIndex() {
-  DCHECK(already_quickened_);
-  if (kIsDebugBuild && quicken_index_ >= existing_quicken_info_.NumIndices()) {
-    for (const DexInstructionPcPair& pair : unit_.GetCodeItemAccessor()) {
-      LOG(ERROR) << pair->DumpString(nullptr);
-    }
-    LOG(FATAL) << "Mismatched number of quicken slots.";
-  }
-  const uint16_t ret = existing_quicken_info_.GetData(quicken_index_);
-  quicken_index_++;
-  return ret;
-}
-
-uint16_t DexToDexCompiler::CompilationState::GetIndexForInstruction(const Instruction* inst,
-                                                                    uint32_t index) {
-  if (UNLIKELY(already_quickened_)) {
-    return inst->IsQuickened() ? NextIndex() : index;
-  }
-  DCHECK(!inst->IsQuickened());
-  return index;
-}
-
-bool DexToDexCompiler::ShouldCompileMethod(const MethodReference& ref) {
-  // TODO: It's probably safe to avoid the lock here if the active_dex_file_ matches since we only
-  // only call ShouldCompileMethod on one dex at a time.
-  MutexLock lock(Thread::Current(), lock_);
-  return GetOrAddBitVectorForDex(ref.dex_file)->IsBitSet(ref.index);
-}
-
-std::vector<uint8_t> DexToDexCompiler::CompilationState::Compile() {
-  DCHECK_EQ(compilation_level_, CompilationLevel::kOptimize);
-  const CodeItemDataAccessor& instructions = unit_.GetCodeItemAccessor();
-  for (DexInstructionIterator it = instructions.begin(); it != instructions.end(); ++it) {
-    const uint32_t dex_pc = it.DexPc();
-    Instruction* inst = const_cast<Instruction*>(&it.Inst());
-
-    if (!already_quickened_) {
-      DCHECK(!inst->IsQuickened());
-    }
-
-    switch (inst->Opcode()) {
-      case Instruction::RETURN_VOID:
-        CompileReturnVoid(inst, dex_pc);
-        break;
-
-      case Instruction::CHECK_CAST:
-        inst = CompileCheckCast(inst, dex_pc);
-        if (inst->Opcode() == Instruction::NOP) {
-          // We turned the CHECK_CAST into two NOPs, avoid visiting the second NOP twice since this
-          // would add 2 quickening info entries.
-          ++it;
-        }
-        break;
-
-      case Instruction::IGET:
-      case Instruction::IGET_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_QUICK, false);
-        break;
-
-      case Instruction::IGET_WIDE:
-      case Instruction::IGET_WIDE_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_WIDE_QUICK, false);
-        break;
-
-      case Instruction::IGET_OBJECT:
-      case Instruction::IGET_OBJECT_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_OBJECT_QUICK, false);
-        break;
-
-      case Instruction::IGET_BOOLEAN:
-      case Instruction::IGET_BOOLEAN_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_BOOLEAN_QUICK, false);
-        break;
-
-      case Instruction::IGET_BYTE:
-      case Instruction::IGET_BYTE_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_BYTE_QUICK, false);
-        break;
-
-      case Instruction::IGET_CHAR:
-      case Instruction::IGET_CHAR_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_CHAR_QUICK, false);
-        break;
-
-      case Instruction::IGET_SHORT:
-      case Instruction::IGET_SHORT_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_SHORT_QUICK, false);
-        break;
-
-      case Instruction::IPUT:
-      case Instruction::IPUT_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_QUICK, true);
-        break;
-
-      case Instruction::IPUT_BOOLEAN:
-      case Instruction::IPUT_BOOLEAN_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_BOOLEAN_QUICK, true);
-        break;
-
-      case Instruction::IPUT_BYTE:
-      case Instruction::IPUT_BYTE_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_BYTE_QUICK, true);
-        break;
-
-      case Instruction::IPUT_CHAR:
-      case Instruction::IPUT_CHAR_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_CHAR_QUICK, true);
-        break;
-
-      case Instruction::IPUT_SHORT:
-      case Instruction::IPUT_SHORT_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_SHORT_QUICK, true);
-        break;
-
-      case Instruction::IPUT_WIDE:
-      case Instruction::IPUT_WIDE_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_WIDE_QUICK, true);
-        break;
-
-      case Instruction::IPUT_OBJECT:
-      case Instruction::IPUT_OBJECT_QUICK:
-        CompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_OBJECT_QUICK, true);
-        break;
-
-      case Instruction::INVOKE_VIRTUAL:
-      case Instruction::INVOKE_VIRTUAL_QUICK:
-        CompileInvokeVirtual(inst, dex_pc, Instruction::INVOKE_VIRTUAL_QUICK, false);
-        break;
-
-      case Instruction::INVOKE_VIRTUAL_RANGE:
-      case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
-        CompileInvokeVirtual(inst, dex_pc, Instruction::INVOKE_VIRTUAL_RANGE_QUICK, true);
-        break;
-
-      case Instruction::NOP:
-        if (already_quickened_) {
-          const uint16_t reference_index = NextIndex();
-          quickened_info_.push_back(QuickenedInfo(dex_pc, reference_index));
-          if (reference_index == DexFile::kDexNoIndex16) {
-            // This means it was a normal nop and not a check-cast.
-            break;
-          }
-          const uint16_t type_index = NextIndex();
-          if (driver_.IsSafeCast(&unit_, dex_pc)) {
-            quickened_info_.push_back(QuickenedInfo(dex_pc, type_index));
-          }
-          ++it;
-        } else {
-          // We need to differentiate between check cast inserted NOP and normal NOP, put an invalid
-          // index in the map for normal nops. This should be rare in real code.
-          quickened_info_.push_back(QuickenedInfo(dex_pc, DexFile::kDexNoIndex16));
-        }
-        break;
-
-      default:
-        // Nothing to do.
-        break;
-    }
-  }
-
-  if (already_quickened_) {
-    DCHECK_EQ(quicken_index_, existing_quicken_info_.NumIndices());
-  }
-
-  // Even if there are no indices, generate an empty quicken info so that we know the method was
-  // quickened.
-
-  std::vector<uint8_t> quicken_data;
-  if (kIsDebugBuild) {
-    // Double check that the counts line up with the size of the quicken info.
-    size_t quicken_count = 0;
-    for (const DexInstructionPcPair& pair : instructions) {
-      if (QuickenInfoTable::NeedsIndexForInstruction(&pair.Inst())) {
-        ++quicken_count;
-      }
-    }
-    CHECK_EQ(quicken_count, GetQuickenedInfo().size());
-  }
-
-  QuickenInfoTable::Builder builder(&quicken_data, GetQuickenedInfo().size());
-  // Length is encoded by the constructor.
-  for (const CompilationState::QuickenedInfo& info : GetQuickenedInfo()) {
-    // Dex pc is not serialized, only used for checking the instructions. Since we access the
-    // array based on the index of the quickened instruction, the indexes must line up perfectly.
-    // The reader side uses the NeedsIndexForInstruction function too.
-    const Instruction& inst = instructions.InstructionAt(info.dex_pc);
-    CHECK(QuickenInfoTable::NeedsIndexForInstruction(&inst)) << inst.Opcode();
-    builder.AddIndex(info.dex_member_index);
-  }
-  DCHECK(!quicken_data.empty());
-  return quicken_data;
-}
-
-void DexToDexCompiler::CompilationState::CompileReturnVoid(Instruction* inst, uint32_t dex_pc) {
-  DCHECK_EQ(inst->Opcode(), Instruction::RETURN_VOID);
-  if (unit_.IsConstructor()) {
-    // Are we compiling a non clinit constructor which needs a barrier ?
-    if (!unit_.IsStatic() && unit_.RequiresConstructorBarrier()) {
-      return;
-    }
-  }
-  // Replace RETURN_VOID by RETURN_VOID_NO_BARRIER.
-  VLOG(compiler) << "Replacing " << Instruction::Name(inst->Opcode())
-                 << " by " << Instruction::Name(Instruction::RETURN_VOID_NO_BARRIER)
-                 << " at dex pc " << StringPrintf("0x%x", dex_pc) << " in method "
-                 << GetDexFile().PrettyMethod(unit_.GetDexMethodIndex(), true);
-  inst->SetOpcode(Instruction::RETURN_VOID_NO_BARRIER);
-  optimized_return_void_ = true;
-}
-
-Instruction* DexToDexCompiler::CompilationState::CompileCheckCast(Instruction* inst,
-                                                                  uint32_t dex_pc) {
-  if (!kEnableCheckCastEllision) {
-    return inst;
-  }
-  if (!driver_.IsSafeCast(&unit_, dex_pc)) {
-    return inst;
-  }
-  // Ok, this is a safe cast. Since the "check-cast" instruction size is 2 code
-  // units and a "nop" instruction size is 1 code unit, we need to replace it by
-  // 2 consecutive NOP instructions.
-  // Because the caller loops over instructions by calling Instruction::Next onto
-  // the current instruction, we need to return the 2nd NOP instruction. Indeed,
-  // its next instruction is the former check-cast's next instruction.
-  VLOG(compiler) << "Removing " << Instruction::Name(inst->Opcode())
-                 << " by replacing it with 2 NOPs at dex pc "
-                 << StringPrintf("0x%x", dex_pc) << " in method "
-                 << GetDexFile().PrettyMethod(unit_.GetDexMethodIndex(), true);
-  if (!already_quickened_) {
-    quickened_info_.push_back(QuickenedInfo(dex_pc, inst->VRegA_21c()));
-    quickened_info_.push_back(QuickenedInfo(dex_pc, inst->VRegB_21c()));
-
-    // We are modifying 4 consecutive bytes.
-    inst->SetOpcode(Instruction::NOP);
-    inst->SetVRegA_10x(0u);  // keep compliant with verifier.
-    // Get to next instruction which is the second half of check-cast and replace
-    // it by a NOP.
-    inst = const_cast<Instruction*>(inst->Next());
-    inst->SetOpcode(Instruction::NOP);
-    inst->SetVRegA_10x(0u);  // keep compliant with verifier.
-  }
-  return inst;
-}
-
-void DexToDexCompiler::CompilationState::CompileInstanceFieldAccess(Instruction* inst,
-                                                                    uint32_t dex_pc,
-                                                                    Instruction::Code new_opcode,
-                                                                    bool is_put) {
-  if (!kEnableQuickening) {
-    return;
-  }
-  uint32_t field_idx = GetIndexForInstruction(inst, inst->VRegC_22c());
-  MemberOffset field_offset(0u);
-  bool is_volatile;
-  bool fast_path = driver_.ComputeInstanceFieldInfo(field_idx, &unit_, is_put,
-                                                    &field_offset, &is_volatile);
-  if (fast_path && !is_volatile && IsUint<16>(field_offset.Int32Value())) {
-    VLOG(compiler) << "Quickening " << Instruction::Name(inst->Opcode())
-                   << " to " << Instruction::Name(new_opcode)
-                   << " by replacing field index " << field_idx
-                   << " by field offset " << field_offset.Int32Value()
-                   << " at dex pc " << StringPrintf("0x%x", dex_pc) << " in method "
-                   << GetDexFile().PrettyMethod(unit_.GetDexMethodIndex(), true);
-    if (!already_quickened_) {
-      // We are modifying 4 consecutive bytes.
-      inst->SetOpcode(new_opcode);
-      // Replace field index by field offset.
-      inst->SetVRegC_22c(static_cast<uint16_t>(field_offset.Int32Value()));
-    }
-    quickened_info_.push_back(QuickenedInfo(dex_pc, field_idx));
-  }
-}
-
-const DexFile& DexToDexCompiler::CompilationState::GetDexFile() const {
-  return *unit_.GetDexFile();
-}
-
-void DexToDexCompiler::CompilationState::CompileInvokeVirtual(Instruction* inst,
-                                                              uint32_t dex_pc,
-                                                              Instruction::Code new_opcode,
-                                                              bool is_range) {
-  if (!kEnableQuickening) {
-    return;
-  }
-  uint32_t method_idx = GetIndexForInstruction(inst,
-                                               is_range ? inst->VRegB_3rc() : inst->VRegB_35c());
-  ScopedObjectAccess soa(Thread::Current());
-
-  ClassLinker* class_linker = unit_.GetClassLinker();
-  ArtMethod* resolved_method =
-      class_linker->ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
-          method_idx,
-          unit_.GetDexCache(),
-          unit_.GetClassLoader(),
-          /* referrer= */ nullptr,
-          kVirtual);
-
-  if (UNLIKELY(resolved_method == nullptr)) {
-    // Clean up any exception left by type resolution.
-    soa.Self()->ClearException();
-    return;
-  }
-
-  uint32_t vtable_idx = resolved_method->GetMethodIndex();
-  DCHECK(IsUint<16>(vtable_idx));
-  VLOG(compiler) << "Quickening " << Instruction::Name(inst->Opcode())
-                 << "(" << GetDexFile().PrettyMethod(method_idx, true) << ")"
-                 << " to " << Instruction::Name(new_opcode)
-                 << " by replacing method index " << method_idx
-                 << " by vtable index " << vtable_idx
-                 << " at dex pc " << StringPrintf("0x%x", dex_pc) << " in method "
-                 << GetDexFile().PrettyMethod(unit_.GetDexMethodIndex(), true);
-  if (!already_quickened_) {
-    // We are modifying 4 consecutive bytes.
-    inst->SetOpcode(new_opcode);
-    // Replace method index by vtable index.
-    if (is_range) {
-      inst->SetVRegB_3rc(static_cast<uint16_t>(vtable_idx));
-    } else {
-      inst->SetVRegB_35c(static_cast<uint16_t>(vtable_idx));
-    }
-  }
-  quickened_info_.push_back(QuickenedInfo(dex_pc, method_idx));
-}
-
-CompiledMethod* DexToDexCompiler::CompileMethod(
-    const dex::CodeItem* code_item,
-    uint32_t access_flags,
-    InvokeType invoke_type ATTRIBUTE_UNUSED,
-    uint16_t class_def_idx,
-    uint32_t method_idx,
-    Handle<mirror::ClassLoader> class_loader,
-    const DexFile& dex_file,
-    CompilationLevel compilation_level) {
-  if (compilation_level == CompilationLevel::kDontDexToDexCompile) {
-    return nullptr;
-  }
-
-  ScopedObjectAccess soa(Thread::Current());
-  StackHandleScope<1> hs(soa.Self());
-  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
-  art::DexCompilationUnit unit(
-      class_loader,
-      class_linker,
-      dex_file,
-      code_item,
-      class_def_idx,
-      method_idx,
-      access_flags,
-      driver_->GetCompilerOptions().GetVerifiedMethod(&dex_file, method_idx),
-      hs.NewHandle(class_linker->FindDexCache(soa.Self(), dex_file)));
-
-  std::vector<uint8_t> quicken_data;
-  // If the code item is shared with multiple different method ids, make sure that we quicken only
-  // once and verify that all the dequicken maps match.
-  if (UNLIKELY(shared_code_items_.find(code_item) != shared_code_items_.end())) {
-    // Avoid quickening the shared code items for now because the existing conflict detection logic
-    // does not currently handle cases where the code item is quickened in one place but
-    // compiled in another.
-    static constexpr bool kAvoidQuickeningSharedCodeItems = true;
-    if (kAvoidQuickeningSharedCodeItems) {
-      return nullptr;
-    }
-    // For shared code items, use a lock to prevent races.
-    MutexLock mu(soa.Self(), lock_);
-    auto existing = shared_code_item_quicken_info_.find(code_item);
-    QuickenState* existing_data = nullptr;
-    std::vector<uint8_t>* existing_quicken_data = nullptr;
-    if (existing != shared_code_item_quicken_info_.end()) {
-      existing_data = &existing->second;
-      if (existing_data->conflict_) {
-        return nullptr;
-      }
-      existing_quicken_data = &existing_data->quicken_data_;
-    }
-    bool optimized_return_void;
-    {
-      CompilationState state(this, unit, compilation_level, existing_quicken_data);
-      quicken_data = state.Compile();
-      optimized_return_void = state.optimized_return_void_;
-    }
-
-    // Already quickened, check that the data matches what was previously seen.
-    MethodReference method_ref(&dex_file, method_idx);
-    if (existing_data != nullptr) {
-      if (*existing_quicken_data != quicken_data ||
-          existing_data->optimized_return_void_ != optimized_return_void) {
-        VLOG(compiler) << "Quicken data mismatch, for method "
-                       << dex_file.PrettyMethod(method_idx);
-        // Mark the method as a conflict to never attempt to quicken it in the future.
-        existing_data->conflict_ = true;
-      }
-      existing_data->methods_.push_back(method_ref);
-    } else {
-      QuickenState new_state;
-      new_state.methods_.push_back(method_ref);
-      new_state.quicken_data_ = quicken_data;
-      new_state.optimized_return_void_ = optimized_return_void;
-      bool inserted = shared_code_item_quicken_info_.emplace(code_item, new_state).second;
-      CHECK(inserted) << "Failed to insert " << dex_file.PrettyMethod(method_idx);
-    }
-
-    // Easy sanity check is to check that the existing stuff matches by re-quickening using the
-    // newly produced quicken data.
-    // Note that this needs to be behind the lock for this case since we may unquicken in another
-    // thread.
-    if (kIsDebugBuild) {
-      CompilationState state2(this, unit, compilation_level, &quicken_data);
-      std::vector<uint8_t> new_data = state2.Compile();
-      CHECK(new_data == quicken_data) << "Mismatch producing new quicken data";
-    }
-  } else {
-    CompilationState state(this, unit, compilation_level, /*quicken_data*/ nullptr);
-    quicken_data = state.Compile();
-
-    // Easy sanity check is to check that the existing stuff matches by re-quickening using the
-    // newly produced quicken data.
-    if (kIsDebugBuild) {
-      CompilationState state2(this, unit, compilation_level, &quicken_data);
-      std::vector<uint8_t> new_data = state2.Compile();
-      CHECK(new_data == quicken_data) << "Mismatch producing new quicken data";
-    }
-  }
-
-  if (quicken_data.empty()) {
-    return nullptr;
-  }
-
-  // Create a `CompiledMethod`, with the quickened information in the vmap table.
-  InstructionSet instruction_set = driver_->GetCompilerOptions().GetInstructionSet();
-  if (instruction_set == InstructionSet::kThumb2) {
-    // Don't use the thumb2 instruction set to avoid the one off code delta.
-    instruction_set = InstructionSet::kArm;
-  }
-  CompiledMethod* ret = CompiledMethod::SwapAllocCompiledMethod(
-      driver_->GetCompiledMethodStorage(),
-      instruction_set,
-      ArrayRef<const uint8_t>(),                   // no code
-      ArrayRef<const uint8_t>(quicken_data),       // vmap_table
-      ArrayRef<const uint8_t>(),                   // cfi data
-      ArrayRef<const linker::LinkerPatch>());
-  DCHECK(ret != nullptr);
-  return ret;
-}
-
-void DexToDexCompiler::SetDexFiles(const std::vector<const DexFile*>& dex_files) {
-  // Record what code items are already seen to detect when multiple methods have the same code
-  // item.
-  std::unordered_set<const dex::CodeItem*> seen_code_items;
-  for (const DexFile* dex_file : dex_files) {
-    for (ClassAccessor accessor : dex_file->GetClasses()) {
-      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
-        const dex::CodeItem* code_item = method.GetCodeItem();
-        // Detect the shared code items.
-        if (!seen_code_items.insert(code_item).second) {
-          shared_code_items_.insert(code_item);
-        }
-      }
-    }
-  }
-  VLOG(compiler) << "Shared code items " << shared_code_items_.size();
-}
-
-void DexToDexCompiler::UnquickenConflictingMethods() {
-  MutexLock mu(Thread::Current(), lock_);
-  size_t unquicken_count = 0;
-  for (const auto& pair : shared_code_item_quicken_info_) {
-    const dex::CodeItem* code_item = pair.first;
-    const QuickenState& state = pair.second;
-    CHECK_GE(state.methods_.size(), 1u);
-    if (state.conflict_) {
-      // Unquicken using the existing quicken data.
-      // TODO: Do we really need to pass a dex file in?
-      optimizer::ArtDecompileDEX(*state.methods_[0].dex_file,
-                                 *code_item,
-                                 ArrayRef<const uint8_t>(state.quicken_data_),
-                                 /* decompile_return_instruction*/ true);
-      ++unquicken_count;
-      // Go clear the vmaps for all the methods that were already quickened to avoid writing them
-      // out during oat writing.
-      for (const MethodReference& ref : state.methods_) {
-        CompiledMethod* method = driver_->RemoveCompiledMethod(ref);
-        if (method != nullptr) {
-          // There is up to one compiled method for each method ref. Releasing it leaves the
-          // deduped data intact, this means its safe to do even when other threads might be
-          // compiling.
-          CompiledMethod::ReleaseSwapAllocatedCompiledMethod(driver_->GetCompiledMethodStorage(),
-                                                             method);
-        }
-      }
-    }
-  }
-}
-
-}  // namespace optimizer
-
-}  // namespace art
diff --git a/dex2oat/dex/dex_to_dex_compiler.h b/dex2oat/dex/dex_to_dex_compiler.h
deleted file mode 100644
index 06e16e4..0000000
--- a/dex2oat/dex/dex_to_dex_compiler.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2015 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_DEX2OAT_DEX_DEX_TO_DEX_COMPILER_H_
-#define ART_DEX2OAT_DEX_DEX_TO_DEX_COMPILER_H_
-
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
-
-#include "base/bit_vector.h"
-#include "base/mutex.h"
-#include "dex/invoke_type.h"
-#include "dex/method_reference.h"
-#include "handle.h"
-#include "quicken_info.h"
-
-namespace art {
-
-class CompiledMethod;
-class CompilerDriver;
-class DexCompilationUnit;
-class DexFile;
-
-namespace dex {
-struct CodeItem;
-}  // namespace dex
-
-namespace mirror {
-class ClassLoader;
-}  // namespace mirror
-
-namespace optimizer {
-
-class DexToDexCompiler {
- public:
-  enum class CompilationLevel {
-    kDontDexToDexCompile,   // Only meaning wrt image time interpretation.
-    kOptimize               // Perform peep-hole optimizations.
-  };
-
-  explicit DexToDexCompiler(CompilerDriver* driver);
-
-  CompiledMethod* CompileMethod(const dex::CodeItem* code_item,
-                                uint32_t access_flags,
-                                InvokeType invoke_type,
-                                uint16_t class_def_idx,
-                                uint32_t method_idx,
-                                Handle<mirror::ClassLoader> class_loader,
-                                const DexFile& dex_file,
-                                const CompilationLevel compilation_level) WARN_UNUSED;
-
-  void MarkForCompilation(Thread* self,
-                          const MethodReference& method_ref);
-
-  void ClearState();
-
-  // Unquicken all methods that have conflicting quicken info. This is not done during the
-  // quickening process to avoid race conditions.
-  void UnquickenConflictingMethods();
-
-  CompilerDriver* GetDriver() {
-    return driver_;
-  }
-
-  bool ShouldCompileMethod(const MethodReference& ref);
-
-  // Return the number of code items to quicken.
-  size_t NumCodeItemsToQuicken(Thread* self) const;
-
-  void SetDexFiles(const std::vector<const DexFile*>& dex_files);
-
- private:
-  // Holds the state for compiling a single method.
-  struct CompilationState;
-
-  // Quicken state for a code item, may be referenced by multiple methods.
-  struct QuickenState {
-    std::vector<MethodReference> methods_;
-    std::vector<uint8_t> quicken_data_;
-    bool optimized_return_void_ = false;
-    bool conflict_ = false;
-  };
-
-  BitVector* GetOrAddBitVectorForDex(const DexFile* dex_file) REQUIRES(lock_);
-
-  CompilerDriver* const driver_;
-
-  // State for adding methods (should this be in its own class?).
-  const DexFile* active_dex_file_ = nullptr;
-  BitVector* active_bit_vector_ = nullptr;
-
-  // Lock that guards duplicate code items and the bitmap.
-  mutable Mutex lock_;
-  // Record what method references are going to get quickened.
-  std::unordered_map<const DexFile*, BitVector> should_quicken_;
-  // Guarded by lock_ during writing, accessed without a lock during quickening.
-  // This is safe because no thread is adding to the shared code items during the quickening phase.
-  std::unordered_set<const dex::CodeItem*> shared_code_items_;
-  // Blacklisted code items are unquickened in UnquickenConflictingMethods.
-  std::unordered_map<const dex::CodeItem*, QuickenState> shared_code_item_quicken_info_
-      GUARDED_BY(lock_);
-  // Number of added code items.
-  size_t num_code_items_ GUARDED_BY(lock_) = 0u;
-};
-
-std::ostream& operator<<(std::ostream& os, const DexToDexCompiler::CompilationLevel& rhs);
-
-}  // namespace optimizer
-
-}  // namespace art
-
-#endif  // ART_DEX2OAT_DEX_DEX_TO_DEX_COMPILER_H_
diff --git a/dex2oat/dex/dex_to_dex_decompiler_test.cc b/dex2oat/dex/dex_to_dex_decompiler_test.cc
deleted file mode 100644
index 9d65436..0000000
--- a/dex2oat/dex/dex_to_dex_decompiler_test.cc
+++ /dev/null
@@ -1,115 +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.
- */
-
-#include "dex_to_dex_decompiler.h"
-
-#include "base/casts.h"
-#include "class_linker.h"
-#include "common_compiler_driver_test.h"
-#include "compiled_method-inl.h"
-#include "compiler_callbacks.h"
-#include "dex/class_accessor-inl.h"
-#include "dex/dex_file.h"
-#include "driver/compiler_driver.h"
-#include "driver/compiler_options.h"
-#include "handle_scope-inl.h"
-#include "mirror/class_loader.h"
-#include "quick_compiler_callbacks.h"
-#include "runtime.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread.h"
-#include "verifier/verifier_deps.h"
-
-namespace art {
-
-class DexToDexDecompilerTest : public CommonCompilerDriverTest {
- public:
-  void CompileAll(jobject class_loader) REQUIRES(!Locks::mutator_lock_) {
-    TimingLogger timings("DexToDexDecompilerTest::CompileAll", false, false);
-    compiler_options_->image_type_ = CompilerOptions::ImageType::kNone;
-    compiler_options_->SetCompilerFilter(CompilerFilter::kQuicken);
-    // Create the main VerifierDeps, here instead of in the compiler since we want to aggregate
-    // the results for all the dex files, not just the results for the current dex file.
-    down_cast<QuickCompilerCallbacks*>(Runtime::Current()->GetCompilerCallbacks())->SetVerifierDeps(
-        new verifier::VerifierDeps(GetDexFiles(class_loader)));
-    std::vector<const DexFile*> dex_files = GetDexFiles(class_loader);
-    CommonCompilerDriverTest::CompileAll(class_loader, dex_files, &timings);
-  }
-
-  void RunTest(const char* dex_name) {
-    Thread* self = Thread::Current();
-    // First load the original dex file.
-    jobject original_class_loader;
-    {
-      ScopedObjectAccess soa(self);
-      original_class_loader = LoadDex(dex_name);
-    }
-    const DexFile* original_dex_file = GetDexFiles(original_class_loader)[0];
-
-    // Load the dex file again and make it writable to quicken them.
-    jobject class_loader;
-    const DexFile* updated_dex_file = nullptr;
-    {
-      ScopedObjectAccess soa(self);
-      class_loader = LoadDex(dex_name);
-      updated_dex_file = GetDexFiles(class_loader)[0];
-      Runtime::Current()->GetClassLinker()->RegisterDexFile(
-          *updated_dex_file, soa.Decode<mirror::ClassLoader>(class_loader));
-    }
-    // The dex files should be identical.
-    int cmp = memcmp(original_dex_file->Begin(),
-                     updated_dex_file->Begin(),
-                     updated_dex_file->Size());
-    ASSERT_EQ(0, cmp);
-
-    updated_dex_file->EnableWrite();
-    CompileAll(class_loader);
-    // The dex files should be different after quickening.
-    cmp = memcmp(original_dex_file->Begin(), updated_dex_file->Begin(), updated_dex_file->Size());
-    ASSERT_NE(0, cmp);
-
-    // Unquicken the dex file.
-    for (ClassAccessor accessor : updated_dex_file->GetClasses()) {
-      // Unquicken each method.
-      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
-        CompiledMethod* compiled_method = compiler_driver_->GetCompiledMethod(
-            method.GetReference());
-        ArrayRef<const uint8_t> table;
-        if (compiled_method != nullptr) {
-          table = compiled_method->GetVmapTable();
-        }
-        optimizer::ArtDecompileDEX(*updated_dex_file,
-                                   *accessor.GetCodeItem(method),
-                                   table,
-                                   /* decompile_return_instruction= */ true);
-      }
-    }
-
-    // Make sure after unquickening we go back to the same contents as the original dex file.
-    cmp = memcmp(original_dex_file->Begin(), updated_dex_file->Begin(), updated_dex_file->Size());
-    ASSERT_EQ(0, cmp);
-  }
-};
-
-TEST_F(DexToDexDecompilerTest, VerifierDeps) {
-  RunTest("VerifierDeps");
-}
-
-TEST_F(DexToDexDecompilerTest, DexToDexDecompiler) {
-  RunTest("DexToDexDecompiler");
-}
-
-}  // namespace art
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 5654894..84e4622 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -24,6 +24,7 @@
 #include <fstream>
 #include <iostream>
 #include <limits>
+#include <log/log.h>
 #include <sstream>
 #include <string>
 #include <type_traits>
@@ -40,6 +41,7 @@
 #include "android-base/parseint.h"
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
+#include "android-base/unique_fd.h"
 
 #include "aot_class_linker.h"
 #include "arch/instruction_set_features.h"
@@ -51,6 +53,7 @@
 #include "base/macros.h"
 #include "base/mutex.h"
 #include "base/os.h"
+#include "base/fast_exit.h"
 #include "base/scoped_flock.h"
 #include "base/stl_util.h"
 #include "base/time_utils.h"
@@ -71,7 +74,6 @@
 #include "dex/quick_compiler_callbacks.h"
 #include "dex/verification_results.h"
 #include "dex2oat_options.h"
-#include "dex2oat_return_codes.h"
 #include "dexlayout.h"
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
@@ -94,6 +96,7 @@
 #include "oat.h"
 #include "oat_file.h"
 #include "oat_file_assistant.h"
+#include "palette/palette.h"
 #include "profile/profile_compilation_info.h"
 #include "runtime.h"
 #include "runtime_options.h"
@@ -106,6 +109,14 @@
 
 namespace art {
 
+namespace dex2oat {
+  enum class ReturnCode : int {
+    kNoFailure = 0,          // No failure, execution completed successfully.
+    kOther = 1,              // Some other not closer specified error occurred.
+    kCreateRuntime = 2,      // Dex2oat failed creating a runtime.
+  };
+}  // namespace dex2oat
+
 using android::base::StringAppendV;
 using android::base::StringPrintf;
 using gc::space::ImageSpace;
@@ -223,304 +234,12 @@
 
   UsageError("Usage: dex2oat [options]...");
   UsageError("");
-  UsageError("  -j<number>: specifies the number of threads used for compilation.");
-  UsageError("       Default is the number of detected hardware threads available on the");
-  UsageError("       host system.");
-  UsageError("      Example: -j12");
-  UsageError("");
-  UsageError("  --cpu-set=<set>: sets the cpu affinity to <set>. The <set> argument is a comma");
-  UsageError("    separated list of CPUs.");
-  UsageError("    Example: --cpu-set=0,1,2,3");
-  UsageError("");
-  UsageError("  --dex-file=<dex-file>: specifies a .dex, .jar, or .apk file to compile.");
-  UsageError("      Example: --dex-file=/system/framework/core.jar");
-  UsageError("");
-  UsageError("  --dex-location=<dex-location>: specifies an alternative dex location to");
-  UsageError("      encode in the oat file for the corresponding --dex-file argument.");
-  UsageError("      Example: --dex-file=/home/build/out/system/framework/core.jar");
-  UsageError("               --dex-location=/system/framework/core.jar");
-  UsageError("");
-  UsageError("  --zip-fd=<file-descriptor>: specifies a file descriptor of a zip file");
-  UsageError("      containing a classes.dex file to compile.");
-  UsageError("      Example: --zip-fd=5");
-  UsageError("");
-  UsageError("  --zip-location=<zip-location>: specifies a symbolic name for the file");
-  UsageError("      corresponding to the file descriptor specified by --zip-fd.");
-  UsageError("      Example: --zip-location=/system/app/Calculator.apk");
-  UsageError("");
-  UsageError("  --oat-file=<file.oat>: specifies an oat output destination via a filename.");
-  UsageError("      Example: --oat-file=/system/framework/boot.oat");
-  UsageError("");
-  UsageError("  --oat-symbols=<file.oat>: specifies a symbolized oat output destination.");
-  UsageError("      Example: --oat-file=symbols/system/framework/boot.oat");
-  UsageError("");
-  UsageError("  --oat-fd=<number>: specifies the oat output destination via a file descriptor.");
-  UsageError("      Example: --oat-fd=6");
-  UsageError("");
-  UsageError("  --input-vdex-fd=<number>: specifies the vdex input source via a file descriptor.");
-  UsageError("      Example: --input-vdex-fd=6");
-  UsageError("");
-  UsageError("  --output-vdex-fd=<number>: specifies the vdex output destination via a file");
-  UsageError("      descriptor.");
-  UsageError("      Example: --output-vdex-fd=6");
-  UsageError("");
-  UsageError("  --oat-location=<oat-name>: specifies a symbolic name for the file corresponding");
-  UsageError("      to the file descriptor specified by --oat-fd.");
-  UsageError("      Example: --oat-location=/data/dalvik-cache/system@app@Calculator.apk.oat");
-  UsageError("");
-  UsageError("  --oat-symbols=<file.oat>: specifies a destination where the oat file is copied.");
-  UsageError("      This is equivalent to file copy as build post-processing step.");
-  UsageError("      It is intended to be used with --strip and it happens before it.");
-  UsageError("      Example: --oat-symbols=/symbols/system/framework/boot.oat");
-  UsageError("");
-  UsageError("  --strip: remove all debugging sections at the end (but keep mini-debug-info).");
-  UsageError("      This is equivalent to the \"strip\" command as build post-processing step.");
-  UsageError("      It is intended to be used with --oat-symbols and it happens after it.");
-  UsageError("      Example: --oat-symbols=/symbols/system/framework/boot.oat");
-  UsageError("");
-  UsageError("  --image=<file.art>: specifies an output image filename.");
-  UsageError("      Example: --image=/system/framework/boot.art");
-  UsageError("");
-  UsageError("  --image-fd=<number>: same as --image but accepts a file descriptor instead.");
-  UsageError("      Cannot be used together with --image.");
-  UsageError("");
-  UsageError("  --image-format=(uncompressed|lz4|lz4hc):");
-  UsageError("      Which format to store the image.");
-  UsageError("      Example: --image-format=lz4");
-  UsageError("      Default: uncompressed");
-  UsageError("");
-  UsageError("  --base=<hex-address>: specifies the base address when creating a boot image.");
-  UsageError("      Example: --base=0x50000000");
-  UsageError("");
-  UsageError("  --boot-image=<file.art>: provide the image file for the boot class path.");
-  UsageError("      Do not include the arch as part of the name, it is added automatically.");
-  UsageError("      Example: --boot-image=/system/framework/boot.art");
-  UsageError("               (specifies /system/framework/<arch>/boot.art as the image file)");
-  UsageError("      Example: --boot-image=boot.art:boot-framework.art");
-  UsageError("               (specifies <bcp-path1>/<arch>/boot.art as the image file and");
-  UsageError("               <bcp-path2>/<arch>/boot-framework.art as the image extension file");
-  UsageError("               with paths taken from corresponding boot class path components)");
-  UsageError("      Example: --boot-image=/apex/com.android.art/boot.art:/system/framework/*:*");
-  UsageError("               (specifies /apex/com.android.art/<arch>/boot.art as the image");
-  UsageError("               file and search for extensions in /framework/system and boot");
-  UsageError("               class path components' paths)");
-  UsageError("      Default: $ANDROID_ROOT/system/framework/boot.art");
-  UsageError("");
-  UsageError("  --android-root=<path>: used to locate libraries for portable linking.");
-  UsageError("      Example: --android-root=out/host/linux-x86");
-  UsageError("      Default: $ANDROID_ROOT");
-  UsageError("");
-  UsageError("  --instruction-set=(arm|arm64|x86|x86_64): compile for a particular");
-  UsageError("      instruction set.");
-  UsageError("      Example: --instruction-set=x86");
-  UsageError("      Default: arm");
-  UsageError("");
-  UsageError("  --instruction-set-features=...,: Specify instruction set features");
-  UsageError("      On target the value 'runtime' can be used to detect features at run time.");
-  UsageError("      If target does not support run-time detection the value 'runtime'");
-  UsageError("      has the same effect as the value 'default'.");
-  UsageError("      Note: the value 'runtime' has no effect if it is used on host.");
-  UsageError("      Example: --instruction-set-features=div");
-  UsageError("      Default: default");
-  UsageError("");
-  UsageError("  --compiler-backend=(Quick|Optimizing): select compiler backend");
-  UsageError("      set.");
-  UsageError("      Example: --compiler-backend=Optimizing");
-  UsageError("      Default: Optimizing");
-  UsageError("");
-  UsageError("  --compiler-filter="
-                "(assume-verified"
-                "|extract"
-                "|verify"
-                "|quicken"
-                "|space-profile"
-                "|space"
-                "|speed-profile"
-                "|speed"
-                "|everything-profile"
-                "|everything):");
-  UsageError("      select compiler filter.");
-  UsageError("      Example: --compiler-filter=everything");
-  UsageError("      Default: speed-profile if --profile-file or --profile-file-fd is used,");
-  UsageError("               speed otherwise");
-  UsageError("");
-  UsageError("  --huge-method-max=<method-instruction-count>: threshold size for a huge");
-  UsageError("      method for compiler filter tuning.");
-  UsageError("      Example: --huge-method-max=%d", CompilerOptions::kDefaultHugeMethodThreshold);
-  UsageError("      Default: %d", CompilerOptions::kDefaultHugeMethodThreshold);
-  UsageError("");
-  UsageError("  --large-method-max=<method-instruction-count>: threshold size for a large");
-  UsageError("      method for compiler filter tuning.");
-  UsageError("      Example: --large-method-max=%d", CompilerOptions::kDefaultLargeMethodThreshold);
-  UsageError("      Default: %d", CompilerOptions::kDefaultLargeMethodThreshold);
-  UsageError("");
-  UsageError("  --num-dex-methods=<method-count>: threshold size for a small dex file for");
-  UsageError("      compiler filter tuning. If the input has fewer than this many methods");
-  UsageError("      and the filter is not interpret-only or verify-none or verify-at-runtime, ");
-  UsageError("      overrides the filter to use speed");
-  UsageError("      Example: --num-dex-method=%d", CompilerOptions::kDefaultNumDexMethodsThreshold);
-  UsageError("      Default: %d", CompilerOptions::kDefaultNumDexMethodsThreshold);
-  UsageError("");
-  UsageError("  --inline-max-code-units=<code-units-count>: the maximum code units that a method");
-  UsageError("      can have to be considered for inlining. A zero value will disable inlining.");
-  UsageError("      Honored only by Optimizing. Has priority over the --compiler-filter option.");
-  UsageError("      Intended for development/experimental use.");
-  UsageError("      Example: --inline-max-code-units=%d",
-             CompilerOptions::kDefaultInlineMaxCodeUnits);
-  UsageError("      Default: %d", CompilerOptions::kDefaultInlineMaxCodeUnits);
-  UsageError("");
-  UsageError("  --dump-timings: display a breakdown of where time was spent");
-  UsageError("");
-  UsageError("  --dump-pass-timings: display a breakdown of time spent in optimization");
-  UsageError("      passes for each compiled method.");
-  UsageError("");
-  UsageError("  -g");
-  UsageError("  --generate-debug-info: Generate debug information for native debugging,");
-  UsageError("      such as stack unwinding information, ELF symbols and DWARF sections.");
-  UsageError("      If used without --debuggable, it will be best-effort only.");
-  UsageError("      This option does not affect the generated code. (disabled by default)");
-  UsageError("");
-  UsageError("  --no-generate-debug-info: Do not generate debug information for native debugging.");
-  UsageError("");
-  UsageError("  --generate-mini-debug-info: Generate minimal amount of LZMA-compressed");
-  UsageError("      debug information necessary to print backtraces. (disabled by default)");
-  UsageError("");
-  UsageError("  --no-generate-mini-debug-info: Do not generate backtrace info.");
-  UsageError("");
-  UsageError("  --generate-build-id: Generate GNU-compatible linker build ID ELF section with");
-  UsageError("      SHA-1 of the file content (and thus stable across identical builds)");
-  UsageError("");
-  UsageError("  --no-generate-build-id: Do not generate the build ID ELF section.");
-  UsageError("");
-  UsageError("  --debuggable: Produce code debuggable with Java debugger.");
-  UsageError("");
-  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.");
-  UsageError("      Example: --runtime-arg -Xms256m");
-  UsageError("");
-  UsageError("  --profile-file=<filename>: specify profiler output file to use for compilation.");
-  UsageError("");
-  UsageError("  --profile-file-fd=<number>: same as --profile-file but accepts a file descriptor.");
-  UsageError("      Cannot be used together with --profile-file.");
-  UsageError("");
-  UsageError("  --swap-file=<file-name>: specifies a file to use for swap.");
-  UsageError("      Example: --swap-file=/data/tmp/swap.001");
-  UsageError("");
-  UsageError("  --swap-fd=<file-descriptor>: specifies a file to use for swap (by descriptor).");
-  UsageError("      Example: --swap-fd=10");
-  UsageError("");
-  UsageError("  --swap-dex-size-threshold=<size>: specifies the minimum total dex file size in");
-  UsageError("      bytes to allow the use of swap.");
-  UsageError("      Example: --swap-dex-size-threshold=1000000");
-  UsageError("      Default: %zu", kDefaultMinDexFileCumulativeSizeForSwap);
-  UsageError("");
-  UsageError("  --swap-dex-count-threshold=<count>: specifies the minimum number of dex files to");
-  UsageError("      allow the use of swap.");
-  UsageError("      Example: --swap-dex-count-threshold=10");
-  UsageError("      Default: %zu", kDefaultMinDexFilesForSwap);
-  UsageError("");
-  UsageError("  --very-large-app-threshold=<size>: specifies the minimum total dex file size in");
-  UsageError("      bytes to consider the input \"very large\" and reduce compilation done.");
-  UsageError("      Example: --very-large-app-threshold=100000000");
-  UsageError("");
-  UsageError("  --app-image-fd=<file-descriptor>: specify output file descriptor for app image.");
-  UsageError("      The image is non-empty only if a profile is passed in.");
-  UsageError("      Example: --app-image-fd=10");
-  UsageError("");
-  UsageError("  --app-image-file=<file-name>: specify a file name for app image.");
-  UsageError("      Example: --app-image-file=/data/dalvik-cache/system@app@Calculator.apk.art");
-  UsageError("");
-  UsageError("  --multi-image: specify that separate oat and image files be generated for ");
-  UsageError("      each input dex file; the default for boot image and boot image extension.");
-  UsageError("");
-  UsageError("  --single-image: specify that a single oat and image file be generated for ");
-  UsageError("      all input dex files; the default for app image.");
-  UsageError("");
-  UsageError("  --force-determinism: force the compiler to emit a deterministic output.");
-  UsageError("");
-  UsageError("  --dump-cfg=<cfg-file>: dump control-flow graphs (CFGs) to specified file.");
-  UsageError("      Example: --dump-cfg=output.cfg");
-  UsageError("");
-  UsageError("  --dump-cfg-append: when dumping CFGs to an existing file, append new CFG data to");
-  UsageError("      existing data (instead of overwriting existing data with new data, which is");
-  UsageError("      the default behavior). This option is only meaningful when used with");
-  UsageError("      --dump-cfg.");
-  UsageError("");
-  UsageError("  --verbose-methods=<method-names>: Restrict dumped CFG data to methods whose name");
-  UsageError("      contain one of the method names passed as argument");
-  UsageError("      Example: --verbose-methods=toString,hashCode");
-  UsageError("");
-  UsageError("  --classpath-dir=<directory-path>: directory used to resolve relative class paths.");
-  UsageError("");
-  UsageError("  --class-loader-context=<string spec>: a string specifying the intended");
-  UsageError("      runtime loading context for the compiled dex files.");
-  UsageError("");
-  UsageError("  --stored-class-loader-context=<string spec>: a string specifying the intended");
-  UsageError("      runtime loading context that is stored in the oat file. Overrides");
-  UsageError("      --class-loader-context. Note that this ignores the classpath_dir arg.");
-  UsageError("");
-  UsageError("      It describes how the class loader chain should be built in order to ensure");
-  UsageError("      classes are resolved during dex2aot as they would be resolved at runtime.");
-  UsageError("      This spec will be encoded in the oat file. If at runtime the dex file is");
-  UsageError("      loaded in a different context, the oat file will be rejected.");
-  UsageError("");
-  UsageError("      The chain is interpreted in the natural 'parent order', meaning that class");
-  UsageError("      loader 'i+1' will be the parent of class loader 'i'.");
-  UsageError("      The compilation sources will be appended to the classpath of the first class");
-  UsageError("      loader.");
-  UsageError("");
-  UsageError("      E.g. if the context is 'PCL[lib1.dex];DLC[lib2.dex]' and ");
-  UsageError("      --dex-file=src.dex then dex2oat will setup a PathClassLoader with classpath ");
-  UsageError("      'lib1.dex:src.dex' and set its parent to a DelegateLastClassLoader with ");
-  UsageError("      classpath 'lib2.dex'.");
-  UsageError("");
-  UsageError("      Note that the compiler will be tolerant if the source dex files specified");
-  UsageError("      with --dex-file are found in the classpath. The source dex files will be");
-  UsageError("      removed from any class loader's classpath possibly resulting in empty");
-  UsageError("      class loaders.");
-  UsageError("");
-  UsageError("      Example: --class-loader-context=PCL[lib1.dex:lib2.dex];DLC[lib3.dex]");
-  UsageError("");
-  UsageError("  --class-loader-context-fds=<fds>: a colon-separated list of file descriptors");
-  UsageError("      for dex files in --class-loader-context. Their order must be the same as");
-  UsageError("      dex files in flattened class loader context.");
-  UsageError("");
-  UsageError("  --dirty-image-objects=<file-path>: list of known dirty objects in the image.");
-  UsageError("      The image writer will group them together.");
-  UsageError("");
-  UsageError("  --updatable-bcp-packages-file=<file-path>: file with a list of updatable");
-  UsageError("      boot class path packages. Classes in these packages and sub-packages");
-  UsageError("      shall not be resolved during app compilation to avoid AOT assumptions");
-  UsageError("      being invalidated after applying updates to these components.");
-  UsageError("");
-  UsageError("  --compact-dex-level=none|fast: None avoids generating compact dex, fast");
-  UsageError("      generates compact dex with low compile time. If speed-profile is specified as");
-  UsageError("      the compiler filter and the profile is not empty, the default compact dex");
-  UsageError("      level is always used.");
-  UsageError("");
-  UsageError("  --deduplicate-code=true|false: enable|disable code deduplication. Deduplicated");
-  UsageError("      code will have an arbitrary symbol tagged with [DEDUPED].");
-  UsageError("");
-  UsageError("  --copy-dex-files=true|false: enable|disable copying the dex files into the");
-  UsageError("      output vdex.");
-  UsageError("");
-  UsageError("  --compilation-reason=<string>: optional metadata specifying the reason for");
-  UsageError("      compiling the apk. If specified, the string will be embedded verbatim in");
-  UsageError("      the key value store of the oat file.");
-  UsageError("      Example: --compilation-reason=install");
-  UsageError("");
-  UsageError("  --resolve-startup-const-strings=true|false: If true, the compiler eagerly");
-  UsageError("      resolves strings referenced from const-string of startup methods.");
-  UsageError("");
-  UsageError("  --max-image-block-size=<size>: Maximum solid block size for compressed images.");
-  UsageError("");
+
+  std::stringstream oss;
+  VariableIndentationOutputStream vios(&oss);
+  auto parser = CreateDex2oatArgumentParser();
+  parser.DumpHelp(vios);
+  UsageError(oss.str().c_str());
   std::cerr << "See log for usage error information\n";
   exit(EXIT_FAILURE);
 }
@@ -774,6 +493,15 @@
   Handle<mirror::Object> old_field_value_;
 };
 
+class OatKeyValueStore : public SafeMap<std::string, std::string> {
+ public:
+  using SafeMap::Put;
+
+  iterator Put(const std::string& k, bool v) {
+    return SafeMap::Put(k, v ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+  }
+};
+
 class Dex2Oat final {
  public:
   explicit Dex2Oat(TimingLogger* timings) :
@@ -809,11 +537,15 @@
       opened_dex_files_maps_(),
       opened_dex_files_(),
       avoid_storing_invocation_(false),
-      swap_fd_(kInvalidFd),
-      app_image_fd_(kInvalidFd),
-      profile_file_fd_(kInvalidFd),
+      swap_fd_(File::kInvalidFd),
+      app_image_fd_(File::kInvalidFd),
+      profile_file_fd_(File::kInvalidFd),
       timings_(timings),
-      force_determinism_(false)
+      force_determinism_(false),
+      check_linkage_conditions_(false),
+      crash_on_linkage_violation_(false),
+      compile_individually_(false),
+      profile_load_attempted_(false)
       {}
 
   ~Dex2Oat() {
@@ -840,6 +572,12 @@
       verification_results_.release();  // NOLINT
       key_value_store_.release();       // NOLINT
     }
+
+    // Remind the user if they passed testing only flags.
+    if (!kIsTargetBuild && force_allow_oj_inlines_) {
+      LOG(ERROR) << "Inlines allowed from core-oj! FOR TESTING USE ONLY! DO NOT DISTRIBUTE"
+                  << " BINARIES BUILT WITH THIS OPTION!";
+    }
   }
 
   struct ParserOptions {
@@ -889,6 +627,7 @@
   }
 
   void ProcessOptions(ParserOptions* parser_options) {
+    compiler_options_->compiler_type_ = CompilerOptions::CompilerType::kAotCompiler;
     compiler_options_->compile_pic_ = true;  // All AOT compilation is PIC.
 
     if (android_root_.empty()) {
@@ -979,7 +718,8 @@
 
     if (!IsBootImage() && boot_image_filename_.empty()) {
       DCHECK(!IsBootImageExtension());
-      boot_image_filename_ = GetDefaultBootImageLocation(android_root_);
+      boot_image_filename_ =
+          GetDefaultBootImageLocation(android_root_, /*deny_art_apex_data_files=*/false);
     }
 
     if (dex_filenames_.empty() && zip_fd_ == -1) {
@@ -1040,7 +780,7 @@
     }
 
     const bool have_profile_file = !profile_file_.empty();
-    const bool have_profile_fd = profile_file_fd_ != kInvalidFd;
+    const bool have_profile_fd = profile_file_fd_ != File::kInvalidFd;
     if (have_profile_file && have_profile_fd) {
       Usage("Profile file should not be specified with both --profile-file-fd and --profile-file");
     }
@@ -1109,7 +849,7 @@
     }
 
     // Fill some values into the key-value store for the oat header.
-    key_value_store_.reset(new SafeMap<std::string, std::string>());
+    key_value_store_.reset(new OatKeyValueStore());
 
     // Automatically force determinism for the boot image and boot image extensions in a host build.
     if (!kIsTargetBuild && (IsBootImage() || IsBootImageExtension())) {
@@ -1117,6 +857,9 @@
     }
     compiler_options_->force_determinism_ = force_determinism_;
 
+    compiler_options_->check_linkage_conditions_ = check_linkage_conditions_;
+    compiler_options_->crash_on_linkage_violation_ = crash_on_linkage_violation_;
+
     if (passes_to_run_filename_ != nullptr) {
       passes_to_run_ = ReadCommentedInputFromFile<std::vector<std::string>>(
           passes_to_run_filename_,
@@ -1148,9 +891,6 @@
     }
 
     compiler_options_->passes_to_run_ = passes_to_run_.get();
-    compiler_options_->compiling_with_core_image_ =
-        !boot_image_filename_.empty() &&
-        CompilerOptions::IsCoreImageFilename(boot_image_filename_);
   }
 
   void ExpandOatAndImageFilenames() {
@@ -1198,16 +938,13 @@
       }
       key_value_store_->Put(OatHeader::kDex2OatCmdLineKey, oss.str());
     }
-    key_value_store_->Put(
-        OatHeader::kDebuggableKey,
-        compiler_options_->debuggable_ ? OatHeader::kTrueValue : OatHeader::kFalseValue);
-    key_value_store_->Put(
-        OatHeader::kNativeDebuggableKey,
-        compiler_options_->GetNativeDebuggable() ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+    key_value_store_->Put(OatHeader::kDebuggableKey, compiler_options_->debuggable_);
+    key_value_store_->Put(OatHeader::kNativeDebuggableKey,
+                          compiler_options_->GetNativeDebuggable());
     key_value_store_->Put(OatHeader::kCompilerFilter,
-        CompilerFilter::NameOfFilter(compiler_options_->GetCompilerFilter()));
-    key_value_store_->Put(OatHeader::kConcurrentCopying,
-                          kUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+                          CompilerFilter::NameOfFilter(compiler_options_->GetCompilerFilter()));
+    key_value_store_->Put(OatHeader::kConcurrentCopying, kUseReadBarrier);
+    key_value_store_->Put(OatHeader::kRequiresImage, compiler_options_->IsGeneratingImage());
     if (invocation_file_.get() != -1) {
       std::ostringstream oss;
       for (int i = 0; i < argc; ++i) {
@@ -1336,6 +1073,11 @@
     AssignIfExists(args, M::UpdatableBcpPackagesFile, &updatable_bcp_packages_filename_);
     AssignIfExists(args, M::ImageFormat, &image_storage_mode_);
     AssignIfExists(args, M::CompilationReason, &compilation_reason_);
+    AssignTrueIfExists(args, M::CheckLinkageConditions, &check_linkage_conditions_);
+    AssignTrueIfExists(args, M::CrashOnLinkageViolation, &crash_on_linkage_violation_);
+    AssignTrueIfExists(args, M::ForceAllowOjInlines, &force_allow_oj_inlines_);
+    AssignIfExists(args, M::PublicSdk, &public_sdk_);
+    AssignIfExists(args, M::ApexVersions, &apex_versions_argument_);
 
     AssignIfExists(args, M::Backend, &compiler_kind_);
     parser_options->requested_specific_compiler = args.Exists(M::Backend);
@@ -1366,6 +1108,7 @@
     if (args.Exists(M::ForceDeterminism)) {
       force_determinism_ = true;
     }
+    AssignTrueIfExists(args, M::CompileIndividually, &compile_individually_);
 
     if (args.Exists(M::Base)) {
       ParseBase(*args.Get(M::Base));
@@ -1419,7 +1162,7 @@
     // before reading compiler options.
     static_assert(CompilerFilter::kDefaultCompilerFilter == CompilerFilter::kSpeed);
     DCHECK_EQ(compiler_options_->GetCompilerFilter(), CompilerFilter::kSpeed);
-    if (UseProfile()) {
+    if (HasProfileInput()) {
       compiler_options_->SetCompilerFilter(CompilerFilter::kSpeedProfile);
     }
 
@@ -1428,9 +1171,6 @@
     }
 
     ProcessOptions(parser_options.get());
-
-    // Insert some compiler things.
-    InsertCompileOptions(argc, argv);
   }
 
   // Check whether the oat output files are writable, and open them for later. Also open a swap
@@ -1556,8 +1296,8 @@
     // the information to remain valid.
     if (update_input_vdex_) {
       File* vdex_file = vdex_files_.back().get();
-      if (!vdex_file->PwriteFully(&VdexFile::VerifierDepsHeader::kVdexInvalidMagic,
-                                  arraysize(VdexFile::VerifierDepsHeader::kVdexInvalidMagic),
+      if (!vdex_file->PwriteFully(&VdexFile::VdexFileHeader::kVdexInvalidMagic,
+                                  arraysize(VdexFile::VdexFileHeader::kVdexInvalidMagic),
                                   /*offset=*/ 0u)) {
         PLOG(ERROR) << "Failed to invalidate vdex header. File: " << vdex_file->GetPath();
         return false;
@@ -1600,7 +1340,21 @@
           LOG(WARNING) << "Could not open vdex file in DexMetadata archive: " << error_msg;
         } else {
           input_vdex_file_ = std::make_unique<VdexFile>(std::move(input_file));
-          VLOG(verifier) << "Doing fast verification with vdex from DexMetadata archive";
+          if (!input_vdex_file_->IsValid()) {
+            // Ideally we would do this validation at the framework level but the framework
+            // has not knowledge of the .vdex format and adding new APIs just for it is
+            // overkill.
+            // TODO(calin): include this in dex2oat metrics.
+            LOG(WARNING) << "The dex metadata .vdex is not valid. Ignoring it.";
+            input_vdex_file_ = nullptr;
+          } else {
+            if (input_vdex_file_->HasDexSection()) {
+              LOG(ERROR) << "The dex metadata is not allowed to contain dex files";
+              android_errorWriteLog(0x534e4554, "178055795");  // Report to SafetyNet.
+              return false;
+            }
+            VLOG(verifier) << "Doing fast verification with vdex from DexMetadata archive";
+          }
         }
       }
     }
@@ -1640,7 +1394,7 @@
     if (!IsImage()) {
       return;
     }
-    if (profile_compilation_info_ != nullptr) {
+    if (DoProfileGuidedOptimizations()) {
       // TODO: The following comment looks outdated or misplaced.
       // Filter out class path classes since we don't want to include these in the image.
       HashSet<std::string> image_classes = profile_compilation_info_->GetClassDescriptors(
@@ -1710,7 +1464,7 @@
             opened_dex_files_maps_.push_back(std::move(map));
           }
           for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
-            dex_file_oat_index_map_.emplace(dex_file.get(), i);
+            dex_file_oat_index_map_.insert(std::make_pair(dex_file.get(), i));
             opened_dex_files_.push_back(std::move(dex_file));
           }
         }
@@ -1720,6 +1474,10 @@
     compiler_options_->dex_files_for_oat_file_ = MakeNonOwningPointerVector(opened_dex_files_);
     const std::vector<const DexFile*>& dex_files = compiler_options_->dex_files_for_oat_file_;
 
+    if (!ValidateInputVdexChecksums()) {
+       return dex2oat::ReturnCode::kOther;
+    }
+
     // Check if we need to downgrade the compiler-filter for size reasons.
     // Note: This does not affect the compiler filter already stored in the key-value
     //       store which is used for determining whether the oat file is up to date,
@@ -1807,6 +1565,12 @@
         LOG(ERROR) << "Missing required boot image(s) for boot image extension.";
         return dex2oat::ReturnCode::kOther;
       }
+    } else {
+      // Check that we loaded at least the primary boot image for app compilation.
+      if (runtime_->GetHeap()->GetBootImageSpaces().empty()) {
+        LOG(ERROR) << "Missing primary boot image for app compilation.";
+        return dex2oat::ReturnCode::kOther;
+      }
     }
 
     if (!compilation_reason_.empty()) {
@@ -1846,6 +1610,11 @@
         key_value_store_->Put(
             OatHeader::kBootClassPathChecksumsKey,
             gc::space::ImageSpace::GetBootClassPathChecksums(image_spaces, bcp_dex_files));
+
+        std::string versions = apex_versions_argument_.empty()
+            ? runtime->GetApexVersions()
+            : apex_versions_argument_;
+        key_value_store_->Put(OatHeader::kApexVersionsKey, versions);
       }
 
       // Open dex files for class path.
@@ -1871,8 +1640,7 @@
       // (because the encoding adds the dex checksum...)
       // TODO(calin): consider redesigning this so we don't have to open the dex files before
       // creating the actual class loader.
-      if (!class_loader_context_->OpenDexFiles(runtime_->GetInstructionSet(),
-                                               classpath_dir_,
+      if (!class_loader_context_->OpenDexFiles(classpath_dir_,
                                                class_loader_context_fds_)) {
         // Do not abort if we couldn't open files from the classpath. They might be
         // apks without dex files and right now are opening flow will fail them.
@@ -1957,12 +1725,60 @@
       }
     }
 
+    // Setup VerifierDeps for compilation and report if we fail to parse the data.
+    if (!DoEagerUnquickeningOfVdex() && input_vdex_file_ != nullptr) {
+      std::unique_ptr<verifier::VerifierDeps> verifier_deps(
+          new verifier::VerifierDeps(dex_files, /*output_only=*/ false));
+      if (!verifier_deps->ParseStoredData(dex_files, input_vdex_file_->GetVerifierDepsData())) {
+        return dex2oat::ReturnCode::kOther;
+      }
+      callbacks_->SetVerifierDeps(verifier_deps.release());
+    } else {
+      // Create the main VerifierDeps, here instead of in the compiler since we want to aggregate
+      // the results for all the dex files, not just the results for the current dex file.
+      callbacks_->SetVerifierDeps(new verifier::VerifierDeps(dex_files));
+    }
+
     return dex2oat::ReturnCode::kNoFailure;
   }
 
+  // Validates that the input vdex checksums match the source dex checksums.
+  // Note that this is only effective and relevant if the input_vdex_file does not
+  // contain a dex section (e.g. when they come from .dm files).
+  // If the input vdex does contain dex files, the dex files will be opened from there
+  // and so this check is redundant.
+  bool ValidateInputVdexChecksums() {
+    if (input_vdex_file_ == nullptr) {
+      // Nothing to validate
+      return true;
+    }
+    if (input_vdex_file_->GetNumberOfDexFiles()
+          != compiler_options_->dex_files_for_oat_file_.size()) {
+      LOG(ERROR) << "Vdex file contains a different number of dex files than the source. "
+          << " vdex_num=" << input_vdex_file_->GetNumberOfDexFiles()
+          << " dex_source_num=" << compiler_options_->dex_files_for_oat_file_.size();
+      return false;
+    }
+
+    for (size_t i = 0; i < compiler_options_->dex_files_for_oat_file_.size(); i++) {
+      uint32_t dex_source_checksum =
+          compiler_options_->dex_files_for_oat_file_[i]->GetLocationChecksum();
+      uint32_t vdex_checksum = input_vdex_file_->GetLocationChecksum(i);
+      if (dex_source_checksum != vdex_checksum) {
+        LOG(ERROR) << "Vdex file checksum different than source dex checksum for position " << i
+          << std::hex
+          << " vdex_checksum=0x" << vdex_checksum
+          << " dex_source_checksum=0x" << dex_source_checksum
+          << std::dec;
+        return false;
+      }
+    }
+    return true;
+  }
+
   // If we need to keep the oat file open for the image writer.
   bool ShouldKeepOatFileOpen() const {
-    return IsImage() && oat_fd_ != kInvalidFd;
+    return IsImage() && oat_fd_ != File::kInvalidFd;
   }
 
   // Doesn't return the class loader since it's not meant to be used for image compilation.
@@ -1990,17 +1806,17 @@
   }
 
   bool ShouldCompileDexFilesIndividually() const {
-    // Compile individually if we are:
-    // 1. not building an image,
-    // 2. not verifying a vdex file,
-    // 3. using multidex,
+    // Compile individually if we are allowed to, and
+    // 1. not building an image, and
+    // 2. not verifying a vdex file, and
+    // 3. using multidex, and
     // 4. not doing any AOT compilation.
     // This means extract, no-vdex verify, and quicken, will use the individual compilation
     // mode (to reduce RAM used by the compiler).
-    return !IsImage() &&
-        !update_input_vdex_ &&
-        compiler_options_->dex_files_for_oat_file_.size() > 1 &&
-        !CompilerFilter::IsAotCompilationEnabled(compiler_options_->GetCompilerFilter());
+    return compile_individually_ &&
+           (!IsImage() && !update_input_vdex_ &&
+            compiler_options_->dex_files_for_oat_file_.size() > 1 &&
+            !CompilerFilter::IsAotCompilationEnabled(compiler_options_->GetCompilerFilter()));
   }
 
   uint32_t GetCombinedChecksums() const {
@@ -2024,7 +1840,12 @@
     // For now, on the host always have core-oj removed.
     const std::string core_oj = "core-oj";
     if (!kIsTargetBuild && !ContainsElement(no_inline_filters, core_oj)) {
-      no_inline_filters.push_back(core_oj);
+      if (force_allow_oj_inlines_) {
+        LOG(ERROR) << "Inlines allowed from core-oj! FOR TESTING USE ONLY! DO NOT DISTRIBUTE"
+                   << " BINARIES BUILT WITH THIS OPTION!";
+      } else {
+        no_inline_filters.push_back(core_oj);
+      }
     }
 
     if (!no_inline_filters.empty()) {
@@ -2093,25 +1914,6 @@
 
     // Setup vdex for compilation.
     const std::vector<const DexFile*>& dex_files = compiler_options_->dex_files_for_oat_file_;
-    if (!DoEagerUnquickeningOfVdex() && input_vdex_file_ != nullptr) {
-      callbacks_->SetVerifierDeps(
-          new verifier::VerifierDeps(dex_files, input_vdex_file_->GetVerifierDepsData()));
-
-      // TODO: we unquicken unconditionally, as we don't know
-      // if the boot image has changed. How exactly we'll know is under
-      // experimentation.
-      TimingLogger::ScopedTiming time_unquicken("Unquicken", timings_);
-
-      // We do not decompile a RETURN_VOID_NO_BARRIER into a RETURN_VOID, as the quickening
-      // optimization does not depend on the boot image (the optimization relies on not
-      // having final fields in a class, which does not change for an app).
-      input_vdex_file_->Unquicken(dex_files, /* decompile_return_instruction */ false);
-    } else {
-      // Create the main VerifierDeps, here instead of in the compiler since we want to aggregate
-      // the results for all the dex files, not just the results for the current dex file.
-      callbacks_->SetVerifierDeps(new verifier::VerifierDeps(dex_files));
-    }
-
     // To allow initialization of classes that construct ThreadLocal objects in class initializer,
     // re-initialize the ThreadLocal.nextHashCode to a new object that's not in the boot image.
     ThreadLocalHashOverride thread_local_hash_override(
@@ -2137,6 +1939,21 @@
     }
     if (!IsBootImage()) {
       callbacks_->SetDexFiles(&dex_files);
+
+      // We need to set this after we create the class loader so that the runtime can access
+      // the hidden fields of the well known class loaders.
+      if (!public_sdk_.empty()) {
+        std::string error_msg;
+        std::unique_ptr<SdkChecker> sdk_checker(SdkChecker::Create(public_sdk_, &error_msg));
+        if (sdk_checker != nullptr) {
+          AotClassLinker* aot_class_linker = down_cast<AotClassLinker*>(class_linker);
+          aot_class_linker->SetSdkChecker(std::move(sdk_checker));
+        } else {
+          LOG(FATAL) << "Failed to create SdkChecker with dex files "
+              << public_sdk_ << " Error: " << error_msg;
+          UNREACHABLE();
+        }
+      }
     }
 
     // Register dex caches and key them to the class loader so that they only unload when the
@@ -2261,11 +2078,7 @@
 
       // We need to prepare method offsets in the image address space for resolving linker patches.
       TimingLogger::ScopedTiming t2("dex2oat Prepare image address space", timings_);
-      // Do not preload dex caches for "assume-verified". This filter is used for in-memory
-      // compilation of boot image extension; in that scenario it is undesirable to use a lot
-      // of time to look up things now in hope it will be somewhat useful later.
-      bool preload_dex_caches = !compiler_options_->AssumeDexFilesAreVerified();
-      if (!image_writer_->PrepareImageAddressSpace(preload_dex_caches, timings_)) {
+      if (!image_writer_->PrepareImageAddressSpace(timings_)) {
         LOG(ERROR) << "Failed to prepare image address space.";
         return false;
       }
@@ -2285,23 +2098,8 @@
       verifier::VerifierDeps* verifier_deps = callbacks_->GetVerifierDeps();
       for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
         File* vdex_file = vdex_files_[i].get();
-        std::unique_ptr<BufferedOutputStream> vdex_out =
-            std::make_unique<BufferedOutputStream>(
-                std::make_unique<FileOutputStream>(vdex_file));
-
-        if (!oat_writers_[i]->WriteVerifierDeps(vdex_out.get(), verifier_deps)) {
-          LOG(ERROR) << "Failed to write verifier dependencies into VDEX " << vdex_file->GetPath();
-          return false;
-        }
-
-        if (!oat_writers_[i]->WriteQuickeningInfo(vdex_out.get())) {
-          LOG(ERROR) << "Failed to write quickening info into VDEX " << vdex_file->GetPath();
-          return false;
-        }
-
-        // VDEX finalized, seek back to the beginning and write checksums and the header.
-        if (!oat_writers_[i]->WriteChecksumsAndVdexHeader(vdex_out.get())) {
-          LOG(ERROR) << "Failed to write vdex header into VDEX " << vdex_file->GetPath();
+        if (!oat_writers_[i]->FinishVdexFile(vdex_file, verifier_deps)) {
+          LOG(ERROR) << "Failed to finish VDEX file " << vdex_file->GetPath();
           return false;
         }
       }
@@ -2427,12 +2225,16 @@
 
         TimingLogger::ScopedTiming t("dex2oat OatFile copy", timings_);
         std::unique_ptr<File>& in = oat_files_[i];
-        std::unique_ptr<File> out(OS::CreateEmptyFile(oat_unstripped_[i].c_str()));
         int64_t in_length = in->GetLength();
         if (in_length < 0) {
           PLOG(ERROR) << "Failed to get the length of oat file: " << in->GetPath();
           return false;
         }
+        std::unique_ptr<File> out(OS::CreateEmptyFile(oat_unstripped_[i].c_str()));
+        if (out == nullptr) {
+          PLOG(ERROR) << "Failed to open oat file for writing: " << oat_unstripped_[i];
+          return false;
+        }
         if (!out->Copy(in.get(), 0, in_length)) {
           PLOG(ERROR) << "Failed to copy oat file to file: " << out->GetPath();
           return false;
@@ -2524,12 +2326,16 @@
     return is_host_;
   }
 
-  bool UseProfile() const {
+  bool HasProfileInput() const {
     return profile_file_fd_ != -1 || !profile_file_.empty();
   }
 
+  // Must be called after the profile is loaded.
   bool DoProfileGuidedOptimizations() const {
-    return UseProfile();
+    DCHECK(!HasProfileInput() || profile_load_attempted_)
+        << "The profile has to be loaded before we can decided "
+        << "if we do profile guided optimizations";
+    return profile_compilation_info_ != nullptr && !profile_compilation_info_->IsEmpty();
   }
 
   bool DoGenerateCompactDex() const {
@@ -2555,24 +2361,29 @@
   }
 
   bool LoadProfile() {
-    DCHECK(UseProfile());
+    DCHECK(HasProfileInput());
+    profile_load_attempted_ = true;
     // TODO(calin): We should be using the runtime arena pool (instead of the
     // default profile arena). However the setup logic is messy and needs
     // cleaning up before that (e.g. the oat writers are created before the
     // runtime).
-    profile_compilation_info_.reset(new ProfileCompilationInfo());
-    ScopedFlock profile_file;
-    std::string error;
+    bool for_boot_image = IsBootImage() || IsBootImageExtension();
+    profile_compilation_info_.reset(new ProfileCompilationInfo(for_boot_image));
+    // Dex2oat only uses the reference profile and that is not updated concurrently by the app or
+    // other processes. So we don't need to lock (as we have to do in profman or when writing the
+    // profile info).
+    std::unique_ptr<File> profile_file;
     if (profile_file_fd_ != -1) {
-      profile_file = LockedFile::DupOf(profile_file_fd_, "profile",
-                                       true /* read_only_mode */, &error);
+      profile_file.reset(new File(DupCloexec(profile_file_fd_),
+                                  "profile",
+                                  /* check_usage= */ false,
+                                  /* read_only_mode= */ true));
     } else if (profile_file_ != "") {
-      profile_file = LockedFile::Open(profile_file_.c_str(), O_RDONLY, true, &error);
+      profile_file.reset(OS::OpenFileForReading(profile_file_.c_str()));
     }
 
-    // Return early if we're unable to obtain a lock on the profile.
     if (profile_file.get() == nullptr) {
-      LOG(ERROR) << "Cannot lock profiles: " << error;
+      PLOG(ERROR) << "Cannot lock profiles";
       return false;
     }
 
@@ -2584,6 +2395,95 @@
     return true;
   }
 
+  // If we're asked to speed-profile the app but we have no profile, or the profile
+  // is empty, change the filter to verify, and the image_type to none.
+  // A speed-profile compilation without profile data is equivalent to verify and
+  // this change will increase the precision of the telemetry data.
+  void UpdateCompilerOptionsBasedOnProfile() {
+    if (!DoProfileGuidedOptimizations() &&
+        compiler_options_->GetCompilerFilter() == CompilerFilter::kSpeedProfile) {
+      VLOG(compiler) << "Changing compiler filter to verify from speed-profile "
+          << "because of empty or non existing profile";
+
+      compiler_options_->SetCompilerFilter(CompilerFilter::kVerify);
+
+      // Note that we could reset the image_type to CompilerOptions::ImageType::kNone
+      // to prevent an app image generation.
+      // However, if we were pass an image file we would essentially leave the image
+      // file empty (possibly triggering some harmless errors when we try to load it).
+      //
+      // Letting the image_type_ be determined by whether or not we passed an image
+      // file will at least write the appropriate header making it an empty but valid
+      // image.
+    }
+  }
+
+  class ScopedDex2oatReporting {
+   public:
+    explicit ScopedDex2oatReporting(const Dex2Oat& dex2oat) {
+      bool should_report = false;
+      PaletteShouldReportDex2oatCompilation(&should_report);
+      if (should_report) {
+        if (dex2oat.zip_fd_ != -1) {
+          zip_dup_fd_.reset(DupCloexecOrError(dex2oat.zip_fd_));
+          if (zip_dup_fd_ < 0) {
+            return;
+          }
+        }
+        int image_fd = dex2oat.IsAppImage() ? dex2oat.app_image_fd_ : dex2oat.image_fd_;
+        if (image_fd != -1) {
+          image_dup_fd_.reset(DupCloexecOrError(image_fd));
+          if (image_dup_fd_ < 0) {
+            return;
+          }
+        }
+        oat_dup_fd_.reset(DupCloexecOrError(dex2oat.oat_fd_));
+        if (oat_dup_fd_ < 0) {
+          return;
+        }
+        vdex_dup_fd_.reset(DupCloexecOrError(dex2oat.output_vdex_fd_));
+        if (vdex_dup_fd_ < 0) {
+          return;
+        }
+        PaletteNotifyStartDex2oatCompilation(zip_dup_fd_,
+                                             image_dup_fd_,
+                                             oat_dup_fd_,
+                                             vdex_dup_fd_);
+      }
+      error_reporting_ = false;
+    }
+
+    ~ScopedDex2oatReporting() {
+      if (!error_reporting_) {
+        bool should_report = false;
+        PaletteShouldReportDex2oatCompilation(&should_report);
+        if (should_report) {
+          PaletteNotifyEndDex2oatCompilation(zip_dup_fd_,
+                                             image_dup_fd_,
+                                             oat_dup_fd_,
+                                             vdex_dup_fd_);
+        }
+      }
+    }
+
+    bool ErrorReporting() const { return error_reporting_; }
+
+   private:
+    int DupCloexecOrError(int fd) {
+      int dup_fd = DupCloexec(fd);
+      if (dup_fd < 0) {
+        LOG(ERROR) << "Error dup'ing a file descriptor " << strerror(errno);
+        error_reporting_ = true;
+      }
+      return dup_fd;
+    }
+    android::base::unique_fd oat_dup_fd_;
+    android::base::unique_fd vdex_dup_fd_;
+    android::base::unique_fd zip_dup_fd_;
+    android::base::unique_fd image_dup_fd_;
+    bool error_reporting_ = false;
+  };
+
  private:
   bool UseSwap(bool is_image, const std::vector<const DexFile*>& dex_files) {
     if (is_image) {
@@ -2732,9 +2632,6 @@
       elf_writers_.emplace_back(linker::CreateElfWriterQuick(*compiler_options_, oat_file.get()));
       elf_writers_.back()->Start();
       bool do_oat_writer_layout = DoDexLayoutOptimizations() || DoOatLayoutOptimizations();
-      if (profile_compilation_info_ != nullptr && profile_compilation_info_->IsEmpty()) {
-        do_oat_writer_layout = false;
-      }
       oat_writers_.emplace_back(new linker::OatWriter(
           *compiler_options_,
           timings_,
@@ -2787,12 +2684,6 @@
         std::make_pair("imageinstructionset",
                        GetInstructionSetString(compiler_options_->GetInstructionSet())));
 
-    // Only allow no boot image for the runtime if we're compiling one. When we compile an app,
-    // we don't want fallback mode, it will abort as we do not push a boot classpath (it might
-    // have been stripped in preopting, anyways).
-    if (!IsBootImage()) {
-      raw_options.push_back(std::make_pair("-Xno-dex-file-fallback", nullptr));
-    }
     // Never allow implicit image compilation.
     raw_options.push_back(std::make_pair("-Xnoimage-dex2oat", nullptr));
     // Disable libsigchain. We don't don't need it during compilation and it prevents us
@@ -2891,13 +2782,13 @@
   template <typename T>
   static std::unique_ptr<T> ReadCommentedInputFromFile(
       const char* input_filename, std::function<std::string(const char*)>* process) {
-    std::unique_ptr<std::ifstream> input_file(new std::ifstream(input_filename, std::ifstream::in));
-    if (input_file.get() == nullptr) {
+    std::ifstream input_file(input_filename, std::ifstream::in);
+    if (!input_file.good()) {
       LOG(ERROR) << "Failed to open input file " << input_filename;
       return nullptr;
     }
-    std::unique_ptr<T> result = ReadCommentedInputStream<T>(*input_file, process);
-    input_file->close();
+    std::unique_ptr<T> result = ReadCommentedInputStream<T>(input_file, process);
+    input_file.close();
     return result;
   }
 
@@ -2988,7 +2879,7 @@
   std::unique_ptr<CompilerOptions> compiler_options_;
   Compiler::Kind compiler_kind_;
 
-  std::unique_ptr<SafeMap<std::string, std::string> > key_value_store_;
+  std::unique_ptr<OatKeyValueStore> key_value_store_;
 
   std::unique_ptr<VerificationResults> verification_results_;
 
@@ -3046,6 +2937,7 @@
   bool is_host_;
   std::string android_root_;
   std::string no_inline_from_string_;
+  bool force_allow_oj_inlines_ = false;
   CompactDexLevel compact_dex_level_ = kDefaultCompactDexLevel;
 
   std::vector<std::unique_ptr<linker::ElfWriter>> elf_writers_;
@@ -3072,13 +2964,17 @@
   std::unique_ptr<ProfileCompilationInfo> profile_compilation_info_;
   TimingLogger* timings_;
   std::vector<std::vector<const DexFile*>> dex_files_per_oat_file_;
-  std::unordered_map<const DexFile*, size_t> dex_file_oat_index_map_;
+  HashMap<const DexFile*, size_t> dex_file_oat_index_map_;
 
   // Backing storage.
   std::forward_list<std::string> char_backing_storage_;
 
   // See CompilerOptions.force_determinism_.
   bool force_determinism_;
+  // See CompilerOptions.crash_on_linkage_violation_.
+  bool check_linkage_conditions_;
+  // See CompilerOptions.crash_on_linkage_violation_.
+  bool crash_on_linkage_violation_;
 
   // Directory of relative classpaths.
   std::string classpath_dir_;
@@ -3093,6 +2989,19 @@
   // The reason for invoking the compiler.
   std::string compilation_reason_;
 
+  // Whether to force individual compilation.
+  bool compile_individually_;
+
+  // The classpath that determines if a given symbol should be resolved at compile time or not.
+  std::string public_sdk_;
+
+  // The apex versions of jars in the boot classpath. Set through command line
+  // argument.
+  std::string apex_versions_argument_;
+
+  // Whether or we attempted to load the profile (if given).
+  bool profile_load_attempted_;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
 };
 
@@ -3130,7 +3039,7 @@
   jobject obj_;
 };
 
-static dex2oat::ReturnCode CompileImage(Dex2Oat& dex2oat) {
+static dex2oat::ReturnCode DoCompilation(Dex2Oat& dex2oat) {
   dex2oat.LoadClassProfileDescriptors();
   jobject class_loader = dex2oat.Compile();
   // Keep the class loader that was used for compilation live for the rest of the compilation
@@ -3142,7 +3051,7 @@
     return dex2oat::ReturnCode::kOther;
   }
 
-  // Flush boot.oat.  Keep it open as we might still modify it later (strip it).
+  // Flush output files.  Keep them open as we might still modify them later (strip them).
   if (!dex2oat.FlushOutputFiles()) {
     dex2oat.EraseOutputFiles();
     return dex2oat::ReturnCode::kOther;
@@ -3162,51 +3071,13 @@
     return dex2oat::ReturnCode::kNoFailure;
   }
 
-  // Copy stripped to unstripped location, if necessary.
-  if (!dex2oat.CopyOatFilesToSymbolsDirectoryAndStrip()) {
-    return dex2oat::ReturnCode::kOther;
-  }
-
-  // FlushClose again, as stripping might have re-opened the oat files.
-  if (!dex2oat.FlushCloseOutputFiles()) {
-    return dex2oat::ReturnCode::kOther;
-  }
-
-  dex2oat.DumpTiming();
-  return dex2oat::ReturnCode::kNoFailure;
-}
-
-static dex2oat::ReturnCode CompileApp(Dex2Oat& dex2oat) {
-  jobject class_loader = dex2oat.Compile();
-  // Keep the class loader that was used for compilation live for the rest of the compilation
-  // process.
-  ScopedGlobalRef global_ref(class_loader);
-
-  if (!dex2oat.WriteOutputFiles(class_loader)) {
-    dex2oat.EraseOutputFiles();
-    return dex2oat::ReturnCode::kOther;
-  }
-
-  // Do not close the oat files here. We might have gotten the output file by file descriptor,
-  // which we would lose.
-
-  // When given --host, finish early without stripping.
-  if (dex2oat.IsHost()) {
-    if (!dex2oat.FlushCloseOutputFiles()) {
-      return dex2oat::ReturnCode::kOther;
-    }
-
-    dex2oat.DumpTiming();
-    return dex2oat::ReturnCode::kNoFailure;
-  }
-
   // Copy stripped to unstripped location, if necessary. This will implicitly flush & close the
   // stripped versions. If this is given, we expect to be able to open writable files by name.
   if (!dex2oat.CopyOatFilesToSymbolsDirectoryAndStrip()) {
     return dex2oat::ReturnCode::kOther;
   }
 
-  // Flush and close the files.
+  // FlushClose again, as stripping might have re-opened the oat files.
   if (!dex2oat.FlushCloseOutputFiles()) {
     return dex2oat::ReturnCode::kOther;
   }
@@ -3233,16 +3104,27 @@
 
   // If needed, process profile information for profile guided compilation.
   // This operation involves I/O.
-  if (dex2oat->UseProfile()) {
+  if (dex2oat->HasProfileInput()) {
     if (!dex2oat->LoadProfile()) {
       LOG(ERROR) << "Failed to process profile file";
       return dex2oat::ReturnCode::kOther;
     }
   }
 
+  // Check if we need to update any of the compiler options (such as the filter)
+  // and do it before anything else (so that the other operations have a true
+  // view of the state).
+  dex2oat->UpdateCompilerOptionsBasedOnProfile();
+
+  // Insert the compiler options in the key value store.
+  // We have to do this after we altered any incoming arguments
+  // (such as the compiler filter).
+  dex2oat->InsertCompileOptions(argc, argv);
 
   // Check early that the result of compilation can be written
   if (!dex2oat->OpenFile()) {
+    // Flush close so that the File Guard checks don't fail the assertions.
+    dex2oat->FlushCloseOutputFiles();
     return dex2oat::ReturnCode::kOther;
   }
 
@@ -3261,6 +3143,13 @@
     LOG(INFO) << StrippedCommandLine();
   }
 
+  Dex2Oat::ScopedDex2oatReporting sdr(*dex2oat.get());
+
+  if (sdr.ErrorReporting()) {
+    dex2oat->EraseOutputFiles();
+    return dex2oat::ReturnCode::kOther;
+  }
+
   dex2oat::ReturnCode setup_code = dex2oat->Setup();
   if (setup_code != dex2oat::ReturnCode::kNoFailure) {
     dex2oat->EraseOutputFiles();
@@ -3276,7 +3165,7 @@
   // Note: If dex2oat fails, installd will remove the oat files causing the app
   // to fallback to apk with possible in-memory extraction. We want to avoid
   // that, and thus we're lenient towards profile corruptions.
-  if (dex2oat->UseProfile()) {
+  if (dex2oat->DoProfileGuidedOptimizations()) {
     dex2oat->VerifyProfileData();
   }
 
@@ -3284,12 +3173,7 @@
   // instance. Used by tools/bisection_search/bisection_search.py.
   VLOG(compiler) << "Running dex2oat (parent PID = " << getppid() << ")";
 
-  dex2oat::ReturnCode result;
-  if (dex2oat->IsImage()) {
-    result = CompileImage(*dex2oat);
-  } else {
-    result = CompileApp(*dex2oat);
-  }
+  dex2oat::ReturnCode result = DoCompilation(*dex2oat);
 
   return result;
 }
@@ -3301,7 +3185,7 @@
   // time (bug 10645725) unless we're a debug or instrumented build or running on a memory tool.
   // Note: The Dex2Oat class should not destruct the runtime in this case.
   if (!art::kIsDebugBuild && !art::kIsPGOInstrumentation && !art::kRunningOnMemoryTool) {
-    _exit(result);
+    art::FastExit(result);
   }
   return result;
 }
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index d01b64f..a44a3e4 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -184,13 +184,11 @@
   }
   // Compile only a subset of the libcore dex files to make this test shorter.
   std::vector<std::string> libcore_dex_files = GetLibCoreDexFileNames();
-  // The primary image must contain at least core-oj and core-libart to initialize the runtime
-  // and we also need the core-icu4j if we want to compile these with full profile.
+  // The primary image must contain at least core-oj and core-libart to initialize the runtime.
   ASSERT_NE(std::string::npos, libcore_dex_files[0].find("core-oj"));
   ASSERT_NE(std::string::npos, libcore_dex_files[1].find("core-libart"));
-  ASSERT_NE(std::string::npos, libcore_dex_files[2].find("core-icu4j"));
   ArrayRef<const std::string> dex_files =
-      ArrayRef<const std::string>(libcore_dex_files).SubArray(/*pos=*/ 0u, /*length=*/ 3u);
+      ArrayRef<const std::string>(libcore_dex_files).SubArray(/*pos=*/ 0u, /*length=*/ 2u);
 
   ImageSizes base_sizes = CompileImageAndGetSizes(dex_files, {});
   ImageSizes everything_sizes;
@@ -201,10 +199,10 @@
   ArrayRef<const std::string> libcore_dexes_array(libcore_dexes);
   {
     ScratchFile profile_file;
-    GenerateProfile(libcore_dexes_array,
-                    profile_file.GetFile(),
-                    /*method_frequency=*/ 1u,
-                    /*type_frequency=*/ 1u);
+    GenerateBootProfile(libcore_dexes_array,
+                        profile_file.GetFile(),
+                        /*method_frequency=*/ 1u,
+                        /*type_frequency=*/ 1u);
     everything_sizes = CompileImageAndGetSizes(
         dex_files,
         {"--profile-file=" + profile_file.GetFilename(),
@@ -213,7 +211,7 @@
     std::cout << "All methods and classes sizes " << everything_sizes << std::endl;
     // Putting all classes as image classes should increase art size
     EXPECT_GE(everything_sizes.art_size, base_sizes.art_size);
-    // Sanity check that dex is the same size.
+    // Check that dex is the same size.
     EXPECT_EQ(everything_sizes.vdex_size, base_sizes.vdex_size);
   }
   static size_t kMethodFrequency = 3;
@@ -221,10 +219,10 @@
   // Test compiling fewer methods and classes.
   {
     ScratchFile profile_file;
-    GenerateProfile(libcore_dexes_array,
-                    profile_file.GetFile(),
-                    kMethodFrequency,
-                    kTypeFrequency);
+    GenerateBootProfile(libcore_dexes_array,
+                        profile_file.GetFile(),
+                        kMethodFrequency,
+                        kTypeFrequency);
     filter_sizes = CompileImageAndGetSizes(
         dex_files,
         {"--profile-file=" + profile_file.GetFilename(),
@@ -261,7 +259,7 @@
   std::string image_dir = scratch_dir + GetInstructionSetString(kRuntimeISA);
   int mkdir_result = mkdir(image_dir.c_str(), 0700);
   ASSERT_EQ(0, mkdir_result);
-  std::string filename_prefix = image_dir + "/core";
+  std::string filename_prefix = image_dir + "/boot";
 
   // Copy the libcore dex files to a custom dir inside `scratch_dir` so that we do not
   // accidentally load pre-compiled core images from their original directory based on BCP paths.
@@ -274,25 +272,23 @@
 
   ArrayRef<const std::string> full_bcp(libcore_dex_files);
   size_t total_dex_files = full_bcp.size();
-  ASSERT_GE(total_dex_files, 5u);  // 3 for "head", 1 for "tail", at least one for "mid", see below.
+  ASSERT_GE(total_dex_files, 4u);  // 2 for "head", 1 for "tail", at least one for "mid", see below.
 
-  // The primary image must contain at least core-oj and core-libart to initialize the runtime
-  // and we also need the core-icu4j if we want to compile these with full profile.
+  // The primary image must contain at least core-oj and core-libart to initialize the runtime.
   ASSERT_NE(std::string::npos, full_bcp[0].find("core-oj"));
   ASSERT_NE(std::string::npos, full_bcp[1].find("core-libart"));
-  ASSERT_NE(std::string::npos, full_bcp[2].find("core-icu4j"));
-  ArrayRef<const std::string> head_dex_files = full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ 3u);
+  ArrayRef<const std::string> head_dex_files = full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ 2u);
   // Middle part is everything else except for conscrypt.
   ASSERT_NE(std::string::npos, full_bcp[full_bcp.size() - 1u].find("conscrypt"));
   ArrayRef<const std::string> mid_bcp =
       full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ total_dex_files - 1u);
-  ArrayRef<const std::string> mid_dex_files = mid_bcp.SubArray(/*pos=*/ 3u);
+  ArrayRef<const std::string> mid_dex_files = mid_bcp.SubArray(/*pos=*/ 2u);
   // Tail is just the conscrypt.
   ArrayRef<const std::string> tail_dex_files =
       full_bcp.SubArray(/*pos=*/ total_dex_files - 1u, /*length=*/ 1u);
 
   // Prepare the "head", "mid" and "tail" names and locations.
-  std::string base_name = "core.art";
+  std::string base_name = "boot.art";
   std::string base_location = scratch_dir + base_name;
   std::vector<std::string> expanded_mid = gc::space::ImageSpace::ExpandMultiImageLocations(
       mid_dex_files.SubArray(/*pos=*/ 0u, /*length=*/ 1u),
@@ -314,22 +310,22 @@
 
   // Create profiles.
   ScratchFile head_profile_file;
-  GenerateProfile(head_dex_files,
-                  head_profile_file.GetFile(),
-                  /*method_frequency=*/ 1u,
-                  /*type_frequency=*/ 1u);
+  GenerateBootProfile(head_dex_files,
+                      head_profile_file.GetFile(),
+                      /*method_frequency=*/ 1u,
+                      /*type_frequency=*/ 1u);
   const std::string& head_profile_filename = head_profile_file.GetFilename();
   ScratchFile mid_profile_file;
-  GenerateProfile(mid_dex_files,
-                  mid_profile_file.GetFile(),
-                  /*method_frequency=*/ 5u,
-                  /*type_frequency=*/ 4u);
+  GenerateBootProfile(mid_dex_files,
+                      mid_profile_file.GetFile(),
+                      /*method_frequency=*/ 5u,
+                      /*type_frequency=*/ 4u);
   const std::string& mid_profile_filename = mid_profile_file.GetFilename();
   ScratchFile tail_profile_file;
-  GenerateProfile(tail_dex_files,
-                  tail_profile_file.GetFile(),
-                  /*method_frequency=*/ 5u,
-                  /*type_frequency=*/ 4u);
+  GenerateBootProfile(tail_dex_files,
+                      tail_profile_file.GetFile(),
+                      /*method_frequency=*/ 5u,
+                      /*type_frequency=*/ 4u);
   const std::string& tail_profile_filename = tail_profile_file.GetFilename();
 
   // Compile the "head", i.e. the primary boot image.
@@ -373,17 +369,17 @@
   std::string single_image_dir = single_dir + GetInstructionSetString(kRuntimeISA);
   mkdir_result = mkdir(single_image_dir.c_str(), 0700);
   ASSERT_EQ(0, mkdir_result);
-  std::string single_filename_prefix = single_image_dir + "/core";
+  std::string single_filename_prefix = single_image_dir + "/boot";
 
   // The dex files for the single-image are everything not in the "head".
   ArrayRef<const std::string> single_dex_files = full_bcp.SubArray(/*pos=*/ head_dex_files.size());
 
   // Create a smaller profile for the single-image test that squashes the "mid" and "tail".
   ScratchFile single_profile_file;
-  GenerateProfile(single_dex_files,
-                  single_profile_file.GetFile(),
-                  /*method_frequency=*/ 5u,
-                  /*type_frequency=*/ 4u);
+  GenerateBootProfile(single_dex_files,
+                      single_profile_file.GetFile(),
+                      /*method_frequency=*/ 5u,
+                      /*type_frequency=*/ 4u);
   const std::string& single_profile_filename = single_profile_file.GetFilename();
 
   // Prepare the single image name and location.
@@ -428,10 +424,8 @@
                                                 /*boot_class_path_locations=*/ libcore_dex_files,
                                                 image_location,
                                                 kRuntimeISA,
-                                                gc::space::ImageSpaceLoadingOrder::kSystemFirst,
                                                 relocate,
                                                 /*executable=*/ true,
-                                                /*is_zygote=*/ false,
                                                 /*extra_reservation_size=*/ 0u,
                                                 &boot_image_spaces,
                                                 &extra_reservation);
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index ddfc84b..280db7a 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -34,6 +34,7 @@
   }
 
   static const char* Name() { return "InstructionSet"; }
+  static const char* DescribeType() { return "arm|arm64|x86|x86_64|none"; }
 };
 
 #define COMPILER_OPTIONS_MAP_TYPE Dex2oatArgumentMap
@@ -57,18 +58,44 @@
   builder.
       Define("--dex-file=_")
           .WithType<std::vector<std::string>>().AppendValues()
+          .WithHelp("Specifies a .dex, .jar, or .apk file to compile.\n"
+                    "Eg: --dex-file=/system/framework/core.jar")
+          .WithMetavar("<dex-file>")
           .IntoKey(M::DexFiles)
       .Define("--dex-location=_")
           .WithType<std::vector<std::string>>().AppendValues()
+          .WithMetavar("<dex-location>")
+          .WithHelp("specifies an alternative dex location to encode in the oat file for the\n"
+                    "corresponding --dex-file argument. The first --dex-location corresponds to\n"
+                    "the first --dex-file, the second to the second and so on.\n"
+                    "Eg: --dex-file=/home/build/out/system/framework/core.jar\n"
+                    "    --dex-location=/system/framework/core.jar")
           .IntoKey(M::DexLocations)
       .Define("--zip-fd=_")
           .WithType<int>()
+          .WithHelp("specifies a file descriptor of a zip file containing a classes.dex file to\n"
+                    "compile. Eg: --zip-fd=5")
           .IntoKey(M::ZipFd)
       .Define("--zip-location=_")
           .WithType<std::string>()
+          .WithHelp("Specifies a symbolic name for the file corresponding to the FD given by\n"
+                    "--zip-fd.")
           .IntoKey(M::ZipLocation)
       .Define("--boot-image=_")
           .WithType<std::string>()
+          .WithHelp("provide the image file for the boot class path.\n"
+                    "Do not include the arch as part of the name, it is added automatically.\n"
+                    "Example: --boot-image=/system/framework/boot.art\n"
+                    "         (specifies /system/framework/<arch>/boot.art as the image file)\n"
+                    "Example: --boot-image=boot.art:boot-framework.art\n"
+                    "         (specifies <bcp-path1>/<arch>/boot.art as the image file and\n"
+                    "         <bcp-path2>/<arch>/boot-framework.art as the image extension file\n"
+                    "         with paths taken from corresponding boot class path components)\n"
+                    "Example: --boot-image=/apex/com.android.art/boot.art:/system/framework/*:*\n"
+                    "         (specifies /apex/com.android.art/<arch>/boot.art as the image\n"
+                    "         file and search for extensions in /framework/system and boot\n"
+                    "         class path components' paths)\n"
+                    "Default: $ANDROID_ROOT/system/framework/boot.art")
           .IntoKey(M::BootImage);
 }
 
@@ -76,35 +103,53 @@
   builder.
       Define("--input-vdex-fd=_")
           .WithType<int>()
+          .WithHelp("specifies the vdex input source via a file descriptor.")
           .IntoKey(M::InputVdexFd)
       .Define("--input-vdex=_")
           .WithType<std::string>()
+          .WithHelp("specifies the vdex input source via a filename.")
           .IntoKey(M::InputVdex)
       .Define("--output-vdex-fd=_")
+          .WithHelp("specifies the vdex output destination via a file descriptor.")
           .WithType<int>()
           .IntoKey(M::OutputVdexFd)
       .Define("--output-vdex=_")
           .WithType<std::string>()
+          .WithHelp("specifies the vdex output destination via a filename.")
           .IntoKey(M::OutputVdex)
       .Define("--dm-fd=_")
           .WithType<int>()
+          .WithHelp("specifies the dm output destination via a file descriptor.")
           .IntoKey(M::DmFd)
       .Define("--dm-file=_")
           .WithType<std::string>()
+          .WithHelp("specifies the dm output destination via a filename.")
           .IntoKey(M::DmFile)
       .Define("--oat-file=_")
           .WithType<std::string>()
+          .WithHelp(" Specifies an oat output destination via a filename.\n"
+                    "Eg: --oat-file=/system/framework/boot.oat")
           .IntoKey(M::OatFile)
       .Define("--oat-symbols=_")
           .WithType<std::string>()
+          .WithHelp("Specifies a symbolized oat output destination.\n"
+                    "Eg: --oat-symbols=symbols/system/framework/boot.oat")
           .IntoKey(M::OatSymbols)
       .Define("--strip")
+          .WithHelp("remove all debugging sections at the end (but keep mini-debug-info).\n"
+                    "This is equivalent to the \"strip\" command as build post-processing step.\n"
+                    "It is intended to be used with --oat-symbols and it happens after it.\n"
+                    "Eg: --oat-symbols=/symbols/system/framework/boot.oat")
           .IntoKey(M::Strip)
       .Define("--oat-fd=_")
           .WithType<int>()
+          .WithHelp("Specifies the oat output destination via a file descriptor. Eg: --oat-fd=5")
           .IntoKey(M::OatFd)
       .Define("--oat-location=_")
           .WithType<std::string>()
+          .WithHelp("specifies a symbolic name for the file corresponding to the file descriptor\n"
+                    "specified by --oat-fd.\n"
+                    "Eg: --oat-location=/data/dalvik-cache/system@app@Calculator.apk.oat")
           .IntoKey(M::OatLocation);
 }
 
@@ -112,33 +157,52 @@
   builder.
       Define("--image=_")
           .WithType<std::string>()
+          .WithHelp("specifies an output image filename. Eg: --image=/system/framework/boot.art")
           .IntoKey(M::ImageFilename)
       .Define("--image-fd=_")
           .WithType<int>()
+          .WithHelp("specifies an output image file descriptor. Cannot be used with --image.\n"
+                    "Eg: --image-fd=7")
           .IntoKey(M::ImageFd)
       .Define("--base=_")
           .WithType<std::string>()
+          .WithHelp("Specifies the base address when creating a boot image. Eg: --base=0x50000000")
+          .WithMetavar("{hex address}")
           .IntoKey(M::Base)
       .Define("--app-image-file=_")
           .WithType<std::string>()
+          .WithHelp("Specify a file name for app image. Only used if a profile is passed in.")
           .IntoKey(M::AppImageFile)
       .Define("--app-image-fd=_")
           .WithType<int>()
+          .WithHelp("Specify a file descriptor for app image. Only used if a profile is passed in.")
           .IntoKey(M::AppImageFileFd)
       .Define({"--multi-image", "--single-image"})
           .WithValues({true, false})
+          .WithHelp("Specifies if separate oat and image files should be generated for each dex\n"
+                    "file. --multi-image is default for boot image and --single-image for app\n"
+                    "images.")
           .IntoKey(M::MultiImage)
       .Define("--dirty-image-objects=_")
           .WithType<std::string>()
+          .WithHelp("list of known dirty objects in the image. The image writer will group them"
+                    " together")
           .IntoKey(M::DirtyImageObjects)
       .Define("--updatable-bcp-packages-file=_")
           .WithType<std::string>()
+          .WithHelp("file with a list of updatable boot class path packages. Classes in these\n"
+                    "packages and sub-packages shall not be resolved during app compilation to\n"
+                    "avoid AOT assumptions being invalidated after applying updates to these\n"
+                    "components."
+          )
           .IntoKey(M::UpdatableBcpPackagesFile)
       .Define("--image-format=_")
           .WithType<ImageHeader::StorageMode>()
           .WithValueMap({{"lz4", ImageHeader::kStorageModeLZ4},
                          {"lz4hc", ImageHeader::kStorageModeLZ4HC},
                          {"uncompressed", ImageHeader::kStorageModeUncompressed}})
+          .WithHelp("Which format to store the image Defaults to uncompressed. Eg:"
+                    " --image-format=lz4")
           .IntoKey(M::ImageFormat);
 }
 
@@ -146,15 +210,19 @@
   builder.
       Define("--swap-file=_")
           .WithType<std::string>()
+          .WithHelp("Specify a file to use for swap. Eg: --swap-file=/data/tmp/swap.001")
           .IntoKey(M::SwapFile)
       .Define("--swap-fd=_")
           .WithType<int>()
+          .WithHelp("Specify a file to use for swap by file-descriptor. Eg: --swap-fd=3")
           .IntoKey(M::SwapFileFd)
       .Define("--swap-dex-size-threshold=_")
           .WithType<unsigned int>()
+          .WithHelp("specifies the minimum total dex file size in bytes to allow the use of swap.")
           .IntoKey(M::SwapDexSizeThreshold)
       .Define("--swap-dex-count-threshold=_")
           .WithType<unsigned int>()
+          .WithHelp("specifies the minimum number of dex file to allow the use of swap.")
           .IntoKey(M::SwapDexCountThreshold);
 }
 
@@ -165,9 +233,11 @@
           .IntoKey(M::Passes)
       .Define("--profile-file=_")
           .WithType<std::string>()
+          .WithHelp("Specify profiler output file to use for compilation using a filename.")
           .IntoKey(M::Profile)
       .Define("--profile-file-fd=_")
           .WithType<int>()
+          .WithHelp("Specify profiler output file to use for compilation using a file-descriptor.")
           .IntoKey(M::ProfileFd)
       .Define("--no-inline-from=_")
           .WithType<std::string>()
@@ -178,16 +248,27 @@
   builder.
       Define("--instruction-set=_")
           .WithType<InstructionSet>()
+          .WithHelp("Compile for a particular instruction set.")
           .IntoKey(M::TargetInstructionSet)
       .Define("--instruction-set-variant=_")
           .WithType<std::string>()
+          .WithHelp("Specify instruction set features using variant name.\n"
+                    "Eg: --instruction-set-variant=silvermont")
+          .WithMetavar("{Variant Name}")
           .IntoKey(M::TargetInstructionSetVariant)
       .Define("--instruction-set-features=_")
           .WithType<std::string>()
+          .WithHelp("Specify instruction set features.\n"
+                    "On target the value 'runtime' can be used to detect features at run time.\n"
+                    "If target does not support run-time detection the value 'runtime'\n"
+                    "has the same effect as the value 'default'.\n"
+                    "Note: the value 'runtime' has no effect if it is used on host.\n"
+                    "Example: --instruction-set-features=div\n"
+                    "Default: default")
           .IntoKey(M::TargetInstructionSetFeatures);
 }
 
-static Parser CreateArgumentParser() {
+Parser CreateDex2oatArgumentParser() {
   std::unique_ptr<Builder> parser_builder = std::make_unique<Builder>();
 
   AddInputMappings(*parser_builder);
@@ -199,66 +280,147 @@
 
   parser_builder->
       Define({"--watch-dog", "--no-watch-dog"})
+          .WithHelp("Enable or disable the watchdog timer.")
           .WithValues({true, false})
           .IntoKey(M::Watchdog)
       .Define("--watchdog-timeout=_")
           .WithType<int>()
+          .WithHelp("Set the watchdog timeout value in seconds.")
           .IntoKey(M::WatchdogTimeout)
       .Define("-j_")
           .WithType<unsigned int>()
+          .WithHelp("specifies the number of threads used for compilation. Default is the number\n"
+                    "of detected hardware threads available on the host system.")
           .IntoKey(M::Threads)
       .Define("--cpu-set=_")
           .WithType<std::vector<int32_t>>()
+          .WithHelp("sets the cpu affinitiy to the given <set>. The <set> is a comma separated\n"
+                    "list of cpus. Eg: --cpu-set=0,1,2,3")
+          .WithMetavar("<set>")
           .IntoKey(M::CpuSet)
       .Define("--android-root=_")
           .WithType<std::string>()
+          .WithHelp("Used to locate libraries for portable linking.\n"
+                    "Eg: --android-root=out/host/linux-x86\n"
+                    "Default: $ANDROID_ROOT")
           .IntoKey(M::AndroidRoot)
       .Define("--compiler-backend=_")
           .WithType<Compiler::Kind>()
           .WithValueMap({{"Quick", Compiler::Kind::kQuick},
                          {"Optimizing", Compiler::Kind::kOptimizing}})
+          .WithHelp("Select a compiler backend set. Default: optimizing")
           .IntoKey(M::Backend)
       .Define("--host")
+          .WithHelp("Run in host mode")
           .IntoKey(M::Host)
       .Define("--avoid-storing-invocation")
+          .WithHelp("Avoid storing the invocation args in the key-value store. Used to test\n"
+                    "determinism with different args.")
           .IntoKey(M::AvoidStoringInvocation)
       .Define("--very-large-app-threshold=_")
           .WithType<unsigned int>()
+          .WithHelp("Specifies the minimum total dex file size in bytes to consider the input\n"
+                    "\"very large\" and reduce compilation done.")
           .IntoKey(M::VeryLargeAppThreshold)
       .Define("--force-determinism")
+          .WithHelp("Force the compiler to emit a deterministic output")
           .IntoKey(M::ForceDeterminism)
+      .Define("--check-linkage-conditions")
+          .IntoKey(M::CheckLinkageConditions)
+      .Define("--crash-on-linkage-violation")
+          .IntoKey(M::CrashOnLinkageViolation)
       .Define("--copy-dex-files=_")
           .WithType<linker::CopyOption>()
           .WithValueMap({{"true", linker::CopyOption::kOnlyIfCompressed},
                          {"false", linker::CopyOption::kNever},
                          {"always", linker::CopyOption::kAlways}})
+          .WithHelp("enable|disable copying the dex files into the output vdex.")
           .IntoKey(M::CopyDexFiles)
+      .Define("--force-allow-oj-inlines")
+          .WithHelp("Disables automatic no-inline for core-oj on host. Has no effect on target."
+                    " FOR TESTING USE ONLY! DO NOT DISTRIBUTE BINARIES BUILT WITH THIS OPTION!")
+          .IntoKey(M::ForceAllowOjInlines)
       .Define("--write-invocation-to=_")
+          .WithHelp("Write the invocation commandline to the given file for later use. Used to\n"
+                    "test determinism with different args.")
           .WithType<std::string>()
           .IntoKey(M::InvocationFile)
       .Define("--classpath-dir=_")
           .WithType<std::string>()
+          .WithHelp("Directory used to resolve relative class paths.")
           .IntoKey(M::ClasspathDir)
       .Define("--class-loader-context=_")
           .WithType<std::string>()
+          .WithHelp("a string specifying the intended runtime loading context for the compiled\n"
+                    "dex files.")
           .IntoKey(M::ClassLoaderContext)
       .Define("--class-loader-context-fds=_")
           .WithType<std::string>()
+          .WithHelp("a colon-separated list of file descriptors for dex files in\n"
+                    "--class-loader-context. Their order must be the same as dex files in a\n"
+                    "flattened class loader context")
           .IntoKey(M::ClassLoaderContextFds)
       .Define("--stored-class-loader-context=_")
           .WithType<std::string>()
+          .WithHelp("a string specifying the intended runtime loading context that is stored\n"
+                    "in the oat file. Overrides --class-loader-context. Note that this ignores\n"
+                    "the classpath_dir arg.\n"
+                    "\n"
+                    "It describes how the class loader chain should be built in order to ensure\n"
+                    "classes are resolved during dex2aot as they would be resolved at runtime.\n"
+                    "This spec will be encoded in the oat file. If at runtime the dex file is\n"
+                    "loaded in a different context, the oat file will be rejected.\n"
+                    "\n"
+                    "The chain is interpreted in the natural 'parent order', meaning that class\n"
+                    "loader 'i+1' will be the parent of class loader 'i'.\n"
+                    "The compilation sources will be appended to the classpath of the first class\n"
+                    "loader.\n"
+                    "\n"
+                    "E.g. if the context is 'PCL[lib1.dex];DLC[lib2.dex]' and \n"
+                    "--dex-file=src.dex then dex2oat will setup a PathClassLoader with classpath \n"
+                    "'lib1.dex:src.dex' and set its parent to a DelegateLastClassLoader with \n"
+                    "classpath 'lib2.dex'.\n"
+                    "\n"
+                    "Note that the compiler will be tolerant if the source dex files specified\n"
+                    "with --dex-file are found in the classpath. The source dex files will be\n"
+                    "removed from any class loader's classpath possibly resulting in empty\n"
+                    "class loaders.\n"
+                    "\n"
+                    "Example: --class-loader-context=PCL[lib1.dex:lib2.dex];DLC[lib3.dex]")
           .IntoKey(M::StoredClassLoaderContext)
       .Define("--compact-dex-level=_")
           .WithType<CompactDexLevel>()
           .WithValueMap({{"none", CompactDexLevel::kCompactDexLevelNone},
                          {"fast", CompactDexLevel::kCompactDexLevelFast}})
+          .WithHelp("None avoids generating compact dex, fast generates compact dex with low\n"
+                    "compile time. If speed-profile is specified as the compiler filter and the\n"
+                    "profile is not empty, the default compact dex level is always used.")
           .IntoKey(M::CompactDexLevel)
       .Define("--runtime-arg _")
           .WithType<std::vector<std::string>>().AppendValues()
+          .WithMetavar("{dalvikvm-arg}")
+          .WithHelp("used to specify various arguments for the runtime, such as initial heap\n"
+                    "size, maximum heap size, and verbose output. Use a separate --runtime-arg\n"
+                    "switch for each argument.\n"
+                    "Example: --runtime-arg -Xms256m")
           .IntoKey(M::RuntimeOptions)
       .Define("--compilation-reason=_")
           .WithType<std::string>()
-          .IntoKey(M::CompilationReason);
+          .WithHelp("optional metadata specifying the reason for compiling the apk. If specified,\n"
+                    "the string will be embedded verbatim in the key value store of the oat file.\n"
+                    "Example: --compilation-reason=install")
+          .IntoKey(M::CompilationReason)
+      .Define("--compile-individually")
+          .WithHelp("Compiles dex files individually, unloading classes in between compiling each"
+                    " file.")
+          .IntoKey(M::CompileIndividually)
+      .Define("--public-sdk=_")
+          .WithType<std::string>()
+          .IntoKey(M::PublicSdk)
+      .Define("--apex-versions=_")
+          .WithType<std::string>()
+          .WithHelp("Versions of apexes in the boot classpath, separated by '/'")
+          .IntoKey(M::ApexVersions);
 
   AddCompilerOptionsArgumentParserOptions<Dex2oatArgumentMap>(*parser_builder);
 
@@ -270,7 +432,7 @@
 std::unique_ptr<Dex2oatArgumentMap> Dex2oatArgumentMap::Parse(int argc,
                                                               const char** argv,
                                                               std::string* error_msg) {
-  Parser parser = CreateArgumentParser();
+  Parser parser = CreateDex2oatArgumentParser();
   CmdlineResult parse_result = parser.Parse(argv, argc);
   if (!parse_result.IsSuccess()) {
     *error_msg = parse_result.GetMessage();
diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def
index dbb7c9e..71a769a 100644
--- a/dex2oat/dex2oat_options.def
+++ b/dex2oat/dex2oat_options.def
@@ -92,5 +92,11 @@
 DEX2OAT_OPTIONS_KEY (std::string,                    UpdatableBcpPackagesFile)
 DEX2OAT_OPTIONS_KEY (std::vector<std::string>,       RuntimeOptions)
 DEX2OAT_OPTIONS_KEY (std::string,                    CompilationReason)
+DEX2OAT_OPTIONS_KEY (Unit,                           CheckLinkageConditions)
+DEX2OAT_OPTIONS_KEY (Unit,                           CrashOnLinkageViolation)
+DEX2OAT_OPTIONS_KEY (Unit,                           CompileIndividually)
+DEX2OAT_OPTIONS_KEY (std::string,                    PublicSdk)
+DEX2OAT_OPTIONS_KEY (Unit,                           ForceAllowOjInlines)
+DEX2OAT_OPTIONS_KEY (std::string,                    ApexVersions)
 
 #undef DEX2OAT_OPTIONS_KEY
diff --git a/dex2oat/dex2oat_options.h b/dex2oat/dex2oat_options.h
index 27d3d25..1da1ff9 100644
--- a/dex2oat/dex2oat_options.h
+++ b/dex2oat/dex2oat_options.h
@@ -72,6 +72,8 @@
 #include "dex2oat_options.def"
 };
 
+CmdlineParser<Dex2oatArgumentMap, Dex2oatArgumentMap::Key> CreateDex2oatArgumentParser();
+
 extern template struct CompilerOptionsMap<Dex2oatArgumentMap, Dex2oatArgumentMapKey>;
 
 }  // namespace art
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 34c8c5e..cc29b0f 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -43,7 +43,8 @@
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
 #include "dex2oat_environment_test.h"
-#include "dex2oat_return_codes.h"
+#include "elf_file.h"
+#include "elf_file_impl.h"
 #include "gc_root-inl.h"
 #include "intern_table-inl.h"
 #include "oat.h"
@@ -54,9 +55,6 @@
 
 namespace art {
 
-static constexpr bool kDebugArgs = false;
-static const char* kDisableCompactDex = "--compact-dex-level=none";
-
 using android::base::StringPrintf;
 
 class Dex2oatTest : public Dex2oatEnvironmentTest {
@@ -66,7 +64,6 @@
 
     output_ = "";
     error_msg_ = "";
-    success_ = false;
   }
 
  protected:
@@ -100,7 +97,7 @@
 
     args.insert(args.end(), extra_args.begin(), extra_args.end());
 
-    int status = Dex2Oat(args, error_msg);
+    int status = Dex2Oat(args, &output_, error_msg);
     if (oat_file != nullptr) {
       CHECK_EQ(oat_file->FlushClose(), 0) << "Could not flush and close oat file";
     }
@@ -207,58 +204,22 @@
     EXPECT_EQ(expected, actual);
   }
 
-  int Dex2Oat(const std::vector<std::string>& dex2oat_args, std::string* error_msg) {
-    std::vector<std::string> argv;
-    if (!CommonRuntimeTest::StartDex2OatCommandLine(&argv, error_msg)) {
-      return false;
-    }
-
-    Runtime* runtime = Runtime::Current();
-    if (!runtime->IsVerificationEnabled()) {
-      argv.push_back("--compiler-filter=assume-verified");
-    }
-
-    if (runtime->MustRelocateIfPossible()) {
-      argv.push_back("--runtime-arg");
-      argv.push_back("-Xrelocate");
-    } else {
-      argv.push_back("--runtime-arg");
-      argv.push_back("-Xnorelocate");
-    }
-
-    if (!kIsTargetBuild) {
-      argv.push_back("--host");
-    }
-
-    argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
-
-    // We must set --android-root.
-    const char* android_root = getenv("ANDROID_ROOT");
-    CHECK(android_root != nullptr);
-    argv.push_back("--android-root=" + std::string(android_root));
-
-    if (kDebugArgs) {
-      std::string all_args;
-      for (const std::string& arg : argv) {
-        all_args += arg + " ";
-      }
-      LOG(ERROR) << all_args;
-    }
-
-    // We need dex2oat to actually log things.
-    auto post_fork_fn = []() { return setenv("ANDROID_LOG_TAGS", "*:d", 1) == 0; };
-    ForkAndExecResult res = ForkAndExec(argv, post_fork_fn, &output_);
-    if (res.stage != ForkAndExecResult::kFinished) {
-      *error_msg = strerror(errno);
-      return -1;
-    }
-    success_ = res.StandardSuccess();
-    return res.status_code;
-  }
-
   std::string output_ = "";
   std::string error_msg_ = "";
-  bool success_ = false;
+};
+
+// This test class provides an easy way to validate an expected filter which is different
+// then the one pass to generate the odex file (compared to adding yet another argument
+// to what's already huge test methods).
+class Dex2oatWithExpectedFilterTest : public Dex2oatTest {
+ protected:
+  void CheckFilter(
+        CompilerFilter::Filter expected ATTRIBUTE_UNUSED,
+        CompilerFilter::Filter actual) override {
+    EXPECT_EQ(expected_filter_, actual);
+  }
+
+  CompilerFilter::Filter expected_filter_;
 };
 
 class Dex2oatSwapTest : public Dex2oatTest {
@@ -282,7 +243,6 @@
     ASSERT_TRUE(GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, copy));
 
     CheckValidity();
-    ASSERT_TRUE(success_);
     CheckResult(expect_use);
   }
 
@@ -497,6 +457,14 @@
                bool expect_large,
                bool expect_downgrade,
                const std::vector<std::string>& extra_args = {}) {
+    RunTest(filter, filter, expect_large, expect_downgrade, extra_args);
+  }
+
+  void RunTest(CompilerFilter::Filter filter,
+               CompilerFilter::Filter expected_filter,
+               bool expect_large,
+               bool expect_downgrade,
+               const std::vector<std::string>& extra_args = {}) {
     std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
     std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
     std::string app_image_file = GetScratchDir() + "/Test.art";
@@ -508,11 +476,11 @@
     ASSERT_TRUE(GenerateOdexForTest(dex_location, odex_location, filter, new_args));
 
     CheckValidity();
-    ASSERT_TRUE(success_);
     CheckResult(dex_location,
                 odex_location,
                 app_image_file,
                 filter,
+                expected_filter,
                 expect_large,
                 expect_downgrade);
   }
@@ -521,6 +489,7 @@
                    const std::string& odex_location,
                    const std::string& app_image_file,
                    CompilerFilter::Filter filter,
+                   CompilerFilter::Filter expected_filter,
                    bool expect_large,
                    bool expect_downgrade) {
     if (expect_downgrade) {
@@ -552,13 +521,13 @@
         ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
         for (uint16_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
           OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
-          EXPECT_EQ(oat_class.GetType(), OatClassType::kOatClassNoneCompiled);
+          EXPECT_EQ(oat_class.GetType(), OatClassType::kNoneCompiled);
         }
       }
 
       // If the input filter was "below," it should have been used.
       if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kExtract, filter)) {
-        EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
+        EXPECT_EQ(odex_file->GetCompilerFilter(), expected_filter);
       }
 
       // If expect large, make sure the app image isn't generated or is empty.
@@ -566,7 +535,7 @@
         EXPECT_EQ(file->GetLength(), 0u);
       }
     } else {
-      EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
+      EXPECT_EQ(odex_file->GetCompilerFilter(), expected_filter);
       ASSERT_TRUE(file != nullptr) << app_image_file;
       EXPECT_GT(file->GetLength(), 0u);
     }
@@ -615,26 +584,23 @@
 TEST_F(Dex2oatVeryLargeTest, DontUseVeryLarge) {
   RunTest(CompilerFilter::kAssumeVerified, false, false);
   RunTest(CompilerFilter::kExtract, false, false);
-  RunTest(CompilerFilter::kQuicken, false, false);
   RunTest(CompilerFilter::kSpeed, false, false);
 
   RunTest(CompilerFilter::kAssumeVerified, false, false, { "--very-large-app-threshold=10000000" });
   RunTest(CompilerFilter::kExtract, false, false, { "--very-large-app-threshold=10000000" });
-  RunTest(CompilerFilter::kQuicken, false, false, { "--very-large-app-threshold=10000000" });
   RunTest(CompilerFilter::kSpeed, false, false, { "--very-large-app-threshold=10000000" });
 }
 
 TEST_F(Dex2oatVeryLargeTest, UseVeryLarge) {
   RunTest(CompilerFilter::kAssumeVerified, true, false, { "--very-large-app-threshold=100" });
   RunTest(CompilerFilter::kExtract, true, false, { "--very-large-app-threshold=100" });
-  RunTest(CompilerFilter::kQuicken, true, true, { "--very-large-app-threshold=100" });
   RunTest(CompilerFilter::kSpeed, true, true, { "--very-large-app-threshold=100" });
 }
 
 // Regressin test for b/35665292.
 TEST_F(Dex2oatVeryLargeTest, SpeedProfileNoProfile) {
   // Test that dex2oat doesn't crash with speed-profile but no input profile.
-  RunTest(CompilerFilter::kSpeedProfile, false, false);
+  RunTest(CompilerFilter::kSpeedProfile, CompilerFilter::kVerify, false, false);
 }
 
 class Dex2oatLayoutTest : public Dex2oatTest {
@@ -730,10 +696,10 @@
                          /*use_fd=*/ false,
                          /*num_profile_classes=*/ 0);
       CheckValidity();
-      ASSERT_TRUE(success_);
       // Don't check the result since CheckResult relies on the class being in the profile.
       image_file_empty_profile = GetImageObjectSectionSize(app_image_file);
       EXPECT_GT(image_file_empty_profile, 0u);
+      CheckCompilerFilter(dex_location, odex_location, CompilerFilter::Filter::kVerify);
     }
 
     // Small profile.
@@ -743,8 +709,8 @@
                        /*use_fd=*/ false,
                        /*num_profile_classes=*/ 1);
     CheckValidity();
-    ASSERT_TRUE(success_);
     CheckResult(dex_location, odex_location, app_image_file);
+    CheckCompilerFilter(dex_location, odex_location, CompilerFilter::Filter::kSpeedProfile);
 
     if (app_image) {
       // Test that the profile made a difference by adding more classes.
@@ -753,6 +719,21 @@
     }
   }
 
+  void CheckCompilerFilter(
+      const std::string& dex_location,
+      const std::string& odex_location,
+      CompilerFilter::Filter expected_filter) {
+    std::string error_msg;
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/ -1,
+                                                     odex_location.c_str(),
+                                                     odex_location.c_str(),
+                                                     /*executable=*/ false,
+                                                     /*low_4gb=*/ false,
+                                                     dex_location,
+                                                     &error_msg));
+    EXPECT_EQ(odex_file->GetCompilerFilter(), expected_filter);
+  }
+
   void RunTestVDex() {
     std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
     std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
@@ -789,7 +770,6 @@
     }
     ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
     CheckValidity();
-    ASSERT_TRUE(success_);
   }
 
   void CheckResult(const std::string& dex_location,
@@ -874,148 +854,6 @@
   RunTestVDex();
 }
 
-class Dex2oatUnquickenTest : public Dex2oatTest {
- protected:
-  void RunUnquickenMultiDex() {
-    std::string dex_location = GetScratchDir() + "/UnquickenMultiDex.jar";
-    std::string odex_location = GetOdexDir() + "/UnquickenMultiDex.odex";
-    std::string vdex_location = GetOdexDir() + "/UnquickenMultiDex.vdex";
-    Copy(GetTestDexFileName("MultiDex"), dex_location);
-
-    std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
-    CHECK(vdex_file1 != nullptr) << vdex_location;
-    // Quicken the dex file into a vdex file.
-    {
-      std::string input_vdex = "--input-vdex-fd=-1";
-      std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
-      ASSERT_TRUE(GenerateOdexForTest(dex_location,
-                                      odex_location,
-                                      CompilerFilter::kQuicken,
-                                      { input_vdex, output_vdex },
-                                      /* expect_success= */ true,
-                                      /* use_fd= */ true));
-      EXPECT_GT(vdex_file1->GetLength(), 0u);
-    }
-    // Get the dex file checksums.
-    std::vector<uint32_t> checksums1;
-    GetDexFileChecksums(dex_location, odex_location, &checksums1);
-    // Unquicken by running the verify compiler filter on the vdex file.
-    {
-      std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
-      std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
-      ASSERT_TRUE(GenerateOdexForTest(dex_location,
-                                      odex_location,
-                                      CompilerFilter::kVerify,
-                                      { input_vdex, output_vdex, kDisableCompactDex },
-                                      /* expect_success= */ true,
-                                      /* use_fd= */ true));
-    }
-    ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
-    CheckResult(dex_location, odex_location);
-    // Verify that the checksums did not change.
-    std::vector<uint32_t> checksums2;
-    GetDexFileChecksums(dex_location, odex_location, &checksums2);
-    ASSERT_EQ(checksums1.size(), checksums2.size());
-    for (size_t i = 0; i != checksums1.size(); ++i) {
-      EXPECT_EQ(checksums1[i], checksums2[i]) << i;
-    }
-    ASSERT_TRUE(success_);
-  }
-
-  void RunUnquickenMultiDexCDex() {
-    std::string dex_location = GetScratchDir() + "/UnquickenMultiDex.jar";
-    std::string odex_location = GetOdexDir() + "/UnquickenMultiDex.odex";
-    std::string odex_location2 = GetOdexDir() + "/UnquickenMultiDex2.odex";
-    std::string vdex_location = GetOdexDir() + "/UnquickenMultiDex.vdex";
-    std::string vdex_location2 = GetOdexDir() + "/UnquickenMultiDex2.vdex";
-    Copy(GetTestDexFileName("MultiDex"), dex_location);
-
-    std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
-    std::unique_ptr<File> vdex_file2(OS::CreateEmptyFile(vdex_location2.c_str()));
-    CHECK(vdex_file1 != nullptr) << vdex_location;
-    CHECK(vdex_file2 != nullptr) << vdex_location2;
-
-    // Quicken the dex file into a vdex file.
-    {
-      std::string input_vdex = "--input-vdex-fd=-1";
-      std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
-      ASSERT_TRUE(GenerateOdexForTest(dex_location,
-                                      odex_location,
-                                      CompilerFilter::kQuicken,
-                                      { input_vdex, output_vdex, "--compact-dex-level=fast"},
-                                      /* expect_success= */ true,
-                                      /* use_fd= */ true));
-      EXPECT_GT(vdex_file1->GetLength(), 0u);
-    }
-    // Unquicken by running the verify compiler filter on the vdex file.
-    {
-      std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
-      std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2->Fd());
-      ASSERT_TRUE(GenerateOdexForTest(dex_location,
-                                      odex_location2,
-                                      CompilerFilter::kVerify,
-                                      { input_vdex, output_vdex, "--compact-dex-level=none"},
-                                      /* expect_success= */ true,
-                                      /* use_fd= */ true));
-    }
-    ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
-    ASSERT_EQ(vdex_file2->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
-    CheckResult(dex_location, odex_location2);
-    ASSERT_TRUE(success_);
-  }
-
-  void CheckResult(const std::string& dex_location, const std::string& odex_location) {
-    std::string error_msg;
-    std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/ -1,
-                                                     odex_location.c_str(),
-                                                     odex_location.c_str(),
-                                                     /*executable=*/ false,
-                                                     /*low_4gb=*/ false,
-                                                     dex_location,
-                                                     &error_msg));
-    ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
-    ASSERT_GE(odex_file->GetOatDexFiles().size(), 1u);
-
-    // Iterate over the dex files and ensure there is no quickened instruction.
-    for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
-      std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
-      for (ClassAccessor accessor : dex_file->GetClasses()) {
-        for (const ClassAccessor::Method& method : accessor.GetMethods()) {
-          for (const DexInstructionPcPair& inst : method.GetInstructions()) {
-            ASSERT_FALSE(inst->IsQuickened()) << inst->Opcode() << " " << output_;
-          }
-        }
-      }
-    }
-  }
-
-  void GetDexFileChecksums(const std::string& dex_location,
-                           const std::string& odex_location,
-                           /*out*/std::vector<uint32_t>* checksums) {
-    std::string error_msg;
-    std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/ -1,
-                                                     odex_location.c_str(),
-                                                     odex_location.c_str(),
-                                                     /*executable=*/ false,
-                                                     /*low_4gb=*/ false,
-                                                     dex_location,
-                                                     &error_msg));
-    ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
-    ASSERT_GE(odex_file->GetOatDexFiles().size(), 1u);
-    for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
-      checksums->push_back(oat_dex_file->GetDexFileLocationChecksum());
-    }
-  }
-};
-
-TEST_F(Dex2oatUnquickenTest, UnquickenMultiDex) {
-  RunUnquickenMultiDex();
-}
-
-TEST_F(Dex2oatUnquickenTest, UnquickenMultiDexCDex) {
-  RunUnquickenMultiDexCDex();
-}
-
 class Dex2oatWatchdogTest : public Dex2oatTest {
  protected:
   void RunTest(bool expect_success, const std::vector<std::string>& extra_args = {}) {
@@ -1084,12 +922,6 @@
   }
 };
 
-TEST_F(Dex2oatReturnCodeTest, TestCreateRuntime) {
-  TEST_DISABLED_FOR_MEMORY_TOOL();  // b/19100793
-  int status = RunTest({ "--boot-image=/this/does/not/exist/yolo.oat" });
-  EXPECT_EQ(static_cast<int>(dex2oat::ReturnCode::kCreateRuntime), WEXITSTATUS(status)) << output_;
-}
-
 class Dex2oatClassLoaderContextTest : public Dex2oatTest {
  protected:
   void RunTest(const char* class_loader_context,
@@ -1119,7 +951,7 @@
 
     ASSERT_TRUE(GenerateOdexForTest(dex_location,
                                     odex_location,
-                                    CompilerFilter::kQuicken,
+                                    CompilerFilter::kVerify,
                                     extra_args,
                                     expected_success,
                                     /*use_fd=*/ false,
@@ -1150,12 +982,6 @@
   RunTest("PCL[]", kEmptyClassPathKey, /*expected_success*/ true);
 }
 
-TEST_F(Dex2oatClassLoaderContextTest, SpecialContext) {
-  RunTest(OatFile::kSpecialSharedLibrary,
-          OatFile::kSpecialSharedLibrary,
-          /*expected_success*/ true);
-}
-
 TEST_F(Dex2oatClassLoaderContextTest, ContextWithTheSourceDexFiles) {
   std::string context = "PCL[" + GetUsedDexLocation() + "]";
   RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
@@ -1170,55 +996,15 @@
   RunTest(context.c_str(), expected_classpath_key.c_str(), true);
 }
 
-TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFiles) {
-  std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
-  Copy(GetStrippedDexSrc1(), stripped_classpath);
+TEST_F(Dex2oatClassLoaderContextTest, ContextWithResourceOnlyDexFiles) {
+  std::string resource_only_classpath = GetScratchDir() + "/resource_only_classpath.jar";
+  Copy(GetResourceOnlySrc1(), resource_only_classpath);
 
-  std::string context = "PCL[" + stripped_classpath + "]";
-  // Expect an empty context because stripped dex files cannot be open.
+  std::string context = "PCL[" + resource_only_classpath + "]";
+  // Expect an empty context because resource only dex files cannot be open.
   RunTest(context.c_str(), kEmptyClassPathKey , /*expected_success*/ true);
 }
 
-TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFilesBackedByOdex) {
-  std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
-  std::string odex_for_classpath = GetOdexDir() + "/stripped_classpath.odex";
-
-  Copy(GetDexSrc1(), stripped_classpath);
-
-  ASSERT_TRUE(GenerateOdexForTest(stripped_classpath,
-                                  odex_for_classpath,
-                                  CompilerFilter::kQuicken,
-                                  {},
-                                  true));
-
-  // Strip the dex file
-  Copy(GetStrippedDexSrc1(), stripped_classpath);
-
-  std::string context = "PCL[" + stripped_classpath + "]";
-  std::string expected_classpath_key;
-  {
-    // Open the oat file to get the expected classpath.
-    OatFileAssistant oat_file_assistant(stripped_classpath.c_str(), kRuntimeISA, false, false);
-    std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile());
-    std::vector<std::unique_ptr<const DexFile>> oat_dex_files =
-        OatFileAssistant::LoadDexFiles(*oat_file, stripped_classpath.c_str());
-    expected_classpath_key = "PCL[";
-    for (size_t i = 0; i < oat_dex_files.size(); i++) {
-      if (i > 0) {
-        expected_classpath_key + ":";
-      }
-      expected_classpath_key += oat_dex_files[i]->GetLocation() + "*" +
-          std::to_string(oat_dex_files[i]->GetLocationChecksum());
-    }
-    expected_classpath_key += "]";
-  }
-
-  RunTest(context.c_str(),
-          expected_classpath_key.c_str(),
-          /*expected_success*/ true,
-          /*use_second_source*/ true);
-}
-
 TEST_F(Dex2oatClassLoaderContextTest, ContextWithNotExistentDexFiles) {
   std::string context = "PCL[does_not_exists.dex]";
   // Expect an empty context because stripped dex files cannot be open.
@@ -1308,7 +1094,6 @@
   const std::string unload_vdex_name = out_dir + "/unload.vdex";
   const std::string no_unload_oat_name = out_dir + "/nounload.oat";
   const std::string no_unload_vdex_name = out_dir + "/nounload.vdex";
-  const std::string app_image_name = out_dir + "/unload.art";
   std::string error_msg;
   const std::vector<gc::space::ImageSpace*>& spaces = runtime->GetHeap()->GetBootImageSpaces();
   ASSERT_GT(spaces.size(), 0u);
@@ -1317,7 +1102,7 @@
   const int res = GenerateOdexForTestWithStatus(
       GetLibCoreDexFileNames(),
       base_oat_name,
-      CompilerFilter::Filter::kQuicken,
+      CompilerFilter::Filter::kVerify,
       &error_msg,
       {"--force-determinism", "--avoid-storing-invocation"});
   ASSERT_EQ(res, 0);
@@ -1334,9 +1119,9 @@
   const int res2 = GenerateOdexForTestWithStatus(
       GetLibCoreDexFileNames(),
       base_oat_name,
-      CompilerFilter::Filter::kQuicken,
+      CompilerFilter::Filter::kVerify,
       &error_msg,
-      {"--force-determinism", "--avoid-storing-invocation", "--app-image-file=" + app_image_name});
+      {"--force-determinism", "--avoid-storing-invocation", "--compile-individually"});
   ASSERT_EQ(res2, 0);
   Copy(base_oat_name, no_unload_oat_name);
   Copy(base_vdex_name, no_unload_vdex_name);
@@ -1353,10 +1138,6 @@
       << unload_oat_name << " " << no_unload_oat_name;
   EXPECT_EQ(unload_vdex->Compare(no_unload_vdex.get()), 0)
       << unload_vdex_name << " " << no_unload_vdex_name;
-  // App image file.
-  std::unique_ptr<File> app_image_file(OS::OpenFileForReading(app_image_name.c_str()));
-  ASSERT_TRUE(app_image_file != nullptr);
-  EXPECT_GT(app_image_file->GetLength(), 0u);
 }
 
 // Test that dexlayout section info is correctly written to the oat file for profile based
@@ -1423,7 +1204,7 @@
   const int res = GenerateOdexForTestWithStatus(
       {dex->GetLocation()},
       oat_filename,
-      CompilerFilter::Filter::kQuicken,
+      CompilerFilter::Filter::kVerify,
       &error_msg,
       {"--profile-file=" + profile_file.GetFilename()});
   EXPECT_EQ(res, 0);
@@ -1532,7 +1313,7 @@
   const int res = GenerateOdexForTestWithStatus(
       { dex_location },
       oat_filename,
-      CompilerFilter::Filter::kQuicken,
+      CompilerFilter::Filter::kVerify,
       &error_msg,
       {"--compact-dex-level=fast"});
   EXPECT_EQ(res, 0);
@@ -1592,7 +1373,7 @@
   const int res_fail = GenerateOdexForTestWithStatus(
         {dex->GetLocation()},
         base_oat_name,
-        CompilerFilter::Filter::kQuicken,
+        CompilerFilter::Filter::kVerify,
         &error_msg,
         {"--abort-on-hard-verifier-error"});
   EXPECT_NE(0, res_fail);
@@ -1600,14 +1381,14 @@
   const int res_no_fail = GenerateOdexForTestWithStatus(
         {dex->GetLocation()},
         base_oat_name,
-        CompilerFilter::Filter::kQuicken,
+        CompilerFilter::Filter::kVerify,
         &error_msg,
         {"--no-abort-on-hard-verifier-error"});
   EXPECT_EQ(0, res_no_fail);
 }
 
 TEST_F(Dex2oatVerifierAbort, SoftFail) {
-  // Use VerifierDepsMulti as it has hard-failing classes.
+  // Use VerifierDepsMulti as it has soft-failing classes.
   std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDepsMulti"));
   std::string out_dir = GetScratchDir();
   const std::string base_oat_name = out_dir + "/base.oat";
@@ -1615,7 +1396,7 @@
   const int res_fail = GenerateOdexForTestWithStatus(
         {dex->GetLocation()},
         base_oat_name,
-        CompilerFilter::Filter::kQuicken,
+        CompilerFilter::Filter::kVerify,
         &error_msg,
         {"--abort-on-soft-verifier-error"});
   EXPECT_NE(0, res_fail);
@@ -1623,7 +1404,7 @@
   const int res_no_fail = GenerateOdexForTestWithStatus(
         {dex->GetLocation()},
         base_oat_name,
-        CompilerFilter::Filter::kQuicken,
+        CompilerFilter::Filter::kVerify,
         &error_msg,
         {"--no-abort-on-soft-verifier-error"});
   EXPECT_EQ(0, res_no_fail);
@@ -1669,7 +1450,7 @@
   const std::string base_oat_name = out_dir + "/base.oat";
   ASSERT_TRUE(GenerateOdexForTest(dex->GetLocation(),
                                   base_oat_name,
-                                  CompilerFilter::Filter::kQuicken,
+                                  CompilerFilter::Filter::kVerify,
                                   { },
                                   /*expect_success=*/ true,
                                   /*use_fd=*/ false,
@@ -1679,6 +1460,22 @@
                                   }));
 }
 
+TEST_F(Dex2oatTest, MissingBootImageTest) {
+  std::string out_dir = GetScratchDir();
+  const std::string base_oat_name = out_dir + "/base.oat";
+  std::string error_msg;
+  int status = GenerateOdexForTestWithStatus(
+      { GetTestDexFileName("MainUncompressedAligned") },
+      base_oat_name,
+      CompilerFilter::Filter::kVerify,
+      &error_msg,
+      // Note: Extra options go last and the second `--boot-image` option overrides the first.
+      { "--boot-image=/nonx/boot.art" });
+  // Expect to fail with code 1 and not SIGSEGV or SIGABRT.
+  ASSERT_TRUE(WIFEXITED(status));
+  ASSERT_EQ(WEXITSTATUS(status), 1) << error_msg;
+}
+
 TEST_F(Dex2oatTest, EmptyUncompressedDexTest) {
   std::string out_dir = GetScratchDir();
   const std::string base_oat_name = out_dir + "/base.oat";
@@ -1686,7 +1483,7 @@
   int status = GenerateOdexForTestWithStatus(
       { GetTestDexFileName("MainEmptyUncompressed") },
       base_oat_name,
-      CompilerFilter::Filter::kQuicken,
+      CompilerFilter::Filter::kVerify,
       &error_msg,
       { },
       /*use_fd*/ false);
@@ -1702,7 +1499,7 @@
   int status = GenerateOdexForTestWithStatus(
       { GetTestDexFileName("MainEmptyUncompressedAligned") },
       base_oat_name,
-      CompilerFilter::Filter::kQuicken,
+      CompilerFilter::Filter::kVerify,
       &error_msg,
       { },
       /*use_fd*/ false);
@@ -1841,7 +1638,7 @@
   const std::string odex_location = GetOdexDir() + "/output.odex";
   ASSERT_TRUE(GenerateOdexForTest(dex_location,
                                   odex_location,
-                                  CompilerFilter::kQuicken,
+                                  CompilerFilter::kVerify,
                                   { "--compact-dex-level=fast" },
                                   true));
 }
@@ -1855,7 +1652,7 @@
 
   ASSERT_TRUE(GenerateOdexForTest(dex_location,
                                   odex_location,
-                                  CompilerFilter::kQuicken,
+                                  CompilerFilter::kVerify,
                                   { "--runtime-arg", "-Xuse-stderr-logger" },
                                   true));
   // Look for some random part of dex2oat logging. With the stderr logger this should be captured,
@@ -2001,89 +1798,10 @@
     EXPECT_TRUE(found_fast_verify) << "Expected to find " << kFastVerifyString << "\n" << output_;
   };
 
-  // Generate a quickened dex by using the input dm file to verify.
-  generate_and_check(CompilerFilter::Filter::kQuicken);
-  // Use verify compiler filter to sanity check that FastVerify works for that filter too.
+  // Use verify compiler filter to check that FastVerify works for that filter too.
   generate_and_check(CompilerFilter::Filter::kVerify);
 }
 
-// Test that dex files with quickened opcodes aren't dequickened.
-TEST_F(Dex2oatTest, QuickenedInput) {
-  std::string error_msg;
-  ScratchFile temp_dex;
-  MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [] (DexFile* dex) {
-    bool mutated_successfully = false;
-    // Change the dex instructions to make an opcode that spans past the end of the code item.
-    for (ClassAccessor accessor : dex->GetClasses()) {
-      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
-        CodeItemInstructionAccessor instructions = method.GetInstructions();
-        // Make a quickened instruction that doesn't run past the end of the code item.
-        if (instructions.InsnsSizeInCodeUnits() > 2) {
-          const_cast<Instruction&>(instructions.InstructionAt(0)).SetOpcode(
-              Instruction::IGET_BYTE_QUICK);
-          mutated_successfully = true;
-        }
-      }
-    }
-    CHECK(mutated_successfully)
-        << "Failed to find candidate code item with only one code unit in last instruction.";
-  });
-
-  const std::string& dex_location = temp_dex.GetFilename();
-  std::string odex_location = GetOdexDir() + "/quickened.odex";
-  std::string vdex_location = GetOdexDir() + "/quickened.vdex";
-  std::unique_ptr<File> vdex_output(OS::CreateEmptyFile(vdex_location.c_str()));
-  // Quicken the dex
-  {
-    std::string input_vdex = "--input-vdex-fd=-1";
-    std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_output->Fd());
-    ASSERT_TRUE(GenerateOdexForTest(dex_location,
-                                    odex_location,
-                                    CompilerFilter::kQuicken,
-                                    // Disable cdex since we want to compare against the original
-                                    // dex file after unquickening.
-                                    { input_vdex, output_vdex, kDisableCompactDex },
-                                    /* expect_success= */ true,
-                                    /* use_fd= */ true));
-  }
-  // Unquicken by running the verify compiler filter on the vdex file and verify it matches.
-  std::string odex_location2 = GetOdexDir() + "/unquickened.odex";
-  std::string vdex_location2 = GetOdexDir() + "/unquickened.vdex";
-  std::unique_ptr<File> vdex_unquickened(OS::CreateEmptyFile(vdex_location2.c_str()));
-  {
-    std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_output->Fd());
-    std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_unquickened->Fd());
-    ASSERT_TRUE(GenerateOdexForTest(dex_location,
-                                    odex_location2,
-                                    CompilerFilter::kVerify,
-                                    // Disable cdex to avoid needing to write out the shared
-                                    // section.
-                                    { input_vdex, output_vdex, kDisableCompactDex },
-                                    /* expect_success= */ true,
-                                    /* use_fd= */ true));
-  }
-  ASSERT_EQ(vdex_unquickened->Flush(), 0) << "Could not flush and close vdex file";
-  ASSERT_TRUE(success_);
-  {
-    // Check that hte vdex has one dex and compare it to the original one.
-    std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location2.c_str(),
-                                                  /*writable*/ false,
-                                                  /*low_4gb*/ false,
-                                                  /*unquicken*/ false,
-                                                  &error_msg));
-    std::vector<std::unique_ptr<const DexFile>> dex_files;
-    bool result = vdex->OpenAllDexFiles(&dex_files, &error_msg);
-    ASSERT_TRUE(result) << error_msg;
-    ASSERT_EQ(dex_files.size(), 1u) << error_msg;
-    ScratchFile temp;
-    ASSERT_TRUE(temp.GetFile()->WriteFully(dex_files[0]->Begin(), dex_files[0]->Size()));
-    ASSERT_EQ(temp.GetFile()->Flush(), 0) << "Could not flush extracted dex";
-    EXPECT_EQ(temp.GetFile()->Compare(temp_dex.GetFile()), 0);
-  }
-  ASSERT_EQ(vdex_output->FlushCloseOrErase(), 0) << "Could not flush and close";
-  ASSERT_EQ(vdex_unquickened->FlushCloseOrErase(), 0) << "Could not flush and close";
-}
-
 // Test that compact dex generation with invalid dex files doesn't crash dex2oat. b/75970654
 TEST_F(Dex2oatTest, CompactDexInvalidSource) {
   ScratchFile invalid_dex;
@@ -2111,7 +1829,7 @@
   int status = GenerateOdexForTestWithStatus(
       {dex_location},
       odex_location,
-      CompilerFilter::kQuicken,
+      CompilerFilter::kVerify,
       &error_msg,
       { "--compact-dex-level=fast" });
   ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
@@ -2150,7 +1868,7 @@
   status = GenerateOdexForTestWithStatus(
       { invalid_dex_zip.GetFilename() },
       GetOdexDir() + "/output_apk.odex",
-      CompilerFilter::kQuicken,
+      CompilerFilter::kVerify,
       &error_msg,
       { "--compact-dex-level=fast" });
   ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
@@ -2158,13 +1876,16 @@
   status = GenerateOdexForTestWithStatus(
       { invalid_dex.GetFilename() },
       GetOdexDir() + "/output.odex",
-      CompilerFilter::kQuicken,
+      CompilerFilter::kVerify,
       &error_msg,
       { "--compact-dex-level=fast" });
   ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
 }
 
-TEST_F(Dex2oatTest, AppImageNoProfile) {
+TEST_F(Dex2oatWithExpectedFilterTest, AppImageNoProfile) {
+  // Set the expected filter.
+  expected_filter_ = CompilerFilter::Filter::kVerify;
+
   ScratchFile app_image_file;
   const std::string out_dir = GetScratchDir();
   const std::string odex_location = out_dir + "/base.odex";
@@ -2206,14 +1927,17 @@
   const std::string base_oat_name = out_dir + "/base.oat";
   ASSERT_TRUE(GenerateOdexForTest(zip_location,
                                   base_oat_name,
-                                  CompilerFilter::Filter::kQuicken,
+                                  CompilerFilter::Filter::kVerify,
                                   extra_args,
                                   /*expect_success=*/ true,
                                   /*use_fd=*/ false,
                                   /*use_zip_fd=*/ true));
 }
 
-TEST_F(Dex2oatTest, AppImageEmptyDex) {
+TEST_F(Dex2oatWithExpectedFilterTest, AppImageEmptyDex) {
+  // Set the expected filter.
+  expected_filter_ = CompilerFilter::Filter::kVerify;
+
   // Create a profile with the startup method marked.
   ScratchFile profile_file;
   ScratchFile temp_dex;
@@ -2305,7 +2029,7 @@
   };
   ASSERT_TRUE(GenerateOdexForTest(dex_location,
                                   base_oat_name,
-                                  CompilerFilter::Filter::kQuicken,
+                                  CompilerFilter::Filter::kVerify,
                                   extra_args,
                                   /*expect_success=*/ true,
                                   /*use_fd=*/ false,
@@ -2411,43 +2135,17 @@
         seen.insert(str.Read()->ToModifiedUtf8());
       }
     });
-    // Ensure that the dex cache has a preresolved string array.
-    std::set<std::string> preresolved_seen;
-    bool saw_dexcache = false;
-    space->GetLiveBitmap()->VisitAllMarked(
-        [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
-      if (obj->IsDexCache<kVerifyNone>()) {
-        ObjPtr<mirror::DexCache> dex_cache = obj->AsDexCache();
-        GcRoot<mirror::String>* preresolved_strings = dex_cache->GetPreResolvedStrings();
-        ASSERT_EQ(dex_file->NumStringIds(), dex_cache->NumPreResolvedStrings());
-        for (size_t i = 0; i < dex_cache->NumPreResolvedStrings(); ++i) {
-          ObjPtr<mirror::String> string = preresolved_strings[i].Read<kWithoutReadBarrier>();
-          if (string != nullptr) {
-            preresolved_seen.insert(string->ToModifiedUtf8());
-          }
-        }
-        saw_dexcache = true;
-      }
-    });
-    ASSERT_TRUE(saw_dexcache);
-    // Everything in the preresolved array should also be in the intern table.
-    for (const std::string& str : preresolved_seen) {
-      EXPECT_TRUE(seen.find(str) != seen.end());
-    }
     // Normal methods
-    EXPECT_TRUE(preresolved_seen.find("Loading ") != preresolved_seen.end());
-    EXPECT_TRUE(preresolved_seen.find("Starting up") != preresolved_seen.end());
-    EXPECT_TRUE(preresolved_seen.find("abcd.apk") != preresolved_seen.end());
+    EXPECT_TRUE(seen.find("Loading ") != seen.end());
+    EXPECT_TRUE(seen.find("Starting up") != seen.end());
+    EXPECT_TRUE(seen.find("abcd.apk") != seen.end());
     EXPECT_TRUE(seen.find("Unexpected error") == seen.end());
     EXPECT_TRUE(seen.find("Shutting down!") == seen.end());
-    EXPECT_TRUE(preresolved_seen.find("Unexpected error") == preresolved_seen.end());
-    EXPECT_TRUE(preresolved_seen.find("Shutting down!") == preresolved_seen.end());
     // Classes initializers
-    EXPECT_TRUE(preresolved_seen.find("Startup init") != preresolved_seen.end());
+    EXPECT_TRUE(seen.find("Startup init") != seen.end());
     EXPECT_TRUE(seen.find("Other class init") == seen.end());
-    EXPECT_TRUE(preresolved_seen.find("Other class init") == preresolved_seen.end());
     // Expect the sets match.
-    EXPECT_GE(seen.size(), preresolved_seen.size());
+    EXPECT_GE(seen.size(), seen.size());
 
     // Verify what strings are marked as boot image.
     std::set<std::string> boot_image_strings;
@@ -2492,7 +2190,7 @@
   // The class path should not be valid and should fail being stored.
   EXPECT_TRUE(GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
                                   odex_location,
-                                  CompilerFilter::Filter::kQuicken,
+                                  CompilerFilter::Filter::kVerify,
                                   { "--class-loader-context=" + stored_context },
                                   /*expect_success=*/ true,
                                   /*use_fd=*/ false,
@@ -2504,7 +2202,7 @@
   // The stored context should match what we expect even though it's invalid.
   EXPECT_TRUE(GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
                                   odex_location,
-                                  CompilerFilter::Filter::kQuicken,
+                                  CompilerFilter::Filter::kVerify,
                                   { "--class-loader-context=" + valid_context,
                                     "--stored-class-loader-context=" + stored_context },
                                   /*expect_success=*/ true,
@@ -2549,4 +2247,133 @@
   RunTest();
 }
 
+class LinkageTest : public Dex2oatTest {};
+
+TEST_F(LinkageTest, LinkageEnabled) {
+  TEST_DISABLED_FOR_TARGET();
+  std::unique_ptr<const DexFile> dex(OpenTestDexFile("LinkageTest"));
+  std::string out_dir = GetScratchDir();
+  const std::string base_oat_name = out_dir + "/base.oat";
+  std::string error_msg;
+  const int res_fail = GenerateOdexForTestWithStatus(
+        {dex->GetLocation()},
+        base_oat_name,
+        CompilerFilter::Filter::kSpeed,
+        &error_msg,
+        {"--check-linkage-conditions", "--crash-on-linkage-violation"});
+  EXPECT_NE(0, res_fail);
+
+  const int res_no_fail = GenerateOdexForTestWithStatus(
+        {dex->GetLocation()},
+        base_oat_name,
+        CompilerFilter::Filter::kSpeed,
+        &error_msg,
+        {"--check-linkage-conditions"});
+  EXPECT_EQ(0, res_no_fail);
+}
+
+// Regression test for bug 179221298.
+TEST_F(Dex2oatTest, LoadOutOfDateOatFile) {
+  std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
+  std::string out_dir = GetScratchDir();
+  const std::string base_oat_name = out_dir + "/base.oat";
+  ASSERT_TRUE(GenerateOdexForTest(dex->GetLocation(),
+                                  base_oat_name,
+                                  CompilerFilter::Filter::kSpeed,
+                                  { "--deduplicate-code=false" },
+                                  /*expect_success=*/ true,
+                                  /*use_fd=*/ false,
+                                  /*use_zip_fd=*/ false));
+
+  // Check that we can open the oat file as executable.
+  {
+    std::string error_msg;
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/ -1,
+                                                     base_oat_name.c_str(),
+                                                     base_oat_name.c_str(),
+                                                     /*executable=*/ true,
+                                                     /*low_4gb=*/ false,
+                                                     dex->GetLocation(),
+                                                     &error_msg));
+    ASSERT_TRUE(odex_file != nullptr) << error_msg;
+  }
+
+  // Rewrite the oat file with wrong version and bogus contents.
+  {
+    std::unique_ptr<File> file(OS::OpenFileReadWrite(base_oat_name.c_str()));
+    ASSERT_TRUE(file != nullptr);
+    // Retrieve the offset and size of the embedded oat file.
+    size_t oatdata_offset;
+    size_t oatdata_size;
+    {
+      std::string error_msg;
+      std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.get(),
+                                                      /*writable=*/ false,
+                                                      /*program_header_only=*/ true,
+                                                      /*low_4gb=*/ false,
+                                                      &error_msg));
+      ASSERT_TRUE(elf_file != nullptr) << error_msg;
+      ASSERT_TRUE(elf_file->Load(file.get(),
+                                 /*executable=*/ false,
+                                 /*low_4gb=*/ false,
+                                 /*reservation=*/ nullptr,
+                                 &error_msg)) << error_msg;
+      const uint8_t* base_address = elf_file->Is64Bit()
+          ? elf_file->GetImpl64()->GetBaseAddress()
+          : elf_file->GetImpl32()->GetBaseAddress();
+      const uint8_t* oatdata = elf_file->FindDynamicSymbolAddress("oatdata");
+      ASSERT_TRUE(oatdata != nullptr);
+      ASSERT_TRUE(oatdata > base_address);
+      // Note: We're assuming here that the virtual address offset is the same
+      // as file offset. This is currently true for all oat files we generate.
+      oatdata_offset = static_cast<size_t>(oatdata - base_address);
+      const uint8_t* oatlastword = elf_file->FindDynamicSymbolAddress("oatlastword");
+      ASSERT_TRUE(oatlastword != nullptr);
+      ASSERT_TRUE(oatlastword > oatdata);
+      oatdata_size = oatlastword - oatdata;
+    }
+
+    // Check that we have the right `oatdata_offset`.
+    int64_t length = file->GetLength();
+    ASSERT_GE(length, static_cast<ssize_t>(oatdata_offset + sizeof(OatHeader)));
+    alignas(OatHeader) uint8_t header_data[sizeof(OatHeader)];
+    ASSERT_TRUE(file->PreadFully(header_data, sizeof(header_data), oatdata_offset));
+    const OatHeader& header = reinterpret_cast<const OatHeader&>(header_data);
+    ASSERT_TRUE(header.IsValid()) << header.GetValidationErrorMessage();
+
+    // Overwrite all oat data from version onwards with bytes with value 4.
+    // (0x04040404 is not a valid version, we're using three decimal digits and '\0'.)
+    //
+    // We previously tried to find the value for key "debuggable" (bug 179221298)
+    // in the key-value store before checking the oat header. This test tries to
+    // ensure that such early processing of the key-value store shall crash.
+    // Reading 0x04040404 as the size of the key-value store yields a bit over
+    // 64MiB which should hopefully include some unmapped memory beyond the end
+    // of the loaded oat file. Overwriting the whole embedded oat file ensures
+    // that we do not match the key within the oat file but we could still
+    // accidentally match it in the additional sections of the elf file, so this
+    // approach could fail to catch similar issues. At the time of writing, this
+    // test crashed when run without the fix on 64-bit host (but not 32-bit).
+    static constexpr size_t kVersionOffset = sizeof(OatHeader::kOatMagic);
+    static_assert(kVersionOffset < sizeof(OatHeader));
+    std::vector<uint8_t> data(oatdata_size - kVersionOffset, 4u);
+    ASSERT_TRUE(file->PwriteFully(data.data(), data.size(), oatdata_offset + kVersionOffset));
+    UNUSED(oatdata_size);
+    CHECK_EQ(file->FlushClose(), 0) << "Could not flush and close oat file";
+  }
+
+  // Check that we reject the oat file without crashing.
+  {
+    std::string error_msg;
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/ -1,
+                                                     base_oat_name.c_str(),
+                                                     base_oat_name.c_str(),
+                                                     /*executable=*/ true,
+                                                     /*low_4gb=*/ false,
+                                                     dex->GetLocation(),
+                                                     &error_msg));
+    ASSERT_FALSE(odex_file != nullptr);
+  }
+}
+
 }  // namespace art
diff --git a/dex2oat/dex2oat_vdex_test.cc b/dex2oat/dex2oat_vdex_test.cc
new file mode 100644
index 0000000..3b980e0
--- /dev/null
+++ b/dex2oat/dex2oat_vdex_test.cc
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2020 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 <string>
+#include <vector>
+
+#include "common_runtime_test.h"
+#include "dex2oat_environment_test.h"
+
+#include "vdex_file.h"
+#include "verifier/verifier_deps.h"
+#include "ziparchive/zip_writer.h"
+
+namespace art {
+
+using verifier::VerifierDeps;
+
+class Dex2oatVdexTest : public Dex2oatEnvironmentTest {
+ public:
+  void TearDown() override {
+    Dex2oatEnvironmentTest::TearDown();
+
+    output_ = "";
+    error_msg_ = "";
+    opened_vdex_files_.clear();
+  }
+
+ protected:
+  bool RunDex2oat(const std::string& dex_location,
+                  const std::string& odex_location,
+                  const std::string* public_sdk,
+                  bool copy_dex_files = false,
+                  const std::vector<std::string>& extra_args = {}) {
+    std::vector<std::string> args;
+    args.push_back("--dex-file=" + dex_location);
+    args.push_back("--oat-file=" + odex_location);
+    if (public_sdk != nullptr) {
+      args.push_back("--public-sdk=" + *public_sdk);
+    }
+    args.push_back("--compiler-filter=" +
+        CompilerFilter::NameOfFilter(CompilerFilter::Filter::kVerify));
+    args.push_back("--runtime-arg");
+    args.push_back("-Xnorelocate");
+    if (!copy_dex_files) {
+      args.push_back("--copy-dex-files=false");
+    }
+    args.push_back("--runtime-arg");
+    args.push_back("-verbose:verifier,compiler");
+    // Use a single thread to facilitate debugging. We only compile tiny dex files.
+    args.push_back("-j1");
+
+    args.insert(args.end(), extra_args.begin(), extra_args.end());
+
+    return Dex2Oat(args, &output_, &error_msg_) == 0;
+  }
+
+  std::unique_ptr<VerifierDeps> GetVerifierDeps(
+        const std::string& vdex_location, const DexFile* dex_file) {
+    // Verify the vdex file content: only the classes using public APIs should be verified.
+    std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location.c_str(),
+                                                  /*writable=*/ false,
+                                                  /*low_4gb=*/ false,
+                                                  /*unquicken=*/ false,
+                                                  &error_msg_));
+    // Check the vdex doesn't have dex.
+    if (vdex->HasDexSection()) {
+      ::testing::AssertionFailure() << "The vdex should not contain dex code";
+    }
+
+    // Verify the deps.
+    VdexFile::VdexFileHeader vdex_header = vdex->GetVdexFileHeader();
+    if (!vdex_header.IsValid()) {
+      ::testing::AssertionFailure() << "Invalid vdex header";
+    }
+
+    std::vector<const DexFile*> dex_files;
+    dex_files.push_back(dex_file);
+    std::unique_ptr<VerifierDeps> deps(new VerifierDeps(dex_files, /*output_only=*/ false));
+
+    if (!deps->ParseStoredData(dex_files, vdex->GetVerifierDepsData())) {
+      ::testing::AssertionFailure() << error_msg_;
+    }
+
+    opened_vdex_files_.push_back(std::move(vdex));
+    return deps;
+  }
+
+  uint16_t GetClassDefIndex(const std::string& cls, const DexFile& dex_file) {
+    const dex::TypeId* type_id = dex_file.FindTypeId(cls.c_str());
+    DCHECK(type_id != nullptr);
+    dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
+    const dex::ClassDef* class_def = dex_file.FindClassDef(type_idx);
+    DCHECK(class_def != nullptr);
+    return dex_file.GetIndexForClassDef(*class_def);
+  }
+
+  bool HasVerifiedClass(const std::unique_ptr<VerifierDeps>& deps,
+                        const std::string& cls,
+                        const DexFile& dex_file) {
+    uint16_t class_def_idx = GetClassDefIndex(cls, dex_file);
+    return deps->GetVerifiedClasses(dex_file)[class_def_idx];
+  }
+
+  void CreateDexMetadata(const std::string& vdex, const std::string& out_dm) {
+    // Read the vdex bytes.
+    std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex.c_str()));
+    std::vector<uint8_t> data(vdex_file->GetLength());
+    ASSERT_TRUE(vdex_file->ReadFully(data.data(), data.size()));
+
+    // Zip the content.
+    FILE* file = fopen(out_dm.c_str(), "wb");
+    ZipWriter writer(file);
+    writer.StartEntry("primary.vdex", ZipWriter::kAlign32);
+    writer.WriteBytes(data.data(), data.size());
+    writer.FinishEntry();
+    writer.Finish();
+    fflush(file);
+    fclose(file);
+  }
+
+  std::string GetFilename(const std::unique_ptr<const DexFile>& dex_file) {
+    const std::string& str = dex_file->GetLocation();
+    size_t idx = str.rfind('/');
+    if (idx == std::string::npos) {
+      return str;
+    }
+    return str.substr(idx + 1);
+  }
+
+  std::string GetOdex(const std::unique_ptr<const DexFile>& dex_file,
+                      const std::string& suffix = "") {
+    return GetScratchDir() + "/" + GetFilename(dex_file) + suffix + ".odex";
+  }
+
+  std::string GetVdex(const std::unique_ptr<const DexFile>& dex_file,
+                      const std::string& suffix = "") {
+    return GetScratchDir() + "/" + GetFilename(dex_file) + suffix + ".vdex";
+  }
+
+  std::string output_;
+  std::string error_msg_;
+  std::vector<std::unique_ptr<VdexFile>> opened_vdex_files_;
+};
+
+// Validates verification against public API stubs:
+// - create a vdex file contraints by a predefined list of public API (passed as separate dex)
+// - compile with the above vdex file as input to validate the compilation flow
+TEST_F(Dex2oatVdexTest, VerifyPublicSdkStubs) {
+  std::string error_msg;
+
+  // Dex2oatVdexTestDex is the subject app using normal APIs found in the boot classpath.
+  std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Dex2oatVdexTestDex"));
+  // Dex2oatVdexPublicSdkDex serves as the public API-stubs, restricting what can be verified.
+  const std::string api_dex_location = GetTestDexFileName("Dex2oatVdexPublicSdkDex");
+
+  // Compile the subject app using the predefined API-stubs
+  ASSERT_TRUE(RunDex2oat(dex_file->GetLocation(), GetOdex(dex_file), &api_dex_location));
+
+  std::unique_ptr<VerifierDeps> deps = GetVerifierDeps(GetVdex(dex_file), dex_file.get());
+
+  // Verify public API usage. The classes should be verified.
+  ASSERT_TRUE(HasVerifiedClass(deps, "LAccessPublicCtor;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps, "LAccessPublicMethod;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps, "LAccessPublicMethodFromParent;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps, "LAccessPublicStaticMethod;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps, "LAccessPublicStaticField;", *dex_file));
+
+  // Verify NON public API usage. The classes should be verified, but will run
+  // with access checks.
+  ASSERT_TRUE(HasVerifiedClass(deps, "LAccessNonPublicCtor;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps, "LAccessNonPublicMethod;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps, "LAccessNonPublicMethodFromParent;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps, "LAccessNonPublicStaticMethod;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps, "LAccessNonPublicStaticField;", *dex_file));
+
+  // Compile again without public API stubs but with the previously generated vdex.
+  // This simulates a normal install where the apk has its code pre-verified.
+  // The results should be the same.
+
+  std::string dm_file = GetScratchDir() + "/base.dm";
+  CreateDexMetadata(GetVdex(dex_file), dm_file);
+  std::vector<std::string> extra_args;
+  extra_args.push_back("--dm-file=" + dm_file);
+  output_ = "";
+  ASSERT_TRUE(RunDex2oat(dex_file->GetLocation(), GetOdex(dex_file), nullptr, false, extra_args));
+
+  std::unique_ptr<VerifierDeps> deps2 = GetVerifierDeps(GetVdex(dex_file), dex_file.get());
+
+  ASSERT_TRUE(HasVerifiedClass(deps2, "LAccessPublicCtor;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps2, "LAccessPublicMethod;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps2, "LAccessPublicMethodFromParent;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps2, "LAccessPublicStaticMethod;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps2, "LAccessPublicStaticField;", *dex_file));
+
+  ASSERT_TRUE(HasVerifiedClass(deps2, "LAccessNonPublicCtor;", *dex_file)) << output_;
+  ASSERT_TRUE(HasVerifiedClass(deps2, "LAccessNonPublicMethod;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps2, "LAccessNonPublicMethodFromParent;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps2, "LAccessNonPublicStaticMethod;", *dex_file));
+  ASSERT_TRUE(HasVerifiedClass(deps2, "LAccessNonPublicStaticField;", *dex_file));
+}
+
+// Check that if the input dm does contain dex files then the compilation fails
+TEST_F(Dex2oatVdexTest, VerifyPublicSdkStubsWithDexFiles) {
+  std::string error_msg;
+
+  // Dex2oatVdexTestDex is the subject app using normal APIs found in the boot classpath.
+  std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Dex2oatVdexTestDex"));
+
+  // Compile the subject app using the predefined API-stubs
+  ASSERT_TRUE(RunDex2oat(
+      dex_file->GetLocation(),
+      GetOdex(dex_file),
+      /*public_sdk=*/ nullptr,
+      /*copy_dex_files=*/ true));
+
+  // Create the .dm file with the output.
+  std::string dm_file = GetScratchDir() + "/base.dm";
+  CreateDexMetadata(GetVdex(dex_file), dm_file);
+  std::vector<std::string> extra_args;
+  extra_args.push_back("--dm-file=" + dm_file);
+
+  // Recompile again with the .dm file which contains a vdex with code.
+  // The compilation should fail.
+  ASSERT_FALSE(RunDex2oat(
+      dex_file->GetLocation(),
+      GetOdex(dex_file, "v2"),
+      /*public_sdk=*/ nullptr,
+      /*copy_dex_files=*/ true,
+      extra_args));
+}
+
+// Check that corrupt vdex files from .dm archives are ignored.
+TEST_F(Dex2oatVdexTest, VerifyCorruptVdexFile) {
+  std::string error_msg;
+
+  // Dex2oatVdexTestDex is the subject app using normal APIs found in the boot classpath.
+  std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Dex2oatVdexTestDex"));
+
+  // Create the .dm file with the output.
+  // Instead passing the vdex files, pass the actual dex file. This will simulate a vdex corruption.
+  // The compiler should ignore it.
+  std::string dm_file = GetScratchDir() + "/base.dm";
+  CreateDexMetadata(dex_file->GetLocation(), dm_file);
+  std::vector<std::string> extra_args;
+  extra_args.push_back("--dm-file=" + dm_file);
+
+  // Compile the dex file. Despite having a corrupt input .vdex, we should not crash.
+  ASSERT_TRUE(RunDex2oat(
+      dex_file->GetLocation(),
+      GetOdex(dex_file),
+      /*public_sdk=*/ nullptr,
+      /*copy_dex_files=*/ true,
+      extra_args)) << output_;
+}
+
+// Check that if the input dm a vdex with mismatching checksums the compilation fails
+TEST_F(Dex2oatVdexTest, VerifyInputDmWithMismatchedChecksums) {
+  std::string error_msg;
+
+  // Generate a vdex file for Dex2oatVdexTestDex.
+  std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Dex2oatVdexTestDex"));
+
+  ASSERT_TRUE(RunDex2oat(
+      dex_file->GetLocation(),
+      GetOdex(dex_file),
+      /*public_sdk=*/ nullptr,
+      /*copy_dex_files=*/ false));
+
+  // Create the .dm file with the output.
+  std::string dm_file = GetScratchDir() + "/base.dm";
+  CreateDexMetadata(GetVdex(dex_file), dm_file);
+  std::vector<std::string> extra_args;
+  extra_args.push_back("--dm-file=" + dm_file);
+
+  // Try to compile Main using an input dm which contains the vdex for
+  // Dex2oatVdexTestDex. It should fail.
+  std::unique_ptr<const DexFile> dex_file2(OpenTestDexFile("Main"));
+  ASSERT_FALSE(RunDex2oat(
+      dex_file2->GetLocation(),
+      GetOdex(dex_file2, "v2"),
+      /*public_sdk=*/ nullptr,
+      /*copy_dex_files=*/ false,
+      extra_args)) << output_;
+}
+
+}  // namespace art
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index cb186d3..9029693 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -23,7 +23,6 @@
 #endif
 
 #include <string_view>
-#include <unordered_set>
 #include <vector>
 
 #include "android-base/logging.h"
@@ -36,6 +35,7 @@
 #include "base/array_ref.h"
 #include "base/bit_vector.h"
 #include "base/enums.h"
+#include "base/hash_set.h"
 #include "base/logging.h"  // For VLOG
 #include "base/stl_util.h"
 #include "base/string_view_cpp20.h"
@@ -52,7 +52,6 @@
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_annotations.h"
 #include "dex/dex_instruction-inl.h"
-#include "dex/dex_to_dex_compiler.h"
 #include "dex/verification_results.h"
 #include "dex/verified_method.h"
 #include "driver/compiler_options.h"
@@ -63,6 +62,7 @@
 #include "gc/space/space.h"
 #include "handle_scope-inl.h"
 #include "intrinsics_enum.h"
+#include "intrinsics_list.h"
 #include "jni/jni_internal.h"
 #include "linker/linker_patch.h"
 #include "mirror/class-inl.h"
@@ -83,7 +83,6 @@
 #include "trampolines/trampoline_compiler.h"
 #include "transaction.h"
 #include "utils/atomic_dex_ref_map-inl.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
 #include "utils/swap_space.h"
 #include "vdex_file.h"
 #include "verifier/class_verifier.h"
@@ -265,8 +264,7 @@
       parallel_thread_count_(thread_count),
       stats_(new AOTCompilationStats),
       compiled_method_storage_(swap_fd),
-      max_arena_alloc_(0),
-      dex_to_dex_compiler_(this) {
+      max_arena_alloc_(0) {
   DCHECK(compiler_options_ != nullptr);
 
   compiled_method_storage_.SetDedupeEnabled(compiler_options_->DeduplicateCode());
@@ -300,7 +298,9 @@
 
 std::unique_ptr<const std::vector<uint8_t>>
 CompilerDriver::CreateJniDlsymLookupCriticalTrampoline() const {
-  CREATE_TRAMPOLINE(JNI, kJniAbi, pDlsymLookupCritical)
+  // @CriticalNative calls do not have the `JNIEnv*` parameter, so this trampoline uses the
+  // architecture-dependent access to `Thread*` using the managed code ABI, i.e. `kQuickAbi`.
+  CREATE_TRAMPOLINE(JNI, kQuickAbi, pDlsymLookupCritical)
 }
 
 std::unique_ptr<const std::vector<uint8_t>> CompilerDriver::CreateQuickGenericJniTrampoline()
@@ -322,6 +322,14 @@
     const {
   CREATE_TRAMPOLINE(QUICK, kQuickAbi, pQuickToInterpreterBridge)
 }
+
+std::unique_ptr<const std::vector<uint8_t>> CompilerDriver::CreateNterpTrampoline()
+    const {
+  // We use QuickToInterpreterBridge to not waste one word in the Thread object.
+  // The Nterp trampoline gets replaced with the nterp entrypoint when loading
+  // an image.
+  CREATE_TRAMPOLINE(QUICK, kQuickAbi, pQuickToInterpreterBridge)
+}
 #undef CREATE_TRAMPOLINE
 
 void CompilerDriver::CompileAll(jobject class_loader,
@@ -331,12 +339,6 @@
 
   CheckThreadPools();
 
-  if (GetCompilerOptions().IsBootImage()) {
-    // All intrinsics must be in the primary boot image, so we don't need to setup
-    // the intrinsics for any other compilation, as those compilations will pick up
-    // a boot image that have the ArtMethod already set with the intrinsics flag.
-    InitializeIntrinsics();
-  }
   // Compile:
   // 1) Compile all classes and methods enabled for compilation. May fall back to dex-to-dex
   //    compilation.
@@ -348,61 +350,6 @@
   }
 }
 
-static optimizer::DexToDexCompiler::CompilationLevel GetDexToDexCompilationLevel(
-    Thread* self, const CompilerDriver& driver, Handle<mirror::ClassLoader> class_loader,
-    const DexFile& dex_file, const dex::ClassDef& class_def)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  // When the dex file is uncompressed in the APK, we do not generate a copy in the .vdex
-  // file. As a result, dex2oat will map the dex file read-only, and we only need to check
-  // that to know if we can do quickening.
-  if (dex_file.GetContainer() != nullptr && dex_file.GetContainer()->IsReadOnly()) {
-    return optimizer::DexToDexCompiler::CompilationLevel::kDontDexToDexCompile;
-  }
-  auto* const runtime = Runtime::Current();
-  DCHECK(driver.GetCompilerOptions().IsQuickeningCompilationEnabled());
-  const char* descriptor = dex_file.GetClassDescriptor(class_def);
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  ObjPtr<mirror::Class> klass = class_linker->FindClass(self, descriptor, class_loader);
-  if (klass == nullptr) {
-    CHECK(self->IsExceptionPending());
-    self->ClearException();
-    return optimizer::DexToDexCompiler::CompilationLevel::kDontDexToDexCompile;
-  }
-  // DexToDex at the kOptimize level may introduce quickened opcodes, which replace symbolic
-  // references with actual offsets. We cannot re-verify such instructions.
-  //
-  // We store the verification information in the class status in the oat file, which the linker
-  // can validate (checksums) and use to skip load-time verification. It is thus safe to
-  // optimize when a class has been fully verified before.
-  optimizer::DexToDexCompiler::CompilationLevel max_level =
-      optimizer::DexToDexCompiler::CompilationLevel::kOptimize;
-  if (driver.GetCompilerOptions().GetDebuggable()) {
-    // We are debuggable so definitions of classes might be changed. We don't want to do any
-    // optimizations that could break that.
-    max_level = optimizer::DexToDexCompiler::CompilationLevel::kDontDexToDexCompile;
-  }
-  if (klass->IsVerified()) {
-    // Class is verified so we can enable DEX-to-DEX compilation for performance.
-    return max_level;
-  } else {
-    // Class verification has failed: do not run DEX-to-DEX optimizations.
-    return optimizer::DexToDexCompiler::CompilationLevel::kDontDexToDexCompile;
-  }
-}
-
-static optimizer::DexToDexCompiler::CompilationLevel GetDexToDexCompilationLevel(
-    Thread* self,
-    const CompilerDriver& driver,
-    jobject jclass_loader,
-    const DexFile& dex_file,
-    const dex::ClassDef& class_def) {
-  ScopedObjectAccess soa(self);
-  StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::ClassLoader> class_loader(
-      hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
-  return GetDexToDexCompilationLevel(self, driver, class_loader, dex_file, class_def);
-}
-
 // Does the runtime for the InstructionSet provide an implementation returned by
 // GetQuickGenericJniStub allowing down calls that aren't compiled using a JNI compiler?
 static bool InstructionSetHasGenericJniStub(InstructionSet isa) {
@@ -427,7 +374,6 @@
     uint32_t method_idx,
     Handle<mirror::ClassLoader> class_loader,
     const DexFile& dex_file,
-    optimizer::DexToDexCompiler::CompilationLevel dex_to_dex_compilation_level,
     Handle<mirror::DexCache> dex_cache,
     CompileFn compile_fn) {
   DCHECK(driver != nullptr);
@@ -444,7 +390,6 @@
                                method_idx,
                                class_loader,
                                dex_file,
-                               dex_to_dex_compilation_level,
                                dex_cache);
 
   if (kTimeCompileMethod) {
@@ -466,68 +411,6 @@
   }
 }
 
-static void CompileMethodDex2Dex(
-    Thread* self,
-    CompilerDriver* driver,
-    const dex::CodeItem* code_item,
-    uint32_t access_flags,
-    InvokeType invoke_type,
-    uint16_t class_def_idx,
-    uint32_t method_idx,
-    Handle<mirror::ClassLoader> class_loader,
-    const DexFile& dex_file,
-    optimizer::DexToDexCompiler::CompilationLevel dex_to_dex_compilation_level,
-    Handle<mirror::DexCache> dex_cache) {
-  auto dex_2_dex_fn = [](Thread* self ATTRIBUTE_UNUSED,
-      CompilerDriver* driver,
-      const dex::CodeItem* code_item,
-      uint32_t access_flags,
-      InvokeType invoke_type,
-      uint16_t class_def_idx,
-      uint32_t method_idx,
-      Handle<mirror::ClassLoader> class_loader,
-      const DexFile& dex_file,
-      optimizer::DexToDexCompiler::CompilationLevel dex_to_dex_compilation_level,
-      Handle<mirror::DexCache> dex_cache ATTRIBUTE_UNUSED) -> CompiledMethod* {
-    DCHECK(driver != nullptr);
-    MethodReference method_ref(&dex_file, method_idx);
-
-    optimizer::DexToDexCompiler* const compiler = &driver->GetDexToDexCompiler();
-
-    if (compiler->ShouldCompileMethod(method_ref)) {
-      const VerificationResults* results = driver->GetCompilerOptions().GetVerificationResults();
-      DCHECK(results != nullptr);
-      const VerifiedMethod* verified_method = results->GetVerifiedMethod(method_ref);
-      // Do not optimize if a VerifiedMethod is missing. SafeCast elision,
-      // for example, relies on it.
-      return compiler->CompileMethod(
-          code_item,
-          access_flags,
-          invoke_type,
-          class_def_idx,
-          method_idx,
-          class_loader,
-          dex_file,
-          (verified_method != nullptr)
-          ? dex_to_dex_compilation_level
-              : optimizer::DexToDexCompiler::CompilationLevel::kDontDexToDexCompile);
-    }
-    return nullptr;
-  };
-  CompileMethodHarness(self,
-                       driver,
-                       code_item,
-                       access_flags,
-                       invoke_type,
-                       class_def_idx,
-                       method_idx,
-                       class_loader,
-                       dex_file,
-                       dex_to_dex_compilation_level,
-                       dex_cache,
-                       dex_2_dex_fn);
-}
-
 static void CompileMethodQuick(
     Thread* self,
     CompilerDriver* driver,
@@ -538,10 +421,9 @@
     uint32_t method_idx,
     Handle<mirror::ClassLoader> class_loader,
     const DexFile& dex_file,
-    optimizer::DexToDexCompiler::CompilationLevel dex_to_dex_compilation_level,
     Handle<mirror::DexCache> dex_cache) {
   auto quick_fn = [](
-      Thread* self,
+      Thread* self ATTRIBUTE_UNUSED,
       CompilerDriver* driver,
       const dex::CodeItem* code_item,
       uint32_t access_flags,
@@ -550,7 +432,6 @@
       uint32_t method_idx,
       Handle<mirror::ClassLoader> class_loader,
       const DexFile& dex_file,
-      optimizer::DexToDexCompiler::CompilationLevel dex_to_dex_compilation_level,
       Handle<mirror::DexCache> dex_cache) {
     DCHECK(driver != nullptr);
     CompiledMethod* compiled_method = nullptr;
@@ -622,13 +503,6 @@
           }
         }
       }
-      if (compiled_method == nullptr &&
-          dex_to_dex_compilation_level !=
-              optimizer::DexToDexCompiler::CompilationLevel::kDontDexToDexCompile) {
-        DCHECK(!Runtime::Current()->UseJitCompilation());
-        // TODO: add a command-line option to disable DEX-to-DEX compilation ?
-        driver->GetDexToDexCompiler().MarkForCompilation(self, method_ref);
-      }
     }
     return compiled_method;
   };
@@ -641,7 +515,6 @@
                        method_idx,
                        class_loader,
                        dex_file,
-                       dex_to_dex_compilation_level,
                        dex_cache,
                        quick_fn);
 }
@@ -684,11 +557,6 @@
 
   for (const DexFile* dex_file : dex_files) {
     dex_cache.Assign(class_linker->FindDexCache(soa.Self(), *dex_file));
-    bool added_preresolved_string_array = false;
-    if (only_startup_strings) {
-      // When resolving startup strings, create the preresolved strings array.
-      added_preresolved_string_array = dex_cache->AddPreResolvedStringsArray();
-    }
     TimingLogger::ScopedTiming t("Resolve const-string Strings", timings);
 
     // TODO: Implement a profile-based filter for the boot image. See b/76145463.
@@ -714,7 +582,7 @@
         if (profile_compilation_info != nullptr && !is_startup_clinit) {
           ProfileCompilationInfo::MethodHotness hotness =
               profile_compilation_info->GetMethodHotness(method.GetReference());
-          if (added_preresolved_string_array ? !hotness.IsStartup() : !hotness.IsInProfile()) {
+          if (only_startup_strings ? !hotness.IsStartup() : !hotness.IsInProfile()) {
             continue;
           }
         }
@@ -732,10 +600,6 @@
                   : inst->VRegB_31c());
               ObjPtr<mirror::String> string = class_linker->ResolveString(string_index, dex_cache);
               CHECK(string != nullptr) << "Could not allocate a string when forcing determinism";
-              if (added_preresolved_string_array) {
-                dex_cache->GetPreResolvedStrings()[string_index.index_] =
-                    GcRoot<mirror::String>(string);
-              }
               ++num_instructions;
               break;
             }
@@ -845,15 +709,56 @@
   }
 }
 
-void CompilerDriver::PrepareDexFilesForOatFile(TimingLogger* timings) {
+void CompilerDriver::PrepareDexFilesForOatFile(TimingLogger* timings ATTRIBUTE_UNUSED) {
   compiled_classes_.AddDexFiles(GetCompilerOptions().GetDexFilesForOatFile());
-
-  if (GetCompilerOptions().IsAnyCompilationEnabled()) {
-    TimingLogger::ScopedTiming t2("Dex2Dex SetDexFiles", timings);
-    dex_to_dex_compiler_.SetDexFiles(GetCompilerOptions().GetDexFilesForOatFile());
-  }
 }
 
+class CreateConflictTablesVisitor : public ClassVisitor {
+ public:
+  explicit CreateConflictTablesVisitor(VariableSizedHandleScope& hs)
+      : hs_(hs) {}
+
+  bool operator()(ObjPtr<mirror::Class> klass) override
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass)) {
+      return true;
+    }
+    // Collect handles since there may be thread suspension in future EnsureInitialized.
+    to_visit_.push_back(hs_.NewHandle(klass));
+    return true;
+  }
+
+  void FillAllIMTAndConflictTables() REQUIRES_SHARED(Locks::mutator_lock_) {
+    ScopedAssertNoThreadSuspension ants(__FUNCTION__);
+    for (Handle<mirror::Class> c : to_visit_) {
+      // Create the conflict tables.
+      FillIMTAndConflictTables(c.Get());
+    }
+  }
+
+ private:
+  void FillIMTAndConflictTables(ObjPtr<mirror::Class> klass)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (!klass->ShouldHaveImt()) {
+      return;
+    }
+    if (visited_classes_.find(klass.Ptr()) != visited_classes_.end()) {
+      return;
+    }
+    if (klass->HasSuperClass()) {
+      FillIMTAndConflictTables(klass->GetSuperClass());
+    }
+    if (!klass->IsTemp()) {
+      Runtime::Current()->GetClassLinker()->FillIMTAndConflictTables(klass);
+    }
+    visited_classes_.insert(klass.Ptr());
+  }
+
+  VariableSizedHandleScope& hs_;
+  std::vector<Handle<mirror::Class>> to_visit_;
+  HashSet<mirror::Class*> visited_classes_;
+};
+
 void CompilerDriver::PreCompile(jobject class_loader,
                                 const std::vector<const DexFile*>& dex_files,
                                 TimingLogger* timings,
@@ -930,6 +835,15 @@
       InitializeClasses(class_loader, dex_files, timings);
       VLOG(compiler) << "InitializeClasses: " << GetMemoryUsageString(false);
     }
+    {
+      // Create conflict tables, as the runtime expects boot image classes to
+      // always have their conflict tables filled.
+      ScopedObjectAccess soa(Thread::Current());
+      VariableSizedHandleScope hs(soa.Self());
+      CreateConflictTablesVisitor visitor(hs);
+      Runtime::Current()->GetClassLinker()->VisitClassesWithoutClassesLock(&visitor);
+      visitor.FillAllIMTAndConflictTables();
+    }
 
     UpdateImageClasses(timings, image_classes);
     VLOG(compiler) << "UpdateImageClasses: " << GetMemoryUsageString(false);
@@ -979,8 +893,7 @@
     return true;
   }
 
-  void FindExceptionTypesToResolve(
-      std::set<std::pair<dex::TypeIndex, const DexFile*>>* exceptions_to_resolve)
+  void FindExceptionTypesToResolve(std::set<TypeReference>* exceptions_to_resolve)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     const auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
     for (ObjPtr<mirror::Class> klass : classes_) {
@@ -993,7 +906,7 @@
  private:
   void FindExceptionTypesToResolveForMethod(
       ArtMethod* method,
-      std::set<std::pair<dex::TypeIndex, const DexFile*>>* exceptions_to_resolve)
+      std::set<TypeReference>* exceptions_to_resolve)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     if (method->GetCodeItem() == nullptr) {
       return;  // native or abstract method
@@ -1016,8 +929,8 @@
             dex::TypeIndex(DecodeUnsignedLeb128(&encoded_catch_handler_list));
         // Add to set of types to resolve if not already in the dex cache resolved types
         if (!method->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) {
-          exceptions_to_resolve->emplace(encoded_catch_handler_handlers_type_idx,
-                                         method->GetDexFile());
+          exceptions_to_resolve->emplace(method->GetDexFile(),
+                                         encoded_catch_handler_handlers_type_idx);
         }
         // ignore address associated with catch handler
         DecodeUnsignedLeb128(&encoded_catch_handler_list);
@@ -1073,6 +986,15 @@
   HashSet<std::string>* const image_classes_;
 };
 
+// Add classes which contain intrinsics methods to the list of image classes.
+static void AddClassesContainingIntrinsics(/* out */ HashSet<std::string>* image_classes) {
+#define ADD_INTRINSIC_OWNER_CLASS(_, __, ___, ____, _____, ClassName, ______, _______) \
+  image_classes->insert(ClassName);
+
+  INTRINSICS_LIST(ADD_INTRINSIC_OWNER_CLASS)
+#undef ADD_INTRINSIC_OWNER_CLASS
+}
+
 // Make a list of descriptors for classes to include in the image
 void CompilerDriver::LoadImageClasses(TimingLogger* timings,
                                       /*inout*/ HashSet<std::string>* image_classes) {
@@ -1081,13 +1003,32 @@
     return;
   }
 
-  // Make sure the File[] class is in the primary boot image. b/150319075
+  // A hard-coded list of array classes that should be in the primary boot image profile. The impact
+  // of each class can be approximately measured by comparing oatdump output with and without it:
+  // `m dump-oat-boot && grep -cE 'Class.*VisiblyInitialized' boot.host-<arch>.oatdump.txt`.
+  //   - b/150319075: File[]
+  //   - b/156098788: int[][], int[][][], short[][], byte[][][]
+  //
   // TODO: Implement support for array classes in profiles and remove this workaround. b/148067697
   if (GetCompilerOptions().IsBootImage()) {
     image_classes->insert("[Ljava/io/File;");
+    image_classes->insert("[[I");
+    image_classes->insert("[[[I");
+    image_classes->insert("[[S");
+    image_classes->insert("[[[B");
   }
 
   TimingLogger::ScopedTiming t("LoadImageClasses", timings);
+
+  if (GetCompilerOptions().IsBootImage()) {
+    AddClassesContainingIntrinsics(image_classes);
+
+    // All intrinsics must be in the primary boot image, so we don't need to setup
+    // the intrinsics for any other compilation, as those compilations will pick up
+    // a boot image that have the ArtMethod already set with the intrinsics flag.
+    InitializeIntrinsics();
+  }
+
   // Make a first pass to load all classes explicitly listed in the file
   Thread* self = Thread::Current();
   ScopedObjectAccess soa(self);
@@ -1110,10 +1051,12 @@
   // Resolve exception classes referenced by the loaded classes. The catch logic assumes
   // exceptions are resolved by the verifier when there is a catch block in an interested method.
   // Do this here so that exception classes appear to have been specified image classes.
-  std::set<std::pair<dex::TypeIndex, const DexFile*>> unresolved_exception_types;
-  StackHandleScope<1> hs(self);
+  std::set<TypeReference> unresolved_exception_types;
+  StackHandleScope<2u> hs(self);
   Handle<mirror::Class> java_lang_Throwable(
       hs.NewHandle(class_linker->FindSystemClass(self, "Ljava/lang/Throwable;")));
+  MutableHandle<mirror::DexCache> dex_cache = hs.NewHandle(java_lang_Throwable->GetDexCache());
+  DCHECK(dex_cache != nullptr);
   do {
     unresolved_exception_types.clear();
     {
@@ -1124,24 +1067,25 @@
       class_linker->VisitClasses(&visitor);
       visitor.FindExceptionTypesToResolve(&unresolved_exception_types);
     }
-    for (const auto& exception_type : unresolved_exception_types) {
-      dex::TypeIndex exception_type_idx = exception_type.first;
-      const DexFile* dex_file = exception_type.second;
-      StackHandleScope<1> hs2(self);
-      Handle<mirror::DexCache> dex_cache(hs2.NewHandle(class_linker->RegisterDexFile(*dex_file,
-                                                                                     nullptr)));
-      ObjPtr<mirror::Class> klass =
-          (dex_cache != nullptr)
-              ? class_linker->ResolveType(exception_type_idx,
-                                          dex_cache,
-                                          ScopedNullHandle<mirror::ClassLoader>())
-              : nullptr;
+    for (auto it = unresolved_exception_types.begin(); it != unresolved_exception_types.end(); ) {
+      dex::TypeIndex exception_type_idx = it->TypeIndex();
+      const DexFile* dex_file = it->dex_file;
+      if (dex_cache->GetDexFile() != dex_file) {
+        dex_cache.Assign(class_linker->RegisterDexFile(*dex_file, /*class_loader=*/ nullptr));
+        DCHECK(dex_cache != nullptr);
+      }
+      ObjPtr<mirror::Class> klass = class_linker->ResolveType(
+          exception_type_idx, dex_cache, ScopedNullHandle<mirror::ClassLoader>());
       if (klass == nullptr) {
         const dex::TypeId& type_id = dex_file->GetTypeId(exception_type_idx);
         const char* descriptor = dex_file->GetTypeDescriptor(type_id);
-        LOG(FATAL) << "Failed to resolve class " << descriptor;
+        VLOG(compiler) << "Failed to resolve exception class " << descriptor;
+        self->ClearException();
+        it = unresolved_exception_types.erase(it);
+      } else {
+        DCHECK(java_lang_Throwable->IsAssignableFrom(klass));
+        ++it;
       }
-      DCHECK(java_lang_Throwable->IsAssignableFrom(klass));
     }
     // Resolving exceptions may load classes that reference more exceptions, iterate until no
     // more are found
@@ -1315,7 +1259,7 @@
 
   mutable VariableSizedHandleScope hs_;
   mutable std::vector<Handle<mirror::Class>> to_insert_;
-  mutable std::unordered_set<mirror::Object*> marked_objects_;
+  mutable HashSet<mirror::Object*> marked_objects_;
   HashSet<std::string>* const image_class_descriptors_;
   std::vector<Handle<mirror::Class>> image_classes_;
   Thread* const self_;
@@ -1399,21 +1343,6 @@
   }
 }
 
-bool CompilerDriver::IsSafeCast(const DexCompilationUnit* mUnit, uint32_t dex_pc) {
-  if (!compiler_options_->IsVerificationEnabled()) {
-    // If we didn't verify, every cast has to be treated as non-safe.
-    return false;
-  }
-  DCHECK(mUnit->GetVerifiedMethod() != nullptr);
-  bool result = mUnit->GetVerifiedMethod()->IsSafeCast(dex_pc);
-  if (result) {
-    stats_->SafeCast();
-  } else {
-    stats_->NotASafeCast();
-  }
-  return result;
-}
-
 class CompilationVisitor {
  public:
   virtual ~CompilationVisitor() {}
@@ -1601,7 +1530,7 @@
     // generated code.
     const dex::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
     ScopedObjectAccess soa(self);
-    StackHandleScope<2> hs(soa.Self());
+    StackHandleScope<5> hs(soa.Self());
     Handle<mirror::ClassLoader> class_loader(
         hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
     Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(
@@ -1616,6 +1545,40 @@
       CheckAndClearResolveException(soa.Self());
       resolve_fields_and_methods = false;
     } else {
+      Handle<mirror::Class> hklass(hs.NewHandle(klass));
+      if (manager_->GetCompiler()->GetCompilerOptions().IsCheckLinkageConditions() &&
+          !manager_->GetCompiler()->GetCompilerOptions().IsBootImage()) {
+        bool is_fatal = manager_->GetCompiler()->GetCompilerOptions().IsCrashOnLinkageViolation();
+        ObjPtr<mirror::ClassLoader> resolving_class_loader = hklass->GetClassLoader();
+        if (resolving_class_loader != soa.Decode<mirror::ClassLoader>(jclass_loader)) {
+          // Redefinition via different ClassLoaders.
+          // This OptStat stuff is to enable logging from the APK scanner.
+          if (is_fatal)
+            LOG(FATAL) << "OptStat#" << hklass->PrettyClassAndClassLoader() << ": 1";
+          else
+            LOG(ERROR)
+                << "LINKAGE VIOLATION: "
+                << hklass->PrettyClassAndClassLoader()
+                << " was redefined";
+        }
+        // Check that the current class is not a subclass of java.lang.ClassLoader.
+        if (!hklass->IsInterface() &&
+            hklass->IsSubClass(class_linker->FindClass(self,
+                                                       "Ljava/lang/ClassLoader;",
+                                                       hs.NewHandle(resolving_class_loader)))) {
+          // Subclassing of java.lang.ClassLoader.
+          // This OptStat stuff is to enable logging from the APK scanner.
+          if (is_fatal)
+            LOG(FATAL) << "OptStat#" << hklass->PrettyClassAndClassLoader() << ": 1";
+          else
+            LOG(ERROR)
+                << "LINKAGE VIOLATION: "
+                << hklass->PrettyClassAndClassLoader()
+                << " is a subclass of java.lang.ClassLoader";
+        }
+        CHECK(hklass->IsResolved()) << hklass->PrettyClass();
+        klass.Assign(hklass.Get());
+      }
       // We successfully resolved a class, should we skip it?
       if (SkipClass(jclass_loader, dex_file, klass)) {
         return;
@@ -1789,9 +1752,6 @@
   if (!verifier_deps->ValidateDependencies(
       soa.Self(),
       class_loader,
-      // This returns classpath dex files in no particular order but VerifierDeps
-      // does not care about the order.
-      classpath_classes_.GetDexFiles(),
       &error_msg)) {
     LOG(WARNING) << "Fast verification failed: " << error_msg;
     return false;
@@ -1818,12 +1778,13 @@
           ClassReference ref(dex_file, accessor.GetClassDefIndex());
           const ClassStatus existing = ClassStatus::kNotReady;
           ClassStateTable::InsertResult result =
-             compiled_classes_.Insert(ref, existing, ClassStatus::kVerified);
+             compiled_classes_.Insert(ref, existing, ClassStatus::kVerifiedNeedsAccessChecks);
           CHECK_EQ(result, ClassStateTable::kInsertResultSuccess) << ref.dex_file->GetLocation();
         } else {
           // Update the class status, so later compilation stages know they don't need to verify
           // the class.
-          LoadAndUpdateStatus(accessor, ClassStatus::kVerified, class_loader, soa.Self());
+          LoadAndUpdateStatus(
+              accessor, ClassStatus::kVerifiedNeedsAccessChecks, class_loader, soa.Self());
           // Create `VerifiedMethod`s for each methods, the compiler expects one for
           // quickening or compiling.
           // Note that this means:
@@ -1922,6 +1883,7 @@
         hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
     Handle<mirror::Class> klass(
         hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader)));
+    ClassReference ref(manager_->GetDexFile(), class_def_index);
     verifier::FailureKind failure_kind;
     if (klass == nullptr) {
       CHECK(soa.Self()->IsExceptionPending());
@@ -1937,6 +1899,7 @@
       std::string error_msg;
       failure_kind =
           verifier::ClassVerifier::VerifyClass(soa.Self(),
+                                               soa.Self()->GetVerifierDeps(),
                                                &dex_file,
                                                dex_cache,
                                                class_loader,
@@ -1946,36 +1909,40 @@
                                                log_level_,
                                                sdk_version_,
                                                &error_msg);
-      if (failure_kind == verifier::FailureKind::kHardFailure) {
-        LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
-                   << " because: " << error_msg;
-        manager_->GetCompiler()->SetHadHardVerifierFailure();
-      } else if (failure_kind == verifier::FailureKind::kSoftFailure) {
-        manager_->GetCompiler()->AddSoftVerifierFailure();
-      } else {
-        // Force a soft failure for the VerifierDeps. This is a sanity measure, as
-        // the vdex file already records that the class hasn't been resolved. It avoids
-        // trying to do future verification optimizations when processing the vdex file.
-        DCHECK(failure_kind == verifier::FailureKind::kNoFailure ||
-               failure_kind == verifier::FailureKind::kAccessChecksFailure) << failure_kind;
-        failure_kind = verifier::FailureKind::kSoftFailure;
+      switch (failure_kind) {
+        case verifier::FailureKind::kHardFailure: {
+          LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
+                     << " because: " << error_msg;
+          manager_->GetCompiler()->SetHadHardVerifierFailure();
+          break;
+        }
+        case verifier::FailureKind::kSoftFailure: {
+          manager_->GetCompiler()->AddSoftVerifierFailure();
+          break;
+        }
+        case verifier::FailureKind::kTypeChecksFailure: {
+          // Don't record anything, we will do the type checks from the vdex
+          // file at runtime.
+          break;
+        }
+        case verifier::FailureKind::kAccessChecksFailure: {
+          manager_->GetCompiler()->RecordClassStatus(ref, ClassStatus::kVerifiedNeedsAccessChecks);
+          break;
+        }
+        case verifier::FailureKind::kNoFailure: {
+          manager_->GetCompiler()->RecordClassStatus(ref, ClassStatus::kVerified);
+          break;
+        }
       }
     } else if (&klass->GetDexFile() != &dex_file) {
       // Skip a duplicate class (as the resolved class is from another, earlier dex file).
-      // Record the information that we skipped this class in the vdex.
-      // If the class resolved to a dex file not covered by the vdex, e.g. boot class path,
-      // it is considered external, dependencies on it will be recorded and the vdex will
-      // remain usable regardless of whether the class remains redefined or not (in the
-      // latter case, this class will be verify-at-runtime).
-      // On the other hand, if the class resolved to a dex file covered by the vdex, i.e.
-      // a different dex file within the same APK, this class will always be eclipsed by it.
-      // Recording that it was redefined is not necessary but will save class resolution
-      // time during fast-verify.
-      verifier::VerifierDeps::MaybeRecordClassRedefinition(dex_file, class_def);
       return;  // Do not update state.
     } else if (!SkipClass(jclass_loader, dex_file, klass.Get())) {
       CHECK(klass->IsResolved()) << klass->PrettyClass();
-      failure_kind = class_linker->VerifyClass(soa.Self(), klass, log_level_);
+      failure_kind = class_linker->VerifyClass(soa.Self(),
+                                               soa.Self()->GetVerifierDeps(),
+                                               klass,
+                                               log_level_);
 
       if (klass->IsErroneous()) {
         // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
@@ -1993,7 +1960,6 @@
           << klass->PrettyDescriptor() << ": state=" << klass->GetStatus();
 
       // Class has a meaningful status for the compiler now, record it.
-      ClassReference ref(manager_->GetDexFile(), class_def_index);
       ClassStatus status = klass->GetStatus();
       if (status == ClassStatus::kInitialized) {
         // Initialized classes shall be visibly initialized when loaded from the image.
@@ -2022,7 +1988,8 @@
         } else if (klass->IsVerifiedNeedsAccessChecks()) {
           DCHECK_EQ(failure_kind, verifier::FailureKind::kAccessChecksFailure);
         } else if (klass->ShouldVerifyAtRuntime()) {
-          DCHECK_EQ(failure_kind, verifier::FailureKind::kSoftFailure);
+          DCHECK(failure_kind == verifier::FailureKind::kSoftFailure ||
+                 failure_kind == verifier::FailureKind::kTypeChecksFailure);
         } else {
           DCHECK_EQ(failure_kind, verifier::FailureKind::kHardFailure);
         }
@@ -2031,7 +1998,10 @@
       // Make the skip a soft failure, essentially being considered as verify at runtime.
       failure_kind = verifier::FailureKind::kSoftFailure;
     }
-    verifier::VerifierDeps::MaybeRecordVerificationStatus(dex_file, class_def, failure_kind);
+    verifier::VerifierDeps::MaybeRecordVerificationStatus(soa.Self()->GetVerifierDeps(),
+                                                          dex_file,
+                                                          class_def,
+                                                          failure_kind);
     soa.Self()->AssertNoPendingException();
   }
 
@@ -2149,7 +2119,7 @@
 
     if (klass != nullptr) {
       if (!SkipClass(manager_->GetClassLoader(), dex_file, klass.Get())) {
-        TryInitializeClass(klass, class_loader);
+        TryInitializeClass(soa.Self(), klass, class_loader);
       }
       manager_->GetCompiler()->stats_->AddClassStatus(klass->GetStatus());
     }
@@ -2158,14 +2128,15 @@
   }
 
   // A helper function for initializing klass.
-  void TryInitializeClass(Handle<mirror::Class> klass, Handle<mirror::ClassLoader>& class_loader)
+  void TryInitializeClass(Thread* self,
+                          Handle<mirror::Class> klass,
+                          Handle<mirror::ClassLoader>& class_loader)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     const DexFile& dex_file = klass->GetDexFile();
     const dex::ClassDef* class_def = klass->GetClassDef();
     const dex::TypeId& class_type_id = dex_file.GetTypeId(class_def->class_idx_);
     const char* descriptor = dex_file.StringDataByIdx(class_type_id.descriptor_idx_);
-    ScopedObjectAccessUnchecked soa(Thread::Current());
-    StackHandleScope<3> hs(soa.Self());
+    StackHandleScope<3> hs(self);
     ClassLinker* const class_linker = manager_->GetClassLinker();
     Runtime* const runtime = Runtime::Current();
     const CompilerOptions& compiler_options = manager_->GetCompiler()->GetCompilerOptions();
@@ -2190,7 +2161,8 @@
     if (klass->IsVerified()) {
       // Attempt to initialize the class but bail if we either need to initialize the super-class
       // or static fields.
-      class_linker->EnsureInitialized(soa.Self(), klass, false, false);
+      class_linker->EnsureInitialized(self, klass, false, false);
+      DCHECK(!self->IsExceptionPending());
       old_status = klass->GetStatus();
       if (!klass->IsInitialized()) {
         // We don't want non-trivial class initialization occurring on multiple threads due to
@@ -2202,18 +2174,16 @@
         // We need to use an ObjectLock due to potential suspension in the interpreting code. Rather
         // than use a special Object for the purpose we use the Class of java.lang.Class.
         Handle<mirror::Class> h_klass(hs.NewHandle(klass->GetClass()));
-        ObjectLock<mirror::Class> lock(soa.Self(), h_klass);
+        ObjectLock<mirror::Class> lock(self, h_klass);
         // Attempt to initialize allowing initialization of parent classes but still not static
         // fields.
         // Initialize dependencies first only for app or boot image extension,
         // to make TryInitializeClass() recursive.
         bool try_initialize_with_superclasses =
-            is_boot_image ? true : InitializeDependencies(klass, class_loader, soa.Self());
+            is_boot_image ? true : InitializeDependencies(klass, class_loader, self);
         if (try_initialize_with_superclasses) {
-          class_linker->EnsureInitialized(soa.Self(), klass, false, true);
-          // It's OK to clear the exception here since the compiler is supposed to be fault
-          // tolerant and will silently not initialize classes that have exceptions.
-          soa.Self()->ClearException();
+          class_linker->EnsureInitialized(self, klass, false, true);
+          DCHECK(!self->IsExceptionPending());
         }
         // Otherwise it's in app image or boot image extension but superclasses
         // cannot be initialized, no need to proceed.
@@ -2244,10 +2214,10 @@
             // <clinit> at compile time.
             can_init_static_fields =
                 ClassLinker::kAppImageMayContainStrings &&
-                !soa.Self()->IsExceptionPending() &&
+                !self->IsExceptionPending() &&
                 !compiler_options.GetDebuggable() &&
                 (compiler_options.InitializeAppImageClasses() ||
-                 NoClinitInDependency(klass, soa.Self(), &class_loader));
+                 NoClinitInDependency(klass, self, &class_loader));
             // TODO The checking for clinit can be removed since it's already
             // checked when init superclass. Currently keep it because it contains
             // processing of intern strings. Will be removed later when intern strings
@@ -2258,25 +2228,25 @@
             VLOG(compiler) << "Initializing: " << descriptor;
             // TODO multithreading support. We should ensure the current compilation thread has
             // exclusive access to the runtime and the transaction. To achieve this, we could use
-            // a ReaderWriterMutex but we're holding the mutator lock so we fail mutex sanity
-            // checks in Thread::AssertThreadSuspensionIsAllowable.
+            // a ReaderWriterMutex but we're holding the mutator lock so we fail the check of mutex
+            // validity in Thread::AssertThreadSuspensionIsAllowable.
 
             // Resolve and initialize the exception type before enabling the transaction in case
             // the transaction aborts and cannot resolve the type.
             // TransactionAbortError is not initialized ant not in boot image, needed only by
             // compiler and will be pruned by ImageWriter.
             Handle<mirror::Class> exception_class =
-                hs.NewHandle(class_linker->FindClass(soa.Self(),
-                                                     Transaction::kAbortExceptionSignature,
+                hs.NewHandle(class_linker->FindClass(self,
+                                                     Transaction::kAbortExceptionDescriptor,
                                                      class_loader));
             bool exception_initialized =
-                class_linker->EnsureInitialized(soa.Self(), exception_class, true, true);
+                class_linker->EnsureInitialized(self, exception_class, true, true);
             DCHECK(exception_initialized);
 
             // Run the class initializer in transaction mode.
             runtime->EnterTransactionMode(is_app_image, klass.Get());
 
-            bool success = class_linker->EnsureInitialized(soa.Self(), klass, true, true);
+            bool success = class_linker->EnsureInitialized(self, klass, true, true);
             // TODO we detach transaction from runtime to indicate we quit the transactional
             // mode which prevents the GC from visiting objects modified during the transaction.
             // Ensure GC is not run so don't access freed objects when aborting transaction.
@@ -2295,8 +2265,8 @@
                   old_status = klass->GetStatus();
                 }
               } else {
-                CHECK(soa.Self()->IsExceptionPending());
-                mirror::Throwable* exception = soa.Self()->GetException();
+                CHECK(self->IsExceptionPending());
+                mirror::Throwable* exception = self->GetException();
                 VLOG(compiler) << "Initialization of " << descriptor << " aborted because of "
                                << exception->Dump();
                 std::ostream* file_log = manager_->GetCompiler()->
@@ -2305,7 +2275,7 @@
                   *file_log << descriptor << "\n";
                   *file_log << exception->Dump() << "\n";
                 }
-                soa.Self()->ClearException();
+                self->ClearException();
                 runtime->RollbackAllTransactions();
                 CHECK_EQ(old_status, klass->GetStatus()) << "Previous class status not restored";
               }
@@ -2328,16 +2298,16 @@
         // Clear exception in case EnsureInitialized has caused one in the code above.
         // It's OK to clear the exception here since the compiler is supposed to be fault
         // tolerant and will silently not initialize classes that have exceptions.
-        soa.Self()->ClearException();
+        self->ClearException();
 
         // If the class still isn't initialized, at least try some checks that initialization
         // would do so they can be skipped at runtime.
         if (!klass->IsInitialized() && class_linker->ValidateSuperClassDescriptors(klass)) {
           old_status = ClassStatus::kSuperclassValidated;
         } else {
-          soa.Self()->ClearException();
+          self->ClearException();
         }
-        soa.Self()->AssertNoPendingException();
+        self->AssertNoPendingException();
       }
     }
     if (old_status == ClassStatus::kInitialized) {
@@ -2349,6 +2319,11 @@
     // Back up the status before doing initialization for static encoded fields,
     // because the static encoded branch wants to keep the status to uninitialized.
     manager_->GetCompiler()->RecordClassStatus(ref, old_status);
+
+    if (kIsDebugBuild) {
+      // Make sure the class initialization did not leave any local references.
+      self->GetJniEnv()->AssertLocalsEmpty();
+    }
   }
 
  private:
@@ -2468,7 +2443,7 @@
       StackHandleScope<1> hs(self);
       Handle<mirror::Class> super_class = hs.NewHandle(klass->GetSuperClass());
       if (!super_class->IsInitialized()) {
-        this->TryInitializeClass(super_class, class_loader);
+        this->TryInitializeClass(self, super_class, class_loader);
         if (!super_class->IsInitialized()) {
           return false;
         }
@@ -2481,7 +2456,7 @@
         StackHandleScope<1> hs(self);
         Handle<mirror::Class> iface = hs.NewHandle(klass->GetIfTable()->GetInterface(i));
         if (iface->HasDefaultMethods() && !iface->IsInitialized()) {
-          TryInitializeClass(iface, class_loader);
+          TryInitializeClass(self, iface, class_loader);
           if (!iface->IsInitialized()) {
             return false;
           }
@@ -2562,56 +2537,6 @@
   class_linker->MakeInitializedClassesVisiblyInitialized(Thread::Current(), /*wait=*/ true);
 }
 
-class InitializeArrayClassesAndCreateConflictTablesVisitor : public ClassVisitor {
- public:
-  explicit InitializeArrayClassesAndCreateConflictTablesVisitor(VariableSizedHandleScope& hs)
-      : hs_(hs) {}
-
-  bool operator()(ObjPtr<mirror::Class> klass) override
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass)) {
-      return true;
-    }
-    if (klass->IsArrayClass()) {
-      StackHandleScope<1> hs(Thread::Current());
-      auto h_klass = hs.NewHandleWrapper(&klass);
-      Runtime::Current()->GetClassLinker()->EnsureInitialized(hs.Self(), h_klass, true, true);
-    }
-    // Collect handles since there may be thread suspension in future EnsureInitialized.
-    to_visit_.push_back(hs_.NewHandle(klass));
-    return true;
-  }
-
-  void FillAllIMTAndConflictTables() REQUIRES_SHARED(Locks::mutator_lock_) {
-    for (Handle<mirror::Class> c : to_visit_) {
-      // Create the conflict tables.
-      FillIMTAndConflictTables(c.Get());
-    }
-  }
-
- private:
-  void FillIMTAndConflictTables(ObjPtr<mirror::Class> klass)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (!klass->ShouldHaveImt()) {
-      return;
-    }
-    if (visited_classes_.find(klass) != visited_classes_.end()) {
-      return;
-    }
-    if (klass->HasSuperClass()) {
-      FillIMTAndConflictTables(klass->GetSuperClass());
-    }
-    if (!klass->IsTemp()) {
-      Runtime::Current()->GetClassLinker()->FillIMTAndConflictTables(klass);
-    }
-    visited_classes_.insert(klass);
-  }
-
-  VariableSizedHandleScope& hs_;
-  std::vector<Handle<mirror::Class>> to_visit_;
-  std::unordered_set<ObjPtr<mirror::Class>, HashObjPtr> visited_classes_;
-};
-
 void CompilerDriver::InitializeClasses(jobject class_loader,
                                        const std::vector<const DexFile*>& dex_files,
                                        TimingLogger* timings) {
@@ -2620,20 +2545,6 @@
     CHECK(dex_file != nullptr);
     InitializeClasses(class_loader, *dex_file, dex_files, timings);
   }
-  if (GetCompilerOptions().IsBootImage() ||
-      GetCompilerOptions().IsBootImageExtension() ||
-      GetCompilerOptions().IsAppImage()) {
-    // Make sure that we call EnsureIntiailized on all the array classes to call
-    // SetVerificationAttempted so that the access flags are set. If we do not do this they get
-    // changed at runtime resulting in more dirty image pages.
-    // Also create conflict tables.
-    // Only useful if we are compiling an image.
-    ScopedObjectAccess soa(Thread::Current());
-    VariableSizedHandleScope hs(soa.Self());
-    InitializeArrayClassesAndCreateConflictTablesVisitor visitor(hs);
-    Runtime::Current()->GetClassLinker()->VisitClassesWithoutClassesLock(&visitor);
-    visitor.FillAllIMTAndConflictTables();
-  }
   if (GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension()) {
     // Prune garbage objects created during aborted transactions.
     Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ true);
@@ -2700,10 +2611,6 @@
     // Go to native so that we don't block GC during compilation.
     ScopedThreadSuspension sts(soa.Self(), kNative);
 
-    // Can we run DEX-to-DEX compiler on this class ?
-    optimizer::DexToDexCompiler::CompilationLevel dex_to_dex_compilation_level =
-        GetDexToDexCompilationLevel(soa.Self(), *driver, jclass_loader, dex_file, class_def);
-
     // Compile direct and virtual methods.
     int64_t previous_method_idx = -1;
     for (const ClassAccessor::Method& method : accessor.GetMethods()) {
@@ -2723,7 +2630,6 @@
                  method_idx,
                  class_loader,
                  dex_file,
-                 dex_to_dex_compilation_level,
                  dex_cache);
     }
   };
@@ -2742,7 +2648,6 @@
             : profile_compilation_info->DumpInfo(dex_files));
   }
 
-  dex_to_dex_compiler_.ClearState();
   for (const DexFile* dex_file : dex_files) {
     CHECK(dex_file != nullptr);
     CompileDexFile(this,
@@ -2760,23 +2665,6 @@
     Runtime::Current()->ReclaimArenaPoolMemory();
   }
 
-  if (dex_to_dex_compiler_.NumCodeItemsToQuicken(Thread::Current()) > 0u) {
-    // TODO: Not visit all of the dex files, its probably rare that only one would have quickened
-    // methods though.
-    for (const DexFile* dex_file : dex_files) {
-      CompileDexFile(this,
-                     class_loader,
-                     *dex_file,
-                     dex_files,
-                     parallel_thread_pool_.get(),
-                     parallel_thread_count_,
-                     timings,
-                     "Compile Dex File Dex2Dex",
-                     CompileMethodDex2Dex);
-    }
-    dex_to_dex_compiler_.ClearState();
-  }
-
   VLOG(compiler) << "Compile: " << GetMemoryUsageString(false);
 }
 
diff --git a/dex2oat/driver/compiler_driver.h b/dex2oat/driver/compiler_driver.h
index 4f2cb81..0a3c0fe 100644
--- a/dex2oat/driver/compiler_driver.h
+++ b/dex2oat/driver/compiler_driver.h
@@ -35,12 +35,10 @@
 #include "compiler.h"
 #include "dex/class_reference.h"
 #include "dex/dex_file_types.h"
-#include "dex/dex_to_dex_compiler.h"
 #include "dex/method_reference.h"
 #include "driver/compiled_method_storage.h"
 #include "thread_pool.h"
 #include "utils/atomic_dex_ref_map.h"
-#include "utils/dex_cache_arrays_layout.h"
 
 namespace art {
 
@@ -129,6 +127,7 @@
   std::unique_ptr<const std::vector<uint8_t>> CreateQuickImtConflictTrampoline() const;
   std::unique_ptr<const std::vector<uint8_t>> CreateQuickResolutionTrampoline() const;
   std::unique_ptr<const std::vector<uint8_t>> CreateQuickToInterpreterBridge() const;
+  std::unique_ptr<const std::vector<uint8_t>> CreateNterpTrampoline() const;
 
   ClassStatus GetClassStatus(const ClassReference& ref) const;
   bool GetCompiledClass(const ClassReference& ref, ClassStatus* status) const;
@@ -183,8 +182,6 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
 
-  bool IsSafeCast(const DexCompilationUnit* mUnit, uint32_t dex_pc);
-
   size_t GetThreadCount() const {
     return parallel_thread_count_;
   }
@@ -225,10 +222,6 @@
     return &compiled_method_storage_;
   }
 
-  optimizer::DexToDexCompiler& GetDexToDexCompiler() {
-    return dex_to_dex_compiler_;
-  }
-
  private:
   void LoadImageClasses(TimingLogger* timings, /*inout*/ HashSet<std::string>* image_classes)
       REQUIRES(!Locks::mutator_lock_);
@@ -338,9 +331,6 @@
 
   size_t max_arena_alloc_;
 
-  // Compiler for dex to dex (quickening).
-  optimizer::DexToDexCompiler dex_to_dex_compiler_;
-
   friend class CommonCompilerDriverTest;
   friend class CompileClassVisitor;
   friend class DexToDexDecompilerTest;
diff --git a/dex2oat/driver/compiler_driver_test.cc b/dex2oat/driver/compiler_driver_test.cc
index 3096fc3..65aa888 100644
--- a/dex2oat/driver/compiler_driver_test.cc
+++ b/dex2oat/driver/compiler_driver_test.cc
@@ -137,11 +137,9 @@
   }
   EXPECT_TRUE(dex_cache->StaticMethodSize() == dex_cache->NumResolvedMethods()
       || dex.NumMethodIds() ==  dex_cache->NumResolvedMethods());
-  auto* cl = Runtime::Current()->GetClassLinker();
-  auto pointer_size = cl->GetImagePointerSize();
   for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
     // FIXME: This is outdated for hash-based method array.
-    ArtMethod* method = dex_cache->GetResolvedMethod(i, pointer_size);
+    ArtMethod* method = dex_cache->GetResolvedMethod(i);
     EXPECT_TRUE(method != nullptr) << "method_idx=" << i
                                 << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i))
                                 << " " << dex.GetMethodName(dex.GetMethodId(i));
@@ -153,7 +151,7 @@
       || dex.NumFieldIds() ==  dex_cache->NumResolvedFields());
   for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
     // FIXME: This is outdated for hash-based field array.
-    ArtField* field = dex_cache->GetResolvedField(i, cl->GetImagePointerSize());
+    ArtField* field = dex_cache->GetResolvedField(i);
     EXPECT_TRUE(field != nullptr) << "field_idx=" << i
                                << " " << dex.GetFieldDeclaringClassDescriptor(dex.GetFieldId(i))
                                << " " << dex.GetFieldName(dex.GetFieldId(i));
diff --git a/dex2oat/include/dex2oat_return_codes.h b/dex2oat/include/dex2oat_return_codes.h
deleted file mode 100644
index ad09d47..0000000
--- a/dex2oat/include/dex2oat_return_codes.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2017 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_DEX2OAT_INCLUDE_DEX2OAT_RETURN_CODES_H_
-#define ART_DEX2OAT_INCLUDE_DEX2OAT_RETURN_CODES_H_
-
-namespace art {
-namespace dex2oat {
-
-enum class ReturnCode : int {
-  kNoFailure = 0,          // No failure, execution completed successfully.
-  kOther = 1,              // Some other not closer specified error occurred.
-  kCreateRuntime = 2,      // Dex2oat failed creating a runtime. This may be indicative
-                           // of a missing or out of date boot image, for example.
-};
-
-}  // namespace dex2oat
-}  // namespace art
-
-#endif  // ART_DEX2OAT_INCLUDE_DEX2OAT_RETURN_CODES_H_
diff --git a/dex2oat/linker/arm/relative_patcher_thumb2.cc b/dex2oat/linker/arm/relative_patcher_thumb2.cc
index 72b93ec..99728cf 100644
--- a/dex2oat/linker/arm/relative_patcher_thumb2.cc
+++ b/dex2oat/linker/arm/relative_patcher_thumb2.cc
@@ -29,7 +29,6 @@
 #include "mirror/array-inl.h"
 #include "mirror/object.h"
 #include "read_barrier.h"
-#include "utils/arm/assembler_arm_vixl.h"
 
 namespace art {
 namespace linker {
diff --git a/dex2oat/linker/arm64/relative_patcher_arm64.cc b/dex2oat/linker/arm64/relative_patcher_arm64.cc
index 2260f66..4028f75 100644
--- a/dex2oat/linker/arm64/relative_patcher_arm64.cc
+++ b/dex2oat/linker/arm64/relative_patcher_arm64.cc
@@ -33,7 +33,6 @@
 #include "oat_quick_method_header.h"
 #include "read_barrier.h"
 #include "stream/output_stream.h"
-#include "utils/arm64/assembler_arm64.h"
 
 namespace art {
 namespace linker {
@@ -65,8 +64,11 @@
     case LinkerPatch::Type::kDataBimgRelRo:
     case LinkerPatch::Type::kMethodRelative:
     case LinkerPatch::Type::kMethodBssEntry:
+    case LinkerPatch::Type::kJniEntrypointRelative:
     case LinkerPatch::Type::kTypeRelative:
     case LinkerPatch::Type::kTypeBssEntry:
+    case LinkerPatch::Type::kPublicTypeBssEntry:
+    case LinkerPatch::Type::kPackageTypeBssEntry:
     case LinkerPatch::Type::kStringRelative:
     case LinkerPatch::Type::kStringBssEntry:
       return patch.LiteralOffset() == patch.PcInsnOffset();
@@ -261,6 +263,8 @@
                patch.GetType() == LinkerPatch::Type::kTypeRelative ||
                patch.GetType() == LinkerPatch::Type::kStringRelative ||
                patch.GetType() == LinkerPatch::Type::kTypeBssEntry ||
+               patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry ||
+               patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry ||
                patch.GetType() == LinkerPatch::Type::kStringBssEntry) << patch.GetType();
       }
       shift = 0u;  // No shift for ADD.
@@ -268,7 +272,10 @@
       // LDR/STR 32-bit or 64-bit with imm12 == 0 (unset).
       DCHECK(patch.GetType() == LinkerPatch::Type::kDataBimgRelRo ||
              patch.GetType() == LinkerPatch::Type::kMethodBssEntry ||
+             patch.GetType() == LinkerPatch::Type::kJniEntrypointRelative ||
              patch.GetType() == LinkerPatch::Type::kTypeBssEntry ||
+             patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry ||
+             patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry ||
              patch.GetType() == LinkerPatch::Type::kStringBssEntry) << patch.GetType();
       DCHECK_EQ(insn & 0xbfbffc00, 0xb9000000) << std::hex << insn;
     }
diff --git a/dex2oat/linker/elf_writer.cc b/dex2oat/linker/elf_writer.cc
index ca34864..aa5097a 100644
--- a/dex2oat/linker/elf_writer.cc
+++ b/dex2oat/linker/elf_writer.cc
@@ -48,17 +48,5 @@
   CHECK_NE(0U, *oat_data_offset);
 }
 
-bool ElfWriter::Fixup(File* file, uintptr_t oat_data_begin) {
-  std::string error_msg;
-  std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, /*low_4gb*/false, &error_msg));
-  CHECK(elf_file.get() != nullptr) << error_msg;
-
-  // Lookup "oatdata" symbol address.
-  uintptr_t oatdata_address = ElfWriter::GetOatDataAddress(elf_file.get());
-  uintptr_t base_address = oat_data_begin - oatdata_address;
-
-  return elf_file->Fixup(base_address);
-}
-
 }  // namespace linker
 }  // namespace art
diff --git a/dex2oat/linker/elf_writer.h b/dex2oat/linker/elf_writer.h
index a60c708..e41377e 100644
--- a/dex2oat/linker/elf_writer.h
+++ b/dex2oat/linker/elf_writer.h
@@ -50,8 +50,6 @@
   // Returns runtime oat_data runtime address for an opened ElfFile.
   static uintptr_t GetOatDataAddress(ElfFile* elf_file);
 
-  static bool Fixup(File* file, uintptr_t oat_data_begin);
-
   virtual ~ElfWriter() {}
 
   virtual void Start() = 0;
diff --git a/dex2oat/linker/elf_writer_quick.cc b/dex2oat/linker/elf_writer_quick.cc
index 6463445..424c252 100644
--- a/dex2oat/linker/elf_writer_quick.cc
+++ b/dex2oat/linker/elf_writer_quick.cc
@@ -18,8 +18,6 @@
 
 #include <memory>
 #include <openssl/sha.h>
-#include <unordered_map>
-#include <unordered_set>
 
 #include <android-base/logging.h>
 
@@ -266,6 +264,10 @@
 template <typename ElfTypes>
 void ElfWriterQuick<ElfTypes>::WriteDebugInfo(const debug::DebugInfo& debug_info) {
   if (compiler_options_.GetGenerateMiniDebugInfo()) {
+    // If mini-debug-info wasn't explicitly created so far, create it now (happens in tests).
+    if (debug_info_task_ == nullptr) {
+      PrepareDebugInfo(debug_info);
+    }
     // Wait for the mini-debug-info generation to finish and write it to disk.
     Thread* self = Thread::Current();
     DCHECK(debug_info_thread_pool_ != nullptr);
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index 303c262..13a424b 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -204,10 +204,10 @@
     vdex_filenames.push_back(vdex_filename);
   }
 
-  std::unordered_map<const DexFile*, size_t> dex_file_to_oat_index_map;
+  HashMap<const DexFile*, size_t> dex_file_to_oat_index_map;
   size_t image_idx = 0;
   for (const DexFile* dex_file : class_path) {
-    dex_file_to_oat_index_map.emplace(dex_file, image_idx);
+    dex_file_to_oat_index_map.insert(std::make_pair(dex_file, image_idx));
     ++image_idx;
   }
   std::unique_ptr<ImageWriter> writer(new ImageWriter(*compiler_options_,
@@ -276,8 +276,7 @@
           ASSERT_TRUE(cur_opened_dex_files.empty());
         }
       }
-      bool image_space_ok =
-          writer->PrepareImageAddressSpace(/*preload_dex_caches=*/ true, &timings);
+      bool image_space_ok = writer->PrepareImageAddressSpace(&timings);
       ASSERT_TRUE(image_space_ok);
 
       DCHECK_EQ(out_helper.vdex_files.size(), out_helper.oat_files.size());
@@ -294,12 +293,7 @@
         ASSERT_TRUE(start_rodata_ok);
         oat_writer->Initialize(driver, writer.get(), cur_dex_files);
 
-        std::unique_ptr<BufferedOutputStream> vdex_out =
-            std::make_unique<BufferedOutputStream>(
-                std::make_unique<FileOutputStream>(out_helper.vdex_files[i].GetFile()));
-        oat_writer->WriteVerifierDeps(vdex_out.get(), nullptr);
-        oat_writer->WriteQuickeningInfo(vdex_out.get());
-        oat_writer->WriteChecksumsAndVdexHeader(vdex_out.get());
+        oat_writer->FinishVdexFile(out_helper.vdex_files[i].GetFile(), /*verifier_deps=*/ nullptr);
 
         oat_writer->PrepareLayout(&patcher);
         elf_writer->PrepareDynamicSection(oat_writer->GetOatHeader().GetExecutableOffset(),
@@ -344,20 +338,10 @@
       }
     }
 
-    bool success_image = writer->Write(kInvalidFd,
+    bool success_image = writer->Write(File::kInvalidFd,
                                        image_filenames,
                                        image_filenames.size());
     ASSERT_TRUE(success_image);
-
-    for (size_t i = 0, size = oat_filenames.size(); i != size; ++i) {
-      const char* oat_filename = oat_filenames[i].c_str();
-      std::unique_ptr<File> oat_file(OS::OpenFileReadWrite(oat_filename));
-      ASSERT_TRUE(oat_file != nullptr);
-      bool success_fixup = ElfWriter::Fixup(oat_file.get(), writer->GetOatDataBegin(i));
-      ASSERT_TRUE(success_fixup);
-      ASSERT_EQ(oat_file->FlushCloseOrErase(), 0) << "Could not flush and close oat file "
-                                                  << oat_filename;
-    }
   }
 }
 
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 51edca4..b69c750 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -23,7 +23,6 @@
 
 #include <memory>
 #include <numeric>
-#include <unordered_set>
 #include <vector>
 
 #include "art_field-inl.h"
@@ -35,7 +34,7 @@
 #include "base/stl_util.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "compiled_method.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_types.h"
@@ -73,6 +72,7 @@
 #include "mirror/object_array-alloc-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/string-inl.h"
+#include "nterp_helpers.h"
 #include "oat.h"
 #include "oat_file.h"
 #include "oat_file_manager.h"
@@ -80,7 +80,6 @@
 #include "runtime.h"
 #include "scoped_thread_state_change-inl.h"
 #include "subtype_check.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
 #include "well_known_classes.h"
 
 using ::art::mirror::Class;
@@ -92,6 +91,24 @@
 namespace art {
 namespace linker {
 
+// The actual value of `kImageClassTableMinLoadFactor` is irrelevant because image class tables
+// are never resized, but we still need to pass a reasonable value to the constructor.
+constexpr double kImageClassTableMinLoadFactor = 0.5;
+// We use `kImageClassTableMaxLoadFactor` to determine the buffer size for image class tables
+// to make them full. We never insert additional elements to them, so we do not want to waste
+// extra memory. And unlike runtime class tables, we do not want this to depend on runtime
+// properties (see `Runtime::GetHashTableMaxLoadFactor()` checking for low memory mode).
+constexpr double kImageClassTableMaxLoadFactor = 0.7;
+
+// The actual value of `kImageInternTableMinLoadFactor` is irrelevant because image intern tables
+// are never resized, but we still need to pass a reasonable value to the constructor.
+constexpr double kImageInternTableMinLoadFactor = 0.5;
+// We use `kImageInternTableMaxLoadFactor` to determine the buffer size for image intern tables
+// to make them full. We never insert additional elements to them, so we do not want to waste
+// extra memory. And unlike runtime intern tables, we do not want this to depend on runtime
+// properties (see `Runtime::GetHashTableMaxLoadFactor()` checking for low memory mode).
+constexpr double kImageInternTableMaxLoadFactor = 0.7;
+
 static ArrayRef<const uint8_t> MaybeCompressData(ArrayRef<const uint8_t> source,
                                                  ImageHeader::StorageMode image_storage_mode,
                                                  /*out*/ std::vector<uint8_t>* storage) {
@@ -237,7 +254,7 @@
   Runtime::Current()->GetHeap()->VisitObjects(visitor);
 }
 
-bool ImageWriter::PrepareImageAddressSpace(bool preload_dex_caches, TimingLogger* timings) {
+bool ImageWriter::PrepareImageAddressSpace(TimingLogger* timings) {
   target_ptr_size_ = InstructionSetPointerSize(compiler_options_.GetInstructionSet());
 
   Thread* const self = Thread::Current();
@@ -277,47 +294,12 @@
     Runtime::Current()->GetInternTable()->PromoteWeakToStrong();
   }
 
-  if (preload_dex_caches) {
-    TimingLogger::ScopedTiming t("PreloadDexCaches", timings);
-    // Preload deterministic contents to the dex cache arrays we're going to write.
-    ScopedObjectAccess soa(self);
-    ObjPtr<mirror::ClassLoader> class_loader = GetAppClassLoader();
-    std::vector<ObjPtr<mirror::DexCache>> dex_caches = FindDexCaches(self);
-    for (ObjPtr<mirror::DexCache> dex_cache : dex_caches) {
-      if (!IsImageDexCache(dex_cache)) {
-        continue;  // Boot image DexCache is not written to the app image.
-      }
-      PreloadDexCache(dex_cache, class_loader);
-    }
-  }
-
   {
     TimingLogger::ScopedTiming t("CalculateNewObjectOffsets", timings);
     ScopedObjectAccess soa(self);
     CalculateNewObjectOffsets();
   }
 
-  // Obtain class count for debugging purposes
-  if (VLOG_IS_ON(compiler) && compiler_options_.IsAppImage()) {
-    ScopedObjectAccess soa(self);
-
-    size_t app_image_class_count  = 0;
-
-    for (ImageInfo& info : image_infos_) {
-      info.class_table_->Visit([&](ObjPtr<mirror::Class> klass)
-                                   REQUIRES_SHARED(Locks::mutator_lock_) {
-        if (!IsInBootImage(klass.Ptr())) {
-          ++app_image_class_count;
-        }
-
-        // Indicate that we would like to continue visiting classes.
-        return true;
-      });
-    }
-
-    VLOG(compiler) << "Dex2Oat:AppImage:classCount = " << app_image_class_count;
-  }
-
   // This needs to happen after CalculateNewObjectOffsets since it relies on intern_table_bytes_ and
   // bin size sums being calculated.
   TimingLogger::ScopedTiming t("AllocMemory", timings);
@@ -403,10 +385,10 @@
 bool ImageWriter::Write(int image_fd,
                         const std::vector<std::string>& image_filenames,
                         size_t component_count) {
-  // If image_fd or oat_fd are not kInvalidFd then we may have empty strings in image_filenames or
-  // oat_filenames.
+  // If image_fd or oat_fd are not File::kInvalidFd then we may have empty strings in
+  // image_filenames or oat_filenames.
   CHECK(!image_filenames.empty());
-  if (image_fd != kInvalidFd) {
+  if (image_fd != File::kInvalidFd) {
     CHECK_EQ(image_filenames.size(), 1u);
   }
   DCHECK(!oat_filenames_.empty());
@@ -444,7 +426,7 @@
     const std::string& image_filename = image_filenames[i];
     ImageInfo& image_info = GetImageInfo(i);
     ImageFileGuard image_file;
-    if (image_fd != kInvalidFd) {
+    if (image_fd != File::kInvalidFd) {
       // Ignore image_filename, it is supplied only for better diagnostic.
       image_file.reset(new File(image_fd, unix_file::kCheckSafeUsage));
       // Empty the file in case it already exists.
@@ -642,7 +624,7 @@
       break;
     case LockWord::kHashCode:
       DCHECK(saved_hashcode_map_.find(object) == saved_hashcode_map_.end());
-      saved_hashcode_map_.emplace(object, lw.GetHashCode());
+      saved_hashcode_map_.insert(std::make_pair(object, lw.GetHashCode()));
       break;
     default:
       LOG(FATAL) << "Unreachable.";
@@ -654,112 +636,8 @@
   DCHECK(IsImageBinSlotAssigned(object));
 }
 
-void ImageWriter::PrepareDexCacheArraySlots() {
-  // Prepare dex cache array starts based on the ordering specified in the CompilerOptions.
-  // Set the slot size early to avoid DCHECK() failures in IsImageBinSlotAssigned()
-  // when AssignImageBinSlot() assigns their indexes out or order.
-  for (const DexFile* dex_file : compiler_options_.GetDexFilesForOatFile()) {
-    auto it = dex_file_oat_index_map_.find(dex_file);
-    DCHECK(it != dex_file_oat_index_map_.end()) << dex_file->GetLocation();
-    ImageInfo& image_info = GetImageInfo(it->second);
-    image_info.dex_cache_array_starts_.Put(
-        dex_file, image_info.GetBinSlotSize(Bin::kDexCacheArray));
-    DexCacheArraysLayout layout(target_ptr_size_, dex_file);
-    image_info.IncrementBinSlotSize(Bin::kDexCacheArray, layout.Size());
-  }
-
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Thread* const self = Thread::Current();
-  ReaderMutexLock mu(self, *Locks::dex_lock_);
-  for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
-    ObjPtr<mirror::DexCache> dex_cache =
-        ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
-    if (dex_cache == nullptr || !IsImageDexCache(dex_cache)) {
-      continue;
-    }
-    const DexFile* dex_file = dex_cache->GetDexFile();
-    CHECK(dex_file_oat_index_map_.find(dex_file) != dex_file_oat_index_map_.end())
-        << "Dex cache should have been pruned " << dex_file->GetLocation()
-        << "; possibly in class path";
-    DexCacheArraysLayout layout(target_ptr_size_, dex_file);
-    // Empty dex files will not have a "valid" DexCacheArraysLayout.
-    if (dex_file->NumTypeIds() + dex_file->NumStringIds() + dex_file->NumMethodIds() +
-        dex_file->NumFieldIds() + dex_file->NumProtoIds() + dex_file->NumCallSiteIds() != 0) {
-      DCHECK(layout.Valid());
-    }
-    size_t oat_index = GetOatIndexForDexFile(dex_file);
-    ImageInfo& image_info = GetImageInfo(oat_index);
-    uint32_t start = image_info.dex_cache_array_starts_.Get(dex_file);
-    DCHECK_EQ(dex_file->NumTypeIds() != 0u, dex_cache->GetResolvedTypes() != nullptr);
-    AddDexCacheArrayRelocation(dex_cache->GetResolvedTypes(),
-                               start + layout.TypesOffset(),
-                               oat_index);
-    DCHECK_EQ(dex_file->NumMethodIds() != 0u, dex_cache->GetResolvedMethods() != nullptr);
-    AddDexCacheArrayRelocation(dex_cache->GetResolvedMethods(),
-                               start + layout.MethodsOffset(),
-                               oat_index);
-    DCHECK_EQ(dex_file->NumFieldIds() != 0u, dex_cache->GetResolvedFields() != nullptr);
-    AddDexCacheArrayRelocation(dex_cache->GetResolvedFields(),
-                               start + layout.FieldsOffset(),
-                               oat_index);
-    DCHECK_EQ(dex_file->NumStringIds() != 0u, dex_cache->GetStrings() != nullptr);
-    AddDexCacheArrayRelocation(dex_cache->GetStrings(), start + layout.StringsOffset(), oat_index);
-
-    AddDexCacheArrayRelocation(dex_cache->GetResolvedMethodTypes(),
-                               start + layout.MethodTypesOffset(),
-                               oat_index);
-    AddDexCacheArrayRelocation(dex_cache->GetResolvedCallSites(),
-                                start + layout.CallSitesOffset(),
-                                oat_index);
-
-    // Preresolved strings aren't part of the special layout.
-    GcRoot<mirror::String>* preresolved_strings = dex_cache->GetPreResolvedStrings();
-    if (preresolved_strings != nullptr) {
-      DCHECK(!IsInBootImage(preresolved_strings));
-      // Add the array to the metadata section.
-      const size_t count = dex_cache->NumPreResolvedStrings();
-      auto bin = BinTypeForNativeRelocationType(NativeObjectRelocationType::kGcRootPointer);
-      for (size_t i = 0; i < count; ++i) {
-        native_object_relocations_.emplace(&preresolved_strings[i],
-            NativeObjectRelocation { oat_index,
-                                     image_info.GetBinSlotSize(bin),
-                                     NativeObjectRelocationType::kGcRootPointer });
-        image_info.IncrementBinSlotSize(bin, sizeof(GcRoot<mirror::Object>));
-      }
-    }
-  }
-}
-
-void ImageWriter::AddDexCacheArrayRelocation(void* array,
-                                             size_t offset,
-                                             size_t oat_index) {
-  if (array != nullptr) {
-    DCHECK(!IsInBootImage(array));
-    native_object_relocations_.emplace(array,
-        NativeObjectRelocation { oat_index, offset, NativeObjectRelocationType::kDexCacheArray });
-  }
-}
-
-void ImageWriter::AddMethodPointerArray(ObjPtr<mirror::PointerArray> arr) {
-  DCHECK(arr != nullptr);
-  if (kIsDebugBuild) {
-    for (size_t i = 0, len = arr->GetLength(); i < len; i++) {
-      ArtMethod* method = arr->GetElementPtrSize<ArtMethod*>(i, target_ptr_size_);
-      if (method != nullptr && !method->IsRuntimeMethod()) {
-        ObjPtr<mirror::Class> klass = method->GetDeclaringClass();
-        CHECK(klass == nullptr || KeepClass(klass))
-            << Class::PrettyClass(klass) << " should be a kept class";
-      }
-    }
-  }
-  // kBinArtMethodClean picked arbitrarily, just required to differentiate between ArtFields and
-  // ArtMethods.
-  pointer_arrays_.emplace(arr.Ptr(), Bin::kArtMethodClean);
-}
-
 ImageWriter::Bin ImageWriter::AssignImageBinSlot(mirror::Object* object, size_t oat_index) {
   DCHECK(object != nullptr);
-  size_t object_size = object->SizeOf();
 
   // The magic happens here. We segregate objects into different bins based
   // on how likely they are to get dirty at runtime.
@@ -780,12 +658,6 @@
     // Memory analysis has determined that the following types of objects get dirtied
     // the most:
     //
-    // * Dex cache arrays are stored in a special bin. The arrays for each dex cache have
-    //   a fixed layout which helps improve generated code (using PC-relative addressing),
-    //   so we pre-calculate their offsets separately in PrepareDexCacheArraySlots().
-    //   Since these arrays are huge, most pages do not overlap other objects and it's not
-    //   really important where they are for the clean/dirty separation. Due to their
-    //   special PC-relative addressing, we arbitrarily keep them at the end.
     // * Class'es which are verified [their clinit runs only at runtime]
     //   - classes in general [because their static fields get overwritten]
     //   - initialized classes with all-final statics are unlikely to be ever dirty,
@@ -807,24 +679,14 @@
       bin = Bin::kClassVerified;
       ObjPtr<mirror::Class> klass = object->AsClass();
 
-      // Add non-embedded vtable to the pointer array table if there is one.
-      ObjPtr<mirror::PointerArray> vtable = klass->GetVTable();
-      if (vtable != nullptr) {
-        AddMethodPointerArray(vtable);
-      }
-      ObjPtr<mirror::IfTable> iftable = klass->GetIfTable();
-      if (iftable != nullptr) {
-        for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
-          if (iftable->GetMethodArrayCount(i) > 0) {
-            AddMethodPointerArray(iftable->GetMethodArray(i));
-          }
-        }
-      }
-
       // Move known dirty objects into their own sections. This includes:
       //   - classes with dirty static fields.
-      if (dirty_image_objects_ != nullptr &&
-          dirty_image_objects_->find(klass->PrettyDescriptor()) != dirty_image_objects_->end()) {
+      auto is_dirty = [&](ObjPtr<mirror::Class> k) REQUIRES_SHARED(Locks::mutator_lock_) {
+        std::string temp;
+        std::string_view descriptor = k->GetDescriptor(&temp);
+        return dirty_image_objects_->find(descriptor) != dirty_image_objects_->end();
+      };
+      if (dirty_image_objects_ != nullptr && is_dirty(klass)) {
         bin = Bin::kKnownDirty;
       } else if (klass->GetStatus() == ClassStatus::kVisiblyInitialized) {
         bin = Bin::kClassInitialized;
@@ -863,9 +725,21 @@
     // else bin = kBinRegular
   }
 
+  AssignImageBinSlot(object, oat_index, bin);
+  return bin;
+}
+
+void ImageWriter::AssignImageBinSlot(mirror::Object* object, size_t oat_index, Bin bin) {
+  DCHECK(object != nullptr);
+  size_t object_size = object->SizeOf();
+
   // Assign the oat index too.
-  DCHECK(oat_index_map_.find(object) == oat_index_map_.end());
-  oat_index_map_.emplace(object, oat_index);
+  if (IsMultiImage()) {
+    DCHECK(oat_index_map_.find(object) == oat_index_map_.end());
+    oat_index_map_.insert(std::make_pair(object, oat_index));
+  } else {
+    DCHECK(oat_index_map_.empty());
+  }
 
   ImageInfo& image_info = GetImageInfo(oat_index);
 
@@ -882,8 +756,6 @@
 
   // Grow the image closer to the end by the object we just assigned.
   image_info.image_end_ += offset_delta;
-
-  return bin;
 }
 
 bool ImageWriter::WillMethodBeDirty(ArtMethod* m) const {
@@ -983,7 +855,7 @@
  public:
   PruneObjectReferenceVisitor(ImageWriter* image_writer,
                         bool* early_exit,
-                        std::unordered_set<mirror::Object*>* visited,
+                        HashSet<mirror::Object*>* visited,
                         bool* result)
       : image_writer_(image_writer), early_exit_(early_exit), visited_(visited), result_(result) {}
 
@@ -1019,12 +891,14 @@
           image_writer_->PruneImageClassInternal(ref->AsClass(), early_exit_, visited_);
     } else {
       // Record the object visited in case of circular reference.
-      visited_->emplace(ref);
+      visited_->insert(ref);
       *result_ = *result_ ||
           image_writer_->PruneImageClassInternal(klass, early_exit_, visited_);
       ref->VisitReferences(*this, *this);
       // Clean up before exit for next call of this function.
-      visited_->erase(ref);
+      auto it = visited_->find(ref);
+      DCHECK(it != visited_->end());
+      visited_->erase(it);
     }
   }
 
@@ -1037,21 +911,21 @@
  private:
   ImageWriter* image_writer_;
   bool* early_exit_;
-  std::unordered_set<mirror::Object*>* visited_;
+  HashSet<mirror::Object*>* visited_;
   bool* const result_;
 };
 
 
 bool ImageWriter::PruneImageClass(ObjPtr<mirror::Class> klass) {
   bool early_exit = false;
-  std::unordered_set<mirror::Object*> visited;
+  HashSet<mirror::Object*> visited;
   return PruneImageClassInternal(klass, &early_exit, &visited);
 }
 
 bool ImageWriter::PruneImageClassInternal(
     ObjPtr<mirror::Class> klass,
     bool* early_exit,
-    std::unordered_set<mirror::Object*>* visited) {
+    HashSet<mirror::Object*>* visited) {
   DCHECK(early_exit != nullptr);
   DCHECK(visited != nullptr);
   DCHECK(compiler_options_.IsAppImage() || compiler_options_.IsBootImageExtension());
@@ -1068,7 +942,7 @@
     *early_exit = true;
     return false;
   }
-  visited->emplace(klass.Ptr());
+  visited->insert(klass.Ptr());
   bool result = IsBootClassLoaderClass(klass);
   std::string temp;
   // Prune if not an image class, this handles any broken sets of image classes such as having a
@@ -1142,7 +1016,7 @@
   // dependencies. If visited is empty then we are the root caller, in this case the cycle was in
   // a child call and we can remember the result.
   if (result == true || !my_early_exit || visited->empty()) {
-    prune_class_memo_[klass.Ptr()] = result;
+    prune_class_memo_.Overwrite(klass.Ptr(), result);
   }
   *early_exit |= my_early_exit;
   return result;
@@ -1206,7 +1080,7 @@
  private:
   ImageWriter* const image_writer_;
   const ObjPtr<mirror::ClassLoader> class_loader_;
-  std::unordered_set<mirror::Class*> classes_to_prune_;
+  HashSet<mirror::Class*> classes_to_prune_;
   size_t defined_class_count_;
 };
 
@@ -1243,143 +1117,43 @@
   // Clear methods.
   mirror::MethodDexCacheType* resolved_methods = dex_cache->GetResolvedMethods();
   for (size_t slot_idx = 0, num = dex_cache->NumResolvedMethods(); slot_idx != num; ++slot_idx) {
-    auto pair =
-        mirror::DexCache::GetNativePairPtrSize(resolved_methods, slot_idx, target_ptr_size_);
-    if (pair.object != nullptr) {
-      dex_cache->ClearResolvedMethod(pair.index, target_ptr_size_);
-    }
+    mirror::MethodDexCachePair invalid(nullptr,
+                                       mirror::MethodDexCachePair::InvalidIndexForSlot(slot_idx));
+    mirror::DexCache::SetNativePair(resolved_methods, slot_idx, invalid);
   }
   // Clear fields.
   mirror::FieldDexCacheType* resolved_fields = dex_cache->GetResolvedFields();
   for (size_t slot_idx = 0, num = dex_cache->NumResolvedFields(); slot_idx != num; ++slot_idx) {
-    auto pair = mirror::DexCache::GetNativePairPtrSize(resolved_fields, slot_idx, target_ptr_size_);
-    if (pair.object != nullptr) {
-      dex_cache->ClearResolvedField(pair.index, target_ptr_size_);
-    }
+    mirror::FieldDexCachePair invalid(nullptr,
+                                      mirror::FieldDexCachePair::InvalidIndexForSlot(slot_idx));
+    mirror::DexCache::SetNativePair(resolved_fields, slot_idx, invalid);
   }
   // Clear types.
+  mirror::TypeDexCacheType* resolved_types = dex_cache->GetResolvedTypes();
   for (size_t slot_idx = 0, num = dex_cache->NumResolvedTypes(); slot_idx != num; ++slot_idx) {
-    mirror::TypeDexCachePair pair =
-        dex_cache->GetResolvedTypes()[slot_idx].load(std::memory_order_relaxed);
-    if (!pair.object.IsNull()) {
-      dex_cache->ClearResolvedType(dex::TypeIndex(pair.index));
-    }
+    mirror::TypeDexCachePair invalid(nullptr,
+                                     mirror::TypeDexCachePair::InvalidIndexForSlot(slot_idx));
+    resolved_types[slot_idx].store(invalid, std::memory_order_relaxed);
   }
   // Clear strings.
+  mirror::StringDexCacheType* resolved_strings = dex_cache->GetStrings();
   for (size_t slot_idx = 0, num = dex_cache->NumStrings(); slot_idx != num; ++slot_idx) {
-    mirror::StringDexCachePair pair =
-        dex_cache->GetStrings()[slot_idx].load(std::memory_order_relaxed);
-    if (!pair.object.IsNull()) {
-      dex_cache->ClearString(dex::StringIndex(pair.index));
-    }
+    mirror::StringDexCachePair invalid(nullptr,
+                                       mirror::StringDexCachePair::InvalidIndexForSlot(slot_idx));
+    resolved_strings[slot_idx].store(invalid, std::memory_order_relaxed);
   }
-}
-
-void ImageWriter::PreloadDexCache(ObjPtr<mirror::DexCache> dex_cache,
-                                  ObjPtr<mirror::ClassLoader> class_loader) {
-  // To ensure deterministic contents of the hash-based arrays, each slot shall contain
-  // the candidate with the lowest index. As we're processing entries in increasing index
-  // order, this means trying to look up the entry for the current index if the slot is
-  // empty or if it contains a higher index.
-
-  Runtime* runtime = Runtime::Current();
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  const DexFile& dex_file = *dex_cache->GetDexFile();
-  // Preload the methods array and make the contents deterministic.
-  mirror::MethodDexCacheType* resolved_methods = dex_cache->GetResolvedMethods();
-  dex::TypeIndex last_class_idx;  // Initialized to invalid index.
-  ObjPtr<mirror::Class> last_class = nullptr;
-  for (size_t i = 0, num = dex_cache->GetDexFile()->NumMethodIds(); i != num; ++i) {
-    uint32_t slot_idx = dex_cache->MethodSlotIndex(i);
-    auto pair =
-        mirror::DexCache::GetNativePairPtrSize(resolved_methods, slot_idx, target_ptr_size_);
-    uint32_t stored_index = pair.index;
-    ArtMethod* method = pair.object;
-    if (method != nullptr && i > stored_index) {
-      continue;  // Already checked.
-    }
-    // Check if the referenced class is in the image. Note that we want to check the referenced
-    // class rather than the declaring class to preserve the semantics, i.e. using a MethodId
-    // results in resolving the referenced class and that can for example throw OOME.
-    const dex::MethodId& method_id = dex_file.GetMethodId(i);
-    if (method_id.class_idx_ != last_class_idx) {
-      last_class_idx = method_id.class_idx_;
-      last_class = class_linker->LookupResolvedType(last_class_idx, dex_cache, class_loader);
-    }
-    if (method == nullptr || i < stored_index) {
-      if (last_class != nullptr) {
-        // Try to resolve the method with the class linker, which will insert
-        // it into the dex cache if successful.
-        method = class_linker->FindResolvedMethod(last_class, dex_cache, class_loader, i);
-        DCHECK(method == nullptr || dex_cache->GetResolvedMethod(i, target_ptr_size_) == method);
-      }
-    } else {
-      DCHECK_EQ(i, stored_index);
-      DCHECK(last_class != nullptr);
-    }
+  // Clear method types.
+  mirror::MethodTypeDexCacheType* resolved_method_types = dex_cache->GetResolvedMethodTypes();
+  size_t num_resolved_method_types = dex_cache->NumResolvedMethodTypes();
+  for (size_t slot_idx = 0; slot_idx != num_resolved_method_types; ++slot_idx) {
+    mirror::MethodTypeDexCachePair invalid(
+        nullptr, mirror::MethodTypeDexCachePair::InvalidIndexForSlot(slot_idx));
+    resolved_method_types[slot_idx].store(invalid, std::memory_order_relaxed);
   }
-  // Preload the fields array and make the contents deterministic.
-  mirror::FieldDexCacheType* resolved_fields = dex_cache->GetResolvedFields();
-  last_class_idx = dex::TypeIndex();  // Initialized to invalid index.
-  last_class = nullptr;
-  for (size_t i = 0, end = dex_file.NumFieldIds(); i < end; ++i) {
-    uint32_t slot_idx = dex_cache->FieldSlotIndex(i);
-    auto pair = mirror::DexCache::GetNativePairPtrSize(resolved_fields, slot_idx, target_ptr_size_);
-    uint32_t stored_index = pair.index;
-    ArtField* field = pair.object;
-    if (field != nullptr && i > stored_index) {
-      continue;  // Already checked.
-    }
-    // Check if the referenced class is in the image. Note that we want to check the referenced
-    // class rather than the declaring class to preserve the semantics, i.e. using a FieldId
-    // results in resolving the referenced class and that can for example throw OOME.
-    const dex::FieldId& field_id = dex_file.GetFieldId(i);
-    if (field_id.class_idx_ != last_class_idx) {
-      last_class_idx = field_id.class_idx_;
-      last_class = class_linker->LookupResolvedType(last_class_idx, dex_cache, class_loader);
-      if (last_class != nullptr && !KeepClass(last_class)) {
-        last_class = nullptr;
-      }
-    }
-    if (field == nullptr || i < stored_index) {
-      if (last_class != nullptr) {
-        // Try to resolve the field with the class linker, which will insert
-        // it into the dex cache if successful.
-        field = class_linker->FindResolvedFieldJLS(last_class, dex_cache, class_loader, i);
-        DCHECK(field == nullptr || dex_cache->GetResolvedField(i, target_ptr_size_) == field);
-      }
-    } else {
-      DCHECK_EQ(i, stored_index);
-      DCHECK(last_class != nullptr);
-    }
-  }
-  // Preload the types array and make the contents deterministic.
-  // This is done after fields and methods as their lookup can touch the types array.
-  for (size_t i = 0, end = dex_cache->GetDexFile()->NumTypeIds(); i < end; ++i) {
-    dex::TypeIndex type_idx(i);
-    uint32_t slot_idx = dex_cache->TypeSlotIndex(type_idx);
-    mirror::TypeDexCachePair pair =
-        dex_cache->GetResolvedTypes()[slot_idx].load(std::memory_order_relaxed);
-    uint32_t stored_index = pair.index;
-    ObjPtr<mirror::Class> klass = pair.object.Read();
-    if (klass == nullptr || i < stored_index) {
-      klass = class_linker->LookupResolvedType(type_idx, dex_cache, class_loader);
-      DCHECK(klass == nullptr || dex_cache->GetResolvedType(type_idx) == klass);
-    }
-  }
-  // Preload the strings array and make the contents deterministic.
-  for (size_t i = 0, end = dex_cache->GetDexFile()->NumStringIds(); i < end; ++i) {
-    dex::StringIndex string_idx(i);
-    uint32_t slot_idx = dex_cache->StringSlotIndex(string_idx);
-    mirror::StringDexCachePair pair =
-        dex_cache->GetStrings()[slot_idx].load(std::memory_order_relaxed);
-    uint32_t stored_index = pair.index;
-    ObjPtr<mirror::String> string = pair.object.Read();
-    if (string == nullptr || i < stored_index) {
-      string = class_linker->LookupString(string_idx, dex_cache);
-      DCHECK(string == nullptr || dex_cache->GetResolvedString(string_idx) == string);
-    }
-  }
+  // Clear call sites.
+  std::fill_n(dex_cache->GetResolvedCallSites(),
+              dex_cache->NumResolvedCallSites(),
+              GcRoot<mirror::CallSite>(nullptr));
 }
 
 void ImageWriter::PruneNonImageClasses() {
@@ -1412,7 +1186,7 @@
     VLOG(compiler) << "Pruned " << class_loader_visitor.GetRemovedClassCount() << " classes";
   }
 
-  // Completely clear DexCaches. They shall be re-filled in PreloadDexCaches if requested.
+  // Completely clear DexCaches.
   std::vector<ObjPtr<mirror::DexCache>> dex_caches = FindDexCaches(self);
   for (ObjPtr<mirror::DexCache> dex_cache : dex_caches) {
     ClearDexCache(dex_cache);
@@ -1462,7 +1236,7 @@
 
 ObjPtr<mirror::ObjectArray<mirror::Object>> ImageWriter::CollectDexCaches(Thread* self,
                                                                           size_t oat_index) const {
-  std::unordered_set<const DexFile*> image_dex_files;
+  HashSet<const DexFile*> image_dex_files;
   for (auto& pair : dex_file_oat_index_map_) {
     const DexFile* image_dex_file = pair.first;
     size_t image_oat_index = pair.second;
@@ -1560,146 +1334,92 @@
   return image_roots.Get();
 }
 
-void ImageWriter::RecordNativeRelocations(ObjPtr<mirror::Object> obj, size_t oat_index) {
-  if (obj->IsString()) {
-    ObjPtr<mirror::String> str = obj->AsString();
-    InternTable* intern_table = Runtime::Current()->GetInternTable();
-    Thread* const self = Thread::Current();
-    if (intern_table->LookupStrong(self, str) == str) {
-      DCHECK(std::none_of(image_infos_.begin(),
-                          image_infos_.end(),
-                          [=](ImageInfo& info) REQUIRES_SHARED(Locks::mutator_lock_) {
-                            return info.intern_table_->LookupStrong(self, str) != nullptr;
-                          }));
-      ObjPtr<mirror::String> interned =
-          GetImageInfo(oat_index).intern_table_->InternStrongImageString(str);
-      DCHECK_EQ(interned, obj);
+void ImageWriter::RecordNativeRelocations(ObjPtr<mirror::Class> klass, size_t oat_index) {
+  // Visit and assign offsets for fields and field arrays.
+  DCHECK_EQ(oat_index, GetOatIndexForClass(klass));
+  DCHECK(!klass->IsErroneous()) << klass->GetStatus();
+  if (compiler_options_.IsAppImage()) {
+    // Extra consistency check: no boot loader classes should be left!
+    CHECK(!IsBootClassLoaderClass(klass)) << klass->PrettyClass();
+  }
+  LengthPrefixedArray<ArtField>* fields[] = {
+      klass->GetSFieldsPtr(), klass->GetIFieldsPtr(),
+  };
+  ImageInfo& image_info = GetImageInfo(oat_index);
+  for (LengthPrefixedArray<ArtField>* cur_fields : fields) {
+    // Total array length including header.
+    if (cur_fields != nullptr) {
+      // Forward the entire array at once.
+      size_t offset = image_info.GetBinSlotSize(Bin::kArtField);
+      DCHECK(!IsInBootImage(cur_fields));
+      bool inserted =
+          native_object_relocations_.insert(std::make_pair(
+              cur_fields,
+              NativeObjectRelocation {
+                  oat_index, offset, NativeObjectRelocationType::kArtFieldArray
+              })).second;
+      CHECK(inserted) << "Field array " << cur_fields << " already forwarded";
+      const size_t size = LengthPrefixedArray<ArtField>::ComputeSize(cur_fields->size());
+      offset += size;
+      image_info.IncrementBinSlotSize(Bin::kArtField, size);
+      DCHECK_EQ(offset, image_info.GetBinSlotSize(Bin::kArtField));
     }
-  } else if (obj->IsDexCache()) {
-    DCHECK_EQ(oat_index, GetOatIndexForDexFile(obj->AsDexCache()->GetDexFile()));
-  } else if (obj->IsClass()) {
-    // Visit and assign offsets for fields and field arrays.
-    ObjPtr<mirror::Class> as_klass = obj->AsClass();
-    DCHECK_EQ(oat_index, GetOatIndexForClass(as_klass));
-    DCHECK(!as_klass->IsErroneous()) << as_klass->GetStatus();
-    if (compiler_options_.IsAppImage()) {
-      // Extra sanity, no boot loader classes should be left!
-      CHECK(!IsBootClassLoaderClass(as_klass)) << as_klass->PrettyClass();
+  }
+  // Visit and assign offsets for methods.
+  size_t num_methods = klass->NumMethods();
+  if (num_methods != 0) {
+    bool any_dirty = false;
+    for (auto& m : klass->GetMethods(target_ptr_size_)) {
+      if (WillMethodBeDirty(&m)) {
+        any_dirty = true;
+        break;
+      }
     }
-    LengthPrefixedArray<ArtField>* fields[] = {
-        as_klass->GetSFieldsPtr(), as_klass->GetIFieldsPtr(),
-    };
-    ImageInfo& image_info = GetImageInfo(oat_index);
-    if (!compiler_options_.IsAppImage()) {
-      // Note: Avoid locking to prevent lock order violations from root visiting;
-      // image_info.class_table_ is only accessed from the image writer.
-      image_info.class_table_->InsertWithoutLocks(as_klass);
-    }
-    for (LengthPrefixedArray<ArtField>* cur_fields : fields) {
-      // Total array length including header.
-      if (cur_fields != nullptr) {
-        const size_t header_size = LengthPrefixedArray<ArtField>::ComputeSize(0);
-        // Forward the entire array at once.
-        auto it = native_object_relocations_.find(cur_fields);
-        CHECK(it == native_object_relocations_.end()) << "Field array " << cur_fields
-                                                << " already forwarded";
-        size_t offset = image_info.GetBinSlotSize(Bin::kArtField);
-        DCHECK(!IsInBootImage(cur_fields));
-        native_object_relocations_.emplace(
-            cur_fields,
+    NativeObjectRelocationType type = any_dirty
+        ? NativeObjectRelocationType::kArtMethodDirty
+        : NativeObjectRelocationType::kArtMethodClean;
+    Bin bin_type = BinTypeForNativeRelocationType(type);
+    // Forward the entire array at once, but header first.
+    const size_t method_alignment = ArtMethod::Alignment(target_ptr_size_);
+    const size_t method_size = ArtMethod::Size(target_ptr_size_);
+    const size_t header_size = LengthPrefixedArray<ArtMethod>::ComputeSize(0,
+                                                                           method_size,
+                                                                           method_alignment);
+    LengthPrefixedArray<ArtMethod>* array = klass->GetMethodsPtr();
+    size_t offset = image_info.GetBinSlotSize(bin_type);
+    DCHECK(!IsInBootImage(array));
+    bool inserted =
+        native_object_relocations_.insert(std::make_pair(
+            array,
             NativeObjectRelocation {
-                oat_index, offset, NativeObjectRelocationType::kArtFieldArray
-            });
-        offset += header_size;
-        // Forward individual fields so that we can quickly find where they belong.
-        for (size_t i = 0, count = cur_fields->size(); i < count; ++i) {
-          // Need to forward arrays separate of fields.
-          ArtField* field = &cur_fields->At(i);
-          auto it2 = native_object_relocations_.find(field);
-          CHECK(it2 == native_object_relocations_.end()) << "Field at index=" << i
-              << " already assigned " << field->PrettyField() << " static=" << field->IsStatic();
-          DCHECK(!IsInBootImage(field));
-          native_object_relocations_.emplace(
-              field,
-              NativeObjectRelocation { oat_index,
-                                       offset,
-                                       NativeObjectRelocationType::kArtField });
-          offset += sizeof(ArtField);
-        }
-        image_info.IncrementBinSlotSize(
-            Bin::kArtField, header_size + cur_fields->size() * sizeof(ArtField));
-        DCHECK_EQ(offset, image_info.GetBinSlotSize(Bin::kArtField));
-      }
+                  oat_index,
+                  offset,
+                  any_dirty ? NativeObjectRelocationType::kArtMethodArrayDirty
+                            : NativeObjectRelocationType::kArtMethodArrayClean
+              })).second;
+    CHECK(inserted) << "Method array " << array << " already forwarded";
+    image_info.IncrementBinSlotSize(bin_type, header_size);
+    for (auto& m : klass->GetMethods(target_ptr_size_)) {
+      AssignMethodOffset(&m, type, oat_index);
     }
-    // Visit and assign offsets for methods.
-    size_t num_methods = as_klass->NumMethods();
-    if (num_methods != 0) {
-      bool any_dirty = false;
-      for (auto& m : as_klass->GetMethods(target_ptr_size_)) {
-        if (WillMethodBeDirty(&m)) {
-          any_dirty = true;
-          break;
+    (any_dirty ? dirty_methods_ : clean_methods_) += num_methods;
+  }
+  // Assign offsets for all runtime methods in the IMT since these may hold conflict tables
+  // live.
+  if (klass->ShouldHaveImt()) {
+    ImTable* imt = klass->GetImt(target_ptr_size_);
+    if (TryAssignImTableOffset(imt, oat_index)) {
+      // Since imt's can be shared only do this the first time to not double count imt method
+      // fixups.
+      for (size_t i = 0; i < ImTable::kSize; ++i) {
+        ArtMethod* imt_method = imt->Get(i, target_ptr_size_);
+        DCHECK(imt_method != nullptr);
+        if (imt_method->IsRuntimeMethod() &&
+            !IsInBootImage(imt_method) &&
+            !NativeRelocationAssigned(imt_method)) {
+          AssignMethodOffset(imt_method, NativeObjectRelocationType::kRuntimeMethod, oat_index);
         }
       }
-      NativeObjectRelocationType type = any_dirty
-          ? NativeObjectRelocationType::kArtMethodDirty
-          : NativeObjectRelocationType::kArtMethodClean;
-      Bin bin_type = BinTypeForNativeRelocationType(type);
-      // Forward the entire array at once, but header first.
-      const size_t method_alignment = ArtMethod::Alignment(target_ptr_size_);
-      const size_t method_size = ArtMethod::Size(target_ptr_size_);
-      const size_t header_size = LengthPrefixedArray<ArtMethod>::ComputeSize(0,
-                                                                             method_size,
-                                                                             method_alignment);
-      LengthPrefixedArray<ArtMethod>* array = as_klass->GetMethodsPtr();
-      auto it = native_object_relocations_.find(array);
-      CHECK(it == native_object_relocations_.end())
-          << "Method array " << array << " already forwarded";
-      size_t offset = image_info.GetBinSlotSize(bin_type);
-      DCHECK(!IsInBootImage(array));
-      native_object_relocations_.emplace(array,
-          NativeObjectRelocation {
-              oat_index,
-              offset,
-              any_dirty ? NativeObjectRelocationType::kArtMethodArrayDirty
-                        : NativeObjectRelocationType::kArtMethodArrayClean });
-      image_info.IncrementBinSlotSize(bin_type, header_size);
-      for (auto& m : as_klass->GetMethods(target_ptr_size_)) {
-        AssignMethodOffset(&m, type, oat_index);
-      }
-      (any_dirty ? dirty_methods_ : clean_methods_) += num_methods;
-    }
-    // Assign offsets for all runtime methods in the IMT since these may hold conflict tables
-    // live.
-    if (as_klass->ShouldHaveImt()) {
-      ImTable* imt = as_klass->GetImt(target_ptr_size_);
-      if (TryAssignImTableOffset(imt, oat_index)) {
-        // Since imt's can be shared only do this the first time to not double count imt method
-        // fixups.
-        for (size_t i = 0; i < ImTable::kSize; ++i) {
-          ArtMethod* imt_method = imt->Get(i, target_ptr_size_);
-          DCHECK(imt_method != nullptr);
-          if (imt_method->IsRuntimeMethod() &&
-              !IsInBootImage(imt_method) &&
-              !NativeRelocationAssigned(imt_method)) {
-            AssignMethodOffset(imt_method, NativeObjectRelocationType::kRuntimeMethod, oat_index);
-          }
-        }
-      }
-    }
-  } else if (obj->IsClassLoader()) {
-    // Register the class loader if it has a class table.
-    // The fake boot class loader should not get registered.
-    ObjPtr<mirror::ClassLoader> class_loader = obj->AsClassLoader();
-    if (class_loader->GetClassTable() != nullptr) {
-      DCHECK(compiler_options_.IsAppImage());
-      if (class_loader == GetAppClassLoader()) {
-        ImageInfo& image_info = GetImageInfo(oat_index);
-        // Note: Avoid locking to prevent lock order violations from root visiting;
-        // image_info.class_table_ table is only accessed from the image writer
-        // and class_loader->GetClassTable() is iterated but not modified.
-        image_info.class_table_->CopyWithoutLocks(*class_loader->GetClassTable());
-      }
     }
   }
 }
@@ -1716,12 +1436,13 @@
   // If the method is a conflict method we also want to assign the conflict table offset.
   ImageInfo& image_info = GetImageInfo(oat_index);
   const size_t size = ImTable::SizeInBytes(target_ptr_size_);
-  native_object_relocations_.emplace(
+  native_object_relocations_.insert(std::make_pair(
       imt,
       NativeObjectRelocation {
           oat_index,
           image_info.GetBinSlotSize(Bin::kImTable),
-          NativeObjectRelocationType::kIMTable});
+          NativeObjectRelocationType::kIMTable
+      }));
   image_info.IncrementBinSlotSize(Bin::kImTable, size);
   return true;
 }
@@ -1735,12 +1456,13 @@
   // If the method is a conflict method we also want to assign the conflict table offset.
   ImageInfo& image_info = GetImageInfo(oat_index);
   const size_t size = table->ComputeSize(target_ptr_size_);
-  native_object_relocations_.emplace(
+  native_object_relocations_.insert(std::make_pair(
       table,
       NativeObjectRelocation {
           oat_index,
           image_info.GetBinSlotSize(Bin::kIMTConflictTable),
-          NativeObjectRelocationType::kIMTConflictTable});
+          NativeObjectRelocationType::kIMTConflictTable
+      }));
   image_info.IncrementBinSlotSize(Bin::kIMTConflictTable, size);
 }
 
@@ -1756,7 +1478,8 @@
   ImageInfo& image_info = GetImageInfo(oat_index);
   Bin bin_type = BinTypeForNativeRelocationType(type);
   size_t offset = image_info.GetBinSlotSize(bin_type);
-  native_object_relocations_.emplace(method, NativeObjectRelocation { oat_index, offset, type });
+  native_object_relocations_.insert(
+      std::make_pair(method, NativeObjectRelocation { oat_index, offset, type }));
   image_info.IncrementBinSlotSize(bin_type, ArtMethod::Size(target_ptr_size_));
 }
 
@@ -1772,8 +1495,7 @@
 
   void ProcessDexFileObjects(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
   void ProcessRoots(VariableSizedHandleScope* handles) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  void ProcessWorkQueue() REQUIRES_SHARED(Locks::mutator_lock_);
+  void FinalizeInternTables() REQUIRES_SHARED(Locks::mutator_lock_);
 
   void VerifyImageBinSlotsAssigned() REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -1788,7 +1510,7 @@
    * string. To speed up the visiting of references at load time we include
    * a list of offsets to string references in the AppImage.
    */
-  void CollectStringReferenceInfo(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
+  void CollectStringReferenceInfo() REQUIRES_SHARED(Locks::mutator_lock_);
 
  private:
   class CollectClassesVisitor;
@@ -1796,6 +1518,9 @@
   class CollectStringReferenceVisitor;
   class VisitReferencesVisitor;
 
+  void ProcessInterns(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
+  void ProcessWorkQueue() REQUIRES_SHARED(Locks::mutator_lock_);
+
   using WorkQueue = std::deque<std::pair<ObjPtr<mirror::Object>, size_t>>;
 
   void VisitReferences(ObjPtr<mirror::Object> obj, size_t oat_index)
@@ -1812,6 +1537,11 @@
   // Objects for individual bins. Indexed by `oat_index` and `bin`.
   // Cannot use ObjPtr<> because of invalidation in Heap::VisitObjects().
   dchecked_vector<dchecked_vector<dchecked_vector<mirror::Object*>>> bin_objects_;
+
+  // Interns that do not have a corresponding StringId in any of the input dex files.
+  // These shall be assigned to individual images based on the `oat_index` that we
+  // see as we visit them during the work queue processing.
+  dchecked_vector<mirror::String*> non_dex_file_interns_;
 };
 
 class ImageWriter::LayoutHelper::CollectClassesVisitor : public ClassVisitor {
@@ -1846,11 +1576,11 @@
     return true;
   }
 
-  WorkQueue SortAndReleaseClasses()
-      REQUIRES_SHARED(Locks::mutator_lock_) {
+  WorkQueue ProcessCollectedClasses(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
     std::sort(klasses_.begin(), klasses_.end());
 
-    WorkQueue result;
+    ImageWriter* image_writer = image_writer_;
+    WorkQueue work_queue;
     size_t last_dex_file_index = static_cast<size_t>(-1);
     size_t last_oat_index = static_cast<size_t>(-1);
     for (const ClassEntry& entry : klasses_) {
@@ -1859,14 +1589,95 @@
           last_oat_index = GetDefaultOatIndex();  // Primitive type.
         } else {
           uint32_t dex_file_index = entry.dex_file_index - 1u;  // 0 is for primitive types.
-          last_oat_index = image_writer_->GetOatIndexForDexFile(dex_files_[dex_file_index]);
+          last_oat_index = image_writer->GetOatIndexForDexFile(dex_files_[dex_file_index]);
         }
         last_dex_file_index = entry.dex_file_index;
       }
-      result.emplace_back(entry.klass, last_oat_index);
+      // Count the number of classes for class tables.
+      image_writer->image_infos_[last_oat_index].class_table_size_ += 1u;
+      work_queue.emplace_back(entry.klass, last_oat_index);
     }
     klasses_.clear();
-    return result;
+
+    // Prepare image class tables.
+    std::vector<mirror::Class*> boot_image_classes;
+    if (image_writer->compiler_options_.IsAppImage()) {
+      DCHECK_EQ(image_writer->image_infos_.size(), 1u);
+      ImageInfo& image_info = image_writer->image_infos_[0];
+      // Log the non-boot image class count for app image for debugging purposes.
+      VLOG(compiler) << "Dex2Oat:AppImage:classCount = " << image_info.class_table_size_;
+      // Collect boot image classes referenced by app class loader's class table.
+      ClassTable* app_class_table = image_writer->GetAppClassLoader()->GetClassTable();
+      ReaderMutexLock lock(self, app_class_table->lock_);
+      DCHECK_EQ(app_class_table->classes_.size(), 1u);
+      const ClassTable::ClassSet& app_class_set = app_class_table->classes_[0];
+      DCHECK_GE(app_class_set.size(), image_info.class_table_size_);
+      boot_image_classes.reserve(app_class_set.size() - image_info.class_table_size_);
+      for (const ClassTable::TableSlot& slot : app_class_set) {
+        mirror::Class* klass = slot.Read<kWithoutReadBarrier>().Ptr();
+        if (image_writer->IsInBootImage(klass)) {
+          boot_image_classes.push_back(klass);
+        }
+      }
+      DCHECK_EQ(app_class_set.size() - image_info.class_table_size_, boot_image_classes.size());
+      // Increase the app class table size to include referenced boot image classes.
+      image_info.class_table_size_ = app_class_set.size();
+    }
+    for (ImageInfo& image_info : image_writer->image_infos_) {
+      if (image_info.class_table_size_ != 0u) {
+        // Make sure the class table shall be full by allocating a buffer of the right size.
+        size_t buffer_size = static_cast<size_t>(
+            ceil(image_info.class_table_size_ / kImageClassTableMaxLoadFactor));
+        image_info.class_table_buffer_.reset(new ClassTable::TableSlot[buffer_size]);
+        DCHECK(image_info.class_table_buffer_ != nullptr);
+        image_info.class_table_.emplace(kImageClassTableMinLoadFactor,
+                                        kImageClassTableMaxLoadFactor,
+                                        image_info.class_table_buffer_.get(),
+                                        buffer_size);
+      }
+    }
+    for (const auto& pair : work_queue) {
+      ObjPtr<mirror::Class> klass = pair.first->AsClass();
+      size_t oat_index = pair.second;
+      DCHECK(image_writer->image_infos_[oat_index].class_table_.has_value());
+      ClassTable::ClassSet& class_table = *image_writer->image_infos_[oat_index].class_table_;
+      uint32_t hash = ClassTable::TableSlot::HashDescriptor(klass);
+      bool inserted = class_table.InsertWithHash(ClassTable::TableSlot(klass, hash), hash).second;
+      DCHECK(inserted) << "Class " << klass->PrettyDescriptor()
+          << " (" << klass.Ptr() << ") already inserted";
+    }
+    if (image_writer->compiler_options_.IsAppImage()) {
+      DCHECK_EQ(image_writer->image_infos_.size(), 1u);
+      ImageInfo& image_info = image_writer->image_infos_[0];
+      if (image_info.class_table_size_ != 0u) {
+        // Insert boot image class references to the app class table.
+        // The order of insertion into the app class loader's ClassTable is non-deterministic,
+        // so sort the boot image classes by the boot image address to get deterministic table.
+        std::sort(boot_image_classes.begin(), boot_image_classes.end());
+        DCHECK(image_info.class_table_.has_value());
+        ClassTable::ClassSet& table = *image_info.class_table_;
+        for (mirror::Class* klass : boot_image_classes) {
+          uint32_t hash = ClassTable::TableSlot::HashDescriptor(klass);
+          bool inserted = table.InsertWithHash(ClassTable::TableSlot(klass, hash), hash).second;
+          DCHECK(inserted) << "Boot image class " << klass->PrettyDescriptor()
+              << " (" << klass << ") already inserted";
+        }
+        DCHECK_EQ(table.size(), image_info.class_table_size_);
+      }
+    }
+    for (ImageInfo& image_info : image_writer->image_infos_) {
+      DCHECK_EQ(image_info.class_table_bytes_, 0u);
+      if (image_info.class_table_size_ != 0u) {
+        DCHECK(image_info.class_table_.has_value());
+        DCHECK_EQ(image_info.class_table_->size(), image_info.class_table_size_);
+        image_info.class_table_bytes_ = image_info.class_table_->WriteToMemory(nullptr);
+        DCHECK_NE(image_info.class_table_bytes_, 0u);
+      } else {
+        DCHECK(!image_info.class_table_.has_value());
+      }
+    }
+
+    return work_queue;
   }
 
  private:
@@ -2015,6 +1826,38 @@
   const size_t oat_index_;
 };
 
+// Visit method pointer arrays in `klass` that were not inherited from its superclass.
+template <typename Visitor>
+static void VisitNewMethodPointerArrays(ObjPtr<mirror::Class> klass, Visitor&& visitor)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  ObjPtr<mirror::Class> super = klass->GetSuperClass<kVerifyNone, kWithoutReadBarrier>();
+  ObjPtr<mirror::PointerArray> vtable = klass->GetVTable<kVerifyNone, kWithoutReadBarrier>();
+  if (vtable != nullptr &&
+      (super == nullptr || vtable != super->GetVTable<kVerifyNone, kWithoutReadBarrier>())) {
+    visitor(vtable);
+  }
+  int32_t iftable_count = klass->GetIfTableCount();
+  int32_t super_iftable_count = (super != nullptr) ? super->GetIfTableCount() : 0;
+  ObjPtr<mirror::IfTable> iftable = klass->GetIfTable<kVerifyNone, kWithoutReadBarrier>();
+  ObjPtr<mirror::IfTable> super_iftable =
+      (super != nullptr) ? super->GetIfTable<kVerifyNone, kWithoutReadBarrier>() : nullptr;
+  for (int32_t i = 0; i < iftable_count; ++i) {
+    ObjPtr<mirror::PointerArray> methods =
+        iftable->GetMethodArrayOrNull<kVerifyNone, kWithoutReadBarrier>(i);
+    ObjPtr<mirror::PointerArray> super_methods = (i < super_iftable_count)
+        ? super_iftable->GetMethodArrayOrNull<kVerifyNone, kWithoutReadBarrier>(i)
+        : nullptr;
+    if (methods != super_methods) {
+      DCHECK(methods != nullptr);
+      if (i < super_iftable_count) {
+        DCHECK(super_methods != nullptr);
+        DCHECK_EQ(methods->GetLength(), super_methods->GetLength());
+      }
+      visitor(methods);
+    }
+  }
+}
+
 void ImageWriter::LayoutHelper::ProcessDexFileObjects(Thread* self) {
   Runtime* runtime = Runtime::Current();
   ClassLinker* class_linker = runtime->GetClassLinker();
@@ -2026,34 +1869,33 @@
   CollectClassesVisitor visitor(image_writer_);
   class_linker->VisitClasses(&visitor);
   DCHECK(work_queue_.empty());
-  work_queue_ = visitor.SortAndReleaseClasses();
+  work_queue_ = visitor.ProcessCollectedClasses(self);
   for (const std::pair<ObjPtr<mirror::Object>, size_t>& entry : work_queue_) {
-    DCHECK(entry.first->IsClass());
-    bool assigned = TryAssignBinSlot(entry.first, entry.second);
-    DCHECK(assigned);
+    DCHECK(entry.first != nullptr);
+    ObjPtr<mirror::Class> klass = entry.first->AsClass();
+    size_t oat_index = entry.second;
+    DCHECK(!image_writer_->IsInBootImage(klass.Ptr()));
+    DCHECK(!image_writer_->IsImageBinSlotAssigned(klass.Ptr()));
+    image_writer_->RecordNativeRelocations(klass, oat_index);
+    Bin klass_bin = image_writer_->AssignImageBinSlot(klass.Ptr(), oat_index);
+    bin_objects_[oat_index][enum_cast<size_t>(klass_bin)].push_back(klass.Ptr());
+
+    auto method_pointer_array_visitor =
+        [&](ObjPtr<mirror::PointerArray> pointer_array) REQUIRES_SHARED(Locks::mutator_lock_) {
+          Bin bin = kBinObjects ? Bin::kMethodPointerArray : Bin::kRegular;
+          image_writer_->AssignImageBinSlot(pointer_array.Ptr(), oat_index, bin);
+          bin_objects_[oat_index][enum_cast<size_t>(bin)].push_back(pointer_array.Ptr());
+          // No need to add to the work queue. The class reference, if not in the boot image
+          // (that is, when compiling the primary boot image), is already in the work queue.
+        };
+    VisitNewMethodPointerArrays(klass, method_pointer_array_visitor);
   }
 
-  // Assign bin slots to strings and dex caches.
+  // Assign bin slots to dex caches.
   for (const DexFile* dex_file : image_writer_->compiler_options_.GetDexFilesForOatFile()) {
     auto it = image_writer_->dex_file_oat_index_map_.find(dex_file);
     DCHECK(it != image_writer_->dex_file_oat_index_map_.end()) << dex_file->GetLocation();
     const size_t oat_index = it->second;
-    // Assign bin slots for strings defined in this dex file in StringId (lexicographical) order.
-    InternTable* const intern_table = runtime->GetInternTable();
-    for (size_t i = 0, count = dex_file->NumStringIds(); i < count; ++i) {
-      uint32_t utf16_length;
-      const char* utf8_data = dex_file->StringDataAndUtf16LengthByIdx(dex::StringIndex(i),
-                                                                      &utf16_length);
-      ObjPtr<mirror::String> string = intern_table->LookupStrong(self, utf16_length, utf8_data);
-      if (string != nullptr && !image_writer_->IsInBootImage(string.Ptr())) {
-        // Try to assign bin slot to this string but do not add it to the work list.
-        // The only reference in a String is its class, processed above for the boot image.
-        bool assigned = TryAssignBinSlot(string, oat_index);
-        DCHECK(assigned ||
-               // We could have seen the same string in an earlier dex file.
-               dex_file != image_writer_->compiler_options_.GetDexFilesForOatFile().front());
-      }
-    }
     // Assign bin slot to this file's dex cache and add it to the end of the work queue.
     ObjPtr<mirror::DexCache> dex_cache = class_linker->FindDexCache(self, *dex_file);
     DCHECK(dex_cache != nullptr);
@@ -2062,6 +1904,10 @@
     work_queue_.emplace_back(dex_cache, oat_index);
   }
 
+  // Assign interns to images depending on the first dex file they appear in.
+  // Record those that do not have a StringId in any dex file.
+  ProcessInterns(self);
+
   // Since classes and dex caches have been assigned to their bins, when we process a class
   // we do not follow through the class references or dex caches, so we correctly process
   // only objects actually belonging to that class before taking a new class from the queue.
@@ -2086,6 +1932,159 @@
   ProcessWorkQueue();
 }
 
+void ImageWriter::LayoutHelper::ProcessInterns(Thread* self) {
+  // String bins are empty at this point.
+  DCHECK(std::all_of(bin_objects_.begin(),
+                     bin_objects_.end(),
+                     [](const auto& bins) {
+                       return bins[enum_cast<size_t>(Bin::kString)].empty();
+                     }));
+
+  // There is only one non-boot image intern table and it's the last one.
+  InternTable* const intern_table = Runtime::Current()->GetInternTable();
+  MutexLock mu(self, *Locks::intern_table_lock_);
+  DCHECK_EQ(std::count_if(intern_table->strong_interns_.tables_.begin(),
+                          intern_table->strong_interns_.tables_.end(),
+                          [](const InternTable::Table::InternalTable& table) {
+                            return !table.IsBootImage();
+                          }),
+            1);
+  DCHECK(!intern_table->strong_interns_.tables_.back().IsBootImage());
+  const InternTable::UnorderedSet& intern_set = intern_table->strong_interns_.tables_.back().set_;
+
+  // Assign bin slots to all interns with a corresponding StringId in one of the input dex files.
+  ImageWriter* image_writer = image_writer_;
+  for (const DexFile* dex_file : image_writer->compiler_options_.GetDexFilesForOatFile()) {
+    auto it = image_writer->dex_file_oat_index_map_.find(dex_file);
+    DCHECK(it != image_writer->dex_file_oat_index_map_.end()) << dex_file->GetLocation();
+    const size_t oat_index = it->second;
+    // Assign bin slots for strings defined in this dex file in StringId (lexicographical) order.
+    auto& string_bin_objects = bin_objects_[oat_index][enum_cast<size_t>(Bin::kString)];
+    for (size_t i = 0, count = dex_file->NumStringIds(); i != count; ++i) {
+      uint32_t utf16_length;
+      const char* utf8_data = dex_file->StringDataAndUtf16LengthByIdx(dex::StringIndex(i),
+                                                                      &utf16_length);
+      int32_t hash = ComputeUtf16HashFromModifiedUtf8(utf8_data, utf16_length);
+      InternTable::Utf8String utf8_string(utf16_length, utf8_data, hash);
+      auto intern_it = intern_set.find(utf8_string);
+      if (intern_it != intern_set.end()) {
+        mirror::String* string = intern_it->Read<kWithoutReadBarrier>();
+        DCHECK(string != nullptr);
+        DCHECK(!image_writer->IsInBootImage(string));
+        if (!image_writer->IsImageBinSlotAssigned(string)) {
+          Bin bin = image_writer->AssignImageBinSlot(string, oat_index);
+          DCHECK_EQ(bin, Bin::kString);
+          string_bin_objects.push_back(string);
+        } else {
+          // We have already seen this string in a previous dex file.
+          DCHECK(dex_file != image_writer->compiler_options_.GetDexFilesForOatFile().front());
+        }
+      }
+    }
+  }
+
+  // String bins have been filled with dex file interns. Record their numbers in image infos.
+  DCHECK_EQ(bin_objects_.size(), image_writer_->image_infos_.size());
+  size_t total_dex_file_interns = 0u;
+  for (size_t oat_index = 0, size = bin_objects_.size(); oat_index != size; ++oat_index) {
+    size_t num_dex_file_interns = bin_objects_[oat_index][enum_cast<size_t>(Bin::kString)].size();
+    ImageInfo& image_info = image_writer_->GetImageInfo(oat_index);
+    DCHECK_EQ(image_info.intern_table_size_, 0u);
+    image_info.intern_table_size_ = num_dex_file_interns;
+    total_dex_file_interns += num_dex_file_interns;
+  }
+
+  // Collect interns that do not have a corresponding StringId in any of the input dex files.
+  non_dex_file_interns_.reserve(intern_set.size() - total_dex_file_interns);
+  for (const GcRoot<mirror::String>& root : intern_set) {
+    mirror::String* string = root.Read<kWithoutReadBarrier>();
+    if (!image_writer->IsImageBinSlotAssigned(string)) {
+      non_dex_file_interns_.push_back(string);
+    }
+  }
+  DCHECK_EQ(intern_set.size(), total_dex_file_interns + non_dex_file_interns_.size());
+}
+
+void ImageWriter::LayoutHelper::FinalizeInternTables() {
+  // Remove interns that do not have a bin slot assigned. These correspond
+  // to the DexCache locations excluded in VerifyImageBinSlotsAssigned().
+  ImageWriter* image_writer = image_writer_;
+  auto retained_end = std::remove_if(
+      non_dex_file_interns_.begin(),
+      non_dex_file_interns_.end(),
+      [=](mirror::String* string) REQUIRES_SHARED(Locks::mutator_lock_) {
+        return !image_writer->IsImageBinSlotAssigned(string);
+      });
+  non_dex_file_interns_.resize(std::distance(non_dex_file_interns_.begin(), retained_end));
+
+  // Sort `non_dex_file_interns_` based on oat index and bin offset.
+  ArrayRef<mirror::String*> non_dex_file_interns(non_dex_file_interns_);
+  std::sort(non_dex_file_interns.begin(),
+            non_dex_file_interns.end(),
+            [=](mirror::String* lhs, mirror::String* rhs) REQUIRES_SHARED(Locks::mutator_lock_) {
+              size_t lhs_oat_index = image_writer->GetOatIndex(lhs);
+              size_t rhs_oat_index = image_writer->GetOatIndex(rhs);
+              if (lhs_oat_index != rhs_oat_index) {
+                return lhs_oat_index < rhs_oat_index;
+              }
+              BinSlot lhs_bin_slot = image_writer->GetImageBinSlot(lhs, lhs_oat_index);
+              BinSlot rhs_bin_slot = image_writer->GetImageBinSlot(rhs, rhs_oat_index);
+              return lhs_bin_slot < rhs_bin_slot;
+            });
+
+  // Allocate and fill intern tables.
+  size_t ndfi_index = 0u;
+  DCHECK_EQ(bin_objects_.size(), image_writer->image_infos_.size());
+  for (size_t oat_index = 0, size = bin_objects_.size(); oat_index != size; ++oat_index) {
+    // Find the end of `non_dex_file_interns` for this oat file.
+    size_t ndfi_end = ndfi_index;
+    while (ndfi_end != non_dex_file_interns.size() &&
+           image_writer->GetOatIndex(non_dex_file_interns[ndfi_end]) == oat_index) {
+      ++ndfi_end;
+    }
+
+    // Calculate final intern table size.
+    ImageInfo& image_info = image_writer->GetImageInfo(oat_index);
+    DCHECK_EQ(image_info.intern_table_bytes_, 0u);
+    size_t num_dex_file_interns = image_info.intern_table_size_;
+    size_t num_non_dex_file_interns = ndfi_end - ndfi_index;
+    image_info.intern_table_size_ = num_dex_file_interns + num_non_dex_file_interns;
+    if (image_info.intern_table_size_ != 0u) {
+      // Make sure the intern table shall be full by allocating a buffer of the right size.
+      size_t buffer_size = static_cast<size_t>(
+          ceil(image_info.intern_table_size_ / kImageInternTableMaxLoadFactor));
+      image_info.intern_table_buffer_.reset(new GcRoot<mirror::String>[buffer_size]);
+      DCHECK(image_info.intern_table_buffer_ != nullptr);
+      image_info.intern_table_.emplace(kImageInternTableMinLoadFactor,
+                                       kImageInternTableMaxLoadFactor,
+                                       image_info.intern_table_buffer_.get(),
+                                       buffer_size);
+
+      // Fill the intern table. Dex file interns are at the start of the bin_objects[.][kString].
+      InternTable::UnorderedSet& table = *image_info.intern_table_;
+      const auto& oat_file_strings = bin_objects_[oat_index][enum_cast<size_t>(Bin::kString)];
+      DCHECK_LE(num_dex_file_interns, oat_file_strings.size());
+      ArrayRef<mirror::Object* const> dex_file_interns(
+          oat_file_strings.data(), num_dex_file_interns);
+      for (mirror::Object* string : dex_file_interns) {
+        bool inserted = table.insert(GcRoot<mirror::String>(string->AsString())).second;
+        DCHECK(inserted) << "String already inserted: " << string->AsString()->ToModifiedUtf8();
+      }
+      ArrayRef<mirror::String*> current_non_dex_file_interns =
+          non_dex_file_interns.SubArray(ndfi_index, num_non_dex_file_interns);
+      for (mirror::String* string : current_non_dex_file_interns) {
+        bool inserted = table.insert(GcRoot<mirror::String>(string)).second;
+        DCHECK(inserted) << "String already inserted: " << string->ToModifiedUtf8();
+      }
+
+      // Record the intern table size in bytes.
+      image_info.intern_table_bytes_ = table.WriteToMemory(nullptr);
+    }
+
+    ndfi_index = ndfi_end;
+  }
+}
+
 void ImageWriter::LayoutHelper::ProcessWorkQueue() {
   while (!work_queue_.empty()) {
     std::pair<ObjPtr<mirror::Object>, size_t> pair = work_queue_.front();
@@ -2193,10 +2192,6 @@
           bin_offset = RoundUp(bin_offset, ArtMethod::Alignment(image_writer_->target_ptr_size_));
           break;
         }
-        case Bin::kDexCacheArray:
-          bin_offset =
-              RoundUp(bin_offset, DexCacheArraysLayout::Alignment(image_writer_->target_ptr_size_));
-          break;
         case Bin::kImTable:
         case Bin::kIMTConflictTable: {
           bin_offset = RoundUp(bin_offset, static_cast<size_t>(image_writer_->target_ptr_size_));
@@ -2278,8 +2273,7 @@
   VLOG(image) << "Space wasted for region alignment " << image_writer_->region_alignment_wasted_;
 }
 
-void ImageWriter::LayoutHelper::CollectStringReferenceInfo(Thread* self) {
-  size_t managed_string_refs = 0u;
+void ImageWriter::LayoutHelper::CollectStringReferenceInfo() {
   size_t total_string_refs = 0u;
 
   const size_t num_image_infos = image_writer_->image_infos_.size();
@@ -2309,49 +2303,13 @@
       }
     }
 
-    managed_string_refs += image_info.string_reference_offsets_.size();
-
-    // Collect dex cache string arrays.
-    for (const DexFile* dex_file : image_writer_->compiler_options_.GetDexFilesForOatFile()) {
-      if (image_writer_->GetOatIndexForDexFile(dex_file) == oat_index) {
-        ObjPtr<mirror::DexCache> dex_cache =
-            Runtime::Current()->GetClassLinker()->FindDexCache(self, *dex_file);
-        DCHECK(dex_cache != nullptr);
-        size_t base_offset = image_writer_->GetImageOffset(dex_cache.Ptr(), oat_index);
-
-        // Visit all string cache entries.
-        mirror::StringDexCacheType* strings = dex_cache->GetStrings();
-        const size_t num_strings = dex_cache->NumStrings();
-        for (uint32_t index = 0; index != num_strings; ++index) {
-          ObjPtr<mirror::String> referred_string = strings[index].load().object.Read();
-          if (image_writer_->IsInternedAppImageStringReference(referred_string)) {
-            image_info.string_reference_offsets_.emplace_back(
-                SetDexCacheStringNativeRefTag(base_offset), index);
-          }
-        }
-
-        // Visit all pre-resolved string entries.
-        GcRoot<mirror::String>* preresolved_strings = dex_cache->GetPreResolvedStrings();
-        const size_t num_pre_resolved_strings = dex_cache->NumPreResolvedStrings();
-        for (uint32_t index = 0; index != num_pre_resolved_strings; ++index) {
-          ObjPtr<mirror::String> referred_string = preresolved_strings[index].Read();
-          if (image_writer_->IsInternedAppImageStringReference(referred_string)) {
-            image_info.string_reference_offsets_.emplace_back(
-                SetDexCachePreResolvedStringNativeRefTag(base_offset), index);
-          }
-        }
-      }
-    }
-
     total_string_refs += image_info.string_reference_offsets_.size();
 
     // Check that we collected the same number of string references as we saw in the previous pass.
     CHECK_EQ(image_info.string_reference_offsets_.size(), image_info.num_string_references_);
   }
 
-  VLOG(compiler) << "Dex2Oat:AppImage:stringReferences = " << total_string_refs
-      << " (managed: " << managed_string_refs
-      << ", native: " << (total_string_refs - managed_string_refs) << ")";
+  VLOG(compiler) << "Dex2Oat:AppImage:stringReferences = " << total_string_refs;
 }
 
 void ImageWriter::LayoutHelper::VisitReferences(ObjPtr<mirror::Object> obj, size_t oat_index) {
@@ -2375,7 +2333,6 @@
   }
   bool assigned = false;
   if (!image_writer_->IsImageBinSlotAssigned(obj.Ptr())) {
-    image_writer_->RecordNativeRelocations(obj, oat_index);
     Bin bin = image_writer_->AssignImageBinSlot(obj.Ptr(), oat_index);
     bin_objects_[oat_index][enum_cast<size_t>(bin)].push_back(obj.Ptr());
     assigned = true;
@@ -2452,36 +2409,17 @@
   LayoutHelper layout_helper(this);
   layout_helper.ProcessDexFileObjects(self);
   layout_helper.ProcessRoots(&handles);
+  layout_helper.FinalizeInternTables();
 
   // Verify that all objects have assigned image bin slots.
   layout_helper.VerifyImageBinSlotsAssigned();
 
-  // Calculate size of the dex cache arrays slot and prepare offsets.
-  PrepareDexCacheArraySlots();
-
-  // Calculate the sizes of the intern tables, class tables, and fixup tables.
-  for (ImageInfo& image_info : image_infos_) {
-    // Calculate how big the intern table will be after being serialized.
-    InternTable* const intern_table = image_info.intern_table_.get();
-    CHECK_EQ(intern_table->WeakSize(), 0u) << " should have strong interned all the strings";
-    if (intern_table->StrongSize() != 0u) {
-      image_info.intern_table_bytes_ = intern_table->WriteToMemory(nullptr);
-    }
-
-    // Calculate the size of the class table.
-    ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
-    DCHECK_EQ(image_info.class_table_->NumReferencedZygoteClasses(), 0u);
-    if (image_info.class_table_->NumReferencedNonZygoteClasses() != 0u) {
-      image_info.class_table_bytes_ += image_info.class_table_->WriteToMemory(nullptr);
-    }
-  }
-
   // Finalize bin slot offsets. This may add padding for regions.
   layout_helper.FinalizeBinSlotOffsets();
 
   // Collect string reference info for app images.
   if (ClassLinker::kAppImageMayContainStrings && compiler_options_.IsAppImage()) {
-    layout_helper.CollectStringReferenceInfo(self);
+    layout_helper.CollectStringReferenceInfo();
   }
 
   // Calculate image offsets.
@@ -2557,19 +2495,11 @@
       ImageSection(GetBinSlotOffset(Bin::kRuntimeMethod), GetBinSlotSize(Bin::kRuntimeMethod));
 
   /*
-   * DexCache Arrays section.
-   */
-  const ImageSection& dex_cache_arrays_section =
-      sections[ImageHeader::kSectionDexCacheArrays] =
-          ImageSection(GetBinSlotOffset(Bin::kDexCacheArray),
-                       GetBinSlotSize(Bin::kDexCacheArray));
-
-  /*
    * Interned Strings section
    */
 
   // Round up to the alignment the string table expects. See HashSet::WriteToMemory.
-  size_t cur_pos = RoundUp(dex_cache_arrays_section.End(), sizeof(uint64_t));
+  size_t cur_pos = RoundUp(sections[ImageHeader::kSectionRuntimeMethods].End(), sizeof(uint64_t));
 
   const ImageSection& interned_strings_section =
       sections[ImageHeader::kSectionInternedStrings] =
@@ -2606,8 +2536,7 @@
    */
 
   // Round up to the alignment of the offsets we are going to store.
-  cur_pos = RoundUp(string_reference_offsets.End(),
-                    mirror::DexCache::PreResolvedStringsAlignment());
+  cur_pos = RoundUp(string_reference_offsets.End(), sizeof(uint32_t));
 
   const ImageSection& metadata_section =
       sections[ImageHeader::kSectionMetadata] =
@@ -2803,13 +2732,6 @@
     DCHECK_GE(dest, image_info.image_.Begin() + image_info.image_end_);
     DCHECK(!IsInBootImage(pair.first));
     switch (relocation.type) {
-      case NativeObjectRelocationType::kArtField: {
-        memcpy(dest, pair.first, sizeof(ArtField));
-        CopyAndFixupReference(
-            reinterpret_cast<ArtField*>(dest)->GetDeclaringClassAddressWithoutBarrier(),
-            reinterpret_cast<ArtField*>(pair.first)->GetDeclaringClass());
-        break;
-      }
       case NativeObjectRelocationType::kRuntimeMethod:
       case NativeObjectRelocationType::kArtMethodClean:
       case NativeObjectRelocationType::kArtMethodDirty: {
@@ -2818,14 +2740,23 @@
                            oat_index);
         break;
       }
-      // For arrays, copy just the header since the elements will get copied by their corresponding
-      // relocations.
       case NativeObjectRelocationType::kArtFieldArray: {
-        memcpy(dest, pair.first, LengthPrefixedArray<ArtField>::ComputeSize(0));
+        // Copy and fix up the entire field array.
+        auto* src_array = reinterpret_cast<LengthPrefixedArray<ArtField>*>(pair.first);
+        auto* dest_array = reinterpret_cast<LengthPrefixedArray<ArtField>*>(dest);
+        size_t size = src_array->size();
+        memcpy(dest_array, src_array, LengthPrefixedArray<ArtField>::ComputeSize(size));
+        for (size_t i = 0; i != size; ++i) {
+          CopyAndFixupReference(
+              dest_array->At(i).GetDeclaringClassAddressWithoutBarrier(),
+              src_array->At(i).GetDeclaringClass());
+        }
         break;
       }
       case NativeObjectRelocationType::kArtMethodArrayClean:
       case NativeObjectRelocationType::kArtMethodArrayDirty: {
+        // For method arrays, copy just the header since the elements will
+        // get copied by their corresponding relocations.
         size_t size = ArtMethod::Size(target_ptr_size_);
         size_t alignment = ArtMethod::Alignment(target_ptr_size_);
         memcpy(dest, pair.first, LengthPrefixedArray<ArtMethod>::ComputeSize(0, size, alignment));
@@ -2834,9 +2765,6 @@
         reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(dest)->ClearPadding(size, alignment);
         break;
       }
-      case NativeObjectRelocationType::kDexCacheArray:
-        // Nothing to copy here, everything is done in FixupDexCache().
-        break;
       case NativeObjectRelocationType::kIMTable: {
         ImTable* orig_imt = reinterpret_cast<ImTable*>(pair.first);
         ImTable* dest_imt = reinterpret_cast<ImTable*>(dest);
@@ -2871,10 +2799,11 @@
   // Write the intern table into the image.
   if (image_info.intern_table_bytes_ > 0) {
     const ImageSection& intern_table_section = image_header->GetInternedStringsSection();
-    InternTable* const intern_table = image_info.intern_table_.get();
+    DCHECK(image_info.intern_table_.has_value());
+    const InternTable::UnorderedSet& intern_table = *image_info.intern_table_;
     uint8_t* const intern_table_memory_ptr =
         image_info.image_.Begin() + intern_table_section.Offset();
-    const size_t intern_table_bytes = intern_table->WriteToMemory(intern_table_memory_ptr);
+    const size_t intern_table_bytes = intern_table.WriteToMemory(intern_table_memory_ptr);
     CHECK_EQ(intern_table_bytes, image_info.intern_table_bytes_);
     // Fixup the pointers in the newly written intern table to contain image addresses.
     InternTable temp_intern_table;
@@ -2885,47 +2814,53 @@
     temp_intern_table.AddTableFromMemory(intern_table_memory_ptr,
                                          VoidFunctor(),
                                          /*is_boot_image=*/ false);
-    CHECK_EQ(temp_intern_table.Size(), intern_table->Size());
+    CHECK_EQ(temp_intern_table.Size(), intern_table.size());
     temp_intern_table.VisitRoots(&root_visitor, kVisitRootFlagAllRoots);
-    // Record relocations. (The root visitor does not get to see the slot addresses.)
-    MutexLock lock(Thread::Current(), *Locks::intern_table_lock_);
-    DCHECK(!temp_intern_table.strong_interns_.tables_.empty());
-    DCHECK(!temp_intern_table.strong_interns_.tables_[0].Empty());  // Inserted at the beginning.
+
+    if (kIsDebugBuild) {
+      MutexLock lock(Thread::Current(), *Locks::intern_table_lock_);
+      CHECK(!temp_intern_table.strong_interns_.tables_.empty());
+      // The UnorderedSet was inserted at the beginning.
+      CHECK_EQ(temp_intern_table.strong_interns_.tables_[0].Size(), intern_table.size());
+    }
   }
+
   // Write the class table(s) into the image. class_table_bytes_ may be 0 if there are multiple
   // class loaders. Writing multiple class tables into the image is currently unsupported.
   if (image_info.class_table_bytes_ > 0u) {
     const ImageSection& class_table_section = image_header->GetClassTableSection();
     uint8_t* const class_table_memory_ptr =
         image_info.image_.Begin() + class_table_section.Offset();
-    Thread* self = Thread::Current();
-    ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
 
-    ClassTable* table = image_info.class_table_.get();
-    CHECK(table != nullptr);
-    const size_t class_table_bytes = table->WriteToMemory(class_table_memory_ptr);
+    DCHECK(image_info.class_table_.has_value());
+    const ClassTable::ClassSet& table = *image_info.class_table_;
+    CHECK_EQ(table.size(), image_info.class_table_size_);
+    const size_t class_table_bytes = table.WriteToMemory(class_table_memory_ptr);
     CHECK_EQ(class_table_bytes, image_info.class_table_bytes_);
+
     // Fixup the pointers in the newly written class table to contain image addresses. See
     // above comment for intern tables.
     ClassTable temp_class_table;
     temp_class_table.ReadFromMemory(class_table_memory_ptr);
-    CHECK_EQ(temp_class_table.NumReferencedZygoteClasses(),
-             table->NumReferencedNonZygoteClasses() + table->NumReferencedZygoteClasses());
+    CHECK_EQ(temp_class_table.NumReferencedZygoteClasses(), table.size());
     UnbufferedRootVisitor visitor(&root_visitor, RootInfo(kRootUnknown));
     temp_class_table.VisitRoots(visitor);
-    // Record relocations. (The root visitor does not get to see the slot addresses.)
-    // Note that the low bits in the slots contain bits of the descriptors' hash codes
-    // but the relocation works fine for these "adjusted" references.
-    ReaderMutexLock lock(self, temp_class_table.lock_);
-    DCHECK(!temp_class_table.classes_.empty());
-    DCHECK(!temp_class_table.classes_[0].empty());  // The ClassSet was inserted at the beginning.
+
+    if (kIsDebugBuild) {
+      ReaderMutexLock lock(Thread::Current(), temp_class_table.lock_);
+      CHECK(!temp_class_table.classes_.empty());
+      // The ClassSet was inserted at the beginning.
+      CHECK_EQ(temp_class_table.classes_[0].size(), table.size());
+    }
   }
 }
 
-void ImageWriter::FixupPointerArray(mirror::Object* dst,
-                                    mirror::PointerArray* arr,
-                                    Bin array_type) {
-  CHECK(arr->IsIntArray() || arr->IsLongArray()) << arr->GetClass()->PrettyClass() << " " << arr;
+void ImageWriter::CopyAndFixupMethodPointerArray(mirror::PointerArray* arr) {
+  // Pointer arrays are processed early and each is visited just once.
+  // Therefore we know that this array has not been copied yet.
+  mirror::Object* dst = CopyObject</*kCheckIfDone=*/ false>(arr);
+  DCHECK(dst != nullptr);
+  DCHECK(arr->IsIntArray() || arr->IsLongArray()) << arr->GetClass()->PrettyClass() << " " << arr;
   // Fixup int and long pointers for the ArtMethod or ArtField arrays.
   const size_t num_elements = arr->GetLength();
   CopyAndFixupReference(
@@ -2936,18 +2871,10 @@
     if (kIsDebugBuild && elem != nullptr && !IsInBootImage(elem)) {
       auto it = native_object_relocations_.find(elem);
       if (UNLIKELY(it == native_object_relocations_.end())) {
-        if (it->second.IsArtMethodRelocation()) {
-          auto* method = reinterpret_cast<ArtMethod*>(elem);
-          LOG(FATAL) << "No relocation entry for ArtMethod " << method->PrettyMethod() << " @ "
-                     << method << " idx=" << i << "/" << num_elements << " with declaring class "
-                     << Class::PrettyClass(method->GetDeclaringClass());
-        } else {
-          CHECK_EQ(array_type, Bin::kArtField);
-          auto* field = reinterpret_cast<ArtField*>(elem);
-          LOG(FATAL) << "No relocation entry for ArtField " << field->PrettyField() << " @ "
-              << field << " idx=" << i << "/" << num_elements << " with declaring class "
-              << Class::PrettyClass(field->GetDeclaringClass());
-        }
+        auto* method = reinterpret_cast<ArtMethod*>(elem);
+        LOG(FATAL) << "No relocation entry for ArtMethod " << method->PrettyMethod() << " @ "
+                   << method << " idx=" << i << "/" << num_elements << " with declaring class "
+                   << Class::PrettyClass(method->GetDeclaringClass());
         UNREACHABLE();
       }
     }
@@ -2959,6 +2886,15 @@
   if (!IsImageBinSlotAssigned(obj)) {
     return;
   }
+  // Some objects (such as method pointer arrays) may have been processed before.
+  mirror::Object* dst = CopyObject</*kCheckIfDone=*/ true>(obj);
+  if (dst != nullptr) {
+    FixupObject(obj, dst);
+  }
+}
+
+template <bool kCheckIfDone>
+inline Object* ImageWriter::CopyObject(Object* obj) {
   size_t oat_index = GetOatIndex(obj);
   size_t offset = GetImageOffset(obj, oat_index);
   ImageInfo& image_info = GetImageInfo(oat_index);
@@ -2966,7 +2902,12 @@
   DCHECK_LT(offset, image_info.image_end_);
   const auto* src = reinterpret_cast<const uint8_t*>(obj);
 
-  image_info.image_bitmap_.Set(dst);  // Mark the obj as live.
+  bool done = image_info.image_bitmap_.Set(dst);  // Mark the obj as live.
+  // Check if the object was already copied, unless the caller indicated that it was not.
+  if (kCheckIfDone && done) {
+    return nullptr;
+  }
+  DCHECK(!done);
 
   const size_t n = obj->SizeOf();
 
@@ -2994,7 +2935,7 @@
     // safe since we mark all of the objects that may reference non immune objects as gray.
     CHECK(dst->AtomicSetMarkBit(0, 1));
   }
-  FixupObject(obj, dst);
+  return dst;
 }
 
 // Rewrite all the references in the copied object to point to their image address equivalent
@@ -3031,11 +2972,34 @@
 };
 
 void ImageWriter::CopyAndFixupObjects() {
+  // Copy and fix up pointer arrays first as they require special treatment.
+  auto method_pointer_array_visitor =
+      [&](ObjPtr<mirror::PointerArray> pointer_array) REQUIRES_SHARED(Locks::mutator_lock_) {
+        CopyAndFixupMethodPointerArray(pointer_array.Ptr());
+      };
+  for (ImageInfo& image_info : image_infos_) {
+    if (image_info.class_table_size_ != 0u) {
+      DCHECK(image_info.class_table_.has_value());
+      for (const ClassTable::TableSlot slot : *image_info.class_table_) {
+        ObjPtr<mirror::Class> klass = slot.Read<kWithoutReadBarrier>();
+        DCHECK(klass != nullptr);
+        // Do not process boot image classes present in app image class table.
+        DCHECK(!IsInBootImage(klass.Ptr()) || compiler_options_.IsAppImage());
+        if (!IsInBootImage(klass.Ptr())) {
+          // Do not fix up method pointer arrays inherited from superclass. If they are part
+          // of the current image, they were or shall be copied when visiting the superclass.
+          VisitNewMethodPointerArrays(klass, method_pointer_array_visitor);
+        }
+      }
+    }
+  }
+
   auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
     DCHECK(obj != nullptr);
     CopyAndFixupObject(obj);
   };
   Runtime::Current()->GetHeap()->VisitObjects(visitor);
+
   // Fill the padding objects since they are required for in order traversal of the image space.
   for (ImageInfo& image_info : image_infos_) {
     for (const size_t start_offset : image_info.padding_offsets_) {
@@ -3057,6 +3021,7 @@
       }
     }
   }
+
   // We no longer need the hashcode map, values have already been copied to target objects.
   saved_hashcode_map_.clear();
 }
@@ -3111,13 +3076,6 @@
   }
 }
 
-template <typename T>
-T* ImageWriter::NativeCopyLocation(T* obj) {
-  const NativeObjectRelocation relocation = GetNativeRelocation(obj);
-  const ImageInfo& image_info = GetImageInfo(relocation.oat_index);
-  return reinterpret_cast<T*>(image_info.image_.Begin() + relocation.offset);
-}
-
 class ImageWriter::NativeLocationVisitor {
  public:
   explicit NativeLocationVisitor(ImageWriter* image_writer)
@@ -3180,16 +3138,6 @@
   if (kUseBakerReadBarrier) {
     orig->AssertReadBarrierState();
   }
-  if (orig->IsIntArray() || orig->IsLongArray()) {
-    // Is this a native pointer array?
-    auto it = pointer_arrays_.find(down_cast<mirror::PointerArray*>(orig));
-    if (it != pointer_arrays_.end()) {
-      // Should only need to fixup every pointer array exactly once.
-      FixupPointerArray(copy, down_cast<mirror::PointerArray*>(orig), it->second);
-      pointer_arrays_.erase(it);
-      return;
-    }
-  }
   if (orig->IsClass()) {
     FixupClass(orig->AsClass<kVerifyNone>().Ptr(), down_cast<mirror::Class*>(copy));
   } else {
@@ -3204,7 +3152,7 @@
       ArtMethod* src_method = src->GetArtMethod();
       CopyAndFixupPointer(dest, mirror::Executable::ArtMethodOffset(), src_method);
     } else if (klass == GetClassRoot<mirror::DexCache>(class_roots)) {
-      FixupDexCache(down_cast<mirror::DexCache*>(orig), down_cast<mirror::DexCache*>(copy));
+      down_cast<mirror::DexCache*>(copy)->ResetNativeFields();
     } else if (klass->IsClassLoaderClass()) {
       mirror::ClassLoader* copy_loader = down_cast<mirror::ClassLoader*>(copy);
       // If src is a ClassLoader, set the class table to null so that it gets recreated by the
@@ -3220,113 +3168,6 @@
   }
 }
 
-template <typename T>
-void ImageWriter::FixupDexCacheArrayEntry(std::atomic<mirror::DexCachePair<T>>* orig_array,
-                                          std::atomic<mirror::DexCachePair<T>>* new_array,
-                                          uint32_t array_index) {
-  static_assert(sizeof(std::atomic<mirror::DexCachePair<T>>) == sizeof(mirror::DexCachePair<T>),
-                "Size check for removing std::atomic<>.");
-  mirror::DexCachePair<T>* orig_pair =
-      reinterpret_cast<mirror::DexCachePair<T>*>(&orig_array[array_index]);
-  mirror::DexCachePair<T>* new_pair =
-      reinterpret_cast<mirror::DexCachePair<T>*>(&new_array[array_index]);
-  CopyAndFixupReference(
-      new_pair->object.AddressWithoutBarrier(), orig_pair->object.Read());
-  new_pair->index = orig_pair->index;
-}
-
-template <typename T>
-void ImageWriter::FixupDexCacheArrayEntry(std::atomic<mirror::NativeDexCachePair<T>>* orig_array,
-                                          std::atomic<mirror::NativeDexCachePair<T>>* new_array,
-                                          uint32_t array_index) {
-  static_assert(
-      sizeof(std::atomic<mirror::NativeDexCachePair<T>>) == sizeof(mirror::NativeDexCachePair<T>),
-      "Size check for removing std::atomic<>.");
-  if (target_ptr_size_ == PointerSize::k64) {
-    DexCache::ConversionPair64* orig_pair =
-        reinterpret_cast<DexCache::ConversionPair64*>(orig_array) + array_index;
-    DexCache::ConversionPair64* new_pair =
-        reinterpret_cast<DexCache::ConversionPair64*>(new_array) + array_index;
-    *new_pair = *orig_pair;  // Copy original value and index.
-    if (orig_pair->first != 0u) {
-      CopyAndFixupPointer(
-          reinterpret_cast<void**>(&new_pair->first), reinterpret_cast64<void*>(orig_pair->first));
-    }
-  } else {
-    DexCache::ConversionPair32* orig_pair =
-        reinterpret_cast<DexCache::ConversionPair32*>(orig_array) + array_index;
-    DexCache::ConversionPair32* new_pair =
-        reinterpret_cast<DexCache::ConversionPair32*>(new_array) + array_index;
-    *new_pair = *orig_pair;  // Copy original value and index.
-    if (orig_pair->first != 0u) {
-      CopyAndFixupPointer(
-          reinterpret_cast<void**>(&new_pair->first), reinterpret_cast32<void*>(orig_pair->first));
-    }
-  }
-}
-
-void ImageWriter::FixupDexCacheArrayEntry(GcRoot<mirror::CallSite>* orig_array,
-                                          GcRoot<mirror::CallSite>* new_array,
-                                          uint32_t array_index) {
-  CopyAndFixupReference(
-      new_array[array_index].AddressWithoutBarrier(), orig_array[array_index].Read());
-}
-
-template <typename EntryType>
-void ImageWriter::FixupDexCacheArray(DexCache* orig_dex_cache,
-                                     DexCache* copy_dex_cache,
-                                     MemberOffset array_offset,
-                                     uint32_t size) {
-  EntryType* orig_array = orig_dex_cache->GetFieldPtr64<EntryType*>(array_offset);
-  DCHECK_EQ(orig_array != nullptr, size != 0u);
-  if (orig_array != nullptr) {
-    // Though the DexCache array fields are usually treated as native pointers, we clear
-    // the top 32 bits for 32-bit targets.
-    CopyAndFixupPointer(copy_dex_cache, array_offset, orig_array, PointerSize::k64);
-    EntryType* new_array = NativeCopyLocation(orig_array);
-    for (uint32_t i = 0; i != size; ++i) {
-      FixupDexCacheArrayEntry(orig_array, new_array, i);
-    }
-  }
-}
-
-void ImageWriter::FixupDexCache(DexCache* orig_dex_cache, DexCache* copy_dex_cache) {
-  FixupDexCacheArray<mirror::StringDexCacheType>(orig_dex_cache,
-                                                 copy_dex_cache,
-                                                 DexCache::StringsOffset(),
-                                                 orig_dex_cache->NumStrings());
-  FixupDexCacheArray<mirror::TypeDexCacheType>(orig_dex_cache,
-                                               copy_dex_cache,
-                                               DexCache::ResolvedTypesOffset(),
-                                               orig_dex_cache->NumResolvedTypes());
-  FixupDexCacheArray<mirror::MethodDexCacheType>(orig_dex_cache,
-                                                 copy_dex_cache,
-                                                 DexCache::ResolvedMethodsOffset(),
-                                                 orig_dex_cache->NumResolvedMethods());
-  FixupDexCacheArray<mirror::FieldDexCacheType>(orig_dex_cache,
-                                                copy_dex_cache,
-                                                DexCache::ResolvedFieldsOffset(),
-                                                orig_dex_cache->NumResolvedFields());
-  FixupDexCacheArray<mirror::MethodTypeDexCacheType>(orig_dex_cache,
-                                                     copy_dex_cache,
-                                                     DexCache::ResolvedMethodTypesOffset(),
-                                                     orig_dex_cache->NumResolvedMethodTypes());
-  FixupDexCacheArray<GcRoot<mirror::CallSite>>(orig_dex_cache,
-                                               copy_dex_cache,
-                                               DexCache::ResolvedCallSitesOffset(),
-                                               orig_dex_cache->NumResolvedCallSites());
-  if (orig_dex_cache->GetPreResolvedStrings() != nullptr) {
-    CopyAndFixupPointer(copy_dex_cache,
-                        DexCache::PreResolvedStringsOffset(),
-                        orig_dex_cache->GetPreResolvedStrings(),
-                        PointerSize::k64);
-  }
-
-  // Remove the DexFile pointers. They will be fixed up when the runtime loads the oat file. Leaving
-  // compiler pointers in here will make the output non-deterministic.
-  copy_dex_cache->SetDexFile(nullptr);
-}
-
 const uint8_t* ImageWriter::GetOatAddress(StubType type) const {
   DCHECK_LE(type, StubType::kLast);
   // If we are compiling a boot image extension or app image,
@@ -3353,6 +3194,8 @@
         return static_cast<const uint8_t*>(header.GetQuickResolutionTrampoline());
       case StubType::kQuickToInterpreterBridge:
         return static_cast<const uint8_t*>(header.GetQuickToInterpreterBridge());
+      case StubType::kNterpTrampoline:
+        return static_cast<const uint8_t*>(header.GetNterpTrampoline());
       default:
         UNREACHABLE();
     }
@@ -3385,14 +3228,27 @@
     quick_code = GetOatAddressForOffset(quick_oat_code_offset, image_info);
   }
 
+  bool needs_clinit_check = NeedsClinitCheckBeforeCall(method) &&
+      !method->GetDeclaringClass()->IsVisiblyInitialized();
+
   if (quick_code == nullptr) {
-    // If we don't have code, use generic jni / interpreter bridge.
-    // Both perform class initialization check if needed.
-    quick_code = method->IsNative()
-        ? GetOatAddress(StubType::kQuickGenericJNITrampoline)
-        : GetOatAddress(StubType::kQuickToInterpreterBridge);
-  } else if (NeedsClinitCheckBeforeCall(method) &&
-             !method->GetDeclaringClass()->IsVisiblyInitialized()) {
+    // If we don't have code, use generic jni / interpreter.
+    if (method->IsNative()) {
+      // The generic JNI trampolines performs class initialization check if needed.
+      quick_code = GetOatAddress(StubType::kQuickGenericJNITrampoline);
+    } else if (CanMethodUseNterp(method, compiler_options_.GetInstructionSet())) {
+      // The nterp trampoline doesn't do initialization checks, so install the
+      // resolution stub if needed.
+      if (needs_clinit_check) {
+        quick_code = GetOatAddress(StubType::kQuickResolutionTrampoline);
+      } else {
+        quick_code = GetOatAddress(StubType::kNterpTrampoline);
+      }
+    } else {
+      // The interpreter brige performs class initialization check if needed.
+      quick_code = GetOatAddress(StubType::kQuickToInterpreterBridge);
+    }
+  } else if (needs_clinit_check) {
     // If we do have code but the method needs a class initialization check before calling
     // that code, install the resolution stub that will perform the check.
     quick_code = GetOatAddress(StubType::kQuickResolutionTrampoline);
@@ -3432,6 +3288,9 @@
       CopyAndFixupPointer(copy, ArtMethod::DataOffset(target_ptr_size_), orig_table);
     } else if (UNLIKELY(orig == runtime->GetResolutionMethod())) {
       quick_code = GetOatAddress(StubType::kQuickResolutionTrampoline);
+      // Set JNI entrypoint for resolving @CriticalNative methods called from compiled code .
+      const void* jni_code = GetOatAddress(StubType::kJNIDlsymLookupCriticalTrampoline);
+      copy->SetEntryPointFromJniPtrSize(jni_code, target_ptr_size_);
     } else {
       bool found_one = false;
       for (size_t i = 0; i < static_cast<size_t>(CalleeSaveType::kLastCalleeSaveType); ++i) {
@@ -3463,8 +3322,10 @@
         StubType stub_type = orig->IsCriticalNative() ? StubType::kJNIDlsymLookupCriticalTrampoline
                                                       : StubType::kJNIDlsymLookupTrampoline;
         copy->SetEntryPointFromJniPtrSize(GetOatAddress(stub_type), target_ptr_size_);
-      } else {
+      } else if (!orig->HasCodeItem()) {
         CHECK(copy->GetDataPtrSize(target_ptr_size_) == nullptr);
+      } else {
+        CHECK(copy->GetDataPtrSize(target_ptr_size_) != nullptr);
       }
     }
   }
@@ -3505,7 +3366,6 @@
 
 ImageWriter::Bin ImageWriter::BinTypeForNativeRelocationType(NativeObjectRelocationType type) {
   switch (type) {
-    case NativeObjectRelocationType::kArtField:
     case NativeObjectRelocationType::kArtFieldArray:
       return Bin::kArtField;
     case NativeObjectRelocationType::kArtMethodClean:
@@ -3514,8 +3374,6 @@
     case NativeObjectRelocationType::kArtMethodDirty:
     case NativeObjectRelocationType::kArtMethodArrayDirty:
       return Bin::kArtMethodDirty;
-    case NativeObjectRelocationType::kDexCacheArray:
-      return Bin::kDexCacheArray;
     case NativeObjectRelocationType::kRuntimeMethod:
       return Bin::kRuntimeMethod;
     case NativeObjectRelocationType::kIMTable:
@@ -3530,6 +3388,7 @@
 
 size_t ImageWriter::GetOatIndex(mirror::Object* obj) const {
   if (!IsMultiImage()) {
+    DCHECK(oat_index_map_.empty());
     return GetDefaultOatIndex();
   }
   auto it = oat_index_map_.find(obj);
@@ -3609,6 +3468,8 @@
                                  oat_header.GetQuickResolutionTrampolineOffset());
     cur_image_info.SetStubOffset(StubType::kQuickToInterpreterBridge,
                                  oat_header.GetQuickToInterpreterBridgeOffset());
+    cur_image_info.SetStubOffset(StubType::kNterpTrampoline,
+                                 oat_header.GetNterpTrampolineOffset());
   }
 }
 
@@ -3617,7 +3478,7 @@
     uintptr_t image_begin,
     ImageHeader::StorageMode image_storage_mode,
     const std::vector<std::string>& oat_filenames,
-    const std::unordered_map<const DexFile*, size_t>& dex_file_oat_index_map,
+    const HashMap<const DexFile*, size_t>& dex_file_oat_index_map,
     jobject class_loader,
     const HashSet<std::string>* dirty_image_objects)
     : compiler_options_(compiler_options),
@@ -3652,8 +3513,8 @@
 }
 
 ImageWriter::ImageInfo::ImageInfo()
-    : intern_table_(new InternTable),
-      class_table_(new ClassTable) {}
+    : intern_table_(),
+      class_table_() {}
 
 template <typename DestType>
 void ImageWriter::CopyAndFixupReference(DestType* dest, ObjPtr<mirror::Object> src) {
diff --git a/dex2oat/linker/image_writer.h b/dex2oat/linker/image_writer.h
index 769f2ff..1321ced 100644
--- a/dex2oat/linker/image_writer.h
+++ b/dex2oat/linker/image_writer.h
@@ -26,13 +26,13 @@
 #include <set>
 #include <stack>
 #include <string>
-#include <unordered_map>
-#include <unordered_set>
 
 #include "art_method.h"
 #include "base/bit_utils.h"
 #include "base/dchecked_vector.h"
 #include "base/enums.h"
+#include "base/unix_file/fd_file.h"
+#include "base/hash_map.h"
 #include "base/hash_set.h"
 #include "base/length_prefixed_array.h"
 #include "base/macros.h"
@@ -71,8 +71,6 @@
 class ImtConflictTable;
 class TimingLogger;
 
-static constexpr int kInvalidFd = -1;
-
 namespace linker {
 
 // Write a Space built during compilation for use during execution.
@@ -82,7 +80,7 @@
               uintptr_t image_begin,
               ImageHeader::StorageMode image_storage_mode,
               const std::vector<std::string>& oat_filenames,
-              const std::unordered_map<const DexFile*, size_t>& dex_file_oat_index_map,
+              const HashMap<const DexFile*, size_t>& dex_file_oat_index_map,
               jobject class_loader,
               const HashSet<std::string>* dirty_image_objects);
 
@@ -102,7 +100,7 @@
    * image have been initialized and all native methods have been generated.  In
    * addition, no other thread should be modifying the heap.
    */
-  bool PrepareImageAddressSpace(bool preload_dex_caches, TimingLogger* timings);
+  bool PrepareImageAddressSpace(TimingLogger* timings);
 
   bool IsImageAddressSpaceReady() const {
     DCHECK(!image_infos_.empty());
@@ -139,9 +137,9 @@
     return GetImageInfo(oat_index).oat_file_begin_;
   }
 
-  // If image_fd is not kInvalidFd, then we use that for the image file. Otherwise we open
+  // If image_fd is not File::kInvalidFd, then we use that for the image file. Otherwise we open
   // the names in image_filenames.
-  // If oat_fd is not kInvalidFd, then we use that for the oat file. Otherwise we open
+  // If oat_fd is not File::kInvalidFd, then we use that for the oat file. Otherwise we open
   // the names in oat_filenames.
   bool Write(int image_fd,
              const std::vector<std::string>& image_filenames,
@@ -191,6 +189,8 @@
     kClassInitializedFinalStatics,  // Class initializers have been run, no non-final statics
     // Likely-clean:
     kString,                      // [String] Almost always immutable (except for obj header).
+    // Definitely clean:
+    kMethodPointerArray,          // ART internal vtables and interface method tables, int[]/long[].
     // Add more bins here if we add more segregation code.
     // Non mirror fields must be below.
     // ArtFields should be always clean.
@@ -208,18 +208,13 @@
     kRuntimeMethod,
     // Metadata bin for data that is temporary during image lifetime.
     kMetadata,
-    // Dex cache arrays have a special slot for PC-relative addressing. Since they are
-    // huge, and as such their dirtiness is not important for the clean/dirty separation,
-    // we arbitrarily keep them at the end of the native data.
-    kDexCacheArray,               // Arrays belonging to dex cache.
-    kLast = kDexCacheArray,
+    kLast = kMetadata,
     // Number of bins which are for mirror objects.
     kMirrorCount = kArtField,
   };
-  friend std::ostream& operator<<(std::ostream& stream, const Bin& bin);
+  friend std::ostream& operator<<(std::ostream& stream, Bin bin);
 
   enum class NativeObjectRelocationType {
-    kArtField,
     kArtFieldArray,
     kArtMethodClean,
     kArtMethodArrayClean,
@@ -229,9 +224,8 @@
     kRuntimeMethod,
     kIMTable,
     kIMTConflictTable,
-    kDexCacheArray,
   };
-  friend std::ostream& operator<<(std::ostream& stream, const NativeObjectRelocationType& type);
+  friend std::ostream& operator<<(std::ostream& stream, NativeObjectRelocationType type);
 
   enum class StubType {
     kJNIDlsymLookupTrampoline,
@@ -240,9 +234,10 @@
     kQuickIMTConflictTrampoline,
     kQuickResolutionTrampoline,
     kQuickToInterpreterBridge,
-    kLast = kQuickToInterpreterBridge,
+    kNterpTrampoline,
+    kLast = kNterpTrampoline,
   };
-  friend std::ostream& operator<<(std::ostream& stream, const StubType& stub_type);
+  friend std::ostream& operator<<(std::ostream& stream, StubType stub_type);
 
   static constexpr size_t kBinBits =
       MinimumBitsToStore<uint32_t>(static_cast<size_t>(Bin::kMirrorCount) - 1);
@@ -395,10 +390,14 @@
     std::vector<AppImageReferenceOffsetInfo> string_reference_offsets_;
 
     // Intern table associated with this image for serialization.
-    std::unique_ptr<InternTable> intern_table_;
+    size_t intern_table_size_ = 0;
+    std::unique_ptr<GcRoot<mirror::String>[]> intern_table_buffer_;
+    std::optional<InternTable::UnorderedSet> intern_table_;
 
     // Class table associated with this image for serialization.
-    std::unique_ptr<ClassTable> class_table_;
+    size_t class_table_size_ = 0;
+    std::unique_ptr<ClassTable::ClassSet::value_type[]> class_table_buffer_;
+    std::optional<ClassTable::ClassSet> class_table_;
 
     // Padding offsets to ensure region alignment (if required).
     // Objects need to be added from the recorded offset until the end of the region.
@@ -409,10 +408,11 @@
   size_t GetImageOffset(mirror::Object* object, size_t oat_index) const
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void PrepareDexCacheArraySlots() REQUIRES_SHARED(Locks::mutator_lock_);
   Bin AssignImageBinSlot(mirror::Object* object, size_t oat_index)
       REQUIRES_SHARED(Locks::mutator_lock_);
-  void RecordNativeRelocations(ObjPtr<mirror::Object> obj, size_t oat_index)
+  void AssignImageBinSlot(mirror::Object* object, size_t oat_index, Bin bin)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void RecordNativeRelocations(ObjPtr<mirror::Class> klass, size_t oat_index)
       REQUIRES_SHARED(Locks::mutator_lock_);
   void SetImageBinSlot(mirror::Object* object, BinSlot bin_slot)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -423,11 +423,6 @@
   void UpdateImageBinSlotOffset(mirror::Object* object, size_t oat_index, size_t new_offset)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void AddDexCacheArrayRelocation(void* array, size_t offset, size_t oat_index)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void AddMethodPointerArray(ObjPtr<mirror::PointerArray> arr)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Returns the address in the boot image if we are compiling the app image.
   const uint8_t* GetOatAddress(StubType type) const;
 
@@ -455,11 +450,6 @@
   void ClearDexCache(ObjPtr<mirror::DexCache> dex_cache)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Preload deterministic DexCache contents.
-  void PreloadDexCache(ObjPtr<mirror::DexCache> dex_cache, ObjPtr<mirror::ClassLoader> class_loader)
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::classlinker_classes_lock_);
-
   // Find dex caches for pruning or preloading.
   std::vector<ObjPtr<mirror::DexCache>> FindDexCaches(Thread* self)
       REQUIRES_SHARED(Locks::mutator_lock_)
@@ -486,6 +476,10 @@
   void CopyAndFixupNativeData(size_t oat_index) REQUIRES_SHARED(Locks::mutator_lock_);
   void CopyAndFixupObjects() REQUIRES_SHARED(Locks::mutator_lock_);
   void CopyAndFixupObject(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
+  template <bool kCheckIfDone>
+  mirror::Object* CopyObject(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
+  void CopyAndFixupMethodPointerArray(mirror::PointerArray* arr)
+      REQUIRES_SHARED(Locks::mutator_lock_);
   void CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy, size_t oat_index)
       REQUIRES_SHARED(Locks::mutator_lock_);
   void CopyAndFixupImTable(ImTable* orig, ImTable* copy)
@@ -511,33 +505,6 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
   void FixupObject(mirror::Object* orig, mirror::Object* copy)
       REQUIRES_SHARED(Locks::mutator_lock_);
-  template <typename T>
-  void FixupDexCacheArrayEntry(std::atomic<mirror::DexCachePair<T>>* orig_array,
-                               std::atomic<mirror::DexCachePair<T>>* new_array,
-                               uint32_t array_index)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  template <typename T>
-  void FixupDexCacheArrayEntry(std::atomic<mirror::NativeDexCachePair<T>>* orig_array,
-                               std::atomic<mirror::NativeDexCachePair<T>>* new_array,
-                               uint32_t array_index)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void FixupDexCacheArrayEntry(GcRoot<mirror::CallSite>* orig_array,
-                               GcRoot<mirror::CallSite>* new_array,
-                               uint32_t array_index)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  template <typename EntryType>
-  void FixupDexCacheArray(mirror::DexCache* orig_dex_cache,
-                          mirror::DexCache* copy_dex_cache,
-                          MemberOffset array_offset,
-                          uint32_t size)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void FixupDexCache(mirror::DexCache* orig_dex_cache,
-                     mirror::DexCache* copy_dex_cache)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  void FixupPointerArray(mirror::Object* dst,
-                         mirror::PointerArray* arr,
-                         Bin array_type)
-      REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Get quick code for non-resolution/imt_conflict/abstract method.
   const uint8_t* GetQuickCode(ArtMethod* method, const ImageInfo& image_info)
@@ -573,7 +540,7 @@
   // early_exit is true if we had a cyclic dependency anywhere down the chain.
   bool PruneImageClassInternal(ObjPtr<mirror::Class> klass,
                                bool* early_exit,
-                               std::unordered_set<mirror::Object*>* visited)
+                               HashSet<mirror::Object*>* visited)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   bool IsMultiImage() const {
@@ -600,10 +567,6 @@
   template <typename T>
   T* NativeLocationInImage(T* obj) REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Location of where the temporary copy of the object currently is.
-  template <typename T>
-  T* NativeCopyLocation(T* obj) REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Return true if `dex_cache` belongs to the image we're writing.
   // For a boot image, this is true for all dex caches.
   // For an app image, boot class path dex caches are excluded.
@@ -675,16 +638,12 @@
   // Offset from image_begin_ to where the first object is in image_.
   size_t image_objects_offset_begin_;
 
-  // Pointer arrays that need to be updated. Since these are only some int and long arrays, we need
-  // to keep track. These include vtable arrays, iftable arrays, and dex caches.
-  std::unordered_map<mirror::PointerArray*, Bin> pointer_arrays_;
-
   // Saved hash codes. We use these to restore lockwords which were temporarily used to have
   // forwarding addresses as well as copying over hash codes.
-  std::unordered_map<mirror::Object*, uint32_t> saved_hashcode_map_;
+  HashMap<mirror::Object*, uint32_t> saved_hashcode_map_;
 
   // Oat index map for objects.
-  std::unordered_map<mirror::Object*, uint32_t> oat_index_map_;
+  HashMap<mirror::Object*, uint32_t> oat_index_map_;
 
   // Size of pointers on the target architecture.
   PointerSize target_ptr_size_;
@@ -695,7 +654,7 @@
   // ArtField, ArtMethod relocating map. These are allocated as array of structs but we want to
   // have one entry per art field for convenience. ArtFields are placed right after the end of the
   // image objects (aka sum of bin_slot_sizes_). ArtMethods are placed right after the ArtFields.
-  std::unordered_map<void*, NativeObjectRelocation> native_object_relocations_;
+  HashMap<void*, NativeObjectRelocation> native_object_relocations_;
 
   // Runtime ArtMethods which aren't reachable from any Class but need to be copied into the image.
   ArtMethod* image_methods_[ImageHeader::kImageMethodsCount];
@@ -705,7 +664,7 @@
   uint64_t clean_methods_;
 
   // Prune class memoization table to speed up ContainsBootClassLoaderNonImageClass.
-  std::unordered_map<mirror::Class*, bool> prune_class_memo_;
+  HashMap<mirror::Class*, bool> prune_class_memo_;
 
   // The application class loader. Null for boot image.
   jobject app_class_loader_;
@@ -720,7 +679,7 @@
   const std::vector<std::string>& oat_filenames_;
 
   // Map of dex files to the indexes of oat files that they were compiled into.
-  const std::unordered_map<const DexFile*, size_t>& dex_file_oat_index_map_;
+  const HashMap<const DexFile*, size_t>& dex_file_oat_index_map_;
 
   // Set of objects known to be dirty in the image. Can be nullptr if there are none.
   const HashSet<std::string>* dirty_image_objects_;
@@ -747,6 +706,10 @@
   DISALLOW_COPY_AND_ASSIGN(ImageWriter);
 };
 
+std::ostream& operator<<(std::ostream& stream, ImageWriter::Bin bin);
+std::ostream& operator<<(std::ostream& stream, ImageWriter::NativeObjectRelocationType type);
+std::ostream& operator<<(std::ostream& stream, ImageWriter::StubType stub_type);
+
 }  // namespace linker
 }  // namespace art
 
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index eed76cc..af2db2d 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -70,7 +70,6 @@
 #include "stream/buffered_output_stream.h"
 #include "stream/file_output_stream.h"
 #include "stream/output_stream.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
 #include "vdex_file.h"
 #include "verifier/verifier_deps.h"
 
@@ -186,14 +185,25 @@
     return static_cast<const uint8_t*>(source_);
   }
 
+  void SetDexLayoutData(std::vector<uint8_t>&& dexlayout_data) {
+    DCHECK_GE(dexlayout_data.size(), sizeof(DexFile::Header));
+    dexlayout_data_ = std::move(dexlayout_data);
+    type_ = kRawData;
+    source_ = dexlayout_data_.data();
+  }
+
   void Clear() {
     type_ = kNone;
     source_ = nullptr;
+    // Release the memory held by `dexlayout_data_`.
+    std::vector<uint8_t> temp;
+    temp.swap(dexlayout_data_);
   }
 
  private:
   Type type_;
   const void* source_;
+  std::vector<uint8_t> dexlayout_data_;
 };
 
 // OatClassHeader is the header only part of the oat class that is required even when compilation
@@ -206,15 +216,15 @@
                  ClassStatus status)
       : status_(enum_cast<uint16_t>(status)),
         offset_(offset) {
-    // We just arbitrarily say that 0 methods means kOatClassNoneCompiled and that we won't use
-    // kOatClassAllCompiled unless there is at least one compiled method. This means in an
-    // interpreter only system, we can assert that all classes are kOatClassNoneCompiled.
+    // We just arbitrarily say that 0 methods means OatClassType::kNoneCompiled and that we won't
+    // use OatClassType::kAllCompiled unless there is at least one compiled method. This means in
+    // an interpreter only system, we can assert that all classes are OatClassType::kNoneCompiled.
     if (num_non_null_compiled_methods == 0) {
-      type_ = kOatClassNoneCompiled;
+      type_ = enum_cast<uint16_t>(OatClassType::kNoneCompiled);
     } else if (num_non_null_compiled_methods == num_methods) {
-      type_ = kOatClassAllCompiled;
+      type_ = enum_cast<uint16_t>(OatClassType::kAllCompiled);
     } else {
-      type_ = kOatClassSomeCompiled;
+      type_ = enum_cast<uint16_t>(OatClassType::kSomeCompiled);
     }
   }
 
@@ -225,10 +235,10 @@
   }
 
   // Data to write.
-  static_assert(enum_cast<>(ClassStatus::kLast) < (1 << 16), "class status won't fit in 16bits");
+  static_assert(sizeof(ClassStatus) <= sizeof(uint16_t), "class status won't fit in 16bits");
   uint16_t status_;
 
-  static_assert(OatClassType::kOatClassMax < (1 << 16), "oat_class type won't fit in 16bits");
+  static_assert(sizeof(OatClassType) <= sizeof(uint16_t), "oat_class type won't fit in 16bits");
   uint16_t type_;
 
   // Offset of start of OatClass from beginning of OatHeader. It is
@@ -257,17 +267,25 @@
   // Offset from OatClass::offset_ to the OatMethodOffsets for the
   // class_def_method_index. If 0, it means the corresponding
   // CompiledMethod entry in OatClass::compiled_methods_ should be
-  // null and that the OatClass::type_ should be kOatClassBitmap.
+  // null and that the OatClass::type_ should be OatClassType::kSomeCompiled.
   dchecked_vector<uint32_t> oat_method_offsets_offsets_from_oat_class_;
 
   // Data to write.
-  uint32_t method_bitmap_size_;
 
-  // bit vector indexed by ClassDef method index. When
-  // OatClassType::type_ is kOatClassBitmap, a set bit indicates the
-  // method has an OatMethodOffsets in methods_offsets_, otherwise
-  // the entry was ommited to save space. If OatClassType::type_ is
-  // not is kOatClassBitmap, the bitmap will be null.
+  // Number of methods recorded in OatClass. For `OatClassType::kNoneCompiled`
+  // this shall be zero and shall not be written to the file, otherwise it
+  // shall be the number of methods in the class definition. It is used to
+  // determine the size of `BitVector` data for `OatClassType::kSomeCompiled` and
+  // the size of the `OatMethodOffsets` table for `OatClassType::kAllCompiled`.
+  // (The size of the `OatMethodOffsets` table for `OatClassType::kSomeCompiled`
+  // is determined by the number of bits set in the `BitVector` data.)
+  uint32_t num_methods_;
+
+  // Bit vector indexed by ClassDef method index. When OatClass::type_ is
+  // OatClassType::kSomeCompiled, a set bit indicates the method has an
+  // OatMethodOffsets in methods_offsets_, otherwise
+  // the entry was omitted to save space. If OatClass::type_ is
+  // not is OatClassType::kSomeCompiled, the bitmap will be null.
   std::unique_ptr<BitVector> method_bitmap_;
 
   // OatMethodOffsets and OatMethodHeaders for each CompiledMethod
@@ -290,7 +308,6 @@
  public:
   OatDexFile(const char* dex_file_location,
              DexFileSource source,
-             CreateTypeLookupTable create_type_lookup_table,
              uint32_t dex_file_location_checksun,
              size_t dex_file_size);
   OatDexFile(OatDexFile&& src) = default;
@@ -310,11 +327,8 @@
   // The source of the dex file.
   DexFileSource source_;
 
-  // Whether to create the type lookup table.
-  CreateTypeLookupTable create_type_lookup_table_;
-
   // Dex file size. Passed in the constructor, but could be
-  // overwritten by LayoutAndWriteDexFile.
+  // overwritten by LayoutDexFile.
   size_t dex_file_size_;
 
   // Offset of start of OatDexFile from beginning of OatHeader. It is
@@ -340,6 +354,8 @@
   uint32_t class_offsets_offset_;
   uint32_t method_bss_mapping_offset_;
   uint32_t type_bss_mapping_offset_;
+  uint32_t public_type_bss_mapping_offset_;
+  uint32_t package_type_bss_mapping_offset_;
   uint32_t string_bss_mapping_offset_;
 
   // Offset of dex sections that will have different runtime madvise states.
@@ -380,6 +396,7 @@
     compiler_options_(compiler_options),
     image_writer_(nullptr),
     extract_dex_files_into_vdex_(true),
+    vdex_begin_(nullptr),
     dex_files_(nullptr),
     primary_oat_file_(false),
     vdex_size_(0u),
@@ -387,6 +404,7 @@
     vdex_dex_shared_data_offset_(0u),
     vdex_verifier_deps_offset_(0u),
     vdex_quickening_info_offset_(0u),
+    vdex_lookup_tables_offset_(0u),
     oat_checksum_(adler32(0L, Z_NULL, 0)),
     code_size_(0u),
     oat_size_(0u),
@@ -400,12 +418,15 @@
     bss_method_entry_references_(),
     bss_method_entries_(),
     bss_type_entries_(),
+    bss_public_type_entries_(),
+    bss_package_type_entries_(),
     bss_string_entries_(),
     oat_data_offset_(0u),
     oat_header_(nullptr),
     size_vdex_header_(0),
     size_vdex_checksums_(0),
     size_dex_file_alignment_(0),
+    size_quickening_table_offset_(0),
     size_executable_offset_alignment_(0),
     size_oat_header_(0),
     size_oat_header_key_value_store_(0),
@@ -414,6 +435,8 @@
     size_verifier_deps_alignment_(0),
     size_quickening_info_(0),
     size_quickening_info_alignment_(0),
+    size_vdex_lookup_table_alignment_(0),
+    size_vdex_lookup_table_(0),
     size_interpreter_to_interpreter_bridge_(0),
     size_interpreter_to_compiled_code_bridge_(0),
     size_jni_dlsym_lookup_trampoline_(0),
@@ -422,6 +445,7 @@
     size_quick_imt_conflict_trampoline_(0),
     size_quick_resolution_trampoline_(0),
     size_quick_to_interpreter_bridge_(0),
+    size_nterp_trampoline_(0),
     size_trampoline_alignment_(0),
     size_method_header_(0),
     size_code_(0),
@@ -443,17 +467,20 @@
     size_oat_dex_file_dex_layout_sections_alignment_(0),
     size_oat_dex_file_method_bss_mapping_offset_(0),
     size_oat_dex_file_type_bss_mapping_offset_(0),
+    size_oat_dex_file_public_type_bss_mapping_offset_(0),
+    size_oat_dex_file_package_type_bss_mapping_offset_(0),
     size_oat_dex_file_string_bss_mapping_offset_(0),
-    size_oat_lookup_table_alignment_(0),
-    size_oat_lookup_table_(0),
     size_oat_class_offsets_alignment_(0),
     size_oat_class_offsets_(0),
     size_oat_class_type_(0),
     size_oat_class_status_(0),
+    size_oat_class_num_methods_(0),
     size_oat_class_method_bitmaps_(0),
     size_oat_class_method_offsets_(0),
     size_method_bss_mappings_(0u),
     size_type_bss_mappings_(0u),
+    size_public_type_bss_mappings_(0u),
+    size_package_type_bss_mappings_(0u),
     size_string_bss_mappings_(0u),
     relative_patcher_(nullptr),
     profile_compilation_info_(info),
@@ -500,9 +527,7 @@
   return AsUnalignedDexFileHeader(raw_header);
 }
 
-bool OatWriter::AddDexFileSource(const char* filename,
-                                 const char* location,
-                                 CreateTypeLookupTable create_type_lookup_table) {
+bool OatWriter::AddDexFileSource(const char* filename, const char* location) {
   DCHECK(write_state_ == WriteState::kAddingDexFileSources);
   File fd(filename, O_RDONLY, /* check_usage= */ false);
   if (fd.Fd() == -1) {
@@ -510,14 +535,12 @@
     return false;
   }
 
-  return AddDexFileSource(std::move(fd), location, create_type_lookup_table);
+  return AddDexFileSource(std::move(fd), location);
 }
 
 // Add dex file source(s) from a file specified by a file handle.
 // Note: The `dex_file_fd` specifies a plain dex file or a zip file.
-bool OatWriter::AddDexFileSource(File&& dex_file_fd,
-                                 const char* location,
-                                 CreateTypeLookupTable create_type_lookup_table) {
+bool OatWriter::AddDexFileSource(File&& dex_file_fd, const char* location) {
   DCHECK(write_state_ == WriteState::kAddingDexFileSources);
   std::string error_msg;
   uint32_t magic;
@@ -539,7 +562,6 @@
     oat_dex_files_.emplace_back(/* OatDexFile */
         location,
         DexFileSource(raw_dex_files_.back().get()),
-        create_type_lookup_table,
         header->checksum_,
         header->file_size_);
   } else if (IsZipMagic(magic)) {
@@ -563,7 +585,6 @@
       oat_dex_files_.emplace_back(/* OatDexFile */
           full_location,
           DexFileSource(zipped_dex_files_.back().get()),
-          create_type_lookup_table,
           zipped_dex_files_.back()->GetCrc32(),
           zipped_dex_files_.back()->GetUncompressedLength());
     }
@@ -579,14 +600,13 @@
 }
 
 // Add dex file source(s) from a vdex file specified by a file handle.
-bool OatWriter::AddVdexDexFilesSource(const VdexFile& vdex_file,
-                                      const char* location,
-                                      CreateTypeLookupTable create_type_lookup_table) {
+bool OatWriter::AddVdexDexFilesSource(const VdexFile& vdex_file, const char* location) {
   DCHECK(write_state_ == WriteState::kAddingDexFileSources);
   DCHECK(vdex_file.HasDexSection());
   const uint8_t* current_dex_data = nullptr;
-  for (size_t i = 0; i < vdex_file.GetVerifierDepsHeader().GetNumberOfDexFiles(); ++i) {
-    current_dex_data = vdex_file.GetNextDexFileData(current_dex_data);
+  size_t i = 0;
+  for (; i < vdex_file.GetNumberOfDexFiles(); ++i) {
+    current_dex_data = vdex_file.GetNextDexFileData(current_dex_data, i);
     if (current_dex_data == nullptr) {
       LOG(ERROR) << "Unexpected number of dex files in vdex " << location;
       return false;
@@ -603,12 +623,11 @@
     oat_dex_files_.emplace_back(/* OatDexFile */
         full_location,
         DexFileSource(current_dex_data),
-        create_type_lookup_table,
         vdex_file.GetLocationChecksum(i),
         header->file_size_);
   }
 
-  if (vdex_file.GetNextDexFileData(current_dex_data) != nullptr) {
+  if (vdex_file.GetNextDexFileData(current_dex_data, i) != nullptr) {
     LOG(ERROR) << "Unexpected number of dex files in vdex " << location;
     return false;
   }
@@ -623,8 +642,7 @@
 // Add dex file source from raw memory.
 bool OatWriter::AddRawDexFileSource(const ArrayRef<const uint8_t>& data,
                                     const char* location,
-                                    uint32_t location_checksum,
-                                    CreateTypeLookupTable create_type_lookup_table) {
+                                    uint32_t location_checksum) {
   DCHECK(write_state_ == WriteState::kAddingDexFileSources);
   if (data.size() < sizeof(DexFile::Header)) {
     LOG(ERROR) << "Provided data is shorter than dex file header. size: "
@@ -644,7 +662,6 @@
   oat_dex_files_.emplace_back(/* OatDexFile */
       location,
       DexFileSource(data.data()),
-      create_type_lookup_table,
       location_checksum,
       header->file_size_);
   return true;
@@ -672,22 +689,23 @@
     /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
   CHECK(write_state_ == WriteState::kAddingDexFileSources);
 
-  // Reserve space for Vdex header and checksums.
-  vdex_size_ = sizeof(VdexFile::VerifierDepsHeader) +
-      oat_dex_files_.size() * sizeof(VdexFile::VdexChecksum);
+  size_vdex_header_ = sizeof(VdexFile::VdexFileHeader) +
+      VdexSection::kNumberOfSections * sizeof(VdexFile::VdexSectionHeader);
+  // Reserve space for Vdex header, sections, and checksums.
+  vdex_size_ = size_vdex_header_ + oat_dex_files_.size() * sizeof(VdexFile::VdexChecksum);
 
-  std::unique_ptr<BufferedOutputStream> vdex_out =
-      std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(vdex_file));
   // Write DEX files into VDEX, mmap and open them.
   std::vector<MemMap> dex_files_map;
   std::vector<std::unique_ptr<const DexFile>> dex_files;
-  if (!WriteDexFiles(vdex_out.get(), vdex_file, update_input_vdex, copy_dex_files) ||
+  if (!WriteDexFiles(vdex_file, update_input_vdex, copy_dex_files, &dex_files_map) ||
       !OpenDexFiles(vdex_file, verify, &dex_files_map, &dex_files)) {
     return false;
   }
 
   *opened_dex_files_map = std::move(dex_files_map);
   *opened_dex_files = std::move(dex_files);
+  // Create type lookup tables to speed up lookups during compilation.
+  InitializeTypeLookupTables(*opened_dex_files);
   write_state_ = WriteState::kStartRoData;
   return true;
 }
@@ -711,11 +729,6 @@
 
   ChecksumUpdatingOutputStream checksum_updating_rodata(oat_rodata, this);
 
-  // Write type lookup tables into the oat file.
-  if (!WriteTypeLookupTables(&checksum_updating_rodata, dex_files)) {
-    return false;
-  }
-
   // Write dex layout sections into the oat file.
   if (!WriteDexLayoutSections(&checksum_updating_rodata, dex_files)) {
     return false;
@@ -873,12 +886,6 @@
   return method != nullptr && !method->GetQuickCode().empty();
 }
 
-static bool HasQuickeningInfo(const CompiledMethod* method) {
-  // The dextodexcompiler puts the quickening info table into the CompiledMethod
-  // for simplicity.
-  return method != nullptr && method->GetQuickCode().empty() && !method->GetVmapTable().empty();
-}
-
 class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor {
  public:
   explicit InitBssLayoutMethodVisitor(OatWriter* writer)
@@ -906,6 +913,18 @@
                           target_type.dex_file->NumTypeIds(),
                           &writer_->bss_type_entry_references_);
           writer_->bss_type_entries_.Overwrite(target_type, /* placeholder */ 0u);
+        } else if (patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry) {
+          TypeReference target_type(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+          AddBssReference(target_type,
+                          target_type.dex_file->NumTypeIds(),
+                          &writer_->bss_public_type_entry_references_);
+          writer_->bss_public_type_entries_.Overwrite(target_type, /* placeholder */ 0u);
+        } else if (patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry) {
+          TypeReference target_type(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+          AddBssReference(target_type,
+                          target_type.dex_file->NumTypeIds(),
+                          &writer_->bss_package_type_entry_references_);
+          writer_->bss_package_type_entries_.Overwrite(target_type, /* placeholder */ 0u);
         } else if (patch.GetType() == LinkerPatch::Type::kStringBssEntry) {
           StringReference target_string(patch.TargetStringDexFile(), patch.TargetStringIndex());
           AddBssReference(target_string,
@@ -927,6 +946,7 @@
     // We currently support inlining of throwing instructions only when they originate in the
     // same dex file as the outer method. All .bss references are used by throwing instructions.
     DCHECK_EQ(dex_file_, ref.dex_file);
+    DCHECK_LT(ref.index, number_of_indexes);
 
     auto refs_it = references->find(ref.dex_file);
     if (refs_it == references->end()) {
@@ -1343,18 +1363,16 @@
     // Update quick method header.
     DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size());
     OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
-    uint32_t vmap_table_offset = method_header->GetVmapTableOffset();
-    // The code offset was 0 when the mapping/vmap table offset was set, so it's set
-    // to 0-offset and we need to adjust it by code_offset.
+    uint32_t code_info_offset = method_header->GetCodeInfoOffset();
     uint32_t code_offset = quick_code_offset - thumb_offset;
     CHECK(!compiled_method->GetQuickCode().empty());
     // If the code is compiled, we write the offset of the stack map relative
-    // to the code.
-    if (vmap_table_offset != 0u) {
-      vmap_table_offset += code_offset;
-      DCHECK_LT(vmap_table_offset, code_offset);
+    // to the code. The offset was previously stored relative to start of file.
+    if (code_info_offset != 0u) {
+      DCHECK_LT(code_info_offset, code_offset);
+      code_info_offset = code_offset - code_info_offset;
     }
-    *method_header = OatQuickMethodHeader(vmap_table_offset, code_size);
+    *method_header = OatQuickMethodHeader(code_info_offset);
 
     if (!deduped) {
       // Update offsets. (Checksum is updated when writing.)
@@ -1370,6 +1388,7 @@
 
       // Record debug information for this function if we are doing that.
       debug::MethodDebugInfo& info = writer_->method_info_[debug_info_idx];
+      // Simpleperf relies on art_jni_trampoline to detect jni methods.
       info.custom_name = (access_flags & kAccNative) ? "art_jni_trampoline" : "";
       info.dex_file = method_ref.dex_file;
       info.class_def_index = class_def_index;
@@ -1478,7 +1497,7 @@
 
     if (HasCompiledCode(compiled_method)) {
       DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
-      DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].GetVmapTableOffset(), 0u);
+      DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].GetCodeInfoOffset(), 0u);
 
       ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
       if (map.size() != 0u) {
@@ -1486,9 +1505,9 @@
           // Deduplicate the inner BitTable<>s within the CodeInfo.
           return offset_ + dedupe_bit_table_.Dedupe(map.data());
         });
-        // Code offset is not initialized yet, so set the map offset to 0u-offset.
+        // Code offset is not initialized yet, so set file offset for now.
         DCHECK_EQ(oat_class->method_offsets_[method_offsets_index_].code_offset_, 0u);
-        oat_class->method_headers_[method_offsets_index_].SetVmapTableOffset(0u - offset);
+        oat_class->method_headers_[method_offsets_index_].SetCodeInfoOffset(offset);
       }
       ++method_offsets_index_;
     }
@@ -1827,6 +1846,26 @@
                                                                    target_offset);
               break;
             }
+            case LinkerPatch::Type::kPublicTypeBssEntry: {
+              TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+              uint32_t target_offset =
+                  writer_->bss_start_ + writer_->bss_public_type_entries_.Get(ref);
+              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                   patch,
+                                                                   offset_ + literal_offset,
+                                                                   target_offset);
+              break;
+            }
+            case LinkerPatch::Type::kPackageTypeBssEntry: {
+              TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+              uint32_t target_offset =
+                  writer_->bss_start_ + writer_->bss_package_type_entries_.Get(ref);
+              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                   patch,
+                                                                   offset_ + literal_offset,
+                                                                   target_offset);
+              break;
+            }
             case LinkerPatch::Type::kMethodRelative: {
               uint32_t target_offset = GetTargetMethodOffset(GetTargetMethod(patch));
               writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
@@ -1835,6 +1874,17 @@
                                                                    target_offset);
               break;
             }
+            case LinkerPatch::Type::kJniEntrypointRelative: {
+              DCHECK(GetTargetMethod(patch)->IsNative());
+              uint32_t target_offset =
+                  GetTargetMethodOffset(GetTargetMethod(patch)) +
+                  ArtMethod::EntryPointFromJniOffset(pointer_size_).Uint32Value();
+              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                   patch,
+                                                                   offset_ + literal_offset,
+                                                                   target_offset);
+              break;
+            }
             case LinkerPatch::Type::kCallEntrypoint: {
               writer_->relative_patcher_->PatchEntrypointCall(&patched_code_,
                                                               patch,
@@ -2113,9 +2163,22 @@
   return IndexBssMapping::ComputeSize(number_of_entries);
 }
 
+static size_t CalculateIndexBssMappingSize(
+    const DexFile* dex_file,
+    const BitVector& type_indexes,
+    const SafeMap<TypeReference, size_t, TypeReferenceValueComparator>& bss_entries) {
+  return CalculateIndexBssMappingSize(
+      dex_file->NumTypeIds(),
+      sizeof(GcRoot<mirror::Class>),
+      type_indexes,
+      [=](uint32_t index) { return bss_entries.Get({dex_file, dex::TypeIndex(index)}); });
+}
+
 size_t OatWriter::InitIndexBssMappings(size_t offset) {
   if (bss_method_entry_references_.empty() &&
       bss_type_entry_references_.empty() &&
+      bss_public_type_entry_references_.empty() &&
+      bss_package_type_entry_references_.empty() &&
       bss_string_entry_references_.empty()) {
     return offset;
   }
@@ -2126,6 +2189,8 @@
 
   size_t number_of_method_dex_files = 0u;
   size_t number_of_type_dex_files = 0u;
+  size_t number_of_public_type_dex_files = 0u;
+  size_t number_of_package_type_dex_files = 0u;
   size_t number_of_string_dex_files = 0u;
   PointerSize pointer_size = GetInstructionSetPointerSize(oat_header_->GetInstructionSet());
   for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
@@ -2149,13 +2214,23 @@
       const BitVector& type_indexes = type_it->second;
       ++number_of_type_dex_files;
       oat_dex_files_[i].type_bss_mapping_offset_ = offset;
-      offset += CalculateIndexBssMappingSize(
-          dex_file->NumTypeIds(),
-          sizeof(GcRoot<mirror::Class>),
-          type_indexes,
-          [=](uint32_t index) {
-            return bss_type_entries_.Get({dex_file, dex::TypeIndex(index)});
-          });
+      offset += CalculateIndexBssMappingSize(dex_file, type_indexes, bss_type_entries_);
+    }
+
+    auto public_type_it = bss_public_type_entry_references_.find(dex_file);
+    if (public_type_it != bss_public_type_entry_references_.end()) {
+      const BitVector& type_indexes = public_type_it->second;
+      ++number_of_public_type_dex_files;
+      oat_dex_files_[i].public_type_bss_mapping_offset_ = offset;
+      offset += CalculateIndexBssMappingSize(dex_file, type_indexes, bss_public_type_entries_);
+    }
+
+    auto package_type_it = bss_package_type_entry_references_.find(dex_file);
+    if (package_type_it != bss_package_type_entry_references_.end()) {
+      const BitVector& type_indexes = package_type_it->second;
+      ++number_of_package_type_dex_files;
+      oat_dex_files_[i].package_type_bss_mapping_offset_ = offset;
+      offset += CalculateIndexBssMappingSize(dex_file, type_indexes, bss_package_type_entries_);
     }
 
     auto string_it = bss_string_entry_references_.find(dex_file);
@@ -2175,6 +2250,8 @@
   // Check that all dex files targeted by bss entries are in `*dex_files_`.
   CHECK_EQ(number_of_method_dex_files, bss_method_entry_references_.size());
   CHECK_EQ(number_of_type_dex_files, bss_type_entry_references_.size());
+  CHECK_EQ(number_of_public_type_dex_files, bss_public_type_entry_references_.size());
+  CHECK_EQ(number_of_package_type_dex_files, bss_package_type_entry_references_.size());
   CHECK_EQ(number_of_string_dex_files, bss_string_entry_references_.size());
   return offset;
 }
@@ -2224,6 +2301,7 @@
     DO_TRAMPOLINE(quick_imt_conflict_trampoline_, QuickImtConflictTrampoline);
     DO_TRAMPOLINE(quick_resolution_trampoline_, QuickResolutionTrampoline);
     DO_TRAMPOLINE(quick_to_interpreter_bridge_, QuickToInterpreterBridge);
+    DO_TRAMPOLINE(nterp_trampoline_, NterpTrampoline);
 
     #undef DO_TRAMPOLINE
   } else {
@@ -2233,6 +2311,7 @@
     oat_header_->SetQuickImtConflictTrampolineOffset(0);
     oat_header_->SetQuickResolutionTrampolineOffset(0);
     oat_header_->SetQuickToInterpreterBridgeOffset(0);
+    oat_header_->SetNterpTrampolineOffset(0);
   }
   return offset;
 }
@@ -2326,6 +2405,8 @@
   DCHECK_EQ(bss_size_, 0u);
   if (bss_method_entries_.empty() &&
       bss_type_entries_.empty() &&
+      bss_public_type_entries_.empty() &&
+      bss_package_type_entries_.empty() &&
       bss_string_entries_.empty()) {
     // Nothing to put to the .bss section.
     return;
@@ -2349,6 +2430,18 @@
     entry.second = bss_size_;
     bss_size_ += sizeof(GcRoot<mirror::Class>);
   }
+  // Prepare offsets for .bss public Class entries.
+  for (auto& entry : bss_public_type_entries_) {
+    DCHECK_EQ(entry.second, 0u);
+    entry.second = bss_size_;
+    bss_size_ += sizeof(GcRoot<mirror::Class>);
+  }
+  // Prepare offsets for .bss package Class entries.
+  for (auto& entry : bss_package_type_entries_) {
+    DCHECK_EQ(entry.second, 0u);
+    entry.second = bss_size_;
+    bss_size_ += sizeof(GcRoot<mirror::Class>);
+  }
   // Prepare offsets for .bss String entries.
   for (auto& entry : bss_string_entries_) {
     DCHECK_EQ(entry.second, 0u);
@@ -2418,260 +2511,34 @@
   return true;
 }
 
-class OatWriter::WriteQuickeningInfoMethodVisitor {
- public:
-  WriteQuickeningInfoMethodVisitor(OatWriter* writer, OutputStream* out)
-      : writer_(writer),
-        out_(out) {}
-
-  bool VisitDexMethods(const std::vector<const DexFile*>& dex_files) {
-    // Map of offsets for quicken info related to method indices.
-    SafeMap<const uint8_t*, uint32_t> offset_map;
-    // Use method index order to minimize the encoded size of the offset table.
-    for (const DexFile* dex_file : dex_files) {
-      std::vector<uint32_t>* const offsets =
-          &quicken_info_offset_indices_.Put(dex_file, std::vector<uint32_t>())->second;
-      for (uint32_t method_idx = 0; method_idx < dex_file->NumMethodIds(); ++method_idx) {
-        uint32_t offset = 0u;
-        MethodReference method_ref(dex_file, method_idx);
-        CompiledMethod* compiled_method = writer_->compiler_driver_->GetCompiledMethod(method_ref);
-        if (compiled_method != nullptr && HasQuickeningInfo(compiled_method)) {
-          ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
-
-          // Record each index if required. written_bytes_ is the offset from the start of the
-          // quicken info data.
-          // May be already inserted for deduplicate items.
-          // Add offset of one to make sure 0 represents unused.
-          auto pair = offset_map.emplace(map.data(), written_bytes_ + 1);
-          offset = pair.first->second;
-          // Write out the map if it's not already written.
-          if (pair.second) {
-            const uint32_t length = map.size() * sizeof(map.front());
-            if (!out_->WriteFully(map.data(), length)) {
-              PLOG(ERROR) << "Failed to write quickening info for " << method_ref.PrettyMethod()
-                          << " to " << out_->GetLocation();
-              return false;
-            }
-            written_bytes_ += length;
-          }
-        }
-        offsets->push_back(offset);
-      }
-    }
-    return true;
-  }
-
-  size_t GetNumberOfWrittenBytes() const {
-    return written_bytes_;
-  }
-
-  SafeMap<const DexFile*, std::vector<uint32_t>>& GetQuickenInfoOffsetIndices() {
-    return quicken_info_offset_indices_;
-  }
-
- private:
-  OatWriter* const writer_;
-  OutputStream* const out_;
-  size_t written_bytes_ = 0u;
-  SafeMap<const DexFile*, std::vector<uint32_t>> quicken_info_offset_indices_;
-};
-
-class OatWriter::WriteQuickeningInfoOffsetsMethodVisitor {
- public:
-  WriteQuickeningInfoOffsetsMethodVisitor(
-      OutputStream* out,
-      uint32_t start_offset,
-      SafeMap<const DexFile*, std::vector<uint32_t>>* quicken_info_offset_indices,
-      std::vector<uint32_t>* out_table_offsets)
-      : out_(out),
-        start_offset_(start_offset),
-        quicken_info_offset_indices_(quicken_info_offset_indices),
-        out_table_offsets_(out_table_offsets) {}
-
-  bool VisitDexMethods(const std::vector<const DexFile*>& dex_files) {
-    for (const DexFile* dex_file : dex_files) {
-      auto it = quicken_info_offset_indices_->find(dex_file);
-      DCHECK(it != quicken_info_offset_indices_->end()) << "Failed to find dex file "
-                                                        << dex_file->GetLocation();
-      const std::vector<uint32_t>* const offsets = &it->second;
-
-      const uint32_t current_offset = start_offset_ + written_bytes_;
-      CHECK_ALIGNED_PARAM(current_offset, CompactOffsetTable::kAlignment);
-
-      // Generate and write the data.
-      std::vector<uint8_t> table_data;
-      CompactOffsetTable::Build(*offsets, &table_data);
-
-      // Store the offset since we need to put those after the dex file. Table offsets are relative
-      // to the start of the quicken info section.
-      out_table_offsets_->push_back(current_offset);
-
-      const uint32_t length = table_data.size() * sizeof(table_data.front());
-      if (!out_->WriteFully(table_data.data(), length)) {
-        PLOG(ERROR) << "Failed to write quickening offset table for " << dex_file->GetLocation()
-                    << " to " << out_->GetLocation();
-        return false;
-      }
-      written_bytes_ += length;
-    }
-    return true;
-  }
-
-  size_t GetNumberOfWrittenBytes() const {
-    return written_bytes_;
-  }
-
- private:
-  OutputStream* const out_;
-  const uint32_t start_offset_;
-  size_t written_bytes_ = 0u;
-  // Maps containing the offsets for the tables.
-  SafeMap<const DexFile*, std::vector<uint32_t>>* const quicken_info_offset_indices_;
-  std::vector<uint32_t>* const out_table_offsets_;
-};
-
-bool OatWriter::WriteQuickeningInfo(OutputStream* vdex_out) {
-  if (!extract_dex_files_into_vdex_) {
-    // Nothing to write. Leave `vdex_size_` untouched and unaligned.
-    vdex_quickening_info_offset_ = vdex_size_;
-    size_quickening_info_alignment_ = 0;
-    return true;
-  }
-  size_t initial_offset = vdex_size_;
-  // Make sure the table is properly aligned.
-  size_t start_offset = RoundUp(initial_offset, 4u);
-
-  off_t actual_offset = vdex_out->Seek(start_offset, kSeekSet);
-  if (actual_offset != static_cast<off_t>(start_offset)) {
-    PLOG(ERROR) << "Failed to seek to quickening info section. Actual: " << actual_offset
-                << " Expected: " << start_offset
-                << " Output: " << vdex_out->GetLocation();
-    return false;
-  }
-
-  size_t current_offset = start_offset;
-  if (GetCompilerOptions().IsQuickeningCompilationEnabled()) {
-    std::vector<uint32_t> dex_files_indices;
-    WriteQuickeningInfoMethodVisitor write_quicken_info_visitor(this, vdex_out);
-    if (!write_quicken_info_visitor.VisitDexMethods(*dex_files_)) {
-      PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation();
-      return false;
-    }
-
-    uint32_t quicken_info_offset = write_quicken_info_visitor.GetNumberOfWrittenBytes();
-    current_offset = current_offset + quicken_info_offset;
-    uint32_t before_offset = current_offset;
-    current_offset = RoundUp(current_offset, CompactOffsetTable::kAlignment);
-    const size_t extra_bytes = current_offset - before_offset;
-    quicken_info_offset += extra_bytes;
-    actual_offset = vdex_out->Seek(current_offset, kSeekSet);
-    if (actual_offset != static_cast<off_t>(current_offset)) {
-      PLOG(ERROR) << "Failed to seek to quickening offset table section. Actual: " << actual_offset
-                  << " Expected: " << current_offset
-                  << " Output: " << vdex_out->GetLocation();
-      return false;
-    }
-
-    std::vector<uint32_t> table_offsets;
-    WriteQuickeningInfoOffsetsMethodVisitor table_visitor(
-        vdex_out,
-        quicken_info_offset,
-        &write_quicken_info_visitor.GetQuickenInfoOffsetIndices(),
-        /*out*/ &table_offsets);
-    if (!table_visitor.VisitDexMethods(*dex_files_)) {
-      PLOG(ERROR) << "Failed to write the vdex quickening info. File: "
-                  << vdex_out->GetLocation();
-      return false;
-    }
-
-    CHECK_EQ(table_offsets.size(), dex_files_->size());
-
-    current_offset += table_visitor.GetNumberOfWrittenBytes();
-
-    // Store the offset table offset as a preheader for each dex.
-    size_t index = 0;
-    for (const OatDexFile& oat_dex_file : oat_dex_files_) {
-      const off_t desired_offset = oat_dex_file.dex_file_offset_ -
-          sizeof(VdexFile::QuickeningTableOffsetType);
-      actual_offset = vdex_out->Seek(desired_offset, kSeekSet);
-      if (actual_offset != desired_offset) {
-        PLOG(ERROR) << "Failed to seek to before dex file for writing offset table offset: "
-                    << actual_offset << " Expected: " << desired_offset
-                    << " Output: " << vdex_out->GetLocation();
-        return false;
-      }
-      uint32_t offset = table_offsets[index];
-      if (!vdex_out->WriteFully(reinterpret_cast<const uint8_t*>(&offset), sizeof(offset))) {
-        PLOG(ERROR) << "Failed to write verifier deps."
-                    << " File: " << vdex_out->GetLocation();
-        return false;
-      }
-      ++index;
-    }
-    if (!vdex_out->Flush()) {
-      PLOG(ERROR) << "Failed to flush stream after writing quickening info."
-                  << " File: " << vdex_out->GetLocation();
-      return false;
-    }
-    size_quickening_info_ = current_offset - start_offset;
-  } else {
-    // We know we did not quicken.
-    size_quickening_info_ = 0;
-  }
-
-  if (size_quickening_info_ == 0) {
-    // Nothing was written. Leave `vdex_size_` untouched and unaligned.
-    vdex_quickening_info_offset_ = initial_offset;
-    size_quickening_info_alignment_ = 0;
-  } else {
-    vdex_size_ = start_offset + size_quickening_info_;
-    vdex_quickening_info_offset_ = start_offset;
-    size_quickening_info_alignment_ = start_offset - initial_offset;
-  }
-
-  return true;
+void OatWriter::WriteQuickeningInfo(/*out*/std::vector<uint8_t>* ATTRIBUTE_UNUSED) {
+  // Nothing to write. Leave `vdex_size_` untouched and unaligned.
+  vdex_quickening_info_offset_ = vdex_size_;
+  size_quickening_info_alignment_ = 0;
 }
 
-bool OatWriter::WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps) {
+void OatWriter::WriteVerifierDeps(verifier::VerifierDeps* verifier_deps,
+                                  /*out*/std::vector<uint8_t>* buffer) {
   if (verifier_deps == nullptr) {
     // Nothing to write. Record the offset, but no need
     // for alignment.
     vdex_verifier_deps_offset_ = vdex_size_;
-    return true;
+    return;
   }
 
-  size_t initial_offset = vdex_size_;
-  size_t start_offset = RoundUp(initial_offset, 4u);
+  TimingLogger::ScopedTiming split("VDEX verifier deps", timings_);
 
-  vdex_size_ = start_offset;
+  DCHECK(buffer->empty());
+  verifier_deps->Encode(*dex_files_, buffer);
+  size_verifier_deps_ = buffer->size();
+
+  // Verifier deps data should be 4 byte aligned.
+  size_verifier_deps_alignment_ = RoundUp(vdex_size_, 4u) - vdex_size_;
+  buffer->insert(buffer->begin(), size_verifier_deps_alignment_, 0u);
+
+  vdex_size_ += size_verifier_deps_alignment_;
   vdex_verifier_deps_offset_ = vdex_size_;
-  size_verifier_deps_alignment_ = start_offset - initial_offset;
-
-  off_t actual_offset = vdex_out->Seek(start_offset, kSeekSet);
-  if (actual_offset != static_cast<off_t>(start_offset)) {
-    PLOG(ERROR) << "Failed to seek to verifier deps section. Actual: " << actual_offset
-                << " Expected: " << start_offset
-                << " Output: " << vdex_out->GetLocation();
-    return false;
-  }
-
-  std::vector<uint8_t> buffer;
-  verifier_deps->Encode(*dex_files_, &buffer);
-
-  if (!vdex_out->WriteFully(buffer.data(), buffer.size())) {
-    PLOG(ERROR) << "Failed to write verifier deps."
-                << " File: " << vdex_out->GetLocation();
-    return false;
-  }
-  if (!vdex_out->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after writing verifier deps."
-                << " File: " << vdex_out->GetLocation();
-    return false;
-  }
-
-  size_verifier_deps_ = buffer.size();
   vdex_size_ += size_verifier_deps_;
-  return true;
 }
 
 bool OatWriter::WriteCode(OutputStream* out) {
@@ -2757,12 +2624,15 @@
     DO_STAT(size_vdex_header_);
     DO_STAT(size_vdex_checksums_);
     DO_STAT(size_dex_file_alignment_);
+    DO_STAT(size_quickening_table_offset_);
     DO_STAT(size_executable_offset_alignment_);
     DO_STAT(size_oat_header_);
     DO_STAT(size_oat_header_key_value_store_);
     DO_STAT(size_dex_file_);
     DO_STAT(size_verifier_deps_);
     DO_STAT(size_verifier_deps_alignment_);
+    DO_STAT(size_vdex_lookup_table_);
+    DO_STAT(size_vdex_lookup_table_alignment_);
     DO_STAT(size_quickening_info_);
     DO_STAT(size_quickening_info_alignment_);
     DO_STAT(size_interpreter_to_interpreter_bridge_);
@@ -2773,6 +2643,7 @@
     DO_STAT(size_quick_imt_conflict_trampoline_);
     DO_STAT(size_quick_resolution_trampoline_);
     DO_STAT(size_quick_to_interpreter_bridge_);
+    DO_STAT(size_nterp_trampoline_);
     DO_STAT(size_trampoline_alignment_);
     DO_STAT(size_method_header_);
     DO_STAT(size_code_);
@@ -2794,17 +2665,20 @@
     DO_STAT(size_oat_dex_file_dex_layout_sections_alignment_);
     DO_STAT(size_oat_dex_file_method_bss_mapping_offset_);
     DO_STAT(size_oat_dex_file_type_bss_mapping_offset_);
+    DO_STAT(size_oat_dex_file_public_type_bss_mapping_offset_);
+    DO_STAT(size_oat_dex_file_package_type_bss_mapping_offset_);
     DO_STAT(size_oat_dex_file_string_bss_mapping_offset_);
-    DO_STAT(size_oat_lookup_table_alignment_);
-    DO_STAT(size_oat_lookup_table_);
     DO_STAT(size_oat_class_offsets_alignment_);
     DO_STAT(size_oat_class_offsets_);
     DO_STAT(size_oat_class_type_);
     DO_STAT(size_oat_class_status_);
+    DO_STAT(size_oat_class_num_methods_);
     DO_STAT(size_oat_class_method_bitmaps_);
     DO_STAT(size_oat_class_method_offsets_);
     DO_STAT(size_method_bss_mappings_);
     DO_STAT(size_type_bss_mappings_);
+    DO_STAT(size_public_type_bss_mappings_);
+    DO_STAT(size_package_type_bss_mappings_);
     DO_STAT(size_string_bss_mappings_);
     #undef DO_STAT
 
@@ -2970,12 +2844,27 @@
   return mappings_size;
 }
 
+size_t WriteIndexBssMapping(
+    OutputStream* out,
+    const DexFile* dex_file,
+    const BitVector& type_indexes,
+    const SafeMap<TypeReference, size_t, TypeReferenceValueComparator>& bss_entries) {
+  return WriteIndexBssMapping(
+      out,
+      dex_file->NumTypeIds(),
+      sizeof(GcRoot<mirror::Class>),
+      type_indexes,
+      [=](uint32_t index) { return bss_entries.Get({dex_file, dex::TypeIndex(index)}); });
+}
+
 size_t OatWriter::WriteIndexBssMappings(OutputStream* out,
                                         size_t file_offset,
                                         size_t relative_offset) {
   TimingLogger::ScopedTiming split("WriteMethodBssMappings", timings_);
   if (bss_method_entry_references_.empty() &&
       bss_type_entry_references_.empty() &&
+      bss_public_type_entry_references_.empty() &&
+      bss_package_type_entry_references_.empty() &&
       bss_string_entry_references_.empty()) {
     return relative_offset;
   }
@@ -3016,14 +2905,8 @@
       const BitVector& type_indexes = type_it->second;
       DCHECK_EQ(relative_offset, oat_dex_file->type_bss_mapping_offset_);
       DCHECK_OFFSET();
-      size_t type_mappings_size = WriteIndexBssMapping(
-          out,
-          dex_file->NumTypeIds(),
-          sizeof(GcRoot<mirror::Class>),
-          type_indexes,
-          [=](uint32_t index) {
-            return bss_type_entries_.Get({dex_file, dex::TypeIndex(index)});
-          });
+      size_t type_mappings_size =
+          WriteIndexBssMapping(out, dex_file, type_indexes, bss_type_entries_);
       if (type_mappings_size == 0u) {
         return 0u;
       }
@@ -3033,6 +2916,38 @@
       DCHECK_EQ(0u, oat_dex_file->type_bss_mapping_offset_);
     }
 
+    auto public_type_it = bss_public_type_entry_references_.find(dex_file);
+    if (public_type_it != bss_public_type_entry_references_.end()) {
+      const BitVector& type_indexes = public_type_it->second;
+      DCHECK_EQ(relative_offset, oat_dex_file->public_type_bss_mapping_offset_);
+      DCHECK_OFFSET();
+      size_t public_type_mappings_size =
+          WriteIndexBssMapping(out, dex_file, type_indexes, bss_public_type_entries_);
+      if (public_type_mappings_size == 0u) {
+        return 0u;
+      }
+      size_public_type_bss_mappings_ += public_type_mappings_size;
+      relative_offset += public_type_mappings_size;
+    } else {
+      DCHECK_EQ(0u, oat_dex_file->public_type_bss_mapping_offset_);
+    }
+
+    auto package_type_it = bss_package_type_entry_references_.find(dex_file);
+    if (package_type_it != bss_package_type_entry_references_.end()) {
+      const BitVector& type_indexes = package_type_it->second;
+      DCHECK_EQ(relative_offset, oat_dex_file->package_type_bss_mapping_offset_);
+      DCHECK_OFFSET();
+      size_t package_type_mappings_size =
+          WriteIndexBssMapping(out, dex_file, type_indexes, bss_package_type_entries_);
+      if (package_type_mappings_size == 0u) {
+        return 0u;
+      }
+      size_package_type_bss_mappings_ += package_type_mappings_size;
+      relative_offset += package_type_mappings_size;
+    } else {
+      DCHECK_EQ(0u, oat_dex_file->package_type_bss_mapping_offset_);
+    }
+
     auto string_it = bss_string_entry_references_.find(dex_file);
     if (string_it != bss_string_entry_references_.end()) {
       const BitVector& string_indexes = string_it->second;
@@ -3105,6 +3020,7 @@
     DO_TRAMPOLINE(quick_imt_conflict_trampoline_);
     DO_TRAMPOLINE(quick_resolution_trampoline_);
     DO_TRAMPOLINE(quick_to_interpreter_bridge_);
+    DO_TRAMPOLINE(nterp_trampoline_);
     #undef DO_TRAMPOLINE
   }
   return relative_offset;
@@ -3182,10 +3098,10 @@
   return true;
 }
 
-bool OatWriter::WriteDexFiles(OutputStream* out,
-                              File* file,
+bool OatWriter::WriteDexFiles(File* file,
                               bool update_input_vdex,
-                              CopyOption copy_dex_files) {
+                              CopyOption copy_dex_files,
+                              /*out*/ std::vector<MemMap>* opened_dex_files_map) {
   TimingLogger::ScopedTiming split("Write Dex files", timings_);
 
   // If extraction is enabled, only do it if not all the dex files are aligned and uncompressed.
@@ -3210,116 +3126,155 @@
   }
 
   if (extract_dex_files_into_vdex_) {
-    // Add the dex section header.
-    vdex_size_ += sizeof(VdexFile::DexSectionHeader);
     vdex_dex_files_offset_ = vdex_size_;
-    // Write dex files.
-    for (OatDexFile& oat_dex_file : oat_dex_files_) {
-      if (!WriteDexFile(out, file, &oat_dex_file, update_input_vdex)) {
-        return false;
+
+    // Perform dexlayout if requested.
+    if (profile_compilation_info_ != nullptr ||
+        compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone) {
+      for (OatDexFile& oat_dex_file : oat_dex_files_) {
+        // update_input_vdex disables compact dex and layout.
+        CHECK(!update_input_vdex)
+            << "We should never update the input vdex when doing dexlayout or compact dex";
+        if (!LayoutDexFile(&oat_dex_file)) {
+          return false;
+        }
       }
     }
 
-    // Write shared dex file data section and fix up the dex file headers.
-    vdex_dex_shared_data_offset_ = vdex_size_;
-    uint32_t shared_data_size = 0u;
-
-    if (dex_container_ != nullptr) {
-      CHECK(!update_input_vdex) << "Update input vdex should have empty dex container";
-      DexContainer::Section* const section = dex_container_->GetDataSection();
-      if (section->Size() > 0) {
-        CHECK(compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone);
-        const off_t existing_offset = out->Seek(0, kSeekCurrent);
-        if (static_cast<uint32_t>(existing_offset) != vdex_dex_shared_data_offset_) {
-          PLOG(ERROR) << "Expected offset " << vdex_dex_shared_data_offset_ << " but got "
-                      << existing_offset;
-          return false;
-        }
-        shared_data_size = section->Size();
-        if (!out->WriteFully(section->Begin(), shared_data_size)) {
-          PLOG(ERROR) << "Failed to write shared data!";
-          return false;
-        }
-        if (!out->Flush()) {
-          PLOG(ERROR) << "Failed to flush after writing shared dex section.";
-          return false;
-        }
-        // Fix up the dex headers to have correct offsets to the data section.
-        for (OatDexFile& oat_dex_file : oat_dex_files_) {
-          // Overwrite the header by reading it, updating the offset, and writing it back out.
-          DexFile::Header header;
-          if (!file->PreadFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
-            PLOG(ERROR) << "Failed to read dex header for updating";
-            return false;
-          }
-          if (!CompactDexFile::IsMagicValid(header.magic_)) {
-            // Non-compact dex file, probably failed to convert due to duplicate methods.
-            continue;
-          }
-          CHECK_GT(vdex_dex_shared_data_offset_, oat_dex_file.dex_file_offset_);
-          // Offset is from the dex file base.
-          header.data_off_ = vdex_dex_shared_data_offset_ - oat_dex_file.dex_file_offset_;
-          // The size should already be what part of the data buffer may be used by the dex.
-          CHECK_LE(header.data_size_, shared_data_size);
-          if (!file->PwriteFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
-            PLOG(ERROR) << "Failed to write dex header for updating";
-            return false;
-          }
-        }
-        section->Clear();
+    // Calculate the total size after the dex files.
+    size_t vdex_size_with_dex_files = vdex_size_;
+    for (OatDexFile& oat_dex_file : oat_dex_files_) {
+      // Dex files are required to be 4 byte aligned.
+      vdex_size_with_dex_files = RoundUp(vdex_size_with_dex_files, 4u);
+      // Record offset for the dex file.
+      oat_dex_file.dex_file_offset_ = vdex_size_with_dex_files;
+      // Add the size of the dex file.
+      if (oat_dex_file.dex_file_size_ < sizeof(DexFile::Header)) {
+        LOG(ERROR) << "Dex file " << oat_dex_file.GetLocation() << " is too short: "
+            << oat_dex_file.dex_file_size_ << " < " << sizeof(DexFile::Header);
+        return false;
       }
-      dex_container_.reset();
+      vdex_size_with_dex_files += oat_dex_file.dex_file_size_;
+    }
+    // Add the shared data section size.
+    const uint8_t* raw_dex_file_shared_data_begin = nullptr;
+    uint32_t shared_data_size = 0u;
+    if (dex_container_ != nullptr) {
+      shared_data_size = dex_container_->GetDataSection()->Size();
     } else {
-      const uint8_t* data_begin = nullptr;
-      for (OatDexFile& oat_dex_file : oat_dex_files_) {
-        DexFile::Header header;
-        if (!file->PreadFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
-          PLOG(ERROR) << "Failed to read dex header";
-          return false;
+      // Dex files from input vdex are represented as raw dex files and they can be
+      // compact dex files. These need to specify the same shared data section if any.
+      for (const OatDexFile& oat_dex_file : oat_dex_files_) {
+        if (!oat_dex_file.source_.IsRawData()) {
+          continue;
         }
-        if (!CompactDexFile::IsMagicValid(header.magic_)) {
+        const uint8_t* raw_data = oat_dex_file.source_.GetRawData();
+        const UnalignedDexFileHeader& header = *AsUnalignedDexFileHeader(raw_data);
+        if (!CompactDexFile::IsMagicValid(header.magic_) || header.data_size_ == 0u) {
           // Non compact dex does not have shared data section.
           continue;
         }
-        const uint32_t expected_data_off = vdex_dex_shared_data_offset_ -
-            oat_dex_file.dex_file_offset_;
-        if (header.data_off_ != expected_data_off) {
-          PLOG(ERROR) << "Shared data section offset " << header.data_off_
-                      << " does not match expected value " << expected_data_off;
+        const uint8_t* cur_data_begin = raw_data + header.data_off_;
+        if (raw_dex_file_shared_data_begin == nullptr) {
+          raw_dex_file_shared_data_begin = cur_data_begin;
+        } else if (raw_dex_file_shared_data_begin != cur_data_begin) {
+          LOG(ERROR) << "Mismatched shared data sections in raw dex files: "
+                     << static_cast<const void*>(raw_dex_file_shared_data_begin)
+                     << " != " << static_cast<const void*>(cur_data_begin);
           return false;
         }
-        if (oat_dex_file.source_.IsRawData()) {
-          // Figure out the start of the shared data section so we can copy it below.
-          const uint8_t* cur_data_begin = oat_dex_file.source_.GetRawData() + header.data_off_;
-          if (data_begin != nullptr) {
-            CHECK_EQ(data_begin, cur_data_begin);
-          }
-          data_begin = cur_data_begin;
-        }
         // The different dex files currently can have different data sizes since
         // the dex writer writes them one at a time into the shared section.:w
         shared_data_size = std::max(shared_data_size, header.data_size_);
       }
-      // If we are not updating the input vdex, write out the shared data section.
+    }
+    if (shared_data_size != 0u) {
+      // Shared data section is required to be 4 byte aligned.
+      vdex_size_with_dex_files = RoundUp(vdex_size_with_dex_files, 4u);
+    }
+    vdex_dex_shared_data_offset_ = vdex_size_with_dex_files;
+    vdex_size_with_dex_files += shared_data_size;
+
+    // Extend the file and include the full page at the end as we need to write
+    // additional data there and do not want to mmap that page twice.
+    size_t page_aligned_size = RoundUp(vdex_size_with_dex_files, kPageSize);
+    if (!update_input_vdex) {
+      if (file->SetLength(page_aligned_size) != 0) {
+        PLOG(ERROR) << "Failed to resize vdex file " << file->GetPath();
+        return false;
+      }
+    }
+
+    std::string error_msg;
+    MemMap dex_files_map = MemMap::MapFile(
+        page_aligned_size,
+        PROT_READ | PROT_WRITE,
+        MAP_SHARED,
+        file->Fd(),
+        /*start=*/ 0u,
+        /*low_4gb=*/ false,
+        file->GetPath().c_str(),
+        &error_msg);
+    if (!dex_files_map.IsValid()) {
+      LOG(ERROR) << "Failed to mmap() dex files from oat file. File: " << file->GetPath()
+                 << " error: " << error_msg;
+      return false;
+    }
+    vdex_begin_ = dex_files_map.Begin();
+
+    // Write dex files.
+    for (OatDexFile& oat_dex_file : oat_dex_files_) {
+      // Dex files are required to be 4 byte aligned.
+      size_t old_vdex_size = vdex_size_;
+      vdex_size_ = RoundUp(vdex_size_, 4u);
+      size_dex_file_alignment_ += vdex_size_ - old_vdex_size;
+      // Write the actual dex file.
+      if (!WriteDexFile(file, &oat_dex_file, update_input_vdex)) {
+        return false;
+      }
+    }
+
+    // Write shared dex file data section and fix up the dex file headers.
+    if (shared_data_size != 0u) {
+      DCHECK_EQ(RoundUp(vdex_size_, 4u), vdex_dex_shared_data_offset_);
       if (!update_input_vdex) {
-        const off_t existing_offset = out->Seek(0, kSeekCurrent);
-        if (static_cast<uint32_t>(existing_offset) != vdex_dex_shared_data_offset_) {
-          PLOG(ERROR) << "Expected offset " << vdex_dex_shared_data_offset_ << " but got "
-                      << existing_offset;
-          return false;
-        }
-        if (!out->WriteFully(data_begin, shared_data_size)) {
-          PLOG(ERROR) << "Failed to write shared data!";
-          return false;
-        }
-        if (!out->Flush()) {
-          PLOG(ERROR) << "Failed to flush after writing shared dex section.";
-          return false;
+        memset(vdex_begin_ + vdex_size_, 0, vdex_dex_shared_data_offset_ - vdex_size_);
+      }
+      size_dex_file_alignment_ += vdex_dex_shared_data_offset_ - vdex_size_;
+      vdex_size_ = vdex_dex_shared_data_offset_;
+
+      if (dex_container_ != nullptr) {
+        CHECK(!update_input_vdex) << "Update input vdex should have empty dex container";
+        CHECK(compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone);
+        DexContainer::Section* const section = dex_container_->GetDataSection();
+        DCHECK_EQ(shared_data_size, section->Size());
+        memcpy(vdex_begin_ + vdex_size_, section->Begin(), shared_data_size);
+        section->Clear();
+        dex_container_.reset();
+      } else if (!update_input_vdex) {
+        // If we are not updating the input vdex, write out the shared data section.
+        memcpy(vdex_begin_ + vdex_size_, raw_dex_file_shared_data_begin, shared_data_size);
+      }
+      vdex_size_ += shared_data_size;
+      size_dex_file_ += shared_data_size;
+      if (!update_input_vdex) {
+        // Fix up the dex headers to have correct offsets to the data section.
+        for (OatDexFile& oat_dex_file : oat_dex_files_) {
+          DexFile::Header* header =
+              reinterpret_cast<DexFile::Header*>(vdex_begin_ + oat_dex_file.dex_file_offset_);
+          if (!CompactDexFile::IsMagicValid(header->magic_)) {
+            // Non-compact dex file, probably failed to convert due to duplicate methods.
+            continue;
+          }
+          CHECK_GT(vdex_dex_shared_data_offset_, oat_dex_file.dex_file_offset_);
+          // Offset is from the dex file base.
+          header->data_off_ = vdex_dex_shared_data_offset_ - oat_dex_file.dex_file_offset_;
+          // The size should already be what part of the data buffer may be used by the dex.
+          CHECK_LE(header->data_size_, shared_data_size);
         }
       }
     }
-    vdex_size_ += shared_data_size;
-    size_dex_file_ += shared_data_size;
+    opened_dex_files_map->push_back(std::move(dex_files_map));
   } else {
     vdex_dex_shared_data_offset_ = vdex_size_;
   }
@@ -3336,86 +3291,35 @@
   raw_dex_files_.clear();
 }
 
-bool OatWriter::WriteDexFile(OutputStream* out,
-                             File* file,
+bool OatWriter::WriteDexFile(File* file,
                              OatDexFile* oat_dex_file,
                              bool update_input_vdex) {
-  if (!SeekToDexFile(out, file, oat_dex_file)) {
-    return false;
-  }
-  // update_input_vdex disables compact dex and layout.
-  if (profile_compilation_info_ != nullptr ||
-      compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone) {
-    CHECK(!update_input_vdex)
-        << "We should never update the input vdex when doing dexlayout or compact dex";
-    if (!LayoutAndWriteDexFile(out, oat_dex_file)) {
-      return false;
-    }
-  } else if (oat_dex_file->source_.IsZipEntry()) {
+  DCHECK_EQ(vdex_size_, oat_dex_file->dex_file_offset_);
+  if (oat_dex_file->source_.IsZipEntry()) {
     DCHECK(!update_input_vdex);
-    if (!WriteDexFile(out, file, oat_dex_file, oat_dex_file->source_.GetZipEntry())) {
+    if (!WriteDexFile(file, oat_dex_file, oat_dex_file->source_.GetZipEntry())) {
       return false;
     }
   } else if (oat_dex_file->source_.IsRawFile()) {
     DCHECK(!update_input_vdex);
-    if (!WriteDexFile(out, file, oat_dex_file, oat_dex_file->source_.GetRawFile())) {
+    if (!WriteDexFile(file, oat_dex_file, oat_dex_file->source_.GetRawFile())) {
       return false;
     }
   } else {
     DCHECK(oat_dex_file->source_.IsRawData());
-    if (!WriteDexFile(out, oat_dex_file, oat_dex_file->source_.GetRawData(), update_input_vdex)) {
+    const uint8_t* raw_data = oat_dex_file->source_.GetRawData();
+    if (!WriteDexFile(oat_dex_file, raw_data, update_input_vdex)) {
       return false;
     }
   }
 
   // Update current size and account for the written data.
-  DCHECK_EQ(vdex_size_, oat_dex_file->dex_file_offset_);
   vdex_size_ += oat_dex_file->dex_file_size_;
   size_dex_file_ += oat_dex_file->dex_file_size_;
   return true;
 }
 
-bool OatWriter::SeekToDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file) {
-  // Dex files are required to be 4 byte aligned.
-  size_t initial_offset = vdex_size_;
-  size_t start_offset = RoundUp(initial_offset, 4);
-  size_dex_file_alignment_ += start_offset - initial_offset;
-
-  // Leave extra room for the quicken offset table offset.
-  start_offset += sizeof(VdexFile::QuickeningTableOffsetType);
-  // TODO: Not count the offset as part of alignment.
-  size_dex_file_alignment_ += sizeof(VdexFile::QuickeningTableOffsetType);
-
-  size_t file_offset = start_offset;
-
-  // Seek to the start of the dex file and flush any pending operations in the stream.
-  // Verify that, after flushing the stream, the file is at the same offset as the stream.
-  off_t actual_offset = out->Seek(file_offset, kSeekSet);
-  if (actual_offset != static_cast<off_t>(file_offset)) {
-    PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset
-                << " Expected: " << file_offset
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (!out->Flush()) {
-    PLOG(ERROR) << "Failed to flush before writing dex file."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  actual_offset = lseek(file->Fd(), 0, SEEK_CUR);
-  if (actual_offset != static_cast<off_t>(file_offset)) {
-    PLOG(ERROR) << "Stream/file position mismatch! Actual: " << actual_offset
-                << " Expected: " << file_offset
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-
-  vdex_size_ = start_offset;
-  oat_dex_file->dex_file_offset_ = start_offset;
-  return true;
-}
-
-bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_file) {
+bool OatWriter::LayoutDexFile(OatDexFile* oat_dex_file) {
   TimingLogger::ScopedTiming split("Dex Layout", timings_);
   std::string error_msg;
   std::string location(oat_dex_file->GetLocation());
@@ -3436,8 +3340,8 @@
     dex_file = dex_file_loader.Open(location,
                                     zip_entry->GetCrc32(),
                                     std::move(mem_map),
-                                    /* verify */ true,
-                                    /* verify_checksum */ true,
+                                    /*verify=*/ true,
+                                    /*verify_checksum=*/ true,
                                     &error_msg);
   } else if (oat_dex_file->source_.IsRawFile()) {
     File* raw_file = oat_dex_file->source_.GetRawFile();
@@ -3448,9 +3352,9 @@
     }
     TimingLogger::ScopedTiming extract("Open", timings_);
     dex_file = dex_file_loader.OpenDex(dup_fd, location,
-                                       /* verify */ true,
-                                       /* verify_checksum */ true,
-                                       /* mmap_shared */ false,
+                                       /*verify=*/ true,
+                                       /*verify_checksum=*/ true,
+                                       /*mmap_shared=*/ false,
                                        &error_msg);
   } else {
     // The source data is a vdex file.
@@ -3468,8 +3372,8 @@
                                     location,
                                     oat_dex_file->dex_file_location_checksum_,
                                     nullptr,
-                                    /* verify */ false,
-                                    /* verify_checksum */ false,
+                                    /*verify=*/ false,
+                                    /*verify_checksum=*/ false,
                                     &error_msg);
   }
   if (dex_file == nullptr) {
@@ -3480,7 +3384,6 @@
   options.compact_dex_level_ = compact_dex_level_;
   options.update_checksum_ = true;
   DexLayout dex_layout(options, profile_compilation_info_, /*file*/ nullptr, /*header*/ nullptr);
-  const uint8_t* dex_src = nullptr;
   {
     TimingLogger::ScopedTiming extract("ProcessDexFile", timings_);
     if (dex_layout.ProcessDexFile(location.c_str(),
@@ -3489,163 +3392,48 @@
                                   &dex_container_,
                                   &error_msg)) {
       oat_dex_file->dex_sections_layout_ = dex_layout.GetSections();
+      oat_dex_file->source_.SetDexLayoutData(dex_container_->GetMainSection()->ReleaseData());
       // Dex layout can affect the size of the dex file, so we update here what we have set
       // when adding the dex file as a source.
       const UnalignedDexFileHeader* header =
-          AsUnalignedDexFileHeader(dex_container_->GetMainSection()->Begin());
+          AsUnalignedDexFileHeader(oat_dex_file->source_.GetRawData());
       oat_dex_file->dex_file_size_ = header->file_size_;
-      dex_src = dex_container_->GetMainSection()->Begin();
     } else {
       LOG(WARNING) << "Failed to run dex layout, reason:" << error_msg;
       // Since we failed to convert the dex, just copy the input dex.
-      dex_src = dex_file->Begin();
+      if (dex_container_ != nullptr) {
+        // Clear the main section before processing next dex file in case we have written some data.
+        dex_container_->GetMainSection()->Clear();
+      }
     }
   }
-  {
-    TimingLogger::ScopedTiming extract("WriteDexFile", timings_);
-    if (!WriteDexFile(out, oat_dex_file, dex_src, /* update_input_vdex */ false)) {
-      return false;
-    }
-  }
-  if (dex_container_ != nullptr) {
-    // Clear the main section in case we write more data into the container.
-    dex_container_->GetMainSection()->Clear();
-  }
   CHECK_EQ(oat_dex_file->dex_file_location_checksum_, dex_file->GetLocationChecksum());
   return true;
 }
 
-bool OatWriter::WriteDexFile(OutputStream* out,
-                             File* file,
+bool OatWriter::WriteDexFile(File* file,
                              OatDexFile* oat_dex_file,
                              ZipEntry* dex_file) {
-  size_t start_offset = vdex_size_;
-  DCHECK_EQ(static_cast<off_t>(start_offset), out->Seek(0, kSeekCurrent));
+  uint8_t* raw_output = vdex_begin_ + oat_dex_file->dex_file_offset_;
 
-  // Extract the dex file and get the extracted size.
+  // Extract the dex file.
   std::string error_msg;
-  if (!dex_file->ExtractToFile(*file, &error_msg)) {
+  if (!dex_file->ExtractToMemory(raw_output, &error_msg)) {
     LOG(ERROR) << "Failed to extract dex file from ZIP entry: " << error_msg
                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
     return false;
   }
-  if (file->Flush() != 0) {
-    PLOG(ERROR) << "Failed to flush dex file from ZIP entry."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  off_t extracted_end = lseek(file->Fd(), 0, SEEK_CUR);
-  if (extracted_end == static_cast<off_t>(-1)) {
-    PLOG(ERROR) << "Failed get end offset after writing dex file from ZIP entry."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (extracted_end < static_cast<off_t>(start_offset)) {
-    LOG(ERROR) << "Dex file end position is before start position! End: " << extracted_end
-               << " Start: " << start_offset
-               << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  uint64_t extracted_size = static_cast<uint64_t>(extracted_end - start_offset);
-  if (extracted_size < sizeof(DexFile::Header)) {
-    LOG(ERROR) << "Extracted dex file is shorter than dex file header. size: "
-               << extracted_size << " File: " << oat_dex_file->GetLocation();
-    return false;
-  }
-
-  // Read the dex file header and extract required data to OatDexFile.
-  off_t actual_offset = lseek(file->Fd(), start_offset, SEEK_SET);
-  if (actual_offset != static_cast<off_t>(start_offset)) {
-    PLOG(ERROR) << "Failed to seek back to dex file header. Actual: " << actual_offset
-                << " Expected: " << start_offset
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (extracted_size < oat_dex_file->dex_file_size_) {
-    LOG(ERROR) << "Extracted truncated dex file. Extracted size: " << extracted_size
-               << " file size from header: " << oat_dex_file->dex_file_size_
-               << " File: " << oat_dex_file->GetLocation();
-    return false;
-  }
-
-  // Seek both file and stream to the end offset.
-  size_t end_offset = start_offset + oat_dex_file->dex_file_size_;
-  actual_offset = lseek(file->Fd(), end_offset, SEEK_SET);
-  if (actual_offset != static_cast<off_t>(end_offset)) {
-    PLOG(ERROR) << "Failed to seek to end of dex file. Actual: " << actual_offset
-                << " Expected: " << end_offset
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  actual_offset = out->Seek(end_offset, kSeekSet);
-  if (actual_offset != static_cast<off_t>(end_offset)) {
-    PLOG(ERROR) << "Failed to seek stream to end of dex file. Actual: " << actual_offset
-                << " Expected: " << end_offset << " File: " << oat_dex_file->GetLocation();
-    return false;
-  }
-  if (!out->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after seeking over dex file."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-
-  // If we extracted more than the size specified in the header, truncate the file.
-  if (extracted_size > oat_dex_file->dex_file_size_) {
-    if (file->SetLength(end_offset) != 0) {
-      PLOG(ERROR) << "Failed to truncate excessive dex file length."
-                  << " File: " << oat_dex_file->GetLocation()
-                  << " Output: " << file->GetPath();
-      return false;
-    }
-  }
 
   return true;
 }
 
-bool OatWriter::WriteDexFile(OutputStream* out,
-                             File* file,
+bool OatWriter::WriteDexFile(File* file,
                              OatDexFile* oat_dex_file,
                              File* dex_file) {
-  size_t start_offset = vdex_size_;
-  DCHECK_EQ(static_cast<off_t>(start_offset), out->Seek(0, kSeekCurrent));
+  uint8_t* raw_output = vdex_begin_ + oat_dex_file->dex_file_offset_;
 
-  off_t input_offset = lseek(dex_file->Fd(), 0, SEEK_SET);
-  if (input_offset != static_cast<off_t>(0)) {
-    PLOG(ERROR) << "Failed to seek to dex file header. Actual: " << input_offset
-                << " Expected: 0"
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-
-  // Copy the input dex file using sendfile().
-  if (!file->Copy(dex_file, 0, oat_dex_file->dex_file_size_)) {
-    PLOG(ERROR) << "Failed to copy dex file to oat file."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  if (file->Flush() != 0) {
-    PLOG(ERROR) << "Failed to flush dex file."
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-
-  // Check file position and seek the stream to the end offset.
-  size_t end_offset = start_offset + oat_dex_file->dex_file_size_;
-  off_t actual_offset = lseek(file->Fd(), 0, SEEK_CUR);
-  if (actual_offset != static_cast<off_t>(end_offset)) {
-    PLOG(ERROR) << "Unexpected file position after copying dex file. Actual: " << actual_offset
-                << " Expected: " << end_offset
-                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
-    return false;
-  }
-  actual_offset = out->Seek(end_offset, kSeekSet);
-  if (actual_offset != static_cast<off_t>(end_offset)) {
-    PLOG(ERROR) << "Failed to seek stream to end of dex file. Actual: " << actual_offset
-                << " Expected: " << end_offset << " File: " << oat_dex_file->GetLocation();
-    return false;
-  }
-  if (!out->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after seeking over dex file."
+  if (!dex_file->PreadFully(raw_output, oat_dex_file->dex_file_size_, /*offset=*/ 0u)) {
+    PLOG(ERROR) << "Failed to copy dex file to vdex file."
                 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
     return false;
   }
@@ -3653,29 +3441,20 @@
   return true;
 }
 
-bool OatWriter::WriteDexFile(OutputStream* out,
-                             OatDexFile* oat_dex_file,
+bool OatWriter::WriteDexFile(OatDexFile* oat_dex_file,
                              const uint8_t* dex_file,
                              bool update_input_vdex) {
   // Note: The raw data has already been checked to contain the header
   // and all the data that the header specifies as the file size.
   DCHECK(dex_file != nullptr);
   DCHECK(ValidateDexFileHeader(dex_file, oat_dex_file->GetLocation()));
-  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(dex_file);
+  DCHECK_EQ(oat_dex_file->dex_file_size_, AsUnalignedDexFileHeader(dex_file)->file_size_);
 
   if (update_input_vdex) {
     // The vdex already contains the dex code, no need to write it again.
   } else {
-    if (!out->WriteFully(dex_file, header->file_size_)) {
-      PLOG(ERROR) << "Failed to write dex file " << oat_dex_file->GetLocation()
-                  << " to " << out->GetLocation();
-      return false;
-    }
-    if (!out->Flush()) {
-      PLOG(ERROR) << "Failed to flush stream after writing dex file."
-                  << " File: " << oat_dex_file->GetLocation();
-      return false;
-    }
+    uint8_t* raw_output = vdex_begin_ + oat_dex_file->dex_file_offset_;
+    memcpy(raw_output, dex_file, oat_dex_file->dex_file_size_);
   }
   return true;
 }
@@ -3683,7 +3462,7 @@
 bool OatWriter::OpenDexFiles(
     File* file,
     bool verify,
-    /*out*/ std::vector<MemMap>* opened_dex_files_map,
+    /*inout*/ std::vector<MemMap>* opened_dex_files_map,
     /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
   TimingLogger::ScopedTiming split("OpenDexFiles", timings_);
 
@@ -3693,6 +3472,7 @@
   }
 
   if (!extract_dex_files_into_vdex_) {
+    DCHECK_EQ(opened_dex_files_map->size(), 0u);
     std::vector<std::unique_ptr<const DexFile>> dex_files;
     std::vector<MemMap> maps;
     for (OatDexFile& oat_dex_file : oat_dex_files_) {
@@ -3730,37 +3510,20 @@
   // make it consistent with the case we're not writing the dex files, we close them now.
   CloseSources();
 
-  size_t map_offset = oat_dex_files_[0].dex_file_offset_;
-  size_t length = vdex_size_ - map_offset;
-
-  std::string error_msg;
-  MemMap dex_files_map = MemMap::MapFile(
-      length,
-      PROT_READ | PROT_WRITE,
-      MAP_SHARED,
-      file->Fd(),
-      map_offset,
-      /* low_4gb */ false,
-      file->GetPath().c_str(),
-      &error_msg);
-  if (!dex_files_map.IsValid()) {
-    LOG(ERROR) << "Failed to mmap() dex files from oat file. File: " << file->GetPath()
-               << " error: " << error_msg;
-    return false;
-  }
+  DCHECK_EQ(opened_dex_files_map->size(), 1u);
+  DCHECK(vdex_begin_ == opened_dex_files_map->front().Begin());
   const ArtDexFileLoader dex_file_loader;
   std::vector<std::unique_ptr<const DexFile>> dex_files;
   for (OatDexFile& oat_dex_file : oat_dex_files_) {
-    const uint8_t* raw_dex_file =
-        dex_files_map.Begin() + oat_dex_file.dex_file_offset_ - map_offset;
+    const uint8_t* raw_dex_file = vdex_begin_ + oat_dex_file.dex_file_offset_;
 
     if (kIsDebugBuild) {
-      // Sanity check our input files.
+      // Check the validity of the input files.
       // Note that ValidateDexFileHeader() logs error messages.
       CHECK(ValidateDexFileHeader(raw_dex_file, oat_dex_file.GetLocation()))
           << "Failed to verify written dex file header!"
-          << " Output: " << file->GetPath() << " ~ " << std::hex << map_offset
-          << " ~ " << static_cast<const void*>(raw_dex_file);
+          << " Output: " << file->GetPath()
+          << " ~ " << std::hex << static_cast<const void*>(raw_dex_file);
 
       const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file);
       CHECK_EQ(header->file_size_, oat_dex_file.dex_file_size_)
@@ -3770,6 +3533,7 @@
     }
 
     // Now, open the dex file.
+    std::string error_msg;
     dex_files.emplace_back(dex_file_loader.Open(raw_dex_file,
                                                 oat_dex_file.dex_file_size_,
                                                 oat_dex_file.GetLocation(),
@@ -3789,92 +3553,33 @@
     oat_dex_file.class_offsets_.resize(dex_files.back()->GetHeader().class_defs_size_);
   }
 
-  opened_dex_files_map->push_back(std::move(dex_files_map));
   *opened_dex_files = std::move(dex_files);
   return true;
 }
 
-bool OatWriter::WriteTypeLookupTables(OutputStream* oat_rodata,
-                                      const std::vector<const DexFile*>& opened_dex_files) {
-  TimingLogger::ScopedTiming split("WriteTypeLookupTables", timings_);
-
-  uint32_t expected_offset = oat_data_offset_ + oat_size_;
-  off_t actual_offset = oat_rodata->Seek(expected_offset, kSeekSet);
-  if (static_cast<uint32_t>(actual_offset) != expected_offset) {
-    PLOG(ERROR) << "Failed to seek to TypeLookupTable section. Actual: " << actual_offset
-                << " Expected: " << expected_offset << " File: " << oat_rodata->GetLocation();
-    return false;
-  }
-
+void OatWriter::InitializeTypeLookupTables(
+    const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files) {
+  TimingLogger::ScopedTiming split("InitializeTypeLookupTables", timings_);
   DCHECK_EQ(opened_dex_files.size(), oat_dex_files_.size());
   for (size_t i = 0, size = opened_dex_files.size(); i != size; ++i) {
     OatDexFile* oat_dex_file = &oat_dex_files_[i];
     DCHECK_EQ(oat_dex_file->lookup_table_offset_, 0u);
 
-    if (oat_dex_file->create_type_lookup_table_ != CreateTypeLookupTable::kCreate ||
-        oat_dex_file->class_offsets_.empty()) {
-      continue;
-    }
-
     size_t table_size = TypeLookupTable::RawDataLength(oat_dex_file->class_offsets_.size());
     if (table_size == 0u) {
+      // We want a 1:1 mapping between `dex_files_` and `type_lookup_table_oat_dex_files_`,
+      // to simplify `WriteTypeLookupTables`. We push a null entry to notify
+      // that the dex file at index `i` does not have a type lookup table.
+      type_lookup_table_oat_dex_files_.push_back(nullptr);
       continue;
     }
 
-    // Create the lookup table. When `nullptr` is given as the storage buffer,
-    // TypeLookupTable allocates its own and OatDexFile takes ownership.
-    // TODO: Create the table in an mmap()ed region of the output file to reduce dirty memory.
-    // (We used to do that when dex files were still copied into the oat file.)
-    const DexFile& dex_file = *opened_dex_files[i];
-    {
-      TypeLookupTable type_lookup_table = TypeLookupTable::Create(dex_file);
-      type_lookup_table_oat_dex_files_.push_back(
-          std::make_unique<art::OatDexFile>(std::move(type_lookup_table)));
-      dex_file.SetOatDexFile(type_lookup_table_oat_dex_files_.back().get());
-    }
-    const TypeLookupTable& table = type_lookup_table_oat_dex_files_.back()->GetTypeLookupTable();
-    DCHECK(table.Valid());
-
-    // Type tables are required to be 4 byte aligned.
-    size_t initial_offset = oat_size_;
-    size_t rodata_offset = RoundUp(initial_offset, 4);
-    size_t padding_size = rodata_offset - initial_offset;
-
-    if (padding_size != 0u) {
-      std::vector<uint8_t> buffer(padding_size, 0u);
-      if (!oat_rodata->WriteFully(buffer.data(), padding_size)) {
-        PLOG(ERROR) << "Failed to write lookup table alignment padding."
-                    << " File: " << oat_dex_file->GetLocation()
-                    << " Output: " << oat_rodata->GetLocation();
-        return false;
-      }
-    }
-
-    DCHECK_EQ(oat_data_offset_ + rodata_offset,
-              static_cast<size_t>(oat_rodata->Seek(0u, kSeekCurrent)));
-    DCHECK_EQ(table_size, table.RawDataLength());
-
-    if (!oat_rodata->WriteFully(table.RawData(), table_size)) {
-      PLOG(ERROR) << "Failed to write lookup table."
-                  << " File: " << oat_dex_file->GetLocation()
-                  << " Output: " << oat_rodata->GetLocation();
-      return false;
-    }
-
-    oat_dex_file->lookup_table_offset_ = rodata_offset;
-
-    oat_size_ += padding_size + table_size;
-    size_oat_lookup_table_ += table_size;
-    size_oat_lookup_table_alignment_ += padding_size;
+    const DexFile& dex_file = *opened_dex_files[i].get();
+    TypeLookupTable type_lookup_table = TypeLookupTable::Create(dex_file);
+    type_lookup_table_oat_dex_files_.push_back(
+        std::make_unique<art::OatDexFile>(std::move(type_lookup_table)));
+    dex_file.SetOatDexFile(type_lookup_table_oat_dex_files_.back().get());
   }
-
-  if (!oat_rodata->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after writing type lookup tables."
-                << " File: " << oat_rodata->GetLocation();
-    return false;
-  }
-
-  return true;
 }
 
 bool OatWriter::WriteDexLayoutSections(OutputStream* oat_rodata,
@@ -3940,69 +3645,179 @@
   return true;
 }
 
-bool OatWriter::WriteChecksumsAndVdexHeader(OutputStream* vdex_out) {
-  // Write checksums
-  off_t checksums_offset = sizeof(VdexFile::VerifierDepsHeader);
-  off_t actual_offset = vdex_out->Seek(checksums_offset, kSeekSet);
-  if (actual_offset != checksums_offset) {
-    PLOG(ERROR) << "Failed to seek to the checksum location of vdex file. Actual: " << actual_offset
-                << " File: " << vdex_out->GetLocation();
+void OatWriter::WriteTypeLookupTables(/*out*/std::vector<uint8_t>* buffer) {
+  TimingLogger::ScopedTiming split("WriteTypeLookupTables", timings_);
+  size_t type_lookup_table_size = 0u;
+  for (const DexFile* dex_file : *dex_files_) {
+    type_lookup_table_size +=
+        sizeof(uint32_t) + TypeLookupTable::RawDataLength(dex_file->NumClassDefs());
+  }
+  // Reserve the space to avoid reallocations later on.
+  buffer->reserve(buffer->size() + type_lookup_table_size);
+
+  // Align the start of the first type lookup table.
+  size_t initial_offset = vdex_size_;
+  size_t table_offset = RoundUp(initial_offset, 4);
+  size_t padding_size = table_offset - initial_offset;
+
+  size_vdex_lookup_table_alignment_ += padding_size;
+  for (uint32_t j = 0; j < padding_size; ++j) {
+    buffer->push_back(0);
+  }
+  vdex_size_ += padding_size;
+  vdex_lookup_tables_offset_ = vdex_size_;
+  for (size_t i = 0, size = type_lookup_table_oat_dex_files_.size(); i != size; ++i) {
+    OatDexFile* oat_dex_file = &oat_dex_files_[i];
+    if (type_lookup_table_oat_dex_files_[i] == nullptr) {
+      buffer->insert(buffer->end(), {0u, 0u, 0u, 0u});
+      size_vdex_lookup_table_ += sizeof(uint32_t);
+      vdex_size_ += sizeof(uint32_t);
+      oat_dex_file->lookup_table_offset_ = 0u;
+    } else {
+      oat_dex_file->lookup_table_offset_ = vdex_size_ + sizeof(uint32_t);
+      const TypeLookupTable& table = type_lookup_table_oat_dex_files_[i]->GetTypeLookupTable();
+      uint32_t table_size = table.RawDataLength();
+      DCHECK_NE(0u, table_size);
+      DCHECK_ALIGNED(table_size, 4);
+      size_t old_buffer_size = buffer->size();
+      buffer->resize(old_buffer_size + table.RawDataLength() + sizeof(uint32_t), 0u);
+      memcpy(buffer->data() + old_buffer_size, &table_size, sizeof(uint32_t));
+      memcpy(buffer->data() + old_buffer_size + sizeof(uint32_t), table.RawData(), table_size);
+      vdex_size_ += table_size + sizeof(uint32_t);
+      size_vdex_lookup_table_ += table_size + sizeof(uint32_t);
+    }
+  }
+}
+
+bool OatWriter::FinishVdexFile(File* vdex_file, verifier::VerifierDeps* verifier_deps) {
+  size_t old_vdex_size = vdex_size_;
+  std::vector<uint8_t> buffer;
+  buffer.reserve(64 * KB);
+  WriteVerifierDeps(verifier_deps, &buffer);
+  WriteTypeLookupTables(&buffer);
+  DCHECK_EQ(vdex_size_, old_vdex_size + buffer.size());
+
+  // Resize the vdex file.
+  if (vdex_file->SetLength(vdex_size_) != 0) {
+    PLOG(ERROR) << "Failed to resize vdex file " << vdex_file->GetPath();
     return false;
   }
 
-  for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) {
-    OatDexFile* oat_dex_file = &oat_dex_files_[i];
-    if (!vdex_out->WriteFully(
-            &oat_dex_file->dex_file_location_checksum_, sizeof(VdexFile::VdexChecksum))) {
-      PLOG(ERROR) << "Failed to write dex file location checksum. File: "
-                  << vdex_out->GetLocation();
+  uint8_t* vdex_begin = vdex_begin_;
+  MemMap extra_map;
+  if (extract_dex_files_into_vdex_) {
+    DCHECK(vdex_begin != nullptr);
+    // Write data to the last already mmapped page of the vdex file.
+    size_t mmapped_vdex_size = RoundUp(old_vdex_size, kPageSize);
+    size_t first_chunk_size = std::min(buffer.size(), mmapped_vdex_size - old_vdex_size);
+    memcpy(vdex_begin + old_vdex_size, buffer.data(), first_chunk_size);
+
+    if (first_chunk_size != buffer.size()) {
+      size_t tail_size = buffer.size() - first_chunk_size;
+      std::string error_msg;
+      extra_map = MemMap::MapFile(
+          tail_size,
+          PROT_READ | PROT_WRITE,
+          MAP_SHARED,
+          vdex_file->Fd(),
+          /*start=*/ mmapped_vdex_size,
+          /*low_4gb=*/ false,
+          vdex_file->GetPath().c_str(),
+          &error_msg);
+      if (!extra_map.IsValid()) {
+        LOG(ERROR) << "Failed to mmap() vdex file tail. File: " << vdex_file->GetPath()
+                   << " error: " << error_msg;
+        return false;
+      }
+      memcpy(extra_map.Begin(), buffer.data() + first_chunk_size, tail_size);
+    }
+  } else {
+    DCHECK(vdex_begin == nullptr);
+    std::string error_msg;
+    extra_map = MemMap::MapFile(
+        vdex_size_,
+        PROT_READ | PROT_WRITE,
+        MAP_SHARED,
+        vdex_file->Fd(),
+        /*start=*/ 0u,
+        /*low_4gb=*/ false,
+        vdex_file->GetPath().c_str(),
+        &error_msg);
+    if (!extra_map.IsValid()) {
+      LOG(ERROR) << "Failed to mmap() vdex file. File: " << vdex_file->GetPath()
+                 << " error: " << error_msg;
       return false;
     }
+    vdex_begin = extra_map.Begin();
+    memcpy(vdex_begin + old_vdex_size, buffer.data(), buffer.size());
+  }
+
+  // Write checksums
+  off_t checksums_offset = VdexFile::GetChecksumsOffset();
+  VdexFile::VdexChecksum* checksums_data =
+      reinterpret_cast<VdexFile::VdexChecksum*>(vdex_begin + checksums_offset);
+  for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) {
+    OatDexFile* oat_dex_file = &oat_dex_files_[i];
+    checksums_data[i] = oat_dex_file->dex_file_location_checksum_;
     size_vdex_checksums_ += sizeof(VdexFile::VdexChecksum);
   }
 
-  // Maybe write dex section header.
-  DCHECK_NE(vdex_verifier_deps_offset_, 0u);
-  DCHECK_NE(vdex_quickening_info_offset_, 0u);
+  // Write sections.
+  uint8_t* ptr = vdex_begin + sizeof(VdexFile::VdexFileHeader);
 
-  bool has_dex_section = extract_dex_files_into_vdex_;
-  if (has_dex_section) {
-    DCHECK_NE(vdex_dex_files_offset_, 0u);
-    size_t dex_section_size = vdex_dex_shared_data_offset_ - vdex_dex_files_offset_;
-    size_t dex_shared_data_size = vdex_verifier_deps_offset_ - vdex_dex_shared_data_offset_;
-    size_t quickening_info_section_size = vdex_size_ - vdex_quickening_info_offset_;
+  // Checksums section.
+  new (ptr) VdexFile::VdexSectionHeader(VdexSection::kChecksumSection,
+                                        checksums_offset,
+                                        size_vdex_checksums_);
+  ptr += sizeof(VdexFile::VdexSectionHeader);
 
-    VdexFile::DexSectionHeader dex_section_header(dex_section_size,
-                                                  dex_shared_data_size,
-                                                  quickening_info_section_size);
-    if (!vdex_out->WriteFully(&dex_section_header, sizeof(VdexFile::DexSectionHeader))) {
-      PLOG(ERROR) << "Failed to write vdex header. File: " << vdex_out->GetLocation();
+  // Dex section.
+  new (ptr) VdexFile::VdexSectionHeader(
+      VdexSection::kDexFileSection,
+      extract_dex_files_into_vdex_ ? vdex_dex_files_offset_ : 0u,
+      extract_dex_files_into_vdex_ ? vdex_verifier_deps_offset_ - vdex_dex_files_offset_ : 0u);
+  ptr += sizeof(VdexFile::VdexSectionHeader);
+
+  // VerifierDeps section.
+  new (ptr) VdexFile::VdexSectionHeader(VdexSection::kVerifierDepsSection,
+                                        vdex_verifier_deps_offset_,
+                                        size_verifier_deps_);
+  ptr += sizeof(VdexFile::VdexSectionHeader);
+
+  // TypeLookupTable section.
+  new (ptr) VdexFile::VdexSectionHeader(VdexSection::kTypeLookupTableSection,
+                                        vdex_lookup_tables_offset_,
+                                        vdex_size_ - vdex_lookup_tables_offset_);
+
+  // All the contents (except the header) of the vdex file has been emitted in memory. Flush it
+  // to disk.
+  {
+    TimingLogger::ScopedTiming split("VDEX flush contents", timings_);
+    // Sync the data to the disk while the header is invalid. We do not want to end up with
+    // a valid header and invalid data if the process is suddenly killed.
+    if (extract_dex_files_into_vdex_) {
+      // Note: We passed the ownership of the vdex dex file MemMap to the caller,
+      // so we need to use msync() for the range explicitly.
+      if (msync(vdex_begin, RoundUp(old_vdex_size, kPageSize), MS_SYNC) != 0) {
+        PLOG(ERROR) << "Failed to sync vdex file contents" << vdex_file->GetPath();
+        return false;
+      }
+    }
+    if (extra_map.IsValid() && !extra_map.Sync()) {
+      PLOG(ERROR) << "Failed to sync vdex file contents" << vdex_file->GetPath();
       return false;
     }
-    size_vdex_header_ += sizeof(VdexFile::DexSectionHeader);
   }
 
-  // Write header.
-  actual_offset = vdex_out->Seek(0, kSeekSet);
-  if (actual_offset != 0) {
-    PLOG(ERROR) << "Failed to seek to the beginning of vdex file. Actual: " << actual_offset
-                << " File: " << vdex_out->GetLocation();
-    return false;
-  }
+  // Now that we know all contents have been flushed to disk, we can write
+  // the header which will mke the vdex usable.
+  bool has_dex_section = extract_dex_files_into_vdex_;
+  new (vdex_begin) VdexFile::VdexFileHeader(has_dex_section);
 
-  size_t verifier_deps_section_size = vdex_quickening_info_offset_ - vdex_verifier_deps_offset_;
-
-  VdexFile::VerifierDepsHeader deps_header(
-      oat_dex_files_.size(), verifier_deps_section_size, has_dex_section);
-  if (!vdex_out->WriteFully(&deps_header, sizeof(VdexFile::VerifierDepsHeader))) {
-    PLOG(ERROR) << "Failed to write vdex header. File: " << vdex_out->GetLocation();
-    return false;
-  }
-  size_vdex_header_ += sizeof(VdexFile::VerifierDepsHeader);
-
-  if (!vdex_out->Flush()) {
-    PLOG(ERROR) << "Failed to flush stream after writing to vdex file."
-                << " File: " << vdex_out->GetLocation();
+  // Note: If `extract_dex_files_into_vdex_`, we passed the ownership of the vdex dex file
+  // MemMap to the caller, so we need to use msync() for the range explicitly.
+  if (msync(vdex_begin, kPageSize, MS_SYNC) != 0) {
+    PLOG(ERROR) << "Failed to sync vdex file header " << vdex_file->GetPath();
     return false;
   }
 
@@ -4039,11 +3854,9 @@
 
 OatWriter::OatDexFile::OatDexFile(const char* dex_file_location,
                                   DexFileSource source,
-                                  CreateTypeLookupTable create_type_lookup_table,
                                   uint32_t dex_file_location_checksum,
                                   size_t dex_file_size)
-    : source_(source),
-      create_type_lookup_table_(create_type_lookup_table),
+    : source_(std::move(source)),
       dex_file_size_(dex_file_size),
       offset_(0),
       dex_file_location_size_(strlen(dex_file_location)),
@@ -4054,6 +3867,8 @@
       class_offsets_offset_(0u),
       method_bss_mapping_offset_(0u),
       type_bss_mapping_offset_(0u),
+      public_type_bss_mapping_offset_(0u),
+      package_type_bss_mapping_offset_(0u),
       string_bss_mapping_offset_(0u),
       dex_sections_layout_offset_(0u),
       class_offsets_() {
@@ -4068,6 +3883,8 @@
           + sizeof(lookup_table_offset_)
           + sizeof(method_bss_mapping_offset_)
           + sizeof(type_bss_mapping_offset_)
+          + sizeof(public_type_bss_mapping_offset_)
+          + sizeof(package_type_bss_mapping_offset_)
           + sizeof(string_bss_mapping_offset_)
           + sizeof(dex_sections_layout_offset_);
 }
@@ -4130,6 +3947,21 @@
   }
   oat_writer->size_oat_dex_file_type_bss_mapping_offset_ += sizeof(type_bss_mapping_offset_);
 
+  if (!out->WriteFully(&public_type_bss_mapping_offset_, sizeof(public_type_bss_mapping_offset_))) {
+    PLOG(ERROR) << "Failed to write public type bss mapping offset to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_dex_file_public_type_bss_mapping_offset_ +=
+      sizeof(public_type_bss_mapping_offset_);
+
+  if (!out->WriteFully(&package_type_bss_mapping_offset_,
+                       sizeof(package_type_bss_mapping_offset_))) {
+    PLOG(ERROR) << "Failed to write package type bss mapping offset to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_dex_file_package_type_bss_mapping_offset_ +=
+      sizeof(package_type_bss_mapping_offset_);
+
   if (!out->WriteFully(&string_bss_mapping_offset_, sizeof(string_bss_mapping_offset_))) {
     PLOG(ERROR) << "Failed to write string bss mapping offset to " << out->GetLocation();
     return false;
@@ -4162,15 +3994,18 @@
   method_headers_.resize(compiled_methods_with_code);
 
   uint32_t oat_method_offsets_offset_from_oat_class = OatClassHeader::SizeOf();
-  // We only create this instance if there are at least some compiled.
-  if (oat_class_type == kOatClassSomeCompiled) {
-    method_bitmap_.reset(new BitVector(num_methods, false, Allocator::GetMallocAllocator()));
-    method_bitmap_size_ = method_bitmap_->GetSizeOf();
-    oat_method_offsets_offset_from_oat_class += sizeof(method_bitmap_size_);
-    oat_method_offsets_offset_from_oat_class += method_bitmap_size_;
-  } else {
-    method_bitmap_ = nullptr;
-    method_bitmap_size_ = 0;
+  // We only write method-related data if there are at least some compiled methods.
+  num_methods_ = 0u;
+  DCHECK(method_bitmap_ == nullptr);
+  if (oat_class_type != enum_cast<uint16_t>(OatClassType::kNoneCompiled)) {
+    num_methods_ = num_methods;
+    oat_method_offsets_offset_from_oat_class += sizeof(num_methods_);
+    if (oat_class_type == enum_cast<uint16_t>(OatClassType::kSomeCompiled)) {
+      method_bitmap_.reset(new BitVector(num_methods, false, Allocator::GetMallocAllocator()));
+      uint32_t bitmap_size = BitVector::BitsToWords(num_methods) * BitVector::kWordBytes;
+      DCHECK_EQ(bitmap_size, method_bitmap_->GetSizeOf());
+      oat_method_offsets_offset_from_oat_class += bitmap_size;
+    }
   }
 
   for (size_t i = 0; i < num_methods; i++) {
@@ -4178,7 +4013,7 @@
     if (HasCompiledCode(compiled_method)) {
       oat_method_offsets_offsets_from_oat_class_[i] = oat_method_offsets_offset_from_oat_class;
       oat_method_offsets_offset_from_oat_class += sizeof(OatMethodOffsets);
-      if (oat_class_type == kOatClassSomeCompiled) {
+      if (oat_class_type == enum_cast<uint16_t>(OatClassType::kSomeCompiled)) {
         method_bitmap_->SetBit(i);
       }
     } else {
@@ -4188,9 +4023,9 @@
 }
 
 size_t OatWriter::OatClass::SizeOf() const {
-  return ((method_bitmap_size_ == 0) ? 0 : sizeof(method_bitmap_size_))
-          + method_bitmap_size_
-          + (sizeof(method_offsets_[0]) * method_offsets_.size());
+  return ((num_methods_ == 0) ? 0 : sizeof(num_methods_)) +
+         ((method_bitmap_ != nullptr) ? method_bitmap_->GetSizeOf() : 0u) +
+         (sizeof(method_offsets_[0]) * method_offsets_.size());
 }
 
 bool OatWriter::OatClassHeader::Write(OatWriter* oat_writer,
@@ -4212,18 +4047,20 @@
 }
 
 bool OatWriter::OatClass::Write(OatWriter* oat_writer, OutputStream* out) const {
-  if (method_bitmap_size_ != 0) {
-    if (!out->WriteFully(&method_bitmap_size_, sizeof(method_bitmap_size_))) {
-      PLOG(ERROR) << "Failed to write method bitmap size to " << out->GetLocation();
+  if (num_methods_ != 0u) {
+    if (!out->WriteFully(&num_methods_, sizeof(num_methods_))) {
+      PLOG(ERROR) << "Failed to write number of methods to " << out->GetLocation();
       return false;
     }
-    oat_writer->size_oat_class_method_bitmaps_ += sizeof(method_bitmap_size_);
+    oat_writer->size_oat_class_num_methods_ += sizeof(num_methods_);
+  }
 
-    if (!out->WriteFully(method_bitmap_->GetRawStorage(), method_bitmap_size_)) {
+  if (method_bitmap_ != nullptr) {
+    if (!out->WriteFully(method_bitmap_->GetRawStorage(), method_bitmap_->GetSizeOf())) {
       PLOG(ERROR) << "Failed to write method bitmap to " << out->GetLocation();
       return false;
     }
-    oat_writer->size_oat_class_method_bitmaps_ += method_bitmap_size_;
+    oat_writer->size_oat_class_method_bitmaps_ += method_bitmap_->GetSizeOf();
   }
 
   if (!out->WriteFully(method_offsets_.data(), GetMethodOffsetsRawSize())) {
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index f83f077..87174eb 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -114,12 +114,6 @@
 //
 class OatWriter {
  public:
-  enum class CreateTypeLookupTable {
-    kCreate,
-    kDontCreate,
-    kDefault = kCreate
-  };
-
   OatWriter(const CompilerOptions& compiler_options,
             TimingLogger* timings,
             ProfileCompilationInfo* info,
@@ -132,9 +126,7 @@
   // Then the user must call in order
   //   - WriteAndOpenDexFiles()
   //   - StartRoData()
-  //   - WriteVerifierDeps()
-  //   - WriteQuickeningInfo()
-  //   - WriteChecksumsAndVdexHeader()
+  //   - FinishVdexFile()
   //   - PrepareLayout(),
   //   - WriteRodata(),
   //   - WriteCode(),
@@ -145,25 +137,21 @@
   // a zip file with one or more dex files.
   bool AddDexFileSource(
       const char* filename,
-      const char* location,
-      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
+      const char* location);
   // Add dex file source(s) from a file specified by a file handle.
   // Note: The `dex_file_fd` specifies a plain dex file or a zip file.
   bool AddDexFileSource(
       File&& dex_file_fd,
-      const char* location,
-      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
+      const char* location);
   // Add dex file source from raw memory.
   bool AddRawDexFileSource(
       const ArrayRef<const uint8_t>& data,
       const char* location,
-      uint32_t location_checksum,
-      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
+      uint32_t location_checksum);
   // Add dex file source(s) from a vdex file.
   bool AddVdexDexFilesSource(
       const VdexFile& vdex_file,
-      const char* location,
-      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
+      const char* location);
   dchecked_vector<std::string> GetSourceLocations() const;
 
   // Write raw dex files to the vdex file, mmap the file and open the dex files from it.
@@ -185,9 +173,7 @@
   void Initialize(const CompilerDriver* compiler_driver,
                   ImageWriter* image_writer,
                   const std::vector<const DexFile*>& dex_files);
-  bool WriteQuickeningInfo(OutputStream* vdex_out);
-  bool WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps);
-  bool WriteChecksumsAndVdexHeader(OutputStream* vdex_out);
+  bool FinishVdexFile(File* vdex_file, verifier::VerifierDeps* verifier_deps);
 
   // Prepare layout of remaining data.
   void PrepareLayout(MultiOatRelativePatcher* relative_patcher);
@@ -282,8 +268,6 @@
   class InitImageMethodVisitor;
   class WriteCodeMethodVisitor;
   class WriteMapMethodVisitor;
-  class WriteQuickeningInfoMethodVisitor;
-  class WriteQuickeningInfoOffsetsMethodVisitor;
 
   // Visit all the methods in all the compiled dex files in their definition order
   // with a given DexMethodVisitor.
@@ -291,32 +275,31 @@
 
   // If `update_input_vdex` is true, then this method won't actually write the dex files,
   // and the compiler will just re-use the existing vdex file.
-  bool WriteDexFiles(OutputStream* out,
-                     File* file,
+  bool WriteDexFiles(File* file,
                      bool update_input_vdex,
-                     CopyOption copy_dex_files);
-  bool WriteDexFile(OutputStream* out,
-                    File* file,
+                     CopyOption copy_dex_files,
+                     /*out*/ std::vector<MemMap>* opened_dex_files_map);
+  bool WriteDexFile(File* file,
                     OatDexFile* oat_dex_file,
                     bool update_input_vdex);
-  bool SeekToDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file);
-  bool LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_file);
-  bool WriteDexFile(OutputStream* out,
-                    File* file,
+  bool LayoutDexFile(OatDexFile* oat_dex_file);
+  bool WriteDexFile(File* file,
                     OatDexFile* oat_dex_file,
                     ZipEntry* dex_file);
-  bool WriteDexFile(OutputStream* out,
-                    File* file,
+  bool WriteDexFile(File* file,
                     OatDexFile* oat_dex_file,
                     File* dex_file);
-  bool WriteDexFile(OutputStream* out,
-                    OatDexFile* oat_dex_file,
+  bool WriteDexFile(OatDexFile* oat_dex_file,
                     const uint8_t* dex_file,
                     bool update_input_vdex);
   bool OpenDexFiles(File* file,
                     bool verify,
-                    /*out*/ std::vector<MemMap>* opened_dex_files_map,
+                    /*inout*/ std::vector<MemMap>* opened_dex_files_map,
                     /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
+  void WriteQuickeningInfo(/*out*/std::vector<uint8_t>* buffer);
+  void WriteTypeLookupTables(/*out*/std::vector<uint8_t>* buffer);
+  void WriteVerifierDeps(verifier::VerifierDeps* verifier_deps,
+                         /*out*/std::vector<uint8_t>* buffer);
 
   size_t InitOatHeader(uint32_t num_dex_files, SafeMap<std::string, std::string>* key_value_store);
   size_t InitClassOffsets(size_t offset);
@@ -339,8 +322,8 @@
   size_t WriteDataBimgRelRo(OutputStream* out, size_t file_offset, size_t relative_offset);
 
   bool RecordOatDataOffset(OutputStream* out);
-  bool WriteTypeLookupTables(OutputStream* oat_rodata,
-                             const std::vector<const DexFile*>& opened_dex_files);
+  void InitializeTypeLookupTables(
+      const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files);
   bool WriteDexLayoutSections(OutputStream* oat_rodata,
                               const std::vector<const DexFile*>& opened_dex_files);
   bool WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta);
@@ -386,6 +369,8 @@
   ImageWriter* image_writer_;
   // Whether the dex files being compiled are going to be extracted to the vdex.
   bool extract_dex_files_into_vdex_;
+  // The start of the vdex file section mmapped for writing dex files.
+  uint8_t* vdex_begin_;
 
   // note OatFile does not take ownership of the DexFiles
   const std::vector<const DexFile*>* dex_files_;
@@ -408,6 +393,9 @@
   // Offset of section holding quickening info inside Vdex.
   size_t vdex_quickening_info_offset_;
 
+  // Offset of type lookup tables inside Vdex.
+  size_t vdex_lookup_tables_offset_;
+
   // OAT checksum.
   uint32_t oat_checksum_;
 
@@ -445,6 +433,12 @@
   // Map for recording references to GcRoot<mirror::Class> entries in .bss.
   SafeMap<const DexFile*, BitVector> bss_type_entry_references_;
 
+  // Map for recording references to public GcRoot<mirror::Class> entries in .bss.
+  SafeMap<const DexFile*, BitVector> bss_public_type_entry_references_;
+
+  // Map for recording references to package GcRoot<mirror::Class> entries in .bss.
+  SafeMap<const DexFile*, BitVector> bss_package_type_entry_references_;
+
   // Map for recording references to GcRoot<mirror::String> entries in .bss.
   SafeMap<const DexFile*, BitVector> bss_string_entry_references_;
 
@@ -458,6 +452,16 @@
   // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
   SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_type_entries_;
 
+  // Map for allocating public Class entries in .bss. Indexed by TypeReference for the source
+  // type in the dex file with the "type value comparator" for deduplication. The value
+  // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
+  SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_public_type_entries_;
+
+  // Map for allocating package Class entries in .bss. Indexed by TypeReference for the source
+  // type in the dex file with the "type value comparator" for deduplication. The value
+  // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
+  SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_package_type_entries_;
+
   // Map for allocating String entries in .bss. Indexed by StringReference for the source
   // string in the dex file with the "string value comparator" for deduplication. The value
   // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
@@ -480,11 +484,13 @@
   std::unique_ptr<const std::vector<uint8_t>> quick_imt_conflict_trampoline_;
   std::unique_ptr<const std::vector<uint8_t>> quick_resolution_trampoline_;
   std::unique_ptr<const std::vector<uint8_t>> quick_to_interpreter_bridge_;
+  std::unique_ptr<const std::vector<uint8_t>> nterp_trampoline_;
 
   // output stats
   uint32_t size_vdex_header_;
   uint32_t size_vdex_checksums_;
   uint32_t size_dex_file_alignment_;
+  uint32_t size_quickening_table_offset_;
   uint32_t size_executable_offset_alignment_;
   uint32_t size_oat_header_;
   uint32_t size_oat_header_key_value_store_;
@@ -493,6 +499,8 @@
   uint32_t size_verifier_deps_alignment_;
   uint32_t size_quickening_info_;
   uint32_t size_quickening_info_alignment_;
+  uint32_t size_vdex_lookup_table_alignment_;
+  uint32_t size_vdex_lookup_table_;
   uint32_t size_interpreter_to_interpreter_bridge_;
   uint32_t size_interpreter_to_compiled_code_bridge_;
   uint32_t size_jni_dlsym_lookup_trampoline_;
@@ -501,6 +509,7 @@
   uint32_t size_quick_imt_conflict_trampoline_;
   uint32_t size_quick_resolution_trampoline_;
   uint32_t size_quick_to_interpreter_bridge_;
+  uint32_t size_nterp_trampoline_;
   uint32_t size_trampoline_alignment_;
   uint32_t size_method_header_;
   uint32_t size_code_;
@@ -522,17 +531,20 @@
   uint32_t size_oat_dex_file_dex_layout_sections_alignment_;
   uint32_t size_oat_dex_file_method_bss_mapping_offset_;
   uint32_t size_oat_dex_file_type_bss_mapping_offset_;
+  uint32_t size_oat_dex_file_public_type_bss_mapping_offset_;
+  uint32_t size_oat_dex_file_package_type_bss_mapping_offset_;
   uint32_t size_oat_dex_file_string_bss_mapping_offset_;
-  uint32_t size_oat_lookup_table_alignment_;
-  uint32_t size_oat_lookup_table_;
   uint32_t size_oat_class_offsets_alignment_;
   uint32_t size_oat_class_offsets_;
   uint32_t size_oat_class_type_;
   uint32_t size_oat_class_status_;
+  uint32_t size_oat_class_num_methods_;
   uint32_t size_oat_class_method_bitmaps_;
   uint32_t size_oat_class_method_offsets_;
   uint32_t size_method_bss_mappings_;
   uint32_t size_type_bss_mappings_;
+  uint32_t size_public_type_bss_mappings_;
+  uint32_t size_package_type_bss_mappings_;
   uint32_t size_string_bss_mappings_;
 
   // The helper for processing relative patches is external so that we can patch across oat files.
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index 1b27bce..7bcff2b 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -212,15 +212,7 @@
                                       oat_writer.GetBssRootsOffset(),
                                       oat_writer.GetVdexSize());
 
-    std::unique_ptr<BufferedOutputStream> vdex_out =
-        std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(vdex_file));
-    if (!oat_writer.WriteVerifierDeps(vdex_out.get(), nullptr)) {
-      return false;
-    }
-    if (!oat_writer.WriteQuickeningInfo(vdex_out.get())) {
-      return false;
-    }
-    if (!oat_writer.WriteChecksumsAndVdexHeader(vdex_out.get())) {
+    if (!oat_writer.FinishVdexFile(vdex_file, /*verifier_deps=*/ nullptr)) {
       return false;
     }
 
@@ -299,13 +291,6 @@
                           dex_file_data->GetHeader().file_size_));
       ASSERT_EQ(dex_file_data->GetLocation(), opened_dex_file->GetLocation());
     }
-    const VdexFile::DexSectionHeader &vdex_header =
-        opened_oat_file->GetVdexFile()->GetDexSectionHeader();
-    if (!compiler_driver_->GetCompilerOptions().IsQuickeningCompilationEnabled()) {
-      // If quickening is enabled we will always write the table since there is no special logic
-      // that checks for all methods not being quickened (not worth the complexity).
-      ASSERT_EQ(vdex_header.GetQuickeningInfoSize(), 0u);
-    }
 
     int64_t actual_vdex_size = vdex_file.GetFile()->GetLength();
     ASSERT_GE(actual_vdex_size, 0);
@@ -492,7 +477,7 @@
 
     const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(accessor.GetClassDefIndex());
     CHECK_EQ(ClassStatus::kNotReady, oat_class.GetStatus()) << descriptor;
-    CHECK_EQ(kCompile ? OatClassType::kOatClassAllCompiled : OatClassType::kOatClassNoneCompiled,
+    CHECK_EQ(kCompile ? OatClassType::kAllCompiled : OatClassType::kNoneCompiled,
              oat_class.GetType()) << descriptor;
 
     size_t method_index = 0;
@@ -517,9 +502,9 @@
 TEST_F(OatTest, OatHeaderSizeCheck) {
   // If this test is failing and you have to update these constants,
   // it is time to update OatHeader::kOatVersion
-  EXPECT_EQ(60U, sizeof(OatHeader));
+  EXPECT_EQ(64U, sizeof(OatHeader));
   EXPECT_EQ(4U, sizeof(OatMethodOffsets));
-  EXPECT_EQ(8U, sizeof(OatQuickMethodHeader));
+  EXPECT_EQ(4U, sizeof(OatQuickMethodHeader));
   EXPECT_EQ(169 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
             sizeof(QuickEntryPoints));
 }
@@ -605,8 +590,8 @@
 
   ScratchFile dex_file1;
   TestDexFileBuilder builder1;
-  builder1.AddField("Lsome.TestClass;", "int", "someField");
-  builder1.AddMethod("Lsome.TestClass;", "()I", "foo");
+  builder1.AddField("Lsome/TestClass;", "int", "someField");
+  builder1.AddMethod("Lsome/TestClass;", "()I", "foo");
   std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename());
 
   MaybeModifyDexFileToFail(verify, dex_file1_data);
@@ -622,8 +607,8 @@
 
   ScratchFile dex_file2;
   TestDexFileBuilder builder2;
-  builder2.AddField("Land.AnotherTestClass;", "boolean", "someOtherField");
-  builder2.AddMethod("Land.AnotherTestClass;", "()J", "bar");
+  builder2.AddField("Land/AnotherTestClass;", "boolean", "someOtherField");
+  builder2.AddMethod("Land/AnotherTestClass;", "()J", "bar");
   std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename());
 
   MaybeModifyDexFileToFail(verify, dex_file2_data);
@@ -729,8 +714,8 @@
 
   ScratchFile dex_file1;
   TestDexFileBuilder builder1;
-  builder1.AddField("Lsome.TestClass;", "long", "someField");
-  builder1.AddMethod("Lsome.TestClass;", "()D", "foo");
+  builder1.AddField("Lsome/TestClass;", "long", "someField");
+  builder1.AddMethod("Lsome/TestClass;", "()D", "foo");
   std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename());
 
   MaybeModifyDexFileToFail(verify, dex_file1_data);
@@ -747,8 +732,8 @@
 
   ScratchFile dex_file2;
   TestDexFileBuilder builder2;
-  builder2.AddField("Land.AnotherTestClass;", "boolean", "someOtherField");
-  builder2.AddMethod("Land.AnotherTestClass;", "()J", "bar");
+  builder2.AddField("Land/AnotherTestClass;", "boolean", "someOtherField");
+  builder2.AddMethod("Land/AnotherTestClass;", "()J", "bar");
   std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename());
 
   MaybeModifyDexFileToFail(verify, dex_file2_data);
diff --git a/dex2oat/linker/relative_patcher_test.h b/dex2oat/linker/relative_patcher_test.h
index f34e6eb..56e0dc1 100644
--- a/dex2oat/linker/relative_patcher_test.h
+++ b/dex2oat/linker/relative_patcher_test.h
@@ -145,15 +145,15 @@
 
     // Write data.
     DCHECK(output_.empty());
-    uint8_t dummy_trampoline[kTrampolineSize];
-    memset(dummy_trampoline, 0, sizeof(dummy_trampoline));
-    out_->WriteFully(dummy_trampoline, kTrampolineSize);
+    uint8_t fake_trampoline[kTrampolineSize];
+    memset(fake_trampoline, 0, sizeof(fake_trampoline));
+    out_->WriteFully(fake_trampoline, kTrampolineSize);
     offset = kTrampolineSize;
     static const uint8_t kPadding[] = {
         0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u
     };
-    uint8_t dummy_header[sizeof(OatQuickMethodHeader)];
-    memset(dummy_header, 0, sizeof(dummy_header));
+    uint8_t fake_header[sizeof(OatQuickMethodHeader)];
+    memset(fake_header, 0, sizeof(fake_header));
     for (auto& compiled_method : compiled_methods_) {
       offset = patcher_->WriteThunks(out_.get(), offset);
 
@@ -162,7 +162,7 @@
       out_->WriteFully(kPadding, alignment_size);
       offset += alignment_size;
 
-      out_->WriteFully(dummy_header, sizeof(OatQuickMethodHeader));
+      out_->WriteFully(fake_header, sizeof(OatQuickMethodHeader));
       offset += sizeof(OatQuickMethodHeader);
       ArrayRef<const uint8_t> code = compiled_method->GetQuickCode();
       if (!compiled_method->GetPatches().empty()) {
@@ -214,7 +214,7 @@
   }
 
   bool CheckLinkedMethod(MethodReference method_ref, const ArrayRef<const uint8_t>& expected_code) {
-    // Sanity check: original code size must match linked_code.size().
+    // Check that the original code size must match linked_code.size().
     size_t idx = 0u;
     for (auto ref : compiled_method_refs_) {
       if (ref == method_ref) {
diff --git a/dex2oat/linker/x86/relative_patcher_x86.cc b/dex2oat/linker/x86/relative_patcher_x86.cc
index 3323506..e3b94b0 100644
--- a/dex2oat/linker/x86/relative_patcher_x86.cc
+++ b/dex2oat/linker/x86/relative_patcher_x86.cc
@@ -39,14 +39,14 @@
   DCHECK_EQ((*code)[anchor_literal_offset - 1u], 0x00u);
   DCHECK_EQ((*code)[anchor_literal_offset] & 0xf8u, 0x58u);
 
-  // Check that the patched data contains kDummy32BitOffset.
-  // Must match X86Mir2Lir::kDummy32BitOffset and CodeGeneratorX86_64::kDummy32BitOffset.
-  constexpr int kDummy32BitOffset = 256;
+  // Check that the patched data contains kPlaceholder32BitOffset.
+  // Must match CodeGeneratorX86_64::kPlaceholder32BitOffset.
+  constexpr int kPlaceholder32BitOffset = 256;
   DCHECK_LE(literal_offset, code->size());
-  DCHECK_EQ((*code)[literal_offset + 0u], static_cast<uint8_t>(kDummy32BitOffset >> 0));
-  DCHECK_EQ((*code)[literal_offset + 1u], static_cast<uint8_t>(kDummy32BitOffset >> 8));
-  DCHECK_EQ((*code)[literal_offset + 2u], static_cast<uint8_t>(kDummy32BitOffset >> 16));
-  DCHECK_EQ((*code)[literal_offset + 3u], static_cast<uint8_t>(kDummy32BitOffset >> 24));
+  DCHECK_EQ((*code)[literal_offset + 0u], static_cast<uint8_t>(kPlaceholder32BitOffset >> 0));
+  DCHECK_EQ((*code)[literal_offset + 1u], static_cast<uint8_t>(kPlaceholder32BitOffset >> 8));
+  DCHECK_EQ((*code)[literal_offset + 2u], static_cast<uint8_t>(kPlaceholder32BitOffset >> 16));
+  DCHECK_EQ((*code)[literal_offset + 3u], static_cast<uint8_t>(kPlaceholder32BitOffset >> 24));
 
   // Apply patch.
   uint32_t anchor_offset = patch_offset - literal_offset + anchor_literal_offset;
diff --git a/dex2oat/linker/x86/relative_patcher_x86_test.cc b/dex2oat/linker/x86/relative_patcher_x86_test.cc
index b855dec..4b44cd5 100644
--- a/dex2oat/linker/x86/relative_patcher_x86_test.cc
+++ b/dex2oat/linker/x86/relative_patcher_x86_test.cc
@@ -116,7 +116,7 @@
   static const uint8_t raw_code[] = {
       0xe8, 0x00, 0x00, 0x00, 0x00,         // call +0
       0x5b,                                 // pop ebx
-      0x8b, 0x83, 0x00, 0x01, 0x00, 0x00,   // mov eax, [ebx + 256 (kDummy32BitValue)]
+      0x8b, 0x83, 0x00, 0x01, 0x00, 0x00,   // mov eax, [ebx + 256 (kPlaceholder32BitOffset)]
   };
   constexpr uint32_t anchor_offset = 5u;  // After call +0.
   ArrayRef<const uint8_t> code(raw_code);
@@ -148,7 +148,7 @@
   static const uint8_t raw_code[] = {
       0xe8, 0x00, 0x00, 0x00, 0x00,         // call +0
       0x5b,                                 // pop ebx
-      0x8d, 0x83, 0x00, 0x01, 0x00, 0x00,   // lea eax, [ebx + 256 (kDummy32BitValue)]
+      0x8d, 0x83, 0x00, 0x01, 0x00, 0x00,   // lea eax, [ebx + 256 (kPlaceholder32BitOffset)]
   };
   constexpr uint32_t anchor_offset = 5u;  // After call +0.
   ArrayRef<const uint8_t> code(raw_code);
diff --git a/dex2oat/verifier_deps_test.cc b/dex2oat/verifier_deps_test.cc
index 4094425..e833180 100644
--- a/dex2oat/verifier_deps_test.cc
+++ b/dex2oat/verifier_deps_test.cc
@@ -163,9 +163,9 @@
               method.GetInvokeType(class_def->access_flags_));
       CHECK(resolved_method != nullptr);
       if (method_name == resolved_method->GetName()) {
-        soa.Self()->SetVerifierDeps(callbacks_->GetVerifierDeps());
         std::unique_ptr<MethodVerifier> verifier(
             MethodVerifier::CreateVerifier(soa.Self(),
+                                           callbacks_->GetVerifierDeps(),
                                            primary_dex_file_,
                                            dex_cache_handle,
                                            class_loader_handle,
@@ -199,10 +199,7 @@
     VerifyWithCompilerDriver(/* verifier_deps= */ nullptr);
   }
 
-  bool TestAssignabilityRecording(const std::string& dst,
-                                  const std::string& src,
-                                  bool is_strict,
-                                  bool is_assignable) {
+  bool TestAssignabilityRecording(const std::string& dst, const std::string& src) {
     ScopedObjectAccess soa(Thread::Current());
     LoadDexFile(soa);
     StackHandleScope<1> hs(soa.Self());
@@ -211,10 +208,9 @@
     ObjPtr<mirror::Class> klass_src = FindClassByName(soa, src);
     DCHECK(klass_src != nullptr) << src;
     verifier_deps_->AddAssignability(*primary_dex_file_,
+                                     primary_dex_file_->GetClassDef(0),
                                      klass_dst.Get(),
-                                     klass_src,
-                                     is_strict,
-                                     is_assignable);
+                                     klass_src);
     return true;
   }
 
@@ -239,7 +235,7 @@
         } else if (&cls->GetDexFile() != dex_file) {
           // Ignore classes from different dex files.
         } else if (verified_classes[i]) {
-          ASSERT_EQ(cls->GetStatus(), ClassStatus::kVerified);
+          ASSERT_EQ(cls->GetStatus(), ClassStatus::kVerifiedNeedsAccessChecks);
         } else {
           ASSERT_LT(cls->GetStatus(), ClassStatus::kVerified);
         }
@@ -256,171 +252,39 @@
     return dex_file.GetIndexForClassDef(*class_def);
   }
 
+  bool HasVerifiedClass(const std::string& cls) {
+    return HasVerifiedClass(cls, *primary_dex_file_);
+  }
+
   bool HasUnverifiedClass(const std::string& cls) {
-    return HasUnverifiedClass(cls, *primary_dex_file_);
+    return !HasVerifiedClass(cls, *primary_dex_file_);
   }
 
   bool HasUnverifiedClass(const std::string& cls, const DexFile& dex_file) {
-    uint16_t class_def_idx = GetClassDefIndex(cls, dex_file);
-    return !verifier_deps_->GetVerifiedClasses(dex_file)[class_def_idx];
+    return !HasVerifiedClass(cls, dex_file);
   }
 
-  bool HasRedefinedClass(const std::string& cls) {
-    uint16_t class_def_idx = GetClassDefIndex(cls, *primary_dex_file_);
-    return verifier_deps_->GetRedefinedClasses(*primary_dex_file_)[class_def_idx];
+  bool HasVerifiedClass(const std::string& cls, const DexFile& dex_file) {
+    uint16_t class_def_idx = GetClassDefIndex(cls, dex_file);
+    return verifier_deps_->GetVerifiedClasses(dex_file)[class_def_idx];
   }
 
   // Iterates over all assignability records and tries to find an entry which
   // matches the expected destination/source pair.
   bool HasAssignable(const std::string& expected_destination,
-                     const std::string& expected_source,
-                     bool expected_is_assignable) {
+                     const std::string& expected_source) const {
     for (auto& dex_dep : verifier_deps_->dex_deps_) {
       const DexFile& dex_file = *dex_dep.first;
-      auto& storage = expected_is_assignable ? dex_dep.second->assignable_types_
-                                             : dex_dep.second->unassignable_types_;
-      for (auto& entry : storage) {
-        std::string actual_destination =
-            verifier_deps_->GetStringFromId(dex_file, entry.GetDestination());
-        std::string actual_source = verifier_deps_->GetStringFromId(dex_file, entry.GetSource());
-        if ((expected_destination == actual_destination) && (expected_source == actual_source)) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  // Iterates over all class resolution records, finds an entry which matches
-  // the given class descriptor and tests its properties.
-  bool HasClass(const std::string& expected_klass,
-                bool expected_resolved,
-                const std::string& expected_access_flags = "") {
-    for (auto& dex_dep : verifier_deps_->dex_deps_) {
-      for (auto& entry : dex_dep.second->classes_) {
-        if (expected_resolved != entry.IsResolved()) {
-          continue;
-        }
-
-        std::string actual_klass = dex_dep.first->StringByTypeIdx(entry.GetDexTypeIndex());
-        if (expected_klass != actual_klass) {
-          continue;
-        }
-
-        if (expected_resolved) {
-          // Test access flags. Note that PrettyJavaAccessFlags always appends
-          // a space after the modifiers. Add it to the expected access flags.
-          std::string actual_access_flags = PrettyJavaAccessFlags(entry.GetAccessFlags());
-          if (expected_access_flags + " " != actual_access_flags) {
-            continue;
+      auto& storage = dex_dep.second->assignable_types_;
+      for (auto& set : storage) {
+        for (auto& entry : set) {
+          std::string actual_destination =
+              verifier_deps_->GetStringFromId(dex_file, entry.GetDestination());
+          std::string actual_source = verifier_deps_->GetStringFromId(dex_file, entry.GetSource());
+          if ((expected_destination == actual_destination) && (expected_source == actual_source)) {
+            return true;
           }
         }
-
-        return true;
-      }
-    }
-    return false;
-  }
-
-  // Iterates over all field resolution records, finds an entry which matches
-  // the given field class+name+type and tests its properties.
-  bool HasField(const std::string& expected_klass,
-                const std::string& expected_name,
-                const std::string& expected_type,
-                bool expected_resolved,
-                const std::string& expected_access_flags = "",
-                const std::string& expected_decl_klass = "") {
-    for (auto& dex_dep : verifier_deps_->dex_deps_) {
-      for (auto& entry : dex_dep.second->fields_) {
-        if (expected_resolved != entry.IsResolved()) {
-          continue;
-        }
-
-        const dex::FieldId& field_id = dex_dep.first->GetFieldId(entry.GetDexFieldIndex());
-
-        std::string actual_klass = dex_dep.first->StringByTypeIdx(field_id.class_idx_);
-        if (expected_klass != actual_klass) {
-          continue;
-        }
-
-        std::string actual_name = dex_dep.first->StringDataByIdx(field_id.name_idx_);
-        if (expected_name != actual_name) {
-          continue;
-        }
-
-        std::string actual_type = dex_dep.first->StringByTypeIdx(field_id.type_idx_);
-        if (expected_type != actual_type) {
-          continue;
-        }
-
-        if (expected_resolved) {
-          // Test access flags. Note that PrettyJavaAccessFlags always appends
-          // a space after the modifiers. Add it to the expected access flags.
-          std::string actual_access_flags = PrettyJavaAccessFlags(entry.GetAccessFlags());
-          if (expected_access_flags + " " != actual_access_flags) {
-            continue;
-          }
-
-          std::string actual_decl_klass = verifier_deps_->GetStringFromId(
-              *dex_dep.first, entry.GetDeclaringClassIndex());
-          if (expected_decl_klass != actual_decl_klass) {
-            continue;
-          }
-        }
-
-        return true;
-      }
-    }
-    return false;
-  }
-
-  // Iterates over all method resolution records, finds an entry which matches
-  // the given field kind+class+name+signature and tests its properties.
-  bool HasMethod(const std::string& expected_klass,
-                 const std::string& expected_name,
-                 const std::string& expected_signature,
-                 bool expect_resolved,
-                 const std::string& expected_access_flags = "",
-                 const std::string& expected_decl_klass = "") {
-    for (auto& dex_dep : verifier_deps_->dex_deps_) {
-      for (const VerifierDeps::MethodResolution& entry : dex_dep.second->methods_) {
-        if (expect_resolved != entry.IsResolved()) {
-          continue;
-        }
-
-        const dex::MethodId& method_id = dex_dep.first->GetMethodId(entry.GetDexMethodIndex());
-
-        std::string actual_klass = dex_dep.first->StringByTypeIdx(method_id.class_idx_);
-        if (expected_klass != actual_klass) {
-          continue;
-        }
-
-        std::string actual_name = dex_dep.first->StringDataByIdx(method_id.name_idx_);
-        if (expected_name != actual_name) {
-          continue;
-        }
-
-        std::string actual_signature = dex_dep.first->GetMethodSignature(method_id).ToString();
-        if (expected_signature != actual_signature) {
-          continue;
-        }
-
-        if (expect_resolved) {
-          // Test access flags. Note that PrettyJavaAccessFlags always appends
-          // a space after the modifiers. Add it to the expected access flags.
-          std::string actual_access_flags = PrettyJavaAccessFlags(entry.GetAccessFlags());
-          if (expected_access_flags + " " != actual_access_flags) {
-            continue;
-          }
-
-          std::string actual_decl_klass = verifier_deps_->GetStringFromId(
-              *dex_dep.first, entry.GetDeclaringClassIndex());
-          if (expected_decl_klass != actual_decl_klass) {
-            continue;
-          }
-        }
-
-        return true;
       }
     }
     return false;
@@ -437,36 +301,20 @@
   bool HasEachKindOfRecord() {
     bool has_strings = false;
     bool has_assignability = false;
-    bool has_classes = false;
-    bool has_fields = false;
-    bool has_methods = false;
     bool has_verified_classes = false;
     bool has_unverified_classes = false;
-    bool has_redefined_classes = false;
-    bool has_not_redefined_classes = false;
 
     for (auto& entry : verifier_deps_->dex_deps_) {
       has_strings |= !entry.second->strings_.empty();
       has_assignability |= !entry.second->assignable_types_.empty();
-      has_assignability |= !entry.second->unassignable_types_.empty();
-      has_classes |= !entry.second->classes_.empty();
-      has_fields |= !entry.second->fields_.empty();
-      has_methods |= !entry.second->methods_.empty();
       has_verified_classes |= HasBoolValue(entry.second->verified_classes_, true);
       has_unverified_classes |= HasBoolValue(entry.second->verified_classes_, false);
-      has_redefined_classes |= HasBoolValue(entry.second->redefined_classes_, true);
-      has_not_redefined_classes |= HasBoolValue(entry.second->redefined_classes_, false);
     }
 
     return has_strings &&
            has_assignability &&
-           has_classes &&
-           has_fields &&
-           has_methods &&
            has_verified_classes &&
-           has_unverified_classes &&
-           has_redefined_classes &&
-           has_not_redefined_classes;
+           has_unverified_classes;
   }
 
   // Load the dex file again with a new class loader, decode the VerifierDeps
@@ -478,7 +326,9 @@
     jobject second_loader = LoadDex("VerifierDeps");
     const auto& second_dex_files = GetDexFiles(second_loader);
 
-    VerifierDeps decoded_deps(second_dex_files, ArrayRef<const uint8_t>(buffer));
+    VerifierDeps decoded_deps(second_dex_files, /*output_only=*/ false);
+    bool parsed = decoded_deps.ParseStoredData(second_dex_files, ArrayRef<const uint8_t>(buffer));
+    CHECK(parsed);
     VerifierDeps::DexFileDeps* decoded_dex_deps =
         decoded_deps.GetDexFileDeps(*second_dex_files.front());
 
@@ -491,7 +341,6 @@
 
     return decoded_deps.ValidateDependencies(soa.Self(),
                                              new_class_loader,
-                                             std::vector<const DexFile*>(),
                                              error_msg);
   }
 
@@ -529,609 +378,107 @@
 
 TEST_F(VerifierDepsTest, Assignable_BothInBoot) {
   ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/util/TimeZone;",
-                                         /* src= */ "Ljava/util/SimpleTimeZone;",
-                                         /* is_strict= */ true,
-                                         /* is_assignable= */ true));
-  ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;", true));
-}
-
-TEST_F(VerifierDepsTest, Assignable_DestinationInBoot1) {
-  ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/net/Socket;",
-                                         /* src= */ "LMySSLSocket;",
-                                         /* is_strict= */ true,
-                                         /* is_assignable= */ true));
-  ASSERT_TRUE(HasAssignable("Ljava/net/Socket;", "Ljavax/net/ssl/SSLSocket;", true));
-}
-
-TEST_F(VerifierDepsTest, Assignable_DestinationInBoot2) {
-  ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/util/TimeZone;",
-                                         /* src= */ "LMySimpleTimeZone;",
-                                         /* is_strict= */ true,
-                                         /* is_assignable= */ true));
-  ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;", true));
-}
-
-TEST_F(VerifierDepsTest, Assignable_DestinationInBoot3) {
-  ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/util/Collection;",
-                                         /* src= */ "LMyThreadSet;",
-                                         /* is_strict= */ true,
-                                         /* is_assignable= */ true));
-  ASSERT_TRUE(HasAssignable("Ljava/util/Collection;", "Ljava/util/Set;", true));
+                                         /* src= */ "Ljava/util/SimpleTimeZone;"));
+  ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;"));
 }
 
 TEST_F(VerifierDepsTest, Assignable_BothArrays_Resolved) {
   ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "[[Ljava/util/TimeZone;",
-                                         /* src= */ "[[Ljava/util/SimpleTimeZone;",
-                                         /* is_strict= */ true,
-                                         /* is_assignable= */ true));
+                                         /* src= */ "[[Ljava/util/SimpleTimeZone;"));
   // If the component types of both arrays are resolved, we optimize the list of
   // dependencies by recording a dependency on the component types.
-  ASSERT_FALSE(HasAssignable("[[Ljava/util/TimeZone;", "[[Ljava/util/SimpleTimeZone;", true));
-  ASSERT_FALSE(HasAssignable("[Ljava/util/TimeZone;", "[Ljava/util/SimpleTimeZone;", true));
-  ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;", true));
-}
-
-TEST_F(VerifierDepsTest, NotAssignable_BothInBoot) {
-  ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/lang/Exception;",
-                                         /* src= */ "Ljava/util/SimpleTimeZone;",
-                                         /* is_strict= */ true,
-                                         /* is_assignable= */ false));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/util/SimpleTimeZone;", false));
-}
-
-TEST_F(VerifierDepsTest, NotAssignable_DestinationInBoot1) {
-  ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/lang/Exception;",
-                                         /* src= */ "LMySSLSocket;",
-                                         /* is_strict= */ true,
-                                         /* is_assignable= */ false));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljavax/net/ssl/SSLSocket;", false));
-}
-
-TEST_F(VerifierDepsTest, NotAssignable_DestinationInBoot2) {
-  ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/lang/Exception;",
-                                         /* src= */ "LMySimpleTimeZone;",
-                                         /* is_strict= */ true,
-                                         /* is_assignable= */ false));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/util/SimpleTimeZone;", false));
-}
-
-TEST_F(VerifierDepsTest, NotAssignable_BothArrays) {
-  ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "[Ljava/lang/Exception;",
-                                         /* src= */ "[Ljava/util/SimpleTimeZone;",
-                                         /* is_strict= */ true,
-                                         /* is_assignable= */ false));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/util/SimpleTimeZone;", false));
-}
-
-TEST_F(VerifierDepsTest, ArgumentType_ResolvedClass) {
-  ASSERT_TRUE(VerifyMethod("ArgumentType_ResolvedClass"));
-  ASSERT_TRUE(HasClass("Ljava/lang/Thread;", true, "public"));
-}
-
-TEST_F(VerifierDepsTest, ArgumentType_UnresolvedClass) {
-  ASSERT_TRUE(VerifyMethod("ArgumentType_UnresolvedClass"));
-  ASSERT_TRUE(HasClass("LUnresolvedClass;", false));
-}
-
-TEST_F(VerifierDepsTest, ArgumentType_UnresolvedSuper) {
-  ASSERT_TRUE(VerifyMethod("ArgumentType_UnresolvedSuper"));
-  ASSERT_TRUE(HasClass("LMySetWithUnresolvedSuper;", false));
+  ASSERT_FALSE(HasAssignable("[[Ljava/util/TimeZone;", "[[Ljava/util/SimpleTimeZone;"));
+  ASSERT_FALSE(HasAssignable("[Ljava/util/TimeZone;", "[Ljava/util/SimpleTimeZone;"));
+  ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;"));
 }
 
 TEST_F(VerifierDepsTest, ReturnType_Reference) {
   ASSERT_TRUE(VerifyMethod("ReturnType_Reference"));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/lang/IllegalStateException;", true));
-}
-
-TEST_F(VerifierDepsTest, ReturnType_Array) {
-  ASSERT_FALSE(VerifyMethod("ReturnType_Array"));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Integer;", "Ljava/lang/IllegalStateException;", false));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/lang/IllegalStateException;"));
 }
 
 TEST_F(VerifierDepsTest, InvokeArgumentType) {
   ASSERT_TRUE(VerifyMethod("InvokeArgumentType"));
-  ASSERT_TRUE(HasClass("Ljava/text/SimpleDateFormat;", true, "public"));
-  ASSERT_TRUE(HasClass("Ljava/util/SimpleTimeZone;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljava/text/SimpleDateFormat;",
-                        "setTimeZone",
-                        "(Ljava/util/TimeZone;)V",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/text/DateFormat;"));
-  ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;", true));
+  ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;"));
 }
 
 TEST_F(VerifierDepsTest, MergeTypes_RegisterLines) {
   ASSERT_TRUE(VerifyMethod("MergeTypes_RegisterLines"));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;", true));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "LMySocketTimeoutException;"));
   ASSERT_TRUE(HasAssignable(
-      "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;", true));
+      "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;"));
 }
 
 TEST_F(VerifierDepsTest, MergeTypes_IfInstanceOf) {
   ASSERT_TRUE(VerifyMethod("MergeTypes_IfInstanceOf"));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;", true));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;"));
   ASSERT_TRUE(HasAssignable(
-      "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;", true));
-  ASSERT_TRUE(HasAssignable("Ljava/net/SocketTimeoutException;", "Ljava/lang/Exception;", false));
+      "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;"));
 }
 
 TEST_F(VerifierDepsTest, MergeTypes_Unresolved) {
   ASSERT_TRUE(VerifyMethod("MergeTypes_Unresolved"));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;", true));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;"));
   ASSERT_TRUE(HasAssignable(
-      "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;", true));
-}
-
-TEST_F(VerifierDepsTest, ConstClass_Resolved) {
-  ASSERT_TRUE(VerifyMethod("ConstClass_Resolved"));
-  ASSERT_TRUE(HasClass("Ljava/lang/IllegalStateException;", true, "public"));
-}
-
-TEST_F(VerifierDepsTest, ConstClass_Unresolved) {
-  ASSERT_FALSE(VerifyMethod("ConstClass_Unresolved"));
-  ASSERT_TRUE(HasClass("LUnresolvedClass;", false));
-}
-
-TEST_F(VerifierDepsTest, CheckCast_Resolved) {
-  ASSERT_TRUE(VerifyMethod("CheckCast_Resolved"));
-  ASSERT_TRUE(HasClass("Ljava/lang/IllegalStateException;", true, "public"));
-}
-
-TEST_F(VerifierDepsTest, CheckCast_Unresolved) {
-  ASSERT_FALSE(VerifyMethod("CheckCast_Unresolved"));
-  ASSERT_TRUE(HasClass("LUnresolvedClass;", false));
-}
-
-TEST_F(VerifierDepsTest, InstanceOf_Resolved) {
-  ASSERT_TRUE(VerifyMethod("InstanceOf_Resolved"));
-  ASSERT_TRUE(HasClass("Ljava/lang/IllegalStateException;", true, "public"));
-}
-
-TEST_F(VerifierDepsTest, InstanceOf_Unresolved) {
-  ASSERT_FALSE(VerifyMethod("InstanceOf_Unresolved"));
-  ASSERT_TRUE(HasClass("LUnresolvedClass;", false));
-}
-
-TEST_F(VerifierDepsTest, NewInstance_Resolved) {
-  ASSERT_TRUE(VerifyMethod("NewInstance_Resolved"));
-  ASSERT_TRUE(HasClass("Ljava/lang/IllegalStateException;", true, "public"));
-}
-
-TEST_F(VerifierDepsTest, NewInstance_Unresolved) {
-  ASSERT_FALSE(VerifyMethod("NewInstance_Unresolved"));
-  ASSERT_TRUE(HasClass("LUnresolvedClass;", false));
-}
-
-TEST_F(VerifierDepsTest, NewArray_Unresolved) {
-  ASSERT_FALSE(VerifyMethod("NewArray_Unresolved"));
-  ASSERT_TRUE(HasClass("[LUnresolvedClass;", false));
+      "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;"));
 }
 
 TEST_F(VerifierDepsTest, Throw) {
   ASSERT_TRUE(VerifyMethod("Throw"));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/lang/IllegalStateException;", true));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/lang/IllegalStateException;"));
 }
 
 TEST_F(VerifierDepsTest, MoveException_Resolved) {
   ASSERT_TRUE(VerifyMethod("MoveException_Resolved"));
-  ASSERT_TRUE(HasClass("Ljava/io/InterruptedIOException;", true, "public"));
-  ASSERT_TRUE(HasClass("Ljava/net/SocketTimeoutException;", true, "public"));
-  ASSERT_TRUE(HasClass("Ljava/util/zip/ZipException;", true, "public"));
 
   // Testing that all exception types are assignable to Throwable.
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/io/InterruptedIOException;", true));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/net/SocketTimeoutException;", true));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/util/zip/ZipException;", true));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/io/InterruptedIOException;"));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/net/SocketTimeoutException;"));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/util/zip/ZipException;"));
 
   // Testing that the merge type is assignable to Throwable.
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/io/IOException;", true));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/io/IOException;"));
 
   // Merging of exception types.
-  ASSERT_TRUE(HasAssignable("Ljava/io/IOException;", "Ljava/io/InterruptedIOException;", true));
-  ASSERT_TRUE(HasAssignable("Ljava/io/IOException;", "Ljava/util/zip/ZipException;", true));
+  ASSERT_TRUE(HasAssignable("Ljava/io/IOException;", "Ljava/io/InterruptedIOException;"));
+  ASSERT_TRUE(HasAssignable("Ljava/io/IOException;", "Ljava/util/zip/ZipException;"));
   ASSERT_TRUE(HasAssignable(
-      "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;", true));
-}
-
-TEST_F(VerifierDepsTest, MoveException_Unresolved) {
-  ASSERT_FALSE(VerifyMethod("MoveException_Unresolved"));
-  ASSERT_TRUE(HasClass("LUnresolvedException;", false));
-}
-
-TEST_F(VerifierDepsTest, StaticField_Resolved_DeclaredInReferenced) {
-  ASSERT_TRUE(VerifyMethod("StaticField_Resolved_DeclaredInReferenced"));
-  ASSERT_TRUE(HasClass("Ljava/lang/System;", true, "public"));
-  ASSERT_TRUE(HasField("Ljava/lang/System;",
-                       "out",
-                       "Ljava/io/PrintStream;",
-                       true,
-                       "public static",
-                       "Ljava/lang/System;"));
-}
-
-TEST_F(VerifierDepsTest, StaticField_Resolved_DeclaredInSuperclass1) {
-  ASSERT_TRUE(VerifyMethod("StaticField_Resolved_DeclaredInSuperclass1"));
-  ASSERT_TRUE(HasClass("Ljava/util/SimpleTimeZone;", true, "public"));
-  ASSERT_TRUE(HasField(
-      "Ljava/util/SimpleTimeZone;", "LONG", "I", true, "public static", "Ljava/util/TimeZone;"));
-}
-
-TEST_F(VerifierDepsTest, StaticField_Resolved_DeclaredInSuperclass2) {
-  ASSERT_TRUE(VerifyMethod("StaticField_Resolved_DeclaredInSuperclass2"));
-  ASSERT_TRUE(HasField(
-      "LMySimpleTimeZone;", "SHORT", "I", true, "public static", "Ljava/util/TimeZone;"));
-}
-
-TEST_F(VerifierDepsTest, StaticField_Resolved_DeclaredInInterface1) {
-  ASSERT_TRUE(VerifyMethod("StaticField_Resolved_DeclaredInInterface1"));
-  ASSERT_TRUE(HasClass("Ljavax/xml/transform/dom/DOMResult;", true, "public"));
-  ASSERT_TRUE(HasField("Ljavax/xml/transform/dom/DOMResult;",
-                       "PI_ENABLE_OUTPUT_ESCAPING",
-                       "Ljava/lang/String;",
-                       true,
-                       "public static",
-                       "Ljavax/xml/transform/Result;"));
-}
-
-TEST_F(VerifierDepsTest, StaticField_Resolved_DeclaredInInterface2) {
-  ASSERT_TRUE(VerifyMethod("StaticField_Resolved_DeclaredInInterface2"));
-  ASSERT_TRUE(HasField("LMyDOMResult;",
-                       "PI_ENABLE_OUTPUT_ESCAPING",
-                       "Ljava/lang/String;",
-                       true,
-                       "public static",
-                       "Ljavax/xml/transform/Result;"));
-}
-
-TEST_F(VerifierDepsTest, StaticField_Resolved_DeclaredInInterface3) {
-  ASSERT_TRUE(VerifyMethod("StaticField_Resolved_DeclaredInInterface3"));
-  ASSERT_TRUE(HasField("LMyResult;",
-                       "PI_ENABLE_OUTPUT_ESCAPING",
-                       "Ljava/lang/String;",
-                       true,
-                       "public static",
-                       "Ljavax/xml/transform/Result;"));
-}
-
-TEST_F(VerifierDepsTest, StaticField_Resolved_DeclaredInInterface4) {
-  ASSERT_TRUE(VerifyMethod("StaticField_Resolved_DeclaredInInterface4"));
-  ASSERT_TRUE(HasField("LMyDocument;",
-                       "ELEMENT_NODE",
-                       "S",
-                       true,
-                       "public static",
-                       "Lorg/w3c/dom/Node;"));
-}
-
-TEST_F(VerifierDepsTest, StaticField_Unresolved_ReferrerInBoot) {
-  ASSERT_TRUE(VerifyMethod("StaticField_Unresolved_ReferrerInBoot"));
-  ASSERT_TRUE(HasClass("Ljava/util/TimeZone;", true, "public"));
-  ASSERT_TRUE(HasField("Ljava/util/TimeZone;", "x", "I", false));
-}
-
-TEST_F(VerifierDepsTest, StaticField_Unresolved_ReferrerInDex) {
-  ASSERT_TRUE(VerifyMethod("StaticField_Unresolved_ReferrerInDex"));
-  ASSERT_TRUE(HasField("LMyThreadSet;", "x", "I", false));
+      "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;"));
 }
 
 TEST_F(VerifierDepsTest, InstanceField_Resolved_DeclaredInReferenced) {
   ASSERT_TRUE(VerifyMethod("InstanceField_Resolved_DeclaredInReferenced"));
-  ASSERT_TRUE(HasClass("Ljava/io/InterruptedIOException;", true, "public"));
-  ASSERT_TRUE(HasField("Ljava/io/InterruptedIOException;",
-                       "bytesTransferred",
-                       "I",
-                       true,
-                       "public",
-                       "Ljava/io/InterruptedIOException;"));
   ASSERT_TRUE(HasAssignable(
-      "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;", true));
+      "Ljava/io/InterruptedIOException;", "LMySocketTimeoutException;"));
 }
 
 TEST_F(VerifierDepsTest, InstanceField_Resolved_DeclaredInSuperclass1) {
   ASSERT_TRUE(VerifyMethod("InstanceField_Resolved_DeclaredInSuperclass1"));
-  ASSERT_TRUE(HasClass("Ljava/net/SocketTimeoutException;", true, "public"));
-  ASSERT_TRUE(HasField("Ljava/net/SocketTimeoutException;",
-                       "bytesTransferred",
-                       "I",
-                       true,
-                       "public",
-                       "Ljava/io/InterruptedIOException;"));
   ASSERT_TRUE(HasAssignable(
-      "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;", true));
+      "Ljava/io/InterruptedIOException;", "LMySocketTimeoutException;"));
 }
 
 TEST_F(VerifierDepsTest, InstanceField_Resolved_DeclaredInSuperclass2) {
   ASSERT_TRUE(VerifyMethod("InstanceField_Resolved_DeclaredInSuperclass2"));
-  ASSERT_TRUE(HasField("LMySocketTimeoutException;",
-                       "bytesTransferred",
-                       "I",
-                       true,
-                       "public",
-                       "Ljava/io/InterruptedIOException;"));
   ASSERT_TRUE(HasAssignable(
-      "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;", true));
-}
-
-TEST_F(VerifierDepsTest, InstanceField_Unresolved_ReferrerInBoot) {
-  ASSERT_TRUE(VerifyMethod("InstanceField_Unresolved_ReferrerInBoot"));
-  ASSERT_TRUE(HasClass("Ljava/io/InterruptedIOException;", true, "public"));
-  ASSERT_TRUE(HasField("Ljava/io/InterruptedIOException;", "x", "I", false));
-}
-
-TEST_F(VerifierDepsTest, InstanceField_Unresolved_ReferrerInDex) {
-  ASSERT_TRUE(VerifyMethod("InstanceField_Unresolved_ReferrerInDex"));
-  ASSERT_TRUE(HasField("LMyThreadSet;", "x", "I", false));
-}
-
-TEST_F(VerifierDepsTest, InvokeStatic_Resolved_DeclaredInReferenced) {
-  ASSERT_TRUE(VerifyMethod("InvokeStatic_Resolved_DeclaredInReferenced"));
-  ASSERT_TRUE(HasClass("Ljava/net/Socket;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljava/net/Socket;",
-                        "setSocketImplFactory",
-                        "(Ljava/net/SocketImplFactory;)V",
-                        /* expect_resolved= */ true,
-                        "public static",
-                        "Ljava/net/Socket;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeStatic_Resolved_DeclaredInSuperclass1) {
-  ASSERT_TRUE(VerifyMethod("InvokeStatic_Resolved_DeclaredInSuperclass1"));
-  ASSERT_TRUE(HasClass("Ljavax/net/ssl/SSLSocket;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljavax/net/ssl/SSLSocket;",
-                        "setSocketImplFactory",
-                        "(Ljava/net/SocketImplFactory;)V",
-                        /* expect_resolved= */ true,
-                        "public static",
-                        "Ljava/net/Socket;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeStatic_Resolved_DeclaredInSuperclass2) {
-  ASSERT_TRUE(VerifyMethod("InvokeStatic_Resolved_DeclaredInSuperclass2"));
-  ASSERT_TRUE(HasMethod("LMySSLSocket;",
-                        "setSocketImplFactory",
-                        "(Ljava/net/SocketImplFactory;)V",
-                        /* expect_resolved= */ true,
-                        "public static",
-                        "Ljava/net/Socket;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeStatic_DeclaredInInterface1) {
-  ASSERT_TRUE(VerifyMethod("InvokeStatic_DeclaredInInterface1"));
-  ASSERT_TRUE(HasClass("Ljava/util/Map$Entry;", true, "public interface"));
-  ASSERT_TRUE(HasMethod("Ljava/util/Map$Entry;",
-                        "comparingByKey",
-                        "()Ljava/util/Comparator;",
-                        /* expect_resolved= */ true,
-                        "public static",
-                        "Ljava/util/Map$Entry;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeStatic_DeclaredInInterface2) {
-  ASSERT_FALSE(VerifyMethod("InvokeStatic_DeclaredInInterface2"));
-  ASSERT_TRUE(HasClass("Ljava/util/AbstractMap$SimpleEntry;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljava/util/AbstractMap$SimpleEntry;",
-                        "comparingByKey",
-                        "()Ljava/util/Comparator;",
-                        /* expect_resolved= */ false));
-}
-
-TEST_F(VerifierDepsTest, InvokeStatic_Unresolved1) {
-  ASSERT_FALSE(VerifyMethod("InvokeStatic_Unresolved1"));
-  ASSERT_TRUE(HasClass("Ljavax/net/ssl/SSLSocket;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljavax/net/ssl/SSLSocket;",
-                        "x",
-                        "()V",
-                        /* expect_resolved= */ false));
-}
-
-TEST_F(VerifierDepsTest, InvokeStatic_Unresolved2) {
-  ASSERT_FALSE(VerifyMethod("InvokeStatic_Unresolved2"));
-  ASSERT_TRUE(HasMethod("LMySSLSocket;",
-                        "x",
-                        "()V",
-                        /* expect_resolved= */ false));
-}
-
-TEST_F(VerifierDepsTest, InvokeDirect_Resolved_DeclaredInReferenced) {
-  ASSERT_TRUE(VerifyMethod("InvokeDirect_Resolved_DeclaredInReferenced"));
-  ASSERT_TRUE(HasClass("Ljava/net/Socket;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljava/net/Socket;",
-                        "<init>",
-                        "()V",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/net/Socket;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeDirect_Resolved_DeclaredInSuperclass1) {
-  ASSERT_FALSE(VerifyMethod("InvokeDirect_Resolved_DeclaredInSuperclass1"));
-  ASSERT_TRUE(HasClass("Ljavax/net/ssl/SSLSocket;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljavax/net/ssl/SSLSocket;",
-                        "checkOldImpl",
-                        "()V",
-                        /* expect_resolved= */ true,
-                        "private",
-                        "Ljava/net/Socket;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeDirect_Resolved_DeclaredInSuperclass2) {
-  ASSERT_FALSE(VerifyMethod("InvokeDirect_Resolved_DeclaredInSuperclass2"));
-  ASSERT_TRUE(HasMethod("LMySSLSocket;",
-                        "checkOldImpl",
-                        "()V",
-                        /* expect_resolved= */ true,
-                        "private",
-                        "Ljava/net/Socket;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeDirect_Unresolved1) {
-  ASSERT_FALSE(VerifyMethod("InvokeDirect_Unresolved1"));
-  ASSERT_TRUE(HasClass("Ljavax/net/ssl/SSLSocket;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljavax/net/ssl/SSLSocket;",
-                        "x",
-                        "()V",
-                        /* expect_resolved= */ false));
-}
-
-TEST_F(VerifierDepsTest, InvokeDirect_Unresolved2) {
-  ASSERT_FALSE(VerifyMethod("InvokeDirect_Unresolved2"));
-  ASSERT_TRUE(HasMethod("LMySSLSocket;",
-                        "x",
-                        "()V",
-                        /* expect_resolved= */ false));
+      "Ljava/io/InterruptedIOException;", "LMySocketTimeoutException;"));
 }
 
 TEST_F(VerifierDepsTest, InvokeVirtual_Resolved_DeclaredInReferenced) {
   ASSERT_TRUE(VerifyMethod("InvokeVirtual_Resolved_DeclaredInReferenced"));
-  ASSERT_TRUE(HasClass("Ljava/lang/Throwable;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljava/lang/Throwable;",
-                        "getMessage",
-                        "()Ljava/lang/String;",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/lang/Throwable;"));
   // Type dependency on `this` argument.
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/net/SocketTimeoutException;", true));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "LMySocketTimeoutException;"));
 }
 
 TEST_F(VerifierDepsTest, InvokeVirtual_Resolved_DeclaredInSuperclass1) {
   ASSERT_TRUE(VerifyMethod("InvokeVirtual_Resolved_DeclaredInSuperclass1"));
-  ASSERT_TRUE(HasClass("Ljava/io/InterruptedIOException;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljava/io/InterruptedIOException;",
-                        "getMessage",
-                        "()Ljava/lang/String;",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/lang/Throwable;"));
   // Type dependency on `this` argument.
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/net/SocketTimeoutException;", true));
-}
-
-TEST_F(VerifierDepsTest, InvokeVirtual_Resolved_DeclaredInSuperclass2) {
-  ASSERT_TRUE(VerifyMethod("InvokeVirtual_Resolved_DeclaredInSuperclass2"));
-  ASSERT_TRUE(HasMethod("LMySocketTimeoutException;",
-                        "getMessage",
-                        "()Ljava/lang/String;",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/lang/Throwable;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeVirtual_Resolved_DeclaredInSuperinterface) {
-  ASSERT_TRUE(VerifyMethod("InvokeVirtual_Resolved_DeclaredInSuperinterface"));
-  ASSERT_TRUE(HasMethod("LMyThreadSet;",
-                        "size",
-                        "()I",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/util/Set;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeVirtual_Unresolved1) {
-  ASSERT_FALSE(VerifyMethod("InvokeVirtual_Unresolved1"));
-  ASSERT_TRUE(HasClass("Ljava/io/InterruptedIOException;", true, "public"));
-  ASSERT_TRUE(HasMethod("Ljava/io/InterruptedIOException;",
-                        "x",
-                        "()V",
-                        /* expect_resolved= */ false));
-}
-
-TEST_F(VerifierDepsTest, InvokeVirtual_Unresolved2) {
-  ASSERT_FALSE(VerifyMethod("InvokeVirtual_Unresolved2"));
-  ASSERT_TRUE(HasMethod("LMySocketTimeoutException;",
-                        "x",
-                        "()V",
-                        /* expect_resolved= */ false));
-}
-
-TEST_F(VerifierDepsTest, InvokeInterface_Resolved_DeclaredInReferenced) {
-  ASSERT_TRUE(VerifyMethod("InvokeInterface_Resolved_DeclaredInReferenced"));
-  ASSERT_TRUE(HasClass("Ljava/lang/Runnable;", true, "public interface"));
-  ASSERT_TRUE(HasMethod("Ljava/lang/Runnable;",
-                        "run",
-                        "()V",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/lang/Runnable;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeInterface_Resolved_DeclaredInSuperclass) {
-  ASSERT_FALSE(VerifyMethod("InvokeInterface_Resolved_DeclaredInSuperclass"));
-  // TODO: Maybe we should not record dependency if the invoke type does not match the lookup type.
-  ASSERT_TRUE(HasMethod("LMyThread;",
-                        "join",
-                        "()V",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/lang/Thread;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeInterface_Resolved_DeclaredInSuperinterface1) {
-  ASSERT_FALSE(VerifyMethod("InvokeInterface_Resolved_DeclaredInSuperinterface1"));
-  // TODO: Maybe we should not record dependency if the invoke type does not match the lookup type.
-  ASSERT_TRUE(HasMethod("LMyThreadSet;",
-                        "run",
-                        "()V",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/lang/Thread;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeInterface_Resolved_DeclaredInSuperinterface2) {
-  ASSERT_FALSE(VerifyMethod("InvokeInterface_Resolved_DeclaredInSuperinterface2"));
-  ASSERT_TRUE(HasMethod("LMyThreadSet;",
-                        "isEmpty",
-                        "()Z",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/util/Set;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeInterface_Unresolved1) {
-  ASSERT_FALSE(VerifyMethod("InvokeInterface_Unresolved1"));
-  ASSERT_TRUE(HasClass("Ljava/lang/Runnable;", true, "public interface"));
-  ASSERT_TRUE(HasMethod("Ljava/lang/Runnable;",
-                        "x",
-                        "()V",
-                        /* expect_resolved= */ false));
-}
-
-TEST_F(VerifierDepsTest, InvokeInterface_Unresolved2) {
-  ASSERT_FALSE(VerifyMethod("InvokeInterface_Unresolved2"));
-  ASSERT_TRUE(HasMethod("LMyThreadSet;", "x", "()V", /* expect_resolved= */ false));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "LMySocketTimeoutException;"));
 }
 
 TEST_F(VerifierDepsTest, InvokeSuper_ThisAssignable) {
   ASSERT_TRUE(VerifyMethod("InvokeSuper_ThisAssignable"));
-  ASSERT_TRUE(HasClass("Ljava/lang/Runnable;", true, "public interface"));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Runnable;", "Ljava/lang/Thread;", true));
-  ASSERT_TRUE(HasMethod("Ljava/lang/Runnable;",
-                        "run",
-                        "()V",
-                        /* expect_resolved= */ true,
-                        "public",
-                        "Ljava/lang/Runnable;"));
-}
-
-TEST_F(VerifierDepsTest, InvokeSuper_ThisNotAssignable) {
-  ASSERT_FALSE(VerifyMethod("InvokeSuper_ThisNotAssignable"));
-  ASSERT_TRUE(HasClass("Ljava/lang/Integer;", true, "public"));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Integer;", "Ljava/lang/Thread;", false));
-  ASSERT_TRUE(HasMethod("Ljava/lang/Integer;",
-                        "intValue", "()I",
-                        /* expect_resolved= */ true,
-                        "public", "Ljava/lang/Integer;"));
-}
-
-TEST_F(VerifierDepsTest, ArgumentType_ResolvedReferenceArray) {
-  ASSERT_TRUE(VerifyMethod("ArgumentType_ResolvedReferenceArray"));
-  ASSERT_TRUE(HasClass("[Ljava/lang/Thread;", true, "public"));
-}
-
-TEST_F(VerifierDepsTest, NewArray_Resolved) {
-  ASSERT_TRUE(VerifyMethod("NewArray_Resolved"));
-  ASSERT_TRUE(HasClass("[Ljava/lang/IllegalStateException;", true, "public"));
+  ASSERT_TRUE(HasAssignable("Ljava/lang/Runnable;", "LMain;"));
 }
 
 TEST_F(VerifierDepsTest, EncodeDecode) {
@@ -1144,7 +491,9 @@
   verifier_deps_->Encode(dex_files_, &buffer);
   ASSERT_FALSE(buffer.empty());
 
-  VerifierDeps decoded_deps(dex_files_, ArrayRef<const uint8_t>(buffer));
+  VerifierDeps decoded_deps(dex_files_, /*output_only=*/ false);
+  bool parsed = decoded_deps.ParseStoredData(dex_files_, ArrayRef<const uint8_t>(buffer));
+  ASSERT_TRUE(parsed);
   ASSERT_TRUE(verifier_deps_->Equals(decoded_deps));
 }
 
@@ -1170,7 +519,9 @@
   }
 
   // Dump the new verifier deps to ensure it can properly read the data.
-  VerifierDeps decoded_deps(dex_files, ArrayRef<const uint8_t>(buffer));
+  VerifierDeps decoded_deps(dex_files, /*output_only=*/ false);
+  bool parsed = decoded_deps.ParseStoredData(dex_files, ArrayRef<const uint8_t>(buffer));
+  ASSERT_TRUE(parsed);
   std::ostringstream stream;
   VariableIndentationOutputStream os(&stream);
   decoded_deps.Dump(&os);
@@ -1183,24 +534,10 @@
   ASSERT_TRUE(HasUnverifiedClass("LMain;"));
   // Test that a class with hard failure is recorded.
   ASSERT_TRUE(HasUnverifiedClass("LMyVerificationFailure;"));
-  // Test that a class with unresolved super is recorded.
-  ASSERT_TRUE(HasUnverifiedClass("LMyClassWithNoSuper;"));
   // Test that a class with unresolved super and hard failure is recorded.
   ASSERT_TRUE(HasUnverifiedClass("LMyClassWithNoSuperButFailures;"));
-}
-
-TEST_F(VerifierDepsTest, RedefinedClass) {
-  VerifyDexFile();
-  // Test that a class which redefines a boot classpath class has dependencies recorded.
-  ASSERT_TRUE(HasRedefinedClass("Ljava/net/SocketTimeoutException;"));
-  // These come from test case InstanceField_Resolved_DeclaredInSuperclass1.
-  ASSERT_TRUE(HasClass("Ljava/net/SocketTimeoutException;", true, "public"));
-  ASSERT_TRUE(HasField("Ljava/net/SocketTimeoutException;",
-                       "bytesTransferred",
-                       "I",
-                       true,
-                       "public",
-                       "Ljava/io/InterruptedIOException;"));
+  // Test that a class with unresolved super can be verified.
+  ASSERT_TRUE(HasVerifiedClass("LMyClassWithNoSuper;"));
 }
 
 TEST_F(VerifierDepsTest, UnverifiedOrder) {
@@ -1210,25 +547,23 @@
   ASSERT_GT(dex_files.size(), 0u);
   const DexFile* dex_file = dex_files[0];
   VerifierDeps deps1(dex_files);
-  Thread* const self = Thread::Current();
-  ASSERT_TRUE(self->GetVerifierDeps() == nullptr);
-  self->SetVerifierDeps(&deps1);
-  deps1.MaybeRecordVerificationStatus(*dex_file,
+  deps1.MaybeRecordVerificationStatus(&deps1,
+                                      *dex_file,
                                       dex_file->GetClassDef(0u),
                                       verifier::FailureKind::kHardFailure);
-  deps1.MaybeRecordVerificationStatus(*dex_file,
+  deps1.MaybeRecordVerificationStatus(&deps1,
+                                      *dex_file,
                                       dex_file->GetClassDef(1u),
                                       verifier::FailureKind::kHardFailure);
   VerifierDeps deps2(dex_files);
-  self->SetVerifierDeps(nullptr);
-  self->SetVerifierDeps(&deps2);
-  deps2.MaybeRecordVerificationStatus(*dex_file,
+  deps2.MaybeRecordVerificationStatus(&deps2,
+                                      *dex_file,
                                       dex_file->GetClassDef(1u),
                                       verifier::FailureKind::kHardFailure);
-  deps2.MaybeRecordVerificationStatus(*dex_file,
+  deps2.MaybeRecordVerificationStatus(&deps2,
+                                      *dex_file,
                                       dex_file->GetClassDef(0u),
                                       verifier::FailureKind::kHardFailure);
-  self->SetVerifierDeps(nullptr);
   std::vector<uint8_t> buffer1;
   deps1.Encode(dex_files, &buffer1);
   std::vector<uint8_t> buffer2;
@@ -1254,159 +589,6 @@
   // Check that dependencies are satisfied after decoding `buffer`.
   ASSERT_TRUE(RunValidation([](VerifierDeps::DexFileDeps&) {}, buffer, &error_msg))
       << error_msg;
-
-  // Mess with the dependencies to make sure we catch any change and fail to verify.
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        deps.assignable_types_.insert(*deps.unassignable_types_.begin());
-      }, buffer, &error_msg));
-
-  // Mess with the unassignable_types.
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        deps.unassignable_types_.insert(*deps.assignable_types_.begin());
-      }, buffer, &error_msg));
-
-  // Mess with classes.
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        for (const auto& entry : deps.classes_) {
-          if (entry.IsResolved()) {
-            deps.classes_.insert(VerifierDeps::ClassResolution(
-                entry.GetDexTypeIndex(), VerifierDeps::kUnresolvedMarker));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any resolved classes";
-        UNREACHABLE();
-      }, buffer, &error_msg));
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        for (const auto& entry : deps.classes_) {
-          if (!entry.IsResolved()) {
-            deps.classes_.insert(VerifierDeps::ClassResolution(
-                entry.GetDexTypeIndex(), VerifierDeps::kUnresolvedMarker - 1));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any unresolved classes";
-        UNREACHABLE();
-      }, buffer, &error_msg));
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        for (const auto& entry : deps.classes_) {
-          if (entry.IsResolved()) {
-            deps.classes_.insert(VerifierDeps::ClassResolution(
-                entry.GetDexTypeIndex(), entry.GetAccessFlags() - 1));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any resolved classes";
-        UNREACHABLE();
-      }, buffer, &error_msg));
-
-  // Mess with fields.
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        for (const auto& entry : deps.fields_) {
-          if (entry.IsResolved()) {
-            deps.fields_.insert(VerifierDeps::FieldResolution(entry.GetDexFieldIndex(),
-                                                              VerifierDeps::kUnresolvedMarker,
-                                                              entry.GetDeclaringClassIndex()));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any resolved fields";
-        UNREACHABLE();
-      }, buffer, &error_msg));
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        for (const auto& entry : deps.fields_) {
-          if (!entry.IsResolved()) {
-            constexpr dex::StringIndex kStringIndexZero(0);  // We know there is a class there.
-            deps.fields_.insert(VerifierDeps::FieldResolution(0 /* we know there is a field there */,
-                                                              VerifierDeps::kUnresolvedMarker - 1,
-                                                              kStringIndexZero));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any unresolved fields";
-        UNREACHABLE();
-      }, buffer, &error_msg));
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        for (const auto& entry : deps.fields_) {
-          if (entry.IsResolved()) {
-            deps.fields_.insert(VerifierDeps::FieldResolution(entry.GetDexFieldIndex(),
-                                                              entry.GetAccessFlags() - 1,
-                                                              entry.GetDeclaringClassIndex()));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any resolved fields";
-        UNREACHABLE();
-      }, buffer, &error_msg));
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        for (const auto& entry : deps.fields_) {
-          constexpr dex::StringIndex kNewTypeIndex(0);
-          if (entry.GetDeclaringClassIndex() != kNewTypeIndex) {
-            deps.fields_.insert(VerifierDeps::FieldResolution(entry.GetDexFieldIndex(),
-                                                              entry.GetAccessFlags(),
-                                                              kNewTypeIndex));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any suitable fields";
-        UNREACHABLE();
-      }, buffer, &error_msg));
-
-  // Mess with methods.
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        std::set<VerifierDeps::MethodResolution>* methods = &deps.methods_;
-        for (const auto& entry : *methods) {
-          if (entry.IsResolved()) {
-            methods->insert(VerifierDeps::MethodResolution(entry.GetDexMethodIndex(),
-                                                          VerifierDeps::kUnresolvedMarker,
-                                                          entry.GetDeclaringClassIndex()));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any resolved methods";
-        UNREACHABLE();
-      }, buffer, &error_msg));
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        std::set<VerifierDeps::MethodResolution>* methods = &deps.methods_;
-        for (const auto& entry : *methods) {
-          if (!entry.IsResolved()) {
-            constexpr dex::StringIndex kStringIndexZero(0);  // We know there is a class there.
-            methods->insert(VerifierDeps::MethodResolution(0 /* we know there is a method there */,
-                                                          VerifierDeps::kUnresolvedMarker - 1,
-                                                          kStringIndexZero));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any unresolved methods";
-        UNREACHABLE();
-      }, buffer, &error_msg));
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        std::set<VerifierDeps::MethodResolution>* methods = &deps.methods_;
-        for (const auto& entry : *methods) {
-          if (entry.IsResolved()) {
-            methods->insert(VerifierDeps::MethodResolution(entry.GetDexMethodIndex(),
-                                                          entry.GetAccessFlags() - 1,
-                                                          entry.GetDeclaringClassIndex()));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any resolved methods";
-        UNREACHABLE();
-      }, buffer, &error_msg));
-  ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) {
-        std::set<VerifierDeps::MethodResolution>* methods = &deps.methods_;
-        for (const auto& entry : *methods) {
-          constexpr dex::StringIndex kNewTypeIndex(0);
-          if (entry.IsResolved() && entry.GetDeclaringClassIndex() != kNewTypeIndex) {
-            methods->insert(VerifierDeps::MethodResolution(entry.GetDexMethodIndex(),
-                                                          entry.GetAccessFlags(),
-                                                          kNewTypeIndex));
-            return;
-          }
-        }
-        LOG(FATAL) << "Could not find any suitable methods";
-        UNREACHABLE();
-      }, buffer, &error_msg));
 }
 
 TEST_F(VerifierDepsTest, CompilerDriver) {
@@ -1430,21 +612,9 @@
         ScopedObjectAccess soa(Thread::Current());
         LoadDexFile(soa, "VerifierDeps", multi);
       }
-      verifier::VerifierDeps decoded_deps(dex_files_, ArrayRef<const uint8_t>(buffer));
-      if (verify_failure) {
-        // Just taint the decoded VerifierDeps with one invalid entry.
-        VerifierDeps::DexFileDeps* deps = decoded_deps.GetDexFileDeps(*primary_dex_file_);
-        bool found = false;
-        for (const auto& entry : deps->classes_) {
-          if (entry.IsResolved()) {
-            deps->classes_.insert(VerifierDeps::ClassResolution(
-                entry.GetDexTypeIndex(), VerifierDeps::kUnresolvedMarker));
-            found = true;
-            break;
-          }
-        }
-        ASSERT_TRUE(found);
-      }
+      VerifierDeps decoded_deps(dex_files_, /*output_only=*/ false);
+      bool parsed = decoded_deps.ParseStoredData(dex_files_, ArrayRef<const uint8_t>(buffer));
+      ASSERT_TRUE(parsed);
       VerifyWithCompilerDriver(&decoded_deps);
 
       if (verify_failure) {
@@ -1470,23 +640,11 @@
   ASSERT_FALSE(buffer.empty());
 }
 
-TEST_F(VerifierDepsTest, NotAssignable_InterfaceWithClassInBoot) {
-  ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/lang/Exception;",
-                                         /* src= */ "LIface;",
-                                         /* is_strict= */ true,
-                                         /* is_assignable= */ false));
-  ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "LIface;", false));
-}
-
 TEST_F(VerifierDepsTest, Assignable_Arrays) {
   ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "[LIface;",
-                                         /* src= */ "[LMyClassExtendingInterface;",
-                                         /* is_strict= */ false,
-                                         /* is_assignable= */ true));
+                                         /* src= */ "[LMyClassExtendingInterface;"));
   ASSERT_FALSE(HasAssignable(
-      "LIface;", "LMyClassExtendingInterface;", /* expected_is_assignable= */ true));
-  ASSERT_FALSE(HasAssignable(
-      "LIface;", "LMyClassExtendingInterface;", /* expected_is_assignable= */ false));
+      "LIface;", "LMyClassExtendingInterface;"));
 }
 
 }  // namespace verifier
diff --git a/dexdump/Android.bp b/dexdump/Android.bp
index 0bbb001..31faa34 100644
--- a/dexdump/Android.bp
+++ b/dexdump/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "dexdump_defaults",
     defaults: ["art_defaults"],
@@ -37,7 +46,7 @@
         // Use static libs on host: required for Windows build and
         // static_sdk_tools build.
         host: {
-            enabled: true,
+            stl: "libc++_static",
             static_libs: [
                 "libdexfile",
                 "libartbase",
@@ -51,18 +60,42 @@
         darwin: {
             enabled: true,
         },
+        windows: {
+            // dexdump is provided in the Windows SDK.
+            enabled: true,
+        },
     },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
-        "//apex_available:platform", // for SDK
     ],
 }
 
+art_cc_defaults {
+    name: "art_dexdump_tests_defaults",
+    srcs: ["dexdump_test.cc"],
+    target: {
+        host: {
+            required: ["dexdump"],
+        },
+    },
+}
+
+// Version of ART gtest `art_dexdump_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
 art_cc_test {
     name: "art_dexdump_tests",
     defaults: [
         "art_gtest_defaults",
+        "art_dexdump_tests_defaults",
     ],
-    srcs: ["dexdump_test.cc"],
+}
+
+// Standalone version of ART gtest `art_dexdump_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_dexdump_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_dexdump_tests_defaults",
+    ],
 }
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index a412938..1d1eab8 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -37,6 +37,8 @@
 #include <inttypes.h>
 #include <stdio.h>
 
+#include <cctype>
+#include <iomanip>
 #include <memory>
 #include <sstream>
 #include <vector>
@@ -45,6 +47,7 @@
 #include "android-base/logging.h"
 #include "android-base/stringprintf.h"
 
+#include "base/bit_utils.h"
 #include "dex/class_accessor-inl.h"
 #include "dex/code_item_accessors-inl.h"
 #include "dex/dex_file-inl.h"
@@ -360,10 +363,10 @@
 /*
  * Dumps a string value with some escape characters.
  */
-static void dumpEscapedString(const char* p) {
+static void dumpEscapedString(std::string_view p) {
   fputs("\"", gOutFile);
-  for (; *p; p++) {
-    switch (*p) {
+  for (char c : p) {
+    switch (c) {
       case '\\':
         fputs("\\\\", gOutFile);
         break;
@@ -380,42 +383,78 @@
         fputs("\\r", gOutFile);
         break;
       default:
-        putc(*p, gOutFile);
+        putc(c, gOutFile);
     }  // switch
   }  // for
   fputs("\"", gOutFile);
 }
 
+static size_t utf8Bytes(char start_byte) {
+  uint8_t sb = static_cast<uint8_t>(start_byte);
+  if ((sb & 0x80) == 0) {
+    return 1;
+  }
+  size_t msb = art::MostSignificantBit(static_cast<uint8_t>(~sb));
+  CHECK_LE(7u - msb, 4u);
+  return 7 - msb;
+}
+
 /*
  * Dumps a string as an XML attribute value.
  */
-static void dumpXmlAttribute(const char* p) {
-  for (; *p; p++) {
-    switch (*p) {
-      case '&':
-        fputs("&amp;", gOutFile);
-        break;
-      case '<':
-        fputs("&lt;", gOutFile);
-        break;
-      case '>':
-        fputs("&gt;", gOutFile);
-        break;
-      case '"':
-        fputs("&quot;", gOutFile);
-        break;
-      case '\t':
-        fputs("&#x9;", gOutFile);
-        break;
-      case '\n':
-        fputs("&#xA;", gOutFile);
-        break;
-      case '\r':
-        fputs("&#xD;", gOutFile);
-        break;
-      default:
-        putc(*p, gOutFile);
-    }  // switch
+static void dumpXmlAttribute(std::string_view p) __attribute__((optnone)) {
+  for (const char* c = p.begin(); c < p.end(); ++c) {
+    if (std::isprint(*c)) {
+      switch (*c) {
+        case '&':
+          fputs("&amp;", gOutFile);
+          break;
+        case '<':
+          fputs("&lt;", gOutFile);
+          break;
+        case '>':
+          fputs("&gt;", gOutFile);
+          break;
+        case '"':
+          fputs("&quot;", gOutFile);
+          break;
+        case '\\':
+          fputs("\\\\", gOutFile);
+          break;
+        default:
+          putc(*c, gOutFile);
+      }  // switch
+    } else {
+      uint32_t data = 0;
+      size_t remaining;
+      uint8_t uc = static_cast<uint8_t>(*c);
+      if (((uc) & 0x80) == 0) {
+        // Not a multi-byte char
+        data = static_cast<uint32_t>(*c);
+        remaining = 0;
+      } else if (utf8Bytes(uc) == 2) {
+        // 2 bytes
+        data = ((uc) & 0b00011111);
+        remaining = 1;
+      } else if (utf8Bytes(uc) == 3) {
+        // 3 bytes
+        data = ((uc) & 0b00001111);
+        remaining = 2;
+      } else {
+        // 4 bytes
+        CHECK_EQ(utf8Bytes(uc), 4u);
+        data = ((uc) & 0b00000111);
+        remaining = 3;
+      }
+      for (size_t i = 0; i < remaining; ++i) {
+        ++c;
+        data = data << 6;
+        uc = static_cast<uint8_t>(*c);
+        data |= static_cast<uint32_t>(uc & 0b00111111u);
+      }
+      // No good option so just use java encoding, too many chars are invalid
+      fprintf(gOutFile, "\\u%04x", data);
+    }
   }  // for
 }
 
@@ -478,9 +517,9 @@
     case DexFile::kDexAnnotationString: {
       const u4 idx = static_cast<u4>(readVarWidth(data, arg, false));
       if (gOptions.outputFormat == OUTPUT_PLAIN) {
-        dumpEscapedString(pDexFile->StringDataByIdx(dex::StringIndex(idx)));
+        dumpEscapedString(pDexFile->StringViewByIdx(dex::StringIndex(idx)));
       } else {
-        dumpXmlAttribute(pDexFile->StringDataByIdx(dex::StringIndex(idx)));
+        dumpXmlAttribute(pDexFile->StringViewByIdx(dex::StringIndex(idx)));
       }
       break;
     }
@@ -1236,6 +1275,9 @@
     fprintf(gOutFile, "      name          : '%s'\n", name);
     fprintf(gOutFile, "      type          : '%s'\n", typeDescriptor);
     fprintf(gOutFile, "      access        : 0x%04x (%s)\n", flags, accessStr);
+    if (gOptions.showSectionHeaders) {
+      fprintf(gOutFile, "      method_idx    : %d\n", method.GetIndex());
+    }
     if (hiddenapiFlags != 0u) {
       fprintf(gOutFile,
               "      hiddenapi     : 0x%04x (%s)\n",
@@ -1657,14 +1699,6 @@
     fprintf(gOutFile, "  type        : %s\n", type);
     fprintf(gOutFile, "  target      : %s %s\n", declaring_class, member);
     fprintf(gOutFile, "  target_type : %s\n", member_type.c_str());
-  } else {
-    fprintf(gOutFile, "<method_handle index=\"%u\"\n", idx);
-    fprintf(gOutFile, " type=\"%s\"\n", type);
-    fprintf(gOutFile, " target_class=\"%s\"\n", declaring_class);
-    fprintf(gOutFile, " target_member=\"%s\"\n", member);
-    fprintf(gOutFile, " target_member_type=");
-    dumpEscapedString(member_type.c_str());
-    fprintf(gOutFile, "\n>\n</method_handle>\n");
   }
 }
 
@@ -1691,17 +1725,6 @@
     fprintf(gOutFile, "  link_argument[0] : %u (MethodHandle)\n", method_handle_idx);
     fprintf(gOutFile, "  link_argument[1] : %s (String)\n", method_name);
     fprintf(gOutFile, "  link_argument[2] : %s (MethodType)\n", method_type.c_str());
-  } else {
-    fprintf(gOutFile, "<call_site index=\"%u\" offset=\"%u\">\n", idx, call_site_id.data_off_);
-    fprintf(gOutFile,
-            "<link_argument index=\"0\" type=\"MethodHandle\" value=\"%u\"/>\n",
-            method_handle_idx);
-    fprintf(gOutFile,
-            "<link_argument index=\"1\" type=\"String\" values=\"%s\"/>\n",
-            method_name);
-    fprintf(gOutFile,
-            "<link_argument index=\"2\" type=\"MethodType\" value=\"%s\"/>\n",
-            method_type.c_str());
   }
 
   size_t argument = 3;
@@ -1781,19 +1804,11 @@
 
     if (gOptions.outputFormat == OUTPUT_PLAIN) {
       fprintf(gOutFile, "  link_argument[%zu] : %s (%s)\n", argument, value.c_str(), type);
-    } else {
-      fprintf(gOutFile, "<link_argument index=\"%zu\" type=\"%s\" value=", argument, type);
-      dumpEscapedString(value.c_str());
-      fprintf(gOutFile, "/>\n");
     }
 
     it.Next();
     argument++;
   }
-
-  if (gOptions.outputFormat == OUTPUT_XML) {
-    fprintf(gOutFile, "</call_site>\n");
-  }
 }
 
 /*
@@ -1815,11 +1830,6 @@
     dumpFileHeader(pDexFile);
   }
 
-  // Open XML context.
-  if (gOptions.outputFormat == OUTPUT_XML) {
-    fprintf(gOutFile, "<api>\n");
-  }
-
   // Iterate over all classes.
   char* package = nullptr;
   const u4 classDefsSize = pDexFile->GetHeader().class_defs_size_;
@@ -1842,11 +1852,6 @@
     fprintf(gOutFile, "</package>\n");
     free(package);
   }
-
-  // Close XML context.
-  if (gOptions.outputFormat == OUTPUT_XML) {
-    fprintf(gOutFile, "</api>\n");
-  }
 }
 
 /*
@@ -1890,9 +1895,19 @@
   if (gOptions.checksumOnly) {
     fprintf(gOutFile, "Checksum verified\n");
   } else {
+    // Open XML context.
+    if (gOptions.outputFormat == OUTPUT_XML) {
+      fprintf(gOutFile, "<api>\n");
+    }
+
     for (size_t i = 0, n = dex_files.size(); i < n; i++) {
       processDexFile(fileName, dex_files[i].get(), i, n);
     }
+
+    // Close XML context.
+    if (gOptions.outputFormat == OUTPUT_XML) {
+      fprintf(gOutFile, "</api>\n");
+    }
   }
   return 0;
 }
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index cd40620..922e134 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 art_cc_defaults {
     name: "libart-dexlayout-defaults",
     defaults: ["art_defaults"],
@@ -47,12 +56,12 @@
             ],
         },
     },
-    static_libs: ["libz"],
+    shared_libs: ["libz"],
 }
 
 cc_defaults {
     name: "libart-dexlayout_static_base_defaults",
-    static_libs: [
+    whole_static_libs: [
         "libbase",
         "libz",
     ],
@@ -95,7 +104,7 @@
         },
     },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -108,7 +117,7 @@
         "libdexfile_static_defaults",
         "libprofile_static_defaults",
     ],
-    static_libs: ["libart-dexlayout"],
+    whole_static_libs: ["libart-dexlayout"],
 }
 
 art_cc_library {
@@ -142,6 +151,10 @@
     },
     apex_available: [
         "com.android.art.debug",
+        // TODO(b/183882457): This lib doesn't go into com.android.art, but
+        // apex_available lists need to be the same for internal libs to avoid
+        // stubs, and this depends on libdexfiled.
+        "com.android.art",
     ],
 }
 
@@ -153,7 +166,7 @@
         "libdexfiled_static_defaults",
         "libprofiled_static_defaults",
     ],
-    static_libs: ["libartd-dexlayout"],
+    whole_static_libs: ["libartd-dexlayout"],
 }
 
 cc_defaults {
@@ -176,7 +189,7 @@
         "libart-dexlayout",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -229,7 +242,18 @@
         "libprofiled",
         "libartd-dexlayout",
     ],
+    data: [
+        ":art-gtest-jars-ManyMethods",
+    ],
     srcs: ["dexlayout_test.cc"],
+    target: {
+        host: {
+            required: [
+                "dexdump",
+                "dexlayoutd",
+            ],
+        },
+    },
 }
 
 art_cc_binary {
@@ -253,7 +277,7 @@
         },
     },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -265,4 +289,9 @@
         "art_gtest_defaults",
     ],
     srcs: ["dexdiag_test.cc"],
+    target: {
+        host: {
+            required: ["dexdiag"],
+        },
+    },
 }
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc
index a7dad07..b8c6ebe 100644
--- a/dexlayout/compact_dex_writer.cc
+++ b/dexlayout/compact_dex_writer.cc
@@ -34,9 +34,8 @@
   return dex_layout_->GetOptions().compact_dex_level_;
 }
 
-CompactDexWriter::Container::Container(bool dedupe_code_items)
-    : code_item_dedupe_(dedupe_code_items, &data_section_),
-      data_item_dedupe_(/*enabled=*/ true, &data_section_) {}
+CompactDexWriter::Container::Container()
+    : data_item_dedupe_(&data_section_) {}
 
 uint32_t CompactDexWriter::WriteDebugInfoOffsetTable(Stream* stream) {
   const uint32_t start_offset = stream->Tell();
@@ -117,7 +116,10 @@
 }
 
 CompactDexWriter::ScopedDataSectionItem::~ScopedDataSectionItem() {
-  // After having written, maybe dedupe the whole code item (excluding padding).
+  if (deduper_ == nullptr) {
+    return;
+  }
+  // After having written, maybe dedupe the whole section (excluding padding).
   const uint32_t deduped_offset = deduper_->Dedupe(start_offset_,
                                                    stream_->Tell(),
                                                    item_->GetOffset());
@@ -145,7 +147,7 @@
   ScopedDataSectionItem data_item(stream,
                                   code_item,
                                   CompactDexFile::CodeItem::kAlignment,
-                                  code_item_dedupe_);
+                                  /* deduper= */ nullptr);
 
   CompactDexFile::CodeItem disk_code_item;
 
@@ -209,18 +211,14 @@
 }
 
 
-CompactDexWriter::Deduper::Deduper(bool enabled, DexContainer::Section* section)
-    : enabled_(enabled),
-      dedupe_map_(/*__n=*/ 32,
+CompactDexWriter::Deduper::Deduper(DexContainer::Section* section)
+    : dedupe_map_(/*__n=*/ 32,
                   HashedMemoryRange::HashEqual(section),
                   HashedMemoryRange::HashEqual(section)) {}
 
 uint32_t CompactDexWriter::Deduper::Dedupe(uint32_t data_start,
                                            uint32_t data_end,
                                            uint32_t item_offset) {
-  if (!enabled_) {
-    return kDidNotDedupe;
-  }
   HashedMemoryRange range {data_start, data_end - data_start};
   auto existing = dedupe_map_.emplace(range, item_offset);
   if (!existing.second) {
@@ -397,7 +395,6 @@
   data_stream->Seek(std::max(
       static_cast<uint32_t>(output->GetDataSection()->Size()),
       kDataSectionAlignment));
-  code_item_dedupe_ = &container->code_item_dedupe_;
   data_item_dedupe_ = &container->data_item_dedupe_;
 
   // Starting offset is right after the header.
@@ -521,17 +518,11 @@
     WriteHeader(main_stream);
   }
 
-  // Clear the dedupe to prevent interdex code item deduping. This does not currently work well with
-  // dex2oat's class unloading. The issue is that verification encounters quickened opcodes after
-  // the first dex gets unloaded.
-  code_item_dedupe_->Clear();
-
   return true;
 }
 
 std::unique_ptr<DexContainer> CompactDexWriter::CreateDexContainer() const {
-  return std::unique_ptr<DexContainer>(
-      new CompactDexWriter::Container(dex_layout_->GetOptions().dedupe_code_items_));
+  return std::unique_ptr<DexContainer>(new CompactDexWriter::Container());
 }
 
 }  // namespace art
diff --git a/dexlayout/compact_dex_writer.h b/dexlayout/compact_dex_writer.h
index c81d0c7..d78f8be 100644
--- a/dexlayout/compact_dex_writer.h
+++ b/dexlayout/compact_dex_writer.h
@@ -37,8 +37,7 @@
    public:
     static const uint32_t kDidNotDedupe = 0;
 
-    // if not enabled, Dedupe will always return kDidNotDedupe.
-    explicit Deduper(bool enabled, DexContainer::Section* section);
+    explicit Deduper(DexContainer::Section* section);
 
     // Deduplicate a blob of data that has been written to mem_map.
     // Returns the offset of the deduplicated data or kDidNotDedupe did deduplication did not occur.
@@ -85,8 +84,6 @@
       };
     };
 
-    const bool enabled_;
-
     // Dedupe map.
     std::unordered_map<HashedMemoryRange,
                        uint32_t,
@@ -125,11 +122,10 @@
     }
 
    private:
-    explicit Container(bool dedupe_code_items);
+    Container();
 
     VectorSection main_section_;
     VectorSection data_section_;
-    Deduper code_item_dedupe_;
     Deduper data_item_dedupe_;
 
     friend class CompactDexWriter;
@@ -173,8 +169,6 @@
   uint32_t owned_data_begin_ = 0u;
   uint32_t owned_data_end_ = 0u;
 
-  // State for where we are deduping.
-  Deduper* code_item_dedupe_ = nullptr;
   Deduper* data_item_dedupe_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(CompactDexWriter);
diff --git a/dexlayout/dex_container.h b/dexlayout/dex_container.h
index 2d742b0..713de1b 100644
--- a/dexlayout/dex_container.h
+++ b/dexlayout/dex_container.h
@@ -46,6 +46,9 @@
     // Clear the container.
     virtual void Clear() = 0;
 
+    // Release the data, clearing the container contents.
+    virtual std::vector<uint8_t> ReleaseData() = 0;
+
     // Returns the end of the memory region.
     uint8_t* End() {
       return Begin() + Size();
@@ -73,6 +76,12 @@
       data_.clear();
     }
 
+    std::vector<uint8_t> ReleaseData() override {
+      std::vector<uint8_t> temp;
+      temp.swap(data_);
+      return temp;
+    }
+
    private:
     std::vector<uint8_t> data_;
   };
diff --git a/dexlayout/dex_visualize.cc b/dexlayout/dex_visualize.cc
index 27cec8d9..382e294 100644
--- a/dexlayout/dex_visualize.cc
+++ b/dexlayout/dex_visualize.cc
@@ -70,7 +70,7 @@
         if (printed_one) {
           fprintf(out_file_, ", ");
         }
-        fprintf(out_file_, "\"%s\" %d", s.name.c_str(), s.offset / kPageSize);
+        fprintf(out_file_, "\"%s\" %" PRIuPTR, s.name.c_str(), s.offset / kPageSize);
         printed_one = true;
       }
     }
@@ -331,7 +331,7 @@
       bytes = FindNextByteAfterSection(header, sorted_sections, i) - file_section.offset;
     }
     fprintf(stdout,
-            "%-10s %8d %8d %8d %8d %%%02d\n",
+            "%-10s %8d %8d %8d %8" PRIuPTR " %%%02d\n",
             file_section.name.c_str(),
             file_section.offset,
             file_section.size,
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index f5eeeb7..75afc78 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1178,6 +1178,9 @@
     fprintf(out_file_, "      name          : '%s'\n", name);
     fprintf(out_file_, "      type          : '%s'\n", type_descriptor);
     fprintf(out_file_, "      access        : 0x%04x (%s)\n", flags, access_str);
+    if (options_.show_section_headers_) {
+      fprintf(out_file_, "      method_idx    : %d\n", method_id->GetIndex());
+    }
     if (hiddenapi_flags != 0u) {
       fprintf(out_file_,
               "      hiddenapi     : 0x%04x (%s)\n",
diff --git a/dexlayout/dexlayout.h b/dexlayout/dexlayout.h
index 60076bf..9bb7b8b 100644
--- a/dexlayout/dexlayout.h
+++ b/dexlayout/dexlayout.h
@@ -67,7 +67,6 @@
   bool visualize_pattern_ = false;
   bool update_checksum_ = false;
   CompactDexLevel compact_dex_level_ = CompactDexLevel::kCompactDexLevelNone;
-  bool dedupe_code_items_ = true;
   OutputFormat output_format_ = kOutputPlain;
   const char* output_dex_directory_ = nullptr;
   const char* output_file_name_ = nullptr;
diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc
index b4e023f..3c37e6d 100644
--- a/dexlayout/dexlayout_test.cc
+++ b/dexlayout/dexlayout_test.cc
@@ -438,19 +438,13 @@
 
     // -v makes sure that the layout did not corrupt the dex file.
     std::vector<std::string> dexlayout_args =
-        { "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, dex_file };
+        { "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, dex_file };
     if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option=*/ false)) {
       return false;
     }
 
     // Recreate the profile with the new dex location. This is required so that the profile dex
     // location matches.
-    // For convenience we just copy the previous dex file to the new location so we can re-use it
-    // for profile generation.
-
-    // Don't check the output. The exec cmd wrongfully coplains that the cp cmd fails.
-    std::vector<std::string> cp_args = {"/usr/bin/cp", dex_file, output_dex};
-    art::Exec(cp_args, error_msg);
     CreateProfile(output_dex, profile_file);
     // -v makes sure that the layout did not corrupt the dex file.
     // -i since the checksum won't match from the first layout.
diff --git a/dexlist/Android.bp b/dexlist/Android.bp
index 860a5fd..1e69bdc 100644
--- a/dexlist/Android.bp
+++ b/dexlist/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 art_cc_binary {
     name: "dexlist",
     defaults: ["art_defaults"],
@@ -23,7 +32,7 @@
         "libbase",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -48,10 +57,31 @@
     },
 }
 
+art_cc_defaults {
+    name: "art_dexlist_tests_defaults",
+    srcs: ["dexlist_test.cc"],
+    target: {
+        host: {
+            required: ["dexlist"],
+        },
+    },
+}
+
+// Version of ART gtest `art_dexlist_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
 art_cc_test {
     name: "art_dexlist_tests",
     defaults: [
         "art_gtest_defaults",
+        "art_dexlist_tests_defaults",
     ],
-    srcs: ["dexlist_test.cc"],
+}
+
+// Standalone version of ART gtest `art_dexlist_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_dexlist_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_dexlist_tests_defaults",
+    ],
 }
diff --git a/dexoptanalyzer/Android.bp b/dexoptanalyzer/Android.bp
index 7875dbb..a66bd29 100644
--- a/dexoptanalyzer/Android.bp
+++ b/dexoptanalyzer/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "dexoptanalyzer-defaults",
     host_supported: true,
@@ -24,8 +33,7 @@
 
     target: {
         android: {
-            // Use the 32-bit version of dexoptanalyzer on devices.
-            compile_multilib: "prefer32",
+            compile_multilib: "first",
         },
     },
 
@@ -34,6 +42,17 @@
     ],
 }
 
+cc_library_headers {
+    name: "dexoptanalyzer_headers",
+    export_include_dirs: ["."],
+    host_supported: true,
+    apex_available: [
+        "com.android.art.debug",
+        "com.android.art",
+    ],
+    min_sdk_version: "S",
+}
+
 art_cc_binary {
     name: "dexoptanalyzer",
     defaults: ["dexoptanalyzer-defaults"],
@@ -42,7 +61,7 @@
         "libartbase",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -62,13 +81,50 @@
     ],
 }
 
+art_cc_defaults {
+    name: "art_dexoptanalyzer_tests_defaults",
+    shared_libs: [
+        "libbacktrace",
+    ],
+    data: [
+        ":art-gtest-jars-LinkageTest",
+        ":art-gtest-jars-Main",
+        ":art-gtest-jars-MainStripped",
+        ":art-gtest-jars-MultiDex",
+        ":art-gtest-jars-MultiDexModifiedSecondary",
+        ":art-gtest-jars-MyClassNatives",
+        ":art-gtest-jars-Nested",
+        ":art-gtest-jars-VerifierDeps",
+        ":art-gtest-jars-VerifierDepsMulti",
+    ],
+    srcs: ["dexoptanalyzer_test.cc"],
+    target: {
+        host: {
+            required: [
+                "dex2oatd",
+                "dexoptanalyzerd",
+            ],
+        },
+    },
+}
+
+// Version of ART gtest `art_dexoptanalyzer_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
 art_cc_test {
     name: "art_dexoptanalyzer_tests",
     defaults: [
         "art_gtest_defaults",
+        "art_dexoptanalyzer_tests_defaults",
     ],
-    shared_libs: [
-        "libbacktrace",
+}
+
+// Standalone version of ART gtest `art_dexoptanalyzer_tests`, not bundled with the ART APEX on
+// target.
+art_cc_test {
+    name: "art_standalone_dexoptanalyzer_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_dexoptanalyzer_tests_defaults",
     ],
-    srcs: ["dexoptanalyzer_test.cc"],
+    test_config_template: "art_standalone_dexoptanalyzer_tests.xml",
 }
diff --git a/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml b/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml
new file mode 100644
index 0000000..ae112d4
--- /dev/null
+++ b/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs art_standalone_dexoptanalyzer_tests (as root).">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art_standalone_dexoptanalyzer_tests->/data/local/tmp/nativetest/art_standalone_dexoptanalyzer_tests" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art-gtest-jars-LinkageTest.dex->/data/local/tmp/nativetest/art-gtest-jars-LinkageTest.dex" />
+        <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/nativetest/art-gtest-jars-Main.jar" />
+        <option name="push" value="art-gtest-jars-MainStripped.jar->/data/local/tmp/nativetest/art-gtest-jars-MainStripped.jar" />
+        <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/nativetest/art-gtest-jars-MultiDex.jar" />
+        <option name="push" value="art-gtest-jars-MultiDexModifiedSecondary.jar->/data/local/tmp/nativetest/art-gtest-jars-MultiDexModifiedSecondary.jar" />
+        <option name="push" value="art-gtest-jars-MyClassNatives.jar->/data/local/tmp/nativetest/art-gtest-jars-MyClassNatives.jar" />
+        <option name="push" value="art-gtest-jars-Nested.jar->/data/local/tmp/nativetest/art-gtest-jars-Nested.jar" />
+        <option name="push" value="art-gtest-jars-VerifierDeps.dex->/data/local/tmp/nativetest/art-gtest-jars-VerifierDeps.dex" />
+        <option name="push" value="art-gtest-jars-VerifierDepsMulti.dex->/data/local/tmp/nativetest/art-gtest-jars-VerifierDepsMulti.dex" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/nativetest" />
+        <option name="module-name" value="art_standalone_dexoptanalyzer_tests" />
+        <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+        <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc
index 7454993..fd1f43d 100644
--- a/dexoptanalyzer/dexoptanalyzer.cc
+++ b/dexoptanalyzer/dexoptanalyzer.cc
@@ -14,46 +14,35 @@
  * limitations under the License.
  */
 
+#include "dexoptanalyzer.h"
+
 #include <iostream>
 #include <string>
 #include <string_view>
 
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
+#include "base/compiler_filter.h"
 #include "base/file_utils.h"
 #include "base/logging.h"  // For InitLogging.
 #include "base/mutex.h"
 #include "base/os.h"
 #include "base/string_view_cpp20.h"
 #include "base/utils.h"
-#include "compiler_filter.h"
+#include "class_linker.h"
 #include "class_loader_context.h"
 #include "dex/dex_file.h"
+#include "gc/heap.h"
+#include "gc/space/image_space.h"
 #include "noop_compiler_callbacks.h"
+#include "oat.h"
 #include "oat_file_assistant.h"
 #include "runtime.h"
 #include "thread-inl.h"
+#include "vdex_file.h"
 
 namespace art {
-
-// See OatFileAssistant docs for the meaning of the valid return codes.
-enum ReturnCodes {
-  kNoDexOptNeeded = 0,
-  kDex2OatFromScratch = 1,
-  kDex2OatForBootImageOat = 2,
-  kDex2OatForFilterOat = 3,
-  kDex2OatForBootImageOdex = 4,
-  kDex2OatForFilterOdex = 5,
-
-  // Success return code when executed with --flatten-class-loader-context.
-  // Success is typically signalled with a zero but we use a non-colliding
-  // code to communicate that the flattening code path was taken.
-  kFlattenClassLoaderContextSuccess = 50,
-
-  kErrorInvalidArguments = 101,
-  kErrorCannotCreateRuntime = 102,
-  kErrorUnknownDexOptNeeded = 103
-};
+namespace dexoptanalyzer {
 
 static int original_argc;
 static char** original_argv;
@@ -98,8 +87,8 @@
   UsageError("  --compiler-filter=<string>: the target compiler filter to be used as reference");
   UsageError("       when deciding if the dex file needs to be optimized.");
   UsageError("");
-  UsageError("  --assume-profile-changed: assumes the profile information has changed");
-  UsageError("       when deciding if the dex file needs to be optimized.");
+  UsageError("  --profile_analysis_result=<int>: the result of the profile analysis, used in");
+  UsageError("       deciding if the dex file needs to be optimized.");
   UsageError("");
   UsageError("  --image=<filename>: optional, the image to be used to decide if the associated");
   UsageError("       oat file is up to date. Defaults to $ANDROID_ROOT/framework/boot.art.");
@@ -133,6 +122,9 @@
   UsageError("      print a colon-separated list of its dex files to standard output. Dexopt");
   UsageError("      needed analysis is not performed when this option is set.");
   UsageError("");
+  UsageError("  --validate-bcp: validates the boot class path files (.art, .oat, .vdex).");
+  UsageError("      Requires --isa and --image options to locate artifacts.");
+  UsageError("");
   UsageError("Return code:");
   UsageError("  To make it easier to integrate with the internal tools this command will make");
   UsageError("    available its result (dexoptNeeded) as the exit/return code. i.e. it will not");
@@ -150,14 +142,14 @@
   UsageError("        kErrorUnknownDexOptNeeded = 103");
   UsageError("");
 
-  exit(kErrorInvalidArguments);
+  exit(static_cast<int>(ReturnCode::kErrorInvalidArguments));
 }
 
 class DexoptAnalyzer final {
  public:
   DexoptAnalyzer() :
       only_flatten_context_(false),
-      assume_profile_changed_(false),
+      only_validate_bcp_(false),
       downgrade_(false) {}
 
   void ParseArgs(int argc, char **argv) {
@@ -177,8 +169,16 @@
     for (int i = 0; i < argc; ++i) {
       const char* raw_option = argv[i];
       const std::string_view option(raw_option);
-      if (option == "--assume-profile-changed") {
-        assume_profile_changed_ = true;
+
+      if (StartsWith(option, "--profile-analysis-result=")) {
+        int parse_result = std::stoi(std::string(
+            option.substr(strlen("--profile-analysis-result="))), nullptr, 0);
+        if (parse_result != static_cast<int>(ProfileAnalysisResult::kOptimize) &&
+            parse_result != static_cast<int>(ProfileAnalysisResult::kDontOptimizeSmallDelta) &&
+            parse_result != static_cast<int>(ProfileAnalysisResult::kDontOptimizeEmptyProfiles)) {
+          Usage("Invalid --profile-analysis-result= %d", parse_result);
+        }
+        profile_analysis_result_ = static_cast<ProfileAnalysisResult>(parse_result);
       } else if (StartsWith(option, "--dex-file=")) {
         dex_file_ = std::string(option.substr(strlen("--dex-file=")));
       } else if (StartsWith(option, "--compiler-filter=")) {
@@ -236,6 +236,8 @@
         }
       } else if (option == "--flatten-class-loader-context") {
         only_flatten_context_ = true;
+      } else if (option == "--validate-bcp") {
+        only_validate_bcp_ = true;
       } else {
         Usage("Unknown argument '%s'", raw_option);
       }
@@ -287,9 +289,9 @@
     return true;
   }
 
-  int GetDexOptNeeded() const {
+  ReturnCode GetDexOptNeeded() const {
     if (!CreateRuntime()) {
-      return kErrorCannotCreateRuntime;
+      return ReturnCode::kErrorCannotCreateRuntime;
     }
     std::unique_ptr<Runtime> runtime(Runtime::Current());
 
@@ -303,46 +305,140 @@
         Usage("Invalid --class-loader-context '%s'", context_str_.c_str());
       }
     }
+    if (class_loader_context != nullptr) {
+      size_t dir_index = dex_file_.rfind('/');
+      std::string classpath_dir = (dir_index != std::string::npos)
+          ? dex_file_.substr(0, dir_index)
+          : "";
+
+      if (!class_loader_context->OpenDexFiles(classpath_dir,
+                                              context_fds_,
+                                              /*only_read_checksums=*/ true)) {
+        return ReturnCode::kDex2OatFromScratch;
+      }
+    }
 
     std::unique_ptr<OatFileAssistant> oat_file_assistant;
     oat_file_assistant = std::make_unique<OatFileAssistant>(dex_file_.c_str(),
                                                             isa_,
+                                                            class_loader_context.get(),
                                                             /*load_executable=*/ false,
-                                                            /*only_load_system_executable=*/ false,
+                                                            /*only_load_trusted_executable=*/ false,
                                                             vdex_fd_,
                                                             oat_fd_,
                                                             zip_fd_);
     // Always treat elements of the bootclasspath as up-to-date.
     // TODO(calin): this check should be in OatFileAssistant.
     if (oat_file_assistant->IsInBootClassPath()) {
-      return kNoDexOptNeeded;
+      return ReturnCode::kNoDexOptNeeded;
     }
 
-    int dexoptNeeded = oat_file_assistant->GetDexOptNeeded(compiler_filter_,
-                                                           class_loader_context.get(),
-                                                           context_fds_,
-                                                           assume_profile_changed_,
+    // If the compiler filter depends on profiles but the profiles are empty,
+    // change the test filter to kVerify. It's what dex2oat also does.
+    CompilerFilter::Filter actual_compiler_filter = compiler_filter_;
+    if (CompilerFilter::DependsOnProfile(compiler_filter_) &&
+        profile_analysis_result_ == ProfileAnalysisResult::kDontOptimizeEmptyProfiles) {
+      actual_compiler_filter = CompilerFilter::kVerify;
+    }
+
+    // TODO: GetDexOptNeeded should get the raw analysis result instead of assume_profile_changed.
+    bool assume_profile_changed = profile_analysis_result_ == ProfileAnalysisResult::kOptimize;
+    int dexoptNeeded = oat_file_assistant->GetDexOptNeeded(actual_compiler_filter,
+                                                           assume_profile_changed,
                                                            downgrade_);
 
-    // Convert OatFileAssitant codes to dexoptanalyzer codes.
+    // Convert OatFileAssistant codes to dexoptanalyzer codes.
     switch (dexoptNeeded) {
-      case OatFileAssistant::kNoDexOptNeeded: return kNoDexOptNeeded;
-      case OatFileAssistant::kDex2OatFromScratch: return kDex2OatFromScratch;
-      case OatFileAssistant::kDex2OatForBootImage: return kDex2OatForBootImageOat;
-      case OatFileAssistant::kDex2OatForFilter: return kDex2OatForFilterOat;
+      case OatFileAssistant::kNoDexOptNeeded: return ReturnCode::kNoDexOptNeeded;
+      case OatFileAssistant::kDex2OatFromScratch: return ReturnCode::kDex2OatFromScratch;
+      case OatFileAssistant::kDex2OatForBootImage: return ReturnCode::kDex2OatForBootImageOat;
+      case OatFileAssistant::kDex2OatForFilter: return ReturnCode::kDex2OatForFilterOat;
 
-      case -OatFileAssistant::kDex2OatForBootImage: return kDex2OatForBootImageOdex;
-      case -OatFileAssistant::kDex2OatForFilter: return kDex2OatForFilterOdex;
+      case -OatFileAssistant::kDex2OatForBootImage: return ReturnCode::kDex2OatForBootImageOdex;
+      case -OatFileAssistant::kDex2OatForFilter: return ReturnCode::kDex2OatForFilterOdex;
       default:
         LOG(ERROR) << "Unknown dexoptNeeded " << dexoptNeeded;
-        return kErrorUnknownDexOptNeeded;
+        return ReturnCode::kErrorUnknownDexOptNeeded;
     }
   }
 
-  int FlattenClassLoaderContext() const {
+  // Validates the boot classpath and boot classpath extensions by checking the image checksums,
+  // the oat files and the vdex files.
+  //
+  // Returns `ReturnCode::kNoDexOptNeeded` when all the files are up-to-date,
+  // `ReturnCode::kDex2OatFromScratch` if any of the files are missing or out-of-date, and
+  // `ReturnCode::kErrorCannotCreateRuntime` if the files could not be tested due to problem
+  // creating a runtime.
+  ReturnCode ValidateBcp() const {
+    using ImageSpace = gc::space::ImageSpace;
+
+    if (!CreateRuntime()) {
+      return ReturnCode::kErrorCannotCreateRuntime;
+    }
+    std::unique_ptr<Runtime> runtime(Runtime::Current());
+
+    auto dex_files = ArrayRef<const DexFile* const>(runtime->GetClassLinker()->GetBootClassPath());
+    auto boot_image_spaces = ArrayRef<ImageSpace* const>(runtime->GetHeap()->GetBootImageSpaces());
+    const std::string checksums = ImageSpace::GetBootClassPathChecksums(boot_image_spaces,
+                                                                        dex_files);
+
+    std::string error_msg;
+    const std::vector<std::string>& bcp = runtime->GetBootClassPath();
+    const std::vector<std::string>& bcp_locations = runtime->GetBootClassPathLocations();
+    const std::string bcp_locations_path = android::base::Join(bcp_locations, ':');
+    if (!ImageSpace::VerifyBootClassPathChecksums(checksums,
+                                                  bcp_locations_path,
+                                                  runtime->GetImageLocation(),
+                                                  ArrayRef<const std::string>(bcp_locations),
+                                                  ArrayRef<const std::string>(bcp),
+                                                  runtime->GetInstructionSet(),
+                                                  &error_msg)) {
+      LOG(INFO) << "Failed to verify boot class path checksums: " << error_msg;
+      return ReturnCode::kDex2OatFromScratch;
+    }
+
+    const auto& image_spaces = runtime->GetHeap()->GetBootImageSpaces();
+    size_t bcp_component_count = 0;
+    for (const auto& image_space : image_spaces) {
+      if (!image_space->GetImageHeader().IsValid()) {
+        LOG(INFO) << "Image header is not valid: " << image_space->GetImageFilename();
+        return ReturnCode::kDex2OatFromScratch;
+      }
+      const OatFile* oat_file = image_space->GetOatFile();
+      if (oat_file == nullptr) {
+        const std::string oat_path = ReplaceFileExtension(image_space->GetImageFilename(), "oat");
+        LOG(INFO) << "Oat file missing: " << oat_path;
+        return ReturnCode::kDex2OatFromScratch;
+      }
+      if (!oat_file->GetOatHeader().IsValid() ||
+          !ImageSpace::ValidateOatFile(*oat_file, &error_msg)) {
+        LOG(INFO) << "Oat file is not valid: " << oat_file->GetLocation() << " " << error_msg;
+        return ReturnCode::kDex2OatFromScratch;
+      }
+      const VdexFile* vdex_file = oat_file->GetVdexFile();
+      if (vdex_file == nullptr || !vdex_file->IsValid()) {
+        LOG(INFO) << "Vdex file is not valid : " << oat_file->GetLocation();
+        return ReturnCode::kDex2OatFromScratch;
+      }
+      bcp_component_count += image_space->GetComponentCount();
+    }
+
+    // If the number of components encountered in the image spaces does not match the number
+    // of components expected from the boot classpath locations then something is missing.
+    if (bcp_component_count != bcp_locations.size()) {
+      for (size_t i = bcp_component_count; i < bcp_locations.size(); ++i) {
+        LOG(INFO) << "Missing image file for " << bcp_locations[i];
+      }
+      return ReturnCode::kDex2OatFromScratch;
+    }
+
+    return ReturnCode::kNoDexOptNeeded;
+  }
+
+  ReturnCode FlattenClassLoaderContext() const {
     DCHECK(only_flatten_context_);
     if (context_str_.empty()) {
-      return kErrorInvalidArguments;
+      return ReturnCode::kErrorInvalidArguments;
     }
 
     std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str_);
@@ -351,12 +447,14 @@
     }
 
     std::cout << context->FlattenDexPaths() << std::flush;
-    return kFlattenClassLoaderContextSuccess;
+    return ReturnCode::kFlattenClassLoaderContextSuccess;
   }
 
-  int Run() const {
+  ReturnCode Run() const {
     if (only_flatten_context_) {
       return FlattenClassLoaderContext();
+    } else if (only_validate_bcp_) {
+      return ValidateBcp();
     } else {
       return GetDexOptNeeded();
     }
@@ -368,7 +466,8 @@
   CompilerFilter::Filter compiler_filter_;
   std::string context_str_;
   bool only_flatten_context_;
-  bool assume_profile_changed_;
+  bool only_validate_bcp_;
+  ProfileAnalysisResult profile_analysis_result_;
   bool downgrade_;
   std::string image_;
   std::vector<const char*> runtime_args_;
@@ -379,7 +478,7 @@
   std::vector<int> context_fds_;
 };
 
-static int dexoptAnalyze(int argc, char** argv) {
+static ReturnCode dexoptAnalyze(int argc, char** argv) {
   DexoptAnalyzer analyzer;
 
   // Parse arguments. Argument mistakes will lead to exit(kErrorInvalidArguments) in UsageError.
@@ -387,8 +486,10 @@
   return analyzer.Run();
 }
 
+}  // namespace dexoptanalyzer
 }  // namespace art
 
 int main(int argc, char **argv) {
-  return art::dexoptAnalyze(argc, argv);
+  art::dexoptanalyzer::ReturnCode return_code = art::dexoptanalyzer::dexoptAnalyze(argc, argv);
+  return static_cast<int>(return_code);
 }
diff --git a/dexoptanalyzer/dexoptanalyzer.h b/dexoptanalyzer/dexoptanalyzer.h
new file mode 100644
index 0000000..8083057
--- /dev/null
+++ b/dexoptanalyzer/dexoptanalyzer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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_DEXOPTANALYZER_DEXOPTANALYZER_H_
+#define ART_DEXOPTANALYZER_DEXOPTANALYZER_H_
+
+namespace art {
+namespace dexoptanalyzer {
+
+// See OatFileAssistant docs for the meaning of the valid return codes.
+enum class ReturnCode {
+  kNoDexOptNeeded = 0,
+  kDex2OatFromScratch = 1,
+  kDex2OatForBootImageOat = 2,
+  kDex2OatForFilterOat = 3,
+  kDex2OatForBootImageOdex = 4,
+  kDex2OatForFilterOdex = 5,
+
+  // Success return code when executed with --flatten-class-loader-context.
+  // Success is typically signalled with a zero but we use a non-colliding
+  // code to communicate that the flattening code path was taken.
+  kFlattenClassLoaderContextSuccess = 50,
+
+  kErrorInvalidArguments = 101,
+  kErrorCannotCreateRuntime = 102,
+  kErrorUnknownDexOptNeeded = 103
+};
+
+// Accepted values for the profile analysis results.
+enum class ProfileAnalysisResult {
+  kOptimize = 1,
+  kDontOptimizeSmallDelta = 2,
+  kDontOptimizeEmptyProfiles = 3,
+};
+
+}  // namespace dexoptanalyzer
+}  // namespace art
+
+#endif  // ART_DEXOPTANALYZER_DEXOPTANALYZER_H_
diff --git a/dexoptanalyzer/dexoptanalyzer_test.cc b/dexoptanalyzer/dexoptanalyzer_test.cc
index 651fa4a..7abd4ba 100644
--- a/dexoptanalyzer/dexoptanalyzer_test.cc
+++ b/dexoptanalyzer/dexoptanalyzer_test.cc
@@ -16,11 +16,15 @@
 
 #include <gtest/gtest.h>
 
+#include <string>
+
 #include "arch/instruction_set.h"
-#include "compiler_filter.h"
+#include "base/compiler_filter.h"
 #include "dexopt_test.h"
+#include "dexoptanalyzer.h"
 
 namespace art {
+namespace dexoptanalyzer {
 
 class DexoptAnalyzerTest : public DexoptTest {
  protected:
@@ -35,17 +39,21 @@
 
   int Analyze(const std::string& dex_file,
               CompilerFilter::Filter compiler_filter,
-              bool assume_profile_changed,
-              const char* class_loader_context) {
+              ProfileAnalysisResult profile_analysis_result,
+              const char* class_loader_context,
+              bool downgrade = false) {
     std::string dexoptanalyzer_cmd = GetDexoptAnalyzerCmd();
     std::vector<std::string> argv_str;
     argv_str.push_back(dexoptanalyzer_cmd);
     argv_str.push_back("--dex-file=" + dex_file);
     argv_str.push_back("--isa=" + std::string(GetInstructionSetString(kRuntimeISA)));
     argv_str.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(compiler_filter));
-    if (assume_profile_changed) {
-      argv_str.push_back("--assume-profile-changed");
+    argv_str.push_back("--profile-analysis-result=" +
+        std::to_string(static_cast<int>(profile_analysis_result)));
+    if (downgrade) {
+      argv_str.push_back("--downgrade");
     }
+
     argv_str.push_back("--runtime-arg");
     argv_str.push_back(GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()));
     argv_str.push_back("--runtime-arg");
@@ -76,126 +84,177 @@
   // as the output of OatFileAssistant::GetDexOptNeeded.
   void Verify(const std::string& dex_file,
               CompilerFilter::Filter compiler_filter,
-              bool assume_profile_changed = false,
+              ProfileAnalysisResult profile_analysis_result =
+                  ProfileAnalysisResult::kDontOptimizeSmallDelta,
               bool downgrade = false,
               const char* class_loader_context = "PCL[]") {
-    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);
-    std::vector<int> context_fds;
-
     std::unique_ptr<ClassLoaderContext> context = class_loader_context == nullptr
         ? nullptr
         : ClassLoaderContext::Create(class_loader_context);
+    if (context != nullptr) {
+      std::vector<int> context_fds;
+      ASSERT_TRUE(context->OpenDexFiles("", context_fds, /*only_read_checksums*/ true));
+    }
 
+    int dexoptanalyzerResult = Analyze(
+        dex_file, compiler_filter, profile_analysis_result, class_loader_context, downgrade);
+    dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult);
+    OatFileAssistant oat_file_assistant(dex_file.c_str(),
+                                        kRuntimeISA,
+                                        context.get(),
+                                        /*load_executable=*/ false);
+    bool assume_profile_changed = profile_analysis_result == ProfileAnalysisResult::kOptimize;
     int assistantResult = oat_file_assistant.GetDexOptNeeded(
-        compiler_filter, context.get(), context_fds, assume_profile_changed, downgrade);
+        compiler_filter, assume_profile_changed, downgrade);
     EXPECT_EQ(assistantResult, dexoptanalyzerResult);
   }
 };
 
 // The tests below exercise the same test case from oat_file_assistant_test.cc.
 
-// Case: We have a DEX file, but no OAT file for it.
+// Case: We have a DEX file, but no ODEX file for it.
 TEST_F(DexoptAnalyzerTest, DexNoOat) {
   std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
   Copy(GetDexSrc1(), dex_location);
 
   Verify(dex_location, CompilerFilter::kSpeed);
   Verify(dex_location, CompilerFilter::kExtract);
-  Verify(dex_location, CompilerFilter::kQuicken);
+  Verify(dex_location, CompilerFilter::kVerify);
   Verify(dex_location, CompilerFilter::kSpeedProfile);
-  Verify(dex_location, CompilerFilter::kSpeed, false, false, nullptr);
+  Verify(dex_location, CompilerFilter::kSpeed,
+      ProfileAnalysisResult::kDontOptimizeSmallDelta, false, nullptr);
 }
 
-// Case: We have a DEX file and up-to-date OAT file for it.
+// Case: We have a DEX file and up-to-date ODEX file for it.
 TEST_F(DexoptAnalyzerTest, OatUpToDate) {
   std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
+  std::string odex_location = GetOdexDir() + "/OatUpToDate.odex";
   Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  GenerateOdexForTest(dex_location.c_str(), odex_location.c_str(), CompilerFilter::kSpeed);
 
   Verify(dex_location, CompilerFilter::kSpeed);
-  Verify(dex_location, CompilerFilter::kQuicken);
+  Verify(dex_location, CompilerFilter::kVerify);
   Verify(dex_location, CompilerFilter::kExtract);
   Verify(dex_location, CompilerFilter::kEverything);
-  Verify(dex_location, CompilerFilter::kSpeed, false, false, nullptr);
+  Verify(dex_location, CompilerFilter::kSpeed,
+      ProfileAnalysisResult::kDontOptimizeSmallDelta, false, nullptr);
 }
 
-// Case: We have a DEX file and speed-profile OAT file for it.
+// Case: We have a DEX file and speed-profile ODEX file for it.
 TEST_F(DexoptAnalyzerTest, ProfileOatUpToDate) {
   std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
+  std::string odex_location = GetOdexDir() + "/ProfileOatUpToDate.odex";
   Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
+  GenerateOdexForTest(dex_location.c_str(), odex_location.c_str(), CompilerFilter::kSpeedProfile);
 
-  Verify(dex_location, CompilerFilter::kSpeedProfile, false);
-  Verify(dex_location, CompilerFilter::kQuicken, false);
-  Verify(dex_location, CompilerFilter::kSpeedProfile, true);
-  Verify(dex_location, CompilerFilter::kQuicken, true);
+  Verify(dex_location, CompilerFilter::kSpeedProfile,
+      ProfileAnalysisResult::kDontOptimizeSmallDelta);
+  Verify(dex_location, CompilerFilter::kVerify, ProfileAnalysisResult::kDontOptimizeSmallDelta);
+  Verify(dex_location, CompilerFilter::kSpeedProfile, ProfileAnalysisResult::kOptimize);
+  Verify(dex_location, CompilerFilter::kVerify, ProfileAnalysisResult::kOptimize);
+}
+
+// Case: We have a DEX file, verify odex file for it, and we ask if it's up to date
+// when the profiles are empty or full.
+TEST_F(DexoptAnalyzerTest, VerifyAndEmptyProfiles) {
+  std::string dex_location = GetScratchDir() + "/VerifyAndEmptyProfiles.jar";
+  std::string odex_location = GetOdexDir() + "/VerifyAndEmptyProfiles.odex";
+  Copy(GetDexSrc1(), dex_location);
+
+  GenerateOdexForTest(dex_location.c_str(), odex_location.c_str(), CompilerFilter::kVerify);
+
+  // If we want to speed-profile something that was verified, do it even if
+  // the profile analysis returns kDontOptimizeSmallDelta (it means that we do have profile data,
+  // so a transition verify -> speed-profile is still worth).
+  ASSERT_EQ(
+      static_cast<int>(ReturnCode::kDex2OatForFilterOdex),
+      Analyze(dex_location, CompilerFilter::kSpeedProfile,
+          ProfileAnalysisResult::kDontOptimizeSmallDelta, "PCL[]"));
+  // If we want to speed-profile something that was verified but the profiles are empty,
+  // don't do it - there will be no gain.
+  ASSERT_EQ(
+      static_cast<int>(ReturnCode::kNoDexOptNeeded),
+      Analyze(dex_location, CompilerFilter::kSpeedProfile,
+          ProfileAnalysisResult::kDontOptimizeEmptyProfiles, "PCL[]"));
+  // Standard case where we need to re-compile a speed-profile because of sufficient new
+  // information in the profile.
+  ASSERT_EQ(
+      static_cast<int>(ReturnCode::kDex2OatForFilterOdex),
+      Analyze(dex_location, CompilerFilter::kSpeedProfile,
+          ProfileAnalysisResult::kOptimize, "PCL[]"));
 }
 
 TEST_F(DexoptAnalyzerTest, Downgrade) {
   std::string dex_location = GetScratchDir() + "/Downgrade.jar";
+  std::string odex_location = GetOdexDir() + "/Downgrade.odex";
   Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
+  GenerateOdexForTest(dex_location.c_str(), odex_location.c_str(), CompilerFilter::kVerify);
 
-  Verify(dex_location, CompilerFilter::kSpeedProfile, false, true);
-  Verify(dex_location, CompilerFilter::kQuicken, false, true);
-  Verify(dex_location, CompilerFilter::kVerify, false, true);
+  Verify(dex_location, CompilerFilter::kSpeedProfile,
+      ProfileAnalysisResult::kDontOptimizeSmallDelta, true);
+  Verify(dex_location, CompilerFilter::kVerify,
+      ProfileAnalysisResult::kDontOptimizeSmallDelta, true);
+  Verify(dex_location, CompilerFilter::kExtract,
+      ProfileAnalysisResult::kDontOptimizeSmallDelta, true);
 }
 
-// Case: We have a MultiDEX file and up-to-date OAT file for it.
+// Case: We have a MultiDEX file and up-to-date ODEX file for it.
 TEST_F(DexoptAnalyzerTest, MultiDexOatUpToDate) {
   std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
-  Copy(GetMultiDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  std::string odex_location = GetOdexDir() + "/MultiDexOatUpToDate.odex";
 
-  Verify(dex_location, CompilerFilter::kSpeed, false);
+  Copy(GetMultiDexSrc1(), dex_location);
+  GenerateOdexForTest(dex_location.c_str(), odex_location.c_str(), CompilerFilter::kSpeed);
+
+  Verify(dex_location, CompilerFilter::kSpeed, ProfileAnalysisResult::kDontOptimizeSmallDelta);
 }
 
 // Case: We have a MultiDEX file where the secondary dex file is out of date.
 TEST_F(DexoptAnalyzerTest, MultiDexSecondaryOutOfDate) {
   std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
+  std::string odex_location = GetOdexDir() + "/MultiDexSecondaryOutOfDate.odex";
 
   // Compile code for GetMultiDexSrc1.
   Copy(GetMultiDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  GenerateOdexForTest(dex_location.c_str(), odex_location.c_str(), CompilerFilter::kSpeed);
 
   // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
   // is out of date.
   Copy(GetMultiDexSrc2(), dex_location);
 
-  Verify(dex_location, CompilerFilter::kSpeed, false);
+  Verify(dex_location, CompilerFilter::kSpeed, ProfileAnalysisResult::kDontOptimizeSmallDelta);
 }
 
-
-// Case: We have a DEX file and an OAT file out of date with respect to the
+// Case: We have a DEX file and an ODEX file out of date with respect to the
 // dex checksum.
 TEST_F(DexoptAnalyzerTest, OatDexOutOfDate) {
   std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
+  std::string odex_location = GetOdexDir() + "/OatDexOutOfDate.odex";
 
   // We create a dex, generate an oat for it, then overwrite the dex with a
   // different dex to make the oat out of date.
   Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  GenerateOdexForTest(dex_location.c_str(), odex_location.c_str(), CompilerFilter::kSpeed);
   Copy(GetDexSrc2(), dex_location);
 
   Verify(dex_location, CompilerFilter::kExtract);
   Verify(dex_location, CompilerFilter::kSpeed);
 }
 
-// Case: We have a DEX file and an OAT file out of date with respect to the
+// Case: We have a DEX file and an ODEX file out of date with respect to the
 // boot image.
 TEST_F(DexoptAnalyzerTest, OatImageOutOfDate) {
   std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
+  std::string odex_location = GetOdexDir() + "/OatImageOutOfDate.odex";
 
   Copy(GetDexSrc1(), dex_location);
   GenerateOatForTest(dex_location.c_str(),
+                     odex_location.c_str(),
                      CompilerFilter::kSpeed,
                      /*with_alternate_image=*/true);
 
   Verify(dex_location, CompilerFilter::kExtract);
-  Verify(dex_location, CompilerFilter::kQuicken);
+  Verify(dex_location, CompilerFilter::kVerify);
   Verify(dex_location, CompilerFilter::kSpeed);
 }
 
@@ -205,14 +264,16 @@
 // verify-at-runtime.
 TEST_F(DexoptAnalyzerTest, OatVerifyAtRuntimeImageOutOfDate) {
   std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
+  std::string odex_location = GetOdexDir() + "/OatVerifyAtRuntimeImageOutOfDate.odex";
 
   Copy(GetDexSrc1(), dex_location);
   GenerateOatForTest(dex_location.c_str(),
+                     odex_location.c_str(),
                      CompilerFilter::kExtract,
                      /*with_alternate_image=*/true);
 
   Verify(dex_location, CompilerFilter::kExtract);
-  Verify(dex_location, CompilerFilter::kQuicken);
+  Verify(dex_location, CompilerFilter::kVerify);
 }
 
 // Case: We have a DEX file and an ODEX file, but no OAT file.
@@ -228,51 +289,16 @@
   Verify(dex_location, CompilerFilter::kEverything);
 }
 
-// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
-TEST_F(DexoptAnalyzerTest, StrippedDexOdexNoOat) {
-  std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
-  std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
-
-  Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
-
-  // Strip the dex file
-  Copy(GetStrippedDexSrc1(), dex_location);
-
-  Verify(dex_location, CompilerFilter::kSpeed);
-}
-
-// Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file.
-TEST_F(DexoptAnalyzerTest, StrippedDexOdexOat) {
-  std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
-  std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
-
-  // Create the oat file from a different dex file so it looks out of date.
-  Copy(GetDexSrc2(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
-
-  // Create the odex file
-  Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
-
-  // Strip the dex file.
-  Copy(GetStrippedDexSrc1(), dex_location);
-
-  Verify(dex_location, CompilerFilter::kExtract);
-  Verify(dex_location, CompilerFilter::kSpeed);
-  Verify(dex_location, CompilerFilter::kEverything);
-}
-
 // Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
 // OAT file. Expect: The status is kNoDexOptNeeded.
 TEST_F(DexoptAnalyzerTest, ResourceOnlyDex) {
   std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
 
-  Copy(GetStrippedDexSrc1(), dex_location);
+  Copy(GetResourceOnlySrc1(), dex_location);
 
   Verify(dex_location, CompilerFilter::kSpeed);
   Verify(dex_location, CompilerFilter::kExtract);
-  Verify(dex_location, CompilerFilter::kQuicken);
+  Verify(dex_location, CompilerFilter::kVerify);
 }
 
 // Case: We have a DEX file, an ODEX file and an OAT file.
@@ -333,6 +359,9 @@
   // 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.c_str());
+  Verify(dex_location1, CompilerFilter::kSpeed, ProfileAnalysisResult::kDontOptimizeSmallDelta,
+      false, class_loader_context.c_str());
 }
+
+}  // namespace dexoptanalyzer
 }  // namespace art
diff --git a/disassembler/Android.bp b/disassembler/Android.bp
index 064aaea..71ad051 100644
--- a/disassembler/Android.bp
+++ b/disassembler/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 art_cc_defaults {
     name: "libart-disassembler-defaults",
     defaults: ["art_defaults"],
@@ -48,33 +57,69 @@
 art_cc_library {
     name: "libart-disassembler",
     defaults: ["libart-disassembler-defaults"],
-    shared_libs: [
-        // For disassembler_arm*.
-        "libvixl",
-    ],
+    codegen: {
+        arm: {
+            static_libs: [
+                // For disassembler_arm*.
+                "libvixl",
+            ],
+        },
+        arm64: {
+            static_libs: [
+                // For disassembler_arm*.
+                "libvixl",
+            ],
+        },
+    },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
 
+cc_defaults {
+    name: "libart-disassembler_static_defaults",
+    whole_static_libs: [
+        "libart-disassembler",
+        "libvixl",
+    ],
+}
+
 art_cc_library {
     name: "libartd-disassembler",
     defaults: [
         "art_debug_defaults",
         "libart-disassembler-defaults",
     ],
-    shared_libs: [
-        // For disassembler_arm*.
-        "libvixld",
-    ],
+    codegen: {
+        arm: {
+            static_libs: [
+                // For disassembler_arm*.
+                "libvixld",
+            ],
+        },
+        arm64: {
+            static_libs: [
+                // For disassembler_arm*.
+                "libvixld",
+            ],
+        },
+    },
 
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
 
+cc_defaults {
+    name: "libartd-disassembler_static_defaults",
+    whole_static_libs: [
+        "libartd-disassembler",
+        "libvixld",
+    ],
+}
+
 cc_library_headers {
     name: "art_disassembler_headers",
     host_supported: true,
@@ -84,6 +129,7 @@
 
     apex_available: [
         "com.android.art.debug",
-        "com.android.art.release",
+        "com.android.art",
     ],
+    min_sdk_version: "S",
 }
diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc
index 94ea006..c2156ca 100644
--- a/disassembler/disassembler_arm.cc
+++ b/disassembler/disassembler_arm.cc
@@ -68,6 +68,22 @@
           PrintLiteral(type, offset);
           return *this;
         }
+        case kCodeLocation:
+          DisassemblerStream::operator<<(label);
+          // Improve the disassembly of branch to thunk jumping to pointer from thread entrypoint.
+          if (disasm_->GetIsT32() && GetCurrentInstructionType() == vixl::aarch32::kBl) {
+            const uintptr_t begin = reinterpret_cast<uintptr_t>(options_->base_address_);
+            const uintptr_t end = reinterpret_cast<uintptr_t>(options_->end_address_);
+            uintptr_t address = label.GetLocation() + (options_->absolute_addresses_ ? 0u : begin);
+            if ((address >= begin && address < end && end - address >= 4u) &&
+                reinterpret_cast<const uint16_t*>(address)[0] == 0xf8d9 &&  // LDR Rt, [tr, #imm12]
+                (reinterpret_cast<const uint16_t*>(address)[1] >> 12) == 0xf) {  // Rt == PC
+              uint32_t imm12 = reinterpret_cast<const uint16_t*>(address)[1] & 0xfffu;
+              os() << " ; ";
+              options_->thread_offset_name_function_(os(), imm12);
+            }
+          }
+          return *this;
         default:
           return DisassemblerStream::operator<<(label);
       }
diff --git a/disassembler/disassembler_arm64.cc b/disassembler/disassembler_arm64.cc
index 49b9623..0d51cfd 100644
--- a/disassembler/disassembler_arm64.cc
+++ b/disassembler/disassembler_arm64.cc
@@ -101,13 +101,35 @@
   Disassembler::VisitLoadStoreUnsignedOffset(instr);
 
   if (instr->GetRn() == TR) {
-    int64_t offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
-    std::ostringstream tmp_stream;
-    options_->thread_offset_name_function_(tmp_stream, static_cast<uint32_t>(offset));
-    AppendToOutput(" ; %s", tmp_stream.str().c_str());
+    AppendThreadOfsetName(instr);
   }
 }
 
+void CustomDisassembler::VisitUnconditionalBranch(const Instruction* instr) {
+  Disassembler::VisitUnconditionalBranch(instr);
+
+  if (instr->Mask(UnconditionalBranchMask) == BL) {
+    const Instruction* target = instr->GetImmPCOffsetTarget();
+    if (target >= base_address_ &&
+        target < end_address_ &&
+        target->Mask(LoadStoreMask) == LDR_x &&
+        target->GetRn() == TR &&
+        target->GetRt() == IP0 &&
+        target->GetNextInstruction() < end_address_ &&
+        target->GetNextInstruction()->Mask(UnconditionalBranchToRegisterMask) == BR &&
+        target->GetNextInstruction()->GetRn() == IP0) {
+      AppendThreadOfsetName(target);
+    }
+  }
+}
+
+void CustomDisassembler::AppendThreadOfsetName(const vixl::aarch64::Instruction* instr) {
+  int64_t offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
+  std::ostringstream tmp_stream;
+  options_->thread_offset_name_function_(tmp_stream, static_cast<uint32_t>(offset));
+  AppendToOutput(" ; %s", tmp_stream.str().c_str());
+}
+
 size_t DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin) {
   const Instruction* instr = reinterpret_cast<const Instruction*>(begin);
   decoder.Decode(instr);
diff --git a/disassembler/disassembler_arm64.h b/disassembler/disassembler_arm64.h
index 89beaa9..a895dfe 100644
--- a/disassembler/disassembler_arm64.h
+++ b/disassembler/disassembler_arm64.h
@@ -53,7 +53,12 @@
   // Improve the disassembly of thread offset.
   void VisitLoadStoreUnsignedOffset(const vixl::aarch64::Instruction* instr) override;
 
+  // Improve the disassembly of branch to thunk jumping to pointer from thread entrypoint.
+  void VisitUnconditionalBranch(const vixl::aarch64::Instruction* instr) override;
+
  private:
+  void AppendThreadOfsetName(const vixl::aarch64::Instruction* instr);
+
   // Indicate if the disassembler should read data loaded from literal pools.
   // This should only be enabled if reading the target of literal loads is safe.
   // Here are possible outputs when the option is on or off:
diff --git a/dt_fd_forward/Android.bp b/dt_fd_forward/Android.bp
index e722a4d..dd321ff 100644
--- a/dt_fd_forward/Android.bp
+++ b/dt_fd_forward/Android.bp
@@ -16,6 +16,37 @@
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
 
+package {
+    default_applicable_licenses: ["art_dt_fd_forward_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "art_dt_fd_forward_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-GPL-2.0",
+        "SPDX-license-identifier-GPL-with-classpath-exception",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_defaults {
     name: "dt_fd_forward-defaults",
     host_supported: true,
@@ -49,7 +80,7 @@
     name: "libdt_fd_forward",
     defaults: ["dt_fd_forward-defaults"],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
diff --git a/dt_fd_forward/dt_fd_forward.cc b/dt_fd_forward/dt_fd_forward.cc
index d5b6de5..2a6bfda 100644
--- a/dt_fd_forward/dt_fd_forward.cc
+++ b/dt_fd_forward/dt_fd_forward.cc
@@ -52,6 +52,8 @@
 
 #include <base/strlcpy.h>
 
+#include "fd_transport.h"
+
 namespace dt_fd_forward {
 
 // Helper that puts line-number in error message.
@@ -287,6 +289,11 @@
   TEMP_FAILURE_RETRY(send(fd, kAcceptMessage, sizeof(kAcceptMessage), MSG_EOR));
 }
 
+static void SendHandshakeCompleteMessage(int fd) {
+  TEMP_FAILURE_RETRY(
+      send(fd, kHandshakeCompleteMessage, sizeof(kHandshakeCompleteMessage), MSG_EOR));
+}
+
 IOResult FdForwardTransport::ReceiveFdsFromSocket(bool* do_handshake) {
   union {
     cmsghdr cm;
@@ -402,6 +409,8 @@
         continue;
       }
     }
+    // Tell everyone we have finished the handshake.
+    SendHandshakeCompleteMessage(close_notify_fd_);
     break;
   }
   CHECK(ChangeState(TransportState::kOpening, TransportState::kOpen));
diff --git a/dt_fd_forward/export/Android.bp b/dt_fd_forward/export/Android.bp
index 4039196..a4e9673 100644
--- a/dt_fd_forward/export/Android.bp
+++ b/dt_fd_forward/export/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_dt_fd_forward_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_dt_fd_forward_license"],
+}
+
 cc_library_headers {
     name: "dt_fd_forward_export",
     export_include_dirs: ["."],
@@ -22,6 +31,7 @@
 
     apex_available: [
         "com.android.art.debug",
-        "com.android.art.release",
+        "com.android.art",
     ],
+    min_sdk_version: "S",
 }
diff --git a/dt_fd_forward/export/fd_transport.h b/dt_fd_forward/export/fd_transport.h
index 144ac5c..40dbe42 100644
--- a/dt_fd_forward/export/fd_transport.h
+++ b/dt_fd_forward/export/fd_transport.h
@@ -65,6 +65,11 @@
 // fds are closed.
 static constexpr char kAcceptMessage[] = "dt_fd_forward:ACCEPTED";
 
+// This message is sent over the fd associated with the transport when we have
+// completed the handshake. If the handshake was already performed this is sent
+// immediately.
+static constexpr char kHandshakeCompleteMessage[] = "dt_fd_forward:HANDSHAKE-COMPLETE";
+
 // This message is sent over the fd associated with the transport when we are closing the fds. This
 // can be used by the proxy to send additional data on a dup'd fd. The write_lock_fd_ will be held
 // until the other two fds are closed and then it will be released and closed.
diff --git a/imgdiag/Android.bp b/imgdiag/Android.bp
index 7c2f515..dcc1d05 100644
--- a/imgdiag/Android.bp
+++ b/imgdiag/Android.bp
@@ -16,6 +16,15 @@
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "imgdiag-defaults",
     host_supported: true,
@@ -58,7 +67,7 @@
         "libart-compiler",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -85,4 +94,9 @@
         "art_gtest_defaults",
     ],
     srcs: ["imgdiag_test.cc"],
+    target: {
+        host: {
+            required: ["imgdiagd"],
+        },
+    },
 }
diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc
index 421e7d7..e8f4d05 100644
--- a/imgdiag/imgdiag.cc
+++ b/imgdiag/imgdiag.cc
@@ -358,7 +358,7 @@
   ~ImgObjectVisitor() override { }
 
   void Visit(mirror::Object* object) override REQUIRES_SHARED(Locks::mutator_lock_) {
-    // Sanity check that we are reading a real mirror::Object
+    // Check that we are reading a real mirror::Object
     CHECK(object->GetClass() != nullptr) << "Image object at address "
                                          << object
                                          << " has null class";
@@ -514,7 +514,8 @@
   void DumpDirtyObjects() REQUIRES_SHARED(Locks::mutator_lock_) {
     for (mirror::Object* obj : dirty_objects_) {
       if (obj->IsClass()) {
-        os_ << "Private dirty object: " << obj->AsClass()->PrettyDescriptor() << "\n";
+        std::string temp;
+        os_ << "Private dirty object: " << obj->AsClass()->GetDescriptor(&temp) << "\n";
       }
     }
   }
@@ -1471,7 +1472,7 @@
       return false;
     }
     backtrace_map_t boot_map = maybe_boot_map.value_or(backtrace_map_t{});
-    // Sanity check boot_map_.
+    // Check the validity of the boot_map_.
     CHECK(boot_map.end >= boot_map.start);
 
     // Adjust the `end` of the mapping. Some other mappings may have been
@@ -1777,7 +1778,7 @@
     return str.substr(idx + 1);
   }
 
-  // Return the image location, stripped of any directories, e.g. "boot.art" or "core.art"
+  // Return the image location, stripped of any directories, e.g. "boot.art"
   static std::string GetImageLocationBaseName(const std::string& image_location) {
     return BaseName(std::string(image_location));
   }
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index a9d5db2..8bd3bd1 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "libartbase_defaults",
     defaults: ["art_defaults"],
@@ -24,9 +33,11 @@
         "base/arena_allocator.cc",
         "base/arena_bit_vector.cc",
         "base/bit_vector.cc",
+        "base/compiler_filter.cc",
         "base/enums.cc",
         "base/file_magic.cc",
         "base/file_utils.cc",
+        "base/flags.cc",
         "base/hex_dump.cc",
         "base/hiddenapi_flags.cc",
         "base/logging.cc",
@@ -36,6 +47,7 @@
         "base/memory_region.cc",
         "base/mem_map.cc",
         // "base/mem_map_fuchsia.cc", put in target when fuchsia supported by soong
+        "base/metrics/metrics_common.cc",
         "base/os_linux.cc",
         "base/runtime_debug.cc",
         "base/safe_copy.cc",
@@ -51,31 +63,31 @@
     target: {
         android: {
             srcs: [
+                "base/globals_unix.cc",
                 "base/mem_map_unix.cc",
             ],
             static_libs: [
                 // ZipArchive support, the order matters here to get all symbols.
                 "libziparchive",
-                "libz",
             ],
             shared_libs: [
+                "libz",
                 "liblog",
                 // For ashmem.
                 "libartpalette",
                 // 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.
-            version_script: "libartbase.map",
+            export_shared_lib_headers: ["libbase"], // ART's macros.h depends on libbase's macros.h.
         },
         not_windows: {
             srcs: [
                 "base/globals_unix.cc",
                 "base/mem_map_unix.cc",
             ],
+            static: {
+                cflags: ["-DART_STATIC_LIBARTBASE"],
+            },
             shared_libs: [
                 "libziparchive",
                 "libz",
@@ -85,13 +97,9 @@
                 // For common macros.
                 "libbase",
             ],
-            export_shared_lib_headers: ["libbase"],
-        },
-        linux_glibc: {
-            version_script: "libartbase.map",
+            export_shared_lib_headers: ["libbase"], // ART's macros.h depends on libbase's macros.h.
         },
         windows: {
-            version_script: "libartbase.map",
             srcs: [
                 "base/mem_map_windows.cc",
             ],
@@ -104,7 +112,8 @@
                 // For common macros.
                 "libbase",
             ],
-            export_static_lib_headers: ["libbase"],
+            export_static_lib_headers: ["libbase"], // ART's macros.h depends on libbase's macros.h.
+
             cflags: ["-Wno-thread-safety"],
         },
         darwin: {
@@ -112,25 +121,13 @@
         },
     },
     generated_sources: ["art_libartbase_operator_srcs"],
-    cflags: ["-DBUILDING_LIBART=1"],
-
-    // Utilities used by various ART libs and tools are linked in statically
-    // here to avoid shared lib dependencies outside the ART APEX. No target
-    // there should depend on these separately.
-    whole_static_libs: [
-        "liblz4",
-        "liblzma",
-    ],
 
     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.
 }
 
 cc_defaults {
     name: "libartbase_static_base_defaults",
-    static_libs: [
+    whole_static_libs: [
         "libbase",
         "libartpalette",
         "liblog",
@@ -142,13 +139,13 @@
 cc_defaults {
     name: "libartbase_static_defaults",
     defaults: ["libartbase_static_base_defaults"],
-    static_libs: ["libartbase"],
+    whole_static_libs: ["libartbase"],
 }
 
 cc_defaults {
     name: "libartbased_static_defaults",
     defaults: ["libartbase_static_base_defaults"],
-    static_libs: ["libartbased"],
+    whole_static_libs: ["libartbased"],
 }
 
 gensrcs {
@@ -168,13 +165,20 @@
     defaults: [
         "libartbase_defaults",
         "libart_nativeunwind_defaults",
+        "art_pgo_defaults",
     ],
     visibility: [
+        // TODO(b/183483755): Please visibility checks when the prebuilt
+        // libartbase is present but not preferred, and the prebuilt libdexfile
+        // hence depends on the source instead.
+        // TODO(b/172480617): Alternatively, clean up when we no longer need to
+        // support both prebuilts and sources present simultaneously.
+        "//prebuilts/module_sdk/art/current/host-exports",
         // TODO(b/133140750): Clean this up.
         "//packages/modules/NetworkStack/tests:__subpackages__",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 
@@ -217,15 +221,12 @@
     },
 }
 
-art_cc_library {
-    name: "libartbase-art-gtest",
-    defaults: ["libart-gtest-defaults"],
+art_cc_defaults {
+    name: "libartbase-art-gtest-defaults",
     srcs: [
         "base/common_art_test.cc",
     ],
     shared_libs: [
-        "libartbased",
-        "libdexfiled",
         "libbase",
         "libbacktrace",
     ],
@@ -240,11 +241,32 @@
     },
 }
 
-art_cc_test {
-    name: "art_libartbase_tests",
+art_cc_library {
+    name: "libartbase-art-gtest",
     defaults: [
-        "art_gtest_defaults",
+        "libart-gtest-defaults",
+        "libartbase-art-gtest-defaults",
     ],
+    shared_libs: [
+        "libartbase",
+        "libdexfile",
+    ],
+}
+
+art_cc_library {
+    name: "libartbased-art-gtest",
+    defaults: [
+        "libartd-gtest-defaults",
+        "libartbase-art-gtest-defaults",
+    ],
+    shared_libs: [
+        "libartbased",
+        "libdexfiled",
+    ],
+}
+
+art_cc_defaults {
+    name: "art_libartbase_tests_defaults",
     srcs: [
         "arch/instruction_set_test.cc",
         "base/arena_allocator_test.cc",
@@ -255,7 +277,10 @@
         "base/bit_table_test.cc",
         "base/bit_utils_test.cc",
         "base/bit_vector_test.cc",
+        "base/compiler_filter_test.cc",
         "base/file_utils_test.cc",
+        "base/flags_test.cc",
+        "base/hash_map_test.cc",
         "base/hash_set_test.cc",
         "base/hex_dump_test.cc",
         "base/histogram_test.cc",
@@ -267,6 +292,7 @@
         "base/membarrier_test.cc",
         "base/memory_region_test.cc",
         "base/mem_map_test.cc",
+        "base/metrics/metrics_test.cc",
         "base/safe_copy_test.cc",
         "base/scoped_flock_test.cc",
         "base/time_utils_test.cc",
@@ -280,6 +306,28 @@
     shared_libs: [
         "libbase",
     ],
+    static_libs: [
+        "libgmock",
+    ],
+}
+
+// Version of ART gtest `art_libartbase_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
+art_cc_test {
+    name: "art_libartbase_tests",
+    defaults: [
+        "art_gtest_defaults",
+        "art_libartbase_tests_defaults",
+    ],
+}
+
+// Standalone version of ART gtest `art_libartbase_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_libartbase_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_libartbase_tests_defaults",
+    ],
 }
 
 cc_library_headers {
@@ -290,7 +338,8 @@
     export_shared_lib_headers: ["libbase"],
 
     apex_available: [
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
     ],
+    min_sdk_version: "S",
 }
diff --git a/libartbase/arch/instruction_set.h b/libartbase/arch/instruction_set.h
index 6f0cf52..dbaacda 100644
--- a/libartbase/arch/instruction_set.h
+++ b/libartbase/arch/instruction_set.h
@@ -34,7 +34,7 @@
   kX86_64,
   kLast = kX86_64
 };
-std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs);
+std::ostream& operator<<(std::ostream& os, InstructionSet rhs);
 
 #if defined(__arm__)
 static constexpr InstructionSet kRuntimeISA = InstructionSet::kArm;
@@ -61,6 +61,9 @@
 // ARM64 instruction alignment. This is the recommended alignment for maximum performance.
 static constexpr size_t kArm64Alignment = 16;
 
+// ARM64 default SVE vector length.
+static constexpr size_t kArm64DefaultSVEVectorLength = 256;
+
 // X86 instruction alignment. This is the recommended alignment for maximum performance.
 static constexpr size_t kX86Alignment = 16;
 
diff --git a/libartbase/base/allocator.h b/libartbase/base/allocator.h
index 5eb6ea6..2f85286 100644
--- a/libartbase/base/allocator.h
+++ b/libartbase/base/allocator.h
@@ -67,7 +67,7 @@
   kAllocatorTagRosAlloc,
   kAllocatorTagCount,  // Must always be last element.
 };
-std::ostream& operator<<(std::ostream& os, const AllocatorTag& tag);
+std::ostream& operator<<(std::ostream& os, AllocatorTag tag);
 
 namespace TrackedAllocators {
 
diff --git a/libartbase/base/arena_allocator.cc b/libartbase/base/arena_allocator.cc
index 0e7f6cc..3438651 100644
--- a/libartbase/base/arena_allocator.cc
+++ b/libartbase/base/arena_allocator.cc
@@ -44,6 +44,7 @@
   "BlockList    ",
   "RevPostOrder ",
   "LinearOrder  ",
+  "Reachability ",
   "ConstantsMap ",
   "Predecessors ",
   "Successors   ",
diff --git a/libartbase/base/arena_allocator.h b/libartbase/base/arena_allocator.h
index a9ccae1..44c3add 100644
--- a/libartbase/base/arena_allocator.h
+++ b/libartbase/base/arena_allocator.h
@@ -53,6 +53,7 @@
   kArenaAllocBlockList,
   kArenaAllocReversePostOrder,
   kArenaAllocLinearOrder,
+  kArenaAllocReachabilityGraph,
   kArenaAllocConstantsMap,
   kArenaAllocPredecessors,
   kArenaAllocSuccessors,
diff --git a/libartbase/base/arena_bit_vector.h b/libartbase/base/arena_bit_vector.h
index 0fb6bbf..a367da8 100644
--- a/libartbase/base/arena_bit_vector.h
+++ b/libartbase/base/arena_bit_vector.h
@@ -18,6 +18,7 @@
 #define ART_LIBARTBASE_BASE_ARENA_BIT_VECTOR_H_
 
 #include "arena_object.h"
+#include "base/arena_allocator.h"
 #include "bit_vector.h"
 
 namespace art {
@@ -49,8 +50,58 @@
                  ArenaAllocKind kind = kArenaAllocGrowableBitMap);
   ~ArenaBitVector() {}
 
+  ArenaBitVector(ArenaBitVector&&) = default;
+  ArenaBitVector(const ArenaBitVector&) = delete;
+};
+
+// A BitVectorArray implementation that uses Arena allocation. See
+// BitVectorArray for more information.
+// This is a helper for dealing with 2d bit-vector arrays packed into a single
+// bit-vector
+class ArenaBitVectorArray final : public BaseBitVectorArray,
+                                  public ArenaObject<kArenaAllocGrowableBitMap> {
+ public:
+  ArenaBitVectorArray(const ArenaBitVectorArray& bv) = delete;
+  ArenaBitVectorArray& operator=(const ArenaBitVectorArray& other) = delete;
+
+  explicit ArenaBitVectorArray(ArenaBitVector&& bv) : BaseBitVectorArray(), data_(std::move(bv)) {}
+  ArenaBitVectorArray(ArenaBitVector&& bv, size_t cols)
+      : BaseBitVectorArray(BaseBitVectorArray::MaxRowsFor(bv, cols), cols), data_(std::move(bv)) {}
+
+  ArenaBitVectorArray(ArenaAllocator* allocator,
+                      size_t start_rows,
+                      size_t start_cols,
+                      bool expandable,
+                      ArenaAllocKind kind = kArenaAllocGrowableBitMap)
+      : BaseBitVectorArray(start_rows, start_cols),
+        data_(ArenaBitVector(allocator,
+                             BaseBitVectorArray::RequiredBitVectorSize(start_rows, start_cols),
+                             expandable,
+                             kind)) {}
+
+  ArenaBitVectorArray(ScopedArenaAllocator* allocator,
+                      size_t start_rows,
+                      size_t start_cols,
+                      bool expandable,
+                      ArenaAllocKind kind = kArenaAllocGrowableBitMap)
+      : BaseBitVectorArray(start_rows, start_cols),
+        data_(ArenaBitVector(allocator,
+                             BaseBitVectorArray::RequiredBitVectorSize(start_rows, start_cols),
+                             expandable,
+                             kind)) {}
+
+  ~ArenaBitVectorArray() override {}
+
+  const BitVector& GetRawData() const override {
+    return data_;
+  }
+
+  BitVector& GetRawData() override {
+    return data_;
+  }
+
  private:
-  DISALLOW_COPY_AND_ASSIGN(ArenaBitVector);
+  ArenaBitVector data_;
 };
 
 }  // namespace art
diff --git a/libartbase/base/array_ref.h b/libartbase/base/array_ref.h
index e8b3bce..064e26b 100644
--- a/libartbase/base/array_ref.h
+++ b/libartbase/base/array_ref.h
@@ -203,6 +203,19 @@
   return !(lhs == rhs);
 }
 
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const ArrayRef<T>& ts) {
+  bool first = true;
+  os << "[";
+  for (const T& t : ts) {
+    if (!first) { os << ", "; }
+    first = false;
+    os << t;
+  }
+  os << "]";
+  return os;
+}
+
 }  // namespace art
 
 
diff --git a/libartbase/base/array_slice.h b/libartbase/base/array_slice.h
index 4679146..a58ff44 100644
--- a/libartbase/base/array_slice.h
+++ b/libartbase/base/array_slice.h
@@ -17,6 +17,7 @@
 #ifndef ART_LIBARTBASE_BASE_ARRAY_SLICE_H_
 #define ART_LIBARTBASE_BASE_ARRAY_SLICE_H_
 
+#include <ostream>
 #include "bit_utils.h"
 #include "casts.h"
 #include "iteration_range.h"
@@ -63,6 +64,10 @@
             lpa != nullptr && lpa->size() != 0 ? &lpa->At(0, element_size, alignment) : nullptr,
             lpa != nullptr ? lpa->size() : 0,
             element_size) {}
+  ArraySlice(const ArraySlice<T>&) = default;
+  ArraySlice(ArraySlice<T>&&) = default;
+  ArraySlice<T>& operator=(const ArraySlice<T>&) = default;
+  ArraySlice<T>& operator=(ArraySlice<T>&&) = default;
 
   // Iterators.
   iterator begin() { return iterator(&AtUnchecked(0), element_size_); }
@@ -166,6 +171,19 @@
   size_t element_size_;
 };
 
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const ArraySlice<T>& ts) {
+  bool first = true;
+  os << "[";
+  for (const T& t : ts) {
+    if (!first) { os << ", "; }
+    first = false;
+    os << t;
+  }
+  os << "]";
+  return os;
+}
+
 }  // namespace art
 
 #endif  // ART_LIBARTBASE_BASE_ARRAY_SLICE_H_
diff --git a/libartbase/base/bit_memory_region.h b/libartbase/base/bit_memory_region.h
index 5d54445..6168488 100644
--- a/libartbase/base/bit_memory_region.h
+++ b/libartbase/base/bit_memory_region.h
@@ -172,6 +172,24 @@
     StoreBits(bit_offset + bit, src.LoadBits(bit, num_bits), num_bits);
   }
 
+  // Or bits from other bit region.
+  ALWAYS_INLINE void OrBits(size_t bit_offset, const BitMemoryRegion& src, size_t bit_length) {
+    // TODO: Load `size_t` chunks (instead of `uint32_t`) from aligned
+    // addresses except for the leading and trailing bits. Refactor to
+    // share code with StoreBits() and maybe other functions.
+    DCHECK_LE(bit_offset, bit_size_);
+    DCHECK_LE(bit_length, bit_size_ - bit_offset);
+    size_t bit = 0;
+    constexpr size_t kNumBits = BitSizeOf<uint32_t>();
+    for (; bit + kNumBits <= bit_length; bit += kNumBits) {
+      size_t old_bits = LoadBits(bit_offset + bit, kNumBits);
+      StoreBits(bit_offset + bit, old_bits | src.LoadBits(bit, kNumBits), kNumBits);
+    }
+    size_t num_bits = bit_length - bit;
+    size_t old_bits = LoadBits(bit_offset + bit, num_bits);
+    StoreBits(bit_offset + bit, old_bits | src.LoadBits(bit, num_bits), num_bits);
+  }
+
   // Count the number of set bits within the given bit range.
   ALWAYS_INLINE size_t PopCount(size_t bit_offset, size_t bit_length) const {
     DCHECK_LE(bit_offset, bit_size_);
@@ -186,6 +204,23 @@
     return count;
   }
 
+  // Check if there is any bit set within the given bit range.
+  ALWAYS_INLINE bool HasSomeBitSet(size_t bit_offset, size_t bit_length) const {
+    // TODO: Load `size_t` chunks (instead of `uint32_t`) from aligned
+    // addresses except for the leading and trailing bits. Refactor to
+    // share code with PopCount() and maybe also Compare().
+    DCHECK_LE(bit_offset, bit_size_);
+    DCHECK_LE(bit_length, bit_size_ - bit_offset);
+    size_t bit = 0;
+    constexpr size_t kNumBits = BitSizeOf<uint32_t>();
+    for (; bit + kNumBits <= bit_length; bit += kNumBits) {
+      if (LoadBits(bit_offset + bit, kNumBits) != 0u) {
+        return true;
+      }
+    }
+    return LoadBits(bit_offset + bit, bit_length - bit) != 0u;
+  }
+
   static int Compare(const BitMemoryRegion& lhs, const BitMemoryRegion& rhs) {
     if (lhs.size_in_bits() != rhs.size_in_bits()) {
       return (lhs.size_in_bits() < rhs.size_in_bits()) ? -1 : 1;
diff --git a/libartbase/base/bit_struct.h b/libartbase/base/bit_struct.h
index eca8780..4cc222c 100644
--- a/libartbase/base/bit_struct.h
+++ b/libartbase/base/bit_struct.h
@@ -277,7 +277,7 @@
 #define BITSTRUCT_UINT(bit_offset, bit_width)                                  \
     BitStructUint<(bit_offset), (bit_width), StorageType>
 
-// End the definition of a bitstruct, and insert a sanity check
+// End the definition of a bitstruct, and insert a check
 // to ensure that the bitstruct did not exceed the specified size.
 //
 // See top of file for usage example.
diff --git a/libartbase/base/bit_vector.cc b/libartbase/base/bit_vector.cc
index c706c7e..d3cb652 100644
--- a/libartbase/base/bit_vector.cc
+++ b/libartbase/base/bit_vector.cc
@@ -45,9 +45,10 @@
               allocator,
               BitsToWords(start_bits),
               static_cast<uint32_t*>(allocator->Alloc(BitsToWords(start_bits) * kWordBytes))) {
+  // We don't know if the allocator cleared things.
+  ClearAllBits();
 }
 
-
 BitVector::BitVector(const BitVector& src,
                      bool expandable,
                      Allocator* allocator)
@@ -60,7 +61,10 @@
 }
 
 BitVector::~BitVector() {
-  allocator_->Free(storage_);
+  if (storage_ != nullptr) {
+    // Only free if we haven't been moved out of.
+    allocator_->Free(storage_);
+  }
 }
 
 bool BitVector::SameBitsSet(const BitVector *src) const {
@@ -154,7 +158,7 @@
 
     EnsureSize(highest_bit);
 
-    // Paranoid: storage size should be big enough to hold this bit now.
+    // Check: storage size should be big enough to hold this bit now.
     DCHECK_LT(static_cast<uint32_t> (highest_bit), storage_size_ * kWordBits);
   }
 
@@ -186,7 +190,7 @@
   if (storage_size_ < union_with_size) {
     EnsureSize(highest_bit);
 
-    // Paranoid: storage size should be big enough to hold this bit now.
+    // Check: storage size should be big enough to hold this bit now.
     DCHECK_LT(static_cast<uint32_t> (highest_bit), storage_size_ * kWordBits);
   }
 
@@ -372,4 +376,31 @@
   return allocator_;
 }
 
+void BaseBitVectorArray::Resize(size_t rows, size_t cols, bool clear) {
+  DCHECK(IsExpandable());
+  if (clear) {
+    Clear();
+  }
+  cols = RoundUp(cols, BitVector::kWordBits);
+  num_columns_ = cols;
+  num_rows_ = rows;
+  // Ensure size
+  GetRawData().SetBit(num_rows_ * num_columns_ - 1);
+  GetRawData().ClearBit(num_rows_ * num_columns_ - 1);
+}
+
+// In order to improve performance we do this in 4-byte blocks. Clang should be
+// able to optimize this to larger blocks if possible.
+void BaseBitVectorArray::UnionRows(size_t dest_row, size_t other) {
+  DCHECK_LT(dest_row, num_rows_);
+  DCHECK_LT(other, num_rows_);
+  size_t block_words = num_columns_ / BitVector::kWordBits;
+  uint32_t* dest =
+      GetRawData().GetRawStorage() + ((dest_row * num_columns_) / BitVector::kWordBits);
+  uint32_t* source = GetRawData().GetRawStorage() + ((other * num_columns_) / BitVector::kWordBits);
+  for (uint32_t i = 0; i < block_words; ++i, ++dest, ++source) {
+    *dest = (*dest) | (*source);
+  }
+}
+
 }  // namespace art
diff --git a/libartbase/base/bit_vector.h b/libartbase/base/bit_vector.h
index a930f4e..0c735cc 100644
--- a/libartbase/base/bit_vector.h
+++ b/libartbase/base/bit_vector.h
@@ -18,6 +18,7 @@
 #define ART_LIBARTBASE_BASE_BIT_VECTOR_H_
 
 #include <stdint.h>
+
 #include <iterator>
 
 #include "bit_utils.h"
@@ -26,6 +27,7 @@
 namespace art {
 
 class Allocator;
+class ArenaBitVector;
 
 /*
  * Expanding bitmap, used for tracking resources.  Bits are numbered starting
@@ -33,6 +35,9 @@
  */
 class BitVector {
  public:
+  static constexpr uint32_t kWordBytes = sizeof(uint32_t);
+  static constexpr uint32_t kWordBits = kWordBytes * 8;
+
   class IndexContainer;
 
   /**
@@ -47,7 +52,7 @@
    *   }
    */
   class IndexIterator :
-      std::iterator<std::forward_iterator_tag, uint32_t, ptrdiff_t, void, uint32_t> {
+      public std::iterator<std::forward_iterator_tag, uint32_t, ptrdiff_t, void, uint32_t> {
    public:
     bool operator==(const IndexIterator& other) const;
 
@@ -226,11 +231,22 @@
     return storage_size_ * kWordBytes;
   }
 
+  size_t GetBitSizeOf() const {
+    return storage_size_ * kWordBits;
+  }
+
   /**
    * @return the highest bit set, -1 if none are set
    */
   int GetHighestBitSet() const;
 
+  /**
+   * @return true if there are any bits set, false otherwise.
+   */
+  bool IsAnyBitSet() const {
+    return GetHighestBitSet() != -1;
+  }
+
   // Minimum number of bits required to store this vector, 0 if none are set.
   size_t GetNumberOfBits() const {
     return GetHighestBitSet() + 1;
@@ -281,15 +297,148 @@
     return 1 << (idx & 0x1f);
   }
 
-  static constexpr uint32_t kWordBytes = sizeof(uint32_t);
-  static constexpr uint32_t kWordBits = kWordBytes * 8;
-
   uint32_t*  storage_;            // The storage for the bit vector.
   uint32_t   storage_size_;       // Current size, in 32-bit words.
   Allocator* const allocator_;    // Allocator if expandable.
   const bool expandable_;         // Should the bitmap expand if too small?
 };
 
+// Helper for dealing with 2d bit-vector arrays packed into a single bit-vec
+class BaseBitVectorArray {
+ public:
+  BaseBitVectorArray(const BaseBitVectorArray& bv) = default;
+  BaseBitVectorArray& operator=(const BaseBitVectorArray& other) = default;
+
+  BaseBitVectorArray() : num_columns_(0), num_rows_(0) {}
+
+  BaseBitVectorArray(size_t num_rows, size_t num_columns)
+      : num_columns_(RoundUp(num_columns, BitVector::kWordBits)), num_rows_(num_rows) {}
+
+  virtual ~BaseBitVectorArray() {}
+
+  bool IsExpandable() const {
+    return GetRawData().IsExpandable();
+  }
+
+  // Let subclasses provide storage for various types.
+  virtual const BitVector& GetRawData() const = 0;
+  virtual BitVector& GetRawData() = 0;
+
+  size_t NumRows() const {
+    return num_rows_;
+  }
+
+  // NB This might be more than the requested size for alignment purposes.
+  size_t NumColumns() const {
+    return num_columns_;
+  }
+
+  void Clear() {
+    GetRawData().ClearAllBits();
+  }
+
+  // Ensure that we can set all bits in the given range. The actual number of
+  // columns might be larger than requested for alignment purposes.
+  void Resize(size_t rows, size_t cols, bool clear = true);
+
+  void SetBit(size_t row, size_t col) {
+    DCHECK_LT(col, num_columns_);
+    DCHECK_LT(row, num_rows_);
+    GetRawData().SetBit(row * num_columns_ + col);
+  }
+
+  void ClearBit(size_t row, size_t col) {
+    DCHECK_LT(col, num_columns_);
+    DCHECK_LT(row, num_rows_);
+    GetRawData().ClearBit(row * num_columns_ + col);
+  }
+
+  bool IsBitSet(size_t row, size_t col) const {
+    DCHECK_LT(col, num_columns_);
+    DCHECK_LT(row, num_rows_);
+    return GetRawData().IsBitSet(row * num_columns_ + col);
+  }
+
+  // Union the vector of 'other' into 'dest_row'.
+  void UnionRows(size_t dest_row, size_t other);
+
+  static size_t RequiredBitVectorSize(size_t rows, size_t cols) {
+    return rows * RoundUp(cols, BitVector::kWordBits);
+  }
+
+  static size_t MaxRowsFor(const BitVector& bv, size_t cols) {
+    return cols != 0 ? bv.GetBitSizeOf() / RoundUp(cols, BitVector::kWordBits) : 0;
+  }
+
+ private:
+  size_t num_columns_;
+  size_t num_rows_;
+};
+
+// A BitVectorArray with a standard owned BitVector providing the backing
+// storage. This should be used when the BitVectorArray is the owner of the
+// whole BitVector and should use standard allocators for cleanup/allocation.
+// Contrast this with ArenaBitVectorArray which uses arena allocators.
+class BitVectorArray final : public BaseBitVectorArray {
+ public:
+  BitVectorArray(const BitVectorArray& bv) = delete;
+  BitVectorArray& operator=(const BitVectorArray& other) = delete;
+
+  explicit BitVectorArray(BitVector&& bv) : BaseBitVectorArray(), data_(std::move(bv)) {}
+  explicit BitVectorArray(BitVector&& bv, size_t cols)
+      : BaseBitVectorArray(BaseBitVectorArray::MaxRowsFor(bv, cols), cols), data_(std::move(bv)) {}
+  explicit BitVectorArray(BitVector&& bv, size_t rows, size_t cols)
+      : BaseBitVectorArray(rows, cols), data_(std::move(bv)) {}
+
+  BitVectorArray(uint32_t start_rows, uint32_t start_cols, bool expandable, Allocator* allocator)
+      : BaseBitVectorArray(start_rows, start_cols),
+        data_(BaseBitVectorArray::RequiredBitVectorSize(start_rows, start_cols),
+              expandable,
+              allocator) {}
+
+  BitVectorArray(const BaseBitVectorArray& src, bool expandable, Allocator* allocator)
+      : BaseBitVectorArray(src.NumRows(), src.NumColumns()),
+        data_(src.GetRawData(), expandable, allocator) {}
+
+  ~BitVectorArray() override {}
+
+  const BitVector& GetRawData() const override {
+    return data_;
+  }
+
+  BitVector& GetRawData() override {
+    return data_;
+  }
+
+ private:
+  BitVector data_;
+};
+
+// A bit vector array that uses an unowned BitVector reference as it's backing
+// data.
+class BitVectorArrayWrapper final : public BaseBitVectorArray {
+ public:
+  BitVectorArrayWrapper& operator=(BitVectorArrayWrapper& other) = default;
+  BitVectorArrayWrapper(BitVectorArrayWrapper&) = default;
+  explicit BitVectorArrayWrapper(BitVector* bv) : BaseBitVectorArray(), data_(bv) {}
+  explicit BitVectorArrayWrapper(BitVector* bv, size_t cols)
+      : BaseBitVectorArray(BaseBitVectorArray::MaxRowsFor(*bv, cols), cols), data_(bv) {}
+  explicit BitVectorArrayWrapper(BitVector* bv, size_t rows, size_t cols)
+      : BaseBitVectorArray(rows, cols), data_(bv) {}
+
+  ~BitVectorArrayWrapper() override {}
+
+  const BitVector& GetRawData() const override {
+    return *data_;
+  }
+
+  BitVector& GetRawData() override {
+    return *data_;
+  }
+
+ private:
+  BitVector* data_;
+};
 
 }  // namespace art
 
diff --git a/libartbase/base/bit_vector_test.cc b/libartbase/base/bit_vector_test.cc
index 0e3df76..5f1b167 100644
--- a/libartbase/base/bit_vector_test.cc
+++ b/libartbase/base/bit_vector_test.cc
@@ -15,10 +15,13 @@
  */
 
 #include <memory>
+#include <random>
 
 #include "allocator.h"
+#include "base/stl_util.h"
 #include "bit_vector-inl.h"
 #include "gtest/gtest.h"
+#include "transform_iterator.h"
 
 namespace art {
 
@@ -65,6 +68,32 @@
   EXPECT_TRUE(iterator == bv.Indexes().end());
 }
 
+struct MessyAllocator : public Allocator {
+ public:
+  MessyAllocator() : malloc_(Allocator::GetMallocAllocator()) {}
+  ~MessyAllocator() {}
+
+  void* Alloc(size_t s) override {
+    void* res = malloc_->Alloc(s);
+    memset(res, 0xfe, s);
+    return res;
+  }
+
+  void Free(void* v) override {
+    malloc_->Free(v);
+  }
+
+ private:
+  Allocator* malloc_;
+};
+
+TEST(BitVector, MessyAllocator) {
+  MessyAllocator alloc;
+  BitVector bv(32, false, &alloc);
+  EXPECT_EQ(bv.NumSetBits(), 0u);
+  EXPECT_EQ(bv.GetHighestBitSet(), -1);
+}
+
 TEST(BitVector, NoopAllocator) {
   const uint32_t kWords = 2;
 
@@ -269,4 +298,125 @@
   }
 }
 
+TEST(BitVector, TransformIterator) {
+  BitVector bv(16, false, Allocator::GetMallocAllocator());
+  bv.SetBit(4);
+  bv.SetBit(8);
+
+  auto indexs = bv.Indexes();
+  for (int32_t negative :
+       MakeTransformRange(indexs, [](uint32_t idx) { return -1 * static_cast<int32_t>(idx); })) {
+    EXPECT_TRUE(negative == -4 || negative == -8);
+  }
+}
+
+class SingleAllocator : public Allocator {
+ public:
+  SingleAllocator() : alloc_count_(0), free_count_(0) {}
+  ~SingleAllocator() {
+    EXPECT_EQ(alloc_count_, 1u);
+    EXPECT_EQ(free_count_, 1u);
+  }
+
+  void* Alloc(size_t s) override {
+    EXPECT_LT(s, 1024ull);
+    EXPECT_EQ(alloc_count_, free_count_);
+    ++alloc_count_;
+    return bytes_.begin();
+  }
+
+  void Free(void*) override {
+    ++free_count_;
+  }
+
+  uint32_t AllocCount() const {
+    return alloc_count_;
+  }
+  uint32_t FreeCount() const {
+    return free_count_;
+  }
+
+ private:
+  std::array<uint8_t, 1024> bytes_;
+  uint32_t alloc_count_;
+  uint32_t free_count_;
+};
+
+TEST(BitVector, MovementFree) {
+  SingleAllocator alloc;
+  {
+    BitVector bv(16, false, &alloc);
+    bv.SetBit(13);
+    EXPECT_EQ(alloc.FreeCount(), 0u);
+    EXPECT_EQ(alloc.AllocCount(), 1u);
+    ASSERT_TRUE(bv.GetRawStorage() != nullptr);
+    EXPECT_TRUE(bv.IsBitSet(13));
+    {
+      BitVector bv2(std::move(bv));
+      ASSERT_TRUE(bv.GetRawStorage() == nullptr);
+      EXPECT_TRUE(bv2.IsBitSet(13));
+      EXPECT_EQ(alloc.FreeCount(), 0u);
+      EXPECT_EQ(alloc.AllocCount(), 1u);
+    }
+    EXPECT_EQ(alloc.FreeCount(), 1u);
+    EXPECT_EQ(alloc.AllocCount(), 1u);
+  }
+  EXPECT_EQ(alloc.FreeCount(), 1u);
+  EXPECT_EQ(alloc.AllocCount(), 1u);
+}
+
+TEST(BitVector, ArrayCol) {
+  {
+    BitVectorArray bva(100, 200, true, Allocator::GetMallocAllocator());
+    for (uint32_t i : Range(bva.NumColumns())) {
+      bva.SetBit(bva.NumRows() / 2, i);
+    }
+    EXPECT_EQ(bva.GetRawData().NumSetBits(), bva.NumColumns());
+  }
+  {
+    BitVectorArray bva(100, 200, true, Allocator::GetMallocAllocator());
+    for (uint32_t i : Range(bva.NumRows())) {
+      bva.SetBit(i, bva.NumColumns() / 2);
+    }
+    EXPECT_EQ(bva.GetRawData().NumSetBits(), bva.NumRows());
+  }
+}
+
+TEST(BitVector, ArrayUnion) {
+  {
+    BitVectorArray bva(100, 200, true, Allocator::GetMallocAllocator());
+    bva.SetBit(4, 12);
+    bva.SetBit(40, 120);
+    bva.SetBit(40, 121);
+    bva.SetBit(40, 122);
+
+    bva.UnionRows(4, 40);
+
+    EXPECT_TRUE(bva.IsBitSet(4, 12));
+    EXPECT_TRUE(bva.IsBitSet(4, 120));
+    EXPECT_TRUE(bva.IsBitSet(4, 121));
+    EXPECT_TRUE(bva.IsBitSet(4, 122));
+    EXPECT_FALSE(bva.IsBitSet(40, 12));
+    EXPECT_TRUE(bva.IsBitSet(40, 120));
+    EXPECT_TRUE(bva.IsBitSet(40, 121));
+    EXPECT_TRUE(bva.IsBitSet(40, 122));
+    EXPECT_EQ(bva.GetRawData().NumSetBits(), 7u);
+  }
+  {
+    BitVectorArray bva(100, 100, true, Allocator::GetMallocAllocator());
+    for (uint32_t i : Range(bva.NumRows())) {
+      bva.SetBit(i, i);
+    }
+    for (uint32_t i : Range(1, bva.NumRows())) {
+      bva.UnionRows(0, i);
+    }
+    for (uint32_t col : Range(bva.NumColumns())) {
+      for (uint32_t row : Range(bva.NumRows())) {
+        // We set every bit where row== column and every bit on row 0 up to number of rows.
+        EXPECT_EQ(bva.IsBitSet(row, col), row == col || (row == 0 && col < bva.NumRows()));
+      }
+    }
+  }
+}
+
 }  // namespace art
diff --git a/libartbase/base/common_art_test.cc b/libartbase/base/common_art_test.cc
index 978f69c..843f286 100644
--- a/libartbase/base/common_art_test.cc
+++ b/libartbase/base/common_art_test.cc
@@ -16,14 +16,15 @@
 
 #include "common_art_test.h"
 
+#include <cstdio>
 #include <dirent.h>
 #include <dlfcn.h>
 #include <fcntl.h>
+#include <filesystem>
 #include <ftw.h>
+#include <libgen.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <cstdio>
-#include <filesystem>
 #include "android-base/file.h"
 #include "android-base/logging.h"
 #include "nativehelper/scoped_local_ref.h"
@@ -41,6 +42,7 @@
 #include "base/os.h"
 #include "base/runtime_debug.h"
 #include "base/stl_util.h"
+#include "base/string_view_cpp20.h"
 #include "base/unix_file/fd_file.h"
 #include "dex/art_dex_file_loader.h"
 #include "dex/dex_file-inl.h"
@@ -52,7 +54,7 @@
 
 using android::base::StringPrintf;
 
-ScratchDir::ScratchDir() {
+ScratchDir::ScratchDir(bool keep_files) : keep_files_(keep_files) {
   // ANDROID_DATA needs to be set
   CHECK_NE(static_cast<char*>(nullptr), getenv("ANDROID_DATA")) <<
       "Are you subclassing RuntimeTest?";
@@ -64,15 +66,17 @@
 }
 
 ScratchDir::~ScratchDir() {
-  // Recursively delete the directory and all its content.
-  nftw(path_.c_str(), [](const char* name, const struct stat*, int type, struct FTW *) {
-    if (type == FTW_F) {
-      unlink(name);
-    } else if (type == FTW_DP) {
-      rmdir(name);
-    }
-    return 0;
-  }, 256 /* max open file descriptors */, FTW_DEPTH);
+  if (!keep_files_) {
+    // Recursively delete the directory and all its content.
+    nftw(path_.c_str(), [](const char* name, const struct stat*, int type, struct FTW *) {
+      if (type == FTW_F) {
+        unlink(name);
+      } else if (type == FTW_DP) {
+        rmdir(name);
+      }
+      return 0;
+    }, 256 /* max open file descriptors */, FTW_DEPTH);
+  }
 }
 
 ScratchFile::ScratchFile() {
@@ -122,10 +126,11 @@
 }
 
 void ScratchFile::Close() {
-  if (file_.get() != nullptr) {
+  if (file_ != nullptr) {
     if (file_->FlushCloseOrErase() != 0) {
       PLOG(WARNING) << "Error closing scratch file.";
     }
+    file_.reset();
   }
 }
 
@@ -138,62 +143,99 @@
   CHECK_EQ(0, unlink_result);
 }
 
+std::string CommonArtTestImpl::GetAndroidBuildTop() {
+  CHECK(IsHost());
+  std::string android_build_top;
+
+  // Look at how we were invoked to find the expected directory.
+  std::string argv;
+  if (android::base::ReadFileToString("/proc/self/cmdline", &argv)) {
+    // /proc/self/cmdline is the programs 'argv' with elements delimited by '\0'.
+    std::filesystem::path path(argv.substr(0, argv.find('\0')));
+    path = std::filesystem::absolute(path);
+    // Walk up until we find the one of the well-known directories.
+    for (; path.parent_path() != path; path = path.parent_path()) {
+      // We are running tests from out/host/linux-x86 on developer machine.
+      if (path.filename() == std::filesystem::path("linux-x86")) {
+        android_build_top = path.parent_path().parent_path().parent_path();
+        break;
+      }
+      // We are running tests from testcases (extracted from zip) on tradefed.
+      // The first path is for remote runs and the second path for local runs.
+      if (path.filename() == std::filesystem::path("testcases") ||
+          StartsWith(path.filename().string(), "host_testcases")) {
+        android_build_top = path.append("art_common");
+        break;
+      }
+    }
+  }
+  CHECK(!android_build_top.empty());
+
+  // Check that the expected directory matches the environment variable.
+  const char* android_build_top_from_env = getenv("ANDROID_BUILD_TOP");
+  android_build_top = std::filesystem::path(android_build_top).string();
+  CHECK(!android_build_top.empty());
+  if (android_build_top_from_env != nullptr) {
+    if (std::filesystem::weakly_canonical(android_build_top).string() !=
+        std::filesystem::weakly_canonical(android_build_top_from_env).string()) {
+      LOG(WARNING) << "Execution path (" << argv << ") not below ANDROID_BUILD_TOP ("
+                   << android_build_top_from_env << ")! Using env-var.";
+      android_build_top = android_build_top_from_env;
+    }
+  } else {
+    setenv("ANDROID_BUILD_TOP", android_build_top.c_str(), /*overwrite=*/0);
+  }
+  if (android_build_top.back() != '/') {
+    android_build_top += '/';
+  }
+  return android_build_top;
+}
+
+std::string CommonArtTestImpl::GetAndroidHostOut() {
+  CHECK(IsHost());
+
+  // Check that the expected directory matches the environment variable.
+  // ANDROID_HOST_OUT is set by envsetup or unset and is the full path to host binaries/libs
+  const char* android_host_out_from_env = getenv("ANDROID_HOST_OUT");
+  // OUT_DIR is a user-settable ENV_VAR that controls where soong puts build artifacts. It can
+  // either be relative to ANDROID_BUILD_TOP or a concrete path.
+  const char* android_out_dir = getenv("OUT_DIR");
+  // Take account of OUT_DIR setting.
+  if (android_out_dir == nullptr) {
+    android_out_dir = "out";
+  }
+  std::string android_host_out;
+  if (android_out_dir[0] == '/') {
+    android_host_out = (std::filesystem::path(android_out_dir) / "host" / "linux-x86").string();
+  } else {
+    android_host_out =
+        (std::filesystem::path(GetAndroidBuildTop()) / android_out_dir / "host" / "linux-x86")
+            .string();
+  }
+  std::filesystem::path expected(android_host_out);
+  if (android_host_out_from_env != nullptr) {
+    std::filesystem::path from_env(std::filesystem::weakly_canonical(android_host_out_from_env));
+    if (std::filesystem::weakly_canonical(expected).string() != from_env.string()) {
+      LOG(WARNING) << "Execution path (" << expected << ") not below ANDROID_HOST_OUT ("
+                   << from_env << ")! Using env-var.";
+      expected = from_env;
+    }
+  } else {
+    setenv("ANDROID_HOST_OUT", android_host_out.c_str(), /*overwrite=*/0);
+  }
+  return expected.string();
+}
+
 void CommonArtTestImpl::SetUpAndroidRootEnvVars() {
   if (IsHost()) {
-    // Make sure that ANDROID_BUILD_TOP is set. If not, set it from CWD.
-    const char* android_build_top_from_env = getenv("ANDROID_BUILD_TOP");
-    if (android_build_top_from_env == nullptr) {
-      // Not set by build server, so default to current directory.
-      char* cwd = getcwd(nullptr, 0);
-      setenv("ANDROID_BUILD_TOP", cwd, 1);
-      free(cwd);
-      android_build_top_from_env = getenv("ANDROID_BUILD_TOP");
-    }
-
-    const char* android_host_out_from_env = getenv("ANDROID_HOST_OUT");
-    if (android_host_out_from_env == nullptr) {
-      // Not set by build server, so default to the usual value of
-      // ANDROID_HOST_OUT.
-      std::string android_host_out;
-#if defined(__linux__)
-      // Fallback
-      android_host_out = std::string(android_build_top_from_env) + "/out/host/linux-x86";
-      // Look at how we were invoked
-      std::string argv;
-      if (android::base::ReadFileToString("/proc/self/cmdline", &argv)) {
-        // /proc/self/cmdline is the programs 'argv' with elements delimited by '\0'.
-        std::string cmdpath(argv.substr(0, argv.find('\0')));
-        std::filesystem::path path(cmdpath);
-        // If the path is relative then prepend the android_build_top_from_env to it
-        if (path.is_relative()) {
-          path = std::filesystem::path(android_build_top_from_env).append(cmdpath);
-          DCHECK(path.is_absolute()) << path;
-        }
-        // Walk up until we find the linux-x86 directory or we hit the root directory.
-        while (path.has_parent_path() && path.parent_path() != path &&
-               path.filename() != std::filesystem::path("linux-x86")) {
-          path = path.parent_path();
-        }
-        // If we found a linux-x86 directory path is now android_host_out
-        if (path.filename() == std::filesystem::path("linux-x86")) {
-          android_host_out = path.string();
-        }
-      }
-#elif defined(__APPLE__)
-      android_host_out = std::string(android_build_top_from_env) + "/out/host/darwin-x86";
-#else
-#error unsupported OS
-#endif
-      setenv("ANDROID_HOST_OUT", android_host_out.c_str(), 1);
-      android_host_out_from_env = getenv("ANDROID_HOST_OUT");
-    }
+    std::string android_host_out = GetAndroidHostOut();
 
     // Environment variable ANDROID_ROOT is set on the device, but not
     // necessarily on the host.
     const char* android_root_from_env = getenv("ANDROID_ROOT");
     if (android_root_from_env == nullptr) {
       // Use ANDROID_HOST_OUT for ANDROID_ROOT.
-      setenv("ANDROID_ROOT", android_host_out_from_env, 1);
+      setenv("ANDROID_ROOT", android_host_out.c_str(), 1);
       android_root_from_env = getenv("ANDROID_ROOT");
     }
 
@@ -203,7 +245,7 @@
     const char* android_i18n_root_from_env = getenv("ANDROID_I18N_ROOT");
     if (android_i18n_root_from_env == nullptr) {
       // Use ${ANDROID_I18N_OUT}/com.android.i18n for ANDROID_I18N_ROOT.
-      std::string android_i18n_root = android_host_out_from_env;
+      std::string android_i18n_root = android_host_out.c_str();
       android_i18n_root += "/com.android.i18n";
       setenv("ANDROID_I18N_ROOT", android_i18n_root.c_str(), 1);
     }
@@ -214,7 +256,7 @@
     const char* android_art_root_from_env = getenv("ANDROID_ART_ROOT");
     if (android_art_root_from_env == nullptr) {
       // Use ${ANDROID_HOST_OUT}/com.android.art for ANDROID_ART_ROOT.
-      std::string android_art_root = android_host_out_from_env;
+      std::string android_art_root = android_host_out.c_str();
       android_art_root += "/com.android.art";
       setenv("ANDROID_ART_ROOT", android_art_root.c_str(), 1);
     }
@@ -225,7 +267,7 @@
     const char* android_tzdata_root_from_env = getenv("ANDROID_TZDATA_ROOT");
     if (android_tzdata_root_from_env == nullptr) {
       // Use ${ANDROID_HOST_OUT}/com.android.tzdata for ANDROID_TZDATA_ROOT.
-      std::string android_tzdata_root = android_host_out_from_env;
+      std::string android_tzdata_root = android_host_out.c_str();
       android_tzdata_root += "/com.android.tzdata";
       setenv("ANDROID_TZDATA_ROOT", android_tzdata_root.c_str(), 1);
     }
@@ -235,7 +277,6 @@
 }
 
 void CommonArtTestImpl::SetUpAndroidDataDir(std::string& android_data) {
-  // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
   if (IsHost()) {
     const char* tmpdir = getenv("TMPDIR");
     if (tmpdir != nullptr && tmpdir[0] != 0) {
@@ -244,7 +285,11 @@
       android_data = "/tmp";
     }
   } else {
-    android_data = "/data/dalvik-cache";
+    // On target, we cannot use `/mnt/sdcard` because it is mounted `noexec`,
+    // nor `/data/dalvik-cache` as it is not accessible on `user` builds.
+    // Instead, use `/data/local/tmp`, which does not require any special
+    // permission.
+    android_data = "/data/local/tmp";
   }
   android_data += "/art-data-XXXXXX";
   if (mkdtemp(&android_data[0]) == nullptr) {
@@ -254,17 +299,35 @@
 }
 
 void CommonArtTestImpl::SetUp() {
+  // Some tests clear these and when running with --no_isolate this can cause
+  // later tests to fail
+  Locks::Init();
+  MemMap::Init();
   SetUpAndroidRootEnvVars();
   SetUpAndroidDataDir(android_data_);
-  dalvik_cache_.append(android_data_.c_str());
-  dalvik_cache_.append("/dalvik-cache");
-  int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
+
+  // Re-use the data temporary directory for /system_ext tests
+  android_system_ext_.append(android_data_.c_str());
+  android_system_ext_.append("/system_ext");
+  int mkdir_result = mkdir(android_system_ext_.c_str(), 0700);
+  ASSERT_EQ(mkdir_result, 0);
+  setenv("ANDROID_SYSTEM_EXT", android_system_ext_.c_str(), 1);
+
+  std::string system_ext_framework = android_system_ext_ + "/framework";
+  mkdir_result = mkdir(system_ext_framework.c_str(), 0700);
   ASSERT_EQ(mkdir_result, 0);
 
-  static bool gSlowDebugTestFlag = false;
-  RegisterRuntimeDebugFlag(&gSlowDebugTestFlag);
-  SetRuntimeDebugFlagsEnabled(true);
-  CHECK(gSlowDebugTestFlag);
+  dalvik_cache_.append(android_data_.c_str());
+  dalvik_cache_.append("/dalvik-cache");
+  mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
+  ASSERT_EQ(mkdir_result, 0);
+
+  if (kIsDebugBuild) {
+    static bool gSlowDebugTestFlag = false;
+    RegisterRuntimeDebugFlag(&gSlowDebugTestFlag);
+    SetRuntimeDebugFlagsEnabled(true);
+    CHECK(gSlowDebugTestFlag);
+  }
 }
 
 void CommonArtTestImpl::TearDownAndroidDataDir(const std::string& android_data,
@@ -276,52 +339,20 @@
   }
 }
 
-// Helper - find directory with the following format:
-// ${ANDROID_BUILD_TOP}/${subdir1}/${subdir2}-${version}/${subdir3}/bin/
-std::string CommonArtTestImpl::GetAndroidToolsDir(const std::string& subdir1,
-                                                  const std::string& subdir2,
-                                                  const std::string& subdir3) {
-  std::string root;
-  const char* android_build_top = getenv("ANDROID_BUILD_TOP");
-  if (android_build_top != nullptr) {
-    root = android_build_top;
-  } else {
-    // Not set by build server, so default to current directory
-    char* cwd = getcwd(nullptr, 0);
-    setenv("ANDROID_BUILD_TOP", cwd, 1);
-    root = cwd;
-    free(cwd);
-  }
-
-  std::string toolsdir = root + "/" + subdir1;
-  std::string founddir;
-  DIR* dir;
-  if ((dir = opendir(toolsdir.c_str())) != nullptr) {
-    float maxversion = 0;
-    struct dirent* entry;
-    while ((entry = readdir(dir)) != nullptr) {
-      std::string format = subdir2 + "-%f";
-      float version;
-      if (std::sscanf(entry->d_name, format.c_str(), &version) == 1) {
-        if (version > maxversion) {
-          maxversion = version;
-          founddir = toolsdir + "/" + entry->d_name + "/" + subdir3 + "/bin/";
-        }
-      }
-    }
-    closedir(dir);
-  }
-
-  if (founddir.empty()) {
-    ADD_FAILURE() << "Cannot find Android tools directory.";
-  }
-  return founddir;
-}
-
-std::string CommonArtTestImpl::GetAndroidHostToolsDir() {
-  return GetAndroidToolsDir("prebuilts/gcc/linux-x86/host",
-                            "x86_64-linux-glibc2.17",
-                            "x86_64-linux");
+// Get prebuilt binary tool.
+// The paths need to be updated when Android prebuilts update.
+std::string CommonArtTestImpl::GetAndroidTool(const char* name, InstructionSet) {
+#ifndef ART_CLANG_PATH
+  UNUSED(name);
+  LOG(FATAL) << "There are no prebuilt tools available.";
+  UNREACHABLE();
+#else
+  std::string path = GetAndroidBuildTop() + ART_CLANG_PATH + "/bin/";
+  CHECK(OS::DirectoryExists(path.c_str())) << path;
+  path += name;
+  CHECK(OS::FileExists(path.c_str())) << path;
+  return path;
+#endif
 }
 
 std::string CommonArtTestImpl::GetCoreArtLocation() {
@@ -338,14 +369,18 @@
   MemMap::Init();
   static constexpr bool kVerifyChecksum = true;
   const ArtDexFileLoader dex_file_loader;
-  if (!dex_file_loader.Open(
-        location, location, /* verify= */ true, kVerifyChecksum, &error_msg, &dex_files)) {
-    LOG(FATAL) << "Could not open .dex file '" << location << "': " << error_msg << "\n";
+  std::string filename(IsHost() ? GetAndroidBuildTop() + location : location);
+  if (!dex_file_loader.Open(filename.c_str(),
+                            std::string(location),
+                            /* verify= */ true,
+                            kVerifyChecksum,
+                            &error_msg,
+                            &dex_files)) {
+    LOG(FATAL) << "Could not open .dex file '" << filename << "': " << error_msg << "\n";
     UNREACHABLE();
-  } else {
-    CHECK_EQ(1U, dex_files.size()) << "Expected only one dex file in " << location;
-    return std::move(dex_files[0]);
   }
+  CHECK_EQ(1U, dex_files.size()) << "Expected only one dex file in " << filename;
+  return std::move(dex_files[0]);
 }
 
 void CommonArtTestImpl::ClearDirectory(const char* dirpath, bool recursive) {
@@ -383,33 +418,35 @@
   ClearDirectory(dalvik_cache_.c_str());
   int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
   ASSERT_EQ(0, rmdir_cache_result);
+  ClearDirectory(android_system_ext_.c_str(), true);
+  rmdir_cache_result = rmdir(android_system_ext_.c_str());
+  ASSERT_EQ(0, rmdir_cache_result);
   TearDownAndroidDataDir(android_data_, true);
   dalvik_cache_.clear();
+  android_system_ext_.clear();
 }
 
 static std::string GetDexFileName(const std::string& jar_prefix, bool host) {
-  if (host) {
-    std::string path = GetAndroidRoot();
-    return StringPrintf("%s/framework/%s-hostdex.jar", path.c_str(), jar_prefix.c_str());
-  } else {
-    const char* apex = (jar_prefix == "conscrypt") ? "com.android.conscrypt" : "com.android.art";
-    return StringPrintf("/apex/%s/javalib/%s.jar", apex, jar_prefix.c_str());
-  }
+  std::string prefix(host ? GetAndroidRoot() : "");
+  const char* apexPath = (jar_prefix == "conscrypt") ? kAndroidConscryptApexDefaultPath
+    : (jar_prefix == "core-icu4j" ? kAndroidI18nApexDefaultPath
+    : kAndroidArtApexDefaultPath);
+  return StringPrintf("%s%s/javalib/%s.jar", prefix.c_str(), apexPath, jar_prefix.c_str());
 }
 
 std::vector<std::string> CommonArtTestImpl::GetLibCoreModuleNames() const {
   // 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.
+  // because that's what we use for compiling the boot.art image.
   // It may contain additional modules from TEST_CORE_JARS.
   return {
       // CORE_IMG_JARS modules.
       "core-oj",
       "core-libart",
-      "core-icu4j",
       "okhttp",
       "bouncycastle",
       "apache-xml",
       // Additional modules.
+      "core-icu4j",
       "conscrypt",
   };
 }
@@ -434,16 +471,11 @@
   std::vector<std::string> result = GetLibCoreDexFileNames(modules);
   if (IsHost()) {
     // Strip the ANDROID_BUILD_TOP directory including the directory separator '/'.
-    const char* host_dir = getenv("ANDROID_BUILD_TOP");
-    CHECK(host_dir != nullptr);
-    std::string prefix = host_dir;
-    CHECK(!prefix.empty());
-    if (prefix.back() != '/') {
-      prefix += '/';
-    }
+    std::string prefix = GetAndroidBuildTop();
     for (std::string& location : result) {
       CHECK_GT(location.size(), prefix.size());
-      CHECK_EQ(location.compare(0u, prefix.size(), prefix), 0);
+      CHECK_EQ(location.compare(0u, prefix.size(), prefix), 0)
+          << " prefix=" << prefix << " location=" << location;
       location.erase(0u, prefix.size());
     }
   }
@@ -473,16 +505,21 @@
 
 std::string CommonArtTestImpl::GetTestDexFileName(const char* name) const {
   CHECK(name != nullptr);
-  std::string filename;
-  if (IsHost()) {
-    filename += GetAndroidRoot() + "/framework/";
-  } else {
-    filename += ART_TARGET_NATIVETEST_DIR_STRING;
+  // The needed jar files for gtest are located next to the gtest binary itself.
+  std::string cmdline;
+  bool result = android::base::ReadFileToString("/proc/self/cmdline", &cmdline);
+  CHECK(result);
+  UniqueCPtr<char[]> executable_path(realpath(cmdline.c_str(), nullptr));
+  CHECK(executable_path != nullptr);
+  std::string executable_dir = dirname(executable_path.get());
+  for (auto ext : {".jar", ".dex"}) {
+    std::string path = executable_dir + "/art-gtest-jars-" + name + ext;
+    if (OS::FileExists(path.c_str())) {
+      return path;
+    }
   }
-  filename += "art-gtest-";
-  filename += name;
-  filename += ".jar";
-  return filename;
+  LOG(FATAL) << "Test file " << name << " not found";
+  UNREACHABLE();
 }
 
 std::vector<std::unique_ptr<const DexFile>> CommonArtTestImpl::OpenDexFiles(const char* filename) {
@@ -520,18 +557,21 @@
   return OpenDexFile(GetTestDexFileName(name).c_str());
 }
 
+std::string CommonArtTestImpl::GetImageDirectory() {
+  std::string path;
+  if (IsHost()) {
+    const char* host_dir = getenv("ANDROID_HOST_OUT");
+    CHECK(host_dir != nullptr);
+    path = std::string(host_dir) + "/apex/art_boot_images";
+  } else {
+    path = std::string(kAndroidArtApexDefaultPath);
+  }
+  return path + "/javalib";
+}
+
 std::string CommonArtTestImpl::GetCoreFileLocation(const char* suffix) {
   CHECK(suffix != nullptr);
-
-  std::string location;
-  if (IsHost()) {
-    std::string host_dir = GetAndroidRoot();
-    location = StringPrintf("%s/framework/core.%s", host_dir.c_str(), suffix);
-  } else {
-    location = StringPrintf("/apex/com.android.art/javalib/boot.%s", suffix);
-  }
-
-  return location;
+  return GetImageDirectory() + "/boot." + suffix;
 }
 
 std::string CommonArtTestImpl::CreateClassPath(
diff --git a/libartbase/base/common_art_test.h b/libartbase/base/common_art_test.h
index 8cd25c3..8dd1f88 100644
--- a/libartbase/base/common_art_test.h
+++ b/libartbase/base/common_art_test.h
@@ -45,7 +45,7 @@
 
 class ScratchDir {
  public:
-  ScratchDir();
+  explicit ScratchDir(bool keep_files = false);
 
   ~ScratchDir();
 
@@ -55,6 +55,7 @@
 
  private:
   std::string path_;
+  bool keep_files_;  // Useful for debugging.
 
   DISALLOW_COPY_AND_ASSIGN(ScratchDir);
 };
@@ -93,69 +94,32 @@
   std::unique_ptr<File> file_;
 };
 
-// Close to store a fake dex file and its underlying data.
-class FakeDex {
+// Helper class that removes an environment variable whilst in scope.
+class ScopedUnsetEnvironmentVariable {
  public:
-  static std::unique_ptr<FakeDex> Create(
-      const std::string& location,
-      uint32_t checksum,
-      uint32_t num_method_ids) {
-    FakeDex* fake_dex = new FakeDex();
-    fake_dex->dex = CreateFakeDex(location, checksum, num_method_ids, &fake_dex->storage);
-    return std::unique_ptr<FakeDex>(fake_dex);
+  explicit ScopedUnsetEnvironmentVariable(const char* variable)
+      : variable_{variable}, old_value_{GetOldValue(variable)} {
+    unsetenv(variable);
   }
 
-  static std::unique_ptr<const DexFile> CreateFakeDex(
-      const std::string& location,
-      uint32_t checksum,
-      uint32_t num_method_ids,
-      std::vector<uint8_t>* storage) {
-    storage->resize(kPageSize);
-    CompactDexFile::Header* header =
-        const_cast<CompactDexFile::Header*>(CompactDexFile::Header::At(storage->data()));
-    CompactDexFile::WriteMagic(header->magic_);
-    CompactDexFile::WriteCurrentVersion(header->magic_);
-    header->data_off_ = 0;
-    header->data_size_ = storage->size();
-    header->method_ids_size_ = num_method_ids;
-
-    const DexFileLoader dex_file_loader;
-    std::string error_msg;
-    std::unique_ptr<const DexFile> dex(dex_file_loader.Open(storage->data(),
-                                                            storage->size(),
-                                                            location,
-                                                            checksum,
-                                                            /*oat_dex_file=*/nullptr,
-                                                            /*verify=*/false,
-                                                            /*verify_checksum=*/false,
-                                                            &error_msg));
-    CHECK(dex != nullptr) << error_msg;
-    return dex;
-  }
-
-  std::unique_ptr<const DexFile>& Dex() {
-    return dex;
+  ~ScopedUnsetEnvironmentVariable() {
+    if (old_value_.has_value()) {
+      static constexpr int kReplace = 1;  // tidy-issue: replace argument has libc dependent name.
+      setenv(variable_, old_value_.value().c_str(), kReplace);
+    } else {
+      unsetenv(variable_);
+    }
   }
 
  private:
-  std::vector<uint8_t> storage;
-  std::unique_ptr<const DexFile> dex;
-};
-
-// Convenience class to store multiple fake dex files in order to make
-// allocation/de-allocation easier in tests.
-class FakeDexStorage {
- public:
-  const DexFile* AddFakeDex(
-      const std::string& location,
-      uint32_t checksum,
-      uint32_t num_method_ids) {
-    fake_dex_files.push_back(FakeDex::Create(location, checksum, num_method_ids));
-    return fake_dex_files.back()->Dex().get();
+  static std::optional<std::string> GetOldValue(const char* variable) {
+    const char* value = getenv(variable);
+    return value != nullptr ? std::optional<std::string>{value} : std::nullopt;
   }
 
- private:
-  std::vector<std::unique_ptr<FakeDex>> fake_dex_files;
+  const char* variable_;
+  std::optional<std::string> old_value_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedUnsetEnvironmentVariable);
 };
 
 class CommonArtTestImpl {
@@ -193,9 +157,6 @@
   static std::string GetClassPathOption(const char* option,
                                         const std::vector<std::string>& class_path);
 
-  // Returns bin directory which contains host's prebuild tools.
-  static std::string GetAndroidHostToolsDir();
-
   // Retuerns the filename for a test dex (i.e. XandY or ManyMethods).
   std::string GetTestDexFileName(const char* name) const;
 
@@ -248,21 +209,24 @@
                                        const PostForkFn& post_fork,
                                        std::string* output);
 
+  // Helper - find prebuilt tool (e.g. objdump).
+  static std::string GetAndroidTool(const char* name, InstructionSet isa = InstructionSet::kX86_64);
+
  protected:
   static bool IsHost() {
     return !kIsTargetBuild;
   }
 
-  // Helper - find directory with the following format:
-  // ${ANDROID_BUILD_TOP}/${subdir1}/${subdir2}-${version}/${subdir3}/bin/
-  static std::string GetAndroidToolsDir(const std::string& subdir1,
-                                        const std::string& subdir2,
-                                        const std::string& subdir3);
+  // Returns ${ANDROID_BUILD_TOP}. Ensure it has tailing /.
+  static std::string GetAndroidBuildTop();
 
-  // File location to core.art, e.g. $ANDROID_HOST_OUT/system/framework/core.art
+  // Returns ${ANDROID_HOST_OUT}.
+  static std::string GetAndroidHostOut();
+
+  // File location to boot.art, e.g. /apex/com.android.art/javalib/boot.art
   static std::string GetCoreArtLocation();
 
-  // File location to core.oat, e.g. $ANDROID_HOST_OUT/system/framework/core.oat
+  // File location to boot.oat, e.g. /apex/com.android.art/javalib/boot.oat
   static std::string GetCoreOatLocation();
 
   std::unique_ptr<const DexFile> LoadExpectSingleDexFile(const char* location);
@@ -280,8 +244,8 @@
 
   std::unique_ptr<const DexFile> OpenTestDexFile(const char* name);
 
-
   std::string android_data_;
+  std::string android_system_ext_;
   std::string dalvik_cache_;
 
   virtual void SetUp();
@@ -296,6 +260,7 @@
   std::string CreateClassPathWithChecksums(
       const std::vector<std::unique_ptr<const DexFile>>& dex_files);
 
+  static std::string GetImageDirectory();
   static std::string GetCoreFileLocation(const char* suffix);
 
   std::vector<std::unique_ptr<const DexFile>> loaded_dex_files_;
diff --git a/libartbase/base/compiler_filter.cc b/libartbase/base/compiler_filter.cc
new file mode 100644
index 0000000..a6d1c80
--- /dev/null
+++ b/libartbase/base/compiler_filter.cc
@@ -0,0 +1,227 @@
+/*
+ * 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 "compiler_filter.h"
+
+#include <ostream>
+
+#include "base/utils.h"
+
+namespace art {
+
+bool CompilerFilter::IsAotCompilationEnabled(Filter filter) {
+  switch (filter) {
+    case CompilerFilter::kAssumeVerified:
+    case CompilerFilter::kExtract:
+    case CompilerFilter::kVerify: return false;
+
+    case CompilerFilter::kSpaceProfile:
+    case CompilerFilter::kSpace:
+    case CompilerFilter::kSpeedProfile:
+    case CompilerFilter::kSpeed:
+    case CompilerFilter::kEverythingProfile:
+    case CompilerFilter::kEverything: return true;
+  }
+  UNREACHABLE();
+}
+
+bool CompilerFilter::IsJniCompilationEnabled(Filter filter) {
+  switch (filter) {
+    case CompilerFilter::kAssumeVerified:
+    case CompilerFilter::kExtract:
+    case CompilerFilter::kVerify: return false;
+
+    case CompilerFilter::kSpaceProfile:
+    case CompilerFilter::kSpace:
+    case CompilerFilter::kSpeedProfile:
+    case CompilerFilter::kSpeed:
+    case CompilerFilter::kEverythingProfile:
+    case CompilerFilter::kEverything: return true;
+  }
+  UNREACHABLE();
+}
+
+bool CompilerFilter::IsAnyCompilationEnabled(Filter filter) {
+  return IsJniCompilationEnabled(filter) || IsAotCompilationEnabled(filter);
+}
+
+bool CompilerFilter::IsVerificationEnabled(Filter filter) {
+  switch (filter) {
+    case CompilerFilter::kAssumeVerified:
+    case CompilerFilter::kExtract: return false;
+
+    case CompilerFilter::kVerify:
+    case CompilerFilter::kSpaceProfile:
+    case CompilerFilter::kSpace:
+    case CompilerFilter::kSpeedProfile:
+    case CompilerFilter::kSpeed:
+    case CompilerFilter::kEverythingProfile:
+    case CompilerFilter::kEverything: return true;
+  }
+  UNREACHABLE();
+}
+
+bool CompilerFilter::DependsOnImageChecksum(Filter filter) {
+  // We run dex2dex with verification, so the oat file will depend on the
+  // image checksum if verification is enabled.
+  return IsVerificationEnabled(filter);
+}
+
+bool CompilerFilter::DependsOnProfile(Filter filter) {
+  switch (filter) {
+    case CompilerFilter::kAssumeVerified:
+    case CompilerFilter::kExtract:
+    case CompilerFilter::kVerify:
+    case CompilerFilter::kSpace:
+    case CompilerFilter::kSpeed:
+    case CompilerFilter::kEverything: return false;
+
+    case CompilerFilter::kSpaceProfile:
+    case CompilerFilter::kSpeedProfile:
+    case CompilerFilter::kEverythingProfile: return true;
+  }
+  UNREACHABLE();
+}
+
+CompilerFilter::Filter CompilerFilter::GetNonProfileDependentFilterFrom(Filter filter) {
+  switch (filter) {
+    case CompilerFilter::kAssumeVerified:
+    case CompilerFilter::kExtract:
+    case CompilerFilter::kVerify:
+    case CompilerFilter::kSpace:
+    case CompilerFilter::kSpeed:
+    case CompilerFilter::kEverything:
+      return filter;
+
+    case CompilerFilter::kSpaceProfile:
+      return CompilerFilter::kSpace;
+
+    case CompilerFilter::kSpeedProfile:
+      return CompilerFilter::kSpeed;
+
+    case CompilerFilter::kEverythingProfile:
+      return CompilerFilter::kEverything;
+  }
+  UNREACHABLE();
+}
+
+CompilerFilter::Filter CompilerFilter::GetSafeModeFilterFrom(Filter filter) {
+  // For safe mode, we should not return a filter that generates AOT compiled
+  // code.
+  switch (filter) {
+    case CompilerFilter::kAssumeVerified:
+    case CompilerFilter::kExtract:
+    case CompilerFilter::kVerify:
+      return filter;
+
+    case CompilerFilter::kSpace:
+    case CompilerFilter::kSpeed:
+    case CompilerFilter::kEverything:
+    case CompilerFilter::kSpaceProfile:
+    case CompilerFilter::kSpeedProfile:
+    case CompilerFilter::kEverythingProfile:
+      return CompilerFilter::kVerify;
+  }
+  UNREACHABLE();
+}
+
+bool CompilerFilter::IsAsGoodAs(Filter current, Filter target) {
+  return current >= target;
+}
+
+bool CompilerFilter::IsBetter(Filter current, Filter target) {
+  return current > target;
+}
+
+std::string CompilerFilter::NameOfFilter(Filter filter) {
+  switch (filter) {
+    case CompilerFilter::kAssumeVerified: return "assume-verified";
+    case CompilerFilter::kExtract: return "extract";
+    case CompilerFilter::kVerify: return "verify";
+    case CompilerFilter::kSpaceProfile: return "space-profile";
+    case CompilerFilter::kSpace: return "space";
+    case CompilerFilter::kSpeedProfile: return "speed-profile";
+    case CompilerFilter::kSpeed: return "speed";
+    case CompilerFilter::kEverythingProfile: return "everything-profile";
+    case CompilerFilter::kEverything: return "everything";
+  }
+  UNREACHABLE();
+}
+
+bool CompilerFilter::ParseCompilerFilter(const char* option, Filter* filter) {
+  CHECK(filter != nullptr);
+
+  if (strcmp(option, "verify-none") == 0) {
+    LOG(WARNING) << "'verify-none' is an obsolete compiler filter name that will be "
+                 << "removed in future releases, please use 'assume-verified' instead.";
+    *filter = kAssumeVerified;
+  } else if (strcmp(option, "interpret-only") == 0) {
+    LOG(WARNING) << "'interpret-only' is an obsolete compiler filter name that will be "
+                 << "removed in future releases, please use 'quicken' instead.";
+    *filter = kVerify;
+  } else if (strcmp(option, "verify-profile") == 0) {
+    LOG(WARNING) << "'verify-profile' is an obsolete compiler filter name that will be "
+                 << "removed in future releases, please use 'verify' instead.";
+    *filter = kVerify;
+  } else if (strcmp(option, "verify-at-runtime") == 0) {
+    LOG(WARNING) << "'verify-at-runtime' is an obsolete compiler filter name that will be "
+                 << "removed in future releases, please use 'extract' instead.";
+    *filter = kExtract;
+  } else if (strcmp(option, "balanced") == 0) {
+    LOG(WARNING) << "'balanced' is an obsolete compiler filter name that will be "
+                 << "removed in future releases, please use 'speed' instead.";
+    *filter = kSpeed;
+  } else if (strcmp(option, "time") == 0) {
+    LOG(WARNING) << "'time' is an obsolete compiler filter name that will be "
+                 << "removed in future releases, please use 'space' instead.";
+    *filter = kSpace;
+  } else if (strcmp(option, "assume-verified") == 0) {
+    *filter = kAssumeVerified;
+  } else if (strcmp(option, "extract") == 0) {
+    *filter = kExtract;
+  } else if (strcmp(option, "verify") == 0) {
+    *filter = kVerify;
+  } else if (strcmp(option, "quicken") == 0) {
+    // b/170086509 'quicken' becomes an alias to 'verify.
+    *filter = kVerify;
+  } else if (strcmp(option, "space") == 0) {
+    *filter = kSpace;
+  } else if (strcmp(option, "space-profile") == 0) {
+    *filter = kSpaceProfile;
+  } else if (strcmp(option, "speed") == 0) {
+    *filter = kSpeed;
+  } else if (strcmp(option, "speed-profile") == 0) {
+    *filter = kSpeedProfile;
+  } else if (strcmp(option, "everything") == 0) {
+    *filter = kEverything;
+  } else if (strcmp(option, "everything-profile") == 0) {
+    *filter = kEverythingProfile;
+  } else {
+    return false;
+  }
+  return true;
+}
+
+const char* CompilerFilter::DescribeOptions() {
+  return "assume-verified|extract|verify|quicken|space{,-profile}|speed{,-profile}|"
+          "everything{,-profile}";
+}
+
+std::ostream& operator<<(std::ostream& os, const CompilerFilter::Filter& rhs) {
+  return os << CompilerFilter::NameOfFilter(rhs);
+}
+
+}  // namespace art
diff --git a/libartbase/base/compiler_filter.h b/libartbase/base/compiler_filter.h
new file mode 100644
index 0000000..4ca3c76
--- /dev/null
+++ b/libartbase/base/compiler_filter.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_LIBARTBASE_BASE_COMPILER_FILTER_H_
+#define ART_LIBARTBASE_BASE_COMPILER_FILTER_H_
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+
+namespace art {
+
+class CompilerFilter final {
+ public:
+  // Note: Order here matters. Later filter choices are considered "as good
+  // as" earlier filter choices.
+  enum Filter {
+    kAssumeVerified,      // Skip verification but mark all classes as verified anyway.
+    kExtract,             // Delay verication to runtime, do not compile anything.
+    kVerify,              // Only verify classes.
+    kSpaceProfile,        // Maximize space savings based on profile.
+    kSpace,               // Maximize space savings.
+    kSpeedProfile,        // Maximize runtime performance based on profile.
+    kSpeed,               // Maximize runtime performance.
+    kEverythingProfile,   // Compile everything capable of being compiled based on profile.
+    kEverything,          // Compile everything capable of being compiled.
+  };
+
+  static const Filter kDefaultCompilerFilter = kSpeed;
+
+  // Returns true if an oat file with this compiler filter contains
+  // compiled executable code for bytecode.
+  static bool IsAotCompilationEnabled(Filter filter);
+
+  // Returns true if an oat file with this compiler filter contains
+  // compiled executable code for bytecode, JNI methods, or quickened dex
+  // bytecode.
+  static bool IsAnyCompilationEnabled(Filter filter);
+
+  // Returns true if an oat file with this compiler filter contains
+  // compiled executable code for JNI methods.
+  static bool IsJniCompilationEnabled(Filter filter);
+
+  // Returns true if this compiler filter requires running verification.
+  static bool IsVerificationEnabled(Filter filter);
+
+  // Returns true if an oat file with this compiler filter depends on the
+  // boot image checksum.
+  static bool DependsOnImageChecksum(Filter filter);
+
+  // Returns true if an oat file with this compiler filter depends on a
+  // profile.
+  static bool DependsOnProfile(Filter filter);
+
+  // Returns a non-profile-guided version of the given filter.
+  static Filter GetNonProfileDependentFilterFrom(Filter filter);
+
+  // Returns a filter suitable for safe mode.
+  static Filter GetSafeModeFilterFrom(Filter filter);
+
+  // Returns true if the 'current' compiler filter is considered at least as
+  // good as the 'target' compilation type.
+  // For example: kSpeed is as good as kInterpretOnly, but kInterpretOnly is
+  // not as good as kSpeed.
+  static bool IsAsGoodAs(Filter current, Filter target);
+
+  // Returns true if 'current' compiler filter is better than 'target' compiler
+  // filter. Compared to IsAsGoodAs, this returns false if the compiler filters are
+  // equal.
+  static bool IsBetter(Filter current, Filter target);
+
+  // Return the flag name of the given filter.
+  // For example: given kVerifyAtRuntime, returns "verify-at-runtime".
+  // The name returned corresponds to the name accepted by
+  // ParseCompilerFilter.
+  static std::string NameOfFilter(Filter filter);
+
+  // Parse the compiler filter from the given name.
+  // Returns true and sets filter to the parsed value if name refers to a
+  // valid filter. Returns false if no filter matches that name.
+  // 'filter' must be non-null.
+  static bool ParseCompilerFilter(const char* name, /*out*/Filter* filter);
+
+  static const char* DescribeOptions();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(CompilerFilter);
+};
+
+std::ostream& operator<<(std::ostream& os, const CompilerFilter::Filter& rhs);
+
+}  // namespace art
+
+#endif  // ART_LIBARTBASE_BASE_COMPILER_FILTER_H_
diff --git a/libartbase/base/compiler_filter_test.cc b/libartbase/base/compiler_filter_test.cc
new file mode 100644
index 0000000..df7c8e7
--- /dev/null
+++ b/libartbase/base/compiler_filter_test.cc
@@ -0,0 +1,68 @@
+/*
+ * 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 "compiler_filter.h"
+
+#include <gtest/gtest.h>
+
+namespace art {
+
+static void TestCompilerFilterName(CompilerFilter::Filter filter, const std::string& name) {
+  CompilerFilter::Filter parsed;
+  EXPECT_TRUE(CompilerFilter::ParseCompilerFilter(name.c_str(), &parsed));
+  EXPECT_EQ(filter, parsed);
+
+  EXPECT_EQ(name, CompilerFilter::NameOfFilter(filter));
+}
+
+static void TestSafeModeFilter(CompilerFilter::Filter expected, const std::string& name) {
+  CompilerFilter::Filter parsed;
+  EXPECT_TRUE(CompilerFilter::ParseCompilerFilter(name.c_str(), &parsed));
+  EXPECT_EQ(expected, CompilerFilter::GetSafeModeFilterFrom(parsed));
+}
+
+
+// Verify the dexopt status values from dalvik.system.DexFile
+// match the OatFileAssistant::DexOptStatus values.
+TEST(CompilerFilterTest, ParseCompilerFilter) {
+  CompilerFilter::Filter filter;
+
+  TestCompilerFilterName(CompilerFilter::kAssumeVerified, "assume-verified");
+  TestCompilerFilterName(CompilerFilter::kExtract, "extract");
+  TestCompilerFilterName(CompilerFilter::kVerify, "verify");
+  TestCompilerFilterName(CompilerFilter::kSpaceProfile, "space-profile");
+  TestCompilerFilterName(CompilerFilter::kSpace, "space");
+  TestCompilerFilterName(CompilerFilter::kSpeedProfile, "speed-profile");
+  TestCompilerFilterName(CompilerFilter::kSpeed, "speed");
+  TestCompilerFilterName(CompilerFilter::kEverythingProfile, "everything-profile");
+  TestCompilerFilterName(CompilerFilter::kEverything, "everything");
+
+  EXPECT_FALSE(CompilerFilter::ParseCompilerFilter("super-awesome-filter", &filter));
+}
+
+TEST(CompilerFilterTest, SafeModeFilter) {
+  TestSafeModeFilter(CompilerFilter::kAssumeVerified, "assume-verified");
+  TestSafeModeFilter(CompilerFilter::kExtract, "extract");
+  TestSafeModeFilter(CompilerFilter::kVerify, "verify");
+  TestSafeModeFilter(CompilerFilter::kVerify, "space-profile");
+  TestSafeModeFilter(CompilerFilter::kVerify, "space");
+  TestSafeModeFilter(CompilerFilter::kVerify, "speed-profile");
+  TestSafeModeFilter(CompilerFilter::kVerify, "speed");
+  TestSafeModeFilter(CompilerFilter::kVerify, "everything-profile");
+  TestSafeModeFilter(CompilerFilter::kVerify, "everything");
+}
+
+}  // namespace art
diff --git a/libartbase/base/fast_exit.h b/libartbase/base/fast_exit.h
new file mode 100644
index 0000000..35dd85e
--- /dev/null
+++ b/libartbase/base/fast_exit.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 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_LIBARTBASE_BASE_FAST_EXIT_H_
+#define ART_LIBARTBASE_BASE_FAST_EXIT_H_
+
+// Header-only definition of `art::FastExit`.
+//
+// Ideally, this routine should be declared in `base/os.h` and defined in
+// `base/os_linux.cc`, but as `libartbase` is not linked (directly) with
+// `dalvikvm`, we would not be able to easily use `art::FastExit` in
+// `dex2oat`. Use a header-only approach and define `art::FastExit` in its own
+// file for clarity.
+
+#include <base/macros.h>
+
+namespace art {
+
+#ifdef __ANDROID_CLANG_COVERAGE__
+static constexpr bool kAndroidClangCoverage = true;
+#else
+static constexpr bool kAndroidClangCoverage = false;
+#endif
+
+// Terminate program without completely cleaning the resources (e.g. without
+// calling destructors), unless ART is built with Clang (native) code coverage
+// instrumentation; in that case, exit normally to allow LLVM's code coverage
+// profile dumping routine (`__llvm_profile_write_file`), registered via
+// `atexit` in Android when Clang instrumentation is enabled, to be called
+// before terminating the program.
+NO_RETURN inline void FastExit(int exit_code) {
+  if (kAndroidClangCoverage) {
+    exit(exit_code);
+  } else {
+    _exit(exit_code);
+  }
+}
+
+}  // namespace art
+
+#endif  // ART_LIBARTBASE_BASE_FAST_EXIT_H_
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc
index a899b86..cb0023e 100644
--- a/libartbase/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -38,9 +38,10 @@
 #endif
 #endif
 
-
 #include <memory>
+#include <sstream>
 
+#include "android-base/file.h"
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
 
@@ -65,15 +66,17 @@
 using android::base::StringPrintf;
 
 static constexpr const char* kClassesDex = "classes.dex";
-static constexpr const char* kApexDefaultPath = "/apex/";
 static constexpr const char* kAndroidRootEnvVar = "ANDROID_ROOT";
 static constexpr const char* kAndroidRootDefaultPath = "/system";
+static constexpr const char* kAndroidSystemExtRootEnvVar = "ANDROID_SYSTEM_EXT";
+static constexpr const char* kAndroidSystemExtRootDefaultPath = "/system_ext";
 static constexpr const char* kAndroidDataEnvVar = "ANDROID_DATA";
 static constexpr const char* kAndroidDataDefaultPath = "/data";
 static constexpr const char* kAndroidArtRootEnvVar = "ANDROID_ART_ROOT";
-static constexpr const char* kAndroidArtApexDefaultPath = "/apex/com.android.art";
 static constexpr const char* kAndroidConscryptRootEnvVar = "ANDROID_CONSCRYPT_ROOT";
-static constexpr const char* kAndroidConscryptApexDefaultPath = "/apex/com.android.conscrypt";
+static constexpr const char* kAndroidI18nRootEnvVar = "ANDROID_I18N_ROOT";
+static constexpr const char* kApexDefaultPath = "/apex/";
+static constexpr const char* kArtApexDataEnvVar = "ART_APEX_DATA";
 
 // Get the "root" directory containing the "lib" directory where this instance
 // of the libartbase library (which contains `GetRootContainingLibartbase`) is
@@ -173,9 +176,11 @@
   return android_dir;
 }
 
-static const char* GetAndroidDir(const char* env_var, const char* default_dir) {
+static const char* GetAndroidDir(const char* env_var,
+                                 const char* default_dir,
+                                 bool must_exist = true) {
   std::string error_msg;
-  const char* dir = GetAndroidDirSafe(env_var, default_dir, /* must_exist= */ true, &error_msg);
+  const char* dir = GetAndroidDirSafe(env_var, default_dir, must_exist, &error_msg);
   if (dir != nullptr) {
     return dir;
   } else {
@@ -274,14 +279,75 @@
   return GetAndroidDir(kAndroidDataEnvVar, kAndroidDataDefaultPath);
 }
 
-std::string GetDefaultBootImageLocation(const std::string& android_root) {
+std::string GetArtApexData() {
+  return GetAndroidDir(kArtApexDataEnvVar, kArtApexDataDefaultPath, /*must_exist=*/false);
+}
+
+static std::string GetFirstBootClasspathExtensionJar(const std::string& android_root) {
+  DCHECK(kIsTargetBuild);
+
+  // This method finds the first non-APEX DEX file in the boot class path as defined by the
+  // DEX2OATBOOTCLASSPATH environment variable. This corresponds to the first boot classpath
+  // extension (see IMAGE SECTION documentation in image.h). When on-device signing is used the
+  // boot class extensions are compiled together as a single image with a name derived from the
+  // first extension. This first boot classpath extension is usually
+  // '/system/framework/framework.jar'.
+  //
+  // DEX2OATBOOTCLASSPATH is generated at build time by in the init.environ.rc.in:
+  //   ${ANDROID_BUILD_TOP}/system/core/rootdir/Android.mk
+  // and initialized on Android by init in init.environ.rc:
+  //   ${ANDROID_BUILD_TOP}/system/core/rootdir/init.environ.rc.in.
+  // It is used by installd too.
+  const char* bcp = getenv("DEX2OATBOOTCLASSPATH");
+  const std::string kDefaultBcpExtensionJar = android_root + "/framework/framework.jar";
+  if (bcp != nullptr) {
+    for (std::string_view component : SplitString(bcp, ':')) {
+      if (component.empty()) {
+        continue;
+      }
+      if (!LocationIsOnApex(component)) {
+        return std::string{component};
+      }
+    }
+  }
+  return kDefaultBcpExtensionJar;
+}
+
+std::string GetDefaultBootImageLocation(const std::string& android_root,
+                                        bool deny_art_apex_data_files) {
+  constexpr static const char* kJavalibBootArt = "javalib/boot.art";
+  constexpr static const char* kEtcBootImageProf = "etc/boot-image.prof";
+
   // Boot image consists of two parts:
-  //  - the primary boot image in the ART apex (contains the Core Libraries)
-  //  - the boot image extension on the system partition (contains framework libraries)
-  return StringPrintf("%s/javalib/boot.art:%s/framework/boot-framework.art!%s/etc/boot-image.prof",
+  //  - the primary boot image in the ART APEX (contains the Core Libraries)
+  //  - the boot image extensions (contains framework libraries) on the system partition, or
+  //    in the ART APEX data directory, if an update for the ART module has been been installed.
+  if (kIsTargetBuild && !deny_art_apex_data_files) {
+    // If the ART APEX has been updated, the compiled boot image extension will be in the ART APEX
+    // data directory (assuming there is space and we trust the artifacts there). Otherwise, for a factory installed ART APEX it is
+    // under $ANDROID_ROOT/framework/.
+    const std::string first_extension_jar{GetFirstBootClasspathExtensionJar(android_root)};
+    const std::string boot_extension_image = GetApexDataBootImage(first_extension_jar);
+    const std::string boot_extension_filename =
+        GetSystemImageFilename(boot_extension_image.c_str(), kRuntimeISA);
+    if (OS::FileExists(boot_extension_filename.c_str(), /*check_file_type=*/true)) {
+      return StringPrintf("%s/%s:%s!%s/%s",
+                          kAndroidArtApexDefaultPath,
+                          kJavalibBootArt,
+                          boot_extension_image.c_str(),
+                          android_root.c_str(),
+                          kEtcBootImageProf);
+    } else if (errno == EACCES) {
+      // Additional warning for potential SELinux misconfiguration.
+      PLOG(ERROR) << "Default boot image check failed, could not stat: " << boot_extension_image;
+    }
+  }
+  return StringPrintf("%s/%s:%s/framework/boot-framework.art!%s/%s",
                       kAndroidArtApexDefaultPath,
+                      kJavalibBootArt,
                       android_root.c_str(),
-                      android_root.c_str());
+                      android_root.c_str(),
+                      kEtcBootImageProf);
 }
 
 std::string GetDefaultBootImageLocation(std::string* error_msg) {
@@ -289,7 +355,18 @@
   if (android_root.empty()) {
     return "";
   }
-  return GetDefaultBootImageLocation(android_root);
+  return GetDefaultBootImageLocation(android_root, /*deny_art_apex_data_files=*/false);
+}
+
+static std::string GetDalvikCacheDirectory(std::string_view root_directory,
+                                           std::string_view sub_directory = {}) {
+  static constexpr std::string_view kDalvikCache = "dalvik-cache";
+  std::stringstream oss;
+  oss << root_directory << '/' << kDalvikCache;
+  if (!sub_directory.empty()) {
+    oss << '/' << sub_directory;
+  }
+  return oss.str();
 }
 
 void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache,
@@ -314,7 +391,7 @@
   } else {
     *have_android_data = true;
   }
-  const std::string dalvik_cache_root = android_data + "/dalvik-cache";
+  const std::string dalvik_cache_root = GetDalvikCacheDirectory(android_data);
   *dalvik_cache = dalvik_cache_root + '/' + subdir;
   *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str());
   *is_global_cache = (android_data == kAndroidDataDefaultPath);
@@ -326,18 +403,6 @@
 #endif
 }
 
-std::string GetDalvikCache(const char* subdir) {
-  CHECK(subdir != nullptr);
-  std::string android_data = GetAndroidData();
-  const std::string dalvik_cache_root = android_data + "/dalvik-cache";
-  const std::string dalvik_cache = dalvik_cache_root + '/' + subdir;
-  if (!OS::DirectoryExists(dalvik_cache.c_str())) {
-    // TODO: Check callers. Traditional behavior is to not abort.
-    return "";
-  }
-  return dalvik_cache;
-}
-
 bool GetDalvikCacheFilename(const char* location, const char* cache_location,
                             std::string* filename, std::string* error_msg) {
   if (location[0] != '/') {
@@ -356,6 +421,68 @@
   return true;
 }
 
+static std::string GetApexDataDalvikCacheDirectory(InstructionSet isa) {
+  if (isa != InstructionSet::kNone) {
+    return GetDalvikCacheDirectory(GetArtApexData(), GetInstructionSetString(isa));
+  }
+  return GetDalvikCacheDirectory(GetArtApexData());
+}
+
+static std::string GetApexDataDalvikCacheFilename(std::string_view dex_location,
+                                                  InstructionSet isa,
+                                                  bool encode_location,
+                                                  std::string_view file_extension) {
+  if (LocationIsOnApex(dex_location)) {
+    return {};
+  }
+  std::string apex_data_dalvik_cache = GetApexDataDalvikCacheDirectory(isa);
+  if (encode_location) {
+    // Arguments: "/system/framework/xyz.jar", "arm", true, "odex"
+    // Result:
+    // "/data/misc/apexdata/com.android.art/dalvik-cache/arm/system@framework@xyz.jar@classes.odex"
+    std::string result, unused_error_msg;
+    GetDalvikCacheFilename(std::string{dex_location}.c_str(),
+                           apex_data_dalvik_cache.c_str(),
+                           &result,
+                           &unused_error_msg);
+    return ReplaceFileExtension(result, file_extension);
+  } else {
+    // Arguments: "/system/framework/xyz.jar", "x86_64", false, "art"
+    // Results: "/data/misc/apexdata/com.android.art/dalvik-cache/x86_64/boot-xyz.jar@classes.art"
+    std::string basename = android::base::Basename(std::string{dex_location});
+    return apex_data_dalvik_cache + "/boot-" + ReplaceFileExtension(basename, file_extension);
+  }
+}
+
+std::string GetApexDataOatFilename(std::string_view location, InstructionSet isa) {
+  return GetApexDataDalvikCacheFilename(location, isa, /*encode_location=*/false, "oat");
+}
+
+std::string GetApexDataOdexFilename(std::string_view location, InstructionSet isa) {
+  return GetApexDataDalvikCacheFilename(location, isa, /*encode_location=*/true, "odex");
+}
+
+std::string GetApexDataBootImage(std::string_view dex_location) {
+  return GetApexDataDalvikCacheFilename(dex_location,
+                                        InstructionSet::kNone,
+                                        /*encode_location=*/false,
+                                        kArtImageExtension);
+}
+
+std::string GetApexDataImage(std::string_view dex_location) {
+  return GetApexDataDalvikCacheFilename(dex_location,
+                                        InstructionSet::kNone,
+                                        /*encode_location=*/true,
+                                        kArtImageExtension);
+}
+
+std::string GetApexDataDalvikCacheFilename(std::string_view dex_location,
+                                           InstructionSet isa,
+                                           std::string_view file_extension) {
+  return GetApexDataDalvikCacheFilename(
+      dex_location, isa, /*encode_location=*/true, file_extension);
+}
+
 std::string GetVdexFilename(const std::string& oat_location) {
   return ReplaceFileExtension(oat_location, "vdex");
 }
@@ -377,16 +504,25 @@
   return filename;
 }
 
-std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) {
+std::string ReplaceFileExtension(std::string_view filename, std::string_view new_extension) {
   const size_t last_ext = filename.find_last_of("./");
+  std::string result;
   if (last_ext == std::string::npos || filename[last_ext] != '.') {
-    return filename + "." + new_extension;
+    result.reserve(filename.size() + 1 + new_extension.size());
+    result.append(filename).append(".").append(new_extension);
   } else {
-    return filename.substr(0, last_ext + 1) + new_extension;
+    result.reserve(last_ext + 1 + new_extension.size());
+    result.append(filename.substr(0, last_ext + 1)).append(new_extension);
   }
+  return result;
 }
 
-bool LocationIsOnArtModule(const char* full_path) {
+bool LocationIsOnArtApexData(std::string_view location) {
+  const std::string art_apex_data = GetArtApexData();
+  return android::base::StartsWith(location, art_apex_data);
+}
+
+bool LocationIsOnArtModule(std::string_view full_path) {
   std::string unused_error_msg;
   std::string module_path = GetArtRootSafe(/* must_exist= */ kIsTargetBuild, &unused_error_msg);
   if (module_path.empty()) {
@@ -409,26 +545,26 @@
 // Returns true if `full_path` is located in folder either provided with `env_var`
 // or in `default_path` otherwise. The caller may optionally provide a `subdir`
 // which will be appended to the tested prefix.
-// All of `default_path`, `subdir` and the value of environment variable `env_var`
+// `default_path` and the value of environment variable `env_var`
 // are expected to begin with a slash and not end with one. If this ever changes,
 // the path-building logic should be updated.
-static bool IsLocationOnModule(const char* full_path,
-                               const char* env_var,
-                               const char* default_path,
-                               const char* subdir = nullptr) {
+static bool IsLocationOn(std::string_view full_path,
+                         const char* env_var,
+                         const char* default_path,
+                         const char* subdir = nullptr) {
   std::string unused_error_msg;
-  const char* module_path = GetAndroidDirSafe(env_var,
-                                              default_path,
-                                              /* must_exist= */ kIsTargetBuild,
-                                              &unused_error_msg);
-  if (module_path == nullptr) {
+  const char* path = GetAndroidDirSafe(env_var,
+                                       default_path,
+                                       /* must_exist= */ kIsTargetBuild,
+                                       &unused_error_msg);
+  if (path == nullptr) {
     return false;
   }
 
   // Build the path which we will check is a prefix of `full_path`. The prefix must
   // end with a slash, so that "/foo/bar" does not match "/foo/barz".
-  DCHECK(StartsWithSlash(module_path)) << module_path;
-  std::string path_prefix(module_path);
+  DCHECK(StartsWithSlash(path)) << path;
+  std::string path_prefix(path);
   if (!EndsWithSlash(path_prefix.c_str())) {
     path_prefix.append("/");
   }
@@ -443,34 +579,59 @@
   return android::base::StartsWith(full_path, path_prefix);
 }
 
-bool LocationIsOnSystemFramework(const char* full_path) {
-  return IsLocationOnModule(full_path,
-                            kAndroidRootEnvVar,
-                            kAndroidRootDefaultPath,
-                            /* subdir= */ "framework/");
+bool LocationIsOnSystemFramework(std::string_view full_path) {
+  return IsLocationOn(full_path,
+                      kAndroidRootEnvVar,
+                      kAndroidRootDefaultPath,
+                      /* subdir= */ "framework/");
 }
 
-bool LocationIsOnConscryptModule(const char* full_path) {
-  return IsLocationOnModule(
+bool LocationIsOnSystemExtFramework(std::string_view full_path) {
+  return IsLocationOn(full_path,
+                      kAndroidSystemExtRootEnvVar,
+                      kAndroidSystemExtRootDefaultPath,
+                      /* subdir= */ "framework/") ||
+      // When the 'system_ext' partition is not present, builds will create
+      // '/system/system_ext' instead.
+      IsLocationOn(full_path,
+                   kAndroidRootEnvVar,
+                   kAndroidRootDefaultPath,
+                   /* subdir= */ "system_ext/framework/");
+}
+
+bool LocationIsOnConscryptModule(std::string_view full_path) {
+  return IsLocationOn(
       full_path, kAndroidConscryptRootEnvVar, kAndroidConscryptApexDefaultPath);
 }
 
-bool LocationIsOnApex(const char* full_path) {
+bool LocationIsOnI18nModule(std::string_view full_path) {
+  return IsLocationOn(
+      full_path, kAndroidI18nRootEnvVar, kAndroidI18nApexDefaultPath);
+}
+
+bool LocationIsOnApex(std::string_view full_path) {
   return android::base::StartsWith(full_path, kApexDefaultPath);
 }
 
-bool LocationIsOnSystem(const char* path) {
+bool LocationIsOnSystem(const std::string& location) {
 #ifdef _WIN32
-  UNUSED(path);
+  UNUSED(location);
   LOG(FATAL) << "LocationIsOnSystem is unsupported on Windows.";
   return false;
 #else
-  UniqueCPtr<const char[]> full_path(realpath(path, nullptr));
+  UniqueCPtr<const char[]> full_path(realpath(location.c_str(), nullptr));
   return full_path != nullptr &&
       android::base::StartsWith(full_path.get(), GetAndroidRoot().c_str());
 #endif
 }
 
+bool LocationIsTrusted(const std::string& location, bool trust_art_apex_data_files) {
+  if (LocationIsOnSystem(location)) {
+    return true;
+  }
+  return LocationIsOnArtApexData(location) & trust_art_apex_data_files;
+}
+
 bool ArtModuleRootDistinctFromAndroidRoot() {
   std::string error_msg;
   const char* android_root = GetAndroidDirSafe(kAndroidRootEnvVar,
diff --git a/libartbase/base/file_utils.h b/libartbase/base/file_utils.h
index 6a57fbd..c1b0095 100644
--- a/libartbase/base/file_utils.h
+++ b/libartbase/base/file_utils.h
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 
 #include <string>
+#include <string_view>
 
 #include <android-base/logging.h>
 
@@ -27,6 +28,13 @@
 
 namespace art {
 
+static constexpr const char kAndroidArtApexDefaultPath[] = "/apex/com.android.art";
+static constexpr const char kArtApexDataDefaultPath[] = "/data/misc/apexdata/com.android.art";
+static constexpr const char kAndroidConscryptApexDefaultPath[] = "/apex/com.android.conscrypt";
+static constexpr const char kAndroidI18nApexDefaultPath[] = "/apex/com.android.i18n";
+
+static constexpr const char kArtImageExtension[] = "art";
+
 // These methods return the Android Root, which is the historical location of
 // the Android "system" directory, containing the built Android artifacts. On
 // target, this is normally "/system". On host this is usually a directory under
@@ -58,30 +66,54 @@
 // Find $ANDROID_DATA, /data, or return an empty string.
 std::string GetAndroidDataSafe(/*out*/ std::string* error_msg);
 
+// Find $ART_APEX_DATA, /data/misc/apexdata/com.android.art, or abort.
+std::string GetArtApexData();
+
 // Returns the default boot image location (ANDROID_ROOT/framework/boot.art).
 // Returns an empty string if ANDROID_ROOT is not set.
 std::string GetDefaultBootImageLocation(std::string* error_msg);
 
-// Returns the default boot image location, based on the passed android root.
-std::string GetDefaultBootImageLocation(const std::string& android_root);
-
-// Returns the dalvik-cache location, with subdir appended. Returns the empty string if the cache
-// could not be found.
-std::string GetDalvikCache(const char* subdir);
+// Returns the default boot image location, based on the passed `android_root`.
+std::string GetDefaultBootImageLocation(const std::string& android_root,
+                                        bool deny_art_apex_data_files);
 
 // Return true if we found the dalvik cache and stored it in the dalvik_cache argument.
-// have_android_data will be set to true if we have an ANDROID_DATA that exists,
-// dalvik_cache_exists will be true if there is a dalvik-cache directory that is present.
-// The flag is_global_cache tells whether this cache is /data/dalvik-cache.
+// `have_android_data` will be set to true if we have an ANDROID_DATA that exists,
+// `dalvik_cache_exists` will be true if there is a dalvik-cache directory that is present.
+// The flag `is_global_cache` tells whether this cache is /data/dalvik-cache.
 void GetDalvikCache(const char* subdir, bool create_if_absent, std::string* dalvik_cache,
                     bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache);
 
 // Returns the absolute dalvik-cache path for a DexFile or OatFile. The path returned will be
-// rooted at cache_location.
-bool GetDalvikCacheFilename(const char* file_location, const char* cache_location,
+// rooted at `cache_location`.
+bool GetDalvikCacheFilename(const char* location, const char* cache_location,
                             std::string* filename, std::string* error_msg);
 
-// Returns the system location for an image
+// Gets the oat location in the ART APEX data directory for a DEX file installed anywhere other
+// than in an APEX. Returns the oat filename if `location` is valid, empty string otherwise.
+std::string GetApexDataOatFilename(std::string_view location, InstructionSet isa);
+
+// Gets the odex location in the ART APEX data directory for a DEX file installed anywhere other
+// than in an APEX. Returns the odex filename if `location` is valid, empty string otherwise.
+std::string GetApexDataOdexFilename(std::string_view location, InstructionSet isa);
+
+// Gets the boot image in the ART APEX data directory for a DEX file installed anywhere other
+// than in an APEX. Returns the image location if `dex_location` is valid, empty string otherwise.
+std::string GetApexDataBootImage(std::string_view dex_location);
+
+// Gets the image in the ART APEX data directory for a DEX file installed installed anywhere other
+// than in an APEX. Returns the image location if `dex_location` is valid, empty string otherwise.
+std::string GetApexDataImage(std::string_view dex_location);
+
+// Gets the name of a file in the ART APEX directory dalvik-cache. This method assumes the
+// `dex_location` is for an application and that the `dex_location` is not within an APEX.
+// Returns the location of the file in the dalvik-cache
+std::string GetApexDataDalvikCacheFilename(std::string_view dex_location,
+                                           InstructionSet isa,
+                                           std::string_view file_extension);
+
+// Returns the system location for an image. This method inserts the `isa` between the
+// dirname and basename of `location`.
 std::string GetSystemImageFilename(const char* location, InstructionSet isa);
 
 // Returns the vdex filename for the given oat filename.
@@ -92,22 +124,36 @@
 // a period, and `new_extension`.
 // Example: ReplaceFileExtension("foo.bar", "abc") == "foo.abc"
 //          ReplaceFileExtension("foo", "abc") == "foo.abc"
-std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension);
+std::string ReplaceFileExtension(std::string_view filename, std::string_view new_extension);
 
 // Return whether the location is on /apex/com.android.art
-bool LocationIsOnArtModule(const char* location);
+bool LocationIsOnArtModule(std::string_view location);
+
+// Return whether the location is on /data/misc/apexdata/com.android.art/.
+bool LocationIsOnArtApexData(std::string_view location);
 
 // Return whether the location is on /apex/com.android.conscrypt
-bool LocationIsOnConscryptModule(const char* location);
+bool LocationIsOnConscryptModule(std::string_view location);
+
+// Return whether the location is on /apex/com.android.i18n
+bool LocationIsOnI18nModule(std::string_view location);
 
 // Return whether the location is on system (i.e. android root).
-bool LocationIsOnSystem(const char* location);
+bool LocationIsOnSystem(const std::string& location);
 
-// Return whether the location is on system/framework (i.e. android_root/framework).
-bool LocationIsOnSystemFramework(const char* location);
+// Return whether the location is on system/framework (i.e. $ANDROID_ROOT/framework).
+bool LocationIsOnSystemFramework(std::string_view location);
+
+// Return whether the location is on system_ext/framework
+bool LocationIsOnSystemExtFramework(std::string_view location);
 
 // Return whether the location is on /apex/.
-bool LocationIsOnApex(const char* location);
+bool LocationIsOnApex(std::string_view location);
+
+// Returns whether the location is trusted for loading oat files. Trusted locations are protected
+// by dm-verity or fs-verity. The recognized locations are on /system or
+// /data/misc/apexdata/com.android.art.
+bool LocationIsTrusted(const std::string& location, bool trust_art_apex_data_files);
 
 // Compare the ART module root against android root. Returns true if they are
 // both known and distinct. This is meant to be a proxy for 'running with apex'.
diff --git a/libartbase/base/file_utils_test.cc b/libartbase/base/file_utils_test.cc
index 85c1104..4dce3dc 100644
--- a/libartbase/base/file_utils_test.cc
+++ b/libartbase/base/file_utils_test.cc
@@ -19,6 +19,8 @@
 #include <libgen.h>
 #include <stdlib.h>
 
+#include <optional>
+
 #include "base/stl_util.h"
 #include "common_art_test.h"
 
@@ -46,19 +48,14 @@
   EXPECT_EQ("/foo/system@framework@boot.oat", name);
 }
 
-TEST_F(FileUtilsTest, GetDalvikCache) {
-  EXPECT_STREQ("", GetDalvikCache("should-not-exist123").c_str());
-
-  EXPECT_STREQ((android_data_ + "/dalvik-cache/.").c_str(), GetDalvikCache(".").c_str());
-}
-
-
 TEST_F(FileUtilsTest, GetSystemImageFilename) {
   EXPECT_STREQ("/system/framework/arm/boot.art",
                GetSystemImageFilename("/system/framework/boot.art", InstructionSet::kArm).c_str());
 }
 
-TEST_F(FileUtilsTest, GetAndroidRootSafe) {
+// TODO(dsrbecky): b/160885380: This test is failing in eng-prod because libartbase
+//                              is loaded from different path (under testcases).
+TEST_F(FileUtilsTest, DISABLED_GetAndroidRootSafe) {
   std::string error_msg;
 
   // We don't expect null returns for most cases, so don't check and let std::string crash.
@@ -78,6 +75,7 @@
   // Set a bogus value for ANDROID_ROOT. This should be an error.
   ASSERT_EQ(0, setenv("ANDROID_ROOT", "/this/is/obviously/bogus", /* overwrite */ 1));
   EXPECT_EQ(GetAndroidRootSafe(&error_msg), "");
+  error_msg = "";
 
   // Inferring the Android Root from the location of libartbase only works on host.
   if (!kIsTargetBuild) {
@@ -162,4 +160,107 @@
   EXPECT_EQ("/.directory/file.vdex", ReplaceFileExtension("/.directory/file", "vdex"));
 }
 
+TEST_F(FileUtilsTest, GetApexDataOatFilename) {
+  ScopedUnsetEnvironmentVariable android_root("ANDROID_ROOT");
+  ScopedUnsetEnvironmentVariable i18n_root("ANDROID_I18N_ROOT");
+  ScopedUnsetEnvironmentVariable art_apex_data("ART_APEX_DATA");
+
+  EXPECT_EQ(GetArtApexData() + "/dalvik-cache/arm/boot-beep.oat",
+            GetApexDataOatFilename("/product/javalib/beep.jar", InstructionSet::kArm));
+
+  const std::string art_apex_jar = std::string {kAndroidArtApexDefaultPath} + "/javalib/some.jar";
+  EXPECT_EQ(std::string{}, GetApexDataOatFilename(art_apex_jar.c_str(), InstructionSet::kArm));
+
+  const std::string i18n_jar =
+      std::string {kAndroidI18nApexDefaultPath} + "/javalib/core-icu4j.jar";
+  EXPECT_EQ(std::string{}, GetApexDataOatFilename(i18n_jar, InstructionSet::kArm));
+
+  const std::string system_jar_apexdata_oat = GetArtApexData() + "/dalvik-cache/x86/boot-lace.oat";
+  EXPECT_EQ(system_jar_apexdata_oat,
+            GetApexDataOatFilename("/system/framework/lace.jar", InstructionSet::kX86));
+}
+
+TEST_F(FileUtilsTest, GetApexDataOdexFilename) {
+  ScopedUnsetEnvironmentVariable android_root("ANDROID_ROOT");
+  ScopedUnsetEnvironmentVariable art_apex_data("ART_APEX_DATA");
+
+  EXPECT_EQ(GetArtApexData() + "/dalvik-cache/arm/data@some@code.odex",
+            GetApexDataOdexFilename("/data/some/code.dex", InstructionSet::kArm));
+
+  const std::string art_apex_jar = std::string {kAndroidArtApexDefaultPath} + "/javalib/some.jar";
+  EXPECT_EQ(std::string{}, GetApexDataOdexFilename(art_apex_jar.c_str(), InstructionSet::kArm));
+
+  const std::string i18n_jar =
+      std::string {kAndroidI18nApexDefaultPath} + "/javalib/core-icu4j.jar";
+  EXPECT_EQ(std::string{}, GetApexDataOdexFilename(i18n_jar.c_str(), InstructionSet::kArm));
+
+  const std::string system_jar_apexdata_odex =
+      GetArtApexData() + "/dalvik-cache/x86/system@framework@cookie.jar@classes.odex";
+  EXPECT_EQ(system_jar_apexdata_odex,
+            GetApexDataOdexFilename("/system/framework/cookie.jar", InstructionSet::kX86));
+}
+
+TEST_F(FileUtilsTest, GetApexDataBootImage) {
+  ScopedUnsetEnvironmentVariable android_root("ANDROID_ROOT");
+  ScopedUnsetEnvironmentVariable art_apex_data("ART_APEX_DATA");
+
+  EXPECT_EQ(std::string{},
+            GetApexDataBootImage(std::string {kAndroidI18nApexDefaultPath} + "/javalib/bar.jar"));
+
+  // Check image location has the prefix "boot-" in front of the basename of dex location and
+  // that image suffix is .art.
+  const std::string system_jar = "/system/framework/disk.jar";
+  const std::string boot_image = GetApexDataBootImage(system_jar.c_str());
+  EXPECT_EQ(GetArtApexData() + "/dalvik-cache/boot-disk.art", boot_image);
+
+  // Check the image filename corresponds to the oat file for the same system jar.
+  const InstructionSet isa = InstructionSet::kArm64;
+  const std::string boot_image_filename = GetSystemImageFilename(boot_image.c_str(), isa);
+  const std::string accompanying_oat_file = ReplaceFileExtension(boot_image_filename, "oat");
+  EXPECT_EQ(accompanying_oat_file, GetApexDataOatFilename(system_jar.c_str(), isa));
+}
+
+TEST_F(FileUtilsTest, GetApexDataImage) {
+  ScopedUnsetEnvironmentVariable android_root("ANDROID_ROOT");
+  ScopedUnsetEnvironmentVariable art_apex_data("ART_APEX_DATA");
+
+  EXPECT_EQ(std::string{},
+            GetApexDataImage(std::string {kAndroidI18nApexDefaultPath} + "/lib/javalib/bar.jar"));
+
+  // Check image has basename of dex location with the .art suffix.
+  const char* jar = "/system/framework/mcguffin/test.jar";
+  const std::string image = GetApexDataImage(jar);
+  EXPECT_EQ(GetArtApexData() + "/dalvik-cache/system@framework@mcguffin@test.jar@classes.art",
+            image);
+
+  // Check the image filename corresponds to the .odex file for the same system jar.
+  const InstructionSet isa = InstructionSet::kX86_64;
+  const std::string image_filename = GetSystemImageFilename(image.c_str(), isa);
+  const std::string accompanying_odex_file = ReplaceFileExtension(image_filename, "odex");
+  EXPECT_EQ(accompanying_odex_file, GetApexDataOdexFilename(jar, isa));
+}
+
+TEST_F(FileUtilsTest, GetApexDataDalvikCacheFilename) {
+  // Check /apex inputs return empty string
+  const std::string apex_jar = std::string {kAndroidI18nApexDefaultPath} + "/lib/javalib/bar.jar";
+  EXPECT_EQ(std::string{},
+            GetApexDataDalvikCacheFilename(apex_jar, InstructionSet::kX86_64, "art"));
+
+  // Check dalvik-cache filename follows convention.
+  const std::string non_apex_jar = "/vendor/javalib/test.jar";
+  const std::string art_filename =
+      GetApexDataDalvikCacheFilename(non_apex_jar, InstructionSet::kArm, "art");
+  CHECK_EQ(GetArtApexData() + "/dalvik-cache/arm/vendor@javalib@test.jar@classes.art",
+           art_filename);
+
+  // Check ".art", ".odex" and ".vdex" filenames are the same with the appropriate extensions
+  // substituted.
+  const std::string odex_filename =
+      GetApexDataDalvikCacheFilename(non_apex_jar, InstructionSet::kArm, "odex");
+  CHECK_EQ(odex_filename, ReplaceFileExtension(art_filename, "odex"));
+  const std::string vdex_filename =
+      GetApexDataDalvikCacheFilename(non_apex_jar, InstructionSet::kArm, "vdex");
+  CHECK_EQ(vdex_filename, ReplaceFileExtension(art_filename, "vdex"));
+}
+
 }  // namespace art
diff --git a/libartbase/base/flags.cc b/libartbase/base/flags.cc
new file mode 100644
index 0000000..6cf9ef1
--- /dev/null
+++ b/libartbase/base/flags.cc
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2021 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 "flags.h"
+
+#include <algorithm>
+
+#include "android-base/parsebool.h"
+#include "android-base/parseint.h"
+#include "android-base/properties.h"
+
+#include "base/utils.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+namespace {
+constexpr const char* kPhenotypeFlagPrefix = "persist.device_config.runtime_native.";
+constexpr const char* kSysPropertyFlagPrefix = "dalvik.vm.";
+constexpr const char* kUndefinedValue = "";
+
+// The various ParseValue functions store the parsed value into *destination. If parsing fails for
+// some reason, ParseValue makes no changes to *destination.
+
+bool ParseValue(const std::string_view value, std::optional<bool>* destination) {
+  switch (::android::base::ParseBool(value)) {
+    case ::android::base::ParseBoolResult::kError:
+      return false;
+    case ::android::base::ParseBoolResult::kTrue:
+      *destination = true;
+      return true;
+    case ::android::base::ParseBoolResult::kFalse:
+      *destination = false;
+      return true;
+  }
+}
+
+bool ParseValue(const std::string_view value, std::optional<int32_t>* destination) {
+  int32_t parsed_value = 0;
+  if (::android::base::ParseInt(std::string{value}, &parsed_value)) {
+    *destination = parsed_value;
+    return true;
+  }
+  return false;
+}
+
+bool ParseValue(const std::string_view value,
+                std::optional<uint32_t>* destination) {
+  uint32_t parsed_value = 0;
+  if (::android::base::ParseUint(std::string{value}, &parsed_value)) {
+    *destination = parsed_value;
+    return true;
+  }
+  return false;
+}
+
+bool ParseValue(const std::string_view value, std::optional<std::string>* destination) {
+  *destination = value;
+  return true;
+}
+
+}  // namespace
+
+namespace art {
+
+template <>
+std::forward_list<FlagBase*> FlagBase::ALL_FLAGS{};
+
+// gFlags must be defined after FlagBase::ALL_FLAGS so the constructors run in the right order.
+Flags gFlags;
+
+static std::string GenerateCmdLineArgName(const std::string& name) {
+  std::string result = "-X" + name + ":_";
+  std::replace(result.begin(), result.end(), '.', '-');
+  return result;
+}
+
+static std::string GenerateSysPropName(const std::string& name) {
+  return kSysPropertyFlagPrefix + name;
+}
+
+static std::string GeneratePhenotypeName(const std::string& name) {
+  return kPhenotypeFlagPrefix + name;
+}
+
+template <typename Value>
+Flag<Value>::Flag(const std::string& name, Value default_value, FlagType type) :
+    FlagBase(GenerateCmdLineArgName(name),
+             GenerateSysPropName(name),
+             GeneratePhenotypeName(name),
+             type),
+    initialized_{false},
+    default_{default_value} {
+  ALL_FLAGS.push_front(this);
+}
+
+template <typename Value>
+Flag<Value>::~Flag() {
+  ALL_FLAGS.remove(this);
+}
+
+template <typename Value>
+void Flag<Value>::Reload() {
+  initialized_ = true;
+
+  // The cmdline flags are loaded by the parsed_options infra. No action needed here.
+  if (type_ == FlagType::kCmdlineOnly) {
+    return;
+  }
+
+  // Load system properties.
+  from_system_property_ = std::nullopt;
+  const std::string sysprop = ::android::base::GetProperty(system_property_name_, kUndefinedValue);
+  if (sysprop != kUndefinedValue) {
+    if (!ParseValue(sysprop, &from_system_property_)) {
+      LOG(ERROR) << "Failed to parse " << system_property_name_ << "=" << sysprop;
+    }
+  }
+
+  // Load the server-side configuration.
+  from_server_setting_ = std::nullopt;
+  const std::string server_config =
+      ::android::base::GetProperty(server_setting_name_, kUndefinedValue);
+  if (server_config != kUndefinedValue) {
+    if (!ParseValue(server_config, &from_server_setting_)) {
+      LOG(ERROR) << "Failed to parse " << server_setting_name_ << "=" << server_config;
+    }
+  }
+}
+
+template <typename Value>
+void DumpValue(std::ostream& oss, const std::optional<Value>& val) {
+  if (val.has_value()) {
+    oss << val.value();
+  } else {
+    oss << kUndefinedValue;
+  }
+}
+
+template <typename Value>
+void Flag<Value>::Dump(std::ostream& oss) const {
+  std::pair<Value, FlagOrigin> valueOrigin = GetValueAndOrigin();
+  std::string origin;
+  switch (std::get<1>(valueOrigin)) {
+    case FlagOrigin::kDefaultValue: origin = "default_value"; break;
+    case FlagOrigin::kCmdlineArg: origin = "cmdline_arg"; break;
+    case FlagOrigin::kSystemProperty: origin = "system_property"; break;
+    case FlagOrigin::kServerSetting: origin = "server_setting"; break;
+  }
+
+  oss << "value: " << std::get<0>(valueOrigin) << " (from " << origin << ")";
+
+  oss << "\n default: " << default_;
+  oss << "\n " << command_line_argument_name_ << ": ";
+  DumpValue(oss, from_command_line_);
+  oss << "\n " << system_property_name_ << ": ";
+  DumpValue(oss, from_system_property_);
+  oss << "\n " << server_setting_name_ << ": ";
+  DumpValue(oss, from_server_setting_);
+}
+
+template class Flag<bool>;
+template class Flag<int>;
+template class Flag<std::string>;
+
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
diff --git a/libartbase/base/flags.h b/libartbase/base/flags.h
new file mode 100644
index 0000000..d1e1ca6
--- /dev/null
+++ b/libartbase/base/flags.h
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2021 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_LIBARTBASE_BASE_FLAGS_H_
+#define ART_LIBARTBASE_BASE_FLAGS_H_
+
+#include <forward_list>
+#include <optional>
+#include <string>
+#include <variant>
+
+#include "logging.h"
+
+// This file defines a set of flags that can be used to enable/disable features within ART or
+// otherwise tune ART's behavior. Flags can be set through command line options, server side
+// configuration, system properties, or default values. This flexibility enables easier development
+// and also larger experiments.
+//
+// The value is retrieved in the following oder:
+//   1) server side (device config) property
+//   2) system property
+//   3) cmdline flag
+//   4) default value
+//
+// The flags are defined in the Flags struct near the bottom of the file. To define a new flag, add
+// a Flag field to the struct. Then to read the value of the flag, use gFlag.MyNewFlag().
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+namespace art {
+
+// Enum representing the type of the ART flag.
+enum class FlagType {
+  // A flag that only looks at the cmdline argument to retrieve its value.
+  kCmdlineOnly,
+  // A flag that also looks at system properties and device config
+  // (phenotype properties) when retrieving its value.
+  kDeviceConfig,
+};
+
+// FlagMetaBase handles automatically adding flags to the command line parser. It is parameterized
+// by all supported flag types. In general, this should be treated as though it does not exist and
+// FlagBase, which is already specialized to the types we support, should be used instead.
+template <typename... T>
+class FlagMetaBase {
+ public:
+  FlagMetaBase(const std::string&& command_line_argument_name,
+               const std::string&& system_property_name,
+               const std::string&& server_setting_name,
+               FlagType type) :
+      command_line_argument_name_(command_line_argument_name),
+      system_property_name_(system_property_name),
+      server_setting_name_(server_setting_name),
+      type_(type) {}
+  virtual ~FlagMetaBase() {}
+
+  template <typename Builder>
+  static void AddFlagsToCmdlineParser(Builder* builder) {
+    for (auto* flag : ALL_FLAGS) {
+      // Each flag can return a pointer to where its command line value is stored. Because these can
+      // be different types, the return value comes as a variant. The cases list below contains a
+      // lambda that is specialized to handle each branch of the variant and call the correct
+      // methods on the command line parser builder.
+      FlagValuePointer location = flag->GetCmdLineLocation();
+      auto cases = {std::function<void()>([&]() {
+        if (std::holds_alternative<std::optional<T>*>(location)) {
+          builder = &builder->Define(flag->command_line_argument_name_.c_str())
+                         .template WithType<T>()
+                         .IntoLocation(std::get<std::optional<T>*>(location));
+        }
+      })...};
+      for (auto c : cases) {
+        c();
+      }
+    }
+  }
+
+  // Reload the value of the flags.
+  //
+  // DO NOT CALL this outside Runtime Init or Zygote post fork.
+  // This is a convention, as we should strive to have a constant view
+  // of the flags and not change the runtime behaviour midway during execution.
+  static void ReloadAllFlags(const std::string& caller) {
+    // Check the caller. This is a simple workaround to attract the attention
+    // to a possible dangerous call to ReloadAllFlags, while avoid building
+    // a lot of infra for it or having a complex friend definition.
+    DCHECK(caller == "Init"
+        || caller == "ZygoteHooks_nativePostForkChild"
+        || caller == "ZygoteHooks_nativePostForkSystemServer"
+        || caller == "test") << caller;
+    for (auto* flag : ALL_FLAGS) {
+      flag->Reload();
+    }
+
+    if (VLOG_IS_ON(startup)) {
+      VLOG_STREAM(startup) << "Dumping flags for " << caller;
+      DumpFlags(VLOG_STREAM(startup));
+    }
+  }
+
+  // Dump all the flags info to the given stream.
+  static void DumpFlags(std::ostream& oss) {
+    for (auto* flag : ALL_FLAGS) {
+      oss << "\n{\n";
+      flag->Dump(oss);
+      oss << "\n}";
+    }
+  }
+
+ protected:
+  using FlagValuePointer = std::variant<std::optional<T>*...>;
+  // Return the pointer to the value holder associated with the cmd line location.
+  virtual FlagValuePointer GetCmdLineLocation() = 0;
+  // Reloads the flag values.
+  virtual void Reload() = 0;
+  // Dumps the flags info to the given stream.
+  virtual void Dump(std::ostream& oss) const = 0;
+
+  static std::forward_list<FlagMetaBase<T...>*> ALL_FLAGS;
+
+  const std::string command_line_argument_name_;
+  const std::string system_property_name_;
+  const std::string server_setting_name_;
+  FlagType type_;
+};
+
+using FlagBase = FlagMetaBase<bool, int32_t, uint32_t, std::string>;
+
+template <>
+std::forward_list<FlagBase*> FlagBase::ALL_FLAGS;
+
+class FlagsTests;
+
+// Describes the possible origins of a flag value.
+enum class FlagOrigin {
+  kDefaultValue,
+  kCmdlineArg,
+  kSystemProperty,
+  kServerSetting,
+};
+
+// This class defines a flag with a value of a particular type.
+template <typename Value>
+class Flag : public FlagBase {
+ public:
+  // Create a new Flag. The name parameter is used to generate the names from the various parameter
+  // sources. See the documentation on the Flags struct for an example.
+  Flag(const std::string& name, Value default_value, FlagType type);
+  virtual ~Flag();
+
+
+  // Returns the flag value.
+  //
+  // The value is retrieved in the following oder:
+  //   1) server side (device config) property
+  //   2) system property
+  //   3) cmdline flag
+  //   4) default value
+  ALWAYS_INLINE Value GetValue() const {
+    return std::get<0>(GetValueAndOrigin());
+  }
+
+  ALWAYS_INLINE Value operator()() const {
+    return GetValue();
+  }
+
+  // Return the value of the flag as optional.
+  //
+  // Returns the value of the flag if and only if the flag is set via
+  // a server side setting, system property or a cmdline arg.
+  // Otherwise it returns nullopt (meaning this never returns the default value).
+  //
+  // This is useful for properties that do not have a good default natural value
+  // (e.g. file path arguments).
+  ALWAYS_INLINE std::optional<Value> GetValueOptional() const {
+    std::pair<Value, FlagOrigin> result = GetValueAndOrigin();
+    return std::get<1>(result) == FlagOrigin::kDefaultValue
+      ? std::nullopt
+      : std::make_optional(std::get<0>(result));
+  }
+
+  // Returns the value and the origin of that value for the given flag.
+  ALWAYS_INLINE std::pair<Value, FlagOrigin> GetValueAndOrigin() const {
+    DCHECK(initialized_);
+    if (from_server_setting_.has_value()) {
+      return std::pair{from_server_setting_.value(), FlagOrigin::kServerSetting};
+    }
+    if (from_system_property_.has_value()) {
+      return std::pair{from_system_property_.value(), FlagOrigin::kSystemProperty};
+    }
+    if (from_command_line_.has_value()) {
+      return std::pair{from_command_line_.value(), FlagOrigin::kCmdlineArg};
+    }
+    return std::pair{default_, FlagOrigin::kDefaultValue};
+  }
+
+  void Dump(std::ostream& oss) const override;
+
+ protected:
+  FlagValuePointer GetCmdLineLocation() override { return &from_command_line_; }
+
+
+  // Reload the server-configured value and system property values. In general this should not be
+  // used directly, but it can be used to support reloading the value without restarting the device.
+  void Reload() override;
+
+ private:
+  bool initialized_;
+  const Value default_;
+  std::optional<Value> from_command_line_;
+  std::optional<Value> from_system_property_;
+  std::optional<Value> from_server_setting_;
+
+  friend class TestFlag;
+};
+
+// This struct contains the list of ART flags. Flags are parameterized by the type of value they
+// support (bool, int, string, etc.). In addition to field name, flags have a name for the parameter
+// as well.
+//
+// Example:
+//
+//     Flag<int> WriteMetricsToLog{"my-feature-test.flag", 42, FlagType::kDeviceConfig};
+//
+// This creates a boolean flag that can be read through gFlags.WriteMetricsToLog(). The default
+// value is false. Note that the default value can be left unspecified, in which the value of the
+// type's default constructor will be used.
+//
+// The flag can be set through the following generated means:
+//
+// Command Line:
+//
+//     -Xmy-feature-test-flag=1
+//
+// Server Side (Phenotype) Configuration:
+//
+//     persist.device_config.runtime_native.my-feature-test.flag
+//
+// System Property:
+//
+//     setprop dalvik.vm.metrics.my-feature-test.flag 2
+struct Flags {
+  // Flag used to test the infra.
+  // TODO: can be removed once we add real flags.
+  Flag<int32_t> MyFeatureTestFlag{"my-feature-test.flag", 42, FlagType::kDeviceConfig};
+
+
+  // Metric infra flags.
+
+  // The reporting spec for regular apps. An example of valid value is "S,1,2,4,*".
+  // See metrics::ReportingPeriodSpec for complete docs.
+  Flag<std::string> MetricsReportingSpec{"metrics.reporting-spec", "", FlagType::kDeviceConfig};
+
+  // The reporting spec for the system server. See MetricsReportingSpec as well.
+  Flag<std::string> MetricsReportingSpecSystemServer{"metrics.reporting-spec-server", "",
+      FlagType::kDeviceConfig};
+
+  // The mods that should report metrics. Together with MetricsReportingNumMods, they
+  // dictate what percentage of the runtime execution will report metrics.
+  // If the `session_id (a random number) % MetricsReportingNumMods < MetricsReportingMods`
+  // then the runtime session will report metrics.
+  //
+  // By default, the mods are 0, which means the reporting is disabled.
+  Flag<uint32_t> MetricsReportingMods{"metrics.reporting-mods", 0,
+      FlagType::kDeviceConfig};
+  Flag<uint32_t> MetricsReportingModsServer{"metrics.reporting-mods-server", 0,
+      FlagType::kDeviceConfig};
+
+  // See MetricsReportingMods docs.
+  //
+  // By default the number of mods is 100, so MetricsReportingMods will naturally
+  // read as the percent of runtime sessions that will report metrics. If a finer
+  // grain unit is needed (e.g. a tenth of a percent), the num-mods can be increased.
+  Flag<uint32_t> MetricsReportingNumMods{"metrics.reporting-num-mods", 100,
+      FlagType::kDeviceConfig};
+  Flag<uint32_t> MetricsReportingNumModsServer{"metrics.reporting-num-mods-server", 100,
+      FlagType::kDeviceConfig};
+
+  // Whether or not we should write metrics to statsd.
+  // Note that the actual write is still controlled by
+  // MetricsReportingMods and MetricsReportingNumMods.
+  Flag<bool> MetricsWriteToStatsd{ "metrics.write-to-statsd", false, FlagType::kDeviceConfig};
+
+  // Whether or not we should write metrics to logcat.
+  // Note that the actual write is still controlled by
+  // MetricsReportingMods and MetricsReportingNumMods.
+  Flag<bool> MetricsWriteToLogcat{ "metrics.write-to-logcat", false, FlagType::kCmdlineOnly};
+
+  // Whether or not we should write metrics to a file.
+  // Note that the actual write is still controlled by
+  // MetricsReportingMods and MetricsReportingNumMods.
+  Flag<std::string> MetricsWriteToFile{"metrics.write-to-file", "", FlagType::kCmdlineOnly};
+};
+
+// This is the actual instance of all the flags.
+extern Flags gFlags;
+
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
+
+#endif  // ART_LIBARTBASE_BASE_FLAGS_H_
diff --git a/libartbase/base/flags_test.cc b/libartbase/base/flags_test.cc
new file mode 100644
index 0000000..b41df46
--- /dev/null
+++ b/libartbase/base/flags_test.cc
@@ -0,0 +1,247 @@
+/*
+ * 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.
+ */
+
+#include "base/flags.h"
+
+#include <optional>
+
+#include "android-base/properties.h"
+#include "common_runtime_test.h"
+
+
+namespace art {
+
+// Tests may be run in parallel so this helper class ensures
+// that we generate a unique test flag each time to avoid
+// tests stepping on each other
+class TestFlag {
+ public:
+  // Takes control of the tmp_file pointer.
+  TestFlag(ScratchFile* tmp_file, FlagType flag_type) {
+    tmp_file_.reset(tmp_file);
+
+    std::string tmp_name = tmp_file_->GetFilename();
+    size_t tmp_last_slash = tmp_name.rfind('/');
+    tmp_name = tmp_name.substr(tmp_last_slash + 1);
+
+    flag_name_ = "art.gtest." + tmp_name;
+    system_prop_name_ = "dalvik.vm." + flag_name_;
+    server_name_ = "persist.device_config.runtime_native." + flag_name_;
+    cmd_line_name_ = flag_name_;
+    std::replace(cmd_line_name_.begin(), cmd_line_name_.end(), '.', '-');
+
+    flag_.reset(new Flag<int>(flag_name_, /*default_value=*/ 42, flag_type));
+  }
+
+  void AssertCmdlineValue(bool has_value, int expected) {
+    ASSERT_EQ(flag_->from_command_line_.has_value(), has_value);
+    if (has_value) {
+      ASSERT_EQ(flag_->from_command_line_.value(), expected);
+    }
+  }
+
+  void AssertSysPropValue(bool has_value, int expected) {
+    ASSERT_EQ(flag_->from_system_property_.has_value(), has_value);
+    if (has_value) {
+      ASSERT_EQ(flag_->from_system_property_.value(), expected);
+    }
+  }
+
+  void AssertServerSettingValue(bool has_value, int expected) {
+    ASSERT_EQ(flag_->from_server_setting_.has_value(), has_value);
+    if (has_value) {
+      ASSERT_EQ(flag_->from_server_setting_.value(), expected);
+    }
+  }
+
+  void AssertDefaultValue(int expected) {
+    ASSERT_EQ(flag_->default_, expected);
+  }
+
+  int Value() {
+    return (*flag_)();
+  }
+
+  std::string SystemProperty() const {
+    return system_prop_name_;
+  }
+
+  std::string ServerSetting() const {
+    return server_name_;
+  }
+
+  std::string CmdLineName() const {
+    return cmd_line_name_;
+  }
+
+ private:
+  std::unique_ptr<ScratchFile> tmp_file_;
+  std::unique_ptr<Flag<int>> flag_;
+  std::string flag_name_;
+  std::string cmd_line_name_;
+  std::string system_prop_name_;
+  std::string server_name_;
+};
+
+class FlagsTests : public CommonRuntimeTest {
+ protected:
+  // We need to initialize the flag after the ScratchDir is created
+  // but before we configure the runtime options (so that we can get
+  // the right name for the config).
+  //
+  // So we do it in SetUpRuntimeOptions.
+  virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
+    test_flag_.reset(new TestFlag(new ScratchFile(), FlagType::kDeviceConfig));
+    CommonRuntimeTest::SetUpRuntimeOptions(options);
+  }
+
+  virtual void TearDown() {
+    test_flag_ = nullptr;
+    CommonRuntimeTest::TearDown();
+  }
+
+  std::unique_ptr<TestFlag> test_flag_;
+};
+
+class FlagsTestsWithCmdLineBase : public FlagsTests {
+ public:
+  explicit FlagsTestsWithCmdLineBase(FlagType type) : flag_type_(type) {
+  }
+
+ protected:
+  virtual void TearDown() {
+    android::base::SetProperty(test_flag_->SystemProperty(), "");
+    android::base::SetProperty(test_flag_->ServerSetting(), "");
+    FlagsTests::TearDown();
+  }
+
+  virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
+    test_flag_.reset(new TestFlag(new ScratchFile(), flag_type_));
+    std::string option = "-X" + test_flag_->CmdLineName() + ":1";
+    options->emplace_back(option.c_str(), nullptr);
+  }
+
+  FlagType flag_type_;
+};
+
+class FlagsTestsWithCmdLine : public FlagsTestsWithCmdLineBase {
+ public:
+  FlagsTestsWithCmdLine() : FlagsTestsWithCmdLineBase(FlagType::kDeviceConfig) {
+  }
+};
+
+class FlagsTestsCmdLineOnly : public FlagsTestsWithCmdLineBase {
+ public:
+  FlagsTestsCmdLineOnly() : FlagsTestsWithCmdLineBase(FlagType::kCmdlineOnly) {
+  }
+};
+
+// Validate that when no flag is set, the default is taken and none of the other
+// locations are populated
+TEST_F(FlagsTests, ValidateDefaultValue) {
+  FlagBase::ReloadAllFlags("test");
+
+  test_flag_->AssertCmdlineValue(false, 1);
+  test_flag_->AssertSysPropValue(false, 2);
+  test_flag_->AssertServerSettingValue(false, 3);
+  test_flag_->AssertDefaultValue(42);
+
+  ASSERT_EQ(test_flag_->Value(), 42);
+}
+
+// Validate that the server side config is picked when it is set.
+TEST_F(FlagsTestsWithCmdLine, FlagsTestsGetValueServerSetting) {
+  // On older releases (e.g. nougat) the system properties have very strict
+  // limitations (e.g. for length) and setting the properties will fail.
+  // On modern platforms this should not be the case, so condition the test
+  // based on the success of setting the properties.
+  if (!android::base::SetProperty(test_flag_->SystemProperty(), "2")) {
+    LOG(ERROR) << "Release does not support property setting, skipping test: "
+        << test_flag_->SystemProperty();
+    return;
+  }
+
+  if (android::base::SetProperty(test_flag_->ServerSetting(), "3")) {
+    LOG(ERROR) << "Release does not support property setting, skipping test: "
+        << test_flag_->ServerSetting();
+    return;
+  }
+
+  FlagBase::ReloadAllFlags("test");
+
+  test_flag_->AssertCmdlineValue(true, 1);
+  test_flag_->AssertSysPropValue(true, 2);
+  test_flag_->AssertServerSettingValue(true, 3);
+  test_flag_->AssertDefaultValue(42);
+
+  ASSERT_EQ(test_flag_->Value(), 3);
+}
+
+// Validate that the system property value is picked when the server one is not set.
+TEST_F(FlagsTestsWithCmdLine, FlagsTestsGetValueSysProperty) {
+  if (!android::base::SetProperty(test_flag_->SystemProperty(), "2")) {
+    LOG(ERROR) << "Release does not support property setting, skipping test: "
+        << test_flag_->SystemProperty();
+    return;
+  }
+
+  FlagBase::ReloadAllFlags("test");
+
+  test_flag_->AssertCmdlineValue(true, 1);
+  test_flag_->AssertSysPropValue(true, 2);
+  test_flag_->AssertServerSettingValue(false, 3);
+  test_flag_->AssertDefaultValue(42);
+
+  ASSERT_EQ(test_flag_->Value(), 2);
+}
+
+// Validate that the cmdline value is picked when no properties are set.
+TEST_F(FlagsTestsWithCmdLine, FlagsTestsGetValueCmdline) {
+  FlagBase::ReloadAllFlags("test");
+
+  test_flag_->AssertCmdlineValue(true, 1);
+  test_flag_->AssertSysPropValue(false, 2);
+  test_flag_->AssertServerSettingValue(false, 3);
+  test_flag_->AssertDefaultValue(42);
+
+  ASSERT_EQ(test_flag_->Value(), 1);
+}
+
+// Validate that cmdline only flags don't read system properties.
+TEST_F(FlagsTestsCmdLineOnly, CmdlineOnlyFlags) {
+  if (!android::base::SetProperty(test_flag_->SystemProperty(), "2")) {
+    LOG(ERROR) << "Release does not support property setting, skipping test: "
+        << test_flag_->SystemProperty();
+    return;
+  }
+
+  if (android::base::SetProperty(test_flag_->ServerSetting(), "3")) {
+    LOG(ERROR) << "Release does not support property setting, skipping test: "
+        << test_flag_->ServerSetting();
+    return;
+  }
+
+  FlagBase::ReloadAllFlags("test");
+
+  test_flag_->AssertCmdlineValue(true, 1);
+  test_flag_->AssertSysPropValue(false, 2);
+  test_flag_->AssertServerSettingValue(false, 3);
+  test_flag_->AssertDefaultValue(42);
+
+  ASSERT_EQ(test_flag_->Value(), 1);
+}
+
+}  // namespace art
diff --git a/libartbase/base/globals.h b/libartbase/base/globals.h
index 97eae63..700d4e6 100644
--- a/libartbase/base/globals.h
+++ b/libartbase/base/globals.h
@@ -36,7 +36,7 @@
 
 // System page size. We check this against sysconf(_SC_PAGE_SIZE) at runtime, but use a simple
 // compile-time constant so the compiler can generate better code.
-static constexpr int kPageSize = 4096;
+static constexpr size_t kPageSize = 4096;
 
 // 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
diff --git a/libartbase/base/globals_unix.cc b/libartbase/base/globals_unix.cc
index 0d2e8a9..9a67dc4 100644
--- a/libartbase/base/globals_unix.cc
+++ b/libartbase/base/globals_unix.cc
@@ -22,6 +22,8 @@
 
 namespace art {
 
+#ifndef ART_STATIC_LIBARTBASE
+
 #ifdef __APPLE__
 // dlopen(3) on Linux with just an SO name will search the already
 // opened libraries. On Darwin, we need dlopen(3) needs the SO name
@@ -72,4 +74,6 @@
   }
 } g_check_loaded_build;
 
+#endif  // !ART_STATIC_LIBARTBASE
+
 }  // namespace art
diff --git a/libartbase/base/hash_map.h b/libartbase/base/hash_map.h
index a3bb5b5..8823c8b 100644
--- a/libartbase/base/hash_map.h
+++ b/libartbase/base/hash_map.h
@@ -23,53 +23,76 @@
 
 namespace art {
 
-template <typename Fn>
-class HashMapWrapper {
+template <typename Key, typename Value, typename HashFn>
+class HashMapHashWrapper {
  public:
-  // Hash function.
-  template <class Key, class Value>
-  size_t operator()(const std::pair<Key, Value>& pair) const {
-    return fn_(pair.first);
-  }
-  template <class Key>
   size_t operator()(const Key& key) const {
-    return fn_(key);
+    return hash_fn_(key);
   }
-  template <class Key, class Value>
-  bool operator()(const std::pair<Key, Value>& a, const std::pair<Key, Value>& b) const {
-    return fn_(a.first, b.first);
-  }
-  template <class Key, class Value, class Element>
-  bool operator()(const std::pair<Key, Value>& a, const Element& element) const {
-    return fn_(a.first, element);
+
+  size_t operator()(const std::pair<Key, Value>& pair) const {
+    return hash_fn_(pair.first);
   }
 
  private:
-  Fn fn_;
+  HashFn hash_fn_;
+};
+
+template <typename Key, typename Value, typename PredFn>
+class HashMapPredWrapper {
+ public:
+  bool operator()(const std::pair<Key, Value>& a, const std::pair<Key, Value>& b) const {
+    return pred_fn_(a.first, b.first);
+  }
+
+  template <typename Element>
+  bool operator()(const std::pair<Key, Value>& a, const Element& element) const {
+    return pred_fn_(a.first, element);
+  }
+
+ private:
+  PredFn pred_fn_;
+};
+
+template <typename Key, typename Value>
+class DefaultMapEmptyFn {
+ public:
+  void MakeEmpty(std::pair<Key, Value>& item) const {
+    item = std::pair<Key, Value>();
+  }
+  bool IsEmpty(const std::pair<Key, Value>& item) const {
+    return item.first == Key();
+  }
 };
 
 template <class Key,
           class Value,
-          class EmptyFn,
+          class EmptyFn = DefaultMapEmptyFn<Key, Value>,
           class HashFn = DefaultHashFn<Key>,
           class Pred = DefaultPred<Key>,
           class Alloc = std::allocator<std::pair<Key, Value>>>
 class HashMap : public HashSet<std::pair<Key, Value>,
                                EmptyFn,
-                               HashMapWrapper<HashFn>,
-                               HashMapWrapper<Pred>,
+                               HashMapHashWrapper<Key, Value, HashFn>,
+                               HashMapPredWrapper<Key, Value, Pred>,
                                Alloc> {
  private:
   using Base = HashSet<std::pair<Key, Value>,
                        EmptyFn,
-                       HashMapWrapper<HashFn>,
-                       HashMapWrapper<Pred>,
+                       HashMapHashWrapper<Key, Value, HashFn>,
+                       HashMapPredWrapper<Key, Value, Pred>,
                        Alloc>;
 
  public:
-  HashMap() : Base() { }
-  explicit HashMap(const Alloc& alloc)
-      : Base(alloc) { }
+  // Inherit constructors.
+  using Base::Base;
+
+  // Used to insert a new mapping.
+  typename Base::iterator Overwrite(const Key& k, const Value& v) {
+    auto res = Base::insert({ k, v }).first;
+    *res = { k, v };
+    return res;
+  }
 };
 
 }  // namespace art
diff --git a/libartbase/base/hash_map_test.cc b/libartbase/base/hash_map_test.cc
new file mode 100644
index 0000000..4ef8eee
--- /dev/null
+++ b/libartbase/base/hash_map_test.cc
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 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 "hash_map.h"
+
+#include <gtest/gtest.h>
+
+namespace art {
+
+TEST(HashMap, NonComparableValue) {
+  struct IntWrapper { int value; };  // Not equality comparable.
+  HashMap<int, IntWrapper> map;
+  map.insert(std::make_pair(1, IntWrapper{2}));
+}
+
+}  // namespace art
diff --git a/libartbase/base/hash_set.h b/libartbase/base/hash_set.h
index 585c4ce..bd2ac38 100644
--- a/libartbase/base/hash_set.h
+++ b/libartbase/base/hash_set.h
@@ -193,9 +193,37 @@
   }
 
   HashSet() : HashSet(kDefaultMinLoadFactor, kDefaultMaxLoadFactor) {}
+  explicit HashSet(const allocator_type& alloc) noexcept
+      : HashSet(kDefaultMinLoadFactor, kDefaultMaxLoadFactor, alloc) {}
 
   HashSet(double min_load_factor, double max_load_factor) noexcept
-      : num_elements_(0u),
+      : HashSet(min_load_factor, max_load_factor, allocator_type()) {}
+  HashSet(double min_load_factor, double max_load_factor, const allocator_type& alloc) noexcept
+      : HashSet(min_load_factor, max_load_factor, HashFn(), Pred(), alloc) {}
+
+  HashSet(const HashFn& hashfn,
+          const Pred& pred) noexcept
+      : HashSet(kDefaultMinLoadFactor, kDefaultMaxLoadFactor, hashfn, pred) {}
+  HashSet(const HashFn& hashfn,
+          const Pred& pred,
+          const allocator_type& alloc) noexcept
+      : HashSet(kDefaultMinLoadFactor, kDefaultMaxLoadFactor, hashfn, pred, alloc) {}
+
+  HashSet(double min_load_factor,
+          double max_load_factor,
+          const HashFn& hashfn,
+          const Pred& pred) noexcept
+      : HashSet(min_load_factor, max_load_factor, hashfn, pred, allocator_type()) {}
+  HashSet(double min_load_factor,
+          double max_load_factor,
+          const HashFn& hashfn,
+          const Pred& pred,
+          const allocator_type& alloc) noexcept
+      : allocfn_(alloc),
+        hashfn_(hashfn),
+        emptyfn_(),
+        pred_(pred),
+        num_elements_(0u),
         num_buckets_(0u),
         elements_until_expand_(0u),
         owns_data_(false),
@@ -206,20 +234,6 @@
     DCHECK_LT(max_load_factor, 1.0);
   }
 
-  explicit HashSet(const allocator_type& alloc) noexcept
-      : allocfn_(alloc),
-        hashfn_(),
-        emptyfn_(),
-        pred_(),
-        num_elements_(0u),
-        num_buckets_(0u),
-        elements_until_expand_(0u),
-        owns_data_(false),
-        data_(nullptr),
-        min_load_factor_(kDefaultMinLoadFactor),
-        max_load_factor_(kDefaultMaxLoadFactor) {
-  }
-
   HashSet(const HashSet& other) noexcept
       : allocfn_(other.allocfn_),
         hashfn_(other.hashfn_),
@@ -259,6 +273,34 @@
     other.data_ = nullptr;
   }
 
+  // Construct with pre-existing buffer, usually stack-allocated,
+  // to avoid malloc/free overhead for small HashSet<>s.
+  HashSet(value_type* buffer, size_t buffer_size)
+      : HashSet(kDefaultMinLoadFactor, kDefaultMaxLoadFactor, buffer, buffer_size) {}
+  HashSet(value_type* buffer, size_t buffer_size, const allocator_type& alloc)
+      : HashSet(kDefaultMinLoadFactor, kDefaultMaxLoadFactor, buffer, buffer_size, alloc) {}
+  HashSet(double min_load_factor, double max_load_factor, value_type* buffer, size_t buffer_size)
+      : HashSet(min_load_factor, max_load_factor, buffer, buffer_size, allocator_type()) {}
+  HashSet(double min_load_factor,
+          double max_load_factor,
+          value_type* buffer,
+          size_t buffer_size,
+          const allocator_type& alloc)
+      : allocfn_(alloc),
+        num_elements_(0u),
+        num_buckets_(buffer_size),
+        elements_until_expand_(buffer_size * max_load_factor),
+        owns_data_(false),
+        data_(buffer),
+        min_load_factor_(min_load_factor),
+        max_load_factor_(max_load_factor) {
+    DCHECK_GT(min_load_factor, 0.0);
+    DCHECK_LT(max_load_factor, 1.0);
+    for (size_t i = 0; i != buffer_size; ++i) {
+      emptyfn_.MakeEmpty(buffer[i]);
+    }
+  }
+
   // Construct from existing data.
   // Read from a block of memory, if make_copy_of_data is false, then data_ points to within the
   // passed in ptr_.
@@ -417,8 +459,8 @@
 
   // Find an element, returns end() if not found.
   // Allows custom key (K) types, example of when this is useful:
-  // Set of Class* sorted by name, want to find a class with a name but can't allocate a dummy
-  // object in the heap for performance solution.
+  // Set of Class* indexed by name, want to find a class with a name but can't allocate
+  // a temporary Class object in the heap for performance solution.
   template <typename K>
   iterator find(const K& key) {
     return FindWithHash(key, hashfn_(key));
@@ -439,7 +481,7 @@
     return const_iterator(this, FindIndex(key, hash));
   }
 
-  // Insert an element with hint, allows duplicates.
+  // Insert an element with hint.
   // Note: The hint is not very useful for a HashSet<> unless there are many hash conflicts
   // and in that case the use of HashSet<> itself should be reconsidered.
   std::pair<iterator, bool> insert(const_iterator hint ATTRIBUTE_UNUSED, const T& element) {
@@ -449,7 +491,7 @@
     return insert(std::move(element));
   }
 
-  // Insert an element, allows duplicates.
+  // Insert an element.
   std::pair<iterator, bool> insert(const T& element) {
     return InsertWithHash(element, hashfn_(element));
   }
@@ -768,6 +810,7 @@
   friend class HashSetIterator;
 
   ART_FRIEND_TEST(InternTableTest, CrossHash);
+  ART_FRIEND_TEST(HashSetTest, Preallocated);
 };
 
 template <class T, class EmptyFn, class HashFn, class Pred, class Alloc>
diff --git a/libartbase/base/hash_set_test.cc b/libartbase/base/hash_set_test.cc
index 9e6e6d2..b7b289c 100644
--- a/libartbase/base/hash_set_test.cc
+++ b/libartbase/base/hash_set_test.cc
@@ -357,7 +357,7 @@
 }
 
 TEST_F(HashSetTest, IteratorConversion) {
-  const char* test_string = "dummy";
+  const char* test_string = "test string";
   HashSet<std::string> hash_set;
   HashSet<std::string>::iterator it = hash_set.insert(test_string).first;
   HashSet<std::string>::const_iterator cit = it;
@@ -366,7 +366,7 @@
 }
 
 TEST_F(HashSetTest, StringSearchStringView) {
-  const char* test_string = "dummy";
+  const char* test_string = "test string";
   HashSet<std::string> hash_set;
   HashSet<std::string>::iterator insert_pos = hash_set.insert(test_string).first;
   HashSet<std::string>::iterator it = hash_set.find(std::string_view(test_string));
@@ -374,11 +374,118 @@
 }
 
 TEST_F(HashSetTest, DoubleInsert) {
-  const char* test_string = "dummy";
+  const char* test_string = "test string";
   HashSet<std::string> hash_set;
   hash_set.insert(test_string);
   hash_set.insert(test_string);
   ASSERT_EQ(1u, hash_set.size());
 }
 
+TEST_F(HashSetTest, Preallocated) {
+  static const size_t kBufferSize = 64;
+  uint32_t buffer[kBufferSize];
+  HashSet<uint32_t> hash_set(buffer, kBufferSize);
+  size_t max_without_resize = kBufferSize * hash_set.GetMaxLoadFactor();
+  for (size_t i = 0; i != max_without_resize; ++i) {
+    hash_set.insert(i);
+  }
+  ASSERT_FALSE(hash_set.owns_data_);
+  hash_set.insert(max_without_resize);
+  ASSERT_TRUE(hash_set.owns_data_);
+}
+
+class SmallIndexEmptyFn {
+ public:
+  void MakeEmpty(uint16_t& item) const {
+    item = std::numeric_limits<uint16_t>::max();
+  }
+  bool IsEmpty(const uint16_t& item) const {
+    return item == std::numeric_limits<uint16_t>::max();
+  }
+};
+
+class StatefulHashFn {
+ public:
+  explicit StatefulHashFn(const std::vector<std::string>* strings)
+      : strings_(strings) {}
+
+  size_t operator() (const uint16_t& index) const {
+    CHECK_LT(index, strings_->size());
+    return (*this)((*strings_)[index]);
+  }
+
+  size_t operator() (std::string_view s) const {
+    return DataHash()(s);
+  }
+
+ private:
+  const std::vector<std::string>* strings_;
+};
+
+class StatefulPred {
+ public:
+  explicit StatefulPred(const std::vector<std::string>* strings)
+      : strings_(strings) {}
+
+  bool operator() (const uint16_t& lhs, const uint16_t& rhs) const {
+    CHECK_LT(rhs, strings_->size());
+    return (*this)(lhs, (*strings_)[rhs]);
+  }
+
+  bool operator() (const uint16_t& lhs, std::string_view rhs) const {
+    CHECK_LT(lhs, strings_->size());
+    return (*strings_)[lhs] == rhs;
+  }
+
+ private:
+  const std::vector<std::string>* strings_;
+};
+
+TEST_F(HashSetTest, StatefulHashSet) {
+  std::vector<std::string> strings{
+      "duplicate",
+      "a",
+      "b",
+      "xyz",
+      "___",
+      "123",
+      "placeholder",
+      "duplicate"
+  };
+  const size_t duplicateFirstIndex = 0;
+  const size_t duplicateSecondIndex = strings.size() - 1u;
+  const size_t otherIndex = 1u;
+
+  StatefulHashFn hashfn(&strings);
+  StatefulPred pred(&strings);
+  HashSet<uint16_t, SmallIndexEmptyFn, StatefulHashFn, StatefulPred> hash_set(hashfn, pred);
+  for (size_t index = 0, size = strings.size(); index != size; ++index) {
+    bool inserted = hash_set.insert(index).second;
+    ASSERT_EQ(index != duplicateSecondIndex, inserted) << index;
+  }
+
+  // Check search by string.
+  for (size_t index = 0, size = strings.size(); index != size; ++index) {
+    auto it = hash_set.find(strings[index]);
+    ASSERT_FALSE(it == hash_set.end());
+    ASSERT_EQ(index == duplicateSecondIndex ? duplicateFirstIndex : index, *it) << index;
+  }
+  ASSERT_TRUE(hash_set.find("missing") == hash_set.end());
+
+  // Check search by index.
+  for (size_t index = 0, size = strings.size(); index != size; ++index) {
+    auto it = hash_set.find(index);
+    ASSERT_FALSE(it == hash_set.end());
+    ASSERT_EQ(index == duplicateSecondIndex ? duplicateFirstIndex : index, *it) << index;
+  }
+  // Note: Searching for index >= strings.size() is not supported by Stateful{HashFn,Pred}.
+
+  // Test removal and search by missing index.
+  auto remove_it = hash_set.find(otherIndex);
+  ASSERT_FALSE(remove_it == hash_set.end());
+  hash_set.erase(remove_it);
+  auto search_it = hash_set.find(otherIndex);
+  ASSERT_TRUE(search_it == hash_set.end());
+}
+
 }  // namespace art
diff --git a/libartbase/base/hiddenapi_flags.h b/libartbase/base/hiddenapi_flags.h
index a9a903b..3ece966 100644
--- a/libartbase/base/hiddenapi_flags.h
+++ b/libartbase/base/hiddenapi_flags.h
@@ -81,27 +81,28 @@
 class ApiList {
  private:
   // Number of bits reserved for Value in dex flags, and the corresponding bit mask.
-  static constexpr uint32_t kValueBitSize = 3;
+  static constexpr uint32_t kValueBitSize = 4;
   static constexpr uint32_t kValueBitMask = helper::BitMask(kValueBitSize);
 
   enum class Value : uint32_t {
     // Values independent of target SDK version of app
-    kWhitelist =    0,
-    kGreylist =     1,
-    kBlacklist =    2,
+    kSdk =    0,
+    kUnsupported =     1,
+    kBlocked =    2,
 
     // Values dependent on target SDK version of app. Put these last as
     // their list will be extended in future releases.
     // The max release code implicitly includes all maintenance releases,
-    // e.g. GreylistMaxO is accessible to targetSdkVersion <= 27 (O_MR1).
-    kGreylistMaxO = 3,
-    kGreylistMaxP = 4,
-    kGreylistMaxQ = 5,
+    // e.g. MaxTargetO is accessible to targetSdkVersion <= 27 (O_MR1).
+    kMaxTargetO = 3,
+    kMaxTargetP = 4,
+    kMaxTargetQ = 5,
+    kMaxTargetR = 6,
 
     // Special values
     kInvalid =      (static_cast<uint32_t>(-1) & kValueBitMask),
-    kMin =          kWhitelist,
-    kMax =          kGreylistMaxQ,
+    kMin =          kSdk,
+    kMax =          kMaxTargetR,
   };
 
   // Additional bit flags after the first kValueBitSize bits in dex flags.
@@ -122,7 +123,7 @@
   static_assert(kValueBitSize >= MinimumBitsToStore(helper::ToUint(Value::kMax)),
                 "Not enough bits to store all ApiList values");
 
-  // Sanity checks that all Values are covered by kValueBitMask.
+  // Checks that all Values are covered by kValueBitMask.
   static_assert(helper::MatchesBitMask(Value::kMin, kValueBitMask));
   static_assert(helper::MatchesBitMask(Value::kMax, kValueBitMask));
 
@@ -131,14 +132,19 @@
 
   // Names corresponding to Values.
   static constexpr const char* kValueNames[] = {
-    "whitelist",
-    "greylist",
-    "blacklist",
-    "greylist-max-o",
-    "greylist-max-p",
-    "greylist-max-q",
+    "sdk",
+    "unsupported",
+    "blocked",
+    "max-target-o",
+    "max-target-p",
+    "max-target-q",
+    "max-target-r",
   };
 
+  // A magic marker used by tests to mimic a hiddenapi list which doesn't exist
+  // yet.
+  static constexpr const char* kFutureValueName = "max-target-future";
+
   // Names corresponding to DomainApis.
   static constexpr const char* kDomainApiNames[] {
     "core-platform-api",
@@ -147,12 +153,13 @@
 
   // Maximum SDK versions allowed to access ApiList of given Value.
   static constexpr SdkVersion kMaxSdkVersions[] {
-    /* whitelist */ SdkVersion::kMax,
-    /* greylist */ SdkVersion::kMax,
-    /* blacklist */ SdkVersion::kMin,
-    /* greylist-max-o */ SdkVersion::kO_MR1,
-    /* greylist-max-p */ SdkVersion::kP,
-    /* greylist-max-q */ SdkVersion::kQ,
+    /* sdk */ SdkVersion::kMax,
+    /* unsupported */ SdkVersion::kMax,
+    /* blocklist */ SdkVersion::kMin,
+    /* max-target-o */ SdkVersion::kO_MR1,
+    /* max-target-p */ SdkVersion::kP,
+    /* max-target-q */ SdkVersion::kQ,
+    /* max-target-r */ SdkVersion::kR,
   };
 
   explicit ApiList(Value val, uint32_t domain_apis = 0u)
@@ -169,9 +176,11 @@
     // Treat all ones as invalid value
     if (value == helper::ToUint(Value::kInvalid)) {
       return Value::kInvalid;
+    } else if (value > helper::ToUint(Value::kMax)) {
+      // For future unknown flag values, return unsupported.
+      return Value::kUnsupported;
     } else {
       DCHECK_GE(value, helper::ToUint(Value::kMin));
-      DCHECK_LE(value, helper::ToUint(Value::kMax));
       return static_cast<Value>(value);
     }
   }
@@ -188,12 +197,13 @@
   }
 
   // Helpers for conveniently constructing ApiList instances.
-  static ApiList Whitelist() { return ApiList(Value::kWhitelist); }
-  static ApiList Greylist() { return ApiList(Value::kGreylist); }
-  static ApiList Blacklist() { return ApiList(Value::kBlacklist); }
-  static ApiList GreylistMaxO() { return ApiList(Value::kGreylistMaxO); }
-  static ApiList GreylistMaxP() { return ApiList(Value::kGreylistMaxP); }
-  static ApiList GreylistMaxQ() { return ApiList(Value::kGreylistMaxQ); }
+  static ApiList Sdk() { return ApiList(Value::kSdk); }
+  static ApiList Unsupported() { return ApiList(Value::kUnsupported); }
+  static ApiList Blocked() { return ApiList(Value::kBlocked); }
+  static ApiList MaxTargetO() { return ApiList(Value::kMaxTargetO); }
+  static ApiList MaxTargetP() { return ApiList(Value::kMaxTargetP); }
+  static ApiList MaxTargetQ() { return ApiList(Value::kMaxTargetQ); }
+  static ApiList MaxTargetR() { return ApiList(Value::kMaxTargetR); }
   static ApiList CorePlatformApi() { return ApiList(DomainApi::kCorePlatformApi); }
   static ApiList TestApi() { return ApiList(DomainApi::kTestApi); }
 
@@ -212,6 +222,10 @@
         return ApiList(helper::GetEnumAt<DomainApi>(i));
       }
     }
+    if (str == kFutureValueName) {
+      static_assert(helper::ToUint(Value::kMax) + 1 < helper::ToUint(Value::kInvalid));
+      return ApiList(helper::ToUint(Value::kMax) + 1);
+    }
     return ApiList();
   }
 
@@ -240,9 +254,26 @@
     return true;
   }
 
+  // Clamp a max-target-* up to the given maxSdk; if the given api list is higher than
+  // maxSdk, return unsupported instead.
+  static std::string CoerceAtMost(const std::string& name, const std::string& maxSdk) {
+    const auto apiListToClamp = FromName(name);
+    // If the api list is a domain instead, return it unmodified.
+    if (!apiListToClamp.IsValid()) {
+      return name;
+    }
+    const auto maxApiList = FromName(maxSdk);
+    CHECK(maxApiList.IsValid()) << "invalid api list name " << maxSdk;
+    if (apiListToClamp > maxApiList) {
+      return kValueNames[Unsupported().GetIntValue()];
+    }
+    return name;
+  }
+
   bool operator==(const ApiList& other) const { return dex_flags_ == other.dex_flags_; }
   bool operator!=(const ApiList& other) const { return !(*this == other); }
   bool operator<(const ApiList& other) const { return dex_flags_ < other.dex_flags_; }
+  bool operator>(const ApiList& other) const { return dex_flags_ > other.dex_flags_; }
 
   // Returns true if combining this ApiList with `other` will succeed.
   bool CanCombineWith(const ApiList& other) const {
@@ -290,9 +321,9 @@
   // Returns true when no ApiList is specified and no domain_api flags either.
   bool IsEmpty() const { return (GetValue() == Value::kInvalid) && (GetDomainApis() == 0); }
 
-  // Returns true if the ApiList is on blacklist.
-  bool IsBlacklisted() const {
-    return GetValue() == Value::kBlacklist;
+  // Returns true if the ApiList is on blocklist.
+  bool IsBlocked() const {
+    return GetValue() == Value::kBlocked;
   }
 
   // Returns true if the ApiList is a test API.
diff --git a/libartbase/base/hiddenapi_stubs.h b/libartbase/base/hiddenapi_stubs.h
index 94ef95c..74713a6 100644
--- a/libartbase/base/hiddenapi_stubs.h
+++ b/libartbase/base/hiddenapi_stubs.h
@@ -47,7 +47,8 @@
 
   static bool IsStubsFlag(const std::string_view& api_flag_name) {
     return api_flag_name == kPublicApiStr || api_flag_name == kSystemApiStr ||
-        api_flag_name == kTestApiStr || api_flag_name == kCorePlatformApiStr;
+        api_flag_name == kTestApiStr || api_flag_name == kCorePlatformApiStr ||
+        api_flag_name == kRemovedApiStr || api_flag_name == kLowPriorityApiStr;
   }
 
  private:
@@ -55,6 +56,8 @@
   static constexpr std::string_view kSystemApiStr{"system-api"};
   static constexpr std::string_view kTestApiStr{"test-api"};
   static constexpr std::string_view kCorePlatformApiStr{"core-platform-api"};
+  static constexpr std::string_view kRemovedApiStr{"removed"};
+  static constexpr std::string_view kLowPriorityApiStr{"lo-prio"};
 };
 
 }  // namespace hiddenapi
diff --git a/libartbase/base/iteration_range.h b/libartbase/base/iteration_range.h
index eaed8b0..c916250 100644
--- a/libartbase/base/iteration_range.h
+++ b/libartbase/base/iteration_range.h
@@ -18,6 +18,7 @@
 #define ART_LIBARTBASE_BASE_ITERATION_RANGE_H_
 
 #include <iterator>
+#include <type_traits>
 
 namespace art {
 
@@ -49,9 +50,11 @@
   return IterationRange<Iter>(begin_it, end_it);
 }
 
-template<typename List>
-inline IterationRange<typename List::iterator> MakeIterationRange(List& list) {
-  return IterationRange<typename List::iterator>(list.begin(), list.end());
+template <typename List>
+inline auto MakeIterationRange(List& list) -> IterationRange<decltype(list.begin())> {
+  static_assert(std::is_same_v<decltype(list.begin()), decltype(list.end())>,
+                "Different iterator types");
+  return MakeIterationRange(list.begin(), list.end());
 }
 
 template <typename Iter>
diff --git a/libartbase/base/logging_test.cc b/libartbase/base/logging_test.cc
index 46ba41b..540b9a7 100644
--- a/libartbase/base/logging_test.cc
+++ b/libartbase/base/logging_test.cc
@@ -39,10 +39,6 @@
   }
 };
 
-#ifdef NDEBUG
-#error Unexpected NDEBUG
-#endif
-
 class TestClass {
  public:
   DECLARE_RUNTIME_DEBUG_FLAG(kFlag);
@@ -51,7 +47,12 @@
 
 TEST_F(LoggingTest, DECL_DEF) {
   SetRuntimeDebugFlagsEnabled(true);
-  EXPECT_TRUE(TestClass::kFlag);
+  if (kIsDebugBuild) {
+    EXPECT_TRUE(TestClass::kFlag);
+  } else {
+    // Runtime debug flags have a constant `false` value on non-debug builds.
+    EXPECT_FALSE(TestClass::kFlag);
+  }
 
   SetRuntimeDebugFlagsEnabled(false);
   EXPECT_FALSE(TestClass::kFlag);
diff --git a/libartbase/base/macros.h b/libartbase/base/macros.h
index e6f72ff..eec73cb 100644
--- a/libartbase/base/macros.h
+++ b/libartbase/base/macros.h
@@ -104,4 +104,7 @@
 #define LOCKABLE CAPABILITY("mutex")
 #define SHARED_LOCKABLE SHARED_CAPABILITY("mutex")
 
+#define HIDDEN __attribute__((visibility("hidden")))
+#define EXPORT __attribute__((visibility("default")))
+
 #endif  // ART_LIBARTBASE_BASE_MACROS_H_
diff --git a/libartbase/base/mem_map.cc b/libartbase/base/mem_map.cc
index 03e8218..aa07f1c 100644
--- a/libartbase/base/mem_map.cc
+++ b/libartbase/base/mem_map.cc
@@ -389,7 +389,7 @@
                 reuse);
 }
 
-MemMap MemMap::MapDummy(const char* name, uint8_t* addr, size_t byte_count) {
+MemMap MemMap::MapPlaceholder(const char* name, uint8_t* addr, size_t byte_count) {
   if (byte_count == 0) {
     return Invalid();
   }
@@ -597,19 +597,21 @@
 
 void MemMap::DoReset() {
   DCHECK(IsValid());
-
+  size_t real_base_size = base_size_;
   // Unlike Valgrind, AddressSanitizer requires that all manually poisoned memory is unpoisoned
   // before it is returned to the system.
   if (redzone_size_ != 0) {
+    // Add redzone_size_ back to base_size or it will cause a mmap leakage.
+    real_base_size += redzone_size_;
     MEMORY_TOOL_MAKE_UNDEFINED(
-        reinterpret_cast<char*>(base_begin_) + base_size_ - redzone_size_,
+        reinterpret_cast<char*>(base_begin_) + real_base_size - redzone_size_,
         redzone_size_);
   }
 
   if (!reuse_) {
     MEMORY_TOOL_MAKE_UNDEFINED(base_begin_, base_size_);
     if (!already_unmapped_) {
-      int result = TargetMUnmap(base_begin_, base_size_);
+      int result = TargetMUnmap(base_begin_, real_base_size);
       if (result == -1) {
         PLOG(FATAL) << "munmap failed";
       }
diff --git a/libartbase/base/mem_map.h b/libartbase/base/mem_map.h
index 4b6257b..4c41388 100644
--- a/libartbase/base/mem_map.h
+++ b/libartbase/base/mem_map.h
@@ -171,7 +171,7 @@
   // This is useful when we do not have control over the code calling mmap,
   // but when we still want to keep track of it in the list.
   // The region is not considered to be owned and will not be unmmaped.
-  static MemMap MapDummy(const char* name, uint8_t* addr, size_t byte_count);
+  static MemMap MapPlaceholder(const char* name, uint8_t* addr, size_t byte_count);
 
   // Map part of a file, taking care of non-page aligned offsets.  The
   // "start" offset is absolute, not relative.
diff --git a/libartbase/base/metrics/README.md b/libartbase/base/metrics/README.md
new file mode 100644
index 0000000..ade5852
--- /dev/null
+++ b/libartbase/base/metrics/README.md
@@ -0,0 +1,52 @@
+# ART Metrics
+
+This directory contains most of ART's metrics framework. Some portions that
+rely on the runtime can be found in the `runtime/metrics` directory.
+
+## Declaring Metrics
+
+ART's internal metrics are listed in the `ART_METRICS` macro in `metrics.h`.
+Each metric has a `METRIC` entry which takes a name for the metric, a type
+ (such as counter or histogram), and any additional arguments that are needed.
+
+### Counters
+
+    METRIC(MyCounter, MetricsCounter)
+
+Counters store a single value that can be added to. This is useful for counting
+events, counting the total amount of time spent in a section of code, and other
+uses.
+
+### Accumulators
+
+    METRIC(MyAccumulator, MetricsAccumulator, type, accumulator_function)
+
+Example:
+
+    METRIC(MaximumTestMetric, MetricsAccumulator, int64_t, std::max<int64_t>)
+
+Accumulators are a generalization of counters that takes an accumulator
+function that is used to combine the new value with the old value. Common
+choices are the min and max function. To be valid, the accumulator function
+must be monotonic in its first argument. That is, if
+`x_new == accumulator_function(x_old, y)` then `x_new ⪯ x_old` for some
+ordering relation `⪯` (e.g. less-than-or-equal or greater-than-or-equal).
+
+### Histograms
+
+    METRIC(MyHistogram, MetricsHistogram, num_buckets, minimum_value, maximum_value)
+
+Histograms divide a range into several buckets and count how many times a value
+falls within each bucket. They are useful for seeing the overall distribution
+for different events.
+
+The `num_buckets` parameter affects memory usage for the histogram and data
+usage for exported metrics. It is recommended to keep this below 16. The
+`minimum_value` and `maximum_value` parameters are needed because we need to
+know what range the fixed number of buckets cover. We could keep track of the
+observed ranges and try to rescale the buckets or allocate new buckets, but
+this would make incrementing them more expensive than just some index
+arithmetic and an add. Values outside the range get clamped to the nearest
+bucket (basically, the two buckets on either side are infinitely long). If we
+see those buckets being way taller than the others, it means we should consider
+expanding the range.
diff --git a/libartbase/base/metrics/metrics.h b/libartbase/base/metrics/metrics.h
new file mode 100644
index 0000000..17fb0d8
--- /dev/null
+++ b/libartbase/base/metrics/metrics.h
@@ -0,0 +1,602 @@
+/*
+ * Copyright (C) 2020 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_LIBARTBASE_BASE_METRICS_METRICS_H_
+#define ART_LIBARTBASE_BASE_METRICS_METRICS_H_
+
+#include <stdint.h>
+
+#include <array>
+#include <atomic>
+#include <optional>
+#include <sstream>
+#include <string_view>
+#include <thread>
+#include <vector>
+
+#include "android-base/logging.h"
+#include "base/bit_utils.h"
+#include "base/time_utils.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+// See README.md in this directory for how to define metrics.
+#define ART_METRICS(METRIC)                                             \
+  METRIC(ClassLoadingTotalTime, MetricsCounter)                         \
+  METRIC(ClassVerificationTotalTime, MetricsCounter)                    \
+  METRIC(ClassVerificationCount, MetricsCounter)                        \
+  METRIC(WorldStopTimeDuringGCAvg, MetricsAverage)                      \
+  METRIC(YoungGcCount, MetricsCounter)                                  \
+  METRIC(FullGcCount, MetricsCounter)                                   \
+  METRIC(TotalBytesAllocated, MetricsCounter)                           \
+  METRIC(TotalGcCollectionTime, MetricsCounter)                         \
+  METRIC(YoungGcThroughputAvg, MetricsAverage)                          \
+  METRIC(FullGcThroughputAvg, MetricsAverage)                           \
+  METRIC(YoungGcTracingThroughputAvg, MetricsAverage)                   \
+  METRIC(FullGcTracingThroughputAvg, MetricsAverage)                    \
+  METRIC(JitMethodCompileTotalTime, MetricsCounter)                     \
+  METRIC(JitMethodCompileCount, MetricsCounter)                         \
+  METRIC(YoungGcCollectionTime, MetricsHistogram, 15, 0, 60'000)        \
+  METRIC(FullGcCollectionTime, MetricsHistogram, 15, 0, 60'000)         \
+  METRIC(YoungGcThroughput, MetricsHistogram, 15, 0, 10'000)            \
+  METRIC(FullGcThroughput, MetricsHistogram, 15, 0, 10'000)             \
+  METRIC(YoungGcTracingThroughput, MetricsHistogram, 15, 0, 10'000)     \
+  METRIC(FullGcTracingThroughput, MetricsHistogram, 15, 0, 10'000)
+
+// A lot of the metrics implementation code is generated by passing one-off macros into ART_COUNTERS
+// and ART_HISTOGRAMS. This means metrics.h and metrics.cc are very #define-heavy, which can be
+// challenging to read. The alternative was to require a lot of boilerplate code for each new metric
+// added, all of which would need to be rewritten if the metrics implementation changed. Using
+// macros lets us add new metrics by adding a single line to either ART_COUNTERS or ART_HISTOGRAMS,
+// and modifying the implementation only requires changing the implementation once, instead of once
+// per metric.
+
+namespace art {
+
+class Runtime;
+struct RuntimeArgumentMap;
+
+namespace metrics {
+
+/**
+ * An enumeration of all ART counters and histograms.
+ */
+enum class DatumId {
+#define METRIC(name, type, ...) k##name,
+  ART_METRICS(METRIC)
+#undef METRIC
+};
+
+// Names come from PackageManagerServiceCompilerMapping.java
+#define REASON_NAME_LIST(V) \
+  V(kError, "error") \
+  V(kUnknown, "unknown") \
+  V(kFirstBoot, "first-boot") \
+  V(kBootAfterOTA, "boot-after-ota") \
+  V(kPostBoot, "post-boot") \
+  V(kInstall, "install") \
+  V(kInstallFast, "install-fast") \
+  V(kInstallBulk, "install-bulk") \
+  V(kInstallBulkSecondary, "install-bulk-secondary") \
+  V(kInstallBulkDowngraded, "install-bulk-downgraded") \
+  V(kInstallBulkSecondaryDowngraded, "install-bulk-secondary-downgraded") \
+  V(kBgDexopt, "bg-dexopt") \
+  V(kABOTA, "ab-ota") \
+  V(kInactive, "inactive") \
+  V(kShared, "shared") \
+  V(kInstallWithDexMetadata, "install-with-dex-metadata") \
+  V(kPrebuilt, "prebuilt") \
+  V(kCmdLine, "cmdline")
+
+// We log compilation reasons as part of the metadata we report. Since elsewhere compilation reasons
+// are specified as a string, we define them as an enum here which indicates the reasons that we
+// support.
+enum class CompilationReason {
+#define REASON(kind, name) kind,
+  REASON_NAME_LIST(REASON)
+#undef REASON
+};
+
+#define REASON_NAME(kind, kind_name) \
+    case CompilationReason::kind: return kind_name;
+#define REASON_FROM_NAME(kind, kind_name) \
+    if (name == kind_name) { return CompilationReason::kind; }
+
+constexpr const char* CompilationReasonName(CompilationReason reason) {
+  switch (reason) {
+    REASON_NAME_LIST(REASON_NAME)
+  }
+}
+
+constexpr CompilationReason CompilationReasonFromName(std::string_view name) {
+  REASON_NAME_LIST(REASON_FROM_NAME)
+  return CompilationReason::kError;
+}
+
+#undef REASON_NAME
+#undef ReasonFromName
+
+#define COMPILER_FILTER_REPORTING_LIST(V) \
+  V(kError, "error") /* Error (invalid value) condition */ \
+  V(kUnknown, "unknown") /* Unknown (not set) condition */ \
+  V(kAssumeVerified, "assume-verified") /* Standard compiler filters */ \
+  V(kExtract, "extract") \
+  V(kVerify, "verify") \
+  V(kSpaceProfile, "space-profile") \
+  V(kSpace, "space") \
+  V(kSpeedProfile, "speed-profile") \
+  V(kSpeed, "speed") \
+  V(kEverythingProfile, "everything-profile") \
+  V(kEverything, "everything") \
+  V(kRunFromApk, "run-from-apk") /* Augmented compiler filters as produces by OatFileAssistant#GetOptimizationStatus */ \
+  V(kRunFromApkFallback, "run-from-apk-fallback")
+
+// Augmented compiler filter enum, used in the reporting infra.
+enum class CompilerFilterReporting {
+#define FILTER(kind, name) kind,
+  COMPILER_FILTER_REPORTING_LIST(FILTER)
+#undef FILTER
+};
+
+#define FILTER_NAME(kind, kind_name) \
+    case CompilerFilterReporting::kind: return kind_name;
+#define FILTER_FROM_NAME(kind, kind_name) \
+    if (name == kind_name) { return CompilerFilterReporting::kind; }
+
+constexpr const char* CompilerFilterReportingName(CompilerFilterReporting filter) {
+  switch (filter) {
+    COMPILER_FILTER_REPORTING_LIST(FILTER_NAME)
+  }
+}
+
+constexpr CompilerFilterReporting CompilerFilterReportingFromName(std::string_view name) {
+  COMPILER_FILTER_REPORTING_LIST(FILTER_FROM_NAME)
+  return CompilerFilterReporting::kError;
+}
+
+#undef FILTER_NAME
+#undef FILTER_FROM_NAME
+
+// SessionData contains metadata about a metrics session (basically the lifetime of an ART process).
+// This information should not change for the lifetime of the session.
+struct SessionData {
+  static SessionData CreateDefault();
+
+  static constexpr int64_t kInvalidSessionId = -1;
+  static constexpr int32_t kInvalidUserId = -1;
+
+  int64_t session_id;
+  int32_t uid;
+  CompilationReason compilation_reason;
+  CompilerFilterReporting compiler_filter;
+};
+
+// MetricsBackends are used by a metrics reporter to write metrics to some external location. For
+// example, a backend might write to logcat, or to a file, or to statsd.
+class MetricsBackend {
+ public:
+  virtual ~MetricsBackend() {}
+
+  // Begins an ART metrics session.
+  //
+  // This is called by the metrics reporter when the runtime is starting up. The session_data
+  // includes a session id which is used to correlate any metric reports with the same instance of
+  // the ART runtime. Additionally, session_data includes useful metadata such as the package name
+  // for this process.
+  //
+  // It may also be called whenever there is an update to the session metadata (e.g. optimization
+  // state).
+  virtual void BeginOrUpdateSession(const SessionData& session_data) = 0;
+
+ protected:
+  // Called by the metrics reporter to indicate that a new metrics report is starting.
+  virtual void BeginReport(uint64_t timestamp_since_start_ms) = 0;
+
+  // Called by the metrics reporter to give the current value of the counter with id counter_type.
+  //
+  // This will be called multiple times for each counter based on when the metrics reporter chooses
+  // to report metrics. For example, the metrics reporter may call this at shutdown or every N
+  // minutes. Counters are not reset in between invocations, so the value should represent the
+  // total count at the point this method is called.
+  virtual void ReportCounter(DatumId counter_type, uint64_t value) = 0;
+
+  // Called by the metrics reporter to report a histogram.
+  //
+  // This is called similarly to ReportCounter, but instead of receiving a single value, it receives
+  // a vector of the value in each bucket. Additionally, the function receives the lower and upper
+  // limit for the histogram. Note that these limits are the allowed limits, and not the observed
+  // range. Values below the lower limit will be counted in the first bucket, and values above the
+  // upper limit will be counted in the last bucket. Backends should store the minimum and maximum
+  // values to allow comparisons across module versions, since the minimum and maximum values may
+  // change over time.
+  virtual void ReportHistogram(DatumId histogram_type,
+                               int64_t minimum_value,
+                               int64_t maximum_value,
+                               const std::vector<uint32_t>& buckets) = 0;
+
+  // Called by the metrics reporter to indicate that the current metrics report is complete.
+  virtual void EndReport() = 0;
+
+  template <DatumId counter_type, typename T>
+  friend class MetricsCounter;
+  template <DatumId histogram_type, size_t num_buckets, int64_t low_value, int64_t high_value>
+  friend class MetricsHistogram;
+  template <DatumId datum_id, typename T, const T& AccumulatorFunction(const T&, const T&)>
+  friend class MetricsAccumulator;
+  template <DatumId datum_id, typename T>
+  friend class MetricsAverage;
+  friend class ArtMetrics;
+};
+
+template <typename value_t>
+class MetricsBase {
+ public:
+  virtual void Add(value_t value) = 0;
+  virtual ~MetricsBase() { }
+};
+
+template <DatumId counter_type, typename T = uint64_t>
+class MetricsCounter : public MetricsBase<T> {
+ public:
+  using value_t = T;
+  explicit constexpr MetricsCounter(uint64_t value = 0) : value_{value} {
+    // Ensure we do not have any unnecessary data in this class.
+    // Adding intptr_t to accommodate vtable, and rounding up to incorporate
+    // padding.
+    static_assert(RoundUp(sizeof(*this), sizeof(uint64_t))
+                  == RoundUp(sizeof(intptr_t) + sizeof(value_t), sizeof(uint64_t)));
+  }
+
+  void AddOne() { Add(1u); }
+  void Add(value_t value) { value_.fetch_add(value, std::memory_order::memory_order_relaxed); }
+
+  void Report(MetricsBackend* backend) const { backend->ReportCounter(counter_type, Value()); }
+
+ protected:
+  void Reset() {
+    value_ = 0;
+  }
+
+  value_t Value() const { return value_.load(std::memory_order::memory_order_relaxed); }
+
+ private:
+  std::atomic<value_t> value_;
+  static_assert(std::atomic<value_t>::is_always_lock_free);
+
+  friend class ArtMetrics;
+};
+
+template <DatumId datum_id, typename T = uint64_t>
+class MetricsAverage final : public MetricsCounter<datum_id, T> {
+ public:
+  using value_t = T;
+  using count_t = T;
+  explicit constexpr MetricsAverage(uint64_t value = 0, uint64_t count = 0) :
+      MetricsCounter<datum_id, value_t>(value), count_(count) {
+    // Ensure we do not have any unnecessary data in this class.
+    // Adding intptr_t to accommodate vtable, and rounding up to incorporate
+    // padding.
+    static_assert(RoundUp(sizeof(*this), sizeof(uint64_t))
+                  == RoundUp(sizeof(intptr_t) + sizeof(value_t) + sizeof(count_t),
+                             sizeof(uint64_t)));
+  }
+
+  // We use release memory-order here and then acquire in Report() to ensure
+  // that at least the non-racy reads/writes to this metric are consistent. This
+  // doesn't guarantee the atomicity of the change to both fields, but that
+  // may not be desired because:
+  // 1. The metric eventually becomes consistent.
+  // 2. For sufficiently large count_, a few data points which are off shouldn't
+  // make a huge difference to the reporter.
+  void Add(value_t value) {
+    MetricsCounter<datum_id, value_t>::Add(value);
+    count_.fetch_add(1, std::memory_order::memory_order_release);
+  }
+
+  void Report(MetricsBackend* backend) const {
+    count_t count = count_.load(std::memory_order::memory_order_acquire);
+    backend->ReportCounter(datum_id,
+                           // Avoid divide-by-0.
+                           count != 0 ? MetricsCounter<datum_id, value_t>::Value() / count : 0);
+  }
+
+ protected:
+  void Reset() {
+    count_ = 0;
+    MetricsCounter<datum_id, value_t>::Reset();
+  }
+
+ private:
+  std::atomic<count_t> count_;
+  static_assert(std::atomic<count_t>::is_always_lock_free);
+
+  friend class ArtMetrics;
+};
+
+template <DatumId histogram_type_,
+          size_t num_buckets_,
+          int64_t minimum_value_,
+          int64_t maximum_value_>
+class MetricsHistogram final : public MetricsBase<int64_t> {
+  static_assert(num_buckets_ >= 1);
+  static_assert(minimum_value_ < maximum_value_);
+
+ public:
+  using value_t = uint32_t;
+
+  constexpr MetricsHistogram() : buckets_{} {
+    // Ensure we do not have any unnecessary data in this class.
+    // Adding intptr_t to accommodate vtable, and rounding up to incorporate
+    // padding.
+    static_assert(RoundUp(sizeof(*this), sizeof(uint64_t))
+                  == RoundUp(sizeof(intptr_t) + sizeof(value_t) * num_buckets_, sizeof(uint64_t)));
+  }
+
+  void Add(int64_t value) {
+    const size_t i = FindBucketId(value);
+    buckets_[i].fetch_add(1u, std::memory_order::memory_order_relaxed);
+  }
+
+  void Report(MetricsBackend* backend) const {
+    backend->ReportHistogram(histogram_type_, minimum_value_, maximum_value_, GetBuckets());
+  }
+
+ protected:
+  void Reset() {
+    for (auto& bucket : buckets_) {
+      bucket = 0;
+    }
+  }
+
+ private:
+  inline constexpr size_t FindBucketId(int64_t value) const {
+    // Values below the minimum are clamped into the first bucket.
+    if (value <= minimum_value_) {
+      return 0;
+    }
+    // Values above the maximum are clamped into the last bucket.
+    if (value >= maximum_value_) {
+      return num_buckets_ - 1;
+    }
+    // Otherise, linearly interpolate the value into the right bucket
+    constexpr size_t bucket_width = maximum_value_ - minimum_value_;
+    return static_cast<size_t>(value - minimum_value_) * num_buckets_ / bucket_width;
+  }
+
+  std::vector<value_t> GetBuckets() const {
+    // The loads from buckets_ will all be memory_order_seq_cst, which means they will be acquire
+    // loads. This is a stricter memory order than is needed, but this should not be a
+    // performance-critical section of code.
+    return std::vector<value_t>{buckets_.begin(), buckets_.end()};
+  }
+
+  std::array<std::atomic<value_t>, num_buckets_> buckets_;
+  static_assert(std::atomic<value_t>::is_always_lock_free);
+
+  friend class ArtMetrics;
+};
+
+template <DatumId datum_id, typename T, const T& AccumulatorFunction(const T&, const T&)>
+class MetricsAccumulator final : MetricsBase<T> {
+ public:
+  explicit constexpr MetricsAccumulator(T value = 0) : value_{value} {
+    // Ensure we do not have any unnecessary data in this class.
+    // Adding intptr_t to accommodate vtable, and rounding up to incorporate
+    // padding.
+    static_assert(RoundUp(sizeof(*this), sizeof(uint64_t)) ==
+                  RoundUp(sizeof(intptr_t) + sizeof(T), sizeof(uint64_t)));
+  }
+
+  void Add(T value) {
+    T current = value_.load(std::memory_order::memory_order_relaxed);
+    T new_value;
+    do {
+      new_value = AccumulatorFunction(current, value);
+      // If the value didn't change, don't bother storing it.
+      if (current == new_value) {
+        break;
+      }
+    } while (!value_.compare_exchange_weak(
+        current, new_value, std::memory_order::memory_order_relaxed));
+  }
+
+  // Report the metric as a counter, since this has only a single value.
+  void Report(MetricsBackend* backend) const {
+    backend->ReportCounter(datum_id, static_cast<uint64_t>(Value()));
+  }
+
+ protected:
+  void Reset() {
+    value_ = 0;
+  }
+
+ private:
+  T Value() const { return value_.load(std::memory_order::memory_order_relaxed); }
+
+  std::atomic<T> value_;
+
+  friend class ArtMetrics;
+};
+
+// A backend that writes metrics in a human-readable format to a string.
+//
+// This is used as a base for LogBackend and FileBackend.
+class StringBackend : public MetricsBackend {
+ public:
+  StringBackend();
+
+  void BeginOrUpdateSession(const SessionData& session_data) override;
+
+  void BeginReport(uint64_t timestamp_millis) override;
+
+  void ReportCounter(DatumId counter_type, uint64_t value) override;
+
+  void ReportHistogram(DatumId histogram_type,
+                       int64_t low_value,
+                       int64_t high_value,
+                       const std::vector<uint32_t>& buckets) override;
+
+  void EndReport() override;
+
+  std::string GetAndResetBuffer();
+
+ private:
+  std::ostringstream os_;
+  std::optional<SessionData> session_data_;
+};
+
+// A backend that writes metrics in human-readable format to the log (i.e. logcat).
+class LogBackend : public StringBackend {
+ public:
+  explicit LogBackend(android::base::LogSeverity level);
+
+  void BeginReport(uint64_t timestamp_millis) override;
+  void EndReport() override;
+
+ private:
+  android::base::LogSeverity level_;
+};
+
+// A backend that writes metrics to a file.
+//
+// These are currently written in the same human-readable format used by StringBackend and
+// LogBackend, but we will probably want a more machine-readable format in the future.
+class FileBackend : public StringBackend {
+ public:
+  explicit FileBackend(const std::string& filename);
+
+  void BeginReport(uint64_t timestamp_millis) override;
+  void EndReport() override;
+
+ private:
+  std::string filename_;
+};
+
+/**
+ * AutoTimer simplifies time-based metrics collection.
+ *
+ * Several modes are supported. In the default case, the timer starts immediately and stops when it
+ * goes out of scope. Example:
+ *
+ *     {
+ *       AutoTimer timer{metric};
+ *       DoStuff();
+ *       // timer stops and updates metric automatically here.
+ *     }
+ *
+ * You can also stop the timer early:
+ *
+ *     timer.Stop();
+ *
+ * Finally, you can choose to not automatically start the timer at the beginning by passing false as
+ * the second argument to the constructor:
+ *
+ *     AutoTimer timer{metric, false};
+ *     DoNotTimeThis();
+ *     timer.Start();
+ *     TimeThis();
+ *
+ * Manually started timers will still automatically stop in the destructor, but they can be manually
+ * stopped as well.
+ *
+ * Note that AutoTimer makes calls to MicroTime(), so this may not be suitable on critical paths, or
+ * in cases where the counter needs to be started and stopped on different threads.
+ */
+template <typename Metric>
+class AutoTimer {
+ public:
+  explicit AutoTimer(Metric* metric, bool autostart = true)
+      : running_{false}, start_time_microseconds_{}, metric_{metric} {
+    if (autostart) {
+      Start();
+    }
+  }
+
+  ~AutoTimer() {
+    if (running_) {
+      Stop();
+    }
+  }
+
+  void Start() {
+    DCHECK(!running_);
+    running_ = true;
+    start_time_microseconds_ = MicroTime();
+  }
+
+  // Stops a running timer. Returns the time elapsed since starting the timer in microseconds.
+  uint64_t Stop() {
+    DCHECK(running_);
+    uint64_t stop_time_microseconds = MicroTime();
+    running_ = false;
+
+    uint64_t elapsed_time = stop_time_microseconds - start_time_microseconds_;
+    metric_->Add(static_cast<typename Metric::value_t>(elapsed_time));
+    return elapsed_time;
+  }
+
+ private:
+  bool running_;
+  uint64_t start_time_microseconds_;
+  Metric* metric_;
+};
+
+/**
+ * This struct contains all of the metrics that ART reports.
+ */
+class ArtMetrics {
+ public:
+  ArtMetrics();
+
+  void ReportAllMetrics(MetricsBackend* backend) const;
+  void DumpForSigQuit(std::ostream& os) const;
+
+  // Resets all metrics to their initial value. This is intended to be used after forking from the
+  // zygote so we don't attribute parent values to the child process.
+  void Reset();
+
+#define METRIC_ACCESSORS(name, Kind, ...)                                        \
+  Kind<DatumId::k##name, ##__VA_ARGS__>* name() { return &name##_; } \
+  const Kind<DatumId::k##name, ##__VA_ARGS__>* name() const { return &name##_; }
+  ART_METRICS(METRIC_ACCESSORS)
+#undef METRIC_ACCESSORS
+
+ private:
+  uint64_t beginning_timestamp_;
+
+#define METRIC(name, Kind, ...) Kind<DatumId::k##name, ##__VA_ARGS__> name##_;
+  ART_METRICS(METRIC)
+#undef METRIC
+};
+
+// Returns a human readable name for the given DatumId.
+std::string DatumName(DatumId datum);
+
+// We also log the thread type for metrics so we can distinguish things that block the UI thread
+// from things that happen on the background thread. This enum keeps track of what thread types we
+// support.
+enum class ThreadType {
+  kMain,
+  kBackground,
+};
+
+}  // namespace metrics
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
+
+#endif  // ART_LIBARTBASE_BASE_METRICS_METRICS_H_
diff --git a/libartbase/base/metrics/metrics_common.cc b/libartbase/base/metrics/metrics_common.cc
new file mode 100644
index 0000000..f09987b
--- /dev/null
+++ b/libartbase/base/metrics/metrics_common.cc
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2020 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 <sstream>
+
+#include "android-base/file.h"
+#include "android-base/logging.h"
+#include "base/macros.h"
+#include "base/scoped_flock.h"
+#include "metrics.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+namespace art {
+namespace metrics {
+
+std::string DatumName(DatumId datum) {
+  switch (datum) {
+#define ART_METRIC(name, Kind, ...) \
+  case DatumId::k##name:  \
+    return #name;
+    ART_METRICS(ART_METRIC)
+#undef ART_METRIC
+
+    default:
+      LOG(FATAL) << "Unknown datum id: " << static_cast<unsigned>(datum);
+      UNREACHABLE();
+  }
+}
+
+SessionData SessionData::CreateDefault() {
+#ifdef _WIN32
+  int32_t uid = kInvalidUserId;  // Windows does not support getuid();
+#else
+  int32_t uid = static_cast<int32_t>(getuid());
+#endif
+
+  return SessionData{
+    .compilation_reason = CompilationReason::kUnknown,
+    .compiler_filter = CompilerFilterReporting::kUnknown,
+    .session_id = kInvalidSessionId,
+    .uid = uid,
+  };
+}
+
+ArtMetrics::ArtMetrics() : beginning_timestamp_ {MilliTime()}
+#define ART_METRIC(name, Kind, ...) \
+  , name##_ {}
+ART_METRICS(ART_METRIC)
+#undef ART_METRIC
+{
+}
+
+void ArtMetrics::ReportAllMetrics(MetricsBackend* backend) const {
+  backend->BeginReport(MilliTime() - beginning_timestamp_);
+
+#define ART_METRIC(name, Kind, ...) name()->Report(backend);
+  ART_METRICS(ART_METRIC)
+#undef ART_METRIC
+
+  backend->EndReport();
+}
+
+void ArtMetrics::DumpForSigQuit(std::ostream& os) const {
+  StringBackend backend;
+  ReportAllMetrics(&backend);
+  os << backend.GetAndResetBuffer();
+}
+
+void ArtMetrics::Reset() {
+  beginning_timestamp_ = MilliTime();
+#define ART_METRIC(name, kind, ...) name##_.Reset();
+  ART_METRICS(ART_METRIC);
+#undef ART_METRIC
+}
+
+StringBackend::StringBackend() {}
+
+std::string StringBackend::GetAndResetBuffer() {
+  std::string result = os_.str();
+  os_.clear();
+  os_.str("");
+  return result;
+}
+
+void StringBackend::BeginOrUpdateSession(const SessionData& session_data) {
+  session_data_ = session_data;
+}
+
+void StringBackend::BeginReport(uint64_t timestamp_since_start_ms) {
+  os_ << "\n*** ART internal metrics ***\n";
+  os_ << "  Metadata:\n";
+  os_ << "    timestamp_since_start_ms: " << timestamp_since_start_ms << "\n";
+  if (session_data_.has_value()) {
+    os_ << "    session_id: " << session_data_->session_id << "\n";
+    os_ << "    uid: " << session_data_->uid << "\n";
+    os_ << "    compilation_reason: " << CompilationReasonName(session_data_->compilation_reason)
+        << "\n";
+    os_ << "    compiler_filter: " << CompilerFilterReportingName(session_data_->compiler_filter)
+        << "\n";
+  }
+  os_ << "  Metrics:\n";
+}
+
+void StringBackend::EndReport() { os_ << "*** Done dumping ART internal metrics ***\n"; }
+
+void StringBackend::ReportCounter(DatumId counter_type, uint64_t value) {
+  os_ << "    " << DatumName(counter_type) << ": count = " << value << "\n";
+}
+
+void StringBackend::ReportHistogram(DatumId histogram_type,
+                                    int64_t minimum_value_,
+                                    int64_t maximum_value_,
+                                    const std::vector<uint32_t>& buckets) {
+  os_ << "    " << DatumName(histogram_type) << ": range = " << minimum_value_ << "..." << maximum_value_;
+  if (buckets.size() > 0) {
+    os_ << ", buckets: ";
+    bool first = true;
+    for (const auto& count : buckets) {
+      if (!first) {
+        os_ << ",";
+      }
+      first = false;
+      os_ << count;
+    }
+    os_ << "\n";
+  } else {
+    os_ << ", no buckets\n";
+  }
+}
+
+LogBackend::LogBackend(android::base::LogSeverity level) : level_{level} {}
+
+void LogBackend::BeginReport(uint64_t timestamp_since_start_ms) {
+  GetAndResetBuffer();
+  StringBackend::BeginReport(timestamp_since_start_ms);
+}
+
+void LogBackend::EndReport() {
+  StringBackend::EndReport();
+  LOG_STREAM(level_) << GetAndResetBuffer();
+}
+
+FileBackend::FileBackend(const std::string& filename) : filename_{filename} {}
+
+void FileBackend::BeginReport(uint64_t timestamp_since_start_ms) {
+  GetAndResetBuffer();
+  StringBackend::BeginReport(timestamp_since_start_ms);
+}
+
+void FileBackend::EndReport() {
+  StringBackend::EndReport();
+  std::string error_message;
+  auto file{
+      LockedFile::Open(filename_.c_str(), O_CREAT | O_WRONLY | O_APPEND, true, &error_message)};
+  if (file.get() == nullptr) {
+    LOG(WARNING) << "Could open metrics file '" << filename_ << "': " << error_message;
+  } else {
+    if (!android::base::WriteStringToFd(GetAndResetBuffer(), file.get()->Fd())) {
+      PLOG(WARNING) << "Error writing metrics to file";
+    }
+  }
+}
+
+// Make sure CompilationReasonName and CompilationReasonForName are inverses.
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kError)) ==
+              CompilationReason::kError);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kUnknown)) ==
+              CompilationReason::kUnknown);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kFirstBoot)) ==
+              CompilationReason::kFirstBoot);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kBootAfterOTA)) ==
+              CompilationReason::kBootAfterOTA);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kPostBoot)) ==
+              CompilationReason::kPostBoot);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstall)) ==
+              CompilationReason::kInstall);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstallFast)) ==
+              CompilationReason::kInstallFast);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstallBulk)) ==
+              CompilationReason::kInstallBulk);
+static_assert(
+    CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstallBulkSecondary)) ==
+    CompilationReason::kInstallBulkSecondary);
+static_assert(
+    CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstallBulkDowngraded)) ==
+    CompilationReason::kInstallBulkDowngraded);
+static_assert(CompilationReasonFromName(
+                  CompilationReasonName(CompilationReason::kInstallBulkSecondaryDowngraded)) ==
+              CompilationReason::kInstallBulkSecondaryDowngraded);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kBgDexopt)) ==
+              CompilationReason::kBgDexopt);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kABOTA)) ==
+              CompilationReason::kABOTA);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kInactive)) ==
+              CompilationReason::kInactive);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kShared)) ==
+              CompilationReason::kShared);
+static_assert(
+    CompilationReasonFromName(CompilationReasonName(CompilationReason::kInstallWithDexMetadata)) ==
+    CompilationReason::kInstallWithDexMetadata);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kPrebuilt)) ==
+              CompilationReason::kPrebuilt);
+static_assert(CompilationReasonFromName(CompilationReasonName(CompilationReason::kCmdLine)) ==
+              CompilationReason::kCmdLine);
+
+}  // namespace metrics
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
diff --git a/libartbase/base/metrics/metrics_test.cc b/libartbase/base/metrics/metrics_test.cc
new file mode 100644
index 0000000..ed6f88d
--- /dev/null
+++ b/libartbase/base/metrics/metrics_test.cc
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2020 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 "metrics.h"
+
+#include "gtest/gtest.h"
+#include "metrics_test.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+namespace art {
+namespace metrics {
+
+using test::CounterValue;
+using test::GetBuckets;
+using test::TestBackendBase;
+
+class MetricsTest : public testing::Test {};
+
+TEST_F(MetricsTest, SimpleCounter) {
+  MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter;
+
+  EXPECT_EQ(0u, CounterValue(test_counter));
+
+  test_counter.AddOne();
+  EXPECT_EQ(1u, CounterValue(test_counter));
+
+  test_counter.Add(5);
+  EXPECT_EQ(6u, CounterValue(test_counter));
+}
+
+TEST_F(MetricsTest, CounterTimer) {
+  MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter;
+  {
+    AutoTimer timer{&test_counter};
+    // Sleep for 2µs so the counter will be greater than 0.
+    NanoSleep(2'000);
+  }
+  EXPECT_GT(CounterValue(test_counter), 0u);
+}
+
+TEST_F(MetricsTest, CounterTimerExplicitStop) {
+  MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter;
+  AutoTimer timer{&test_counter};
+  // Sleep for 2µs so the counter will be greater than 0.
+  NanoSleep(2'000);
+  timer.Stop();
+  EXPECT_GT(CounterValue(test_counter), 0u);
+}
+
+TEST_F(MetricsTest, CounterTimerExplicitStart) {
+  MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter;
+  {
+    AutoTimer timer{&test_counter, /*autostart=*/false};
+    // Sleep for 2µs so the counter will be greater than 0.
+    NanoSleep(2'000);
+  }
+  EXPECT_EQ(CounterValue(test_counter), 0u);
+
+  {
+    AutoTimer timer{&test_counter, /*autostart=*/false};
+    timer.Start();
+    // Sleep for 2µs so the counter will be greater than 0.
+    NanoSleep(2'000);
+  }
+  EXPECT_GT(CounterValue(test_counter), 0u);
+}
+
+TEST_F(MetricsTest, CounterTimerExplicitStartStop) {
+  MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter;
+  AutoTimer timer{&test_counter, /*autostart=*/false};
+  // Sleep for 2µs so the counter will be greater than 0.
+  timer.Start();
+  NanoSleep(2'000);
+  timer.Stop();
+  EXPECT_GT(CounterValue(test_counter), 0u);
+}
+
+TEST_F(MetricsTest, AccumulatorMetric) {
+  MetricsAccumulator<DatumId::kClassLoadingTotalTime, uint64_t, std::max> accumulator;
+
+  std::vector<std::thread> threads;
+
+  constexpr uint64_t kMaxValue = 100;
+
+  for (uint64_t i = 0; i <= kMaxValue; i++) {
+    threads.emplace_back(std::thread{[&accumulator, i]() {
+      accumulator.Add(i);
+    }});
+  }
+
+  for (auto& thread : threads) {
+    thread.join();
+  }
+
+  EXPECT_EQ(CounterValue(accumulator), kMaxValue);
+}
+
+TEST_F(MetricsTest, AverageMetric) {
+  MetricsAverage<DatumId::kClassLoadingTotalTime, uint64_t> avg;
+
+  std::vector<std::thread> threads;
+
+  constexpr uint64_t kMaxValue = 100;
+
+  for (uint64_t i = 0; i <= kMaxValue; i++) {
+    threads.emplace_back(std::thread{[&avg, i]() {
+      avg.Add(i);
+    }});
+  }
+
+  for (auto& thread : threads) {
+    thread.join();
+  }
+
+  EXPECT_EQ(CounterValue(avg), (kMaxValue + 1) / 2);
+}
+
+TEST_F(MetricsTest, DatumName) {
+  EXPECT_EQ("ClassVerificationTotalTime", DatumName(DatumId::kClassVerificationTotalTime));
+}
+
+TEST_F(MetricsTest, SimpleHistogramTest) {
+  MetricsHistogram<DatumId::kYoungGcCollectionTime, 5, 0, 100> histogram;
+
+  // bucket 0: 0-19
+  histogram.Add(10);
+
+  // bucket 1: 20-39
+  histogram.Add(20);
+  histogram.Add(25);
+
+  // bucket 2: 40-59
+  histogram.Add(56);
+  histogram.Add(57);
+  histogram.Add(58);
+  histogram.Add(59);
+
+  // bucket 3: 60-79
+  histogram.Add(70);
+  histogram.Add(70);
+  histogram.Add(70);
+
+  // bucket 4: 80-99
+  // leave this bucket empty
+
+  std::vector<uint32_t> buckets{GetBuckets(histogram)};
+  EXPECT_EQ(1u, buckets[0u]);
+  EXPECT_EQ(2u, buckets[1u]);
+  EXPECT_EQ(4u, buckets[2u]);
+  EXPECT_EQ(3u, buckets[3u]);
+  EXPECT_EQ(0u, buckets[4u]);
+}
+
+// Make sure values added outside the range of the histogram go into the first or last bucket.
+TEST_F(MetricsTest, HistogramOutOfRangeTest) {
+  MetricsHistogram<DatumId::kYoungGcCollectionTime, 2, 0, 100> histogram;
+
+  // bucket 0: 0-49
+  histogram.Add(-500);
+
+  // bucket 1: 50-99
+  histogram.Add(250);
+  histogram.Add(1000);
+
+  std::vector<uint32_t> buckets{GetBuckets(histogram)};
+  EXPECT_EQ(1u, buckets[0u]);
+  EXPECT_EQ(2u, buckets[1u]);
+}
+
+// Test adding values to ArtMetrics and reporting them through a test backend.
+TEST_F(MetricsTest, ArtMetricsReport) {
+  ArtMetrics metrics;
+
+  // Collect some data
+  static constexpr uint64_t verification_time = 42;
+  metrics.ClassVerificationTotalTime()->Add(verification_time);
+  // Add a negative value so we are guaranteed that it lands in the first bucket.
+  metrics.YoungGcCollectionTime()->Add(-5);
+
+  // Report and check the data
+  class TestBackend : public TestBackendBase {
+   public:
+    ~TestBackend() {
+      EXPECT_TRUE(found_counter_);
+      EXPECT_TRUE(found_histogram_);
+    }
+
+    void ReportCounter(DatumId counter_type, uint64_t value) override {
+      if (counter_type == DatumId::kClassVerificationTotalTime) {
+        EXPECT_EQ(value, verification_time);
+        found_counter_ = true;
+      } else {
+        EXPECT_EQ(value, 0u);
+      }
+    }
+
+    void ReportHistogram(DatumId histogram_type,
+                         int64_t,
+                         int64_t,
+                         const std::vector<uint32_t>& buckets) override {
+      if (histogram_type == DatumId::kYoungGcCollectionTime) {
+        EXPECT_EQ(buckets[0], 1u);
+        for (size_t i = 1; i < buckets.size(); ++i) {
+          EXPECT_EQ(buckets[i], 0u);
+        }
+        found_histogram_ = true;
+      } else {
+        for (size_t i = 0; i < buckets.size(); ++i) {
+          EXPECT_EQ(buckets[i], 0u);
+        }
+      }
+    }
+
+   private:
+    bool found_counter_{false};
+    bool found_histogram_{false};
+  } backend;
+
+  metrics.ReportAllMetrics(&backend);
+}
+
+TEST_F(MetricsTest, HistogramTimer) {
+  MetricsHistogram<DatumId::kYoungGcCollectionTime, 1, 0, 100> test_histogram;
+  {
+    AutoTimer timer{&test_histogram};
+    // Sleep for 2µs so the counter will be greater than 0.
+    NanoSleep(2'000);
+  }
+
+  EXPECT_GT(GetBuckets(test_histogram)[0], 0u);
+}
+
+// Makes sure all defined metrics are included when dumping through StreamBackend.
+TEST_F(MetricsTest, StreamBackendDumpAllMetrics) {
+  ArtMetrics metrics;
+  StringBackend backend;
+
+  metrics.ReportAllMetrics(&backend);
+
+  // Make sure the resulting string lists all the metrics.
+  const std::string result = backend.GetAndResetBuffer();
+#define METRIC(name, type, ...) \
+  EXPECT_NE(result.find(DatumName(DatumId::k##name)), std::string::npos);
+  ART_METRICS(METRIC);
+#undef METRIC
+}
+
+TEST_F(MetricsTest, ResetMetrics) {
+  ArtMetrics metrics;
+
+  // Add something to each of the metrics.
+#define METRIC(name, type, ...) metrics.name()->Add(42);
+  ART_METRICS(METRIC)
+#undef METRIC
+
+  class NonZeroBackend : public TestBackendBase {
+   public:
+    void ReportCounter(DatumId, uint64_t value) override {
+      EXPECT_NE(value, 0u);
+    }
+
+    void ReportHistogram(DatumId, int64_t, int64_t, const std::vector<uint32_t>& buckets) override {
+      bool nonzero = false;
+      for (const auto value : buckets) {
+        nonzero |= (value != 0u);
+      }
+      EXPECT_TRUE(nonzero);
+    }
+  } non_zero_backend;
+
+  // Make sure the metrics all have a nonzero value.
+  metrics.ReportAllMetrics(&non_zero_backend);
+
+  // Reset the metrics and make sure they are all zero again
+  metrics.Reset();
+
+  class ZeroBackend : public TestBackendBase {
+   public:
+    void ReportCounter(DatumId, uint64_t value) override {
+      EXPECT_EQ(value, 0u);
+    }
+
+    void ReportHistogram(DatumId, int64_t, int64_t, const std::vector<uint32_t>& buckets) override {
+      for (const auto value : buckets) {
+        EXPECT_EQ(value, 0u);
+      }
+    }
+  } zero_backend;
+
+  metrics.ReportAllMetrics(&zero_backend);
+}
+
+TEST(CompilerFilterReportingTest, FromName) {
+  ASSERT_EQ(CompilerFilterReportingFromName("error"),
+            CompilerFilterReporting::kError);
+  ASSERT_EQ(CompilerFilterReportingFromName("unknown"),
+            CompilerFilterReporting::kUnknown);
+  ASSERT_EQ(CompilerFilterReportingFromName("assume-verified"),
+            CompilerFilterReporting::kAssumeVerified);
+  ASSERT_EQ(CompilerFilterReportingFromName("extract"),
+            CompilerFilterReporting::kExtract);
+  ASSERT_EQ(CompilerFilterReportingFromName("verify"),
+            CompilerFilterReporting::kVerify);
+  ASSERT_EQ(CompilerFilterReportingFromName("space-profile"),
+            CompilerFilterReporting::kSpaceProfile);
+  ASSERT_EQ(CompilerFilterReportingFromName("space"),
+            CompilerFilterReporting::kSpace);
+  ASSERT_EQ(CompilerFilterReportingFromName("speed-profile"),
+            CompilerFilterReporting::kSpeedProfile);
+  ASSERT_EQ(CompilerFilterReportingFromName("speed"),
+            CompilerFilterReporting::kSpeed);
+  ASSERT_EQ(CompilerFilterReportingFromName("everything-profile"),
+            CompilerFilterReporting::kEverythingProfile);
+  ASSERT_EQ(CompilerFilterReportingFromName("everything"),
+            CompilerFilterReporting::kEverything);
+  ASSERT_EQ(CompilerFilterReportingFromName("run-from-apk"),
+            CompilerFilterReporting::kRunFromApk);
+  ASSERT_EQ(CompilerFilterReportingFromName("run-from-apk-fallback"),
+            CompilerFilterReporting::kRunFromApkFallback);
+}
+
+TEST(CompilerFilterReportingTest, Name) {
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kError),
+            "error");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kUnknown),
+            "unknown");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kAssumeVerified),
+            "assume-verified");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kExtract),
+            "extract");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kVerify),
+            "verify");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpaceProfile),
+            "space-profile");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpace),
+            "space");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpeedProfile),
+            "speed-profile");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpeed),
+            "speed");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kEverythingProfile),
+            "everything-profile");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kEverything),
+            "everything");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kRunFromApk),
+            "run-from-apk");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kRunFromApkFallback),
+            "run-from-apk-fallback");
+}
+
+TEST(CompilerReason, FromName) {
+  ASSERT_EQ(CompilationReasonFromName("unknown"),
+            CompilationReason::kUnknown);
+  ASSERT_EQ(CompilationReasonFromName("first-boot"),
+            CompilationReason::kFirstBoot);
+  ASSERT_EQ(CompilationReasonFromName("boot-after-ota"),
+            CompilationReason::kBootAfterOTA);
+  ASSERT_EQ(CompilationReasonFromName("post-boot"),
+            CompilationReason::kPostBoot);
+  ASSERT_EQ(CompilationReasonFromName("install"),
+            CompilationReason::kInstall);
+  ASSERT_EQ(CompilationReasonFromName("install-fast"),
+            CompilationReason::kInstallFast);
+  ASSERT_EQ(CompilationReasonFromName("install-bulk"),
+            CompilationReason::kInstallBulk);
+  ASSERT_EQ(CompilationReasonFromName("install-bulk-secondary"),
+            CompilationReason::kInstallBulkSecondary);
+  ASSERT_EQ(CompilationReasonFromName("install-bulk-downgraded"),
+            CompilationReason::kInstallBulkDowngraded);
+  ASSERT_EQ(CompilationReasonFromName("install-bulk-secondary-downgraded"),
+            CompilationReason::kInstallBulkSecondaryDowngraded);
+  ASSERT_EQ(CompilationReasonFromName("bg-dexopt"),
+            CompilationReason::kBgDexopt);
+  ASSERT_EQ(CompilationReasonFromName("ab-ota"),
+            CompilationReason::kABOTA);
+  ASSERT_EQ(CompilationReasonFromName("inactive"),
+            CompilationReason::kInactive);
+  ASSERT_EQ(CompilationReasonFromName("shared"),
+            CompilationReason::kShared);
+  ASSERT_EQ(CompilationReasonFromName("install-with-dex-metadata"),
+            CompilationReason::kInstallWithDexMetadata);
+  ASSERT_EQ(CompilationReasonFromName("prebuilt"),
+            CompilationReason::kPrebuilt);
+  ASSERT_EQ(CompilationReasonFromName("cmdline"),
+            CompilationReason::kCmdLine);
+  ASSERT_EQ(CompilationReasonFromName("error"),
+            CompilationReason::kError);
+}
+
+TEST(CompilerReason, Name) {
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kUnknown),
+            "unknown");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kFirstBoot),
+            "first-boot");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kBootAfterOTA),
+            "boot-after-ota");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kPostBoot),
+            "post-boot");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstall),
+            "install");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallFast),
+            "install-fast");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulk),
+            "install-bulk");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkSecondary),
+            "install-bulk-secondary");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkDowngraded),
+            "install-bulk-downgraded");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkSecondaryDowngraded),
+            "install-bulk-secondary-downgraded");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kBgDexopt),
+            "bg-dexopt");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kABOTA),
+            "ab-ota");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInactive),
+            "inactive");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kShared),
+            "shared");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallWithDexMetadata),
+            "install-with-dex-metadata");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kPrebuilt),
+            "prebuilt");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kCmdLine),
+            "cmdline");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kError),
+            "error");
+}
+}  // namespace metrics
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
diff --git a/libartbase/base/metrics/metrics_test.h b/libartbase/base/metrics/metrics_test.h
new file mode 100644
index 0000000..3e8b42a
--- /dev/null
+++ b/libartbase/base/metrics/metrics_test.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 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_LIBARTBASE_BASE_METRICS_METRICS_TEST_H_
+#define ART_LIBARTBASE_BASE_METRICS_METRICS_TEST_H_
+
+#include "metrics.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+namespace art {
+namespace metrics {
+namespace test {
+
+// This namespace contains functions that are helpful for testing metrics but should not be used in
+// production code.
+
+// A trivial MetricsBackend that does nothing for all of the members. This can be overridden by
+// test cases to test specific behaviors.
+class TestBackendBase : public MetricsBackend {
+ public:
+  void BeginOrUpdateSession([[maybe_unused]] const SessionData& session_data) override {}
+
+  void BeginReport([[maybe_unused]] uint64_t timestamp_since_start_ms) override {}
+
+  void ReportCounter([[maybe_unused]] DatumId counter_type,
+                     [[maybe_unused]] uint64_t value) override {}
+
+  void ReportHistogram([[maybe_unused]] DatumId histogram_type,
+                       [[maybe_unused]] int64_t low_value_,
+                       [[maybe_unused]] int64_t high_value,
+                       [[maybe_unused]] const std::vector<uint32_t>& buckets) override {}
+
+  void EndReport() override {}
+};
+
+template <typename MetricType>
+uint64_t CounterValue(const MetricType& counter) {
+  uint64_t counter_value{0};
+  struct CounterBackend : public TestBackendBase {
+    explicit CounterBackend(uint64_t* counter_value) : counter_value_{counter_value} {}
+
+    void ReportCounter(DatumId, uint64_t value) override { *counter_value_ = value; }
+
+    uint64_t* counter_value_;
+  } backend{&counter_value};
+  counter.Report(&backend);
+  return counter_value;
+}
+
+template <DatumId histogram_type, size_t num_buckets, int64_t low_value, int64_t high_value>
+std::vector<uint32_t> GetBuckets(
+    const MetricsHistogram<histogram_type, num_buckets, low_value, high_value>& histogram) {
+  std::vector<uint32_t> buckets;
+  struct HistogramBackend : public TestBackendBase {
+    explicit HistogramBackend(std::vector<uint32_t>* buckets) : buckets_{buckets} {}
+
+    void ReportHistogram(DatumId, int64_t, int64_t, const std::vector<uint32_t>& buckets) override {
+      *buckets_ = buckets;
+    }
+
+    std::vector<uint32_t>* buckets_;
+  } backend{&buckets};
+  histogram.Report(&backend);
+  return buckets;
+}
+
+}  // namespace test
+}  // namespace metrics
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
+
+#endif  // ART_LIBARTBASE_BASE_METRICS_METRICS_TEST_H_
diff --git a/libartbase/base/scoped_arena_containers.h b/libartbase/base/scoped_arena_containers.h
index 80144d2..bd2428b 100644
--- a/libartbase/base/scoped_arena_containers.h
+++ b/libartbase/base/scoped_arena_containers.h
@@ -26,6 +26,8 @@
 
 #include "arena_containers.h"  // For ArenaAllocatorAdapterKind.
 #include "dchecked_vector.h"
+#include "hash_map.h"
+#include "hash_set.h"
 #include "safe_map.h"
 #include "scoped_arena_allocator.h"
 
@@ -72,7 +74,7 @@
 
 template <typename Key,
           typename Value,
-          typename EmptyFn = DefaultEmptyFn<std::pair<Key, Value>>,
+          typename EmptyFn = DefaultMapEmptyFn<Key, Value>,
           typename HashFn = DefaultHashFn<Key>,
           typename Pred = DefaultPred<Key>>
 using ScopedArenaHashMap = HashMap<Key,
diff --git a/libartbase/base/sdk_version.h b/libartbase/base/sdk_version.h
index 219ac86..4a253d2 100644
--- a/libartbase/base/sdk_version.h
+++ b/libartbase/base/sdk_version.h
@@ -34,6 +34,7 @@
   kO_MR1 = 27u,
   kP     = 28u,
   kQ     = 29u,
+  kR     = 30u,
   kMax   = std::numeric_limits<uint32_t>::max(),
 };
 
diff --git a/libartbase/base/stats-inl.h b/libartbase/base/stats-inl.h
new file mode 100644
index 0000000..77a95c9
--- /dev/null
+++ b/libartbase/base/stats-inl.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 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_LIBARTBASE_BASE_STATS_INL_H_
+#define ART_LIBARTBASE_BASE_STATS_INL_H_
+
+#include <iomanip>
+#include <map>
+
+#include "base/stats.h"
+#include "base/indenter.h"
+
+namespace art {
+  void Stats::DumpSizes(VariableIndentationOutputStream& os, std::string_view name) const {
+    Dump(os, name, Value(), 1000.0, "KB");
+  }
+
+  void Stats::Dump(VariableIndentationOutputStream& os,
+                   std::string_view name,
+                   double total,
+                   double unit_size,
+                   const char* unit) const {
+    double percent = total > 0 ? 100.0 * Value() / total : 0;
+    const size_t name_width = 52 - os.GetIndentation();
+    if (name.length() > name_width) {
+      // Handle very long names by printing them on their own line.
+      os.Stream() << name << " \\\n";
+      name = "";
+    }
+    os.Stream()
+        << std::setw(name_width) << std::left << name << " "
+        << std::setw(6) << std::right << Count() << " "
+        << std::setw(10) << std::fixed << std::setprecision(3) << Value() / unit_size << unit << " "
+        << std::setw(6) << std::fixed << std::setprecision(1) << percent << "%\n";
+
+    // Sort all children by largest value first, then by name.
+    std::map<std::pair<double, std::string_view>, const Stats&> sorted_children;
+    for (const auto& it : Children()) {
+      sorted_children.emplace(std::make_pair(-it.second.Value(), it.first), it.second);
+    }
+
+    // Add "other" row to represent any amount not account for by the children.
+    Stats other;
+    other.AddBytes(Value() - SumChildrenValues(), Count());
+    if (other.Value() != 0.0 && !Children().empty()) {
+      sorted_children.emplace(std::make_pair(-other.Value(), "(other)"), other);
+    }
+
+    // Print the data.
+    ScopedIndentation indent1(&os);
+    for (const auto& it : sorted_children) {
+      it.second.Dump(os, it.first.second, total, unit_size, unit);
+    }
+  }
+}  // namespace art
+
+#endif  // ART_LIBARTBASE_BASE_STATS_INL_H_
diff --git a/libartbase/base/stats.h b/libartbase/base/stats.h
index 4dcbfe8..c568035 100644
--- a/libartbase/base/stats.h
+++ b/libartbase/base/stats.h
@@ -18,17 +18,20 @@
 #define ART_LIBARTBASE_BASE_STATS_H_
 
 #include <unordered_map>
+#include <string>
 
 #include "globals.h"
 
 namespace art {
 
+class VariableIndentationOutputStream;
+
 // Simple structure to record tree of statistical values.
 class Stats {
  public:
   double Value() const { return value_; }
   size_t Count() const { return count_; }
-  Stats* Child(const char* name) { return &children_[name]; }
+  Stats& operator[](const char* name) { return children_[name]; }
   const std::unordered_map<const char*, Stats>& Children() const { return children_; }
 
   void AddBytes(double bytes, size_t count = 1) { Add(bytes, count); }
@@ -44,12 +47,20 @@
     return sum;
   }
 
+  inline void DumpSizes(VariableIndentationOutputStream& os, std::string_view name) const;
+
  private:
   void Add(double value, size_t count = 1) {
     value_ += value;
     count_ += count;
   }
 
+  inline void Dump(VariableIndentationOutputStream& os,
+                   std::string_view name,
+                   double total,
+                   double unit_size,
+                   const char* unit) const;
+
   double value_ = 0.0;  // Commutative sum of the collected statistic in basic units.
   size_t count_ = 0;    // The number of samples for this node.
   std::unordered_map<const char*, Stats> children_;
diff --git a/libartbase/base/stl_util.h b/libartbase/base/stl_util.h
index fbafd53..dfe994e 100644
--- a/libartbase/base/stl_util.h
+++ b/libartbase/base/stl_util.h
@@ -19,6 +19,7 @@
 
 #include <algorithm>
 #include <iterator>
+#include <set>
 #include <sstream>
 
 #include <android-base/logging.h>
@@ -124,6 +125,11 @@
   return it != container.end();
 }
 
+template <typename T>
+bool ContainsElement(const std::set<T>& container, const T& value) {
+  return container.count(value) != 0u;
+}
+
 // 32-bit FNV-1a hash function suitable for std::unordered_map.
 // It can be used with any container which works with range-based for loop.
 // See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
@@ -223,6 +229,154 @@
                         ZipLeftIter(iter_left.end(), iter_right.end()));
 }
 
+static inline IterationRange<CountIter> Range(size_t start, size_t end) {
+  return IterationRange(CountIter(start), CountIter(end));
+}
+
+static inline IterationRange<CountIter> Range(size_t end) {
+  return Range(0, end);
+}
+
+template <typename RealIter, typename Filter>
+struct FilterIterator
+    : public std::iterator<std::forward_iterator_tag, typename RealIter::value_type> {
+ public:
+  FilterIterator(RealIter rl,
+                 Filter cond,
+                 std::optional<RealIter> end = std::nullopt)
+      : real_iter_(rl), cond_(cond), end_(end) {
+    DCHECK(std::make_optional(rl) == end_ || cond_(*real_iter_));
+  }
+
+  FilterIterator<RealIter, Filter>& operator++() {
+    DCHECK(std::make_optional(real_iter_) != end_);
+    do {
+      if (std::make_optional(++real_iter_) == end_) {
+        break;
+      }
+    } while (!cond_(*real_iter_));
+    return *this;
+  }
+  FilterIterator<RealIter, Filter> operator++(int) {
+    FilterIterator<RealIter, Filter> ret(real_iter_, cond_, end_);
+    ++(*this);
+    return ret;
+  }
+  bool operator==(const FilterIterator<RealIter, Filter>& other) const {
+    return real_iter_ == other.real_iter_;
+  }
+  bool operator!=(const FilterIterator<RealIter, Filter>& other) const {
+    return !(*this == other);
+  }
+  typename RealIter::value_type operator*() const {
+    return *real_iter_;
+  }
+
+ private:
+  RealIter real_iter_;
+  Filter cond_;
+  std::optional<RealIter> end_;
+};
+
+template <typename Iter, typename Filter>
+static inline IterationRange<FilterIterator<Iter, Filter>> Filter(
+    IterationRange<Iter> it, Filter cond) {
+  auto end = it.end();
+  auto start = std::find_if(it.begin(), end, cond);
+  return MakeIterationRange(FilterIterator(start, cond, std::make_optional(end)),
+                            FilterIterator(end, cond, std::make_optional(end)));
+}
+
+template <typename Val>
+struct NonNullFilter {
+ public:
+  static_assert(std::is_pointer<Val>::value, "Must be pointer type!");
+  constexpr bool operator()(Val v) const {
+    return v != nullptr;
+  }
+};
+
+template <typename InnerIter>
+using FilterNull = FilterIterator<InnerIter, NonNullFilter<typename InnerIter::value_type>>;
+
+template <typename InnerIter>
+static inline IterationRange<FilterNull<InnerIter>> FilterOutNull(IterationRange<InnerIter> inner) {
+  return Filter(inner, NonNullFilter<typename InnerIter::value_type>());
+}
+
+template <typename Val>
+struct SafePrinter  {
+  const Val* val_;
+};
+
+template<typename Val>
+std::ostream& operator<<(std::ostream& os, const SafePrinter<Val>& v) {
+  if (v.val_ == nullptr) {
+    return os << "NULL";
+  } else {
+    return os << *v.val_;
+  }
+}
+
+template<typename Val>
+SafePrinter<Val> SafePrint(const Val* v) {
+  return SafePrinter<Val>{v};
+}
+
+// Helper struct for iterating a split-string without allocation.
+struct SplitStringIter : public std::iterator<std::forward_iterator_tag, std::string_view> {
+ public:
+  // Direct iterator constructor. The iteration state is only the current index.
+  // We use that with the split char and the full string to get the current and
+  // next segment.
+  SplitStringIter(size_t index, char split, std::string_view sv)
+      : cur_index_(index), split_on_(split), sv_(sv) {}
+  SplitStringIter(const SplitStringIter&) = default;
+  SplitStringIter(SplitStringIter&&) = default;
+  SplitStringIter& operator=(SplitStringIter&&) = default;
+  SplitStringIter& operator=(const SplitStringIter&) = default;
+
+  SplitStringIter& operator++() {
+    size_t nxt = sv_.find(split_on_, cur_index_);
+    if (nxt == std::string_view::npos) {
+      cur_index_ = std::string_view::npos;
+    } else {
+      cur_index_ = nxt + 1;
+    }
+    return *this;
+  }
+
+  SplitStringIter operator++(int) {
+    SplitStringIter ret(cur_index_, split_on_, sv_);
+    ++(*this);
+    return ret;
+  }
+
+  bool operator==(const SplitStringIter& other) const {
+    return sv_ == other.sv_ && split_on_ == other.split_on_ && cur_index_== other.cur_index_;
+  }
+
+  bool operator!=(const SplitStringIter& other) const {
+    return !(*this == other);
+  }
+
+  typename std::string_view operator*() const {
+    return sv_.substr(cur_index_, sv_.substr(cur_index_).find(split_on_));
+  }
+
+ private:
+  size_t cur_index_;
+  char split_on_;
+  std::string_view sv_;
+};
+
+// Create an iteration range over the string 'sv' split at each 'target' occurrence.
+// Eg: SplitString(":foo::bar") -> ["", "foo", "", "bar"]
+inline IterationRange<SplitStringIter> SplitString(std::string_view sv, char target) {
+  return MakeIterationRange(SplitStringIter(0, target, sv),
+                            SplitStringIter(std::string_view::npos, target, sv));
+}
+
 }  // namespace art
 
 #endif  // ART_LIBARTBASE_BASE_STL_UTIL_H_
diff --git a/libartbase/base/systrace.h b/libartbase/base/systrace.h
index 30bba49..42975d7 100644
--- a/libartbase/base/systrace.h
+++ b/libartbase/base/systrace.h
@@ -27,8 +27,8 @@
 namespace art {
 
 inline bool ATraceEnabled() {
-  int enabled = 0;
-  if (UNLIKELY(PaletteTraceEnabled(&enabled) == PaletteStatus::kOkay && enabled != 0)) {
+  bool enabled = false;
+  if (UNLIKELY(PaletteTraceEnabled(&enabled) == PALETTE_STATUS_OK && enabled)) {
     return true;
   } else {
     return false;
diff --git a/libartbase/base/time_utils.cc b/libartbase/base/time_utils.cc
index aa6c987..aeb7fa2 100644
--- a/libartbase/base/time_utils.cc
+++ b/libartbase/base/time_utils.cc
@@ -131,17 +131,29 @@
 }
 
 std::string GetIsoDate() {
-  time_t now = time(nullptr);
   tm tmbuf;
+  int ns;
 #ifdef _WIN32
+  time_t now = time(nullptr);
   localtime_s(&tmbuf, &now);
-  tm* ptm = &tmbuf;
+  ns = 0;
 #else
-  tm* ptm = localtime_r(&now, &tmbuf);
+  if (__builtin_available(macOS 10.12, *)) {
+    timespec now;
+    clock_gettime(CLOCK_REALTIME, &now);
+    localtime_r(&now.tv_sec, &tmbuf);
+    ns = now.tv_nsec;
+  } else {
+    time_t now = time(nullptr);
+    localtime_r(&now, &tmbuf);
+    ns = 0;
+  }
 #endif
-  return StringPrintf("%04d-%02d-%02d %02d:%02d:%02d",
-      ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday,
-      ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
+  char zone[16] = {};
+  strftime(zone, sizeof(zone), "%z", &tmbuf);
+  return StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%09d%s",
+      tmbuf.tm_year + 1900, tmbuf.tm_mon+1, tmbuf.tm_mday,
+      tmbuf.tm_hour, tmbuf.tm_min, tmbuf.tm_sec, ns, zone);
 }
 
 uint64_t MilliTime() {
@@ -209,7 +221,7 @@
 
 void NanoSleep(uint64_t ns) {
   timespec tm;
-  tm.tv_sec = ns / MsToNs(1000);
+  tm.tv_sec = SaturatedTimeT(ns / MsToNs(1000));
   tm.tv_nsec = ns - static_cast<uint64_t>(tm.tv_sec) * MsToNs(1000);
   nanosleep(&tm, nullptr);
 }
diff --git a/libartbase/base/time_utils.h b/libartbase/base/time_utils.h
index 69c867c..dd73b1c 100644
--- a/libartbase/base/time_utils.h
+++ b/libartbase/base/time_utils.h
@@ -35,6 +35,10 @@
   kTimeUnitSecond,
 };
 
+// Constants for common time periods.
+constexpr unsigned int kOneMinuteInSeconds = 60;
+constexpr unsigned int kOneHourInSeconds = 60 * kOneMinuteInSeconds;
+
 // Returns a human-readable time string which prints every nanosecond while trying to limit the
 // number of trailing zeros. Prints using the largest human readable unit up to a second.
 // e.g. "1ms", "1.000000001s", "1.001us"
@@ -69,24 +73,42 @@
 uint64_t ProcessCpuNanoTime();
 
 // Converts the given number of nanoseconds to milliseconds.
-static constexpr inline uint64_t NsToMs(uint64_t ns) {
+static constexpr uint64_t NsToMs(uint64_t ns) {
   return ns / 1000 / 1000;
 }
 
+// Converts the given number of nanoseconds to microseconds.
+static constexpr uint64_t NsToUs(uint64_t ns) {
+  return ns / 1000;
+}
+
 // Converts the given number of milliseconds to nanoseconds
-static constexpr inline uint64_t MsToNs(uint64_t ms) {
+static constexpr uint64_t MsToNs(uint64_t ms) {
   return ms * 1000 * 1000;
 }
 
 // Converts the given number of milliseconds to microseconds
-static constexpr inline uint64_t MsToUs(uint64_t ms) {
+static constexpr uint64_t MsToUs(uint64_t ms) {
   return ms * 1000;
 }
 
-static constexpr inline uint64_t UsToNs(uint64_t us) {
+static constexpr uint64_t UsToNs(uint64_t us) {
   return us * 1000;
 }
 
+static constexpr uint64_t SecondsToMs(uint64_t seconds) {
+  return seconds * 1000;
+}
+
+static constexpr time_t SaturatedTimeT(int64_t secs) {
+  if (sizeof(time_t) < sizeof(int64_t)) {
+    return static_cast<time_t>(std::min(secs,
+                                        static_cast<int64_t>(std::numeric_limits<time_t>::max())));
+  } else {
+    return secs;
+  }
+}
+
 #if defined(__APPLE__)
 #ifndef CLOCK_REALTIME
 // No clocks to specify on OS/X < 10.12, fake value to pass to routines that require a clock.
diff --git a/libartbase/base/transform_array_ref.h b/libartbase/base/transform_array_ref.h
index ef29573..2f56e9b 100644
--- a/libartbase/base/transform_array_ref.h
+++ b/libartbase/base/transform_array_ref.h
@@ -93,7 +93,7 @@
   const_iterator begin() const { return MakeIterator(base().cbegin()); }
   const_iterator cbegin() const { return MakeIterator(base().cbegin()); }
   iterator end() { return MakeIterator(base().end()); }
-  const_iterator end() const { MakeIterator(base().cend()); }
+  const_iterator end() const { return MakeIterator(base().cend()); }
   const_iterator cend() const { return MakeIterator(base().cend()); }
   reverse_iterator rbegin() { return reverse_iterator(end()); }
   const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
diff --git a/libartbase/base/transform_array_ref_test.cc b/libartbase/base/transform_array_ref_test.cc
index fc73d56..896209b 100644
--- a/libartbase/base/transform_array_ref_test.cc
+++ b/libartbase/base/transform_array_ref_test.cc
@@ -174,18 +174,34 @@
   ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
   output.clear();
 
+  std::copy(std::begin(ctaref), std::end(ctaref), std::back_inserter(output));
+  ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
+  output.clear();
+
   std::copy(ctaref.cbegin(), ctaref.cend(), std::back_inserter(output));
   ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
   output.clear();
 
+  std::copy(std::cbegin(ctaref), std::cend(ctaref), std::back_inserter(output));
+  ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
+  output.clear();
+
   std::copy(ctaref.rbegin(), ctaref.rend(), std::back_inserter(output));
   ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output);
   output.clear();
 
+  std::copy(std::rbegin(ctaref), std::rend(ctaref), std::back_inserter(output));
+  ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output);
+  output.clear();
+
   std::copy(ctaref.crbegin(), ctaref.crend(), std::back_inserter(output));
   ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output);
   output.clear();
 
+  std::copy(std::crbegin(ctaref), std::crend(ctaref), std::back_inserter(output));
+  ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output);
+  output.clear();
+
   ASSERT_EQ(cinput.size(), ctaref.size());
   ASSERT_EQ(cinput.empty(), ctaref.empty());
   ASSERT_EQ(cinput.front().value, ctaref.front());
diff --git a/libartbase/base/unix_file/fd_file.cc b/libartbase/base/unix_file/fd_file.cc
index 8831b9c..2102fec 100644
--- a/libartbase/base/unix_file/fd_file.cc
+++ b/libartbase/base/unix_file/fd_file.cc
@@ -179,7 +179,7 @@
     }
     DCHECK_GE(guard_state_, GuardState::kClosed);
   }
-  if (fd_ != -1) {
+  if (fd_ != kInvalidFd) {
     if (Close() != 0) {
       PLOG(WARNING) << "Failed to close file with fd=" << fd_ << " path=" << file_path_;
     }
@@ -197,7 +197,7 @@
   }
 #endif
   other.guard_state_ = GuardState::kClosed;
-  other.fd_ = -1;
+  other.fd_ = kInvalidFd;
 }
 
 FdFile& FdFile::operator=(FdFile&& other) noexcept {
@@ -220,7 +220,7 @@
   }
 #endif
   other.guard_state_ = GuardState::kClosed;
-  other.fd_ = -1;
+  other.fd_ = kInvalidFd;
   return *this;
 }
 
@@ -230,7 +230,7 @@
 
 int FdFile::Release() {
   int tmp_fd = fd_;
-  fd_ = -1;
+  fd_ = kInvalidFd;
   guard_state_ = GuardState::kNoCheck;
 #if defined(__BIONIC__)
   if (tmp_fd >= 0) {
@@ -243,7 +243,7 @@
 void FdFile::Reset(int fd, bool check_usage) {
   CHECK_NE(fd, fd_);
 
-  if (fd_ != -1) {
+  if (fd_ != kInvalidFd) {
     Destroy();
   }
   fd_ = fd;
@@ -255,7 +255,7 @@
 #endif
 
   if (check_usage) {
-    guard_state_ = fd == -1 ? GuardState::kNoCheck : GuardState::kBase;
+    guard_state_ = fd == kInvalidFd ? GuardState::kNoCheck : GuardState::kBase;
   } else {
     guard_state_ = GuardState::kNoCheck;
   }
@@ -290,10 +290,10 @@
 
 bool FdFile::Open(const std::string& path, int flags, mode_t mode) {
   static_assert(O_RDONLY == 0, "Readonly flag has unexpected value.");
-  DCHECK_EQ(fd_, -1) << path;
+  DCHECK_EQ(fd_, kInvalidFd) << path;
   read_only_mode_ = ((flags & O_ACCMODE) == O_RDONLY);
   fd_ = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
-  if (fd_ == -1) {
+  if (fd_ == kInvalidFd) {
     return false;
   }
 
@@ -336,7 +336,7 @@
   }
 #endif
 
-  fd_ = -1;
+  fd_ = kInvalidFd;
   file_path_ = "";
   return 0;
 }
@@ -409,7 +409,7 @@
 }
 
 bool FdFile::IsOpened() const {
-  return fd_ >= 0;
+  return FdFile::IsOpenFd(fd_);
 }
 
 static ssize_t ReadIgnoreOffset(int fd, void *buf, size_t count, off_t offset) {
@@ -642,4 +642,18 @@
   return 0;
 }
 
+bool FdFile::IsOpenFd(int fd) {
+  if (fd == kInvalidFd) {
+    return false;
+  }
+  #ifdef _WIN32  // Windows toolchain does not support F_GETFD.
+    return true;
+  #else
+    int saved_errno = errno;
+    bool is_open = (fcntl(fd, F_GETFD) != -1);
+    errno = saved_errno;
+    return is_open;
+  #endif
+}
+
 }  // namespace unix_file
diff --git a/libartbase/base/unix_file/fd_file.h b/libartbase/base/unix_file/fd_file.h
index f5aa2a5..3947101 100644
--- a/libartbase/base/unix_file/fd_file.h
+++ b/libartbase/base/unix_file/fd_file.h
@@ -34,6 +34,8 @@
 // Not thread safe.
 class FdFile : public RandomAccessFile {
  public:
+  static constexpr int kInvalidFd = -1;
+
   FdFile() = default;
   // Creates an FdFile using the given file descriptor.
   // Takes ownership of the file descriptor.
@@ -93,7 +95,13 @@
   int Fd() const;
   bool ReadOnlyMode() const;
   bool CheckUsage() const;
+
+  // Check whether the underlying file descriptor refers to an open file.
   bool IsOpened() const;
+
+  // Check whether the numeric value of the underlying file descriptor is valid (Fd() != -1).
+  bool IsValid() const { return fd_ != kInvalidFd; }
+
   const std::string& GetPath() const {
     return file_path_;
   }
@@ -122,18 +130,22 @@
   void MarkUnchecked();
 
   // Compare against another file. Returns 0 if the files are equivalent, otherwise returns -1 or 1
-  // depending on if the lenghts are different. If the lengths are the same, the function returns
+  // depending on if the lengths are different. If the lengths are the same, the function returns
   // the difference of the first byte that differs.
   int Compare(FdFile* other);
 
+  // Check that `fd` has a valid value (!= kInvalidFd) and refers to an open file.
+  // On Windows, this call only checks that the value of `fd` is valid .
+  static bool IsOpenFd(int fd);
+
  protected:
-  // If the guard state indicates checking (!=kNoCheck), go to the target state "target". Print the
+  // If the guard state indicates checking (!=kNoCheck), go to the target state `target`. Print the
   // given warning if the current state is or exceeds warn_threshold.
   void moveTo(GuardState target, GuardState warn_threshold, const char* warning);
 
-  // If the guard state indicates checking (<kNoCheck), and is below the target state "target", go
-  // to "target." If the current state is higher (excluding kNoCheck) than the trg state, print the
-  // warning.
+  // If the guard state indicates checking (<kNoCheck), and is below the target state `target`, go
+  // to `target`. If the current state is higher (excluding kNoCheck) than the target state, print
+  // the warning.
   void moveUp(GuardState target, const char* warning);
 
   // Forcefully sets the state to the given one. This can overwrite kNoCheck.
@@ -145,7 +157,7 @@
 
   GuardState guard_state_ = GuardState::kClosed;
 
-  // Opens file 'file_path' using 'flags' and 'mode'.
+  // Opens file `file_path` using `flags` and `mode`.
   bool Open(const std::string& file_path, int flags);
   bool Open(const std::string& file_path, int flags, mode_t mode);
 
@@ -155,14 +167,14 @@
 
   void Destroy();  // For ~FdFile and operator=(&&).
 
-  int fd_ = -1;
+  int fd_ = kInvalidFd;
   std::string file_path_;
   bool read_only_mode_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(FdFile);
 };
 
-std::ostream& operator<<(std::ostream& os, const FdFile::GuardState& kind);
+std::ostream& operator<<(std::ostream& os, FdFile::GuardState kind);
 
 }  // namespace unix_file
 
diff --git a/libartbase/base/unix_file/fd_file_test.cc b/libartbase/base/unix_file/fd_file_test.cc
index 3a9cf59..f593337 100644
--- a/libartbase/base/unix_file/fd_file_test.cc
+++ b/libartbase/base/unix_file/fd_file_test.cc
@@ -46,11 +46,25 @@
 
 TEST_F(FdFileTest, UnopenedFile) {
   FdFile file;
-  EXPECT_EQ(-1, file.Fd());
+  EXPECT_EQ(FdFile::kInvalidFd, file.Fd());
   EXPECT_FALSE(file.IsOpened());
   EXPECT_TRUE(file.GetPath().empty());
 }
 
+TEST_F(FdFileTest, IsOpenFd) {
+  art::ScratchFile scratch_file;
+  FdFile* file = scratch_file.GetFile();
+  ASSERT_TRUE(file->IsOpened());
+  EXPECT_GE(file->Fd(), 0);
+  EXPECT_NE(file->Fd(), FdFile::kInvalidFd);
+  EXPECT_TRUE(FdFile::IsOpenFd(file->Fd()));
+  int old_fd = file->Fd();
+  ASSERT_TRUE(file != nullptr);
+  ASSERT_EQ(file->FlushClose(), 0);
+  EXPECT_FALSE(file->IsOpened());
+  EXPECT_FALSE(FdFile::IsOpenFd(old_fd));
+}
+
 TEST_F(FdFileTest, OpenClose) {
   std::string good_path(GetTmpPath("some-file.txt"));
   FdFile file(good_path, O_CREAT | O_WRONLY, true);
@@ -60,7 +74,7 @@
   EXPECT_FALSE(file.ReadOnlyMode());
   EXPECT_EQ(0, file.Flush());
   EXPECT_EQ(0, file.Close());
-  EXPECT_EQ(-1, file.Fd());
+  EXPECT_EQ(FdFile::kInvalidFd, file.Fd());
   EXPECT_FALSE(file.IsOpened());
   FdFile file2(good_path, O_RDONLY, true);
   EXPECT_TRUE(file2.IsOpened());
diff --git a/libartbase/base/utils.cc b/libartbase/base/utils.cc
index 19311b3..ba62f30 100644
--- a/libartbase/base/utils.cc
+++ b/libartbase/base/utils.cc
@@ -25,11 +25,13 @@
 
 #include <fstream>
 #include <memory>
+#include <string>
 
 #include "android-base/file.h"
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
 
+#include "base/stl_util.h"
 #include "bit_utils.h"
 #include "os.h"
 
@@ -179,7 +181,7 @@
   return false;
 }
 
-pid_t GetTid() {
+uint32_t GetTid() {
 #if defined(__APPLE__)
   uint64_t owner;
   CHECK_PTHREAD_CALL(pthread_threadid_np, (nullptr, &owner), __FUNCTION__);  // Requires Mac OS 10.6
@@ -209,48 +211,66 @@
   return result;
 }
 
-std::string PrettySize(int64_t byte_count) {
+std::string PrettySize(uint64_t byte_count) {
   // The byte thresholds at which we display amounts.  A byte count is displayed
   // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
-  static const int64_t kUnitThresholds[] = {
-    0,       // B up to...
-    10*KB,   // KB up to...
-    10*MB,   // MB up to...
-    10LL*GB  // GB from here.
+  static const uint64_t kUnitThresholds[] = {
+    0,        // B up to...
+    10*KB,    // KB up to...
+    10*MB,    // MB up to...
+    10ULL*GB  // GB from here.
   };
-  static const int64_t kBytesPerUnit[] = { 1, KB, MB, GB };
+  static const uint64_t kBytesPerUnit[] = { 1, KB, MB, GB };
   static const char* const kUnitStrings[] = { "B", "KB", "MB", "GB" };
-  const char* negative_str = "";
-  if (byte_count < 0) {
-    negative_str = "-";
-    byte_count = -byte_count;
-  }
   int i = arraysize(kUnitThresholds);
   while (--i > 0) {
     if (byte_count >= kUnitThresholds[i]) {
       break;
     }
   }
-  return StringPrintf("%s%" PRId64 "%s",
-                      negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
+  return StringPrintf("%" PRIu64 "%s",
+                      byte_count / kBytesPerUnit[i], kUnitStrings[i]);
 }
 
-void Split(const std::string& s, char separator, std::vector<std::string>* result) {
-  const char* p = s.data();
-  const char* end = p + s.size();
-  while (p != end) {
-    if (*p == separator) {
-      ++p;
-    } else {
-      const char* start = p;
-      while (++p != end && *p != separator) {
-        // Skip to the next occurrence of the separator.
-      }
-      result->push_back(std::string(start, p - start));
+template <typename StrIn, typename Str>
+void Split(const StrIn& s, char separator, std::vector<Str>* out_result) {
+  auto split = SplitString(std::string_view(s), separator);
+  for (std::string_view p : split) {
+    if (p.empty()) {
+      continue;
     }
+    out_result->push_back(Str(p));
   }
 }
 
+template void Split(const char *const& s, char separator, std::vector<std::string>* out_result);
+template void Split(const std::string& s, char separator, std::vector<std::string>* out_result);
+template void Split(const char *const& s, char separator, std::vector<std::string_view>* out_result);
+template void Split(const std::string_view& s,
+                    char separator,
+                    std::vector<std::string_view>* out_result);
+
+template <typename Str>
+void Split(const Str& s, char separator, size_t len, Str* out_result) {
+  Str* last = out_result + len;
+  auto split = SplitString(std::string_view(s), separator);
+  for (std::string_view p : split) {
+    if (p.empty()) {
+      continue;
+    }
+    if (out_result == last) {
+      return;
+    }
+    *out_result++ = Str(p);
+  }
+}
+
+template void Split(const std::string& s, char separator, size_t len, std::string* out_result);
+template void Split(const std::string_view& s,
+                    char separator,
+                    size_t len,
+                    std::string_view* out_result);
+
 void SetThreadName(const char* thread_name) {
   bool hasAt = false;
   bool hasDot = false;
diff --git a/libartbase/base/utils.h b/libartbase/base/utils.h
index 4bcb915..7160302 100644
--- a/libartbase/base/utils.h
+++ b/libartbase/base/utils.h
@@ -40,14 +40,23 @@
 }
 
 // Returns a human-readable size string such as "1MB".
-std::string PrettySize(int64_t size_in_bytes);
+std::string PrettySize(uint64_t size_in_bytes);
 
 // Splits a string using the given separator character into a vector of
 // strings. Empty strings will be omitted.
-void Split(const std::string& s, char separator, std::vector<std::string>* result);
+template<typename StrIn, typename Str>
+void Split(const StrIn& s, char separator, std::vector<Str>* out_result);
+
+template<typename Str>
+void Split(const Str& s, char separator, size_t len, Str* out_result);
+
+template<typename StrIn, typename Str, size_t kLen>
+void Split(const StrIn& s, char separator, std::array<Str, kLen>* out_result) {
+  Split<Str>(Str(s), separator, kLen, &((*out_result)[0]));
+}
 
 // Returns the calling thread's tid. (The C libraries don't expose this.)
-pid_t GetTid();
+uint32_t GetTid();
 
 // Returns the given thread's name.
 std::string GetThreadName(pid_t tid);
diff --git a/libartbase/base/utils_test.cc b/libartbase/base/utils_test.cc
index 631a225..ab8627f 100644
--- a/libartbase/base/utils_test.cc
+++ b/libartbase/base/utils_test.cc
@@ -15,7 +15,9 @@
  */
 
 #include "utils.h"
+#include "stl_util.h"
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
 namespace art {
@@ -41,9 +43,13 @@
   EXPECT_EQ("512B", PrettySize(512));
 }
 
+void Split(const char* arr, char s, std::vector<std::string_view>* sv) {
+  Split<std::string_view>(std::string_view(arr), s, sv);
+}
+
 TEST_F(UtilsTest, Split) {
-  std::vector<std::string> actual;
-  std::vector<std::string> expected;
+  std::vector<std::string_view> actual;
+  std::vector<std::string_view> expected;
 
   expected.clear();
 
@@ -108,11 +114,58 @@
 }
 
 TEST_F(UtilsTest, GetProcessStatus) {
-  EXPECT_EQ("utils_test", GetProcessStatus("Name"));
+  EXPECT_THAT(GetProcessStatus("Name"),
+              testing::AnyOf(
+                  "art_libartbase_",    // Test binary name: `art_libartbase_test`.
+                  "art_standalone_"));  // Test binary name: `art_standalone_libartbase_test`.
   EXPECT_EQ("R (running)", GetProcessStatus("State"));
   EXPECT_EQ("<unknown>", GetProcessStatus("tate"));
   EXPECT_EQ("<unknown>", GetProcessStatus("e"));
-  EXPECT_EQ("<unknown>", GetProcessStatus("Dummy"));
+  EXPECT_EQ("<unknown>", GetProcessStatus("InvalidFieldName"));
+}
+
+TEST_F(UtilsTest, StringSplit) {
+  auto range = SplitString("[ab[c[[d[e[", '[');
+  auto it = range.begin();
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "");
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "ab");
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "c");
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "");
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "d");
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "e");
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "");
+  EXPECT_TRUE(it == range.end());
+}
+
+TEST_F(UtilsTest, StringSplit2) {
+  auto range = SplitString("ab[c[[d[e", '[');
+  auto it = range.begin();
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "ab");
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "c");
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "");
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "d");
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "e");
+  EXPECT_TRUE(it == range.end());
+}
+
+TEST_F(UtilsTest, StringSplit3) {
+  auto range = SplitString("", '[');
+  auto it = range.begin();
+  EXPECT_FALSE(it == range.end());
+  EXPECT_EQ(*it++, "");
+  EXPECT_TRUE(it == range.end());
 }
 
 }  // namespace art
diff --git a/libartbase/base/variant_map.h b/libartbase/base/variant_map.h
index 581bc23..7349bbc 100644
--- a/libartbase/base/variant_map.h
+++ b/libartbase/base/variant_map.h
@@ -229,6 +229,14 @@
     return GetValuePtr(key);
   }
 
+  // Look up the value from the key and return the value wrapped in a std::optional. If it was not
+  // set in the map, return an empty std::optional.
+  template <typename TValue>
+  std::optional<TValue> GetOptional(const TKey<TValue>& key) const {
+    auto* ptr = Get(key);
+    return (ptr == nullptr) ? std::optional<TValue>{} : std::make_optional(*ptr);
+  }
+
   // Lookup the value from the key. If it was not set in the map, return the default value.
   // The default value is either the key's default, or TValue{} if the key doesn't have a default.
   template <typename TValue>
diff --git a/libartbase/base/zip_archive.cc b/libartbase/base/zip_archive.cc
index c899039..6abcdc5 100644
--- a/libartbase/base/zip_archive.cc
+++ b/libartbase/base/zip_archive.cc
@@ -60,7 +60,7 @@
 
 bool ZipEntry::ExtractToFile(File& file, std::string* error_msg) {
   const int32_t error = ExtractEntryToFile(handle_, zip_entry_, file.Fd());
-  if (error) {
+  if (error != 0) {
     *error_msg = std::string(ErrorCodeString(error));
     return false;
   }
@@ -84,15 +84,23 @@
     return MemMap::Invalid();
   }
 
-  const int32_t error = ExtractToMemory(handle_, zip_entry_, map.Begin(), map.Size());
-  if (error) {
-    *error_msg = std::string(ErrorCodeString(error));
+  DCHECK_EQ(map.Size(), GetUncompressedLength());
+  if (!ExtractToMemory(map.Begin(), error_msg)) {
     return MemMap::Invalid();
   }
 
   return map;
 }
 
+bool ZipEntry::ExtractToMemory(/*out*/uint8_t* buffer, /*out*/std::string* error_msg) {
+  const int32_t error = ::ExtractToMemory(handle_, zip_entry_, buffer, GetUncompressedLength());
+  if (error != 0) {
+    *error_msg = std::string(ErrorCodeString(error));
+    return false;
+  }
+  return true;
+}
+
 MemMap ZipEntry::MapDirectlyFromFile(const char* zip_filename, std::string* error_msg) {
   const int zip_fd = GetFileDescriptor(handle_);
   const char* entry_filename = entry_name_.c_str();
@@ -227,7 +235,7 @@
 
   ZipArchiveHandle handle;
   const int32_t error = OpenArchive(filename, &handle);
-  if (error) {
+  if (error != 0) {
     *error_msg = std::string(ErrorCodeString(error));
     CloseArchive(handle);
     return nullptr;
@@ -243,7 +251,7 @@
 
   ZipArchiveHandle handle;
   const int32_t error = OpenArchiveFd(fd, filename, &handle);
-  if (error) {
+  if (error != 0) {
     *error_msg = std::string(ErrorCodeString(error));
     CloseArchive(handle);
     return nullptr;
@@ -259,7 +267,7 @@
   // Resist the urge to delete the space. <: is a bigraph sequence.
   std::unique_ptr< ::ZipEntry> zip_entry(new ::ZipEntry);
   const int32_t error = FindEntry(handle_, name, zip_entry.get());
-  if (error) {
+  if (error != 0) {
     *error_msg = std::string(ErrorCodeString(error));
     return nullptr;
   }
diff --git a/libartbase/base/zip_archive.h b/libartbase/base/zip_archive.h
index fc04ec1..a4e56b5 100644
--- a/libartbase/base/zip_archive.h
+++ b/libartbase/base/zip_archive.h
@@ -41,12 +41,17 @@
 
 class ZipEntry {
  public:
-  bool ExtractToFile(File& file, std::string* error_msg);
+  // Extracts this entry to file.
+  // Returns true on success, false on failure.
+  bool ExtractToFile(File& file, /*out*/std::string* error_msg);
   // Extract this entry to anonymous memory (R/W).
   // Returns null on failure and sets error_msg.
   MemMap ExtractToMemMap(const char* zip_filename,
                          const char* entry_filename,
-                         std::string* error_msg);
+                         /*out*/std::string* error_msg);
+  // Extracts this entry to memory. Stores `GetUncompressedSize()` bytes on success.
+  // Returns true on success, false on failure.
+  bool ExtractToMemory(/*out*/uint8_t* buffer, /*out*/std::string* error_msg);
   // Create a file-backed private (clean, R/W) memory mapping to this entry.
   // 'zip_filename' is used for diagnostics only,
   //   the original file that the ZipArchive was open with is used
diff --git a/libartbase/libartbase.map b/libartbase/libartbase.map
deleted file mode 100644
index 6249930..0000000
--- a/libartbase/libartbase.map
+++ /dev/null
@@ -1,15 +0,0 @@
-# This is used only to hide data symbols that get imported through
-# whole_static_libs, or else they might trigger the ASan odr-violation check.
-# Before adding symbols here, please make sure that it doesn't give rise to a
-# real ODR problem. All these symbols are either in .rodata or .data.rel.ro
-# sections.
-LIBARTBASE {
-  local:
-    PPMD7_kExpEscape;
-    XZ_SIG;
-    g_AlignedAlloc;
-    g_Alloc;
-    g_BigAlloc;
-    g_MidAlloc;
-    k7zSignature;
-};
diff --git a/libartimagevalues/Android.bp b/libartimagevalues/Android.bp
deleted file mode 100644
index 0f38952..0000000
--- a/libartimagevalues/Android.bp
+++ /dev/null
@@ -1,17 +0,0 @@
-// Inherit image values.
-art_global_defaults {
-    name: "libartimagevalues_defaults",
-}
-
-cc_library_static {
-    name: "libartimagevalues",
-    defaults: ["libartimagevalues_defaults"],
-    visibility: [
-        "//art/build/sdk",
-        // TODO(b/133140750): Clean this up.
-        "//frameworks/native/cmds/installd",
-    ],
-    srcs: ["art_image_values.cpp"],
-    export_include_dirs: ["."],
-    cflags: ["-Wconversion"],
-}
diff --git a/libartimagevalues/art_image_values.cpp b/libartimagevalues/art_image_values.cpp
deleted file mode 100644
index 849e218..0000000
--- a/libartimagevalues/art_image_values.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 "art_image_values.h"
-
-namespace android {
-namespace art {
-namespace imagevalues {
-
-uint32_t GetImageBaseAddress() {
-    return ART_BASE_ADDRESS;
-}
-int32_t GetImageMinBaseAddressDelta() {
-    return ART_BASE_ADDRESS_MIN_DELTA;
-}
-int32_t GetImageMaxBaseAddressDelta() {
-    return ART_BASE_ADDRESS_MAX_DELTA;
-}
-
-static_assert(ART_BASE_ADDRESS_MIN_DELTA < ART_BASE_ADDRESS_MAX_DELTA, "Inconsistent setup");
-
-}  // namespace imagevalues
-}  // namespace art
-}  // namespace android
diff --git a/libartimagevalues/art_image_values.h b/libartimagevalues/art_image_values.h
deleted file mode 100644
index 14e5f75..0000000
--- a/libartimagevalues/art_image_values.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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_LIBARTIMAGEVALUES_ART_IMAGE_VALUES_H_
-#define ART_LIBARTIMAGEVALUES_ART_IMAGE_VALUES_H_
-
-#include <cstdint>
-
-namespace android {
-namespace art {
-namespace imagevalues {
-
-uint32_t GetImageBaseAddress();
-int32_t GetImageMinBaseAddressDelta();
-int32_t GetImageMaxBaseAddressDelta();
-
-}  // namespace imagevalues
-}  // namespace art
-}  // namespace android
-
-#endif  // ART_LIBARTIMAGEVALUES_ART_IMAGE_VALUES_H_
diff --git a/libartpalette/Android.bp b/libartpalette/Android.bp
index b4b2e0b..19d12c7 100644
--- a/libartpalette/Android.bp
+++ b/libartpalette/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "libartpalette_defaults",
     defaults: ["art_defaults"],
@@ -25,7 +34,10 @@
     name: "libartpalette-headers",
     export_include_dirs: ["include"],
     host_supported: true,
-    visibility: ["//system/libartpalette"],
+    visibility: [
+        "//art:__subpackages__",
+        "//system/libartpalette",
+    ],
 }
 
 // libartpalette is the dynamic loader of the platform abstraction
@@ -34,12 +46,24 @@
 art_cc_library {
     name: "libartpalette",
     defaults: ["libartpalette_defaults"],
-    required: ["libartpalette-system"], // libartpalette.so dlopen()'s libartpalette-system.
-    header_libs: ["libbase_headers"],
+    visibility: [
+        // TODO(b/183483755): Please visibility checks when the prebuilt
+        // libartpalette is present but not preferred, and the prebuilt
+        // libdexfile hence depends on the source instead.
+        // TODO(b/172480617): Alternatively, clean up when we no longer need to
+        // support both prebuilts and sources present simultaneously.
+        "//prebuilts/module_sdk/art/current/host-exports",
+    ],
+    header_libs: [
+        "libbase_headers",
+        "jni_headers",
+    ],
     target: {
         // Targets supporting dlopen build the client library which loads
         // and binds the methods in the libartpalette-system library.
         android: {
+            // libartpalette.so dlopen()'s libartpalette-system.
+            runtime_libs: ["libartpalette-system"],
             srcs: ["apex/palette.cc"],
             shared_libs: ["liblog"],
             version_script: "libartpalette.map.txt",
@@ -88,18 +112,36 @@
         },
     },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
         // TODO(b/142944931): remove this
         "com.android.runtime", // due to the transitive dependency from linker
     ],
 }
 
-art_cc_test {
-    name: "art_libartpalette_tests",
-    defaults: ["art_gtest_defaults"],
-    host_supported: true,
+art_cc_defaults {
+    name: "art_libartpalette_tests_defaults",
     srcs: ["apex/palette_test.cc"],
     shared_libs: ["libartpalette"],
-    test_per_src: true,
+}
+
+// Version of ART gtest `art_libartpalette_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
+art_cc_test {
+    name: "art_libartpalette_tests",
+    defaults: [
+        "art_gtest_defaults",
+        "art_libartpalette_tests_defaults",
+    ],
+    host_supported: true,
+}
+
+// Standalone version of ART gtest `art_libartpalette_tests`, not bundled with the ART APEX on
+// target.
+art_cc_test {
+    name: "art_standalone_libartpalette_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_libartpalette_tests_defaults",
+    ],
 }
diff --git a/libartpalette/apex/palette.cc b/libartpalette/apex/palette.cc
index 041fe7a..71fd39d 100644
--- a/libartpalette/apex/palette.cc
+++ b/libartpalette/apex/palette.cc
@@ -32,13 +32,13 @@
 
 // Generic method used when a dynamically loaded palette instance does not
 // support a method.
-enum PaletteStatus PaletteMethodNotSupported() {
-  return PaletteStatus::kNotSupported;
+palette_status_t PaletteMethodNotSupported() {
+  return PALETTE_STATUS_NOT_SUPPORTED;
 }
 
 // Declare type aliases for pointers to each function in the interface.
 #define PALETTE_METHOD_TYPE_ALIAS(Name, ...) \
-  using Name ## Method = PaletteStatus(*)(__VA_ARGS__);
+  using Name ## Method = palette_status_t(*)(__VA_ARGS__);
 PALETTE_METHOD_LIST(PALETTE_METHOD_TYPE_ALIAS)
 #undef PALETTE_METHOD_TYPE_ALIAS
 
@@ -93,7 +93,7 @@
     return reinterpret_cast<void*>(PaletteMethodNotSupported);
   }
   // TODO(oth): consider new GetMethodSignature() in the Palette API which
-  // would allow sanity checking the type signatures.
+  // would allow checking the validity of the type signatures.
   return method;
 }
 
@@ -110,57 +110,112 @@
 
 extern "C" {
 
-enum PaletteStatus PaletteGetVersion(/*out*/int32_t* version) {
-  PaletteGetVersionMethod m = PaletteLoader::Instance().GetPaletteGetVersionMethod();
-  return m(version);
-}
-
-enum PaletteStatus PaletteSchedSetPriority(int32_t tid, int32_t java_priority) {
+palette_status_t PaletteSchedSetPriority(int32_t tid, int32_t java_priority) {
   PaletteSchedSetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedSetPriorityMethod();
   return m(tid, java_priority);
 }
 
-enum PaletteStatus PaletteSchedGetPriority(int32_t tid, /*out*/int32_t* java_priority) {
+palette_status_t PaletteSchedGetPriority(int32_t tid, /*out*/int32_t* java_priority) {
   PaletteSchedGetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedGetPriorityMethod();
   return m(tid, java_priority);
 }
 
-enum PaletteStatus PaletteWriteCrashThreadStacks(/*in*/const char* stack, size_t stack_len) {
+palette_status_t PaletteWriteCrashThreadStacks(/*in*/const char* stack, size_t stack_len) {
   PaletteWriteCrashThreadStacksMethod m =
       PaletteLoader::Instance().GetPaletteWriteCrashThreadStacksMethod();
   return m(stack, stack_len);
 }
 
-enum PaletteStatus PaletteTraceEnabled(/*out*/int32_t* enabled) {
+palette_status_t PaletteTraceEnabled(/*out*/bool* enabled) {
   PaletteTraceEnabledMethod m = PaletteLoader::Instance().GetPaletteTraceEnabledMethod();
   return m(enabled);
 }
 
-enum PaletteStatus PaletteTraceBegin(/*in*/const char* name) {
+palette_status_t PaletteTraceBegin(/*in*/const char* name) {
   PaletteTraceBeginMethod m = PaletteLoader::Instance().GetPaletteTraceBeginMethod();
   return m(name);
 }
 
-enum PaletteStatus PaletteTraceEnd() {
+palette_status_t PaletteTraceEnd() {
   PaletteTraceEndMethod m = PaletteLoader::Instance().GetPaletteTraceEndMethod();
   return m();
 }
 
-enum PaletteStatus PaletteTraceIntegerValue(/*in*/const char* name, int32_t value) {
+palette_status_t PaletteTraceIntegerValue(/*in*/const char* name, int32_t value) {
   PaletteTraceIntegerValueMethod m = PaletteLoader::Instance().GetPaletteTraceIntegerValueMethod();
   return m(name, value);
 }
 
-enum PaletteStatus PaletteAshmemCreateRegion(const char* name, size_t size, int* fd) {
+palette_status_t PaletteAshmemCreateRegion(const char* name, size_t size, int* fd) {
   PaletteAshmemCreateRegionMethod m =
       PaletteLoader::Instance().GetPaletteAshmemCreateRegionMethod();
   return m(name, size, fd);
 }
 
-enum PaletteStatus PaletteAshmemSetProtRegion(int fd, int prot) {
+palette_status_t PaletteAshmemSetProtRegion(int fd, int prot) {
   PaletteAshmemSetProtRegionMethod m =
       PaletteLoader::Instance().GetPaletteAshmemSetProtRegionMethod();
   return m(fd, prot);
 }
 
+palette_status_t PaletteCreateOdrefreshStagingDirectory(const char** staging_dir) {
+  PaletteCreateOdrefreshStagingDirectoryMethod m =
+      PaletteLoader::Instance().GetPaletteCreateOdrefreshStagingDirectoryMethod();
+  return m(staging_dir);
+}
+
+palette_status_t PaletteShouldReportDex2oatCompilation(bool* value) {
+  PaletteShouldReportDex2oatCompilationMethod m =
+      PaletteLoader::Instance().GetPaletteShouldReportDex2oatCompilationMethod();
+  return m(value);
+}
+
+palette_status_t PaletteNotifyStartDex2oatCompilation(int source_fd,
+                                                      int art_fd,
+                                                      int oat_fd,
+                                                      int vdex_fd) {
+  PaletteNotifyStartDex2oatCompilationMethod m =
+      PaletteLoader::Instance().GetPaletteNotifyStartDex2oatCompilationMethod();
+  return m(source_fd, art_fd, oat_fd, vdex_fd);
+}
+
+palette_status_t PaletteNotifyEndDex2oatCompilation(int source_fd,
+                                                    int art_fd,
+                                                    int oat_fd,
+                                                    int vdex_fd) {
+  PaletteNotifyEndDex2oatCompilationMethod m =
+      PaletteLoader::Instance().GetPaletteNotifyEndDex2oatCompilationMethod();
+  return m(source_fd, art_fd, oat_fd, vdex_fd);
+}
+
+palette_status_t PaletteNotifyDexFileLoaded(const char* path) {
+  PaletteNotifyDexFileLoadedMethod m =
+      PaletteLoader::Instance().GetPaletteNotifyDexFileLoadedMethod();
+  return m(path);
+}
+
+palette_status_t PaletteNotifyOatFileLoaded(const char* path) {
+  PaletteNotifyOatFileLoadedMethod m =
+      PaletteLoader::Instance().GetPaletteNotifyOatFileLoadedMethod();
+  return m(path);
+}
+
+palette_status_t PaletteShouldReportJniInvocations(bool* value) {
+  PaletteShouldReportJniInvocationsMethod m =
+      PaletteLoader::Instance().GetPaletteShouldReportJniInvocationsMethod();
+  return m(value);
+}
+
+palette_status_t PaletteNotifyBeginJniInvocation(JNIEnv* env) {
+  PaletteNotifyBeginJniInvocationMethod m =
+      PaletteLoader::Instance().GetPaletteNotifyBeginJniInvocationMethod();
+  return m(env);
+}
+
+palette_status_t PaletteNotifyEndJniInvocation(JNIEnv* env) {
+  PaletteNotifyEndJniInvocationMethod m =
+      PaletteLoader::Instance().GetPaletteNotifyEndJniInvocationMethod();
+  return m(env);
+}
+
 }  // extern "C"
diff --git a/libartpalette/apex/palette_test.cc b/libartpalette/apex/palette_test.cc
index 8bbe0ee..e6018ee 100644
--- a/libartpalette/apex/palette_test.cc
+++ b/libartpalette/apex/palette_test.cc
@@ -35,30 +35,23 @@
 
 class PaletteClientTest : public testing::Test {};
 
-TEST_F(PaletteClientTest, GetVersion) {
-  int32_t version = -1;
-  PaletteStatus status = PaletteGetVersion(&version);
-  ASSERT_EQ(PaletteStatus::kOkay, status);
-  ASSERT_GE(version, 1);
-}
-
 TEST_F(PaletteClientTest, SchedPriority) {
   int32_t tid = GetTid();
   int32_t saved_priority;
-  EXPECT_EQ(PaletteStatus::kOkay, PaletteSchedGetPriority(tid, &saved_priority));
+  EXPECT_EQ(PALETTE_STATUS_OK, PaletteSchedGetPriority(tid, &saved_priority));
 
-  EXPECT_EQ(PaletteStatus::kInvalidArgument, PaletteSchedSetPriority(tid, /*java_priority=*/ 0));
-  EXPECT_EQ(PaletteStatus::kInvalidArgument, PaletteSchedSetPriority(tid, /*java_priority=*/ -1));
-  EXPECT_EQ(PaletteStatus::kInvalidArgument, PaletteSchedSetPriority(tid, /*java_priority=*/ 11));
+  EXPECT_EQ(PALETTE_STATUS_INVALID_ARGUMENT, PaletteSchedSetPriority(tid, /*java_priority=*/ 0));
+  EXPECT_EQ(PALETTE_STATUS_INVALID_ARGUMENT, PaletteSchedSetPriority(tid, /*java_priority=*/ -1));
+  EXPECT_EQ(PALETTE_STATUS_INVALID_ARGUMENT, PaletteSchedSetPriority(tid, /*java_priority=*/ 11));
 
-  EXPECT_EQ(PaletteStatus::kOkay, PaletteSchedSetPriority(tid, /*java_priority=*/ 1));
-  EXPECT_EQ(PaletteStatus::kOkay, PaletteSchedSetPriority(tid, saved_priority));
+  EXPECT_EQ(PALETTE_STATUS_OK, PaletteSchedSetPriority(tid, /*java_priority=*/ 1));
+  EXPECT_EQ(PALETTE_STATUS_OK, PaletteSchedSetPriority(tid, saved_priority));
 }
 
 TEST_F(PaletteClientTest, Trace) {
-  int32_t enabled;
-  EXPECT_EQ(PaletteStatus::kOkay, PaletteTraceEnabled(&enabled));
-  EXPECT_EQ(PaletteStatus::kOkay, PaletteTraceBegin("Hello world!"));
-  EXPECT_EQ(PaletteStatus::kOkay, PaletteTraceEnd());
-  EXPECT_EQ(PaletteStatus::kOkay, PaletteTraceIntegerValue("Beans", /*value=*/ 3));
+  bool enabled = false;
+  EXPECT_EQ(PALETTE_STATUS_OK, PaletteTraceEnabled(&enabled));
+  EXPECT_EQ(PALETTE_STATUS_OK, PaletteTraceBegin("Hello world!"));
+  EXPECT_EQ(PALETTE_STATUS_OK, PaletteTraceEnd());
+  EXPECT_EQ(PALETTE_STATUS_OK, PaletteTraceIntegerValue("Beans", /*value=*/ 3));
 }
diff --git a/libartpalette/include/palette/palette.h b/libartpalette/include/palette/palette.h
index 1f58403..3e12b14 100644
--- a/libartpalette/include/palette/palette.h
+++ b/libartpalette/include/palette/palette.h
@@ -26,7 +26,7 @@
 // Palette method signatures are defined in palette_method_list.h.
 
 #define PALETTE_METHOD_DECLARATION(Name, ...) \
-  enum PaletteStatus Name(__VA_ARGS__);
+  palette_status_t Name(__VA_ARGS__);
 #include "palette_method_list.h"
 PALETTE_METHOD_LIST(PALETTE_METHOD_DECLARATION)
 #undef PALETTE_METHOD_DECLARATION
diff --git a/libartpalette/include/palette/palette_method_list.h b/libartpalette/include/palette/palette_method_list.h
index 1140399..6a7822b 100644
--- a/libartpalette/include/palette/palette_method_list.h
+++ b/libartpalette/include/palette/palette_method_list.h
@@ -17,20 +17,41 @@
 #ifndef ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_METHOD_LIST_H_
 #define ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_METHOD_LIST_H_
 
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 
+#include "jni.h"
+
 // Methods in version 1 API
 #define PALETTE_METHOD_LIST(M)                                              \
-  M(PaletteGetVersion, /*out*/int32_t* version)                             \
   M(PaletteSchedSetPriority, int32_t tid, int32_t java_priority)            \
   M(PaletteSchedGetPriority, int32_t tid, /*out*/int32_t* java_priority)    \
   M(PaletteWriteCrashThreadStacks, const char* stacks, size_t stacks_len)   \
-  M(PaletteTraceEnabled, /*out*/int32_t* enabled)                           \
+  M(PaletteTraceEnabled, /*out*/bool* enabled)                              \
   M(PaletteTraceBegin, const char* name)                                    \
   M(PaletteTraceEnd)                                                        \
   M(PaletteTraceIntegerValue, const char* name, int32_t value)              \
   M(PaletteAshmemCreateRegion, const char* name, size_t size, int* fd)      \
-  M(PaletteAshmemSetProtRegion, int, int)
+  M(PaletteAshmemSetProtRegion, int, int)                                   \
+  /* Create the staging directory for on-device signing.                 */ \
+  /* `staging_dir` is updated to point to a constant string in the       */ \
+  /* palette implementation.                                             */ \
+  /* This method is not thread-safe.                                     */ \
+  M(PaletteCreateOdrefreshStagingDirectory, /*out*/const char** staging_dir)\
+  M(PaletteShouldReportDex2oatCompilation, bool*)                           \
+  M(PaletteNotifyStartDex2oatCompilation, int source_fd,                    \
+                                          int art_fd,                       \
+                                          int oat_fd,                       \
+                                          int vdex_fd)                      \
+  M(PaletteNotifyEndDex2oatCompilation, int source_fd,                      \
+                                        int art_fd,                         \
+                                        int oat_fd,                         \
+                                        int vdex_fd)                        \
+  M(PaletteNotifyDexFileLoaded, const char* path)                           \
+  M(PaletteNotifyOatFileLoaded, const char* path)                           \
+  M(PaletteShouldReportJniInvocations, bool*)                               \
+  M(PaletteNotifyBeginJniInvocation, JNIEnv* env)                           \
+  M(PaletteNotifyEndJniInvocation, JNIEnv* env)                             \
 
 #endif  // ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_METHOD_LIST_H_
diff --git a/libartpalette/include/palette/palette_types.h b/libartpalette/include/palette/palette_types.h
index c2cd6b8..905a341 100644
--- a/libartpalette/include/palette/palette_types.h
+++ b/libartpalette/include/palette/palette_types.h
@@ -23,14 +23,24 @@
 extern "C" {
 #endif  // __cplusplus
 
-// Return values for palette functions.
-enum PaletteStatus {
-  kOkay = 0,
-  kCheckErrno = 1,
-  kInvalidArgument = 2,
-  kNotSupported = 3,
-  kFailedCheckLog = 4,
-};
+typedef int32_t palette_status_t;
+
+// Palette function return value when the function completed successfully.
+#define PALETTE_STATUS_OK                 ((palette_status_t) 0)
+
+// Palette function return value when the function called yielded and error captured by `errno`.
+#define PALETTE_STATUS_CHECK_ERRNO        ((palette_status_t) 1)
+
+// Palette function return value when an argument to the function was invalid.
+#define PALETTE_STATUS_INVALID_ARGUMENT   ((palette_status_t) 2)
+
+// Palette function return value when the function called is not supported. This value allows
+// palette functions to be retired across Android versions. Palette functions can never be removed
+// from the palette interface by design.
+#define PALETTE_STATUS_NOT_SUPPORTED      ((palette_status_t) 3)
+
+// Palette function return value when the function failed for unknown reasons.
+#define PALETTE_STATUS_FAILED_CHECK_LOG   ((palette_status_t) 4)
 
 #ifdef __cplusplus
 }
diff --git a/libartpalette/libartpalette.map.txt b/libartpalette/libartpalette.map.txt
index d2c90d5..9c846b1 100644
--- a/libartpalette/libartpalette.map.txt
+++ b/libartpalette/libartpalette.map.txt
@@ -17,16 +17,24 @@
 LIBARTPALETTE_1 {
   global:
     # --- VERSION 01 API ---
-    PaletteGetVersion;
-    PaletteSchedSetPriority;
-    PaletteSchedGetPriority;
-    PaletteWriteCrashThreadStacks;
-    PaletteTraceEnabled;
-    PaletteTraceBegin;
-    PaletteTraceEnd;
-    PaletteTraceIntegerValue;
-    PaletteAshmemCreateRegion;
-    PaletteAshmemSetProtRegion;
+    PaletteSchedSetPriority; # apex
+    PaletteSchedGetPriority; # apex
+    PaletteWriteCrashThreadStacks; #apex
+    PaletteTraceEnabled; # apex
+    PaletteTraceBegin; # apex
+    PaletteTraceEnd; # apex
+    PaletteTraceIntegerValue; # apex
+    PaletteAshmemCreateRegion; # apex
+    PaletteAshmemSetProtRegion; # apex
+    PaletteCreateOdrefreshStagingDirectory; # apex
+    PaletteShouldReportDex2oatCompilation; #apex
+    PaletteNotifyStartDex2oatCompilation; #apex
+    PaletteNotifyEndDex2oatCompilation; #apex
+    PaletteNotifyDexFileLoaded; #apex
+    PaletteNotifyOatFileLoaded; #apex
+    PaletteShouldReportJniInvocations; #apex
+    PaletteNotifyBeginJniInvocation; #apex
+    PaletteNotifyEndJniInvocation; #apex
 
   local:
     *;
diff --git a/libartpalette/system/palette_fake.cc b/libartpalette/system/palette_fake.cc
index dc0ee76..dbbbf89 100644
--- a/libartpalette/system/palette_fake.cc
+++ b/libartpalette/system/palette_fake.cc
@@ -18,72 +18,113 @@
 
 #include <map>
 #include <mutex>
+#include <stdbool.h>
 
 #include <android-base/logging.h>
 #include <android-base/macros.h>  // For ATTRIBUTE_UNUSED
 
 #include "palette_system.h"
 
-enum PaletteStatus PaletteGetVersion(int32_t* version) {
-  *version = art::palette::kPaletteVersion;
-  return PaletteStatus::kOkay;
-}
-
 // Cached thread priority for testing. No thread priorities are ever affected.
 static std::mutex g_tid_priority_map_mutex;
 static std::map<int32_t, int32_t> g_tid_priority_map;
 
-enum PaletteStatus PaletteSchedSetPriority(int32_t tid, int32_t priority) {
+palette_status_t PaletteSchedSetPriority(int32_t tid, int32_t priority) {
   if (priority < art::palette::kMinManagedThreadPriority ||
       priority > art::palette::kMaxManagedThreadPriority) {
-    return PaletteStatus::kInvalidArgument;
+    return PALETTE_STATUS_INVALID_ARGUMENT;
   }
   std::lock_guard guard(g_tid_priority_map_mutex);
   g_tid_priority_map[tid] = priority;
-  return PaletteStatus::kOkay;
+  return PALETTE_STATUS_OK;
 }
 
-enum PaletteStatus PaletteSchedGetPriority(int32_t tid,
-                                           /*out*/int32_t* priority) {
+palette_status_t PaletteSchedGetPriority(int32_t tid,
+                                         /*out*/int32_t* priority) {
   std::lock_guard guard(g_tid_priority_map_mutex);
   if (g_tid_priority_map.find(tid) == g_tid_priority_map.end()) {
     g_tid_priority_map[tid] = art::palette::kNormalManagedThreadPriority;
   }
   *priority = g_tid_priority_map[tid];
-  return PaletteStatus::kOkay;
+  return PALETTE_STATUS_OK;
 }
 
-enum PaletteStatus PaletteWriteCrashThreadStacks(/*in*/ const char* stacks, size_t stacks_len) {
+palette_status_t PaletteWriteCrashThreadStacks(/*in*/ const char* stacks, size_t stacks_len) {
   LOG(INFO) << std::string_view(stacks, stacks_len);
-  return PaletteStatus::kOkay;
+  return PALETTE_STATUS_OK;
 }
 
-enum PaletteStatus PaletteTraceEnabled(/*out*/int32_t* enabled) {
-  *enabled = 0;
-  return PaletteStatus::kOkay;
+palette_status_t PaletteTraceEnabled(/*out*/bool* enabled) {
+  *enabled = false;
+  return PALETTE_STATUS_OK;
 }
 
-enum PaletteStatus PaletteTraceBegin(const char* name ATTRIBUTE_UNUSED) {
-  return PaletteStatus::kOkay;
+palette_status_t PaletteTraceBegin(const char* name ATTRIBUTE_UNUSED) {
+  return PALETTE_STATUS_OK;
 }
 
-enum PaletteStatus PaletteTraceEnd() {
-  return PaletteStatus::kOkay;
+palette_status_t PaletteTraceEnd() {
+  return PALETTE_STATUS_OK;
 }
 
-enum PaletteStatus PaletteTraceIntegerValue(const char* name ATTRIBUTE_UNUSED,
-                                            int32_t value ATTRIBUTE_UNUSED) {
-  return PaletteStatus::kOkay;
+palette_status_t PaletteTraceIntegerValue(const char* name ATTRIBUTE_UNUSED,
+                                          int32_t value ATTRIBUTE_UNUSED) {
+  return PALETTE_STATUS_OK;
 }
 
-enum PaletteStatus PaletteAshmemCreateRegion(const char* name ATTRIBUTE_UNUSED,
-                                             size_t size ATTRIBUTE_UNUSED,
-                                             int* fd) {
+palette_status_t PaletteAshmemCreateRegion(const char* name ATTRIBUTE_UNUSED,
+                                           size_t size ATTRIBUTE_UNUSED,
+                                           int* fd) {
   *fd = -1;
-  return PaletteStatus::kNotSupported;
+  return PALETTE_STATUS_NOT_SUPPORTED;
 }
 
-enum PaletteStatus PaletteAshmemSetProtRegion(int fd ATTRIBUTE_UNUSED,
-                                              int prot ATTRIBUTE_UNUSED) {
-  return PaletteStatus::kNotSupported;
+palette_status_t PaletteAshmemSetProtRegion(int fd ATTRIBUTE_UNUSED,
+                                            int prot ATTRIBUTE_UNUSED) {
+  return PALETTE_STATUS_NOT_SUPPORTED;
+}
+
+palette_status_t PaletteCreateOdrefreshStagingDirectory(const char** staging_dir) {
+  *staging_dir = nullptr;
+  return PALETTE_STATUS_NOT_SUPPORTED;
+}
+
+palette_status_t PaletteShouldReportDex2oatCompilation(bool* value) {
+  *value = false;
+  return PALETTE_STATUS_OK;
+}
+
+palette_status_t PaletteNotifyStartDex2oatCompilation(int source_fd ATTRIBUTE_UNUSED,
+                                                      int art_fd ATTRIBUTE_UNUSED,
+                                                      int oat_fd ATTRIBUTE_UNUSED,
+                                                      int vdex_fd ATTRIBUTE_UNUSED) {
+  return PALETTE_STATUS_OK;
+}
+
+palette_status_t PaletteNotifyEndDex2oatCompilation(int source_fd ATTRIBUTE_UNUSED,
+                                                    int art_fd ATTRIBUTE_UNUSED,
+                                                    int oat_fd ATTRIBUTE_UNUSED,
+                                                    int vdex_fd ATTRIBUTE_UNUSED) {
+  return PALETTE_STATUS_OK;
+}
+
+palette_status_t PaletteNotifyDexFileLoaded(const char* path ATTRIBUTE_UNUSED) {
+  return PALETTE_STATUS_OK;
+}
+
+palette_status_t PaletteNotifyOatFileLoaded(const char* path ATTRIBUTE_UNUSED) {
+  return PALETTE_STATUS_OK;
+}
+
+palette_status_t PaletteShouldReportJniInvocations(bool* value) {
+  *value = false;
+  return PALETTE_STATUS_OK;
+}
+
+palette_status_t PaletteNotifyBeginJniInvocation(JNIEnv* env ATTRIBUTE_UNUSED) {
+  return PALETTE_STATUS_OK;
+}
+
+palette_status_t PaletteNotifyEndJniInvocation(JNIEnv* env ATTRIBUTE_UNUSED) {
+  return PALETTE_STATUS_OK;
 }
diff --git a/libartpalette/system/palette_system.h b/libartpalette/system/palette_system.h
index b28e00d..c4137e6 100644
--- a/libartpalette/system/palette_system.h
+++ b/libartpalette/system/palette_system.h
@@ -22,8 +22,6 @@
 namespace art {
 namespace palette {
 
-static constexpr int32_t kPaletteVersion = 1;
-
 // Managed thread definitions
 static constexpr int32_t kNormalManagedThreadPriority = 5;
 static constexpr int32_t kMinManagedThreadPriority = 1;
diff --git a/libartservice/api/current.txt b/libartservice/api/current.txt
new file mode 100644
index 0000000..c7844e0
--- /dev/null
+++ b/libartservice/api/current.txt
@@ -0,0 +1,9 @@
+// Signature format: 2.0
+package com.android.server.art {
+
+  public final class ArtManagerLocal {
+    ctor public ArtManagerLocal();
+  }
+
+}
+
diff --git a/libartservice/api/removed.txt b/libartservice/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/libartservice/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/libartservice/api/system-server-current.txt b/libartservice/api/system-server-current.txt
new file mode 100644
index 0000000..c7844e0
--- /dev/null
+++ b/libartservice/api/system-server-current.txt
@@ -0,0 +1,9 @@
+// Signature format: 2.0
+package com.android.server.art {
+
+  public final class ArtManagerLocal {
+    ctor public ArtManagerLocal();
+  }
+
+}
+
diff --git a/libartservice/api/system-server-removed.txt b/libartservice/api/system-server-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/libartservice/api/system-server-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 86e8170..31cf197 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "libdexfile_defaults",
     defaults: ["art_defaults"],
@@ -37,14 +46,25 @@
         "dex/type_lookup_table.cc",
         "dex/utf.cc",
     ],
-
+    header_libs: [
+        "jni_headers",
+        "libdexfile_external_headers",
+    ],
+    export_header_lib_headers: [
+        "jni_headers",
+        "libdexfile_external_headers",
+    ],
     target: {
         android: {
+            srcs: [
+                "external/dex_file_ext.cc",
+            ],
             static_libs: [
                 "libziparchive",
-                "libz",
             ],
             shared_libs: [
+                // libz provides a stub from platform, shouldn't be statically linked
+                "libz",
                 // For MemMap.
                 "libartpalette",
                 "liblog",
@@ -56,6 +76,9 @@
             ],
         },
         not_windows: {
+            srcs: [
+                "external/dex_file_ext.cc",
+            ],
             shared_libs: [
                 "libziparchive",
                 "libz",
@@ -94,7 +117,7 @@
 
 cc_defaults {
     name: "libdexfile_static_base_defaults",
-    static_libs: [
+    whole_static_libs: [
         "libbase",
         "liblog",
         "libz",
@@ -111,7 +134,7 @@
     defaults_visibility: [
         "//art:__subpackages__",
     ],
-    static_libs: ["libdexfile"],
+    whole_static_libs: ["libdexfile"],
 }
 
 cc_defaults {
@@ -120,7 +143,7 @@
         "libartbased_static_defaults",
         "libdexfile_static_base_defaults",
     ],
-    static_libs: ["libdexfiled"],
+    whole_static_libs: ["libdexfiled"],
 }
 
 gensrcs {
@@ -133,7 +156,6 @@
         "dex/dex_instruction.h",
         "dex/dex_instruction_utils.h",
         "dex/invoke_type.h",
-        "dex/method_reference.h",
     ],
     output_extension: "operator_out.cc",
 }
@@ -175,9 +197,13 @@
         },
     },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
+    stubs: {
+        symbol_file: "libdexfile.map.txt",
+        versions: ["1"],
+    },
 }
 
 art_cc_library {
@@ -218,14 +244,15 @@
     },
     apex_available: [
         "com.android.art.debug",
+        // TODO(b/183882457): This lib doesn't go into com.android.art, but
+        // apex_available lists need to be the same for internal libs to avoid
+        // stubs, and libartd depends on this.
+        "com.android.art",
     ],
 }
 
-art_cc_test {
-    name: "art_libdexfile_tests",
-    defaults: [
-        "art_gtest_defaults",
-    ],
+art_cc_defaults {
+    name: "art_libdexfile_tests_defaults",
     srcs: [
         "dex/art_dex_file_loader_test.cc",
         "dex/class_accessor_test.cc",
@@ -242,12 +269,40 @@
         "dex/type_lookup_table_test.cc",
         "dex/utf_test.cc",
     ],
+    data: [
+        ":art-gtest-jars-GetMethodSignature",
+        ":art-gtest-jars-Lookup",
+        ":art-gtest-jars-Main",
+        ":art-gtest-jars-MultiDex",
+        ":art-gtest-jars-Nested",
+    ],
+    header_libs: ["jni_headers"],
     shared_libs: [
         "libbacktrace",
         "libziparchive",
     ],
 }
 
+// Version of ART gtest `art_libdexfile_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
+art_cc_test {
+    name: "art_libdexfile_tests",
+    defaults: [
+        "art_gtest_defaults",
+        "art_libdexfile_tests_defaults",
+    ],
+}
+
+// Standalone version of ART gtest `art_libdexfile_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_libdexfile_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_libdexfile_tests_defaults",
+    ],
+    test_config: "art_standalone_libdexfile_tests.xml",
+}
+
 cc_library_headers {
     name: "libdexfile_external_headers",
     visibility: ["//visibility:public"],
@@ -264,9 +319,12 @@
 
     apex_available: [
         "//apex_available:platform",
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
+        "com.android.media",
+        "com.android.runtime",
     ],
+    min_sdk_version: "S",
 }
 
 // Make dex_instruction_list.h available for tools/jvmti-agents/titrace
@@ -277,183 +335,221 @@
     export_include_dirs: ["."],
 
     apex_available: [
-        "com.android.art.debug",
-        "com.android.art.release",
-    ],
-}
-
-cc_defaults {
-    name: "libdexfile_external-defaults",
-    host_supported: true,
-    srcs: [
-        "external/dex_file_ext.cc",
-    ],
-    header_libs: ["libdexfile_external_headers"],
-    shared_libs: [
-        "libbase",
-    ],
-    stubs: {
-        symbol_file: "external/libdexfile_external.map.txt",
-        versions: ["1"],
-    },
-    export_header_lib_headers: ["libdexfile_external_headers"],
-}
-
-cc_library {
-    name: "libdexfile_external",
-    defaults: [
-        "art_defaults",
-        "libdexfile_external-defaults",
-    ],
-    visibility: ["//visibility:public"],
-    target: {
-        darwin: {
-            enabled: true,
-        },
-    },
-    shared_libs: [
-        "libdexfile",
-    ],
-    apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
-}
-
-cc_library {
-    name: "libdexfiled_external",
-    defaults: [
-        "art_debug_defaults",
-        "libdexfile_external-defaults",
-    ],
-    target: {
-        darwin: {
-            enabled: true,
-        },
-    },
-    shared_libs: [
-        "libdexfiled",
-    ],
-    apex_available: [
-        "com.android.art.debug",
-    ],
+    min_sdk_version: "S",
 }
 
 art_cc_test {
     name: "art_libdexfile_external_tests",
-    host_supported: true,
-    test_per_src: true, // For consistency with other ART gtests.
+    defaults: [
+        "art_module_source_build_defaults",
+        "art_test_defaults",
+    ],
+    test_suites: ["general-tests"],
     srcs: [
         "external/dex_file_ext_c_test.c",
+        "external/dex_file_ext_test.cc",
     ],
-    header_libs: ["libdexfile_external_headers"],
+    shared_libs: [
+        "libartbase",
+        "libdexfile",
+    ],
+    header_libs: [
+        "jni_headers",
+        "libdexfile_external_headers",
+    ],
 }
 
 // Support library with a C++ API for accessing the libdexfile API for external
 // (non-ART) users.
 //
-// This library dlopens libdexfile_external on first use, so there is no build
-// time dependency on dex file logic. It is therefore safe to use from binaries
+// This library dlopens libdexfile(d).so on first use, so there is no build time
+// dependency on dex file logic. It is therefore safe to use from binaries
 // compiled without dex file support, given they won't encounter any dex file
 // stack frames.
-cc_library {
+art_cc_library_static {
     name: "libdexfile_support",
     visibility: ["//visibility:public"],
     host_supported: true,
     srcs: [
         "external/dex_file_supp.cc",
     ],
-    runtime_libs: ["libdexfile_external"],
-    shared_libs: ["liblog"],
+    runtime_libs: ["libdexfile"],
+    shared_libs: [
+        "liblog",
+        "libbase",
+    ],
     header_libs: ["libdexfile_external_headers"],
     export_header_lib_headers: ["libdexfile_external_headers"],
 
     apex_available: [
         "//apex_available:platform",
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
+        "com.android.media",
+        "com.android.media.swcodec",
+        "com.android.runtime",
     ],
+    min_sdk_version: "S",
 }
 
-// The same source file is used in two tests here, so unlike other ART gtests it
-// doesn't use test_per_src. Its test target is
-// test-art-{host,target}-gtest-art_libdexfile_support_tests.
-art_cc_test {
-    name: "art_libdexfile_support_tests",
+art_cc_defaults {
+    name: "art_libdexfile_support_tests_defaults",
     defaults: [
-        "art_test_defaults",
+        "art_module_source_build_defaults",
     ],
-    host_supported: true,
+    test_suites: ["general-tests"],
     srcs: [
         "external/dex_file_supp_test.cc",
     ],
     shared_libs: [
         "libartbase",
         "libbase",
-        "libdexfile_external",
+        "libdexfile",
+        "liblog",
+    ],
+    static_libs: [
         "libdexfile_support",
     ],
 }
 
-cc_defaults {
-    name: "libdexfile_support_static_defaults",
+// Version of ART gtest `art_libdexfile_support_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
+art_cc_test {
+    name: "art_libdexfile_support_tests",
+    host_supported: true,
+    defaults: [
+        "art_test_defaults",
+        "art_libdexfile_support_tests_defaults",
+    ],
+}
+
+// Standalone version of ART gtest `art_libdexfile_support_tests`, not bundled with the ART APEX on
+// target.
+art_cc_test {
+    name: "art_standalone_libdexfile_support_tests",
+    defaults: [
+        "art_standalone_test_defaults",
+        "art_libdexfile_support_tests_defaults",
+    ],
+
+    // Support multilib variants (using different suffix per sub-architecture), which is needed on
+    // build targets with secondary architectures, as the MTS test suite packaging logic flattens
+    // all test artifacts into a single `testcases` directory.
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+
+    test_suites: [
+        "mts-art",
+    ],
+}
+
+cc_library_static {
+    name: "libdexfile_support_static",
     host_supported: true,
     srcs: [
         "external/dex_file_supp.cc",
     ],
     cflags: ["-DSTATIC_LIB"],
-    // Using whole_static_libs here only as a "poor man's transitivity" kludge.
-    whole_static_libs: [
-        "libbase",
-        "liblog",
-        "libz",
-        "libziparchive",
-    ],
     header_libs: ["libdexfile_external_headers"],
     export_header_lib_headers: ["libdexfile_external_headers"],
 }
 
-cc_library_static {
-    name: "libdexfile_support_static",
-    visibility: [
-        "//art:__subpackages__",
-        // Required for the simpleperf binary in the NDK. No other modules than
-        // //system/extras/simpleperf:simpleperf_ndk are allowed to use it.
-        "//system/extras/simpleperf",
-    ],
+cc_defaults {
+    name: "libdexfile_support_static_defaults",
     defaults: [
         "libdexfile_static_defaults",
-        "libdexfile_support_static_defaults",
     ],
     whole_static_libs: [
         "libdexfile",
-        "libdexfile_external",
+        "libdexfile_support_static",
     ],
 }
 
-cc_library_static {
-    name: "libdexfiled_support_static",
+cc_defaults {
+    name: "libdexfiled_support_static_defaults",
     defaults: [
-        "libdexfile_support_static_defaults",
         "libdexfiled_static_defaults",
     ],
     whole_static_libs: [
         "libdexfiled",
-        "libdexfiled_external",
+        "libdexfile_support_static",
     ],
 }
 
-// The same source file is used in two tests here, so unlike other ART gtests it
-// doesn't use test_per_src. Its test target is
-// test-art-{host,target}-gtest-art_libdexfile_support_static_tests.
 art_cc_test {
     name: "art_libdexfile_support_static_tests",
+    test_suites: ["general-tests"],
+    defaults: [
+        "art_module_source_build_defaults",
+        "art_test_defaults",
+        "libdexfile_support_static_defaults",
+    ],
+    srcs: [
+        "external/dex_file_supp_test.cc",
+    ],
+}
+
+// For use by external packages allowed to link in static libdexfile_support.
+// This is not allowed in any module that may end up in an APEX or platform
+// image, so visibility is restrictive.
+cc_library_static {
+    name: "libdexfile_static",
     host_supported: true,
+    visibility: [
+        // Required for simpleperf, libsimpleperf_record, and libsimpleperf_report
+        // in the NDK.
+        "//system/extras/simpleperf",
+        "//cts/tests/tests/simpleperf",
+    ],
+    // Using libdexfile_support_static_defaults will link in external libs like
+    // libbase and libz statically as well, which are likely to cause duplicate
+    // copies in the depending module.
+    // TODO(b/169885605): Avoid exposing symbols from those libs.
+    defaults: [
+        "art_defaults",
+        "libdexfile_support_static_defaults",
+    ],
+}
+
+art_cc_test {
+    name: "art_libdexfile_static_tests",
+    defaults: ["art_test_defaults"],
+    test_suites: ["general-tests"],
     srcs: [
         "external/dex_file_supp_test.cc",
     ],
     static_libs: [
-        "libbase",
-        "libdexfile_support_static",
+        "libdexfile_static",
     ],
+    enabled: false,
+    target: {
+        linux: {
+            enabled: true,
+        },
+    },
+    // TODO(b/181740144): Enable a ubsan check to create a dependency on
+    // ubsan_minimal. It's needed to be able to link with the prebuilt
+    // libdexfile_static.a, which contains libziparchive.a, which is
+    // built with some ubsan checks
+    // (https://cs.android.com/android/platform/superproject/+/master:system/libziparchive/Android.bp;l=47-59;drc=c7b498fdf2002194709e40ea58ce39f43684fc14)
+    // that the SDK snapshots currently don't propagate properly for static
+    // libs.
+    sanitize: {
+        misc_undefined: ["shift"],
+    },
+}
+
+filegroup {
+    name: "art_libdexfile_dex_instruction_list_header",
+    srcs: ["dex/dex_instruction_list.h"],
 }
diff --git a/libdexfile/art_standalone_libdexfile_tests.xml b/libdexfile/art_standalone_libdexfile_tests.xml
new file mode 100644
index 0000000..57987fd
--- /dev/null
+++ b/libdexfile/art_standalone_libdexfile_tests.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs art_standalone_libdexfile_tests.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art_standalone_libdexfile_tests->/data/local/tmp/nativetest/art_standalone_libdexfile_tests" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art-gtest-jars-GetMethodSignature.jar->/data/local/tmp/nativetest/art-gtest-jars-GetMethodSignature.jar" />
+        <option name="push" value="art-gtest-jars-Lookup.jar->/data/local/tmp/nativetest/art-gtest-jars-Lookup.jar" />
+        <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/nativetest/art-gtest-jars-Main.jar" />
+        <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/nativetest/art-gtest-jars-MultiDex.jar" />
+        <option name="push" value="art-gtest-jars-Nested.jar->/data/local/tmp/nativetest/art-gtest-jars-Nested.jar" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/nativetest" />
+        <option name="module-name" value="art_standalone_libdexfile_tests" />
+        <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+        <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/libdexfile/dex/art_dex_file_loader.cc b/libdexfile/dex/art_dex_file_loader.cc
index d17c61e..62014aa 100644
--- a/libdexfile/dex/art_dex_file_loader.cc
+++ b/libdexfile/dex/art_dex_file_loader.cc
@@ -86,6 +86,7 @@
 
 bool ArtDexFileLoader::GetMultiDexChecksums(const char* filename,
                                             std::vector<uint32_t>* checksums,
+                                            std::vector<std::string>* dex_locations,
                                             std::string* error_msg,
                                             int zip_fd,
                                             bool* zip_file_only_contains_uncompressed_dex) const {
@@ -113,8 +114,8 @@
       return false;
     }
 
-    uint32_t i = 0;
-    std::string zip_entry_name = GetMultiDexClassesDexName(i++);
+    uint32_t idx = 0;
+    std::string zip_entry_name = GetMultiDexClassesDexName(idx);
     std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(zip_entry_name.c_str(), error_msg));
     if (zip_entry.get() == nullptr) {
       *error_msg = StringPrintf("Zip archive '%s' doesn't contain %s (error msg: %s)", filename,
@@ -134,7 +135,8 @@
         }
       }
       checksums->push_back(zip_entry->GetCrc32());
-      zip_entry_name = GetMultiDexClassesDexName(i++);
+      dex_locations->push_back(GetMultiDexLocation(idx, filename));
+      zip_entry_name = GetMultiDexClassesDexName(++idx);
       zip_entry.reset(zip_archive->Find(zip_entry_name.c_str(), error_msg));
     } while (zip_entry.get() != nullptr);
     return true;
@@ -250,6 +252,18 @@
   return OpenWithMagic(magic, fd, location, verify, verify_checksum, error_msg, dex_files);
 }
 
+bool ArtDexFileLoader::Open(const char* filename,
+                            int fd,
+                            const std::string& location,
+                            bool verify,
+                            bool verify_checksum,
+                            std::string* error_msg,
+                            std::vector<std::unique_ptr<const DexFile>>* dex_files) const {
+  return fd == -1
+      ? Open(filename, location, verify, verify_checksum, error_msg, dex_files)
+      : Open(fd, location, verify, verify_checksum, error_msg, dex_files);
+}
+
 bool ArtDexFileLoader::OpenWithMagic(uint32_t magic,
                                      int fd,
                                      const std::string& location,
@@ -417,6 +431,10 @@
     }
   }
 
+  ScopedTrace map_extract_trace(StringPrintf("Mapped=%s Extracted=%s",
+      map.IsValid() ? "true" : "false",
+      map.IsValid() ? "false" : "true"));  // this is redundant but much easier to read in traces.
+
   if (!map.IsValid()) {
     // Default path for compressed ZIP entries,
     // and fallback for stored ZIP entries.
diff --git a/libdexfile/dex/art_dex_file_loader.h b/libdexfile/dex/art_dex_file_loader.h
index bf38527..786142a 100644
--- a/libdexfile/dex/art_dex_file_loader.h
+++ b/libdexfile/dex/art_dex_file_loader.h
@@ -46,9 +46,14 @@
   // the descriptor and `filename` will be used as alias for error logging. If
   // zip_fd is -1, the method will try to open the `filename` and read the
   // content from it.
+  //
+  // The dex_locations vector will be populated with the corresponding multidex
+  // locations.
+  //
   // Return true if the checksums could be found, false otherwise.
   bool GetMultiDexChecksums(const char* filename,
                             std::vector<uint32_t>* checksums,
+                            std::vector<std::string>* dex_locations,
                             std::string* error_msg,
                             int zip_fd = -1,
                             bool* only_contains_uncompressed_dex = nullptr) const override;
@@ -86,6 +91,16 @@
             bool verify_checksum,
             std::string* error_msg,
             std::vector<std::unique_ptr<const DexFile>>* dex_files) const;
+  // Opens all .dex files found in the file, guessing the container format based on file magic.
+  // If the fd is -1 then the dex files are opened using the filename; otherwise they are
+  // opened using the fd.
+  bool Open(const char* filename,
+            int fd,
+            const std::string& location,
+            bool verify,
+            bool verify_checksum,
+            std::string* error_msg,
+            std::vector<std::unique_ptr<const DexFile>>* dex_files) const;
 
   // Open a single dex file from an fd. This function closes the fd.
   std::unique_ptr<const DexFile> OpenDex(int fd,
diff --git a/libdexfile/dex/art_dex_file_loader_test.cc b/libdexfile/dex/art_dex_file_loader_test.cc
index be1221c..1863c1b 100644
--- a/libdexfile/dex/art_dex_file_loader_test.cc
+++ b/libdexfile/dex/art_dex_file_loader_test.cc
@@ -64,33 +64,42 @@
 
 TEST_F(ArtDexFileLoaderTest, GetChecksum) {
   std::vector<uint32_t> checksums;
+  std::vector<std::string> dex_locations;
   std::string error_msg;
   const ArtDexFileLoader dex_file_loader;
   EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(GetLibCoreDexFileNames()[0].c_str(),
-                                                    &checksums,
-                                                    &error_msg))
+                                                   &checksums,
+                                                   &dex_locations,
+                                                   &error_msg))
       << error_msg;
   ASSERT_EQ(1U, checksums.size());
+  ASSERT_EQ(1U, dex_locations.size());
   EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksums[0]);
+  EXPECT_EQ(java_lang_dex_file_->GetLocation(), dex_locations[0]);
 }
 
 TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksums) {
   std::string error_msg;
   std::vector<uint32_t> checksums;
+  std::vector<std::string> dex_locations;
   std::string multidex_file = GetTestDexFileName("MultiDex");
   const ArtDexFileLoader dex_file_loader;
   EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(multidex_file.c_str(),
-                                                    &checksums,
-                                                    &error_msg)) << error_msg;
+                                                   &checksums,
+                                                   &dex_locations,
+                                                   &error_msg)) << error_msg;
 
   std::vector<std::unique_ptr<const DexFile>> dexes = OpenTestDexFiles("MultiDex");
   ASSERT_EQ(2U, dexes.size());
   ASSERT_EQ(2U, checksums.size());
+  ASSERT_EQ(2U, dex_locations.size());
 
   EXPECT_EQ(dexes[0]->GetLocation(), DexFileLoader::GetMultiDexLocation(0, multidex_file.c_str()));
+  EXPECT_EQ(dexes[0]->GetLocation(), dex_locations[0]);
   EXPECT_EQ(dexes[0]->GetLocationChecksum(), checksums[0]);
 
   EXPECT_EQ(dexes[1]->GetLocation(), DexFileLoader::GetMultiDexLocation(1, multidex_file.c_str()));
+  EXPECT_EQ(dexes[1]->GetLocation(), dex_locations[1]);
   EXPECT_EQ(dexes[1]->GetLocationChecksum(), checksums[1]);
 }
 
diff --git a/libdexfile/dex/compact_dex_file.h b/libdexfile/dex/compact_dex_file.h
index 47edd51..9c3b7a4 100644
--- a/libdexfile/dex/compact_dex_file.h
+++ b/libdexfile/dex/compact_dex_file.h
@@ -27,6 +27,7 @@
 class CompactDexFile : public DexFile {
  public:
   static constexpr uint8_t kDexMagic[kDexMagicSize] = { 'c', 'd', 'e', 'x' };
+  // Last change: remove code item deduping.
   static constexpr uint8_t kDexMagicVersion[] = {'0', '0', '1', '\0'};
 
   enum class FeatureFlags : uint32_t {
@@ -89,24 +90,41 @@
     // Max preheader size in uint16_ts.
     static constexpr size_t kMaxPreHeaderSize = 6;
 
-   private:
-    CodeItem() = default;
+    static constexpr size_t FieldsOffset() {
+      return OFFSETOF_MEMBER(CodeItem, fields_);
+    }
+
+    static constexpr size_t InsnsCountAndFlagsOffset() {
+      return OFFSETOF_MEMBER(CodeItem, insns_count_and_flags_);
+    }
+
+    static constexpr size_t InsnsOffset() {
+      return OFFSETOF_MEMBER(CodeItem, insns_);
+    }
 
     static constexpr size_t kRegistersSizeShift = 12;
     static constexpr size_t kInsSizeShift = 8;
     static constexpr size_t kOutsSizeShift = 4;
     static constexpr size_t kTriesSizeSizeShift = 0;
-    static constexpr uint16_t kFlagPreHeaderRegisterSize = 0x1 << 0;
-    static constexpr uint16_t kFlagPreHeaderInsSize = 0x1 << 1;
-    static constexpr uint16_t kFlagPreHeaderOutsSize = 0x1 << 2;
-    static constexpr uint16_t kFlagPreHeaderTriesSize = 0x1 << 3;
-    static constexpr uint16_t kFlagPreHeaderInsnsSize = 0x1 << 4;
+    static constexpr uint16_t kBitPreHeaderRegistersSize = 0;
+    static constexpr uint16_t kBitPreHeaderInsSize = 1;
+    static constexpr uint16_t kBitPreHeaderOutsSize = 2;
+    static constexpr uint16_t kBitPreHeaderTriesSize = 3;
+    static constexpr uint16_t kBitPreHeaderInsnsSize = 4;
+    static constexpr uint16_t kFlagPreHeaderRegistersSize = 0x1 << kBitPreHeaderRegistersSize;
+    static constexpr uint16_t kFlagPreHeaderInsSize = 0x1 << kBitPreHeaderInsSize;
+    static constexpr uint16_t kFlagPreHeaderOutsSize = 0x1 << kBitPreHeaderOutsSize;
+    static constexpr uint16_t kFlagPreHeaderTriesSize = 0x1 << kBitPreHeaderTriesSize;
+    static constexpr uint16_t kFlagPreHeaderInsnsSize = 0x1 << kBitPreHeaderInsnsSize;
     static constexpr size_t kInsnsSizeShift = 5;
     static constexpr size_t kInsnsSizeBits = sizeof(uint16_t) * kBitsPerByte -  kInsnsSizeShift;
 
+   private:
+    CodeItem() = default;
+
     // Combined preheader flags for fast testing if we need to go slow path.
     static constexpr uint16_t kFlagPreHeaderCombined =
-        kFlagPreHeaderRegisterSize |
+        kFlagPreHeaderRegistersSize |
         kFlagPreHeaderInsSize |
         kFlagPreHeaderOutsSize |
         kFlagPreHeaderTriesSize |
@@ -154,7 +172,7 @@
           *out_preheader = size;
         }
       };
-      preheader_encode(registers_size, kFlagPreHeaderRegisterSize);
+      preheader_encode(registers_size, kFlagPreHeaderRegistersSize);
       preheader_encode(ins_size, kFlagPreHeaderInsSize);
       preheader_encode(outs_size, kFlagPreHeaderOutsSize);
       preheader_encode(tries_size, kFlagPreHeaderTriesSize);
@@ -203,7 +221,7 @@
           *insns_count += static_cast<uint32_t>(*preheader) << 16;
         }
         if (!kDecodeOnlyInstructionCount) {
-          if (HasPreHeader(kFlagPreHeaderRegisterSize)) {
+          if (HasPreHeader(kFlagPreHeaderRegistersSize)) {
             --preheader;
             *registers_size += preheader[0];
           }
diff --git a/libdexfile/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h
index 61c4593..0e1fb68 100644
--- a/libdexfile/dex/dex_file-inl.h
+++ b/libdexfile/dex/dex_file-inl.h
@@ -130,6 +130,10 @@
   return StringDataAndUtf16LengthByIdx(method_id.name_idx_, utf_length);
 }
 
+inline const char* DexFile::GetMethodName(uint32_t idx) const {
+  return StringDataByIdx(GetMethodId(idx).name_idx_);
+}
+
 inline const char* DexFile::GetMethodName(uint32_t idx, uint32_t* utf_length) const {
   return StringDataAndUtf16LengthByIdx(GetMethodId(idx).name_idx_, utf_length);
 }
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 030b43b..dc5f27e 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -225,16 +225,23 @@
   return nullptr;
 }
 
-uint32_t DexFile::FindCodeItemOffset(const ClassDef& class_def, uint32_t method_idx) const {
+std::optional<uint32_t> DexFile::GetCodeItemOffset(const ClassDef &class_def,
+                                                   uint32_t method_idx) const {
   ClassAccessor accessor(*this, class_def);
   CHECK(accessor.HasClassData());
-  for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+  for (const ClassAccessor::Method &method : accessor.GetMethods()) {
     if (method.GetIndex() == method_idx) {
       return method.GetCodeItemOffset();
     }
   }
-  LOG(FATAL) << "Unable to find method " << method_idx;
-  UNREACHABLE();
+  return std::nullopt;
+}
+
+uint32_t DexFile::FindCodeItemOffset(const dex::ClassDef &class_def,
+                                     uint32_t dex_method_idx) const {
+  std::optional<uint32_t> val = GetCodeItemOffset(class_def, dex_method_idx);
+  CHECK(val.has_value()) << "Unable to find method " << dex_method_idx;
+  return *val;
 }
 
 const FieldId* DexFile::FindFieldId(const TypeId& declaring_klass,
@@ -279,6 +286,13 @@
   const dex::TypeIndex class_idx = GetIndexForTypeId(declaring_klass);
   const dex::StringIndex name_idx = GetIndexForStringId(name);
   const dex::ProtoIndex proto_idx = GetIndexForProtoId(signature);
+  return FindMethodIdByIndex(class_idx, name_idx, proto_idx);
+}
+
+const MethodId* DexFile::FindMethodIdByIndex(dex::TypeIndex class_idx,
+                                             dex::StringIndex name_idx,
+                                             dex::ProtoIndex proto_idx) const {
+  // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
   int32_t lo = 0;
   int32_t hi = NumMethodIds() - 1;
   while (hi >= lo) {
@@ -299,6 +313,9 @@
         } else if (proto_idx < method.proto_idx_) {
           hi = mid - 1;
         } else {
+          DCHECK_EQ(class_idx, method.class_idx_);
+          DCHECK_EQ(proto_idx, method.proto_idx_);
+          DCHECK_EQ(name_idx, method.name_idx_);
           return &method;
         }
       }
@@ -519,34 +536,35 @@
   return val;
 }
 
-std::string DexFile::PrettyMethod(uint32_t method_idx, bool with_signature) const {
+void DexFile::AppendPrettyMethod(uint32_t method_idx,
+                                 bool with_signature,
+                                 std::string* const result) const {
   if (method_idx >= NumMethodIds()) {
-    return StringPrintf("<<invalid-method-idx-%d>>", method_idx);
+    android::base::StringAppendF(result, "<<invalid-method-idx-%d>>", method_idx);
+    return;
   }
   const MethodId& method_id = GetMethodId(method_idx);
-  std::string result;
   const ProtoId* proto_id = with_signature ? &GetProtoId(method_id.proto_idx_) : nullptr;
   if (with_signature) {
-    AppendPrettyDescriptor(StringByTypeIdx(proto_id->return_type_idx_), &result);
-    result += ' ';
+    AppendPrettyDescriptor(StringByTypeIdx(proto_id->return_type_idx_), result);
+    result->push_back(' ');
   }
-  AppendPrettyDescriptor(GetMethodDeclaringClassDescriptor(method_id), &result);
-  result += '.';
-  result += GetMethodName(method_id);
+  AppendPrettyDescriptor(GetMethodDeclaringClassDescriptor(method_id), result);
+  result->push_back('.');
+  result->append(GetMethodName(method_id));
   if (with_signature) {
-    result += '(';
+    result->push_back('(');
     const TypeList* params = GetProtoParameters(*proto_id);
     if (params != nullptr) {
       const char* separator = "";
       for (uint32_t i = 0u, size = params->Size(); i != size; ++i) {
-        result += separator;
+        result->append(separator);
         separator = ", ";
-        AppendPrettyDescriptor(StringByTypeIdx(params->GetTypeItem(i).type_idx_), &result);
+        AppendPrettyDescriptor(StringByTypeIdx(params->GetTypeItem(i).type_idx_), result);
       }
     }
-    result += ')';
+    result->push_back(')');
   }
-  return result;
 }
 
 std::string DexFile::PrettyField(uint32_t field_idx, bool with_type) const {
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index ca95e0e..5363b00 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -18,6 +18,7 @@
 #define ART_LIBDEXFILE_DEX_DEX_FILE_H_
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <vector>
@@ -77,14 +78,14 @@
   static constexpr size_t kDexVersionLen = 4;
 
   // First Dex format version enforcing class definition ordering rules.
-  static const uint32_t kClassDefinitionOrderEnforcedVersion = 37;
+  static constexpr uint32_t kClassDefinitionOrderEnforcedVersion = 37;
 
   static constexpr size_t kSha1DigestSize = 20;
   static constexpr uint32_t kDexEndianConstant = 0x12345678;
 
   // The value of an invalid index.
-  static const uint16_t kDexNoIndex16 = 0xFFFF;
-  static const uint32_t kDexNoIndex32 = 0xFFFFFFFF;
+  static constexpr uint16_t kDexNoIndex16 = 0xFFFF;
+  static constexpr uint32_t kDexNoIndex32 = 0xFFFFFFFF;
 
   // Raw header_item.
   struct Header {
@@ -271,6 +272,9 @@
   const dex::StringId* FindStringId(const char* string) const;
 
   const dex::TypeId* FindTypeId(const char* string) const;
+  const dex::TypeId* FindTypeId(std::string_view string) const {
+    return FindTypeId(std::string(string).c_str());
+  }
 
   // Returns the number of type identifiers in the .dex file.
   uint32_t NumTypeIds() const {
@@ -330,6 +334,13 @@
                                   const dex::StringId& name,
                                   const dex::TypeId& type) const;
 
+  // Return the code-item offset associated with the class and method or nullopt
+  // if the method does not exist or has no code.
+  std::optional<uint32_t> GetCodeItemOffset(const dex::ClassDef& class_def,
+                                            uint32_t dex_method_idx) const;
+
+  // Return the code-item offset associated with the class and method or
+  // LOG(FATAL) if the method does not exist or has no code.
   uint32_t FindCodeItemOffset(const dex::ClassDef& class_def,
                               uint32_t dex_method_idx) const;
 
@@ -370,6 +381,10 @@
                                     const dex::StringId& name,
                                     const dex::ProtoId& signature) const;
 
+  const dex::MethodId* FindMethodIdByIndex(dex::TypeIndex declaring_klass,
+                                           dex::StringIndex name,
+                                           dex::ProtoIndex signature) const;
+
   // Returns the declaring class descriptor string of a method id.
   const char* GetMethodDeclaringClassDescriptor(const dex::MethodId& method_id) const;
 
@@ -387,6 +402,7 @@
   // Returns the name of a method id.
   const char* GetMethodName(const dex::MethodId& method_id) const;
   const char* GetMethodName(const dex::MethodId& method_id, uint32_t* utf_length) const;
+  const char* GetMethodName(uint32_t idx) const;
   const char* GetMethodName(uint32_t idx, uint32_t* utf_length) const;
 
   // Returns the shorty of a method by its index.
@@ -746,13 +762,19 @@
   // when computing the adler32 checksum of the entire file.
   static constexpr uint32_t kNumNonChecksumBytes = OFFSETOF_MEMBER(DexFile::Header, signature_);
 
-  // Returns a human-readable form of the method at an index.
-  std::string PrettyMethod(uint32_t method_idx, bool with_signature = true) const;
+  // Appends a human-readable form of the method at an index.
+  void AppendPrettyMethod(uint32_t method_idx, bool with_signature, std::string* result) const;
   // Returns a human-readable form of the field at an index.
   std::string PrettyField(uint32_t field_idx, bool with_type = true) const;
   // Returns a human-readable form of the type at an index.
   std::string PrettyType(dex::TypeIndex type_idx) const;
 
+  ALWAYS_INLINE std::string PrettyMethod(uint32_t method_idx, bool with_signature = true) const {
+    std::string result;
+    AppendPrettyMethod(method_idx, with_signature, &result);
+    return result;
+  }
+
   // Not virtual for performance reasons.
   ALWAYS_INLINE bool IsCompactDexFile() const {
     return is_compact_dex_;
@@ -789,7 +811,7 @@
 
  protected:
   // First Dex format version supporting default methods.
-  static const uint32_t kDefaultMethodsVersion = 37;
+  static constexpr uint32_t kDefaultMethodsVersion = 37;
 
   DexFile(const uint8_t* base,
           size_t size,
@@ -963,7 +985,7 @@
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedArrayValueIterator);
 };
-std::ostream& operator<<(std::ostream& os, const EncodedArrayValueIterator::ValueType& code);
+std::ostream& operator<<(std::ostream& os, EncodedArrayValueIterator::ValueType code);
 
 class EncodedStaticFieldValueIterator : public EncodedArrayValueIterator {
  public:
@@ -976,7 +998,6 @@
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedStaticFieldValueIterator);
 };
-std::ostream& operator<<(std::ostream& os, const EncodedStaticFieldValueIterator::ValueType& code);
 
 class CallSiteArrayValueIterator : public EncodedArrayValueIterator {
  public:
@@ -991,7 +1012,6 @@
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(CallSiteArrayValueIterator);
 };
-std::ostream& operator<<(std::ostream& os, const CallSiteArrayValueIterator::ValueType& code);
 
 }  // namespace art
 
diff --git a/libdexfile/dex/dex_file_layout.h b/libdexfile/dex/dex_file_layout.h
index 183aefa..8ee91ff 100644
--- a/libdexfile/dex/dex_file_layout.h
+++ b/libdexfile/dex/dex_file_layout.h
@@ -45,7 +45,7 @@
   // Unused value, just the number of elements in the enum.
   kLayoutTypeCount,
 };
-std::ostream& operator<<(std::ostream& os, const LayoutType& collector_type);
+std::ostream& operator<<(std::ostream& os, LayoutType collector_type);
 
 // Return the "best" layout option if the same item has multiple different layouts.
 static inline LayoutType MergeLayoutType(LayoutType a, LayoutType b) {
@@ -60,7 +60,7 @@
   // Trim by madvising code that is unlikely to be too important in the future.
   kMadviseStateFinishedTrim,
 };
-std::ostream& operator<<(std::ostream& os, const MadviseState& collector_type);
+std::ostream& operator<<(std::ostream& os, MadviseState collector_type);
 
 // A dex layout section such as code items or strings. Each section is composed of subsections
 // that are laid out adjacently to each other such as (hot, unused, startup, etc...).
@@ -118,7 +118,7 @@
   DexLayoutSection sections_[static_cast<size_t>(SectionType::kSectionCount)];
 };
 
-std::ostream& operator<<(std::ostream& os, const DexLayoutSections::SectionType& collector_type);
+std::ostream& operator<<(std::ostream& os, DexLayoutSections::SectionType collector_type);
 std::ostream& operator<<(std::ostream& os, const DexLayoutSection& section);
 std::ostream& operator<<(std::ostream& os, const DexLayoutSections& sections);
 
diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc
index 7ccc93f..861f911 100644
--- a/libdexfile/dex/dex_file_loader.cc
+++ b/libdexfile/dex/dex_file_loader.cc
@@ -211,6 +211,7 @@
 bool DexFileLoader::GetMultiDexChecksums(
     const char* filename ATTRIBUTE_UNUSED,
     std::vector<uint32_t>* checksums ATTRIBUTE_UNUSED,
+    std::vector<std::string>* dex_locations ATTRIBUTE_UNUSED,
     std::string* error_msg,
     int zip_fd ATTRIBUTE_UNUSED,
     bool* zip_file_only_contains_uncompress_dex ATTRIBUTE_UNUSED) const {
@@ -219,6 +220,30 @@
 }
 
 std::unique_ptr<const DexFile> DexFileLoader::Open(
+    const std::string& location,
+    uint32_t location_checksum,
+    std::vector<uint8_t>&& memory,
+    const OatDexFile* oat_dex_file,
+    bool verify,
+    bool verify_checksum,
+    std::string* error_msg) {
+  auto memory_data = memory.data();
+  auto memory_size = memory.size();
+  return OpenCommon(memory_data,
+                    memory_size,
+                    /*data_base=*/ nullptr,
+                    /*data_size=*/ 0,
+                    location,
+                    location_checksum,
+                    oat_dex_file,
+                    verify,
+                    verify_checksum,
+                    error_msg,
+                    std::make_unique<VectorContainer>(std::move(memory)),
+                    /*verify_result=*/ nullptr);
+}
+
+std::unique_ptr<const DexFile> DexFileLoader::Open(
     const uint8_t* base,
     size_t size,
     const std::string& location,
@@ -415,9 +440,11 @@
     return nullptr;
   }
   VerifyResult verify_result;
+  auto map_data = map.data();
+  auto map_size = map.size();
   std::unique_ptr<const DexFile> dex_file = OpenCommon(
-      map.data(),
-      map.size(),
+      map_data,
+      map_size,
       /*data_base=*/ nullptr,
       /*data_size=*/ 0u,
       location,
diff --git a/libdexfile/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h
index 49e177f..d6268bc 100644
--- a/libdexfile/dex/dex_file_loader.h
+++ b/libdexfile/dex/dex_file_loader.h
@@ -113,14 +113,29 @@
   // the descriptor and `filename` will be used as alias for error logging. If
   // zip_fd is -1, the method will try to open the `filename` and read the
   // content from it.
+  //
+  // The dex_locations vector will be populated with the corresponding multidex
+  // locations.
+  //
   // Return true if the checksums could be found, false otherwise.
   virtual bool GetMultiDexChecksums(const char* filename,
                                     std::vector<uint32_t>* checksums,
+                                    std::vector<std::string>* dex_locations,
                                     std::string* error_msg,
                                     int zip_fd = -1,
                                     bool* zip_file_only_contains_uncompress_dex = nullptr) const;
 
-  // Opens .dex file, backed by existing memory
+  // Opens .dex file, backed by existing vector memory.
+  static std::unique_ptr<const DexFile> Open(
+      const std::string& location,
+      uint32_t location_checksum,
+      std::vector<uint8_t>&& memory,
+      const OatDexFile* oat_dex_file,
+      bool verify,
+      bool verify_checksum,
+      std::string* error_msg);
+
+  // Opens .dex file, backed by existing memory.
   virtual std::unique_ptr<const DexFile> Open(
       const uint8_t* base,
       size_t size,
diff --git a/libdexfile/dex/dex_file_reference.h b/libdexfile/dex/dex_file_reference.h
index 1c6ba13..dcc0398 100644
--- a/libdexfile/dex/dex_file_reference.h
+++ b/libdexfile/dex/dex_file_reference.h
@@ -17,7 +17,9 @@
 #ifndef ART_LIBDEXFILE_DEX_DEX_FILE_REFERENCE_H_
 #define ART_LIBDEXFILE_DEX_DEX_FILE_REFERENCE_H_
 
+#include <cstddef>
 #include <cstdint>
+#include <utility>
 
 namespace art {
 
@@ -46,7 +48,21 @@
 inline bool operator==(const DexFileReference& a, const DexFileReference& b) {
   return a.dex_file == b.dex_file && a.index == b.index;
 }
+inline bool operator!=(const DexFileReference& a, const DexFileReference& b) {
+  return !(a == b);
+}
 
 }  // namespace art
 
+namespace std {
+// Hash implementation used for std::set/std::map. Simply xor the hash of the dex-file and index
+template <>
+struct hash<art::DexFileReference> {
+  size_t operator()(const art::DexFileReference& ref) const {
+    return hash<decltype(ref.dex_file)>()(ref.dex_file) ^
+           hash<decltype(ref.index)>()(ref.index);
+  }
+};
+}  // namespace std
+
 #endif  // ART_LIBDEXFILE_DEX_DEX_FILE_REFERENCE_H_
diff --git a/libdexfile/dex/dex_file_verifier.cc b/libdexfile/dex/dex_file_verifier.cc
index 1d33271..f72528f 100644
--- a/libdexfile/dex/dex_file_verifier.cc
+++ b/libdexfile/dex/dex_file_verifier.cc
@@ -448,15 +448,11 @@
   // All sources of the `idx` have already been checked in CheckIntraSection().
   DCHECK_LT(idx.index_, header_->type_ids_size_);
 
-  auto err_fn = [&](const char* descriptor) {
-    ErrorStringPrintf("%s: '%s'", error_msg, descriptor);
-  };
-
   char cached_char = verified_type_descriptors_[idx.index_];
   if (cached_char != 0) {
     if (!extra_check(cached_char)) {
       const char* descriptor = dex_file_->StringByTypeIdx(idx);
-      err_fn(descriptor);
+      ErrorStringPrintf("%s: '%s'", error_msg, descriptor);
       return false;
     }
     return true;
@@ -464,13 +460,13 @@
 
   const char* descriptor = dex_file_->StringByTypeIdx(idx);
   if (UNLIKELY(!IsValidDescriptor(descriptor))) {
-    err_fn(descriptor);
+    ErrorStringPrintf("%s: '%s'", error_msg, descriptor);
     return false;
   }
   verified_type_descriptors_[idx.index_] = descriptor[0];
 
   if (!extra_check(descriptor[0])) {
-    err_fn(descriptor);
+    ErrorStringPrintf("%s: '%s'", error_msg, descriptor);
     return false;
   }
   return true;
@@ -671,7 +667,7 @@
   uint32_t data_items_left = header_->data_size_;
   uint32_t used_bits = 0;
 
-  // Sanity check the size of the map list.
+  // Check the validity of the size of the map list.
   if (!CheckListSize(item, count, sizeof(dex::MapItem), "map size")) {
     return false;
   }
@@ -1728,7 +1724,7 @@
 }
 
 bool DexFileVerifier::CheckIntraDebugInfoItem() {
-  DECODE_UNSIGNED_CHECKED_FROM(ptr_, dummy);
+  DECODE_UNSIGNED_CHECKED_FROM(ptr_, unused_line_start);
   DECODE_UNSIGNED_CHECKED_FROM(ptr_, parameters_size);
   if (UNLIKELY(parameters_size > 65536)) {
     ErrorStringPrintf("Invalid parameters_size: %x", parameters_size);
@@ -1752,11 +1748,11 @@
         return true;
       }
       case DexFile::DBG_ADVANCE_PC: {
-        DECODE_UNSIGNED_CHECKED_FROM(ptr_, advance_pc_dummy);
+        DECODE_UNSIGNED_CHECKED_FROM(ptr_, unused_advance_pc);
         break;
       }
       case DexFile::DBG_ADVANCE_LINE: {
-        DECODE_SIGNED_CHECKED_FROM(ptr_, advance_line_dummy);
+        DECODE_SIGNED_CHECKED_FROM(ptr_, unused_advance_line);
         break;
       }
       case DexFile::DBG_START_LOCAL: {
@@ -2273,7 +2269,7 @@
   size_t data_start = header_->data_off_;
   size_t data_end = data_start + header_->data_size_;
 
-  // Sanity check the offset of the section.
+  // Check the validity of the offset of the section.
   if (UNLIKELY((offset < data_start) || (offset > data_end))) {
     ErrorStringPrintf("Bad offset for data subsection: %zx", offset);
     return false;
@@ -2762,16 +2758,16 @@
 
       // Check that a class is defined after its super class (if the
       // latter is defined in the same Dex file).
-      const dex::ClassDef* superclass_def = dex_file_->FindClassDef(item->superclass_idx_);
-      if (superclass_def != nullptr) {
+      uint16_t superclass_idx = item->superclass_idx_.index_;
+      if (defined_classes_[superclass_idx]) {
         // The superclass is defined in this Dex file.
-        if (superclass_def > item) {
+        if (&dex_file_->GetClassDef(defined_class_indexes_[superclass_idx]) > item) {
           // ClassDef item for super class appearing after the class' ClassDef item.
           ErrorStringPrintf("Invalid class definition ordering:"
                             " class with type idx: '%d' defined before"
                             " superclass with type idx: '%d'",
                             item->class_idx_.index_,
-                            item->superclass_idx_.index_);
+                            superclass_idx);
           return false;
         }
       }
@@ -2800,17 +2796,16 @@
 
         // Check that a class is defined after the interfaces it implements
         // (if they are defined in the same Dex file).
-        const dex::ClassDef* interface_def =
-            dex_file_->FindClassDef(interfaces->GetTypeItem(i).type_idx_);
-        if (interface_def != nullptr) {
+        uint16_t interface_idx = interfaces->GetTypeItem(i).type_idx_.index_;
+        if (defined_classes_[interface_idx]) {
           // The interface is defined in this Dex file.
-          if (interface_def > item) {
+          if (&dex_file_->GetClassDef(defined_class_indexes_[interface_idx]) > item) {
             // ClassDef item for interface appearing after the class' ClassDef item.
             ErrorStringPrintf("Invalid class definition ordering:"
                               " class with type idx: '%d' defined before"
                               " implemented interface with type idx: '%d'",
                               item->class_idx_.index_,
-                              interfaces->GetTypeItem(i).type_idx_.index_);
+                              interface_idx);
             return false;
           }
         }
diff --git a/libdexfile/dex/dex_instruction.cc b/libdexfile/dex/dex_instruction.cc
index 37fc455..11a2d97 100644
--- a/libdexfile/dex/dex_instruction.cc
+++ b/libdexfile/dex/dex_instruction.cc
@@ -281,15 +281,6 @@
             break;
           }
           FALLTHROUGH_INTENDED;
-        case IGET_QUICK:
-        case IGET_OBJECT_QUICK:
-          if (file != nullptr) {
-            uint32_t field_idx = VRegC_22c();
-            os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
-               << "// offset@" << field_idx;
-            break;
-          }
-          FALLTHROUGH_INTENDED;
         case IPUT:
         case IPUT_WIDE:
         case IPUT_OBJECT:
@@ -304,15 +295,6 @@
             break;
           }
           FALLTHROUGH_INTENDED;
-        case IPUT_QUICK:
-        case IPUT_OBJECT_QUICK:
-          if (file != nullptr) {
-            uint32_t field_idx = VRegC_22c();
-            os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
-               << "// offset@" << field_idx;
-            break;
-          }
-          FALLTHROUGH_INTENDED;
         case INSTANCE_OF:
           if (file != nullptr) {
             dex::TypeIndex type_idx(VRegC_22c());
@@ -399,15 +381,6 @@
             break;
           }
           FALLTHROUGH_INTENDED;
-        case INVOKE_VIRTUAL_QUICK:
-          if (file != nullptr) {
-            os << opcode << " {";
-            uint32_t vtable_offset = VRegB_35c();
-            DumpArgs(VRegA_35c());
-            os << "},  // vtable@" << vtable_offset;
-            break;
-          }
-          FALLTHROUGH_INTENDED;
         case INVOKE_CUSTOM:
           if (file != nullptr) {
             os << opcode << " {";
@@ -441,14 +414,6 @@
             break;
           }
           FALLTHROUGH_INTENDED;
-        case INVOKE_VIRTUAL_RANGE_QUICK:
-          if (file != nullptr) {
-            uint32_t method_idx = VRegB_3rc();
-            os << StringPrintf("%s, {v%d .. v%d}, ", opcode, first_reg, last_reg)
-               << "// vtable@" << method_idx;
-            break;
-          }
-          FALLTHROUGH_INTENDED;
         case INVOKE_CUSTOM_RANGE:
           if (file != nullptr) {
             uint32_t call_site_idx = VRegB_3rc();
@@ -547,7 +512,7 @@
   #undef EXPERIMENTAL_CHECK
 };
 
-std::ostream& operator<<(std::ostream& os, const Instruction::Code& code) {
+std::ostream& operator<<(std::ostream& os, Instruction::Code code) {
   return os << Instruction::Name(code);
 }
 
diff --git a/libdexfile/dex/dex_instruction.h b/libdexfile/dex/dex_instruction.h
index c15fa43..7e43f75 100644
--- a/libdexfile/dex/dex_instruction.h
+++ b/libdexfile/dex/dex_instruction.h
@@ -141,7 +141,7 @@
     kIndexProtoRef,           // prototype reference index
   };
 
-  enum Flags : uint8_t {
+  enum Flags : uint8_t {  // private marker to avoid generate-operator-out.py from processing.
     kBranch              = 0x01,  // conditional or unconditional branch
     kContinue            = 0x02,  // flow can continue to next statement
     kSwitch              = 0x04,  // switch statement
@@ -173,7 +173,7 @@
     kRegBFieldOrConstant = 0x0800000,  // is the second virtual register a field or literal constant (vB)
   };
 
-  enum VerifyFlag : uint32_t {
+  enum VerifyFlag : uint32_t {  // private marker to avoid generate-operator-out.py from processing.
     kVerifyNothing            = 0x0000000,
     kVerifyRegA               = 0x0000001,
     kVerifyRegAWide           = 0x0000002,
@@ -692,10 +692,8 @@
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
 };
-std::ostream& operator<<(std::ostream& os, const Instruction::Code& code);
-std::ostream& operator<<(std::ostream& os, const Instruction::Format& format);
-std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags);
-std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags);
+std::ostream& operator<<(std::ostream& os, Instruction::Code code);
+std::ostream& operator<<(std::ostream& os, Instruction::Format format);
 
 // Base class for accessing instruction operands. Unifies operand
 // access for instructions that have range and varargs forms
diff --git a/libdexfile/dex/dex_instruction_list.h b/libdexfile/dex/dex_instruction_list.h
index b9540a6..9a01bfe 100644
--- a/libdexfile/dex/dex_instruction_list.h
+++ b/libdexfile/dex/dex_instruction_list.h
@@ -134,7 +134,7 @@
   V(0x70, INVOKE_DIRECT, "invoke-direct", k35c, kIndexMethodRef, kContinue | kThrow | kInvoke, 0, kVerifyRegBMethod | kVerifyVarArgNonZero) \
   V(0x71, INVOKE_STATIC, "invoke-static", k35c, kIndexMethodRef, kContinue | kThrow | kInvoke, 0, kVerifyRegBMethod | kVerifyVarArg) \
   V(0x72, INVOKE_INTERFACE, "invoke-interface", k35c, kIndexMethodRef, kContinue | kThrow | kInvoke, 0, kVerifyRegBMethod | kVerifyVarArgNonZero) \
-  V(0x73, RETURN_VOID_NO_BARRIER, "return-void-no-barrier", k10x, kIndexNone, kReturn, 0, kVerifyNothing) \
+  V(0x73, UNUSED_73, "unused-73", k10x, kIndexUnknown, 0, 0, kVerifyError) \
   V(0x74, INVOKE_VIRTUAL_RANGE, "invoke-virtual/range", k3rc, kIndexMethodRef, kContinue | kThrow | kInvoke, 0, kVerifyRegBMethod | kVerifyVarArgRangeNonZero) \
   V(0x75, INVOKE_SUPER_RANGE, "invoke-super/range", k3rc, kIndexMethodRef, kContinue | kThrow | kInvoke, 0, kVerifyRegBMethod | kVerifyVarArgRangeNonZero) \
   V(0x76, INVOKE_DIRECT_RANGE, "invoke-direct/range", k3rc, kIndexMethodRef, kContinue | kThrow | kInvoke, 0, kVerifyRegBMethod | kVerifyVarArgRangeNonZero) \
@@ -246,22 +246,22 @@
   V(0xE0, SHL_INT_LIT8, "shl-int/lit8", k22b, kIndexNone, kContinue, kShl | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB) \
   V(0xE1, SHR_INT_LIT8, "shr-int/lit8", k22b, kIndexNone, kContinue, kShr | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB) \
   V(0xE2, USHR_INT_LIT8, "ushr-int/lit8", k22b, kIndexNone, kContinue, kUshr | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB) \
-  V(0xE3, IGET_QUICK, "iget-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kLoad | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xE4, IGET_WIDE_QUICK, "iget-wide-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kLoad | kRegCFieldOrConstant, kVerifyRegAWide | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xE5, IGET_OBJECT_QUICK, "iget-object-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kLoad | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xE6, IPUT_QUICK, "iput-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kStore | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xE7, IPUT_WIDE_QUICK, "iput-wide-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kStore | kRegCFieldOrConstant, kVerifyRegAWide | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xE8, IPUT_OBJECT_QUICK, "iput-object-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kStore | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xE9, INVOKE_VIRTUAL_QUICK, "invoke-virtual-quick", k35c, kIndexVtableOffset, kContinue | kThrow | kInvoke, 0, kVerifyVarArgNonZero | kVerifyRuntimeOnly) \
-  V(0xEA, INVOKE_VIRTUAL_RANGE_QUICK, "invoke-virtual/range-quick", k3rc, kIndexVtableOffset, kContinue | kThrow | kInvoke, 0, kVerifyVarArgRangeNonZero | kVerifyRuntimeOnly) \
-  V(0xEB, IPUT_BOOLEAN_QUICK, "iput-boolean-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kStore | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xEC, IPUT_BYTE_QUICK, "iput-byte-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kStore | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xED, IPUT_CHAR_QUICK, "iput-char-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kStore | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xEE, IPUT_SHORT_QUICK, "iput-short-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kStore | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xEF, IGET_BOOLEAN_QUICK, "iget-boolean-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kLoad | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xF0, IGET_BYTE_QUICK, "iget-byte-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kLoad | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xF1, IGET_CHAR_QUICK, "iget-char-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kLoad | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
-  V(0xF2, IGET_SHORT_QUICK, "iget-short-quick", k22c, kIndexFieldOffset, kContinue | kThrow, kLoad | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \
+  V(0xE3, UNUSED_E3, "unused-e3", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xE4, UNUSED_E4, "unused-e4", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xE5, UNUSED_E5, "unused-e5", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xE6, UNUSED_E6, "unused-e6", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xE7, UNUSED_E7, "unused-e7", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xE8, UNUSED_E8, "unused-e8", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xE9, UNUSED_E9, "unused-e9", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xEA, UNUSED_EA, "unused-ea", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xEB, UNUSED_EB, "unused-eb", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xEC, UNUSED_EC, "unused-ec", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xED, UNUSED_ED, "unused-ed", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xEE, UNUSED_EE, "unused-ee", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xEF, UNUSED_EF, "unused-ef", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xF0, UNUSED_F0, "unused-f0", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xF1, UNUSED_F1, "unused-f1", k10x, kIndexUnknown, 0, 0, kVerifyError) \
+  V(0xF2, UNUSED_F2, "unused-f2", k10x, kIndexUnknown, 0, 0, kVerifyError) \
   V(0xF3, UNUSED_F3, "unused-f3", k10x, kIndexUnknown, 0, 0, kVerifyError) \
   V(0xF4, UNUSED_F4, "unused-f4", k10x, kIndexUnknown, 0, 0, kVerifyError) \
   V(0xF5, UNUSED_F5, "unused-f5", k10x, kIndexUnknown, 0, 0, kVerifyError) \
diff --git a/libdexfile/dex/dex_instruction_test.cc b/libdexfile/dex/dex_instruction_test.cc
index 3f79abf..b0e3d6e 100644
--- a/libdexfile/dex/dex_instruction_test.cc
+++ b/libdexfile/dex/dex_instruction_test.cc
@@ -169,8 +169,6 @@
             "filled-new-array {v3, v2}, type@1234");
   EXPECT_EQ(DumpInst35c(Instruction::INVOKE_VIRTUAL, 1234, {3, 2, 1, 5, 6}),
             "invoke-virtual {v3, v2, v1, v5, v6}, thing@1234");
-  EXPECT_EQ(DumpInst35c(Instruction::INVOKE_VIRTUAL_QUICK, 1234, {3, 2, 1, 5}),
-            "invoke-virtual-quick {v3, v2, v1, v5}, thing@1234");
   EXPECT_EQ(DumpInst35c(Instruction::INVOKE_CUSTOM, 1234, {3, 2, 1}),
             "invoke-custom {v3, v2, v1}, thing@1234");
 }
diff --git a/libdexfile/dex/dex_instruction_utils.h b/libdexfile/dex/dex_instruction_utils.h
index e7614ad..242bbcd 100644
--- a/libdexfile/dex/dex_instruction_utils.h
+++ b/libdexfile/dex/dex_instruction_utils.h
@@ -45,7 +45,7 @@
   kDexMemAccessTypeCount
 };
 
-std::ostream& operator<<(std::ostream& os, const DexMemAccessType& type);
+std::ostream& operator<<(std::ostream& os, DexMemAccessType type);
 
 // NOTE: The following functions disregard quickened instructions.
 
@@ -65,12 +65,7 @@
 
 constexpr bool IsInstructionInvoke(Instruction::Code opcode) {
   return Instruction::INVOKE_VIRTUAL <= opcode && opcode <= Instruction::INVOKE_INTERFACE_RANGE &&
-      opcode != Instruction::RETURN_VOID_NO_BARRIER;
-}
-
-constexpr bool IsInstructionQuickInvoke(Instruction::Code opcode) {
-  return opcode == Instruction::INVOKE_VIRTUAL_QUICK ||
-      opcode == Instruction::INVOKE_VIRTUAL_RANGE_QUICK;
+      opcode != Instruction::UNUSED_73;
 }
 
 constexpr bool IsInstructionInvokeStatic(Instruction::Code opcode) {
@@ -117,11 +112,6 @@
   return Instruction::IGET <= code && code <= Instruction::IPUT_SHORT;
 }
 
-constexpr bool IsInstructionIGetQuickOrIPutQuick(Instruction::Code code) {
-  return (code >= Instruction::IGET_QUICK && code <= Instruction::IPUT_OBJECT_QUICK) ||
-      (code >= Instruction::IPUT_BOOLEAN_QUICK && code <= Instruction::IGET_SHORT_QUICK);
-}
-
 constexpr bool IsInstructionSGetOrSPut(Instruction::Code code) {
   return Instruction::SGET <= code && code <= Instruction::SPUT_SHORT;
 }
@@ -181,29 +171,6 @@
   return (code >= Instruction::IPUT) ? IPutMemAccessType(code) : IGetMemAccessType(code);
 }
 
-inline DexMemAccessType IGetQuickOrIPutQuickMemAccessType(Instruction::Code code) {
-  DCHECK(IsInstructionIGetQuickOrIPutQuick(code));
-  switch (code) {
-    case Instruction::IGET_QUICK: case Instruction::IPUT_QUICK:
-      return kDexMemAccessWord;
-    case Instruction::IGET_WIDE_QUICK: case Instruction::IPUT_WIDE_QUICK:
-      return kDexMemAccessWide;
-    case Instruction::IGET_OBJECT_QUICK: case Instruction::IPUT_OBJECT_QUICK:
-      return kDexMemAccessObject;
-    case Instruction::IGET_BOOLEAN_QUICK: case Instruction::IPUT_BOOLEAN_QUICK:
-      return kDexMemAccessBoolean;
-    case Instruction::IGET_BYTE_QUICK: case Instruction::IPUT_BYTE_QUICK:
-      return kDexMemAccessByte;
-    case Instruction::IGET_CHAR_QUICK: case Instruction::IPUT_CHAR_QUICK:
-      return kDexMemAccessChar;
-    case Instruction::IGET_SHORT_QUICK: case Instruction::IPUT_SHORT_QUICK:
-      return kDexMemAccessShort;
-    default:
-      LOG(FATAL) << code;
-      UNREACHABLE();
-  }
-}
-
 constexpr DexMemAccessType SGetOrSPutMemAccessType(Instruction::Code code) {
   DCHECK(IsInstructionSGetOrSPut(code));
   return (code >= Instruction::SPUT) ? SPutMemAccessType(code) : SGetMemAccessType(code);
diff --git a/libdexfile/dex/invoke_type.h b/libdexfile/dex/invoke_type.h
index 1740c07..448d75a 100644
--- a/libdexfile/dex/invoke_type.h
+++ b/libdexfile/dex/invoke_type.h
@@ -32,7 +32,7 @@
   kMaxInvokeType = kCustom
 };
 
-std::ostream& operator<<(std::ostream& os, const InvokeType& rhs);
+std::ostream& operator<<(std::ostream& os, InvokeType rhs);
 
 }  // namespace art
 
diff --git a/libdexfile/dex/modifiers.h b/libdexfile/dex/modifiers.h
index bdb3781..60141df 100644
--- a/libdexfile/dex/modifiers.h
+++ b/libdexfile/dex/modifiers.h
@@ -58,35 +58,37 @@
 // Used by a class to denote that this class and any objects with this as a
 // declaring-class/super-class are to be considered obsolete, meaning they should not be used by.
 static constexpr uint32_t kAccObsoleteObject =        0x00200000;  // class (runtime)
-// This is set by the class linker during LinkInterfaceMethods. It is used by a method to represent
-// that it was copied from its declaring class into another class. All methods marked kAccMiranda
-// and kAccDefaultConflict will have this bit set. Any kAccDefault method contained in the methods_
-// array of a concrete class will also have this bit set.
-// We need copies of the original method because the method may end up in
-// different places in classes vtables, and the vtable index is set in ArtMethod.method_index.
-static constexpr uint32_t kAccCopied =                0x00100000;  // method (runtime)
-static constexpr uint32_t kAccMiranda =               0x00200000;  // method (runtime, not native)
+// This is set by the class linker during LinkInterfaceMethods. It is used by a method
+// to represent that it was copied from its declaring class into another class.
+// We need copies of the original method because the method may end up in different
+// places in classes vtables, and the vtable index is set in ArtMethod.method_index.
+//
+// Default methods copied to a sub-interface or a concrete class shall have this bit set.
+// Default conflict methods shall be marked as copied, abstract and default.
+// Miranda methods shall be marked as copied and abstract but not default.
+//
+// We do not have intrinsics for any default methods and therefore intrinsics are never
+// copied. We can therefore use a flag from the intrinsic flags range.
+static constexpr uint32_t kAccCopied =                0x01000000;  // method (runtime)
 static constexpr uint32_t kAccDefault =               0x00400000;  // method (runtime)
 // Native method flags are set when linking the methods based on the presence of the
 // @dalvik.annotation.optimization.{Fast,Critical}Native annotations with build visibility.
 // Reuse the values of kAccSkipAccessChecks and kAccMiranda which are not used for native methods.
 static constexpr uint32_t kAccFastNative =            0x00080000;  // method (runtime; native only)
-static constexpr uint32_t kAccCriticalNative =        0x00200000;  // method (runtime; native only)
+static constexpr uint32_t kAccCriticalNative =        0x00100000;  // method (runtime; native only)
 
 // Set by the JIT when clearing profiling infos to denote that a method was previously warm.
 static constexpr uint32_t kAccPreviouslyWarm =        0x00800000;  // method (runtime)
 
-// This is set by the class linker during LinkInterfaceMethods. Prior to that point we do not know
-// if any particular method needs to be a default conflict. Used to figure out at runtime if
-// invoking this method will throw an exception.
-static constexpr uint32_t kAccDefaultConflict =       0x01000000;  // method (runtime)
-
 // Set by the verifier for a method we do not want the compiler to compile.
 static constexpr uint32_t kAccCompileDontBother =     0x02000000;  // method (runtime)
 
-// Used in conjunction with kAccCompileDontBother to mark the method as pre
-// compiled by the JIT compiler.
-static constexpr uint32_t kAccPreCompiled =           0x00200000;  // method (runtime)
+// Used in conjunction with kAccCompileDontBother to mark the method as pre compiled
+// by the JIT compiler. We are reusing the value of the kAccPreviouslyWarm flag which
+// is meaningless for other methods with kAccCompileDontBother as we do not collect
+// samples for such methods.
+static constexpr uint32_t kAccPreCompiled =           0x00800000;  // method (runtime)
+static_assert(kAccPreCompiled == kAccPreviouslyWarm);
 
 // Set by the verifier for a method that could not be verified to follow structured locking.
 static constexpr uint32_t kAccMustCountLocks =        0x04000000;  // method (runtime)
@@ -95,6 +97,12 @@
 // virtual call.
 static constexpr uint32_t kAccSingleImplementation =  0x08000000;  // method (runtime)
 
+// Whether nterp can take a fast path when entering this method (runtime; non-native)
+static constexpr uint32_t kAccNterpEntryPointFastPathFlag = 0x00100000;
+// Set by the class linker to mark that a method does not have floating points
+// or longs in its shorty.
+static constexpr uint32_t kAccNterpInvokeFastPathFlag     = 0x00200000;  // method (runtime)
+
 static constexpr uint32_t kAccPublicApi =             0x10000000;  // field, method
 static constexpr uint32_t kAccCorePlatformApi =       0x20000000;  // field, method
 
@@ -118,7 +126,7 @@
 // Continuous sequence of bits used to hold the ordinal of an intrinsic method. Flags
 // which overlap are not valid when kAccIntrinsic is set.
 static constexpr uint32_t kAccIntrinsicBits = kAccHiddenapiBits |
-    kAccSingleImplementation | kAccMustCountLocks | kAccCompileDontBother | kAccDefaultConflict |
+    kAccSingleImplementation | kAccMustCountLocks | kAccCompileDontBother | kAccCopied |
     kAccPreviouslyWarm | kAccFastInterpreterToInterpreterInvoke;
 
 // Valid (meaningful) bits for a field.
diff --git a/libdexfile/dex/signature.h b/libdexfile/dex/signature.h
index 3fbb543..232819b 100644
--- a/libdexfile/dex/signature.h
+++ b/libdexfile/dex/signature.h
@@ -59,8 +59,8 @@
 
   friend class DexFile;
 
-  const DexFile* const dex_file_ = nullptr;
-  const dex::ProtoId* const proto_id_ = nullptr;
+  const DexFile* dex_file_ = nullptr;
+  const dex::ProtoId* proto_id_ = nullptr;
 };
 std::ostream& operator<<(std::ostream& os, const Signature& sig);
 
diff --git a/libdexfile/dex/string_reference_test.cc b/libdexfile/dex/string_reference_test.cc
index b9cbf48..6c10f22 100644
--- a/libdexfile/dex/string_reference_test.cc
+++ b/libdexfile/dex/string_reference_test.cc
@@ -33,14 +33,14 @@
   // that it's the wrong string. Without the fix the strings would then compare equal.
   TestDexFileBuilder builder1;
   builder1.AddString("String1");
-  std::unique_ptr<const DexFile> dex_file1 = builder1.Build("dummy location 1");
+  std::unique_ptr<const DexFile> dex_file1 = builder1.Build("fake location 1");
   ASSERT_EQ(1u, dex_file1->NumStringIds());
   ASSERT_STREQ("String1", dex_file1->GetStringData(dex_file1->GetStringId(dex::StringIndex(0))));
   StringReference sr1(dex_file1.get(), dex::StringIndex(0));
 
   TestDexFileBuilder builder2;
   builder2.AddString("String2");
-  std::unique_ptr<const DexFile> dex_file2 = builder2.Build("dummy location 2");
+  std::unique_ptr<const DexFile> dex_file2 = builder2.Build("fake location 2");
   ASSERT_EQ(1u, dex_file2->NumStringIds());
   ASSERT_STREQ("String2", dex_file2->GetStringData(dex_file2->GetStringId(dex::StringIndex(0))));
   StringReference sr2(dex_file2.get(), dex::StringIndex(0));
@@ -78,7 +78,7 @@
   for (const char* s : kDexFile1Strings) {
     builder1.AddString(s);
   }
-  std::unique_ptr<const DexFile> dex_file1 = builder1.Build("dummy location 1");
+  std::unique_ptr<const DexFile> dex_file1 = builder1.Build("fake location 1");
   ASSERT_EQ(arraysize(kDexFile1Strings), dex_file1->NumStringIds());
   for (size_t index = 0; index != arraysize(kDexFile1Strings); ++index) {
     ASSERT_STREQ(kDexFile1Strings[index],
@@ -89,7 +89,7 @@
   for (const char* s : kDexFile2Strings) {
     builder2.AddString(s);
   }
-  std::unique_ptr<const DexFile> dex_file2 = builder2.Build("dummy location 1");
+  std::unique_ptr<const DexFile> dex_file2 = builder2.Build("fake location 1");
   ASSERT_EQ(arraysize(kDexFile2Strings), dex_file2->NumStringIds());
   for (size_t index = 0; index != arraysize(kDexFile2Strings); ++index) {
     ASSERT_STREQ(kDexFile2Strings[index],
diff --git a/libdexfile/dex/test_dex_file_builder.h b/libdexfile/dex/test_dex_file_builder.h
index 2b0bad0..283dd48 100644
--- a/libdexfile/dex/test_dex_file_builder.h
+++ b/libdexfile/dex/test_dex_file_builder.h
@@ -26,6 +26,7 @@
 
 #include <android-base/logging.h>
 
+#include "base/array_ref.h"
 #include "base/bit_utils.h"
 #include "dex/dex_file_loader.h"
 #include "dex/standard_dex_file.h"
@@ -35,24 +36,22 @@
 class TestDexFileBuilder {
  public:
   TestDexFileBuilder()
-      : strings_(), types_(), fields_(), protos_(), dex_file_data_() {
+      : strings_(), types_(), fields_(), protos_() {
   }
 
   void AddString(const std::string& str) {
-    CHECK(dex_file_data_.empty());
-    auto it = strings_.emplace(str, IdxAndDataOffset()).first;
-    CHECK_LT(it->first.length(), 128u);  // Don't allow multi-byte length in uleb128.
+    CHECK_LT(str.length(), 128u);  // Don't allow multi-byte length in uleb128.
+    strings_.emplace(str, IdxAndDataOffset());
   }
 
   void AddType(const std::string& descriptor) {
-    CHECK(dex_file_data_.empty());
     AddString(descriptor);
     types_.emplace(descriptor, 0u);
   }
 
-  void AddField(const std::string& class_descriptor, const std::string& type,
+  void AddField(const std::string& class_descriptor,
+                const std::string& type,
                 const std::string& name) {
-    CHECK(dex_file_data_.empty());
     AddType(class_descriptor);
     AddType(type);
     AddString(name);
@@ -60,9 +59,9 @@
     fields_.emplace(key, 0u);
   }
 
-  void AddMethod(const std::string& class_descriptor, const std::string& signature,
+  void AddMethod(const std::string& class_descriptor,
+                 const std::string& signature,
                  const std::string& name) {
-    CHECK(dex_file_data_.empty());
     AddType(class_descriptor);
     AddString(name);
 
@@ -81,9 +80,8 @@
     methods_.emplace(method_key, 0u);
   }
 
-  // NOTE: The builder holds the actual data, so it must live as long as the dex file.
-  std::unique_ptr<const DexFile> Build(const std::string& dex_location) {
-    CHECK(dex_file_data_.empty());
+  std::unique_ptr<const DexFile> Build(const std::string& dex_location,
+                                       uint32_t location_checksum = 0u) {
     union {
       uint8_t data[sizeof(DexFile::Header)];
       uint64_t force_alignment;
@@ -164,19 +162,22 @@
     header->data_off_ = (data_section_size != 0u) ? data_section_offset : 0u;
 
     uint32_t total_size = data_section_offset + data_section_size;
-
-    dex_file_data_.resize(total_size);
+    std::vector<uint8_t> dex_file_data(total_size, 0u);
 
     for (const auto& entry : strings_) {
       CHECK_LT(entry.first.size(), 128u);
       uint32_t raw_offset = data_section_offset + entry.second.data_offset;
-      dex_file_data_[raw_offset] = static_cast<uint8_t>(entry.first.size());
-      std::memcpy(&dex_file_data_[raw_offset + 1], entry.first.c_str(), entry.first.size() + 1);
-      Write32(string_ids_offset + entry.second.idx * sizeof(dex::StringId), raw_offset);
+      dex_file_data[raw_offset] = static_cast<uint8_t>(entry.first.size());
+      std::memcpy(&dex_file_data[raw_offset + 1], entry.first.c_str(), entry.first.size() + 1);
+      Write32(dex_file_data,
+              string_ids_offset + entry.second.idx * sizeof(dex::StringId),
+              raw_offset);
     }
 
     for (const auto& entry : types_) {
-      Write32(type_ids_offset + entry.second * sizeof(dex::TypeId), GetStringIdx(entry.first));
+      Write32(dex_file_data,
+              type_ids_offset + entry.second * sizeof(dex::TypeId),
+              GetStringIdx(entry.first));
       ++type_idx;
     }
 
@@ -185,14 +186,15 @@
       uint32_t type_list_offset =
           (num_args != 0u) ? data_section_offset + entry.second.data_offset : 0u;
       uint32_t raw_offset = proto_ids_offset + entry.second.idx * sizeof(dex::ProtoId);
-      Write32(raw_offset + 0u, GetStringIdx(entry.first.shorty));
-      Write16(raw_offset + 4u, GetTypeIdx(entry.first.return_type));
-      Write32(raw_offset + 8u, type_list_offset);
+      Write32(dex_file_data, raw_offset + 0u, GetStringIdx(entry.first.shorty));
+      Write16(dex_file_data, raw_offset + 4u, GetTypeIdx(entry.first.return_type));
+      Write32(dex_file_data, raw_offset + 8u, type_list_offset);
       if (num_args != 0u) {
         CHECK_NE(entry.second.data_offset, 0u);
-        Write32(type_list_offset, num_args);
+        Write32(dex_file_data, type_list_offset, num_args);
         for (size_t i = 0; i != num_args; ++i) {
-          Write16(type_list_offset + 4u + i * sizeof(dex::TypeItem),
+          Write16(dex_file_data,
+                  type_list_offset + 4u + i * sizeof(dex::TypeItem),
                   GetTypeIdx(entry.first.args[i]));
         }
       }
@@ -200,46 +202,46 @@
 
     for (const auto& entry : fields_) {
       uint32_t raw_offset = field_ids_offset + entry.second * sizeof(dex::FieldId);
-      Write16(raw_offset + 0u, GetTypeIdx(entry.first.class_descriptor));
-      Write16(raw_offset + 2u, GetTypeIdx(entry.first.type));
-      Write32(raw_offset + 4u, GetStringIdx(entry.first.name));
+      Write16(dex_file_data, raw_offset + 0u, GetTypeIdx(entry.first.class_descriptor));
+      Write16(dex_file_data, raw_offset + 2u, GetTypeIdx(entry.first.type));
+      Write32(dex_file_data, raw_offset + 4u, GetStringIdx(entry.first.name));
     }
 
     for (const auto& entry : methods_) {
       uint32_t raw_offset = method_ids_offset + entry.second * sizeof(dex::MethodId);
-      Write16(raw_offset + 0u, GetTypeIdx(entry.first.class_descriptor));
+      Write16(dex_file_data, raw_offset + 0u, GetTypeIdx(entry.first.class_descriptor));
       auto it = protos_.find(*entry.first.proto);
       CHECK(it != protos_.end());
-      Write16(raw_offset + 2u, it->second.idx);
-      Write32(raw_offset + 4u, GetStringIdx(entry.first.name));
+      Write16(dex_file_data, raw_offset + 2u, it->second.idx);
+      Write32(dex_file_data, raw_offset + 4u, GetStringIdx(entry.first.name));
     }
 
     // Leave signature as zeros.
 
-    header->file_size_ = dex_file_data_.size();
+    header->file_size_ = dex_file_data.size();
 
     // Write the complete header early, as part of it needs to be checksummed.
-    std::memcpy(&dex_file_data_[0], header_data.data, sizeof(DexFile::Header));
+    std::memcpy(&dex_file_data[0], header_data.data, sizeof(DexFile::Header));
 
     // Checksum starts after the checksum field.
     size_t skip = sizeof(header->magic_) + sizeof(header->checksum_);
     header->checksum_ = adler32(adler32(0L, Z_NULL, 0),
-                                dex_file_data_.data() + skip,
-                                dex_file_data_.size() - skip);
+                                dex_file_data.data() + skip,
+                                dex_file_data.size() - skip);
 
     // Write the complete header again, just simpler that way.
-    std::memcpy(&dex_file_data_[0], header_data.data, sizeof(DexFile::Header));
+    std::memcpy(&dex_file_data[0], header_data.data, sizeof(DexFile::Header));
+
+    // Do not protect the final data from writing. Some tests need to modify it.
 
     static constexpr bool kVerify = false;
     static constexpr bool kVerifyChecksum = false;
     std::string error_msg;
-    const DexFileLoader dex_file_loader;
-    std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(
-        &dex_file_data_[0],
-        dex_file_data_.size(),
+    std::unique_ptr<const DexFile> dex_file(DexFileLoader::Open(
         dex_location,
-        0u,
-        nullptr,
+        location_checksum,
+        std::move(dex_file_data),
+        /*oat_dex_file=*/ nullptr,
         kVerify,
         kVerifyChecksum,
         &error_msg));
@@ -366,25 +368,25 @@
     return key;
   }
 
-  void Write32(size_t offset, uint32_t value) {
-    CHECK_LE(offset + 4u, dex_file_data_.size());
-    CHECK_EQ(dex_file_data_[offset + 0], 0u);
-    CHECK_EQ(dex_file_data_[offset + 1], 0u);
-    CHECK_EQ(dex_file_data_[offset + 2], 0u);
-    CHECK_EQ(dex_file_data_[offset + 3], 0u);
-    dex_file_data_[offset + 0] = static_cast<uint8_t>(value >> 0);
-    dex_file_data_[offset + 1] = static_cast<uint8_t>(value >> 8);
-    dex_file_data_[offset + 2] = static_cast<uint8_t>(value >> 16);
-    dex_file_data_[offset + 3] = static_cast<uint8_t>(value >> 24);
+  static void Write32(std::vector<uint8_t>& dex_file_data, size_t offset, uint32_t value) {
+    CHECK_LE(offset + 4u, dex_file_data.size());
+    CHECK_EQ(dex_file_data[offset + 0], 0u);
+    CHECK_EQ(dex_file_data[offset + 1], 0u);
+    CHECK_EQ(dex_file_data[offset + 2], 0u);
+    CHECK_EQ(dex_file_data[offset + 3], 0u);
+    dex_file_data[offset + 0] = static_cast<uint8_t>(value >> 0);
+    dex_file_data[offset + 1] = static_cast<uint8_t>(value >> 8);
+    dex_file_data[offset + 2] = static_cast<uint8_t>(value >> 16);
+    dex_file_data[offset + 3] = static_cast<uint8_t>(value >> 24);
   }
 
-  void Write16(size_t offset, uint32_t value) {
+  static void Write16(std::vector<uint8_t>& dex_file_data, size_t offset, uint32_t value) {
     CHECK_LE(value, 0xffffu);
-    CHECK_LE(offset + 2u, dex_file_data_.size());
-    CHECK_EQ(dex_file_data_[offset + 0], 0u);
-    CHECK_EQ(dex_file_data_[offset + 1], 0u);
-    dex_file_data_[offset + 0] = static_cast<uint8_t>(value >> 0);
-    dex_file_data_[offset + 1] = static_cast<uint8_t>(value >> 8);
+    CHECK_LE(offset + 2u, dex_file_data.size());
+    CHECK_EQ(dex_file_data[offset + 0], 0u);
+    CHECK_EQ(dex_file_data[offset + 1], 0u);
+    dex_file_data[offset + 0] = static_cast<uint8_t>(value >> 0);
+    dex_file_data[offset + 1] = static_cast<uint8_t>(value >> 8);
   }
 
   std::map<std::string, IdxAndDataOffset> strings_;
@@ -392,8 +394,6 @@
   std::map<FieldKey, uint32_t, FieldKeyComparator> fields_;
   std::map<ProtoKey, IdxAndDataOffset, ProtoKeyComparator> protos_;
   std::map<MethodKey, uint32_t, MethodKeyComparator> methods_;
-
-  std::vector<uint8_t> dex_file_data_;
 };
 
 }  // namespace art
diff --git a/libdexfile/dex/test_dex_file_builder_test.cc b/libdexfile/dex/test_dex_file_builder_test.cc
index 11e073a..9aeaded 100644
--- a/libdexfile/dex/test_dex_file_builder_test.cc
+++ b/libdexfile/dex/test_dex_file_builder_test.cc
@@ -80,7 +80,9 @@
   EXPECT_EQ(2u, builder.GetTypeIdx("Ljava/lang/Class;"));
   EXPECT_EQ(0u, builder.GetFieldIdx("LTestClass;", "[I", "intField"));
   EXPECT_EQ(1u, builder.GetMethodIdx("LTestClass;", "()I", "foo"));
-  EXPECT_EQ(0u, builder.GetMethodIdx("LTestClass;", "(Ljava/lang/Object;[Ljava/lang/Object;)LTestClass;", "bar"));
+  EXPECT_EQ(0u, builder.GetMethodIdx("LTestClass;",
+                                     "(Ljava/lang/Object;[Ljava/lang/Object;)LTestClass;",
+                                     "bar"));
 }
 
 }  // namespace art
diff --git a/libdexfile/external/dex_file_ext.cc b/libdexfile/external/dex_file_ext.cc
index e1b7874..7c0bf2d 100644
--- a/libdexfile/external/dex_file_ext.cc
+++ b/libdexfile/external/dex_file_ext.cc
@@ -18,13 +18,13 @@
 
 #include <inttypes.h>
 #include <stdint.h>
-#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <cerrno>
 #include <cstring>
+#include <deque>
 #include <map>
 #include <memory>
 #include <string>
@@ -41,120 +41,119 @@
 #include <dex/dex_file-inl.h>
 #include <dex/dex_file_loader.h>
 
-namespace art {
-namespace {
-
-struct MethodCacheEntry {
-  int32_t offset;  // Offset relative to the start of the dex file header.
-  int32_t len;
-  int32_t index;  // Method index.
-};
-
-class MappedFileContainer : public DexFileContainer {
- public:
-  explicit MappedFileContainer(std::unique_ptr<android::base::MappedFile>&& map)
-      : map_(std::move(map)) {}
-  ~MappedFileContainer() override {}
-  int GetPermissions() override { return 0; }
-  bool IsReadOnly() override { return true; }
-  bool EnableWrite() override { return false; }
-  bool DisableWrite() override { return false; }
-
- private:
-  std::unique_ptr<android::base::MappedFile> map_;
-  DISALLOW_COPY_AND_ASSIGN(MappedFileContainer);
-};
-
-}  // namespace
-}  // namespace art
-
 extern "C" {
 
-struct ExtDexFileString {
-  const std::string str_;
+struct ADexFile_Method {
+  ADexFile* adex;
+  uint32_t index;
+  size_t offset;
+  size_t size;
 };
 
-static const ExtDexFileString empty_string{""};
-
-const ExtDexFileString* ExtDexFileMakeString(const char* str, size_t size) {
-  if (size == 0) {
-    return &empty_string;
-  }
-  return new ExtDexFileString{std::string(str, size)};
-}
-
-const char* ExtDexFileGetString(const ExtDexFileString* ext_string, /*out*/ size_t* size) {
-  DCHECK(ext_string != nullptr);
-  *size = ext_string->str_.size();
-  return ext_string->str_.data();
-}
-
-void ExtDexFileFreeString(const ExtDexFileString* ext_string) {
-  DCHECK(ext_string != nullptr);
-  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*.
-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.
-  std::map<int32_t, art::MethodCacheEntry> method_cache_;
-
-  // Index of first class def for which method_cache_ isn't complete.
-  uint32_t class_def_index_ = 0;
-
- public:
-  std::unique_ptr<const art::DexFile> dex_file_;
-  explicit ExtDexFile(std::unique_ptr<const art::DexFile>&& dex_file)
+// Opaque implementation of ADexFile for the C interface.
+struct ADexFile {
+  explicit ADexFile(std::unique_ptr<const art::DexFile> dex_file)
       : dex_file_(std::move(dex_file)) {}
 
-  art::MethodCacheEntry* GetMethodCacheEntryForOffset(int64_t dex_offset) {
-    // First look in the method cache.
-    auto it = method_cache_.upper_bound(dex_offset);
-    if (it != method_cache_.end() && dex_offset >= it->second.offset) {
-      return &it->second;
-    }
-
-    for (; class_def_index_ < dex_file_->NumClassDefs(); class_def_index_++) {
-      art::ClassAccessor accessor(*dex_file_, class_def_index_);
-
+  inline bool FindMethod(uint32_t dex_offset, /*out*/ ADexFile_Method* result) {
+    uint32_t class_def_index;
+    if (GetClassDefIndex(dex_offset, &class_def_index)) {
+      art::ClassAccessor accessor(*dex_file_, class_def_index);
       for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
         art::CodeItemInstructionAccessor code = method.GetInstructions();
         if (!code.HasCodeItem()) {
           continue;
         }
+        size_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
+        size_t size = code.InsnsSizeInBytes();
+        if (offset <= dex_offset && dex_offset < offset + size) {
+          *result = ADexFile_Method {
+            .adex = this,
+            .index = method.GetIndex(),
+            .offset = offset,
+            .size = size,
+          };
+          return true;
+        }
+      }
+    }
+    return false;
+  }
 
-        int32_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
-        int32_t len = code.InsnsSizeInBytes();
-        int32_t index = method.GetIndex();
-        auto res = method_cache_.emplace(offset + len, art::MethodCacheEntry{offset, len, index});
-        if (offset <= dex_offset && dex_offset < offset + len) {
-          return &res.first->second;
+  void CreateClassCache() {
+    // Create binary search table with (end_dex_offset, class_def_index) entries.
+    // That is, we don't assume that dex code of given class is consecutive.
+    std::deque<std::pair<uint32_t, uint32_t>> cache;
+    for (art::ClassAccessor accessor : dex_file_->GetClasses()) {
+      for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
+        art::CodeItemInstructionAccessor code = method.GetInstructions();
+        if (code.HasCodeItem()) {
+          int32_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
+          DCHECK_NE(offset, 0);
+          cache.emplace_back(offset + code.InsnsSizeInBytes(), accessor.GetClassDefIndex());
+        }
+      }
+    }
+    std::sort(cache.begin(), cache.end());
+
+    // If two consecutive methods belong to same class, we can merge them.
+    // This tends to reduce the number of entries (used memory) by 10x.
+    size_t num_entries = cache.size();
+    if (cache.size() > 1) {
+      for (auto it = std::next(cache.begin()); it != cache.end(); it++) {
+        if (std::prev(it)->second == it->second) {
+          std::prev(it)->first = 0;  // Clear entry with lower end_dex_offset (mark to remove).
+          num_entries--;
         }
       }
     }
 
-    return nullptr;
+    // The cache is immutable now. Store it as continuous vector to save space.
+    class_cache_.reserve(num_entries);
+    auto pred = [](auto it) { return it.first != 0; };  // Entries to copy (not cleared above).
+    std::copy_if(cache.begin(), cache.end(), std::back_inserter(class_cache_), pred);
   }
-};
 
-int ExtDexFileOpenFromMemory(const void* addr,
-                             /*inout*/ size_t* size,
-                             const char* location,
-                             /*out*/ const ExtDexFileString** ext_error_msg,
-                             /*out*/ ExtDexFile** ext_dex_file) {
-  if (*size < sizeof(art::DexFile::Header)) {
-    *size = sizeof(art::DexFile::Header);
-    *ext_error_msg = nullptr;
+  inline bool GetClassDefIndex(uint32_t dex_offset, uint32_t* class_def_index) {
+    if (class_cache_.empty()) {
+      CreateClassCache();
+    }
+
+    // Binary search in the class cache. First element of the pair is the key.
+    auto comp = [](uint32_t value, const auto& it) { return value < it.first; };
+    auto it = std::upper_bound(class_cache_.begin(), class_cache_.end(), dex_offset, comp);
+    if (it != class_cache_.end()) {
+      *class_def_index = it->second;
+      return true;
+    }
     return false;
   }
 
-  const art::DexFile::Header* header = reinterpret_cast<const art::DexFile::Header*>(addr);
+  // The underlying ART object.
+  std::unique_ptr<const art::DexFile> dex_file_;
+
+  // Binary search table with (end_dex_offset, class_def_index) entries.
+  std::vector<std::pair<uint32_t, uint32_t>> class_cache_;
+
+  // Used as short lived temporary when needed. Avoids alloc/free.
+  std::string temporary_qualified_name_;
+};
+
+ADexFile_Error ADexFile_create(const void* _Nonnull address,
+                               size_t size,
+                               size_t* _Nullable new_size,
+                               const char* _Nonnull location,
+                               /*out*/ ADexFile* _Nullable * _Nonnull out_dex_file) {
+  *out_dex_file = nullptr;
+
+  if (size < sizeof(art::DexFile::Header)) {
+    if (new_size != nullptr) {
+      *new_size = sizeof(art::DexFile::Header);
+    }
+    return ADEXFILE_ERROR_NOT_ENOUGH_DATA;
+  }
+
+  const art::DexFile::Header* header = reinterpret_cast<const art::DexFile::Header*>(address);
   uint32_t file_size = header->file_size_;
   if (art::CompactDexFile::IsMagicValid(header->magic_)) {
     // Compact dex files store the data section separately so that it can be shared.
@@ -163,30 +162,27 @@
     //       In practice, this should be fine, as such sharing only happens on disk.
     uint32_t computed_file_size;
     if (__builtin_add_overflow(header->data_off_, header->data_size_, &computed_file_size)) {
-      *ext_error_msg = new ExtDexFileString{
-          android::base::StringPrintf("Corrupt CompactDexFile header in '%s'", location)};
-      return false;
+      return ADEXFILE_ERROR_INVALID_HEADER;
     }
     if (computed_file_size > file_size) {
       file_size = computed_file_size;
     }
   } else if (!art::StandardDexFile::IsMagicValid(header->magic_)) {
-    *ext_error_msg = new ExtDexFileString{
-        android::base::StringPrintf("Unrecognized dex file header in '%s'", location)};
-    return false;
+    return ADEXFILE_ERROR_INVALID_HEADER;
   }
 
-  if (*size < file_size) {
-    *size = file_size;
-    *ext_error_msg = nullptr;
-    return false;
+  if (size < file_size) {
+    if (new_size != nullptr) {
+      *new_size = file_size;
+    }
+    return ADEXFILE_ERROR_NOT_ENOUGH_DATA;
   }
 
   std::string loc_str(location);
   art::DexFileLoader loader;
   std::string error_msg;
-  std::unique_ptr<const art::DexFile> dex_file = loader.Open(static_cast<const uint8_t*>(addr),
-                                                             *size,
+  std::unique_ptr<const art::DexFile> dex_file = loader.Open(static_cast<const uint8_t*>(address),
+                                                             size,
                                                              loc_str,
                                                              header->checksum_,
                                                              /*oat_dex_file=*/nullptr,
@@ -194,149 +190,118 @@
                                                              /*verify_checksum=*/false,
                                                              &error_msg);
   if (dex_file == nullptr) {
-    *ext_error_msg = new ExtDexFileString{std::move(error_msg)};
-    return false;
+    LOG(ERROR) << "Can not open dex file " << loc_str << ": " << error_msg;
+    return ADEXFILE_ERROR_INVALID_DEX;
   }
 
-  *ext_dex_file = new ExtDexFile(std::move(dex_file));
-  return true;
+  *out_dex_file = new ADexFile(std::move(dex_file));
+  return ADEXFILE_ERROR_OK;
 }
 
-int ExtDexFileOpenFromFd(int fd,
-                         off_t offset,
-                         const char* location,
-                         /*out*/ const ExtDexFileString** ext_error_msg,
-                         /*out*/ ExtDexFile** ext_dex_file) {
-  size_t length;
-  {
-    struct stat sbuf;
-    std::memset(&sbuf, 0, sizeof(sbuf));
-    if (fstat(fd, &sbuf) == -1) {
-      *ext_error_msg = new ExtDexFileString{
-          android::base::StringPrintf("fstat '%s' failed: %s", location, std::strerror(errno))};
-      return false;
-    }
-    if (S_ISDIR(sbuf.st_mode)) {
-      *ext_error_msg = new ExtDexFileString{
-          android::base::StringPrintf("Attempt to mmap directory '%s'", location)};
-      return false;
-    }
-    length = sbuf.st_size;
-  }
-
-  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)};
-    return false;
-  }
-
-  // Cannot use MemMap in libartbase here, because it pulls in dlopen which we
-  // can't have when being compiled statically.
-  std::unique_ptr<android::base::MappedFile> map =
-      android::base::MappedFile::FromFd(fd, offset, length, PROT_READ);
-  if (map == nullptr) {
-    *ext_error_msg = new ExtDexFileString{
-        android::base::StringPrintf("mmap '%s' failed: %s", location, std::strerror(errno))};
-    return false;
-  }
-
-  const art::DexFile::Header* header = reinterpret_cast<const art::DexFile::Header*>(map->data());
-  uint32_t file_size;
-  if (__builtin_add_overflow(offset, header->file_size_, &file_size)) {
-    *ext_error_msg =
-        new ExtDexFileString{android::base::StringPrintf("Corrupt header in '%s'", location)};
-    return false;
-  }
-  if (length < file_size) {
-    *ext_error_msg = new ExtDexFileString{
-        android::base::StringPrintf("Dex file '%s' too short: expected %" PRIu32 ", got %" PRIu64,
-                                    location,
-                                    file_size,
-                                    uint64_t{length})};
-    return false;
-  }
-
-  void* addr = map->data();
-  size_t size = map->size();
-  auto container = std::make_unique<art::MappedFileContainer>(std::move(map));
-
-  std::string loc_str(location);
-  std::string error_msg;
-  art::DexFileLoader loader;
-  std::unique_ptr<const art::DexFile> dex_file = loader.Open(reinterpret_cast<const uint8_t*>(addr),
-                                                             size,
-                                                             loc_str,
-                                                             header->checksum_,
-                                                             /*oat_dex_file=*/nullptr,
-                                                             /*verify=*/false,
-                                                             /*verify_checksum=*/false,
-                                                             &error_msg,
-                                                             std::move(container));
-  if (dex_file == nullptr) {
-    *ext_error_msg = new ExtDexFileString{std::move(error_msg)};
-    return false;
-  }
-  *ext_dex_file = new ExtDexFile(std::move(dex_file));
-  return true;
+void ADexFile_destroy(ADexFile* self) {
+  delete self;
 }
 
-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.
+size_t ADexFile_findMethodAtOffset(ADexFile* self,
+                                   size_t dex_offset,
+                                   ADexFile_MethodCallback* callback,
+                                   void* callback_data) {
+  const art::DexFile* dex_file = self->dex_file_.get();
+  if (!dex_file->IsInDataSection(dex_file->Begin() + dex_offset)) {
+    return 0;  // The DEX offset is not within the bytecode of this dex file.
   }
 
-  if (ext_dex_file->dex_file_->IsCompactDexFile()) {
+  if (dex_file->IsCompactDexFile()) {
     // The data section of compact dex files might be shared.
     // Check the subrange unique to this compact dex.
     const art::CompactDexFile::Header& cdex_header =
-        ext_dex_file->dex_file_->AsCompactDexFile()->GetHeader();
+        dex_file->AsCompactDexFile()->GetHeader();
     uint32_t begin = cdex_header.data_off_ + cdex_header.OwnedDataBegin();
     uint32_t end = cdex_header.data_off_ + cdex_header.OwnedDataEnd();
     if (dex_offset < begin || dex_offset >= end) {
-      return false;  // The DEX offset is not within the bytecode of this dex file.
+      return 0;  // The DEX offset is not within the bytecode of this dex file.
     }
   }
 
-  art::MethodCacheEntry* entry = ext_dex_file->GetMethodCacheEntryForOffset(dex_offset);
-  if (entry != nullptr) {
-    method_info->offset = entry->offset;
-    method_info->len = entry->len;
-    method_info->name =
-        new ExtDexFileString{ext_dex_file->dex_file_->PrettyMethod(entry->index, with_signature)};
-    return true;
+  ADexFile_Method info;
+  if (!self->FindMethod(dex_offset, &info)) {
+    return 0;
   }
 
-  return false;
+  callback(callback_data, &info);
+  return 1;
 }
 
-void ExtDexFileGetAllMethodInfos(ExtDexFile* ext_dex_file,
-                                 int with_signature,
-                                 ExtDexFileMethodInfoCallback* method_info_cb,
-                                 void* user_data) {
-  for (art::ClassAccessor accessor : ext_dex_file->dex_file_->GetClasses()) {
+size_t ADexFile_forEachMethod(ADexFile* self,
+                              ADexFile_MethodCallback* callback,
+                              void* callback_data) {
+  size_t count = 0;
+  for (art::ClassAccessor accessor : self->dex_file_->GetClasses()) {
     for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
       art::CodeItemInstructionAccessor code = method.GetInstructions();
-      if (!code.HasCodeItem()) {
-        continue;
+      if (code.HasCodeItem()) {
+        size_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - self->dex_file_->Begin();
+        ADexFile_Method info {
+          .adex = self,
+          .index = method.GetIndex(),
+          .offset = offset,
+          .size = code.InsnsSizeInBytes(),
+        };
+        callback(callback_data, &info);
+        count++;
       }
-
-      ExtDexFileMethodInfo method_info;
-      method_info.offset = static_cast<int32_t>(reinterpret_cast<const uint8_t*>(code.Insns()) -
-                                                ext_dex_file->dex_file_->Begin());
-      method_info.len = code.InsnsSizeInBytes();
-      method_info.name = new ExtDexFileString{
-          ext_dex_file->dex_file_->PrettyMethod(method.GetIndex(), with_signature)};
-      method_info_cb(&method_info, user_data);
     }
   }
+  return count;
 }
 
-void ExtDexFileFree(ExtDexFile* ext_dex_file) { delete (ext_dex_file); }
+size_t ADexFile_Method_getCodeOffset(const ADexFile_Method* self,
+                                     size_t* out_size) {
+  if (out_size != nullptr) {
+    *out_size = self->size;
+  }
+  return self->offset;
+}
+
+const char* ADexFile_Method_getName(const ADexFile_Method* self,
+                                    size_t* out_size) {
+  const char* name = self->adex->dex_file_->GetMethodName(self->index);
+  if (out_size != nullptr) {
+    *out_size = strlen(name);
+  }
+  return name;
+}
+
+const char* ADexFile_Method_getQualifiedName(const ADexFile_Method* self,
+                                             int with_params,
+                                             size_t* out_size) {
+  std::string& temp = self->adex->temporary_qualified_name_;
+  temp.clear();
+  self->adex->dex_file_->AppendPrettyMethod(self->index, with_params, &temp);
+  if (out_size != nullptr) {
+    *out_size = temp.size();
+  }
+  return temp.data();
+}
+
+const char* ADexFile_Method_getClassDescriptor(const ADexFile_Method* self,
+                                               size_t* out_size) {
+  const art::dex::MethodId& method_id = self->adex->dex_file_->GetMethodId(self->index);
+  const char* name = self->adex->dex_file_->GetMethodDeclaringClassDescriptor(method_id);
+  if (out_size != nullptr) {
+    *out_size = strlen(name);
+  }
+  return name;
+}
+
+const char* ADexFile_Error_toString(ADexFile_Error self) {
+  switch (self) {
+    case ADEXFILE_ERROR_OK: return "Ok";
+    case ADEXFILE_ERROR_INVALID_DEX: return "Dex file is invalid.";
+    case ADEXFILE_ERROR_NOT_ENOUGH_DATA: return "Not enough data. Incomplete dex file.";
+    case ADEXFILE_ERROR_INVALID_HEADER: return "Invalid dex file header.";
+  }
+  return nullptr;
+}
 
 }  // extern "C"
diff --git a/libdexfile/external/dex_file_ext_c_test.c b/libdexfile/external/dex_file_ext_c_test.c
index c448a16..656a6cb 100644
--- a/libdexfile/external/dex_file_ext_c_test.c
+++ b/libdexfile/external/dex_file_ext_c_test.c
@@ -14,42 +14,6 @@
  * 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. */
+/* The main purpose of this file 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_ext_test.cc b/libdexfile/external/dex_file_ext_test.cc
new file mode 100644
index 0000000..54aaa3b
--- /dev/null
+++ b/libdexfile/external/dex_file_ext_test.cc
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2021 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_external.h"
+#include "dex_file_test_data.h"
+
+namespace art_api {
+namespace dex {
+
+class ADexFileTest : public ::testing::Test {
+ protected:
+  void TearDown() override {
+    ADexFile_destroy(dex_);
+  }
+
+  ADexFile* dex_ = nullptr;
+};
+
+TEST_F(ADexFileTest, create) {
+  size_t size = sizeof(kDexData);
+  EXPECT_EQ(ADexFile_create(kDexData, size, &size, "", &dex_), ADEXFILE_ERROR_OK);
+  EXPECT_EQ(size, sizeof(kDexData));
+  EXPECT_NE(dex_, nullptr);
+}
+
+TEST_F(ADexFileTest, create_null_new_size) {
+  const size_t size = sizeof(kDexData);
+  EXPECT_EQ(ADexFile_create(kDexData, size, nullptr, "", &dex_), ADEXFILE_ERROR_OK);
+  EXPECT_NE(dex_, nullptr);
+}
+
+TEST_F(ADexFileTest, create_header_too_small) {
+  size_t size = sizeof(art::DexFile::Header) - 1;
+  EXPECT_EQ(ADexFile_create(kDexData, size, &size, "", &dex_), ADEXFILE_ERROR_NOT_ENOUGH_DATA);
+  EXPECT_EQ(size, sizeof(art::DexFile::Header));
+  EXPECT_EQ(dex_, nullptr);
+}
+
+TEST_F(ADexFileTest, create_file_too_small) {
+  size_t size = sizeof(art::DexFile::Header);
+  EXPECT_EQ(ADexFile_create(kDexData, size, &size, "", &dex_), ADEXFILE_ERROR_NOT_ENOUGH_DATA);
+  EXPECT_EQ(size, sizeof(kDexData));
+  EXPECT_EQ(dex_, nullptr);
+}
+
+static ADexFile* GetTestDexData() {
+  size_t size = sizeof(kDexData);
+  ADexFile* dex;
+  EXPECT_EQ(ADexFile_create(kDexData, size, &size, "", &dex), ADEXFILE_ERROR_OK);
+  EXPECT_EQ(size, sizeof(kDexData));
+  EXPECT_NE(dex, nullptr);
+  return dex;
+}
+
+TEST_F(ADexFileTest, findMethodAtOffset) {
+  dex_ = GetTestDexData();
+  ASSERT_NE(dex_, nullptr);
+
+  bool found_init = false;
+  auto check_init = [](void* ctx, const ADexFile_Method* method) {
+    size_t size;
+    size_t offset = ADexFile_Method_getCodeOffset(method, &size);
+    EXPECT_EQ(offset, 0x100u);
+    EXPECT_EQ(size, 8u);
+    EXPECT_STREQ(ADexFile_Method_getName(method, &size), "<init>");
+    EXPECT_STREQ(ADexFile_Method_getQualifiedName(method, false, &size), "Main.<init>");
+    EXPECT_STREQ(ADexFile_Method_getQualifiedName(method, true, &size), "void Main.<init>()");
+    EXPECT_STREQ(ADexFile_Method_getClassDescriptor(method, &size), "LMain;");
+    *reinterpret_cast<bool*>(ctx) = true;
+  };
+  EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x102, check_init, &found_init), 1u);
+  EXPECT_TRUE(found_init);
+
+  bool found_main = false;
+  auto check_main = [](void* ctx, const ADexFile_Method* method) {
+    size_t size;
+    size_t offset = ADexFile_Method_getCodeOffset(method, &size);
+    EXPECT_EQ(offset, 0x118u);
+    EXPECT_EQ(size, 2u);
+    EXPECT_STREQ(ADexFile_Method_getName(method, &size), "main");
+    EXPECT_STREQ(ADexFile_Method_getQualifiedName(method, false, &size), "Main.main");
+    EXPECT_STREQ(ADexFile_Method_getQualifiedName(method, true, &size), "void Main.main(java.lang.String[])");
+    EXPECT_STREQ(ADexFile_Method_getClassDescriptor(method, &size), "LMain;");
+    *reinterpret_cast<bool*>(ctx) = true;
+  };
+  EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x118, check_main, &found_main), 1u);
+  EXPECT_TRUE(found_main);
+}
+
+TEST_F(ADexFileTest, findMethodAtOffset_for_offset_boundaries) {
+  dex_ = GetTestDexData();
+  ASSERT_NE(dex_, nullptr);
+
+  auto no_cb = [](void*, const ADexFile_Method*) {};
+  EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x99, no_cb, nullptr), 0);
+  EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x100, no_cb, nullptr), 1);
+  EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x107, no_cb, nullptr), 1);
+  EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x108, no_cb, nullptr), 0);
+  EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x100000, no_cb, nullptr), 0);
+}
+
+TEST_F(ADexFileTest, forEachMethod) {
+  dex_ = GetTestDexData();
+  ASSERT_NE(dex_, nullptr);
+
+  std::vector<std::string> names;
+  auto add = [](void* ctx, const ADexFile_Method* method) {
+    reinterpret_cast<decltype(names)*>(ctx)->
+        push_back(ADexFile_Method_getQualifiedName(method, false, nullptr));
+  };
+  EXPECT_EQ(ADexFile_forEachMethod(dex_, add, &names), 2u);
+  EXPECT_EQ(names, std::vector<std::string>({"Main.<init>", "Main.main"}));
+}
+
+TEST_F(ADexFileTest, Error_toString) {
+  constexpr size_t kNumErrors = 4;
+  for (size_t i = 0; i < kNumErrors; i++) {
+    const char* err = ADexFile_Error_toString(static_cast<ADexFile_Error>(i));
+    ASSERT_NE(err, nullptr);
+    ASSERT_FALSE(std::string_view(err).empty());
+  }
+  const char* err = ADexFile_Error_toString(static_cast<ADexFile_Error>(kNumErrors));
+  ASSERT_EQ(err, nullptr);
+}
+
+}  // namespace dex
+}  // namespace art_api
diff --git a/libdexfile/external/dex_file_supp.cc b/libdexfile/external/dex_file_supp.cc
index e207953..23fc88a 100644
--- a/libdexfile/external/dex_file_supp.cc
+++ b/libdexfile/external/dex_file_supp.cc
@@ -17,7 +17,12 @@
 #include "art_api/dex_file_support.h"
 
 #include <dlfcn.h>
+#include <inttypes.h>
 #include <mutex>
+#include <sys/stat.h>
+
+#include <android-base/mapped_file.h>
+#include <android-base/stringprintf.h>
 
 #ifndef STATIC_LIB
 // Not used in the static lib, so avoid a dependency on this header in
@@ -28,25 +33,15 @@
 namespace art_api {
 namespace dex {
 
-#define FOR_ALL_DLFUNCS(MACRO) \
-  MACRO(DexString, ExtDexFileMakeString) \
-  MACRO(DexString, ExtDexFileGetString) \
-  MACRO(DexString, ExtDexFileFreeString) \
-  MACRO(DexFile, ExtDexFileOpenFromMemory) \
-  MACRO(DexFile, ExtDexFileOpenFromFd) \
-  MACRO(DexFile, ExtDexFileGetMethodInfoForOffset) \
-  MACRO(DexFile, ExtDexFileGetAllMethodInfos) \
-  MACRO(DexFile, ExtDexFileFree)
-
-#ifdef STATIC_LIB
-#define DEFINE_DLFUNC_PTR(CLASS, DLFUNC) decltype(DLFUNC)* CLASS::g_##DLFUNC = DLFUNC;
+#if defined(STATIC_LIB)
+#define DEFINE_ADEX_FILE_SYMBOL(DLFUNC) decltype(DLFUNC)* g_##DLFUNC = DLFUNC;
 #else
-#define DEFINE_DLFUNC_PTR(CLASS, DLFUNC) decltype(DLFUNC)* CLASS::g_##DLFUNC = nullptr;
+#define DEFINE_ADEX_FILE_SYMBOL(DLFUNC) decltype(DLFUNC)* g_##DLFUNC = nullptr;
 #endif
-FOR_ALL_DLFUNCS(DEFINE_DLFUNC_PTR)
-#undef DEFINE_DLFUNC_PTR
+FOR_EACH_ADEX_FILE_SYMBOL(DEFINE_ADEX_FILE_SYMBOL)
+#undef DEFINE_ADEX_FILE_SYMBOL
 
-bool TryLoadLibdexfileExternal([[maybe_unused]] std::string* err_msg) {
+bool TryLoadLibdexfile([[maybe_unused]] std::string* err_msg) {
 #if defined(STATIC_LIB)
   // Nothing to do here since all function pointers are initialised statically.
   return true;
@@ -64,10 +59,10 @@
     // Check which version is already loaded to avoid loading both debug and
     // release builds. We might also be backtracing from separate process, in
     // which case neither is loaded.
-    const char* so_name = "libdexfiled_external.so";
+    const char* so_name = "libdexfiled.so";
     void* handle = dlopen(so_name, RTLD_NOLOAD | RTLD_NOW | RTLD_NODELETE);
     if (handle == nullptr) {
-      so_name = "libdexfile_external.so";
+      so_name = "libdexfile.so";
       handle = dlopen(so_name, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
     }
     if (handle == nullptr) {
@@ -75,18 +70,18 @@
       return false;
     }
 
-#define RESOLVE_DLFUNC_PTR(CLASS, DLFUNC) \
-    decltype(DLFUNC)* DLFUNC##_ptr = reinterpret_cast<decltype(DLFUNC)*>(dlsym(handle, #DLFUNC)); \
-    if (DLFUNC == nullptr) { \
+#define RESOLVE_ADEX_FILE_SYMBOL(DLFUNC) \
+    auto DLFUNC##_ptr = reinterpret_cast<decltype(DLFUNC)*>(dlsym(handle, #DLFUNC)); \
+    if (DLFUNC##_ptr == nullptr) { \
       *err_msg = dlerror(); \
       return false; \
     }
-    FOR_ALL_DLFUNCS(RESOLVE_DLFUNC_PTR);
-#undef RESOLVE_DLFUNC_PTR
+FOR_EACH_ADEX_FILE_SYMBOL(RESOLVE_ADEX_FILE_SYMBOL)
+#undef RESOLVE_ADEX_FILE_SYMBOL
 
-#define SET_DLFUNC_PTR(CLASS, DLFUNC) CLASS::g_##DLFUNC = DLFUNC##_ptr;
-    FOR_ALL_DLFUNCS(SET_DLFUNC_PTR);
-#undef SET_DLFUNC_PTR
+#define SET_ADEX_FILE_SYMBOL(DLFUNC) g_##DLFUNC = DLFUNC##_ptr;
+    FOR_EACH_ADEX_FILE_SYMBOL(SET_ADEX_FILE_SYMBOL);
+#undef SET_ADEX_FILE_SYMBOL
 
     is_loaded = true;
   }
@@ -95,24 +90,13 @@
 #endif  // !defined(NO_DEXFILE_SUPPORT) && !defined(STATIC_LIB)
 }
 
-void LoadLibdexfileExternal() {
+void LoadLibdexfile() {
 #ifndef STATIC_LIB
-  if (std::string err_msg; !TryLoadLibdexfileExternal(&err_msg)) {
+  if (std::string err_msg; !TryLoadLibdexfile(&err_msg)) {
     LOG_ALWAYS_FATAL("%s", err_msg.c_str());
   }
 #endif
 }
 
-DexFile::~DexFile() { g_ExtDexFileFree(ext_dex_file_); }
-
-MethodInfo DexFile::AbsorbMethodInfo(const ExtDexFileMethodInfo& ext_method_info) {
-  return {ext_method_info.offset, ext_method_info.len, DexString(ext_method_info.name)};
-}
-
-void DexFile::AddMethodInfoCallback(const ExtDexFileMethodInfo* ext_method_info, void* ctx) {
-  auto vect = static_cast<MethodInfoVector*>(ctx);
-  vect->emplace_back(AbsorbMethodInfo(*ext_method_info));
-}
-
 }  // namespace dex
 }  // namespace art_api
diff --git a/libdexfile/external/dex_file_supp_test.cc b/libdexfile/external/dex_file_supp_test.cc
index 6c2f900..3285edf 100644
--- a/libdexfile/external/dex_file_supp_test.cc
+++ b/libdexfile/external/dex_file_supp_test.cc
@@ -25,275 +25,104 @@
 #include <gtest/gtest.h>
 
 #include "art_api/dex_file_support.h"
+#include "dex_file_test_data.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);
+TEST(DexFileTest, create) {
+  size_t size = sizeof(kDexData);
+  std::unique_ptr<DexFile> dex_file;
+  EXPECT_TRUE(DexFile::Create(kDexData, size, &size, "", &dex_file).Ok());
   EXPECT_EQ(size, sizeof(kDexData));
-  EXPECT_TRUE(error_msg.empty());
+  EXPECT_NE(dex_file, nullptr);
+}
+
+TEST(DexFileTest, create_header_too_small) {
+  size_t size = sizeof(art::DexFile::Header) - 1;
+  std::unique_ptr<DexFile> dex_file;
+  DexFile::Error error = DexFile::Create(kDexData, size, &size, "", &dex_file);
+  EXPECT_FALSE(error.Ok());
+  EXPECT_EQ(error.Code(), ADEXFILE_ERROR_NOT_ENOUGH_DATA);
+  EXPECT_STREQ(error.ToString(), "Not enough data. Incomplete dex file.");
+  EXPECT_EQ(size, sizeof(art::DexFile::Header));
+  EXPECT_EQ(dex_file, nullptr);
+}
+
+TEST(DexFileTest, create_file_too_small) {
+  size_t size = sizeof(art::DexFile::Header);
+  std::unique_ptr<DexFile> dex_file;
+  DexFile::Error error = DexFile::Create(kDexData, size, &size, "", &dex_file);
+  EXPECT_FALSE(error.Ok());
+  EXPECT_EQ(error.Code(), ADEXFILE_ERROR_NOT_ENOUGH_DATA);
+  EXPECT_STREQ(error.ToString(), "Not enough data. Incomplete dex file.");
+  EXPECT_EQ(size, sizeof(kDexData));
+  EXPECT_EQ(dex_file, nullptr);
 }
 
 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());
+  std::unique_ptr<DexFile> dex_file;
+  EXPECT_TRUE(DexFile::Create(kDexData, size, &size, "", &dex_file).Ok());
+  EXPECT_EQ(size, sizeof(kDexData));
+  EXPECT_NE(dex_file, nullptr);
   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) {
+TEST(DexFileTest, findMethodAtOffset) {
   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>");
+  bool found_init = false;
+  auto check_init = [&](const DexFile::Method& method) {
+    size_t size;
+    size_t offset = method.GetCodeOffset(&size);
+    EXPECT_EQ(offset, 0x100u);
+    EXPECT_EQ(size, 8u);
+    EXPECT_STREQ(method.GetName(), "<init>");
+    EXPECT_STREQ(method.GetQualifiedName(), "Main.<init>");
+    EXPECT_STREQ(method.GetQualifiedName(true), "void Main.<init>()");
+    EXPECT_STREQ(method.GetClassDescriptor(), "LMain;");
+    found_init = true;
+  };
+  EXPECT_EQ(dex_file->FindMethodAtOffset(0x102, check_init), 1u);
+  EXPECT_TRUE(found_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>");
+  bool found_main = false;
+  auto check_main = [&](const DexFile::Method& method) {
+    size_t size;
+    size_t offset = method.GetCodeOffset(&size);
+    EXPECT_EQ(offset, 0x118u);
+    EXPECT_EQ(size, 2u);
+    EXPECT_STREQ(method.GetName(), "main");
+    EXPECT_STREQ(method.GetQualifiedName(), "Main.main");
+    EXPECT_STREQ(method.GetQualifiedName(true), "void Main.main(java.lang.String[])");
+    EXPECT_STREQ(method.GetClassDescriptor(), "LMain;");
+    found_main = true;
+  };
+  EXPECT_EQ(dex_file->FindMethodAtOffset(0x118, check_main), 1u);
+  EXPECT_TRUE(found_main);
 }
 
 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});
+  EXPECT_EQ(dex_file->FindMethodAtOffset(0x99, [](auto){}), 0);
+  EXPECT_EQ(dex_file->FindMethodAtOffset(0x100, [](auto){}), 1);
+  EXPECT_EQ(dex_file->FindMethodAtOffset(0x107, [](auto){}), 1);
+  EXPECT_EQ(dex_file->FindMethodAtOffset(0x108, [](auto){}), 0);
+  EXPECT_EQ(dex_file->FindMethodAtOffset(0x100000, [](auto){}), 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});
-}
-
-TEST(DexFileTest, pointer_construct) {
-  std::unique_ptr<DexFile> dex_file = GetTestDexData();
-  ASSERT_NE(dex_file, nullptr);
-
-  auto new_dex = DexFile(dex_file);
-  ASSERT_TRUE(dex_file.get() == nullptr);
-
-  MethodInfo info = new_dex.GetMethodInfoForOffset(0x100, false);
-  EXPECT_EQ(info.offset, int32_t{0x100});
+  std::vector<std::string> names;
+  auto add = [&](const DexFile::Method& method) { names.push_back(method.GetQualifiedName()); };
+  EXPECT_EQ(dex_file->ForEachMethod(add), 2u);
+  EXPECT_EQ(names, std::vector<std::string>({"Main.<init>", "Main.main"}));
 }
 
 }  // namespace dex
diff --git a/libdexfile/external/dex_file_test_data.h b/libdexfile/external/dex_file_test_data.h
new file mode 100644
index 0000000..fd6b80b
--- /dev/null
+++ b/libdexfile/external/dex_file_test_data.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 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_DEX_FILE_TEST_DATA_H_
+#define ART_LIBDEXFILE_EXTERNAL_DEX_FILE_TEST_DATA_H_
+
+#include <stdint.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,
+};
+
+}  // namespace dex
+}  // namespace art_api
+
+#endif  // ART_LIBDEXFILE_EXTERNAL_DEX_FILE_TEST_DATA_H_
diff --git a/libdexfile/external/include/art_api/dex_file_external.h b/libdexfile/external/include/art_api/dex_file_external.h
index b29e759..360be92 100644
--- a/libdexfile/external/include/art_api/dex_file_external.h
+++ b/libdexfile/external/include/art_api/dex_file_external.h
@@ -18,72 +18,140 @@
 #define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
 
 // Dex file external API
-
+#include <stdint.h>
+#include <sys/cdefs.h>
 #include <sys/types.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
 // 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;
+struct ADexFile;
+typedef struct ADexFile ADexFile;
 
-// Returns an ExtDexFileString initialized to the given string.
-const struct ExtDexFileString* ExtDexFileMakeString(const char* str, size_t size);
+struct ADexFile_Method;
+typedef struct ADexFile_Method ADexFile_Method;
 
-// 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;
+enum ADexFile_Error : uint32_t {
+  ADEXFILE_ERROR_OK = 0,
+  ADEXFILE_ERROR_INVALID_DEX = 1,
+  ADEXFILE_ERROR_INVALID_HEADER = 2,
+  ADEXFILE_ERROR_NOT_ENOUGH_DATA = 3,
 };
+typedef enum ADexFile_Error ADexFile_Error;
 
-struct ExtDexFile;
+// Callback used to return information about a dex method.
+// The method information is valid only during the callback.
+typedef void ADexFile_MethodCallback(void* _Nullable callback_data,
+                                     const ADexFile_Method* _Nonnull method);
 
-// 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);
+// Interprets a chunk of memory as a dex file.
+//
+// @param address Pointer to the start of dex file data.
+//                The caller must retain the memory until the object is destroyed.
+// @param size Size of the memory range. If the size is too small, the method returns
+//             ADEXFILE_ERROR_NOT_ENOUGH_DATA and sets new_size to some larger size
+//             (which still might large enough, so several retries might be needed).
+// @param new_size On successful load, this contains exact dex file size from header.
+// @param location A string that describes the dex file. Preferably its path.
+//                 It is mostly used just for log messages and may be "".
+// @param dex_file The created dex file object, or nullptr on error.
+//                 It must be later freed with ADexFile_Destroy.
+//
+// @return ADEXFILE_ERROR_OK if successful.
+// @return ADEXFILE_ERROR_NOT_ENOUGH_DATA if the provided dex file is too short (truncated).
+// @return ADEXFILE_ERROR_INVALID_HEADER if the memory does not seem to represent DEX file.
+// @return ADEXFILE_ERROR_INVALID_DEX if any other non-specific error occurs.
+//
+// Thread-safe (creates new object).
+ADexFile_Error ADexFile_create(const void* _Nonnull address,
+                               size_t size,
+                               size_t* _Nullable new_size,
+                               const char* _Nonnull location,
+                               /*out*/ ADexFile* _Nullable * _Nonnull out_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);
+// Find method at given offset and call callback with information about the method.
+//
+// @param dex_offset Offset relative to the start of the dex file header.
+// @param callback The callback to call when method is found. Any data that needs to
+//                 outlive the execution of the callback must be copied by the user.
+// @param callback_data Extra user-specified argument for the callback.
+//
+// @return Number of methods found (0 or 1).
+//
+// Not thread-safe for calls on the same ADexFile instance.
+size_t ADexFile_findMethodAtOffset(ADexFile* _Nonnull self,
+                                   size_t dex_offset,
+                                   ADexFile_MethodCallback* _Nonnull callback,
+                                   void* _Nullable callback_data);
 
-// 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);
+// Call callback for all methods in the DEX file.
+//
+// @param flags Specifies which information should be obtained.
+// @param callback The callback to call for all methods. Any data that needs to
+//                 outlive the execution of the callback must be copied by the user.
+// @param callback_data Extra user-specified argument for the callback.
+//
+// @return Number of methods found.
+//
+// Not thread-safe for calls on the same ADexFile instance.
+size_t ADexFile_forEachMethod(ADexFile* _Nonnull self,
+                              ADexFile_MethodCallback* _Nonnull callback,
+                              void* _Nullable callback_data);
 
-typedef void ExtDexFileMethodInfoCallback(const struct ExtDexFileMethodInfo* ext_method_info,
-                                          void* user_data);
+// Free the given object.
+//
+// Thread-safe, can be called only once for given instance.
+void ADexFile_destroy(ADexFile* _Nullable self);
 
-// See art_api::dex::DexFile::GetAllMethodInfos.
-void ExtDexFileGetAllMethodInfos(struct ExtDexFile* ext_dex_file,
-                                 int with_signature,
-                                 ExtDexFileMethodInfoCallback* method_info_cb,
-                                 void* user_data);
+// @return Offset of byte-code of the method relative to start of the dex file.
+// @param out_size Optionally return size of byte-code in bytes.
+// Not thread-safe for calls on the same ADexFile instance.
+size_t ADexFile_Method_getCodeOffset(const ADexFile_Method* _Nonnull self,
+                                     size_t* _Nullable out_size);
 
-// Frees an ExtDexFile.
-void ExtDexFileFree(struct ExtDexFile* ext_dex_file);
+// @return Method name only (without class).
+//         The encoding is slightly modified UTF8 (see Dex specification).
+// @param out_size Optionally return string size (excluding null-terminator).
+//
+// Returned data may be short lived: it must be copied before calling
+// this method again within the same ADexFile.
+// (it is currently long lived, but this is not guaranteed in the future).
+//
+// Not thread-safe for calls on the same ADexFile instance.
+const char* _Nonnull ADexFile_Method_getName(const ADexFile_Method* _Nonnull self,
+                                             size_t* _Nullable out_size);
 
-#ifdef __cplusplus
-}  // extern "C"
-#endif
+// @return Method name (with class name).
+//         The encoding is slightly modified UTF8 (see Dex specification).
+// @param out_size Optionally return string size (excluding null-terminator).
+// @param with_params Whether to include method parameters and return type.
+//
+// Returned data may be short lived: it must be copied before calling
+// this method again within the same ADexFile.
+// (it points to pretty printing buffer within the ADexFile instance)
+//
+// Not thread-safe for calls on the same ADexFile instance.
+const char* _Nonnull ADexFile_Method_getQualifiedName(const ADexFile_Method* _Nonnull self,
+                                                      int with_params,
+                                                      size_t* _Nullable out_size);
+
+// @return Class descriptor (mangled class name).
+//         The encoding is slightly modified UTF8 (see Dex specification).
+// @param out_size Optionally return string size (excluding null-terminator).
+//
+// Returned data may be short lived: it must be copied before calling
+// this method again within the same ADexFile.
+// (it is currently long lived, but this is not guaranteed in the future).
+//
+// Not thread-safe for calls on the same ADexFile instance.
+const char* _Nonnull ADexFile_Method_getClassDescriptor(const ADexFile_Method* _Nonnull self,
+                                                        size_t* _Nullable out_size);
+
+// @return Compile-time literal or nullptr on error.
+const char* _Nullable ADexFile_Error_toString(ADexFile_Error self);
+
+__END_DECLS
 
 #endif  // ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
diff --git a/libdexfile/external/include/art_api/dex_file_support.h b/libdexfile/external/include/art_api/dex_file_support.h
index 404fa65..2361bf9 100644
--- a/libdexfile/external/include/art_api/dex_file_support.h
+++ b/libdexfile/external/include/art_api/dex_file_support.h
@@ -19,12 +19,8 @@
 
 // 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>
 
@@ -33,204 +29,104 @@
 namespace art_api {
 namespace dex {
 
-// Returns true if libdexfile_external.so is already loaded. Otherwise tries to
+#define FOR_EACH_ADEX_FILE_SYMBOL(MACRO) \
+  MACRO(ADexFile_Error_toString) \
+  MACRO(ADexFile_Method_getClassDescriptor) \
+  MACRO(ADexFile_Method_getCodeOffset) \
+  MACRO(ADexFile_Method_getName) \
+  MACRO(ADexFile_Method_getQualifiedName) \
+  MACRO(ADexFile_create) \
+  MACRO(ADexFile_destroy) \
+  MACRO(ADexFile_findMethodAtOffset) \
+  MACRO(ADexFile_forEachMethod) \
+
+#define DEFINE_ADEX_FILE_SYMBOL(DLFUNC) extern decltype(DLFUNC)* g_##DLFUNC;
+FOR_EACH_ADEX_FILE_SYMBOL(DEFINE_ADEX_FILE_SYMBOL)
+#undef DEFINE_ADEX_FILE_SYMBOL
+
+// Returns true if libdexfile.so is already loaded. Otherwise tries to
 // load it and returns true if successful. Otherwise returns false and sets
-// *error_msg. If false is returned then calling any function below may abort
-// the process. Thread safe.
-bool TryLoadLibdexfileExternal(std::string* error_msg);
+// *error_msg. Thread safe.
+bool TryLoadLibdexfile(std::string* error_msg);
 
-// Loads the libdexfile_external.so library and sets up function pointers.
-// Aborts with a fatal error on any error. For internal use by the classes
-// below.
-void LoadLibdexfileExternal();
+// TryLoadLibdexfile and fatally abort process if unsuccessful.
+void LoadLibdexfile();
 
-// Minimal std::string look-alike for a string returned from libdexfile.
-class DexString final {
- public:
-  DexString(DexString&& dex_str) noexcept : ext_string_(dex_str.ext_string_) {
-    dex_str.ext_string_ = MakeExtDexFileString("", 0);
-  }
-  explicit DexString(const char* str = "")
-      : ext_string_(MakeExtDexFileString(str, std::strlen(str))) {}
-  explicit DexString(std::string_view str)
-      : ext_string_(MakeExtDexFileString(str.data(), str.size())) {}
-  ~DexString() { g_ExtDexFileFreeString(ext_string_); }
-
-  DexString& operator=(DexString&& dex_str) noexcept {
-    std::swap(ext_string_, dex_str.ext_string_);
-    return *this;
-  }
-
-  const char* data() const {
-    size_t ignored;
-    return g_ExtDexFileGetString(ext_string_, &ignored);
-  }
-  const char* c_str() const { return data(); }
-
-  size_t size() const {
-    size_t len;
-    (void)g_ExtDexFileGetString(ext_string_, &len);
-    return len;
-  }
-  size_t length() const { return size(); }
-
-  operator std::string_view() const {
-    size_t len;
-    const char* chars = g_ExtDexFileGetString(ext_string_, &len);
-    return std::string_view(chars, len);
-  }
-
- private:
-  friend bool TryLoadLibdexfileExternal(std::string* error_msg);
-  friend class DexFile;
-  friend bool operator==(const DexString&, const DexString&);
-  explicit DexString(const ExtDexFileString* ext_string) : ext_string_(ext_string) {}
-  const ExtDexFileString* ext_string_;  // Owned instance. Never nullptr.
-
-  // These are initialized by TryLoadLibdexfileExternal.
-  static decltype(ExtDexFileMakeString)* g_ExtDexFileMakeString;
-  static decltype(ExtDexFileGetString)* g_ExtDexFileGetString;
-  static decltype(ExtDexFileFreeString)* g_ExtDexFileFreeString;
-
-  static const struct ExtDexFileString* MakeExtDexFileString(const char* str, size_t size) {
-    if (UNLIKELY(g_ExtDexFileMakeString == nullptr)) {
-      LoadLibdexfileExternal();
-    }
-    return g_ExtDexFileMakeString(str, size);
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(DexString);
-};
-
-inline bool operator==(const DexString& s1, const DexString& s2) {
-  size_t l1, l2;
-  const char* str1 = DexString::g_ExtDexFileGetString(s1.ext_string_, &l1);
-  const char* str2 = DexString::g_ExtDexFileGetString(s2.ext_string_, &l2);
-  // Use memcmp to avoid assumption about absence of null characters in the strings.
-  return l1 == l2 && !std::memcmp(str1, str2, l1);
-}
-
-struct MethodInfo {
-  int32_t offset;  // Code offset relative to the start of the dex file header
-  int32_t len;  // Code length
-  DexString name;
-};
-
-inline bool operator==(const MethodInfo& s1, const MethodInfo& s2) {
-  return s1.offset == s2.offset && s1.len == s2.len && s1.name == s2.name;
-}
-
-// External stable API to access ordinary dex files and CompactDex. This wraps
-// the stable C ABI and handles instance ownership. Thread-compatible but not
-// thread-safe.
+// API for reading ordinary dex files and CompactDex files.
+// It is minimal 1:1 C++ wrapper around the C ABI.
+// See documentation in dex_file_external.h
 class DexFile {
  public:
-  DexFile(DexFile&& dex_file) noexcept {
-    ext_dex_file_ = dex_file.ext_dex_file_;
-    dex_file.ext_dex_file_ = nullptr;
-  }
-
-  explicit DexFile(std::unique_ptr<DexFile>& dex_file) noexcept {
-    ext_dex_file_ = dex_file->ext_dex_file_;
-    dex_file->ext_dex_file_ = nullptr;
-    dex_file.reset(nullptr);
-  }
-  virtual ~DexFile();
-
-  // Interprets a chunk of memory as a dex file. As long as *size is too small,
-  // returns nullptr, sets *size to a new size to try again with, and sets
-  // *error_msg to "". That might happen repeatedly. Also returns nullptr
-  // on error in which case *error_msg is set to a nonempty string.
-  //
-  // location is a string that describes the dex file, and is preferably its
-  // path. It is mostly used to make error messages better, and may be "".
-  //
-  // The caller must retain the memory.
-  static std::unique_ptr<DexFile> OpenFromMemory(const void* addr,
-                                                 size_t* size,
-                                                 const std::string& location,
-                                                 /*out*/ std::string* error_msg) {
-    if (UNLIKELY(g_ExtDexFileOpenFromMemory == nullptr)) {
-      // Load libdexfile_external.so in this factory function, so instance
-      // methods don't need to check this.
-      LoadLibdexfileExternal();
+  struct Method {
+    size_t GetCodeOffset(size_t* out_size = nullptr) const {
+      return g_ADexFile_Method_getCodeOffset(self, out_size);
     }
-    ExtDexFile* ext_dex_file;
-    const ExtDexFileString* ext_error_msg = nullptr;
-    if (g_ExtDexFileOpenFromMemory(addr, size, location.c_str(), &ext_error_msg, &ext_dex_file)) {
-      return std::unique_ptr<DexFile>(new DexFile(ext_dex_file));
+
+    const char* GetName(size_t* out_size = nullptr) const {
+      return g_ADexFile_Method_getName(self, out_size);
     }
-    *error_msg = (ext_error_msg == nullptr) ? "" : std::string(DexString(ext_error_msg));
-    return nullptr;
+
+    const char* GetQualifiedName(bool with_params = false, size_t* out_size = nullptr) const {
+      return g_ADexFile_Method_getQualifiedName(self, with_params, out_size);
+    }
+
+    const char* GetClassDescriptor(size_t* out_size = nullptr) const {
+      return g_ADexFile_Method_getClassDescriptor(self, out_size);
+    }
+
+    const ADexFile_Method* const self;
+  };
+
+  struct Error {
+    const char* ToString() const {
+      return g_ADexFile_Error_toString(self);
+    }
+
+    bool Ok() const {
+      return self == ADEXFILE_ERROR_OK;
+    }
+
+    ADexFile_Error Code() {
+      return self;
+    }
+
+    ADexFile_Error const self;
+  };
+
+  static Error Create(const void* address,
+                      size_t size,
+                      size_t* new_size,
+                      const char* location,
+                      /*out*/ std::unique_ptr<DexFile>* out_dex_file) {
+    LoadLibdexfile();
+    ADexFile* adex = nullptr;
+    ADexFile_Error error = g_ADexFile_create(address, size, new_size, location, &adex);
+    if (adex != nullptr) {
+      *out_dex_file = std::unique_ptr<DexFile>(new DexFile{adex});
+    }
+    return Error{error};
   }
 
-  // mmaps the given file offset in the open fd and reads a dexfile from there.
-  // Returns nullptr on error in which case *error_msg is set.
-  //
-  // location is a string that describes the dex file, and is preferably its
-  // path. It is mostly used to make error messages better, and may be "".
-  static std::unique_ptr<DexFile> OpenFromFd(int fd,
-                                             off_t offset,
-                                             const std::string& location,
-                                             /*out*/ std::string* error_msg) {
-    if (UNLIKELY(g_ExtDexFileOpenFromFd == nullptr)) {
-      // Load libdexfile_external.so in this factory function, so instance
-      // methods don't need to check this.
-      LoadLibdexfileExternal();
-    }
-    ExtDexFile* ext_dex_file;
-    const ExtDexFileString* ext_error_msg = nullptr;
-    if (g_ExtDexFileOpenFromFd(fd, offset, location.c_str(), &ext_error_msg, &ext_dex_file)) {
-      return std::unique_ptr<DexFile>(new DexFile(ext_dex_file));
-    }
-    *error_msg = std::string(DexString(ext_error_msg));
-    return nullptr;
+  virtual ~DexFile() {
+    g_ADexFile_destroy(self_);
   }
 
-  // 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.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 (g_ExtDexFileGetMethodInfoForOffset(ext_dex_file_,
-                                           dex_offset,
-                                           with_signature,
-                                           &ext_method_info)) {
-      return AbsorbMethodInfo(ext_method_info);
-    }
-    return {/*offset=*/0, /*len=*/0, /*name=*/DexString()};
+  template<typename T /* lambda which takes (const DexFile::Method&) as argument */>
+  inline size_t FindMethodAtOffset(uint32_t dex_offset, T callback) {
+    auto cb = [](void* ctx, const ADexFile_Method* m) { (*reinterpret_cast<T*>(ctx))(Method{m}); };
+    return g_ADexFile_findMethodAtOffset(self_, dex_offset, cb, &callback);
   }
 
-  // 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) {
-    MethodInfoVector res;
-    g_ExtDexFileGetAllMethodInfos(ext_dex_file_,
-                                  with_signature,
-                                  AddMethodInfoCallback,
-                                  static_cast<void*>(&res));
-    return res;
+  template<typename T /* lambda which takes (const DexFile::Method&) as argument */>
+  inline size_t ForEachMethod(T callback) {
+    auto cb = [](void* ctx, const ADexFile_Method* m) { (*reinterpret_cast<T*>(ctx))(Method{m}); };
+    return g_ADexFile_forEachMethod(self_, cb, &callback);
   }
 
- private:
-  friend bool TryLoadLibdexfileExternal(std::string* error_msg);
-  explicit DexFile(ExtDexFile* ext_dex_file) : ext_dex_file_(ext_dex_file) {}
-  ExtDexFile* ext_dex_file_;  // Owned instance. nullptr only in moved-from zombies.
+ protected:
+  explicit DexFile(ADexFile* self) : self_(self) {}
 
-  typedef std::vector<MethodInfo> MethodInfoVector;
-
-  static MethodInfo AbsorbMethodInfo(const ExtDexFileMethodInfo& ext_method_info);
-  static void AddMethodInfoCallback(const ExtDexFileMethodInfo* ext_method_info, void* user_data);
-
-  // These are initialized by TryLoadLibdexfileExternal.
-  static decltype(ExtDexFileOpenFromMemory)* g_ExtDexFileOpenFromMemory;
-  static decltype(ExtDexFileOpenFromFd)* g_ExtDexFileOpenFromFd;
-  static decltype(ExtDexFileGetMethodInfoForOffset)* g_ExtDexFileGetMethodInfoForOffset;
-  static decltype(ExtDexFileGetAllMethodInfos)* g_ExtDexFileGetAllMethodInfos;
-  static decltype(ExtDexFileFree)* g_ExtDexFileFree;
+  ADexFile* const self_;
 
   DISALLOW_COPY_AND_ASSIGN(DexFile);
 };
diff --git a/libdexfile/external/libdexfile_external.map.txt b/libdexfile/external/libdexfile_external.map.txt
deleted file mode 100644
index 450b633..0000000
--- a/libdexfile/external/libdexfile_external.map.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-LIBDEXFILE_EXTERNAL_1 {
-  global:
-    ExtDexFileFree;
-    ExtDexFileFreeString;
-    ExtDexFileGetAllMethodInfos;
-    ExtDexFileGetMethodInfoForOffset;
-    ExtDexFileGetString;
-    ExtDexFileMakeString;
-    ExtDexFileOpenFromFd;
-    ExtDexFileOpenFromMemory;
-  local:
-    *;
-};
diff --git a/libdexfile/libdexfile.map.txt b/libdexfile/libdexfile.map.txt
new file mode 100644
index 0000000..9cbdc13
--- /dev/null
+++ b/libdexfile/libdexfile.map.txt
@@ -0,0 +1,14 @@
+LIBDEXFILE_1 {
+  global:
+    ADexFile_Error_toString; # apex
+    ADexFile_Method_getClassDescriptor; # apex
+    ADexFile_Method_getCodeOffset; # apex
+    ADexFile_Method_getName; # apex
+    ADexFile_Method_getQualifiedName; # apex
+    ADexFile_create; # apex
+    ADexFile_destroy; # apex
+    ADexFile_findMethodAtOffset; # apex
+    ADexFile_forEachMethod; # apex
+  local:
+    *;
+};
diff --git a/libelffile/Android.bp b/libelffile/Android.bp
index de7fa96..8281068 100644
--- a/libelffile/Android.bp
+++ b/libelffile/Android.bp
@@ -14,8 +14,18 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 art_cc_defaults {
     name: "libelffile-defaults",
+    defaults: ["art_defaults"],
     host_supported: true,
     export_include_dirs: ["."],
     srcs: [
@@ -27,20 +37,20 @@
     ],
     shared_libs: [
         "libbase",
+        "liblzma",
     ],
 }
 
 art_cc_library_static {
     name: "libelffile",
     defaults: [
-        "art_defaults",
         "libelffile-defaults",
     ],
     shared_libs: [
         "libartbase",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
diff --git a/libelffile/dwarf/register.h b/libelffile/dwarf/register.h
index eadb441..7742ec4 100644
--- a/libelffile/dwarf/register.h
+++ b/libelffile/dwarf/register.h
@@ -40,10 +40,6 @@
   static Reg ArmDp(int num) { return Reg(256 + num); }  // D0–D31.
   static Reg Arm64Core(int num) { return Reg(num); }  // X0-X31.
   static Reg Arm64Fp(int num) { return Reg(64 + num); }  // V0-V31.
-  static Reg MipsCore(int num) { return Reg(num); }
-  static Reg Mips64Core(int num) { return Reg(num); }
-  static Reg MipsFp(int num) { return Reg(32 + num); }
-  static Reg Mips64Fp(int num) { return Reg(32 + num); }
   static Reg X86Core(int num) { return Reg(num); }
   static Reg X86Fp(int num) { return Reg(21 + num); }
   static Reg X86_64Core(int num) {
diff --git a/libelffile/elf/elf_builder.h b/libelffile/elf/elf_builder.h
index 07f0d00..086bd41 100644
--- a/libelffile/elf/elf_builder.h
+++ b/libelffile/elf/elf_builder.h
@@ -130,7 +130,7 @@
     }
 
     // Start writing file data of this section.
-    void Start() {
+    virtual void Start() {
       CHECK(owner_->current_section_ == nullptr);
       Elf_Word align = AddSection();
       CHECK_EQ(header_.sh_offset, 0u);
@@ -139,7 +139,7 @@
     }
 
     // Finish writing file data of this section.
-    void End() {
+    virtual void End() {
       CHECK(owner_->current_section_ == this);
       Elf_Word position = GetPosition();
       CHECK(header_.sh_size == 0u || header_.sh_size == position);
@@ -310,7 +310,12 @@
       last_offset_ = 0;
     }
 
-    Elf_Word Write(const std::string& name) {
+    void Start() {
+      Section::Start();
+      Write("");  // ELF specification requires that the section starts with empty string.
+    }
+
+    Elf_Word Write(std::string_view name) {
       if (current_offset_ == 0) {
         DCHECK(name.empty());
       } else if (name == last_name_) {
@@ -318,7 +323,9 @@
       }
       last_name_ = name;
       last_offset_ = current_offset_;
-      this->WriteFully(name.c_str(), name.length() + 1);
+      this->WriteFully(name.data(), name.length());
+      char null_terminator = '\0';
+      this->WriteFully(&null_terminator, sizeof(null_terminator));
       current_offset_ += name.length() + 1;
       return last_offset_;
     }
@@ -366,10 +373,13 @@
 
     // Buffer symbol for this section.  It will be written later.
     void Add(Elf_Sym sym, const Section* section) {
-      DCHECK(section != nullptr);
-      DCHECK_LE(section->GetAddress(), sym.st_value);
-      DCHECK_LE(sym.st_value, section->GetAddress() + section->header_.sh_size);
-      sym.st_shndx = section->GetSectionIndex();
+      if (section != nullptr) {
+        DCHECK_LE(section->GetAddress(), sym.st_value);
+        DCHECK_LE(sym.st_value, section->GetAddress() + section->header_.sh_size);
+        sym.st_shndx = section->GetSectionIndex();
+      } else {
+        sym.st_shndx = SHN_UNDEF;
+      }
       syms_.push_back(sym);
     }
 
@@ -733,7 +743,7 @@
     // Buckets.  Having just one makes it linear search.
     hash.push_back(1);  // Point to first non-NULL symbol.
     // Chains.  This creates linked list of symbols.
-    hash.push_back(0);  // Dummy entry for the NULL symbol.
+    hash.push_back(0);  // Placeholder entry for the NULL symbol.
     for (int i = 1; i < count - 1; i++) {
       hash.push_back(i + 1);  // Each symbol points to the next one.
     }
@@ -798,6 +808,21 @@
      return stream_.Seek(RoundUp(stream_.Seek(0, kSeekCurrent), alignment), kSeekSet);
   }
 
+  static InstructionSet GetIsaFromHeader(const Elf_Ehdr& header) {
+    switch (header.e_machine) {
+      case EM_ARM:
+        return InstructionSet::kThumb2;
+      case EM_AARCH64:
+        return InstructionSet::kArm64;
+      case EM_386:
+        return InstructionSet::kX86;
+      case EM_X86_64:
+        return InstructionSet::kX86_64;
+    }
+    LOG(FATAL) << "Unknown architecture: " << header.e_machine;
+    UNREACHABLE();
+  }
+
  private:
   static Elf_Ehdr MakeElfHeader(InstructionSet isa) {
     Elf_Ehdr elf_header = Elf_Ehdr();
@@ -832,6 +857,8 @@
         LOG(FATAL) << "Unknown instruction set " << isa;
       }
     }
+    DCHECK_EQ(GetIsaFromHeader(elf_header),
+              (isa == InstructionSet::kArm) ? InstructionSet::kThumb2 : isa);
 
     elf_header.e_ident[EI_MAG0]       = ELFMAG0;
     elf_header.e_ident[EI_MAG1]       = ELFMAG1;
diff --git a/libelffile/elf/elf_debug_reader.h b/libelffile/elf/elf_debug_reader.h
index 2b03037..266c638 100644
--- a/libelffile/elf/elf_debug_reader.h
+++ b/libelffile/elf/elf_debug_reader.h
@@ -36,6 +36,7 @@
  public:
   // Note that the input buffer might be misaligned.
   typedef typename ElfTypes::Ehdr ALIGNED(1) Elf_Ehdr;
+  typedef typename ElfTypes::Phdr ALIGNED(1) Elf_Phdr;
   typedef typename ElfTypes::Shdr ALIGNED(1) Elf_Shdr;
   typedef typename ElfTypes::Sym ALIGNED(1) Elf_Sym;
   typedef typename ElfTypes::Addr ALIGNED(1) Elf_Addr;
@@ -65,10 +66,11 @@
     CHECK_EQ(header_->e_ident[1], ELFMAG1);
     CHECK_EQ(header_->e_ident[2], ELFMAG2);
     CHECK_EQ(header_->e_ident[3], ELFMAG3);
+    CHECK_EQ(header_->e_ident[4], sizeof(Elf_Addr) / sizeof(uint32_t));
     CHECK_EQ(header_->e_ehsize, sizeof(Elf_Ehdr));
-    CHECK_EQ(header_->e_shentsize, sizeof(Elf_Shdr));
 
     // Find all ELF sections.
+    CHECK_EQ(header_->e_shentsize, sizeof(Elf_Shdr));
     sections_ = Read<Elf_Shdr>(header_->e_shoff, header_->e_shnum);
     for (const Elf_Shdr& section : sections_) {
       const char* name = Read<char>(sections_[header_->e_shstrndx].sh_offset + section.sh_name);
@@ -84,16 +86,38 @@
     }
   }
 
-  explicit ElfDebugReader(std::vector<uint8_t>& file)
+  explicit ElfDebugReader(const std::vector<uint8_t>& file)
       : ElfDebugReader(ArrayRef<const uint8_t>(file)) {
   }
 
+  // Check that ELF signature is present at the start of the files,
+  // and that the ELF bitness matches the ElfTypes template arguments.
+  static bool IsValidElfHeader(const std::vector<uint8_t>& data) {
+    static constexpr bool kIs64Bit = sizeof(Elf_Addr) == sizeof(uint64_t);
+    static constexpr char kMagic[] = { 0x7f, 'E', 'L', 'F', kIs64Bit ? 2 : 1 };
+    return data.size() >= sizeof(kMagic) && memcmp(data.data(), kMagic, sizeof(kMagic)) == 0;
+  }
+
   const Elf_Ehdr* GetHeader() { return header_; }
 
   ArrayRef<Elf_Shdr> GetSections() { return sections_; }
 
   const Elf_Shdr* GetSection(const char* name) { return section_map_[name]; }
 
+  // Find the base address where the ELF file wants to be loaded.
+  // This is generally zero (therefore always requiring relocation).
+  Elf_Addr GetLoadAddress() {
+    std::optional<Elf_Addr> addr;
+    CHECK_EQ(header_->e_phentsize, sizeof(Elf_Phdr));
+    for (const Elf_Phdr& phdr : Read<Elf_Phdr>(header_->e_phoff, header_->e_phnum)) {
+      if (phdr.p_type == PT_LOAD) {
+        addr = addr.has_value() ? std::min(addr.value(), phdr.p_vaddr) : phdr.p_vaddr;
+      }
+    }
+    CHECK(addr.has_value());
+    return addr.value();
+  }
+
   template <typename VisitSym>
   void VisitFunctionSymbols(VisitSym visit_sym) {
     const Elf_Shdr* symtab = GetSection(".symtab");
diff --git a/libelffile/elf/elf_utils.h b/libelffile/elf/elf_utils.h
index a20312a..181dd10 100644
--- a/libelffile/elf/elf_utils.h
+++ b/libelffile/elf/elf_utils.h
@@ -62,14 +62,9 @@
 
 // Architecture dependent flags for the ELF header.
 #define EF_ARM_EABI_VER5 0x05000000
-#define EF_MIPS_ABI_O32 0x00001000
-#define EF_MIPS_ARCH_32R2 0x70000000
-#define EF_MIPS_ARCH_32R6 0x90000000
-#define EF_MIPS_ARCH_64R6 0xa0000000
 
 #define EI_ABIVERSION 8
 #define EM_ARM 40
-#define EF_MIPS_NOREORDER 1
 #define STV_DEFAULT 0
 
 #define EM_AARCH64 183
@@ -82,24 +77,6 @@
 #define DT_RUNPATH 29
 #define DT_FLAGS 30
 
-/* MIPS dependent d_tag field for Elf32_Dyn.  */
-#define DT_MIPS_RLD_VERSION  0x70000001 /* Runtime Linker Interface ID */
-#define DT_MIPS_TIME_STAMP   0x70000002 /* Timestamp */
-#define DT_MIPS_ICHECKSUM    0x70000003 /* Cksum of ext. str. and com. sizes */
-#define DT_MIPS_IVERSION     0x70000004 /* Version string (string tbl index) */
-#define DT_MIPS_FLAGS        0x70000005 /* Flags */
-#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Segment base address */
-#define DT_MIPS_CONFLICT     0x70000008 /* Adr of .conflict section */
-#define DT_MIPS_LIBLIST      0x70000009 /* Address of .liblist section */
-#define DT_MIPS_LOCAL_GOTNO  0x7000000a /* Number of local .GOT entries */
-#define DT_MIPS_CONFLICTNO   0x7000000b /* Number of .conflict entries */
-#define DT_MIPS_LIBLISTNO    0x70000010 /* Number of .liblist entries */
-#define DT_MIPS_SYMTABNO     0x70000011 /* Number of .dynsym entries */
-#define DT_MIPS_UNREFEXTNO   0x70000012 /* First external DYNSYM */
-#define DT_MIPS_GOTSYM       0x70000013 /* First GOT entry in .dynsym */
-#define DT_MIPS_HIPAGENO     0x70000014 /* Number of GOT page table entries */
-#define DT_MIPS_RLD_MAP      0x70000016 /* Address of debug map pointer */
-
 // Patching section type
 #define SHT_OAT_PATCH        SHT_LOUSER
 
@@ -107,7 +84,9 @@
   sym->st_info = (b << 4) + (t & 0x0f);
 }
 
-static inline bool IsDynamicSectionPointer(Elf32_Word d_tag, Elf32_Word e_machine) {
+static inline bool IsDynamicSectionPointer(Elf32_Word d_tag,
+                                           Elf32_Word e_machine ATTRIBUTE_UNUSED) {
+  // TODO: Remove the `e_machine` parameter from API (not needed after Mips target was removed).
   switch (d_tag) {
     // case 1: well known d_tag values that imply Elf32_Dyn.d_un contains an address in d_ptr
     case DT_PLTGOT:
@@ -158,35 +137,7 @@
       if ((DT_ENCODING  < d_tag && d_tag < DT_LOOS)
           || (DT_LOOS   < d_tag && d_tag < DT_HIOS)
           || (DT_LOPROC < d_tag && d_tag < DT_HIPROC)) {
-        // Special case for MIPS which breaks the regular rules between DT_LOPROC and DT_HIPROC
-        if (e_machine == EM_MIPS) {
-          switch (d_tag) {
-            case DT_MIPS_RLD_VERSION:
-            case DT_MIPS_TIME_STAMP:
-            case DT_MIPS_ICHECKSUM:
-            case DT_MIPS_IVERSION:
-            case DT_MIPS_FLAGS:
-            case DT_MIPS_LOCAL_GOTNO:
-            case DT_MIPS_CONFLICTNO:
-            case DT_MIPS_LIBLISTNO:
-            case DT_MIPS_SYMTABNO:
-            case DT_MIPS_UNREFEXTNO:
-            case DT_MIPS_GOTSYM:
-            case DT_MIPS_HIPAGENO: {
-              return false;
-            }
-            case DT_MIPS_BASE_ADDRESS:
-            case DT_MIPS_CONFLICT:
-            case DT_MIPS_LIBLIST:
-            case DT_MIPS_RLD_MAP: {
-              return true;
-            }
-            default: {
-              LOG(FATAL) << "Unknown MIPS d_tag value 0x" << std::hex << d_tag;
-              return false;
-            }
-          }
-        } else if ((d_tag % 2) == 0) {
+        if ((d_tag % 2) == 0) {
           return true;
         } else {
           return false;
diff --git a/libelffile/elf/xz_utils.cc b/libelffile/elf/xz_utils.cc
index 87c9a7b..f064cb0 100644
--- a/libelffile/elf/xz_utils.cc
+++ b/libelffile/elf/xz_utils.cc
@@ -32,8 +32,6 @@
 
 namespace art {
 
-constexpr size_t kChunkSize = 16 * KB;
-
 static void XzInitCrc() {
   static std::once_flag crc_initialized;
   std::call_once(crc_initialized, []() {
@@ -42,14 +40,17 @@
   });
 }
 
-void XzCompress(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst, int level) {
+void XzCompress(ArrayRef<const uint8_t> src,
+                std::vector<uint8_t>* dst,
+                int level,
+                size_t block_size) {
   // Configure the compression library.
   XzInitCrc();
   CLzma2EncProps lzma2Props;
   Lzma2EncProps_Init(&lzma2Props);
   lzma2Props.lzmaProps.level = level;
   lzma2Props.lzmaProps.reduceSize = src.size();  // Size of data that will be compressed.
-  lzma2Props.blockSize = kChunkSize;
+  lzma2Props.blockSize = block_size;
   Lzma2EncProps_Normalize(&lzma2Props);
   CXzProps props;
   XzProps_Init(&props);
diff --git a/libelffile/elf/xz_utils.h b/libelffile/elf/xz_utils.h
index df5cb56..b1903ff 100644
--- a/libelffile/elf/xz_utils.h
+++ b/libelffile/elf/xz_utils.h
@@ -20,10 +20,17 @@
 #include <vector>
 
 #include "base/array_ref.h"
+#include "base/bit_utils.h"
 
 namespace art {
 
-void XzCompress(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst, int level = 1 /* speed */);
+constexpr size_t kXzDefaultBlockSize = 16 * KB;
+
+void XzCompress(ArrayRef<const uint8_t> src,
+                std::vector<uint8_t>* dst,
+                int level = 1 /* speed */,
+                size_t block_size = kXzDefaultBlockSize);
+
 void XzDecompress(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst);
 
 }  // namespace art
diff --git a/libnativebridge/.clang-format b/libnativebridge/.clang-format
deleted file mode 120000
index fd0645f..0000000
--- a/libnativebridge/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-2
\ No newline at end of file
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index 60bf3ad..8e87997 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -1,11 +1,23 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "libnativebridge-defaults",
     defaults: ["art_defaults"],
-    cppflags: [
-        "-fvisibility=protected",
+    header_libs: [
+        "jni_headers",
+        "libnativebridge-headers",
     ],
-    header_libs: ["libnativebridge-headers"],
-    export_header_lib_headers: ["libnativebridge-headers"],
+    export_header_lib_headers: [
+        "jni_headers",
+        "libnativebridge-headers",
+    ],
 }
 
 cc_library_headers {
@@ -16,12 +28,14 @@
 
     apex_available: [
         "//apex_available:platform",
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
+        "com.android.media",
     ],
+    min_sdk_version: "S",
 }
 
-cc_library {
+art_cc_library {
     name: "libnativebridge",
     defaults: ["libnativebridge-defaults"],
     visibility: [
@@ -30,7 +44,7 @@
         "//frameworks/base/native/webview/loader/libwebviewchromium_loader",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 
@@ -47,10 +61,10 @@
 
     target: {
         android: {
-            version_script: "libnativebridge.map.txt",
-        },
-        linux: {
-            version_script: "libnativebridge.map.txt",
+            header_libs: [
+                "libnativeloader-headers", // For dlext_namespaces.h
+            ],
+            shared_libs: ["libdl_android"],
         },
     },
 
@@ -70,10 +84,16 @@
         "//frameworks/native/opengl/libs",
         "//frameworks/native/vulkan/libvulkan",
     ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+        "com.android.media.swcodec",
+    ],
 
     host_supported: false,
     srcs: ["native_bridge_lazy.cc"],
-    required: ["libnativebridge"],
+    runtime_libs: ["libnativebridge"],
+    shared_libs: ["liblog"],
 }
 
 subdirs = ["tests"]
diff --git a/libnativebridge/include/nativebridge/native_bridge.h b/libnativebridge/include/nativebridge/native_bridge.h
index e20b627..2199bab 100644
--- a/libnativebridge/include/nativebridge/native_bridge.h
+++ b/libnativebridge/include/nativebridge/native_bridge.h
@@ -29,6 +29,11 @@
 extern "C" {
 #endif  // __cplusplus
 
+// Loads a shared library from the system linker namespace, suitable for
+// platform libraries in /system/lib(64). If linker namespaces don't exist (i.e.
+// on host), this simply calls dlopen().
+void* OpenSystemLibrary(const char* path, int flags);
+
 struct NativeBridgeRuntimeCallbacks;
 struct NativeBridgeRuntimeValues;
 
diff --git a/libnativebridge/libnativebridge.map.txt b/libnativebridge/libnativebridge.map.txt
index 158363b..8b51ab8 100644
--- a/libnativebridge/libnativebridge.map.txt
+++ b/libnativebridge/libnativebridge.map.txt
@@ -14,33 +14,18 @@
 # limitations under the License.
 #
 
-# TODO(b/122710865): Most of these uses come from libnativeloader, which should be bundled
-# together with libnativebridge in the APEX. Once this happens, prune this list.
+# Platform dependencies go through libnativebridge_lazy, which accesses
+# libnativebridge symbols through dlopen/dlsym. That means this list doesn't
+# have much effect, rather it's the function wrappers in native_bridge_lazy.cpp
+# that defines the exported interface. Please keep in sync with this list.
 LIBNATIVEBRIDGE_1 {
   global:
-    NativeBridgeIsSupported;
-    NativeBridgeLoadLibrary;
-    NativeBridgeUnloadLibrary;
     NativeBridgeGetError;
-    NativeBridgeIsPathSupported;
-    NativeBridgeCreateNamespace;
-    NativeBridgeGetExportedNamespace;
-    NativeBridgeLinkNamespaces;
-    NativeBridgeLoadLibraryExt;
-    NativeBridgeInitAnonymousNamespace;
     NativeBridgeInitialized;
     NativeBridgeGetTrampoline;
-    LoadNativeBridge;
     PreInitializeNativeBridge;
-    PreZygoteForkNativeBridge;
-    InitializeNativeBridge;
-    NativeBridgeGetVersion;
-    NativeBridgeGetSignalHandler;
-    UnloadNativeBridge;
     NativeBridgeAvailable;
     NeedsNativeBridge;
-    NativeBridgeError;
-    NativeBridgeNameAcceptable;
   local:
     *;
 };
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index b24d14a..fb13d62 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -31,6 +31,10 @@
 #include <android-base/macros.h>
 #include <log/log.h>
 
+#ifdef ART_TARGET_ANDROID
+#include "nativeloader/dlext_namespaces.h"
+#endif
+
 namespace android {
 
 #ifdef __APPLE__
@@ -40,6 +44,28 @@
 
 extern "C" {
 
+void* OpenSystemLibrary(const char* path, int flags) {
+#ifdef ART_TARGET_ANDROID
+  // The system namespace is called "default" for binaries in /system and
+  // "system" for those in the Runtime APEX. Try "system" first since
+  // "default" always exists.
+  // TODO(b/185587109): Get rid of this error prone logic.
+  android_namespace_t* system_ns = android_get_exported_namespace("system");
+  if (system_ns == nullptr) {
+    system_ns = android_get_exported_namespace("default");
+    LOG_ALWAYS_FATAL_IF(system_ns == nullptr,
+                        "Failed to get system namespace for loading %s", path);
+  }
+  const android_dlextinfo dlextinfo = {
+      .flags = ANDROID_DLEXT_USE_NAMESPACE,
+      .library_namespace = system_ns,
+  };
+  return android_dlopen_ext(path, flags, &dlextinfo);
+#else
+  return dlopen(path, flags);
+#endif
+}
+
 // Environment values required by the apps running with native bridge.
 struct NativeBridgeRuntimeValues {
     const char* os_arch;
@@ -223,8 +249,12 @@
     if (!NativeBridgeNameAcceptable(nb_library_filename)) {
       CloseNativeBridge(true);
     } else {
-      // Try to open the library.
-      void* handle = dlopen(nb_library_filename, RTLD_LAZY);
+      // Try to open the library. We assume this library is provided by the
+      // platform rather than the ART APEX itself, so use the system namespace
+      // to avoid requiring a static linker config link to it from the
+      // com_android_art namespace.
+      void* handle = OpenSystemLibrary(nb_library_filename, RTLD_LAZY);
+
       if (handle != nullptr) {
         callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle,
                                                                    kNativeBridgeInterfaceSymbol));
@@ -233,13 +263,18 @@
             // Store the handle for later.
             native_bridge_handle = handle;
           } else {
+            ALOGW("Unsupported native bridge API in %s (is version %d not compatible with %d)",
+                  nb_library_filename, callbacks->version, NAMESPACE_VERSION);
             callbacks = nullptr;
             dlclose(handle);
-            ALOGW("Unsupported native bridge interface.");
           }
         } else {
           dlclose(handle);
+          ALOGW("Unsupported native bridge API in %s: %s not found",
+                nb_library_filename, kNativeBridgeInterfaceSymbol);
         }
+      } else {
+        ALOGW("Failed to load native bridge implementation: %s", dlerror());
       }
 
       // Two failure conditions: could not find library (dlopen failed), or could not find native
@@ -263,6 +298,65 @@
   return strncmp(instruction_set, ABI_STRING, strlen(ABI_STRING) + 1) != 0;
 }
 
+#ifndef __APPLE__
+static bool MountCpuinfo(const char* cpuinfo_path) {
+  // If the file does not exist, the mount command will fail,
+  // so we save the extra file existence check.
+  if (TEMP_FAILURE_RETRY(mount(cpuinfo_path,        // Source.
+                               "/proc/cpuinfo",     // Target.
+                               nullptr,             // FS type.
+                               MS_BIND,             // Mount flags: bind mount.
+                               nullptr)) == -1) {   // "Data."
+    ALOGW("Failed to bind-mount %s as /proc/cpuinfo: %s", cpuinfo_path, strerror(errno));
+    return false;
+  }
+  return true;
+}
+#endif
+
+static void MountCpuinfoForInstructionSet(const char* instruction_set) {
+  if (instruction_set == nullptr) {
+    return;
+  }
+
+  size_t isa_len = strlen(instruction_set);
+  if (isa_len > 10) {
+    // 10 is a loose upper bound on the currently known instruction sets (a tight bound is 7 for
+    // x86_64 [including the trailing \0]). This is so we don't have to change here if there will
+    // be another instruction set in the future.
+    ALOGW("Instruction set %s is malformed, must be less than or equal to 10 characters.",
+          instruction_set);
+    return;
+  }
+
+#if defined(__APPLE__)
+  ALOGW("Mac OS does not support bind-mounting. Host simulation of native bridge impossible.");
+
+#elif !defined(__ANDROID__)
+  // To be able to test on the host, we hardwire a relative path.
+  MountCpuinfo("./cpuinfo");
+
+#else  // __ANDROID__
+  char cpuinfo_path[1024];
+
+  // Bind-mount /system/etc/cpuinfo.<isa>.txt to /proc/cpuinfo.
+  snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/etc/cpuinfo.%s.txt", instruction_set);
+  if (MountCpuinfo(cpuinfo_path)) {
+    return;
+  }
+
+  // Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo.
+  // TODO(b/179753190): remove when all implementations migrate to system/etc!
+#ifdef __LP64__
+  snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib64/%s/cpuinfo", instruction_set);
+#else
+  snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib/%s/cpuinfo", instruction_set);
+#endif  // __LP64__
+  MountCpuinfo(cpuinfo_path);
+
+#endif
+}
+
 bool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) {
   if (state != NativeBridgeState::kOpened) {
     ALOGE("Invalid state: native bridge is expected to be opened.");
@@ -281,52 +375,11 @@
     app_code_cache_dir = nullptr;
   }
 
-  // Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo.
-  // Failure is not fatal and will keep the native bridge in kPreInitialized.
+  // Mount cpuinfo that corresponds to the instruction set.
+  // Failure is not fatal.
+  MountCpuinfoForInstructionSet(instruction_set);
+
   state = NativeBridgeState::kPreInitialized;
-
-#ifndef __APPLE__
-  if (instruction_set == nullptr) {
-    return true;
-  }
-  size_t isa_len = strlen(instruction_set);
-  if (isa_len > 10) {
-    // 10 is a loose upper bound on the currently known instruction sets (a tight bound is 7 for
-    // x86_64 [including the trailing \0]). This is so we don't have to change here if there will
-    // be another instruction set in the future.
-    ALOGW("Instruction set %s is malformed, must be less than or equal to 10 characters.",
-          instruction_set);
-    return true;
-  }
-
-  // If the file does not exist, the mount command will fail,
-  // so we save the extra file existence check.
-  char cpuinfo_path[1024];
-
-#if defined(__ANDROID__)
-  snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib"
-#ifdef __LP64__
-      "64"
-#endif  // __LP64__
-      "/%s/cpuinfo", instruction_set);
-#else   // !__ANDROID__
-  // To be able to test on the host, we hardwire a relative path.
-  snprintf(cpuinfo_path, sizeof(cpuinfo_path), "./cpuinfo");
-#endif
-
-  // Bind-mount.
-  if (TEMP_FAILURE_RETRY(mount(cpuinfo_path,        // Source.
-                               "/proc/cpuinfo",     // Target.
-                               nullptr,             // FS type.
-                               MS_BIND,             // Mount flags: bind mount.
-                               nullptr)) == -1) {   // "Data."
-    ALOGW("Failed to bind-mount %s as /proc/cpuinfo: %s", cpuinfo_path, strerror(errno));
-  }
-#else  // __APPLE__
-  UNUSED(instruction_set);
-  ALOGW("Mac OS does not support bind-mounting. Host simulation of native bridge impossible.");
-#endif
-
   return true;
 }
 
diff --git a/libnativebridge/native_bridge_lazy.cc b/libnativebridge/native_bridge_lazy.cc
index edc7848..dd8a806 100644
--- a/libnativebridge/native_bridge_lazy.cc
+++ b/libnativebridge/native_bridge_lazy.cc
@@ -40,16 +40,10 @@
   return f;
 }
 
-#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&name)>(#name)
+#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&(name))>(#name)
 
 }  // namespace
 
-bool LoadNativeBridge(const char* native_bridge_library_filename,
-                      const struct NativeBridgeRuntimeCallbacks* runtime_callbacks) {
-  static auto f = GET_FUNC_PTR(LoadNativeBridge);
-  return f(native_bridge_library_filename, runtime_callbacks);
-}
-
 bool NeedsNativeBridge(const char* instruction_set) {
   static auto f = GET_FUNC_PTR(NeedsNativeBridge);
   return f(instruction_set);
@@ -60,21 +54,6 @@
   return f(app_data_dir, instruction_set);
 }
 
-void PreZygoteForkNativeBridge() {
-  static auto f = GET_FUNC_PTR(PreZygoteForkNativeBridge);
-  return f();
-}
-
-bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
-  static auto f = GET_FUNC_PTR(InitializeNativeBridge);
-  return f(env, instruction_set);
-}
-
-void UnloadNativeBridge() {
-  static auto f = GET_FUNC_PTR(UnloadNativeBridge);
-  return f();
-}
-
 bool NativeBridgeAvailable() {
   static auto f = GET_FUNC_PTR(NativeBridgeAvailable);
   return f();
@@ -85,88 +64,16 @@
   return f();
 }
 
-void* NativeBridgeLoadLibrary(const char* libpath, int flag) {
-  static auto f = GET_FUNC_PTR(NativeBridgeLoadLibrary);
-  return f(libpath, flag);
-}
-
 void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len) {
   static auto f = GET_FUNC_PTR(NativeBridgeGetTrampoline);
   return f(handle, name, shorty, len);
 }
 
-bool NativeBridgeIsSupported(const char* libpath) {
-  static auto f = GET_FUNC_PTR(NativeBridgeIsSupported);
-  return f(libpath);
-}
-
-uint32_t NativeBridgeGetVersion() {
-  static auto f = GET_FUNC_PTR(NativeBridgeGetVersion);
-  return f();
-}
-
-NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
-  static auto f = GET_FUNC_PTR(NativeBridgeGetSignalHandler);
-  return f(signal);
-}
-
-bool NativeBridgeError() {
-  static auto f = GET_FUNC_PTR(NativeBridgeError);
-  return f();
-}
-
-bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename) {
-  static auto f = GET_FUNC_PTR(NativeBridgeNameAcceptable);
-  return f(native_bridge_library_filename);
-}
-
-int NativeBridgeUnloadLibrary(void* handle) {
-  static auto f = GET_FUNC_PTR(NativeBridgeUnloadLibrary);
-  return f(handle);
-}
-
 const char* NativeBridgeGetError() {
   static auto f = GET_FUNC_PTR(NativeBridgeGetError);
   return f();
 }
 
-bool NativeBridgeIsPathSupported(const char* path) {
-  static auto f = GET_FUNC_PTR(NativeBridgeIsPathSupported);
-  return f(path);
-}
-
-bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
-                                        const char* anon_ns_library_path) {
-  static auto f = GET_FUNC_PTR(NativeBridgeInitAnonymousNamespace);
-  return f(public_ns_sonames, anon_ns_library_path);
-}
-
-struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
-    const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
-    const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent_ns) {
-  static auto f = GET_FUNC_PTR(NativeBridgeCreateNamespace);
-  return f(name, ld_library_path, default_library_path, type, permitted_when_isolated_path,
-           parent_ns);
-}
-
-bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
-                                struct native_bridge_namespace_t* to,
-                                const char* shared_libs_sonames) {
-  static auto f = GET_FUNC_PTR(NativeBridgeLinkNamespaces);
-  return f(from, to, shared_libs_sonames);
-}
-
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
-                                 struct native_bridge_namespace_t* ns) {
-  static auto f = GET_FUNC_PTR(NativeBridgeLoadLibraryExt);
-  return f(libpath, flag, ns);
-}
-
-struct native_bridge_namespace_t* NativeBridgeGetVendorNamespace() {
-  static auto f = GET_FUNC_PTR(NativeBridgeGetVendorNamespace);
-  return f();
-}
-
 #undef GET_FUNC_PTR
 
 }  // namespace android
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
index 4ccf35e..b789a2e 100644
--- a/libnativebridge/tests/Android.bp
+++ b/libnativebridge/tests/Android.bp
@@ -14,8 +14,17 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
-    name: "libnativebridge-dummy-defaults",
+    name: "libnativebridge-test-case-defaults",
     defaults: [
         "art_defaults",
         "art_test_defaults",
@@ -32,52 +41,53 @@
             ],
         },
     },
-    header_libs: ["libnativebridge-headers"],
+    header_libs: [
+        "jni_headers",
+        "libnativebridge-headers",
+    ],
     cppflags: ["-fvisibility=protected"],
 }
 
-cc_library_shared {
-    name: "libnativebridge-dummy",
-    srcs: ["DummyNativeBridge.cpp"],
-    defaults: ["libnativebridge-dummy-defaults"],
+cc_test_library {
+    name: "libnativebridge-test-case",
+    srcs: ["NativeBridgeTestCase.cpp"],
+    defaults: ["libnativebridge-test-case-defaults"],
 }
 
-cc_library_shared {
-    name: "libnativebridge2-dummy",
-    srcs: ["DummyNativeBridge2.cpp"],
-    defaults: ["libnativebridge-dummy-defaults"],
+cc_test_library {
+    name: "libnativebridge2-test-case",
+    srcs: ["NativeBridgeTestCase2.cpp"],
+    defaults: ["libnativebridge-test-case-defaults"],
 }
 
-cc_library_shared {
-    name: "libnativebridge3-dummy",
-    srcs: ["DummyNativeBridge3.cpp"],
-    defaults: ["libnativebridge-dummy-defaults"],
+cc_test_library {
+    name: "libnativebridge3-test-case",
+    srcs: ["NativeBridgeTestCase3.cpp"],
+    defaults: ["libnativebridge-test-case-defaults"],
 }
 
-cc_library_shared {
-    name: "libnativebridge6-dummy",
-    srcs: ["DummyNativeBridge6.cpp"],
-    defaults: ["libnativebridge-dummy-defaults"],
+cc_test_library {
+    name: "libnativebridge6-test-case",
+    srcs: ["NativeBridgeTestCase6.cpp"],
+    defaults: ["libnativebridge-test-case-defaults"],
     shared_libs: [
         "libnativebridge6prezygotefork",
     ],
 }
 
-// A helper library to produce dummy side effect of PreZygoteForkNativeBridge.
-cc_library_shared {
+// A helper library to produce test-case side effect of PreZygoteForkNativeBridge.
+cc_test_library {
     name: "libnativebridge6prezygotefork",
     srcs: ["NativeBridge6PreZygoteFork_lib.cpp"],
-    defaults: ["libnativebridge-dummy-defaults"],
+    defaults: ["libnativebridge-test-case-defaults"],
 }
 
-// Build the unit tests.
 cc_defaults {
     name: "libnativebridge-tests-defaults",
     defaults: [
         "art_defaults",
         "art_test_defaults",
     ],
-    test_per_src: true,
     // TODO(mast): Split up art_gtest_defaults so that it can be used for the
     // following without pulling in lots of libs.
     target: {
@@ -90,8 +100,18 @@
             ],
         },
     },
+}
+
+cc_test {
+    name: "libnativebridge-tests",
+    defaults: ["libnativebridge-tests-defaults"],
+
+    // native_bridge.cc doesn't support reloading the native bridge after
+    // unloading, so each test needs to be its own process.
+    test_per_src: true,
 
     srcs: [
+        "NativeBridgeApi.c",
         "CodeCacheCreate_test.cpp",
         "CodeCacheExists_test.cpp",
         "CodeCacheStatFail_test.cpp",
@@ -101,7 +121,6 @@
         "NativeBridgeVersion_test.cpp",
         "NeedsNativeBridge_test.cpp",
         "PreInitializeNativeBridge_test.cpp",
-        "PreInitializeNativeBridgeFail1_test.cpp",
         "PreInitializeNativeBridgeFail2_test.cpp",
         "ReSetupNativeBridge_test.cpp",
         "UnavailableNativeBridge_test.cpp",
@@ -117,47 +136,24 @@
 
     shared_libs: [
         "liblog",
-        "libnativebridge-dummy",
+        "libnativebridge",
+        "libnativebridge-test-case",
+        "libnativebridge2-test-case",
+        "libnativebridge3-test-case",
+        "libnativebridge6-test-case",
         "libnativebridge6prezygotefork",
     ],
     header_libs: ["libbase_headers"],
 }
 
 cc_test {
-    name: "libnativebridge-tests",
-    defaults: ["libnativebridge-tests-defaults"],
-    shared_libs: ["libnativebridge"],
-}
-
-cc_test {
     name: "libnativebridge-lazy-tests",
     defaults: ["libnativebridge-tests-defaults"],
     host_supported: false,
-    shared_libs: ["libnativebridge_lazy"],
-}
-
-// Build the test for the C API.
-cc_test {
-    name: "libnativebridge-api-tests",
-    defaults: [
-        "art_defaults",
-        "art_test_defaults",
+    test_suites: ["device-tests"],
+    static_libs: [
+        "libbase",
+        "libnativebridge_lazy",
     ],
-    test_per_src: true,
-    // TODO(mast): Split up art_gtest_defaults so that it can be used for the
-    // following without pulling in lots of libs.
-    target: {
-        linux: {
-            cflags: [
-                // gtest issue
-                "-Wno-used-but-marked-unused",
-                "-Wno-deprecated",
-                "-Wno-missing-noreturn",
-            ],
-        },
-    },
-    srcs: [
-        "NativeBridgeApi.c",
-    ],
-    header_libs: ["libnativebridge-headers"],
+    srcs: ["libnativebridge_lazy_test.cpp"],
 }
diff --git a/libnativebridge/tests/CodeCacheCreate_test.cpp b/libnativebridge/tests/CodeCacheCreate_test.cpp
index 58270c4..1bd309c 100644
--- a/libnativebridge/tests/CodeCacheCreate_test.cpp
+++ b/libnativebridge/tests/CodeCacheCreate_test.cpp
@@ -23,9 +23,10 @@
 namespace android {
 
 // Tests that the bridge initialization creates the code_cache if it doesn't
-// exists.
+// exist.
 TEST_F(NativeBridgeTest, CodeCacheCreate) {
-    // Make sure that code_cache does not exists
+    // Make sure that code_cache does not exist
+    rmdir(kCodeCache);
     struct stat st;
     ASSERT_EQ(-1, stat(kCodeCache, &st));
     ASSERT_EQ(ENOENT, errno);
diff --git a/libnativebridge/tests/DummyNativeBridge.cpp b/libnativebridge/tests/DummyNativeBridge.cpp
deleted file mode 100644
index b9894f6..0000000
--- a/libnativebridge/tests/DummyNativeBridge.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-// A dummy implementation of the native-bridge interface.
-
-#include "nativebridge/native_bridge.h"
-
-// NativeBridgeCallbacks implementations
-extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
-                                         const char* /* app_code_cache_dir */,
-                                         const char* /* isa */) {
-  return true;
-}
-
-extern "C" void* native_bridge_loadLibrary(const char* /* libpath */, int /* flag */) {
-  return nullptr;
-}
-
-extern "C" void* native_bridge_getTrampoline(void* /* handle */, const char* /* name */,
-                                             const char* /* shorty */, uint32_t /* len */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge_isSupported(const char* /* libpath */) {
-  return false;
-}
-
-extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv(
-    const char* /* abi */) {
-  return nullptr;
-}
-
-android::NativeBridgeCallbacks NativeBridgeItf {
-  .version = 1,
-  .initialize = &native_bridge_initialize,
-  .loadLibrary = &native_bridge_loadLibrary,
-  .getTrampoline = &native_bridge_getTrampoline,
-  .isSupported = &native_bridge_isSupported,
-  .getAppEnv = &native_bridge_getAppEnv
-};
diff --git a/libnativebridge/tests/DummyNativeBridge2.cpp b/libnativebridge/tests/DummyNativeBridge2.cpp
deleted file mode 100644
index 6920c74..0000000
--- a/libnativebridge/tests/DummyNativeBridge2.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.
- */
-
-// A dummy implementation of the native-bridge interface.
-
-#include "nativebridge/native_bridge.h"
-
-#include <signal.h>
-
-// NativeBridgeCallbacks implementations
-extern "C" bool native_bridge2_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
-                                         const char* /* app_code_cache_dir */,
-                                         const char* /* isa */) {
-  return true;
-}
-
-extern "C" void* native_bridge2_loadLibrary(const char* /* libpath */, int /* flag */) {
-  return nullptr;
-}
-
-extern "C" void* native_bridge2_getTrampoline(void* /* handle */, const char* /* name */,
-                                             const char* /* shorty */, uint32_t /* len */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge2_isSupported(const char* /* libpath */) {
-  return false;
-}
-
-extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge2_getAppEnv(
-    const char* /* abi */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge2_is_compatible_compatible_with(uint32_t version) {
-  // For testing, allow 1 and 2, but disallow 3+.
-  return version <= 2;
-}
-
-static bool native_bridge2_dummy_signal_handler(int, siginfo_t*, void*) {
-  // TODO: Implement something here. We'd either have to have a death test with a log here, or
-  //       we'd have to be able to resume after the faulting instruction...
-  return true;
-}
-
-extern "C" android::NativeBridgeSignalHandlerFn native_bridge2_get_signal_handler(int signal) {
-  if (signal == SIGSEGV) {
-    return &native_bridge2_dummy_signal_handler;
-  }
-  return nullptr;
-}
-
-android::NativeBridgeCallbacks NativeBridgeItf {
-  .version = 2,
-  .initialize = &native_bridge2_initialize,
-  .loadLibrary = &native_bridge2_loadLibrary,
-  .getTrampoline = &native_bridge2_getTrampoline,
-  .isSupported = &native_bridge2_isSupported,
-  .getAppEnv = &native_bridge2_getAppEnv,
-  .isCompatibleWith = &native_bridge2_is_compatible_compatible_with,
-  .getSignalHandler = &native_bridge2_get_signal_handler
-};
-
diff --git a/libnativebridge/tests/DummyNativeBridge3.cpp b/libnativebridge/tests/DummyNativeBridge3.cpp
deleted file mode 100644
index 4ef1c82..0000000
--- a/libnativebridge/tests/DummyNativeBridge3.cpp
+++ /dev/null
@@ -1,124 +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.
- */
-
-// A dummy implementation of the native-bridge interface.
-
-#include "nativebridge/native_bridge.h"
-
-#include <signal.h>
-
-// NativeBridgeCallbacks implementations
-extern "C" bool native_bridge3_initialize(
-                      const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
-                      const char* /* app_code_cache_dir */,
-                      const char* /* isa */) {
-  return true;
-}
-
-extern "C" void* native_bridge3_loadLibrary(const char* /* libpath */, int /* flag */) {
-  return nullptr;
-}
-
-extern "C" void* native_bridge3_getTrampoline(void* /* handle */, const char* /* name */,
-                                             const char* /* shorty */, uint32_t /* len */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge3_isSupported(const char* /* libpath */) {
-  return false;
-}
-
-extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge3_getAppEnv(
-    const char* /* abi */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge3_isCompatibleWith(uint32_t version) {
-  // For testing, allow 1-3, but disallow 4+.
-  return version <= 3;
-}
-
-static bool native_bridge3_dummy_signal_handler(int, siginfo_t*, void*) {
-  // TODO: Implement something here. We'd either have to have a death test with a log here, or
-  //       we'd have to be able to resume after the faulting instruction...
-  return true;
-}
-
-extern "C" android::NativeBridgeSignalHandlerFn native_bridge3_getSignalHandler(int signal) {
-  if (signal == SIGSEGV) {
-    return &native_bridge3_dummy_signal_handler;
-  }
-  return nullptr;
-}
-
-extern "C" int native_bridge3_unloadLibrary(void* /* handle */) {
-  return 0;
-}
-
-extern "C" const char* native_bridge3_getError() {
-  return nullptr;
-}
-
-extern "C" bool native_bridge3_isPathSupported(const char* /* path */) {
-  return true;
-}
-
-extern "C" bool native_bridge3_initAnonymousNamespace(const char* /* public_ns_sonames */,
-                                                      const char* /* anon_ns_library_path */) {
-  return true;
-}
-
-extern "C" android::native_bridge_namespace_t*
-native_bridge3_createNamespace(const char* /* name */,
-                               const char* /* ld_library_path */,
-                               const char* /* default_library_path */,
-                               uint64_t /* type */,
-                               const char* /* permitted_when_isolated_path */,
-                               android::native_bridge_namespace_t* /* parent_ns */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge3_linkNamespaces(android::native_bridge_namespace_t* /* from */,
-                                              android::native_bridge_namespace_t* /* to */,
-                                              const char* /* shared_libs_soname */) {
-  return true;
-}
-
-extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */,
-                                               int /* flag */,
-                                               android::native_bridge_namespace_t* /* ns */) {
-  return nullptr;
-}
-
-android::NativeBridgeCallbacks NativeBridgeItf{
-    // v1
-    .version = 3,
-    .initialize = &native_bridge3_initialize,
-    .loadLibrary = &native_bridge3_loadLibrary,
-    .getTrampoline = &native_bridge3_getTrampoline,
-    .isSupported = &native_bridge3_isSupported,
-    .getAppEnv = &native_bridge3_getAppEnv,
-    // v2
-    .isCompatibleWith = &native_bridge3_isCompatibleWith,
-    .getSignalHandler = &native_bridge3_getSignalHandler,
-    // v3
-    .unloadLibrary = &native_bridge3_unloadLibrary,
-    .getError = &native_bridge3_getError,
-    .isPathSupported = &native_bridge3_isPathSupported,
-    .initAnonymousNamespace = &native_bridge3_initAnonymousNamespace,
-    .createNamespace = &native_bridge3_createNamespace,
-    .linkNamespaces = &native_bridge3_linkNamespaces,
-    .loadLibraryExt = &native_bridge3_loadLibraryExt};
diff --git a/libnativebridge/tests/DummyNativeBridge6.cpp b/libnativebridge/tests/DummyNativeBridge6.cpp
deleted file mode 100644
index ce27e67..0000000
--- a/libnativebridge/tests/DummyNativeBridge6.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-// A dummy implementation of the native-bridge interface.
-
-#include "nativebridge/native_bridge.h"
-
-#include "NativeBridge6PreZygoteFork_lib.h"
-
-// NativeBridgeCallbacks implementations
-extern "C" bool native_bridge6_initialize(
-                      const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
-                      const char* /* app_code_cache_dir */,
-                      const char* /* isa */) {
-  return true;
-}
-
-extern "C" void* native_bridge6_loadLibrary(const char* /* libpath */, int /* flag */) {
-  return nullptr;
-}
-
-extern "C" void* native_bridge6_getTrampoline(void* /* handle */, const char* /* name */,
-                                             const char* /* shorty */, uint32_t /* len */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge6_isSupported(const char* /* libpath */) {
-  return false;
-}
-
-extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge6_getAppEnv(
-    const char* /* abi */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge6_isCompatibleWith(uint32_t version) {
-  // For testing, allow 1-6, but disallow 7+.
-  return version <= 6;
-}
-
-extern "C" android::NativeBridgeSignalHandlerFn native_bridge6_getSignalHandler(int /* signal */) {
-  return nullptr;
-}
-
-extern "C" int native_bridge6_unloadLibrary(void* /* handle */) {
-  return 0;
-}
-
-extern "C" const char* native_bridge6_getError() {
-  return nullptr;
-}
-
-extern "C" bool native_bridge6_isPathSupported(const char* /* path */) {
-  return true;
-}
-
-extern "C" bool native_bridge6_initAnonymousNamespace(const char* /* public_ns_sonames */,
-                                                      const char* /* anon_ns_library_path */) {
-  return true;
-}
-
-extern "C" android::native_bridge_namespace_t*
-native_bridge6_createNamespace(const char* /* name */,
-                               const char* /* ld_library_path */,
-                               const char* /* default_library_path */,
-                               uint64_t /* type */,
-                               const char* /* permitted_when_isolated_path */,
-                               android::native_bridge_namespace_t* /* parent_ns */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge6_linkNamespaces(android::native_bridge_namespace_t* /* from */,
-                                              android::native_bridge_namespace_t* /* to */,
-                                              const char* /* shared_libs_soname */) {
-  return true;
-}
-
-extern "C" void* native_bridge6_loadLibraryExt(const char* /* libpath */,
-                                               int /* flag */,
-                                               android::native_bridge_namespace_t* /* ns */) {
-  return nullptr;
-}
-
-extern "C" android::native_bridge_namespace_t* native_bridge6_getVendorNamespace() {
-  return nullptr;
-}
-
-extern "C" android::native_bridge_namespace_t* native_bridge6_getExportedNamespace(const char* /* name */) {
-  return nullptr;
-}
-
-extern "C" void native_bridge6_preZygoteFork() {
-  android::SetPreZygoteForkDone();
-}
-
-android::NativeBridgeCallbacks NativeBridgeItf{
-    // v1
-    .version = 6,
-    .initialize = &native_bridge6_initialize,
-    .loadLibrary = &native_bridge6_loadLibrary,
-    .getTrampoline = &native_bridge6_getTrampoline,
-    .isSupported = &native_bridge6_isSupported,
-    .getAppEnv = &native_bridge6_getAppEnv,
-    // v2
-    .isCompatibleWith = &native_bridge6_isCompatibleWith,
-    .getSignalHandler = &native_bridge6_getSignalHandler,
-    // v3
-    .unloadLibrary = &native_bridge6_unloadLibrary,
-    .getError = &native_bridge6_getError,
-    .isPathSupported = &native_bridge6_isPathSupported,
-    .initAnonymousNamespace = &native_bridge6_initAnonymousNamespace,
-    .createNamespace = &native_bridge6_createNamespace,
-    .linkNamespaces = &native_bridge6_linkNamespaces,
-    .loadLibraryExt = &native_bridge6_loadLibraryExt,
-    // v4
-    &native_bridge6_getVendorNamespace,
-    // v5
-    &native_bridge6_getExportedNamespace,
-    // v6
-    &native_bridge6_preZygoteFork};
diff --git a/libnativebridge/tests/NativeBridge2Signal_test.cpp b/libnativebridge/tests/NativeBridge2Signal_test.cpp
index 44e45e3..0573a5a 100644
--- a/libnativebridge/tests/NativeBridge2Signal_test.cpp
+++ b/libnativebridge/tests/NativeBridge2Signal_test.cpp
@@ -21,8 +21,6 @@
 
 namespace android {
 
-constexpr const char* kNativeBridgeLibrary2 = "libnativebridge2-dummy.so";
-
 TEST_F(NativeBridgeTest, V2_Signal) {
     // Init
     ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary2, nullptr));
diff --git a/libnativebridge/tests/NativeBridge3CreateNamespace_test.cpp b/libnativebridge/tests/NativeBridge3CreateNamespace_test.cpp
index 668d942..db7dd31 100644
--- a/libnativebridge/tests/NativeBridge3CreateNamespace_test.cpp
+++ b/libnativebridge/tests/NativeBridge3CreateNamespace_test.cpp
@@ -18,8 +18,6 @@
 
 namespace android {
 
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
 TEST_F(NativeBridgeTest, V3_CreateNamespace) {
     // Init
     ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
diff --git a/libnativebridge/tests/NativeBridge3GetError_test.cpp b/libnativebridge/tests/NativeBridge3GetError_test.cpp
index 0b9f582..afd0a7d 100644
--- a/libnativebridge/tests/NativeBridge3GetError_test.cpp
+++ b/libnativebridge/tests/NativeBridge3GetError_test.cpp
@@ -18,8 +18,6 @@
 
 namespace android {
 
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
 TEST_F(NativeBridgeTest, V3_GetError) {
     // Init
     ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
diff --git a/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp b/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
index b0d6b09..f82c9e9 100644
--- a/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
+++ b/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
@@ -18,8 +18,6 @@
 
 namespace android {
 
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
 TEST_F(NativeBridgeTest, V3_InitAnonymousNamespace) {
   // Init
   ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
diff --git a/libnativebridge/tests/NativeBridge3IsPathSupported_test.cpp b/libnativebridge/tests/NativeBridge3IsPathSupported_test.cpp
index 325e40b..4cbc0e8 100644
--- a/libnativebridge/tests/NativeBridge3IsPathSupported_test.cpp
+++ b/libnativebridge/tests/NativeBridge3IsPathSupported_test.cpp
@@ -18,8 +18,6 @@
 
 namespace android {
 
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
 TEST_F(NativeBridgeTest, V3_IsPathSupported) {
     // Init
     ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
diff --git a/libnativebridge/tests/NativeBridge3LoadLibraryExt_test.cpp b/libnativebridge/tests/NativeBridge3LoadLibraryExt_test.cpp
index 4caeb44..3d66768 100644
--- a/libnativebridge/tests/NativeBridge3LoadLibraryExt_test.cpp
+++ b/libnativebridge/tests/NativeBridge3LoadLibraryExt_test.cpp
@@ -18,8 +18,6 @@
 
 namespace android {
 
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
 TEST_F(NativeBridgeTest, V3_LoadLibraryExt) {
     // Init
     ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
diff --git a/libnativebridge/tests/NativeBridge3UnloadLibrary_test.cpp b/libnativebridge/tests/NativeBridge3UnloadLibrary_test.cpp
index 93a979c..a366edc 100644
--- a/libnativebridge/tests/NativeBridge3UnloadLibrary_test.cpp
+++ b/libnativebridge/tests/NativeBridge3UnloadLibrary_test.cpp
@@ -18,8 +18,6 @@
 
 namespace android {
 
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
 TEST_F(NativeBridgeTest, V3_UnloadLibrary) {
     // Init
     ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
diff --git a/libnativebridge/tests/NativeBridge6PreZygoteFork_test.cpp b/libnativebridge/tests/NativeBridge6PreZygoteFork_test.cpp
index 9e348a2..ba6a007 100644
--- a/libnativebridge/tests/NativeBridge6PreZygoteFork_test.cpp
+++ b/libnativebridge/tests/NativeBridge6PreZygoteFork_test.cpp
@@ -19,8 +19,6 @@
 
 namespace android {
 
-constexpr const char* kNativeBridgeLibrary6 = "libnativebridge6-dummy.so";
-
 TEST_F(NativeBridgeTest, V6_PreZygoteFork) {
     // Init
     ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary6, nullptr));
diff --git a/libnativebridge/tests/NativeBridgeApi.c b/libnativebridge/tests/NativeBridgeApi.c
index 7ab71fe..8440b59 100644
--- a/libnativebridge/tests/NativeBridgeApi.c
+++ b/libnativebridge/tests/NativeBridgeApi.c
@@ -17,9 +17,3 @@
 /* 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 "nativebridge/native_bridge.h"
-
-int main(int argc, char** argv) {
-  (void)argc;
-  (void)argv;
-  return 0;
-}
diff --git a/libnativebridge/tests/NativeBridgeTest.h b/libnativebridge/tests/NativeBridgeTest.h
index cc79907..62509b8 100644
--- a/libnativebridge/tests/NativeBridgeTest.h
+++ b/libnativebridge/tests/NativeBridgeTest.h
@@ -22,11 +22,12 @@
 #include <nativebridge/native_bridge.h>
 #include <gtest/gtest.h>
 
-constexpr const char* kNativeBridgeLibrary = "libnativebridge-dummy.so";
+constexpr const char* kNativeBridgeLibrary = "libnativebridge-test-case.so";
 constexpr const char* kCodeCache = "./code_cache";
 constexpr const char* kCodeCacheStatFail = "./code_cache/temp";
-constexpr const char* kNativeBridgeLibrary2 = "libnativebridge2-dummy.so";
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
+constexpr const char* kNativeBridgeLibrary2 = "libnativebridge2-test-case.so";
+constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-test-case.so";
+constexpr const char* kNativeBridgeLibrary6 = "libnativebridge6-test-case.so";
 
 namespace android {
 
@@ -36,4 +37,3 @@
 };  // namespace android
 
 #endif  // ART_LIBNATIVEBRIDGE_TESTS_NATIVEBRIDGETEST_H_
-
diff --git a/libnativebridge/tests/NativeBridgeTestCase.cpp b/libnativebridge/tests/NativeBridgeTestCase.cpp
new file mode 100644
index 0000000..234c70e
--- /dev/null
+++ b/libnativebridge/tests/NativeBridgeTestCase.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+// An implementation of the native-bridge interface for testing.
+
+#include "nativebridge/native_bridge.h"
+
+// NativeBridgeCallbacks implementations
+extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
+                                         const char* /* app_code_cache_dir */,
+                                         const char* /* isa */) {
+  return true;
+}
+
+extern "C" void* native_bridge_loadLibrary(const char* /* libpath */, int /* flag */) {
+  return nullptr;
+}
+
+extern "C" void* native_bridge_getTrampoline(void* /* handle */, const char* /* name */,
+                                             const char* /* shorty */, uint32_t /* len */) {
+  return nullptr;
+}
+
+extern "C" bool native_bridge_isSupported(const char* /* libpath */) {
+  return false;
+}
+
+extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv(
+    const char* /* abi */) {
+  return nullptr;
+}
+
+android::NativeBridgeCallbacks NativeBridgeItf {
+  .version = 1,
+  .initialize = &native_bridge_initialize,
+  .loadLibrary = &native_bridge_loadLibrary,
+  .getTrampoline = &native_bridge_getTrampoline,
+  .isSupported = &native_bridge_isSupported,
+  .getAppEnv = &native_bridge_getAppEnv
+};
diff --git a/libnativebridge/tests/NativeBridgeTestCase2.cpp b/libnativebridge/tests/NativeBridgeTestCase2.cpp
new file mode 100644
index 0000000..5164dec
--- /dev/null
+++ b/libnativebridge/tests/NativeBridgeTestCase2.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+// An implementation of the native-bridge interface for testing.
+
+#include "nativebridge/native_bridge.h"
+
+#include <signal.h>
+
+// NativeBridgeCallbacks implementations
+extern "C" bool native_bridge2_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
+                                         const char* /* app_code_cache_dir */,
+                                         const char* /* isa */) {
+  return true;
+}
+
+extern "C" void* native_bridge2_loadLibrary(const char* /* libpath */, int /* flag */) {
+  return nullptr;
+}
+
+extern "C" void* native_bridge2_getTrampoline(void* /* handle */, const char* /* name */,
+                                             const char* /* shorty */, uint32_t /* len */) {
+  return nullptr;
+}
+
+extern "C" bool native_bridge2_isSupported(const char* /* libpath */) {
+  return false;
+}
+
+extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge2_getAppEnv(
+    const char* /* abi */) {
+  return nullptr;
+}
+
+extern "C" bool native_bridge2_is_compatible_compatible_with(uint32_t version) {
+  // For testing, allow 1-3, but disallow later.
+  return version <= 3;
+}
+
+static bool native_bridge2_test_case_signal_handler(int, siginfo_t*, void*) {
+  // TODO: Implement something here. We'd either have to have a death test with a log here, or
+  //       we'd have to be able to resume after the faulting instruction...
+  return true;
+}
+
+extern "C" android::NativeBridgeSignalHandlerFn native_bridge2_get_signal_handler(int signal) {
+  if (signal == SIGSEGV) {
+    return &native_bridge2_test_case_signal_handler;
+  }
+  return nullptr;
+}
+
+android::NativeBridgeCallbacks NativeBridgeItf {
+  .version = 2,
+  .initialize = &native_bridge2_initialize,
+  .loadLibrary = &native_bridge2_loadLibrary,
+  .getTrampoline = &native_bridge2_getTrampoline,
+  .isSupported = &native_bridge2_isSupported,
+  .getAppEnv = &native_bridge2_getAppEnv,
+  .isCompatibleWith = &native_bridge2_is_compatible_compatible_with,
+  .getSignalHandler = &native_bridge2_get_signal_handler
+};
diff --git a/libnativebridge/tests/NativeBridgeTestCase3.cpp b/libnativebridge/tests/NativeBridgeTestCase3.cpp
new file mode 100644
index 0000000..c5bd032
--- /dev/null
+++ b/libnativebridge/tests/NativeBridgeTestCase3.cpp
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+// An implementation of the native-bridge interface for testing.
+
+#include "nativebridge/native_bridge.h"
+
+#include <signal.h>
+
+// NativeBridgeCallbacks implementations
+extern "C" bool native_bridge3_initialize(
+                      const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
+                      const char* /* app_code_cache_dir */,
+                      const char* /* isa */) {
+  return true;
+}
+
+extern "C" void* native_bridge3_loadLibrary(const char* /* libpath */, int /* flag */) {
+  return nullptr;
+}
+
+extern "C" void* native_bridge3_getTrampoline(void* /* handle */, const char* /* name */,
+                                             const char* /* shorty */, uint32_t /* len */) {
+  return nullptr;
+}
+
+extern "C" bool native_bridge3_isSupported(const char* /* libpath */) {
+  return false;
+}
+
+extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge3_getAppEnv(
+    const char* /* abi */) {
+  return nullptr;
+}
+
+extern "C" bool native_bridge3_isCompatibleWith(uint32_t version) {
+  // For testing, allow 1-3, but disallow 4+.
+  return version <= 3;
+}
+
+static bool native_bridge3_test_case_signal_handler(int, siginfo_t*, void*) {
+  // TODO: Implement something here. We'd either have to have a death test with a log here, or
+  //       we'd have to be able to resume after the faulting instruction...
+  return true;
+}
+
+extern "C" android::NativeBridgeSignalHandlerFn native_bridge3_getSignalHandler(int signal) {
+  if (signal == SIGSEGV) {
+    return &native_bridge3_test_case_signal_handler;
+  }
+  return nullptr;
+}
+
+extern "C" int native_bridge3_unloadLibrary(void* /* handle */) {
+  return 0;
+}
+
+extern "C" const char* native_bridge3_getError() {
+  return nullptr;
+}
+
+extern "C" bool native_bridge3_isPathSupported(const char* /* path */) {
+  return true;
+}
+
+extern "C" bool native_bridge3_initAnonymousNamespace(const char* /* public_ns_sonames */,
+                                                      const char* /* anon_ns_library_path */) {
+  return true;
+}
+
+extern "C" android::native_bridge_namespace_t*
+native_bridge3_createNamespace(const char* /* name */,
+                               const char* /* ld_library_path */,
+                               const char* /* default_library_path */,
+                               uint64_t /* type */,
+                               const char* /* permitted_when_isolated_path */,
+                               android::native_bridge_namespace_t* /* parent_ns */) {
+  return nullptr;
+}
+
+extern "C" bool native_bridge3_linkNamespaces(android::native_bridge_namespace_t* /* from */,
+                                              android::native_bridge_namespace_t* /* to */,
+                                              const char* /* shared_libs_soname */) {
+  return true;
+}
+
+extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */,
+                                               int /* flag */,
+                                               android::native_bridge_namespace_t* /* ns */) {
+  return nullptr;
+}
+
+android::NativeBridgeCallbacks NativeBridgeItf{
+    // v1
+    .version = 3,
+    .initialize = &native_bridge3_initialize,
+    .loadLibrary = &native_bridge3_loadLibrary,
+    .getTrampoline = &native_bridge3_getTrampoline,
+    .isSupported = &native_bridge3_isSupported,
+    .getAppEnv = &native_bridge3_getAppEnv,
+    // v2
+    .isCompatibleWith = &native_bridge3_isCompatibleWith,
+    .getSignalHandler = &native_bridge3_getSignalHandler,
+    // v3
+    .unloadLibrary = &native_bridge3_unloadLibrary,
+    .getError = &native_bridge3_getError,
+    .isPathSupported = &native_bridge3_isPathSupported,
+    .initAnonymousNamespace = &native_bridge3_initAnonymousNamespace,
+    .createNamespace = &native_bridge3_createNamespace,
+    .linkNamespaces = &native_bridge3_linkNamespaces,
+    .loadLibraryExt = &native_bridge3_loadLibraryExt};
diff --git a/libnativebridge/tests/NativeBridgeTestCase6.cpp b/libnativebridge/tests/NativeBridgeTestCase6.cpp
new file mode 100644
index 0000000..2b9fba5
--- /dev/null
+++ b/libnativebridge/tests/NativeBridgeTestCase6.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+// An implementation of the native-bridge interface for testing.
+
+#include "nativebridge/native_bridge.h"
+
+#include "NativeBridge6PreZygoteFork_lib.h"
+
+// NativeBridgeCallbacks implementations
+extern "C" bool native_bridge6_initialize(
+                      const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
+                      const char* /* app_code_cache_dir */,
+                      const char* /* isa */) {
+  return true;
+}
+
+extern "C" void* native_bridge6_loadLibrary(const char* /* libpath */, int /* flag */) {
+  return nullptr;
+}
+
+extern "C" void* native_bridge6_getTrampoline(void* /* handle */, const char* /* name */,
+                                             const char* /* shorty */, uint32_t /* len */) {
+  return nullptr;
+}
+
+extern "C" bool native_bridge6_isSupported(const char* /* libpath */) {
+  return false;
+}
+
+extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge6_getAppEnv(
+    const char* /* abi */) {
+  return nullptr;
+}
+
+extern "C" bool native_bridge6_isCompatibleWith(uint32_t version) {
+  // For testing, allow 1-6, but disallow 7+.
+  return version <= 6;
+}
+
+extern "C" android::NativeBridgeSignalHandlerFn native_bridge6_getSignalHandler(int /* signal */) {
+  return nullptr;
+}
+
+extern "C" int native_bridge6_unloadLibrary(void* /* handle */) {
+  return 0;
+}
+
+extern "C" const char* native_bridge6_getError() {
+  return nullptr;
+}
+
+extern "C" bool native_bridge6_isPathSupported(const char* /* path */) {
+  return true;
+}
+
+extern "C" bool native_bridge6_initAnonymousNamespace(const char* /* public_ns_sonames */,
+                                                      const char* /* anon_ns_library_path */) {
+  return true;
+}
+
+extern "C" android::native_bridge_namespace_t*
+native_bridge6_createNamespace(const char* /* name */,
+                               const char* /* ld_library_path */,
+                               const char* /* default_library_path */,
+                               uint64_t /* type */,
+                               const char* /* permitted_when_isolated_path */,
+                               android::native_bridge_namespace_t* /* parent_ns */) {
+  return nullptr;
+}
+
+extern "C" bool native_bridge6_linkNamespaces(android::native_bridge_namespace_t* /* from */,
+                                              android::native_bridge_namespace_t* /* to */,
+                                              const char* /* shared_libs_soname */) {
+  return true;
+}
+
+extern "C" void* native_bridge6_loadLibraryExt(const char* /* libpath */,
+                                               int /* flag */,
+                                               android::native_bridge_namespace_t* /* ns */) {
+  return nullptr;
+}
+
+extern "C" android::native_bridge_namespace_t* native_bridge6_getVendorNamespace() {
+  return nullptr;
+}
+
+extern "C" android::native_bridge_namespace_t* native_bridge6_getExportedNamespace(const char* /* name */) {
+  return nullptr;
+}
+
+extern "C" void native_bridge6_preZygoteFork() {
+  android::SetPreZygoteForkDone();
+}
+
+android::NativeBridgeCallbacks NativeBridgeItf{
+    // v1
+    .version = 6,
+    .initialize = &native_bridge6_initialize,
+    .loadLibrary = &native_bridge6_loadLibrary,
+    .getTrampoline = &native_bridge6_getTrampoline,
+    .isSupported = &native_bridge6_isSupported,
+    .getAppEnv = &native_bridge6_getAppEnv,
+    // v2
+    .isCompatibleWith = &native_bridge6_isCompatibleWith,
+    .getSignalHandler = &native_bridge6_getSignalHandler,
+    // v3
+    .unloadLibrary = &native_bridge6_unloadLibrary,
+    .getError = &native_bridge6_getError,
+    .isPathSupported = &native_bridge6_isPathSupported,
+    .initAnonymousNamespace = &native_bridge6_initAnonymousNamespace,
+    .createNamespace = &native_bridge6_createNamespace,
+    .linkNamespaces = &native_bridge6_linkNamespaces,
+    .loadLibraryExt = &native_bridge6_loadLibraryExt,
+    // v4
+    &native_bridge6_getVendorNamespace,
+    // v5
+    &native_bridge6_getExportedNamespace,
+    // v6
+    &native_bridge6_preZygoteFork};
diff --git a/libnativebridge/tests/NativeBridgeVersion_test.cpp b/libnativebridge/tests/NativeBridgeVersion_test.cpp
index d3f9a80..22aecad 100644
--- a/libnativebridge/tests/NativeBridgeVersion_test.cpp
+++ b/libnativebridge/tests/NativeBridgeVersion_test.cpp
@@ -24,7 +24,7 @@
     // When a bridge isn't loaded, we expect 0.
     EXPECT_EQ(NativeBridgeGetVersion(), 0U);
 
-    // After our dummy bridge has been loaded, we expect 1.
+    // After our fake bridge has been loaded, we expect 1.
     ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
     EXPECT_EQ(NativeBridgeGetVersion(), 1U);
 
diff --git a/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp b/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp
deleted file mode 100644
index 5a2b0a1..0000000
--- a/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.
- */
-
-#include "NativeBridgeTest.h"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-#include <cstdio>
-#include <cstring>
-
-#include <android/log.h>
-
-namespace android {
-
-TEST_F(NativeBridgeTest, PreInitializeNativeBridgeFail1) {
-  // Needs a valid application directory.
-  ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
-  ASSERT_FALSE(PreInitializeNativeBridge(nullptr, "isa"));
-  ASSERT_TRUE(NativeBridgeError());
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/PreInitializeNativeBridge_test.cpp b/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
index cd5a8e2..149b05e 100644
--- a/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
+++ b/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
@@ -38,7 +38,7 @@
 
     // Try to create our mount namespace.
     if (unshare(CLONE_NEWNS) != -1) {
-        // Create a dummy file.
+        // Create a placeholder file.
         FILE* cpuinfo = fopen("./cpuinfo", "w");
         ASSERT_NE(nullptr, cpuinfo) << strerror(errno);
         fprintf(cpuinfo, kTestData);
diff --git a/libnativebridge/tests/libnativebridge_lazy_test.cpp b/libnativebridge/tests/libnativebridge_lazy_test.cpp
new file mode 100644
index 0000000..e1d66f5
--- /dev/null
+++ b/libnativebridge/tests/libnativebridge_lazy_test.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 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 <android-base/macros.h>
+#include <gtest/gtest.h>
+
+#include "nativebridge/native_bridge.h"
+
+namespace android {
+
+class NativeBridgeLazyTest : public ::testing::Test {};
+
+// The testing we can do here is limited since there's no exported API to
+// actually load the native bridge, but we only need to test the trivial
+// wrappers.
+
+TEST_F(NativeBridgeLazyTest, NeedsNativeBridge) {
+  EXPECT_FALSE(NeedsNativeBridge(ABI_STRING));
+}
+
+TEST_F(NativeBridgeLazyTest, PreInitializeNativeBridge) {
+  EXPECT_FALSE(PreInitializeNativeBridge(nullptr, ""));
+}
+
+TEST_F(NativeBridgeLazyTest, NativeBridgeAvailable) {
+  EXPECT_FALSE(NativeBridgeAvailable());
+}
+
+TEST_F(NativeBridgeLazyTest, NativeBridgeInitialized) {
+  EXPECT_FALSE(NativeBridgeInitialized());
+}
+
+TEST_F(NativeBridgeLazyTest, NativeBridgeGetTrampoline) {
+  EXPECT_EQ(nullptr, NativeBridgeGetTrampoline(nullptr, nullptr, nullptr, 0));
+}
+
+TEST_F(NativeBridgeLazyTest, NativeBridgeGetError) {
+  EXPECT_STREQ("native bridge is not initialized", NativeBridgeGetError());
+}
+
+};  // namespace android
diff --git a/libnativebridge/tests/preupload_check_test_tag.sh b/libnativebridge/tests/preupload_check_test_tag.sh
new file mode 100755
index 0000000..1c8cd4b
--- /dev/null
+++ b/libnativebridge/tests/preupload_check_test_tag.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# A simple preupload check that the runtests.sh script has been run for the
+# libnativebridge tests if that library has been changed.
+# TODO(b/189484095): Port these tests to atest and enable in presubmit so we
+# don't need the custom script to run them.
+
+commit_message="$1"
+shift
+
+nativebridge_change=false
+for file; do
+  [[ $file = libnativebridge/* ]] && nativebridge_change=true
+done
+
+if $nativebridge_change; then
+  if grep '^Test: art/libnativebridge/tests/runtests.sh' <<< $commit_message ; then :; else
+    echo "Please run art/libnativebridge/tests/runtests.sh and add the tag:" 1>&2
+    echo "Test: art/libnativebridge/tests/runtests.sh [--skip-host|--skip-target]" 1>&2
+    exit 1
+  fi
+fi
diff --git a/libnativebridge/tests/runtests.sh b/libnativebridge/tests/runtests.sh
new file mode 100755
index 0000000..1eb232d
--- /dev/null
+++ b/libnativebridge/tests/runtests.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+set -e
+
+skip_build=
+skip_host=
+skip_target=
+skip_cleanup=
+for arg; do
+  case "$arg" in
+    --skip-build) skip_build=true ;;
+    --skip-host) skip_host=true ;;
+    --skip-target) skip_target=true ;;
+    --skip-cleanup) skip_cleanup=true ;;
+    *) break ;;
+  esac
+  shift
+done
+
+echo_and_run() {
+  echo "$@"
+  eval "$@"
+}
+
+device_test_root=/data/local/tmp/libnativebridge-test
+
+vars="$(build/soong/soong_ui.bash --dumpvars-mode --vars='HOST_OUT PRODUCT_OUT TARGET_ARCH')"
+# Assign to a variable and eval that, since bash ignores any error status
+# from the command substitution if it's directly on the eval line.
+eval $vars
+
+if [ -z "$skip_build" ]; then
+  rm -rf $HOST_OUT/nativetest{,64} $PRODUCT_OUT/data/nativetest{,64}/art/$TARGET_ARCH
+  echo_and_run build/soong/soong_ui.bash --make-mode MODULES-IN-art-libnativebridge-tests
+fi
+
+if [ -z "$skip_host" ]; then
+  for build_dir in $HOST_OUT/nativetest{,64}/ ; do
+    if [ ! -d $build_dir ]; then
+      echo "Skipping missing $build_dir"
+    else
+      for test_path in $build_dir/*/* ; do
+        test_rel_path=${test_path#${build_dir}/}
+        echo_and_run \( cd $build_dir \; $test_rel_path $* \)
+      done
+    fi
+  done
+fi
+
+if [ -z "$skip_target" ]; then
+  adb root
+  adb wait-for-device
+
+  for build_dir in $PRODUCT_OUT/data/nativetest{,64}/art/$TARGET_ARCH ; do
+    if [ ! -d $build_dir ]; then
+      echo "Skipping missing $build_dir"
+    else
+      test_dir=$device_test_root/$TARGET_ARCH
+
+      echo_and_run adb shell rm -rf $test_dir
+      echo_and_run adb push $build_dir $test_dir
+
+      for test_path in $build_dir/*/* ; do
+        test_rel_path=${test_path#${build_dir}/}
+        echo_and_run adb shell cd $test_dir '\;' LD_LIBRARY_PATH=. $test_rel_path $*
+      done
+    fi
+  done
+
+  if [ -z "$skip_cleanup" ]; then
+    echo_and_run adb shell rm -rf $device_test_root
+  fi
+fi
+
+echo "No errors"
diff --git a/libnativeloader/.clang-format b/libnativeloader/.clang-format
deleted file mode 120000
index fd0645f..0000000
--- a/libnativeloader/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-2
\ No newline at end of file
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index bfafa76..3f13506 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -1,16 +1,22 @@
 // Shared library for target
 // ========================================================
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "libnativeloader-defaults",
     defaults: ["art_defaults"],
-    cppflags: [
-        "-fvisibility=hidden",
-    ],
     header_libs: ["libnativeloader-headers"],
     export_header_lib_headers: ["libnativeloader-headers"],
 }
 
-cc_library {
+art_cc_library {
     name: "libnativeloader",
     defaults: ["libnativeloader-defaults"],
     visibility: [
@@ -19,20 +25,35 @@
         "//frameworks/base/native/webview/loader",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
     host_supported: true,
     srcs: [
         "native_loader.cpp",
     ],
-    header_libs: ["libnativehelper_header_only"],
+    header_libs: [
+        "libnativehelper_header_only",
+    ],
     shared_libs: [
         "liblog",
         "libnativebridge",
         "libbase",
     ],
     target: {
+        // Library search path needed for running host tests remotely (from testcases directory).
+        linux_glibc_x86: {
+            ldflags: [
+                "-Wl,-rpath,$ORIGIN/../art_common/out/host/linux-x86/lib",
+                "-Wl,--enable-new-dtags",
+            ],
+        },
+        linux_glibc_x86_64: {
+            ldflags: [
+                "-Wl,-rpath,$ORIGIN/../art_common/out/host/linux-x86/lib64",
+                "-Wl,--enable-new-dtags",
+            ],
+        },
         android: {
             srcs: [
                 "library_namespaces.cpp",
@@ -42,7 +63,7 @@
             shared_libs: [
                 "libdl_android",
             ],
-            whole_static_libs: [
+            static_libs: [
                 "PlatformProperties",
             ],
         },
@@ -62,18 +83,26 @@
         "//frameworks/native/opengl/libs",
         "//frameworks/native/vulkan/libvulkan",
     ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+        "com.android.media.swcodec",
+    ],
     host_supported: false,
     srcs: ["native_loader_lazy.cpp"],
-    required: ["libnativeloader"],
+    runtime_libs: ["libnativeloader"],
+    shared_libs: ["liblog"],
 }
 
 cc_library_headers {
     name: "libnativeloader-headers",
     apex_available: [
         "//apex_available:platform",
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
+        "com.android.media",
     ],
+    min_sdk_version: "S",
     visibility: [
         "//art:__subpackages__",
         // TODO(b/133140750): Clean this up.
@@ -83,34 +112,60 @@
     ],
     host_supported: true,
     export_include_dirs: ["include"],
+    header_libs: ["jni_headers"],
+    export_header_lib_headers: ["jni_headers"],
 }
 
-cc_test {
-    name: "libnativeloader_test",
-    srcs: [
-        "native_loader_test.cpp",
-        "native_loader.cpp",
-        "library_namespaces.cpp",
-        "native_loader_namespace.cpp",
-        "public_libraries.cpp",
+cc_defaults {
+    name: "libnativeloader-test-defaults",
+    defaults: [
+        "art_module_source_build_defaults",
+        "art_test_defaults",
     ],
+    host_supported: false,
+
     cflags: ["-DANDROID"],
-    static_libs: [
-        "libbase",
-        "liblog",
-        "libgmock",
-        "PlatformProperties",
+
+    // The tests mock libdl_android and libnativebridge symbols, so export them
+    // to override the ones loaded from their libs.
+    ldflags: [
+        "-Wl,--export-dynamic-symbol=android_*",
+        "-Wl,--export-dynamic-symbol=NativeBridge*",
     ],
+
     header_libs: [
         "libnativebridge-headers",
         "libnativehelper_header_only",
-        "libnativeloader-headers",
     ],
-    // native_loader_test.cpp mocks libdl APIs so system_shared_libs
-    // are used to include C libraries without libdl.
-    system_shared_libs: [
-        "libc",
-        "libm",
+    static_libs: [
+        "libgmock",
     ],
+    shared_libs: [
+        "libbase",
+    ],
+
     test_suites: ["device-tests"],
 }
+
+art_cc_test {
+    name: "libnativeloader_test",
+    defaults: ["libnativeloader-test-defaults"],
+    srcs: [
+        "native_loader_api_test.c",
+        "native_loader_test.cpp",
+    ],
+    shared_libs: [
+        "libnativeloader",
+    ],
+}
+
+art_cc_test {
+    name: "libnativeloader_lazy_test",
+    defaults: ["libnativeloader-test-defaults"],
+    srcs: [
+        "native_loader_lazy_test.cpp",
+    ],
+    static_libs: [
+        "libnativeloader_lazy",
+    ],
+}
diff --git a/libnativeloader/README.md b/libnativeloader/README.md
index 57b9001..c5ace61 100644
--- a/libnativeloader/README.md
+++ b/libnativeloader/README.md
@@ -34,7 +34,7 @@
 [APEX](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/docs/README.md),
 some libraries are no longer provided from platform, but from the APEXes which
 have their own linker namespaces. For example, ICU libraries `libicuuc.so` and
-`libicui18n.so` are from the runtime APEX.
+`libicui18n.so` are from the I18n APEX.
 
 The list of public native libraries is not static. The default set of libraries
 are defined in AOSP, but partners can extend it to include their own libraries.
diff --git a/libnativeloader/include/nativeloader/dlext_namespaces.h b/libnativeloader/include/nativeloader/dlext_namespaces.h
index ed335ee..79537ef 100644
--- a/libnativeloader/include/nativeloader/dlext_namespaces.h
+++ b/libnativeloader/include/nativeloader/dlext_namespaces.h
@@ -45,10 +45,10 @@
    */
   ANDROID_NAMESPACE_TYPE_SHARED = 2,
 
-  /* This flag instructs linker to enable grey-list workaround for the namespace.
+  /* This flag instructs linker to enable exempt-list workaround for the namespace.
    * See http://b/26394120 for details.
    */
-  ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
+  ANDROID_NAMESPACE_TYPE_EXEMPT_LIST_ENABLED = 0x08000000,
 
   /* This flag instructs linker to use this namespace as the anonymous
    * namespace. The anonymous namespace is used in the case when linker cannot
diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
index 4fd8092..92d192f 100644
--- a/libnativeloader/include/nativeloader/native_loader.h
+++ b/libnativeloader/include/nativeloader/native_loader.h
@@ -38,7 +38,7 @@
 
 __attribute__((visibility("default"))) jstring CreateClassLoaderNamespace(
     JNIEnv* env, int32_t target_sdk_version, jobject class_loader, bool is_shared, jstring dex_path,
-    jstring library_path, jstring permitted_path);
+    jstring library_path, jstring permitted_path, jstring uses_library_list);
 
 __attribute__((visibility("default"))) void* OpenNativeLibrary(
     JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader,
diff --git a/libnativeloader/libnativeloader.map.txt b/libnativeloader/libnativeloader.map.txt
index 40c30bd..59f457c 100644
--- a/libnativeloader/libnativeloader.map.txt
+++ b/libnativeloader/libnativeloader.map.txt
@@ -14,12 +14,13 @@
 # limitations under the License.
 #
 
-# TODO(b/122710865): Prune these uses once the runtime APEX is complete.
+# Platform dependencies go through libnativeloader_lazy, which accesses
+# libnativeloader symbols through dlopen/dlsym. That means this list doesn't
+# have much effect, rather it's the function wrappers in native_loader_lazy.cpp
+# that defines the exported interface. Please keep in sync with this list.
 LIBNATIVELOADER_1 {
   global:
     OpenNativeLibrary;
-    InitializeNativeLoader;
-    ResetNativeLoader;
     CloseNativeLibrary;
     OpenNativeLibraryInNamespace;
     FindNamespaceByClassLoader;
diff --git a/libnativeloader/library_namespaces.cpp b/libnativeloader/library_namespaces.cpp
index 9e41c2f..8b87338 100644
--- a/libnativeloader/library_namespaces.cpp
+++ b/libnativeloader/library_namespaces.cpp
@@ -13,6 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+#if defined(ART_TARGET_ANDROID)
+
 #include "library_namespaces.h"
 
 #include <dirent.h>
@@ -25,7 +28,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
-#include <android-base/properties.h>
+#include <android-base/result.h>
 #include <android-base/strings.h>
 #include <nativehelper/scoped_utf_chars.h>
 
@@ -36,6 +39,9 @@
 namespace android::nativeloader {
 
 namespace {
+
+constexpr const char* kApexPath = "/apex/";
+
 // The device may be configured to have the vendor libraries loaded to a separate namespace.
 // For historical reasons this namespace was named sphal but effectively it is intended
 // to use to load vendor libraries to separate namespace with controlled interface between
@@ -43,9 +49,6 @@
 constexpr const char* kVendorNamespaceName = "sphal";
 constexpr const char* kVndkNamespaceName = "vndk";
 constexpr const char* kVndkProductNamespaceName = "vndk_product";
-constexpr const char* kArtNamespaceName = "com_android_art";
-constexpr const char* kNeuralNetworksNamespaceName = "com_android_neuralnetworks";
-constexpr const char* kStatsdNamespaceName = "com_android_os_statsd";
 
 // classloader-namespace is a linker namespace that is created for the loaded
 // app. To be specific, it is created for the app classloader. When
@@ -93,23 +96,17 @@
   return env->CallObjectMethod(class_loader, get_parent);
 }
 
-ApkOrigin GetApkOriginFromDexPath(JNIEnv* env, jstring dex_path) {
+ApkOrigin GetApkOriginFromDexPath(const std::string& dex_path) {
   ApkOrigin apk_origin = APK_ORIGIN_DEFAULT;
+  if (std::regex_search(dex_path, kVendorDexPathRegex)) {
+    apk_origin = APK_ORIGIN_VENDOR;
+  }
+  if (std::regex_search(dex_path, kProductDexPathRegex)) {
+    LOG_ALWAYS_FATAL_IF(apk_origin == APK_ORIGIN_VENDOR,
+                        "Dex path contains both vendor and product partition : %s",
+                        dex_path.c_str());
 
-  if (dex_path != nullptr) {
-    ScopedUtfChars dex_path_utf_chars(env, dex_path);
-
-    if (std::regex_search(dex_path_utf_chars.c_str(), kVendorDexPathRegex)) {
-      apk_origin = APK_ORIGIN_VENDOR;
-    }
-
-    if (std::regex_search(dex_path_utf_chars.c_str(), kProductDexPathRegex)) {
-      LOG_ALWAYS_FATAL_IF(apk_origin == APK_ORIGIN_VENDOR,
-                          "Dex path contains both vendor and product partition : %s",
-                          dex_path_utf_chars.c_str());
-
-      apk_origin = APK_ORIGIN_PRODUCT;
-    }
+    apk_origin = APK_ORIGIN_PRODUCT;
   }
   return apk_origin;
 }
@@ -124,33 +121,89 @@
     return;
   }
 
-  // android_init_namespaces() expects all the public libraries
-  // to be loaded so that they can be found by soname alone.
+  // Load the preloadable public libraries. Since libnativeloader is in the
+  // com_android_art namespace, use OpenSystemLibrary rather than dlopen to
+  // ensure the libraries are loaded in the system namespace.
   //
   // TODO(dimitry): this is a bit misleading since we do not know
   // if the vendor public library is going to be opened from /vendor/lib
   // we might as well end up loading them from /system/lib or /product/lib
   // For now we rely on CTS test to catch things like this but
   // it should probably be addressed in the future.
-  for (const auto& soname : android::base::Split(preloadable_public_libraries(), ":")) {
-    LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr,
+  for (const std::string& soname : android::base::Split(preloadable_public_libraries(), ":")) {
+    void* handle = OpenSystemLibrary(soname.c_str(), RTLD_NOW | RTLD_NODELETE);
+    LOG_ALWAYS_FATAL_IF(handle == nullptr,
                         "Error preloading public library %s: %s", soname.c_str(), dlerror());
   }
 }
 
+// "ALL" is a magic name that allows all public libraries even when the
+// target SDK is > 30. Currently this is used for (Java) shared libraries
+// which don't use <uses-native-library>
+// TODO(b/142191088) remove this hack
+static constexpr const char LIBRARY_ALL[] = "ALL";
+
+// Returns the colon-separated list of library names by filtering uses_libraries from
+// public_libraries. The returned names will actually be available to the app. If the app is pre-S
+// (<= 30), the filtering is not done; the entire public_libraries are provided.
+static const std::string filter_public_libraries(
+    uint32_t target_sdk_version, const std::vector<std::string>& uses_libraries,
+    const std::string& public_libraries) {
+  // Apps targeting Android 11 or earlier gets all public libraries
+  if (target_sdk_version <= 30) {
+    return public_libraries;
+  }
+  if (std::find(uses_libraries.begin(), uses_libraries.end(), LIBRARY_ALL) !=
+      uses_libraries.end()) {
+    return public_libraries;
+  }
+  std::vector<std::string> filtered;
+  std::vector<std::string> orig = android::base::Split(public_libraries, ":");
+  for (const auto& lib : uses_libraries) {
+    if (std::find(orig.begin(), orig.end(), lib) != orig.end()) {
+      filtered.emplace_back(lib);
+    }
+  }
+  return android::base::Join(filtered, ":");
+}
+
 Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version,
                                                          jobject class_loader, bool is_shared,
-                                                         jstring dex_path,
+                                                         jstring dex_path_j,
                                                          jstring java_library_path,
-                                                         jstring java_permitted_path) {
+                                                         jstring java_permitted_path,
+                                                         jstring uses_library_list) {
   std::string library_path;  // empty string by default.
+  std::string dex_path;
 
   if (java_library_path != nullptr) {
     ScopedUtfChars library_path_utf_chars(env, java_library_path);
     library_path = library_path_utf_chars.c_str();
   }
 
-  ApkOrigin apk_origin = GetApkOriginFromDexPath(env, dex_path);
+  if (dex_path_j != nullptr) {
+    ScopedUtfChars dex_path_chars(env, dex_path_j);
+    dex_path = dex_path_chars.c_str();
+  }
+
+  std::vector<std::string> uses_libraries;
+  if (uses_library_list != nullptr) {
+    ScopedUtfChars names(env, uses_library_list);
+    uses_libraries = android::base::Split(names.c_str(), ":");
+  } else {
+    // uses_library_list could be nullptr when System.loadLibrary is called from a
+    // custom classloader. In that case, we don't know the list of public
+    // libraries because we don't know which apk the classloader is for. Only
+    // choices we can have are 1) allowing all public libs (as before), or 2)
+    // not allowing all but NDK libs. Here we take #1 because #2 would surprise
+    // developers unnecessarily.
+    // TODO(b/142191088) finalize the policy here. We could either 1) allow all
+    // public libs, 2) disallow any lib, or 3) use the libs that were granted to
+    // the first (i.e. app main) classloader.
+    uses_libraries.emplace_back(LIBRARY_ALL);
+  }
+
+  ApkOrigin apk_origin = GetApkOriginFromDexPath(dex_path);
 
   // (http://b/27588281) This is a workaround for apps using custom
   // classloaders and calling System.load() with an absolute path which
@@ -212,10 +265,12 @@
     ALOGD("classloader namespace configured for unbundled %s apk. library_path=%s",
           origin_partition, library_path.c_str());
   } else {
+    auto libs = filter_public_libraries(target_sdk_version, uses_libraries,
+                                        extended_public_libraries());
     // extended public libraries are NOT available to vendor apks, otherwise it
     // would be system->vendor violation.
-    if (!extended_public_libraries().empty()) {
-      system_exposed_libraries = system_exposed_libraries + ':' + extended_public_libraries();
+    if (!libs.empty()) {
+      system_exposed_libraries = system_exposed_libraries + ':' + libs;
     }
   }
 
@@ -239,7 +294,7 @@
   // racing here.
   auto app_ns = NativeLoaderNamespace::Create(
       namespace_name, library_path, permitted_path, parent_ns, is_shared,
-      target_sdk_version < 24 /* is_greylist_enabled */, also_used_as_anonymous);
+      target_sdk_version < 24 /* is_exempt_list_enabled */, also_used_as_anonymous);
   if (!app_ns.ok()) {
     return app_ns.error();
   }
@@ -251,27 +306,19 @@
     return system_ns.error();
   }
 
-  auto linked = app_ns->Link(*system_ns, system_exposed_libraries);
+  auto linked = app_ns->Link(&system_ns.value(), system_exposed_libraries);
   if (!linked.ok()) {
     return linked.error();
   }
 
-  auto art_ns = NativeLoaderNamespace::GetExportedNamespace(kArtNamespaceName, is_bridged);
-  // ART APEX does not exist on host, and under certain build conditions.
-  if (art_ns.ok()) {
-    linked = app_ns->Link(*art_ns, art_public_libraries());
-    if (!linked.ok()) {
-      return linked.error();
-    }
-  }
-
-  // Give access to NNAPI libraries (apex-updated LLNDK library).
-  auto nnapi_ns =
-      NativeLoaderNamespace::GetExportedNamespace(kNeuralNetworksNamespaceName, is_bridged);
-  if (nnapi_ns.ok()) {
-    linked = app_ns->Link(*nnapi_ns, neuralnetworks_public_libraries());
-    if (!linked.ok()) {
-      return linked.error();
+  for (const auto&[apex_ns_name, public_libs] : apex_public_libraries()) {
+    auto ns = NativeLoaderNamespace::GetExportedNamespace(apex_ns_name, is_bridged);
+    // Even if APEX namespace is visible, it may not be available to bridged.
+    if (ns.ok()) {
+      linked = app_ns->Link(&ns.value(), public_libs);
+      if (!linked.ok()) {
+        return linked.error();
+      }
     }
   }
 
@@ -279,7 +326,7 @@
   if (unbundled_app_origin == APK_ORIGIN_VENDOR && !vndksp_libraries_vendor().empty()) {
     auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkNamespaceName, is_bridged);
     if (vndk_ns.ok()) {
-      linked = app_ns->Link(*vndk_ns, vndksp_libraries_vendor());
+      linked = app_ns->Link(&vndk_ns.value(), vndksp_libraries_vendor());
       if (!linked.ok()) {
         return linked.error();
       }
@@ -290,29 +337,37 @@
   if (unbundled_app_origin == APK_ORIGIN_PRODUCT && !vndksp_libraries_product().empty()) {
     auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkProductNamespaceName, is_bridged);
     if (vndk_ns.ok()) {
-      linked = app_ns->Link(*vndk_ns, vndksp_libraries_product());
+      linked = app_ns->Link(&vndk_ns.value(), vndksp_libraries_product());
       if (!linked.ok()) {
         return linked.error();
       }
     }
   }
 
-  // Give access to StatsdAPI libraries
-  auto statsd_ns =
-      NativeLoaderNamespace::GetExportedNamespace(kStatsdNamespaceName, is_bridged);
-  if (statsd_ns.ok()) {
-    linked = app_ns->Link(*statsd_ns, statsd_public_libraries());
-    if (!linked.ok()) {
-      return linked.error();
+  for (const std::string& each_jar_path : android::base::Split(dex_path, ":")) {
+    auto apex_ns_name = FindApexNamespaceName(each_jar_path);
+    if (apex_ns_name.ok()) {
+      const auto& jni_libs = apex_jni_libraries(*apex_ns_name);
+      if (jni_libs != "") {
+        auto apex_ns = NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged);
+        if (apex_ns.ok()) {
+          linked = app_ns->Link(&apex_ns.value(), jni_libs);
+          if (!linked.ok()) {
+            return linked.error();
+          }
+        }
+      }
     }
   }
 
-  if (!vendor_public_libraries().empty()) {
+  auto vendor_libs = filter_public_libraries(target_sdk_version, uses_libraries,
+                                             vendor_public_libraries());
+  if (!vendor_libs.empty()) {
     auto vendor_ns = NativeLoaderNamespace::GetExportedNamespace(kVendorNamespaceName, is_bridged);
     // when vendor_ns is not configured, link to the system namespace
     auto target_ns = vendor_ns.ok() ? vendor_ns : system_ns;
     if (target_ns.ok()) {
-      linked = app_ns->Link(*target_ns, vendor_public_libraries());
+      linked = app_ns->Link(&target_ns.value(), vendor_libs);
       if (!linked.ok()) {
         return linked.error();
       }
@@ -356,4 +411,23 @@
   return nullptr;
 }
 
+base::Result<std::string> FindApexNamespaceName(const std::string& location) {
+  // Lots of implicit assumptions here: we expect `location` to be of the form:
+  // /apex/modulename/...
+  //
+  // And we extract from it 'modulename', and then apply mangling rule to get namespace name for it.
+  if (android::base::StartsWith(location, kApexPath)) {
+    size_t start_index = strlen(kApexPath);
+    size_t slash_index = location.find_first_of('/', start_index);
+    LOG_ALWAYS_FATAL_IF((slash_index == std::string::npos),
+                        "Error finding namespace of apex: no slash in path %s", location.c_str());
+    std::string name = location.substr(start_index, slash_index - start_index);
+    std::replace(name.begin(), name.end(), '.', '_');
+    return name;
+  }
+  return base::Error();
+}
+
 }  // namespace android::nativeloader
+
+#endif  // defined(ART_TARGET_ANDROID)
diff --git a/libnativeloader/library_namespaces.h b/libnativeloader/library_namespaces.h
index 8fac534..4871528 100644
--- a/libnativeloader/library_namespaces.h
+++ b/libnativeloader/library_namespaces.h
@@ -17,8 +17,8 @@
 #ifndef ART_LIBNATIVELOADER_LIBRARY_NAMESPACES_H_
 #define ART_LIBNATIVELOADER_LIBRARY_NAMESPACES_H_
 
-#if !defined(__ANDROID__)
-#error "Not available for host"
+#if !defined(ART_TARGET_ANDROID)
+#error "Not available for host or linux target"
 #endif
 
 #define LOG_TAG "nativeloader"
@@ -55,7 +55,8 @@
   }
   Result<NativeLoaderNamespace*> Create(JNIEnv* env, uint32_t target_sdk_version,
                                         jobject class_loader, bool is_shared, jstring dex_path,
-                                        jstring java_library_path, jstring java_permitted_path);
+                                        jstring java_library_path, jstring java_permitted_path,
+                                        jstring uses_library_list);
   NativeLoaderNamespace* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
 
  private:
@@ -67,6 +68,8 @@
   std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
 };
 
+Result<std::string> FindApexNamespaceName(const std::string& location);
+
 }  // namespace android::nativeloader
 
 #endif  // ART_LIBNATIVELOADER_LIBRARY_NAMESPACES_H_
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 988e8a8..2deb5ef 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -30,10 +30,11 @@
 #include <android-base/file.h>
 #include <android-base/macros.h>
 #include <android-base/strings.h>
+#include <android-base/thread_annotations.h>
 #include <nativebridge/native_bridge.h>
 #include <nativehelper/scoped_utf_chars.h>
 
-#ifdef __ANDROID__
+#ifdef ART_TARGET_ANDROID
 #include <log/log.h>
 #include "library_namespaces.h"
 #include "nativeloader/dlext_namespaces.h"
@@ -42,63 +43,165 @@
 namespace android {
 
 namespace {
-#if defined(__ANDROID__)
-using android::nativeloader::LibraryNamespaces;
 
-constexpr const char* kApexPath = "/apex/";
+#if defined(ART_TARGET_ANDROID)
+
+// NATIVELOADER_DEFAULT_NAMESPACE_LIBS is an environment variable that can be
+// used to list extra libraries (separated by ":") that libnativeloader will
+// load from the default namespace. The libraries must be listed without paths,
+// and then LD_LIBRARY_PATH is typically set to the directories to load them
+// from. The libraries will be available in all classloader namespaces, and also
+// in the fallback namespace used when no classloader is given.
+//
+// kNativeloaderExtraLibs is the name of that fallback namespace.
+//
+// NATIVELOADER_DEFAULT_NAMESPACE_LIBS is intended to be used for testing only,
+// and in particular in the ART run tests that are executed through dalvikvm in
+// the APEX. In that case the default namespace links to the ART namespace
+// (com_android_art) for all libraries, which means this can be used to load
+// test libraries that depend on ART internal libraries.
+constexpr const char* kNativeloaderExtraLibs = "nativeloader-extra-libs";
+
+using android::nativeloader::LibraryNamespaces;
 
 std::mutex g_namespaces_mutex;
 LibraryNamespaces* g_namespaces = new LibraryNamespaces;
+NativeLoaderNamespace* g_nativeloader_extra_libs_namespace = nullptr;
 
 android_namespace_t* FindExportedNamespace(const char* caller_location) {
-  std::string location = caller_location;
-  // Lots of implicit assumptions here: we expect `caller_location` to be of the form:
-  // /apex/modulename/...
-  //
-  // And we extract from it 'modulename', which is the name of the linker namespace.
-  if (android::base::StartsWith(location, kApexPath)) {
-    size_t start_index = strlen(kApexPath);
-    size_t slash_index = location.find_first_of('/', start_index);
-    LOG_ALWAYS_FATAL_IF((slash_index == std::string::npos),
-                        "Error finding namespace of apex: no slash in path %s", caller_location);
-    std::string name = location.substr(start_index, slash_index - start_index);
-    std::replace(name.begin(), name.end(), '.', '_');
-    android_namespace_t* boot_namespace = android_get_exported_namespace(name.c_str());
+  auto name = nativeloader::FindApexNamespaceName(caller_location);
+  if (name.ok()) {
+    android_namespace_t* boot_namespace = android_get_exported_namespace(name->c_str());
     LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
-                        "Error finding namespace of apex: no namespace called %s", name.c_str());
+                        "Error finding namespace of apex: no namespace called %s", name->c_str());
     return boot_namespace;
   }
   return nullptr;
 }
-#endif  // #if defined(__ANDROID__)
+
+Result<void> CreateNativeloaderDefaultNamespaceLibsLink(NativeLoaderNamespace& ns)
+    REQUIRES(g_namespaces_mutex) {
+  const char* links = getenv("NATIVELOADER_DEFAULT_NAMESPACE_LIBS");
+  if (links == nullptr || *links == 0) {
+    return {};
+  }
+  // Pass nullptr to Link() to create a link to the default namespace without
+  // requiring it to be visible.
+  return ns.Link(nullptr, links);
+}
+
+Result<NativeLoaderNamespace*> GetNativeloaderExtraLibsNamespace() REQUIRES(g_namespaces_mutex) {
+  if (g_nativeloader_extra_libs_namespace != nullptr) {
+    return g_nativeloader_extra_libs_namespace;
+  }
+
+  Result<NativeLoaderNamespace> ns =
+      NativeLoaderNamespace::Create(kNativeloaderExtraLibs,
+                                    /*search_paths=*/"",
+                                    /*permitted_paths=*/"",
+                                    /*parent=*/nullptr,
+                                    /*is_shared=*/false,
+                                    /*is_exempt_list_enabled=*/false,
+                                    /*also_used_as_anonymous=*/false);
+  if (!ns.ok()) {
+    return ns.error();
+  }
+  g_nativeloader_extra_libs_namespace = new NativeLoaderNamespace(std::move(ns.value()));
+  Result<void> linked =
+      CreateNativeloaderDefaultNamespaceLibsLink(*g_nativeloader_extra_libs_namespace);
+  if (!linked.ok()) {
+    return linked.error();
+  }
+  return g_nativeloader_extra_libs_namespace;
+}
+
+// If the given path matches a library in NATIVELOADER_DEFAULT_NAMESPACE_LIBS
+// then load it in the nativeloader-extra-libs namespace, otherwise return
+// nullptr without error.
+Result<void*> TryLoadNativeloaderExtraLib(const char* path) {
+  const char* links = getenv("NATIVELOADER_DEFAULT_NAMESPACE_LIBS");
+  if (links == nullptr || *links == 0) {
+    return nullptr;
+  }
+  std::vector<std::string> lib_list = base::Split(links, ":");
+  if (std::find(lib_list.begin(), lib_list.end(), path) == lib_list.end()) {
+    return nullptr;
+  }
+
+  std::lock_guard<std::mutex> guard(g_namespaces_mutex);
+  Result<NativeLoaderNamespace*> ns = GetNativeloaderExtraLibsNamespace();
+  if (!ns.ok()) {
+    return ns.error();
+  }
+  return ns.value()->Load(path);
+}
+
+Result<NativeLoaderNamespace*> CreateClassLoaderNamespaceLocked(JNIEnv* env,
+                                                                int32_t target_sdk_version,
+                                                                jobject class_loader,
+                                                                bool is_shared,
+                                                                jstring dex_path,
+                                                                jstring library_path,
+                                                                jstring permitted_path,
+                                                                jstring uses_library_list)
+    REQUIRES(g_namespaces_mutex) {
+  Result<NativeLoaderNamespace*> ns = g_namespaces->Create(env,
+                                                           target_sdk_version,
+                                                           class_loader,
+                                                           is_shared,
+                                                           dex_path,
+                                                           library_path,
+                                                           permitted_path,
+                                                           uses_library_list);
+  if (!ns.ok()) {
+    return ns;
+  }
+  Result<void> linked = CreateNativeloaderDefaultNamespaceLibsLink(*ns.value());
+  if (!linked.ok()) {
+    return linked.error();
+  }
+  return ns;
+}
+
+#endif  // #if defined(ART_TARGET_ANDROID)
+
 }  // namespace
 
 void InitializeNativeLoader() {
-#if defined(__ANDROID__)
+#if defined(ART_TARGET_ANDROID)
   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
   g_namespaces->Initialize();
 #endif
 }
 
 void ResetNativeLoader() {
-#if defined(__ANDROID__)
+#if defined(ART_TARGET_ANDROID)
   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
   g_namespaces->Reset();
+  delete g_nativeloader_extra_libs_namespace;
+  g_nativeloader_extra_libs_namespace = nullptr;
 #endif
 }
 
 jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
                                    bool is_shared, jstring dex_path, jstring library_path,
-                                   jstring permitted_path) {
-#if defined(__ANDROID__)
+                                   jstring permitted_path, jstring uses_library_list) {
+#if defined(ART_TARGET_ANDROID)
   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
-  auto ns = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
-                                 library_path, permitted_path);
+  Result<NativeLoaderNamespace*> ns = CreateClassLoaderNamespaceLocked(env,
+                                                                       target_sdk_version,
+                                                                       class_loader,
+                                                                       is_shared,
+                                                                       dex_path,
+                                                                       library_path,
+                                                                       permitted_path,
+                                                                       uses_library_list);
   if (!ns.ok()) {
     return env->NewStringUTF(ns.error().message().c_str());
   }
 #else
-  UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path);
+  UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path,
+         uses_library_list);
 #endif
   return nullptr;
 }
@@ -106,8 +209,9 @@
 void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
                         jobject class_loader, const char* caller_location, jstring library_path,
                         bool* needs_native_bridge, char** error_msg) {
-#if defined(__ANDROID__)
+#if defined(ART_TARGET_ANDROID)
   UNUSED(target_sdk_version);
+
   if (class_loader == nullptr) {
     *needs_native_bridge = false;
     if (caller_location != nullptr) {
@@ -124,7 +228,25 @@
         return handle;
       }
     }
-    void* handle = dlopen(path, RTLD_NOW);
+
+    // Check if the library is in NATIVELOADER_DEFAULT_NAMESPACE_LIBS and should
+    // be loaded from the kNativeloaderExtraLibs namespace.
+    {
+      Result<void*> handle = TryLoadNativeloaderExtraLib(path);
+      if (!handle.ok()) {
+        *error_msg = strdup(handle.error().message().c_str());
+        return nullptr;
+      }
+      if (handle.value() != nullptr) {
+        return handle.value();
+      }
+    }
+
+    // Fall back to the system namespace. This happens for preloaded JNI
+    // libraries in the zygote.
+    // TODO(b/185833744): Investigate if this should fall back to the app main
+    // namespace (aka anonymous namespace) instead.
+    void* handle = OpenSystemLibrary(path, RTLD_NOW);
     if (handle == nullptr) {
       *error_msg = strdup(dlerror());
     }
@@ -138,8 +260,14 @@
     // This is the case where the classloader was not created by ApplicationLoaders
     // In this case we create an isolated not-shared namespace for it.
     Result<NativeLoaderNamespace*> isolated_ns =
-        g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */, nullptr,
-                             library_path, nullptr);
+        CreateClassLoaderNamespaceLocked(env,
+                                         target_sdk_version,
+                                         class_loader,
+                                         /*is_shared=*/false,
+                                         /*dex_path=*/nullptr,
+                                         library_path,
+                                         /*permitted_path=*/nullptr,
+                                         /*uses_library_list=*/nullptr);
     if (!isolated_ns.ok()) {
       *error_msg = strdup(isolated_ns.error().message().c_str());
       return nullptr;
@@ -220,7 +348,7 @@
   free(msg);
 }
 
-#if defined(__ANDROID__)
+#if defined(ART_TARGET_ANDROID)
 void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
                                    bool* needs_native_bridge, char** error_msg) {
   auto handle = ns->Load(path);
@@ -249,6 +377,24 @@
   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
   return g_namespaces->FindNamespaceByClassLoader(env, class_loader);
 }
-#endif
+
+void LinkNativeLoaderNamespaceToExportedNamespaceLibrary(struct NativeLoaderNamespace* ns,
+                                                         const char* exported_ns_name,
+                                                         const char* library_name,
+                                                         char** error_msg) {
+  Result<NativeLoaderNamespace> exported_ns =
+      NativeLoaderNamespace::GetExportedNamespace(exported_ns_name, ns->IsBridged());
+  if (!exported_ns.ok()) {
+    *error_msg = strdup(exported_ns.error().message().c_str());
+    return;
+  }
+
+  Result<void> linked = ns->Link(&exported_ns.value(), std::string(library_name));
+  if (!linked.ok()) {
+    *error_msg = strdup(linked.error().message().c_str());
+  }
+}
+
+#endif  // ART_TARGET_ANDROID
 
 };  // namespace android
diff --git a/libnativeloader/native_loader_api_test.c b/libnativeloader/native_loader_api_test.c
new file mode 100644
index 0000000..e7b9f2c
--- /dev/null
+++ b/libnativeloader/native_loader_api_test.c
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+/* 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 "nativeloader/native_loader.h"
diff --git a/libnativeloader/native_loader_lazy.cpp b/libnativeloader/native_loader_lazy.cpp
index 2eb1203..5b82d00 100644
--- a/libnativeloader/native_loader_lazy.cpp
+++ b/libnativeloader/native_loader_lazy.cpp
@@ -40,21 +40,16 @@
   return f;
 }
 
-#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&name)>(#name)
+#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&(name))>(#name)
 
 }  // namespace
 
-void InitializeNativeLoader() {
-  static auto f = GET_FUNC_PTR(InitializeNativeLoader);
-  return f();
-}
-
 jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
                                    bool is_shared, jstring dex_path, jstring library_path,
-                                   jstring permitted_path) {
+                                   jstring permitted_path, jstring uses_library_list) {
   static auto f = GET_FUNC_PTR(CreateClassLoaderNamespace);
   return f(env, target_sdk_version, class_loader, is_shared, dex_path, library_path,
-           permitted_path);
+           permitted_path, uses_library_list);
 }
 
 void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
@@ -92,11 +87,6 @@
   return f(ns, path, needs_native_bridge, error_msg);
 }
 
-void ResetNativeLoader() {
-  static auto f = GET_FUNC_PTR(ResetNativeLoader);
-  return f();
-}
-
 #undef GET_FUNC_PTR
 
 }  // namespace android
diff --git a/libnativeloader/native_loader_lazy_test.cpp b/libnativeloader/native_loader_lazy_test.cpp
new file mode 100644
index 0000000..b863c85
--- /dev/null
+++ b/libnativeloader/native_loader_lazy_test.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#if defined(ART_TARGET_ANDROID)
+
+#include <gtest/gtest.h>
+
+#include "native_loader_test.h"
+#include "nativehelper/scoped_utf_chars.h"
+#include "nativeloader/native_loader.h"
+
+namespace android {
+namespace nativeloader {
+
+using ::testing::StrEq;
+
+// Only need to test that the trivial lazy lib wrappers call through to the real
+// functions, but still have to mock things well enough to avoid null pointer
+// dereferences.
+
+class NativeLoaderLazyTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    mock = std::make_unique<testing::NiceMock<MockPlatform>>(false);
+    env = std::make_unique<JNIEnv>();
+    env->functions = CreateJNINativeInterface();
+  }
+
+  void TearDown() override {
+    // ResetNativeLoader isn't accessible through the lazy library, so we cannot
+    // reset libnativeloader internal state. Hence be sure to not reuse the same
+    // class loader/namespace names.
+    delete env->functions;
+    mock.reset();
+  }
+
+  void CallCreateClassLoaderNamespace(const char* class_loader) {
+    ON_CALL(*mock, JniObject_getParent(StrEq(class_loader))).WillByDefault(Return(nullptr));
+    EXPECT_CALL(*mock, mock_create_namespace)
+        .WillOnce(Return(TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE(class_loader))));
+    ON_CALL(*mock, mock_link_namespaces).WillByDefault(Return(true));
+
+    jstring err = CreateClassLoaderNamespace(env.get(),
+                                             17,
+                                             env.get()->NewStringUTF(class_loader),
+                                             false,
+                                             env.get()->NewStringUTF("/data/app/foo/classes.dex"),
+                                             env.get()->NewStringUTF("/data/app/foo"),
+                                             /*permitted_path=*/nullptr,
+                                             /*uses_library_list=*/nullptr);
+    EXPECT_EQ(err, nullptr) << "Error is: " << std::string(ScopedUtfChars(env.get(), err).c_str());
+  }
+
+  std::unique_ptr<JNIEnv> env;
+};
+
+TEST_F(NativeLoaderLazyTest, CreateClassLoaderNamespace) {
+  CallCreateClassLoaderNamespace("my_classloader_1");
+}
+
+TEST_F(NativeLoaderLazyTest, OpenNativeLibrary) {
+  bool needs_native_bridge;
+  char* errmsg = nullptr;
+  EXPECT_EQ(nullptr,
+            OpenNativeLibrary(env.get(),
+                              17,
+                              "libnotfound.so",
+                              env.get()->NewStringUTF("my_classloader"),
+                              /*caller_location=*/nullptr,
+                              /*library_path=*/nullptr,
+                              &needs_native_bridge,
+                              &errmsg));
+  EXPECT_NE(nullptr, errmsg);
+  NativeLoaderFreeErrorMessage(errmsg);
+}
+
+TEST_F(NativeLoaderLazyTest, CloseNativeLibrary) {
+  char* errmsg = nullptr;
+  EXPECT_FALSE(CloseNativeLibrary(nullptr, false, &errmsg));
+  EXPECT_NE(nullptr, errmsg);
+  NativeLoaderFreeErrorMessage(errmsg);
+}
+
+TEST_F(NativeLoaderLazyTest, OpenNativeLibraryInNamespace) {
+  CallCreateClassLoaderNamespace("my_classloader_2");
+  struct NativeLoaderNamespace* ns = FindNativeLoaderNamespaceByClassLoader(
+      env.get(), env.get()->NewStringUTF("my_classloader_2"));
+  ASSERT_NE(nullptr, ns);
+
+  bool needs_native_bridge;
+  char* errmsg = nullptr;
+  EXPECT_FALSE(OpenNativeLibraryInNamespace(ns, "libnotfound.so", &needs_native_bridge, &errmsg));
+  EXPECT_NE(nullptr, errmsg);
+  NativeLoaderFreeErrorMessage(errmsg);
+}
+
+TEST_F(NativeLoaderLazyTest, FindNamespaceByClassLoader) {
+  EXPECT_EQ(nullptr, FindNamespaceByClassLoader(env.get(), env.get()->NewStringUTF("namespace")));
+}
+
+TEST_F(NativeLoaderLazyTest, FindNativeLoaderNamespaceByClassLoader) {
+  EXPECT_EQ(
+      nullptr,
+      FindNativeLoaderNamespaceByClassLoader(env.get(), env.get()->NewStringUTF("namespace")));
+}
+
+TEST_F(NativeLoaderLazyTest, NativeLoaderFreeErrorMessage) {
+  NativeLoaderFreeErrorMessage(nullptr);
+}
+
+}  // namespace nativeloader
+}  // namespace android
+
+#endif  // defined(ART_TARGET_ANDROID)
diff --git a/libnativeloader/native_loader_namespace.cpp b/libnativeloader/native_loader_namespace.cpp
index 49f3035..669fa74 100644
--- a/libnativeloader/native_loader_namespace.cpp
+++ b/libnativeloader/native_loader_namespace.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#if defined(ART_TARGET_ANDROID)
+
 #define LOG_TAG "nativeloader"
 
 #include "native_loader_namespace.h"
@@ -84,7 +86,7 @@
 
 Result<NativeLoaderNamespace> NativeLoaderNamespace::Create(
     const std::string& name, const std::string& search_paths, const std::string& permitted_paths,
-    const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled,
+    const NativeLoaderNamespace* parent, bool is_shared, bool is_exempt_list_enabled,
     bool also_used_as_anonymous) {
   bool is_bridged = false;
   if (parent != nullptr) {
@@ -114,8 +116,8 @@
   if (is_shared) {
     type |= ANDROID_NAMESPACE_TYPE_SHARED;
   }
-  if (is_greylist_enabled) {
-    type |= ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED;
+  if (is_exempt_list_enabled) {
+    type |= ANDROID_NAMESPACE_TYPE_EXEMPT_LIST_ENABLED;
   }
 
   if (!is_bridged) {
@@ -137,18 +139,20 @@
                 is_bridged ? "bridged" : "native", name, search_paths, permitted_paths);
 }
 
-Result<void> NativeLoaderNamespace::Link(const NativeLoaderNamespace& target,
+Result<void> NativeLoaderNamespace::Link(const NativeLoaderNamespace* target,
                                          const std::string& shared_libs) const {
   LOG_ALWAYS_FATAL_IF(shared_libs.empty(), "empty share lib when linking %s to %s",
-                      this->name().c_str(), target.name().c_str());
+                      this->name().c_str(), target == nullptr ? "default" : target->name().c_str());
   if (!IsBridged()) {
-    if (android_link_namespaces(this->ToRawAndroidNamespace(), target.ToRawAndroidNamespace(),
+    if (android_link_namespaces(this->ToRawAndroidNamespace(),
+                                target == nullptr ? nullptr : target->ToRawAndroidNamespace(),
                                 shared_libs.c_str())) {
       return {};
     }
   } else {
     if (NativeBridgeLinkNamespaces(this->ToRawNativeBridgeNamespace(),
-                                   target.ToRawNativeBridgeNamespace(), shared_libs.c_str())) {
+                                   target == nullptr ? nullptr : target->ToRawNativeBridgeNamespace(),
+                                   shared_libs.c_str())) {
       return {};
     }
   }
@@ -175,3 +179,5 @@
 }
 
 }  // namespace android
+
+#endif  // defined(ART_TARGET_ANDROID)
diff --git a/libnativeloader/native_loader_namespace.h b/libnativeloader/native_loader_namespace.h
index ee84f61..9a5aeac 100644
--- a/libnativeloader/native_loader_namespace.h
+++ b/libnativeloader/native_loader_namespace.h
@@ -17,7 +17,7 @@
 #ifndef ART_LIBNATIVELOADER_NATIVE_LOADER_NAMESPACE_H_
 #define ART_LIBNATIVELOADER_NATIVE_LOADER_NAMESPACE_H_
 
-#if defined(__ANDROID__)
+#if defined(ART_TARGET_ANDROID)
 
 #include <string>
 #include <variant>
@@ -42,7 +42,7 @@
                                               const std::string& search_paths,
                                               const std::string& permitted_paths,
                                               const NativeLoaderNamespace* parent, bool is_shared,
-                                              bool is_greylist_enabled,
+                                              bool is_exempt_list_enabled,
                                               bool also_used_as_anonymous);
 
   NativeLoaderNamespace(NativeLoaderNamespace&&) = default;
@@ -55,7 +55,11 @@
   std::string name() const { return name_; }
   bool IsBridged() const { return raw_.index() == 1; }
 
-  Result<void> Link(const NativeLoaderNamespace& target, const std::string& shared_libs) const;
+  // Creates a link from this namespace to target for the ":"-separated list of
+  // libraries in shared_libs. If target is nullptr it creates a link to the
+  // default namespace.
+  Result<void> Link(const NativeLoaderNamespace* target, const std::string& shared_libs) const;
+
   Result<void*> Load(const char* lib_name) const;
 
   static Result<NativeLoaderNamespace> GetExportedNamespace(const std::string& name,
@@ -73,6 +77,6 @@
 };
 
 }  // namespace android
-#endif  // #if defined(__ANDROID__)
+#endif  // #if defined(ART_TARGET_ANDROID)
 
 #endif  // ART_LIBNATIVELOADER_NATIVE_LOADER_NAMESPACE_H_
diff --git a/libnativeloader/native_loader_test.cpp b/libnativeloader/native_loader_test.cpp
index 8c4a8c5..c1dd4aa 100644
--- a/libnativeloader/native_loader_test.cpp
+++ b/libnativeloader/native_loader_test.cpp
@@ -14,18 +14,16 @@
  * limitations under the License.
  */
 
+#if defined(ART_TARGET_ANDROID)
+
+#include "native_loader_test.h"
+
 #include <dlfcn.h>
-#include <memory>
-#include <unordered_map>
 
 #include <android-base/strings.h>
-#include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <jni.h>
 
-#include "native_loader_namespace.h"
 #include "nativehelper/scoped_utf_chars.h"
-#include "nativeloader/dlext_namespaces.h"
 #include "nativeloader/native_loader.h"
 #include "public_libraries.h"
 
@@ -33,10 +31,10 @@
 namespace nativeloader {
 
 using ::testing::Eq;
-using ::testing::Return;
+using ::testing::NotNull;
 using ::testing::StrEq;
-using ::testing::_;
 using internal::ConfigEntry;
+using internal::ParseApexLibrariesConfig;
 using internal::ParseConfig;
 
 #if defined(__LP64__)
@@ -45,240 +43,6 @@
 #define LIB_DIR "lib"
 #endif
 
-// gmock interface that represents interested platform APIs on libdl and libnativebridge
-class Platform {
- public:
-  virtual ~Platform() {}
-
-  // libdl APIs
-  virtual void* dlopen(const char* filename, int flags) = 0;
-  virtual int dlclose(void* handle) = 0;
-  virtual char* dlerror(void) = 0;
-
-  // These mock_* are the APIs semantically the same across libdl and libnativebridge.
-  // Instead of having two set of mock APIs for the two, define only one set with an additional
-  // argument 'bool bridged' to identify the context (i.e., called for libdl or libnativebridge).
-  typedef char* mock_namespace_handle;
-  virtual bool mock_init_anonymous_namespace(bool bridged, const char* sonames,
-                                             const char* search_paths) = 0;
-  virtual mock_namespace_handle mock_create_namespace(
-      bool bridged, const char* name, const char* ld_library_path, const char* default_library_path,
-      uint64_t type, const char* permitted_when_isolated_path, mock_namespace_handle parent) = 0;
-  virtual bool mock_link_namespaces(bool bridged, mock_namespace_handle from,
-                                    mock_namespace_handle to, const char* sonames) = 0;
-  virtual mock_namespace_handle mock_get_exported_namespace(bool bridged, const char* name) = 0;
-  virtual void* mock_dlopen_ext(bool bridged, const char* filename, int flags,
-                                mock_namespace_handle ns) = 0;
-
-  // libnativebridge APIs for which libdl has no corresponding APIs
-  virtual bool NativeBridgeInitialized() = 0;
-  virtual const char* NativeBridgeGetError() = 0;
-  virtual bool NativeBridgeIsPathSupported(const char*) = 0;
-  virtual bool NativeBridgeIsSupported(const char*) = 0;
-
-  // To mock "ClassLoader Object.getParent()"
-  virtual const char* JniObject_getParent(const char*) = 0;
-};
-
-// The mock does not actually create a namespace object. But simply casts the pointer to the
-// string for the namespace name as the handle to the namespace object.
-#define TO_ANDROID_NAMESPACE(str) \
-  reinterpret_cast<struct android_namespace_t*>(const_cast<char*>(str))
-
-#define TO_BRIDGED_NAMESPACE(str) \
-  reinterpret_cast<struct native_bridge_namespace_t*>(const_cast<char*>(str))
-
-#define TO_MOCK_NAMESPACE(ns) reinterpret_cast<Platform::mock_namespace_handle>(ns)
-
-// These represents built-in namespaces created by the linker according to ld.config.txt
-static std::unordered_map<std::string, Platform::mock_namespace_handle> namespaces = {
-    {"system", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("system"))},
-    {"default", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("default"))},
-    {"com_android_art", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("com_android_art"))},
-    {"sphal", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("sphal"))},
-    {"vndk", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("vndk"))},
-    {"vndk_product", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("vndk_product"))},
-    {"com_android_neuralnetworks", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("com_android_neuralnetworks"))},
-    {"com_android_os_statsd", TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("com_android_os_statsd"))},
-};
-
-// The actual gmock object
-class MockPlatform : public Platform {
- public:
-  explicit MockPlatform(bool is_bridged) : is_bridged_(is_bridged) {
-    ON_CALL(*this, NativeBridgeIsSupported(_)).WillByDefault(Return(is_bridged_));
-    ON_CALL(*this, NativeBridgeIsPathSupported(_)).WillByDefault(Return(is_bridged_));
-    ON_CALL(*this, mock_get_exported_namespace(_, _))
-        .WillByDefault(testing::Invoke([](bool, const char* name) -> mock_namespace_handle {
-          if (namespaces.find(name) != namespaces.end()) {
-            return namespaces[name];
-          }
-          return TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE("(namespace not found"));
-        }));
-  }
-
-  // Mocking libdl APIs
-  MOCK_METHOD2(dlopen, void*(const char*, int));
-  MOCK_METHOD1(dlclose, int(void*));
-  MOCK_METHOD0(dlerror, char*());
-
-  // Mocking the common APIs
-  MOCK_METHOD3(mock_init_anonymous_namespace, bool(bool, const char*, const char*));
-  MOCK_METHOD7(mock_create_namespace,
-               mock_namespace_handle(bool, const char*, const char*, const char*, uint64_t,
-                                     const char*, mock_namespace_handle));
-  MOCK_METHOD4(mock_link_namespaces,
-               bool(bool, mock_namespace_handle, mock_namespace_handle, const char*));
-  MOCK_METHOD2(mock_get_exported_namespace, mock_namespace_handle(bool, const char*));
-  MOCK_METHOD4(mock_dlopen_ext, void*(bool, const char*, int, mock_namespace_handle));
-
-  // Mocking libnativebridge APIs
-  MOCK_METHOD0(NativeBridgeInitialized, bool());
-  MOCK_METHOD0(NativeBridgeGetError, const char*());
-  MOCK_METHOD1(NativeBridgeIsPathSupported, bool(const char*));
-  MOCK_METHOD1(NativeBridgeIsSupported, bool(const char*));
-
-  // Mocking "ClassLoader Object.getParent()"
-  MOCK_METHOD1(JniObject_getParent, const char*(const char*));
-
- private:
-  bool is_bridged_;
-};
-
-static std::unique_ptr<MockPlatform> mock;
-
-// Provide C wrappers for the mock object.
-extern "C" {
-void* dlopen(const char* file, int flag) {
-  return mock->dlopen(file, flag);
-}
-
-int dlclose(void* handle) {
-  return mock->dlclose(handle);
-}
-
-char* dlerror(void) {
-  return mock->dlerror();
-}
-
-bool android_init_anonymous_namespace(const char* sonames, const char* search_path) {
-  return mock->mock_init_anonymous_namespace(false, sonames, search_path);
-}
-
-struct android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
-                                                     const char* default_library_path,
-                                                     uint64_t type,
-                                                     const char* permitted_when_isolated_path,
-                                                     struct android_namespace_t* parent) {
-  return TO_ANDROID_NAMESPACE(
-      mock->mock_create_namespace(false, name, ld_library_path, default_library_path, type,
-                                  permitted_when_isolated_path, TO_MOCK_NAMESPACE(parent)));
-}
-
-bool android_link_namespaces(struct android_namespace_t* from, struct android_namespace_t* to,
-                             const char* sonames) {
-  return mock->mock_link_namespaces(false, TO_MOCK_NAMESPACE(from), TO_MOCK_NAMESPACE(to), sonames);
-}
-
-struct android_namespace_t* android_get_exported_namespace(const char* name) {
-  return TO_ANDROID_NAMESPACE(mock->mock_get_exported_namespace(false, name));
-}
-
-void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* info) {
-  return mock->mock_dlopen_ext(false, filename, flags, TO_MOCK_NAMESPACE(info->library_namespace));
-}
-
-// libnativebridge APIs
-bool NativeBridgeIsSupported(const char* libpath) {
-  return mock->NativeBridgeIsSupported(libpath);
-}
-
-struct native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name) {
-  return TO_BRIDGED_NAMESPACE(mock->mock_get_exported_namespace(true, name));
-}
-
-struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
-    const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
-    const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent) {
-  return TO_BRIDGED_NAMESPACE(
-      mock->mock_create_namespace(true, name, ld_library_path, default_library_path, type,
-                                  permitted_when_isolated_path, TO_MOCK_NAMESPACE(parent)));
-}
-
-bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
-                                struct native_bridge_namespace_t* to, const char* sonames) {
-  return mock->mock_link_namespaces(true, TO_MOCK_NAMESPACE(from), TO_MOCK_NAMESPACE(to), sonames);
-}
-
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
-                                 struct native_bridge_namespace_t* ns) {
-  return mock->mock_dlopen_ext(true, libpath, flag, TO_MOCK_NAMESPACE(ns));
-}
-
-bool NativeBridgeInitialized() {
-  return mock->NativeBridgeInitialized();
-}
-
-bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
-                                        const char* anon_ns_library_path) {
-  return mock->mock_init_anonymous_namespace(true, public_ns_sonames, anon_ns_library_path);
-}
-
-const char* NativeBridgeGetError() {
-  return mock->NativeBridgeGetError();
-}
-
-bool NativeBridgeIsPathSupported(const char* path) {
-  return mock->NativeBridgeIsPathSupported(path);
-}
-
-}  // extern "C"
-
-// A very simple JNI mock.
-// jstring is a pointer to utf8 char array. We don't need utf16 char here.
-// jobject, jclass, and jmethodID are also a pointer to utf8 char array
-// Only a few JNI methods that are actually used in libnativeloader are mocked.
-JNINativeInterface* CreateJNINativeInterface() {
-  JNINativeInterface* inf = new JNINativeInterface();
-  memset(inf, 0, sizeof(JNINativeInterface));
-
-  inf->GetStringUTFChars = [](JNIEnv*, jstring s, jboolean*) -> const char* {
-    return reinterpret_cast<const char*>(s);
-  };
-
-  inf->ReleaseStringUTFChars = [](JNIEnv*, jstring, const char*) -> void { return; };
-
-  inf->NewStringUTF = [](JNIEnv*, const char* bytes) -> jstring {
-    return reinterpret_cast<jstring>(const_cast<char*>(bytes));
-  };
-
-  inf->FindClass = [](JNIEnv*, const char* name) -> jclass {
-    return reinterpret_cast<jclass>(const_cast<char*>(name));
-  };
-
-  inf->CallObjectMethodV = [](JNIEnv*, jobject obj, jmethodID mid, va_list) -> jobject {
-    if (strcmp("getParent", reinterpret_cast<const char*>(mid)) == 0) {
-      // JniObject_getParent can be a valid jobject or nullptr if there is
-      // no parent classloader.
-      const char* ret = mock->JniObject_getParent(reinterpret_cast<const char*>(obj));
-      return reinterpret_cast<jobject>(const_cast<char*>(ret));
-    }
-    return nullptr;
-  };
-
-  inf->GetMethodID = [](JNIEnv*, jclass, const char* name, const char*) -> jmethodID {
-    return reinterpret_cast<jmethodID>(const_cast<char*>(name));
-  };
-
-  inf->NewWeakGlobalRef = [](JNIEnv*, jobject obj) -> jobject { return obj; };
-
-  inf->IsSameObject = [](JNIEnv*, jobject a, jobject b) -> jboolean {
-    return strcmp(reinterpret_cast<const char*>(a), reinterpret_cast<const char*>(b)) == 0;
-  };
-
-  return inf;
-}
-
 static void* const any_nonnull = reinterpret_cast<void*>(0x12345678);
 
 // Custom matcher for comparing namespace handles
@@ -305,7 +69,8 @@
     std::vector<std::string> default_public_libs =
         android::base::Split(preloadable_public_libraries(), ":");
     for (auto l : default_public_libs) {
-      EXPECT_CALL(*mock, dlopen(StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE))
+      EXPECT_CALL(*mock,
+                  mock_dlopen_ext(false, StrEq(l.c_str()), RTLD_NOW | RTLD_NODELETE, NotNull()))
           .WillOnce(Return(any_nonnull));
     }
   }
@@ -328,6 +93,76 @@
   RunTest();
 }
 
+TEST_P(NativeLoaderTest, OpenNativeLibraryWithoutClassloaderInApex) {
+  const char* test_lib_path = "libfoo.so";
+  void* fake_handle = &fake_handle;  // Arbitrary non-null value
+  EXPECT_CALL(*mock,
+              mock_dlopen_ext(false, StrEq(test_lib_path), RTLD_NOW, NsEq("com_android_art")))
+      .WillOnce(Return(fake_handle));
+
+  bool needs_native_bridge = false;
+  char* errmsg = nullptr;
+  EXPECT_EQ(fake_handle,
+            OpenNativeLibrary(env.get(),
+                              /*target_sdk_version=*/17,
+                              test_lib_path,
+                              /*class_loader=*/nullptr,
+                              /*caller_location=*/"/apex/com.android.art/javalib/myloadinglib.jar",
+                              /*library_path=*/nullptr,
+                              &needs_native_bridge,
+                              &errmsg));
+  // OpenNativeLibrary never uses nativebridge when there's no classloader. That
+  // should maybe change.
+  EXPECT_EQ(needs_native_bridge, false);
+  EXPECT_EQ(errmsg, nullptr);
+}
+
+TEST_P(NativeLoaderTest, OpenNativeLibraryWithoutClassloaderInFramework) {
+  const char* test_lib_path = "libfoo.so";
+  void* fake_handle = &fake_handle;  // Arbitrary non-null value
+  EXPECT_CALL(*mock, mock_dlopen_ext(false, StrEq(test_lib_path), RTLD_NOW, NsEq("system")))
+      .WillOnce(Return(fake_handle));
+
+  bool needs_native_bridge = false;
+  char* errmsg = nullptr;
+  EXPECT_EQ(fake_handle,
+            OpenNativeLibrary(env.get(),
+                              /*target_sdk_version=*/17,
+                              test_lib_path,
+                              /*class_loader=*/nullptr,
+                              /*caller_location=*/"/system/framework/framework.jar!classes1.dex",
+                              /*library_path=*/nullptr,
+                              &needs_native_bridge,
+                              &errmsg));
+  // OpenNativeLibrary never uses nativebridge when there's no classloader. That
+  // should maybe change.
+  EXPECT_EQ(needs_native_bridge, false);
+  EXPECT_EQ(errmsg, nullptr);
+}
+
+TEST_P(NativeLoaderTest, OpenNativeLibraryWithoutClassloaderAndCallerLocation) {
+  const char* test_lib_path = "libfoo.so";
+  void* fake_handle = &fake_handle;  // Arbitrary non-null value
+  EXPECT_CALL(*mock, mock_dlopen_ext(false, StrEq(test_lib_path), RTLD_NOW, NsEq("system")))
+      .WillOnce(Return(fake_handle));
+
+  bool needs_native_bridge = false;
+  char* errmsg = nullptr;
+  EXPECT_EQ(fake_handle,
+            OpenNativeLibrary(env.get(),
+                              /*target_sdk_version=*/17,
+                              test_lib_path,
+                              /*class_loader=*/nullptr,
+                              /*caller_location=*/nullptr,
+                              /*library_path=*/nullptr,
+                              &needs_native_bridge,
+                              &errmsg));
+  // OpenNativeLibrary never uses nativebridge when there's no classloader. That
+  // should maybe change.
+  EXPECT_EQ(needs_native_bridge, false);
+  EXPECT_EQ(errmsg, nullptr);
+}
+
 INSTANTIATE_TEST_SUITE_P(NativeLoaderTests, NativeLoaderTest, testing::Bool());
 
 /////////////////////////////////////////////////////////////////
@@ -352,20 +187,22 @@
   std::string expected_parent_namespace = "system";
   bool expected_link_with_platform_ns = true;
   bool expected_link_with_art_ns = true;
+  bool expected_link_with_i18n_ns = true;
+  bool expected_link_with_conscrypt_ns = false;
   bool expected_link_with_sphal_ns = !vendor_public_libraries().empty();
   bool expected_link_with_vndk_ns = false;
   bool expected_link_with_vndk_product_ns = false;
   bool expected_link_with_default_ns = false;
   bool expected_link_with_neuralnetworks_ns = true;
-  bool expected_link_with_statsd_ns = true;
   std::string expected_shared_libs_to_platform_ns = default_public_libraries();
-  std::string expected_shared_libs_to_art_ns = art_public_libraries();
+  std::string expected_shared_libs_to_art_ns = apex_public_libraries().at("com_android_art");
+  std::string expected_shared_libs_to_i18n_ns = apex_public_libraries().at("com_android_i18n");
+  std::string expected_shared_libs_to_conscrypt_ns = apex_jni_libraries("com_android_conscrypt");
   std::string expected_shared_libs_to_sphal_ns = vendor_public_libraries();
   std::string expected_shared_libs_to_vndk_ns = vndksp_libraries_vendor();
   std::string expected_shared_libs_to_vndk_product_ns = vndksp_libraries_product();
   std::string expected_shared_libs_to_default_ns = default_public_libraries();
-  std::string expected_shared_libs_to_neuralnetworks_ns = neuralnetworks_public_libraries();
-  std::string expected_shared_libs_to_statsd_ns = statsd_public_libraries();
+  std::string expected_shared_libs_to_neuralnetworks_ns = apex_public_libraries().at("com_android_neuralnetworks");
 
   void SetExpectations() {
     NativeLoaderTest::SetExpectations();
@@ -390,6 +227,11 @@
                                               StrEq(expected_shared_libs_to_art_ns)))
           .WillOnce(Return(true));
     }
+    if (expected_link_with_i18n_ns) {
+      EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_i18n"),
+                                              StrEq(expected_shared_libs_to_i18n_ns)))
+          .WillOnce(Return(true));
+    }
     if (expected_link_with_sphal_ns) {
       EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("sphal"),
                                               StrEq(expected_shared_libs_to_sphal_ns)))
@@ -415,9 +257,9 @@
                                               StrEq(expected_shared_libs_to_neuralnetworks_ns)))
           .WillOnce(Return(true));
     }
-    if (expected_link_with_statsd_ns) {
-      EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_os_statsd"),
-                                              StrEq(expected_shared_libs_to_statsd_ns)))
+    if (expected_link_with_conscrypt_ns) {
+      EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), _, NsEq("com_android_conscrypt"),
+                                              StrEq(expected_shared_libs_to_conscrypt_ns)))
           .WillOnce(Return(true));
     }
   }
@@ -428,7 +270,7 @@
     jstring err = CreateClassLoaderNamespace(
         env(), target_sdk_version, env()->NewStringUTF(class_loader.c_str()), is_shared,
         env()->NewStringUTF(dex_path.c_str()), env()->NewStringUTF(library_path.c_str()),
-        env()->NewStringUTF(permitted_path.c_str()));
+        env()->NewStringUTF(permitted_path.c_str()), /*uses_library_list=*/ nullptr);
 
     // no error
     EXPECT_EQ(err, nullptr) << "Error is: " << std::string(ScopedUtfChars(env(), err).c_str());
@@ -501,6 +343,17 @@
   RunTest();
 }
 
+TEST_P(NativeLoaderTest_Create, SystemServerWithApexJars) {
+  dex_path = "/system/framework/services.jar:/apex/com.android.conscrypt/javalib/service-foo.jar";
+  is_shared = true;
+
+  expected_namespace_name = "classloader-namespace-shared";
+  expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
+  expected_link_with_conscrypt_ns = true;
+  SetExpectations();
+  RunTest();
+}
+
 TEST_P(NativeLoaderTest_Create, UnbundledProductApp) {
   dex_path = "/product/app/foo/foo.apk";
   is_shared = false;
@@ -569,7 +422,7 @@
       env(), second_app_target_sdk_version, env()->NewStringUTF(second_app_class_loader.c_str()),
       second_app_is_shared, env()->NewStringUTF(second_app_dex_path.c_str()),
       env()->NewStringUTF(second_app_library_path.c_str()),
-      env()->NewStringUTF(second_app_permitted_path.c_str()));
+      env()->NewStringUTF(second_app_permitted_path.c_str()), /*uses_library_list=*/ nullptr);
 
   // success
   EXPECT_EQ(err, nullptr) << "Error is: " << std::string(ScopedUtfChars(env(), err).c_str());
@@ -674,5 +527,77 @@
   ASSERT_FALSE(ParseConfig("libA.so nopreload # comment", always_true).ok());
 }
 
+TEST(NativeLoaderApexLibrariesConfigParser, BasicLoading) {
+  const char file_content[] = R"(
+# comment
+jni com_android_foo libfoo.so
+# Empty line is ignored
+
+jni com_android_bar libbar.so:libbar2.so
+
+  public com_android_bar libpublic.so
+)";
+
+  auto jni_libs = ParseApexLibrariesConfig(file_content, "jni");
+  ASSERT_RESULT_OK(jni_libs);
+  std::map<std::string, std::string> expected_jni_libs {
+    {"com_android_foo", "libfoo.so"},
+    {"com_android_bar", "libbar.so:libbar2.so"},
+  };
+  ASSERT_EQ(expected_jni_libs, *jni_libs);
+
+  auto public_libs = ParseApexLibrariesConfig(file_content, "public");
+  ASSERT_RESULT_OK(public_libs);
+  std::map<std::string, std::string> expected_public_libs {
+    {"com_android_bar", "libpublic.so"},
+  };
+  ASSERT_EQ(expected_public_libs, *public_libs);
+}
+
+TEST(NativeLoaderApexLibrariesConfigParser, RejectMalformedLine) {
+  const char file_content[] = R"(
+jni com_android_foo libfoo
+# missing <library list>
+jni com_android_bar
+)";
+  auto result = ParseApexLibrariesConfig(file_content, "jni");
+  ASSERT_FALSE(result.ok());
+  ASSERT_EQ("Malformed line \"jni com_android_bar\"", result.error().message());
+}
+
+TEST(NativeLoaderApexLibrariesConfigParser, RejectInvalidTag) {
+  const char file_content[] = R"(
+jni apex1 lib
+public apex2 lib
+# unknown tag
+unknown com_android_foo libfoo
+)";
+  auto result = ParseApexLibrariesConfig(file_content, "jni");
+  ASSERT_FALSE(result.ok());
+  ASSERT_EQ("Invalid tag \"unknown com_android_foo libfoo\"", result.error().message());
+}
+
+TEST(NativeLoaderApexLibrariesConfigParser, RejectInvalidApexNamespace) {
+  const char file_content[] = R"(
+# apex linker namespace should be mangled ('.' -> '_')
+jni com.android.foo lib
+)";
+  auto result = ParseApexLibrariesConfig(file_content, "jni");
+  ASSERT_FALSE(result.ok());
+  ASSERT_EQ("Invalid apex_namespace \"jni com.android.foo lib\"", result.error().message());
+}
+
+TEST(NativeLoaderApexLibrariesConfigParser, RejectInvalidLibraryList) {
+  const char file_content[] = R"(
+# library list is ":" separated list of filenames
+jni com_android_foo lib64/libfoo.so
+)";
+  auto result = ParseApexLibrariesConfig(file_content, "jni");
+  ASSERT_FALSE(result.ok());
+  ASSERT_EQ("Invalid library_list \"jni com_android_foo lib64/libfoo.so\"", result.error().message());
+}
+
 }  // namespace nativeloader
 }  // namespace android
+
+#endif  // defined(ART_TARGET_ANDROID)
diff --git a/libnativeloader/native_loader_test.h b/libnativeloader/native_loader_test.h
new file mode 100644
index 0000000..09c56e5
--- /dev/null
+++ b/libnativeloader/native_loader_test.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2021 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_LIBNATIVELOADER_NATIVE_LOADER_TEST_H_
+#define ART_LIBNATIVELOADER_NATIVE_LOADER_TEST_H_
+
+#include <string>
+#include <unordered_map>
+
+#include <android-base/stringprintf.h>
+#include <gmock/gmock.h>
+#include <jni.h>
+
+#include "native_loader_namespace.h"
+#include "nativeloader/dlext_namespaces.h"
+
+namespace android {
+namespace nativeloader {
+
+using ::testing::Return;
+using ::testing::_;
+
+// gmock interface that represents interested platform APIs on libdl_android and libnativebridge
+class Platform {
+ public:
+  virtual ~Platform() {}
+
+  // These mock_* are the APIs semantically the same across libdl_android and libnativebridge.
+  // Instead of having two set of mock APIs for the two, define only one set with an additional
+  // argument 'bool bridged' to identify the context (i.e., called for libdl_android or
+  // libnativebridge).
+  typedef char* mock_namespace_handle;
+  virtual bool mock_init_anonymous_namespace(bool bridged, const char* sonames,
+                                             const char* search_paths) = 0;
+  virtual mock_namespace_handle mock_create_namespace(
+      bool bridged, const char* name, const char* ld_library_path, const char* default_library_path,
+      uint64_t type, const char* permitted_when_isolated_path, mock_namespace_handle parent) = 0;
+  virtual bool mock_link_namespaces(bool bridged, mock_namespace_handle from,
+                                    mock_namespace_handle to, const char* sonames) = 0;
+  virtual mock_namespace_handle mock_get_exported_namespace(bool bridged, const char* name) = 0;
+  virtual void* mock_dlopen_ext(bool bridged, const char* filename, int flags,
+                                mock_namespace_handle ns) = 0;
+
+  // libnativebridge APIs for which libdl_android has no corresponding APIs
+  virtual bool NativeBridgeInitialized() = 0;
+  virtual const char* NativeBridgeGetError() = 0;
+  virtual bool NativeBridgeIsPathSupported(const char*) = 0;
+  virtual bool NativeBridgeIsSupported(const char*) = 0;
+
+  // To mock "ClassLoader Object.getParent()"
+  virtual const char* JniObject_getParent(const char*) = 0;
+};
+
+// The mock does not actually create a namespace object. But simply casts the pointer to the
+// string for the namespace name as the handle to the namespace object.
+#define TO_ANDROID_NAMESPACE(str) \
+  reinterpret_cast<struct android_namespace_t*>(const_cast<char*>(str))
+
+#define TO_BRIDGED_NAMESPACE(str) \
+  reinterpret_cast<struct native_bridge_namespace_t*>(const_cast<char*>(str))
+
+#define TO_MOCK_NAMESPACE(ns) reinterpret_cast<Platform::mock_namespace_handle>(ns)
+
+// These represents built-in namespaces created by the linker according to ld.config.txt
+static std::unordered_map<std::string, Platform::mock_namespace_handle> namespaces = {
+#define NAMESPACE_ENTRY(ns) {ns, TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE(ns))}
+  NAMESPACE_ENTRY("com_android_i18n"),
+  NAMESPACE_ENTRY("com_android_neuralnetworks"),
+  NAMESPACE_ENTRY("com_android_art"),
+
+  // TODO(b/191644631) This can be removed when the test becomes more test-friendly.
+  // This is added so that the test can exercise the JNI lib related behavior.
+  NAMESPACE_ENTRY("com_android_conscrypt"),
+
+  NAMESPACE_ENTRY("default"),
+  NAMESPACE_ENTRY("sphal"),
+  NAMESPACE_ENTRY("system"),
+  NAMESPACE_ENTRY("vndk"),
+  NAMESPACE_ENTRY("vndk_product"),
+#undef NAMESPACE_ENTRY
+};
+
+// The actual gmock object
+class MockPlatform : public Platform {
+ public:
+  explicit MockPlatform(bool is_bridged) : is_bridged_(is_bridged) {
+    ON_CALL(*this, NativeBridgeIsSupported(_)).WillByDefault(Return(is_bridged_));
+    ON_CALL(*this, NativeBridgeIsPathSupported(_)).WillByDefault(Return(is_bridged_));
+    ON_CALL(*this, mock_get_exported_namespace(_, _))
+        .WillByDefault(testing::Invoke([](bool, const char* name) -> mock_namespace_handle {
+          if (namespaces.find(name) != namespaces.end()) {
+            return namespaces[name];
+          }
+          std::string msg = android::base::StringPrintf("(namespace %s not found)", name);
+          // The strdup'ed string will leak, but the test is already failing if we get here.
+          return TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE(strdup(msg.c_str())));
+        }));
+  }
+
+  // Mocking the common APIs
+  MOCK_METHOD3(mock_init_anonymous_namespace, bool(bool, const char*, const char*));
+  MOCK_METHOD7(mock_create_namespace,
+               mock_namespace_handle(bool, const char*, const char*, const char*, uint64_t,
+                                     const char*, mock_namespace_handle));
+  MOCK_METHOD4(mock_link_namespaces,
+               bool(bool, mock_namespace_handle, mock_namespace_handle, const char*));
+  MOCK_METHOD2(mock_get_exported_namespace, mock_namespace_handle(bool, const char*));
+  MOCK_METHOD4(mock_dlopen_ext, void*(bool, const char*, int, mock_namespace_handle));
+
+  // Mocking libnativebridge APIs
+  MOCK_METHOD0(NativeBridgeInitialized, bool());
+  MOCK_METHOD0(NativeBridgeGetError, const char*());
+  MOCK_METHOD1(NativeBridgeIsPathSupported, bool(const char*));
+  MOCK_METHOD1(NativeBridgeIsSupported, bool(const char*));
+
+  // Mocking "ClassLoader Object.getParent()"
+  MOCK_METHOD1(JniObject_getParent, const char*(const char*));
+
+ private:
+  bool is_bridged_;
+};
+
+static std::unique_ptr<MockPlatform> mock;
+
+// Provide C wrappers for the mock object. These symbols must be exported by ld
+// to be able to override the real symbols in the shared libs.
+extern "C" {
+
+// libdl_android APIs
+
+bool android_init_anonymous_namespace(const char* sonames, const char* search_path) {
+  return mock->mock_init_anonymous_namespace(false, sonames, search_path);
+}
+
+struct android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
+                                                     const char* default_library_path,
+                                                     uint64_t type,
+                                                     const char* permitted_when_isolated_path,
+                                                     struct android_namespace_t* parent) {
+  return TO_ANDROID_NAMESPACE(
+      mock->mock_create_namespace(false, name, ld_library_path, default_library_path, type,
+                                  permitted_when_isolated_path, TO_MOCK_NAMESPACE(parent)));
+}
+
+bool android_link_namespaces(struct android_namespace_t* from, struct android_namespace_t* to,
+                             const char* sonames) {
+  return mock->mock_link_namespaces(false, TO_MOCK_NAMESPACE(from), TO_MOCK_NAMESPACE(to), sonames);
+}
+
+struct android_namespace_t* android_get_exported_namespace(const char* name) {
+  return TO_ANDROID_NAMESPACE(mock->mock_get_exported_namespace(false, name));
+}
+
+void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* info) {
+  return mock->mock_dlopen_ext(false, filename, flags, TO_MOCK_NAMESPACE(info->library_namespace));
+}
+
+// libnativebridge APIs
+
+bool NativeBridgeIsSupported(const char* libpath) {
+  return mock->NativeBridgeIsSupported(libpath);
+}
+
+struct native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name) {
+  return TO_BRIDGED_NAMESPACE(mock->mock_get_exported_namespace(true, name));
+}
+
+struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
+    const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
+    const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent) {
+  return TO_BRIDGED_NAMESPACE(
+      mock->mock_create_namespace(true, name, ld_library_path, default_library_path, type,
+                                  permitted_when_isolated_path, TO_MOCK_NAMESPACE(parent)));
+}
+
+bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
+                                struct native_bridge_namespace_t* to, const char* sonames) {
+  return mock->mock_link_namespaces(true, TO_MOCK_NAMESPACE(from), TO_MOCK_NAMESPACE(to), sonames);
+}
+
+void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
+                                 struct native_bridge_namespace_t* ns) {
+  return mock->mock_dlopen_ext(true, libpath, flag, TO_MOCK_NAMESPACE(ns));
+}
+
+bool NativeBridgeInitialized() {
+  return mock->NativeBridgeInitialized();
+}
+
+bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
+                                        const char* anon_ns_library_path) {
+  return mock->mock_init_anonymous_namespace(true, public_ns_sonames, anon_ns_library_path);
+}
+
+const char* NativeBridgeGetError() {
+  return mock->NativeBridgeGetError();
+}
+
+bool NativeBridgeIsPathSupported(const char* path) {
+  return mock->NativeBridgeIsPathSupported(path);
+}
+
+}  // extern "C"
+
+// A very simple JNI mock.
+// jstring is a pointer to utf8 char array. We don't need utf16 char here.
+// jobject, jclass, and jmethodID are also a pointer to utf8 char array
+// Only a few JNI methods that are actually used in libnativeloader are mocked.
+JNINativeInterface* CreateJNINativeInterface() {
+  JNINativeInterface* inf = new JNINativeInterface();
+  memset(inf, 0, sizeof(JNINativeInterface));
+
+  inf->GetStringUTFChars = [](JNIEnv*, jstring s, jboolean*) -> const char* {
+    return reinterpret_cast<const char*>(s);
+  };
+
+  inf->ReleaseStringUTFChars = [](JNIEnv*, jstring, const char*) -> void { return; };
+
+  inf->NewStringUTF = [](JNIEnv*, const char* bytes) -> jstring {
+    return reinterpret_cast<jstring>(const_cast<char*>(bytes));
+  };
+
+  inf->FindClass = [](JNIEnv*, const char* name) -> jclass {
+    return reinterpret_cast<jclass>(const_cast<char*>(name));
+  };
+
+  inf->CallObjectMethodV = [](JNIEnv*, jobject obj, jmethodID mid, va_list) -> jobject {
+    if (strcmp("getParent", reinterpret_cast<const char*>(mid)) == 0) {
+      // JniObject_getParent can be a valid jobject or nullptr if there is
+      // no parent classloader.
+      const char* ret = mock->JniObject_getParent(reinterpret_cast<const char*>(obj));
+      return reinterpret_cast<jobject>(const_cast<char*>(ret));
+    }
+    return nullptr;
+  };
+
+  inf->GetMethodID = [](JNIEnv*, jclass, const char* name, const char*) -> jmethodID {
+    return reinterpret_cast<jmethodID>(const_cast<char*>(name));
+  };
+
+  inf->NewWeakGlobalRef = [](JNIEnv*, jobject obj) -> jobject { return obj; };
+
+  inf->IsSameObject = [](JNIEnv*, jobject a, jobject b) -> jboolean {
+    return strcmp(reinterpret_cast<const char*>(a), reinterpret_cast<const char*>(b)) == 0;
+  };
+
+  return inf;
+}
+
+}  // namespace nativeloader
+}  // namespace android
+
+#endif  // ART_LIBNATIVELOADER_NATIVE_LOADER_TEST_H_
diff --git a/libnativeloader/public_libraries.cpp b/libnativeloader/public_libraries.cpp
index a9d4e4d..827be5b 100644
--- a/libnativeloader/public_libraries.cpp
+++ b/libnativeloader/public_libraries.cpp
@@ -21,16 +21,18 @@
 #include <dirent.h>
 
 #include <algorithm>
+#include <map>
 #include <memory>
+#include <regex>
+#include <string>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
-#include <android-base/properties.h>
 #include <android-base/result.h>
 #include <android-base/strings.h>
 #include <log/log.h>
 
-#if defined(__ANDROID__)
+#if defined(ART_TARGET_ANDROID)
 #include <android/sysprop/VndkProperties.sysprop.h>
 #endif
 
@@ -42,6 +44,7 @@
 using android::base::Result;
 using internal::ConfigEntry;
 using internal::ParseConfig;
+using internal::ParseApexLibrariesConfig;
 using std::literals::string_literals::operator""s;
 
 namespace {
@@ -49,20 +52,11 @@
 constexpr const char* kDefaultPublicLibrariesFile = "/etc/public.libraries.txt";
 constexpr const char* kExtendedPublicLibrariesFilePrefix = "public.libraries-";
 constexpr const char* kExtendedPublicLibrariesFileSuffix = ".txt";
+constexpr const char* kApexLibrariesConfigFile = "/linkerconfig/apex.libraries.config.txt";
 constexpr const char* kVendorPublicLibrariesFile = "/vendor/etc/public.libraries.txt";
 constexpr const char* kLlndkLibrariesFile = "/apex/com.android.vndk.v{}/etc/llndk.libraries.{}.txt";
 constexpr const char* kVndkLibrariesFile = "/apex/com.android.vndk.v{}/etc/vndksp.libraries.{}.txt";
 
-const std::vector<const std::string> kArtApexPublicLibraries = {
-    "libicuuc.so",
-    "libicui18n.so",
-};
-
-constexpr const char* kArtApexLibPath = "/apex/com.android.art/" LIB;
-
-constexpr const char* kNeuralNetworksApexPublicLibrary = "libneuralnetworks.so";
-
-constexpr const char* kStatsdApexPublicLibrary = "libstats_jni.so";
 
 // TODO(b/130388701): do we need this?
 std::string root_dir() {
@@ -70,11 +64,6 @@
   return android_root_env != nullptr ? android_root_env : "/system";
 }
 
-bool debuggable() {
-  static bool debuggable = android::base::GetBoolProperty("ro.debuggable", false);
-  return debuggable;
-}
-
 std::string vndk_version_str(bool use_product_vndk) {
   if (use_product_vndk) {
     static std::string product_vndk_version = get_vndk_version(true);
@@ -85,16 +74,6 @@
   }
 }
 
-// For debuggable platform builds use ANDROID_ADDITIONAL_PUBLIC_LIBRARIES environment
-// variable to add libraries to the list. This is intended for platform tests only.
-std::string additional_public_libraries() {
-  if (debuggable()) {
-    const char* val = getenv("ANDROID_ADDITIONAL_PUBLIC_LIBRARIES");
-    return val ? val : "";
-  }
-  return "";
-}
-
 // insert vndk version in every {} placeholder
 void InsertVndkVersionStr(std::string* file_name, bool use_product_vndk) {
   CHECK(file_name != nullptr);
@@ -180,59 +159,22 @@
     return "";
   }
 
-  std::string additional_libs = additional_public_libraries();
-  if (!additional_libs.empty()) {
-    auto vec = base::Split(additional_libs, ":");
-    std::copy(vec.begin(), vec.end(), std::back_inserter(*sonames));
-  }
-
   // If this is for preloading libs, don't remove the libs from APEXes.
   if (for_preload) {
     return android::base::Join(*sonames, ':');
   }
 
-  // Remove the public libs in the art namespace.
-  // These libs are listed in public.android.txt, but we don't want the rest of android
-  // in default namespace to dlopen the libs.
-  // For example, libicuuc.so is exposed to classloader namespace from art namespace.
-  // Unfortunately, it does not have stable C symbols, and default namespace should only use
-  // stable symbols in libandroidicu.so. http://b/120786417
-  for (const std::string& lib_name : kArtApexPublicLibraries) {
-    std::string path(kArtApexLibPath);
-    path.append("/").append(lib_name);
-
-    struct stat s;
-    // Do nothing if the path in /apex does not exist.
-    // Runtime APEX must be mounted since libnativeloader is in the same APEX
-    if (stat(path.c_str(), &s) != 0) {
-      continue;
-    }
-
-    auto it = std::find(sonames->begin(), sonames->end(), lib_name);
-    if (it != sonames->end()) {
-      sonames->erase(it);
-    }
-  }
-
-  // Remove the public libs in the nnapi namespace.
-  auto it = std::find(sonames->begin(), sonames->end(), kNeuralNetworksApexPublicLibrary);
-  if (it != sonames->end()) {
-    sonames->erase(it);
+  // Remove the public libs provided by apexes because these libs are available
+  // from apex namespaces.
+  for (const auto& p : apex_public_libraries()) {
+    auto public_libs = base::Split(p.second, ":");
+    sonames->erase(std::remove_if(sonames->begin(), sonames->end(), [&public_libs](const std::string& v) {
+      return std::find(public_libs.begin(), public_libs.end(), v) != public_libs.end();
+    }), sonames->end());
   }
   return android::base::Join(*sonames, ':');
 }
 
-static std::string InitArtPublicLibraries() {
-  CHECK_GT((int)sizeof(kArtApexPublicLibraries), 0);
-  std::string list = android::base::Join(kArtApexPublicLibraries, ":");
-
-  std::string additional_libs = additional_public_libraries();
-  if (!additional_libs.empty()) {
-    list = list + ':' + additional_libs;
-  }
-  return list;
-}
-
 static std::string InitVendorPublicLibraries() {
   // This file is optional, quietly ignore if the file does not exist.
   auto sonames = ReadConfig(kVendorPublicLibrariesFile, always_true);
@@ -305,12 +247,44 @@
   return android::base::Join(*sonames, ':');
 }
 
-static std::string InitNeuralNetworksPublicLibraries() {
-  return kNeuralNetworksApexPublicLibrary;
+static std::map<std::string, std::string> InitApexLibraries(const std::string& tag) {
+  std::string file_content;
+  if (!base::ReadFileToString(kApexLibrariesConfigFile, &file_content)) {
+    // config is optional
+    return {};
+  }
+  auto config = ParseApexLibrariesConfig(file_content, tag);
+  if (!config.ok()) {
+    LOG_ALWAYS_FATAL("%s: %s", kApexLibrariesConfigFile, config.error().message().c_str());
+    return {};
+  }
+  return *config;
 }
 
-static std::string InitStatsdPublicLibraries() {
-  return kStatsdApexPublicLibrary;
+struct ApexLibrariesConfigLine {
+  std::string tag;
+  std::string apex_namespace;
+  std::string library_list;
+};
+
+const std::regex kApexNamespaceRegex("[0-9a-zA-Z_]+");
+const std::regex kLibraryListRegex("[0-9a-zA-Z.:@+_-]+");
+
+Result<ApexLibrariesConfigLine> ParseApexLibrariesConfigLine(const std::string& line) {
+  std::vector<std::string> tokens = base::Split(line, " ");
+  if (tokens.size() != 3) {
+    return Errorf("Malformed line \"{}\"", line);
+  }
+  if (tokens[0] != "jni" && tokens[0] != "public") {
+    return Errorf("Invalid tag \"{}\"", line);
+  }
+  if (!std::regex_match(tokens[1], kApexNamespaceRegex)) {
+    return Errorf("Invalid apex_namespace \"{}\"", line);
+  }
+  if (!std::regex_match(tokens[2], kLibraryListRegex)) {
+    return Errorf("Invalid library_list \"{}\"", line);
+  }
+  return ApexLibrariesConfigLine{std::move(tokens[0]), std::move(tokens[1]), std::move(tokens[2])};
 }
 
 }  // namespace
@@ -325,11 +299,6 @@
   return list;
 }
 
-const std::string& art_public_libraries() {
-  static std::string list = InitArtPublicLibraries();
-  return list;
-}
-
 const std::string& vendor_public_libraries() {
   static std::string list = InitVendorPublicLibraries();
   return list;
@@ -340,16 +309,6 @@
   return list;
 }
 
-const std::string& neuralnetworks_public_libraries() {
-  static std::string list = InitNeuralNetworksPublicLibraries();
-  return list;
-}
-
-const std::string& statsd_public_libraries() {
-  static std::string list = InitStatsdPublicLibraries();
-  return list;
-}
-
 const std::string& llndk_libraries_product() {
   static std::string list = InitLlndkLibrariesProduct();
   return list;
@@ -370,8 +329,18 @@
   return list;
 }
 
+const std::string& apex_jni_libraries(const std::string& apex_ns_name) {
+  static std::map<std::string, std::string> jni_libraries = InitApexLibraries("jni");
+  return jni_libraries[apex_ns_name];
+}
+
+const std::map<std::string, std::string>& apex_public_libraries() {
+  static std::map<std::string, std::string> public_libraries = InitApexLibraries("public");
+  return public_libraries;
+}
+
 bool is_product_vndk_version_defined() {
-#if defined(__ANDROID__)
+#if defined(ART_TARGET_ANDROID)
   return android::sysprop::VndkProperties::product_vndk_version().has_value();
 #else
   return false;
@@ -379,7 +348,7 @@
 }
 
 std::string get_vndk_version(bool is_product_vndk) {
-#if defined(__ANDROID__)
+#if defined(ART_TARGET_ANDROID)
   if (is_product_vndk) {
     return android::sysprop::VndkProperties::product_vndk_version().value_or("");
   }
@@ -447,6 +416,38 @@
   return sonames;
 }
 
+// Parses apex.libraries.config.txt file generated by linkerconfig which looks like
+//   system/linkerconfig/testdata/golden_output/stages/apex.libraries.config.txt
+// and returns mapping of <apex namespace> to <library list> which matches <tag>.
+//
+// The file is line-based and each line consists of "<tag> <apex namespace> <library list>".
+//
+// <tag> explains what <library list> is. (e.g "jni", "public")
+// <library list> is colon-separated list of library names. (e.g "libfoo.so:libbar.so")
+//
+// If <tag> is "jni", <library list> is the list of JNI libraries exposed by <apex namespace>.
+// If <tag> is "public", <library list> is the list of public libraries exposed by <apex namespace>.
+// Public libraries are the libs listed in /system/etc/public.libraries.txt.
+Result<std::map<std::string, std::string>> ParseApexLibrariesConfig(const std::string& file_content, const std::string& tag) {
+  std::map<std::string, std::string> entries;
+  std::vector<std::string> lines = base::Split(file_content, "\n");
+  for (auto& line : lines) {
+    auto trimmed_line = base::Trim(line);
+    if (trimmed_line[0] == '#' || trimmed_line.empty()) {
+      continue;
+    }
+    auto config_line = ParseApexLibrariesConfigLine(trimmed_line);
+    if (!config_line.ok()) {
+      return config_line.error();
+    }
+    if (config_line->tag != tag) {
+      continue;
+    }
+    entries[config_line->apex_namespace] = config_line->library_list;
+  }
+  return entries;
+}
+
 }  // namespace internal
 
 }  // namespace android::nativeloader
diff --git a/libnativeloader/public_libraries.h b/libnativeloader/public_libraries.h
index f086b3b..71c1b8f 100644
--- a/libnativeloader/public_libraries.h
+++ b/libnativeloader/public_libraries.h
@@ -18,6 +18,7 @@
 #define ART_LIBNATIVELOADER_PUBLIC_LIBRARIES_H_
 
 #include <algorithm>
+#include <map>
 #include <string>
 
 #include <android-base/result.h>
@@ -31,15 +32,19 @@
 // e.g., if it is a vendor app or not, different set of libraries are made available.
 const std::string& preloadable_public_libraries();
 const std::string& default_public_libraries();
-const std::string& art_public_libraries();
-const std::string& statsd_public_libraries();
 const std::string& vendor_public_libraries();
 const std::string& extended_public_libraries();
-const std::string& neuralnetworks_public_libraries();
 const std::string& llndk_libraries_product();
 const std::string& llndk_libraries_vendor();
 const std::string& vndksp_libraries_product();
 const std::string& vndksp_libraries_vendor();
+const std::string& apex_jni_libraries(const std::string& apex_name);
+
+// Returns the table of apexes and public libraries provided by the apexes.
+// For example, com_android_foo -> libfoo.so:libbar.so
+// Note that libfoo.so and libbar.so are listed in /system/etc/public.libraries.txt
+// but provided by com.android.foo APEX.
+const std::map<std::string, std::string>& apex_public_libraries();
 
 // Returns true if libnativeloader is running on devices and the device has
 // ro.product.vndk.version property. It returns false for host.
@@ -62,6 +67,11 @@
     const std::string& file_content,
     const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn);
 
+// Parses apex.libraries.config.txt file generated by linkerconfig
+// and returns mapping of <apex namespace> to <library list> which matches <tag>.
+Result<std::map<std::string, std::string>> ParseApexLibrariesConfig(
+    const std::string& file_content, const std::string& tag);
+
 }  // namespace internal
 
 }  // namespace android::nativeloader
diff --git a/libnativeloader/test/Android.bp b/libnativeloader/test/Android.bp
index 72e8c0f..fb9ae0d 100644
--- a/libnativeloader/test/Android.bp
+++ b/libnativeloader/test/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_library {
     name: "libfoo.oem1",
     srcs: ["test.cpp"],
@@ -69,17 +78,3 @@
         "libbase",
     ],
 }
-
-// Build the test for the C API.
-cc_test {
-    name: "libnativeloader-api-tests",
-    defaults: [
-        "art_defaults",
-        "art_test_defaults",
-    ],
-    test_per_src: true,
-    srcs: [
-        "api_test.c",
-    ],
-    header_libs: ["libnativeloader-headers"],
-}
diff --git a/libnativeloader/test/Android.mk b/libnativeloader/test/Android.mk
index 65e7b09..95fa68a 100644
--- a/libnativeloader/test/Android.mk
+++ b/libnativeloader/test/Android.mk
@@ -17,6 +17,9 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := public.libraries-oem1.txt
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 LOCAL_SRC_FILES:= $(LOCAL_MODULE)
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
@@ -24,6 +27,9 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := public.libraries-oem2.txt
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 LOCAL_SRC_FILES:= $(LOCAL_MODULE)
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
@@ -31,6 +37,9 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := public.libraries-product1.txt
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 LOCAL_SRC_FILES:= $(LOCAL_MODULE)
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)
@@ -44,6 +53,9 @@
 LOCAL_SDK_VERSION := current
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_MODULE_PATH := $(TARGET_OUT_APPS)
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 include $(BUILD_PACKAGE)
 
 include $(CLEAR_VARS)
@@ -54,4 +66,7 @@
 LOCAL_SDK_VERSION := current
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_APPS)
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 include $(BUILD_PACKAGE)
diff --git a/libnativeloader/test/api_test.c b/libnativeloader/test/api_test.c
deleted file mode 100644
index e7025fd..0000000
--- a/libnativeloader/test/api_test.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-
-/* 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 "nativeloader/native_loader.h"
-
-int main(int argc, char** argv) {
-  (void)argc;
-  (void)argv;
-  return 0;
-}
diff --git a/libprofile/Android.bp b/libprofile/Android.bp
index 367eefc..ecbcd0b 100644
--- a/libprofile/Android.bp
+++ b/libprofile/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "libprofile_defaults",
     defaults: ["art_defaults"],
@@ -27,13 +36,13 @@
             shared_libs: [
                 "libartpalette",
                 "libbase",
+                "libz",
             ],
             static_libs: [
                 // ZipArchive support, the order matters here to get all symbols.
                 "libziparchive",
-                "libz",
             ],
-            export_shared_lib_headers: ["libbase"],
+            export_shared_lib_headers: ["libbase"], // ART's macros.h depends on libbase's macros.h.
         },
         not_windows: {
             shared_libs: [
@@ -42,7 +51,7 @@
                 "libz",
                 "libbase",
             ],
-            export_shared_lib_headers: ["libbase"],
+            export_shared_lib_headers: ["libbase"], // ART's macros.h depends on libbase's macros.h.
         },
         windows: {
             cflags: ["-Wno-thread-safety"],
@@ -52,23 +61,19 @@
                 "libz",
                 "libbase",
             ],
-            export_static_lib_headers: ["libbase"],
+            export_static_lib_headers: ["libbase"], // ART's macros.h depends on libbase's macros.h.
         },
         darwin: {
             enabled: true,
         },
     },
     //generated_sources: ["art_libartbase_operator_srcs"],
-    cflags: ["-DBUILDING_LIBART=1"],
     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.
 }
 
 cc_defaults {
     name: "libprofile_static_base_defaults",
-    static_libs: [
+    whole_static_libs: [
         "libbase",
         "libz",
         "libziparchive",
@@ -82,7 +87,7 @@
         "libartbase_static_defaults",
         "libdexfile_static_defaults",
     ],
-    static_libs: ["libprofile"],
+    whole_static_libs: ["libprofile"],
 }
 
 cc_defaults {
@@ -92,7 +97,7 @@
         "libartbased_static_defaults",
         "libdexfiled_static_defaults",
     ],
-    static_libs: ["libprofiled"],
+    whole_static_libs: ["libprofiled"],
 }
 
 art_cc_library {
@@ -131,7 +136,7 @@
         },
     },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -169,25 +174,56 @@
     export_shared_lib_headers: ["libbase"],
     apex_available: [
         "com.android.art.debug",
+        // TODO(b/183882457): This lib doesn't go into com.android.art, but
+        // apex_available lists need to be the same for internal libs to avoid
+        // stubs, and libartd depends on this.
+        "com.android.art",
     ],
 }
 
 // For now many of these tests still use CommonRuntimeTest, almost universally because of
 // ScratchFile and related.
 // TODO: Remove CommonRuntimeTest dependency from these tests.
-art_cc_test {
-    name: "art_libprofile_tests",
-    defaults: [
-        "art_gtest_defaults",
+art_cc_defaults {
+    name: "art_libprofile_tests_defaults",
+    data: [
+        ":art-gtest-jars-ManyMethods",
+        ":art-gtest-jars-MultiDex",
+        ":art-gtest-jars-ProfileTestMultiDex",
     ],
     srcs: [
         "profile/profile_boot_info_test.cc",
         "profile/profile_compilation_info_test.cc",
     ],
     shared_libs: [
-        "libartbased",
-        "libdexfiled",
-        "libartbased",
         "libziparchive",
     ],
 }
+
+// Version of ART gtest `art_libprofile_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
+art_cc_test {
+    name: "art_libprofile_tests",
+    defaults: [
+        "art_gtest_defaults",
+        "art_libprofile_tests_defaults",
+    ],
+    shared_libs: [
+        "libartbased",
+        "libdexfiled",
+    ],
+}
+
+// Standalone version of ART gtest `art_libprofile_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_libprofile_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_libprofile_tests_defaults",
+    ],
+    shared_libs: [
+        "libartbase",
+        "libdexfile",
+    ],
+    test_config: "art_standalone_libprofile_tests.xml",
+}
diff --git a/libprofile/art_standalone_libprofile_tests.xml b/libprofile/art_standalone_libprofile_tests.xml
new file mode 100644
index 0000000..069f203
--- /dev/null
+++ b/libprofile/art_standalone_libprofile_tests.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs art_standalone_libprofile_tests.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art_standalone_libprofile_tests->/data/local/tmp/nativetest/art_standalone_libprofile_tests" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art-gtest-jars-ManyMethods.jar->/data/local/tmp/nativetest/art-gtest-jars-ManyMethods.jar" />
+        <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/nativetest/art-gtest-jars-MultiDex.jar" />
+        <option name="push" value="art-gtest-jars-ProfileTestMultiDex.jar->/data/local/tmp/nativetest/art-gtest-jars-ProfileTestMultiDex.jar" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/nativetest" />
+        <option name="module-name" value="art_standalone_libprofile_tests" />
+        <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+        <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/libprofile/profile/profile_compilation_info.cc b/libprofile/profile/profile_compilation_info.cc
index 24419ef..8267174 100644
--- a/libprofile/profile/profile_compilation_info.cc
+++ b/libprofile/profile/profile_compilation_info.cc
@@ -35,6 +35,7 @@
 #include "android-base/file.h"
 
 #include "base/arena_allocator.h"
+#include "base/bit_utils.h"
 #include "base/dumpable.h"
 #include "base/file_utils.h"
 #include "base/logging.h"  // For VLOG.
@@ -48,16 +49,15 @@
 #include "base/unix_file/fd_file.h"
 #include "base/utils.h"
 #include "base/zip_archive.h"
+#include "dex/descriptors_names.h"
 #include "dex/dex_file_loader.h"
 
 namespace art {
 
 const uint8_t ProfileCompilationInfo::kProfileMagic[] = { 'p', 'r', 'o', '\0' };
-// Last profile version: merge profiles directly from the file without creating
-// profile_compilation_info object. All the profile line headers are now placed together
-// before corresponding method_encodings and class_ids.
-const uint8_t ProfileCompilationInfo::kProfileVersion[] = { '0', '1', '0', '\0' };
-const uint8_t ProfileCompilationInfo::kProfileVersionForBootImage[] = { '0', '1', '2', '\0' };
+// Last profile version: New extensible profile format.
+const uint8_t ProfileCompilationInfo::kProfileVersion[] = { '0', '1', '5', '\0' };
+const uint8_t ProfileCompilationInfo::kProfileVersionForBootImage[] = { '0', '1', '6', '\0' };
 
 static_assert(sizeof(ProfileCompilationInfo::kProfileVersion) == 4,
               "Invalid profile version size");
@@ -77,7 +77,19 @@
 
 static constexpr char kSampleMetadataSeparator = ':';
 
-static constexpr uint16_t kMaxDexFileKeyLength = PATH_MAX;
+// Note: This used to be PATH_MAX (usually 4096) but that seems excessive
+// and we do not want to rely on that external constant anyway.
+static constexpr uint16_t kMaxDexFileKeyLength = 1024;
+
+// Extra descriptors are serialized with a `uint16_t` prefix. This defines the length limit.
+static constexpr size_t kMaxExtraDescriptorLength = std::numeric_limits<uint16_t>::max();
+
+// According to dex file specification, there can be more than 2^16 valid method indexes
+// but bytecode uses only 16 bits, so higher method indexes are not very useful (though
+// such methods could be reached through virtual or interface dispatch). Consequently,
+// dex files with more than 2^16 method indexes are not really used and the profile file
+// format does not support higher method indexes.
+static constexpr uint32_t kMaxSupportedMethodIndex = 0xffffu;
 
 // Debug flag to ignore checksums when testing if a method or a class is present in the profile.
 // Used to facilitate testing profile guided compilation across a large number of apps
@@ -104,11 +116,443 @@
   return kDebugIgnoreChecksum || dex_file_checksum == checksum;
 }
 
+namespace {
+
+// Deflate the input buffer `in_buffer`. It returns a buffer of
+// compressed data for the input buffer of `*compressed_data_size` size.
+std::unique_ptr<uint8_t[]> DeflateBuffer(ArrayRef<const uint8_t> in_buffer,
+                                         /*out*/ uint32_t* compressed_data_size) {
+  z_stream strm;
+  strm.zalloc = Z_NULL;
+  strm.zfree = Z_NULL;
+  strm.opaque = Z_NULL;
+  int init_ret = deflateInit(&strm, 1);
+  if (init_ret != Z_OK) {
+    return nullptr;
+  }
+
+  uint32_t out_size = dchecked_integral_cast<uint32_t>(deflateBound(&strm, in_buffer.size()));
+
+  std::unique_ptr<uint8_t[]> compressed_buffer(new uint8_t[out_size]);
+  strm.avail_in = in_buffer.size();
+  strm.next_in = const_cast<uint8_t*>(in_buffer.data());
+  strm.avail_out = out_size;
+  strm.next_out = &compressed_buffer[0];
+  int ret = deflate(&strm, Z_FINISH);
+  if (ret == Z_STREAM_ERROR) {
+    return nullptr;
+  }
+  *compressed_data_size = out_size - strm.avail_out;
+
+  int end_ret = deflateEnd(&strm);
+  if (end_ret != Z_OK) {
+    return nullptr;
+  }
+
+  return compressed_buffer;
+}
+
+// Inflate the data from `in_buffer` into `out_buffer`. The `out_buffer.size()`
+// is the expected output size of the buffer. It returns Z_STREAM_END on success.
+// On error, it returns Z_STREAM_ERROR if the compressed data is inconsistent
+// and Z_DATA_ERROR if the stream ended prematurely or the stream has extra data.
+int InflateBuffer(ArrayRef<const uint8_t> in_buffer, /*out*/ ArrayRef<uint8_t> out_buffer) {
+  /* allocate inflate state */
+  z_stream strm;
+  strm.zalloc = Z_NULL;
+  strm.zfree = Z_NULL;
+  strm.opaque = Z_NULL;
+  strm.avail_in = in_buffer.size();
+  strm.next_in = const_cast<uint8_t*>(in_buffer.data());
+  strm.avail_out = out_buffer.size();
+  strm.next_out = out_buffer.data();
+
+  int init_ret = inflateInit(&strm);
+  if (init_ret != Z_OK) {
+    return init_ret;
+  }
+
+  int ret = inflate(&strm, Z_NO_FLUSH);
+  if (strm.avail_in != 0 || strm.avail_out != 0) {
+    return Z_DATA_ERROR;
+  }
+
+  int end_ret = inflateEnd(&strm);
+  if (end_ret != Z_OK) {
+    return end_ret;
+  }
+
+  return ret;
+}
+
+}  // anonymous namespace
+
+enum class ProfileCompilationInfo::ProfileLoadStatus : uint32_t {
+  kSuccess,
+  kIOError,
+  kBadMagic,
+  kVersionMismatch,
+  kBadData,
+  kMergeError,  // Merging failed. There are too many extra descriptors
+                // or classes without TypeId referenced by a dex file.
+};
+
+enum class ProfileCompilationInfo::FileSectionType : uint32_t {
+  // The values of section enumerators and data format for individual sections
+  // must not be changed without changing the profile file version. New sections
+  // can be added at the end and they shall be ignored by old versions of ART.
+
+  // The list of the dex files included in the profile.
+  // There must be exactly one dex file section and it must be first.
+  kDexFiles = 0,
+
+  // Extra descriptors for referencing classes that do not have a `dex::TypeId`
+  // in the referencing dex file, such as classes from a different dex file
+  // (even outside of the dex files in the profile) or array classes that were
+  // used from other dex files or created through reflection.
+  kExtraDescriptors = 1,
+
+  // Classes included in the profile.
+  kClasses = 2,
+
+  // Methods included in the profile, their hotness flags and inline caches.
+  kMethods = 3,
+
+  // The number of known sections.
+  kNumberOfSections = 4
+};
+
+class ProfileCompilationInfo::FileSectionInfo {
+ public:
+  // Constructor for reading from a `ProfileSource`. Data shall be filled from the source.
+  FileSectionInfo() {}
+
+  // Constructor for writing to a file.
+  FileSectionInfo(FileSectionType type,
+                  uint32_t file_offset,
+                  uint32_t file_size,
+                  uint32_t inflated_size)
+      : type_(type),
+        file_offset_(file_offset),
+        file_size_(file_size),
+        inflated_size_(inflated_size) {}
+
+  void SetFileOffset(uint32_t file_offset) {
+    DCHECK_EQ(file_offset_, 0u);
+    DCHECK_NE(file_offset, 0u);
+    file_offset_ = file_offset;
+  }
+
+  FileSectionType GetType() const {
+    return type_;
+  }
+
+  uint32_t GetFileOffset() const {
+    return file_offset_;
+  }
+
+  uint32_t GetFileSize() const {
+    return file_size_;
+  }
+
+  uint32_t GetInflatedSize() const {
+    return inflated_size_;
+  }
+
+  uint32_t GetMemSize() const {
+    return inflated_size_ != 0u ? inflated_size_ : file_size_;
+  }
+
+ private:
+  FileSectionType type_;
+  uint32_t file_offset_;
+  uint32_t file_size_;
+  uint32_t inflated_size_;  // If 0, do not inflate and use data from file directly.
+};
+
+// The file header.
+class ProfileCompilationInfo::FileHeader {
+ public:
+  // Constructor for reading from a `ProfileSource`. Data shall be filled from the source.
+  FileHeader() {
+    DCHECK(!IsValid());
+  }
+
+  // Constructor for writing to a file.
+  FileHeader(const uint8_t* version, uint32_t file_section_count)
+      : file_section_count_(file_section_count) {
+    static_assert(sizeof(magic_) == sizeof(kProfileMagic));
+    static_assert(sizeof(version_) == sizeof(kProfileVersion));
+    static_assert(sizeof(version_) == sizeof(kProfileVersionForBootImage));
+    memcpy(magic_, kProfileMagic, sizeof(kProfileMagic));
+    memcpy(version_, version, sizeof(version_));
+    DCHECK_LE(file_section_count, kMaxFileSectionCount);
+    DCHECK(IsValid());
+  }
+
+  bool IsValid() const {
+    return memcmp(magic_, kProfileMagic, sizeof(kProfileMagic)) == 0 &&
+           (memcmp(version_, kProfileVersion, kProfileVersionSize) == 0 ||
+            memcmp(version_, kProfileVersionForBootImage, kProfileVersionSize) == 0) &&
+           file_section_count_ != 0u &&  // The dex files section is mandatory.
+           file_section_count_ <= kMaxFileSectionCount;
+  }
+
+  const uint8_t* GetVersion() const {
+    DCHECK(IsValid());
+    return version_;
+  }
+
+  ProfileLoadStatus InvalidHeaderMessage(/*out*/ std::string* error_msg) const;
+
+  uint32_t GetFileSectionCount() const {
+    DCHECK(IsValid());
+    return file_section_count_;
+  }
+
+ private:
+  // The upper bound for file section count is used to ensure that there
+  // shall be no arithmetic overflow when calculating size of the header
+  // with section information.
+  static const uint32_t kMaxFileSectionCount;
+
+  uint8_t magic_[4] = {0, 0, 0, 0};
+  uint8_t version_[4] = {0, 0, 0, 0};
+  uint32_t file_section_count_ = 0u;
+};
+
+const uint32_t ProfileCompilationInfo::FileHeader::kMaxFileSectionCount =
+    (std::numeric_limits<uint32_t>::max() - sizeof(FileHeader)) / sizeof(FileSectionInfo);
+
+ProfileCompilationInfo::ProfileLoadStatus
+ProfileCompilationInfo::FileHeader::InvalidHeaderMessage(/*out*/ std::string* error_msg) const {
+  if (memcmp(magic_, kProfileMagic, sizeof(kProfileMagic)) != 0) {
+    *error_msg = "Profile missing magic.";
+    return ProfileLoadStatus::kBadMagic;
+  }
+  if (memcmp(version_, kProfileVersion, sizeof(kProfileVersion)) != 0 &&
+      memcmp(version_, kProfileVersion, sizeof(kProfileVersionForBootImage)) != 0) {
+    *error_msg = "Profile version mismatch.";
+    return ProfileLoadStatus::kVersionMismatch;
+  }
+  if (file_section_count_ == 0u) {
+    *error_msg = "Missing mandatory dex files section.";
+    return ProfileLoadStatus::kBadData;
+  }
+  DCHECK_GT(file_section_count_, kMaxFileSectionCount);
+  *error_msg ="Too many sections.";
+  return ProfileLoadStatus::kBadData;
+}
+
+/**
+ * Encapsulate the source of profile data for loading.
+ * The source can be either a plain file or a zip file.
+ * For zip files, the profile entry will be extracted to
+ * the memory map.
+ */
+class ProfileCompilationInfo::ProfileSource {
+ public:
+  /**
+   * Create a profile source for the given fd. The ownership of the fd
+   * remains to the caller; as this class will not attempt to close it at any
+   * point.
+   */
+  static ProfileSource* Create(int32_t fd) {
+    DCHECK_GT(fd, -1);
+    return new ProfileSource(fd, MemMap::Invalid());
+  }
+
+  /**
+   * Create a profile source backed by a memory map. The map can be null in
+   * which case it will the treated as an empty source.
+   */
+  static ProfileSource* Create(MemMap&& mem_map) {
+    return new ProfileSource(/*fd*/ -1, std::move(mem_map));
+  }
+
+  // Seek to the given offset in the source.
+  bool Seek(off_t offset);
+
+  /**
+   * Read bytes from this source.
+   * Reading will advance the current source position so subsequent
+   * invocations will read from the las position.
+   */
+  ProfileLoadStatus Read(void* buffer,
+                         size_t byte_count,
+                         const std::string& debug_stage,
+                         std::string* error);
+
+  /** Return true if the source has 0 data. */
+  bool HasEmptyContent() const;
+
+ private:
+  ProfileSource(int32_t fd, MemMap&& mem_map)
+      : fd_(fd), mem_map_(std::move(mem_map)), mem_map_cur_(0) {}
+
+  bool IsMemMap() const {
+    return fd_ == -1;
+  }
+
+  int32_t fd_;  // The fd is not owned by this class.
+  MemMap mem_map_;
+  size_t mem_map_cur_;  // Current position in the map to read from.
+};
+
+// A helper structure to make sure we don't read past our buffers in the loops.
+// Also used for writing but the buffer should be pre-sized correctly for that, so we
+// DCHECK() we do not write beyond the end, rather than returning `false` on failure.
+class ProfileCompilationInfo::SafeBuffer {
+ public:
+  SafeBuffer()
+      : storage_(nullptr),
+        ptr_current_(nullptr),
+        ptr_end_(nullptr) {}
+
+  explicit SafeBuffer(size_t size)
+      : storage_(new uint8_t[size]),
+        ptr_current_(storage_.get()),
+        ptr_end_(ptr_current_ + size) {}
+
+  // Reads an uint value and advances the current pointer.
+  template <typename T>
+  bool ReadUintAndAdvance(/*out*/ T* value) {
+    static_assert(std::is_unsigned<T>::value, "Type is not unsigned");
+    if (sizeof(T) > GetAvailableBytes()) {
+      return false;
+    }
+    *value = 0;
+    for (size_t i = 0; i < sizeof(T); i++) {
+      *value += ptr_current_[i] << (i * kBitsPerByte);
+    }
+    ptr_current_ += sizeof(T);
+    return true;
+  }
+
+  // Reads a length-prefixed string as `std::string_view` and advances the current pointer.
+  // The length is `uint16_t`.
+  bool ReadStringAndAdvance(/*out*/ std::string_view* value) {
+    uint16_t length;
+    if (!ReadUintAndAdvance(&length)) {
+      return false;
+    }
+    if (length > GetAvailableBytes()) {
+      return false;
+    }
+    const void* null_char = memchr(GetCurrentPtr(), 0, length);
+    if (null_char != nullptr) {
+      // Embedded nulls are invalid.
+      return false;
+    }
+    *value = std::string_view(reinterpret_cast<const char*>(GetCurrentPtr()), length);
+    Advance(length);
+    return true;
+  }
+
+  // Compares the given data with the content at the current pointer.
+  // If the contents are equal it advances the current pointer by data_size.
+  bool CompareAndAdvance(const uint8_t* data, size_t data_size) {
+    if (data_size > GetAvailableBytes()) {
+      return false;
+    }
+    if (memcmp(ptr_current_, data, data_size) == 0) {
+      ptr_current_ += data_size;
+      return true;
+    }
+    return false;
+  }
+
+  void WriteAndAdvance(const void* data, size_t data_size) {
+    DCHECK_LE(data_size, GetAvailableBytes());
+    memcpy(ptr_current_, data, data_size);
+    ptr_current_ += data_size;
+  }
+
+  template <typename T>
+  void WriteUintAndAdvance(T value) {
+    static_assert(std::is_integral_v<T>);
+    WriteAndAdvance(&value, sizeof(value));
+  }
+
+  // Deflate a filled buffer. Replaces the internal buffer with a new one, also filled.
+  bool Deflate() {
+    DCHECK_EQ(GetAvailableBytes(), 0u);
+    DCHECK_NE(Size(), 0u);
+    ArrayRef<const uint8_t> in_buffer(Get(), Size());
+    uint32_t output_size = 0;
+    std::unique_ptr<uint8_t[]> compressed_buffer = DeflateBuffer(in_buffer, &output_size);
+    if (compressed_buffer == nullptr) {
+      return false;
+    }
+    storage_ = std::move(compressed_buffer);
+    ptr_current_ = storage_.get() + output_size;
+    ptr_end_ = ptr_current_;
+    return true;
+  }
+
+  // Inflate an unread buffer. Replaces the internal buffer with a new one, also unread.
+  bool Inflate(size_t uncompressed_data_size) {
+    DCHECK(ptr_current_ == storage_.get());
+    DCHECK_NE(Size(), 0u);
+    ArrayRef<const uint8_t> in_buffer(Get(), Size());
+    SafeBuffer uncompressed_buffer(uncompressed_data_size);
+    ArrayRef<uint8_t> out_buffer(uncompressed_buffer.Get(), uncompressed_data_size);
+    int ret = InflateBuffer(in_buffer, out_buffer);
+    if (ret != Z_STREAM_END) {
+      return false;
+    }
+    Swap(uncompressed_buffer);
+    DCHECK(ptr_current_ == storage_.get());
+    return true;
+  }
+
+  // Advances current pointer by data_size.
+  void Advance(size_t data_size) {
+    DCHECK_LE(data_size, GetAvailableBytes());
+    ptr_current_ += data_size;
+  }
+
+  // Returns the count of unread bytes.
+  size_t GetAvailableBytes() const {
+    DCHECK_LE(static_cast<void*>(ptr_current_), static_cast<void*>(ptr_end_));
+    return (ptr_end_ - ptr_current_) * sizeof(*ptr_current_);
+  }
+
+  // Returns the current pointer.
+  uint8_t* GetCurrentPtr() {
+    return ptr_current_;
+  }
+
+  // Get the underlying raw buffer.
+  uint8_t* Get() {
+    return storage_.get();
+  }
+
+  // Get the size of the raw buffer.
+  size_t Size() const {
+    return ptr_end_ - storage_.get();
+  }
+
+  void Swap(SafeBuffer& other) {
+    std::swap(storage_, other.storage_);
+    std::swap(ptr_current_, other.ptr_current_);
+    std::swap(ptr_end_, other.ptr_end_);
+  }
+
+ private:
+  std::unique_ptr<uint8_t[]> storage_;
+  uint8_t* ptr_current_;
+  uint8_t* ptr_end_;
+};
+
 ProfileCompilationInfo::ProfileCompilationInfo(ArenaPool* custom_arena_pool, bool for_boot_image)
     : default_arena_pool_(),
       allocator_(custom_arena_pool),
       info_(allocator_.Adapter(kArenaAllocProfile)),
-      profile_key_map_(std::less<const std::string>(), allocator_.Adapter(kArenaAllocProfile)) {
+      profile_key_map_(std::less<const std::string_view>(), allocator_.Adapter(kArenaAllocProfile)),
+      extra_descriptors_(),
+      extra_descriptors_indexes_(ExtraDescriptorHash(&extra_descriptors_),
+                                 ExtraDescriptorEquals(&extra_descriptors_)) {
   memcpy(version_,
          for_boot_image ? kProfileVersionForBootImage : kProfileVersion,
          kProfileVersionSize);
@@ -125,11 +569,9 @@
 
 ProfileCompilationInfo::~ProfileCompilationInfo() {
   VLOG(profiler) << Dumpable<MemStats>(allocator_.GetMemStats());
-  ClearData();
 }
 
-void ProfileCompilationInfo::DexPcData::AddClass(uint16_t dex_profile_idx,
-                                                 const dex::TypeIndex& type_idx) {
+void ProfileCompilationInfo::DexPcData::AddClass(const dex::TypeIndex& type_idx) {
   if (is_megamorphic || is_missing_types) {
     return;
   }
@@ -138,9 +580,8 @@
   // element. We do this because emplace() allocates the node before doing the
   // lookup and if it then finds an identical element, it shall deallocate the
   // node. For Arena allocations, that's essentially a leak.
-  ClassReference ref(dex_profile_idx, type_idx);
-  auto it = classes.find(ref);
-  if (it != classes.end()) {
+  auto lb = classes.lower_bound(type_idx);
+  if (lb != classes.end() && *lb == type_idx) {
     // The type index exists.
     return;
   }
@@ -153,7 +594,7 @@
   }
 
   // The type does not exist and the inline cache will not be megamorphic.
-  classes.insert(ref);
+  classes.emplace_hint(lb, type_idx);
 }
 
 // Transform the actual dex location into a key used to index the dex file in the profile.
@@ -171,7 +612,8 @@
 // Note: this is OK because we don't store profiles of different apps into the same file.
 // Apps with split apks don't cause trouble because each split has a different name and will not
 // collide with other entries.
-std::string ProfileCompilationInfo::GetProfileDexFileBaseKey(const std::string& dex_location) {
+std::string_view ProfileCompilationInfo::GetProfileDexFileBaseKeyView(
+    std::string_view dex_location) {
   DCHECK(!dex_location.empty());
   size_t last_sep_index = dex_location.find_last_of('/');
   if (last_sep_index == std::string::npos) {
@@ -182,12 +624,23 @@
   }
 }
 
-std::string ProfileCompilationInfo::GetBaseKeyFromAugmentedKey(
-    const std::string& profile_key) {
+std::string ProfileCompilationInfo::GetProfileDexFileBaseKey(const std::string& dex_location) {
+  // Note: Conversions between std::string and std::string_view.
+  return std::string(GetProfileDexFileBaseKeyView(dex_location));
+}
+
+std::string_view ProfileCompilationInfo::GetBaseKeyViewFromAugmentedKey(
+    std::string_view profile_key) {
   size_t pos = profile_key.rfind(kSampleMetadataSeparator);
   return (pos == std::string::npos) ? profile_key : profile_key.substr(0, pos);
 }
 
+std::string ProfileCompilationInfo::GetBaseKeyFromAugmentedKey(
+    const std::string& profile_key) {
+  // Note: Conversions between std::string and std::string_view.
+  return std::string(GetBaseKeyViewFromAugmentedKey(profile_key));
+}
+
 std::string ProfileCompilationInfo::MigrateAnnotationInfo(
     const std::string& base_key,
     const std::string& augmented_key) {
@@ -216,6 +669,62 @@
   return true;
 }
 
+dex::TypeIndex ProfileCompilationInfo::FindOrCreateTypeIndex(const DexFile& dex_file,
+                                                             TypeReference class_ref) {
+  DCHECK(class_ref.dex_file != nullptr);
+  DCHECK_LT(class_ref.TypeIndex().index_, class_ref.dex_file->NumTypeIds());
+  if (class_ref.dex_file == &dex_file) {
+    // We can use the type index from the `class_ref` as it's a valid index in the `dex_file`.
+    return class_ref.TypeIndex();
+  }
+  // Try to find a `TypeId` in the method's dex file.
+  const char* descriptor = class_ref.dex_file->StringByTypeIdx(class_ref.TypeIndex());
+  return FindOrCreateTypeIndex(dex_file, descriptor);
+}
+
+dex::TypeIndex ProfileCompilationInfo::FindOrCreateTypeIndex(const DexFile& dex_file,
+                                                             const char* descriptor) {
+  const dex::TypeId* type_id = dex_file.FindTypeId(descriptor);
+  if (type_id != nullptr) {
+    return dex_file.GetIndexForTypeId(*type_id);
+  }
+  // Try to find an existing extra descriptor.
+  uint32_t num_type_ids = dex_file.NumTypeIds();
+  uint32_t max_artificial_ids = DexFile::kDexNoIndex16 - num_type_ids;
+  std::string_view descriptor_view(descriptor);
+  // Check descriptor length for "extra descriptor". We are using `uint16_t` as prefix.
+  if (UNLIKELY(descriptor_view.size() > kMaxExtraDescriptorLength)) {
+    return dex::TypeIndex();  // Invalid.
+  }
+  auto it = extra_descriptors_indexes_.find(descriptor_view);
+  if (it != extra_descriptors_indexes_.end()) {
+    return (*it < max_artificial_ids) ? dex::TypeIndex(num_type_ids + *it) : dex::TypeIndex();
+  }
+  // Check if inserting the extra descriptor yields a valid artificial type index.
+  if (UNLIKELY(extra_descriptors_.size() >= max_artificial_ids)) {
+    return dex::TypeIndex();  // Invalid.
+  }
+  // Add the descriptor to extra descriptors and return the artificial type index.
+  ExtraDescriptorIndex new_extra_descriptor_index = AddExtraDescriptor(descriptor_view);
+  DCHECK_LT(new_extra_descriptor_index, max_artificial_ids);
+  return dex::TypeIndex(num_type_ids + new_extra_descriptor_index);
+}
+
+bool ProfileCompilationInfo::AddClass(const DexFile& dex_file,
+                                      const char* descriptor,
+                                      const ProfileSampleAnnotation& annotation) {
+  DexFileData* const data = GetOrAddDexFileData(&dex_file, annotation);
+  if (data == nullptr) {  // checksum mismatch
+    return false;
+  }
+  dex::TypeIndex type_index = FindOrCreateTypeIndex(dex_file, descriptor);
+  if (!type_index.IsValid()) {
+    return false;
+  }
+  data->class_set.insert(type_index);
+  return true;
+}
+
 bool ProfileCompilationInfo::MergeWith(const std::string& filename) {
   std::string error;
 #ifdef _WIN32
@@ -234,7 +743,7 @@
   int fd = profile_file->Fd();
 
   ProfileLoadStatus status = LoadInternal(fd, &error);
-  if (status == kProfileLoadSuccess) {
+  if (status == ProfileLoadStatus::kSuccess) {
     return true;
   }
 
@@ -269,12 +778,14 @@
   int fd = profile_file->Fd();
 
   ProfileLoadStatus status = LoadInternal(fd, &error);
-  if (status == kProfileLoadSuccess) {
+  if (status == ProfileLoadStatus::kSuccess) {
     return true;
   }
 
   if (clear_if_invalid &&
-      ((status == kProfileLoadVersionMismatch) || (status == kProfileLoadBadData))) {
+      ((status == ProfileLoadStatus::kBadMagic) ||
+       (status == ProfileLoadStatus::kVersionMismatch) ||
+       (status == ProfileLoadStatus::kBadData))) {
     LOG(WARNING) << "Clearing bad or obsolete profile data from file "
                  << filename << ": " << error;
     if (profile_file->ClearContent()) {
@@ -335,305 +846,295 @@
 }
 
 // Returns true if all the bytes were successfully written to the file descriptor.
-static bool WriteBuffer(int fd, const uint8_t* buffer, size_t byte_count) {
+static bool WriteBuffer(int fd, const void* buffer, size_t byte_count) {
   while (byte_count > 0) {
     int bytes_written = TEMP_FAILURE_RETRY(write(fd, buffer, byte_count));
     if (bytes_written == -1) {
       return false;
     }
     byte_count -= bytes_written;  // Reduce the number of remaining bytes.
-    buffer += bytes_written;  // Move the buffer forward.
+    reinterpret_cast<const uint8_t*&>(buffer) += bytes_written;  // Move the buffer forward.
   }
   return true;
 }
 
-// Add the string bytes to the buffer.
-static void AddStringToBuffer(std::vector<uint8_t>* buffer, const std::string& value) {
-  buffer->insert(buffer->end(), value.begin(), value.end());
-}
-
-// Insert each byte, from low to high into the buffer.
-template <typename T>
-static void AddUintToBuffer(std::vector<uint8_t>* buffer, T value) {
-  for (size_t i = 0; i < sizeof(T); i++) {
-    buffer->push_back((value >> (i * kBitsPerByte)) & 0xff);
-  }
-}
-
-static constexpr size_t kLineHeaderSize =
-    2 * sizeof(uint16_t) +  // class_set.size + dex_location.size
-    3 * sizeof(uint32_t);   // method_map.size + checksum + num_method_ids
-
 /**
  * Serialization format:
- * [profile_header, zipped[[profile_line_header1, profile_line_header2...],[profile_line_data1,
- *    profile_line_data2...]]
- * profile_header:
- *   magic,version,number_of_dex_files,uncompressed_size_of_zipped_data,compressed_data_size
- * profile_line_header:
- *   profile_key,number_of_classes,methods_region_size,dex_location_checksum,num_method_ids
- * profile_line_data:
- *   method_encoding_1,method_encoding_2...,class_id1,class_id2...,method_flags bitmap,
- * The method_encoding is:
- *    method_id,number_of_inline_caches,inline_cache1,inline_cache2...
- * The inline_cache is:
- *    dex_pc,[M|dex_map_size], dex_profile_index,class_id1,class_id2...,dex_profile_index2,...
- *    dex_map_size is the number of dex_indeces that follows.
- *       Classes are grouped per their dex files and the line
- *       `dex_profile_index,class_id1,class_id2...,dex_profile_index2,...` encodes the
- *       mapping from `dex_profile_index` to the set of classes `class_id1,class_id2...`
- *    M stands for megamorphic or missing types and it's encoded as either
- *    the byte kIsMegamorphicEncoding or kIsMissingTypesEncoding.
- *    When present, there will be no class ids following.
+ *
+ * The file starts with a header and section information:
+ *   FileHeader
+ *   FileSectionInfo[]
+ * The first FileSectionInfo must be for the DexFiles section.
+ *
+ * The rest of the file is allowed to contain different sections in any order,
+ * at arbitrary offsets, with any gaps betweeen them and each section can be
+ * either plaintext or separately zipped. However, we're writing sections
+ * without any gaps with the following order and compression:
+ *   DexFiles - mandatory, plaintext
+ *   ExtraDescriptors - optional, zipped
+ *   Classes - optional, zipped
+ *   Methods - optional, zipped
+ *
+ * DexFiles:
+ *    number_of_dex_files
+ *    (checksum,num_type_ids,num_method_ids,profile_key)[number_of_dex_files]
+ * where `profile_key` is a length-prefixed string, the length is `uint16_t`.
+ *
+ * ExtraDescriptors:
+ *    number_of_extra_descriptors
+ *    (extra_descriptor)[number_of_extra_descriptors]
+ * where `extra_descriptor` is a length-prefixed string, the length is `uint16_t`.
+ *
+ * Classes contains records for any number of dex files, each consisting of:
+ *    profile_index  // Index of the dex file in DexFiles section.
+ *    number_of_classes
+ *    type_index_diff[number_of_classes]
+ * where instead of storing plain sorted type indexes, we store their differences
+ * as smaller numbers are likely to compress better.
+ *
+ * Methods contains records for any number of dex files, each consisting of:
+ *    profile_index  // Index of the dex file in DexFiles section.
+ *    following_data_size  // For easy skipping of remaining data when dex file is filtered out.
+ *    method_flags
+ *    bitmap_data
+ *    method_encoding[]  // Until the size indicated by `following_data_size`.
+ * where `method_flags` is a union of flags recorded for methods in the referenced dex file,
+ * `bitmap_data` contains `num_method_ids` bits for each bit set in `method_flags` other
+ * than "hot" (the size of `bitmap_data` is rounded up to whole bytes) and `method_encoding[]`
+ * contains data for hot methods. The `method_encoding` is:
+ *    method_index_diff
+ *    number_of_inline_caches
+ *    inline_cache_encoding[number_of_inline_caches]
+ * where differences in method indexes are used for better compression,
+ * and the `inline_cache_encoding` is
+ *    dex_pc
+ *    (M|dex_map_size)
+ *    type_index_diff[dex_map_size]
+ * where `M` stands for special encodings indicating missing types (kIsMissingTypesEncoding)
+ * or memamorphic call (kIsMegamorphicEncoding) which both imply `dex_map_size == 0`.
  **/
 bool ProfileCompilationInfo::Save(int fd) {
   uint64_t start = NanoTime();
   ScopedTrace trace(__PRETTY_FUNCTION__);
   DCHECK_GE(fd, 0);
 
-  // Use a vector wrapper to avoid keeping track of offsets when we add elements.
-  std::vector<uint8_t> buffer;
-  if (!WriteBuffer(fd, kProfileMagic, sizeof(kProfileMagic))) {
-    return false;
+  // Collect uncompressed section sizes.
+  // Use `uint64_t` and assume this cannot overflow as we would have run out of memory.
+  uint64_t extra_descriptors_section_size = 0u;
+  if (!extra_descriptors_.empty()) {
+    extra_descriptors_section_size += sizeof(uint16_t);  // Number of descriptors.
+    for (const std::string& descriptor : extra_descriptors_) {
+      // Length-prefixed string, the length is `uint16_t`.
+      extra_descriptors_section_size += sizeof(uint16_t) + descriptor.size();
+    }
   }
-  if (!WriteBuffer(fd, version_, sizeof(version_))) {
-    return false;
-  }
-
+  uint64_t dex_files_section_size = sizeof(ProfileIndexType);  // Number of dex files.
+  uint64_t classes_section_size = 0u;
+  uint64_t methods_section_size = 0u;
   DCHECK_LE(info_.size(), MaxProfileIndex());
-  WriteProfileIndex(&buffer, static_cast<ProfileIndexType>(info_.size()));
-
-  uint32_t required_capacity = 0;
-  for (const DexFileData* dex_data_ptr : info_) {
-    const DexFileData& dex_data = *dex_data_ptr;
-    uint32_t methods_region_size = GetMethodsRegionSize(dex_data);
-    required_capacity += kLineHeaderSize +
-        dex_data.profile_key.size() +
-        sizeof(uint16_t) * dex_data.class_set.size() +
-        methods_region_size +
-        dex_data.bitmap_storage.size();
-  }
-  // Allow large profiles for non target builds for the case where we are merging many profiles
-  // to generate a boot image profile.
-  VLOG(profiler) << "Required capacity: " << required_capacity << " bytes.";
-  if (required_capacity > GetSizeErrorThresholdBytes()) {
-    LOG(ERROR) << "Profile data size exceeds "
-               << GetSizeErrorThresholdBytes()
-               << " bytes. Profile will not be written to disk."
-               << " It requires " << required_capacity << " bytes.";
-    return false;
-  }
-  AddUintToBuffer(&buffer, required_capacity);
-  if (!WriteBuffer(fd, buffer.data(), buffer.size())) {
-    return false;
-  }
-  // Make sure that the buffer has enough capacity to avoid repeated resizings
-  // while we add data.
-  buffer.reserve(required_capacity);
-  buffer.clear();
-
-  // Dex files must be written in the order of their profile index. This
-  // avoids writing the index in the output file and simplifies the parsing logic.
-  // Write profile line headers.
-  for (const DexFileData* dex_data_ptr : info_) {
-    const DexFileData& dex_data = *dex_data_ptr;
-
-    if (dex_data.profile_key.size() >= kMaxDexFileKeyLength) {
+  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
+    if (dex_data->profile_key.size() > kMaxDexFileKeyLength) {
       LOG(WARNING) << "DexFileKey exceeds allocated limit";
       return false;
     }
-
-    uint32_t methods_region_size = GetMethodsRegionSize(dex_data);
-
-    DCHECK_LE(dex_data.profile_key.size(), std::numeric_limits<uint16_t>::max());
-    DCHECK_LE(dex_data.class_set.size(), std::numeric_limits<uint16_t>::max());
-    // Write profile line header.
-    AddUintToBuffer(&buffer, static_cast<uint16_t>(dex_data.profile_key.size()));
-    AddUintToBuffer(&buffer, static_cast<uint16_t>(dex_data.class_set.size()));
-    AddUintToBuffer(&buffer, methods_region_size);  // uint32_t
-    AddUintToBuffer(&buffer, dex_data.checksum);  // uint32_t
-    AddUintToBuffer(&buffer, dex_data.num_method_ids);  // uint32_t
-
-    AddStringToBuffer(&buffer, dex_data.profile_key);
+    dex_files_section_size +=
+        3 * sizeof(uint32_t) +  // Checksum, num_type_ids, num_method_ids.
+        // Length-prefixed string, the length is `uint16_t`.
+        sizeof(uint16_t) + dex_data->profile_key.size();
+    classes_section_size += dex_data->ClassesDataSize();
+    methods_section_size += dex_data->MethodsDataSize();
   }
 
-  for (const DexFileData* dex_data_ptr : info_) {
-    const DexFileData& dex_data = *dex_data_ptr;
+  const uint32_t file_section_count =
+      /* dex files */ 1u +
+      /* extra descriptors */ (extra_descriptors_section_size != 0u ? 1u : 0u) +
+      /* classes */ (classes_section_size != 0u ? 1u : 0u) +
+      /* methods */ (methods_section_size != 0u ? 1u : 0u);
+  uint64_t header_and_infos_size =
+      sizeof(FileHeader) + file_section_count * sizeof(FileSectionInfo);
 
-    // Note that we allow dex files without any methods or classes, so that
-    // inline caches can refer valid dex files.
-
-    uint16_t last_method_index = 0;
-    for (const auto& method_it : dex_data.method_map) {
-      // Store the difference between the method indices. The SafeMap is ordered by
-      // method_id, so the difference will always be non negative.
-      DCHECK_GE(method_it.first, last_method_index);
-      uint16_t diff_with_last_method_index = method_it.first - last_method_index;
-      last_method_index = method_it.first;
-      AddUintToBuffer(&buffer, diff_with_last_method_index);
-      AddInlineCacheToBuffer(&buffer, method_it.second);
-    }
-
-    uint16_t last_class_index = 0;
-    for (const auto& class_id : dex_data.class_set) {
-      // Store the difference between the class indices. The set is ordered by
-      // class_id, so the difference will always be non negative.
-      DCHECK_GE(class_id.index_, last_class_index);
-      uint16_t diff_with_last_class_index = class_id.index_ - last_class_index;
-      last_class_index = class_id.index_;
-      AddUintToBuffer(&buffer, diff_with_last_class_index);
-    }
-
-    buffer.insert(buffer.end(),
-                  dex_data.bitmap_storage.begin(),
-                  dex_data.bitmap_storage.end());
+  // Check size limit. Allow large profiles for non target builds for the case
+  // where we are merging many profiles to generate a boot image profile.
+  uint64_t total_uncompressed_size =
+      header_and_infos_size +
+      dex_files_section_size +
+      extra_descriptors_section_size +
+      classes_section_size +
+      methods_section_size;
+  VLOG(profiler) << "Required capacity: " << total_uncompressed_size << " bytes.";
+  if (total_uncompressed_size > GetSizeErrorThresholdBytes()) {
+    LOG(ERROR) << "Profile data size exceeds "
+               << GetSizeErrorThresholdBytes()
+               << " bytes. Profile will not be written to disk."
+               << " It requires " << total_uncompressed_size << " bytes.";
+    return false;
   }
 
-  uint32_t output_size = 0;
-  std::unique_ptr<uint8_t[]> compressed_buffer = DeflateBuffer(buffer.data(),
-                                                               required_capacity,
-                                                               &output_size);
+  // Start with an invalid file header and section infos.
+  DCHECK_EQ(lseek(fd, 0, SEEK_CUR), 0);
+  constexpr uint32_t kMaxNumberOfSections = enum_cast<uint32_t>(FileSectionType::kNumberOfSections);
+  constexpr uint64_t kMaxHeaderAndInfosSize =
+      sizeof(FileHeader) + kMaxNumberOfSections * sizeof(FileSectionInfo);
+  DCHECK_LE(header_and_infos_size, kMaxHeaderAndInfosSize);
+  std::array<uint8_t, kMaxHeaderAndInfosSize> placeholder;
+  memset(placeholder.data(), 0, header_and_infos_size);
+  if (!WriteBuffer(fd, placeholder.data(), header_and_infos_size)) {
+    return false;
+  }
 
-  if (output_size > GetSizeWarningThresholdBytes()) {
+  std::array<FileSectionInfo, kMaxNumberOfSections> section_infos;
+  size_t section_index = 0u;
+  uint32_t file_offset = header_and_infos_size;
+  auto add_section_info = [&](FileSectionType type, uint32_t file_size, uint32_t inflated_size) {
+    DCHECK_LT(section_index, section_infos.size());
+    section_infos[section_index] = FileSectionInfo(type, file_offset, file_size, inflated_size);
+    file_offset += file_size;
+    section_index += 1u;
+  };
+
+  // Write the dex files section.
+  {
+    SafeBuffer buffer(dex_files_section_size);
+    buffer.WriteUintAndAdvance(dchecked_integral_cast<ProfileIndexType>(info_.size()));
+    for (const std::unique_ptr<DexFileData>& dex_data : info_) {
+      buffer.WriteUintAndAdvance(dex_data->checksum);
+      buffer.WriteUintAndAdvance(dex_data->num_type_ids);
+      buffer.WriteUintAndAdvance(dex_data->num_method_ids);
+      buffer.WriteUintAndAdvance(dchecked_integral_cast<uint16_t>(dex_data->profile_key.size()));
+      buffer.WriteAndAdvance(dex_data->profile_key.c_str(), dex_data->profile_key.size());
+    }
+    DCHECK_EQ(buffer.GetAvailableBytes(), 0u);
+    // Write the dex files section uncompressed.
+    if (!WriteBuffer(fd, buffer.Get(), dex_files_section_size)) {
+      return false;
+    }
+    add_section_info(FileSectionType::kDexFiles, dex_files_section_size, /*inflated_size=*/ 0u);
+  }
+
+  // Write the extra descriptors section.
+  if (extra_descriptors_section_size != 0u) {
+    SafeBuffer buffer(extra_descriptors_section_size);
+    buffer.WriteUintAndAdvance(dchecked_integral_cast<uint16_t>(extra_descriptors_.size()));
+    for (const std::string& descriptor : extra_descriptors_) {
+      buffer.WriteUintAndAdvance(dchecked_integral_cast<uint16_t>(descriptor.size()));
+      buffer.WriteAndAdvance(descriptor.c_str(), descriptor.size());
+    }
+    if (!buffer.Deflate()) {
+      return false;
+    }
+    if (!WriteBuffer(fd, buffer.Get(), buffer.Size())) {
+      return false;
+    }
+    add_section_info(
+        FileSectionType::kExtraDescriptors, buffer.Size(), extra_descriptors_section_size);
+  }
+
+  // Write the classes section.
+  if (classes_section_size != 0u) {
+    SafeBuffer buffer(classes_section_size);
+    for (const std::unique_ptr<DexFileData>& dex_data : info_) {
+      dex_data->WriteClasses(buffer);
+    }
+    if (!buffer.Deflate()) {
+      return false;
+    }
+    if (!WriteBuffer(fd, buffer.Get(), buffer.Size())) {
+      return false;
+    }
+    add_section_info(FileSectionType::kClasses, buffer.Size(), classes_section_size);
+  }
+
+  // Write the methods section.
+  if (methods_section_size != 0u) {
+    SafeBuffer buffer(methods_section_size);
+    for (const std::unique_ptr<DexFileData>& dex_data : info_) {
+      dex_data->WriteMethods(buffer);
+    }
+    if (!buffer.Deflate()) {
+      return false;
+    }
+    if (!WriteBuffer(fd, buffer.Get(), buffer.Size())) {
+      return false;
+    }
+    add_section_info(FileSectionType::kMethods, buffer.Size(), methods_section_size);
+  }
+
+  if (file_offset > GetSizeWarningThresholdBytes()) {
     LOG(WARNING) << "Profile data size exceeds "
         << GetSizeWarningThresholdBytes()
-        << " It has " << output_size << " bytes";
+        << " It has " << file_offset << " bytes";
   }
 
-  buffer.clear();
-  AddUintToBuffer(&buffer, output_size);
+  // Write section infos.
+  if (lseek64(fd, sizeof(FileHeader), SEEK_SET) != sizeof(FileHeader)) {
+    return false;
+  }
+  SafeBuffer section_infos_buffer(section_index * 4u * sizeof(uint32_t));
+  for (size_t i = 0; i != section_index; ++i) {
+    const FileSectionInfo& info = section_infos[i];
+    section_infos_buffer.WriteUintAndAdvance(enum_cast<uint32_t>(info.GetType()));
+    section_infos_buffer.WriteUintAndAdvance(info.GetFileOffset());
+    section_infos_buffer.WriteUintAndAdvance(info.GetFileSize());
+    section_infos_buffer.WriteUintAndAdvance(info.GetInflatedSize());
+  }
+  DCHECK_EQ(section_infos_buffer.GetAvailableBytes(), 0u);
+  if (!WriteBuffer(fd, section_infos_buffer.Get(), section_infos_buffer.Size())) {
+    return false;
+  }
 
-  if (!WriteBuffer(fd, buffer.data(), buffer.size())) {
+  // Write header.
+  FileHeader header(version_, section_index);
+  if (lseek(fd, 0, SEEK_SET) != 0) {
     return false;
   }
-  if (!WriteBuffer(fd, compressed_buffer.get(), output_size)) {
+  if (!WriteBuffer(fd, &header, sizeof(FileHeader))) {
     return false;
   }
+
   uint64_t total_time = NanoTime() - start;
   VLOG(profiler) << "Compressed from "
-                 << std::to_string(required_capacity)
+                 << std::to_string(total_uncompressed_size)
                  << " to "
-                 << std::to_string(output_size);
+                 << std::to_string(file_offset);
   VLOG(profiler) << "Time to save profile: " << std::to_string(total_time);
   return true;
 }
 
-void ProfileCompilationInfo::AddInlineCacheToBuffer(std::vector<uint8_t>* buffer,
-                                                    const InlineCacheMap& inline_cache_map) {
-  // Add inline cache map size.
-  AddUintToBuffer(buffer, static_cast<uint16_t>(inline_cache_map.size()));
-  if (inline_cache_map.size() == 0) {
-    return;
-  }
-  for (const auto& inline_cache_it : inline_cache_map) {
-    uint16_t dex_pc = inline_cache_it.first;
-    const DexPcData dex_pc_data = inline_cache_it.second;
-    const ClassSet& classes = dex_pc_data.classes;
-
-    // Add the dex pc.
-    AddUintToBuffer(buffer, dex_pc);
-
-    // Add the megamorphic/missing_types encoding if needed and continue.
-    // In either cases we don't add any classes to the profiles and so there's
-    // no point to continue.
-    // TODO(calin): in case we miss types there is still value to add the
-    // rest of the classes. They can be added without bumping the profile version.
-    if (dex_pc_data.is_missing_types) {
-      DCHECK(!dex_pc_data.is_megamorphic);  // at this point the megamorphic flag should not be set.
-      DCHECK_EQ(classes.size(), 0u);
-      AddUintToBuffer(buffer, kIsMissingTypesEncoding);
-      continue;
-    } else if (dex_pc_data.is_megamorphic) {
-      DCHECK_EQ(classes.size(), 0u);
-      AddUintToBuffer(buffer, kIsMegamorphicEncoding);
-      continue;
-    }
-
-    DCHECK_LT(classes.size(), ProfileCompilationInfo::kIndividualInlineCacheSize);
-    DCHECK_NE(classes.size(), 0u) << "InlineCache contains a dex_pc with 0 classes";
-
-    SafeMap<ProfileIndexType, std::vector<dex::TypeIndex>> dex_to_classes_map;
-    // Group the classes by dex. We expect that most of the classes will come from
-    // the same dex, so this will be more efficient than encoding the dex index
-    // for each class reference.
-    GroupClassesByDex(classes, &dex_to_classes_map);
-    // Add the dex map size.
-    AddUintToBuffer(buffer, static_cast<uint8_t>(dex_to_classes_map.size()));
-    for (const auto& dex_it : dex_to_classes_map) {
-      ProfileIndexType dex_profile_index = dex_it.first;
-      const std::vector<dex::TypeIndex>& dex_classes = dex_it.second;
-      // Add the dex profile index.
-      WriteProfileIndex(buffer, dex_profile_index);
-      // Add the the number of classes for each dex profile index.
-      AddUintToBuffer(buffer, static_cast<uint8_t>(dex_classes.size()));
-      for (size_t i = 0; i < dex_classes.size(); i++) {
-        // Add the type index of the classes.
-        AddUintToBuffer(buffer, dex_classes[i].index_);
-      }
-    }
-  }
-}
-
-uint32_t ProfileCompilationInfo::GetMethodsRegionSize(const DexFileData& dex_data) {
-  // ((uint16_t)method index + (uint16_t)inline cache size) * number of methods
-  uint32_t size = 2 * sizeof(uint16_t) * dex_data.method_map.size();
-  for (const auto& method_it : dex_data.method_map) {
-    const InlineCacheMap& inline_cache = method_it.second;
-    size += sizeof(uint16_t) * inline_cache.size();  // dex_pc
-    for (const auto& inline_cache_it : inline_cache) {
-      const ClassSet& classes = inline_cache_it.second.classes;
-      SafeMap<ProfileIndexType, std::vector<dex::TypeIndex>> dex_to_classes_map;
-      GroupClassesByDex(classes, &dex_to_classes_map);
-      size += sizeof(uint8_t);  // dex_to_classes_map size
-      for (const auto& dex_it : dex_to_classes_map) {
-        size += SizeOfProfileIndexType();  // dex profile index
-        size += sizeof(uint8_t);  // number of classes
-        const std::vector<dex::TypeIndex>& dex_classes = dex_it.second;
-        size += sizeof(uint16_t) * dex_classes.size();  // the actual classes
-      }
-    }
-  }
-  return size;
-}
-
-void ProfileCompilationInfo::GroupClassesByDex(
-    const ClassSet& classes,
-    /*out*/SafeMap<ProfileIndexType, std::vector<dex::TypeIndex>>* dex_to_classes_map) {
-  for (const auto& classes_it : classes) {
-    auto dex_it = dex_to_classes_map->FindOrAdd(classes_it.dex_profile_index);
-    dex_it->second.push_back(classes_it.type_index);
-  }
-}
-
 ProfileCompilationInfo::DexFileData* ProfileCompilationInfo::GetOrAddDexFileData(
     const std::string& profile_key,
     uint32_t checksum,
+    uint32_t num_type_ids,
     uint32_t num_method_ids) {
-  const auto profile_index_it = profile_key_map_.FindOrAdd(profile_key, profile_key_map_.size());
-  if (profile_key_map_.size() > MaxProfileIndex()) {
-    // Allow only a limited number dex files to be profiled. This allows us to save bytes
-    // when encoding. For regular profiles this 2^8, and for boot profiles is 2^16
-    // (well above what we expect for normal applications).
-    if (kIsDebugBuild) {
+  DCHECK_EQ(profile_key_map_.size(), info_.size());
+  auto profile_index_it = profile_key_map_.lower_bound(profile_key);
+  if (profile_index_it == profile_key_map_.end() || profile_index_it->first != profile_key) {
+    // We did not find the key. Create a new DexFileData if we did not reach the limit.
+    DCHECK_LE(profile_key_map_.size(), MaxProfileIndex());
+    if (profile_key_map_.size() == MaxProfileIndex()) {
+      // Allow only a limited number dex files to be profiled. This allows us to save bytes
+      // when encoding. For regular profiles this 2^8, and for boot profiles is 2^16
+      // (well above what we expect for normal applications).
       LOG(ERROR) << "Exceeded the maximum number of dex file. Something went wrong";
+      return nullptr;
     }
-    profile_key_map_.erase(profile_key);
-    return nullptr;
-  }
-
-  ProfileIndexType profile_index = profile_index_it->second;
-  if (info_.size() <= profile_index) {
-    // This is a new addition. Add it to the info_ array.
-    DexFileData* dex_file_data = new (&allocator_) DexFileData(
+    ProfileIndexType new_profile_index = dchecked_integral_cast<ProfileIndexType>(info_.size());
+    std::unique_ptr<DexFileData> dex_file_data(new (&allocator_) DexFileData(
         &allocator_,
         profile_key,
         checksum,
-        profile_index,
+        new_profile_index,
+        num_type_ids,
         num_method_ids,
-        IsForBootImage());
-    info_.push_back(dex_file_data);
+        IsForBootImage()));
+    // Record the new data in `profile_key_map_` and `info_`.
+    std::string_view new_key(dex_file_data->profile_key);
+    profile_index_it = profile_key_map_.PutBefore(profile_index_it, new_key, new_profile_index);
+    info_.push_back(std::move(dex_file_data));
+    DCHECK_EQ(profile_key_map_.size(), info_.size());
   }
-  DexFileData* result = info_[profile_index];
+
+  ProfileIndexType profile_index = profile_index_it->second;
+  DexFileData* result = info_[profile_index].get();
 
   // Check that the checksum matches.
   // This may different if for example the dex file was updated and we had a record of the old one.
@@ -647,11 +1148,11 @@
   DCHECK_EQ(profile_key, result->profile_key);
   DCHECK_EQ(profile_index, result->profile_index);
 
-  if (num_method_ids != result->num_method_ids) {
+  if (num_type_ids != result->num_type_ids || num_method_ids != result->num_method_ids) {
     // This should not happen... added to help investigating b/65812889.
-    LOG(ERROR) << "num_method_ids mismatch for dex " << profile_key
-        << ", expected=" << num_method_ids
-        << ", actual=" << result->num_method_ids;
+    LOG(ERROR) << "num_type_ids or num_method_ids mismatch for dex " << profile_key
+        << ", types: expected=" << num_type_ids << " v. actual=" << result->num_type_ids
+        << ", methods: expected=" << num_method_ids << " actual=" << result->num_method_ids;
     return nullptr;
   }
 
@@ -668,7 +1169,7 @@
   }
 
   ProfileIndexType profile_index = profile_index_it->second;
-  const DexFileData* result = info_[profile_index];
+  const DexFileData* result = info_[profile_index].get();
   if (verify_checksum && !ChecksumMatch(result->checksum, checksum)) {
     return nullptr;
   }
@@ -681,13 +1182,13 @@
       const DexFile* dex_file,
       const ProfileSampleAnnotation& annotation) const {
   if (annotation == ProfileSampleAnnotation::kNone) {
-    std::string profile_key = GetProfileDexFileBaseKey(dex_file->GetLocation());
-    for (const DexFileData* dex_data : info_) {
-      if (profile_key == GetBaseKeyFromAugmentedKey(dex_data->profile_key)) {
+    std::string_view profile_key = GetProfileDexFileBaseKeyView(dex_file->GetLocation());
+    for (const std::unique_ptr<DexFileData>& dex_data : info_) {
+      if (profile_key == GetBaseKeyViewFromAugmentedKey(dex_data->profile_key)) {
         if (!ChecksumMatch(dex_data->checksum, dex_file->GetLocationChecksum())) {
           return nullptr;
         }
-        return dex_data;
+        return dex_data.get();
       }
     }
   } else {
@@ -701,16 +1202,31 @@
 void ProfileCompilationInfo::FindAllDexData(
     const DexFile* dex_file,
     /*out*/ std::vector<const ProfileCompilationInfo::DexFileData*>* result) const {
-  std::string profile_key = GetProfileDexFileBaseKey(dex_file->GetLocation());
-  for (const DexFileData* dex_data : info_) {
-    if (profile_key == GetBaseKeyFromAugmentedKey(dex_data->profile_key)) {
+  std::string_view profile_key = GetProfileDexFileBaseKeyView(dex_file->GetLocation());
+  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
+    if (profile_key == GetBaseKeyViewFromAugmentedKey(dex_data->profile_key)) {
       if (ChecksumMatch(dex_data->checksum, dex_file->GetLocationChecksum())) {
-        result->push_back(dex_data);
+        result->push_back(dex_data.get());
       }
     }
   }
 }
 
+ProfileCompilationInfo::ExtraDescriptorIndex ProfileCompilationInfo::AddExtraDescriptor(
+    std::string_view extra_descriptor) {
+  DCHECK_LE(extra_descriptor.size(), kMaxExtraDescriptorLength);
+  DCHECK(extra_descriptors_indexes_.find(extra_descriptor) == extra_descriptors_indexes_.end());
+  ExtraDescriptorIndex new_extra_descriptor_index = extra_descriptors_.size();
+  DCHECK_LE(new_extra_descriptor_index, kMaxExtraDescriptors);
+  if (UNLIKELY(new_extra_descriptor_index == kMaxExtraDescriptors)) {
+    return kMaxExtraDescriptors;  // Cannot add another extra descriptor.
+  }
+  // Add the extra descriptor and record the new index.
+  extra_descriptors_.emplace_back(extra_descriptor);
+  extra_descriptors_indexes_.insert(new_extra_descriptor_index);
+  return new_extra_descriptor_index;
+}
+
 bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi,
                                        MethodHotness::Flag flags,
                                        const ProfileSampleAnnotation& annotation) {
@@ -726,11 +1242,7 @@
     return true;
   }
 
-  // Add inline caches. Do this only for regular profiles. The boot image profiles don't use
-  // them and they take up useless space.
-  if (IsForBootImage()) {
-    return true;  // early success return.
-  }
+  // Add inline caches.
   InlineCacheMap* inline_cache = data->FindOrAddHotMethod(pmi.ref.index);
   DCHECK(inline_cache != nullptr);
 
@@ -739,355 +1251,28 @@
       FindOrAddDexPc(inline_cache, cache.dex_pc)->SetIsMissingTypes();
       continue;
     }
+    if  (cache.is_megamorphic) {
+      FindOrAddDexPc(inline_cache, cache.dex_pc)->SetIsMegamorphic();
+      continue;
+    }
     for (const TypeReference& class_ref : cache.classes) {
-      DexFileData* class_dex_data = GetOrAddDexFileData(class_ref.dex_file, annotation);
-      if (class_dex_data == nullptr) {  // checksum mismatch
-        return false;
-      }
       DexPcData* dex_pc_data = FindOrAddDexPc(inline_cache, cache.dex_pc);
-      if (dex_pc_data->is_missing_types) {
-        // Don't bother adding classes if we are missing types.
+      if (dex_pc_data->is_missing_types || dex_pc_data->is_megamorphic) {
+        // Don't bother adding classes if we are missing types or already megamorphic.
         break;
       }
-      dex_pc_data->AddClass(class_dex_data->profile_index, class_ref.TypeIndex());
-    }
-  }
-  return true;
-}
-
-#define READ_UINT(type, buffer, dest, error)            \
-  do {                                                  \
-    if (!(buffer).ReadUintAndAdvance<type>(&(dest))) {  \
-      *(error) = "Could not read "#dest;                \
-      return false;                                     \
-    }                                                   \
-  }                                                     \
-  while (false)
-
-bool ProfileCompilationInfo::ReadInlineCache(
-    SafeBuffer& buffer,
-    ProfileIndexType number_of_dex_files,
-    const SafeMap<ProfileIndexType, ProfileIndexType>& dex_profile_index_remap,
-    /*out*/ InlineCacheMap* inline_cache,
-    /*out*/ std::string* error) {
-  uint16_t inline_cache_size;
-  READ_UINT(uint16_t, buffer, inline_cache_size, error);
-  for (; inline_cache_size > 0; inline_cache_size--) {
-    uint16_t dex_pc;
-    uint8_t dex_to_classes_map_size;
-    READ_UINT(uint16_t, buffer, dex_pc, error);
-    READ_UINT(uint8_t, buffer, dex_to_classes_map_size, error);
-    DexPcData* dex_pc_data = FindOrAddDexPc(inline_cache, dex_pc);
-    if (dex_to_classes_map_size == kIsMissingTypesEncoding) {
-      dex_pc_data->SetIsMissingTypes();
-      continue;
-    }
-    if (dex_to_classes_map_size == kIsMegamorphicEncoding) {
-      dex_pc_data->SetIsMegamorphic();
-      continue;
-    }
-    for (; dex_to_classes_map_size > 0; dex_to_classes_map_size--) {
-      ProfileIndexType dex_profile_index;
-      uint8_t dex_classes_size;
-      if (!ReadProfileIndex(buffer, &dex_profile_index)) {
-        *error = "Cannot read profile index";
-        return false;
-      }
-      READ_UINT(uint8_t, buffer, dex_classes_size, error);
-      if (dex_profile_index >= number_of_dex_files) {
-        *error = "dex_profile_index out of bounds ";
-        *error += std::to_string(dex_profile_index) + " " + std::to_string(number_of_dex_files);
-        return false;
-      }
-      for (; dex_classes_size > 0; dex_classes_size--) {
-        uint16_t type_index;
-        READ_UINT(uint16_t, buffer, type_index, error);
-        auto it = dex_profile_index_remap.find(dex_profile_index);
-        if (it == dex_profile_index_remap.end()) {
-          // If we don't have an index that's because the dex file was filtered out when loading.
-          // Set missing types on the dex pc data.
-          dex_pc_data->SetIsMissingTypes();
-        } else {
-          dex_pc_data->AddClass(it->second, dex::TypeIndex(type_index));
-        }
+      dex::TypeIndex type_index = FindOrCreateTypeIndex(*pmi.ref.dex_file, class_ref);
+      if (type_index.IsValid()) {
+        dex_pc_data->AddClass(type_index);
+      } else {
+        // Could not create artificial type index.
+        dex_pc_data->SetIsMissingTypes();
       }
     }
   }
   return true;
 }
 
-bool ProfileCompilationInfo::ReadMethods(
-    SafeBuffer& buffer,
-    ProfileIndexType number_of_dex_files,
-    const ProfileLineHeader& line_header,
-    const SafeMap<ProfileIndexType, ProfileIndexType>& dex_profile_index_remap,
-    /*out*/std::string* error) {
-  uint32_t unread_bytes_before_operation = buffer.CountUnreadBytes();
-  if (unread_bytes_before_operation < line_header.method_region_size_bytes) {
-    *error += "Profile EOF reached prematurely for ReadMethod";
-    return false;
-  }
-  size_t expected_unread_bytes_after_operation = buffer.CountUnreadBytes()
-      - line_header.method_region_size_bytes;
-  uint16_t last_method_index = 0;
-  while (buffer.CountUnreadBytes() > expected_unread_bytes_after_operation) {
-    DexFileData* const data = GetOrAddDexFileData(line_header.profile_key,
-                                                  line_header.checksum,
-                                                  line_header.num_method_ids);
-    uint16_t diff_with_last_method_index;
-    READ_UINT(uint16_t, buffer, diff_with_last_method_index, error);
-    uint16_t method_index = last_method_index + diff_with_last_method_index;
-    last_method_index = method_index;
-    InlineCacheMap* inline_cache = data->FindOrAddHotMethod(method_index);
-    if (inline_cache == nullptr) {
-      return false;
-    }
-    if (!ReadInlineCache(buffer,
-                         number_of_dex_files,
-                         dex_profile_index_remap,
-                         inline_cache,
-                         error)) {
-      return false;
-    }
-  }
-  uint32_t total_bytes_read = unread_bytes_before_operation - buffer.CountUnreadBytes();
-  if (total_bytes_read != line_header.method_region_size_bytes) {
-    *error += "Profile data inconsistent for ReadMethods";
-    return false;
-  }
-  return true;
-}
-
-bool ProfileCompilationInfo::ReadClasses(SafeBuffer& buffer,
-                                         const ProfileLineHeader& line_header,
-                                         /*out*/std::string* error) {
-  size_t unread_bytes_before_op = buffer.CountUnreadBytes();
-  if (unread_bytes_before_op < line_header.class_set_size) {
-    *error += "Profile EOF reached prematurely for ReadClasses";
-    return false;
-  }
-
-  uint16_t last_class_index = 0;
-  for (uint16_t i = 0; i < line_header.class_set_size; i++) {
-    uint16_t diff_with_last_class_index;
-    READ_UINT(uint16_t, buffer, diff_with_last_class_index, error);
-    uint16_t type_index = last_class_index + diff_with_last_class_index;
-    last_class_index = type_index;
-
-    DexFileData* const data = GetOrAddDexFileData(line_header.profile_key,
-                                                  line_header.checksum,
-                                                  line_header.num_method_ids);
-    if (data == nullptr) {
-       return false;
-    }
-    data->class_set.insert(dex::TypeIndex(type_index));
-  }
-  size_t total_bytes_read = unread_bytes_before_op - buffer.CountUnreadBytes();
-  uint32_t expected_bytes_read = line_header.class_set_size * sizeof(uint16_t);
-  if (total_bytes_read != expected_bytes_read) {
-    *error += "Profile data inconsistent for ReadClasses";
-    return false;
-  }
-  return true;
-}
-
-// Tests for EOF by trying to read 1 byte from the descriptor.
-// Returns:
-//   0 if the descriptor is at the EOF,
-//  -1 if there was an IO error
-//   1 if the descriptor has more content to read
-static int testEOF(int fd) {
-  uint8_t buffer[1];
-  return TEMP_FAILURE_RETRY(read(fd, buffer, 1));
-}
-
-// Reads an uint value previously written with AddUintToBuffer.
-template <typename T>
-bool ProfileCompilationInfo::SafeBuffer::ReadUintAndAdvance(/*out*/T* value) {
-  static_assert(std::is_unsigned<T>::value, "Type is not unsigned");
-  if (ptr_current_ + sizeof(T) > ptr_end_) {
-    return false;
-  }
-  *value = 0;
-  for (size_t i = 0; i < sizeof(T); i++) {
-    *value += ptr_current_[i] << (i * kBitsPerByte);
-  }
-  ptr_current_ += sizeof(T);
-  return true;
-}
-
-bool ProfileCompilationInfo::SafeBuffer::CompareAndAdvance(const uint8_t* data, size_t data_size) {
-  if (ptr_current_ + data_size > ptr_end_) {
-    return false;
-  }
-  if (memcmp(ptr_current_, data, data_size) == 0) {
-    ptr_current_ += data_size;
-    return true;
-  }
-  return false;
-}
-
-ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::SafeBuffer::Fill(
-      ProfileSource& source,
-      const std::string& debug_stage,
-      /*out*/ std::string* error) {
-  size_t byte_count = (ptr_end_ - ptr_current_) * sizeof(*ptr_current_);
-  uint8_t* buffer = ptr_current_;
-  return source.Read(buffer, byte_count, debug_stage, error);
-}
-
-size_t ProfileCompilationInfo::SafeBuffer::CountUnreadBytes() {
-  return (ptr_end_ - ptr_current_) * sizeof(*ptr_current_);
-}
-
-const uint8_t* ProfileCompilationInfo::SafeBuffer::GetCurrentPtr() {
-  return ptr_current_;
-}
-
-void ProfileCompilationInfo::SafeBuffer::Advance(size_t data_size) {
-  ptr_current_ += data_size;
-}
-
-ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadProfileHeader(
-      ProfileSource& source,
-      /*out*/ProfileIndexType* number_of_dex_files,
-      /*out*/uint32_t* uncompressed_data_size,
-      /*out*/uint32_t* compressed_data_size,
-      /*out*/std::string* error) {
-  // Read magic and version
-  const size_t kMagicVersionSize =
-    sizeof(kProfileMagic) +
-    kProfileVersionSize;
-  SafeBuffer safe_buffer_version(kMagicVersionSize);
-
-  ProfileLoadStatus status = safe_buffer_version.Fill(source, "ReadProfileHeaderVersion", error);
-  if (status != kProfileLoadSuccess) {
-    return status;
-  }
-
-  if (!safe_buffer_version.CompareAndAdvance(kProfileMagic, sizeof(kProfileMagic))) {
-    *error = "Profile missing magic";
-    return kProfileLoadVersionMismatch;
-  }
-  if (safe_buffer_version.CountUnreadBytes() < kProfileVersionSize) {
-     *error = "Cannot read profile version";
-     return kProfileLoadBadData;
-  }
-  memcpy(version_, safe_buffer_version.GetCurrentPtr(), kProfileVersionSize);
-  if ((memcmp(version_, kProfileVersion, kProfileVersionSize) != 0) &&
-      (memcmp(version_, kProfileVersionForBootImage, kProfileVersionSize) != 0)) {
-    *error = "Profile version mismatch";
-    return kProfileLoadVersionMismatch;
-  }
-
-  const size_t kProfileHeaderDataSize =
-    SizeOfProfileIndexType() +  // number of dex files
-    sizeof(uint32_t) +  // size of uncompressed profile data
-    sizeof(uint32_t);  // size of compressed profile data
-  SafeBuffer safe_buffer_header_data(kProfileHeaderDataSize);
-
-  status = safe_buffer_header_data.Fill(source, "ReadProfileHeaderData", error);
-  if (status != kProfileLoadSuccess) {
-    return status;
-  }
-
-  if (!ReadProfileIndex(safe_buffer_header_data, number_of_dex_files)) {
-    *error = "Cannot read the number of dex files";
-    return kProfileLoadBadData;
-  }
-  if (!safe_buffer_header_data.ReadUintAndAdvance<uint32_t>(uncompressed_data_size)) {
-    *error = "Cannot read the size of uncompressed data";
-    return kProfileLoadBadData;
-  }
-  if (!safe_buffer_header_data.ReadUintAndAdvance<uint32_t>(compressed_data_size)) {
-    *error = "Cannot read the size of compressed data";
-    return kProfileLoadBadData;
-  }
-  return kProfileLoadSuccess;
-}
-
-bool ProfileCompilationInfo::ReadProfileLineHeaderElements(SafeBuffer& buffer,
-                                                           /*out*/uint16_t* profile_key_size,
-                                                           /*out*/ProfileLineHeader* line_header,
-                                                           /*out*/std::string* error) {
-  READ_UINT(uint16_t, buffer, *profile_key_size, error);
-  READ_UINT(uint16_t, buffer, line_header->class_set_size, error);
-  READ_UINT(uint32_t, buffer, line_header->method_region_size_bytes, error);
-  READ_UINT(uint32_t, buffer, line_header->checksum, error);
-  READ_UINT(uint32_t, buffer, line_header->num_method_ids, error);
-  return true;
-}
-
-ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadProfileLineHeader(
-    SafeBuffer& buffer,
-    /*out*/ProfileLineHeader* line_header,
-    /*out*/std::string* error) {
-  if (buffer.CountUnreadBytes() < kLineHeaderSize) {
-    *error += "Profile EOF reached prematurely for ReadProfileLineHeader";
-    return kProfileLoadBadData;
-  }
-
-  uint16_t profile_key_size;
-  if (!ReadProfileLineHeaderElements(buffer, &profile_key_size, line_header, error)) {
-    return kProfileLoadBadData;
-  }
-
-  if (profile_key_size == 0 || profile_key_size > kMaxDexFileKeyLength) {
-    *error = "ProfileKey has an invalid size: " +
-        std::to_string(static_cast<uint32_t>(profile_key_size));
-    return kProfileLoadBadData;
-  }
-
-  if (buffer.CountUnreadBytes() < profile_key_size) {
-    *error += "Profile EOF reached prematurely for ReadProfileHeaderDexLocation";
-    return kProfileLoadBadData;
-  }
-  const uint8_t* base_ptr = buffer.GetCurrentPtr();
-  line_header->profile_key.assign(
-      reinterpret_cast<const char*>(base_ptr), profile_key_size);
-  buffer.Advance(profile_key_size);
-  return kProfileLoadSuccess;
-}
-
-ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadProfileLine(
-      SafeBuffer& buffer,
-      ProfileIndexType number_of_dex_files,
-      const ProfileLineHeader& line_header,
-      const SafeMap<ProfileIndexType, ProfileIndexType>& dex_profile_index_remap,
-      bool merge_classes,
-      /*out*/std::string* error) {
-  DexFileData* data = GetOrAddDexFileData(line_header.profile_key,
-                                          line_header.checksum,
-                                          line_header.num_method_ids);
-  if (data == nullptr) {
-    *error = "Error when reading profile file line header: checksum mismatch for "
-        + line_header.profile_key;
-    return kProfileLoadBadData;
-  }
-
-  if (!ReadMethods(buffer, number_of_dex_files, line_header, dex_profile_index_remap, error)) {
-    return kProfileLoadBadData;
-  }
-
-  if (merge_classes) {
-    if (!ReadClasses(buffer, line_header, error)) {
-      return kProfileLoadBadData;
-    }
-  }
-
-  // Read method bitmap.
-  const size_t bytes = data->bitmap_storage.size();
-  if (buffer.CountUnreadBytes() < bytes) {
-    *error += "Profile EOF reached prematurely for ReadProfileHeaderDexLocation";
-    return kProfileLoadBadData;
-  }
-  const uint8_t* base_ptr = buffer.GetCurrentPtr();
-  std::copy_n(base_ptr, bytes, data->bitmap_storage.data());
-  buffer.Advance(bytes);
-
-  return kProfileLoadSuccess;
-}
-
 // TODO(calin): Fix this API. ProfileCompilationInfo::Load should be static and
 // return a unique pointer to a ProfileCompilationInfo upon success.
 bool ProfileCompilationInfo::Load(
@@ -1096,7 +1281,7 @@
 
   ProfileLoadStatus status = LoadInternal(fd, &error, merge_classes, filter_fn);
 
-  if (status == kProfileLoadSuccess) {
+  if (status == ProfileLoadStatus::kSuccess) {
     return true;
   } else {
     LOG(WARNING) << "Error when reading profile: " << error;
@@ -1105,13 +1290,13 @@
 }
 
 bool ProfileCompilationInfo::VerifyProfileData(const std::vector<const DexFile*>& dex_files) {
-  std::unordered_map<std::string, const DexFile*> key_to_dex_file;
+  std::unordered_map<std::string_view, const DexFile*> key_to_dex_file;
   for (const DexFile* dex_file : dex_files) {
-    key_to_dex_file.emplace(GetProfileDexFileBaseKey(dex_file->GetLocation()), dex_file);
+    key_to_dex_file.emplace(GetProfileDexFileBaseKeyView(dex_file->GetLocation()), dex_file);
   }
-  for (const DexFileData* dex_data : info_) {
+  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
     // We need to remove any annotation from the key during verification.
-    const auto it = key_to_dex_file.find(GetBaseKeyFromAugmentedKey(dex_data->profile_key));
+    const auto it = key_to_dex_file.find(GetBaseKeyViewFromAugmentedKey(dex_data->profile_key));
     if (it == key_to_dex_file.end()) {
       // It is okay if profile contains data for additional dex files.
       continue;
@@ -1126,71 +1311,45 @@
       return false;
     }
 
-    if (dex_data->num_method_ids != dex_file->NumMethodIds()) {
-      LOG(ERROR) << "Number of method ids in dex file and profile don't match."
-                 << "dex location " << dex_location << " NumMethodId in DexFile"
-                 << dex_file->NumMethodIds() << ", NumMethodId in profile"
-                 << dex_data->num_method_ids;
+    if (dex_data->num_method_ids != dex_file->NumMethodIds() ||
+        dex_data->num_type_ids != dex_file->NumTypeIds()) {
+      LOG(ERROR) << "Number of type or method ids in dex file and profile don't match."
+                 << "dex location " << dex_location
+                 << " dex_file.NumTypeIds=" << dex_file->NumTypeIds()
+                 << " .v dex_data.num_type_ids=" << dex_data->num_type_ids
+                 << ", dex_file.NumMethodIds=" << dex_file->NumMethodIds()
+                 << " v. dex_data.num_method_ids=" << dex_data->num_method_ids;
       return false;
     }
 
-    // Verify method_encoding.
-    for (const auto& method_it : dex_data->method_map) {
-      size_t method_id = (size_t)(method_it.first);
-      if (method_id >= dex_file->NumMethodIds()) {
-        LOG(ERROR) << "Invalid method id in profile file. dex location="
-                   << dex_location << " method_id=" << method_id << " NumMethodIds="
-                   << dex_file->NumMethodIds();
-        return false;
-      }
+    // Class and method data should be valid. Verify only in debug builds.
+    if (kIsDebugBuild) {
+      // Verify method_encoding.
+      for (const auto& method_it : dex_data->method_map) {
+        CHECK_LT(method_it.first, dex_data->num_method_ids);
 
-      // Verify class indices of inline caches.
-      const InlineCacheMap &inline_cache_map = method_it.second;
-      for (const auto& inline_cache_it : inline_cache_map) {
-        const DexPcData dex_pc_data = inline_cache_it.second;
-        if (dex_pc_data.is_missing_types || dex_pc_data.is_megamorphic) {
-          // No class indices to verify.
-          continue;
-        }
-
-        const ClassSet &classes = dex_pc_data.classes;
-        SafeMap<ProfileIndexType, std::vector<dex::TypeIndex>> dex_to_classes_map;
-        // Group the classes by dex. We expect that most of the classes will come from
-        // the same dex, so this will be more efficient than encoding the dex index
-        // for each class reference.
-        GroupClassesByDex(classes, &dex_to_classes_map);
-        for (const auto &dex_it : dex_to_classes_map) {
-          ProfileIndexType dex_profile_index = dex_it.first;
-          const auto dex_file_inline_cache_it = key_to_dex_file.find(
-              info_[dex_profile_index]->profile_key);
-          if (dex_file_inline_cache_it == key_to_dex_file.end()) {
-            // It is okay if profile contains data for additional dex files.
+        // Verify class indices of inline caches.
+        const InlineCacheMap &inline_cache_map = method_it.second;
+        for (const auto& inline_cache_it : inline_cache_map) {
+          const DexPcData& dex_pc_data = inline_cache_it.second;
+          if (dex_pc_data.is_missing_types || dex_pc_data.is_megamorphic) {
+            // No class indices to verify.
+            CHECK(dex_pc_data.classes.empty());
             continue;
           }
-          const DexFile *dex_file_for_inline_cache_check = dex_file_inline_cache_it->second;
-          const std::vector<dex::TypeIndex> &dex_classes = dex_it.second;
-          for (size_t i = 0; i < dex_classes.size(); i++) {
-            if (dex_classes[i].index_ >= dex_file_for_inline_cache_check->NumTypeIds()) {
-              LOG(ERROR) << "Invalid inline cache in profile file. dex location="
-                  << dex_location << " method_id=" << method_id
-                  << " dex_profile_index="
-                  << static_cast<uint16_t >(dex_profile_index) << " type_index="
-                  << dex_classes[i].index_
-                  << " NumTypeIds="
-                  << dex_file_for_inline_cache_check->NumTypeIds();
-              return false;
+
+          for (const dex::TypeIndex& type_index : dex_pc_data.classes) {
+            if (type_index.index_ >= dex_data->num_type_ids) {
+              CHECK_LT(type_index.index_ - dex_data->num_type_ids, extra_descriptors_.size());
             }
           }
         }
       }
-    }
-    // Verify class_ids.
-    for (const auto& class_id : dex_data->class_set) {
-      if (class_id.index_ >= dex_file->NumTypeIds()) {
-        LOG(ERROR) << "Invalid class id in profile file. dex_file location "
-                   << dex_location << " class_id=" << class_id.index_ << " NumClassIds="
-                   << dex_file->NumClassDefs();
-        return false;
+      // Verify class_ids.
+      for (const dex::TypeIndex& type_index : dex_data->class_set) {
+        if (type_index.index_ >= dex_data->num_type_ids) {
+          CHECK_LT(type_index.index_ - dex_data->num_type_ids, extra_descriptors_.size());
+        }
       }
     }
   }
@@ -1203,13 +1362,13 @@
     /*out*/ std::string* error) {
   if (IsProfileFile(fd)) {
     source->reset(ProfileSource::Create(fd));
-    return kProfileLoadSuccess;
+    return ProfileLoadStatus::kSuccess;
   } else {
     std::unique_ptr<ZipArchive> zip_archive(
         ZipArchive::OpenFromFd(DupCloexec(fd), "profile", error));
     if (zip_archive.get() == nullptr) {
       *error = "Could not open the profile zip archive";
-      return kProfileLoadBadData;
+      return ProfileLoadStatus::kBadData;
     }
     std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(kDexMetadataProfileEntry, error));
     if (zip_entry == nullptr) {
@@ -1219,11 +1378,11 @@
       LOG(WARNING) << "Could not find entry " << kDexMetadataProfileEntry
           << " in the zip archive. Creating an empty profile.";
       source->reset(ProfileSource::Create(MemMap::Invalid()));
-      return kProfileLoadSuccess;
+      return ProfileLoadStatus::kSuccess;
     }
     if (zip_entry->GetUncompressedLength() == 0) {
       *error = "Empty profile entry in the zip archive.";
-      return kProfileLoadBadData;
+      return ProfileLoadStatus::kBadData;
     }
 
     // TODO(calin) pass along file names to assist with debugging.
@@ -1232,48 +1391,58 @@
 
     if (map.IsValid()) {
       source->reset(ProfileSource::Create(std::move(map)));
-      return kProfileLoadSuccess;
+      return ProfileLoadStatus::kSuccess;
     } else {
-      return kProfileLoadBadData;
+      return ProfileLoadStatus::kBadData;
     }
   }
 }
 
+bool ProfileCompilationInfo::ProfileSource::Seek(off_t offset) {
+  DCHECK_GE(offset, 0);
+  if (IsMemMap()) {
+    if (offset > static_cast<int64_t>(mem_map_.Size())) {
+      return false;
+    }
+    mem_map_cur_ = offset;
+    return true;
+  } else {
+    if (lseek64(fd_, offset, SEEK_SET) != offset) {
+      return false;
+    }
+    return true;
+  }
+}
+
 ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ProfileSource::Read(
-    uint8_t* buffer,
+    void* buffer,
     size_t byte_count,
     const std::string& debug_stage,
     std::string* error) {
   if (IsMemMap()) {
-    if (mem_map_cur_ + byte_count > mem_map_.Size()) {
-      return kProfileLoadBadData;
+    DCHECK_LE(mem_map_cur_, mem_map_.Size());
+    if (byte_count > mem_map_.Size() - mem_map_cur_) {
+      return ProfileLoadStatus::kBadData;
     }
-    for (size_t i = 0; i < byte_count; i++) {
-      buffer[i] = *(mem_map_.Begin() + mem_map_cur_);
-      mem_map_cur_++;
-    }
+    memcpy(buffer, mem_map_.Begin() + mem_map_cur_, byte_count);
+    mem_map_cur_ += byte_count;
   } else {
     while (byte_count > 0) {
       int bytes_read = TEMP_FAILURE_RETRY(read(fd_, buffer, byte_count));;
       if (bytes_read == 0) {
         *error += "Profile EOF reached prematurely for " + debug_stage;
-        return kProfileLoadBadData;
+        return ProfileLoadStatus::kBadData;
       } else if (bytes_read < 0) {
         *error += "Profile IO error for " + debug_stage + strerror(errno);
-        return kProfileLoadIOError;
+        return ProfileLoadStatus::kIOError;
       }
       byte_count -= bytes_read;
-      buffer += bytes_read;
+      reinterpret_cast<uint8_t*&>(buffer) += bytes_read;
     }
   }
-  return kProfileLoadSuccess;
+  return ProfileLoadStatus::kSuccess;
 }
 
-bool ProfileCompilationInfo::ProfileSource::HasConsumedAllData() const {
-  return IsMemMap()
-      ? (!mem_map_.IsValid() || mem_map_cur_ == mem_map_.Size())
-      : (testEOF(fd_) == 0);
-}
 
 bool ProfileCompilationInfo::ProfileSource::HasEmptyContent() const {
   if (IsMemMap()) {
@@ -1287,18 +1456,233 @@
   }
 }
 
+ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadSectionData(
+    ProfileSource& source,
+    const FileSectionInfo& section_info,
+    /*out*/ SafeBuffer* buffer,
+    /*out*/ std::string* error) {
+  DCHECK_EQ(buffer->Size(), 0u);
+  if (!source.Seek(section_info.GetFileOffset())) {
+    *error = "Failed to seek to section data.";
+    return ProfileLoadStatus::kIOError;
+  }
+  SafeBuffer temp_buffer(section_info.GetFileSize());
+  ProfileLoadStatus status = source.Read(
+      temp_buffer.GetCurrentPtr(), temp_buffer.GetAvailableBytes(), "ReadSectionData", error);
+  if (status != ProfileLoadStatus::kSuccess) {
+    return status;
+  }
+  if (section_info.GetInflatedSize() != 0u &&
+      !temp_buffer.Inflate(section_info.GetInflatedSize())) {
+    *error += "Error uncompressing section data.";
+    return ProfileLoadStatus::kBadData;
+  }
+  buffer->Swap(temp_buffer);
+  return ProfileLoadStatus::kSuccess;
+}
+
+ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadDexFilesSection(
+    ProfileSource& source,
+    const FileSectionInfo& section_info,
+    const ProfileLoadFilterFn& filter_fn,
+    /*out*/ dchecked_vector<ProfileIndexType>* dex_profile_index_remap,
+    /*out*/ std::string* error) {
+  DCHECK(section_info.GetType() == FileSectionType::kDexFiles);
+  SafeBuffer buffer;
+  ProfileLoadStatus status = ReadSectionData(source, section_info, &buffer, error);
+  if (status != ProfileLoadStatus::kSuccess) {
+    return status;
+  }
+
+  ProfileIndexType num_dex_files;
+  if (!buffer.ReadUintAndAdvance(&num_dex_files)) {
+    *error = "Error reading number of dex files.";
+    return ProfileLoadStatus::kBadData;
+  }
+  if (num_dex_files >= MaxProfileIndex()) {
+    *error = "Too many dex files.";
+    return ProfileLoadStatus::kBadData;
+  }
+
+  DCHECK(dex_profile_index_remap->empty());
+  for (ProfileIndexType i = 0u; i != num_dex_files; ++i) {
+    uint32_t checksum, num_type_ids, num_method_ids;
+    if (!buffer.ReadUintAndAdvance(&checksum) ||
+        !buffer.ReadUintAndAdvance(&num_type_ids) ||
+        !buffer.ReadUintAndAdvance(&num_method_ids)) {
+      *error = "Error reading dex file data.";
+      return ProfileLoadStatus::kBadData;
+    }
+    std::string_view profile_key_view;
+    if (!buffer.ReadStringAndAdvance(&profile_key_view)) {
+      *error += "Missing terminating null character for profile key.";
+      return ProfileLoadStatus::kBadData;
+    }
+    if (profile_key_view.size() == 0u || profile_key_view.size() > kMaxDexFileKeyLength) {
+      *error = "ProfileKey has an invalid size: " + std::to_string(profile_key_view.size());
+      return ProfileLoadStatus::kBadData;
+    }
+    std::string profile_key(profile_key_view);
+    if (!filter_fn(profile_key, checksum)) {
+      // Do not load data for this key. Store invalid index to `dex_profile_index_remap`.
+      VLOG(compiler) << "Profile: Filtered out " << profile_key << " 0x" << std::hex << checksum;
+      dex_profile_index_remap->push_back(MaxProfileIndex());
+      continue;
+    }
+    DexFileData* data = GetOrAddDexFileData(profile_key, checksum, num_type_ids, num_method_ids);
+    if (data == nullptr) {
+      if (UNLIKELY(profile_key_map_.size() == MaxProfileIndex()) &&
+          profile_key_map_.find(profile_key) == profile_key_map_.end()) {
+        *error = "Too many dex files.";
+      } else {
+        *error = "Checksum, NumTypeIds, or NumMethodIds mismatch for " + profile_key;
+      }
+      return ProfileLoadStatus::kBadData;
+    }
+    dex_profile_index_remap->push_back(data->profile_index);
+  }
+  if (buffer.GetAvailableBytes() != 0u) {
+    *error = "Unexpected data at end of dex files section.";
+    return ProfileLoadStatus::kBadData;
+  }
+  return ProfileLoadStatus::kSuccess;
+}
+
+ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadExtraDescriptorsSection(
+    ProfileSource& source,
+    const FileSectionInfo& section_info,
+    /*out*/ dchecked_vector<ExtraDescriptorIndex>* extra_descriptors_remap,
+    /*out*/ std::string* error) {
+  DCHECK(section_info.GetType() == FileSectionType::kExtraDescriptors);
+  SafeBuffer buffer;
+  ProfileLoadStatus status = ReadSectionData(source, section_info, &buffer, error);
+  if (status != ProfileLoadStatus::kSuccess) {
+    return status;
+  }
+
+  uint16_t num_extra_descriptors;
+  if (!buffer.ReadUintAndAdvance(&num_extra_descriptors)) {
+    *error = "Error reading number of extra descriptors.";
+    return ProfileLoadStatus::kBadData;
+  }
+
+  // Note: We allow multiple extra descriptors sections in a single profile file
+  // but that can lead to `kMergeError` if there are too many extra descriptors.
+  // Other sections can reference only extra descriptors from preceding sections.
+  extra_descriptors_remap->reserve(
+      std::min<size_t>(extra_descriptors_remap->size() + num_extra_descriptors,
+                       std::numeric_limits<uint16_t>::max()));
+  for (uint16_t i = 0; i != num_extra_descriptors; ++i) {
+    std::string_view extra_descriptor;
+    if (!buffer.ReadStringAndAdvance(&extra_descriptor)) {
+      *error += "Missing terminating null character for extra descriptor.";
+      return ProfileLoadStatus::kBadData;
+    }
+    if (!IsValidDescriptor(std::string(extra_descriptor).c_str())) {
+      *error += "Invalid extra descriptor.";
+      return ProfileLoadStatus::kBadData;
+    }
+    // Try to match an existing extra descriptor.
+    auto it = extra_descriptors_indexes_.find(extra_descriptor);
+    if (it != extra_descriptors_indexes_.end()) {
+      extra_descriptors_remap->push_back(*it);
+      continue;
+    }
+    // Try to insert a new extra descriptor.
+    ExtraDescriptorIndex extra_descriptor_index = AddExtraDescriptor(extra_descriptor);
+    if (extra_descriptor_index == kMaxExtraDescriptors) {
+      *error = "Too many extra descriptors.";
+      return ProfileLoadStatus::kMergeError;
+    }
+    extra_descriptors_remap->push_back(extra_descriptor_index);
+  }
+  return ProfileLoadStatus::kSuccess;
+}
+
+ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadClassesSection(
+    ProfileSource& source,
+    const FileSectionInfo& section_info,
+    const dchecked_vector<ProfileIndexType>& dex_profile_index_remap,
+    const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
+    /*out*/ std::string* error) {
+  DCHECK(section_info.GetType() == FileSectionType::kClasses);
+  SafeBuffer buffer;
+  ProfileLoadStatus status = ReadSectionData(source, section_info, &buffer, error);
+  if (status != ProfileLoadStatus::kSuccess) {
+    return status;
+  }
+
+  while (buffer.GetAvailableBytes() != 0u) {
+    ProfileIndexType profile_index;
+    if (!buffer.ReadUintAndAdvance(&profile_index)) {
+      *error = "Error profile index in classes section.";
+      return ProfileLoadStatus::kBadData;
+    }
+    if (profile_index >= dex_profile_index_remap.size()) {
+      *error = "Invalid profile index in classes section.";
+      return ProfileLoadStatus::kBadData;
+    }
+    profile_index = dex_profile_index_remap[profile_index];
+    if (profile_index == MaxProfileIndex()) {
+      status = DexFileData::SkipClasses(buffer, error);
+    } else {
+      status = info_[profile_index]->ReadClasses(buffer, extra_descriptors_remap, error);
+    }
+    if (status != ProfileLoadStatus::kSuccess) {
+      return status;
+    }
+  }
+  return ProfileLoadStatus::kSuccess;
+}
+
+ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadMethodsSection(
+    ProfileSource& source,
+    const FileSectionInfo& section_info,
+    const dchecked_vector<ProfileIndexType>& dex_profile_index_remap,
+    const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
+    /*out*/ std::string* error) {
+  DCHECK(section_info.GetType() == FileSectionType::kMethods);
+  SafeBuffer buffer;
+  ProfileLoadStatus status = ReadSectionData(source, section_info, &buffer, error);
+  if (status != ProfileLoadStatus::kSuccess) {
+    return status;
+  }
+
+  while (buffer.GetAvailableBytes() != 0u) {
+    ProfileIndexType profile_index;
+    if (!buffer.ReadUintAndAdvance(&profile_index)) {
+      *error = "Error profile index in methods section.";
+      return ProfileLoadStatus::kBadData;
+    }
+    if (profile_index >= dex_profile_index_remap.size()) {
+      *error = "Invalid profile index in methods section.";
+      return ProfileLoadStatus::kBadData;
+    }
+    profile_index = dex_profile_index_remap[profile_index];
+    if (profile_index == MaxProfileIndex()) {
+      status = DexFileData::SkipMethods(buffer, error);
+    } else {
+      status = info_[profile_index]->ReadMethods(buffer, extra_descriptors_remap, error);
+    }
+    if (status != ProfileLoadStatus::kSuccess) {
+      return status;
+    }
+  }
+  return ProfileLoadStatus::kSuccess;
+}
+
 // TODO(calin): fail fast if the dex checksums don't match.
 ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::LoadInternal(
-      int32_t fd,
-      std::string* error,
-      bool merge_classes,
-      const ProfileLoadFilterFn& filter_fn) {
+    int32_t fd,
+    std::string* error,
+    bool merge_classes,
+    const ProfileLoadFilterFn& filter_fn) {
   ScopedTrace trace(__PRETTY_FUNCTION__);
   DCHECK_GE(fd, 0);
 
   std::unique_ptr<ProfileSource> source;
   ProfileLoadStatus status = OpenSource(fd, &source, error);
-  if (status != kProfileLoadSuccess) {
+  if (status != ProfileLoadStatus::kSuccess) {
     return status;
   }
 
@@ -1306,29 +1690,58 @@
   // Profiles may be created by ActivityManager or installd before we manage to
   // process them in the runtime or profman.
   if (source->HasEmptyContent()) {
-    return kProfileLoadSuccess;
+    return ProfileLoadStatus::kSuccess;
   }
 
-  // Read profile header: magic + version + number_of_dex_files.
-  ProfileIndexType number_of_dex_files;
-  uint32_t uncompressed_data_size;
-  uint32_t compressed_data_size;
-  status = ReadProfileHeader(*source,
-                             &number_of_dex_files,
-                             &uncompressed_data_size,
-                             &compressed_data_size,
-                             error);
-
-  if (status != kProfileLoadSuccess) {
+  // Read file header.
+  FileHeader header;
+  status = source->Read(&header, sizeof(FileHeader), "ReadProfileHeader", error);
+  if (status != ProfileLoadStatus::kSuccess) {
     return status;
   }
+  if (!header.IsValid()) {
+    return header.InvalidHeaderMessage(error);
+  }
+  if (memcmp(header.GetVersion(), version_, kProfileVersionSize) != 0) {
+    *error = IsForBootImage() ? "Expected boot profile, got app profile."
+                              : "Expected app profile, got boot profile.";
+    return ProfileLoadStatus::kMergeError;
+  }
+
+  // Check if there are too many section infos.
+  uint32_t section_count = header.GetFileSectionCount();
+  uint32_t uncompressed_data_size = sizeof(FileHeader) + section_count * sizeof(FileSectionInfo);
+  if (uncompressed_data_size > GetSizeErrorThresholdBytes()) {
+    LOG(ERROR) << "Profile data size exceeds " << GetSizeErrorThresholdBytes()
+               << " bytes. It has " << uncompressed_data_size << " bytes.";
+    return ProfileLoadStatus::kBadData;
+  }
+
+  // Read section infos.
+  dchecked_vector<FileSectionInfo> section_infos(section_count);
+  status = source->Read(
+      section_infos.data(), section_count * sizeof(FileSectionInfo), "ReadSectionInfos", error);
+  if (status != ProfileLoadStatus::kSuccess) {
+    return status;
+  }
+
+  // Finish uncompressed data size calculation.
+  for (const FileSectionInfo& section_info : section_infos) {
+    uint32_t mem_size = section_info.GetMemSize();
+    if (UNLIKELY(mem_size > std::numeric_limits<uint32_t>::max() - uncompressed_data_size)) {
+      *error = "Total memory size overflow.";
+      return ProfileLoadStatus::kBadData;
+    }
+    uncompressed_data_size += mem_size;
+  }
+
   // Allow large profiles for non target builds for the case where we are merging many profiles
   // to generate a boot image profile.
   if (uncompressed_data_size > GetSizeErrorThresholdBytes()) {
     LOG(ERROR) << "Profile data size exceeds "
                << GetSizeErrorThresholdBytes()
                << " bytes. It has " << uncompressed_data_size << " bytes.";
-    return kProfileLoadBadData;
+    return ProfileLoadStatus::kBadData;
   }
   if (uncompressed_data_size > GetSizeWarningThresholdBytes()) {
     LOG(WARNING) << "Profile data size exceeds "
@@ -1336,172 +1749,61 @@
                  << " bytes. It has " << uncompressed_data_size << " bytes.";
   }
 
-  std::unique_ptr<uint8_t[]> compressed_data(new uint8_t[compressed_data_size]);
-  status = source->Read(compressed_data.get(), compressed_data_size, "ReadContent", error);
-  if (status != kProfileLoadSuccess) {
-    *error += "Unable to read compressed profile data";
+  // Process the mandatory dex files section.
+  DCHECK_NE(section_count, 0u);  // Checked by `header.IsValid()` above.
+  const FileSectionInfo& dex_files_section_info = section_infos[0];
+  if (dex_files_section_info.GetType() != FileSectionType::kDexFiles) {
+    *error = "First section is not dex files section.";
+    return ProfileLoadStatus::kBadData;
+  }
+  dchecked_vector<ProfileIndexType> dex_profile_index_remap;
+  status = ReadDexFilesSection(
+      *source, dex_files_section_info, filter_fn, &dex_profile_index_remap, error);
+  if (status != ProfileLoadStatus::kSuccess) {
+    DCHECK(!error->empty());
     return status;
   }
 
-  if (!source->HasConsumedAllData()) {
-    *error += "Unexpected data in the profile file.";
-    return kProfileLoadBadData;
-  }
-
-  SafeBuffer uncompressed_data(uncompressed_data_size);
-
-  int ret = InflateBuffer(compressed_data.get(),
-                          compressed_data_size,
-                          uncompressed_data_size,
-                          uncompressed_data.Get());
-
-  if (ret != Z_STREAM_END) {
-    *error += "Error reading uncompressed profile data";
-    return kProfileLoadBadData;
-  }
-
-  std::vector<ProfileLineHeader> profile_line_headers;
-  // Read profile line headers.
-  for (ProfileIndexType k = 0; k < number_of_dex_files; k++) {
-    ProfileLineHeader line_header;
-
-    // First, read the line header to get the amount of data we need to read.
-    status = ReadProfileLineHeader(uncompressed_data, &line_header, error);
-    if (status != kProfileLoadSuccess) {
+  // Process all other sections.
+  dchecked_vector<ExtraDescriptorIndex> extra_descriptors_remap;
+  for (uint32_t i = 1u; i != section_count; ++i) {
+    const FileSectionInfo& section_info = section_infos[i];
+    DCHECK(status == ProfileLoadStatus::kSuccess);
+    switch (section_info.GetType()) {
+      case FileSectionType::kDexFiles:
+        *error = "Unsupported additional dex files section.";
+        status = ProfileLoadStatus::kBadData;
+        break;
+      case FileSectionType::kExtraDescriptors:
+        status = ReadExtraDescriptorsSection(
+            *source, section_info, &extra_descriptors_remap, error);
+        break;
+      case FileSectionType::kClasses:
+        // Skip if all dex files were filtered out.
+        if (!info_.empty() && merge_classes) {
+          status = ReadClassesSection(
+              *source, section_info, dex_profile_index_remap, extra_descriptors_remap, error);
+        }
+        break;
+      case FileSectionType::kMethods:
+        // Skip if all dex files were filtered out.
+        if (!info_.empty()) {
+          status = ReadMethodsSection(
+              *source, section_info, dex_profile_index_remap, extra_descriptors_remap, error);
+        }
+        break;
+      default:
+        // Unknown section. Skip it. New versions of ART are allowed
+        // to add sections that shall be ignored by old versions.
+        break;
+    }
+    if (status != ProfileLoadStatus::kSuccess) {
+      DCHECK(!error->empty());
       return status;
     }
-    profile_line_headers.push_back(line_header);
   }
 
-  SafeMap<ProfileIndexType, ProfileIndexType> dex_profile_index_remap;
-  if (!RemapProfileIndex(profile_line_headers, filter_fn, &dex_profile_index_remap)) {
-    return kProfileLoadBadData;
-  }
-
-  for (ProfileIndexType k = 0; k < number_of_dex_files; k++) {
-    if (!filter_fn(profile_line_headers[k].profile_key, profile_line_headers[k].checksum)) {
-      // We have to skip the line. Advanced the current pointer of the buffer.
-      size_t profile_line_size =
-           profile_line_headers[k].class_set_size * sizeof(uint16_t) +
-           profile_line_headers[k].method_region_size_bytes +
-           DexFileData::ComputeBitmapStorage(IsForBootImage(),
-              profile_line_headers[k].num_method_ids);
-      uncompressed_data.Advance(profile_line_size);
-    } else {
-      // Now read the actual profile line.
-      status = ReadProfileLine(uncompressed_data,
-                               number_of_dex_files,
-                               profile_line_headers[k],
-                               dex_profile_index_remap,
-                               merge_classes,
-                               error);
-      if (status != kProfileLoadSuccess) {
-        return status;
-      }
-    }
-  }
-
-  // Check that we read everything and that profiles don't contain junk data.
-  if (uncompressed_data.CountUnreadBytes() > 0) {
-    *error = "Unexpected content in the profile file: " +
-        std::to_string(uncompressed_data.CountUnreadBytes()) + " extra bytes";
-    return kProfileLoadBadData;
-  } else {
-    return kProfileLoadSuccess;
-  }
-}
-
-bool ProfileCompilationInfo::RemapProfileIndex(
-    const std::vector<ProfileLineHeader>& profile_line_headers,
-    const ProfileLoadFilterFn& filter_fn,
-    /*out*/SafeMap<ProfileIndexType, ProfileIndexType>* dex_profile_index_remap) {
-  // First verify that all checksums match. This will avoid adding garbage to
-  // the current profile info.
-  // Note that the number of elements should be very small, so this should not
-  // be a performance issue.
-  for (const ProfileLineHeader& other_profile_line_header : profile_line_headers) {
-    if (!filter_fn(other_profile_line_header.profile_key, other_profile_line_header.checksum)) {
-      continue;
-    }
-    // verify_checksum is false because we want to differentiate between a missing dex data and
-    // a mismatched checksum.
-    const DexFileData* dex_data = FindDexData(other_profile_line_header.profile_key,
-                                              /* checksum= */ 0u,
-                                              /* verify_checksum= */ false);
-    if ((dex_data != nullptr) && (dex_data->checksum != other_profile_line_header.checksum)) {
-      LOG(WARNING) << "Checksum mismatch for dex " << other_profile_line_header.profile_key;
-      return false;
-    }
-  }
-  // All checksums match. Import the data.
-  uint32_t num_dex_files = static_cast<uint32_t>(profile_line_headers.size());
-  for (uint32_t i = 0; i < num_dex_files; i++) {
-    if (!filter_fn(profile_line_headers[i].profile_key, profile_line_headers[i].checksum)) {
-      continue;
-    }
-    const DexFileData* dex_data = GetOrAddDexFileData(profile_line_headers[i].profile_key,
-                                                      profile_line_headers[i].checksum,
-                                                      profile_line_headers[i].num_method_ids);
-    if (dex_data == nullptr) {
-      return false;  // Could happen if we exceed the number of allowed dex files.
-    }
-    dex_profile_index_remap->Put(i, dex_data->profile_index);
-  }
-  return true;
-}
-
-std::unique_ptr<uint8_t[]> ProfileCompilationInfo::DeflateBuffer(const uint8_t* in_buffer,
-                                                                 uint32_t in_size,
-                                                                 uint32_t* compressed_data_size) {
-  z_stream strm;
-  strm.zalloc = Z_NULL;
-  strm.zfree = Z_NULL;
-  strm.opaque = Z_NULL;
-  int ret = deflateInit(&strm, 1);
-  if (ret != Z_OK) {
-    return nullptr;
-  }
-
-  uint32_t out_size = deflateBound(&strm, in_size);
-
-  std::unique_ptr<uint8_t[]> compressed_buffer(new uint8_t[out_size]);
-  strm.avail_in = in_size;
-  strm.next_in = const_cast<uint8_t*>(in_buffer);
-  strm.avail_out = out_size;
-  strm.next_out = &compressed_buffer[0];
-  ret = deflate(&strm, Z_FINISH);
-  if (ret == Z_STREAM_ERROR) {
-    return nullptr;
-  }
-  *compressed_data_size = out_size - strm.avail_out;
-  deflateEnd(&strm);
-  return compressed_buffer;
-}
-
-int ProfileCompilationInfo::InflateBuffer(const uint8_t* in_buffer,
-                                          uint32_t in_size,
-                                          uint32_t expected_uncompressed_data_size,
-                                          uint8_t* out_buffer) {
-  z_stream strm;
-
-  /* allocate inflate state */
-  strm.zalloc = Z_NULL;
-  strm.zfree = Z_NULL;
-  strm.opaque = Z_NULL;
-  strm.avail_in = in_size;
-  strm.next_in = const_cast<uint8_t*>(in_buffer);
-  strm.avail_out = expected_uncompressed_data_size;
-  strm.next_out = out_buffer;
-
-  int ret;
-  inflateInit(&strm);
-  ret = inflate(&strm, Z_NO_FLUSH);
-
-  if (strm.avail_in != 0 || strm.avail_out != 0) {
-    return Z_DATA_ERROR;
-  }
-  inflateEnd(&strm);
-  return ret;
+  return ProfileLoadStatus::kSuccess;
 }
 
 bool ProfileCompilationInfo::MergeWith(const ProfileCompilationInfo& other,
@@ -1515,7 +1817,7 @@
   // the current profile info.
   // Note that the number of elements should be very small, so this should not
   // be a performance issue.
-  for (const DexFileData* other_dex_data : other.info_) {
+  for (const std::unique_ptr<DexFileData>& other_dex_data : other.info_) {
     // verify_checksum is false because we want to differentiate between a missing dex data and
     // a mismatched checksum.
     const DexFileData* dex_data = FindDexData(other_dex_data->profile_key,
@@ -1537,28 +1839,61 @@
   // and one from split-B.
 
   // First, build a mapping from other_dex_profile_index to this_dex_profile_index.
-  // This will make sure that the ClassReferences  will point to the correct dex file.
-  SafeMap<ProfileIndexType, ProfileIndexType> dex_profile_index_remap;
-  for (const DexFileData* other_dex_data : other.info_) {
+  dchecked_vector<ProfileIndexType> dex_profile_index_remap;
+  dex_profile_index_remap.reserve(other.info_.size());
+  for (const std::unique_ptr<DexFileData>& other_dex_data : other.info_) {
     const DexFileData* dex_data = GetOrAddDexFileData(other_dex_data->profile_key,
                                                       other_dex_data->checksum,
+                                                      other_dex_data->num_type_ids,
                                                       other_dex_data->num_method_ids);
     if (dex_data == nullptr) {
-      return false;  // Could happen if we exceed the number of allowed dex files.
+      // Could happen if we exceed the number of allowed dex files or there is
+      // a mismatch in `num_type_ids` or `num_method_ids`.
+      return false;
     }
-    dex_profile_index_remap.Put(other_dex_data->profile_index, dex_data->profile_index);
+    DCHECK_EQ(other_dex_data->profile_index, dex_profile_index_remap.size());
+    dex_profile_index_remap.push_back(dex_data->profile_index);
+  }
+
+  // Then merge extra descriptors.
+  dchecked_vector<ExtraDescriptorIndex> extra_descriptors_remap;
+  extra_descriptors_remap.reserve(other.extra_descriptors_.size());
+  for (const std::string& other_extra_descriptor : other.extra_descriptors_) {
+    auto it = extra_descriptors_indexes_.find(std::string_view(other_extra_descriptor));
+    if (it != extra_descriptors_indexes_.end()) {
+      extra_descriptors_remap.push_back(*it);
+    } else {
+      ExtraDescriptorIndex extra_descriptor_index = AddExtraDescriptor(other_extra_descriptor);
+      if (extra_descriptor_index == kMaxExtraDescriptors) {
+        // Too many extra descriptors.
+        return false;
+      }
+      extra_descriptors_remap.push_back(extra_descriptor_index);
+    }
   }
 
   // Merge the actual profile data.
-  for (const DexFileData* other_dex_data : other.info_) {
-    DexFileData* dex_data = const_cast<DexFileData*>(FindDexData(other_dex_data->profile_key,
-                                                                 other_dex_data->checksum));
-    DCHECK(dex_data != nullptr);
+  for (const std::unique_ptr<DexFileData>& other_dex_data : other.info_) {
+    DexFileData* dex_data = info_[dex_profile_index_remap[other_dex_data->profile_index]].get();
+    DCHECK_EQ(dex_data, FindDexData(other_dex_data->profile_key, other_dex_data->checksum));
 
     // Merge the classes.
+    uint32_t num_type_ids = dex_data->num_type_ids;
+    DCHECK_EQ(num_type_ids, other_dex_data->num_type_ids);
     if (merge_classes) {
-      dex_data->class_set.insert(other_dex_data->class_set.begin(),
-                                 other_dex_data->class_set.end());
+      // Classes are ordered by the `TypeIndex`, so we have the classes with a `TypeId`
+      // in the dex file first, followed by classes using extra descriptors.
+      auto it = other_dex_data->class_set.lower_bound(dex::TypeIndex(num_type_ids));
+      dex_data->class_set.insert(other_dex_data->class_set.begin(), it);
+      for (auto end = other_dex_data->class_set.end(); it != end; ++it) {
+        ExtraDescriptorIndex new_extra_descriptor_index =
+            extra_descriptors_remap[it->index_ - num_type_ids];
+        if (new_extra_descriptor_index >= DexFile::kDexNoIndex16 - num_type_ids) {
+          // Cannot represent the type with new extra descriptor index.
+          return false;
+        }
+        dex_data->class_set.insert(dex::TypeIndex(num_type_ids + new_extra_descriptor_index));
+      }
     }
 
     // Merge the methods and the inline caches.
@@ -1571,16 +1906,24 @@
       const auto& other_inline_cache = other_method_it.second;
       for (const auto& other_ic_it : other_inline_cache) {
         uint16_t other_dex_pc = other_ic_it.first;
-        const ClassSet& other_class_set = other_ic_it.second.classes;
+        const ArenaSet<dex::TypeIndex>& other_class_set = other_ic_it.second.classes;
         DexPcData* dex_pc_data = FindOrAddDexPc(inline_cache, other_dex_pc);
         if (other_ic_it.second.is_missing_types) {
           dex_pc_data->SetIsMissingTypes();
         } else if (other_ic_it.second.is_megamorphic) {
           dex_pc_data->SetIsMegamorphic();
         } else {
-          for (const auto& class_it : other_class_set) {
-            dex_pc_data->AddClass(dex_profile_index_remap.Get(
-                class_it.dex_profile_index), class_it.type_index);
+          for (dex::TypeIndex type_index : other_class_set) {
+            if (type_index.index_ >= num_type_ids) {
+              ExtraDescriptorIndex new_extra_descriptor_index =
+                  extra_descriptors_remap[type_index.index_ - num_type_ids];
+              if (new_extra_descriptor_index >= DexFile::kDexNoIndex16 - num_type_ids) {
+                // Cannot represent the type with new extra descriptor index.
+                return false;
+              }
+              type_index = dex::TypeIndex(num_type_ids + new_extra_descriptor_index);
+            }
+            dex_pc_data->AddClass(type_index);
           }
         }
       }
@@ -1602,28 +1945,6 @@
       : MethodHotness();
 }
 
-std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo>
-ProfileCompilationInfo::GetHotMethodInfo(const MethodReference& method_ref,
-                                         const ProfileSampleAnnotation& annotation) const {
-  MethodHotness hotness(GetMethodHotness(method_ref, annotation));
-  if (!hotness.IsHot()) {
-    return nullptr;
-  }
-  const InlineCacheMap* inline_caches = hotness.GetInlineCacheMap();
-  DCHECK(inline_caches != nullptr);
-  std::unique_ptr<OfflineProfileMethodInfo> pmi(new OfflineProfileMethodInfo(inline_caches));
-
-  pmi->dex_references.resize(info_.size());
-  for (const DexFileData* dex_data : info_) {
-    pmi->dex_references[dex_data->profile_index].profile_key = dex_data->profile_key;
-    pmi->dex_references[dex_data->profile_index].dex_checksum = dex_data->checksum;
-    pmi->dex_references[dex_data->profile_index].num_method_ids = dex_data->num_method_ids;
-  }
-
-  return pmi;
-}
-
-
 bool ProfileCompilationInfo::ContainsClass(const DexFile& dex_file,
                                            dex::TypeIndex type_idx,
                                            const ProfileSampleAnnotation& annotation) const {
@@ -1633,7 +1954,7 @@
 
 uint32_t ProfileCompilationInfo::GetNumberOfMethods() const {
   uint32_t total = 0;
-  for (const DexFileData* dex_data : info_) {
+  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
     total += dex_data->method_map.size();
   }
   return total;
@@ -1641,7 +1962,7 @@
 
 uint32_t ProfileCompilationInfo::GetNumberOfResolvedClasses() const {
   uint32_t total = 0;
-  for (const DexFileData* dex_data : info_) {
+  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
     total += dex_data->class_set.size();
   }
   return total;
@@ -1665,9 +1986,17 @@
     return os.str();
   }
 
+  if (!extra_descriptors_.empty()) {
+    os << "\nextra descriptors:";
+    for (const std::string& str : extra_descriptors_) {
+      os << "\n\t" << str;
+    }
+    os << "\n";
+  }
+
   const std::string kFirstDexFileKeySubstitute = "!classes.dex";
 
-  for (const DexFileData* dex_data : info_) {
+  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
     os << "\n";
     if (print_full_dex_location) {
       os << dex_data->profile_key;
@@ -1679,9 +2008,11 @@
     }
     os << " [index=" << static_cast<uint32_t>(dex_data->profile_index) << "]";
     os << " [checksum=" << std::hex << dex_data->checksum << "]" << std::dec;
+    os << " [num_type_ids=" << dex_data->num_type_ids << "]";
+    os << " [num_method_ids=" << dex_data->num_method_ids << "]";
     const DexFile* dex_file = nullptr;
     for (const DexFile* current : dex_files) {
-      if (GetBaseKeyFromAugmentedKey(dex_data->profile_key) == current->GetLocation() &&
+      if (GetBaseKeyViewFromAugmentedKey(dex_data->profile_key) == current->GetLocation() &&
           dex_data->checksum == current->GetLocationChecksum()) {
         dex_file = current;
       }
@@ -1702,9 +2033,10 @@
         } else if (inline_cache_it.second.is_megamorphic) {
           os << "MM";
         } else {
-          for (const ClassReference& class_ref : inline_cache_it.second.classes) {
-            os << "(" << static_cast<uint32_t>(class_ref.dex_profile_index)
-               << "," << class_ref.type_index.index_ << ")";
+          const char* separator = "";
+          for (dex::TypeIndex type_index : inline_cache_it.second.classes) {
+            os << separator << type_index.index_;
+            separator = ",";
           }
         }
         os << "}";
@@ -1730,11 +2062,11 @@
       startup = false;
     }
     os << "\n\tclasses: ";
-    for (const auto class_it : dex_data->class_set) {
+    for (dex::TypeIndex type_index : dex_data->class_set) {
       if (dex_file != nullptr) {
-        os << "\n\t\t" << dex_file->PrettyType(class_it);
+        os << "\n\t\t" << PrettyDescriptor(GetTypeDescriptor(dex_file, type_index));
       } else {
-        os << class_it.index_ << ",";
+        os << type_index.index_ << ",";
       }
     }
   }
@@ -1804,9 +2136,9 @@
   const std::string base_dex_location = "base.apk";
   ProfileCompilationInfo info;
   // The limits are defined by the dex specification.
-  const uint16_t max_method = std::numeric_limits<uint16_t>::max();
+  const uint16_t max_methods = std::numeric_limits<uint16_t>::max();
   const uint16_t max_classes = std::numeric_limits<uint16_t>::max();
-  uint16_t number_of_methods = max_method * method_percentage / 100;
+  uint16_t number_of_methods = max_methods * method_percentage / 100;
   uint16_t number_of_classes = max_classes * class_percentage / 100;
 
   std::srand(random_seed);
@@ -1820,9 +2152,10 @@
     std::string dex_location = DexFileLoader::GetMultiDexLocation(i, base_dex_location.c_str());
     std::string profile_key = info.GetProfileDexFileBaseKey(dex_location);
 
-    DexFileData* const data = info.GetOrAddDexFileData(profile_key, /*checksum=*/ 0, max_method);
+    DexFileData* const data =
+        info.GetOrAddDexFileData(profile_key, /*checksum=*/ 0, max_classes, max_methods);
     for (uint16_t m = 0; m < number_of_methods; m++) {
-      uint16_t method_idx = rand() % max_method;
+      uint16_t method_idx = rand() % max_methods;
       if (m < (number_of_methods / kFavorSplit)) {
         method_idx %= kFavorFirstN;
       }
@@ -1873,7 +2206,7 @@
     uint32_t classes_required_in_profile = (number_of_classes * class_percentage) / 100;
 
     DexFileData* const data = info.GetOrAddDexFileData(
-          profile_key, checksum, dex_file->NumMethodIds());
+          profile_key, checksum, dex_file->NumTypeIds(), dex_file->NumMethodIds());
     for (uint32_t class_index : create_shuffled_range(classes_required_in_profile,
                                                       number_of_classes)) {
       data->class_set.insert(dex_file->GetClassDef(class_index).class_idx_);
@@ -1894,114 +2227,12 @@
   return info.Save(fd);
 }
 
-bool ProfileCompilationInfo::OfflineProfileMethodInfo::operator==(
-      const OfflineProfileMethodInfo& other) const {
-  if (inline_caches->size() != other.inline_caches->size()) {
-    return false;
-  }
-
-  // We can't use a simple equality test because we need to match the dex files
-  // of the inline caches which might have different profile indexes.
-  for (const auto& inline_cache_it : *inline_caches) {
-    uint16_t dex_pc = inline_cache_it.first;
-    const DexPcData dex_pc_data = inline_cache_it.second;
-    const auto& other_it = other.inline_caches->find(dex_pc);
-    if (other_it == other.inline_caches->end()) {
-      return false;
-    }
-    const DexPcData& other_dex_pc_data = other_it->second;
-    if (dex_pc_data.is_megamorphic != other_dex_pc_data.is_megamorphic ||
-        dex_pc_data.is_missing_types != other_dex_pc_data.is_missing_types) {
-      return false;
-    }
-    for (const ClassReference& class_ref : dex_pc_data.classes) {
-      bool found = false;
-      for (const ClassReference& other_class_ref : other_dex_pc_data.classes) {
-        CHECK_LE(class_ref.dex_profile_index, dex_references.size());
-        CHECK_LE(other_class_ref.dex_profile_index, other.dex_references.size());
-        const DexReference& dex_ref = dex_references[class_ref.dex_profile_index];
-        const DexReference& other_dex_ref = other.dex_references[other_class_ref.dex_profile_index];
-        if (class_ref.type_index == other_class_ref.type_index &&
-            dex_ref == other_dex_ref) {
-          found = true;
-          break;
-        }
-      }
-      if (!found) {
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
-bool ProfileCompilationInfo::OfflineProfileMethodInfo::operator==(
-      const std::vector<ProfileMethodInfo::ProfileInlineCache>& runtime_caches) const {
-  if (inline_caches->size() != runtime_caches.size()) {
-    return false;
-  }
-
-  for (const auto& inline_cache_it : *inline_caches) {
-    uint16_t dex_pc = inline_cache_it.first;
-    const DexPcData dex_pc_data = inline_cache_it.second;
-
-    // Find the corresponding inline cahce.
-    const ProfileMethodInfo::ProfileInlineCache* runtime_cache = nullptr;
-    for (const ProfileMethodInfo::ProfileInlineCache& pic : runtime_caches) {
-      if (pic.dex_pc == dex_pc) {
-        runtime_cache = &pic;
-        break;
-      }
-    }
-    // If not found, returnb false.
-    if (runtime_cache == nullptr) {
-      return false;
-    }
-    // Check that the inline cache properties match up.
-    if (dex_pc_data.is_missing_types) {
-      if (!runtime_cache->is_missing_types) {
-        return false;
-      } else {
-        // If the inline cache is megamorphic do not check the classes (they don't matter).
-        continue;
-      }
-    }
-
-    if (dex_pc_data.is_megamorphic) {
-      if (runtime_cache->classes.size() < ProfileCompilationInfo::kIndividualInlineCacheSize) {
-        return false;
-      } else {
-        // If the inline cache is megamorphic do not check the classes (they don't matter).
-        continue;
-      }
-    }
-
-    if (dex_pc_data.classes.size() != runtime_cache->classes.size()) {
-      return false;
-    }
-    // Verify that all classes matches.
-    for (const ClassReference& class_ref : dex_pc_data.classes) {
-      bool found = false;
-      const DexReference& dex_ref = dex_references[class_ref.dex_profile_index];
-      for (const TypeReference& type_ref : runtime_cache->classes) {
-        if (class_ref.type_index == type_ref.TypeIndex() &&
-            dex_ref.MatchesDex(type_ref.dex_file)) {
-          found = true;
-          break;
-        }
-      }
-      if (!found) {
-        return false;
-      }
-    }
-  }
-  // If we didn't fail until now, then the two inline caches are equal.
-  return true;
-}
-
 bool ProfileCompilationInfo::IsEmpty() const {
-  DCHECK_EQ(info_.empty(), profile_key_map_.empty());
-  return info_.empty();
+  DCHECK_EQ(info_.size(), profile_key_map_.size());
+  // Note that this doesn't look at the bitmap region, so we will return true
+  // when the profile contains only non-hot methods. This is generally ok
+  // as for speed-profile to be useful we do need hot methods and resolved classes.
+  return GetNumberOfMethods() == 0 && GetNumberOfResolvedClasses() == 0;
 }
 
 ProfileCompilationInfo::InlineCacheMap*
@@ -2017,8 +2248,9 @@
 
 // Mark a method as executed at least once.
 bool ProfileCompilationInfo::DexFileData::AddMethod(MethodHotness::Flag flags, size_t index) {
-  if (index >= num_method_ids) {
-    LOG(ERROR) << "Invalid method index " << index << ". num_method_ids=" << num_method_ids;
+  if (index >= num_method_ids || index > kMaxSupportedMethodIndex) {
+    LOG(ERROR) << "Invalid method index " << index << ". num_method_ids=" << num_method_ids
+        << ", max: " << kMaxSupportedMethodIndex;
     return false;
   }
 
@@ -2031,9 +2263,8 @@
   return true;
 }
 
-void ProfileCompilationInfo::DexFileData::SetMethodHotness(size_t index,
-                                                           MethodHotness::Flag flags) {
-  DCHECK_LT(index, num_method_ids);
+template <typename Fn>
+ALWAYS_INLINE void ProfileCompilationInfo::DexFileData::ForMethodBitmapHotnessFlags(Fn fn) const {
   uint32_t lastFlag = is_for_boot_image
       ? MethodHotness::kFlagLastBoot
       : MethodHotness::kFlagLastRegular;
@@ -2043,28 +2274,30 @@
       // We store the hotness by recording the method in the method list.
       continue;
     }
+    fn(enum_cast<MethodHotness::Flag>(flag));
+  }
+}
+
+void ProfileCompilationInfo::DexFileData::SetMethodHotness(size_t index,
+                                                           MethodHotness::Flag flags) {
+  DCHECK_LT(index, num_method_ids);
+  ForMethodBitmapHotnessFlags([&](MethodHotness::Flag flag) {
     if ((flags & flag) != 0) {
       method_bitmap.StoreBit(MethodFlagBitmapIndex(
           static_cast<MethodHotness::Flag>(flag), index), /*value=*/ true);
     }
-  }
+  });
 }
 
 ProfileCompilationInfo::MethodHotness ProfileCompilationInfo::DexFileData::GetHotnessInfo(
     uint32_t dex_method_index) const {
   MethodHotness ret;
-  uint32_t lastFlag = is_for_boot_image
-      ? MethodHotness::kFlagLastBoot
-      : MethodHotness::kFlagLastRegular;
-  for (uint32_t flag = MethodHotness::kFlagFirst; flag <= lastFlag; flag = flag << 1) {
-    if (flag == MethodHotness::kFlagHot) {
-      continue;
-    }
+  ForMethodBitmapHotnessFlags([&](MethodHotness::Flag flag) {
     if (method_bitmap.LoadBit(MethodFlagBitmapIndex(
           static_cast<MethodHotness::Flag>(flag), dex_method_index))) {
       ret.AddFlag(static_cast<MethodHotness::Flag>(flag));
     }
-  }
+  });
   auto it = method_map.find(dex_method_index);
   if (it != method_map.end()) {
     ret.SetInlineCacheMap(&it->second);
@@ -2110,9 +2343,20 @@
   return WhichPowerOf2(static_cast<uint32_t>(flag)) - 1;
 }
 
+uint16_t ProfileCompilationInfo::DexFileData::GetUsedBitmapFlags() const {
+  uint32_t used_flags = 0u;
+  ForMethodBitmapHotnessFlags([&](MethodHotness::Flag flag) {
+    size_t index = FlagBitmapIndex(static_cast<MethodHotness::Flag>(flag));
+    if (method_bitmap.HasSomeBitSet(index * num_method_ids, num_method_ids)) {
+      used_flags |= flag;
+    }
+  });
+  return dchecked_integral_cast<uint16_t>(used_flags);
+}
+
 ProfileCompilationInfo::DexPcData*
 ProfileCompilationInfo::FindOrAddDexPc(InlineCacheMap* inline_cache, uint32_t dex_pc) {
-  return &(inline_cache->FindOrAdd(dex_pc, DexPcData(&allocator_))->second);
+  return &(inline_cache->FindOrAdd(dex_pc, DexPcData(inline_cache->get_allocator()))->second);
 }
 
 HashSet<std::string> ProfileCompilationInfo::GetClassDescriptors(
@@ -2123,14 +2367,7 @@
     const DexFileData* data = FindDexDataUsingAnnotations(dex_file, annotation);
     if (data != nullptr) {
       for (dex::TypeIndex type_idx : data->class_set) {
-        if (!dex_file->IsTypeIndexValid(type_idx)) {
-          // Something went bad. The profile is probably corrupted. Abort and return an emtpy set.
-          LOG(WARNING) << "Corrupted profile: invalid type index "
-              << type_idx.index_ << " in dex " << dex_file->GetLocation();
-          return HashSet<std::string>();
-        }
-        const dex::TypeId& type_id = dex_file->GetTypeId(type_idx);
-        ret.insert(dex_file->GetTypeDescriptor(type_id));
+        ret.insert(GetTypeDescriptor(dex_file, type_idx));
       }
     } else {
       VLOG(compiler) << "Failed to find profile data for " << dex_file->GetLocation();
@@ -2155,7 +2392,7 @@
   // The files is not empty. Check if it contains the profile magic.
   size_t byte_count = sizeof(kProfileMagic);
   uint8_t buffer[sizeof(kProfileMagic)];
-  if (!android::base::ReadFully(fd, buffer, byte_count)) {
+  if (!android::base::ReadFullyAtOffset(fd, buffer, byte_count, /*offset=*/ 0)) {
     return false;
   }
 
@@ -2172,9 +2409,10 @@
 bool ProfileCompilationInfo::UpdateProfileKeys(
       const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
   for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
-    for (DexFileData* dex_data : info_) {
-      if (dex_data->checksum == dex_file->GetLocationChecksum()
-          && dex_data->num_method_ids == dex_file->NumMethodIds()) {
+    for (const std::unique_ptr<DexFileData>& dex_data : info_) {
+      if (dex_data->checksum == dex_file->GetLocationChecksum() &&
+          dex_data->num_type_ids == dex_file->NumTypeIds() &&
+          dex_data->num_method_ids == dex_file->NumMethodIds()) {
         std::string new_profile_key = GetProfileDexFileBaseKey(dex_file->GetLocation());
         std::string dex_data_base_key = GetBaseKeyFromAugmentedKey(dex_data->profile_key);
         if (dex_data_base_key != new_profile_key) {
@@ -2187,9 +2425,8 @@
           profile_key_map_.erase(dex_data->profile_key);
           // Retain the annotation (if any) during the renaming by re-attaching the info
           // form the old key.
-          profile_key_map_.Put(MigrateAnnotationInfo(new_profile_key, dex_data->profile_key),
-                               dex_data->profile_index);
-          dex_data->profile_key = new_profile_key;
+          dex_data->profile_key = MigrateAnnotationInfo(new_profile_key, dex_data->profile_key);
+          profile_key_map_.Put(dex_data->profile_key, dex_data->profile_index);
         }
       }
     }
@@ -2204,11 +2441,10 @@
 }
 
 void ProfileCompilationInfo::ClearData() {
-  for (DexFileData* data : info_) {
-    delete data;
-  }
-  info_.clear();
   profile_key_map_.clear();
+  info_.clear();
+  extra_descriptors_indexes_.clear();
+  extra_descriptors_.clear();
 }
 
 void ProfileCompilationInfo::ClearDataAndAdjustVersion(bool for_boot_image) {
@@ -2226,10 +2462,396 @@
   return version_;
 }
 
-bool ProfileCompilationInfo::DexFileData::ContainsClass(const dex::TypeIndex type_index) const {
+bool ProfileCompilationInfo::DexFileData::ContainsClass(dex::TypeIndex type_index) const {
   return class_set.find(type_index) != class_set.end();
 }
 
+uint32_t ProfileCompilationInfo::DexFileData::ClassesDataSize() const {
+  return class_set.empty()
+      ? 0u
+      : sizeof(ProfileIndexType) +            // Which dex file.
+        sizeof(uint16_t) +                    // Number of classes.
+        sizeof(uint16_t) * class_set.size();  // Type index diffs.
+}
+
+void ProfileCompilationInfo::DexFileData::WriteClasses(SafeBuffer& buffer) const {
+  if (class_set.empty()) {
+    return;
+  }
+  buffer.WriteUintAndAdvance(profile_index);
+  buffer.WriteUintAndAdvance(dchecked_integral_cast<uint16_t>(class_set.size()));
+  WriteClassSet(buffer, class_set);
+}
+
+ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::DexFileData::ReadClasses(
+    SafeBuffer& buffer,
+    const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
+    std::string* error) {
+  uint16_t classes_size;
+  if (!buffer.ReadUintAndAdvance(&classes_size)) {
+    *error = "Error reading classes size.";
+    return ProfileLoadStatus::kBadData;
+  }
+  uint16_t num_valid_type_indexes = dchecked_integral_cast<uint16_t>(
+      std::min<size_t>(num_type_ids + extra_descriptors_remap.size(), DexFile::kDexNoIndex16));
+  uint16_t type_index = 0u;
+  for (size_t i = 0; i != classes_size; ++i) {
+    uint16_t type_index_diff;
+    if (!buffer.ReadUintAndAdvance(&type_index_diff)) {
+      *error = "Error reading class type index diff.";
+      return ProfileLoadStatus::kBadData;
+    }
+    if (type_index_diff == 0u && i != 0u) {
+      *error = "Duplicate type index.";
+      return ProfileLoadStatus::kBadData;
+    }
+    if (type_index_diff >= num_valid_type_indexes - type_index) {
+      *error = "Invalid type index.";
+      return ProfileLoadStatus::kBadData;
+    }
+    type_index += type_index_diff;
+    if (type_index >= num_type_ids) {
+      uint32_t new_extra_descriptor_index = extra_descriptors_remap[type_index - num_type_ids];
+      if (new_extra_descriptor_index >= DexFile::kDexNoIndex16 - num_type_ids) {
+        *error = "Remapped type index out of range.";
+        return ProfileLoadStatus::kMergeError;
+      }
+      type_index = num_type_ids + new_extra_descriptor_index;
+    }
+    class_set.insert(dex::TypeIndex(type_index));
+  }
+  return ProfileLoadStatus::kSuccess;
+}
+
+ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::DexFileData::SkipClasses(
+    SafeBuffer& buffer,
+    std::string* error) {
+  uint16_t classes_size;
+  if (!buffer.ReadUintAndAdvance(&classes_size)) {
+    *error = "Error reading classes size to skip.";
+    return ProfileLoadStatus::kBadData;
+  }
+  size_t following_data_size = static_cast<size_t>(classes_size) * sizeof(uint16_t);
+  if (following_data_size > buffer.GetAvailableBytes()) {
+    *error = "Classes data size to skip exceeds remaining data.";
+    return ProfileLoadStatus::kBadData;
+  }
+  buffer.Advance(following_data_size);
+  return ProfileLoadStatus::kSuccess;
+}
+
+uint32_t ProfileCompilationInfo::DexFileData::MethodsDataSize(
+    /*out*/ uint16_t* method_flags,
+    /*out*/ size_t* saved_bitmap_bit_size) const {
+  uint16_t local_method_flags = GetUsedBitmapFlags();
+  size_t local_saved_bitmap_bit_size = POPCOUNT(local_method_flags) * num_method_ids;
+  if (!method_map.empty()) {
+    local_method_flags |= enum_cast<uint16_t>(MethodHotness::kFlagHot);
+  }
+  size_t size = 0u;
+  if (local_method_flags != 0u) {
+    size_t num_hot_methods = method_map.size();
+    size_t num_dex_pc_entries = 0u;
+    size_t num_class_entries = 0u;
+    for (const auto& method_entry : method_map) {
+      const InlineCacheMap& inline_cache_map = method_entry.second;
+      num_dex_pc_entries += inline_cache_map.size();
+      for (const auto& inline_cache_entry : inline_cache_map) {
+        const DexPcData& dex_pc_data = inline_cache_entry.second;
+        num_class_entries += dex_pc_data.classes.size();
+      }
+    }
+
+    constexpr size_t kPerHotMethodSize =
+        sizeof(uint16_t) +  // Method index diff.
+        sizeof(uint16_t);   // Inline cache size.
+    constexpr size_t kPerDexPcEntrySize =
+        sizeof(uint16_t) +  // Dex PC.
+        sizeof(uint8_t);    // Number of inline cache classes.
+    constexpr size_t kPerClassEntrySize =
+        sizeof(uint16_t);   // Type index diff.
+
+    size_t saved_bitmap_byte_size = BitsToBytesRoundUp(local_saved_bitmap_bit_size);
+    size = sizeof(ProfileIndexType) +                 // Which dex file.
+           sizeof(uint32_t) +                         // Total size of following data.
+           sizeof(uint16_t) +                         // Method flags.
+           saved_bitmap_byte_size +                   // Bitmap data.
+           num_hot_methods * kPerHotMethodSize +      // Data for hot methods.
+           num_dex_pc_entries * kPerDexPcEntrySize +  // Data for dex pc entries.
+           num_class_entries * kPerClassEntrySize;    // Data for inline cache class entries.
+  }
+  if (method_flags != nullptr) {
+    *method_flags = local_method_flags;
+  }
+  if (saved_bitmap_bit_size != nullptr) {
+    *saved_bitmap_bit_size = local_saved_bitmap_bit_size;
+  }
+  return size;
+}
+
+void ProfileCompilationInfo::DexFileData::WriteMethods(SafeBuffer& buffer) const {
+  uint16_t method_flags;
+  size_t saved_bitmap_bit_size;
+  uint32_t methods_data_size = MethodsDataSize(&method_flags, &saved_bitmap_bit_size);
+  if (methods_data_size == 0u) {
+    return;  // No data to write.
+  }
+  DCHECK_GE(buffer.GetAvailableBytes(), methods_data_size);
+  uint32_t expected_available_bytes_at_end = buffer.GetAvailableBytes() - methods_data_size;
+
+  // Write the profile index.
+  buffer.WriteUintAndAdvance(profile_index);
+  // Write the total size of the following methods data (without the profile index
+  // and the total size itself) for easy skipping when the dex file is filtered out.
+  uint32_t following_data_size = methods_data_size - sizeof(ProfileIndexType) - sizeof(uint32_t);
+  buffer.WriteUintAndAdvance(following_data_size);
+  // Write the used method flags.
+  buffer.WriteUintAndAdvance(method_flags);
+
+  // Write the bitmap data.
+  size_t saved_bitmap_byte_size = BitsToBytesRoundUp(saved_bitmap_bit_size);
+  DCHECK_LE(saved_bitmap_byte_size, buffer.GetAvailableBytes());
+  BitMemoryRegion saved_bitmap(buffer.GetCurrentPtr(), /*bit_start=*/ 0, saved_bitmap_bit_size);
+  size_t saved_bitmap_index = 0u;
+  ForMethodBitmapHotnessFlags([&](MethodHotness::Flag flag) {
+    if ((method_flags & flag) != 0u) {
+      size_t index = FlagBitmapIndex(static_cast<MethodHotness::Flag>(flag));
+      BitMemoryRegion src = method_bitmap.Subregion(index * num_method_ids, num_method_ids);
+      saved_bitmap.StoreBits(saved_bitmap_index * num_method_ids, src, num_method_ids);
+      ++saved_bitmap_index;
+    }
+  });
+  DCHECK_EQ(saved_bitmap_index * num_method_ids, saved_bitmap_bit_size);
+  buffer.Advance(saved_bitmap_byte_size);
+
+  uint16_t last_method_index = 0;
+  for (const auto& method_entry : method_map) {
+    uint16_t method_index = method_entry.first;
+    const InlineCacheMap& inline_cache_map = method_entry.second;
+
+    // Store the difference between the method indices for better compression.
+    // The SafeMap is ordered by method_id, so the difference will always be non negative.
+    DCHECK_GE(method_index, last_method_index);
+    uint16_t diff_with_last_method_index = method_index - last_method_index;
+    last_method_index = method_index;
+    buffer.WriteUintAndAdvance(diff_with_last_method_index);
+
+    // Add inline cache map size.
+    buffer.WriteUintAndAdvance(dchecked_integral_cast<uint16_t>(inline_cache_map.size()));
+
+    // Add inline cache entries.
+    for (const auto& inline_cache_entry : inline_cache_map) {
+      uint16_t dex_pc = inline_cache_entry.first;
+      const DexPcData& dex_pc_data = inline_cache_entry.second;
+      const ArenaSet<dex::TypeIndex>& classes = dex_pc_data.classes;
+
+      // Add the dex pc.
+      buffer.WriteUintAndAdvance(dex_pc);
+
+      // Add the megamorphic/missing_types encoding if needed and continue.
+      // In either cases we don't add any classes to the profiles and so there's
+      // no point to continue.
+      // TODO: in case we miss types there is still value to add the rest of the
+      // classes. (This requires changing profile version or using a new section type.)
+      if (dex_pc_data.is_missing_types) {
+        // At this point the megamorphic flag should not be set.
+        DCHECK(!dex_pc_data.is_megamorphic);
+        DCHECK_EQ(classes.size(), 0u);
+        buffer.WriteUintAndAdvance(kIsMissingTypesEncoding);
+        continue;
+      } else if (dex_pc_data.is_megamorphic) {
+        DCHECK_EQ(classes.size(), 0u);
+        buffer.WriteUintAndAdvance(kIsMegamorphicEncoding);
+        continue;
+      }
+
+      DCHECK_LT(classes.size(), ProfileCompilationInfo::kIndividualInlineCacheSize);
+      DCHECK_NE(classes.size(), 0u) << "InlineCache contains a dex_pc with 0 classes";
+
+      // Add the number of classes for the dex PC.
+      buffer.WriteUintAndAdvance(dchecked_integral_cast<uint8_t>(classes.size()));
+      // Store the class set.
+      WriteClassSet(buffer, classes);
+    }
+  }
+
+  // Check if we've written the right number of bytes.
+  DCHECK_EQ(buffer.GetAvailableBytes(), expected_available_bytes_at_end);
+}
+
+ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::DexFileData::ReadMethods(
+    SafeBuffer& buffer,
+    const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
+    std::string* error) {
+  uint32_t following_data_size;
+  if (!buffer.ReadUintAndAdvance(&following_data_size)) {
+    *error = "Error reading methods data size.";
+    return ProfileLoadStatus::kBadData;
+  }
+  if (following_data_size > buffer.GetAvailableBytes()) {
+    *error = "Methods data size exceeds available data size.";
+    return ProfileLoadStatus::kBadData;
+  }
+  uint32_t expected_available_bytes_at_end = buffer.GetAvailableBytes() - following_data_size;
+
+  // Read method flags.
+  uint16_t method_flags;
+  if (!buffer.ReadUintAndAdvance(&method_flags)) {
+    *error = "Error reading method flags.";
+    return ProfileLoadStatus::kBadData;
+  }
+  if (!is_for_boot_image && method_flags >= (MethodHotness::kFlagLastRegular << 1)) {
+    // The profile we're loading contains data for boot image.
+    *error = "Method flags contain boot image profile flags for non-boot image profile.";
+    return ProfileLoadStatus::kBadData;
+  }
+
+  // Read method bitmap.
+  size_t saved_bitmap_bit_size = POPCOUNT(method_flags & ~MethodHotness::kFlagHot) * num_method_ids;
+  size_t saved_bitmap_byte_size = BitsToBytesRoundUp(saved_bitmap_bit_size);
+  if (sizeof(uint16_t) + saved_bitmap_byte_size > following_data_size) {
+    *error = "Insufficient available data for method bitmap.";
+    return ProfileLoadStatus::kBadData;
+  }
+  BitMemoryRegion saved_bitmap(buffer.GetCurrentPtr(), /*bit_start=*/ 0, saved_bitmap_bit_size);
+  size_t saved_bitmap_index = 0u;
+  ForMethodBitmapHotnessFlags([&](MethodHotness::Flag flag) {
+    if ((method_flags & flag) != 0u) {
+      size_t index = FlagBitmapIndex(static_cast<MethodHotness::Flag>(flag));
+      BitMemoryRegion src =
+          saved_bitmap.Subregion(saved_bitmap_index * num_method_ids, num_method_ids);
+      method_bitmap.OrBits(index * num_method_ids, src, num_method_ids);
+      ++saved_bitmap_index;
+    }
+  });
+  buffer.Advance(saved_bitmap_byte_size);
+
+  // Load hot methods.
+  if ((method_flags & MethodHotness::kFlagHot) != 0u) {
+    uint32_t num_valid_method_indexes =
+        std::min<uint32_t>(kMaxSupportedMethodIndex + 1u, num_method_ids);
+    uint16_t num_valid_type_indexes = dchecked_integral_cast<uint16_t>(
+        std::min<size_t>(num_type_ids + extra_descriptors_remap.size(), DexFile::kDexNoIndex16));
+    uint16_t method_index = 0;
+    bool first_diff = true;
+    while (buffer.GetAvailableBytes() > expected_available_bytes_at_end) {
+      uint16_t diff_with_last_method_index;
+      if (!buffer.ReadUintAndAdvance(&diff_with_last_method_index)) {
+        *error = "Error reading method index diff.";
+        return ProfileLoadStatus::kBadData;
+      }
+      if (diff_with_last_method_index == 0u && !first_diff) {
+        *error = "Duplicate method index.";
+        return ProfileLoadStatus::kBadData;
+      }
+      first_diff = false;
+      if (diff_with_last_method_index >= num_valid_method_indexes - method_index) {
+        *error = "Invalid method index.";
+        return ProfileLoadStatus::kBadData;
+      }
+      method_index += diff_with_last_method_index;
+      InlineCacheMap* inline_cache = FindOrAddHotMethod(method_index);
+      DCHECK(inline_cache != nullptr);
+
+      // Load inline cache map size.
+      uint16_t inline_cache_size;
+      if (!buffer.ReadUintAndAdvance(&inline_cache_size)) {
+        *error = "Error reading inline cache size.";
+        return ProfileLoadStatus::kBadData;
+      }
+      for (uint16_t ic_index = 0; ic_index != inline_cache_size; ++ic_index) {
+        // Load dex pc.
+        uint16_t dex_pc;
+        if (!buffer.ReadUintAndAdvance(&dex_pc)) {
+          *error = "Error reading inline cache dex pc.";
+          return ProfileLoadStatus::kBadData;
+        }
+        DexPcData* dex_pc_data = FindOrAddDexPc(inline_cache, dex_pc);
+        DCHECK(dex_pc_data != nullptr);
+
+        // Load inline cache classes.
+        uint8_t inline_cache_classes_size;
+        if (!buffer.ReadUintAndAdvance(&inline_cache_classes_size)) {
+          *error = "Error reading inline cache classes size.";
+          return ProfileLoadStatus::kBadData;
+        }
+        if (inline_cache_classes_size == kIsMissingTypesEncoding) {
+          dex_pc_data->SetIsMissingTypes();
+        } else if (inline_cache_classes_size == kIsMegamorphicEncoding) {
+          dex_pc_data->SetIsMegamorphic();
+        } else if (inline_cache_classes_size >= kIndividualInlineCacheSize) {
+          *error = "Inline cache size too large.";
+          return ProfileLoadStatus::kBadData;
+        } else {
+          uint16_t type_index = 0u;
+          for (size_t i = 0; i != inline_cache_classes_size; ++i) {
+            uint16_t type_index_diff;
+            if (!buffer.ReadUintAndAdvance(&type_index_diff)) {
+              *error = "Error reading inline cache type index diff.";
+              return ProfileLoadStatus::kBadData;
+            }
+            if (type_index_diff == 0u && i != 0u) {
+              *error = "Duplicate inline cache type index.";
+              return ProfileLoadStatus::kBadData;
+            }
+            if (type_index_diff >= num_valid_type_indexes - type_index) {
+              *error = "Invalid inline cache type index.";
+              return ProfileLoadStatus::kBadData;
+            }
+            type_index += type_index_diff;
+            if (type_index >= num_type_ids) {
+              ExtraDescriptorIndex new_extra_descriptor_index =
+                  extra_descriptors_remap[type_index - num_type_ids];
+              if (new_extra_descriptor_index >= DexFile::kDexNoIndex16 - num_type_ids) {
+                *error = "Remapped inline cache type index out of range.";
+                return ProfileLoadStatus::kMergeError;
+              }
+              type_index = num_type_ids + new_extra_descriptor_index;
+            }
+            dex_pc_data->AddClass(dex::TypeIndex(type_index));
+          }
+        }
+      }
+    }
+  }
+
+  if (buffer.GetAvailableBytes() != expected_available_bytes_at_end) {
+    *error = "Methods data did not end at expected position.";
+    return ProfileLoadStatus::kBadData;
+  }
+
+  return ProfileLoadStatus::kSuccess;
+}
+
+ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::DexFileData::SkipMethods(
+    SafeBuffer& buffer,
+    std::string* error) {
+  uint32_t following_data_size;
+  if (!buffer.ReadUintAndAdvance(&following_data_size)) {
+    *error = "Error reading methods data size to skip.";
+    return ProfileLoadStatus::kBadData;
+  }
+  if (following_data_size > buffer.GetAvailableBytes()) {
+    *error = "Methods data size to skip exceeds remaining data.";
+    return ProfileLoadStatus::kBadData;
+  }
+  buffer.Advance(following_data_size);
+  return ProfileLoadStatus::kSuccess;
+}
+
+void ProfileCompilationInfo::DexFileData::WriteClassSet(
+    SafeBuffer& buffer,
+    const ArenaSet<dex::TypeIndex>& class_set) {
+  // Store the difference between the type indexes for better compression.
+  uint16_t last_type_index = 0u;
+  for (const dex::TypeIndex& type_index : class_set) {
+    DCHECK_GE(type_index.index_, last_type_index);
+    uint16_t diff_with_last_type_index = type_index.index_ - last_type_index;
+    last_type_index = type_index.index_;
+    buffer.WriteUintAndAdvance(diff_with_last_type_index);
+  }
+}
+
 size_t ProfileCompilationInfo::GetSizeWarningThresholdBytes() const {
   return IsForBootImage() ?  kSizeWarningThresholdBootBytes : kSizeWarningThresholdBytes;
 }
@@ -2239,52 +2861,15 @@
 }
 
 std::ostream& operator<<(std::ostream& stream,
-                         const ProfileCompilationInfo::DexReference& dex_ref) {
-  stream << "[profile_key=" << dex_ref.profile_key
-         << ",dex_checksum=" << std::hex << dex_ref.dex_checksum << std::dec
-         << ",num_method_ids=" << dex_ref.num_method_ids
+                         ProfileCompilationInfo::DexReferenceDumper dumper) {
+  stream << "[profile_key=" << dumper.GetProfileKey()
+         << ",dex_checksum=" << std::hex << dumper.GetDexChecksum() << std::dec
+         << ",num_type_ids=" << dumper.GetNumTypeIds()
+         << ",num_method_ids=" << dumper.GetNumMethodIds()
          << "]";
   return stream;
 }
 
-bool ProfileCompilationInfo::ProfileSampleAnnotation::operator==(
-      const ProfileSampleAnnotation& other) const {
-  return origin_package_name_ == other.origin_package_name_;
-}
-
-void ProfileCompilationInfo::WriteProfileIndex(
-    std::vector<uint8_t>* buffer, ProfileIndexType value) const {
-  if (IsForBootImage()) {
-    AddUintToBuffer(buffer, value);
-  } else {
-    AddUintToBuffer(buffer, static_cast<ProfileIndexTypeRegular>(value));
-  }
-}
-
-bool ProfileCompilationInfo::ReadProfileIndex(
-    SafeBuffer& safe_buffer, ProfileIndexType* value) const {
-  if (IsForBootImage()) {
-    return safe_buffer.ReadUintAndAdvance<ProfileIndexType>(value);
-  } else {
-    ProfileIndexTypeRegular out;
-    bool result = safe_buffer.ReadUintAndAdvance<ProfileIndexTypeRegular>(&out);
-    *value = out;
-    return result;
-  }
-}
-
-ProfileCompilationInfo::ProfileIndexType ProfileCompilationInfo::MaxProfileIndex() const {
-  return IsForBootImage()
-      ? std::numeric_limits<ProfileIndexType>::max()
-      : std::numeric_limits<ProfileIndexTypeRegular>::max();
-}
-
-uint32_t ProfileCompilationInfo::SizeOfProfileIndexType() const {
-  return IsForBootImage()
-    ? sizeof(ProfileIndexType)
-    : sizeof(ProfileIndexTypeRegular);
-}
-
 FlattenProfileData::FlattenProfileData() :
     max_aggregation_for_methods_(0),
     max_aggregation_for_classes_(0) {
@@ -2341,6 +2926,12 @@
 
       // Check which classes from the current dex files are in the profile.
       for (const dex::TypeIndex& type_index : dex_data->class_set) {
+        if (type_index.index_ >= dex_file->NumTypeIds()) {
+          // Not a valid `dex::TypeIndex` for `TypeReference`.
+          // TODO: Rewrite the API to use descriptors or the `ProfileCompilationInfo` directly
+          // instead of the `FlattenProfileData` helper class.
+          continue;
+        }
         TypeReference ref(dex_file.get(), type_index);
         FlattenProfileData::ItemMetadata& metadata =
             result->class_metadata_.GetOrCreate(ref, create_metadata_fn);
diff --git a/libprofile/profile/profile_compilation_info.h b/libprofile/profile/profile_compilation_info.h
index 0b0c423..2061867 100644
--- a/libprofile/profile/profile_compilation_info.h
+++ b/libprofile/profile/profile_compilation_info.h
@@ -17,14 +17,18 @@
 #ifndef ART_LIBPROFILE_PROFILE_PROFILE_COMPILATION_INFO_H_
 #define ART_LIBPROFILE_PROFILE_PROFILE_COMPILATION_INFO_H_
 
+#include <array>
 #include <list>
 #include <set>
+#include <string_view>
 #include <vector>
 
 #include "base/arena_containers.h"
 #include "base/arena_object.h"
+#include "base/array_ref.h"
 #include "base/atomic.h"
 #include "base/bit_memory_region.h"
+#include "base/hash_map.h"
 #include "base/hash_set.h"
 #include "base/malloc_arena_pool.h"
 #include "base/mem_map.h"
@@ -44,12 +48,21 @@
   struct ProfileInlineCache {
     ProfileInlineCache(uint32_t pc,
                        bool missing_types,
-                       const std::vector<TypeReference>& profile_classes)
-        : dex_pc(pc), is_missing_types(missing_types), classes(profile_classes) {}
+                       const std::vector<TypeReference>& profile_classes,
+                       // Only used by profman for creating profiles from text
+                       bool megamorphic = false)
+        : dex_pc(pc),
+          is_missing_types(missing_types),
+          classes(profile_classes),
+          is_megamorphic(megamorphic) {}
 
     const uint32_t dex_pc;
     const bool is_missing_types;
+    // TODO: Replace `TypeReference` with `dex::TypeIndex` and allow artificial
+    // type indexes for types without a `dex::TypeId` in any dex file processed
+    // by the profman. See `ProfileCompilationInfo::FindOrCreateTypeIndex()`.
     const std::vector<TypeReference> classes;
+    const bool is_megamorphic;
   };
 
   explicit ProfileMethodInfo(MethodReference reference) : ref(reference) {}
@@ -85,51 +98,16 @@
   // This is exposed as public in order to make it available to dex2oat compilations
   // (see compiler/optimizing/inliner.cc).
 
-  // A profile reference to the dex file (profile key, dex checksum and number of methods).
-  struct DexReference {
-    DexReference() : dex_checksum(0), num_method_ids(0) {}
-
-    DexReference(const std::string& key, uint32_t checksum, uint32_t num_methods)
-        : profile_key(key), dex_checksum(checksum), num_method_ids(num_methods) {}
-
-    bool operator==(const DexReference& other) const {
-      return dex_checksum == other.dex_checksum &&
-          profile_key == other.profile_key &&
-          num_method_ids == other.num_method_ids;
-    }
-
-    bool MatchesDex(const DexFile* dex_file) const {
-      return dex_checksum == dex_file->GetLocationChecksum() &&
-           profile_key == GetProfileDexFileBaseKey(dex_file->GetLocation());
-    }
-
-    std::string profile_key;
-    uint32_t dex_checksum;
-    uint32_t num_method_ids;
-  };
-
-  // The types used to manipulate the profile index of dex files.
-  // They set an upper limit to how many dex files a given profile can recored.
-  //
-  // Boot profiles have more needs than regular profiles as they contain data from
-  // many apps merged together. As such they set the default type for data manipulation.
-  //
-  // Regular profiles don't record a lot of dex files, and use a smaller data type
-  // in order to save disk and ram.
-  //
-  // In-memory all profiles will use ProfileIndexType to represent the indices. However,
-  // when serialized, the profile type (boot or regular) will determine which data type
-  // is used to write the data.
+  // The type used to manipulate the profile index of dex files.
+  // It sets an upper limit to how many dex files a given profile can record.
   using ProfileIndexType = uint16_t;
-  using ProfileIndexTypeRegular = uint8_t;
 
   // Encodes a class reference in the profile.
   // The owning dex file is encoded as the index (dex_profile_index) it has in the
-  // profile rather than as a full DexRefence(location,checksum).
+  // profile rather than as a full reference (location, checksum).
   // This avoids excessive string copying when managing the profile data.
-  // The dex_profile_index is an index in either of:
-  //  - OfflineProfileMethodInfo#dex_references vector (public use)
-  //  - DexFileData#profile_index (internal use).
+  // The dex_profile_index is an index in the `DexFileData::profile_index` (internal use)
+  // and a matching dex file can found with `FindDexFileForProfileIndex()`.
   // Note that the dex_profile_index is not necessary the multidex index.
   // We cannot rely on the actual multidex index because a single profile may store
   // data from multiple splits. This means that a profile may contain a classes2.dex from split-A
@@ -151,18 +129,17 @@
     dex::TypeIndex type_index;  // the type index of the class
   };
 
-  // The set of classes that can be found at a given dex pc.
-  using ClassSet = ArenaSet<ClassReference>;
-
   // Encodes the actual inline cache for a given dex pc (whether or not the receiver is
   // megamorphic and its possible types).
   // If the receiver is megamorphic or is missing types the set of classes will be empty.
   struct DexPcData : public ArenaObject<kArenaAllocProfile> {
     explicit DexPcData(ArenaAllocator* allocator)
+        : DexPcData(allocator->Adapter(kArenaAllocProfile)) {}
+    explicit DexPcData(const ArenaAllocatorAdapter<void>& allocator)
         : is_missing_types(false),
           is_megamorphic(false),
-          classes(std::less<ClassReference>(), allocator->Adapter(kArenaAllocProfile)) {}
-    void AddClass(uint16_t dex_profile_idx, const dex::TypeIndex& type_idx);
+          classes(std::less<dex::TypeIndex>(), allocator) {}
+    void AddClass(const dex::TypeIndex& type_idx);
     void SetIsMegamorphic() {
       if (is_missing_types) return;
       is_megamorphic = true;
@@ -184,7 +161,7 @@
     // encoded. When types are missing this field will be set to true.
     bool is_missing_types;
     bool is_megamorphic;
-    ClassSet classes;
+    ArenaSet<dex::TypeIndex> classes;
   };
 
   // The inline cache map: DexPc -> DexPcData.
@@ -263,14 +240,14 @@
       return flags_ != 0;
     }
 
-   private:
-    const InlineCacheMap* inline_cache_map_ = nullptr;
-    uint32_t flags_ = 0;
-
     const InlineCacheMap* GetInlineCacheMap() const {
       return inline_cache_map_;
     }
 
+   private:
+    const InlineCacheMap* inline_cache_map_ = nullptr;
+    uint32_t flags_ = 0;
+
     void SetInlineCacheMap(const InlineCacheMap* info) {
       inline_cache_map_ = info;
     }
@@ -278,23 +255,6 @@
     friend class ProfileCompilationInfo;
   };
 
-  // Encodes the full set of inline caches for a given method.
-  // The dex_references vector is indexed according to the ClassReference::dex_profile_index.
-  // i.e. the dex file of any ClassReference present in the inline caches can be found at
-  // dex_references[ClassReference::dex_profile_index].
-  struct OfflineProfileMethodInfo {
-    explicit OfflineProfileMethodInfo(const InlineCacheMap* inline_cache_map)
-        : inline_caches(inline_cache_map) {}
-
-    bool operator==(const OfflineProfileMethodInfo& other) const;
-    // Checks that this offline representation of inline caches matches the runtime view of the
-    // data.
-    bool operator==(const std::vector<ProfileMethodInfo::ProfileInlineCache>& other) const;
-
-    const InlineCacheMap* const inline_caches;
-    std::vector<DexReference> dex_references;
-  };
-
   // Encapsulates metadata that can be associated with the methods and classes added to the profile.
   // The additional metadata is serialized in the profile and becomes part of the profile key
   // representation. It can be used to differentiate the samples that are added to the profile
@@ -307,7 +267,9 @@
 
     const std::string& GetOriginPackageName() const { return origin_package_name_; }
 
-    bool operator==(const ProfileSampleAnnotation& other) const;
+    bool operator==(const ProfileSampleAnnotation& other) const {
+      return origin_package_name_ == other.origin_package_name_;
+    }
 
     bool operator<(const ProfileSampleAnnotation& other) const {
       return origin_package_name_ < other.origin_package_name_;
@@ -322,6 +284,9 @@
     const std::string origin_package_name_;
   };
 
+  // Helper class for printing referenced dex file information to a stream.
+  struct DexReferenceDumper;
+
   // Public methods to create, extend or query the profile.
   ProfileCompilationInfo();
   explicit ProfileCompilationInfo(bool for_boot_image);
@@ -330,6 +295,20 @@
 
   ~ProfileCompilationInfo();
 
+  // Returns the maximum value for the profile index.
+  static constexpr ProfileIndexType MaxProfileIndex() {
+    return std::numeric_limits<ProfileIndexType>::max();
+  }
+
+  // Find or add a tracked dex file. Returns `MaxProfileIndex()` on failure, whether due to
+  // checksum/num_type_ids/num_method_ids mismatch or reaching the maximum number of dex files.
+  ProfileIndexType FindOrAddDexFile(
+      const DexFile& dex_file,
+      const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
+    DexFileData* data = GetOrAddDexFileData(&dex_file, annotation);
+    return (data != nullptr) ? data->profile_index : MaxProfileIndex();
+  }
+
   // Add the given methods to the current profile object.
   //
   // Note: if an annotation is provided, the methods/classes will be associated with the group
@@ -338,6 +317,61 @@
                   MethodHotness::Flag flags,
                   const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone);
 
+  // Find a type index in the `dex_file` if there is a `TypeId` for it. Otherwise,
+  // find or insert the descriptor in "extra descriptors" and return an artificial
+  // type index beyond `dex_file.NumTypeIds()`. This fails if the artificial index
+  // would be kDexNoIndex16 (0xffffu) or higher, returning an invalid type index.
+  // The returned type index can be used, if valid, for `AddClass()` or (TODO) as
+  // a type index for inline caches.
+  dex::TypeIndex FindOrCreateTypeIndex(const DexFile& dex_file, TypeReference class_ref);
+  dex::TypeIndex FindOrCreateTypeIndex(const DexFile& dex_file, const char* descriptor);
+
+  // Add a class with the specified `type_index` to the profile. The `type_index`
+  // can be either a normal index for a `TypeId` in the dex file, or an artificial
+  // type index created by `FindOrCreateTypeIndex()`.
+  void AddClass(ProfileIndexType profile_index, dex::TypeIndex type_index) {
+    DCHECK_LT(profile_index, info_.size());
+    DexFileData* const data = info_[profile_index].get();
+    DCHECK(type_index.IsValid());
+    DCHECK(type_index.index_ <= data->num_type_ids ||
+           type_index.index_ - data->num_type_ids < extra_descriptors_.size());
+    data->class_set.insert(type_index);
+  }
+
+  // Add a class with the specified `type_index` to the profile. The `type_index`
+  // can be either a normal index for a `TypeId` in the dex file, or an artificial
+  // type index created by `FindOrCreateTypeIndex()`.
+  // Returns `true` on success, `false` on failure.
+  bool AddClass(const DexFile& dex_file,
+                dex::TypeIndex type_index,
+                const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
+    DCHECK(type_index.IsValid());
+    DCHECK(type_index.index_ <= dex_file.NumTypeIds() ||
+           type_index.index_ - dex_file.NumTypeIds() < extra_descriptors_.size());
+    DexFileData* const data = GetOrAddDexFileData(&dex_file, annotation);
+    if (data == nullptr) {  // Checksum/num_type_ids/num_method_ids mismatch or too many dex files.
+      return false;
+    }
+    data->class_set.insert(type_index);
+    return true;
+  }
+
+  // Add a class with the specified `descriptor` to the profile.
+  // Returns `true` on success, `false` on failure.
+  bool AddClass(const DexFile& dex_file,
+                const char* descriptor,
+                const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone);
+  bool AddClass(const DexFile& dex_file,
+                const std::string& descriptor,
+                const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
+    return AddClass(dex_file, descriptor.c_str(), annotation);
+  }
+  bool AddClass(const DexFile& dex_file,
+                std::string_view descriptor,
+                const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
+    return AddClass(dex_file, std::string(descriptor).c_str(), annotation);
+  }
+
   // Add multiple type ids for classes in a single dex file. Iterator is for type_ids not
   // class_defs.
   //
@@ -356,6 +390,13 @@
     return true;
   }
 
+  void AddMethod(ProfileIndexType profile_index, uint32_t method_index, MethodHotness::Flag flags) {
+    DCHECK_LT(profile_index, info_.size());
+    DexFileData* const data = info_[profile_index].get();
+    DCHECK_LT(method_index, data->num_method_ids);
+    data->AddMethod(flags, method_index);
+  }
+
   // Add a method to the profile using its online representation (containing runtime structures).
   //
   // Note: see AddMethods docs for the handling of annotations.
@@ -411,7 +452,7 @@
   // - No class id exceeds NumTypeIds corresponding to the dex_file.
   // - For every inline_caches, class_ids does not exceed NumTypeIds corresponding to
   //   the dex_file they are in.
-  bool VerifyProfileData(const std::vector<const DexFile *> &dex_files);
+  bool VerifyProfileData(const std::vector<const DexFile*>& dex_files);
 
   // Load profile information from the given file
   // If the current profile is non-empty the load will fail.
@@ -433,6 +474,11 @@
   // Save the current profile into the given file. The file will be cleared before saving.
   bool Save(const std::string& filename, uint64_t* bytes_written);
 
+  // Return the number of dex files referenced in the profile.
+  size_t GetNumberOfDexFiles() const {
+    return info_.size();
+  }
+
   // Return the number of methods that were profiled.
   uint32_t GetNumberOfMethods() const;
 
@@ -460,15 +506,28 @@
       dex::TypeIndex type_idx,
       const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) const;
 
-  // Return the hot method info for the given location and index from the profiling info.
-  // If the method index is not found or the checksum doesn't match, null is returned.
-  // Note: the inline cache map is a pointer to the map stored in the profile and
-  // its allocation will go away if the profile goes out of scope.
-  //
-  // Note: see GetMethodHotness docs for the handling of annotations.
-  std::unique_ptr<OfflineProfileMethodInfo> GetHotMethodInfo(
-      const MethodReference& method_ref,
-      const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) const;
+  // Return the dex file for the given `profile_index`, or null if none of the provided
+  // dex files has a matching checksum and a location with the same base key.
+  template <typename Container>
+  const DexFile* FindDexFileForProfileIndex(ProfileIndexType profile_index,
+                                            const Container& dex_files) const {
+    static_assert(std::is_same_v<typename Container::value_type, const DexFile*> ||
+                  std::is_same_v<typename Container::value_type, std::unique_ptr<const DexFile>>);
+    DCHECK_LE(profile_index, info_.size());
+    const DexFileData* dex_file_data = info_[profile_index].get();
+    DCHECK(dex_file_data != nullptr);
+    uint32_t dex_checksum = dex_file_data->checksum;
+    std::string_view base_key = GetBaseKeyViewFromAugmentedKey(dex_file_data->profile_key);
+    for (const auto& dex_file : dex_files) {
+      if (dex_checksum == dex_file->GetLocationChecksum() &&
+          base_key == GetProfileDexFileBaseKeyView(dex_file->GetLocation())) {
+        return std::addressof(*dex_file);
+      }
+    }
+    return nullptr;
+  }
+
+  DexReferenceDumper DumpDexReference(ProfileIndexType profile_index) const;
 
   // Dump all the loaded profile info into a string and returns it.
   // If dex_files is not empty then the method indices will be resolved to their
@@ -525,10 +584,6 @@
                                   uint16_t class_percentage,
                                   uint32_t random_seed);
 
-  // Check that the given profile method info contain the same data.
-  static bool Equals(const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi1,
-                     const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi2);
-
   ArenaAllocator* GetAllocator() { return &allocator_; }
 
   // Return all of the class descriptors in the profile for a set of dex files.
@@ -569,6 +624,19 @@
   // Returns true if the profile is configured to store aggregation counters.
   bool IsForBootImage() const;
 
+  // Get type descriptor for a valid type index, whether a normal type index
+  // referencing a `dex::TypeId` in the dex file, or an artificial type index
+  // referencing an "extra descriptor".
+  const char* GetTypeDescriptor(const DexFile* dex_file, dex::TypeIndex type_index) const {
+    DCHECK(type_index.IsValid());
+    uint32_t num_type_ids = dex_file->NumTypeIds();
+    if (type_index.index_ < num_type_ids) {
+      return dex_file->StringByTypeIdx(type_index);
+    } else {
+      return extra_descriptors_[type_index.index_ - num_type_ids].c_str();
+    }
+  }
+
   // Return the version of this profile.
   const uint8_t* GetVersion() const;
 
@@ -582,25 +650,83 @@
       const std::vector<std::unique_ptr<const DexFile>>& dex_files) const;
 
  private:
-  enum ProfileLoadStatus {
-    kProfileLoadWouldOverwiteData,
-    kProfileLoadIOError,
-    kProfileLoadVersionMismatch,
-    kProfileLoadBadData,
-    kProfileLoadSuccess
+  // Helper classes.
+  class FileHeader;
+  class FileSectionInfo;
+  enum class FileSectionType : uint32_t;
+  enum class ProfileLoadStatus : uint32_t;
+  class ProfileSource;
+  class SafeBuffer;
+
+  // Extra descriptors are used to reference classes with `TypeIndex` between the dex
+  // file's `NumTypeIds()` and the `DexFile::kDexNoIndex16`. The range of usable
+  // extra descriptor indexes is therefore also limited by `DexFile::kDexNoIndex16`.
+  using ExtraDescriptorIndex = uint16_t;
+  static constexpr ExtraDescriptorIndex kMaxExtraDescriptors = DexFile::kDexNoIndex16;
+
+  class ExtraDescriptorIndexEmpty {
+   public:
+    void MakeEmpty(ExtraDescriptorIndex& index) const {
+      index = kMaxExtraDescriptors;
+    }
+    bool IsEmpty(const ExtraDescriptorIndex& index) const {
+      return index == kMaxExtraDescriptors;
+    }
   };
 
+  class ExtraDescriptorHash {
+   public:
+    explicit ExtraDescriptorHash(const dchecked_vector<std::string>* extra_descriptors)
+        : extra_descriptors_(extra_descriptors) {}
+
+    size_t operator()(const ExtraDescriptorIndex& index) const {
+      std::string_view str = (*extra_descriptors_)[index];
+      return (*this)(str);
+    }
+
+    size_t operator()(std::string_view str) const {
+      return DataHash()(str);
+    }
+
+   private:
+    const dchecked_vector<std::string>* extra_descriptors_;
+  };
+
+  class ExtraDescriptorEquals {
+   public:
+    explicit ExtraDescriptorEquals(const dchecked_vector<std::string>* extra_descriptors)
+        : extra_descriptors_(extra_descriptors) {}
+
+    size_t operator()(const ExtraDescriptorIndex& lhs, const ExtraDescriptorIndex& rhs) const {
+      DCHECK_EQ(lhs == rhs, (*this)(lhs, (*extra_descriptors_)[rhs]));
+      return lhs == rhs;
+    }
+
+    size_t operator()(const ExtraDescriptorIndex& lhs, std::string_view rhs_str) const {
+      std::string_view lhs_str = (*extra_descriptors_)[lhs];
+      return lhs_str == rhs_str;
+    }
+
+   private:
+    const dchecked_vector<std::string>* extra_descriptors_;
+  };
+
+  using ExtraDescriptorHashSet = HashSet<ExtraDescriptorIndex,
+                                         ExtraDescriptorIndexEmpty,
+                                         ExtraDescriptorHash,
+                                         ExtraDescriptorEquals>;
+
   // Internal representation of the profile information belonging to a dex file.
-  // Note that we could do without profile_key (the key used to encode the dex
-  // file in the profile) and profile_index (the index of the dex file in the
-  // profile) fields in this struct because we can infer them from
-  // profile_key_map_ and info_. However, it makes the profiles logic much
-  // simpler if we have references here as well.
+  // Note that we could do without the profile_index (the index of the dex file
+  // in the profile) field in this struct because we can infer it from
+  // `profile_key_map_` and `info_`. However, it makes the profiles logic much
+  // simpler if we have the profile index here as well.
   struct DexFileData : public DeletableArenaObject<kArenaAllocProfile> {
     DexFileData(ArenaAllocator* allocator,
                 const std::string& key,
                 uint32_t location_checksum,
                 uint16_t index,
+                uint32_t num_types,
                 uint32_t num_methods,
                 bool for_boot_image)
         : allocator_(allocator),
@@ -609,6 +735,7 @@
           checksum(location_checksum),
           method_map(std::less<uint16_t>(), allocator->Adapter(kArenaAllocProfile)),
           class_set(std::less<dex::TypeIndex>(), allocator->Adapter(kArenaAllocProfile)),
+          num_type_ids(num_types),
           num_method_ids(num_methods),
           bitmap_storage(allocator->Adapter(kArenaAllocProfile)),
           is_for_boot_image(for_boot_image) {
@@ -655,7 +782,24 @@
     void SetMethodHotness(size_t index, MethodHotness::Flag flags);
     MethodHotness GetHotnessInfo(uint32_t dex_method_index) const;
 
-    bool ContainsClass(const dex::TypeIndex type_index) const;
+    bool ContainsClass(dex::TypeIndex type_index) const;
+
+    uint32_t ClassesDataSize() const;
+    void WriteClasses(SafeBuffer& buffer) const;
+    ProfileLoadStatus ReadClasses(
+        SafeBuffer& buffer,
+        const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
+        std::string* error);
+    static ProfileLoadStatus SkipClasses(SafeBuffer& buffer, std::string* error);
+
+    uint32_t MethodsDataSize(/*out*/ uint16_t* method_flags = nullptr,
+                             /*out*/ size_t* saved_bitmap_bit_size = nullptr) const;
+    void WriteMethods(SafeBuffer& buffer) const;
+    ProfileLoadStatus ReadMethods(
+        SafeBuffer& buffer,
+        const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
+        std::string* error);
+    static ProfileLoadStatus SkipMethods(SafeBuffer& buffer, std::string* error);
 
     // The allocator used to allocate new inline cache maps.
     ArenaAllocator* const allocator_;
@@ -673,6 +817,8 @@
     // Find the inline caches of the the given method index. Add an empty entry if
     // no previous data is found.
     InlineCacheMap* FindOrAddHotMethod(uint16_t method_index);
+    // Num type ids.
+    uint32_t num_type_ids;
     // Num method ids.
     uint32_t num_method_ids;
     ArenaVector<uint8_t> bitmap_storage;
@@ -680,27 +826,31 @@
     bool is_for_boot_image;
 
    private:
+    template <typename Fn>
+    void ForMethodBitmapHotnessFlags(Fn fn) const;
+
+    static void WriteClassSet(SafeBuffer& buffer, const ArenaSet<dex::TypeIndex>& class_set);
     size_t MethodFlagBitmapIndex(MethodHotness::Flag flag, size_t method_index) const;
     static size_t FlagBitmapIndex(MethodHotness::Flag flag);
+
+    uint16_t GetUsedBitmapFlags() const;
   };
 
   // Return the profile data for the given profile key or null if the dex location
   // already exists but has a different checksum
   DexFileData* GetOrAddDexFileData(const std::string& profile_key,
                                    uint32_t checksum,
+                                   uint32_t num_type_ids,
                                    uint32_t num_method_ids);
 
   DexFileData* GetOrAddDexFileData(const DexFile* dex_file,
                                    const ProfileSampleAnnotation& annotation) {
     return GetOrAddDexFileData(GetProfileDexFileAugmentedKey(dex_file->GetLocation(), annotation),
                                dex_file->GetLocationChecksum(),
+                               dex_file->NumTypeIds(),
                                dex_file->NumMethodIds());
   }
 
-  // Encode the known dex_files into a vector. The index of a dex_reference will
-  // be the same as the profile index of the dex file (used to encode the ClassReferences).
-  void DexFileToProfileIndex(/*out*/std::vector<DexReference>* dex_references) const;
-
   // Return the dex data associated with the given profile key or null if the profile
   // doesn't contain the key.
   const DexFileData* FindDexData(const std::string& profile_key,
@@ -720,127 +870,47 @@
       const DexFile* dex_file,
       /*out*/ std::vector<const ProfileCompilationInfo::DexFileData*>* result) const;
 
-  // Inflate the input buffer (in_buffer) of size in_size. It returns a buffer of
-  // compressed data for the input buffer of "compressed_data_size" size.
-  std::unique_ptr<uint8_t[]> DeflateBuffer(const uint8_t* in_buffer,
-                                           uint32_t in_size,
-                                           /*out*/uint32_t* compressed_data_size);
-
-  // Inflate the input buffer(in_buffer) of size in_size. out_size is the expected output
-  // size of the buffer. It puts the output in out_buffer. It returns Z_STREAM_END on
-  // success. On error, it returns Z_STREAM_ERROR if the compressed data is inconsistent
-  // and Z_DATA_ERROR if the stream ended prematurely or the stream has extra data.
-  int InflateBuffer(const uint8_t* in_buffer,
-                    uint32_t in_size,
-                    uint32_t out_size,
-                    /*out*/uint8_t* out_buffer);
+  // Add a new extra descriptor. Returns kMaxExtraDescriptors on failure.
+  ExtraDescriptorIndex AddExtraDescriptor(std::string_view extra_descriptor);
 
   // Parsing functionality.
 
-  // The information present in the header of each profile line.
-  struct ProfileLineHeader {
-    std::string profile_key;
-    uint16_t class_set_size;
-    uint32_t method_region_size_bytes;
-    uint32_t checksum;
-    uint32_t num_method_ids;
-  };
-
-  /**
-   * Encapsulate the source of profile data for loading.
-   * The source can be either a plain file or a zip file.
-   * For zip files, the profile entry will be extracted to
-   * the memory map.
-   */
-  class ProfileSource {
-   public:
-    /**
-     * Create a profile source for the given fd. The ownership of the fd
-     * remains to the caller; as this class will not attempt to close it at any
-     * point.
-     */
-    static ProfileSource* Create(int32_t fd) {
-      DCHECK_GT(fd, -1);
-      return new ProfileSource(fd, MemMap::Invalid());
-    }
-
-    /**
-     * Create a profile source backed by a memory map. The map can be null in
-     * which case it will the treated as an empty source.
-     */
-    static ProfileSource* Create(MemMap&& mem_map) {
-      return new ProfileSource(/*fd*/ -1, std::move(mem_map));
-    }
-
-    /**
-     * Read bytes from this source.
-     * Reading will advance the current source position so subsequent
-     * invocations will read from the las position.
-     */
-    ProfileLoadStatus Read(uint8_t* buffer,
-                           size_t byte_count,
-                           const std::string& debug_stage,
-                           std::string* error);
-
-    /** Return true if the source has 0 data. */
-    bool HasEmptyContent() const;
-    /** Return true if all the information from this source has been read. */
-    bool HasConsumedAllData() const;
-
-   private:
-    ProfileSource(int32_t fd, MemMap&& mem_map)
-        : fd_(fd), mem_map_(std::move(mem_map)), mem_map_cur_(0) {}
-
-    bool IsMemMap() const { return fd_ == -1; }
-
-    int32_t fd_;  // The fd is not owned by this class.
-    MemMap mem_map_;
-    size_t mem_map_cur_;  // Current position in the map to read from.
-  };
-
-  // A helper structure to make sure we don't read past our buffers in the loops.
-  struct SafeBuffer {
-   public:
-    explicit SafeBuffer(size_t size) : storage_(new uint8_t[size]) {
-      ptr_current_ = storage_.get();
-      ptr_end_ = ptr_current_ + size;
-    }
-
-    // Reads the content of the descriptor at the current position.
-    ProfileLoadStatus Fill(ProfileSource& source,
-                           const std::string& debug_stage,
-                           /*out*/std::string* error);
-
-    // Reads an uint value (high bits to low bits) and advances the current pointer
-    // with the number of bits read.
-    template <typename T> bool ReadUintAndAdvance(/*out*/ T* value);
-
-    // Compares the given data with the content current pointer. If the contents are
-    // equal it advances the current pointer by data_size.
-    bool CompareAndAdvance(const uint8_t* data, size_t data_size);
-
-    // Advances current pointer by data_size.
-    void Advance(size_t data_size);
-
-    // Returns the count of unread bytes.
-    size_t CountUnreadBytes();
-
-    // Returns the current pointer.
-    const uint8_t* GetCurrentPtr();
-
-    // Get the underlying raw buffer.
-    uint8_t* Get() { return storage_.get(); }
-
-   private:
-    std::unique_ptr<uint8_t[]> storage_;
-    uint8_t* ptr_end_;
-    uint8_t* ptr_current_;
-  };
-
   ProfileLoadStatus OpenSource(int32_t fd,
                                /*out*/ std::unique_ptr<ProfileSource>* source,
                                /*out*/ std::string* error);
 
+  ProfileLoadStatus ReadSectionData(ProfileSource& source,
+                                    const FileSectionInfo& section_info,
+                                    /*out*/ SafeBuffer* buffer,
+                                    /*out*/ std::string* error);
+
+  ProfileLoadStatus ReadDexFilesSection(
+      ProfileSource& source,
+      const FileSectionInfo& section_info,
+      const ProfileLoadFilterFn& filter_fn,
+      /*out*/ dchecked_vector<ProfileIndexType>* dex_profile_index_remap,
+      /*out*/ std::string* error);
+
+  ProfileLoadStatus ReadExtraDescriptorsSection(
+      ProfileSource& source,
+      const FileSectionInfo& section_info,
+      /*out*/ dchecked_vector<ExtraDescriptorIndex>* extra_descriptors_remap,
+      /*out*/ std::string* error);
+
+  ProfileLoadStatus ReadClassesSection(
+      ProfileSource& source,
+      const FileSectionInfo& section_info,
+      const dchecked_vector<ProfileIndexType>& dex_profile_index_remap,
+      const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
+      /*out*/ std::string* error);
+
+  ProfileLoadStatus ReadMethodsSection(
+      ProfileSource& source,
+      const FileSectionInfo& section_info,
+      const dchecked_vector<ProfileIndexType>& dex_profile_index_remap,
+      const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
+      /*out*/ std::string* error);
+
   // Entry point for profile loading functionality.
   ProfileLoadStatus LoadInternal(
       int32_t fd,
@@ -848,77 +918,9 @@
       bool merge_classes = true,
       const ProfileLoadFilterFn& filter_fn = ProfileFilterFnAcceptAll);
 
-  // Read the profile header from the given fd and store the number of profile
-  // lines into number_of_dex_files.
-  ProfileLoadStatus ReadProfileHeader(ProfileSource& source,
-                                      /*out*/ProfileIndexType* number_of_dex_files,
-                                      /*out*/uint32_t* size_uncompressed_data,
-                                      /*out*/uint32_t* size_compressed_data,
-                                      /*out*/std::string* error);
-
-  // Read the header of a profile line from the given fd.
-  ProfileLoadStatus ReadProfileLineHeader(SafeBuffer& buffer,
-                                          /*out*/ProfileLineHeader* line_header,
-                                          /*out*/std::string* error);
-
-  // Read individual elements from the profile line header.
-  bool ReadProfileLineHeaderElements(SafeBuffer& buffer,
-                                     /*out*/uint16_t* dex_location_size,
-                                     /*out*/ProfileLineHeader* line_header,
-                                     /*out*/std::string* error);
-
-  // Read a single profile line from the given fd.
-  ProfileLoadStatus ReadProfileLine(
-      SafeBuffer& buffer,
-      ProfileIndexType number_of_dex_files,
-      const ProfileLineHeader& line_header,
-      const SafeMap<ProfileIndexType, ProfileIndexType>& dex_profile_index_remap,
-      bool merge_classes,
-      /*out*/std::string* error);
-
-  // Read all the classes from the buffer into the profile `info_` structure.
-  bool ReadClasses(SafeBuffer& buffer,
-                   const ProfileLineHeader& line_header,
-                   /*out*/std::string* error);
-
-  // Read all the methods from the buffer into the profile `info_` structure.
-  bool ReadMethods(SafeBuffer& buffer,
-                   ProfileIndexType number_of_dex_files,
-                   const ProfileLineHeader& line_header,
-                   const SafeMap<ProfileIndexType, ProfileIndexType>& dex_profile_index_remap,
-                   /*out*/std::string* error);
-
-  // The method generates mapping of profile indices while merging a new profile
-  // data into current data. It returns true, if the mapping was successful.
-  bool RemapProfileIndex(
-      const std::vector<ProfileLineHeader>& profile_line_headers,
-      const ProfileLoadFilterFn& filter_fn,
-      /*out*/SafeMap<ProfileIndexType, ProfileIndexType>* dex_profile_index_remap);
-
-  // Read the inline cache encoding from line_bufer into inline_cache.
-  bool ReadInlineCache(SafeBuffer& buffer,
-                       ProfileIndexType number_of_dex_files,
-                       const SafeMap<ProfileIndexType, ProfileIndexType>& dex_profile_index_remap,
-                       /*out*/InlineCacheMap* inline_cache,
-                       /*out*/std::string* error);
-
-  // Encode the inline cache into the given buffer.
-  void AddInlineCacheToBuffer(std::vector<uint8_t>* buffer,
-                              const InlineCacheMap& inline_cache);
-
-  // Return the number of bytes needed to encode the profile information
-  // for the methods in dex_data.
-  uint32_t GetMethodsRegionSize(const DexFileData& dex_data);
-
-  // Group `classes` by their owning dex profile index and put the result in
-  // `dex_to_classes_map`.
-  void GroupClassesByDex(
-      const ClassSet& classes,
-      /*out*/SafeMap<ProfileIndexType, std::vector<dex::TypeIndex>>* dex_to_classes_map);
-
   // Find the data for the dex_pc in the inline cache. Adds an empty entry
   // if no previous data exists.
-  DexPcData* FindOrAddDexPc(InlineCacheMap* inline_cache, uint32_t dex_pc);
+  static DexPcData* FindOrAddDexPc(InlineCacheMap* inline_cache, uint32_t dex_pc);
 
   // Initializes the profile version to the desired one.
   void InitProfileVersionInternal(const uint8_t version[]);
@@ -928,6 +930,13 @@
   // Returns the threshold size (in bytes) which will cause save/load failures.
   size_t GetSizeErrorThresholdBytes() const;
 
+  // Implementation of `GetProfileDexFileBaseKey()` but returning a subview
+  // referencing the same underlying data to avoid excessive heap allocations.
+  static std::string_view GetProfileDexFileBaseKeyView(std::string_view dex_location);
+
+  // Implementation of `GetBaseKeyFromAugmentedKey()` but returning a subview
+  // referencing the same underlying data to avoid excessive heap allocations.
+  static std::string_view GetBaseKeyViewFromAugmentedKey(std::string_view dex_location);
 
   // Returns the augmented profile key associated with the given dex location.
   // The return key will contain a serialized form of the information from the provided
@@ -940,18 +949,6 @@
   static std::string MigrateAnnotationInfo(const std::string& base_key,
                                            const std::string& augmented_key);
 
-  // Returns the maximum value for the profile index. It depends on the profile type.
-  // Boot profiles can store more dex files than regular profiles.
-  ProfileIndexType MaxProfileIndex() const;
-  // Returns the size of the profile index type used for serialization.
-  uint32_t SizeOfProfileIndexType() const;
-  // Writes the profile index to the buffer. The type of profile will determine the
-  // number of bytes used for serialization.
-  void WriteProfileIndex(std::vector<uint8_t>* buffer, ProfileIndexType value) const;
-  // Read the profile index from the buffer. The type of profile will determine the
-  // number of bytes used for serialization.
-  bool ReadProfileIndex(SafeBuffer& safe_buffer, ProfileIndexType* value) const;
-
   friend class ProfileCompilationInfoTest;
   friend class CompilerDriverProfileTest;
   friend class ProfileAssistantTest;
@@ -963,12 +960,17 @@
   // Vector containing the actual profile info.
   // The vector index is the profile index of the dex data and
   // matched DexFileData::profile_index.
-  ArenaVector<DexFileData*> info_;
+  ArenaVector<std::unique_ptr<DexFileData>> info_;
 
   // Cache mapping profile keys to profile index.
   // This is used to speed up searches since it avoids iterating
   // over the info_ vector when searching by profile key.
-  ArenaSafeMap<const std::string, ProfileIndexType> profile_key_map_;
+  // The backing storage for the `string_view` is the associated `DexFileData`.
+  ArenaSafeMap<const std::string_view, ProfileIndexType> profile_key_map_;
+
+  // Additional descriptors for referencing types not present in a dex files's `TypeId`s.
+  dchecked_vector<std::string> extra_descriptors_;
+  ExtraDescriptorHashSet extra_descriptors_indexes_;
 
   // The version of the profile.
   uint8_t version_[kProfileVersionSize];
@@ -1038,7 +1040,7 @@
   // Class data.
   SafeMap<TypeReference, ItemMetadata> class_metadata_;
   // Maximum aggregation counter for all methods.
-  // This is essentially a cache equal to the max size of any method's annation set.
+  // This is essentially a cache equal to the max size of any method's annotation set.
   // It avoids the traversal of all the methods which can be quite expensive.
   uint32_t max_aggregation_for_methods_;
   // Maximum aggregation counter for all classes.
@@ -1048,8 +1050,32 @@
   friend class ProfileCompilationInfo;
 };
 
-std::ostream& operator<<(std::ostream& stream,
-                         const ProfileCompilationInfo::DexReference& dex_ref);
+struct ProfileCompilationInfo::DexReferenceDumper {
+  const std::string& GetProfileKey() {
+    return dex_file_data->profile_key;
+  }
+
+  uint32_t GetDexChecksum() const {
+    return dex_file_data->checksum;
+  }
+
+  uint32_t GetNumTypeIds() const {
+    return dex_file_data->num_type_ids;
+  }
+
+  uint32_t GetNumMethodIds() const {
+    return dex_file_data->num_method_ids;
+  }
+
+  const DexFileData* dex_file_data;
+};
+
+inline ProfileCompilationInfo::DexReferenceDumper ProfileCompilationInfo::DumpDexReference(
+    ProfileIndexType profile_index) const {
+  return DexReferenceDumper{info_[profile_index].get()};
+}
+
+std::ostream& operator<<(std::ostream& stream, ProfileCompilationInfo::DexReferenceDumper dumper);
 
 }  // namespace art
 
diff --git a/libprofile/profile/profile_compilation_info_test.cc b/libprofile/profile/profile_compilation_info_test.cc
index d6ae8a2..8c9d0df 100644
--- a/libprofile/profile/profile_compilation_info_test.cc
+++ b/libprofile/profile/profile_compilation_info_test.cc
@@ -27,94 +27,43 @@
 #include "dex/method_reference.h"
 #include "dex/type_reference.h"
 #include "profile/profile_compilation_info.h"
+#include "profile/profile_test_helper.h"
 #include "ziparchive/zip_writer.h"
 
 namespace art {
 
-using Hotness = ProfileCompilationInfo::MethodHotness;
-using ProfileInlineCache = ProfileMethodInfo::ProfileInlineCache;
-using ProfileSampleAnnotation = ProfileCompilationInfo::ProfileSampleAnnotation;
-using ProfileIndexType = ProfileCompilationInfo::ProfileIndexType;
-using ProfileIndexTypeRegular = ProfileCompilationInfo::ProfileIndexTypeRegular;
 using ItemMetadata = FlattenProfileData::ItemMetadata;
 
-static constexpr size_t kMaxMethodIds = 65535;
-static uint32_t kMaxHotnessFlagBootIndex =
-    WhichPowerOf2(static_cast<uint32_t>(Hotness::kFlagLastBoot));
-static uint32_t kMaxHotnessFlagRegularIndex =
-    WhichPowerOf2(static_cast<uint32_t>(Hotness::kFlagLastRegular));
-
-class ProfileCompilationInfoTest : public CommonArtTest {
+class ProfileCompilationInfoTest : public CommonArtTest, public ProfileTestHelper {
  public:
   void SetUp() override {
     CommonArtTest::SetUp();
     allocator_.reset(new ArenaAllocator(&pool_));
 
-    dex1 = fake_dex_storage.AddFakeDex("location1", /* checksum= */ 1, /* num_method_ids= */ 10001);
-    dex2 = fake_dex_storage.AddFakeDex("location2", /* checksum= */ 2, /* num_method_ids= */ 10002);
-    dex3 = fake_dex_storage.AddFakeDex("location3", /* checksum= */ 3, /* num_method_ids= */ 10003);
-    dex4 = fake_dex_storage.AddFakeDex("location4", /* checksum= */ 4, /* num_method_ids= */ 10004);
+    dex1 = BuildDex("location1", /*checksum=*/ 1, "LUnique1;", /*num_method_ids=*/ 101);
+    dex2 = BuildDex("location2", /*checksum=*/ 2, "LUnique2;", /*num_method_ids=*/ 102);
+    dex3 = BuildDex("location3", /*checksum=*/ 3, "LUnique3;", /*num_method_ids=*/ 103);
+    dex4 = BuildDex("location4", /*checksum=*/ 4, "LUnique4;", /*num_method_ids=*/ 104);
 
-    dex1_checksum_missmatch = fake_dex_storage.AddFakeDex(
-        "location1", /* checksum= */ 12, /* num_method_ids= */ 10001);
-    dex1_renamed = fake_dex_storage.AddFakeDex(
-        "location1-renamed", /* checksum= */ 1, /* num_method_ids= */ 10001);
-    dex2_renamed = fake_dex_storage.AddFakeDex(
-        "location2-renamed", /* checksum= */ 2, /* num_method_ids= */ 10002);
-
-    dex_max_methods1 = fake_dex_storage.AddFakeDex(
-        "location-max1", /* checksum= */ 5, /* num_method_ids= */ kMaxMethodIds);
-    dex_max_methods2 = fake_dex_storage.AddFakeDex(
-        "location-max2", /* checksum= */ 6, /* num_method_ids= */ kMaxMethodIds);
+    dex1_checksum_missmatch =
+        BuildDex("location1", /*checksum=*/ 12, "LUnique1;", /*num_method_ids=*/ 101);
+    dex1_renamed =
+        BuildDex("location1-renamed", /*checksum=*/ 1, "LUnique1;", /*num_method_ids=*/ 101);
+    dex2_renamed =
+        BuildDex("location2-renamed", /*checksum=*/ 2, "LUnique2;", /*num_method_ids=*/ 102);
   }
 
  protected:
-  bool AddMethod(ProfileCompilationInfo* info,
-                 const DexFile* dex,
-                 uint16_t method_idx,
-                 Hotness::Flag flags = Hotness::kFlagHot,
-                 const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
-    return info->AddMethod(ProfileMethodInfo(MethodReference(dex, method_idx)),
-                           flags,
-                           annotation);
-  }
-
-  bool AddMethod(ProfileCompilationInfo* info,
-                const DexFile* dex,
-                uint16_t method_idx,
-                const std::vector<ProfileInlineCache>& inline_caches,
-                const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
-    return info->AddMethod(
-        ProfileMethodInfo(MethodReference(dex, method_idx), inline_caches),
-        Hotness::kFlagHot,
-        annotation);
-  }
-
-  bool AddClass(ProfileCompilationInfo* info,
-                const DexFile* dex,
-                dex::TypeIndex type_index,
-                const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
-    std::vector<dex::TypeIndex> classes = {type_index};
-    return info->AddClassesForDex(dex, classes.begin(), classes.end(), annotation);
-  }
-
   uint32_t GetFd(const ScratchFile& file) {
     return static_cast<uint32_t>(file.GetFd());
   }
 
-  std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> GetMethod(
+  ProfileCompilationInfo::MethodHotness GetMethod(
       const ProfileCompilationInfo& info,
       const DexFile* dex,
       uint16_t method_idx,
       const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
-    return info.GetHotMethodInfo(MethodReference(dex, method_idx), annotation);
-  }
-
-  // Creates an inline cache which will be destructed at the end of the test.
-  ProfileCompilationInfo::InlineCacheMap* CreateInlineCacheMap() {
-    used_inline_caches.emplace_back(new ProfileCompilationInfo::InlineCacheMap(
-        std::less<uint16_t>(), allocator_->Adapter(kArenaAllocProfile)));
-    return used_inline_caches.back().get();
+    return info.GetMethodHotness(MethodReference(dex, method_idx), annotation);
   }
 
   // Creates the default inline caches used in tests.
@@ -123,7 +72,7 @@
     // Monomorphic
     for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) {
       std::vector<TypeReference> types = {TypeReference(dex1, dex::TypeIndex(0))};
-      inline_caches.push_back(ProfileInlineCache(dex_pc, /* missing_types*/ false, types));
+      inline_caches.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ false, types));
     }
     // Polymorphic
     for (uint16_t dex_pc = 11; dex_pc < 22; dex_pc++) {
@@ -131,23 +80,24 @@
           TypeReference(dex1, dex::TypeIndex(0)),
           TypeReference(dex2, dex::TypeIndex(1)),
           TypeReference(dex3, dex::TypeIndex(2))};
-      inline_caches.push_back(ProfileInlineCache(dex_pc, /* missing_types*/ false, types));
+      inline_caches.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ false, types));
     }
     // Megamorphic
     for (uint16_t dex_pc = 22; dex_pc < 33; dex_pc++) {
-      // we need 5 types to make the cache megamorphic
+      // We need 5 types to make the cache megamorphic.
+      // The `is_megamorphic` flag shall be `false`; it is not used for testing.
       std::vector<TypeReference> types = {
           TypeReference(dex1, dex::TypeIndex(0)),
           TypeReference(dex1, dex::TypeIndex(1)),
           TypeReference(dex1, dex::TypeIndex(2)),
           TypeReference(dex1, dex::TypeIndex(3)),
           TypeReference(dex1, dex::TypeIndex(4))};
-      inline_caches.push_back(ProfileInlineCache(dex_pc, /* missing_types*/ false, types));
+      inline_caches.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ false, types));
     }
     // Missing types
     for (uint16_t dex_pc = 33; dex_pc < 44; dex_pc++) {
       std::vector<TypeReference> types;
-      inline_caches.push_back(ProfileInlineCache(dex_pc, /* missing_types*/ true, types));
+      inline_caches.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ true, types));
     }
 
     return inline_caches;
@@ -180,16 +130,15 @@
     ScratchFile profile;
     ProfileCompilationInfo saved_info;
     for (uint16_t i = 0; i < 10; i++) {
-      ASSERT_TRUE(AddMethod(&saved_info, dex1, /* method_idx= */ i));
-      ASSERT_TRUE(AddMethod(&saved_info, dex2, /* method_idx= */ i));
+      ASSERT_TRUE(AddMethod(&saved_info, dex1, /*method_idx=*/ i));
+      ASSERT_TRUE(AddMethod(&saved_info, dex2, /*method_idx=*/ i));
     }
     ASSERT_TRUE(saved_info.Save(GetFd(profile)));
     ASSERT_EQ(0, profile.GetFile()->Flush());
 
     // Prepare the profile content for zipping.
-    ASSERT_TRUE(profile.GetFile()->ResetOffset());
     std::vector<uint8_t> data(profile.GetFile()->GetLength());
-    ASSERT_TRUE(profile.GetFile()->ReadFully(data.data(), data.size()));
+    ASSERT_TRUE(profile.GetFile()->PreadFully(data.data(), data.size(), /*offset=*/ 0));
 
     // Zip the profile content.
     ScratchFile zip;
@@ -204,7 +153,6 @@
 
     // Verify loading from the zip archive.
     ProfileCompilationInfo loaded_info;
-    ASSERT_TRUE(zip.GetFile()->ResetOffset());
     ASSERT_EQ(should_succeed, loaded_info.Load(zip.GetFile()->GetPath(), false));
     if (should_succeed) {
       if (should_succeed_with_empty_profile) {
@@ -220,15 +168,14 @@
   }
 
   void SizeStressTest(bool random) {
-    ProfileCompilationInfo boot_profile(/*for_boot_image*/ true);
-    ProfileCompilationInfo reg_profile(/*for_boot_image*/ false);
+    ProfileCompilationInfo boot_profile(/*for_boot_image=*/ true);
+    ProfileCompilationInfo reg_profile(/*for_boot_image=*/ false);
 
     static constexpr size_t kNumDexFiles = 5;
 
-    FakeDexStorage local_storage;
     std::vector<const DexFile*> dex_files;
     for (uint32_t i = 0; i < kNumDexFiles; i++) {
-      dex_files.push_back(local_storage.AddFakeDex(std::to_string(i), i, kMaxMethodIds));
+      dex_files.push_back(BuildDex(std::to_string(i), i, "LC;", kMaxMethodIds));
     }
 
     std::srand(0);
@@ -261,15 +208,20 @@
 
     ASSERT_TRUE(boot_profile.Save(GetFd(boot_file)));
     ASSERT_TRUE(reg_profile.Save(GetFd(reg_file)));
-    ASSERT_TRUE(boot_file.GetFile()->ResetOffset());
-    ASSERT_TRUE(reg_file.GetFile()->ResetOffset());
 
-    ProfileCompilationInfo loaded_boot;
+    ProfileCompilationInfo loaded_boot(/*for_boot_image=*/ true);
     ProfileCompilationInfo loaded_reg;
     ASSERT_TRUE(loaded_boot.Load(GetFd(boot_file)));
     ASSERT_TRUE(loaded_reg.Load(GetFd(reg_file)));
   }
 
+  static constexpr size_t kMaxMethodIds = 65535;
+  static constexpr size_t kMaxClassIds = 65535;
+  static constexpr uint32_t kMaxHotnessFlagBootIndex =
+      WhichPowerOf2(static_cast<uint32_t>(Hotness::kFlagLastBoot));
+  static constexpr uint32_t kMaxHotnessFlagRegularIndex =
+      WhichPowerOf2(static_cast<uint32_t>(Hotness::kFlagLastRegular));
+
   // Cannot sizeof the actual arrays so hard code the values here.
   // They should not change anyway.
   static constexpr int kProfileMagicSize = 4;
@@ -285,40 +237,68 @@
   const DexFile* dex1_checksum_missmatch;
   const DexFile* dex1_renamed;
   const DexFile* dex2_renamed;
-  const DexFile* dex_max_methods1;
-  const DexFile* dex_max_methods2;
 
   // Cache of inline caches generated during tests.
   // This makes it easier to pass data between different utilities and ensure that
   // caches are destructed at the end of the test.
   std::vector<std::unique_ptr<ProfileCompilationInfo::InlineCacheMap>> used_inline_caches;
-
-  FakeDexStorage fake_dex_storage;
 };
 
+TEST_F(ProfileCompilationInfoTest, AddClasses) {
+  ProfileCompilationInfo info;
+
+  // Add all classes with a `TypeId` in `dex1`.
+  uint32_t num_type_ids1 = dex1->NumTypeIds();
+  for (uint32_t type_index = 0; type_index != num_type_ids1; ++type_index) {
+    ASSERT_TRUE(info.AddClass(*dex1, dex::TypeIndex(type_index)));
+  }
+  // Add classes without `TypeId` in `dex1`.
+  for (uint32_t type_index = num_type_ids1; type_index != DexFile::kDexNoIndex16; ++type_index) {
+    std::string descriptor = "LX" + std::to_string(type_index) + ";";
+    ASSERT_TRUE(info.AddClass(*dex1, descriptor));
+  }
+  // Fail to add another class without `TypeId` in `dex1` as we have
+  // run out of available artificial type indexes.
+  ASSERT_FALSE(info.AddClass(*dex1, "LCannotAddThis;"));
+
+  // Add all classes with a `TypeId` in `dex2`.
+  uint32_t num_type_ids2 = dex2->NumTypeIds();
+  for (uint32_t type_index = 0; type_index != num_type_ids2; ++type_index) {
+    ASSERT_TRUE(info.AddClass(*dex2, dex::TypeIndex(type_index)));
+  }
+  // Fail to add another class without `TypeId` in `dex2` as we have
+  // run out of available artificial type indexes when adding types for `dex1`.
+  ASSERT_FALSE(info.AddClass(*dex2, "LCannotAddThis;"));
+  // Add classes without `TypeId` in `dex2` for which we already have articial indexes.
+  ASSERT_EQ(num_type_ids1, num_type_ids2);
+  for (uint32_t type_index = num_type_ids2; type_index != DexFile::kDexNoIndex16; ++type_index) {
+    std::string descriptor = "LX" + std::to_string(type_index) + ";";
+    ASSERT_TRUE(info.AddClass(*dex2, descriptor));
+  }
+}
+
 TEST_F(ProfileCompilationInfoTest, SaveFd) {
   ScratchFile profile;
 
   ProfileCompilationInfo saved_info;
   // Save a few methods.
   for (uint16_t i = 0; i < 10; i++) {
-    ASSERT_TRUE(AddMethod(&saved_info, dex1, /* method_idx= */ i));
-    ASSERT_TRUE(AddMethod(&saved_info, dex2, /* method_idx= */ i));
+    ASSERT_TRUE(AddMethod(&saved_info, dex1, /*method_idx=*/ i));
+    ASSERT_TRUE(AddMethod(&saved_info, dex2, /*method_idx=*/ i));
   }
   ASSERT_TRUE(saved_info.Save(GetFd(profile)));
   ASSERT_EQ(0, profile.GetFile()->Flush());
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
   ASSERT_TRUE(loaded_info.Equals(saved_info));
 
   // Save more methods.
   for (uint16_t i = 0; i < 100; i++) {
-    ASSERT_TRUE(AddMethod(&saved_info, dex1, /* method_idx= */ i));
-    ASSERT_TRUE(AddMethod(&saved_info, dex2, /* method_idx= */ i));
-    ASSERT_TRUE(AddMethod(&saved_info, dex3, /* method_idx= */ i));
+    ASSERT_TRUE(AddMethod(&saved_info, dex1, /*method_idx=*/ i));
+    ASSERT_TRUE(AddMethod(&saved_info, dex2, /*method_idx=*/ i));
+    ASSERT_TRUE(AddMethod(&saved_info, dex3, /*method_idx=*/ i));
   }
   ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(saved_info.Save(GetFd(profile)));
@@ -326,7 +306,6 @@
 
   // Check that we get back everything we saved.
   ProfileCompilationInfo loaded_info2;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info2.Load(GetFd(profile)));
   ASSERT_TRUE(loaded_info2.Equals(saved_info));
 }
@@ -335,19 +314,19 @@
   ScratchFile profile;
 
   ProfileCompilationInfo info;
-  ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ 1));
+  ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ 1));
   // Trying to add info for an existing file but with a different checksum.
-  ASSERT_FALSE(AddMethod(&info, dex1_checksum_missmatch, /* method_idx= */ 2));
+  ASSERT_FALSE(AddMethod(&info, dex1_checksum_missmatch, /*method_idx=*/ 2));
 }
 
 TEST_F(ProfileCompilationInfoTest, MergeFail) {
   ScratchFile profile;
 
   ProfileCompilationInfo info1;
-  ASSERT_TRUE(AddMethod(&info1, dex1, /* method_idx= */ 1));
+  ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ 1));
   // Use the same file, change the checksum.
   ProfileCompilationInfo info2;
-  ASSERT_TRUE(AddMethod(&info2, dex1_checksum_missmatch, /* method_idx= */ 2));
+  ASSERT_TRUE(AddMethod(&info2, dex1_checksum_missmatch, /*method_idx=*/ 2));
 
   ASSERT_FALSE(info1.MergeWith(info2));
 }
@@ -357,14 +336,13 @@
   ScratchFile profile;
 
   ProfileCompilationInfo info1;
-  ASSERT_TRUE(AddMethod(&info1, dex1, /* method_idx= */ 1));
+  ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ 1));
   // Use the same file, change the checksum.
   ProfileCompilationInfo info2;
-  ASSERT_TRUE(AddMethod(&info2, dex1_checksum_missmatch, /* method_idx= */ 2));
+  ASSERT_TRUE(AddMethod(&info2, dex1_checksum_missmatch, /*method_idx=*/ 2));
 
   ASSERT_TRUE(info1.Save(profile.GetFd()));
   ASSERT_EQ(0, profile.GetFile()->Flush());
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
 
   ASSERT_FALSE(info2.Load(profile.GetFd()));
 }
@@ -372,16 +350,22 @@
 TEST_F(ProfileCompilationInfoTest, SaveMaxMethods) {
   ScratchFile profile;
 
+  const DexFile* dex_max1 = BuildDex(
+      "location-max1", /*checksum=*/ 5, "LUniqueMax1;", kMaxMethodIds, kMaxClassIds);
+  const DexFile* dex_max2 = BuildDex(
+      "location-max2", /*checksum=*/ 6, "LUniqueMax2;", kMaxMethodIds, kMaxClassIds);
+
+
   ProfileCompilationInfo saved_info;
   // Save the maximum number of methods
   for (uint16_t i = 0; i < std::numeric_limits<uint16_t>::max(); i++) {
-    ASSERT_TRUE(AddMethod(&saved_info, dex_max_methods1, /* method_idx= */ i));
-    ASSERT_TRUE(AddMethod(&saved_info, dex_max_methods2, /* method_idx= */ i));
+    ASSERT_TRUE(AddMethod(&saved_info, dex_max1, /*method_idx=*/ i));
+    ASSERT_TRUE(AddMethod(&saved_info, dex_max2, /*method_idx=*/ i));
   }
   // Save the maximum number of classes
   for (uint16_t i = 0; i < std::numeric_limits<uint16_t>::max(); i++) {
-    ASSERT_TRUE(AddClass(&saved_info, dex1, dex::TypeIndex(i)));
-    ASSERT_TRUE(AddClass(&saved_info, dex2, dex::TypeIndex(i)));
+    ASSERT_TRUE(AddClass(&saved_info, dex_max1, dex::TypeIndex(i)));
+    ASSERT_TRUE(AddClass(&saved_info, dex_max2, dex::TypeIndex(i)));
   }
 
   ASSERT_TRUE(saved_info.Save(GetFd(profile)));
@@ -389,7 +373,6 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
   ASSERT_TRUE(loaded_info.Equals(saved_info));
 }
@@ -403,7 +386,6 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
   ASSERT_TRUE(loaded_info.Equals(saved_info));
 }
@@ -414,7 +396,6 @@
   ProfileCompilationInfo empty_info;
 
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
   ASSERT_TRUE(loaded_info.Equals(empty_info));
 }
@@ -424,7 +405,6 @@
   uint8_t buffer[] = { 1, 2, 3, 4 };
   ASSERT_TRUE(profile.GetFile()->WriteFully(buffer, sizeof(buffer)));
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_FALSE(loaded_info.Load(GetFd(profile)));
 }
 
@@ -438,7 +418,6 @@
   ASSERT_EQ(0, profile.GetFile()->Flush());
 
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_FALSE(loaded_info.Load(GetFd(profile)));
 }
 
@@ -448,13 +427,12 @@
       ProfileCompilationInfo::kProfileMagic, kProfileMagicSize));
   ASSERT_TRUE(profile.GetFile()->WriteFully(
       ProfileCompilationInfo::kProfileVersion, kProfileVersionSize));
-  // Write that we have at least one line.
-  uint8_t line_number[] = { 0, 1 };
-  ASSERT_TRUE(profile.GetFile()->WriteFully(line_number, sizeof(line_number)));
+  // Write that we have one section info.
+  const uint32_t file_section_count = 1u;
+  ASSERT_TRUE(profile.GetFile()->WriteFully(&file_section_count, sizeof(file_section_count)));
   ASSERT_EQ(0, profile.GetFile()->Flush());
 
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_FALSE(loaded_info.Load(GetFd(profile)));
 }
 
@@ -464,18 +442,41 @@
       ProfileCompilationInfo::kProfileMagic, kProfileMagicSize));
   ASSERT_TRUE(profile.GetFile()->WriteFully(
       ProfileCompilationInfo::kProfileVersion, kProfileVersionSize));
-  // Write that we have at least one line.
-  uint8_t line_number[] = { 0, 1 };
-  ASSERT_TRUE(profile.GetFile()->WriteFully(line_number, sizeof(line_number)));
+  // Write that we have one section info.
+  const uint32_t file_section_count = 1u;
+  ASSERT_TRUE(profile.GetFile()->WriteFully(&file_section_count, sizeof(file_section_count)));
 
-  // dex_location_size, methods_size, classes_size, checksum.
-  // Dex location size is too big and should be rejected.
-  uint8_t line[] = { 255, 255, 0, 1, 0, 1, 0, 0, 0, 0 };
-  ASSERT_TRUE(profile.GetFile()->WriteFully(line, sizeof(line)));
+  constexpr size_t kInvalidDexFileLocationLength = 1025u;
+  constexpr uint32_t kDexFilesOffset =
+      kProfileMagicSize + kProfileVersionSize + sizeof(file_section_count) + 4u * sizeof(uint32_t);
+  constexpr uint32_t kDexFilesSize =
+      sizeof(ProfileIndexType) +  // number of dex files
+      3u * sizeof(uint32_t) +  // numeric data
+      kInvalidDexFileLocationLength + 1u;  // null-terminated string
+  const uint32_t section_info[] = {
+      0u,  // type = kDexFiles
+      kDexFilesOffset,
+      kDexFilesSize,
+      0u,  // inflated size = 0
+  };
+  ASSERT_TRUE(profile.GetFile()->WriteFully(section_info, sizeof(section_info)));
+
+  ProfileIndexType num_dex_files = 1u;
+  ASSERT_TRUE(profile.GetFile()->WriteFully(&num_dex_files, sizeof(num_dex_files)));
+
+  uint32_t numeric_data[3] = {
+      1234u,  // checksum
+      1u,  // num_type_ids
+      2u,  // num_method_ids
+  };
+  ASSERT_TRUE(profile.GetFile()->WriteFully(numeric_data, sizeof(numeric_data)));
+
+  std::string dex_location(kInvalidDexFileLocationLength, 'a');
+  ASSERT_TRUE(profile.GetFile()->WriteFully(dex_location.c_str(), dex_location.size() + 1u));
+
   ASSERT_EQ(0, profile.GetFile()->Flush());
 
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_FALSE(loaded_info.Load(GetFd(profile)));
 }
 
@@ -484,19 +485,22 @@
 
   ProfileCompilationInfo saved_info;
   for (uint16_t i = 0; i < 10; i++) {
-    ASSERT_TRUE(AddMethod(&saved_info, dex1, /* method_idx= */ i));
+    ASSERT_TRUE(AddMethod(&saved_info, dex1, /*method_idx=*/ i));
   }
   ASSERT_TRUE(saved_info.Save(GetFd(profile)));
 
   uint8_t random_data[] = { 1, 2, 3};
-  ASSERT_TRUE(profile.GetFile()->WriteFully(random_data, sizeof(random_data)));
+  int64_t file_length = profile.GetFile()->GetLength();
+  ASSERT_GT(file_length, 0);
+  ASSERT_TRUE(profile.GetFile()->PwriteFully(random_data, sizeof(random_data), file_length));
 
   ASSERT_EQ(0, profile.GetFile()->Flush());
+  ASSERT_EQ(profile.GetFile()->GetLength(),
+            file_length + static_cast<int64_t>(sizeof(random_data)));
 
-  // Check that we fail because of unexpected data at the end of the file.
+  // Extra data at the end of the file is OK, loading the profile should succeed.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
-  ASSERT_FALSE(loaded_info.Load(GetFd(profile)));
+  ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
 }
 
 TEST_F(ProfileCompilationInfoTest, SaveInlineCaches) {
@@ -519,19 +523,18 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
 
   ASSERT_TRUE(loaded_info.Equals(saved_info));
 
-  std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi1 =
-      GetMethod(loaded_info, dex1, /* method_idx= */ 3);
-  ASSERT_TRUE(loaded_pmi1 != nullptr);
-  ASSERT_TRUE(*loaded_pmi1 == inline_caches);
-  std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi2 =
-      GetMethod(loaded_info, dex4, /* method_idx= */ 3);
-  ASSERT_TRUE(loaded_pmi2 != nullptr);
-  ASSERT_TRUE(*loaded_pmi2 == inline_caches);
+  ProfileCompilationInfo::MethodHotness loaded_hotness1 =
+      GetMethod(loaded_info, dex1, /*method_idx=*/ 3);
+  ASSERT_TRUE(loaded_hotness1.IsHot());
+  ASSERT_TRUE(EqualInlineCaches(inline_caches, dex1, loaded_hotness1, loaded_info));
+  ProfileCompilationInfo::MethodHotness loaded_hotness2 =
+      GetMethod(loaded_info, dex4, /*method_idx=*/ 3);
+  ASSERT_TRUE(loaded_hotness2.IsHot());
+  ASSERT_TRUE(EqualInlineCaches(inline_caches, dex4, loaded_hotness2, loaded_info));
 }
 
 TEST_F(ProfileCompilationInfoTest, MegamorphicInlineCaches) {
@@ -564,16 +567,15 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(extra_profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info.Load(GetFd(extra_profile)));
 
   ASSERT_TRUE(loaded_info.Equals(saved_info));
 
-  std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi1 =
-      GetMethod(loaded_info, dex1, /* method_idx= */ 3);
+  ProfileCompilationInfo::MethodHotness loaded_hotness1 =
+      GetMethod(loaded_info, dex1, /*method_idx=*/ 3);
 
-  ASSERT_TRUE(loaded_pmi1 != nullptr);
-  ASSERT_TRUE(*loaded_pmi1 == inline_caches_extra);
+  ASSERT_TRUE(loaded_hotness1.IsHot());
+  ASSERT_TRUE(EqualInlineCaches(inline_caches_extra, dex1, loaded_hotness1, loaded_info));
 }
 
 TEST_F(ProfileCompilationInfoTest, MissingTypesInlineCaches) {
@@ -614,15 +616,14 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(extra_profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info.Load(GetFd(extra_profile)));
 
   ASSERT_TRUE(loaded_info.Equals(saved_info));
 
-  std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi1 =
-      GetMethod(loaded_info, dex1, /* method_idx= */ 3);
-  ASSERT_TRUE(loaded_pmi1 != nullptr);
-  ASSERT_TRUE(*loaded_pmi1 == missing_types);
+  ProfileCompilationInfo::MethodHotness loaded_hotness1 =
+      GetMethod(loaded_info, dex1, /*method_idx=*/ 3);
+  ASSERT_TRUE(loaded_hotness1.IsHot());
+  ASSERT_TRUE(EqualInlineCaches(missing_types, dex1, loaded_hotness1, loaded_info));
 }
 
 TEST_F(ProfileCompilationInfoTest, InvalidChecksumInInlineCache) {
@@ -636,8 +637,45 @@
       &inline_caches2[0].classes);
   types->front().dex_file = dex1_checksum_missmatch;
 
-  ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ 0, inline_caches1));
-  ASSERT_FALSE(AddMethod(&info, dex2, /* method_idx= */ 0, inline_caches2));
+  ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ 0, inline_caches1));
+
+  // The dex files referenced in inline infos do not matter. We are recoding class
+  // references across dex files by looking up the descriptor in the referencing
+  // method's dex file. If not found, we create an artificial type index.
+  ASSERT_TRUE(AddMethod(&info, dex2, /*method_idx=*/ 0, inline_caches2));
+}
+
+TEST_F(ProfileCompilationInfoTest, InlineCacheAcrossDexFiles) {
+  ScratchFile profile;
+
+  const char kDex1Class[] = "LUnique1;";
+  const dex::TypeId* dex1_tid = dex1->FindTypeId(kDex1Class);
+  ASSERT_TRUE(dex1_tid != nullptr);
+  dex::TypeIndex dex1_tidx = dex1->GetIndexForTypeId(*dex1_tid);
+  ASSERT_FALSE(dex2->FindTypeId(kDex1Class) != nullptr);
+
+  const uint16_t dex_pc = 33u;
+  std::vector<TypeReference> types = {TypeReference(dex1, dex1_tidx)};
+  std::vector<ProfileInlineCache> inline_caches {
+      ProfileInlineCache(dex_pc, /*missing_types=*/ false, types)
+  };
+
+  ProfileCompilationInfo info;
+  ASSERT_TRUE(AddMethod(&info, dex2, /*method_idx=*/ 0, inline_caches));
+  Hotness hotness = GetMethod(info, dex2, /*method_idx=*/ 0);
+  ASSERT_TRUE(hotness.IsHot());
+  ASSERT_TRUE(EqualInlineCaches(inline_caches, dex2, hotness, info));
+  const ProfileCompilationInfo::InlineCacheMap* inline_cache_map = hotness.GetInlineCacheMap();
+  ASSERT_TRUE(inline_cache_map != nullptr);
+  ASSERT_EQ(1u, inline_cache_map->size());
+  ASSERT_EQ(dex_pc, inline_cache_map->begin()->first);
+  const ProfileCompilationInfo::DexPcData& dex_pc_data = inline_cache_map->begin()->second;
+  ASSERT_FALSE(dex_pc_data.is_missing_types);
+  ASSERT_FALSE(dex_pc_data.is_megamorphic);
+  ASSERT_EQ(1u, dex_pc_data.classes.size());
+  dex::TypeIndex type_index = *dex_pc_data.classes.begin();
+  ASSERT_FALSE(dex2->IsTypeIndexValid(type_index));
+  ASSERT_STREQ(kDex1Class, info.GetTypeDescriptor(dex2, type_index));
 }
 
 // Verify that profiles behave correctly even if the methods are added in a different
@@ -653,7 +691,7 @@
     std::vector<TypeReference> types = {
         TypeReference(dex1, dex::TypeIndex(0)),
         TypeReference(dex2, dex::TypeIndex(1))};
-    inline_caches.push_back(ProfileInlineCache(dex_pc, /* missing_types*/ false, types));
+    inline_caches.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ false, types));
   }
 
   std::vector<ProfileInlineCache> inline_caches_reindexed;
@@ -661,7 +699,7 @@
     std::vector<TypeReference> types = {
         TypeReference(dex2, dex::TypeIndex(1)),
         TypeReference(dex1, dex::TypeIndex(0))};
-    inline_caches_reindexed.push_back(ProfileInlineCache(dex_pc, /* missing_types*/ false, types));
+    inline_caches_reindexed.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ false, types));
   }
   // Profile 1 and Profile 2 get the same methods but in different order.
   // This will trigger a different dex numbers.
@@ -681,45 +719,39 @@
   // Merging should have no effect as we're adding the exact same stuff.
   ASSERT_TRUE(info.Equals(info_backup));
   for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
-    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi1 =
-        GetMethod(info, dex1, method_idx);
-    ASSERT_TRUE(loaded_pmi1 != nullptr);
-    ASSERT_TRUE(*loaded_pmi1 == inline_caches);
-    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi2 =
-        GetMethod(info, dex2, method_idx);
-    ASSERT_TRUE(loaded_pmi2 != nullptr);
-    ASSERT_TRUE(*loaded_pmi2 == inline_caches);
+    ProfileCompilationInfo::MethodHotness loaded_hotness1 = GetMethod(info, dex1, method_idx);
+    ASSERT_TRUE(loaded_hotness1.IsHot());
+    ASSERT_TRUE(EqualInlineCaches(inline_caches, dex1, loaded_hotness1, info));
+    ProfileCompilationInfo::MethodHotness loaded_hotness2 = GetMethod(info, dex2, method_idx);
+    ASSERT_TRUE(loaded_hotness2.IsHot());
+    ASSERT_TRUE(EqualInlineCaches(inline_caches, dex2, loaded_hotness2, info));
   }
 }
 
 TEST_F(ProfileCompilationInfoTest, AddMoreDexFileThanLimitRegular) {
-  FakeDexStorage local_storage;
   ProfileCompilationInfo info;
   // Save a few methods.
-  for (uint16_t i = 0; i < std::numeric_limits<ProfileIndexTypeRegular>::max(); i++) {
+  for (uint16_t i = 0; i < std::numeric_limits<ProfileIndexType>::max(); i++) {
     std::string location = std::to_string(i);
-    const DexFile* dex = local_storage.AddFakeDex(
-        location, /* checksum= */ 1, /* num_method_ids= */ 1);
-    ASSERT_TRUE(AddMethod(&info, dex, /* method_idx= */ 0));
+    const DexFile* dex = BuildDex(location, /*checksum=*/ 1, "LC;", /*num_method_ids=*/ 1);
+    ASSERT_TRUE(AddMethod(&info, dex, /*method_idx=*/ 0));
   }
   // Add an extra dex file.
-  const DexFile* dex = local_storage.AddFakeDex("-1", /* checksum= */ 1, /* num_method_ids= */ 1);
-  ASSERT_FALSE(AddMethod(&info, dex, /* method_idx= */ 0));
+  const DexFile* dex = BuildDex("-1", /*checksum=*/ 1, "LC;", /*num_method_ids=*/ 1);
+  ASSERT_FALSE(AddMethod(&info, dex, /*method_idx=*/ 0));
 }
 
 TEST_F(ProfileCompilationInfoTest, AddMoreDexFileThanLimitBoot) {
-  FakeDexStorage local_storage;
   ProfileCompilationInfo info(/*for_boot_image=*/true);
   // Save a few methods.
   for (uint16_t i = 0; i < std::numeric_limits<ProfileIndexType>::max(); i++) {
     std::string location = std::to_string(i);
-    const DexFile* dex = local_storage.AddFakeDex(
-        location, /* checksum= */ 1, /* num_method_ids= */ 1);
-    ASSERT_TRUE(AddMethod(&info, dex, /* method_idx= */ 0));
+    const DexFile* dex = BuildDex(location, /*checksum=*/ 1, "LC;", /*num_method_ids=*/ 1);
+    ASSERT_TRUE(AddMethod(&info, dex, /*method_idx=*/ 0));
   }
   // Add an extra dex file.
-  const DexFile* dex = local_storage.AddFakeDex("-1", /* checksum= */ 1, /* num_method_ids= */ 1);
-  ASSERT_FALSE(AddMethod(&info, dex, /* method_idx= */ 0));
+  const DexFile* dex = BuildDex("-1", /*checksum=*/ 1, "LC;", /*num_method_ids=*/ 1);
+  ASSERT_FALSE(AddMethod(&info, dex, /*method_idx=*/ 0));
 }
 
 TEST_F(ProfileCompilationInfoTest, MegamorphicInlineCachesMerge) {
@@ -731,7 +763,7 @@
           TypeReference(dex1, dex::TypeIndex(2)),
           TypeReference(dex1, dex::TypeIndex(3)),
           TypeReference(dex1, dex::TypeIndex(4))};
-  inline_caches.push_back(ProfileInlineCache(0, /* missing_types*/ false, types));
+  inline_caches.push_back(ProfileInlineCache(0, /*missing_types=*/ false, types));
 
   ProfileCompilationInfo info_megamorphic;
   ASSERT_TRUE(AddMethod(&info_megamorphic, dex1, 0, inline_caches));
@@ -751,7 +783,7 @@
   // Create an inline cache with missing types
   std::vector<ProfileInlineCache> inline_caches;
   std::vector<TypeReference> types = {};
-  inline_caches.push_back(ProfileInlineCache(0, /* missing_types*/ true, types));
+  inline_caches.push_back(ProfileInlineCache(0, /*missing_types=*/ true, types));
 
   ProfileCompilationInfo info_missing_types;
   ASSERT_TRUE(AddMethod(&info_missing_types, dex1, /*method_idx=*/ 0, inline_caches));
@@ -789,7 +821,6 @@
   ScratchFile profile;
   ASSERT_TRUE(test_info.Save(GetFd(profile)));
   ASSERT_EQ(0, profile.GetFile()->Flush());
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
 
   // Load the profile and make sure we can read the data and it matches what we expect.
   ProfileCompilationInfo loaded_info;
@@ -878,15 +909,14 @@
       ProfileCompilationInfo::kProfileMagic, kProfileMagicSize));
   ASSERT_TRUE(profile.GetFile()->WriteFully(
       ProfileCompilationInfo::kProfileVersion, kProfileVersionSize));
-  // Write that we have at least one line.
-  uint8_t line_number[] = { 0, 1 };
-  ASSERT_TRUE(profile.GetFile()->WriteFully(line_number, sizeof(line_number)));
+  // Write that we have one section info.
+  const uint32_t file_section_count = 1u;
+  ASSERT_TRUE(profile.GetFile()->WriteFully(&file_section_count, sizeof(file_section_count)));
   ASSERT_EQ(0, profile.GetFile()->Flush());
 
   // Prepare the profile content for zipping.
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   std::vector<uint8_t> data(profile.GetFile()->GetLength());
-  ASSERT_TRUE(profile.GetFile()->ReadFully(data.data(), data.size()));
+  ASSERT_TRUE(profile.GetFile()->PreadFully(data.data(), data.size(), /*offset=*/ 0));
 
   // Zip the profile content.
   ScratchFile zip;
@@ -901,7 +931,6 @@
 
   // Check that we failed to load.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(zip.GetFile()->ResetOffset());
   ASSERT_FALSE(loaded_info.Load(GetFd(zip)));
 }
 
@@ -911,17 +940,43 @@
   dex_files.push_back(std::unique_ptr<const DexFile>(dex2_renamed));
 
   ProfileCompilationInfo info;
-  AddMethod(&info, dex1, /* method_idx= */ 0);
-  AddMethod(&info, dex2, /* method_idx= */ 0);
+  AddMethod(&info, dex1, /*method_idx=*/ 0);
+  AddMethod(&info, dex2, /*method_idx=*/ 0);
 
   // Update the profile keys based on the original dex files
   ASSERT_TRUE(info.UpdateProfileKeys(dex_files));
 
   // Verify that we find the methods when searched with the original dex files.
   for (const std::unique_ptr<const DexFile>& dex : dex_files) {
-    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi =
-        GetMethod(info, dex.get(), /* method_idx= */ 0);
-    ASSERT_TRUE(loaded_pmi != nullptr);
+    ProfileCompilationInfo::MethodHotness loaded_hotness =
+        GetMethod(info, dex.get(), /*method_idx=*/ 0);
+    ASSERT_TRUE(loaded_hotness.IsHot());
+  }
+
+  // Release the ownership as this is held by the test class;
+  for (std::unique_ptr<const DexFile>& dex : dex_files) {
+    UNUSED(dex.release());
+  }
+}
+
+TEST_F(ProfileCompilationInfoTest, UpdateProfileKeyOkWithAnnotation) {
+  std::vector<std::unique_ptr<const DexFile>> dex_files;
+  dex_files.push_back(std::unique_ptr<const DexFile>(dex1_renamed));
+  dex_files.push_back(std::unique_ptr<const DexFile>(dex2_renamed));
+
+  ProfileCompilationInfo info;
+  ProfileCompilationInfo::ProfileSampleAnnotation annotation("test.package");
+  AddMethod(&info, dex1, /*method_idx=*/ 0, Hotness::kFlagHot, annotation);
+  AddMethod(&info, dex2, /*method_idx=*/ 0, Hotness::kFlagHot, annotation);
+
+  // Update the profile keys based on the original dex files
+  ASSERT_TRUE(info.UpdateProfileKeys(dex_files));
+
+  // Verify that we find the methods when searched with the original dex files.
+  for (const std::unique_ptr<const DexFile>& dex : dex_files) {
+    ProfileCompilationInfo::MethodHotness loaded_hotness =
+        GetMethod(info, dex.get(), /*method_idx=*/ 0, annotation);
+    ASSERT_TRUE(loaded_hotness.IsHot());
   }
 
   // Release the ownership as this is held by the test class;
@@ -935,7 +990,7 @@
   dex_files.push_back(std::unique_ptr<const DexFile>(dex1));
 
   ProfileCompilationInfo info;
-  AddMethod(&info, dex2, /* method_idx= */ 0);
+  AddMethod(&info, dex2, /*method_idx=*/ 0);
 
   // Update the profile keys based on the original dex files.
   ASSERT_TRUE(info.UpdateProfileKeys(dex_files));
@@ -943,15 +998,15 @@
   // Verify that we did not perform any update and that we cannot find anything with the new
   // location.
   for (const std::unique_ptr<const DexFile>& dex : dex_files) {
-    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi =
-        GetMethod(info, dex.get(), /* method_idx= */ 0);
-    ASSERT_TRUE(loaded_pmi == nullptr);
+    ProfileCompilationInfo::MethodHotness loaded_hotness =
+        GetMethod(info, dex.get(), /*method_idx=*/ 0);
+    ASSERT_FALSE(loaded_hotness.IsHot());
   }
 
   // Verify that we can find the original entry.
-  std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi =
-        GetMethod(info, dex2, /* method_idx= */ 0);
-  ASSERT_TRUE(loaded_pmi != nullptr);
+  ProfileCompilationInfo::MethodHotness loaded_hotness =
+        GetMethod(info, dex2, /*method_idx=*/ 0);
+  ASSERT_TRUE(loaded_hotness.IsHot());
 
   // Release the ownership as this is held by the test class;
   for (std::unique_ptr<const DexFile>& dex : dex_files) {
@@ -964,11 +1019,11 @@
   dex_files.push_back(std::unique_ptr<const DexFile>(dex1_renamed));
 
   ProfileCompilationInfo info;
-  AddMethod(&info, dex1, /* method_idx= */ 0);
+  AddMethod(&info, dex1, /*method_idx=*/ 0);
 
   // Add a method index using the location we want to rename to.
   // This will cause the rename to fail because an existing entry would already have that name.
-  AddMethod(&info, dex1_renamed, /* method_idx= */ 0);
+  AddMethod(&info, dex1_renamed, /*method_idx=*/ 0);
 
   ASSERT_FALSE(info.UpdateProfileKeys(dex_files));
 
@@ -998,7 +1053,6 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
 
   // Filter out dex locations. Keep only dex_location1 and dex_location3.
   ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
@@ -1009,64 +1063,28 @@
   ASSERT_TRUE(loaded_info.Load(GetFd(profile), true, filter_fn));
 
   // Verify that we filtered out locations during load.
+  // Note that `dex3` did not have any data recorded in the profile.
+  ASSERT_EQ(1u, loaded_info.GetNumberOfDexFiles());
 
   // Dex location 2 and 4 should have been filtered out
   for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
-    ASSERT_TRUE(nullptr == GetMethod(loaded_info, dex2, method_idx));
-    ASSERT_TRUE(nullptr == GetMethod(loaded_info, dex4, method_idx));
+    ASSERT_FALSE(GetMethod(loaded_info, dex2, method_idx).IsHot());
+    ASSERT_FALSE(GetMethod(loaded_info, dex4, method_idx).IsHot());
   }
 
   // Dex location 1 should have all all the inline caches referencing dex location 2 set to
   // missing types.
   for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
     // The methods for dex location 1 should be in the profile data.
-    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi1 =
+    ProfileCompilationInfo::MethodHotness loaded_hotness1 =
         GetMethod(loaded_info, dex1, method_idx);
-    ASSERT_TRUE(loaded_pmi1 != nullptr);
+    ASSERT_TRUE(loaded_hotness1.IsHot());
 
-    // Verify the inline cache.
-    // Everything should be as constructed by GetTestInlineCaches with the exception
-    // of the inline caches referring types from dex_location2.
-    // These should be set to IsMissingType.
-    ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap();
-
-    // Monomorphic types should remain the same as dex_location1 was kept.
-    for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) {
-      ProfileCompilationInfo::DexPcData dex_pc_data(allocator_.get());
-      dex_pc_data.AddClass(0, dex::TypeIndex(0));
-      ic_map->Put(dex_pc, dex_pc_data);
-    }
-    // Polymorphic inline cache should have been transformed to IsMissingType due to
-    // the removal of dex_location2.
-    for (uint16_t dex_pc = 11; dex_pc < 22; dex_pc++) {
-      ProfileCompilationInfo::DexPcData dex_pc_data(allocator_.get());
-      dex_pc_data.SetIsMissingTypes();
-      ic_map->Put(dex_pc, dex_pc_data);
-    }
-
-    // Megamorphic are not affected by removal of dex files.
-    for (uint16_t dex_pc = 22; dex_pc < 33; dex_pc++) {
-      ProfileCompilationInfo::DexPcData dex_pc_data(allocator_.get());
-      dex_pc_data.SetIsMegamorphic();
-      ic_map->Put(dex_pc, dex_pc_data);
-    }
-    // Missing types are not affected be removal of dex files.
-    for (uint16_t dex_pc = 33; dex_pc < 44; dex_pc++) {
-      ProfileCompilationInfo::DexPcData dex_pc_data(allocator_.get());
-      dex_pc_data.SetIsMissingTypes();
-      ic_map->Put(dex_pc, dex_pc_data);
-    }
-
-    ProfileCompilationInfo::OfflineProfileMethodInfo expected_pmi(ic_map);
-
-    // The dex references should not have  dex_location2 in the list.
-    expected_pmi.dex_references.emplace_back(
-        dex1->GetLocation(), dex1->GetLocationChecksum(), dex1->NumMethodIds());
-    expected_pmi.dex_references.emplace_back(
-        dex3->GetLocation(), dex3->GetLocationChecksum(), dex3->NumMethodIds());
-
-    // Now check that we get back what we expect.
-    ASSERT_TRUE(*loaded_pmi1 == expected_pmi);
+    // Verify the inline cache. Note that references to other dex files are translated
+    // to use type indexes within the referencing dex file and artificial type indexes
+    // referencing "extra descriptors" are used when there is no `dex::TypeId` for
+    // these types. `EqualInlineCaches()` compares descriptors when necessary.
+    ASSERT_TRUE(EqualInlineCaches(inline_caches, dex1, loaded_hotness1, loaded_info));
   }
 }
 
@@ -1090,7 +1108,6 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
 
   // Remove all elements.
   ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
@@ -1121,7 +1138,6 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
 
   // Keep all elements.
   ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
@@ -1132,16 +1148,16 @@
   ASSERT_TRUE(loaded_info.Equals(saved_info));
 
   for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
-    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi1 =
+    ProfileCompilationInfo::MethodHotness loaded_hotness1 =
         GetMethod(loaded_info, dex1, method_idx);
-    ASSERT_TRUE(loaded_pmi1 != nullptr);
-    ASSERT_TRUE(*loaded_pmi1 == inline_caches);
+    ASSERT_TRUE(loaded_hotness1.IsHot());
+    ASSERT_TRUE(EqualInlineCaches(inline_caches, dex1, loaded_hotness1, loaded_info));
   }
   for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
-    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> loaded_pmi2 =
+    ProfileCompilationInfo::MethodHotness loaded_hotness2 =
         GetMethod(loaded_info, dex4, method_idx);
-    ASSERT_TRUE(loaded_pmi2 != nullptr);
-    ASSERT_TRUE(*loaded_pmi2 == inline_caches);
+    ASSERT_TRUE(loaded_hotness2.IsHot());
+    ASSERT_TRUE(EqualInlineCaches(inline_caches, dex4, loaded_hotness2, loaded_info));
   }
 }
 
@@ -1150,31 +1166,42 @@
 TEST_F(ProfileCompilationInfoTest, FilteredLoadingWithClasses) {
   ScratchFile profile;
 
+  const DexFile* dex1_1000 = BuildDex("location1_1000",
+                                      /*checksum=*/ 7,
+                                      "LC1_1000;",
+                                      /*num_method_ids=*/ 1u,
+                                      /*num_class_ids=*/ 1000u);
+  const DexFile* dex2_1000 = BuildDex("location2_1000",
+                                      /*checksum=*/ 8,
+                                      "LC2_1000;",
+                                      /*num_method_ids=*/ 1u,
+                                      /*num_class_ids=*/ 1000u);
+
   // Save a profile with 2 dex files containing just classes.
   ProfileCompilationInfo saved_info;
   uint16_t item_count = 1000;
   for (uint16_t i = 0; i < item_count; i++) {
-    ASSERT_TRUE(AddClass(&saved_info, dex1, dex::TypeIndex(i)));
-    ASSERT_TRUE(AddClass(&saved_info, dex2, dex::TypeIndex(i)));
+    ASSERT_TRUE(AddClass(&saved_info, dex1_1000, dex::TypeIndex(i)));
+    ASSERT_TRUE(AddClass(&saved_info, dex2_1000, dex::TypeIndex(i)));
   }
 
   ASSERT_TRUE(saved_info.Save(GetFd(profile)));
   ASSERT_EQ(0, profile.GetFile()->Flush());
 
 
-  // Filter out dex locations: kepp only dex_location2.
+  // Filter out dex locations: keep only `dex2_1000->GetLocation()`.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
-      [&dex2 = dex2](const std::string& dex_location, uint32_t checksum) -> bool {
-          return (dex_location == dex2->GetLocation() && checksum == dex2->GetLocationChecksum());
+      [dex2_1000](const std::string& dex_location, uint32_t checksum) -> bool {
+          return dex_location == dex2_1000->GetLocation() &&
+                 checksum == dex2_1000->GetLocationChecksum();
         };
   ASSERT_TRUE(loaded_info.Load(GetFd(profile), true, filter_fn));
 
   // Compute the expectation.
   ProfileCompilationInfo expected_info;
   for (uint16_t i = 0; i < item_count; i++) {
-    ASSERT_TRUE(AddClass(&expected_info, dex2, dex::TypeIndex(i)));
+    ASSERT_TRUE(AddClass(&expected_info, dex2_1000, dex::TypeIndex(i)));
   }
 
   // Validate the expectation.
@@ -1185,7 +1212,7 @@
 TEST_F(ProfileCompilationInfoTest, ClearData) {
   ProfileCompilationInfo info;
   for (uint16_t i = 0; i < 10; i++) {
-    ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ i));
+    ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i));
   }
   ASSERT_FALSE(IsEmpty(info));
   info.ClearData();
@@ -1195,7 +1222,7 @@
 TEST_F(ProfileCompilationInfoTest, ClearDataAndSave) {
   ProfileCompilationInfo info;
   for (uint16_t i = 0; i < 10; i++) {
-    ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ i));
+    ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i));
   }
   info.ClearData();
 
@@ -1205,7 +1232,6 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
   ASSERT_TRUE(loaded_info.Equals(info));
 }
@@ -1220,7 +1246,6 @@
   ASSERT_FALSE(info.IsForBootImage());
 
   ProfileCompilationInfo info1(/*for_boot_image=*/ true);
-
   ASSERT_EQ(
       memcmp(info1.GetVersion(),
              ProfileCompilationInfo::kProfileVersionForBootImage,
@@ -1236,7 +1261,7 @@
 }
 
 TEST_F(ProfileCompilationInfoTest, AllMethodFlags) {
-  ProfileCompilationInfo info(/*for_boot_image*/ true);
+  ProfileCompilationInfo info(/*for_boot_image=*/ true);
 
   for (uint32_t index = 0; index <= kMaxHotnessFlagBootIndex; index++) {
     AddMethod(&info, dex1, index, static_cast<Hotness::Flag>(1 << index));
@@ -1256,16 +1281,15 @@
   ScratchFile profile;
   ASSERT_TRUE(info.Save(GetFd(profile)));
   ASSERT_EQ(0, profile.GetFile()->Flush());
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
 
   // Load the profile and make sure we can read the data and it matches what we expect.
-  ProfileCompilationInfo loaded_info;
+  ProfileCompilationInfo loaded_info(/*for_boot_image=*/ true);
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
   run_test(loaded_info);
 }
 
 TEST_F(ProfileCompilationInfoTest, AllMethodFlagsOnOneMethod) {
-  ProfileCompilationInfo info(/*for_boot_image*/ true);
+  ProfileCompilationInfo info(/*for_boot_image=*/ true);
 
   // Set all flags on a single method.
   for (uint32_t index = 0; index <= kMaxHotnessFlagBootIndex; index++) {
@@ -1285,18 +1309,17 @@
   ScratchFile profile;
   ASSERT_TRUE(info.Save(GetFd(profile)));
   ASSERT_EQ(0, profile.GetFile()->Flush());
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
 
   // Load the profile and make sure we can read the data and it matches what we expect.
-  ProfileCompilationInfo loaded_info;
+  ProfileCompilationInfo loaded_info(/*for_boot_image=*/ true);
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
   run_test(loaded_info);
 }
 
 
 TEST_F(ProfileCompilationInfoTest, MethodFlagsMerge) {
-  ProfileCompilationInfo info1(/*for_boot_image*/ true);
-  ProfileCompilationInfo info2(/*for_boot_image*/ true);
+  ProfileCompilationInfo info1(/*for_boot_image=*/ true);
+  ProfileCompilationInfo info2(/*for_boot_image=*/ true);
 
   // Set a few flags on a 2 different methods in each of the profile.
   for (uint32_t index = 0; index <= kMaxHotnessFlagBootIndex / 4; index++) {
@@ -1355,10 +1378,9 @@
   ScratchFile profile;
   ASSERT_TRUE(info1.Save(GetFd(profile)));
   ASSERT_EQ(0, profile.GetFile()->Flush());
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
 
   // Load the profile and make sure we can read the data and it matches what we expect.
-  ProfileCompilationInfo loaded_info;
+  ProfileCompilationInfo loaded_info(/*for_boot_image=*/ true);
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
   run_test(loaded_info);
 }
@@ -1414,14 +1436,13 @@
   info.AddMethod(ProfileMethodInfo(startup, inline_caches), Hotness::kFlagStartup);
 
   // Check the hot method's inline cache.
-  std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> hot_pmi =
-      GetMethod(info, dex1, hot.index);
-  ASSERT_TRUE(hot_pmi != nullptr);
-  ASSERT_EQ(hot_pmi->inline_caches->size(), 1u);
-  ASSERT_TRUE(hot_pmi->inline_caches->Get(0).is_missing_types);
+  ProfileCompilationInfo::MethodHotness hot_hotness = GetMethod(info, dex1, hot.index);
+  ASSERT_TRUE(hot_hotness.IsHot());
+  ASSERT_EQ(hot_hotness.GetInlineCacheMap()->size(), 1u);
+  ASSERT_TRUE(hot_hotness.GetInlineCacheMap()->Get(0).is_missing_types);
 
   // Check there's no inline caches for the startup method.
-  ASSERT_TRUE(GetMethod(info, dex1, startup.index) == nullptr);
+  ASSERT_FALSE(GetMethod(info, dex1, startup.index).IsHot());
 }
 
 // Verifies that we correctly add methods to the profile according to their flags.
@@ -1443,47 +1464,47 @@
   ProfileSampleAnnotation psa2("test2");
   // Save a few methods using different annotations, some overlapping, some not.
   for (uint16_t i = 0; i < 10; i++) {
-    ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ i, Hotness::kFlagHot, psa1));
+    ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
   }
   for (uint16_t i = 5; i < 15; i++) {
-    ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ i, Hotness::kFlagHot, psa2));
+    ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
   }
 
   auto run_test = [&dex1 = dex1, &psa1 = psa1, &psa2 = psa2](const ProfileCompilationInfo& info) {
     // Check that all methods are in.
     for (uint16_t i = 0; i < 10; i++) {
       EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa1).IsInProfile());
-      EXPECT_TRUE(info.GetHotMethodInfo(MethodReference(dex1, i), psa1) != nullptr);
+      EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa1).IsHot());
     }
     for (uint16_t i = 5; i < 15; i++) {
       EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsInProfile());
-      EXPECT_TRUE(info.GetHotMethodInfo(MethodReference(dex1, i), psa2) != nullptr);
+      EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsHot());
     }
     // Check that the non-overlapping methods are not added with a wrong annotation.
     for (uint16_t i = 10; i < 15; i++) {
       EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i), psa1).IsInProfile());
-      EXPECT_FALSE(info.GetHotMethodInfo(MethodReference(dex1, i), psa1) != nullptr);
+      EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i), psa1).IsHot());
     }
     for (uint16_t i = 0; i < 5; i++) {
       EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsInProfile());
-      EXPECT_FALSE(info.GetHotMethodInfo(MethodReference(dex1, i), psa2) != nullptr);
+      EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsHot());
     }
     // Check that when querying without an annotation only the first one is searched.
     for (uint16_t i = 0; i < 10; i++) {
       EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i)).IsInProfile());
-      EXPECT_TRUE(info.GetHotMethodInfo(MethodReference(dex1, i)) != nullptr);
+      EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i)).IsHot());
     }
     // ... this should be false because they belong the second appearance of dex1.
     for (uint16_t i = 10; i < 15; i++) {
       EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i)).IsInProfile());
-      EXPECT_FALSE(info.GetHotMethodInfo(MethodReference(dex1, i)) != nullptr);
+      EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i)).IsHot());
     }
 
-    // Sanity check that methods cannot be found with a non existing annotation.
+    // Check that the methods cannot be found with a non existing annotation.
     MethodReference ref(dex1, 0);
-    ProfileSampleAnnotation not_exisiting("A");
-    EXPECT_FALSE(info.GetMethodHotness(ref, not_exisiting).IsInProfile());
-    EXPECT_FALSE(info.GetHotMethodInfo(ref, not_exisiting) != nullptr);
+    ProfileSampleAnnotation not_existing("A");
+    EXPECT_FALSE(info.GetMethodHotness(ref, not_existing).IsInProfile());
+    EXPECT_FALSE(info.GetMethodHotness(ref, not_existing).IsHot());
   };
 
   // Run the test before save.
@@ -1495,7 +1516,6 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
   ASSERT_TRUE(loaded_info.Equals(info));
 
@@ -1510,38 +1530,38 @@
   ProfileSampleAnnotation psa1("test1");
   ProfileSampleAnnotation psa2("test2");
   // Save a few classes using different annotations, some overlapping, some not.
-  for (uint16_t i = 0; i < 10; i++) {
+  for (uint16_t i = 0; i < 7; i++) {
     ASSERT_TRUE(AddClass(&info, dex1, dex::TypeIndex(i), psa1));
   }
-  for (uint16_t i = 5; i < 15; i++) {
+  for (uint16_t i = 3; i < 10; i++) {
     ASSERT_TRUE(AddClass(&info, dex1, dex::TypeIndex(i), psa2));
   }
 
   auto run_test = [&dex1 = dex1, &psa1 = psa1, &psa2 = psa2](const ProfileCompilationInfo& info) {
     // Check that all classes are in.
-    for (uint16_t i = 0; i < 10; i++) {
+    for (uint16_t i = 0; i < 7; i++) {
       EXPECT_TRUE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa1));
     }
-    for (uint16_t i = 5; i < 15; i++) {
+    for (uint16_t i = 3; i < 10; i++) {
       EXPECT_TRUE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa2));
     }
     // Check that the non-overlapping classes are not added with a wrong annotation.
-    for (uint16_t i = 10; i < 15; i++) {
+    for (uint16_t i = 7; i < 10; i++) {
       EXPECT_FALSE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa1));
     }
-    for (uint16_t i = 0; i < 5; i++) {
+    for (uint16_t i = 0; i < 3; i++) {
       EXPECT_FALSE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa2));
     }
     // Check that when querying without an annotation only the first one is searched.
-    for (uint16_t i = 0; i < 10; i++) {
+    for (uint16_t i = 0; i < 7; i++) {
       EXPECT_TRUE(info.ContainsClass(*dex1, dex::TypeIndex(i)));
     }
     // ... this should be false because they belong the second appearance of dex1.
-    for (uint16_t i = 10; i < 15; i++) {
+    for (uint16_t i = 7; i < 10; i++) {
       EXPECT_FALSE(info.ContainsClass(*dex1, dex::TypeIndex(i)));
     }
 
-    // Sanity check that classes cannot be found with a non existing annotation.
+    // Check that the classes cannot be found with a non existing annotation.
     EXPECT_FALSE(info.ContainsClass(*dex1, dex::TypeIndex(0), ProfileSampleAnnotation("new_test")));
   };
 
@@ -1554,7 +1574,6 @@
 
   // Check that we get back what we saved.
   ProfileCompilationInfo loaded_info;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
   ASSERT_TRUE(loaded_info.Equals(info));
 
@@ -1570,14 +1589,14 @@
   ProfileSampleAnnotation psa1("test1");
   ProfileSampleAnnotation psa2("test2");
 
-  for (uint16_t i = 0; i < 10; i++) {
-    ASSERT_TRUE(AddMethod(&info1, dex1, /* method_idx= */ i, Hotness::kFlagHot, psa1));
+  for (uint16_t i = 0; i < 7; i++) {
+    ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
     ASSERT_TRUE(AddClass(&info1, dex1, dex::TypeIndex(i), psa1));
   }
-  for (uint16_t i = 5; i < 15; i++) {
-    ASSERT_TRUE(AddMethod(&info2, dex1, /* method_idx= */ i, Hotness::kFlagHot, psa1));
-    ASSERT_TRUE(AddMethod(&info2, dex1, /* method_idx= */ i, Hotness::kFlagHot, psa2));
-    ASSERT_TRUE(AddMethod(&info2, dex2, /* method_idx= */ i, Hotness::kFlagHot, psa2));
+  for (uint16_t i = 3; i < 10; i++) {
+    ASSERT_TRUE(AddMethod(&info2, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
+    ASSERT_TRUE(AddMethod(&info2, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
+    ASSERT_TRUE(AddMethod(&info2, dex2, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
     ASSERT_TRUE(AddClass(&info2, dex1, dex::TypeIndex(i), psa1));
     ASSERT_TRUE(AddClass(&info2, dex1, dex::TypeIndex(i), psa2));
   }
@@ -1587,24 +1606,98 @@
   ASSERT_TRUE(info.MergeWith(info2));
 
   // Check that all items are in.
-  for (uint16_t i = 0; i < 15; i++) {
+  for (uint16_t i = 0; i < 10; i++) {
     EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa1).IsInProfile());
     EXPECT_TRUE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa1));
   }
-  for (uint16_t i = 5; i < 15; i++) {
+  for (uint16_t i = 3; i < 10; i++) {
     EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsInProfile());
     EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex2, i), psa2).IsInProfile());
     EXPECT_TRUE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa2));
   }
 
   // Check that the non-overlapping items are not added with a wrong annotation.
-  for (uint16_t i = 0; i < 5; i++) {
+  for (uint16_t i = 0; i < 3; i++) {
     EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsInProfile());
     EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex2, i), psa2).IsInProfile());
     EXPECT_FALSE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa2));
   }
 }
 
+// Verify we can merge samples with annotations.
+TEST_F(ProfileCompilationInfoTest, MergeWithInlineCaches) {
+  ProfileCompilationInfo info1(/*for_boot_image=*/ true);
+  ProfileCompilationInfo info2(/*for_boot_image=*/ true);
+  // TODO This should be something other than 'kNone'
+  ProfileSampleAnnotation psa1(ProfileSampleAnnotation::kNone);
+  std::vector<TypeReference> dex1_type_12 { TypeReference(dex1, dex::TypeIndex(1)),
+                                            TypeReference(dex1, dex::TypeIndex(2)) };
+  std::vector<TypeReference> dex1_type_48 { TypeReference(dex1, dex::TypeIndex(4)),
+                                            TypeReference(dex1, dex::TypeIndex(8)) };
+  std::vector<TypeReference> dex2_type_12 { TypeReference(dex2, dex::TypeIndex(1)),
+                                            TypeReference(dex2, dex::TypeIndex(2)) };
+  std::vector<TypeReference> dex2_type_48 { TypeReference(dex2, dex::TypeIndex(4)),
+                                            TypeReference(dex2, dex::TypeIndex(8)) };
+  std::vector<ProfileInlineCache> ic1 { ProfileInlineCache(
+                                            /*pc=*/ 12,
+                                            /*missing_types=*/ false,
+                                            /*profile_classes=*/ dex1_type_12),
+                                        ProfileInlineCache(
+                                            /*pc=*/ 15,
+                                            /*missing_types=*/ false,
+                                            /*profile_classes=*/ dex1_type_48) };
+  std::vector<ProfileInlineCache> ic2 { ProfileInlineCache(
+                                            /*pc=*/ 12,
+                                            /*missing_types=*/ false,
+                                            /*profile_classes=*/ dex2_type_48),
+                                        ProfileInlineCache(
+                                            /*pc=*/ 15,
+                                            /*missing_types=*/ false,
+                                            /*profile_classes=*/ dex2_type_12) };
+
+  for (uint16_t i = 0; i < 10; i++) {
+    ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ i, ic1, psa1));
+    ASSERT_TRUE(AddClass(&info1, dex1, dex::TypeIndex(i), psa1));
+    ASSERT_TRUE(AddClass(&info1, dex2, dex::TypeIndex(i), psa1));
+    ASSERT_TRUE(AddMethod(&info2, dex1, /*method_idx=*/ i, ic2, psa1));
+    ASSERT_TRUE(AddClass(&info2, dex1, dex::TypeIndex(i), psa1));
+    ASSERT_TRUE(AddClass(&info2, dex2, dex::TypeIndex(i), psa1));
+  }
+
+  ProfileCompilationInfo info_12(/*for_boot_image=*/ true);
+  ASSERT_TRUE(info_12.MergeWith(info1));
+  ASSERT_TRUE(info_12.MergeWith(info2));
+
+  // Check that all items are in.
+  for (uint16_t i = 0; i < 10; i++) {
+    EXPECT_TRUE(info_12.GetMethodHotness(MethodReference(dex1, i), psa1).IsInProfile());
+    EXPECT_TRUE(info_12.ContainsClass(*dex1, dex::TypeIndex(i), psa1));
+    ProfileCompilationInfo::MethodHotness loaded_ic_12 =
+        GetMethod(info_12, dex1, /*method_idx=*/ i);
+    ASSERT_TRUE(loaded_ic_12.IsHot());
+    std::vector<TypeReference> cls_pc12;
+    cls_pc12.resize(dex1_type_12.size() + dex2_type_48.size(),
+                    TypeReference(nullptr, dex::TypeIndex(-1)));
+    auto copy_end_12 = std::copy(dex1_type_12.begin(), dex1_type_12.end(), cls_pc12.begin());
+    std::copy(dex2_type_48.begin(), dex2_type_48.end(), copy_end_12);
+    std::vector<TypeReference> cls_pc15;
+    cls_pc15.resize(dex2_type_12.size() + dex1_type_48.size(),
+                    TypeReference(nullptr, dex::TypeIndex(-1)));
+    auto copy_end_15 = std::copy(dex2_type_12.begin(), dex2_type_12.end(), cls_pc15.begin());
+    std::copy(dex1_type_48.begin(), dex1_type_48.end(), copy_end_15);
+    std::vector<ProfileInlineCache> expected{ ProfileInlineCache(
+                                                      /*pc=*/ 12,
+                                                      /*missing_types=*/ false,
+                                                      /*profile_classes=*/ cls_pc12),
+                                              ProfileInlineCache(
+                                                      /*pc=*/ 15,
+                                                      /*missing_types=*/ false,
+                                                      /*profile_classes=*/ cls_pc15) };
+    EXPECT_EQ(loaded_ic_12.GetInlineCacheMap()->size(), expected.size());
+    EXPECT_TRUE(EqualInlineCaches(expected, dex1, loaded_ic_12, info_12)) << i;
+  }
+}
+
 // Verify the bulk extraction API.
 TEST_F(ProfileCompilationInfoTest, ExtractInfoWithAnnations) {
   ProfileCompilationInfo info;
@@ -1618,14 +1711,14 @@
   std::set<uint16_t> expected_post_startup_methods;
 
   for (uint16_t i = 0; i < 10; i++) {
-    ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ i, Hotness::kFlagHot, psa1));
+    ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
     ASSERT_TRUE(AddClass(&info, dex1, dex::TypeIndex(i), psa1));
     expected_hot_methods.insert(i);
     expected_classes.insert(dex::TypeIndex(i));
   }
   for (uint16_t i = 5; i < 15; i++) {
-    ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ i, Hotness::kFlagHot, psa2));
-    ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ i, Hotness::kFlagStartup, psa1));
+    ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
+    ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagStartup, psa1));
     expected_startup_methods.insert(i);
   }
 
@@ -1691,7 +1784,7 @@
 TEST_F(ProfileCompilationInfoTest, ClearDataAndAdjustVersionRegularToBoot) {
   ProfileCompilationInfo info;
 
-  AddMethod(&info, dex1, /* method_idx= */ 0, Hotness::kFlagHot);
+  AddMethod(&info, dex1, /*method_idx=*/ 0, Hotness::kFlagHot);
 
   info.ClearDataAndAdjustVersion(/*for_boot_image=*/true);
   ASSERT_TRUE(info.IsEmpty());
@@ -1701,7 +1794,7 @@
 TEST_F(ProfileCompilationInfoTest, ClearDataAndAdjustVersionBootToRegular) {
   ProfileCompilationInfo info(/*for_boot_image=*/true);
 
-  AddMethod(&info, dex1, /* method_idx= */ 0, Hotness::kFlagHot);
+  AddMethod(&info, dex1, /*method_idx=*/ 0, Hotness::kFlagHot);
 
   info.ClearDataAndAdjustVersion(/*for_boot_image=*/false);
   ASSERT_TRUE(info.IsEmpty());
@@ -1725,13 +1818,13 @@
 
   for (uint16_t i = 0; i < 10; i++) {
     // Add dex1 data with different annotations so that we can check the annotation count.
-    ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ i, Hotness::kFlagHot, psa1));
+    ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
     ASSERT_TRUE(AddClass(&info, dex1, dex::TypeIndex(i), psa1));
-    ASSERT_TRUE(AddMethod(&info, dex1, /* method_idx= */ i, Hotness::kFlagStartup, psa2));
+    ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagStartup, psa2));
     ASSERT_TRUE(AddClass(&info, dex1, dex::TypeIndex(i), psa2));
-    ASSERT_TRUE(AddMethod(&info, dex2, /* method_idx= */ i, Hotness::kFlagHot, psa2));
+    ASSERT_TRUE(AddMethod(&info, dex2, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
     // dex3 will not be used in the data extraction
-    ASSERT_TRUE(AddMethod(&info, dex3, /* method_idx= */ i, Hotness::kFlagHot, psa2));
+    ASSERT_TRUE(AddMethod(&info, dex3, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
   }
 
   std::vector<std::unique_ptr<const DexFile>> dex_files;
@@ -1789,12 +1882,12 @@
 
   for (uint16_t i = 0; i < 10; i++) {
     // Add dex1 data with different annotations so that we can check the annotation count.
-    ASSERT_TRUE(AddMethod(&info1, dex1, /* method_idx= */ i, Hotness::kFlagHot, psa1));
+    ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
     ASSERT_TRUE(AddClass(&info2, dex1, dex::TypeIndex(i), psa1));
-    ASSERT_TRUE(AddMethod(&info1, dex1, /* method_idx= */ i, Hotness::kFlagStartup, psa2));
+    ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ i, Hotness::kFlagStartup, psa2));
     ASSERT_TRUE(AddClass(&info1, dex1, dex::TypeIndex(i), psa2));
     ASSERT_TRUE(AddMethod(i % 2 == 0 ? &info1 : &info2, dex2,
-                          /* method_idx= */ i,
+                          /*method_idx=*/ i,
                           Hotness::kFlagHot,
                           psa2));
   }
diff --git a/libprofile/profile/profile_test_helper.h b/libprofile/profile/profile_test_helper.h
new file mode 100644
index 0000000..9410620
--- /dev/null
+++ b/libprofile/profile/profile_test_helper.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2021 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_LIBPROFILE_PROFILE_PROFILE_TEST_HELPER_H_
+#define ART_LIBPROFILE_PROFILE_PROFILE_TEST_HELPER_H_
+
+#include <memory>
+#include <vector>
+
+#include "dex/test_dex_file_builder.h"
+#include "profile/profile_compilation_info.h"
+
+namespace art {
+
+class ProfileTestHelper {
+ public:
+  ProfileTestHelper() = default;
+
+  using Hotness = ProfileCompilationInfo::MethodHotness;
+  using ProfileInlineCache = ProfileMethodInfo::ProfileInlineCache;
+  using ProfileSampleAnnotation = ProfileCompilationInfo::ProfileSampleAnnotation;
+  using ProfileIndexType = ProfileCompilationInfo::ProfileIndexType;
+
+  static bool AddMethod(
+      ProfileCompilationInfo* info,
+      const DexFile* dex,
+      uint16_t method_idx,
+      const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
+    return AddMethod(info, dex, method_idx, Hotness::kFlagHot, annotation);
+  }
+
+  static bool AddMethod(
+      ProfileCompilationInfo* info,
+      const DexFile* dex,
+      uint16_t method_idx,
+      Hotness::Flag flags,
+      const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
+    return info->AddMethod(
+        ProfileMethodInfo(MethodReference(dex, method_idx)), flags, annotation);
+  }
+
+  static bool AddMethod(
+      ProfileCompilationInfo* info,
+      const DexFile* dex,
+      uint16_t method_idx,
+      const std::vector<ProfileInlineCache>& inline_caches,
+      const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
+    return AddMethod(info, dex, method_idx, inline_caches, Hotness::kFlagHot, annotation);
+  }
+
+  static bool AddMethod(
+      ProfileCompilationInfo* info,
+      const DexFile* dex,
+      uint16_t method_idx,
+      const std::vector<ProfileInlineCache>& inline_caches,
+      Hotness::Flag flags,
+      const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
+    return info->AddMethod(
+        ProfileMethodInfo(MethodReference(dex, method_idx), inline_caches), flags, annotation);
+  }
+
+  static bool AddClass(ProfileCompilationInfo* info,
+                       const DexFile* dex,
+                       dex::TypeIndex type_index,
+                       const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
+    return info->AddClass(*dex, type_index, annotation);
+  }
+
+  static bool ProfileIndexMatchesDexFile(const ProfileCompilationInfo& info,
+                                         ProfileIndexType profile_index,
+                                         const DexFile* dex_file) {
+    DCHECK(dex_file != nullptr);
+    std::array<const DexFile*, 1u> dex_files{dex_file};
+    return dex_file == info.FindDexFileForProfileIndex(profile_index, dex_files);
+  }
+
+  // Compare different representations of inline caches for equality.
+  static bool EqualInlineCaches(const std::vector<ProfileMethodInfo::ProfileInlineCache>& expected,
+                                const DexFile* dex_file,
+                                const ProfileCompilationInfo::MethodHotness& actual_hotness,
+                                const ProfileCompilationInfo& info) {
+    CHECK(actual_hotness.IsHot());
+    CHECK(actual_hotness.GetInlineCacheMap() != nullptr);
+    const ProfileCompilationInfo::InlineCacheMap& actual = *actual_hotness.GetInlineCacheMap();
+    if (expected.size() != actual.size()) {
+      return false;
+    }
+    // The `expected` data should be sorted by dex pc.
+    CHECK(std::is_sorted(expected.begin(),
+                         expected.end(),
+                         [](auto&& lhs, auto&& rhs) { return lhs.dex_pc < rhs.dex_pc; }));
+    // The `actual` data is a map sorted by dex pc, so we can just iterate over both.
+    auto expected_it = expected.begin();
+    for (auto it = actual.begin(), end = actual.end(); it != end; ++it, ++expected_it) {
+      uint32_t dex_pc = it->first;
+      const ProfileCompilationInfo::DexPcData& dex_pc_data = it->second;
+      if (dex_pc != expected_it->dex_pc) {
+        return false;
+      }
+      if (dex_pc_data.is_missing_types != expected_it->is_missing_types) {
+        return false;
+      } else if (dex_pc_data.is_missing_types) {
+        continue;  // The classes do not matter if we're missing some types.
+      }
+      // The `expected_it->is_megamorphic` is not initialized. Check the number of classes.
+      bool expected_is_megamorphic =
+          (expected_it->classes.size() >= ProfileCompilationInfo::kIndividualInlineCacheSize);
+      if (dex_pc_data.is_megamorphic != expected_is_megamorphic) {
+        return false;
+      } else if (dex_pc_data.is_megamorphic) {
+        continue;  // The classes do not matter if the inline cache is megamorphic.
+      }
+      if (dex_pc_data.classes.size() != expected_it->classes.size()) {
+        return false;
+      }
+      for (dex::TypeIndex type_index : dex_pc_data.classes) {
+        if (std::none_of(expected_it->classes.begin(),
+                         expected_it->classes.end(),
+                         [&](const TypeReference& type_ref) {
+                           if (type_ref.dex_file == dex_file) {
+                             return type_index == type_ref.TypeIndex();
+                           } else {
+                             const char* expected_descriptor =
+                                 type_ref.dex_file->StringByTypeIdx(type_ref.TypeIndex());
+                             const char* descriptor = info.GetTypeDescriptor(dex_file, type_index);
+                             return strcmp(expected_descriptor, descriptor) == 0;
+                           }
+                         })) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+ protected:
+  static constexpr size_t kNumSharedTypes = 10u;
+
+  const DexFile* BuildDex(const std::string& location,
+                          uint32_t location_checksum,
+                          const std::string& class_descriptor,
+                          size_t num_method_ids,
+                          size_t num_class_ids = kNumSharedTypes + 1u) {
+    TestDexFileBuilder builder;
+    builder.AddType(class_descriptor);
+    CHECK_NE(num_class_ids, 0u);
+    size_t num_shared_ids = std::min(num_class_ids - 1u, kNumSharedTypes);
+    for (size_t shared_type_index = 0; shared_type_index != num_shared_ids; ++shared_type_index) {
+      builder.AddType("LSharedType" + std::to_string(shared_type_index) + ";");
+    }
+    for (size_t i = 1u + num_shared_ids; i < num_class_ids; ++i) {
+      builder.AddType("LFiller" + std::to_string(i) + ";");
+    }
+    for (size_t method_index = 0; method_index != num_method_ids; ++method_index) {
+      // Some tests add the maximum number of methods (`num_method_ids` is 2^16) and we
+      // do not want to waste memory with that many unique name strings (with identical
+      // proto id). So create up to num_shared_ids^2 proto ids and only
+      // num_method_ids/num_shared_ids^2 names.
+      size_t return_type_index = method_index % num_shared_ids;
+      size_t arg_type_index = (method_index / num_shared_ids) % num_shared_ids;
+      size_t method_name_index = (method_index / num_shared_ids) / num_shared_ids;
+      std::string return_type = "LSharedType" + std::to_string(return_type_index) + ";";
+      std::string arg_type = "LSharedType" + std::to_string(arg_type_index) + ";";
+      std::string signature = "(" + arg_type + ")" + return_type;
+      builder.AddMethod(class_descriptor, signature, "m" + std::to_string(method_name_index));
+    }
+    storage.push_back(builder.Build(location, location_checksum));
+    return storage.back().get();
+  }
+
+  std::vector<std::unique_ptr<const DexFile>> storage;
+};
+
+}  // namespace art
+
+#endif  // ART_LIBPROFILE_PROFILE_PROFILE_TEST_HELPER_H_
diff --git a/oatdump/Android.bp b/oatdump/Android.bp
index e36d9d7..a8e6dfe 100644
--- a/oatdump/Android.bp
+++ b/oatdump/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "oatdump-defaults",
     defaults: ["art_defaults"],
@@ -24,41 +33,105 @@
     ],
 }
 
+// Collect all the static defaults and build a host-only static library, which
+// is then used for the (mostly) static host oatdump binary.
+art_cc_library_static {
+    name: "liboatdump_static",
+    device_supported: false,
+    host_supported: true,
+    defaults: [
+        "libart-compiler_static_defaults",
+        "libart-dexlayout_static_defaults",
+        "libart-disassembler_static_defaults",
+        "libart_static_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+        "libprofile_static_defaults",
+        "oatdump-defaults",
+    ],
+    whole_static_libs: [
+        "libbase",
+    ],
+}
+
 art_cc_binary {
     name: "oatdump",
     defaults: ["oatdump-defaults"],
-    shared_libs: [
-        "libart",
-        "libart-compiler",
-        "libart-dexlayout",
-        "libart-disassembler",
-        "libdexfile",
-        "libartbase",
-        "libprofile",
-        "libbase",
-    ],
+
+    target: {
+        android: {
+            shared_libs: [
+                "libart",
+                "libart-compiler",
+                "libart-dexlayout",
+                "libart-disassembler",
+                "libartbase",
+                "libbase",
+                "libdexfile",
+                "libprofile",
+            ],
+        },
+        host: {
+            // Make the host binary static, except for system libraries.
+            static_libs: ["liboatdump_static"],
+            stl: "c++_static",
+        },
+    },
+
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
 
+// Collect all the static defaults and build a host-only static library, which
+// is then used for the (mostly) static host oatdump binary.
+art_cc_library_static {
+    name: "liboatdumpd_static",
+    device_supported: false,
+    host_supported: true,
+    defaults: [
+        "libartd-compiler_static_defaults",
+        "libartd-dexlayout_static_defaults",
+        "libartd-disassembler_static_defaults",
+        "libartd_static_defaults",
+        "libartbased_static_defaults",
+        "libdexfiled_static_defaults",
+        "libprofiled_static_defaults",
+        "oatdump-defaults",
+    ],
+    whole_static_libs: [
+        "libbase",
+    ],
+}
+
 art_cc_binary {
     name: "oatdumpd",
     defaults: [
         "art_debug_defaults",
         "oatdump-defaults",
     ],
-    shared_libs: [
-        "libartd",
-        "libartd-compiler",
-        "libartd-dexlayout",
-        "libartd-disassembler",
-        "libdexfiled",
-        "libartbased",
-        "libprofiled",
-        "libbase",
-    ],
+
+    target: {
+        android: {
+            shared_libs: [
+                "libartbased",
+                "libartd",
+                "libartd-compiler",
+                "libartd-dexlayout",
+                "libartd-disassembler",
+                "libbase",
+                "libdexfiled",
+                "libprofiled",
+            ],
+        },
+        host: {
+            // Make the host binary static, except for system libraries.
+            static_libs: ["liboatdumpd_static"],
+            stl: "c++_static",
+        },
+    },
+
     apex_available: [
         "com.android.art.debug",
     ],
@@ -84,7 +157,7 @@
         // Try to get rid of it.
         "-z muldefs",
     ],
-    static_libs: ["libsigchain_dummy"],
+    static_libs: ["libsigchain_fake"],
 }
 
 art_cc_binary {
@@ -121,11 +194,6 @@
         "libartd-dexlayout_static_defaults",
         "oatdumps-defaults",
     ],
-    target: {
-        linux_glibc_x86_64: {
-            use_clang_lld: true,
-        },
-    },
     static_libs: [
         "libartd-disassembler",
         "libvixld",
@@ -133,14 +201,45 @@
     group_static_libs: true,
 }
 
-art_cc_test {
-    name: "art_oatdump_tests",
-    defaults: [
-        "art_gtest_defaults",
+art_cc_defaults {
+    name: "art_oatdump_tests_defaults",
+    data: [
+        ":art-gtest-jars-ProfileTestMultiDex",
     ],
     srcs: [
         "oatdump_app_test.cc",
         "oatdump_test.cc",
         "oatdump_image_test.cc",
     ],
+    target: {
+        host: {
+            required: [
+                "dex2oatd",
+                "dex2oatds",
+                "dexdump",
+                "oatdumpd",
+                "oatdumpds",
+            ],
+        },
+    },
+}
+
+// Version of ART gtest `art_oatdump_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
+art_cc_test {
+    name: "art_oatdump_tests",
+    defaults: [
+        "art_gtest_defaults",
+        "art_oatdump_tests_defaults",
+    ],
+}
+
+// Standalone version of ART gtest `art_oatdump_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_oatdump_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_oatdump_tests_defaults",
+    ],
+    test_config: "art_standalone_oatdump_tests.xml",
 }
diff --git a/oatdump/Android.mk b/oatdump/Android.mk
index 317f9cd..e5375eb 100644
--- a/oatdump/Android.mk
+++ b/oatdump/Android.mk
@@ -16,50 +16,5 @@
 
 LOCAL_PATH := $(call my-dir)
 
-########################################################################
-# oatdump targets
-
-ART_DUMP_OAT_PATH ?= $(OUT_DIR)
-
-OATDUMP := $(HOST_OUT_EXECUTABLES)/oatdump$(HOST_EXECUTABLE_SUFFIX)
-OATDUMPD := $(HOST_OUT_EXECUTABLES)/oatdumpd$(HOST_EXECUTABLE_SUFFIX)
-# TODO: for now, override with debug version for better error reporting
-OATDUMP := $(OATDUMPD)
-
 .PHONY: dump-oat
-dump-oat: dump-oat-core dump-oat-boot
-
-.PHONY: dump-oat-core
-dump-oat-core: dump-oat-core-host dump-oat-core-target
-
-.PHONY: dump-oat-core-host
-ifeq ($(ART_BUILD_HOST),true)
-dump-oat-core-host: $(HOST_CORE_IMG_OUTS) $(OATDUMP)
-	$(OATDUMP) --image=$(HOST_CORE_IMG_LOCATION) --output=$(ART_DUMP_OAT_PATH)/core.host.oatdump.txt
-	@echo Output in $(ART_DUMP_OAT_PATH)/core.host.oatdump.txt
-endif
-
-.PHONY: dump-oat-core-target-$(TARGET_ARCH)
-ifeq ($(ART_BUILD_TARGET),true)
-dump-oat-core-target-$(TARGET_ARCH): $(TARGET_CORE_IMAGE_DEFAULT_$(ART_PHONY_TEST_TARGET_SUFFIX)) $(OATDUMP)
-	$(OATDUMP) --image=$(TARGET_CORE_IMG_LOCATION) \
-	  --output=$(ART_DUMP_OAT_PATH)/core.target.$(TARGET_ARCH).oatdump.txt --instruction-set=$(TARGET_ARCH)
-	@echo Output in $(ART_DUMP_OAT_PATH)/core.target.$(TARGET_ARCH).oatdump.txt
-endif
-
-ifdef TARGET_2ND_ARCH
-.PHONY: dump-oat-core-target-$(TARGET_2ND_ARCH)
-ifeq ($(ART_BUILD_TARGET),true)
-dump-oat-core-target-$(TARGET_2ND_ARCH): $(TARGET_CORE_IMAGE_DEFAULT_$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)) $(OATDUMP)
-	$(OATDUMP) --image=$(TARGET_CORE_IMG_LOCATION) \
-	  --output=$(ART_DUMP_OAT_PATH)/core.target.$(TARGET_2ND_ARCH).oatdump.txt --instruction-set=$(TARGET_2ND_ARCH)
-	@echo Output in $(ART_DUMP_OAT_PATH)/core.target.$(TARGET_2ND_ARCH).oatdump.txt
-endif
-endif
-
-.PHONY: dump-oat-core-target
-dump-oat-core-target: dump-oat-core-target-$(TARGET_ARCH)
-ifdef TARGET_2ND_ARCH
-dump-oat-core-target: dump-oat-core-target-$(TARGET_2ND_ARCH)
-endif
-
+dump-oat: dump-oat-boot
diff --git a/oatdump/art_standalone_oatdump_tests.xml b/oatdump/art_standalone_oatdump_tests.xml
new file mode 100644
index 0000000..e83d2a2
--- /dev/null
+++ b/oatdump/art_standalone_oatdump_tests.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs art_standalone_oatdump_tests.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art_standalone_oatdump_tests->/data/local/tmp/nativetest/art_standalone_oatdump_tests" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art-gtest-jars-ProfileTestMultiDex.jar->/data/local/tmp/nativetest/art-gtest-jars-ProfileTestMultiDex.jar" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/nativetest" />
+        <option name="module-name" value="art_standalone_oatdump_tests" />
+        <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+        <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 8d33970..df31ded 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -39,12 +39,12 @@
 #include "base/indenter.h"
 #include "base/os.h"
 #include "base/safe_map.h"
-#include "base/stats.h"
+#include "base/stats-inl.h"
 #include "base/stl_util.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker-inl.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "compiled_method.h"
 #include "debug/debug_info.h"
 #include "debug/elf_debug_writer.h"
@@ -201,6 +201,7 @@
     DO_TRAMPOLINE(QuickImtConflictTrampoline);
     DO_TRAMPOLINE(QuickResolutionTrampoline);
     DO_TRAMPOLINE(QuickToInterpreterBridge);
+    DO_TRAMPOLINE(NterpTrampoline);
     #undef DO_TRAMPOLINE
 
     Walk();
@@ -251,13 +252,13 @@
       const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
       OatClassType type = oat_class.GetType();
       switch (type) {
-        case kOatClassAllCompiled:
-        case kOatClassSomeCompiled:
+        case OatClassType::kAllCompiled:
+        case OatClassType::kSomeCompiled:
           WalkOatClass(oat_class, *dex_file, class_def_index);
           break;
 
-        case kOatClassNoneCompiled:
-        case kOatClassMax:
+        case OatClassType::kNoneCompiled:
+        case OatClassType::kOatClassMax:
           // Ignore.
           break;
       }
@@ -458,6 +459,8 @@
                            GetQuickResolutionTrampolineOffset);
     DUMP_OAT_HEADER_OFFSET("QUICK TO INTERPRETER BRIDGE",
                            GetQuickToInterpreterBridgeOffset);
+    DUMP_OAT_HEADER_OFFSET("NTERP_TRAMPOLINE",
+                           GetNterpTrampolineOffset);
 #undef DUMP_OAT_HEADER_OFFSET
 
     // Print the key-value store.
@@ -542,6 +545,20 @@
             [=](uint32_t index) { return dex_file->PrettyType(dex::TypeIndex(index)); });
         DumpBssEntries(
             os,
+            "Public Class",
+            oat_dex_file->GetPublicTypeBssMapping(),
+            dex_file->NumTypeIds(),
+            sizeof(GcRoot<mirror::Class>),
+            [=](uint32_t index) { return dex_file->PrettyType(dex::TypeIndex(index)); });
+        DumpBssEntries(
+            os,
+            "Package Class",
+            oat_dex_file->GetPackageTypeBssMapping(),
+            dex_file->NumTypeIds(),
+            sizeof(GcRoot<mirror::Class>),
+            [=](uint32_t index) { return dex_file->PrettyType(dex::TypeIndex(index)); });
+        DumpBssEntries(
+            os,
             "String",
             oat_dex_file->GetStringBssMapping(),
             dex_file->NumStringIds(),
@@ -552,7 +569,7 @@
 
     if (!options_.dump_header_only_) {
       VariableIndentationOutputStream vios(&os);
-      VdexFile::VerifierDepsHeader vdex_header = oat_file_.GetVdexFile()->GetVerifierDepsHeader();
+      VdexFile::VdexFileHeader vdex_header = oat_file_.GetVdexFile()->GetVdexFileHeader();
       if (vdex_header.IsValid()) {
         std::string error_msg;
         std::vector<const DexFile*> dex_files;
@@ -564,15 +581,17 @@
           }
           dex_files.push_back(dex_file);
         }
-        verifier::VerifierDeps deps(dex_files, oat_file_.GetVdexFile()->GetVerifierDepsData());
+        verifier::VerifierDeps deps(dex_files, /*output_only=*/ false);
+        if (!deps.ParseStoredData(dex_files, oat_file_.GetVdexFile()->GetVerifierDepsData())) {
+          os << "Error parsing verifier dependencies." << std::endl;
+          return false;
+        }
         deps.Dump(&vios);
       } else {
         os << "UNRECOGNIZED vdex file, magic "
            << vdex_header.GetMagic()
-           << ", verifier deps version "
-           << vdex_header.GetVerifierDepsVersion()
-           << ", dex section version "
-           << vdex_header.GetDexSectionVersion()
+           << ", version "
+           << vdex_header.GetVdexVersion()
            << "\n";
       }
       for (size_t i = 0; i < oat_dex_files_.size(); i++) {
@@ -593,9 +612,9 @@
       }
 
       DexFileUniqV vdex_dex_files;
-      std::unique_ptr<const VdexFile> vdex_file = OpenVdexUnquicken(vdex_filename,
-                                                                    &vdex_dex_files,
-                                                                    &error_msg);
+      std::unique_ptr<const VdexFile> vdex_file = OpenVdex(vdex_filename,
+                                                           &vdex_dex_files,
+                                                           &error_msg);
       if (vdex_file.get() == nullptr) {
         os << "Failed to open vdex file: " << error_msg << "\n";
         return false;
@@ -675,7 +694,7 @@
       os << "OAT FILE STATS:\n";
       VariableIndentationOutputStream vios(&os);
       stats_.AddBytes(oat_file_.Size());
-      DumpStats(vios, "OatFile", stats_, stats_.Value());
+      stats_.DumpSizes(vios, "OatFile");
     }
 
     os << std::flush;
@@ -743,10 +762,10 @@
   }
 
   // Returns nullptr and updates error_msg if the Vdex file cannot be opened, otherwise all Dex
-  // files are fully unquickened and stored in dex_files
-  std::unique_ptr<const VdexFile> OpenVdexUnquicken(const std::string& vdex_filename,
-                                                    /* out */ DexFileUniqV* dex_files,
-                                                    /* out */ std::string* error_msg) {
+  // files are stored in dex_files.
+  std::unique_ptr<const VdexFile> OpenVdex(const std::string& vdex_filename,
+                                           /* out */ DexFileUniqV* dex_files,
+                                           /* out */ std::string* error_msg) {
     std::unique_ptr<const File> file(OS::OpenFileForReading(vdex_filename.c_str()));
     if (file == nullptr) {
       *error_msg = "Could not open file " + vdex_filename + " for reading.";
@@ -785,9 +804,6 @@
       return nullptr;
     }
 
-    vdex_file->Unquicken(MakeNonOwningPointerVector(tmp_dex_files),
-                         /* decompile_return_instruction= */ true);
-
     *dex_files = std::move(tmp_dex_files);
     return vdex_file;
   }
@@ -796,39 +812,6 @@
     return seen_stats_objects_.insert(address).second;  // Inserted new entry.
   }
 
-  void DumpStats(VariableIndentationOutputStream& os,
-                 const std::string& name,
-                 const Stats& stats,
-                 double total) {
-    if (std::fabs(stats.Value()) > 0 || !stats.Children().empty()) {
-      double percent = 100.0 * stats.Value() / total;
-      os.Stream()
-          << std::setw(40 - os.GetIndentation()) << std::left << name << std::right << " "
-          << std::setw(8) << stats.Count() << " "
-          << std::setw(12) << std::fixed << std::setprecision(3) << stats.Value() / KB << "KB "
-          << std::setw(8) << std::fixed << std::setprecision(1) << percent << "%\n";
-
-      // Sort all children by largest value first, than by name.
-      std::map<std::pair<double, std::string>, const Stats&> sorted_children;
-      for (const auto& it : stats.Children()) {
-        sorted_children.emplace(std::make_pair(-it.second.Value(), it.first), it.second);
-      }
-
-      // Add "other" row to represent any amount not account for by the children.
-      Stats other;
-      other.AddBytes(stats.Value() - stats.SumChildrenValues(), stats.Count());
-      if (std::fabs(other.Value()) > 0 && !stats.Children().empty()) {
-        sorted_children.emplace(std::make_pair(-other.Value(), "(other)"), other);
-      }
-
-      // Print the data.
-      ScopedIndentation indent1(&os);
-      for (const auto& it : sorted_children) {
-        DumpStats(os, it.first.second, it.second, total);
-      }
-    }
-  }
-
  private:
   void AddAllOffsets() {
     // We don't know the length of the code for each method, but we need to know where to stop
@@ -1144,7 +1127,12 @@
       vios->Stream() << "DEX CODE:\n";
       ScopedIndentation indent2(vios);
       if (code_item_accessor.HasCodeItem()) {
+        uint32_t max_pc = code_item_accessor.InsnsSizeInCodeUnits();
         for (const DexInstructionPcPair& inst : code_item_accessor) {
+          if (inst.DexPc() + inst->SizeInCodeUnits() > max_pc) {
+            LOG(WARNING) << "GLITCH: run-away instruction at idx=0x" << std::hex << inst.DexPc();
+            break;
+          }
           vios->Stream() << StringPrintf("0x%04x: ", inst.DexPc()) << inst->DumpHexLE(5)
                          << StringPrintf("\t| %s\n", inst->DumpString(&dex_file).c_str());
         }
@@ -1194,15 +1182,16 @@
       uint32_t method_header_offset = oat_method.GetOatQuickMethodHeaderOffset();
       const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader();
       if (AddStatsObject(method_header)) {
-        stats_.Child("QuickMethodHeader")->AddBytes(sizeof(*method_header));
+        stats_["QuickMethodHeader"].AddBytes(sizeof(*method_header));
       }
       if (options_.absolute_addresses_) {
         vios->Stream() << StringPrintf("%p ", method_header);
       }
       vios->Stream() << StringPrintf("(offset=0x%08x)\n", method_header_offset);
-      if (method_header_offset > oat_file_.Size()) {
+      if (method_header_offset > oat_file_.Size() ||
+          sizeof(OatQuickMethodHeader) > oat_file_.Size() - method_header_offset) {
         vios->Stream() << StringPrintf(
-            "WARNING: oat quick method header offset 0x%08x is past end of file 0x%08zx.\n",
+            "WARNING: oat quick method header at offset 0x%08x is past end of file 0x%08zx.\n",
             method_header_offset, oat_file_.Size());
         // If we can't read the OatQuickMethodHeader, the rest of the data is dangerous to read.
         vios->Stream() << std::flush;
@@ -1214,8 +1203,8 @@
       if (options_.absolute_addresses_) {
         vios->Stream() << StringPrintf("%p ", oat_method.GetVmapTable());
       }
-      uint32_t vmap_table_offset = method_header ==
-          nullptr ? 0 : method_header->GetVmapTableOffset();
+      uint32_t vmap_table_offset =
+          (method_header == nullptr) ? 0 : method_header->GetCodeInfoOffset();
       vios->Stream() << StringPrintf("(offset=0x%08x)\n", vmap_table_offset);
 
       size_t vmap_table_offset_limit =
@@ -1224,11 +1213,9 @@
               : method_header->GetCode() - oat_file_.Begin();
       if (vmap_table_offset >= vmap_table_offset_limit) {
         vios->Stream() << StringPrintf("WARNING: "
-                                       "vmap table offset 0x%08x is past end of file 0x%08zx. "
-                                       "vmap table offset was loaded from offset 0x%08x.\n",
+                                       "vmap table offset 0x%08x is past end of file 0x%08zx. ",
                                        vmap_table_offset,
-                                       vmap_table_offset_limit,
-                                       oat_method.GetVmapTableOffsetOffset());
+                                       vmap_table_offset_limit);
         success = false;
       } else if (options_.dump_vmap_) {
         DumpVmapData(vios, oat_method, code_item_accessor);
@@ -1256,27 +1243,19 @@
     }
     {
       vios->Stream() << "CODE: ";
-      uint32_t code_size_offset = oat_method.GetQuickCodeSizeOffset();
-      if (code_size_offset > oat_file_.Size()) {
-        ScopedIndentation indent2(vios);
-        vios->Stream() << StringPrintf("WARNING: "
-                                       "code size offset 0x%08x is past end of file 0x%08zx.",
-                                       code_size_offset, oat_file_.Size());
-        success = false;
-      } else {
+      {
         const void* code = oat_method.GetQuickCode();
         uint32_t aligned_code_begin = AlignCodeOffset(code_offset);
         uint64_t aligned_code_end = aligned_code_begin + code_size;
         if (AddStatsObject(code)) {
-          stats_.Child("Code")->AddBytes(code_size);
+          stats_["Code"].AddBytes(code_size);
         }
 
         if (options_.absolute_addresses_) {
           vios->Stream() << StringPrintf("%p ", code);
         }
-        vios->Stream() << StringPrintf("(code_offset=0x%08x size_offset=0x%08x size=%u)%s\n",
+        vios->Stream() << StringPrintf("(code_offset=0x%08x size=%u)%s\n",
                                        code_offset,
-                                       code_size_offset,
                                        code_size,
                                        code != nullptr ? "..." : "");
 
@@ -1290,12 +1269,13 @@
           vios->Stream() << StringPrintf(
               "WARNING: "
               "end of code at 0x%08" PRIx64 " is past end of file 0x%08zx. "
-              "code size is 0x%08x loaded from offset 0x%08x.\n",
-              aligned_code_end, oat_file_.Size(),
-              code_size, code_size_offset);
+              "code size is 0x%08x.\n",
+              aligned_code_end,
+              oat_file_.Size(),
+              code_size);
           success = false;
           if (options_.disassemble_code_) {
-            if (code_size_offset + kPrologueBytes <= oat_file_.Size()) {
+            if (aligned_code_begin + kPrologueBytes <= oat_file_.Size()) {
               DumpCode(vios, oat_method, code_item_accessor, true, kPrologueBytes);
             }
           }
@@ -1303,12 +1283,13 @@
           vios->Stream() << StringPrintf(
               "WARNING: "
               "code size %d is bigger than max expected threshold of %d. "
-              "code size is 0x%08x loaded from offset 0x%08x.\n",
-              code_size, kMaxCodeSize,
-              code_size, code_size_offset);
+              "code size is 0x%08x.\n",
+              code_size,
+              kMaxCodeSize,
+              code_size);
           success = false;
           if (options_.disassemble_code_) {
-            if (code_size_offset + kPrologueBytes <= oat_file_.Size()) {
+            if (aligned_code_begin + kPrologueBytes <= oat_file_.Size()) {
               DumpCode(vios, oat_method, code_item_accessor, true, kPrologueBytes);
             }
           }
@@ -1520,87 +1501,6 @@
     return nullptr;
   }
 
-  // The StackMapsHelper provides the stack maps in the native PC order.
-  // For identical native PCs, the order from the CodeInfo is preserved.
-  class StackMapsHelper {
-   public:
-    explicit StackMapsHelper(const uint8_t* raw_code_info, InstructionSet instruction_set)
-        : code_info_(raw_code_info),
-          number_of_stack_maps_(code_info_.GetNumberOfStackMaps()),
-          indexes_(),
-          offset_(static_cast<uint32_t>(-1)),
-          stack_map_index_(0u),
-          instruction_set_(instruction_set) {
-      if (number_of_stack_maps_ != 0u) {
-        // Check if native PCs are ordered.
-        bool ordered = true;
-        StackMap last = code_info_.GetStackMapAt(0u);
-        for (size_t i = 1; i != number_of_stack_maps_; ++i) {
-          StackMap current = code_info_.GetStackMapAt(i);
-          if (last.GetNativePcOffset(instruction_set) >
-              current.GetNativePcOffset(instruction_set)) {
-            ordered = false;
-            break;
-          }
-          last = current;
-        }
-        if (!ordered) {
-          // Create indirection indexes for access in native PC order. We do not optimize
-          // for the fact that there can currently be only two separately ordered ranges,
-          // namely normal stack maps and catch-point stack maps.
-          indexes_.resize(number_of_stack_maps_);
-          std::iota(indexes_.begin(), indexes_.end(), 0u);
-          std::sort(indexes_.begin(),
-                    indexes_.end(),
-                    [this](size_t lhs, size_t rhs) {
-                      StackMap left = code_info_.GetStackMapAt(lhs);
-                      uint32_t left_pc = left.GetNativePcOffset(instruction_set_);
-                      StackMap right = code_info_.GetStackMapAt(rhs);
-                      uint32_t right_pc = right.GetNativePcOffset(instruction_set_);
-                      // If the PCs are the same, compare indexes to preserve the original order.
-                      return (left_pc < right_pc) || (left_pc == right_pc && lhs < rhs);
-                    });
-        }
-        offset_ = GetStackMapAt(0).GetNativePcOffset(instruction_set_);
-      }
-    }
-
-    const CodeInfo& GetCodeInfo() const {
-      return code_info_;
-    }
-
-    uint32_t GetOffset() const {
-      return offset_;
-    }
-
-    StackMap GetStackMap() const {
-      return GetStackMapAt(stack_map_index_);
-    }
-
-    void Next() {
-      ++stack_map_index_;
-      offset_ = (stack_map_index_ == number_of_stack_maps_)
-          ? static_cast<uint32_t>(-1)
-          : GetStackMapAt(stack_map_index_).GetNativePcOffset(instruction_set_);
-    }
-
-   private:
-    StackMap GetStackMapAt(size_t i) const {
-      if (!indexes_.empty()) {
-        i = indexes_[i];
-      }
-      DCHECK_LT(i, number_of_stack_maps_);
-      return code_info_.GetStackMapAt(i);
-    }
-
-    const CodeInfo code_info_;
-    const size_t number_of_stack_maps_;
-    dchecked_vector<size_t> indexes_;  // Used if stack map native PCs are not ordered.
-    uint32_t offset_;
-    size_t stack_map_index_;
-    const InstructionSet instruction_set_;
-  };
-
   void DumpCode(VariableIndentationOutputStream* vios,
                 const OatFile::OatMethod& oat_method,
                 const CodeItemDataAccessor& code_item_accessor,
@@ -1616,29 +1516,29 @@
     } else if (!bad_input && IsMethodGeneratedByOptimizingCompiler(oat_method,
                                                                    code_item_accessor)) {
       // The optimizing compiler outputs its CodeInfo data in the vmap table.
-      StackMapsHelper helper(oat_method.GetVmapTable(), instruction_set_);
+      CodeInfo code_info(oat_method.GetVmapTable());
       if (AddStatsObject(oat_method.GetVmapTable())) {
-        helper.GetCodeInfo().CollectSizeStats(oat_method.GetVmapTable(), &stats_);
+        code_info.CollectSizeStats(oat_method.GetVmapTable(), stats_["CodeInfo"]);
       }
+      std::unordered_map<uint32_t, std::vector<StackMap>> stack_maps;
+      for (const StackMap& it : code_info.GetStackMaps()) {
+        stack_maps[it.GetNativePcOffset(instruction_set_)].push_back(it);
+      }
+
       const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
       size_t offset = 0;
       while (offset < code_size) {
         offset += disassembler_->Dump(vios->Stream(), quick_native_pc + offset);
-        if (offset == helper.GetOffset()) {
+        auto it = stack_maps.find(offset);
+        if (it != stack_maps.end()) {
           ScopedIndentation indent1(vios);
-          StackMap stack_map = helper.GetStackMap();
-          DCHECK(stack_map.IsValid());
-          stack_map.Dump(vios,
-                         helper.GetCodeInfo(),
-                         oat_method.GetCodeOffset(),
-                         instruction_set_);
-          do {
-            helper.Next();
-            // There may be multiple stack maps at a given PC. We display only the first one.
-          } while (offset == helper.GetOffset());
+          for (StackMap stack_map : it->second) {
+            stack_map.Dump(vios, code_info, oat_method.GetCodeOffset(), instruction_set_);
+          }
+          stack_maps.erase(it);
         }
-        DCHECK_LT(offset, helper.GetOffset());
       }
+      DCHECK_EQ(stack_maps.size(), 0u);  // Check that all stack maps have been printed.
     } else {
       const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
       size_t offset = 0;
@@ -1876,7 +1776,6 @@
     os << "\n";
 
     Runtime* const runtime = Runtime::Current();
-    ClassLinker* class_linker = runtime->GetClassLinker();
     std::string image_filename = image_space_.GetImageFilename();
     std::string oat_location = ImageHeader::GetOatLocationFromImageLocation(image_filename);
     os << "OAT LOCATION: " << oat_location;
@@ -1901,6 +1800,7 @@
     os << "\n";
 
     stats_.oat_file_bytes = oat_file->Size();
+    stats_.oat_file_stats.AddBytes(oat_file->Size());
 
     oat_dumper_.reset(new OatDumper(*oat_file, *oat_dumper_options_));
 
@@ -1928,18 +1828,6 @@
       heap->RevokeAllThreadLocalAllocationStacks(self);
     }
     {
-      // Mark dex caches.
-      dex_caches_.clear();
-      {
-        ReaderMutexLock mu(self, *Locks::dex_lock_);
-        for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
-          ObjPtr<mirror::DexCache> dex_cache =
-              ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
-          if (dex_cache != nullptr) {
-            dex_caches_.insert(dex_cache.Ptr());
-          }
-        }
-      }
       auto dump_visitor = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
         DumpObject(obj);
       };
@@ -1966,73 +1854,31 @@
     if (file == nullptr) {
       LOG(WARNING) << "Failed to find image in " << image_filename;
     } else {
-      stats_.file_bytes = file->GetLength();
+      size_t file_bytes = file->GetLength();
       // If the image is compressed, adjust to decompressed size.
       size_t uncompressed_size = image_header_.GetImageSize() - sizeof(ImageHeader);
       if (!image_header_.HasCompressedBlock()) {
         DCHECK_EQ(uncompressed_size, data_size) << "Sizes should match for uncompressed image";
       }
-      stats_.file_bytes += uncompressed_size - data_size;
-    }
-    size_t header_bytes = sizeof(ImageHeader);
-    const auto& object_section = image_header_.GetObjectsSection();
-    const auto& field_section = image_header_.GetFieldsSection();
-    const auto& method_section = image_header_.GetMethodsSection();
-    const auto& dex_cache_arrays_section = image_header_.GetDexCacheArraysSection();
-    const auto& intern_section = image_header_.GetInternedStringsSection();
-    const auto& class_table_section = image_header_.GetClassTableSection();
-    const auto& sro_section = image_header_.GetImageStringReferenceOffsetsSection();
-    const auto& metadata_section = image_header_.GetMetadataSection();
-    const auto& bitmap_section = image_header_.GetImageBitmapSection();
-
-    stats_.header_bytes = header_bytes;
-
-    // Objects are kObjectAlignment-aligned.
-    // CHECK_EQ(RoundUp(header_bytes, kObjectAlignment), object_section.Offset());
-    if (object_section.Offset() > header_bytes) {
-      stats_.alignment_bytes += object_section.Offset() - header_bytes;
+      file_bytes += uncompressed_size - data_size;
+      stats_.art_file_stats.AddBytes(file_bytes);
+      stats_.art_file_stats["Header"].AddBytes(sizeof(ImageHeader));
     }
 
-    // Field section is 4-byte aligned.
-    constexpr size_t kFieldSectionAlignment = 4U;
-    uint32_t end_objects = object_section.Offset() + object_section.Size();
-    CHECK_EQ(RoundUp(end_objects, kFieldSectionAlignment), field_section.Offset());
-    stats_.alignment_bytes += field_section.Offset() - end_objects;
+    size_t pointer_size = static_cast<size_t>(image_header_.GetPointerSize());
+    CHECK_ALIGNED(image_header_.GetFieldsSection().Offset(), 4);
+    CHECK_ALIGNED_PARAM(image_header_.GetMethodsSection().Offset(), pointer_size);
+    CHECK_ALIGNED(image_header_.GetInternedStringsSection().Offset(), 8);
+    CHECK_ALIGNED(image_header_.GetImageBitmapSection().Offset(), kPageSize);
 
-    // Method section is 4/8 byte aligned depending on target. Just check for 4-byte alignment.
-    uint32_t end_fields = field_section.Offset() + field_section.Size();
-    CHECK_ALIGNED(method_section.Offset(), 4);
-    stats_.alignment_bytes += method_section.Offset() - end_fields;
+    for (size_t i = 0; i < ImageHeader::ImageSections::kSectionCount; i++) {
+      ImageHeader::ImageSections index = ImageHeader::ImageSections(i);
+      const char* name = ImageHeader::GetImageSectionName(index);
+      stats_.art_file_stats[name].AddBytes(image_header_.GetImageSection(index).Size());
+    }
 
-    // Dex cache arrays section is aligned depending on the target. Just check for 4-byte alignment.
-    uint32_t end_methods = method_section.Offset() + method_section.Size();
-    CHECK_ALIGNED(dex_cache_arrays_section.Offset(), 4);
-    stats_.alignment_bytes += dex_cache_arrays_section.Offset() - end_methods;
-
-    // Intern table is 8-byte aligned.
-    uint32_t end_caches = dex_cache_arrays_section.Offset() + dex_cache_arrays_section.Size();
-    CHECK_EQ(RoundUp(end_caches, 8U), intern_section.Offset());
-    stats_.alignment_bytes += intern_section.Offset() - end_caches;
-
-    // Add space between intern table and class table.
-    uint32_t end_intern = intern_section.Offset() + intern_section.Size();
-    stats_.alignment_bytes += class_table_section.Offset() - end_intern;
-
-    // Add space between end of image data and bitmap. Expect the bitmap to be page-aligned.
-    const size_t bitmap_offset = sizeof(ImageHeader) + data_size;
-    CHECK_ALIGNED(bitmap_section.Offset(), kPageSize);
-    stats_.alignment_bytes += RoundUp(bitmap_offset, kPageSize) - bitmap_offset;
-
-    stats_.bitmap_bytes += bitmap_section.Size();
-    stats_.art_field_bytes += field_section.Size();
-    stats_.art_method_bytes += method_section.Size();
-    stats_.dex_cache_arrays_bytes += dex_cache_arrays_section.Size();
-    stats_.interned_strings_bytes += intern_section.Size();
-    stats_.class_table_bytes += class_table_section.Size();
-    stats_.sro_offset_bytes += sro_section.Size();
-    stats_.metadata_bytes += metadata_section.Size();
-
-    stats_.Dump(os, indent_os);
+    stats_.object_stats.AddBytes(image_header_.GetObjectsSection().Size());
+    stats_.Dump(os);
     os << "\n";
 
     os << std::flush;
@@ -2138,6 +1984,7 @@
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     if (class_linker->IsQuickResolutionStub(quick_code) ||
         class_linker->IsQuickToInterpreterBridge(quick_code) ||
+        class_linker->IsNterpTrampoline(quick_code) ||
         class_linker->IsQuickGenericJniStub(quick_code) ||
         class_linker->IsJniDlsymLookupStub(quick_code) ||
         class_linker->IsJniDlsymLookupCriticalStub(quick_code)) {
@@ -2175,11 +2022,6 @@
       return;
     }
 
-    size_t object_bytes = obj->SizeOf();
-    size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes;
-    stats_.object_bytes += object_bytes;
-    stats_.alignment_bytes += alignment_bytes;
-
     std::ostream& os = vios_.Stream();
 
     ObjPtr<mirror::Class> obj_class = obj->GetClass();
@@ -2201,7 +2043,6 @@
     }
     ScopedIndentation indent1(&vios_);
     DumpFields(os, obj, obj_class);
-    const PointerSize image_pointer_size = image_header_.GetPointerSize();
     if (obj->IsObjectArray()) {
       ObjPtr<mirror::ObjectArray<mirror::Object>> obj_array = obj->AsObjectArray<mirror::Object>();
       for (int32_t i = 0, length = obj_array->GetLength(); i < length; i++) {
@@ -2240,116 +2081,11 @@
           PrintField(os, &field, field.GetDeclaringClass());
         }
       }
-    } else {
-      auto it = dex_caches_.find(obj);
-      if (it != dex_caches_.end()) {
-        auto* dex_cache = down_cast<mirror::DexCache*>(obj);
-        const auto& field_section = image_header_.GetFieldsSection();
-        const auto& method_section = image_header_.GetMethodsSection();
-        size_t num_methods = dex_cache->NumResolvedMethods();
-        if (num_methods != 0u) {
-          os << "Methods (size=" << num_methods << "):\n";
-          ScopedIndentation indent2(&vios_);
-          mirror::MethodDexCacheType* resolved_methods = dex_cache->GetResolvedMethods();
-          for (size_t i = 0, length = dex_cache->NumResolvedMethods(); i < length; ++i) {
-            ArtMethod* elem = mirror::DexCache::GetNativePairPtrSize(
-                resolved_methods, i, image_pointer_size).object;
-            size_t run = 0;
-            for (size_t j = i + 1;
-                 j != length &&
-                 elem == mirror::DexCache::GetNativePairPtrSize(
-                     resolved_methods, j, image_pointer_size).object;
-                 ++j) {
-              ++run;
-            }
-            if (run == 0) {
-              os << StringPrintf("%zd: ", i);
-            } else {
-              os << StringPrintf("%zd to %zd: ", i, i + run);
-              i = i + run;
-            }
-            std::string msg;
-            if (elem == nullptr) {
-              msg = "null";
-            } else if (method_section.Contains(
-                reinterpret_cast<uint8_t*>(elem) - image_space_.Begin())) {
-              msg = reinterpret_cast<ArtMethod*>(elem)->PrettyMethod();
-            } else {
-              msg = "<not in method section>";
-            }
-            os << StringPrintf("%p   %s\n", elem, msg.c_str());
-          }
-        }
-        size_t num_fields = dex_cache->NumResolvedFields();
-        if (num_fields != 0u) {
-          os << "Fields (size=" << num_fields << "):\n";
-          ScopedIndentation indent2(&vios_);
-          auto* resolved_fields = dex_cache->GetResolvedFields();
-          for (size_t i = 0, length = dex_cache->NumResolvedFields(); i < length; ++i) {
-            ArtField* elem = mirror::DexCache::GetNativePairPtrSize(
-                resolved_fields, i, image_pointer_size).object;
-            size_t run = 0;
-            for (size_t j = i + 1;
-                 j != length &&
-                 elem == mirror::DexCache::GetNativePairPtrSize(
-                     resolved_fields, j, image_pointer_size).object;
-                 ++j) {
-              ++run;
-            }
-            if (run == 0) {
-              os << StringPrintf("%zd: ", i);
-            } else {
-              os << StringPrintf("%zd to %zd: ", i, i + run);
-              i = i + run;
-            }
-            std::string msg;
-            if (elem == nullptr) {
-              msg = "null";
-            } else if (field_section.Contains(
-                reinterpret_cast<uint8_t*>(elem) - image_space_.Begin())) {
-              msg = reinterpret_cast<ArtField*>(elem)->PrettyField();
-            } else {
-              msg = "<not in field section>";
-            }
-            os << StringPrintf("%p   %s\n", elem, msg.c_str());
-          }
-        }
-        size_t num_types = dex_cache->NumResolvedTypes();
-        if (num_types != 0u) {
-          os << "Types (size=" << num_types << "):\n";
-          ScopedIndentation indent2(&vios_);
-          auto* resolved_types = dex_cache->GetResolvedTypes();
-          for (size_t i = 0; i < num_types; ++i) {
-            auto pair = resolved_types[i].load(std::memory_order_relaxed);
-            size_t run = 0;
-            for (size_t j = i + 1; j != num_types; ++j) {
-              auto other_pair = resolved_types[j].load(std::memory_order_relaxed);
-              if (pair.index != other_pair.index ||
-                  pair.object.Read() != other_pair.object.Read()) {
-                break;
-              }
-              ++run;
-            }
-            if (run == 0) {
-              os << StringPrintf("%zd: ", i);
-            } else {
-              os << StringPrintf("%zd to %zd: ", i, i + run);
-              i = i + run;
-            }
-            std::string msg;
-            auto* elem = pair.object.Read();
-            if (elem == nullptr) {
-              msg = "null";
-            } else {
-              msg = elem->PrettyClass();
-            }
-            os << StringPrintf("%p   %u %s\n", elem, pair.index, msg.c_str());
-          }
-        }
-      }
     }
     std::string temp;
-    stats_.Update(obj_class->GetDescriptor(&temp), object_bytes);
+    const char* desc = obj_class->GetDescriptor(&temp);
+    desc = stats_.descriptors.emplace(desc).first->c_str();  // Dedup and keep alive.
+    stats_.object_stats[desc].AddBytes(obj->SizeOf());
   }
 
   void DumpMethod(ArtMethod* method, std::ostream& indent_os)
@@ -2362,7 +2098,7 @@
       uint32_t quick_oat_code_size = GetQuickOatCodeSize(method);
       ComputeOatSize(quick_oat_code_begin, &first_occurrence);
       if (first_occurrence) {
-        stats_.native_to_managed_code_bytes += quick_oat_code_size;
+        stats_.oat_file_stats["native_code"].AddBytes(quick_oat_code_size);
       }
       if (quick_oat_code_begin != method->GetEntryPointFromQuickCompiledCodePtrSize(
           image_header_.GetPointerSize())) {
@@ -2371,12 +2107,22 @@
     } else if (method->IsAbstract() || method->IsClassInitializer()) {
       // Don't print information for these.
     } else if (method->IsRuntimeMethod()) {
-      ImtConflictTable* table = method->GetImtConflictTable(image_header_.GetPointerSize());
-      if (table != nullptr) {
-        indent_os << "IMT conflict table " << table << " method: ";
-        for (size_t i = 0, count = table->NumEntries(pointer_size); i < count; ++i) {
-          indent_os << ArtMethod::PrettyMethod(table->GetImplementationMethod(i, pointer_size))
-                    << " ";
+      if (method == Runtime::Current()->GetResolutionMethod()) {
+        const void* resolution_trampoline =
+            method->GetEntryPointFromQuickCompiledCodePtrSize(image_header_.GetPointerSize());
+        indent_os << StringPrintf("Resolution trampoline: %p\n", resolution_trampoline);
+        const void* critical_native_resolution_trampoline =
+            method->GetEntryPointFromJniPtrSize(image_header_.GetPointerSize());
+        indent_os << StringPrintf("Resolution trampoline for @CriticalNative: %p\n",
+                                  critical_native_resolution_trampoline);
+      } else {
+        ImtConflictTable* table = method->GetImtConflictTable(image_header_.GetPointerSize());
+        if (table != nullptr) {
+          indent_os << "IMT conflict table " << table << " method: ";
+          for (size_t i = 0, count = table->NumEntries(pointer_size); i < count; ++i) {
+            indent_os << ArtMethod::PrettyMethod(table->GetImplementationMethod(i, pointer_size))
+                      << " ";
+          }
         }
       }
     } else {
@@ -2403,14 +2149,16 @@
       ComputeOatSize(quick_oat_code_begin, &first_occurrence);
       if (first_occurrence) {
         stats_.managed_code_bytes += quick_oat_code_size;
+        art::Stats& managed_code_stats = stats_.oat_file_stats["managed_code"];
+        managed_code_stats.AddBytes(quick_oat_code_size);
         if (method->IsConstructor()) {
           if (method->IsStatic()) {
-            stats_.class_initializer_code_bytes += quick_oat_code_size;
+            managed_code_stats["class_initializer"].AddBytes(quick_oat_code_size);
           } else if (dex_instruction_bytes > kLargeConstructorDexBytes) {
-            stats_.large_initializer_code_bytes += quick_oat_code_size;
+            managed_code_stats["large_initializer"].AddBytes(quick_oat_code_size);
           }
         } else if (dex_instruction_bytes > kLargeMethodDexBytes) {
-          stats_.large_method_code_bytes += quick_oat_code_size;
+          managed_code_stats["large_method"].AddBytes(quick_oat_code_size);
         }
       }
       stats_.managed_code_bytes_ignoring_deduplication += quick_oat_code_size;
@@ -2447,27 +2195,14 @@
 
  public:
   struct Stats {
+    art::Stats art_file_stats;
+    art::Stats oat_file_stats;
+    art::Stats object_stats;
+    std::set<std::string> descriptors;
+
     size_t oat_file_bytes = 0u;
-    size_t file_bytes = 0u;
-
-    size_t header_bytes = 0u;
-    size_t object_bytes = 0u;
-    size_t art_field_bytes = 0u;
-    size_t art_method_bytes = 0u;
-    size_t dex_cache_arrays_bytes = 0u;
-    size_t interned_strings_bytes = 0u;
-    size_t class_table_bytes = 0u;
-    size_t sro_offset_bytes = 0u;
-    size_t metadata_bytes = 0u;
-    size_t bitmap_bytes = 0u;
-    size_t alignment_bytes = 0u;
-
     size_t managed_code_bytes = 0u;
     size_t managed_code_bytes_ignoring_deduplication = 0u;
-    size_t native_to_managed_code_bytes = 0u;
-    size_t class_initializer_code_bytes = 0u;
-    size_t large_initializer_code_bytes = 0u;
-    size_t large_method_code_bytes = 0u;
 
     size_t vmap_table_bytes = 0u;
 
@@ -2480,36 +2215,10 @@
 
     Stats() {}
 
-    struct SizeAndCount {
-      SizeAndCount(size_t bytes_in, size_t count_in) : bytes(bytes_in), count(count_in) {}
-      size_t bytes;
-      size_t count;
-    };
-    using SizeAndCountTable = SafeMap<std::string, SizeAndCount>;
-    SizeAndCountTable sizes_and_counts;
-
-    void Update(const char* descriptor, size_t object_bytes_in) {
-      SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor);
-      if (it != sizes_and_counts.end()) {
-        it->second.bytes += object_bytes_in;
-        it->second.count += 1;
-      } else {
-        sizes_and_counts.Put(descriptor, SizeAndCount(object_bytes_in, 1));
-      }
-    }
-
     double PercentOfOatBytes(size_t size) {
       return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100;
     }
 
-    double PercentOfFileBytes(size_t size) {
-      return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100;
-    }
-
-    double PercentOfObjectBytes(size_t size) {
-      return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
-    }
-
     void ComputeOutliers(size_t total_size, double expansion, ArtMethod* method) {
       method_outlier_size.push_back(total_size);
       method_outlier_expansion.push_back(expansion);
@@ -2620,76 +2329,16 @@
       os << "\n" << std::flush;
     }
 
-    void Dump(std::ostream& os, std::ostream& indent_os)
+    void Dump(std::ostream& os)
         REQUIRES_SHARED(Locks::mutator_lock_) {
-      {
-        os << "art_file_bytes = " << PrettySize(file_bytes) << "\n\n"
-           << "art_file_bytes = header_bytes + object_bytes + alignment_bytes\n";
-        indent_os << StringPrintf("header_bytes           =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "object_bytes           =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "art_field_bytes        =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "art_method_bytes       =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "dex_cache_arrays_bytes =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "interned_string_bytes  =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "class_table_bytes      =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "sro_bytes              =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "metadata_bytes         =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "bitmap_bytes           =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "alignment_bytes        =  %8zd (%2.0f%% of art file bytes)\n\n",
-                                  header_bytes, PercentOfFileBytes(header_bytes),
-                                  object_bytes, PercentOfFileBytes(object_bytes),
-                                  art_field_bytes, PercentOfFileBytes(art_field_bytes),
-                                  art_method_bytes, PercentOfFileBytes(art_method_bytes),
-                                  dex_cache_arrays_bytes,
-                                  PercentOfFileBytes(dex_cache_arrays_bytes),
-                                  interned_strings_bytes,
-                                  PercentOfFileBytes(interned_strings_bytes),
-                                  class_table_bytes, PercentOfFileBytes(class_table_bytes),
-                                  sro_offset_bytes, PercentOfFileBytes(sro_offset_bytes),
-                                  metadata_bytes, PercentOfFileBytes(metadata_bytes),
-                                  bitmap_bytes, PercentOfFileBytes(bitmap_bytes),
-                                  alignment_bytes, PercentOfFileBytes(alignment_bytes))
-            << std::flush;
-        CHECK_EQ(file_bytes,
-                 header_bytes + object_bytes + art_field_bytes + art_method_bytes +
-                 dex_cache_arrays_bytes + interned_strings_bytes + class_table_bytes +
-                 sro_offset_bytes + metadata_bytes + bitmap_bytes + alignment_bytes);
-      }
-
-      os << "object_bytes breakdown:\n";
-      size_t object_bytes_total = 0;
-      for (const auto& sizes_and_count : sizes_and_counts) {
-        const std::string& descriptor(sizes_and_count.first);
-        double average = static_cast<double>(sizes_and_count.second.bytes) /
-            static_cast<double>(sizes_and_count.second.count);
-        double percent = PercentOfObjectBytes(sizes_and_count.second.bytes);
-        os << StringPrintf("%32s %8zd bytes %6zd instances "
-                           "(%4.0f bytes/instance) %2.0f%% of object_bytes\n",
-                           descriptor.c_str(), sizes_and_count.second.bytes,
-                           sizes_and_count.second.count, average, percent);
-        object_bytes_total += sizes_and_count.second.bytes;
-      }
+      VariableIndentationOutputStream vios(&os);
+      art_file_stats.DumpSizes(vios, "ArtFile");
       os << "\n" << std::flush;
-      CHECK_EQ(object_bytes, object_bytes_total);
+      object_stats.DumpSizes(vios, "Objects");
+      os << "\n" << std::flush;
+      oat_file_stats.DumpSizes(vios, "OatFile");
+      os << "\n" << std::flush;
 
-      os << StringPrintf("oat_file_bytes               = %8zd\n"
-                         "managed_code_bytes           = %8zd (%2.0f%% of oat file bytes)\n"
-                         "native_to_managed_code_bytes = %8zd (%2.0f%% of oat file bytes)\n\n"
-                         "class_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
-                         "large_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
-                         "large_method_code_bytes      = %8zd (%2.0f%% of oat file bytes)\n\n",
-                         oat_file_bytes,
-                         managed_code_bytes,
-                         PercentOfOatBytes(managed_code_bytes),
-                         native_to_managed_code_bytes,
-                         PercentOfOatBytes(native_to_managed_code_bytes),
-                         class_initializer_code_bytes,
-                         PercentOfOatBytes(class_initializer_code_bytes),
-                         large_initializer_code_bytes,
-                         PercentOfOatBytes(large_initializer_code_bytes),
-                         large_method_code_bytes,
-                         PercentOfOatBytes(large_method_code_bytes))
-            << "DexFile sizes:\n";
       for (const std::pair<std::string, size_t>& oat_dex_file_size : oat_dex_file_sizes) {
         os << StringPrintf("%s = %zd (%2.0f%% of oat file bytes)\n",
                            oat_dex_file_size.first.c_str(), oat_dex_file_size.second,
@@ -2732,7 +2381,6 @@
   const ImageHeader& image_header_;
   std::unique_ptr<OatDumper> oat_dumper_;
   OatDumperOptions* oat_dumper_options_;
-  std::set<mirror::Object*> dex_caches_;
 
   DISALLOW_COPY_AND_ASSIGN(ImageDumper);
 };
diff --git a/oatdump/oatdump_app_test.cc b/oatdump/oatdump_app_test.cc
index b4997ba..9c37707 100644
--- a/oatdump/oatdump_app_test.cc
+++ b/oatdump/oatdump_app_test.cc
@@ -19,36 +19,36 @@
 namespace art {
 
 TEST_F(OatDumpTest, TestAppWithBootImage) {
-  ASSERT_TRUE(GenerateAppOdexFile(kDynamic, {"--runtime-arg", "-Xmx64M"}));
-  ASSERT_TRUE(Exec(kDynamic, kModeOatWithBootImage, {}, kListAndCode));
+  ASSERT_TRUE(GenerateAppOdexFile(Flavor::kDynamic, {"--runtime-arg", "-Xmx64M"}));
+  ASSERT_TRUE(Exec(Flavor::kDynamic, kModeOatWithBootImage, {}, kListAndCode));
 }
 TEST_F(OatDumpTest, TestAppWithBootImageStatic) {
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
-  ASSERT_TRUE(GenerateAppOdexFile(kStatic, {"--runtime-arg", "-Xmx64M"}));
-  ASSERT_TRUE(Exec(kStatic, kModeOatWithBootImage, {}, kListAndCode));
+  ASSERT_TRUE(GenerateAppOdexFile(Flavor::kStatic, {"--runtime-arg", "-Xmx64M"}));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeOatWithBootImage, {}, kListAndCode));
 }
 
 TEST_F(OatDumpTest, TestAppImageWithBootImage) {
   TEST_DISABLED_WITHOUT_BAKER_READ_BARRIERS();  // GC bug, b/126305867
   const std::string app_image_arg = "--app-image-file=" + GetAppImageName();
-  ASSERT_TRUE(GenerateAppOdexFile(kDynamic, {"--runtime-arg", "-Xmx64M", app_image_arg}));
-  ASSERT_TRUE(Exec(kDynamic, kModeAppImage, {}, kListAndCode));
+  ASSERT_TRUE(GenerateAppOdexFile(Flavor::kDynamic, {"--runtime-arg", "-Xmx64M", app_image_arg}));
+  ASSERT_TRUE(Exec(Flavor::kDynamic, kModeAppImage, {}, kListAndCode));
 }
 TEST_F(OatDumpTest, TestAppImageWithBootImageStatic) {
   TEST_DISABLED_WITHOUT_BAKER_READ_BARRIERS();  // GC bug, b/126305867
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
   const std::string app_image_arg = "--app-image-file=" + GetAppImageName();
-  ASSERT_TRUE(GenerateAppOdexFile(kStatic, {"--runtime-arg", "-Xmx64M", app_image_arg}));
-  ASSERT_TRUE(Exec(kStatic, kModeAppImage, {}, kListAndCode));
+  ASSERT_TRUE(GenerateAppOdexFile(Flavor::kStatic, {"--runtime-arg", "-Xmx64M", app_image_arg}));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeAppImage, {}, kListAndCode));
 }
 
 TEST_F(OatDumpTest, TestAppImageInvalidPath) {
   TEST_DISABLED_WITHOUT_BAKER_READ_BARRIERS();  // GC bug, b/126305867
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
   const std::string app_image_arg = "--app-image-file=" + GetAppImageName();
-  ASSERT_TRUE(GenerateAppOdexFile(kStatic, {"--runtime-arg", "-Xmx64M", app_image_arg}));
+  ASSERT_TRUE(GenerateAppOdexFile(Flavor::kStatic, {"--runtime-arg", "-Xmx64M", app_image_arg}));
   SetAppImageName("missing_app_image.art");
-  ASSERT_TRUE(Exec(kStatic, kModeAppImage, {}, kListAndCode, /*expect_failure=*/true));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeAppImage, {}, kListAndCode, /*expect_failure=*/true));
 }
 
 }  // namespace art
diff --git a/oatdump/oatdump_image_test.cc b/oatdump/oatdump_image_test.cc
index 6270105..7308f82 100644
--- a/oatdump/oatdump_image_test.cc
+++ b/oatdump/oatdump_image_test.cc
@@ -26,25 +26,25 @@
 TEST_F(OatDumpTest, TestImage) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kDynamic, kModeArt, {}, kListAndCode));
+  ASSERT_TRUE(Exec(Flavor::kDynamic, kModeArt, {}, kListAndCode));
 }
 TEST_F(OatDumpTest, TestImageStatic) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kStatic, kModeArt, {}, kListAndCode));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeArt, {}, kListAndCode));
 }
 
 TEST_F(OatDumpTest, TestOatImage) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kDynamic, kModeCoreOat, {}, kListAndCode));
+  ASSERT_TRUE(Exec(Flavor::kDynamic, kModeCoreOat, {}, kListAndCode));
 }
 TEST_F(OatDumpTest, TestOatImageStatic) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kStatic, kModeCoreOat, {}, kListAndCode));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeCoreOat, {}, kListAndCode));
 }
 
 }  // namespace art
diff --git a/oatdump/oatdump_test.cc b/oatdump/oatdump_test.cc
index 8dcc143..49bee48 100644
--- a/oatdump/oatdump_test.cc
+++ b/oatdump/oatdump_test.cc
@@ -28,70 +28,67 @@
 TEST_F(OatDumpTest, TestNoDumpVmap) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--no-dump:vmap"}, kListAndCode));
+  ASSERT_TRUE(Exec(Flavor::kDynamic, kModeArt, {"--no-dump:vmap"}, kListAndCode));
 }
 TEST_F(OatDumpTest, TestNoDumpVmapStatic) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kStatic, kModeArt, {"--no-dump:vmap"}, kListAndCode));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeArt, {"--no-dump:vmap"}, kListAndCode));
 }
 
 TEST_F(OatDumpTest, TestNoDisassemble) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--no-disassemble"}, kListAndCode));
+  ASSERT_TRUE(Exec(Flavor::kDynamic, kModeArt, {"--no-disassemble"}, kListAndCode));
 }
 TEST_F(OatDumpTest, TestNoDisassembleStatic) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kStatic, kModeArt, {"--no-disassemble"}, kListAndCode));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeArt, {"--no-disassemble"}, kListAndCode));
 }
 
 TEST_F(OatDumpTest, TestListClasses) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--list-classes"}, kListOnly));
+  ASSERT_TRUE(Exec(Flavor::kDynamic, kModeArt, {"--list-classes"}, kListOnly));
 }
 TEST_F(OatDumpTest, TestListClassesStatic) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kStatic, kModeArt, {"--list-classes"}, kListOnly));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeArt, {"--list-classes"}, kListOnly));
 }
 
 TEST_F(OatDumpTest, TestListMethods) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--list-methods"}, kListOnly));
+  ASSERT_TRUE(Exec(Flavor::kDynamic, kModeArt, {"--list-methods"}, kListOnly));
 }
 TEST_F(OatDumpTest, TestListMethodsStatic) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kStatic, kModeArt, {"--list-methods"}, kListOnly));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeArt, {"--list-methods"}, kListOnly));
 }
 
 TEST_F(OatDumpTest, TestSymbolize) {
-  TEST_DISABLED_FOR_ARM_AND_ARM64();
+  TEST_DISABLED_FOR_TARGET();  // Can not write files inside the apex directory.
   std::string error_msg;
-  ASSERT_TRUE(Exec(kDynamic, kModeSymbolize, {}, kListOnly));
+  ASSERT_TRUE(Exec(Flavor::kDynamic, kModeSymbolize, {}, kListOnly));
 }
 TEST_F(OatDumpTest, TestSymbolizeStatic) {
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
   std::string error_msg;
-  ASSERT_TRUE(Exec(kStatic, kModeSymbolize, {}, kListOnly));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeSymbolize, {}, kListOnly));
 }
 
 TEST_F(OatDumpTest, TestExportDex) {
-  TEST_DISABLED_FOR_ARM_AND_ARM64();
-  // Test is failing on target, b/77469384.
-  TEST_DISABLED_FOR_TARGET();
   std::string error_msg;
-  ASSERT_TRUE(GenerateAppOdexFile(kDynamic, {"--runtime-arg", "-Xmx64M"}));
-  ASSERT_TRUE(Exec(kDynamic, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly));
+  ASSERT_TRUE(GenerateAppOdexFile(Flavor::kDynamic, {"--runtime-arg", "-Xmx64M"}));
+  ASSERT_TRUE(Exec(Flavor::kDynamic, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly));
   const std::string dex_location =
       tmp_dir_+ "/" + android::base::Basename(GetTestDexFileName(GetAppBaseName().c_str())) +
       "_export.dex";
@@ -108,8 +105,8 @@
   TEST_DISABLED_FOR_ARM_AND_ARM64();
   TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
   std::string error_msg;
-  ASSERT_TRUE(GenerateAppOdexFile(kStatic, {"--runtime-arg", "-Xmx64M"}));
-  ASSERT_TRUE(Exec(kStatic, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly));
+  ASSERT_TRUE(GenerateAppOdexFile(Flavor::kStatic, {"--runtime-arg", "-Xmx64M"}));
+  ASSERT_TRUE(Exec(Flavor::kStatic, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly));
 }
 
 }  // namespace art
diff --git a/oatdump/oatdump_test.h b/oatdump/oatdump_test.h
index cbbce3b..3ec5b94 100644
--- a/oatdump/oatdump_test.h
+++ b/oatdump/oatdump_test.h
@@ -65,7 +65,7 @@
   }
 
   // Linking flavor.
-  enum Flavor {
+  enum class Flavor {
     kDynamic,  // oatdump(d), dex2oat(d)
     kStatic,   // oatdump(d)s, dex2oat(d)s
   };
@@ -86,7 +86,7 @@
   }
 
   std::string GetExecutableFilePath(Flavor flavor, const char* name, bool bitness) {
-    return GetExecutableFilePath(name, kIsDebugBuild, flavor == kStatic, bitness);
+    return GetExecutableFilePath(name, kIsDebugBuild, flavor == Flavor::kStatic, bitness);
   }
 
   enum Mode {
@@ -228,6 +228,7 @@
         exec_argv.push_back("--app-image=" + GetAppImageName());
       } else if (mode == kModeCoreOat) {
         exec_argv.push_back("--oat-file=" + core_oat_location_);
+        exec_argv.push_back("--dex-file=" + GetLibCoreDexFileNames()[0]);
       } else {
         CHECK_EQ(static_cast<size_t>(mode), static_cast<size_t>(kModeOat));
         exec_argv.push_back("--oat-file=" + GetAppOdexName());
@@ -341,8 +342,11 @@
         // Avoid crash as valid exit.
         return ::testing::AssertionSuccess();
       }
-      return ::testing::AssertionFailure() << "Did not terminate successfully: " << res.status_code
-          << " " << error_buf.data();
+      std::ostringstream cmd;
+      std::copy(exec_argv.begin(), exec_argv.end(), std::ostream_iterator<std::string>(cmd, " "));
+      LOG(ERROR) << "Output: " << error_buf.data();  // Output first as it might be extremely  long.
+      LOG(ERROR) << "Failed command: " << cmd.str();  // Useful to reproduce the failure separately.
+      return ::testing::AssertionFailure() << "Did not terminate successfully: " << res.status_code;
     } else if (expect_failure) {
       return ::testing::AssertionFailure() << "Expected failure";
     }
diff --git a/odrefresh/Android.bp b/odrefresh/Android.bp
new file mode 100644
index 0000000..58c228b
--- /dev/null
+++ b/odrefresh/Android.bp
@@ -0,0 +1,224 @@
+//
+// Copyright (C) 2020 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.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+cc_defaults {
+    name: "odrefresh-defaults",
+    host_supported: true,
+    defaults: ["art_defaults"],
+    srcs: [
+        "odrefresh.cc",
+        "odr_compilation_log.cc",
+        "odr_fs_utils.cc",
+        "odr_metrics.cc",
+        "odr_metrics_record.cc",
+    ],
+    local_include_dirs: ["include"],
+    header_libs: ["dexoptanalyzer_headers"],
+    generated_sources: [
+        "apex-info-list",
+        "art-apex-cache-info",
+        "art-odrefresh-operator-srcs",
+    ],
+    shared_libs: [
+        "libartpalette",
+        "libbase",
+        "libdexfile",
+        "liblog",
+    ],
+    static_libs: ["libxml2"],
+    target: {
+        android: {
+            compile_multilib: "first",
+        },
+        host: {
+            shared_libs: [
+                // Both these libraries for libxml2 on host for code derived from apex-info-list.
+                "libicui18n",
+                "libicuuc",
+            ],
+        },
+    },
+    tidy: true,
+    tidy_flags: [
+        "-format-style=file",
+        "-header-filter=(art/odrefresh/|system/apex/)",
+    ],
+}
+
+cc_library_headers {
+    name: "odrefresh_headers",
+    export_include_dirs: ["include"],
+    host_supported: true,
+    stl: "none",
+    system_shared_libs: [],
+    min_sdk_version: "29", // As part of mainline modules(APEX), it should support at least 29(Q).
+    sdk_version: "minimum", // The minimum sdk version required by users of this module.
+    apex_available: [
+        "//apex_available:platform", // For odsign.
+    ],
+    visibility: ["//visibility:public"],
+}
+
+gensrcs {
+    name: "art-odrefresh-operator-srcs",
+    cmd: "$(location generate_operator_out) art/odrefresh $(in) > $(out)",
+    tools: ["generate_operator_out"],
+    srcs: [
+        "odr_metrics.h",
+    ],
+    output_extension: "operator_out.cc",
+}
+
+art_cc_binary {
+    name: "odrefresh",
+    defaults: ["odrefresh-defaults"],
+    required: [
+        "dexoptanalyzer",
+        "dex2oat",
+    ],
+    shared_libs: [
+        "libart",
+        "libartbase",
+    ],
+    apex_available: [
+        "com.android.art",
+        "com.android.art.debug",
+    ],
+}
+
+art_cc_binary {
+    name: "odrefreshd",
+    defaults: [
+        "art_debug_defaults",
+        "odrefresh-defaults",
+    ],
+    required: [
+        "dexoptanalyzerd",
+        "dex2oatd",
+    ],
+    shared_libs: [
+        "libartd",
+        "libartbased",
+    ],
+    apex_available: [
+        "com.android.art.debug",
+        // TODO(b/183882457): This binary doesn't go into com.android.art, but
+        // apex_available lists need to be the same for internal libs to avoid
+        // stubs, and this depends on libartd.
+        "com.android.art",
+    ],
+}
+
+cc_library_static {
+    name: "libodrstatslog",
+    defaults: ["art_defaults"],
+    host_supported: true,
+    export_include_dirs: ["include"],
+
+    local_include_dirs: ["include"],
+    shared_libs: ["libartbase"],
+    target: {
+        android: {
+            generated_headers: ["statslog_odrefresh.h"],
+            generated_sources: ["statslog_odrefresh.cpp"],
+            srcs: [
+                "odr_metrics_record.cc",
+                "odr_statslog_android.cc",
+            ],
+            shared_libs: ["libstatssocket"],
+        },
+        host: {
+            srcs: ["odr_statslog_host.cc"],
+        },
+    },
+    apex_available: [
+        "com.android.art",
+        "com.android.art.debug",
+    ],
+}
+
+art_cc_defaults {
+    name: "art_odrefresh_tests_defaults",
+    generated_sources: ["art-odrefresh-operator-srcs"],
+    header_libs: ["odrefresh_headers"],
+    srcs: [
+        "odr_artifacts_test.cc",
+        "odr_compilation_log.cc",
+        "odr_compilation_log_test.cc",
+        "odr_fs_utils.cc",
+        "odr_fs_utils_test.cc",
+        "odr_metrics.cc",
+        "odr_metrics_test.cc",
+        "odr_metrics_record.cc",
+        "odr_metrics_record_test.cc",
+        "odrefresh_test.cc",
+    ],
+    shared_libs: ["libbase"],
+}
+
+// Version of ART gtest `art_odrefresh_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
+art_cc_test {
+    name: "art_odrefresh_tests",
+    defaults: [
+        "art_gtest_defaults",
+        "art_odrefresh_tests_defaults",
+    ],
+}
+
+// Standalone version of ART gtest `art_odrefresh_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_odrefresh_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_odrefresh_tests_defaults",
+    ],
+}
+
+genrule {
+    name: "statslog_odrefresh.h",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_odrefresh.h --module art --namespace art,metrics,statsd",
+    out: [
+        "statslog_odrefresh.h",
+    ],
+}
+
+genrule {
+    name: "statslog_odrefresh.cpp",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_odrefresh.cpp --module art --namespace art,metrics,statsd --importHeader statslog_odrefresh.h",
+    out: [
+        "statslog_odrefresh.cpp",
+    ],
+}
+
+xsd_config {
+    name: "art-apex-cache-info",
+    srcs: ["CacheInfo.xsd"],
+    package_name: "com.android.art",
+    api_dir: "schema",
+    gen_writer: true,
+}
diff --git a/odrefresh/CacheInfo.xsd b/odrefresh/CacheInfo.xsd
new file mode 100644
index 0000000..b58453a
--- /dev/null
+++ b/odrefresh/CacheInfo.xsd
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           version="2.0"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           targetNamespace="http://schemas.android.com/art/apex-cache-info/v1_0"
+           xmlns:t="http://schemas.android.com/art/apex-cache-info/v1_0" >
+  <!-- Data type holding information on the AOT artifact cache in
+    `/data/misc/apexdata/com.android.art/dalvik-cache` -->
+  <xs:element name="cacheInfo">
+    <xs:complexType>
+    <xs:sequence>
+      <xs:element name="artModuleInfo" minOccurs="1" maxOccurs="1" type="t:artModuleInfo" />
+      <xs:element name="dex2oatBootClasspath" type="t:dex2oatBootClasspath" />
+      <xs:element name="systemServerClasspath" type="t:systemServerClasspath" />
+    </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+
+  <!-- Data type representing the provenance of the AOT artifacts in the cache. -->
+  <xs:complexType name="artModuleInfo">
+    <!-- Module versionCode for the active ART APEX from `/apex/apex-info-list.xml`. -->
+    <xs:attribute name="versionCode" type="xs:long" use="required" />
+    <!-- Module versionName for the active ART APEX from `/apex/apex-info-list.xml`. -->
+    <xs:attribute name="versionName" type="xs:string" use="required" />
+    <!-- Module lastUpdateMillis for the active ART APEX from `/apex/apex-info-list.xml`. -->
+    <xs:attribute name="lastUpdateMillis" type="xs:long" use="required" />
+  </xs:complexType>
+
+  <!-- Components of the `DEX2OATBOOTCLASSPATH`. -->
+  <xs:complexType name="dex2oatBootClasspath">
+    <xs:sequence>
+      <xs:element name="component" type="t:component" />
+    </xs:sequence>
+  </xs:complexType>
+
+  <!-- Components of the `SYSTEMSERVERCLASSPATH`. -->
+  <xs:complexType name="systemServerClasspath">
+    <xs:sequence>
+      <xs:element name="component" type="t:component" />
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="component">
+    <!-- File path of component. -->
+    <xs:attribute name="file" type="xs:string" use="required" />
+    <!-- Size of component when cache information is generated. -->
+    <xs:attribute name="size" type="xs:unsignedLong" use="required" />
+    <!-- DEX file checksums within the component. Multidex files have multiple checksums. -->
+    <xs:attribute name="checksums" type="xs:string" use="required" />
+  </xs:complexType>
+
+</xs:schema>
diff --git a/odrefresh/README.md b/odrefresh/README.md
new file mode 100644
index 0000000..181ef72
--- /dev/null
+++ b/odrefresh/README.md
@@ -0,0 +1,7 @@
+# On-Device Refresh (odrefresh)
+
+This tool is part of the ART APEX and is used to refresh compilation artifacts following an
+ART APEX update. It provides two key features:
+
+* checking the freshness of compilation artifacts for boot class path extensions and system_server.
+* regenerating the compilation artifacts for boot class path extensions and system_server.
\ No newline at end of file
diff --git a/odrefresh/TODO.md b/odrefresh/TODO.md
new file mode 100644
index 0000000..9d7c9fc
--- /dev/null
+++ b/odrefresh/TODO.md
@@ -0,0 +1,26 @@
+# TODO Work Items
+
+## TODO (STOPSHIP until done)
+
+1. denylist for AOT artifacts.
+
+## DONE
+
+<strike>
+
+1. Fix dexoptanalyzer so it can analyze boot extensions.
+2. Parse apex-info-list.xml into an apex_info (to make version and location available).
+3. Timeouts for pathological failures.
+4. Add a log file that tracks status of recent compilation.
+5. Metrics for tracking issues:
+   - Successful compilation of all artifacts.
+   - Time limit exceeded (indicates a pathological issue, e.g. dex2oat bug, device driver bug, etc).
+   - Insufficient space for compilation.
+   - Compilation failure (boot extensions)
+   - Compilation failure (system server)
+   - Unexpected error (a setup or clean-up action failed).
+6. Metrics recording for subprocess timeouts.
+7. Free space calculation and only attempting compilation if sufficient space.
+8. Implement back off on trying compilation when previous attempt(s) failed.
+
+</strike>
diff --git a/odrefresh/include/odr_statslog/odr_statslog.h b/odrefresh/include/odr_statslog/odr_statslog.h
new file mode 100644
index 0000000..0a27475
--- /dev/null
+++ b/odrefresh/include/odr_statslog/odr_statslog.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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_ODREFRESH_INCLUDE_ODR_STATSLOG_ODR_STATSLOG_H_
+#define ART_ODREFRESH_INCLUDE_ODR_STATSLOG_ODR_STATSLOG_H_
+
+#include <iosfwd>  // For forward-declaration of std::string.
+namespace art {
+namespace odrefresh {
+
+// Upload the metrics (if any) generated by odrefresh by passing the data `statsd` process.
+//
+// Metrics from odrefresh a persisted to the path specified by `OdrefreshMetricsFile`. This method
+// reads the saved metrics, passes them to statsd, then removes the file to avoid uploading them
+// in future.
+//
+// Returns true on success. On failure `error_msg` summarizes the failure and this method returns
+// false.
+bool UploadStatsIfAvailable(/*out*/std::string* error_msg);
+
+}  // namespace odrefresh
+}  // namespace art
+
+#endif  // ART_ODREFRESH_INCLUDE_ODR_STATSLOG_ODR_STATSLOG_H_
diff --git a/odrefresh/include/odrefresh/odrefresh.h b/odrefresh/include/odrefresh/odrefresh.h
new file mode 100644
index 0000000..1fe2382
--- /dev/null
+++ b/odrefresh/include/odrefresh/odrefresh.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 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_ODREFRESH_INCLUDE_ODREFRESH_ODREFRESH_H_
+#define ART_ODREFRESH_INCLUDE_ODREFRESH_ODREFRESH_H_
+
+#include <sysexits.h>
+
+namespace art {
+namespace odrefresh {
+
+static constexpr const char* kOdrefreshArtifactDirectory =
+    "/data/misc/apexdata/com.android.art/dalvik-cache";
+
+//
+// Exit codes from the odrefresh process (in addition to standard exit codes in sysexits.h).
+//
+// NB if odrefresh crashes, then the caller should not sign any artifacts and should remove any
+// unsigned artifacts under `kOdrefreshArtifactDirectory`.
+//
+enum ExitCode : int {
+  // No compilation required, all artifacts look good or there is insufficient space to compile.
+  // For ART APEX in the system image, there may be no artifacts present under
+  // `kOdrefreshArtifactDirectory`.
+  kOkay = EX_OK,
+
+  // Compilation required (only returned for --check). Re-run program with --compile on the
+  // command-line to generate + new artifacts under `kOdrefreshArtifactDirectory`.
+  kCompilationRequired = EX__MAX + 1,
+
+  // New artifacts successfully generated under `kOdrefreshArtifactDirectory`.
+  kCompilationSuccess = EX__MAX + 2,
+
+  // Compilation failed. Any artifacts under `kOdrefreshArtifactDirectory` are valid and should not
+  // be removed. This may happen, for example, if compilation of boot extensions succeeds, but the
+  // compilation of the system_server jars fails due to lack of storage space.
+  kCompilationFailed = EX__MAX + 3,
+
+  // Removal of existing artifacts (or files under `kOdrefreshArtifactDirectory`) failed. Artifacts
+  // should be treated as invalid and should be removed if possible.
+  kCleanupFailed = EX__MAX + 4,
+
+  // Last exit code defined.
+  kLastExitCode = kCleanupFailed,
+};
+
+static_assert(EX_OK == 0);
+static_assert(ExitCode::kOkay < EX__BASE);
+static_assert(ExitCode::kLastExitCode < 0xff);  // The `exit()` man page discusses the mask value.
+
+}  // namespace odrefresh
+}  // namespace art
+
+#endif  // ART_ODREFRESH_INCLUDE_ODREFRESH_ODREFRESH_H_
diff --git a/odrefresh/odr_artifacts.h b/odrefresh/odr_artifacts.h
new file mode 100644
index 0000000..66d76f0
--- /dev/null
+++ b/odrefresh/odr_artifacts.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 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_ODREFRESH_ODR_ARTIFACTS_H_
+#define ART_ODREFRESH_ODR_ARTIFACTS_H_
+
+#include <iosfwd>
+#include <string>
+
+#include <base/file_utils.h>
+
+namespace art {
+namespace odrefresh {
+
+// A grouping of odrefresh generated artifacts.
+class OdrArtifacts {
+ public:
+  static OdrArtifacts ForBootImageExtension(const std::string& image_path) {
+    return OdrArtifacts(image_path, "oat");
+  }
+
+  static OdrArtifacts ForSystemServer(const std::string& image_path) {
+    return OdrArtifacts(image_path, "odex");
+  }
+
+  const std::string& ImagePath() const { return image_path_; }
+  const std::string& OatPath() const { return oat_path_; }
+  const std::string& VdexPath() const { return vdex_path_; }
+
+ private:
+  OdrArtifacts(const std::string& image_path, const char* aot_extension)
+      : image_path_{image_path},
+        oat_path_{ReplaceFileExtension(image_path, aot_extension)},
+        vdex_path_{ReplaceFileExtension(image_path, "vdex")} {}
+
+  OdrArtifacts() = delete;
+  OdrArtifacts(const OdrArtifacts&) = delete;
+  OdrArtifacts& operator=(const OdrArtifacts&) = delete;
+
+  const std::string image_path_;
+  const std::string oat_path_;
+  const std::string vdex_path_;
+};
+
+}  // namespace odrefresh
+}  // namespace art
+
+#endif  // ART_ODREFRESH_ODR_ARTIFACTS_H_
diff --git a/odrefresh/odr_artifacts_test.cc b/odrefresh/odr_artifacts_test.cc
new file mode 100644
index 0000000..97f1fd7
--- /dev/null
+++ b/odrefresh/odr_artifacts_test.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 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 "odr_artifacts.h"
+
+#include "arch/instruction_set.h"
+#include "base/common_art_test.h"
+#include "base/file_utils.h"
+#include "base/string_view_cpp20.h"
+#include "odrefresh/odrefresh.h"
+
+namespace art {
+namespace odrefresh {
+
+TEST(OdrArtifactsTest, ForBootImageExtension) {
+  ScopedUnsetEnvironmentVariable no_env("ART_APEX_DATA");
+
+  const std::string image_location = GetApexDataBootImage("/system/framework/framework.jar");
+  EXPECT_TRUE(StartsWith(image_location, GetArtApexData()));
+
+  const std::string image_filename =
+      GetSystemImageFilename(image_location.c_str(), InstructionSet::kArm64);
+
+  const auto artifacts = OdrArtifacts::ForBootImageExtension(image_filename);
+  CHECK_EQ(std::string(kOdrefreshArtifactDirectory) + "/arm64/boot-framework.art",
+           artifacts.ImagePath());
+  CHECK_EQ(std::string(kOdrefreshArtifactDirectory) + "/arm64/boot-framework.oat",
+           artifacts.OatPath());
+  CHECK_EQ(std::string(kOdrefreshArtifactDirectory) + "/arm64/boot-framework.vdex",
+           artifacts.VdexPath());
+}
+
+TEST(OdrArtifactsTest, ForSystemServer) {
+  ScopedUnsetEnvironmentVariable no_env("ART_APEX_DATA");
+
+  const std::string image_location = GetApexDataImage("/system/framework/services.jar");
+  EXPECT_TRUE(StartsWith(image_location, GetArtApexData()));
+
+  const std::string image_filename =
+      GetSystemImageFilename(image_location.c_str(), InstructionSet::kX86);
+  const auto artifacts = OdrArtifacts::ForSystemServer(image_filename);
+  CHECK_EQ(
+      std::string(kOdrefreshArtifactDirectory) + "/x86/system@framework@services.jar@classes.art",
+      artifacts.ImagePath());
+  CHECK_EQ(
+      std::string(kOdrefreshArtifactDirectory) + "/x86/system@framework@services.jar@classes.odex",
+      artifacts.OatPath());
+  CHECK_EQ(
+      std::string(kOdrefreshArtifactDirectory) + "/x86/system@framework@services.jar@classes.vdex",
+      artifacts.VdexPath());
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odr_compilation_log.cc b/odrefresh/odr_compilation_log.cc
new file mode 100644
index 0000000..37804a2
--- /dev/null
+++ b/odrefresh/odr_compilation_log.cc
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2021 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 <odr_compilation_log.h>
+
+#include <errno.h>
+
+#include <fstream>
+#include <ios>
+#include <iosfwd>
+#include <istream>
+#include <ostream>
+#include <streambuf>
+#include <string>
+#include <vector>
+
+#include "android-base/logging.h"
+#include "base/os.h"
+
+#include "odrefresh/odrefresh.h"
+#include "odr_metrics.h"
+
+namespace art {
+namespace odrefresh {
+
+std::istream& operator>>(std::istream& is, OdrCompilationLogEntry& entry) {
+  // Block I/O related exceptions
+  auto saved_exceptions = is.exceptions();
+  is.exceptions(std::ios_base::iostate {});
+
+  // Write log entry. NB update OdrCompilationLog::kLogVersion if changing the format here.
+  is >> entry.apex_version >> std::ws;
+  is >> entry.last_update_millis >> std::ws;
+  is >> entry.trigger >> std::ws;
+  is >> entry.when >> std::ws;
+  is >> entry.exit_code >> std::ws;
+
+  // Restore I/O related exceptions
+  is.exceptions(saved_exceptions);
+  return is;
+}
+
+std::ostream& operator<<(std::ostream& os, const OdrCompilationLogEntry& entry) {
+  static const char kSpace = ' ';
+
+  // Block I/O related exceptions
+  auto saved_exceptions = os.exceptions();
+  os.exceptions(std::ios_base::iostate {});
+
+  os << entry.apex_version << kSpace;
+  os << entry.last_update_millis << kSpace;
+  os << entry.trigger << kSpace;
+  os << entry.when << kSpace;
+  os << entry.exit_code << std::endl;
+
+  // Restore I/O related exceptions
+  os.exceptions(saved_exceptions);
+  return os;
+}
+
+bool operator==(const OdrCompilationLogEntry& lhs, const OdrCompilationLogEntry& rhs) {
+  return lhs.apex_version == rhs.apex_version && lhs.last_update_millis == rhs.last_update_millis &&
+         lhs.trigger == rhs.trigger && lhs.when == rhs.when && lhs.exit_code == rhs.exit_code;
+}
+
+bool operator!=(const OdrCompilationLogEntry& lhs, const OdrCompilationLogEntry& rhs) {
+  return !(lhs == rhs);
+}
+
+OdrCompilationLog::OdrCompilationLog(const char* compilation_log_path)
+    : log_path_(compilation_log_path) {
+  if (log_path_ != nullptr && OS::FileExists(log_path_)) {
+    if (!Read()) {
+      PLOG(ERROR) << "Failed to read compilation log: " << log_path_;
+    }
+  }
+}
+
+OdrCompilationLog::~OdrCompilationLog() {
+  if (log_path_ != nullptr && !Write()) {
+    PLOG(ERROR) << "Failed to write compilation log: " << log_path_;
+  }
+}
+
+bool OdrCompilationLog::Read() {
+  std::ifstream ifs(log_path_);
+  if (!ifs.good()) {
+    return false;
+  }
+
+  std::string log_version;
+  ifs >> log_version >> std::ws;
+  if (log_version != kLogVersion) {
+    return false;
+  }
+
+  while (!ifs.eof()) {
+    OdrCompilationLogEntry entry;
+    ifs >> entry;
+    if (ifs.fail()) {
+      entries_.clear();
+      return false;
+    }
+    entries_.push_back(entry);
+  }
+
+  return true;
+}
+
+bool OdrCompilationLog::Write() const {
+  std::ofstream ofs(log_path_, std::ofstream::trunc);
+  if (!ofs.good()) {
+    return false;
+  }
+
+  ofs << kLogVersion << std::endl;
+  for (const auto& entry : entries_) {
+    ofs << entry;
+    if (ofs.fail()) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void OdrCompilationLog::Truncate() {
+  if (entries_.size() < kMaxLoggedEntries) {
+    return;
+  }
+
+  size_t excess = entries_.size() - kMaxLoggedEntries;
+  entries_.erase(entries_.begin(), entries_.begin() + excess);
+}
+
+size_t OdrCompilationLog::NumberOfEntries() const {
+  return entries_.size();
+}
+
+const OdrCompilationLogEntry* OdrCompilationLog::Peek(size_t index) const {
+  if (index >= entries_.size()) {
+    return nullptr;
+  }
+  return &entries_[index];
+}
+
+void OdrCompilationLog::Log(int64_t apex_version,
+                            int64_t last_update_millis,
+                            OdrMetrics::Trigger trigger,
+                            ExitCode compilation_result) {
+  time_t now;
+  time(&now);
+  Log(apex_version, last_update_millis, trigger, now, compilation_result);
+}
+
+void OdrCompilationLog::Log(int64_t apex_version,
+                            int64_t last_update_millis,
+                            OdrMetrics::Trigger trigger,
+                            time_t when,
+                            ExitCode compilation_result) {
+  entries_.push_back(OdrCompilationLogEntry{apex_version,
+                                            last_update_millis,
+                                            static_cast<int32_t>(trigger),
+                                            when,
+                                            static_cast<int32_t>(compilation_result)});
+  Truncate();
+}
+
+bool OdrCompilationLog::ShouldAttemptCompile(int64_t apex_version,
+                                             int64_t last_update_millis,
+                                             OdrMetrics::Trigger trigger,
+                                             time_t now) const {
+  if (entries_.size() == 0) {
+    // We have no history, try to compile.
+    return true;
+  }
+
+  if (apex_version != entries_.back().apex_version) {
+    // There is a new ART APEX, we should compile right away.
+    return true;
+  }
+
+    if (last_update_millis != entries_.back().last_update_millis) {
+    // There is a samegrade ART APEX update, we should compile right away.
+    return true;
+  }
+
+  if (trigger == OdrMetrics::Trigger::kDexFilesChanged) {
+    // The DEX files in the classpaths have changed, possibly an OTA has updated them.
+    return true;
+  }
+
+  // Compute the backoff time based on the number of consecutive failures.
+  //
+  // Wait 12 hrs * pow(2, consecutive_failures) since the last compilation attempt.
+  static const int kSecondsPerDay = 86'400;
+  time_t backoff = kSecondsPerDay / 2;
+  for (auto it = entries_.crbegin(); it != entries_.crend(); ++it, backoff *= 2) {
+    if (it->exit_code == ExitCode::kCompilationSuccess) {
+      break;
+    }
+  }
+
+  if (now == 0) {
+    time(&now);
+  }
+
+  const time_t last_attempt = entries_.back().when;
+  const time_t threshold = last_attempt + backoff;
+  return now >= threshold;
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odr_compilation_log.h b/odrefresh/odr_compilation_log.h
new file mode 100644
index 0000000..894079c
--- /dev/null
+++ b/odrefresh/odr_compilation_log.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2021 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_ODREFRESH_ODR_COMPILATION_LOG_H_
+#define ART_ODREFRESH_ODR_COMPILATION_LOG_H_
+
+#include <time.h>
+
+#include <cstdint>
+#include <iosfwd>
+#include <vector>
+
+#include <odrefresh/odrefresh.h>
+#include <odr_metrics.h>
+
+namespace art {
+namespace odrefresh {
+
+// OdrCompilationLogEntry represents the result of a compilation attempt by odrefresh.
+struct OdrCompilationLogEntry {
+  int64_t apex_version;
+  int64_t last_update_millis;
+  int32_t trigger;
+  time_t when;
+  int32_t exit_code;
+};
+
+// Read an `OdrCompilationLogEntry` from an input stream.
+std::istream& operator>>(std::istream& is, OdrCompilationLogEntry& entry);
+
+// Write an `OdrCompilationLogEntry` to an output stream.
+std::ostream& operator<<(std::ostream& os, const OdrCompilationLogEntry& entry);
+
+// Equality test for two `OdrCompilationLogEntry` instances.
+bool operator==(const OdrCompilationLogEntry& lhs, const OdrCompilationLogEntry& rhs);
+bool operator!=(const OdrCompilationLogEntry& lhs, const OdrCompilationLogEntry& rhs);
+
+class OdrCompilationLog {
+ public:
+  // The compilation log location is in the same directory as used for the metricss.log. This
+  // directory is only used by odrefresh whereas the ART apexdata directory is also used by odsign
+  // and others which may lead to the deletion (or rollback) of the log file.
+  static constexpr const char* kCompilationLogFile = "/data/misc/odrefresh/compilation-log.txt";
+
+  // Version string that appears on the first line of the compilation log.
+  static constexpr const char kLogVersion[] = "CompilationLog/1.0";
+
+  // Number of log entries in the compilation log.
+  static constexpr const size_t kMaxLoggedEntries = 4;
+
+  explicit OdrCompilationLog(const char* compilation_log_path = kCompilationLogFile);
+  ~OdrCompilationLog();
+
+  // Applies policy to compilation log to determine whether to recompile.
+  bool ShouldAttemptCompile(int64_t apex_version,
+                            int64_t last_update_millis,
+                            OdrMetrics::Trigger trigger,
+                            time_t now = 0) const;
+
+  // Returns the number of entries in the log. The log never exceeds `kMaxLoggedEntries`.
+  size_t NumberOfEntries() const;
+
+  // Returns the entry at position `index` or nullptr if `index` is out of bounds.
+  const OdrCompilationLogEntry* Peek(size_t index) const;
+
+  void Log(int64_t apex_version,
+           int64_t last_update_millis,
+           OdrMetrics::Trigger trigger,
+           ExitCode compilation_result);
+
+  void Log(int64_t apex_version,
+           int64_t last_update_millis,
+           OdrMetrics::Trigger trigger,
+           time_t when,
+           ExitCode compilation_result);
+
+  // Truncates the in memory log to have `kMaxLoggedEntries` records.
+  void Truncate();
+
+ private:
+  bool Read();
+  bool Write() const;
+
+  std::vector<OdrCompilationLogEntry> entries_;
+  const char* log_path_;
+};
+
+}  // namespace odrefresh
+}  // namespace art
+
+#endif  // ART_ODREFRESH_ODR_COMPILATION_LOG_H_
diff --git a/odrefresh/odr_compilation_log_test.cc b/odrefresh/odr_compilation_log_test.cc
new file mode 100644
index 0000000..d99b4d9
--- /dev/null
+++ b/odrefresh/odr_compilation_log_test.cc
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2021 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 <odr_compilation_log.h>
+
+#include <time.h>
+
+#include <cstdint>
+#include <ctime>
+#include <iosfwd>
+#include <istream>
+#include <limits>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "android-base/file.h"
+#include "base/common_art_test.h"
+#include "odrefresh/odrefresh.h"
+#include "odr_metrics.h"
+
+namespace art {
+namespace odrefresh {
+
+const time_t kSecondsPerDay = 86'400;
+
+class OdrCompilationLogTest : public CommonArtTest {};
+
+TEST(OdrCompilationLogEntry, Equality) {
+  OdrCompilationLogEntry a{1, 2, 3, 4, 5};
+
+  ASSERT_EQ(a, (OdrCompilationLogEntry{1, 2, 3, 4, 5}));
+  ASSERT_NE(a, (OdrCompilationLogEntry{9, 2, 3, 4, 5}));
+  ASSERT_NE(a, (OdrCompilationLogEntry{1, 9, 3, 4, 5}));
+  ASSERT_NE(a, (OdrCompilationLogEntry{1, 2, 9, 4, 5}));
+  ASSERT_NE(a, (OdrCompilationLogEntry{2, 2, 3, 9, 5}));
+  ASSERT_NE(a, (OdrCompilationLogEntry{2, 2, 3, 5, 9}));
+}
+
+TEST(OdrCompilationLogEntry, InputOutput) {
+  const OdrCompilationLogEntry entries[] = {
+      {1, 2, 3, 4, 5},
+      {std::numeric_limits<int64_t>::min(),
+       std::numeric_limits<int64_t>::min(),
+       std::numeric_limits<int32_t>::min(),
+       std::numeric_limits<time_t>::min(),
+       std::numeric_limits<int32_t>::min()},
+      {std::numeric_limits<int64_t>::max(),
+       std::numeric_limits<int64_t>::max(),
+       std::numeric_limits<int32_t>::max(),
+       std::numeric_limits<time_t>::max(),
+       std::numeric_limits<int32_t>::max()},
+       {0, 0, 0, 0, 0},
+      {0x7fedcba9'87654321, 0x5a5a5a5a'5a5a5a5a, 0x12345678, 0x2346789, 0x76543210}
+  };
+  for (const auto& entry : entries) {
+    std::stringstream ss;
+    ss << entry;
+    OdrCompilationLogEntry actual;
+    ss >> actual;
+    ASSERT_EQ(entry, actual);
+  }
+}
+
+TEST(OdrCompilationLogEntry, TruncatedInput) {
+  std::stringstream ss;
+  ss << "1 2";
+
+  OdrCompilationLogEntry entry;
+  ss >> entry;
+
+  ASSERT_TRUE(ss.fail());
+  ASSERT_FALSE(ss.bad());
+}
+
+TEST(OdrCompilationLogEntry, ReadMultiple) {
+  std::stringstream ss;
+  ss << "0 1 2 3 4\n5 6 7 8 9\n";
+
+  OdrCompilationLogEntry entry0, entry1;
+  ss >> entry0 >> entry1;
+  ASSERT_EQ(entry0, (OdrCompilationLogEntry{0, 1, 2, 3, 4}));
+  ASSERT_EQ(entry1, (OdrCompilationLogEntry{5, 6, 7, 8, 9}));
+
+  ASSERT_FALSE(ss.fail());
+  ASSERT_FALSE(ss.bad());
+}
+
+TEST(OdrCompilationLog, ShouldAttemptCompile) {
+  OdrCompilationLog ocl(/*compilation_log_path=*/nullptr);
+
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1, /*last_update_millis=*/762, OdrMetrics::Trigger::kMissingArtifacts, 0));
+
+  ocl.Log(
+      /*apex_version=*/1,
+      /*last_update_millis=*/762,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      ExitCode::kCompilationSuccess);
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/2, /*last_update_millis=*/762, OdrMetrics::Trigger::kApexVersionMismatch));
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1, /*last_update_millis=*/10000, OdrMetrics::Trigger::kApexVersionMismatch));
+  ASSERT_FALSE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1, /*last_update_millis=*/762, OdrMetrics::Trigger::kApexVersionMismatch));
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1, /*last_update_millis=*/762, OdrMetrics::Trigger::kDexFilesChanged));
+  ASSERT_FALSE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1, /*last_update_millis=*/762, OdrMetrics::Trigger::kUnknown));
+}
+
+TEST(OdrCompilationLog, BackOffNoHistory) {
+  time_t start_time;
+  time(&start_time);
+
+  OdrCompilationLog ocl(/*compilation_log_path=*/nullptr);
+
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time));
+
+  // Start log
+  ocl.Log(/*apex_version=*/1,
+          /*last_update_millis=*/0,
+          OdrMetrics::Trigger::kApexVersionMismatch,
+          start_time,
+          ExitCode::kCompilationFailed);
+  ASSERT_FALSE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time));
+  ASSERT_FALSE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + kSecondsPerDay / 2));
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + kSecondsPerDay));
+
+  // Add one more log entry
+  ocl.Log(/*apex_version=*/1,
+          /*last_update_millis=*/0,
+          OdrMetrics::Trigger::kApexVersionMismatch,
+          start_time,
+          ExitCode::kCompilationFailed);
+  ASSERT_FALSE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + kSecondsPerDay));
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + 2 * kSecondsPerDay));
+
+  // One more.
+  ocl.Log(/*apex_version=*/1,
+          /*last_update_millis=*/0,
+          OdrMetrics::Trigger::kApexVersionMismatch,
+          start_time,
+          ExitCode::kCompilationFailed);
+  ASSERT_FALSE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + 3 * kSecondsPerDay));
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + 4 * kSecondsPerDay));
+
+  // And one for the road.
+  ocl.Log(/*apex_version=*/1,
+          /*last_update_millis=*/0,
+          OdrMetrics::Trigger::kApexVersionMismatch,
+          start_time,
+          ExitCode::kCompilationFailed);
+  ASSERT_FALSE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + 7 * kSecondsPerDay));
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + 8 * kSecondsPerDay));
+}
+
+TEST(OdrCompilationLog, BackOffHappyHistory) {
+  time_t start_time;
+  time(&start_time);
+
+  OdrCompilationLog ocl(/*compilation_log_path=*/nullptr);
+
+  // Start log with a successful entry.
+  ocl.Log(/*apex_version=*/1,
+          /*last_update_millis=*/0,
+          OdrMetrics::Trigger::kApexVersionMismatch,
+          start_time,
+          ExitCode::kCompilationSuccess);
+  ASSERT_FALSE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time));
+  ASSERT_FALSE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + kSecondsPerDay / 4));
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + kSecondsPerDay / 2));
+
+  // Add a log entry for a failed compilation.
+  ocl.Log(/*apex_version=*/1,
+          /*last_update_millis=*/0,
+          OdrMetrics::Trigger::kApexVersionMismatch,
+          start_time,
+          ExitCode::kCompilationFailed);
+  ASSERT_FALSE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + kSecondsPerDay / 2));
+  ASSERT_TRUE(ocl.ShouldAttemptCompile(
+      /*apex_version=*/1,
+      /*last_update_millis=*/0,
+      OdrMetrics::Trigger::kApexVersionMismatch,
+      start_time + kSecondsPerDay));
+}
+
+TEST_F(OdrCompilationLogTest, LogNumberOfEntriesAndPeek) {
+  OdrCompilationLog ocl(/*compilation_log_path=*/nullptr);
+
+  std::vector<OdrCompilationLogEntry> entries = {
+    { 0, 1, 2, 3, 4 },
+    { 1, 2, 3, 4, 5 },
+    { 2, 3, 4, 5, 6 },
+    { 3, 4, 5, 6, 7 },
+    { 4, 5, 6, 7, 8 },
+    { 5, 6, 7, 8, 9 },
+    { 6, 7, 8, 9, 10 }
+  };
+
+  for (size_t i = 0; i < entries.size(); ++i) {
+    OdrCompilationLogEntry& e = entries[i];
+    ocl.Log(e.apex_version,
+            e.last_update_millis,
+            static_cast<OdrMetrics::Trigger>(e.trigger),
+            e.when,
+            static_cast<ExitCode>(e.exit_code));
+    if (i < OdrCompilationLog::kMaxLoggedEntries) {
+      ASSERT_EQ(i + 1, ocl.NumberOfEntries());
+    } else {
+      ASSERT_EQ(OdrCompilationLog::kMaxLoggedEntries, ocl.NumberOfEntries());
+    }
+
+    for (size_t j = 0; j < ocl.NumberOfEntries(); ++j) {
+      const OdrCompilationLogEntry* logged = ocl.Peek(j);
+      ASSERT_TRUE(logged != nullptr);
+      const OdrCompilationLogEntry& expected = entries[i + 1 - ocl.NumberOfEntries() + j];
+      ASSERT_EQ(expected, *logged);
+    }
+  }
+}
+
+TEST_F(OdrCompilationLogTest, LogReadWrite) {
+  std::vector<OdrCompilationLogEntry> entries = {
+    { 0, 1, 2, 3, 4 },
+    { 1, 2, 3, 4, 5 },
+    { 2, 3, 4, 5, 6 },
+    { 3, 4, 5, 6, 7 },
+    { 4, 5, 6, 7, 8 },
+    { 5, 6, 7, 8, 9 },
+    { 6, 7, 8, 9, 10 }
+  };
+
+  ScratchFile scratch_file;
+  scratch_file.Close();
+
+  for (size_t i = 0; i < entries.size(); ++i) {
+    {
+      OdrCompilationLog ocl(scratch_file.GetFilename().c_str());
+      OdrCompilationLogEntry& e = entries[i];
+      ocl.Log(e.apex_version,
+              e.last_update_millis,
+              static_cast<OdrMetrics::Trigger>(e.trigger),
+              e.when,
+              static_cast<ExitCode>(e.exit_code));
+    }
+
+    {
+      OdrCompilationLog ocl(scratch_file.GetFilename().c_str());
+      if (i < OdrCompilationLog::kMaxLoggedEntries) {
+        ASSERT_EQ(i + 1, ocl.NumberOfEntries());
+      } else {
+        ASSERT_EQ(OdrCompilationLog::kMaxLoggedEntries, ocl.NumberOfEntries());
+      }
+
+      for (size_t j = 0; j < ocl.NumberOfEntries(); ++j) {
+        const OdrCompilationLogEntry* logged = ocl.Peek(j);
+        ASSERT_TRUE(logged != nullptr);
+        const OdrCompilationLogEntry& expected = entries[i + 1 - ocl.NumberOfEntries() + j];
+        ASSERT_EQ(expected, *logged);
+      }
+    }
+  }
+}
+
+TEST_F(OdrCompilationLogTest, BackoffBasedOnLog) {
+  time_t start_time;
+  time(&start_time);
+
+  ScratchFile scratch_file;
+  scratch_file.Close();
+
+  const char* log_path = scratch_file.GetFilename().c_str();
+  {
+    OdrCompilationLog ocl(log_path);
+
+    ASSERT_TRUE(ocl.ShouldAttemptCompile(
+        /*apex_version=*/1,
+        /*last_update_millis=*/0,
+        OdrMetrics::Trigger::kApexVersionMismatch,
+        start_time));
+  }
+
+  {
+    OdrCompilationLog ocl(log_path);
+
+    // Start log
+    ocl.Log(/*apex_version=*/1,
+            /*last_update_millis=*/0,
+            OdrMetrics::Trigger::kApexVersionMismatch,
+            start_time,
+            ExitCode::kCompilationFailed);
+  }
+
+  {
+    OdrCompilationLog ocl(log_path);
+    ASSERT_FALSE(ocl.ShouldAttemptCompile(
+        /*apex_version=*/1,
+        /*last_update_millis=*/0,
+        OdrMetrics::Trigger::kApexVersionMismatch,
+        start_time));
+    ASSERT_FALSE(ocl.ShouldAttemptCompile(
+        /*apex_version=*/1,
+        /*last_update_millis=*/0,
+        OdrMetrics::Trigger::kApexVersionMismatch,
+        start_time + kSecondsPerDay / 2));
+    ASSERT_TRUE(ocl.ShouldAttemptCompile(
+        /*apex_version=*/1,
+        /*last_update_millis=*/0,
+        OdrMetrics::Trigger::kApexVersionMismatch,
+        start_time + kSecondsPerDay));
+  }
+
+  {
+    // Add one more log entry
+    OdrCompilationLog ocl(log_path);
+    ocl.Log(/*apex_version=*/1,
+            /*last_update_millis=*/0,
+            OdrMetrics::Trigger::kApexVersionMismatch,
+            start_time,
+            ExitCode::kCompilationFailed);
+  }
+
+  {
+    OdrCompilationLog ocl(log_path);
+
+    ASSERT_FALSE(ocl.ShouldAttemptCompile(
+        /*apex_version=*/1,
+        /*last_update_millis=*/0,
+        OdrMetrics::Trigger::kApexVersionMismatch,
+        start_time + kSecondsPerDay));
+    ASSERT_TRUE(ocl.ShouldAttemptCompile(
+        /*apex_version=*/1,
+        /*last_update_millis=*/0,
+        OdrMetrics::Trigger::kApexVersionMismatch,
+        start_time + 2 * kSecondsPerDay));
+  }
+
+  {
+    // One more log entry.
+    OdrCompilationLog ocl(log_path);
+    ocl.Log(/*apex_version=*/1,
+            /*last_update_millis=*/0,
+            OdrMetrics::Trigger::kApexVersionMismatch,
+            start_time,
+            ExitCode::kCompilationFailed);
+  }
+
+  {
+    OdrCompilationLog ocl(log_path);
+    ASSERT_FALSE(ocl.ShouldAttemptCompile(
+        /*apex_version=*/1,
+        /*last_update_millis=*/0,
+        OdrMetrics::Trigger::kApexVersionMismatch,
+        start_time + 3 * kSecondsPerDay));
+    ASSERT_TRUE(ocl.ShouldAttemptCompile(
+        /*apex_version=*/1,
+        /*last_update_millis=*/0,
+        OdrMetrics::Trigger::kApexVersionMismatch,
+        start_time + 4 * kSecondsPerDay));
+  }
+
+  {
+    // And one for the road.
+    OdrCompilationLog ocl(log_path);
+    ocl.Log(/*apex_version=*/1,
+            /*last_update_millis=*/0,
+            OdrMetrics::Trigger::kApexVersionMismatch,
+            start_time,
+            ExitCode::kCompilationFailed);
+  }
+
+  {
+    OdrCompilationLog ocl(log_path);
+    ASSERT_FALSE(ocl.ShouldAttemptCompile(
+        /*apex_version=*/1,
+        /*last_update_millis=*/0,
+        OdrMetrics::Trigger::kApexVersionMismatch,
+        start_time + 7 * kSecondsPerDay));
+    ASSERT_TRUE(ocl.ShouldAttemptCompile(
+        /*apex_version=*/1,
+        /*last_update_millis=*/0,
+        OdrMetrics::Trigger::kApexVersionMismatch,
+        start_time + 8 * kSecondsPerDay));
+  }
+}
+
+TEST(OdrCompilationLog, LastUpdateMillisChangeTriggersCompilation) {
+  time_t start_time;
+  time(&start_time);
+
+  OdrCompilationLog ocl(/*compilation_log_path=*/nullptr);
+
+  for (int64_t last_update_millis = 0; last_update_millis < 10000; last_update_millis += 1000) {
+    static const int64_t kApexVersion = 19999;
+    ASSERT_TRUE(ocl.ShouldAttemptCompile(
+        kApexVersion, last_update_millis, OdrMetrics::Trigger::kApexVersionMismatch, start_time));
+    ocl.Log(kApexVersion,
+            last_update_millis,
+            OdrMetrics::Trigger::kApexVersionMismatch,
+            start_time,
+            ExitCode::kCompilationSuccess);
+    ASSERT_FALSE(ocl.ShouldAttemptCompile(kApexVersion,
+                                          last_update_millis,
+                                          OdrMetrics::Trigger::kApexVersionMismatch,
+                                          start_time + 1));
+  }
+}
+
+TEST(OdrCompilationLog, ApexVersionChangeTriggersCompilation) {
+  time_t start_time;
+  time(&start_time);
+
+  OdrCompilationLog ocl(/*compilation_log_path=*/nullptr);
+
+  for (int64_t apex_version = 0; apex_version < 10000; apex_version += 1000) {
+    static const int64_t kLastUpdateMillis = 777;
+    ASSERT_TRUE(ocl.ShouldAttemptCompile(apex_version,
+                                         kLastUpdateMillis,
+                                         OdrMetrics::Trigger::kApexVersionMismatch,
+                                         start_time + 8 * kSecondsPerDay));
+    ocl.Log(apex_version,
+            kLastUpdateMillis,
+            OdrMetrics::Trigger::kApexVersionMismatch,
+            start_time,
+            ExitCode::kCompilationSuccess);
+    ASSERT_FALSE(ocl.ShouldAttemptCompile(apex_version,
+                                          kLastUpdateMillis,
+                                          OdrMetrics::Trigger::kApexVersionMismatch,
+                                          start_time + 1));
+  }
+}
+
+TEST_F(OdrCompilationLogTest, NewLogVersionTriggersCompilation) {
+  static const int64_t kApexVersion = 1066;
+  static const int64_t kLastUpdateMillis = 777;
+  time_t start_time;
+  time(&start_time);
+
+  ScratchFile scratch_file;
+  scratch_file.Close();
+
+  // Generate a compilation log.
+  {
+    OdrCompilationLog ocl(scratch_file.GetFilename().c_str());
+    for (size_t i = 0; i < OdrCompilationLog::kMaxLoggedEntries; ++i) {
+      ocl.Log(kApexVersion,
+              kLastUpdateMillis,
+              OdrMetrics::Trigger::kApexVersionMismatch,
+              start_time,
+              ExitCode::kCompilationSuccess);
+      ASSERT_FALSE(ocl.ShouldAttemptCompile(
+          kApexVersion, kLastUpdateMillis, OdrMetrics::Trigger::kApexVersionMismatch, start_time));
+    }
+  }
+
+  // Replace version string in the compilation log.
+  std::string log_text;
+  ASSERT_TRUE(android::base::ReadFileToString(scratch_file.GetFilename(), &log_text));
+  std::string new_log_version = std::string(OdrCompilationLog::kLogVersion) + "a";
+  log_text.replace(0, new_log_version.size() - 1, new_log_version);
+  ASSERT_TRUE(android::base::WriteStringToFile(log_text, scratch_file.GetFilename()));
+
+  // Read log with updated version entry, check it is treated as out-of-date.
+  {
+    OdrCompilationLog ocl(scratch_file.GetFilename().c_str());
+    ASSERT_TRUE(ocl.ShouldAttemptCompile(
+        kApexVersion, kLastUpdateMillis, OdrMetrics::Trigger::kApexVersionMismatch, start_time));
+    ASSERT_EQ(0u, ocl.NumberOfEntries());
+  }
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odr_config.h b/odrefresh/odr_config.h
new file mode 100644
index 0000000..4161944
--- /dev/null
+++ b/odrefresh/odr_config.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2021 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_ODREFRESH_ODR_CONFIG_H_
+#define ART_ODREFRESH_ODR_CONFIG_H_
+
+#include <string>
+#include <vector>
+
+#include "android-base/file.h"
+#include "arch/instruction_set.h"
+#include "base/globals.h"
+#include "log/log.h"
+
+namespace art {
+namespace odrefresh {
+
+// An enumeration of the possible zygote configurations on Android.
+enum class ZygoteKind : uint8_t {
+  // 32-bit primary zygote, no secondary zygote.
+  kZygote32 = 0,
+  // 32-bit primary zygote, 64-bit secondary zygote.
+  kZygote32_64 = 1,
+  // 64-bit primary zygote, 32-bit secondary zygote.
+  kZygote64_32 = 2,
+  // 64-bit primary zygote, no secondary zygote.
+  kZygote64 = 3
+};
+
+// Configuration class for odrefresh. Exists to enable abstracting environment variables and
+// system properties into a configuration class for development and testing purposes.
+class OdrConfig final {
+ private:
+  std::string apex_info_list_file_;
+  std::string art_bin_dir_;
+  std::string dex2oat_;
+  std::string dex2oat_boot_classpath_;
+  bool dry_run_;
+  InstructionSet isa_;
+  std::string program_name_;
+  std::string system_server_classpath_;
+  std::string updatable_bcp_packages_file_;
+  ZygoteKind zygote_kind_;
+
+ public:
+  explicit OdrConfig(const char* program_name)
+    : dry_run_(false),
+      isa_(InstructionSet::kNone),
+      program_name_(android::base::Basename(program_name)) {
+  }
+
+  const std::string& GetApexInfoListFile() const { return apex_info_list_file_; }
+
+  std::vector<InstructionSet> GetBootExtensionIsas() const {
+    const auto [isa32, isa64] = GetPotentialInstructionSets();
+    switch (zygote_kind_) {
+      case ZygoteKind::kZygote32:
+        return {isa32};
+      case ZygoteKind::kZygote32_64:
+      case ZygoteKind::kZygote64_32:
+        return {isa32, isa64};
+      case ZygoteKind::kZygote64:
+        return {isa64};
+    }
+  }
+
+  InstructionSet GetSystemServerIsa() const {
+    const auto [isa32, isa64] = GetPotentialInstructionSets();
+    switch (zygote_kind_) {
+      case ZygoteKind::kZygote32:
+      case ZygoteKind::kZygote32_64:
+        return isa32;
+      case ZygoteKind::kZygote64_32:
+      case ZygoteKind::kZygote64:
+        return isa64;
+    }
+  }
+
+  const std::string& GetDex2oatBootClasspath() const { return dex2oat_boot_classpath_; }
+
+  std::string GetDex2Oat() const {
+    const char* prefix = UseDebugBinaries() ? "dex2oatd" : "dex2oat";
+    const char* suffix = "";
+    if (kIsTargetBuild) {
+      switch (zygote_kind_) {
+        case ZygoteKind::kZygote32:
+          suffix = "32";
+          break;
+        case ZygoteKind::kZygote32_64:
+        case ZygoteKind::kZygote64_32:
+        case ZygoteKind::kZygote64:
+          suffix = "64";
+          break;
+      }
+    }
+    return art_bin_dir_ + '/' + prefix + suffix;
+  }
+
+  std::string GetDexOptAnalyzer() const {
+    const char* dexoptanalyzer{UseDebugBinaries() ? "dexoptanalyzerd" : "dexoptanalyzer"};
+    return art_bin_dir_ + '/' + dexoptanalyzer;
+  }
+
+  bool GetDryRun() const { return dry_run_; }
+  const std::string& GetSystemServerClasspath() const { return system_server_classpath_; }
+  const std::string& GetUpdatableBcpPackagesFile() const { return updatable_bcp_packages_file_; }
+
+  void SetApexInfoListFile(const std::string& file_path) { apex_info_list_file_ = file_path; }
+  void SetArtBinDir(const std::string& art_bin_dir) { art_bin_dir_ = art_bin_dir; }
+
+  void SetDex2oatBootclasspath(const std::string& classpath) {
+    dex2oat_boot_classpath_ = classpath;
+  }
+
+  void SetDryRun() { dry_run_ = true; }
+  void SetIsa(const InstructionSet isa) { isa_ = isa; }
+
+  void SetSystemServerClasspath(const std::string& classpath) {
+    system_server_classpath_ = classpath;
+  }
+
+  void SetUpdatableBcpPackagesFile(const std::string& file) { updatable_bcp_packages_file_ = file; }
+  void SetZygoteKind(ZygoteKind zygote_kind) { zygote_kind_ = zygote_kind; }
+
+ private:
+  // Returns a pair for the possible instruction sets for the configured instruction set
+  // architecture. The first item is the 32-bit architecture and the second item is the 64-bit
+  // architecture. The current `isa` is based on `kRuntimeISA` on target, odrefresh is compiled
+  // 32-bit by default so this method returns all options which are finessed based on the
+  // `ro.zygote` property.
+  std::pair<InstructionSet, InstructionSet> GetPotentialInstructionSets() const {
+    switch (isa_) {
+      case art::InstructionSet::kArm:
+      case art::InstructionSet::kArm64:
+        return std::make_pair(art::InstructionSet::kArm, art::InstructionSet::kArm64);
+      case art::InstructionSet::kX86:
+      case art::InstructionSet::kX86_64:
+        return std::make_pair(art::InstructionSet::kX86, art::InstructionSet::kX86_64);
+      case art::InstructionSet::kThumb2:
+      case art::InstructionSet::kNone:
+        LOG(FATAL) << "Invalid instruction set " << isa_;
+        return std::make_pair(art::InstructionSet::kNone, art::InstructionSet::kNone);
+    }
+  }
+
+  bool UseDebugBinaries() const { return program_name_ == "odrefreshd"; }
+
+  OdrConfig() = delete;
+  OdrConfig(const OdrConfig&) = delete;
+  OdrConfig& operator=(const OdrConfig&) = delete;
+};
+
+}  // namespace odrefresh
+}  // namespace art
+
+#endif  // ART_ODREFRESH_ODR_CONFIG_H_
diff --git a/odrefresh/odr_fs_utils.cc b/odrefresh/odr_fs_utils.cc
new file mode 100644
index 0000000..9f3a68b
--- /dev/null
+++ b/odrefresh/odr_fs_utils.cc
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2021 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 "odr_fs_utils.h"
+
+#include <dirent.h>
+#include <ftw.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <unistd.h>
+
+#include <iosfwd>
+#include <memory>
+#include <ostream>
+#include <queue>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/strings.h>
+#include <base/os.h>
+
+namespace art {
+namespace odrefresh {
+
+// Callback for use with nftw(3) to assist with clearing files and sub-directories.
+// This method removes files and directories below the top-level directory passed to nftw().
+static int NftwCleanUpCallback(const char* fpath,
+                               const struct stat* sb ATTRIBUTE_UNUSED,
+                               int typeflag,
+                               struct FTW* ftwbuf) {
+  switch (typeflag) {
+    case FTW_F:
+      return unlink(fpath);
+    case FTW_DP:
+      return (ftwbuf->level == 0) ? 0 : rmdir(fpath);
+    default:
+      return -1;
+  }
+}
+
+WARN_UNUSED bool CleanDirectory(const std::string& dir_path) {
+  if (!OS::DirectoryExists(dir_path.c_str())) {
+    return true;
+  }
+
+  static constexpr int kMaxDescriptors = 4;  // Limit the need for nftw() to re-open descriptors.
+  if (nftw(dir_path.c_str(), NftwCleanUpCallback, kMaxDescriptors, FTW_DEPTH | FTW_MOUNT) != 0) {
+    LOG(ERROR) << "Failed to clean-up '" << dir_path << "'";
+    return false;
+  }
+  return true;
+}
+
+WARN_UNUSED bool EnsureDirectoryExists(const std::string& absolute_path) {
+  if (absolute_path.empty() || absolute_path[0] != '/') {
+    LOG(ERROR) << "Path not absolute '" << absolute_path << "'";
+    return false;
+  }
+  std::string path;
+  for (const std::string& directory : android::base::Split(absolute_path, "/")) {
+    path.append("/").append(directory);
+    if (!OS::DirectoryExists(path.c_str())) {
+      static constexpr mode_t kDirectoryMode = S_IRWXU | S_IRGRP | S_IXGRP| S_IROTH | S_IXOTH;
+      if (mkdir(path.c_str(), kDirectoryMode) != 0) {
+        PLOG(ERROR) << "Could not create directory: " << path;
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool GetFreeSpace(const std::string& path, uint64_t* bytes) {
+  struct statvfs sv;
+  if (statvfs(path.c_str(), &sv) != 0) {
+    PLOG(ERROR) << "statvfs '" << path << "'";
+    return false;
+  }
+  *bytes = sv.f_bfree * sv.f_bsize;
+  return true;
+}
+
+bool GetUsedSpace(const std::string& path, uint64_t* bytes) {
+  static constexpr std::string_view kCurrentDirectory{"."};
+  static constexpr std::string_view kParentDirectory{".."};
+  static constexpr size_t kBytesPerBlock = 512;  // see manual page for stat(2).
+
+  uint64_t file_bytes = 0;
+  std::queue<std::string> unvisited;
+  unvisited.push(path);
+  while (!unvisited.empty()) {
+    std::string current = unvisited.front();
+    unvisited.pop();
+    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(current.c_str()), closedir);
+    if (!dir) {
+      continue;
+    }
+    for (auto entity = readdir(dir.get()); entity != nullptr; entity = readdir(dir.get())) {
+      std::string_view name{entity->d_name};
+      if (name == kCurrentDirectory || name == kParentDirectory) {
+        continue;
+      }
+      std::string entity_name = current + "/" + entity->d_name;
+      if (entity->d_type == DT_DIR) {
+        unvisited.push(entity_name.c_str());
+      } else if (entity->d_type == DT_REG) {
+        struct stat sb;
+        if (stat(entity_name.c_str(), &sb) != 0) {
+          PLOG(ERROR) << "Failed to stat() file " << entity_name;
+          continue;
+        }
+        file_bytes += sb.st_blocks * kBytesPerBlock;
+      }
+    }
+  }
+  *bytes = file_bytes;
+  return true;
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odr_fs_utils.h b/odrefresh/odr_fs_utils.h
new file mode 100644
index 0000000..cefa11e
--- /dev/null
+++ b/odrefresh/odr_fs_utils.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 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_ODREFRESH_ODR_FS_UTILS_H_
+#define ART_ODREFRESH_ODR_FS_UTILS_H_
+
+#include <cstdint>
+#include <iosfwd>
+
+#include <android-base/macros.h>
+
+namespace art {
+namespace odrefresh {
+
+// Cleans directory by removing all files and sub-directories under `dir_path`.
+// Returns true on success, false otherwise.
+WARN_UNUSED bool CleanDirectory(const std::string& dir_path);
+
+// Create all directories on `absolute_dir_path`.
+// Returns true on success, false otherwise.
+WARN_UNUSED bool EnsureDirectoryExists(const std::string& absolute_dir_path);
+
+// Get free space for filesystem containing `path`.
+// Returns true on success, false otherwise.
+WARN_UNUSED bool GetFreeSpace(const std::string& path, uint64_t* bytes);
+
+// Gets space used under directory `dir_path`.
+// Returns true on success, false otherwise.
+WARN_UNUSED bool GetUsedSpace(const std::string& dir_path, uint64_t* bytes);
+
+}  // namespace odrefresh
+}  // namespace art
+
+#endif  // ART_ODREFRESH_ODR_FS_UTILS_H_
diff --git a/odrefresh/odr_fs_utils_test.cc b/odrefresh/odr_fs_utils_test.cc
new file mode 100644
index 0000000..6c43265
--- /dev/null
+++ b/odrefresh/odr_fs_utils_test.cc
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2021 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 <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <iosfwd>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "android-base/stringprintf.h"
+#include "base/bit_utils.h"
+#include "base/common_art_test.h"
+#include "base/os.h"
+#include "base/unix_file/fd_file.h"
+#include "odr_fs_utils.h"
+
+namespace art {
+namespace odrefresh {
+
+class OdrFsUtilsTest : public CommonArtTest {};
+namespace {
+
+static bool CreateFile(const char* file_path, size_t bytes) {
+  std::unique_ptr<File> fp(OS::CreateEmptyFile(file_path));
+  if (!fp) {
+    return false;
+  }
+
+  std::vector<char> buffer(bytes, 0xa5);
+  if (!fp->WriteFully(buffer.data(), buffer.size())) {
+    fp->Erase();
+    return false;
+  }
+
+  if (fp->FlushClose() != 0) {
+    fp->Erase();
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+TEST_F(OdrFsUtilsTest, CleanDirectory) {
+  ScratchDir scratch_dir(/*keep_files=*/false);
+
+  // Create some sub-directories and files
+  const std::string dir_paths[] = {
+      scratch_dir.GetPath() + "/a",
+      scratch_dir.GetPath() + "/b",
+      scratch_dir.GetPath() + "/b/c",
+      scratch_dir.GetPath() + "/d"
+  };
+  for (const auto& dir_path : dir_paths) {
+    ASSERT_EQ(0, mkdir(dir_path.c_str(), S_IRWXU));
+  }
+
+  const std::string file_paths[] = {
+      scratch_dir.GetPath() + "/zero.txt",
+      scratch_dir.GetPath() + "/a/one.txt",
+      scratch_dir.GetPath() + "/b/two.txt",
+      scratch_dir.GetPath() + "/b/c/three.txt",
+      scratch_dir.GetPath() + "/b/c/four.txt",
+  };
+  for (const auto& file_path : file_paths) {
+    ASSERT_TRUE(CreateFile(file_path.c_str(), 4096));
+  }
+
+  // Clean all files and sub-directories
+  ASSERT_TRUE(CleanDirectory(scratch_dir.GetPath()));
+
+  // Check nothing we created remains.
+  for (const auto& dir_path : dir_paths) {
+    ASSERT_FALSE(OS::DirectoryExists(dir_path.c_str()));
+  }
+
+  for (const auto& file_path : file_paths) {
+    ASSERT_FALSE(OS::FileExists(file_path.c_str(), true));
+  }
+}
+
+TEST_F(OdrFsUtilsTest, EnsureDirectoryExistsBadPath) {
+  // Pick a path where not even a root test runner can write.
+  ASSERT_FALSE(EnsureDirectoryExists("/proc/unlikely/to/be/writable"));
+}
+
+TEST_F(OdrFsUtilsTest, EnsureDirectoryExistsEmptyPath) {
+  ASSERT_FALSE(EnsureDirectoryExists(""));
+}
+
+TEST_F(OdrFsUtilsTest, EnsureDirectoryExistsRelativePath) {
+  ASSERT_FALSE(EnsureDirectoryExists("a/b/c"));
+}
+
+TEST_F(OdrFsUtilsTest, EnsureDirectoryExistsSubDirs) {
+  ScratchDir scratch_dir(/*keep_files=*/false);
+
+  const char* relative_sub_dirs[] = {"a", "b/c", "d/e/f/"};
+  for (const char* relative_sub_dir : relative_sub_dirs) {
+    ASSERT_TRUE(EnsureDirectoryExists(scratch_dir.GetPath() + "/" + relative_sub_dir));
+  }
+}
+
+TEST_F(OdrFsUtilsTest, DISABLED_GetUsedSpace) {
+  static constexpr size_t kFirstFileBytes = 1;
+  static constexpr size_t kSecondFileBytes = 16111;
+  static constexpr size_t kBytesPerBlock = 512;
+
+  ScratchDir scratch_dir(/*keep_files=*/false);
+
+  const std::string first_file_path = scratch_dir.GetPath() + "/1.dat";
+  ASSERT_TRUE(CreateFile(first_file_path.c_str(), kFirstFileBytes));
+
+  struct stat sb;
+  ASSERT_EQ(0, stat(first_file_path.c_str(), &sb));
+  ASSERT_EQ(kFirstFileBytes, static_cast<decltype(kFirstFileBytes)>(sb.st_size));
+
+  uint64_t bytes_used = 0;
+  ASSERT_TRUE(GetUsedSpace(scratch_dir.GetPath().c_str(), &bytes_used));
+
+  const std::string second_file_path = scratch_dir.GetPath() + "/2.dat";
+  ASSERT_TRUE(CreateFile(second_file_path.c_str(), kSecondFileBytes));
+
+  ASSERT_TRUE(GetUsedSpace(scratch_dir.GetPath().c_str(), &bytes_used));
+  uint64_t expected_bytes_used = RoundUp(kFirstFileBytes, sb.st_blocks * kBytesPerBlock) +
+                                 RoundUp(kSecondFileBytes, sb.st_blocks * kBytesPerBlock);
+  ASSERT_EQ(expected_bytes_used, bytes_used);
+
+  const std::string sub_dir_path = scratch_dir.GetPath() + "/sub";
+  ASSERT_TRUE(EnsureDirectoryExists(sub_dir_path));
+  for (size_t i = 1; i < 32768; i *= 17) {
+    const std::string path = android::base::StringPrintf("%s/%zu", sub_dir_path.c_str(), i);
+    ASSERT_TRUE(CreateFile(path.c_str(), i));
+    expected_bytes_used += RoundUp(i, sb.st_blocks * kBytesPerBlock);
+    ASSERT_TRUE(GetUsedSpace(scratch_dir.GetPath().c_str(), &bytes_used));
+    ASSERT_EQ(expected_bytes_used, bytes_used);
+  }
+}
+
+TEST_F(OdrFsUtilsTest, GetUsedSpaceBadPath) {
+  ScratchDir scratch_dir(/*keep_files=*/false);
+  const std::string bad_path = scratch_dir.GetPath() + "/bad_path";
+  uint64_t bytes_used = ~0ull;
+  ASSERT_TRUE(GetUsedSpace(bad_path, &bytes_used));
+  ASSERT_EQ(0ull, bytes_used);
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odr_metrics.cc b/odrefresh/odr_metrics.cc
new file mode 100644
index 0000000..4bddb17
--- /dev/null
+++ b/odrefresh/odr_metrics.cc
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2021 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 "odr_metrics.h"
+
+#include <unistd.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <fstream>
+#include <iosfwd>
+#include <optional>
+#include <ostream>
+#include <string>
+
+#include <android-base/logging.h>
+#include <base/os.h>
+#include <base/string_view_cpp20.h>
+#include <odr_fs_utils.h>
+#include <odr_metrics_record.h>
+
+namespace art {
+namespace odrefresh {
+
+OdrMetrics::OdrMetrics(const std::string& cache_directory, const std::string& metrics_file)
+    : cache_directory_(cache_directory), metrics_file_(metrics_file), status_(Status::kOK) {
+  DCHECK(StartsWith(metrics_file_, "/"));
+
+  // Remove existing metrics file if it exists.
+  if (OS::FileExists(metrics_file.c_str())) {
+    if (unlink(metrics_file.c_str()) != 0) {
+      PLOG(ERROR) << "Failed to remove metrics file '" << metrics_file << "'";
+    }
+  }
+
+  // Create apexdata dalvik-cache directory if it does not exist. It is required before
+  // calling GetFreeSpaceMiB().
+  if (!EnsureDirectoryExists(cache_directory)) {
+    // This should never fail except for no space on device or configuration issues (e.g. SELinux).
+    LOG(WARNING) << "Cache directory '" << cache_directory << "' could not be created.";
+  }
+  cache_space_free_start_mib_ = GetFreeSpaceMiB(cache_directory);
+}
+
+OdrMetrics::~OdrMetrics() {
+  cache_space_free_end_mib_ = GetFreeSpaceMiB(cache_directory_);
+
+  // Log metrics only if odrefresh detected a reason to compile.
+  if (trigger_.has_value()) {
+    WriteToFile(metrics_file_, this);
+  }
+}
+
+void OdrMetrics::SetCompilationTime(int32_t seconds) {
+  switch (stage_) {
+    case Stage::kPrimaryBootClasspath:
+      primary_bcp_compilation_seconds_ = seconds;
+      break;
+    case Stage::kSecondaryBootClasspath:
+      secondary_bcp_compilation_seconds_ = seconds;
+      break;
+    case Stage::kSystemServerClasspath:
+      system_server_compilation_seconds_ = seconds;
+      break;
+    case Stage::kCheck:
+    case Stage::kComplete:
+    case Stage::kPreparation:
+    case Stage::kUnknown:
+      break;
+  }
+}
+
+void OdrMetrics::SetStage(Stage stage) {
+  if (status_ == Status::kOK) {
+    stage_ = stage;
+  }
+}
+
+int32_t OdrMetrics::GetFreeSpaceMiB(const std::string& path) {
+  static constexpr uint32_t kBytesPerMiB = 1024 * 1024;
+  static constexpr uint64_t kNominalMaximumCacheBytes = 1024 * kBytesPerMiB;
+
+  // Assume nominal cache space is 1GiB (much larger than expected, ~100MB).
+  uint64_t used_space_bytes;
+  if (!GetUsedSpace(path, &used_space_bytes)) {
+    used_space_bytes = 0;
+  }
+  uint64_t nominal_free_space_bytes = kNominalMaximumCacheBytes - used_space_bytes;
+
+  // Get free space on partition containing `path`.
+  uint64_t free_space_bytes;
+  if (!GetFreeSpace(path, &free_space_bytes)) {
+    free_space_bytes = kNominalMaximumCacheBytes;
+  }
+
+  // Pick the smallest free space, ie space on partition or nominal space in cache.
+  // There are two things of interest for metrics:
+  //  (i) identifying failed compilations due to low space.
+  // (ii) understanding what the storage requirements are for the spectrum of boot classpaths and
+  //      system_server classpaths.
+  uint64_t free_space_mib = std::min(free_space_bytes, nominal_free_space_bytes) / kBytesPerMiB;
+  return static_cast<int32_t>(free_space_mib);
+}
+
+bool OdrMetrics::ToRecord(/*out*/OdrMetricsRecord* record) const {
+  if (!trigger_.has_value()) {
+    return false;
+  }
+  record->art_apex_version = art_apex_version_;
+  record->trigger = static_cast<uint32_t>(trigger_.value());
+  record->stage_reached = static_cast<uint32_t>(stage_);
+  record->status = static_cast<uint32_t>(status_);
+  record->primary_bcp_compilation_seconds = primary_bcp_compilation_seconds_;
+  record->secondary_bcp_compilation_seconds = secondary_bcp_compilation_seconds_;
+  record->system_server_compilation_seconds = system_server_compilation_seconds_;
+  record->cache_space_free_start_mib = cache_space_free_start_mib_;
+  record->cache_space_free_end_mib = cache_space_free_end_mib_;
+  return true;
+}
+
+void OdrMetrics::WriteToFile(const std::string& path, const OdrMetrics* metrics) {
+  OdrMetricsRecord record;
+  if (!metrics->ToRecord(&record)) {
+    LOG(ERROR) << "Attempting to report metrics without a compilation trigger.";
+    return;
+  }
+
+  // Preserve order from frameworks/proto_logging/stats/atoms.proto in metrics file written.
+  std::ofstream ofs(path);
+  ofs << record;
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odr_metrics.h b/odrefresh/odr_metrics.h
new file mode 100644
index 0000000..cd80bef
--- /dev/null
+++ b/odrefresh/odr_metrics.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2021 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_ODREFRESH_ODR_METRICS_H_
+#define ART_ODREFRESH_ODR_METRICS_H_
+
+#include <chrono>
+#include <cstdint>
+#include <iosfwd>
+#include <optional>
+#include <string>
+
+#include "base/macros.h"
+#include "odr_metrics_record.h"
+
+namespace art {
+namespace odrefresh {
+
+class OdrMetrics final {
+ public:
+  // Enumeration used to track the latest stage reached running odrefresh.
+  //
+  // These values mirror those in OdrefreshReported::Stage in frameworks/proto_logging/atoms.proto.
+  // NB There are gaps between the values in case an additional stages are introduced.
+  enum class Stage : uint8_t {
+    kUnknown = 0,
+    kCheck = 10,
+    kPreparation = 20,
+    kPrimaryBootClasspath = 30,
+    kSecondaryBootClasspath = 40,
+    kSystemServerClasspath = 50,
+    kComplete = 60,
+  };
+
+  // Enumeration describing the overall status, processing stops on the first error discovered.
+  //
+  // These values mirror those in OdrefreshReported::Status in frameworks/proto_logging/atoms.proto.
+  enum class Status : uint8_t {
+    kUnknown = 0,
+    kOK = 1,
+    kNoSpace = 2,
+    kIoError = 3,
+    kDex2OatError = 4,
+    kTimeLimitExceeded = 5,
+    kStagingFailed = 6,
+    kInstallFailed = 7,
+  };
+
+  // Enumeration describing the cause of compilation (if any) in odrefresh.
+  //
+  // These values mirror those in OdrefreshReported::Trigger in
+  // frameworks/proto_logging/atoms.proto.
+  enum class Trigger : uint8_t {
+    kUnknown = 0,
+    kApexVersionMismatch = 1,
+    kDexFilesChanged = 2,
+    kMissingArtifacts = 3,
+  };
+
+  explicit OdrMetrics(const std::string& cache_directory,
+                      const std::string& metrics_file = kOdrefreshMetricsFile);
+  ~OdrMetrics();
+
+  // Gets the ART APEX that metrics are being collected on behalf of.
+  int64_t GetArtApexVersion() const {
+    return art_apex_version_;
+  }
+
+  // Sets the ART APEX that metrics are being collected on behalf of.
+  void SetArtApexVersion(int64_t version) {
+    art_apex_version_ = version;
+  }
+
+  // Gets the ART APEX last update time in milliseconds.
+  int64_t GetArtApexLastUpdateMillis() const {
+    return art_apex_last_update_millis_;
+  }
+
+  // Sets the ART APEX last update time in milliseconds.
+  void SetArtApexLastUpdateMillis(int64_t last_update_millis) {
+    art_apex_last_update_millis_ = last_update_millis;
+  }
+
+  // Gets the trigger for metrics collection. The trigger is the reason why odrefresh considers
+  // compilation necessary.
+  Trigger GetTrigger() const {
+    return trigger_.has_value() ? trigger_.value() : Trigger::kUnknown;
+  }
+
+  // Sets the trigger for metrics collection. The trigger is the reason why odrefresh considers
+  // compilation necessary. Only call this method if compilation is necessary as the presence
+  // of a trigger means we will try to record and upload metrics.
+  void SetTrigger(const Trigger trigger) {
+    trigger_ = trigger;
+  }
+
+  // Sets the execution status of the current odrefresh processing stage.
+  void SetStatus(const Status status) {
+    status_ = status;
+  }
+
+  // Sets the current odrefresh processing stage.
+  void SetStage(Stage stage);
+
+  // Record metrics into an OdrMetricsRecord.
+  // returns true on success, false if instance is not valid (because the trigger value is not set).
+  bool ToRecord(/*out*/OdrMetricsRecord* record) const;
+
+ private:
+  OdrMetrics(const OdrMetrics&) = delete;
+  OdrMetrics operator=(const OdrMetrics&) = delete;
+
+  static int32_t GetFreeSpaceMiB(const std::string& path);
+  static void WriteToFile(const std::string& path, const OdrMetrics* metrics);
+
+  void SetCompilationTime(int32_t seconds);
+
+  const std::string cache_directory_;
+  const std::string metrics_file_;
+
+  int64_t art_apex_version_ = 0;
+  int64_t art_apex_last_update_millis_ = 0;
+  std::optional<Trigger> trigger_ = {};  // metrics are only logged if compilation is triggered.
+  Stage stage_ = Stage::kUnknown;
+  Status status_ = Status::kUnknown;
+
+  int32_t primary_bcp_compilation_seconds_ = 0;
+  int32_t secondary_bcp_compilation_seconds_ = 0;
+  int32_t system_server_compilation_seconds_ = 0;
+  int32_t cache_space_free_start_mib_ = 0;
+  int32_t cache_space_free_end_mib_ = 0;
+
+  friend class ScopedOdrCompilationTimer;
+};
+
+// Timer used to measure compilation time (in seconds). Automatically associates the time recorded
+// with the current stage of the metrics used.
+class ScopedOdrCompilationTimer final {
+ public:
+  explicit ScopedOdrCompilationTimer(OdrMetrics& metrics) :
+    metrics_(metrics), start_(std::chrono::steady_clock::now()) {}
+
+  ~ScopedOdrCompilationTimer() {
+    auto elapsed_time = std::chrono::steady_clock::now() - start_;
+    auto elapsed_seconds = std::chrono::duration_cast<std::chrono::seconds>(elapsed_time);
+    metrics_.SetCompilationTime(static_cast<int32_t>(elapsed_seconds.count()));
+  }
+
+ private:
+  OdrMetrics& metrics_;
+  std::chrono::time_point<std::chrono::steady_clock> start_;
+
+  DISALLOW_ALLOCATION();
+};
+
+// Generated ostream operators.
+std::ostream& operator<<(std::ostream& os, OdrMetrics::Status status);
+std::ostream& operator<<(std::ostream& os, OdrMetrics::Stage stage);
+std::ostream& operator<<(std::ostream& os, OdrMetrics::Trigger trigger);
+
+}  // namespace odrefresh
+}  // namespace art
+
+#endif  // ART_ODREFRESH_ODR_METRICS_H_
diff --git a/odrefresh/odr_metrics_record.cc b/odrefresh/odr_metrics_record.cc
new file mode 100644
index 0000000..fc135d3
--- /dev/null
+++ b/odrefresh/odr_metrics_record.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 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 "odr_metrics_record.h"
+
+#include <iosfwd>
+#include <istream>
+#include <ostream>
+#include <streambuf>
+#include <string>
+
+namespace art {
+namespace odrefresh {
+
+std::istream& operator>>(std::istream& is, OdrMetricsRecord& record) {
+  // Block I/O related exceptions
+  auto saved_exceptions = is.exceptions();
+  is.exceptions(std::ios_base::iostate {});
+
+  // The order here matches the field order of MetricsRecord.
+  is >> record.art_apex_version >> std::ws;
+  is >> record.trigger >> std::ws;
+  is >> record.stage_reached >> std::ws;
+  is >> record.status >> std::ws;
+  is >> record.primary_bcp_compilation_seconds >> std::ws;
+  is >> record.secondary_bcp_compilation_seconds >> std::ws;
+  is >> record.system_server_compilation_seconds >> std::ws;
+  is >> record.cache_space_free_start_mib >> std::ws;
+  is >> record.cache_space_free_end_mib >> std::ws;
+
+  // Restore I/O related exceptions
+  is.exceptions(saved_exceptions);
+  return is;
+}
+
+std::ostream& operator<<(std::ostream& os, const OdrMetricsRecord& record) {
+  static const char kSpace = ' ';
+
+  // Block I/O related exceptions
+  auto saved_exceptions = os.exceptions();
+  os.exceptions(std::ios_base::iostate {});
+
+  // The order here matches the field order of MetricsRecord.
+  os << record.art_apex_version << kSpace;
+  os << record.trigger << kSpace;
+  os << record.stage_reached << kSpace;
+  os << record.status << kSpace;
+  os << record.primary_bcp_compilation_seconds << kSpace;
+  os << record.secondary_bcp_compilation_seconds << kSpace;
+  os << record.system_server_compilation_seconds << kSpace;
+  os << record.cache_space_free_start_mib << kSpace;
+  os << record.cache_space_free_end_mib << std::endl;
+
+  // Restore I/O related exceptions
+  os.exceptions(saved_exceptions);
+  return os;
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odr_metrics_record.h b/odrefresh/odr_metrics_record.h
new file mode 100644
index 0000000..9dd51a6
--- /dev/null
+++ b/odrefresh/odr_metrics_record.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 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_ODREFRESH_ODR_METRICS_RECORD_H_
+#define ART_ODREFRESH_ODR_METRICS_RECORD_H_
+
+#include <cstdint>
+#include <iosfwd>  // For forward-declaration of std::string.
+
+namespace art {
+namespace odrefresh {
+
+// Default location for storing metrics from odrefresh.
+constexpr const char* kOdrefreshMetricsFile = "/data/misc/odrefresh/odrefresh-metrics.txt";
+
+// MetricsRecord is a simpler container for Odrefresh metric values reported to statsd. The order
+// and types of fields here mirror definition of `OdrefreshReported` in
+// frameworks/proto_logging/stats/atoms.proto.
+struct OdrMetricsRecord {
+  int64_t art_apex_version;
+  int32_t trigger;
+  int32_t stage_reached;
+  int32_t status;
+  int32_t primary_bcp_compilation_seconds;
+  int32_t secondary_bcp_compilation_seconds;
+  int32_t system_server_compilation_seconds;
+  int32_t cache_space_free_start_mib;
+  int32_t cache_space_free_end_mib;
+};
+
+// Read a `MetricsRecord` from an `istream`.
+//
+// This method blocks istream related exceptions, the caller should check `is.fail()` is false after
+// calling.
+//
+// Returns `is`.
+std::istream& operator>>(std::istream& is, OdrMetricsRecord& record);
+
+// Write a `MetricsRecord` to an `ostream`.
+//
+// This method blocks ostream related exceptions, the caller should check `os.fail()` is false after
+// calling.
+//
+// Returns `os`
+std::ostream& operator<<(std::ostream& os, const OdrMetricsRecord& record);
+
+}  // namespace odrefresh
+}  // namespace art
+
+#endif  // ART_ODREFRESH_ODR_METRICS_RECORD_H_
diff --git a/odrefresh/odr_metrics_record_test.cc b/odrefresh/odr_metrics_record_test.cc
new file mode 100644
index 0000000..dd739d6
--- /dev/null
+++ b/odrefresh/odr_metrics_record_test.cc
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2021 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 "odr_metrics_record.h"
+
+#include <string.h>
+
+#include <fstream>
+
+#include "base/common_art_test.h"
+
+namespace art {
+namespace odrefresh {
+
+class OdrMetricsRecordTest : public CommonArtTest {};
+
+TEST_F(OdrMetricsRecordTest, HappyPath) {
+  const OdrMetricsRecord expected {
+    .art_apex_version = 0x01233456'789abcde,
+    .trigger = 0x01020304,
+    .stage_reached = 0x11121314,
+    .status = 0x21222324,
+    .primary_bcp_compilation_seconds = 0x31323334,
+    .secondary_bcp_compilation_seconds = 0x41424344,
+    .system_server_compilation_seconds = 0x51525354,
+    .cache_space_free_start_mib = 0x61626364,
+    .cache_space_free_end_mib = 0x71727374
+  };
+
+  ScratchDir dir(/*keep_files=*/false);
+  std::string file_path = dir.GetPath() + "/metrics-record.txt";
+
+  {
+    std::ofstream ofs(file_path);
+    ofs << expected;
+    ASSERT_FALSE(ofs.fail());
+    ofs.close();
+  }
+
+  OdrMetricsRecord actual {};
+  {
+    std::ifstream ifs(file_path);
+    ifs >> actual;
+    ASSERT_TRUE(ifs.eof());
+  }
+
+  ASSERT_EQ(expected.art_apex_version, actual.art_apex_version);
+  ASSERT_EQ(expected.trigger, actual.trigger);
+  ASSERT_EQ(expected.stage_reached, actual.stage_reached);
+  ASSERT_EQ(expected.status, actual.status);
+  ASSERT_EQ(expected.primary_bcp_compilation_seconds, actual.primary_bcp_compilation_seconds);
+  ASSERT_EQ(expected.secondary_bcp_compilation_seconds, actual.secondary_bcp_compilation_seconds);
+  ASSERT_EQ(expected.system_server_compilation_seconds, actual.system_server_compilation_seconds);
+  ASSERT_EQ(expected.cache_space_free_start_mib, actual.cache_space_free_start_mib);
+  ASSERT_EQ(expected.cache_space_free_end_mib, actual.cache_space_free_end_mib);
+  ASSERT_EQ(0, memcmp(&expected, &actual, sizeof(expected)));
+}
+
+TEST_F(OdrMetricsRecordTest, EmptyInput) {
+  ScratchDir dir(/*keep_files=*/false);
+  std::string file_path = dir.GetPath() + "/metrics-record.txt";
+
+  std::ifstream ifs(file_path);
+  OdrMetricsRecord record;
+  ifs >> record;
+
+  ASSERT_TRUE(ifs.fail());
+  ASSERT_TRUE(!ifs);
+}
+
+TEST_F(OdrMetricsRecordTest, ClosedInput) {
+  ScratchDir dir(/*keep_files=*/false);
+  std::string file_path = dir.GetPath() + "/metrics-record.txt";
+
+  std::ifstream ifs(file_path);
+  ifs.close();
+
+  OdrMetricsRecord record;
+  ifs >> record;
+
+  ASSERT_TRUE(ifs.fail());
+  ASSERT_TRUE(!ifs);
+}
+
+TEST_F(OdrMetricsRecordTest, ClosedOutput) {
+  ScratchDir dir(/*keep_files=*/false);
+  std::string file_path = dir.GetPath() + "/metrics-record.txt";
+
+  std::ofstream ofs(file_path);
+  ofs.close();
+
+  OdrMetricsRecord record {};
+  ofs << record;
+
+  ASSERT_TRUE(ofs.fail());
+  ASSERT_TRUE(!ofs.good());
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odr_metrics_test.cc b/odrefresh/odr_metrics_test.cc
new file mode 100644
index 0000000..4519f00
--- /dev/null
+++ b/odrefresh/odr_metrics_test.cc
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2021 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 "odr_metrics.h"
+#include "base/casts.h"
+#include "odr_metrics_record.h"
+
+#include <unistd.h>
+
+#include <fstream>
+#include <memory>
+#include <string>
+
+#include "base/common_art_test.h"
+
+namespace art {
+namespace odrefresh {
+
+class OdrMetricsTest : public CommonArtTest {
+ public:
+  void SetUp() override {
+    CommonArtTest::SetUp();
+
+    scratch_dir_ = std::make_unique<ScratchDir>();
+    metrics_file_path_ = scratch_dir_->GetPath() + "/metrics.txt";
+    cache_directory_ = scratch_dir_->GetPath() + "/dir";
+    mkdir(cache_directory_.c_str(), S_IRWXU);
+  }
+
+  void TearDown() override {
+    scratch_dir_.reset();
+  }
+
+  bool MetricsFileExists() const {
+    const char* path = metrics_file_path_.c_str();
+    return OS::FileExists(path);
+  }
+
+  bool RemoveMetricsFile() const {
+    const char* path = metrics_file_path_.c_str();
+    if (OS::FileExists(path)) {
+      return unlink(path) == 0;
+    }
+    return true;
+  }
+
+  const std::string GetCacheDirectory() const { return cache_directory_; }
+  const std::string GetMetricsFilePath() const { return metrics_file_path_; }
+
+ protected:
+  std::unique_ptr<ScratchDir> scratch_dir_;
+  std::string metrics_file_path_;
+  std::string cache_directory_;
+};
+
+TEST_F(OdrMetricsTest, ToRecordFailsIfNotTriggered) {
+  {
+    OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
+    OdrMetricsRecord record {};
+    EXPECT_FALSE(metrics.ToRecord(&record));
+  }
+
+  {
+    OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
+    metrics.SetArtApexVersion(99);
+    metrics.SetStage(OdrMetrics::Stage::kCheck);
+    metrics.SetStatus(OdrMetrics::Status::kNoSpace);
+    OdrMetricsRecord record {};
+    EXPECT_FALSE(metrics.ToRecord(&record));
+  }
+}
+
+TEST_F(OdrMetricsTest, ToRecordSucceedsIfTriggered) {
+  OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
+  metrics.SetArtApexVersion(99);
+  metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
+  metrics.SetStage(OdrMetrics::Stage::kCheck);
+  metrics.SetStatus(OdrMetrics::Status::kNoSpace);
+
+  OdrMetricsRecord record{};
+  EXPECT_TRUE(metrics.ToRecord(&record));
+
+  EXPECT_EQ(99, record.art_apex_version);
+  EXPECT_EQ(OdrMetrics::Trigger::kApexVersionMismatch,
+            enum_cast<OdrMetrics::Trigger>(record.trigger));
+  EXPECT_EQ(OdrMetrics::Stage::kCheck, enum_cast<OdrMetrics::Stage>(record.stage_reached));
+  EXPECT_EQ(OdrMetrics::Status::kNoSpace, enum_cast<OdrMetrics::Status>(record.status));
+}
+
+TEST_F(OdrMetricsTest, MetricsFileIsNotCreatedIfNotTriggered) {
+  EXPECT_TRUE(RemoveMetricsFile());
+
+  // Metrics file is (potentially) written in OdrMetrics destructor.
+  {
+    OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
+    metrics.SetArtApexVersion(99);
+    metrics.SetStage(OdrMetrics::Stage::kCheck);
+    metrics.SetStatus(OdrMetrics::Status::kNoSpace);
+  }
+  EXPECT_FALSE(MetricsFileExists());
+}
+
+TEST_F(OdrMetricsTest, NoMetricsFileIsCreatedIfTriggered) {
+  EXPECT_TRUE(RemoveMetricsFile());
+
+  // Metrics file is (potentially) written in OdrMetrics destructor.
+  {
+    OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
+    metrics.SetArtApexVersion(101);
+    metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
+    metrics.SetStage(OdrMetrics::Stage::kCheck);
+    metrics.SetStatus(OdrMetrics::Status::kNoSpace);
+  }
+  EXPECT_TRUE(MetricsFileExists());
+}
+
+TEST_F(OdrMetricsTest, StageDoesNotAdvancedAfterFailure) {
+  OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
+  metrics.SetArtApexVersion(1999);
+  metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
+  metrics.SetStage(OdrMetrics::Stage::kCheck);
+  metrics.SetStatus(OdrMetrics::Status::kNoSpace);
+  metrics.SetStage(OdrMetrics::Stage::kComplete);
+
+  OdrMetricsRecord record{};
+  EXPECT_TRUE(metrics.ToRecord(&record));
+
+  EXPECT_EQ(OdrMetrics::Stage::kCheck, enum_cast<OdrMetrics::Stage>(record.stage_reached));
+}
+
+TEST_F(OdrMetricsTest, TimeValuesAreRecorded) {
+  OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
+  metrics.SetArtApexVersion(1999);
+  metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
+  metrics.SetStage(OdrMetrics::Stage::kCheck);
+  metrics.SetStatus(OdrMetrics::Status::kOK);
+
+  // Primary boot classpath compilation time.
+  OdrMetricsRecord record{};
+  {
+    metrics.SetStage(OdrMetrics::Stage::kPrimaryBootClasspath);
+    ScopedOdrCompilationTimer timer(metrics);
+    sleep(2u);
+  }
+  EXPECT_TRUE(metrics.ToRecord(&record));
+  EXPECT_EQ(OdrMetrics::Stage::kPrimaryBootClasspath,
+            enum_cast<OdrMetrics::Stage>(record.stage_reached));
+  EXPECT_NE(0, record.primary_bcp_compilation_seconds);
+  EXPECT_GT(10, record.primary_bcp_compilation_seconds);
+  EXPECT_EQ(0, record.secondary_bcp_compilation_seconds);
+  EXPECT_EQ(0, record.system_server_compilation_seconds);
+
+  // Secondary boot classpath compilation time.
+  {
+    metrics.SetStage(OdrMetrics::Stage::kSecondaryBootClasspath);
+    ScopedOdrCompilationTimer timer(metrics);
+    sleep(2u);
+  }
+  EXPECT_TRUE(metrics.ToRecord(&record));
+  EXPECT_EQ(OdrMetrics::Stage::kSecondaryBootClasspath,
+            enum_cast<OdrMetrics::Stage>(record.stage_reached));
+  EXPECT_NE(0, record.primary_bcp_compilation_seconds);
+  EXPECT_NE(0, record.secondary_bcp_compilation_seconds);
+  EXPECT_GT(10, record.secondary_bcp_compilation_seconds);
+  EXPECT_EQ(0, record.system_server_compilation_seconds);
+
+  // system_server classpath compilation time.
+  {
+    metrics.SetStage(OdrMetrics::Stage::kSystemServerClasspath);
+    ScopedOdrCompilationTimer timer(metrics);
+    sleep(2u);
+  }
+  EXPECT_TRUE(metrics.ToRecord(&record));
+  EXPECT_EQ(OdrMetrics::Stage::kSystemServerClasspath,
+            enum_cast<OdrMetrics::Stage>(record.stage_reached));
+  EXPECT_NE(0, record.primary_bcp_compilation_seconds);
+  EXPECT_NE(0, record.secondary_bcp_compilation_seconds);
+  EXPECT_NE(0, record.system_server_compilation_seconds);
+  EXPECT_GT(10, record.system_server_compilation_seconds);
+}
+
+TEST_F(OdrMetricsTest, CacheSpaceValuesAreUpdated) {
+  OdrMetricsRecord snap {};
+  snap.cache_space_free_start_mib = -1;
+  snap.cache_space_free_end_mib = -1;
+  {
+    OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
+    metrics.SetArtApexVersion(1999);
+    metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
+    metrics.SetStage(OdrMetrics::Stage::kCheck);
+    metrics.SetStatus(OdrMetrics::Status::kOK);
+    EXPECT_TRUE(metrics.ToRecord(&snap));
+    EXPECT_NE(0, snap.cache_space_free_start_mib);
+    EXPECT_EQ(0, snap.cache_space_free_end_mib);
+  }
+
+  OdrMetricsRecord on_disk;
+  std::ifstream ifs(GetMetricsFilePath());
+  EXPECT_TRUE(ifs);
+  ifs >> on_disk;
+  EXPECT_TRUE(ifs);
+  EXPECT_EQ(snap.cache_space_free_start_mib, on_disk.cache_space_free_start_mib);
+  EXPECT_NE(0, on_disk.cache_space_free_end_mib);
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odr_statslog_android.cc b/odrefresh/odr_statslog_android.cc
new file mode 100644
index 0000000..7db348e
--- /dev/null
+++ b/odrefresh/odr_statslog_android.cc
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2021 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 "odr_statslog/odr_statslog.h"
+
+#include <cstdint>
+#include <fstream>
+#include <istream>
+#include <string>
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+#include "odr_metrics.h"
+#include "odr_metrics_record.h"
+#include "statslog_odrefresh.h"
+
+namespace art {
+namespace odrefresh {
+
+using android::base::StringPrintf;
+
+namespace {
+
+// Convert bare value from art::metrics::Stage to value defined in atoms.proto.
+int32_t TranslateStage(int32_t art_metrics_stage) {
+  switch (static_cast<OdrMetrics::Stage>(art_metrics_stage)) {
+    case OdrMetrics::Stage::kUnknown:
+      return metrics::statsd::ODREFRESH_REPORTED__STAGE_REACHED__STAGE_UNKNOWN;
+    case OdrMetrics::Stage::kCheck:
+      return metrics::statsd::ODREFRESH_REPORTED__STAGE_REACHED__STAGE_CHECK;
+    case OdrMetrics::Stage::kPreparation:
+      return metrics::statsd::ODREFRESH_REPORTED__STAGE_REACHED__STAGE_PREPARATION;
+    case OdrMetrics::Stage::kPrimaryBootClasspath:
+      return metrics::statsd::ODREFRESH_REPORTED__STAGE_REACHED__STAGE_PRIMARY_BOOT_CLASSPATH;
+    case OdrMetrics::Stage::kSecondaryBootClasspath:
+      return metrics::statsd::ODREFRESH_REPORTED__STAGE_REACHED__STAGE_SECONDARY_BOOT_CLASSPATH;
+    case OdrMetrics::Stage::kSystemServerClasspath:
+      return metrics::statsd::ODREFRESH_REPORTED__STAGE_REACHED__STAGE_SYSTEM_SERVER_CLASSPATH;
+    case OdrMetrics::Stage::kComplete:
+      return metrics::statsd::ODREFRESH_REPORTED__STAGE_REACHED__STAGE_COMPLETE;
+  }
+
+  LOG(ERROR) << "Unknown stage value: " << art_metrics_stage;
+  return -1;
+}
+
+// Convert bare value from art::metrics::Status to value defined in atoms.proto.
+int32_t TranslateStatus(int32_t art_metrics_status) {
+  switch (static_cast<OdrMetrics::Status>(art_metrics_status)) {
+    case OdrMetrics::Status::kUnknown:
+      return metrics::statsd::ODREFRESH_REPORTED__STATUS__STATUS_UNKNOWN;
+    case OdrMetrics::Status::kOK:
+      return metrics::statsd::ODREFRESH_REPORTED__STATUS__STATUS_OK;
+    case OdrMetrics::Status::kNoSpace:
+      return metrics::statsd::ODREFRESH_REPORTED__STATUS__STATUS_NO_SPACE;
+    case OdrMetrics::Status::kIoError:
+      return metrics::statsd::ODREFRESH_REPORTED__STATUS__STATUS_IO_ERROR;
+    case OdrMetrics::Status::kDex2OatError:
+      return metrics::statsd::ODREFRESH_REPORTED__STATUS__STATUS_DEX2OAT_ERROR;
+    case OdrMetrics::Status::kTimeLimitExceeded:
+      return metrics::statsd::ODREFRESH_REPORTED__STATUS__STATUS_TIME_LIMIT_EXCEEDED;
+    case OdrMetrics::Status::kStagingFailed:
+      return metrics::statsd::ODREFRESH_REPORTED__STATUS__STATUS_STAGING_FAILED;
+    case OdrMetrics::Status::kInstallFailed:
+      return metrics::statsd::ODREFRESH_REPORTED__STATUS__STATUS_INSTALL_FAILED;
+  }
+
+  LOG(ERROR) << "Unknown status value: " << art_metrics_status;
+  return -1;
+}
+
+// Convert bare value from art::metrics::Trigger to value defined in atoms.proto.
+int32_t TranslateTrigger(int32_t art_metrics_trigger) {
+  switch (static_cast<OdrMetrics::Trigger>(art_metrics_trigger)) {
+    case OdrMetrics::Trigger::kUnknown:
+      return metrics::statsd::ODREFRESH_REPORTED__TRIGGER__TRIGGER_UNKNOWN;
+    case OdrMetrics::Trigger::kApexVersionMismatch:
+      return metrics::statsd::ODREFRESH_REPORTED__TRIGGER__TRIGGER_APEX_VERSION_MISMATCH;
+    case OdrMetrics::Trigger::kDexFilesChanged:
+      return metrics::statsd::ODREFRESH_REPORTED__TRIGGER__TRIGGER_DEX_FILES_CHANGED;
+    case OdrMetrics::Trigger::kMissingArtifacts:
+      return metrics::statsd::ODREFRESH_REPORTED__TRIGGER__TRIGGER_MISSING_ARTIFACTS;
+  }
+
+  LOG(ERROR) << "Unknown trigger value: " << art_metrics_trigger;
+  return -1;
+}
+
+bool ReadValues(const char* metrics_file,
+                /*out*/ OdrMetricsRecord* record,
+                /*out*/ std::string* error_msg) {
+  std::ifstream ifs(metrics_file);
+  if (!ifs) {
+    *error_msg = android::base::StringPrintf(
+        "metrics file '%s' could not be opened: %s", metrics_file, strerror(errno));
+    return false;
+  }
+
+  ifs >> *record;
+  if (!ifs) {
+    *error_msg = "file parsing error.";
+    return false;
+  }
+
+  //
+  // Convert values defined as enums to their statsd values.
+  //
+
+  record->trigger = TranslateTrigger(record->trigger);
+  if (record->trigger < 0) {
+    *error_msg = "failed to parse trigger.";
+    return false;
+  }
+
+  record->stage_reached = TranslateStage(record->stage_reached);
+  if (record->stage_reached < 0) {
+    *error_msg = "failed to parse stage_reached.";
+    return false;
+  }
+
+  record->status = TranslateStatus(record->status);
+  if (record->status < 0) {
+    *error_msg = "failed to parse status.";
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+bool UploadStatsIfAvailable(/*out*/std::string* error_msg) {
+  OdrMetricsRecord record;
+  if (!ReadValues(kOdrefreshMetricsFile, &record, error_msg)) {
+    return false;
+  }
+
+  // Write values to statsd. The order of values passed is the same as the order of the
+  // fields in OdrMetricsRecord.
+  int bytes_written = art::metrics::statsd::stats_write(metrics::statsd::ODREFRESH_REPORTED,
+                                                        record.art_apex_version,
+                                                        record.trigger,
+                                                        record.stage_reached,
+                                                        record.status,
+                                                        record.primary_bcp_compilation_seconds,
+                                                        record.secondary_bcp_compilation_seconds,
+                                                        record.system_server_compilation_seconds,
+                                                        record.cache_space_free_start_mib,
+                                                        record.cache_space_free_end_mib);
+  if (bytes_written <= 0) {
+    *error_msg = android::base::StringPrintf("stats_write returned %d", bytes_written);
+    return false;
+  }
+
+  if (unlink(kOdrefreshMetricsFile) != 0) {
+    *error_msg = StringPrintf("failed to unlink '%s': %s", kOdrefreshMetricsFile, strerror(errno));
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odr_statslog_host.cc b/odrefresh/odr_statslog_host.cc
new file mode 100644
index 0000000..118563a
--- /dev/null
+++ b/odrefresh/odr_statslog_host.cc
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 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 "odr_statslog/odr_statslog.h"  // for declararation of UploadStatsIfAvailable().
+
+#include <iosfwd>                       // for forward declaration of std::string.
+namespace art {
+namespace odrefresh {
+
+bool UploadStatsIfAvailable(/*out*/std::string* /*error_msg*/) {
+  // No stats reported from host, report success.
+  return true;
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
new file mode 100644
index 0000000..2cef50d
--- /dev/null
+++ b/odrefresh/odrefresh.cc
@@ -0,0 +1,1514 @@
+/*
+ * Copyright (C) 2020 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 "odrefresh/odrefresh.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <cstdarg>
+#include <cstdint>
+#include <cstdlib>
+#include <fstream>
+#include <initializer_list>
+#include <iosfwd>
+#include <iostream>
+#include <memory>
+#include <optional>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "android-base/file.h"
+#include "android-base/logging.h"
+#include "android-base/macros.h"
+#include "android-base/properties.h"
+#include "android-base/stringprintf.h"
+#include "android-base/strings.h"
+#include "android/log.h"
+#include "arch/instruction_set.h"
+#include "base/file_utils.h"
+#include "base/globals.h"
+#include "base/macros.h"
+#include "base/os.h"
+#include "base/string_view_cpp20.h"
+#include "base/unix_file/fd_file.h"
+#include "com_android_apex.h"
+#include "com_android_art.h"
+#include "dex/art_dex_file_loader.h"
+#include "dexoptanalyzer.h"
+#include "exec_utils.h"
+#include "log/log.h"
+#include "palette/palette.h"
+#include "palette/palette_types.h"
+
+#include "odr_artifacts.h"
+#include "odr_compilation_log.h"
+#include "odr_config.h"
+#include "odr_fs_utils.h"
+#include "odr_metrics.h"
+
+namespace art {
+namespace odrefresh {
+
+namespace apex = com::android::apex;
+namespace art_apex = com::android::art;
+
+namespace {
+
+// Name of cache info file in the ART Apex artifact cache.
+static constexpr const char* kCacheInfoFile = "cache-info.xml";
+
+static void UsageErrorV(const char* fmt, va_list ap) {
+  std::string error;
+  android::base::StringAppendV(&error, fmt, ap);
+  if (isatty(fileno(stderr))) {
+    std::cerr << error << std::endl;
+  } else {
+    LOG(ERROR) << error;
+  }
+}
+
+static void UsageError(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  UsageErrorV(fmt, ap);
+  va_end(ap);
+}
+
+NO_RETURN static void ArgumentError(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  UsageErrorV(fmt, ap);
+  va_end(ap);
+  UsageError("Try '--help' for more information.");
+  exit(EX_USAGE);
+}
+
+NO_RETURN static void UsageHelp(const char* argv0) {
+  std::string name(android::base::Basename(argv0));
+  UsageError("Usage: %s ACTION", name.c_str());
+  UsageError("On-device refresh tool for boot class path extensions and system server");
+  UsageError("following an update of the ART APEX.");
+  UsageError("");
+  UsageError("Valid ACTION choices are:");
+  UsageError("");
+  UsageError(
+      "--check          Check compilation artifacts are up-to-date based on metadata (fast).");
+  UsageError("--compile        Compile boot class path extensions and system_server jars");
+  UsageError("                 when necessary.");
+  UsageError("--force-compile  Unconditionally compile the boot class path extensions and");
+  UsageError("                 system_server jars.");
+  UsageError("--verify         Verify artifacts are up-to-date with dexoptanalyzer (slow).");
+  UsageError("--help           Display this help information.");
+  exit(EX_USAGE);
+}
+
+static std::string Concatenate(std::initializer_list<std::string_view> args) {
+  std::stringstream ss;
+  for (auto arg : args) {
+    ss << arg;
+  }
+  return ss.str();
+}
+
+static std::string GetEnvironmentVariableOrDie(const char* name) {
+  const char* value = getenv(name);
+  LOG_ALWAYS_FATAL_IF(value == nullptr, "%s is not defined.", name);
+  return value;
+}
+
+static std::string QuotePath(std::string_view path) {
+  return Concatenate({"'", path, "'"});
+}
+
+static void EraseFiles(const std::vector<std::unique_ptr<File>>& files) {
+  for (auto& file : files) {
+    file->Erase(/*unlink=*/true);
+  }
+}
+
+// Moves `files` to the directory `output_directory_path`.
+//
+// If any of the files cannot be moved, then all copies of the files are removed from both
+// the original location and the output location.
+//
+// Returns true if all files are moved, false otherwise.
+static bool MoveOrEraseFiles(const std::vector<std::unique_ptr<File>>& files,
+                             std::string_view output_directory_path) {
+  std::vector<std::unique_ptr<File>> output_files;
+  for (auto& file : files) {
+    const std::string file_basename(android::base::Basename(file->GetPath()));
+    const std::string output_file_path = Concatenate({output_directory_path, "/", file_basename});
+    const std::string input_file_path = file->GetPath();
+
+    output_files.emplace_back(OS::CreateEmptyFileWriteOnly(output_file_path.c_str()));
+    if (output_files.back() == nullptr) {
+      PLOG(ERROR) << "Failed to open " << QuotePath(output_file_path);
+      output_files.pop_back();
+      EraseFiles(output_files);
+      EraseFiles(files);
+      return false;
+    }
+
+    static constexpr mode_t kFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+    if (fchmod(output_files.back()->Fd(), kFileMode) != 0) {
+      PLOG(ERROR) << "Could not set file mode on " << QuotePath(output_file_path);
+      EraseFiles(output_files);
+      EraseFiles(files);
+      return false;
+    }
+
+    const size_t file_bytes = file->GetLength();
+    if (!output_files.back()->Copy(file.get(), /*offset=*/0, file_bytes)) {
+      PLOG(ERROR) << "Failed to copy " << QuotePath(file->GetPath())
+                  << " to " << QuotePath(output_file_path);
+      EraseFiles(output_files);
+      EraseFiles(files);
+      return false;
+    }
+
+    if (!file->Erase(/*unlink=*/true)) {
+      PLOG(ERROR) << "Failed to erase " << QuotePath(file->GetPath());
+      EraseFiles(output_files);
+      EraseFiles(files);
+      return false;
+    }
+
+    if (output_files.back()->FlushCloseOrErase() != 0) {
+      PLOG(ERROR) << "Failed to flush and close file " << QuotePath(output_file_path);
+      EraseFiles(output_files);
+      EraseFiles(files);
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace
+
+bool ParseZygoteKind(const char* input, ZygoteKind* zygote_kind) {
+  std::string_view z(input);
+  if (z == "zygote32") {
+    *zygote_kind = ZygoteKind::kZygote32;
+    return true;
+  } else if (z == "zygote32_64") {
+    *zygote_kind = ZygoteKind::kZygote32_64;
+    return true;
+  } else if (z == "zygote64_32") {
+    *zygote_kind = ZygoteKind::kZygote64_32;
+    return true;
+  } else if (z == "zygote64") {
+    *zygote_kind = ZygoteKind::kZygote64;
+    return true;
+  }
+  return false;
+}
+
+class OnDeviceRefresh final {
+ private:
+  // Maximum execution time for odrefresh from start to end.
+  static constexpr time_t kMaximumExecutionSeconds = 300;
+
+  // Maximum execution time for any child process spawned.
+  static constexpr time_t kMaxChildProcessSeconds = 90;
+
+  // Configuration to use.
+  const OdrConfig& config_;
+
+  // Path to cache information file that is used to speed up artifact checking.
+  const std::string cache_info_filename_;
+
+  // List of boot extension components that should be compiled.
+  std::vector<std::string> boot_extension_compilable_jars_;
+
+  // List of system_server components that should be compiled.
+  std::vector<std::string> systemserver_compilable_jars_;
+
+  const time_t start_time_;
+
+ public:
+  explicit OnDeviceRefresh(const OdrConfig& config)
+      : config_{config},
+        cache_info_filename_{Concatenate({kOdrefreshArtifactDirectory, "/", kCacheInfoFile})},
+        start_time_{time(nullptr)} {
+    for (const std::string& jar : android::base::Split(config_.GetDex2oatBootClasspath(), ":")) {
+      // Boot class path extensions are those not in the ART APEX. Updatable APEXes should not
+      // have DEX files in the DEX2OATBOOTCLASSPATH. At the time of writing i18n is a non-updatable
+      // APEX and so does appear in the DEX2OATBOOTCLASSPATH.
+      if (!LocationIsOnArtModule(jar)) {
+        boot_extension_compilable_jars_.emplace_back(jar);
+      }
+    }
+
+    for (const std::string& jar : android::base::Split(config_.GetSystemServerClasspath(), ":")) {
+      // Only consider DEX files on the SYSTEMSERVERCLASSPATH for compilation that do not reside
+      // in APEX modules. Otherwise, we'll recompile on boot any time one of these APEXes updates.
+      if (!LocationIsOnApex(jar)) {
+        systemserver_compilable_jars_.emplace_back(jar);
+      }
+    }
+  }
+
+  time_t GetExecutionTimeUsed() const { return time(nullptr) - start_time_; }
+
+  time_t GetExecutionTimeRemaining() const {
+    return kMaximumExecutionSeconds - GetExecutionTimeUsed();
+  }
+
+  time_t GetSubprocessTimeout() const {
+    return std::max(GetExecutionTimeRemaining(), kMaxChildProcessSeconds);
+  }
+
+  // Gets the `ApexInfo` associated with the currently active ART APEX.
+  std::optional<apex::ApexInfo> GetArtApexInfo() const {
+    auto info_list = apex::readApexInfoList(config_.GetApexInfoListFile().c_str());
+    if (!info_list.has_value()) {
+      return {};
+    }
+
+    for (const apex::ApexInfo& info : info_list->getApexInfo()) {
+      if (info.getIsActive() && info.getModuleName() == "com.android.art") {
+        return info;
+      }
+    }
+    return {};
+  }
+
+  // Reads the ART APEX cache information (if any) found in `kOdrefreshArtifactDirectory`.
+  std::optional<art_apex::CacheInfo> ReadCacheInfo() {
+    return art_apex::read(cache_info_filename_.c_str());
+  }
+
+  // Write ART APEX cache information to `kOdrefreshArtifactDirectory`.
+  void WriteCacheInfo() const {
+    if (OS::FileExists(cache_info_filename_.c_str())) {
+      if (unlink(cache_info_filename_.c_str()) != 0) {
+        PLOG(ERROR) << "Failed to unlink() file " << QuotePath(cache_info_filename_);
+      }
+    }
+
+    const std::string dir_name = android::base::Dirname(cache_info_filename_);
+    if (!EnsureDirectoryExists(dir_name)) {
+      LOG(ERROR) << "Could not create directory: " << QuotePath(dir_name);
+      return;
+    }
+
+    std::optional<art_apex::ArtModuleInfo> art_module_info = GenerateArtModuleInfo();
+    if (!art_module_info.has_value()) {
+      LOG(ERROR) << "Unable to generate cache provenance";
+      return;
+    }
+
+    // There can be only one CacheProvence in the XML file, but `xsdc` does not have
+    // minOccurs/maxOccurs in the xsd schema.
+    const std::vector<art_apex::ArtModuleInfo> art_module_infos { art_module_info.value() };
+
+    std::optional<std::vector<art_apex::Component>> bcp_components =
+        GenerateBootExtensionComponents();
+    if (!bcp_components.has_value()) {
+      LOG(ERROR) << "No boot classpath extension components.";
+      return;
+    }
+
+    std::optional<std::vector<art_apex::Component>> system_server_components =
+        GenerateSystemServerComponents();
+    if (!system_server_components.has_value()) {
+      LOG(ERROR) << "No system_server extension components.";
+      return;
+    }
+
+    std::ofstream out(cache_info_filename_.c_str());
+    art_apex::CacheInfo info{art_module_infos,
+                             {{art_apex::Dex2oatBootClasspath{bcp_components.value()}}},
+                             {{art_apex::SystemServerClasspath{system_server_components.value()}}}};
+
+    art_apex::write(out, info);
+  }
+
+  // Returns cache provenance information based on the current ART APEX version and filesystem
+  // information.
+  std::optional<art_apex::ArtModuleInfo> GenerateArtModuleInfo() const {
+    auto info = GetArtApexInfo();
+    if (!info.has_value()) {
+      LOG(ERROR) << "Could not update " << QuotePath(cache_info_filename_) << " : no ART Apex info";
+      return {};
+    }
+    // The lastUpdateMillis is an addition to ApexInfoList.xsd to support samegrade installs.
+    int64_t last_update_millis = info->hasLastUpdateMillis() ? info->getLastUpdateMillis() : 0;
+    return art_apex::ArtModuleInfo{
+        info->getVersionCode(), info->getVersionName(), last_update_millis};
+  }
+
+  bool CheckComponents(const std::vector<art_apex::Component>& expected_components,
+                       const std::vector<art_apex::Component>& actual_components,
+                       std::string* error_msg) const {
+    if (expected_components.size() != actual_components.size()) {
+      return false;
+    }
+
+    for (size_t i = 0; i < expected_components.size(); ++i) {
+      const art_apex::Component& expected = expected_components[i];
+      const art_apex::Component& actual = actual_components[i];
+
+      if (expected.getFile() != actual.getFile()) {
+        *error_msg = android::base::StringPrintf("Component %zu file differs ('%s' != '%s')",
+                                                 i,
+                                                 expected.getFile().c_str(),
+                                                 actual.getFile().c_str());
+        return false;
+      }
+      if (expected.getSize() != actual.getSize()) {
+        *error_msg = android::base::StringPrintf("Component %zu size differs (%" PRIu64
+                                                 " != %" PRIu64 ")",
+                                                 i,
+                                                 expected.getSize(),
+                                                 actual.getSize());
+        return false;
+      }
+      if (expected.getChecksums() != actual.getChecksums()) {
+        *error_msg = android::base::StringPrintf("Component %zu checksums differ ('%s' != '%s')",
+                                                 i,
+                                                 expected.getChecksums().c_str(),
+                                                 actual.getChecksums().c_str());
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  std::vector<art_apex::Component> GenerateComponents(const std::vector<std::string>& jars) const {
+    std::vector<art_apex::Component> components;
+
+    ArtDexFileLoader loader;
+    for (const std::string& path : jars) {
+      struct stat sb;
+      if (stat(path.c_str(), &sb) == -1) {
+        PLOG(ERROR) << "Failed to get component: " << QuotePath(path);
+        return {};
+      }
+
+      std::vector<uint32_t> checksums;
+      std::vector<std::string> dex_locations;
+      std::string error_msg;
+      if (!loader.GetMultiDexChecksums(path.c_str(), &checksums, &dex_locations, &error_msg)) {
+        LOG(ERROR) << "Failed to get components: " << error_msg;
+        return {};
+      }
+
+      std::ostringstream oss;
+      for (size_t i = 0; i < checksums.size(); ++i) {
+        if (i != 0) {
+          oss << ';';
+        }
+        oss << android::base::StringPrintf("%08x", checksums[i]);
+      }
+      const std::string checksum = oss.str();
+
+      components.emplace_back(
+          art_apex::Component{path, static_cast<uint64_t>(sb.st_size), checksum});
+    }
+
+    return components;
+  }
+
+  std::vector<art_apex::Component> GenerateBootExtensionComponents() const {
+    return GenerateComponents(boot_extension_compilable_jars_);
+  }
+
+  std::vector<art_apex::Component> GenerateSystemServerComponents() const {
+    return GenerateComponents(systemserver_compilable_jars_);
+  }
+
+  // Checks whether a group of artifacts exists. Returns true if all are present, false otherwise.
+  static bool ArtifactsExist(const OdrArtifacts& artifacts, /*out*/ std::string* error_msg) {
+    const auto paths = {
+        artifacts.ImagePath().c_str(), artifacts.OatPath().c_str(), artifacts.VdexPath().c_str()};
+    for (const char* path : paths) {
+      if (!OS::FileExists(path)) {
+        if (errno == EACCES) {
+          PLOG(ERROR) << "Failed to stat() " << path;
+        }
+        *error_msg = "Missing file: " + QuotePath(path);
+        return false;
+      }
+    }
+    return true;
+  }
+
+  // Checks whether all boot extension artifacts are present on /data. Returns true if all are
+  // present, false otherwise.
+  WARN_UNUSED bool BootExtensionArtifactsExistOnData(const InstructionSet isa,
+                                                     /*out*/ std::string* error_msg) const {
+    const std::string apexdata_image_location = GetBootImageExtensionImagePath(isa);
+    const OdrArtifacts artifacts = OdrArtifacts::ForBootImageExtension(apexdata_image_location);
+    return ArtifactsExist(artifacts, error_msg);
+  }
+
+  // Checks whether all system_server artifacts are present on /data. The artifacts are checked in
+  // their order of compilation. Returns true if all are present, false otherwise.
+  WARN_UNUSED bool SystemServerArtifactsExistOnData(/*out*/ std::string* error_msg) const {
+    for (const std::string& jar_path : systemserver_compilable_jars_) {
+      const std::string image_location = GetSystemServerImagePath(/*on_system=*/false, jar_path);
+      const OdrArtifacts artifacts = OdrArtifacts::ForSystemServer(image_location);
+      if (!ArtifactsExist(artifacts, error_msg)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  WARN_UNUSED ExitCode CheckArtifactsAreUpToDate(OdrMetrics& metrics) {
+    metrics.SetStage(OdrMetrics::Stage::kCheck);
+
+    // Clean-up helper used to simplify clean-ups and handling failures there.
+    auto cleanup_return = [this](ExitCode exit_code) {
+      return CleanApexdataDirectory() ? exit_code : ExitCode::kCleanupFailed;
+    };
+
+    const auto apex_info = GetArtApexInfo();
+    if (!apex_info.has_value()) {
+      // This should never happen, further up-to-date checks are not possible if it does.
+      LOG(ERROR) << "Could not get ART APEX info.";
+      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
+      return cleanup_return(ExitCode::kCompilationRequired);
+    }
+
+    // Generate current module info for the current ART APEX.
+    const auto current_info = GenerateArtModuleInfo();
+    if (!current_info.has_value()) {
+      // This should never happen, further up-to-date checks are not possible if it does.
+      LOG(ERROR) << "Failed to generate cache provenance.";
+      metrics.SetTrigger(OdrMetrics::Trigger::kUnknown);
+      return cleanup_return(ExitCode::kCompilationRequired);
+    }
+
+    // Record ART APEX version for metrics reporting.
+    metrics.SetArtApexVersion(current_info->getVersionCode());
+
+    // Record ART APEX last update milliseconds (used in compilation log).
+    metrics.SetArtApexLastUpdateMillis(current_info->getLastUpdateMillis());
+
+    if (apex_info->getIsFactory()) {
+      // Remove any artifacts on /data as they are not necessary and no compilation is necessary.
+      LOG(INFO) << "Factory APEX mounted.";
+      return cleanup_return(ExitCode::kOkay);
+    }
+
+    if (!OS::FileExists(cache_info_filename_.c_str())) {
+      // If the cache info file does not exist, assume compilation is required because the
+      // file is missing and because the current ART APEX is not factory installed.
+      PLOG(ERROR) << "No prior cache-info file: " << QuotePath(cache_info_filename_);
+      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
+      return cleanup_return(ExitCode::kCompilationRequired);
+    }
+
+    // Get and parse the ART APEX cache info file.
+    std::optional<art_apex::CacheInfo> cache_info = ReadCacheInfo();
+    if (!cache_info.has_value()) {
+      // This should never happen, further up-to-date checks are not possible if it does.
+      PLOG(ERROR) << "Failed to read cache-info file: " << QuotePath(cache_info_filename_);
+      metrics.SetTrigger(OdrMetrics::Trigger::kUnknown);
+      return cleanup_return(ExitCode::kCompilationRequired);
+    }
+
+    // Check whether the current cache ART module info differs from the current ART module info.
+    // Always check APEX version.
+    const auto cached_info = cache_info->getFirstArtModuleInfo();
+
+    if (cached_info->getVersionCode() != current_info->getVersionCode()) {
+      LOG(INFO) << "ART APEX version code mismatch ("
+                << cached_info->getVersionCode()
+                << " != " << current_info->getVersionCode() << ").";
+      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
+      return cleanup_return(ExitCode::kCompilationRequired);
+    }
+
+    if (cached_info->getVersionName() != current_info->getVersionName()) {
+      LOG(INFO) << "ART APEX version name mismatch ("
+                << cached_info->getVersionName()
+                << " != " << current_info->getVersionName() << ").";
+      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
+      return cleanup_return(ExitCode::kCompilationRequired);
+    }
+
+    // Check lastUpdateMillis for samegrade installs. If `cached_info` is missing lastUpdateMillis
+    // then it is not current with the schema used by this binary so treat it as a samegrade
+    // update. Otherwise check whether the lastUpdateMillis changed.
+    if (!cached_info->hasLastUpdateMillis() ||
+        cached_info->getLastUpdateMillis() != current_info->getLastUpdateMillis()) {
+      LOG(INFO) << "ART APEX last update time mismatch ("
+                << cached_info->getLastUpdateMillis()
+                << " != " << current_info->getLastUpdateMillis() << ").";
+      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
+      return cleanup_return(ExitCode::kCompilationRequired);
+    }
+
+    // Check boot class components.
+    //
+    // This checks the size and checksums of odrefresh compilable files on the DEX2OATBOOTCLASSPATH
+    // (the Odrefresh constructor determines which files are compilable). If the number of files
+    // there changes, or their size or checksums change then compilation will be triggered.
+    //
+    // The boot class components may change unexpectedly, for example an OTA could update
+    // framework.jar.
+    const std::vector<art_apex::Component> expected_bcp_components =
+        GenerateBootExtensionComponents();
+    if (expected_bcp_components.size() != 0 &&
+        (!cache_info->hasDex2oatBootClasspath() ||
+         !cache_info->getFirstDex2oatBootClasspath()->hasComponent())) {
+      LOG(INFO) << "Missing Dex2oatBootClasspath components.";
+      metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
+      return cleanup_return(ExitCode::kCompilationRequired);
+    }
+
+    std::string error_msg;
+    const std::vector<art_apex::Component>& bcp_components =
+        cache_info->getFirstDex2oatBootClasspath()->getComponent();
+    if (!CheckComponents(expected_bcp_components, bcp_components, &error_msg)) {
+      LOG(INFO) << "Dex2OatClasspath components mismatch: " << error_msg;
+      metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
+      return cleanup_return(ExitCode::kCompilationRequired);
+    }
+
+    // Check system server components.
+    //
+    // This checks the size and checksums of odrefresh compilable files on the
+    // SYSTEMSERVERCLASSPATH (the Odrefresh constructor determines which files are compilable). If
+    // the number of files there changes, or their size or checksums change then compilation will be
+    // triggered.
+    //
+    // The system_server components may change unexpectedly, for example an OTA could update
+    // services.jar.
+    auto cleanup_system_server_return = [this](ExitCode exit_code) {
+      return RemoveSystemServerArtifactsFromData() ? exit_code : ExitCode::kCleanupFailed;
+    };
+
+    const std::vector<art_apex::Component> expected_system_server_components =
+        GenerateSystemServerComponents();
+    if (expected_system_server_components.size() != 0 &&
+        (!cache_info->hasSystemServerClasspath() ||
+         !cache_info->getFirstSystemServerClasspath()->hasComponent())) {
+      LOG(INFO) << "Missing SystemServerClasspath components.";
+      metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
+      return cleanup_system_server_return(ExitCode::kCompilationRequired);
+    }
+
+    const std::vector<art_apex::Component>& system_server_components =
+        cache_info->getFirstSystemServerClasspath()->getComponent();
+    if (!CheckComponents(expected_system_server_components, system_server_components, &error_msg)) {
+      LOG(INFO) << "SystemServerClasspath components mismatch: " << error_msg;
+      metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
+      return cleanup_system_server_return(ExitCode::kCompilationRequired);
+    }
+
+    // Cache info looks good, check all compilation artifacts exist.
+    auto cleanup_boot_extensions_return = [this](ExitCode exit_code, InstructionSet isa) {
+      return RemoveBootExtensionArtifactsFromData(isa) ? exit_code : ExitCode::kCleanupFailed;
+    };
+
+    for (const InstructionSet isa : config_.GetBootExtensionIsas()) {
+      if (!BootExtensionArtifactsExistOnData(isa, &error_msg)) {
+        LOG(INFO) << "Incomplete boot extension artifacts. " << error_msg;
+        metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
+        return cleanup_boot_extensions_return(ExitCode::kCompilationRequired, isa);
+      }
+    }
+
+    if (!SystemServerArtifactsExistOnData(&error_msg)) {
+      LOG(INFO) << "Incomplete system_server artifacts. " << error_msg;
+      // No clean-up is required here: we have boot extension artifacts. The method
+      // `SystemServerArtifactsExistOnData()` checks in compilation order so it is possible some of
+      // the artifacts are here. We likely ran out of space compiling the system_server artifacts.
+      // Any artifacts present are usable.
+      metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
+      return ExitCode::kCompilationRequired;
+    }
+
+    return ExitCode::kOkay;
+  }
+
+  static void AddDex2OatCommonOptions(/*inout*/ std::vector<std::string>* args) {
+    args->emplace_back("--android-root=out/empty");
+    args->emplace_back("--abort-on-hard-verifier-error");
+    args->emplace_back("--no-abort-on-soft-verifier-error");
+    args->emplace_back("--compilation-reason=boot");
+    args->emplace_back("--image-format=lz4");
+    args->emplace_back("--force-determinism");
+    args->emplace_back("--resolve-startup-const-strings=true");
+  }
+
+  static void AddDex2OatConcurrencyArguments(/*inout*/ std::vector<std::string>* args) {
+    static constexpr std::pair<const char*, const char*> kPropertyArgPairs[] = {
+        std::make_pair("dalvik.vm.boot-dex2oat-cpu-set", "--cpu-set="),
+        std::make_pair("dalvik.vm.boot-dex2oat-threads", "-j"),
+    };
+    for (auto property_arg_pair : kPropertyArgPairs) {
+      auto [property, arg] = property_arg_pair;
+      std::string value = android::base::GetProperty(property, {});
+      if (!value.empty()) {
+        args->push_back(arg + value);
+      }
+    }
+  }
+
+  static void AddDex2OatDebugInfo(/*inout*/ std::vector<std::string>* args) {
+    args->emplace_back("--generate-mini-debug-info");
+    args->emplace_back("--strip");
+  }
+
+  static void AddDex2OatInstructionSet(/*inout*/ std::vector<std::string>* args,
+                                       InstructionSet isa) {
+    const char* isa_str = GetInstructionSetString(isa);
+    args->emplace_back(Concatenate({"--instruction-set=", isa_str}));
+  }
+
+
+  static void AddDex2OatProfileAndCompilerFilter(/*inout*/ std::vector<std::string>* args,
+                                                 const std::string& profile_file) {
+    if (OS::FileExists(profile_file.c_str(), /*check_file_type=*/true)) {
+      args->emplace_back(Concatenate({"--profile-file=", profile_file}));
+      args->emplace_back("--compiler-filter=speed-profile");
+    } else {
+      args->emplace_back("--compiler-filter=speed");
+    }
+  }
+
+  WARN_UNUSED bool VerifySystemServerArtifactsAreUpToDate(bool on_system) const {
+    std::vector<std::string> classloader_context;
+    for (const std::string& jar_path : systemserver_compilable_jars_) {
+      std::vector<std::string> args;
+      args.emplace_back(config_.GetDexOptAnalyzer());
+      args.emplace_back("--dex-file=" + jar_path);
+
+      const std::string image_location = GetSystemServerImagePath(on_system, jar_path);
+
+      // odrefresh produces app-image files, but these are not guaranteed for those pre-installed
+      // on /system.
+      if (!on_system && !OS::FileExists(image_location.c_str(), true)) {
+        LOG(INFO) << "Missing image file: " << QuotePath(image_location);
+        return false;
+      }
+
+      // Generate set of artifacts that are output by compilation.
+      OdrArtifacts artifacts = OdrArtifacts::ForSystemServer(image_location);
+      if (!on_system) {
+        CHECK_EQ(artifacts.OatPath(),
+                 GetApexDataOdexFilename(jar_path, config_.GetSystemServerIsa()));
+        CHECK_EQ(artifacts.ImagePath(),
+                 GetApexDataDalvikCacheFilename(jar_path, config_.GetSystemServerIsa(), "art"));
+        CHECK_EQ(artifacts.OatPath(),
+                 GetApexDataDalvikCacheFilename(jar_path, config_.GetSystemServerIsa(), "odex"));
+        CHECK_EQ(artifacts.VdexPath(),
+                 GetApexDataDalvikCacheFilename(jar_path, config_.GetSystemServerIsa(), "vdex"));
+      }
+
+      // Associate inputs and outputs with dexoptanalyzer arguments.
+      std::pair<const std::string, const char*> location_args[] = {
+          std::make_pair(artifacts.OatPath(), "--oat-fd="),
+          std::make_pair(artifacts.VdexPath(), "--vdex-fd="),
+          std::make_pair(jar_path, "--zip-fd=")
+      };
+
+      // Open file descriptors for dexoptanalyzer file inputs and add to the command-line.
+      std::vector<std::unique_ptr<File>> files;
+      for (const auto& location_arg : location_args) {
+        auto& [location, arg] = location_arg;
+        std::unique_ptr<File> file(OS::OpenFileForReading(location.c_str()));
+        if (file == nullptr) {
+          PLOG(ERROR) << "Failed to open \"" << location << "\"";
+          return false;
+        }
+        args.emplace_back(android::base::StringPrintf("%s%d", arg, file->Fd()));
+        files.emplace_back(file.release());
+      }
+
+      const std::string basename(android::base::Basename(jar_path));
+      const std::string root = GetAndroidRoot();
+      const std::string profile_file = Concatenate({root, "/framework/", basename, ".prof"});
+      if (OS::FileExists(profile_file.c_str())) {
+        args.emplace_back("--compiler-filter=speed-profile");
+      } else {
+        args.emplace_back("--compiler-filter=speed");
+      }
+
+      args.emplace_back(
+          Concatenate({"--image=", GetBootImage(), ":", GetBootImageExtensionImage(on_system)}));
+      args.emplace_back(
+          Concatenate({"--isa=", GetInstructionSetString(config_.GetSystemServerIsa())}));
+      args.emplace_back("--runtime-arg");
+      args.emplace_back(Concatenate({"-Xbootclasspath:", config_.GetDex2oatBootClasspath()}));
+      args.emplace_back(Concatenate(
+          {"--class-loader-context=PCL[", android::base::Join(classloader_context, ':'), "]"}));
+
+      classloader_context.emplace_back(jar_path);
+
+      LOG(INFO) << "Checking " << jar_path << ": " << android::base::Join(args, ' ');
+      std::string error_msg;
+      bool timed_out = false;
+      const time_t timeout = GetSubprocessTimeout();
+      const int dexoptanalyzer_result = ExecAndReturnCode(args, timeout, &timed_out, &error_msg);
+      if (dexoptanalyzer_result == -1) {
+        LOG(ERROR) << "Unexpected exit from dexoptanalyzer: " << error_msg;
+        if (timed_out) {
+          // TODO(oth): record metric for timeout.
+        }
+        return false;
+      }
+      LOG(INFO) << "dexoptanalyzer returned " << dexoptanalyzer_result;
+
+      bool unexpected_result = true;
+      switch (static_cast<dexoptanalyzer::ReturnCode>(dexoptanalyzer_result)) {
+        case art::dexoptanalyzer::ReturnCode::kNoDexOptNeeded:
+          unexpected_result = false;
+          break;
+
+        // Recompile needed
+        case art::dexoptanalyzer::ReturnCode::kDex2OatFromScratch:
+        case art::dexoptanalyzer::ReturnCode::kDex2OatForBootImageOat:
+        case art::dexoptanalyzer::ReturnCode::kDex2OatForFilterOat:
+        case art::dexoptanalyzer::ReturnCode::kDex2OatForBootImageOdex:
+        case art::dexoptanalyzer::ReturnCode::kDex2OatForFilterOdex:
+          return false;
+
+        // Unexpected issues (note no default-case here to catch missing enum values, but the
+        // return code from dexoptanalyzer may also be outside expected values, such as a
+        // process crash.
+        case art::dexoptanalyzer::ReturnCode::kFlattenClassLoaderContextSuccess:
+        case art::dexoptanalyzer::ReturnCode::kErrorInvalidArguments:
+        case art::dexoptanalyzer::ReturnCode::kErrorCannotCreateRuntime:
+        case art::dexoptanalyzer::ReturnCode::kErrorUnknownDexOptNeeded:
+          break;
+      }
+
+      if (unexpected_result) {
+        LOG(ERROR) << "Unexpected result from dexoptanalyzer: " << dexoptanalyzer_result;
+        return false;
+      }
+    }
+    return true;
+  }
+
+  WARN_UNUSED bool RemoveSystemServerArtifactsFromData() const {
+    if (config_.GetDryRun()) {
+      LOG(INFO) << "Removal of system_server artifacts on /data skipped (dry-run).";
+      return true;
+    }
+
+    bool success = true;
+    for (const std::string& jar_path : systemserver_compilable_jars_) {
+      const std::string image_location =
+          GetSystemServerImagePath(/*on_system=*/false, jar_path);
+      const OdrArtifacts artifacts = OdrArtifacts::ForSystemServer(image_location);
+      LOG(INFO) << "Removing system_server artifacts on /data for " << QuotePath(jar_path);
+      success &= RemoveArtifacts(artifacts);
+    }
+    return success;
+  }
+
+  // Verify the validity of system server artifacts on both /system and /data.
+  // This method has the side-effect of removing system server artifacts on /data, if there are
+  // valid artifacts on /system, or if the artifacts on /data are not valid.
+  // Returns true if valid artifacts are found.
+  WARN_UNUSED bool VerifySystemServerArtifactsAreUpToDate() const {
+    bool system_ok = VerifySystemServerArtifactsAreUpToDate(/*on_system=*/true);
+    LOG(INFO) << "system_server artifacts on /system are " << (system_ok ? "ok" : "stale");
+    bool data_ok = VerifySystemServerArtifactsAreUpToDate(/*on_system=*/false);
+    LOG(INFO) << "system_server artifacts on /data are " << (data_ok ? "ok" : "stale");
+    return system_ok || data_ok;
+  }
+
+  // Check the validity of boot class path extension artifacts.
+  //
+  // Returns true if artifacts exist and are valid according to dexoptanalyzer.
+  WARN_UNUSED bool VerifyBootExtensionArtifactsAreUpToDate(const InstructionSet isa,
+                                                           bool on_system) const {
+    const std::string dex_file = boot_extension_compilable_jars_.front();
+    const std::string image_location = GetBootImageExtensionImage(on_system);
+
+    std::vector<std::string> args;
+    args.emplace_back(config_.GetDexOptAnalyzer());
+    args.emplace_back("--validate-bcp");
+    args.emplace_back(Concatenate({"--image=", GetBootImage(), ":", image_location}));
+    args.emplace_back(Concatenate({"--isa=", GetInstructionSetString(isa)}));
+    args.emplace_back("--runtime-arg");
+    args.emplace_back(Concatenate({"-Xbootclasspath:", config_.GetDex2oatBootClasspath()}));
+
+    LOG(INFO) << "Checking " << dex_file << ": " << android::base::Join(args, ' ');
+
+    std::string error_msg;
+    bool timed_out = false;
+    const time_t timeout = GetSubprocessTimeout();
+    const int dexoptanalyzer_result = ExecAndReturnCode(args, timeout, &timed_out, &error_msg);
+    if (dexoptanalyzer_result == -1) {
+      LOG(ERROR) << "Unexpected exit from dexoptanalyzer: " << error_msg;
+      if (timed_out) {
+        // TODO(oth): record metric for timeout.
+      }
+      return false;
+    }
+    auto rc = static_cast<dexoptanalyzer::ReturnCode>(dexoptanalyzer_result);
+    if (rc == dexoptanalyzer::ReturnCode::kNoDexOptNeeded) {
+      return true;
+    }
+    return false;
+  }
+
+  // Remove boot extension artifacts from /data.
+  WARN_UNUSED bool RemoveBootExtensionArtifactsFromData(InstructionSet isa) const {
+    if (config_.GetDryRun()) {
+      LOG(INFO) << "Removal of bcp extension artifacts on /data skipped (dry-run).";
+      return true;
+    }
+
+    bool success = true;
+    if (isa == config_.GetSystemServerIsa()) {
+      // system_server artifacts are invalid without boot extension artifacts.
+      success &= RemoveSystemServerArtifactsFromData();
+    }
+
+    const std::string apexdata_image_location = GetBootImageExtensionImagePath(isa);
+    LOG(INFO) << "Removing boot class path artifacts on /data for "
+              << QuotePath(apexdata_image_location);
+    success &= RemoveArtifacts(OdrArtifacts::ForBootImageExtension(apexdata_image_location));
+    return success;
+  }
+
+  // Verify whether boot extension artifacts for `isa` are valid on system partition or in apexdata.
+  // This method has the side-effect of removing boot classpath extension artifacts on /data,
+  // if there are valid artifacts on /system, or if the artifacts on /data are not valid.
+  // Returns true if valid boot externsion artifacts are valid.
+  WARN_UNUSED bool VerifyBootExtensionArtifactsAreUpToDate(InstructionSet isa) const {
+    bool system_ok = VerifyBootExtensionArtifactsAreUpToDate(isa, /*on_system=*/true);
+    LOG(INFO) << "Boot extension artifacts on /system are " << (system_ok ? "ok" : "stale");
+    bool data_ok = VerifyBootExtensionArtifactsAreUpToDate(isa, /*on_system=*/false);
+    LOG(INFO) << "Boot extension artifacts on /data are " << (data_ok ? "ok" : "stale");
+    return system_ok || data_ok;
+  }
+
+  // Verify all artifacts are up-to-date.
+  //
+  // This method checks artifacts can be loaded by the runtime.
+  //
+  // Returns ExitCode::kOkay if artifacts are up-to-date, ExitCode::kCompilationRequired otherwise.
+  //
+  // NB This is the main function used by the --check command-line option. When invoked with
+  // --compile, we only recompile the out-of-date artifacts, not all (see `Odrefresh::Compile`).
+  WARN_UNUSED ExitCode VerifyArtifactsAreUpToDate() {
+    ExitCode exit_code = ExitCode::kOkay;
+    for (const InstructionSet isa : config_.GetBootExtensionIsas()) {
+      if (!VerifyBootExtensionArtifactsAreUpToDate(isa)) {
+        if (!RemoveBootExtensionArtifactsFromData(isa)) {
+          return ExitCode::kCleanupFailed;
+        }
+        exit_code = ExitCode::kCompilationRequired;
+      }
+    }
+    if (!VerifySystemServerArtifactsAreUpToDate()) {
+      if (!RemoveSystemServerArtifactsFromData()) {
+        return ExitCode::kCleanupFailed;
+      }
+      exit_code = ExitCode::kCompilationRequired;
+    }
+    return exit_code;
+  }
+
+  WARN_UNUSED bool CleanApexdataDirectory() const {
+    const std::string& apex_data_path = GetArtApexData();
+    if (config_.GetDryRun()) {
+      LOG(INFO) << "Files under `" << QuotePath(apex_data_path) << " would be removed (dry-run).";
+      return true;
+    }
+    return CleanDirectory(apex_data_path);
+  }
+
+  WARN_UNUSED bool RemoveArtifacts(const OdrArtifacts& artifacts) const {
+    bool success = true;
+    for (const auto& location :
+         {artifacts.ImagePath(), artifacts.OatPath(), artifacts.VdexPath()}) {
+      if (config_.GetDryRun()) {
+        LOG(INFO) << "Removing " << QuotePath(location) << " (dry-run).";
+        continue;
+      }
+
+      if (OS::FileExists(location.c_str()) && unlink(location.c_str()) != 0) {
+        PLOG(ERROR) << "Failed to remove: " << QuotePath(location);
+        success = false;
+      }
+    }
+    return success;
+  }
+
+  static std::string GetBootImage() {
+    // Typically "/apex/com.android.art/javalib/boot.art".
+    return GetArtRoot() + "/javalib/boot.art";
+  }
+
+  std::string GetBootImageExtensionImage(bool on_system) const {
+    CHECK(!boot_extension_compilable_jars_.empty());
+    const std::string leading_jar = boot_extension_compilable_jars_[0];
+    if (on_system) {
+      const std::string jar_name = android::base::Basename(leading_jar);
+      const std::string image_name = ReplaceFileExtension(jar_name, "art");
+      // Typically "/system/framework/boot-framework.art".
+      return Concatenate({GetAndroidRoot(), "/framework/boot-", image_name});
+    } else {
+      // Typically "/data/misc/apexdata/com.android.art/dalvik-cache/boot-framework.art".
+      return GetApexDataBootImage(leading_jar);
+    }
+  }
+
+  std::string GetBootImageExtensionImagePath(const InstructionSet isa) const {
+    // Typically "/data/misc/apexdata/com.android.art/dalvik-cache/<isa>/boot-framework.art".
+    return GetSystemImageFilename(GetBootImageExtensionImage(/*on_system=*/false).c_str(), isa);
+  }
+
+  std::string GetSystemServerImagePath(bool on_system, const std::string& jar_path) const {
+    if (on_system) {
+      const std::string jar_name = android::base::Basename(jar_path);
+      const std::string image_name = ReplaceFileExtension(jar_name, "art");
+      const char* isa_str = GetInstructionSetString(config_.GetSystemServerIsa());
+      // Typically "/system/framework/oat/<isa>/services.art".
+      return Concatenate({GetAndroidRoot(), "/framework/oat/", isa_str, "/", image_name});
+    } else {
+      // Typically
+      // "/data/misc/apexdata/.../dalvik-cache/<isa>/system@framework@services.jar@classes.art".
+      const std::string image = GetApexDataImage(jar_path.c_str());
+      return GetSystemImageFilename(image.c_str(), config_.GetSystemServerIsa());
+    }
+  }
+
+  std::string GetStagingLocation(const std::string& staging_dir, const std::string& path) const {
+    return Concatenate({staging_dir, "/", android::base::Basename(path)});
+  }
+
+  WARN_UNUSED bool CompileBootExtensionArtifacts(const InstructionSet isa,
+                                                 const std::string& staging_dir,
+                                                 OdrMetrics& metrics,
+                                                 uint32_t* dex2oat_invocation_count,
+                                                 std::string* error_msg) const {
+    ScopedOdrCompilationTimer compilation_timer(metrics);
+    std::vector<std::string> args;
+    args.push_back(config_.GetDex2Oat());
+
+    AddDex2OatCommonOptions(&args);
+    AddDex2OatConcurrencyArguments(&args);
+    AddDex2OatDebugInfo(&args);
+    AddDex2OatInstructionSet(&args, isa);
+    const std::string boot_profile_file(GetAndroidRoot() + "/etc/boot-image.prof");
+    AddDex2OatProfileAndCompilerFilter(&args, boot_profile_file);
+
+    // Compile as a single image for fewer files and slightly less memory overhead.
+    args.emplace_back("--single-image");
+
+    // Set boot-image and expectation of compiling boot classpath extensions.
+    args.emplace_back("--boot-image=" + GetBootImage());
+
+    const std::string dirty_image_objects_file(GetAndroidRoot() + "/etc/dirty-image-objects");
+    if (OS::FileExists(dirty_image_objects_file.c_str())) {
+      args.emplace_back(Concatenate({"--dirty-image-objects=", dirty_image_objects_file}));
+    } else {
+      LOG(WARNING) << "Missing dirty objects file : " << QuotePath(dirty_image_objects_file);
+    }
+
+    // Add boot extensions to compile.
+    for (const std::string& component : boot_extension_compilable_jars_) {
+      args.emplace_back("--dex-file=" + component);
+    }
+
+    args.emplace_back("--runtime-arg");
+    args.emplace_back(Concatenate({"-Xbootclasspath:", config_.GetDex2oatBootClasspath()}));
+
+    const std::string image_location = GetBootImageExtensionImagePath(isa);
+    const OdrArtifacts artifacts = OdrArtifacts::ForBootImageExtension(image_location);
+    CHECK_EQ(GetApexDataOatFilename(boot_extension_compilable_jars_.front().c_str(), isa),
+             artifacts.OatPath());
+
+    args.emplace_back("--oat-location=" + artifacts.OatPath());
+    const std::pair<const std::string, const char*> location_kind_pairs[] = {
+        std::make_pair(artifacts.ImagePath(), "image"),
+        std::make_pair(artifacts.OatPath(), "oat"),
+        std::make_pair(artifacts.VdexPath(), "output-vdex")
+    };
+
+    std::vector<std::unique_ptr<File>> staging_files;
+    for (const auto& location_kind_pair : location_kind_pairs) {
+      auto& [location, kind] = location_kind_pair;
+      const std::string staging_location = GetStagingLocation(staging_dir, location);
+      std::unique_ptr<File> staging_file(OS::CreateEmptyFile(staging_location.c_str()));
+      if (staging_file == nullptr) {
+        PLOG(ERROR) << "Failed to create " << kind << " file: " << staging_location;
+        metrics.SetStatus(OdrMetrics::Status::kIoError);
+        EraseFiles(staging_files);
+        return false;
+      }
+
+      if (fchmod(staging_file->Fd(), S_IRUSR | S_IWUSR) != 0) {
+        PLOG(ERROR) << "Could not set file mode on " << QuotePath(staging_location);
+        metrics.SetStatus(OdrMetrics::Status::kIoError);
+        EraseFiles(staging_files);
+        return false;
+      }
+
+      args.emplace_back(android::base::StringPrintf("--%s-fd=%d", kind, staging_file->Fd()));
+      staging_files.emplace_back(std::move(staging_file));
+    }
+
+    const std::string install_location = android::base::Dirname(image_location);
+    if (!EnsureDirectoryExists(install_location)) {
+      metrics.SetStatus(OdrMetrics::Status::kIoError);
+      return false;
+    }
+
+    const time_t timeout = GetSubprocessTimeout();
+    const std::string cmd_line = android::base::Join(args, ' ');
+    LOG(INFO) << "Compiling boot extensions (" << isa << "): " << cmd_line
+              << " [timeout " << timeout << "s]";
+    if (config_.GetDryRun()) {
+      LOG(INFO) << "Compilation skipped (dry-run).";
+      return true;
+    }
+
+    bool timed_out = false;
+    int dex2oat_exit_code = ExecAndReturnCode(args, timeout, &timed_out, error_msg);
+    if (dex2oat_exit_code != 0) {
+      if (timed_out) {
+        metrics.SetStatus(OdrMetrics::Status::kTimeLimitExceeded);
+      } else {
+        metrics.SetStatus(OdrMetrics::Status::kDex2OatError);
+      }
+      EraseFiles(staging_files);
+      return false;
+    }
+
+    if (!MoveOrEraseFiles(staging_files, install_location)) {
+      metrics.SetStatus(OdrMetrics::Status::kInstallFailed);
+      return false;
+    }
+
+    *dex2oat_invocation_count = *dex2oat_invocation_count + 1;
+    ReportNextBootAnimationProgress(*dex2oat_invocation_count);
+
+    return true;
+  }
+
+  WARN_UNUSED bool CompileSystemServerArtifacts(const std::string& staging_dir,
+                                                OdrMetrics& metrics,
+                                                uint32_t* dex2oat_invocation_count,
+                                                std::string* error_msg) const {
+    ScopedOdrCompilationTimer compilation_timer(metrics);
+    std::vector<std::string> classloader_context;
+
+    const std::string dex2oat = config_.GetDex2Oat();
+    const InstructionSet isa = config_.GetSystemServerIsa();
+    for (const std::string& jar : systemserver_compilable_jars_) {
+      std::vector<std::string> args;
+      args.emplace_back(dex2oat);
+      args.emplace_back("--dex-file=" + jar);
+
+      AddDex2OatCommonOptions(&args);
+      AddDex2OatConcurrencyArguments(&args);
+      AddDex2OatDebugInfo(&args);
+      AddDex2OatInstructionSet(&args, isa);
+      const std::string jar_name(android::base::Basename(jar));
+      const std::string profile = Concatenate({GetAndroidRoot(), "/framework/", jar_name, ".prof"});
+      std::string compiler_filter =
+          android::base::GetProperty("dalvik.vm.systemservercompilerfilter", "speed");
+      if (compiler_filter == "speed-profile") {
+        AddDex2OatProfileAndCompilerFilter(&args, profile);
+      } else {
+        args.emplace_back("--compiler-filter=" + compiler_filter);
+      }
+
+      const std::string image_location = GetSystemServerImagePath(/*on_system=*/false, jar);
+      const std::string install_location = android::base::Dirname(image_location);
+      if (classloader_context.empty()) {
+        // All images are in the same directory, we only need to check on the first iteration.
+        if (!EnsureDirectoryExists(install_location)) {
+          metrics.SetStatus(OdrMetrics::Status::kIoError);
+          return false;
+        }
+      }
+
+      OdrArtifacts artifacts = OdrArtifacts::ForSystemServer(image_location);
+      CHECK_EQ(artifacts.OatPath(), GetApexDataOdexFilename(jar.c_str(), isa));
+
+      const std::pair<const std::string, const char*> location_kind_pairs[] = {
+          std::make_pair(artifacts.ImagePath(), "app-image"),
+          std::make_pair(artifacts.OatPath(), "oat"),
+          std::make_pair(artifacts.VdexPath(), "output-vdex")
+      };
+
+      std::vector<std::unique_ptr<File>> staging_files;
+      for (const auto& location_kind_pair : location_kind_pairs) {
+        auto& [location, kind] = location_kind_pair;
+        const std::string staging_location = GetStagingLocation(staging_dir, location);
+        std::unique_ptr<File> staging_file(OS::CreateEmptyFile(staging_location.c_str()));
+        if (staging_file == nullptr) {
+          PLOG(ERROR) << "Failed to create " << kind << " file: " << staging_location;
+          metrics.SetStatus(OdrMetrics::Status::kIoError);
+          EraseFiles(staging_files);
+          return false;
+        }
+        args.emplace_back(android::base::StringPrintf("--%s-fd=%d", kind, staging_file->Fd()));
+        staging_files.emplace_back(std::move(staging_file));
+      }
+      args.emplace_back("--oat-location=" + artifacts.OatPath());
+
+      if (!config_.GetUpdatableBcpPackagesFile().empty()) {
+        const std::string& bcp_packages = config_.GetUpdatableBcpPackagesFile();
+        if (!OS::FileExists(bcp_packages.c_str())) {
+          *error_msg = "Cannot compile system_server JARs: missing " + QuotePath(bcp_packages);
+          metrics.SetStatus(OdrMetrics::Status::kIoError);
+          EraseFiles(staging_files);
+          return false;
+        }
+        args.emplace_back("--updatable-bcp-packages-file=" + bcp_packages);
+      }
+
+      args.emplace_back("--runtime-arg");
+      args.emplace_back(Concatenate({"-Xbootclasspath:", config_.GetDex2oatBootClasspath()}));
+      const std::string context_path = android::base::Join(classloader_context, ':');
+      args.emplace_back(Concatenate({"--class-loader-context=PCL[", context_path, "]"}));
+      const std::string extension_image = GetBootImageExtensionImage(/*on_system=*/false);
+      args.emplace_back(Concatenate({"--boot-image=", GetBootImage(), ":", extension_image}));
+
+      const time_t timeout = GetSubprocessTimeout();
+      const std::string cmd_line = android::base::Join(args, ' ');
+      LOG(INFO) << "Compiling " << jar << ": " << cmd_line << " [timeout " << timeout << "s]";
+      if (config_.GetDryRun()) {
+        LOG(INFO) << "Compilation skipped (dry-run).";
+        return true;
+      }
+
+      bool timed_out = false;
+      int dex2oat_exit_code = ExecAndReturnCode(args, timeout, &timed_out, error_msg);
+      if (dex2oat_exit_code != 0) {
+        if (timed_out) {
+          metrics.SetStatus(OdrMetrics::Status::kTimeLimitExceeded);
+        } else {
+          metrics.SetStatus(OdrMetrics::Status::kDex2OatError);
+        }
+        EraseFiles(staging_files);
+        return false;
+      }
+
+      if (!MoveOrEraseFiles(staging_files, install_location)) {
+        metrics.SetStatus(OdrMetrics::Status::kInstallFailed);
+        return false;
+      }
+
+      *dex2oat_invocation_count = *dex2oat_invocation_count + 1;
+      ReportNextBootAnimationProgress(*dex2oat_invocation_count);
+      classloader_context.emplace_back(jar);
+    }
+
+    return true;
+  }
+
+  void ReportNextBootAnimationProgress(uint32_t current_compilation) const {
+    uint32_t number_of_compilations =
+        config_.GetBootExtensionIsas().size() + systemserver_compilable_jars_.size();
+    // We arbitrarily show progress until 90%, expecting that our compilations
+    // take a large chunk of boot time.
+    uint32_t value = (90 * current_compilation) / number_of_compilations;
+    android::base::SetProperty("service.bootanim.progress", std::to_string(value));
+  }
+
+  WARN_UNUSED bool CheckCompilationSpace() const {
+    // Check the available storage space against an arbitrary threshold because dex2oat does not
+    // report when it runs out of storage space and we do not want to completely fill
+    // the users data partition.
+    //
+    // We do not have a good way of pre-computing the required space for a compilation step, but
+    // typically observe 16MB as the largest size of an AOT artifact. Since there are three
+    // AOT artifacts per compilation step - an image file, executable file, and a verification
+    // data file - the threshold is three times 16MB.
+    static constexpr uint64_t kMinimumSpaceForCompilation = 3 * 16 * 1024 * 1024;
+
+    uint64_t bytes_available;
+    const std::string& art_apex_data_path = GetArtApexData();
+    if (!GetFreeSpace(art_apex_data_path, &bytes_available)) {
+      return false;
+    }
+
+    if (bytes_available < kMinimumSpaceForCompilation) {
+      LOG(WARNING) << "Low space for " << QuotePath(art_apex_data_path) << " (" << bytes_available
+                   << " bytes)";
+      return false;
+    }
+
+    return true;
+  }
+
+  WARN_UNUSED ExitCode Compile(OdrMetrics& metrics, bool force_compile) const {
+    const char* staging_dir = nullptr;
+    metrics.SetStage(OdrMetrics::Stage::kPreparation);
+    // Clean-up existing files.
+    if (force_compile && !CleanApexdataDirectory()) {
+      metrics.SetStatus(OdrMetrics::Status::kIoError);
+      return ExitCode::kCleanupFailed;
+    }
+
+    // Create staging area and assign label for generating compilation artifacts.
+    if (PaletteCreateOdrefreshStagingDirectory(&staging_dir) != PALETTE_STATUS_OK) {
+      metrics.SetStatus(OdrMetrics::Status::kStagingFailed);
+      return ExitCode::kCleanupFailed;
+    }
+
+    // Emit cache info before compiling. This can be used to throttle compilation attempts later.
+    WriteCacheInfo();
+
+    std::string error_msg;
+
+    uint32_t dex2oat_invocation_count = 0;
+    ReportNextBootAnimationProgress(dex2oat_invocation_count);
+
+    const auto& bcp_instruction_sets = config_.GetBootExtensionIsas();
+    DCHECK(!bcp_instruction_sets.empty() && bcp_instruction_sets.size() <= 2);
+    for (const InstructionSet isa : bcp_instruction_sets) {
+      auto stage = (isa == bcp_instruction_sets.front()) ?
+                       OdrMetrics::Stage::kPrimaryBootClasspath :
+                       OdrMetrics::Stage::kSecondaryBootClasspath;
+      metrics.SetStage(stage);
+      if (force_compile || !BootExtensionArtifactsExistOnData(isa, &error_msg)) {
+        // Remove artifacts we are about to generate. Ordinarily these are removed in the checking
+        // step, but this is not always run (e.g. during manual testing).
+        if (!RemoveBootExtensionArtifactsFromData(isa)) {
+            return ExitCode::kCleanupFailed;
+        }
+
+        if (!CheckCompilationSpace()) {
+          metrics.SetStatus(OdrMetrics::Status::kNoSpace);
+          // Return kOkay so odsign will keep and sign whatever we have been able to compile.
+          return ExitCode::kOkay;
+        }
+
+        if (!CompileBootExtensionArtifacts(
+                isa, staging_dir, metrics, &dex2oat_invocation_count, &error_msg)) {
+          LOG(ERROR) << "Compilation of BCP failed: " << error_msg;
+          if (!config_.GetDryRun() && !CleanDirectory(staging_dir)) {
+            return ExitCode::kCleanupFailed;
+          }
+          return ExitCode::kCompilationFailed;
+        }
+      }
+    }
+
+    if (force_compile || !SystemServerArtifactsExistOnData(&error_msg)) {
+      metrics.SetStage(OdrMetrics::Stage::kSystemServerClasspath);
+
+      if (!CheckCompilationSpace()) {
+        metrics.SetStatus(OdrMetrics::Status::kNoSpace);
+        // Return kOkay so odsign will keep and sign whatever we have been able to compile.
+        return ExitCode::kOkay;
+      }
+
+      if (!CompileSystemServerArtifacts(
+              staging_dir, metrics, &dex2oat_invocation_count, &error_msg)) {
+        LOG(ERROR) << "Compilation of system_server failed: " << error_msg;
+        if (!config_.GetDryRun() && !CleanDirectory(staging_dir)) {
+          return ExitCode::kCleanupFailed;
+        }
+        return ExitCode::kCompilationFailed;
+      }
+    }
+
+    metrics.SetStage(OdrMetrics::Stage::kComplete);
+    return ExitCode::kCompilationSuccess;
+  }
+
+  static bool ArgumentMatches(std::string_view argument,
+                              std::string_view prefix,
+                              std::string* value) {
+    if (StartsWith(argument, prefix)) {
+      *value = std::string(argument.substr(prefix.size()));
+      return true;
+    }
+    return false;
+  }
+
+  static bool ArgumentEquals(std::string_view argument, std::string_view expected) {
+    return argument == expected;
+  }
+
+  static bool InitializeCommonConfig(std::string_view argument, OdrConfig* config) {
+    static constexpr std::string_view kDryRunArgument{"--dry-run"};
+    if (ArgumentEquals(argument, kDryRunArgument)) {
+      config->SetDryRun();
+      return true;
+    }
+    return false;
+  }
+
+  static int InitializeHostConfig(int argc, const char** argv, OdrConfig* config) {
+    __android_log_set_logger(__android_log_stderr_logger);
+
+    std::string current_binary;
+    if (argv[0][0] == '/') {
+      current_binary = argv[0];
+    } else {
+      std::vector<char> buf(PATH_MAX);
+      if (getcwd(buf.data(), buf.size()) == nullptr) {
+        PLOG(FATAL) << "Failed getwd()";
+      }
+      current_binary = Concatenate({buf.data(), "/", argv[0]});
+    }
+    config->SetArtBinDir(android::base::Dirname(current_binary));
+
+    int n = 1;
+    for (; n < argc - 1; ++n) {
+      const char* arg = argv[n];
+      std::string value;
+      if (ArgumentMatches(arg, "--android-root=", &value)) {
+        setenv("ANDROID_ROOT", value.c_str(), 1);
+      } else if (ArgumentMatches(arg, "--android-art-root=", &value)) {
+        setenv("ANDROID_ART_ROOT", value.c_str(), 1);
+      } else if (ArgumentMatches(arg, "--apex-info-list=", &value)) {
+        config->SetApexInfoListFile(value);
+      } else if (ArgumentMatches(arg, "--art-apex-data=", &value)) {
+        setenv("ART_APEX_DATA", value.c_str(), 1);
+      } else if (ArgumentMatches(arg, "--dex2oat-bootclasspath=", &value)) {
+        config->SetDex2oatBootclasspath(value);
+      } else if (ArgumentMatches(arg, "--isa=", &value)) {
+        config->SetIsa(GetInstructionSetFromString(value.c_str()));
+      } else if (ArgumentMatches(arg, "--system-server-classpath=", &value)) {
+        config->SetSystemServerClasspath(arg);
+      } else if (ArgumentMatches(arg, "--updatable-bcp-packages-file=", &value)) {
+        config->SetUpdatableBcpPackagesFile(value);
+      } else if (ArgumentMatches(arg, "--zygote-arch=", &value)) {
+        ZygoteKind zygote_kind;
+        if (!ParseZygoteKind(value.c_str(), &zygote_kind)) {
+          ArgumentError("Unrecognized zygote kind: '%s'", value.c_str());
+        }
+        config->SetZygoteKind(zygote_kind);
+      } else if (!InitializeCommonConfig(arg, config)) {
+        UsageError("Unrecognized argument: '%s'", arg);
+      }
+    }
+    return n;
+  }
+
+  static int InitializeTargetConfig(int argc, const char** argv, OdrConfig* config) {
+    config->SetApexInfoListFile("/apex/apex-info-list.xml");
+    config->SetArtBinDir(GetArtBinDir());
+    config->SetDex2oatBootclasspath(GetEnvironmentVariableOrDie("DEX2OATBOOTCLASSPATH"));
+    config->SetSystemServerClasspath(GetEnvironmentVariableOrDie("SYSTEMSERVERCLASSPATH"));
+    config->SetIsa(kRuntimeISA);
+
+    const std::string zygote = android::base::GetProperty("ro.zygote", {});
+    ZygoteKind zygote_kind;
+    if (!ParseZygoteKind(zygote.c_str(), &zygote_kind)) {
+      LOG(FATAL) << "Unknown zygote: " << QuotePath(zygote);
+    }
+    config->SetZygoteKind(zygote_kind);
+
+    const std::string updatable_packages =
+        android::base::GetProperty("dalvik.vm.dex2oat-updatable-bcp-packages-file", {});
+    config->SetUpdatableBcpPackagesFile(updatable_packages);
+
+    int n = 1;
+    for (; n < argc - 1; ++n) {
+      if (!InitializeCommonConfig(argv[n], config)) {
+        UsageError("Unrecognized argument: '%s'", argv[n]);
+      }
+    }
+    return n;
+  }
+
+  static int InitializeConfig(int argc, const char** argv, OdrConfig* config) {
+    if (kIsTargetBuild) {
+      return InitializeTargetConfig(argc, argv, config);
+    } else {
+      return InitializeHostConfig(argc, argv, config);
+    }
+  }
+
+  static int main(int argc, const char** argv) {
+    OdrConfig config(argv[0]);
+    int n = InitializeConfig(argc, argv, &config);
+    argv += n;
+    argc -= n;
+    if (argc != 1) {
+      UsageError("Expected 1 argument, but have %d.", argc);
+    }
+
+    OdrMetrics metrics(kOdrefreshArtifactDirectory);
+    OnDeviceRefresh odr(config);
+    for (int i = 0; i < argc; ++i) {
+      std::string_view action(argv[i]);
+      if (action == "--check") {
+        // Fast determination of whether artifacts are up to date.
+        return odr.CheckArtifactsAreUpToDate(metrics);
+      } else if (action == "--compile") {
+        const ExitCode exit_code = odr.CheckArtifactsAreUpToDate(metrics);
+        if (exit_code != ExitCode::kCompilationRequired) {
+          return exit_code;
+        }
+        OdrCompilationLog compilation_log;
+        if (!compilation_log.ShouldAttemptCompile(metrics.GetArtApexVersion(),
+                                                  metrics.GetArtApexLastUpdateMillis(),
+                                                  metrics.GetTrigger())) {
+          return ExitCode::kOkay;
+        }
+        ExitCode compile_result = odr.Compile(metrics, /*force_compile=*/false);
+        compilation_log.Log(metrics.GetArtApexVersion(),
+                            metrics.GetArtApexLastUpdateMillis(),
+                            metrics.GetTrigger(),
+                            compile_result);
+        return compile_result;
+      } else if (action == "--force-compile") {
+        return odr.Compile(metrics, /*force_compile=*/true);
+      } else if (action == "--verify") {
+        // Slow determination of whether artifacts are up to date. These are too slow for checking
+        // during boot (b/181689036).
+        return odr.VerifyArtifactsAreUpToDate();
+      } else if (action == "--help") {
+        UsageHelp(argv[0]);
+      } else {
+        UsageError("Unknown argument: ", argv[i]);
+      }
+    }
+    return ExitCode::kOkay;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(OnDeviceRefresh);
+};
+
+}  // namespace odrefresh
+}  // namespace art
+
+int main(int argc, const char** argv) {
+  // odrefresh is launched by `init` which sets the umask of forked processed to
+  // 077 (S_IRWXG | S_IRWXO). This blocks the ability to make files and directories readable
+  // by others and prevents system_server from loading generated artifacts.
+  umask(S_IWGRP | S_IWOTH);
+  return art::odrefresh::OnDeviceRefresh::main(argc, argv);
+}
diff --git a/odrefresh/odrefresh_test.cc b/odrefresh/odrefresh_test.cc
new file mode 100644
index 0000000..a09accb
--- /dev/null
+++ b/odrefresh/odrefresh_test.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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 "odrefresh/odrefresh.h"
+
+#include "base/common_art_test.h"
+#include "base/file_utils.h"
+
+namespace art {
+namespace odrefresh {
+
+TEST(OdRefreshTest, OdrefreshArtifactDirectory) {
+    // odrefresh.h defines kOdrefreshArtifactDirectory for external callers of odrefresh. This is
+    // where compilation artifacts end up.
+    ScopedUnsetEnvironmentVariable no_env("ART_APEX_DATA");
+    EXPECT_EQ(kOdrefreshArtifactDirectory, GetArtApexData() + "/dalvik-cache");
+}
+
+}  // namespace odrefresh
+}  // namespace art
diff --git a/odrefresh/schema/current.txt b/odrefresh/schema/current.txt
new file mode 100644
index 0000000..e6933f6
--- /dev/null
+++ b/odrefresh/schema/current.txt
@@ -0,0 +1,60 @@
+// Signature format: 2.0
+package com.android.art {
+
+  public class ArtModuleInfo {
+    ctor public ArtModuleInfo();
+    method public long getLastUpdateMillis();
+    method public long getVersionCode();
+    method public String getVersionName();
+    method public void setLastUpdateMillis(long);
+    method public void setVersionCode(long);
+    method public void setVersionName(String);
+  }
+
+  public class CacheInfo {
+    ctor public CacheInfo();
+    method public com.android.art.ArtModuleInfo getArtModuleInfo();
+    method public com.android.art.Dex2oatBootClasspath getDex2oatBootClasspath();
+    method public com.android.art.SystemServerClasspath getSystemServerClasspath();
+    method public void setArtModuleInfo(com.android.art.ArtModuleInfo);
+    method public void setDex2oatBootClasspath(com.android.art.Dex2oatBootClasspath);
+    method public void setSystemServerClasspath(com.android.art.SystemServerClasspath);
+  }
+
+  public class Component {
+    ctor public Component();
+    method public String getChecksums();
+    method public String getFile();
+    method public java.math.BigInteger getSize();
+    method public void setChecksums(String);
+    method public void setFile(String);
+    method public void setSize(java.math.BigInteger);
+  }
+
+  public class Dex2oatBootClasspath {
+    ctor public Dex2oatBootClasspath();
+    method public com.android.art.Component getComponent();
+    method public void setComponent(com.android.art.Component);
+  }
+
+  public class SystemServerClasspath {
+    ctor public SystemServerClasspath();
+    method public com.android.art.Component getComponent();
+    method public void setComponent(com.android.art.Component);
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method public static com.android.art.CacheInfo read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+  public class XmlWriter implements java.io.Closeable {
+    ctor public XmlWriter(java.io.PrintWriter);
+    method public void close();
+    method public static void write(com.android.art.XmlWriter, com.android.art.CacheInfo) throws java.io.IOException;
+  }
+
+}
+
diff --git a/test/559-bce-ssa/expected.txt b/odrefresh/schema/last_current.txt
similarity index 100%
copy from test/559-bce-ssa/expected.txt
copy to odrefresh/schema/last_current.txt
diff --git a/test/559-bce-ssa/expected.txt b/odrefresh/schema/last_removed.txt
similarity index 100%
copy from test/559-bce-ssa/expected.txt
copy to odrefresh/schema/last_removed.txt
diff --git a/odrefresh/schema/removed.txt b/odrefresh/schema/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/odrefresh/schema/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/openjdkjvm/Android.bp b/openjdkjvm/Android.bp
index ace8d0b..99ab9e3 100644
--- a/openjdkjvm/Android.bp
+++ b/openjdkjvm/Android.bp
@@ -13,6 +13,36 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["art_openjdkjvm_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "art_openjdkjvm_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-GPL-2.0",
+        "SPDX-license-identifier-GPL-with-classpath-exception",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_defaults {
     name: "libopenjdkjvm_defaults",
     defaults: ["art_defaults"],
@@ -35,7 +65,7 @@
         "libartbase",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
diff --git a/openjdkjvm/OpenjdkJvm.cc b/openjdkjvm/OpenjdkJvm.cc
index 675a401..d64086d 100644
--- a/openjdkjvm/OpenjdkJvm.cc
+++ b/openjdkjvm/OpenjdkJvm.cc
@@ -45,6 +45,7 @@
 #include "../../libcore/ojluni/src/main/native/jvm.h"  // TODO(narayan): fix it
 
 #include "base/macros.h"
+#include "base/fast_exit.h"
 #include "common_throws.h"
 #include "gc/heap.h"
 #include "handle_scope-inl.h"
@@ -315,7 +316,7 @@
   art::Runtime::Current()->CallExitHook(status);
   // Unsafe to call exit() while threads may still be running. They would race
   // with static destructors.
-  _exit(status);
+  art::FastExit(status);
 }
 
 JNIEXPORT jstring JVM_NativeLoad(JNIEnv* env,
diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp
index 3311afc..841a964 100644
--- a/openjdkjvmti/Android.bp
+++ b/openjdkjvmti/Android.bp
@@ -13,18 +13,52 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["art_openjdkjvmti_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "art_openjdkjvmti_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-GPL-2.0",
+        "SPDX-license-identifier-GPL-with-classpath-exception",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_headers {
     name: "libopenjdkjvmti_headers",
     visibility: ["//visibility:public"],
+    header_libs: ["jni_headers"],
     host_supported: true,
+    export_header_lib_headers: ["jni_headers"],
     export_include_dirs: ["include"],
     sdk_version: "current",
 
     apex_available: [
         "//apex_available:platform",
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
     ],
+    min_sdk_version: "S",
 }
 
 cc_defaults {
@@ -64,6 +98,7 @@
         "transform.cc",
     ],
     header_libs: [
+        "art_cmdlineparser_headers",
         "libnativehelper_header_only",
         "libopenjdkjvmti_headers",
     ],
@@ -83,7 +118,7 @@
         "libartbase",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
diff --git a/openjdkjvmti/OpenjdkJvmTi.cc b/openjdkjvmti/OpenjdkJvmTi.cc
index 4ce376f..09900e1 100644
--- a/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/openjdkjvmti/OpenjdkJvmTi.cc
@@ -1376,60 +1376,7 @@
                                    jvmtiVerboseFlag flag,
                                    jboolean value) {
     ENSURE_VALID_ENV(env);
-    if (flag == jvmtiVerboseFlag::JVMTI_VERBOSE_OTHER) {
-      // OTHER is special, as it's 0, so can't do a bit check.
-      bool val = (value == JNI_TRUE) ? true : false;
-
-      art::gLogVerbosity.collector = val;
-      art::gLogVerbosity.compiler = val;
-      art::gLogVerbosity.deopt = val;
-      art::gLogVerbosity.heap = val;
-      art::gLogVerbosity.interpreter = val;
-      art::gLogVerbosity.jdwp = val;
-      art::gLogVerbosity.jit = val;
-      art::gLogVerbosity.monitor = val;
-      art::gLogVerbosity.oat = val;
-      art::gLogVerbosity.profiler = val;
-      art::gLogVerbosity.signals = val;
-      art::gLogVerbosity.simulator = val;
-      art::gLogVerbosity.startup = val;
-      art::gLogVerbosity.third_party_jni = val;
-      art::gLogVerbosity.threads = val;
-      art::gLogVerbosity.verifier = val;
-      // Do not set verifier-debug.
-      art::gLogVerbosity.image = val;
-      art::gLogVerbosity.plugin = val;
-
-      // Note: can't switch systrace_lock_logging. That requires changing entrypoints.
-
-      art::gLogVerbosity.agents = val;
-    } else {
-      // Spec isn't clear whether "flag" is a mask or supposed to be single. We implement the mask
-      // semantics.
-      constexpr std::underlying_type<jvmtiVerboseFlag>::type kMask =
-          jvmtiVerboseFlag::JVMTI_VERBOSE_GC |
-          jvmtiVerboseFlag::JVMTI_VERBOSE_CLASS |
-          jvmtiVerboseFlag::JVMTI_VERBOSE_JNI;
-      if ((flag & ~kMask) != 0) {
-        return ERR(ILLEGAL_ARGUMENT);
-      }
-
-      bool val = (value == JNI_TRUE) ? true : false;
-
-      if ((flag & jvmtiVerboseFlag::JVMTI_VERBOSE_GC) != 0) {
-        art::gLogVerbosity.gc = val;
-      }
-
-      if ((flag & jvmtiVerboseFlag::JVMTI_VERBOSE_CLASS) != 0) {
-        art::gLogVerbosity.class_linker = val;
-      }
-
-      if ((flag & jvmtiVerboseFlag::JVMTI_VERBOSE_JNI) != 0) {
-        art::gLogVerbosity.jni = val;
-      }
-    }
-
-    return ERR(NONE);
+    return LogUtil::SetVerboseFlag(env, flag, value);
   }
 
   static jvmtiError GetJLocationFormat(jvmtiEnv* env, jvmtiJlocationFormat* format_ptr) {
@@ -1491,6 +1438,13 @@
     return JNI_OK;
   } else {
     printf("version 0x%x is not valid!", version);
+    if (IsJvmtiVersion(version)) {
+      LOG(ERROR) << "JVMTI Version 0x" << std::hex << version << " requested but the runtime is not"
+                 << " debuggable! Only limited, best effort kArtTiVersion"
+                 << " (0x" << std::hex << kArtTiVersion << ") environments are available. If"
+                 << " possible, rebuild your apk in debuggable mode or start the runtime with"
+                 << " the `-Xcompiler-option --debuggable` flags.";
+    }
     return JNI_EVERSION;
   }
 }
diff --git a/openjdkjvmti/deopt_manager.cc b/openjdkjvmti/deopt_manager.cc
index 3e3691a..bf1b4f0 100644
--- a/openjdkjvmti/deopt_manager.cc
+++ b/openjdkjvmti/deopt_manager.cc
@@ -421,13 +421,13 @@
   if (target->IncrementForceInterpreterCount() == 1) {
     struct DeoptClosure : public art::Closure {
      public:
-      explicit DeoptClosure(DeoptManager* man) : man_(man) {}
+      explicit DeoptClosure(DeoptManager* manager) : manager_(manager) {}
       void Run(art::Thread* self) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
-        man_->DeoptimizeThread(self);
+        manager_->DeoptimizeThread(self);
       }
 
      private:
-      DeoptManager* man_;
+      DeoptManager* manager_;
     };
     DeoptClosure c(this);
     target->RequestSynchronousCheckpoint(&c);
diff --git a/openjdkjvmti/events-inl.h b/openjdkjvmti/events-inl.h
index 883a4cc..92cfbc9 100644
--- a/openjdkjvmti/events-inl.h
+++ b/openjdkjvmti/events-inl.h
@@ -49,10 +49,10 @@
 
 namespace impl {
 
-// Helper for ensuring that the dispatch environment is sane. Events with JNIEnvs need to stash
-// pending exceptions since they can cause new ones to be thrown. In accordance with the JVMTI
-// specification we allow exceptions originating from events to overwrite the current exception,
-// including exceptions originating from earlier events.
+// Helper for ensuring that the dispatch environment is suitably provisioned. Events with JNIEnvs
+// need to stash pending exceptions since they can cause new ones to be thrown. In accordance with
+// the JVMTI specification we allow exceptions originating from events to overwrite the current
+// exception, including exceptions originating from earlier events.
 class ScopedEventDispatchEnvironment final : public art::ValueObject {
  public:
   ScopedEventDispatchEnvironment() : env_(nullptr), throw_(nullptr, nullptr) {
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc
index 64a02e8..cd7155f 100644
--- a/openjdkjvmti/events.cc
+++ b/openjdkjvmti/events.cc
@@ -300,7 +300,6 @@
       art::Thread* self = art::Thread::Current();
       handler_->DispatchEvent<ArtJvmtiEvent::kDdmPublishChunk>(
           self,
-          static_cast<JNIEnv*>(self->GetJniEnv()),
           static_cast<jint>(type),
           static_cast<jint>(data.size()),
           reinterpret_cast<const jbyte*>(data.data()));
diff --git a/openjdkjvmti/events.h b/openjdkjvmti/events.h
index d4eb171..be0839b 100644
--- a/openjdkjvmti/events.h
+++ b/openjdkjvmti/events.h
@@ -99,7 +99,6 @@
                                      static_cast<jint>(ArtJvmtiEvent::kMinInternalEventTypeVal) + 1;
 
 using ArtJvmtiEventDdmPublishChunk = void (*)(jvmtiEnv *jvmti_env,
-                                              JNIEnv* jni_env,
                                               jint data_type,
                                               jint data_len,
                                               const jbyte* data);
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index eefbe41..9d1fabf 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -39,7 +39,6 @@
 // Runtime includes.
 #include "dex_container.h"
 #include "dex/compact_dex_level.h"
-#include "dex_to_dex_decompiler.h"
 #include "dexlayout.h"
 #include "oat_file.h"
 #include "vdex_file.h"
@@ -51,28 +50,6 @@
       dex_file->CalculateChecksum();
 }
 
-static const art::VdexFile* GetVdex(const art::DexFile& original_dex_file) {
-  const art::OatDexFile* oat_dex = original_dex_file.GetOatDexFile();
-  if (oat_dex == nullptr) {
-    return nullptr;
-  }
-  const art::OatFile* oat_file = oat_dex->GetOatFile();
-  if (oat_file == nullptr) {
-    return nullptr;
-  }
-  return oat_file->GetVdexFile();
-}
-
-static void DoDexUnquicken(const art::DexFile& new_dex_file,
-                           const art::DexFile& original_dex_file) {
-  const art::VdexFile* vdex = GetVdex(original_dex_file);
-  if (vdex != nullptr) {
-    vdex->UnquickenDexFile(new_dex_file,
-                           original_dex_file,
-                           /* decompile_return_instruction= */ true);
-  }
-}
-
 static void DCheckVerifyDexFile(const art::DexFile& dex) {
   if (art::kIsDebugBuild) {
     std::string error;
@@ -150,8 +127,6 @@
 
   new_dex_file->SetHiddenapiDomain(original.GetHiddenapiDomain());
 
-  DoDexUnquicken(*new_dex_file, original);
-
   RecomputeDexChecksum(const_cast<art::DexFile*>(new_dex_file.get()));
   DCheckVerifyDexFile(*new_dex_file);
   std::unique_ptr<FixedUpDexFile> ret(new FixedUpDexFile(std::move(new_dex_file), std::move(data)));
diff --git a/openjdkjvmti/ti_class.cc b/openjdkjvmti/ti_class.cc
index 4d6b41a..924a0d8 100644
--- a/openjdkjvmti/ti_class.cc
+++ b/openjdkjvmti/ti_class.cc
@@ -56,6 +56,7 @@
 #include "gc/heap.h"
 #include "gc_root.h"
 #include "handle.h"
+#include "hidden_api.h"
 #include "jni/jni_env_ext-inl.h"
 #include "jni/jni_internal.h"
 #include "mirror/array-alloc-inl.h"
@@ -661,7 +662,7 @@
   // spec says these should not be reported.
   if (klass->IsArrayClass()) {
     *interface_count_ptr = 0;
-    *interfaces_ptr = nullptr;  // TODO: Should we allocate a dummy here?
+    *interfaces_ptr = nullptr;  // TODO: Should we allocate a placeholder here?
     return ERR(NONE);
   }
 
@@ -1137,4 +1138,38 @@
   return OK;
 }
 
+jvmtiError ClassUtil::DisableHiddenApiEnforcementPolicy(jvmtiEnv* env) {
+  return SetHiddenApiEnforcementPolicy(
+      env, static_cast<jint>(art::hiddenapi::EnforcementPolicy::kDisabled));
+}
+
+jvmtiError ClassUtil::GetHiddenApiEnforcementPolicy(jvmtiEnv* env, jint* policy) {
+  if (env == nullptr) {
+    return ERR(INVALID_ENVIRONMENT);
+  } else if (art::Thread::Current() == nullptr) {
+    return ERR(UNATTACHED_THREAD);
+  } else if (policy == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  *policy = static_cast<jint>(art::Runtime::Current()->GetHiddenApiEnforcementPolicy());
+  return OK;
+}
+
+jvmtiError ClassUtil::SetHiddenApiEnforcementPolicy(jvmtiEnv* env, jint policy) {
+  if (env == nullptr) {
+    return ERR(INVALID_ENVIRONMENT);
+  } else if (art::Thread::Current() == nullptr) {
+    return ERR(UNATTACHED_THREAD);
+  } else if (policy < static_cast<jint>(art::hiddenapi::EnforcementPolicy::kDisabled) ||
+             policy > static_cast<jint>(art::hiddenapi::EnforcementPolicy::kMax)) {
+    JVMTI_LOG(INFO, env) << "Bad policy: " << policy << ", must be between "
+                         << static_cast<jint>(art::hiddenapi::EnforcementPolicy::kDisabled)
+                         << " and " << static_cast<jint>(art::hiddenapi::EnforcementPolicy::kMax);
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+  art::Runtime::Current()->SetHiddenApiEnforcementPolicy(
+      static_cast<art::hiddenapi::EnforcementPolicy>(policy));
+  return OK;
+}
+
 }  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_class.h b/openjdkjvmti/ti_class.h
index 7e427a0..229a6ce 100644
--- a/openjdkjvmti/ti_class.h
+++ b/openjdkjvmti/ti_class.h
@@ -93,6 +93,10 @@
   static jvmtiError GetSourceDebugExtension(jvmtiEnv* env,
                                             jclass klass,
                                             char** source_debug_extension_ptr);
+
+  static jvmtiError DisableHiddenApiEnforcementPolicy(jvmtiEnv* env);
+  static jvmtiError GetHiddenApiEnforcementPolicy(jvmtiEnv* env, jint* policy);
+  static jvmtiError SetHiddenApiEnforcementPolicy(jvmtiEnv* env, jint policy);
 };
 
 }  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_class_definition.cc b/openjdkjvmti/ti_class_definition.cc
index ec267155..a480ac0 100644
--- a/openjdkjvmti/ti_class_definition.cc
+++ b/openjdkjvmti/ti_class_definition.cc
@@ -34,7 +34,7 @@
 #include "base/array_slice.h"
 #include "base/logging.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/dex_file.h"
 #include "fixed_up_dex_file.h"
 #include "handle.h"
diff --git a/openjdkjvmti/ti_extension.cc b/openjdkjvmti/ti_extension.cc
index 62c6fb2..10ea43a 100644
--- a/openjdkjvmti/ti_extension.cc
+++ b/openjdkjvmti/ti_extension.cc
@@ -488,6 +488,79 @@
     LOG(INFO) << "debuggable & jni-type indices are required to implement structural "
               << "class redefinition extensions.";
   }
+  // SetVerboseFlagExt
+  error = add_extension(
+      reinterpret_cast<jvmtiExtensionFunction>(LogUtil::SetVerboseFlagExt),
+      "com.android.art.misc.set_verbose_flag_ext",
+      "Sets the verbose flags selected by the 'option' c-string. Valid options are anything that"
+      " would be accepted by the -verbose:<option> runtime flag. The verbose selections are turned"
+      " on if 'enable' is set to true and disabled otherwise. You may select multiple options at"
+      " once using commas just like with the -verbose:<option> flag. For example \"class,deopt,gc\""
+      " is equivalent to turning on all of the VLOG(class_linker), VLOG(deopt) and VLOG(gc)"
+      " messages.",
+      {
+        { "option", JVMTI_KIND_IN_BUF, JVMTI_TYPE_CCHAR, false },
+        { "enable", JVMTI_KIND_IN, JVMTI_TYPE_JBOOLEAN, false },
+      },
+      {
+         ERR(NULL_POINTER),
+         ERR(ILLEGAL_ARGUMENT),
+      });
+  if (error != ERR(NONE)) {
+    return error;
+  }
+  // GetHiddenApiEnforcementPolicy
+  error = add_extension(
+      reinterpret_cast<jvmtiExtensionFunction>(ClassUtil::GetHiddenApiEnforcementPolicy),
+      "com.android.art.misc.get_hidden_api_enforcement_policy",
+      "Gets the current hiddenapi enforcement policy. Policy values are defined in"
+      " `frameworks/base/core/java/android/content/pm/ApplicationInfo.java` as the"
+      " HIDDEN_API_ENFORCEMENT_ static fields. See the comments in `art/runtime/hidden_api.h` for"
+      " more information. This should be used with"
+      " `com.android.art.misc.set_hidden_api_enforcement_policy` in order to restore the"
+      " hidden-api state after temporarily toggling it.",
+      {
+        { "policy", JVMTI_KIND_OUT, JVMTI_TYPE_JINT, false },
+      },
+      {
+         ERR(NULL_POINTER),
+      });
+  if (error != ERR(NONE)) {
+    return error;
+  }
+  // SetHiddenApiEnforcementPolicy
+  error = add_extension(
+      reinterpret_cast<jvmtiExtensionFunction>(ClassUtil::SetHiddenApiEnforcementPolicy),
+      "com.android.art.misc.set_hidden_api_enforcement_policy",
+      "Sets the hiddenapi enforcement policy to the given value. Policy values are defined in"
+      " `frameworks/base/core/java/android/content/pm/ApplicationInfo.java` as the"
+      " HIDDEN_API_ENFORCEMENT_ static fields. See the comments in `art/runtime/hidden_api.h` for"
+      " more information. This API should always be used sparingly and in conjunction with"
+      " `com.android.art.misc.get_hidden_api_enforcement_policy` to temporarily toggle"
+      " hidden-api on and off as changes are required.",
+      {
+        { "policy", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
+      },
+      {
+         ERR(ILLEGAL_ARGUMENT),
+      });
+  if (error != ERR(NONE)) {
+    return error;
+  }
+  // DisableHiddenApiEnforcementPolicy
+  error = add_extension(
+      reinterpret_cast<jvmtiExtensionFunction>(ClassUtil::DisableHiddenApiEnforcementPolicy),
+      "com.android.art.misc.disable_hidden_api_enforcement_policy",
+      "Sets the hiddenapi enforcement policy to disabled. This API should always be"
+      " used sparingly and in conjunction with"
+      " `com.android.art.misc.get_hidden_api_enforcement_policy` and"
+      " `com.android.art.misc.set_hidden_api_enforcement_policy` to temporarily"
+      " toggle hidden-api on and off as changes are required.",
+      {},
+      {});
+  if (error != ERR(NONE)) {
+    return error;
+  }
 
   // Copy into output buffer.
 
@@ -578,15 +651,16 @@
   jvmtiError error;
   error = add_extension(
       ArtJvmtiEvent::kDdmPublishChunk,
-      "com.android.art.internal.ddm.publish_chunk",
+      "com.android.art.internal.ddm.publish_chunk_safe",
       "Called when there is new ddms information that the agent or other clients can use. The"
       " agent is given the 'type' of the ddms chunk and a 'data_size' byte-buffer in 'data'."
       " The 'data' pointer is only valid for the duration of the publish_chunk event. The agent"
       " is responsible for interpreting the information present in the 'data' buffer. This is"
       " provided for backwards-compatibility support only. Agents should prefer to use relevant"
-      " JVMTI events and functions above listening for this event.",
+      " JVMTI events and functions above listening for this event. Previous publish_chunk"
+      " event was inherently unsafe since using the JNIEnv could cause deadlocks in some scenarios."
+      " The current version does not have these issues.",
       {
-        { "jni_env", JVMTI_KIND_IN_PTR, JVMTI_TYPE_JNIENV, false },
         { "type", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
         { "data_size", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
         { "data",  JVMTI_KIND_IN_BUF, JVMTI_TYPE_JBYTE, false },
diff --git a/openjdkjvmti/ti_heap.cc b/openjdkjvmti/ti_heap.cc
index 974a710..f4e34dd 100644
--- a/openjdkjvmti/ti_heap.cc
+++ b/openjdkjvmti/ti_heap.cc
@@ -29,7 +29,6 @@
 #include "base/mutex.h"
 #include "base/utils.h"
 #include "class_linker.h"
-#include "class_root.h"
 #include "deopt_manager.h"
 #include "dex/primitive.h"
 #include "events-inl.h"
@@ -760,7 +759,8 @@
 
   bool stop_reports = false;
   const HeapFilter heap_filter(heap_filter_int);
-  art::ObjPtr<art::mirror::Class> filter_klass = soa.Decode<art::mirror::Class>(klass);
+  art::StackHandleScope<1> hs(self);
+  art::Handle<art::mirror::Class> filter_klass(hs.NewHandle(soa.Decode<art::mirror::Class>(klass)));
   auto visitor = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
     // Early return, as we can't really stop visiting.
     if (stop_reports) {
@@ -782,7 +782,7 @@
     }
 
     if (filter_klass != nullptr) {
-      if (filter_klass != klass) {
+      if (filter_klass.Get() != klass) {
         return;
       }
     }
diff --git a/openjdkjvmti/ti_logging.cc b/openjdkjvmti/ti_logging.cc
index 60f4340..8740ec6 100644
--- a/openjdkjvmti/ti_logging.cc
+++ b/openjdkjvmti/ti_logging.cc
@@ -33,8 +33,11 @@
 
 #include "art_jvmti.h"
 
+#include "base/logging.h"
 #include "base/mutex.h"
 #include "base/strlcpy.h"
+#include "cmdline_types.h"
+#include "jvmti.h"
 #include "thread-current-inl.h"
 
 namespace openjdkjvmti {
@@ -69,4 +72,91 @@
   return OK;
 }
 
+jvmtiError LogUtil::SetVerboseFlagExt(jvmtiEnv* env, const char* data, jboolean enable) {
+  if (env == nullptr) {
+    return ERR(INVALID_ENVIRONMENT);
+  } else if (data == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+  bool new_value = (enable == JNI_TRUE) ? true : false;
+  art::CmdlineType<art::LogVerbosity> cmdline_parser;
+  std::string parse_data(data);
+  art::CmdlineType<art::LogVerbosity>::Result result = cmdline_parser.Parse(parse_data);
+  if (result.IsError()) {
+    JVMTI_LOG(INFO, env) << "Invalid verbose argument: '" << parse_data << "'. Error was "
+                         << result.GetMessage();
+    return ERR(ILLEGAL_ARGUMENT);
+  }
+
+  const art::LogVerbosity& input_verbosity = result.GetValue();
+  const bool* verbosity_arr = reinterpret_cast<const bool*>(&input_verbosity);
+  bool* g_log_verbosity_arr = reinterpret_cast<bool*>(&art::gLogVerbosity);
+  // Copy/invert the verbosity byte-by-byte (sizeof(bool) == 1).
+  for (size_t i = 0; i < sizeof(art::LogVerbosity); i++) {
+    if (verbosity_arr[i]) {
+      g_log_verbosity_arr[i] = new_value;
+    }
+  }
+  return OK;
+}
+
+jvmtiError LogUtil::SetVerboseFlag(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                   jvmtiVerboseFlag flag,
+                                   jboolean value) {
+  if (flag == jvmtiVerboseFlag::JVMTI_VERBOSE_OTHER) {
+    // OTHER is special, as it's 0, so can't do a bit check.
+    bool val = (value == JNI_TRUE) ? true : false;
+
+    art::gLogVerbosity.collector = val;
+    art::gLogVerbosity.compiler = val;
+    art::gLogVerbosity.deopt = val;
+    art::gLogVerbosity.heap = val;
+    art::gLogVerbosity.interpreter = val;
+    art::gLogVerbosity.jdwp = val;
+    art::gLogVerbosity.jit = val;
+    art::gLogVerbosity.monitor = val;
+    art::gLogVerbosity.oat = val;
+    art::gLogVerbosity.profiler = val;
+    art::gLogVerbosity.signals = val;
+    art::gLogVerbosity.simulator = val;
+    art::gLogVerbosity.startup = val;
+    art::gLogVerbosity.third_party_jni = val;
+    art::gLogVerbosity.threads = val;
+    art::gLogVerbosity.verifier = val;
+    // Do not set verifier-debug.
+    art::gLogVerbosity.image = val;
+    art::gLogVerbosity.plugin = val;
+
+    // Note: can't switch systrace_lock_logging. That requires changing entrypoints.
+
+    art::gLogVerbosity.agents = val;
+  } else {
+    // Spec isn't clear whether "flag" is a mask or supposed to be single. We implement the mask
+    // semantics.
+    constexpr std::underlying_type<jvmtiVerboseFlag>::type kMask =
+        jvmtiVerboseFlag::JVMTI_VERBOSE_GC |
+        jvmtiVerboseFlag::JVMTI_VERBOSE_CLASS |
+        jvmtiVerboseFlag::JVMTI_VERBOSE_JNI;
+    if ((flag & ~kMask) != 0) {
+      return ERR(ILLEGAL_ARGUMENT);
+    }
+
+    bool val = (value == JNI_TRUE) ? true : false;
+
+    if ((flag & jvmtiVerboseFlag::JVMTI_VERBOSE_GC) != 0) {
+      art::gLogVerbosity.gc = val;
+    }
+
+    if ((flag & jvmtiVerboseFlag::JVMTI_VERBOSE_CLASS) != 0) {
+      art::gLogVerbosity.class_linker = val;
+    }
+
+    if ((flag & jvmtiVerboseFlag::JVMTI_VERBOSE_JNI) != 0) {
+      art::gLogVerbosity.jni = val;
+    }
+  }
+
+  return ERR(NONE);
+}
+
 }  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_logging.h b/openjdkjvmti/ti_logging.h
index b4ce5b6..fc814ef 100644
--- a/openjdkjvmti/ti_logging.h
+++ b/openjdkjvmti/ti_logging.h
@@ -94,6 +94,9 @@
  public:
   static jvmtiError ClearLastError(jvmtiEnv* env);
   static jvmtiError GetLastError(jvmtiEnv* env, char** data);
+
+  static jvmtiError SetVerboseFlag(jvmtiEnv* env, jvmtiVerboseFlag flag, jboolean value);
+  static jvmtiError SetVerboseFlagExt(jvmtiEnv* env, const char* data, jboolean enable);
 };
 
 }  // namespace openjdkjvmti
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
index e7f071f..f2646c6 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -190,7 +190,8 @@
     return ERR(NONE);
   }
 
-  DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
+  DCHECK(art_method->HasCodeItem());
+  DCHECK_NE(art_method->GetCodeItem(), nullptr);
   *size_ptr = art_method->DexInstructionData().InsSize();
 
   return ERR(NONE);
@@ -306,7 +307,8 @@
     return ERR(NONE);
   }
 
-  DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
+  DCHECK(art_method->HasCodeItem());
+  DCHECK_NE(art_method->GetCodeItem(), nullptr);
   *max_ptr = art_method->DexInstructionData().RegistersSize();
 
   return ERR(NONE);
@@ -420,7 +422,8 @@
     return ERR(NONE);
   }
 
-  DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
+  DCHECK(art_method->HasCodeItem());
+  DCHECK_NE(art_method->GetCodeItem(), nullptr);
   *start_location_ptr = 0;
   *end_location_ptr = art_method->DexInstructions().InsnsSizeInCodeUnits() - 1;
 
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index c457dba..b2b839b 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -61,7 +61,7 @@
 #include "base/utils.h"
 #include "class_linker-inl.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "class_status.h"
 #include "debugger.h"
 #include "dex/art_dex_file_loader.h"
@@ -186,7 +186,7 @@
       DCHECK(obsolete_dex_caches_->Get(next_free_slot_) != nullptr);
       next_free_slot_++;
     }
-    // Sanity check that the same slot in obsolete_dex_caches_ is free.
+    // Check that the same slot in obsolete_dex_caches_ is free.
     DCHECK(obsolete_dex_caches_->Get(next_free_slot_) == nullptr);
   }
 
@@ -260,7 +260,7 @@
 };
 
 // This visitor walks thread stacks and allocates and sets up the obsolete methods. It also does
-// some basic sanity checks that the obsolete method is sane.
+// some basic soundness checks that the obsolete method is valid.
 class ObsoleteMethodStackVisitor : public art::StackVisitor {
  protected:
   ObsoleteMethodStackVisitor(
@@ -758,13 +758,10 @@
     return nullptr;
   }
   art::WriterMutexLock mu(driver_->self_, *art::Locks::dex_lock_);
-  art::mirror::DexCache::InitializeDexCache(driver_->self_,
-                                            cache.Get(),
-                                            location.Get(),
-                                            dex_file_.get(),
-                                            loader.IsNull() ? driver_->runtime_->GetLinearAlloc()
-                                                            : loader->GetAllocator(),
-                                            art::kRuntimePointerSize);
+  cache->SetLocation(location.Get());
+  cache->InitializeNativeFields(dex_file_.get(),
+                                loader.IsNull() ? driver_->runtime_->GetLinearAlloc()
+                                                : loader->GetAllocator());
   return cache.Get();
 }
 
@@ -1173,7 +1170,7 @@
 class RedefinitionDataIter;
 
 // A wrapper that lets us hold onto the arbitrary sized data needed for redefinitions in a
-// reasonably sane way. This adds no fields to the normal ObjectArray. By doing this we can avoid
+// reasonable way. This adds no fields to the normal ObjectArray. By doing this we can avoid
 // having to deal with the fact that we need to hold an arbitrary number of references live.
 class RedefinitionDataHolder {
  public:
@@ -1616,6 +1613,7 @@
   // TODO Make verification log level lower
   art::verifier::FailureKind failure =
       art::verifier::ClassVerifier::VerifyClass(driver_->self_,
+                                                /*verifier_deps=*/nullptr,
                                                 dex_file_.get(),
                                                 hs.NewHandle(iter.GetNewDexCache()),
                                                 hs.NewHandle(GetClassLoader()),
@@ -1633,6 +1631,7 @@
       return true;
     case art::verifier::FailureKind::kSoftFailure:
     case art::verifier::FailureKind::kAccessChecksFailure:
+    case art::verifier::FailureKind::kTypeChecksFailure:
       // Soft failures might require interpreter on some methods. It won't prevent redefinition but
       // it does mean we need to run the verifier again and potentially update method flags after
       // performing the swap.
@@ -2489,9 +2488,11 @@
   // At this point we can no longer fail without corrupting the runtime state.
   for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
     art::ClassLinker* cl = runtime_->GetClassLinker();
-    cl->RegisterExistingDexCache(data.GetNewDexCache(), data.GetSourceClassLoader());
     if (data.GetSourceClassLoader() == nullptr) {
+      // AppendToBootClassPath includes dex file registration.
       cl->AppendToBootClassPath(self_, &data.GetRedefinition().GetDexFile());
+    } else {
+      cl->RegisterExistingDexCache(data.GetNewDexCache(), data.GetSourceClassLoader());
     }
   }
   UnregisterAllBreakpoints();
@@ -2583,7 +2584,10 @@
     uint32_t dex_method_idx = dex_file_->GetIndexForMethodId(*method_id);
     method.SetDexMethodIndex(dex_method_idx);
     linker->SetEntryPointsToInterpreter(&method);
-    method.SetCodeItemOffset(dex_file_->FindCodeItemOffset(class_def, dex_method_idx));
+    if (method.HasCodeItem()) {
+      method.SetCodeItem(
+          dex_file_->GetCodeItem(dex_file_->FindCodeItemOffset(class_def, dex_method_idx)));
+    }
     // Clear all the intrinsics related flags.
     method.SetNotIntrinsic();
   }
@@ -2761,8 +2765,6 @@
   art::Locks::mutator_lock_->AssertExclusiveHeld(driver_->self_);
   art::ClassLinker* cl = driver_->runtime_->GetClassLinker();
   art::ScopedAssertNoThreadSuspension sants(__FUNCTION__);
-  art::ObjPtr<art::mirror::Class> orig(holder.GetMirrorClass());
-  art::ObjPtr<art::mirror::Class> replacement(holder.GetNewClassObject());
   art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> new_classes(holder.GetNewClasses());
   art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> old_classes(holder.GetOldClasses());
   // Collect mappings from old to new fields/methods
@@ -2773,8 +2775,6 @@
       holder.GetNewInstanceObjects());
   art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> old_instances(
       holder.GetOldInstanceObjects());
-  CHECK(!orig.IsNull());
-  CHECK(!replacement.IsNull());
   // Once we do the ReplaceReferences old_classes will have the new_classes in it. We want to keep
   // ahold of the old classes so copy them now.
   std::vector<art::ObjPtr<art::mirror::Class>> old_classes_vec(old_classes->Iterate().begin(),
@@ -2848,16 +2848,26 @@
       }
     }
     // We can only shadow things from our superclasses
-    if (LIKELY(!field_or_method->GetDeclaringClass()->IsAssignableFrom(orig))) {
+    auto orig_classes_iter = old_classes->Iterate();
+    auto replacement_classes_iter = new_classes->Iterate();
+    art::ObjPtr<art::mirror::Class> f_or_m_class = field_or_method->GetDeclaringClass();
+    if (LIKELY(!f_or_m_class->IsAssignableFrom(holder.GetMirrorClass()) &&
+               std::find(orig_classes_iter.begin(), orig_classes_iter.end(), f_or_m_class) ==
+                   orig_classes_iter.end())) {
       return false;
     }
     if constexpr (is_method) {
-      auto direct_methods = replacement->GetDirectMethods(art::kRuntimePointerSize);
-      return std::find_if(direct_methods.begin(),
-                          direct_methods.end(),
-                          [&](art::ArtMethod& m) REQUIRES(art::Locks::mutator_lock_) {
-                            return UNLIKELY(m.HasSameNameAndSignature(field_or_method));
-                          }) != direct_methods.end();
+      return std::any_of(
+          replacement_classes_iter.begin(),
+          replacement_classes_iter.end(),
+          [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
+            auto direct_methods = cand->GetDirectMethods(art::kRuntimePointerSize);
+            return std::find_if(direct_methods.begin(),
+                                direct_methods.end(),
+                                [&](art::ArtMethod& m) REQUIRES(art::Locks::mutator_lock_) {
+                                  return UNLIKELY(m.HasSameNameAndSignature(field_or_method));
+                                }) != direct_methods.end();
+          });
     } else {
       auto pred = [&](art::ArtField& f) REQUIRES(art::Locks::mutator_lock_) {
         return std::string_view(f.GetName()) == std::string_view(field_or_method->GetName()) &&
@@ -2865,11 +2875,21 @@
                    std::string_view(field_or_method->GetTypeDescriptor());
       };
       if (field_or_method->IsStatic()) {
-        auto sfields = replacement->GetSFields();
-        return std::find_if(sfields.begin(), sfields.end(), pred) != sfields.end();
+        return std::any_of(
+            replacement_classes_iter.begin(),
+            replacement_classes_iter.end(),
+            [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
+              auto sfields = cand->GetSFields();
+              return std::find_if(sfields.begin(), sfields.end(), pred) != sfields.end();
+            });
       } else {
-        auto ifields = replacement->GetIFields();
-        return std::find_if(ifields.begin(), ifields.end(), pred) != ifields.end();
+        return std::any_of(
+            replacement_classes_iter.begin(),
+            replacement_classes_iter.end(),
+            [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
+              auto ifields = cand->GetIFields();
+              return std::find_if(ifields.begin(), ifields.end(), pred) != ifields.end();
+            });
       }
     }
   };
@@ -2879,28 +2899,28 @@
       [&](art::ArtField* f, const auto& info) REQUIRES(art::Locks::mutator_lock_) {
         DCHECK(f != nullptr) << info;
         auto it = field_map.find(f);
-        if (it != field_map.end()) {
+        if (UNLIKELY(could_change_resolution_of(f, info))) {
+          // Dex-cache Resolution might change. Just clear the resolved value.
+          VLOG(plugin) << "Clearing resolution " << info << " for (field) " << f->PrettyField();
+          return static_cast<art::ArtField*>(nullptr);
+        } else if (it != field_map.end()) {
           VLOG(plugin) << "Updating " << info << " object for (field) "
                        << it->second->PrettyField();
           return it->second;
-        } else if (UNLIKELY(could_change_resolution_of(f, info))) {
-          // Resolution might change. Just clear the resolved value.
-          VLOG(plugin) << "Clearing resolution " << info << " for (field) " << f->PrettyField();
-          return static_cast<art::ArtField*>(nullptr);
         }
         return f;
       },
       [&](art::ArtMethod* m, const auto& info) REQUIRES(art::Locks::mutator_lock_) {
         DCHECK(m != nullptr) << info;
         auto it = method_map.find(m);
-        if (it != method_map.end()) {
+        if (UNLIKELY(could_change_resolution_of(m, info))) {
+          // Dex-cache Resolution might change. Just clear the resolved value.
+          VLOG(plugin) << "Clearing resolution " << info << " for (method) " << m->PrettyMethod();
+          return static_cast<art::ArtMethod*>(nullptr);
+        } else if (it != method_map.end()) {
           VLOG(plugin) << "Updating " << info << " object for (method) "
                       << it->second->PrettyMethod();
           return it->second;
-        } else if (UNLIKELY(could_change_resolution_of(m, info))) {
-          // Resolution might change. Just clear the resolved value.
-          VLOG(plugin) << "Clearing resolution " << info << " for (method) " << m->PrettyMethod();
-          return static_cast<art::ArtMethod*>(nullptr);
         }
         return m;
       });
@@ -2955,18 +2975,25 @@
   if (art::kIsDebugBuild) {
     // Just make sure we didn't screw up any of the now obsolete methods or fields. We need their
     // declaring-class to still be the obolete class
-    orig->VisitMethods([&](art::ArtMethod* method) REQUIRES_SHARED(art::Locks::mutator_lock_) {
-      if (method->IsCopied()) {
-        // Copied methods have interfaces as their declaring class.
-        return;
-      }
-      DCHECK_EQ(method->GetDeclaringClass(), orig) << method->GetDeclaringClass()->PrettyClass()
-                                                   << " vs " << orig->PrettyClass();
-    }, art::kRuntimePointerSize);
-    orig->VisitFields([&](art::ArtField* field) REQUIRES_SHARED(art::Locks::mutator_lock_) {
-      DCHECK_EQ(field->GetDeclaringClass(), orig) << field->GetDeclaringClass()->PrettyClass()
-                                                  << " vs " << orig->PrettyClass();
-    });
+    std::for_each(
+        old_classes_vec.cbegin(),
+        old_classes_vec.cend(),
+        [](art::ObjPtr<art::mirror::Class> orig) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+          orig->VisitMethods(
+              [&](art::ArtMethod* method) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+                if (method->IsCopied()) {
+                  // Copied methods have interfaces as their declaring class.
+                  return;
+                }
+                DCHECK_EQ(method->GetDeclaringClass(), orig)
+                    << method->GetDeclaringClass()->PrettyClass() << " vs " << orig->PrettyClass();
+              },
+              art::kRuntimePointerSize);
+          orig->VisitFields([&](art::ArtField* field) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+            DCHECK_EQ(field->GetDeclaringClass(), orig)
+                << field->GetDeclaringClass()->PrettyClass() << " vs " << orig->PrettyClass();
+          });
+        });
   }
 }
 
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc
index 1a5b227..bb8fa3b 100644
--- a/openjdkjvmti/ti_thread.cc
+++ b/openjdkjvmti/ti_thread.cc
@@ -39,12 +39,13 @@
 #include "base/mutex.h"
 #include "deopt_manager.h"
 #include "events-inl.h"
-#include "gc/system_weak.h"
 #include "gc/collector_type.h"
 #include "gc/gc_cause.h"
 #include "gc/scoped_gc_critical_section.h"
+#include "gc/system_weak.h"
 #include "gc_root-inl.h"
 #include "jni/jni_internal.h"
+#include "metrics/reporter.h"
 #include "mirror/class.h"
 #include "mirror/object-inl.h"
 #include "mirror/string.h"
@@ -123,13 +124,12 @@
     if (!started) {
       // Runtime isn't started. We only expect at most the signal handler or JIT threads to be
       // started here; this includes the perfetto_hprof_listener signal handler thread for
-      // perfetto_hprof.
+      // perfetto_hprof, as well as the metrics background reporting thread.
       if (art::kIsDebugBuild) {
         std::string name;
         self->GetThreadName(name);
-        if (name != "JDWP" &&
-            name != "Signal Catcher" &&
-            name != "perfetto_hprof_listener" &&
+        if (name != "JDWP" && name != "Signal Catcher" && name != "perfetto_hprof_listener" &&
+            name != art::metrics::MetricsReporter::kBackgroundThreadName &&
             !android::base::StartsWith(name, "Jit thread pool") &&
             !android::base::StartsWith(name, "Runtime worker thread")) {
           LOG(FATAL) << "Unexpected thread before start: " << name << " id: "
diff --git a/openjdkjvmti/transform.cc b/openjdkjvmti/transform.cc
index 715a98c..011bd71 100644
--- a/openjdkjvmti/transform.cc
+++ b/openjdkjvmti/transform.cc
@@ -68,7 +68,6 @@
 #include "ti_redefine.h"
 #include "ti_logging.h"
 #include "transform.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
 
 namespace openjdkjvmti {
 
diff --git a/perfetto_hprof/Android.bp b/perfetto_hprof/Android.bp
index 65c072e..b2c9dad 100644
--- a/perfetto_hprof/Android.bp
+++ b/perfetto_hprof/Android.bp
@@ -20,6 +20,15 @@
 // to be backwards compatible, see
 // https://android.googlesource.com/platform/external/perfetto/+/refs/heads/master/protos/perfetto/ipc/producer_port.proto.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 gensrcs {
     name: "art_perfetto_hprof_operator_srcs",
     cmd: "$(location generate_operator_out) art/perfetto_hprof $(in) > $(out)",
@@ -35,10 +44,6 @@
     host_supported: false,
     srcs: ["perfetto_hprof.cc"],
     defaults: ["art_defaults"],
-    include_dirs: [
-        "external/perfetto/include",
-        "external/perfetto/protos",
-    ],
 
     // Note that this tool needs to be built for both 32-bit and 64-bit since it requires
     // to be same ISA as what it is attached to.
@@ -54,12 +59,8 @@
         "perfetto_trace_protos",
     ],
     generated_sources: [
-        "perfetto_protos_perfetto_config_profiling_zero_gen",
         "art_perfetto_hprof_operator_srcs",
     ],
-    generated_headers: [
-        "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    ],
     target: {
         darwin: {
             enabled: false,
@@ -78,7 +79,7 @@
         "libartbase",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
diff --git a/perfetto_hprof/perfetto_hprof.cc b/perfetto_hprof/perfetto_hprof.cc
index 3f5d06d..3affe8d 100644
--- a/perfetto_hprof/perfetto_hprof.cc
+++ b/perfetto_hprof/perfetto_hprof.cc
@@ -19,6 +19,7 @@
 #include "perfetto_hprof.h"
 
 #include <android-base/logging.h>
+#include <base/fast_exit.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <sched.h>
@@ -31,6 +32,8 @@
 #include <thread>
 #include <time.h>
 
+#include <limits>
+#include <optional>
 #include <type_traits>
 
 #include "gc/heap-visit-objects-inl.h"
@@ -38,7 +41,6 @@
 #include "gc/scoped_gc_critical_section.h"
 #include "mirror/object-refvisitor-inl.h"
 #include "nativehelper/scoped_local_ref.h"
-#include "perfetto/profiling/normalize.h"
 #include "perfetto/profiling/parse_smaps.h"
 #include "perfetto/trace/interned_data/interned_data.pbzero.h"
 #include "perfetto/trace/profiling/heap_graph.pbzero.h"
@@ -82,6 +84,7 @@
   return state_cv;
 }
 
+static int requested_tracing_session_id = 0;
 static State g_state = State::kUninitialized;
 
 // Pipe to signal from the signal handler into a worker thread that handles the
@@ -148,85 +151,34 @@
   return false;
 }
 
-bool CanConnectToSocket(const char* name) {
-  struct sockaddr_un addr = {};
-  addr.sun_family = AF_UNIX;
-  strncpy(addr.sun_path, name, sizeof(addr.sun_path) - 1);
-  int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
-  if (fd == -1) {
-    PLOG(ERROR) << "failed to create socket";
-    return false;
-  }
-  bool connected = connect(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) == 0;
-  close(fd);
-  return connected;
-}
-
-constexpr size_t kMaxCmdlineSize = 512;
-
 class JavaHprofDataSource : public perfetto::DataSource<JavaHprofDataSource> {
  public:
   constexpr static perfetto::BufferExhaustedPolicy kBufferExhaustedPolicy =
     perfetto::BufferExhaustedPolicy::kStall;
   void OnSetup(const SetupArgs& args) override {
+    uint64_t normalized_cfg_tracing_session_id =
+      args.config->tracing_session_id() % std::numeric_limits<int32_t>::max();
+    if (requested_tracing_session_id < 0) {
+      LOG(ERROR) << "invalid requested tracing session id " << requested_tracing_session_id;
+      return;
+    }
+    if (static_cast<uint64_t>(requested_tracing_session_id) != normalized_cfg_tracing_session_id) {
+      return;
+    }
+
     // This is on the heap as it triggers -Wframe-larger-than.
     std::unique_ptr<perfetto::protos::pbzero::JavaHprofConfig::Decoder> cfg(
         new perfetto::protos::pbzero::JavaHprofConfig::Decoder(
           args.config->java_hprof_config_raw()));
 
-    if (args.config->enable_extra_guardrails() && !CanConnectToSocket("/dev/socket/heapprofd")) {
-      LOG(ERROR) << "rejecting extra guardrails";
-      enabled_ = false;
-      return;
-    }
-
     dump_smaps_ = cfg->dump_smaps();
-
-    uint64_t self_pid = static_cast<uint64_t>(getpid());
-    for (auto pid_it = cfg->pid(); pid_it; ++pid_it) {
-      if (*pid_it == self_pid) {
-        enabled_ = true;
-        return;
-      }
+    for (auto it = cfg->ignored_types(); it; ++it) {
+      std::string name = (*it).ToStdString();
+      ignored_types_.emplace_back(std::move(name));
     }
-
-    if (cfg->has_process_cmdline()) {
-      int fd = open("/proc/self/cmdline", O_RDONLY | O_CLOEXEC);
-      if (fd == -1) {
-        PLOG(ERROR) << "failed to open /proc/self/cmdline";
-        return;
-      }
-      char cmdline[kMaxCmdlineSize];
-      ssize_t rd = read(fd, cmdline, sizeof(cmdline) - 1);
-      if (rd == -1) {
-        PLOG(ERROR) << "failed to read /proc/self/cmdline";
-      }
-      close(fd);
-      if (rd == -1) {
-        return;
-      }
-      cmdline[rd] = '\0';
-      char* cmdline_ptr = cmdline;
-      ssize_t sz = perfetto::profiling::NormalizeCmdLine(&cmdline_ptr, static_cast<size_t>(rd + 1));
-      if (sz == -1) {
-        PLOG(ERROR) << "failed to normalize cmdline";
-      }
-      for (auto it = cfg->process_cmdline(); it; ++it) {
-        std::string other = (*it).ToStdString();
-        // Append \0 to make this a C string.
-        other.resize(other.size() + 1);
-        char* other_ptr = &(other[0]);
-        ssize_t other_sz = perfetto::profiling::NormalizeCmdLine(&other_ptr, other.size());
-        if (other_sz == -1) {
-          PLOG(ERROR) << "failed to normalize other cmdline";
-          continue;
-        }
-        if (sz == other_sz && strncmp(cmdline_ptr, other_ptr, static_cast<size_t>(sz)) == 0) {
-          enabled_ = true;
-          return;
-        }
-      }
-    }
+    // This tracing session ID matches the requesting tracing session ID, so we know heapprofd
+    // has verified it targets this process.
+    enabled_ = true;
   }
 
   bool dump_smaps() { return dump_smaps_; }
@@ -243,7 +195,20 @@
     }
   }
 
-  void OnStop(const StopArgs&) override {}
+  // This datasource can be used with a trace config with a short duration_ms
+  // but a long datasource_stop_timeout_ms. In that case, OnStop is called (in
+  // general) before the dump is done. In that case, we handle the stop
+  // asynchronously, and notify the tracing service once we are done.
+  // In case OnStop is called after the dump is done (but before the process)
+  // has exited, we just acknowledge the request.
+  void OnStop(const StopArgs& a) override {
+    art::MutexLock lk(art_thread(), finish_mutex_);
+    if (is_finished_) {
+      return;
+    }
+    is_stopped_ = true;
+    async_stop_ = std::move(a.HandleStopAsynchronously());
+  }
 
   static art::Thread* art_thread() {
     // TODO(fmayer): Attach the Perfetto producer thread to ART and give it a name. This is
@@ -255,10 +220,27 @@
     return nullptr;
   }
 
+  std::vector<std::string> ignored_types() { return ignored_types_; }
+
+  void Finish() {
+    art::MutexLock lk(art_thread(), finish_mutex_);
+    if (is_stopped_) {
+      async_stop_();
+    } else {
+      is_finished_ = true;
+    }
+  }
+
  private:
   bool enabled_ = false;
   bool dump_smaps_ = false;
+  std::vector<std::string> ignored_types_;
   static art::Thread* self_;
+
+  art::Mutex finish_mutex_{"perfetto_hprof_ds_mutex", art::LockLevel::kGenericBottomLock};
+  bool is_finished_ = false;
+  bool is_stopped_ = false;
+  std::function<void()> async_stop_;
 };
 
 art::Thread* JavaHprofDataSource::self_ = nullptr;
@@ -271,6 +253,7 @@
 
   perfetto::DataSourceDescriptor dsd;
   dsd.set_name("android.java_hprof");
+  dsd.set_will_notify_on_stop(true);
   JavaHprofDataSource::Register(dsd);
 
   LOG(INFO) << "waiting for data source";
@@ -342,13 +325,18 @@
 class ReferredObjectsFinder {
  public:
   explicit ReferredObjectsFinder(
-      std::vector<std::pair<std::string, art::mirror::Object*>>* referred_objects)
-      : referred_objects_(referred_objects) {}
+      std::vector<std::pair<std::string, art::mirror::Object*>>* referred_objects,
+      art::mirror::Object** min_nonnull_ptr)
+      : referred_objects_(referred_objects), min_nonnull_ptr_(min_nonnull_ptr) {}
 
   // For art::mirror::Object::VisitReferences.
   void operator()(art::ObjPtr<art::mirror::Object> obj, art::MemberOffset offset,
                   bool is_static) const
       REQUIRES_SHARED(art::Locks::mutator_lock_) {
+    if (offset.Uint32Value() == art::mirror::Object::ClassOffset().Uint32Value()) {
+      // Skip shadow$klass pointer.
+      return;
+    }
     art::mirror::Object* ref = obj->GetFieldObject<art::mirror::Object>(offset);
     art::ArtField* field;
     if (is_static) {
@@ -361,6 +349,9 @@
       field_name = field->PrettyField(/*with_type=*/true);
     }
     referred_objects_->emplace_back(std::move(field_name), ref);
+    if (!*min_nonnull_ptr_ || (ref && *min_nonnull_ptr_ > ref)) {
+      *min_nonnull_ptr_ = ref;
+    }
   }
 
   void VisitRootIfNonNull(art::mirror::CompressedReference<art::mirror::Object>* root
@@ -372,6 +363,7 @@
   // We can use a raw Object* pointer here, because there are no concurrent GC threads after the
   // fork.
   std::vector<std::pair<std::string, art::mirror::Object*>>* referred_objects_;
+  art::mirror::Object** min_nonnull_ptr_;
 };
 
 class RootFinder : public art::SingleRootVisitor {
@@ -391,37 +383,68 @@
 };
 
 perfetto::protos::pbzero::HeapGraphRoot::Type ToProtoType(art::RootType art_type) {
+  using perfetto::protos::pbzero::HeapGraphRoot;
   switch (art_type) {
     case art::kRootUnknown:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_UNKNOWN;
+      return HeapGraphRoot::ROOT_UNKNOWN;
     case art::kRootJNIGlobal:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_JNI_GLOBAL;
+      return HeapGraphRoot::ROOT_JNI_GLOBAL;
     case art::kRootJNILocal:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_JNI_LOCAL;
+      return HeapGraphRoot::ROOT_JNI_LOCAL;
     case art::kRootJavaFrame:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_JAVA_FRAME;
+      return HeapGraphRoot::ROOT_JAVA_FRAME;
     case art::kRootNativeStack:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_NATIVE_STACK;
+      return HeapGraphRoot::ROOT_NATIVE_STACK;
     case art::kRootStickyClass:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_STICKY_CLASS;
+      return HeapGraphRoot::ROOT_STICKY_CLASS;
     case art::kRootThreadBlock:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_THREAD_BLOCK;
+      return HeapGraphRoot::ROOT_THREAD_BLOCK;
     case art::kRootMonitorUsed:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_MONITOR_USED;
+      return HeapGraphRoot::ROOT_MONITOR_USED;
     case art::kRootThreadObject:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_THREAD_OBJECT;
+      return HeapGraphRoot::ROOT_THREAD_OBJECT;
     case art::kRootInternedString:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_INTERNED_STRING;
+      return HeapGraphRoot::ROOT_INTERNED_STRING;
     case art::kRootFinalizing:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_FINALIZING;
+      return HeapGraphRoot::ROOT_FINALIZING;
     case art::kRootDebugger:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_DEBUGGER;
+      return HeapGraphRoot::ROOT_DEBUGGER;
     case art::kRootReferenceCleanup:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_REFERENCE_CLEANUP;
+      return HeapGraphRoot::ROOT_REFERENCE_CLEANUP;
     case art::kRootVMInternal:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_VM_INTERNAL;
+      return HeapGraphRoot::ROOT_VM_INTERNAL;
     case art::kRootJNIMonitor:
-      return perfetto::protos::pbzero::HeapGraphRoot::ROOT_JNI_MONITOR;
+      return HeapGraphRoot::ROOT_JNI_MONITOR;
+  }
+}
+
+perfetto::protos::pbzero::HeapGraphType::Kind ProtoClassKind(uint32_t class_flags) {
+  using perfetto::protos::pbzero::HeapGraphType;
+  switch (class_flags) {
+    case art::mirror::kClassFlagNormal:
+      return HeapGraphType::KIND_NORMAL;
+    case art::mirror::kClassFlagNoReferenceFields:
+      return HeapGraphType::KIND_NOREFERENCES;
+    case art::mirror::kClassFlagString | art::mirror::kClassFlagNoReferenceFields:
+      return HeapGraphType::KIND_STRING;
+    case art::mirror::kClassFlagObjectArray:
+      return HeapGraphType::KIND_ARRAY;
+    case art::mirror::kClassFlagClass:
+      return HeapGraphType::KIND_CLASS;
+    case art::mirror::kClassFlagClassLoader:
+      return HeapGraphType::KIND_CLASSLOADER;
+    case art::mirror::kClassFlagDexCache:
+      return HeapGraphType::KIND_DEXCACHE;
+    case art::mirror::kClassFlagSoftReference:
+      return HeapGraphType::KIND_SOFT_REFERENCE;
+    case art::mirror::kClassFlagWeakReference:
+      return HeapGraphType::KIND_WEAK_REFERENCE;
+    case art::mirror::kClassFlagFinalizerReference:
+      return HeapGraphType::KIND_FINALIZER_REFERENCE;
+    case art::mirror::kClassFlagPhantomReference:
+      return HeapGraphType::KIND_PHANTOM_REFERENCE;
+    default:
+      return HeapGraphType::KIND_UNKNOWN;
   }
 }
 
@@ -460,6 +483,32 @@
   return reinterpret_cast<uint64_t>(obj) / std::alignment_of<art::mirror::Object>::value;
 }
 
+template <typename F>
+void ForInstanceReferenceField(art::mirror::Class* klass, F fn) NO_THREAD_SAFETY_ANALYSIS {
+  for (art::ArtField& af : klass->GetIFields()) {
+    if (af.IsPrimitiveType() ||
+        af.GetOffset().Uint32Value() == art::mirror::Object::ClassOffset().Uint32Value()) {
+      continue;
+    }
+    fn(af.GetOffset());
+  }
+}
+
+bool IsIgnored(const std::vector<std::string>& ignored_types,
+               art::mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS {
+  if (obj->IsClass()) {
+    return false;
+  }
+  art::mirror::Class* klass = obj->GetClass();
+  return std::find(ignored_types.begin(), ignored_types.end(), PrettyType(klass)) !=
+         ignored_types.end();
+}
+
+size_t EncodedSize(uint64_t n) {
+  if (n == 0) return 1;
+  return 1 + static_cast<size_t>(art::MostSignificantBit(n)) / 7;
+}
+
 void DumpPerfetto(art::Thread* self) {
   pid_t parent_pid = getpid();
   LOG(INFO) << "preparing to dump heap for " << parent_pid;
@@ -471,10 +520,14 @@
   // We need to do this before the fork, because otherwise it can deadlock
   // waiting for the GC, as all other threads get terminated by the clone, but
   // their locks are not released.
-  art::gc::ScopedGCCriticalSection gcs(self, art::gc::kGcCauseHprof,
-                                       art::gc::kCollectorTypeHprof);
+  // This does not perfectly solve all fork-related issues, as there could still be threads that
+  // are unaffected by ScopedSuspendAll and in a non-fork-friendly situation
+  // (e.g. inside a malloc holding a lock). This situation is quite rare, and in that case we will
+  // hit the watchdog in the grand-child process if it gets stuck.
+  std::optional<art::gc::ScopedGCCriticalSection> gcs(std::in_place, self, art::gc::kGcCauseHprof,
+                                                      art::gc::kCollectorTypeHprof);
 
-  art::ScopedSuspendAll ssa(__FUNCTION__, /* long_suspend=*/ true);
+  std::optional<art::ScopedSuspendAll> ssa(std::in_place, __FUNCTION__, /* long_suspend=*/ true);
 
   pid_t pid = fork();
   if (pid == -1) {
@@ -484,17 +537,49 @@
   }
   if (pid != 0) {
     // Parent
-    int stat_loc;
-    for (;;) {
-      if (waitpid(pid, &stat_loc, 0) != -1 || errno != EINTR) {
+    // Stop the thread suspension as soon as possible to allow the rest of the application to
+    // continue while we waitpid here.
+    ssa.reset();
+    gcs.reset();
+    for (size_t i = 0;; ++i) {
+      if (i == 1000) {
+        // The child hasn't exited for 1 second (and all it was supposed to do was fork itself).
+        // Give up and SIGKILL it. The next waitpid should succeed.
+        LOG(ERROR) << "perfetto_hprof child timed out. Sending SIGKILL.";
+        kill(pid, SIGKILL);
+      }
+      // Busy waiting here will introduce some extra latency, but that is okay because we have
+      // already unsuspended all other threads. This runs on the perfetto_hprof_listener, which
+      // is not needed for progress of the app itself.
+      int stat_loc;
+      pid_t wait_result = waitpid(pid, &stat_loc, WNOHANG);
+      if (wait_result == -1 && errno != EINTR) {
+        if (errno != ECHILD) {
+          // This hopefully never happens (should only be EINVAL).
+          PLOG(FATAL_WITHOUT_ABORT) << "waitpid";
+        }
+        // If we get ECHILD, the parent process was handling SIGCHLD, or did a wildcard wait.
+        // The child is no longer here either way, so that's good enough for us.
         break;
+      } else if (wait_result > 0) {
+        break;
+      } else {  // wait_result == 0 || errno == EINTR.
+        usleep(1000);
       }
     }
     return;
   }
 
   // The following code is only executed by the child of the original process.
-  //
+
+  // Uninstall signal handler, so we don't trigger a profile on it.
+  if (sigaction(kJavaHeapprofdSignal, &g_orig_act, nullptr) != 0) {
+    close(g_signal_pipe_fds[0]);
+    close(g_signal_pipe_fds[1]);
+    PLOG(FATAL) << "Failed to sigaction";
+    return;
+  }
+
   // Daemon creates a new process that is the grand-child of the original process, and exits.
   if (daemon(0, 0) == -1) {
     PLOG(FATAL) << "daemon";
@@ -518,13 +603,16 @@
       [parent_pid, timestamp](JavaHprofDataSource::TraceContext ctx)
           NO_THREAD_SAFETY_ANALYSIS {
             bool dump_smaps;
+            std::vector<std::string> ignored_types;
             {
               auto ds = ctx.GetDataSourceLocked();
               if (!ds || !ds->enabled()) {
+                if (ds) ds->Finish();
                 LOG(INFO) << "skipping irrelevant data source.";
                 return;
               }
               dump_smaps = ds->dump_smaps();
+              ignored_types = ds->ignored_types();
             }
             LOG(INFO) << "dumping heap for " << parent_pid;
             if (dump_smaps) {
@@ -566,9 +654,11 @@
             std::unique_ptr<protozero::PackedVarInt> reference_object_ids(
                 new protozero::PackedVarInt);
 
+            uint64_t prev_object_id = 0;
+
             art::Runtime::Current()->GetHeap()->VisitObjectsPaused(
-                [&writer, &interned_fields, &interned_locations,
-                &reference_field_ids, &reference_object_ids, &interned_classes](
+                [&writer, &interned_fields, &interned_locations, &reference_field_ids,
+                 &reference_object_ids, &interned_classes, &ignored_types, &prev_object_id](
                     art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
                   if (obj->IsClass()) {
                     art::mirror::Class* klass = obj->AsClass().Ptr();
@@ -579,6 +669,24 @@
                     type_proto->set_class_name(PrettyType(klass));
                     type_proto->set_location_id(FindOrAppend(&interned_locations,
                           klass->GetLocation()));
+                    type_proto->set_object_size(klass->GetObjectSize());
+                    type_proto->set_kind(ProtoClassKind(klass->GetClassFlags()));
+                    type_proto->set_classloader_id(GetObjectId(klass->GetClassLoader().Ptr()));
+                    if (klass->GetSuperClass().Ptr()) {
+                      type_proto->set_superclass_id(
+                        FindOrAppend(&interned_classes,
+                                     reinterpret_cast<uintptr_t>(klass->GetSuperClass().Ptr())));
+                    }
+                    ForInstanceReferenceField(
+                        klass, [klass, &reference_field_ids, &interned_fields](
+                                   art::MemberOffset offset) NO_THREAD_SAFETY_ANALYSIS {
+                          auto art_field = art::ArtField::FindInstanceFieldWithOffset(
+                              klass, offset.Uint32Value());
+                          reference_field_ids->Append(
+                              FindOrAppend(&interned_fields, art_field->PrettyField(true)));
+                        });
+                    type_proto->set_reference_field_id(*reference_field_ids);
+                    reference_field_ids->Reset();
                   }
 
                   art::mirror::Class* klass = obj->GetClass();
@@ -600,38 +708,97 @@
                           obj->AsClass()->GetLocation()));
                   }
 
+                  if (IsIgnored(ignored_types, obj)) {
+                    return;
+                  }
+
                   auto class_id = FindOrAppend(&interned_classes, class_ptr);
 
+                  uint64_t object_id = GetObjectId(obj);
                   perfetto::protos::pbzero::HeapGraphObject* object_proto =
                     writer.GetHeapGraph()->add_objects();
-                  object_proto->set_id(GetObjectId(obj));
+                  if (prev_object_id && prev_object_id < object_id) {
+                    object_proto->set_id_delta(object_id - prev_object_id);
+                  } else {
+                    object_proto->set_id(object_id);
+                  }
+                  prev_object_id = object_id;
                   object_proto->set_type_id(class_id);
-                  object_proto->set_self_size(obj->SizeOf());
+
+                  // Arrays / strings are magic and have an instance dependent size.
+                  if (obj->SizeOf() != klass->GetObjectSize())
+                    object_proto->set_self_size(obj->SizeOf());
 
                   std::vector<std::pair<std::string, art::mirror::Object*>>
                       referred_objects;
-                  ReferredObjectsFinder objf(&referred_objects);
-                  obj->VisitReferences(objf, art::VoidFunctor());
-                  for (const auto& p : referred_objects) {
-                    reference_field_ids->Append(FindOrAppend(&interned_fields, p.first));
-                    reference_object_ids->Append(GetObjectId(p.second));
+                  art::mirror::Object* min_nonnull_ptr = nullptr;
+                  ReferredObjectsFinder objf(&referred_objects, &min_nonnull_ptr);
+
+                  const bool emit_field_ids =
+                      klass->GetClassFlags() != art::mirror::kClassFlagObjectArray &&
+                      klass->GetClassFlags() != art::mirror::kClassFlagNormal;
+                  if (klass->GetClassFlags() != art::mirror::kClassFlagNormal) {
+                    obj->VisitReferences(objf, art::VoidFunctor());
+                  } else {
+                    for (art::mirror::Class* cls = klass; cls != nullptr;
+                         cls = cls->GetSuperClass().Ptr()) {
+                      ForInstanceReferenceField(
+                          cls, [obj, objf](art::MemberOffset offset) NO_THREAD_SAFETY_ANALYSIS {
+                            objf(art::ObjPtr<art::mirror::Object>(obj), offset,
+                                 /*is_static=*/false);
+                          });
+                    }
                   }
-                  object_proto->set_reference_field_id(*reference_field_ids);
+
+                  uint64_t bytes_saved = 0;
+                  uint64_t base_obj_id = GetObjectId(min_nonnull_ptr);
+                  if (base_obj_id) {
+                    // We need to decrement the base for object ids so that we can tell apart
+                    // null references.
+                    base_obj_id--;
+                  }
+                  if (base_obj_id) {
+                    for (auto& p : referred_objects) {
+                      art::mirror::Object*& referred_obj = p.second;
+                      if (!referred_obj || IsIgnored(ignored_types, referred_obj)) {
+                        referred_obj = nullptr;
+                        continue;
+                      }
+                      uint64_t referred_obj_id = GetObjectId(referred_obj);
+                      bytes_saved +=
+                          EncodedSize(referred_obj_id) - EncodedSize(referred_obj_id - base_obj_id);
+                    }
+                  }
+
+                  // +1 for storing the field id.
+                  if (bytes_saved <= EncodedSize(base_obj_id) + 1) {
+                    // Subtracting the base ptr gains fewer bytes than it takes to store it.
+                    base_obj_id = 0;
+                  }
+
+                  for (auto& p : referred_objects) {
+                    const std::string& field_name = p.first;
+                    art::mirror::Object* referred_obj = p.second;
+                    if (emit_field_ids) {
+                      reference_field_ids->Append(FindOrAppend(&interned_fields, field_name));
+                    }
+                    uint64_t referred_obj_id = GetObjectId(referred_obj);
+                    if (referred_obj_id) {
+                      referred_obj_id -= base_obj_id;
+                    }
+                    reference_object_ids->Append(referred_obj_id);
+                  }
+                  if (emit_field_ids) {
+                    object_proto->set_reference_field_id(*reference_field_ids);
+                    reference_field_ids->Reset();
+                  }
+                  if (base_obj_id) {
+                    object_proto->set_reference_field_id_base(base_obj_id);
+                  }
                   object_proto->set_reference_object_id(*reference_object_ids);
-                  reference_field_ids->Reset();
                   reference_object_ids->Reset();
                 });
 
-            for (const auto& p : interned_fields) {
-              const std::string& str = p.first;
-              uint64_t id = p.second;
-
-              perfetto::protos::pbzero::InternedString* field_proto =
-                writer.GetHeapGraph()->add_field_names();
-              field_proto->set_iid(id);
-              field_proto->set_str(
-                  reinterpret_cast<const uint8_t*>(str.c_str()), str.size());
-            }
             for (const auto& p : interned_locations) {
               const std::string& str = p.first;
               uint64_t id = p.second;
@@ -642,9 +809,18 @@
               location_proto->set_str(reinterpret_cast<const uint8_t*>(str.c_str()),
                                   str.size());
             }
+            for (const auto& p : interned_fields) {
+              const std::string& str = p.first;
+              uint64_t id = p.second;
+
+              perfetto::protos::pbzero::InternedString* field_proto =
+                writer.GetHeapGraph()->add_field_names();
+              field_proto->set_iid(id);
+              field_proto->set_str(
+                  reinterpret_cast<const uint8_t*>(str.c_str()), str.size());
+            }
 
             writer.Finalize();
-
             ctx.Flush([] {
               {
                 art::MutexLock lk(JavaHprofDataSource::art_thread(), GetStateMutex());
@@ -652,16 +828,28 @@
                 GetStateCV().Broadcast(JavaHprofDataSource::art_thread());
               }
             });
+            // Wait for the Flush that will happen on the Perfetto thread.
+            {
+              art::MutexLock lk(JavaHprofDataSource::art_thread(), GetStateMutex());
+              while (g_state != State::kEnd) {
+                GetStateCV().Wait(JavaHprofDataSource::art_thread());
+              }
+            }
+            {
+              auto ds = ctx.GetDataSourceLocked();
+              if (ds) {
+                ds->Finish();
+              } else {
+                LOG(ERROR) << "datasource timed out (duration_ms + datasource_stop_timeout_ms) "
+                              "before dump finished";
+              }
+            }
           });
 
-  art::MutexLock lk(self, GetStateMutex());
-  while (g_state != State::kEnd) {
-    GetStateCV().Wait(self);
-  }
   LOG(INFO) << "finished dumping heap for " << parent_pid;
-  // Prevent the atexit handlers to run. We do not want to call cleanup
+  // Prevent the `atexit` handlers from running. We do not want to call cleanup
   // functions the parent process has registered.
-  _exit(0);
+  art::FastExit(0);
 }
 
 // The plugin initialization function.
@@ -686,7 +874,8 @@
 
   struct sigaction act = {};
   act.sa_flags = SA_SIGINFO | SA_RESTART;
-  act.sa_sigaction = [](int, siginfo_t*, void*) {
+  act.sa_sigaction = [](int, siginfo_t* si, void*) {
+    requested_tracing_session_id = si->si_value.sival_int;
     if (write(g_signal_pipe_fds[1], kByte, sizeof(kByte)) == -1) {
       PLOG(ERROR) << "Failed to trigger heap dump";
     }
diff --git a/perfetto_hprof/perfetto_hprof.h b/perfetto_hprof/perfetto_hprof.h
index 1713286..f02ef59 100644
--- a/perfetto_hprof/perfetto_hprof.h
+++ b/perfetto_hprof/perfetto_hprof.h
@@ -35,7 +35,7 @@
   kEnd,
 };
 
-std::ostream& operator<<(std::ostream&, const State&);
+std::ostream& operator<<(std::ostream& os, State state);
 
 }  // namespace perfetto_hprof
 
diff --git a/profman/Android.bp b/profman/Android.bp
index c574fde..917d79a 100644
--- a/profman/Android.bp
+++ b/profman/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "profman-defaults",
     host_supported: true,
@@ -26,29 +35,80 @@
 
     target: {
         android: {
-            // Use the 32-bit version of profman on devices.
-            compile_multilib: "prefer32",
+            compile_multilib: "first",
+            shared_libs: [
+                "libbase",
+            ],
+        },
+        host: {
+            whole_static_libs: [
+                "libbase",
+            ],
         },
         darwin: {
             enabled: true,
         },
     },
+}
 
-    shared_libs: [
-        "libbase",
+// Collect all the static defaults and build a host-only static library, which
+// is then used for the (mostly) static host profman binary.
+art_cc_library_static {
+    name: "libprofman_static",
+    device_supported: false,
+    host_supported: true,
+    defaults: [
+        "art_defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
+        "libprofile_static_defaults",
     ],
+    target: {
+        darwin: {
+            enabled: true,
+        },
+    },
+}
+
+art_cc_library_static {
+    name: "libprofmand_static",
+    device_supported: false,
+    host_supported: true,
+    defaults: [
+        "art_debug_defaults",
+        "art_defaults",
+        "libartbased_static_defaults",
+        "libdexfiled_static_defaults",
+        "libprofiled_static_defaults",
+    ],
+    target: {
+        darwin: {
+            enabled: true,
+        },
+    },
 }
 
 art_cc_binary {
     name: "profman",
     defaults: ["profman-defaults"],
-    shared_libs: [
-        "libprofile",
-        "libdexfile",
-        "libartbase",
-    ],
+    target: {
+        android: {
+            shared_libs: [
+                "libartbase",
+                "libdexfile",
+                "libprofile",
+            ],
+        },
+        host: {
+            // Make the host binary static, except for system libraries. This
+            // avoids having to bundle host dynamic libs in prebuilts.
+            static_libs: ["libprofman_static"],
+            stl: "c++_static",
+
+        },
+    },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -59,11 +119,22 @@
         "art_debug_defaults",
         "profman-defaults",
     ],
-    shared_libs: [
-        "libprofiled",
-        "libdexfiled",
-        "libartbased",
-    ],
+    target: {
+        android: {
+            shared_libs: [
+                "libartbased",
+                "libdexfiled",
+                "libprofiled",
+            ],
+        },
+        host: {
+            // Make the host binary static, except for system libraries. This
+            // avoids having to bundle host dynamic libs in prebuilts.
+            static_libs: ["libprofmand_static"],
+            stl: "c++_static",
+
+        },
+    },
     apex_available: [
         "com.android.art.debug",
     ],
@@ -90,13 +161,46 @@
     },
 }
 
+art_cc_defaults {
+    name: "art_profman_tests_defaults",
+    data: [
+        ":art-gtest-jars-ProfileTestMultiDex",
+    ],
+    srcs: ["profile_assistant_test.cc"],
+}
+
+// Version of ART gtest `art_profman_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
 art_cc_test {
     name: "art_profman_tests",
     defaults: [
         "art_gtest_defaults",
+        "art_profman_tests_defaults",
     ],
     shared_libs: [
         "libprofiled",
     ],
-    srcs: ["profile_assistant_test.cc"],
+    target: {
+        host: {
+            required: ["profmand"],
+        },
+    },
+}
+
+// Standalone version of ART gtest `art_profman_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_profman_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_profman_tests_defaults",
+    ],
+    shared_libs: [
+        "libprofile",
+    ],
+    target: {
+        host: {
+            required: ["profman"],
+        },
+    },
+    test_config_template: "art_standalone_profman_tests.xml",
 }
diff --git a/profman/art_standalone_profman_tests.xml b/profman/art_standalone_profman_tests.xml
new file mode 100644
index 0000000..31bee91
--- /dev/null
+++ b/profman/art_standalone_profman_tests.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs art_standalone_profman_tests (as root).">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art_standalone_profman_tests->/data/local/tmp/nativetest/art_standalone_profman_tests" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art-gtest-jars-ProfileTestMultiDex.jar->/data/local/tmp/nativetest/art-gtest-jars-ProfileTestMultiDex.jar" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/nativetest" />
+        <option name="module-name" value="art_standalone_profman_tests" />
+        <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+        <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+
+        <!-- The following tests from `art_standalone_profman_tests` are currently failing when
+             run as 32-bit on a 64-bit device, because they try to execute other system (64-bit)
+             processes but `LD_LIBRARY_PATH` is set to a directory of 32-bit libraries which make
+             them fail to dynamically link to the expected (64-bit) libraries.
+
+             TODO(b/162834439): Investigate these failures and re-enable these tests. -->
+        <option name="exclude-filter" value="ProfileAssistantTest.TestProfileRoundTrip" />
+        <option name="exclude-filter" value="ProfileAssistantTest.TestProfileRoundTripWithAnnotations" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/profman/boot_image_profile.cc b/profman/boot_image_profile.cc
index 3f9665f..fc20f20 100644
--- a/profman/boot_image_profile.cc
+++ b/profman/boot_image_profile.cc
@@ -189,9 +189,9 @@
                                       uint32_t max_aggregation_count,
                                       const FlattenProfileData::ItemMetadata& metadata,
                                       const BootImageOptions& options) {
-  bool blacklisted = options.preloaded_classes_blacklist.find(class_name) !=
-      options.preloaded_classes_blacklist.end();
-  return !blacklisted && IncludeItemInProfile(
+  bool denylisted = options.preloaded_classes_denylist.find(class_name) !=
+      options.preloaded_classes_denylist.end();
+  return !denylisted && IncludeItemInProfile(
       max_aggregation_count, options.preloaded_class_threshold, metadata, options);
 }
 
@@ -210,7 +210,7 @@
 
   std::unique_ptr<FlattenProfileData> flattend_data(new FlattenProfileData());
   for (const std::string& profile_file : profile_files) {
-    ProfileCompilationInfo profile;
+    ProfileCompilationInfo profile(/*for_boot_image=*/ true);
     if (!profile.Load(profile_file, /*clear_if_invalid=*/ false)) {
       LOG(ERROR) << "Profile is not a valid: " << profile_file;
       return false;
diff --git a/profman/boot_image_profile.h b/profman/boot_image_profile.h
index a3dd52c..19cdb2f 100644
--- a/profman/boot_image_profile.h
+++ b/profman/boot_image_profile.h
@@ -66,7 +66,7 @@
   bool append_package_use_list = false;
 
   // The set of classes that should not be preloaded in Zygote
-  std::set<std::string> preloaded_classes_blacklist;
+  std::set<std::string> preloaded_classes_denylist;
 };
 
 // Generate a boot image profile according to the specified options.
diff --git a/profman/profile_assistant.cc b/profman/profile_assistant.cc
index 1695d8c..d098738 100644
--- a/profman/profile_assistant.cc
+++ b/profman/profile_assistant.cc
@@ -24,9 +24,7 @@
 // Minimum number of new methods/classes that profiles
 // must contain to enable recompilation.
 static constexpr const uint32_t kMinNewMethodsForCompilation = 100;
-static constexpr const uint32_t kMinNewMethodsPercentChangeForCompilation = 2;
 static constexpr const uint32_t kMinNewClassesForCompilation = 50;
-static constexpr const uint32_t kMinNewClassesPercentChangeForCompilation = 2;
 
 
 ProfileAssistant::ProcessingResult ProfileAssistant::ProcessProfilesInternal(
@@ -55,7 +53,7 @@
 
   // Merge all current profiles.
   for (size_t i = 0; i < profile_files.size(); i++) {
-    ProfileCompilationInfo cur_info;
+    ProfileCompilationInfo cur_info(options.IsBootImageMerge());
     if (!cur_info.Load(profile_files[i]->Fd(), /*merge_classes=*/ true, filter_fn)) {
       LOG(WARNING) << "Could not load profile file at index " << i;
       if (options.IsForceMerge()) {
@@ -64,22 +62,12 @@
         // cleared lazily.
         continue;
       }
-      return kErrorBadProfiles;
-    }
-
-    // Check version mismatch.
-    // This may happen during profile analysis if one profile is regular and
-    // the other one is for the boot image. For example when switching on-off
-    // the boot image profiles.
-    if (!info.SameVersion(cur_info)) {
-      if (options.IsForceMerge()) {
-        // If we have to merge forcefully, ignore the current profile and
-        // continue to the next one.
-        continue;
-      } else {
-        // Otherwise, return an error.
+      // TODO: Do we really need to use a different error code for version mismatch?
+      ProfileCompilationInfo wrong_info(!options.IsBootImageMerge());
+      if (wrong_info.Load(profile_files[i]->Fd(), /*merge_classes=*/ true, filter_fn)) {
         return kErrorDifferentVersions;
       }
+      return kErrorBadProfiles;
     }
 
     if (!info.MergeWith(cur_info)) {
@@ -90,17 +78,20 @@
 
   // If we perform a forced merge do not analyze the difference between profiles.
   if (!options.IsForceMerge()) {
+    if (info.IsEmpty()) {
+      return kSkipCompilationEmptyProfiles;
+    }
     uint32_t min_change_in_methods_for_compilation = std::max(
-        (kMinNewMethodsPercentChangeForCompilation * number_of_methods) / 100,
+        (options.GetMinNewMethodsPercentChangeForCompilation() * number_of_methods) / 100,
         kMinNewMethodsForCompilation);
     uint32_t min_change_in_classes_for_compilation = std::max(
-        (kMinNewClassesPercentChangeForCompilation * number_of_classes) / 100,
+        (options.GetMinNewClassesPercentChangeForCompilation() * number_of_classes) / 100,
         kMinNewClassesForCompilation);
     // Check if there is enough new information added by the current profiles.
     if (((info.GetNumberOfMethods() - number_of_methods) < min_change_in_methods_for_compilation) &&
         ((info.GetNumberOfResolvedClasses() - number_of_classes)
             < min_change_in_classes_for_compilation)) {
-      return kSkipCompilation;
+      return kSkipCompilationSmallDelta;
     }
   }
 
diff --git a/profman/profile_assistant.h b/profman/profile_assistant.h
index 9aa0768..0ef4f88 100644
--- a/profman/profile_assistant.h
+++ b/profman/profile_assistant.h
@@ -32,28 +32,47 @@
   enum ProcessingResult {
     kSuccess = 0,  // Generic success code for non-analysis runs.
     kCompile = 1,
-    kSkipCompilation = 2,
+    kSkipCompilationSmallDelta = 2,
     kErrorBadProfiles = 3,
     kErrorIO = 4,
     kErrorCannotLock = 5,
     kErrorDifferentVersions = 6,
+    kSkipCompilationEmptyProfiles = 7,
   };
 
   class Options {
    public:
     static constexpr bool kForceMergeDefault = false;
     static constexpr bool kBootImageMergeDefault = false;
+    static constexpr uint32_t kMinNewMethodsPercentChangeForCompilation = 20;
+    static constexpr uint32_t kMinNewClassesPercentChangeForCompilation = 20;
 
     Options()
         : force_merge_(kForceMergeDefault),
-          boot_image_merge_(kBootImageMergeDefault) {
+          boot_image_merge_(kBootImageMergeDefault),
+          min_new_methods_percent_change_for_compilation_(
+              kMinNewMethodsPercentChangeForCompilation),
+          min_new_classes_percent_change_for_compilation_(
+              kMinNewClassesPercentChangeForCompilation) {
     }
 
     bool IsForceMerge() const { return force_merge_; }
     bool IsBootImageMerge() const { return boot_image_merge_; }
+    uint32_t GetMinNewMethodsPercentChangeForCompilation() const {
+        return min_new_methods_percent_change_for_compilation_;
+    }
+    uint32_t GetMinNewClassesPercentChangeForCompilation() const {
+        return min_new_classes_percent_change_for_compilation_;
+    }
 
     void SetForceMerge(bool value) { force_merge_ = value; }
     void SetBootImageMerge(bool value) { boot_image_merge_ = value; }
+    void SetMinNewMethodsPercentChangeForCompilation(uint32_t value) {
+      min_new_methods_percent_change_for_compilation_ = value;
+    }
+    void SetMinNewClassesPercentChangeForCompilation(uint32_t value) {
+      min_new_classes_percent_change_for_compilation_ = value;
+    }
 
    private:
     // If true, performs a forced merge, without analyzing if there is a
@@ -63,6 +82,8 @@
     // Signals that the merge is for boot image profiles. It will ignore differences
     // in profile versions (instead of aborting).
     bool boot_image_merge_;
+    uint32_t min_new_methods_percent_change_for_compilation_;
+    uint32_t min_new_classes_percent_change_for_compilation_;
   };
 
   // Process the profile information present in the given files. Returns one of
@@ -75,10 +96,11 @@
   // reference_profile will be updated with the profiling info obtain after
   // merging all profiles.
   //
-  // When the returned value is kSkipCompilation, the difference between the
-  // merge of the current profiles and the reference one is insignificant. In
-  // this case no file will be updated.
-  //
+  // When the returned value is kSkipCompilationSmallDelta, the difference between
+  // the merge of the current profiles and the reference one is insignificant. In
+  // this case no file will be updated. A variation of this code is
+  // kSkipCompilationEmptyProfiles which indicates that all the profiles are empty.
+  // This allow the caller to make fine grain decisions on the compilation strategy.
   static ProcessingResult ProcessProfiles(
       const std::vector<std::string>& profile_files,
       const std::string& reference_profile_file,
diff --git a/profman/profile_assistant_test.cc b/profman/profile_assistant_test.cc
index 2f3f58d..f446c09 100644
--- a/profman/profile_assistant_test.cc
+++ b/profman/profile_assistant_test.cc
@@ -15,73 +15,51 @@
  */
 
 #include <gtest/gtest.h>
+#include <sstream>
+#include <string>
 
 #include "android-base/file.h"
 #include "android-base/strings.h"
 #include "art_method-inl.h"
+#include "base/globals.h"
 #include "base/unix_file/fd_file.h"
 #include "base/utils.h"
 #include "common_runtime_test.h"
 #include "dex/descriptors_names.h"
+#include "dex/dex_file_structs.h"
+#include "dex/dex_instruction-inl.h"
+#include "dex/dex_instruction_iterator.h"
 #include "dex/type_reference.h"
 #include "exec_utils.h"
 #include "linear_alloc.h"
 #include "mirror/class-inl.h"
 #include "obj_ptr-inl.h"
 #include "profile/profile_compilation_info.h"
+#include "profile/profile_test_helper.h"
 #include "profile_assistant.h"
 #include "scoped_thread_state_change-inl.h"
 
 namespace art {
 
-using Hotness = ProfileCompilationInfo::MethodHotness;
 using TypeReferenceSet = std::set<TypeReference, TypeReferenceValueComparator>;
-using ProfileInlineCache = ProfileMethodInfo::ProfileInlineCache;
 
 // TODO(calin): These tests share a lot with the ProfileCompilationInfo tests.
 // we should introduce a better abstraction to extract the common parts.
-class ProfileAssistantTest : public CommonRuntimeTest {
+class ProfileAssistantTest : public CommonRuntimeTest, public ProfileTestHelper {
  public:
   void PostRuntimeCreate() override {
     allocator_.reset(new ArenaAllocator(Runtime::Current()->GetArenaPool()));
 
-    dex1 = fake_dex_storage.AddFakeDex("location1", /* checksum= */ 1, /* num_method_ids= */ 10001);
-    dex2 = fake_dex_storage.AddFakeDex("location2", /* checksum= */ 2, /* num_method_ids= */ 10002);
-    dex3 = fake_dex_storage.AddFakeDex("location3", /* checksum= */ 3, /* num_method_ids= */ 10003);
-    dex4 = fake_dex_storage.AddFakeDex("location4", /* checksum= */ 4, /* num_method_ids= */ 10004);
+    dex1 = BuildDex("location1", /*checksum=*/ 1, "LUnique1;", /*num_method_ids=*/ 10001);
+    dex2 = BuildDex("location2", /*checksum=*/ 2, "LUnique2;", /*num_method_ids=*/ 10002);
+    dex3 = BuildDex("location3", /*checksum=*/ 3, "LUnique3;", /*num_method_ids=*/ 10003);
+    dex4 = BuildDex("location4", /*checksum=*/ 4, "LUnique4;", /*num_method_ids=*/ 10004);
 
-    dex1_checksum_missmatch = fake_dex_storage.AddFakeDex(
-        "location1", /* checksum= */ 12, /* num_method_ids= */ 10001);
+    dex1_checksum_missmatch =
+        BuildDex("location1", /*checksum=*/ 12, "LUnique1;", /*num_method_ids=*/ 10001);
   }
 
  protected:
-  bool AddMethod(ProfileCompilationInfo* info,
-                const DexFile* dex,
-                uint16_t method_idx,
-                const std::vector<ProfileInlineCache>& inline_caches,
-                Hotness::Flag flags) {
-    return info->AddMethod(
-        ProfileMethodInfo(MethodReference(dex, method_idx), inline_caches), flags);
-  }
-
-  bool AddMethod(ProfileCompilationInfo* info,
-                 const DexFile* dex,
-                 uint16_t method_idx,
-                 Hotness::Flag flags,
-                 const ProfileCompilationInfo::ProfileSampleAnnotation& annotation
-                    = ProfileCompilationInfo::ProfileSampleAnnotation::kNone) {
-    return info->AddMethod(ProfileMethodInfo(MethodReference(dex, method_idx)),
-                           flags,
-                           annotation);
-  }
-
-  bool AddClass(ProfileCompilationInfo* info,
-                const DexFile* dex,
-                dex::TypeIndex type_index) {
-    std::vector<dex::TypeIndex> classes = {type_index};
-    return info->AddClassesForDex(dex, classes.begin(), classes.end());
-  }
-
   void SetupProfile(const DexFile* dex_file1,
                     const DexFile* dex_file2,
                     uint16_t number_of_methods,
@@ -93,9 +71,10 @@
     for (uint16_t i = start_method_index; i < start_method_index + number_of_methods; i++) {
       // reverse_dex_write_order controls the order in which the dex files will be added to
       // the profile and thus written to disk.
-      std::vector<ProfileInlineCache> inline_caches = GetTestInlineCaches(dex_file1 , dex_file2, dex3);
-      Hotness::Flag flags = static_cast<Hotness::Flag>(
-          Hotness::kFlagHot | Hotness::kFlagPostStartup);
+      std::vector<ProfileInlineCache> inline_caches =
+          GetTestInlineCaches(dex_file1, dex_file2, dex3);
+      Hotness::Flag flags =
+          static_cast<Hotness::Flag>(Hotness::kFlagHot | Hotness::kFlagPostStartup);
       if (reverse_dex_write_order) {
         ASSERT_TRUE(AddMethod(info, dex_file2, i, inline_caches, flags));
         ASSERT_TRUE(AddMethod(info, dex_file1, i, inline_caches, flags));
@@ -110,7 +89,6 @@
 
     ASSERT_TRUE(info->Save(GetFd(profile)));
     ASSERT_EQ(0, profile.GetFile()->Flush());
-    ASSERT_TRUE(profile.GetFile()->ResetOffset());
   }
 
   void SetupBasicProfile(const DexFile* dex,
@@ -130,7 +108,6 @@
     }
     ASSERT_TRUE(info->Save(GetFd(profile)));
     ASSERT_EQ(0, profile.GetFile()->Flush());
-    ASSERT_TRUE(profile.GetFile()->ResetOffset());
   }
 
   // The dex1_substitute can be used to replace the default dex1 file.
@@ -176,7 +153,6 @@
 
   void CheckProfileInfo(ScratchFile& file, const ProfileCompilationInfo& info) {
     ProfileCompilationInfo file_info;
-    ASSERT_TRUE(file.GetFile()->ResetOffset());
     ASSERT_TRUE(file_info.Load(GetFd(file)));
     ASSERT_TRUE(file_info.Equals(info));
   }
@@ -231,41 +207,42 @@
 
   bool CreateProfile(const std::string& profile_file_contents,
                      const std::string& filename,
-                     const std::string& dex_location) {
+                     const std::string& dex_location,
+                     bool for_boot_image = false) {
     ScratchFile class_names_file;
     File* file = class_names_file.GetFile();
     EXPECT_TRUE(file->WriteFully(profile_file_contents.c_str(), profile_file_contents.length()));
     EXPECT_EQ(0, file->Flush());
-    EXPECT_TRUE(file->ResetOffset());
     std::string profman_cmd = GetProfmanCmd();
     std::vector<std::string> argv_str;
     argv_str.push_back(profman_cmd);
+    argv_str.push_back(for_boot_image ? "--output-profile-type=boot" : "--output-profile-type=app");
     argv_str.push_back("--create-profile-from=" + class_names_file.GetFilename());
     argv_str.push_back("--reference-profile-file=" + filename);
     argv_str.push_back("--apk=" + dex_location);
     argv_str.push_back("--dex-location=" + dex_location);
     std::string error;
-    EXPECT_EQ(ExecAndReturnCode(argv_str, &error), 0);
+    EXPECT_EQ(ExecAndReturnCode(argv_str, &error), 0) << error;
     return true;
   }
 
   bool RunProfman(const std::string& filename,
                   std::vector<std::string>& extra_args,
-                  std::string* output) {
+                  std::string* output,
+                  std::string_view target_apk) {
     ScratchFile output_file;
     std::string profman_cmd = GetProfmanCmd();
     std::vector<std::string> argv_str;
     argv_str.push_back(profman_cmd);
     argv_str.insert(argv_str.end(), extra_args.begin(), extra_args.end());
     argv_str.push_back("--profile-file=" + filename);
-    argv_str.push_back("--apk=" + GetLibCoreDexFileNames()[0]);
-    argv_str.push_back("--dex-location=" + GetLibCoreDexFileNames()[0]);
+    argv_str.push_back(std::string("--apk=").append(target_apk));
+    argv_str.push_back(std::string("--dex-location=").append(target_apk));
     argv_str.push_back("--dump-output-to-fd=" + std::to_string(GetFd(output_file)));
     std::string error;
-    EXPECT_EQ(ExecAndReturnCode(argv_str, &error), 0);
+    EXPECT_EQ(ExecAndReturnCode(argv_str, &error), 0) << error;
     File* file = output_file.GetFile();
     EXPECT_EQ(0, file->Flush());
-    EXPECT_TRUE(file->ResetOffset());
     int64_t length = file->GetLength();
     std::unique_ptr<char[]> buf(new char[length]);
     EXPECT_EQ(file->Read(buf.get(), length, 0), length);
@@ -273,26 +250,29 @@
     return true;
   }
 
-  bool DumpClassesAndMethods(const std::string& filename, std::string* file_contents) {
+  bool DumpClassesAndMethods(const std::string& filename,
+                             std::string* file_contents,
+                             std::optional<const std::string_view> target = std::nullopt) {
     std::vector<std::string> extra_args;
     extra_args.push_back("--dump-classes-and-methods");
-    return RunProfman(filename, extra_args, file_contents);
+    return RunProfman(
+        filename, extra_args, file_contents, target.value_or(GetLibCoreDexFileNames()[0]));
   }
 
   bool DumpOnly(const std::string& filename, std::string* file_contents) {
     std::vector<std::string> extra_args;
     extra_args.push_back("--dump-only");
-    return RunProfman(filename, extra_args, file_contents);
+    return RunProfman(filename, extra_args, file_contents, GetLibCoreDexFileNames()[0]);
   }
 
   bool CreateAndDump(const std::string& input_file_contents,
-                     std::string* output_file_contents) {
+                     std::string* output_file_contents,
+                     std::optional<const std::string> target = std::nullopt) {
     ScratchFile profile_file;
     EXPECT_TRUE(CreateProfile(input_file_contents,
                               profile_file.GetFilename(),
-                              GetLibCoreDexFileNames()[0]));
-    profile_file.GetFile()->ResetOffset();
-    EXPECT_TRUE(DumpClassesAndMethods(profile_file.GetFilename(), output_file_contents));
+                              target.value_or(GetLibCoreDexFileNames()[0])));
+    EXPECT_TRUE(DumpClassesAndMethods(profile_file.GetFilename(), output_file_contents, target));
     return true;
   }
 
@@ -328,30 +308,102 @@
     return TypeReference(&klass->GetDexFile(), klass->GetDexTypeIndex());
   }
 
-  // Verify that given method has the expected inline caches and nothing else.
+  // Find the first dex-pc in the given method after 'start_pc' (if given) which
+  // contains a call to any method of 'klass'. If 'start_pc' is not given we
+  // will search from the first dex-pc.
+  uint16_t GetDexPcOfCallTo(ArtMethod* method,
+                            Handle<mirror::Class> klass,
+                            std::optional<uint32_t> start_pc = std::nullopt)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    const DexFile* dex_file = method->GetDexFile();
+    for (const DexInstructionPcPair& inst :
+         CodeItemInstructionAccessor(*dex_file, method->GetCodeItem())) {
+      if (start_pc && inst.DexPc() <= *start_pc) {
+        continue;
+      } else if (inst->IsInvoke()) {
+        const dex::MethodId& method_id = dex_file->GetMethodId(inst->VRegB());
+        std::string_view desc(
+            dex_file->GetTypeDescriptor(dex_file->GetTypeId(method_id.class_idx_)));
+        std::string scratch;
+        if (desc == klass->GetDescriptor(&scratch)) {
+          return inst.DexPc();
+        }
+      }
+    }
+    EXPECT_TRUE(false) << "Unable to find dex-pc in " << method->PrettyMethod() << " for call to "
+                       << klass->PrettyClass()
+                       << " after dexpc: " << (start_pc ? static_cast<int64_t>(*start_pc) : -1);
+    return -1;
+  }
+
   void AssertInlineCaches(ArtMethod* method,
-                          const TypeReferenceSet& expected_clases,
+                          uint16_t dex_pc,
+                          const TypeReferenceSet& expected_classes,
                           const ProfileCompilationInfo& info,
                           bool is_megamorphic,
                           bool is_missing_types)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> pmi =
-        info.GetHotMethodInfo(MethodReference(
-            method->GetDexFile(), method->GetDexMethodIndex()));
-    ASSERT_TRUE(pmi != nullptr);
-    ASSERT_EQ(pmi->inline_caches->size(), 1u);
-    const ProfileCompilationInfo::DexPcData& dex_pc_data = pmi->inline_caches->begin()->second;
+    ProfileCompilationInfo::MethodHotness hotness =
+        info.GetMethodHotness(MethodReference(method->GetDexFile(), method->GetDexMethodIndex()));
+    ASSERT_TRUE(hotness.IsHot());
+    const ProfileCompilationInfo::InlineCacheMap* inline_caches = hotness.GetInlineCacheMap();
+    ASSERT_TRUE(inline_caches->find(dex_pc) != inline_caches->end());
+    AssertInlineCaches(expected_classes,
+                       info,
+                       method,
+                       inline_caches->find(dex_pc)->second,
+                       is_megamorphic,
+                       is_missing_types);
+  }
+  void AssertInlineCaches(ArtMethod* method,
+                          const TypeReferenceSet& expected_classes,
+                          const ProfileCompilationInfo& info,
+                          bool is_megamorphic,
+                          bool is_missing_types)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    ProfileCompilationInfo::MethodHotness hotness =
+        info.GetMethodHotness(MethodReference(method->GetDexFile(), method->GetDexMethodIndex()));
+    ASSERT_TRUE(hotness.IsHot());
+    const ProfileCompilationInfo::InlineCacheMap* inline_caches = hotness.GetInlineCacheMap();
+    ASSERT_EQ(inline_caches->size(), 1u);
+    AssertInlineCaches(expected_classes,
+                       info,
+                       method,
+                       inline_caches->begin()->second,
+                       is_megamorphic,
+                       is_missing_types);
+  }
 
+  void AssertInlineCaches(const TypeReferenceSet& expected_clases,
+                          const ProfileCompilationInfo& info,
+                          ArtMethod* method,
+                          const ProfileCompilationInfo::DexPcData& dex_pc_data,
+                          bool is_megamorphic,
+                          bool is_missing_types)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
     ASSERT_EQ(dex_pc_data.is_megamorphic, is_megamorphic);
     ASSERT_EQ(dex_pc_data.is_missing_types, is_missing_types);
     ASSERT_EQ(expected_clases.size(), dex_pc_data.classes.size());
+    const DexFile* dex_file = method->GetDexFile();
     size_t found = 0;
     for (const TypeReference& type_ref : expected_clases) {
-      for (const auto& class_ref : dex_pc_data.classes) {
-        ProfileCompilationInfo::DexReference dex_ref =
-            pmi->dex_references[class_ref.dex_profile_index];
-        if (dex_ref.MatchesDex(type_ref.dex_file) && class_ref.type_index == type_ref.TypeIndex()) {
-          found++;
+      if (type_ref.dex_file == dex_file) {
+        CHECK_LT(type_ref.TypeIndex().index_, dex_file->NumTypeIds());
+        for (dex::TypeIndex type_index : dex_pc_data.classes) {
+          ASSERT_TRUE(type_index.IsValid());
+          if (type_ref.TypeIndex() == type_index) {
+            ++found;
+          }
+        }
+      } else {
+        // Match by descriptor.
+        const char* expected_descriptor = type_ref.dex_file->StringByTypeIdx(type_ref.TypeIndex());
+        for (dex::TypeIndex type_index : dex_pc_data.classes) {
+          ASSERT_TRUE(type_index.IsValid());
+          const char* descriptor = info.GetTypeDescriptor(dex_file, type_index);
+          if (strcmp(expected_descriptor, descriptor) == 0) {
+            ++found;
+          }
         }
       }
     }
@@ -360,7 +412,9 @@
   }
 
   int CheckCompilationMethodPercentChange(uint16_t methods_in_cur_profile,
-                                          uint16_t methods_in_ref_profile) {
+                                          uint16_t methods_in_ref_profile,
+                                          const std::vector<const std::string>& extra_args =
+                                              std::vector<const std::string>()) {
     ScratchFile profile;
     ScratchFile reference_profile;
     std::vector<int> profile_fds({ GetFd(profile)});
@@ -380,11 +434,19 @@
     ProfileCompilationInfo info2;
     SetupBasicProfile(dex1, hot_methods_ref, empty_vector, empty_vector,
         reference_profile,  &info2);
-    return ProcessProfiles(profile_fds, reference_profile_fd);
+    return ProcessProfiles(profile_fds, reference_profile_fd, extra_args);
   }
 
   int CheckCompilationClassPercentChange(uint16_t classes_in_cur_profile,
-                                         uint16_t classes_in_ref_profile) {
+                                         uint16_t classes_in_ref_profile,
+                                         const std::vector<const std::string>& extra_args =
+                                             std::vector<const std::string>()) {
+    uint16_t max_classes = std::max(classes_in_cur_profile, classes_in_ref_profile);
+    const DexFile* dex1_x = BuildDex(
+        "location1_x", /*checksum=*/ 0x101, "LUnique1_x;", /*num_method_ids=*/ 0, max_classes);
+    const DexFile* dex2_x = BuildDex(
+        "location2_x", /*checksum=*/ 0x102, "LUnique2_x;", /*num_method_ids=*/ 0, max_classes);
+
     ScratchFile profile;
     ScratchFile reference_profile;
 
@@ -392,10 +454,10 @@
     int reference_profile_fd = GetFd(reference_profile);
 
     ProfileCompilationInfo info1;
-    SetupProfile(dex1, dex2, 0, classes_in_cur_profile, profile,  &info1);
+    SetupProfile(dex1_x, dex2_x, 0, classes_in_cur_profile, profile,  &info1);
     ProfileCompilationInfo info2;
-    SetupProfile(dex1, dex2, 0, classes_in_ref_profile, reference_profile, &info2);
-    return ProcessProfiles(profile_fds, reference_profile_fd);
+    SetupProfile(dex1_x, dex2_x, 0, classes_in_ref_profile, reference_profile, &info2);
+    return ProcessProfiles(profile_fds, reference_profile_fd, extra_args);
   }
 
   std::unique_ptr<ArenaAllocator> allocator_;
@@ -405,7 +467,6 @@
   const DexFile* dex3;
   const DexFile* dex4;
   const DexFile* dex1_checksum_missmatch;
-  FakeDexStorage fake_dex_storage;
 };
 
 TEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferences) {
@@ -429,7 +490,6 @@
             ProcessProfiles(profile_fds, reference_profile_fd));
   // The resulting compilation info must be equal to the merge of the inputs.
   ProfileCompilationInfo result;
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
   ASSERT_TRUE(result.Load(reference_profile_fd));
 
   ProfileCompilationInfo expected;
@@ -444,6 +504,18 @@
 
 // TODO(calin): Add more tests for classes.
 TEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferencesBecauseOfClasses) {
+  const uint16_t kNumberOfClassesToEnableCompilation = 100;
+  const DexFile* dex1_100 = BuildDex("location1_100",
+                                     /*checksum=*/ 101,
+                                     "LUnique1_100;",
+                                     /*num_method_ids=*/ 0,
+                                     /*num_type_ids=*/ 100);
+  const DexFile* dex2_100 = BuildDex("location2_100",
+                                     /*checksum=*/ 102,
+                                     "LUnique2_100;",
+                                     /*num_method_ids=*/ 0,
+                                     /*num_type_ids=*/ 100);
+
   ScratchFile profile1;
   ScratchFile reference_profile;
 
@@ -451,16 +523,14 @@
       GetFd(profile1)});
   int reference_profile_fd = GetFd(reference_profile);
 
-  const uint16_t kNumberOfClassesToEnableCompilation = 100;
   ProfileCompilationInfo info1;
-  SetupProfile(dex1, dex2, 0, kNumberOfClassesToEnableCompilation, profile1, &info1);
+  SetupProfile(dex1_100, dex2_100, 0, kNumberOfClassesToEnableCompilation, profile1, &info1);
 
   // We should advise compilation.
   ASSERT_EQ(ProfileAssistant::kCompile,
             ProcessProfiles(profile_fds, reference_profile_fd));
   // The resulting compilation info must be equal to the merge of the inputs.
   ProfileCompilationInfo result;
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
   ASSERT_TRUE(result.Load(reference_profile_fd));
 
   ProfileCompilationInfo expected;
@@ -501,7 +571,6 @@
 
   // The resulting compilation info must be equal to the merge of the inputs
   ProfileCompilationInfo result;
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
   ASSERT_TRUE(result.Load(reference_profile_fd));
 
   ProfileCompilationInfo expected;
@@ -515,6 +584,42 @@
   CheckProfileInfo(profile2, info2);
 }
 
+TEST_F(ProfileAssistantTest, DoNotAdviseCompilationEmptyProfile) {
+  ScratchFile profile1;
+  ScratchFile profile2;
+  ScratchFile reference_profile;
+
+  std::vector<int> profile_fds({
+      GetFd(profile1),
+      GetFd(profile2)});
+  int reference_profile_fd = GetFd(reference_profile);
+
+  ProfileCompilationInfo info1;
+  SetupProfile(dex1, dex2, /*number_of_methods=*/ 0, /*number_of_classes*/ 0, profile1, &info1);
+  ProfileCompilationInfo info2;
+  SetupProfile(dex3, dex4, /*number_of_methods=*/ 0, /*number_of_classes*/ 0, profile2, &info2);
+
+  // We should not advise compilation.
+  ASSERT_EQ(ProfileAssistant::kSkipCompilationEmptyProfiles,
+            ProcessProfiles(profile_fds, reference_profile_fd));
+
+  // The information from profiles must remain the same.
+  ProfileCompilationInfo file_info1;
+  ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
+  ASSERT_TRUE(file_info1.Equals(info1));
+
+  ProfileCompilationInfo file_info2;
+  ASSERT_TRUE(file_info2.Load(GetFd(profile2)));
+  ASSERT_TRUE(file_info2.Equals(info2));
+
+  // Reference profile files must remain empty.
+  ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
+
+  // The information from profiles must remain the same.
+  CheckProfileInfo(profile1, info1);
+  CheckProfileInfo(profile2, info2);
+}
+
 TEST_F(ProfileAssistantTest, DoNotAdviseCompilation) {
   ScratchFile profile1;
   ScratchFile profile2;
@@ -532,17 +637,15 @@
   SetupProfile(dex3, dex4, kNumberOfMethodsToSkipCompilation, 0, profile2, &info2);
 
   // We should not advise compilation.
-  ASSERT_EQ(ProfileAssistant::kSkipCompilation,
+  ASSERT_EQ(ProfileAssistant::kSkipCompilationSmallDelta,
             ProcessProfiles(profile_fds, reference_profile_fd));
 
   // The information from profiles must remain the same.
   ProfileCompilationInfo file_info1;
-  ASSERT_TRUE(profile1.GetFile()->ResetOffset());
   ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
   ASSERT_TRUE(file_info1.Equals(info1));
 
   ProfileCompilationInfo file_info2;
-  ASSERT_TRUE(profile2.GetFile()->ResetOffset());
   ASSERT_TRUE(file_info2.Load(GetFd(profile2)));
   ASSERT_TRUE(file_info2.Equals(info2));
 
@@ -557,36 +660,68 @@
 TEST_F(ProfileAssistantTest, DoNotAdviseCompilationMethodPercentage) {
   const uint16_t kNumberOfMethodsInRefProfile = 6000;
   const uint16_t kNumberOfMethodsInCurProfile = 6100;  // Threshold is 2%.
+  std::vector<const std::string> extra_args({"--min-new-methods-percent-change=2"});
+
   // We should not advise compilation.
-  ASSERT_EQ(ProfileAssistant::kSkipCompilation,
+  ASSERT_EQ(ProfileAssistant::kSkipCompilationSmallDelta,
             CheckCompilationMethodPercentChange(kNumberOfMethodsInCurProfile,
-                                                kNumberOfMethodsInRefProfile));
+                                                kNumberOfMethodsInRefProfile,
+                                                extra_args));
 }
 
 TEST_F(ProfileAssistantTest, ShouldAdviseCompilationMethodPercentage) {
   const uint16_t kNumberOfMethodsInRefProfile = 6000;
   const uint16_t kNumberOfMethodsInCurProfile = 6200;  // Threshold is 2%.
+  std::vector<const std::string> extra_args({"--min-new-methods-percent-change=2"});
+
   // We should advise compilation.
   ASSERT_EQ(ProfileAssistant::kCompile,
             CheckCompilationMethodPercentChange(kNumberOfMethodsInCurProfile,
+                                                kNumberOfMethodsInRefProfile,
+                                                extra_args));
+}
+
+TEST_F(ProfileAssistantTest, DoNotAdviseCompilationMethodPercentageWithNewMin) {
+  const uint16_t kNumberOfMethodsInRefProfile = 6000;
+  const uint16_t kNumberOfMethodsInCurProfile = 6200;  // Threshold is 20%.
+
+  // We should not advise compilation.
+  ASSERT_EQ(ProfileAssistant::kSkipCompilationSmallDelta,
+            CheckCompilationMethodPercentChange(kNumberOfMethodsInCurProfile,
                                                 kNumberOfMethodsInRefProfile));
 }
 
-TEST_F(ProfileAssistantTest, DoNotdviseCompilationClassPercentage) {
+TEST_F(ProfileAssistantTest, DoNotAdviseCompilationClassPercentage) {
   const uint16_t kNumberOfClassesInRefProfile = 6000;
   const uint16_t kNumberOfClassesInCurProfile = 6110;  // Threshold is 2%.
+  std::vector<const std::string> extra_args({"--min-new-classes-percent-change=2"});
+
   // We should not advise compilation.
-  ASSERT_EQ(ProfileAssistant::kSkipCompilation,
+  ASSERT_EQ(ProfileAssistant::kSkipCompilationSmallDelta,
             CheckCompilationClassPercentChange(kNumberOfClassesInCurProfile,
-                                               kNumberOfClassesInRefProfile));
+                                               kNumberOfClassesInRefProfile,
+                                               extra_args));
 }
 
 TEST_F(ProfileAssistantTest, ShouldAdviseCompilationClassPercentage) {
   const uint16_t kNumberOfClassesInRefProfile = 6000;
   const uint16_t kNumberOfClassesInCurProfile = 6120;  // Threshold is 2%.
+  std::vector<const std::string> extra_args({"--min-new-classes-percent-change=2"});
+
   // We should advise compilation.
   ASSERT_EQ(ProfileAssistant::kCompile,
             CheckCompilationClassPercentChange(kNumberOfClassesInCurProfile,
+                                               kNumberOfClassesInRefProfile,
+                                               extra_args));
+}
+
+TEST_F(ProfileAssistantTest, DoNotAdviseCompilationClassPercentageWithNewMin) {
+  const uint16_t kNumberOfClassesInRefProfile = 6000;
+  const uint16_t kNumberOfClassesInCurProfile = 6200;  // Threshold is 20%.
+
+  // We should not advise compilation.
+  ASSERT_EQ(ProfileAssistant::kSkipCompilationSmallDelta,
+            CheckCompilationClassPercentChange(kNumberOfClassesInCurProfile,
                                                kNumberOfClassesInRefProfile));
 }
 
@@ -633,12 +768,14 @@
   ProfileCompilationInfo info1;
   SetupProfile(dex1, dex2, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
   ProfileCompilationInfo reference_info;
-  SetupProfile(
-      dex1_checksum_missmatch, dex2, kNumberOfMethodsToEnableCompilation, 0, reference_profile, &reference_info);
+  SetupProfile(dex1_checksum_missmatch,
+               dex2,
+               kNumberOfMethodsToEnableCompilation,
+               0,
+               reference_profile,
+               &reference_info);
 
   // We should not advise compilation.
-  ASSERT_TRUE(profile1.GetFile()->ResetOffset());
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
   ASSERT_EQ(ProfileAssistant::kErrorBadProfiles,
             ProcessProfiles(profile_fds, reference_profile_fd));
 
@@ -652,7 +789,6 @@
   GenerateTestProfile(profile.GetFilename());
 
   // Verify that the generated profile is valid and can be loaded.
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ProfileCompilationInfo info;
   ASSERT_TRUE(info.Load(GetFd(profile)));
 }
@@ -663,7 +799,6 @@
   GenerateTestProfileWithInputDex(profile.GetFilename());
 
   // Verify that the generated profile is valid and can be loaded.
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ProfileCompilationInfo info;
   ASSERT_TRUE(info.Load(GetFd(profile)));
 }
@@ -676,6 +811,8 @@
     "Ljava/lang/Math;",
     "Ljava/lang/Object;",
     "SPLjava/lang/Comparable;->compareTo(Ljava/lang/Object;)I",
+    "[[[[[[[[I",                   // No `TypeId`s in core-oj with this many array dimensions,
+    "[[[[[[[[Ljava/lang/Object;",  // "extra descriptors" shall be used for these array classes.
   };
   std::string file_contents;
   for (std::string& class_name : class_names) {
@@ -717,19 +854,18 @@
                             profile_file.GetFilename(),
                             GetLibCoreDexFileNames()[0]));
   ProfileCompilationInfo info;
-  profile_file.GetFile()->ResetOffset();
   ASSERT_TRUE(info.Load(GetFd(profile_file)));
   // Verify that the profile has matching methods.
   ScopedObjectAccess soa(Thread::Current());
-  ObjPtr<mirror::Class> klass = GetClass(soa, /* class_loader= */ nullptr, "Ljava/lang/Math;");
+  ObjPtr<mirror::Class> klass = GetClass(soa, /*class_loader=*/ nullptr, "Ljava/lang/Math;");
   ASSERT_TRUE(klass != nullptr);
   size_t method_count = 0;
   for (ArtMethod& method : klass->GetMethods(kRuntimePointerSize)) {
     if (!method.IsCopied() && method.GetCodeItem() != nullptr) {
       ++method_count;
-      std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> pmi =
-          info.GetHotMethodInfo(MethodReference(method.GetDexFile(), method.GetDexMethodIndex()));
-      ASSERT_TRUE(pmi != nullptr) << method.PrettyMethod();
+      ProfileCompilationInfo::MethodHotness hotness =
+          info.GetMethodHotness(MethodReference(method.GetDexFile(), method.GetDexMethodIndex()));
+      ASSERT_TRUE(hotness.IsHot()) << method.PrettyMethod();
     }
   }
   EXPECT_GT(method_count, 0u);
@@ -763,8 +899,8 @@
       "Ljava/lang/Object;->toString()Ljava/lang/String;";
   // Method used by a special package which will get a different threshold;
   const std::string kUncommonSpecialPackageMethod = "Ljava/lang/Object;->hashCode()I";
-  // Blacklisted class
-  const std::string kPreloadedBlacklistedClass = "Ljava/lang/Thread;";
+  // Denylisted class
+  const std::string kPreloadedDenylistedClass = "Ljava/lang/Thread;";
 
   // Thresholds for this test.
   static const size_t kDirtyThreshold = 100;
@@ -782,42 +918,41 @@
       "{dex1}H" + kCommonHotMethod,
       "{dex1}P" + kStartupMethodForUpgrade,
       "{dex1}" + kUncommonDirtyClass,
-      "{dex1}" + kPreloadedBlacklistedClass,
+      "{dex1}" + kPreloadedDenylistedClass,
 
       "{dex2}" + kCleanClass,
       "{dex2}" + kDirtyClass,
       "{dex2}P" + kCommonHotMethod,
       "{dex2}P" + kStartupMethodForUpgrade,
       "{dex2}" + kUncommonDirtyClass,
-      "{dex2}" + kPreloadedBlacklistedClass,
+      "{dex2}" + kPreloadedDenylistedClass,
 
       "{dex3}P" + kUncommonMethod,
       "{dex3}PS" + kStartupMethodForUpgrade,
       "{dex3}S" + kCommonHotMethod,
       "{dex3}S" + kSpecialPackageStartupMethod,
       "{dex3}" + kDirtyClass,
-      "{dex3}" + kPreloadedBlacklistedClass,
+      "{dex3}" + kPreloadedDenylistedClass,
 
       "{dex4}" + kDirtyClass,
       "{dex4}P" + kCommonHotMethod,
       "{dex4}S" + kSpecialPackageStartupMethod,
       "{dex4}P" + kUncommonSpecialPackageMethod,
-      "{dex4}" + kPreloadedBlacklistedClass,
+      "{dex4}" + kPreloadedDenylistedClass,
   };
   std::string input_file_contents = JoinProfileLines(input_data);
 
-  ScratchFile preloaded_class_blacklist;
-  std::string blacklist_content = DescriptorToDot(kPreloadedBlacklistedClass.c_str());
-  EXPECT_TRUE(preloaded_class_blacklist.GetFile()->WriteFully(
-      blacklist_content.c_str(), blacklist_content.length()));
+  ScratchFile preloaded_class_denylist;
+  std::string denylist_content = DescriptorToDot(kPreloadedDenylistedClass.c_str());
+  EXPECT_TRUE(preloaded_class_denylist.GetFile()->WriteFully(
+      denylist_content.c_str(), denylist_content.length()));
 
-  EXPECT_EQ(0, preloaded_class_blacklist.GetFile()->Flush());
-  EXPECT_TRUE(preloaded_class_blacklist.GetFile()->ResetOffset());
+  EXPECT_EQ(0, preloaded_class_denylist.GetFile()->Flush());
   // Expected data
   std::vector<std::string> expected_data = {
       kCleanClass,
       kDirtyClass,
-      kPreloadedBlacklistedClass,
+      kPreloadedDenylistedClass,
       "HSP" + kCommonHotMethod,
       "HS" + kSpecialPackageStartupMethod,
       "HSP" + kStartupMethodForUpgrade
@@ -830,16 +965,17 @@
   std::string expected_preloaded_content = JoinProfileLines(expected_preloaded_data);
 
   ScratchFile profile;
-  EXPECT_TRUE(CreateProfile(input_file_contents, profile.GetFilename(), core_dex));
+  EXPECT_TRUE(CreateProfile(input_file_contents,
+                            profile.GetFilename(),
+                            core_dex,
+                            /*for_boot_image=*/ true));
 
-  ProfileCompilationInfo bootProfile;
-  bootProfile.Load(profile.GetFilename(), /*for_boot_image*/ true);
+  ProfileCompilationInfo bootProfile(/*for_boot_image=*/ true);
+  bootProfile.Load(profile.GetFilename(), /*clear_if_invalid=*/ true);
 
   // Generate the boot profile.
   ScratchFile out_profile;
   ScratchFile out_preloaded_classes;
-  ASSERT_TRUE(out_profile.GetFile()->ResetOffset());
-  ASSERT_TRUE(out_preloaded_classes.GetFile()->ResetOffset());
   std::vector<std::string> args;
   args.push_back(GetProfmanCmd());
   args.push_back("--generate-boot-image-profile");
@@ -854,11 +990,10 @@
   args.push_back("--out-preloaded-classes-path=" + out_preloaded_classes.GetFilename());
   args.push_back("--apk=" + core_dex);
   args.push_back("--dex-location=" + core_dex);
-  args.push_back("--preloaded-classes-blacklist=" + preloaded_class_blacklist.GetFilename());
+  args.push_back("--preloaded-classes-denylist=" + preloaded_class_denylist.GetFilename());
 
   std::string error;
   ASSERT_EQ(ExecAndReturnCode(args, &error), 0) << error;
-  ASSERT_TRUE(out_profile.GetFile()->ResetOffset());
 
   // Verify the boot profile contents.
   std::string output_profile_contents;
@@ -921,19 +1056,23 @@
 
   ScratchFile profile1;
   ScratchFile profile2;
-  EXPECT_TRUE(CreateProfile(input_file_contents1, profile1.GetFilename(), core_dex));
-  EXPECT_TRUE(CreateProfile(input_file_contents2, profile2.GetFilename(), core_dex));
+  EXPECT_TRUE(CreateProfile(input_file_contents1,
+                            profile1.GetFilename(),
+                            core_dex,
+                            /*for_boot_image=*/ true));
+  EXPECT_TRUE(CreateProfile(input_file_contents2,
+                            profile2.GetFilename(),
+                            core_dex,
+                            /*for_boot_image=*/ true));
 
   ProfileCompilationInfo boot_profile1;
   ProfileCompilationInfo boot_profile2;
-  boot_profile1.Load(profile1.GetFilename(), /*for_boot_image*/ true);
-  boot_profile2.Load(profile2.GetFilename(), /*for_boot_image*/ true);
+  boot_profile1.Load(profile1.GetFilename(), /*for_boot_image=*/ true);
+  boot_profile2.Load(profile2.GetFilename(), /*for_boot_image=*/ true);
 
   // Generate the boot profile.
   ScratchFile out_profile;
   ScratchFile out_preloaded_classes;
-  ASSERT_TRUE(out_profile.GetFile()->ResetOffset());
-  ASSERT_TRUE(out_preloaded_classes.GetFile()->ResetOffset());
   std::vector<std::string> args;
   args.push_back(GetProfmanCmd());
   args.push_back("--generate-boot-image-profile");
@@ -949,7 +1088,6 @@
 
   std::string error;
   ASSERT_EQ(ExecAndReturnCode(args, &error), 0) << error;
-  ASSERT_TRUE(out_profile.GetFile()->ResetOffset());
 
   // Verify the boot profile contents.
   std::string output_profile_contents;
@@ -994,29 +1132,145 @@
   ASSERT_EQ(output_file_contents, expected_contents);
 }
 
-TEST_F(ProfileAssistantTest, TestProfileCreateInlineCache) {
+// Test that we can dump profiles in a way they can be re-constituted.
+// Test goes 'txt -> prof -> txt -> prof' and then compares the two profs.
+TEST_F(ProfileAssistantTest, TestProfileRoundTrip) {
   // Create the profile content.
-  std::vector<std::string> methods = {
+  std::vector<std::string_view> methods = {
     "HLTestInline;->inlineMonomorphic(LSuper;)I+LSubA;",
     "HLTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;",
     "HLTestInline;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;",
     "HLTestInline;->inlineMissingTypes(LSuper;)I+missing_types",
-    "HLTestInline;->noInlineCache(LSuper;)I"
+    "HLTestInline;->noInlineCache(LSuper;)I",
+    "HLTestInline;->inlineMultiMonomorphic(LSuper;LSecret;)I+]LSuper;LSubA;]LSecret;LSubB;",
+    "HLTestInline;->inlineMultiPolymorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
+    "HLTestInline;->inlineMultiMegamorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;,LSubD;,LSubE;]LSecret;megamorphic_types",
+    "HLTestInline;->inlineMultiMissingTypes(LSuper;LSecret;)I+]LSuper;missing_types]LSecret;missing_types",
+    "HLTestInline;->inlineTriplePolymorphic(LSuper;LSecret;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
+    "HLTestInline;->noInlineCacheMulti(LSuper;LSecret;)I",
   };
-  std::string input_file_contents;
-  for (std::string& m : methods) {
-    input_file_contents += m + std::string("\n");
+  std::ostringstream input_file_contents;
+  for (const std::string_view& m : methods) {
+    input_file_contents << m << "\n";
   }
 
   // Create the profile and save it to disk.
   ScratchFile profile_file;
-  ASSERT_TRUE(CreateProfile(input_file_contents,
+  ASSERT_TRUE(CreateProfile(input_file_contents.str(),
+                            profile_file.GetFilename(),
+                            GetTestDexFileName("ProfileTestMultiDex")));
+
+  // Dump the file back into text.
+  std::string text_two;
+  ASSERT_TRUE(DumpClassesAndMethods(
+      profile_file.GetFilename(), &text_two, GetTestDexFileName("ProfileTestMultiDex")));
+
+  // Create another profile and save it to the disk as well.
+  ScratchFile profile_two;
+  ASSERT_TRUE(CreateProfile(
+      text_two, profile_two.GetFilename(), GetTestDexFileName("ProfileTestMultiDex")));
+
+  // These two profiles should be bit-identical.
+  // TODO We could compare the 'text_two' to the methods but since the order is
+  // arbitrary for many parts and there are multiple 'correct' dumps we'd need
+  // to basically parse everything and this is simply easier.
+  std::string error;
+  std::vector<std::string> args { kIsTargetBuild ? "/system/bin/cmp" : "/usr/bin/cmp",
+                                  "-s",
+                                  profile_file.GetFilename(),
+                                  profile_two.GetFilename() };
+  ASSERT_EQ(ExecAndReturnCode(args, &error), 0) << error << " from " << text_two;
+}
+
+
+// Test that we can dump profiles in a way they can be re-constituted and
+// annotations don't interfere. Test goes 'txt -> ProfileWithAnnotations -> txt
+// -> prof' and then compares that to one that is 'txt ->
+// prof_without_annotations'.
+TEST_F(ProfileAssistantTest, TestProfileRoundTripWithAnnotations) {
+  // Create the profile content.
+  std::vector<std::string_view> methods = {
+    "HLTestInline;->inlineMonomorphic(LSuper;)I+LSubA;",
+    "HLTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;",
+    "HLTestInline;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;",
+    "HLTestInline;->inlineMissingTypes(LSuper;)I+missing_types",
+    "HLTestInline;->noInlineCache(LSuper;)I",
+    "HLTestInline;->inlineMultiMonomorphic(LSuper;LSecret;)I+]LSuper;LSubA;]LSecret;LSubB;",
+    "HLTestInline;->inlineMultiPolymorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
+    "HLTestInline;->inlineMultiMegamorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;,LSubD;,LSubE;]LSecret;megamorphic_types",
+    "HLTestInline;->inlineMultiMissingTypes(LSuper;LSecret;)I+]LSuper;missing_types]LSecret;missing_types",
+    "HLTestInline;->inlineTriplePolymorphic(LSuper;LSecret;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
+    "HLTestInline;->noInlineCacheMulti(LSuper;LSecret;)I",
+  };
+  std::ostringstream no_annotation_input_file_contents;
+  std::ostringstream with_annotation_input_file_contents;
+  for (const std::string_view& m : methods) {
+    no_annotation_input_file_contents << m << "\n";
+    with_annotation_input_file_contents << "{foobar}" << m << "\n";
+  }
+
+  // Create the profile and save it to disk.
+  ScratchFile with_annotation_profile_file;
+  ASSERT_TRUE(CreateProfile(with_annotation_input_file_contents.str(),
+                            with_annotation_profile_file.GetFilename(),
+                            GetTestDexFileName("ProfileTestMultiDex")));
+
+  ScratchFile no_annotation_profile_file;
+  ASSERT_TRUE(CreateProfile(no_annotation_input_file_contents.str(),
+                            no_annotation_profile_file.GetFilename(),
+                            GetTestDexFileName("ProfileTestMultiDex")));
+
+  // Dump the file back into text.
+  std::string text_two;
+  ASSERT_TRUE(DumpClassesAndMethods(with_annotation_profile_file.GetFilename(),
+                                    &text_two,
+                                    GetTestDexFileName("ProfileTestMultiDex")));
+
+  // Create another profile and save it to the disk as well.
+  ScratchFile profile_two;
+  ASSERT_TRUE(CreateProfile(
+      text_two, profile_two.GetFilename(), GetTestDexFileName("ProfileTestMultiDex")));
+
+  // These two profiles should be bit-identical.
+  // TODO We could compare the 'text_two' to the methods but since the order is
+  // arbitrary for many parts and there are multiple 'correct' dumps we'd need
+  // to basically parse everything and this is simply easier.
+  std::string error;
+  std::vector<std::string> args { kIsTargetBuild ? "/system/bin/cmp" : "/usr/bin/cmp",
+                                  "-s",
+                                  no_annotation_profile_file.GetFilename(),
+                                  profile_two.GetFilename() };
+  ASSERT_EQ(ExecAndReturnCode(args, &error), 0) << error << " from " << text_two;
+}
+
+TEST_F(ProfileAssistantTest, TestProfileCreateInlineCache) {
+  // Create the profile content.
+  std::vector<std::string_view> methods = {
+    "HLTestInline;->inlineMonomorphic(LSuper;)I+LSubA;",
+    "HLTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;",
+    "HLTestInline;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;",
+    "HLTestInline;->inlineMissingTypes(LSuper;)I+missing_types",
+    "HLTestInline;->noInlineCache(LSuper;)I",
+    "HLTestInline;->inlineMultiMonomorphic(LSuper;LSecret;)I+]LSuper;LSubA;]LSecret;LSubB;",
+    "HLTestInline;->inlineMultiPolymorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
+    "HLTestInline;->inlineMultiMegamorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;,LSubD;,LSubE;]LSecret;LSubA;,LSubB;,LSubC;,LSubD;,LSubE;",
+    "HLTestInline;->inlineMultiMissingTypes(LSuper;LSecret;)I+]LSuper;missing_types]LSecret;missing_types",
+    "HLTestInline;->inlineTriplePolymorphic(LSuper;LSecret;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
+    "HLTestInline;->noInlineCacheMulti(LSuper;LSecret;)I",
+  };
+  std::ostringstream input_file_contents;
+  for (const std::string_view& m : methods) {
+    input_file_contents << m << "\n";
+  }
+
+  // Create the profile and save it to disk.
+  ScratchFile profile_file;
+  ASSERT_TRUE(CreateProfile(input_file_contents.str(),
                             profile_file.GetFilename(),
                             GetTestDexFileName("ProfileTestMultiDex")));
 
   // Load the profile from disk.
   ProfileCompilationInfo info;
-  profile_file.GetFile()->ResetOffset();
   ASSERT_TRUE(info.Load(GetFd(profile_file)));
 
   // Load the dex files and verify that the profile contains the expected methods info.
@@ -1024,11 +1278,15 @@
   jobject class_loader = LoadDex("ProfileTestMultiDex");
   ASSERT_NE(class_loader, nullptr);
 
-  StackHandleScope<3> hs(soa.Self());
+  StackHandleScope<5> hs(soa.Self());
+  Handle<mirror::Class> super_klass = hs.NewHandle(GetClass(soa, class_loader, "LSuper;"));
+  Handle<mirror::Class> secret_klass = hs.NewHandle(GetClass(soa, class_loader, "LSecret;"));
   Handle<mirror::Class> sub_a = hs.NewHandle(GetClass(soa, class_loader, "LSubA;"));
   Handle<mirror::Class> sub_b = hs.NewHandle(GetClass(soa, class_loader, "LSubB;"));
   Handle<mirror::Class> sub_c = hs.NewHandle(GetClass(soa, class_loader, "LSubC;"));
 
+  ASSERT_TRUE(super_klass != nullptr);
+  ASSERT_TRUE(secret_klass != nullptr);
   ASSERT_TRUE(sub_a != nullptr);
   ASSERT_TRUE(sub_b != nullptr);
   ASSERT_TRUE(sub_c != nullptr);
@@ -1097,11 +1355,150 @@
     // Verify that method noInlineCache has no inline caches in the profile.
     ArtMethod* no_inline_cache = GetVirtualMethod(class_loader, "LTestInline;", "noInlineCache");
     ASSERT_TRUE(no_inline_cache != nullptr);
-    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> pmi_no_inline_cache =
-        info.GetHotMethodInfo(MethodReference(
-            no_inline_cache->GetDexFile(), no_inline_cache->GetDexMethodIndex()));
-    ASSERT_TRUE(pmi_no_inline_cache != nullptr);
-    ASSERT_TRUE(pmi_no_inline_cache->inline_caches->empty());
+    ProfileCompilationInfo::MethodHotness hotness_no_inline_cache = info.GetMethodHotness(
+        MethodReference(no_inline_cache->GetDexFile(), no_inline_cache->GetDexMethodIndex()));
+    ASSERT_TRUE(hotness_no_inline_cache.IsHot());
+    ASSERT_TRUE(hotness_no_inline_cache.GetInlineCacheMap()->empty());
+  }
+
+  {
+    // Verify that method inlineMonomorphic has the expected inline caches and nothing else.
+    ArtMethod* inline_monomorphic = GetVirtualMethod(class_loader,
+                                                     "LTestInline;",
+                                                     "inlineMultiMonomorphic");
+    ASSERT_TRUE(inline_monomorphic != nullptr);
+    TypeReferenceSet expected_monomorphic_super;
+    TypeReferenceSet expected_monomorphic_secret;
+    expected_monomorphic_super.insert(MakeTypeReference(sub_a.Get()));
+    expected_monomorphic_secret.insert(MakeTypeReference(sub_b.Get()));
+    AssertInlineCaches(inline_monomorphic,
+                       GetDexPcOfCallTo(inline_monomorphic, super_klass),
+                       expected_monomorphic_super,
+                       info,
+                       /*is_megamorphic=*/false,
+                       /*is_missing_types=*/false);
+    AssertInlineCaches(inline_monomorphic,
+                       GetDexPcOfCallTo(inline_monomorphic, secret_klass),
+                       expected_monomorphic_secret,
+                       info,
+                       /*is_megamorphic=*/false,
+                       /*is_missing_types=*/false);
+  }
+
+  {
+    // Verify that method inlinePolymorphic has the expected inline caches and nothing else.
+    ArtMethod* inline_polymorhic = GetVirtualMethod(class_loader,
+                                                    "LTestInline;",
+                                                    "inlineMultiPolymorphic");
+    ASSERT_TRUE(inline_polymorhic != nullptr);
+    TypeReferenceSet expected_polymorphic_super;
+    expected_polymorphic_super.insert(MakeTypeReference(sub_a.Get()));
+    expected_polymorphic_super.insert(MakeTypeReference(sub_b.Get()));
+    expected_polymorphic_super.insert(MakeTypeReference(sub_c.Get()));
+    TypeReferenceSet expected_polymorphic_secret;
+    expected_polymorphic_secret.insert(MakeTypeReference(sub_b.Get()));
+    expected_polymorphic_secret.insert(MakeTypeReference(sub_c.Get()));
+    AssertInlineCaches(inline_polymorhic,
+                       GetDexPcOfCallTo(inline_polymorhic, super_klass),
+                       expected_polymorphic_super,
+                       info,
+                       /*is_megamorphic=*/false,
+                       /*is_missing_types=*/false);
+    AssertInlineCaches(inline_polymorhic,
+                       GetDexPcOfCallTo(inline_polymorhic, secret_klass),
+                       expected_polymorphic_secret,
+                       info,
+                       /*is_megamorphic=*/false,
+                       /*is_missing_types=*/false);
+  }
+
+  {
+    // Verify that method inlinePolymorphic has the expected inline caches and nothing else.
+    ArtMethod* inline_polymorhic = GetVirtualMethod(class_loader,
+                                                    "LTestInline;",
+                                                    "inlineTriplePolymorphic");
+    ASSERT_TRUE(inline_polymorhic != nullptr);
+    TypeReferenceSet expected_polymorphic_super;
+    expected_polymorphic_super.insert(MakeTypeReference(sub_a.Get()));
+    expected_polymorphic_super.insert(MakeTypeReference(sub_b.Get()));
+    expected_polymorphic_super.insert(MakeTypeReference(sub_c.Get()));
+    TypeReferenceSet expected_polymorphic_secret;
+    expected_polymorphic_secret.insert(MakeTypeReference(sub_b.Get()));
+    expected_polymorphic_secret.insert(MakeTypeReference(sub_c.Get()));
+    AssertInlineCaches(inline_polymorhic,
+                       GetDexPcOfCallTo(inline_polymorhic, super_klass),
+                       expected_polymorphic_super,
+                       info,
+                       /*is_megamorphic=*/false,
+                       /*is_missing_types=*/false);
+    uint16_t first_call = GetDexPcOfCallTo(inline_polymorhic, secret_klass);
+    AssertInlineCaches(inline_polymorhic,
+                       first_call,
+                       expected_polymorphic_secret,
+                       info,
+                       /*is_megamorphic=*/false,
+                       /*is_missing_types=*/false);
+    uint16_t second_call = GetDexPcOfCallTo(inline_polymorhic, secret_klass, first_call);
+    ASSERT_LT(first_call, second_call);
+    AssertInlineCaches(inline_polymorhic,
+                       second_call,
+                       expected_polymorphic_secret,
+                       info,
+                       /*is_megamorphic=*/false,
+                       /*is_missing_types=*/false);
+  }
+
+  {
+    // Verify that method inlineMegamorphic has the expected inline caches and nothing else.
+    ArtMethod* inline_megamorphic = GetVirtualMethod(class_loader,
+                                                     "LTestInline;",
+                                                     "inlineMultiMegamorphic");
+    ASSERT_TRUE(inline_megamorphic != nullptr);
+    TypeReferenceSet expected_megamorphic;
+    AssertInlineCaches(inline_megamorphic,
+                       GetDexPcOfCallTo(inline_megamorphic, super_klass),
+                       expected_megamorphic,
+                       info,
+                       /*is_megamorphic=*/true,
+                       /*is_missing_types=*/false);
+    AssertInlineCaches(inline_megamorphic,
+                       GetDexPcOfCallTo(inline_megamorphic, secret_klass),
+                       expected_megamorphic,
+                       info,
+                       /*is_megamorphic=*/true,
+                       /*is_missing_types=*/false);
+  }
+
+  {
+    // Verify that method inlineMegamorphic has the expected inline caches and nothing else.
+    ArtMethod* inline_missing_types = GetVirtualMethod(class_loader,
+                                                       "LTestInline;",
+                                                       "inlineMultiMissingTypes");
+    ASSERT_TRUE(inline_missing_types != nullptr);
+    TypeReferenceSet expected_missing_Types;
+    AssertInlineCaches(inline_missing_types,
+                       GetDexPcOfCallTo(inline_missing_types, super_klass),
+                       expected_missing_Types,
+                       info,
+                       /*is_megamorphic=*/false,
+                       /*is_missing_types=*/true);
+    AssertInlineCaches(inline_missing_types,
+                       GetDexPcOfCallTo(inline_missing_types, secret_klass),
+                       expected_missing_Types,
+                       info,
+                       /*is_megamorphic=*/false,
+                       /*is_missing_types=*/true);
+  }
+
+  {
+    // Verify that method noInlineCacheMulti has no inline caches in the profile.
+    ArtMethod* no_inline_cache =
+        GetVirtualMethod(class_loader, "LTestInline;", "noInlineCacheMulti");
+    ASSERT_TRUE(no_inline_cache != nullptr);
+    ProfileCompilationInfo::MethodHotness hotness_no_inline_cache = info.GetMethodHotness(
+        MethodReference(no_inline_cache->GetDexFile(), no_inline_cache->GetDexMethodIndex()));
+    ASSERT_TRUE(hotness_no_inline_cache.IsHot());
+    ASSERT_TRUE(hotness_no_inline_cache.GetInlineCacheMap()->empty());
   }
 }
 
@@ -1133,7 +1530,6 @@
 
   // The resulting compilation info must be equal to the merge of the inputs.
   ProfileCompilationInfo result;
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
   ASSERT_TRUE(result.Load(reference_profile_fd));
 
   ProfileCompilationInfo expected;
@@ -1145,12 +1541,104 @@
   CheckProfileInfo(profile1, info1);
 }
 
+TEST_F(ProfileAssistantTest, TestProfileCreateWithSubtype) {
+  // Create the profile content.
+  std::vector<std::string> profile_methods = {
+      "HLTestInlineSubtype;->inlineMonomorphic(LSuper;)I+]LSuper;LSubA;",
+  };
+  std::string input_file_contents;
+  for (std::string& m : profile_methods) {
+    input_file_contents += m + std::string("\n");
+  }
+
+  // Create the profile and save it to disk.
+  ScratchFile profile_file;
+  std::string dex_filename = GetTestDexFileName("ProfileTestMultiDex");
+  ASSERT_TRUE(CreateProfile(input_file_contents, profile_file.GetFilename(), dex_filename));
+
+  // Load the profile from disk.
+  ProfileCompilationInfo info;
+  ASSERT_TRUE(info.Load(GetFd(profile_file)));
+  LOG(ERROR) << profile_file.GetFilename();
+
+  // Load the dex files and verify that the profile contains the expected
+  // methods info.
+  ScopedObjectAccess soa(Thread::Current());
+  jobject class_loader = LoadDex("ProfileTestMultiDex");
+  ASSERT_NE(class_loader, nullptr);
+
+  // NB This is the supertype of the declared line!
+  ArtMethod* inline_monomorphic_super =
+      GetVirtualMethod(class_loader, "LTestInline;", "inlineMonomorphic");
+  const DexFile* dex_file = inline_monomorphic_super->GetDexFile();
+
+  // Verify that the inline cache is present in the superclass
+  ProfileCompilationInfo::MethodHotness hotness_super = info.GetMethodHotness(
+      MethodReference(dex_file, inline_monomorphic_super->GetDexMethodIndex()));
+  ASSERT_TRUE(hotness_super.IsHot());
+  const ProfileCompilationInfo::InlineCacheMap* inline_caches = hotness_super.GetInlineCacheMap();
+  ASSERT_EQ(inline_caches->size(), 1u);
+  const ProfileCompilationInfo::DexPcData& dex_pc_data = inline_caches->begin()->second;
+  dex::TypeIndex target_type_index(dex_file->GetIndexForTypeId(*dex_file->FindTypeId("LSubA;")));
+  ASSERT_EQ(1u, dex_pc_data.classes.size());
+  ASSERT_EQ(target_type_index, *dex_pc_data.classes.begin());
+
+  // Verify that the method is present in subclass but there are no
+  // inline-caches (since there is no code).
+  const dex::MethodId& super_method_id =
+      dex_file->GetMethodId(inline_monomorphic_super->GetDexMethodIndex());
+  uint32_t sub_method_index = dex_file->GetIndexForMethodId(
+      *dex_file->FindMethodId(*dex_file->FindTypeId("LTestInlineSubtype;"),
+                              dex_file->GetStringId(super_method_id.name_idx_),
+                              dex_file->GetProtoId(super_method_id.proto_idx_)));
+  ProfileCompilationInfo::MethodHotness hotness_sub =
+      info.GetMethodHotness(MethodReference(dex_file, sub_method_index));
+  ASSERT_TRUE(hotness_sub.IsHot());
+  ASSERT_EQ(hotness_sub.GetInlineCacheMap()->size(), 0u);
+}
+
+TEST_F(ProfileAssistantTest, TestProfileCreateWithSubtypeAndDump) {
+  // Create the profile content.
+  std::vector<std::string> profile_methods = {
+      "HLTestInlineSubtype;->inlineMonomorphic(LSuper;)I+]LSuper;LSubA;",
+  };
+  std::string input_file_contents;
+  for (std::string& m : profile_methods) {
+    input_file_contents += m + std::string("\n");
+  }
+
+  // Create the profile and save it to disk.
+  ScratchFile profile_file;
+  std::string dex_filename = GetTestDexFileName("ProfileTestMultiDex");
+  ASSERT_TRUE(CreateProfile(input_file_contents, profile_file.GetFilename(), dex_filename));
+
+  std::string dump_ic;
+  ASSERT_TRUE(DumpClassesAndMethods(
+      profile_file.GetFilename(), &dump_ic, GetTestDexFileName("ProfileTestMultiDex")));
+
+  std::vector<std::string> lines;
+  std::stringstream dump_stream(dump_ic);
+  std::string cur;
+  while (std::getline(dump_stream, cur, '\n')) {
+    lines.push_back(std::move(cur));
+  }
+
+  EXPECT_EQ(lines.size(), 2u);
+  EXPECT_TRUE(std::find(lines.cbegin(),
+                        lines.cend(),
+                        "HLTestInline;->inlineMonomorphic(LSuper;)I+]LSuper;LSubA;") !=
+              lines.cend());
+  EXPECT_TRUE(std::find(lines.cbegin(),
+                        lines.cend(),
+                        "HLTestInlineSubtype;->inlineMonomorphic(LSuper;)I") != lines.cend());
+}
+
 TEST_F(ProfileAssistantTest, TestProfileCreateWithInvalidData) {
   // Create the profile content.
   std::vector<std::string> profile_methods = {
-    "HLTestInline;->inlineMonomorphic(LSuper;)I+invalid_class",
-    "HLTestInline;->invalid_method",
-    "invalid_class"
+    "HLTestInline;->inlineMonomorphic(LSuper;)I+invalid_class",  // Invalid descriptor for IC.
+    "HLTestInline;->invalid_method",  // Invalid method spec (no signature).
+    "invalid_class",  // Invalid descriptor.
   };
   std::string input_file_contents;
   for (std::string& m : profile_methods) {
@@ -1166,7 +1654,6 @@
 
   // Load the profile from disk.
   ProfileCompilationInfo info;
-  profile_file.GetFile()->ResetOffset();
   ASSERT_TRUE(info.Load(GetFd(profile_file)));
 
   // Load the dex files and verify that the profile contains the expected methods info.
@@ -1179,33 +1666,24 @@
                                                    "inlineMonomorphic");
   const DexFile* dex_file = inline_monomorphic->GetDexFile();
 
-  // Verify that the inline cache contains the invalid type.
-  std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> pmi =
-      info.GetHotMethodInfo(MethodReference(dex_file, inline_monomorphic->GetDexMethodIndex()));
-  ASSERT_TRUE(pmi != nullptr);
-  ASSERT_EQ(pmi->inline_caches->size(), 1u);
-  const ProfileCompilationInfo::DexPcData& dex_pc_data = pmi->inline_caches->begin()->second;
-  dex::TypeIndex invalid_class_index(std::numeric_limits<uint16_t>::max() - 1);
-  ASSERT_EQ(1u, dex_pc_data.classes.size());
-  ASSERT_EQ(invalid_class_index, dex_pc_data.classes.begin()->type_index);
+  // Invalid descriptor in IC results in rejection of the entire line.
+  ProfileCompilationInfo::MethodHotness hotness =
+      info.GetMethodHotness(MethodReference(dex_file, inline_monomorphic->GetDexMethodIndex()));
+  ASSERT_FALSE(hotness.IsHot());
 
-  // Verify that the start-up classes contain the invalid class.
+  // No data was recorded, so the dex file does not appear in the profile.
+  // TODO: Record all dex files passed to `profman` in the profile. Note that
+  // this makes sense only if there are no annotations, otherwise we do not
+  // know what annotation to use with each dex file.
   std::set<dex::TypeIndex> classes;
   std::set<uint16_t> hot_methods;
   std::set<uint16_t> startup_methods;
   std::set<uint16_t> post_start_methods;
-  ASSERT_TRUE(info.GetClassesAndMethods(*dex_file,
-                                        &classes,
-                                        &hot_methods,
-                                        &startup_methods,
-                                        &post_start_methods));
-  ASSERT_EQ(1u, classes.size());
-  ASSERT_TRUE(classes.find(invalid_class_index) != classes.end());
-
-  // Verify that the invalid method did not get in the profile.
-  ASSERT_EQ(1u, hot_methods.size());
-  uint16_t invalid_method_index = std::numeric_limits<uint16_t>::max() - 1;
-  ASSERT_FALSE(hot_methods.find(invalid_method_index) != hot_methods.end());
+  ASSERT_FALSE(info.GetClassesAndMethods(*dex_file,
+                                         &classes,
+                                         &hot_methods,
+                                         &startup_methods,
+                                         &post_start_methods));
 }
 
 TEST_F(ProfileAssistantTest, DumpOnly) {
@@ -1314,14 +1792,8 @@
   // Verify that we can load the result.
 
   ProfileCompilationInfo result;
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
   ASSERT_TRUE(result.Load(reference_profile_fd));
 
-
-  ASSERT_TRUE(profile1.GetFile()->ResetOffset());
-  ASSERT_TRUE(profile2.GetFile()->ResetOffset());
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
-
   // Verify that the result filtered out data not belonging to the dex file.
   // This is equivalent to checking that the result is equal to the merging of
   // all profiles while filtering out data not belonging to the dex file.
@@ -1361,11 +1833,10 @@
   ProfileCompilationInfo info1;
   uint16_t num_methods_to_add = std::min(d1.NumMethodIds(), d2.NumMethodIds());
 
-  FakeDexStorage local_storage;
-  const DexFile* dex_to_be_updated1 = local_storage.AddFakeDex(
-      "fake-location1", d1.GetLocationChecksum(), d1.NumMethodIds());
-  const DexFile* dex_to_be_updated2 = local_storage.AddFakeDex(
-      "fake-location2", d2.GetLocationChecksum(), d2.NumMethodIds());
+  const DexFile* dex_to_be_updated1 = BuildDex(
+      "fake-location1", d1.GetLocationChecksum(), "LC;", d1.NumMethodIds(), d1.NumTypeIds());
+  const DexFile* dex_to_be_updated2 = BuildDex(
+      "fake-location2", d2.GetLocationChecksum(), "LC;", d2.NumMethodIds(), d2.NumTypeIds());
   SetupProfile(dex_to_be_updated1,
                dex_to_be_updated2,
                num_methods_to_add,
@@ -1391,17 +1862,15 @@
 
   // Verify that we can load the result.
   ProfileCompilationInfo result;
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
   ASSERT_TRUE(result.Load(reference_profile.GetFd()));
 
   // Verify that the renaming was done.
   for (uint16_t i = 0; i < num_methods_to_add; i ++) {
-    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> pmi;
-    ASSERT_TRUE(result.GetHotMethodInfo(MethodReference(&d1, i)) != nullptr) << i;
-    ASSERT_TRUE(result.GetHotMethodInfo(MethodReference(&d2, i)) != nullptr) << i;
+    ASSERT_TRUE(result.GetMethodHotness(MethodReference(&d1, i)).IsHot()) << i;
+    ASSERT_TRUE(result.GetMethodHotness(MethodReference(&d2, i)).IsHot()) << i;
 
-    ASSERT_TRUE(result.GetHotMethodInfo(MethodReference(dex_to_be_updated1, i)) == nullptr);
-    ASSERT_TRUE(result.GetHotMethodInfo(MethodReference(dex_to_be_updated2, i)) == nullptr);
+    ASSERT_FALSE(result.GetMethodHotness(MethodReference(dex_to_be_updated1, i)).IsHot()) << i;
+    ASSERT_FALSE(result.GetMethodHotness(MethodReference(dex_to_be_updated2, i)).IsHot()) << i;
   }
 }
 
@@ -1420,7 +1889,7 @@
   for (size_t i = 0; i < num_methods; ++i) {
     hot_methods_ref.push_back(i);
   }
-  ProfileCompilationInfo info1;
+  ProfileCompilationInfo info1(/*for_boot_image=*/ true);
   SetupBasicProfile(dex1, hot_methods_cur, empty_vector, empty_vector,
       profile, &info1);
   ProfileCompilationInfo info2(/*for_boot_image=*/true);
@@ -1435,8 +1904,7 @@
 
   // Verify the result: it should be equal to info2 since info1 is a regular profile
   // and should be ignored.
-  ProfileCompilationInfo result;
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
+  ProfileCompilationInfo result(/*for_boot_image=*/ true);
   ASSERT_TRUE(result.Load(reference_profile.GetFd()));
   ASSERT_TRUE(result.Equals(info2));
 }
@@ -1449,6 +1917,17 @@
   const uint16_t kNumberOfClassesInRefProfile = 6000;
   const uint16_t kNumberOfClassesInCurProfile = 6110;  // Threshold is 2%.
 
+  const DexFile* dex1_7000 = BuildDex("location1_7000",
+                                      /*checksum=*/ 7001,
+                                      "LUnique1_7000;",
+                                      /*num_method_ids=*/ 0,
+                                      /*num_type_ids=*/ 7000);
+  const DexFile* dex2_7000 = BuildDex("location2_7000",
+                                      /*checksum=*/ 7002,
+                                      "LUnique2_7000;",
+                                      /*num_method_ids=*/ 0,
+                                      /*num_type_ids=*/ 7000);
+
   ScratchFile profile;
   ScratchFile reference_profile;
 
@@ -1456,9 +1935,9 @@
   int reference_profile_fd = GetFd(reference_profile);
 
   ProfileCompilationInfo info1;
-  SetupProfile(dex1, dex2, 0, kNumberOfClassesInRefProfile, profile,  &info1);
+  SetupProfile(dex1_7000, dex2_7000, 0, kNumberOfClassesInRefProfile, profile,  &info1);
   ProfileCompilationInfo info2;
-  SetupProfile(dex1, dex2, 0, kNumberOfClassesInCurProfile, reference_profile, &info2);
+  SetupProfile(dex1_7000, dex2_7000, 0, kNumberOfClassesInCurProfile, reference_profile, &info2);
 
   std::vector<const std::string> extra_args({"--force-merge"});
   int return_code = ProcessProfiles(profile_fds, reference_profile_fd, extra_args);
@@ -1467,7 +1946,6 @@
 
   // Check that the result is the aggregation.
   ProfileCompilationInfo result;
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
   ASSERT_TRUE(result.Load(reference_profile.GetFd()));
   ASSERT_TRUE(info1.MergeWith(info2));
   ASSERT_TRUE(result.Equals(info1));
@@ -1486,14 +1964,13 @@
   const DexFile& d1 = *dex_files[0];
   const DexFile& d2 = *dex_files[1];
   // The new profile info will contain the methods with indices 0-100.
-  ProfileCompilationInfo info(/*for_boot_image*/ true);
+  ProfileCompilationInfo info(/*for_boot_image=*/ true);
   ProfileCompilationInfo::ProfileSampleAnnotation psa1("package1");
   ProfileCompilationInfo::ProfileSampleAnnotation psa2("package2");
 
   AddMethod(&info, &d1, 0, Hotness::kFlagHot, psa1);
   AddMethod(&info, &d2, 0, Hotness::kFlagHot, psa2);
   info.Save(profile.GetFd());
-  profile.GetFile()->ResetOffset();
 
   // Run profman and pass the dex file with --apk-fd.
   android::base::unique_fd apk_fd(
@@ -1513,8 +1990,7 @@
   EXPECT_EQ(ExecAndReturnCode(argv_str, &error), ProfileAssistant::kSuccess) << error;
 
   // Verify that we can load the result and that it equals to what we saved.
-  ProfileCompilationInfo result;
-  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
+  ProfileCompilationInfo result(/*for_boot_image=*/ true);
   ASSERT_TRUE(result.Load(reference_profile_fd));
   ASSERT_TRUE(info.Equals(result));
 }
@@ -1523,24 +1999,25 @@
   ScratchFile profile1;
   ScratchFile profile2;
 
-  ProfileCompilationInfo info1(/*for_boot_image*/ false);
+  ProfileCompilationInfo info1(/*for_boot_image=*/ false);
   info1.Save(profile1.GetFd());
-  profile1.GetFile()->ResetOffset();
 
-  ProfileCompilationInfo info2(/*for_boot_image*/ true);
+  ProfileCompilationInfo info2(/*for_boot_image=*/ true);
   info2.Save(profile2.GetFd());
-  profile2.GetFile()->ResetOffset();
 
   std::vector<int> profile_fds({ GetFd(profile1)});
   int reference_profile_fd = GetFd(profile2);
-  ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd),
+  std::vector<const std::string> boot_image_args({"--boot-image-merge"});
+  ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd, boot_image_args),
             ProfileAssistant::kErrorDifferentVersions);
+  ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd),
+            ProfileAssistant::kErrorBadProfiles);
 
   // Reverse the order of the profiles to verify we get the same behaviour.
   profile_fds[0] = GetFd(profile2);
   reference_profile_fd = GetFd(profile1);
-  profile1.GetFile()->ResetOffset();
-  profile2.GetFile()->ResetOffset();
+  ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd, boot_image_args),
+            ProfileAssistant::kErrorBadProfiles);
   ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd),
             ProfileAssistant::kErrorDifferentVersions);
 }
@@ -1555,27 +2032,26 @@
   // Write corrupt data in the first file.
   std::string content = "giberish";
   ASSERT_TRUE(profile1.GetFile()->WriteFully(content.c_str(), content.length()));
-  profile1.GetFile()->ResetOffset();
 
-  ProfileCompilationInfo info2(/*for_boot_image*/ true);
+  ProfileCompilationInfo info2(/*for_boot_image=*/ true);
   info2.Save(profile2.GetFd());
-  profile2.GetFile()->ResetOffset();
 
   std::vector<int> profile_fds({ GetFd(profile1)});
   int reference_profile_fd = GetFd(profile2);
 
   // With force-merge we should merge successfully.
-  std::vector<const std::string> extra_args({"--force-merge"});
+  std::vector<const std::string> extra_args({"--force-merge", "--boot-image-merge"});
   ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd, extra_args),
             ProfileAssistant::kSuccess);
 
-  ProfileCompilationInfo result;
-  ASSERT_TRUE(profile2.GetFile()->ResetOffset());
+  ProfileCompilationInfo result(/*for_boot_image=*/ true);
   ASSERT_TRUE(result.Load(reference_profile_fd));
   ASSERT_TRUE(info2.Equals(result));
 
   // Without force-merge we should fail.
-  ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd, extra_args),
+  std::vector<const std::string> extra_args2({"--boot-image-merge"});
+  ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd, extra_args2),
             ProfileAssistant::kErrorBadProfiles);
 }
+
 }  // namespace art
diff --git a/profman/profman.cc b/profman/profman.cc
index a011cd0..1968468 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -21,11 +21,15 @@
 #include <sys/param.h>
 #include <unistd.h>
 
+#include <cstdint>
 #include <fstream>
 #include <iostream>
+#include <optional>
+#include <ostream>
 #include <set>
 #include <string>
 #include <string_view>
+#include <tuple>
 #include <unordered_set>
 #include <vector>
 
@@ -33,6 +37,7 @@
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
 
+#include "base/array_ref.h"
 #include "base/dumpable.h"
 #include "base/logging.h"  // For InitLogging.
 #include "base/mem_map.h"
@@ -47,10 +52,14 @@
 #include "dex/art_dex_file_loader.h"
 #include "dex/bytecode_utils.h"
 #include "dex/class_accessor-inl.h"
+#include "dex/class_reference.h"
 #include "dex/code_item_accessors-inl.h"
+#include "dex/descriptors_names.h"
 #include "dex/dex_file.h"
 #include "dex/dex_file_loader.h"
+#include "dex/dex_file_structs.h"
 #include "dex/dex_file_types.h"
+#include "dex/method_reference.h"
 #include "dex/type_reference.h"
 #include "profile/profile_boot_info.h"
 #include "profile/profile_compilation_info.h"
@@ -72,10 +81,8 @@
   return android::base::Join(command, ' ');
 }
 
-static constexpr int kInvalidFd = -1;
-
 static bool FdIsValid(int fd) {
-  return fd != kInvalidFd;
+  return fd != File::kInvalidFd;
 }
 
 static void UsageErrorV(const char* fmt, va_list ap) {
@@ -136,15 +143,17 @@
   UsageError("  --generate-test-profile-seed=<number>: seed for random number generator used when");
   UsageError("      generating random test profiles. Defaults to using NanoTime.");
   UsageError("");
-  UsageError("  --create-profile-from=<filename>: creates a profile from a list of classes and");
-  UsageError("      methods.");
+  UsageError("  --create-profile-from=<filename>: creates a profile from a list of classes,");
+  UsageError("      methods and inline caches.");
+  UsageError("  --output-profile-type=(app|boot|bprof): Select output profile format for");
+  UsageError("      the --create-profile-from option. Default: app.");
   UsageError("");
   UsageError("  --dex-location=<string>: location string to use with corresponding");
   UsageError("      apk-fd to find dex files");
   UsageError("");
   UsageError("  --apk-fd=<number>: file descriptor containing an open APK to");
   UsageError("      search for dex files");
-  UsageError("  --apk-=<filename>: an APK to search for dex files");
+  UsageError("  --apk=<filename>: an APK to search for dex files");
   UsageError("  --skip-apk-verification: do not attempt to verify APKs");
   UsageError("");
   UsageError("  --generate-boot-image-profile: Generate a boot image profile based on input");
@@ -161,7 +170,7 @@
   UsageError("  --preloaded-class-threshold=percentage between 0 and 100");
   UsageError("      what threshold to apply to the classes when deciding whether or not to");
   UsageError("      include it in the final preloaded classes.");
-  UsageError("  --preloaded-classes-blacklist=file");
+  UsageError("  --preloaded-classes-denylist=file");
   UsageError("      a file listing the classes that should not be preloaded in Zygote");
   UsageError("  --upgrade-startup-to-hot=true|false:");
   UsageError("      whether or not to upgrade startup methods to hot");
@@ -179,6 +188,10 @@
   UsageError("      In this case, the reference profile must have a boot profile version.");
   UsageError("  --force-merge: performs a forced merge, without analyzing if there is a");
   UsageError("      significant difference between the current profile and the reference profile.");
+  UsageError("  --min-new-methods-percent-change=percentage between 0 and 100 (default 20)");
+  UsageError("      the min percent of new methods to trigger a compilation.");
+  UsageError("  --min-new-classes-percent-change=percentage between 0 and 100 (default 20)");
+  UsageError("      the min percent of new classes to trigger a compilation.");
   UsageError("");
 
   exit(EXIT_FAILURE);
@@ -192,12 +205,12 @@
 // Separators used when parsing human friendly representation of profiles.
 static const std::string kMethodSep = "->";  // NOLINT [runtime/string] [4]
 static const std::string kMissingTypesMarker = "missing_types";  // NOLINT [runtime/string] [4]
-static const std::string kInvalidClassDescriptor = "invalid_class";  // NOLINT [runtime/string] [4]
-static const std::string kInvalidMethod = "invalid_method";  // NOLINT [runtime/string] [4]
+static const std::string kMegamorphicTypesMarker = "megamorphic_types";  // NOLINT [runtime/string] [4]
 static const std::string kClassAllMethods = "*";  // NOLINT [runtime/string] [4]
 static constexpr char kAnnotationStart = '{';
 static constexpr char kAnnotationEnd = '}';
 static constexpr char kProfileParsingInlineChacheSep = '+';
+static constexpr char kProfileParsingInlineChacheTargetSep = ']';
 static constexpr char kProfileParsingTypeSep = ',';
 static constexpr char kProfileParsingFirstCharInSignature = '(';
 static constexpr char kMethodFlagStringHot = 'H';
@@ -264,17 +277,41 @@
   *out = result == android::base::ParseBoolResult::kTrue;
 }
 
+enum class OutputProfileType {
+  kApp,
+  kBoot,
+  kBprof,
+};
+
+static void ParseOutputProfileType(const char* raw_option,
+                                   std::string_view option_prefix,
+                                   OutputProfileType* out) {
+  DCHECK(EndsWith(option_prefix, "="));
+  DCHECK(StartsWith(raw_option, option_prefix)) << raw_option << " " << option_prefix;
+  const char* value_string = raw_option + option_prefix.size();
+  if (strcmp(value_string, "app") == 0) {
+    *out = OutputProfileType::kApp;
+  } else if (strcmp(value_string, "boot") == 0) {
+    *out = OutputProfileType::kBoot;
+  } else if (strcmp(value_string, "bprof") == 0) {
+    *out = OutputProfileType::kBprof;
+  } else {
+    std::string option_name(option_prefix.substr(option_prefix.size() - 1u));
+    Usage("Failed to parse %s '%s' as (app|boot|bprof)", option_name.c_str(), value_string);
+  }
+}
+
 // TODO(calin): This class has grown too much from its initial design. Split the functionality
 // into smaller, more contained pieces.
 class ProfMan final {
  public:
   ProfMan() :
-      reference_profile_file_fd_(kInvalidFd),
+      reference_profile_file_fd_(File::kInvalidFd),
       dump_only_(false),
       dump_classes_and_methods_(false),
       generate_boot_image_profile_(false),
-      generate_boot_profile_(false),
-      dump_output_to_fd_(kInvalidFd),
+      output_profile_type_(OutputProfileType::kApp),
+      dump_output_to_fd_(File::kInvalidFd),
       test_profile_num_dex_(kDefaultTestProfileNumDex),
       test_profile_method_percerntage_(kDefaultTestProfileMethodPercentage),
       test_profile_class_percentage_(kDefaultTestProfileClassPercentage),
@@ -315,10 +352,10 @@
         dump_classes_and_methods_ = true;
       } else if (StartsWith(option, "--create-profile-from=")) {
         create_profile_from_file_ = std::string(option.substr(strlen("--create-profile-from=")));
+      } else if (StartsWith(option, "--output-profile-type=")) {
+        ParseOutputProfileType(raw_option, "--output-profile-type=", &output_profile_type_);
       } else if (StartsWith(option, "--dump-output-to-fd=")) {
         ParseUintOption(raw_option, "--dump-output-to-fd=", &dump_output_to_fd_);
-      } else if (option == "--generate-boot-profile") {
-        generate_boot_profile_ = true;
       } else if (option == "--generate-boot-image-profile") {
         generate_boot_image_profile_ = true;
       } else if (StartsWith(option, "--method-threshold=")) {
@@ -345,15 +382,15 @@
                         &boot_image_options_.preloaded_class_threshold,
                         0u,
                         100u);
-      } else if (StartsWith(option, "--preloaded-classes-blacklist=")) {
-        std::string preloaded_classes_blacklist =
-            std::string(option.substr(strlen("--preloaded-classes-blacklist=")));
+      } else if (StartsWith(option, "--preloaded-classes-denylist=")) {
+        std::string preloaded_classes_denylist =
+            std::string(option.substr(strlen("--preloaded-classes-denylist=")));
         // Read the user-specified list of methods.
         std::unique_ptr<std::set<std::string>>
-            blacklist(ReadCommentedInputFromFile<std::set<std::string>>(
-                preloaded_classes_blacklist.c_str(), nullptr));  // No post-processing.
-        boot_image_options_.preloaded_classes_blacklist.insert(
-            blacklist->begin(), blacklist->end());
+            denylist(ReadCommentedInputFromFile<std::set<std::string>>(
+                preloaded_classes_denylist.c_str(), nullptr));  // No post-processing.
+        boot_image_options_.preloaded_classes_denylist.insert(
+            denylist->begin(), denylist->end());
       } else if (StartsWith(option, "--upgrade-startup-to-hot=")) {
         ParseBoolOption(raw_option,
                         "--upgrade-startup-to-hot=",
@@ -406,6 +443,24 @@
                         &test_profile_class_percentage_);
       } else if (StartsWith(option, "--generate-test-profile-seed=")) {
         ParseUintOption(raw_option, "--generate-test-profile-seed=", &test_profile_seed_);
+      } else if (StartsWith(option, "--min-new-methods-percent-change=")) {
+        uint32_t min_new_methods_percent_change;
+        ParseUintOption(raw_option,
+                        "--min-new-methods-percent-change=",
+                        &min_new_methods_percent_change,
+                        0u,
+                        100u);
+        profile_assistant_options_.SetMinNewMethodsPercentChangeForCompilation(
+            min_new_methods_percent_change);
+      } else if (StartsWith(option, "--min-new-classes-percent-change=")) {
+        uint32_t min_new_classes_percent_change;
+        ParseUintOption(raw_option,
+                        "--min-new-classes-percent-change=",
+                        &min_new_classes_percent_change,
+                        0u,
+                        100u);
+        profile_assistant_options_.SetMinNewClassesPercentChangeForCompilation(
+            min_new_classes_percent_change);
       } else if (option == "--copy-and-update-profile-key") {
         copy_and_update_profile_key_ = true;
       } else if (option == "--boot-image-merge") {
@@ -609,7 +664,9 @@
 #endif
   }
 
-  std::unique_ptr<const ProfileCompilationInfo> LoadProfile(const std::string& filename, int fd) {
+  std::unique_ptr<const ProfileCompilationInfo> LoadProfile(const std::string& filename,
+                                                            int fd,
+                                                            bool for_boot_image) {
     if (!filename.empty()) {
 #ifdef _WIN32
       int flags = O_RDWR;
@@ -622,7 +679,7 @@
         return nullptr;
       }
     }
-    std::unique_ptr<ProfileCompilationInfo> info(new ProfileCompilationInfo);
+    std::unique_ptr<ProfileCompilationInfo> info(new ProfileCompilationInfo(for_boot_image));
     if (!info->Load(fd)) {
       LOG(ERROR) << "Cannot load profile info from fd=" << fd << "\n";
       return nullptr;
@@ -635,7 +692,12 @@
                      int fd,
                      const std::vector<std::unique_ptr<const DexFile>>* dex_files,
                      std::string* dump) {
-    std::unique_ptr<const ProfileCompilationInfo> info(LoadProfile(filename, fd));
+    // For dumping, try loading as app profile and if that fails try loading as boot profile.
+    std::unique_ptr<const ProfileCompilationInfo> info =
+        LoadProfile(filename, fd, /*for_boot_image=*/ false);
+    if (info == nullptr) {
+      info = LoadProfile(filename, fd, /*for_boot_image=*/ true);
+    }
     if (info == nullptr) {
       LOG(ERROR) << "Cannot load profile info from filename=" << filename << " fd=" << fd;
       return -1;
@@ -684,7 +746,7 @@
       }
     }
     for (const std::string& profile_file : profile_files_) {
-      int ret = DumpOneProfile(kOrdinaryProfile, profile_file, kInvalidFd, &dex_files, &dump);
+      int ret = DumpOneProfile(kOrdinaryProfile, profile_file, File::kInvalidFd, &dex_files, &dump);
       if (ret != 0) {
         return ret;
       }
@@ -703,7 +765,7 @@
     if (!reference_profile_file_.empty()) {
       int ret = DumpOneProfile(kReferenceProfile,
                                reference_profile_file_,
-                               kInvalidFd,
+                               File::kInvalidFd,
                                &dex_files,
                                &dump);
       if (ret != 0) {
@@ -725,14 +787,80 @@
     return dump_only_;
   }
 
-  bool GetClassNamesAndMethods(int fd,
+  // Creates the inline-cache portion of a text-profile line. If there is no
+  // inline-caches this will be and empty string. Otherwise it will be '@'
+  // followed by an IC description matching the format described by ProcessLine
+  // below. Note that this will collapse all ICs with the same receiver type.
+  std::string GetInlineCacheLine(const ProfileCompilationInfo& profile_info,
+                                 const dex::MethodId& id,
+                                 const DexFile* dex_file,
+                                 uint16_t dex_method_idx) {
+    ProfileCompilationInfo::MethodHotness hotness =
+        profile_info.GetMethodHotness(MethodReference(dex_file, dex_method_idx));
+    DCHECK(!hotness.IsHot() || hotness.GetInlineCacheMap() != nullptr);
+    if (!hotness.IsHot() || hotness.GetInlineCacheMap()->empty()) {
+      return "";
+    }
+    const ProfileCompilationInfo::InlineCacheMap* inline_caches = hotness.GetInlineCacheMap();
+    struct IcLineInfo {
+      bool is_megamorphic_ = false;
+      bool is_missing_types_ = false;
+      std::set<dex::TypeIndex> classes_;
+    };
+    std::unordered_map<dex::TypeIndex, IcLineInfo> ics;
+    CodeItemInstructionAccessor accessor(
+        *dex_file,
+        dex_file->GetCodeItem(dex_file->FindCodeItemOffset(*dex_file->FindClassDef(id.class_idx_),
+                                                            dex_method_idx)));
+    for (const auto& [pc, ic_data] : *inline_caches) {
+      const Instruction& inst = accessor.InstructionAt(pc);
+      const dex::MethodId& target = dex_file->GetMethodId(inst.VRegB());
+      if (ic_data.classes.empty() && !ic_data.is_megamorphic && !ic_data.is_missing_types) {
+        continue;
+      }
+      auto val = ics.find(target.class_idx_);
+      if (val == ics.end()) {
+        val = ics.insert({ target.class_idx_, {} }).first;
+      }
+      if (ic_data.is_megamorphic) {
+        val->second.is_megamorphic_ = true;
+      }
+      if (ic_data.is_missing_types) {
+        val->second.is_missing_types_ = true;
+      }
+      for (dex::TypeIndex type_index : ic_data.classes) {
+        val->second.classes_.insert(type_index);
+      }
+    }
+    if (ics.empty()) {
+      return "";
+    }
+    std::ostringstream dump_ic;
+    dump_ic << kProfileParsingInlineChacheSep;
+    for (const auto& [target, dex_data] : ics) {
+      dump_ic << kProfileParsingInlineChacheTargetSep;
+      dump_ic << dex_file->GetTypeDescriptor(dex_file->GetTypeId(target));
+      if (dex_data.is_missing_types_) {
+        dump_ic << kMissingTypesMarker;
+      } else if (dex_data.is_megamorphic_) {
+        dump_ic << kMegamorphicTypesMarker;
+      } else {
+        bool first = true;
+        for (dex::TypeIndex type_index : dex_data.classes_) {
+          if (!first) {
+            dump_ic << kProfileParsingTypeSep;
+          }
+          first = false;
+          dump_ic << profile_info.GetTypeDescriptor(dex_file, type_index);
+        }
+      }
+    }
+    return dump_ic.str();
+  }
+
+  bool GetClassNamesAndMethods(const ProfileCompilationInfo& profile_info,
                                std::vector<std::unique_ptr<const DexFile>>* dex_files,
                                std::set<std::string>* out_lines) {
-    ProfileCompilationInfo profile_info;
-    if (!profile_info.Load(fd)) {
-      LOG(ERROR) << "Cannot load profile info";
-      return false;
-    }
     for (const std::unique_ptr<const DexFile>& dex_file : *dex_files) {
       std::set<dex::TypeIndex> class_types;
       std::set<uint16_t> hot_methods;
@@ -745,8 +873,7 @@
                                             &startup_methods,
                                             &post_startup_methods)) {
         for (const dex::TypeIndex& type_index : class_types) {
-          const dex::TypeId& type_id = dex_file->GetTypeId(type_index);
-          out_lines->insert(std::string(dex_file->GetTypeDescriptor(type_id)));
+          out_lines->insert(profile_info.GetTypeDescriptor(dex_file.get(), type_index));
         }
         combined_methods = hot_methods;
         combined_methods.insert(startup_methods.begin(), startup_methods.end());
@@ -766,17 +893,30 @@
           if (post_startup_methods.find(dex_method_idx) != post_startup_methods.end()) {
             flags_string += kMethodFlagStringPostStartup;
           }
-          out_lines->insert(flags_string +
-                            type_string +
-                            kMethodSep +
-                            method_name +
-                            signature_string);
+          std::string inline_cache_string =
+              GetInlineCacheLine(profile_info, id, dex_file.get(), dex_method_idx);
+          out_lines->insert(flags_string + type_string + kMethodSep + method_name +
+                            signature_string + inline_cache_string);
         }
       }
     }
     return true;
   }
 
+  bool GetClassNamesAndMethods(int fd,
+                               std::vector<std::unique_ptr<const DexFile>>* dex_files,
+                               std::set<std::string>* out_lines) {
+    // For dumping, try loading as app profile and if that fails try loading as boot profile.
+    for (bool for_boot_image : {false, true}) {
+      ProfileCompilationInfo profile_info(for_boot_image);
+      if (profile_info.Load(fd)) {
+        return GetClassNamesAndMethods(profile_info, dex_files, out_lines);
+      }
+    }
+    LOG(ERROR) << "Cannot load profile info";
+    return false;
+  }
+
   bool GetClassNamesAndMethods(const std::string& profile_file,
                                std::vector<std::unique_ptr<const DexFile>>* dex_files,
                                std::set<std::string>* out_lines) {
@@ -895,74 +1035,56 @@
     return output.release();
   }
 
-  // Find class klass_descriptor in the given dex_files and store its reference
-  // in the out parameter class_ref.
-  // Return true if the definition or a reference of the class was found in any
-  // of the dex_files.
-  bool FindClass(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
-                 const std::string& klass_descriptor,
-                 /*out*/TypeReference* class_ref) {
-    constexpr uint16_t kInvalidTypeIndex = std::numeric_limits<uint16_t>::max() - 1;
-    for (const std::unique_ptr<const DexFile>& dex_file_ptr : dex_files) {
-      const DexFile* dex_file = dex_file_ptr.get();
-      if (klass_descriptor == kInvalidClassDescriptor) {
-        if (kInvalidTypeIndex >= dex_file->NumTypeIds()) {
-          // The dex file does not contain all possible type ids which leaves us room
-          // to add an "invalid" type id.
-          *class_ref = TypeReference(dex_file, dex::TypeIndex(kInvalidTypeIndex));
-          return true;
-        } else {
-          // The dex file contains all possible type ids. We don't have any free type id
-          // that we can use as invalid.
-          continue;
+  // Find class definition for a descriptor.
+  const dex::ClassDef* FindClassDef(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
+                                    std::string_view klass_descriptor,
+                                    /*out*/ TypeReference* class_ref) {
+    for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+      const dex::TypeId* type_id = dex_file->FindTypeId(klass_descriptor);
+      if (type_id != nullptr) {
+        dex::TypeIndex type_index = dex_file->GetIndexForTypeId(*type_id);
+        const dex::ClassDef* class_def = dex_file->FindClassDef(type_index);
+        if (class_def != nullptr) {
+          *class_ref = TypeReference(dex_file.get(), type_index);
+          return class_def;
         }
       }
-
-      const dex::TypeId* type_id = dex_file->FindTypeId(klass_descriptor.c_str());
-      if (type_id == nullptr) {
-        continue;
-      }
-      dex::TypeIndex type_index = dex_file->GetIndexForTypeId(*type_id);
-      *class_ref = TypeReference(dex_file, type_index);
-
-      if (dex_file->FindClassDef(type_index) == nullptr) {
-        // Class is only referenced in the current dex file but not defined in it.
-        // We use its current type reference, but keep looking for its
-        // definition.
-        // Note that array classes fall into that category, as they do not have
-        // a class definition.
-        continue;
-      }
-      return true;
     }
-    // If we arrive here, we haven't found a class definition. If the dex file
-    // of the class reference is not null, then we have found a type reference,
-    // and we return that to the caller.
-    return (class_ref->dex_file != nullptr);
+    return nullptr;
+  }
+
+  // Find class klass_descriptor in the given dex_files and store its reference
+  // in the out parameter class_ref.
+  // Return true if a reference of the class was found in any of the dex_files.
+  bool FindClass(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
+                 std::string_view klass_descriptor,
+                 /*out*/ TypeReference* class_ref) {
+    for (const std::unique_ptr<const DexFile>& dex_file_ptr : dex_files) {
+      const DexFile* dex_file = dex_file_ptr.get();
+      const dex::TypeId* type_id = dex_file->FindTypeId(klass_descriptor);
+      if (type_id != nullptr) {
+        *class_ref = TypeReference(dex_file, dex_file->GetIndexForTypeId(*type_id));
+        return true;
+      }
+    }
+    return false;
   }
 
   // Find the method specified by method_spec in the class class_ref.
   uint32_t FindMethodIndex(const TypeReference& class_ref,
-                           const std::string& method_spec) {
+                           std::string_view method_spec) {
     const DexFile* dex_file = class_ref.dex_file;
-    if (method_spec == kInvalidMethod) {
-      constexpr uint16_t kInvalidMethodIndex = std::numeric_limits<uint16_t>::max() - 1;
-      return kInvalidMethodIndex >= dex_file->NumMethodIds()
-             ? kInvalidMethodIndex
-             : dex::kDexNoIndex;
-    }
 
-    std::vector<std::string> name_and_signature;
-    Split(method_spec, kProfileParsingFirstCharInSignature, &name_and_signature);
-    if (name_and_signature.size() != 2) {
-      LOG(ERROR) << "Invalid method name and signature " << method_spec;
+    size_t signature_start = method_spec.find(kProfileParsingFirstCharInSignature);
+    if (signature_start == std::string_view::npos) {
+      LOG(ERROR) << "Invalid method name and signature: " << method_spec;
       return dex::kDexNoIndex;
     }
 
-    const std::string& name = name_and_signature[0];
-    const std::string& signature = kProfileParsingFirstCharInSignature + name_and_signature[1];
+    const std::string_view name = method_spec.substr(0u, signature_start);
+    const std::string_view signature = method_spec.substr(signature_start);
 
-    const dex::StringId* name_id = dex_file->FindStringId(name.c_str());
+    const dex::StringId* name_id = dex_file->FindStringId(std::string(name).c_str());
     if (name_id == nullptr) {
       LOG(WARNING) << "Could not find name: "  << name;
       return dex::kDexNoIndex;
@@ -970,7 +1092,7 @@
     dex::TypeIndex return_type_idx;
     std::vector<dex::TypeIndex> param_type_idxs;
     if (!dex_file->CreateTypeList(signature, &return_type_idx, &param_type_idxs)) {
-      LOG(WARNING) << "Could not create type list" << signature;
+      LOG(WARNING) << "Could not create type list: " << signature;
       return dex::kDexNoIndex;
     }
     const dex::ProtoId* proto_id = dex_file->FindProtoId(return_type_idx, param_type_idxs);
@@ -988,63 +1110,243 @@
     return dex_file->GetIndexForMethodId(*method_id);
   }
 
+  template <typename Visitor>
+  void VisitAllInstructions(const TypeReference& class_ref, uint16_t method_idx, Visitor visitor) {
+    const DexFile* dex_file = class_ref.dex_file;
+    const dex::ClassDef* def = dex_file->FindClassDef(class_ref.TypeIndex());
+    if (def == nullptr) {
+      return;
+    }
+    std::optional<uint32_t> offset = dex_file->GetCodeItemOffset(*def, method_idx);
+    if (offset.has_value()) {
+      for (const DexInstructionPcPair& inst :
+          CodeItemInstructionAccessor(*dex_file, dex_file->GetCodeItem(*offset))) {
+        if (!visitor(inst)) {
+          break;
+        }
+      }
+    } else {
+      LOG(WARNING) << "Could not find method " << method_idx;
+    }
+  }
+
+  // Get dex-pcs of any virtual + interface invokes referencing a method of the
+  // 'target' type in the given method.
+  void GetAllInvokes(const TypeReference& class_ref,
+                     uint16_t method_idx,
+                     dex::TypeIndex target,
+                     /*out*/ std::vector<uint32_t>* dex_pcs) {
+    const DexFile* dex_file = class_ref.dex_file;
+    VisitAllInstructions(class_ref, method_idx, [&](const DexInstructionPcPair& inst) -> bool {
+      switch (inst->Opcode()) {
+        case Instruction::INVOKE_INTERFACE:
+        case Instruction::INVOKE_INTERFACE_RANGE:
+        case Instruction::INVOKE_VIRTUAL:
+        case Instruction::INVOKE_VIRTUAL_RANGE: {
+          const dex::MethodId& meth = dex_file->GetMethodId(inst->VRegB());
+          if (meth.class_idx_ == target) {
+            dex_pcs->push_back(inst.DexPc());
+          }
+          break;
+        }
+        default:
+          break;
+      }
+      return true;
+    });
+  }
+
   // Given a method, return true if the method has a single INVOKE_VIRTUAL in its byte code.
   // Upon success it returns true and stores the method index and the invoke dex pc
   // in the output parameters.
   // The format of the method spec is "inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;".
-  //
-  // TODO(calin): support INVOKE_INTERFACE and the range variants.
   bool HasSingleInvoke(const TypeReference& class_ref,
                        uint16_t method_index,
-                       /*out*/uint32_t* dex_pc) {
-    const DexFile* dex_file = class_ref.dex_file;
-    uint32_t offset = dex_file->FindCodeItemOffset(
-        *dex_file->FindClassDef(class_ref.TypeIndex()),
-        method_index);
-    const dex::CodeItem* code_item = dex_file->GetCodeItem(offset);
-
+                       /*out*/ uint32_t* dex_pc) {
     bool found_invoke = false;
-    for (const DexInstructionPcPair& inst : CodeItemInstructionAccessor(*dex_file, code_item)) {
+    bool found_multiple_invokes = false;
+    VisitAllInstructions(class_ref, method_index, [&](const DexInstructionPcPair& inst) -> bool {
       if (inst->Opcode() == Instruction::INVOKE_VIRTUAL ||
-          inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE) {
+          inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE ||
+          inst->Opcode() == Instruction::INVOKE_INTERFACE ||
+          inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE) {
         if (found_invoke) {
           LOG(ERROR) << "Multiple invoke INVOKE_VIRTUAL found: "
-                     << dex_file->PrettyMethod(method_index);
+                     << class_ref.dex_file->PrettyMethod(method_index);
           return false;
         }
         found_invoke = true;
         *dex_pc = inst.DexPc();
       }
-    }
+      return true;
+    });
     if (!found_invoke) {
-      LOG(ERROR) << "Could not find any INVOKE_VIRTUAL: " << dex_file->PrettyMethod(method_index);
+      LOG(ERROR) << "Could not find any INVOKE_VIRTUAL/INTERFACE: "
+                 << class_ref.dex_file->PrettyMethod(method_index);
     }
-    return found_invoke;
+    return found_invoke && !found_multiple_invokes;
+  }
+
+  struct InlineCacheSegment {
+   public:
+    using IcArray =
+        std::array<std::string_view, ProfileCompilationInfo::kIndividualInlineCacheSize + 1>;
+    static void SplitInlineCacheSegment(std::string_view ic_line,
+                                        /*out*/ std::vector<InlineCacheSegment>* res) {
+      if (ic_line[0] != kProfileParsingInlineChacheTargetSep) {
+        // single target
+        InlineCacheSegment out;
+        Split(ic_line, kProfileParsingTypeSep, &out.inline_caches_);
+        res->push_back(out);
+        return;
+      }
+      std::vector<std::string_view> targets_and_resolutions;
+      // Avoid a zero-length entry.
+      for (std::string_view t :
+           SplitString(ic_line.substr(1), kProfileParsingInlineChacheTargetSep)) {
+        InlineCacheSegment out;
+        DCHECK_EQ(t[0], 'L') << "Target is not a class? " << t;
+        size_t recv_end = t.find_first_of(';');
+        out.receiver_ = t.substr(0, recv_end + 1);
+        Split(t.substr(recv_end + 1), kProfileParsingTypeSep, &out.inline_caches_);
+        res->push_back(out);
+      }
+    }
+
+    bool IsSingleReceiver() const {
+      return !receiver_.has_value();
+    }
+
+    const std::string_view& GetReceiverType() const {
+      DCHECK(!IsSingleReceiver());
+      return *receiver_;
+    }
+
+    const IcArray& GetIcTargets() const {
+      return inline_caches_;
+    }
+
+    size_t NumIcTargets() const {
+      return std::count_if(
+          inline_caches_.begin(), inline_caches_.end(), [](const auto& x) { return !x.empty(); });
+    }
+
+    std::ostream& Dump(std::ostream& os) const {
+      if (!IsSingleReceiver()) {
+        os << "[" << GetReceiverType();
+      }
+      bool first = true;
+      for (std::string_view target : inline_caches_) {
+        if (target.empty()) {
+          break;
+        } else if (!first) {
+          os << ",";
+        }
+        first = false;
+        os << target;
+      }
+      return os;
+    }
+
+   private:
+    std::optional<std::string_view> receiver_;
+    // Max number of ics in the profile file. Don't need to store more than this
+    // (although internally we can have as many as we want). If we fill this up
+    // we are megamorphic.
+    IcArray inline_caches_;
+
+    friend std::ostream& operator<<(std::ostream& os, const InlineCacheSegment& ics);
+  };
+
+  struct ClassMethodReference {
+    TypeReference type_;
+    uint32_t method_index_;
+
+    bool operator==(const ClassMethodReference& ref) {
+      return ref.type_ == type_ && ref.method_index_ == method_index_;
+    }
+    bool operator!=(const ClassMethodReference& ref) {
+      return !(*this == ref);
+    }
+  };
+
+  // Try to perform simple method resolution to produce a more useful profile.
+  // This will resolve to the nearest class+method-index which is within the
+  // same dexfile and in a declared supertype of the starting class. It will
+  // return nullopt if it cannot find an appropriate method or the nearest
+  // possibility is private.
+  // TODO: This should ideally support looking in other dex files. That's getting
+  // to the point of needing to have a whole class-linker so it's probably not
+  // worth it.
+  std::optional<ClassMethodReference> ResolveMethod(TypeReference class_ref,
+                                                    uint32_t method_index) {
+    const DexFile* dex = class_ref.dex_file;
+    const dex::ClassDef* def = dex->FindClassDef(class_ref.TypeIndex());
+    if (def == nullptr || method_index >= dex->NumMethodIds()) {
+      // Class not in dex-file.
+      return std::nullopt;
+    }
+    if (LIKELY(dex->GetCodeItemOffset(*def, method_index).has_value())) {
+      return ClassMethodReference{class_ref, method_index};
+    }
+    // What to look for.
+    const dex::MethodId& method_id = dex->GetMethodId(method_index);
+    // No going between different dexs so use name and proto directly
+    const dex::ProtoIndex& method_proto = method_id.proto_idx_;
+    const dex::StringIndex& method_name = method_id.name_idx_;
+    // Floyd's algo to prevent infinite loops.
+    // Slow-iterator position for Floyd's
+    dex::TypeIndex slow_class_type = def->class_idx_;
+    // Whether to take a step with the slow iterator.
+    bool update_slow = false;
+    for (dex::TypeIndex cur_candidate = def->superclass_idx_;
+         cur_candidate != dex::TypeIndex::Invalid() && cur_candidate != slow_class_type;) {
+      const dex::ClassDef* cur_class_def = dex->FindClassDef(cur_candidate);
+      if (cur_class_def == nullptr) {
+        // We left the dex file.
+        return std::nullopt;
+      }
+      const dex::MethodId* cur_id =
+          dex->FindMethodIdByIndex(cur_candidate, method_name, method_proto);
+      if (cur_id != nullptr) {
+        if (dex->GetCodeItemOffset(*cur_class_def, dex->GetIndexForMethodId(*cur_id)).has_value()) {
+          return ClassMethodReference{TypeReference(dex, cur_candidate),
+                                      dex->GetIndexForMethodId(*cur_id)};
+        }
+      }
+      // Floyd's algo step.
+      cur_candidate = cur_class_def->superclass_idx_;
+      slow_class_type =
+          update_slow ? dex->FindClassDef(slow_class_type)->superclass_idx_ : slow_class_type;
+      update_slow = !update_slow;
+    }
+    return std::nullopt;
   }
 
   // Process a line defining a class or a method and its inline caches.
   // Upon success return true and add the class or the method info to profile.
+  // Inline caches are identified by the type of the declared receiver type.
   // The possible line formats are:
   // "LJustTheClass;".
   // "LTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;".
-  // "LTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,invalid_class".
   // "LTestInline;->inlineMissingTypes(LSuper;)I+missing_types".
+  // // Note no ',' after [LTarget;
+  // "LTestInline;->multiInlinePolymorphic(LSuper;)I+]LTarget1;LResA;,LResB;]LTarget2;LResC;,LResD;".
+  // "LTestInline;->multiInlinePolymorphic(LSuper;)I+]LTarget1;missing_types]LTarget2;LResC;,LResD;".
   // "{annotation}LTestInline;->inlineNoInlineCaches(LSuper;)I".
   // "LTestInline;->*".
-  // "invalid_class".
-  // "LTestInline;->invalid_method".
   // The method and classes are searched only in the given dex files.
   bool ProcessLine(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
-                   const std::string& maybe_annotated_line,
+                   std::string_view maybe_annotated_line,
                    /*out*/ProfileCompilationInfo* profile) {
     // First, process the annotation.
     if (maybe_annotated_line.empty()) {
       return true;
     }
     // Working line variable which will contain the user input without the annotations.
-    std::string line = maybe_annotated_line;
+    std::string_view line = maybe_annotated_line;
 
-    std::string annotation_string;
+    std::string_view annotation_string;
     if (maybe_annotated_line[0] == kAnnotationStart) {
       size_t end_pos = maybe_annotated_line.find(kAnnotationEnd, 0);
       if (end_pos == std::string::npos || end_pos == 0) {
@@ -1058,17 +1360,17 @@
 
     ProfileSampleAnnotation annotation = annotation_string.empty()
         ? ProfileSampleAnnotation::kNone
-        : ProfileSampleAnnotation(annotation_string);
+        : ProfileSampleAnnotation(std::string(annotation_string));
 
-    // Now process the rest of the lines.
-    std::string klass;
-    std::string method_str;
+    // Now process the rest of the line.
+    std::string_view klass;
+    std::string_view method_str;
     bool is_hot = false;
     bool is_startup = false;
     bool is_post_startup = false;
     const size_t method_sep_index = line.find(kMethodSep, 0);
     if (method_sep_index == std::string::npos) {
-      klass = line.substr(0);
+      klass = line;
     } else {
       // The method prefix flags are only valid for method strings.
       size_t start_index = 0;
@@ -1090,6 +1392,41 @@
       method_str = line.substr(method_sep_index + kMethodSep.size());
     }
 
+    if (!IsValidDescriptor(std::string(klass).c_str())) {
+      LOG(ERROR) << "Invalid descriptor: " << klass;
+      return false;
+    }
+
+    if (method_str.empty()) {
+      auto array_it = std::find_if(klass.begin(), klass.end(), [](char c) { return c != '['; });
+      size_t array_dim = std::distance(klass.begin(), array_it);
+      if (klass.size() == array_dim + 1u) {
+        // Attribute primitive types and their arrays to the first dex file.
+        profile->AddClass(*dex_files[0], klass, annotation);
+        return true;
+      }
+      // Attribute non-primitive classes and their arrays to the dex file with the definition.
+      TypeReference class_ref(/* dex_file= */ nullptr, dex::TypeIndex());
+      if (FindClassDef(dex_files, klass.substr(array_dim), &class_ref) == nullptr) {
+        LOG(WARNING) << "Could not find class definition: " << klass.substr(array_dim);
+        return false;
+      }
+      if (array_dim != 0) {
+        // Let the ProfileCompilationInfo find the type index or add an extra descriptor.
+        return profile->AddClass(*class_ref.dex_file, klass, annotation);
+      } else {
+        return profile->AddClass(*class_ref.dex_file, class_ref.TypeIndex(), annotation);
+      }
+    }
+
+    DCHECK_NE(klass[0], '[');
+    TypeReference class_ref(/* dex_file= */ nullptr, dex::TypeIndex());
+    const dex::ClassDef* class_def = FindClassDef(dex_files, klass, &class_ref);
+    if (class_def == nullptr) {
+      LOG(WARNING) << "Could not find class definition: " << klass;
+      return false;
+    }
+
     uint32_t flags = 0;
     if (is_hot) {
       flags |= ProfileCompilationInfo::MethodHotness::kFlagHot;
@@ -1101,52 +1438,38 @@
       flags |= ProfileCompilationInfo::MethodHotness::kFlagPostStartup;
     }
 
-    TypeReference class_ref(/* dex_file= */ nullptr, dex::TypeIndex());
-    if (!FindClass(dex_files, klass, &class_ref)) {
-      LOG(WARNING) << "Could not find class: " << klass;
-      return false;
-    }
-
-    if (method_str.empty() || method_str == kClassAllMethods) {
+    if (method_str == kClassAllMethods) {
       // Start by adding the class.
-      const DexFile* dex_file = class_ref.dex_file;
+      profile->AddClass(*class_ref.dex_file, class_ref.TypeIndex(), annotation);
+      uint16_t class_def_index = class_ref.dex_file->GetIndexForClassDef(*class_def);
+      ClassAccessor accessor(*class_ref.dex_file, class_def_index);
       std::vector<ProfileMethodInfo> methods;
-      if (method_str == kClassAllMethods) {
-        ClassAccessor accessor(
-            *dex_file,
-            dex_file->GetIndexForClassDef(*dex_file->FindClassDef(class_ref.TypeIndex())));
-        for (const ClassAccessor::Method& method : accessor.GetMethods()) {
-          if (method.GetCodeItemOffset() != 0) {
-            // Add all of the methods that have code to the profile.
-            methods.push_back(ProfileMethodInfo(method.GetReference()));
-          }
+      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+        if (method.GetCodeItemOffset() != 0) {
+          // Add all of the methods that have code to the profile.
+          methods.push_back(ProfileMethodInfo(method.GetReference()));
         }
       }
-      // TODO: Check return values?
+      // TODO: Check return value?
       profile->AddMethods(
           methods, static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags), annotation);
-      std::set<dex::TypeIndex> classes;
-      classes.insert(class_ref.TypeIndex());
-      profile->AddClassesForDex(dex_file, classes.begin(), classes.end(), annotation);
       return true;
     }
 
     // Process the method.
     std::string method_spec;
-    std::vector<std::string> inline_cache_elems;
 
     // If none of the flags are set, default to hot.
+    // TODO: Why is this done after we have already calculated `flags`?
     is_hot = is_hot || (!is_hot && !is_startup && !is_post_startup);
 
-    std::vector<std::string> method_elems;
-    bool is_missing_types = false;
+    // Lifetime of segments is same as method_elems since it contains pointers into the string-data
+    std::vector<InlineCacheSegment> segments;
+    std::vector<std::string_view> method_elems;
     Split(method_str, kProfileParsingInlineChacheSep, &method_elems);
     if (method_elems.size() == 2) {
       method_spec = method_elems[0];
-      is_missing_types = method_elems[1] == kMissingTypesMarker;
-      if (!is_missing_types) {
-        Split(method_elems[1], kProfileParsingTypeSep, &inline_cache_elems);
-      }
+      InlineCacheSegment::SplitInlineCacheSegment(method_elems[1], &segments);
     } else if (method_elems.size() == 1) {
       method_spec = method_elems[0];
     } else {
@@ -1156,31 +1479,116 @@
 
     const uint32_t method_index = FindMethodIndex(class_ref, method_spec);
     if (method_index == dex::kDexNoIndex) {
+      LOG(WARNING) << "Could not find method " << klass << "->" << method_spec;
       return false;
     }
 
+    std::optional<ClassMethodReference>
+        resolved_class_method_ref = ResolveMethod(class_ref, method_index);
+
     std::vector<ProfileMethodInfo::ProfileInlineCache> inline_caches;
-    if (is_missing_types || !inline_cache_elems.empty()) {
-      uint32_t dex_pc;
-      if (!HasSingleInvoke(class_ref, method_index, &dex_pc)) {
-        return false;
-      }
-      std::vector<TypeReference> classes(inline_cache_elems.size(),
-                                         TypeReference(/* dex_file= */ nullptr, dex::TypeIndex()));
-      size_t class_it = 0;
-      for (const std::string& ic_class : inline_cache_elems) {
-        if (!FindClass(dex_files, ic_class, &(classes[class_it++]))) {
-          LOG(ERROR) << "Could not find class: " << ic_class;
-          return false;
+    // We can only create inline-caches when we actually have code we can
+    // examine. If we couldn't resolve the method don't bother trying to create
+    // inline-caches.
+    if (resolved_class_method_ref) {
+      for (const InlineCacheSegment& segment : segments) {
+        std::vector<uint32_t> dex_pcs;
+        if (segment.IsSingleReceiver()) {
+          DCHECK_EQ(segments.size(), 1u);
+          dex_pcs.resize(1, -1);
+          // TODO This single invoke format should really be phased out and
+          // removed.
+          if (!HasSingleInvoke(class_ref, method_index, &dex_pcs[0])) {
+            return false;
+          }
+        } else {
+          // Get the type-ref the method code will use.
+          std::string receiver_str(segment.GetReceiverType());
+          const dex::TypeId *type_id =
+              class_ref.dex_file->FindTypeId(receiver_str.c_str());
+          if (type_id == nullptr) {
+            LOG(WARNING) << "Could not find class: "
+                         << segment.GetReceiverType() << " in dex-file "
+                         << class_ref.dex_file << ". Ignoring IC group: '"
+                         << segment << "'";
+            continue;
+          }
+          dex::TypeIndex target_index =
+              class_ref.dex_file->GetIndexForTypeId(*type_id);
+
+          GetAllInvokes(resolved_class_method_ref->type_,
+                        resolved_class_method_ref->method_index_,
+                        target_index,
+                        &dex_pcs);
+        }
+        bool missing_types = segment.GetIcTargets()[0] == kMissingTypesMarker;
+        bool megamorphic_types =
+            segment.GetIcTargets()[0] == kMegamorphicTypesMarker;
+        std::vector<TypeReference> classes;
+        if (!missing_types && !megamorphic_types) {
+          classes.reserve(segment.NumIcTargets());
+          for (const std::string_view& ic_class : segment.GetIcTargets()) {
+            if (ic_class.empty()) {
+              break;
+            }
+            if (!IsValidDescriptor(std::string(ic_class).c_str())) {
+              LOG(ERROR) << "Invalid descriptor for inline cache: " << ic_class;
+              return false;
+            }
+            // TODO: Allow referencing classes without a `dex::TypeId` in any of the dex files.
+            TypeReference ic_class_ref(/* dex_file= */ nullptr, dex::TypeIndex());
+            if (!FindClass(dex_files, ic_class, &ic_class_ref)) {
+              LOG(segment.IsSingleReceiver() ? ERROR : WARNING)
+                  << "Could not find class: " << ic_class << " in " << segment;
+              if (segment.IsSingleReceiver()) {
+                return false;
+              } else {
+                // Be a bit more forgiving with profiles from servers.
+                missing_types = true;
+                classes.clear();
+                break;
+              }
+            }
+            classes.push_back(ic_class_ref);
+          }
+        }
+        for (size_t dex_pc : dex_pcs) {
+          inline_caches.emplace_back(dex_pc, missing_types, classes, megamorphic_types);
         }
       }
-      inline_caches.emplace_back(dex_pc, is_missing_types, classes);
     }
     MethodReference ref(class_ref.dex_file, method_index);
     if (is_hot) {
-      profile->AddMethod(ProfileMethodInfo(ref, inline_caches),
-          static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
-          annotation);
+      ClassMethodReference orig_cmr { class_ref, method_index };
+      if (!inline_caches.empty() &&
+          resolved_class_method_ref &&
+          orig_cmr != *resolved_class_method_ref) {
+        // We have inline-caches on a method that doesn't actually exist. We
+        // want to put the inline caches on the resolved version of the method
+        // (if we could find one) and just mark the actual method as present.
+        const DexFile *dex = resolved_class_method_ref->type_.dex_file;
+        LOG(VERBOSE) << "Adding "
+                     << dex->PrettyMethod(
+                            resolved_class_method_ref->method_index_)
+                     << " as alias for " << dex->PrettyMethod(method_index);
+        // The inline-cache refers to a supertype of the actual profile line.
+        // Include this supertype method in the profile as well.
+        MethodReference resolved_ref(class_ref.dex_file,
+                                     resolved_class_method_ref->method_index_);
+        profile->AddMethod(
+            ProfileMethodInfo(resolved_ref, inline_caches),
+            static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
+            annotation);
+        profile->AddMethod(
+            ProfileMethodInfo(ref),
+            static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
+            annotation);
+      } else {
+        profile->AddMethod(
+            ProfileMethodInfo(ref, inline_caches),
+            static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
+            annotation);
+      }
     }
     if (flags != 0) {
       if (!profile->AddMethod(ProfileMethodInfo(ref),
@@ -1194,15 +1602,19 @@
   }
 
   bool ProcessBootLine(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
-                       const std::string& line,
+                       std::string_view line,
                        ProfileBootInfo* boot_profiling_info) {
     const size_t method_sep_index = line.find(kMethodSep, 0);
-    std::string klass_str = line.substr(0, method_sep_index);
-    std::string method_str = line.substr(method_sep_index + kMethodSep.size());
+    if (method_sep_index == std::string_view::npos) {
+      LOG(ERROR) << "Invalid boot line: " << line;
+      return false;
+    }
+    std::string_view klass_str = line.substr(0, method_sep_index);
+    std::string_view method_str = line.substr(method_sep_index + kMethodSep.size());
 
     TypeReference class_ref(/* dex_file= */ nullptr, dex::TypeIndex());
-    if (!FindClass(dex_files, klass_str, &class_ref)) {
-      LOG(WARNING) << "Could not find class: " << klass_str;
+    if (FindClassDef(dex_files, klass_str, &class_ref) == nullptr) {
+      LOG(WARNING) << "Could not find class definition: " << klass_str;
       return false;
     }
 
@@ -1227,7 +1639,7 @@
       fd = open(reference_profile_file_.c_str(), flags, 0644);
       if (fd < 0) {
         PLOG(ERROR) << "Cannot open " << reference_profile_file_;
-        return kInvalidFd;
+        return File::kInvalidFd;
       }
     }
     return fd;
@@ -1320,7 +1732,19 @@
     OpenApkFilesFromLocations(&dex_files);
 
     // Process the lines one by one and add the successful ones to the profile.
-    ProfileCompilationInfo info;
+    bool for_boot_image = GetOutputProfileType() == OutputProfileType::kBoot;
+    ProfileCompilationInfo info(for_boot_image);
+
+    if (for_boot_image) {
+      // Add all dex files to the profile. This is needed for jitzygote to indicate
+      // which dex files are part of the boot image extension to compile in memory.
+      for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+        if (info.FindOrAddDexFile(*dex_file) == info.MaxProfileIndex()) {
+          LOG(ERROR) << "Failed to add dex file to boot image profile: " << dex_file->GetLocation();
+          return -1;
+        }
+      }
+    }
 
     for (const auto& line : *user_lines) {
       ProcessLine(dex_files, line, &info);
@@ -1338,8 +1762,8 @@
     return generate_boot_image_profile_;
   }
 
-  bool ShouldCreateBootProfile() const {
-    return generate_boot_profile_;
+  OutputProfileType GetOutputProfileType() const {
+    return output_profile_type_;
   }
 
   // Create and store a ProfileCompilationInfo for the boot image.
@@ -1506,7 +1930,7 @@
   bool dump_only_;
   bool dump_classes_and_methods_;
   bool generate_boot_image_profile_;
-  bool generate_boot_profile_;
+  OutputProfileType output_profile_type_;
   int dump_output_to_fd_;
   BootImageOptions boot_image_options_;
   std::string test_profile_;
@@ -1522,6 +1946,10 @@
   std::string preloaded_classes_out_path_;
 };
 
+std::ostream& operator<<(std::ostream& os, const ProfMan::InlineCacheSegment& ics) {
+  return ics.Dump(os);
+}
+
 // See ProfileAssistant::ProcessingResult for return codes.
 static int profman(int argc, char** argv) {
   ProfMan profman;
@@ -1541,11 +1969,12 @@
   if (profman.ShouldOnlyDumpClassesAndMethods()) {
     return profman.DumpClassesAndMethods();
   }
-  if (profman.ShouldCreateBootProfile()) {
-    return profman.CreateBootProfile();
-  }
   if (profman.ShouldCreateProfile()) {
-    return profman.CreateProfile();
+    if (profman.GetOutputProfileType() == OutputProfileType::kBprof) {
+      return profman.CreateBootProfile();
+    } else {
+      return profman.CreateProfile();
+    }
   }
 
   if (profman.ShouldCreateBootImageProfile()) {
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 7e75016..e9343e7 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -18,6 +18,15 @@
 // we use gold as the linker (arm, x86, x86_64). The symbol is used by the debuggers to detect when
 // new jit code is generated. We don't want it to be called when a different function with the same
 // (empty) body is called.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 JIT_DEBUG_REGISTER_CODE_LDFLAGS = [
     "-Wl,--keep-unique,__jit_debug_register_code",
     "-Wl,--keep-unique,__dex_debug_register_code",
@@ -27,8 +36,8 @@
 // in stack traces often.
 libart_cc_defaults {
     name: "libart_nativeunwind_defaults",
-    arch: {
-        arm: {
+    target: {
+        android_arm: {
             // Arm 32 bit does not produce complete exidx unwind information
             // so keep the .debug_frame which is relatively small and does
             // include needed unwind information.
@@ -39,17 +48,17 @@
         },
         // For all other architectures, leave the symbols in the shared library
         // so that stack unwinders can produce meaningful name resolution.
-        arm64: {
+        android_arm64: {
             strip: {
                 keep_symbols: true,
             },
         },
-        x86: {
+        android_x86: {
             strip: {
                 keep_symbols: true,
             },
         },
-        x86_64: {
+        android_x86_64: {
             strip: {
                 keep_symbols: true,
             },
@@ -62,8 +71,10 @@
     defaults: ["art_defaults"],
     host_supported: true,
     srcs: [
+        "app_info.cc",
         "aot_class_linker.cc",
         "art_field.cc",
+        "sdk_checker.cc",
         "art_method.cc",
         "backtrace_helper.cc",
         "barrier.cc",
@@ -78,12 +89,11 @@
         "class_root.cc",
         "class_table.cc",
         "common_throws.cc",
-        "compiler_filter.cc",
+        "compat_framework.cc",
         "debug_print.cc",
         "debugger.cc",
         "dex/dex_file_annotations.cc",
         "dex_register_location.cc",
-        "dex_to_dex_decompiler.cc",
         "elf_file.cc",
         "exec_utils.cc",
         "fault_handler.cc",
@@ -120,6 +130,7 @@
         "gc/space/zygote_space.cc",
         "gc/task_processor.cc",
         "gc/verification.cc",
+        "handle.cc",
         "hidden_api.cc",
         "hprof/hprof.cc",
         "image.cc",
@@ -139,6 +150,7 @@
         "interpreter/shadow_frame.cc",
         "interpreter/unstarted_runtime.cc",
         "java_frame_root_info.cc",
+        "javaheapprof/javaheapsampler.cc",
         "jit/debugger_interface.cc",
         "jit/jit.cc",
         "jit/jit_code_cache.cc",
@@ -151,8 +163,8 @@
         "jni/jni_id_manager.cc",
         "jni/jni_internal.cc",
         "linear_alloc.cc",
-        "managed_stack.cc",
         "method_handles.cc",
+        "metrics/reporter.cc",
         "mirror/array.cc",
         "mirror/class.cc",
         "mirror/class_ext.cc",
@@ -280,8 +292,9 @@
         arm: {
             srcs: [
                 "interpreter/mterp/mterp.cc",
-                "interpreter/mterp/nterp_stub.cc",
+                "interpreter/mterp/nterp.cc",
                 ":libart_mterp.arm",
+                ":libart_mterp.armng",
                 "arch/arm/context_arm.cc",
                 "arch/arm/entrypoints_init_arm.cc",
                 "arch/arm/instruction_set_features_assembly_tests.S",
@@ -296,8 +309,9 @@
         arm64: {
             srcs: [
                 "interpreter/mterp/mterp.cc",
-                "interpreter/mterp/nterp_stub.cc",
+                "interpreter/mterp/nterp.cc",
                 ":libart_mterp.arm64",
+                ":libart_mterp.arm64ng",
                 "arch/arm64/context_arm64.cc",
                 "arch/arm64/entrypoints_init_arm64.cc",
                 "arch/arm64/jni_entrypoints_arm64.S",
@@ -313,6 +327,7 @@
                 "interpreter/mterp/mterp.cc",
                 "interpreter/mterp/nterp_stub.cc",
                 ":libart_mterp.x86",
+                "arch/x86/__x86.get_pc_thunk.S",
                 "arch/x86/context_x86.cc",
                 "arch/x86/entrypoints_init_x86.cc",
                 "arch/x86/jni_entrypoints_x86.S",
@@ -353,23 +368,31 @@
             },
         },
     },
+
     target: {
         android: {
             srcs: [
                 "monitor_android.cc",
                 "runtime_android.cc",
                 "thread_android.cc",
+                "metrics/statsd.cc",
+            ],
+            header_libs: [
+                "libnativeloader-headers", // For dlext_namespaces.h
             ],
             shared_libs: [
                 "libdl_android",
+                "libicu",
+                "libstatssocket",
+                "libz", // For adler32.
+                "heapprofd_client_api",
             ],
             static_libs: [
-                "libz", // For adler32.
+                "libstatslog_art",
+                "libxml2",
             ],
-            cflags: [
-                // ART is allowed to link to libicuuc directly
-                // since they are in the same module
-                "-DANDROID_LINK_SHARED_ICU4C",
+            generated_sources: [
+                "apex-info-list",
             ],
         },
         android_arm: {
@@ -390,35 +413,59 @@
                 "runtime_linux.cc",
                 "thread_linux.cc",
             ],
+            header_libs: [
+                "libicuuc_headers",
+            ],
             shared_libs: [
                 "libz", // For adler32.
             ],
         },
     },
-    cflags: ["-DBUILDING_LIBART=1"],
-    generated_sources: ["art_operator_srcs"],
+
+    generated_sources: [
+        "art_operator_srcs",
+    ],
     // asm_support_gen.h (used by asm_support.h) is generated with cpp-define-generator
     generated_headers: ["cpp-define-generator-asm-support"],
-    // export our headers so the libart-gtest targets can use it as well.
+    // export our headers so the libart(d)-gtest targets can use it as well.
     export_generated_headers: ["cpp-define-generator-asm-support"],
+
     header_libs: [
         "art_cmdlineparser_headers",
         "cpp-define-generator-definitions",
-        "libicuuc_headers",
-        "libnativehelper_header_only",
         "jni_platform_headers",
+        "libnativehelper_header_only",
+    ],
+    whole_static_libs: [
+        "libcpu_features",
     ],
     shared_libs: [
         "libartpalette",
+        "libbacktrace",
+        "libbase", // For common macros.
+        "liblog",
+        "liblz4",
+        "liblzma", // libelffile(d) dependency; must be repeated here since it's a static lib.
         "libnativebridge",
         "libnativeloader",
-        "libbacktrace",
-        "liblog",
-        // For common macros.
-        "libbase",
-        "libunwindstack",
         "libsigchain",
+        "libunwindstack",
     ],
+    static_libs: ["libodrstatslog"],
+
+    runtime_libs: [
+        // Libraries loaded at runtime. Exceptions:
+        // - libart(d)-compiler.so and libopenjdk(d).so cannot be listed here
+        //   due to cyclic dependency.
+        // - libicu_jni.so is only loaded to handle dependency order in VM
+        //   startup (see Runtime::InitNativeMethods), but its API is internal
+        //   to com.android.i18n and not used by ART/libcore. Therefore it's not
+        //   listed here to avoid visibility issues. Instead it's linked from
+        //   the ART module namespace through an entry in requireNativeLibs in
+        //   manifest-art.json.
+        "libjavacore",
+    ],
+
     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
@@ -428,17 +475,27 @@
 
 libart_static_cc_defaults {
     name: "libart_static_base_defaults",
-    static_libs: [
+    whole_static_libs: [
         "libartpalette",
         "libbacktrace",
         "libbase",
         "liblog",
+        "liblz4",
+        "liblzma", // libelffile dependency; must be repeated here since it's a static lib.
         "libnativebridge",
         "libnativeloader",
-        "libsigchain_dummy",
+        "libodrstatslog",
+        "libsigchain_fake",
         "libunwindstack",
         "libz",
     ],
+    target: {
+        bionic: {
+            whole_static_libs: [
+                "libasync_safe", // libunwindstack dependency on Bionic.
+            ],
+        },
+    },
 }
 
 cc_defaults {
@@ -447,11 +504,11 @@
         "libart_static_base_defaults",
         "libartbase_static_defaults",
         "libdexfile_static_defaults",
+        "libdexfile_support_static_defaults",
         "libprofile_static_defaults",
     ],
-    static_libs: [
+    whole_static_libs: [
         "libart",
-        "libdexfile_support_static",
         "libelffile",
     ],
 }
@@ -462,11 +519,11 @@
         "libart_static_base_defaults",
         "libartbased_static_defaults",
         "libdexfiled_static_defaults",
+        "libdexfiled_support_static_defaults",
         "libprofiled_static_defaults",
     ],
-    static_libs: [
+    whole_static_libs: [
         "libartd",
-        "libdexfiled_support_static",
         "libelffiled",
     ],
 }
@@ -478,15 +535,13 @@
     srcs: [
         "base/callee_save_type.h",
         "base/locks.h",
-        "class_loader_context.h",
         "class_status.h",
-        "debugger.h",
+        "compilation_kind.h",
         "gc_root.h",
         "gc/allocator_type.h",
         "gc/allocator/rosalloc.h",
         "gc/collector_type.h",
         "gc/collector/gc_type.h",
-        "gc/heap.h",
         "gc/space/region_space.h",
         "gc/space/space.h",
         "gc/weak_root_state.h",
@@ -497,14 +552,12 @@
         "jni_id_type.h",
         "lock_word.h",
         "oat_file.h",
-        "object_callbacks.h",
         "process_state.h",
         "reflective_value_visitor.h",
         "stack.h",
         "suspend_reason.h",
         "thread.h",
         "thread_state.h",
-        "ti/agent.h",
         "trace.h",
         "verifier/verifier_enums.h",
     ],
@@ -519,6 +572,8 @@
     defaults: [
         "libart_defaults",
         "libart_nativeunwind_defaults",
+        "art_hugepage_defaults",
+        "art_pgo_defaults",
     ],
     whole_static_libs: [
     ],
@@ -528,8 +583,6 @@
     shared_libs: [
         "libartbase",
         "libdexfile",
-        // We need to eagerly load it so libdexfile_support used from libunwindstack can find it.
-        "libdexfile_external",
         "libprofile",
     ],
     export_shared_lib_headers: [
@@ -543,7 +596,7 @@
         },
     },
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
@@ -562,9 +615,6 @@
     shared_libs: [
         "libartbased",
         "libdexfiled",
-        // We need to eagerly preload it, so that libunwindstack can find it.
-        // Otherwise, it would try to load the non-debug version with dlopen.
-        "libdexfiled_external",
         "libprofiled",
     ],
     export_shared_lib_headers: [
@@ -572,19 +622,20 @@
     ],
     apex_available: [
         "com.android.art.debug",
+        // TODO(b/183882457): This lib doesn't go into com.android.art, but
+        // apex_available lists need to be the same for internal libs to avoid
+        // stubs, and this depends on libsigchain.
+        "com.android.art",
     ],
 }
 
-art_cc_library {
-    name: "libart-runtime-gtest",
-    defaults: ["libart-gtest-defaults"],
+art_cc_defaults {
+    name: "libart-runtime-gtest-defaults",
     srcs: [
         "common_runtime_test.cc",
         "dexopt_test.cc",
     ],
     shared_libs: [
-        "libartd",
-        "libartbase-art-gtest",
         "libbase",
         "libbacktrace",
     ],
@@ -593,12 +644,73 @@
     ],
 }
 
-art_cc_test {
-    name: "art_runtime_tests",
+art_cc_library {
+    name: "libart-runtime-gtest",
     defaults: [
-        "art_gtest_defaults",
+        "libart-runtime-gtest-defaults",
+        "libart-gtest-defaults",
+    ],
+    shared_libs: [
+        "libart",
+        "libartbase-art-gtest",
+    ],
+}
+
+art_cc_library {
+    name: "libartd-runtime-gtest",
+    defaults: [
+        "libart-runtime-gtest-defaults",
+        "libartd-gtest-defaults",
+    ],
+    shared_libs: [
+        "libartd",
+        "libartbased-art-gtest",
+    ],
+}
+
+art_cc_defaults {
+    name: "art_runtime_tests_defaults",
+    data: [
+        ":art-gtest-jars-AllFields",
+        ":art-gtest-jars-ErroneousA",
+        ":art-gtest-jars-ErroneousB",
+        ":art-gtest-jars-ErroneousInit",
+        ":art-gtest-jars-Extension1",
+        ":art-gtest-jars-Extension2",
+        ":art-gtest-jars-ForClassLoaderA",
+        ":art-gtest-jars-ForClassLoaderB",
+        ":art-gtest-jars-ForClassLoaderC",
+        ":art-gtest-jars-ForClassLoaderD",
+        ":art-gtest-jars-HiddenApiSignatures",
+        ":art-gtest-jars-IMTA",
+        ":art-gtest-jars-IMTB",
+        ":art-gtest-jars-Instrumentation",
+        ":art-gtest-jars-Interfaces",
+        ":art-gtest-jars-LinkageTest",
+        ":art-gtest-jars-Main",
+        ":art-gtest-jars-MainStripped",
+        ":art-gtest-jars-MainUncompressedAligned",
+        ":art-gtest-jars-MethodTypes",
+        ":art-gtest-jars-MultiDex",
+        ":art-gtest-jars-MultiDexModifiedSecondary",
+        ":art-gtest-jars-MultiDexUncompressedAligned",
+        ":art-gtest-jars-MyClass",
+        ":art-gtest-jars-MyClassNatives",
+        ":art-gtest-jars-Nested",
+        ":art-gtest-jars-Packages",
+        ":art-gtest-jars-ProfileTestMultiDex",
+        ":art-gtest-jars-ProtoCompare",
+        ":art-gtest-jars-ProtoCompare2",
+        ":art-gtest-jars-StaticLeafMethods",
+        ":art-gtest-jars-Statics",
+        ":art-gtest-jars-StaticsFromCode",
+        ":art-gtest-jars-Transaction",
+        ":art-gtest-jars-VerifierDeps",
+        ":art-gtest-jars-VerifierDepsMulti",
+        ":art-gtest-jars-XandY",
     ],
     srcs: [
+        "app_info_test.cc",
         "arch/arch_test.cc",
         "arch/instruction_set_features_test.cc",
         "arch/memcmp16_test.cc",
@@ -608,13 +720,13 @@
         "arch/x86/instruction_set_features_x86_test.cc",
         "arch/x86_64/instruction_set_features_x86_64_test.cc",
         "barrier_test.cc",
+        "base/message_queue_test.cc",
         "base/mutex_test.cc",
         "base/timing_logger_test.cc",
         "cha_test.cc",
         "class_linker_test.cc",
         "class_loader_context_test.cc",
         "class_table_test.cc",
-        "compiler_filter_test.cc",
         "entrypoints/math_entrypoints_test.cc",
         "entrypoints/quick/quick_trampoline_entrypoints_test.cc",
         "entrypoints_order_test.cc",
@@ -650,6 +762,7 @@
         "jni/java_vm_ext_test.cc",
         "jni/jni_internal_test.cc",
         "method_handles_test.cc",
+        "metrics/reporter_test.cc",
         "mirror/dex_cache_test.cc",
         "mirror/method_type_test.cc",
         "mirror/object_test.cc",
@@ -681,19 +794,88 @@
     ],
 }
 
+// Version of ART gtest `art_runtime_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
 art_cc_test {
-    name: "art_runtime_compiler_tests",
+    name: "art_runtime_tests",
     defaults: [
         "art_gtest_defaults",
+        "art_runtime_tests_defaults",
     ],
+    target: {
+        host: {
+            required: ["dex2oatd"],
+        },
+    },
+}
+
+// Standalone version of ART gtest `art_runtime_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_runtime_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_runtime_tests_defaults",
+    ],
+    target: {
+        host: {
+            required: ["dex2oat"],
+        },
+    },
+    // Some tests are currently failing (observed on
+    // `aosp_cf_x86_64_phone-userdebug`); use a special test configuration for
+    // `art_standalone_runtime_tests` to filter them out for now.
+    // TODO(b/162834439): Investigate these failures and re-enable these tests.
+    test_config: "art_standalone_runtime_tests.xml",
+}
+
+art_cc_defaults {
+    name: "art_runtime_compiler_tests_defaults",
     srcs: [
         "reflection_test.cc",
         "module_exclusion_test.cc",
     ],
+    data: [
+        ":art-gtest-jars-Main",
+        ":art-gtest-jars-NonStaticLeafMethods",
+        ":art-gtest-jars-StaticLeafMethods",
+    ],
+}
+
+// Version of ART gtest `art_runtime_compiler_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
+art_cc_test {
+    name: "art_runtime_compiler_tests",
+    defaults: [
+        "art_gtest_defaults",
+        "art_runtime_compiler_tests_defaults",
+    ],
     shared_libs: [
         "libartd-compiler",
-        "libvixld",
     ],
+    target: {
+        host: {
+            required: ["dex2oatd"],
+        },
+    },
+}
+
+// Standalone version of ART gtest `art_runtime_compiler_tests`, not bundled with the ART APEX on
+// target.
+art_cc_test {
+    name: "art_standalone_runtime_compiler_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_runtime_compiler_tests_defaults",
+    ],
+    shared_libs: [
+        "libart-compiler",
+    ],
+    target: {
+        host: {
+            required: ["dex2oat"],
+        },
+    },
+    test_config: "art_standalone_runtime_compiler_tests.xml",
 }
 
 cc_library_headers {
@@ -703,9 +885,10 @@
     sdk_version: "current",
 
     apex_available: [
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
     ],
+    min_sdk_version: "S",
 }
 
 genrule {
@@ -715,6 +898,7 @@
     tool_files: [
         "interpreter/mterp/gen_mterp.py",
         "interpreter/mterp/common/gen_setup.py",
+        ":art_libdexfile_dex_instruction_list_header",
     ],
     cmd: "$(location interpreter/mterp/gen_mterp.py) $(out) $(in)",
 }
@@ -726,6 +910,7 @@
     tool_files: [
         "interpreter/mterp/gen_mterp.py",
         "interpreter/mterp/common/gen_setup.py",
+        ":art_libdexfile_dex_instruction_list_header",
     ],
     cmd: "$(location interpreter/mterp/gen_mterp.py) $(out) $(in)",
 }
@@ -737,6 +922,7 @@
     tool_files: [
         "interpreter/mterp/gen_mterp.py",
         "interpreter/mterp/common/gen_setup.py",
+        ":art_libdexfile_dex_instruction_list_header",
     ],
     cmd: "$(location interpreter/mterp/gen_mterp.py) $(out) $(in)",
 }
@@ -748,6 +934,7 @@
     tool_files: [
         "interpreter/mterp/gen_mterp.py",
         "interpreter/mterp/common/gen_setup.py",
+        ":art_libdexfile_dex_instruction_list_header",
     ],
     cmd: "$(location interpreter/mterp/gen_mterp.py) $(out) $(in)",
 }
@@ -763,6 +950,72 @@
     tool_files: [
         "interpreter/mterp/gen_mterp.py",
         "interpreter/mterp/common/gen_setup.py",
+        ":art_libdexfile_dex_instruction_list_header",
     ],
     cmd: "$(location interpreter/mterp/gen_mterp.py) $(out) $(in)",
 }
+
+genrule {
+    name: "libart_mterp.arm64ng",
+    out: ["mterp_arm64ng.S"],
+    srcs: [
+        "interpreter/mterp/arm64ng/*.S",
+        "interpreter/mterp/arm64/arithmetic.S",
+        "interpreter/mterp/arm64/floating_point.S",
+    ],
+    tool_files: [
+        "interpreter/mterp/gen_mterp.py",
+        "interpreter/mterp/common/gen_setup.py",
+        ":art_libdexfile_dex_instruction_list_header",
+    ],
+    cmd: "$(location interpreter/mterp/gen_mterp.py) $(out) $(in)",
+}
+
+genrule {
+    name: "libart_mterp.armng",
+    out: ["mterp_armng.S"],
+    srcs: [
+        "interpreter/mterp/armng/*.S",
+    ],
+    tool_files: [
+        "interpreter/mterp/gen_mterp.py",
+        "interpreter/mterp/common/gen_setup.py",
+        ":art_libdexfile_dex_instruction_list_header",
+    ],
+    cmd: "$(location interpreter/mterp/gen_mterp.py) $(out) $(in)",
+}
+
+cc_library_static {
+    name: "libstatslog_art",
+    defaults: ["art_defaults"],
+    generated_sources: ["statslog_art.cpp"],
+    generated_headers: ["statslog_art.h"],
+    export_generated_headers: ["statslog_art.h"],
+    shared_libs: [
+        "liblog",
+        "libstatssocket",
+        "libutils",
+    ],
+    apex_available: [
+        "com.android.art",
+        "com.android.art.debug",
+    ],
+}
+
+genrule {
+    name: "statslog_art.h",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_art.h --module art --namespace art,metrics,statsd",
+    out: [
+        "statslog_art.h",
+    ],
+}
+
+genrule {
+    name: "statslog_art.cpp",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_art.cpp --module art --namespace art,metrics,statsd --importHeader statslog_art.h",
+    out: [
+        "statslog_art.cpp",
+    ],
+}
diff --git a/runtime/alloc_instrumentation.md b/runtime/alloc_instrumentation.md
new file mode 100644
index 0000000..513bbe3
--- /dev/null
+++ b/runtime/alloc_instrumentation.md
@@ -0,0 +1,33 @@
+In order to buy some performance on the common, uninstrumented, fast path, we replace repeated
+checks for both allocation instrumentation and allocator changes by  a single function table
+dispatch, and templatized allocation code that can be used to generate either instrumented
+or uninstrumented versions of allocation routines.
+
+When we call an allocation routine, we always indirect through a thread-local function table that
+either points to instrumented or uninstrumented allocation routines. The instrumented code has a
+`kInstrumented` = true template argument (or `kIsInstrumented` in some places), the uninstrumented
+code has `kInstrumented` = false.
+
+The function table is thread-local. There appears to be no logical necessity for that; it just
+makes it easier to access from compiled Java code.
+
+- The function table is switched out by `InstrumentQuickAllocEntryPoints[Locked]`, and a
+corresponding `UninstrumentQuickAlloc`... function.
+
+- These in turn are called by `SetStatsEnabled()`, `SetAllocationListener()`, et al, which
+require the mutator lock is not held.
+
+- With a started runtime, `SetEntrypointsInstrumented()` calls `ScopedSupendAll(`) before updating
+  the function table.
+
+Mutual exclusion in the dispatch table is thus ensured by the fact that it is only updated while
+all other threads are suspended, and is only accessed with the mutator lock logically held,
+which inhibits suspension.
+
+To ensure correctness, we thus must:
+
+1. Suspend all threads when swapping out the dispatch table, and
+2. Make sure that we hold the mutator lock when accessing it.
+3. Not trust kInstrumented once we've given up the mutator lock, since it could have changed in the
+    interim.
+
diff --git a/runtime/aot_class_linker.cc b/runtime/aot_class_linker.cc
index a2f450b..5d8b61d 100644
--- a/runtime/aot_class_linker.cc
+++ b/runtime/aot_class_linker.cc
@@ -103,10 +103,12 @@
   return success;
 }
 
-verifier::FailureKind AotClassLinker::PerformClassVerification(Thread* self,
-                                                               Handle<mirror::Class> klass,
-                                                               verifier::HardFailLogMode log_level,
-                                                               std::string* error_msg) {
+verifier::FailureKind AotClassLinker::PerformClassVerification(
+    Thread* self,
+    verifier::VerifierDeps* verifier_deps,
+    Handle<mirror::Class> klass,
+    verifier::HardFailLogMode log_level,
+    std::string* error_msg) {
   Runtime* const runtime = Runtime::Current();
   CompilerCallbacks* callbacks = runtime->GetCompilerCallbacks();
   ClassStatus old_status = callbacks->GetPreviousClassState(
@@ -125,7 +127,7 @@
     return verifier::FailureKind::kSoftFailure;
   }
   // Do the actual work.
-  return ClassLinker::PerformClassVerification(self, klass, log_level, error_msg);
+  return ClassLinker::PerformClassVerification(self, verifier_deps, klass, log_level, error_msg);
 }
 
 bool AotClassLinker::CanReferenceInBootImageExtension(ObjPtr<mirror::Class> klass, gc::Heap* heap) {
@@ -242,5 +244,30 @@
   }
   return false;
 }
+void AotClassLinker::SetSdkChecker(std::unique_ptr<SdkChecker>&& sdk_checker) {
+  sdk_checker_ = std::move(sdk_checker);
+}
+
+const SdkChecker* AotClassLinker::GetSdkChecker() const {
+  return sdk_checker_.get();
+}
+
+bool AotClassLinker::DenyAccessBasedOnPublicSdk(ArtMethod* art_method) const
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  return sdk_checker_ != nullptr && sdk_checker_->ShouldDenyAccess(art_method);
+}
+bool AotClassLinker::DenyAccessBasedOnPublicSdk(ArtField* art_field) const
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  return sdk_checker_ != nullptr && sdk_checker_->ShouldDenyAccess(art_field);
+}
+bool AotClassLinker::DenyAccessBasedOnPublicSdk(const char* type_descriptor) const {
+  return sdk_checker_ != nullptr && sdk_checker_->ShouldDenyAccess(type_descriptor);
+}
+
+void AotClassLinker::SetEnablePublicSdkChecks(bool enabled) {
+  if (sdk_checker_ != nullptr) {
+    sdk_checker_->SetEnabled(enabled);
+  }
+}
 
 }  // namespace art
diff --git a/runtime/aot_class_linker.h b/runtime/aot_class_linker.h
index 76984bd..9be8869 100644
--- a/runtime/aot_class_linker.h
+++ b/runtime/aot_class_linker.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_AOT_CLASS_LINKER_H_
 #define ART_RUNTIME_AOT_CLASS_LINKER_H_
 
+#include "sdk_checker.h"
 #include "class_linker.h"
 
 namespace art {
@@ -32,15 +33,26 @@
   explicit AotClassLinker(InternTable *intern_table);
   ~AotClassLinker();
 
-  static bool CanReferenceInBootImageExtension(ObjPtr<mirror::Class> klass, gc::Heap* heap)
+static bool CanReferenceInBootImageExtension(ObjPtr<mirror::Class> klass, gc::Heap* heap)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   bool SetUpdatableBootClassPackages(const std::vector<std::string>& packages);
 
+  void SetSdkChecker(std::unique_ptr<SdkChecker>&& sdk_checker_);
+  const SdkChecker* GetSdkChecker() const;
+
+  bool DenyAccessBasedOnPublicSdk(ArtMethod* art_method ATTRIBUTE_UNUSED) const override
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  bool DenyAccessBasedOnPublicSdk(ArtField* art_field ATTRIBUTE_UNUSED) const override
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  bool DenyAccessBasedOnPublicSdk(const char* type_descriptor ATTRIBUTE_UNUSED) const override;
+  void SetEnablePublicSdkChecks(bool enabled) override;
+
  protected:
   // Overridden version of PerformClassVerification allows skipping verification if the class was
   // previously verified but unloaded.
   verifier::FailureKind PerformClassVerification(Thread* self,
+                                                 verifier::VerifierDeps* verifier_deps,
                                                  Handle<mirror::Class> klass,
                                                  verifier::HardFailLogMode log_level,
                                                  std::string* error_msg)
@@ -66,6 +78,8 @@
 
  private:
   std::vector<std::string> updatable_boot_class_path_descriptor_prefixes_;
+
+  std::unique_ptr<SdkChecker> sdk_checker_;
 };
 
 }  // namespace art
diff --git a/runtime/app_info.cc b/runtime/app_info.cc
new file mode 100644
index 0000000..c72951e
--- /dev/null
+++ b/runtime/app_info.cc
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2021 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 <app_info.h>
+
+#include "base/logging.h"
+#include "base/mutex.h"
+#include "base/safe_map.h"
+#include "thread-inl.h"
+
+namespace art {
+
+static constexpr const char* kUnknownValue = "unknown";
+
+AppInfo::AppInfo()
+    : update_mutex_("app_info_update_mutex", LockLevel::kGenericBottomLock) {}
+
+// Converts VMRuntime.java constansts to a CodeType.
+AppInfo::CodeType AppInfo::FromVMRuntimeConstants(uint32_t code_type) {
+  switch (code_type) {
+    case kVMRuntimePrimaryApk : return CodeType::kPrimaryApk;
+    case kVMRuntimeSplitApk : return CodeType::kPrimaryApk;
+    case kVMRuntimeSecondaryDex : return CodeType::kSecondaryDex;
+    default:
+      LOG(WARNING) << "Unknown code type: " << code_type;
+      return CodeType::kUnknown;
+  }
+}
+
+static const char* CodeTypeName(AppInfo::CodeType code_type) {
+  switch (code_type) {
+    case AppInfo::CodeType::kPrimaryApk : return "primary-apk";
+    case AppInfo::CodeType::kSplitApk : return "split-apk";
+    case AppInfo::CodeType::kSecondaryDex : return "secondary-dex";
+    case AppInfo::CodeType::kUnknown : return "unknown";
+  }
+}
+
+void AppInfo::RegisterAppInfo(const std::string& package_name,
+                              const std::vector<std::string>& code_paths,
+                              const std::string& cur_profile_path,
+                              const std::string& ref_profile_path,
+                              AppInfo::CodeType code_type) {
+  MutexLock mu(Thread::Current(), update_mutex_);
+
+  package_name_ = package_name;
+
+  for (const std::string& code_path : code_paths) {
+    CodeLocationInfo& cli = registered_code_locations_.GetOrCreate(
+        code_path, []() { return CodeLocationInfo(); });
+    cli.cur_profile_path = cur_profile_path;
+    cli.ref_profile_path = ref_profile_path;
+    cli.code_type = code_type;
+
+    VLOG(startup) << "Registering code path. "
+        << "\npackage_name=" << package_name
+        << "\ncode_path=" << code_path
+        << "\ncode_type=" << CodeTypeName(code_type)
+        << "\ncur_profile=" << cur_profile_path
+        << "\nref_profile=" << ref_profile_path;
+  }
+}
+
+void AppInfo::RegisterOdexStatus(const std::string& code_path,
+                                 const std::string& compiler_filter,
+                                 const std::string& compilation_reason,
+                                 const std::string& odex_status) {
+  MutexLock mu(Thread::Current(), update_mutex_);
+
+  CodeLocationInfo& cli = registered_code_locations_.GetOrCreate(
+      code_path, []() { return CodeLocationInfo(); });
+  cli.compiler_filter = compiler_filter;
+  cli.compilation_reason = compilation_reason;
+  cli.odex_status = odex_status;
+
+  VLOG(startup) << "Registering odex status. "
+        << "\ncode_path=" << code_path
+        << "\ncompiler_filter=" << compiler_filter
+        << "\ncompilation_reason=" << compilation_reason
+        << "\nodex_status=" << odex_status;
+}
+
+void AppInfo::GetPrimaryApkOptimizationStatus(
+    std::string* out_compiler_filter,
+    std::string* out_compilation_reason) {
+  MutexLock mu(Thread::Current(), update_mutex_);
+
+  for (const auto& it : registered_code_locations_) {
+    const CodeLocationInfo& cli = it.second;
+    if (cli.code_type == CodeType::kPrimaryApk) {
+      *out_compiler_filter = cli.compiler_filter.value_or(kUnknownValue);
+      *out_compilation_reason = cli.compilation_reason.value_or(kUnknownValue);
+      return;
+    }
+  }
+  *out_compiler_filter = kUnknownValue;
+  *out_compilation_reason = kUnknownValue;
+}
+
+std::ostream& operator<<(std::ostream& os, AppInfo& rhs) {
+  MutexLock mu(Thread::Current(), rhs.update_mutex_);
+
+  os << "AppInfo for package_name=" << rhs.package_name_.value_or(kUnknownValue) << "\n";
+  for (const auto& it : rhs.registered_code_locations_) {
+    const std::string code_path = it.first;
+    const AppInfo::CodeLocationInfo& cli = it.second;
+
+    os << "\ncode_path=" << code_path
+        << "\ncode_type=" << CodeTypeName(cli.code_type)
+        << "\ncompiler_filter=" << cli.compiler_filter.value_or(kUnknownValue)
+        << "\ncompilation_reason=" << cli.compilation_reason.value_or(kUnknownValue)
+        << "\nodex_status=" << cli.odex_status.value_or(kUnknownValue)
+        << "\ncur_profile=" << cli.cur_profile_path.value_or(kUnknownValue)
+        << "\nref_profile=" << cli.ref_profile_path.value_or(kUnknownValue)
+        << "\n";
+  }
+  return os;
+}
+
+}  // namespace art
diff --git a/runtime/app_info.h b/runtime/app_info.h
new file mode 100644
index 0000000..68f2c58
--- /dev/null
+++ b/runtime/app_info.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2021 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_APP_INFO_H_
+#define ART_RUNTIME_APP_INFO_H_
+
+#include <vector>
+
+#include "base/mutex.h"
+#include <base/safe_map.h>
+
+namespace art {
+
+// Constants used by VMRuntime.java to interface with the runtime.
+// We could get them from the well known class but it's simpler to
+// redefine them here.
+
+// VMRuntime.CODE_PATH_TYPE_PRIMARY_APK
+static constexpr int32_t kVMRuntimePrimaryApk = 1 << 0;
+// VMRuntime.CODE_PATH_TYPE_SPLIT_APK
+static constexpr int32_t kVMRuntimeSplitApk = 1 << 1;
+// VMRuntime.CODE_PATH_TYPE_SECONDARY_DEX
+static constexpr int32_t kVMRuntimeSecondaryDex = 1 << 2;
+
+// Encapsulates the information the runtime has about the application.
+//
+// The app's info comes from 2 channels:
+//   1) during class loading, when we load oat files.
+//   2) during app startup, when the framework calls VMRuntime#registerAppInfo.
+// In general the class loading event happens before VMRuntime#registerAppInfo.
+class AppInfo {
+ public:
+  enum class CodeType {
+    kUnknown,
+    kPrimaryApk,
+    kSplitApk,
+    kSecondaryDex,
+  };
+
+  // Converts VMRuntime.java constansts to a CodeType.
+  static CodeType FromVMRuntimeConstants(uint32_t code_type);
+
+  AppInfo();
+
+  // Registers the application code paths, types, and associated profiles.
+  void RegisterAppInfo(const std::string& package_name,
+                       const std::vector<std::string>& code_paths,
+                       const std::string& profile_output_filename,
+                       const std::string& ref_profile_filename,
+                       CodeType code_type);
+
+  // Registers the optimization status for single code path.
+  void RegisterOdexStatus(const std::string& code_path,
+                          const std::string& compiler_filter,
+                          const std::string& compilation_reason,
+                          const std::string& odex_status);
+
+  // Extracts the optimization status of the primary apk into the given arguments.
+  // If there are multiple primary APKs registed via RegisterAppInfo, the method
+  // will assign the status of the first APK, sorted by the location name.
+  //
+  // Assigns "unknown" if there is no primary apk or the optimization status was
+  // not set via RegisterOdexStatus,
+  void GetPrimaryApkOptimizationStatus(std::string* out_compiler_filter,
+                                       std::string* out_compilation_reason);
+
+ private:
+  // Encapsulates optimization information about a particular code location.
+  struct CodeLocationInfo {
+    // The type of the code location (primary, split, secondary, unknown).
+    CodeType code_type{CodeType::kUnknown};
+
+    // The compiler filter of the oat file. Note that this contains
+    // the output of OatFileAssistant#GetOptimizationStatus() which may
+    // contain values outside the scope of the CompilerFilter enum.
+    std::optional<std::string> compiler_filter;
+
+    // The compiler reason of the oat file. Note that this contains
+    // the output of OatFileAssistant#GetOptimizationStatus().
+    std::optional<std::string> compilation_reason;
+
+    // The odes status as produced by OatFileAssistant#GetOptimizationStatus().
+    std::optional<std::string> odex_status;
+
+    // The path to the primary profile if given.
+    std::optional<std::string> cur_profile_path;
+
+    // The path to the reference profile if given.
+    std::optional<std::string> ref_profile_path;
+  };
+
+  // The name of the package if set.
+  std::optional<std::string> package_name_ GUARDED_BY(update_mutex_);
+
+  // The registered code locations.
+  SafeMap<std::string, CodeLocationInfo> registered_code_locations_ GUARDED_BY(update_mutex_);
+
+  // Lock to touch the state ot the AppInfo object.
+  art::Mutex update_mutex_ BOTTOM_MUTEX_ACQUIRED_AFTER;
+
+  friend std::ostream& operator<<(std::ostream& os, AppInfo& rhs);
+};
+
+std::ostream& operator<<(std::ostream& os, AppInfo& rhs);
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_APP_INFO_H_
diff --git a/runtime/app_info_test.cc b/runtime/app_info_test.cc
new file mode 100644
index 0000000..4a365de
--- /dev/null
+++ b/runtime/app_info_test.cc
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2021 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 "app_info.h"
+
+#include <vector>
+
+#include "gtest/gtest.h"
+
+namespace art {
+
+TEST(AppInfoTest, RegisterAppInfo) {
+  AppInfo app_info;
+  app_info.RegisterAppInfo(
+      "package_name",
+      std::vector<std::string>({"code_location"}),
+      "",
+      "",
+      AppInfo::CodeType::kPrimaryApk);
+
+  std::string filter;
+  std::string reason;
+  app_info.GetPrimaryApkOptimizationStatus(&filter, &reason);
+
+  // Odex status was not registered.
+  ASSERT_EQ(filter, "unknown");
+  ASSERT_EQ(reason, "unknown");
+}
+
+TEST(AppInfoTest, RegisterAppInfoWithOdexStatus) {
+  AppInfo app_info;
+  app_info.RegisterAppInfo(
+      "package_name",
+      std::vector<std::string>({"code_location"}),
+      "",
+      "",
+      AppInfo::CodeType::kPrimaryApk);
+  app_info.RegisterOdexStatus(
+      "code_location",
+      "filter",
+      "reason",
+      "odex_status");
+
+  std::string filter;
+  std::string reason;
+  app_info.GetPrimaryApkOptimizationStatus(&filter, &reason);
+
+  ASSERT_EQ(filter, "filter");
+  ASSERT_EQ(reason, "reason");
+}
+
+TEST(AppInfoTest, RegisterAppInfoWithOdexStatusMultiplePrimary) {
+  AppInfo app_info;
+  app_info.RegisterOdexStatus(
+      "code_location",
+      "filter",
+      "reason",
+      "odex_status");
+  app_info.RegisterOdexStatus(
+      "code_location2",
+      "filter2",
+      "reason2",
+      "odex_status");
+  app_info.RegisterAppInfo(
+      "package_name",
+      std::vector<std::string>({"code_location"}),
+      "",
+      "",
+      AppInfo::CodeType::kPrimaryApk);
+
+  std::string filter;
+  std::string reason;
+  app_info.GetPrimaryApkOptimizationStatus(&filter, &reason);
+
+  // The optimization status should be the one of the first apk.
+  ASSERT_EQ(filter, "filter");
+  ASSERT_EQ(reason, "reason");
+}
+
+TEST(AppInfoTest, RegisterAppInfoWithOdexStatusNoPrimary) {
+  AppInfo app_info;
+
+  // Check that the status is not known in an empty app_info.
+  std::string filter;
+  std::string reason;
+  app_info.GetPrimaryApkOptimizationStatus(&filter, &reason);
+
+  // Register a split.s
+  app_info.RegisterAppInfo(
+      "package_name",
+      std::vector<std::string>({"code_location"}),
+      "",
+      "",
+      AppInfo::CodeType::kSplitApk);
+  app_info.RegisterOdexStatus(
+      "code_location",
+      "filter",
+      "reason",
+      "odex_status");
+
+
+  // The optimization status is unknown since we don't have primary apks.
+  app_info.GetPrimaryApkOptimizationStatus(&filter, &reason);
+  ASSERT_EQ(filter, "unknown");
+  ASSERT_EQ(reason, "unknown");
+}
+
+}  // namespace art
diff --git a/runtime/arch/arm/asm_support_arm.S b/runtime/arch/arm/asm_support_arm.S
index 5b51e51..ff95bdd 100644
--- a/runtime/arch/arm/asm_support_arm.S
+++ b/runtime/arch/arm/asm_support_arm.S
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_ARCH_ARM_ASM_SUPPORT_ARM_S_
 
 #include "asm_support_arm.h"
+#include "interpreter/cfi_asm_support.h"
 
 // Define special registers.
 
@@ -35,8 +36,35 @@
 
 .syntax unified
 .arch armv7-a
+.arch_extension idiv
 .thumb
 
+.macro CFI_EXPRESSION_BREG n, b, offset
+    .if (-0x40 <= (\offset)) && ((\offset) < 0x40)
+        CFI_EXPRESSION_BREG_1(\n, \b, \offset)
+    .elseif (-0x2000 <= (\offset)) && ((\offset) < 0x2000)
+        CFI_EXPRESSION_BREG_2(\n, \b, \offset)
+    .else
+        .error "Unsupported offset"
+    .endif
+.endm
+
+.macro CFI_DEF_CFA_BREG_PLUS_UCONST reg, offset, size
+    .if ((\size) < 0)
+        .error "Size should be positive"
+    .endif
+    .if (((\offset) < -0x40) || ((\offset) >= 0x40))
+        .error "Unsupported offset"
+    .endif
+    .if ((\size) < 0x80)
+        CFI_DEF_CFA_BREG_PLUS_UCONST_1_1(\reg, \offset, \size)
+    .elseif ((\size) < 0x4000)
+        CFI_DEF_CFA_BREG_PLUS_UCONST_1_2(\reg, \offset, \size)
+    .else
+        .error "Unsupported size"
+    .endif
+.endm
+
 // Macro to generate the value of Runtime::Current into rDest. As it uses labels
 // then the labels need to be unique. We bind these to the function name in the ENTRY macros.
 .macro RUNTIME_CURRENT name, num, rDest
@@ -149,6 +177,16 @@
 #endif  // USE_HEAP_POISONING
 .endm
 
+.macro INCREASE_FRAME frame_adjustment
+    sub sp, sp, #(\frame_adjustment)
+    .cfi_adjust_cfa_offset (\frame_adjustment)
+.endm
+
+.macro DECREASE_FRAME frame_adjustment
+    add sp, sp, #(\frame_adjustment)
+    .cfi_adjust_cfa_offset -(\frame_adjustment)
+.endm
+
 // Macro to refresh the Marking Register (R8).
 //
 // This macro must be called at the end of functions implementing
@@ -160,6 +198,39 @@
 #endif
 .endm
 
+.macro CONDITIONAL_CBZ reg, reg_if, dest
+.ifc \reg, \reg_if
+    cbz \reg, \dest
+.endif
+.endm
+
+.macro CONDITIONAL_CMPBZ reg, reg_if, dest
+.ifc \reg, \reg_if
+    cmp \reg, #0
+    beq \dest
+.endif
+.endm
+
+// Use CBZ if the register is in {r0, r7} otherwise compare and branch.
+.macro SMART_CBZ reg, dest
+    CONDITIONAL_CBZ \reg, r0, \dest
+    CONDITIONAL_CBZ \reg, r1, \dest
+    CONDITIONAL_CBZ \reg, r2, \dest
+    CONDITIONAL_CBZ \reg, r3, \dest
+    CONDITIONAL_CBZ \reg, r4, \dest
+    CONDITIONAL_CBZ \reg, r5, \dest
+    CONDITIONAL_CBZ \reg, r6, \dest
+    CONDITIONAL_CBZ \reg, r7, \dest
+    CONDITIONAL_CMPBZ \reg, r8, \dest
+    CONDITIONAL_CMPBZ \reg, r9, \dest
+    CONDITIONAL_CMPBZ \reg, r10, \dest
+    CONDITIONAL_CMPBZ \reg, r11, \dest
+    CONDITIONAL_CMPBZ \reg, r12, \dest
+    CONDITIONAL_CMPBZ \reg, r13, \dest
+    CONDITIONAL_CMPBZ \reg, r14, \dest
+    CONDITIONAL_CMPBZ \reg, r15, \dest
+.endm
+
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs), except for storing the method.
@@ -269,4 +340,73 @@
     DELIVER_PENDING_EXCEPTION_FRAME_READY
 .endm
 
+.macro  RETURN_OR_DELIVER_PENDING_EXCEPTION_REG reg
+    ldr \reg, [rSELF, #THREAD_EXCEPTION_OFFSET]  @ Get exception field.
+    cbnz \reg, 1f
+    bx lr
+1:
+    DELIVER_PENDING_EXCEPTION
+.endm
+
+.macro  RETURN_OR_DELIVER_PENDING_EXCEPTION_R1
+    RETURN_OR_DELIVER_PENDING_EXCEPTION_REG r1
+.endm
+
+.macro  RETURN_OR_DELIVER_PENDING_EXCEPTION
+    ldr ip, [rSELF, #THREAD_EXCEPTION_OFFSET]  @ Get exception field.
+    cmp ip, #0
+    bne 1f
+    bx lr
+1:
+    DELIVER_PENDING_EXCEPTION
+.endm
+
+    /*
+     * Macro that sets up the callee save frame to conform with
+     * Runtime::CreateCalleeSaveMethod(kSaveRefsOnly).
+     */
+.macro SETUP_SAVE_REFS_ONLY_FRAME rTemp
+    // Note: We could avoid saving R8 in the case of Baker read
+    // barriers, as it is overwritten by REFRESH_MARKING_REGISTER
+    // later; but it's not worth handling this special case.
+    push {r5-r8, r10-r11, lr}                     @ 7 words of callee saves
+    .cfi_adjust_cfa_offset 28
+    .cfi_rel_offset r5, 0
+    .cfi_rel_offset r6, 4
+    .cfi_rel_offset r7, 8
+    .cfi_rel_offset r8, 12
+    .cfi_rel_offset r10, 16
+    .cfi_rel_offset r11, 20
+    .cfi_rel_offset lr, 24
+    sub sp, #4                                    @ bottom word will hold Method*
+    .cfi_adjust_cfa_offset 4
+    RUNTIME_CURRENT2 \rTemp                       @ Load Runtime::Current into rTemp.
+    @ Load kSaveRefsOnly Method* into rTemp.
+    ldr \rTemp, [\rTemp, #RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET]
+    str \rTemp, [sp, #0]                          @ Place Method* at bottom of stack.
+    str sp, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]  @ Place sp in Thread::Current()->top_quick_frame.
+
+    // Ugly compile-time check, but we only have the preprocessor.
+#if (FRAME_SIZE_SAVE_REFS_ONLY != 28 + 4)
+#error "FRAME_SIZE_SAVE_REFS_ONLY(ARM) size not as expected."
+#endif
+.endm
+
+.macro RESTORE_SAVE_REFS_ONLY_FRAME
+    add sp, #4               @ bottom word holds Method*
+    .cfi_adjust_cfa_offset -4
+    // Note: Likewise, we could avoid restoring R8 in the case of Baker
+    // read barriers, as it is overwritten by REFRESH_MARKING_REGISTER
+    // later; but it's not worth handling this special case.
+    pop {r5-r8, r10-r11, lr} @ 7 words of callee saves
+    .cfi_restore r5
+    .cfi_restore r6
+    .cfi_restore r7
+    .cfi_restore r8
+    .cfi_restore r10
+    .cfi_restore r11
+    .cfi_restore lr
+    .cfi_adjust_cfa_offset -28
+.endm
+
 #endif  // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
diff --git a/runtime/arch/arm/asm_support_arm.h b/runtime/arch/arm/asm_support_arm.h
index 9a01656..aff055e 100644
--- a/runtime/arch/arm/asm_support_arm.h
+++ b/runtime/arch/arm/asm_support_arm.h
@@ -38,8 +38,8 @@
 // i.e. art_quick_read_barrier_mark_introspection_arrays.
 #define BAKER_MARK_INTROSPECTION_ARRAY_SWITCH_OFFSET 0x100
 // The offset from art_quick_read_barrier_mark_introspection to the entrypoint for the
-// UnsafeCASObject intrinsic, i.e. art_quick_read_barrier_mark_introspection_unsafe_cas.
-#define BAKER_MARK_INTROSPECTION_UNSAFE_CAS_ENTRYPOINT_OFFSET 0x180
+// CAS intrinsics, i.e. art_quick_read_barrier_mark_introspection_intrinsic_cas.
+#define BAKER_MARK_INTROSPECTION_INTRINSIC_CAS_ENTRYPOINT_OFFSET 0x180
 
 // The offset of the reference load LDR from the return address in LR for field loads.
 #ifdef USE_HEAP_POISONING
@@ -58,7 +58,7 @@
 // The offset of the reference load LDR from the return address in LR for GC root loads.
 #define BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_WIDE_OFFSET -8
 #define BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_NARROW_OFFSET -6
-// The offset of the ADD from the return address in LR for UnsafeCASObject intrinsic.
-#define BAKER_MARK_INTROSPECTION_UNSAFE_CAS_ADD_OFFSET -8
+// The offset of the MOV from the return address in LR for intrinsic CAS.
+#define BAKER_MARK_INTROSPECTION_INTRINSIC_CAS_MOV_OFFSET -8
 
 #endif  // ART_RUNTIME_ARCH_ARM_ASM_SUPPORT_ARM_H_
diff --git a/runtime/arch/arm/context_arm.h b/runtime/arch/arm/context_arm.h
index 845cdaa..006939c 100644
--- a/runtime/arch/arm/context_arm.h
+++ b/runtime/arch/arm/context_arm.h
@@ -46,6 +46,10 @@
     SetGPR(PC, new_pc);
   }
 
+  void SetNterpDexPC(uintptr_t dex_pc_ptr) override {
+    SetGPR(R11, dex_pc_ptr);
+  }
+
   void SetArg0(uintptr_t new_arg0_value) override {
     SetGPR(R0, new_arg0_value);
   }
diff --git a/runtime/arch/arm/entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc
index c1a03ab..0cfbb04 100644
--- a/runtime/arch/arm/entrypoints_init_arm.cc
+++ b/runtime/arch/arm/entrypoints_init_arm.cc
@@ -59,7 +59,7 @@
 extern "C" mirror::Object* art_quick_read_barrier_mark_introspection_gc_roots_wide(mirror::Object*);
 extern "C" mirror::Object* art_quick_read_barrier_mark_introspection_gc_roots_narrow(
     mirror::Object*);
-extern "C" mirror::Object* art_quick_read_barrier_mark_introspection_unsafe_cas(mirror::Object*);
+extern "C" mirror::Object* art_quick_read_barrier_mark_introspection_intrinsic_cas(mirror::Object*);
 
 // Used by soft float.
 // Single-precision FP arithmetics.
@@ -114,10 +114,10 @@
         reinterpret_cast<intptr_t>(art_quick_read_barrier_mark_introspection_gc_roots_narrow) -
         reinterpret_cast<intptr_t>(art_quick_read_barrier_mark_introspection);
     DCHECK_EQ(BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_NARROW_ENTRYPOINT_OFFSET, gc_roots_narrow_diff);
-    intptr_t unsafe_cas_diff =
-        reinterpret_cast<intptr_t>(art_quick_read_barrier_mark_introspection_unsafe_cas) -
+    intptr_t intrinsic_cas_diff =
+        reinterpret_cast<intptr_t>(art_quick_read_barrier_mark_introspection_intrinsic_cas) -
         reinterpret_cast<intptr_t>(art_quick_read_barrier_mark_introspection);
-    DCHECK_EQ(BAKER_MARK_INTROSPECTION_UNSAFE_CAS_ENTRYPOINT_OFFSET, unsafe_cas_diff);
+    DCHECK_EQ(BAKER_MARK_INTROSPECTION_INTRINSIC_CAS_ENTRYPOINT_OFFSET, intrinsic_cas_diff);
     // The register 12, i.e. IP, is reserved, so there is no art_quick_read_barrier_mark_reg12.
     // We're using the entry to hold a pointer to the introspection entrypoint instead.
     qpoints->pReadBarrierMarkReg12 =
diff --git a/runtime/arch/arm/fault_handler_arm.cc b/runtime/arch/arm/fault_handler_arm.cc
index 4e7d64c..7bd402f 100644
--- a/runtime/arch/arm/fault_handler_arm.cc
+++ b/runtime/arch/arm/fault_handler_arm.cc
@@ -107,14 +107,17 @@
   struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
   struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
   uint8_t* ptr = reinterpret_cast<uint8_t*>(sc->arm_pc);
-  uint32_t instr_size = GetInstructionSize(ptr);
-  uintptr_t gc_map_location = (sc->arm_pc + instr_size) | 1;
+  bool in_thumb_mode = sc->arm_cpsr & (1 << 5);
+  uint32_t instr_size = in_thumb_mode ? GetInstructionSize(ptr) : 4;
+  uintptr_t gc_map_location = (sc->arm_pc + instr_size) | (in_thumb_mode ? 1 : 0);
 
   // Push the gc map location to the stack and pass the fault address in LR.
   sc->arm_sp -= sizeof(uintptr_t);
   *reinterpret_cast<uintptr_t*>(sc->arm_sp) = gc_map_location;
   sc->arm_lr = reinterpret_cast<uintptr_t>(info->si_addr);
   sc->arm_pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
+  // Make sure the thumb bit is set as the handler is in thumb mode.
+  sc->arm_cpsr = sc->arm_cpsr | (1 << 5);
   // Pass the faulting address as the first argument of
   // art_quick_throw_null_pointer_exception_from_signal.
   VLOG(signals) << "Generating null pointer exception";
@@ -231,6 +234,9 @@
   // the function to which this handler returns (art_quick_throw_stack_overflow).
   sc->arm_pc = reinterpret_cast<uintptr_t>(art_quick_throw_stack_overflow);
 
+  // Make sure the thumb bit is set as the handler is in thumb mode.
+  sc->arm_cpsr = sc->arm_cpsr | (1 << 5);
+
   // The kernel will now return to the address in sc->arm_pc.
   return true;
 }
diff --git a/runtime/arch/arm/instruction_set_features_arm.cc b/runtime/arch/arm/instruction_set_features_arm.cc
index fdf4dbd..43c66f8 100644
--- a/runtime/arch/arm/instruction_set_features_arm.cc
+++ b/runtime/arch/arm/instruction_set_features_arm.cc
@@ -29,6 +29,15 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
+#include <cpu_features_macros.h>
+
+#ifdef CPU_FEATURES_ARCH_ARM
+// This header can only be included on ARM targets,
+// as determined by cpu_features own define.
+#include <cpuinfo_arm.h>
+#endif
+
+
 #if defined(__arm__)
 extern "C" bool artCheckForArmSdivInstruction();
 extern "C" bool artCheckForArmv8AInstructions();
@@ -257,7 +266,7 @@
 
   // Use compile time features to "detect" LPAE support.
   // TODO: write an assembly LPAE support test.
-#if defined(__ARM_FEATURE_LPAE)
+#if defined (__ARM_ARCH_8A__) || defined(__ARM_FEATURE_LPAE)
   const bool has_atomic_ldrd_strd = true;
 #else
   const bool has_atomic_ldrd_strd = false;
@@ -267,6 +276,19 @@
                                                             has_armv8a));
 }
 
+ArmFeaturesUniquePtr ArmInstructionSetFeatures::FromCpuFeatures() {
+#ifdef CPU_FEATURES_ARCH_ARM
+  auto info = cpu_features::GetArmInfo();
+  auto features = info.features;
+  return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(features.idiva,
+                                                            features.lpae,
+                                                            info.architecture == 8));
+#else
+  UNIMPLEMENTED(WARNING);
+  return FromCppDefines();
+#endif
+}
+
 bool ArmInstructionSetFeatures::Equals(const InstructionSetFeatures* other) const {
   if (InstructionSet::kArm != other->GetInstructionSet()) {
     return false;
diff --git a/runtime/arch/arm/instruction_set_features_arm.h b/runtime/arch/arm/instruction_set_features_arm.h
index d964148..613ed14 100644
--- a/runtime/arch/arm/instruction_set_features_arm.h
+++ b/runtime/arch/arm/instruction_set_features_arm.h
@@ -47,6 +47,9 @@
   // InstructionSetFeatures. This works around kernel bugs in AT_HWCAP and /proc/cpuinfo.
   static ArmFeaturesUniquePtr FromAssembly();
 
+  // Use external cpu_features library.
+  static ArmFeaturesUniquePtr FromCpuFeatures();
+
   bool Equals(const InstructionSetFeatures* other) const override;
 
   bool HasAtLeast(const InstructionSetFeatures* other) const override;
diff --git a/runtime/arch/arm/jni_entrypoints_arm.S b/runtime/arch/arm/jni_entrypoints_arm.S
index ceef772..3c506b0 100644
--- a/runtime/arch/arm/jni_entrypoints_arm.S
+++ b/runtime/arch/arm/jni_entrypoints_arm.S
@@ -24,10 +24,6 @@
 ENTRY art_jni_dlsym_lookup_stub
     push   {r0, r1, r2, r3, lr}           @ spill regs
     .cfi_adjust_cfa_offset 20
-    .cfi_rel_offset r0, 0
-    .cfi_rel_offset r1, 4
-    .cfi_rel_offset r2, 8
-    .cfi_rel_offset r3, 12
     .cfi_rel_offset lr, 16
     sub    sp, #12                        @ pad stack pointer to align frame
     .cfi_adjust_cfa_offset 12
@@ -40,10 +36,10 @@
     ldr    ip, [ip]                                   // ArtMethod* method
     ldr    ip, [ip, #ART_METHOD_ACCESS_FLAGS_OFFSET]  // uint32_t access_flags
     tst    ip, #(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE)
-    bne    .Llookup_stub_fast_native
+    bne    .Llookup_stub_fast_or_critical_native
     blx    artFindNativeMethod
     b      .Llookup_stub_continue
-.Llookup_stub_fast_native:
+.Llookup_stub_fast_or_critical_native:
     blx    artFindNativeMethodRunnable
 .Llookup_stub_continue:
     mov    r12, r0                        @ save result in r12
@@ -53,10 +49,6 @@
     cbz    r0, 1f                         @ is method code null?
     pop    {r0, r1, r2, r3, lr}           @ restore regs
     .cfi_adjust_cfa_offset -20
-    .cfi_restore r0
-    .cfi_restore r1
-    .cfi_restore r2
-    .cfi_restore r3
     .cfi_restore lr
     bx     r12                            @ if non-null, tail call to method's code
 1:
@@ -69,29 +61,94 @@
     tst    r4, #1
     bne art_jni_dlsym_lookup_stub
 
-    // We need to create a GenericJNI managed frame above the stack args.
+    // Reserve space for a SaveRefsAndArgs managed frame, either for the actual runtime
+    // method or for a GenericJNI frame which is similar but has a native method and a tag.
+    // Do this eagerly, so that we can use these registers as temps without the need to
+    // save and restore them multiple times.
+    INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS
 
-    // GenericJNI frame is similar to SaveRegsAndArgs frame with the native method
-    // instead of runtime method saved at the bottom. Note that the runtime shall
-    // not examine the args here, otherwise we would have to move them in registers
-    // and stack to account for the difference between managed and native ABIs.
-    SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
-    // Save the hidden arg as method pointer, r0 in the padding.
-    // (x0 is an arg in native ABI but not considered an arg in managed ABI.)
-    strd   r4, r0, [sp]
+    // Save args, the hidden arg and caller PC. No CFI needed for args and the hidden arg.
+    push   {r0, r1, r2, r3, r4, lr}
+    .cfi_adjust_cfa_offset 24
+    .cfi_rel_offset lr, 20
 
-    // Call artCriticalNativeOutArgsSize(method)
+    // Call artCriticalNativeFrameSize(method, caller_pc)
     mov    r0, r4  // r0 := method (from hidden arg)
-    bl     artCriticalNativeOutArgsSize
+    mov    r1, lr  // r1 := caller_pc
+    bl     artCriticalNativeFrameSize
 
-    // Check if we have any stack args.
-    cbnz   r0, .Lcritical_has_stack_args
+    // Prepare the return address for managed stack walk of the SaveRefsAndArgs frame.
+    // If we're coming from JNI stub with tail call, it is LR. If we're coming from
+    // JNI stub that saved the return address, it will be the last value we copy below.
+    // If we're coming directly from compiled code, it is LR, set further down.
+    ldr    lr, [sp, #20]
 
-    // Without stack args, the frame is fully constructed.
-    // Place tagged managed sp in Thread::Current()->top_quick_frame.
-    mov    ip, sp
-    orr    ip, #1  // Tag as GenericJNI frame.
-    str    ip, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]
+    // Move the stack args if any.
+    add    r4, sp, #24
+    cbz    r0, .Lcritical_skip_copy_args
+.Lcritical_copy_args_loop:
+    ldrd   ip, lr, [r4, #FRAME_SIZE_SAVE_REFS_AND_ARGS]
+    subs   r0, r0, #8
+    strd   ip, lr, [r4], #8
+    bne    .Lcritical_copy_args_loop
+.Lcritical_skip_copy_args:
+    // The managed frame address is now in R4. This is conveniently a callee-save in native ABI.
+
+    // Restore args.
+    pop    {r0, r1, r2, r3}
+    .cfi_adjust_cfa_offset -16
+
+    // Spill registers for the SaveRefsAndArgs frame above the stack args.
+    // Note that the runtime shall not examine the args here, otherwise we would have to
+    // move them in registers and stack to account for the difference between managed and
+    // native ABIs.
+    add    ip, r4, #FRAME_SIZE_SAVE_REFS_AND_ARGS - 40
+    stmia  ip, {r1-r3, r5-r8, r10-r11, lr}  // LR: Save return address for tail call from JNI stub.
+    // (If there were any stack args, we're storing the value that's already there.
+    // For direct calls from compiled managed code, we shall overwrite this below.)
+    // Skip args r1-r3.
+    CFI_EXPRESSION_BREG 5, 4, FRAME_SIZE_SAVE_REFS_AND_ARGS - 28
+    CFI_EXPRESSION_BREG 6, 4, FRAME_SIZE_SAVE_REFS_AND_ARGS - 24
+    CFI_EXPRESSION_BREG 7, 4, FRAME_SIZE_SAVE_REFS_AND_ARGS - 20
+    CFI_EXPRESSION_BREG 8, 4, FRAME_SIZE_SAVE_REFS_AND_ARGS - 16
+    CFI_EXPRESSION_BREG 10, 4, FRAME_SIZE_SAVE_REFS_AND_ARGS - 12
+    CFI_EXPRESSION_BREG 11, 4, FRAME_SIZE_SAVE_REFS_AND_ARGS - 8
+    // The saved return PC for managed stack walk is not necessarily our LR.
+    // Skip managed FP args as these are native ABI caller-saves and not args.
+
+    // Restore the hidden arg to r1 and caller PC.
+    pop    {r1, lr}
+    .cfi_adjust_cfa_offset -8
+    .cfi_restore lr
+
+    // Save our return PC in the padding.
+    str   lr, [r4, #__SIZEOF_POINTER__]
+    CFI_EXPRESSION_BREG 14, 4, __SIZEOF_POINTER__
+
+    ldr    ip, [r1, #ART_METHOD_ACCESS_FLAGS_OFFSET]  // Load access flags.
+    add    r2, r4, #1             // Prepare managed SP tagged for a GenericJNI frame.
+    tst    ip, #ACCESS_FLAGS_METHOD_IS_NATIVE
+    bne    .Lcritical_skip_prepare_runtime_method
+
+    // When coming from a compiled method, the return PC for managed stack walk is LR.
+    // (When coming from a compiled stub, the correct return PC is already stored above.)
+    str    lr, [r4, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)]
+
+    // Replace the target method with the SaveRefsAndArgs runtime method.
+    RUNTIME_CURRENT1 r1
+    ldr    r1, [r1, #RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET]
+
+    mov    r2, r4                 // Prepare untagged managed SP for the runtime method.
+
+.Lcritical_skip_prepare_runtime_method:
+    // Store the method on the bottom of the managed frame.
+    str    r1, [r4]
+
+    // Place (maybe tagged) managed SP in Thread::Current()->top_quick_frame.
+    str    r2, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]
+
+    // Preserve the native arg register r0 in callee-save register r10 which was saved above.
+    mov    r10, r0
 
     // Call artFindNativeMethodRunnable()
     mov    r0, rSELF   // pass Thread::Current()
@@ -100,150 +157,88 @@
     // Store result in scratch reg.
     mov    ip, r0
 
-    // Restore frame.
-    .cfi_remember_state
-    ldrd   r4, r0, [sp]
-    RESTORE_SAVE_REFS_AND_ARGS_FRAME
-    REFRESH_MARKING_REGISTER
+    // Restore the native arg register r0.
+    mov    r0, r10
 
-    // Check for exception.
-    cmp    ip, #0
-    beq    .Lcritical_deliver_exception
-
-    // Do the tail call.
-    bx     ip
-    .cfi_restore_state
-    .cfi_def_cfa_offset FRAME_SIZE_SAVE_REFS_AND_ARGS
-
-.Lcritical_has_stack_args:
-    // Move the out args size to a scratch register.
-    mov    ip, r0
-
-    // Restore register args as we're about to move stack args.
-    ldrd   r4, r0, [sp]
-    RESTORE_SAVE_REFS_AND_ARGS_FRAME
-
-    // Reserve space for SaveRefsAndArgs frame.
-    sub sp, #FRAME_SIZE_SAVE_REFS_AND_ARGS
-    .cfi_adjust_cfa_offset FRAME_SIZE_SAVE_REFS_AND_ARGS
-
-    // Save arg regs so that we can use them as temporaries.
-    push   {r0-r3}
-    .cfi_adjust_cfa_offset 16
-
-    // Move out args. For simplicity include the return address at the end.
-    add    r0, sp, #16   // Destination.
-    add    ip, r0, ip    // Destination end.
-1:
-    ldrd   r2, r3, [r0, #FRAME_SIZE_SAVE_REFS_AND_ARGS]
-    strd   r2, r3, [r0], #8
-    cmp    r0, ip
-    bne    1b
-
-    // Save our LR, load caller's LR and redefine CFI to take ownership of the JNI stub frame.
-    str    lr, [ip, #-__SIZEOF_POINTER__]
-    mov    lr, r3  // The last moved value from the loop above.
-    .cfi_def_cfa ip, FRAME_SIZE_SAVE_REFS_AND_ARGS
-
-    // Restore arg regs.
-    pop    {r0-r3}  // No `.cfi_adjust_cfa_offset`, CFA register is currently ip, not sp.
-
-    // Re-create the SaveRefsAndArgs frame above the args.
-    strd   r4, r0, [ip]  // r0 in the padding as before.
-    add    r4, ip, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40
-    stmia  r4, {r1-r3, r5-r8, r10-r11, lr}   @ 10 words of callee saves and args.
-    .cfi_rel_offset r1, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 0
-    .cfi_rel_offset r2, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 4
-    .cfi_rel_offset r3, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 8
-    .cfi_rel_offset r5, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 12
-    .cfi_rel_offset r6, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 16
-    .cfi_rel_offset r7, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 20
-    .cfi_rel_offset r8, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 24
-    .cfi_rel_offset r10, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 28
-    .cfi_rel_offset r11, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 32
-    .cfi_rel_offset lr, FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 + 36
-    vstmdb r4!, {s0-s15}                     @ 16 words of float args.
-
-    // Move the frame register to a callee-save register.
-    mov    r11, ip
-    .cfi_def_cfa_register r11
-
-    // Place tagged managed sp in Thread::Current()->top_quick_frame.
-    orr    ip, r11, #1  // Tag as GenericJNI frame.
-    str    ip, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]
-
-    // Call artFindNativeMethodRunnable()
-    mov    r0, rSELF   // pass Thread::Current()
-    bl     artFindNativeMethodRunnable
-
-    // Store result in scratch reg.
-    mov    ip, r0
-
-    // Restore the frame. We shall not need the method anymore, so use r4 as scratch register.
-    mov    r4, r11
-    .cfi_def_cfa_register r4
-    ldr    r0, [r4, #4]
-    add    r11, r4, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - 40 - 64)
-    vldmia r11!, {s0-s15}                    @ 16 words of float args.
-    ldmia  r11, {r1-r3, r5-r8, r10-r11, lr}  @ 10 words of callee saves and args.
-    .cfi_restore r1
-    .cfi_restore r2
-    .cfi_restore r3
+    // Restore the frame. We shall not need the method anymore.
+    add    r1, r4, #FRAME_SIZE_SAVE_REFS_AND_ARGS - 40
+    ldmia  r1, {r1-r3, r5-r8, r10-r11}
     .cfi_restore r5
     .cfi_restore r6
     .cfi_restore r7
     .cfi_restore r8
     .cfi_restore r10
     .cfi_restore r11
-    .cfi_restore lr
+
     REFRESH_MARKING_REGISTER
 
-    // Check for exception.
+    // Check for exception before moving args back to keep the return PC for managed stack walk.
     cmp    ip, #0
-    beq    3f
+    beq    .Lcritical_deliver_exception
 
-    // Save arg regs so that we can use them as temporaries.
-    push   {r0-r3}  // No `.cfi_adjust_cfa_offset`, CFA register is currently r4, not sp.
+    .cfi_remember_state
+
+    // Restore our return PC.
+    ldr    lr, [r4, #__SIZEOF_POINTER__]
+    .cfi_restore lr
 
     // Move stack args to their original place.
-    mov    r0, r4
-    add    r1, sp, #16
-2:
-    ldrd   r2, r3, [r0, #-8]!
-    strd   r2, r3, [r0, #FRAME_SIZE_SAVE_REFS_AND_ARGS]
-    cmp    r1, r0
-    bne    2b
-
-    // Replace original return address with caller's return address.
-    ldr    r1, [r4, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)]
-    str    lr, [r4, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)]
-
-    // Restore LR and redefine CFI to release ownership of the JNI stub frame.
-    .cfi_remember_state
-    mov    lr, r1
-    .cfi_def_cfa sp, FRAME_SIZE_SAVE_REFS_AND_ARGS + 16
-
-    // Restore args
-    pop    {r0-r3}
+    cmp    sp, r4
+    beq    .Lcritical_skip_copy_args_back
+    push   {r0, r1, r2, r3}
+    .cfi_adjust_cfa_offset 16
+    add    r0, sp, #16
+    sub    r0, r4, r0
+.Lcritical_copy_args_loop_back:
+    ldrd   r2, r3, [r4, #-8]!
+    subs   r0, r0, #8
+    strd   r2, r3, [r4, #FRAME_SIZE_SAVE_REFS_AND_ARGS]
+    bne    .Lcritical_copy_args_loop_back
+    pop    {r0, r1, r2, r3}
     .cfi_adjust_cfa_offset -16
+.Lcritical_skip_copy_args_back:
 
     // Remove the frame reservation.
-    add    sp, #FRAME_SIZE_SAVE_REFS_AND_ARGS
-    .cfi_adjust_cfa_offset -FRAME_SIZE_SAVE_REFS_AND_ARGS
+    DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS
 
     // Do the tail call.
     bx     ip
     .cfi_restore_state
-    .cfi_def_cfa x4, FRAME_SIZE_SAVE_REFS_AND_ARGS
-
-3:
-    // Drop stack args and the SaveRefsAndArgs reservation.
-    mov    sp, r4
-    add    sp, #FRAME_SIZE_SAVE_REFS_AND_ARGS
-    .cfi_def_cfa sp, 0
+    .cfi_def_cfa sp, FRAME_SIZE_SAVE_REFS_AND_ARGS
 
 .Lcritical_deliver_exception:
-    // When delivering exception, we check that rSELF was saved but the SaveRefsAndArgs frame does
-    // not save it, so we cannot use DELIVER_PENDING_EXCEPTION_FRAME_READY with the above frames.
-    DELIVER_PENDING_EXCEPTION
+    // The exception delivery checks that rSELF was saved but the SaveRefsAndArgs
+    // frame does not save it, so we cannot use the existing SaveRefsAndArgs frame.
+    // That's why we checked for exception after restoring registers from it.
+    // We need to build a SaveAllCalleeSaves frame instead. Args are irrelevant at this
+    // point but keep the area allocated for stack args to keep CFA definition simple.
+#if FRAME_SIZE_SAVE_REFS_AND_ARGS != FRAME_SIZE_SAVE_ALL_CALLEE_SAVES
+#  error "Expected FRAME_SIZE_SAVE_REFS_AND_ARGS == FRAME_SIZE_SAVE_ALL_CALLEE_SAVES"
+    // Otherwise we would need to adjust SP and R4 and move our return PC which is at [R4, #4].
+    // (Luckily, both SaveRefsAndArgs and SaveAllCalleeSaves frames have padding there.)
+#endif
+
+    // Spill registers for the SaveAllCalleeSaves frame above the stack args area.
+    add    ip, r4, #FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 32
+    stmia  ip, {r5-r11}  // Keep the caller PC for managed stack walk.
+    CFI_EXPRESSION_BREG 5, 4, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 32
+    CFI_EXPRESSION_BREG 6, 4, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 28
+    CFI_EXPRESSION_BREG 7, 4, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 24
+    CFI_EXPRESSION_BREG 8, 4, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 20
+    CFI_EXPRESSION_BREG 9, 4, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 16
+    CFI_EXPRESSION_BREG 10, 4, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 12
+    CFI_EXPRESSION_BREG 11, 4, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 8
+    // Skip R4, it is callee-save in managed ABI.
+    add    ip, r4, #12
+    vstmia ip, {s16-s31}
+
+    // Store ArtMethod* Runtime::callee_save_methods_[kSaveAllCalleeSaves] to the managed frame.
+    RUNTIME_CURRENT2 ip
+    ldr   ip, [ip, #RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET]
+    str   ip, [r4]
+
+    // Place the managed frame SP in Thread::Current()->top_quick_frame.
+    str   r4, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]
+
+    DELIVER_PENDING_EXCEPTION_FRAME_READY
 END art_jni_dlsym_lookup_critical_stub
diff --git a/runtime/arch/arm/jni_frame_arm.h b/runtime/arch/arm/jni_frame_arm.h
index 5203eaf..2263873 100644
--- a/runtime/arch/arm/jni_frame_arm.h
+++ b/runtime/arch/arm/jni_frame_arm.h
@@ -38,9 +38,8 @@
 // Note: AAPCS is soft-float, so these are all core registers.
 constexpr size_t kJniArgumentRegisterCount = 4u;
 
-// Get the size of "out args" for @CriticalNative method stub.
-// This must match the size of the frame emitted by the JNI compiler at the native call site.
-inline size_t GetCriticalNativeOutArgsSize(const char* shorty, uint32_t shorty_len) {
+// Get stack args size for @CriticalNative method calls.
+inline size_t GetCriticalNativeCallArgsSize(const char* shorty, uint32_t shorty_len) {
   DCHECK_EQ(shorty_len, strlen(shorty));
 
   size_t reg = 0;  // Register for the current argument; if reg >= 4, we shall use stack.
@@ -54,7 +53,14 @@
     reg += 1u;
   }
   size_t stack_args = std::max(reg, kJniArgumentRegisterCount) - kJniArgumentRegisterCount;
-  size_t size = kFramePointerSize * stack_args;
+  return kFramePointerSize * stack_args;
+}
+
+// Get the frame size for @CriticalNative method stub.
+// This must match the size of the frame emitted by the JNI compiler at the native call site.
+inline size_t GetCriticalNativeStubFrameSize(const char* shorty, uint32_t shorty_len) {
+  // The size of outgoing arguments.
+  size_t size = GetCriticalNativeCallArgsSize(shorty, shorty_len);
 
   // Check if this is a tail call, i.e. there are no stack args and the return type
   // is not  an FP type (otherwise we need to move the result to FP register).
@@ -65,6 +71,16 @@
   return RoundUp(size, kAapcsStackAlignment);
 }
 
+// Get the frame size for direct call to a @CriticalNative method.
+// This must match the size of the extra frame emitted by the compiler at the native call site.
+inline size_t GetCriticalNativeDirectCallFrameSize(const char* shorty, uint32_t shorty_len) {
+  // The size of outgoing arguments.
+  size_t size = GetCriticalNativeCallArgsSize(shorty, shorty_len);
+
+  // No return PC to save, zero- and sign-extension and FP value moves are handled by the caller.
+  return RoundUp(size, kAapcsStackAlignment);
+}
+
 }  // namespace arm
 }  // namespace art
 
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index f94694d..f5f1274 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -24,54 +24,6 @@
     /* Deliver an exception pending on a thread */
     .extern artDeliverPendingException
 
-    /*
-     * Macro that sets up the callee save frame to conform with
-     * Runtime::CreateCalleeSaveMethod(kSaveRefsOnly).
-     */
-.macro SETUP_SAVE_REFS_ONLY_FRAME rTemp
-    // Note: We could avoid saving R8 in the case of Baker read
-    // barriers, as it is overwritten by REFRESH_MARKING_REGISTER
-    // later; but it's not worth handling this special case.
-    push {r5-r8, r10-r11, lr}                     @ 7 words of callee saves
-    .cfi_adjust_cfa_offset 28
-    .cfi_rel_offset r5, 0
-    .cfi_rel_offset r6, 4
-    .cfi_rel_offset r7, 8
-    .cfi_rel_offset r8, 12
-    .cfi_rel_offset r10, 16
-    .cfi_rel_offset r11, 20
-    .cfi_rel_offset lr, 24
-    sub sp, #4                                    @ bottom word will hold Method*
-    .cfi_adjust_cfa_offset 4
-    RUNTIME_CURRENT2 \rTemp                       @ Load Runtime::Current into rTemp.
-    @ Load kSaveRefsOnly Method* into rTemp.
-    ldr \rTemp, [\rTemp, #RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET]
-    str \rTemp, [sp, #0]                          @ Place Method* at bottom of stack.
-    str sp, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]  @ Place sp in Thread::Current()->top_quick_frame.
-
-    // Ugly compile-time check, but we only have the preprocessor.
-#if (FRAME_SIZE_SAVE_REFS_ONLY != 28 + 4)
-#error "FRAME_SIZE_SAVE_REFS_ONLY(ARM) size not as expected."
-#endif
-.endm
-
-.macro RESTORE_SAVE_REFS_ONLY_FRAME
-    add sp, #4               @ bottom word holds Method*
-    .cfi_adjust_cfa_offset -4
-    // Note: Likewise, we could avoid restoring R8 in the case of Baker
-    // read barriers, as it is overwritten by REFRESH_MARKING_REGISTER
-    // later; but it's not worth handling this special case.
-    pop {r5-r8, r10-r11, lr} @ 7 words of callee saves
-    .cfi_restore r5
-    .cfi_restore r6
-    .cfi_restore r7
-    .cfi_restore r8
-    .cfi_restore r10
-    .cfi_restore r11
-    .cfi_restore lr
-    .cfi_adjust_cfa_offset -28
-.endm
-
 .macro SETUP_SAVE_REFS_AND_ARGS_FRAME rTemp
     SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
     RUNTIME_CURRENT3 \rTemp                       @ Load Runtime::Current into rTemp.
@@ -230,18 +182,6 @@
 END \c_name
 .endm
 
-.macro  RETURN_OR_DELIVER_PENDING_EXCEPTION_REG reg
-    ldr \reg, [rSELF, #THREAD_EXCEPTION_OFFSET]  @ Get exception field.
-    cbnz \reg, 1f
-    bx lr
-1:
-    DELIVER_PENDING_EXCEPTION
-.endm
-
-.macro  RETURN_OR_DELIVER_PENDING_EXCEPTION_R1
-    RETURN_OR_DELIVER_PENDING_EXCEPTION_REG r1
-.endm
-
 .macro RETURN_IF_RESULT_IS_ZERO_OR_DELIVER
     RETURN_IF_RESULT_IS_ZERO
     DELIVER_PENDING_EXCEPTION
@@ -1224,6 +1164,8 @@
 .endm
 
 // The common code for art_quick_alloc_object_*region_tlab
+// Currently the implementation ignores isInitialized. TODO(b/172087402): clean this up.
+// Caller must execute a constructor fence after this.
 .macro GENERATE_ALLOC_OBJECT_RESOLVED_TLAB name, entrypoint, isInitialized
 ENTRY \name
     // Fast path tlab allocation.
@@ -1290,6 +1232,7 @@
     bx     lr
 .endm
 
+// Caller must execute a constructor fence after this.
 .macro GENERATE_ALLOC_ARRAY_TLAB name, entrypoint, size_setup
 ENTRY \name
     // Fast path array allocation for region tlab allocation.
@@ -1313,10 +1256,6 @@
 .endm
 
 .macro COMPUTE_ARRAY_SIZE_UNKNOWN slow_path
-    bkpt                                                    // We should never enter here.
-                                                            // Code below is for reference.
-                                                            // Possibly a large object, go slow.
-                                                            // Also does negative array size check.
     movw r2, #((MIN_LARGE_OBJECT_THRESHOLD - MIRROR_WIDE_ARRAY_DATA_OFFSET) / 8)
     cmp r1, r2
     bhi \slow_path
@@ -1384,8 +1323,6 @@
     add    r2, r2, #(MIRROR_WIDE_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK)
 .endm
 
-// TODO(ngeoffray): art_quick_alloc_array_resolved_region_tlab is not used for arm, remove
-// the entrypoint once all backends have been updated to use the size variants.
 GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_UNKNOWN
 GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved8_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_8
 GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved16_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_16
@@ -1446,113 +1383,31 @@
     /*
      * Called to resolve an imt conflict.
      * r0 is the conflict ArtMethod.
-     * r12 is a hidden argument that holds the target interface method's dex method index.
+     * r12 is a hidden argument that holds the target interface method.
      *
      * Note that this stub writes to r0, r4, and r12.
      */
-    .extern artLookupResolvedMethod
 ENTRY art_quick_imt_conflict_trampoline
-    push    {r1-r2}
-    .cfi_adjust_cfa_offset (2 * 4)
-    .cfi_rel_offset r1, 0
-    .cfi_rel_offset r2, 4
-    ldr     r4, [sp, #(2 * 4)]  // Load referrer.
-    ldr     r2, [r0, #ART_METHOD_JNI_OFFSET_32]  // Load ImtConflictTable
-    // Load the declaring class (without read barrier) and access flags (for obsolete method check).
-    // The obsolete flag is set with suspended threads, so we do not need an acquire operation here.
-#if ART_METHOD_ACCESS_FLAGS_OFFSET != ART_METHOD_DECLARING_CLASS_OFFSET + 4
-#error "Expecting declaring class and access flags to be consecutive for LDRD."
-#endif
-    ldrd    r0, r1, [r4, #ART_METHOD_DECLARING_CLASS_OFFSET]
-    // If the method is obsolete, just go through the dex cache miss slow path.
-    lsrs    r1, #(ACC_OBSOLETE_METHOD_SHIFT + 1)
-    bcs     .Limt_conflict_trampoline_dex_cache_miss
-    ldr     r4, [r0, #MIRROR_CLASS_DEX_CACHE_OFFSET]  // Load the DexCache (without read barrier).
-    UNPOISON_HEAP_REF r4
-    ubfx    r1, r12, #0, #METHOD_DEX_CACHE_HASH_BITS  // Calculate DexCache method slot index.
-    ldr     r4, [r4, #MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET]  // Load the resolved methods.
-    add     r4, r4, r1, lsl #(POINTER_SIZE_SHIFT + 1)  // Load DexCache method slot address.
-
-// FIXME: Configure the build to use the faster code when appropriate.
-//        Currently we fall back to the slower version.
-#if HAS_ATOMIC_LDRD
-    ldrd    r0, r1, [r4]
-#else
-    push    {r3}
-    .cfi_adjust_cfa_offset 4
-    .cfi_rel_offset r3, 0
-.Limt_conflict_trampoline_retry_load:
-    ldrexd  r0, r1, [r4]
-    strexd  r3, r0, r1, [r4]
-    cmp     r3, #0
-    bne     .Limt_conflict_trampoline_retry_load
-    pop     {r3}
-    .cfi_adjust_cfa_offset -4
-    .cfi_restore r3
-#endif
-
-    ldr     r4, [r2]  // Load first entry in ImtConflictTable.
-    cmp     r1, r12   // Compare method index to see if we had a DexCache method hit.
-    bne     .Limt_conflict_trampoline_dex_cache_miss
+    ldr     r0, [r0, #ART_METHOD_JNI_OFFSET_32]  // Load ImtConflictTable
+    ldr     r4, [r0]  // Load first entry in ImtConflictTable.
 .Limt_table_iterate:
-    cmp     r4, r0
+    cmp     r4, r12
     // Branch if found. Benchmarks have shown doing a branch here is better.
     beq     .Limt_table_found
     // If the entry is null, the interface method is not in the ImtConflictTable.
     cbz     r4, .Lconflict_trampoline
     // Iterate over the entries of the ImtConflictTable.
-    ldr     r4, [r2, #(2 * __SIZEOF_POINTER__)]!
+    ldr     r4, [r0, #(2 * __SIZEOF_POINTER__)]!
     b .Limt_table_iterate
 .Limt_table_found:
     // We successfully hit an entry in the table. Load the target method
     // and jump to it.
-    ldr     r0, [r2, #__SIZEOF_POINTER__]
-    .cfi_remember_state
-    pop     {r1-r2}
-    .cfi_adjust_cfa_offset -(2 * 4)
-    .cfi_restore r1
-    .cfi_restore r2
+    ldr     r0, [r0, #__SIZEOF_POINTER__]
     ldr     pc, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
-    .cfi_restore_state
 .Lconflict_trampoline:
-    // Call the runtime stub to populate the ImtConflictTable and jump to the
-    // resolved method.
-    .cfi_remember_state
-    pop     {r1-r2}
-    .cfi_adjust_cfa_offset -(2 * 4)
-    .cfi_restore r1
-    .cfi_restore r2
+    // Pass interface method to the trampoline.
+    mov r0, r12
     INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
-    .cfi_restore_state
-.Limt_conflict_trampoline_dex_cache_miss:
-    // We're not creating a proper runtime method frame here,
-    // artLookupResolvedMethod() is not allowed to walk the stack.
-
-    // Save ImtConflictTable (r2), remaining arg (r3), first entry (r4), return address (lr).
-    push    {r2-r4, lr}
-    .cfi_adjust_cfa_offset (4 * 4)
-    .cfi_rel_offset r3, 4
-    .cfi_rel_offset lr, 12
-    // Save FPR args.
-    vpush   {d0-d7}
-    .cfi_adjust_cfa_offset (8 * 8)
-
-    mov     r0, ip                      // Pass method index.
-    ldr     r1, [sp, #(8 * 8 + 6 * 4)]  // Pass referrer.
-    bl      artLookupResolvedMethod     // (uint32_t method_index, ArtMethod* referrer)
-
-    // Restore FPR args.
-    vpop    {d0-d7}
-    .cfi_adjust_cfa_offset -(8 * 8)
-    // Restore ImtConflictTable (r2), remaining arg (r3), first entry (r4), return address (lr).
-    pop     {r2-r4, lr}
-    .cfi_adjust_cfa_offset -(4 * 4)
-    .cfi_restore r3
-    .cfi_restore lr
-
-    cmp     r0, #0                  // If the method wasn't resolved,
-    beq     .Lconflict_trampoline   //   skip the lookup and go to artInvokeInterfaceTrampoline().
-    b       .Limt_table_iterate
 END art_quick_imt_conflict_trampoline
 
     .extern artQuickResolutionTrampoline
@@ -1643,6 +1498,7 @@
 
     // Tear down the alloca.
     mov sp, r10
+    .cfi_remember_state
     .cfi_def_cfa_register sp
 
     // Tear down the callee-save frame. Skip arg registers.
@@ -1654,18 +1510,21 @@
     // store into fpr, for when it's a fpr return...
     vmov d0, r0, r1
     bx lr      // ret
-    // Undo the unwinding information from above since it doesn't apply below.
-    .cfi_def_cfa_register r10
-    .cfi_adjust_cfa_offset FRAME_SIZE_SAVE_REFS_AND_ARGS-FRAME_SIZE_SAVE_REFS_ONLY
 
+    // Undo the unwinding information from above since it doesn't apply below.
+    .cfi_restore_state
+    .cfi_def_cfa r10, FRAME_SIZE_SAVE_REFS_AND_ARGS
 .Lexception_in_native:
     ldr ip, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]
     add ip, ip, #-1  // Remove the GenericJNI tag. ADD/SUB writing directly to SP is UNPREDICTABLE.
     mov sp, ip
-    .cfi_def_cfa_register sp
+    bl art_deliver_pending_exception
+END art_quick_generic_jni_trampoline
+
+ENTRY art_deliver_pending_exception
     # This will create a new save-all frame, required by the runtime.
     DELIVER_PENDING_EXCEPTION
-END art_quick_generic_jni_trampoline
+END art_deliver_pending_exception
 
     .extern artQuickToInterpreterBridge
 ENTRY art_quick_to_interpreter_bridge
@@ -2077,39 +1936,6 @@
     RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
 END art_quick_string_builder_append
 
-.macro CONDITIONAL_CBZ reg, reg_if, dest
-.ifc \reg, \reg_if
-    cbz \reg, \dest
-.endif
-.endm
-
-.macro CONDITIONAL_CMPBZ reg, reg_if, dest
-.ifc \reg, \reg_if
-    cmp \reg, #0
-    beq \dest
-.endif
-.endm
-
-// Use CBZ if the register is in {r0, r7} otherwise compare and branch.
-.macro SMART_CBZ reg, dest
-    CONDITIONAL_CBZ \reg, r0, \dest
-    CONDITIONAL_CBZ \reg, r1, \dest
-    CONDITIONAL_CBZ \reg, r2, \dest
-    CONDITIONAL_CBZ \reg, r3, \dest
-    CONDITIONAL_CBZ \reg, r4, \dest
-    CONDITIONAL_CBZ \reg, r5, \dest
-    CONDITIONAL_CBZ \reg, r6, \dest
-    CONDITIONAL_CBZ \reg, r7, \dest
-    CONDITIONAL_CMPBZ \reg, r8, \dest
-    CONDITIONAL_CMPBZ \reg, r9, \dest
-    CONDITIONAL_CMPBZ \reg, r10, \dest
-    CONDITIONAL_CMPBZ \reg, r11, \dest
-    CONDITIONAL_CMPBZ \reg, r12, \dest
-    CONDITIONAL_CMPBZ \reg, r13, \dest
-    CONDITIONAL_CMPBZ \reg, r14, \dest
-    CONDITIONAL_CMPBZ \reg, r15, \dest
-.endm
-
     /*
      * Create a function `name` calling the ReadBarrier::Mark routine,
      * getting its argument and returning its result through register
@@ -2444,11 +2270,15 @@
      * The thunk also performs all the fast-path checks, so we need just the
      * slow path.
      *
-     * The UnsafeCASObject intrinsic is similar to the GC roots wide approach
-     * but using ADD (register, T3) instead of the LDR (immediate, T3), so the
-     * destination register is in bits 8-11 rather than 12-15. Therefore it has
-     * its own entrypoint, art_quick_read_barrier_mark_introspection_unsafe_cas
-     * at the offset BAKER_MARK_INTROSPECTION_UNSAFE_CAS_ENTRYPOINT_OFFSET.
+     * Intrinsic CAS operations (VarHandle*CompareAnd{Set,Exchange}* and
+     * UnsafeCASObject) use similar code to the GC roots wide load but using
+     * MOV (register, T3) instead of the LDR (immediate, T3), with destination
+     * register in bits 8-11 rather than 12-15. Therefore they have their own
+     * entrypoint, art_quick_read_barrier_mark_introspection_intrinsic_cas
+     * at the offset BAKER_MARK_INTROSPECTION_INTRINSIC_CAS_ENTRYPOINT_OFFSET.
+     * This is used only for high registers, low registers reuse the GC roots
+     * narrow load entrypoint as the low 3 bits of the destination register
+     * for MOV (register) encoding T1 match the LDR (immediate) encoding T1.
      *
      * The code structure is
      *   art_quick_read_barrier_mark_introspection:                   // @0x00
@@ -2485,9 +2315,9 @@
      *     return switch.
      *   art_quick_read_barrier_mark_introspection_arrays:            // @0x100
      *     Exactly 128 bytes for array load switch cases (16x2 instructions).
-     *   art_quick_read_barrier_mark_introspection_unsafe_cas:        // @0x180
-     *     UnsafeCASObject intrinsic entrypoint for ADD (register) encoding T3
-     *     (6 bytes). Loads the return register and jumps to the runtime call.
+     *   art_quick_read_barrier_mark_introspection_intrinsic_cas:     // @0x180
+     *     Intrinsic CAS entrypoint for MOV (register) encoding T3 (6 bytes).
+     *     Loads the return register and jumps to the runtime call.
      */
 #if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER)
 ENTRY_ALIGNED art_quick_read_barrier_mark_introspection, 512
@@ -2556,15 +2386,14 @@
 
     .balign 8
     .thumb_func
-    .type art_quick_read_barrier_mark_introspection_unsafe_cas, #function
-    .hidden art_quick_read_barrier_mark_introspection_unsafe_cas
-    .global art_quick_read_barrier_mark_introspection_unsafe_cas
-art_quick_read_barrier_mark_introspection_unsafe_cas:
-    // Load the byte of the ADD instruction that contains Rd. Adjust for the thumb state in LR.
-    // The ADD (register, T3) is |11101011000|S|Rn|(0)imm3|Rd|imm2|type|Rm| and we're using
-    // no shift (type=0, imm2=0, imm3=0), so the byte we read here, i.e. |(0)imm3|Rd|,
-    // contains only the register number, the top 4 bits are 0.
-    ldrb    rMR, [lr, #(-1 + BAKER_MARK_INTROSPECTION_UNSAFE_CAS_ADD_OFFSET + 3)]
+    .type art_quick_read_barrier_mark_introspection_intrinsic_cas, #function
+    .hidden art_quick_read_barrier_mark_introspection_intrinsic_cas
+    .global art_quick_read_barrier_mark_introspection_intrinsic_cas
+art_quick_read_barrier_mark_introspection_intrinsic_cas:
+    // Load the byte of the MOV instruction that contains Rd. Adjust for the thumb state in LR.
+    // The MOV (register, T3) is |11101010010|S|1111|(0)000|Rd|0000|Rm|, so the byte we read
+    // here, i.e. |(0)000|Rd|, contains only the register number, the top 4 bits are 0.
+    ldrb    rMR, [lr, #(-1 + BAKER_MARK_INTROSPECTION_INTRINSIC_CAS_MOV_OFFSET + 3)]
     b .Lmark_introspection_runtime_call
 END art_quick_read_barrier_mark_introspection
 #else  // defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER)
diff --git a/runtime/arch/arm64/asm_support_arm64.S b/runtime/arch/arm64/asm_support_arm64.S
index b1e5c86..e02d7f2 100644
--- a/runtime/arch/arm64/asm_support_arm64.S
+++ b/runtime/arch/arm64/asm_support_arm64.S
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_ARCH_ARM64_ASM_SUPPORT_ARM64_S_
 
 #include "asm_support_arm64.h"
+#include "interpreter/cfi_asm_support.h"
 
 // Define special registers.
 
@@ -40,6 +41,32 @@
 #define wMR w20
 #endif
 
+.macro CFI_EXPRESSION_BREG n, b, offset
+    .if (-0x40 <= (\offset)) && ((\offset) < 0x40)
+        CFI_EXPRESSION_BREG_1(\n, \b, \offset)
+    .elseif (-0x2000 <= (\offset)) && ((\offset) < 0x2000)
+        CFI_EXPRESSION_BREG_2(\n, \b, \offset)
+    .else
+        .error "Unsupported offset"
+    .endif
+.endm
+
+.macro CFI_DEF_CFA_BREG_PLUS_UCONST reg, offset, size
+    .if ((\size) < 0)
+        .error "Size should be positive"
+    .endif
+    .if (((\offset) < -0x40) || ((\offset) >= 0x40))
+        .error "Unsupported offset"
+    .endif
+    .if ((\size) < 0x80)
+        CFI_DEF_CFA_BREG_PLUS_UCONST_1_1(\reg, \offset, \size)
+    .elseif ((\size) < 0x4000)
+        CFI_DEF_CFA_BREG_PLUS_UCONST_1_2(\reg, \offset, \size)
+    .else
+        .error "Unsupported size"
+    .endif
+.endm
+
 .macro ENTRY_ALIGNED name, alignment
     .type \name, #function
     .hidden \name  // Hide this as a global symbol, so we do not incur plt calls.
@@ -98,11 +125,15 @@
     .cfi_rel_offset \reg, (\offset)
 .endm
 
-.macro RESTORE_REG reg, offset
-    ldr \reg, [sp, #(\offset)]
+.macro RESTORE_REG_BASE base, reg, offset
+    ldr \reg, [\base, #(\offset)]
     .cfi_restore \reg
 .endm
 
+.macro RESTORE_REG reg, offset
+    RESTORE_REG_BASE sp, \reg, \offset
+.endm
+
 .macro SAVE_TWO_REGS_BASE base, reg1, reg2, offset
     stp \reg1, \reg2, [\base, #(\offset)]
     .cfi_rel_offset \reg1, (\offset)
@@ -125,11 +156,11 @@
 
 .macro LOAD_RUNTIME_INSTANCE reg
 #if __has_feature(hwaddress_sanitizer) && __clang_major__ >= 10
-    adrp xIP0, :pg_hi21_nc:_ZN3art7Runtime9instance_E
+    adrp \reg, :pg_hi21_nc:_ZN3art7Runtime9instance_E
 #else
-    adrp xIP0, _ZN3art7Runtime9instance_E
+    adrp \reg, _ZN3art7Runtime9instance_E
 #endif
-    ldr xIP0, [xIP0, #:lo12:_ZN3art7Runtime9instance_E]
+    ldr \reg, [\reg, #:lo12:_ZN3art7Runtime9instance_E]
 .endm
 
 // Macro to refresh the Marking Register (W20).
@@ -263,6 +294,22 @@
     DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS
 .endm
 
+.macro SAVE_ALL_CALLEE_SAVES offset
+    // FP callee-saves.
+    stp d8, d9,   [sp, #(0 + \offset)]
+    stp d10, d11, [sp, #(16 + \offset)]
+    stp d12, d13, [sp, #(32 + \offset)]
+    stp d14, d15, [sp, #(48 + \offset)]
+
+    // GP callee-saves
+    SAVE_TWO_REGS x19, x20, (64 + \offset)
+    SAVE_TWO_REGS x21, x22, (80 + \offset)
+    SAVE_TWO_REGS x23, x24, (96 + \offset)
+    SAVE_TWO_REGS x25, x26, (112 + \offset)
+    SAVE_TWO_REGS x27, x28, (128 + \offset)
+    SAVE_TWO_REGS x29, xLR, (144 + \offset)
+.endm
+
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveAllCalleeSaves)
@@ -283,19 +330,7 @@
 #endif
 
     // Stack alignment filler [sp, #8].
-    // FP callee-saves.
-    stp d8, d9,   [sp, #16]
-    stp d10, d11, [sp, #32]
-    stp d12, d13, [sp, #48]
-    stp d14, d15, [sp, #64]
-
-    // GP callee-saves
-    SAVE_TWO_REGS x19, x20, 80
-    SAVE_TWO_REGS x21, x22, 96
-    SAVE_TWO_REGS x23, x24, 112
-    SAVE_TWO_REGS x25, x26, 128
-    SAVE_TWO_REGS x27, x28, 144
-    SAVE_TWO_REGS x29, xLR, 160
+    SAVE_ALL_CALLEE_SAVES 16
 
     // Store ArtMethod* Runtime::callee_save_methods_[kSaveAllCalleeSaves].
     str xIP0, [sp]
diff --git a/runtime/arch/arm64/asm_support_arm64.h b/runtime/arch/arm64/asm_support_arm64.h
index 57376d0..887ee02 100644
--- a/runtime/arch/arm64/asm_support_arm64.h
+++ b/runtime/arch/arm64/asm_support_arm64.h
@@ -19,7 +19,9 @@
 
 #include "asm_support.h"
 
-#define FRAME_SIZE_SAVE_ALL_CALLEE_SAVES 176
+#define CALLEE_SAVES_SIZE (12 * 8 + 8 * 8)
+// +8 for the ArtMethod, +8 for alignment.
+#define FRAME_SIZE_SAVE_ALL_CALLEE_SAVES (CALLEE_SAVES_SIZE + 16)
 #define FRAME_SIZE_SAVE_REFS_ONLY 96
 #define FRAME_SIZE_SAVE_REFS_AND_ARGS 224
 #define FRAME_SIZE_SAVE_EVERYTHING 512
diff --git a/runtime/arch/arm64/context_arm64.h b/runtime/arch/arm64/context_arm64.h
index 95dac90..5ab63c0 100644
--- a/runtime/arch/arm64/context_arm64.h
+++ b/runtime/arch/arm64/context_arm64.h
@@ -46,6 +46,10 @@
     SetGPR(kPC, new_lr);
   }
 
+  void SetNterpDexPC(uintptr_t dex_pc_ptr) override {
+    SetGPR(X22, dex_pc_ptr);
+  }
+
   void SetArg0(uintptr_t new_arg0_value) override {
     SetGPR(X0, new_arg0_value);
   }
diff --git a/runtime/arch/arm64/instruction_set_features_arm64.cc b/runtime/arch/arm64/instruction_set_features_arm64.cc
index 17369e8..1e779f5 100644
--- a/runtime/arch/arm64/instruction_set_features_arm64.cc
+++ b/runtime/arch/arm64/instruction_set_features_arm64.cc
@@ -30,6 +30,14 @@
 
 #include "base/stl_util.h"
 
+#include <cpu_features_macros.h>
+
+#ifdef CPU_FEATURES_ARCH_AARCH64
+// This header can only be included on aarch64 targets,
+// as determined by cpu_features own define.
+#include <cpuinfo_aarch64.h>
+#endif
+
 namespace art {
 
 using android::base::StringPrintf;
@@ -245,6 +253,22 @@
   return FromCppDefines();
 }
 
+Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromCpuFeatures() {
+#ifdef CPU_FEATURES_ARCH_AARCH64
+  auto features = cpu_features::GetAarch64Info().features;
+  return Arm64FeaturesUniquePtr(new Arm64InstructionSetFeatures(false,
+                                                                false,
+                                                                features.crc32,
+                                                                features.atomics,
+                                                                features.fphp,
+                                                                features.asimddp,
+                                                                features.sve));
+#else
+  UNIMPLEMENTED(WARNING);
+  return FromCppDefines();
+#endif
+}
+
 bool Arm64InstructionSetFeatures::Equals(const InstructionSetFeatures* other) const {
   if (InstructionSet::kArm64 != other->GetInstructionSet()) {
     return false;
diff --git a/runtime/arch/arm64/instruction_set_features_arm64.h b/runtime/arch/arm64/instruction_set_features_arm64.h
index d3c127a..eb98c01 100644
--- a/runtime/arch/arm64/instruction_set_features_arm64.h
+++ b/runtime/arch/arm64/instruction_set_features_arm64.h
@@ -21,6 +21,9 @@
 
 namespace art {
 
+// SVE is currently not enabled.
+static constexpr bool kArm64AllowSVE = false;
+
 class Arm64InstructionSetFeatures;
 using Arm64FeaturesUniquePtr = std::unique_ptr<const Arm64InstructionSetFeatures>;
 
@@ -47,6 +50,9 @@
   // InstructionSetFeatures. This works around kernel bugs in AT_HWCAP and /proc/cpuinfo.
   static Arm64FeaturesUniquePtr FromAssembly();
 
+  // Use external cpu_features library.
+  static Arm64FeaturesUniquePtr FromCpuFeatures();
+
   bool Equals(const InstructionSetFeatures* other) const override;
 
   // Note that newer CPUs do not have a53 erratum 835769 and 843419,
@@ -91,7 +97,12 @@
   }
 
   bool HasSVE() const {
-    return has_sve_;
+    return kArm64AllowSVE && has_sve_;
+  }
+
+  size_t GetSVEVectorLength() const {
+    // TODO: support SVE vector length detection.
+    return kArm64DefaultSVEVectorLength;
   }
 
   virtual ~Arm64InstructionSetFeatures() {}
diff --git a/runtime/arch/arm64/jni_entrypoints_arm64.S b/runtime/arch/arm64/jni_entrypoints_arm64.S
index 8a34662..f72bc55 100644
--- a/runtime/arch/arm64/jni_entrypoints_arm64.S
+++ b/runtime/arch/arm64/jni_entrypoints_arm64.S
@@ -55,10 +55,10 @@
     ldr   xIP0, [xIP0, #ART_METHOD_ACCESS_FLAGS_OFFSET]   // uint32_t access_flags
     mov   xIP1, #(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE)
     tst   xIP0, xIP1
-    b.ne  .Llookup_stub_fast_native
+    b.ne  .Llookup_stub_fast_or_critical_native
     bl    artFindNativeMethod
     b     .Llookup_stub_continue
-    .Llookup_stub_fast_native:
+    .Llookup_stub_fast_or_critical_native:
     bl    artFindNativeMethodRunnable
 .Llookup_stub_continue:
     mov   x17, x0    // store result in scratch reg.
@@ -97,136 +97,235 @@
     // For Generic JNI we already have a managed frame, so we reuse the art_jni_dlsym_lookup_stub.
     tbnz  x15, #0, art_jni_dlsym_lookup_stub
 
-    // We need to create a GenericJNI managed frame above the stack args.
+    // Save args, the hidden arg and caller PC. No CFI needed for args and the hidden arg.
+    stp   x0, x1, [sp, #-(8 * 8 + 8 * 8 + 2 * 8)]!
+    .cfi_adjust_cfa_offset (8 * 8 + 8 * 8 + 2 * 8)
+    stp   x2, x3, [sp, #16]
+    stp   x4, x5, [sp, #32]
+    stp   x6, x7, [sp, #48]
+    stp   d0, d1, [sp, #64]
+    stp   d2, d3, [sp, #80]
+    stp   d4, d5, [sp, #96]
+    stp   d6, d7, [sp, #112]
+    stp   x15, lr, [sp, #128]
+    .cfi_rel_offset lr, 136
 
-    // GenericJNI frame is similar to SaveRegsAndArgs frame with the native method
-    // instead of runtime method saved at the bottom. Note that the runtime shall
-    // not examine the args here, otherwise we would have to move them in registers
-    // and stack to account for the difference between managed and native ABIs.
-    INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS
-    SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL sp
-    // Save the hidden arg as method pointer, x0 in the padding.
-    // (x0 is an arg in native ABI but not considered an arg in managed ABI.)
-    SAVE_TWO_REGS x15, x0, 0
-
-    // Call artCriticalNativeOutArgsSize(method)
+    // Call artCriticalNativeFrameSize(method, caller_pc)
     mov   x0, x15  // x0 := method (from hidden arg)
-    bl    artCriticalNativeOutArgsSize
+    mov   x1, lr   // x1 := caller_pc
+    bl    artCriticalNativeFrameSize
 
-    // Check if we have any stack args.
-    cbnz  x0, .Lcritical_has_stack_args
+    // Move frame size to x14.
+    mov   x14, x0
 
-    // Without stack args, the frame is fully constructed.
-    // Place tagged managed sp in Thread::Current()->top_quick_frame.
-    mov   xIP0, sp
-    orr   xIP0, xIP0, #1  // Tag as GenericJNI frame.
-    str   xIP0, [xSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]
+    // Restore args, the hidden arg and caller PC.
+    ldp   x2, x3, [sp, #16]
+    ldp   x4, x5, [sp, #32]
+    ldp   x6, x7, [sp, #48]
+    ldp   d0, d1, [sp, #64]
+    ldp   d2, d3, [sp, #80]
+    ldp   d4, d5, [sp, #96]
+    ldp   d6, d7, [sp, #112]
+    ldp   x15, lr, [sp, #128]
+    .cfi_restore lr
+    ldp   x0, x1, [sp], #(8 * 8 + 8 * 8 + 2 * 8)
+    .cfi_adjust_cfa_offset -(8 * 8 + 8 * 8 + 2 * 8)
+
+    // Reserve space for a SaveRefsAndArgs managed frame, either for the actual runtime
+    // method or for a GenericJNI frame which is similar but has a native method and a tag.
+    INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS
+
+    // Calculate the base address of the managed frame.
+    add   x13, sp, x14
+
+    // Prepare the return address for managed stack walk of the SaveRefsAndArgs frame.
+    // If we're coming from JNI stub with tail call, it is LR. If we're coming from
+    // JNI stub that saved the return address, it will be the last value we copy below.
+    // If we're coming directly from compiled code, it is LR, set further down.
+    mov   xIP1, lr
+
+    // Move the stack args if any.
+    cbz   x14, .Lcritical_skip_copy_args
+    mov   x12, sp
+.Lcritical_copy_args_loop:
+    ldp   xIP0, xIP1, [x12, #FRAME_SIZE_SAVE_REFS_AND_ARGS]
+    subs  x14, x14, #16
+    stp   xIP0, xIP1, [x12], #16
+    bne   .Lcritical_copy_args_loop
+.Lcritical_skip_copy_args:
+
+    // Spill registers for the SaveRefsAndArgs frame above the stack args.
+    // Note that the runtime shall not examine the args here, otherwise we would have to
+    // move them in registers and stack to account for the difference between managed and
+    // native ABIs. Do not update CFI while we hold the frame address in x13 and the values
+    // in registers are unchanged.
+    stp   d0, d1, [x13, #16]
+    stp   d2, d3, [x13, #32]
+    stp   d4, d5, [x13, #48]
+    stp   d6, d7, [x13, #64]
+    stp   x1, x2, [x13, #80]
+    stp   x3, x4, [x13, #96]
+    stp   x5, x6, [x13, #112]
+    stp   x7, x20, [x13, #128]
+    stp   x21, x22, [x13, #144]
+    stp   x23, x24, [x13, #160]
+    stp   x25, x26, [x13, #176]
+    stp   x27, x28, [x13, #192]
+    stp   x29, xIP1, [x13, #208]  // xIP1: Save return address for tail call from JNI stub.
+    // (If there were any stack args, we're storing the value that's already there.
+    // For direct calls from compiled managed code, we shall overwrite this below.)
+
+    // Move the managed frame address to native callee-save register x29 and update CFI.
+    mov   x29, x13
+    // Skip args d0-d7, x1-x7
+    CFI_EXPRESSION_BREG 20, 29, 136
+    CFI_EXPRESSION_BREG 21, 29, 144
+    CFI_EXPRESSION_BREG 22, 29, 152
+    CFI_EXPRESSION_BREG 23, 29, 160
+    CFI_EXPRESSION_BREG 24, 29, 168
+    CFI_EXPRESSION_BREG 25, 29, 176
+    CFI_EXPRESSION_BREG 26, 29, 184
+    CFI_EXPRESSION_BREG 27, 29, 192
+    CFI_EXPRESSION_BREG 28, 29, 200
+    CFI_EXPRESSION_BREG 29, 29, 208
+    // The saved return PC for managed stack walk is not necessarily our LR.
+
+    // Save our return PC in the padding.
+    str   lr, [x29, #__SIZEOF_POINTER__]
+    CFI_EXPRESSION_BREG 30, 29, __SIZEOF_POINTER__
+
+    ldr   wIP0, [x15, #ART_METHOD_ACCESS_FLAGS_OFFSET]  // Load access flags.
+    add   x14, x29, #1            // Prepare managed SP tagged for a GenericJNI frame.
+    tbnz  wIP0, #ACCESS_FLAGS_METHOD_IS_NATIVE_BIT, .Lcritical_skip_prepare_runtime_method
+
+    // When coming from a compiled method, the return PC for managed stack walk is LR.
+    // (When coming from a compiled stub, the correct return PC is already stored above.)
+    str   lr, [x29, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)]
+
+    // Replace the target method with the SaveRefsAndArgs runtime method.
+    LOAD_RUNTIME_INSTANCE x15
+    ldr   x15, [x15, #RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET]
+
+    mov   x14, x29                // Prepare untagged managed SP for the runtime method.
+
+.Lcritical_skip_prepare_runtime_method:
+    // Store the method on the bottom of the managed frame.
+    str   x15, [x29]
+
+    // Place (maybe tagged) managed SP in Thread::Current()->top_quick_frame.
+    str   x14, [xSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]
+
+    // Preserve the native arg register x0 in callee-save register x28 which was saved above.
+    mov   x28, x0
 
     // Call artFindNativeMethodRunnable()
     mov   x0, xSELF   // pass Thread::Current()
     bl    artFindNativeMethodRunnable
 
     // Store result in scratch reg.
-    mov   xIP0, x0
+    mov   x13, x0
 
-    // Restore frame.
+    // Restore the native arg register x0.
+    mov   x0, x28
+
+    // Restore our return PC.
+    RESTORE_REG_BASE x29, lr, __SIZEOF_POINTER__
+
+    // Remember the stack args size, negated because SP cannot be on the right-hand side in SUB.
+    sub   x14, sp, x29
+
+    // Restore the frame. We shall not need the method anymore.
+    ldp   d0, d1, [x29, #16]
+    ldp   d2, d3, [x29, #32]
+    ldp   d4, d5, [x29, #48]
+    ldp   d6, d7, [x29, #64]
+    ldp   x1, x2, [x29, #80]
+    ldp   x3, x4, [x29, #96]
+    ldp   x5, x6, [x29, #112]
+    ldp   x7, x20, [x29, #128]
+    .cfi_restore x20
+    RESTORE_TWO_REGS_BASE x29, x21, x22, 144
+    RESTORE_TWO_REGS_BASE x29, x23, x24, 160
+    RESTORE_TWO_REGS_BASE x29, x25, x26, 176
+    RESTORE_TWO_REGS_BASE x29, x27, x28, 192
+    RESTORE_REG_BASE x29, x29, 208
+
+    REFRESH_MARKING_REGISTER
+
+    // Check for exception before moving args back to keep the return PC for managed stack walk.
+    cbz   x13, .Lcritical_deliver_exception
+
     .cfi_remember_state
-    RESTORE_TWO_REGS x15, x0, 0
-    RESTORE_SAVE_REFS_AND_ARGS_FRAME
-    REFRESH_MARKING_REGISTER
-
-    // Check for exception.
-    cbz   xIP0, .Lcritical_deliver_exception
-
-    // Do the tail call
-    br    xIP0
-    .cfi_restore_state
-    .cfi_def_cfa_offset FRAME_SIZE_SAVE_REFS_AND_ARGS
-
-.Lcritical_has_stack_args:
-    // Move the out args size to a scratch register.
-    mov   xIP0, x0
-
-    // Restore register args as we're about to move stack args.
-    RESTORE_TWO_REGS x15, x0, 0
-    RESTORE_SAVE_REFS_AND_ARGS_FRAME_INTERNAL sp
-
-    // Move out args. For simplicity include the return address at the end.
-    mov   x8, sp        // Destination.
-    add   x9, sp, xIP0  // Destination end.
-1:
-    ldp   x10, x11, [x8, #FRAME_SIZE_SAVE_REFS_AND_ARGS]
-    stp   x10, x11, [x8], #16
-    cmp   x8, x9
-    bne   1b
-
-    // Save our LR, load caller's LR and redefine CFI to take ownership of the JNI stub frame.
-    str   xLR, [x9, #-__SIZEOF_POINTER__]
-    mov   xLR, x11  // The last moved value from the loop above.
-    .cfi_def_cfa x9, FRAME_SIZE_SAVE_REFS_AND_ARGS
-
-    // Re-create the SaveRefsAndArgs frame above the args.
-    SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL x9
-    SAVE_TWO_REGS_BASE x9, x15, x0, 0
-
-    // Move the frame register to a callee-save register.
-    mov   x29, x9
-    .cfi_def_cfa_register x29
-
-    // Place tagged managed sp in Thread::Current()->top_quick_frame.
-    orr   xIP0, x29, #1  // Tag as GenericJNI frame.
-    str   xIP0, [xSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]
-
-    // Call artFindNativeMethodRunnable()
-    mov   x0, xSELF   // pass Thread::Current()
-    bl    artFindNativeMethodRunnable
-
-    // Store result in scratch reg.
-    mov   xIP0, x0
-
-    // Restore the frame.
-    mov   x9, x29
-    .cfi_def_cfa_register x9
-    RESTORE_TWO_REGS_BASE x9, x15, x0, 0
-    RESTORE_SAVE_REFS_AND_ARGS_FRAME_INTERNAL x9
-    REFRESH_MARKING_REGISTER
-
-    // Check for exception.
-    cbz   xIP0, 3f
 
     // Move stack args to their original place.
-    mov   x8, x9
-2:
-    ldp   x10, x11, [x8, #-16]!
-    stp   x10, x11, [x8, #FRAME_SIZE_SAVE_REFS_AND_ARGS]
-    cmp   sp, x8
-    bne   2b
-
-    // Replace original return address with caller's return address.
-    ldr   xIP1, [x9, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)]
-    str   xLR, [x9, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)]
-
-    // Restore LR and redefine CFI to release ownership of the JNI stub frame.
-    .cfi_remember_state
-    mov   xLR, xIP1
-    .cfi_def_cfa sp, FRAME_SIZE_SAVE_REFS_AND_ARGS
+    cbz   x14, .Lcritical_skip_copy_args_back
+    sub   x12, sp, x14
+.Lcritical_copy_args_back_loop:
+    ldp   xIP0, xIP1, [x12, #-16]!
+    adds  x14, x14, #16
+    stp   xIP0, xIP1, [x12, #FRAME_SIZE_SAVE_REFS_AND_ARGS]
+    bne   .Lcritical_copy_args_back_loop
+.Lcritical_skip_copy_args_back:
 
     // Remove the frame reservation.
     DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS
 
     // Do the tail call.
-    br    xIP0
+    br    x13
     .cfi_restore_state
-    .cfi_def_cfa x9, FRAME_SIZE_SAVE_REFS_AND_ARGS
-
-3:
-    // Drop stack args and the SaveRefsAndArgs reservation.
-    mov   sp, x9
-    add   sp, sp, #FRAME_SIZE_SAVE_REFS_AND_ARGS
-    .cfi_def_cfa sp, 0
+    .cfi_def_cfa sp, FRAME_SIZE_SAVE_REFS_AND_ARGS
 
 .Lcritical_deliver_exception:
-    // When delivering exception, we check that xSELF was saved but the SaveRefsAndArgs frame does
-    // not save it, so we cannot use DELIVER_PENDING_EXCEPTION_FRAME_READY with the above frames.
-    DELIVER_PENDING_EXCEPTION
+    // The exception delivery checks that xSELF was saved but the SaveRefsAndArgs
+    // frame does not save it, so we cannot use the existing SaveRefsAndArgs frame.
+    // That's why we checked for exception after restoring registers from it.
+    // We need to build a SaveAllCalleeSaves frame instead. Args are irrelevant at this
+    // point but keep the area allocated for stack args to keep CFA definition simple.
+    DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS - FRAME_SIZE_SAVE_ALL_CALLEE_SAVES
+
+    // Calculate the base address of the managed frame.
+    sub   x13, sp, x14
+
+    // Spill registers for the SaveAllCalleeSaves frame above the stack args area. Do not update
+    // CFI while we hold the frame address in x13 and the values in registers are unchanged.
+    stp   d8, d9, [x13, #16]
+    stp   d10, d11, [x13, #32]
+    stp   d12, d13, [x13, #48]
+    stp   d14, d15, [x13, #64]
+    stp   x19, x20, [x13, #80]
+    stp   x21, x22, [x13, #96]
+    stp   x23, x24, [x13, #112]
+    stp   x25, x26, [x13, #128]
+    stp   x27, x28, [x13, #144]
+    str   x29, [x13, #160]
+    // Keep the caller PC for managed stack walk.
+
+    // Move the managed frame address to native callee-save register x29 and update CFI.
+    mov   x29, x13
+    CFI_EXPRESSION_BREG 19, 29, 80
+    CFI_EXPRESSION_BREG 20, 29, 88
+    CFI_EXPRESSION_BREG 21, 29, 96
+    CFI_EXPRESSION_BREG 22, 29, 104
+    CFI_EXPRESSION_BREG 23, 29, 112
+    CFI_EXPRESSION_BREG 24, 29, 120
+    CFI_EXPRESSION_BREG 25, 29, 128
+    CFI_EXPRESSION_BREG 26, 29, 136
+    CFI_EXPRESSION_BREG 27, 29, 144
+    CFI_EXPRESSION_BREG 28, 29, 152
+    CFI_EXPRESSION_BREG 29, 29, 160
+    // The saved return PC for managed stack walk is not necessarily our LR.
+
+    // Save our return PC in the padding.
+    str   lr, [x29, #__SIZEOF_POINTER__]
+    CFI_EXPRESSION_BREG 30, 29, __SIZEOF_POINTER__
+
+    // Store ArtMethod* Runtime::callee_save_methods_[kSaveAllCalleeSaves] to the managed frame.
+    LOAD_RUNTIME_INSTANCE xIP0
+    ldr xIP0, [xIP0, #RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET]
+    str xIP0, [x29]
+
+    // Place the managed frame SP in Thread::Current()->top_quick_frame.
+    str x29, [xSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]
+
+    DELIVER_PENDING_EXCEPTION_FRAME_READY
 END art_jni_dlsym_lookup_critical_stub
diff --git a/runtime/arch/arm64/jni_frame_arm64.h b/runtime/arch/arm64/jni_frame_arm64.h
index fa4d43c..17e7434 100644
--- a/runtime/arch/arm64/jni_frame_arm64.h
+++ b/runtime/arch/arm64/jni_frame_arm64.h
@@ -41,28 +41,34 @@
 // in registers. The rest of the args must go on the stack.
 constexpr size_t kMaxIntLikeRegisterArguments = 8u;
 
-// Get the size of "out args" for @CriticalNative method stub.
-// This must match the size of the frame emitted by the JNI compiler at the native call site.
-inline size_t GetCriticalNativeOutArgsSize(const char* shorty, uint32_t shorty_len) {
-  DCHECK_EQ(shorty_len, strlen(shorty));
-
-  size_t num_fp_args = 0u;
-  for (size_t i = 1; i != shorty_len; ++i) {
-    if (shorty[i] == 'F' || shorty[i] == 'D') {
-      num_fp_args += 1u;
-    }
-  }
-  size_t num_non_fp_args = shorty_len - 1u - num_fp_args;
-
+// Get the size of the arguments for a native call.
+inline size_t GetNativeOutArgsSize(size_t num_fp_args, size_t num_non_fp_args) {
   // Account for FP arguments passed through v0-v7.
   size_t num_stack_fp_args =
       num_fp_args - std::min(kMaxFloatOrDoubleRegisterArguments, num_fp_args);
   // Account for other (integer and pointer) arguments passed through GPR (x0-x7).
   size_t num_stack_non_fp_args =
       num_non_fp_args - std::min(kMaxIntLikeRegisterArguments, num_non_fp_args);
+  // Each stack argument takes 8 bytes.
+  return (num_stack_fp_args + num_stack_non_fp_args) * static_cast<size_t>(kArm64PointerSize);
+}
+
+// Get stack args size for @CriticalNative method calls.
+inline size_t GetCriticalNativeCallArgsSize(const char* shorty, uint32_t shorty_len) {
+  DCHECK_EQ(shorty_len, strlen(shorty));
+
+  size_t num_fp_args =
+      std::count_if(shorty + 1, shorty + shorty_len, [](char c) { return c == 'F' || c == 'D'; });
+  size_t num_non_fp_args = shorty_len - 1u - num_fp_args;
+
+  return GetNativeOutArgsSize(num_fp_args, num_non_fp_args);
+}
+
+// Get the frame size for @CriticalNative method stub.
+// This must match the size of the extra frame emitted by the compiler at the native call site.
+inline size_t GetCriticalNativeStubFrameSize(const char* shorty, uint32_t shorty_len) {
   // The size of outgoing arguments.
-  size_t size =
-      (num_stack_fp_args + num_stack_non_fp_args) * static_cast<size_t>(kArm64PointerSize);
+  size_t size = GetCriticalNativeCallArgsSize(shorty, shorty_len);
 
   // We can make a tail call if there are no stack args and we do not need
   // to extend the result. Otherwise, add space for return PC.
@@ -72,6 +78,16 @@
   return RoundUp(size, kAapcs64StackAlignment);
 }
 
+// Get the frame size for direct call to a @CriticalNative method.
+// This must match the size of the frame emitted by the JNI compiler at the native call site.
+inline size_t GetCriticalNativeDirectCallFrameSize(const char* shorty, uint32_t shorty_len) {
+  // The size of outgoing arguments.
+  size_t size = GetCriticalNativeCallArgsSize(shorty, shorty_len);
+
+  // No return PC to save, zero- and sign-extension are handled by the caller.
+  return RoundUp(size, kAapcs64StackAlignment);
+}
+
 }  // namespace arm64
 }  // namespace art
 
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 634c762..022a0e4 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -1503,6 +1503,8 @@
 .endm
 
 // The common code for art_quick_alloc_object_*region_tlab
+// Currently the implementation ignores isInitialized. TODO(b/172087402): clean this up.
+// Caller must execute a constructor fence after this.
 .macro GENERATE_ALLOC_OBJECT_RESOLVED_TLAB name, entrypoint, isInitialized
 ENTRY \name
     // Fast path region tlab allocation.
@@ -1570,6 +1572,7 @@
     ret
 .endm
 
+// Caller must execute a constructor fence after this.
 .macro GENERATE_ALLOC_ARRAY_TLAB name, entrypoint, size_setup
 ENTRY \name
     // Fast path array allocation for region tlab allocation.
@@ -1698,96 +1701,33 @@
     /*
      * Called to resolve an imt conflict.
      * x0 is the conflict ArtMethod.
-     * xIP1 is a hidden argument that holds the target interface method's dex method index.
+     * xIP1 is a hidden argument that holds the target interface method.
      *
-     * Note that this stub writes to xIP0, xIP1, x13-x15, and x0.
+     * Note that this stub writes to xIP0, xIP1, and x0.
      */
-    .extern artLookupResolvedMethod
 ENTRY art_quick_imt_conflict_trampoline
-    ldr xIP0, [sp, #0]  // Load referrer
-    // Load the declaring class (without read barrier) and access flags (for obsolete method check).
-    // The obsolete flag is set with suspended threads, so we do not need an acquire operation here.
-#if ART_METHOD_ACCESS_FLAGS_OFFSET != ART_METHOD_DECLARING_CLASS_OFFSET + 4
-#error "Expecting declaring class and access flags to be consecutive for LDP."
-#endif
-    ldp wIP0, w15, [xIP0, #ART_METHOD_DECLARING_CLASS_OFFSET]
-    // If the method is obsolete, just go through the dex cache miss slow path.
-    tbnz x15, #ACC_OBSOLETE_METHOD_SHIFT, .Limt_conflict_trampoline_dex_cache_miss
-    ldr wIP0, [xIP0, #MIRROR_CLASS_DEX_CACHE_OFFSET]  // Load the DexCache (without read barrier).
-    UNPOISON_HEAP_REF wIP0
-    ubfx x15, xIP1, #0, #METHOD_DEX_CACHE_HASH_BITS  // Calculate DexCache method slot index.
-    ldr xIP0, [xIP0, #MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET]  // Load the resolved methods.
-    add xIP0, xIP0, x15, lsl #(POINTER_SIZE_SHIFT + 1)  // Load DexCache method slot address.
-
-    // Relaxed atomic load x14:x15 from the dex cache slot.
-.Limt_conflict_trampoline_retry_load:
-    ldxp x14, x15, [xIP0]
-    stxp w13, x14, x15, [xIP0]
-    cbnz w13, .Limt_conflict_trampoline_retry_load
-
-    cmp x15, xIP1       // Compare method index to see if we had a DexCache method hit.
-    bne .Limt_conflict_trampoline_dex_cache_miss
-.Limt_conflict_trampoline_have_interface_method:
-    ldr xIP1, [x0, #ART_METHOD_JNI_OFFSET_64]  // Load ImtConflictTable
-    ldr x0, [xIP1]  // Load first entry in ImtConflictTable.
+    ldr xIP0, [x0, #ART_METHOD_JNI_OFFSET_64]  // Load ImtConflictTable
+    ldr x0, [xIP0]  // Load first entry in ImtConflictTable.
 .Limt_table_iterate:
-    cmp x0, x14
+    cmp x0, xIP1
     // Branch if found. Benchmarks have shown doing a branch here is better.
     beq .Limt_table_found
     // If the entry is null, the interface method is not in the ImtConflictTable.
     cbz x0, .Lconflict_trampoline
     // Iterate over the entries of the ImtConflictTable.
-    ldr x0, [xIP1, #(2 * __SIZEOF_POINTER__)]!
+    ldr x0, [xIP0, #(2 * __SIZEOF_POINTER__)]!
     b .Limt_table_iterate
 .Limt_table_found:
     // We successfully hit an entry in the table. Load the target method
     // and jump to it.
-    ldr x0, [xIP1, #__SIZEOF_POINTER__]
+    ldr x0, [xIP0, #__SIZEOF_POINTER__]
     ldr xIP0, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
     br xIP0
 .Lconflict_trampoline:
     // Call the runtime stub to populate the ImtConflictTable and jump to the
     // resolved method.
-    mov x0, x14  // Load interface method
+    mov x0, xIP1  // Load interface method
     INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
-.Limt_conflict_trampoline_dex_cache_miss:
-    // We're not creating a proper runtime method frame here,
-    // artLookupResolvedMethod() is not allowed to walk the stack.
-
-    // Save GPR args and return address, allocate space for FPR args, align stack.
-    SAVE_TWO_REGS_INCREASE_FRAME x0, x1, (8 * 8 + 8 * 8 + 8 + 8)
-    SAVE_TWO_REGS x2, x3, 16
-    SAVE_TWO_REGS x4, x5, 32
-    SAVE_TWO_REGS x6, x7, 48
-    SAVE_REG      xLR, (8 * 8 + 8 * 8 + 8)
-
-    // Save FPR args.
-    stp d0, d1, [sp, #64]
-    stp d2, d3, [sp, #80]
-    stp d4, d5, [sp, #96]
-    stp d6, d7, [sp, #112]
-
-    mov x0, xIP1                            // Pass method index.
-    ldr x1, [sp, #(8 * 8 + 8 * 8 + 8 + 8)]  // Pass referrer.
-    bl artLookupResolvedMethod              // (uint32_t method_index, ArtMethod* referrer)
-    mov x14, x0   // Move the interface method to x14 where the loop above expects it.
-
-    // Restore FPR args.
-    ldp d0, d1, [sp, #64]
-    ldp d2, d3, [sp, #80]
-    ldp d4, d5, [sp, #96]
-    ldp d6, d7, [sp, #112]
-
-    // Restore GPR args and return address.
-    RESTORE_REG      xLR, (8 * 8 + 8 * 8 + 8)
-    RESTORE_TWO_REGS x2, x3, 16
-    RESTORE_TWO_REGS x4, x5, 32
-    RESTORE_TWO_REGS x6, x7, 48
-    RESTORE_TWO_REGS_DECREASE_FRAME x0, x1, (8 * 8 + 8 * 8 + 8 + 8)
-
-    // If the method wasn't resolved, skip the lookup and go to artInvokeInterfaceTrampoline().
-    cbz x14, .Lconflict_trampoline
-    b .Limt_conflict_trampoline_have_interface_method
 END art_quick_imt_conflict_trampoline
 
 ENTRY art_quick_resolution_trampoline
@@ -1934,6 +1874,7 @@
 
     // Tear down the alloca.
     mov sp, x28
+    .cfi_remember_state
     .cfi_def_cfa_register sp
 
     // Tear down the callee-save frame.
@@ -1944,14 +1885,20 @@
     fmov d0, x0
     ret
 
+    // Undo the unwinding information from above since it doesn't apply below.
+    .cfi_restore_state
+    .cfi_def_cfa x28, FRAME_SIZE_SAVE_REFS_AND_ARGS
 .Lexception_in_native:
     // Move to x1 then sp to please assembler.
     ldr x1, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
     add sp, x1, #-1  // Remove the GenericJNI tag.
-    .cfi_def_cfa_register sp
+    bl art_deliver_pending_exception
+END art_quick_generic_jni_trampoline
+
+ENTRY art_deliver_pending_exception
     # This will create a new save-all frame, required by the runtime.
     DELIVER_PENDING_EXCEPTION
-END art_quick_generic_jni_trampoline
+END art_deliver_pending_exception
 
 /*
  * Called to bridge from the quick to interpreter ABI. On entry the arguments match those
diff --git a/runtime/arch/instruction_set_features.cc b/runtime/arch/instruction_set_features.cc
index 2581f6e..ec1e340 100644
--- a/runtime/arch/instruction_set_features.cc
+++ b/runtime/arch/instruction_set_features.cc
@@ -166,6 +166,25 @@
   UNREACHABLE();
 }
 
+std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCpuFeatures() {
+  switch (kRuntimeISA) {
+    case InstructionSet::kArm:
+    case InstructionSet::kThumb2:
+      return ArmInstructionSetFeatures::FromCpuFeatures();
+    case InstructionSet::kArm64:
+      return Arm64InstructionSetFeatures::FromCpuFeatures();
+    case InstructionSet::kX86:
+      return X86InstructionSetFeatures::FromCpuFeatures();
+    case InstructionSet::kX86_64:
+      return X86_64InstructionSetFeatures::FromCpuFeatures();
+
+    default:
+      break;
+  }
+  UNIMPLEMENTED(FATAL) << kRuntimeISA;
+  UNREACHABLE();
+}
+
 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::AddFeaturesFromString(
     const std::string& feature_list, /* out */ std::string* error_msg) const {
   std::vector<std::string> features;
diff --git a/runtime/arch/instruction_set_features.h b/runtime/arch/instruction_set_features.h
index 78ce580..b80d36f 100644
--- a/runtime/arch/instruction_set_features.h
+++ b/runtime/arch/instruction_set_features.h
@@ -71,6 +71,9 @@
   // InstructionSetFeatures. This works around kernel bugs in AT_HWCAP and /proc/cpuinfo.
   static std::unique_ptr<const InstructionSetFeatures> FromAssembly();
 
+  // Use external cpu_features library.
+  static std::unique_ptr<const InstructionSetFeatures> FromCpuFeatures();
+
   // Parse a string of the form "div,-atomic_ldrd_strd" adding and removing these features to
   // create a new InstructionSetFeatures.
   std::unique_ptr<const InstructionSetFeatures> AddFeaturesFromString(
diff --git a/runtime/arch/instruction_set_features_test.cc b/runtime/arch/instruction_set_features_test.cc
index d9b2e3f..82b8242 100644
--- a/runtime/arch/instruction_set_features_test.cc
+++ b/runtime/arch/instruction_set_features_test.cc
@@ -16,6 +16,7 @@
 
 #include <array>
 
+#include "common_runtime_test.h"
 #include "instruction_set_features.h"
 
 #include <gtest/gtest.h>
@@ -39,6 +40,12 @@
 #else
 TEST(InstructionSetFeaturesTest, FeaturesFromSystemPropertyVariant) {
 #endif
+  if (kIsTargetBuild) {
+    // atest differs in build-time and run-time features.
+    TEST_DISABLED_FOR_X86();
+    TEST_DISABLED_FOR_X86_64();
+  }
+
   // Take the default set of instruction features from the build.
   std::unique_ptr<const InstructionSetFeatures> instruction_set_features(
       InstructionSetFeatures::FromCppDefines());
@@ -66,6 +73,12 @@
 #else
 TEST(InstructionSetFeaturesTest, FeaturesFromSystemPropertyString) {
 #endif
+  if (kIsTargetBuild) {
+    // atest differs in build-time and run-time features.
+    TEST_DISABLED_FOR_X86();
+    TEST_DISABLED_FOR_X86_64();
+  }
+
   // Take the default set of instruction features from the build.
   std::unique_ptr<const InstructionSetFeatures> instruction_set_features(
       InstructionSetFeatures::FromCppDefines());
@@ -163,6 +176,20 @@
       << "\nFeatures from build: " << *instruction_set_features.get();
 }
 
+TEST(InstructionSetFeaturesTest, FeaturestFromCpuFeatures) {
+  // Take the default set of instruction features from the build.
+  std::unique_ptr<const InstructionSetFeatures> instruction_set_features(
+      InstructionSetFeatures::FromCppDefines());
+
+  // Check we get the same instruction set features using the cpu_features library
+  std::unique_ptr<const InstructionSetFeatures> library_features(
+      InstructionSetFeatures::FromCpuFeatures());
+
+  EXPECT_TRUE(library_features->HasAtLeast(instruction_set_features.get()))
+      << "Library features: " << *library_features.get()
+      << "\nFeatures from build: " << *instruction_set_features.get();
+}
+
 TEST(InstructionSetFeaturesTest, FeaturesFromRuntimeDetection) {
   if (!InstructionSetFeatures::IsRuntimeDetectionSupported()) {
     EXPECT_EQ(InstructionSetFeatures::FromRuntimeDetection(), nullptr);
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 2b47cef..772681d 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -21,7 +21,7 @@
 #include "base/callee_save_type.h"
 #include "base/enums.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_runtime_test.h"
 #include "entrypoints/quick/quick_entrypoints_enum.h"
 #include "imt_conflict_table.h"
diff --git a/runtime/arch/x86/__x86.get_pc_thunk.S b/runtime/arch/x86/__x86.get_pc_thunk.S
new file mode 100644
index 0000000..9dda2bf
--- /dev/null
+++ b/runtime/arch/x86/__x86.get_pc_thunk.S
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+// Typically GCC outputs functions like these into any object file that needs a PIC base register,
+// and one of the copies for each register is used. Clang doesn't use these functions, but
+// SETUP_GOT_NOSAVE in asm_support_x86.S calls this one.
+
+    .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+    .globl __x86.get_pc_thunk.bx
+    .hidden __x86.get_pc_thunk.bx
+    .p2align 4
+    .type __x86.get_pc_thunk.bx,@function
+__x86.get_pc_thunk.bx:
+    .cfi_startproc
+    movl (%esp), %ebx
+    ret
+    .cfi_endproc
diff --git a/runtime/arch/x86/asm_support_x86.S b/runtime/arch/x86/asm_support_x86.S
index 8938d8b..370eea1 100644
--- a/runtime/arch/x86/asm_support_x86.S
+++ b/runtime/arch/x86/asm_support_x86.S
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
 
 #include "asm_support_x86.h"
+#include "interpreter/cfi_asm_support.h"
 
 // Regular gas(1) & current clang/llvm assembler support named macro parameters.
 #define MACRO0(macro_name) .macro macro_name
@@ -77,6 +78,7 @@
     #define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
     #define CFI_RESTORE(reg) .cfi_restore reg
     #define CFI_REL_OFFSET(reg,size) .cfi_rel_offset reg,size
+    #define CFI_REGISTER(orig_reg, current_reg) .cfi_register orig_reg, current_reg
     #define CFI_REMEMBER_STATE .cfi_remember_state
     // The spec is not clear whether the CFA is part of the saved state and tools
     // differ in the behaviour, so explicitly set the CFA to avoid any ambiguity.
@@ -93,11 +95,34 @@
     #define CFI_DEF_CFA_REGISTER(reg)
     #define CFI_RESTORE(reg)
     #define CFI_REL_OFFSET(reg,size)
+    #define CFI_REGISTER(orig_reg, current_reg)
     #define CFI_REMEMBER_STATE
     #define CFI_RESTORE_STATE_AND_DEF_CFA(reg,off)
     #define CFI_ESCAPE(...)
 #endif
 
+#define CFI_REG_eax 0
+#define CFI_REG_ecx 1
+#define CFI_REG_edx 2
+#define CFI_REG_ebx 3
+#define CFI_REG_esp 4
+#define CFI_REG_ebp 5
+#define CFI_REG_esi 6
+#define CFI_REG_edi 7
+#define CFI_REG_eip 8
+
+#define CFI_REG(reg) CFI_REG_##reg
+
+MACRO3(CFI_EXPRESSION_BREG, n, b, offset)
+    .if (-0x40 <= (\offset)) && ((\offset) < 0x40)
+        CFI_EXPRESSION_BREG_1(\n, \b, \offset)
+    .elseif (-0x2000 <= (\offset)) && ((\offset) < 0x2000)
+        CFI_EXPRESSION_BREG_2(\n, \b, \offset)
+    .else
+        .error "Unsupported offset"
+    .endif
+END_MACRO
+
     // Symbols. On a Mac, we need a leading underscore.
 #if !defined(__APPLE__)
     #define SYMBOL(name) name
@@ -131,7 +156,7 @@
     ALIGN_FUNCTION_ENTRY
 CALLVAR(c_name):
     CFI_STARTPROC
-    // Ensure we get a sane starting CFA.
+    // Ensure we get an appropriate starting CFA.
     CFI_DEF_CFA(esp, RAW_VAR(cfa_offset))
 END_MACRO
 
@@ -172,6 +197,16 @@
     CFI_RESTORE(REG_VAR(reg))
 END_MACRO
 
+MACRO1(INCREASE_FRAME, frame_adjustment)
+    subl MACRO_LITERAL(RAW_VAR(frame_adjustment)), %esp
+    CFI_ADJUST_CFA_OFFSET((RAW_VAR(frame_adjustment)))
+END_MACRO
+
+MACRO1(DECREASE_FRAME, frame_adjustment)
+    addl MACRO_LITERAL(RAW_VAR(frame_adjustment)), %esp
+    CFI_ADJUST_CFA_OFFSET(-(RAW_VAR(frame_adjustment)))
+END_MACRO
+
 #define UNREACHABLE int3
 
 MACRO1(UNIMPLEMENTED,name)
@@ -197,6 +232,13 @@
 #endif
 END_MACRO
 
+MACRO2(LOAD_RUNTIME_INSTANCE, reg, got_reg)
+    SETUP_GOT_NOSAVE \got_reg
+    // Load Runtime::instance_ from GOT.
+    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(reg)
+    movl (REG_VAR(reg)), REG_VAR(reg)
+END_MACRO
+
 // Macros to poison (negate) the reference for heap poisoning.
 MACRO1(POISON_HEAP_REF, rRef)
 #ifdef USE_HEAP_POISONING
@@ -223,8 +265,7 @@
     PUSH_ARG edx
     PUSH_ARG ecx
     // Create space for FPR args.
-    subl MACRO_LITERAL(4 * 8), %esp
-    CFI_ADJUST_CFA_OFFSET(4 * 8)
+    INCREASE_FRAME 4 * 8
     // Save FPRs.
     movsd %xmm0, 0(%esp)
     movsd %xmm1, 8(%esp)
@@ -246,8 +287,7 @@
     movsd 20(%esp), %xmm2
     movsd 28(%esp), %xmm3
 
-    addl MACRO_LITERAL(36), %esp  // Remove FPRs and method pointer.
-    CFI_ADJUST_CFA_OFFSET(-36)
+    DECREASE_FRAME 36             // Remove FPRs and method pointer.
 
     POP_ARG ecx                   // Restore args
     POP_ARG edx
@@ -263,12 +303,12 @@
      */
 MACRO0(DELIVER_PENDING_EXCEPTION_FRAME_READY)
     // Outgoing argument set up
-    subl MACRO_LITERAL(12), %esp               // alignment padding
-    CFI_ADJUST_CFA_OFFSET(12)
+    INCREASE_FRAME 12                          // alignment padding
     pushl %fs:THREAD_SELF_OFFSET               // pass Thread::Current()
     CFI_ADJUST_CFA_OFFSET(4)
     call SYMBOL(artDeliverPendingExceptionFromCode)  // artDeliverPendingExceptionFromCode(Thread*)
     UNREACHABLE
+    CFI_ADJUST_CFA_OFFSET(-16)                 // Reset CFA in case there is more code afterwards.
 END_MACRO
 
 #endif  // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
diff --git a/runtime/arch/x86/instruction_set_features_x86.cc b/runtime/arch/x86/instruction_set_features_x86.cc
index 0c3d26e..d2dbe1d 100644
--- a/runtime/arch/x86/instruction_set_features_x86.cc
+++ b/runtime/arch/x86/instruction_set_features_x86.cc
@@ -25,6 +25,14 @@
 
 #include "arch/x86_64/instruction_set_features_x86_64.h"
 
+#include <cpu_features_macros.h>
+
+#ifdef CPU_FEATURES_ARCH_X86
+// This header can only be included on x86 targets,
+// as determined by cpu_features own define.
+#include <cpuinfo_x86.h>
+#endif
+
 namespace art {
 
 using android::base::StringPrintf;
@@ -97,6 +105,12 @@
 X86FeaturesUniquePtr X86InstructionSetFeatures::FromVariant(
     const std::string& variant, std::string* error_msg ATTRIBUTE_UNUSED,
     bool x86_64) {
+  const bool is_runtime_isa =
+      kRuntimeISA == (x86_64 ? InstructionSet::kX86_64 : InstructionSet::kX86);
+  if (is_runtime_isa && variant == "default") {
+    return FromCppDefines(x86_64);
+  }
+
   bool has_SSSE3 = FindVariantInArray(x86_variants_with_ssse3, arraysize(x86_variants_with_ssse3),
                                       variant);
   bool has_SSE4_1 = FindVariantInArray(x86_variants_with_sse4_1,
@@ -232,6 +246,24 @@
   return FromCppDefines(x86_64);
 }
 
+
+X86FeaturesUniquePtr X86InstructionSetFeatures::FromCpuFeatures(bool x86_64) {
+#ifdef CPU_FEATURES_ARCH_X86
+  cpu_features::X86Features features = cpu_features::GetX86Info().features;
+  return Create(x86_64,
+    features.ssse3,
+    features.sse4_1,
+    features.sse4_2,
+    features.avx,
+    features.avx2,
+    features.popcnt);
+#else
+  UNIMPLEMENTED(WARNING);
+  return FromCppDefines(x86_64);
+#endif
+}
+
+
 bool X86InstructionSetFeatures::Equals(const InstructionSetFeatures* other) const {
   if (GetInstructionSet() != other->GetInstructionSet()) {
     return false;
diff --git a/runtime/arch/x86/instruction_set_features_x86.h b/runtime/arch/x86/instruction_set_features_x86.h
index bf1b606..1a8ebb5 100644
--- a/runtime/arch/x86/instruction_set_features_x86.h
+++ b/runtime/arch/x86/instruction_set_features_x86.h
@@ -69,6 +69,9 @@
   // InstructionSetFeatures. This works around kernel bugs in AT_HWCAP and /proc/cpuinfo.
   static X86FeaturesUniquePtr FromAssembly(bool x86_64 = false);
 
+  // Use external cpu_features library.
+  static X86FeaturesUniquePtr FromCpuFeatures(bool x86_64 = false);
+
   bool Equals(const InstructionSetFeatures* other) const override;
 
   bool HasAtLeast(const InstructionSetFeatures* other) const override;
diff --git a/runtime/arch/x86/instruction_set_features_x86_test.cc b/runtime/arch/x86/instruction_set_features_x86_test.cc
index cdf15af..ce8e9f4 100644
--- a/runtime/arch/x86/instruction_set_features_x86_test.cc
+++ b/runtime/arch/x86/instruction_set_features_x86_test.cc
@@ -21,15 +21,18 @@
 namespace art {
 
 TEST(X86InstructionSetFeaturesTest, X86FeaturesFromDefaultVariant) {
+  const bool is_runtime_isa = kRuntimeISA == InstructionSet::kX86;
   std::string error_msg;
   std::unique_ptr<const InstructionSetFeatures> x86_features(
       InstructionSetFeatures::FromVariant(InstructionSet::kX86, "default", &error_msg));
   ASSERT_TRUE(x86_features.get() != nullptr) << error_msg;
   EXPECT_EQ(x86_features->GetInstructionSet(), InstructionSet::kX86);
   EXPECT_TRUE(x86_features->Equals(x86_features.get()));
-  EXPECT_STREQ("-ssse3,-sse4.1,-sse4.2,-avx,-avx2,-popcnt",
-               x86_features->GetFeatureString().c_str());
-  EXPECT_EQ(x86_features->AsBitmap(), 0U);
+  EXPECT_EQ(x86_features->GetFeatureString(),
+            is_runtime_isa ? X86InstructionSetFeatures::FromCppDefines()->GetFeatureString()
+                    : "-ssse3,-sse4.1,-sse4.2,-avx,-avx2,-popcnt");
+  EXPECT_EQ(x86_features->AsBitmap(),
+            is_runtime_isa ? X86InstructionSetFeatures::FromCppDefines()->AsBitmap() : 0);
 }
 
 TEST(X86InstructionSetFeaturesTest, X86FeaturesFromAtomVariant) {
@@ -44,16 +47,6 @@
                x86_features->GetFeatureString().c_str());
   EXPECT_EQ(x86_features->AsBitmap(), 1U);
 
-  // Build features for a 32-bit x86 default processor.
-  std::unique_ptr<const InstructionSetFeatures> x86_default_features(
-      InstructionSetFeatures::FromVariant(InstructionSet::kX86, "default", &error_msg));
-  ASSERT_TRUE(x86_default_features.get() != nullptr) << error_msg;
-  EXPECT_EQ(x86_default_features->GetInstructionSet(), InstructionSet::kX86);
-  EXPECT_TRUE(x86_default_features->Equals(x86_default_features.get()));
-  EXPECT_STREQ("-ssse3,-sse4.1,-sse4.2,-avx,-avx2,-popcnt",
-               x86_default_features->GetFeatureString().c_str());
-  EXPECT_EQ(x86_default_features->AsBitmap(), 0U);
-
   // Build features for a 64-bit x86-64 atom processor.
   std::unique_ptr<const InstructionSetFeatures> x86_64_features(
       InstructionSetFeatures::FromVariant(InstructionSet::kX86_64, "atom", &error_msg));
@@ -65,8 +58,6 @@
   EXPECT_EQ(x86_64_features->AsBitmap(), 1U);
 
   EXPECT_FALSE(x86_64_features->Equals(x86_features.get()));
-  EXPECT_FALSE(x86_64_features->Equals(x86_default_features.get()));
-  EXPECT_FALSE(x86_features->Equals(x86_default_features.get()));
 }
 
 TEST(X86InstructionSetFeaturesTest, X86FeaturesFromSandybridgeVariant) {
@@ -81,16 +72,6 @@
                x86_features->GetFeatureString().c_str());
   EXPECT_EQ(x86_features->AsBitmap(), 39U);
 
-  // Build features for a 32-bit x86 default processor.
-  std::unique_ptr<const InstructionSetFeatures> x86_default_features(
-      InstructionSetFeatures::FromVariant(InstructionSet::kX86, "default", &error_msg));
-  ASSERT_TRUE(x86_default_features.get() != nullptr) << error_msg;
-  EXPECT_EQ(x86_default_features->GetInstructionSet(), InstructionSet::kX86);
-  EXPECT_TRUE(x86_default_features->Equals(x86_default_features.get()));
-  EXPECT_STREQ("-ssse3,-sse4.1,-sse4.2,-avx,-avx2,-popcnt",
-               x86_default_features->GetFeatureString().c_str());
-  EXPECT_EQ(x86_default_features->AsBitmap(), 0U);
-
   // Build features for a 64-bit x86-64 sandybridge processor.
   std::unique_ptr<const InstructionSetFeatures> x86_64_features(
       InstructionSetFeatures::FromVariant(InstructionSet::kX86_64, "sandybridge", &error_msg));
@@ -102,8 +83,6 @@
   EXPECT_EQ(x86_64_features->AsBitmap(), 39U);
 
   EXPECT_FALSE(x86_64_features->Equals(x86_features.get()));
-  EXPECT_FALSE(x86_64_features->Equals(x86_default_features.get()));
-  EXPECT_FALSE(x86_features->Equals(x86_default_features.get()));
 }
 
 TEST(X86InstructionSetFeaturesTest, X86FeaturesFromSilvermontVariant) {
@@ -118,16 +97,6 @@
                x86_features->GetFeatureString().c_str());
   EXPECT_EQ(x86_features->AsBitmap(), 39U);
 
-  // Build features for a 32-bit x86 default processor.
-  std::unique_ptr<const InstructionSetFeatures> x86_default_features(
-      InstructionSetFeatures::FromVariant(InstructionSet::kX86, "default", &error_msg));
-  ASSERT_TRUE(x86_default_features.get() != nullptr) << error_msg;
-  EXPECT_EQ(x86_default_features->GetInstructionSet(), InstructionSet::kX86);
-  EXPECT_TRUE(x86_default_features->Equals(x86_default_features.get()));
-  EXPECT_STREQ("-ssse3,-sse4.1,-sse4.2,-avx,-avx2,-popcnt",
-               x86_default_features->GetFeatureString().c_str());
-  EXPECT_EQ(x86_default_features->AsBitmap(), 0U);
-
   // Build features for a 64-bit x86-64 silvermont processor.
   std::unique_ptr<const InstructionSetFeatures> x86_64_features(
       InstructionSetFeatures::FromVariant(InstructionSet::kX86_64, "silvermont", &error_msg));
@@ -139,8 +108,6 @@
   EXPECT_EQ(x86_64_features->AsBitmap(), 39U);
 
   EXPECT_FALSE(x86_64_features->Equals(x86_features.get()));
-  EXPECT_FALSE(x86_64_features->Equals(x86_default_features.get()));
-  EXPECT_FALSE(x86_features->Equals(x86_default_features.get()));
 }
 
 TEST(X86InstructionSetFeaturesTest, X86FeaturesFromKabylakeVariant) {
@@ -155,16 +122,6 @@
                x86_features->GetFeatureString().c_str());
   EXPECT_EQ(x86_features->AsBitmap(), 63U);
 
-  // Build features for a 32-bit x86 default processor.
-  std::unique_ptr<const InstructionSetFeatures> x86_default_features(
-      InstructionSetFeatures::FromVariant(InstructionSet::kX86, "default", &error_msg));
-  ASSERT_TRUE(x86_default_features.get() != nullptr) << error_msg;
-  EXPECT_EQ(x86_default_features->GetInstructionSet(), InstructionSet::kX86);
-  EXPECT_TRUE(x86_default_features->Equals(x86_default_features.get()));
-  EXPECT_STREQ("-ssse3,-sse4.1,-sse4.2,-avx,-avx2,-popcnt",
-               x86_default_features->GetFeatureString().c_str());
-  EXPECT_EQ(x86_default_features->AsBitmap(), 0U);
-
   // Build features for a 64-bit x86-64 kabylake processor.
   std::unique_ptr<const InstructionSetFeatures> x86_64_features(
       InstructionSetFeatures::FromVariant(InstructionSet::kX86_64, "kabylake", &error_msg));
@@ -176,7 +133,5 @@
   EXPECT_EQ(x86_64_features->AsBitmap(), 63U);
 
   EXPECT_FALSE(x86_64_features->Equals(x86_features.get()));
-  EXPECT_FALSE(x86_64_features->Equals(x86_default_features.get()));
-  EXPECT_FALSE(x86_features->Equals(x86_default_features.get()));
-  }
+}
 }  // namespace art
diff --git a/runtime/arch/x86/jni_entrypoints_x86.S b/runtime/arch/x86/jni_entrypoints_x86.S
index 086e96f..a1a371c 100644
--- a/runtime/arch/x86/jni_entrypoints_x86.S
+++ b/runtime/arch/x86/jni_entrypoints_x86.S
@@ -20,9 +20,8 @@
      * Jni dlsym lookup stub.
      */
 DEFINE_FUNCTION art_jni_dlsym_lookup_stub
-    subl LITERAL(8), %esp         // align stack
-    CFI_ADJUST_CFA_OFFSET(8)
-    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    INCREASE_FRAME 8              // Align stack.
+    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
     CFI_ADJUST_CFA_OFFSET(4)
     // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable()
     // for @FastNative or @CriticalNative.
@@ -32,17 +31,16 @@
     movl (%eax), %eax                                // ArtMethod* method
     testl LITERAL(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE), \
           ART_METHOD_ACCESS_FLAGS_OFFSET(%eax)
-    jne .Llookup_stub_fast_native
+    jne .Llookup_stub_fast_or_critical_native
     call SYMBOL(artFindNativeMethod)  // (Thread*)
     jmp .Llookup_stub_continue
-.Llookup_stub_fast_native:
+.Llookup_stub_fast_or_critical_native:
     call SYMBOL(artFindNativeMethodRunnable)  // (Thread*)
 .Llookup_stub_continue:
-    addl LITERAL(12), %esp        // remove argument & padding
-    CFI_ADJUST_CFA_OFFSET(-12)
-    testl %eax, %eax              // check if returned method code is null
-    jz .Lno_native_code_found     // if null, jump to return to handle
-    jmp *%eax                     // otherwise, tail call to intended method
+    DECREASE_FRAME 12             // Remove argument & padding.
+    testl %eax, %eax              // Check if returned method code is null.
+    jz .Lno_native_code_found     // If null, jump to return to handle.
+    jmp *%eax                     // Otherwise, tail call to intended method.
 .Lno_native_code_found:
     ret
 END_FUNCTION art_jni_dlsym_lookup_stub
@@ -53,31 +51,94 @@
     testl LITERAL(1), %eax
     jnz art_jni_dlsym_lookup_stub
 
-    // We need to create a GenericJNI managed frame above the stack args.
+    // Since the native call args are all on the stack, we can use the managed args
+    // registers as scratch registers. So, EBX, EDX and ECX are available.
 
-    // GenericJNI frame is similar to SaveRegsAndArgs frame with the native method
-    // instead of runtime method saved at the bottom. Note that the runtime shall
-    // not examine the args here, otherwise we would have to reload them from stack
-    // to account for the difference between managed and native ABIs.
-    SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
-    pushl %eax  // Save the hidden arg as method pointer at the bottom of the stack.
-    CFI_ADJUST_CFA_OFFSET(4)
+    // Load caller PC.
+    movl (%esp), %ecx
 
-    // Call artCriticalNativeOutArgsSize(method); method is conveniently at the bottom of the stack.
-    call SYMBOL(artCriticalNativeOutArgsSize)
+    // Save the caller method from the hidden arg.
+    PUSH_ARG eax
 
-    // Check if we have any stack args other than return PC.
-    cmp LITERAL(__SIZEOF_POINTER__), %eax
-    jnz .Lcritical_has_stack_args
+    // Call artCriticalNativeFrameSize(method, caller_pc).
+    PUSH_ARG ecx                  // Pass caller PC.
+    PUSH_ARG eax                  // Pass method.
+    call SYMBOL(artCriticalNativeFrameSize)  // (method, caller_pc)
+    DECREASE_FRAME 8              // Remove args.
 
-    // Without stack args, the frame is fully constructed.
-    // Place tagged managed sp in Thread::Current()->top_quick_frame.
-    leal 1(%esp), %eax  // Tag as GenericJNI frame.
-    mov %eax, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
+    // Restore method register to EBX.
+    POP_ARG ebx
+
+    // Load caller PC to EDX and redefine return PC for CFI.
+    movl (%esp), %edx
+    CFI_REGISTER(%eip, %edx)
+
+    // Reserve space for a SaveRefsAndArgs managed frame, either for the actual runtime
+    // method or for a GenericJNI frame which is similar but has a native method and a tag.
+    INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__
+
+    // Calculate the number of DWORDs to move.
+    movl %eax, %ecx
+    shrl LITERAL(2), %ecx
+    jecxz .Lcritical_skip_copy_args
+
+    // Save EDI, ESI so that we can use them for moving stack args.
+    PUSH edi
+    PUSH esi
+
+    // Move the stack args.
+    leal 2 * __SIZEOF_POINTER__(%esp), %edi
+    leal FRAME_SIZE_SAVE_REFS_AND_ARGS(%edi), %esi
+    rep movsd
+
+    // Restore EDI, ESI.
+    POP esi
+    POP edi
+
+.Lcritical_skip_copy_args:
+    // Calculate the base address of the managed frame.
+    leal (%esp, %eax, 1), %eax
+
+    leal 1(%eax), %ecx            // Prepare namaged SP tagged for a GenericJNI frame.
+    testl LITERAL(ACCESS_FLAGS_METHOD_IS_NATIVE), ART_METHOD_ACCESS_FLAGS_OFFSET(%ebx)
+    jnz .Lcritical_skip_prepare_runtime_method
+
+    // Save the return PC for managed stack walk.
+    // (When coming from a compiled stub, the correct return PC is already there.)
+    movl %edx, FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__(%eax)
+
+    // Replace the target method with the SaveRefsAndArgs runtime method.
+    LOAD_RUNTIME_INSTANCE ecx, ebx
+    movl RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET(%ecx), %ebx
+
+    movl %eax, %ecx               // Prepare untagged managed SP for the runtime method.
+
+.Lcritical_skip_prepare_runtime_method:
+    // Store the method on the bottom of the managed frame.
+    movl %ebx, (%eax)
+
+    // Move the managed frame address to native callee-save register EBX.
+    movl %eax, %ebx
+
+    // Spill registers for the SaveRefsAndArgs frame above the stack args.
+    movl %edi, 56(%ebx)
+    CFI_EXPRESSION_BREG CFI_REG(edi), CFI_REG(ebx), 56
+    movl %esi, 52(%ebx)
+    CFI_EXPRESSION_BREG CFI_REG(esi), CFI_REG(ebx), 52
+    movl %ebp, 48(%ebx)
+    CFI_EXPRESSION_BREG CFI_REG(ebp), CFI_REG(ebx), 48
+    // Skip managed ABI args EBX, EDX, ECX and FPRs. The runtime shall not examine the
+    // args in the managed frame. (We have already clobbered EBX, EDX, ECX anyway.)
+
+    // Place (maybe tagged) managed SP in Thread::Current()->top_quick_frame.
+    movl %ecx, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
+
+    // Save our return PC in a slot reserved for first FP arg in managed ABI.
+    movl %edx, __SIZEOF_POINTER__(%ebx)
+    CFI_EXPRESSION_BREG CFI_REG(eip), CFI_REG(ebx), __SIZEOF_POINTER__
 
     // Call artFindNativeMethodRunnable()
-    subl LITERAL(12), %esp         // align stack
-    CFI_ADJUST_CFA_OFFSET(12)
+    INCREASE_FRAME 12             // Align stack.
     pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
     CFI_ADJUST_CFA_OFFSET(4)
     call SYMBOL(artFindNativeMethodRunnable)  // (Thread*)
@@ -86,87 +147,15 @@
 
     // Check for exception.
     test %eax, %eax
-    jz 1f
+    jz .Lcritical_deliver_exception
 
-    // Restore frame and do the tail call.
     CFI_REMEMBER_STATE
-    RESTORE_SAVE_REFS_AND_ARGS_FRAME
-    jmp *%eax
-    CFI_RESTORE_STATE_AND_DEF_CFA(%esp, FRAME_SIZE_SAVE_REFS_AND_ARGS)
 
-1:
-    DELIVER_PENDING_EXCEPTION_FRAME_READY
+    // Remember our return PC in EDX.
+    movl __SIZEOF_POINTER__(%ebx), %edx
+    CFI_REGISTER(%eip, %edx)
 
-.Lcritical_has_stack_args:
-    // As mentioned above, the runtime shall not examine the args in the managed frame
-    // and since all args for the native call are on the stack, we can use the managed
-    // args registers as scratch registers. So, EBX, EDX and ECX are available and we
-    // do not need to restore xmm0-xmm3 either.
-
-    // Restore registers as we're about to move stack args over the current SaveRefsAndArgs frame.
-    movl (%esp), %edx   // Remember the method in EDX.
-    movl 48(%esp), %ebp
-    CFI_RESTORE(%ebp)
-    movl 52(%esp), %esi
-    CFI_RESTORE(%esi)
-    movl 56(%esp), %edi
-    CFI_RESTORE(%edi)
-
-    // Calculate the address of the end of the move destination and redefine CFI to take
-    // ownership of the JNI stub frame. EBX is conveniently callee-save in native ABI.
-    leal 0(%esp, %eax, 1), %ebx
-    CFI_DEF_CFA(%ebx, FRAME_SIZE_SAVE_REFS_AND_ARGS)
-
-    // Calculate the number of DWORDs to move.
-    shrl LITERAL(2), %eax
-    leal -1(%eax), %ecx  // Do not move the return PC.
-
-    // Load our return PC to EAX.
-    movl FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__(%esp), %eax
-
-    // Save EDI, ESI so that we can use them for moving stack args.
-    pushl %edi  // No `CFI_ADJUST_CFA_OFFSET`, CFA register is currently EBX, not ESP.
-    pushl %esi  // ditto
-
-    // Mov the stack args.
-    leal 2 * __SIZEOF_POINTER__(%esp), %edi
-    leal FRAME_SIZE_SAVE_REFS_AND_ARGS(%edi), %esi
-    rep movsd
-
-    // Save our return PC.
-    movl %eax, (%edi)
-
-    // Restore EDI, ESI.
-    popl %esi   // No `CFI_ADJUST_CFA_OFFSET`, CFA register is currently EBX, not ESP.
-    popl %edi   // ditto
-
-    // Re-create the SaveRefsAndArgs frame above the args.
-    movl %edi, 56(%ebx)
-    CFI_REL_OFFSET(%edi, 56)
-    movl %esi, 52(%ebx)
-    CFI_REL_OFFSET(%esi, 52)
-    movl %ebp, 48(%ebx)
-    CFI_REL_OFFSET(%ebp, 48)
-    // Skip managed ABI args EBX, EDX, ECX and FPRs, see above.
-    // (We have already clobbered EBX, EDX, ECX anyway).
-    movl %edx, (%ebx)    // Save method pointer.
-
-    // Place tagged managed sp in Thread::Current()->top_quick_frame.
-    leal 1(%ebx), %eax  // Tag as GenericJNI frame.
-    movl %eax, %fs:THREAD_TOP_QUICK_FRAME_OFFSET
-
-    // Call artFindNativeMethodRunnable()
-    subl LITERAL(12), %esp        // align stack, no `CFI_ADJUST_CFA_OFFSET`.
-    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
-    call SYMBOL(artFindNativeMethodRunnable)  // (Thread*)
-    addl LITERAL(16), %esp        // Pop args, no `CFI_ADJUST_CFA_OFFSET`.
-
-    // Check for exception.
-    test %eax, %eax
-    jz 2f
-
-    // Restore the frame. We shall not need the method anymore.
-    CFI_REMEMBER_STATE
+    // Restore callee-save registers from the frame. We shall not need the method anymore.
     movl 48(%ebx), %ebp
     CFI_RESTORE(%ebp)
     movl 52(%ebx), %esi
@@ -174,50 +163,39 @@
     movl 56(%ebx), %edi
     CFI_RESTORE(%edi)
 
-    // Remember our return PC in EDX.
-    movl -__SIZEOF_POINTER__(%ebx), %edx
-
     // Calculate the number of DWORDs to move.
-    leal -__SIZEOF_POINTER__(%ebx), %ecx  // Do not move return PC.
+    movl %ebx, %ecx
     subl %esp, %ecx
     shrl LITERAL(2), %ecx
+    jecxz .Lcritical_skip_copy_args_back
 
     // Save EDI, ESI so that we can use them for moving stack args.
-    pushl %edi  // No `CFI_ADJUST_CFA_OFFSET`, CFA register is currently EBX, not ESP.
-    pushl %esi  // ditto
+    PUSH edi
+    PUSH esi
 
-    // Mov stack args to their original place.
-    leal -2 * __SIZEOF_POINTER__(%ebx), %esi
-    leal FRAME_SIZE_SAVE_REFS_AND_ARGS - 2 * __SIZEOF_POINTER__(%ebx), %edi
+    // Move stack args to their original place.
+    leal -__SIZEOF_POINTER__(%ebx), %esi
+    leal FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__(%ebx), %edi
     std
     rep movsd
     cld
 
-    // Store our return PC.
-    movl %edx, (%edi)
-
     // Restore EDI, ESI.
-    popl %esi   // No `CFI_ADJUST_CFA_OFFSET`, CFA register is currently EBX, not ESP.
-    popl %edi   // ditto
+    POP esi
+    POP edi
 
-    // Redefine CFI to release ownership of the JNI stub frame.
-    CFI_DEF_CFA(%esp, FRAME_SIZE_SAVE_REFS_AND_ARGS)
-
+.Lcritical_skip_copy_args_back:
     // Remove the frame reservation.
-    addl LITERAL(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__), %esp
-    CFI_ADJUST_CFA_OFFSET(-FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)
+    DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__
+
+    // Store our return PC.
+    movl %edx, (%esp)
+    CFI_REL_OFFSET(%eip, 0)
 
     // Do the tail call.
     jmp *%eax
-    CFI_RESTORE_STATE_AND_DEF_CFA(%ebx, FRAME_SIZE_SAVE_REFS_AND_ARGS)
+    CFI_RESTORE_STATE_AND_DEF_CFA(%esp, FRAME_SIZE_SAVE_REFS_AND_ARGS)
 
-2:
-    // Replicate DELIVER_PENDING_EXCEPTION_FRAME_READY without CFI_ADJUST_CFA_OFFSET,
-    // CFA register is currently EBX, not ESP.
-
-    // Outgoing argument set up
-    subl MACRO_LITERAL(12), %esp               // alignment padding
-    pushl %fs:THREAD_SELF_OFFSET               // pass Thread::Current()
-    call SYMBOL(artDeliverPendingExceptionFromCode)  // artDeliverPendingExceptionFromCode(Thread*)
-    UNREACHABLE
+.Lcritical_deliver_exception:
+    DELIVER_PENDING_EXCEPTION_FRAME_READY
 END_FUNCTION art_jni_dlsym_lookup_critical_stub
diff --git a/runtime/arch/x86/jni_frame_x86.h b/runtime/arch/x86/jni_frame_x86.h
index e710179..15ccff8 100644
--- a/runtime/arch/x86/jni_frame_x86.h
+++ b/runtime/arch/x86/jni_frame_x86.h
@@ -33,31 +33,47 @@
 static constexpr size_t kNativeStackAlignment = 16;  // IA-32 cdecl requires 16 byte alignment.
 static_assert(kNativeStackAlignment == kStackAlignment);
 
-// Get the size of "out args" for @CriticalNative method stub.
-// This must match the size of the frame emitted by the JNI compiler at the native call site.
-inline size_t GetCriticalNativeOutArgsSize(const char* shorty, uint32_t shorty_len) {
+// Get the size of the arguments for a native call.
+inline size_t GetNativeOutArgsSize(size_t num_args, size_t num_long_or_double_args) {
+  size_t num_arg_words = num_args + num_long_or_double_args;
+  return num_arg_words * static_cast<size_t>(kX86PointerSize);
+}
+
+// Get stack args size for @CriticalNative method calls.
+inline size_t GetCriticalNativeCallArgsSize(const char* shorty, uint32_t shorty_len) {
   DCHECK_EQ(shorty_len, strlen(shorty));
 
-  size_t num_long_or_double_args = 0u;
-  for (size_t i = 1; i != shorty_len; ++i) {
-    if (shorty[i] == 'J' || shorty[i] == 'D') {
-      num_long_or_double_args += 1u;
-    }
-  }
-  size_t num_arg_words = shorty_len - 1u + num_long_or_double_args;
+  size_t num_long_or_double_args =
+      std::count_if(shorty + 1, shorty + shorty_len, [](char c) { return c == 'J' || c == 'D'; });
 
+  return GetNativeOutArgsSize(/*num_args=*/ shorty_len - 1u, num_long_or_double_args);
+}
+
+// Get the frame size for @CriticalNative method stub.
+// This must match the size of the frame emitted by the JNI compiler at the native call site.
+inline size_t GetCriticalNativeStubFrameSize(const char* shorty, uint32_t shorty_len) {
   // The size of outgoing arguments.
-  size_t size = num_arg_words * static_cast<size_t>(kX86PointerSize);
+  size_t size = GetCriticalNativeCallArgsSize(shorty, shorty_len);
 
-  // Add return address size.
-  size += kFramePointerSize;
   // We can make a tail call if there are no stack args and the return type is not
   // FP type (needs moving from ST0 to MMX0) and we do not need to extend the result.
   bool return_type_ok = shorty[0] == 'I' || shorty[0] == 'J' || shorty[0] == 'V';
-  if (return_type_ok && size == kFramePointerSize) {
-    return kFramePointerSize;
+  if (return_type_ok && size == 0u) {
+    return 0u;
   }
 
+  // Add return address size.
+  size += kFramePointerSize;
+  return RoundUp(size, kNativeStackAlignment);
+}
+
+// Get the frame size for direct call to a @CriticalNative method.
+// This must match the size of the extra frame emitted by the compiler at the native call site.
+inline size_t GetCriticalNativeDirectCallFrameSize(const char* shorty, uint32_t shorty_len) {
+  // The size of outgoing arguments.
+  size_t size = GetCriticalNativeCallArgsSize(shorty, shorty_len);
+
+  // No return PC to save, zero- and sign-extension and FP value moves are handled by the caller.
   return RoundUp(size, kNativeStackAlignment);
 }
 
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 4abdf70..2bf92bb 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -31,10 +31,7 @@
     PUSH ebp
     subl MACRO_LITERAL(12), %esp  // Grow stack by 3 words.
     CFI_ADJUST_CFA_OFFSET(12)
-    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
-    // Load Runtime::instance_ from GOT.
-    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
-    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
+    LOAD_RUNTIME_INSTANCE \temp_reg, \got_reg
     // Push save all callee-save method.
     pushl RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET(REG_VAR(temp_reg))
     CFI_ADJUST_CFA_OFFSET(4)
@@ -57,10 +54,7 @@
     PUSH ebp
     subl MACRO_LITERAL(12), %esp  // Grow stack by 3 words.
     CFI_ADJUST_CFA_OFFSET(12)
-    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
-    // Load Runtime::instance_ from GOT.
-    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
-    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
+    LOAD_RUNTIME_INSTANCE \temp_reg, \got_reg
     // Push save all callee-save method.
     pushl RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET(REG_VAR(temp_reg))
     CFI_ADJUST_CFA_OFFSET(4)
@@ -87,10 +81,7 @@
     subl MACRO_LITERAL(8), %esp  // Grow stack by 2 words.
     CFI_ADJUST_CFA_OFFSET(8)
 
-    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
-    // Load Runtime::instance_ from GOT.
-    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
-    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
+    LOAD_RUNTIME_INSTANCE \temp_reg, \got_reg
     // Push save all callee-save method.
     pushl RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET(REG_VAR(temp_reg))
     CFI_ADJUST_CFA_OFFSET(4)
@@ -122,10 +113,7 @@
 MACRO2(SETUP_SAVE_REFS_AND_ARGS_FRAME, got_reg, temp_reg)
     SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
 
-    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
-    // Load Runtime::instance_ from GOT.
-    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
-    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
+    LOAD_RUNTIME_INSTANCE \temp_reg, \got_reg
     // Push save all callee-save method.
     pushl RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET(REG_VAR(temp_reg))
     CFI_ADJUST_CFA_OFFSET(4)
@@ -196,10 +184,7 @@
     movsd %xmm6, 60(%esp)
     movsd %xmm7, 68(%esp)
 
-    SETUP_GOT_NOSAVE RAW_VAR(got_reg)
-    // Load Runtime::instance_ from GOT.
-    movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(temp_reg)
-    movl (REG_VAR(temp_reg)), REG_VAR(temp_reg)
+    LOAD_RUNTIME_INSTANCE \temp_reg, \got_reg
     // Push save everything callee-save method.
     pushl \runtime_method_offset(REG_VAR(temp_reg))
     CFI_ADJUST_CFA_OFFSET(4)
@@ -364,7 +349,7 @@
     PUSH eax                                              // pass arg1
     call SYMBOL(artThrowNullPointerExceptionFromSignal)   // (addr, self)
     UNREACHABLE
-END_FUNCTION art_quick_throw_null_pointer_exception
+END_FUNCTION art_quick_throw_null_pointer_exception_from_signal
 
     /*
      * Called by managed code to create and deliver an ArithmeticException.
@@ -1727,104 +1712,39 @@
     /*
      * Called to resolve an imt conflict.
      * eax is the conflict ArtMethod.
-     * xmm7 is a hidden argument that holds the target interface method's dex method index.
+     * xmm7 is a hidden argument that holds the target interface method.
      *
      * Note that this stub writes to eax.
-     * Because of lack of free registers, it also saves and restores edi.
+     * Because of lack of free registers, it also saves and restores esi.
      */
 DEFINE_FUNCTION art_quick_imt_conflict_trampoline
-    PUSH EDI
     PUSH ESI
-    PUSH EDX
-    movl 16(%esp), %edi         // Load referrer.
     movd %xmm7, %esi            // Get target method index stored in xmm7, remember it in ESI.
-    // If the method is obsolete, just go through the dex cache miss slow path.
-    // The obsolete flag is set with suspended threads, so we do not need an acquire operation here.
-    testl LITERAL(ACC_OBSOLETE_METHOD), ART_METHOD_ACCESS_FLAGS_OFFSET(%edi)
-    jnz .Limt_conflict_trampoline_dex_cache_miss
-    movl ART_METHOD_DECLARING_CLASS_OFFSET(%edi), %edi // Load declaring class (no read barrier).
-    movl MIRROR_CLASS_DEX_CACHE_OFFSET(%edi), %edi     // Load the DexCache (without read barrier).
-    UNPOISON_HEAP_REF edi
-    movl MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET(%edi), %edi  // Load the resolved methods.
-    pushl ART_METHOD_JNI_OFFSET_32(%eax)  // Push ImtConflictTable.
-    CFI_ADJUST_CFA_OFFSET(4)
-    movl %esi, %eax             // Copy the method index from ESI.
-    andl LITERAL(METHOD_DEX_CACHE_SIZE_MINUS_ONE), %eax  // Calculate DexCache method slot index.
-    leal 0(%edi, %eax, 2 * __SIZEOF_POINTER__), %edi  // Load DexCache method slot address.
-    mov %ecx, %edx              // Make EDX:EAX == ECX:EBX so that LOCK CMPXCHG8B makes no changes.
-    mov %ebx, %eax              // (The actual value does not matter.)
-    lock cmpxchg8b (%edi)       // Relaxed atomic load EDX:EAX from the dex cache slot.
-    popl %edi                   // Pop ImtConflictTable.
-    CFI_ADJUST_CFA_OFFSET(-4)
-    cmp %edx, %esi              // Compare method index to see if we had a DexCache method hit.
-    jne .Limt_conflict_trampoline_dex_cache_miss
+    movl ART_METHOD_JNI_OFFSET_32(%eax), %eax  // Load ImtConflictTable.
 .Limt_table_iterate:
-    cmpl %eax, 0(%edi)
+    cmpl %esi, 0(%eax)
     jne .Limt_table_next_entry
     // We successfully hit an entry in the table. Load the target method
     // and jump to it.
-    movl __SIZEOF_POINTER__(%edi), %eax
+    movl __SIZEOF_POINTER__(%eax), %eax
     CFI_REMEMBER_STATE
-    POP EDX
     POP ESI
-    POP EDI
     jmp *ART_METHOD_QUICK_CODE_OFFSET_32(%eax)
-    CFI_RESTORE_STATE_AND_DEF_CFA(esp, 16)
+    CFI_RESTORE_STATE_AND_DEF_CFA(esp, 8)
 .Limt_table_next_entry:
     // If the entry is null, the interface method is not in the ImtConflictTable.
-    cmpl LITERAL(0), 0(%edi)
+    cmpl LITERAL(0), 0(%eax)
     jz .Lconflict_trampoline
     // Iterate over the entries of the ImtConflictTable.
-    addl LITERAL(2 * __SIZEOF_POINTER__), %edi
+    addl LITERAL(2 * __SIZEOF_POINTER__), %eax
     jmp .Limt_table_iterate
 .Lconflict_trampoline:
     // Call the runtime stub to populate the ImtConflictTable and jump to the
     // resolved method.
-    CFI_REMEMBER_STATE
-    POP EDX
+    // Pass the interface method in first argument.
+    movl %esi, %eax
     POP ESI
-    POP EDI
     INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
-    CFI_RESTORE_STATE_AND_DEF_CFA(esp, 16)
-.Limt_conflict_trampoline_dex_cache_miss:
-    // We're not creating a proper runtime method frame here,
-    // artLookupResolvedMethod() is not allowed to walk the stack.
-
-    // Save core register args; EDX is already saved.
-    PUSH ebx
-    PUSH ecx
-
-    // Save FPR args.
-    subl MACRO_LITERAL(32), %esp
-    CFI_ADJUST_CFA_OFFSET(32)
-    movsd %xmm0, 0(%esp)
-    movsd %xmm1, 8(%esp)
-    movsd %xmm2, 16(%esp)
-    movsd %xmm3, 24(%esp)
-
-    pushl 32+8+16(%esp)         // Pass referrer.
-    CFI_ADJUST_CFA_OFFSET(4)
-    pushl %esi                  // Pass method index.
-    CFI_ADJUST_CFA_OFFSET(4)
-    call SYMBOL(artLookupResolvedMethod)  // (uint32_t method_index, ArtMethod* referrer)
-    addl LITERAL(8), %esp       // Pop arguments.
-    CFI_ADJUST_CFA_OFFSET(-8)
-
-    // Restore FPR args.
-    movsd 0(%esp), %xmm0
-    movsd 8(%esp), %xmm1
-    movsd 16(%esp), %xmm2
-    movsd 24(%esp), %xmm3
-    addl MACRO_LITERAL(32), %esp
-    CFI_ADJUST_CFA_OFFSET(-32)
-
-    // Restore core register args.
-    POP ecx
-    POP ebx
-
-    cmp LITERAL(0), %eax        // If the method wasn't resolved,
-    je .Lconflict_trampoline    //   skip the lookup and go to artInvokeInterfaceTrampoline().
-    jmp .Limt_table_iterate
 END_FUNCTION art_quick_imt_conflict_trampoline
 
 DEFINE_FUNCTION art_quick_resolution_trampoline
@@ -1906,9 +1826,9 @@
 
     // Tear down the alloca.
     movl %ebp, %esp
+    CFI_REMEMBER_STATE
     CFI_DEF_CFA_REGISTER(esp)
 
-
     // Tear down the callee-save frame.
     // Remove space for FPR args and EAX
     addl LITERAL(4 + 4 * 8), %esp
@@ -1926,16 +1846,21 @@
     movd %edx, %xmm1
     punpckldq %xmm1, %xmm0
     ret
+
+    // Undo the unwinding information from above since it doesn't apply below.
+    CFI_RESTORE_STATE_AND_DEF_CFA(ebp, 64)
 .Lexception_in_native:
     pushl %fs:THREAD_TOP_QUICK_FRAME_OFFSET
     addl LITERAL(-1), (%esp)  // Remove the GenericJNI tag.
     movl (%esp), %esp
-    // Do a call to push a new save-all frame required by the runtime.
-    call .Lexception_call
-.Lexception_call:
-    DELIVER_PENDING_EXCEPTION
+    call art_deliver_pending_exception
 END_FUNCTION art_quick_generic_jni_trampoline
 
+DEFINE_FUNCTION art_deliver_pending_exception
+    // This will create a new save-all frame, required by the runtime.
+    DELIVER_PENDING_EXCEPTION
+END_FUNCTION art_deliver_pending_exception
+
 DEFINE_FUNCTION art_quick_to_interpreter_bridge
     SETUP_SAVE_REFS_AND_ARGS_FRAME  ebx, ebx  // save frame
     mov %esp, %edx                // remember SP
diff --git a/runtime/arch/x86/thread_x86.cc b/runtime/arch/x86/thread_x86.cc
index cc8f1fa..cca9a91 100644
--- a/runtime/arch/x86/thread_x86.cc
+++ b/runtime/arch/x86/thread_x86.cc
@@ -135,7 +135,7 @@
   // Allow easy indirection back to Thread*.
   tlsPtr_.self = this;
 
-  // Sanity check that reads from %fs point to this Thread*.
+  // Check that the reads from %fs point to this Thread*.
   Thread* self_check;
   CHECK_EQ(THREAD_SELF_OFFSET, SelfOffset<PointerSize::k32>().Int32Value());
   __asm__ __volatile__("movl %%fs:(%1), %0"
@@ -144,7 +144,7 @@
       :);  // clobber
   CHECK_EQ(self_check, this);
 
-  // Sanity check other offsets.
+  // Check the other offsets
   CHECK_EQ(THREAD_EXCEPTION_OFFSET, ExceptionOffset<PointerSize::k32>().Int32Value());
   CHECK_EQ(THREAD_CARD_TABLE_OFFSET, CardTableOffset<PointerSize::k32>().Int32Value());
   CHECK_EQ(THREAD_ID_OFFSET, ThinLockIdOffset<PointerSize::k32>().Int32Value());
@@ -153,7 +153,7 @@
 void Thread::CleanupCpu() {
   MutexLock mu(this, *Locks::modify_ldt_lock_);
 
-  // Sanity check that reads from %fs point to this Thread*.
+  // Check that the reads from %fs point to this Thread*.
   Thread* self_check;
   __asm__ __volatile__("movl %%fs:(%1), %0"
       : "=r"(self_check)  // output
diff --git a/runtime/arch/x86_64/asm_support_x86_64.S b/runtime/arch/x86_64/asm_support_x86_64.S
index 6a60a98..2e68024 100644
--- a/runtime/arch/x86_64/asm_support_x86_64.S
+++ b/runtime/arch/x86_64/asm_support_x86_64.S
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_S_
 
 #include "asm_support_x86_64.h"
+#include "interpreter/cfi_asm_support.h"
 
 // Regular gas(1) & current clang/llvm assembler support named macro parameters.
 #define MACRO0(macro_name) .macro macro_name
@@ -76,6 +77,7 @@
     #define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
     #define CFI_RESTORE(reg) .cfi_restore reg
     #define CFI_REL_OFFSET(reg,size) .cfi_rel_offset reg,size
+    #define CFI_REGISTER(orig_reg, current_reg) .cfi_register orig_reg, current_reg
     #define CFI_REMEMBER_STATE .cfi_remember_state
     // The spec is not clear whether the CFA is part of the saved state and tools
     // differ in the behaviour, so explicitly set the CFA to avoid any ambiguity.
@@ -92,11 +94,59 @@
     #define CFI_DEF_CFA_REGISTER(reg)
     #define CFI_RESTORE(reg)
     #define CFI_REL_OFFSET(reg,size)
+    #define CFI_REGISTER(orig_reg, current_reg)
     #define CFI_REMEMBER_STATE
     #define CFI_RESTORE_STATE_AND_DEF_CFA(off)
     #define CFI_RESTORE_STATE
 #endif
 
+// The register numbers are a bit mixed up for x86-64.
+#define CFI_REG_rax 0
+#define CFI_REG_rcx 2
+#define CFI_REG_rdx 1
+#define CFI_REG_rbx 3
+#define CFI_REG_rsp 7
+#define CFI_REG_rbp 6
+#define CFI_REG_rsi 4
+#define CFI_REG_rdi 5
+#define CFI_REG_r8 8
+#define CFI_REG_r9 9
+#define CFI_REG_r10 10
+#define CFI_REG_r11 11
+#define CFI_REG_r12 12
+#define CFI_REG_r13 13
+#define CFI_REG_r14 14
+#define CFI_REG_r15 15
+#define CFI_REG_rip 16
+
+#define CFI_REG(reg) CFI_REG_##reg
+
+MACRO3(CFI_EXPRESSION_BREG, n, b, offset)
+    .if (-0x40 <= (\offset)) && ((\offset) < 0x40)
+        CFI_EXPRESSION_BREG_1(\n, \b, \offset)
+    .elseif (-0x2000 <= (\offset)) && ((\offset) < 0x2000)
+        CFI_EXPRESSION_BREG_2(\n, \b, \offset)
+    .else
+        .error "Unsupported offset"
+    .endif
+END_MACRO
+
+MACRO3(CFI_DEF_CFA_BREG_PLUS_UCONST, reg, offset, size)
+    .if ((\size) < 0)
+        .error "Size should be positive"
+    .endif
+    .if (((\offset) < -0x40) || ((\offset) >= 0x40))
+        .error "Unsupported offset"
+    .endif
+    .if ((\size) < 0x80)
+        CFI_DEF_CFA_BREG_PLUS_UCONST_1_1(\reg, \offset, \size)
+    .elseif ((\size) < 0x4000)
+        CFI_DEF_CFA_BREG_PLUS_UCONST_1_2(\reg, \offset, \size)
+    .else
+        .error "Unsupported size"
+    .endif
+END_MACRO
+
     // Symbols.
 #if !defined(__APPLE__)
     #define SYMBOL(name) name
@@ -131,7 +181,7 @@
     ALIGN_FUNCTION_ENTRY
 CALLVAR(c_name):
     CFI_STARTPROC
-    // Ensure we get a sane starting CFA.
+    // Ensure we get an appropriate starting CFA.
     CFI_DEF_CFA(rsp, RAW_VAR(cfa_offset))
 END_MACRO
 
@@ -178,6 +228,16 @@
     CFI_RESTORE(REG_VAR(reg))
 END_MACRO
 
+MACRO1(INCREASE_FRAME, frame_adjustment)
+    subq MACRO_LITERAL(RAW_VAR(frame_adjustment)), %rsp
+    CFI_ADJUST_CFA_OFFSET((RAW_VAR(frame_adjustment)))
+END_MACRO
+
+MACRO1(DECREASE_FRAME, frame_adjustment)
+    addq MACRO_LITERAL(RAW_VAR(frame_adjustment)), %rsp
+    CFI_ADJUST_CFA_OFFSET(-(RAW_VAR(frame_adjustment)))
+END_MACRO
+
 MACRO1(UNIMPLEMENTED,name)
     FUNCTION_TYPE(SYMBOL(\name))
     ASM_HIDDEN VAR(name)
@@ -199,6 +259,11 @@
     int3
 END_MACRO
 
+MACRO1(LOAD_RUNTIME_INSTANCE, reg)
+    movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), REG_VAR(reg)
+    movq (REG_VAR(reg)), REG_VAR(reg)
+END_MACRO
+
 // Macros to poison (negate) the reference for heap poisoning.
 MACRO1(POISON_HEAP_REF, rRef)
 #ifdef USE_HEAP_POISONING
@@ -223,8 +288,7 @@
     int3
 #else
     // R10 := Runtime::Current()
-    movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10
-    movq (%r10), %r10
+    LOAD_RUNTIME_INSTANCE r10
     // Save callee and GPR args, mixed together to agree with core spills bitmap.
     PUSH r15  // Callee save.
     PUSH r14  // Callee save.
@@ -233,8 +297,7 @@
     PUSH rbp  // Callee save.
     PUSH rbx  // Callee save.
     // Create space for FPR args, plus space for ArtMethod*.
-    subq LITERAL(8 + 4 * 8), %rsp
-    CFI_ADJUST_CFA_OFFSET(8 + 4 * 8)
+    INCREASE_FRAME 8 + 4 * 8
     // Save FPRs.
     movq %xmm12, 8(%rsp)
     movq %xmm13, 16(%rsp)
@@ -260,8 +323,7 @@
     movq 16(%rsp), %xmm13
     movq 24(%rsp), %xmm14
     movq 32(%rsp), %xmm15
-    addq LITERAL(8 + 4*8), %rsp
-    CFI_ADJUST_CFA_OFFSET(-8 - 4*8)
+    DECREASE_FRAME 8 + 4*8
     // TODO: optimize by not restoring callee-saves restored by the ABI
     POP rbx
     POP rbp
@@ -289,8 +351,7 @@
     PUSH_ARG rdx  // Quick arg 2.
     PUSH_ARG rcx  // Quick arg 3.
     // Create space for FPR args and create 2 slots for ArtMethod*.
-    subq MACRO_LITERAL(16 + 12 * 8), %rsp
-    CFI_ADJUST_CFA_OFFSET(16 + 12 * 8)
+    INCREASE_FRAME 16 + 12 * 8
     // Save FPRs.
     movq %xmm0, 16(%rsp)
     movq %xmm1, 24(%rsp)
@@ -326,8 +387,7 @@
     movq 88(%rsp), %xmm13
     movq 96(%rsp), %xmm14
     movq 104(%rsp), %xmm15
-    addq MACRO_LITERAL(80 + 4 * 8), %rsp
-    CFI_ADJUST_CFA_OFFSET(-(80 + 4 * 8))
+    DECREASE_FRAME 80 + 4 * 8
     // Restore callee and GPR args, mixed together to agree with core spills bitmap.
     POP_ARG rcx
     POP_ARG rdx
@@ -352,8 +412,7 @@
     int3
 #else
     // R10 := Runtime::Current()
-    movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10
-    movq (%r10), %r10
+    LOAD_RUNTIME_INSTANCE r10
     // Save callee save registers to agree with core spills bitmap.
     PUSH r15  // Callee save.
     PUSH r14  // Callee save.
@@ -362,8 +421,7 @@
     PUSH rbp  // Callee save.
     PUSH rbx  // Callee save.
     // Create space for FPR args, plus space for ArtMethod*.
-    subq MACRO_LITERAL(4 * 8 + 8), %rsp
-    CFI_ADJUST_CFA_OFFSET(4 * 8 + 8)
+    INCREASE_FRAME 4 * 8 + 8
     // Save FPRs.
     movq %xmm12, 8(%rsp)
     movq %xmm13, 16(%rsp)
@@ -386,8 +444,7 @@
 
 MACRO0(SETUP_FP_CALLEE_SAVE_FRAME)
     // Create space for ART FP callee-saved registers
-    subq MACRO_LITERAL(4 * 8), %rsp
-    CFI_ADJUST_CFA_OFFSET(4 * 8)
+    INCREASE_FRAME 4 * 8
     movq %xmm12, 0(%rsp)
     movq %xmm13, 8(%rsp)
     movq %xmm14, 16(%rsp)
@@ -400,8 +457,7 @@
     movq 8(%rsp), %xmm13
     movq 16(%rsp), %xmm14
     movq 24(%rsp), %xmm15
-    addq MACRO_LITERAL(4 * 8), %rsp
-    CFI_ADJUST_CFA_OFFSET(- 4 * 8)
+    DECREASE_FRAME 4 * 8
 END_MACRO
 
     /*
diff --git a/runtime/arch/x86_64/instruction_set_features_x86_64.h b/runtime/arch/x86_64/instruction_set_features_x86_64.h
index 76258fa..9b90365 100644
--- a/runtime/arch/x86_64/instruction_set_features_x86_64.h
+++ b/runtime/arch/x86_64/instruction_set_features_x86_64.h
@@ -59,6 +59,11 @@
     return Convert(X86InstructionSetFeatures::FromAssembly(true));
   }
 
+  // Use external cpu_features library.
+  static X86_64FeaturesUniquePtr FromCpuFeatures() {
+    return Convert(X86InstructionSetFeatures::FromCpuFeatures(true));
+  }
+
   InstructionSet GetInstructionSet() const override {
     return InstructionSet::kX86_64;
   }
diff --git a/runtime/arch/x86_64/instruction_set_features_x86_64_test.cc b/runtime/arch/x86_64/instruction_set_features_x86_64_test.cc
index 2b307da..3201050 100644
--- a/runtime/arch/x86_64/instruction_set_features_x86_64_test.cc
+++ b/runtime/arch/x86_64/instruction_set_features_x86_64_test.cc
@@ -21,15 +21,18 @@
 namespace art {
 
 TEST(X86_64InstructionSetFeaturesTest, X86Features) {
+  const bool is_runtime_isa = kRuntimeISA == InstructionSet::kX86_64;
   std::string error_msg;
   std::unique_ptr<const InstructionSetFeatures> x86_64_features(
       InstructionSetFeatures::FromVariant(InstructionSet::kX86_64, "default", &error_msg));
   ASSERT_TRUE(x86_64_features.get() != nullptr) << error_msg;
   EXPECT_EQ(x86_64_features->GetInstructionSet(), InstructionSet::kX86_64);
   EXPECT_TRUE(x86_64_features->Equals(x86_64_features.get()));
-  EXPECT_STREQ("-ssse3,-sse4.1,-sse4.2,-avx,-avx2,-popcnt",
-               x86_64_features->GetFeatureString().c_str());
-  EXPECT_EQ(x86_64_features->AsBitmap(), 0U);
+  EXPECT_EQ(x86_64_features->GetFeatureString(),
+            is_runtime_isa ? X86_64InstructionSetFeatures::FromCppDefines()->GetFeatureString()
+                    : "-ssse3,-sse4.1,-sse4.2,-avx,-avx2,-popcnt");
+  EXPECT_EQ(x86_64_features->AsBitmap(),
+            is_runtime_isa ? X86_64InstructionSetFeatures::FromCppDefines()->AsBitmap() : 0);
 }
 
 }  // namespace art
diff --git a/runtime/arch/x86_64/jni_entrypoints_x86_64.S b/runtime/arch/x86_64/jni_entrypoints_x86_64.S
index e1b8e52..a1b8c7b 100644
--- a/runtime/arch/x86_64/jni_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/jni_entrypoints_x86_64.S
@@ -28,8 +28,7 @@
     PUSH_ARG rdx  // Arg.
     PUSH_ARG rcx  // Arg.
     // Create space for FPR args, plus padding for alignment
-    subq LITERAL(72), %rsp
-    CFI_ADJUST_CFA_OFFSET(72)
+    INCREASE_FRAME 72
     // Save FPRs.
     movq %xmm0, 0(%rsp)
     movq %xmm1, 8(%rsp)
@@ -48,10 +47,10 @@
     movq (%rax), %rax                                // ArtMethod* method
     testl LITERAL(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE), \
           ART_METHOD_ACCESS_FLAGS_OFFSET(%rax)
-    jne .Llookup_stub_fast_native
+    jne .Llookup_stub_fast_or_critical_native
     call SYMBOL(artFindNativeMethod)  // (Thread*)
     jmp .Llookup_stub_continue
-.Llookup_stub_fast_native:
+.Llookup_stub_fast_or_critical_native:
     call SYMBOL(artFindNativeMethodRunnable)  // (Thread*)
 .Llookup_stub_continue:
     // restore arguments
@@ -63,8 +62,7 @@
     movq 40(%rsp), %xmm5
     movq 48(%rsp), %xmm6
     movq 56(%rsp), %xmm7
-    addq LITERAL(72), %rsp
-    CFI_ADJUST_CFA_OFFSET(-72)
+    DECREASE_FRAME 72
     POP_ARG rcx  // Arg.
     POP_ARG rdx  // Arg.
     POP_ARG rsi  // Arg.
@@ -79,34 +77,21 @@
 END_FUNCTION art_jni_dlsym_lookup_stub
 
 DEFINE_FUNCTION art_jni_dlsym_lookup_critical_stub
-    // The hidden arg holding the tagged method (bit 0 set means GenericJNI) is r11.
+    // The hidden arg holding the tagged method (bit 0 set means GenericJNI) is RAX.
     // For Generic JNI we already have a managed frame, so we reuse the art_jni_dlsym_lookup_stub.
-    testq LITERAL(1), %r11
+    testq LITERAL(1), %rax
     jnz art_jni_dlsym_lookup_stub
 
-    // We need to create a GenericJNI managed frame above the stack args.
-
-    // GenericJNI frame is similar to SaveRegsAndArgs frame with the native method
-    // instead of runtime method saved at the bottom.
-
-    // As we always have "stack args" on x86-64 (due to xmm12-xmm15 being callee-save
-    // in managed ABI but caller-save in native ABI), do not create a proper frame yet
-    // as we do on other architectures where it's useful for no stack args case.
-
-    // Reserve space for the frame (return PC is on stack).
-    subq MACRO_LITERAL(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__), %rsp
-    CFI_ADJUST_CFA_OFFSET(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)
-
-    // Save GPR args.
+    // Save GPR args and method.
     PUSH_ARG r9
     PUSH_ARG r8
     PUSH_ARG rdi
     PUSH_ARG rsi
     PUSH_ARG rdx
     PUSH_ARG rcx
+    PUSH_ARG rax
     // Create space for FPR args.
-    subq LITERAL(64), %rsp
-    CFI_ADJUST_CFA_OFFSET(64)
+    INCREASE_FRAME 8 * 8
     // Save FPRs.
     movq %xmm0, 0(%rsp)
     movq %xmm1, 8(%rsp)
@@ -116,119 +101,15 @@
     movq %xmm5, 40(%rsp)
     movq %xmm6, 48(%rsp)
     movq %xmm7, 56(%rsp)
+    // Note: It's the caller's responsibility to preserve xmm12-xmm15 as the tail call
+    // to native shall always risk clobbering those.
 
-    // Add alignment padding.
-    subq MACRO_LITERAL(__SIZEOF_POINTER__), %rsp
-    CFI_ADJUST_CFA_OFFSET(__SIZEOF_POINTER__)
-    // Save hidden arg.
-    PUSH_ARG r11
+    // Call artCriticalNativeFrameSize(method, caller_pc).
+    movq %rax, %rdi       // Pass the method from hidden arg.
+    movq 120(%rsp), %rsi  // Pass caller PC.
+    call SYMBOL(artCriticalNativeFrameSize)
 
-    // Call artCriticalNativeOutArgsSize(method).
-    movq %r11, %rdi  // Pass the method from hidden arg.
-    call SYMBOL(artCriticalNativeOutArgsSize)
-
-    // Calculate the address of the end of the move destination and redefine CFI to take
-    // ownership of the JNI stub frame.
-    leaq 16 * __SIZEOF_POINTER__(%rsp, %rax, 1), %r10  // 16 QWORDs of registers saved above.
-    CFI_DEF_CFA(%r10, FRAME_SIZE_SAVE_REFS_AND_ARGS)
-
-    // Calculate the number of QWORDs to move.
-    shrq LITERAL(3), %rax
-    leaq -1(%rax), %rcx  // Do not move the return PC.
-
-    // Load our return PC to EAX.
-    movq FRAME_SIZE_SAVE_REFS_AND_ARGS + (16 - 1) * __SIZEOF_POINTER__(%rsp), %rax
-
-    // Mov the stack args.
-    leaq 16 * __SIZEOF_POINTER__(%rsp), %rdi
-    leaq FRAME_SIZE_SAVE_REFS_AND_ARGS(%rdi), %rsi
-    rep movsq
-
-    // Save our return PC.
-    movq %rax, (%rdi)
-
-    // Pop the hidden arg and alignment padding.
-    popq %r11    // No `.cfi_adjust_cfa_offset`, CFA register is currently R10, not RSP.
-    addq MACRO_LITERAL(__SIZEOF_POINTER__), %rsp  // ditto
-
-    // Fill the SaveRefsAndArgs frame above the args, without actual args. Note that
-    // the runtime shall not examine the args here, otherwise we would have to move them in
-    // registers and stack to account for the difference between managed and native ABIs.
-    SAVE_REG_BASE r10, r15, 192
-    SAVE_REG_BASE r10, r14, 184
-    SAVE_REG_BASE r10, r13, 176
-    SAVE_REG_BASE r10, r12, 168
-    // Skip args r9, r8, rsi.
-    SAVE_REG_BASE r10, rbp, 136
-    SAVE_REG_BASE r10, rbx, 128
-    // Skip args rdx, rcx.
-    // Skip args xmm0-xmm7.
-    // Copy managed callee-saves xmm12-xmm15 from out args to the managed frame as they
-    // may theoretically store variables or unwinding data. (The compiled stub preserves
-    // them but the artCriticalNativeOutArgsSize() call above may clobber them.)
-    movq -5 * __SIZEOF_POINTER__(%r10), %xmm12
-    movq -4 * __SIZEOF_POINTER__(%r10), %xmm13
-    movq -3 * __SIZEOF_POINTER__(%r10), %xmm14
-    movq -2 * __SIZEOF_POINTER__(%r10), %xmm15
-    movq %xmm12, 80(%r10)
-    movq %xmm13, 88(%r10)
-    movq %xmm14, 96(%r10)
-    movq %xmm15, 104(%r10)
-    // Save the hidden arg as method pointer at the bottom of the stack.
-    movq %r11, (%r10)
-
-    // Move the frame register to a callee-save register.
-    movq %r10, %rbp
-    CFI_DEF_CFA_REGISTER(%rbp)
-
-    // Place tagged managed sp in Thread::Current()->top_quick_frame.
-    leaq 1(%rbp), %rax  // Tag as GenericJNI frame.
-    movq %rax, %gs:THREAD_TOP_QUICK_FRAME_OFFSET
-
-    // Call artFindNativeMethodRunnable()
-    movq %gs:THREAD_SELF_OFFSET, %rdi  // pass Thread::Current()
-    call SYMBOL(artFindNativeMethodRunnable)  // (Thread*)
-
-    // Check for exception.
-    test %rax, %rax
-    jz 2f
-
-    // Restore the frame. We shall not need the method anymore.
-    .cfi_remember_state
-    movq %rbp, %r10
-    CFI_DEF_CFA_REGISTER(%r10)
-    // Skip args xmm0-xmm7 and managed callee-saves xmm12-xmm15 (not needed for native call).
-    // Skip args rdx, rcx.
-    RESTORE_REG_BASE r10, rbx, 128
-    RESTORE_REG_BASE r10, rbp, 136
-    // Skip args r9, r8, rsi.
-    RESTORE_REG_BASE r10, r12, 168
-    RESTORE_REG_BASE r10, r13, 176
-    RESTORE_REG_BASE r10, r14, 184
-    RESTORE_REG_BASE r10, r15, 192
-
-    // Remember our return PC in R11.
-    movq -__SIZEOF_POINTER__(%r10), %r11
-
-    // Calculate the number of DWORDs to move.
-    leaq -(1 + 14) * __SIZEOF_POINTER__(%r10), %rcx  // Do not move return PC, 14 arg regs saved.
-    subq %rsp, %rcx
-    shrq LITERAL(3), %rcx
-
-    // Mov stack args to their original place.
-    leaq -2 * __SIZEOF_POINTER__(%r10), %rsi
-    leaq FRAME_SIZE_SAVE_REFS_AND_ARGS - 2 * __SIZEOF_POINTER__(%r10), %rdi
-    std
-    rep movsq
-    cld
-
-    // Store our return PC.
-    movq %r11, (%rdi)
-
-    // Redefine CFI to release ownership of the JNI stub frame.
-    CFI_DEF_CFA(%rsp, FRAME_SIZE_SAVE_REFS_AND_ARGS + 14 * __SIZEOF_POINTER__)
-
-    // Restore args.
+    // Restore registers.
     movq 0(%rsp), %xmm0
     movq 8(%rsp), %xmm1
     movq 16(%rsp), %xmm2
@@ -237,8 +118,8 @@
     movq 40(%rsp), %xmm5
     movq 48(%rsp), %xmm6
     movq 56(%rsp), %xmm7
-    addq LITERAL(64), %rsp
-    CFI_ADJUST_CFA_OFFSET(-64)
+    DECREASE_FRAME 8 * 8
+    POP_ARG r10  // Restore method to R10.
     POP_ARG rcx
     POP_ARG rdx
     POP_ARG rsi
@@ -246,17 +127,185 @@
     POP_ARG r8
     POP_ARG r9
 
+    // Load caller PC to R11 and redefine return PC for CFI.
+    movq (%rsp), %r11
+    CFI_REGISTER(%rip, %r11)
+
+    // Reserve space for a SaveRefsAndArgs managed frame, either for the actual runtime
+    // method or for a GenericJNI frame which is similar but has a native method and a tag.
+    INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__
+
+    // Calculate the number of QWORDs to move.
+    shrq LITERAL(3), %rax
+    jz .Lcritical_skip_copy_args
+
+    // Save RDI, RSI, RCX so that we can use them for moving stack args.
+    PUSH_ARG rdi
+    PUSH_ARG rsi
+    PUSH_ARG rcx
+
+    // Move the stack args.
+    movq %rax, %rcx
+    leaq 3 * __SIZEOF_POINTER__(%rsp), %rdi
+    leaq FRAME_SIZE_SAVE_REFS_AND_ARGS(%rdi), %rsi
+    rep movsq
+
+    // Restore RDI, RSI, RCX.
+    POP_ARG rcx
+    POP_ARG rsi
+    POP_ARG rdi
+
+.Lcritical_skip_copy_args:
+    // Calculate the base address of the managed frame.
+    leaq (%rsp, %rax, 8), %rax
+
+    // Spill registers for the SaveRefsAndArgs frame above the stack args.
+    // Note that the runtime shall not examine the args here, otherwise we would have to
+    // move them in registers and stack to account for the difference between managed and
+    // native ABIs. Do not update CFI while we hold the frame address in RAX and the values
+    // in registers are unchanged.
+    movq %r15, 192(%rax)
+    movq %r14, 184(%rax)
+    movq %r13, 176(%rax)
+    movq %r12, 168(%rax)
+    movq %r9, 160(%rax)
+    movq %r8, 152(%rax)
+    movq %rsi, 144(%rax)
+    movq %rbp, 136(%rax)
+    movq %rbx, 128(%rax)
+    movq %rdx, 120(%rax)
+    movq %rcx, 112(%rax)
+    movq %xmm0, 16(%rax)
+    movq %xmm1, 24(%rax)
+    movq %xmm2, 32(%rax)
+    movq %xmm3, 40(%rax)
+    movq %xmm4, 48(%rax)
+    movq %xmm5, 56(%rax)
+    movq %xmm6, 64(%rax)
+    movq %xmm7, 72(%rax)
+    // Skip managed ABI callee-saves xmm12-xmm15.
+
+    // Move the managed frame address to native callee-save register RBP and update CFI.
+    movq %rax, %rbp
+    CFI_EXPRESSION_BREG CFI_REG(r15), CFI_REG(rbp), 192
+    CFI_EXPRESSION_BREG CFI_REG(r14), CFI_REG(rbp), 184
+    CFI_EXPRESSION_BREG CFI_REG(r13), CFI_REG(rbp), 176
+    CFI_EXPRESSION_BREG CFI_REG(r12), CFI_REG(rbp), 168
+    // Skip args r9, r8, rsi.
+    CFI_EXPRESSION_BREG CFI_REG(rbp), CFI_REG(rbp), 136
+    CFI_EXPRESSION_BREG CFI_REG(rbx), CFI_REG(rbp), 128
+    // Skip args rdx, rcx.
+    // Skip args xmm0-xmm7.
+
+    leaq 1(%rbp), %rax            // Prepare managed SP tagged for a GenericJNI frame.
+    testl LITERAL(ACCESS_FLAGS_METHOD_IS_NATIVE), ART_METHOD_ACCESS_FLAGS_OFFSET(%r10)
+    jnz .Lcritical_skip_prepare_runtime_method
+
+    // Save the return PC for managed stack walk.
+    // (When coming from a compiled stub, the correct return PC is already there.)
+    movq %r11, FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__(%rbp)
+
+    // Replace the target method with the SaveRefsAndArgs runtime method.
+    LOAD_RUNTIME_INSTANCE r10
+    movq RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET(%r10), %r10
+
+    movq %rbp, %rax               // Prepare untagged managed SP for the runtime method.
+
+.Lcritical_skip_prepare_runtime_method:
+    // Store the method on the bottom of the managed frame.
+    movq %r10, (%rbp)
+
+    // Place (maybe tagged) managed SP in Thread::Current()->top_quick_frame.
+    movq %rax, %gs:THREAD_TOP_QUICK_FRAME_OFFSET
+
+    // Save our return PC in the padding.
+    movq %r11, __SIZEOF_POINTER__(%rbp)
+    CFI_EXPRESSION_BREG CFI_REG(rip), CFI_REG(rbp), __SIZEOF_POINTER__
+
+    // Preserve the native arg register RDI in callee-save register RBX which was saved above.
+    movq %rdi, %rbx
+
+    // Call artFindNativeMethodRunnable()
+    movq %gs:THREAD_SELF_OFFSET, %rdi  // pass Thread::Current()
+    call SYMBOL(artFindNativeMethodRunnable)  // (Thread*)
+
+    // Check for exception.
+    test %rax, %rax
+    jz .Lcritical_deliver_exception
+
+    CFI_REMEMBER_STATE
+
+    // Restore the native arg register RDI.
+    movq %rbx, %rdi
+
+    // Remember our return PC in R11.
+    movq __SIZEOF_POINTER__(%rbp), %r11
+    CFI_REGISTER(%rip, %r11)
+
+    // Remember the frame base address in r10 but do not redefine CFI.
+    movq %rbp, %r10
+
+    // Restore the frame. We shall not need the method anymore.
+    movq 16(%rbp), %xmm0
+    movq 24(%rbp), %xmm1
+    movq 32(%rbp), %xmm2
+    movq 40(%rbp), %xmm3
+    movq 48(%rbp), %xmm4
+    movq 56(%rbp), %xmm5
+    movq 64(%rbp), %xmm6
+    movq 72(%rbp), %xmm7
+    // Skip managed callee-saves xmm12-xmm15.
+    movq 112(%rbp), %rcx
+    movq 120(%rbp), %rdx
+    RESTORE_REG_BASE rbp, rbx, 128
+    // Delay restoring RBP as it's the managed frame base.
+    movq 144(%rbp), %rsi
+    movq 152(%rbp), %r8
+    movq 160(%rbp), %r9
+    RESTORE_REG_BASE rbp, r12, 168
+    RESTORE_REG_BASE rbp, r13, 176
+    RESTORE_REG_BASE rbp, r14, 184
+    RESTORE_REG_BASE rbp, r15, 192
+    // Restore RBP last.
+    RESTORE_REG_BASE rbp, rbp, 136
+
+    cmp %r10, %rsp
+    je .Lcritical_skip_copy_args_back
+
+    // Save RDI, RSI, RCX so that we can use them for moving stack args.
+    PUSH_ARG rdi
+    PUSH_ARG rsi
+    PUSH_ARG rcx
+
+    // Calculate the number of QWORDs to move.
+    leaq -3 * __SIZEOF_POINTER__(%r10), %rcx
+    subq %rsp, %rcx
+    shrq LITERAL(3), %rcx
+
+    // Move the stack args.
+    leaq -__SIZEOF_POINTER__(%r10), %rsi
+    leaq FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__(%r10), %rdi
+    std
+    rep movsq
+    cld
+
+    // Restore RDI, RSI, RCX.
+    POP_ARG rcx
+    POP_ARG rsi
+    POP_ARG rdi
+
+.Lcritical_skip_copy_args_back:
     // Remove the frame reservation.
-    addq LITERAL(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__), %rsp
-    CFI_ADJUST_CFA_OFFSET(-(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__))
+    DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__
+
+    // Store our return PC.
+    movq %r11, (%rsp)
+    CFI_REL_OFFSET(%rip, 0)
 
     // Do the tail call.
     jmp *%rax
     CFI_RESTORE_STATE_AND_DEF_CFA(%rbp, FRAME_SIZE_SAVE_REFS_AND_ARGS)
 
-2:
-    // Drop the args from the stack (the r11 and padding was already removed).
-    addq LITERAL(14 * __SIZEOF_POINTER__), %rsp
-
+.Lcritical_deliver_exception:
     DELIVER_PENDING_EXCEPTION_FRAME_READY
 END_FUNCTION art_jni_dlsym_lookup_critical_stub
diff --git a/runtime/arch/x86_64/jni_frame_x86_64.h b/runtime/arch/x86_64/jni_frame_x86_64.h
index 65736fe..959e266 100644
--- a/runtime/arch/x86_64/jni_frame_x86_64.h
+++ b/runtime/arch/x86_64/jni_frame_x86_64.h
@@ -46,28 +46,34 @@
 // -- JNI calling convention only (Managed excludes RDI, so it's actually 5).
 constexpr size_t kMaxIntLikeRegisterArguments = 6u;
 
-// Get the size of "out args" for @CriticalNative method stub.
-// This must match the size of the frame emitted by the JNI compiler at the native call site.
-inline size_t GetCriticalNativeOutArgsSize(const char* shorty, uint32_t shorty_len) {
-  DCHECK_EQ(shorty_len, strlen(shorty));
-
-  size_t num_fp_args = 0u;
-  for (size_t i = 1; i != shorty_len; ++i) {
-    if (shorty[i] == 'F' || shorty[i] == 'D') {
-      num_fp_args += 1u;
-    }
-  }
-  size_t num_non_fp_args = shorty_len - 1u - num_fp_args;
-
+// Get the size of the arguments for a native call.
+inline size_t GetNativeOutArgsSize(size_t num_fp_args, size_t num_non_fp_args) {
   // Account for FP arguments passed through Xmm0..Xmm7.
   size_t num_stack_fp_args =
       num_fp_args - std::min(kMaxFloatOrDoubleRegisterArguments, num_fp_args);
   // Account for other (integer) arguments passed through GPR (RDI, RSI, RDX, RCX, R8, R9).
   size_t num_stack_non_fp_args =
       num_non_fp_args - std::min(kMaxIntLikeRegisterArguments, num_non_fp_args);
-  // The size of outgoing arguments.
   static_assert(kFramePointerSize == kMmxSpillSize);
-  size_t size = (num_stack_fp_args + num_stack_non_fp_args) * kFramePointerSize;
+  return (num_stack_fp_args + num_stack_non_fp_args) * kFramePointerSize;
+}
+
+// Get stack args size for @CriticalNative method calls.
+inline size_t GetCriticalNativeCallArgsSize(const char* shorty, uint32_t shorty_len) {
+  DCHECK_EQ(shorty_len, strlen(shorty));
+
+  size_t num_fp_args =
+      std::count_if(shorty + 1, shorty + shorty_len, [](char c) { return c == 'F' || c == 'D'; });
+  size_t num_non_fp_args = shorty_len - 1u - num_fp_args;
+
+  return GetNativeOutArgsSize(num_fp_args, num_non_fp_args);
+}
+
+// Get the frame size for @CriticalNative method stub.
+// This must match the size of the frame emitted by the JNI compiler at the native call site.
+inline size_t GetCriticalNativeStubFrameSize(const char* shorty, uint32_t shorty_len) {
+  // The size of outgoing arguments.
+  size_t size = GetCriticalNativeCallArgsSize(shorty, shorty_len);
 
   // We always need to spill xmm12-xmm15 as they are managed callee-saves
   // but not native callee-saves.
@@ -78,6 +84,16 @@
   return RoundUp(size, kNativeStackAlignment);
 }
 
+// Get the frame size for direct call to a @CriticalNative method.
+// This must match the size of the extra frame emitted by the compiler at the native call site.
+inline size_t GetCriticalNativeDirectCallFrameSize(const char* shorty, uint32_t shorty_len) {
+  // The size of outgoing arguments.
+  size_t size = GetCriticalNativeCallArgsSize(shorty, shorty_len);
+
+  // No return PC to save, zero- and sign-extension are handled by the caller.
+  return RoundUp(size, kNativeStackAlignment);
+}
+
 }  // namespace x86_64
 }  // namespace art
 
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index abc3a8a..9a4edd2 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -40,8 +40,7 @@
 #else
     SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY
     // R10 := Runtime::Current()
-    movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10
-    movq (%r10), %r10
+    LOAD_RUNTIME_INSTANCE r10
     // R10 := ArtMethod* for ref and args callee save frame method.
     movq RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET(%r10), %r10
     // Store ArtMethod* to bottom of stack.
@@ -88,8 +87,7 @@
     subq MACRO_LITERAL(8 + 16 * 8), %rsp
     CFI_ADJUST_CFA_OFFSET(8 + 16 * 8)
     // R10 := Runtime::Current()
-    movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10
-    movq (%r10), %r10
+    LOAD_RUNTIME_INSTANCE r10
     // Save FPRs.
     movq %xmm0, 8(%rsp)
     movq %xmm1, 16(%rsp)
@@ -1413,45 +1411,23 @@
     /*
      * Called to resolve an imt conflict.
      * rdi is the conflict ArtMethod.
-     * rax is a hidden argument that holds the target interface method's dex method index.
+     * rax is a hidden argument that holds the target interface method.
      *
-     * Note that this stub writes to r10, r11, rax and rdi.
+     * Note that this stub writes to rdi.
      */
 DEFINE_FUNCTION art_quick_imt_conflict_trampoline
 #if defined(__APPLE__)
     int3
     int3
 #else
-    movq __SIZEOF_POINTER__(%rsp), %r10 // Load referrer.
-    mov %eax, %r11d             // Remember method index in R11.
-    PUSH rdx                    // Preserve RDX as we need to clobber it by LOCK CMPXCHG16B.
-    // If the method is obsolete, just go through the dex cache miss slow path.
-    // The obsolete flag is set with suspended threads, so we do not need an acquire operation here.
-    testl LITERAL(ACC_OBSOLETE_METHOD), ART_METHOD_ACCESS_FLAGS_OFFSET(%r10)
-    jnz .Limt_conflict_trampoline_dex_cache_miss
-    movl ART_METHOD_DECLARING_CLASS_OFFSET(%r10), %r10d  // Load declaring class (no read barrier).
-    movl MIRROR_CLASS_DEX_CACHE_OFFSET(%r10), %r10d    // Load the DexCache (without read barrier).
-    UNPOISON_HEAP_REF r10d
-    movq MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET(%r10), %r10  // Load the resolved methods.
-    andl LITERAL(METHOD_DEX_CACHE_SIZE_MINUS_ONE), %eax  // Calculate DexCache method slot index.
-    shll LITERAL(1), %eax       // Multiply by 2 as entries have size 2 * __SIZEOF_POINTER__.
-    leaq 0(%r10, %rax, __SIZEOF_POINTER__), %r10 // Load DexCache method slot address.
-    mov %rcx, %rdx              // Make RDX:RAX == RCX:RBX so that LOCK CMPXCHG16B makes no changes.
-    mov %rbx, %rax              // (The actual value does not matter.)
-    lock cmpxchg16b (%r10)      // Relaxed atomic load RDX:RAX from the dex cache slot.
     movq ART_METHOD_JNI_OFFSET_64(%rdi), %rdi  // Load ImtConflictTable
-    cmp %rdx, %r11              // Compare method index to see if we had a DexCache method hit.
-    jne .Limt_conflict_trampoline_dex_cache_miss
 .Limt_table_iterate:
     cmpq %rax, 0(%rdi)
     jne .Limt_table_next_entry
     // We successfully hit an entry in the table. Load the target method
     // and jump to it.
     movq __SIZEOF_POINTER__(%rdi), %rdi
-    CFI_REMEMBER_STATE
-    POP rdx
     jmp *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi)
-    CFI_RESTORE_STATE_AND_DEF_CFA(rsp, 16)
 .Limt_table_next_entry:
     // If the entry is null, the interface method is not in the ImtConflictTable.
     cmpq LITERAL(0), 0(%rdi)
@@ -1462,66 +1438,8 @@
 .Lconflict_trampoline:
     // Call the runtime stub to populate the ImtConflictTable and jump to the
     // resolved method.
-    CFI_REMEMBER_STATE
-    POP rdx
     movq %rax, %rdi  // Load interface method
     INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
-    CFI_RESTORE_STATE_AND_DEF_CFA(rsp, 16)
-.Limt_conflict_trampoline_dex_cache_miss:
-    // We're not creating a proper runtime method frame here,
-    // artLookupResolvedMethod() is not allowed to walk the stack.
-
-    // Save GPR args and ImtConflictTable; RDX is already saved.
-    PUSH r9   // Quick arg 5.
-    PUSH r8   // Quick arg 4.
-    PUSH rsi  // Quick arg 1.
-    PUSH rcx  // Quick arg 3.
-    PUSH rdi  // ImtConflictTable
-    // Save FPR args and callee-saves, align stack to 16B.
-    subq MACRO_LITERAL(12 * 8 + 8), %rsp
-    CFI_ADJUST_CFA_OFFSET(12 * 8 + 8)
-    movq %xmm0, 0(%rsp)
-    movq %xmm1, 8(%rsp)
-    movq %xmm2, 16(%rsp)
-    movq %xmm3, 24(%rsp)
-    movq %xmm4, 32(%rsp)
-    movq %xmm5, 40(%rsp)
-    movq %xmm6, 48(%rsp)
-    movq %xmm7, 56(%rsp)
-    movq %xmm12, 64(%rsp)  // XMM12-15 are callee-save in ART compiled code ABI
-    movq %xmm13, 72(%rsp)  // but caller-save in native ABI.
-    movq %xmm14, 80(%rsp)
-    movq %xmm15, 88(%rsp)
-
-    movq %r11, %rdi             // Pass method index.
-    movq 12 * 8 + 8 + 6 * 8 + 8(%rsp), %rsi   // Pass referrer.
-    call SYMBOL(artLookupResolvedMethod)  // (uint32_t method_index, ArtMethod* referrer)
-
-    // Restore FPRs.
-    movq 0(%rsp), %xmm0
-    movq 8(%rsp), %xmm1
-    movq 16(%rsp), %xmm2
-    movq 24(%rsp), %xmm3
-    movq 32(%rsp), %xmm4
-    movq 40(%rsp), %xmm5
-    movq 48(%rsp), %xmm6
-    movq 56(%rsp), %xmm7
-    movq 64(%rsp), %xmm12
-    movq 72(%rsp), %xmm13
-    movq 80(%rsp), %xmm14
-    movq 88(%rsp), %xmm15
-    addq MACRO_LITERAL(12 * 8 + 8), %rsp
-    CFI_ADJUST_CFA_OFFSET(-(12 * 8 + 8))
-    // Restore ImtConflictTable and GPR args.
-    POP rdi
-    POP rcx
-    POP rsi
-    POP r8
-    POP r9
-
-    cmp LITERAL(0), %rax        // If the method wasn't resolved,
-    je .Lconflict_trampoline    //   skip the lookup and go to artInvokeInterfaceTrampoline().
-    jmp .Limt_table_iterate
 #endif  // __APPLE__
 END_FUNCTION art_quick_imt_conflict_trampoline
 
@@ -1676,13 +1594,16 @@
     movq 48(%rsp), %xmm6
     movq 56(%rsp), %xmm7
 
-    // Load hidden arg (r11) for @CriticalNative.
-    movq 64(%rsp), %r11
+    // Save call target in scratch register.
+    movq %rax, %r11
+
+    // Load hidden arg (rax) for @CriticalNative.
+    movq 64(%rsp), %rax
     // Load SP for out args, releasing unneeded reserved area.
     movq 72(%rsp), %rsp
 
     // native call
-    call *%rax
+    call *%r11
 
     // result sign extension is handled in C code
     // prepare for artQuickGenericJniEndTrampoline call
@@ -1702,6 +1623,7 @@
 
     // Tear down the alloca.
     movq %rbp, %rsp
+    CFI_REMEMBER_STATE
     CFI_DEF_CFA_REGISTER(rsp)
 
     // Tear down the callee-save frame.
@@ -1736,17 +1658,21 @@
     // store into fpr, for when it's a fpr return...
     movq %rax, %xmm0
     ret
+
+    // Undo the unwinding information from above since it doesn't apply below.
+    CFI_RESTORE_STATE_AND_DEF_CFA(rbp, 208)
 .Lexception_in_native:
     pushq %gs:THREAD_TOP_QUICK_FRAME_OFFSET
     addq LITERAL(-1), (%rsp)  // Remove the GenericJNI tag.
     movq (%rsp), %rsp
-    CFI_DEF_CFA_REGISTER(rsp)
-    // Do a call to push a new save-all frame required by the runtime.
-    call .Lexception_call
-.Lexception_call:
-    DELIVER_PENDING_EXCEPTION
+    call art_deliver_pending_exception
 END_FUNCTION art_quick_generic_jni_trampoline
 
+DEFINE_FUNCTION art_deliver_pending_exception
+    // This will create a new save-all frame, required by the runtime.
+    DELIVER_PENDING_EXCEPTION
+END_FUNCTION art_deliver_pending_exception
+
     /*
      * Called to bridge from the quick to interpreter ABI. On entry the arguments match those
      * of a quick call:
diff --git a/runtime/arch/x86_64/thread_x86_64.cc b/runtime/arch/x86_64/thread_x86_64.cc
index 5c0446f..b01a1d3 100644
--- a/runtime/arch/x86_64/thread_x86_64.cc
+++ b/runtime/arch/x86_64/thread_x86_64.cc
@@ -58,7 +58,7 @@
   // Allow easy indirection back to Thread*.
   tlsPtr_.self = this;
 
-  // Sanity check that reads from %gs point to this Thread*.
+  // Check that the reads from %gs point to this Thread*.
   Thread* self_check;
   __asm__ __volatile__("movq %%gs:(%1), %0"
       : "=r"(self_check)  // output
@@ -68,7 +68,7 @@
 }
 
 void Thread::CleanupCpu() {
-  // Sanity check that reads from %gs point to this Thread*.
+  // Check that the reads from %gs point to this Thread*.
   Thread* self_check;
   __asm__ __volatile__("movq %%gs:(%1), %0"
       : "=r"(self_check)  // output
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index dfadc62..630a8a5 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -120,6 +120,8 @@
       ObjPtr<mirror::Class> methods_class = GetDeclaringClass();
       return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
     }
+    case kPolymorphic:
+      return !IsSignaturePolymorphic();
     default:
       LOG(FATAL) << "Unreachable - invocation type: " << type;
       UNREACHABLE();
@@ -221,7 +223,15 @@
 }
 
 inline const dex::CodeItem* ArtMethod::GetCodeItem() {
-  return GetDexFile()->GetCodeItem(GetCodeItemOffset());
+  if (!HasCodeItem()) {
+    return nullptr;
+  }
+  Runtime* runtime = Runtime::Current();
+  PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
+  return runtime->IsAotCompiler()
+      ? GetDexFile()->GetCodeItem(reinterpret_cast32<uint32_t>(GetDataPtrSize(pointer_size)))
+      : reinterpret_cast<const dex::CodeItem*>(
+          reinterpret_cast<uintptr_t>(GetDataPtrSize(pointer_size)) & ~1);
 }
 
 inline bool ArtMethod::IsResolvedTypeIdx(dex::TypeIndex type_idx) {
@@ -382,8 +392,6 @@
     if (old_native_code != new_native_code) {
       SetEntryPointFromJniPtrSize(new_native_code, pointer_size);
     }
-  } else {
-    DCHECK(GetDataPtrSize(pointer_size) == nullptr);
   }
   const void* old_code = GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
   const void* new_code = visitor(old_code);
@@ -405,20 +413,18 @@
 }
 
 inline void ArtMethod::SetCounter(uint16_t hotness_count) {
-  DCHECK(!IsAbstract()) << PrettyMethod();
+  DCHECK(!IsAbstract());
   hotness_count_ = hotness_count;
 }
 
 inline uint16_t ArtMethod::GetCounter() {
-  DCHECK(!IsAbstract()) << PrettyMethod();
+  DCHECK(!IsAbstract());
   return hotness_count_;
 }
 
 inline uint32_t ArtMethod::GetImtIndex() {
-  if (LIKELY(IsAbstract() && imt_index_ != 0)) {
-    uint16_t imt_index = ~imt_index_;
-    DCHECK_EQ(imt_index, ImTable::GetImtIndex(this)) << PrettyMethod();
-    return imt_index;
+  if (LIKELY(IsAbstract())) {
+    return imt_index_;
   } else {
     return ImTable::GetImtIndex(this);
   }
@@ -426,7 +432,7 @@
 
 inline void ArtMethod::CalculateAndSetImtIndex() {
   DCHECK(IsAbstract()) << PrettyMethod();
-  imt_index_ = ~ImTable::GetImtIndex(this);
+  imt_index_ = ImTable::GetImtIndex(this);
 }
 
 }  // namespace art
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index d0b6fde..89dc93b 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -26,7 +26,7 @@
 #include "base/enums.h"
 #include "base/stl_util.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "debugger.h"
 #include "dex/class_accessor-inl.h"
 #include "dex/descriptors_names.h"
@@ -63,7 +63,7 @@
 extern "C" void art_quick_invoke_static_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*,
                                              const char*);
 
-// Enforce that we he have the right index for runtime methods.
+// Enforce that we have the right index for runtime methods.
 static_assert(ArtMethod::kRuntimeMethodDexMethodIndex == dex::kDexNoIndex,
               "Wrong runtime-method dex method index");
 
@@ -94,11 +94,14 @@
 }
 
 ArtMethod* ArtMethod::GetSingleImplementation(PointerSize pointer_size) {
-  if (!IsAbstract()) {
-    // A non-abstract's single implementation is itself.
+  if (IsInvokable()) {
+    // An invokable method single implementation is itself.
     return this;
   }
-  return reinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size));
+  DCHECK(!IsDefaultConflicting());
+  ArtMethod* m = reinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size));
+  CHECK(m == nullptr || !m->IsDefaultConflicting());
+  return m;
 }
 
 ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
@@ -149,8 +152,6 @@
 
 void ArtMethod::ThrowInvocationTimeError() {
   DCHECK(!IsInvokable());
-  // NOTE: IsDefaultConflicting must be first since the actual method might or might not be abstract
-  //       due to the way we select it.
   if (IsDefaultConflicting()) {
     ThrowIncompatibleClassChangeErrorForMethodConflict(this);
   } else {
@@ -167,7 +168,7 @@
     return kInterface;
   } else if (IsDirect()) {
     return kDirect;
-  } else if (IsPolymorphicSignature()) {
+  } else if (IsSignaturePolymorphic()) {
     return kPolymorphic;
   } else {
     return kVirtual;
@@ -392,29 +393,11 @@
   self->PopManagedStackFragment(fragment);
 }
 
-const void* ArtMethod::RegisterNative(const void* native_method) {
-  CHECK(IsNative()) << PrettyMethod();
-  CHECK(native_method != nullptr) << PrettyMethod();
-  void* new_native_method = nullptr;
-  Runtime::Current()->GetRuntimeCallbacks()->RegisterNativeMethod(this,
-                                                                  native_method,
-                                                                  /*out*/&new_native_method);
-  SetEntryPointFromJni(new_native_method);
-  return new_native_method;
-}
-
-void ArtMethod::UnregisterNative() {
-  CHECK(IsNative()) << PrettyMethod();
-  // restore stub to lookup native pointer via dlsym
-  SetEntryPointFromJni(
-      IsCriticalNative() ? GetJniDlsymLookupCriticalStub() : GetJniDlsymLookupStub());
-}
-
 bool ArtMethod::IsOverridableByDefaultMethod() {
   return GetDeclaringClass()->IsInterface();
 }
 
-bool ArtMethod::IsPolymorphicSignature() {
+bool ArtMethod::IsSignaturePolymorphic() {
   // Methods with a polymorphic signature have constraints that they
   // are native and varargs and belong to either MethodHandle or VarHandle.
   if (!IsNative() || !IsVarargs()) {
@@ -552,33 +535,6 @@
   return true;
 }
 
-ArrayRef<const uint8_t> ArtMethod::GetQuickenedInfo() {
-  const DexFile& dex_file = *GetDexFile();
-  const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
-  if (oat_dex_file == nullptr) {
-    return ArrayRef<const uint8_t>();
-  }
-  return oat_dex_file->GetQuickenedInfoOf(dex_file, GetDexMethodIndex());
-}
-
-uint16_t ArtMethod::GetIndexFromQuickening(uint32_t dex_pc) {
-  ArrayRef<const uint8_t> data = GetQuickenedInfo();
-  if (data.empty()) {
-    return DexFile::kDexNoIndex16;
-  }
-  QuickenInfoTable table(data);
-  uint32_t quicken_index = 0;
-  for (const DexInstructionPcPair& pair : DexInstructions()) {
-    if (pair.DexPc() == dex_pc) {
-      return table.GetData(quicken_index);
-    }
-    if (QuickenInfoTable::NeedsIndexForInstruction(&pair.Inst())) {
-      ++quicken_index;
-    }
-  }
-  return DexFile::kDexNoIndex16;
-}
-
 const OatQuickMethodHeader* ArtMethod::GetOatQuickMethodHeader(uintptr_t pc) {
   // Our callers should make sure they don't pass the instrumentation exit pc,
   // as this method does not look at the side instrumentation stack.
@@ -646,7 +602,10 @@
       DCHECK(class_linker->IsQuickGenericJniStub(existing_entry_point) ||
              class_linker->IsQuickResolutionStub(existing_entry_point) ||
              existing_entry_point == GetQuickInstrumentationEntryPoint() ||
-             (jit != nullptr && jit->GetCodeCache()->ContainsPc(existing_entry_point)));
+             (jit != nullptr && jit->GetCodeCache()->ContainsPc(existing_entry_point)))
+          << " entrypoint: " << existing_entry_point
+          << " size: " << OatQuickMethodHeader::FromEntryPoint(existing_entry_point)->GetCodeSize()
+          << " pc: " << reinterpret_cast<const void*>(pc);
       return nullptr;
     }
     // Only for unit tests.
@@ -780,9 +739,17 @@
           image_pointer_size);
     }
   }
-  // Clear the profiling info for the same reasons as the JIT code.
-  if (!src->IsNative()) {
-    SetProfilingInfoPtrSize(nullptr, image_pointer_size);
+  if (interpreter::IsNterpSupported() &&
+      (GetEntryPointFromQuickCompiledCodePtrSize(image_pointer_size) ==
+          interpreter::GetNterpEntryPoint())) {
+    // If the entrypoint is nterp, it's too early to check if the new method
+    // will support it. So for simplicity, use the interpreter bridge.
+    SetEntryPointFromQuickCompiledCodePtrSize(GetQuickToInterpreterBridge(), image_pointer_size);
+  }
+
+  // Clear the data pointer, it will be set if needed by the caller.
+  if (!src->HasCodeItem() && !src->IsNative()) {
+    SetDataPtrSize(nullptr, image_pointer_size);
   }
   // Clear hotness to let the JIT properly decide when to compile this method.
   hotness_count_ = 0;
@@ -876,6 +843,15 @@
   }
 }
 
+void ArtMethod::SetCodeItem(const dex::CodeItem* code_item) {
+  DCHECK(HasCodeItem());
+  // We mark the lowest bit for the interpreter to know whether it's executing a
+  // method in a compact or standard dex file.
+  uintptr_t data =
+      reinterpret_cast<uintptr_t>(code_item) | (GetDexFile()->IsCompactDexFile() ? 1 : 0);
+  SetDataPtrSize(reinterpret_cast<void*>(data), kRuntimePointerSize);
+}
+
 // AssertSharedHeld doesn't work in GetAccessFlags, so use a NO_THREAD_SAFETY_ANALYSIS helper.
 // TODO: Figure out why ASSERT_SHARED_CAPABILITY doesn't work.
 template <ReadBarrierOption kReadBarrierOption>
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 70d8d15..44a2f3d 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -78,7 +78,7 @@
   // constexpr, and ensure that the value is correct in art_method.cc.
   static constexpr uint32_t kRuntimeMethodDexMethodIndex = 0xFFFFFFFF;
 
-  ArtMethod() : access_flags_(0), dex_code_item_offset_(0), dex_method_index_(0),
+  ArtMethod() : access_flags_(0), dex_method_index_(0),
       method_index_(0), hotness_count_(0) { }
 
   ArtMethod(ArtMethod* src, PointerSize image_pointer_size) {
@@ -192,9 +192,11 @@
   void SetNotIntrinsic() REQUIRES_SHARED(Locks::mutator_lock_);
 
   bool IsCopied() const {
-    static_assert((kAccCopied & (kAccIntrinsic | kAccIntrinsicBits)) == 0,
-                  "kAccCopied conflicts with intrinsic modifier");
-    const bool copied = (GetAccessFlags() & kAccCopied) != 0;
+    // We do not have intrinsics for any default methods and therefore intrinsics are never copied.
+    // So we are using a flag from the intrinsic flags range and need to check `kAccIntrinsic` too.
+    static_assert((kAccCopied & kAccIntrinsicBits) != 0,
+                  "kAccCopied deliberately overlaps intrinsic bits");
+    const bool copied = (GetAccessFlags() & (kAccIntrinsic | kAccCopied)) == kAccCopied;
     // (IsMiranda() || IsDefaultConflicting()) implies copied
     DCHECK(!(IsMiranda() || IsDefaultConflicting()) || copied)
         << "Miranda or default-conflict methods must always be copied.";
@@ -202,24 +204,41 @@
   }
 
   bool IsMiranda() const {
-    // The kAccMiranda flag value is used with a different meaning for native methods and methods
-    // marked kAccCompileDontBother, so we need to check these flags as well.
-    return (GetAccessFlags() & (kAccNative | kAccMiranda | kAccCompileDontBother)) == kAccMiranda;
+    // Miranda methods are marked as copied and abstract but not default.
+    // We need to check the kAccIntrinsic too, see `IsCopied()`.
+    static constexpr uint32_t kMask = kAccIntrinsic | kAccCopied | kAccAbstract | kAccDefault;
+    static constexpr uint32_t kValue = kAccCopied | kAccAbstract;
+    return (GetAccessFlags() & kMask) == kValue;
+  }
+
+  // A default conflict method is a special sentinel method that stands for a conflict between
+  // multiple default methods. It cannot be invoked, throwing an IncompatibleClassChangeError
+  // if one attempts to do so.
+  bool IsDefaultConflicting() const {
+    // Default conflct methods are marked as copied, abstract and default.
+    // We need to check the kAccIntrinsic too, see `IsCopied()`.
+    static constexpr uint32_t kMask = kAccIntrinsic | kAccCopied | kAccAbstract | kAccDefault;
+    static constexpr uint32_t kValue = kAccCopied | kAccAbstract | kAccDefault;
+    return (GetAccessFlags() & kMask) == kValue;
   }
 
   // Returns true if invoking this method will not throw an AbstractMethodError or
   // IncompatibleClassChangeError.
   bool IsInvokable() const {
-    return !IsAbstract() && !IsDefaultConflicting();
+    // Default conflicting methods are marked with `kAccAbstract` (as well as `kAccCopied`
+    // and `kAccDefault`) but they are not considered abstract, see `IsAbstract()`.
+    DCHECK_EQ((GetAccessFlags() & kAccAbstract) == 0, !IsDefaultConflicting() && !IsAbstract());
+    return (GetAccessFlags() & kAccAbstract) == 0;
   }
 
   bool IsPreCompiled() const {
-    if (IsIntrinsic()) {
-      // kAccCompileDontBother overlaps with kAccIntrinsicBits.
-      return false;
-    }
-    uint32_t expected = (kAccPreCompiled | kAccCompileDontBother);
-    return (GetAccessFlags() & expected) == expected;
+    // kAccCompileDontBother and kAccPreCompiled overlap with kAccIntrinsicBits.
+    // Intrinsics should be compiled in primary boot image, not pre-compiled by JIT.
+    static_assert((kAccCompileDontBother & kAccIntrinsicBits) != 0);
+    static_assert((kAccPreCompiled & kAccIntrinsicBits) != 0);
+    static constexpr uint32_t kMask = kAccIntrinsic | kAccCompileDontBother | kAccPreCompiled;
+    static constexpr uint32_t kValue = kAccCompileDontBother | kAccPreCompiled;
+    return (GetAccessFlags() & kMask) == kValue;
   }
 
   void SetPreCompiled() REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -253,16 +272,6 @@
     AddAccessFlags(kAccCompileDontBother);
   }
 
-  // A default conflict method is a special sentinel method that stands for a conflict between
-  // multiple default methods. It cannot be invoked, throwing an IncompatibleClassChangeError if one
-  // attempts to do so.
-  bool IsDefaultConflicting() const {
-    if (IsIntrinsic()) {
-      return false;
-    }
-    return (GetAccessFlags() & kAccDefaultConflict) != 0u;
-  }
-
   // This is set by the class linker.
   bool IsDefault() const {
     static_assert((kAccDefault & (kAccIntrinsic | kAccIntrinsicBits)) == 0,
@@ -301,7 +310,8 @@
   }
 
   bool IsAbstract() const {
-    return (GetAccessFlags() & kAccAbstract) != 0;
+    // Default confliciting methods have `kAccAbstract` set but they are not actually abstract.
+    return (GetAccessFlags() & kAccAbstract) != 0 && !IsDefaultConflicting();
   }
 
   bool IsSynthetic() const {
@@ -314,7 +324,7 @@
 
   bool IsProxyMethod() REQUIRES_SHARED(Locks::mutator_lock_);
 
-  bool IsPolymorphicSignature() REQUIRES_SHARED(Locks::mutator_lock_);
+  bool IsSignaturePolymorphic() REQUIRES_SHARED(Locks::mutator_lock_);
 
   bool UseFastInterpreterToInterpreterInvoke() const {
     // The bit is applicable only if the method is not intrinsic.
@@ -351,11 +361,9 @@
   }
 
   bool PreviouslyWarm() const {
-    if (IsIntrinsic()) {
-      // kAccPreviouslyWarm overlaps with kAccIntrinsicBits.
-      return true;
-    }
-    return (GetAccessFlags() & kAccPreviouslyWarm) != 0;
+    // kAccPreviouslyWarm overlaps with kAccIntrinsicBits. Return true for intrinsics.
+    constexpr uint32_t mask = kAccPreviouslyWarm | kAccIntrinsic;
+    return (GetAccessFlags() & mask) != 0u;
   }
 
   void SetPreviouslyWarm() REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -384,6 +392,20 @@
     ClearAccessFlags(kAccSkipAccessChecks);
   }
 
+  bool HasNterpEntryPointFastPathFlag() const {
+    constexpr uint32_t mask = kAccNative | kAccNterpEntryPointFastPathFlag;
+    return (GetAccessFlags() & mask) == kAccNterpEntryPointFastPathFlag;
+  }
+
+  void SetNterpEntryPointFastPathFlag() REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK(!IsNative());
+    AddAccessFlags(kAccNterpEntryPointFastPathFlag);
+  }
+
+  void SetNterpInvokeFastPathFlag() REQUIRES_SHARED(Locks::mutator_lock_) {
+    AddAccessFlags(kAccNterpInvokeFastPathFlag);
+  }
+
   // Returns true if this method could be overridden by a default method.
   bool IsOverridableByDefaultMethod() REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -419,15 +441,6 @@
     return MemberOffset(OFFSETOF_MEMBER(ArtMethod, imt_index_));
   }
 
-  uint32_t GetCodeItemOffset() const {
-    return dex_code_item_offset_;
-  }
-
-  void SetCodeItemOffset(uint32_t new_code_off) REQUIRES_SHARED(Locks::mutator_lock_) {
-    // Not called within a transaction.
-    dex_code_item_offset_ = new_code_off;
-  }
-
   // Number of 32bit registers that would be required to hold all the arguments
   static size_t NumArgRegisters(const char* shorty);
 
@@ -489,13 +502,6 @@
     ClearFastInterpreterToInterpreterInvokeFlag();
   }
 
-  // Registers the native method and returns the new entry point. NB The returned entry point might
-  // be different from the native_method argument if some MethodCallback modifies it.
-  const void* RegisterNative(const void* native_method)
-      REQUIRES_SHARED(Locks::mutator_lock_) WARN_UNUSED;
-
-  void UnregisterNative() REQUIRES_SHARED(Locks::mutator_lock_);
-
   static constexpr MemberOffset DataOffset(PointerSize pointer_size) {
     return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
         PtrSizedFields, data_) / sizeof(void*) * static_cast<size_t>(pointer_size));
@@ -522,27 +528,6 @@
     SetDataPtrSize(table, pointer_size);
   }
 
-  ProfilingInfo* GetProfilingInfo(PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (UNLIKELY(IsNative() || IsProxyMethod() || !IsInvokable())) {
-      return nullptr;
-    }
-    return reinterpret_cast<ProfilingInfo*>(GetDataPtrSize(pointer_size));
-  }
-
-  ALWAYS_INLINE void SetProfilingInfo(ProfilingInfo* info) REQUIRES_SHARED(Locks::mutator_lock_) {
-    SetDataPtrSize(info, kRuntimePointerSize);
-  }
-
-  ALWAYS_INLINE void SetProfilingInfoPtrSize(ProfilingInfo* info, PointerSize pointer_size)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    SetDataPtrSize(info, pointer_size);
-  }
-
-  static MemberOffset ProfilingInfoOffset() {
-    DCHECK(IsImagePointerSize(kRuntimePointerSize));
-    return DataOffset(kRuntimePointerSize);
-  }
-
   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
   ALWAYS_INLINE bool HasSingleImplementation() REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -587,7 +572,9 @@
 
   void SetEntryPointFromJni(const void* entrypoint)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(IsNative());
+    // The resolution method also has a JNI entrypoint for direct calls from
+    // compiled code to the JNI dlsym lookup stub for @CriticalNative.
+    DCHECK(IsNative() || IsRuntimeMethod());
     SetEntryPointFromJniPtrSize(entrypoint, kRuntimePointerSize);
   }
 
@@ -613,6 +600,12 @@
     return dex_method_index_ == kRuntimeMethodDexMethodIndex;
   }
 
+  bool HasCodeItem() REQUIRES_SHARED(Locks::mutator_lock_) {
+    return !IsRuntimeMethod() && !IsNative() && !IsProxyMethod() && !IsAbstract();
+  }
+
+  void SetCodeItem(const dex::CodeItem* code_item) REQUIRES_SHARED(Locks::mutator_lock_);
+
   // Is this a hand crafted method used for something like describing callee saves?
   bool IsCalleeSaveMethod() REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -711,9 +704,9 @@
   void CopyFrom(ArtMethod* src, PointerSize image_pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE void SetCounter(uint16_t hotness_count) REQUIRES_SHARED(Locks::mutator_lock_);
+  ALWAYS_INLINE void SetCounter(uint16_t hotness_count);
 
-  ALWAYS_INLINE uint16_t GetCounter() REQUIRES_SHARED(Locks::mutator_lock_);
+  ALWAYS_INLINE uint16_t GetCounter();
 
   ALWAYS_INLINE static constexpr uint16_t MaxCounter() {
     return std::numeric_limits<decltype(hotness_count_)>::max();
@@ -727,9 +720,6 @@
     return MemberOffset(OFFSETOF_MEMBER(ArtMethod, hotness_count_));
   }
 
-  ArrayRef<const uint8_t> GetQuickenedInfo() REQUIRES_SHARED(Locks::mutator_lock_);
-  uint16_t GetIndexFromQuickening(uint32_t dex_pc) REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Returns the method header for the compiled code containing 'pc'. Note that runtime
   // methods will return null for this method, as they are not oat based.
   const OatQuickMethodHeader* GetOatQuickMethodHeader(uintptr_t pc)
@@ -768,7 +758,6 @@
     DCHECK(IsImagePointerSize(kRuntimePointerSize));
     visitor(this, &declaring_class_, "declaring_class_");
     visitor(this, &access_flags_, "access_flags_");
-    visitor(this, &dex_code_item_offset_, "dex_code_item_offset_");
     visitor(this, &dex_method_index_, "dex_method_index_");
     visitor(this, &method_index_, "method_index_");
     visitor(this, &hotness_count_, "hotness_count_");
@@ -808,9 +797,6 @@
 
   /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */
 
-  // Offset to the CodeItem.
-  uint32_t dex_code_item_offset_;
-
   // Index into method_ids of the dex file associated with this method.
   uint32_t dex_method_index_;
 
@@ -825,8 +811,7 @@
     // Non-abstract methods: The hotness we measure for this method. Not atomic,
     // as we allow missing increments: if the method is hot, we will see it eventually.
     uint16_t hotness_count_;
-    // Abstract methods: IMT index (bitwise negated) or zero if it was not cached.
-    // The negation is needed to distinguish zero index and missing cached entry.
+    // Abstract methods: IMT index.
     uint16_t imt_index_;
   };
 
@@ -837,10 +822,13 @@
     // Depending on the method type, the data is
     //   - native method: pointer to the JNI function registered to this method
     //                    or a function to resolve the JNI function,
+    //   - resolution method: pointer to a function to resolve the method and
+    //                        the JNI function for @CriticalNative.
     //   - conflict method: ImtConflictTable,
     //   - abstract/interface method: the single-implementation if any,
     //   - proxy method: the original interface method or constructor,
-    //   - other methods: the profiling data.
+    //   - other methods: during AOT the code item offset, at runtime a pointer
+    //                    to the code item.
     void* data_;
 
     // Method dispatch from quick compiled code invokes this pointer which may cause bridging into
diff --git a/runtime/art_standalone_runtime_compiler_tests.xml b/runtime/art_standalone_runtime_compiler_tests.xml
new file mode 100644
index 0000000..0f6bb4b
--- /dev/null
+++ b/runtime/art_standalone_runtime_compiler_tests.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs art_standalone_runtime_compiler_tests.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art_standalone_runtime_compiler_tests->/data/local/tmp/nativetest/art_standalone_runtime_compiler_tests" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/nativetest/art-gtest-jars-Main.jar" />
+        <option name="push" value="art-gtest-jars-NonStaticLeafMethods.jar->/data/local/tmp/nativetest/art-gtest-jars-NonStaticLeafMethods.jar" />
+        <option name="push" value="art-gtest-jars-StaticLeafMethods.jar->/data/local/tmp/nativetest/art-gtest-jars-StaticLeafMethods.jar" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/nativetest" />
+        <option name="module-name" value="art_standalone_runtime_compiler_tests" />
+        <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+        <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/runtime/art_standalone_runtime_tests.xml b/runtime/art_standalone_runtime_tests.xml
new file mode 100644
index 0000000..1267213
--- /dev/null
+++ b/runtime/art_standalone_runtime_tests.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs art_standalone_runtime_tests.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art_standalone_runtime_tests->/data/local/tmp/nativetest/art_standalone_runtime_tests" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="art-gtest-jars-AllFields.jar->/data/local/tmp/nativetest/art-gtest-jars-AllFields.jar" />
+        <option name="push" value="art-gtest-jars-ErroneousA.jar->/data/local/tmp/nativetest/art-gtest-jars-ErroneousA.jar" />
+        <option name="push" value="art-gtest-jars-ErroneousB.jar->/data/local/tmp/nativetest/art-gtest-jars-ErroneousB.jar" />
+        <option name="push" value="art-gtest-jars-ErroneousInit.jar->/data/local/tmp/nativetest/art-gtest-jars-ErroneousInit.jar" />
+        <option name="push" value="art-gtest-jars-Extension1.jar->/data/local/tmp/nativetest/art-gtest-jars-Extension1.jar" />
+        <option name="push" value="art-gtest-jars-Extension2.jar->/data/local/tmp/nativetest/art-gtest-jars-Extension2.jar" />
+        <option name="push" value="art-gtest-jars-ForClassLoaderA.jar->/data/local/tmp/nativetest/art-gtest-jars-ForClassLoaderA.jar" />
+        <option name="push" value="art-gtest-jars-ForClassLoaderB.jar->/data/local/tmp/nativetest/art-gtest-jars-ForClassLoaderB.jar" />
+        <option name="push" value="art-gtest-jars-ForClassLoaderC.jar->/data/local/tmp/nativetest/art-gtest-jars-ForClassLoaderC.jar" />
+        <option name="push" value="art-gtest-jars-ForClassLoaderD.jar->/data/local/tmp/nativetest/art-gtest-jars-ForClassLoaderD.jar" />
+        <option name="push" value="art-gtest-jars-HiddenApiSignatures.jar->/data/local/tmp/nativetest/art-gtest-jars-HiddenApiSignatures.jar" />
+        <option name="push" value="art-gtest-jars-IMTA.jar->/data/local/tmp/nativetest/art-gtest-jars-IMTA.jar" />
+        <option name="push" value="art-gtest-jars-IMTB.jar->/data/local/tmp/nativetest/art-gtest-jars-IMTB.jar" />
+        <option name="push" value="art-gtest-jars-Instrumentation.jar->/data/local/tmp/nativetest/art-gtest-jars-Instrumentation.jar" />
+        <option name="push" value="art-gtest-jars-Interfaces.jar->/data/local/tmp/nativetest/art-gtest-jars-Interfaces.jar" />
+        <option name="push" value="art-gtest-jars-LinkageTest.dex->/data/local/tmp/nativetest/art-gtest-jars-LinkageTest.dex" />
+        <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/nativetest/art-gtest-jars-Main.jar" />
+        <option name="push" value="art-gtest-jars-MainStripped.jar->/data/local/tmp/nativetest/art-gtest-jars-MainStripped.jar" />
+        <option name="push" value="art-gtest-jars-MainUncompressedAligned.jar->/data/local/tmp/nativetest/art-gtest-jars-MainUncompressedAligned.jar" />
+        <option name="push" value="art-gtest-jars-MethodTypes.jar->/data/local/tmp/nativetest/art-gtest-jars-MethodTypes.jar" />
+        <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/nativetest/art-gtest-jars-MultiDex.jar" />
+        <option name="push" value="art-gtest-jars-MultiDexModifiedSecondary.jar->/data/local/tmp/nativetest/art-gtest-jars-MultiDexModifiedSecondary.jar" />
+        <option name="push" value="art-gtest-jars-MultiDexUncompressedAligned.jar->/data/local/tmp/nativetest/art-gtest-jars-MultiDexUncompressedAligned.jar" />
+        <option name="push" value="art-gtest-jars-MyClass.jar->/data/local/tmp/nativetest/art-gtest-jars-MyClass.jar" />
+        <option name="push" value="art-gtest-jars-MyClassNatives.jar->/data/local/tmp/nativetest/art-gtest-jars-MyClassNatives.jar" />
+        <option name="push" value="art-gtest-jars-Nested.jar->/data/local/tmp/nativetest/art-gtest-jars-Nested.jar" />
+        <option name="push" value="art-gtest-jars-Packages.jar->/data/local/tmp/nativetest/art-gtest-jars-Packages.jar" />
+        <option name="push" value="art-gtest-jars-ProfileTestMultiDex.jar->/data/local/tmp/nativetest/art-gtest-jars-ProfileTestMultiDex.jar" />
+        <option name="push" value="art-gtest-jars-ProtoCompare.jar->/data/local/tmp/nativetest/art-gtest-jars-ProtoCompare.jar" />
+        <option name="push" value="art-gtest-jars-ProtoCompare2.jar->/data/local/tmp/nativetest/art-gtest-jars-ProtoCompare2.jar" />
+        <option name="push" value="art-gtest-jars-StaticLeafMethods.jar->/data/local/tmp/nativetest/art-gtest-jars-StaticLeafMethods.jar" />
+        <option name="push" value="art-gtest-jars-Statics.jar->/data/local/tmp/nativetest/art-gtest-jars-Statics.jar" />
+        <option name="push" value="art-gtest-jars-StaticsFromCode.jar->/data/local/tmp/nativetest/art-gtest-jars-StaticsFromCode.jar" />
+        <option name="push" value="art-gtest-jars-Transaction.jar->/data/local/tmp/nativetest/art-gtest-jars-Transaction.jar" />
+        <option name="push" value="art-gtest-jars-VerifierDeps.dex->/data/local/tmp/nativetest/art-gtest-jars-VerifierDeps.dex" />
+        <option name="push" value="art-gtest-jars-VerifierDepsMulti.dex->/data/local/tmp/nativetest/art-gtest-jars-VerifierDepsMulti.dex" />
+        <option name="push" value="art-gtest-jars-XandY.jar->/data/local/tmp/nativetest/art-gtest-jars-XandY.jar" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/nativetest" />
+        <option name="module-name" value="art_standalone_runtime_tests" />
+        <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+        <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+
+        <!-- The following tests from `art_standalone_runtime_tests` are currently failing
+             (observed on `aosp_cf_x86_64_phone-userdebug`).
+
+              TODO(b/162834439): Investigate these failures and re-enable these tests. -->
+        <option name="exclude-filter" value="HiddenApiTest.DexDomain_SystemDir" />
+        <option name="exclude-filter" value="HiddenApiTest.DexDomain_SystemDir_MultiDex" />
+        <option name="exclude-filter" value="HiddenApiTest.DexDomain_SystemFrameworkDir" />
+        <option name="exclude-filter" value="HiddenApiTest.DexDomain_SystemFrameworkDir_MultiDex" />
+        <option name="exclude-filter" value="HiddenApiTest.DexDomain_SystemSystemExtDir" />
+        <option name="exclude-filter" value="HiddenApiTest.DexDomain_SystemSystemExtDir_MultiDex" />
+        <option name="exclude-filter" value="HiddenApiTest.DexDomain_SystemSystemExtFrameworkDir" />
+        <option name="exclude-filter" value="HiddenApiTest.DexDomain_SystemSystemExtFrameworkDir_MultiDex" />
+        <option name="exclude-filter" value="JniInternalTest.CallVarArgMethodBadPrimitive" />
+        <option name="exclude-filter" value="OatFileAssistantTest.SystemFrameworkDir" />
+        <option name="exclude-filter" value="StubTest.Fields16" />
+        <option name="exclude-filter" value="StubTest.Fields32" />
+        <option name="exclude-filter" value="StubTest.Fields64" />
+        <option name="exclude-filter" value="StubTest.Fields8" />
+        <option name="exclude-filter" value="StubTest.FieldsObj" />
+        <option name="exclude-filter" value="SubtypeCheckInfoTest.IllegalValues" />
+
+        <!-- The following tests from `art_standalone_runtime_tests` are currently failing when
+             run as 32-bit on a 64-bit device, because they try to execute other system (64-bit)
+             processes but `LD_LIBRARY_PATH` is set to a directory of 32-bit libraries which make
+             them fail to dynamically link to the expected (64-bit) libraries.
+
+             TODO(b/162834439): Investigate these failures and re-enable these tests. -->
+        <option name="exclude-filter" value="ExecUtilsTest.EnvSnapshotDeletionsAreNotVisible" />
+        <option name="exclude-filter" value="ExecUtilsTest.ExecNoTimeout" />
+        <option name="exclude-filter" value="ExecUtilsTest.ExecSuccess" />
+        <option name="exclude-filter" value="ExecUtilsTest.ExecTimeout" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/runtime/backtrace_helper.cc b/runtime/backtrace_helper.cc
index 2d39270..994b0fa 100644
--- a/runtime/backtrace_helper.cc
+++ b/runtime/backtrace_helper.cc
@@ -20,6 +20,7 @@
 
 #include <sys/types.h>
 #include <unistd.h>
+#include <iomanip>
 
 #include "unwindstack/Regs.h"
 #include "unwindstack/RegsGetLocal.h"
@@ -43,23 +44,29 @@
 // gcstress this isn't a huge deal.
 #if defined(__linux__)
 
+// Strict integrity check of the backtrace:
+// All methods must have a name, all the way to "main".
+static constexpr bool kStrictUnwindChecks = true;
+
 struct UnwindHelper : public TLSData {
   static constexpr const char* kTlsKey = "UnwindHelper::kTlsKey";
 
   explicit UnwindHelper(size_t max_depth)
-      : memory_(unwindstack::Memory::CreateProcessMemory(getpid())),
-        jit_(memory_),
-        dex_(memory_),
+      : arch_(unwindstack::Regs::CurrentArch()),
+        memory_(unwindstack::Memory::CreateProcessMemoryThreadCached(getpid())),
+        jit_(unwindstack::CreateJitDebug(arch_, memory_)),
+        dex_(unwindstack::CreateDexFiles(arch_, memory_)),
         unwinder_(max_depth, &maps_, memory_) {
     CHECK(maps_.Parse());
-    unwinder_.SetJitDebug(&jit_, unwindstack::Regs::CurrentArch());
-    unwinder_.SetDexFiles(&dex_, unwindstack::Regs::CurrentArch());
-    unwinder_.SetResolveNames(false);
+    unwinder_.SetArch(arch_);
+    unwinder_.SetJitDebug(jit_.get());
+    unwinder_.SetDexFiles(dex_.get());
+    unwinder_.SetResolveNames(kStrictUnwindChecks);
     unwindstack::Elf::SetCachingEnabled(true);
   }
 
   // Reparse process mmaps to detect newly loaded libraries.
-  bool Reparse() { return maps_.Reparse(); }
+  bool Reparse(bool* any_changed) { return maps_.Reparse(any_changed); }
 
   static UnwindHelper* Get(Thread* self, size_t max_depth) {
     UnwindHelper* tls = reinterpret_cast<UnwindHelper*>(self->GetCustomTLS(kTlsKey));
@@ -74,24 +81,38 @@
 
  private:
   unwindstack::LocalUpdatableMaps maps_;
+  unwindstack::ArchEnum arch_;
   std::shared_ptr<unwindstack::Memory> memory_;
-  unwindstack::JitDebug jit_;
-  unwindstack::DexFiles dex_;
+  std::unique_ptr<unwindstack::JitDebug> jit_;
+  std::unique_ptr<unwindstack::DexFiles> dex_;
   unwindstack::Unwinder unwinder_;
 };
 
 void BacktraceCollector::Collect() {
-  if (!CollectImpl()) {
-    // Reparse process mmaps to detect newly loaded libraries and retry.
-    UnwindHelper::Get(Thread::Current(), max_depth_)->Reparse();
-    if (!CollectImpl()) {
-      // Failed to unwind stack. Ignore for now.
+  unwindstack::Unwinder* unwinder = UnwindHelper::Get(Thread::Current(), max_depth_)->Unwinder();
+  if (!CollectImpl(unwinder)) {
+    // Reparse process mmaps to detect newly loaded libraries and retry,
+    // but only if any maps changed (we don't want to hide racy failures).
+    bool any_changed;
+    UnwindHelper::Get(Thread::Current(), max_depth_)->Reparse(&any_changed);
+    if (!any_changed || !CollectImpl(unwinder)) {
+      if (kStrictUnwindChecks) {
+        std::vector<unwindstack::FrameData>& frames = unwinder->frames();
+        LOG(ERROR) << "Failed to unwind stack (error " << unwinder->LastErrorCodeString() << "):";
+        for (auto it = frames.begin(); it != frames.end(); it++) {
+          if (it == frames.begin() || std::prev(it)->map_name != it->map_name) {
+            LOG(ERROR) << " in " << it->map_name.c_str();
+          }
+          LOG(ERROR) << " pc " << std::setw(8) << std::setfill('0') << std::hex <<
+            it->rel_pc << " " << it->function_name.c_str();
+        }
+        LOG(FATAL);
+      }
     }
   }
 }
 
-bool BacktraceCollector::CollectImpl() {
-  unwindstack::Unwinder* unwinder = UnwindHelper::Get(Thread::Current(), max_depth_)->Unwinder();
+bool BacktraceCollector::CollectImpl(unwindstack::Unwinder* unwinder) {
   std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
   RegsGetLocal(regs.get());
   unwinder->SetRegs(regs.get());
@@ -104,18 +125,28 @@
       out_frames_[num_frames_++] = static_cast<uintptr_t>(it->pc);
 
       // Expected early end: Instrumentation breaks unwinding (b/138296821).
-      size_t align = GetInstructionSetAlignment(kRuntimeISA);
-      if (RoundUp(it->pc, align) == reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc())) {
+      // Inexact compare because the unwinder does not give us exact return address,
+      // but rather it tries to guess the address of the preceding call instruction.
+      size_t exit_pc = reinterpret_cast<size_t>(GetQuickInstrumentationExitPc());
+      if (exit_pc - 4 <= it->pc && it->pc <= exit_pc) {
         return true;
       }
+
+      if (kStrictUnwindChecks) {
+        if (it->function_name.empty()) {
+          return false;
+        }
+        if (it->function_name == "main" ||
+            it->function_name == "start_thread" ||
+            it->function_name == "__start_thread") {
+          return true;
+        }
+      }
     }
   }
 
-  if (unwinder->LastErrorCode() == unwindstack::ERROR_INVALID_MAP) {
-    return false;
-  }
-
-  return true;
+  unwindstack::ErrorCode error = unwinder->LastErrorCode();
+  return error == unwindstack::ERROR_NONE || error == unwindstack::ERROR_MAX_FRAMES_EXCEEDED;
 }
 
 #else
diff --git a/runtime/backtrace_helper.h b/runtime/backtrace_helper.h
index 2fee62c..a74d0e0 100644
--- a/runtime/backtrace_helper.h
+++ b/runtime/backtrace_helper.h
@@ -20,6 +20,10 @@
 #include <stddef.h>
 #include <stdint.h>
 
+namespace unwindstack {
+class Unwinder;
+}
+
 namespace art {
 
 // Using libbacktrace
@@ -38,7 +42,7 @@
  private:
   // Try to collect backtrace. Returns false on failure.
   // It is used to retry backtrace on temporary failure.
-  bool CollectImpl();
+  bool CollectImpl(unwindstack::Unwinder* unwinder);
 
   uintptr_t* const out_frames_ = nullptr;
   size_t num_frames_ = 0u;
diff --git a/runtime/barrier.h b/runtime/barrier.h
index ad8f66f..432df76 100644
--- a/runtime/barrier.h
+++ b/runtime/barrier.h
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// CAUTION: THIS IS NOT A FULLY GENERAL BARRIER API.
+// CAUTION: THIS IS NOT A FULLY GENERAL BARRIER API. Some names are unconventional.
 
 // It may either be used as a "latch" or single-use barrier, or it may be reused under
 // very limited conditions, e.g. if only Pass(), but not Wait() is called.  Unlike a standard
@@ -22,7 +22,7 @@
 // Pass() or Wait(), and only then set the count using the Increment() method.  Threads at
 // a Wait() are only awoken if the count reaches zero AFTER the decrement is applied.
 // This works because, also unlike most latch APIs, there is no way to Wait() without
-// decrementing the count, and thus nobody can spuriosly wake up on the initial zero.
+// decrementing the count, and thus nobody can spuriously wake up on the initial zero.
 
 #ifndef ART_RUNTIME_BARRIER_H_
 #define ART_RUNTIME_BARRIER_H_
@@ -52,7 +52,7 @@
   // Pass through the barrier, decrement the count but do not block.
   void Pass(Thread* self) REQUIRES(!GetLock());
 
-  // Wait on the barrier, decrement the count.
+  // Decrement the count, then wait until the count is zero.
   void Wait(Thread* self) REQUIRES(!GetLock());
 
   // The following three calls are only safe if we somehow know that no other thread both
@@ -61,13 +61,13 @@
   // If these calls are made in that situation, the offending thread is likely to go back
   // to sleep, resulting in a deadlock.
 
-  // Increment the count by delta, wait on condition if count is non zero.  If LockHandling is
+  // Increment the count by delta, wait on condition while count is non zero.  If LockHandling is
   // kAllowHoldingLocks we will not check that all locks are released when waiting.
   template <Barrier::LockHandling locks = kDisallowHoldingLocks>
   void Increment(Thread* self, int delta) REQUIRES(!GetLock());
 
-  // Increment the count by delta, wait on condition if count is non zero, with a timeout. Returns
-  // true if time out occurred.
+  // Increment the count by delta, wait on condition while count is non zero, with a timeout.
+  // Returns true if time out occurred.
   bool Increment(Thread* self, int delta, uint32_t timeout_ms) REQUIRES(!GetLock());
 
   // Set the count to a new value.  This should only be used if there is no possibility that
diff --git a/runtime/base/callee_save_type.h b/runtime/base/callee_save_type.h
index e7cc7e6..fcafe9c 100644
--- a/runtime/base/callee_save_type.h
+++ b/runtime/base/callee_save_type.h
@@ -32,7 +32,7 @@
   kSaveEverythingForSuspendCheck,  // Special kSaveEverything for suspend check.
   kLastCalleeSaveType   // Value used for iteration.
 };
-std::ostream& operator<<(std::ostream& os, const CalleeSaveType& rhs);
+std::ostream& operator<<(std::ostream& os, CalleeSaveType rhs);
 
 static inline constexpr CalleeSaveType GetCanonicalCalleeSaveType(CalleeSaveType type) {
   if (type == CalleeSaveType::kSaveEverythingForClinit ||
diff --git a/runtime/base/locks.h b/runtime/base/locks.h
index c1667f3..7008539 100644
--- a/runtime/base/locks.h
+++ b/runtime/base/locks.h
@@ -150,7 +150,7 @@
 
   kLockLevelCount  // Must come last.
 };
-std::ostream& operator<<(std::ostream& os, const LockLevel& rhs);
+std::ostream& operator<<(std::ostream& os, LockLevel rhs);
 
 // For StartNoThreadSuspension and EndNoThreadSuspension.
 class CAPABILITY("role") Role {
diff --git a/runtime/base/message_queue.h b/runtime/base/message_queue.h
new file mode 100644
index 0000000..b0f1460
--- /dev/null
+++ b/runtime/base/message_queue.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2020 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_BASE_MESSAGE_QUEUE_H_
+#define ART_RUNTIME_BASE_MESSAGE_QUEUE_H_
+
+#include <deque>
+#include <optional>
+#include <variant>
+
+#include "base/time_utils.h"
+#include "mutex.h"
+#include "thread.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+namespace art {
+
+struct TimeoutExpiredMessage {};
+
+// MessageQueue is an unbounded multiple producer, multiple consumer (MPMC) queue that can be
+// specialized to send messages between threads. The queue is parameterized by a set of types that
+// serve as the message types. Note that messages are passed by value, so smaller messages should be
+// used when possible.
+//
+// Example:
+//
+//     struct IntMessage { int value; };
+//     struct DoubleMessage { double value; };
+//
+//     MessageQueue<IntMessage, DoubleMessage> queue;
+//
+//     queue.SendMessage(IntMessage{42});
+//     queue.SendMessage(DoubleMessage{42.0});
+//
+//     auto message = queue.ReceiveMessage();  // message is a std::variant of the different
+//                                             // message types.
+//
+//     if (std::holds_alternative<IntMessage>(message)) {
+//       cout << "Received int message with value " << std::get<IntMessage>(message) << "\n";
+//     }
+//
+// The message queue also supports a special timeout message. This is scheduled to be sent by the
+// SetTimeout method, which will cause the MessageQueue to deliver a TimeoutExpiredMessage after the
+// time period has elapsed. Note that only one timeout can be active can be active at a time, and
+// subsequent calls to SetTimeout will overwrite any existing timeout.
+//
+// Example:
+//
+//     queue.SetTimeout(5000);  // request to send TimeoutExpiredMessage in 5000ms.
+//
+//     auto message = queue.ReceiveMessage();  // blocks for 5000ms and returns
+//                                             // TimeoutExpiredMessage
+//
+// Note additional messages can be sent in the meantime and a ReceiveMessage call will wake up to
+// return that message. The TimeoutExpiredMessage will still be sent at the right time.
+//
+// Finally, MessageQueue has a SwitchReceive method that can be used to run different code depending
+// on the type of message received. SwitchReceive takes a set of lambda expressions that take one
+// argument of one of the allowed message types. An additional lambda expression that takes a single
+// auto argument can be used to serve as a catch-all case.
+//
+// Example:
+//
+//     queue.SwitchReceive(
+//       [&](IntMessage message) {
+//         cout << "Received int: " << message.value << "\n";
+//       },
+//       [&](DoubleMessage message) {
+//         cout << "Received double: " << message.value << "\n";
+//       },
+//       [&](auto other_message) {
+//         // Another message was received. In this case, it's TimeoutExpiredMessage.
+//       }
+//     )
+//
+// For additional examples, see message_queue_test.cc.
+template <typename... MessageTypes>
+class MessageQueue {
+ public:
+  using Message = std::variant<TimeoutExpiredMessage, MessageTypes...>;
+
+  // Adds a message to the message queue, which can later be received with ReceiveMessage. See class
+  // comment for more details.
+  void SendMessage(Message message) {
+    // TimeoutExpiredMessage should not be sent manually.
+    DCHECK(!std::holds_alternative<TimeoutExpiredMessage>(message));
+    Thread* self = Thread::Current();
+    MutexLock lock{self, mutex_};
+    messages_.push_back(message);
+    cv_.Signal(self);
+  }
+
+  // Schedule a TimeoutExpiredMessage to be delivered in timeout_milliseconds. See class comment for
+  // more details.
+  void SetTimeout(uint64_t timeout_milliseconds) {
+    Thread* self = Thread::Current();
+    MutexLock lock{self, mutex_};
+    deadline_milliseconds_ = timeout_milliseconds + MilliTime();
+    cv_.Signal(self);
+  }
+
+  // Remove and return a message from the queue. If no message is available, ReceiveMessage will
+  // block until one becomes available. See class comment for more details.
+  Message ReceiveMessage() {
+    Thread* self = Thread::Current();
+    MutexLock lock{self, mutex_};
+
+    // Loop until we receive a message
+    while (true) {
+      uint64_t const current_time = MilliTime();
+      // First check if the deadline has passed.
+      if (deadline_milliseconds_.has_value() && deadline_milliseconds_.value() < current_time) {
+        deadline_milliseconds_.reset();
+        return TimeoutExpiredMessage{};
+      }
+
+      // Check if there is a message in the queue.
+      if (messages_.size() > 0) {
+        Message message = messages_.front();
+        messages_.pop_front();
+        return message;
+      }
+
+      // Otherwise, wait until we have a message or a timeout.
+      if (deadline_milliseconds_.has_value()) {
+        DCHECK_LE(current_time, deadline_milliseconds_.value());
+        int64_t timeout = static_cast<int64_t>(deadline_milliseconds_.value() - current_time);
+        cv_.TimedWait(self, timeout, /*ns=*/0);
+      } else {
+        cv_.Wait(self);
+      }
+    }
+  }
+
+  // Waits for a message and applies the appropriate function argument to the received message. See
+  // class comment for more details.
+  template <typename ReturnType = void, typename... Fn>
+  ReturnType SwitchReceive(Fn... case_fn) {
+    struct Matcher : Fn... {
+      using Fn::operator()...;
+    } matcher{case_fn...};
+    return std::visit(matcher, ReceiveMessage());
+  }
+
+ private:
+  Mutex mutex_{"MessageQueue Mutex"};
+  ConditionVariable cv_{"MessageQueue ConditionVariable", mutex_};
+
+  std::deque<Message> messages_ GUARDED_BY(mutex_);
+  std::optional<uint64_t> deadline_milliseconds_ GUARDED_BY(mutex_);
+};
+
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
+
+#endif  // ART_RUNTIME_BASE_MESSAGE_QUEUE_H_
diff --git a/runtime/base/message_queue_test.cc b/runtime/base/message_queue_test.cc
new file mode 100644
index 0000000..7a788a9
--- /dev/null
+++ b/runtime/base/message_queue_test.cc
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2020 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 "message_queue.h"
+
+#include <thread>
+
+#include "common_runtime_test.h"
+#include "thread-current-inl.h"
+
+namespace art {
+
+class MessageQueueTest : public CommonRuntimeTest {};
+
+namespace {
+
+// Define some message types
+struct EmptyMessage {};
+struct IntMessage {
+  int value;
+};
+struct OtherIntMessage {
+  int other_value;
+};
+struct TwoIntMessage {
+  int value1;
+  int value2;
+};
+struct StringMessage {
+  std::string message;
+};
+
+using TestMessageQueue =
+    MessageQueue<EmptyMessage, IntMessage, OtherIntMessage, TwoIntMessage, StringMessage>;
+
+}  // namespace
+
+TEST_F(MessageQueueTest, SendReceiveTest) {
+  TestMessageQueue queue;
+
+  queue.SendMessage(EmptyMessage{});
+  ASSERT_TRUE(std::holds_alternative<EmptyMessage>(queue.ReceiveMessage()));
+
+  queue.SendMessage(IntMessage{42});
+  ASSERT_TRUE(std::holds_alternative<IntMessage>(queue.ReceiveMessage()));
+
+  queue.SendMessage(OtherIntMessage{43});
+  ASSERT_TRUE(std::holds_alternative<OtherIntMessage>(queue.ReceiveMessage()));
+
+  queue.SendMessage(TwoIntMessage{1, 2});
+  ASSERT_TRUE(std::holds_alternative<TwoIntMessage>(queue.ReceiveMessage()));
+
+  queue.SendMessage(StringMessage{"Hello, World!"});
+  ASSERT_TRUE(std::holds_alternative<StringMessage>(queue.ReceiveMessage()));
+}
+
+TEST_F(MessageQueueTest, TestTimeout) {
+  TestMessageQueue queue;
+
+  constexpr uint64_t kDuration = 500;
+
+  const auto start = MilliTime();
+  queue.SetTimeout(kDuration);
+  ASSERT_TRUE(std::holds_alternative<TimeoutExpiredMessage>(queue.ReceiveMessage()));
+  const auto elapsed = MilliTime() - start;
+
+  ASSERT_GT(elapsed, kDuration);
+}
+
+TEST_F(MessageQueueTest, TwoWayMessaging) {
+  TestMessageQueue queue1;
+  TestMessageQueue queue2;
+
+  std::thread thread{[&]() {
+    // Tell the parent thread we are running.
+    queue1.SendMessage(EmptyMessage{});
+
+    // Wait for a message from the parent thread.
+    queue2.ReceiveMessage();
+  }};
+
+  queue1.ReceiveMessage();
+  queue2.SendMessage(EmptyMessage{});
+
+  thread.join();
+}
+
+TEST_F(MessageQueueTest, SwitchReceiveTest) {
+  TestMessageQueue queue;
+
+  queue.SendMessage(EmptyMessage{});
+  queue.SendMessage(IntMessage{42});
+  queue.SendMessage(OtherIntMessage{43});
+  queue.SendMessage(TwoIntMessage{1, 2});
+  queue.SendMessage(StringMessage{"Hello, World!"});
+  queue.SetTimeout(500);
+
+  bool empty_received = false;
+  bool int_received = false;
+  bool other_int_received = false;
+  bool two_int_received = false;
+  bool string_received = false;
+  bool timeout_received = false;
+
+  while (!(empty_received && int_received && other_int_received && two_int_received &&
+           string_received && timeout_received)) {
+    queue.SwitchReceive(
+        [&]([[maybe_unused]] const EmptyMessage& message) {
+          ASSERT_FALSE(empty_received);
+          empty_received = true;
+        },
+        [&](const IntMessage& message) {
+          ASSERT_FALSE(int_received);
+          int_received = true;
+
+          ASSERT_EQ(message.value, 42);
+        },
+        [&](const OtherIntMessage& message) {
+          ASSERT_FALSE(other_int_received);
+          other_int_received = true;
+
+          ASSERT_EQ(message.other_value, 43);
+        },
+        // The timeout message is here to make sure the cases can go in any order
+        [&]([[maybe_unused]] const TimeoutExpiredMessage& message) {
+          ASSERT_FALSE(timeout_received);
+          timeout_received = true;
+        },
+        [&](const TwoIntMessage& message) {
+          ASSERT_FALSE(two_int_received);
+          two_int_received = true;
+
+          ASSERT_EQ(message.value1, 1);
+          ASSERT_EQ(message.value2, 2);
+        },
+        [&](const StringMessage& message) {
+          ASSERT_FALSE(string_received);
+          string_received = true;
+
+          ASSERT_EQ(message.message, "Hello, World!");
+        });
+  }
+}
+
+TEST_F(MessageQueueTest, SwitchReceiveAutoTest) {
+  TestMessageQueue queue;
+
+  queue.SendMessage(EmptyMessage{});
+  queue.SendMessage(IntMessage{42});
+  queue.SendMessage(OtherIntMessage{43});
+  queue.SendMessage(TwoIntMessage{1, 2});
+  queue.SendMessage(StringMessage{"Hello, World!"});
+  queue.SetTimeout(500);
+
+  int pending_messages = 6;
+
+  while (pending_messages > 0) {
+    queue.SwitchReceive([&]([[maybe_unused]] auto message) { pending_messages--; });
+  }
+}
+
+TEST_F(MessageQueueTest, SwitchReceivePartialAutoTest) {
+  TestMessageQueue queue;
+
+  queue.SendMessage(EmptyMessage{});
+  queue.SendMessage(IntMessage{42});
+  queue.SendMessage(OtherIntMessage{43});
+  queue.SendMessage(TwoIntMessage{1, 2});
+  queue.SendMessage(StringMessage{"Hello, World!"});
+  queue.SetTimeout(500);
+
+  bool running = true;
+  while (running) {
+    queue.SwitchReceive(
+        [&](const StringMessage& message) {
+          ASSERT_EQ(message.message, "Hello, World!");
+          running = false;
+        },
+        [&]([[maybe_unused]] const auto& message) {
+          const bool is_string{std::is_same<StringMessage, decltype(message)>()};
+          ASSERT_FALSE(is_string);
+        });
+  }
+}
+
+TEST_F(MessageQueueTest, SwitchReceiveReturn) {
+  TestMessageQueue queue;
+
+  queue.SendMessage(EmptyMessage{});
+
+  ASSERT_TRUE(
+      queue.SwitchReceive<bool>([&]([[maybe_unused]] const EmptyMessage& message) { return true; },
+                                [&]([[maybe_unused]] const auto& message) { return false; }));
+
+  queue.SendMessage(IntMessage{42});
+
+  ASSERT_FALSE(
+      queue.SwitchReceive<bool>([&]([[maybe_unused]] const EmptyMessage& message) { return true; },
+                                [&]([[maybe_unused]] const auto& message) { return false; }));
+}
+
+TEST_F(MessageQueueTest, ReceiveInOrder) {
+  TestMessageQueue queue;
+
+  std::vector<TestMessageQueue::Message> messages{
+      EmptyMessage{},
+      IntMessage{42},
+      OtherIntMessage{43},
+      TwoIntMessage{1, 2},
+      StringMessage{"Hello, World!"},
+  };
+
+  // Send the messages
+  for (const auto& message : messages) {
+    queue.SendMessage(message);
+  }
+  queue.SetTimeout(500);
+
+  // Receive the messages. Make sure they came in order, except for the TimeoutExpiredMessage, which
+  // can come at any time.
+  bool received_timeout = false;
+  size_t i = 0;
+  while (i < messages.size()) {
+    auto message = queue.ReceiveMessage();
+    if (std::holds_alternative<TimeoutExpiredMessage>(message)) {
+      ASSERT_FALSE(received_timeout);
+      received_timeout = true;
+    } else {
+      ASSERT_EQ(message.index(), messages[i].index());
+      i++;
+    }
+  }
+  if (!received_timeout) {
+    // If we have not received the timeout yet, receive one more message and make sure it's the
+    // timeout.
+    ASSERT_TRUE(std::holds_alternative<TimeoutExpiredMessage>(queue.ReceiveMessage()));
+  }
+}
+
+}  // namespace art
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h
index 821c75d..2a1a08d 100644
--- a/runtime/base/mutex-inl.h
+++ b/runtime/base/mutex-inl.h
@@ -57,8 +57,8 @@
 }
 
 static inline void CheckUnattachedThread(LockLevel level) NO_THREAD_SAFETY_ANALYSIS {
-  // The check below enumerates the cases where we expect not to be able to sanity check locks
-  // on a thread. Lock checking is disabled to avoid deadlock when checking shutdown lock.
+  // The check below enumerates the cases where we expect not to be able to check the validity of
+  // locks on a thread. Lock checking is disabled to avoid deadlock when checking shutdown lock.
   // TODO: tighten this check.
   if (kDebugLocking) {
     CHECK(!Locks::IsSafeToCallAbortRacy() ||
@@ -227,7 +227,7 @@
   DCHECK(self == nullptr || self == Thread::Current());
   bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
   if (kDebugLocking) {
-    // Sanity debug check that if we think it is locked we have it in our held mutexes.
+    // Debug check that if we think it is locked we have it in our held mutexes.
     if (result && self != nullptr && level_ != kMonitorLock && !gAborting) {
       if (level_ == kThreadWaitLock && self->GetHeldMutex(kThreadWaitLock) != this) {
         CHECK_EQ(self->GetHeldMutex(kThreadWaitWakeLock), this);
@@ -257,7 +257,7 @@
   DCHECK(self == nullptr || self == Thread::Current());
   bool result = (GetExclusiveOwnerTid() == SafeGetTid(self));
   if (kDebugLocking) {
-    // Sanity that if the pthread thinks we own the lock the Thread agrees.
+    // Verify that if the pthread thinks we own the lock the Thread agrees.
     if (self != nullptr && result)  {
       CHECK_EQ(self->GetHeldMutex(level_), this);
     }
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 0b8c781..6574ec0 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -31,11 +31,18 @@
 #include "mutex-inl.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread-inl.h"
+#include "thread.h"
+#include "thread_list.h"
 
 namespace art {
 
 using android::base::StringPrintf;
 
+static constexpr uint64_t kIntervalMillis = 50;
+static constexpr int kMonitorTimeoutTryMax = 5;
+
+static const char* kLastDumpStackTime = "LastDumpStackTime";
+
 struct AllMutexData {
   // A guard for all_mutexes_ that's not a mutex (Mutexes must CAS to acquire and busy wait).
   Atomic<const BaseMutex*> all_mutexes_guard;
@@ -45,6 +52,13 @@
 };
 static struct AllMutexData gAllMutexData[kAllMutexDataSize];
 
+struct DumpStackLastTimeTLSData : public art::TLSData {
+  explicit DumpStackLastTimeTLSData(uint64_t last_dump_time_ms) {
+    last_dump_time_ms_ = last_dump_time_ms;
+  }
+  uint64_t last_dump_time_ms_;
+};
+
 #if ART_USE_FUTEXES
 static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, const timespec& rhs) {
   const int32_t one_sec = 1000 * 1000 * 1000;  // one second in nanoseconds.
@@ -443,15 +457,28 @@
           if (UNLIKELY(should_respond_to_empty_checkpoint_request_)) {
             self->CheckEmptyCheckpointFromMutex();
           }
+
+          uint64_t wait_start_ms = enable_monitor_timeout_ ? MilliTime() : 0;
+          uint64_t try_times = 0;
           do {
+            timespec timeout_ts;
+            timeout_ts.tv_sec = 0;
+            timeout_ts.tv_nsec = Runtime::Current()->GetMonitorTimeoutNs();
             if (futex(state_and_contenders_.Address(), FUTEX_WAIT_PRIVATE, cur_state,
-                      nullptr, nullptr, 0) != 0) {
+                      enable_monitor_timeout_ ? &timeout_ts : nullptr , nullptr, 0) != 0) {
               // We only went to sleep after incrementing and contenders and checking that the
               // lock is still held by someone else.  EAGAIN and EINTR both indicate a spurious
               // failure, try again from the beginning.  We don't use TEMP_FAILURE_RETRY so we can
               // intentionally retry to acquire the lock.
               if ((errno != EAGAIN) && (errno != EINTR)) {
-                PLOG(FATAL) << "futex wait failed for " << name_;
+                if (errno == ETIMEDOUT) {
+                  try_times++;
+                  if (try_times <= kMonitorTimeoutTryMax) {
+                    DumpStack(self, wait_start_ms, try_times);
+                  }
+                } else {
+                  PLOG(FATAL) << "futex wait failed for " << name_;
+                }
               }
             }
             SleepIfRuntimeDeleted(self);
@@ -481,6 +508,57 @@
   }
 }
 
+void Mutex::DumpStack(Thread* self, uint64_t wait_start_ms, uint64_t try_times) {
+  ScopedObjectAccess soa(self);
+  Locks::thread_list_lock_->ExclusiveLock(self);
+  std::string owner_stack_dump;
+  pid_t owner_tid = GetExclusiveOwnerTid();
+  Thread *owner = Runtime::Current()->GetThreadList()->FindThreadByTid(owner_tid);
+  if (owner != nullptr) {
+    if (IsDumpFrequent(owner, try_times)) {
+      Locks::thread_list_lock_->ExclusiveUnlock(self);
+      LOG(WARNING) << "Contention with tid " << owner_tid << ", monitor id " << monitor_id_;
+      return;
+    }
+    struct CollectStackTrace : public Closure {
+      void Run(art::Thread* thread) override
+        REQUIRES_SHARED(art::Locks::mutator_lock_) {
+        if (IsDumpFrequent(thread)) {
+          return;
+        }
+        thread->SetCustomTLS(kLastDumpStackTime, new DumpStackLastTimeTLSData(MilliTime()));
+        thread->DumpJavaStack(oss);
+      }
+      std::ostringstream oss;
+    };
+    CollectStackTrace owner_trace;
+    owner->RequestSynchronousCheckpoint(&owner_trace);
+    owner_stack_dump = owner_trace.oss.str();
+    uint64_t wait_ms = MilliTime() - wait_start_ms;
+    LOG(WARNING) << "Monitor contention with tid " << owner_tid << ", wait time: " << wait_ms
+                 << "ms, monitor id: " << monitor_id_
+                 << "\nPerfMonitor owner thread(" << owner_tid << ") stack is:\n"
+                 << owner_stack_dump;
+  } else {
+    Locks::thread_list_lock_->ExclusiveUnlock(self);
+  }
+}
+
+bool Mutex::IsDumpFrequent(Thread* thread, uint64_t try_times) {
+  uint64_t last_dump_time_ms = 0;
+  DumpStackLastTimeTLSData* tls_data =
+      reinterpret_cast<DumpStackLastTimeTLSData*>(thread->GetCustomTLS(kLastDumpStackTime));
+  if (tls_data != nullptr) {
+     last_dump_time_ms = tls_data->last_dump_time_ms_;
+  }
+  uint64_t interval = MilliTime() - last_dump_time_ms;
+  if (interval < kIntervalMillis * try_times) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
 bool Mutex::ExclusiveTryLock(Thread* self) {
   DCHECK(self == nullptr || self == Thread::Current());
   if (kDebugLocking && !recursive_) {
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 33878e6..8f2a8ea 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -221,6 +221,18 @@
 
   void Dump(std::ostream& os) const override;
 
+  void DumpStack(Thread *self, uint64_t wait_start_ms, uint64_t try_times = 1);
+
+  static bool IsDumpFrequent(Thread *self, uint64_t try_times = 1);
+
+  void setEnableMonitorTimeout() {
+    enable_monitor_timeout_ = true;
+  }
+
+  void setMonitorId(uint32_t monitorId) {
+    monitor_id_ = monitorId;
+  }
+
   // For negative capabilities in clang annotations.
   const Mutex& operator!() const { return *this; }
 
@@ -260,7 +272,7 @@
 
   int32_t get_contenders() {
     // Result is guaranteed to include any contention added by this thread; otherwise approximate.
-    // Treat contenders as unsigned because we're paranoid about overflow; should never matter.
+    // Treat contenders as unsigned because we're concerned about overflow; should never matter.
     return static_cast<uint32_t>(state_and_contenders_.load(std::memory_order_relaxed))
         >> kContenderShift;
   }
@@ -275,6 +287,10 @@
   unsigned int recursion_count_;
   const bool recursive_;  // Can the lock be recursively held?
 
+  bool enable_monitor_timeout_ = false;
+
+  uint32_t monitor_id_;
+
   friend class ConditionVariable;
   DISALLOW_COPY_AND_ASSIGN(Mutex);
 };
diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc
index bd39192..abf4f58 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -20,7 +20,6 @@
 
 #include <android-base/logging.h>
 
-#include "base/histogram-inl.h"
 #include "base/mutex.h"
 #include "base/stl_util.h"
 #include "base/systrace.h"
@@ -34,8 +33,6 @@
 
 namespace art {
 
-constexpr size_t CumulativeLogger::kLowMemoryBucketCount;
-constexpr size_t CumulativeLogger::kDefaultBucketCount;
 constexpr size_t TimingLogger::kIndexNotFound;
 
 CumulativeLogger::CumulativeLogger(const std::string& name)
@@ -46,7 +43,7 @@
 }
 
 CumulativeLogger::~CumulativeLogger() {
-  STLDeleteElements(&histograms_);
+  cumulative_timers_.clear();
 }
 
 void CumulativeLogger::SetName(const std::string& name) {
@@ -66,7 +63,7 @@
   MutexLock mu(Thread::Current(), *GetLock());
   iterations_ = 0;
   total_time_ = 0;
-  STLDeleteElements(&histograms_);
+  cumulative_timers_.clear();
 }
 
 void CumulativeLogger::AddLogger(const TimingLogger &logger) {
@@ -88,46 +85,46 @@
 
 void CumulativeLogger::Dump(std::ostream &os) const {
   MutexLock mu(Thread::Current(), *GetLock());
-  DumpHistogram(os);
+  DumpAverages(os);
 }
 
-void CumulativeLogger::AddPair(const std::string& label, uint64_t delta_time) {
+void CumulativeLogger::AddPair(const char* label, uint64_t delta_time) {
   // Convert delta time to microseconds so that we don't overflow our counters.
   delta_time /= kAdjust;
   total_time_ += delta_time;
-  Histogram<uint64_t>* histogram;
-  Histogram<uint64_t> dummy(label.c_str());
-  auto it = histograms_.find(&dummy);
-  if (it == histograms_.end()) {
-    const size_t max_buckets = Runtime::Current()->GetHeap()->IsLowMemoryMode() ?
-        kLowMemoryBucketCount : kDefaultBucketCount;
-    histogram = new Histogram<uint64_t>(label.c_str(), kInitialBucketSize, max_buckets);
-    histograms_.insert(histogram);
+  CumulativeTime candidate(label, delta_time);
+  auto it = std::lower_bound(cumulative_timers_.begin(), cumulative_timers_.end(), candidate);
+  // Maintain the vector sorted so that lookup above, which is more frequent can
+  // happen in log(n).
+  if (it == cumulative_timers_.end() || it->Name() != label) {
+    cumulative_timers_.insert(it, candidate);
   } else {
-    histogram = *it;
+    it->Add(delta_time);
   }
-  histogram->AddValue(delta_time);
 }
 
-class CompareHistorgramByTimeSpentDeclining {
- public:
-  bool operator()(const Histogram<uint64_t>* a, const Histogram<uint64_t>* b) const {
-    return a->Sum() > b->Sum();
-  }
-};
-
-void CumulativeLogger::DumpHistogram(std::ostream &os) const {
-  os << "Start Dumping histograms for " << iterations_ << " iterations"
+void CumulativeLogger::DumpAverages(std::ostream &os) const {
+  os << "Start Dumping Averages for " << iterations_ << " iterations"
      << " for " << name_ << "\n";
-  std::set<Histogram<uint64_t>*, CompareHistorgramByTimeSpentDeclining>
-      sorted_histograms(histograms_.begin(), histograms_.end());
-  for (Histogram<uint64_t>* histogram : sorted_histograms) {
-    Histogram<uint64_t>::CumulativeData cumulative_data;
-    // We don't expect DumpHistogram to be called often, so it is not performance critical.
-    histogram->CreateHistogram(&cumulative_data);
-    histogram->PrintConfidenceIntervals(os, 0.99, cumulative_data);
+  const size_t timers_sz = cumulative_timers_.size();
+  // Create an array of pointers to cumulative timers on stack and sort it in
+  // decreasing order of accumulated timer so that the most time consuming
+  // timer is printed first.
+  const CumulativeTime* sorted_timers[timers_sz];
+  for (size_t i = 0; i < timers_sz; i++) {
+    sorted_timers[i] = cumulative_timers_.data() + i;
   }
-  os << "Done Dumping histograms\n";
+  std::sort(sorted_timers,
+            sorted_timers + timers_sz,
+            [](const CumulativeTime* a, const CumulativeTime* b) { return a->Sum() > b->Sum(); });
+  for (size_t i = 0; i < timers_sz; i++) {
+    const CumulativeTime *timer = sorted_timers[i];
+    uint64_t total_time_ns = timer->Sum() * kAdjust;
+    os << timer->Name()
+       << ":\tSum: " << PrettyDuration(total_time_ns)
+       << " Avg: " << PrettyDuration(total_time_ns / iterations_) << "\n";
+  }
+  os << "Done Dumping Averages\n";
 }
 
 TimingLogger::TimingLogger(const char* name,
diff --git a/runtime/base/timing_logger.h b/runtime/base/timing_logger.h
index 974a14d..4f72a80 100644
--- a/runtime/base/timing_logger.h
+++ b/runtime/base/timing_logger.h
@@ -17,7 +17,6 @@
 #ifndef ART_RUNTIME_BASE_TIMING_LOGGER_H_
 #define ART_RUNTIME_BASE_TIMING_LOGGER_H_
 
-#include "base/histogram.h"
 #include "base/locks.h"
 #include "base/macros.h"
 #include "base/time_utils.h"
@@ -48,19 +47,24 @@
   size_t GetIterations() const REQUIRES(!GetLock());
 
  private:
-  class HistogramComparator {
+  class CumulativeTime {
    public:
-    bool operator()(const Histogram<uint64_t>* a, const Histogram<uint64_t>* b) const {
-      return a->Name() < b->Name();
+    CumulativeTime(const char* name, uint64_t time) : name_(name), time_(time) {}
+    void Add(uint64_t time) { time_ += time; }
+    const char* Name() const { return name_; }
+    uint64_t Sum() const { return time_; }
+    // Compare addresses of names for sorting.
+    bool operator< (const CumulativeTime& ct) const {
+      return std::less<const char*>()(name_, ct.name_);
     }
+
+   private:
+    const char* name_;
+    uint64_t time_;
   };
 
-  static constexpr size_t kLowMemoryBucketCount = 16;
-  static constexpr size_t kDefaultBucketCount = 100;
-  static constexpr size_t kInitialBucketSize = 50;  // 50 microseconds.
-
-  void AddPair(const std::string &label, uint64_t delta_time) REQUIRES(GetLock());
-  void DumpHistogram(std::ostream &os) const REQUIRES(GetLock());
+  void DumpAverages(std::ostream &os) const REQUIRES(GetLock());
+  void AddPair(const char* label, uint64_t delta_time) REQUIRES(GetLock());
   uint64_t GetTotalTime() const {
     return total_time_;
   }
@@ -69,8 +73,11 @@
     return lock_.get();
   }
 
-  static const uint64_t kAdjust = 1000;
-  std::set<Histogram<uint64_t>*, HistogramComparator> histograms_ GUARDED_BY(GetLock());
+  static constexpr uint64_t kAdjust = 1000;
+  // Use a vector to keep dirty memory to minimal number of pages. Using a
+  // hashtable would be performant, but could lead to more dirty pages. Also, we
+  // don't expect this vector to be too big.
+  std::vector<CumulativeTime> cumulative_timers_ GUARDED_BY(GetLock());
   std::string name_;
   const std::string lock_name_;
   mutable std::unique_ptr<Mutex> lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
diff --git a/runtime/base/timing_logger_test.cc b/runtime/base/timing_logger_test.cc
index 770d2c0..6f8d8cd 100644
--- a/runtime/base/timing_logger_test.cc
+++ b/runtime/base/timing_logger_test.cc
@@ -46,7 +46,7 @@
   logger.NewTiming(split2name);
   logger.NewTiming(split3name);
   logger.EndTiming();
-  // Get the timings and verify that they are sane.
+  // Get the timings and verify that they are appropriate.
   const auto& timings = logger.GetTimings();
   // 6 timings in the timing logger at this point.
   EXPECT_EQ(6U, timings.size());
diff --git a/runtime/cha.cc b/runtime/cha.cc
index a142723..c345af8 100644
--- a/runtime/cha.cc
+++ b/runtime/cha.cc
@@ -543,7 +543,8 @@
       // Abstract method starts with single-implementation flag set and null
       // implementation method.
       method->SetHasSingleImplementation(true);
-      DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
+      DCHECK(!method->HasCodeItem()) << method->PrettyMethod();
+      DCHECK(method->GetSingleImplementation(pointer_size) == nullptr) << method->PrettyMethod();
     }
   // Default conflicting methods cannot be treated with single implementations,
   // as we need to call them (and not inline them) in case of ICCE.
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index f4bda90..a7c3e45 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -59,18 +59,35 @@
     return false;
   }
 
-  void CheckReferences(int* registers, int number_of_references, uint32_t native_pc_offset)
+  void CheckReferences(int* registers,
+                       int number_of_references,
+                       uint32_t dex_pc,
+                       uint32_t native_pc_offset,
+                       bool search_for_valid_stack_map)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     CHECK(GetCurrentOatQuickMethodHeader()->IsOptimized());
-    CheckOptimizedMethod(registers, number_of_references, native_pc_offset);
+    CheckOptimizedMethod(
+        registers, number_of_references, dex_pc, native_pc_offset, search_for_valid_stack_map);
   }
 
  private:
-  void CheckOptimizedMethod(int* registers, int number_of_references, uint32_t native_pc_offset)
+  void CheckOptimizedMethod(int* registers,
+                            int number_of_references,
+                            uint32_t dex_pc,
+                            uint32_t native_pc_offset,
+                            bool search_for_valid_stack_map)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     ArtMethod* m = GetMethod();
     CodeInfo code_info(GetCurrentOatQuickMethodHeader());
     StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+    if (search_for_valid_stack_map && !code_info.GetStackMaskOf(stack_map).IsValid()) {
+      for (StackMap map : code_info.GetStackMaps()) {
+        if (map.GetDexPc() == dex_pc && code_info.GetStackMaskOf(map).IsValid()) {
+          stack_map = map;
+          break;
+        }
+      }
+    }
     CodeItemDataAccessor accessor(m->DexInstructionData());
     uint16_t number_of_dex_registers = accessor.RegistersSize();
 
@@ -93,6 +110,7 @@
           CHECK(false);
           break;
         case DexRegisterLocation::Kind::kInStack:
+          CHECK(stack_mask.IsValid());
           DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0);
           CHECK(stack_mask.LoadBit(location.GetValue() / kFrameSlotSize));
           break;
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index b3aecde..c45f001 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -226,6 +226,7 @@
   switch (type) {
     case kStatic:
     case kSuper:
+    case kPolymorphic:
       break;
     case kInterface: {
       // We have to check whether the method id really belongs to an interface (dex static bytecode
@@ -279,7 +280,7 @@
         const dex::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx);
         ObjPtr<mirror::Class> klass =
             LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
-        DCHECK(klass != nullptr);
+        DCHECK(klass != nullptr) << dex_cache->GetDexFile()->PrettyMethod(method_idx);
         return klass;
       });
 }
@@ -287,8 +288,7 @@
 inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx,
                                                     ObjPtr<mirror::DexCache> dex_cache,
                                                     ObjPtr<mirror::ClassLoader> class_loader) {
-  PointerSize pointer_size = image_pointer_size_;
-  ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, pointer_size);
+  ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx);
   if (resolved == nullptr) {
     const DexFile& dex_file = *dex_cache->GetDexFile();
     const dex::MethodId& method_id = dex_file.GetMethodId(method_idx);
@@ -310,7 +310,7 @@
   // We do not need the read barrier for getting the DexCache for the initial resolved method
   // lookup as both from-space and to-space copies point to the same native resolved methods array.
   ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
-      method_idx, image_pointer_size_);
+      method_idx);
   if (resolved_method == nullptr) {
     return nullptr;
   }
@@ -320,6 +320,16 @@
     // Check if the invoke type matches the class type.
     ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
     ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
+    const dex::MethodId& method_id = referrer->GetDexFile()->GetMethodId(method_idx);
+    ObjPtr<mirror::Class> cls = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
+    if (cls == nullptr) {
+      // The verifier breaks the invariant that a resolved method must have its
+      // class in the class table. Because this method should only lookup and not
+      // resolve class, return null. The caller is responsible for calling
+      // `ResolveMethod` afterwards.
+      // b/73760543
+      return nullptr;
+    }
     if (CheckInvokeClassMismatch</* kThrow= */ false>(dex_cache, type, method_idx, class_loader)) {
       return nullptr;
     }
@@ -353,7 +363,7 @@
   // We do not need the read barrier for getting the DexCache for the initial resolved method
   // lookup as both from-space and to-space copies point to the same native resolved methods array.
   ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
-      method_idx, image_pointer_size_);
+      method_idx);
   DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod());
   if (UNLIKELY(resolved_method == nullptr)) {
     referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
@@ -421,7 +431,7 @@
   // We do not need the read barrier for getting the DexCache for the initial resolved field
   // lookup as both from-space and to-space copies point to the same native resolved fields array.
   ArtField* field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
-      field_idx, image_pointer_size_);
+      field_idx);
   if (field == nullptr) {
     ObjPtr<mirror::ClassLoader> class_loader = referrer->GetDeclaringClass()->GetClassLoader();
     field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static);
@@ -436,7 +446,7 @@
   // We do not need the read barrier for getting the DexCache for the initial resolved field
   // lookup as both from-space and to-space copies point to the same native resolved fields array.
   ArtField* resolved_field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
-      field_idx, image_pointer_size_);
+      field_idx);
   if (UNLIKELY(resolved_field == nullptr)) {
     StackHandleScope<2> hs(Thread::Current());
     ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c39c5be..b9751ab 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -28,7 +28,6 @@
 #include <string>
 #include <string_view>
 #include <tuple>
-#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -40,8 +39,11 @@
 #include "base/arena_allocator.h"
 #include "base/casts.h"
 #include "base/file_utils.h"
+#include "base/hash_map.h"
+#include "base/hash_set.h"
 #include "base/leb128.h"
 #include "base/logging.h"
+#include "base/metrics/metrics.h"
 #include "base/mutex-inl.h"
 #include "base/os.h"
 #include "base/quasi_atomic.h"
@@ -57,7 +59,7 @@
 #include "cha.h"
 #include "class_linker-inl.h"
 #include "class_loader_utils.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "class_table-inl.h"
 #include "compiler_callbacks.h"
 #include "debug_print.h"
@@ -88,6 +90,7 @@
 #include "imtable-inl.h"
 #include "intern_table-inl.h"
 #include "interpreter/interpreter.h"
+#include "interpreter/mterp/nterp.h"
 #include "jit/debugger_interface.h"
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
@@ -127,6 +130,7 @@
 #include "mirror/var_handle.h"
 #include "native/dalvik_system_DexFile.h"
 #include "nativehelper/scoped_local_ref.h"
+#include "nterp_helpers.h"
 #include "oat.h"
 #include "oat_file-inl.h"
 #include "oat_file.h"
@@ -142,8 +146,9 @@
 #include "thread_list.h"
 #include "trace.h"
 #include "transaction.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
+#include "vdex_file.h"
 #include "verifier/class_verifier.h"
+#include "verifier/verifier_deps.h"
 #include "well_known_classes.h"
 
 #include "interpreter/interpreter_mterp_impl.h"
@@ -152,7 +157,7 @@
 
 using android::base::StringPrintf;
 
-static constexpr bool kSanityCheckObjects = kIsDebugBuild;
+static constexpr bool kCheckImageObjects = kIsDebugBuild;
 static constexpr bool kVerifyArtMethodDeclaringClasses = kIsDebugBuild;
 
 static void ThrowNoClassDefFoundError(const char* fmt, ...)
@@ -226,6 +231,22 @@
   self->AssertPendingException();
 }
 
+static void ChangeInterpreterBridgeToNterp(ArtMethod* method, ClassLinker* class_linker)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  Runtime* runtime = Runtime::Current();
+  if (class_linker->IsQuickToInterpreterBridge(method->GetEntryPointFromQuickCompiledCode()) &&
+      CanMethodUseNterp(method)) {
+    if (method->GetDeclaringClass()->IsVisiblyInitialized() ||
+        !NeedsClinitCheckBeforeCall(method)) {
+      runtime->GetInstrumentation()->UpdateMethodsCode(method, interpreter::GetNterpEntryPoint());
+    } else {
+      // Put the resolution stub, which will initialize the class and then
+      // call the method with nterp.
+      runtime->GetInstrumentation()->UpdateMethodsCode(method, GetQuickResolutionStub());
+    }
+  }
+}
+
 // Ensures that methods have the kAccSkipAccessChecks bit set. We use the
 // kAccVerificationAttempted bit on the class access flags to determine whether this has been done
 // before.
@@ -240,16 +261,7 @@
     // to methods that currently use the switch interpreter.
     if (interpreter::CanRuntimeUseNterp()) {
       for (ArtMethod& m : klass->GetMethods(pointer_size)) {
-        if (class_linker->IsQuickToInterpreterBridge(m.GetEntryPointFromQuickCompiledCode()) &&
-            interpreter::CanMethodUseNterp(&m)) {
-          if (klass->IsVisiblyInitialized() || !NeedsClinitCheckBeforeCall(&m)) {
-            runtime->GetInstrumentation()->UpdateMethodsCode(&m, interpreter::GetNterpEntryPoint());
-          } else {
-            // Put the resolution stub, which will initialize the class and then
-            // call the method with nterp.
-            runtime->GetInstrumentation()->UpdateMethodsCode(&m, GetQuickResolutionStub());
-          }
-        }
+        ChangeInterpreterBridgeToNterp(&m, class_linker);
       }
     }
   }
@@ -322,7 +334,7 @@
           vm->DeleteWeakGlobalRef(self, classes_[i]);
           if (klass != nullptr) {
             mirror::Class::SetStatus(klass, ClassStatus::kVisiblyInitialized, self);
-            class_linker_->FixupStaticTrampolines(klass.Get());
+            class_linker_->FixupStaticTrampolines(self, klass.Get());
           }
         }
         num_classes_ = 0u;
@@ -422,14 +434,14 @@
     // Thanks to the x86 memory model, we do not need any memory fences and
     // we can immediately mark the class as visibly initialized.
     mirror::Class::SetStatus(klass, ClassStatus::kVisiblyInitialized, self);
-    FixupStaticTrampolines(klass.Get());
+    FixupStaticTrampolines(self, klass.Get());
     return nullptr;
   }
   if (Runtime::Current()->IsActiveTransaction()) {
     // Transactions are single-threaded, so we can mark the class as visibly intialized.
     // (Otherwise we'd need to track the callback's entry in the transaction for rollback.)
     mirror::Class::SetStatus(klass, ClassStatus::kVisiblyInitialized, self);
-    FixupStaticTrampolines(klass.Get());
+    FixupStaticTrampolines(self, klass.Get());
     return nullptr;
   }
   mirror::Class::SetStatus(klass, ClassStatus::kInitialized, self);
@@ -449,6 +461,65 @@
   }
 }
 
+const void* ClassLinker::RegisterNative(
+    Thread* self, ArtMethod* method, const void* native_method) {
+  CHECK(method->IsNative()) << method->PrettyMethod();
+  CHECK(native_method != nullptr) << method->PrettyMethod();
+  void* new_native_method = nullptr;
+  Runtime* runtime = Runtime::Current();
+  runtime->GetRuntimeCallbacks()->RegisterNativeMethod(method,
+                                                       native_method,
+                                                       /*out*/&new_native_method);
+  if (method->IsCriticalNative()) {
+    MutexLock lock(self, critical_native_code_with_clinit_check_lock_);
+    // Remove old registered method if any.
+    auto it = critical_native_code_with_clinit_check_.find(method);
+    if (it != critical_native_code_with_clinit_check_.end()) {
+      critical_native_code_with_clinit_check_.erase(it);
+    }
+    // To ensure correct memory visibility, we need the class to be visibly
+    // initialized before we can set the JNI entrypoint.
+    if (method->GetDeclaringClass()->IsVisiblyInitialized()) {
+      method->SetEntryPointFromJni(new_native_method);
+    } else {
+      critical_native_code_with_clinit_check_.emplace(method, new_native_method);
+    }
+  } else {
+    method->SetEntryPointFromJni(new_native_method);
+  }
+  return new_native_method;
+}
+
+void ClassLinker::UnregisterNative(Thread* self, ArtMethod* method) {
+  CHECK(method->IsNative()) << method->PrettyMethod();
+  // Restore stub to lookup native pointer via dlsym.
+  if (method->IsCriticalNative()) {
+    MutexLock lock(self, critical_native_code_with_clinit_check_lock_);
+    auto it = critical_native_code_with_clinit_check_.find(method);
+    if (it != critical_native_code_with_clinit_check_.end()) {
+      critical_native_code_with_clinit_check_.erase(it);
+    }
+    method->SetEntryPointFromJni(GetJniDlsymLookupCriticalStub());
+  } else {
+    method->SetEntryPointFromJni(GetJniDlsymLookupStub());
+  }
+}
+
+const void* ClassLinker::GetRegisteredNative(Thread* self, ArtMethod* method) {
+  if (method->IsCriticalNative()) {
+    MutexLock lock(self, critical_native_code_with_clinit_check_lock_);
+    auto it = critical_native_code_with_clinit_check_.find(method);
+    if (it != critical_native_code_with_clinit_check_.end()) {
+      return it->second;
+    }
+    const void* native_code = method->GetEntryPointFromJni();
+    return IsJniDlsymLookupCriticalStub(native_code) ? nullptr : native_code;
+  } else {
+    const void* native_code = method->GetEntryPointFromJni();
+    return IsJniDlsymLookupStub(native_code) ? nullptr : native_code;
+  }
+}
+
 void ClassLinker::ThrowEarlierClassFailure(ObjPtr<mirror::Class> c,
                                            bool wrap_in_no_class_def,
                                            bool log) {
@@ -515,8 +586,8 @@
   ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
   CHECK(cause.get() != nullptr);
 
-  // Boot classpath classes should not fail initialization. This is a sanity debug check. This
-  // cannot in general be guaranteed, but in all likelihood leads to breakage down the line.
+  // Boot classpath classes should not fail initialization. This is a consistency debug check.
+  // This cannot in general be guaranteed, but in all likelihood leads to breakage down the line.
   if (klass->GetClassLoader() == nullptr && !Runtime::Current()->IsAotCompiler()) {
     std::string tmp;
     // We want to LOG(FATAL) on debug builds since this really shouldn't be happening but we need to
@@ -539,87 +610,6 @@
   VlogClassInitializationFailure(klass);
 }
 
-// Gap between two fields in object layout.
-struct FieldGap {
-  uint32_t start_offset;  // The offset from the start of the object.
-  uint32_t size;  // The gap size of 1, 2, or 4 bytes.
-};
-struct FieldGapsComparator {
-  FieldGapsComparator() {
-  }
-  bool operator() (const FieldGap& lhs, const FieldGap& rhs)
-      NO_THREAD_SAFETY_ANALYSIS {
-    // Sort by gap size, largest first. Secondary sort by starting offset.
-    // Note that the priority queue returns the largest element, so operator()
-    // should return true if lhs is less than rhs.
-    return lhs.size < rhs.size || (lhs.size == rhs.size && lhs.start_offset > rhs.start_offset);
-  }
-};
-using FieldGaps = std::priority_queue<FieldGap, std::vector<FieldGap>, FieldGapsComparator>;
-
-// Adds largest aligned gaps to queue of gaps.
-static void AddFieldGap(uint32_t gap_start, uint32_t gap_end, FieldGaps* gaps) {
-  DCHECK(gaps != nullptr);
-
-  uint32_t current_offset = gap_start;
-  while (current_offset != gap_end) {
-    size_t remaining = gap_end - current_offset;
-    if (remaining >= sizeof(uint32_t) && IsAligned<4>(current_offset)) {
-      gaps->push(FieldGap {current_offset, sizeof(uint32_t)});
-      current_offset += sizeof(uint32_t);
-    } else if (remaining >= sizeof(uint16_t) && IsAligned<2>(current_offset)) {
-      gaps->push(FieldGap {current_offset, sizeof(uint16_t)});
-      current_offset += sizeof(uint16_t);
-    } else {
-      gaps->push(FieldGap {current_offset, sizeof(uint8_t)});
-      current_offset += sizeof(uint8_t);
-    }
-    DCHECK_LE(current_offset, gap_end) << "Overran gap";
-  }
-}
-// Shuffle fields forward, making use of gaps whenever possible.
-template<int n>
-static void ShuffleForward(size_t* current_field_idx,
-                           MemberOffset* field_offset,
-                           std::deque<ArtField*>* grouped_and_sorted_fields,
-                           FieldGaps* gaps)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  DCHECK(current_field_idx != nullptr);
-  DCHECK(grouped_and_sorted_fields != nullptr);
-  DCHECK(gaps != nullptr);
-  DCHECK(field_offset != nullptr);
-
-  DCHECK(IsPowerOfTwo(n));
-  while (!grouped_and_sorted_fields->empty()) {
-    ArtField* field = grouped_and_sorted_fields->front();
-    Primitive::Type type = field->GetTypeAsPrimitiveType();
-    if (Primitive::ComponentSize(type) < n) {
-      break;
-    }
-    if (!IsAligned<n>(field_offset->Uint32Value())) {
-      MemberOffset old_offset = *field_offset;
-      *field_offset = MemberOffset(RoundUp(field_offset->Uint32Value(), n));
-      AddFieldGap(old_offset.Uint32Value(), field_offset->Uint32Value(), gaps);
-    }
-    CHECK(type != Primitive::kPrimNot) << field->PrettyField();  // should be primitive types
-    grouped_and_sorted_fields->pop_front();
-    if (!gaps->empty() && gaps->top().size >= n) {
-      FieldGap gap = gaps->top();
-      gaps->pop();
-      DCHECK_ALIGNED(gap.start_offset, n);
-      field->SetOffset(MemberOffset(gap.start_offset));
-      if (gap.size > n) {
-        AddFieldGap(gap.start_offset + n, gap.start_offset + gap.size, gaps);
-      }
-    } else {
-      DCHECK_ALIGNED(field_offset->Uint32Value(), n);
-      field->SetOffset(*field_offset);
-      *field_offset = MemberOffset(field_offset->Uint32Value() + n);
-    }
-    ++(*current_field_idx);
-  }
-}
-
 ClassLinker::ClassLinker(InternTable* intern_table, bool fast_class_not_found_exceptions)
     : boot_class_table_(new ClassTable()),
       failed_dex_cache_class_lookups_(0),
@@ -635,9 +625,12 @@
       quick_imt_conflict_trampoline_(nullptr),
       quick_generic_jni_trampoline_(nullptr),
       quick_to_interpreter_bridge_trampoline_(nullptr),
+      nterp_trampoline_(nullptr),
       image_pointer_size_(kRuntimePointerSize),
       visibly_initialized_callback_lock_("visibly initialized callback lock"),
       visibly_initialized_callback_(nullptr),
+      critical_native_code_with_clinit_check_lock_("critical native code with clinit check lock"),
+      critical_native_code_with_clinit_check_(),
       cha_(Runtime::Current()->IsAotCompiler() ? nullptr : new ClassHierarchyAnalysis()) {
   // For CHA disabled during Aot, see b/34193647.
 
@@ -860,6 +853,7 @@
     quick_imt_conflict_trampoline_ = GetQuickImtConflictStub();
     quick_generic_jni_trampoline_ = GetQuickGenericJniStub();
     quick_to_interpreter_bridge_trampoline_ = GetQuickToInterpreterBridge();
+    nterp_trampoline_ = interpreter::GetNterpEntryPoint();
   }
 
   // Object, String, ClassExt and DexCache need to be rerun through FindSystemClass to finish init
@@ -903,8 +897,7 @@
   object_array_class->GetIfTable()->SetInterface(0, java_lang_Cloneable.Get());
   object_array_class->GetIfTable()->SetInterface(1, java_io_Serializable.Get());
 
-  // Sanity check Class[] and Object[]'s interfaces. GetDirectInterface may cause thread
-  // suspension.
+  // Check Class[] and Object[]'s interfaces. GetDirectInterface may cause thread suspension.
   CHECK_EQ(java_lang_Cloneable.Get(),
            mirror::Class::GetDirectInterface(self, class_array_class.Get(), 0));
   CHECK_EQ(java_io_Serializable.Get(),
@@ -1133,19 +1126,34 @@
     if (!c->IsArrayClass() && !c->IsPrimitive()) {
       StackHandleScope<1> hs(self);
       Handle<mirror::Class> h_class(hs.NewHandle(c));
-      EnsureInitialized(self, h_class, true, true);
-      self->AssertNoPendingException();
+      if (!EnsureInitialized(self, h_class, true, true)) {
+        LOG(FATAL) << "Exception when initializing " << h_class->PrettyClass()
+            << ": " << self->GetException()->Dump();
+      }
     } else {
       DCHECK(c->IsInitialized());
     }
   }
 }
 
+static void InitializeObjectVirtualMethodHashes(ObjPtr<mirror::Class> java_lang_Object,
+                                                PointerSize pointer_size,
+                                                /*out*/ ArrayRef<uint32_t> virtual_method_hashes)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  ArraySlice<ArtMethod> virtual_methods = java_lang_Object->GetVirtualMethods(pointer_size);
+  DCHECK_EQ(virtual_method_hashes.size(), virtual_methods.size());
+  for (size_t i = 0; i != virtual_method_hashes.size(); ++i) {
+    const char* name = virtual_methods[i].GetName();
+    virtual_method_hashes[i] = ComputeModifiedUtf8Hash(name);
+  }
+}
+
 struct TrampolineCheckData {
   const void* quick_resolution_trampoline;
   const void* quick_imt_conflict_trampoline;
   const void* quick_generic_jni_trampoline;
   const void* quick_to_interpreter_bridge_trampoline;
+  const void* nterp_trampoline;
   PointerSize pointer_size;
   ArtMethod* m;
   bool error;
@@ -1212,6 +1220,7 @@
   quick_imt_conflict_trampoline_ = default_oat_header.GetQuickImtConflictTrampoline();
   quick_generic_jni_trampoline_ = default_oat_header.GetQuickGenericJniTrampoline();
   quick_to_interpreter_bridge_trampoline_ = default_oat_header.GetQuickToInterpreterBridge();
+  nterp_trampoline_ = default_oat_header.GetNterpTrampoline();
   if (kIsDebugBuild) {
     // Check that the other images use the same trampoline.
     for (size_t i = 1; i < oat_files.size(); ++i) {
@@ -1228,12 +1237,15 @@
           ith_oat_header.GetQuickGenericJniTrampoline();
       const void* ith_quick_to_interpreter_bridge_trampoline =
           ith_oat_header.GetQuickToInterpreterBridge();
+      const void* ith_nterp_trampoline =
+          ith_oat_header.GetNterpTrampoline();
       if (ith_jni_dlsym_lookup_trampoline_ != jni_dlsym_lookup_trampoline_ ||
           ith_jni_dlsym_lookup_critical_trampoline_ != jni_dlsym_lookup_critical_trampoline_ ||
           ith_quick_resolution_trampoline != quick_resolution_trampoline_ ||
           ith_quick_imt_conflict_trampoline != quick_imt_conflict_trampoline_ ||
           ith_quick_generic_jni_trampoline != quick_generic_jni_trampoline_ ||
-          ith_quick_to_interpreter_bridge_trampoline != quick_to_interpreter_bridge_trampoline_) {
+          ith_quick_to_interpreter_bridge_trampoline != quick_to_interpreter_bridge_trampoline_ ||
+          ith_nterp_trampoline != nterp_trampoline_) {
         // Make sure that all methods in this image do not contain those trampolines as
         // entrypoints. Otherwise the class-linker won't be able to work with a single set.
         TrampolineCheckData data;
@@ -1243,6 +1255,7 @@
         data.quick_imt_conflict_trampoline = ith_quick_imt_conflict_trampoline;
         data.quick_generic_jni_trampoline = ith_quick_generic_jni_trampoline;
         data.quick_to_interpreter_bridge_trampoline = ith_quick_to_interpreter_bridge_trampoline;
+        data.nterp_trampoline = ith_nterp_trampoline;
         ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
         auto visitor = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
           if (obj->IsClass()) {
@@ -1301,6 +1314,9 @@
   for (const std::unique_ptr<const DexFile>& dex_file : boot_dex_files_) {
     OatDexFile::MadviseDexFile(*dex_file, MadviseState::kMadviseStateAtLoad);
   }
+  InitializeObjectVirtualMethodHashes(GetClassRoot<mirror::Object>(this),
+                                      image_pointer_size_,
+                                      ArrayRef<uint32_t>(object_virtual_method_hashes_));
   FinishInit(self);
 
   VLOG(startup) << __FUNCTION__ << " exiting";
@@ -1312,6 +1328,11 @@
     std::vector<std::unique_ptr<const DexFile>>&& additional_dex_files) {
   for (std::unique_ptr<const DexFile>& dex_file : additional_dex_files) {
     AppendToBootClassPath(self, dex_file.get());
+    if (kIsDebugBuild) {
+      for (const auto& boot_dex_file : boot_dex_files_) {
+        DCHECK_NE(boot_dex_file->GetLocation(), dex_file->GetLocation());
+      }
+    }
     boot_dex_files_.push_back(std::move(dex_file));
   }
 }
@@ -1448,7 +1469,6 @@
 template <typename Visitor>
 static void VisitInternedStringReferences(
     gc::space::ImageSpace* space,
-    bool use_preresolved_strings,
     const Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
   const uint8_t* target_base = space->Begin();
   const ImageSection& sro_section =
@@ -1465,75 +1485,26 @@
   for (size_t offset_index = 0; offset_index < num_string_offsets; ++offset_index) {
     uint32_t base_offset = sro_base[offset_index].first;
 
-    if (HasDexCacheStringNativeRefTag(base_offset)) {
-      base_offset = ClearDexCacheNativeRefTags(base_offset);
-      DCHECK_ALIGNED(base_offset, 2);
+    uint32_t raw_member_offset = sro_base[offset_index].second;
+    DCHECK_ALIGNED(base_offset, 2);
+    DCHECK_ALIGNED(raw_member_offset, 2);
 
-      ObjPtr<mirror::DexCache> dex_cache =
-          reinterpret_cast<mirror::DexCache*>(space->Begin() + base_offset);
-      uint32_t string_slot_index = sro_base[offset_index].second;
-
-      mirror::StringDexCachePair source =
-          dex_cache->GetStrings()[string_slot_index].load(std::memory_order_relaxed);
-      ObjPtr<mirror::String> referred_string = source.object.Read();
-      DCHECK(referred_string != nullptr);
-
-      ObjPtr<mirror::String> visited = visitor(referred_string);
-      if (visited != referred_string) {
-        // Because we are not using a helper function we need to mark the GC card manually.
-        WriteBarrier::ForEveryFieldWrite(dex_cache);
-        dex_cache->GetStrings()[string_slot_index].store(
-            mirror::StringDexCachePair(visited, source.index), std::memory_order_relaxed);
-      }
-    } else if (HasDexCachePreResolvedStringNativeRefTag(base_offset)) {
-      if (use_preresolved_strings) {
-        base_offset = ClearDexCacheNativeRefTags(base_offset);
-        DCHECK_ALIGNED(base_offset, 2);
-
-        ObjPtr<mirror::DexCache> dex_cache =
-            reinterpret_cast<mirror::DexCache*>(space->Begin() + base_offset);
-        uint32_t string_index = sro_base[offset_index].second;
-
-        GcRoot<mirror::String>* preresolved_strings =
-            dex_cache->GetPreResolvedStrings();
-        // Handle calls to ClearPreResolvedStrings that might occur concurrently by the profile
-        // saver that runs shortly after startup. In case the strings are cleared, there is nothing
-        // to fix up.
-        if (preresolved_strings != nullptr) {
-          ObjPtr<mirror::String> referred_string =
-              preresolved_strings[string_index].Read();
-          if (referred_string != nullptr) {
-            ObjPtr<mirror::String> visited = visitor(referred_string);
-            if (visited != referred_string) {
-              // Because we are not using a helper function we need to mark the GC card manually.
-              WriteBarrier::ForEveryFieldWrite(dex_cache);
-              preresolved_strings[string_index] = GcRoot<mirror::String>(visited);
-            }
-          }
-        }
-      }
-    } else {
-      uint32_t raw_member_offset = sro_base[offset_index].second;
-      DCHECK_ALIGNED(base_offset, 2);
-      DCHECK_ALIGNED(raw_member_offset, 2);
-
-      ObjPtr<mirror::Object> obj_ptr =
-          reinterpret_cast<mirror::Object*>(space->Begin() + base_offset);
-      MemberOffset member_offset(raw_member_offset);
-      ObjPtr<mirror::String> referred_string =
-          obj_ptr->GetFieldObject<mirror::String,
-                                  kVerifyNone,
-                                  kWithoutReadBarrier,
-                                  /* kIsVolatile= */ false>(member_offset);
-      DCHECK(referred_string != nullptr);
-
-      ObjPtr<mirror::String> visited = visitor(referred_string);
-      if (visited != referred_string) {
-        obj_ptr->SetFieldObject</* kTransactionActive= */ false,
-                                /* kCheckTransaction= */ false,
+    ObjPtr<mirror::Object> obj_ptr =
+        reinterpret_cast<mirror::Object*>(space->Begin() + base_offset);
+    MemberOffset member_offset(raw_member_offset);
+    ObjPtr<mirror::String> referred_string =
+        obj_ptr->GetFieldObject<mirror::String,
                                 kVerifyNone,
-                                /* kIsVolatile= */ false>(member_offset, visited);
-      }
+                                kWithoutReadBarrier,
+                                /* kIsVolatile= */ false>(member_offset);
+    DCHECK(referred_string != nullptr);
+
+    ObjPtr<mirror::String> visited = visitor(referred_string);
+    if (visited != referred_string) {
+      obj_ptr->SetFieldObject</* kTransactionActive= */ false,
+                              /* kCheckTransaction= */ false,
+                              kVerifyNone,
+                              /* kIsVolatile= */ false>(member_offset, visited);
     }
   }
 }
@@ -1551,7 +1522,6 @@
   size_t num_recorded_refs = 0u;
   VisitInternedStringReferences(
       space,
-      /*use_preresolved_strings=*/ true,
       [&image_interns, &num_recorded_refs](ObjPtr<mirror::String> str)
           REQUIRES_SHARED(Locks::mutator_lock_) {
         auto it = image_interns.find(GcRoot<mirror::String>(str));
@@ -1573,8 +1543,7 @@
       ClassLinker* class_linker,
       gc::space::ImageSpace* space,
       Handle<mirror::ClassLoader> class_loader,
-      Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches,
-      ClassTable::ClassSet* new_class_set)
+      Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches)
       REQUIRES(!Locks::dex_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -1586,8 +1555,7 @@
     ClassLinker* class_linker,
     gc::space::ImageSpace* space,
     Handle<mirror::ClassLoader> class_loader,
-    Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches,
-    ClassTable::ClassSet* new_class_set)
+    Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches)
     REQUIRES(!Locks::dex_lock_)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   ScopedTrace app_image_timing("AppImage:Updating");
@@ -1602,7 +1570,6 @@
   Runtime* const runtime = Runtime::Current();
   gc::Heap* const heap = runtime->GetHeap();
   const ImageHeader& header = space->GetImageHeader();
-  bool load_app_image_startup_cache = runtime->LoadAppImageStartupCache();
   {
     // Register dex caches with the class loader.
     WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
@@ -1613,56 +1580,6 @@
         CHECK(class_linker->FindDexCacheDataLocked(*dex_file) == nullptr);
         class_linker->RegisterDexFileLocked(*dex_file, dex_cache, class_loader.Get());
       }
-
-      if (!load_app_image_startup_cache) {
-        dex_cache->ClearPreResolvedStrings();
-      }
-
-      if (kIsDebugBuild) {
-        CHECK(new_class_set != nullptr);
-        mirror::TypeDexCacheType* const types = dex_cache->GetResolvedTypes();
-        const size_t num_types = dex_cache->NumResolvedTypes();
-        for (size_t j = 0; j != num_types; ++j) {
-          // The image space is not yet added to the heap, avoid read barriers.
-          ObjPtr<mirror::Class> klass = types[j].load(std::memory_order_relaxed).object.Read();
-
-          if (space->HasAddress(klass.Ptr())) {
-            DCHECK(!klass->IsErroneous()) << klass->GetStatus();
-            auto it = new_class_set->find(ClassTable::TableSlot(klass));
-            DCHECK(it != new_class_set->end());
-            DCHECK_EQ(it->Read(), klass);
-            ObjPtr<mirror::Class> super_class = klass->GetSuperClass();
-
-            if (super_class != nullptr && !heap->ObjectIsInBootImageSpace(super_class)) {
-              auto it2 = new_class_set->find(ClassTable::TableSlot(super_class));
-              DCHECK(it2 != new_class_set->end());
-              DCHECK_EQ(it2->Read(), super_class);
-            }
-
-            for (ArtMethod& m : klass->GetDirectMethods(kRuntimePointerSize)) {
-              const void* code = m.GetEntryPointFromQuickCompiledCode();
-              const void* oat_code = m.IsInvokable() ? class_linker->GetQuickOatCodeFor(&m) : code;
-              if (!class_linker->IsQuickResolutionStub(code) &&
-                  !class_linker->IsQuickGenericJniStub(code) &&
-                  !class_linker->IsQuickToInterpreterBridge(code) &&
-                  !m.IsNative()) {
-                DCHECK_EQ(code, oat_code) << m.PrettyMethod();
-              }
-            }
-
-            for (ArtMethod& m : klass->GetVirtualMethods(kRuntimePointerSize)) {
-              const void* code = m.GetEntryPointFromQuickCompiledCode();
-              const void* oat_code = m.IsInvokable() ? class_linker->GetQuickOatCodeFor(&m) : code;
-              if (!class_linker->IsQuickResolutionStub(code) &&
-                  !class_linker->IsQuickGenericJniStub(code) &&
-                  !class_linker->IsQuickToInterpreterBridge(code) &&
-                  !m.IsNative()) {
-                DCHECK_EQ(code, oat_code) << m.PrettyMethod();
-              }
-            }
-          }
-        }
-      }
     }
   }
 
@@ -1692,8 +1609,6 @@
   Runtime* const runtime = Runtime::Current();
   InternTable* const intern_table = runtime->GetInternTable();
 
-  const bool load_startup_cache = runtime->LoadAppImageStartupCache();
-
   // Add the intern table, removing any conflicts. For conflicts, store the new address in a map
   // for faster lookup.
   // TODO: Optimize with a bitmap or bloom filter
@@ -1733,7 +1648,7 @@
         }
       }, /*visit_boot_images=*/false, /*visit_non_boot_images=*/true);
     }
-    // Sanity check to ensure correctness.
+    // Consistency check to ensure correctness.
     if (kIsDebugBuild) {
       for (GcRoot<mirror::String>& root : interns) {
         ObjPtr<mirror::String> string = root.Read();
@@ -1747,7 +1662,6 @@
     VLOG(image) << "AppImage:conflictingInternStrings = " << intern_remap.size();
     VisitInternedStringReferences(
         space,
-        load_startup_cache,
         [&intern_remap](ObjPtr<mirror::String> str) REQUIRES_SHARED(Locks::mutator_lock_) {
           auto it = intern_remap.find(str.Ptr());
           if (it != intern_remap.end()) {
@@ -1814,11 +1728,11 @@
 
 // Helper class for ArtMethod checks when adding an image. Keeps all required functionality
 // together and caches some intermediate results.
-class ImageSanityChecks final {
+class ImageChecker final {
  public:
   static void CheckObjects(gc::Heap* heap, ClassLinker* class_linker)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    ImageSanityChecks isc(heap, class_linker);
+    ImageChecker ic(heap, class_linker);
     auto visitor = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
       DCHECK(obj != nullptr);
       CHECK(obj->GetClass() != nullptr) << "Null class in object " << obj;
@@ -1831,29 +1745,29 @@
         for (ArtField& field : klass->GetSFields()) {
           CHECK_EQ(field.GetDeclaringClass(), klass);
         }
-        const PointerSize pointer_size = isc.pointer_size_;
+        const PointerSize pointer_size = ic.pointer_size_;
         for (ArtMethod& m : klass->GetMethods(pointer_size)) {
-          isc.SanityCheckArtMethod(&m, klass);
+          ic.CheckArtMethod(&m, klass);
         }
         ObjPtr<mirror::PointerArray> vtable = klass->GetVTable();
         if (vtable != nullptr) {
-          isc.SanityCheckArtMethodPointerArray(vtable, nullptr);
+          ic.CheckArtMethodPointerArray(vtable, nullptr);
         }
         if (klass->ShouldHaveImt()) {
           ImTable* imt = klass->GetImt(pointer_size);
           for (size_t i = 0; i < ImTable::kSize; ++i) {
-            isc.SanityCheckArtMethod(imt->Get(i, pointer_size), nullptr);
+            ic.CheckArtMethod(imt->Get(i, pointer_size), nullptr);
           }
         }
         if (klass->ShouldHaveEmbeddedVTable()) {
           for (int32_t i = 0; i < klass->GetEmbeddedVTableLength(); ++i) {
-            isc.SanityCheckArtMethod(klass->GetEmbeddedVTableEntry(i, pointer_size), nullptr);
+            ic.CheckArtMethod(klass->GetEmbeddedVTableEntry(i, pointer_size), nullptr);
           }
         }
         ObjPtr<mirror::IfTable> iftable = klass->GetIfTable();
         for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
           if (iftable->GetMethodArrayCount(i) > 0) {
-            isc.SanityCheckArtMethodPointerArray(iftable->GetMethodArray(i), nullptr);
+            ic.CheckArtMethodPointerArray(iftable->GetMethodArray(i), nullptr);
           }
         }
       }
@@ -1861,17 +1775,8 @@
     heap->VisitObjects(visitor);
   }
 
-  static void CheckArtMethodDexCacheArray(gc::Heap* heap,
-                                          ClassLinker* class_linker,
-                                          mirror::MethodDexCacheType* arr,
-                                          size_t size)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    ImageSanityChecks isc(heap, class_linker);
-    isc.SanityCheckArtMethodDexCacheArray(arr, size);
-  }
-
  private:
-  ImageSanityChecks(gc::Heap* heap, ClassLinker* class_linker)
+  ImageChecker(gc::Heap* heap, ClassLinker* class_linker)
      :  spaces_(heap->GetBootImageSpaces()),
         pointer_size_(class_linker->GetImagePointerSize()) {
     space_begin_.reserve(spaces_.size());
@@ -1885,7 +1790,7 @@
     }
   }
 
-  void SanityCheckArtMethod(ArtMethod* m, ObjPtr<mirror::Class> expected_class)
+  void CheckArtMethod(ArtMethod* m, ObjPtr<mirror::Class> expected_class)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     if (m->IsRuntimeMethod()) {
       ObjPtr<mirror::Class> declaring_class = m->GetDeclaringClassUnchecked();
@@ -1906,8 +1811,8 @@
     }
   }
 
-  void SanityCheckArtMethodPointerArray(ObjPtr<mirror::PointerArray> arr,
-                                        ObjPtr<mirror::Class> expected_class)
+  void CheckArtMethodPointerArray(ObjPtr<mirror::PointerArray> arr,
+                                  ObjPtr<mirror::Class> expected_class)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     CHECK(arr != nullptr);
     for (int32_t j = 0; j < arr->GetLength(); ++j) {
@@ -1917,31 +1822,7 @@
         CHECK(method != nullptr);
       }
       if (method != nullptr) {
-        SanityCheckArtMethod(method, expected_class);
-      }
-    }
-  }
-
-  void SanityCheckArtMethodDexCacheArray(mirror::MethodDexCacheType* arr, size_t size)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    CHECK_EQ(arr != nullptr, size != 0u);
-    if (arr != nullptr) {
-      bool contains = false;
-      for (auto space : spaces_) {
-        auto offset = reinterpret_cast<uint8_t*>(arr) - space->Begin();
-        if (space->GetImageHeader().GetDexCacheArraysSection().Contains(offset)) {
-          contains = true;
-          break;
-        }
-      }
-      CHECK(contains);
-    }
-    for (size_t j = 0; j < size; ++j) {
-      auto pair = mirror::DexCache::GetNativePairPtrSize(arr, j, pointer_size_);
-      ArtMethod* method = pair.object;
-      // expected_class == null means we are a dex cache.
-      if (method != nullptr) {
-        SanityCheckArtMethod(method, nullptr);
+        CheckArtMethod(method, expected_class);
       }
     }
   }
@@ -1957,8 +1838,8 @@
 
 static void VerifyAppImage(const ImageHeader& header,
                            const Handle<mirror::ClassLoader>& class_loader,
-                           const Handle<mirror::ObjectArray<mirror::DexCache> >& dex_caches,
-                           ClassTable* class_table, gc::space::ImageSpace* space)
+                           ClassTable* class_table,
+                           gc::space::ImageSpace* space)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   header.VisitPackedArtMethods([&](ArtMethod& method) REQUIRES_SHARED(Locks::mutator_lock_) {
     ObjPtr<mirror::Class> klass = method.GetDeclaringClass();
@@ -1986,17 +1867,6 @@
       }
     }
   }
-  // Check that all non-primitive classes in dex caches are also in the class table.
-  for (auto dex_cache : dex_caches.ConstIterate<mirror::DexCache>()) {
-    mirror::TypeDexCacheType* const types = dex_cache->GetResolvedTypes();
-    for (int32_t j = 0, num_types = dex_cache->NumResolvedTypes(); j < num_types; j++) {
-      ObjPtr<mirror::Class> klass = types[j].load(std::memory_order_relaxed).object.Read();
-      if (klass != nullptr && !klass->IsPrimitive()) {
-        CHECK(class_table->Contains(klass))
-            << klass->PrettyDescriptor() << " " << dex_cache->GetDexFile()->GetLocation();
-      }
-    }
-  }
 }
 
 bool ClassLinker::AddImageSpace(
@@ -2068,24 +1938,15 @@
       return false;
     }
 
-    if (app_image) {
-      // The current dex file field is bogus, overwrite it so that we can get the dex file in the
-      // loop below.
-      dex_cache->SetDexFile(dex_file.get());
-      mirror::TypeDexCacheType* const types = dex_cache->GetResolvedTypes();
-      for (int32_t j = 0, num_types = dex_cache->NumResolvedTypes(); j < num_types; j++) {
-        ObjPtr<mirror::Class> klass = types[j].load(std::memory_order_relaxed).object.Read();
-        if (klass != nullptr) {
-          DCHECK(!klass->IsErroneous()) << klass->GetStatus();
-        }
-      }
-    } else {
-      if (kSanityCheckObjects) {
-        ImageSanityChecks::CheckArtMethodDexCacheArray(heap,
-                                                       this,
-                                                       dex_cache->GetResolvedMethods(),
-                                                       dex_cache->NumResolvedMethods());
-      }
+    LinearAlloc* linear_alloc = GetOrCreateAllocatorForClassLoader(class_loader.Get());
+    DCHECK(linear_alloc != nullptr);
+    DCHECK_EQ(linear_alloc == Runtime::Current()->GetLinearAlloc(), !app_image);
+    {
+      // Native fields are all null.  Initialize them and allocate native memory.
+      WriterMutexLock mu(self, *Locks::dex_lock_);
+      dex_cache->InitializeNativeFields(dex_file.get(), linear_alloc);
+    }
+    if (!app_image) {
       // Register dex files, keep track of existing ones that are conflicts.
       AppendToBootClassPath(dex_file.get(), dex_cache);
     }
@@ -2101,17 +1962,9 @@
     }
   }
 
-  if (kSanityCheckObjects) {
-    for (auto dex_cache : dex_caches.Iterate<mirror::DexCache>()) {
-      for (size_t j = 0; j < dex_cache->NumResolvedFields(); ++j) {
-        auto* field = dex_cache->GetResolvedField(j, image_pointer_size_);
-        if (field != nullptr) {
-          CHECK(field->GetDeclaringClass()->GetClass() != nullptr);
-        }
-      }
-    }
+  if (kCheckImageObjects) {
     if (!app_image) {
-      ImageSanityChecks::CheckObjects(heap, this);
+      ImageChecker::CheckObjects(heap, this);
     }
   }
 
@@ -2129,13 +1982,27 @@
     }, space->Begin(), image_pointer_size_);
   }
 
-  if (interpreter::CanRuntimeUseNterp()) {
-    // Set image methods' entry point that point to the interpreter bridge to the nterp entry point.
+  if (!runtime->IsAotCompiler()) {
+    ScopedTrace trace("AppImage:UpdateCodeItemAndNterp");
+    bool can_use_nterp = interpreter::CanRuntimeUseNterp();
     header.VisitPackedArtMethods([&](ArtMethod& method) REQUIRES_SHARED(Locks::mutator_lock_) {
-      if (IsQuickToInterpreterBridge(method.GetEntryPointFromQuickCompiledCode()) &&
-          interpreter::CanMethodUseNterp(&method)) {
-        method.SetEntryPointFromQuickCompiledCodePtrSize(interpreter::GetNterpEntryPoint(),
-                                                         image_pointer_size_);
+      // In the image, the `data` pointer field of the ArtMethod contains the code
+      // item offset. Change this to the actual pointer to the code item.
+      if (method.HasCodeItem()) {
+        const dex::CodeItem* code_item = method.GetDexFile()->GetCodeItem(
+            reinterpret_cast32<uint32_t>(method.GetDataPtrSize(image_pointer_size_)));
+        method.SetCodeItem(code_item);
+      }
+      // Set image methods' entry point that point to the interpreter bridge to the
+      // nterp entry point.
+      if (method.GetEntryPointFromQuickCompiledCode() == nterp_trampoline_) {
+        if (can_use_nterp) {
+          DCHECK(!NeedsClinitCheckBeforeCall(&method) ||
+                 method.GetDeclaringClass()->IsVisiblyInitialized());
+          method.SetEntryPointFromQuickCompiledCode(interpreter::GetNterpEntryPoint());
+        } else {
+          method.SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+        }
       }
     }, space->Begin(), image_pointer_size_);
   }
@@ -2167,7 +2034,7 @@
     VLOG(image) << "Adding class table classes took " << PrettyDuration(NanoTime() - start_time2);
   }
   if (app_image) {
-    AppImageLoadingHelper::Update(this, space, class_loader, dex_caches, &temp_set);
+    AppImageLoadingHelper::Update(this, space, class_loader, dex_caches);
 
     {
       ScopedTrace trace("AppImage:UpdateClassLoaders");
@@ -2220,18 +2087,13 @@
     // This verification needs to happen after the classes have been added to the class loader.
     // Since it ensures classes are in the class table.
     ScopedTrace trace("AppImage:Verify");
-    VerifyAppImage(header, class_loader, dex_caches, class_table, space);
+    VerifyAppImage(header, class_loader, class_table, space);
   }
 
   VLOG(class_linker) << "Adding image space took " << PrettyDuration(NanoTime() - start_time);
   return true;
 }
 
-bool ClassLinker::ClassInClassTable(ObjPtr<mirror::Class> klass) {
-  ClassTable* const class_table = ClassTableForClassLoader(klass->GetClassLoader());
-  return class_table != nullptr && class_table->Contains(klass);
-}
-
 void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) {
   // Acquire tracing_enabled before locking class linker lock to prevent lock order violation. Since
   // enabling tracing requires the mutator lock, there are no race conditions here.
@@ -2496,6 +2358,17 @@
     CHAOnDeleteUpdateClassVisitor visitor(data.allocator);
     data.class_table->Visit<CHAOnDeleteUpdateClassVisitor, kWithoutReadBarrier>(visitor);
   }
+  {
+    MutexLock lock(self, critical_native_code_with_clinit_check_lock_);
+    auto end = critical_native_code_with_clinit_check_.end();
+    for (auto it = critical_native_code_with_clinit_check_.begin(); it != end; ) {
+      if (data.allocator->ContainsUnsafe(it->first)) {
+        it = critical_native_code_with_clinit_check_.erase(it);
+      } else {
+        ++it;
+      }
+    }
+  }
 
   delete data.allocator;
   delete data.class_table;
@@ -2508,11 +2381,8 @@
           : ObjPtr<mirror::Array>(mirror::IntArray::Alloc(self, length)));
 }
 
-ObjPtr<mirror::DexCache> ClassLinker::AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location,
-                                                    Thread* self,
-                                                    const DexFile& dex_file) {
+ObjPtr<mirror::DexCache> ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) {
   StackHandleScope<1> hs(self);
-  DCHECK(out_location != nullptr);
   auto dex_cache(hs.NewHandle(ObjPtr<mirror::DexCache>::DownCast(
       GetClassRoot<mirror::DexCache>(this)->AllocObject(self))));
   if (dex_cache == nullptr) {
@@ -2526,24 +2396,17 @@
     self->AssertPendingOOMException();
     return nullptr;
   }
-  *out_location = location;
+  dex_cache->SetLocation(location);
   return dex_cache.Get();
 }
 
 ObjPtr<mirror::DexCache> ClassLinker::AllocAndInitializeDexCache(Thread* self,
                                                                  const DexFile& dex_file,
                                                                  LinearAlloc* linear_alloc) {
-  ObjPtr<mirror::String> location = nullptr;
-  ObjPtr<mirror::DexCache> dex_cache = AllocDexCache(&location, self, dex_file);
+  ObjPtr<mirror::DexCache> dex_cache = AllocDexCache(self, dex_file);
   if (dex_cache != nullptr) {
     WriterMutexLock mu(self, *Locks::dex_lock_);
-    DCHECK(location != nullptr);
-    mirror::DexCache::InitializeDexCache(self,
-                                         dex_cache,
-                                         location,
-                                         &dex_file,
-                                         linear_alloc,
-                                         image_pointer_size_);
+    dex_cache->InitializeNativeFields(&dex_file, linear_alloc);
   }
   return dex_cache;
 }
@@ -2933,31 +2796,31 @@
          IsDelegateLastClassLoader(soa, class_loader))
       << "Unexpected class loader for descriptor " << descriptor;
 
+  const DexFile* dex_file = nullptr;
+  const dex::ClassDef* class_def = nullptr;
   ObjPtr<mirror::Class> ret;
-  auto define_class = [&](const DexFile* cp_dex_file) REQUIRES_SHARED(Locks::mutator_lock_) {
-    const dex::ClassDef* dex_class_def = OatDexFile::FindClassDef(*cp_dex_file, descriptor, hash);
-    if (dex_class_def != nullptr) {
-      ObjPtr<mirror::Class> klass = DefineClass(soa.Self(),
-                                                descriptor,
-                                                hash,
-                                                class_loader,
-                                                *cp_dex_file,
-                                                *dex_class_def);
-      if (klass == nullptr) {
-        CHECK(soa.Self()->IsExceptionPending()) << descriptor;
-        FilterDexFileCaughtExceptions(soa.Self(), this);
-        // TODO: Is it really right to break here, and not check the other dex files?
-      } else {
-        DCHECK(!soa.Self()->IsExceptionPending());
-      }
-      ret = klass;
-      return false;  // Found a Class (or error == nullptr), stop visit.
+  auto find_class_def = [&](const DexFile* cp_dex_file) REQUIRES_SHARED(Locks::mutator_lock_) {
+    const dex::ClassDef* cp_class_def = OatDexFile::FindClassDef(*cp_dex_file, descriptor, hash);
+    if (cp_class_def != nullptr) {
+      dex_file = cp_dex_file;
+      class_def = cp_class_def;
+      return false;  // Found a class definition, stop visit.
     }
     return true;  // Continue with the next DexFile.
   };
+  VisitClassLoaderDexFiles(soa, class_loader, find_class_def);
 
-  VisitClassLoaderDexFiles(soa, class_loader, define_class);
-  return ret;
+  ObjPtr<mirror::Class> klass = nullptr;
+  if (class_def != nullptr) {
+    klass = DefineClass(soa.Self(), descriptor, hash, class_loader, *dex_file, *class_def);
+    if (UNLIKELY(klass == nullptr)) {
+      CHECK(soa.Self()->IsExceptionPending()) << descriptor;
+      FilterDexFileCaughtExceptions(soa.Self(), this);
+    } else {
+      DCHECK(!soa.Self()->IsExceptionPending());
+    }
+  }
+  return klass;
 }
 
 ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self,
@@ -3199,6 +3062,7 @@
                                                const dex::ClassDef& dex_class_def) {
   ScopedDefiningClass sdc(self);
   StackHandleScope<3> hs(self);
+  metrics::AutoTimer timer{GetMetrics()->ClassLoadingTotalTime()};
   auto klass = hs.NewHandle<mirror::Class>(nullptr);
 
   // Load the class from the dex file.
@@ -3231,6 +3095,21 @@
     return sdc.Finish(nullptr);
   }
 
+  // For AOT-compilation of an app, we may use only a public SDK to resolve symbols. If the SDK
+  // checks are configured (a non null SdkChecker) and the descriptor is not in the provided
+  // public class path then we prevent the definition of the class.
+  //
+  // NOTE that we only do the checks for the boot classpath APIs. Anything else, like the app
+  // classpath is not checked.
+  if (class_loader == nullptr &&
+      Runtime::Current()->IsAotCompiler() &&
+      DenyAccessBasedOnPublicSdk(descriptor)) {
+    ObjPtr<mirror::Throwable> pre_allocated =
+        Runtime::Current()->GetPreAllocatedNoClassDefFoundError();
+    self->SetException(pre_allocated);
+    return sdc.Finish(nullptr);
+  }
+
   // This is to prevent the calls to ClassLoad and ClassPrepare which can cause java/user-supplied
   // code to be executed. We put it up here so we can avoid all the allocations associated with
   // creating the class. This can happen with (eg) jit threads.
@@ -3462,7 +3341,7 @@
     return GetQuickGenericJniStub();
   }
 
-  if (interpreter::CanRuntimeUseNterp() && interpreter::CanMethodUseNterp(method)) {
+  if (interpreter::CanRuntimeUseNterp() && CanMethodUseNterp(method)) {
     return interpreter::GetNterpEntryPoint();
   }
 
@@ -3529,15 +3408,31 @@
   return false;
 }
 
-void ClassLinker::FixupStaticTrampolines(ObjPtr<mirror::Class> klass) {
+void ClassLinker::FixupStaticTrampolines(Thread* self, ObjPtr<mirror::Class> klass) {
   ScopedAssertNoThreadSuspension sants(__FUNCTION__);
   DCHECK(klass->IsVisiblyInitialized()) << klass->PrettyDescriptor();
-  if (klass->NumDirectMethods() == 0) {
+  size_t num_direct_methods = klass->NumDirectMethods();
+  if (num_direct_methods == 0) {
     return;  // No direct methods => no static methods.
   }
   if (UNLIKELY(klass->IsProxyClass())) {
     return;
   }
+  PointerSize pointer_size = image_pointer_size_;
+  if (std::any_of(klass->GetDirectMethods(pointer_size).begin(),
+                  klass->GetDirectMethods(pointer_size).end(),
+                  [](const ArtMethod& m) { return m.IsCriticalNative(); })) {
+    // Store registered @CriticalNative methods, if any, to JNI entrypoints.
+    // Direct methods are a contiguous chunk of memory, so use the ordering of the map.
+    ArtMethod* first_method = klass->GetDirectMethod(0u, pointer_size);
+    ArtMethod* last_method = klass->GetDirectMethod(num_direct_methods - 1u, pointer_size);
+    MutexLock lock(self, critical_native_code_with_clinit_check_lock_);
+    auto lb = critical_native_code_with_clinit_check_.lower_bound(first_method);
+    while (lb != critical_native_code_with_clinit_check_.end() && lb->first <= last_method) {
+      lb->first->SetEntryPointFromJni(lb->second);
+      lb = critical_native_code_with_clinit_check_.erase(lb);
+    }
+  }
   Runtime* runtime = Runtime::Current();
   if (!runtime->IsStarted()) {
     if (runtime->IsAotCompiler() || runtime->GetHeap()->HasBootImageSpace()) {
@@ -3546,18 +3441,13 @@
   }
 
   const DexFile& dex_file = klass->GetDexFile();
-  const uint16_t class_def_idx = klass->GetDexClassDefIndex();
-  CHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
-  ClassAccessor accessor(dex_file, class_def_idx);
-  // There should always be class data if there were direct methods.
-  CHECK(accessor.HasClassData()) << klass->PrettyDescriptor();
   bool has_oat_class;
   OatFile::OatClass oat_class = OatFile::FindOatClass(dex_file,
                                                       klass->GetDexClassDefIndex(),
                                                       &has_oat_class);
   // Link the code of methods skipped by LinkCode.
-  for (size_t method_index = 0; method_index < accessor.NumDirectMethods(); ++method_index) {
-    ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_);
+  for (size_t method_index = 0; method_index < num_direct_methods; ++method_index) {
+    ArtMethod* method = klass->GetDirectMethod(method_index, pointer_size);
     if (!method->IsStatic()) {
       // Only update static methods.
       continue;
@@ -3580,7 +3470,7 @@
 
     if (quick_code == nullptr &&
         interpreter::CanRuntimeUseNterp() &&
-        interpreter::CanMethodUseNterp(method)) {
+        CanMethodUseNterp(method)) {
       quick_code = interpreter::GetNterpEntryPoint();
     }
 
@@ -3662,8 +3552,10 @@
   }
 
   if (method->IsNative()) {
-    // Unregistering restores the dlsym lookup stub.
-    method->UnregisterNative();
+    // Set up the dlsym lookup stub. Do not go through `UnregisterNative()`
+    // as the extra processing for @CriticalNative is not needed yet.
+    method->SetEntryPointFromJni(
+        method->IsCriticalNative() ? GetJniDlsymLookupCriticalStub() : GetJniDlsymLookupStub());
 
     if (enter_interpreter || quick_code == nullptr) {
       // We have a native method here without code. Then it should have the generic JNI
@@ -3887,7 +3779,6 @@
   ScopedAssertNoThreadSuspension ants("LoadMethod");
   dst->SetDexMethodIndex(dex_method_idx);
   dst->SetDeclaringClass(klass.Get());
-  dst->SetCodeItemOffset(method.GetCodeItemOffset());
 
   // Get access flags from the DexFile and set hiddenapi runtime access flags.
   uint32_t access_flags = method.GetAccessFlags() | hiddenapi::CreateRuntimeFlags(method);
@@ -3936,6 +3827,41 @@
   if (klass->IsInterface() && dst->IsAbstract()) {
     dst->CalculateAndSetImtIndex();
   }
+  if (dst->HasCodeItem()) {
+    DCHECK_NE(method.GetCodeItemOffset(), 0u);
+    if (Runtime::Current()->IsAotCompiler()) {
+      dst->SetDataPtrSize(reinterpret_cast32<void*>(method.GetCodeItemOffset()), image_pointer_size_);
+    } else {
+      dst->SetCodeItem(dst->GetDexFile()->GetCodeItem(method.GetCodeItemOffset()));
+    }
+  } else {
+    dst->SetDataPtrSize(nullptr, image_pointer_size_);
+    DCHECK_EQ(method.GetCodeItemOffset(), 0u);
+  }
+
+  // Set optimization flags related to the shorty.
+  const char* shorty = dst->GetShorty();
+  bool all_parameters_are_reference = true;
+  bool all_parameters_are_reference_or_int = true;
+  bool return_type_is_fp = (shorty[0] == 'F' || shorty[0] == 'D');
+
+  for (size_t i = 1, e = strlen(shorty); i < e; ++i) {
+    if (shorty[i] != 'L') {
+      all_parameters_are_reference = false;
+      if (shorty[i] == 'F' || shorty[i] == 'D' || shorty[i] == 'J') {
+        all_parameters_are_reference_or_int = false;
+        break;
+      }
+    }
+  }
+
+  if (!dst->IsNative() && all_parameters_are_reference) {
+    dst->SetNterpEntryPointFastPathFlag();
+  }
+
+  if (!return_type_is_fp && all_parameters_are_reference_or_int) {
+    dst->SetNterpInvokeFastPathFlag();
+  }
 }
 
 void ClassLinker::AppendToBootClassPath(Thread* self, const DexFile* dex_file) {
@@ -3962,6 +3888,7 @@
   Thread* const self = Thread::Current();
   Locks::dex_lock_->AssertExclusiveHeld(self);
   CHECK(dex_cache != nullptr) << dex_file.GetLocation();
+  CHECK_EQ(dex_cache->GetDexFile(), &dex_file) << dex_file.GetLocation();
   // For app images, the dex cache location may be a suffix of the dex file location since the
   // dex file location is an absolute path.
   const std::string dex_cache_location = dex_cache->GetLocation()->ToModifiedUtf8();
@@ -4008,7 +3935,6 @@
   hiddenapi::InitializeDexFileDomain(dex_file, class_loader);
 
   jweak dex_cache_jweak = vm->AddWeakGlobalRef(self, dex_cache);
-  dex_cache->SetDexFile(&dex_file);
   DexCacheData data;
   data.weak_root = dex_cache_jweak;
   data.dex_file = dex_cache->GetDexFile();
@@ -4078,10 +4004,11 @@
   }
 }
 
-static void ThrowDexFileAlreadyRegisteredError(Thread* self, const DexFile& dex_file) REQUIRES_SHARED(Locks::mutator_lock_) {
+static void ThrowDexFileAlreadyRegisteredError(Thread* self, const DexFile& dex_file)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
   self->ThrowNewExceptionF("Ljava/lang/InternalError;",
-                            "Attempt to register dex file %s with multiple class loaders",
-                            dex_file.GetLocation().c_str());
+                           "Attempt to register dex file %s with multiple class loaders",
+                           dex_file.GetLocation().c_str());
 }
 
 ObjPtr<mirror::DexCache> ClassLinker::RegisterDexFile(const DexFile& dex_file,
@@ -4121,11 +4048,7 @@
   // get to a suspend point.
   StackHandleScope<3> hs(self);
   Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
-  ObjPtr<mirror::String> location;
-  Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(AllocDexCache(/*out*/&location,
-                                                                  self,
-                                                                  dex_file)));
-  Handle<mirror::String> h_location(hs.NewHandle(location));
+  Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(AllocDexCache(self, dex_file)));
   {
     // Avoid a deadlock between a garbage collecting thread running a checkpoint,
     // a thread holding the dex lock and blocking on a condition variable regarding
@@ -4135,15 +4058,10 @@
     const DexCacheData* old_data = FindDexCacheDataLocked(dex_file);
     old_dex_cache = DecodeDexCacheLocked(self, old_data);
     if (old_dex_cache == nullptr && h_dex_cache != nullptr) {
-      // Do InitializeDexCache while holding dex lock to make sure two threads don't call it at the
-      // same time with the same dex cache. Since the .bss is shared this can cause failing DCHECK
-      // that the arrays are null.
-      mirror::DexCache::InitializeDexCache(self,
-                                           h_dex_cache.Get(),
-                                           h_location.Get(),
-                                           &dex_file,
-                                           linear_alloc,
-                                           image_pointer_size_);
+      // Do InitializeNativeFields while holding dex lock to make sure two threads don't call it
+      // at the same time with the same dex cache. Since the .bss is shared this can cause failing
+      // DCHECK that the arrays are null.
+      h_dex_cache->InitializeNativeFields(&dex_file, linear_alloc);
       RegisterDexFileLocked(dex_file, h_dex_cache.Get(), h_class_loader.Get());
     }
     if (old_dex_cache != nullptr) {
@@ -4174,6 +4092,8 @@
     // remembered sets and generational GCs.
     WriteBarrier::ForEveryFieldWrite(h_class_loader.Get());
   }
+  VLOG(class_linker) << "Registered dex file " << dex_file.GetLocation();
+  PaletteNotifyDexFileLoaded(dex_file.GetLocation().c_str());
   return h_dex_cache.Get();
 }
 
@@ -4561,6 +4481,7 @@
 }
 
 bool ClassLinker::AttemptSupertypeVerification(Thread* self,
+                                               verifier::VerifierDeps* verifier_deps,
                                                Handle<mirror::Class> klass,
                                                Handle<mirror::Class> supertype) {
   DCHECK(self != nullptr);
@@ -4568,7 +4489,7 @@
   DCHECK(supertype != nullptr);
 
   if (!supertype->IsVerified() && !supertype->IsErroneous()) {
-    VerifyClass(self, supertype);
+    VerifyClass(self, verifier_deps, supertype);
   }
 
   if (supertype->IsVerified()
@@ -4605,8 +4526,10 @@
   return false;
 }
 
-verifier::FailureKind ClassLinker::VerifyClass(
-    Thread* self, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level) {
+verifier::FailureKind ClassLinker::VerifyClass(Thread* self,
+                                               verifier::VerifierDeps* verifier_deps,
+                                               Handle<mirror::Class> klass,
+                                               verifier::HardFailLogMode log_level) {
   {
     // TODO: assert that the monitor on the Class is held
     ObjectLock<mirror::Class> lock(self, klass);
@@ -4635,6 +4558,22 @@
     // Don't attempt to re-verify if already verified.
     if (klass->IsVerified()) {
       EnsureSkipAccessChecksMethods(klass, image_pointer_size_);
+      if (verifier_deps != nullptr &&
+          verifier_deps->ContainsDexFile(klass->GetDexFile()) &&
+          !verifier_deps->HasRecordedVerifiedStatus(klass->GetDexFile(), *klass->GetClassDef()) &&
+          !Runtime::Current()->IsAotCompiler()) {
+        // If the klass is verified, but `verifier_deps` did not record it, this
+        // means we are running background verification of a secondary dex file.
+        // Re-run the verifier to populate `verifier_deps`.
+        // No need to run the verification when running on the AOT Compiler, as
+        // the driver handles those multithreaded cases already.
+        std::string error_msg;
+        verifier::FailureKind failure =
+            PerformClassVerification(self, verifier_deps, klass, log_level, &error_msg);
+        // We could have soft failures, so just check that we don't have a hard
+        // failure.
+        DCHECK_NE(failure, verifier::FailureKind::kHardFailure) << error_msg;
+      }
       return verifier::FailureKind::kNoFailure;
     }
 
@@ -4674,7 +4613,8 @@
   StackHandleScope<2> hs(self);
   MutableHandle<mirror::Class> supertype(hs.NewHandle(klass->GetSuperClass()));
   // If we have a superclass and we get a hard verification failure we can return immediately.
-  if (supertype != nullptr && !AttemptSupertypeVerification(self, klass, supertype)) {
+  if (supertype != nullptr &&
+      !AttemptSupertypeVerification(self, verifier_deps, klass, supertype)) {
     CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
     return verifier::FailureKind::kHardFailure;
   }
@@ -4700,7 +4640,7 @@
       // We only care if we have default interfaces and can skip if we are already verified...
       if (LIKELY(!iface->HasDefaultMethods() || iface->IsVerified())) {
         continue;
-      } else if (UNLIKELY(!AttemptSupertypeVerification(self, klass, iface))) {
+      } else if (UNLIKELY(!AttemptSupertypeVerification(self, verifier_deps, klass, iface))) {
         // We had a hard failure while verifying this interface. Just return immediately.
         CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
         return verifier::FailureKind::kHardFailure;
@@ -4723,7 +4663,7 @@
   // Try to use verification information from the oat file, otherwise do runtime verification.
   const DexFile& dex_file = *klass->GetDexCache()->GetDexFile();
   ClassStatus oat_file_class_status(ClassStatus::kNotReady);
-  bool preverified = VerifyClassUsingOatFile(dex_file, klass.Get(), oat_file_class_status);
+  bool preverified = VerifyClassUsingOatFile(self, dex_file, klass, oat_file_class_status);
 
   VLOG(class_linker) << "Class preverified status for class "
                      << klass->PrettyDescriptor()
@@ -4740,7 +4680,7 @@
   std::string error_msg;
   verifier::FailureKind verifier_failure = verifier::FailureKind::kNoFailure;
   if (!preverified) {
-    verifier_failure = PerformClassVerification(self, klass, log_level, &error_msg);
+    verifier_failure = PerformClassVerification(self, verifier_deps, klass, log_level, &error_msg);
   }
 
   // Verification is done, grab the lock again.
@@ -4772,12 +4712,14 @@
       }
     } else {
       CHECK(verifier_failure == verifier::FailureKind::kSoftFailure ||
+            verifier_failure == verifier::FailureKind::kTypeChecksFailure ||
             verifier_failure == verifier::FailureKind::kAccessChecksFailure);
       // Soft failures at compile time should be retried at runtime. Soft
       // failures at runtime will be handled by slow paths in the generated
       // code. Set status accordingly.
       if (Runtime::Current()->IsAotCompiler()) {
-        if (verifier_failure == verifier::FailureKind::kSoftFailure) {
+        if (verifier_failure == verifier::FailureKind::kSoftFailure ||
+            verifier_failure == verifier::FailureKind::kTypeChecksFailure) {
           mirror::Class::SetStatus(klass, ClassStatus::kRetryVerificationAtRuntime, self);
         } else {
           mirror::Class::SetStatus(klass, ClassStatus::kVerifiedNeedsAccessChecks, self);
@@ -4823,11 +4765,13 @@
 }
 
 verifier::FailureKind ClassLinker::PerformClassVerification(Thread* self,
+                                                            verifier::VerifierDeps* verifier_deps,
                                                             Handle<mirror::Class> klass,
                                                             verifier::HardFailLogMode log_level,
                                                             std::string* error_msg) {
   Runtime* const runtime = Runtime::Current();
   return verifier::ClassVerifier::VerifyClass(self,
+                                              verifier_deps,
                                               klass.Get(),
                                               runtime->GetCompilerCallbacks(),
                                               runtime->IsAotCompiler(),
@@ -4836,8 +4780,9 @@
                                               error_msg);
 }
 
-bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file,
-                                          ObjPtr<mirror::Class> klass,
+bool ClassLinker::VerifyClassUsingOatFile(Thread* self,
+                                          const DexFile& dex_file,
+                                          Handle<mirror::Class> klass,
                                           ClassStatus& oat_file_class_status) {
   // If we're compiling, we can only verify the class using the oat file if
   // we are not compiling the image or if the class we're verifying is not part of
@@ -4846,7 +4791,7 @@
   if (Runtime::Current()->IsAotCompiler()) {
     CompilerCallbacks* callbacks = Runtime::Current()->GetCompilerCallbacks();
     // We are compiling an app (not the image).
-    if (!callbacks->CanUseOatStatusForVerification(klass.Ptr())) {
+    if (!callbacks->CanUseOatStatusForVerification(klass.Get())) {
       return false;
     }
   }
@@ -4867,6 +4812,16 @@
     // check the class status to ensure we run with access checks.
     return true;
   }
+
+  // Check the class status with the vdex file.
+  const OatFile* oat_file = oat_dex_file->GetOatFile();
+  if (oat_file != nullptr) {
+    oat_file_class_status = oat_file->GetVdexFile()->ComputeClassStatus(self, klass);
+    if (oat_file_class_status >= ClassStatus::kVerifiedNeedsAccessChecks) {
+      return true;
+    }
+  }
+
   // If we only verified a subset of the classes at compile time, we can end up with classes that
   // were resolved by the verifier.
   if (oat_file_class_status == ClassStatus::kResolved) {
@@ -5094,7 +5049,9 @@
     Handle<mirror::ObjectArray<mirror::Class>> h_interfaces(
         hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>>(interfaces)));
     if (!LinkClass(self, descriptor, temp_klass, h_interfaces, &klass)) {
-      mirror::Class::SetStatus(temp_klass, ClassStatus::kErrorUnresolved, self);
+      if (!temp_klass->IsErroneous()) {
+        mirror::Class::SetStatus(temp_klass, ClassStatus::kErrorUnresolved, self);
+      }
       return nullptr;
     }
   }
@@ -5132,7 +5089,7 @@
     callback->MakeVisible(self);
   }
 
-  // sanity checks
+  // Consistency checks.
   if (kIsDebugBuild) {
     CHECK(klass->GetIFieldsPtr() == nullptr);
     CheckProxyConstructor(klass->GetDirectMethod(0, image_pointer_size_));
@@ -5205,18 +5162,14 @@
 
   // Set class to be the concrete proxy class.
   out->SetDeclaringClass(klass.Get());
-  // Clear the abstract, default and conflict flags to ensure that defaults aren't picked in
+  // Clear the abstract and default flags to ensure that defaults aren't picked in
   // preference to the invocation handler.
-  const uint32_t kRemoveFlags = kAccAbstract | kAccDefault | kAccDefaultConflict;
+  const uint32_t kRemoveFlags = kAccAbstract | kAccDefault;
   // Make the method final.
   // Mark kAccCompileDontBother so that we don't take JIT samples for the method. b/62349349
   const uint32_t kAddFlags = kAccFinal | kAccCompileDontBother;
   out->SetAccessFlags((out->GetAccessFlags() & ~kRemoveFlags) | kAddFlags);
 
-  // Clear the dex_code_item_offset_. It needs to be 0 since proxy methods have no CodeItems but the
-  // method they copy might (if it's a default method).
-  out->SetCodeItemOffset(0);
-
   // Set the original interface method.
   out->SetDataPtrSize(prototype, image_pointer_size_);
 
@@ -5226,7 +5179,7 @@
 }
 
 void ClassLinker::CheckProxyMethod(ArtMethod* method, ArtMethod* prototype) const {
-  // Basic sanity
+  // Basic consistency checks.
   CHECK(!prototype->IsFinal());
   CHECK(method->IsFinal());
   CHECK(method->IsInvokable());
@@ -5280,8 +5233,10 @@
   return can_init_parents && CanWeInitializeClass(super_class, can_init_statics, can_init_parents);
 }
 
-bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
-                                  bool can_init_statics, bool can_init_parents) {
+bool ClassLinker::InitializeClass(Thread* self,
+                                  Handle<mirror::Class> klass,
+                                  bool can_init_statics,
+                                  bool can_init_parents) {
   // see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol
 
   // Are we already initialized and therefore done?
@@ -5297,6 +5252,8 @@
   }
 
   self->AllowThreadSuspension();
+  Runtime* const runtime = Runtime::Current();
+  const bool stats_enabled = runtime->HasStatsEnabled();
   uint64_t t0;
   {
     ObjectLock<mirror::Class> lock(self, klass);
@@ -5317,7 +5274,7 @@
         << klass->PrettyClass() << ": state=" << klass->GetStatus();
 
     if (!klass->IsVerified()) {
-      VerifyClass(self, klass);
+      VerifyClass(self, /*verifier_deps= */ nullptr, klass);
       if (!klass->IsVerified()) {
         // We failed to verify, expect either the klass to be erroneous or verification failed at
         // compile time.
@@ -5384,7 +5341,6 @@
     // is different at runtime than it was at compile time, the oat file is rejected. So if the
     // oat file is present, the classpaths must match, and the runtime time check can be skipped.
     bool has_oat_class = false;
-    const Runtime* runtime = Runtime::Current();
     const OatFile::OatClass oat_class = (runtime->IsStarted() && !runtime->IsAotCompiler())
         ? OatFile::FindOatClass(klass->GetDexFile(), klass->GetDexClassDefIndex(), &has_oat_class)
         : OatFile::OatClass::Invalid();
@@ -5403,7 +5359,7 @@
     klass->SetClinitThreadId(self->GetTid());
     mirror::Class::SetStatus(klass, ClassStatus::kInitializing, self);
 
-    t0 = NanoTime();
+    t0 = stats_enabled ? NanoTime() : 0u;
   }
 
   uint64_t t_sub = 0;
@@ -5416,9 +5372,9 @@
       CHECK(can_init_parents);
       StackHandleScope<1> hs(self);
       Handle<mirror::Class> handle_scope_super(hs.NewHandle(super_class));
-      uint64_t super_t0 = NanoTime();
+      uint64_t super_t0 = stats_enabled ? NanoTime() : 0u;
       bool super_initialized = InitializeClass(self, handle_scope_super, can_init_statics, true);
-      uint64_t super_t1 = NanoTime();
+      uint64_t super_t1 = stats_enabled ? NanoTime() : 0u;
       if (!super_initialized) {
         // The super class was verified ahead of entering initializing, we should only be here if
         // the super class became erroneous due to initialization.
@@ -5457,12 +5413,13 @@
         // We cannot just call initialize class directly because we need to ensure that ALL
         // interfaces with default methods are initialized. Non-default interface initialization
         // will not affect other non-default super-interfaces.
-        uint64_t inf_t0 = NanoTime();  // This is not very precise, misses all walking.
+        // This is not very precise, misses all walking.
+        uint64_t inf_t0 = stats_enabled ? NanoTime() : 0u;
         bool iface_initialized = InitializeDefaultInterfaceRecursive(self,
                                                                      handle_scope_iface,
                                                                      can_init_statics,
                                                                      can_init_parents);
-        uint64_t inf_t1 = NanoTime();
+        uint64_t inf_t1 = stats_enabled ? NanoTime() : 0u;
         if (!iface_initialized) {
           ObjectLock<mirror::Class> lock(self, klass);
           // Initialization failed because one of our interfaces with default methods is erroneous.
@@ -5487,14 +5444,14 @@
     for (size_t i = 0; i < num_static_fields; ++i) {
       ArtField* field = klass->GetStaticField(i);
       const uint32_t field_idx = field->GetDexFieldIndex();
-      ArtField* resolved_field = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
+      ArtField* resolved_field = dex_cache->GetResolvedField(field_idx);
       if (resolved_field == nullptr) {
         // Populating cache of a dex file which defines `klass` should always be allowed.
         DCHECK(!hiddenapi::ShouldDenyAccessToMember(
             field,
             hiddenapi::AccessContext(class_loader.Get(), dex_cache.Get()),
             hiddenapi::AccessMethod::kNone));
-        dex_cache->SetResolvedField(field_idx, field, image_pointer_size_);
+        dex_cache->SetResolvedField(field_idx, field);
       } else {
         DCHECK_EQ(field, resolved_field);
       }
@@ -5541,7 +5498,7 @@
     }
   }
   self->AllowThreadSuspension();
-  uint64_t t1 = NanoTime();
+  uint64_t t1 = stats_enabled ? NanoTime() : 0u;
 
   VisiblyInitializedCallback* callback = nullptr;
   bool success = true;
@@ -5558,16 +5515,18 @@
       VLOG(compiler) << "Return from class initializer of "
                      << mirror::Class::PrettyDescriptor(klass.Get())
                      << " without exception while transaction was aborted: re-throw it now.";
-      Runtime::Current()->ThrowTransactionAbortError(self);
+      runtime->ThrowTransactionAbortError(self);
       mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
       success = false;
     } else {
-      RuntimeStats* global_stats = Runtime::Current()->GetStats();
-      RuntimeStats* thread_stats = self->GetStats();
-      ++global_stats->class_init_count;
-      ++thread_stats->class_init_count;
-      global_stats->class_init_time_ns += (t1 - t0 - t_sub);
-      thread_stats->class_init_time_ns += (t1 - t0 - t_sub);
+      if (stats_enabled) {
+        RuntimeStats* global_stats = runtime->GetStats();
+        RuntimeStats* thread_stats = self->GetStats();
+        ++global_stats->class_init_count;
+        ++thread_stats->class_init_count;
+        global_stats->class_init_time_ns += (t1 - t0 - t_sub);
+        thread_stats->class_init_time_ns += (t1 - t0 - t_sub);
+      }
       // Set the class as initialized except if failed to initialize static fields.
       callback = MarkClassInitialized(self, klass);
       if (VLOG_IS_ON(class_linker)) {
@@ -5914,6 +5873,10 @@
   if (!success) {
     if (can_init_fields && can_init_parents) {
       CHECK(self->IsExceptionPending()) << c->PrettyClass();
+    } else {
+      // There may or may not be an exception pending. If there is, clear it.
+      // We propagate the exception only if we can initialize fields and parents.
+      self->ClearException();
     }
   } else {
     self->AssertNoPendingException();
@@ -6270,6 +6233,81 @@
   return true;
 }
 
+// A wrapper class representing the result of a method translation used for linking methods and
+// updating superclass default methods. For each method in a classes vtable there are 4 states it
+// could be in:
+// 1) No translation is necessary. In this case there is no MethodTranslation object for it. This
+//    is the standard case and is true when the method is not overridable by a default method,
+//    the class defines a concrete implementation of the method, the default method implementation
+//    remains the same, or an abstract method stayed abstract.
+// 2) The method must be translated to a different default method. We note this with
+//    CreateTranslatedMethod.
+// 3) The method must be replaced with a conflict method. This happens when a superclass
+//    implements an interface with a default method and this class implements an unrelated
+//    interface that also defines that default method. We note this with CreateConflictingMethod.
+// 4) The method must be replaced with an abstract miranda method. This happens when a superclass
+//    implements an interface with a default method and this class implements a subinterface of
+//    the superclass's interface which declares the default method abstract. We note this with
+//    CreateAbstractMethod.
+//
+// When a method translation is unnecessary (case #1), we don't put it into the
+// default_translation maps. So an instance of MethodTranslation must be in one of #2-#4.
+class ClassLinker::MethodTranslation {
+ public:
+  MethodTranslation() : translation_(nullptr), type_(Type::kInvalid) {}
+
+  // This slot must become a default conflict method.
+  static MethodTranslation CreateConflictingMethod() {
+    return MethodTranslation(Type::kConflict, /*translation=*/nullptr);
+  }
+
+  // This slot must become an abstract method.
+  static MethodTranslation CreateAbstractMethod() {
+    return MethodTranslation(Type::kAbstract, /*translation=*/nullptr);
+  }
+
+  // Use the given method as the current value for this vtable slot during translation.
+  static MethodTranslation CreateTranslatedMethod(ArtMethod* new_method) {
+    return MethodTranslation(Type::kTranslation, new_method);
+  }
+
+  // Returns true if this is a method that must become a conflict method.
+  bool IsInConflict() const {
+    return type_ == Type::kConflict;
+  }
+
+  // Returns true if this is a method that must become an abstract method.
+  bool IsAbstract() const {
+    return type_ == Type::kAbstract;
+  }
+
+  // Returns true if this is a method that must become a different method.
+  bool IsTranslation() const {
+    return type_ == Type::kTranslation;
+  }
+
+  // Get the translated version of this method.
+  ArtMethod* GetTranslation() const {
+    DCHECK(IsTranslation());
+    DCHECK(translation_ != nullptr);
+    return translation_;
+  }
+
+ private:
+  enum class Type {
+    kInvalid,
+    kTranslation,
+    kConflict,
+    kAbstract,
+  };
+
+  MethodTranslation(Type type, ArtMethod* translation)
+      : translation_(translation), type_(type) {}
+
+  ArtMethod* translation_;
+  Type type_;
+};
+
 // Populate the class vtable and itable. Compute return type indices.
 bool ClassLinker::LinkMethods(Thread* self,
                               Handle<mirror::Class> klass,
@@ -6280,7 +6318,9 @@
   // A map from vtable indexes to the method they need to be updated to point to. Used because we
   // need to have default methods be in the virtuals array of each class but we don't set that up
   // until LinkInterfaceMethods.
-  std::unordered_map<size_t, ClassLinker::MethodTranslation> default_translations;
+  constexpr size_t kBufferSize = 8;  // Avoid malloc/free for a few translations.
+  std::pair<size_t, ClassLinker::MethodTranslation> buffer[kBufferSize];
+  HashMap<size_t, ClassLinker::MethodTranslation> default_translations(buffer, kBufferSize);
   // Link virtual methods then interface methods.
   // We set up the interface lookup table first because we need it to determine if we need to update
   // any vtable entries with new default method implementations.
@@ -6365,10 +6405,9 @@
     hash_table_[index] = virtual_method_index;
   }
 
-  uint32_t FindAndRemove(MethodNameAndSignatureComparator* comparator)
+  uint32_t FindAndRemove(MethodNameAndSignatureComparator* comparator, uint32_t hash)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    const char* name = comparator->GetName();
-    uint32_t hash = ComputeModifiedUtf8Hash(name);
+    DCHECK_EQ(hash, ComputeModifiedUtf8Hash(comparator->GetName()));
     size_t index = hash % hash_size_;
     while (true) {
       const uint32_t value = hash_table_[index];
@@ -6413,7 +6452,7 @@
 bool ClassLinker::LinkVirtualMethods(
     Thread* self,
     Handle<mirror::Class> klass,
-    /*out*/std::unordered_map<size_t, ClassLinker::MethodTranslation>* default_translations) {
+    /*out*/HashMap<size_t, ClassLinker::MethodTranslation>* default_translations) {
   const size_t num_virtual_methods = klass->NumVirtualMethods();
   if (klass->IsInterface()) {
     // No vtable.
@@ -6538,7 +6577,10 @@
           super_method->GetInterfaceMethodIfProxy(image_pointer_size_));
       // We remove the method so that subsequent lookups will be faster by making the hash-map
       // smaller as we go on.
-      uint32_t hash_index = hash_table.FindAndRemove(&super_method_name_comparator);
+      uint32_t hash = (j < mirror::Object::kVTableLength)
+          ? object_virtual_method_hashes_[j]
+          : ComputeModifiedUtf8Hash(super_method_name_comparator.GetName());
+      uint32_t hash_index = hash_table.FindAndRemove(&super_method_name_comparator, hash);
       if (hash_index != hash_table.GetNotFoundIndex()) {
         ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(
             hash_index, image_pointer_size_);
@@ -6649,6 +6691,9 @@
       virtual_method->SetMethodIndex(i & 0xFFFF);
     }
     klass->SetVTable(vtable);
+    InitializeObjectVirtualMethodHashes(klass.Get(),
+                                        image_pointer_size_,
+                                        ArrayRef<uint32_t>(object_virtual_method_hashes_));
   }
   return true;
 }
@@ -6825,15 +6870,13 @@
 ArtMethod* ClassLinker::AddMethodToConflictTable(ObjPtr<mirror::Class> klass,
                                                  ArtMethod* conflict_method,
                                                  ArtMethod* interface_method,
-                                                 ArtMethod* method,
-                                                 bool force_new_conflict_method) {
+                                                 ArtMethod* method) {
   ImtConflictTable* current_table = conflict_method->GetImtConflictTable(kRuntimePointerSize);
   Runtime* const runtime = Runtime::Current();
   LinearAlloc* linear_alloc = GetAllocatorForClassLoader(klass->GetClassLoader());
-  bool new_entry = conflict_method == runtime->GetImtConflictMethod() || force_new_conflict_method;
 
   // Create a new entry if the existing one is the shared conflict method.
-  ArtMethod* new_conflict_method = new_entry
+  ArtMethod* new_conflict_method = (conflict_method == runtime->GetImtConflictMethod())
       ? runtime->CreateImtConflictMethod(linear_alloc)
       : conflict_method;
 
@@ -6949,9 +6992,6 @@
                        &new_conflict,
                        &imt_data[0]);
   }
-  if (!klass->ShouldHaveImt()) {
-    return;
-  }
   // Compare the IMT with the super class including the conflict methods. If they are equivalent,
   // we can just use the same pointer.
   ImTable* imt = nullptr;
@@ -7115,7 +7155,7 @@
 // Simple helper function that checks that no subtypes of 'val' are contained within the 'classes'
 // set.
 static bool NotSubinterfaceOfAny(
-    const std::unordered_set<ObjPtr<mirror::Class>, HashObjPtr>& classes,
+    const HashSet<mirror::Class*>& classes,
     ObjPtr<mirror::Class> val)
     REQUIRES(Roles::uninterruptible_)
     REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -7147,22 +7187,32 @@
 // super_ifcount entries filled in with the transitive closure of the interfaces of the superclass.
 // The other entries are uninitialized.  We will fill in the remaining entries in this function. The
 // iftable must be large enough to hold all interfaces without changing its size.
-static size_t FillIfTable(ObjPtr<mirror::IfTable> iftable,
+static size_t FillIfTable(Thread* self,
+                          ObjPtr<mirror::Class> klass,
+                          ObjPtr<mirror::ObjectArray<mirror::Class>> interfaces,
+                          ObjPtr<mirror::IfTable> iftable,
                           size_t super_ifcount,
-                          const std::vector<ObjPtr<mirror::Class>>& to_process)
-    REQUIRES(Roles::uninterruptible_)
+                          size_t num_interfaces)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  // This is the set of all class's already in the iftable. Used to make checking if a class has
-  // already been added quicker.
-  std::unordered_set<ObjPtr<mirror::Class>, HashObjPtr> classes_in_iftable;
+  ScopedAssertNoThreadSuspension nts(__FUNCTION__);
+  // This is the set of all classes already in the iftable. Used to make checking
+  // if a class has already been added quicker.
+  constexpr size_t kBufferSize = 32;  // 256 bytes on 64-bit architectures.
+  mirror::Class* buffer[kBufferSize];
+  HashSet<mirror::Class*> classes_in_iftable(buffer, kBufferSize);
   // The first super_ifcount elements are from the superclass. We note that they are already added.
   for (size_t i = 0; i < super_ifcount; i++) {
     ObjPtr<mirror::Class> iface = iftable->GetInterface(i);
     DCHECK(NotSubinterfaceOfAny(classes_in_iftable, iface)) << "Bad ordering.";
-    classes_in_iftable.insert(iface);
+    classes_in_iftable.insert(iface.Ptr());
   }
   size_t filled_ifcount = super_ifcount;
-  for (ObjPtr<mirror::Class> interface : to_process) {
+  const bool have_interfaces = interfaces != nullptr;
+  for (size_t i = 0; i != num_interfaces; ++i) {
+    ObjPtr<mirror::Class> interface = have_interfaces
+        ? interfaces->Get(i)
+        : mirror::Class::GetDirectInterface(self, klass, i);
+
     // Let us call the first filled_ifcount elements of iftable the current-iface-list.
     // At this point in the loop current-iface-list has the invariant that:
     //    for every pair of interfaces I,J within it:
@@ -7170,7 +7220,7 @@
 
     // If we have already seen this element then all of its super-interfaces must already be in the
     // current-iface-list so we can skip adding it.
-    if (!ContainsElement(classes_in_iftable, interface)) {
+    if (classes_in_iftable.find(interface.Ptr()) == classes_in_iftable.end()) {
       // We haven't seen this interface so add all of its super-interfaces onto the
       // current-iface-list, skipping those already on it.
       int32_t ifcount = interface->GetIfTableCount();
@@ -7178,14 +7228,14 @@
         ObjPtr<mirror::Class> super_interface = interface->GetIfTable()->GetInterface(j);
         if (!ContainsElement(classes_in_iftable, super_interface)) {
           DCHECK(NotSubinterfaceOfAny(classes_in_iftable, super_interface)) << "Bad ordering.";
-          classes_in_iftable.insert(super_interface);
+          classes_in_iftable.insert(super_interface.Ptr());
           iftable->SetInterface(filled_ifcount, super_interface);
           filled_ifcount++;
         }
       }
       DCHECK(NotSubinterfaceOfAny(classes_in_iftable, interface)) << "Bad ordering";
       // Place this interface onto the current-iface-list after all of its super-interfaces.
-      classes_in_iftable.insert(interface);
+      classes_in_iftable.insert(interface.Ptr());
       iftable->SetInterface(filled_ifcount, interface);
       filled_ifcount++;
     } else if (kIsDebugBuild) {
@@ -7217,7 +7267,8 @@
   return filled_ifcount;
 }
 
-bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class> klass,
+bool ClassLinker::SetupInterfaceLookupTable(Thread* self,
+                                            Handle<mirror::Class> klass,
                                             Handle<mirror::ObjectArray<mirror::Class>> interfaces) {
   StackHandleScope<1> hs(self);
   const bool has_superclass = klass->HasSuperClass();
@@ -7286,18 +7337,8 @@
   // doesn't really do anything.
   self->AllowThreadSuspension();
 
-  size_t new_ifcount;
-  {
-    ScopedAssertNoThreadSuspension nts("Copying mirror::Class*'s for FillIfTable");
-    std::vector<ObjPtr<mirror::Class>> to_add;
-    for (size_t i = 0; i < num_interfaces; i++) {
-      ObjPtr<mirror::Class> interface = have_interfaces ? interfaces->Get(i) :
-          mirror::Class::GetDirectInterface(self, klass.Get(), i);
-      to_add.push_back(interface);
-    }
-
-    new_ifcount = FillIfTable(iftable.Get(), super_ifcount, std::move(to_add));
-  }
+  const size_t new_ifcount = FillIfTable(
+      self, klass.Get(), interfaces.Get(), iftable.Get(), super_ifcount, num_interfaces);
 
   self->AllowThreadSuspension();
 
@@ -7435,7 +7476,7 @@
           return BaseHashType::HashCombine(BaseHashType::HashCombine(0, key.first), key.second);
         }
       };
-      std::unordered_map<PairType, int32_t, PairHash> seen;
+      HashMap<PairType, int32_t, DefaultMapEmptyFn<PairType, int32_t>, PairHash> seen;
       seen.reserve(2 * num_entries);
       bool need_slow_path = false;
       bool found_dup = false;
@@ -7461,7 +7502,7 @@
             log_fn(it->second, i);
           }
         } else {
-          seen.emplace(pair, i);
+          seen.insert(std::make_pair(pair, i));
         }
       }
       return std::make_pair(need_slow_path, found_dup);
@@ -7478,20 +7519,31 @@
   // Need to check across dex files.
   struct Entry {
     size_t cached_hash = 0;
+    uint32_t name_len = 0;
     const char* name = nullptr;
     Signature signature = Signature::NoSignature();
-    uint32_t name_len = 0;
+
+    Entry() = default;
+    Entry(const Entry& other) = default;
+    Entry& operator=(const Entry& other) = default;
 
     Entry(const DexFile* dex_file, const dex::MethodId& mid)
-        : name(dex_file->StringDataAndUtf16LengthByIdx(mid.name_idx_, &name_len)),
+        : name_len(0),  // Explicit to enforce ordering with -Werror,-Wreorder-ctor.
+          // This call writes `name_len` and it is therefore necessary that the
+          // initializer for `name_len` comes before it, otherwise the value
+          // from the call would be overwritten by that initializer.
+          name(dex_file->StringDataAndUtf16LengthByIdx(mid.name_idx_, &name_len)),
           signature(dex_file->GetMethodSignature(mid)) {
+      // The `name_len` has been initialized to the UTF16 length. Calculate length in bytes.
+      if (name[name_len] != 0) {
+        name_len += strlen(name + name_len);
+      }
     }
 
     bool operator==(const Entry& other) const {
-      if (name_len != other.name_len || strcmp(name, other.name) != 0) {
-        return false;
-      }
-      return signature == other.signature;
+      return name_len == other.name_len &&
+             memcmp(name, other.name, name_len) == 0 &&
+             signature == other.signature;
     }
   };
   struct EntryHash {
@@ -7499,7 +7551,7 @@
       return key.cached_hash;
     }
   };
-  std::unordered_map<Entry, int32_t, EntryHash> map;
+  HashMap<Entry, int32_t, DefaultMapEmptyFn<Entry, int32_t>, EntryHash> map;
   for (int32_t i = 0; i < num_entries; ++i) {
     // Can use Unchecked here as the first loop already ensured that the arrays are correct
     // wrt/ kPointerSize.
@@ -7525,7 +7577,7 @@
     if (it != map.end()) {
       log_fn(it->second, i);
     } else {
-      map.emplace(e, i);
+      map.insert(std::make_pair(e, i));
     }
   }
 }
@@ -7544,7 +7596,7 @@
   }
 }
 
-static void SanityCheckVTable(Thread* self, Handle<mirror::Class> klass, PointerSize pointer_size)
+static void CheckVTable(Thread* self, Handle<mirror::Class> klass, PointerSize pointer_size)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   CheckClassOwnsVTableEntries(self, klass, pointer_size);
   CheckVTableHasNoDuplicates(self, klass, pointer_size);
@@ -7622,7 +7674,7 @@
   void ReallocMethods() REQUIRES_SHARED(Locks::mutator_lock_);
 
   ObjPtr<mirror::PointerArray> UpdateVtable(
-      const std::unordered_map<size_t, ClassLinker::MethodTranslation>& default_translations,
+      const HashMap<size_t, ClassLinker::MethodTranslation>& default_translations,
       Handle<mirror::PointerArray> old_vtable) REQUIRES_SHARED(Locks::mutator_lock_);
 
   void UpdateIfTable(Handle<mirror::IfTable> iftable) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -7635,7 +7687,7 @@
       // Check that there are no stale methods are in the dex cache array.
       auto* resolved_methods = klass_->GetDexCache()->GetResolvedMethods();
       for (size_t i = 0, count = klass_->GetDexCache()->NumResolvedMethods(); i < count; ++i) {
-        auto pair = mirror::DexCache::GetNativePairPtrSize(resolved_methods, i, pointer_size);
+        auto pair = mirror::DexCache::GetNativePair(resolved_methods, i);
         ArtMethod* m = pair.object;
         CHECK(move_table_.find(m) == move_table_.end() ||
               // The original versions of copied methods will still be present so allow those too.
@@ -7874,9 +7926,11 @@
     ArtMethod* mir_method = miranda_methods_[i];
     ArtMethod& new_method = *out;
     new_method.CopyFrom(mir_method, pointer_size);
-    new_method.SetAccessFlags(new_method.GetAccessFlags() | kAccMiranda | kAccCopied);
-    DCHECK_NE(new_method.GetAccessFlags() & kAccAbstract, 0u)
-        << "Miranda method should be abstract!";
+    uint32_t access_flags = new_method.GetAccessFlags();
+    DCHECK_EQ(access_flags & kAccIntrinsic, 0u) << "Miranda method should not be an intrinsic!";
+    DCHECK_EQ(access_flags & kAccDefault, 0u) << "Miranda method should not be a default method!";
+    DCHECK_NE(access_flags & kAccAbstract, 0u) << "Miranda method should be abstract!";
+    new_method.SetAccessFlags(access_flags | kAccCopied);
     move_table_.emplace(mir_method, &new_method);
     // Update the entry in the method array, as the array will be used for future lookups,
     // where thread suspension is allowed.
@@ -7921,17 +7975,20 @@
       ArtMethod& new_method = *out;
       new_method.CopyFrom(conf_method, pointer_size);
       // This is a type of default method (there are default method impls, just a conflict) so
-      // mark this as a default, non-abstract method, since thats what it is. Also clear the
-      // kAccSkipAccessChecks bit since this class hasn't been verified yet it shouldn't have
-      // methods that are skipping access checks.
-      // Also clear potential kAccSingleImplementation to avoid CHA trying to inline
-      // the default method.
-      DCHECK_EQ(new_method.GetAccessFlags() & kAccNative, 0u);
-      constexpr uint32_t kSetFlags = kAccDefault | kAccDefaultConflict | kAccCopied;
-      constexpr uint32_t kMaskFlags =
-          ~(kAccAbstract | kAccSkipAccessChecks | kAccSingleImplementation);
-      new_method.SetAccessFlags((new_method.GetAccessFlags() | kSetFlags) & kMaskFlags);
+      // mark this as a default. We use the `kAccAbstract` flag to distinguish it from invokable
+      // copied default method without using a separate access flag but the default conflicting
+      // method is technically not abstract and ArtMethod::IsAbstract() shall return false.
+      // Also clear the kAccSkipAccessChecks bit since this class hasn't been verified yet it
+      // shouldn't have methods that are skipping access checks. Also clear potential
+      // kAccSingleImplementation to avoid CHA trying to inline the default method.
+      uint32_t access_flags = new_method.GetAccessFlags();
+      DCHECK_EQ(access_flags & kAccNative, 0u);
+      DCHECK_EQ(access_flags & kAccIntrinsic, 0u);
+      constexpr uint32_t kSetFlags = kAccDefault | kAccAbstract | kAccCopied;
+      constexpr uint32_t kMaskFlags = ~(kAccSkipAccessChecks | kAccSingleImplementation);
+      new_method.SetAccessFlags((access_flags | kSetFlags) & kMaskFlags);
       DCHECK(new_method.IsDefaultConflicting());
+      DCHECK(!new_method.IsAbstract());
       // The actual method might or might not be marked abstract since we just copied it from a
       // (possibly default) interface method. We need to set it entry point to be the bridge so
       // that the compiler will not invoke the implementation of whatever method we copied from.
@@ -7950,7 +8007,7 @@
 }
 
 ObjPtr<mirror::PointerArray> ClassLinker::LinkInterfaceMethodsHelper::UpdateVtable(
-    const std::unordered_map<size_t, ClassLinker::MethodTranslation>& default_translations,
+    const HashMap<size_t, ClassLinker::MethodTranslation>& default_translations,
     Handle<mirror::PointerArray> old_vtable) {
   // Update the vtable to the new method structures. We can skip this for interfaces since they
   // do not have vtables.
@@ -8075,7 +8132,7 @@
 bool ClassLinker::LinkInterfaceMethods(
     Thread* self,
     Handle<mirror::Class> klass,
-    const std::unordered_map<size_t, ClassLinker::MethodTranslation>& default_translations,
+    const HashMap<size_t, ClassLinker::MethodTranslation>& default_translations,
     bool* out_new_conflict,
     ArtMethod** out_imt) {
   StackHandleScope<3> hs(self);
@@ -8311,59 +8368,197 @@
     self->EndAssertNoThreadSuspension(old_cause);
   }
   if (kIsDebugBuild && !is_interface) {
-    SanityCheckVTable(self, klass, image_pointer_size_);
+    CheckVTable(self, klass, image_pointer_size_);
   }
   return true;
 }
 
-bool ClassLinker::LinkInstanceFields(Thread* self, Handle<mirror::Class> klass) {
-  CHECK(klass != nullptr);
-  return LinkFields(self, klass, false, nullptr);
-}
+class ClassLinker::LinkFieldsHelper {
+ public:
+  static bool LinkFields(ClassLinker* class_linker,
+                         Thread* self,
+                         Handle<mirror::Class> klass,
+                         bool is_static,
+                         size_t* class_size)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
-bool ClassLinker::LinkStaticFields(Thread* self, Handle<mirror::Class> klass, size_t* class_size) {
-  CHECK(klass != nullptr);
-  return LinkFields(self, klass, true, class_size);
-}
+ private:
+  enum class FieldTypeOrder : uint16_t;
+  class FieldGaps;
 
-struct LinkFieldsComparator {
-  LinkFieldsComparator() REQUIRES_SHARED(Locks::mutator_lock_) {
-  }
-  // No thread safety analysis as will be called from STL. Checked lock held in constructor.
-  bool operator()(ArtField* field1, ArtField* field2)
-      NO_THREAD_SAFETY_ANALYSIS {
-    // First come reference fields, then 64-bit, then 32-bit, and then 16-bit, then finally 8-bit.
-    Primitive::Type type1 = field1->GetTypeAsPrimitiveType();
-    Primitive::Type type2 = field2->GetTypeAsPrimitiveType();
-    if (type1 != type2) {
-      if (type1 == Primitive::kPrimNot) {
-        // Reference always goes first.
-        return true;
-      }
-      if (type2 == Primitive::kPrimNot) {
-        // Reference always goes first.
-        return false;
-      }
-      size_t size1 = Primitive::ComponentSize(type1);
-      size_t size2 = Primitive::ComponentSize(type2);
-      if (size1 != size2) {
-        // Larger primitive types go first.
-        return size1 > size2;
-      }
-      // Primitive types differ but sizes match. Arbitrarily order by primitive type.
-      return type1 < type2;
-    }
-    // Same basic group? Then sort by dex field index. This is guaranteed to be sorted
-    // by name and for equal names by type id index.
-    // NOTE: This works also for proxies. Their static fields are assigned appropriate indexes.
-    return field1->GetDexFieldIndex() < field2->GetDexFieldIndex();
-  }
+  struct FieldTypeOrderAndIndex {
+    FieldTypeOrder field_type_order;
+    uint16_t field_index;
+  };
+
+  static FieldTypeOrder FieldTypeOrderFromFirstDescriptorCharacter(char first_char);
+
+  template <size_t kSize>
+  static MemberOffset AssignFieldOffset(ArtField* field, MemberOffset field_offset)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 };
 
-bool ClassLinker::LinkFields(Thread* self,
-                             Handle<mirror::Class> klass,
-                             bool is_static,
-                             size_t* class_size) {
+// We use the following order of field types for assigning offsets.
+// Some fields can be shuffled forward to fill gaps, see `ClassLinker::LinkFields()`.
+enum class ClassLinker::LinkFieldsHelper::FieldTypeOrder : uint16_t {
+  kReference = 0u,
+  kLong,
+  kDouble,
+  kInt,
+  kFloat,
+  kChar,
+  kShort,
+  kBoolean,
+  kByte,
+
+  kLast64BitType = kDouble,
+  kLast32BitType = kFloat,
+  kLast16BitType = kShort,
+};
+
+ALWAYS_INLINE
+ClassLinker::LinkFieldsHelper::FieldTypeOrder
+ClassLinker::LinkFieldsHelper::FieldTypeOrderFromFirstDescriptorCharacter(char first_char) {
+  switch (first_char) {
+    case 'J':
+      return FieldTypeOrder::kLong;
+    case 'D':
+      return FieldTypeOrder::kDouble;
+    case 'I':
+      return FieldTypeOrder::kInt;
+    case 'F':
+      return FieldTypeOrder::kFloat;
+    case 'C':
+      return FieldTypeOrder::kChar;
+    case 'S':
+      return FieldTypeOrder::kShort;
+    case 'Z':
+      return FieldTypeOrder::kBoolean;
+    case 'B':
+      return FieldTypeOrder::kByte;
+    default:
+      DCHECK(first_char == 'L' || first_char == '[') << first_char;
+      return FieldTypeOrder::kReference;
+  }
+}
+
+// Gaps where we can insert fields in object layout.
+class ClassLinker::LinkFieldsHelper::FieldGaps {
+ public:
+  template <uint32_t kSize>
+  ALWAYS_INLINE MemberOffset AlignFieldOffset(MemberOffset field_offset) {
+    static_assert(kSize == 2u || kSize == 4u || kSize == 8u);
+    if (!IsAligned<kSize>(field_offset.Uint32Value())) {
+      uint32_t gap_start = field_offset.Uint32Value();
+      field_offset = MemberOffset(RoundUp(gap_start, kSize));
+      AddGaps<kSize - 1u>(gap_start, field_offset.Uint32Value());
+    }
+    return field_offset;
+  }
+
+  template <uint32_t kSize>
+  bool HasGap() const {
+    static_assert(kSize == 1u || kSize == 2u || kSize == 4u);
+    return (kSize == 1u && gap1_offset_ != kNoOffset) ||
+           (kSize <= 2u && gap2_offset_ != kNoOffset) ||
+           gap4_offset_ != kNoOffset;
+  }
+
+  template <uint32_t kSize>
+  MemberOffset ReleaseGap() {
+    static_assert(kSize == 1u || kSize == 2u || kSize == 4u);
+    uint32_t result;
+    if (kSize == 1u && gap1_offset_ != kNoOffset) {
+      DCHECK(gap2_offset_ == kNoOffset || gap2_offset_ > gap1_offset_);
+      DCHECK(gap4_offset_ == kNoOffset || gap4_offset_ > gap1_offset_);
+      result = gap1_offset_;
+      gap1_offset_ = kNoOffset;
+    } else if (kSize <= 2u && gap2_offset_ != kNoOffset) {
+      DCHECK(gap4_offset_ == kNoOffset || gap4_offset_ > gap2_offset_);
+      result = gap2_offset_;
+      gap2_offset_ = kNoOffset;
+      if (kSize < 2u) {
+        AddGaps<1u>(result + kSize, result + 2u);
+      }
+    } else {
+      DCHECK_NE(gap4_offset_, kNoOffset);
+      result = gap4_offset_;
+      gap4_offset_ = kNoOffset;
+      if (kSize < 4u) {
+        AddGaps<kSize | 2u>(result + kSize, result + 4u);
+      }
+    }
+    return MemberOffset(result);
+  }
+
+ private:
+  template <uint32_t kGapsToCheck>
+  void AddGaps(uint32_t gap_start, uint32_t gap_end) {
+    if ((kGapsToCheck & 1u) != 0u) {
+      DCHECK_LT(gap_start, gap_end);
+      DCHECK_ALIGNED(gap_end, 2u);
+      if ((gap_start & 1u) != 0u) {
+        DCHECK_EQ(gap1_offset_, kNoOffset);
+        gap1_offset_ = gap_start;
+        gap_start += 1u;
+        if (kGapsToCheck == 1u || gap_start == gap_end) {
+          DCHECK_EQ(gap_start, gap_end);
+          return;
+        }
+      }
+    }
+
+    if ((kGapsToCheck & 2u) != 0u) {
+      DCHECK_LT(gap_start, gap_end);
+      DCHECK_ALIGNED(gap_start, 2u);
+      DCHECK_ALIGNED(gap_end, 4u);
+      if ((gap_start & 2u) != 0u) {
+        DCHECK_EQ(gap2_offset_, kNoOffset);
+        gap2_offset_ = gap_start;
+        gap_start += 2u;
+        if (kGapsToCheck <= 3u || gap_start == gap_end) {
+          DCHECK_EQ(gap_start, gap_end);
+          return;
+        }
+      }
+    }
+
+    if ((kGapsToCheck & 4u) != 0u) {
+      DCHECK_LT(gap_start, gap_end);
+      DCHECK_ALIGNED(gap_start, 4u);
+      DCHECK_ALIGNED(gap_end, 8u);
+      DCHECK_EQ(gap_start + 4u, gap_end);
+      DCHECK_EQ(gap4_offset_, kNoOffset);
+      gap4_offset_ = gap_start;
+      return;
+    }
+
+    DCHECK(false) << "Remaining gap: " << gap_start << " to " << gap_end
+        << " after checking " << kGapsToCheck;
+  }
+
+  static constexpr uint32_t kNoOffset = static_cast<uint32_t>(-1);
+
+  uint32_t gap4_offset_ = kNoOffset;
+  uint32_t gap2_offset_ = kNoOffset;
+  uint32_t gap1_offset_ = kNoOffset;
+};
+
+template <size_t kSize>
+ALWAYS_INLINE
+MemberOffset ClassLinker::LinkFieldsHelper::AssignFieldOffset(ArtField* field,
+                                                              MemberOffset field_offset) {
+  DCHECK_ALIGNED(field_offset.Uint32Value(), kSize);
+  DCHECK_EQ(Primitive::ComponentSize(field->GetTypeAsPrimitiveType()), kSize);
+  field->SetOffset(field_offset);
+  return MemberOffset(field_offset.Uint32Value() + kSize);
+}
+
+bool ClassLinker::LinkFieldsHelper::LinkFields(ClassLinker* class_linker,
+                                               Thread* self,
+                                               Handle<mirror::Class> klass,
+                                               bool is_static,
+                                               size_t* class_size) {
   self->AllowThreadSuspension();
   const size_t num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
   LengthPrefixedArray<ArtField>* const fields = is_static ? klass->GetSFieldsPtr() :
@@ -8372,7 +8567,8 @@
   // Initialize field_offset
   MemberOffset field_offset(0);
   if (is_static) {
-    field_offset = klass->GetFirstReferenceStaticFieldOffsetDuringLinking(image_pointer_size_);
+    field_offset = klass->GetFirstReferenceStaticFieldOffsetDuringLinking(
+        class_linker->GetImagePointerSize());
   } else {
     ObjPtr<mirror::Class> super_class = klass->GetSuperClass();
     if (super_class != nullptr) {
@@ -8398,54 +8594,177 @@
   // 8) All java boolean (8-bit) integer fields, sorted alphabetically.
   // 9) All java byte (8-bit) integer fields, sorted alphabetically.
   //
-  // Once the fields are sorted in this order we will attempt to fill any gaps that might be present
-  // in the memory layout of the structure. See ShuffleForward for how this is done.
-  std::deque<ArtField*> grouped_and_sorted_fields;
+  // (References are first to increase the chance of reference visiting
+  // being able to take a fast path using a bitmap of references at the
+  // start of the object, see `Class::reference_instance_offsets_`.)
+  //
+  // Once the fields are sorted in this order we will attempt to fill any gaps
+  // that might be present in the memory layout of the structure.
+  // Note that we shall not fill gaps between the superclass fields.
+
+  // Collect fields and their "type order index" (see numbered points above).
   const char* old_no_suspend_cause = self->StartAssertNoThreadSuspension(
-      "Naked ArtField references in deque");
-  for (size_t i = 0; i < num_fields; i++) {
-    grouped_and_sorted_fields.push_back(&fields->At(i));
+      "Using plain ArtField references");
+  constexpr size_t kStackBufferEntries = 64;  // Avoid allocations for small number of fields.
+  FieldTypeOrderAndIndex stack_buffer[kStackBufferEntries];
+  std::vector<FieldTypeOrderAndIndex> heap_buffer;
+  ArrayRef<FieldTypeOrderAndIndex> sorted_fields;
+  if (num_fields <= kStackBufferEntries) {
+    sorted_fields = ArrayRef<FieldTypeOrderAndIndex>(stack_buffer, num_fields);
+  } else {
+    heap_buffer.resize(num_fields);
+    sorted_fields = ArrayRef<FieldTypeOrderAndIndex>(heap_buffer);
   }
-  std::sort(grouped_and_sorted_fields.begin(), grouped_and_sorted_fields.end(),
-            LinkFieldsComparator());
-
-  // References should be at the front.
-  size_t current_field = 0;
   size_t num_reference_fields = 0;
-  FieldGaps gaps;
-
-  for (; current_field < num_fields; current_field++) {
-    ArtField* field = grouped_and_sorted_fields.front();
-    Primitive::Type type = field->GetTypeAsPrimitiveType();
-    bool isPrimitive = type != Primitive::kPrimNot;
-    if (isPrimitive) {
-      break;  // past last reference, move on to the next phase
+  size_t primitive_fields_start = num_fields;
+  DCHECK_LE(num_fields, 1u << 16);
+  for (size_t i = 0; i != num_fields; ++i) {
+    ArtField* field = &fields->At(i);
+    const char* descriptor = field->GetTypeDescriptor();
+    FieldTypeOrder field_type_order = FieldTypeOrderFromFirstDescriptorCharacter(descriptor[0]);
+    uint16_t field_index = dchecked_integral_cast<uint16_t>(i);
+    // Insert references to the start, other fields to the end.
+    DCHECK_LT(num_reference_fields, primitive_fields_start);
+    if (field_type_order == FieldTypeOrder::kReference) {
+      sorted_fields[num_reference_fields] = { field_type_order, field_index };
+      ++num_reference_fields;
+    } else {
+      --primitive_fields_start;
+      sorted_fields[primitive_fields_start] = { field_type_order, field_index };
     }
-    if (UNLIKELY(!IsAligned<sizeof(mirror::HeapReference<mirror::Object>)>(
-        field_offset.Uint32Value()))) {
-      MemberOffset old_offset = field_offset;
-      field_offset = MemberOffset(RoundUp(field_offset.Uint32Value(), 4));
-      AddFieldGap(old_offset.Uint32Value(), field_offset.Uint32Value(), &gaps);
-    }
-    DCHECK_ALIGNED(field_offset.Uint32Value(), sizeof(mirror::HeapReference<mirror::Object>));
-    grouped_and_sorted_fields.pop_front();
-    num_reference_fields++;
-    field->SetOffset(field_offset);
-    field_offset = MemberOffset(field_offset.Uint32Value() +
-                                sizeof(mirror::HeapReference<mirror::Object>));
   }
-  // Gaps are stored as a max heap which means that we must shuffle from largest to smallest
-  // otherwise we could end up with suboptimal gap fills.
-  ShuffleForward<8>(&current_field, &field_offset, &grouped_and_sorted_fields, &gaps);
-  ShuffleForward<4>(&current_field, &field_offset, &grouped_and_sorted_fields, &gaps);
-  ShuffleForward<2>(&current_field, &field_offset, &grouped_and_sorted_fields, &gaps);
-  ShuffleForward<1>(&current_field, &field_offset, &grouped_and_sorted_fields, &gaps);
-  CHECK(grouped_and_sorted_fields.empty()) << "Missed " << grouped_and_sorted_fields.size() <<
-      " fields.";
+  DCHECK_EQ(num_reference_fields, primitive_fields_start);
+
+  // Reference fields are already sorted by field index (and dex field index).
+  DCHECK(std::is_sorted(
+      sorted_fields.begin(),
+      sorted_fields.begin() + num_reference_fields,
+      [fields](const auto& lhs, const auto& rhs) REQUIRES_SHARED(Locks::mutator_lock_) {
+        ArtField* lhs_field = &fields->At(lhs.field_index);
+        ArtField* rhs_field = &fields->At(rhs.field_index);
+        CHECK_EQ(lhs_field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
+        CHECK_EQ(rhs_field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
+        CHECK_EQ(lhs_field->GetDexFieldIndex() < rhs_field->GetDexFieldIndex(),
+                 lhs.field_index < rhs.field_index);
+        return lhs_field->GetDexFieldIndex() < rhs_field->GetDexFieldIndex();
+      }));
+  // Primitive fields were stored in reverse order of their field index (and dex field index).
+  DCHECK(std::is_sorted(
+      sorted_fields.begin() + primitive_fields_start,
+      sorted_fields.end(),
+      [fields](const auto& lhs, const auto& rhs) REQUIRES_SHARED(Locks::mutator_lock_) {
+        ArtField* lhs_field = &fields->At(lhs.field_index);
+        ArtField* rhs_field = &fields->At(rhs.field_index);
+        CHECK_NE(lhs_field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
+        CHECK_NE(rhs_field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
+        CHECK_EQ(lhs_field->GetDexFieldIndex() > rhs_field->GetDexFieldIndex(),
+                 lhs.field_index > rhs.field_index);
+        return lhs.field_index > rhs.field_index;
+      }));
+  // Sort the primitive fields by the field type order, then field index.
+  std::sort(sorted_fields.begin() + primitive_fields_start,
+            sorted_fields.end(),
+            [](const auto& lhs, const auto& rhs) {
+              if (lhs.field_type_order != rhs.field_type_order) {
+                return lhs.field_type_order < rhs.field_type_order;
+              } else {
+                return lhs.field_index < rhs.field_index;
+              }
+            });
+  // Primitive fields are now sorted by field size (descending), then type, then field index.
+  DCHECK(std::is_sorted(
+      sorted_fields.begin() + primitive_fields_start,
+      sorted_fields.end(),
+      [fields](const auto& lhs, const auto& rhs) REQUIRES_SHARED(Locks::mutator_lock_) {
+        ArtField* lhs_field = &fields->At(lhs.field_index);
+        ArtField* rhs_field = &fields->At(rhs.field_index);
+        Primitive::Type lhs_type = lhs_field->GetTypeAsPrimitiveType();
+        CHECK_NE(lhs_type, Primitive::kPrimNot);
+        Primitive::Type rhs_type = rhs_field->GetTypeAsPrimitiveType();
+        CHECK_NE(rhs_type, Primitive::kPrimNot);
+        if (lhs_type != rhs_type) {
+          size_t lhs_size = Primitive::ComponentSize(lhs_type);
+          size_t rhs_size = Primitive::ComponentSize(rhs_type);
+          return (lhs_size != rhs_size) ? (lhs_size > rhs_size) : (lhs_type < rhs_type);
+        } else {
+          return lhs_field->GetDexFieldIndex() < rhs_field->GetDexFieldIndex();
+        }
+      }));
+
+  // Process reference fields.
+  FieldGaps field_gaps;
+  size_t index = 0u;
+  if (num_reference_fields != 0u) {
+    constexpr size_t kReferenceSize = sizeof(mirror::HeapReference<mirror::Object>);
+    field_offset = field_gaps.AlignFieldOffset<kReferenceSize>(field_offset);
+    for (; index != num_reference_fields; ++index) {
+      ArtField* field = &fields->At(sorted_fields[index].field_index);
+      field_offset = AssignFieldOffset<kReferenceSize>(field, field_offset);
+    }
+  }
+  // Process 64-bit fields.
+  if (index != num_fields &&
+      sorted_fields[index].field_type_order <= FieldTypeOrder::kLast64BitType) {
+    field_offset = field_gaps.AlignFieldOffset<8u>(field_offset);
+    while (index != num_fields &&
+           sorted_fields[index].field_type_order <= FieldTypeOrder::kLast64BitType) {
+      ArtField* field = &fields->At(sorted_fields[index].field_index);
+      field_offset = AssignFieldOffset<8u>(field, field_offset);
+      ++index;
+    }
+  }
+  // Process 32-bit fields.
+  if (index != num_fields &&
+      sorted_fields[index].field_type_order <= FieldTypeOrder::kLast32BitType) {
+    field_offset = field_gaps.AlignFieldOffset<4u>(field_offset);
+    if (field_gaps.HasGap<4u>()) {
+      ArtField* field = &fields->At(sorted_fields[index].field_index);
+      AssignFieldOffset<4u>(field, field_gaps.ReleaseGap<4u>());  // Ignore return value.
+      ++index;
+      DCHECK(!field_gaps.HasGap<4u>());  // There can be only one gap for a 32-bit field.
+    }
+    while (index != num_fields &&
+           sorted_fields[index].field_type_order <= FieldTypeOrder::kLast32BitType) {
+      ArtField* field = &fields->At(sorted_fields[index].field_index);
+      field_offset = AssignFieldOffset<4u>(field, field_offset);
+      ++index;
+    }
+  }
+  // Process 16-bit fields.
+  if (index != num_fields &&
+      sorted_fields[index].field_type_order <= FieldTypeOrder::kLast16BitType) {
+    field_offset = field_gaps.AlignFieldOffset<2u>(field_offset);
+    while (index != num_fields &&
+           sorted_fields[index].field_type_order <= FieldTypeOrder::kLast16BitType &&
+           field_gaps.HasGap<2u>()) {
+      ArtField* field = &fields->At(sorted_fields[index].field_index);
+      AssignFieldOffset<2u>(field, field_gaps.ReleaseGap<2u>());  // Ignore return value.
+      ++index;
+    }
+    while (index != num_fields &&
+           sorted_fields[index].field_type_order <= FieldTypeOrder::kLast16BitType) {
+      ArtField* field = &fields->At(sorted_fields[index].field_index);
+      field_offset = AssignFieldOffset<2u>(field, field_offset);
+      ++index;
+    }
+  }
+  // Process 8-bit fields.
+  for (; index != num_fields && field_gaps.HasGap<1u>(); ++index) {
+    ArtField* field = &fields->At(sorted_fields[index].field_index);
+    AssignFieldOffset<1u>(field, field_gaps.ReleaseGap<1u>());  // Ignore return value.
+  }
+  for (; index != num_fields; ++index) {
+    ArtField* field = &fields->At(sorted_fields[index].field_index);
+    field_offset = AssignFieldOffset<1u>(field, field_offset);
+  }
+
   self->EndAssertNoThreadSuspension(old_no_suspend_cause);
 
   // We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
-  if (!is_static && klass->DescriptorEquals("Ljava/lang/ref/Reference;")) {
+  DCHECK(!class_linker->init_done_ || !klass->DescriptorEquals("Ljava/lang/ref/Reference;"));
+  if (!is_static &&
+      UNLIKELY(!class_linker->init_done_) &&
+      klass->DescriptorEquals("Ljava/lang/ref/Reference;")) {
     // We know there are no non-reference fields in the Reference classes, and we know
     // that 'referent' is alphabetically last, so this is easy...
     CHECK_EQ(num_reference_fields, num_fields) << klass->PrettyClass();
@@ -8502,7 +8821,7 @@
     // Make sure that the fields array is ordered by name but all reference
     // offsets are at the beginning as far as alignment allows.
     MemberOffset start_ref_offset = is_static
-        ? klass->GetFirstReferenceStaticFieldOffsetDuringLinking(image_pointer_size_)
+        ? klass->GetFirstReferenceStaticFieldOffsetDuringLinking(class_linker->image_pointer_size_)
         : klass->GetFirstReferenceInstanceFieldOffset();
     MemberOffset end_ref_offset(start_ref_offset.Uint32Value() +
                                 num_reference_fields *
@@ -8546,6 +8865,16 @@
   return true;
 }
 
+bool ClassLinker::LinkInstanceFields(Thread* self, Handle<mirror::Class> klass) {
+  CHECK(klass != nullptr);
+  return LinkFieldsHelper::LinkFields(this, self, klass, false, nullptr);
+}
+
+bool ClassLinker::LinkStaticFields(Thread* self, Handle<mirror::Class> klass, size_t* class_size) {
+  CHECK(klass != nullptr);
+  return LinkFieldsHelper::LinkFields(this, self, klass, true, class_size);
+}
+
 //  Set the bitmap of reference instance field offsets.
 void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) {
   uint32_t reference_offsets = 0;
@@ -8618,6 +8947,16 @@
                                                         ObjPtr<mirror::ClassLoader> class_loader) {
   const DexFile& dex_file = *dex_cache->GetDexFile();
   const char* descriptor = dex_file.StringByTypeIdx(type_idx);
+  ObjPtr<mirror::Class> type = LookupResolvedType(descriptor, class_loader);
+  if (type != nullptr) {
+    DCHECK(type->IsResolved());
+    dex_cache->SetResolvedType(type_idx, type);
+  }
+  return type;
+}
+
+ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(const char* descriptor,
+                                                      ObjPtr<mirror::ClassLoader> class_loader) {
   DCHECK_NE(*descriptor, '\0') << "descriptor is empty string";
   ObjPtr<mirror::Class> type = nullptr;
   if (descriptor[1] == '\0') {
@@ -8631,14 +8970,7 @@
     // Find the class in the loaded classes table.
     type = LookupClass(self, descriptor, hash, class_loader);
   }
-  if (type != nullptr) {
-    if (type->IsResolved()) {
-      dex_cache->SetResolvedType(type_idx, type);
-    } else {
-      type = nullptr;
-    }
-  }
-  return type;
+  return (type != nullptr && type->IsResolved()) ? type : nullptr;
 }
 
 template <typename RefType>
@@ -8701,10 +9033,28 @@
   }
   DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr);
   if (resolved != nullptr &&
+      // We pass AccessMethod::kNone instead of kLinking to not warn yet on the
+      // access, as we'll be looking if the method can be accessed through an
+      // interface.
       hiddenapi::ShouldDenyAccessToMember(resolved,
                                           hiddenapi::AccessContext(class_loader, dex_cache),
-                                          hiddenapi::AccessMethod::kLinking)) {
-    resolved = nullptr;
+                                          hiddenapi::AccessMethod::kNone)) {
+    // The resolved method that we have found cannot be accessed due to
+    // hiddenapi (typically it is declared up the hierarchy and is not an SDK
+    // method). Try to find an interface method from the implemented interfaces which is
+    // part of the SDK.
+    ArtMethod* itf_method = klass->FindAccessibleInterfaceMethod(resolved, image_pointer_size_);
+    if (itf_method == nullptr) {
+      // No interface method. Call ShouldDenyAccessToMember again but this time
+      // with AccessMethod::kLinking to ensure that an appropriate warning is
+      // logged.
+      hiddenapi::ShouldDenyAccessToMember(resolved,
+                                          hiddenapi::AccessContext(class_loader, dex_cache),
+                                          hiddenapi::AccessMethod::kLinking);
+      resolved = nullptr;
+    } else {
+      // We found an interface method that is accessible, continue with the resolved method.
+    }
   }
   if (resolved != nullptr) {
     // In case of jmvti, the dex file gets verified before being registered, so first
@@ -8715,7 +9065,7 @@
         << "DexFile referrer: " << dex_file.GetLocation()
         << " ClassLoader: " << DescribeLoaders(class_loader, "");
     // Be a good citizen and update the dex cache to speed subsequent calls.
-    dex_cache->SetResolvedMethod(method_idx, resolved, image_pointer_size_);
+    dex_cache->SetResolvedMethod(method_idx, resolved);
     // Disable the following invariant check as the verifier breaks it. b/73760543
     // const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
     // DCHECK(LookupResolvedType(method_id.class_idx_, dex_cache, class_loader) != nullptr)
@@ -8764,11 +9114,11 @@
                                       Handle<mirror::ClassLoader> class_loader,
                                       ArtMethod* referrer,
                                       InvokeType type) {
+  DCHECK(!Thread::Current()->IsExceptionPending()) << Thread::Current()->GetException()->Dump();
   DCHECK(dex_cache != nullptr);
   DCHECK(referrer == nullptr || !referrer->IsProxyMethod());
   // Check for hit in the dex cache.
-  PointerSize pointer_size = image_pointer_size_;
-  ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, pointer_size);
+  ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx);
   Thread::PoisonObjectPointersIfDebug();
   DCHECK(resolved == nullptr || !resolved->IsRuntimeMethod());
   bool valid_dex_cache_method = resolved != nullptr;
@@ -8858,7 +9208,7 @@
 ArtMethod* ClassLinker::ResolveMethodWithoutInvokeType(uint32_t method_idx,
                                                        Handle<mirror::DexCache> dex_cache,
                                                        Handle<mirror::ClassLoader> class_loader) {
-  ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, image_pointer_size_);
+  ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx);
   Thread::PoisonObjectPointersIfDebug();
   if (resolved != nullptr) {
     DCHECK(!resolved->IsRuntimeMethod());
@@ -8911,7 +9261,8 @@
                                     Handle<mirror::ClassLoader> class_loader,
                                     bool is_static) {
   DCHECK(dex_cache != nullptr);
-  ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
+  DCHECK(!Thread::Current()->IsExceptionPending()) << Thread::Current()->GetException()->Dump();
+  ArtField* resolved = dex_cache->GetResolvedField(field_idx);
   Thread::PoisonObjectPointersIfDebug();
   if (resolved != nullptr) {
     return resolved;
@@ -8937,7 +9288,7 @@
                                        Handle<mirror::DexCache> dex_cache,
                                        Handle<mirror::ClassLoader> class_loader) {
   DCHECK(dex_cache != nullptr);
-  ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
+  ArtField* resolved = dex_cache->GetResolvedField(field_idx);
   Thread::PoisonObjectPointersIfDebug();
   if (resolved != nullptr) {
     return resolved;
@@ -8987,7 +9338,7 @@
   }
 
   if (resolved != nullptr) {
-    dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_);
+    dex_cache->SetResolvedField(field_idx, resolved);
   }
 
   return resolved;
@@ -9014,7 +9365,7 @@
   }
 
   if (resolved != nullptr) {
-    dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_);
+    dex_cache->SetResolvedField(field_idx, resolved);
   }
 
   return resolved;
@@ -9463,16 +9814,22 @@
 }
 
 void ClassLinker::DumpForSigQuit(std::ostream& os) {
-  ScopedObjectAccess soa(Thread::Current());
-  ReaderMutexLock mu(soa.Self(), *Locks::classlinker_classes_lock_);
+  // Avoid a deadlock between a garbage collecting thread running a checkpoint,
+  // a thread holding the dex or classlinker lock and blocking on a condition variable for
+  // weak references access, and a thread blocking on the dex or classlinker lock and thus
+  // unable to run the checkpoint.
+  Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
+  gc::ScopedGCCriticalSection gcs(self, gc::kGcCauseClassLinker, gc::kCollectorTypeClassLinker);
+  ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
   os << "Zygote loaded classes=" << NumZygoteClasses() << " post zygote classes="
      << NumNonZygoteClasses() << "\n";
-  ReaderMutexLock mu2(soa.Self(), *Locks::dex_lock_);
+  ReaderMutexLock mu2(self, *Locks::dex_lock_);
   os << "Dumping registered class loaders\n";
   size_t class_loader_index = 0;
   for (const ClassLoaderData& class_loader : class_loaders_) {
     ObjPtr<mirror::ClassLoader> loader =
-        ObjPtr<mirror::ClassLoader>::DownCast(soa.Self()->DecodeJObject(class_loader.weak_root));
+        ObjPtr<mirror::ClassLoader>::DownCast(self->DecodeJObject(class_loader.weak_root));
     if (loader != nullptr) {
       os << "#" << class_loader_index++ << " " << loader->GetClass()->PrettyDescriptor() << ": [";
       bool saw_one_dex_file = false;
@@ -9491,7 +9848,7 @@
         size_t parent_index = 0;
         for (const ClassLoaderData& class_loader2 : class_loaders_) {
           ObjPtr<mirror::ClassLoader> loader2 = ObjPtr<mirror::ClassLoader>::DownCast(
-              soa.Self()->DecodeJObject(class_loader2.weak_root));
+              self->DecodeJObject(class_loader2.weak_root));
           if (loader2 == loader->GetParent()) {
             os << ", parent #" << parent_index;
             found_parent = true;
@@ -9856,6 +10213,32 @@
   UNREACHABLE();
 }
 
+bool ClassLinker::DenyAccessBasedOnPublicSdk(ArtMethod* art_method ATTRIBUTE_UNUSED) const
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  // Should not be called on ClassLinker, only on AotClassLinker that overrides this.
+  LOG(FATAL) << "UNREACHABLE";
+  UNREACHABLE();
+}
+
+bool ClassLinker::DenyAccessBasedOnPublicSdk(ArtField* art_field ATTRIBUTE_UNUSED) const
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  // Should not be called on ClassLinker, only on AotClassLinker that overrides this.
+  LOG(FATAL) << "UNREACHABLE";
+  UNREACHABLE();
+}
+
+bool ClassLinker::DenyAccessBasedOnPublicSdk(const char* type_descriptor ATTRIBUTE_UNUSED) const {
+  // Should not be called on ClassLinker, only on AotClassLinker that overrides this.
+  LOG(FATAL) << "UNREACHABLE";
+  UNREACHABLE();
+}
+
+void ClassLinker::SetEnablePublicSdkChecks(bool enabled ATTRIBUTE_UNUSED) {
+  // Should not be called on ClassLinker, only on AotClassLinker that overrides this.
+  LOG(FATAL) << "UNREACHABLE";
+  UNREACHABLE();
+}
+
 // Instantiate ClassLinker::ResolveMethod.
 template ArtMethod* ClassLinker::ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
     uint32_t method_idx,
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 4731203..547753a 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -18,15 +18,15 @@
 #define ART_RUNTIME_CLASS_LINKER_H_
 
 #include <list>
+#include <map>
 #include <set>
 #include <string>
 #include <type_traits>
-#include <unordered_map>
-#include <unordered_set>
 #include <utility>
 #include <vector>
 
 #include "base/enums.h"
+#include "base/hash_map.h"
 #include "base/mutex.h"
 #include "base/intrusive_forward_list.h"
 #include "base/locks.h"
@@ -37,10 +37,33 @@
 #include "handle.h"
 #include "jni.h"
 #include "mirror/class.h"
+#include "mirror/object.h"
 #include "verifier/verifier_enums.h"
 
 namespace art {
 
+class ArtField;
+class ArtMethod;
+class ClassHierarchyAnalysis;
+enum class ClassRoot : uint32_t;
+class ClassTable;
+class DexFile;
+template<class T> class Handle;
+class ImtConflictTable;
+template<typename T> class LengthPrefixedArray;
+template<class T> class MutableHandle;
+class InternTable;
+class LinearAlloc;
+class OatFile;
+template<class T> class ObjectLock;
+class Runtime;
+class ScopedObjectAccessAlreadyRunnable;
+class SdkChecker;
+template<size_t kNumReferences> class PACKED(4) StackHandleScope;
+class Thread;
+
+enum VisitRootFlags : uint8_t;
+
 namespace dex {
 struct ClassDef;
 struct MethodHandleItem;
@@ -75,26 +98,9 @@
 using MethodDexCacheType = std::atomic<MethodDexCachePair>;
 }  // namespace mirror
 
-class ArtField;
-class ArtMethod;
-class ClassHierarchyAnalysis;
-enum class ClassRoot : uint32_t;
-class ClassTable;
-class DexFile;
-template<class T> class Handle;
-class ImtConflictTable;
-template<typename T> class LengthPrefixedArray;
-template<class T> class MutableHandle;
-class InternTable;
-class LinearAlloc;
-class OatFile;
-template<class T> class ObjectLock;
-class Runtime;
-class ScopedObjectAccessAlreadyRunnable;
-template<size_t kNumReferences> class PACKED(4) StackHandleScope;
-class Thread;
-
-enum VisitRootFlags : uint8_t;
+namespace verifier {
+class VerifierDeps;
+}
 
 class ClassVisitor {
  public:
@@ -306,6 +312,11 @@
                                            ObjPtr<mirror::ClassLoader> class_loader)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  // Look up a resolved type with the given descriptor associated with the given ClassLoader.
+  ObjPtr<mirror::Class> LookupResolvedType(const char* descriptor,
+                                           ObjPtr<mirror::ClassLoader> class_loader)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   // Determine whether a dex cache result should be trusted, or an IncompatibleClassChangeError
   // check and IllegalAccessError check should be performed even after a hit.
   enum class ResolveMode {  // private.
@@ -551,12 +562,14 @@
 
   verifier::FailureKind VerifyClass(
       Thread* self,
+      verifier::VerifierDeps* verifier_deps,
       Handle<mirror::Class> klass,
       verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_);
-  bool VerifyClassUsingOatFile(const DexFile& dex_file,
-                               ObjPtr<mirror::Class> klass,
+  bool VerifyClassUsingOatFile(Thread* self,
+                               const DexFile& dex_file,
+                               Handle<mirror::Class> klass,
                                ClassStatus& oat_file_class_status)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_);
@@ -597,6 +610,11 @@
   // Is the given entry point the JNI dlsym lookup critical stub?
   bool IsJniDlsymLookupCriticalStub(const void* entry_point) const;
 
+  // Is the given entry point the nterp trampoline?
+  bool IsNterpTrampoline(const void* entry_point) const {
+    return nterp_trampoline_ == entry_point;
+  }
+
   const void* GetQuickToInterpreterBridgeTrampoline() const {
     return quick_to_interpreter_bridge_trampoline_;
   }
@@ -675,11 +693,6 @@
     return image_pointer_size_;
   }
 
-  // Used by image writer for checking.
-  bool ClassInClassTable(ObjPtr<mirror::Class> klass)
-      REQUIRES(Locks::classlinker_classes_lock_)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Clear the ArrayClass cache. This is necessary when cleaning up for the image, as the cache
   // entries are roots, but potentially not image classes.
   void DropFindArrayClassCache() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -716,8 +729,7 @@
   ArtMethod* AddMethodToConflictTable(ObjPtr<mirror::Class> klass,
                                       ArtMethod* conflict_method,
                                       ArtMethod* interface_method,
-                                      ArtMethod* method,
-                                      bool force_new_conflict_method)
+                                      ArtMethod* method)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Create a conflict table with a specified capacity.
@@ -780,6 +792,19 @@
 
   void MakeInitializedClassesVisiblyInitialized(Thread* self, bool wait);
 
+  // Registers the native method and returns the new entry point. NB The returned entry point
+  // might be different from the native_method argument if some MethodCallback modifies it.
+  const void* RegisterNative(Thread* self, ArtMethod* method, const void* native_method)
+      REQUIRES_SHARED(Locks::mutator_lock_) WARN_UNUSED;
+
+  // Unregister native code for a method.
+  void UnregisterNative(Thread* self, ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Get the registered native method entrypoint, if any, otherwise null.
+  const void* GetRegisteredNative(Thread* self, ArtMethod* method)
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!critical_native_code_with_clinit_check_lock_);
+
   struct DexCacheData {
     // Construct an invalid data object.
     DexCacheData()
@@ -811,6 +836,17 @@
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
 
+  // Verifies if the method is accesible according to the SdkChecker (if installed).
+  virtual bool DenyAccessBasedOnPublicSdk(ArtMethod* art_method) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  // Verifies if the field is accesible according to the SdkChecker (if installed).
+  virtual bool DenyAccessBasedOnPublicSdk(ArtField* art_field) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  // Verifies if the descriptor is accesible according to the SdkChecker (if installed).
+  virtual bool DenyAccessBasedOnPublicSdk(const char* type_descriptor) const;
+  // Enable or disable public sdk checks.
+  virtual void SetEnablePublicSdkChecks(bool enabled);
+
  protected:
   virtual bool InitializeClass(Thread* self,
                                Handle<mirror::Class> klass,
@@ -820,6 +856,7 @@
       REQUIRES(!Locks::dex_lock_);
 
   virtual verifier::FailureKind PerformClassVerification(Thread* self,
+                                                         verifier::VerifierDeps* verifier_deps,
                                                          Handle<mirror::Class> klass,
                                                          verifier::HardFailLogMode log_level,
                                                          std::string* error_msg)
@@ -832,7 +869,9 @@
   virtual bool IsUpdatableBootClassPathDescriptor(const char* descriptor);
 
  private:
+  class LinkFieldsHelper;
   class LinkInterfaceMethodsHelper;
+  class MethodTranslation;
   class VisiblyInitializedCallback;
 
   struct ClassLoaderData {
@@ -849,6 +888,7 @@
   // appropriate exceptions if verification failed hard. Returns true for successful verification or
   // soft-failures.
   bool AttemptSupertypeVerification(Thread* self,
+                                    verifier::VerifierDeps* verifier_deps,
                                     Handle<mirror::Class> klass,
                                     Handle<mirror::Class> supertype)
       REQUIRES(!Locks::dex_lock_)
@@ -912,9 +952,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
-  ObjPtr<mirror::DexCache> AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location,
-                                         Thread* self,
-                                         const DexFile& dex_file)
+  ObjPtr<mirror::DexCache> AllocDexCache(Thread* self, const DexFile& dex_file)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
@@ -956,7 +994,8 @@
                   ArtMethod* dst)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void FixupStaticTrampolines(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
+  void FixupStaticTrampolines(Thread* self, ObjPtr<mirror::Class> klass)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Finds a class in a Path- or DexClassLoader, loading it if necessary without using JNI. Hash
   // function is supposed to be ComputeModifiedUtf8Hash(descriptor). Returns true if the
@@ -1113,78 +1152,6 @@
       const dex::MethodHandleItem& method_handle,
       ArtMethod* referrer) REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // A wrapper class representing the result of a method translation used for linking methods and
-  // updating superclass default methods. For each method in a classes vtable there are 4 states it
-  // could be in:
-  // 1) No translation is necessary. In this case there is no MethodTranslation object for it. This
-  //    is the standard case and is true when the method is not overridable by a default method,
-  //    the class defines a concrete implementation of the method, the default method implementation
-  //    remains the same, or an abstract method stayed abstract.
-  // 2) The method must be translated to a different default method. We note this with
-  //    CreateTranslatedMethod.
-  // 3) The method must be replaced with a conflict method. This happens when a superclass
-  //    implements an interface with a default method and this class implements an unrelated
-  //    interface that also defines that default method. We note this with CreateConflictingMethod.
-  // 4) The method must be replaced with an abstract miranda method. This happens when a superclass
-  //    implements an interface with a default method and this class implements a subinterface of
-  //    the superclass's interface which declares the default method abstract. We note this with
-  //    CreateAbstractMethod.
-  //
-  // When a method translation is unnecessary (case #1), we don't put it into the
-  // default_translation maps. So an instance of MethodTranslation must be in one of #2-#4.
-  class MethodTranslation {
-   public:
-    // This slot must become a default conflict method.
-    static MethodTranslation CreateConflictingMethod() {
-      return MethodTranslation(Type::kConflict, /*translation=*/nullptr);
-    }
-
-    // This slot must become an abstract method.
-    static MethodTranslation CreateAbstractMethod() {
-      return MethodTranslation(Type::kAbstract, /*translation=*/nullptr);
-    }
-
-    // Use the given method as the current value for this vtable slot during translation.
-    static MethodTranslation CreateTranslatedMethod(ArtMethod* new_method) {
-      return MethodTranslation(Type::kTranslation, new_method);
-    }
-
-    // Returns true if this is a method that must become a conflict method.
-    bool IsInConflict() const {
-      return type_ == Type::kConflict;
-    }
-
-    // Returns true if this is a method that must become an abstract method.
-    bool IsAbstract() const {
-      return type_ == Type::kAbstract;
-    }
-
-    // Returns true if this is a method that must become a different method.
-    bool IsTranslation() const {
-      return type_ == Type::kTranslation;
-    }
-
-    // Get the translated version of this method.
-    ArtMethod* GetTranslation() const {
-      DCHECK(IsTranslation());
-      DCHECK(translation_ != nullptr);
-      return translation_;
-    }
-
-   private:
-    enum class Type {
-      kTranslation,
-      kConflict,
-      kAbstract,
-    };
-
-    MethodTranslation(Type type, ArtMethod* translation)
-        : translation_(translation), type_(type) {}
-
-    ArtMethod* const translation_;
-    const Type type_;
-  };
-
   // Links the virtual methods for the given class and records any default methods that will need to
   // be updated later.
   //
@@ -1204,7 +1171,7 @@
   bool LinkVirtualMethods(
         Thread* self,
         Handle<mirror::Class> klass,
-        /*out*/std::unordered_map<size_t, MethodTranslation>* default_translations)
+        /*out*/HashMap<size_t, MethodTranslation>* default_translations)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Sets up the interface lookup table (IFTable) in the correct order to allow searching for
@@ -1251,7 +1218,7 @@
   bool LinkInterfaceMethods(
       Thread* self,
       Handle<mirror::Class> klass,
-      const std::unordered_map<size_t, MethodTranslation>& default_translations,
+      const HashMap<size_t, MethodTranslation>& default_translations,
       bool* out_new_conflict,
       ArtMethod** out_imt)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -1260,8 +1227,6 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
   bool LinkInstanceFields(Thread* self, Handle<mirror::Class> klass)
       REQUIRES_SHARED(Locks::mutator_lock_);
-  bool LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_static, size_t* class_size)
-      REQUIRES_SHARED(Locks::mutator_lock_);
   void CreateReferenceInstanceOffsets(Handle<mirror::Class> klass)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -1411,6 +1376,10 @@
   // Well known mirror::Class roots.
   GcRoot<mirror::ObjectArray<mirror::Class>> class_roots_;
 
+  // Method hashes for virtual methods from java.lang.Object used
+  // to avoid recalculating them for each class we link.
+  uint32_t object_virtual_method_hashes_[mirror::Object::kVTableLength];
+
   // A cache of the last FindArrayClass results. The cache serves to avoid creating array class
   // descriptors for the sake of performing FindClass.
   static constexpr size_t kFindArrayCacheSize = 16;
@@ -1432,6 +1401,7 @@
   const void* quick_imt_conflict_trampoline_;
   const void* quick_generic_jni_trampoline_;
   const void* quick_to_interpreter_bridge_trampoline_;
+  const void* nterp_trampoline_;
 
   // Image pointer size.
   PointerSize image_pointer_size_;
@@ -1443,6 +1413,13 @@
   IntrusiveForwardList<VisiblyInitializedCallback> running_visibly_initialized_callbacks_
       GUARDED_BY(visibly_initialized_callback_lock_);
 
+  // Registered native code for @CriticalNative methods of classes that are not visibly
+  // initialized. These code pointers cannot be stored in ArtMethod as that would risk
+  // skipping the class initialization check for direct calls from compiled code.
+  Mutex critical_native_code_with_clinit_check_lock_;
+  std::map<ArtMethod*, void*> critical_native_code_with_clinit_check_
+      GUARDED_BY(critical_native_code_with_clinit_check_lock_);
+
   std::unique_ptr<ClassHierarchyAnalysis> cha_;
 
   class FindVirtualMethodHolderVisitor;
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 931f6df..c561c4d 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -26,7 +26,7 @@
 #include "art_method-inl.h"
 #include "base/enums.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_runtime_test.h"
 #include "dex/dex_file_types.h"
 #include "dex/signature-inl.h"
@@ -485,12 +485,15 @@
 
     // Classes have a different size due to padding field. Strings are variable length.
     if (!klass->IsClassClass() && !klass->IsStringClass() && !is_static) {
-      // Currently only required for AccessibleObject since of the padding fields. The class linker
-      // says AccessibleObject is 9 bytes but sizeof(AccessibleObject) is 12 bytes due to padding.
-      // The RoundUp is to get around this case.
+      // The RoundUp is required for some mirror classes that have a gap at the end,
+      // such as AccessibleObject, ByteArrayViewVarHandle and ByteBufferViewVarHandle.
+      // For example, the AccessibleObject has size 9 according to the class linker.
+      // However, the C++ sizeof(AccessibleObject) is 12 bytes due to alignment, even
+      // though members in C++ subclasses are actually starting at offset 9.
+      //
+      // TODO: We could define a subclass with a `uint8_t` member and check its offset instead.
       static constexpr size_t kPackAlignment = 4;
-      size_t expected_size = RoundUp(is_static ? klass->GetClassSize() : klass->GetObjectSize(),
-          kPackAlignment);
+      size_t expected_size = RoundUp(klass->GetObjectSize(), kPackAlignment);
       if (sizeof(T) != expected_size) {
         LOG(ERROR) << "Class size mismatch:"
            << " class=" << class_descriptor
@@ -1528,13 +1531,10 @@
     }
     ASSERT_TRUE(dex_cache != nullptr);
   }
-  // Make a copy of the dex cache and change the name.
-  dex_cache.Assign(mirror::Object::Clone(dex_cache, soa.Self())->AsDexCache());
   const uint16_t data[] = { 0x20AC, 0x20A1 };
   Handle<mirror::String> location(hs.NewHandle(mirror::String::AllocFromUtf16(soa.Self(),
                                                                               arraysize(data),
                                                                               data)));
-  dex_cache->SetLocation(location.Get());
   const DexFile* old_dex_file = dex_cache->GetDexFile();
 
   std::unique_ptr<DexFile> dex_file(new StandardDexFile(old_dex_file->Begin(),
@@ -1543,6 +1543,10 @@
                                                         0u,
                                                         nullptr,
                                                         nullptr));
+  // Make a copy of the dex cache with changed name.
+  LinearAlloc* alloc = Runtime::Current()->GetLinearAlloc();
+  dex_cache.Assign(class_linker->AllocAndInitializeDexCache(Thread::Current(), *dex_file, alloc));
+  DCHECK_EQ(dex_cache->GetLocation()->CompareTo(location.Get()), 0);
   {
     WriterMutexLock mu(soa.Self(), *Locks::dex_lock_);
     // Check that inserting with a UTF16 name works.
@@ -1768,7 +1772,7 @@
   // in the top parent.
   VerifyClassResolution("LDefinedInAC;", class_loader_d, class_loader_a);
 
-  // Sanity check that we don't find an undefined class.
+  // Check that we don't find an undefined class.
   VerifyClassResolution("LNotDefined;", class_loader_d, nullptr, /*should_find=*/ false);
 }
 
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index 7c723d3..228b950 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -26,9 +26,10 @@
 #include "base/dchecked_vector.h"
 #include "base/file_utils.h"
 #include "base/stl_util.h"
+#include "base/systrace.h"
 #include "class_linker.h"
 #include "class_loader_utils.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/art_dex_file_loader.h"
 #include "dex/dex_file.h"
 #include "dex/dex_file_loader.h"
@@ -61,15 +62,11 @@
 static constexpr char kInMemoryDexClassLoaderDexLocationMagic[] = "<unknown>";
 
 ClassLoaderContext::ClassLoaderContext()
-    : special_shared_library_(false),
-      dex_files_open_attempted_(false),
-      dex_files_open_result_(false),
+    : dex_files_state_(ContextDexFilesState::kDexFilesNotOpened),
       owns_the_dex_files_(true) {}
 
 ClassLoaderContext::ClassLoaderContext(bool owns_the_dex_files)
-    : special_shared_library_(false),
-      dex_files_open_attempted_(true),
-      dex_files_open_result_(true),
+    : dex_files_state_(ContextDexFilesState::kDexFilesOpened),
       owns_the_dex_files_(owns_the_dex_files) {}
 
 // Utility method to add parent and shared libraries of `info` into
@@ -167,10 +164,10 @@
     if (parse_checksums) {
       // Make sure that OpenDexFiles() will never be attempted on this context
       // because the dex locations of IMC do not correspond to real files.
-      CHECK(!dex_files_open_attempted_ || !dex_files_open_result_)
-          << "Parsing spec not supported when context created from a ClassLoader object";
-      dex_files_open_attempted_ = true;
-      dex_files_open_result_ = false;
+      CHECK(dex_files_state_ == kDexFilesNotOpened || dex_files_state_ == kDexFilesOpenFailed)
+          << "Parsing spec not supported when context created from a ClassLoader object: "
+          << "dex_files_state_=" << dex_files_state_;
+      dex_files_state_ = kDexFilesOpenFailed;
     } else {
       // Checksums are not provided and dex locations themselves have no meaning
       // (although we keep them in the spec to simplify parsing). Treat this as
@@ -318,14 +315,6 @@
     return true;
   }
 
-  // Stop early if we detect the special shared library, which may be passed as the classpath
-  // for dex2oat when we want to skip the shared libraries check.
-  if (spec == OatFile::kSpecialSharedLibrary) {
-    LOG(INFO) << "The ClassLoaderContext is a special shared library.";
-    special_shared_library_ = true;
-    return true;
-  }
-
   CHECK(class_loader_chain_ == nullptr);
   class_loader_chain_.reset(ParseInternal(spec, parse_checksums));
   return class_loader_chain_ != nullptr;
@@ -334,7 +323,6 @@
 ClassLoaderContext::ClassLoaderInfo* ClassLoaderContext::ParseInternal(
     const std::string& spec, bool parse_checksums) {
   CHECK(!spec.empty());
-  CHECK_NE(spec, OatFile::kSpecialSharedLibrary);
   std::string remaining = spec;
   std::unique_ptr<ClassLoaderInfo> first(nullptr);
   ClassLoaderInfo* previous_iteration = nullptr;
@@ -400,22 +388,23 @@
 
 // Opens requested class path files and appends them to opened_dex_files. If the dex files have
 // been stripped, this opens them from their oat files (which get added to opened_oat_files).
-bool ClassLoaderContext::OpenDexFiles(InstructionSet isa,
-                                      const std::string& classpath_dir,
-                                      const std::vector<int>& fds) {
-  if (dex_files_open_attempted_) {
-    // Do not attempt to re-open the files if we already tried.
-    return dex_files_open_result_;
+bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir,
+                                      const std::vector<int>& fds,
+                                      bool only_read_checksums) {
+  switch (dex_files_state_) {
+    case kDexFilesNotOpened: break;  // files not opened, continue.
+    case kDexFilesOpenFailed: return false;  // previous attempt failed.
+    case kDexFilesOpened: return true;  // previous attempt succeed.
+    case kDexFilesChecksumsRead:
+      if (only_read_checksums) {
+        return true;  // we already read the checksums.
+      } else {
+        break;  // we already read the checksums but have to open the dex files; continue.
+      }
   }
 
-  dex_files_open_attempted_ = true;
-  // Assume we can open all dex files. If not, we will set this to false as we go.
-  dex_files_open_result_ = true;
-
-  if (special_shared_library_) {
-    // Nothing to open if the context is a special shared library.
-    return true;
-  }
+  // Assume we can open the files. If not, we will adjust as we go.
+  dex_files_state_ = only_read_checksums ? kDexFilesChecksumsRead : kDexFilesOpened;
 
   // Note that we try to open all dex files even if some fail.
   // We may get resource-only apks which we cannot load.
@@ -423,7 +412,9 @@
   // no dex files. So that we can distinguish the real failures...
   const ArtDexFileLoader dex_file_loader;
   std::vector<ClassLoaderInfo*> work_list;
-  CHECK(class_loader_chain_ != nullptr);
+  if (class_loader_chain_ == nullptr) {
+    return true;
+  }
   work_list.push_back(class_loader_chain_.get());
   size_t dex_file_index = 0;
   while (!work_list.empty()) {
@@ -431,7 +422,11 @@
     work_list.pop_back();
     DCHECK(info->type != kInMemoryDexClassLoader) << __FUNCTION__ << " not supported for IMC";
 
-    size_t opened_dex_files_index = info->opened_dex_files.size();
+    // Holds the dex locations for the classpath files we've opened.
+    std::vector<std::string> dex_locations;
+    // Holds the checksums for the classpath files we've opened.
+    std::vector<uint32_t> dex_checksums;
+
     for (const std::string& cp_elem : info->classpath) {
       // If path is relative, append it to the provided base directory.
       std::string location = cp_elem;
@@ -440,13 +435,13 @@
       }
 
       // If file descriptors were provided for the class loader context dex paths,
-      // get the descriptor which correponds to this dex path. We assume the `fds`
+      // get the descriptor which corresponds to this dex path. We assume the `fds`
       // vector follows the same order as a flattened class loader context.
       int fd = -1;
       if (!fds.empty()) {
         if (dex_file_index >= fds.size()) {
           LOG(WARNING) << "Number of FDs is smaller than number of dex files in the context";
-          dex_files_open_result_ = false;
+          dex_files_state_ = kDexFilesOpenFailed;
           return false;
         }
 
@@ -455,45 +450,39 @@
       }
 
       std::string error_msg;
-      // When opening the dex files from the context we expect their checksum to match their
-      // contents. So pass true to verify_checksum.
-      // We don't need to do structural dex file verification, we only need to
-      // check the checksum, so pass false to verify.
-      if (fd < 0) {
+      if (only_read_checksums) {
+        bool zip_file_only_contains_uncompress_dex;
+        if (!dex_file_loader.GetMultiDexChecksums(location.c_str(),
+                                                  &dex_checksums,
+                                                  &dex_locations,
+                                                  &error_msg,
+                                                  fd,
+                                                  &zip_file_only_contains_uncompress_dex)) {
+          LOG(WARNING) << "Could not get dex checksums for location " << location << ", fd=" << fd;
+          dex_files_state_ = kDexFilesOpenFailed;
+        }
+      } else {
+        // When opening the dex files from the context we expect their checksum to match their
+        // contents. So pass true to verify_checksum.
+        // We don't need to do structural dex file verification, we only need to
+        // check the checksum, so pass false to verify.
+        size_t opened_dex_files_index = info->opened_dex_files.size();
         if (!dex_file_loader.Open(location.c_str(),
+                                  fd,
                                   location.c_str(),
                                   /*verify=*/ false,
                                   /*verify_checksum=*/ true,
                                   &error_msg,
                                   &info->opened_dex_files)) {
-          // If we fail to open the dex file because it's been stripped, try to
-          // open the dex file from its corresponding oat file.
-          // This could happen when we need to recompile a pre-build whose dex
-          // code has been stripped (for example, if the pre-build is only
-          // quicken and we want to re-compile it speed-profile).
-          // TODO(calin): Use the vdex directly instead of going through the oat file.
-          OatFileAssistant oat_file_assistant(location.c_str(), isa, false);
-          std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile());
-          std::vector<std::unique_ptr<const DexFile>> oat_dex_files;
-          if (oat_file != nullptr &&
-              OatFileAssistant::LoadDexFiles(*oat_file, location, &oat_dex_files)) {
-            info->opened_oat_files.push_back(std::move(oat_file));
-            info->opened_dex_files.insert(info->opened_dex_files.end(),
-                                          std::make_move_iterator(oat_dex_files.begin()),
-                                          std::make_move_iterator(oat_dex_files.end()));
-          } else {
-            LOG(WARNING) << "Could not open dex files from location: " << location;
-            dex_files_open_result_ = false;
+          LOG(WARNING) << "Could not open dex files for location " << location << ", fd=" << fd;
+          dex_files_state_ = kDexFilesOpenFailed;
+        } else {
+          for (size_t k = opened_dex_files_index; k < info->opened_dex_files.size(); k++) {
+            std::unique_ptr<const DexFile>& dex = info->opened_dex_files[k];
+            dex_locations.push_back(dex->GetLocation());
+            dex_checksums.push_back(dex->GetLocationChecksum());
           }
         }
-      } else if (!dex_file_loader.Open(fd,
-                                       location.c_str(),
-                                       /*verify=*/ false,
-                                       /*verify_checksum=*/ true,
-                                       &error_msg,
-                                       &info->opened_dex_files)) {
-        LOG(WARNING) << "Could not open dex files from fd " << fd << " for location: " << location;
-        dex_files_open_result_ = false;
       }
     }
 
@@ -507,13 +496,9 @@
     // location in the class paths.
     // Note that this will also remove the paths that could not be opened.
     info->original_classpath = std::move(info->classpath);
-    info->classpath.clear();
-    info->checksums.clear();
-    for (size_t k = opened_dex_files_index; k < info->opened_dex_files.size(); k++) {
-      std::unique_ptr<const DexFile>& dex = info->opened_dex_files[k];
-      info->classpath.push_back(dex->GetLocation());
-      info->checksums.push_back(dex->GetLocationChecksum());
-    }
+    DCHECK(dex_locations.size() == dex_checksums.size());
+    info->classpath = dex_locations;
+    info->checksums = dex_checksums;
     AddToWorkList(info, work_list);
   }
 
@@ -522,15 +507,15 @@
   if (dex_file_index != fds.size()) {
     LOG(WARNING) << fds.size() << " FDs provided but only " << dex_file_index
         << " dex files are in the class loader context";
-    dex_files_open_result_ = false;
+    dex_files_state_ = kDexFilesOpenFailed;
   }
 
-  return dex_files_open_result_;
+  return dex_files_state_ != kDexFilesOpenFailed;
 }
 
 bool ClassLoaderContext::RemoveLocationsFromClassPaths(
     const dchecked_vector<std::string>& locations) {
-  CHECK(!dex_files_open_attempted_)
+  CHECK_EQ(dex_files_state_, kDexFilesNotOpened)
       << "RemoveLocationsFromClasspaths cannot be call after OpenDexFiles";
 
   if (class_loader_chain_ == nullptr) {
@@ -617,9 +602,6 @@
                                               bool for_dex2oat,
                                               ClassLoaderContext* stored_context) const {
   CheckDexFilesOpened("EncodeContextForOatFile");
-  if (special_shared_library_) {
-    return OatFile::kSpecialSharedLibrary;
-  }
 
   if (stored_context != nullptr) {
     DCHECK_EQ(GetParentChainSize(), stored_context->GetParentChainSize());
@@ -860,12 +842,7 @@
   Thread* self = Thread::Current();
   ScopedObjectAccess soa(self);
 
-  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
-
-  if (class_loader_chain_ == nullptr) {
-    CHECK(special_shared_library_);
-    return class_linker->CreatePathClassLoader(self, compilation_sources);
-  }
+  CHECK(class_loader_chain_ != nullptr);
 
   // Create a map of canonicalized shared libraries. As we're holding objects,
   // we're creating a variable size handle scope to put handles in the map.
@@ -939,9 +916,9 @@
 }
 
 void ClassLoaderContext::CheckDexFilesOpened(const std::string& calling_method) const {
-  CHECK(dex_files_open_attempted_)
+  CHECK_NE(dex_files_state_, kDexFilesNotOpened)
       << "Dex files were not successfully opened before the call to " << calling_method
-      << "attempt=" << dex_files_open_attempted_ << ", result=" << dex_files_open_result_;
+      << "status=" << dex_files_state_;
 }
 
 // Collects the dex files from the give Java dex_file object. Only the dex files with
@@ -1178,8 +1155,11 @@
 std::unique_ptr<ClassLoaderContext> ClassLoaderContext::CreateContextForClassLoader(
     jobject class_loader,
     jobjectArray dex_elements) {
-  CHECK(class_loader != nullptr);
+  ScopedTrace trace(__FUNCTION__);
 
+  if (class_loader == nullptr) {
+    return nullptr;
+  }
   ScopedObjectAccess soa(Thread::Current());
   StackHandleScope<2> hs(soa.Self());
   Handle<mirror::ClassLoader> h_class_loader =
@@ -1230,9 +1210,10 @@
     const std::string& context_spec,
     bool verify_names,
     bool verify_checksums) const {
+  ScopedTrace trace(__FUNCTION__);
   if (verify_names || verify_checksums) {
-    DCHECK(dex_files_open_attempted_);
-    DCHECK(dex_files_open_result_);
+    DCHECK(dex_files_state_ == kDexFilesChecksumsRead || dex_files_state_ == kDexFilesOpened)
+        << "dex_files_state_=" << dex_files_state_;
   }
 
   ClassLoaderContext expected_context;
@@ -1241,22 +1222,6 @@
     return VerificationResult::kMismatch;
   }
 
-  // Special shared library contexts always match. They essentially instruct the runtime
-  // to ignore the class path check because the oat file is known to be loaded in different
-  // contexts. OatFileManager will further verify if the oat file can be loaded based on the
-  // collision check.
-  if (expected_context.special_shared_library_) {
-    // Special case where we are the only entry in the class path.
-    if (class_loader_chain_ != nullptr &&
-        class_loader_chain_->parent == nullptr &&
-        class_loader_chain_->classpath.size() == 0) {
-      return VerificationResult::kVerifies;
-    }
-    return VerificationResult::kForcedToSkipChecks;
-  } else if (special_shared_library_) {
-    return VerificationResult::kForcedToSkipChecks;
-  }
-
   ClassLoaderInfo* info = class_loader_chain_.get();
   ClassLoaderInfo* expected = expected_context.class_loader_chain_.get();
   CHECK(info != nullptr);
@@ -1404,16 +1369,14 @@
 
 std::set<const DexFile*> ClassLoaderContext::CheckForDuplicateDexFiles(
     const std::vector<const DexFile*>& dex_files_to_check) {
-  DCHECK(dex_files_open_attempted_);
-  DCHECK(dex_files_open_result_);
+  DCHECK_EQ(dex_files_state_, kDexFilesOpened);
 
   std::set<const DexFile*> result;
 
-  // If we are the special shared library or the chain is null there's nothing
-  // we can check, return an empty list;
+  // If the chain is null there's nothing we can check, return an empty list.
   // The class loader chain can be null if there were issues when creating the
   // class loader context (e.g. tests).
-  if (special_shared_library_ || class_loader_chain_ == nullptr) {
+  if (class_loader_chain_ == nullptr) {
     return result;
   }
 
diff --git a/runtime/class_loader_context.h b/runtime/class_loader_context.h
index d564ec8..33af16a 100644
--- a/runtime/class_loader_context.h
+++ b/runtime/class_loader_context.h
@@ -39,7 +39,6 @@
  public:
   enum class VerificationResult {
     kVerifies,
-    kForcedToSkipChecks,
     kMismatch,
   };
 
@@ -74,6 +73,11 @@
   // (Note that one dex file can contain multidexes. Each multidex will be added to the classpath
   // separately.)
   //
+  // only_read_checksums controls whether or not we only read the dex locations and the checksums
+  // from the apk instead of fully opening the dex files.
+  //
+  // This method is not thread safe.
+  //
   // Note that a "false" return could mean that either an apk/jar contained no dex files or
   // that we hit a I/O or checksum mismatch error.
   // TODO(calin): Currently there's no easy way to tell the difference.
@@ -81,9 +85,9 @@
   // TODO(calin): we're forced to complicate the flow in this class with a different
   // OpenDexFiles step because the current dex2oat flow requires the dex files be opened before
   // the class loader is created. Consider reworking the dex2oat part.
-  bool OpenDexFiles(InstructionSet isa,
-                    const std::string& classpath_dir,
-                    const std::vector<int>& context_fds = std::vector<int>());
+  bool OpenDexFiles(const std::string& classpath_dir = "",
+                    const std::vector<int>& context_fds = std::vector<int>(),
+                    bool only_read_checksums = false);
 
   // Remove the specified compilation sources from all classpaths present in this context.
   // Should only be called before the first call to OpenDexFiles().
@@ -160,7 +164,10 @@
   //    - the number and type of the class loaders from the chain matches
   //    - the class loader from the same position have the same classpath
   //      (the order and checksum of the dex files matches)
-  // This should be called after OpenDexFiles().
+  // This should be called after OpenDexFiles() with only_read_checksums=true. There's no
+  // need to fully open the dex files if the only thing that needs to be done is to verify
+  // the context.
+  //
   // Names are only verified if verify_names is true.
   // Checksums are only verified if verify_checksums is true.
   VerificationResult VerifyClassLoaderContextMatch(const std::string& context_spec,
@@ -341,20 +348,24 @@
   // The returned format can be used when parsing a context spec.
   static const char* GetClassLoaderTypeName(ClassLoaderType type);
 
+  // Encodes the state of processing the dex files associated with the context.
+  enum ContextDexFilesState {
+    // The dex files are not opened.
+    kDexFilesNotOpened = 1,
+    // The dex checksums/locations were read from the apk/dex but the dex files were not opened.
+    kDexFilesChecksumsRead = 2,
+    // The dex files are opened (either because we called OpenDexFiles, or we used a class loader
+    // to create the context). This implies kDexFilesChecksumsRead.
+    kDexFilesOpened = 3,
+    // We failed to open the dex files or read the checksums.
+    kDexFilesOpenFailed = 4
+  };
+
   // The class loader chain.
   std::unique_ptr<ClassLoaderInfo> class_loader_chain_;
 
-  // Whether or not the class loader context should be ignored at runtime when loading the oat
-  // files. When true, dex2oat will use OatFile::kSpecialSharedLibrary as the classpath key in
-  // the oat file.
-  // TODO(calin): Can we get rid of this and cover all relevant use cases?
-  // (e.g. packages using prebuild system packages as shared libraries b/36480683)
-  bool special_shared_library_;
-
-  // Whether or not OpenDexFiles() was called.
-  bool dex_files_open_attempted_;
-  // The result of the last OpenDexFiles() operation.
-  bool dex_files_open_result_;
+  // The opening state of the dex files.
+  ContextDexFilesState dex_files_state_;
 
   // Whether or not the context owns the opened dex and oat files.
   // If true, the opened dex files will be de-allocated when the context is destructed.
diff --git a/runtime/class_loader_context_test.cc b/runtime/class_loader_context_test.cc
index 035c513..bf51ae3 100644
--- a/runtime/class_loader_context_test.cc
+++ b/runtime/class_loader_context_test.cc
@@ -23,7 +23,7 @@
 #include "base/dchecked_vector.h"
 #include "base/stl_util.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_runtime_test.h"
 #include "dex/dex_file.h"
 #include "handle_scope-inl.h"
@@ -142,22 +142,38 @@
       ClassLoaderContext* context,
       size_t index,
       std::vector<std::unique_ptr<const DexFile>>* all_dex_files,
-      bool classpath_matches_dex_location = true) {
+      bool classpath_matches_dex_location = true,
+      bool only_read_checksums = false) {
     ASSERT_TRUE(context != nullptr);
-    ASSERT_TRUE(context->dex_files_open_attempted_);
-    ASSERT_TRUE(context->dex_files_open_result_);
+    if (only_read_checksums) {
+      ASSERT_EQ(context->dex_files_state_,
+                ClassLoaderContext::ContextDexFilesState::kDexFilesChecksumsRead);
+    } else {
+      ASSERT_EQ(context->dex_files_state_,
+                ClassLoaderContext::ContextDexFilesState::kDexFilesOpened);
+    }
     ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(index);
     ASSERT_EQ(all_dex_files->size(), info.classpath.size());
-    ASSERT_EQ(all_dex_files->size(), info.opened_dex_files.size());
-    size_t cur_open_dex_index = 0;
-    for (size_t k = 0; k < all_dex_files->size(); k++) {
-      std::unique_ptr<const DexFile>& opened_dex_file =
-            info.opened_dex_files[cur_open_dex_index++];
-      std::unique_ptr<const DexFile>& expected_dex_file = (*all_dex_files)[k];
+    ASSERT_EQ(all_dex_files->size(), info.checksums.size());
+    if (only_read_checksums) {
+      ASSERT_EQ(0u, info.opened_dex_files.size());
+    } else {
+      ASSERT_EQ(all_dex_files->size(), info.opened_dex_files.size());
+    }
 
+    for (size_t k = 0, cur_open_dex_index = 0;
+         k < all_dex_files->size();
+         k++, cur_open_dex_index++) {
+      const std::string& opened_location = only_read_checksums
+          ? info.classpath[cur_open_dex_index]
+          : info.opened_dex_files[cur_open_dex_index]->GetLocation();
+      uint32_t opened_checksum = only_read_checksums
+          ? info.checksums[cur_open_dex_index]
+          : info.opened_dex_files[cur_open_dex_index]->GetLocationChecksum();
+
+      std::unique_ptr<const DexFile>& expected_dex_file = (*all_dex_files)[k];
       std::string expected_location = expected_dex_file->GetLocation();
 
-      const std::string& opened_location = opened_dex_file->GetLocation();
       if (!IsAbsoluteLocation(opened_location)) {
         // If the opened location is relative (it was open from a relative path without a
         // classpath_dir) it might not match the expected location which is absolute in tests).
@@ -169,7 +185,7 @@
       } else {
         ASSERT_EQ(expected_location, opened_location);
       }
-      ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
+      ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_checksum);
       if (classpath_matches_dex_location) {
         ASSERT_EQ(info.classpath[k], opened_location);
       }
@@ -190,10 +206,8 @@
 
   void VerifyContextForClassLoader(ClassLoaderContext* context) {
     ASSERT_TRUE(context != nullptr);
-    ASSERT_TRUE(context->dex_files_open_attempted_);
-    ASSERT_TRUE(context->dex_files_open_result_);
+    ASSERT_EQ(context->dex_files_state_, ClassLoaderContext::ContextDexFilesState::kDexFilesOpened);
     ASSERT_FALSE(context->owns_the_dex_files_);
-    ASSERT_FALSE(context->special_shared_library_);
   }
 
   void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
@@ -215,8 +229,106 @@
   }
 
   void PretendContextOpenedDexFiles(ClassLoaderContext* context) {
-    context->dex_files_open_attempted_ = true;
-    context->dex_files_open_result_ = true;
+    context->dex_files_state_ = ClassLoaderContext::ContextDexFilesState::kDexFilesOpened;
+  }
+
+  void PretendContextOpenedDexFilesForChecksums(ClassLoaderContext* context) {
+    context->dex_files_state_ = ClassLoaderContext::ContextDexFilesState::kDexFilesChecksumsRead;
+  }
+
+  void TestOpenDexFiles(bool only_read_checksums) {
+    std::string multidex_name = GetTestDexFileName("MultiDex");
+    std::string myclass_dex_name = GetTestDexFileName("MyClass");
+    std::string dex_name = GetTestDexFileName("Main");
+
+    std::unique_ptr<ClassLoaderContext> context =
+        ClassLoaderContext::Create(
+            "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
+            "DLC[" + dex_name + "]");
+
+    ASSERT_TRUE(context->OpenDexFiles(
+        /*classpath_dir=*/ "",
+        /*context_fds=*/ std::vector<int>(),
+        only_read_checksums));
+
+    VerifyContextSize(context.get(), 2);
+
+    std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
+    std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
+    for (size_t i = 0; i < myclass_dex_files.size(); i++) {
+      all_dex_files0.emplace_back(myclass_dex_files[i].release());
+    }
+    VerifyOpenDexFiles(context.get(),
+                       /*index=*/ 0,
+                       &all_dex_files0,
+                       /*classpath_matches_dex_location=*/ false,
+                       only_read_checksums);
+    std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
+    VerifyOpenDexFiles(context.get(),
+                       /*index=*/ 1,
+                       &all_dex_files1,
+                       /*classpath_matches_dex_location=*/ false,
+                       only_read_checksums);
+  }
+
+  void TestOpenValidDexFilesRelative(bool use_classpath_dir, bool only_read_checksums) {
+    char cwd_buf[4096];
+    if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
+      PLOG(FATAL) << "Could not get working directory";
+    }
+    std::string multidex_name;
+    std::string myclass_dex_name;
+    std::string dex_name;
+    if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) ||
+        !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) ||
+        !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) {
+      LOG(ERROR) << "Test OpenValidDexFilesRelative cannot be run because target dex files have no "
+                << "relative path.";
+      SUCCEED();
+      return;
+    }
+
+    std::unique_ptr<ClassLoaderContext> context =
+        ClassLoaderContext::Create(
+            "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
+            "DLC[" + dex_name + "]");
+
+    ASSERT_TRUE(context->OpenDexFiles(
+        /*classpath_dir=*/ use_classpath_dir ? cwd_buf : "",
+        /*context_fds=*/ std::vector<int>(),
+        only_read_checksums));
+    VerifyContextSize(context.get(), 2);
+
+    std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
+    std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
+    for (size_t i = 0; i < myclass_dex_files.size(); i++) {
+      all_dex_files0.emplace_back(myclass_dex_files[i].release());
+    }
+    VerifyOpenDexFiles(context.get(),
+                       /*index=*/ 0,
+                       &all_dex_files0,
+                       /*classpath_matches_dex_location=*/ false,
+                       only_read_checksums);
+
+    std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
+    VerifyOpenDexFiles(context.get(),
+                       /*index=*/ 1,
+                       &all_dex_files1,
+                       /*classpath_matches_dex_location=*/ false,
+                       only_read_checksums);
+  }
+
+  // Creates a relative path from cwd to 'in'. Returns false if it cannot be done.
+  // TODO We should somehow support this in all situations. b/72042237.
+  bool CreateRelativeString(const std::string& in, const char* cwd, std::string* out) {
+    int cwd_len = strlen(cwd);
+    if (!android::base::StartsWith(in, cwd) || (cwd_len < 1)) {
+      return false;
+    }
+    bool contains_trailing_slash = (cwd[cwd_len - 1] == '/');
+    int start_position = cwd_len + (contains_trailing_slash ? 0 : 1);
+    *out = in.substr(start_position);
+    return true;
   }
 
  private:
@@ -277,10 +389,10 @@
   VerifyClassLoaderPCL(context.get(), 0, "");
 }
 
-TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
+TEST_F(ClassLoaderContextTest, ParseInvalidSharedLibraryContext) {
+  // '&' used to be a special context.
   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
-  // An shared library context should have no class loader in the chain.
-  VerifyContextSize(context.get(), 0);
+  ASSERT_TRUE(context == nullptr);
 }
 
 TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
@@ -373,12 +485,6 @@
   VerifySharedLibrariesSize(context.get(), 0, 0);
 }
 
-TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
-  std::unique_ptr<ClassLoaderContext> context =
-    ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
-  VerifyContextSize(context.get(), 0);
-}
-
 TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
   ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
   ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
@@ -401,123 +507,58 @@
   std::unique_ptr<ClassLoaderContext> context =
       ClassLoaderContext::Create("PCL[does_not_exist.dex]");
   VerifyContextSize(context.get(), 1);
-  ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
+  ASSERT_FALSE(context->OpenDexFiles("."));
+}
+
+TEST_F(ClassLoaderContextTest, ReadChecksumsInvalidDexFiles) {
+  std::unique_ptr<ClassLoaderContext> context =
+      ClassLoaderContext::Create("PCL[does_not_exist.dex]");
+  VerifyContextSize(context.get(), 1);
+  ASSERT_FALSE(context->OpenDexFiles(
+        /*classpath_dir=*/ ".",
+        /*context_fds=*/ std::vector<int>(),
+        /*only_read_checksums=*/ true));
 }
 
 TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
-  std::string multidex_name = GetTestDexFileName("MultiDex");
-  std::string myclass_dex_name = GetTestDexFileName("MyClass");
-  std::string dex_name = GetTestDexFileName("Main");
-
-
-  std::unique_ptr<ClassLoaderContext> context =
-      ClassLoaderContext::Create(
-          "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
-          "DLC[" + dex_name + "]");
-
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir=*/ ""));
-
-  VerifyContextSize(context.get(), 2);
-
-  std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
-  std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
-  for (size_t i = 0; i < myclass_dex_files.size(); i++) {
-    all_dex_files0.emplace_back(myclass_dex_files[i].release());
-  }
-  VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
-
-  std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
-  VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
+  TestOpenDexFiles(/*only_read_checksums=*/ false);
 }
 
-// Creates a relative path from cwd to 'in'. Returns false if it cannot be done.
-// TODO We should somehow support this in all situations. b/72042237.
-static bool CreateRelativeString(const std::string& in, const char* cwd, std::string* out) {
-  int cwd_len = strlen(cwd);
-  if (!android::base::StartsWith(in, cwd) || (cwd_len < 1)) {
-    return false;
-  }
-  bool contains_trailing_slash = (cwd[cwd_len - 1] == '/');
-  int start_position = cwd_len + (contains_trailing_slash ? 0 : 1);
-  *out = in.substr(start_position);
-  return true;
+TEST_F(ClassLoaderContextTest, ReadDexFileChecksums) {
+  TestOpenDexFiles(/*only_read_checksums=*/ true);
 }
 
 TEST_F(ClassLoaderContextTest, OpenValidDexFilesRelative) {
-  char cwd_buf[4096];
-  if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
-    PLOG(FATAL) << "Could not get working directory";
-  }
-  std::string multidex_name;
-  std::string myclass_dex_name;
-  std::string dex_name;
-  if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) ||
-      !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) ||
-      !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) {
-    LOG(ERROR) << "Test OpenValidDexFilesRelative cannot be run because target dex files have no "
-               << "relative path.";
-    SUCCEED();
-    return;
-  }
+  TestOpenValidDexFilesRelative(/*use_classpath_dir=*/ false, /*only_read_checksums=*/ false);
+}
 
-  std::unique_ptr<ClassLoaderContext> context =
-      ClassLoaderContext::Create(
-          "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
-          "DLC[" + dex_name + "]");
-
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir=*/ ""));
-
-  std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
-  std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
-  for (size_t i = 0; i < myclass_dex_files.size(); i++) {
-    all_dex_files0.emplace_back(myclass_dex_files[i].release());
-  }
-  VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
-
-  std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
-  VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
+TEST_F(ClassLoaderContextTest, ReadChecksumsValidDexFilesRelative) {
+  TestOpenValidDexFilesRelative(/*use_classpath_dir=*/ false, /*only_read_checksums=*/ true);
 }
 
 TEST_F(ClassLoaderContextTest, OpenValidDexFilesClasspathDir) {
-  char cwd_buf[4096];
-  if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
-    PLOG(FATAL) << "Could not get working directory";
-  }
-  std::string multidex_name;
-  std::string myclass_dex_name;
-  std::string dex_name;
-  if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) ||
-      !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) ||
-      !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) {
-    LOG(ERROR) << "Test OpenValidDexFilesClasspathDir cannot be run because target dex files have "
-               << "no relative path.";
-    SUCCEED();
-    return;
-  }
-  std::unique_ptr<ClassLoaderContext> context =
-      ClassLoaderContext::Create(
-          "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
-          "DLC[" + dex_name + "]");
+  TestOpenValidDexFilesRelative(/*use_classpath_dir=*/ true, /*only_read_checksums=*/ false);
+}
 
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, cwd_buf));
-
-  VerifyContextSize(context.get(), 2);
-  std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
-  std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
-  for (size_t i = 0; i < myclass_dex_files.size(); i++) {
-    all_dex_files0.emplace_back(myclass_dex_files[i].release());
-  }
-  VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
-
-  std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
-  VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
+TEST_F(ClassLoaderContextTest, ReadChecksumsValidDexFilesClasspathDir) {
+  TestOpenValidDexFilesRelative(/*use_classpath_dir=*/ true, /*only_read_checksums=*/ true);
 }
 
 TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
   std::string dex_name = GetTestDexFileName("Main");
   std::unique_ptr<ClassLoaderContext> context =
       ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
-  ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_FALSE(context->OpenDexFiles());
+}
+
+TEST_F(ClassLoaderContextTest, ReadChecksumsInvalidDexFilesMix) {
+  std::string dex_name = GetTestDexFileName("Main");
+  std::unique_ptr<ClassLoaderContext> context =
+      ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
+  ASSERT_FALSE(context->OpenDexFiles(
+      /*classpath_dir=*/ "",
+      /*context_fds=*/ std::vector<int>(),
+      /*only_read_checksums=*/ true));
 }
 
 TEST_F(ClassLoaderContextTest, OpenDexFilesForIMCFails) {
@@ -526,14 +567,47 @@
 
   context = ParseContextWithChecksums("IMC[<unknown>*111]");
   VerifyContextSize(context.get(), 1);
-  ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
+  ASSERT_FALSE(context->OpenDexFiles("."));
+}
+
+// Verify that we can fully open the dex files after only reading their checksums.
+TEST_F(ClassLoaderContextTest, SubsequentOpenDexFilesOperations) {
+  std::string dex_name = GetTestDexFileName("Main");
+  std::unique_ptr<ClassLoaderContext> context =
+      ClassLoaderContext::Create("PCL[" + dex_name + "]");
+
+  std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("Main");
+
+  ASSERT_TRUE(context->OpenDexFiles(
+      /*classpath_dir=*/ "",
+      /*context_fds=*/ std::vector<int>(),
+      /*only_read_checksums=*/ true));
+
+  VerifyOpenDexFiles(
+      context.get(),
+      /*index=*/ 0,
+      &all_dex_files0,
+      /*classpath_matches_dex_location=*/ false,
+      /*only_read_checksums=*/ true);
+
+  ASSERT_TRUE(context->OpenDexFiles(
+      /*classpath_dir=*/ "",
+      /*context_fds=*/ std::vector<int>(),
+      /*only_read_checksums=*/ false));
+
+  VerifyOpenDexFiles(
+      context.get(),
+      /*index=*/ 0,
+      &all_dex_files0,
+      /*classpath_matches_dex_location=*/ false,
+      /*only_read_checksums=*/ false);
 }
 
 TEST_F(ClassLoaderContextTest, CreateClassLoader) {
   std::string dex_name = GetTestDexFileName("Main");
   std::unique_ptr<ClassLoaderContext> context =
       ClassLoaderContext::Create("PCL[" + dex_name + "]");
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
@@ -570,7 +644,7 @@
 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
   std::unique_ptr<ClassLoaderContext> context =
       ClassLoaderContext::Create("");
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
 
@@ -594,34 +668,6 @@
       soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
 }
 
-TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
-  std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
-
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
-
-  std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
-
-  std::vector<const DexFile*> compilation_sources_raw =
-      MakeNonOwningPointerVector(compilation_sources);
-  jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
-  ASSERT_TRUE(jclass_loader != nullptr);
-
-  ScopedObjectAccess soa(Thread::Current());
-
-  StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
-      soa.Decode<mirror::ClassLoader>(jclass_loader));
-
-  // A shared library context should create a single PathClassLoader with only the compilation
-  // sources.
-  VerifyClassLoaderDexFiles(soa,
-      class_loader,
-      WellKnownClasses::dalvik_system_PathClassLoader,
-      compilation_sources_raw);
-  ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
-  soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
-}
-
 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
   // Setup the context.
   std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
@@ -635,7 +681,7 @@
       "PCL[" + CreateClassPath(classpath_dex_d) + "]";
 
   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   // Setup the compilation sources.
   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
@@ -705,7 +751,7 @@
       "PCL[" + CreateClassPath(classpath_dex_d) + "]}";
 
   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   // Setup the compilation sources.
   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
@@ -793,7 +839,7 @@
       "PCL[" + CreateClassPath(classpath_dex_d) + "]}";
 
   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   // Setup the compilation sources.
   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
@@ -893,7 +939,7 @@
       "PCL[" + CreateClassPath(classpath_dex_d) + "]";
 
   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   // Setup the compilation sources.
   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
@@ -1008,7 +1054,7 @@
       "PCL[" + CreateClassPath(classpath_dex_b) + "]}";
 
   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   // Setup the compilation sources.
   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
@@ -1085,7 +1131,7 @@
   std::string dex2_name = GetTestDexFileName("MyClass");
   std::unique_ptr<ClassLoaderContext> context =
       ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
   std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
@@ -1100,7 +1146,7 @@
   jobject class_loader_b = LoadDexInInMemoryDexClassLoader("MyClass", class_loader_a);
 
   std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
   std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
@@ -1117,7 +1163,7 @@
   std::string dex2_name = GetTestDexFileName("MultiDex");
   std::unique_ptr<ClassLoaderContext> context =
       ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   std::string encoding = context->EncodeContextForDex2oat("");
   std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]";
@@ -1129,7 +1175,7 @@
   jobject class_loader_b = LoadDexInInMemoryDexClassLoader("MyClass", class_loader_a);
 
   std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
-  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   std::string encoding = context->EncodeContextForDex2oat("");
   std::string expected_encoding = "IMC[<unknown>];PCL[" + GetTestDexFileName("Main") + "]";
@@ -1389,22 +1435,12 @@
   VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
 }
 
-TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextFirstElement) {
-  std::string context_spec = "PCL[]";
-  std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
-  ASSERT_TRUE(context != nullptr);
-  PretendContextOpenedDexFiles(context.get());
-  // Ensure that the special shared library marks as verified for the first thing in the class path.
-  ASSERT_EQ(context->VerifyClassLoaderContextMatch(OatFile::kSpecialSharedLibrary),
-            ClassLoaderContext::VerificationResult::kVerifies);
-}
-
 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
   std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
   std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
   // Pretend that we successfully open the dex files to pass the DCHECKS.
   // (as it's much easier to test all the corner cases without relying on actual dex files).
-  PretendContextOpenedDexFiles(context.get());
+  PretendContextOpenedDexFilesForChecksums(context.get());
 
   VerifyContextSize(context.get(), 2);
   VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
@@ -1458,17 +1494,6 @@
             ClassLoaderContext::VerificationResult::kVerifies);
 }
 
-TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchSpecial) {
-  std::string context_spec = "&";
-  std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
-  // Pretend that we successfully open the dex files to pass the DCHECKS.
-  // (as it's much easier to test all the corner cases without relying on actual dex files).
-  PretendContextOpenedDexFiles(context.get());
-
-  ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec),
-            ClassLoaderContext::VerificationResult::kForcedToSkipChecks);
-}
-
 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchWithSL) {
   std::string context_spec =
       "PCL[a.dex*123:b.dex*456]{PCL[d.dex*321];PCL[e.dex*654]#PCL[f.dex*098:g.dex*999]}"
diff --git a/runtime/class_root-inl.h b/runtime/class_root-inl.h
new file mode 100644
index 0000000..d88b8e1
--- /dev/null
+++ b/runtime/class_root-inl.h
@@ -0,0 +1,99 @@
+/*
+ * 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_RUNTIME_CLASS_ROOT_INL_H_
+#define ART_RUNTIME_CLASS_ROOT_INL_H_
+
+#include "class_root.h"
+
+#include "class_linker-inl.h"
+#include "mirror/class.h"
+#include "mirror/object_array-inl.h"
+#include "obj_ptr-inl.h"
+#include "runtime.h"
+
+namespace art {
+
+template <ReadBarrierOption kReadBarrierOption>
+inline ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root,
+                                          ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots) {
+  DCHECK(class_roots != nullptr);
+  if (kReadBarrierOption == kWithReadBarrier) {
+    // With read barrier all references must point to the to-space.
+    // Without read barrier, this check could fail.
+    DCHECK_EQ(class_roots, Runtime::Current()->GetClassLinker()->GetClassRoots());
+  }
+  DCHECK_LT(static_cast<uint32_t>(class_root), static_cast<uint32_t>(ClassRoot::kMax));
+  int32_t index = static_cast<int32_t>(class_root);
+  ObjPtr<mirror::Class> klass =
+      class_roots->GetWithoutChecks<kDefaultVerifyFlags, kReadBarrierOption>(index);
+  DCHECK(klass != nullptr);
+  return klass;
+}
+
+template <ReadBarrierOption kReadBarrierOption>
+inline ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root, ClassLinker* linker)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  return GetClassRoot<kReadBarrierOption>(class_root, linker->GetClassRoots<kReadBarrierOption>());
+}
+
+template <ReadBarrierOption kReadBarrierOption>
+inline ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  return GetClassRoot<kReadBarrierOption>(class_root, Runtime::Current()->GetClassLinker());
+}
+
+namespace detail {
+
+class ClassNotFoundExceptionTag;
+template <class Tag> struct NoMirrorType;
+
+template <class MirrorType>
+struct ClassRootSelector;  // No definition for unspecialized ClassRoot selector.
+
+#define SPECIALIZE_CLASS_ROOT_SELECTOR(name, descriptor, mirror_type) \
+  template <>                                                         \
+  struct ClassRootSelector<mirror_type> {                             \
+    static constexpr ClassRoot value = ClassRoot::name;               \
+  };
+
+CLASS_ROOT_LIST(SPECIALIZE_CLASS_ROOT_SELECTOR)
+
+#undef SPECIALIZE_CLASS_ROOT_SELECTOR
+
+}  // namespace detail
+
+template <class MirrorType, ReadBarrierOption kReadBarrierOption>
+inline ObjPtr<mirror::Class> GetClassRoot(ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  return GetClassRoot<kReadBarrierOption>(detail::ClassRootSelector<MirrorType>::value,
+                                          class_roots);
+}
+
+template <class MirrorType, ReadBarrierOption kReadBarrierOption>
+inline ObjPtr<mirror::Class> GetClassRoot(ClassLinker* linker)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  return GetClassRoot<kReadBarrierOption>(detail::ClassRootSelector<MirrorType>::value, linker);
+}
+
+template <class MirrorType, ReadBarrierOption kReadBarrierOption>
+inline ObjPtr<mirror::Class> GetClassRoot() REQUIRES_SHARED(Locks::mutator_lock_) {
+  return GetClassRoot<kReadBarrierOption>(detail::ClassRootSelector<MirrorType>::value);
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_CLASS_ROOT_INL_H_
diff --git a/runtime/class_root.cc b/runtime/class_root.cc
index 08820b0..6a6fd26 100644
--- a/runtime/class_root.cc
+++ b/runtime/class_root.cc
@@ -16,10 +16,12 @@
 
 #include "class_root.h"
 
+#include "base/logging.h"
+
 namespace art {
 
 const char* GetClassRootDescriptor(ClassRoot class_root) {
-  static const char* class_roots_descriptors[] = {
+  static const char* const class_roots_descriptors[] = {
 #define CLASS_ROOT_DESCRIPTOR(name, descriptor, mirror_type) descriptor,
       CLASS_ROOT_LIST(CLASS_ROOT_DESCRIPTOR)
 #undef CLASS_ROOT_DESCRIPTOR
diff --git a/runtime/class_root.h b/runtime/class_root.h
index 1ff4845..85e074c 100644
--- a/runtime/class_root.h
+++ b/runtime/class_root.h
@@ -17,20 +17,22 @@
 #ifndef ART_RUNTIME_CLASS_ROOT_H_
 #define ART_RUNTIME_CLASS_ROOT_H_
 
-#include "class_linker-inl.h"
-#include "gc_root-inl.h"
-#include "mirror/class.h"
-#include "mirror/object_array-inl.h"
-#include "obj_ptr-inl.h"
-#include "runtime.h"
+#include <stdint.h>
+
+#include "base/locks.h"
+#include "read_barrier_option.h"
 
 namespace art {
 
+class ClassLinker;
+template<class MirrorType> class ObjPtr;
+
 namespace mirror {
 class ArrayElementVarHandle;
 class ByteArrayViewVarHandle;
 class ByteBufferViewVarHandle;
 class CallSite;
+class Class;
 class ClassExt;
 class ClassLoader;
 class Constructor;
@@ -43,6 +45,7 @@
 class MethodHandlesLookup;
 class MethodType;
 class Object;
+template<class T> class ObjectArray;
 class Proxy;
 template<typename T> class PrimitiveArray;
 class Reference;
@@ -52,37 +55,50 @@
 class VarHandle;
 }  // namespace mirror
 
-#define CLASS_ROOT_LIST(M)                                                                                                                          \
-  M(kJavaLangClass,                         "Ljava/lang/Class;",                          mirror::Class)                                            \
-  M(kJavaLangObject,                        "Ljava/lang/Object;",                         mirror::Object)                                           \
-  M(kClassArrayClass,                       "[Ljava/lang/Class;",                         mirror::ObjectArray<mirror::Class>)                       \
-  M(kObjectArrayClass,                      "[Ljava/lang/Object;",                        mirror::ObjectArray<mirror::Object>)                      \
-  M(kJavaLangString,                        "Ljava/lang/String;",                         mirror::String)                                           \
-  M(kJavaLangDexCache,                      "Ljava/lang/DexCache;",                       mirror::DexCache)                                         \
-  M(kJavaLangRefReference,                  "Ljava/lang/ref/Reference;",                  mirror::Reference)                                        \
-  M(kJavaLangReflectConstructor,            "Ljava/lang/reflect/Constructor;",            mirror::Constructor)                                      \
-  M(kJavaLangReflectField,                  "Ljava/lang/reflect/Field;",                  mirror::Field)                                            \
-  M(kJavaLangReflectMethod,                 "Ljava/lang/reflect/Method;",                 mirror::Method)                                           \
-  M(kJavaLangReflectProxy,                  "Ljava/lang/reflect/Proxy;",                  mirror::Proxy)                                            \
-  M(kJavaLangStringArrayClass,              "[Ljava/lang/String;",                        mirror::ObjectArray<mirror::String>)                      \
-  M(kJavaLangReflectConstructorArrayClass,  "[Ljava/lang/reflect/Constructor;",           mirror::ObjectArray<mirror::Constructor>)                 \
-  M(kJavaLangReflectFieldArrayClass,        "[Ljava/lang/reflect/Field;",                 mirror::ObjectArray<mirror::Field>)                       \
-  M(kJavaLangReflectMethodArrayClass,       "[Ljava/lang/reflect/Method;",                mirror::ObjectArray<mirror::Method>)                      \
-  M(kJavaLangInvokeCallSite,                "Ljava/lang/invoke/CallSite;",                mirror::CallSite)                                         \
-  M(kJavaLangInvokeMethodHandle,            "Ljava/lang/invoke/MethodHandle;",            mirror::MethodHandle)                                     \
-  M(kJavaLangInvokeMethodHandleImpl,        "Ljava/lang/invoke/MethodHandleImpl;",        mirror::MethodHandleImpl)                                 \
-  M(kJavaLangInvokeMethodHandlesLookup,     "Ljava/lang/invoke/MethodHandles$Lookup;",    mirror::MethodHandlesLookup)                              \
-  M(kJavaLangInvokeMethodType,              "Ljava/lang/invoke/MethodType;",              mirror::MethodType)                                       \
-  M(kJavaLangInvokeVarHandle,               "Ljava/lang/invoke/VarHandle;",               mirror::VarHandle)                                        \
-  M(kJavaLangInvokeFieldVarHandle,          "Ljava/lang/invoke/FieldVarHandle;",          mirror::FieldVarHandle)                                   \
-  M(kJavaLangInvokeArrayElementVarHandle,   "Ljava/lang/invoke/ArrayElementVarHandle;",   mirror::ArrayElementVarHandle)                            \
-  M(kJavaLangInvokeByteArrayViewVarHandle,  "Ljava/lang/invoke/ByteArrayViewVarHandle;",  mirror::ByteArrayViewVarHandle)                           \
-  M(kJavaLangInvokeByteBufferViewVarHandle, "Ljava/lang/invoke/ByteBufferViewVarHandle;", mirror::ByteBufferViewVarHandle)                          \
-  M(kJavaLangClassLoader,                   "Ljava/lang/ClassLoader;",                    mirror::ClassLoader)                                      \
-  M(kJavaLangThrowable,                     "Ljava/lang/Throwable;",                      mirror::Throwable)                                        \
+#define CLASS_MIRROR_ROOT_LIST(M)                                                                                                         \
+  M(kJavaLangClass,                         "Ljava/lang/Class;",                          mirror::Class)                                  \
+  M(kJavaLangObject,                        "Ljava/lang/Object;",                         mirror::Object)                                 \
+  M(kClassArrayClass,                       "[Ljava/lang/Class;",                         mirror::ObjectArray<mirror::Class>)             \
+  M(kObjectArrayClass,                      "[Ljava/lang/Object;",                        mirror::ObjectArray<mirror::Object>)            \
+  M(kJavaLangString,                        "Ljava/lang/String;",                         mirror::String)                                 \
+  M(kJavaLangDexCache,                      "Ljava/lang/DexCache;",                       mirror::DexCache)                               \
+  M(kJavaLangRefReference,                  "Ljava/lang/ref/Reference;",                  mirror::Reference)                              \
+  M(kJavaLangReflectConstructor,            "Ljava/lang/reflect/Constructor;",            mirror::Constructor)                            \
+  M(kJavaLangReflectField,                  "Ljava/lang/reflect/Field;",                  mirror::Field)                                  \
+  M(kJavaLangReflectMethod,                 "Ljava/lang/reflect/Method;",                 mirror::Method)                                 \
+  M(kJavaLangReflectProxy,                  "Ljava/lang/reflect/Proxy;",                  mirror::Proxy)                                  \
+  M(kJavaLangStringArrayClass,              "[Ljava/lang/String;",                        mirror::ObjectArray<mirror::String>)            \
+  M(kJavaLangReflectConstructorArrayClass,  "[Ljava/lang/reflect/Constructor;",           mirror::ObjectArray<mirror::Constructor>)       \
+  M(kJavaLangReflectFieldArrayClass,        "[Ljava/lang/reflect/Field;",                 mirror::ObjectArray<mirror::Field>)             \
+  M(kJavaLangReflectMethodArrayClass,       "[Ljava/lang/reflect/Method;",                mirror::ObjectArray<mirror::Method>)            \
+  M(kJavaLangInvokeCallSite,                "Ljava/lang/invoke/CallSite;",                mirror::CallSite)                               \
+  M(kJavaLangInvokeMethodHandle,            "Ljava/lang/invoke/MethodHandle;",            mirror::MethodHandle)                           \
+  M(kJavaLangInvokeMethodHandleImpl,        "Ljava/lang/invoke/MethodHandleImpl;",        mirror::MethodHandleImpl)                       \
+  M(kJavaLangInvokeMethodHandlesLookup,     "Ljava/lang/invoke/MethodHandles$Lookup;",    mirror::MethodHandlesLookup)                    \
+  M(kJavaLangInvokeMethodType,              "Ljava/lang/invoke/MethodType;",              mirror::MethodType)                             \
+  M(kJavaLangInvokeVarHandle,               "Ljava/lang/invoke/VarHandle;",               mirror::VarHandle)                              \
+  M(kJavaLangInvokeFieldVarHandle,          "Ljava/lang/invoke/FieldVarHandle;",          mirror::FieldVarHandle)                         \
+  M(kJavaLangInvokeArrayElementVarHandle,   "Ljava/lang/invoke/ArrayElementVarHandle;",   mirror::ArrayElementVarHandle)                  \
+  M(kJavaLangInvokeByteArrayViewVarHandle,  "Ljava/lang/invoke/ByteArrayViewVarHandle;",  mirror::ByteArrayViewVarHandle)                 \
+  M(kJavaLangInvokeByteBufferViewVarHandle, "Ljava/lang/invoke/ByteBufferViewVarHandle;", mirror::ByteBufferViewVarHandle)                \
+  M(kJavaLangClassLoader,                   "Ljava/lang/ClassLoader;",                    mirror::ClassLoader)                            \
+  M(kJavaLangThrowable,                     "Ljava/lang/Throwable;",                      mirror::Throwable)                              \
+  M(kJavaLangStackTraceElement,             "Ljava/lang/StackTraceElement;",              mirror::StackTraceElement)                      \
+  M(kDalvikSystemEmulatedStackFrame,        "Ldalvik/system/EmulatedStackFrame;",         mirror::EmulatedStackFrame)                     \
+  M(kBooleanArrayClass,                     "[Z",                                         mirror::PrimitiveArray<uint8_t>)                \
+  M(kByteArrayClass,                        "[B",                                         mirror::PrimitiveArray<int8_t>)                 \
+  M(kCharArrayClass,                        "[C",                                         mirror::PrimitiveArray<uint16_t>)               \
+  M(kDoubleArrayClass,                      "[D",                                         mirror::PrimitiveArray<double>)                 \
+  M(kFloatArrayClass,                       "[F",                                         mirror::PrimitiveArray<float>)                  \
+  M(kIntArrayClass,                         "[I",                                         mirror::PrimitiveArray<int32_t>)                \
+  M(kLongArrayClass,                        "[J",                                         mirror::PrimitiveArray<int64_t>)                \
+  M(kShortArrayClass,                       "[S",                                         mirror::PrimitiveArray<int16_t>)                \
+  M(kJavaLangStackTraceElementArrayClass,   "[Ljava/lang/StackTraceElement;",             mirror::ObjectArray<mirror::StackTraceElement>) \
+  M(kJavaLangClassLoaderArrayClass,         "[Ljava/lang/ClassLoader;",                   mirror::ObjectArray<mirror::ClassLoader>)       \
+  M(kDalvikSystemClassExt,                  "Ldalvik/system/ClassExt;",                   mirror::ClassExt)
+
+#define CLASS_NO_MIRROR_ROOT_LIST(M)                                                                                                                \
   M(kJavaLangClassNotFoundException,        "Ljava/lang/ClassNotFoundException;",         detail::NoMirrorType<detail::ClassNotFoundExceptionTag>)  \
-  M(kJavaLangStackTraceElement,             "Ljava/lang/StackTraceElement;",              mirror::StackTraceElement)                                \
-  M(kDalvikSystemEmulatedStackFrame,        "Ldalvik/system/EmulatedStackFrame;",         mirror::EmulatedStackFrame)                               \
   M(kPrimitiveBoolean,                      "Z",                                          detail::NoMirrorType<uint8_t>)                            \
   M(kPrimitiveByte,                         "B",                                          detail::NoMirrorType<int8_t>)                             \
   M(kPrimitiveChar,                         "C",                                          detail::NoMirrorType<uint16_t>)                           \
@@ -91,18 +107,11 @@
   M(kPrimitiveInt,                          "I",                                          detail::NoMirrorType<int32_t>)                            \
   M(kPrimitiveLong,                         "J",                                          detail::NoMirrorType<int64_t>)                            \
   M(kPrimitiveShort,                        "S",                                          detail::NoMirrorType<int16_t>)                            \
-  M(kPrimitiveVoid,                         "V",                                          detail::NoMirrorType<void>)                               \
-  M(kBooleanArrayClass,                     "[Z",                                         mirror::PrimitiveArray<uint8_t>)                          \
-  M(kByteArrayClass,                        "[B",                                         mirror::PrimitiveArray<int8_t>)                           \
-  M(kCharArrayClass,                        "[C",                                         mirror::PrimitiveArray<uint16_t>)                         \
-  M(kDoubleArrayClass,                      "[D",                                         mirror::PrimitiveArray<double>)                           \
-  M(kFloatArrayClass,                       "[F",                                         mirror::PrimitiveArray<float>)                            \
-  M(kIntArrayClass,                         "[I",                                         mirror::PrimitiveArray<int32_t>)                          \
-  M(kLongArrayClass,                        "[J",                                         mirror::PrimitiveArray<int64_t>)                          \
-  M(kShortArrayClass,                       "[S",                                         mirror::PrimitiveArray<int16_t>)                          \
-  M(kJavaLangStackTraceElementArrayClass,   "[Ljava/lang/StackTraceElement;",             mirror::ObjectArray<mirror::StackTraceElement>)           \
-  M(kJavaLangClassLoaderArrayClass,         "[Ljava/lang/ClassLoader;",                   mirror::ObjectArray<mirror::ClassLoader>)                 \
-  M(kDalvikSystemClassExt,                  "Ldalvik/system/ClassExt;",                   mirror::ClassExt)
+  M(kPrimitiveVoid,                         "V",                                          detail::NoMirrorType<void>)
+
+#define CLASS_ROOT_LIST(M)     \
+  CLASS_MIRROR_ROOT_LIST(M)    \
+  CLASS_NO_MIRROR_ROOT_LIST(M)
 
 // Well known mirror::Class roots accessed via ClassLinker::GetClassRoots().
 enum class ClassRoot : uint32_t {
@@ -115,72 +124,26 @@
 const char* GetClassRootDescriptor(ClassRoot class_root);
 
 template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-inline ObjPtr<mirror::Class> GetClassRoot(
-    ClassRoot class_root,
-    ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots) REQUIRES_SHARED(Locks::mutator_lock_) {
-  DCHECK(class_roots != nullptr);
-  if (kReadBarrierOption == kWithReadBarrier) {
-    // With read barrier all references must point to the to-space.
-    // Without read barrier, this check could fail.
-    DCHECK_EQ(class_roots, Runtime::Current()->GetClassLinker()->GetClassRoots());
-  }
-  DCHECK_LT(static_cast<uint32_t>(class_root), static_cast<uint32_t>(ClassRoot::kMax));
-  int32_t index = static_cast<int32_t>(class_root);
-  ObjPtr<mirror::Class> klass =
-      class_roots->GetWithoutChecks<kDefaultVerifyFlags, kReadBarrierOption>(index);
-  DCHECK(klass != nullptr);
-  return klass;
-}
+ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root,
+                                   ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots)
+    REQUIRES_SHARED(Locks::mutator_lock_);
 
 template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-inline ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root, ClassLinker* linker)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  return GetClassRoot<kReadBarrierOption>(class_root, linker->GetClassRoots<kReadBarrierOption>());
-}
+ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root, ClassLinker* linker)
+    REQUIRES_SHARED(Locks::mutator_lock_);
 
 template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-inline ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  return GetClassRoot<kReadBarrierOption>(class_root, Runtime::Current()->GetClassLinker());
-}
-
-namespace detail {
-
-class ClassNotFoundExceptionTag;
-template <class Tag> struct NoMirrorType;
-
-template <class MirrorType>
-struct ClassRootSelector;  // No definition for unspecialized ClassRoot selector.
-
-#define SPECIALIZE_CLASS_ROOT_SELECTOR(name, descriptor, mirror_type) \
-  template <>                                                         \
-  struct ClassRootSelector<mirror_type> {                             \
-    static constexpr ClassRoot value = ClassRoot::name;               \
-  };
-
-CLASS_ROOT_LIST(SPECIALIZE_CLASS_ROOT_SELECTOR)
-
-#undef SPECIALIZE_CLASS_ROOT_SELECTOR
-
-}  // namespace detail
+ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root) REQUIRES_SHARED(Locks::mutator_lock_);
 
 template <class MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-inline ObjPtr<mirror::Class> GetClassRoot(ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  return GetClassRoot<kReadBarrierOption>(detail::ClassRootSelector<MirrorType>::value,
-                                          class_roots);
-}
+ObjPtr<mirror::Class> GetClassRoot(ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots)
+    REQUIRES_SHARED(Locks::mutator_lock_);
 
 template <class MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-inline ObjPtr<mirror::Class> GetClassRoot(ClassLinker* linker)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  return GetClassRoot<kReadBarrierOption>(detail::ClassRootSelector<MirrorType>::value, linker);
-}
+ObjPtr<mirror::Class> GetClassRoot(ClassLinker* linker) REQUIRES_SHARED(Locks::mutator_lock_);
 
 template <class MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-inline ObjPtr<mirror::Class> GetClassRoot() REQUIRES_SHARED(Locks::mutator_lock_) {
-  return GetClassRoot<kReadBarrierOption>(detail::ClassRootSelector<MirrorType>::value);
-}
+ObjPtr<mirror::Class> GetClassRoot() REQUIRES_SHARED(Locks::mutator_lock_);
 
 }  // namespace art
 
diff --git a/runtime/class_status.h b/runtime/class_status.h
index b194ffa..6c686a4 100644
--- a/runtime/class_status.h
+++ b/runtime/class_status.h
@@ -99,7 +99,7 @@
   kLast = kVisiblyInitialized
 };
 
-std::ostream& operator<<(std::ostream& os, const ClassStatus& rhs);
+std::ostream& operator<<(std::ostream& os, ClassStatus rhs);
 
 }  // namespace art
 
diff --git a/runtime/class_table-inl.h b/runtime/class_table-inl.h
index d043af3..8e44ee3 100644
--- a/runtime/class_table-inl.h
+++ b/runtime/class_table-inl.h
@@ -20,6 +20,7 @@
 #include "class_table.h"
 
 #include "base/mutex-inl.h"
+#include "dex/utf.h"
 #include "gc_root-inl.h"
 #include "mirror/class.h"
 #include "oat_file.h"
@@ -27,6 +28,44 @@
 
 namespace art {
 
+inline uint32_t ClassTable::ClassDescriptorHash::operator()(const TableSlot& slot) const {
+  std::string temp;
+  // No read barrier needed, we're reading a chain of constant references for comparison
+  // with null and retrieval of constant primitive data. See ReadBarrierOption.
+  return ComputeModifiedUtf8Hash(slot.Read<kWithoutReadBarrier>()->GetDescriptor(&temp));
+}
+
+inline uint32_t ClassTable::ClassDescriptorHash::operator()(const DescriptorHashPair& pair) const {
+  DCHECK_EQ(ComputeModifiedUtf8Hash(pair.first), pair.second);
+  return pair.second;
+}
+
+inline bool ClassTable::ClassDescriptorEquals::operator()(const TableSlot& a,
+                                                          const TableSlot& b) const {
+  // No read barrier needed, we're reading a chain of constant references for comparison
+  // with null and retrieval of constant primitive data. See ReadBarrierOption.
+  if (a.Hash() != b.Hash()) {
+    std::string temp;
+    DCHECK(!a.Read<kWithoutReadBarrier>()->DescriptorEquals(
+        b.Read<kWithoutReadBarrier>()->GetDescriptor(&temp)));
+    return false;
+  }
+  std::string temp;
+  return a.Read<kWithoutReadBarrier>()->DescriptorEquals(
+      b.Read<kWithoutReadBarrier>()->GetDescriptor(&temp));
+}
+
+inline bool ClassTable::ClassDescriptorEquals::operator()(const TableSlot& a,
+                                                          const DescriptorHashPair& b) const {
+  // No read barrier needed, we're reading a chain of constant references for comparison
+  // with null and retrieval of constant primitive data. See ReadBarrierOption.
+  if (!a.MaskedHashEquals(b.second)) {
+    DCHECK(!a.Read<kWithoutReadBarrier>()->DescriptorEquals(b.first));
+    return false;
+  }
+  return a.Read<kWithoutReadBarrier>()->DescriptorEquals(b.first);
+}
+
 template<class Visitor>
 void ClassTable::VisitRoots(Visitor& visitor) {
   ReaderMutexLock mu(Thread::Current(), lock_);
@@ -142,6 +181,13 @@
                       strong_roots_.end());
 }
 
+inline ObjPtr<mirror::Class> ClassTable::LookupByDescriptor(ObjPtr<mirror::Class> klass) {
+  std::string temp;
+  const char* descriptor = klass->GetDescriptor(&temp);
+  uint32_t hash = TableSlot::HashDescriptor(klass);
+  return Lookup(descriptor, hash);
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_CLASS_TABLE_INL_H_
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index b7d37e2..03921a1 100644
--- a/runtime/class_table.cc
+++ b/runtime/class_table.cc
@@ -33,22 +33,6 @@
   classes_.push_back(ClassSet());
 }
 
-bool ClassTable::Contains(ObjPtr<mirror::Class> klass) {
-  return LookupByDescriptor(klass) == klass;
-}
-
-ObjPtr<mirror::Class> ClassTable::LookupByDescriptor(ObjPtr<mirror::Class> klass) {
-  ReaderMutexLock mu(Thread::Current(), lock_);
-  TableSlot slot(klass);
-  for (ClassSet& class_set : classes_) {
-    auto it = class_set.find(slot);
-    if (it != class_set.end()) {
-      return it->Read();
-    }
-  }
-  return nullptr;
-}
-
 ObjPtr<mirror::Class> ClassTable::UpdateClass(const char* descriptor,
                                               ObjPtr<mirror::Class> klass,
                                               size_t hash) {
@@ -56,7 +40,7 @@
   // Should only be updating latest table.
   DescriptorHashPair pair(descriptor, hash);
   auto existing_it = classes_.back().FindWithHash(pair, hash);
-  if (kIsDebugBuild && existing_it == classes_.back().end()) {
+  if (existing_it == classes_.back().end()) {
     for (const ClassSet& class_set : classes_) {
       if (class_set.FindWithHash(pair, hash) != class_set.end()) {
         LOG(FATAL) << "Updating class found in frozen table " << descriptor;
@@ -127,41 +111,8 @@
   return nullptr;
 }
 
-ObjPtr<mirror::Class> ClassTable::TryInsert(ObjPtr<mirror::Class> klass) {
-  TableSlot slot(klass);
-  WriterMutexLock mu(Thread::Current(), lock_);
-  for (ClassSet& class_set : classes_) {
-    auto it = class_set.find(slot);
-    if (it != class_set.end()) {
-      return it->Read();
-    }
-  }
-  classes_.back().insert(slot);
-  return klass;
-}
-
 void ClassTable::Insert(ObjPtr<mirror::Class> klass) {
-  const uint32_t hash = TableSlot::HashDescriptor(klass);
-  WriterMutexLock mu(Thread::Current(), lock_);
-  classes_.back().InsertWithHash(TableSlot(klass, hash), hash);
-}
-
-void ClassTable::CopyWithoutLocks(const ClassTable& source_table) {
-  if (kIsDebugBuild) {
-    for (ClassSet& class_set : classes_) {
-      CHECK(class_set.empty());
-    }
-  }
-  for (const ClassSet& class_set : source_table.classes_) {
-    for (const TableSlot& slot : class_set) {
-      classes_.back().insert(slot);
-    }
-  }
-}
-
-void ClassTable::InsertWithoutLocks(ObjPtr<mirror::Class> klass) {
-  const uint32_t hash = TableSlot::HashDescriptor(klass);
-  classes_.back().InsertWithHash(TableSlot(klass, hash), hash);
+  InsertWithHash(klass, TableSlot::HashDescriptor(klass));
 }
 
 void ClassTable::InsertWithHash(ObjPtr<mirror::Class> klass, size_t hash) {
@@ -182,44 +133,6 @@
   return false;
 }
 
-uint32_t ClassTable::ClassDescriptorHashEquals::operator()(const TableSlot& slot)
-    const {
-  std::string temp;
-  // No read barrier needed, we're reading a chain of constant references for comparison
-  // with null and retrieval of constant primitive data. See ReadBarrierOption.
-  return ComputeModifiedUtf8Hash(slot.Read<kWithoutReadBarrier>()->GetDescriptor(&temp));
-}
-
-bool ClassTable::ClassDescriptorHashEquals::operator()(const TableSlot& a,
-                                                       const TableSlot& b) const {
-  // No read barrier needed, we're reading a chain of constant references for comparison
-  // with null and retrieval of constant primitive data. See ReadBarrierOption.
-  if (a.Hash() != b.Hash()) {
-    std::string temp;
-    DCHECK(!a.Read<kWithoutReadBarrier>()->DescriptorEquals(
-        b.Read<kWithoutReadBarrier>()->GetDescriptor(&temp)));
-    return false;
-  }
-  std::string temp;
-  return a.Read<kWithoutReadBarrier>()->DescriptorEquals(
-      b.Read<kWithoutReadBarrier>()->GetDescriptor(&temp));
-}
-
-bool ClassTable::ClassDescriptorHashEquals::operator()(const TableSlot& a,
-                                                       const DescriptorHashPair& b) const {
-  // No read barrier needed, we're reading a chain of constant references for comparison
-  // with null and retrieval of constant primitive data. See ReadBarrierOption.
-  if (!a.MaskedHashEquals(b.second)) {
-    DCHECK(!a.Read<kWithoutReadBarrier>()->DescriptorEquals(b.first));
-    return false;
-  }
-  return a.Read<kWithoutReadBarrier>()->DescriptorEquals(b.first);
-}
-
-uint32_t ClassTable::ClassDescriptorHashEquals::operator()(const DescriptorHashPair& pair) const {
-  return ComputeModifiedUtf8Hash(pair.first);
-}
-
 bool ClassTable::InsertStrongRoot(ObjPtr<mirror::Object> obj) {
   WriterMutexLock mu(Thread::Current(), lock_);
   DCHECK(obj != nullptr);
@@ -255,26 +168,6 @@
   return true;
 }
 
-size_t ClassTable::WriteToMemory(uint8_t* ptr) const {
-  ReaderMutexLock mu(Thread::Current(), lock_);
-  ClassSet combined;
-  // Combine all the class sets in case there are multiple, also adjusts load factor back to
-  // default in case classes were pruned.
-  for (const ClassSet& class_set : classes_) {
-    for (const TableSlot& root : class_set) {
-      combined.insert(root);
-    }
-  }
-  const size_t ret = combined.WriteToMemory(ptr);
-  // Sanity check.
-  if (kIsDebugBuild && ptr != nullptr) {
-    size_t read_count;
-    ClassSet class_set(ptr, /*make copy*/false, &read_count);
-    class_set.Verify();
-  }
-  return ret;
-}
-
 size_t ClassTable::ReadFromMemory(uint8_t* ptr) {
   size_t read_count = 0;
   AddClassSet(ClassSet(ptr, /*make copy*/false, &read_count));
diff --git a/runtime/class_table.h b/runtime/class_table.h
index 810c09c..dfae1fd 100644
--- a/runtime/class_table.h
+++ b/runtime/class_table.h
@@ -103,18 +103,22 @@
 
   using DescriptorHashPair = std::pair<const char*, uint32_t>;
 
-  class ClassDescriptorHashEquals {
+  class ClassDescriptorHash {
    public:
     // uint32_t for cross compilation.
     uint32_t operator()(const TableSlot& slot) const NO_THREAD_SAFETY_ANALYSIS;
+    // uint32_t for cross compilation.
+    uint32_t operator()(const DescriptorHashPair& pair) const NO_THREAD_SAFETY_ANALYSIS;
+  };
+
+  class ClassDescriptorEquals {
+   public:
     // Same class loader and descriptor.
     bool operator()(const TableSlot& a, const TableSlot& b) const
         NO_THREAD_SAFETY_ANALYSIS;
     // Same descriptor.
     bool operator()(const TableSlot& a, const DescriptorHashPair& b) const
         NO_THREAD_SAFETY_ANALYSIS;
-    // uint32_t for cross compilation.
-    uint32_t operator()(const DescriptorHashPair& pair) const NO_THREAD_SAFETY_ANALYSIS;
   };
 
   class TableSlotEmptyFn {
@@ -132,17 +136,12 @@
   // should be compared for a matching class descriptor and class loader.
   typedef HashSet<TableSlot,
                   TableSlotEmptyFn,
-                  ClassDescriptorHashEquals,
-                  ClassDescriptorHashEquals,
+                  ClassDescriptorHash,
+                  ClassDescriptorEquals,
                   TrackingAllocator<TableSlot, kAllocatorTagClassTable>> ClassSet;
 
   ClassTable();
 
-  // Used by image writer for checking.
-  bool Contains(ObjPtr<mirror::Class> klass)
-      REQUIRES(!lock_)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Freeze the current class tables by allocating a new table and never updating or modifying the
   // existing table. This helps prevents dirty pages after caused by inserting after zygote fork.
   void FreezeSnapshot()
@@ -205,16 +204,11 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Return the first class that matches the descriptor of klass. Returns null if there are none.
+  // Used for tests and debug-build checks.
   ObjPtr<mirror::Class> LookupByDescriptor(ObjPtr<mirror::Class> klass)
       REQUIRES(!lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Try to insert a class and return the inserted class if successful. If another class
-  // with the same descriptor is already in the table, return the existing entry.
-  ObjPtr<mirror::Class> TryInsert(ObjPtr<mirror::Class> klass)
-      REQUIRES(!lock_)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   void Insert(ObjPtr<mirror::Class> klass)
       REQUIRES(!lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -238,11 +232,6 @@
       REQUIRES(!lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Combines all of the tables into one class set.
-  size_t WriteToMemory(uint8_t* ptr) const
-      REQUIRES(!lock_)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Read a table from ptr and put it at the front of the class set.
   size_t ReadFromMemory(uint8_t* ptr)
       REQUIRES(!lock_)
@@ -269,10 +258,6 @@
   }
 
  private:
-  // Only copies classes.
-  void CopyWithoutLocks(const ClassTable& source_table) NO_THREAD_SAFETY_ANALYSIS;
-  void InsertWithoutLocks(ObjPtr<mirror::Class> klass) NO_THREAD_SAFETY_ANALYSIS;
-
   size_t CountDefiningLoaderClasses(ObjPtr<mirror::ClassLoader> defining_loader,
                                     const ClassSet& set) const
       REQUIRES(lock_)
diff --git a/runtime/class_table_test.cc b/runtime/class_table_test.cc
index 5275c7e..d9f53ed 100644
--- a/runtime/class_table_test.cc
+++ b/runtime/class_table_test.cc
@@ -100,12 +100,9 @@
 
   // Test inserting and related lookup functions.
   EXPECT_TRUE(table.LookupByDescriptor(h_Y.Get()) == nullptr);
-  EXPECT_FALSE(table.Contains(h_Y.Get()));
   table.Insert(h_Y.Get());
   EXPECT_OBJ_PTR_EQ(table.LookupByDescriptor(h_X.Get()), h_X.Get());
   EXPECT_OBJ_PTR_EQ(table.LookupByDescriptor(h_Y.Get()), h_Y.Get());
-  EXPECT_TRUE(table.Contains(h_X.Get()));
-  EXPECT_TRUE(table.Contains(h_Y.Get()));
 
   EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 1u);
   EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 1u);
@@ -142,19 +139,24 @@
 
   // Test remove.
   table.Remove(descriptor_x);
-  EXPECT_FALSE(table.Contains(h_X.Get()));
+  EXPECT_TRUE(table.LookupByDescriptor(h_X.Get()) == nullptr);
 
-  // Test that WriteToMemory and ReadFromMemory work.
+  // Test that reading a class set from memory works.
   table.Insert(h_X.Get());
-  const size_t count = table.WriteToMemory(nullptr);
+  ClassTable::ClassSet temp_set;
+  table.Visit([&temp_set](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
+    temp_set.insert(ClassTable::TableSlot(klass));
+    return true;
+  });
+  const size_t count = temp_set.WriteToMemory(nullptr);
   std::unique_ptr<uint8_t[]> buffer(new uint8_t[count]());
-  ASSERT_EQ(table.WriteToMemory(&buffer[0]), count);
+  ASSERT_EQ(temp_set.WriteToMemory(&buffer[0]), count);
   ClassTable table2;
   size_t count2 = table2.ReadFromMemory(&buffer[0]);
   EXPECT_EQ(count, count2);
   // Strong roots are not serialized, only classes.
-  EXPECT_TRUE(table2.Contains(h_X.Get()));
-  EXPECT_TRUE(table2.Contains(h_Y.Get()));
+  EXPECT_OBJ_PTR_EQ(table2.LookupByDescriptor(h_X.Get()), h_X.Get());
+  EXPECT_OBJ_PTR_EQ(table2.LookupByDescriptor(h_Y.Get()), h_Y.Get());
 
   // TODO: Add tests for UpdateClass, InsertOatFile.
 }
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index ffb8c77..b748e37 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -80,29 +80,6 @@
   runtime_.reset();
 }
 
-std::string CommonRuntimeTestImpl::GetAndroidTargetToolsDir(InstructionSet isa) {
-  switch (isa) {
-    case InstructionSet::kArm:
-    case InstructionSet::kThumb2:
-      return GetAndroidToolsDir("prebuilts/gcc/linux-x86/arm",
-                                "arm-linux-androideabi",
-                                "arm-linux-androideabi");
-    case InstructionSet::kArm64:
-      return GetAndroidToolsDir("prebuilts/gcc/linux-x86/aarch64",
-                                "aarch64-linux-android",
-                                "aarch64-linux-android");
-    case InstructionSet::kX86:
-    case InstructionSet::kX86_64:
-      return GetAndroidToolsDir("prebuilts/gcc/linux-x86/x86",
-                                "x86_64-linux-android",
-                                "x86_64-linux-android");
-    default:
-      break;
-  }
-  ADD_FAILURE() << "Invalid isa " << isa;
-  return "";
-}
-
 void CommonRuntimeTestImpl::SetUp() {
   CommonArtTestImpl::SetUp();
 
@@ -155,8 +132,10 @@
 
   FinalizeSetup();
 
-  // Ensure that we're really running with debug checks enabled.
-  CHECK(gSlowDebugTestFlag);
+  if (kIsDebugBuild) {
+    // Ensure that we're really running with debug checks enabled.
+    CHECK(gSlowDebugTestFlag);
+  }
 }
 
 void CommonRuntimeTestImpl::FinalizeSetup() {
@@ -165,6 +144,8 @@
   if (!unstarted_initialized_) {
     interpreter::UnstartedRuntime::Initialize();
     unstarted_initialized_ = true;
+  } else {
+    interpreter::UnstartedRuntime::Reinitialize();
   }
 
   {
@@ -528,23 +509,13 @@
   return res.StandardSuccess();
 }
 
-std::string CommonRuntimeTestImpl::GetImageDirectory() {
-  if (IsHost()) {
-    const char* host_dir = getenv("ANDROID_HOST_OUT");
-    CHECK(host_dir != nullptr);
-    return std::string(host_dir) + "/framework";
-  } else {
-    return std::string("/apex/com.android.art/javalib");
-  }
-}
-
 std::string CommonRuntimeTestImpl::GetImageLocation() {
-  return GetImageDirectory() + (IsHost() ? "/core.art" : "/boot.art");
+  return GetImageDirectory() + "/boot.art";
 }
 
 std::string CommonRuntimeTestImpl::GetSystemImageFile() {
   std::string isa = GetInstructionSetString(kRuntimeISA);
-  return GetImageDirectory() + "/" + isa + (IsHost() ? "/core.art" : "/boot.art");
+  return GetImageDirectory() + "/" + isa + "/boot.art";
 }
 
 void CommonRuntimeTestImpl::EnterTransactionMode() {
@@ -602,8 +573,9 @@
 void CommonRuntimeTestImpl::GenerateProfile(ArrayRef<const std::string> dexes,
                                             File* out_file,
                                             size_t method_frequency,
-                                            size_t type_frequency) {
-  ProfileCompilationInfo profile;
+                                            size_t type_frequency,
+                                            bool for_boot_image) {
+  ProfileCompilationInfo profile(for_boot_image);
   VisitDexes(
       dexes,
       [&profile](MethodReference ref) {
@@ -650,25 +622,3 @@
 }
 
 }  // namespace art
-
-// Allow other test code to run global initialization/configuration before
-// gtest infra takes over.
-extern "C"
-__attribute__((visibility("default"))) __attribute__((weak))
-void ArtTestGlobalInit() {
-}
-
-int main(int argc, char **argv) {
-  // Gtests can be very noisy. For example, an executable with multiple tests will trigger native
-  // bridge warnings. The following line reduces the minimum log severity to ERROR and suppresses
-  // everything else. In case you want to see all messages, comment out the line.
-  setenv("ANDROID_LOG_TAGS", "*:e", 1);
-
-  art::Locks::Init();
-  art::InitLogging(argv, art::Runtime::Abort);
-  art::MemMap::Init();
-  LOG(INFO) << "Running main() from common_runtime_test.cc...";
-  testing::InitGoogleTest(&argc, argv);
-  ArtTestGlobalInit();
-  return RUN_ALL_TESTS();
-}
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 711bc59..cc347a1 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -75,8 +75,6 @@
   CommonRuntimeTestImpl();
   virtual ~CommonRuntimeTestImpl();
 
-  static std::string GetAndroidTargetToolsDir(InstructionSet isa);
-
   // A helper function to fill the heap.
   static void FillHeap(Thread* self,
                        ClassLinker* class_linker,
@@ -176,7 +174,15 @@
   void GenerateProfile(ArrayRef<const std::string> dexes,
                        File* out_file,
                        size_t method_frequency = 1u,
-                       size_t type_frequency = 1u);
+                       size_t type_frequency = 1u,
+                       bool for_boot_image = false);
+  void GenerateBootProfile(ArrayRef<const std::string> dexes,
+                           File* out_file,
+                           size_t method_frequency = 1u,
+                           size_t type_frequency = 1u) {
+    return GenerateProfile(
+        dexes, out_file, method_frequency, type_frequency, /*for_boot_image=*/ true);
+  }
 
   std::unique_ptr<Runtime> runtime_;
 
@@ -206,8 +212,7 @@
   // initializers, initialize well-known classes, and creates the heap thread pool.
   virtual void FinalizeSetup();
 
-  // Returns the directory where the pre-compiled core.art can be found.
-  static std::string GetImageDirectory();
+  // Returns the directory where the pre-compiled boot.art can be found.
   static std::string GetImageLocation();
   static std::string GetSystemImageFile();
 
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 1c9cf18..1f5c58c 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -476,9 +476,7 @@
     case Instruction::INVOKE_POLYMORPHIC:
     case Instruction::INVOKE_POLYMORPHIC_RANGE:
     case Instruction::INVOKE_SUPER:
-    case Instruction::INVOKE_SUPER_RANGE:
-    case Instruction::INVOKE_VIRTUAL_QUICK:
-    case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
+    case Instruction::INVOKE_SUPER_RANGE: {
       // Without inlining, we could just check that the offset is the class offset.
       // However, when inlining, the compiler can (validly) merge the null check with a field access
       // on the same object. Note that the stack map at the NPE will reflect the invoke's location,
@@ -510,30 +508,6 @@
       return true;
     }
 
-    case Instruction::IGET_OBJECT_QUICK:
-      if (kEmitCompilerReadBarrier && IsValidReadBarrierImplicitCheck(addr)) {
-        return true;
-      }
-      FALLTHROUGH_INTENDED;
-    case Instruction::IGET_QUICK:
-    case Instruction::IGET_BOOLEAN_QUICK:
-    case Instruction::IGET_BYTE_QUICK:
-    case Instruction::IGET_CHAR_QUICK:
-    case Instruction::IGET_SHORT_QUICK:
-    case Instruction::IGET_WIDE_QUICK:
-    case Instruction::IPUT_QUICK:
-    case Instruction::IPUT_BOOLEAN_QUICK:
-    case Instruction::IPUT_BYTE_QUICK:
-    case Instruction::IPUT_CHAR_QUICK:
-    case Instruction::IPUT_SHORT_QUICK:
-    case Instruction::IPUT_WIDE_QUICK:
-    case Instruction::IPUT_OBJECT_QUICK: {
-      // We might be doing an implicit null check with an offset that doesn't correspond
-      // to the instruction, for example with two field accesses and the first one being
-      // eliminated or re-ordered.
-      return true;
-    }
-
     case Instruction::AGET_OBJECT:
       if (kEmitCompilerReadBarrier && IsValidReadBarrierImplicitCheck(addr)) {
         return true;
@@ -616,18 +590,6 @@
     case Instruction::INVOKE_POLYMORPHIC_RANGE:
       ThrowNullPointerExceptionForMethodAccess(instr.VRegB_4rcc(), kVirtual);
       break;
-    case Instruction::INVOKE_VIRTUAL_QUICK:
-    case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
-      uint16_t method_idx = method->GetIndexFromQuickening(throw_dex_pc);
-      if (method_idx != DexFile::kDexNoIndex16) {
-        // NPE with precise message.
-        ThrowNullPointerExceptionForMethodAccess(method_idx, kVirtual);
-      } else {
-        // NPE with imprecise message.
-        ThrowNullPointerException("Attempt to invoke a virtual method on a null object reference");
-      }
-      break;
-    }
     case Instruction::IGET:
     case Instruction::IGET_WIDE:
     case Instruction::IGET_OBJECT:
@@ -641,22 +603,6 @@
       ThrowNullPointerExceptionForFieldAccess(field, /* is_read= */ true);
       break;
     }
-    case Instruction::IGET_QUICK:
-    case Instruction::IGET_BOOLEAN_QUICK:
-    case Instruction::IGET_BYTE_QUICK:
-    case Instruction::IGET_CHAR_QUICK:
-    case Instruction::IGET_SHORT_QUICK:
-    case Instruction::IGET_WIDE_QUICK:
-    case Instruction::IGET_OBJECT_QUICK: {
-      uint16_t field_idx = method->GetIndexFromQuickening(throw_dex_pc);
-      ArtField* field = nullptr;
-      CHECK_NE(field_idx, DexFile::kDexNoIndex16);
-      field = Runtime::Current()->GetClassLinker()->ResolveField(
-          field_idx, method, /* is_static= */ false);
-      Thread::Current()->ClearException();  // Resolution may fail, ignore.
-      ThrowNullPointerExceptionForFieldAccess(field, /* is_read= */ true);
-      break;
-    }
     case Instruction::IPUT:
     case Instruction::IPUT_WIDE:
     case Instruction::IPUT_OBJECT:
@@ -670,22 +616,6 @@
       ThrowNullPointerExceptionForFieldAccess(field, /* is_read= */ false);
       break;
     }
-    case Instruction::IPUT_QUICK:
-    case Instruction::IPUT_BOOLEAN_QUICK:
-    case Instruction::IPUT_BYTE_QUICK:
-    case Instruction::IPUT_CHAR_QUICK:
-    case Instruction::IPUT_SHORT_QUICK:
-    case Instruction::IPUT_WIDE_QUICK:
-    case Instruction::IPUT_OBJECT_QUICK: {
-      uint16_t field_idx = method->GetIndexFromQuickening(throw_dex_pc);
-      ArtField* field = nullptr;
-      CHECK_NE(field_idx, DexFile::kDexNoIndex16);
-      field = Runtime::Current()->GetClassLinker()->ResolveField(
-          field_idx, method, /* is_static= */ false);
-      Thread::Current()->ClearException();  // Resolution may fail, ignore.
-      ThrowNullPointerExceptionForFieldAccess(field, /* is_read= */ false);
-      break;
-    }
     case Instruction::AGET:
     case Instruction::AGET_WIDE:
     case Instruction::AGET_OBJECT:
@@ -831,7 +761,7 @@
     ScopedLocalRef<jobject> stack_state_val(env, nullptr);
     {
       ScopedObjectAccessUnchecked soa(env);  // TODO: Is this necessary?
-      stack_state_val.reset(soa.Self()->CreateInternalStackTrace<false>(soa));
+      stack_state_val.reset(soa.Self()->CreateInternalStackTrace(soa));
     }
     if (stack_state_val != nullptr) {
       env->SetObjectField(exc.get(),
diff --git a/runtime/compat_framework.cc b/runtime/compat_framework.cc
new file mode 100644
index 0000000..17d423b
--- /dev/null
+++ b/runtime/compat_framework.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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 "compat_framework.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "android-base/logging.h"
+#include "thread-current-inl.h"
+
+namespace art {
+
+// Compat change states as strings.
+static constexpr char kUnknownChangeState[] = "UNKNOWN";
+static constexpr char kEnabledChangeState[] = "ENABLED";
+static constexpr char kDisabledChangeState[] = "DISABLED";
+static constexpr char kLoggedState[] = "LOGGED";
+
+CompatFramework::CompatFramework()
+    : reported_compat_changes_lock_("reported compat changes lock") {}
+
+CompatFramework::~CompatFramework() {}
+
+bool CompatFramework::IsChangeEnabled(uint64_t change_id) {
+  const auto enabled = disabled_compat_changes_.count(change_id) == 0;
+  ReportChange(change_id, enabled ? ChangeState::kEnabled : ChangeState::kDisabled);
+  return enabled;
+}
+
+void CompatFramework::LogChange(uint64_t change_id) {
+  ReportChange(change_id, ChangeState::kLogged);
+}
+
+void CompatFramework::ReportChange(uint64_t change_id, ChangeState state) {
+  MutexLock mu(Thread::Current(), reported_compat_changes_lock_);
+  bool already_reported = reported_compat_changes_.count(change_id) != 0;
+  if (already_reported) {
+    return;
+  }
+  LOG(DEBUG) << "Compat change id reported: " << change_id << "; UID " << getuid()
+            << "; state: " << ChangeStateToString(state);
+  // TODO(145743810): add an up call to java to log to statsd
+  reported_compat_changes_.emplace(change_id);
+}
+
+std::string_view CompatFramework::ChangeStateToString(ChangeState state) {
+  switch (state) {
+    case ChangeState::kUnknown:
+      return kUnknownChangeState;
+    case ChangeState::kEnabled:
+      return kEnabledChangeState;
+    case ChangeState::kDisabled:
+      return kDisabledChangeState;
+    case ChangeState::kLogged:
+      return kLoggedState;
+  }
+}
+
+}  // namespace art
diff --git a/runtime/compat_framework.h b/runtime/compat_framework.h
new file mode 100644
index 0000000..99a9215
--- /dev/null
+++ b/runtime/compat_framework.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 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_COMPAT_FRAMEWORK_H_
+#define ART_RUNTIME_COMPAT_FRAMEWORK_H_
+
+#include <set>
+
+#include "base/macros.h"
+#include "base/mutex.h"
+#include "base/string_view_cpp20.h"
+
+namespace art {
+
+// ART counterpart of the compat framework (go/compat-framework).
+// Created in order to avoid repeated up-calls to Java.
+class CompatFramework {
+ public:
+  // Compat change reported state
+  // This must be kept in sync with AppCompatibilityChangeReported.State in
+  // frameworks/proto_logging/stats/atoms.proto
+  enum class ChangeState {
+    kUnknown,
+    kEnabled,
+    kDisabled,
+    kLogged
+  };
+
+  CompatFramework();
+  ~CompatFramework();
+
+  void SetDisabledCompatChanges(const std::set<uint64_t>& disabled_changes) {
+    disabled_compat_changes_ = disabled_changes;
+  }
+
+  const std::set<uint64_t>& GetDisabledCompatChanges() const {
+    return disabled_compat_changes_;
+  }
+  // Query if a given compatibility change is enabled for the current process.
+  // This also gets logged to logcat, and we add the information we logged in
+  // reported_compat_changes_. This ensures we only log once per change id for the app's lifetime.
+  bool IsChangeEnabled(uint64_t change_id);
+
+  // Logs that the code path for this compatibility change has been reached.
+  // This also gets logged to logcat, and we add the information we logged in
+  // reported_compat_changes_. This ensures we only log once per change id for the app's lifetime.
+  void LogChange(uint64_t change_id);
+
+ private:
+  // Get a string equivalent for a compatibility change state.
+  static std::string_view ChangeStateToString(ChangeState s);
+  // Report the state of a compatibility change to logcat.
+  // TODO(145743810): also report to statsd.
+  void ReportChange(uint64_t change_id, ChangeState state);
+
+  // A set of disabled compat changes for the running app, all other changes are enabled.
+  std::set<uint64_t> disabled_compat_changes_;
+
+  // A set of reported compat changes for the running app.
+  std::set<uint64_t> reported_compat_changes_ GUARDED_BY(reported_compat_changes_lock_);
+  Mutex reported_compat_changes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_COMPAT_FRAMEWORK_H_
diff --git a/runtime/compilation_kind.h b/runtime/compilation_kind.h
new file mode 100644
index 0000000..c289e98
--- /dev/null
+++ b/runtime/compilation_kind.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 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_COMPILATION_KIND_H_
+#define ART_RUNTIME_COMPILATION_KIND_H_
+
+#include <iosfwd>
+#include <stdint.h>
+
+namespace art {
+
+enum class CompilationKind {
+  kOsr,
+  kBaseline,
+  kOptimized,
+};
+
+std::ostream& operator<<(std::ostream& os, CompilationKind rhs);
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_COMPILATION_KIND_H_
diff --git a/runtime/compiler_filter.cc b/runtime/compiler_filter.cc
deleted file mode 100644
index c086490..0000000
--- a/runtime/compiler_filter.cc
+++ /dev/null
@@ -1,247 +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.
- */
-
-#include "compiler_filter.h"
-
-#include <ostream>
-
-#include "base/utils.h"
-
-namespace art {
-
-bool CompilerFilter::IsAotCompilationEnabled(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kAssumeVerified:
-    case CompilerFilter::kExtract:
-    case CompilerFilter::kVerify:
-    case CompilerFilter::kQuicken: return false;
-
-    case CompilerFilter::kSpaceProfile:
-    case CompilerFilter::kSpace:
-    case CompilerFilter::kSpeedProfile:
-    case CompilerFilter::kSpeed:
-    case CompilerFilter::kEverythingProfile:
-    case CompilerFilter::kEverything: return true;
-  }
-  UNREACHABLE();
-}
-
-bool CompilerFilter::IsJniCompilationEnabled(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kAssumeVerified:
-    case CompilerFilter::kExtract:
-    case CompilerFilter::kVerify: return false;
-
-    case CompilerFilter::kQuicken:
-    case CompilerFilter::kSpaceProfile:
-    case CompilerFilter::kSpace:
-    case CompilerFilter::kSpeedProfile:
-    case CompilerFilter::kSpeed:
-    case CompilerFilter::kEverythingProfile:
-    case CompilerFilter::kEverything: return true;
-  }
-  UNREACHABLE();
-}
-
-bool CompilerFilter::IsQuickeningCompilationEnabled(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kAssumeVerified:
-    case CompilerFilter::kExtract:
-    case CompilerFilter::kVerify: return false;
-
-    case CompilerFilter::kQuicken:
-    case CompilerFilter::kSpaceProfile:
-    case CompilerFilter::kSpace:
-    case CompilerFilter::kSpeedProfile:
-    case CompilerFilter::kSpeed:
-    case CompilerFilter::kEverythingProfile:
-    case CompilerFilter::kEverything: return true;
-  }
-  UNREACHABLE();
-}
-
-bool CompilerFilter::IsAnyCompilationEnabled(Filter filter) {
-  return IsJniCompilationEnabled(filter) ||
-      IsQuickeningCompilationEnabled(filter) ||
-      IsAotCompilationEnabled(filter);
-}
-
-bool CompilerFilter::IsVerificationEnabled(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kAssumeVerified:
-    case CompilerFilter::kExtract: return false;
-
-    case CompilerFilter::kVerify:
-    case CompilerFilter::kQuicken:
-    case CompilerFilter::kSpaceProfile:
-    case CompilerFilter::kSpace:
-    case CompilerFilter::kSpeedProfile:
-    case CompilerFilter::kSpeed:
-    case CompilerFilter::kEverythingProfile:
-    case CompilerFilter::kEverything: return true;
-  }
-  UNREACHABLE();
-}
-
-bool CompilerFilter::DependsOnImageChecksum(Filter filter) {
-  // We run dex2dex with verification, so the oat file will depend on the
-  // image checksum if verification is enabled.
-  return IsVerificationEnabled(filter);
-}
-
-bool CompilerFilter::DependsOnProfile(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kAssumeVerified:
-    case CompilerFilter::kExtract:
-    case CompilerFilter::kVerify:
-    case CompilerFilter::kQuicken:
-    case CompilerFilter::kSpace:
-    case CompilerFilter::kSpeed:
-    case CompilerFilter::kEverything: return false;
-
-    case CompilerFilter::kSpaceProfile:
-    case CompilerFilter::kSpeedProfile:
-    case CompilerFilter::kEverythingProfile: return true;
-  }
-  UNREACHABLE();
-}
-
-CompilerFilter::Filter CompilerFilter::GetNonProfileDependentFilterFrom(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kAssumeVerified:
-    case CompilerFilter::kExtract:
-    case CompilerFilter::kVerify:
-    case CompilerFilter::kQuicken:
-    case CompilerFilter::kSpace:
-    case CompilerFilter::kSpeed:
-    case CompilerFilter::kEverything:
-      return filter;
-
-    case CompilerFilter::kSpaceProfile:
-      return CompilerFilter::kSpace;
-
-    case CompilerFilter::kSpeedProfile:
-      return CompilerFilter::kSpeed;
-
-    case CompilerFilter::kEverythingProfile:
-      return CompilerFilter::kEverything;
-  }
-  UNREACHABLE();
-}
-
-CompilerFilter::Filter CompilerFilter::GetSafeModeFilterFrom(Filter filter) {
-  // For safe mode, we should not return a filter that generates AOT compiled
-  // code.
-  switch (filter) {
-    case CompilerFilter::kAssumeVerified:
-    case CompilerFilter::kExtract:
-    case CompilerFilter::kVerify:
-    case CompilerFilter::kQuicken:
-      return filter;
-
-    case CompilerFilter::kSpace:
-    case CompilerFilter::kSpeed:
-    case CompilerFilter::kEverything:
-    case CompilerFilter::kSpaceProfile:
-    case CompilerFilter::kSpeedProfile:
-    case CompilerFilter::kEverythingProfile:
-      return CompilerFilter::kQuicken;
-  }
-  UNREACHABLE();
-}
-
-bool CompilerFilter::IsAsGoodAs(Filter current, Filter target) {
-  return current >= target;
-}
-
-bool CompilerFilter::IsBetter(Filter current, Filter target) {
-  return current > target;
-}
-
-std::string CompilerFilter::NameOfFilter(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kAssumeVerified: return "assume-verified";
-    case CompilerFilter::kExtract: return "extract";
-    case CompilerFilter::kVerify: return "verify";
-    case CompilerFilter::kQuicken: return "quicken";
-    case CompilerFilter::kSpaceProfile: return "space-profile";
-    case CompilerFilter::kSpace: return "space";
-    case CompilerFilter::kSpeedProfile: return "speed-profile";
-    case CompilerFilter::kSpeed: return "speed";
-    case CompilerFilter::kEverythingProfile: return "everything-profile";
-    case CompilerFilter::kEverything: return "everything";
-  }
-  UNREACHABLE();
-}
-
-bool CompilerFilter::ParseCompilerFilter(const char* option, Filter* filter) {
-  CHECK(filter != nullptr);
-
-  if (strcmp(option, "verify-none") == 0) {
-    LOG(WARNING) << "'verify-none' is an obsolete compiler filter name that will be "
-                 << "removed in future releases, please use 'assume-verified' instead.";
-    *filter = kAssumeVerified;
-  } else if (strcmp(option, "interpret-only") == 0) {
-    LOG(WARNING) << "'interpret-only' is an obsolete compiler filter name that will be "
-                 << "removed in future releases, please use 'quicken' instead.";
-    *filter = kQuicken;
-  } else if (strcmp(option, "verify-profile") == 0) {
-    LOG(WARNING) << "'verify-profile' is an obsolete compiler filter name that will be "
-                 << "removed in future releases, please use 'verify' instead.";
-    *filter = kVerify;
-  } else if (strcmp(option, "verify-at-runtime") == 0) {
-    LOG(WARNING) << "'verify-at-runtime' is an obsolete compiler filter name that will be "
-                 << "removed in future releases, please use 'extract' instead.";
-    *filter = kExtract;
-  } else if (strcmp(option, "balanced") == 0) {
-    LOG(WARNING) << "'balanced' is an obsolete compiler filter name that will be "
-                 << "removed in future releases, please use 'speed' instead.";
-    *filter = kSpeed;
-  } else if (strcmp(option, "time") == 0) {
-    LOG(WARNING) << "'time' is an obsolete compiler filter name that will be "
-                 << "removed in future releases, please use 'space' instead.";
-    *filter = kSpace;
-  } else if (strcmp(option, "assume-verified") == 0) {
-    *filter = kAssumeVerified;
-  } else if (strcmp(option, "extract") == 0) {
-    *filter = kExtract;
-  } else if (strcmp(option, "verify") == 0) {
-    *filter = kVerify;
-  } else if (strcmp(option, "quicken") == 0) {
-    *filter = kQuicken;
-  } else if (strcmp(option, "space") == 0) {
-    *filter = kSpace;
-  } else if (strcmp(option, "space-profile") == 0) {
-    *filter = kSpaceProfile;
-  } else if (strcmp(option, "speed") == 0) {
-    *filter = kSpeed;
-  } else if (strcmp(option, "speed-profile") == 0) {
-    *filter = kSpeedProfile;
-  } else if (strcmp(option, "everything") == 0) {
-    *filter = kEverything;
-  } else if (strcmp(option, "everything-profile") == 0) {
-    *filter = kEverythingProfile;
-  } else {
-    return false;
-  }
-  return true;
-}
-
-std::ostream& operator<<(std::ostream& os, const CompilerFilter::Filter& rhs) {
-  return os << CompilerFilter::NameOfFilter(rhs);
-}
-
-}  // namespace art
diff --git a/runtime/compiler_filter.h b/runtime/compiler_filter.h
deleted file mode 100644
index c36e40f..0000000
--- a/runtime/compiler_filter.h
+++ /dev/null
@@ -1,112 +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.
- */
-
-#ifndef ART_RUNTIME_COMPILER_FILTER_H_
-#define ART_RUNTIME_COMPILER_FILTER_H_
-
-#include <iosfwd>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-
-namespace art {
-
-class CompilerFilter final {
- public:
-  // Note: Order here matters. Later filter choices are considered "as good
-  // as" earlier filter choices.
-  enum Filter {
-    kAssumeVerified,      // Skip verification but mark all classes as verified anyway.
-    kExtract,             // Delay verication to runtime, do not compile anything.
-    kVerify,              // Only verify classes.
-    kQuicken,             // Verify, quicken, and compile JNI stubs.
-    kSpaceProfile,        // Maximize space savings based on profile.
-    kSpace,               // Maximize space savings.
-    kSpeedProfile,        // Maximize runtime performance based on profile.
-    kSpeed,               // Maximize runtime performance.
-    kEverythingProfile,   // Compile everything capable of being compiled based on profile.
-    kEverything,          // Compile everything capable of being compiled.
-  };
-
-  static const Filter kDefaultCompilerFilter = kSpeed;
-
-  // Returns true if an oat file with this compiler filter contains
-  // compiled executable code for bytecode.
-  static bool IsAotCompilationEnabled(Filter filter);
-
-  // Returns true if an oat file with this compiler filter contains
-  // compiled executable code for bytecode, JNI methods, or quickened dex
-  // bytecode.
-  static bool IsAnyCompilationEnabled(Filter filter);
-
-  // Returns true if an oat file with this compiler filter contains
-  // compiled executable code for JNI methods.
-  static bool IsJniCompilationEnabled(Filter filter);
-
-  // Returns true if an oat file with this compiler filter contains
-  // quickened dex bytecode.
-  static bool IsQuickeningCompilationEnabled(Filter filter);
-
-  // Returns true if this compiler filter requires running verification.
-  static bool IsVerificationEnabled(Filter filter);
-
-  // Returns true if an oat file with this compiler filter depends on the
-  // boot image checksum.
-  static bool DependsOnImageChecksum(Filter filter);
-
-  // Returns true if an oat file with this compiler filter depends on a
-  // profile.
-  static bool DependsOnProfile(Filter filter);
-
-  // Returns a non-profile-guided version of the given filter.
-  static Filter GetNonProfileDependentFilterFrom(Filter filter);
-
-  // Returns a filter suitable for safe mode.
-  static Filter GetSafeModeFilterFrom(Filter filter);
-
-  // Returns true if the 'current' compiler filter is considered at least as
-  // good as the 'target' compilation type.
-  // For example: kSpeed is as good as kInterpretOnly, but kInterpretOnly is
-  // not as good as kSpeed.
-  static bool IsAsGoodAs(Filter current, Filter target);
-
-  // Returns true if 'current' compiler filter is better than 'target' compiler
-  // filter. Compared to IsAsGoodAs, this returns false if the compiler filters are
-  // equal.
-  static bool IsBetter(Filter current, Filter target);
-
-  // Return the flag name of the given filter.
-  // For example: given kVerifyAtRuntime, returns "verify-at-runtime".
-  // The name returned corresponds to the name accepted by
-  // ParseCompilerFilter.
-  static std::string NameOfFilter(Filter filter);
-
-  // Parse the compiler filter from the given name.
-  // Returns true and sets filter to the parsed value if name refers to a
-  // valid filter. Returns false if no filter matches that name.
-  // 'filter' must be non-null.
-  static bool ParseCompilerFilter(const char* name, /*out*/Filter* filter);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CompilerFilter);
-};
-
-std::ostream& operator<<(std::ostream& os, const CompilerFilter::Filter& rhs);
-
-}  // namespace art
-
-#endif  // ART_RUNTIME_COMPILER_FILTER_H_
diff --git a/runtime/compiler_filter_test.cc b/runtime/compiler_filter_test.cc
deleted file mode 100644
index 9b4f845..0000000
--- a/runtime/compiler_filter_test.cc
+++ /dev/null
@@ -1,70 +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.
- */
-
-#include "compiler_filter.h"
-
-#include <gtest/gtest.h>
-
-namespace art {
-
-static void TestCompilerFilterName(CompilerFilter::Filter filter, const std::string& name) {
-  CompilerFilter::Filter parsed;
-  EXPECT_TRUE(CompilerFilter::ParseCompilerFilter(name.c_str(), &parsed));
-  EXPECT_EQ(filter, parsed);
-
-  EXPECT_EQ(name, CompilerFilter::NameOfFilter(filter));
-}
-
-static void TestSafeModeFilter(CompilerFilter::Filter expected, const std::string& name) {
-  CompilerFilter::Filter parsed;
-  EXPECT_TRUE(CompilerFilter::ParseCompilerFilter(name.c_str(), &parsed));
-  EXPECT_EQ(expected, CompilerFilter::GetSafeModeFilterFrom(parsed));
-}
-
-
-// Verify the dexopt status values from dalvik.system.DexFile
-// match the OatFileAssistant::DexOptStatus values.
-TEST(CompilerFilterTest, ParseCompilerFilter) {
-  CompilerFilter::Filter filter;
-
-  TestCompilerFilterName(CompilerFilter::kAssumeVerified, "assume-verified");
-  TestCompilerFilterName(CompilerFilter::kExtract, "extract");
-  TestCompilerFilterName(CompilerFilter::kVerify, "verify");
-  TestCompilerFilterName(CompilerFilter::kQuicken, "quicken");
-  TestCompilerFilterName(CompilerFilter::kSpaceProfile, "space-profile");
-  TestCompilerFilterName(CompilerFilter::kSpace, "space");
-  TestCompilerFilterName(CompilerFilter::kSpeedProfile, "speed-profile");
-  TestCompilerFilterName(CompilerFilter::kSpeed, "speed");
-  TestCompilerFilterName(CompilerFilter::kEverythingProfile, "everything-profile");
-  TestCompilerFilterName(CompilerFilter::kEverything, "everything");
-
-  EXPECT_FALSE(CompilerFilter::ParseCompilerFilter("super-awesome-filter", &filter));
-}
-
-TEST(CompilerFilterTest, SafeModeFilter) {
-  TestSafeModeFilter(CompilerFilter::kAssumeVerified, "assume-verified");
-  TestSafeModeFilter(CompilerFilter::kExtract, "extract");
-  TestSafeModeFilter(CompilerFilter::kVerify, "verify");
-  TestSafeModeFilter(CompilerFilter::kQuicken, "quicken");
-  TestSafeModeFilter(CompilerFilter::kQuicken, "space-profile");
-  TestSafeModeFilter(CompilerFilter::kQuicken, "space");
-  TestSafeModeFilter(CompilerFilter::kQuicken, "speed-profile");
-  TestSafeModeFilter(CompilerFilter::kQuicken, "speed");
-  TestSafeModeFilter(CompilerFilter::kQuicken, "everything-profile");
-  TestSafeModeFilter(CompilerFilter::kQuicken, "everything");
-}
-
-}  // namespace art
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index f218c4e..2da3e41 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -510,7 +510,7 @@
     Write4BE(&p_, reinterpret_cast<uintptr_t>(chunk_ptr));  // virtual address of segment start.
     Write4BE(&p_, 0);  // offset of this piece (relative to the virtual address).
     // [u4]: length of piece, in allocation units
-    // We won't know this until we're done, so save the offset and stuff in a dummy value.
+    // We won't know this until we're done, so save the offset and stuff in a fake value.
     pieceLenField_ = p_;
     Write4BE(&p_, 0x55555555);
     needHeader_ = false;
@@ -951,12 +951,12 @@
   {
     MutexLock mu(self, *Locks::alloc_tracker_lock_);
     gc::AllocRecordObjectMap* records = Runtime::Current()->GetHeap()->GetAllocationRecords();
-    // In case this method is called when allocation tracker is disabled,
+    // In case this method is called when allocation tracker is not enabled,
     // we should still send some data back.
-    gc::AllocRecordObjectMap dummy;
+    gc::AllocRecordObjectMap fallback_record_map;
     if (records == nullptr) {
       CHECK(!Runtime::Current()->GetHeap()->IsAllocTrackingEnabled());
-      records = &dummy;
+      records = &fallback_record_map;
     }
     // We don't need to wait on the condition variable records->new_record_condition_, because this
     // function only reads the class objects, which are already marked so it doesn't change their
diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc
index 24b3a3e..bae86de 100644
--- a/runtime/dex/dex_file_annotations.cc
+++ b/runtime/dex/dex_file_annotations.cc
@@ -24,7 +24,7 @@
 #include "art_method-inl.h"
 #include "base/sdk_version.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_instruction-inl.h"
 #include "jni/jni_internal.h"
@@ -525,21 +525,13 @@
         PointerSize pointer_size = class_linker->GetImagePointerSize();
         set_object = true;
         if (method->IsConstructor()) {
-          if (pointer_size == PointerSize::k64) {
-            element_object = mirror::Constructor::CreateFromArtMethod<PointerSize::k64,
-                kTransactionActive>(self, method);
-          } else {
-            element_object = mirror::Constructor::CreateFromArtMethod<PointerSize::k32,
-                kTransactionActive>(self, method);
-          }
+          element_object = (pointer_size == PointerSize::k64)
+              ? mirror::Constructor::CreateFromArtMethod<PointerSize::k64>(self, method)
+              : mirror::Constructor::CreateFromArtMethod<PointerSize::k32>(self, method);
         } else {
-          if (pointer_size == PointerSize::k64) {
-            element_object = mirror::Method::CreateFromArtMethod<PointerSize::k64,
-                kTransactionActive>(self, method);
-          } else {
-            element_object = mirror::Method::CreateFromArtMethod<PointerSize::k32,
-                kTransactionActive>(self, method);
-          }
+          element_object = (pointer_size == PointerSize::k64)
+              ? mirror::Method::CreateFromArtMethod<PointerSize::k64>(self, method)
+              : mirror::Method::CreateFromArtMethod<PointerSize::k32>(self, method);
         }
         if (element_object == nullptr) {
           return false;
@@ -561,14 +553,7 @@
           return false;
         }
         set_object = true;
-        PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
-        if (pointer_size == PointerSize::k64) {
-          element_object = mirror::Field::CreateFromArtField<PointerSize::k64,
-              kTransactionActive>(self, field, true);
-        } else {
-          element_object = mirror::Field::CreateFromArtField<PointerSize::k32,
-              kTransactionActive>(self, field, true);
-        }
+        element_object = mirror::Field::CreateFromArtField(self, field, true);
         if (element_object == nullptr) {
           return false;
         }
@@ -743,15 +728,9 @@
   ObjPtr<mirror::Class> annotation_member_class =
       WellKnownClasses::ToClass(WellKnownClasses::libcore_reflect_AnnotationMember);
   Handle<mirror::Object> new_member(hs.NewHandle(annotation_member_class->AllocObject(self)));
-  ObjPtr<mirror::Method> method_obj_ptr;
-  DCHECK(!Runtime::Current()->IsActiveTransaction());
-  if (pointer_size == PointerSize::k64) {
-    method_obj_ptr = mirror::Method::CreateFromArtMethod<PointerSize::k64, false>(
-        self, annotation_method);
-  } else {
-    method_obj_ptr = mirror::Method::CreateFromArtMethod<PointerSize::k32, false>(
-        self, annotation_method);
-  }
+  ObjPtr<mirror::Method> method_obj_ptr = (pointer_size == PointerSize::k64)
+      ? mirror::Method::CreateFromArtMethod<PointerSize::k64>(self, annotation_method)
+      : mirror::Method::CreateFromArtMethod<PointerSize::k32>(self, annotation_method);
   Handle<mirror::Method> method_object(hs.NewHandle(method_obj_ptr));
 
   if (new_member == nullptr || string_name == nullptr ||
@@ -1370,50 +1349,24 @@
   if (!accessor.HasCodeItem()) {
     return false;
   }
-  ArrayRef<const uint8_t> quicken_data;
-  const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
-  if (oat_dex_file != nullptr) {
-    quicken_data = oat_dex_file->GetQuickenedInfoOf(dex_file, method_index);
-  }
-  const QuickenInfoTable quicken_info(quicken_data);
-  uint32_t quicken_index = 0;
   for (DexInstructionIterator iter = accessor.begin(); iter != accessor.end(); ++iter) {
     switch (iter->Opcode()) {
       case Instruction::IGET:
-      case Instruction::IGET_QUICK:
       case Instruction::IGET_WIDE:
-      case Instruction::IGET_WIDE_QUICK:
       case Instruction::IGET_OBJECT:
-      case Instruction::IGET_OBJECT_QUICK:
       case Instruction::IGET_BOOLEAN:
-      case Instruction::IGET_BOOLEAN_QUICK:
       case Instruction::IGET_BYTE:
-      case Instruction::IGET_BYTE_QUICK:
       case Instruction::IGET_CHAR:
-      case Instruction::IGET_CHAR_QUICK:
       case Instruction::IGET_SHORT:
-      case Instruction::IGET_SHORT_QUICK:
       case Instruction::IPUT:
-      case Instruction::IPUT_QUICK:
       case Instruction::IPUT_WIDE:
-      case Instruction::IPUT_WIDE_QUICK:
       case Instruction::IPUT_OBJECT:
-      case Instruction::IPUT_OBJECT_QUICK:
       case Instruction::IPUT_BOOLEAN:
-      case Instruction::IPUT_BOOLEAN_QUICK:
       case Instruction::IPUT_BYTE:
-      case Instruction::IPUT_BYTE_QUICK:
       case Instruction::IPUT_CHAR:
-      case Instruction::IPUT_CHAR_QUICK:
       case Instruction::IPUT_SHORT:
-      case Instruction::IPUT_SHORT_QUICK:
         {
-          uint32_t field_index;
-          if (iter->IsQuickened()) {
-            field_index = quicken_info.GetData(quicken_index);
-          } else {
-            field_index = iter->VRegC_22c();
-          }
+          uint32_t field_index = iter->VRegC_22c();
           DCHECK(field_index < dex_file.NumFieldIds());
           // We only guarantee to pay attention to the annotation if it's in the same class,
           // or a containing class, but it's OK to do so in other cases.
@@ -1455,15 +1408,6 @@
           }
         }
         break;
-      case Instruction::INVOKE_VIRTUAL_QUICK:
-      case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
-        {
-          uint32_t called_method_index = quicken_info.GetData(quicken_index);
-          if (MethodIsReachabilitySensitive(dex_file, called_method_index)) {
-            return true;
-          }
-        }
-        break;
         // We explicitly do not handle indirect ReachabilitySensitive accesses through VarHandles,
         // etc. Thus we ignore INVOKE_CUSTOM / INVOKE_CUSTOM_RANGE / INVOKE_POLYMORPHIC /
         // INVOKE_POLYMORPHIC_RANGE.
@@ -1475,9 +1419,6 @@
         // fields, but they can be safely ignored.
         break;
     }
-    if (QuickenInfoTable::NeedsIndexForInstruction(&iter.Inst())) {
-      ++quicken_index;
-    }
   }
   return false;
 }
@@ -1766,7 +1707,7 @@
 int32_t GetLineNumFromPC(const DexFile* dex_file, ArtMethod* method, uint32_t rel_pc) {
   // For native method, lineno should be -2 to indicate it is native. Note that
   // "line number == -2" is how libcore tells from StackTraceElement.
-  if (method->GetCodeItemOffset() == 0) {
+  if (!method->HasCodeItem()) {
     return -2;
   }
 
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
index fb8a760..964b7f3 100644
--- a/runtime/dex2oat_environment_test.h
+++ b/runtime/dex2oat_environment_test.h
@@ -39,6 +39,8 @@
 
 namespace art {
 
+static constexpr bool kDebugArgs = false;
+
 // Test class that provides some helpers to set a test up for compilation using dex2oat.
 class Dex2oatEnvironmentTest : public CommonRuntimeTest {
  public:
@@ -68,16 +70,18 @@
 
     // Verify the environment is as we expect
     std::vector<uint32_t> checksums;
+    std::vector<std::string> dex_locations;
     std::string error_msg;
     ASSERT_TRUE(OS::FileExists(GetSystemImageFile().c_str()))
       << "Expected pre-compiled boot image to be at: " << GetSystemImageFile();
     ASSERT_TRUE(OS::FileExists(GetDexSrc1().c_str()))
       << "Expected dex file to be at: " << GetDexSrc1();
-    ASSERT_TRUE(OS::FileExists(GetStrippedDexSrc1().c_str()))
-      << "Expected stripped dex file to be at: " << GetStrippedDexSrc1();
+    ASSERT_TRUE(OS::FileExists(GetResourceOnlySrc1().c_str()))
+      << "Expected stripped dex file to be at: " << GetResourceOnlySrc1();
     ASSERT_FALSE(
-        dex_file_loader.GetMultiDexChecksums(GetStrippedDexSrc1().c_str(), &checksums, &error_msg))
-      << "Expected stripped dex file to be stripped: " << GetStrippedDexSrc1();
+        dex_file_loader.GetMultiDexChecksums(
+            GetResourceOnlySrc1().c_str(), &checksums, &dex_locations, &error_msg))
+      << "Expected stripped dex file to be stripped: " << GetResourceOnlySrc1();
     ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str()))
       << "Expected dex file to be at: " << GetDexSrc2();
 
@@ -143,7 +147,7 @@
 
   // Returns the path to a dex file equivalent to GetDexSrc1, but with the dex
   // file stripped.
-  std::string GetStrippedDexSrc1() const {
+  std::string GetResourceOnlySrc1() const {
     return GetTestDexFileName("MainStripped");
   }
 
@@ -173,6 +177,62 @@
     return odex_dir_;
   }
 
+  int Dex2Oat(const std::vector<std::string>& dex2oat_args,
+              std::string* output,
+              std::string* error_msg) {
+    std::vector<std::string> argv;
+    if (!CommonRuntimeTest::StartDex2OatCommandLine(&argv, error_msg)) {
+      ::testing::AssertionFailure() << "Could not start dex2oat cmd line " << *error_msg;
+    }
+
+    Runtime* runtime = Runtime::Current();
+    if (!runtime->IsVerificationEnabled()) {
+      argv.push_back("--compiler-filter=assume-verified");
+    }
+
+    if (runtime->MustRelocateIfPossible()) {
+      argv.push_back("--runtime-arg");
+      argv.push_back("-Xrelocate");
+    } else {
+      argv.push_back("--runtime-arg");
+      argv.push_back("-Xnorelocate");
+    }
+
+    if (!kIsTargetBuild) {
+      argv.push_back("--host");
+    }
+
+    argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
+
+    // We must set --android-root.
+    const char* android_root = getenv("ANDROID_ROOT");
+    CHECK(android_root != nullptr);
+    argv.push_back("--android-root=" + std::string(android_root));
+
+    if (kDebugArgs) {
+      std::string all_args;
+      for (const std::string& arg : argv) {
+        all_args += arg + " ";
+      }
+      LOG(ERROR) << all_args;
+    }
+
+    // We need dex2oat to actually log things.
+    auto post_fork_fn = []() { return setenv("ANDROID_LOG_TAGS", "*:d", 1) == 0; };
+    ForkAndExecResult res = ForkAndExec(argv, post_fork_fn, output);
+    if (res.stage != ForkAndExecResult::kFinished) {
+      *error_msg = strerror(errno);
+      ::testing::AssertionFailure() << "Failed to finish dex2oat invocation: " << *error_msg;
+    }
+
+    if (!res.StandardSuccess()) {
+      // We cannot use ASSERT_TRUE since the method returns an int and not void.
+      ::testing::AssertionFailure() << "dex2oat fork/exec failed: " << *error_msg;
+    }
+
+    return res.status_code;
+  }
+
  private:
   std::string scratch_dir_;
   std::string odex_oat_dir_;
diff --git a/runtime/dex_to_dex_decompiler.cc b/runtime/dex_to_dex_decompiler.cc
deleted file mode 100644
index d078d6f..0000000
--- a/runtime/dex_to_dex_decompiler.cc
+++ /dev/null
@@ -1,208 +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.
- */
-
-#include "dex_to_dex_decompiler.h"
-
-#include <android-base/logging.h>
-
-#include "base/macros.h"
-#include "base/mutex.h"
-#include "dex/bytecode_utils.h"
-#include "dex/code_item_accessors-inl.h"
-#include "dex/dex_file-inl.h"
-#include "dex/dex_instruction-inl.h"
-#include "quicken_info.h"
-
-namespace art {
-namespace optimizer {
-
-class DexDecompiler {
- public:
-  DexDecompiler(const DexFile& dex_file,
-                const dex::CodeItem& code_item,
-                const ArrayRef<const uint8_t>& quickened_info,
-                bool decompile_return_instruction)
-    : code_item_accessor_(dex_file, &code_item),
-      quicken_info_(quickened_info),
-      decompile_return_instruction_(decompile_return_instruction) {}
-
-  bool Decompile();
-
- private:
-  void DecompileInstanceFieldAccess(Instruction* inst, Instruction::Code new_opcode) {
-    uint16_t index = NextIndex();
-    inst->SetOpcode(new_opcode);
-    inst->SetVRegC_22c(index);
-  }
-
-  void DecompileInvokeVirtual(Instruction* inst, Instruction::Code new_opcode, bool is_range) {
-    const uint16_t index = NextIndex();
-    inst->SetOpcode(new_opcode);
-    if (is_range) {
-      inst->SetVRegB_3rc(index);
-    } else {
-      inst->SetVRegB_35c(index);
-    }
-  }
-
-  void DecompileNop(Instruction* inst) {
-    const uint16_t reference_index = NextIndex();
-    if (reference_index == DexFile::kDexNoIndex16) {
-      // This means it was a normal nop and not a check-cast.
-      return;
-    }
-    const uint16_t type_index = NextIndex();
-    inst->SetOpcode(Instruction::CHECK_CAST);
-    inst->SetVRegA_21c(reference_index);
-    inst->SetVRegB_21c(type_index);
-  }
-
-  uint16_t NextIndex() {
-    DCHECK_LT(quicken_index_, quicken_info_.NumIndices());
-    const uint16_t ret = quicken_info_.GetData(quicken_index_);
-    quicken_index_++;
-    return ret;
-  }
-
-  const CodeItemInstructionAccessor code_item_accessor_;
-  const QuickenInfoTable quicken_info_;
-  const bool decompile_return_instruction_;
-
-  size_t quicken_index_ = 0u;
-
-  DISALLOW_COPY_AND_ASSIGN(DexDecompiler);
-};
-
-bool DexDecompiler::Decompile() {
-  // We need to iterate over the code item, and not over the quickening data,
-  // because the RETURN_VOID quickening is not encoded in the quickening data. Because
-  // unquickening is a rare need and not performance sensitive, it is not worth the
-  // added storage to also add the RETURN_VOID quickening in the quickened data.
-  for (const DexInstructionPcPair& pair : code_item_accessor_) {
-    Instruction* inst = const_cast<Instruction*>(&pair.Inst());
-
-    switch (inst->Opcode()) {
-      case Instruction::RETURN_VOID_NO_BARRIER:
-        if (decompile_return_instruction_) {
-          inst->SetOpcode(Instruction::RETURN_VOID);
-        }
-        break;
-
-      case Instruction::NOP:
-        if (quicken_info_.NumIndices() > 0) {
-          // Only try to decompile NOP if there are more than 0 indices. Not having
-          // any index happens when we unquicken a code item that only has
-          // RETURN_VOID_NO_BARRIER as quickened instruction.
-          DecompileNop(inst);
-        }
-        break;
-
-      case Instruction::IGET_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IGET);
-        break;
-
-      case Instruction::IGET_WIDE_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IGET_WIDE);
-        break;
-
-      case Instruction::IGET_OBJECT_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IGET_OBJECT);
-        break;
-
-      case Instruction::IGET_BOOLEAN_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IGET_BOOLEAN);
-        break;
-
-      case Instruction::IGET_BYTE_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IGET_BYTE);
-        break;
-
-      case Instruction::IGET_CHAR_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IGET_CHAR);
-        break;
-
-      case Instruction::IGET_SHORT_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IGET_SHORT);
-        break;
-
-      case Instruction::IPUT_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IPUT);
-        break;
-
-      case Instruction::IPUT_BOOLEAN_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IPUT_BOOLEAN);
-        break;
-
-      case Instruction::IPUT_BYTE_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IPUT_BYTE);
-        break;
-
-      case Instruction::IPUT_CHAR_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IPUT_CHAR);
-        break;
-
-      case Instruction::IPUT_SHORT_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IPUT_SHORT);
-        break;
-
-      case Instruction::IPUT_WIDE_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IPUT_WIDE);
-        break;
-
-      case Instruction::IPUT_OBJECT_QUICK:
-        DecompileInstanceFieldAccess(inst, Instruction::IPUT_OBJECT);
-        break;
-
-      case Instruction::INVOKE_VIRTUAL_QUICK:
-        DecompileInvokeVirtual(inst, Instruction::INVOKE_VIRTUAL, false);
-        break;
-
-      case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
-        DecompileInvokeVirtual(inst, Instruction::INVOKE_VIRTUAL_RANGE, true);
-        break;
-
-      default:
-        break;
-    }
-  }
-
-  if (quicken_index_ != quicken_info_.NumIndices()) {
-    if (quicken_index_ == 0) {
-      LOG(WARNING) << "Failed to use any value in quickening info,"
-                   << " potentially due to duplicate methods.";
-    } else {
-      LOG(FATAL) << "Failed to use all values in quickening info."
-                 << " Actual: " << std::hex << quicken_index_
-                 << " Expected: " << quicken_info_.NumIndices();
-    }
-  }
-
-  return true;
-}
-
-bool ArtDecompileDEX(const DexFile& dex_file,
-                     const dex::CodeItem& code_item,
-                     const ArrayRef<const uint8_t>& quickened_info,
-                     bool decompile_return_instruction) {
-  if (quickened_info.size() == 0 && !decompile_return_instruction) {
-    return true;
-  }
-  DexDecompiler decompiler(dex_file, code_item, quickened_info, decompile_return_instruction);
-  return decompiler.Decompile();
-}
-
-}  // namespace optimizer
-}  // namespace art
diff --git a/runtime/dex_to_dex_decompiler.h b/runtime/dex_to_dex_decompiler.h
deleted file mode 100644
index 4b6b0f7..0000000
--- a/runtime/dex_to_dex_decompiler.h
+++ /dev/null
@@ -1,46 +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.
- */
-
-#ifndef ART_RUNTIME_DEX_TO_DEX_DECOMPILER_H_
-#define ART_RUNTIME_DEX_TO_DEX_DECOMPILER_H_
-
-#include "base/array_ref.h"
-
-namespace art {
-
-class DexFile;
-
-namespace dex {
-struct CodeItem;
-}  // namespace dex
-
-namespace optimizer {
-
-// "Decompile", that is unquicken, the code item provided, given the
-// associated quickening data.
-// TODO: code_item isn't really a const element, but changing it
-// to non-const has too many repercussions on the code base. We make it
-// consistent with DexToDexCompiler, but we should really change it to
-// DexFile::CodeItem*.
-bool ArtDecompileDEX(const DexFile& dex_file,
-                     const dex::CodeItem& code_item,
-                     const ArrayRef<const uint8_t>& quickened_data,
-                     bool decompile_return_instruction);
-
-}  // namespace optimizer
-}  // namespace art
-
-#endif  // ART_RUNTIME_DEX_TO_DEX_DECOMPILER_H_
diff --git a/runtime/dexopt_test.cc b/runtime/dexopt_test.cc
index 8ba6f3e..fc5a0086 100644
--- a/runtime/dexopt_test.cc
+++ b/runtime/dexopt_test.cc
@@ -26,11 +26,14 @@
 #include "base/mem_map.h"
 #include "common_runtime_test.h"
 #include "compiler_callbacks.h"
+#include "dex/art_dex_file_loader.h"
+#include "dex/dex_file_loader.h"
 #include "dex2oat_environment_test.h"
 #include "dexopt_test.h"
 #include "gc/space/image_space.h"
 #include "hidden_api.h"
 #include "oat.h"
+#include "profile/profile_compilation_info.h"
 
 namespace art {
 void DexoptTest::SetUp() {
@@ -110,6 +113,24 @@
 
   ScratchFile profile_file;
   if (CompilerFilter::DependsOnProfile(filter)) {
+    // Create a profile with some basic content so that dex2oat
+    // doesn't get an empty profile and changes the filter to verify.
+    std::string error_msg;
+    std::vector<std::unique_ptr<const DexFile>> dex_files;
+    const ArtDexFileLoader dex_file_loader;
+    ASSERT_TRUE(dex_file_loader.Open(
+        dex_location.c_str(), dex_location.c_str(), /*verify=*/ false, /*verify_checksum=*/ false,
+        &error_msg, &dex_files));
+    EXPECT_GE(dex_files.size(), 1U);
+    std::unique_ptr<const DexFile>& dex_file = dex_files[0];
+    ProfileCompilationInfo info;
+
+    info.AddClass(*dex_file, dex::TypeIndex(0));
+
+    ASSERT_TRUE(info.Save(profile_file.GetFd()));
+    ASSERT_EQ(0, profile_file.GetFile()->Flush());
+
+    // Set the argument
     args.push_back("--profile-file=" + profile_file.GetFilename());
   }
 
@@ -156,7 +177,6 @@
         ArrayRef<const std::string>(Runtime::Current()->GetBootClassPathLocations()),
         ArrayRef<const std::string>(Runtime::Current()->GetBootClassPath()),
         kRuntimeISA,
-        gc::space::ImageSpaceLoadingOrder::kSystemFirst,
         &error_msg);
     ASSERT_EQ(!with_alternate_image, match) << error_msg;
   }
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 6bd1c8f..0b4f1f3 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -548,33 +548,32 @@
 
 template <typename ElfTypes>
 typename ElfTypes::Ehdr& ElfFileImpl<ElfTypes>::GetHeader() const {
-  CHECK(header_ != nullptr);  // Header has been checked in SetMap. This is a sanity check.
+  CHECK(header_ != nullptr);  // Header has been checked in SetMap
   return *header_;
 }
 
 template <typename ElfTypes>
 uint8_t* ElfFileImpl<ElfTypes>::GetProgramHeadersStart() const {
-  CHECK(program_headers_start_ != nullptr);  // Header has been set in Setup. This is a sanity
-                                             // check.
+  CHECK(program_headers_start_ != nullptr);  // Header has been set in Setup
   return program_headers_start_;
 }
 
 template <typename ElfTypes>
 uint8_t* ElfFileImpl<ElfTypes>::GetSectionHeadersStart() const {
   CHECK(!program_header_only_);              // Only used in "full" mode.
-  CHECK(section_headers_start_ != nullptr);  // Is checked in CheckSectionsExist. Sanity check.
+  CHECK(section_headers_start_ != nullptr);  // Is checked in CheckSectionsExist
   return section_headers_start_;
 }
 
 template <typename ElfTypes>
 typename ElfTypes::Phdr& ElfFileImpl<ElfTypes>::GetDynamicProgramHeader() const {
-  CHECK(dynamic_program_header_ != nullptr);  // Is checked in CheckSectionsExist. Sanity check.
+  CHECK(dynamic_program_header_ != nullptr);  // Is checked in CheckSectionsExist
   return *dynamic_program_header_;
 }
 
 template <typename ElfTypes>
 typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::GetDynamicSectionStart() const {
-  CHECK(dynamic_section_start_ != nullptr);  // Is checked in CheckSectionsExist. Sanity check.
+  CHECK(dynamic_section_start_ != nullptr);  // Is checked in CheckSectionsExist
   return dynamic_section_start_;
 }
 
@@ -677,7 +676,7 @@
 
 template <typename ElfTypes>
 typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::GetProgramHeader(Elf_Word i) const {
-  CHECK_LT(i, GetProgramHeaderNum()) << file_path_;  // Sanity check for caller.
+  CHECK_LT(i, GetProgramHeaderNum()) << file_path_;  // Validity check for caller.
   uint8_t* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize);
   CHECK_LT(program_header, End());
   return reinterpret_cast<Elf_Phdr*>(program_header);
@@ -1369,56 +1368,6 @@
 }
 
 template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupDebugSections(Elf_Addr base_address_delta) {
-  if (base_address_delta == 0) {
-    return true;
-  }
-  return ApplyOatPatchesTo(".debug_frame", base_address_delta) &&
-         ApplyOatPatchesTo(".debug_info", base_address_delta) &&
-         ApplyOatPatchesTo(".debug_line", base_address_delta);
-}
-
-template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::ApplyOatPatchesTo(
-    const char* target_section_name, Elf_Addr delta) {
-  auto target_section = FindSectionByName(target_section_name);
-  if (target_section == nullptr) {
-    return true;
-  }
-  std::string patches_name = target_section_name + std::string(".oat_patches");
-  auto patches_section = FindSectionByName(patches_name.c_str());
-  if (patches_section == nullptr) {
-    LOG(ERROR) << patches_name << " section not found.";
-    return false;
-  }
-  if (patches_section->sh_type != SHT_OAT_PATCH) {
-    LOG(ERROR) << "Unexpected type of " << patches_name;
-    return false;
-  }
-  ApplyOatPatches(
-      Begin() + patches_section->sh_offset,
-      Begin() + patches_section->sh_offset + patches_section->sh_size,
-      delta,
-      Begin() + target_section->sh_offset,
-      Begin() + target_section->sh_offset + target_section->sh_size);
-  return true;
-}
-
-// Apply LEB128 encoded patches to given section.
-template <typename ElfTypes>
-void ElfFileImpl<ElfTypes>::ApplyOatPatches(
-    const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
-    uint8_t* to_patch, const uint8_t* to_patch_end) {
-  using UnalignedAddress __attribute__((__aligned__(1))) = Elf_Addr;
-  while (patches < patches_end) {
-    to_patch += DecodeUnsignedLeb128(&patches);
-    DCHECK_LE(patches, patches_end) << "Unexpected end of patch list.";
-    DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of section.";
-    *reinterpret_cast<UnalignedAddress*>(to_patch) += delta;
-  }
-}
-
-template <typename ElfTypes>
 bool ElfFileImpl<ElfTypes>::Strip(File* file, std::string* error_msg) {
   // ELF files produced by MCLinker look roughly like this
   //
@@ -1520,163 +1469,6 @@
   return true;
 }
 
-static const bool DEBUG_FIXUP = false;
-
-template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::Fixup(Elf_Addr base_address) {
-  if (!FixupDynamic(base_address)) {
-    LOG(WARNING) << "Failed to fixup .dynamic in " << file_path_;
-    return false;
-  }
-  if (!FixupSectionHeaders(base_address)) {
-    LOG(WARNING) << "Failed to fixup section headers in " << file_path_;
-    return false;
-  }
-  if (!FixupProgramHeaders(base_address)) {
-    LOG(WARNING) << "Failed to fixup program headers in " << file_path_;
-    return false;
-  }
-  if (!FixupSymbols(base_address, true)) {
-    LOG(WARNING) << "Failed to fixup .dynsym in " << file_path_;
-    return false;
-  }
-  if (!FixupSymbols(base_address, false)) {
-    LOG(WARNING) << "Failed to fixup .symtab in " << file_path_;
-    return false;
-  }
-  if (!FixupRelocations(base_address)) {
-    LOG(WARNING) << "Failed to fixup .rel.dyn in " << file_path_;
-    return false;
-  }
-  static_assert(sizeof(Elf_Off) >= sizeof(base_address), "Potentially losing precision.");
-  if (!FixupDebugSections(static_cast<Elf_Off>(base_address))) {
-    LOG(WARNING) << "Failed to fixup debug sections in " << file_path_;
-    return false;
-  }
-  return true;
-}
-
-template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupDynamic(Elf_Addr base_address) {
-  for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
-    Elf_Dyn& elf_dyn = GetDynamic(i);
-    Elf_Word d_tag = elf_dyn.d_tag;
-    if (IsDynamicSectionPointer(d_tag, GetHeader().e_machine)) {
-      Elf_Addr d_ptr = elf_dyn.d_un.d_ptr;
-      if (DEBUG_FIXUP) {
-        LOG(INFO) << StringPrintf("In %s moving Elf_Dyn[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
-                                  file_path_.c_str(), i,
-                                  static_cast<uint64_t>(d_ptr),
-                                  static_cast<uint64_t>(d_ptr + base_address));
-      }
-      d_ptr += base_address;
-      elf_dyn.d_un.d_ptr = d_ptr;
-    }
-  }
-  return true;
-}
-
-template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupSectionHeaders(Elf_Addr base_address) {
-  for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
-    Elf_Shdr* sh = GetSectionHeader(i);
-    CHECK(sh != nullptr);
-    // 0 implies that the section will not exist in the memory of the process
-    if (sh->sh_addr == 0) {
-      continue;
-    }
-    if (DEBUG_FIXUP) {
-      LOG(INFO) << StringPrintf("In %s moving Elf_Shdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
-                                file_path_.c_str(), i,
-                                static_cast<uint64_t>(sh->sh_addr),
-                                static_cast<uint64_t>(sh->sh_addr + base_address));
-    }
-    sh->sh_addr += base_address;
-  }
-  return true;
-}
-
-template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupProgramHeaders(Elf_Addr base_address) {
-  // TODO: ELFObjectFile doesn't have give to Elf_Phdr, so we do that ourselves for now.
-  for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
-    Elf_Phdr* ph = GetProgramHeader(i);
-    CHECK(ph != nullptr);
-    CHECK_EQ(ph->p_vaddr, ph->p_paddr) << file_path_ << " i=" << i;
-    CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
-        << file_path_ << " i=" << i;
-    if (DEBUG_FIXUP) {
-      LOG(INFO) << StringPrintf("In %s moving Elf_Phdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
-                                file_path_.c_str(), i,
-                                static_cast<uint64_t>(ph->p_vaddr),
-                                static_cast<uint64_t>(ph->p_vaddr + base_address));
-    }
-    ph->p_vaddr += base_address;
-    ph->p_paddr += base_address;
-    CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
-        << file_path_ << " i=" << i;
-  }
-  return true;
-}
-
-template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupSymbols(Elf_Addr base_address, bool dynamic) {
-  Elf_Word section_type = dynamic ? SHT_DYNSYM : SHT_SYMTAB;
-  // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
-  Elf_Shdr* symbol_section = FindSectionByType(section_type);
-  if (symbol_section == nullptr) {
-    // file is missing optional .symtab
-    CHECK(!dynamic) << file_path_;
-    return true;
-  }
-  for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
-    Elf_Sym* symbol = GetSymbol(section_type, i);
-    CHECK(symbol != nullptr);
-    if (symbol->st_value != 0) {
-      if (DEBUG_FIXUP) {
-        LOG(INFO) << StringPrintf("In %s moving Elf_Sym[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
-                                  file_path_.c_str(), i,
-                                  static_cast<uint64_t>(symbol->st_value),
-                                  static_cast<uint64_t>(symbol->st_value + base_address));
-      }
-      symbol->st_value += base_address;
-    }
-  }
-  return true;
-}
-
-template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupRelocations(Elf_Addr base_address) {
-  for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
-    Elf_Shdr* sh = GetSectionHeader(i);
-    CHECK(sh != nullptr);
-    if (sh->sh_type == SHT_REL) {
-      for (uint32_t j = 0; j < GetRelNum(*sh); j++) {
-        Elf_Rel& rel = GetRel(*sh, j);
-        if (DEBUG_FIXUP) {
-          LOG(INFO) << StringPrintf("In %s moving Elf_Rel[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
-                                    file_path_.c_str(), j,
-                                    static_cast<uint64_t>(rel.r_offset),
-                                    static_cast<uint64_t>(rel.r_offset + base_address));
-        }
-        rel.r_offset += base_address;
-      }
-    } else if (sh->sh_type == SHT_RELA) {
-      for (uint32_t j = 0; j < GetRelaNum(*sh); j++) {
-        Elf_Rela& rela = GetRela(*sh, j);
-        if (DEBUG_FIXUP) {
-          LOG(INFO) << StringPrintf("In %s moving Elf_Rela[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
-                                    file_path_.c_str(), j,
-                                    static_cast<uint64_t>(rela.r_offset),
-                                    static_cast<uint64_t>(rela.r_offset + base_address));
-        }
-        rela.r_offset += base_address;
-      }
-    }
-  }
-  return true;
-}
-
 // Explicit instantiations
 template class ElfFileImpl<ElfTypes32>;
 template class ElfFileImpl<ElfTypes64>;
@@ -1890,15 +1682,4 @@
   }
 }
 
-bool ElfFile::Fixup(uint64_t base_address) {
-  if (elf64_.get() != nullptr) {
-    return elf64_->Fixup(static_cast<Elf64_Addr>(base_address));
-  } else {
-    DCHECK(elf32_.get() != nullptr);
-    CHECK(IsUint<32>(base_address)) << std::hex << base_address;
-    return elf32_->Fixup(static_cast<Elf32_Addr>(base_address));
-  }
-  DELEGATE_TO_IMPL(Fixup, base_address);
-}
-
 }  // namespace art
diff --git a/runtime/elf_file.h b/runtime/elf_file.h
index ccfd445..0e9dd19 100644
--- a/runtime/elf_file.h
+++ b/runtime/elf_file.h
@@ -86,12 +86,6 @@
   // Returns true on success, false on failure.
   static bool Strip(File* file, std::string* error_msg);
 
-  // Fixup an ELF file so that that oat header will be loaded at oat_begin.
-  // Returns true on success, false on failure.
-  static bool Fixup(File* file, uint64_t oat_data_begin);
-
-  bool Fixup(uint64_t base_address);
-
   bool Is64Bit() const {
     return elf64_.get() != nullptr;
   }
diff --git a/runtime/elf_file_impl.h b/runtime/elf_file_impl.h
index 9900c76..8fd8044 100644
--- a/runtime/elf_file_impl.h
+++ b/runtime/elf_file_impl.h
@@ -59,6 +59,10 @@
     return file_path_;
   }
 
+  uint8_t* GetBaseAddress() const {
+    return base_address_;
+  }
+
   uint8_t* Begin() const {
     return map_.Begin();
   }
@@ -119,17 +123,6 @@
             /*inout*/MemMap* reservation,
             /*out*/std::string* error_msg);
 
-  bool Fixup(Elf_Addr base_address);
-  bool FixupDynamic(Elf_Addr base_address);
-  bool FixupSectionHeaders(Elf_Addr base_address);
-  bool FixupProgramHeaders(Elf_Addr base_address);
-  bool FixupSymbols(Elf_Addr base_address, bool dynamic);
-  bool FixupRelocations(Elf_Addr base_address);
-  bool FixupDebugSections(Elf_Addr base_address_delta);
-  bool ApplyOatPatchesTo(const char* target_section_name, Elf_Addr base_address_delta);
-  static void ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
-                              uint8_t* to_patch, const uint8_t* to_patch_end);
-
   bool Strip(File* file, std::string* error_msg);
 
  private:
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index a31be00..84299d5 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -607,8 +607,7 @@
 inline ArtField* FindFieldFast(uint32_t field_idx, ArtMethod* referrer, FindFieldType type,
                                size_t expected_size) {
   ScopedAssertNoThreadSuspension ants(__FUNCTION__);
-  ArtField* resolved_field =
-      referrer->GetDexCache()->GetResolvedField(field_idx, kRuntimePointerSize);
+  ArtField* resolved_field = referrer->GetDexCache()->GetResolvedField(field_idx);
   if (UNLIKELY(resolved_field == nullptr)) {
     return nullptr;
   }
@@ -759,12 +758,24 @@
   return method->IsStatic() && !method->IsConstructor();
 }
 
-inline HandleScope* GetGenericJniHandleScope(ArtMethod** managed_sp,
-                                             size_t num_handle_scope_references) {
-  // The HandleScope is just below the cookie and padding to align as uintptr_t.
-  const size_t offset =
-      RoundUp(HandleScope::SizeOf(num_handle_scope_references) + kJniCookieSize, sizeof(uintptr_t));
-  return reinterpret_cast<HandleScope*>(reinterpret_cast<uint8_t*>(managed_sp) - offset);
+inline jobject GetGenericJniSynchronizationObject(Thread* self, ArtMethod* called)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  DCHECK(!called->IsCriticalNative());
+  DCHECK(!called->IsFastNative());
+  DCHECK(self->GetManagedStack()->GetTopQuickFrame() != nullptr);
+  DCHECK_EQ(*self->GetManagedStack()->GetTopQuickFrame(), called);
+  if (called->IsStatic()) {
+    // Static methods synchronize on the declaring class object.
+    // The `jclass` is a pointer to the method's declaring class.
+    return reinterpret_cast<jobject>(called->GetDeclaringClassAddressWithoutBarrier());
+  } else {
+    // Instance methods synchronize on the `this` object.
+    // The `this` reference is stored in the first out vreg in the caller's frame.
+    // The `jobject` is a pointer to the spill slot.
+    uint8_t* sp = reinterpret_cast<uint8_t*>(self->GetManagedStack()->GetTopQuickFrame());
+    size_t frame_size = RuntimeCalleeSaveFrame::GetFrameSize(CalleeSaveType::kSaveRefsAndArgs);
+    return reinterpret_cast<jobject>(sp + frame_size + static_cast<size_t>(kRuntimePointerSize));
+  }
 }
 
 }  // namespace art
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 849a967..1c0127a 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -23,16 +23,19 @@
 #include "base/sdk_version.h"
 #include "class_linker-inl.h"
 #include "dex/dex_file-inl.h"
+#include "dex/method_reference.h"
 #include "entrypoints/entrypoint_utils-inl.h"
 #include "entrypoints/quick/callee_save_frame.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
 #include "gc/accounting/card_table-inl.h"
+#include "index_bss_mapping.h"
 #include "jni/java_vm_ext.h"
 #include "mirror/class-inl.h"
 #include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "nth_caller_visitor.h"
+#include "oat_file.h"
 #include "oat_quick_method_header.h"
 #include "reflection.h"
 #include "scoped_thread_state_change-inl.h"
@@ -281,4 +284,32 @@
   return method_type;
 }
 
+void MaybeUpdateBssMethodEntry(ArtMethod* callee, MethodReference callee_reference) {
+  DCHECK(callee != nullptr);
+  if (callee_reference.dex_file->GetOatDexFile() != nullptr) {
+    size_t bss_offset = IndexBssMappingLookup::GetBssOffset(
+        callee_reference.dex_file->GetOatDexFile()->GetMethodBssMapping(),
+        callee_reference.index,
+        callee_reference.dex_file->NumMethodIds(),
+        static_cast<size_t>(kRuntimePointerSize));
+    if (bss_offset != IndexBssMappingLookup::npos) {
+      DCHECK_ALIGNED(bss_offset, static_cast<size_t>(kRuntimePointerSize));
+      const OatFile* oat_file = callee_reference.dex_file->GetOatDexFile()->GetOatFile();
+      ArtMethod** method_entry = reinterpret_cast<ArtMethod**>(const_cast<uint8_t*>(
+          oat_file->BssBegin() + bss_offset));
+      DCHECK_GE(method_entry, oat_file->GetBssMethods().data());
+      DCHECK_LT(method_entry,
+                oat_file->GetBssMethods().data() + oat_file->GetBssMethods().size());
+      std::atomic<ArtMethod*>* atomic_entry =
+          reinterpret_cast<std::atomic<ArtMethod*>*>(method_entry);
+      if (kIsDebugBuild) {
+        ArtMethod* existing = atomic_entry->load(std::memory_order_acquire);
+        CHECK(existing->IsRuntimeMethod() || existing == callee);
+      }
+      static_assert(sizeof(*method_entry) == sizeof(*atomic_entry), "Size check.");
+      atomic_entry->store(callee, std::memory_order_release);
+    }
+  }
+}
+
 }  // namespace art
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 85082d3..72b4c03 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -44,6 +44,7 @@
 class ArtMethod;
 class HandleScope;
 enum InvokeType : uint32_t;
+class MethodReference;
 class OatQuickMethodHeader;
 class ScopedObjectAccessAlreadyRunnable;
 class Thread;
@@ -213,10 +214,15 @@
 // The caller is responsible for performing that check.
 bool NeedsClinitCheckBeforeCall(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
 
-constexpr size_t kJniCookieSize = sizeof(uint32_t);
+// Returns the synchronization object for a native method for a GenericJni frame
+// we have just created or are about to exit. The synchronization object is
+// the class object for static methods and the `this` object otherwise.
+jobject GetGenericJniSynchronizationObject(Thread* self, ArtMethod* called)
+    REQUIRES_SHARED(Locks::mutator_lock_);
 
-inline HandleScope* GetGenericJniHandleScope(ArtMethod** managed_sp,
-                                             size_t num_handle_scope_references);
+// Update .bss method entrypoint if the `callee_reference` has an associated oat file
+// and that oat file has a .bss entry for the `callee_reference`.
+void MaybeUpdateBssMethodEntry(ArtMethod* callee, MethodReference callee_reference);
 
 }  // namespace art
 
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc
index f1e5772..2a73dec 100644
--- a/runtime/entrypoints/jni/jni_entrypoints.cc
+++ b/runtime/entrypoints/jni/jni_entrypoints.cc
@@ -22,31 +22,102 @@
 #include "arch/x86/jni_frame_x86.h"
 #include "arch/x86_64/jni_frame_x86_64.h"
 #include "art_method-inl.h"
-#include "entrypoints/entrypoint_utils.h"
+#include "dex/dex_instruction-inl.h"
+#include "dex/method_reference.h"
+#include "entrypoints/entrypoint_utils-inl.h"
 #include "jni/java_vm_ext.h"
 #include "mirror/object-inl.h"
+#include "oat_quick_method_header.h"
 #include "scoped_thread_state_change-inl.h"
+#include "stack_map.h"
 #include "thread.h"
 
 namespace art {
 
+static inline uint32_t GetInvokeStaticMethodIndex(ArtMethod* caller, uint32_t dex_pc)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  // Get the DexFile and method index.
+  const Instruction& instruction = caller->DexInstructions().InstructionAt(dex_pc);
+  DCHECK(instruction.Opcode() == Instruction::INVOKE_STATIC ||
+         instruction.Opcode() == Instruction::INVOKE_STATIC_RANGE);
+  uint32_t method_idx = (instruction.Opcode() == Instruction::INVOKE_STATIC)
+      ? instruction.VRegB_35c()
+      : instruction.VRegB_3rc();
+  return method_idx;
+}
+
 // Used by the JNI dlsym stub to find the native method to invoke if none is registered.
 extern "C" const void* artFindNativeMethodRunnable(Thread* self)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   Locks::mutator_lock_->AssertSharedHeld(self);  // We come here as Runnable.
-  ArtMethod* method = self->GetCurrentMethod(nullptr);
+  uint32_t dex_pc;
+  ArtMethod* method = self->GetCurrentMethod(&dex_pc);
   DCHECK(method != nullptr);
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+
+  if (!method->IsNative()) {
+    // We're coming from compiled managed code and the `method` we see here is the caller.
+    // Resolve target @CriticalNative method for a direct call from compiled managed code.
+    uint32_t method_idx = GetInvokeStaticMethodIndex(method, dex_pc);
+    ArtMethod* target_method = class_linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
+        self, method_idx, method, kStatic);
+    if (target_method == nullptr) {
+      self->AssertPendingException();
+      return nullptr;
+    }
+    DCHECK(target_method->IsCriticalNative());
+    // Note that the BSS also contains entries used for super calls. Given we
+    // only deal with invokestatic in this code path, we don't need to adjust
+    // the method index.
+    MaybeUpdateBssMethodEntry(target_method, MethodReference(method->GetDexFile(), method_idx));
+
+    // These calls do not have an explicit class initialization check, so do the check now.
+    // (When going through the stub or GenericJNI, the check was already done.)
+    DCHECK(NeedsClinitCheckBeforeCall(target_method));
+    ObjPtr<mirror::Class> declaring_class = target_method->GetDeclaringClass();
+    if (UNLIKELY(!declaring_class->IsVisiblyInitialized())) {
+      StackHandleScope<1> hs(self);
+      Handle<mirror::Class> h_class(hs.NewHandle(declaring_class));
+      if (!class_linker->EnsureInitialized(self, h_class, true, true)) {
+        DCHECK(self->IsExceptionPending()) << method->PrettyMethod();
+        return nullptr;
+      }
+    }
+
+    // Replace the runtime method on the stack with the target method.
+    DCHECK(!self->GetManagedStack()->GetTopQuickFrameTag());
+    ArtMethod** sp = self->GetManagedStack()->GetTopQuickFrameKnownNotTagged();
+    DCHECK(*sp == Runtime::Current()->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs));
+    *sp = target_method;
+    self->SetTopOfStackTagged(sp);  // Fake GenericJNI frame.
+
+    // Continue with the target method.
+    method = target_method;
+  }
+  DCHECK(method == self->GetCurrentMethod(/*dex_pc=*/ nullptr));
+
+  // Check whether we already have a registered native code.
+  // For @CriticalNative it may not be stored in the ArtMethod as a JNI entrypoint if the class
+  // was not visibly initialized yet. Do this check also for @FastNative and normal native for
+  // consistency; though success would mean that another thread raced to do this lookup.
+  const void* native_code = class_linker->GetRegisteredNative(self, method);
+  if (native_code != nullptr) {
+    return native_code;
+  }
 
   // Lookup symbol address for method, on failure we'll return null with an exception set,
   // otherwise we return the address of the method we found.
   JavaVMExt* vm = down_cast<JNIEnvExt*>(self->GetJniEnv())->GetVm();
-  void* native_code = vm->FindCodeForNativeMethod(method);
+  native_code = vm->FindCodeForNativeMethod(method);
   if (native_code == nullptr) {
     self->AssertPendingException();
     return nullptr;
   }
-  // Register so that future calls don't come here
-  return method->RegisterNative(native_code);
+
+  // Register the code. This usually prevents future calls from coming to this function again.
+  // We can still come here if the ClassLinker cannot set the entrypoint in the ArtMethod,
+  // i.e. for @CriticalNative methods with the declaring class not visibly initialized.
+  return class_linker->RegisterNative(self, method, native_code);
 }
 
 // Used by the JNI dlsym stub to find the native method to invoke if none is registered.
@@ -57,23 +128,65 @@
   return artFindNativeMethodRunnable(self);
 }
 
-extern "C" size_t artCriticalNativeOutArgsSize(ArtMethod* method)
+extern "C" size_t artCriticalNativeFrameSize(ArtMethod* method, uintptr_t caller_pc)
     REQUIRES_SHARED(Locks::mutator_lock_)  {
-  uint32_t shorty_len;
-  const char* shorty = method->GetShorty(&shorty_len);
-  switch (kRuntimeISA) {
-    case InstructionSet::kArm:
-    case InstructionSet::kThumb2:
-      return arm::GetCriticalNativeOutArgsSize(shorty, shorty_len);
-    case InstructionSet::kArm64:
-      return arm64::GetCriticalNativeOutArgsSize(shorty, shorty_len);
-    case InstructionSet::kX86:
-      return x86::GetCriticalNativeOutArgsSize(shorty, shorty_len);
-    case InstructionSet::kX86_64:
-      return x86_64::GetCriticalNativeOutArgsSize(shorty, shorty_len);
-    default:
-      UNIMPLEMENTED(FATAL) << kRuntimeISA;
-      UNREACHABLE();
+  if (method->IsNative()) {
+    // Get the method's shorty.
+    DCHECK(method->IsCriticalNative());
+    uint32_t shorty_len;
+    const char* shorty = method->GetShorty(&shorty_len);
+
+    // Return the platform-dependent stub frame size.
+    switch (kRuntimeISA) {
+      case InstructionSet::kArm:
+      case InstructionSet::kThumb2:
+        return arm::GetCriticalNativeStubFrameSize(shorty, shorty_len);
+      case InstructionSet::kArm64:
+        return arm64::GetCriticalNativeStubFrameSize(shorty, shorty_len);
+      case InstructionSet::kX86:
+        return x86::GetCriticalNativeStubFrameSize(shorty, shorty_len);
+      case InstructionSet::kX86_64:
+        return x86_64::GetCriticalNativeStubFrameSize(shorty, shorty_len);
+      default:
+        UNIMPLEMENTED(FATAL) << kRuntimeISA;
+        UNREACHABLE();
+    }
+  } else {
+    // We're coming from compiled managed code and the `method` we see here is the compiled
+    // method that made the call. Get the actual caller (may be inlined) and dex pc.
+    const OatQuickMethodHeader* current_code = method->GetOatQuickMethodHeader(caller_pc);
+    DCHECK(current_code != nullptr);
+    DCHECK(current_code->IsOptimized());
+    uintptr_t native_pc_offset = current_code->NativeQuickPcOffset(caller_pc);
+    CodeInfo code_info = CodeInfo::DecodeInlineInfoOnly(current_code);
+    StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+    DCHECK(stack_map.IsValid());
+    BitTableRange<InlineInfo> inline_infos = code_info.GetInlineInfosOf(stack_map);
+    ArtMethod* caller =
+        inline_infos.empty() ? method : GetResolvedMethod(method, code_info, inline_infos);
+    uint32_t dex_pc = inline_infos.empty() ? stack_map.GetDexPc() : inline_infos.back().GetDexPc();
+
+    // Get the callee shorty.
+    const DexFile* dex_file = method->GetDexFile();
+    uint32_t method_idx = GetInvokeStaticMethodIndex(caller, dex_pc);
+    uint32_t shorty_len;
+    const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx), &shorty_len);
+
+    // Return the platform-dependent direct call frame size.
+    switch (kRuntimeISA) {
+      case InstructionSet::kArm:
+      case InstructionSet::kThumb2:
+        return arm::GetCriticalNativeDirectCallFrameSize(shorty, shorty_len);
+      case InstructionSet::kArm64:
+        return arm64::GetCriticalNativeDirectCallFrameSize(shorty, shorty_len);
+      case InstructionSet::kX86:
+        return x86::GetCriticalNativeDirectCallFrameSize(shorty, shorty_len);
+      case InstructionSet::kX86_64:
+        return x86_64::GetCriticalNativeDirectCallFrameSize(shorty, shorty_len);
+      default:
+        UNIMPLEMENTED(FATAL) << kRuntimeISA;
+        UNREACHABLE();
+    }
   }
 }
 
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
index dba4ecc..c5b4be5 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
@@ -32,7 +32,7 @@
 static constexpr bool kUseTlabFastPath = true;
 
 template <bool kInitialized,
-          bool kFinalize,
+          bool kWithChecks,
           bool kInstrumented,
           gc::AllocatorType allocator_type>
 static ALWAYS_INLINE inline mirror::Object* artAllocObjectFromCode(
@@ -40,7 +40,10 @@
     Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   DCHECK(klass != nullptr);
-  if (kUseTlabFastPath && !kInstrumented && allocator_type == gc::kAllocatorTypeTLAB) {
+  if (kUseTlabFastPath &&
+      !kWithChecks &&
+      !kInstrumented &&
+      allocator_type == gc::kAllocatorTypeTLAB) {
     // The "object size alloc fast path" is set when the class is
     // visibly initialized, objects are fixed size and non-finalizable.
     // Otherwise, the value is too large for the size check to succeed.
@@ -60,7 +63,7 @@
   }
   if (kInitialized) {
     return AllocObjectFromCodeInitialized<kInstrumented>(klass, self, allocator_type).Ptr();
-  } else if (!kFinalize) {
+  } else if (!kWithChecks) {
     return AllocObjectFromCodeResolved<kInstrumented>(klass, self, allocator_type).Ptr();
   } else {
     return AllocObjectFromCode<kInstrumented>(klass, self, allocator_type).Ptr();
@@ -211,7 +214,7 @@
   entry_points_instrumented = instrumented;
 }
 
-void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints, bool is_marking) {
+void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints) {
 #if !defined(__APPLE__) || !defined(__LP64__)
   switch (entry_points_allocator) {
     case gc::kAllocatorTypeDlMalloc: {
@@ -239,12 +242,7 @@
     }
     case gc::kAllocatorTypeRegionTLAB: {
       CHECK(kMovingCollector);
-      if (is_marking) {
-        SetQuickAllocEntryPoints_region_tlab(qpoints, entry_points_instrumented);
-      } else {
-        // Not marking means we need no read barriers and can just use the normal TLAB case.
-        SetQuickAllocEntryPoints_tlab(qpoints, entry_points_instrumented);
-      }
+      SetQuickAllocEntryPoints_region_tlab(qpoints, entry_points_instrumented);
       return;
     }
     default:
@@ -252,7 +250,6 @@
   }
 #else
   UNUSED(qpoints);
-  UNUSED(is_marking);
 #endif
   UNIMPLEMENTED(FATAL);
   UNREACHABLE();
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.h b/runtime/entrypoints/quick/quick_alloc_entrypoints.h
index 937ba8e..c4d8a80 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.h
@@ -23,9 +23,7 @@
 
 namespace art {
 
-// is_marking is only used for CC, if the GC is marking the allocation entrypoint is the marking
-// one.
-void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints, bool is_marking);
+void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints);
 
 // Runtime shutdown lock is necessary to prevent races in thread initialization. When the thread is
 // starting it doesn't hold the mutator lock until after it has been added to the thread list.
diff --git a/runtime/entrypoints/quick/quick_default_init_entrypoints.h b/runtime/entrypoints/quick/quick_default_init_entrypoints.h
index a77bb85..f3fc97e 100644
--- a/runtime/entrypoints/quick/quick_default_init_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_default_init_entrypoints.h
@@ -20,6 +20,7 @@
 #include "base/logging.h"  // FOR VLOG_IS_ON.
 #include "entrypoints/jni/jni_entrypoints.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
+#include "palette/palette.h"
 #include "quick_alloc_entrypoints.h"
 #include "quick_default_externs.h"
 #include "quick_entrypoints.h"
@@ -32,7 +33,7 @@
   jpoints->pDlsymLookupCritical = art_jni_dlsym_lookup_critical_stub;
 
   // Alloc
-  ResetQuickAllocEntryPoints(qpoints, /* is_marking= */ true);
+  ResetQuickAllocEntryPoints(qpoints);
 
   // Resolution and initialization
   qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage;
@@ -129,6 +130,18 @@
   // Tiered JIT support
   qpoints->pUpdateInlineCache = art_quick_update_inline_cache;
   qpoints->pCompileOptimized = art_quick_compile_optimized;
+
+  bool should_report = false;
+  PaletteShouldReportJniInvocations(&should_report);
+  if (should_report) {
+    qpoints->pJniMethodStart = JniMonitoredMethodStart;
+    qpoints->pJniMethodStartSynchronized = JniMonitoredMethodStartSynchronized;
+    qpoints->pJniMethodEnd = JniMonitoredMethodEnd;
+    qpoints->pJniMethodEndSynchronized = JniMonitoredMethodEndSynchronized;
+    qpoints->pJniMethodEndWithReference = JniMonitoredMethodEndWithReference;
+    qpoints->pJniMethodEndWithReferenceSynchronized =
+        JniMonitoredMethodEndWithReferenceSynchronized;
+  }
 }
 
 }  // namespace art
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 838b5b5..c576640 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -85,12 +85,22 @@
   DCHECK(dex_file != nullptr);
   const OatDexFile* oat_dex_file = dex_file->GetOatDexFile();
   if (oat_dex_file != nullptr) {
-    size_t bss_offset = IndexBssMappingLookup::GetBssOffset(oat_dex_file->GetTypeBssMapping(),
-                                                            type_idx.index_,
-                                                            dex_file->NumTypeIds(),
-                                                            sizeof(GcRoot<mirror::Class>));
-    if (bss_offset != IndexBssMappingLookup::npos) {
-      StoreObjectInBss(outer_method, oat_dex_file->GetOatFile(), bss_offset, resolved_type);
+    auto store = [=](const IndexBssMapping* mapping) REQUIRES_SHARED(Locks::mutator_lock_) {
+      size_t bss_offset = IndexBssMappingLookup::GetBssOffset(mapping,
+                                                              type_idx.index_,
+                                                              dex_file->NumTypeIds(),
+                                                              sizeof(GcRoot<mirror::Class>));
+      if (bss_offset != IndexBssMappingLookup::npos) {
+        StoreObjectInBss(outer_method, oat_dex_file->GetOatFile(), bss_offset, resolved_type);
+      }
+    };
+    store(oat_dex_file->GetTypeBssMapping());
+    if (resolved_type->IsPublic()) {
+      store(oat_dex_file->GetPublicTypeBssMapping());
+    }
+    if (resolved_type->IsPublic() ||
+        resolved_type->GetClassLoader() == outer_method->GetClassLoader()) {
+      store(oat_dex_file->GetPackageTypeBssMapping());
     }
   }
 }
@@ -180,7 +190,9 @@
                                                         self,
                                                         /* can_run_clinit= */ false,
                                                         /* verify_access= */ true);
-  // Do not StoreTypeInBss(); access check entrypoint is never used together with .bss.
+  if (LIKELY(result != nullptr) && CanReferenceBss(caller_and_outer.outer_method, caller)) {
+    StoreTypeInBss(caller_and_outer.outer_method, dex::TypeIndex(type_idx), result);
+  }
   return result.Ptr();
 }
 
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index d75893d..d41a276 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -79,16 +79,37 @@
                                                              jobject locked, Thread* self)
     NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
 
+// JNI entrypoints when monitoring entry/exit.
+extern uint32_t JniMonitoredMethodStart(Thread* self) NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+extern uint32_t JniMonitoredMethodStartSynchronized(jobject to_lock, Thread* self)
+    NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+extern void JniMonitoredMethodEnd(uint32_t saved_local_ref_cookie, Thread* self)
+    NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+extern void JniMonitoredMethodEndSynchronized(uint32_t saved_local_ref_cookie,
+                                              jobject locked,
+                                              Thread* self)
+    NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+extern mirror::Object* JniMonitoredMethodEndWithReference(jobject result,
+                                                          uint32_t saved_local_ref_cookie,
+                                                          Thread* self)
+    NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+
+extern mirror::Object* JniMonitoredMethodEndWithReferenceSynchronized(
+    jobject result,
+    uint32_t saved_local_ref_cookie,
+    jobject locked, Thread* self)
+    NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+
+
 extern "C" mirror::String* artStringBuilderAppend(uint32_t format,
                                                   const uint32_t* args,
                                                   Thread* self)
     REQUIRES_SHARED(Locks::mutator_lock_) HOT_ATTR;
 
-extern void ReadBarrierJni(mirror::CompressedReference<mirror::Object>* handle_on_stack,
+extern void ReadBarrierJni(mirror::CompressedReference<mirror::Class>* handle_on_stack,
                            Thread* self)
     NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
 
-
 // Read barrier entrypoints.
 //
 // Compilers for ARM, ARM64 can insert a call to these
diff --git a/runtime/entrypoints/quick/quick_entrypoints_enum.h b/runtime/entrypoints/quick/quick_entrypoints_enum.h
index 6240a7b..017cba6 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_enum.h
+++ b/runtime/entrypoints/quick/quick_entrypoints_enum.h
@@ -18,7 +18,6 @@
 #define ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_ENUM_H_
 
 #include "quick_entrypoints.h"
-#include "quick_entrypoints_enum.h"
 #include "thread.h"
 
 namespace art {
diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h
index e031b21..78e4dbc 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_list.h
+++ b/runtime/entrypoints/quick/quick_entrypoints_list.h
@@ -174,7 +174,7 @@
   V(UpdateInlineCache, void, void) \
   V(CompileOptimized, void, ArtMethod*, Thread*) \
 \
-  V(ReadBarrierJni, void, mirror::CompressedReference<mirror::Object>*, Thread*) \
+  V(ReadBarrierJni, void, mirror::CompressedReference<mirror::Class>*, Thread*) \
   V(ReadBarrierMarkReg00, mirror::Object*, mirror::Object*) \
   V(ReadBarrierMarkReg01, mirror::Object*, mirror::Object*) \
   V(ReadBarrierMarkReg02, mirror::Object*, mirror::Object*) \
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index 56232c5..bfe015f 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -118,25 +118,32 @@
     ArtField* field = FindFieldFast(                                           \
         field_idx, referrer, Static ## PrimitiveOrObject ## Write,             \
         sizeof(PrimitiveType));                                                \
-    if (LIKELY(field != nullptr)) {                                            \
-      field->Set ## Kind <false>(field->GetDeclaringClass(), new_value);       \
-      return 0;                                                                \
+    if (UNLIKELY(field == nullptr)) {                                          \
+      if (IsObject) {                                                          \
+        StackHandleScope<1> hs(self);                                          \
+        HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(               \
+            reinterpret_cast<mirror::Object**>(&new_value)));                  \
+        field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
+            field_idx, referrer, self, sizeof(PrimitiveType));                 \
+      } else {                                                                 \
+        field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
+            field_idx, referrer, self, sizeof(PrimitiveType));                 \
+      }                                                                        \
+      if (UNLIKELY(field == nullptr)) {                                        \
+        return -1;                                                             \
+      }                                                                        \
     }                                                                          \
-    if (IsObject) {                                                            \
-      StackHandleScope<1> hs(self);                                            \
-      HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(                 \
-          reinterpret_cast<mirror::Object**>(&new_value)));                    \
-      field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>(   \
-          field_idx, referrer, self, sizeof(PrimitiveType));                   \
-    } else {                                                                   \
-      field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>(   \
-          field_idx, referrer, self, sizeof(PrimitiveType));                   \
+    if (!referrer->SkipAccessChecks() && IsObject && new_value != 0) {         \
+      StackArtFieldHandleScope<1> rhs(self);                                   \
+      ReflectiveHandle<ArtField> field_handle(rhs.NewHandle(field));           \
+      if (field->ResolveType().IsNull()) {                                     \
+        self->AssertPendingException();                                        \
+        return -1;                                                             \
+      }                                                                        \
+      field = field_handle.Get();                                              \
     }                                                                          \
-    if (LIKELY(field != nullptr)) {                                            \
-      field->Set ## Kind <false>(field->GetDeclaringClass(), new_value);       \
-      return 0;                                                                \
-    }                                                                          \
-    return -1;                                                                 \
+    field->Set ## Kind <false>(field->GetDeclaringClass(), new_value);         \
+    return 0;                                                                  \
   }                                                                            \
                                                                                \
   extern "C" int artSet ## Kind ## InstanceFromCode(uint32_t field_idx,        \
@@ -149,33 +156,42 @@
     ArtField* field = FindFieldFast(                                           \
         field_idx, referrer, Instance ## PrimitiveOrObject ## Write,           \
         sizeof(PrimitiveType));                                                \
-    if (LIKELY(field != nullptr && obj != nullptr)) {                          \
-      field->Set ## Kind <false>(obj, new_value);                              \
-      return 0;                                                                \
+    if (UNLIKELY(field == nullptr || obj == nullptr)) {                        \
+      if (IsObject) {                                                          \
+        StackHandleScope<1> hs(self);                                          \
+        HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(               \
+            reinterpret_cast<mirror::Object**>(&new_value)));                  \
+        field =                                                                \
+            FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>(   \
+                field_idx,                                                     \
+                referrer,                                                      \
+                self,                                                          \
+                sizeof(PrimitiveType),                                         \
+                &obj);                                                         \
+      } else {                                                                 \
+        field =                                                                \
+            FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>(   \
+                field_idx,                                                     \
+                referrer,                                                      \
+                self,                                                          \
+                sizeof(PrimitiveType),                                         \
+                &obj);                                                         \
+      }                                                                        \
+      if (UNLIKELY(field == nullptr)) {                                        \
+        return -1;                                                             \
+      }                                                                        \
     }                                                                          \
-    if (IsObject) {                                                            \
-      StackHandleScope<1> hs(self);                                            \
-      HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(                 \
-          reinterpret_cast<mirror::Object**>(&new_value)));                    \
-      field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
-          field_idx,                                                           \
-          referrer,                                                            \
-          self,                                                                \
-          sizeof(PrimitiveType),                                               \
-          &obj);                                                               \
-    } else {                                                                   \
-      field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
-          field_idx,                                                           \
-          referrer,                                                            \
-          self,                                                                \
-          sizeof(PrimitiveType),                                               \
-          &obj);                                                               \
+    if (!referrer->SkipAccessChecks() && IsObject && new_value != 0) {         \
+      StackArtFieldHandleScope<1> rhs(self);                                   \
+      ReflectiveHandle<ArtField> field_handle(rhs.NewHandle(field));           \
+      if (field->ResolveType().IsNull()) {                                     \
+        self->AssertPendingException();                                        \
+        return -1;                                                             \
+      }                                                                        \
+      field = field_handle.Get();                                              \
     }                                                                          \
-    if (LIKELY(field != nullptr)) {                                            \
-      field->Set ## Kind<false>(obj, new_value);                               \
-      return 0;                                                                \
-    }                                                                          \
-    return -1;                                                                 \
+    field->Set ## Kind<false>(obj, new_value);                                 \
+    return 0;                                                                  \
   }                                                                            \
                                                                                \
   extern "C" RetType artGet ## Kind ## StaticFromCompiledCode(                 \
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index 38c6d3c..3ac7eca 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -21,9 +21,21 @@
 #include "entrypoints/entrypoint_utils-inl.h"
 #include "indirect_reference_table.h"
 #include "mirror/object-inl.h"
+#include "palette/palette.h"
 #include "thread-inl.h"
 #include "verify_object.h"
 
+// For methods that monitor JNI invocations and report their begin/end to
+// palette hooks.
+#define MONITOR_JNI(kind)                                \
+  {                                                      \
+    bool should_report = false;                          \
+    PaletteShouldReportJniInvocations(&should_report);   \
+    if (should_report) {                                 \
+      kind(self->GetJniEnv());                           \
+    }                                                    \
+  }
+
 namespace art {
 
 static_assert(sizeof(IRTSegmentState) == sizeof(uint32_t), "IRTSegmentState size unexpected");
@@ -31,20 +43,20 @@
 
 static inline void GoToRunnableFast(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
 
-extern void ReadBarrierJni(mirror::CompressedReference<mirror::Object>* handle_on_stack,
+extern void ReadBarrierJni(mirror::CompressedReference<mirror::Class>* declaring_class,
                            Thread* self ATTRIBUTE_UNUSED) {
   DCHECK(kUseReadBarrier);
   if (kUseBakerReadBarrier) {
-    DCHECK(handle_on_stack->AsMirrorPtr() != nullptr)
+    DCHECK(declaring_class->AsMirrorPtr() != nullptr)
         << "The class of a static jni call must not be null";
     // Check the mark bit and return early if it's already marked.
-    if (LIKELY(handle_on_stack->AsMirrorPtr()->GetMarkBit() != 0)) {
+    if (LIKELY(declaring_class->AsMirrorPtr()->GetMarkBit() != 0)) {
       return;
     }
   }
   // Call the read barrier and update the handle.
-  mirror::Object* to_ref = ReadBarrier::BarrierForRoot(handle_on_stack);
-  handle_on_stack->Assign(to_ref);
+  mirror::Class* to_ref = ReadBarrier::BarrierForRoot(declaring_class);
+  declaring_class->Assign(to_ref);
 }
 
 // Called on entry to fast JNI, push a new local reference table only.
@@ -68,14 +80,14 @@
   DCHECK(env != nullptr);
   uint32_t saved_local_ref_cookie = bit_cast<uint32_t>(env->GetLocalRefCookie());
   env->SetLocalRefCookie(env->GetLocalsSegmentState());
-  ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
-  // TODO: Introduce special entrypoint for synchronized @FastNative methods?
-  //       Or ban synchronized @FastNative outright to avoid the extra check here?
-  DCHECK(!native_method->IsFastNative() || native_method->IsSynchronized());
-  if (!native_method->IsFastNative()) {
-    // When not fast JNI we transition out of runnable.
-    self->TransitionFromRunnableToSuspended(kNative);
+
+  if (kIsDebugBuild) {
+    ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
+    CHECK(!native_method->IsFastNative()) << native_method->PrettyMethod();
   }
+
+  // Transition out of runnable.
+  self->TransitionFromRunnableToSuspended(kNative);
   return saved_local_ref_cookie;
 }
 
@@ -86,13 +98,12 @@
 
 // TODO: NO_THREAD_SAFETY_ANALYSIS due to different control paths depending on fast JNI.
 static void GoToRunnable(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
-  ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
-  bool is_fast = native_method->IsFastNative();
-  if (!is_fast) {
-    self->TransitionFromSuspendedToRunnable();
-  } else {
-    GoToRunnableFast(self);
+  if (kIsDebugBuild) {
+    ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
+    CHECK(!native_method->IsFastNative()) << native_method->PrettyMethod();
   }
+
+  self->TransitionFromSuspendedToRunnable();
 }
 
 ALWAYS_INLINE static inline void GoToRunnableFast(Thread* self) {
@@ -120,7 +131,6 @@
   }
   env->SetLocalSegmentState(env->GetLocalRefCookie());
   env->SetLocalRefCookie(bit_cast<IRTSegmentState>(saved_local_ref_cookie));
-  self->PopHandleScope();
 }
 
 // TODO: annotalysis disabled as monitor semantics are maintained in Java code.
@@ -223,16 +233,19 @@
   bool fast_native = called->IsFastNative();
   bool normal_native = !critical_native && !fast_native;
 
-  // @Fast and @CriticalNative do not do a state transition.
+  // @CriticalNative does not do a state transition. @FastNative usually does not do a state
+  // transition either but it performs a suspend check that may do state transitions.
   if (LIKELY(normal_native)) {
+    MONITOR_JNI(PaletteNotifyEndJniInvocation);
     GoToRunnable(self);
+  } else if (fast_native) {
+    GoToRunnableFast(self);
   }
   // We need the mutator lock (i.e., calling GoToRunnable()) before accessing the shorty or the
   // locked object.
   if (called->IsSynchronized()) {
     DCHECK(normal_native) << "@FastNative/@CriticalNative and synchronize is not supported";
-    HandleScope* handle_scope = down_cast<HandleScope*>(self->GetTopHandleScope());
-    jobject lock = handle_scope->GetHandle(0).ToJObject();
+    jobject lock = GetGenericJniSynchronizationObject(self, called);
     DCHECK(lock != nullptr);
     UnlockJniSynchronizedMethod(lock, self);
   }
@@ -242,7 +255,7 @@
         result.l, saved_local_ref_cookie, self));
   } else {
     if (LIKELY(!critical_native)) {
-      PopLocalReferences(saved_local_ref_cookie, self);  // Invalidates top handle scope.
+      PopLocalReferences(saved_local_ref_cookie, self);
     }
     switch (return_shorty_char) {
       case 'F': {
@@ -277,4 +290,44 @@
   }
 }
 
+extern uint32_t JniMonitoredMethodStart(Thread* self) {
+  uint32_t result = JniMethodStart(self);
+  MONITOR_JNI(PaletteNotifyBeginJniInvocation);
+  return result;
+}
+
+extern uint32_t JniMonitoredMethodStartSynchronized(jobject to_lock, Thread* self) {
+  uint32_t result = JniMethodStartSynchronized(to_lock, self);
+  MONITOR_JNI(PaletteNotifyBeginJniInvocation);
+  return result;
+}
+
+extern void JniMonitoredMethodEnd(uint32_t saved_local_ref_cookie, Thread* self) {
+  MONITOR_JNI(PaletteNotifyEndJniInvocation);
+  return JniMethodEnd(saved_local_ref_cookie, self);
+}
+
+extern void JniMonitoredMethodEndSynchronized(uint32_t saved_local_ref_cookie,
+                                             jobject locked,
+                                             Thread* self) {
+  MONITOR_JNI(PaletteNotifyEndJniInvocation);
+  return JniMethodEndSynchronized(saved_local_ref_cookie, locked, self);
+}
+
+extern mirror::Object* JniMonitoredMethodEndWithReference(jobject result,
+                                                          uint32_t saved_local_ref_cookie,
+                                                          Thread* self) {
+  MONITOR_JNI(PaletteNotifyEndJniInvocation);
+  return JniMethodEndWithReference(result, saved_local_ref_cookie, self);
+}
+
+extern mirror::Object* JniMonitoredMethodEndWithReferenceSynchronized(
+    jobject result,
+    uint32_t saved_local_ref_cookie,
+    jobject locked,
+    Thread* self) {
+  MONITOR_JNI(PaletteNotifyEndJniInvocation);
+  return JniMethodEndWithReferenceSynchronized(result, saved_local_ref_cookie, locked, self);
+}
+
 }  // namespace art
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 5356637..eaa9f4e 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -19,7 +19,7 @@
 #include "base/enums.h"
 #include "callee_save_frame.h"
 #include "common_throws.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "debug_print.h"
 #include "debugger.h"
 #include "dex/dex_file-inl.h"
@@ -32,7 +32,6 @@
 #include "gc/accounting/card_table-inl.h"
 #include "imt_conflict_table.h"
 #include "imtable-inl.h"
-#include "index_bss_mapping.h"
 #include "instrumentation.h"
 #include "interpreter/interpreter.h"
 #include "interpreter/interpreter_common.h"
@@ -589,8 +588,8 @@
   // Coming from partial-fragment deopt.
   Thread* self = Thread::Current();
   if (kIsDebugBuild) {
-    // Sanity-check: are the methods as expected? We check that the last shadow frame (the bottom
-    // of the call-stack) corresponds to the called method.
+    // Consistency-check: are the methods as expected? We check that the last shadow frame
+    // (the bottom of the call-stack) corresponds to the called method.
     ShadowFrame* linked = deopt_frame;
     while (linked->GetLink() != nullptr) {
       linked = linked->GetLink();
@@ -618,19 +617,19 @@
 
   // Ensure that the stack is still in order.
   if (kIsDebugBuild) {
-    class DummyStackVisitor : public StackVisitor {
+    class EntireStackVisitor : public StackVisitor {
      public:
-      explicit DummyStackVisitor(Thread* self_in) REQUIRES_SHARED(Locks::mutator_lock_)
+      explicit EntireStackVisitor(Thread* self_in) REQUIRES_SHARED(Locks::mutator_lock_)
           : StackVisitor(self_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
 
       bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
-        // Nothing to do here. In a debug build, SanityCheckFrame will do the work in the walking
+        // Nothing to do here. In a debug build, ValidateFrame will do the work in the walking
         // logic. Just always say we want to continue.
         return true;
       }
     };
-    DummyStackVisitor dsv(self);
-    dsv.WalkStack();
+    EntireStackVisitor esv(self);
+    esv.WalkStack();
   }
 
   // Restore the exception that was pending before deoptimization then interpret the
@@ -845,7 +844,7 @@
   DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
   DCHECK(!Runtime::Current()->IsActiveTransaction());
   ObjPtr<mirror::Method> interface_reflect_method =
-      mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), interface_method);
+      mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), interface_method);
   if (interface_reflect_method == nullptr) {
     soa.Self()->AssertPendingOOMException();
     return 0;
@@ -1095,7 +1094,7 @@
   // Instrumentation exit stub must not be entered with a pending exception.
   CHECK(!self->IsExceptionPending()) << "Enter instrumentation exit stub with pending exception "
                                      << self->GetException()->Dump();
-  // Compute address of return PC and sanity check that it currently holds 0.
+  // Compute address of return PC and check that it currently holds 0.
   constexpr size_t return_pc_offset =
       RuntimeCalleeSaveFrame::GetReturnPcOffset(CalleeSaveType::kSaveEverything);
   uintptr_t* return_pc_addr = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(sp) +
@@ -1312,34 +1311,12 @@
   // Resolve method filling in dex cache.
   if (!called_method_known_on_entry) {
     StackHandleScope<1> hs(self);
-    mirror::Object* dummy = nullptr;
+    mirror::Object* fake_receiver = nullptr;
     HandleWrapper<mirror::Object> h_receiver(
-        hs.NewHandleWrapper(virtual_or_interface ? &receiver : &dummy));
+        hs.NewHandleWrapper(virtual_or_interface ? &receiver : &fake_receiver));
     DCHECK_EQ(caller->GetDexFile(), called_method.dex_file);
     called = linker->ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
         self, called_method.index, caller, invoke_type);
-
-    // Update .bss entry in oat file if any.
-    if (called != nullptr && called_method.dex_file->GetOatDexFile() != nullptr) {
-      size_t bss_offset = IndexBssMappingLookup::GetBssOffset(
-          called_method.dex_file->GetOatDexFile()->GetMethodBssMapping(),
-          called_method.index,
-          called_method.dex_file->NumMethodIds(),
-          static_cast<size_t>(kRuntimePointerSize));
-      if (bss_offset != IndexBssMappingLookup::npos) {
-        DCHECK_ALIGNED(bss_offset, static_cast<size_t>(kRuntimePointerSize));
-        const OatFile* oat_file = called_method.dex_file->GetOatDexFile()->GetOatFile();
-        ArtMethod** method_entry = reinterpret_cast<ArtMethod**>(const_cast<uint8_t*>(
-            oat_file->BssBegin() + bss_offset));
-        DCHECK_GE(method_entry, oat_file->GetBssMethods().data());
-        DCHECK_LT(method_entry,
-                  oat_file->GetBssMethods().data() + oat_file->GetBssMethods().size());
-        std::atomic<ArtMethod*>* atomic_entry =
-            reinterpret_cast<std::atomic<ArtMethod*>*>(method_entry);
-        static_assert(sizeof(*method_entry) == sizeof(*atomic_entry), "Size check.");
-        atomic_entry->store(called, std::memory_order_release);
-      }
-    }
   }
   const void* code = nullptr;
   if (LIKELY(!self->IsExceptionPending())) {
@@ -1373,36 +1350,48 @@
                                << mirror::Object::PrettyTypeOf(receiver) << " "
                                << invoke_type << " " << orig_called->GetVtableIndex();
     }
+    // Now that we know the actual target, update .bss entry in oat file, if
+    // any.
+    if (!called_method_known_on_entry) {
+      // We only put non copied methods in the BSS. Putting a copy can lead to an
+      // odd situation where the ArtMethod being executed is unrelated to the
+      // receiver of the method.
+      called = called->GetCanonicalMethod();
+      if (invoke_type == kSuper || invoke_type == kInterface || invoke_type == kVirtual) {
+        if (called->GetDexFile() == called_method.dex_file) {
+          called_method.index = called->GetDexMethodIndex();
+        } else {
+          called_method.index = called->FindDexMethodIndexInOtherDexFile(
+              *called_method.dex_file, called_method.index);
+          DCHECK_NE(called_method.index, dex::kDexNoIndex);
+        }
+      }
+      MaybeUpdateBssMethodEntry(called, called_method);
+    }
 
+    // Static invokes need class initialization check but instance invokes can proceed even if
+    // the class is erroneous, i.e. in the edge case of escaping instances of erroneous classes.
+    bool success = true;
     ObjPtr<mirror::Class> called_class = called->GetDeclaringClass();
     if (NeedsClinitCheckBeforeCall(called) && !called_class->IsVisiblyInitialized()) {
       // Ensure that the called method's class is initialized.
       StackHandleScope<1> hs(soa.Self());
       HandleWrapperObjPtr<mirror::Class> h_called_class(hs.NewHandleWrapper(&called_class));
-      linker->EnsureInitialized(soa.Self(), h_called_class, true, true);
+      success = linker->EnsureInitialized(soa.Self(), h_called_class, true, true);
     }
-    bool force_interpreter = self->IsForceInterpreter() && !called->IsNative();
-    if (called_class->IsInitialized() || called_class->IsInitializing()) {
-      if (UNLIKELY(force_interpreter)) {
-        // If we are single-stepping or the called method is deoptimized (by a
-        // breakpoint, for example), then we have to execute the called method
-        // with the interpreter.
+    if (success) {
+      code = called->GetEntryPointFromQuickCompiledCode();
+      if (linker->IsQuickResolutionStub(code)) {
+        DCHECK_EQ(invoke_type, kStatic);
+        // Go to JIT or oat and grab code.
+        code = linker->GetQuickOatCodeFor(called);
+      }
+      if (linker->ShouldUseInterpreterEntrypoint(called, code)) {
         code = GetQuickToInterpreterBridge();
-      } else {
-        code = called->GetEntryPointFromQuickCompiledCode();
-        if (linker->IsQuickResolutionStub(code)) {
-          DCHECK_EQ(invoke_type, kStatic);
-          // Go to JIT or oat and grab code.
-          code = linker->GetQuickOatCodeFor(called);
-          if (called_class->IsInitialized()) {
-            // Only update the entrypoint once the class is initialized. Other
-            // threads still need to go through the resolution stub.
-            Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(called, code);
-          }
-        }
       }
     } else {
       DCHECK(called_class->IsErroneous());
+      DCHECK(self->IsExceptionPending());
     }
   }
   CHECK_EQ(code == nullptr, self->IsExceptionPending());
@@ -1447,17 +1436,10 @@
  *                            necessary.
  *
  * void PushStack(uintptr_t): Push a value to the stack.
- *
- * uintptr_t PushHandleScope(mirror::Object* ref): Add a reference to the HandleScope. This _will_ have nullptr,
- *                                          as this might be important for null initialization.
- *                                          Must return the jobject, that is, the reference to the
- *                                          entry in the HandleScope (nullptr if necessary).
- *
  */
 template<class T> class BuildNativeCallFrameStateMachine {
  public:
 #if defined(__arm__)
-  // TODO: These are all dummy values!
   static constexpr bool kNativeSoftFloatAbi = true;
   static constexpr size_t kNumNativeGprArgs = 4;  // 4 arguments passed in GPRs, r0-r3
   static constexpr size_t kNumNativeFprArgs = 0;  // 0 arguments passed in FPRs.
@@ -1482,7 +1464,6 @@
   static constexpr bool kAlignLongOnStack = false;
   static constexpr bool kAlignDoubleOnStack = false;
 #elif defined(__i386__)
-  // TODO: Check these!
   static constexpr bool kNativeSoftFloatAbi = false;  // Not using int registers for fp
   static constexpr size_t kNumNativeGprArgs = 0;  // 0 arguments passed in GPRs.
   static constexpr size_t kNumNativeFprArgs = 0;  // 0 arguments passed in FPRs.
@@ -1539,22 +1520,6 @@
     }
   }
 
-  bool HaveHandleScopeGpr() const {
-    return gpr_index_ > 0;
-  }
-
-  void AdvanceHandleScope(mirror::Object* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
-    uintptr_t handle = PushHandle(ptr);
-    if (HaveHandleScopeGpr()) {
-      gpr_index_--;
-      PushGpr(handle);
-    } else {
-      stack_entries_++;
-      PushStack(handle);
-      gpr_index_ = 0;
-    }
-  }
-
   bool HaveIntGpr() const {
     return gpr_index_ > 0;
   }
@@ -1731,9 +1696,6 @@
   void PushStack(uintptr_t val) {
     delegate_->PushStack(val);
   }
-  uintptr_t PushHandle(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_) {
-    return delegate_->PushHandle(ref);
-  }
 
   uint32_t gpr_index_;      // Number of free GPRs
   uint32_t fpr_index_;      // Number of free FPRs
@@ -1778,11 +1740,8 @@
       Primitive::Type cur_type_ = Primitive::GetType(shorty[i]);
       switch (cur_type_) {
         case Primitive::kPrimNot:
-          // TODO: fix abuse of mirror types.
-          sm.AdvanceHandleScope(
-              reinterpret_cast<mirror::Object*>(0x12345678));
+          sm.AdvancePointer(nullptr);
           break;
-
         case Primitive::kPrimBoolean:
         case Primitive::kPrimByte:
         case Primitive::kPrimChar:
@@ -1824,10 +1783,6 @@
     // counting is already done in the superclass
   }
 
-  virtual uintptr_t PushHandle(mirror::Object* /* ptr */) {
-    return reinterpret_cast<uintptr_t>(nullptr);
-  }
-
  protected:
   uint32_t num_stack_entries_;
 };
@@ -1835,26 +1790,18 @@
 class ComputeGenericJniFrameSize final : public ComputeNativeCallFrameSize {
  public:
   explicit ComputeGenericJniFrameSize(bool critical_native)
-    : num_handle_scope_references_(0), critical_native_(critical_native) {}
+    : critical_native_(critical_native) {}
 
-  uintptr_t* ComputeLayout(Thread* self,
-                           ArtMethod** managed_sp,
-                           const char* shorty,
-                           uint32_t shorty_len,
-                           HandleScope** handle_scope) REQUIRES_SHARED(Locks::mutator_lock_) {
+  uintptr_t* ComputeLayout(ArtMethod** managed_sp, const char* shorty, uint32_t shorty_len)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
     DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
 
     Walk(shorty, shorty_len);
 
-    // Add space for cookie and HandleScope.
-    void* storage = GetGenericJniHandleScope(managed_sp, num_handle_scope_references_);
-    DCHECK_ALIGNED(storage, sizeof(uintptr_t));
-    *handle_scope =
-        HandleScope::Create(storage, self->GetTopHandleScope(), num_handle_scope_references_);
-    DCHECK_EQ(*handle_scope, storage);
-    uint8_t* sp8 = reinterpret_cast<uint8_t*>(*handle_scope);
-    DCHECK_GE(static_cast<size_t>(reinterpret_cast<uint8_t*>(managed_sp) - sp8),
-              HandleScope::SizeOf(num_handle_scope_references_) + kJniCookieSize);
+    // Add space for cookie.
+    DCHECK_ALIGNED(managed_sp, sizeof(uintptr_t));
+    static_assert(sizeof(uintptr_t) >= sizeof(IRTSegmentState));
+    uint8_t* sp8 = reinterpret_cast<uint8_t*>(managed_sp) - sizeof(uintptr_t);
 
     // Layout stack arguments.
     sp8 = LayoutStackArgs(sp8);
@@ -1886,22 +1833,14 @@
     return GetHiddenArgSlot(reserved_area) + 1;
   }
 
-  uintptr_t PushHandle(mirror::Object* /* ptr */) override;
-
   // Add JNIEnv* and jobj/jclass before the shorty-derived elements.
   void WalkHeader(BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm) override
       REQUIRES_SHARED(Locks::mutator_lock_);
 
  private:
-  uint32_t num_handle_scope_references_;
   const bool critical_native_;
 };
 
-uintptr_t ComputeGenericJniFrameSize::PushHandle(mirror::Object* /* ptr */) {
-  num_handle_scope_references_++;
-  return reinterpret_cast<uintptr_t>(nullptr);
-}
-
 void ComputeGenericJniFrameSize::WalkHeader(
     BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm) {
   // First 2 parameters are always excluded for @CriticalNative.
@@ -1913,7 +1852,7 @@
   sm->AdvancePointer(nullptr);
 
   // Class object or this as first argument
-  sm->AdvanceHandleScope(reinterpret_cast<mirror::Object*>(0x12345678));
+  sm->AdvancePointer(nullptr);
 }
 
 // Class to push values to three separate regions. Used to fill the native call part. Adheres to
@@ -1952,11 +1891,6 @@
     cur_stack_arg_++;
   }
 
-  virtual uintptr_t PushHandle(mirror::Object*) REQUIRES_SHARED(Locks::mutator_lock_) {
-    LOG(FATAL) << "(Non-JNI) Native call does not use handles.";
-    UNREACHABLE();
-  }
-
  private:
   uintptr_t* cur_gpr_reg_;
   uint32_t* cur_fpr_reg_;
@@ -1975,14 +1909,14 @@
                               ArtMethod** managed_sp,
                               uintptr_t* reserved_area)
      : QuickArgumentVisitor(managed_sp, is_static, shorty, shorty_len),
-       jni_call_(nullptr, nullptr, nullptr, nullptr, critical_native),
-       sm_(&jni_call_) {
+       jni_call_(nullptr, nullptr, nullptr, critical_native),
+       sm_(&jni_call_),
+       current_vreg_(nullptr) {
     DCHECK_ALIGNED(managed_sp, kStackAlignment);
     DCHECK_ALIGNED(reserved_area, sizeof(uintptr_t));
 
     ComputeGenericJniFrameSize fsc(critical_native);
-    uintptr_t* out_args_sp =
-        fsc.ComputeLayout(self, managed_sp, shorty, shorty_len, &handle_scope_);
+    uintptr_t* out_args_sp = fsc.ComputeLayout(managed_sp, shorty, shorty_len);
 
     // Store hidden argument for @CriticalNative.
     uintptr_t* hidden_arg_slot = fsc.GetHiddenArgSlot(reserved_area);
@@ -1995,10 +1929,15 @@
     uintptr_t* out_args_sp_slot = fsc.GetOutArgsSpSlot(reserved_area);
     *out_args_sp_slot = reinterpret_cast<uintptr_t>(out_args_sp);
 
+    // Prepare vreg pointer for spilling references.
+    static constexpr size_t frame_size =
+        RuntimeCalleeSaveFrame::GetFrameSize(CalleeSaveType::kSaveRefsAndArgs);
+    current_vreg_ = reinterpret_cast<uint32_t*>(
+        reinterpret_cast<uint8_t*>(managed_sp) + frame_size + sizeof(ArtMethod*));
+
     jni_call_.Reset(fsc.GetStartGprRegs(reserved_area),
                     fsc.GetStartFprRegs(reserved_area),
-                    out_args_sp,
-                    handle_scope_);
+                    out_args_sp);
 
     // First 2 parameters are always excluded for CriticalNative methods.
     if (LIKELY(!critical_native)) {
@@ -2006,82 +1945,56 @@
       sm_.AdvancePointer(self->GetJniEnv());
 
       if (is_static) {
-        sm_.AdvanceHandleScope(method->GetDeclaringClass().Ptr());
+        // The `jclass` is a pointer to the method's declaring class.
+        // The declaring class must be marked.
+        auto* declaring_class = reinterpret_cast<mirror::CompressedReference<mirror::Class>*>(
+            method->GetDeclaringClassAddressWithoutBarrier());
+        if (kUseReadBarrier) {
+          ReadBarrierJni(declaring_class, self);
+        }
+        sm_.AdvancePointer(declaring_class);
       }  // else "this" reference is already handled by QuickArgumentVisitor.
     }
   }
 
   void Visit() REQUIRES_SHARED(Locks::mutator_lock_) override;
 
-  void FinalizeHandleScope(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  StackReference<mirror::Object>* GetFirstHandleScopeEntry() {
-    return handle_scope_->GetHandle(0).GetReference();
-  }
-
-  jobject GetFirstHandleScopeJObject() const REQUIRES_SHARED(Locks::mutator_lock_) {
-    return handle_scope_->GetHandle(0).ToJObject();
-  }
-
  private:
   // A class to fill a JNI call. Adds reference/handle-scope management to FillNativeCall.
   class FillJniCall final : public FillNativeCall {
    public:
-    FillJniCall(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args,
-                HandleScope* handle_scope, bool critical_native)
-      : FillNativeCall(gpr_regs, fpr_regs, stack_args),
-                       handle_scope_(handle_scope),
-        cur_entry_(0),
-        critical_native_(critical_native) {}
+    FillJniCall(uintptr_t* gpr_regs,
+                uint32_t* fpr_regs,
+                uintptr_t* stack_args,
+                bool critical_native)
+        : FillNativeCall(gpr_regs, fpr_regs, stack_args),
+          cur_entry_(0),
+          critical_native_(critical_native) {}
 
-    uintptr_t PushHandle(mirror::Object* ref) override REQUIRES_SHARED(Locks::mutator_lock_);
-
-    void Reset(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args, HandleScope* scope) {
+    void Reset(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args) {
       FillNativeCall::Reset(gpr_regs, fpr_regs, stack_args);
-      handle_scope_ = scope;
       cur_entry_ = 0U;
     }
 
-    void ResetRemainingScopeSlots() REQUIRES_SHARED(Locks::mutator_lock_) {
-      // Initialize padding entries.
-      size_t expected_slots = handle_scope_->NumberOfReferences();
-      while (cur_entry_ < expected_slots) {
-        handle_scope_->GetMutableHandle(cur_entry_++).Assign(nullptr);
-      }
-
-      if (!critical_native_) {
-        // Non-critical natives have at least the self class (jclass) or this (jobject).
-        DCHECK_NE(cur_entry_, 0U);
-      }
-    }
-
     bool CriticalNative() const {
       return critical_native_;
     }
 
    private:
-    HandleScope* handle_scope_;
     size_t cur_entry_;
     const bool critical_native_;
   };
 
-  HandleScope* handle_scope_;
   FillJniCall jni_call_;
-
   BuildNativeCallFrameStateMachine<FillJniCall> sm_;
 
+  // Pointer to the current vreg in caller's reserved out vreg area.
+  // Used for spilling reference arguments.
+  uint32_t* current_vreg_;
+
   DISALLOW_COPY_AND_ASSIGN(BuildGenericJniFrameVisitor);
 };
 
-uintptr_t BuildGenericJniFrameVisitor::FillJniCall::PushHandle(mirror::Object* ref) {
-  uintptr_t tmp;
-  MutableHandle<mirror::Object> h = handle_scope_->GetMutableHandle(cur_entry_);
-  h.Assign(ref);
-  tmp = reinterpret_cast<uintptr_t>(h.ToJObject());
-  cur_entry_++;
-  return tmp;
-}
-
 void BuildGenericJniFrameVisitor::Visit() {
   Primitive::Type type = GetParamPrimitiveType();
   switch (type) {
@@ -2093,6 +2006,7 @@
         long_arg = *reinterpret_cast<jlong*>(GetParamAddress());
       }
       sm_.AdvanceLong(long_arg);
+      current_vreg_ += 2u;
       break;
     }
     case Primitive::kPrimDouble: {
@@ -2104,16 +2018,22 @@
         double_arg = *reinterpret_cast<uint64_t*>(GetParamAddress());
       }
       sm_.AdvanceDouble(double_arg);
+      current_vreg_ += 2u;
       break;
     }
     case Primitive::kPrimNot: {
-      StackReference<mirror::Object>* stack_ref =
-          reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress());
-      sm_.AdvanceHandleScope(stack_ref->AsMirrorPtr());
+      mirror::Object* obj =
+          reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress())->AsMirrorPtr();
+      StackReference<mirror::Object>* spill_ref =
+          reinterpret_cast<StackReference<mirror::Object>*>(current_vreg_);
+      spill_ref->Assign(obj);
+      sm_.AdvancePointer(obj != nullptr ? spill_ref : nullptr);
+      current_vreg_ += 1u;
       break;
     }
     case Primitive::kPrimFloat:
       sm_.AdvanceFloat(*reinterpret_cast<float*>(GetParamAddress()));
+      current_vreg_ += 1u;
       break;
     case Primitive::kPrimBoolean:  // Fall-through.
     case Primitive::kPrimByte:     // Fall-through.
@@ -2121,6 +2041,7 @@
     case Primitive::kPrimShort:    // Fall-through.
     case Primitive::kPrimInt:      // Fall-through.
       sm_.AdvanceInt(*reinterpret_cast<jint*>(GetParamAddress()));
+      current_vreg_ += 1u;
       break;
     case Primitive::kPrimVoid:
       LOG(FATAL) << "UNREACHABLE";
@@ -2128,15 +2049,6 @@
   }
 }
 
-void BuildGenericJniFrameVisitor::FinalizeHandleScope(Thread* self) {
-  // Clear out rest of the scope.
-  jni_call_.ResetRemainingScopeSlots();
-  if (!jni_call_.CriticalNative()) {
-    // Install HandleScope.
-    self->PushHandleScope(handle_scope_);
-  }
-}
-
 /*
  * Initializes the reserved area assumed to be directly below `managed_sp` for a native call:
  *
@@ -2178,8 +2090,6 @@
   {
     ScopedAssertNoThreadSuspension sants(__FUNCTION__);
     visitor.VisitArguments();
-    // FinalizeHandleScope pushes the handle scope on the thread.
-    visitor.FinalizeHandleScope(self);
   }
 
   // Fix up managed-stack things in Thread. After this we can walk the stack.
@@ -2204,7 +2114,6 @@
       Handle<mirror::Class> h_class(hs.NewHandle(declaring_class));
       if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
         DCHECK(Thread::Current()->IsExceptionPending()) << called->PrettyMethod();
-        self->PopHandleScope();
         return nullptr;  // Report error.
       }
     }
@@ -2217,9 +2126,9 @@
     // Start JNI, save the cookie.
     if (called->IsSynchronized()) {
       DCHECK(normal_native) << " @FastNative and synchronize is not supported";
-      cookie = JniMethodStartSynchronized(visitor.GetFirstHandleScopeJObject(), self);
+      jobject lock = GetGenericJniSynchronizationObject(self, called);
+      cookie = JniMethodStartSynchronized(lock, self);
       if (self->IsExceptionPending()) {
-        self->PopHandleScope();
         return nullptr;  // Report error.
       }
     } else {
@@ -2272,14 +2181,6 @@
   uint32_t* sp32 = reinterpret_cast<uint32_t*>(sp);
   ArtMethod* called = *sp;
   uint32_t cookie = *(sp32 - 1);
-  if (kIsDebugBuild && !called->IsCriticalNative()) {
-    BaseHandleScope* handle_scope = self->GetTopHandleScope();
-    DCHECK(handle_scope != nullptr);
-    DCHECK(!handle_scope->IsVariableSized());
-    // Note: We do not hold mutator lock here for normal JNI, so we cannot use the method's shorty
-    // to determine the number of references. Instead rely on the value from the HandleScope.
-    DCHECK_EQ(handle_scope, GetGenericJniHandleScope(sp, handle_scope->NumberOfReferences()));
-  }
   return GenericJniMethodEnd(self, cookie, result, result_f, called);
 }
 
@@ -2384,21 +2285,6 @@
   return artInvokeCommon<kVirtual, true>(method_idx, this_object, self, sp);
 }
 
-// Helper function for art_quick_imt_conflict_trampoline to look up the interface method.
-extern "C" ArtMethod* artLookupResolvedMethod(uint32_t method_index, ArtMethod* referrer)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  ScopedAssertNoThreadSuspension ants(__FUNCTION__);
-  DCHECK(!referrer->IsProxyMethod());
-  ArtMethod* result = Runtime::Current()->GetClassLinker()->LookupResolvedMethod(
-      method_index, referrer->GetDexCache(), referrer->GetClassLoader());
-  DCHECK(result == nullptr ||
-         result->GetDeclaringClass()->IsInterface() ||
-         result->GetDeclaringClass() ==
-             WellKnownClasses::ToClass(WellKnownClasses::java_lang_Object))
-      << result->PrettyMethod();
-  return result;
-}
-
 // Determine target of interface dispatch. The interface method and this object are known non-null.
 // The interface method is the method returned by the dex cache in the conflict trampoline.
 extern "C" TwoWordReturn artInvokeInterfaceTrampoline(ArtMethod* interface_method,
@@ -2407,17 +2293,15 @@
                                                       ArtMethod** sp)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  StackHandleScope<2> hs(self);
-  Handle<mirror::Object> this_object = hs.NewHandle(raw_this_object);
-  Handle<mirror::Class> cls = hs.NewHandle(this_object->GetClass());
 
-  ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
-  ArtMethod* method = nullptr;
-  ImTable* imt = cls->GetImt(kRuntimePointerSize);
-
-  if (UNLIKELY(interface_method == nullptr)) {
+  Runtime* runtime = Runtime::Current();
+  bool resolve_method = ((interface_method == nullptr) || interface_method->IsRuntimeMethod());
+  if (UNLIKELY(resolve_method)) {
     // The interface method is unresolved, so resolve it in the dex file of the caller.
     // Fetch the dex_method_idx of the target interface method from the caller.
+    StackHandleScope<1> hs(self);
+    Handle<mirror::Object> this_object = hs.NewHandle(raw_this_object);
+    ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
     uint32_t dex_method_idx;
     uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
     const Instruction& instr = caller_method->DexInstructions().InstructionAt(dex_pc);
@@ -2441,7 +2325,7 @@
       ScopedObjectAccessUnchecked soa(self->GetJniEnv());
       RememberForGcArgumentVisitor visitor(sp, false, shorty, shorty_len, &soa);
       visitor.VisitArguments();
-      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+      ClassLinker* class_linker = runtime->GetClassLinker();
       interface_method = class_linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
           self, dex_method_idx, caller_method, kInterface);
       visitor.FixupReferences();
@@ -2451,54 +2335,59 @@
       CHECK(self->IsExceptionPending());
       return GetTwoWordFailureValue();  // Failure.
     }
+    MaybeUpdateBssMethodEntry(interface_method, MethodReference(&dex_file, dex_method_idx));
+
+    // Refresh `raw_this_object` which may have changed after resolution.
+    raw_this_object = this_object.Get();
   }
 
   // The compiler and interpreter make sure the conflict trampoline is never
   // called on a method that resolves to j.l.Object.
-  CHECK(!interface_method->GetDeclaringClass()->IsObjectClass());
-  CHECK(interface_method->GetDeclaringClass()->IsInterface());
-
+  DCHECK(!interface_method->GetDeclaringClass()->IsObjectClass());
+  DCHECK(interface_method->GetDeclaringClass()->IsInterface());
   DCHECK(!interface_method->IsRuntimeMethod());
-  // Look whether we have a match in the ImtConflictTable.
+  DCHECK(!interface_method->IsCopied());
+
+  ObjPtr<mirror::Object> obj_this = raw_this_object;
+  ObjPtr<mirror::Class> cls = obj_this->GetClass();
   uint32_t imt_index = interface_method->GetImtIndex();
+  ImTable* imt = cls->GetImt(kRuntimePointerSize);
   ArtMethod* conflict_method = imt->Get(imt_index, kRuntimePointerSize);
-  if (LIKELY(conflict_method->IsRuntimeMethod())) {
+  DCHECK(conflict_method->IsRuntimeMethod());
+
+  if (UNLIKELY(resolve_method)) {
+    // Now that we know the interface method, look it up in the conflict table.
     ImtConflictTable* current_table = conflict_method->GetImtConflictTable(kRuntimePointerSize);
     DCHECK(current_table != nullptr);
-    method = current_table->Lookup(interface_method, kRuntimePointerSize);
-  } else {
-    // It seems we aren't really a conflict method!
-    if (kIsDebugBuild) {
-      ArtMethod* m = cls->FindVirtualMethodForInterface(interface_method, kRuntimePointerSize);
-      CHECK_EQ(conflict_method, m)
-          << interface_method->PrettyMethod() << " / " << conflict_method->PrettyMethod() << " / "
-          << " / " << ArtMethod::PrettyMethod(m) << " / " << cls->PrettyClass();
+    ArtMethod* method = current_table->Lookup(interface_method, kRuntimePointerSize);
+    if (method != nullptr) {
+      return GetTwoWordSuccessValue(
+          reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode()),
+          reinterpret_cast<uintptr_t>(method));
     }
-    method = conflict_method;
-  }
-  if (method != nullptr) {
-    return GetTwoWordSuccessValue(
-        reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode()),
-        reinterpret_cast<uintptr_t>(method));
+    // Interface method is not in the conflict table. Continue looking up in the
+    // iftable.
   }
 
-  // No match, use the IfTable.
-  method = cls->FindVirtualMethodForInterface(interface_method, kRuntimePointerSize);
+  ArtMethod* method = cls->FindVirtualMethodForInterface(interface_method, kRuntimePointerSize);
   if (UNLIKELY(method == nullptr)) {
+    ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
     ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(
-        interface_method, this_object.Get(), caller_method);
-    return GetTwoWordFailureValue();  // Failure.
+        interface_method, obj_this.Ptr(), caller_method);
+    return GetTwoWordFailureValue();
   }
 
   // We arrive here if we have found an implementation, and it is not in the ImtConflictTable.
   // We create a new table with the new pair { interface_method, method }.
-  DCHECK(conflict_method->IsRuntimeMethod());
-  ArtMethod* new_conflict_method = Runtime::Current()->GetClassLinker()->AddMethodToConflictTable(
-      cls.Get(),
+
+  // Classes in the boot image should never need to update conflict methods in
+  // their IMT.
+  CHECK(!runtime->GetHeap()->ObjectIsInBootImageSpace(cls.Ptr())) << cls->PrettyClass();
+  ArtMethod* new_conflict_method = runtime->GetClassLinker()->AddMethodToConflictTable(
+      cls.Ptr(),
       conflict_method,
       interface_method,
-      method,
-      /*force_new_conflict_method=*/false);
+      method);
   if (new_conflict_method != conflict_method) {
     // Update the IMT if we create a new conflict method. No fence needed here, as the
     // data is consistent.
diff --git a/runtime/entrypoints/runtime_asm_entrypoints.h b/runtime/entrypoints/runtime_asm_entrypoints.h
index 9f47034..d2096ec 100644
--- a/runtime/entrypoints/runtime_asm_entrypoints.h
+++ b/runtime/entrypoints/runtime_asm_entrypoints.h
@@ -19,17 +19,14 @@
 
 #include "deoptimization_kind.h"
 
+#include "base/macros.h"
 #include "jni.h"
 
-namespace art {
+namespace art HIDDEN {
 
 class ArtMethod;
 class Thread;
 
-#ifndef BUILDING_LIBART
-#error "File and symbols only for use within libart."
-#endif
-
 extern "C" void* art_jni_dlsym_lookup_stub(JNIEnv*, jobject);
 static inline const void* GetJniDlsymLookupStub() {
   return reinterpret_cast<const void*>(art_jni_dlsym_lookup_stub);
diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index 52c4142..f6bbd22 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -64,8 +64,7 @@
   void CheckThreadOffsets() {
     CHECKED(OFFSETOF_MEMBER(Thread, tls32_.state_and_flags) == 0, thread_flags_at_zero);
     EXPECT_OFFSET_DIFFP(Thread, tls32_, state_and_flags, suspend_count, 4);
-    EXPECT_OFFSET_DIFFP(Thread, tls32_, suspend_count, debug_suspend_count, 4);
-    EXPECT_OFFSET_DIFFP(Thread, tls32_, debug_suspend_count, thin_lock_thread_id, 4);
+    EXPECT_OFFSET_DIFFP(Thread, tls32_, suspend_count, thin_lock_thread_id, 4);
     EXPECT_OFFSET_DIFFP(Thread, tls32_, thin_lock_thread_id, tid, 4);
     EXPECT_OFFSET_DIFFP(Thread, tls32_, tid, daemon, 4);
     EXPECT_OFFSET_DIFFP(Thread, tls32_, daemon, throwing_OutOfMemoryError, 4);
diff --git a/runtime/exec_utils.cc b/runtime/exec_utils.cc
index db1baa7..463d458 100644
--- a/runtime/exec_utils.cc
+++ b/runtime/exec_utils.cc
@@ -30,18 +30,22 @@
 
 using android::base::StringPrintf;
 
-int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg) {
-  const std::string command_line(android::base::Join(arg_vector, ' '));
-  CHECK_GE(arg_vector.size(), 1U) << command_line;
+namespace {
 
+std::string ToCommandLine(const std::vector<std::string>& args) {
+  return android::base::Join(args, ' ');
+}
+
+// Fork and execute a command specified in a subprocess.
+// If there is a runtime (Runtime::Current != nullptr) then the subprocess is created with the
+// same environment that existed when the runtime was started.
+// Returns the process id of the child process on success, -1 otherwise.
+pid_t ExecWithoutWait(std::vector<std::string>& arg_vector) {
   // Convert the args to char pointers.
   const char* program = arg_vector[0].c_str();
   std::vector<char*> args;
-  for (size_t i = 0; i < arg_vector.size(); ++i) {
-    const std::string& arg = arg_vector[i];
-    char* arg_str = const_cast<char*>(arg.c_str());
-    CHECK(arg_str != nullptr) << i;
-    args.push_back(arg_str);
+  for (const auto& arg : arg_vector) {
+    args.push_back(const_cast<char*>(arg.c_str()));
   }
   args.push_back(nullptr);
 
@@ -61,38 +65,110 @@
     } else {
       execve(program, &args[0], envp);
     }
-    PLOG(ERROR) << "Failed to execve(" << command_line << ")";
+    PLOG(ERROR) << "Failed to execve(" << ToCommandLine(arg_vector) << ")";
     // _exit to avoid atexit handlers in child.
     _exit(1);
   } else {
-    if (pid == -1) {
-      *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
-                                command_line.c_str(), strerror(errno));
-      return -1;
-    }
-
-    // wait for subprocess to finish
-    int status = -1;
-    pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
-    if (got_pid != pid) {
-      *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
-                                "wanted %d, got %d: %s",
-                                command_line.c_str(), pid, got_pid, strerror(errno));
-      return -1;
-    }
-    if (WIFEXITED(status)) {
-      return WEXITSTATUS(status);
-    }
-    return -1;
+    return pid;
   }
 }
 
+}  // namespace
+
+int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg) {
+  pid_t pid = ExecWithoutWait(arg_vector);
+  if (pid == -1) {
+    *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
+                              ToCommandLine(arg_vector).c_str(), strerror(errno));
+    return -1;
+  }
+
+  // wait for subprocess to finish
+  int status = -1;
+  pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+  if (got_pid != pid) {
+    *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
+                              "wanted %d, got %d: %s",
+                              ToCommandLine(arg_vector).c_str(), pid, got_pid, strerror(errno));
+    return -1;
+  }
+  if (WIFEXITED(status)) {
+    return WEXITSTATUS(status);
+  }
+  return -1;
+}
+
+int ExecAndReturnCode(std::vector<std::string>& arg_vector,
+                      time_t timeout_secs,
+                      bool* timed_out,
+                      std::string* error_msg) {
+  *timed_out = false;
+
+  // Start subprocess.
+  pid_t pid = ExecWithoutWait(arg_vector);
+  if (pid == -1) {
+    *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
+                              ToCommandLine(arg_vector).c_str(), strerror(errno));
+    return -1;
+  }
+
+  // Add SIGCHLD to the signal set.
+  sigset_t child_mask, original_mask;
+  sigemptyset(&child_mask);
+  sigaddset(&child_mask, SIGCHLD);
+  if (sigprocmask(SIG_BLOCK, &child_mask, &original_mask) == -1) {
+    *error_msg = StringPrintf("Failed to set sigprocmask(): %s", strerror(errno));
+    return -1;
+  }
+
+  // Wait for a SIGCHLD notification.
+  errno = 0;
+  timespec ts = {timeout_secs, 0};
+  int wait_result = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, nullptr, &ts));
+  int wait_errno = errno;
+
+  // Restore the original signal set.
+  if (sigprocmask(SIG_SETMASK, &original_mask, nullptr) == -1) {
+    *error_msg = StringPrintf("Fail to restore sigprocmask(): %s", strerror(errno));
+    if (wait_result == 0) {
+      return -1;
+    }
+  }
+
+  // Having restored the signal set, see if we need to terminate the subprocess.
+  if (wait_result == -1) {
+    if (wait_errno == EAGAIN) {
+      *error_msg = "Timed out.";
+      *timed_out = true;
+    } else {
+      *error_msg = StringPrintf("Failed to sigtimedwait(): %s", strerror(errno));
+    }
+    if (kill(pid, SIGKILL) != 0) {
+      PLOG(ERROR) << "Failed to kill() subprocess: ";
+    }
+  }
+
+  // Wait for subprocess to finish.
+  int status = -1;
+  pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+  if (got_pid != pid) {
+    *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
+                              "wanted %d, got %d: %s",
+                              ToCommandLine(arg_vector).c_str(), pid, got_pid, strerror(errno));
+    return -1;
+  }
+  if (WIFEXITED(status)) {
+    return WEXITSTATUS(status);
+  }
+  return -1;
+}
+
+
 bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) {
   int status = ExecAndReturnCode(arg_vector, error_msg);
   if (status != 0) {
-    const std::string command_line(android::base::Join(arg_vector, ' '));
     *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
-                              command_line.c_str());
+                              ToCommandLine(arg_vector).c_str());
     return false;
   }
   return true;
diff --git a/runtime/exec_utils.h b/runtime/exec_utils.h
index 093f7b8..5e22639 100644
--- a/runtime/exec_utils.h
+++ b/runtime/exec_utils.h
@@ -23,11 +23,19 @@
 namespace art {
 
 // Wrapper on fork/execv to run a command in a subprocess.
-// Both of these spawn child processes using the environment as it was set when the single instance
+// These spawn child processes using the environment as it was set when the single instance
 // of the runtime (Runtime::Current()) was started.  If no instance of the runtime was started, it
 // will use the current environment settings.
-bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg);
-int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg);
+
+bool Exec(std::vector<std::string>& arg_vector, /*out*/ std::string* error_msg);
+int ExecAndReturnCode(std::vector<std::string>& arg_vector, /*out*/ std::string* error_msg);
+
+// Execute the command specified in `argv_vector` in a subprocess with a timeout.
+// Returns the process exit code on success, -1 otherwise.
+int ExecAndReturnCode(std::vector<std::string>& arg_vector,
+                      time_t timeout_secs,
+                      /*out*/ bool* timed_out,
+                      /*out*/ std::string* error_msg);
 
 }  // namespace art
 
diff --git a/runtime/exec_utils_test.cc b/runtime/exec_utils_test.cc
index c138ce3..dc789aa 100644
--- a/runtime/exec_utils_test.cc
+++ b/runtime/exec_utils_test.cc
@@ -16,6 +16,7 @@
 
 #include "exec_utils.h"
 
+#include "android-base/stringprintf.h"
 #include "base/file_utils.h"
 #include "base/memory_tool.h"
 #include "common_runtime_test.h"
@@ -102,4 +103,35 @@
   EXPECT_EQ(setenv(kDeletedVariable, save_value, kOverwrite), 0);
 }
 
+static std::vector<std::string> SleepCommand(int sleep_seconds) {
+  std::vector<std::string> command;
+  if (kIsTargetBuild) {
+    command.push_back(GetAndroidRoot() + "/bin/sleep");
+  } else {
+    command.push_back("/bin/sleep");
+  }
+  command.push_back(android::base::StringPrintf("%d", sleep_seconds));
+  return command;
+}
+
+TEST_F(ExecUtilsTest, ExecTimeout) {
+  static constexpr int kSleepSeconds = 5;
+  static constexpr int kWaitSeconds = 1;
+  std::vector<std::string> command = SleepCommand(kSleepSeconds);
+  std::string error_msg;
+  bool timed_out;
+  ASSERT_EQ(ExecAndReturnCode(command, kWaitSeconds, &timed_out, &error_msg), -1);
+  EXPECT_TRUE(timed_out);
+}
+
+TEST_F(ExecUtilsTest, ExecNoTimeout) {
+  static constexpr int kSleepSeconds = 1;
+  static constexpr int kWaitSeconds = 5;
+  std::vector<std::string> command = SleepCommand(kSleepSeconds);
+  std::string error_msg;
+  bool timed_out;
+  ASSERT_EQ(ExecAndReturnCode(command, kWaitSeconds, &timed_out, &error_msg), 0);
+  EXPECT_FALSE(timed_out);
+}
+
 }  // namespace art
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index cae7deb..51ac2c3 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -329,6 +329,11 @@
 
   const OatQuickMethodHeader* method_header = method_obj->GetOatQuickMethodHeader(return_pc);
 
+  if (method_header == nullptr) {
+    VLOG(signals) << "no compiled code";
+    return false;
+  }
+
   // We can be certain that this is a method now.  Check if we have a GC map
   // at the return PC address.
   if (true || kIsDebugBuild) {
diff --git a/runtime/gc/accounting/atomic_stack.h b/runtime/gc/accounting/atomic_stack.h
index 9431f80..4486798 100644
--- a/runtime/gc/accounting/atomic_stack.h
+++ b/runtime/gc/accounting/atomic_stack.h
@@ -113,7 +113,7 @@
     *start_address = begin_ + index;
     *end_address = begin_ + new_index;
     if (kIsDebugBuild) {
-      // Sanity check that the memory is zero.
+      // Check that the memory is zero.
       for (int32_t i = index; i < new_index; ++i) {
         DCHECK_EQ(begin_[i].AsMirrorPtr(), static_cast<T*>(nullptr))
             << "i=" << i << " index=" << index << " new_index=" << new_index;
diff --git a/runtime/gc/accounting/card_table-inl.h b/runtime/gc/accounting/card_table-inl.h
index df50682..cc24a1a 100644
--- a/runtime/gc/accounting/card_table-inl.h
+++ b/runtime/gc/accounting/card_table-inl.h
@@ -77,48 +77,53 @@
     ++card_cur;
   }
 
-  uint8_t* aligned_end = card_end -
-      (reinterpret_cast<uintptr_t>(card_end) & (sizeof(uintptr_t) - 1));
+  if (card_cur < card_end) {
+    DCHECK_ALIGNED(card_cur, sizeof(intptr_t));
+    uint8_t* aligned_end = card_end -
+        (reinterpret_cast<uintptr_t>(card_end) & (sizeof(uintptr_t) - 1));
+    DCHECK_LE(card_cur, aligned_end);
 
-  uintptr_t* word_end = reinterpret_cast<uintptr_t*>(aligned_end);
-  for (uintptr_t* word_cur = reinterpret_cast<uintptr_t*>(card_cur); word_cur < word_end;
-      ++word_cur) {
-    while (LIKELY(*word_cur == 0)) {
-      ++word_cur;
-      if (UNLIKELY(word_cur >= word_end)) {
-        goto exit_for;
+    uintptr_t* word_end = reinterpret_cast<uintptr_t*>(aligned_end);
+    for (uintptr_t* word_cur = reinterpret_cast<uintptr_t*>(card_cur); word_cur < word_end;
+        ++word_cur) {
+      while (LIKELY(*word_cur == 0)) {
+        ++word_cur;
+        if (UNLIKELY(word_cur >= word_end)) {
+          goto exit_for;
+        }
+      }
+
+      // Find the first dirty card.
+      uintptr_t start_word = *word_cur;
+      uintptr_t start =
+          reinterpret_cast<uintptr_t>(AddrFromCard(reinterpret_cast<uint8_t*>(word_cur)));
+      // TODO: Investigate if processing continuous runs of dirty cards with
+      // a single bitmap visit is more efficient.
+      for (size_t i = 0; i < sizeof(uintptr_t); ++i) {
+        if (static_cast<uint8_t>(start_word) >= minimum_age) {
+          auto* card = reinterpret_cast<uint8_t*>(word_cur) + i;
+          DCHECK(*card == static_cast<uint8_t>(start_word) || *card == kCardDirty)
+              << "card " << static_cast<size_t>(*card) << " intptr_t " << (start_word & 0xFF);
+          bitmap->VisitMarkedRange(start, start + kCardSize, visitor);
+          ++cards_scanned;
+        }
+        start_word >>= 8;
+        start += kCardSize;
       }
     }
+    exit_for:
 
-    // Find the first dirty card.
-    uintptr_t start_word = *word_cur;
-    uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(reinterpret_cast<uint8_t*>(word_cur)));
-    // TODO: Investigate if processing continuous runs of dirty cards with a single bitmap visit is
-    // more efficient.
-    for (size_t i = 0; i < sizeof(uintptr_t); ++i) {
-      if (static_cast<uint8_t>(start_word) >= minimum_age) {
-        auto* card = reinterpret_cast<uint8_t*>(word_cur) + i;
-        DCHECK(*card == static_cast<uint8_t>(start_word) || *card == kCardDirty)
-            << "card " << static_cast<size_t>(*card) << " intptr_t " << (start_word & 0xFF);
+    // Handle any unaligned cards at the end.
+    card_cur = reinterpret_cast<uint8_t*>(word_end);
+    while (card_cur < card_end) {
+      if (*card_cur >= minimum_age) {
+        uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(card_cur));
         bitmap->VisitMarkedRange(start, start + kCardSize, visitor);
         ++cards_scanned;
       }
-      start_word >>= 8;
-      start += kCardSize;
+      ++card_cur;
     }
   }
-  exit_for:
-
-  // Handle any unaligned cards at the end.
-  card_cur = reinterpret_cast<uint8_t*>(word_end);
-  while (card_cur < card_end) {
-    if (*card_cur >= minimum_age) {
-      uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(card_cur));
-      bitmap->VisitMarkedRange(start, start + kCardSize, visitor);
-      ++cards_scanned;
-    }
-    ++card_cur;
-  }
 
   if (kClearCard) {
     ClearCardRange(scan_begin, scan_end);
@@ -215,7 +220,7 @@
 
 inline uint8_t* CardTable::CardFromAddr(const void *addr) const {
   uint8_t *card_addr = biased_begin_ + (reinterpret_cast<uintptr_t>(addr) >> kCardShift);
-  // Sanity check the caller was asking for address covered by the card table
+  // Check that the caller was asking for an address covered by the card table.
   DCHECK(IsValidCard(card_addr)) << "addr: " << addr
       << " card_addr: " << reinterpret_cast<void*>(card_addr);
   return card_addr;
diff --git a/runtime/gc/accounting/mod_union_table.h b/runtime/gc/accounting/mod_union_table.h
index 011e95c..5f6fd3e 100644
--- a/runtime/gc/accounting/mod_union_table.h
+++ b/runtime/gc/accounting/mod_union_table.h
@@ -82,8 +82,8 @@
   // Visit all of the objects that may contain references to other spaces.
   virtual void VisitObjects(ObjectCallback callback, void* arg) = 0;
 
-  // Verification, sanity checks that we don't have clean cards which conflict with out cached data
-  // for said cards. Exclusive lock is required since verify sometimes uses
+  // Verification: consistency checks that we don't have clean cards which conflict with out
+  // cached data for said cards. Exclusive lock is required since verify sometimes uses
   // SpaceBitmap::VisitMarkedRange and VisitMarkedRange can't know if the callback will modify the
   // bitmap or not.
   virtual void Verify() REQUIRES(Locks::heap_bitmap_lock_) = 0;
diff --git a/runtime/gc/accounting/mod_union_table_test.cc b/runtime/gc/accounting/mod_union_table_test.cc
index e66a174..1cd719d 100644
--- a/runtime/gc/accounting/mod_union_table_test.cc
+++ b/runtime/gc/accounting/mod_union_table_test.cc
@@ -17,7 +17,7 @@
 #include "mod_union_table-inl.h"
 
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_runtime_test.h"
 #include "gc/space/space-inl.h"
 #include "mirror/array-alloc-inl.h"
@@ -248,7 +248,7 @@
       ptr += CardTable::kCardSize) {
     ASSERT_TRUE(table->ContainsCardFor(reinterpret_cast<uintptr_t>(ptr)));
   }
-  // Visit again and make sure the cards got cleared back to their sane state.
+  // Visit again and make sure the cards got cleared back to their expected state.
   std::set<mirror::Object*> visited_after;
   CollectVisitedVisitor collector_after(&visited_after);
   table->UpdateAndMarkReferences(&collector_after);
diff --git a/runtime/gc/allocator/rosalloc.cc b/runtime/gc/allocator/rosalloc.cc
index f1572cd..2698874 100644
--- a/runtime/gc/allocator/rosalloc.cc
+++ b/runtime/gc/allocator/rosalloc.cc
@@ -2069,7 +2069,7 @@
   return reclaimed_bytes;
 }
 
-void RosAlloc::LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) {
+bool RosAlloc::LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) {
   Thread* self = Thread::Current();
   size_t largest_continuous_free_pages = 0;
   WriterMutexLock wmu(self, bulk_free_lock_);
@@ -2098,7 +2098,9 @@
        << ", space footprint " << footprint_ << " bytes"
        << ", space max capacity " << max_capacity_ << " bytes"
        << ")" << std::endl;
+    return true;
   }
+  return false;
 }
 
 void RosAlloc::DumpStats(std::ostream& os) {
diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h
index c4bc76f..a5bfd8f 100644
--- a/runtime/gc/allocator/rosalloc.h
+++ b/runtime/gc/allocator/rosalloc.h
@@ -929,18 +929,18 @@
   void Verify() REQUIRES(Locks::mutator_lock_, !Locks::thread_list_lock_, !bulk_free_lock_,
                          !lock_);
 
-  void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes)
+  bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes)
       REQUIRES(!bulk_free_lock_, !lock_);
 
   void DumpStats(std::ostream& os)
       REQUIRES(Locks::mutator_lock_) REQUIRES(!lock_) REQUIRES(!bulk_free_lock_);
 
  private:
-  friend std::ostream& operator<<(std::ostream& os, const RosAlloc::PageMapKind& rhs);
+  friend std::ostream& operator<<(std::ostream& os, RosAlloc::PageMapKind rhs);
 
   DISALLOW_COPY_AND_ASSIGN(RosAlloc);
 };
-std::ostream& operator<<(std::ostream& os, const RosAlloc::PageMapKind& rhs);
+std::ostream& operator<<(std::ostream& os, RosAlloc::PageMapKind rhs);
 
 // Callback from rosalloc when it needs to increase the footprint. Must be implemented somewhere
 // else (currently rosalloc_space.cc).
diff --git a/runtime/gc/allocator_type.h b/runtime/gc/allocator_type.h
index cd9f5d4..fb29837 100644
--- a/runtime/gc/allocator_type.h
+++ b/runtime/gc/allocator_type.h
@@ -37,7 +37,7 @@
   kAllocatorTypeRegion,  // Use CAS-based contiguous bump-pointer allocation within a region. (*)
   kAllocatorTypeRegionTLAB,  // Use region pieces as TLABs. Default for most small objects. (*)
 };
-std::ostream& operator<<(std::ostream& os, const AllocatorType& rhs);
+std::ostream& operator<<(std::ostream& os, AllocatorType rhs);
 
 inline constexpr bool IsTLABAllocator(AllocatorType allocator) {
   return allocator == kAllocatorTypeTLAB || allocator == kAllocatorTypeRegionTLAB;
diff --git a/runtime/gc/collector/concurrent_copying-inl.h b/runtime/gc/collector/concurrent_copying-inl.h
index 2de7910..76bc812 100644
--- a/runtime/gc/collector/concurrent_copying-inl.h
+++ b/runtime/gc/collector/concurrent_copying-inl.h
@@ -224,8 +224,7 @@
   return ret;
 }
 
-inline mirror::Object* ConcurrentCopying::GetFwdPtr(mirror::Object* from_ref) {
-  DCHECK(region_space_->IsInFromSpace(from_ref));
+inline mirror::Object* ConcurrentCopying::GetFwdPtrUnchecked(mirror::Object* from_ref) {
   LockWord lw = from_ref->GetLockWord(false);
   if (lw.GetState() == LockWord::kForwardingAddress) {
     mirror::Object* fwd_ptr = reinterpret_cast<mirror::Object*>(lw.ForwardingAddress());
@@ -236,6 +235,11 @@
   }
 }
 
+inline mirror::Object* ConcurrentCopying::GetFwdPtr(mirror::Object* from_ref) {
+  DCHECK(region_space_->IsInFromSpace(from_ref));
+  return GetFwdPtrUnchecked(from_ref);
+}
+
 inline bool ConcurrentCopying::IsMarkedInUnevacFromSpace(mirror::Object* from_ref) {
   // Use load-acquire on the read barrier pointer to ensure that we never see a black (non-gray)
   // read barrier state with an unmarked bit due to reordering.
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 1f50c27..538d7be 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -24,7 +24,7 @@
 #include "base/quasi_atomic.h"
 #include "base/stl_util.h"
 #include "base/systrace.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "debugger.h"
 #include "gc/accounting/atomic_stack.h"
 #include "gc/accounting/heap_bitmap-inl.h"
@@ -102,6 +102,8 @@
       copied_live_bytes_ratio_sum_(0.f),
       gc_count_(0),
       reclaimed_bytes_ratio_sum_(0.f),
+      cumulative_bytes_moved_(0),
+      cumulative_objects_moved_(0),
       skipped_blocks_lock_("concurrent copying bytes blocks lock", kMarkSweepMarkStackLock),
       measure_read_barrier_slow_path_(measure_read_barrier_slow_path),
       mark_from_read_barrier_measurements_(false),
@@ -151,6 +153,25 @@
     CHECK(sweep_array_free_buffer_mem_map_.IsValid())
         << "Couldn't allocate sweep array free buffer: " << error_msg;
   }
+  // Return type of these functions are different. And even though the base class
+  // is same, using ternary operator complains.
+  metrics::ArtMetrics* metrics = GetMetrics();
+  are_metrics_initialized_ = true;
+  if (young_gen_) {
+    gc_time_histogram_ = metrics->YoungGcCollectionTime();
+    metrics_gc_count_ = metrics->YoungGcCount();
+    gc_throughput_histogram_ = metrics->YoungGcThroughput();
+    gc_tracing_throughput_hist_ = metrics->YoungGcTracingThroughput();
+    gc_throughput_avg_ = metrics->YoungGcThroughputAvg();
+    gc_tracing_throughput_avg_ = metrics->YoungGcTracingThroughputAvg();
+  } else {
+    gc_time_histogram_ = metrics->FullGcCollectionTime();
+    metrics_gc_count_ = metrics->FullGcCount();
+    gc_throughput_histogram_ = metrics->FullGcThroughput();
+    gc_tracing_throughput_hist_ = metrics->FullGcTracingThroughput();
+    gc_throughput_avg_ = metrics->FullGcThroughputAvg();
+    gc_tracing_throughput_avg_ = metrics->FullGcTracingThroughputAvg();
+  }
 }
 
 void ConcurrentCopying::MarkHeapReference(mirror::HeapReference<mirror::Object>* field,
@@ -389,6 +410,7 @@
   objects_moved_.store(0, std::memory_order_relaxed);
   bytes_moved_gc_thread_ = 0;
   objects_moved_gc_thread_ = 0;
+  bytes_scanned_ = 0;
   GcCause gc_cause = GetCurrentIteration()->GetGcCause();
 
   force_evacuate_all_ = false;
@@ -561,7 +583,7 @@
       }
     }
     // May be null during runtime creation, in this case leave java_lang_Object null.
-    // This is safe since single threaded behavior should mean FillDummyObject does not
+    // This is safe since single threaded behavior should mean FillWithFakeObject does not
     // happen when java_lang_Object_ is null.
     if (WellKnownClasses::java_lang_Object != nullptr) {
       cc->java_lang_Object_ = down_cast<mirror::Class*>(cc->Mark(thread,
@@ -946,43 +968,6 @@
   Thread* const self_;
 };
 
-void ConcurrentCopying::RemoveThreadMarkStackMapping(Thread* thread,
-                                                     accounting::ObjectStack* tl_mark_stack) {
-  CHECK(tl_mark_stack != nullptr);
-  auto it = thread_mark_stack_map_.find(thread);
-  CHECK(it != thread_mark_stack_map_.end());
-  CHECK(it->second == tl_mark_stack);
-  thread_mark_stack_map_.erase(it);
-}
-
-void ConcurrentCopying::AssertEmptyThreadMarkStackMap() {
-  std::ostringstream oss;
-  auto capture_mappings = [this, &oss] () REQUIRES(mark_stack_lock_) {
-    for (const auto & iter : thread_mark_stack_map_) {
-      oss << "thread:" << iter.first << " mark-stack:" << iter.second << "\n";
-    }
-    return oss.str();
-  };
-  CHECK(thread_mark_stack_map_.empty()) << "thread_mark_stack_map not empty. size:"
-                                        << thread_mark_stack_map_.size()
-                                        << "Mappings:\n"
-                                        << capture_mappings()
-                                        << "pooled_mark_stacks size:"
-                                        << pooled_mark_stacks_.size();
-}
-
-void ConcurrentCopying::AssertNoThreadMarkStackMapping(Thread* thread) {
-  MutexLock mu(Thread::Current(), mark_stack_lock_);
-  CHECK(thread_mark_stack_map_.find(thread) == thread_mark_stack_map_.end());
-}
-
-void ConcurrentCopying::AddThreadMarkStackMapping(Thread* thread,
-                                                  accounting::ObjectStack* tl_mark_stack) {
-  CHECK(tl_mark_stack != nullptr);
-  CHECK(thread_mark_stack_map_.find(thread) == thread_mark_stack_map_.end());
-  thread_mark_stack_map_.insert({thread, tl_mark_stack});
-}
-
 class ConcurrentCopying::RevokeThreadLocalMarkStackCheckpoint : public Closure {
  public:
   RevokeThreadLocalMarkStackCheckpoint(ConcurrentCopying* concurrent_copying,
@@ -1003,7 +988,6 @@
       if (tl_mark_stack != nullptr) {
         concurrent_copying_->revoked_mark_stacks_.push_back(tl_mark_stack);
         thread->SetThreadLocalMarkStack(nullptr);
-        concurrent_copying_->RemoveThreadMarkStackMapping(thread, tl_mark_stack);
       }
     }
     // Disable weak ref access.
@@ -1089,7 +1073,35 @@
       REQUIRES_SHARED(Locks::heap_bitmap_lock_) {
     DCHECK_EQ(collector_->RegionSpace()->RegionIdxForRef(obj), obj_region_idx_);
     DCHECK(kHandleInterRegionRefs || collector_->immune_spaces_.ContainsObject(obj));
-    CheckReference(obj->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(offset));
+    mirror::Object* ref =
+            obj->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(offset);
+    // TODO(lokeshgidra): Remove the following condition once b/173676071 is fixed.
+    if (UNLIKELY(ref == nullptr && offset == mirror::Object::ClassOffset())) {
+      // It has been verified as a race condition (see b/173676071)! After a small
+      // wait when we reload the class pointer, it turns out to be a valid class
+      // object. So as a workaround, we can continue execution and log an error
+      // that this happened.
+      for (size_t i = 0; i < 1000; i++) {
+        // Wait for 1ms at a time. Don't wait for more than 1 second in total.
+        usleep(1000);
+        ref = obj->GetClass<kVerifyNone, kWithoutReadBarrier>();
+        if (ref != nullptr) {
+          LOG(ERROR) << "klass pointer for obj: "
+                     << obj << " (" << mirror::Object::PrettyTypeOf(obj)
+                     << ") found to be null first. Reloading after a small wait fetched klass: "
+                     << ref << " (" << mirror::Object::PrettyTypeOf(ref) << ")";
+          break;
+        }
+      }
+
+      if (UNLIKELY(ref == nullptr)) {
+        // It must be heap corruption. Remove memory protection and dump data.
+        collector_->region_space_->Unprotect();
+        LOG(FATAL_WITHOUT_ABORT) << "klass pointer for ref: " << obj << " found to be null.";
+        collector_->heap_->GetVerification()->LogHeapCorruption(obj, offset, ref, /* fatal */ true);
+      }
+    }
+    CheckReference(ref);
   }
 
   void operator()(ObjPtr<mirror::Class> klass, ObjPtr<mirror::Reference> ref) const
@@ -1268,7 +1280,6 @@
   {
     MutexLock mu(thread_running_gc_, mark_stack_lock_);
     CHECK(revoked_mark_stacks_.empty());
-    AssertEmptyThreadMarkStackMap();
     CHECK_EQ(pooled_mark_stacks_.size(), kMarkStackPoolSize);
   }
 
@@ -1831,9 +1842,7 @@
         if (tl_mark_stack != nullptr) {
           // Store the old full stack into a vector.
           revoked_mark_stacks_.push_back(tl_mark_stack);
-          RemoveThreadMarkStackMapping(self, tl_mark_stack);
         }
-        AddThreadMarkStackMapping(self, new_tl_mark_stack);
       } else {
         tl_mark_stack->PushBack(to_ref);
       }
@@ -2060,7 +2069,6 @@
   if (tl_mark_stack != nullptr) {
     CHECK(is_marking_);
     revoked_mark_stacks_.push_back(tl_mark_stack);
-    RemoveThreadMarkStackMapping(thread, tl_mark_stack);
     thread->SetThreadLocalMarkStack(nullptr);
   }
 }
@@ -2110,7 +2118,6 @@
     {
       MutexLock mu(thread_running_gc_, mark_stack_lock_);
       CHECK(revoked_mark_stacks_.empty());
-      AssertEmptyThreadMarkStackMap();
       CHECK_EQ(pooled_mark_stacks_.size(), kMarkStackPoolSize);
     }
     while (true) {
@@ -2138,7 +2145,6 @@
     {
       MutexLock mu(thread_running_gc_, mark_stack_lock_);
       CHECK(revoked_mark_stacks_.empty());
-      AssertEmptyThreadMarkStackMap();
       CHECK_EQ(pooled_mark_stacks_.size(), kMarkStackPoolSize);
     }
     // Process the GC mark stack in the exclusive mode. No need to take the lock.
@@ -2163,10 +2169,6 @@
   if (disable_weak_ref_access) {
     CHECK_EQ(static_cast<uint32_t>(mark_stack_mode_.load(std::memory_order_relaxed)),
              static_cast<uint32_t>(kMarkStackModeShared));
-    // From this point onwards no mutator should require a thread-local mark
-    // stack.
-    MutexLock mu(thread_running_gc_, mark_stack_lock_);
-    AssertEmptyThreadMarkStackMap();
   }
   size_t count = 0;
   std::vector<accounting::AtomicStack<mirror::Object>*> mark_stacks;
@@ -2204,6 +2206,7 @@
 
 inline void ConcurrentCopying::ProcessMarkStackRef(mirror::Object* to_ref) {
   DCHECK(!region_space_->IsInFromSpace(to_ref));
+  size_t obj_size = 0;
   space::RegionSpace::RegionType rtype = region_space_->GetRegionType(to_ref);
   if (kUseBakerReadBarrier) {
     DCHECK(to_ref->GetReadBarrierState() == ReadBarrier::GrayState())
@@ -2290,10 +2293,11 @@
       }
   }
   if (perform_scan) {
+    obj_size = to_ref->SizeOf<kDefaultVerifyFlags>();
     if (use_generational_cc_ && young_gen_) {
-      Scan<true>(to_ref);
+      Scan<true>(to_ref, obj_size);
     } else {
-      Scan<false>(to_ref);
+      Scan<false>(to_ref, obj_size);
     }
   }
   if (kUseBakerReadBarrier) {
@@ -2337,9 +2341,10 @@
     // Add to the live bytes per unevacuated from-space. Note this code is always run by the
     // GC-running thread (no synchronization required).
     DCHECK(region_space_bitmap_->Test(to_ref));
-    size_t obj_size = to_ref->SizeOf<kDefaultVerifyFlags>();
-    size_t alloc_size = RoundUp(obj_size, space::RegionSpace::kAlignment);
-    region_space_->AddLiveBytes(to_ref, alloc_size);
+    if (obj_size == 0) {
+      obj_size = to_ref->SizeOf<kDefaultVerifyFlags>();
+    }
+    region_space_->AddLiveBytes(to_ref, RoundUp(obj_size, space::RegionSpace::kAlignment));
   }
   if (ReadBarrier::kEnableToSpaceInvariantChecks) {
     CHECK(to_ref != nullptr);
@@ -2439,7 +2444,6 @@
     MutexLock mu(thread_running_gc_, mark_stack_lock_);
     CHECK(gc_mark_stack_->IsEmpty());
     CHECK(revoked_mark_stacks_.empty());
-    AssertEmptyThreadMarkStackMap();
     CHECK_EQ(pooled_mark_stacks_.size(), kMarkStackPoolSize);
   }
 }
@@ -2722,9 +2726,9 @@
     const uint64_t unevac_from_bytes = region_space_->GetBytesAllocatedInUnevacFromSpace();
     const uint64_t unevac_from_objects = region_space_->GetObjectsAllocatedInUnevacFromSpace();
     uint64_t to_bytes = bytes_moved_.load(std::memory_order_relaxed) + bytes_moved_gc_thread_;
-    cumulative_bytes_moved_.fetch_add(to_bytes, std::memory_order_relaxed);
+    cumulative_bytes_moved_ += to_bytes;
     uint64_t to_objects = objects_moved_.load(std::memory_order_relaxed) + objects_moved_gc_thread_;
-    cumulative_objects_moved_.fetch_add(to_objects, std::memory_order_relaxed);
+    cumulative_objects_moved_ += to_objects;
     if (kEnableFromSpaceAccountingCheck) {
       CHECK_EQ(from_space_num_objects_at_first_pause_, from_objects + unevac_from_objects);
       CHECK_EQ(from_space_num_bytes_at_first_pause_, from_bytes + unevac_from_bytes);
@@ -2766,6 +2770,7 @@
                 << heap_->num_bytes_allocated_.load();
     }
     RecordFree(ObjectBytePair(freed_objects, freed_bytes));
+    GetCurrentIteration()->SetScannedBytes(bytes_scanned_);
     if (kVerboseMode) {
       LOG(INFO) << "(after) num_bytes_allocated="
                 << heap_->num_bytes_allocated_.load();
@@ -3144,7 +3149,7 @@
 };
 
 template <bool kNoUnEvac>
-inline void ConcurrentCopying::Scan(mirror::Object* to_ref) {
+inline void ConcurrentCopying::Scan(mirror::Object* to_ref, size_t obj_size) {
   // Cannot have `kNoUnEvac` when Generational CC collection is disabled.
   DCHECK(!kNoUnEvac || use_generational_cc_);
   if (kDisallowReadBarrierDuringScan && !Runtime::Current()->IsActiveTransaction()) {
@@ -3153,6 +3158,11 @@
     // trigger read barriers.
     Thread::Current()->ModifyDebugDisallowReadBarrier(1);
   }
+  if (obj_size == 0) {
+    obj_size = to_ref->SizeOf<kDefaultVerifyFlags>();
+  }
+  bytes_scanned_ += obj_size;
+
   DCHECK(!region_space_->IsInFromSpace(to_ref));
   DCHECK_EQ(Thread::Current(), thread_running_gc_);
   RefFieldsVisitor<kNoUnEvac> visitor(this, thread_running_gc_);
@@ -3280,17 +3290,17 @@
   bool enabled_;
 };
 
-// Fill the given memory block with a dummy object. Used to fill in a
+// Fill the given memory block with a fake object. Used to fill in a
 // copy of objects that was lost in race.
-void ConcurrentCopying::FillWithDummyObject(Thread* const self,
-                                            mirror::Object* dummy_obj,
-                                            size_t byte_size) {
+void ConcurrentCopying::FillWithFakeObject(Thread* const self,
+                                           mirror::Object* fake_obj,
+                                           size_t byte_size) {
   // GC doesn't gray immune objects while scanning immune objects. But we need to trigger the read
   // barriers here because we need the updated reference to the int array class, etc. Temporary set
   // gc_grays_immune_objects_ to true so that we won't cause a DCHECK failure in MarkImmuneSpace().
   ScopedGcGraysImmuneObjects scoped_gc_gray_immune_objects(this);
   CHECK_ALIGNED(byte_size, kObjectAlignment);
-  memset(dummy_obj, 0, byte_size);
+  memset(fake_obj, 0, byte_size);
   // Avoid going through read barrier for since kDisallowReadBarrierDuringScan may be enabled.
   // Explicitly mark to make sure to get an object in the to-space.
   mirror::Class* int_array_class = down_cast<mirror::Class*>(
@@ -3309,19 +3319,19 @@
       AssertToSpaceInvariant(nullptr, MemberOffset(0), java_lang_Object_);
     }
     CHECK_EQ(byte_size, java_lang_Object_->GetObjectSize<kVerifyNone>());
-    dummy_obj->SetClass(java_lang_Object_);
-    CHECK_EQ(byte_size, (dummy_obj->SizeOf<kVerifyNone>()));
+    fake_obj->SetClass(java_lang_Object_);
+    CHECK_EQ(byte_size, (fake_obj->SizeOf<kVerifyNone>()));
   } else {
     // Use an int array.
-    dummy_obj->SetClass(int_array_class);
-    CHECK(dummy_obj->IsArrayInstance<kVerifyNone>());
+    fake_obj->SetClass(int_array_class);
+    CHECK(fake_obj->IsArrayInstance<kVerifyNone>());
     int32_t length = (byte_size - data_offset) / component_size;
-    ObjPtr<mirror::Array> dummy_arr = dummy_obj->AsArray<kVerifyNone>();
-    dummy_arr->SetLength(length);
-    CHECK_EQ(dummy_arr->GetLength(), length)
+    ObjPtr<mirror::Array> fake_arr = fake_obj->AsArray<kVerifyNone>();
+    fake_arr->SetLength(length);
+    CHECK_EQ(fake_arr->GetLength(), length)
         << "byte_size=" << byte_size << " length=" << length
         << " component_size=" << component_size << " data_offset=" << data_offset;
-    CHECK_EQ(byte_size, (dummy_obj->SizeOf<kVerifyNone>()))
+    CHECK_EQ(byte_size, (fake_obj->SizeOf<kVerifyNone>()))
         << "byte_size=" << byte_size << " length=" << length
         << " component_size=" << component_size << " data_offset=" << data_offset;
   }
@@ -3344,7 +3354,7 @@
     byte_size = it->first;
     CHECK_GE(byte_size, alloc_size);
     if (byte_size > alloc_size && byte_size - alloc_size < min_object_size) {
-      // If remainder would be too small for a dummy object, retry with a larger request size.
+      // If remainder would be too small for a fake object, retry with a larger request size.
       it = skipped_blocks_map_.lower_bound(alloc_size + min_object_size);
       if (it == skipped_blocks_map_.end()) {
         // Not found.
@@ -3371,12 +3381,12 @@
     // Return the remainder to the map.
     CHECK_ALIGNED(byte_size - alloc_size, space::RegionSpace::kAlignment);
     CHECK_GE(byte_size - alloc_size, min_object_size);
-    // FillWithDummyObject may mark an object, avoid holding skipped_blocks_lock_ to prevent lock
+    // FillWithFakeObject may mark an object, avoid holding skipped_blocks_lock_ to prevent lock
     // violation and possible deadlock. The deadlock case is a recursive case:
-    // FillWithDummyObject -> Mark(IntArray.class) -> Copy -> AllocateInSkippedBlock.
-    FillWithDummyObject(self,
-                        reinterpret_cast<mirror::Object*>(addr + alloc_size),
-                        byte_size - alloc_size);
+    // FillWithFakeObject -> Mark(IntArray.class) -> Copy -> AllocateInSkippedBlock.
+    FillWithFakeObject(self,
+                       reinterpret_cast<mirror::Object*>(addr + alloc_size),
+                       byte_size - alloc_size);
     CHECK(region_space_->IsInToSpace(reinterpret_cast<mirror::Object*>(addr + alloc_size)));
     {
       MutexLock mu(self, skipped_blocks_lock_);
@@ -3409,10 +3419,10 @@
   size_t region_space_bytes_allocated = 0U;
   size_t non_moving_space_bytes_allocated = 0U;
   size_t bytes_allocated = 0U;
-  size_t dummy;
+  size_t unused_size;
   bool fall_back_to_non_moving = false;
   mirror::Object* to_ref = region_space_->AllocNonvirtual</*kForEvac=*/ true>(
-      region_space_alloc_size, &region_space_bytes_allocated, nullptr, &dummy);
+      region_space_alloc_size, &region_space_bytes_allocated, nullptr, &unused_size);
   bytes_allocated = region_space_bytes_allocated;
   if (LIKELY(to_ref != nullptr)) {
     DCHECK_EQ(region_space_alloc_size, region_space_bytes_allocated);
@@ -3438,8 +3448,8 @@
                   << " skipped_objects="
                   << to_space_objects_skipped_.load(std::memory_order_relaxed);
       }
-      to_ref = heap_->non_moving_space_->Alloc(self, obj_size,
-                                               &non_moving_space_bytes_allocated, nullptr, &dummy);
+      to_ref = heap_->non_moving_space_->Alloc(
+          self, obj_size, &non_moving_space_bytes_allocated, nullptr, &unused_size);
       if (UNLIKELY(to_ref == nullptr)) {
         LOG(FATAL_WITHOUT_ABORT) << "Fall-back non-moving space allocation failed for a "
                                  << obj_size << " byte object in region type "
@@ -3472,9 +3482,9 @@
     if (old_lock_word.GetState() == LockWord::kForwardingAddress) {
       // Lost the race. Another thread (either GC or mutator) stored
       // the forwarding pointer first. Make the lost copy (to_ref)
-      // look like a valid but dead (dummy) object and keep it for
+      // look like a valid but dead (fake) object and keep it for
       // future reuse.
-      FillWithDummyObject(self, to_ref, bytes_allocated);
+      FillWithFakeObject(self, to_ref, bytes_allocated);
       if (!fall_back_to_non_moving) {
         DCHECK(region_space_->IsInToSpace(to_ref));
         if (bytes_allocated > space::RegionSpace::kRegionSize) {
@@ -3514,17 +3524,14 @@
       to_ref->SetReadBarrierState(ReadBarrier::GrayState());
     }
 
-    // Do a fence to prevent the field CAS in ConcurrentCopying::Process from possibly reordering
-    // before the object copy.
-    std::atomic_thread_fence(std::memory_order_release);
-
     LockWord new_lock_word = LockWord::FromForwardingAddress(reinterpret_cast<size_t>(to_ref));
 
-    // Try to atomically write the fwd ptr.
+    // Try to atomically write the fwd ptr. Make sure that the copied object is visible to any
+    // readers of the fwd pointer.
     bool success = from_ref->CasLockWord(old_lock_word,
                                          new_lock_word,
                                          CASMode::kWeak,
-                                         std::memory_order_relaxed);
+                                         std::memory_order_release);
     if (LIKELY(success)) {
       // The CAS succeeded.
       DCHECK(thread_running_gc_ != nullptr);
@@ -3555,6 +3562,9 @@
       }
       DCHECK(GetFwdPtr(from_ref) == to_ref);
       CHECK_NE(to_ref->GetLockWord(false).GetState(), LockWord::kForwardingAddress);
+      // Make sure that anyone who sees to_ref also sees both the object contents and the
+      // fwd pointer.
+      QuasiAtomic::ThreadFenceForConstructor();
       PushOntoMarkStack(self, to_ref);
       return to_ref;
     } else {
@@ -3703,7 +3713,6 @@
   {
     MutexLock mu(self, mark_stack_lock_);
     CHECK(revoked_mark_stacks_.empty());
-    AssertEmptyThreadMarkStackMap();
     CHECK_EQ(pooled_mark_stacks_.size(), kMarkStackPoolSize);
   }
   // kVerifyNoMissingCardMarks relies on the region space cards not being cleared to avoid false
@@ -3781,8 +3790,7 @@
         }
       } while (!field->CasWeakRelaxed(from_ref, to_ref));
     } else {
-      // TODO: Why is this seq_cst when the above is relaxed? Document memory ordering.
-      field->Assign</* kIsVolatile= */ true>(to_ref);
+      field->Assign(to_ref);
     }
   }
   return true;
@@ -3852,10 +3860,8 @@
      << (copied_live_bytes_ratio_sum_ / gc_count_) << " over " << gc_count_
      << " " << (young_gen_ ? "minor" : "major") << " GCs\n";
 
-  os << "Cumulative bytes moved "
-     << cumulative_bytes_moved_.load(std::memory_order_relaxed) << "\n";
-  os << "Cumulative objects moved "
-     << cumulative_objects_moved_.load(std::memory_order_relaxed) << "\n";
+  os << "Cumulative bytes moved " << cumulative_bytes_moved_ << "\n";
+  os << "Cumulative objects moved " << cumulative_objects_moved_ << "\n";
 
   os << "Peak regions allocated "
      << region_space_->GetMaxPeakNumNonFreeRegions() << " ("
@@ -3863,6 +3869,9 @@
      << ") / " << region_space_->GetNumRegions() / 2 << " ("
      << PrettySize(region_space_->GetNumRegions() * space::RegionSpace::kRegionSize / 2)
      << ")\n";
+  if (!young_gen_) {
+    os << "Total madvise time " << PrettyDuration(region_space_->GetMadviseTime()) << "\n";
+  }
 }
 
 }  // namespace collector
diff --git a/runtime/gc/collector/concurrent_copying.h b/runtime/gc/collector/concurrent_copying.h
index 6482ff7..72d460d 100644
--- a/runtime/gc/collector/concurrent_copying.h
+++ b/runtime/gc/collector/concurrent_copying.h
@@ -152,6 +152,11 @@
   }
   void RevokeThreadLocalMarkStack(Thread* thread) REQUIRES(!mark_stack_lock_);
 
+  // Blindly return the forwarding pointer from the lockword, or null if there is none.
+  static mirror::Object* GetFwdPtrUnchecked(mirror::Object* from_ref)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // If marked, return the to-space object, otherwise null.
   mirror::Object* IsMarked(mirror::Object* from_ref) override
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -161,6 +166,9 @@
   void PushOntoMarkStack(Thread* const self, mirror::Object* obj)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!mark_stack_lock_);
+  // Returns a to-space copy of the from-space object from_ref, and atomically installs a
+  // forwarding pointer. Ensures that the forwarding reference is visible to other threads before
+  // the returned to-space pointer becomes visible to them.
   mirror::Object* Copy(Thread* const self,
                        mirror::Object* from_ref,
                        mirror::Object* holder,
@@ -169,7 +177,7 @@
       REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_);
   // Scan the reference fields of object `to_ref`.
   template <bool kNoUnEvac>
-  void Scan(mirror::Object* to_ref) REQUIRES_SHARED(Locks::mutator_lock_)
+  void Scan(mirror::Object* to_ref, size_t obj_size = 0) REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!mark_stack_lock_);
   // Scan the reference fields of object 'obj' in the dirty cards during
   // card-table scan. In addition to visiting the references, it also sets the
@@ -257,7 +265,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_);
   void MarkZygoteLargeObjects()
       REQUIRES_SHARED(Locks::mutator_lock_);
-  void FillWithDummyObject(Thread* const self, mirror::Object* dummy_obj, size_t byte_size)
+  void FillWithFakeObject(Thread* const self, mirror::Object* fake_obj, size_t byte_size)
       REQUIRES(!mark_stack_lock_, !skipped_blocks_lock_, !immune_gray_stack_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
   mirror::Object* AllocateInSkippedBlock(Thread* const self, size_t alloc_size)
@@ -266,8 +274,8 @@
   void CheckEmptyMarkStack() REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!mark_stack_lock_);
   void IssueEmptyCheckpoint() REQUIRES_SHARED(Locks::mutator_lock_);
   bool IsOnAllocStack(mirror::Object* ref) REQUIRES_SHARED(Locks::mutator_lock_);
-  mirror::Object* GetFwdPtr(mirror::Object* from_ref)
-      REQUIRES_SHARED(Locks::mutator_lock_);
+  // Return the forwarding pointer from the lockword. The argument must be in from space.
+  mirror::Object* GetFwdPtr(mirror::Object* from_ref) REQUIRES_SHARED(Locks::mutator_lock_);
   void FlipThreadRoots() REQUIRES(!Locks::mutator_lock_);
   void SwapStacks() REQUIRES_SHARED(Locks::mutator_lock_);
   void RecordLiveStackFreezeSize(Thread* self);
@@ -371,9 +379,6 @@
   static constexpr size_t kMarkStackPoolSize = 256;
   std::vector<accounting::ObjectStack*> pooled_mark_stacks_
       GUARDED_BY(mark_stack_lock_);
-  // TODO(lokeshgidra b/140119552): remove this after bug fix.
-  std::unordered_map<Thread*, accounting::ObjectStack*> thread_mark_stack_map_
-      GUARDED_BY(mark_stack_lock_);
   Thread* thread_running_gc_;
   bool is_marking_;                       // True while marking is ongoing.
   // True while we might dispatch on the read barrier entrypoints.
@@ -405,10 +410,6 @@
   // bytes_moved_gc_thread_ are critical for GC triggering; the others are just informative.
   Atomic<size_t> bytes_moved_;  // Used by mutators
   Atomic<size_t> objects_moved_;  // Used by mutators
-  size_t bytes_moved_gc_thread_;  // Used by GC
-  size_t objects_moved_gc_thread_;  // Used by GC
-  Atomic<uint64_t> cumulative_bytes_moved_;
-  Atomic<uint64_t> cumulative_objects_moved_;
 
   // copied_live_bytes_ratio_sum_ is read and written by CC per GC, in
   // ReclaimPhase, and is read by DumpPerformanceInfo (potentially from another
@@ -431,6 +432,15 @@
   // reclaimed_bytes_ratio = reclaimed_bytes/num_allocated_bytes per GC cycle
   float reclaimed_bytes_ratio_sum_;
 
+  // Used only by GC thread, so need not be atomic. Also, should be kept
+  // in a different cacheline than bytes/objects_moved_ (above) to avoid false
+  // cacheline sharing.
+  size_t bytes_moved_gc_thread_;
+  size_t objects_moved_gc_thread_;
+  uint64_t bytes_scanned_;
+  uint64_t cumulative_bytes_moved_;
+  uint64_t cumulative_objects_moved_;
+
   // The skipped blocks are memory blocks/chucks that were copies of
   // objects that were unused due to lost races (cas failures) at
   // object copy/forward pointer install. They may be reused.
@@ -465,7 +475,7 @@
   std::vector<mirror::Object*> immune_gray_stack_ GUARDED_BY(immune_gray_stack_lock_);
 
   // Class of java.lang.Object. Filled in from WellKnownClasses in FlipCallback. Must
-  // be filled in before flipping thread roots so that FillDummyObject can run. Not
+  // be filled in before flipping thread roots so that FillWithFakeObject can run. Not
   // ObjPtr since the GC may transition to suspended and runnable between phases.
   mirror::Class* java_lang_Object_;
 
diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc
index bb1a146..80b3982 100644
--- a/runtime/gc/collector/garbage_collector.cc
+++ b/runtime/gc/collector/garbage_collector.cc
@@ -51,6 +51,7 @@
   timings_.Reset();
   pause_times_.clear();
   duration_ns_ = 0;
+  bytes_scanned_ = 0;
   clear_soft_references_ = clear_soft_references;
   gc_cause_ = gc_cause;
   freed_ = ObjectBytePair();
@@ -69,9 +70,16 @@
       pause_histogram_((name_ + " paused").c_str(), kPauseBucketSize, kPauseBucketCount),
       rss_histogram_((name_ + " peak-rss").c_str(), kMemBucketSize, kMemBucketCount),
       freed_bytes_histogram_((name_ + " freed-bytes").c_str(), kMemBucketSize, kMemBucketCount),
+      gc_time_histogram_(nullptr),
+      metrics_gc_count_(nullptr),
+      gc_throughput_histogram_(nullptr),
+      gc_tracing_throughput_hist_(nullptr),
+      gc_throughput_avg_(nullptr),
+      gc_tracing_throughput_avg_(nullptr),
       cumulative_timings_(name),
       pause_histogram_lock_("pause histogram lock", kDefaultMutexLevel, true),
-      is_transaction_active_(false) {
+      is_transaction_active_(false),
+      are_metrics_initialized_(false) {
   ResetCumulativeStatistics();
 }
 
@@ -85,6 +93,7 @@
   total_time_ns_ = 0u;
   total_freed_objects_ = 0u;
   total_freed_bytes_ = 0;
+  total_scanned_bytes_ = 0;
   rss_histogram_.Reset();
   freed_bytes_histogram_.Reset();
   MutexLock mu(Thread::Current(), pause_histogram_lock_);
@@ -146,6 +155,7 @@
 void GarbageCollector::Run(GcCause gc_cause, bool clear_soft_references) {
   ScopedTrace trace(android::base::StringPrintf("%s %s GC", PrettyCause(gc_cause), GetName()));
   Thread* self = Thread::Current();
+  Runtime* runtime = Runtime::Current();
   uint64_t start_time = NanoTime();
   uint64_t thread_cpu_start_time = ThreadCpuNanoTime();
   GetHeap()->CalculatePreGcWeightedAllocatedBytes();
@@ -153,7 +163,7 @@
   current_iteration->Reset(gc_cause, clear_soft_references);
   // Note transaction mode is single-threaded and there's no asynchronous GC and this flag doesn't
   // change in the middle of a GC.
-  is_transaction_active_ = Runtime::Current()->IsActiveTransaction();
+  is_transaction_active_ = runtime->IsActiveTransaction();
   RunPhases();  // Run all the GC phases.
   GetHeap()->CalculatePostGcWeightedAllocatedBytes();
   // Add the current timings to the cumulative timings.
@@ -161,6 +171,7 @@
   // Update cumulative statistics with how many bytes the GC iteration freed.
   total_freed_objects_ += current_iteration->GetFreedObjects() +
       current_iteration->GetFreedLargeObjects();
+  total_scanned_bytes_ += current_iteration->GetScannedBytes();
   int64_t freed_bytes = current_iteration->GetFreedBytes() +
       current_iteration->GetFreedLargeObjectBytes();
   total_freed_bytes_ += freed_bytes;
@@ -169,17 +180,42 @@
   uint64_t end_time = NanoTime();
   uint64_t thread_cpu_end_time = ThreadCpuNanoTime();
   total_thread_cpu_time_ns_ += thread_cpu_end_time - thread_cpu_start_time;
-  current_iteration->SetDurationNs(end_time - start_time);
+  uint64_t duration_ns = end_time - start_time;
+  current_iteration->SetDurationNs(duration_ns);
   if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
     // The entire GC was paused, clear the fake pauses which might be in the pause times and add
     // the whole GC duration.
     current_iteration->pause_times_.clear();
-    RegisterPause(current_iteration->GetDurationNs());
+    RegisterPause(duration_ns);
   }
-  total_time_ns_ += current_iteration->GetDurationNs();
+  total_time_ns_ += duration_ns;
+  uint64_t total_pause_time = 0;
   for (uint64_t pause_time : current_iteration->GetPauseTimes()) {
     MutexLock mu(self, pause_histogram_lock_);
     pause_histogram_.AdjustAndAddValue(pause_time);
+    total_pause_time += pause_time;
+  }
+  metrics::ArtMetrics* metrics = runtime->GetMetrics();
+  // Report STW pause time in microseconds.
+  metrics->WorldStopTimeDuringGCAvg()->Add(total_pause_time / 1'000);
+  // Report total collection time of all GCs put together.
+  metrics->TotalGcCollectionTime()->Add(NsToMs(duration_ns));
+  if (are_metrics_initialized_) {
+    metrics_gc_count_->Add(1);
+    // Report GC time in milliseconds.
+    gc_time_histogram_->Add(NsToMs(duration_ns));
+    // Throughput in bytes/s. Add 1us to prevent possible division by 0.
+    uint64_t throughput = (current_iteration->GetScannedBytes() * 1'000'000)
+            / (NsToUs(duration_ns) + 1);
+    // Report in MB/s.
+    throughput /= MB;
+    gc_tracing_throughput_hist_->Add(throughput);
+    gc_tracing_throughput_avg_->Add(throughput);
+
+    // Report GC throughput in MB/s.
+    throughput = current_iteration->GetEstimatedThroughput() / MB;
+    gc_throughput_histogram_->Add(throughput);
+    gc_throughput_avg_->Add(throughput);
   }
   is_transaction_active_ = false;
 }
@@ -223,6 +259,7 @@
   total_time_ns_ = 0u;
   total_freed_objects_ = 0u;
   total_freed_bytes_ = 0;
+  total_scanned_bytes_ = 0u;
 }
 
 GarbageCollector::ScopedPause::ScopedPause(GarbageCollector* collector, bool with_reporting)
@@ -282,6 +319,7 @@
   const double seconds = NsToMs(total_ns) / 1000.0;
   const uint64_t freed_bytes = GetTotalFreedBytes();
   const uint64_t freed_objects = GetTotalFreedObjects();
+  const uint64_t scanned_bytes = GetTotalScannedBytes();
   {
     MutexLock mu(Thread::Current(), pause_histogram_lock_);
     if (pause_histogram_.SampleSize() > 0) {
@@ -319,7 +357,11 @@
      << PrettySize(freed_bytes / seconds) << "/s"
      << "  per cpu-time: "
      << static_cast<uint64_t>(freed_bytes / cpu_seconds) << "/s / "
-     << PrettySize(freed_bytes / cpu_seconds) << "/s\n";
+     << PrettySize(freed_bytes / cpu_seconds) << "/s\n"
+     << GetName() << " tracing throughput: "
+     << PrettySize(scanned_bytes / seconds) << "/s "
+     << " per cpu-time: "
+     << PrettySize(scanned_bytes / cpu_seconds) << "/s\n";
 }
 
 }  // namespace collector
diff --git a/runtime/gc/collector/garbage_collector.h b/runtime/gc/collector/garbage_collector.h
index 7505658..d439914 100644
--- a/runtime/gc/collector/garbage_collector.h
+++ b/runtime/gc/collector/garbage_collector.h
@@ -21,6 +21,7 @@
 #include <list>
 
 #include "base/histogram.h"
+#include "base/metrics/metrics.h"
 #include "base/mutex.h"
 #include "base/timing_logger.h"
 #include "gc/collector_type.h"
@@ -91,6 +92,9 @@
   uint64_t GetTotalFreedObjects() const {
     return total_freed_objects_;
   }
+  uint64_t GetTotalScannedBytes() const {
+    return total_scanned_bytes_;
+  }
   // Reset the cumulative timings and pause histogram.
   void ResetMeasurements() REQUIRES(!pause_histogram_lock_);
   // Returns the estimated throughput in bytes / second.
@@ -156,13 +160,24 @@
   Histogram<uint64_t> pause_histogram_ GUARDED_BY(pause_histogram_lock_);
   Histogram<uint64_t> rss_histogram_;
   Histogram<size_t> freed_bytes_histogram_;
+  metrics::MetricsBase<int64_t>* gc_time_histogram_;
+  metrics::MetricsBase<uint64_t>* metrics_gc_count_;
+  metrics::MetricsBase<int64_t>* gc_throughput_histogram_;
+  metrics::MetricsBase<int64_t>* gc_tracing_throughput_hist_;
+  metrics::MetricsBase<uint64_t>* gc_throughput_avg_;
+  metrics::MetricsBase<uint64_t>* gc_tracing_throughput_avg_;
   uint64_t total_thread_cpu_time_ns_;
   uint64_t total_time_ns_;
   uint64_t total_freed_objects_;
   int64_t total_freed_bytes_;
+  uint64_t total_scanned_bytes_;
   CumulativeLogger cumulative_timings_;
   mutable Mutex pause_histogram_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   bool is_transaction_active_;
+  // The garbage collector algorithms will either have all the metrics pointers
+  // (above) initialized, or none of them. So instead of checking each time, we
+  // use this flag.
+  bool are_metrics_initialized_;
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(GarbageCollector);
diff --git a/runtime/gc/collector/gc_type.h b/runtime/gc/collector/gc_type.h
index 401444a..f03ba1f 100644
--- a/runtime/gc/collector/gc_type.h
+++ b/runtime/gc/collector/gc_type.h
@@ -37,7 +37,7 @@
   // Number of different GC types.
   kGcTypeMax,
 };
-std::ostream& operator<<(std::ostream& os, const GcType& policy);
+std::ostream& operator<<(std::ostream& os, GcType policy);
 
 }  // namespace collector
 }  // namespace gc
diff --git a/runtime/gc/collector/immune_spaces_test.cc b/runtime/gc/collector/immune_spaces_test.cc
index b1a21d4..222b3d5 100644
--- a/runtime/gc/collector/immune_spaces_test.cc
+++ b/runtime/gc/collector/immune_spaces_test.cc
@@ -30,21 +30,21 @@
 namespace gc {
 namespace collector {
 
-class DummyOatFile : public OatFile {
+class FakeOatFile : public OatFile {
  public:
-  DummyOatFile(uint8_t* begin, uint8_t* end) : OatFile("Location", /*executable=*/ false) {
+  FakeOatFile(uint8_t* begin, uint8_t* end) : OatFile("Location", /*executable=*/ false) {
     begin_ = begin;
     end_ = end;
   }
 };
 
-class DummyImageSpace : public space::ImageSpace {
+class FakeImageSpace : public space::ImageSpace {
  public:
-  DummyImageSpace(MemMap&& map,
-                  accounting::ContinuousSpaceBitmap&& live_bitmap,
-                  std::unique_ptr<DummyOatFile>&& oat_file,
-                  MemMap&& oat_map)
-      : ImageSpace("DummyImageSpace",
+  FakeImageSpace(MemMap&& map,
+                 accounting::ContinuousSpaceBitmap&& live_bitmap,
+                 std::unique_ptr<FakeOatFile>&& oat_file,
+                 MemMap&& oat_map)
+      : ImageSpace("FakeImageSpace",
                    /*image_location=*/"",
                    /*profile_file=*/"",
                    std::move(map),
@@ -66,7 +66,7 @@
   ImmuneSpacesTest() {}
 
   void ReserveBitmaps() {
-    // Create a bunch of dummy bitmaps since these are required to create image spaces. The bitmaps
+    // Create a bunch of fake bitmaps since these are required to create image spaces. The bitmaps
     // do not need to cover the image spaces though.
     for (size_t i = 0; i < kMaxBitmaps; ++i) {
       accounting::ContinuousSpaceBitmap bitmap(
@@ -79,14 +79,14 @@
   }
 
   // Create an image space, the oat file is optional.
-  DummyImageSpace* CreateImageSpace(size_t image_size,
-                                    size_t oat_size,
-                                    MemMap* image_reservation,
-                                    MemMap* oat_reservation) {
+  FakeImageSpace* CreateImageSpace(size_t image_size,
+                                   size_t oat_size,
+                                   MemMap* image_reservation,
+                                   MemMap* oat_reservation) {
     DCHECK(image_reservation != nullptr);
     DCHECK(oat_reservation != nullptr);
     std::string error_str;
-    MemMap image_map = MemMap::MapAnonymous("DummyImageSpace",
+    MemMap image_map = MemMap::MapAnonymous("FakeImageSpace",
                                             image_size,
                                             PROT_READ | PROT_WRITE,
                                             /*low_4gb=*/ true,
@@ -109,7 +109,7 @@
       LOG(ERROR) << error_str;
       return nullptr;
     }
-    std::unique_ptr<DummyOatFile> oat_file(new DummyOatFile(oat_map.Begin(), oat_map.End()));
+    std::unique_ptr<FakeOatFile> oat_file(new FakeOatFile(oat_map.Begin(), oat_map.End()));
     // Create image header.
     ImageSection sections[ImageHeader::kSectionCount];
     new (image_map.Begin()) ImageHeader(
@@ -130,22 +130,22 @@
         /*boot_image_component_count=*/ 0u,
         /*boot_image_checksum=*/ 0u,
         /*pointer_size=*/ sizeof(void*));
-    return new DummyImageSpace(std::move(image_map),
-                               std::move(live_bitmap),
-                               std::move(oat_file),
-                               std::move(oat_map));
+    return new FakeImageSpace(std::move(image_map),
+                              std::move(live_bitmap),
+                              std::move(oat_file),
+                              std::move(oat_map));
   }
 
  private:
-  // Bitmap pool for pre-allocated dummy bitmaps. We need to pre-allocate them since we don't want
+  // Bitmap pool for pre-allocated fake bitmaps. We need to pre-allocate them since we don't want
   // them to randomly get placed somewhere where we want an image space.
   std::vector<accounting::ContinuousSpaceBitmap> live_bitmaps_;
 };
 
-class DummySpace : public space::ContinuousSpace {
+class FakeSpace : public space::ContinuousSpace {
  public:
-  DummySpace(uint8_t* begin, uint8_t* end)
-      : ContinuousSpace("DummySpace",
+  FakeSpace(uint8_t* begin, uint8_t* end)
+      : ContinuousSpace("FakeSpace",
                         space::kGcRetentionPolicyNeverCollect,
                         begin,
                         end,
@@ -171,8 +171,8 @@
 TEST_F(ImmuneSpacesTest, AppendBasic) {
   ImmuneSpaces spaces;
   uint8_t* const base = reinterpret_cast<uint8_t*>(0x1000);
-  DummySpace a(base, base + 45 * KB);
-  DummySpace b(a.Limit(), a.Limit() + 813 * KB);
+  FakeSpace a(base, base + 45 * KB);
+  FakeSpace b(a.Limit(), a.Limit() + 813 * KB);
   {
     WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
     spaces.AddSpace(&a);
@@ -203,16 +203,16 @@
   ASSERT_TRUE(image_reservation.IsValid());
   ASSERT_TRUE(reservation.IsValid());
 
-  std::unique_ptr<DummyImageSpace> image_space(CreateImageSpace(kImageSize,
-                                                                kImageOatSize,
-                                                                &image_reservation,
-                                                                &reservation));
+  std::unique_ptr<FakeImageSpace> image_space(CreateImageSpace(kImageSize,
+                                                               kImageOatSize,
+                                                               &image_reservation,
+                                                               &reservation));
   ASSERT_TRUE(image_space != nullptr);
   ASSERT_FALSE(image_reservation.IsValid());
   ASSERT_TRUE(reservation.IsValid());
 
   const ImageHeader& image_header = image_space->GetImageHeader();
-  DummySpace space(image_header.GetOatFileEnd(), image_header.GetOatFileEnd() + kOtherSpaceSize);
+  FakeSpace space(image_header.GetOatFileEnd(), image_header.GetOatFileEnd() + kOtherSpaceSize);
 
   EXPECT_EQ(image_header.GetImageSize(), kImageSize);
   EXPECT_EQ(static_cast<size_t>(image_header.GetOatFileEnd() - image_header.GetOatFileBegin()),
@@ -266,18 +266,18 @@
   ASSERT_TRUE(image_reservation.IsValid());
   ASSERT_TRUE(reservation.IsValid());
 
-  std::unique_ptr<DummyImageSpace> space1(CreateImageSpace(kImage1Size,
-                                                           kImage1OatSize,
-                                                           &image_reservation,
-                                                           &reservation));
+  std::unique_ptr<FakeImageSpace> space1(CreateImageSpace(kImage1Size,
+                                                          kImage1OatSize,
+                                                          &image_reservation,
+                                                          &reservation));
   ASSERT_TRUE(space1 != nullptr);
   ASSERT_TRUE(image_reservation.IsValid());
   ASSERT_TRUE(reservation.IsValid());
 
-  std::unique_ptr<DummyImageSpace> space2(CreateImageSpace(kImage2Size,
-                                                           kImage2OatSize,
-                                                           &image_reservation,
-                                                           &reservation));
+  std::unique_ptr<FakeImageSpace> space2(CreateImageSpace(kImage2Size,
+                                                          kImage2OatSize,
+                                                          &image_reservation,
+                                                          &reservation));
   ASSERT_TRUE(space2 != nullptr);
   ASSERT_FALSE(image_reservation.IsValid());
   ASSERT_TRUE(reservation.IsValid());
@@ -286,10 +286,10 @@
   image_reservation = reservation.TakeReservedMemory(kImage3Size);
   ASSERT_TRUE(image_reservation.IsValid());
   ASSERT_TRUE(reservation.IsValid());
-  std::unique_ptr<DummyImageSpace> space3(CreateImageSpace(kImage3Size,
-                                                           kImage3OatSize,
-                                                           &image_reservation,
-                                                           &reservation));
+  std::unique_ptr<FakeImageSpace> space3(CreateImageSpace(kImage3Size,
+                                                          kImage3OatSize,
+                                                          &image_reservation,
+                                                          &reservation));
   ASSERT_TRUE(space3 != nullptr);
   ASSERT_FALSE(image_reservation.IsValid());
   ASSERT_FALSE(reservation.IsValid());
@@ -343,10 +343,10 @@
   image_reservation = reservation.TakeReservedMemory(kImage4Size);
   ASSERT_TRUE(image_reservation.IsValid());
   ASSERT_TRUE(reservation.IsValid());
-  std::unique_ptr<DummyImageSpace> space4(CreateImageSpace(kImage4Size,
-                                                           kImage4OatSize,
-                                                           &image_reservation,
-                                                           &reservation));
+  std::unique_ptr<FakeImageSpace> space4(CreateImageSpace(kImage4Size,
+                                                          kImage4OatSize,
+                                                          &image_reservation,
+                                                          &reservation));
   ASSERT_TRUE(space4 != nullptr);
   ASSERT_FALSE(image_reservation.IsValid());
   ASSERT_TRUE(reservation.IsValid());
@@ -382,10 +382,10 @@
   image_reservation = reservation.TakeReservedMemory(kImage5Size);
   ASSERT_TRUE(image_reservation.IsValid());
   ASSERT_TRUE(reservation.IsValid());
-  std::unique_ptr<DummyImageSpace> space5(CreateImageSpace(kImage5Size,
-                                                           kImage5OatSize,
-                                                           &image_reservation,
-                                                           &reservation));
+  std::unique_ptr<FakeImageSpace> space5(CreateImageSpace(kImage5Size,
+                                                          kImage5OatSize,
+                                                          &image_reservation,
+                                                          &reservation));
   ASSERT_TRUE(space5 != nullptr);
   ASSERT_FALSE(image_reservation.IsValid());
   ASSERT_TRUE(reservation.IsValid());
diff --git a/runtime/gc/collector/iteration.h b/runtime/gc/collector/iteration.h
index 363459a..348f49d 100644
--- a/runtime/gc/collector/iteration.h
+++ b/runtime/gc/collector/iteration.h
@@ -60,6 +60,12 @@
   uint64_t GetFreedRevokeBytes() const {
     return freed_bytes_revoke_;
   }
+  uint64_t GetScannedBytes() const {
+    return bytes_scanned_;
+  }
+  void SetScannedBytes(uint64_t bytes) {
+      bytes_scanned_ = bytes;
+  }
   void SetFreedRevoke(uint64_t freed) {
     freed_bytes_revoke_ = freed;
   }
@@ -84,6 +90,7 @@
   GcCause gc_cause_;
   bool clear_soft_references_;
   uint64_t duration_ns_;
+  uint64_t bytes_scanned_;
   TimingLogger timings_;
   ObjectBytePair freed_;
   ObjectBytePair freed_los_;
diff --git a/runtime/gc/collector/semi_space-inl.h b/runtime/gc/collector/semi_space-inl.h
index 065a125..86ab1fc 100644
--- a/runtime/gc/collector/semi_space-inl.h
+++ b/runtime/gc/collector/semi_space-inl.h
@@ -62,7 +62,7 @@
     DCHECK(!to_space_->HasAddress(obj)) << "Tried to mark " << obj << " in to-space";
     auto slow_path = [this](const mirror::Object* ref) {
       CHECK(!to_space_->HasAddress(ref)) << "Marking " << ref << " in to_space_";
-      // Marking a large object, make sure its aligned as a sanity check.
+      // Marking a large object, make sure its aligned as a consistency check.
       CHECK_ALIGNED(ref, kPageSize);
     };
     if (!mark_bitmap_->Set(obj, slow_path)) {
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index c93410e..d191031 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -426,21 +426,18 @@
 
 mirror::Object* SemiSpace::MarkNonForwardedObject(mirror::Object* obj) {
   const size_t object_size = obj->SizeOf();
-  size_t bytes_allocated, dummy;
+  size_t bytes_allocated, unused_bytes_tl_bulk_allocated;
   // Copy it to the to-space.
-  mirror::Object* forward_address = to_space_->AllocThreadUnsafe(self_,
-                                                                 object_size,
-                                                                 &bytes_allocated,
-                                                                 nullptr,
-                                                                 &dummy);
+  mirror::Object* forward_address = to_space_->AllocThreadUnsafe(
+      self_, object_size, &bytes_allocated, nullptr, &unused_bytes_tl_bulk_allocated);
 
   if (forward_address != nullptr && to_space_live_bitmap_ != nullptr) {
     to_space_live_bitmap_->Set(forward_address);
   }
   // If it's still null, attempt to use the fallback space.
   if (UNLIKELY(forward_address == nullptr)) {
-    forward_address = fallback_space_->AllocThreadUnsafe(self_, object_size, &bytes_allocated,
-                                                         nullptr, &dummy);
+    forward_address = fallback_space_->AllocThreadUnsafe(
+        self_, object_size, &bytes_allocated, nullptr, &unused_bytes_tl_bulk_allocated);
     CHECK(forward_address != nullptr) << "Out of memory in the to-space and fallback space.";
     accounting::ContinuousSpaceBitmap* bitmap = fallback_space_->GetLiveBitmap();
     if (bitmap != nullptr) {
diff --git a/runtime/gc/collector_type.h b/runtime/gc/collector_type.h
index 62527e2..9c99964 100644
--- a/runtime/gc/collector_type.h
+++ b/runtime/gc/collector_type.h
@@ -60,7 +60,7 @@
   // Fake collector type for ScopedGCCriticalSection
   kCollectorTypeCriticalSection,
 };
-std::ostream& operator<<(std::ostream& os, const CollectorType& collector_type);
+std::ostream& operator<<(std::ostream& os, CollectorType collector_type);
 
 static constexpr CollectorType kCollectorTypeDefault =
 #if ART_DEFAULT_GC_TYPE_IS_CMS
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index 4499342..50cfc6e 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -66,7 +66,7 @@
     self->PoisonObjectPointers();
   }
   auto pre_object_allocated = [&]() REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Roles::uninterruptible_) {
+      REQUIRES(!Roles::uninterruptible_ /* only suspends if kInstrumented */) {
     if constexpr (kInstrumented) {
       AllocationListener* l = alloc_listener_.load(std::memory_order_seq_cst);
       if (UNLIKELY(l != nullptr) && UNLIKELY(l->HasPreAlloc())) {
@@ -81,16 +81,20 @@
   size_t bytes_allocated;
   size_t usable_size;
   size_t new_num_bytes_allocated = 0;
+  bool need_gc = false;
+  uint32_t starting_gc_num;  // o.w. GC number at which we observed need for GC.
   {
+    // Bytes allocated that includes bulk thread-local buffer allocations in addition to direct
+    // non-TLAB object allocations. Only set for non-thread-local allocation,
+    size_t bytes_tl_bulk_allocated = 0u;
     // Do the initial pre-alloc
+    // TODO: Consider what happens if the allocator is switched while suspended here.
     pre_object_allocated();
-    ScopedAssertNoThreadSuspension ants("Called PreObjectAllocated, no suspend until alloc");
 
     // Need to check that we aren't the large object allocator since the large object allocation
     // code path includes this function. If we didn't check we would have an infinite loop.
     if (kCheckLargeObject && UNLIKELY(ShouldAllocLargeObject(klass, byte_count))) {
       // AllocLargeObject can suspend and will recall PreObjectAllocated if needed.
-      ScopedAllowThreadSuspension ats;
       obj = AllocLargeObject<kInstrumented, PreFenceVisitor>(self, &klass, byte_count,
                                                              pre_fence_visitor);
       if (obj != nullptr) {
@@ -102,8 +106,12 @@
       // If the large object allocation failed, try to use the normal spaces (main space,
       // non moving space). This can happen if there is significant virtual address space
       // fragmentation.
-      pre_object_allocated();
+      // kInstrumented may be out of date, so recurse without large object checking, rather than
+      // continue.
+      return AllocObjectWithAllocator</*kInstrumented=*/ true, /*kCheckLargeObject=*/ false>
+          (self, klass, byte_count, GetUpdatedAllocator(allocator), pre_fence_visitor);
     }
+    ScopedAssertNoThreadSuspension ants("Called PreObjectAllocated, no suspend until alloc");
     if (IsTLABAllocator(allocator)) {
       byte_count = RoundUp(byte_count, space::BumpPointerSpace::kAlignment);
     }
@@ -132,15 +140,12 @@
       no_suspend_pre_fence_visitor(obj, usable_size);
       QuasiAtomic::ThreadFenceForConstructor();
     } else {
-      // Bytes allocated that includes bulk thread-local buffer allocations in addition to direct
-      // non-TLAB object allocations.
-      size_t bytes_tl_bulk_allocated = 0u;
       obj = TryToAllocate<kInstrumented, false>(self, allocator, byte_count, &bytes_allocated,
                                                 &usable_size, &bytes_tl_bulk_allocated);
       if (UNLIKELY(obj == nullptr)) {
-        // AllocateInternalWithGc can cause thread suspension, if someone instruments the
-        // entrypoints or changes the allocator in a suspend point here, we need to retry the
-        // allocation. It will send the pre-alloc event again.
+        // AllocateInternalWithGc internally re-allows, and can cause, thread suspension, if
+        // someone instruments the entrypoints or changes the allocator in a suspend point here,
+        // we need to retry the allocation. It will send the pre-alloc event again.
         obj = AllocateInternalWithGc(self,
                                      allocator,
                                      kInstrumented,
@@ -157,13 +162,15 @@
             ScopedAllowThreadSuspension ats;
             // AllocObject will pick up the new allocator type, and instrumented as true is the safe
             // default.
-            return AllocObject</*kInstrumented=*/true>(self,
-                                                       klass,
-                                                       byte_count,
-                                                       pre_fence_visitor);
+            return AllocObjectWithAllocator</*kInstrumented=*/true>(self,
+                                                                    klass,
+                                                                    byte_count,
+                                                                    GetUpdatedAllocator(allocator),
+                                                                    pre_fence_visitor);
           }
           return nullptr;
         }
+        // Non-null result implies neither instrumentation nor allocator changed.
       }
       DCHECK_GT(bytes_allocated, 0u);
       DCHECK_GT(usable_size, 0u);
@@ -180,22 +187,32 @@
       }
       no_suspend_pre_fence_visitor(obj, usable_size);
       QuasiAtomic::ThreadFenceForConstructor();
-      if (bytes_tl_bulk_allocated > 0) {
-        size_t num_bytes_allocated_before =
-            num_bytes_allocated_.fetch_add(bytes_tl_bulk_allocated, std::memory_order_relaxed);
-        new_num_bytes_allocated = num_bytes_allocated_before + bytes_tl_bulk_allocated;
-        // Only trace when we get an increase in the number of bytes allocated. This happens when
-        // obtaining a new TLAB and isn't often enough to hurt performance according to golem.
-        if (region_space_) {
-          // With CC collector, during a GC cycle, the heap usage increases as
-          // there are two copies of evacuated objects. Therefore, add evac-bytes
-          // to the heap size. When the GC cycle is not running, evac-bytes
-          // are 0, as required.
-          TraceHeapSize(new_num_bytes_allocated + region_space_->EvacBytes());
-        } else {
-          TraceHeapSize(new_num_bytes_allocated);
-        }
+    }
+    if (bytes_tl_bulk_allocated > 0) {
+      starting_gc_num = GetCurrentGcNum();
+      size_t num_bytes_allocated_before =
+          num_bytes_allocated_.fetch_add(bytes_tl_bulk_allocated, std::memory_order_relaxed);
+      new_num_bytes_allocated = num_bytes_allocated_before + bytes_tl_bulk_allocated;
+      // Only trace when we get an increase in the number of bytes allocated. This happens when
+      // obtaining a new TLAB and isn't often enough to hurt performance according to golem.
+      if (region_space_) {
+        // With CC collector, during a GC cycle, the heap usage increases as
+        // there are two copies of evacuated objects. Therefore, add evac-bytes
+        // to the heap size. When the GC cycle is not running, evac-bytes
+        // are 0, as required.
+        TraceHeapSize(new_num_bytes_allocated + region_space_->EvacBytes());
+      } else {
+        TraceHeapSize(new_num_bytes_allocated);
       }
+      // IsGcConcurrent() isn't known at compile time so we can optimize by not checking it for the
+      // BumpPointer or TLAB allocators. This is nice since it allows the entire if statement to be
+      // optimized out. And for the other allocators, AllocatorMayHaveConcurrentGC is a constant
+      // since the allocator_type should be constant propagated.
+      if (AllocatorMayHaveConcurrentGC(allocator) && IsGcConcurrent()
+          && UNLIKELY(ShouldConcurrentGCForJava(new_num_bytes_allocated))) {
+        need_gc = true;
+      }
+      GetMetrics()->TotalBytesAllocated()->Add(bytes_tl_bulk_allocated);
     }
   }
   if (kIsDebugBuild && Runtime::Current()->IsStarted()) {
@@ -240,14 +257,9 @@
   } else {
     DCHECK(!gc_stress_mode_);
   }
-  // IsGcConcurrent() isn't known at compile time so we can optimize by not checking it for
-  // the BumpPointer or TLAB allocators. This is nice since it allows the entire if statement to be
-  // optimized out. And for the other allocators, AllocatorMayHaveConcurrentGC is a constant since
-  // the allocator_type should be constant propagated.
-  if (AllocatorMayHaveConcurrentGC(allocator) && IsGcConcurrent()) {
-    // New_num_bytes_allocated is zero if we didn't update num_bytes_allocated_.
-    // That's fine.
-    CheckConcurrentGCForJava(self, new_num_bytes_allocated, &obj);
+  if (need_gc) {
+    // Do this only once thread suspension is allowed again, and we're done with kInstrumented.
+    RequestConcurrentGCAndSaveObject(self, /*force_full=*/ false, starting_gc_num, &obj);
   }
   VerifyObject(obj);
   self->VerifyStack();
@@ -275,9 +287,11 @@
   // Save and restore the class in case it moves.
   StackHandleScope<1> hs(self);
   auto klass_wrapper = hs.NewHandleWrapper(klass);
-  return AllocObjectWithAllocator<kInstrumented, false, PreFenceVisitor>(self, *klass, byte_count,
-                                                                         kAllocatorTypeLOS,
-                                                                         pre_fence_visitor);
+  mirror::Object* obj = AllocObjectWithAllocator<kInstrumented, false, PreFenceVisitor>
+                        (self, *klass, byte_count, kAllocatorTypeLOS, pre_fence_visitor);
+  // Java Heap Profiler check and sample allocation.
+  JHPCheckNonTlabSampleAllocation(self, obj, byte_count);
+  return obj;
 }
 
 template <const bool kInstrumented, const bool kGrow>
@@ -393,9 +407,8 @@
       static_assert(kObjectAlignment == space::BumpPointerSpace::kAlignment,
                     "mismatched alignments");
       if (UNLIKELY(self->TlabSize() < alloc_size)) {
-        // kAllocatorTypeTLAB may be the allocator for region space TLAB if the GC is not marking,
-        // that is why the allocator is not passed down.
         return AllocWithNewTLAB(self,
+                                allocator_type,
                                 alloc_size,
                                 kGrow,
                                 bytes_allocated,
@@ -464,14 +477,6 @@
   return new_num_bytes_allocated >= concurrent_start_bytes_;
 }
 
-inline void Heap::CheckConcurrentGCForJava(Thread* self,
-                                    size_t new_num_bytes_allocated,
-                                    ObjPtr<mirror::Object>* obj) {
-  if (UNLIKELY(ShouldConcurrentGCForJava(new_num_bytes_allocated))) {
-    RequestConcurrentGCAndSaveObject(self, false /* force_full */, obj);
-  }
-}
-
 }  // namespace gc
 }  // namespace art
 
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index be3b7f8..08aaaef 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -42,7 +42,7 @@
 #include "base/systrace.h"
 #include "base/time_utils.h"
 #include "base/utils.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_throws.h"
 #include "debugger.h"
 #include "dex/dex_file-inl.h"
@@ -92,8 +92,12 @@
 #include "mirror/var_handle.h"
 #include "nativehelper/scoped_local_ref.h"
 #include "obj_ptr-inl.h"
+#ifdef ART_TARGET_ANDROID
+#include "perfetto/heap_profile.h"
+#endif
 #include "reflection.h"
 #include "runtime.h"
+#include "javaheapprof/javaheapsampler.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread_list.h"
 #include "verify_object-inl.h"
@@ -101,6 +105,36 @@
 
 namespace art {
 
+#ifdef ART_TARGET_ANDROID
+namespace {
+
+// Enable the heap sampler Callback function used by Perfetto.
+void EnableHeapSamplerCallback(void* enable_ptr,
+                               const AHeapProfileEnableCallbackInfo* enable_info_ptr) {
+  HeapSampler* sampler_self = reinterpret_cast<HeapSampler*>(enable_ptr);
+  // Set the ART profiler sampling interval to the value from Perfetto.
+  uint64_t interval = AHeapProfileEnableCallbackInfo_getSamplingInterval(enable_info_ptr);
+  if (interval > 0) {
+    sampler_self->SetSamplingInterval(interval);
+  }
+  // Else default is 4K sampling interval. However, default case shouldn't happen for Perfetto API.
+  // AHeapProfileEnableCallbackInfo_getSamplingInterval should always give the requested
+  // (non-negative) sampling interval. It is a uint64_t and gets checked for != 0
+  // Do not call heap as a temp here, it will build but test run will silently fail.
+  // Heap is not fully constructed yet in some cases.
+  sampler_self->EnableHeapSampler();
+}
+
+// Disable the heap sampler Callback function used by Perfetto.
+void DisableHeapSamplerCallback(void* disable_ptr,
+                                const AHeapProfileDisableCallbackInfo* info_ptr ATTRIBUTE_UNUSED) {
+  HeapSampler* sampler_self = reinterpret_cast<HeapSampler*>(disable_ptr);
+  sampler_self->DisableHeapSampler();
+}
+
+}  // namespace
+#endif
+
 namespace gc {
 
 DEFINE_RUNTIME_DEBUG_FLAG(Heap, kStressCollectorTransition);
@@ -137,6 +171,10 @@
 static constexpr size_t kDefaultAllocationStackSize = 8 * MB /
     sizeof(mirror::HeapReference<mirror::Object>);
 
+// After a GC (due to allocation failure) we should retrieve at least this
+// fraction of the current max heap size. Otherwise throw OOME.
+static constexpr double kMinFreeHeapAfterGcForAlloc = 0.01;
+
 // For deterministic compilation, we need the heap to be at a well-known address.
 static constexpr uint32_t kAllocSpaceBeginForDeterministicAoT = 0x40000000;
 // Dump the rosalloc stats on SIGQUIT.
@@ -230,6 +268,7 @@
            size_t long_pause_log_threshold,
            size_t long_gc_log_threshold,
            bool ignore_target_footprint,
+           bool always_log_explicit_gcs,
            bool use_tlab,
            bool verify_pre_gc_heap,
            bool verify_pre_sweeping_heap,
@@ -243,8 +282,7 @@
            bool use_generational_cc,
            uint64_t min_interval_homogeneous_space_compaction_by_oom,
            bool dump_region_info_before_gc,
-           bool dump_region_info_after_gc,
-           space::ImageSpaceLoadingOrder image_space_loading_order)
+           bool dump_region_info_after_gc)
     : non_moving_space_(nullptr),
       rosalloc_space_(nullptr),
       dlmalloc_space_(nullptr),
@@ -265,6 +303,7 @@
       pre_gc_weighted_allocated_bytes_(0.0),
       post_gc_weighted_allocated_bytes_(0.0),
       ignore_target_footprint_(ignore_target_footprint),
+      always_log_explicit_gcs_(always_log_explicit_gcs),
       zygote_creation_lock_("zygote creation lock", kZygoteCreationLock),
       zygote_space_(nullptr),
       large_object_threshold_(large_object_threshold),
@@ -331,6 +370,8 @@
       min_interval_homogeneous_space_compaction_by_oom_(
           min_interval_homogeneous_space_compaction_by_oom),
       last_time_homogeneous_space_compaction_by_oom_(NanoTime()),
+      gcs_completed_(0u),
+      max_gc_requested_(0u),
       pending_collector_transition_(nullptr),
       pending_heap_trim_(nullptr),
       use_homogeneous_space_compaction_for_oom_(use_homogeneous_space_compaction_for_oom),
@@ -417,10 +458,8 @@
                                        boot_class_path_locations,
                                        image_file_name,
                                        image_instruction_set,
-                                       image_space_loading_order,
                                        runtime->ShouldRelocate(),
                                        /*executable=*/ !runtime->IsAotCompiler(),
-                                       is_zygote,
                                        heap_reservation_size,
                                        &boot_image_spaces,
                                        &heap_reservation)) {
@@ -708,7 +747,8 @@
             "young",
             measure_gc_performance);
       }
-      active_concurrent_copying_collector_ = concurrent_copying_collector_;
+      active_concurrent_copying_collector_.store(concurrent_copying_collector_,
+                                                 std::memory_order_relaxed);
       DCHECK(region_space_ != nullptr);
       concurrent_copying_collector_->SetRegionSpace(region_space_);
       if (use_generational_cc_) {
@@ -742,6 +782,15 @@
       LOG(FATAL) << "There's a gap between the image space and the non-moving space";
     }
   }
+  // Perfetto Java Heap Profiler Support.
+  if (runtime->IsPerfettoJavaHeapStackProfEnabled()) {
+    // Perfetto Plugin is loaded and enabled, initialize the Java Heap Profiler.
+    InitPerfettoJavaHeapProf();
+  } else {
+    // Disable the Java Heap Profiler.
+    GetHeapSampler().DisableHeapSampler();
+  }
+
   instrumentation::Instrumentation* const instrumentation = runtime->GetInstrumentation();
   if (gc_stress_mode_) {
     backtrace_lock_ = new Mutex("GC complete lock");
@@ -901,8 +950,9 @@
   MutexLock mu(self, *thread_flip_lock_);
   thread_flip_cond_->CheckSafeToWait(self);
   bool has_waited = false;
-  uint64_t wait_start = NanoTime();
+  uint64_t wait_start = 0;
   if (thread_flip_running_) {
+    wait_start = NanoTime();
     ScopedTrace trace("IncrementDisableThreadFlip");
     while (thread_flip_running_) {
       has_waited = true;
@@ -1394,8 +1444,22 @@
                allocator_type == kAllocatorTypeRegionTLAB) {
       space = region_space_;
     }
-    if (space != nullptr) {
-      space->LogFragmentationAllocFailure(oss, byte_count);
+
+    // There is no fragmentation info to log for large-object space.
+    if (allocator_type != kAllocatorTypeLOS) {
+      CHECK(space != nullptr) << "allocator_type:" << allocator_type
+                              << " byte_count:" << byte_count
+                              << " total_bytes_free:" << total_bytes_free;
+      // LogFragmentationAllocFailure returns true if byte_count is greater than
+      // the largest free contiguous chunk in the space. Return value false
+      // means that we are throwing OOME because the amount of free heap after
+      // GC is less than kMinFreeHeapAfterGcForAlloc in proportion of the heap-size.
+      // Log an appropriate message in that case.
+      if (!space->LogFragmentationAllocFailure(oss, byte_count)) {
+        oss << "; giving up on allocation because <"
+            << kMinFreeHeapAfterGcForAlloc * 100
+            << "% of heap free after GC.";
+      }
     }
   }
   self->ThrowOutOfMemoryError(oss.str().c_str());
@@ -1416,7 +1480,7 @@
       // Invoke CC full compaction.
       CollectGarbageInternal(collector::kGcTypeFull,
                              kGcCauseCollectorTransition,
-                             /*clear_soft_references=*/false);
+                             /*clear_soft_references=*/false, GC_NUM_ANY);
     } else {
       VLOG(gc) << "CC background compaction ignored due to jank perceptible process state";
     }
@@ -1772,6 +1836,7 @@
       (!instrumented && EntrypointsInstrumented())) {
     return nullptr;
   }
+  uint32_t starting_gc_num = GetCurrentGcNum();
   if (last_gc != collector::kGcTypeNone) {
     // A GC was in progress and we blocked, retry allocation now that memory has been freed.
     mirror::Object* ptr = TryToAllocate<true, false>(self, allocator, alloc_size, bytes_allocated,
@@ -1781,50 +1846,37 @@
     }
   }
 
+  auto have_reclaimed_enough = [&]() {
+    size_t curr_bytes_allocated = GetBytesAllocated();
+    double curr_free_heap =
+        static_cast<double>(growth_limit_ - curr_bytes_allocated) / growth_limit_;
+    return curr_free_heap >= kMinFreeHeapAfterGcForAlloc;
+  };
+  // We perform one GC as per the next_gc_type_ (chosen in GrowForUtilization),
+  // if it's not already tried. If that doesn't succeed then go for the most
+  // exhaustive option. Perform a full-heap collection including clearing
+  // SoftReferences. In case of ConcurrentCopying, it will also ensure that
+  // all regions are evacuated. If allocation doesn't succeed even after that
+  // then there is no hope, so we throw OOME.
   collector::GcType tried_type = next_gc_type_;
-  const bool gc_ran = PERFORM_SUSPENDING_OPERATION(
-      CollectGarbageInternal(tried_type, kGcCauseForAlloc, false) != collector::kGcTypeNone);
+  if (last_gc < tried_type) {
+    const bool gc_ran = PERFORM_SUSPENDING_OPERATION(
+        CollectGarbageInternal(tried_type, kGcCauseForAlloc, false, starting_gc_num + 1)
+        != collector::kGcTypeNone);
 
-  if ((was_default_allocator && allocator != GetCurrentAllocator()) ||
-      (!instrumented && EntrypointsInstrumented())) {
-    return nullptr;
-  }
-  if (gc_ran) {
-    mirror::Object* ptr = TryToAllocate<true, false>(self, allocator, alloc_size, bytes_allocated,
-                                                     usable_size, bytes_tl_bulk_allocated);
-    if (ptr != nullptr) {
-      return ptr;
-    }
-  }
-
-  // Loop through our different Gc types and try to Gc until we get enough free memory.
-  for (collector::GcType gc_type : gc_plan_) {
-    if (gc_type == tried_type) {
-      continue;
-    }
-    // Attempt to run the collector, if we succeed, re-try the allocation.
-    const bool plan_gc_ran = PERFORM_SUSPENDING_OPERATION(
-        CollectGarbageInternal(gc_type, kGcCauseForAlloc, false) != collector::kGcTypeNone);
     if ((was_default_allocator && allocator != GetCurrentAllocator()) ||
         (!instrumented && EntrypointsInstrumented())) {
       return nullptr;
     }
-    if (plan_gc_ran) {
-      // Did we free sufficient memory for the allocation to succeed?
-      mirror::Object* ptr = TryToAllocate<true, false>(self, allocator, alloc_size, bytes_allocated,
+    if (gc_ran && have_reclaimed_enough()) {
+      mirror::Object* ptr = TryToAllocate<true, false>(self, allocator,
+                                                       alloc_size, bytes_allocated,
                                                        usable_size, bytes_tl_bulk_allocated);
       if (ptr != nullptr) {
         return ptr;
       }
     }
   }
-  // Allocations have failed after GCs;  this is an exceptional state.
-  // Try harder, growing the heap if necessary.
-  mirror::Object* ptr = TryToAllocate<true, true>(self, allocator, alloc_size, bytes_allocated,
-                                                  usable_size, bytes_tl_bulk_allocated);
-  if (ptr != nullptr) {
-    return ptr;
-  }
   // Most allocations should have succeeded by now, so the heap is really full, really fragmented,
   // or the requested size is really big. Do another GC, collecting SoftReferences this time. The
   // VM spec requires that all SoftReferences have been collected and cleared before throwing
@@ -1833,14 +1885,21 @@
            << " allocation";
   // TODO: Run finalization, but this may cause more allocations to occur.
   // We don't need a WaitForGcToComplete here either.
+  // TODO: Should check whether another thread already just ran a GC with soft
+  // references.
   DCHECK(!gc_plan_.empty());
-  PERFORM_SUSPENDING_OPERATION(CollectGarbageInternal(gc_plan_.back(), kGcCauseForAlloc, true));
+  PERFORM_SUSPENDING_OPERATION(
+      CollectGarbageInternal(gc_plan_.back(), kGcCauseForAlloc, true, GC_NUM_ANY));
   if ((was_default_allocator && allocator != GetCurrentAllocator()) ||
       (!instrumented && EntrypointsInstrumented())) {
     return nullptr;
   }
-  ptr = TryToAllocate<true, true>(self, allocator, alloc_size, bytes_allocated, usable_size,
-                                  bytes_tl_bulk_allocated);
+  mirror::Object* ptr = nullptr;
+  if (have_reclaimed_enough()) {
+    ptr = TryToAllocate<true, true>(self, allocator, alloc_size, bytes_allocated,
+                                    usable_size, bytes_tl_bulk_allocated);
+  }
+
   if (ptr == nullptr) {
     const uint64_t current_time = NanoTime();
     switch (allocator) {
@@ -1983,71 +2042,10 @@
   VisitObjects(instance_counter);
 }
 
-void Heap::GetInstances(VariableSizedHandleScope& scope,
-                        Handle<mirror::Class> h_class,
-                        bool use_is_assignable_from,
-                        int32_t max_count,
-                        std::vector<Handle<mirror::Object>>& instances) {
-  DCHECK_GE(max_count, 0);
-  auto instance_collector = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (MatchesClass(obj, h_class, use_is_assignable_from)) {
-      if (max_count == 0 || instances.size() < static_cast<size_t>(max_count)) {
-        instances.push_back(scope.NewHandle(obj));
-      }
-    }
-  };
-  VisitObjects(instance_collector);
-}
-
-void Heap::GetReferringObjects(VariableSizedHandleScope& scope,
-                               Handle<mirror::Object> o,
-                               int32_t max_count,
-                               std::vector<Handle<mirror::Object>>& referring_objects) {
-  class ReferringObjectsFinder {
-   public:
-    ReferringObjectsFinder(VariableSizedHandleScope& scope_in,
-                           Handle<mirror::Object> object_in,
-                           int32_t max_count_in,
-                           std::vector<Handle<mirror::Object>>& referring_objects_in)
-        REQUIRES_SHARED(Locks::mutator_lock_)
-        : scope_(scope_in),
-          object_(object_in),
-          max_count_(max_count_in),
-          referring_objects_(referring_objects_in) {}
-
-    // For Object::VisitReferences.
-    void operator()(ObjPtr<mirror::Object> obj,
-                    MemberOffset offset,
-                    bool is_static ATTRIBUTE_UNUSED) const
-        REQUIRES_SHARED(Locks::mutator_lock_) {
-      mirror::Object* ref = obj->GetFieldObject<mirror::Object>(offset);
-      if (ref == object_.Get() && (max_count_ == 0 || referring_objects_.size() < max_count_)) {
-        referring_objects_.push_back(scope_.NewHandle(obj));
-      }
-    }
-
-    void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED)
-        const {}
-    void VisitRoot(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const {}
-
-   private:
-    VariableSizedHandleScope& scope_;
-    Handle<mirror::Object> const object_;
-    const uint32_t max_count_;
-    std::vector<Handle<mirror::Object>>& referring_objects_;
-    DISALLOW_COPY_AND_ASSIGN(ReferringObjectsFinder);
-  };
-  ReferringObjectsFinder finder(scope, o, max_count, referring_objects);
-  auto referring_objects_finder = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
-    obj->VisitReferences(finder, VoidFunctor());
-  };
-  VisitObjects(referring_objects_finder);
-}
-
 void Heap::CollectGarbage(bool clear_soft_references, GcCause cause) {
   // Even if we waited for a GC we still need to do another GC since weaks allocated during the
   // last GC will not have necessarily been cleared.
-  CollectGarbageInternal(gc_plan_.back(), cause, clear_soft_references);
+  CollectGarbageInternal(gc_plan_.back(), cause, clear_soft_references, GC_NUM_ANY);
 }
 
 bool Heap::SupportHomogeneousSpaceCompactAndCollectorTransitions() const {
@@ -2247,8 +2245,9 @@
     if (it == bins_.end()) {
       // No available space in the bins, place it in the target space instead (grows the zygote
       // space).
-      size_t bytes_allocated, dummy;
-      forward_address = to_space_->Alloc(self_, alloc_size, &bytes_allocated, nullptr, &dummy);
+      size_t bytes_allocated, unused_bytes_tl_bulk_allocated;
+      forward_address = to_space_->Alloc(
+          self_, alloc_size, &bytes_allocated, nullptr, &unused_bytes_tl_bulk_allocated);
       if (to_space_live_bitmap_ != nullptr) {
         to_space_live_bitmap_->Set(forward_address);
       } else {
@@ -2313,7 +2312,7 @@
   if (!HasZygoteSpace()) {
     // We still want to GC in case there is some unreachable non moving objects that could cause a
     // suboptimal bin packing when we compact the zygote space.
-    CollectGarbageInternal(collector::kGcTypeFull, kGcCauseBackground, false);
+    CollectGarbageInternal(collector::kGcTypeFull, kGcCauseBackground, false, GC_NUM_ANY);
     // Trim the pages at the end of the non moving space. Trim while not holding zygote lock since
     // the trim process may require locking the mutator lock.
     non_moving_space_->Trim();
@@ -2399,7 +2398,7 @@
   // the old alloc space's bitmaps to null.
   RemoveSpace(old_alloc_space);
   if (collector::SemiSpace::kUseRememberedSet) {
-    // Sanity bound check.
+    // Consistency bound check.
     FindRememberedSetFromSpace(old_alloc_space)->AssertAllDirtyCardsAreWithinSpace();
     // Remove the remembered set for the now zygote space (the old
     // non-moving space). Note now that we have compacted objects into
@@ -2570,15 +2569,25 @@
   // other things. It seems risky to trigger GCs as a result of such changes.
 }
 
+static inline bool GCNumberLt(uint32_t gc_num1, uint32_t gc_num2) {
+  // unsigned comparison, assuming a non-huge difference, but dealing correctly with wrapping.
+  uint32_t difference = gc_num2 - gc_num1;
+  bool completed_more_than_requested = difference > 0x80000000;
+  return difference > 0 && !completed_more_than_requested;
+}
+
+
 collector::GcType Heap::CollectGarbageInternal(collector::GcType gc_type,
                                                GcCause gc_cause,
-                                               bool clear_soft_references) {
+                                               bool clear_soft_references,
+                                               uint32_t requested_gc_num) {
   Thread* self = Thread::Current();
   Runtime* runtime = Runtime::Current();
   // If the heap can't run the GC, silently fail and return that no GC was run.
   switch (gc_type) {
     case collector::kGcTypePartial: {
       if (!HasZygoteSpace()) {
+        // Do not increment gcs_completed_ . We should retry with kGcTypeFull.
         return collector::kGcTypeNone;
       }
       break;
@@ -2593,6 +2602,8 @@
   if (self->IsHandlingStackOverflow()) {
     // If we are throwing a stack overflow error we probably don't have enough remaining stack
     // space to run the GC.
+    // Count this as a GC in case someone is waiting for it to complete.
+    gcs_completed_.fetch_add(1, std::memory_order_release);
     return collector::kGcTypeNone;
   }
   bool compacting_gc;
@@ -2602,16 +2613,24 @@
     MutexLock mu(self, *gc_complete_lock_);
     // Ensure there is only one GC at a time.
     WaitForGcToCompleteLocked(gc_cause, self);
+    if (requested_gc_num != GC_NUM_ANY && !GCNumberLt(GetCurrentGcNum(), requested_gc_num)) {
+      // The appropriate GC was already triggered elsewhere.
+      return collector::kGcTypeNone;
+    }
     compacting_gc = IsMovingGc(collector_type_);
     // GC can be disabled if someone has a used GetPrimitiveArrayCritical.
     if (compacting_gc && disable_moving_gc_count_ != 0) {
       LOG(WARNING) << "Skipping GC due to disable moving GC count " << disable_moving_gc_count_;
+      // Again count this as a GC.
+      gcs_completed_.fetch_add(1, std::memory_order_release);
       return collector::kGcTypeNone;
     }
     if (gc_disabled_for_shutdown_) {
+      gcs_completed_.fetch_add(1, std::memory_order_release);
       return collector::kGcTypeNone;
     }
     collector_type_running_ = collector_type_;
+    last_gc_cause_ = gc_cause;
   }
   if (gc_cause == kGcCauseForAlloc && runtime->HasStatsEnabled()) {
     ++runtime->GetStats()->gc_for_alloc_count;
@@ -2637,19 +2656,24 @@
         collector = semi_space_collector_;
         break;
       case kCollectorTypeCC:
+        collector::ConcurrentCopying* active_cc_collector;
         if (use_generational_cc_) {
           // TODO: Other threads must do the flip checkpoint before they start poking at
           // active_concurrent_copying_collector_. So we should not concurrency here.
-          active_concurrent_copying_collector_ = (gc_type == collector::kGcTypeSticky) ?
-              young_concurrent_copying_collector_ : concurrent_copying_collector_;
-          DCHECK(active_concurrent_copying_collector_->RegionSpace() == region_space_);
+          active_cc_collector = (gc_type == collector::kGcTypeSticky) ?
+                  young_concurrent_copying_collector_ : concurrent_copying_collector_;
+          active_concurrent_copying_collector_.store(active_cc_collector,
+                                                     std::memory_order_relaxed);
+          DCHECK(active_cc_collector->RegionSpace() == region_space_);
+          collector = active_cc_collector;
+        } else {
+          collector = active_concurrent_copying_collector_.load(std::memory_order_relaxed);
         }
-        collector = active_concurrent_copying_collector_;
         break;
       default:
         LOG(FATAL) << "Invalid collector type " << static_cast<size_t>(collector_type_);
     }
-    if (collector != active_concurrent_copying_collector_) {
+    if (collector != active_concurrent_copying_collector_.load(std::memory_order_relaxed)) {
       temp_space_->GetMemMap()->Protect(PROT_READ | PROT_WRITE);
       if (kIsDebugBuild) {
         // Try to read each page of the memory map in case mprotect didn't work properly b/19894268.
@@ -2675,6 +2699,7 @@
   SelfDeletingTask* clear = reference_processor_->CollectClearedReferences(self);
   // Grow the heap so that we know when to perform the next GC.
   GrowForUtilization(collector, bytes_allocated_before_gc);
+  old_native_bytes_allocated_.store(GetNativeBytes());
   LogGC(gc_cause, collector);
   FinishGC(self, gc_type);
   // Actually enqueue all cleared references. Do this after the GC has officially finished since
@@ -2684,8 +2709,6 @@
   // Inform DDMS that a GC completed.
   Dbg::GcDidFinish();
 
-  old_native_bytes_allocated_.store(GetNativeBytes());
-
   // Unload native libraries for class unloading. We do this after calling FinishGC to prevent
   // deadlocks in case the JNI_OnUnload function does allocations.
   {
@@ -2700,7 +2723,7 @@
   const std::vector<uint64_t>& pause_times = GetCurrentGcIteration()->GetPauseTimes();
   // Print the GC if it is an explicit GC (e.g. Runtime.gc()) or a slow GC
   // (mutator time blocked >= long_pause_log_threshold_).
-  bool log_gc = kLogAllGCs || gc_cause == kGcCauseExplicit;
+  bool log_gc = kLogAllGCs || (gc_cause == kGcCauseExplicit && always_log_explicit_gcs_);
   if (!log_gc && CareAboutPauseTimes()) {
     // GC for alloc pauses the allocating thread, so consider it as a pause.
     log_gc = duration > long_gc_log_threshold_ ||
@@ -2751,6 +2774,9 @@
   // Reset.
   running_collection_is_blocking_ = false;
   thread_running_gc_ = nullptr;
+  if (gc_type != collector::kGcTypeNone) {
+    gcs_completed_.fetch_add(1, std::memory_order_release);
+  }
   // Wake anyone who may have been waiting for the GC to complete.
   gc_complete_cond_->Broadcast(self);
 }
@@ -3013,7 +3039,10 @@
     // to heap verification requiring that roots are live (either in the live bitmap or in the
     // allocation stack).
     CHECK(allocation_stack_->AtomicPushBackIgnoreGrowthLimit(obj->Ptr()));
-    CollectGarbageInternal(collector::kGcTypeSticky, kGcCauseForAlloc, false);
+    CollectGarbageInternal(collector::kGcTypeSticky,
+                           kGcCauseForAlloc,
+                           false,
+                           GetCurrentGcNum() + 1);
   } while (!allocation_stack_->AtomicPushBack(obj->Ptr()));
 }
 
@@ -3033,7 +3062,10 @@
     // allocation stack).
     CHECK(allocation_stack_->AtomicPushBackIgnoreGrowthLimit(obj->Ptr()));
     // Push into the reserve allocation stack.
-    CollectGarbageInternal(collector::kGcTypeSticky, kGcCauseForAlloc, false);
+    CollectGarbageInternal(collector::kGcTypeSticky,
+                           kGcCauseForAlloc,
+                           false,
+                           GetCurrentGcNum() + 1);
   }
   self->SetThreadLocalAllocationStack(start_address, end_address);
   // Retry on the new thread-local allocation stack.
@@ -3454,7 +3486,6 @@
     // Don't log fake "GC" types that are only used for debugger or hidden APIs. If we log these,
     // it results in log spam. kGcCauseExplicit is already logged in LogGC, so avoid it here too.
     if (cause == kGcCauseForAlloc ||
-        cause == kGcCauseForNativeAlloc ||
         cause == kGcCauseDisableMovingGc) {
       VLOG(gc) << "Starting a blocking GC " << cause;
     }
@@ -3588,9 +3619,9 @@
           current_gc_iteration_.GetFreedRevokeBytes();
       // Bytes allocated will shrink by freed_bytes after the GC runs, so if we want to figure out
       // how many bytes were allocated during the GC we need to add freed_bytes back on.
-      CHECK_GE(bytes_allocated + freed_bytes, bytes_allocated_before_gc);
-      const size_t bytes_allocated_during_gc = bytes_allocated + freed_bytes -
-          bytes_allocated_before_gc;
+      // Almost always bytes_allocated + freed_bytes >= bytes_allocated_before_gc.
+      const size_t bytes_allocated_during_gc =
+          UnsignedDifference(bytes_allocated + freed_bytes, bytes_allocated_before_gc);
       // Calculate when to perform the next ConcurrentGC.
       // Estimate how many remaining bytes we will have when we need to start the next GC.
       size_t remaining_bytes = bytes_allocated_during_gc;
@@ -3669,25 +3700,29 @@
 
 void Heap::RequestConcurrentGCAndSaveObject(Thread* self,
                                             bool force_full,
+                                            uint32_t observed_gc_num,
                                             ObjPtr<mirror::Object>* obj) {
   StackHandleScope<1> hs(self);
   HandleWrapperObjPtr<mirror::Object> wrapper(hs.NewHandleWrapper(obj));
-  RequestConcurrentGC(self, kGcCauseBackground, force_full);
+  RequestConcurrentGC(self, kGcCauseBackground, force_full, observed_gc_num);
 }
 
 class Heap::ConcurrentGCTask : public HeapTask {
  public:
-  ConcurrentGCTask(uint64_t target_time, GcCause cause, bool force_full)
-      : HeapTask(target_time), cause_(cause), force_full_(force_full) {}
+  ConcurrentGCTask(uint64_t target_time, GcCause cause, bool force_full, uint32_t gc_num)
+      : HeapTask(target_time), cause_(cause), force_full_(force_full), my_gc_num_(gc_num) {}
   void Run(Thread* self) override {
-    gc::Heap* heap = Runtime::Current()->GetHeap();
-    heap->ConcurrentGC(self, cause_, force_full_);
-    heap->ClearConcurrentGCRequest();
+    Runtime* runtime = Runtime::Current();
+    gc::Heap* heap = runtime->GetHeap();
+    DCHECK(GCNumberLt(my_gc_num_, heap->GetCurrentGcNum() + 2));  // <= current_gc_num + 1
+    heap->ConcurrentGC(self, cause_, force_full_, my_gc_num_);
+    CHECK(!GCNumberLt(heap->GetCurrentGcNum(), my_gc_num_) || runtime->IsShuttingDown(self));
   }
 
  private:
   const GcCause cause_;
   const bool force_full_;  // If true, force full (or partial) collection.
+  const uint32_t my_gc_num_;  // Sequence number of requested GC.
 };
 
 static bool CanAddHeapTask(Thread* self) REQUIRES(!Locks::runtime_shutdown_lock_) {
@@ -3696,35 +3731,58 @@
       !self->IsHandlingStackOverflow();
 }
 
-void Heap::ClearConcurrentGCRequest() {
-  concurrent_gc_pending_.store(false, std::memory_order_relaxed);
-}
-
-void Heap::RequestConcurrentGC(Thread* self, GcCause cause, bool force_full) {
-  if (CanAddHeapTask(self) &&
-      concurrent_gc_pending_.CompareAndSetStrongSequentiallyConsistent(false, true)) {
-    task_processor_->AddTask(self, new ConcurrentGCTask(NanoTime(),  // Start straight away.
-                                                        cause,
-                                                        force_full));
+bool Heap::RequestConcurrentGC(Thread* self,
+                               GcCause cause,
+                               bool force_full,
+                               uint32_t observed_gc_num) {
+  uint32_t max_gc_requested = max_gc_requested_.load(std::memory_order_relaxed);
+  if (!GCNumberLt(observed_gc_num, max_gc_requested)) {
+    // observed_gc_num >= max_gc_requested: Nobody beat us to requesting the next gc.
+    if (CanAddHeapTask(self)) {
+      // Since observed_gc_num >= max_gc_requested, this increases max_gc_requested_, if successful.
+      if (max_gc_requested_.CompareAndSetStrongRelaxed(max_gc_requested, observed_gc_num + 1)) {
+        task_processor_->AddTask(self, new ConcurrentGCTask(NanoTime(),  // Start straight away.
+                                                            cause,
+                                                            force_full,
+                                                            observed_gc_num + 1));
+      }
+      DCHECK(GCNumberLt(observed_gc_num, max_gc_requested_.load(std::memory_order_relaxed)));
+      // If we increased max_gc_requested_, then we added a task that will eventually cause
+      // gcs_completed_ to be incremented (to at least observed_gc_num + 1).
+      // If the CAS failed, somebody else did.
+      return true;
+    }
+    return false;
   }
+  return true;  // Vacuously.
 }
 
-void Heap::ConcurrentGC(Thread* self, GcCause cause, bool force_full) {
+void Heap::ConcurrentGC(Thread* self, GcCause cause, bool force_full, uint32_t requested_gc_num) {
   if (!Runtime::Current()->IsShuttingDown(self)) {
-    // Wait for any GCs currently running to finish.
-    if (WaitForGcToComplete(cause, self) == collector::kGcTypeNone) {
-      // 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.
+    // Wait for any GCs currently running to finish. If this incremented GC number, we're done.
+    WaitForGcToComplete(cause, self);
+    if (GCNumberLt(GetCurrentGcNum(), requested_gc_num)) {
       collector::GcType next_gc_type = next_gc_type_;
       // If forcing full and next gc type is sticky, override with a non-sticky type.
       if (force_full && next_gc_type == collector::kGcTypeSticky) {
         next_gc_type = NonStickyGcType();
       }
-      if (CollectGarbageInternal(next_gc_type, cause, false) == collector::kGcTypeNone) {
+      // 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.
+      // We must ensure that we run something that ends up inrementing gcs_completed_.
+      // In the kGcTypePartial case, the initial CollectGarbageInternal call may not have that
+      // effect, but the subsequent KGcTypeFull call will.
+      if (CollectGarbageInternal(next_gc_type, cause, false, requested_gc_num)
+          == collector::kGcTypeNone) {
         for (collector::GcType gc_type : gc_plan_) {
+          if (!GCNumberLt(GetCurrentGcNum(), requested_gc_num)) {
+            // Somebody did it for us.
+            break;
+          }
           // Attempt to run the collector, if we succeed, we are done.
           if (gc_type > next_gc_type &&
-              CollectGarbageInternal(gc_type, cause, false) != collector::kGcTypeNone) {
+              CollectGarbageInternal(gc_type, cause, false, requested_gc_num)
+              != collector::kGcTypeNone) {
             break;
           }
         }
@@ -3765,7 +3823,7 @@
   const uint64_t target_time = NanoTime() + delta_time;
   {
     MutexLock mu(self, *pending_task_lock_);
-    // If we have an existing collector transition, update the targe time to be the new target.
+    // If we have an existing collector transition, update the target time to be the new target.
     if (pending_collector_transition_ != nullptr) {
       task_processor_->UpdateTargetRunTime(self, pending_collector_transition_, target_time);
       return;
@@ -3869,10 +3927,6 @@
   }
 }
 
-bool Heap::IsGCRequestPending() const {
-  return concurrent_gc_pending_.load(std::memory_order_relaxed);
-}
-
 void Heap::RunFinalization(JNIEnv* env, uint64_t timeout) {
   env->CallStaticVoidMethod(WellKnownClasses::dalvik_system_VMRuntime,
                             WellKnownClasses::dalvik_system_VMRuntime_runFinalization,
@@ -3926,21 +3980,27 @@
 
 inline void Heap::CheckGCForNative(Thread* self) {
   bool is_gc_concurrent = IsGcConcurrent();
+  uint32_t starting_gc_num = GetCurrentGcNum();
   size_t current_native_bytes = GetNativeBytes();
   float gc_urgency = NativeMemoryOverTarget(current_native_bytes, is_gc_concurrent);
   if (UNLIKELY(gc_urgency >= 1.0)) {
     if (is_gc_concurrent) {
-      RequestConcurrentGC(self, kGcCauseForNativeAlloc, /*force_full=*/true);
+      bool requested =
+          RequestConcurrentGC(self, kGcCauseForNativeAlloc, /*force_full=*/true, starting_gc_num);
       if (gc_urgency > kStopForNativeFactor
           && current_native_bytes > stop_for_native_allocs_) {
         // We're in danger of running out of memory due to rampant native allocation.
         if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
           LOG(INFO) << "Stopping for native allocation, urgency: " << gc_urgency;
         }
-        WaitForGcToComplete(kGcCauseForNativeAlloc, self);
+        if (WaitForGcToComplete(kGcCauseForNativeAlloc, self) == collector::kGcTypeNone) {
+          DCHECK(!requested
+                 || GCNumberLt(starting_gc_num, max_gc_requested_.load(std::memory_order_relaxed)));
+          // TODO: Eventually sleep here again.
+        }
       }
     } else {
-      CollectGarbageInternal(NonStickyGcType(), kGcCauseForNativeAlloc, false);
+      CollectGarbageInternal(NonStickyGcType(), kGcCauseForNativeAlloc, false, starting_gc_num + 1);
     }
   }
 }
@@ -4087,6 +4147,81 @@
   }
 }
 
+// Perfetto Java Heap Profiler Support.
+
+// Perfetto initialization.
+void Heap::InitPerfettoJavaHeapProf() {
+  // Initialize Perfetto Heap info and Heap id.
+  uint32_t heap_id = 1;  // Initialize to 1, to be overwritten by Perfetto heap id.
+#ifdef ART_TARGET_ANDROID
+  // Register the heap and create the heapid.
+  // Use a Perfetto heap name = "com.android.art" for the Java Heap Profiler.
+  AHeapInfo* info = AHeapInfo_create("com.android.art");
+  // Set the Enable Callback, there is no callback data ("nullptr").
+  AHeapInfo_setEnabledCallback(info, &EnableHeapSamplerCallback, &heap_sampler_);
+  // Set the Disable Callback.
+  AHeapInfo_setDisabledCallback(info, &DisableHeapSamplerCallback, &heap_sampler_);
+  heap_id = AHeapProfile_registerHeap(info);
+  // Do not enable the Java Heap Profiler in this case, wait for Perfetto to enable it through
+  // the callback function.
+#else
+  // This is the host case, enable the Java Heap Profiler for host testing.
+  // Perfetto API is currently not available on host.
+  heap_sampler_.EnableHeapSampler();
+#endif
+  heap_sampler_.SetHeapID(heap_id);
+  VLOG(heap) << "Java Heap Profiler Initialized";
+}
+
+// Check if the Java Heap Profiler is enabled and initialized.
+int Heap::CheckPerfettoJHPEnabled() {
+  return GetHeapSampler().IsEnabled();
+}
+
+void Heap::JHPCheckNonTlabSampleAllocation(Thread* self, mirror::Object* obj, size_t alloc_size) {
+  bool take_sample = false;
+  size_t bytes_until_sample = 0;
+  HeapSampler& prof_heap_sampler = GetHeapSampler();
+  if (obj != nullptr && prof_heap_sampler.IsEnabled()) {
+    // An allocation occurred, sample it, even if non-Tlab.
+    // In case take_sample is already set from the previous GetSampleOffset
+    // because we tried the Tlab allocation first, we will not use this value.
+    // A new value is generated below. Also bytes_until_sample will be updated.
+    // Note that we are not using the return value from the GetSampleOffset in
+    // the NonTlab case here.
+    prof_heap_sampler.GetSampleOffset(alloc_size,
+                                      self->GetTlabPosOffset(),
+                                      &take_sample,
+                                      &bytes_until_sample);
+    prof_heap_sampler.SetBytesUntilSample(bytes_until_sample);
+    if (take_sample) {
+      prof_heap_sampler.ReportSample(obj, alloc_size);
+    }
+    VLOG(heap) << "JHP:NonTlab Non-moving or Large Allocation";
+  }
+}
+
+size_t Heap::JHPCalculateNextTlabSize(Thread* self,
+                                      size_t jhp_def_tlab_size,
+                                      size_t alloc_size,
+                                      bool* take_sample,
+                                      size_t* bytes_until_sample) {
+  size_t next_tlab_size = jhp_def_tlab_size;
+  if (CheckPerfettoJHPEnabled()) {
+    size_t next_sample_point =
+        GetHeapSampler().GetSampleOffset(alloc_size,
+                                         self->GetTlabPosOffset(),
+                                         take_sample,
+                                         bytes_until_sample);
+    next_tlab_size = std::min(next_sample_point, jhp_def_tlab_size);
+  }
+  return next_tlab_size;
+}
+
+void Heap::AdjustSampleOffset(size_t adjustment) {
+  GetHeapSampler().AdjustSampleOffset(adjustment);
+}
+
 void Heap::CheckGcStressMode(Thread* self, ObjPtr<mirror::Object>* obj) {
   DCHECK(gc_stress_mode_);
   auto* const runtime = Runtime::Current();
@@ -4167,20 +4302,29 @@
 }
 
 mirror::Object* Heap::AllocWithNewTLAB(Thread* self,
+                                       AllocatorType allocator_type,
                                        size_t alloc_size,
                                        bool grow,
                                        size_t* bytes_allocated,
                                        size_t* usable_size,
                                        size_t* bytes_tl_bulk_allocated) {
-  const AllocatorType allocator_type = GetCurrentAllocator();
+  mirror::Object* ret = nullptr;
+  bool take_sample = false;
+  size_t bytes_until_sample = 0;
+
   if (kUsePartialTlabs && alloc_size <= self->TlabRemainingCapacity()) {
     DCHECK_GT(alloc_size, self->TlabSize());
     // There is enough space if we grow the TLAB. Lets do that. This increases the
     // TLAB bytes.
     const size_t min_expand_size = alloc_size - self->TlabSize();
+    size_t next_tlab_size = JHPCalculateNextTlabSize(self,
+                                                     kPartialTlabSize,
+                                                     alloc_size,
+                                                     &take_sample,
+                                                     &bytes_until_sample);
     const size_t expand_bytes = std::max(
         min_expand_size,
-        std::min(self->TlabRemainingCapacity() - self->TlabSize(), kPartialTlabSize));
+        std::min(self->TlabRemainingCapacity() - self->TlabSize(), next_tlab_size));
     if (UNLIKELY(IsOutOfMemoryOnAllocation(allocator_type, expand_bytes, grow))) {
       return nullptr;
     }
@@ -4189,7 +4333,12 @@
     DCHECK_LE(alloc_size, self->TlabSize());
   } else if (allocator_type == kAllocatorTypeTLAB) {
     DCHECK(bump_pointer_space_ != nullptr);
-    const size_t new_tlab_size = alloc_size + kDefaultTLABSize;
+    size_t next_tlab_size = JHPCalculateNextTlabSize(self,
+                                                     kDefaultTLABSize,
+                                                     alloc_size,
+                                                     &take_sample,
+                                                     &bytes_until_sample);
+    const size_t new_tlab_size = alloc_size + next_tlab_size;
     if (UNLIKELY(IsOutOfMemoryOnAllocation(allocator_type, new_tlab_size, grow))) {
       return nullptr;
     }
@@ -4199,6 +4348,9 @@
       return nullptr;
     }
     *bytes_tl_bulk_allocated = new_tlab_size;
+    if (CheckPerfettoJHPEnabled()) {
+      VLOG(heap) << "JHP:kAllocatorTypeTLAB, New Tlab bytes allocated= " << new_tlab_size;
+    }
   } else {
     DCHECK(allocator_type == kAllocatorTypeRegionTLAB);
     DCHECK(region_space_ != nullptr);
@@ -4207,25 +4359,37 @@
       if (LIKELY(!IsOutOfMemoryOnAllocation(allocator_type,
                                             space::RegionSpace::kRegionSize,
                                             grow))) {
+        size_t def_pr_tlab_size = kUsePartialTlabs
+                                      ? kPartialTlabSize
+                                      : gc::space::RegionSpace::kRegionSize;
+        size_t next_pr_tlab_size = JHPCalculateNextTlabSize(self,
+                                                            def_pr_tlab_size,
+                                                            alloc_size,
+                                                            &take_sample,
+                                                            &bytes_until_sample);
         const size_t new_tlab_size = kUsePartialTlabs
-            ? std::max(alloc_size, kPartialTlabSize)
-            : gc::space::RegionSpace::kRegionSize;
+            ? std::max(alloc_size, next_pr_tlab_size)
+            : next_pr_tlab_size;
         // Try to allocate a tlab.
         if (!region_space_->AllocNewTlab(self, new_tlab_size, bytes_tl_bulk_allocated)) {
           // Failed to allocate a tlab. Try non-tlab.
-          return region_space_->AllocNonvirtual<false>(alloc_size,
-                                                       bytes_allocated,
-                                                       usable_size,
-                                                       bytes_tl_bulk_allocated);
+          ret = region_space_->AllocNonvirtual<false>(alloc_size,
+                                                      bytes_allocated,
+                                                      usable_size,
+                                                      bytes_tl_bulk_allocated);
+          JHPCheckNonTlabSampleAllocation(self, ret, alloc_size);
+          return ret;
         }
         // Fall-through to using the TLAB below.
       } else {
         // Check OOME for a non-tlab allocation.
         if (!IsOutOfMemoryOnAllocation(allocator_type, alloc_size, grow)) {
-          return region_space_->AllocNonvirtual<false>(alloc_size,
-                                                       bytes_allocated,
-                                                       usable_size,
-                                                       bytes_tl_bulk_allocated);
+          ret = region_space_->AllocNonvirtual<false>(alloc_size,
+                                                      bytes_allocated,
+                                                      usable_size,
+                                                      bytes_tl_bulk_allocated);
+          JHPCheckNonTlabSampleAllocation(self, ret, alloc_size);
+          return ret;
         }
         // Neither tlab or non-tlab works. Give up.
         return nullptr;
@@ -4233,19 +4397,34 @@
     } else {
       // Large. Check OOME.
       if (LIKELY(!IsOutOfMemoryOnAllocation(allocator_type, alloc_size, grow))) {
-        return region_space_->AllocNonvirtual<false>(alloc_size,
-                                                     bytes_allocated,
-                                                     usable_size,
-                                                     bytes_tl_bulk_allocated);
+        ret = region_space_->AllocNonvirtual<false>(alloc_size,
+                                                    bytes_allocated,
+                                                    usable_size,
+                                                    bytes_tl_bulk_allocated);
+        JHPCheckNonTlabSampleAllocation(self, ret, alloc_size);
+        return ret;
       }
       return nullptr;
     }
   }
   // Refilled TLAB, return.
-  mirror::Object* ret = self->AllocTlab(alloc_size);
+  ret = self->AllocTlab(alloc_size);
   DCHECK(ret != nullptr);
   *bytes_allocated = alloc_size;
   *usable_size = alloc_size;
+
+  // JavaHeapProfiler: Send the thread information about this allocation in case a sample is
+  // requested.
+  // This is the fallthrough from both the if and else if above cases => Cases that use TLAB.
+  if (CheckPerfettoJHPEnabled()) {
+    if (take_sample) {
+      GetHeapSampler().ReportSample(ret, alloc_size);
+      // Update the bytes_until_sample now that the allocation is already done.
+      GetHeapSampler().SetBytesUntilSample(bytes_until_sample);
+    }
+    VLOG(heap) << "JHP:Fallthrough Tlab allocation";
+  }
+
   return ret;
 }
 
@@ -4266,7 +4445,7 @@
     // Trigger a GC, if not already done. The first GC after fork, whenever it
     // takes place, will adjust the thresholds to normal levels.
     if (heap->target_footprint_.load(std::memory_order_relaxed) == heap->growth_limit_) {
-      heap->RequestConcurrentGC(self, kGcCauseBackground, false);
+      heap->RequestConcurrentGC(self, kGcCauseBackground, false, heap->GetCurrentGcNum());
     }
   }
 };
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index ebbb843..09aa4e6 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -26,6 +26,7 @@
 
 #include "allocator_type.h"
 #include "base/atomic.h"
+#include "base/histogram.h"
 #include "base/macros.h"
 #include "base/mutex.h"
 #include "base/runtime_debug.h"
@@ -35,7 +36,6 @@
 #include "gc/collector/iteration.h"
 #include "gc/collector_type.h"
 #include "gc/gc_cause.h"
-#include "gc/space/image_space_loading_order.h"
 #include "gc/space/large_object_space.h"
 #include "handle.h"
 #include "obj_ptr.h"
@@ -163,12 +163,13 @@
 
   // 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.
+  // as object allocation time. time_to_call_mallinfo seems to be on the order of 1 usec
+  // on Android.
 #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 = 512;
+  static constexpr uint32_t kNotifyNativeInterval = 384;
 #endif
 
   // RegisterNativeAllocation checks immediately whether GC is needed if size exceeds the
@@ -210,6 +211,7 @@
        size_t long_pause_threshold,
        size_t long_gc_threshold,
        bool ignore_target_footprint,
+       bool always_log_explicit_gcs,
        bool use_tlab,
        bool verify_pre_gc_heap,
        bool verify_pre_sweeping_heap,
@@ -223,8 +225,7 @@
        bool use_generational_cc,
        uint64_t min_interval_homogeneous_space_compaction_by_oom,
        bool dump_region_info_before_gc,
-       bool dump_region_info_after_gc,
-       space::ImageSpaceLoadingOrder image_space_loading_order);
+       bool dump_region_info_after_gc);
 
   ~Heap();
 
@@ -258,11 +259,14 @@
                !*backtrace_lock_,
                !process_state_update_lock_,
                !Roles::uninterruptible_) {
-    return AllocObjectWithAllocator<kInstrumented>(self,
-                                                   klass,
-                                                   num_bytes,
-                                                   GetCurrentNonMovingAllocator(),
-                                                   pre_fence_visitor);
+    mirror::Object* obj = AllocObjectWithAllocator<kInstrumented>(self,
+                                                                  klass,
+                                                                  num_bytes,
+                                                                  GetCurrentNonMovingAllocator(),
+                                                                  pre_fence_visitor);
+    // Java Heap Profiler check and sample allocation.
+    JHPCheckNonTlabSampleAllocation(self, obj, num_bytes);
+    return obj;
   }
 
   template <bool kInstrumented = true, bool kCheckLargeObject = true, typename PreFenceVisitor>
@@ -286,6 +290,11 @@
     return current_non_moving_allocator_;
   }
 
+  AllocatorType GetUpdatedAllocator(AllocatorType old_allocator) {
+    return (old_allocator == kAllocatorTypeNonMoving) ?
+        GetCurrentNonMovingAllocator() : GetCurrentAllocator();
+  }
+
   // Visit all of the live objects in the heap.
   template <typename Visitor>
   ALWAYS_INLINE void VisitObjects(Visitor&& visitor)
@@ -330,7 +339,7 @@
   // proper lock ordering for it.
   void VerifyObjectBody(ObjPtr<mirror::Object> o) NO_THREAD_SAFETY_ANALYSIS;
 
-  // Check sanity of all live references.
+  // Consistency check of all live references.
   void VerifyHeap() REQUIRES(!Locks::heap_bitmap_lock_);
   // Returns how many failures occured.
   size_t VerifyHeapReferences(bool verify_referents = true)
@@ -375,13 +384,14 @@
       REQUIRES(Locks::heap_bitmap_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Initiates an explicit garbage collection.
+  // Initiates an explicit garbage collection. Guarantees that a GC started after this call has
+  // completed.
   void CollectGarbage(bool clear_soft_references, GcCause cause = kGcCauseExplicit)
       REQUIRES(!*gc_complete_lock_, !*pending_task_lock_, !process_state_update_lock_);
 
-  // Does a concurrent GC, should only be called by the GC daemon thread
-  // through runtime.
-  void ConcurrentGC(Thread* self, GcCause cause, bool force_full)
+  // Does a concurrent GC, provided the GC numbered requested_gc_num has not already been
+  // completed. Should only be called by the GC daemon thread through runtime.
+  void ConcurrentGC(Thread* self, GcCause cause, bool force_full, uint32_t requested_gc_num)
       REQUIRES(!Locks::runtime_shutdown_lock_, !*gc_complete_lock_,
                !*pending_task_lock_, !process_state_update_lock_);
 
@@ -393,23 +403,6 @@
       REQUIRES(!Locks::heap_bitmap_lock_, !*gc_complete_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Implements VMDebug.getInstancesOfClasses and JDWP RT_Instances.
-  void GetInstances(VariableSizedHandleScope& scope,
-                    Handle<mirror::Class> c,
-                    bool use_is_assignable_from,
-                    int32_t max_count,
-                    std::vector<Handle<mirror::Object>>& instances)
-      REQUIRES(!Locks::heap_bitmap_lock_, !*gc_complete_lock_)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Implements JDWP OR_ReferringObjects.
-  void GetReferringObjects(VariableSizedHandleScope& scope,
-                           Handle<mirror::Object> o,
-                           int32_t max_count,
-                           std::vector<Handle<mirror::Object>>& referring_objects)
-      REQUIRES(!Locks::heap_bitmap_lock_, !*gc_complete_lock_)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Removes the growth limit on the alloc space so it may grow to its maximum capacity. Used to
   // implement dalvik.system.VMRuntime.clearGrowthLimit.
   void ClearGrowthLimit();
@@ -468,7 +461,8 @@
   void SetIdealFootprint(size_t max_allowed_footprint);
 
   // Blocks the caller until the garbage collector becomes idle and returns the type of GC we
-  // waited for.
+  // waited for. Only waits for running collections, ignoring a requested but unstarted GC. Only
+  // heuristic, since a new GC may have started by the time we return.
   collector::GcType WaitForGcToComplete(GcCause cause, Thread* self) REQUIRES(!*gc_complete_lock_);
 
   // Update the heap's process state to a new value, may cause compaction to occur.
@@ -509,7 +503,7 @@
     verify_object_mode_ = kVerifyObjectModeDisabled;
   }
 
-  // Other checks may be performed if we know the heap should be in a sane state.
+  // Other checks may be performed if we know the heap should be in a healthy state.
   bool IsObjectValidationEnabled() const {
     return verify_object_mode_ > kVerifyObjectModeDisabled;
   }
@@ -796,13 +790,18 @@
 
   // Returns the active concurrent copying collector.
   collector::ConcurrentCopying* ConcurrentCopyingCollector() {
+    collector::ConcurrentCopying* active_collector =
+            active_concurrent_copying_collector_.load(std::memory_order_relaxed);
     if (use_generational_cc_) {
-      DCHECK((active_concurrent_copying_collector_ == concurrent_copying_collector_) ||
-             (active_concurrent_copying_collector_ == young_concurrent_copying_collector_));
+      DCHECK((active_collector == concurrent_copying_collector_) ||
+             (active_collector == young_concurrent_copying_collector_))
+              << "active_concurrent_copying_collector: " << active_collector
+              << " young_concurrent_copying_collector: " << young_concurrent_copying_collector_
+              << " concurrent_copying_collector: " << concurrent_copying_collector_;
     } else {
-      DCHECK_EQ(active_concurrent_copying_collector_, concurrent_copying_collector_);
+      DCHECK_EQ(active_collector, concurrent_copying_collector_);
     }
-    return active_concurrent_copying_collector_;
+    return active_collector;
   }
 
   CollectorType CurrentCollectorType() {
@@ -826,8 +825,19 @@
   // Request an asynchronous trim.
   void RequestTrim(Thread* self) REQUIRES(!*pending_task_lock_);
 
-  // Request asynchronous GC.
-  void RequestConcurrentGC(Thread* self, GcCause cause, bool force_full)
+  // Retrieve the current GC number, i.e. the number n such that we completed n GCs so far.
+  // Provides acquire ordering, so that if we read this first, and then check whether a GC is
+  // required, we know that the GC number read actually preceded the test.
+  uint32_t GetCurrentGcNum() {
+    return gcs_completed_.load(std::memory_order_acquire);
+  }
+
+  // Request asynchronous GC. Observed_gc_num is the value of GetCurrentGcNum() when we started to
+  // evaluate the GC triggering condition. If a GC has been completed since then, we consider our
+  // job done. If we return true, then we ensured that gcs_completed_ will eventually be
+  // incremented beyond observed_gc_num. We return false only in corner cases in which we cannot
+  // ensure that.
+  bool RequestConcurrentGC(Thread* self, GcCause cause, bool force_full, uint32_t observed_gc_num)
       REQUIRES(!*pending_task_lock_);
 
   // Whether or not we may use a garbage collector, used so that we only create collectors we need.
@@ -845,6 +855,33 @@
   uint64_t GetBlockingGcTime() const;
   void DumpGcCountRateHistogram(std::ostream& os) const REQUIRES(!*gc_complete_lock_);
   void DumpBlockingGcCountRateHistogram(std::ostream& os) const REQUIRES(!*gc_complete_lock_);
+  uint64_t GetTotalTimeWaitingForGC() const {
+    return total_wait_time_;
+  }
+
+  // Perfetto Art Heap Profiler Support.
+  HeapSampler& GetHeapSampler() {
+    return heap_sampler_;
+  }
+
+  void InitPerfettoJavaHeapProf();
+  int CheckPerfettoJHPEnabled();
+  // In NonTlab case: Check whether we should report a sample allocation and if so report it.
+  // Also update state (bytes_until_sample).
+  // By calling JHPCheckNonTlabSampleAllocation from different functions for Large allocations and
+  // non-moving allocations we are able to use the stack to identify these allocations separately.
+  void JHPCheckNonTlabSampleAllocation(Thread* self,
+                                       mirror::Object* ret,
+                                       size_t alloc_size);
+  // In Tlab case: Calculate the next tlab size (location of next sample point) and whether
+  // a sample should be taken.
+  size_t JHPCalculateNextTlabSize(Thread* self,
+                                  size_t jhp_def_tlab_size,
+                                  size_t alloc_size,
+                                  bool* take_sample,
+                                  size_t* bytes_until_sample);
+  // Reduce the number of bytes to the next sample position by this adjustment.
+  void AdjustSampleOffset(size_t adjustment);
 
   // Allocation tracking support
   // Callers to this function use double-checked locking to ensure safety on allocation_records_
@@ -991,11 +1028,6 @@
   // Checks whether we should garbage collect:
   ALWAYS_INLINE bool ShouldConcurrentGCForJava(size_t new_num_bytes_allocated);
   float NativeMemoryOverTarget(size_t current_native_bytes, bool is_gc_concurrent);
-  ALWAYS_INLINE void CheckConcurrentGCForJava(Thread* self,
-                                              size_t new_num_bytes_allocated,
-                                              ObjPtr<mirror::Object>* obj)
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!*pending_task_lock_, !*gc_complete_lock_);
   void CheckGCForNative(Thread* self)
       REQUIRES(!*pending_task_lock_, !*gc_complete_lock_, !process_state_update_lock_);
 
@@ -1013,8 +1045,10 @@
       REQUIRES(!*gc_complete_lock_, !*pending_task_lock_,
                !*backtrace_lock_, !process_state_update_lock_);
 
-  // Handles Allocate()'s slow allocation path with GC involved after
-  // an initial allocation attempt failed.
+  // Handles Allocate()'s slow allocation path with GC involved after an initial allocation
+  // attempt failed.
+  // Called with thread suspension disallowed, but re-enables it, and may suspend, internally.
+  // Returns null if instrumentation or the allocator changed.
   mirror::Object* AllocateInternalWithGc(Thread* self,
                                          AllocatorType allocator,
                                          bool instrumented,
@@ -1050,6 +1084,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   mirror::Object* AllocWithNewTLAB(Thread* self,
+                                   AllocatorType allocator_type,
                                    size_t alloc_size,
                                    bool grow,
                                    size_t* bytes_allocated,
@@ -1080,16 +1115,25 @@
   void RequestCollectorTransition(CollectorType desired_collector_type, uint64_t delta_time)
       REQUIRES(!*pending_task_lock_);
 
-  void RequestConcurrentGCAndSaveObject(Thread* self, bool force_full, ObjPtr<mirror::Object>* obj)
+  void RequestConcurrentGCAndSaveObject(Thread* self,
+                                        bool force_full,
+                                        uint32_t observed_gc_num,
+                                        ObjPtr<mirror::Object>* obj)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!*pending_task_lock_);
-  bool IsGCRequestPending() const;
+
+  static constexpr uint32_t GC_NUM_ANY = std::numeric_limits<uint32_t>::max();
 
   // Sometimes CollectGarbageInternal decides to run a different Gc than you requested. Returns
-  // which type of Gc was actually ran.
+  // which type of Gc was actually run.
+  // We pass in the intended GC sequence number to ensure that multiple approximately concurrent
+  // requests result in a single GC; clearly redundant request will be pruned.  A requested_gc_num
+  // of GC_NUM_ANY indicates that we should not prune redundant requests.  (In the unlikely case
+  // that gcs_completed_ gets this big, we just accept a potential extra GC or two.)
   collector::GcType CollectGarbageInternal(collector::GcType gc_plan,
                                            GcCause gc_cause,
-                                           bool clear_soft_references)
+                                           bool clear_soft_references,
+                                           uint32_t requested_gc_num)
       REQUIRES(!*gc_complete_lock_, !Locks::heap_bitmap_lock_, !Locks::thread_suspend_count_lock_,
                !*pending_task_lock_, !process_state_update_lock_);
 
@@ -1156,7 +1200,6 @@
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!*gc_complete_lock_, !*pending_task_lock_, !process_state_update_lock_);
 
-  void ClearConcurrentGCRequest();
   void ClearPendingTrim(Thread* self) REQUIRES(!*pending_task_lock_);
   void ClearPendingCollectorTransition(Thread* self) REQUIRES(!*pending_task_lock_);
 
@@ -1303,6 +1346,10 @@
   // is useful for benchmarking since it reduces time spent in GC to a low %.
   const bool ignore_target_footprint_;
 
+  // If we are running tests or some other configurations we might not actually
+  // want logs for explicit gcs since they can get spammy.
+  const bool always_log_explicit_gcs_;
+
   // Lock which guards zygote space creation.
   Mutex zygote_creation_lock_;
 
@@ -1505,7 +1552,7 @@
 
   std::vector<collector::GarbageCollector*> garbage_collectors_;
   collector::SemiSpace* semi_space_collector_;
-  collector::ConcurrentCopying* active_concurrent_copying_collector_;
+  Atomic<collector::ConcurrentCopying*> active_concurrent_copying_collector_;
   collector::ConcurrentCopying* young_concurrent_copying_collector_;
   collector::ConcurrentCopying* concurrent_copying_collector_;
 
@@ -1534,8 +1581,16 @@
   // Count for performed homogeneous space compaction.
   Atomic<size_t> count_performed_homogeneous_space_compaction_;
 
-  // Whether or not a concurrent GC is pending.
-  Atomic<bool> concurrent_gc_pending_;
+  // The number of garbage collections (either young or full, not trims or the like) we have
+  // completed since heap creation. We include requests that turned out to be impossible
+  // because they were disabled. We guard against wrapping, though that's unlikely.
+  // Increment is guarded by gc_complete_lock_.
+  Atomic<uint32_t> gcs_completed_;
+
+  // The number of the last garbage collection that has been requested.  A value of gcs_completed
+  // + 1 indicates that another collection is needed or in progress. A value of gcs_completed_ or
+  // (logically) less means that no new GC has been requested.
+  Atomic<uint32_t> max_gc_requested_;
 
   // Active tasks which we can modify (change target time, desired collector type, etc..).
   CollectorTransitionTask* pending_collector_transition_ GUARDED_BY(pending_task_lock_);
@@ -1578,6 +1633,9 @@
   std::unique_ptr<AllocRecordObjectMap> allocation_records_;
   size_t alloc_record_depth_;
 
+  // Perfetto Java Heap Profiler support.
+  HeapSampler heap_sampler_;
+
   // GC stress related data structures.
   Mutex* backtrace_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   // Debugging variables, seen backtraces vs unique backtraces.
diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc
index 817c876..5e8c1e3 100644
--- a/runtime/gc/heap_test.cc
+++ b/runtime/gc/heap_test.cc
@@ -42,7 +42,7 @@
                                      /*reuse=*/ false,
                                      /*reservation=*/ nullptr,
                                      &error_msg);
-    ASSERT_TRUE(reserved_.IsValid()) << error_msg;
+    // There is no guarantee that reserved_ will be valid (due to ASLR). See b/175018342.
     CommonRuntimeTest::SetUp();
   }
 
diff --git a/runtime/gc/heap_verification_test.cc b/runtime/gc/heap_verification_test.cc
index 7835c29..ca6a30b 100644
--- a/runtime/gc/heap_verification_test.cc
+++ b/runtime/gc/heap_verification_test.cc
@@ -18,7 +18,7 @@
 
 #include "base/memory_tool.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "handle_scope-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-alloc-inl.h"
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index 498013e..2e74edf 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -20,7 +20,7 @@
 #include "base/mutex.h"
 #include "base/time_utils.h"
 #include "base/utils.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "collector/garbage_collector.h"
 #include "jni/java_vm_ext.h"
 #include "mirror/class-inl.h"
diff --git a/runtime/gc/space/bump_pointer_space.cc b/runtime/gc/space/bump_pointer_space.cc
index c4fda14..3a0155a 100644
--- a/runtime/gc/space/bump_pointer_space.cc
+++ b/runtime/gc/space/bump_pointer_space.cc
@@ -220,12 +220,16 @@
   return true;
 }
 
-void BumpPointerSpace::LogFragmentationAllocFailure(std::ostream& os,
-                                                    size_t /* failed_alloc_bytes */) {
+bool BumpPointerSpace::LogFragmentationAllocFailure(std::ostream& os,
+                                                    size_t failed_alloc_bytes) {
   size_t max_contiguous_allocation = Limit() - End();
-  os << "; failed due to fragmentation (largest possible contiguous allocation "
-     <<  max_contiguous_allocation << " bytes)";
+  if (failed_alloc_bytes > max_contiguous_allocation) {
+    os << "; failed due to fragmentation (largest possible contiguous allocation "
+       <<  max_contiguous_allocation << " bytes)";
+    return true;
+  }
   // Caller's job to print failed_alloc_bytes.
+  return false;
 }
 
 size_t BumpPointerSpace::AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size) {
diff --git a/runtime/gc/space/bump_pointer_space.h b/runtime/gc/space/bump_pointer_space.h
index 559fae8..08ed503 100644
--- a/runtime/gc/space/bump_pointer_space.h
+++ b/runtime/gc/space/bump_pointer_space.h
@@ -161,7 +161,7 @@
     bytes_allocated_.fetch_sub(bytes, std::memory_order_relaxed);
   }
 
-  void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
+  bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Object alignment within the space.
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index f3fccbb..7564c89 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -359,8 +359,8 @@
   }
 }
 
-void DlMallocSpace::LogFragmentationAllocFailure(std::ostream& os,
-                                                 size_t failed_alloc_bytes ATTRIBUTE_UNUSED) {
+bool DlMallocSpace::LogFragmentationAllocFailure(std::ostream& os,
+                                                 size_t failed_alloc_bytes) {
   Thread* const self = Thread::Current();
   size_t max_contiguous_allocation = 0;
   // To allow the Walk/InspectAll() to exclusively-lock the mutator
@@ -369,8 +369,12 @@
   Locks::mutator_lock_->AssertSharedHeld(self);
   ScopedThreadSuspension sts(self, kSuspended);
   Walk(MSpaceChunkCallback, &max_contiguous_allocation);
-  os << "; failed due to fragmentation (largest possible contiguous allocation "
-     <<  max_contiguous_allocation << " bytes)";
+  if (failed_alloc_bytes > max_contiguous_allocation) {
+    os << "; failed due to fragmentation (largest possible contiguous allocation "
+       <<  max_contiguous_allocation << " bytes)";
+    return true;
+  }
+  return false;
 }
 
 }  // namespace space
diff --git a/runtime/gc/space/dlmalloc_space.h b/runtime/gc/space/dlmalloc_space.h
index 930f557..429b4d0 100644
--- a/runtime/gc/space/dlmalloc_space.h
+++ b/runtime/gc/space/dlmalloc_space.h
@@ -149,7 +149,7 @@
     return this;
   }
 
-  void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
+  bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
       REQUIRES_SHARED(Locks::mutator_lock_);
 
  protected:
diff --git a/runtime/gc/space/dlmalloc_space_random_test.cc b/runtime/gc/space/dlmalloc_space_random_test.cc
index 92b56bd..b653bcf 100644
--- a/runtime/gc/space/dlmalloc_space_random_test.cc
+++ b/runtime/gc/space/dlmalloc_space_random_test.cc
@@ -21,6 +21,7 @@
 namespace art {
 namespace gc {
 namespace space {
+namespace {
 
 MallocSpace* CreateDlMallocSpace(const std::string& name,
                                  size_t initial_size,
@@ -32,6 +33,7 @@
 
 TEST_SPACE_CREATE_FN_RANDOM(DlMallocSpace, CreateDlMallocSpace)
 
+}  // namespace
 }  // namespace space
 }  // namespace gc
 }  // namespace art
diff --git a/runtime/gc/space/dlmalloc_space_static_test.cc b/runtime/gc/space/dlmalloc_space_static_test.cc
index 550d1bb..74dd765 100644
--- a/runtime/gc/space/dlmalloc_space_static_test.cc
+++ b/runtime/gc/space/dlmalloc_space_static_test.cc
@@ -21,6 +21,7 @@
 namespace art {
 namespace gc {
 namespace space {
+namespace {
 
 MallocSpace* CreateDlMallocSpace(const std::string& name,
                                  size_t initial_size,
@@ -32,6 +33,7 @@
 
 TEST_SPACE_CREATE_FN_STATIC(DlMallocSpace, CreateDlMallocSpace)
 
+}  // namespace
 }  // namespace space
 }  // namespace gc
 }  // namespace art
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index bda90dd..4eb7f25 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -43,14 +43,13 @@
 #include "base/systrace.h"
 #include "base/time_utils.h"
 #include "base/utils.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/art_dex_file_loader.h"
 #include "dex/dex_file_loader.h"
 #include "exec_utils.h"
 #include "gc/accounting/space_bitmap-inl.h"
 #include "gc/task_processor.h"
 #include "image-inl.h"
-#include "image_space_fs.h"
 #include "intern_table-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/executable-inl.h"
@@ -116,105 +115,12 @@
   return ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA, ART_BASE_ADDRESS_MAX_DELTA);
 }
 
-static bool GenerateImage(const std::string& image_filename,
-                          InstructionSet image_isa,
-                          std::string* error_msg) {
-  Runtime* runtime = Runtime::Current();
-  const std::vector<std::string>& boot_class_path = runtime->GetBootClassPath();
-  if (boot_class_path.empty()) {
-    *error_msg = "Failed to generate image because no boot class path specified";
-    return false;
-  }
-  // We should clean up so we are more likely to have room for the image.
-  if (Runtime::Current()->IsZygote()) {
-    LOG(INFO) << "Pruning dalvik-cache since we are generating an image and will need to recompile";
-    PruneDalvikCache(image_isa);
-  }
-
-  std::vector<std::string> arg_vector;
-
-  std::string dex2oat(Runtime::Current()->GetCompilerExecutable());
-  arg_vector.push_back(dex2oat);
-
-  char* dex2oat_bcp = getenv("DEX2OATBOOTCLASSPATH");
-  std::vector<std::string> dex2oat_bcp_vector;
-  if (dex2oat_bcp != nullptr) {
-    arg_vector.push_back("--runtime-arg");
-    arg_vector.push_back(StringPrintf("-Xbootclasspath:%s", dex2oat_bcp));
-    Split(dex2oat_bcp, ':', &dex2oat_bcp_vector);
-  }
-
-  std::string image_option_string("--image=");
-  image_option_string += image_filename;
-  arg_vector.push_back(image_option_string);
-
-  if (!dex2oat_bcp_vector.empty()) {
-    for (size_t i = 0u; i < dex2oat_bcp_vector.size(); i++) {
-      arg_vector.push_back(std::string("--dex-file=") + dex2oat_bcp_vector[i]);
-      arg_vector.push_back(std::string("--dex-location=") + dex2oat_bcp_vector[i]);
-    }
-  } else {
-    const std::vector<std::string>& boot_class_path_locations =
-        runtime->GetBootClassPathLocations();
-    DCHECK_EQ(boot_class_path.size(), boot_class_path_locations.size());
-    for (size_t i = 0u; i < boot_class_path.size(); i++) {
-      arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]);
-      arg_vector.push_back(std::string("--dex-location=") + boot_class_path_locations[i]);
-    }
-  }
-
-  std::string oat_file_option_string("--oat-file=");
-  oat_file_option_string += ImageHeader::GetOatLocationFromImageLocation(image_filename);
-  arg_vector.push_back(oat_file_option_string);
-
-  // Note: we do not generate a fully debuggable boot image so we do not pass the
-  // compiler flag --debuggable here.
-
-  Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&arg_vector);
-  CHECK_EQ(image_isa, kRuntimeISA)
-      << "We should always be generating an image for the current isa.";
-
-  int32_t base_offset = ChooseRelocationOffsetDelta();
-  LOG(INFO) << "Using an offset of 0x" << std::hex << base_offset << " from default "
-            << "art base address of 0x" << std::hex << ART_BASE_ADDRESS;
-  arg_vector.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset));
-
-  if (!kIsTargetBuild) {
-    arg_vector.push_back("--host");
-  }
-
-  // Check if there is a boot profile, and pass it to dex2oat.
-  if (OS::FileExists("/system/etc/boot-image.prof")) {
-    arg_vector.push_back("--profile-file=/system/etc/boot-image.prof");
-  } else {
-    // We will compile the boot image with compiler filter "speed" unless overridden below.
-    LOG(WARNING) << "Missing boot-image.prof file, /system/etc/boot-image.prof not found: "
-                 << strerror(errno);
-  }
-
-  const std::vector<std::string>& compiler_options = Runtime::Current()->GetImageCompilerOptions();
-  for (size_t i = 0; i < compiler_options.size(); ++i) {
-    arg_vector.push_back(compiler_options[i].c_str());
-  }
-
-  std::string command_line(Join(arg_vector, ' '));
-  LOG(INFO) << "GenerateImage: " << command_line;
-  return Exec(arg_vector, error_msg);
-}
-
 static bool FindImageFilenameImpl(const char* image_location,
                                   const InstructionSet image_isa,
                                   bool* has_system,
-                                  std::string* system_filename,
-                                  bool* dalvik_cache_exists,
-                                  std::string* dalvik_cache,
-                                  bool* is_global_cache,
-                                  bool* has_cache,
-                                  std::string* cache_filename) {
-  DCHECK(dalvik_cache != nullptr);
-
+                                  std::string* system_filename) {
   *has_system = false;
-  *has_cache = false;
+
   // image_location = /system/framework/boot.art
   // system_image_location = /system/framework/<image_isa>/boot.art
   std::string system_image_filename(GetSystemImageFilename(image_location, image_isa));
@@ -223,53 +129,18 @@
     *has_system = true;
   }
 
-  bool have_android_data = false;
-  *dalvik_cache_exists = false;
-  GetDalvikCache(GetInstructionSetString(image_isa),
-                 /*create_if_absent=*/ true,
-                 dalvik_cache,
-                 &have_android_data,
-                 dalvik_cache_exists,
-                 is_global_cache);
-
-  if (*dalvik_cache_exists) {
-    DCHECK(have_android_data);
-    // Always set output location even if it does not exist,
-    // so that the caller knows where to create the image.
-    //
-    // image_location = /system/framework/boot.art
-    // *image_filename = /data/dalvik-cache/<image_isa>/system@framework@boot.art
-    std::string error_msg;
-    if (!GetDalvikCacheFilename(image_location,
-                                dalvik_cache->c_str(),
-                                cache_filename,
-                                &error_msg)) {
-      LOG(WARNING) << error_msg;
-      return *has_system;
-    }
-    *has_cache = OS::FileExists(cache_filename->c_str());
-  }
-  return *has_system || *has_cache;
+  return *has_system;
 }
 
 bool ImageSpace::FindImageFilename(const char* image_location,
                                    const InstructionSet image_isa,
                                    std::string* system_filename,
-                                   bool* has_system,
-                                   std::string* cache_filename,
-                                   bool* dalvik_cache_exists,
-                                   bool* has_cache,
-                                   bool* is_global_cache) {
+                                   bool* has_system) {
   std::string dalvik_cache_unused;
   return FindImageFilenameImpl(image_location,
                                image_isa,
                                has_system,
-                               system_filename,
-                               dalvik_cache_exists,
-                               &dalvik_cache_unused,
-                               is_global_cache,
-                               has_cache,
-                               cache_filename);
+                               system_filename);
 }
 
 static bool ReadSpecificImageHeader(File* image_file,
@@ -307,36 +178,6 @@
   return hdr;
 }
 
-static bool CanWriteToDalvikCache(const InstructionSet isa) {
-  const std::string dalvik_cache = GetDalvikCache(GetInstructionSetString(isa));
-  if (access(dalvik_cache.c_str(), O_RDWR) == 0) {
-    return true;
-  } else if (errno != EACCES) {
-    PLOG(WARNING) << "CanWriteToDalvikCache returned error other than EACCES";
-  }
-  return false;
-}
-
-static bool ImageCreationAllowed(bool is_global_cache,
-                                 const InstructionSet isa,
-                                 bool is_zygote,
-                                 std::string* error_msg) {
-  // Anyone can write into a "local" cache.
-  if (!is_global_cache) {
-    return true;
-  }
-
-  // Only the zygote running as root is allowed to create the global boot image.
-  // If the zygote is running as non-root (and cannot write to the dalvik-cache),
-  // then image creation is not allowed..
-  if (is_zygote) {
-    return CanWriteToDalvikCache(isa);
-  }
-
-  *error_msg = "Only the zygote can create the global boot image.";
-  return false;
-}
-
 void ImageSpace::VerifyImageAllocations() {
   uint8_t* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
   while (current < End()) {
@@ -528,35 +369,6 @@
       const {}
   void VisitRoot(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const {}
 
-  void VisitDexCacheArrays(ObjPtr<mirror::DexCache> dex_cache)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    ScopedTrace st("VisitDexCacheArrays");
-    FixupDexCacheArray<mirror::StringDexCacheType>(dex_cache,
-                                                   mirror::DexCache::StringsOffset(),
-                                                   dex_cache->NumStrings<kVerifyNone>());
-    FixupDexCacheArray<mirror::TypeDexCacheType>(dex_cache,
-                                                 mirror::DexCache::ResolvedTypesOffset(),
-                                                 dex_cache->NumResolvedTypes<kVerifyNone>());
-    FixupDexCacheArray<mirror::MethodDexCacheType>(dex_cache,
-                                                   mirror::DexCache::ResolvedMethodsOffset(),
-                                                   dex_cache->NumResolvedMethods<kVerifyNone>());
-    FixupDexCacheArray<mirror::FieldDexCacheType>(dex_cache,
-                                                  mirror::DexCache::ResolvedFieldsOffset(),
-                                                  dex_cache->NumResolvedFields<kVerifyNone>());
-    FixupDexCacheArray<mirror::MethodTypeDexCacheType>(
-        dex_cache,
-        mirror::DexCache::ResolvedMethodTypesOffset(),
-        dex_cache->NumResolvedMethodTypes<kVerifyNone>());
-    FixupDexCacheArray<GcRoot<mirror::CallSite>>(
-        dex_cache,
-        mirror::DexCache::ResolvedCallSitesOffset(),
-        dex_cache->NumResolvedCallSites<kVerifyNone>());
-    FixupDexCacheArray<GcRoot<mirror::String>>(
-        dex_cache,
-        mirror::DexCache::PreResolvedStringsOffset(),
-        dex_cache->NumPreResolvedStrings<kVerifyNone>());
-  }
-
   template <bool kMayBeNull = true, typename T>
   ALWAYS_INLINE void PatchGcRoot(/*inout*/GcRoot<T>* root) const
       REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -603,54 +415,6 @@
     }
   }
 
-  template <typename T>
-  void FixupDexCacheArrayEntry(std::atomic<mirror::DexCachePair<T>>* array, uint32_t index)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    static_assert(sizeof(std::atomic<mirror::DexCachePair<T>>) == sizeof(mirror::DexCachePair<T>),
-                  "Size check for removing std::atomic<>.");
-    PatchGcRoot(&(reinterpret_cast<mirror::DexCachePair<T>*>(array)[index].object));
-  }
-
-  template <typename T>
-  void FixupDexCacheArrayEntry(std::atomic<mirror::NativeDexCachePair<T>>* array, uint32_t index)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    static_assert(sizeof(std::atomic<mirror::NativeDexCachePair<T>>) ==
-                      sizeof(mirror::NativeDexCachePair<T>),
-                  "Size check for removing std::atomic<>.");
-    mirror::NativeDexCachePair<T> pair =
-        mirror::DexCache::GetNativePairPtrSize(array, index, kPointerSize);
-    if (pair.object != nullptr) {
-      pair.object = native_visitor_(pair.object);
-      mirror::DexCache::SetNativePairPtrSize(array, index, pair, kPointerSize);
-    }
-  }
-
-  void FixupDexCacheArrayEntry(GcRoot<mirror::CallSite>* array, uint32_t index)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    PatchGcRoot(&array[index]);
-  }
-
-  void FixupDexCacheArrayEntry(GcRoot<mirror::String>* array, uint32_t index)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    PatchGcRoot(&array[index]);
-  }
-
-  template <typename EntryType>
-  void FixupDexCacheArray(ObjPtr<mirror::DexCache> dex_cache,
-                          MemberOffset array_offset,
-                          uint32_t size) REQUIRES_SHARED(Locks::mutator_lock_) {
-    EntryType* old_array =
-        reinterpret_cast64<EntryType*>(dex_cache->GetField64<kVerifyNone>(array_offset));
-    DCHECK_EQ(old_array != nullptr, size != 0u);
-    if (old_array != nullptr) {
-      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);
-      }
-    }
-  }
-
  private:
   // Heap objects visitor.
   HeapVisitor heap_visitor_;
@@ -1082,11 +846,11 @@
     // Use the boot image component count to calculate the checksum from
     // the appropriate number of boot image chunks.
     uint32_t boot_image_component_count = image_header.GetBootImageComponentCount();
-    size_t boot_image_spaces_size = boot_image_spaces.size();
-    if (boot_image_component_count > boot_image_spaces_size) {
+    size_t expected_image_component_count = ImageSpace::GetNumberOfComponents(boot_image_spaces);
+    if (boot_image_component_count > expected_image_component_count) {
       *error_msg = StringPrintf("Too many boot image dependencies (%u > %zu) in image %s",
                                 boot_image_component_count,
-                                boot_image_spaces_size,
+                                expected_image_component_count,
                                 image_filename);
       return false;
     }
@@ -1200,6 +964,18 @@
         return MemMap::Invalid();
       }
 
+      Runtime* runtime = Runtime::Current();
+      // The runtime might not be available at this point if we're running
+      // dex2oat or oatdump.
+      if (runtime != nullptr) {
+        size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeArt();
+        Runtime::MadviseFileForRange(madvise_size_limit,
+                                     temp_map.Size(),
+                                     temp_map.Begin(),
+                                     temp_map.End(),
+                                     image_filename);
+      }
+
       if (is_compressed) {
         memcpy(map.Begin(), &image_header, sizeof(ImageHeader));
 
@@ -1501,8 +1277,8 @@
         }
       }
 
-      // Fixup objects may read fields in the boot image, use the mutator lock here for sanity.
-      // Though its probably not required.
+      // Fixup objects may read fields in the boot image so we hold the mutator lock (although it is
+      // probably not required).
       TimingLogger::ScopedTiming timing("Fixup objects", &logger);
       ScopedObjectAccess soa(Thread::Current());
       // Need to update the image to be at the target base.
@@ -1516,15 +1292,6 @@
       image_header->RelocateImageReferences(app_image_objects.Delta());
       image_header->RelocateBootImageReferences(boot_image.Delta());
       CHECK_EQ(image_header->GetImageBegin(), target_base);
-      // Fix up dex cache DexFile pointers.
-      ObjPtr<mirror::ObjectArray<mirror::DexCache>> dex_caches =
-          image_header->GetImageRoot<kWithoutReadBarrier>(ImageHeader::kDexCaches)
-              ->AsObjectArray<mirror::DexCache, kVerifyNone>();
-      for (int32_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
-        ObjPtr<mirror::DexCache> dex_cache = dex_caches->Get<kVerifyNone, kWithoutReadBarrier>(i);
-        CHECK(dex_cache != nullptr);
-        patch_object_visitor.VisitDexCacheArrays(dex_cache);
-      }
     }
     {
       // Only touches objects in the app image, no need for mutator lock.
@@ -1664,17 +1431,6 @@
     return LoadOrValidateFromSystem(image_isa, oat_checksums, error_msg);
   }
 
-  bool LoadFromDalvikCache(const std::string& dalvik_cache, /*out*/std::string* error_msg) {
-    return LoadOrValidateFromDalvikCache(dalvik_cache, /*oat_checksums=*/ nullptr, error_msg);
-  }
-
-  bool ValidateFromDalvikCache(const std::string& dalvik_cache,
-                               /*inout*/std::string_view* oat_checksums,
-                               /*out*/std::string* error_msg) {
-    DCHECK(oat_checksums != nullptr);
-    return LoadOrValidateFromDalvikCache(dalvik_cache, oat_checksums, error_msg);
-  }
-
   ArrayRef<const ImageChunk> GetChunks() const {
     return ArrayRef<const ImageChunk>(chunks_);
   }
@@ -1771,10 +1527,6 @@
                                 /*inout*/std::string_view* oat_checksums,
                                 /*out*/std::string* error_msg);
 
-  bool LoadOrValidateFromDalvikCache(const std::string& dalvik_cache,
-                                     /*inout*/std::string_view* oat_checksums,
-                                     /*out*/std::string* error_msg);
-
   const std::string& image_location_;
   ArrayRef<const std::string> boot_class_path_;
   ArrayRef<const std::string> boot_class_path_locations_;
@@ -2473,18 +2225,6 @@
   return LoadOrValidate(filename_fn, oat_checksums, error_msg);
 }
 
-bool ImageSpace::BootImageLayout::LoadOrValidateFromDalvikCache(
-    const std::string& dalvik_cache,
-    /*inout*/std::string_view* oat_checksums,
-    /*out*/std::string* error_msg) {
-  auto filename_fn = [&dalvik_cache](const std::string& location,
-                                     /*out*/std::string* filename,
-                                     /*out*/std::string* err_msg) {
-    return GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(), filename, err_msg);
-  };
-  return LoadOrValidate(filename_fn, oat_checksums, error_msg);
-}
-
 class ImageSpace::BootImageLoader {
  public:
   BootImageLoader(const std::vector<std::string>& boot_class_path,
@@ -2492,25 +2232,16 @@
                   const std::string& image_location,
                   InstructionSet image_isa,
                   bool relocate,
-                  bool executable,
-                  bool is_zygote)
+                  bool executable)
       : boot_class_path_(boot_class_path),
         boot_class_path_locations_(boot_class_path_locations),
         image_location_(image_location),
         image_isa_(image_isa),
         relocate_(relocate),
         executable_(executable),
-        is_zygote_(is_zygote),
-        has_system_(false),
-        has_cache_(false),
-        is_global_cache_(true),
-        dalvik_cache_exists_(false),
-        dalvik_cache_(),
-        cache_filename_() {
+        has_system_(false) {
   }
 
-  bool IsZygote() const { return is_zygote_; }
-
   void FindImageFiles() {
     BootImageLayout layout(image_location_, boot_class_path_, boot_class_path_locations_);
     std::string image_location = layout.GetPrimaryImageLocation();
@@ -2518,43 +2249,17 @@
     bool found_image = FindImageFilenameImpl(image_location.c_str(),
                                              image_isa_,
                                              &has_system_,
-                                             &system_filename,
-                                             &dalvik_cache_exists_,
-                                             &dalvik_cache_,
-                                             &is_global_cache_,
-                                             &has_cache_,
-                                             &cache_filename_);
-    DCHECK(!dalvik_cache_exists_ || !dalvik_cache_.empty());
-    DCHECK_EQ(found_image, has_system_ || has_cache_);
+                                             &system_filename);
+    DCHECK_EQ(found_image, has_system_);
   }
 
   bool HasSystem() const { return has_system_; }
-  bool HasCache() const { return has_cache_; }
 
-  bool DalvikCacheExists() const { return dalvik_cache_exists_; }
-  bool IsGlobalCache() const { return is_global_cache_; }
-
-  const std::string& GetDalvikCache() const {
-    return dalvik_cache_;
-  }
-
-  const std::string& GetCacheFilename() const {
-    return cache_filename_;
-  }
-
-  bool LoadFromSystem(bool validate_oat_file,
-                      size_t extra_reservation_size,
+  bool LoadFromSystem(size_t extra_reservation_size,
                       /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
                       /*out*/MemMap* extra_reservation,
                       /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_);
 
-  bool LoadFromDalvikCache(
-      bool validate_oat_file,
-      size_t extra_reservation_size,
-      /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
-      /*out*/MemMap* extra_reservation,
-      /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_);
-
  private:
   bool LoadImage(
       const BootImageLayout& layout,
@@ -2872,8 +2577,10 @@
       image_header.VisitPackedArtMethods([&](ArtMethod& method)
           REQUIRES_SHARED(Locks::mutator_lock_) {
         main_patch_object_visitor.PatchGcRoot(&method.DeclaringClassRoot());
-        void** data_address = PointerAddress(&method, ArtMethod::DataOffset(kPointerSize));
-        main_patch_object_visitor.PatchNativePointer(data_address);
+        if (!method.HasCodeItem()) {
+          void** data_address = PointerAddress(&method, ArtMethod::DataOffset(kPointerSize));
+          main_patch_object_visitor.PatchNativePointer(data_address);
+        }
         void** entrypoint_address =
             PointerAddress(&method, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kPointerSize));
         main_patch_object_visitor.PatchNativePointer(entrypoint_address);
@@ -2953,12 +2660,7 @@
           // This is the last pass over objects, so we do not need to Set().
           main_patch_object_visitor.VisitObject(object);
           ObjPtr<mirror::Class> klass = object->GetClass<kVerifyNone, kWithoutReadBarrier>();
-          if (klass->IsDexCacheClass<kVerifyNone>()) {
-            // Patch dex cache array pointers and elements.
-            ObjPtr<mirror::DexCache> dex_cache =
-                object->AsDexCache<kVerifyNone, kWithoutReadBarrier>();
-            main_patch_object_visitor.VisitDexCacheArrays(dex_cache);
-          } else if (klass == method_class || klass == constructor_class) {
+          if (klass == method_class || klass == constructor_class) {
             // Patch the ArtMethod* in the mirror::Executable subobject.
             ObjPtr<mirror::Executable> as_executable =
                 ObjPtr<mirror::Executable>::DownCast(object);
@@ -3080,19 +2782,12 @@
       return result;
     }
 
-    // Should this be a RDWR lock? This is only a defensive measure, as at
-    // this point the image should exist.
-    // However, only the zygote can write into the global dalvik-cache, so
-    // restrict to zygote processes, or any process that isn't using
-    // /data/dalvik-cache (which we assume to be allowed to write there).
-    const bool rw_lock = is_zygote_ || !is_global_cache_;
-
     // Note that we must not use the file descriptor associated with
     // ScopedFlock::GetFile to Init the image file. We want the file
     // descriptor (and the associated exclusive lock) to be released when
     // we leave Create.
     ScopedFlock image = LockedFile::Open(image_filename.c_str(),
-                                         /*flags=*/ rw_lock ? (O_CREAT | O_RDWR) : O_RDONLY,
+                                         /*flags=*/ O_RDONLY,
                                          /*block=*/ true,
                                          error_msg);
 
@@ -3410,17 +3105,10 @@
   const InstructionSet image_isa_;
   const bool relocate_;
   const bool executable_;
-  const bool is_zygote_;
   bool has_system_;
-  bool has_cache_;
-  bool is_global_cache_;
-  bool dalvik_cache_exists_;
-  std::string dalvik_cache_;
-  std::string cache_filename_;
 };
 
 bool ImageSpace::BootImageLoader::LoadFromSystem(
-    bool validate_oat_file,
     size_t extra_reservation_size,
     /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
     /*out*/MemMap* extra_reservation,
@@ -3433,7 +3121,7 @@
   }
 
   if (!LoadImage(layout,
-                 validate_oat_file,
+                 /*validate_oat_file=*/ false,
                  extra_reservation_size,
                  &logger,
                  boot_image_spaces,
@@ -3444,38 +3132,7 @@
 
   if (VLOG_IS_ON(image)) {
     LOG(INFO) << "ImageSpace::BootImageLoader::LoadFromSystem exiting "
-        << boot_image_spaces->front();
-    logger.Dump(LOG_STREAM(INFO));
-  }
-  return true;
-}
-
-bool ImageSpace::BootImageLoader::LoadFromDalvikCache(
-    bool validate_oat_file,
-    size_t extra_reservation_size,
-    /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
-    /*out*/MemMap* extra_reservation,
-    /*out*/std::string* error_msg) {
-  TimingLogger logger(__PRETTY_FUNCTION__, /*precise=*/ true, VLOG_IS_ON(image));
-  DCHECK(DalvikCacheExists());
-
-  BootImageLayout layout(image_location_, boot_class_path_, boot_class_path_locations_);
-  if (!layout.LoadFromDalvikCache(dalvik_cache_, error_msg)) {
-    return false;
-  }
-  if (!LoadImage(layout,
-                 validate_oat_file,
-                 extra_reservation_size,
-                 &logger,
-                 boot_image_spaces,
-                 extra_reservation,
-                 error_msg)) {
-    return false;
-  }
-
-  if (VLOG_IS_ON(image)) {
-    LOG(INFO) << "ImageSpace::BootImageLoader::LoadFromDalvikCache exiting "
-        << boot_image_spaces->front();
+        << *boot_image_spaces->front();
     logger.Dump(LOG_STREAM(INFO));
   }
   return true;
@@ -3487,78 +3144,30 @@
                          ArrayRef<const std::string>(runtime->GetBootClassPath()),
                          ArrayRef<const std::string>(runtime->GetBootClassPathLocations()));
   const std::string image_location = layout.GetPrimaryImageLocation();
-  ImageSpaceLoadingOrder order = runtime->GetImageSpaceLoadingOrder();
   std::unique_ptr<ImageHeader> image_header;
   std::string error_msg;
 
   std::string system_filename;
   bool has_system = false;
-  std::string cache_filename;
-  bool has_cache = false;
-  bool dalvik_cache_exists = false;
-  bool is_global_cache = false;
+
   if (FindImageFilename(image_location.c_str(),
                         image_isa,
                         &system_filename,
-                        &has_system,
-                        &cache_filename,
-                        &dalvik_cache_exists,
-                        &has_cache,
-                        &is_global_cache)) {
-    DCHECK(has_system || has_cache);
-    const std::string& filename = (order == ImageSpaceLoadingOrder::kSystemFirst)
-        ? (has_system ? system_filename : cache_filename)
-        : (has_cache ? cache_filename : system_filename);
-    image_header = ReadSpecificImageHeader(filename.c_str(), &error_msg);
+                        &has_system)) {
+    DCHECK(has_system);
+    image_header = ReadSpecificImageHeader(system_filename.c_str(), &error_msg);
   }
 
   return image_header != nullptr;
 }
 
-static constexpr uint64_t kLowSpaceValue = 50 * MB;
-static constexpr uint64_t kTmpFsSentinelValue = 384 * MB;
-
-// Read the free space of the cache partition and make a decision whether to keep the generated
-// image. This is to try to mitigate situations where the system might run out of space later.
-static bool CheckSpace(const std::string& cache_filename, std::string* error_msg) {
-  // Using statvfs vs statvfs64 because of b/18207376, and it is enough for all practical purposes.
-  struct statvfs buf;
-
-  int res = TEMP_FAILURE_RETRY(statvfs(cache_filename.c_str(), &buf));
-  if (res != 0) {
-    // Could not stat. Conservatively tell the system to delete the image.
-    *error_msg = "Could not stat the filesystem, assuming low-memory situation.";
-    return false;
-  }
-
-  uint64_t fs_overall_size = buf.f_bsize * static_cast<uint64_t>(buf.f_blocks);
-  // Zygote is privileged, but other things are not. Use bavail.
-  uint64_t fs_free_size = buf.f_bsize * static_cast<uint64_t>(buf.f_bavail);
-
-  // Take the overall size as an indicator for a tmpfs, which is being used for the decryption
-  // environment. We do not want to fail quickening the boot image there, as it is beneficial
-  // for time-to-UI.
-  if (fs_overall_size > kTmpFsSentinelValue) {
-    if (fs_free_size < kLowSpaceValue) {
-      *error_msg = StringPrintf("Low-memory situation: only %4.2f megabytes available, need at "
-                                "least %" PRIu64 ".",
-                                static_cast<double>(fs_free_size) / MB,
-                                kLowSpaceValue / MB);
-      return false;
-    }
-  }
-  return true;
-}
-
 bool ImageSpace::LoadBootImage(
     const std::vector<std::string>& boot_class_path,
     const std::vector<std::string>& boot_class_path_locations,
     const std::string& image_location,
     const InstructionSet image_isa,
-    ImageSpaceLoadingOrder order,
     bool relocate,
     bool executable,
-    bool is_zygote,
     size_t extra_reservation_size,
     /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
     /*out*/MemMap* extra_reservation) {
@@ -3579,122 +3188,29 @@
                          image_location,
                          image_isa,
                          relocate,
-                         executable,
-                         is_zygote);
-
-  // Step 0: Extra zygote work.
-
+                         executable);
   loader.FindImageFiles();
 
-  // Step 0.a: If we're the zygote, check for free space, and prune the cache preemptively,
-  //           if necessary. While the runtime may be fine (it is pretty tolerant to
-  //           out-of-disk-space situations), other parts of the platform are not.
-  //
-  //           The advantage of doing this proactively is that the later steps are simplified,
-  //           i.e., we do not need to code retries.
-  bool low_space = false;
-  if (loader.IsZygote() && loader.DalvikCacheExists()) {
-    // Extra checks for the zygote. These only apply when loading the first image, explained below.
-    const std::string& dalvik_cache = loader.GetDalvikCache();
-    DCHECK(!dalvik_cache.empty());
-    std::string local_error_msg;
-    bool check_space = CheckSpace(dalvik_cache, &local_error_msg);
-    if (!check_space) {
-      LOG(WARNING) << local_error_msg << " Preemptively pruning the dalvik cache.";
-      PruneDalvikCache(image_isa);
-
-      // Re-evaluate the image.
-      loader.FindImageFiles();
-
-      // Disable compilation/patching - we do not want to fill up the space again.
-      low_space = true;
-    }
-  }
-
   // Collect all the errors.
   std::vector<std::string> error_msgs;
 
-  auto try_load_from = [&](auto has_fn, auto load_fn, bool validate_oat_file) {
-    if ((loader.*has_fn)()) {
-      std::string local_error_msg;
-      if ((loader.*load_fn)(validate_oat_file,
-                            extra_reservation_size,
-                            boot_image_spaces,
-                            extra_reservation,
-                            &local_error_msg)) {
-        return true;
-      }
-      error_msgs.push_back(local_error_msg);
-    }
-    return false;
-  };
-
-  auto try_load_from_system = [&]() {
-    // Validate the oat files if the loading order checks data first. Otherwise assume system
-    // integrity.
-    return try_load_from(&BootImageLoader::HasSystem,
-                         &BootImageLoader::LoadFromSystem,
-                         /*validate_oat_file=*/ order != ImageSpaceLoadingOrder::kSystemFirst);
-  };
-  auto try_load_from_cache = [&]() {
-    // Always validate oat files from the dalvik cache.
-    return try_load_from(&BootImageLoader::HasCache,
-                         &BootImageLoader::LoadFromDalvikCache,
-                         /*validate_oat_file=*/ true);
-  };
-
-  auto invoke_sequentially = [](auto first, auto second) {
-    return first() || second();
-  };
-
-  // Step 1+2: Check system and cache images in the asked-for order.
-  if (order == ImageSpaceLoadingOrder::kSystemFirst) {
-    if (invoke_sequentially(try_load_from_system, try_load_from_cache)) {
+  std::string error_msg;
+  if (loader.HasSystem()) {
+    if (loader.LoadFromSystem(extra_reservation_size,
+                              boot_image_spaces,
+                              extra_reservation,
+                              &error_msg)) {
       return true;
     }
-  } else {
-    if (invoke_sequentially(try_load_from_cache, try_load_from_system)) {
-      return true;
-    }
-  }
-
-  // Step 3: We do not have an existing image in /system,
-  //         so generate an image into the dalvik cache.
-  if (!loader.HasSystem() && loader.DalvikCacheExists()) {
-    std::string local_error_msg;
-    if (low_space || !Runtime::Current()->IsImageDex2OatEnabled()) {
-      local_error_msg = "Image compilation disabled.";
-    } else if (ImageCreationAllowed(loader.IsGlobalCache(),
-                                    image_isa,
-                                    is_zygote,
-                                    &local_error_msg)) {
-      bool compilation_success =
-          GenerateImage(loader.GetCacheFilename(), image_isa, &local_error_msg);
-      if (compilation_success) {
-        if (loader.LoadFromDalvikCache(/*validate_oat_file=*/ false,
-                                       extra_reservation_size,
-                                       boot_image_spaces,
-                                       extra_reservation,
-                                       &local_error_msg)) {
-          return true;
-        }
-      }
-    }
-    error_msgs.push_back(StringPrintf("Cannot compile image to %s: %s",
-                                      loader.GetCacheFilename().c_str(),
-                                      local_error_msg.c_str()));
-  }
-
-  // We failed. Prune the cache the free up space, create a compound error message
-  // and return false.
-  if (loader.DalvikCacheExists()) {
-    PruneDalvikCache(image_isa);
+    error_msgs.push_back(error_msg);
   }
 
   std::ostringstream oss;
   bool first = true;
   for (const auto& msg : error_msgs) {
-    if (!first) {
+    if (first) {
+      first = false;
+    } else {
       oss << "\n    ";
     }
     oss << msg;
@@ -3763,7 +3279,9 @@
     }
 
     std::vector<uint32_t> checksums;
-    if (!dex_file_loader.GetMultiDexChecksums(dex_file_location.c_str(), &checksums, error_msg)) {
+    std::vector<std::string> dex_locations_ignored;
+    if (!dex_file_loader.GetMultiDexChecksums(
+        dex_file_location.c_str(), &checksums, &dex_locations_ignored, error_msg)) {
       *error_msg = StringPrintf("ValidateOatFile failed to get checksums of dex file '%s' "
                                 "referenced by oat file %s: %s",
                                 dex_file_location.c_str(),
@@ -3866,6 +3384,14 @@
   return boot_image_checksum;
 }
 
+size_t ImageSpace::GetNumberOfComponents(ArrayRef<ImageSpace* const> image_spaces) {
+  size_t n = 0;
+  for (auto&& is : image_spaces) {
+    n += is->GetComponentCount();
+  }
+  return n;
+}
+
 static size_t CheckAndCountBCPComponents(std::string_view oat_boot_class_path,
                                          ArrayRef<const std::string> boot_class_path,
                                          /*out*/std::string* error_msg) {
@@ -3904,7 +3430,6 @@
                                               ArrayRef<const std::string> boot_class_path_locations,
                                               ArrayRef<const std::string> boot_class_path,
                                               InstructionSet image_isa,
-                                              ImageSpaceLoadingOrder order,
                                               /*out*/std::string* error_msg) {
   if (oat_checksums.empty() || oat_boot_class_path.empty()) {
     *error_msg = oat_checksums.empty() ? "Empty checksums." : "Empty boot class path.";
@@ -3928,30 +3453,18 @@
     std::string primary_image_location = layout.GetPrimaryImageLocation();
     std::string system_filename;
     bool has_system = false;
-    std::string cache_filename;
-    bool has_cache = false;
-    bool dalvik_cache_exists = false;
-    bool is_global_cache = false;
     if (!FindImageFilename(primary_image_location.c_str(),
                            image_isa,
                            &system_filename,
-                           &has_system,
-                           &cache_filename,
-                           &dalvik_cache_exists,
-                           &has_cache,
-                           &is_global_cache)) {
+                           &has_system)) {
       *error_msg = StringPrintf("Unable to find image file for %s and %s",
                                 image_location.c_str(),
                                 GetInstructionSetString(image_isa));
       return false;
     }
 
-    DCHECK(has_system || has_cache);
-    bool use_system = (order == ImageSpaceLoadingOrder::kSystemFirst) ? has_system : !has_cache;
-    bool image_checksums_ok = use_system
-        ? layout.ValidateFromSystem(image_isa, &oat_checksums, error_msg)
-        : layout.ValidateFromDalvikCache(cache_filename, &oat_checksums, error_msg);
-    if (!image_checksums_ok) {
+    DCHECK(has_system);
+    if (!layout.ValidateFromSystem(image_isa, &oat_checksums, error_msg)) {
       return false;
     }
     bcp_pos = layout.GetNextBcpIndex();
@@ -3967,19 +3480,18 @@
     oat_checksums.remove_prefix(1u);
 
     const std::string& bcp_filename = boot_class_path[bcp_pos];
-    std::vector<std::unique_ptr<const DexFile>> dex_files;
+    std::vector<uint32_t> checksums;
+    std::vector<std::string> dex_locations;
     const ArtDexFileLoader dex_file_loader;
-    if (!dex_file_loader.Open(bcp_filename.c_str(),
-                              bcp_filename,  // The location does not matter here.
-                              /*verify=*/ false,
-                              /*verify_checksum=*/ false,
-                              error_msg,
-                              &dex_files)) {
+    if (!dex_file_loader.GetMultiDexChecksums(bcp_filename.c_str(),
+                                              &checksums,
+                                              &dex_locations,
+                                              error_msg)) {
       return false;
     }
-    DCHECK(!dex_files.empty());
-    for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
-      std::string dex_file_checksum = StringPrintf("/%08x", dex_file->GetLocationChecksum());
+    DCHECK(!checksums.empty());
+    for (uint32_t checksum : checksums) {
+      std::string dex_file_checksum = StringPrintf("/%08x", checksum);
       if (!StartsWith(oat_checksums, dex_file_checksum)) {
         *error_msg = StringPrintf("Dex checksum mismatch, expected %s to start with %s",
                                   std::string(oat_checksums).c_str(),
@@ -4164,39 +3676,14 @@
   }
 }
 
-void ImageSpace::DisablePreResolvedStrings() {
-  // Clear dex cache pointers.
-  ObjPtr<mirror::ObjectArray<mirror::DexCache>> dex_caches =
-      GetImageHeader().GetImageRoot(ImageHeader::kDexCaches)->AsObjectArray<mirror::DexCache>();
-  for (size_t len = dex_caches->GetLength(), i = 0; i < len; ++i) {
-    ObjPtr<mirror::DexCache> dex_cache = dex_caches->Get(i);
-    dex_cache->ClearPreResolvedStrings();
-  }
-}
-
 void ImageSpace::ReleaseMetadata() {
   const ImageSection& metadata = GetImageHeader().GetMetadataSection();
   VLOG(image) << "Releasing " << metadata.Size() << " image metadata bytes";
-  // In the case where new app images may have been added around the checkpoint, ensure that we
-  // don't madvise the cache for these.
-  ObjPtr<mirror::ObjectArray<mirror::DexCache>> dex_caches =
-      GetImageHeader().GetImageRoot(ImageHeader::kDexCaches)->AsObjectArray<mirror::DexCache>();
-  bool have_startup_cache = false;
-  for (size_t len = dex_caches->GetLength(), i = 0; i < len; ++i) {
-    ObjPtr<mirror::DexCache> dex_cache = dex_caches->Get(i);
-    if (dex_cache->NumPreResolvedStrings() != 0u) {
-      have_startup_cache = true;
-    }
-  }
-  // Only safe to do for images that have their preresolved strings caches disabled. This is because
-  // uncompressed images madvise to the original unrelocated image contents.
-  if (!have_startup_cache) {
-    // Avoid using ZeroAndReleasePages since the zero fill might not be word atomic.
-    uint8_t* const page_begin = AlignUp(Begin() + metadata.Offset(), kPageSize);
-    uint8_t* const page_end = AlignDown(Begin() + metadata.End(), kPageSize);
-    if (page_begin < page_end) {
-      CHECK_NE(madvise(page_begin, page_end - page_begin, MADV_DONTNEED), -1) << "madvise failed";
-    }
+  // Avoid using ZeroAndReleasePages since the zero fill might not be word atomic.
+  uint8_t* const page_begin = AlignUp(Begin() + metadata.Offset(), kPageSize);
+  uint8_t* const page_end = AlignDown(Begin() + metadata.End(), kPageSize);
+  if (page_begin < page_end) {
+    CHECK_NE(madvise(page_begin, page_end - page_begin, MADV_DONTNEED), -1) << "madvise failed";
   }
 }
 
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 4ddc519..545f659 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -19,7 +19,6 @@
 
 #include "gc/accounting/space_bitmap.h"
 #include "image.h"
-#include "image_space_loading_order.h"
 #include "space.h"
 
 namespace art {
@@ -83,8 +82,7 @@
   //     <search-path>/*
   //     *
   // where the second form means that the path of a particular BCP component
-  // should be used to search for that component's boot image extension. These
-  // paths will be searched in the specifed order.
+  // should be used to search for that component's boot image extension.
   //
   // The actual filename shall be derived from the specified locations using
   // `GetSystemImageFilename()` or `GetDalvikCacheFilename()`.
@@ -128,10 +126,8 @@
       const std::vector<std::string>& boot_class_path_locations,
       const std::string& image_location,
       const InstructionSet image_isa,
-      ImageSpaceLoadingOrder order,
       bool relocate,
       bool executable,
-      bool is_zygote,
       size_t extra_reservation_size,
       /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
       /*out*/MemMap* extra_reservation) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -192,6 +188,11 @@
     return &live_bitmap_;
   }
 
+  // Compute the number of components in the image (contributing jar files).
+  size_t GetComponentCount() const {
+    return GetImageHeader().GetComponentCount();
+  }
+
   void Dump(std::ostream& os) const override;
 
   // Sweeping image spaces is a NOP.
@@ -211,15 +212,11 @@
   static bool FindImageFilename(const char* image_location,
                                 InstructionSet image_isa,
                                 std::string* system_location,
-                                bool* has_system,
-                                std::string* data_location,
-                                bool* dalvik_cache_exists,
-                                bool* has_data,
-                                bool *is_global_cache);
+                                bool* has_system);
 
-  // The leading character in an image checksum part of boot class path checkums.
+  // The leading character in an image checksum part of boot class path checksums.
   static constexpr char kImageChecksumPrefix = 'i';
-  // The leading character in a dex file checksum part of boot class path checkums.
+  // The leading character in a dex file checksum part of boot class path checksums.
   static constexpr char kDexFileChecksumPrefix = 'd';
 
   // Returns the checksums for the boot image, extensions and extra boot class path dex files,
@@ -228,6 +225,9 @@
   static std::string GetBootClassPathChecksums(ArrayRef<ImageSpace* const> image_spaces,
                                                ArrayRef<const DexFile* const> boot_class_path);
 
+  // Returns the total number of components (jar files) associated with the image spaces.
+  static size_t GetNumberOfComponents(ArrayRef<gc::space::ImageSpace* const> image_spaces);
+
   // Returns whether the checksums are valid for the given boot class path,
   // image location and ISA (may differ from the ISA of an initialized Runtime).
   // The boot image and dex files do not need to be loaded in memory.
@@ -237,7 +237,6 @@
                                            ArrayRef<const std::string> boot_class_path_locations,
                                            ArrayRef<const std::string> boot_class_path,
                                            InstructionSet image_isa,
-                                           ImageSpaceLoadingOrder order,
                                            /*out*/std::string* error_msg);
 
   // Returns whether the oat checksums and boot class path description are valid
@@ -277,7 +276,6 @@
   // De-initialize the image-space by undoing the effects in Init().
   virtual ~ImageSpace();
 
-  void DisablePreResolvedStrings() REQUIRES_SHARED(Locks::mutator_lock_);
   void ReleaseMetadata() REQUIRES_SHARED(Locks::mutator_lock_);
 
  protected:
diff --git a/runtime/gc/space/image_space_fs.h b/runtime/gc/space/image_space_fs.h
deleted file mode 100644
index c491893..0000000
--- a/runtime/gc/space/image_space_fs.h
+++ /dev/null
@@ -1,111 +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.
- */
-
-#ifndef ART_RUNTIME_GC_SPACE_IMAGE_SPACE_FS_H_
-#define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_FS_H_
-
-#include <dirent.h>
-#include <dlfcn.h>
-
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-
-#include "base/file_utils.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 {
-namespace space {
-
-// This file contains helper code for ImageSpace. It has most of the file-system
-// related code, including handling A/B OTA.
-
-namespace impl {
-
-// Delete the directory and its (regular or link) contents. If the recurse flag is true, delete
-// sub-directories recursively.
-static void DeleteDirectoryContents(const std::string& dir, bool recurse) {
-  if (!OS::DirectoryExists(dir.c_str())) {
-    return;
-  }
-  DIR* c_dir = opendir(dir.c_str());
-  if (c_dir == nullptr) {
-    PLOG(WARNING) << "Unable to open " << dir << " to delete it's contents";
-    return;
-  }
-
-  for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) {
-    const char* name = de->d_name;
-    if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
-      continue;
-    }
-    // We only want to delete regular files and symbolic links.
-    std::string file = android::base::StringPrintf("%s/%s", dir.c_str(), name);
-    if (de->d_type != DT_REG && de->d_type != DT_LNK) {
-      if (de->d_type == DT_DIR) {
-        if (recurse) {
-          DeleteDirectoryContents(file, recurse);
-          // Try to rmdir the directory.
-          if (rmdir(file.c_str()) != 0) {
-            PLOG(ERROR) << "Unable to rmdir " << file;
-          }
-        }
-      } else {
-        LOG(WARNING) << "Unexpected file type of " << std::hex << de->d_type << " encountered.";
-      }
-    } else {
-      // Try to unlink the file.
-      if (unlink(file.c_str()) != 0) {
-        PLOG(ERROR) << "Unable to unlink " << file;
-      }
-    }
-  }
-  CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
-}
-
-}  // namespace impl
-
-
-// We are relocating or generating the core image. We should get rid of everything. It is all
-// out-of-date. We also don't really care if this fails since it is just a convenience.
-// Adapted from prune_dex_cache(const char* subdir) in frameworks/native/cmds/installd/commands.c
-// Note this should only be used during first boot.
-static void PruneDalvikCache(InstructionSet isa) {
-  CHECK_NE(isa, InstructionSet::kNone);
-  // Prune the base /data/dalvik-cache.
-  // Note: GetDalvikCache may return the empty string if the directory doesn't
-  // exist. It is safe to pass "" to DeleteDirectoryContents, so this is okay.
-  impl::DeleteDirectoryContents(GetDalvikCache("."), false);
-  // Prune /data/dalvik-cache/<isa>.
-  impl::DeleteDirectoryContents(GetDalvikCache(GetInstructionSetString(isa)), false);
-
-  // Be defensive. There should be a runtime created here, but this may be called in a test.
-  if (Runtime::Current() != nullptr) {
-    Runtime::Current()->SetPrunedDalvikCache(true);
-  }
-}
-
-}  // namespace space
-}  // namespace gc
-}  // namespace art
-
-#endif  // ART_RUNTIME_GC_SPACE_IMAGE_SPACE_FS_H_
diff --git a/runtime/gc/space/image_space_loading_order.h b/runtime/gc/space/image_space_loading_order.h
deleted file mode 100644
index d8b0be4..0000000
--- a/runtime/gc/space/image_space_loading_order.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ART_RUNTIME_GC_SPACE_IMAGE_SPACE_LOADING_ORDER_H_
-#define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_LOADING_ORDER_H_
-
-namespace art {
-namespace gc {
-namespace space {
-
-enum class ImageSpaceLoadingOrder : char {
-  kSystemFirst,
-  kDataFirst,
-};
-
-}  // namespace space
-}  // namespace gc
-}  // namespace art
-
-#endif  // ART_RUNTIME_GC_SPACE_IMAGE_SPACE_LOADING_ORDER_H_
diff --git a/runtime/gc/space/image_space_test.cc b/runtime/gc/space/image_space_test.cc
index b08c680..885dd21 100644
--- a/runtime/gc/space/image_space_test.cc
+++ b/runtime/gc/space/image_space_test.cc
@@ -24,7 +24,7 @@
 #include "class_linker.h"
 #include "dexopt_test.h"
 #include "dex/utf.h"
-#include "intern_table.h"
+#include "intern_table-inl.h"
 #include "noop_compiler_callbacks.h"
 #include "oat_file.h"
 
@@ -35,8 +35,6 @@
 class ImageSpaceTest : public CommonRuntimeTest {
  protected:
   void SetUpRuntimeOptions(RuntimeOptions* options) override {
-    // Disable implicit dex2oat invocations when loading image spaces.
-    options->emplace_back("-Xnoimage-dex2oat", nullptr);
     // Disable relocation.
     options->emplace_back("-Xnorelocate", nullptr);
   }
@@ -60,13 +58,17 @@
   int mkdir_result = mkdir(image_dir.c_str(), 0700);
   ASSERT_EQ(0, mkdir_result);
 
-  // Prepare boot class path variables, exclude conscrypt which is not in the primary boot image.
+  // Prepare boot class path variables, exclude core-icu4j and conscrypt
+  // which are not in the primary boot image.
   std::vector<std::string> bcp = GetLibCoreDexFileNames();
   std::vector<std::string> bcp_locations = GetLibCoreDexLocations();
   CHECK_EQ(bcp.size(), bcp_locations.size());
   ASSERT_NE(std::string::npos, bcp.back().find("conscrypt"));
   bcp.pop_back();
   bcp_locations.pop_back();
+  ASSERT_NE(std::string::npos, bcp.back().find("core-icu4j"));
+  bcp.pop_back();
+  bcp_locations.pop_back();
   std::string base_bcp_string = android::base::Join(bcp, ':');
   std::string base_bcp_locations_string = android::base::Join(bcp_locations, ':');
   std::string base_image_location = GetImageLocation();
@@ -77,7 +79,7 @@
     std::string jar_name = GetTestDexFileName(base_name);
     ArrayRef<const std::string> dex_files(&jar_name, /*size=*/ 1u);
     ScratchFile profile_file;
-    GenerateProfile(dex_files, profile_file.GetFile());
+    GenerateBootProfile(dex_files, profile_file.GetFile());
     std::vector<std::string> extra_args = {
         "--profile-file=" + profile_file.GetFilename(),
         "--runtime-arg",
@@ -136,10 +138,8 @@
                                      bcp_locations,
                                      full_image_locations,
                                      kRuntimeISA,
-                                     ImageSpaceLoadingOrder::kSystemFirst,
                                      /*relocate=*/ false,
                                      /*executable=*/ true,
-                                     /*is_zygote=*/ false,
                                      /*extra_reservation_size=*/ 0u,
                                      &boot_image_spaces,
                                      &extra_reservation);
@@ -338,7 +338,6 @@
         ArrayRef<const std::string>(bcp_locations),
         ArrayRef<const std::string>(bcp),
         kRuntimeISA,
-        gc::space::ImageSpaceLoadingOrder::kSystemFirst,
         &error_msg);
   };
 
@@ -367,7 +366,7 @@
   }
 }
 
-template <bool kImage, bool kRelocate, bool kImageDex2oat>
+template <bool kImage, bool kRelocate>
 class ImageSpaceLoadingTest : public CommonRuntimeTest {
  protected:
   void SetUpRuntimeOptions(RuntimeOptions* options) override {
@@ -379,7 +378,6 @@
     options->emplace_back(android::base::StringPrintf("-Ximage:%s", image_location.c_str()),
                           nullptr);
     options->emplace_back(kRelocate ? "-Xrelocate" : "-Xnorelocate", nullptr);
-    options->emplace_back(kImageDex2oat ? "-Ximage-dex2oat" : "-Xnoimage-dex2oat", nullptr);
 
     // We want to test the relocation behavior of ImageSpace. As such, don't pretend we're a
     // compiler.
@@ -410,22 +408,17 @@
   UniqueCPtr<const char[]> old_dex2oat_bcp_;
 };
 
-using ImageSpaceDex2oatTest = ImageSpaceLoadingTest<false, true, true>;
-TEST_F(ImageSpaceDex2oatTest, Test) {
-  EXPECT_FALSE(Runtime::Current()->GetHeap()->GetBootImageSpaces().empty());
-}
-
-using ImageSpaceNoDex2oatTest = ImageSpaceLoadingTest<true, true, false>;
+using ImageSpaceNoDex2oatTest = ImageSpaceLoadingTest<true, true>;
 TEST_F(ImageSpaceNoDex2oatTest, Test) {
   EXPECT_FALSE(Runtime::Current()->GetHeap()->GetBootImageSpaces().empty());
 }
 
-using ImageSpaceNoRelocateNoDex2oatTest = ImageSpaceLoadingTest<true, false, false>;
+using ImageSpaceNoRelocateNoDex2oatTest = ImageSpaceLoadingTest<true, false>;
 TEST_F(ImageSpaceNoRelocateNoDex2oatTest, Test) {
   EXPECT_FALSE(Runtime::Current()->GetHeap()->GetBootImageSpaces().empty());
 }
 
-class NoAccessAndroidDataTest : public ImageSpaceLoadingTest<false, true, true> {
+class NoAccessAndroidDataTest : public ImageSpaceLoadingTest<false, true> {
  protected:
   NoAccessAndroidDataTest() : quiet_(LogSeverity::FATAL) {}
 
@@ -446,11 +439,11 @@
     CHECK_NE(fd, -1) << strerror(errno);
     result = close(fd);
     CHECK_EQ(result, 0) << strerror(errno);
-    ImageSpaceLoadingTest<false, true, true>::SetUpRuntimeOptions(options);
+    ImageSpaceLoadingTest<false, true>::SetUpRuntimeOptions(options);
   }
 
   void TearDown() override {
-    ImageSpaceLoadingTest<false, true, true>::TearDown();
+    ImageSpaceLoadingTest<false, true>::TearDown();
     int result = unlink(bad_dalvik_cache_.c_str());
     CHECK_EQ(result, 0) << strerror(errno);
     result = rmdir(bad_android_data_.c_str());
diff --git a/runtime/gc/space/large_object_space.cc b/runtime/gc/space/large_object_space.cc
index d1b4d7c..2d17a18 100644
--- a/runtime/gc/space/large_object_space.cc
+++ b/runtime/gc/space/large_object_space.cc
@@ -641,9 +641,10 @@
   return scc.freed;
 }
 
-void LargeObjectSpace::LogFragmentationAllocFailure(std::ostream& /*os*/,
+bool LargeObjectSpace::LogFragmentationAllocFailure(std::ostream& /*os*/,
                                                     size_t /*failed_alloc_bytes*/) {
   UNIMPLEMENTED(FATAL);
+  UNREACHABLE();
 }
 
 std::pair<uint8_t*, uint8_t*> LargeObjectMapSpace::GetBeginEndAtomic() const {
diff --git a/runtime/gc/space/large_object_space.h b/runtime/gc/space/large_object_space.h
index 13251d6..8b3115c 100644
--- a/runtime/gc/space/large_object_space.h
+++ b/runtime/gc/space/large_object_space.h
@@ -101,7 +101,7 @@
     const uint8_t* byte_obj = reinterpret_cast<const uint8_t*>(obj);
     return Begin() <= byte_obj && byte_obj < End();
   }
-  void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
+  bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Return true if the large object is a zygote large object. Potentially slow.
diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc
index 281d9c2..a9402d2 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -84,7 +84,7 @@
                                  size_t* initial_size,
                                  size_t* growth_limit,
                                  size_t* capacity) {
-  // Sanity check arguments
+  // Consistency check of the arguments.
   if (starting_size > *initial_size) {
     *initial_size = starting_size;
   }
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index faeeec0..091dc4e 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -110,6 +110,7 @@
       use_generational_cc_(use_generational_cc),
       time_(1U),
       num_regions_(mem_map_.Size() / kRegionSize),
+      madvise_time_(0U),
       num_non_free_regions_(0U),
       num_evac_regions_(0U),
       max_peak_num_non_free_regions_(0U),
@@ -499,8 +500,13 @@
   }
 
   // Madvise the memory ranges.
+  uint64_t start_time = NanoTime();
   for (const auto &iter : madvise_list) {
     ZeroAndProtectRegion(iter.first, iter.second);
+  }
+  madvise_time_ += NanoTime() - start_time;
+
+  for (const auto &iter : madvise_list) {
     if (clear_bitmap) {
       GetLiveBitmap()->ClearRange(
           reinterpret_cast<mirror::Object*>(iter.first),
@@ -716,44 +722,52 @@
   }
 }
 
-void RegionSpace::LogFragmentationAllocFailure(std::ostream& os,
-                                               size_t /* failed_alloc_bytes */) {
+bool RegionSpace::LogFragmentationAllocFailure(std::ostream& os,
+                                               size_t failed_alloc_bytes) {
   size_t max_contiguous_allocation = 0;
   MutexLock mu(Thread::Current(), region_lock_);
+
   if (current_region_->End() - current_region_->Top() > 0) {
     max_contiguous_allocation = current_region_->End() - current_region_->Top();
   }
-  if (num_non_free_regions_ * 2 < num_regions_) {
-    // We reserve half of the regions for evaluation only. If we
-    // occupy more than half the regions, do not report the free
-    // regions as available.
-    size_t max_contiguous_free_regions = 0;
-    size_t num_contiguous_free_regions = 0;
-    bool prev_free_region = false;
-    for (size_t i = 0; i < num_regions_; ++i) {
-      Region* r = &regions_[i];
-      if (r->IsFree()) {
-        if (!prev_free_region) {
-          CHECK_EQ(num_contiguous_free_regions, 0U);
-          prev_free_region = true;
-        }
-        ++num_contiguous_free_regions;
-      } else {
-        if (prev_free_region) {
-          CHECK_NE(num_contiguous_free_regions, 0U);
-          max_contiguous_free_regions = std::max(max_contiguous_free_regions,
-                                                 num_contiguous_free_regions);
-          num_contiguous_free_regions = 0U;
-          prev_free_region = false;
-        }
+
+  size_t max_contiguous_free_regions = 0;
+  size_t num_contiguous_free_regions = 0;
+  bool prev_free_region = false;
+  for (size_t i = 0; i < num_regions_; ++i) {
+    Region* r = &regions_[i];
+    if (r->IsFree()) {
+      if (!prev_free_region) {
+        CHECK_EQ(num_contiguous_free_regions, 0U);
+        prev_free_region = true;
       }
+      ++num_contiguous_free_regions;
+    } else if (prev_free_region) {
+      CHECK_NE(num_contiguous_free_regions, 0U);
+      max_contiguous_free_regions = std::max(max_contiguous_free_regions,
+                                             num_contiguous_free_regions);
+      num_contiguous_free_regions = 0U;
+      prev_free_region = false;
     }
-    max_contiguous_allocation = std::max(max_contiguous_allocation,
-                                         max_contiguous_free_regions * kRegionSize);
   }
-  os << "; failed due to fragmentation (largest possible contiguous allocation "
-     <<  max_contiguous_allocation << " bytes)";
+  max_contiguous_allocation = std::max(max_contiguous_allocation,
+                                       max_contiguous_free_regions * kRegionSize);
+
+  // Calculate how many regions are available for allocations as we have to ensure
+  // that enough regions are left for evacuation.
+  size_t regions_free_for_alloc = num_regions_ / 2 - num_non_free_regions_;
+
+  max_contiguous_allocation = std::min(max_contiguous_allocation,
+                                       regions_free_for_alloc * kRegionSize);
+  if (failed_alloc_bytes > max_contiguous_allocation) {
+    os << "; failed due to fragmentation (largest possible contiguous allocation "
+       <<  max_contiguous_allocation << " bytes). Number of "
+       << PrettySize(kRegionSize)
+       << " sized free regions are: " << regions_free_for_alloc;
+    return true;
+  }
   // Caller's job to print failed_alloc_bytes.
+  return false;
 }
 
 void RegionSpace::Clear() {
diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h
index f74abfb..c3b272d 100644
--- a/runtime/gc/space/region_space.h
+++ b/runtime/gc/space/region_space.h
@@ -227,7 +227,7 @@
   accounting::ContinuousSpaceBitmap::SweepCallback* GetSweepCallback() override {
     return nullptr;
   }
-  void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
+  bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!region_lock_);
 
   // Object alignment within the space.
@@ -380,6 +380,10 @@
     return num_evac_regions_ * kRegionSize;
   }
 
+  uint64_t GetMadviseTime() const {
+    return madvise_time_;
+  }
+
  private:
   RegionSpace(const std::string& name, MemMap&& mem_map, bool use_generational_cc);
 
@@ -738,6 +742,7 @@
   const bool use_generational_cc_;
   uint32_t time_;                  // The time as the number of collections since the startup.
   size_t num_regions_;             // The number of regions in this space.
+  uint64_t madvise_time_;          // The amount of time spent in madvise for purging pages.
   // The number of non-free regions in this space.
   size_t num_non_free_regions_ GUARDED_BY(region_lock_);
 
@@ -764,7 +769,7 @@
 
   Region* current_region_;         // The region currently used for allocation.
   Region* evac_region_;            // The region currently used for evacuation.
-  Region full_region_;             // The dummy/sentinel region that looks full.
+  Region full_region_;             // The fake/sentinel region that looks full.
 
   // Index into the region array pointing to the starting region when
   // trying to allocate a new region. Only used when
@@ -777,8 +782,8 @@
   DISALLOW_COPY_AND_ASSIGN(RegionSpace);
 };
 
-std::ostream& operator<<(std::ostream& os, const RegionSpace::RegionState& value);
-std::ostream& operator<<(std::ostream& os, const RegionSpace::RegionType& value);
+std::ostream& operator<<(std::ostream& os, RegionSpace::RegionState value);
+std::ostream& operator<<(std::ostream& os, RegionSpace::RegionType value);
 
 }  // namespace space
 }  // namespace gc
diff --git a/runtime/gc/space/rosalloc_space.h b/runtime/gc/space/rosalloc_space.h
index 00f5ab2..7becea0 100644
--- a/runtime/gc/space/rosalloc_space.h
+++ b/runtime/gc/space/rosalloc_space.h
@@ -152,8 +152,8 @@
 
   virtual ~RosAllocSpace();
 
-  void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override {
-    rosalloc_->LogFragmentationAllocFailure(os, failed_alloc_bytes);
+  bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override {
+    return rosalloc_->LogFragmentationAllocFailure(os, failed_alloc_bytes);
   }
 
   void DumpStats(std::ostream& os);
diff --git a/runtime/gc/space/rosalloc_space_random_test.cc b/runtime/gc/space/rosalloc_space_random_test.cc
index f0b3231..3010b77 100644
--- a/runtime/gc/space/rosalloc_space_random_test.cc
+++ b/runtime/gc/space/rosalloc_space_random_test.cc
@@ -21,6 +21,7 @@
 namespace art {
 namespace gc {
 namespace space {
+namespace {
 
 MallocSpace* CreateRosAllocSpace(const std::string& name,
                                  size_t initial_size,
@@ -36,6 +37,7 @@
 
 TEST_SPACE_CREATE_FN_RANDOM(RosAllocSpace, CreateRosAllocSpace)
 
+}  // namespace
 }  // namespace space
 }  // namespace gc
 }  // namespace art
diff --git a/runtime/gc/space/rosalloc_space_static_test.cc b/runtime/gc/space/rosalloc_space_static_test.cc
index d7e7e90..860a461 100644
--- a/runtime/gc/space/rosalloc_space_static_test.cc
+++ b/runtime/gc/space/rosalloc_space_static_test.cc
@@ -21,6 +21,7 @@
 namespace art {
 namespace gc {
 namespace space {
+namespace {
 
 MallocSpace* CreateRosAllocSpace(const std::string& name,
                                  size_t initial_size,
@@ -35,6 +36,7 @@
 
 TEST_SPACE_CREATE_FN_STATIC(RosAllocSpace, CreateRosAllocSpace)
 
+}  // namespace
 }  // namespace space
 }  // namespace gc
 }  // namespace art
diff --git a/runtime/gc/space/space.h b/runtime/gc/space/space.h
index 3b7e3b7..160c730 100644
--- a/runtime/gc/space/space.h
+++ b/runtime/gc/space/space.h
@@ -64,7 +64,7 @@
   // collections won't scan these areas such as the Zygote.
   kGcRetentionPolicyFullCollect,
 };
-std::ostream& operator<<(std::ostream& os, const GcRetentionPolicy& policy);
+std::ostream& operator<<(std::ostream& os, GcRetentionPolicy policy);
 
 enum SpaceType {
   kSpaceTypeImageSpace,
@@ -74,7 +74,7 @@
   kSpaceTypeLargeObjectSpace,
   kSpaceTypeRegionSpace,
 };
-std::ostream& operator<<(std::ostream& os, const SpaceType& space_type);
+std::ostream& operator<<(std::ostream& os, SpaceType space_type);
 
 // A space contains memory allocated for managed objects.
 class Space {
@@ -243,7 +243,10 @@
   // from Heap::num_bytes_allocated_ or zero if unnecessary.
   virtual size_t RevokeAllThreadLocalBuffers() = 0;
 
-  virtual void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) = 0;
+  // Compute largest free contiguous chunk of memory available in the space and
+  // log it if it's smaller than failed_alloc_bytes and return true.
+  // Otherwise leave os untouched and return false.
+  virtual bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) = 0;
 
  protected:
   struct SweepCallbackContext {
diff --git a/runtime/gc/space/space_create_test.cc b/runtime/gc/space/space_create_test.cc
index d3db679..4849d6c 100644
--- a/runtime/gc/space/space_create_test.cc
+++ b/runtime/gc/space/space_create_test.cc
@@ -87,7 +87,7 @@
 // allocations after the ZygoteSpace is created. The test should also do some GCs to ensure that
 // the GC works with the ZygoteSpace.
 TEST_P(SpaceCreateTest, ZygoteSpaceTestBody) {
-  size_t dummy;
+  size_t unused;
   MallocSpace* space(CreateSpace("test", 4 * MB, 16 * MB, 16 * MB));
   ASSERT_TRUE(space != nullptr);
 
@@ -112,7 +112,7 @@
   EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);
 
   // Fails, requires a higher footprint limit.
-  mirror::Object* ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
+  mirror::Object* ptr2 = Alloc(space, self, 8 * MB, &unused, nullptr, &unused);
   EXPECT_TRUE(ptr2 == nullptr);
 
   // Succeeds, adjusts the footprint.
@@ -130,11 +130,11 @@
   EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);
 
   // Fails, requires a higher footprint limit.
-  mirror::Object* ptr4 = space->Alloc(self, 8 * MB, &dummy, nullptr, &dummy);
+  mirror::Object* ptr4 = space->Alloc(self, 8 * MB, &unused, nullptr, &unused);
   EXPECT_TRUE(ptr4 == nullptr);
 
   // Also fails, requires a higher allowed footprint.
-  mirror::Object* ptr5 = space->AllocWithGrowth(self, 8 * MB, &dummy, nullptr, &dummy);
+  mirror::Object* ptr5 = space->AllocWithGrowth(self, 8 * MB, &unused, nullptr, &unused);
   EXPECT_TRUE(ptr5 == nullptr);
 
   // Release some memory.
@@ -163,7 +163,7 @@
   EXPECT_LE(1U * MB, free1);
 
   // Make sure that the zygote space isn't directly at the start of the space.
-  EXPECT_TRUE(space->Alloc(self, 1U * MB, &dummy, nullptr, &dummy) != nullptr);
+  EXPECT_TRUE(space->Alloc(self, 1U * MB, &unused, nullptr, &unused) != nullptr);
 
   gc::Heap* heap = Runtime::Current()->GetHeap();
   space::Space* old_space = space;
@@ -197,7 +197,7 @@
   EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);
 
   // Fails, requires a higher footprint limit.
-  ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
+  ptr2 = Alloc(space, self, 8 * MB, &unused, nullptr, &unused);
   EXPECT_TRUE(ptr2 == nullptr);
 
   // Succeeds, adjusts the footprint.
@@ -221,7 +221,7 @@
 }
 
 TEST_P(SpaceCreateTest, AllocAndFreeTestBody) {
-  size_t dummy = 0;
+  size_t unused = 0;
   MallocSpace* space(CreateSpace("test", 4 * MB, 16 * MB, 16 * MB));
   ASSERT_TRUE(space != nullptr);
   Thread* self = Thread::Current();
@@ -246,7 +246,7 @@
   EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);
 
   // Fails, requires a higher footprint limit.
-  mirror::Object* ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
+  mirror::Object* ptr2 = Alloc(space, self, 8 * MB, &unused, nullptr, &unused);
   EXPECT_TRUE(ptr2 == nullptr);
 
   // Succeeds, adjusts the footprint.
@@ -264,11 +264,11 @@
   EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);
 
   // Fails, requires a higher footprint limit.
-  mirror::Object* ptr4 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
+  mirror::Object* ptr4 = Alloc(space, self, 8 * MB, &unused, nullptr, &unused);
   EXPECT_TRUE(ptr4 == nullptr);
 
   // Also fails, requires a higher allowed footprint.
-  mirror::Object* ptr5 = AllocWithGrowth(space, self, 8 * MB, &dummy, nullptr, &dummy);
+  mirror::Object* ptr5 = AllocWithGrowth(space, self, 8 * MB, &unused, nullptr, &unused);
   EXPECT_TRUE(ptr5 == nullptr);
 
   // Release some memory.
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index 01d0d68..e40ee50 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -242,7 +242,7 @@
       space->Trim();
     }
 
-    // Bounds sanity
+    // Bounds consistency check.
     footprint = space->GetFootprint();
     EXPECT_LE(amount_allocated, growth_limit);
     EXPECT_GE(footprint, amount_allocated);
@@ -299,16 +299,16 @@
   }
   EXPECT_TRUE(large_object != nullptr);
 
-  // Sanity check footprint
+  // Consistency check of the footprint.
   footprint = space->GetFootprint();
   EXPECT_LE(footprint, growth_limit);
   EXPECT_GE(space->Size(), footprint);
   EXPECT_LE(space->Size(), growth_limit);
 
-  // Clean up
+  // Clean up.
   space->Free(self, large_object.Assign(nullptr));
 
-  // Sanity check footprint
+  // Consistency check of the footprint.
   footprint = space->GetFootprint();
   EXPECT_LE(footprint, growth_limit);
   EXPECT_GE(space->Size(), footprint);
@@ -328,7 +328,7 @@
   MallocSpace* space(create_space("test", initial_size, growth_limit, capacity));
   ASSERT_TRUE(space != nullptr);
 
-  // Basic sanity
+  // Basic consistency check.
   EXPECT_EQ(space->Capacity(), growth_limit);
   EXPECT_EQ(space->NonGrowthLimitCapacity(), capacity);
 
diff --git a/runtime/gc/space/zygote_space.cc b/runtime/gc/space/zygote_space.cc
index 66427a7..c5e3a70 100644
--- a/runtime/gc/space/zygote_space.cc
+++ b/runtime/gc/space/zygote_space.cc
@@ -111,7 +111,7 @@
   UNREACHABLE();
 }
 
-void ZygoteSpace::LogFragmentationAllocFailure(std::ostream&, size_t) {
+bool ZygoteSpace::LogFragmentationAllocFailure(std::ostream&, size_t) {
   UNIMPLEMENTED(FATAL);
   UNREACHABLE();
 }
diff --git a/runtime/gc/space/zygote_space.h b/runtime/gc/space/zygote_space.h
index 631691d..3ebc943 100644
--- a/runtime/gc/space/zygote_space.h
+++ b/runtime/gc/space/zygote_space.h
@@ -79,7 +79,7 @@
     return false;
   }
 
-  void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
+  bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override
       REQUIRES_SHARED(Locks::mutator_lock_);
 
  protected:
diff --git a/runtime/gc/verification.cc b/runtime/gc/verification.cc
index 8670a22..9e0b8a2 100644
--- a/runtime/gc/verification.cc
+++ b/runtime/gc/verification.cc
@@ -86,10 +86,7 @@
                                      MemberOffset offset,
                                      mirror::Object* ref,
                                      bool fatal) const {
-  // Lowest priority logging first:
-  PrintFileToLog("/proc/self/maps", android::base::LogSeverity::FATAL_WITHOUT_ABORT);
-  MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), /* terse= */ true);
-  Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(FATAL_WITHOUT_ABORT));
+  // Highest priority logging first.
   // Buffer the output in the string stream since it is more important than the stack traces
   // and we want it to have log priority. The stack traces are printed from Runtime::Abort
   // which is called from LOG(FATAL) but before the abort message.
@@ -110,6 +107,8 @@
     oss << " reference addr"
         << DumpRAMAroundAddress(reinterpret_cast<uintptr_t>(addr), 4 * kObjectAlignment);
   }
+  Runtime::Current()->GetHeap()->DumpSpaces(oss);
+  MemMap::DumpMaps(oss, /* terse= */ true);
 
   if (fatal) {
     LOG(FATAL) << oss.str();
diff --git a/runtime/gc/weak_root_state.h b/runtime/gc/weak_root_state.h
index e3cefc4..0784d3c 100644
--- a/runtime/gc/weak_root_state.h
+++ b/runtime/gc/weak_root_state.h
@@ -33,7 +33,7 @@
   kWeakRootStateMarkNewRoots,
 };
 
-std::ostream& operator<<(std::ostream& os, const WeakRootState&);
+std::ostream& operator<<(std::ostream& os, WeakRootState weak_root_state);
 
 }  // namespace gc
 }  // namespace art
diff --git a/runtime/gc_root.h b/runtime/gc_root.h
index 8d8c32c..553f3d6 100644
--- a/runtime/gc_root.h
+++ b/runtime/gc_root.h
@@ -54,7 +54,7 @@
   kRootVMInternal,
   kRootJNIMonitor,
 };
-std::ostream& operator<<(std::ostream& os, const RootType& root_type);
+std::ostream& operator<<(std::ostream& os, RootType root_type);
 
 // Only used by hprof. thread_id_ and type_ are only used by hprof.
 class RootInfo {
diff --git a/runtime/gtest_test.cc b/runtime/gtest_test.cc
index a40751d..ab02a79 100644
--- a/runtime/gtest_test.cc
+++ b/runtime/gtest_test.cc
@@ -16,5 +16,5 @@
 
 #include "gtest/gtest.h"
 
-// Sanity test that gtest alone works on host and target
+// Trivial test that gtest alone works on host and target
 TEST(GTest, Nop) {}
diff --git a/runtime/handle.cc b/runtime/handle.cc
new file mode 100644
index 0000000..af77e23
--- /dev/null
+++ b/runtime/handle.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 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 "handle.h"
+
+#include "mirror/object.h"
+#include "mirror/accessible_object.h"
+#include "mirror/array.h"
+#include "mirror/call_site.h"
+#include "mirror/class.h"
+#include "mirror/class_ext.h"
+#include "mirror/dex_cache.h"
+#include "mirror/emulated_stack_frame.h"
+#include "mirror/executable.h"
+#include "mirror/field.h"
+#include "mirror/iftable.h"
+#include "mirror/method_handle_impl.h"
+#include "mirror/method_handles_lookup.h"
+#include "mirror/method_type.h"
+#include "mirror/method.h"
+#include "mirror/proxy.h"
+#include "mirror/reference.h"
+#include "mirror/stack_trace_element.h"
+#include "mirror/string.h"
+#include "mirror/throwable.h"
+#include "mirror/var_handle.h"
+
+#include "class_root-inl.h"
+
+namespace art {
+
+#define MAKE_OBJECT_FOR_GDB(ROOT, NAME, MIRROR)                 \
+  template <> MIRROR* Handle<MIRROR>::GetFromGdb() {            \
+    return Get();                                               \
+  }                                                             \
+  template <> mirror::Object* Handle<MIRROR>::ObjectFromGdb() { \
+    return static_cast<mirror::Object*>(Get());                 \
+  }
+
+CLASS_MIRROR_ROOT_LIST(MAKE_OBJECT_FOR_GDB)
+
+#undef MAKE_OBJECT_FOR_GDB
+
+}  // namespace art
diff --git a/runtime/handle.h b/runtime/handle.h
index 6de4e88..b34d983 100644
--- a/runtime/handle.h
+++ b/runtime/handle.h
@@ -93,14 +93,6 @@
     return reference_->IsNull();
   }
 
-  ALWAYS_INLINE jobject ToJObject() const REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) {
-      // Special case so that we work with null handles.
-      return nullptr;
-    }
-    return reinterpret_cast<jobject>(reference_);
-  }
-
   ALWAYS_INLINE StackReference<mirror::Object>* GetReference() {
     return reference_;
   }
@@ -109,14 +101,17 @@
     return reference_;
   }
 
-  ALWAYS_INLINE bool operator!=(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
+  ALWAYS_INLINE bool operator!=(std::nullptr_t) const {
     return !IsNull();
   }
 
-  ALWAYS_INLINE bool operator==(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
+  ALWAYS_INLINE bool operator==(std::nullptr_t) const {
     return IsNull();
   }
 
+  mirror::Object* ObjectFromGdb() REQUIRES_SHARED(Locks::mutator_lock_);
+  T* GetFromGdb() REQUIRES_SHARED(Locks::mutator_lock_);
+
  protected:
   template<typename S>
   explicit Handle(StackReference<S>* reference)
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h
index 90cf597..3aa9e52 100644
--- a/runtime/handle_scope-inl.h
+++ b/runtime/handle_scope-inl.h
@@ -49,16 +49,19 @@
     : FixedSizeHandleScope<kNumReferences>(self->GetTopHandleScope(), fill_value),
       self_(self) {
   DCHECK_EQ(self, Thread::Current());
+  if (kDebugLocking) {
+    Locks::mutator_lock_->AssertSharedHeld(self_);
+  }
   self_->PushHandleScope(this);
 }
 
 template<size_t kNumReferences>
 inline StackHandleScope<kNumReferences>::~StackHandleScope() {
-  BaseHandleScope* top_handle_scope = self_->PopHandleScope();
-  DCHECK_EQ(top_handle_scope, this);
   if (kDebugLocking) {
     Locks::mutator_lock_->AssertSharedHeld(self_);
   }
+  BaseHandleScope* top_handle_scope = self_->PopHandleScope();
+  DCHECK_EQ(top_handle_scope, this);
 }
 
 inline size_t HandleScope::SizeOf(uint32_t num_references) {
@@ -214,10 +217,17 @@
       self_(self),
       current_scope_(&first_scope_),
       first_scope_(/*link=*/ nullptr) {
+  DCHECK_EQ(self, Thread::Current());
+  if (kDebugLocking) {
+    Locks::mutator_lock_->AssertSharedHeld(self_);
+  }
   self_->PushHandleScope(this);
 }
 
 inline VariableSizedHandleScope::~VariableSizedHandleScope() {
+  if (kDebugLocking) {
+    Locks::mutator_lock_->AssertSharedHeld(self_);
+  }
   BaseHandleScope* top_handle_scope = self_->PopHandleScope();
   DCHECK_EQ(top_handle_scope, this);
   // Don't delete first_scope_ since it is not heap allocated.
@@ -259,7 +269,6 @@
   }
 }
 
-
 }  // namespace art
 
 #endif  // ART_RUNTIME_HANDLE_SCOPE_INL_H_
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index b173453..58322d1 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -196,8 +196,9 @@
 
  private:
   explicit ALWAYS_INLINE FixedSizeHandleScope(BaseHandleScope* link,
-                                              ObjPtr<mirror::Object> fill_value = nullptr);
-  ALWAYS_INLINE ~FixedSizeHandleScope() {}
+                                              ObjPtr<mirror::Object> fill_value = nullptr)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  ALWAYS_INLINE ~FixedSizeHandleScope() REQUIRES_SHARED(Locks::mutator_lock_) {}
 
   template<class T>
   ALWAYS_INLINE MutableHandle<T> GetHandle(size_t i) REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -220,8 +221,10 @@
 class PACKED(4) StackHandleScope final : public FixedSizeHandleScope<kNumReferences> {
  public:
   explicit ALWAYS_INLINE StackHandleScope(Thread* self,
-                                          ObjPtr<mirror::Object> fill_value = nullptr);
-  ALWAYS_INLINE ~StackHandleScope();
+                                          ObjPtr<mirror::Object> fill_value = nullptr)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  ALWAYS_INLINE ~StackHandleScope() REQUIRES_SHARED(Locks::mutator_lock_);
 
   Thread* Self() const {
     return self_;
@@ -240,8 +243,8 @@
 // list.
 class VariableSizedHandleScope : public BaseHandleScope {
  public:
-  explicit VariableSizedHandleScope(Thread* const self);
-  ~VariableSizedHandleScope();
+  explicit VariableSizedHandleScope(Thread* const self) REQUIRES_SHARED(Locks::mutator_lock_);
+  ~VariableSizedHandleScope() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<class T>
   MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index a0dc0d2..f42ed49 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -17,12 +17,13 @@
 #include "hidden_api.h"
 
 #include <nativehelper/scoped_local_ref.h>
+#include <atomic>
 
 #include "art_field-inl.h"
 #include "art_method-inl.h"
+#include "compat_framework.h"
 #include "base/dumpable.h"
 #include "base/file_utils.h"
-#include "class_root.h"
 #include "dex/class_accessor-inl.h"
 #include "dex/dex_file_loader.h"
 #include "mirror/class_ext.h"
@@ -34,22 +35,26 @@
 namespace art {
 namespace hiddenapi {
 
-// Should be the same as dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_P_HIDDEN_APIS and
-// dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_Q_HIDDEN_APIS.
+// Should be the same as dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_P_HIDDEN_APIS,
+// dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_Q_HIDDEN_APIS, and
+// dalvik.system.VMRuntime.ALLOW_TEST_API_ACCESS.
 // Corresponds to bug ids.
 static constexpr uint64_t kHideMaxtargetsdkPHiddenApis = 149997251;
 static constexpr uint64_t kHideMaxtargetsdkQHiddenApis = 149994052;
+static constexpr uint64_t kAllowTestApiAccess = 166236554;
+
+static constexpr uint64_t kMaxLogWarnings = 100;
 
 // Set to true if we should always print a warning in logcat for all hidden API accesses, not just
-// dark grey and black. This can be set to true for developer preview / beta builds, but should be
-// false for public release builds.
+// conditionally and unconditionally blocked. This can be set to true for developer preview / beta
+// builds, but should be false for public release builds.
 // Note that when flipping this flag, you must also update the expectations of test 674-hiddenapi
-// as it affects whether or not we warn for light grey APIs that have been added to the exemptions
+// as it affects whether or not we warn for unsupported APIs that have been added to the exemptions
 // list.
 static constexpr bool kLogAllAccesses = false;
 
 // Exemptions for logcat warning. Following signatures do not produce a warning as app developers
-// should not be alerted on the usage of these greylised APIs. See b/154851649.
+// should not be alerted on the usage of these unsupported APIs. See b/154851649.
 static const std::vector<std::string> kWarningExemptions = {
     "Ljava/nio/Buffer;",
     "Llibcore/io/Memory;",
@@ -94,7 +99,8 @@
   // is set to "/system".
   if (ArtModuleRootDistinctFromAndroidRoot()) {
     if (LocationIsOnArtModule(dex_location.c_str()) ||
-        LocationIsOnConscryptModule(dex_location.c_str())) {
+        LocationIsOnConscryptModule(dex_location.c_str()) ||
+        LocationIsOnI18nModule(dex_location.c_str())) {
       return Domain::kCorePlatform;
     }
 
@@ -107,9 +113,16 @@
     return Domain::kPlatform;
   }
 
+  if (LocationIsOnSystemExtFramework(dex_location.c_str())) {
+    return Domain::kPlatform;
+  }
+
   if (class_loader.IsNull()) {
-    LOG(WARNING) << "DexFile " << dex_location
-        << " is in boot class path but is not in a known location";
+    if (kIsTargetBuild && !kIsTargetLinux) {
+      // This is unexpected only when running on Android.
+      LOG(WARNING) << "DexFile " << dex_location
+          << " is in boot class path but is not in a known location";
+    }
     return Domain::kPlatform;
   }
 
@@ -131,7 +144,6 @@
   // API that cannot be otherwise expressed and propagated through tooling (b/144502743).
   jfieldID private_core_platform_api_fields[] = {
     WellKnownClasses::java_io_FileDescriptor_descriptor,
-    WellKnownClasses::java_io_FileDescriptor_ownerId,
     WellKnownClasses::java_nio_Buffer_address,
     WellKnownClasses::java_nio_Buffer_elementSizeShift,
     WellKnownClasses::java_nio_Buffer_limit,
@@ -235,9 +247,22 @@
 void MemberSignature::WarnAboutAccess(AccessMethod access_method,
                                       hiddenapi::ApiList list,
                                       bool access_denied) {
+  static std::atomic<uint64_t> log_warning_count_ = 0;
+  if (log_warning_count_ > kMaxLogWarnings) {
+    return;
+  }
   LOG(WARNING) << "Accessing hidden " << (type_ == kField ? "field " : "method ")
                << Dumpable<MemberSignature>(*this) << " (" << list << ", " << access_method
                << (access_denied ? ", denied)" : ", allowed)");
+  if (access_denied && list.IsTestApi()) {
+    // see b/177047045 for more details about test api access getting denied
+    LOG(WARNING) << "If this is a platform test consider enabling "
+                 << "VMRuntime.ALLOW_TEST_API_ACCESS change id for this package.";
+  }
+  if (log_warning_count_ >= kMaxLogWarnings) {
+    LOG(WARNING) << "Reached maximum number of hidden api access warnings.";
+  }
+  ++log_warning_count_;
 }
 
 bool MemberSignature::Equals(const MemberSignature& other) {
@@ -406,7 +431,7 @@
           << "Only proxy classes are expected not to have a class def";
       DCHECK(kMemberIsField)
           << "Interface methods should be inspected instead of proxy class methods";
-      flags = ApiList::Greylist();
+      flags = ApiList::Unsupported();
     } else {
       uint32_t member_index = GetMemberDexIndex(member);
       auto fn_visit = [&](const AccessorType& dex_member) {
@@ -470,6 +495,7 @@
 bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod access_method) {
   DCHECK(member != nullptr);
   Runtime* runtime = Runtime::Current();
+  CompatFramework& compatFramework = runtime->GetCompatFramework();
 
   EnforcementPolicy hiddenApiPolicy = runtime->GetHiddenApiEnforcementPolicy();
   DCHECK(hiddenApiPolicy != EnforcementPolicy::kDisabled)
@@ -477,11 +503,11 @@
 
   MemberSignature member_signature(member);
 
-  // Check for an exemption first. Exempted APIs are treated as white list.
+  // Check for an exemption first. Exempted APIs are treated as SDK.
   if (member_signature.DoesPrefixMatchAny(runtime->GetHiddenApiExemptions())) {
     // Avoid re-examining the exemption list next time.
     // Note this results in no warning for the member, which seems like what one would expect.
-    // Exemptions effectively adds new members to the whitelist.
+    // Exemptions effectively adds new members to the public API list.
     MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
     return false;
   }
@@ -490,25 +516,27 @@
 
   bool deny_access = false;
   if (hiddenApiPolicy == EnforcementPolicy::kEnabled) {
-    if (testApiPolicy == EnforcementPolicy::kDisabled && api_list.IsTestApi()) {
+    if (api_list.IsTestApi() &&
+      (testApiPolicy == EnforcementPolicy::kDisabled ||
+        compatFramework.IsChangeEnabled(kAllowTestApiAccess))) {
       deny_access = false;
     } else {
       switch (api_list.GetMaxAllowedSdkVersion()) {
         case SdkVersion::kP:
-          deny_access = runtime->isChangeEnabled(kHideMaxtargetsdkPHiddenApis);
+          deny_access = compatFramework.IsChangeEnabled(kHideMaxtargetsdkPHiddenApis);
           break;
         case SdkVersion::kQ:
-          deny_access = runtime->isChangeEnabled(kHideMaxtargetsdkQHiddenApis);
+          deny_access = compatFramework.IsChangeEnabled(kHideMaxtargetsdkQHiddenApis);
           break;
         default:
           deny_access = IsSdkVersionSetAndMoreThan(runtime->GetTargetSdkVersion(),
-                                                         api_list.GetMaxAllowedSdkVersion());
+                                                   api_list.GetMaxAllowedSdkVersion());
       }
     }
   }
 
   if (access_method != AccessMethod::kNone) {
-    // Warn if non-greylisted signature is being accessed or it is not exempted.
+    // Warn if blocked signature is being accessed or it is not exempted.
     if (deny_access || !member_signature.DoesPrefixMatchAny(kWarningExemptions)) {
       // Print a log message with information about this class member access.
       // We do this if we're about to deny access, or the app is debuggable.
@@ -533,7 +561,7 @@
       }
     }
 
-    // If this access was not denied, move the member into whitelist and skip
+    // If this access was not denied, flag member as SDK and skip
     // the warning the next time the member is accessed.
     if (!deny_access) {
       MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 8817c63..16c2fe8 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -38,7 +38,7 @@
 enum class EnforcementPolicy {
   kDisabled             = 0,
   kJustWarn             = 1,  // keep checks enabled, but allow everything (enables logging)
-  kEnabled              = 2,  // ban dark grey & blacklist
+  kEnabled              = 2,  // ban conditionally blocked & blocklist
   kMax = kEnabled,
 };
 
@@ -203,8 +203,8 @@
   void LogAccessToEventLog(uint32_t sampled_value, AccessMethod access_method, bool access_denied);
 
   // Calls back into managed code to notify VMRuntime.nonSdkApiUsageConsumer that
-  // |member| was accessed. This is usually called when an API is on the black,
-  // dark grey or light grey lists. Given that the callback can execute arbitrary
+  // |member| was accessed. This is usually called when an API is unsupported,
+  // conditionally or unconditionally blocked. Given that the callback can execute arbitrary
   // code, a call to this method can result in thread suspension.
   void NotifyHiddenApiListener(AccessMethod access_method);
 };
@@ -241,7 +241,7 @@
   ApiList api_list(dex_flags);
   DCHECK(api_list.IsValid());
 
-  if (api_list.Contains(ApiList::Whitelist())) {
+  if (api_list.Contains(ApiList::Sdk())) {
     runtime_flags |= kAccPublicApi;
   } else {
     // Only add domain-specific flags for non-public API members.
@@ -284,6 +284,7 @@
       case Intrinsics::kSystemArrayCopyChar:
       case Intrinsics::kStringGetCharsNoCheck:
       case Intrinsics::kReferenceGetReferent:
+      case Intrinsics::kReferenceRefersTo:
       case Intrinsics::kMemoryPeekByte:
       case Intrinsics::kMemoryPokeByte:
       case Intrinsics::kCRC32Update:
@@ -398,6 +399,23 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   DCHECK(member != nullptr);
 
+  // First check if we have an explicit sdk checker installed that should be used to
+  // verify access. If so, make the decision based on it.
+  //
+  // This is used during off-device AOT compilation which may want to generate verification
+  // metadata only for a specific list of public SDKs. Note that the check here is made
+  // based on descriptor equality and it's aim to further restrict a symbol that would
+  // otherwise be resolved.
+  //
+  // The check only applies to boot classpaths dex files.
+  Runtime* runtime = Runtime::Current();
+  if (UNLIKELY(runtime->IsAotCompiler())) {
+    if (member->GetDeclaringClass()->GetClassLoader() == nullptr &&
+        runtime->GetClassLinker()->DenyAccessBasedOnPublicSdk(member)) {
+      return true;
+    }
+  }
+
   // Get the runtime flags encoded in member's access flags.
   // Note: this works for proxy methods because they inherit access flags from their
   // respective interface methods.
@@ -430,7 +448,7 @@
       DCHECK(!callee_context.IsApplicationDomain());
 
       // Exit early if access checks are completely disabled.
-      EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
+      EnforcementPolicy policy = runtime->GetHiddenApiEnforcementPolicy();
       if (policy == EnforcementPolicy::kDisabled) {
         return false;
       }
diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc
index b9214ff..7cec10c 100644
--- a/runtime/hidden_api_test.cc
+++ b/runtime/hidden_api_test.cc
@@ -19,6 +19,7 @@
 #include <fstream>
 #include <sstream>
 
+#include "android-base/stringprintf.h"
 #include "base/file_utils.h"
 #include "base/sdk_version.h"
 #include "base/stl_util.h"
@@ -29,13 +30,102 @@
 
 namespace art {
 
+using android::base::StringPrintf;
 using hiddenapi::detail::MemberSignature;
 using hiddenapi::detail::ShouldDenyAccessToMemberImpl;
 
-// Should be the same as dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_P_HIDDEN_APIS and
-// dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_Q_HIDDEN_APIS.
+// Should be the same as dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_P_HIDDEN_APIS,
+// dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_Q_HIDDEN_APIS, and
+// dalvik.system.VMRuntime.EXEMPT_TEST_API_ACCESS_VERIFICATION.
 static constexpr uint64_t kHideMaxtargetsdkPHiddenApis = 149997251;
 static constexpr uint64_t kHideMaxtargetsdkQHiddenApis = 149994052;
+static constexpr uint64_t kAllowTestApiAccess = 166236554;
+
+
+static bool Copy(const std::string& src, const std::string& dst, /*out*/ std::string* error_msg) {
+  std::ifstream  src_stream(src, std::ios::binary);
+  std::ofstream  dst_stream(dst, std::ios::binary);
+  dst_stream << src_stream.rdbuf();
+  src_stream.close();
+  dst_stream.close();
+  if (src_stream.good() && dst_stream.good()) {
+    return true;
+  } else {
+    *error_msg = "Copy " + src + " => " + dst + " (src_good="
+        + (src_stream.good() ? "true" : "false") + ", dst_good="
+        + (dst_stream.good() ? "true" : "false") + ")";
+    return false;
+  }
+}
+
+static bool LoadDexFiles(const std::string& path,
+                         ScopedObjectAccess& soa,
+                         /* out */ std::vector<std::unique_ptr<const DexFile>>* dex_files,
+                         /* out */ ObjPtr<mirror::ClassLoader>* class_loader,
+                         /* out */ std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
+  if (!ArtDexFileLoader().Open(path.c_str(),
+                               path,
+                               /* verify= */ true,
+                               /* verify_checksum= */ true,
+                               error_msg,
+                               dex_files)) {
+    return false;
+  }
+
+  ClassLinker* const linker = Runtime::Current()->GetClassLinker();
+
+  StackHandleScope<2> hs(soa.Self());
+  Handle<mirror::Class> h_class = hs.NewHandle(soa.Decode<mirror::Class>(
+      WellKnownClasses::dalvik_system_PathClassLoader));
+  Handle<mirror::ClassLoader> h_loader = hs.NewHandle(linker->CreateWellKnownClassLoader(
+      soa.Self(),
+      MakeNonOwningPointerVector(*dex_files),
+      h_class,
+      /* parent_loader= */ ScopedNullHandle<mirror::ClassLoader>(),
+      /* shared_libraries= */ ScopedNullHandle<mirror::ObjectArray<mirror::ClassLoader>>()));
+  for (const auto& dex_file : *dex_files) {
+    linker->RegisterDexFile(*dex_file.get(), h_loader.Get());
+  }
+
+  *class_loader = h_loader.Get();
+  return true;
+}
+
+static bool Remove(const std::string& path, /*out*/ std::string* error_msg) {
+  if (TEMP_FAILURE_RETRY(remove(path.c_str())) == 0) {
+    return true;
+  }
+  *error_msg = StringPrintf("Unable to remove(\"%s\"): %s", path.c_str(), strerror(errno));
+  return false;
+}
+
+static bool CheckAllDexFilesInDomain(ObjPtr<mirror::ClassLoader> loader,
+                                     const std::vector<std::unique_ptr<const DexFile>>& dex_files,
+                                     hiddenapi::Domain expected_domain,
+                                     /* out */ std::string* error_msg)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  for (const auto& dex_file : dex_files) {
+    hiddenapi::AccessContext context(loader, dex_file.get());
+    if (context.GetDomain() != expected_domain) {
+      std::stringstream ss;
+      ss << dex_file->GetLocation() << ": access context domain does not match "
+          << "(expected=" << static_cast<uint32_t>(expected_domain)
+          << ", actual=" << static_cast<uint32_t>(context.GetDomain()) << ")";
+      *error_msg = ss.str();
+      return false;
+    }
+    if (dex_file->GetHiddenapiDomain() != expected_domain) {
+      std::stringstream ss;
+      ss << dex_file->GetLocation() << ": dex file domain does not match "
+          << "(expected=" << static_cast<uint32_t>(expected_domain)
+          << ", actual=" << static_cast<uint32_t>(dex_file->GetHiddenapiDomain()) << ")";
+      *error_msg = ss.str();
+      return false;
+    }
+  }
+
+  return true;
+}
 
 class HiddenApiTest : public CommonRuntimeTest {
  protected:
@@ -48,23 +138,23 @@
     bool started = runtime_->Start();
     CHECK(started);
 
-    class1_field1_ = getArtField("mypackage/packagea/Class1", "field1", "I");
-    class1_field12_ = getArtField("mypackage/packagea/Class1", "field12", "I");
-    class1_init_ = getArtMethod("mypackage/packagea/Class1", "<init>", "()V");
-    class1_method1_ = getArtMethod("mypackage/packagea/Class1", "method1", "()V");
-    class1_method1_i_ = getArtMethod("mypackage/packagea/Class1", "method1", "(I)V");
-    class1_method12_ = getArtMethod("mypackage/packagea/Class1", "method12", "()V");
-    class12_field1_ = getArtField("mypackage/packagea/Class12", "field1", "I");
-    class12_method1_ = getArtMethod("mypackage/packagea/Class12", "method1", "()V");
-    class2_field1_ = getArtField("mypackage/packagea/Class2", "field1", "I");
-    class2_method1_ = getArtMethod("mypackage/packagea/Class2", "method1", "()V");
-    class2_method1_i_ = getArtMethod("mypackage/packagea/Class2", "method1", "(I)V");
-    class3_field1_ = getArtField("mypackage/packageb/Class3", "field1", "I");
-    class3_method1_ = getArtMethod("mypackage/packageb/Class3", "method1", "()V");
-    class3_method1_i_ = getArtMethod("mypackage/packageb/Class3", "method1", "(I)V");
+    class1_field1_ = GetArtField("mypackage/packagea/Class1", "field1", "I");
+    class1_field12_ = GetArtField("mypackage/packagea/Class1", "field12", "I");
+    class1_init_ = GetArtMethod("mypackage/packagea/Class1", "<init>", "()V");
+    class1_method1_ = GetArtMethod("mypackage/packagea/Class1", "method1", "()V");
+    class1_method1_i_ = GetArtMethod("mypackage/packagea/Class1", "method1", "(I)V");
+    class1_method12_ = GetArtMethod("mypackage/packagea/Class1", "method12", "()V");
+    class12_field1_ = GetArtField("mypackage/packagea/Class12", "field1", "I");
+    class12_method1_ = GetArtMethod("mypackage/packagea/Class12", "method1", "()V");
+    class2_field1_ = GetArtField("mypackage/packagea/Class2", "field1", "I");
+    class2_method1_ = GetArtMethod("mypackage/packagea/Class2", "method1", "()V");
+    class2_method1_i_ = GetArtMethod("mypackage/packagea/Class2", "method1", "(I)V");
+    class3_field1_ = GetArtField("mypackage/packageb/Class3", "field1", "I");
+    class3_method1_ = GetArtMethod("mypackage/packageb/Class3", "method1", "()V");
+    class3_method1_i_ = GetArtMethod("mypackage/packageb/Class3", "method1", "(I)V");
   }
 
-  ArtMethod* getArtMethod(const char* class_name, const char* name, const char* signature) {
+  ArtMethod* GetArtMethod(const char* class_name, const char* name, const char* signature) {
     JNIEnv* env = Thread::Current()->GetJniEnv();
     jclass klass = env->FindClass(class_name);
     jmethodID method_id = env->GetMethodID(klass, name, signature);
@@ -72,7 +162,7 @@
     return art_method;
   }
 
-  ArtField* getArtField(const char* class_name, const char* name, const char* signature) {
+  ArtField* GetArtField(const char* class_name, const char* name, const char* signature) {
     JNIEnv* env = Thread::Current()->GetJniEnv();
     jclass klass = env->FindClass(class_name);
     jfieldID field_id = env->GetFieldID(klass, name, signature);
@@ -80,14 +170,15 @@
     return art_field;
   }
 
-  void setChangeIdState(uint64_t change, bool enabled) {
-    std::set<uint64_t> disabled_changes = runtime_->GetDisabledCompatChanges();
+  void SetChangeIdState(uint64_t change, bool enabled) {
+    CompatFramework& compat_framework = runtime_->GetCompatFramework();
+    std::set<uint64_t> disabled_changes = compat_framework.GetDisabledCompatChanges();
     if (enabled) {
       disabled_changes.erase(change);
     } else {
       disabled_changes.insert(change);
     }
-    runtime_->SetDisabledCompatChanges(disabled_changes);
+    compat_framework.SetDisabledCompatChanges(disabled_changes);
   }
 
   bool ShouldDenyAccess(hiddenapi::ApiList list) REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -99,6 +190,25 @@
                                         /* access_method= */ hiddenapi::AccessMethod::kNone);
   }
 
+  void TestLocation(const std::string& location, hiddenapi::Domain expected_domain) {
+    ScopedObjectAccess soa(Thread::Current());
+    std::vector<std::unique_ptr<const DexFile>> dex_files;
+    std::string error_msg;
+    ObjPtr<mirror::ClassLoader> class_loader;
+
+    ASSERT_TRUE(Copy(GetTestDexFileName("Main"), location, &error_msg)) << error_msg;
+    ASSERT_TRUE(LoadDexFiles(location, soa, &dex_files, &class_loader, &error_msg))
+        << error_msg;
+    ASSERT_GE(dex_files.size(), 1u);
+    ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
+                                         dex_files,
+                                         expected_domain,
+                                         &error_msg)) << error_msg;
+
+    dex_files.clear();
+    ASSERT_TRUE(Remove(location, &error_msg)) << error_msg;
+  }
+
  protected:
   Thread* self_;
   jobject jclass_loader_;
@@ -122,67 +232,85 @@
   ScopedObjectAccess soa(self_);
 
   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kJustWarn);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), false);
 
   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
   runtime_->SetTargetSdkVersion(
-      static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxO().GetMaxAllowedSdkVersion()));
-  setChangeIdState(kHideMaxtargetsdkPHiddenApis, false);
-  setChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
+      static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetO().GetMaxAllowedSdkVersion()));
+  SetChangeIdState(kHideMaxtargetsdkPHiddenApis, false);
+  SetChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
 
   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
   runtime_->SetTargetSdkVersion(
-      static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxO().GetMaxAllowedSdkVersion()) + 1);
-  setChangeIdState(kHideMaxtargetsdkPHiddenApis, false);
-  setChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), true);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
-  setChangeIdState(kHideMaxtargetsdkQHiddenApis, true);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), true);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), true);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
+      static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetO().GetMaxAllowedSdkVersion()) + 1);
+  SetChangeIdState(kHideMaxtargetsdkPHiddenApis, false);
+  SetChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
+  SetChangeIdState(kHideMaxtargetsdkQHiddenApis, true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
 
   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
   runtime_->SetTargetSdkVersion(
-      static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxP().GetMaxAllowedSdkVersion()) + 1);
-  setChangeIdState(kHideMaxtargetsdkPHiddenApis, true);
-  setChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), true);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), true);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
+      static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetP().GetMaxAllowedSdkVersion()) + 1);
+  SetChangeIdState(kHideMaxtargetsdkPHiddenApis, true);
+  SetChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
 
   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
   runtime_->SetTargetSdkVersion(
-      static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxQ().GetMaxAllowedSdkVersion()) + 1);
-  setChangeIdState(kHideMaxtargetsdkPHiddenApis, true);
-  setChangeIdState(kHideMaxtargetsdkQHiddenApis, true);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), true);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), true);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), true);
-  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
+      static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetQ().GetMaxAllowedSdkVersion()) + 1);
+  SetChangeIdState(kHideMaxtargetsdkPHiddenApis, true);
+  SetChangeIdState(kHideMaxtargetsdkQHiddenApis, true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
+
+  runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
+  runtime_->SetTargetSdkVersion(
+      static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetR().GetMaxAllowedSdkVersion()) + 1);
+  SetChangeIdState(kHideMaxtargetsdkPHiddenApis, true);
+  SetChangeIdState(kHideMaxtargetsdkQHiddenApis, true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), true);
+  ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
 }
 
 TEST_F(HiddenApiTest, CheckTestApiEnforcement) {
@@ -190,37 +318,61 @@
 
   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
   runtime_->SetTargetSdkVersion(
-      static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxQ().GetMaxAllowedSdkVersion()) + 1);
+      static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetR().GetMaxAllowedSdkVersion()) + 1);
 
   // Default case where all TestApis are treated like non-TestApi.
   runtime_->SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
+  SetChangeIdState(kAllowTestApiAccess, false);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Whitelist()), false);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Sdk()), false);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Greylist()), false);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Unsupported()), false);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxQ()), true);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetR()), true);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxP()), true);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetQ()), true);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxO()), true);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetP()), true);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blacklist()), true);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetO()), true);
+  ASSERT_EQ(
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blocked()), true);
 
   // A case where we want to allow access to TestApis.
   runtime_->SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kDisabled);
+  SetChangeIdState(kAllowTestApiAccess, false);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Whitelist()), false);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Sdk()), false);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Greylist()), false);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Unsupported()), false);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxQ()), false);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetR()), false);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxP()), false);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetQ()), false);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxO()), false);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetP()), false);
   ASSERT_EQ(
-      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blacklist()), false);
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetO()), false);
+  ASSERT_EQ(
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blocked()), false);
+
+  // A second case where we want to allow access to TestApis.
+  runtime_->SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
+  SetChangeIdState(kAllowTestApiAccess, true);
+  ASSERT_EQ(
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Sdk()), false);
+  ASSERT_EQ(
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Unsupported()), false);
+  ASSERT_EQ(
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetR()), false);
+  ASSERT_EQ(
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetQ()), false);
+  ASSERT_EQ(
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetP()), false);
+  ASSERT_EQ(
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetO()), false);
+  ASSERT_EQ(
+      ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blocked()), false);
 }
 
 TEST_F(HiddenApiTest, CheckMembersRead) {
@@ -463,178 +615,69 @@
   ASSERT_EQ("L$Proxy1234;->interfaces:[Ljava/lang/Class;", ss_field.str());
 }
 
-static bool Copy(const std::string& src, const std::string& dst, /*out*/ std::string* error_msg) {
-  std::ifstream  src_stream(src, std::ios::binary);
-  std::ofstream  dst_stream(dst, std::ios::binary);
-  dst_stream << src_stream.rdbuf();
-  src_stream.close();
-  dst_stream.close();
-  if (src_stream.good() && dst_stream.good()) {
-    return true;
-  } else {
-    *error_msg = "Copy " + src + " => " + dst + " (src_good="
-        + (src_stream.good() ? "true" : "false") + ", dst_good="
-        + (dst_stream.good() ? "true" : "false") + ")";
-    return false;
-  }
-}
-
-static bool LoadDexFiles(const std::string& path,
-                         ScopedObjectAccess& soa,
-                         /* out */ std::vector<std::unique_ptr<const DexFile>>* dex_files,
-                         /* out */ ObjPtr<mirror::ClassLoader>* class_loader,
-                         /* out */ std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
-  if (!ArtDexFileLoader().Open(path.c_str(),
-                               path,
-                               /* verify= */ true,
-                               /* verify_checksum= */ true,
-                               error_msg,
-                               dex_files)) {
-    return false;
-  }
-
-  ClassLinker* const linker = Runtime::Current()->GetClassLinker();
-
-  StackHandleScope<2> hs(soa.Self());
-  Handle<mirror::Class> h_class = hs.NewHandle(soa.Decode<mirror::Class>(
-      WellKnownClasses::dalvik_system_PathClassLoader));
-  Handle<mirror::ClassLoader> h_loader = hs.NewHandle(linker->CreateWellKnownClassLoader(
-      soa.Self(),
-      MakeNonOwningPointerVector(*dex_files),
-      h_class,
-      /* parent_loader= */ ScopedNullHandle<mirror::ClassLoader>(),
-      /* shared_libraries= */ ScopedNullHandle<mirror::ObjectArray<mirror::ClassLoader>>()));
-  for (const auto& dex_file : *dex_files) {
-    linker->RegisterDexFile(*dex_file.get(), h_loader.Get());
-  }
-
-  *class_loader = h_loader.Get();
-  return true;
-}
-
-static bool CheckAllDexFilesInDomain(ObjPtr<mirror::ClassLoader> loader,
-                                     const std::vector<std::unique_ptr<const DexFile>>& dex_files,
-                                     hiddenapi::Domain expected_domain,
-                                     /* out */ std::string* error_msg)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  for (const auto& dex_file : dex_files) {
-    hiddenapi::AccessContext context(loader, dex_file.get());
-    if (context.GetDomain() != expected_domain) {
-      std::stringstream ss;
-      ss << dex_file->GetLocation() << ": access context domain does not match "
-          << "(expected=" << static_cast<uint32_t>(expected_domain)
-          << ", actual=" << static_cast<uint32_t>(context.GetDomain()) << ")";
-      *error_msg = ss.str();
-      return false;
-    }
-    if (dex_file->GetHiddenapiDomain() != expected_domain) {
-      std::stringstream ss;
-      ss << dex_file->GetLocation() << ": dex file domain does not match "
-          << "(expected=" << static_cast<uint32_t>(expected_domain)
-          << ", actual=" << static_cast<uint32_t>(dex_file->GetHiddenapiDomain()) << ")";
-      *error_msg = ss.str();
-      return false;
-    }
-  }
-
-  return true;
-}
-
 TEST_F(HiddenApiTest, DexDomain_DataDir) {
   // Load file from a non-system directory and check that it is not flagged as framework.
   std::string data_location_path = android_data_ + "/foo.jar";
   ASSERT_FALSE(LocationIsOnSystemFramework(data_location_path.c_str()));
-
-  ScopedObjectAccess soa(Thread::Current());
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-  std::string error_msg;
-  ObjPtr<mirror::ClassLoader> class_loader;
-
-  ASSERT_TRUE(Copy(GetTestDexFileName("Main"), data_location_path, &error_msg)) << error_msg;
-  ASSERT_TRUE(LoadDexFiles(data_location_path, soa, &dex_files, &class_loader, &error_msg))
-      << error_msg;
-  ASSERT_GE(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
-                                       dex_files,
-                                       hiddenapi::Domain::kApplication,
-                                       &error_msg)) << error_msg;
-
-  dex_files.clear();
-  ASSERT_EQ(0, remove(data_location_path.c_str()));
+  TestLocation(data_location_path, hiddenapi::Domain::kApplication);
 }
 
 TEST_F(HiddenApiTest, DexDomain_SystemDir) {
   // Load file from a system, non-framework directory and check that it is not flagged as framework.
   std::string system_location_path = GetAndroidRoot() + "/foo.jar";
   ASSERT_FALSE(LocationIsOnSystemFramework(system_location_path.c_str()));
+  TestLocation(system_location_path, hiddenapi::Domain::kApplication);
+}
 
-  ScopedObjectAccess soa(Thread::Current());
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-  std::string error_msg;
-  ObjPtr<mirror::ClassLoader> class_loader;
+TEST_F(HiddenApiTest, DexDomain_SystemExtDir) {
+  // Load file from a system_ext, non-framework directory and check that it is not flagged as
+  // framework.
+  std::string system_ext_location_path = android_system_ext_ + "/foo.jar";
+  ASSERT_FALSE(LocationIsOnSystemExtFramework(system_ext_location_path.c_str()));
+  TestLocation(system_ext_location_path, hiddenapi::Domain::kApplication);
+}
 
-  ASSERT_TRUE(Copy(GetTestDexFileName("Main"), system_location_path, &error_msg)) << error_msg;
-  ASSERT_TRUE(LoadDexFiles(system_location_path, soa, &dex_files, &class_loader, &error_msg))
-      << error_msg;
-  ASSERT_GE(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
-                                       dex_files,
-                                       hiddenapi::Domain::kApplication,
-                                       &error_msg)) << error_msg;
-
-  dex_files.clear();
-  ASSERT_EQ(0, remove(system_location_path.c_str()));
+TEST_F(HiddenApiTest, DexDomain_SystemSystemExtDir) {
+  // Load file from a system/system_ext, non-framework directory and check that it is not flagged as
+  // framework.
+  std::filesystem::create_directory(GetAndroidRoot() + "/system_ext");
+  std::string system_ext_location_path =  GetAndroidRoot() + "/system_ext/foo.jar";
+  ASSERT_FALSE(LocationIsOnSystemExtFramework(system_ext_location_path.c_str()));
+  TestLocation(system_ext_location_path, hiddenapi::Domain::kApplication);
 }
 
 TEST_F(HiddenApiTest, DexDomain_SystemFrameworkDir) {
   // Load file from a system/framework directory and check that it is flagged as a framework dex.
+  std::filesystem::create_directory(GetAndroidRoot() + "/framework");
   std::string system_framework_location_path = GetAndroidRoot() + "/framework/foo.jar";
   ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_location_path.c_str()));
+  TestLocation(system_framework_location_path, hiddenapi::Domain::kPlatform);
+}
 
-  ScopedObjectAccess soa(Thread::Current());
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-  std::string error_msg;
-  ObjPtr<mirror::ClassLoader> class_loader;
+TEST_F(HiddenApiTest, DexDomain_SystemExtFrameworkDir) {
+  // Load file from a system_ext/framework directory and check that it is flagged as a framework dex.
+  std::filesystem::create_directory(android_system_ext_ + "/framework");
+  std::string system_ext_framework_location_path = android_system_ext_ + "/framework/foo.jar";
+  ASSERT_TRUE(LocationIsOnSystemExtFramework(system_ext_framework_location_path.c_str()));
+  TestLocation(system_ext_framework_location_path, hiddenapi::Domain::kPlatform);
+}
 
-  ASSERT_TRUE(Copy(GetTestDexFileName("Main"), system_framework_location_path, &error_msg))
-      << error_msg;
-  ASSERT_TRUE(LoadDexFiles(system_framework_location_path,
-                           soa,
-                           &dex_files,
-                           &class_loader,
-                           &error_msg)) << error_msg;
-  ASSERT_GE(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
-                                       dex_files,
-                                       hiddenapi::Domain::kPlatform,
-                                       &error_msg)) << error_msg;
-
-  dex_files.clear();
-  ASSERT_EQ(0, remove(system_framework_location_path.c_str()));
+TEST_F(HiddenApiTest, DexDomain_SystemSystemExtFrameworkDir) {
+  // Load file from a system/system_ext/framework directory and check that it is flagged as a
+  // framework dex.
+  std::filesystem::create_directory(GetAndroidRoot() + "/system_ext");
+  std::filesystem::create_directory(GetAndroidRoot() + "/system_ext/framework");
+  std::string system_ext_framework_location_path =
+       GetAndroidRoot() + "/system_ext/framework/foo.jar";
+  ASSERT_TRUE(LocationIsOnSystemExtFramework(system_ext_framework_location_path.c_str()));
+  TestLocation(system_ext_framework_location_path, hiddenapi::Domain::kPlatform);
 }
 
 TEST_F(HiddenApiTest, DexDomain_DataDir_MultiDex) {
   // Load multidex file from a non-system directory and check that it is not flagged as framework.
   std::string data_multi_location_path = android_data_ + "/multifoo.jar";
   ASSERT_FALSE(LocationIsOnSystemFramework(data_multi_location_path.c_str()));
-
-  ScopedObjectAccess soa(Thread::Current());
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-  std::string error_msg;
-  ObjPtr<mirror::ClassLoader> class_loader;
-
-  ASSERT_TRUE(Copy(GetTestDexFileName("MultiDex"), data_multi_location_path, &error_msg))
-      << error_msg;
-  ASSERT_TRUE(LoadDexFiles(data_multi_location_path, soa, &dex_files, &class_loader, &error_msg))
-      << error_msg;
-  ASSERT_GE(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
-                                       dex_files,
-                                       hiddenapi::Domain::kApplication,
-                                       &error_msg)) << error_msg;
-
-  dex_files.clear();
-  ASSERT_EQ(0, remove(data_multi_location_path.c_str()));
+  TestLocation(data_multi_location_path, hiddenapi::Domain::kApplication);
 }
 
 TEST_F(HiddenApiTest, DexDomain_SystemDir_MultiDex) {
@@ -642,53 +685,55 @@
   // as framework.
   std::string system_multi_location_path = GetAndroidRoot() + "/multifoo.jar";
   ASSERT_FALSE(LocationIsOnSystemFramework(system_multi_location_path.c_str()));
+  TestLocation(system_multi_location_path, hiddenapi::Domain::kApplication);
+}
 
-  ScopedObjectAccess soa(Thread::Current());
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-  std::string error_msg;
-  ObjPtr<mirror::ClassLoader> class_loader;
+TEST_F(HiddenApiTest, DexDomain_SystemExtDir_MultiDex) {
+  // Load multidex file from a system_ext, non-framework directory and check that it is not flagged
+  // as framework.
+  std::string system_ext_multi_location_path = android_system_ext_ + "/multifoo.jar";
+  ASSERT_FALSE(LocationIsOnSystemExtFramework(system_ext_multi_location_path.c_str()));
+  TestLocation(system_ext_multi_location_path, hiddenapi::Domain::kApplication);
+}
 
-  ASSERT_TRUE(Copy(GetTestDexFileName("MultiDex"), system_multi_location_path, &error_msg))
-      << error_msg;
-  ASSERT_TRUE(LoadDexFiles(system_multi_location_path, soa, &dex_files, &class_loader, &error_msg))
-      << error_msg;
-  ASSERT_GT(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
-                                       dex_files,
-                                       hiddenapi::Domain::kApplication,
-                                       &error_msg)) << error_msg;
-
-  dex_files.clear();
-  ASSERT_EQ(0, remove(system_multi_location_path.c_str()));
+TEST_F(HiddenApiTest, DexDomain_SystemSystemExtDir_MultiDex) {
+  // Load multidex file from a system/system_ext, non-framework directory and check that it is not
+  // flagged as framework.
+  std::filesystem::create_directory(GetAndroidRoot() + "/system_ext");
+  std::string system_ext_multi_location_path =
+      GetAndroidRoot() + "/system_ext/multifoo.jar";
+  ASSERT_FALSE(LocationIsOnSystemExtFramework(system_ext_multi_location_path.c_str()));
+  TestLocation(system_ext_multi_location_path, hiddenapi::Domain::kApplication);
 }
 
 TEST_F(HiddenApiTest, DexDomain_SystemFrameworkDir_MultiDex) {
   // Load multidex file from a system/framework directory and check that it is flagged as a
   // framework dex.
+  std::filesystem::create_directory(GetAndroidRoot() + "/framework");
   std::string system_framework_multi_location_path = GetAndroidRoot() + "/framework/multifoo.jar";
   ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_multi_location_path.c_str()));
+  TestLocation(system_framework_multi_location_path, hiddenapi::Domain::kPlatform);
+}
 
-  ScopedObjectAccess soa(Thread::Current());
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-  std::string error_msg;
-  ObjPtr<mirror::ClassLoader> class_loader;
+TEST_F(HiddenApiTest, DexDomain_SystemExtFrameworkDir_MultiDex) {
+  // Load multidex file from a system_ext/framework directory and check that it is flagged as a
+  // framework dex.
+  std::filesystem::create_directory(android_system_ext_ + "/framework");
+  std::string system_ext_framework_multi_location_path =
+      android_system_ext_ + "/framework/multifoo.jar";
+  ASSERT_TRUE(LocationIsOnSystemExtFramework(system_ext_framework_multi_location_path.c_str()));
+  TestLocation(system_ext_framework_multi_location_path, hiddenapi::Domain::kPlatform);
+}
 
-  ASSERT_TRUE(Copy(GetTestDexFileName("MultiDex"),
-                   system_framework_multi_location_path,
-                   &error_msg)) << error_msg;
-  ASSERT_TRUE(LoadDexFiles(system_framework_multi_location_path,
-                           soa,
-                           &dex_files,
-                           &class_loader,
-                           &error_msg)) << error_msg;
-  ASSERT_GT(dex_files.size(), 1u);
-  ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
-                                       dex_files,
-                                       hiddenapi::Domain::kPlatform,
-                                       &error_msg)) << error_msg;
-
-  dex_files.clear();
-  ASSERT_EQ(0, remove(system_framework_multi_location_path.c_str()));
+TEST_F(HiddenApiTest, DexDomain_SystemSystemExtFrameworkDir_MultiDex) {
+  // Load multidex file from a system/system_ext/framework directory and check that it is flagged
+  // as a framework dex.
+  std::filesystem::create_directory(GetAndroidRoot() + "/system_ext");
+  std::filesystem::create_directory(GetAndroidRoot() + "/system_ext/framework");
+  std::string system_ext_framework_multi_location_path =
+       GetAndroidRoot() + "/system_ext/framework/multifoo.jar";
+  ASSERT_TRUE(LocationIsOnSystemExtFramework(system_ext_framework_multi_location_path.c_str()));
+  TestLocation(system_ext_framework_multi_location_path, hiddenapi::Domain::kPlatform);
 }
 
 }  // namespace art
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 516c435..5e4a5f3 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -50,7 +50,7 @@
 #include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_throws.h"
 #include "debugger.h"
 #include "dex/dex_file-inl.h"
@@ -682,7 +682,7 @@
   }
 
   void WriteStackTraces() REQUIRES_SHARED(Locks::mutator_lock_) {
-    // Write a dummy stack trace record so the analysis tools don't freak out.
+    // Write a fake stack trace record so the analysis tools don't freak out.
     output_->StartNewRecord(HPROF_TAG_STACK_TRACE, kHprofTime);
     __ AddStackTraceSerialNumber(kHprofNullStackTrace);
     __ AddU4(kHprofNullThread);
diff --git a/runtime/image.cc b/runtime/image.cc
index 782c0c6..1e5ce6d 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -29,7 +29,8 @@
 namespace art {
 
 const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '8', '5', '\0' };  // Single-image.
+// Last change: kAccNterpInvokeFastPathFlag in method modifiers.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '9', '9', '\0' };
 
 ImageHeader::ImageHeader(uint32_t image_reservation_size,
                          uint32_t component_count,
@@ -199,4 +200,21 @@
   return true;
 }
 
+const char* ImageHeader::GetImageSectionName(ImageSections index) {
+  switch (index) {
+    case kSectionObjects: return "Objects";
+    case kSectionArtFields: return "ArtFields";
+    case kSectionArtMethods: return "ArtMethods";
+    case kSectionRuntimeMethods: return "RuntimeMethods";
+    case kSectionImTables: return "ImTables";
+    case kSectionIMTConflictTables: return "IMTConflictTables";
+    case kSectionInternedStrings: return "InternedStrings";
+    case kSectionClassTable: return "ClassTable";
+    case kSectionStringReferenceOffsets: return "StringReferenceOffsets";
+    case kSectionMetadata: return "Metadata";
+    case kSectionImageBitmap: return "ImageBitmap";
+    case kSectionCount: return nullptr;
+  }
+}
+
 }  // namespace art
diff --git a/runtime/image.h b/runtime/image.h
index 637bf1c..c5773ec 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -258,7 +258,6 @@
     kSectionRuntimeMethods,
     kSectionImTables,
     kSectionIMTConflictTables,
-    kSectionDexCacheArrays,
     kSectionInternedStrings,
     kSectionClassTable,
     kSectionStringReferenceOffsets,
@@ -275,6 +274,8 @@
 
   ArtMethod* GetImageMethod(ImageMethod index) const;
 
+  static const char* GetImageSectionName(ImageSections index);
+
   ImageSection& GetImageSection(ImageSections index) {
     DCHECK_LT(static_cast<size_t>(index), kSectionCount);
     return sections_[index];
@@ -309,10 +310,6 @@
     return GetImageSection(kSectionIMTConflictTables);
   }
 
-  const ImageSection& GetDexCacheArraysSection() const {
-    return GetImageSection(kSectionDexCacheArrays);
-  }
-
   const ImageSection& GetInternedStringsSection() const {
     return GetImageSection(kSectionInternedStrings);
   }
@@ -442,10 +439,12 @@
   // their oat files are mmapped independently.
   uint32_t image_reservation_size_ = 0u;
 
-  // The number of components.
+  // The number of components (jar files contributing to the image).
   // For boot image or boot image extension, the primary image stores the total number
-  // of images, secondary images have this set to 0.
-  // App images have 1 component.
+  // of components, secondary images have this set to 0. App images have 1 component.
+  // The component count usually matches the total number of images (one image per component), but
+  // if multiple components are compiled with --single-image there will only be 1 image associated
+  // with those components.
   uint32_t component_count_ = 0u;
 
   // Required base address for mapping the image.
@@ -457,7 +456,7 @@
   // Image file checksum (calculated with the checksum field set to 0).
   uint32_t image_checksum_ = 0u;
 
-  // Checksum of the oat file we link to for load time sanity check.
+  // Checksum of the oat file we link to for load time consistency check.
   uint32_t oat_checksum_ = 0u;
 
   // Start address for oat file. Will be before oat_data_begin_ for .so files.
@@ -509,81 +508,17 @@
  * This type holds the information necessary to fix up AppImage string
  * references.
  *
- * The first element of the pair is an offset into the image space.  If the
- * offset is tagged (testable using HasDexCacheNativeRefTag) it indicates the location
- * of a DexCache object that has one or more native references to managed
- * strings that need to be fixed up.  In this case the second element has no
- * meaningful value.
- *
- * If the first element isn't tagged then it indicates the location of a
- * managed object with a field that needs fixing up.  In this case the second
- * element of the pair is an object-relative offset to the field in question.
+ * The first element indicates the location of a managed object with a field that needs fixing up.
+ * The second element of the pair is an object-relative offset to the field in question.
  */
 typedef std::pair<uint32_t, uint32_t> AppImageReferenceOffsetInfo;
 
-/*
- * Tags the last bit.  Used by AppImage logic to differentiate between pointers
- * to managed objects and pointers to native reference arrays.
- */
-template<typename T>
-T SetDexCacheStringNativeRefTag(T val) {
-  static_assert(std::is_integral<T>::value, "Expected integral type.");
+std::ostream& operator<<(std::ostream& os, ImageHeader::ImageMethod method);
+std::ostream& operator<<(std::ostream& os, ImageHeader::ImageRoot root);
+std::ostream& operator<<(std::ostream& os, ImageHeader::ImageSections section);
+std::ostream& operator<<(std::ostream& os, ImageHeader::StorageMode mode);
 
-  return val | 1u;
-}
-
-/*
- * Tags the second last bit.  Used by AppImage logic to differentiate between pointers
- * to managed objects and pointers to native reference arrays.
- */
-template<typename T>
-T SetDexCachePreResolvedStringNativeRefTag(T val) {
-  static_assert(std::is_integral<T>::value, "Expected integral type.");
-
-  return val | 2u;
-}
-
-/*
- * Retrieves the value of the last bit.  Used by AppImage logic to
- * differentiate between pointers to managed objects and pointers to native
- * reference arrays.
- */
-template<typename T>
-bool HasDexCacheStringNativeRefTag(T val) {
-  static_assert(std::is_integral<T>::value, "Expected integral type.");
-
-  return (val & 1u) != 0u;
-}
-
-/*
- * Retrieves the value of the second last bit.  Used by AppImage logic to
- * differentiate between pointers to managed objects and pointers to native
- * reference arrays.
- */
-template<typename T>
-bool HasDexCachePreResolvedStringNativeRefTag(T val) {
-  static_assert(std::is_integral<T>::value, "Expected integral type.");
-
-  return (val & 2u) != 0u;
-}
-
-/*
- * Sets the last bit of the value to 0.  Used by AppImage logic to
- * differentiate between pointers to managed objects and pointers to native
- * reference arrays.
- */
-template<typename T>
-T ClearDexCacheNativeRefTags(T val) {
-  static_assert(std::is_integral<T>::value, "Expected integral type.");
-
-  return val & ~3u;
-}
-
-std::ostream& operator<<(std::ostream& os, const ImageHeader::ImageMethod& method);
-std::ostream& operator<<(std::ostream& os, const ImageHeader::ImageRoot& root);
-std::ostream& operator<<(std::ostream& os, const ImageHeader::ImageSections& section);
 std::ostream& operator<<(std::ostream& os, const ImageSection& section);
-std::ostream& operator<<(std::ostream& os, const ImageHeader::StorageMode& mode);
 
 }  // namespace art
 
diff --git a/runtime/imtable-inl.h b/runtime/imtable-inl.h
index 21e3eb1..a0e56dd 100644
--- a/runtime/imtable-inl.h
+++ b/runtime/imtable-inl.h
@@ -83,6 +83,13 @@
 }
 
 inline uint32_t ImTable::GetImtIndex(ArtMethod* method) {
+  DCHECK(!method->IsCopied());
+  if (!method->IsAbstract()) {
+    // For default methods, where we cannot store the imt_index, we use the
+    // method_index instead. We mask it with the closest power of two to
+    // simplify the interpreter.
+    return method->GetMethodIndex() & (ImTable::kSizeTruncToPowerOfTwo - 1);
+  }
   uint32_t class_hash, name_hash, signature_hash;
   GetImtHashComponents(method, &class_hash, &name_hash, &signature_hash);
 
diff --git a/runtime/imtable.h b/runtime/imtable.h
index 48a8643..df10cda 100644
--- a/runtime/imtable.h
+++ b/runtime/imtable.h
@@ -17,10 +17,7 @@
 #ifndef ART_RUNTIME_IMTABLE_H_
 #define ART_RUNTIME_IMTABLE_H_
 
-#ifndef IMT_SIZE
-#error IMT_SIZE not defined
-#endif
-
+#include "base/bit_utils.h"
 #include "base/casts.h"
 #include "base/enums.h"
 #include "base/locks.h"
@@ -36,7 +33,12 @@
   // Interface method table size. Increasing this value reduces the chance of two interface methods
   // colliding in the interface method table but increases the size of classes that implement
   // (non-marker) interfaces.
-  static constexpr size_t kSize = IMT_SIZE;
+  // When this value changes, old images become incompatible, so image file version must change too.
+  static constexpr size_t kSize = 43;
+  // Default methods cannot store the imt_index, so instead we make its IMT index depend on the
+  // method_index and mask it with the closest power of 2 of kSize - 1. This
+  // is to simplify fetching it in the interpreter.
+  static constexpr size_t kSizeTruncToPowerOfTwo = TruncToPowerOfTwo(kSize);
 
   uint8_t* AddressOfElement(size_t index, PointerSize pointer_size) {
     return reinterpret_cast<uint8_t*>(this) + OffsetOfElement(index, pointer_size);
diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h
index 2128f8c..fb2dc1f 100644
--- a/runtime/indirect_reference_table-inl.h
+++ b/runtime/indirect_reference_table-inl.h
@@ -33,36 +33,28 @@
 
 // Verifies that the indirect table lookup is valid.
 // Returns "false" if something looks bad.
-inline bool IndirectReferenceTable::GetChecked(IndirectRef iref) const {
-  if (UNLIKELY(iref == nullptr)) {
-    LOG(WARNING) << "Attempt to look up nullptr " << kind_;
-    return false;
-  }
-  if (UNLIKELY(GetIndirectRefKind(iref) == kHandleScopeOrInvalid)) {
-    AbortIfNoCheckJNI(android::base::StringPrintf("JNI ERROR (app bug): invalid %s %p",
-                                                  GetIndirectRefKindString(kind_),
-                                                  iref));
-    return false;
-  }
+inline bool IndirectReferenceTable::IsValidReference(IndirectRef iref,
+                                                     /*out*/std::string* error_msg) const {
+  DCHECK(iref != nullptr);
+  DCHECK_EQ(GetIndirectRefKind(iref), kind_);
   const uint32_t top_index = segment_state_.top_index;
   uint32_t idx = ExtractIndex(iref);
   if (UNLIKELY(idx >= top_index)) {
-    std::string msg = android::base::StringPrintf(
-        "JNI ERROR (app bug): accessed stale %s %p  (index %d in a table of size %d)",
-        GetIndirectRefKindString(kind_),
-        iref,
-        idx,
-        top_index);
-    AbortIfNoCheckJNI(msg);
+    *error_msg = android::base::StringPrintf("deleted reference at index %u in a table of size %u",
+                                             idx,
+                                             top_index);
     return false;
   }
   if (UNLIKELY(table_[idx].GetReference()->IsNull())) {
-    AbortIfNoCheckJNI(android::base::StringPrintf("JNI ERROR (app bug): accessed deleted %s %p",
-                                                  GetIndirectRefKindString(kind_),
-                                                  iref));
+    *error_msg = android::base::StringPrintf("deleted reference at index %u", idx);
     return false;
   }
-  if (UNLIKELY(!CheckEntry("use", iref, idx))) {
+  uint32_t iref_serial = DecodeSerial(reinterpret_cast<uintptr_t>(iref));
+  uint32_t entry_serial = table_[idx].GetSerial();
+  if (UNLIKELY(iref_serial != entry_serial)) {
+    *error_msg = android::base::StringPrintf("stale reference with serial number %u v. current %u",
+                                             iref_serial,
+                                             entry_serial);
     return false;
   }
   return true;
@@ -88,21 +80,22 @@
 
 template<ReadBarrierOption kReadBarrierOption>
 inline ObjPtr<mirror::Object> IndirectReferenceTable::Get(IndirectRef iref) const {
-  if (!GetChecked(iref)) {
-    return nullptr;
-  }
+  DCHECK_EQ(GetIndirectRefKind(iref), kind_);
   uint32_t idx = ExtractIndex(iref);
+  DCHECK_LT(idx, segment_state_.top_index);
+  DCHECK_EQ(DecodeSerial(reinterpret_cast<uintptr_t>(iref)), table_[idx].GetSerial());
+  DCHECK(!table_[idx].GetReference()->IsNull());
   ObjPtr<mirror::Object> obj = table_[idx].GetReference()->Read<kReadBarrierOption>();
   VerifyObject(obj);
   return obj;
 }
 
 inline void IndirectReferenceTable::Update(IndirectRef iref, ObjPtr<mirror::Object> obj) {
-  if (!GetChecked(iref)) {
-    LOG(WARNING) << "IndirectReferenceTable Update failed to find reference " << iref;
-    return;
-  }
+  DCHECK_EQ(GetIndirectRefKind(iref), kind_);
   uint32_t idx = ExtractIndex(iref);
+  DCHECK_LT(idx, segment_state_.top_index);
+  DCHECK_EQ(DecodeSerial(reinterpret_cast<uintptr_t>(iref)), table_[idx].GetSerial());
+  DCHECK(!table_[idx].GetReference()->IsNull());
   table_[idx].SetReference(obj);
 }
 
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc
index 361dccb..f263b93 100644
--- a/runtime/indirect_reference_table.cc
+++ b/runtime/indirect_reference_table.cc
@@ -14,11 +14,14 @@
  * limitations under the License.
  */
 
+#include "base/bit_utils.h"
+#include "base/globals.h"
 #include "indirect_reference_table-inl.h"
 
 #include "base/mutator_locked_dumpable.h"
 #include "base/systrace.h"
 #include "base/utils.h"
+#include "indirect_reference_table.h"
 #include "jni/java_vm_ext.h"
 #include "jni/jni_internal.h"
 #include "mirror/object-inl.h"
@@ -40,8 +43,8 @@
 
 const char* GetIndirectRefKindString(const IndirectRefKind& kind) {
   switch (kind) {
-    case kHandleScopeOrInvalid:
-      return "HandleScopeOrInvalid";
+    case kJniTransitionOrInvalid:
+      return "JniTransitionOrInvalid";
     case kLocal:
       return "Local";
     case kGlobal:
@@ -73,12 +76,12 @@
       current_num_holes_(0),
       resizable_(resizable) {
   CHECK(error_msg != nullptr);
-  CHECK_NE(desired_kind, kHandleScopeOrInvalid);
+  CHECK_NE(desired_kind, kJniTransitionOrInvalid);
 
   // Overflow and maximum check.
   CHECK_LE(max_count, kMaxTableSizeInBytes / sizeof(IrtEntry));
 
-  const size_t table_bytes = max_count * sizeof(IrtEntry);
+  const size_t table_bytes = RoundUp(max_count * sizeof(IrtEntry), kPageSize);
   table_mem_map_ = MemMap::MapAnonymous("indirect ref table",
                                         table_bytes,
                                         PROT_READ | PROT_WRITE,
@@ -95,6 +98,8 @@
   }
   segment_state_ = kIRTFirstSegment;
   last_known_previous_state_ = kIRTFirstSegment;
+  // Take into account the actual length.
+  max_entries_ = table_bytes / sizeof(IrtEntry);
 }
 
 IndirectReferenceTable::~IndirectReferenceTable() {
@@ -220,7 +225,7 @@
   }
   // Note: the above check also ensures that there is no overflow below.
 
-  const size_t table_bytes = new_size * sizeof(IrtEntry);
+  const size_t table_bytes = RoundUp(new_size * sizeof(IrtEntry), kPageSize);
   MemMap new_map = MemMap::MapAnonymous("indirect ref table",
                                         table_bytes,
                                         PROT_READ | PROT_WRITE,
@@ -233,7 +238,9 @@
   memcpy(new_map.Begin(), table_mem_map_.Begin(), table_mem_map_.Size());
   table_mem_map_ = std::move(new_map);
   table_ = reinterpret_cast<IrtEntry*>(table_mem_map_.Begin());
-  max_entries_ = new_size;
+  const size_t real_new_size = table_bytes / sizeof(IrtEntry);
+  DCHECK_GE(real_new_size, new_size);
+  max_entries_ = real_new_size;
 
   return true;
 }
@@ -354,13 +361,16 @@
 
   DCHECK(table_ != nullptr);
 
-  if (GetIndirectRefKind(iref) == kHandleScopeOrInvalid) {
+  // TODO: We should eagerly check the ref kind against the `kind_` instead of
+  // relying on this weak check and postponing the rest until `CheckEntry()` below.
+  // Passing the wrong kind shall currently result in misleading warnings.
+  if (GetIndirectRefKind(iref) == kJniTransitionOrInvalid) {
     auto* self = Thread::Current();
-    if (self->HandleScopeContains(reinterpret_cast<jobject>(iref))) {
+    ScopedObjectAccess soa(self);
+    if (self->IsJniTransitionReference(reinterpret_cast<jobject>(iref))) {
       auto* env = self->GetJniEnv();
       DCHECK(env != nullptr);
       if (env->IsCheckJniEnabled()) {
-        ScopedObjectAccess soa(self);
         LOG(WARNING) << "Attempt to remove non-JNI local reference, dumping thread";
         if (kDumpStackOnNonLocalReference) {
           self->Dump(LOG_STREAM(WARNING));
@@ -369,6 +379,7 @@
       return true;
     }
   }
+
   const uint32_t idx = ExtractIndex(iref);
   if (idx < bottom_index) {
     // Wrong segment.
@@ -445,8 +456,11 @@
 void IndirectReferenceTable::Trim() {
   ScopedTrace trace(__PRETTY_FUNCTION__);
   const size_t top_index = Capacity();
-  auto* release_start = AlignUp(reinterpret_cast<uint8_t*>(&table_[top_index]), kPageSize);
-  uint8_t* release_end = table_mem_map_.End();
+  uint8_t* release_start = AlignUp(reinterpret_cast<uint8_t*>(&table_[top_index]), kPageSize);
+  uint8_t* release_end = static_cast<uint8_t*>(table_mem_map_.BaseEnd());
+  DCHECK_GE(reinterpret_cast<uintptr_t>(release_end), reinterpret_cast<uintptr_t>(release_start));
+  DCHECK_ALIGNED(release_end, kPageSize);
+  DCHECK_ALIGNED(release_end - release_start, kPageSize);
   madvise(release_start, release_end - release_start, MADV_DONTNEED);
 }
 
diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h
index eb07035..884e8d1 100644
--- a/runtime/indirect_reference_table.h
+++ b/runtime/indirect_reference_table.h
@@ -91,13 +91,13 @@
 //
 // For convenience these match up with enum jobjectRefType from jni.h.
 enum IndirectRefKind {
-  kHandleScopeOrInvalid = 0,           // <<stack indirect reference table or invalid reference>>
-  kLocal                = 1,           // <<local reference>>
-  kGlobal               = 2,           // <<global reference>>
-  kWeakGlobal           = 3,           // <<weak global reference>>
-  kLastKind             = kWeakGlobal
+  kJniTransitionOrInvalid = 0,  // <<JNI transition frame reference or invalid reference>>
+  kLocal                  = 1,  // <<local reference>>
+  kGlobal                 = 2,  // <<global reference>>
+  kWeakGlobal             = 3,  // <<weak global reference>>
+  kLastKind               = kWeakGlobal
 };
-std::ostream& operator<<(std::ostream& os, const IndirectRefKind& rhs);
+std::ostream& operator<<(std::ostream& os, IndirectRefKind rhs);
 const char* GetIndirectRefKindString(const IndirectRefKind& kind);
 
 // Table definition.
@@ -285,6 +285,10 @@
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::alloc_tracker_lock_);
 
+  IndirectRefKind GetKind() const {
+    return kind_;
+  }
+
   // Return the #of entries in the entire table.  This includes holes, and
   // so may be larger than the actual number of "live" entries.
   size_t Capacity() const {
@@ -331,6 +335,10 @@
     return DecodeIndirectRefKind(reinterpret_cast<uintptr_t>(iref));
   }
 
+  /* Reference validation for CheckJNI. */
+  bool IsValidReference(IndirectRef, /*out*/std::string* error_msg) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
  private:
   static constexpr size_t kSerialBits = MinimumBitsToStore(kIRTPrevCount);
   static constexpr uint32_t kShiftedSerialMask = (1u << kSerialBits) - 1;
@@ -381,7 +389,8 @@
     return reinterpret_cast<IndirectRef>(EncodeIndirectRef(table_index, serial));
   }
 
-  // Resize the backing table. Currently must be larger than the current size.
+  // Resize the backing table to be at least new_size elements long. Currently
+  // must be larger than the current size. After return max_entries_ >= new_size.
   bool Resize(size_t new_size, std::string* error_msg);
 
   void RecoverHoles(IRTSegmentState from);
@@ -390,7 +399,6 @@
   static void AbortIfNoCheckJNI(const std::string& msg);
 
   /* extra debugging checks */
-  bool GetChecked(IndirectRef) const REQUIRES_SHARED(Locks::mutator_lock_);
   bool CheckEntry(const char*, IndirectRef, uint32_t) const;
 
   /// semi-public - read/write by jni down calls.
diff --git a/runtime/indirect_reference_table_test.cc b/runtime/indirect_reference_table_test.cc
index c5ae4c6..5da7a30 100644
--- a/runtime/indirect_reference_table_test.cc
+++ b/runtime/indirect_reference_table_test.cc
@@ -106,8 +106,9 @@
   // Table should be empty now.
   EXPECT_EQ(0U, irt.Capacity());
 
-  // Get invalid entry (off the end of the list).
-  EXPECT_TRUE(irt.Get(iref0) == nullptr);
+  // Check that the entry off the end of the list is not valid.
+  // (CheckJNI shall abort for such entries.)
+  EXPECT_FALSE(irt.IsValidReference(iref0, &error_msg));
 
   // Add three, remove in the opposite order.
   iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
@@ -145,8 +146,8 @@
   ASSERT_FALSE(irt.Remove(cookie, iref1));
   CheckDump(&irt, 2, 2);
 
-  // Get invalid entry (from hole).
-  EXPECT_TRUE(irt.Get(iref1) == nullptr);
+  // Check that the reference to the hole is not valid.
+  EXPECT_FALSE(irt.IsValidReference(iref1, &error_msg));
 
   ASSERT_TRUE(irt.Remove(cookie, iref2));
   CheckDump(&irt, 1, 1);
@@ -227,15 +228,12 @@
   ASSERT_EQ(0U, irt.Capacity()) << "temporal del not empty";
   CheckDump(&irt, 0, 0);
 
-  // null isn't a valid iref.
-  ASSERT_TRUE(irt.Get(nullptr) == nullptr);
-
-  // Stale lookup.
+  // Stale reference is not valid.
   iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
   EXPECT_TRUE(iref0 != nullptr);
   CheckDump(&irt, 1, 1);
   ASSERT_TRUE(irt.Remove(cookie, iref0));
-  EXPECT_TRUE(irt.Get(iref0) == nullptr) << "stale lookup succeeded";
+  EXPECT_FALSE(irt.IsValidReference(iref0, &error_msg)) << "stale lookup succeeded";
   CheckDump(&irt, 0, 0);
 
   // Test table resizing.
@@ -322,7 +320,7 @@
 
     // Must not have filled the previous hole.
     EXPECT_EQ(irt.Capacity(), 4u);
-    EXPECT_TRUE(irt.Get(iref1) == nullptr);
+    EXPECT_FALSE(irt.IsValidReference(iref1, &error_msg));
     CheckDump(&irt, 3, 3);
 
     UNUSED(iref0, iref1, iref2, iref3);
@@ -357,7 +355,7 @@
     IndirectRef iref4 = irt.Add(cookie1, obj4.Get(), &error_msg);
 
     EXPECT_EQ(irt.Capacity(), 2u);
-    EXPECT_TRUE(irt.Get(iref2) == nullptr);
+    EXPECT_FALSE(irt.IsValidReference(iref2, &error_msg));
     CheckDump(&irt, 2, 2);
 
     UNUSED(iref0, iref1, iref2, iref3, iref4);
@@ -397,7 +395,7 @@
     IndirectRef iref4 = irt.Add(cookie1, obj4.Get(), &error_msg);
 
     EXPECT_EQ(irt.Capacity(), 3u);
-    EXPECT_TRUE(irt.Get(iref1) == nullptr);
+    EXPECT_FALSE(irt.IsValidReference(iref1, &error_msg));
     CheckDump(&irt, 3, 3);
 
     UNUSED(iref0, iref1, iref2, iref3, iref4);
@@ -439,7 +437,7 @@
     IndirectRef iref5 = irt.Add(cookie1, obj4.Get(), &error_msg);
 
     EXPECT_EQ(irt.Capacity(), 2u);
-    EXPECT_TRUE(irt.Get(iref3) == nullptr);
+    EXPECT_FALSE(irt.IsValidReference(iref3, &error_msg));
     CheckDump(&irt, 2, 2);
 
     UNUSED(iref0, iref1, iref2, iref3, iref4, iref5);
@@ -479,7 +477,7 @@
     IndirectRef iref4 = irt.Add(cookie1, obj3.Get(), &error_msg);
 
     EXPECT_EQ(irt.Capacity(), 2u);
-    EXPECT_TRUE(irt.Get(iref3) == nullptr);
+    EXPECT_FALSE(irt.IsValidReference(iref3, &error_msg));
     CheckDump(&irt, 2, 2);
 
     UNUSED(iref0, iref1, iref2, iref3, iref4);
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 60e7c9c..5170a37 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -843,7 +843,7 @@
 }
 
 static void ResetQuickAllocEntryPointsForThread(Thread* thread, void* arg ATTRIBUTE_UNUSED) {
-  thread->ResetQuickAllocEntryPointsForThread(kUseReadBarrier && thread->GetIsGcMarking());
+  thread->ResetQuickAllocEntryPointsForThread();
 }
 
 void Instrumentation::SetEntrypointsInstrumented(bool instrumented) {
@@ -928,16 +928,6 @@
                  // Proxy.<init> correctly in all cases.
                  method != jni::DecodeArtMethod(WellKnownClasses::java_lang_reflect_Proxy_init)) {
         new_quick_code = GetQuickInstrumentationEntryPoint();
-        if (!method->IsNative() && Runtime::Current()->GetJit() != nullptr) {
-          // Native methods use trampoline entrypoints during interpreter tracing.
-          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.
-          if (profiling_info != nullptr) {
-            profiling_info->SetSavedEntryPoint(quick_code);
-          }
-        }
       } else {
         new_quick_code = quick_code;
       }
@@ -1170,16 +1160,6 @@
     // If we don't need a debug version we should see what the oat file/class linker has to say.
     result = class_linker->GetQuickOatCodeFor(method);
   }
-  // If both those fail try the jit.
-  if (result == GetQuickToInterpreterBridge()) {
-    jit::Jit* jit = Runtime::Current()->GetJit();
-    if (jit != nullptr) {
-      const void* res = jit->GetCodeCache()->FindCompiledCodeForInstrumentation(method);
-      if (res != nullptr) {
-        result = res;
-      }
-    }
-  }
   return result;
 }
 
@@ -1454,24 +1434,7 @@
         } else {
           const Instruction& instr = m->DexInstructions().InstructionAt(stack_visitor->GetDexPc());
           if (instr.IsInvoke()) {
-            auto get_method_index_fn = [](ArtMethod* caller,
-                                          const Instruction& inst,
-                                          uint32_t dex_pc)
-                REQUIRES_SHARED(Locks::mutator_lock_) {
-              switch (inst.Opcode()) {
-                case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
-                case Instruction::INVOKE_VIRTUAL_QUICK: {
-                  uint16_t method_idx = caller->GetIndexFromQuickening(dex_pc);
-                  CHECK_NE(method_idx, DexFile::kDexNoIndex16);
-                  return method_idx;
-                }
-                default: {
-                  return static_cast<uint16_t>(inst.VRegB());
-                }
-              }
-            };
-
-            uint16_t method_index = get_method_index_fn(m, instr, stack_visitor->GetDexPc());
+            uint16_t method_index = static_cast<uint16_t>(instr.VRegB());
             const DexFile* dex_file = m->GetDexFile();
             if (interpreter::IsStringInit(dex_file, method_index)) {
               // Invoking string init constructor is turned into invoking
@@ -1511,7 +1474,7 @@
   InstrumentationStackFrame instrumentation_frame = it->second;
   stack->erase(it);
 
-  // Set return PC and check the sanity of the stack.
+  // Set return PC and check the consistency of the stack.
   // We don't cache the return pc value in a local as it may change after
   // sending a method exit event.
   *return_pc_addr = instrumentation_frame.return_pc_;
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index e30fc9a..6c08333 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -763,8 +763,8 @@
 
   DISALLOW_COPY_AND_ASSIGN(Instrumentation);
 };
-std::ostream& operator<<(std::ostream& os, const Instrumentation::InstrumentationEvent& rhs);
-std::ostream& operator<<(std::ostream& os, const Instrumentation::InstrumentationLevel& rhs);
+std::ostream& operator<<(std::ostream& os, Instrumentation::InstrumentationEvent rhs);
+std::ostream& operator<<(std::ostream& os, Instrumentation::InstrumentationLevel rhs);
 
 // An element in the instrumentation side stack maintained in art::Thread.
 struct InstrumentationStackFrame {
diff --git a/runtime/intern_table-inl.h b/runtime/intern_table-inl.h
index 687f5ee..44bdb1f 100644
--- a/runtime/intern_table-inl.h
+++ b/runtime/intern_table-inl.h
@@ -19,12 +19,61 @@
 
 #include "intern_table.h"
 
+#include "dex/utf.h"
 #include "gc/space/image_space.h"
+#include "gc_root-inl.h"
 #include "image.h"
-#include "mirror/string-inl.h"  // Required for ToModifiedUtf8 below.
+#include "mirror/string-inl.h"
+#include "thread-current-inl.h"
 
 namespace art {
 
+inline std::size_t InternTable::StringHash::operator()(const GcRoot<mirror::String>& root) const {
+  if (kIsDebugBuild) {
+    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
+  }
+  // An additional cast to prevent undesired sign extension.
+  return static_cast<size_t>(
+      static_cast<uint32_t>(root.Read<kWithoutReadBarrier>()->GetHashCode()));
+}
+
+inline bool InternTable::StringEquals::operator()(const GcRoot<mirror::String>& a,
+                                                  const GcRoot<mirror::String>& b) const {
+  if (kIsDebugBuild) {
+    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
+  }
+  return a.Read<kWithoutReadBarrier>()->Equals(b.Read<kWithoutReadBarrier>());
+}
+
+inline bool InternTable::StringEquals::operator()(const GcRoot<mirror::String>& a,
+                                                  const Utf8String& b) const {
+  if (kIsDebugBuild) {
+    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
+  }
+  ObjPtr<mirror::String> a_string = a.Read<kWithoutReadBarrier>();
+  uint32_t a_length = static_cast<uint32_t>(a_string->GetLength());
+  if (a_length != b.GetUtf16Length()) {
+    return false;
+  }
+  if (a_string->IsCompressed()) {
+    size_t b_byte_count = strlen(b.GetUtf8Data());
+    size_t b_utf8_length = CountModifiedUtf8Chars(b.GetUtf8Data(), b_byte_count);
+    // Modified UTF-8 single byte character range is 0x01 .. 0x7f
+    // The string compression occurs on regular ASCII with same exact range,
+    // not on extended ASCII which up to 0xff
+    const bool is_b_regular_ascii = (b_byte_count == b_utf8_length);
+    if (is_b_regular_ascii) {
+      return memcmp(b.GetUtf8Data(),
+                    a_string->GetValueCompressed(), a_length * sizeof(uint8_t)) == 0;
+    } else {
+      return false;
+    }
+  } else {
+    const uint16_t* a_value = a_string->GetValue();
+    return CompareModifiedUtf8ToUtf16AsCodePointValues(b.GetUtf8Data(), a_value, a_length) == 0;
+  }
+}
+
 template <typename Visitor>
 inline void InternTable::AddImageStringsToTable(gc::space::ImageSpace* image_space,
                                                 const Visitor& visitor) {
diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc
index 96f70d1..6af0455 100644
--- a/runtime/intern_table.cc
+++ b/runtime/intern_table.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "intern_table.h"
+#include "intern_table-inl.h"
 
 #include <memory>
 
@@ -100,8 +100,8 @@
 }
 
 ObjPtr<mirror::String> InternTable::LookupStrong(Thread* self,
-                                          uint32_t utf16_length,
-                                          const char* utf8_data) {
+                                                 uint32_t utf16_length,
+                                                 const char* utf8_data) {
   DCHECK_EQ(utf16_length, CountModifiedUtf8Chars(utf8_data));
   Utf8String string(utf16_length,
                     utf8_data,
@@ -307,76 +307,6 @@
   weak_interns_.SweepWeaks(visitor);
 }
 
-size_t InternTable::WriteToMemory(uint8_t* ptr) {
-  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
-  return strong_interns_.WriteToMemory(ptr);
-}
-
-std::size_t InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& root) const {
-  if (kIsDebugBuild) {
-    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
-  }
-  // An additional cast to prevent undesired sign extension.
-  return static_cast<size_t>(
-      static_cast<uint32_t>(root.Read<kWithoutReadBarrier>()->GetHashCode()));
-}
-
-bool InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& a,
-                                               const GcRoot<mirror::String>& b) const {
-  if (kIsDebugBuild) {
-    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
-  }
-  return a.Read<kWithoutReadBarrier>()->Equals(b.Read<kWithoutReadBarrier>());
-}
-
-bool InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& a,
-                                               const Utf8String& b) const {
-  if (kIsDebugBuild) {
-    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
-  }
-  ObjPtr<mirror::String> a_string = a.Read<kWithoutReadBarrier>();
-  uint32_t a_length = static_cast<uint32_t>(a_string->GetLength());
-  if (a_length != b.GetUtf16Length()) {
-    return false;
-  }
-  if (a_string->IsCompressed()) {
-    size_t b_byte_count = strlen(b.GetUtf8Data());
-    size_t b_utf8_length = CountModifiedUtf8Chars(b.GetUtf8Data(), b_byte_count);
-    // Modified UTF-8 single byte character range is 0x01 .. 0x7f
-    // The string compression occurs on regular ASCII with same exact range,
-    // not on extended ASCII which up to 0xff
-    const bool is_b_regular_ascii = (b_byte_count == b_utf8_length);
-    if (is_b_regular_ascii) {
-      return memcmp(b.GetUtf8Data(),
-                    a_string->GetValueCompressed(), a_length * sizeof(uint8_t)) == 0;
-    } else {
-      return false;
-    }
-  } else {
-    const uint16_t* a_value = a_string->GetValue();
-    return CompareModifiedUtf8ToUtf16AsCodePointValues(b.GetUtf8Data(), a_value, a_length) == 0;
-  }
-}
-
-size_t InternTable::Table::WriteToMemory(uint8_t* ptr) {
-  if (tables_.empty()) {
-    return 0;
-  }
-  UnorderedSet* table_to_write;
-  UnorderedSet combined;
-  if (tables_.size() > 1) {
-    table_to_write = &combined;
-    for (InternalTable& table : tables_) {
-      for (GcRoot<mirror::String>& string : table.set_) {
-        combined.insert(string);
-      }
-    }
-  } else {
-    table_to_write = &tables_.back().set_;
-  }
-  return table_to_write->WriteToMemory(ptr);
-}
-
 void InternTable::Table::Remove(ObjPtr<mirror::String> s) {
   for (InternalTable& table : tables_) {
     auto it = table.set_.find(GcRoot<mirror::String>(s));
diff --git a/runtime/intern_table.h b/runtime/intern_table.h
index 7065015..db6016e 100644
--- a/runtime/intern_table.h
+++ b/runtime/intern_table.h
@@ -72,18 +72,23 @@
     const char* utf8_data_;
   };
 
-  class StringHashEquals {
+  class StringHash {
    public:
     std::size_t operator()(const GcRoot<mirror::String>& root) const NO_THREAD_SAFETY_ANALYSIS;
-    bool operator()(const GcRoot<mirror::String>& a, const GcRoot<mirror::String>& b) const
-        NO_THREAD_SAFETY_ANALYSIS;
 
     // Utf8String can be used for lookup.
     std::size_t operator()(const Utf8String& key) const {
       // A cast to prevent undesired sign extension.
       return static_cast<uint32_t>(key.GetHash());
     }
+  };
 
+  class StringEquals {
+   public:
+    bool operator()(const GcRoot<mirror::String>& a, const GcRoot<mirror::String>& b) const
+        NO_THREAD_SAFETY_ANALYSIS;
+
+    // Utf8String can be used for lookup.
     bool operator()(const GcRoot<mirror::String>& a, const Utf8String& b) const
         NO_THREAD_SAFETY_ANALYSIS;
   };
@@ -100,8 +105,8 @@
 
   using UnorderedSet = HashSet<GcRoot<mirror::String>,
                                GcRootEmptyFn,
-                               StringHashEquals,
-                               StringHashEquals,
+                               StringHash,
+                               StringEquals,
                                TrackingAllocator<GcRoot<mirror::String>, kAllocatorTagInternTable>>;
 
   InternTable();
@@ -199,11 +204,6 @@
   void AddNewTable()
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::intern_table_lock_);
 
-  // Write the post zygote intern table to a pointer. Only writes the strong interns since it is
-  // expected that there is no weak interns since this is called from the image writer.
-  size_t WriteToMemory(uint8_t* ptr) REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::intern_table_lock_);
-
   // Change the weak root state. May broadcast to waiters.
   void ChangeWeakRootState(gc::WeakRootState new_state)
       REQUIRES(!Locks::intern_table_lock_);
@@ -236,6 +236,7 @@
       bool is_boot_image_ = false;
 
       friend class InternTable;
+      friend class linker::ImageWriter;
       friend class Table;
       ART_FRIEND_TEST(InternTableTest, CrossHash);
     };
@@ -263,10 +264,6 @@
     template <typename Visitor>
     size_t AddTableFromMemory(const uint8_t* ptr, const Visitor& visitor, bool is_boot_image)
         REQUIRES(!Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
-    // Write the intern tables to ptr, if there are multiple tables they are combined into a single
-    // one. Returns how many bytes were written.
-    size_t WriteToMemory(uint8_t* ptr)
-        REQUIRES(Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
 
    private:
     void SweepWeaks(UnorderedSet* set, IsMarkedVisitor* visitor)
diff --git a/runtime/intern_table_test.cc b/runtime/intern_table_test.cc
index b64ca7d..e4eed55 100644
--- a/runtime/intern_table_test.cc
+++ b/runtime/intern_table_test.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "intern_table.h"
+#include "intern_table-inl.h"
 
 #include "base/hash_set.h"
 #include "common_runtime_test.h"
diff --git a/runtime/interpreter/cfi_asm_support.h b/runtime/interpreter/cfi_asm_support.h
index 04812e1..3b9f991 100644
--- a/runtime/interpreter/cfi_asm_support.h
+++ b/runtime/interpreter/cfi_asm_support.h
@@ -45,15 +45,42 @@
     0x13 /* DW_OP_drop */,                                                     \
     0x92 /* DW_OP_bregx */, dexReg, (dexOffset & 0x7F) /* 1-byte SLEB128 */
 
-  #define CFI_DEFINE_CFA_DEREF(reg, offset, size) .cfi_escape                  \
-    0x0f /* DW_CFA_expression */, 6 /* size */,                                \
+  #define CFI_DEF_CFA_BREG_PLUS_UCONST_1_1(reg, offset, size) .cfi_escape      \
+    0x0f /* DW_CFA_def_cfa_expression */, 6 /* size */,                        \
     0x92 /* bregx */, reg, (offset & 0x7F),                                    \
     0x06 /* DW_OP_DEREF */,                                                    \
     0x23 /* DW_OP_plus_uconst */, size
+
+  #define CFI_DEF_CFA_BREG_PLUS_UCONST_1_2(reg, offset, size) .cfi_escape      \
+    0x0f /* DW_CFA_def_cfa_expression */, 7 /* size */,                        \
+    0x92 /* bregx */, reg, (offset & 0x7F),                                    \
+    0x06 /* DW_OP_DEREF */,                                                    \
+    0x23 /* DW_OP_plus_uconst */,                                              \
+    ((size) & 0x7f) | 0x80,   /* ULEB128 offset, byte 1 */                   \
+    ((size) >> 7) & 0x7f      /* ULEB128 offset, byte 2 */
+
+  #define CFI_EXPRESSION_BREG_1(n, b, offset) .cfi_escape       \
+      0x10,                       /* DW_CFA_expression */       \
+      n,                          /* rule for register n */     \
+      2,                          /* expression length */       \
+      0x70+b,                     /* DW_OP_BREG<b>() */         \
+      (offset) & 0x7f             /* SLEB128 offset */
+
+  #define CFI_EXPRESSION_BREG_2(n, b, offset) .cfi_escape       \
+      0x10,                       /* DW_CFA_expression */       \
+      n,                          /* rule for register n */     \
+      3,                          /* expression length */       \
+      0x70+b,                     /* DW_OP_BREG<b>() */         \
+      ((offset) & 0x7f) | 0x80,   /* SLEB128 offset, byte 1 */  \
+      ((offset) >> 7) & 0x7f      /* SLEB128 offset, byte 2 */
+
 #else
   // Mac OS doesn't like cfi_* directives.
   #define CFI_DEFINE_DEX_PC_WITH_OFFSET(tmpReg, dexReg, dexOffset)
-  #define CFI_DEFINE_CFA_DEREF(reg, offset)
+  #define CFI_DEF_CFA_BREG_PLUS_UCONST_1_1(reg, offset, size)
+  #define CFI_DEF_CFA_BREG_PLUS_UCONST_1_2(reg, offset, size)
+  #define CFI_EXPRESSION_BREG_1(n, b, offset)
+  #define CFI_EXPRESSION_BREG_2(n, b, offset)
 #endif
 
 #endif  // ART_RUNTIME_INTERPRETER_CFI_ASM_SUPPORT_H_
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index b5e5238..302551f 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -244,6 +244,30 @@
 static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind;
 #endif
 
+static JValue ExecuteSwitch(Thread* self,
+                            const CodeItemDataAccessor& accessor,
+                            ShadowFrame& shadow_frame,
+                            JValue result_register,
+                            bool interpret_one_instruction) REQUIRES_SHARED(Locks::mutator_lock_) {
+  if (Runtime::Current()->IsActiveTransaction()) {
+    if (shadow_frame.GetMethod()->SkipAccessChecks()) {
+      return ExecuteSwitchImpl<false, true>(
+          self, accessor, shadow_frame, result_register, interpret_one_instruction);
+    } else {
+      return ExecuteSwitchImpl<true, true>(
+          self, accessor, shadow_frame, result_register, interpret_one_instruction);
+    }
+  } else {
+    if (shadow_frame.GetMethod()->SkipAccessChecks()) {
+      return ExecuteSwitchImpl<false, false>(
+          self, accessor, shadow_frame, result_register, interpret_one_instruction);
+    } else {
+      return ExecuteSwitchImpl<true, false>(
+          self, accessor, shadow_frame, result_register, interpret_one_instruction);
+    }
+  }
+}
+
 static inline JValue Execute(
     Thread* self,
     const CodeItemDataAccessor& accessor,
@@ -279,14 +303,13 @@
         // any value.
         DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
         JValue ret = JValue();
-        bool res = PerformNonStandardReturn<MonitorState::kNoMonitorsLocked>(
+        PerformNonStandardReturn<MonitorState::kNoMonitorsLocked>(
             self,
             shadow_frame,
             ret,
             instrumentation,
             accessor.InsSize(),
             0);
-        DCHECK(res) << "Expected to perform non-standard return!";
         return ret;
       }
       if (UNLIKELY(self->IsExceptionPending())) {
@@ -297,14 +320,13 @@
         JValue ret = JValue();
         if (UNLIKELY(shadow_frame.GetForcePopFrame())) {
           DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
-          bool res = PerformNonStandardReturn<MonitorState::kNoMonitorsLocked>(
+          PerformNonStandardReturn<MonitorState::kNoMonitorsLocked>(
               self,
               shadow_frame,
               ret,
               instrumentation,
               accessor.InsSize(),
               0);
-          DCHECK(res) << "Expected to perform non-standard return!";
         }
         return ret;
       }
@@ -341,72 +363,39 @@
   // reduction of template parameters, we gate it behind access-checks mode.
   DCHECK(!method->SkipAccessChecks() || !method->MustCountLocks());
 
-  bool transaction_active = Runtime::Current()->IsActiveTransaction();
   VLOG(interpreter) << "Interpreting " << method->PrettyMethod();
-  if (LIKELY(method->SkipAccessChecks())) {
-    // Enter the "without access check" interpreter.
-    if (kInterpreterImplKind == kMterpImplKind) {
-      if (transaction_active) {
-        // No Mterp variant - just use the switch interpreter.
-        return ExecuteSwitchImpl<false, true>(self, accessor, shadow_frame, result_register,
-                                              false);
-      } else if (UNLIKELY(!Runtime::Current()->IsStarted())) {
-        return ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame, result_register,
-                                               false);
-      } else {
-        while (true) {
-          // Mterp does not support all instrumentation/debugging.
-          if (!self->UseMterp()) {
-            return ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame, result_register,
-                                                   false);
-          }
-          bool returned = ExecuteMterpImpl(self,
-                                           accessor.Insns(),
-                                           &shadow_frame,
-                                           &result_register);
-          if (returned) {
-            return result_register;
-          } else {
-            // Mterp didn't like that instruction.  Single-step it with the reference interpreter.
-            result_register = ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame,
-                                                              result_register, true);
-            if (shadow_frame.GetDexPC() == dex::kDexNoIndex) {
-              // Single-stepped a return or an exception not handled locally.  Return to caller.
-              return result_register;
-            }
-          }
-        }
-      }
-    } else {
-      DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind);
-      if (transaction_active) {
-        return ExecuteSwitchImpl<false, true>(self, accessor, shadow_frame, result_register,
-                                              false);
-      } else {
-        return ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame, result_register,
-                                               false);
-      }
-    }
-  } else {
-    // Enter the "with access check" interpreter.
 
-    if (kInterpreterImplKind == kMterpImplKind) {
-      // No access check variants for Mterp.  Just use the switch version.
-      if (transaction_active) {
-        return ExecuteSwitchImpl<true, true>(self, accessor, shadow_frame, result_register,
-                                             false);
-      } else {
-        return ExecuteSwitchImpl<true, false>(self, accessor, shadow_frame, result_register,
-                                              false);
-      }
+  // Note that mterp doesn't support non-compilable methods, nor methods on
+  // which we must count locks.
+  if (kInterpreterImplKind == kSwitchImplKind ||
+      UNLIKELY(!Runtime::Current()->IsStarted()) ||
+      !method->IsCompilable() ||
+      method->MustCountLocks() ||
+      Runtime::Current()->IsActiveTransaction()) {
+    return ExecuteSwitch(
+        self, accessor, shadow_frame, result_register, /*interpret_one_instruction=*/ false);
+  }
+
+  CHECK_EQ(kInterpreterImplKind, kMterpImplKind);
+  while (true) {
+    // Mterp does not support all instrumentation/debugging.
+    if (!self->UseMterp()) {
+      return ExecuteSwitch(
+          self, accessor, shadow_frame, result_register, /*interpret_one_instruction=*/ false);
+    }
+    bool returned = ExecuteMterpImpl(self,
+                                     accessor.Insns(),
+                                     &shadow_frame,
+                                     &result_register);
+    if (returned) {
+      return result_register;
     } else {
-      DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind);
-      if (transaction_active) {
-        return ExecuteSwitchImpl<true, true>(self, accessor, shadow_frame, result_register,
-                                             false);
-      } else {
-        return ExecuteSwitchImpl<true, false>(self, accessor, shadow_frame, result_register,
-                                              false);
+      // Mterp didn't like that instruction.  Single-step it with the reference interpreter.
+      result_register = ExecuteSwitch(
+          self, accessor, shadow_frame, result_register, /*interpret_one_instruction=*/ true);
+      if (shadow_frame.GetDexPC() == dex::kDexNoIndex) {
+        // Single-stepped a return or an exception not handled locally.  Return to caller.
+        return result_register;
       }
     }
   }
@@ -445,7 +434,7 @@
     method->ThrowInvocationTimeError();
     return;
   } else {
-    DCHECK(method->IsNative());
+    DCHECK(method->IsNative()) << method->PrettyMethod();
     num_regs = num_ins = ArtMethod::NumArgRegisters(method->GetShorty());
     if (!method->IsStatic()) {
       num_regs++;
diff --git a/runtime/interpreter/interpreter.h b/runtime/interpreter/interpreter.h
index e92d195..ff69c42 100644
--- a/runtime/interpreter/interpreter.h
+++ b/runtime/interpreter/interpreter.h
@@ -64,7 +64,7 @@
                                        JValue* result)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-// One-time sanity check.
+// One-time check of assembler constants.
 void CheckInterpreterAsmConstants();
 
 void InitInterpreterTls(Thread* self);
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 4d964f1..4e88eda 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -20,7 +20,7 @@
 
 #include "base/casts.h"
 #include "base/enums.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "debugger.h"
 #include "dex/dex_file_types.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
@@ -85,10 +85,6 @@
   if (method->IsStatic() && !method->GetDeclaringClass()->IsVisiblyInitialized()) {
     return false;
   }
-  ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize);
-  if ((profiling_info != nullptr) && (profiling_info->GetSavedEntryPoint() != nullptr)) {
-    return false;
-  }
   return true;
 }
 
@@ -342,7 +338,7 @@
 
   // Initialize |result| to 0 as this is the default return value for
   // polymorphic invocations of method handle types with void return
-  // and provides sane return result in error cases.
+  // and provides a sensible return result in error cases.
   result->SetJ(0);
 
   // The invoke_method_idx here is the name of the signature polymorphic method that
@@ -565,7 +561,7 @@
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   ArtMethod* invoke_method =
       class_linker->ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
-          self, invoke_method_idx, shadow_frame.GetMethod(), kVirtual);
+          self, invoke_method_idx, shadow_frame.GetMethod(), kPolymorphic);
 
   // Ensure intrinsic identifiers are initialized.
   DCHECK(invoke_method->IsIntrinsic());
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index c6d8569..959df00 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -39,7 +39,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_dex_operations.h"
 #include "common_throws.h"
 #include "dex/dex_file-inl.h"
@@ -158,7 +158,8 @@
 template <bool kMonitorCounting>
 static NO_INLINE void UnlockHeldMonitors(Thread* self, ShadowFrame* shadow_frame)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  DCHECK(shadow_frame->GetForcePopFrame());
+  DCHECK(shadow_frame->GetForcePopFrame() ||
+         Runtime::Current()->IsTransactionAborted());
   // Unlock all monitors.
   if (kMonitorCounting && shadow_frame->GetMethod()->MustCountLocks()) {
     // Get the monitors from the shadow-frame monitor-count data.
@@ -194,7 +195,7 @@
 };
 
 template<MonitorState kMonitorState>
-static inline ALWAYS_INLINE WARN_UNUSED bool PerformNonStandardReturn(
+static inline ALWAYS_INLINE void PerformNonStandardReturn(
       Thread* self,
       ShadowFrame& frame,
       JValue& result,
@@ -202,33 +203,28 @@
       uint16_t num_dex_inst,
       uint32_t dex_pc) REQUIRES_SHARED(Locks::mutator_lock_) {
   static constexpr bool kMonitorCounting = (kMonitorState == MonitorState::kCountingMonitors);
-  if (UNLIKELY(frame.GetForcePopFrame())) {
-    ObjPtr<mirror::Object> thiz(frame.GetThisObject(num_dex_inst));
-    StackHandleScope<1> hs(self);
-    Handle<mirror::Object> h_thiz(hs.NewHandle(thiz));
-    DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
-    if (UNLIKELY(self->IsExceptionPending())) {
-      LOG(WARNING) << "Suppressing exception for non-standard method exit: "
-                   << self->GetException()->Dump();
-      self->ClearException();
-    }
-    if (kMonitorState != MonitorState::kNoMonitorsLocked) {
-      UnlockHeldMonitors<kMonitorCounting>(self, &frame);
-    }
-    DoMonitorCheckOnExit<kMonitorCounting>(self, &frame);
-    result = JValue();
-    if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) {
-      SendMethodExitEvents(
-          self, instrumentation, frame, h_thiz.Get(), frame.GetMethod(), dex_pc, result);
-    }
-    return true;
+  ObjPtr<mirror::Object> thiz(frame.GetThisObject(num_dex_inst));
+  StackHandleScope<1u> hs(self);
+  Handle<mirror::Object> h_thiz(hs.NewHandle(thiz));
+  if (UNLIKELY(self->IsExceptionPending())) {
+    LOG(WARNING) << "Suppressing exception for non-standard method exit: "
+                 << self->GetException()->Dump();
+    self->ClearException();
   }
-  return false;
+  if (kMonitorState != MonitorState::kNoMonitorsLocked) {
+    UnlockHeldMonitors<kMonitorCounting>(self, &frame);
+  }
+  DoMonitorCheckOnExit<kMonitorCounting>(self, &frame);
+  result = JValue();
+  if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) {
+    SendMethodExitEvents(
+        self, instrumentation, frame, h_thiz.Get(), frame.GetMethod(), dex_pc, result);
+  }
 }
 
 // Handles all invoke-XXX/range instructions except for invoke-polymorphic[/range].
 // Returns true on success, otherwise throws an exception and returns false.
-template<InvokeType type, bool is_range, bool do_access_check, bool is_mterp, bool is_quick = false>
+template<InvokeType type, bool is_range, bool do_access_check, bool is_mterp>
 static ALWAYS_INLINE bool DoInvoke(Thread* self,
                                    ShadowFrame& shadow_frame,
                                    const Instruction* inst,
@@ -250,9 +246,7 @@
   InterpreterCache* tls_cache = self->GetInterpreterCache();
   size_t tls_value;
   ArtMethod* resolved_method;
-  if (is_quick) {
-    resolved_method = nullptr;  // We don't know/care what the original method was.
-  } else if (!IsNterpSupported() && LIKELY(tls_cache->Get(inst, &tls_value))) {
+  if (!IsNterpSupported() && LIKELY(tls_cache->Get(inst, &tls_value))) {
     resolved_method = reinterpret_cast<ArtMethod*>(tls_value);
   } else {
     ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
@@ -274,19 +268,8 @@
   ObjPtr<mirror::Object> receiver =
       (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC);
   ArtMethod* called_method;
-  if (is_quick) {
-    if (UNLIKELY(receiver == nullptr)) {
-      // We lost the reference to the method index so we cannot get a more precise exception.
-      ThrowNullPointerExceptionFromDexPC();
-      return false;
-    }
-    DCHECK(receiver->GetClass()->ShouldHaveEmbeddedVTable());
-    called_method = receiver->GetClass()->GetEmbeddedVTableEntry(
-        /*vtable_idx=*/ method_idx, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
-  } else {
-    called_method = FindMethodToCall<type, do_access_check>(
-        method_idx, resolved_method, &receiver, sf_method, self);
-  }
+  called_method = FindMethodToCall<type, do_access_check>(
+      method_idx, resolved_method, &receiver, sf_method, self);
   if (UNLIKELY(called_method == nullptr)) {
     CHECK(self->IsExceptionPending());
     result->SetJ(0);
@@ -299,10 +282,6 @@
   }
 
   jit::Jit* jit = Runtime::Current()->GetJit();
-  if (jit != nullptr && (type == kVirtual || type == kInterface)) {
-    jit->InvokeVirtualOrInterface(receiver, sf_method, shadow_frame.GetDexPC(), called_method);
-  }
-
   if (is_mterp && !is_range && called_method->IsIntrinsic()) {
     if (MterpHandleIntrinsic(&shadow_frame, called_method, inst, inst_data,
                              shadow_frame.GetResultRegister())) {
@@ -570,71 +549,6 @@
   return true;
 }
 
-// Handles iget-quick, iget-wide-quick and iget-object-quick instructions.
-// Returns true on success, otherwise throws an exception and returns false.
-template<Primitive::Type field_type>
-ALWAYS_INLINE bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* inst,
-                               uint16_t inst_data) REQUIRES_SHARED(Locks::mutator_lock_) {
-  ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
-  if (UNLIKELY(obj == nullptr)) {
-    // We lost the reference to the field index so we cannot get a more
-    // precised exception message.
-    ThrowNullPointerExceptionFromDexPC();
-    return false;
-  }
-  MemberOffset field_offset(inst->VRegC_22c());
-  // Report this field access to instrumentation if needed. Since we only have the offset of
-  // the field from the base of the object, we need to look for it first.
-  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
-  if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
-    ArtField* f = ArtField::FindInstanceFieldWithOffset(obj->GetClass(),
-                                                        field_offset.Uint32Value());
-    DCHECK(f != nullptr);
-    DCHECK(!f->IsStatic());
-    Thread* self = Thread::Current();
-    StackHandleScope<1> hs(self);
-    // Save obj in case the instrumentation event has thread suspension.
-    HandleWrapperObjPtr<mirror::Object> h = hs.NewHandleWrapper(&obj);
-    instrumentation->FieldReadEvent(self,
-                                    obj,
-                                    shadow_frame.GetMethod(),
-                                    shadow_frame.GetDexPC(),
-                                    f);
-    if (UNLIKELY(self->IsExceptionPending())) {
-      return false;
-    }
-  }
-  // Note: iget-x-quick instructions are only for non-volatile fields.
-  const uint32_t vregA = inst->VRegA_22c(inst_data);
-  switch (field_type) {
-    case Primitive::kPrimInt:
-      shadow_frame.SetVReg(vregA, static_cast<int32_t>(obj->GetField32(field_offset)));
-      break;
-    case Primitive::kPrimBoolean:
-      shadow_frame.SetVReg(vregA, static_cast<int32_t>(obj->GetFieldBoolean(field_offset)));
-      break;
-    case Primitive::kPrimByte:
-      shadow_frame.SetVReg(vregA, static_cast<int32_t>(obj->GetFieldByte(field_offset)));
-      break;
-    case Primitive::kPrimChar:
-      shadow_frame.SetVReg(vregA, static_cast<int32_t>(obj->GetFieldChar(field_offset)));
-      break;
-    case Primitive::kPrimShort:
-      shadow_frame.SetVReg(vregA, static_cast<int32_t>(obj->GetFieldShort(field_offset)));
-      break;
-    case Primitive::kPrimLong:
-      shadow_frame.SetVRegLong(vregA, static_cast<int64_t>(obj->GetField64(field_offset)));
-      break;
-    case Primitive::kPrimNot:
-      shadow_frame.SetVRegReference(vregA, obj->GetFieldObject<mirror::Object>(field_offset));
-      break;
-    default:
-      LOG(FATAL) << "Unreachable: " << field_type;
-      UNREACHABLE();
-  }
-  return true;
-}
-
 static inline bool CheckWriteConstraint(Thread* self, ObjPtr<mirror::Object> obj)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   Runtime* runtime = Runtime::Current();
@@ -710,81 +624,6 @@
                                                                                   value);
 }
 
-// Handles iput-quick, iput-wide-quick and iput-object-quick instructions.
-// Returns true on success, otherwise throws an exception and returns false.
-template<Primitive::Type field_type, bool transaction_active>
-ALWAYS_INLINE bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst,
-                               uint16_t inst_data) REQUIRES_SHARED(Locks::mutator_lock_) {
-  ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
-  if (UNLIKELY(obj == nullptr)) {
-    // We lost the reference to the field index so we cannot get a more
-    // precised exception message.
-    ThrowNullPointerExceptionFromDexPC();
-    return false;
-  }
-  MemberOffset field_offset(inst->VRegC_22c());
-  const uint32_t vregA = inst->VRegA_22c(inst_data);
-  // Report this field modification to instrumentation if needed. Since we only have the offset of
-  // the field from the base of the object, we need to look for it first.
-  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
-  if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
-    ArtField* f = ArtField::FindInstanceFieldWithOffset(obj->GetClass(),
-                                                        field_offset.Uint32Value());
-    DCHECK(f != nullptr);
-    DCHECK(!f->IsStatic());
-    JValue field_value = GetFieldValue<field_type>(shadow_frame, vregA);
-    Thread* self = Thread::Current();
-    StackHandleScope<2> hs(self);
-    // Save obj in case the instrumentation event has thread suspension.
-    HandleWrapperObjPtr<mirror::Object> h = hs.NewHandleWrapper(&obj);
-    mirror::Object* fake_root = nullptr;
-    HandleWrapper<mirror::Object> ret(hs.NewHandleWrapper<mirror::Object>(
-        field_type == Primitive::kPrimNot ? field_value.GetGCRoot() : &fake_root));
-    instrumentation->FieldWriteEvent(self,
-                                     obj,
-                                     shadow_frame.GetMethod(),
-                                     shadow_frame.GetDexPC(),
-                                     f,
-                                     field_value);
-    if (UNLIKELY(self->IsExceptionPending())) {
-      return false;
-    }
-    if (UNLIKELY(shadow_frame.GetForcePopFrame())) {
-      // Don't actually set the field. The next instruction will force us to pop.
-      DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
-      return true;
-    }
-  }
-  // Note: iput-x-quick instructions are only for non-volatile fields.
-  switch (field_type) {
-    case Primitive::kPrimBoolean:
-      obj->SetFieldBoolean<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
-      break;
-    case Primitive::kPrimByte:
-      obj->SetFieldByte<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
-      break;
-    case Primitive::kPrimChar:
-      obj->SetFieldChar<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
-      break;
-    case Primitive::kPrimShort:
-      obj->SetFieldShort<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
-      break;
-    case Primitive::kPrimInt:
-      obj->SetField32<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
-      break;
-    case Primitive::kPrimLong:
-      obj->SetField64<transaction_active>(field_offset, shadow_frame.GetVRegLong(vregA));
-      break;
-    case Primitive::kPrimNot:
-      obj->SetFieldObject<transaction_active>(field_offset, shadow_frame.GetVRegReference(vregA));
-      break;
-    default:
-      LOG(FATAL) << "Unreachable: " << field_type;
-      UNREACHABLE();
-  }
-  return true;
-}
-
 // Handles string resolution for const-string and const-string-jumbo instructions. Also ensures the
 // java.lang.String class is initialized.
 static inline ObjPtr<mirror::String> ResolveString(Thread* self,
diff --git a/runtime/interpreter/interpreter_intrinsics.cc b/runtime/interpreter/interpreter_intrinsics.cc
index 63bd967..7236bad 100644
--- a/runtime/interpreter/interpreter_intrinsics.cc
+++ b/runtime/interpreter/interpreter_intrinsics.cc
@@ -439,6 +439,8 @@
     UNIMPLEMENTED_CASE(FloatIsInfinite /* (F)Z */)
     UNIMPLEMENTED_CASE(FloatIsNaN /* (F)Z */)
     UNIMPLEMENTED_CASE(FloatIntBitsToFloat /* (I)F */)
+    UNIMPLEMENTED_CASE(IntegerDivideUnsigned /* (II)I */)
+    UNIMPLEMENTED_CASE(LongDivideUnsigned /* (JJ)J */)
     INTRINSIC_CASE(IntegerReverse)
     INTRINSIC_CASE(IntegerReverseBytes)
     INTRINSIC_CASE(IntegerBitCount)
@@ -498,6 +500,7 @@
     UNIMPLEMENTED_CASE(MathRint /* (D)D */)
     UNIMPLEMENTED_CASE(MathRoundDouble /* (D)J */)
     UNIMPLEMENTED_CASE(MathRoundFloat /* (F)I */)
+    UNIMPLEMENTED_CASE(MathMultiplyHigh /* (JJ)J */)
     UNIMPLEMENTED_CASE(SystemArrayCopyChar /* ([CI[CII)V */)
     UNIMPLEMENTED_CASE(SystemArrayCopy /* (Ljava/lang/Object;ILjava/lang/Object;II)V */)
     UNIMPLEMENTED_CASE(ThreadCurrentThread /* ()Ljava/lang/Thread; */)
@@ -568,6 +571,7 @@
     UNIMPLEMENTED_CASE(UnsafeStoreFence /* ()V */)
     UNIMPLEMENTED_CASE(UnsafeFullFence /* ()V */)
     UNIMPLEMENTED_CASE(ReferenceGetReferent /* ()Ljava/lang/Object; */)
+    UNIMPLEMENTED_CASE(ReferenceRefersTo /* (Ljava/lang/Object;)Z */)
     UNIMPLEMENTED_CASE(IntegerValueOf /* (I)Ljava/lang/Integer; */)
     UNIMPLEMENTED_CASE(ThreadInterrupted /* ()Z */)
     UNIMPLEMENTED_CASE(CRC32Update /* (II)I */)
diff --git a/runtime/interpreter/interpreter_switch_impl-inl.h b/runtime/interpreter/interpreter_switch_impl-inl.h
index 0f15adf..8e16e04 100644
--- a/runtime/interpreter/interpreter_switch_impl-inl.h
+++ b/runtime/interpreter/interpreter_switch_impl-inl.h
@@ -55,68 +55,88 @@
  public:
 #define HANDLER_ATTRIBUTES ALWAYS_INLINE FLATTEN WARN_UNUSED REQUIRES_SHARED(Locks::mutator_lock_)
 
+  HANDLER_ATTRIBUTES bool CheckTransactionAbort() {
+    if (transaction_active && Runtime::Current()->IsTransactionAborted()) {
+      // Transaction abort cannot be caught by catch handlers.
+      // Preserve the abort exception while doing non-standard return.
+      StackHandleScope<1u> hs(Self());
+      Handle<mirror::Throwable> abort_exception = hs.NewHandle(Self()->GetException());
+      DCHECK(abort_exception != nullptr);
+      DCHECK(abort_exception->GetClass()->DescriptorEquals(Transaction::kAbortExceptionDescriptor));
+      Self()->ClearException();
+      PerformNonStandardReturn<kMonitorState>(Self(),
+                                              shadow_frame_,
+                                              ctx_->result,
+                                              Instrumentation(),
+                                              Accessor().InsSize(),
+                                              inst_->GetDexPc(Insns()));
+      Self()->SetException(abort_exception.Get());
+      ExitInterpreterLoop();
+      return false;
+    }
+    return true;
+  }
+
   HANDLER_ATTRIBUTES bool CheckForceReturn() {
-    if (PerformNonStandardReturn<kMonitorState>(self,
-                                                shadow_frame,
-                                                ctx->result,
-                                                instrumentation,
-                                                Accessor().InsSize(),
-                                                inst->GetDexPc(Insns()))) {
-      exit_interpreter_loop = true;
+    if (shadow_frame_.GetForcePopFrame()) {
+      DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
+      PerformNonStandardReturn<kMonitorState>(Self(),
+                                              shadow_frame_,
+                                              ctx_->result,
+                                              Instrumentation(),
+                                              Accessor().InsSize(),
+                                              inst_->GetDexPc(Insns()));
+      ExitInterpreterLoop();
       return false;
     }
     return true;
   }
 
   HANDLER_ATTRIBUTES bool HandlePendingException() {
-    DCHECK(self->IsExceptionPending());
-    self->AllowThreadSuspension();
+    DCHECK(Self()->IsExceptionPending());
+    Self()->AllowThreadSuspension();
+    if (!CheckTransactionAbort()) {
+      return false;
+    }
     if (!CheckForceReturn()) {
       return false;
     }
-    bool skip_event = shadow_frame.GetSkipNextExceptionEvent();
-    shadow_frame.SetSkipNextExceptionEvent(false);
-    if (!MoveToExceptionHandler(self, shadow_frame, skip_event ? nullptr : instrumentation)) {
+    bool skip_event = shadow_frame_.GetSkipNextExceptionEvent();
+    shadow_frame_.SetSkipNextExceptionEvent(false);
+    if (!MoveToExceptionHandler(Self(), shadow_frame_, skip_event ? nullptr : Instrumentation())) {
       /* Structured locking is to be enforced for abnormal termination, too. */
-      DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
-      ctx->result = JValue(); /* Handled in caller. */
-      exit_interpreter_loop = true;
+      DoMonitorCheckOnExit<do_assignability_check>(Self(), &shadow_frame_);
+      ctx_->result = JValue(); /* Handled in caller. */
+      ExitInterpreterLoop();
       return false;  // Return to caller.
     }
     if (!CheckForceReturn()) {
       return false;
     }
     int32_t displacement =
-        static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc);
-    SetNextInstruction(inst->RelativeAt(displacement));
+        static_cast<int32_t>(shadow_frame_.GetDexPC()) - static_cast<int32_t>(dex_pc_);
+    SetNextInstruction(inst_->RelativeAt(displacement));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool PossiblyHandlePendingExceptionOnInvoke(bool is_exception_pending) {
-    if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) {
+    if (UNLIKELY(shadow_frame_.GetForceRetryInstruction())) {
       /* Don't need to do anything except clear the flag and exception. We leave the */
       /* instruction the same so it will be re-executed on the next go-around.       */
-      DCHECK(inst->IsInvoke());
-      shadow_frame.SetForceRetryInstruction(false);
+      DCHECK(inst_->IsInvoke());
+      shadow_frame_.SetForceRetryInstruction(false);
       if (UNLIKELY(is_exception_pending)) {
-        DCHECK(self->IsExceptionPending());
+        DCHECK(Self()->IsExceptionPending());
         if (kIsDebugBuild) {
           LOG(WARNING) << "Suppressing exception for instruction-retry: "
-                       << self->GetException()->Dump();
+                       << Self()->GetException()->Dump();
         }
-        self->ClearException();
+        Self()->ClearException();
       }
-      SetNextInstruction(inst);
+      SetNextInstruction(inst_);
     } else if (UNLIKELY(is_exception_pending)) {
       /* Should have succeeded. */
-      DCHECK(!shadow_frame.GetForceRetryInstruction());
-      return false;  // Pending exception.
-    }
-    return true;
-  }
-
-  HANDLER_ATTRIBUTES bool HandleMonitorChecks() {
-    if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
+      DCHECK(!shadow_frame_.GetForceRetryInstruction());
       return false;  // Pending exception.
     }
     return true;
@@ -129,19 +149,19 @@
     if (!CheckForceReturn()) {
       return false;
     }
-    if (UNLIKELY(instrumentation->HasDexPcListeners())) {
-      uint8_t opcode = inst->Opcode(inst_data);
+    if (UNLIKELY(Instrumentation()->HasDexPcListeners())) {
+      uint8_t opcode = inst_->Opcode(inst_data_);
       bool is_move_result_object = (opcode == Instruction::MOVE_RESULT_OBJECT);
-      JValue* save_ref = is_move_result_object ? &ctx->result_register : nullptr;
-      if (UNLIKELY(!DoDexPcMoveEvent(self,
+      JValue* save_ref = is_move_result_object ? &ctx_->result_register : nullptr;
+      if (UNLIKELY(!DoDexPcMoveEvent(Self(),
                                      Accessor(),
-                                     shadow_frame,
-                                     dex_pc,
-                                     instrumentation,
+                                     shadow_frame_,
+                                     DexPC(),
+                                     Instrumentation(),
                                      save_ref))) {
-        DCHECK(self->IsExceptionPending());
+        DCHECK(Self()->IsExceptionPending());
         // Do not raise exception event if it is caused by other instrumentation event.
-        shadow_frame.SetSkipNextExceptionEvent(true);
+        shadow_frame_.SetSkipNextExceptionEvent(true);
         return false;  // Pending exception.
       }
       if (!CheckForceReturn()) {
@@ -151,48 +171,6 @@
     return true;
   }
 
-  HANDLER_ATTRIBUTES bool BranchInstrumentation(int32_t offset) {
-    if (UNLIKELY(instrumentation->HasBranchListeners())) {
-      instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
-    }
-    JValue result;
-    if (jit::Jit::MaybeDoOnStackReplacement(self,
-                                            shadow_frame.GetMethod(),
-                                            dex_pc,
-                                            offset,
-                                            &result)) {
-      ctx->result = result;
-      exit_interpreter_loop = true;
-      return false;
-    }
-    return true;
-  }
-
-  ALWAYS_INLINE void HotnessUpdate()
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    jit::Jit* jit = Runtime::Current()->GetJit();
-    if (jit != nullptr) {
-      jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
-    }
-  }
-
-  HANDLER_ATTRIBUTES bool HandleAsyncException() {
-    if (UNLIKELY(self->ObserveAsyncException())) {
-      return false;  // Pending exception.
-    }
-    return true;
-  }
-
-  ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (IsBackwardBranch(offset)) {
-      HotnessUpdate();
-      /* Record new dex pc early to have consistent suspend point at loop header. */
-      shadow_frame.SetDexPC(next->GetDexPc(Insns()));
-      self->AllowThreadSuspension();
-    }
-  }
-
   // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
   // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
   // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
@@ -201,7 +179,7 @@
   NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
                                          const CodeItemDataAccessor& accessor,
                                          const ShadowFrame& shadow_frame,
-                                         uint32_t dex_pc,
+                                         uint32_t dex_pc_,
                                          const instrumentation::Instrumentation* instrumentation,
                                          JValue* save_ref)
       REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -215,56 +193,81 @@
     instrumentation->DexPcMovedEvent(self,
                                      shadow_frame.GetThisObject(accessor.InsSize()),
                                      shadow_frame.GetMethod(),
-                                     dex_pc);
+                                     dex_pc_);
     if (UNLIKELY(self->IsExceptionPending())) {
       // We got a new exception in the dex-pc-moved event.
       // We just let this exception replace the old one.
       // TODO It would be good to add the old exception to the
       // suppressed exceptions of the new one if possible.
       return false;  // Pending exception.
-    } else {
-      if (UNLIKELY(!thr.IsNull())) {
-        self->SetException(thr.Get());
-      }
-      return true;
     }
+    if (UNLIKELY(!thr.IsNull())) {
+      self->SetException(thr.Get());
+    }
+    return true;
   }
 
   HANDLER_ATTRIBUTES bool HandleReturn(JValue result) {
-    self->AllowThreadSuspension();
-    if (!HandleMonitorChecks()) {
+    Self()->AllowThreadSuspension();
+    if (!DoMonitorCheckOnExit<do_assignability_check>(Self(), &shadow_frame_)) {
       return false;
     }
-    if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
-                 !SendMethodExitEvents(self,
-                                       instrumentation,
-                                       shadow_frame,
-                                       shadow_frame.GetThisObject(Accessor().InsSize()),
-                                       shadow_frame.GetMethod(),
-                                       inst->GetDexPc(Insns()),
+    if (UNLIKELY(NeedsMethodExitEvent(Instrumentation()) &&
+                 !SendMethodExitEvents(Self(),
+                                       Instrumentation(),
+                                       shadow_frame_,
+                                       shadow_frame_.GetThisObject(Accessor().InsSize()),
+                                       shadow_frame_.GetMethod(),
+                                       inst_->GetDexPc(Insns()),
                                        result))) {
-      DCHECK(self->IsExceptionPending());
+      DCHECK(Self()->IsExceptionPending());
       // Do not raise exception event if it is caused by other instrumentation event.
-      shadow_frame.SetSkipNextExceptionEvent(true);
+      shadow_frame_.SetSkipNextExceptionEvent(true);
       return false;  // Pending exception.
     }
-    ctx->result = result;
-    exit_interpreter_loop = true;
+    ctx_->result = result;
+    ExitInterpreterLoop();
     return false;
   }
 
-  HANDLER_ATTRIBUTES bool HandleGoto(int32_t offset) {
-    if (!HandleAsyncException()) {
-      return false;
+  HANDLER_ATTRIBUTES bool HandleBranch(int32_t offset) {
+    if (UNLIKELY(Self()->ObserveAsyncException())) {
+      return false;  // Pending exception.
     }
-    if (!BranchInstrumentation(offset)) {
-      return false;
+    if (UNLIKELY(Instrumentation()->HasBranchListeners())) {
+      Instrumentation()->Branch(Self(), shadow_frame_.GetMethod(), DexPC(), offset);
     }
-    SetNextInstruction(inst->RelativeAt(offset));
-    HandleBackwardBranch(offset);
+    if (!transaction_active) {
+      // TODO: Do OSR only on back-edges and check if OSR code is ready here.
+      JValue result;
+      if (jit::Jit::MaybeDoOnStackReplacement(Self(),
+                                              shadow_frame_.GetMethod(),
+                                              DexPC(),
+                                              offset,
+                                              &result)) {
+        ctx_->result = result;
+        ExitInterpreterLoop();
+        return false;
+      }
+    }
+    SetNextInstruction(inst_->RelativeAt(offset));
+    if (offset <= 0) {  // Back-edge.
+      // Hotness update.
+      jit::Jit* jit = Runtime::Current()->GetJit();
+      if (jit != nullptr) {
+        jit->AddSamples(Self(), shadow_frame_.GetMethod(), 1, /*with_backedges=*/ true);
+      }
+      // Record new dex pc early to have consistent suspend point at loop header.
+      shadow_frame_.SetDexPC(next_->GetDexPc(Insns()));
+      Self()->AllowThreadSuspension();
+    }
     return true;
   }
 
+  HANDLER_ATTRIBUTES bool HandleIf(bool cond, int32_t offset) {
+    return HandleBranch(cond ? offset : Instruction::SizeInCodeUnits(kFormat));
+  }
+
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wfloat-equal"
 
@@ -299,18 +302,12 @@
 
 #pragma clang diagnostic pop
 
-  HANDLER_ATTRIBUTES bool HandleIf(bool cond, int32_t offset) {
-    if (cond) {
-      if (!BranchInstrumentation(offset)) {
-        return false;
-      }
-      SetNextInstruction(inst->RelativeAt(offset));
-      HandleBackwardBranch(offset);
-    } else {
-      if (!BranchInstrumentation(2)) {
-        return false;
-      }
+  HANDLER_ATTRIBUTES bool HandleConstString() {
+    ObjPtr<mirror::String> s = ResolveString(Self(), shadow_frame_, dex::StringIndex(B()));
+    if (UNLIKELY(s == nullptr)) {
+      return false;  // Pending exception.
     }
+    SetVRegReference(A(), s);
     return true;
   }
 
@@ -325,9 +322,8 @@
     ObjPtr<ArrayType> array = ObjPtr<ArrayType>::DownCast(a);
     if (UNLIKELY(!array->CheckIsValidIndex(index))) {
       return false;  // Pending exception.
-    } else {
-      (this->*setVReg)(A(), array->GetWithoutChecks(index));
     }
+    (this->*setVReg)(A(), array->GetWithoutChecks(index));
     return true;
   }
 
@@ -342,47 +338,35 @@
     ObjPtr<ArrayType> array = ObjPtr<ArrayType>::DownCast(a);
     if (UNLIKELY(!array->CheckIsValidIndex(index))) {
       return false;  // Pending exception.
-    } else {
-      if (transaction_active && !CheckWriteConstraint(self, array)) {
-        return false;
-      }
-      array->template SetWithoutChecks<transaction_active>(index, value);
     }
+    if (transaction_active && !CheckWriteConstraint(Self(), array)) {
+      return false;
+    }
+    array->template SetWithoutChecks<transaction_active>(index, value);
     return true;
   }
 
   template<FindFieldType find_type, Primitive::Type field_type>
   HANDLER_ATTRIBUTES bool HandleGet() {
     return DoFieldGet<find_type, field_type, do_access_check, transaction_active>(
-        self, shadow_frame, inst, inst_data);
-  }
-
-  template<Primitive::Type field_type>
-  HANDLER_ATTRIBUTES bool HandleGetQuick() {
-    return DoIGetQuick<field_type>(shadow_frame, inst, inst_data);
+        Self(), shadow_frame_, inst_, inst_data_);
   }
 
   template<FindFieldType find_type, Primitive::Type field_type>
   HANDLER_ATTRIBUTES bool HandlePut() {
     return DoFieldPut<find_type, field_type, do_access_check, transaction_active>(
-        self, shadow_frame, inst, inst_data);
+        Self(), shadow_frame_, inst_, inst_data_);
   }
 
-  template<Primitive::Type field_type>
-  HANDLER_ATTRIBUTES bool HandlePutQuick() {
-    return DoIPutQuick<field_type, transaction_active>(
-        shadow_frame, inst, inst_data);
-  }
-
-  template<InvokeType type, bool is_range, bool is_quick = false>
+  template<InvokeType type, bool is_range>
   HANDLER_ATTRIBUTES bool HandleInvoke() {
-    bool success = DoInvoke<type, is_range, do_access_check, /*is_mterp=*/ false, is_quick>(
-        self, shadow_frame, inst, inst_data, ResultRegister());
+    bool success = DoInvoke<type, is_range, do_access_check, /*is_mterp=*/ false>(
+        Self(), shadow_frame_, inst_, inst_data_, ResultRegister());
     return PossiblyHandlePendingExceptionOnInvoke(!success);
   }
 
   HANDLER_ATTRIBUTES bool HandleUnused() {
-    UnexpectedOpcode(inst, shadow_frame);
+    UnexpectedOpcode(inst_, shadow_frame_);
     return true;
   }
 
@@ -451,18 +435,13 @@
   }
 
   HANDLER_ATTRIBUTES bool MOVE_EXCEPTION() {
-    ObjPtr<mirror::Throwable> exception = self->GetException();
+    ObjPtr<mirror::Throwable> exception = Self()->GetException();
     DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
     SetVRegReference(A(), exception);
-    self->ClearException();
+    Self()->ClearException();
     return true;
   }
 
-  HANDLER_ATTRIBUTES bool RETURN_VOID_NO_BARRIER() {
-    JValue result;
-    return HandleReturn(result);
-  }
-
   HANDLER_ATTRIBUTES bool RETURN_VOID() {
     QuasiAtomic::ThreadFenceForConstructor();
     JValue result;
@@ -484,14 +463,14 @@
 
   HANDLER_ATTRIBUTES bool RETURN_OBJECT() {
     JValue result;
-    self->AllowThreadSuspension();
-    if (!HandleMonitorChecks()) {
+    Self()->AllowThreadSuspension();
+    if (!DoMonitorCheckOnExit<do_assignability_check>(Self(), &shadow_frame_)) {
       return false;
     }
     const size_t ref_idx = A();
     ObjPtr<mirror::Object> obj_result = GetVRegReference(ref_idx);
     if (do_assignability_check && obj_result != nullptr) {
-      ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
+      ObjPtr<mirror::Class> return_type = shadow_frame_.GetMethod()->ResolveReturnType();
       // Re-load since it might have moved.
       obj_result = GetVRegReference(ref_idx);
       if (return_type == nullptr) {
@@ -502,73 +481,53 @@
         CHECK_LE(Runtime::Current()->GetTargetSdkVersion(), 29u);
         // This should never happen.
         std::string temp1, temp2;
-        self->ThrowNewExceptionF("Ljava/lang/InternalError;",
-                                 "Returning '%s' that is not instance of return type '%s'",
-                                 obj_result->GetClass()->GetDescriptor(&temp1),
-                                 return_type->GetDescriptor(&temp2));
+        Self()->ThrowNewExceptionF("Ljava/lang/InternalError;",
+                                   "Returning '%s' that is not instance of return type '%s'",
+                                   obj_result->GetClass()->GetDescriptor(&temp1),
+                                   return_type->GetDescriptor(&temp2));
         return false;  // Pending exception.
       }
     }
-    StackHandleScope<1> hs(self);
+    StackHandleScope<1> hs(Self());
     MutableHandle<mirror::Object> h_result(hs.NewHandle(obj_result));
     result.SetL(obj_result);
-    if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
-                 !SendMethodExitEvents(self,
-                                       instrumentation,
-                                       shadow_frame,
-                                       shadow_frame.GetThisObject(Accessor().InsSize()),
-                                       shadow_frame.GetMethod(),
-                                       inst->GetDexPc(Insns()),
+    if (UNLIKELY(NeedsMethodExitEvent(Instrumentation()) &&
+                 !SendMethodExitEvents(Self(),
+                                       Instrumentation(),
+                                       shadow_frame_,
+                                       shadow_frame_.GetThisObject(Accessor().InsSize()),
+                                       shadow_frame_.GetMethod(),
+                                       inst_->GetDexPc(Insns()),
                                        h_result))) {
-      DCHECK(self->IsExceptionPending());
+      DCHECK(Self()->IsExceptionPending());
       // Do not raise exception event if it is caused by other instrumentation event.
-      shadow_frame.SetSkipNextExceptionEvent(true);
+      shadow_frame_.SetSkipNextExceptionEvent(true);
       return false;  // Pending exception.
     }
     // Re-load since it might have moved or been replaced during the MethodExitEvent.
     result.SetL(h_result.Get());
-    ctx->result = result;
-    exit_interpreter_loop = true;
+    ctx_->result = result;
+    ExitInterpreterLoop();
     return false;
   }
 
   HANDLER_ATTRIBUTES bool CONST_4() {
-    uint4_t dst = inst->VRegA_11n(inst_data);
-    int4_t val = inst->VRegB_11n(inst_data);
-    SetVReg(dst, val);
-    if (val == 0) {
-      SetVRegReference(dst, nullptr);
-    }
+    SetVReg(A(), B());
     return true;
   }
 
   HANDLER_ATTRIBUTES bool CONST_16() {
-    uint8_t dst = A();
-    int16_t val = B();
-    SetVReg(dst, val);
-    if (val == 0) {
-      SetVRegReference(dst, nullptr);
-    }
+    SetVReg(A(), B());
     return true;
   }
 
   HANDLER_ATTRIBUTES bool CONST() {
-    uint8_t dst = A();
-    int32_t val = B();
-    SetVReg(dst, val);
-    if (val == 0) {
-      SetVRegReference(dst, nullptr);
-    }
+    SetVReg(A(), B());
     return true;
   }
 
   HANDLER_ATTRIBUTES bool CONST_HIGH16() {
-    uint8_t dst = A();
-    int32_t val = static_cast<int32_t>(B() << 16);
-    SetVReg(dst, val);
-    if (val == 0) {
-      SetVRegReference(dst, nullptr);
-    }
+    SetVReg(A(), static_cast<int32_t>(B() << 16));
     return true;
   }
 
@@ -583,7 +542,7 @@
   }
 
   HANDLER_ATTRIBUTES bool CONST_WIDE() {
-    SetVRegLong(A(), inst->WideVRegB());
+    SetVRegLong(A(), inst_->WideVRegB());
     return true;
   }
 
@@ -593,123 +552,104 @@
   }
 
   HANDLER_ATTRIBUTES bool CONST_STRING() {
-    ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
-    if (UNLIKELY(s == nullptr)) {
-      return false;  // Pending exception.
-    } else {
-      SetVRegReference(A(), s);
-    }
-    return true;
+    return HandleConstString();
   }
 
   HANDLER_ATTRIBUTES bool CONST_STRING_JUMBO() {
-    ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
-    if (UNLIKELY(s == nullptr)) {
-      return false;  // Pending exception.
-    } else {
-      SetVRegReference(A(), s);
-    }
-    return true;
+    return HandleConstString();
   }
 
   HANDLER_ATTRIBUTES bool CONST_CLASS() {
     ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
-                                                     shadow_frame.GetMethod(),
-                                                     self,
+                                                     shadow_frame_.GetMethod(),
+                                                     Self(),
                                                      false,
                                                      do_access_check);
     if (UNLIKELY(c == nullptr)) {
       return false;  // Pending exception.
-    } else {
-      SetVRegReference(A(), c);
     }
+    SetVRegReference(A(), c);
     return true;
   }
 
   HANDLER_ATTRIBUTES bool CONST_METHOD_HANDLE() {
     ClassLinker* cl = Runtime::Current()->GetClassLinker();
-    ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
+    ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(Self(),
                                                               B(),
-                                                              shadow_frame.GetMethod());
+                                                              shadow_frame_.GetMethod());
     if (UNLIKELY(mh == nullptr)) {
       return false;  // Pending exception.
-    } else {
-      SetVRegReference(A(), mh);
     }
+    SetVRegReference(A(), mh);
     return true;
   }
 
   HANDLER_ATTRIBUTES bool CONST_METHOD_TYPE() {
     ClassLinker* cl = Runtime::Current()->GetClassLinker();
-    ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
+    ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(Self(),
                                                           dex::ProtoIndex(B()),
-                                                          shadow_frame.GetMethod());
+                                                          shadow_frame_.GetMethod());
     if (UNLIKELY(mt == nullptr)) {
       return false;  // Pending exception.
-    } else {
-      SetVRegReference(A(), mt);
     }
+    SetVRegReference(A(), mt);
     return true;
   }
 
   HANDLER_ATTRIBUTES bool MONITOR_ENTER() {
-    if (!HandleAsyncException()) {
-      return false;
+    if (UNLIKELY(Self()->ObserveAsyncException())) {
+      return false;  // Pending exception.
     }
     ObjPtr<mirror::Object> obj = GetVRegReference(A());
     if (UNLIKELY(obj == nullptr)) {
       ThrowNullPointerExceptionFromInterpreter();
       return false;  // Pending exception.
-    } else {
-      DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
-      return !self->IsExceptionPending();
     }
+    DoMonitorEnter<do_assignability_check>(Self(), &shadow_frame_, obj);
+    return !Self()->IsExceptionPending();
   }
 
   HANDLER_ATTRIBUTES bool MONITOR_EXIT() {
-    if (!HandleAsyncException()) {
-      return false;
+    if (UNLIKELY(Self()->ObserveAsyncException())) {
+      return false;  // Pending exception.
     }
     ObjPtr<mirror::Object> obj = GetVRegReference(A());
     if (UNLIKELY(obj == nullptr)) {
       ThrowNullPointerExceptionFromInterpreter();
       return false;  // Pending exception.
-    } else {
-      DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
-      return !self->IsExceptionPending();
     }
+    DoMonitorExit<do_assignability_check>(Self(), &shadow_frame_, obj);
+    return !Self()->IsExceptionPending();
   }
 
   HANDLER_ATTRIBUTES bool CHECK_CAST() {
     ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
-                                                     shadow_frame.GetMethod(),
-                                                     self,
+                                                     shadow_frame_.GetMethod(),
+                                                     Self(),
                                                      false,
                                                      do_access_check);
     if (UNLIKELY(c == nullptr)) {
       return false;  // Pending exception.
-    } else {
-      ObjPtr<mirror::Object> obj = GetVRegReference(A());
-      if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
-        ThrowClassCastException(c, obj->GetClass());
-        return false;  // Pending exception.
-      }
+    }
+    ObjPtr<mirror::Object> obj = GetVRegReference(A());
+    if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
+      ThrowClassCastException(c, obj->GetClass());
+      return false;  // Pending exception.
     }
     return true;
   }
 
   HANDLER_ATTRIBUTES bool INSTANCE_OF() {
     ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(C()),
-                                                     shadow_frame.GetMethod(),
-                                                     self,
+                                                     shadow_frame_.GetMethod(),
+                                                     Self(),
                                                      false,
                                                      do_access_check);
     if (UNLIKELY(c == nullptr)) {
       return false;  // Pending exception.
-    } else {
-      ObjPtr<mirror::Object> obj = GetVRegReference(B());
-      SetVReg(A(), (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
     }
+    ObjPtr<mirror::Object> obj = GetVRegReference(B());
+    SetVReg(A(), (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
     return true;
   }
 
@@ -718,41 +658,39 @@
     if (UNLIKELY(array == nullptr)) {
       ThrowNullPointerExceptionFromInterpreter();
       return false;  // Pending exception.
-    } else {
-      SetVReg(A(), array->AsArray()->GetLength());
     }
+    SetVReg(A(), array->AsArray()->GetLength());
     return true;
   }
 
   HANDLER_ATTRIBUTES bool NEW_INSTANCE() {
     ObjPtr<mirror::Object> obj = nullptr;
     ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
-                                                     shadow_frame.GetMethod(),
-                                                     self,
+                                                     shadow_frame_.GetMethod(),
+                                                     Self(),
                                                      false,
                                                      do_access_check);
     if (LIKELY(c != nullptr)) {
       // Don't allow finalizable objects to be allocated during a transaction since these can't
       // be finalized without a started runtime.
       if (transaction_active && c->IsFinalizable()) {
-        AbortTransactionF(self,
+        AbortTransactionF(Self(),
                           "Allocating finalizable object in transaction: %s",
                           c->PrettyDescriptor().c_str());
         return false;  // Pending exception.
       }
       gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
       if (UNLIKELY(c->IsStringClass())) {
-        obj = mirror::String::AllocEmptyString(self, allocator_type);
+        obj = mirror::String::AllocEmptyString(Self(), allocator_type);
       } else {
-        obj = AllocObjectFromCode(c, self, allocator_type);
+        obj = AllocObjectFromCode(c, Self(), allocator_type);
       }
     }
     if (UNLIKELY(obj == nullptr)) {
       return false;  // Pending exception.
-    } else {
-      obj->GetClass()->AssertInitializedOrInitializingInThread(self);
-      SetVRegReference(A(), obj);
     }
+    obj->GetClass()->AssertInitializedOrInitializingInThread(Self());
+    SetVRegReference(A(), obj);
     return true;
   }
 
@@ -761,29 +699,28 @@
     ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check>(
         dex::TypeIndex(C()),
         length,
-        shadow_frame.GetMethod(),
-        self,
+        shadow_frame_.GetMethod(),
+        Self(),
         Runtime::Current()->GetHeap()->GetCurrentAllocator());
     if (UNLIKELY(obj == nullptr)) {
       return false;  // Pending exception.
-    } else {
-      SetVRegReference(A(), obj);
     }
+    SetVRegReference(A(), obj);
     return true;
   }
 
   HANDLER_ATTRIBUTES bool FILLED_NEW_ARRAY() {
     return DoFilledNewArray<false, do_access_check, transaction_active>(
-        inst, shadow_frame, self, ResultRegister());
+        inst_, shadow_frame_, Self(), ResultRegister());
   }
 
   HANDLER_ATTRIBUTES bool FILLED_NEW_ARRAY_RANGE() {
     return DoFilledNewArray<true, do_access_check, transaction_active>(
-        inst, shadow_frame, self, ResultRegister());
+        inst_, shadow_frame_, Self(), ResultRegister());
   }
 
   HANDLER_ATTRIBUTES bool FILL_ARRAY_DATA() {
-    const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + B();
+    const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst_) + B();
     const Instruction::ArrayDataPayload* payload =
         reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
     ObjPtr<mirror::Object> obj = GetVRegReference(A());
@@ -797,8 +734,8 @@
   }
 
   HANDLER_ATTRIBUTES bool THROW() {
-    if (!HandleAsyncException()) {
-      return false;
+    if (UNLIKELY(Self()->ObserveAsyncException())) {
+      return false;  // Pending exception.
     }
     ObjPtr<mirror::Object> exception = GetVRegReference(A());
     if (UNLIKELY(exception == nullptr)) {
@@ -806,45 +743,33 @@
     } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
       // This should never happen.
       std::string temp;
-      self->ThrowNewExceptionF("Ljava/lang/InternalError;",
-                               "Throwing '%s' that is not instance of Throwable",
-                               exception->GetClass()->GetDescriptor(&temp));
+      Self()->ThrowNewExceptionF("Ljava/lang/InternalError;",
+                                 "Throwing '%s' that is not instance of Throwable",
+                                 exception->GetClass()->GetDescriptor(&temp));
     } else {
-      self->SetException(exception->AsThrowable());
+      Self()->SetException(exception->AsThrowable());
     }
     return false;  // Pending exception.
   }
 
   HANDLER_ATTRIBUTES bool GOTO() {
-    return HandleGoto(A());
+    return HandleBranch(A());
   }
 
   HANDLER_ATTRIBUTES bool GOTO_16() {
-    return HandleGoto(A());
+    return HandleBranch(A());
   }
 
   HANDLER_ATTRIBUTES bool GOTO_32() {
-    return HandleGoto(A());
+    return HandleBranch(A());
   }
 
   HANDLER_ATTRIBUTES bool PACKED_SWITCH() {
-    int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
-    if (!BranchInstrumentation(offset)) {
-      return false;
-    }
-    SetNextInstruction(inst->RelativeAt(offset));
-    HandleBackwardBranch(offset);
-    return true;
+    return HandleBranch(DoPackedSwitch(inst_, shadow_frame_, inst_data_));
   }
 
   HANDLER_ATTRIBUTES bool SPARSE_SWITCH() {
-    int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
-    if (!BranchInstrumentation(offset)) {
-      return false;
-    }
-    SetNextInstruction(inst->RelativeAt(offset));
-    HandleBackwardBranch(offset);
-    return true;
+    return HandleBranch(DoSparseSwitch(inst_, shadow_frame_, inst_data_));
   }
 
   HANDLER_ATTRIBUTES bool CMPL_FLOAT() {
@@ -978,7 +903,7 @@
     ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
     if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
       if (transaction_active &&
-          (!CheckWriteConstraint(self, array) || !CheckWriteValueConstraint(self, val))) {
+          (!CheckWriteConstraint(Self(), array) || !CheckWriteValueConstraint(Self(), val))) {
         return false;
       }
       array->SetWithoutChecks<transaction_active>(index, val);
@@ -1016,34 +941,6 @@
     return HandleGet<InstanceObjectRead, Primitive::kPrimNot>();
   }
 
-  HANDLER_ATTRIBUTES bool IGET_QUICK() {
-    return HandleGetQuick<Primitive::kPrimInt>();
-  }
-
-  HANDLER_ATTRIBUTES bool IGET_WIDE_QUICK() {
-    return HandleGetQuick<Primitive::kPrimLong>();
-  }
-
-  HANDLER_ATTRIBUTES bool IGET_OBJECT_QUICK() {
-    return HandleGetQuick<Primitive::kPrimNot>();
-  }
-
-  HANDLER_ATTRIBUTES bool IGET_BOOLEAN_QUICK() {
-    return HandleGetQuick<Primitive::kPrimBoolean>();
-  }
-
-  HANDLER_ATTRIBUTES bool IGET_BYTE_QUICK() {
-    return HandleGetQuick<Primitive::kPrimByte>();
-  }
-
-  HANDLER_ATTRIBUTES bool IGET_CHAR_QUICK() {
-    return HandleGetQuick<Primitive::kPrimChar>();
-  }
-
-  HANDLER_ATTRIBUTES bool IGET_SHORT_QUICK() {
-    return HandleGetQuick<Primitive::kPrimShort>();
-  }
-
   HANDLER_ATTRIBUTES bool SGET_BOOLEAN() {
     return HandleGet<StaticPrimitiveRead, Primitive::kPrimBoolean>();
   }
@@ -1100,34 +997,6 @@
     return HandlePut<InstanceObjectWrite, Primitive::kPrimNot>();
   }
 
-  HANDLER_ATTRIBUTES bool IPUT_QUICK() {
-    return HandlePutQuick<Primitive::kPrimInt>();
-  }
-
-  HANDLER_ATTRIBUTES bool IPUT_BOOLEAN_QUICK() {
-    return HandlePutQuick<Primitive::kPrimBoolean>();
-  }
-
-  HANDLER_ATTRIBUTES bool IPUT_BYTE_QUICK() {
-    return HandlePutQuick<Primitive::kPrimByte>();
-  }
-
-  HANDLER_ATTRIBUTES bool IPUT_CHAR_QUICK() {
-    return HandlePutQuick<Primitive::kPrimChar>();
-  }
-
-  HANDLER_ATTRIBUTES bool IPUT_SHORT_QUICK() {
-    return HandlePutQuick<Primitive::kPrimShort>();
-  }
-
-  HANDLER_ATTRIBUTES bool IPUT_WIDE_QUICK() {
-    return HandlePutQuick<Primitive::kPrimLong>();
-  }
-
-  HANDLER_ATTRIBUTES bool IPUT_OBJECT_QUICK() {
-    return HandlePutQuick<Primitive::kPrimNot>();
-  }
-
   HANDLER_ATTRIBUTES bool SPUT_BOOLEAN() {
     return HandlePut<StaticPrimitiveWrite, Primitive::kPrimBoolean>();
   }
@@ -1196,39 +1065,31 @@
     return HandleInvoke<kStatic, /*is_range=*/ true>();
   }
 
-  HANDLER_ATTRIBUTES bool INVOKE_VIRTUAL_QUICK() {
-    return HandleInvoke<kVirtual, /*is_range=*/ false, /*is_quick=*/ true>();
-  }
-
-  HANDLER_ATTRIBUTES bool INVOKE_VIRTUAL_RANGE_QUICK() {
-    return HandleInvoke<kVirtual, /*is_range=*/ true, /*is_quick=*/ true>();
-  }
-
   HANDLER_ATTRIBUTES bool INVOKE_POLYMORPHIC() {
     DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
     bool success = DoInvokePolymorphic</* is_range= */ false>(
-        self, shadow_frame, inst, inst_data, ResultRegister());
+        Self(), shadow_frame_, inst_, inst_data_, ResultRegister());
     return PossiblyHandlePendingExceptionOnInvoke(!success);
   }
 
   HANDLER_ATTRIBUTES bool INVOKE_POLYMORPHIC_RANGE() {
     DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
     bool success = DoInvokePolymorphic</* is_range= */ true>(
-        self, shadow_frame, inst, inst_data, ResultRegister());
+        Self(), shadow_frame_, inst_, inst_data_, ResultRegister());
     return PossiblyHandlePendingExceptionOnInvoke(!success);
   }
 
   HANDLER_ATTRIBUTES bool INVOKE_CUSTOM() {
     DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
     bool success = DoInvokeCustom</* is_range= */ false>(
-        self, shadow_frame, inst, inst_data, ResultRegister());
+        Self(), shadow_frame_, inst_, inst_data_, ResultRegister());
     return PossiblyHandlePendingExceptionOnInvoke(!success);
   }
 
   HANDLER_ATTRIBUTES bool INVOKE_CUSTOM_RANGE() {
     DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
     bool success = DoInvokeCustom</* is_range= */ true>(
-        self, shadow_frame, inst, inst_data, ResultRegister());
+        Self(), shadow_frame_, inst_, inst_data_, ResultRegister());
     return PossiblyHandlePendingExceptionOnInvoke(!success);
   }
 
@@ -1293,16 +1154,12 @@
   }
 
   HANDLER_ATTRIBUTES bool FLOAT_TO_INT() {
-    float val = GetVRegFloat(B());
-    int32_t result = art_float_to_integral<int32_t, float>(val);
-    SetVReg(A(), result);
+    SetVReg(A(), art_float_to_integral<int32_t, float>(GetVRegFloat(B())));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool FLOAT_TO_LONG() {
-    float val = GetVRegFloat(B());
-    int64_t result = art_float_to_integral<int64_t, float>(val);
-    SetVRegLong(A(), result);
+    SetVRegLong(A(), art_float_to_integral<int64_t, float>(GetVRegFloat(B())));
     return true;
   }
 
@@ -1312,16 +1169,12 @@
   }
 
   HANDLER_ATTRIBUTES bool DOUBLE_TO_INT() {
-    double val = GetVRegDouble(B());
-    int32_t result = art_float_to_integral<int32_t, double>(val);
-    SetVReg(A(), result);
+    SetVReg(A(), art_float_to_integral<int32_t, double>(GetVRegDouble(B())));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool DOUBLE_TO_LONG() {
-    double val = GetVRegDouble(B());
-    int64_t result = art_float_to_integral<int64_t, double>(val);
-    SetVRegLong(A(), result);
+    SetVRegLong(A(), art_float_to_integral<int64_t, double>(GetVRegDouble(B())));
     return true;
   }
 
@@ -1361,11 +1214,11 @@
   }
 
   HANDLER_ATTRIBUTES bool DIV_INT() {
-    return DoIntDivide(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
+    return DoIntDivide(shadow_frame_, A(), GetVReg(B()), GetVReg(C()));
   }
 
   HANDLER_ATTRIBUTES bool REM_INT() {
-    return DoIntRemainder(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
+    return DoIntRemainder(shadow_frame_, A(), GetVReg(B()), GetVReg(C()));
   }
 
   HANDLER_ATTRIBUTES bool SHL_INT() {
@@ -1414,11 +1267,11 @@
   }
 
   HANDLER_ATTRIBUTES bool DIV_LONG() {
-    return DoLongDivide(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
+    return DoLongDivide(shadow_frame_, A(), GetVRegLong(B()), GetVRegLong(C()));
   }
 
   HANDLER_ATTRIBUTES bool REM_LONG() {
-    return DoLongRemainder(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
+    return DoLongRemainder(shadow_frame_, A(), GetVRegLong(B()), GetVRegLong(C()));
   }
 
   HANDLER_ATTRIBUTES bool AND_LONG() {
@@ -1502,190 +1355,158 @@
   }
 
   HANDLER_ATTRIBUTES bool ADD_INT_2ADDR() {
-    uint4_t vregA = A();
-    SetVReg(vregA, SafeAdd(GetVReg(vregA), GetVReg(B())));
+    SetVReg(A(), SafeAdd(GetVReg(A()), GetVReg(B())));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool SUB_INT_2ADDR() {
-    uint4_t vregA = A();
-    SetVReg(vregA, SafeSub(GetVReg(vregA), GetVReg(B())));
+    SetVReg(A(), SafeSub(GetVReg(A()), GetVReg(B())));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool MUL_INT_2ADDR() {
-    uint4_t vregA = A();
-    SetVReg(vregA, SafeMul(GetVReg(vregA), GetVReg(B())));
+    SetVReg(A(), SafeMul(GetVReg(A()), GetVReg(B())));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool DIV_INT_2ADDR() {
-    uint4_t vregA = A();
-    return DoIntDivide(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
+    return DoIntDivide(shadow_frame_, A(), GetVReg(A()), GetVReg(B()));
   }
 
   HANDLER_ATTRIBUTES bool REM_INT_2ADDR() {
-    uint4_t vregA = A();
-    return DoIntRemainder(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
+    return DoIntRemainder(shadow_frame_, A(), GetVReg(A()), GetVReg(B()));
   }
 
   HANDLER_ATTRIBUTES bool SHL_INT_2ADDR() {
-    uint4_t vregA = A();
-    SetVReg(vregA, GetVReg(vregA) << (GetVReg(B()) & 0x1f));
+    SetVReg(A(), GetVReg(A()) << (GetVReg(B()) & 0x1f));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool SHR_INT_2ADDR() {
-    uint4_t vregA = A();
-    SetVReg(vregA, GetVReg(vregA) >> (GetVReg(B()) & 0x1f));
+    SetVReg(A(), GetVReg(A()) >> (GetVReg(B()) & 0x1f));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool USHR_INT_2ADDR() {
-    uint4_t vregA = A();
-    SetVReg(vregA, static_cast<uint32_t>(GetVReg(vregA)) >> (GetVReg(B()) & 0x1f));
+    SetVReg(A(), static_cast<uint32_t>(GetVReg(A())) >> (GetVReg(B()) & 0x1f));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool AND_INT_2ADDR() {
-    uint4_t vregA = A();
-    SetVReg(vregA, GetVReg(vregA) & GetVReg(B()));
+    SetVReg(A(), GetVReg(A()) & GetVReg(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool OR_INT_2ADDR() {
-    uint4_t vregA = A();
-    SetVReg(vregA, GetVReg(vregA) | GetVReg(B()));
+    SetVReg(A(), GetVReg(A()) | GetVReg(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool XOR_INT_2ADDR() {
-    uint4_t vregA = A();
-    SetVReg(vregA, GetVReg(vregA) ^ GetVReg(B()));
+    SetVReg(A(), GetVReg(A()) ^ GetVReg(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool ADD_LONG_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegLong(vregA, SafeAdd(GetVRegLong(vregA), GetVRegLong(B())));
+    SetVRegLong(A(), SafeAdd(GetVRegLong(A()), GetVRegLong(B())));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool SUB_LONG_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegLong(vregA, SafeSub(GetVRegLong(vregA), GetVRegLong(B())));
+    SetVRegLong(A(), SafeSub(GetVRegLong(A()), GetVRegLong(B())));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool MUL_LONG_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegLong(vregA, SafeMul(GetVRegLong(vregA), GetVRegLong(B())));
+    SetVRegLong(A(), SafeMul(GetVRegLong(A()), GetVRegLong(B())));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool DIV_LONG_2ADDR() {
-    uint4_t vregA = A();
-    return DoLongDivide(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
+    return DoLongDivide(shadow_frame_, A(), GetVRegLong(A()), GetVRegLong(B()));
   }
 
   HANDLER_ATTRIBUTES bool REM_LONG_2ADDR() {
-    uint4_t vregA = A();
-    return DoLongRemainder(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
+    return DoLongRemainder(shadow_frame_, A(), GetVRegLong(A()), GetVRegLong(B()));
   }
 
   HANDLER_ATTRIBUTES bool AND_LONG_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegLong(vregA, GetVRegLong(vregA) & GetVRegLong(B()));
+    SetVRegLong(A(), GetVRegLong(A()) & GetVRegLong(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool OR_LONG_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegLong(vregA, GetVRegLong(vregA) | GetVRegLong(B()));
+    SetVRegLong(A(), GetVRegLong(A()) | GetVRegLong(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool XOR_LONG_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegLong(vregA, GetVRegLong(vregA) ^ GetVRegLong(B()));
+    SetVRegLong(A(), GetVRegLong(A()) ^ GetVRegLong(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool SHL_LONG_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegLong(vregA, GetVRegLong(vregA) << (GetVReg(B()) & 0x3f));
+    SetVRegLong(A(), GetVRegLong(A()) << (GetVReg(B()) & 0x3f));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool SHR_LONG_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegLong(vregA, GetVRegLong(vregA) >> (GetVReg(B()) & 0x3f));
+    SetVRegLong(A(), GetVRegLong(A()) >> (GetVReg(B()) & 0x3f));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool USHR_LONG_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegLong(vregA, static_cast<uint64_t>(GetVRegLong(vregA)) >> (GetVReg(B()) & 0x3f));
+    SetVRegLong(A(), static_cast<uint64_t>(GetVRegLong(A())) >> (GetVReg(B()) & 0x3f));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool ADD_FLOAT_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegFloat(vregA, GetVRegFloat(vregA) + GetVRegFloat(B()));
+    SetVRegFloat(A(), GetVRegFloat(A()) + GetVRegFloat(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool SUB_FLOAT_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegFloat(vregA, GetVRegFloat(vregA) - GetVRegFloat(B()));
+    SetVRegFloat(A(), GetVRegFloat(A()) - GetVRegFloat(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool MUL_FLOAT_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegFloat(vregA, GetVRegFloat(vregA) * GetVRegFloat(B()));
+    SetVRegFloat(A(), GetVRegFloat(A()) * GetVRegFloat(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool DIV_FLOAT_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegFloat(vregA, GetVRegFloat(vregA) / GetVRegFloat(B()));
+    SetVRegFloat(A(), GetVRegFloat(A()) / GetVRegFloat(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool REM_FLOAT_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegFloat(vregA, fmodf(GetVRegFloat(vregA), GetVRegFloat(B())));
+    SetVRegFloat(A(), fmodf(GetVRegFloat(A()), GetVRegFloat(B())));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool ADD_DOUBLE_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegDouble(vregA, GetVRegDouble(vregA) + GetVRegDouble(B()));
+    SetVRegDouble(A(), GetVRegDouble(A()) + GetVRegDouble(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool SUB_DOUBLE_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegDouble(vregA, GetVRegDouble(vregA) - GetVRegDouble(B()));
+    SetVRegDouble(A(), GetVRegDouble(A()) - GetVRegDouble(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool MUL_DOUBLE_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegDouble(vregA, GetVRegDouble(vregA) * GetVRegDouble(B()));
+    SetVRegDouble(A(), GetVRegDouble(A()) * GetVRegDouble(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool DIV_DOUBLE_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegDouble(vregA, GetVRegDouble(vregA) / GetVRegDouble(B()));
+    SetVRegDouble(A(), GetVRegDouble(A()) / GetVRegDouble(B()));
     return true;
   }
 
   HANDLER_ATTRIBUTES bool REM_DOUBLE_2ADDR() {
-    uint4_t vregA = A();
-    SetVRegDouble(vregA, fmod(GetVRegDouble(vregA), GetVRegDouble(B())));
+    SetVRegDouble(A(), fmod(GetVRegDouble(A()), GetVRegDouble(B())));
     return true;
   }
 
@@ -1705,11 +1526,11 @@
   }
 
   HANDLER_ATTRIBUTES bool DIV_INT_LIT16() {
-    return DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
+    return DoIntDivide(shadow_frame_, A(), GetVReg(B()), C());
   }
 
   HANDLER_ATTRIBUTES bool REM_INT_LIT16() {
-    return DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
+    return DoIntRemainder(shadow_frame_, A(), GetVReg(B()), C());
   }
 
   HANDLER_ATTRIBUTES bool AND_INT_LIT16() {
@@ -1743,11 +1564,11 @@
   }
 
   HANDLER_ATTRIBUTES bool DIV_INT_LIT8() {
-    return DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
+    return DoIntDivide(shadow_frame_, A(), GetVReg(B()), C());
   }
 
   HANDLER_ATTRIBUTES bool REM_INT_LIT8() {
-    return DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
+    return DoIntRemainder(shadow_frame_, A(), GetVReg(B()), C());
   }
 
   HANDLER_ATTRIBUTES bool AND_INT_LIT8() {
@@ -1804,6 +1625,10 @@
     return HandleUnused();
   }
 
+  HANDLER_ATTRIBUTES bool UNUSED_73() {
+    return HandleUnused();
+  }
+
   HANDLER_ATTRIBUTES bool UNUSED_79() {
     return HandleUnused();
   }
@@ -1812,6 +1637,70 @@
     return HandleUnused();
   }
 
+  HANDLER_ATTRIBUTES bool UNUSED_E3() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_E4() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_E5() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_E6() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_E7() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_E8() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_E9() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_EA() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_EB() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_EC() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_ED() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_EE() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_EF() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_F0() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_F1() {
+    return HandleUnused();
+  }
+
+  HANDLER_ATTRIBUTES bool UNUSED_F2() {
+    return HandleUnused();
+  }
+
   HANDLER_ATTRIBUTES bool UNUSED_F3() {
     return HandleUnused();
   }
@@ -1849,15 +1738,15 @@
                                    uint16_t inst_data,
                                    const Instruction*& next,
                                    bool& exit_interpreter_loop)
-    : ctx(ctx),
-      instrumentation(instrumentation),
-      self(self),
-      shadow_frame(shadow_frame),
-      dex_pc(dex_pc),
-      inst(inst),
-      inst_data(inst_data),
-      next(next),
-      exit_interpreter_loop(exit_interpreter_loop) {
+    : ctx_(ctx),
+      instrumentation_(instrumentation),
+      self_(self),
+      shadow_frame_(shadow_frame),
+      dex_pc_(dex_pc),
+      inst_(inst),
+      inst_data_(inst_data),
+      next_(next),
+      exit_interpreter_loop_(exit_interpreter_loop) {
   }
 
  private:
@@ -1865,47 +1754,66 @@
   static constexpr MonitorState kMonitorState =
       do_assignability_check ? MonitorState::kCountingMonitors : MonitorState::kNormalMonitors;
 
-  const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
-  const uint16_t* Insns() { return ctx->accessor.Insns(); }
-  JValue* ResultRegister() { return &ctx->result_register; }
+  ALWAYS_INLINE const CodeItemDataAccessor& Accessor() { return ctx_->accessor; }
+  ALWAYS_INLINE const uint16_t* Insns() { return ctx_->accessor.Insns(); }
+  ALWAYS_INLINE JValue* ResultRegister() { return &ctx_->result_register; }
 
-  ALWAYS_INLINE int32_t A() { return inst->VRegA(kFormat, inst_data); }
-  ALWAYS_INLINE int32_t B() { return inst->VRegB(kFormat, inst_data); }
-  ALWAYS_INLINE int32_t C() { return inst->VRegC(kFormat); }
-
-  int32_t GetVReg(size_t i) const { return shadow_frame.GetVReg(i); }
-  int64_t GetVRegLong(size_t i) const { return shadow_frame.GetVRegLong(i); }
-  float GetVRegFloat(size_t i) const { return shadow_frame.GetVRegFloat(i); }
-  double GetVRegDouble(size_t i) const { return shadow_frame.GetVRegDouble(i); }
-  ObjPtr<mirror::Object> GetVRegReference(size_t i) const REQUIRES_SHARED(Locks::mutator_lock_) {
-    return shadow_frame.GetVRegReference(i);
+  ALWAYS_INLINE Thread* Self() {
+    DCHECK_EQ(self_, Thread::Current());
+    return self_;
   }
 
-  void SetVReg(size_t i, int32_t val) { shadow_frame.SetVReg(i, val); }
-  void SetVRegLong(size_t i, int64_t val) { shadow_frame.SetVRegLong(i, val); }
-  void SetVRegFloat(size_t i, float val) { shadow_frame.SetVRegFloat(i, val); }
-  void SetVRegDouble(size_t i, double val) { shadow_frame.SetVRegDouble(i, val); }
+  ALWAYS_INLINE int32_t DexPC() {
+    DCHECK_EQ(dex_pc_, shadow_frame_.GetDexPC());
+    return dex_pc_;
+  }
+
+  ALWAYS_INLINE const instrumentation::Instrumentation* Instrumentation() {
+    return instrumentation_;
+  }
+
+  ALWAYS_INLINE int32_t A() { return inst_->VRegA(kFormat, inst_data_); }
+  ALWAYS_INLINE int32_t B() { return inst_->VRegB(kFormat, inst_data_); }
+  ALWAYS_INLINE int32_t C() { return inst_->VRegC(kFormat); }
+
+  int32_t GetVReg(size_t i) const { return shadow_frame_.GetVReg(i); }
+  int64_t GetVRegLong(size_t i) const { return shadow_frame_.GetVRegLong(i); }
+  float GetVRegFloat(size_t i) const { return shadow_frame_.GetVRegFloat(i); }
+  double GetVRegDouble(size_t i) const { return shadow_frame_.GetVRegDouble(i); }
+  ObjPtr<mirror::Object> GetVRegReference(size_t i) const REQUIRES_SHARED(Locks::mutator_lock_) {
+    return shadow_frame_.GetVRegReference(i);
+  }
+
+  void SetVReg(size_t i, int32_t val) { shadow_frame_.SetVReg(i, val); }
+  void SetVRegLong(size_t i, int64_t val) { shadow_frame_.SetVRegLong(i, val); }
+  void SetVRegFloat(size_t i, float val) { shadow_frame_.SetVRegFloat(i, val); }
+  void SetVRegDouble(size_t i, double val) { shadow_frame_.SetVRegDouble(i, val); }
   void SetVRegReference(size_t i, ObjPtr<mirror::Object> val)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    shadow_frame.SetVRegReference(i, val);
+    shadow_frame_.SetVRegReference(i, val);
   }
 
   // Set the next instruction to be executed.  It is the 'fall-through' instruction by default.
   ALWAYS_INLINE void SetNextInstruction(const Instruction* next_inst) {
     DCHECK_LT(next_inst->GetDexPc(Insns()), Accessor().InsnsSizeInCodeUnits());
-    next = next_inst;
+    next_ = next_inst;
   }
 
-  SwitchImplContext* const ctx;
-  const instrumentation::Instrumentation* const instrumentation;
-  Thread* const self;
-  ShadowFrame& shadow_frame;
-  uint32_t const dex_pc;
-  const Instruction* const inst;
-  uint16_t const inst_data;
-  const Instruction*& next;
+  // Stop interpreting the current method. (return statement, debugger-forced return, OSR, ...)
+  ALWAYS_INLINE void ExitInterpreterLoop() {
+    exit_interpreter_loop_ = true;
+  }
 
-  bool& exit_interpreter_loop;
+  SwitchImplContext* const ctx_;
+  const instrumentation::Instrumentation* const instrumentation_;
+  Thread* const self_;
+  ShadowFrame& shadow_frame_;
+  uint32_t const dex_pc_;
+  const Instruction* const inst_;
+  uint16_t const inst_data_;
+  const Instruction*& next_;
+
+  bool& exit_interpreter_loop_;
 };
 
 // Don't inline in ASAN. It would create massive stack frame.
@@ -1957,35 +1865,29 @@
     TraceExecution(shadow_frame, inst, dex_pc);
     uint16_t inst_data = inst->Fetch16(0);
     bool exit = false;
+    bool success;  // Moved outside to keep frames small under asan.
     if (InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat>(
             ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit).
             Preamble()) {
+      DCHECK_EQ(self->IsExceptionPending(), inst->Opcode(inst_data) == Instruction::MOVE_EXCEPTION);
       switch (inst->Opcode(inst_data)) {
 #define OPCODE_CASE(OPCODE, OPCODE_NAME, NAME, FORMAT, i, a, e, v)                                \
         case OPCODE: {                                                                            \
-          DCHECK_EQ(self->IsExceptionPending(), (OPCODE == Instruction::MOVE_EXCEPTION));         \
           next = inst->RelativeAt(Instruction::SizeInCodeUnits(Instruction::FORMAT));             \
-          bool success = OP_##OPCODE_NAME<do_access_check, transaction_active>(                   \
+          success = OP_##OPCODE_NAME<do_access_check, transaction_active>(                        \
               ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit);     \
           if (success && LIKELY(!interpret_one_instruction)) {                                    \
-            DCHECK(!exit) << NAME;                                                                \
             continue;                                                                             \
           }                                                                                       \
-          if (exit) {                                                                             \
-            shadow_frame.SetDexPC(dex::kDexNoIndex);                                              \
-            return;                                                                               \
-          }                                                                                       \
           break;                                                                                  \
         }
   DEX_INSTRUCTION_LIST(OPCODE_CASE)
 #undef OPCODE_CASE
       }
-    } else {
-      // Preamble returned false due to debugger event.
-      if (exit) {
-        shadow_frame.SetDexPC(dex::kDexNoIndex);
-        return;  // Return statement or debugger forced exit.
-      }
+    }
+    if (exit) {
+      shadow_frame.SetDexPC(dex::kDexNoIndex);
+      return;  // Return statement or debugger forced exit.
     }
     if (self->IsExceptionPending()) {
       if (!InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat>(
diff --git a/runtime/interpreter/mterp/README.txt b/runtime/interpreter/mterp/README.txt
index 54bb634..c550911 100644
--- a/runtime/interpreter/mterp/README.txt
+++ b/runtime/interpreter/mterp/README.txt
@@ -78,4 +78,4 @@
 to altHandlerTable.  Note that this change is not immediate.  What is actually
 changed is the value of curHandlerTable - which is part of the interpBreak
 structure.  Rather than explicitly check for changes, each thread will
-blindly refresh rIBASE at backward branches, exception throws and returns.
+unconditionally refresh rIBASE at backward branches, exception throws and returns.
diff --git a/runtime/interpreter/mterp/arm/control_flow.S b/runtime/interpreter/mterp/arm/control_flow.S
index 2299ef9..2b4cf20 100644
--- a/runtime/interpreter/mterp/arm/control_flow.S
+++ b/runtime/interpreter/mterp/arm/control_flow.S
@@ -167,15 +167,6 @@
     mov    r1, #0
     b      MterpReturn
 
-%def op_return_void_no_barrier():
-    ldr     lr, [rSELF, #THREAD_FLAGS_OFFSET]
-    mov     r0, rSELF
-    ands    lr, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
-    blne    MterpSuspendCheck                       @ (self)
-    mov    r0, #0
-    mov    r1, #0
-    b      MterpReturn
-
 %def op_return_wide():
     /*
      * Return a 64-bit value.
diff --git a/runtime/interpreter/mterp/arm/invoke.S b/runtime/interpreter/mterp/arm/invoke.S
index 08fd1bb..376c93b 100644
--- a/runtime/interpreter/mterp/arm/invoke.S
+++ b/runtime/interpreter/mterp/arm/invoke.S
@@ -111,11 +111,5 @@
     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
 
-%def op_invoke_virtual_quick():
-%  invoke(helper="MterpInvokeVirtualQuick")
-
 %def op_invoke_virtual_range():
 %  invoke(helper="MterpInvokeVirtualRange")
-
-%def op_invoke_virtual_range_quick():
-%  invoke(helper="MterpInvokeVirtualQuickRange")
diff --git a/runtime/interpreter/mterp/arm/main.S b/runtime/interpreter/mterp/arm/main.S
index 12b3dab..13ea84a 100644
--- a/runtime/interpreter/mterp/arm/main.S
+++ b/runtime/interpreter/mterp/arm/main.S
@@ -447,7 +447,6 @@
 /* Transfer stub to alternate interpreter */
     b    MterpFallback
 
-
 %def helpers():
     ENTRY MterpHelpers
 
@@ -765,6 +764,9 @@
 artMterpAsmInstructionStart = .L_op_nop
     .text
 
+%def default_helper_prefix():
+%  return "mterp_"
+
 %def opcode_start():
     ENTRY mterp_${opcode}
 %def opcode_end():
diff --git a/runtime/interpreter/mterp/arm/object.S b/runtime/interpreter/mterp/arm/object.S
index a044d91..8414a1f 100644
--- a/runtime/interpreter/mterp/arm/object.S
+++ b/runtime/interpreter/mterp/arm/object.S
@@ -87,82 +87,21 @@
 %def op_iget_boolean():
 %  op_iget(load="ldrb", helper="MterpIGetU8")
 
-%def op_iget_boolean_quick():
-%  op_iget_quick(load="ldrb")
-
 %def op_iget_byte():
 %  op_iget(load="ldrsb", helper="MterpIGetI8")
 
-%def op_iget_byte_quick():
-%  op_iget_quick(load="ldrsb")
-
 %def op_iget_char():
 %  op_iget(load="ldrh", helper="MterpIGetU16")
 
-%def op_iget_char_quick():
-%  op_iget_quick(load="ldrh")
-
 %def op_iget_object():
 %  op_iget(is_object=True, helper="MterpIGetObj")
 
-%def op_iget_object_quick():
-    /* For: iget-object-quick */
-    /* op vA, vB, offset@CCCC */
-    mov     r2, rINST, lsr #12          @ r2<- B
-    FETCH r1, 1                         @ r1<- field byte offset
-    EXPORT_PC
-    GET_VREG r0, r2                     @ r0<- object we're operating on
-    bl      artIGetObjectFromMterp      @ (obj, offset)
-    ldr     r3, [rSELF, #THREAD_EXCEPTION_OFFSET]
-    ubfx    r2, rINST, #8, #4           @ r2<- A
-    PREFETCH_INST 2
-    cmp     r3, #0
-    bne     MterpPossibleException      @ bail out
-    SET_VREG_OBJECT r0, r2              @ fp[A]<- r0
-    ADVANCE 2                           @ advance rPC
-    GET_INST_OPCODE ip                  @ extract opcode from rINST
-    GOTO_OPCODE ip                      @ jump to next instruction
-
-%def op_iget_quick(load="ldr"):
-    /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
-    /* op vA, vB, offset@CCCC */
-    mov     r2, rINST, lsr #12          @ r2<- B
-    FETCH r1, 1                         @ r1<- field byte offset
-    GET_VREG r3, r2                     @ r3<- object we're operating on
-    ubfx    r2, rINST, #8, #4           @ r2<- A
-    cmp     r3, #0                      @ check object for null
-    beq     common_errNullObject        @ object was null
-    $load   r0, [r3, r1]                @ r0<- obj.field
-    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
-    SET_VREG r0, r2                     @ fp[A]<- r0
-    GET_INST_OPCODE ip                  @ extract opcode from rINST
-    GOTO_OPCODE ip                      @ jump to next instruction
-
 %def op_iget_short():
 %  op_iget(load="ldrsh", helper="MterpIGetI16")
 
-%def op_iget_short_quick():
-%  op_iget_quick(load="ldrsh")
-
 %def op_iget_wide():
 %  op_iget(is_wide=True, helper="MterpIGetU64")
 
-%def op_iget_wide_quick():
-    /* iget-wide-quick vA, vB, offset@CCCC */
-    mov     r2, rINST, lsr #12          @ r2<- B
-    FETCH ip, 1                         @ ip<- field byte offset
-    GET_VREG r3, r2                     @ r3<- object we're operating on
-    ubfx    r2, rINST, #8, #4           @ r2<- A
-    cmp     r3, #0                      @ check object for null
-    beq     common_errNullObject        @ object was null
-    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
-    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
-    VREG_INDEX_TO_ADDR r3, r2           @ r3<- &fp[A]
-    CLEAR_SHADOW_PAIR r2, ip, lr        @ Zero out the shadow regs
-    GET_INST_OPCODE ip                  @ extract opcode from rINST
-    SET_VREG_WIDE_BY_ADDR r0, r1, r3    @ fp[A]<- r0/r1
-    GOTO_OPCODE ip                      @ jump to next instruction
-
 %def op_instance_of():
     /*
      * Check to see if an object reference is an instance of a class.
@@ -194,75 +133,21 @@
 %def op_iput_boolean():
 %  op_iput(helper="MterpIPutU8")
 
-%def op_iput_boolean_quick():
-%  op_iput_quick(store="strb")
-
 %def op_iput_byte():
 %  op_iput(helper="MterpIPutI8")
 
-%def op_iput_byte_quick():
-%  op_iput_quick(store="strb")
-
 %def op_iput_char():
 %  op_iput(helper="MterpIPutU16")
 
-%def op_iput_char_quick():
-%  op_iput_quick(store="strh")
-
 %def op_iput_object():
 %  op_iput(helper="MterpIPutObj")
 
-%def op_iput_object_quick():
-    EXPORT_PC
-    add     r0, rFP, #OFF_FP_SHADOWFRAME
-    mov     r1, rPC
-    mov     r2, rINST
-    bl      MterpIputObjectQuick
-    cmp     r0, #0
-    beq     MterpException
-    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
-    GET_INST_OPCODE ip                  @ extract opcode from rINST
-    GOTO_OPCODE ip                      @ jump to next instruction
-
-%def op_iput_quick(store="str"):
-    /* For: iput-quick, iput-object-quick */
-    /* op vA, vB, offset@CCCC */
-    mov     r2, rINST, lsr #12          @ r2<- B
-    FETCH r1, 1                         @ r1<- field byte offset
-    GET_VREG r3, r2                     @ r3<- fp[B], the object pointer
-    ubfx    r2, rINST, #8, #4           @ r2<- A
-    cmp     r3, #0                      @ check object for null
-    beq     common_errNullObject        @ object was null
-    GET_VREG r0, r2                     @ r0<- fp[A]
-    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
-    $store     r0, [r3, r1]             @ obj.field<- r0
-    GET_INST_OPCODE ip                  @ extract opcode from rINST
-    GOTO_OPCODE ip                      @ jump to next instruction
-
 %def op_iput_short():
 %  op_iput(helper="MterpIPutI16")
 
-%def op_iput_short_quick():
-%  op_iput_quick(store="strh")
-
 %def op_iput_wide():
 %  op_iput(helper="MterpIPutU64")
 
-%def op_iput_wide_quick():
-    /* iput-wide-quick vA, vB, offset@CCCC */
-    mov     r2, rINST, lsr #12          @ r2<- B
-    FETCH r3, 1                         @ r3<- field byte offset
-    GET_VREG r2, r2                     @ r2<- fp[B], the object pointer
-    ubfx    r0, rINST, #8, #4           @ r0<- A
-    cmp     r2, #0                      @ check object for null
-    beq     common_errNullObject        @ object was null
-    VREG_INDEX_TO_ADDR r0, r0           @ r0<- &fp[A]
-    GET_VREG_WIDE_BY_ADDR r0, r1, r0    @ r0/r1<- fp[A]/fp[A+1]
-    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
-    strd    r0, [r2, r3]                @ obj.field<- r0/r1
-    GET_INST_OPCODE ip                  @ extract opcode from rINST
-    GOTO_OPCODE ip                      @ jump to next instruction
-
 %def op_new_instance():
     /*
      * Create a new instance of a class.
diff --git a/runtime/interpreter/mterp/arm/other.S b/runtime/interpreter/mterp/arm/other.S
index 31b9354..20f1acf 100644
--- a/runtime/interpreter/mterp/arm/other.S
+++ b/runtime/interpreter/mterp/arm/other.S
@@ -357,6 +357,54 @@
 %def op_unused_7a():
 %  unused()
 
+%def op_unused_e3():
+%  unused()
+
+%def op_unused_e4():
+%  unused()
+
+%def op_unused_e5():
+%  unused()
+
+%def op_unused_e6():
+%  unused()
+
+%def op_unused_e7():
+%  unused()
+
+%def op_unused_e8():
+%  unused()
+
+%def op_unused_e9():
+%  unused()
+
+%def op_unused_ea():
+%  unused()
+
+%def op_unused_eb():
+%  unused()
+
+%def op_unused_ec():
+%  unused()
+
+%def op_unused_ed():
+%  unused()
+
+%def op_unused_ee():
+%  unused()
+
+%def op_unused_ef():
+%  unused()
+
+%def op_unused_f0():
+%  unused()
+
+%def op_unused_f1():
+%  unused()
+
+%def op_unused_f2():
+%  unused()
+
 %def op_unused_f3():
 %  unused()
 
diff --git a/runtime/interpreter/mterp/arm64/control_flow.S b/runtime/interpreter/mterp/arm64/control_flow.S
index b634c98..25313d3 100644
--- a/runtime/interpreter/mterp/arm64/control_flow.S
+++ b/runtime/interpreter/mterp/arm64/control_flow.S
@@ -175,18 +175,6 @@
     bl      MterpSuspendCheck           // (self)
     b       .L${opcode}_return
 
-%def op_return_void_no_barrier():
-    ldr     w7, [xSELF, #THREAD_FLAGS_OFFSET]
-    mov     x0, xSELF
-    ands    w7, w7, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
-    b.ne    .L${opcode}_check
-.L${opcode}_return:
-    mov     x0, #0
-    b       MterpReturn
-.L${opcode}_check:
-    bl      MterpSuspendCheck           // (self)
-    b       .L${opcode}_return
-
 %def op_return_wide():
     /*
      * Return a 64-bit value.
diff --git a/runtime/interpreter/mterp/arm64/invoke.S b/runtime/interpreter/mterp/arm64/invoke.S
index 4844213..4d75af6 100644
--- a/runtime/interpreter/mterp/arm64/invoke.S
+++ b/runtime/interpreter/mterp/arm64/invoke.S
@@ -100,11 +100,5 @@
     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
 
-%def op_invoke_virtual_quick():
-%  invoke(helper="MterpInvokeVirtualQuick")
-
 %def op_invoke_virtual_range():
 %  invoke(helper="MterpInvokeVirtualRange")
-
-%def op_invoke_virtual_range_quick():
-%  invoke(helper="MterpInvokeVirtualQuickRange")
diff --git a/runtime/interpreter/mterp/arm64/main.S b/runtime/interpreter/mterp/arm64/main.S
index fd745f1..18ae66a 100644
--- a/runtime/interpreter/mterp/arm64/main.S
+++ b/runtime/interpreter/mterp/arm64/main.S
@@ -464,7 +464,6 @@
 /* Transfer stub to alternate interpreter */
     b    MterpFallback
 
-
 %def helpers():
     ENTRY MterpHelpers
 /*
@@ -787,6 +786,9 @@
 artMterpAsmInstructionStart = .L_op_nop
     .text
 
+%def default_helper_prefix():
+%  return "mterp_"
+
 %def opcode_start():
     ENTRY mterp_${opcode}
 %def opcode_end():
diff --git a/runtime/interpreter/mterp/arm64/object.S b/runtime/interpreter/mterp/arm64/object.S
index 3cc688e..fb1dac9 100644
--- a/runtime/interpreter/mterp/arm64/object.S
+++ b/runtime/interpreter/mterp/arm64/object.S
@@ -83,78 +83,21 @@
 %def op_iget_boolean():
 %  op_iget(load="ldrb", helper="MterpIGetU8")
 
-%def op_iget_boolean_quick():
-%  op_iget_quick(load="ldrb")
-
 %def op_iget_byte():
 %  op_iget(load="ldrsb", helper="MterpIGetI8")
 
-%def op_iget_byte_quick():
-%  op_iget_quick(load="ldrsb")
-
 %def op_iget_char():
 %  op_iget(load="ldrh", helper="MterpIGetU16")
 
-%def op_iget_char_quick():
-%  op_iget_quick(load="ldrh")
-
 %def op_iget_object():
 %  op_iget(is_object=True, helper="MterpIGetObj")
 
-%def op_iget_object_quick():
-    /* For: iget-object-quick */
-    /* op vA, vB, offset//CCCC */
-    lsr     w2, wINST, #12              // w2<- B
-    FETCH w1, 1                         // w1<- field byte offset
-    EXPORT_PC
-    GET_VREG w0, w2                     // w0<- object we're operating on
-    bl      artIGetObjectFromMterp      // (obj, offset)
-    ldr     x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
-    ubfx    w2, wINST, #8, #4           // w2<- A
-    PREFETCH_INST 2
-    cbnz    w3, MterpPossibleException      // bail out
-    SET_VREG_OBJECT w0, w2              // fp[A]<- w0
-    ADVANCE 2                           // advance rPC
-    GET_INST_OPCODE ip                  // extract opcode from wINST
-    GOTO_OPCODE ip                      // jump to next instruction
-
-%def op_iget_quick(load="ldr", extend=""):
-    /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
-    /* op vA, vB, offset//CCCC */
-    lsr     w2, wINST, #12              // w2<- B
-    FETCH w1, 1                         // w1<- field byte offset
-    GET_VREG w3, w2                     // w3<- object we're operating on
-    ubfx    w2, wINST, #8, #4           // w2<- A
-    cbz     w3, common_errNullObject    // object was null
-    $load   w0, [x3, x1]                // w0<- obj.field
-    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
-    $extend
-    SET_VREG w0, w2                     // fp[A]<- w0
-    GET_INST_OPCODE ip                  // extract opcode from rINST
-    GOTO_OPCODE ip                      // jump to next instruction
-
 %def op_iget_short():
 %  op_iget(load="ldrsh", helper="MterpIGetI16")
 
-%def op_iget_short_quick():
-%  op_iget_quick(load="ldrsh")
-
 %def op_iget_wide():
 %  op_iget(is_wide=True, helper="MterpIGetU64")
 
-%def op_iget_wide_quick():
-    /* iget-wide-quick vA, vB, offset//CCCC */
-    lsr     w2, wINST, #12              // w2<- B
-    FETCH w4, 1                         // w4<- field byte offset
-    GET_VREG w3, w2                     // w3<- object we're operating on
-    ubfx    w2, wINST, #8, #4           // w2<- A
-    cbz     w3, common_errNullObject    // object was null
-    ldr     x0, [x3, x4]                // x0<- obj.field
-    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
-    SET_VREG_WIDE x0, w2
-    GET_INST_OPCODE ip                  // extract opcode from wINST
-    GOTO_OPCODE ip                      // jump to next instruction
-
 %def op_instance_of():
     /*
      * Check to see if an object reference is an instance of a class.
@@ -185,71 +128,21 @@
 %def op_iput_boolean():
 %  op_iput(helper="MterpIPutU8")
 
-%def op_iput_boolean_quick():
-%  op_iput_quick(store="strb")
-
 %def op_iput_byte():
 %  op_iput(helper="MterpIPutI8")
 
-%def op_iput_byte_quick():
-%  op_iput_quick(store="strb")
-
 %def op_iput_char():
 %  op_iput(helper="MterpIPutU16")
 
-%def op_iput_char_quick():
-%  op_iput_quick(store="strh")
-
 %def op_iput_object():
 %  op_iput(helper="MterpIPutObj")
 
-%def op_iput_object_quick():
-    EXPORT_PC
-    add     x0, xFP, #OFF_FP_SHADOWFRAME
-    mov     x1, xPC
-    mov     w2, wINST
-    bl      MterpIputObjectQuick
-    cbz     w0, MterpException
-    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
-    GET_INST_OPCODE ip                  // extract opcode from rINST
-    GOTO_OPCODE ip                      // jump to next instruction
-
-%def op_iput_quick(store="str"):
-    /* For: iput-quick, iput-object-quick */
-    /* op vA, vB, offset//CCCC */
-    lsr     w2, wINST, #12              // w2<- B
-    FETCH w1, 1                         // w1<- field byte offset
-    GET_VREG w3, w2                     // w3<- fp[B], the object pointer
-    ubfx    w2, wINST, #8, #4           // w2<- A
-    cbz     w3, common_errNullObject    // object was null
-    GET_VREG w0, w2                     // w0<- fp[A]
-    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
-    $store     w0, [x3, x1]             // obj.field<- w0
-    GET_INST_OPCODE ip                  // extract opcode from rINST
-    GOTO_OPCODE ip                      // jump to next instruction
-
 %def op_iput_short():
 %  op_iput(helper="MterpIPutI16")
 
-%def op_iput_short_quick():
-%  op_iput_quick(store="strh")
-
 %def op_iput_wide():
 %  op_iput(helper="MterpIPutU64")
 
-%def op_iput_wide_quick():
-    /* iput-wide-quick vA, vB, offset//CCCC */
-    lsr     w2, wINST, #12              // w2<- B
-    FETCH w3, 1                         // w3<- field byte offset
-    GET_VREG w2, w2                     // w2<- fp[B], the object pointer
-    ubfx    w0, wINST, #8, #4           // w0<- A
-    cbz     w2, common_errNullObject    // object was null
-    GET_VREG_WIDE x0, w0                // x0<- fp[A]
-    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
-    str     x0, [x2, x3]                // obj.field<- x0
-    GET_INST_OPCODE ip                  // extract opcode from wINST
-    GOTO_OPCODE ip                      // jump to next instruction
-
 %def op_new_instance():
     /*
      * Create a new instance of a class.
diff --git a/runtime/interpreter/mterp/arm64/other.S b/runtime/interpreter/mterp/arm64/other.S
index eccd521..a8cf62e 100644
--- a/runtime/interpreter/mterp/arm64/other.S
+++ b/runtime/interpreter/mterp/arm64/other.S
@@ -331,6 +331,54 @@
 %def op_unused_7a():
 %  unused()
 
+%def op_unused_e3():
+%  unused()
+
+%def op_unused_e4():
+%  unused()
+
+%def op_unused_e5():
+%  unused()
+
+%def op_unused_e6():
+%  unused()
+
+%def op_unused_e7():
+%  unused()
+
+%def op_unused_e8():
+%  unused()
+
+%def op_unused_e9():
+%  unused()
+
+%def op_unused_ea():
+%  unused()
+
+%def op_unused_eb():
+%  unused()
+
+%def op_unused_ec():
+%  unused()
+
+%def op_unused_ed():
+%  unused()
+
+%def op_unused_ee():
+%  unused()
+
+%def op_unused_ef():
+%  unused()
+
+%def op_unused_f0():
+%  unused()
+
+%def op_unused_f1():
+%  unused()
+
+%def op_unused_f2():
+%  unused()
+
 %def op_unused_f3():
 %  unused()
 
diff --git a/runtime/interpreter/mterp/arm64ng/array.S b/runtime/interpreter/mterp/arm64ng/array.S
new file mode 100644
index 0000000..b596bfb
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64ng/array.S
@@ -0,0 +1,163 @@
+%def op_aget(load="ldr", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="0"):
+/*
+ * Array get.  vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
+ *
+ */
+    FETCH_B w2, 1, 0                    // w2<- BB
+    lsr     w9, wINST, #8               // w9<- AA
+    FETCH_B w3, 1, 1                    // w3<- CC
+    GET_VREG w0, w2                     // w0<- vBB (array object)
+    GET_VREG w1, w3                     // w1<- vCC (requested index)
+    cbz     x0, common_errNullObject    // bail if null array object.
+    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
+    add     x0, x0, w1, uxtw #$shift    // w0<- arrayObj + index*width
+    cmp     w1, w3                      // compare unsigned index, length
+    bcs     common_errArrayIndex        // index >= length, bail
+    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
+    GET_INST_OPCODE x10                 // extract opcode from wINST
+    .if $wide
+    ldr     x2, [x0, #$data_offset]     // x2<- vBB[vCC]
+    SET_VREG_WIDE x2, w9
+    GOTO_OPCODE x10                     // jump to next instruction
+    .elseif $is_object
+    $load   w2, [x0, #$data_offset]     // w2<- vBB[vCC]
+    cbnz wMR, 2f
+1:
+    SET_VREG_OBJECT w2, w9              // vAA<- w2
+    GOTO_OPCODE x10                     // jump to next instruction
+2:
+    bl art_quick_read_barrier_mark_reg02
+    b 1b
+    .else
+    $load   w2, [x0, #$data_offset]     // w2<- vBB[vCC]
+    SET_VREG w2, w9                     // vAA<- w2
+    GOTO_OPCODE x10                     // jump to next instruction
+    .endif
+
+%def op_aget_boolean():
+%  op_aget(load="ldrb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET", is_object="0")
+
+%def op_aget_byte():
+%  op_aget(load="ldrsb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET", is_object="0")
+
+%def op_aget_char():
+%  op_aget(load="ldrh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET", is_object="0")
+
+%def op_aget_object():
+%  op_aget(load="ldr", shift="2", data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET", is_object="1")
+
+%def op_aget_short():
+%  op_aget(load="ldrsh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET", is_object="0")
+
+%def op_aget_wide():
+%  op_aget(load="ldr", shift="3", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1", is_object="0")
+
+%def op_aput(store="str", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="0"):
+/*
+ * Array put.  vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
+ *
+ */
+    FETCH_B w2, 1, 0                    // w2<- BB
+    lsr     w9, wINST, #8               // w9<- AA
+    FETCH_B w3, 1, 1                    // w3<- CC
+    GET_VREG w0, w2                     // w0<- vBB (array object)
+    GET_VREG w1, w3                     // w1<- vCC (requested index)
+    cbz     w0, common_errNullObject    // bail if null
+    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
+    .if !$is_object
+    add     x0, x0, w1, uxtw #$shift    // w0<- arrayObj + index*width
+    .endif
+    cmp     w1, w3                      // compare unsigned index, length
+    bcs     common_errArrayIndex        // index >= length, bail
+    .if $is_object
+    EXPORT_PC                           // Export PC before overwriting it.
+    .endif
+    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
+    .if $wide
+    GET_VREG_WIDE x2, w9                // x2<- vAA
+    .else
+    GET_VREG w2, w9                     // w2<- vAA
+    .endif
+    .if $wide
+    $store  x2, [x0, #$data_offset]     // vBB[vCC]<- x2
+    .elseif $is_object
+    bl art_quick_aput_obj
+    .else
+    $store  w2, [x0, #$data_offset]     // vBB[vCC]<- w2
+    .endif
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_aput_boolean():
+%  op_aput(store="strb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aput_byte():
+%  op_aput(store="strb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aput_char():
+%  op_aput(store="strh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aput_short():
+%  op_aput(store="strh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aput_wide():
+%  op_aput(store="str", shift="3", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1", is_object="0")
+
+%def op_aput_object():
+%  op_aput(store="str", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="1")
+
+%def op_array_length():
+    /*
+     * Return the length of an array.
+     */
+    lsr     w1, wINST, #12              // w1<- B
+    ubfx    w2, wINST, #8, #4           // w2<- A
+    GET_VREG w0, w1                     // w0<- vB (object ref)
+    cbz     w0, common_errNullObject    // bail if null
+    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
+    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- array length
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    SET_VREG w3, w2                     // vB<- length
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_fill_array_data():
+    /* fill-array-data vAA, +BBBBBBBB */
+    EXPORT_PC
+    FETCH   w0, 1                       // x0<- 000000000000bbbb (lo)
+    FETCH_S x1, 2                       // x1<- ssssssssssssBBBB (hi)
+    lsr     w3, wINST, #8               // w3<- AA
+    orr     x0, x0, x1, lsl #16         // x0<- ssssssssBBBBbbbb
+    GET_VREG w1, w3                     // w1<- vAA (array object)
+    add     x0, xPC, x0, lsl #1         // x0<- PC + ssssssssBBBBbbbb*2 (array data off.)
+    bl      art_quick_handle_fill_data
+    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_filled_new_array(helper="nterp_filled_new_array"):
+/*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
+    EXPORT_PC
+    mov     x0, xSELF
+    ldr     x1, [sp]
+    mov     x2, xFP
+    mov     x3, xPC
+    bl      $helper
+    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_filled_new_array_range():
+%  op_filled_new_array(helper="nterp_filled_new_array_range")
+
+%def op_new_array():
+  b NterpNewArray
diff --git a/runtime/interpreter/mterp/arm64ng/control_flow.S b/runtime/interpreter/mterp/arm64ng/control_flow.S
new file mode 100644
index 0000000..f2d0559
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64ng/control_flow.S
@@ -0,0 +1,187 @@
+%def bincmp(condition=""):
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "condition"
+     * fragment that specifies the comparison to perform.
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    lsr     w1, wINST, #12              // w1<- B
+    ubfx    w0, wINST, #8, #4           // w0<- A
+    GET_VREG w3, w1                     // w3<- vB
+    GET_VREG w2, w0                     // w2<- vA
+    cmp     w2, w3                      // compare (vA, vB)
+    b.${condition} 1f
+    FETCH_ADVANCE_INST 2
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    GOTO_OPCODE ip                      // jump to next instruction
+1:
+    FETCH_S wINST, 1                    // wINST<- branch offset, in code units
+    BRANCH
+
+%def zcmp(compare="1", branch=""):
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "condition"
+     * fragment that specifies the comparison to perform.
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    lsr     w0, wINST, #8               // w0<- AA
+    GET_VREG w2, w0                     // w2<- vAA
+    .if ${compare}
+    cmp     w2, #0                      // compare (vA, 0)
+    .endif
+    ${branch} 1f
+    FETCH_ADVANCE_INST 2
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    GOTO_OPCODE ip                      // jump to next instruction
+1:
+    FETCH_S wINST, 1                    // w1<- branch offset, in code units
+    BRANCH
+
+%def op_goto():
+/*
+ * Unconditional branch, 8-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+    /* goto +AA */
+    sbfx    wINST, wINST, #8, #8           // wINST<- ssssssAA (sign-extended)
+    BRANCH
+
+%def op_goto_16():
+/*
+ * Unconditional branch, 16-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+    /* goto/16 +AAAA */
+    FETCH_S wINST, 1                    // wINST<- ssssAAAA (sign-extended)
+    BRANCH
+
+%def op_goto_32():
+/*
+ * Unconditional branch, 32-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ *
+ * Because we need the SF bit set, we'll use an adds
+ * to convert from Dalvik offset to byte offset.
+ */
+    /* goto/32 +AAAAAAAA */
+    FETCH w0, 1                         // w0<- aaaa (lo)
+    FETCH w1, 2                         // w1<- AAAA (hi)
+    orr     wINST, w0, w1, lsl #16      // wINST<- AAAAaaaa
+    BRANCH
+
+%def op_if_eq():
+%  bincmp(condition="eq")
+
+%def op_if_eqz():
+%  zcmp(compare="0", branch="cbz     w2,")
+
+%def op_if_ge():
+%  bincmp(condition="ge")
+
+%def op_if_gez():
+%  zcmp(compare="0", branch="tbz     w2, #31,")
+
+%def op_if_gt():
+%  bincmp(condition="gt")
+
+%def op_if_gtz():
+%  zcmp(branch="b.gt")
+
+%def op_if_le():
+%  bincmp(condition="le")
+
+%def op_if_lez():
+%  zcmp(branch="b.le")
+
+%def op_if_lt():
+%  bincmp(condition="lt")
+
+%def op_if_ltz():
+%  zcmp(compare="0", branch="tbnz    w2, #31,")
+
+%def op_if_ne():
+%  bincmp(condition="ne")
+
+%def op_if_nez():
+%  zcmp(compare="0", branch="cbnz    w2,")
+
+%def op_packed_switch(func="NterpDoPackedSwitch"):
+/*
+ * Handle a packed-switch or sparse-switch instruction.  In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+    /* op vAA, +BBBB */
+    FETCH   w0, 1                       // x0<- 000000000000bbbb (lo)
+    FETCH_S x1, 2                       // x1<- ssssssssssssBBBB (hi)
+    lsr     w3, wINST, #8               // w3<- AA
+    orr     x0, x0, x1, lsl #16         // x0<- ssssssssBBBBbbbb
+    GET_VREG w1, w3                     // w1<- vAA
+    add     x0, xPC, x0, lsl #1         // x0<- PC + ssssssssBBBBbbbb*2
+    bl      $func                       // w0<- code-unit branch offset
+    sxtw    xINST, w0
+    BRANCH
+
+%def op_sparse_switch():
+%  op_packed_switch(func="NterpDoSparseSwitch")
+
+/*
+ * Return a 32-bit value.
+ */
+%def op_return(is_object="0", is_void="0", is_wide="0"):
+    .if $is_void
+      // Thread fence for constructor
+      dmb ishst
+    .else
+      lsr     w2, wINST, #8               // w2<- AA
+      .if $is_wide
+        GET_VREG_WIDE x0, w2                // x0<- vAA
+        // In case we're going back to compiled code, put the
+        // result also in d0
+        fmov d0, x0
+      .else
+        GET_VREG w0, w2                     // r0<- vAA
+        .if !$is_object
+        // In case we're going back to compiled code, put the
+        // result also in s0.
+        fmov s0, w0
+        .endif
+      .endif
+    .endif
+    .cfi_remember_state
+    ldr ip, [xREFS, #-8]
+    mov sp, ip
+    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
+    RESTORE_ALL_CALLEE_SAVES
+    ret
+    .cfi_restore_state
+
+%def op_return_object():
+%  op_return(is_object="1", is_void="0", is_wide="0")
+
+%def op_return_void():
+%  op_return(is_object="0", is_void="1", is_wide="0")
+
+%def op_return_wide():
+%  op_return(is_object="0", is_void="0", is_wide="1")
+
+%def op_throw():
+  EXPORT_PC
+  lsr      w2, wINST, #8               // r2<- AA
+  GET_VREG w0, w2                      // r0<- vAA (exception object)
+  mov x1, xSELF
+  bl art_quick_deliver_exception
+  brk 0
diff --git a/runtime/interpreter/mterp/arm64ng/invoke.S b/runtime/interpreter/mterp/arm64ng/invoke.S
new file mode 100644
index 0000000..39f2ea0
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64ng/invoke.S
@@ -0,0 +1,173 @@
+%def op_invoke_custom():
+   EXPORT_PC
+   FETCH w0, 1 // call_site index, first argument of runtime call.
+   b NterpCommonInvokeCustom
+
+%def op_invoke_custom_range():
+   EXPORT_PC
+   FETCH w0, 1 // call_site index, first argument of runtime call.
+   b NterpCommonInvokeCustomRange
+
+%def invoke_direct_or_super(helper="", range="", is_super=""):
+   EXPORT_PC
+   // Fast-path which gets the method from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x0, 2f
+1:
+   // Load the first argument (the 'this' pointer).
+   FETCH w1, 2
+   .if !$range
+   and w1, w1, #0xf
+   .endif
+   GET_VREG w1, w1
+   cbz w1, common_errNullObject    // bail if null
+   b $helper
+2:
+   mov x0, xSELF
+   ldr x1, [sp]
+   mov x2, xPC
+   bl nterp_get_method
+   .if $is_super
+   b 1b
+   .else
+   tbz x0, #0, 1b
+   and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method.
+   .if $range
+   b NterpHandleStringInitRange
+   .else
+   b NterpHandleStringInit
+   .endif
+   .endif
+
+%def op_invoke_direct():
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="0")
+
+%def op_invoke_direct_range():
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="0")
+
+%def op_invoke_super():
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1")
+
+%def op_invoke_super_range():
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1")
+
+%def op_invoke_polymorphic():
+   EXPORT_PC
+   // No need to fetch the target method.
+   // Load the first argument (the 'this' pointer).
+   FETCH w1, 2
+   and w1, w1, #0xf
+   GET_VREG w1, w1
+   cbz w1, common_errNullObject    // bail if null
+   b NterpCommonInvokePolymorphic
+
+%def op_invoke_polymorphic_range():
+   EXPORT_PC
+   // No need to fetch the target method.
+   // Load the first argument (the 'this' pointer).
+   FETCH w1, 2
+   GET_VREG w1, w1
+   cbz w1, common_errNullObject    // bail if null
+   b NterpCommonInvokePolymorphicRange
+
+%def invoke_interface(range=""):
+   EXPORT_PC
+   // Fast-path which gets the method from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x26, 5f
+1:
+   // First argument is the 'this' pointer.
+   FETCH w1, 2
+   .if !$range
+   and w1, w1, #0xf
+   .endif
+   GET_VREG w1, w1
+   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
+   ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
+   // Test the first two bits of the fetched ArtMethod:
+   // - If the first bit is set, this is a method on j.l.Object
+   // - If the second bit is set, this is a default method.
+   tst w26, #0x3
+   b.ne 3f
+   ldrh w3, [x26, #ART_METHOD_IMT_INDEX_OFFSET]
+2:
+   ldr x2, [x2, #MIRROR_CLASS_IMT_PTR_OFFSET_64]
+   ldr x0, [x2, w3, uxtw #3]
+   .if $range
+   b NterpCommonInvokeInterfaceRange
+   .else
+   b NterpCommonInvokeInterface
+   .endif
+3:
+   tbnz w26, #0, 4f
+   and x26, x26, #-4
+   ldrh w3, [x26, #ART_METHOD_METHOD_INDEX_OFFSET]
+   and w3, w3, #ART_METHOD_IMT_MASK
+   b 2b
+4:
+   lsr w26, w26, #16
+   add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64
+   ldr x0, [x2, w26, uxtw #3]
+   .if $range
+   b NterpCommonInvokeInstanceRange
+   .else
+   b NterpCommonInvokeInstance
+   .endif
+5:
+   mov x0, xSELF
+   ldr x1, [sp]
+   mov x2, xPC
+   bl nterp_get_method
+   mov x26, x0
+   b 1b
+
+%def op_invoke_interface():
+%  invoke_interface(range="0")
+
+%def op_invoke_interface_range():
+%  invoke_interface(range="1")
+
+%def invoke_static(helper=""):
+   EXPORT_PC
+   // Fast-path which gets the method from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x0, 1f
+   b $helper
+1:
+   mov x0, xSELF
+   ldr x1, [sp]
+   mov x2, xPC
+   bl nterp_get_method
+   b $helper
+
+%def op_invoke_static():
+%  invoke_static(helper="NterpCommonInvokeStatic")
+
+%def op_invoke_static_range():
+%  invoke_static(helper="NterpCommonInvokeStaticRange")
+
+%def invoke_virtual(helper="", range=""):
+   EXPORT_PC
+   // Fast-path which gets the method from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x2, 2f
+1:
+   FETCH w1, 2
+   .if !$range
+   and w1, w1, #0xf
+   .endif
+   GET_VREG w1, w1
+   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
+   ldr w0, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
+   add w0, w0, #MIRROR_CLASS_VTABLE_OFFSET_64
+   ldr x0, [x0, w2, uxtw #3]
+   b $helper
+2:
+   mov x0, xSELF
+   ldr x1, [sp]
+   mov x2, xPC
+   bl nterp_get_method
+   mov x2, x0
+   b 1b
+
+%def op_invoke_virtual():
+%  invoke_virtual(helper="NterpCommonInvokeInstance", range="0")
+
+%def op_invoke_virtual_range():
+%  invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1")
diff --git a/runtime/interpreter/mterp/arm64ng/main.S b/runtime/interpreter/mterp/arm64ng/main.S
new file mode 100644
index 0000000..627bb04
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64ng/main.S
@@ -0,0 +1,1930 @@
+%def header():
+/*
+ * Copyright (C) 2020 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.
+ */
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "asm_support.h"
+#include "arch/arm64/asm_support_arm64.S"
+
+/**
+ * ARM64 Runtime register usage conventions.
+ *
+ *   r0     : w0 is 32-bit return register and x0 is 64-bit.
+ *   r0-r7  : Argument registers.
+ *   r8-r15 : Caller save registers (used as temporary registers).
+ *   r16-r17: Also known as ip0-ip1, respectively. Used as scratch registers by
+ *            the linker, by the trampolines and other stubs (the compiler uses
+ *            these as temporary registers).
+ *   r18    : Reserved for platform (SCS, shadow call stack)
+ *   r19    : Pointer to thread-local storage.
+ *   r20-r29: Callee save registers.
+ *   r30    : (lr) is reserved (the link register).
+ *   rsp    : (sp) is reserved (the stack pointer).
+ *   rzr    : (zr) is reserved (the zero register).
+ *
+ *   Floating-point registers
+ *   v0-v31
+ *
+ *   v0     : s0 is return register for singles (32-bit) and d0 for doubles (64-bit).
+ *            This is analogous to the C/C++ (hard-float) calling convention.
+ *   v0-v7  : Floating-point argument registers in both Dalvik and C/C++ conventions.
+ *            Also used as temporary and codegen scratch registers.
+ *
+ *   v0-v7 and v16-v31 : Caller save registers (used as temporary registers).
+ *   v8-v15 : bottom 64-bits preserved across C calls (d8-d15 are preserved).
+ *
+ *   v16-v31: Used as codegen temp/scratch.
+ *   v8-v15 : Can be used for promotion.
+ *
+ *   Must maintain 16-byte stack alignment.
+ *
+ * Nterp notes:
+ *
+ * The following registers have fixed assignments:
+ *
+ *   reg nick      purpose
+ *   x19  xSELF     self (Thread) pointer
+ *   x20  wMR       marking register
+ *   x29  xFP       interpreted frame pointer, used for accessing locals and args
+ *   x22  xPC       interpreted program counter, used for fetching instructions
+ *   x23  xINST     first 16-bit code unit of current instruction
+ *   x24  xIBASE    interpreted instruction base pointer, used for computed goto
+ *   x25  xREFS     base of object references of dex registers.
+ *   x16  ip        scratch reg
+ *   x17  ip2       scratch reg (used by macros)
+ *
+ * Macros are provided for common operations.  They MUST NOT alter unspecified registers or
+ * condition codes.
+*/
+
+/* single-purpose registers, given names for clarity */
+#define xSELF    x19
+#define CFI_DEX  22 // DWARF register number of the register holding dex-pc (xPC).
+#define CFI_TMP  0  // DWARF register number of the first argument register (r0).
+#define xPC      x22
+#define xINST    x23
+#define wINST    w23
+#define xIBASE   x24
+#define xREFS    x25
+#define CFI_REFS 25
+#define ip       x16
+#define ip2      x17
+#define wip      w16
+#define wip2     w17
+
+// To avoid putting ifdefs arond the use of wMR, make sure it's defined.
+// IsNterpSupported returns false for configurations that don't have wMR (typically CMS).
+#ifndef wMR
+#define wMR w20
+#endif
+
+// Temporary registers while setting up a frame.
+#define xNEW_FP   x26
+#define xNEW_REFS x27
+#define CFI_NEW_REFS 27
+
+// +8 for the ArtMethod of the caller.
+#define OFFSET_TO_FIRST_ARGUMENT_IN_STACK (CALLEE_SAVES_SIZE + 8)
+
+/*
+ * Fetch the next instruction from xPC into wINST.  Does not advance xPC.
+ */
+.macro FETCH_INST
+    ldrh    wINST, [xPC]
+.endm
+
+/*
+ * Fetch the next instruction from the specified offset.  Advances xPC
+ * to point to the next instruction.  "count" is in 16-bit code units.
+ *
+ * Because of the limited size of immediate constants on ARM, this is only
+ * suitable for small forward movements (i.e. don't try to implement "goto"
+ * with this).
+ *
+ * This must come AFTER anything that can throw an exception, or the
+ * exception catch may miss.  (This also implies that it must come after
+ * EXPORT_PC.)
+ */
+.macro FETCH_ADVANCE_INST count
+    ldrh    wINST, [xPC, #((\count)*2)]!
+.endm
+
+/*
+ * Similar to FETCH_ADVANCE_INST, but does not update xPC.  Used to load
+ * xINST ahead of possible exception point.  Be sure to manually advance xPC
+ * later.
+ */
+.macro PREFETCH_INST count
+    ldrh    wINST, [xPC, #((\count)*2)]
+.endm
+
+/* Advance xPC by some number of code units. */
+.macro ADVANCE count
+  add  xPC, xPC, #((\count)*2)
+.endm
+
+/*
+ * Fetch a half-word code unit from an offset past the current PC.  The
+ * "count" value is in 16-bit code units.  Does not advance xPC.
+ *
+ * The "_S" variant works the same but treats the value as signed.
+ */
+.macro FETCH reg, count
+    ldrh    \reg, [xPC, #((\count)*2)]
+.endm
+
+.macro FETCH_S reg, count
+    ldrsh   \reg, [xPC, #((\count)*2)]
+.endm
+
+/*
+ * Fetch one byte from an offset past the current PC.  Pass in the same
+ * "count" as you would for FETCH, and an additional 0/1 indicating which
+ * byte of the halfword you want (lo/hi).
+ */
+.macro FETCH_B reg, count, byte
+    ldrb     \reg, [xPC, #((\count)*2+(\byte))]
+.endm
+
+/*
+ * Put the instruction's opcode field into the specified register.
+ */
+.macro GET_INST_OPCODE reg
+    and     \reg, xINST, #255
+.endm
+
+/*
+ * Begin executing the opcode in _reg.  Clobbers reg
+ */
+
+.macro GOTO_OPCODE reg
+    add     \reg, xIBASE, \reg, lsl #${handler_size_bits}
+    br      \reg
+.endm
+
+/*
+ * Get/set the 32-bit value from a Dalvik register.
+ */
+.macro GET_VREG reg, vreg
+    ldr     \reg, [xFP, \vreg, uxtw #2]
+.endm
+.macro GET_VREG_OBJECT reg, vreg
+    ldr     \reg, [xREFS, \vreg, uxtw #2]
+.endm
+.macro SET_VREG reg, vreg
+    str     \reg, [xFP, \vreg, uxtw #2]
+    str     wzr, [xREFS, \vreg, uxtw #2]
+.endm
+.macro SET_VREG_OBJECT reg, vreg
+    str     \reg, [xFP, \vreg, uxtw #2]
+    str     \reg, [xREFS, \vreg, uxtw #2]
+.endm
+.macro SET_VREG_FLOAT reg, vreg
+    str     \reg, [xFP, \vreg, uxtw #2]
+    str     wzr, [xREFS, \vreg, uxtw #2]
+.endm
+
+/*
+ * Get/set the 64-bit value from a Dalvik register.
+ */
+.macro GET_VREG_WIDE reg, vreg
+    add     ip2, xFP, \vreg, uxtw #2
+    ldr     \reg, [ip2]
+.endm
+.macro SET_VREG_WIDE reg, vreg
+    add     ip2, xFP, \vreg, uxtw #2
+    str     \reg, [ip2]
+    add     ip2, xREFS, \vreg, uxtw #2
+    str     xzr, [ip2]
+.endm
+.macro GET_VREG_DOUBLE reg, vreg
+    add     ip2, xFP, \vreg, uxtw #2
+    ldr     \reg, [ip2]
+.endm
+.macro SET_VREG_DOUBLE reg, vreg
+    add     ip2, xFP, \vreg, uxtw #2
+    str     \reg, [ip2]
+    add     ip2, xREFS, \vreg, uxtw #2
+    str     xzr, [ip2]
+.endm
+
+/*
+ * Get the 32-bit value from a Dalvik register and sign-extend to 64-bit.
+ * Used to avoid an extra instruction in int-to-long.
+ */
+.macro GET_VREG_S reg, vreg
+    ldrsw   \reg, [xFP, \vreg, uxtw #2]
+.endm
+
+// An assembly entry that has a OatQuickMethodHeader prefix.
+.macro OAT_ENTRY name, end
+    .type \name, #function
+    .hidden \name
+    .global \name
+    .balign 16
+    // Padding of 3 * 8 bytes to get 16 bytes alignment of code entry.
+    .long 0
+    .long 0
+    .long 0
+    // OatQuickMethodHeader. Note that the top two bits must be clear.
+    .long (\end - \name)
+\name:
+.endm
+
+.macro SIZE name
+    .size \name, .-\name
+.endm
+
+.macro NAME_START name
+    .type \name, #function
+    .hidden \name  // Hide this as a global symbol, so we do not incur plt calls.
+    .global \name
+    /* Cache alignment for function entry */
+    .balign 16
+\name:
+.endm
+
+.macro NAME_END name
+  SIZE \name
+.endm
+
+// Macro for defining entrypoints into runtime. We don't need to save registers
+// (we're not holding references there), but there is no
+// kDontSave runtime method. So just use the kSaveRefsOnly runtime method.
+.macro NTERP_TRAMPOLINE name, helper
+ENTRY \name
+  SETUP_SAVE_REFS_ONLY_FRAME
+  bl \helper
+  RESTORE_SAVE_REFS_ONLY_FRAME
+  REFRESH_MARKING_REGISTER
+  RETURN_OR_DELIVER_PENDING_EXCEPTION
+END \name
+.endm
+
+.macro CLEAR_STATIC_VOLATILE_MARKER reg
+  and \reg, \reg, #-2
+.endm
+
+.macro CLEAR_INSTANCE_VOLATILE_MARKER reg
+  neg \reg, \reg
+.endm
+
+.macro EXPORT_PC
+    str    xPC, [xREFS, #-16]
+.endm
+
+.macro BRANCH
+    // Update method counter and do a suspend check if the branch is negative.
+    tbnz wINST, #31, 2f
+1:
+    add     xPC, xPC, wINST, sxtw #1    // update xPC
+    FETCH wINST, 0                      // load wINST
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    GOTO_OPCODE ip                      // jump to next instruction
+2:
+    ldr x0, [sp]
+    ldrh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
+    add x2, x2, #1
+    and w2, w2, #NTERP_HOTNESS_MASK
+    strh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
+    // If the counter overflows, handle this in the runtime.
+    cbz w2, NterpHandleHotnessOverflow
+    // Otherwise, do a suspend check.
+    ldr x0, [xSELF, #THREAD_FLAGS_OFFSET]
+    ands x0, x0, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
+    b.eq 1b
+    EXPORT_PC
+    bl    art_quick_test_suspend
+    b 1b
+.endm
+
+// Uses x12, x13, and x14 as temporaries.
+.macro FETCH_CODE_ITEM_INFO code_item, registers, outs, ins, load_ins
+    tbz \code_item, #0, 4f
+    and \code_item, \code_item, #-2 // Remove the extra bit that marks it's a compact dex file
+    ldrh w13, [\code_item, #COMPACT_CODE_ITEM_FIELDS_OFFSET]
+    ubfx \registers, w13, #COMPACT_CODE_ITEM_REGISTERS_SIZE_SHIFT, #4
+    ubfx \outs, w13, #COMPACT_CODE_ITEM_OUTS_SIZE_SHIFT, #4
+    .if \load_ins
+    ubfx \ins, w13, #COMPACT_CODE_ITEM_INS_SIZE_SHIFT, #4
+    .else
+    ubfx w14, w13, #COMPACT_CODE_ITEM_INS_SIZE_SHIFT, #4
+    add \registers, \registers, w14
+    .endif
+    ldrh w13, [\code_item, #COMPACT_CODE_ITEM_FLAGS_OFFSET]
+    tst w13, #COMPACT_CODE_ITEM_REGISTERS_INS_OUTS_FLAGS
+    b.eq 3f
+    sub x14, \code_item, #4
+    tst w13, #COMPACT_CODE_ITEM_INSNS_FLAG
+    csel x14, x14, \code_item, ne
+
+    tbz w13, #COMPACT_CODE_ITEM_REGISTERS_BIT, 1f
+    ldrh w12, [x14, #-2]!
+    add \registers, \registers, w12
+1:
+    tbz w13, #COMPACT_CODE_ITEM_INS_BIT, 2f
+    ldrh w12, [x14, #-2]!
+    .if \load_ins
+    add \ins, \ins, w12
+    .else
+    add \registers, \registers, w12
+    .endif
+2:
+    tbz w13, #COMPACT_CODE_ITEM_OUTS_BIT, 3f
+    ldrh w12, [x14, #-2]!
+    add \outs, \outs, w12
+3:
+    .if \load_ins
+    add \registers, \registers, \ins
+    .endif
+    add \code_item, \code_item, #COMPACT_CODE_ITEM_INSNS_OFFSET
+    b 5f
+4:
+    // Fetch dex register size.
+    ldrh \registers, [\code_item, #CODE_ITEM_REGISTERS_SIZE_OFFSET]
+    // Fetch outs size.
+    ldrh \outs, [\code_item, #CODE_ITEM_OUTS_SIZE_OFFSET]
+    .if \load_ins
+    ldrh \ins, [\code_item, #CODE_ITEM_INS_SIZE_OFFSET]
+    .endif
+    add \code_item, \code_item, #CODE_ITEM_INSNS_OFFSET
+5:
+.endm
+
+// Setup the stack to start executing the method. Expects:
+// - x0 to contain the ArtMethod
+//
+// Outputs
+// - ip contains the dex registers size
+// - x28 contains the old stack pointer.
+// - \code_item is replaced with a pointer to the instructions
+// - if load_ins is 1, w15 contains the ins
+//
+// Uses ip, ip2, x12, x13, x14 as temporaries.
+.macro SETUP_STACK_FRAME code_item, refs, fp, cfi_refs, load_ins
+    FETCH_CODE_ITEM_INFO \code_item, wip, wip2, w15, \load_ins
+
+    // Compute required frame size: ((2 * ip) + ip2) * 4 + 24
+    // 24 is for saving the previous frame, pc, and method being executed.
+    add x14, ip, ip
+    add x14, x14, ip2
+    lsl x14, x14, #2
+    add x14, x14, #24
+
+    // Compute new stack pointer in x14
+    sub x14, sp, x14
+    // Alignment
+    and x14, x14, #-16
+
+    // Set reference and dex registers, align to pointer size for previous frame and dex pc.
+    add \refs, x14, ip2, lsl #2
+    add \refs, \refs, 28
+    and \refs, \refs, #(-__SIZEOF_POINTER__)
+    add \fp, \refs, ip, lsl #2
+
+    // Now setup the stack pointer.
+    mov x28, sp
+    .cfi_def_cfa_register x28
+    mov sp, x14
+    str x28, [\refs, #-8]
+    CFI_DEF_CFA_BREG_PLUS_UCONST \cfi_refs, -8, CALLEE_SAVES_SIZE
+
+    // Put nulls in reference frame.
+    cbz ip, 2f
+    mov ip2, \refs
+1:
+    str xzr, [ip2], #8  // May clear vreg[0].
+    cmp ip2, \fp
+    b.lo 1b
+2:
+    // Save the ArtMethod.
+    str x0, [sp]
+.endm
+
+// Increase method hotness and do suspend check before starting executing the method.
+.macro START_EXECUTING_INSTRUCTIONS
+    ldr x0, [sp]
+    ldrh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
+    add x2, x2, #1
+    and w2, w2, #NTERP_HOTNESS_MASK
+    strh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
+    // If the counter overflows, handle this in the runtime.
+    cbz w2, 2f
+    ldr x0, [xSELF, #THREAD_FLAGS_OFFSET]
+    tst x0, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
+    b.ne 3f
+1:
+    FETCH_INST
+    GET_INST_OPCODE ip
+    GOTO_OPCODE ip
+2:
+    mov x1, xzr
+    mov x2, xFP
+    bl nterp_hot_method
+    b 1b
+3:
+    EXPORT_PC
+    bl art_quick_test_suspend
+    b 1b
+.endm
+
+.macro SPILL_ALL_CALLEE_SAVES
+    INCREASE_FRAME CALLEE_SAVES_SIZE
+    // Note: we technically don't need to save x19 and x20,
+    // but the runtime will expect those values to be there when unwinding
+    // (see Arm64Context::DoLongJump checking for the thread register).
+    SAVE_ALL_CALLEE_SAVES 0
+.endm
+
+.macro RESTORE_ALL_CALLEE_SAVES
+    // FP callee-saves
+    ldp d8, d9, [sp, #0]
+    ldp d10, d11, [sp, #16]
+    ldp d12, d13, [sp, #32]
+    ldp d14, d15, [sp, #48]
+
+    // GP callee-saves.
+    // No need to restore x19 (it's always the thread), and
+    // don't restore x20 (the marking register) as it may have been updated.
+    RESTORE_TWO_REGS x21, x22, 80
+    RESTORE_TWO_REGS x23, x24, 96
+    RESTORE_TWO_REGS x25, x26, 112
+    RESTORE_TWO_REGS x27, x28, 128
+    RESTORE_TWO_REGS x29, lr, 144
+
+    DECREASE_FRAME CALLEE_SAVES_SIZE
+.endm
+
+.macro SPILL_ALL_ARGUMENTS
+    stp x0, x1, [sp, #-128]!
+    stp x2, x3, [sp, #16]
+    stp x4, x5, [sp, #32]
+    stp x6, x7, [sp, #48]
+    stp d0, d1, [sp, #64]
+    stp d2, d3, [sp, #80]
+    stp d4, d5, [sp, #96]
+    stp d6, d7, [sp, #112]
+.endm
+
+.macro RESTORE_ALL_ARGUMENTS
+    ldp x2, x3, [sp, #16]
+    ldp x4, x5, [sp, #32]
+    ldp x6, x7, [sp, #48]
+    ldp d0, d1, [sp, #64]
+    ldp d2, d3, [sp, #80]
+    ldp d4, d5, [sp, #96]
+    ldp d6, d7, [sp, #112]
+    ldp x0, x1, [sp], #128
+.endm
+
+// Helper to setup the stack after doing a nterp to nterp call. This will setup:
+// - xNEW_FP: the new pointer to dex registers
+// - xNEW_REFS: the new pointer to references
+// - xPC: the new PC pointer to execute
+// - x2: value in instruction to decode the number of arguments.
+// - x3: first dex register
+// - x4: top of dex register array
+//
+// The method expects:
+// - x0 to contain the ArtMethod
+// - x8 to contain the code item
+.macro SETUP_STACK_FOR_INVOKE
+   // We do the same stack overflow check as the compiler. See CanMethodUseNterp
+   // in how we limit the maximum nterp frame size.
+   sub x16, sp, #STACK_OVERFLOW_RESERVED_BYTES
+   ldr wzr, [x16]
+
+   // Spill all callee saves to have a consistent stack frame whether we
+   // are called by compiled code or nterp.
+   SPILL_ALL_CALLEE_SAVES
+
+   // Setup the frame.
+   SETUP_STACK_FRAME x8, xNEW_REFS, xNEW_FP, CFI_NEW_REFS, load_ins=0
+   // Make x4 point to the top of the dex register array.
+   add x4, xNEW_FP, ip, uxtx #2
+
+   // Fetch instruction information before replacing xPC.
+   // TODO: move this down to the method that uses it, fetching it directly from wINST.
+   FETCH_B w2, 0, 1
+   // TODO: we could avoid this as instance invokes already fetch it.
+   FETCH w3, 2
+
+   // Set the dex pc pointer.
+   mov xPC, x8
+   CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
+.endm
+
+// Setup arguments based on a non-range nterp to nterp call, and start executing
+// the method. We expect:
+// - xNEW_FP: the new pointer to dex registers
+// - xNEW_REFS: the new pointer to references
+// - xPC: the new PC pointer to execute
+// - x2: number of arguments (bits 4-7), 5th argument if any (bits 0-3)
+// - x3: first dex register
+// - x4: top of dex register array
+// - x1: receiver if non-static.
+.macro SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
+   // /* op vA, vB, {vC...vG} */
+   asr ip2, x2, #4
+   cbz ip2, 6f
+   mov ip, #-4
+   cmp ip2, #2
+   b.lt 1f
+   b.eq 2f
+   cmp ip2, #4
+   b.lt 3f
+   b.eq 4f
+
+  // We use a decrementing ip to store references relative
+  // to xNEW_FP and dex registers relative to x4
+  //
+  // TODO: We could set up ip as the number of registers (this can be an additional output from
+  // SETUP_STACK_FOR_INVOKE) and then just decrement it by one before copying each arg.
+  // Maybe even introduce macros NEW_VREG_ADDRESS/NEW_VREG_REF_ADDRESS.
+5:
+   and         x2, x2, #15
+   GET_VREG_OBJECT w5, w2
+   str         w5, [xNEW_FP, ip]
+   GET_VREG    w5, w2
+   str         w5, [x4, ip]
+   sub         ip, ip, #4
+4:
+   asr         x2, x3, #12
+   GET_VREG_OBJECT w5, w2
+   str         w5, [xNEW_FP, ip]
+   GET_VREG    w5, w2
+   str         w5, [x4, ip]
+   sub         ip, ip, #4
+3:
+   ubfx        x2, x3, #8, #4
+   GET_VREG_OBJECT w5, w2
+   str         w5, [xNEW_FP, ip]
+   GET_VREG    w5, w2
+   str         w5, [x4, ip]
+   sub         ip, ip, #4
+2:
+   ubfx        x2, x3, #4, #4
+   GET_VREG_OBJECT w5, w2
+   str         w5, [xNEW_FP, ip]
+   GET_VREG    w5, w2
+   str         w5, [x4, ip]
+   .if !\is_string_init
+   sub         ip, ip, #4
+   .endif
+1:
+   .if \is_string_init
+   // Ignore the first argument
+   .elseif \is_static
+   and         x2, x3, #0xf
+   GET_VREG_OBJECT w5, w2
+   str         w5, [xNEW_FP, ip]
+   GET_VREG    w5, w2
+   str         w5, [x4, ip]
+   .else
+   str         w1, [xNEW_FP, ip]
+   str         w1, [x4, ip]
+   .endif
+
+6:
+   // Start executing the method.
+   mov xFP, xNEW_FP
+   mov xREFS, xNEW_REFS
+   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
+   START_EXECUTING_INSTRUCTIONS
+.endm
+
+// Setup arguments based on a range nterp to nterp call, and start executing
+// the method.
+// - xNEW_FP: the new pointer to dex registers
+// - xNEW_REFS: the new pointer to references
+// - xPC: the new PC pointer to execute
+// - x2: number of arguments
+// - x3: first dex register
+// - x4: top of dex register array
+// - x1: receiver if non-static.
+//
+// Uses ip, ip2, x5, x6 as temporaries.
+.macro SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
+   mov ip, #-4
+   .if \is_string_init
+   // Ignore the first argument
+   sub x2, x2, #1
+   add x3, x3, #1
+   .elseif !\is_static
+   sub x2, x2, #1
+   add x3, x3, #1
+   .endif
+
+   cbz x2, 2f
+   add ip2, xREFS, x3, lsl #2  // pointer to first argument in reference array
+   add ip2, ip2, x2, lsl #2    // pointer to last argument in reference array
+   add x5, xFP, x3, lsl #2     // pointer to first argument in register array
+   add x6, x5, x2, lsl #2      // pointer to last argument in register array
+1:
+   ldr  w7, [ip2, #-4]!
+   str  w7, [xNEW_FP, ip]
+   sub  x2, x2, 1
+   ldr  w7, [x6, #-4]!
+   str  w7, [x4, ip]
+   sub ip, ip, 4
+   cbnz x2, 1b
+2:
+   .if \is_string_init
+   // Ignore first argument
+   .elseif !\is_static
+   str w1, [xNEW_FP, ip]
+   str w1, [x4, ip]
+   .endif
+   mov xFP, xNEW_FP
+   mov xREFS, xNEW_REFS
+   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
+   START_EXECUTING_INSTRUCTIONS
+.endm
+
+.macro GET_SHORTY dest, is_interface, is_polymorphic, is_custom
+   stp x0, x1, [sp, #-16]!
+   .if \is_polymorphic
+   ldr x0, [sp, #16]
+   mov x1, xPC
+   bl NterpGetShortyFromInvokePolymorphic
+   .elseif \is_custom
+   ldr x0, [sp, #16]
+   mov x1, xPC
+   bl NterpGetShortyFromInvokeCustom
+   .elseif \is_interface
+   ldr x0, [sp, #16]
+   FETCH w1, 1
+   bl NterpGetShortyFromMethodId
+   .else
+   bl NterpGetShorty
+   .endif
+   mov \dest, x0
+   ldp x0, x1, [sp], #16
+.endm
+
+.macro GET_SHORTY_SLOW_PATH dest, is_interface
+   // Save all registers that can hold arguments in the fast path.
+   stp x0, x1, [sp, #-32]!
+   str w2, [sp, #16]
+   str s0, [sp, #20]
+   .if \is_interface
+   ldr x0, [sp, #32]
+   FETCH w1, 1
+   bl NterpGetShortyFromMethodId
+   .else
+   bl NterpGetShorty
+   .endif
+   mov \dest, x0
+   ldr w2, [sp, #16]
+   ldr s0, [sp, #20]
+   ldp x0, x1, [sp], #32
+.endm
+
+// Input:  x0 contains the ArtMethod
+// Output: x8 contains the code item
+.macro GET_CODE_ITEM
+   ldr x8, [x0, #ART_METHOD_DATA_OFFSET_64]
+.endm
+
+.macro DO_ENTRY_POINT_CHECK call_compiled_code
+   // On entry, the method is x0, the instance is x1
+   adr x2, ExecuteNterpImpl
+   ldr x3, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
+   cmp x2, x3
+   b.ne  \call_compiled_code
+.endm
+
+.macro UPDATE_REGISTERS_FOR_STRING_INIT old_value, new_value
+   mov wip, wzr
+1:
+   GET_VREG_OBJECT wip2, wip
+   cmp wip2, \old_value
+   b.ne 2f
+   SET_VREG_OBJECT \new_value, wip
+2:
+   add wip, wip, #1
+   add ip2, xREFS, wip, uxtw #2
+   cmp ip2, xFP
+   b.ne 1b
+.endm
+
+// Puts the next floating point argument into the expected register,
+// fetching values based on a non-range invoke.
+// Uses ip and ip2.
+.macro LOOP_OVER_SHORTY_LOADING_FPS dreg, sreg, inst, shorty, arg_index, finished
+1: // LOOP
+    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
+    cbz wip, \finished              // if (wip == '\0') goto finished
+    cmp wip, #68                    // if (wip == 'D') goto FOUND_DOUBLE
+    b.eq 2f
+    cmp wip, #70                    // if (wip == 'F') goto FOUND_FLOAT
+    b.eq 3f
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    //  Handle extra argument in arg array taken by a long.
+    cmp wip, #74                   // if (wip != 'J') goto LOOP
+    b.ne 1b
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 1b                        // goto LOOP
+2:  // FOUND_DOUBLE
+    and ip, \inst, #0xf
+    GET_VREG wip, wip
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    cmp \arg_index, #4
+    b.eq 5f
+    and ip2, \inst, #0xf
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 6f
+5:
+    // TODO: Extract from wINST here and below? (Requires using a different register
+    // in the COMMON_INVOKE_NON_RANGE.)
+    FETCH_B wip2, 0, 1
+    and wip2, wip2, #0xf
+6:
+    GET_VREG wip2, wip2
+    add ip, ip, ip2, lsl #32
+    fmov \dreg, ip
+    b 4f
+3:  // FOUND_FLOAT
+    cmp \arg_index, #4
+    b.eq 7f
+    and ip, \inst, #0xf
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 8f
+7:
+    FETCH_B wip, 0, 1
+    and wip, wip, #0xf
+8:
+    GET_VREG \sreg, wip
+4:
+.endm
+
+// Puts the next int/long/object argument in the expected register,
+// fetching values based on a non-range invoke.
+// Uses ip and ip2.
+.macro LOOP_OVER_SHORTY_LOADING_GPRS gpr_reg64, gpr_reg32, inst, shorty, arg_index, finished
+1: // LOOP
+    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
+    cbz wip, \finished              // if (wip == '\0') goto finished
+    cmp wip, #74                    // if (wip == 'J') goto FOUND_LONG
+    b.eq 2f
+    cmp wip, #70                    // if (wip == 'F') goto SKIP_FLOAT
+    b.eq 3f
+    cmp wip, #68                    // if (wip == 'D') goto SKIP_DOUBLE
+    b.eq 4f
+    cmp \arg_index, #4
+    b.eq 7f
+    and ip, \inst, #0xf
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 8f
+7:
+    FETCH_B wip, 0, 1
+    and wip, wip, #0xf
+8:
+    GET_VREG \gpr_reg32, wip
+    b 5f
+2:  // FOUND_LONG
+    and ip, \inst, #0xf
+    GET_VREG wip, wip
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    cmp \arg_index, #4
+    b.eq 9f
+    and ip2, \inst, #0xf
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 10f
+9:
+    FETCH_B wip2, 0, 1
+    and wip2, wip2, #0xf
+10:
+    GET_VREG wip2, wip2
+    add \gpr_reg64, ip, ip2, lsl #32
+    b 5f
+3:  // SKIP_FLOAT
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 1b
+4:  // SKIP_DOUBLE
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    cmp \arg_index, #4
+    b.eq 1b
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 1b
+5:
+.endm
+
+.macro SETUP_RETURN_VALUE shorty
+   ldrb wip, [\shorty]
+   cmp ip, #68       // Test if result type char == 'D'.
+   b.eq 1f
+   cmp ip, #70       // Test if result type char == 'F'.
+   b.ne 2f
+   fmov w0, s0
+   b 2f
+1:
+   fmov x0, d0
+2:
+.endm
+
+.macro COMMON_INVOKE_NON_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0
+   .if \is_polymorphic
+   // We always go to compiled code for polymorphic calls.
+   .elseif \is_custom
+   // We always go to compiled code for custom calls.
+   .else
+     DO_ENTRY_POINT_CHECK .Lcall_compiled_code_\suffix
+     GET_CODE_ITEM
+     .if \is_string_init
+     bl nterp_to_nterp_string_init_non_range
+     .elseif \is_static
+     bl nterp_to_nterp_static_non_range
+     .else
+     bl nterp_to_nterp_instance_non_range
+     .endif
+     b .Ldone_return_\suffix
+   .endif
+
+.Lcall_compiled_code_\suffix:
+   .if \is_polymorphic
+   // No fast path for polymorphic calls.
+   .elseif \is_custom
+   // No fast path for custom calls.
+   .elseif \is_string_init
+   // No fast path for string.init.
+   .else
+     ldr wip, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
+     tbz wip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG_BIT, .Lfast_path_with_few_args_\suffix
+     FETCH_B wip2, 0, 1
+     asr ip, ip2, #4
+     .if \is_static
+     cbz ip, .Linvoke_fast_path_\suffix
+     .else
+     cmp ip, #1
+     b.eq .Linvoke_fast_path_\suffix
+     .endif
+     FETCH w8, 2
+     cmp ip, #2
+     .if \is_static
+     b.lt .Lone_arg_fast_path_\suffix
+     .endif
+     b.eq .Ltwo_args_fast_path_\suffix
+     cmp ip, #4
+     b.lt .Lthree_args_fast_path_\suffix
+     b.eq .Lfour_args_fast_path_\suffix
+
+     and         ip, ip2, #15
+     GET_VREG    w5, wip
+.Lfour_args_fast_path_\suffix:
+     asr         ip, x8, #12
+     GET_VREG    w4, wip
+.Lthree_args_fast_path_\suffix:
+     ubfx        ip, x8, #8, #4
+     GET_VREG    w3, wip
+.Ltwo_args_fast_path_\suffix:
+     ubfx        ip, x8, #4, #4
+     GET_VREG    w2, wip
+.Lone_arg_fast_path_\suffix:
+     .if \is_static
+     and         ip, x8, #0xf
+     GET_VREG    w1, wip
+     .else
+     // First argument already in w1.
+     .endif
+.Linvoke_fast_path_\suffix:
+     .if \is_interface
+     // Setup hidden argument.
+     mov ip2, x26
+     .endif
+     ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
+     blr lr
+     FETCH_ADVANCE_INST 3
+     GET_INST_OPCODE ip
+     GOTO_OPCODE ip
+
+.Lfast_path_with_few_args_\suffix:
+     // Fast path when we have zero or one argument (modulo 'this'). If there
+     // is one argument, we can put it in both floating point and core register.
+     FETCH_B w2, 0, 1
+     .if \is_static
+     cmp w2, #(2 << 4)
+     .else
+     cmp w2, #(3 << 4)
+     .endif
+     b.ge .Lget_shorty_\suffix
+     .if \is_static
+     tbz w2, #4, .Linvoke_with_few_args_\suffix
+     .else
+     tbnz w2, #4, .Linvoke_with_few_args_\suffix
+     .endif
+     FETCH w2, 2
+     .if \is_static
+     and w2, w2, #0xf  // dex register of first argument
+     GET_VREG w1, w2
+     fmov s0, w1
+     .else
+     ubfx x2, x2, #4, #4  // dex register of second argument
+     GET_VREG w2, w2
+     fmov s0, w2
+     .endif
+.Linvoke_with_few_args_\suffix:
+     // Check if the next instruction is move-result or move-result-wide.
+     // If it is, we fetch the shorty and jump to the regular invocation.
+     FETCH w27, 3
+     and ip, x27, #0xfe
+     cmp ip, #0x0a
+     b.eq .Lget_shorty_and_invoke_\suffix
+     .if \is_interface
+     // Setup hidden argument.
+     mov ip2, x26
+     .endif
+     ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
+     blr lr
+     # TODO: Use some other register for shorty and prefetch the instruction directly to wINST.
+     mov xINST, x27
+     ADVANCE 3
+     GET_INST_OPCODE ip
+     GOTO_OPCODE ip
+.Lget_shorty_and_invoke_\suffix:
+     GET_SHORTY_SLOW_PATH xINST, \is_interface
+     b .Lgpr_setup_finished_\suffix
+   .endif
+
+.Lget_shorty_\suffix:
+   GET_SHORTY xINST, \is_interface, \is_polymorphic, \is_custom
+   // From this point:
+   // - xINST contains shorty (in callee-save to switch over return value after call).
+   // - x0 contains method
+   // - x1 contains 'this' pointer for instance method.
+   // - for interface calls, x26 contains the interface method.
+   add x9, xINST, #1  // shorty + 1  ; ie skip return arg character
+   FETCH w11, 2 // arguments
+   .if \is_string_init
+   lsr x11, x11, #4
+   mov x10, #1       // ignore first argument
+   .elseif \is_static
+   mov x10, xzr      // arg_index
+   .else
+   lsr x11, x11, #4
+   mov x10, #1       // ignore first argument
+   .endif
+   LOOP_OVER_SHORTY_LOADING_FPS d0, s0, x11, x9, x10, .Lxmm_setup_finished_\suffix
+   LOOP_OVER_SHORTY_LOADING_FPS d1, s1, x11, x9, x10, .Lxmm_setup_finished_\suffix
+   LOOP_OVER_SHORTY_LOADING_FPS d2, s2, x11, x9, x10, .Lxmm_setup_finished_\suffix
+   LOOP_OVER_SHORTY_LOADING_FPS d3, s3, x11, x9, x10, .Lxmm_setup_finished_\suffix
+   LOOP_OVER_SHORTY_LOADING_FPS d4, s4, x11, x9, x10, .Lxmm_setup_finished_\suffix
+.Lxmm_setup_finished_\suffix:
+   add x9, xINST, #1  // shorty + 1  ; ie skip return arg character
+   FETCH w11, 2 // arguments
+   .if \is_string_init
+   lsr x11, x11, #4
+   mov x10, #1       // ignore first argument
+   LOOP_OVER_SHORTY_LOADING_GPRS x1, w1, x11, x9, x10, .Lgpr_setup_finished_\suffix
+   .elseif \is_static
+   mov x10, xzr      // arg_index
+   LOOP_OVER_SHORTY_LOADING_GPRS x1, w1, x11, x9, x10, .Lgpr_setup_finished_\suffix
+   .else
+   lsr x11, x11, #4
+   mov x10, #1       // ignore first argument
+   .endif
+   LOOP_OVER_SHORTY_LOADING_GPRS x2, w2, x11, x9, x10, .Lgpr_setup_finished_\suffix
+   LOOP_OVER_SHORTY_LOADING_GPRS x3, w3, x11, x9, x10, .Lgpr_setup_finished_\suffix
+   LOOP_OVER_SHORTY_LOADING_GPRS x4, w4, x11, x9, x10, .Lgpr_setup_finished_\suffix
+   LOOP_OVER_SHORTY_LOADING_GPRS x5, w5, x11, x9, x10, .Lgpr_setup_finished_\suffix
+.Lgpr_setup_finished_\suffix:
+   .if \is_polymorphic
+   bl art_quick_invoke_polymorphic
+   .elseif \is_custom
+   bl art_quick_invoke_custom
+   .else
+      .if \is_interface
+      // Setup hidden argument.
+      mov ip2, x26
+      .endif
+      ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
+      blr lr
+   .endif
+   SETUP_RETURN_VALUE xINST
+.Ldone_return_\suffix:
+   /* resume execution of caller */
+   .if \is_string_init
+   FETCH w11, 2 // arguments
+   and x11, x11, #0xf
+   GET_VREG w1, w11
+   UPDATE_REGISTERS_FOR_STRING_INIT w1, w0
+   .endif
+
+   .if \is_polymorphic
+   FETCH_ADVANCE_INST 4
+   .else
+   FETCH_ADVANCE_INST 3
+   .endif
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.endm
+
+// Puts the next floating point argument into the expected register,
+// fetching values based on a range invoke.
+// Uses ip as temporary.
+.macro LOOP_RANGE_OVER_SHORTY_LOADING_FPS dreg, sreg, shorty, arg_index, stack_index, finished
+1: // LOOP
+    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
+    cbz wip, \finished              // if (wip == '\0') goto finished
+    cmp wip, #68                    // if (wip == 'D') goto FOUND_DOUBLE
+    b.eq 2f
+    cmp wip, #70                    // if (wip == 'F') goto FOUND_FLOAT
+    b.eq 3f
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    //  Handle extra argument in arg array taken by a long.
+    cmp wip, #74                    // if (wip != 'J') goto LOOP
+    b.ne 1b
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 1b                        // goto LOOP
+2:  // FOUND_DOUBLE
+    GET_VREG_DOUBLE \dreg, \arg_index
+    add \arg_index, \arg_index, #2
+    add \stack_index, \stack_index, #2
+    b 4f
+3:  // FOUND_FLOAT
+    GET_VREG \sreg, \arg_index
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+4:
+.endm
+
+// Puts the next floating point argument into the expected stack slot,
+// fetching values based on a range invoke.
+// Uses ip as temporary.
+//
+// TODO: We could just copy all the vregs to the stack slots in a simple loop
+// without looking at the shorty at all. (We could also drop
+// the "stack_index" from the macros for loading registers.) We could also do
+// that conditionally if argument word count > 6; otherwise we know that all
+// args fit into registers.
+.macro LOOP_RANGE_OVER_FPs shorty, arg_index, stack_index, finished
+1: // LOOP
+    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
+    cbz wip, \finished              // if (wip == '\0') goto finished
+    cmp wip, #68                    // if (wip == 'D') goto FOUND_DOUBLE
+    b.eq 2f
+    cmp wip, #70                    // if (wip == 'F') goto FOUND_FLOAT
+    b.eq 3f
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    //  Handle extra argument in arg array taken by a long.
+    cmp wip, #74                    // if (wip != 'J') goto LOOP
+    b.ne 1b
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 1b                        // goto LOOP
+2:  // FOUND_DOUBLE
+    GET_VREG_WIDE ip, \arg_index
+    add ip2, sp, \stack_index, uxtw #2
+    str ip, [ip2]
+    add \arg_index, \arg_index, #2
+    add \stack_index, \stack_index, #2
+    b 1b
+3:  // FOUND_FLOAT
+    GET_VREG wip, \arg_index
+    str wip, [sp, \stack_index, uxtw #2]
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 1b
+.endm
+
+// Puts the next int/long/object argument in the expected register,
+// fetching values based on a range invoke.
+// Uses ip as temporary.
+.macro LOOP_RANGE_OVER_SHORTY_LOADING_GPRS reg64, reg32, shorty, arg_index, stack_index, finished
+1: // LOOP
+    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
+    cbz wip, \finished              // if (wip == '\0') goto finished
+    cmp wip, #74                    // if (wip == 'J') goto FOUND_LONG
+    b.eq 2f
+    cmp wip, #70                   // if (wip == 'F') goto SKIP_FLOAT
+    b.eq 3f
+    cmp wip, #68                    // if (wip == 'D') goto SKIP_DOUBLE
+    b.eq 4f
+    GET_VREG \reg32, \arg_index
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 5f
+2:  // FOUND_LONG
+    GET_VREG_WIDE \reg64, \arg_index
+    add \arg_index, \arg_index, #2
+    add \stack_index, \stack_index, #2
+    b 5f
+3:  // SKIP_FLOAT
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 1b
+4:  // SKIP_DOUBLE
+    add \arg_index, \arg_index, #2
+    add \stack_index, \stack_index, #2
+    b 1b
+5:
+.endm
+
+// Puts the next int/long/object argument in the expected stack slot,
+// fetching values based on a range invoke.
+// Uses ip as temporary.
+.macro LOOP_RANGE_OVER_INTs shorty, arg_index, stack_index, finished
+1: // LOOP
+    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
+    cbz wip, \finished              // if (wip == '\0') goto finished
+    cmp wip, #74                    // if (wip == 'J') goto FOUND_LONG
+    b.eq 2f
+    cmp wip, #70                    // if (wip == 'F') goto SKIP_FLOAT
+    b.eq 3f
+    cmp wip, #68                    // if (wip == 'D') goto SKIP_DOUBLE
+    b.eq 4f
+    GET_VREG wip, \arg_index
+    str wip, [sp, \stack_index, uxtw #2]
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 1b
+2:  // FOUND_LONG
+    GET_VREG_WIDE ip, \arg_index
+    add ip2, sp, \stack_index, uxtw #2
+    str ip, [ip2]
+    add \arg_index, \arg_index, #2
+    add \stack_index, \stack_index, #2
+    b 1b
+3:  // SKIP_FLOAT
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 1b
+4:  // SKIP_DOUBLE
+    add \arg_index, \arg_index, #2
+    add \stack_index, \stack_index, #2
+    b 1b
+.endm
+
+.macro COMMON_INVOKE_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0
+   .if \is_polymorphic
+   // We always go to compiled code for polymorphic calls.
+   .elseif \is_custom
+   // We always go to compiled code for custom calls.
+   .else
+     DO_ENTRY_POINT_CHECK .Lcall_compiled_code_range_\suffix
+     GET_CODE_ITEM
+     .if \is_string_init
+     bl nterp_to_nterp_string_init_range
+     .elseif \is_static
+     bl nterp_to_nterp_static_range
+     .else
+     bl nterp_to_nterp_instance_range
+     .endif
+     b .Ldone_return_range_\suffix
+   .endif
+
+.Lcall_compiled_code_range_\suffix:
+   .if \is_polymorphic
+   // No fast path for polymorphic calls.
+   .elseif \is_custom
+   // No fast path for custom calls.
+   .elseif \is_string_init
+   // No fast path for string.init.
+   .else
+     ldr wip, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
+     tbz wip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG_BIT, .Lfast_path_with_few_args_range_\suffix
+     FETCH_B wip2, 0, 1  // Number of arguments
+     .if \is_static
+     cbz ip2, .Linvoke_fast_path_range_\suffix
+     .else
+     cmp ip2, #1
+     b.eq .Linvoke_fast_path_range_\suffix
+     .endif
+     FETCH wip, 2  // dex register of first argument
+     add x8, xFP, wip, uxtw #2  // location of first dex register value
+     cmp ip2, #2
+     .if \is_static
+     b.lt .Lone_arg_fast_path_range_\suffix
+     .endif
+     b.eq .Ltwo_args_fast_path_range_\suffix
+     cmp ip2, #4
+     b.lt .Lthree_args_fast_path_range_\suffix
+     b.eq .Lfour_args_fast_path_range_\suffix
+     cmp ip2, #6
+     b.lt .Lfive_args_fast_path_range_\suffix
+     b.eq .Lsix_args_fast_path_range_\suffix
+     cmp ip2, #7
+     b.eq .Lseven_args_fast_path_range_\suffix
+     // Setup x8 to point to the stack location of parameters we do not need
+     // to put parameters in.
+     add x9, sp, #8  // Add space for the ArtMethod
+
+.Lloop_over_fast_path_range_\suffix:
+     sub ip2, ip2, #1
+     ldr wip, [x8, ip2, lsl #2]
+     str wip, [x9, ip2, lsl #2]
+     cmp ip2, #7
+     b.ne .Lloop_over_fast_path_range_\suffix
+
+.Lseven_args_fast_path_range_\suffix:
+     ldr w7, [x8, #24]
+.Lsix_args_fast_path_range_\suffix:
+     ldr w6, [x8, #20]
+.Lfive_args_fast_path_range_\suffix:
+     ldr w5, [x8, #16]
+.Lfour_args_fast_path_range_\suffix:
+     ldr w4, [x8, #12]
+.Lthree_args_fast_path_range_\suffix:
+     ldr w3, [x8, #8]
+.Ltwo_args_fast_path_range_\suffix:
+     ldr w2, [x8, #4]
+.Lone_arg_fast_path_range_\suffix:
+     .if \is_static
+     ldr w1, [x8, #0]
+     .else
+     // First argument already in w1.
+     .endif
+.Linvoke_fast_path_range_\suffix:
+     .if \is_interface
+     // Setup hidden argument.
+     mov ip2, x26
+     .endif
+     ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
+     blr lr
+     FETCH_ADVANCE_INST 3
+     GET_INST_OPCODE ip
+     GOTO_OPCODE ip
+
+.Lfast_path_with_few_args_range_\suffix:
+     // Fast path when we have zero or one argument (modulo 'this'). If there
+     // is one argument, we can put it in both floating point and core register.
+     FETCH_B w2, 0, 1 // number of arguments
+     .if \is_static
+     cmp w2, #1
+     .else
+     cmp w2, #2
+     .endif
+     b.lt .Linvoke_with_few_args_range_\suffix
+     b.ne .Lget_shorty_range_\suffix
+     FETCH w3, 2  // dex register of first argument
+     .if \is_static
+     GET_VREG w1, w3
+     fmov s0, w1
+     .else
+     add w3, w3, #1  // Add 1 for next argument
+     GET_VREG w2, w3
+     fmov s0, w2
+     .endif
+.Linvoke_with_few_args_range_\suffix:
+     // Check if the next instruction is move-result or move-result-wide.
+     // If it is, we fetch the shorty and jump to the regular invocation.
+     FETCH w27, 3
+     and ip, x27, #0xfe
+     cmp ip, #0x0a
+     b.eq .Lget_shorty_and_invoke_range_\suffix
+     .if \is_interface
+     // Setup hidden argument.
+     mov ip2, x26
+     .endif
+     ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
+     blr lr
+     mov xINST, x27
+     ADVANCE 3
+     GET_INST_OPCODE ip
+     GOTO_OPCODE ip
+.Lget_shorty_and_invoke_range_\suffix:
+     GET_SHORTY_SLOW_PATH xINST, \is_interface
+     b .Lgpr_setup_finished_range_\suffix
+   .endif
+
+.Lget_shorty_range_\suffix:
+   GET_SHORTY xINST, \is_interface, \is_polymorphic, \is_custom
+   // From this point:
+   // - xINST contains shorty (in callee-save to switch over return value after call).
+   // - x0 contains method
+   // - x1 contains 'this' pointer for instance method.
+   // - for interface calls, x26 contains the interface method.
+   add x9, xINST, #1  // shorty + 1  ; ie skip return arg character
+   FETCH w10, 2 // arguments
+   .if \is_string_init
+   add x10, x10, #1  // arg start index
+   mov x11, #1       // index in stack
+   .elseif \is_static
+   mov x11, xzr      // index in stack
+   .else
+   add x10, x10, #1  // arg start index
+   mov x11, #1       // index in stack
+   .endif
+   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d0, s0, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d1, s1, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d2, s2, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d3, s3, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d4, s4, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d5, s5, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d6, s6, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d7, s7, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
+   // Store in the outs array (stored above the ArtMethod in the stack)
+   add x11, x11, #2 // Add two words for the ArtMethod stored before the outs.
+   LOOP_RANGE_OVER_FPs x9, w10, w11, .Lxmm_setup_finished_range_\suffix
+.Lxmm_setup_finished_range_\suffix:
+   add x9, xINST, #1  // shorty + 1  ; ie skip return arg character
+   FETCH w10, 2 // arguments
+   .if \is_string_init
+   add x10, x10, #1  // arg start index
+   mov x11, #1       // index in stack
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x1, w1, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
+   .elseif \is_static
+   mov x11, xzr      // index in stack
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x1, w1, x9, w10, w11 .Lgpr_setup_finished_range_\suffix
+   .else
+   add x10, x10, #1  // arg start index
+   mov x11, #1       // index in stack
+   .endif
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x2, w2, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x3, w3, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x4, w4, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x5, w5, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x6, w6, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x7, w7, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
+   // Store in the outs array (stored above the ArtMethod in the stack)
+   add x11, x11, #2 // Add two words for the ArtMethod stored before the outs.
+   LOOP_RANGE_OVER_INTs x9, w10, w11, .Lgpr_setup_finished_range_\suffix
+.Lgpr_setup_finished_range_\suffix:
+   .if \is_polymorphic
+   bl art_quick_invoke_polymorphic
+   .elseif \is_custom
+   bl art_quick_invoke_custom
+   .else
+      .if \is_interface
+      // Setup hidden argument.
+      mov ip2, x26
+      .endif
+      ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
+      blr lr
+   .endif
+   SETUP_RETURN_VALUE xINST
+.Ldone_return_range_\suffix:
+   /* resume execution of caller */
+   .if \is_string_init
+   FETCH w11, 2 // arguments
+   GET_VREG w1, w11
+   UPDATE_REGISTERS_FOR_STRING_INIT w1, w0
+   .endif
+
+   .if \is_polymorphic
+   FETCH_ADVANCE_INST 4
+   .else
+   FETCH_ADVANCE_INST 3
+   .endif
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.endm
+
+.macro WRITE_BARRIER_IF_OBJECT is_object, value, holder, label
+   .if \is_object
+   cbz     \value, \label
+   ldr     ip, [xSELF, #THREAD_CARD_TABLE_OFFSET]
+   lsr     wip2, \holder, #CARD_TABLE_CARD_SHIFT
+   strb    wip, [ip, ip2]
+\label:
+   .endif
+.endm
+
+// Fetch some information from the thread cache.
+// Uses ip and ip2 as temporaries.
+.macro FETCH_FROM_THREAD_CACHE dest_reg, slow_path
+   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
+   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
+   add      ip, ip, ip2, lsl #4            // entry address within the cache
+   ldp      ip, \dest_reg, [ip]           // entry key (pc) and value (offset)
+   cmp      ip, xPC
+   b.ne \slow_path
+.endm
+
+// Puts the next int/long/object parameter passed in physical register
+// in the expected dex register array entry, and in case of object in the
+// expected reference array entry.
+.macro LOOP_OVER_SHORTY_STORING_GPRS gpr_64, gpr_32, shorty, arg_offset, regs, refs, finished
+1: // LOOP
+    ldrb wip, [\shorty], #1       // Load next character in shorty, and increment.
+    cbz wip, \finished            // if (wip == '\0') goto finished
+    cmp wip, #74                  // if (wip == 'J') goto FOUND_LONG
+    b.eq 2f
+    cmp wip, #70                  // if (wip == 'F') goto SKIP_FLOAT
+    b.eq 3f
+    cmp wip, #68                  // if (wip == 'D') goto SKIP_DOUBLE
+    b.eq 4f
+    str \gpr_32, [\regs, \arg_offset]
+    cmp wip, #76                  // if (wip != 'L') goto NOT_REFERENCE
+    b.ne 6f
+    str \gpr_32, [\refs, \arg_offset]
+6:  // NOT_REFERENCE
+    add \arg_offset, \arg_offset, #4
+    b 5f
+2:  // FOUND_LONG
+    str \gpr_64, [\regs, \arg_offset]
+    add \arg_offset, \arg_offset, #8
+    b 5f
+3:  // SKIP_FLOAT
+    add \arg_offset, \arg_offset, #4
+    b 1b
+4:  // SKIP_DOUBLE
+    add \arg_offset, \arg_offset, #8
+    b 1b
+5:
+.endm
+
+// Puts the next floating point parameter passed in physical register
+// in the expected dex register array entry.
+// Uses ip as temporary.
+.macro LOOP_OVER_SHORTY_STORING_FPS dreg, sreg, shorty, arg_offset, fp, finished
+1: // LOOP
+    ldrb wip, [\shorty], #1                 // Load next character in shorty, and increment.
+    cbz wip, \finished                      // if (wip == '\0') goto finished
+    cmp wip, #68                            // if (wip == 'D') goto FOUND_DOUBLE
+    b.eq 2f
+    cmp wip, #70                            // if (wip == 'F') goto FOUND_FLOAT
+    b.eq 3f
+    add \arg_offset, \arg_offset, #4
+    //  Handle extra argument in arg array taken by a long.
+    cmp wip, #74                            // if (wip != 'J') goto LOOP
+    b.ne 1b
+    add \arg_offset, \arg_offset, #4
+    b 1b                        // goto LOOP
+2:  // FOUND_DOUBLE
+    str \dreg, [\fp, \arg_offset]
+    add \arg_offset, \arg_offset, #8
+    b 4f
+3:  // FOUND_FLOAT
+    str \sreg, [\fp, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+4:
+.endm
+
+// Puts the next floating point parameter passed in stack
+// in the expected dex register array entry.
+// Uses ip as temporary.
+//
+// TODO: Or we could just spill regs to the reserved slots in the caller's
+// frame and copy all regs in a simple loop. This time, however, we would
+// need to look at the shorty anyway to look for the references.
+// (The trade-off is different for passing arguments and receiving them.)
+.macro LOOP_OVER_FPs shorty, arg_offset, regs, stack_ptr, finished
+1: // LOOP
+    ldrb wip, [\shorty], #1                 // Load next character in shorty, and increment.
+    cbz wip, \finished                      // if (wip == '\0') goto finished
+    cmp wip, #68                            // if (wip == 'D') goto FOUND_DOUBLE
+    b.eq 2f
+    cmp wip, #70                            // if (wip == 'F') goto FOUND_FLOAT
+    b.eq 3f
+    add \arg_offset, \arg_offset, #4
+    //  Handle extra argument in arg array taken by a long.
+    cmp wip, #74                            // if (wip != 'J') goto LOOP
+    b.ne 1b
+    add \arg_offset, \arg_offset, #4
+    b 1b                        // goto LOOP
+2:  // FOUND_DOUBLE
+    add ip, \stack_ptr, \arg_offset
+    ldr ip, [ip,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
+    str ip, [\regs, \arg_offset]
+    add \arg_offset, \arg_offset, #8
+    b 1b
+3:  // FOUND_FLOAT
+    add ip, \stack_ptr, \arg_offset
+    ldr wip, [ip,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
+    str wip, [\regs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    b 1b
+.endm
+
+// Puts the next int/long/object parameter passed in stack
+// in the expected dex register array entry, and in case of object in the
+// expected reference array entry.
+// Uses ip and ip2 as temporary.
+.macro LOOP_OVER_INTs shorty, arg_offset, regs, refs, stack_ptr, finished
+1: // LOOP
+    ldrb wip, [\shorty], #1       // Load next character in shorty, and increment.
+    cbz wip, \finished            // if (wip == '\0') goto finished
+    cmp wip, #74                  // if (wip == 'J') goto FOUND_LONG
+    b.eq 2f
+    cmp wip, #70                  // if (wip == 'F') goto SKIP_FLOAT
+    b.eq 3f
+    cmp wip, #68                  // if (wip == 'D') goto SKIP_DOUBLE
+    b.eq 4f
+    add ip2, \stack_ptr, \arg_offset
+    ldr wip2, [ip2,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
+    str wip2, [\regs, \arg_offset]
+    cmp wip, #76                  // if (wip != 'L') goto loop
+    b.ne 3f
+    str wip2, [\refs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    b 1b
+2:  // FOUND_LONG
+    add ip, \stack_ptr, \arg_offset
+    ldr ip, [ip,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
+    str ip, [\regs, \arg_offset]
+    add \arg_offset, \arg_offset, #8
+    b 1b
+3:  // SKIP_FLOAT
+    add \arg_offset, \arg_offset, #4
+    b 1b
+4:  // SKIP_DOUBLE
+    add \arg_offset, \arg_offset, #8
+    b 1b
+.endm
+
+.macro SETUP_REFERENCE_PARAMETER_IN_GPR gpr32, regs, refs, ins, arg_offset, finished
+    str \gpr32, [\regs, \arg_offset]
+    sub \ins, \ins, #1
+    str \gpr32, [\refs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    cbz \ins, \finished
+.endm
+
+// Uses ip2 as temporary.
+.macro SETUP_REFERENCE_PARAMETERS_IN_STACK regs, refs, ins, stack_ptr, arg_offset
+1:
+    ldr wip2, [\stack_ptr, \arg_offset]
+    sub \ins, \ins, #1
+    str wip2, [\regs, \arg_offset]
+    str wip2, [\refs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    cbnz \ins, 1b
+.endm
+
+%def entry():
+/*
+ * ArtMethod entry point.
+ *
+ * On entry:
+ *  x0   ArtMethod* callee
+ *  rest  method parameters
+ */
+
+OAT_ENTRY ExecuteNterpImpl, EndExecuteNterpImpl
+    .cfi_startproc
+    sub x16, sp, #STACK_OVERFLOW_RESERVED_BYTES
+    ldr wzr, [x16]
+    /* Spill callee save regs */
+    SPILL_ALL_CALLEE_SAVES
+
+    ldr xPC, [x0, #ART_METHOD_DATA_OFFSET_64]
+    // Setup the stack for executing the method.
+    SETUP_STACK_FRAME xPC, xREFS, xFP, CFI_REFS, load_ins=1
+
+    // Setup the parameters
+    cbz w15, .Lxmm_setup_finished
+
+    sub ip2, ip, x15
+    ldr w26, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
+    lsl x21, ip2, #2 // x21 is now the offset for inputs into the registers array.
+
+    tbz w26, #ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG_BIT, .Lsetup_slow_path
+    // Setup pointer to inputs in FP and pointer to inputs in REFS
+    add x10, xFP, x21
+    add x11, xREFS, x21
+    mov x12, #0
+    SETUP_REFERENCE_PARAMETER_IN_GPR w1, x10, x11, w15, x12, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR w2, x10, x11, w15, x12, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR w3, x10, x11, w15, x12, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR w4, x10, x11, w15, x12, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR w5, x10, x11, w15, x12, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR w6, x10, x11, w15, x12, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR w7, x10, x11, w15, x12, .Lxmm_setup_finished
+    add x28, x28, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK
+    SETUP_REFERENCE_PARAMETERS_IN_STACK x10, x11, w15, x28, x12
+    b .Lxmm_setup_finished
+
+.Lsetup_slow_path:
+    // If the method is not static and there is one argument ('this'), we don't need to fetch the
+    // shorty.
+    tbnz w26, #ART_METHOD_IS_STATIC_FLAG_BIT, .Lsetup_with_shorty
+    str w1, [xFP, x21]
+    str w1, [xREFS, x21]
+    cmp w15, #1
+    b.eq .Lxmm_setup_finished
+
+.Lsetup_with_shorty:
+    // TODO: Get shorty in a better way and remove below
+    SPILL_ALL_ARGUMENTS
+    bl NterpGetShorty
+    // Save shorty in callee-save xIBASE.
+    mov xIBASE, x0
+    RESTORE_ALL_ARGUMENTS
+
+    // Setup pointer to inputs in FP and pointer to inputs in REFS
+    add x10, xFP, x21
+    add x11, xREFS, x21
+    mov x12, #0
+
+    add x9, xIBASE, #1  // shorty + 1  ; ie skip return arg character
+    tbnz w26, #ART_METHOD_IS_STATIC_FLAG_BIT, .Lhandle_static_method
+    add x10, x10, #4
+    add x11, x11, #4
+    add x28, x28, #4
+    b .Lcontinue_setup_gprs
+.Lhandle_static_method:
+    LOOP_OVER_SHORTY_STORING_GPRS x1, w1, x9, x12, x10, x11, .Lgpr_setup_finished
+.Lcontinue_setup_gprs:
+    LOOP_OVER_SHORTY_STORING_GPRS x2, w2, x9, x12, x10, x11, .Lgpr_setup_finished
+    LOOP_OVER_SHORTY_STORING_GPRS x3, w3, x9, x12, x10, x11, .Lgpr_setup_finished
+    LOOP_OVER_SHORTY_STORING_GPRS x4, w4, x9, x12, x10, x11, .Lgpr_setup_finished
+    LOOP_OVER_SHORTY_STORING_GPRS x5, w5, x9, x12, x10, x11, .Lgpr_setup_finished
+    LOOP_OVER_SHORTY_STORING_GPRS x6, w6, x9, x12, x10, x11, .Lgpr_setup_finished
+    LOOP_OVER_SHORTY_STORING_GPRS x7, w7, x9, x12, x10, x11, .Lgpr_setup_finished
+    LOOP_OVER_INTs x9, x12, x10, x11, x28, .Lgpr_setup_finished
+.Lgpr_setup_finished:
+    add x9, xIBASE, #1  // shorty + 1  ; ie skip return arg character
+    mov x12, #0  // reset counter
+    LOOP_OVER_SHORTY_STORING_FPS d0, s0, x9, x12, x10, .Lxmm_setup_finished
+    LOOP_OVER_SHORTY_STORING_FPS d1, s1, x9, x12, x10, .Lxmm_setup_finished
+    LOOP_OVER_SHORTY_STORING_FPS d2, s2, x9, x12, x10, .Lxmm_setup_finished
+    LOOP_OVER_SHORTY_STORING_FPS d3, s3, x9, x12, x10, .Lxmm_setup_finished
+    LOOP_OVER_SHORTY_STORING_FPS d4, s4, x9, x12, x10, .Lxmm_setup_finished
+    LOOP_OVER_SHORTY_STORING_FPS d5, s5, x9, x12, x10, .Lxmm_setup_finished
+    LOOP_OVER_SHORTY_STORING_FPS d6, s6, x9, x12, x10, .Lxmm_setup_finished
+    LOOP_OVER_SHORTY_STORING_FPS d7, s7, x9, x12, x10, .Lxmm_setup_finished
+    LOOP_OVER_FPs x9, x12, x10, x28, .Lxmm_setup_finished
+.Lxmm_setup_finished:
+    CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
+
+    // Set rIBASE
+    adr xIBASE, artNterpAsmInstructionStart
+    /* start executing the instruction at xPC */
+    START_EXECUTING_INSTRUCTIONS
+    /* NOTE: no fallthrough */
+    // cfi info continues, and covers the whole nterp implementation.
+    SIZE ExecuteNterpImpl
+
+%def opcode_pre():
+
+%def helpers():
+
+%def footer():
+/*
+ * ===========================================================================
+ *  Common subroutines and data
+ * ===========================================================================
+ */
+
+    .text
+    .align  2
+
+// Enclose all code below in a symbol (which gets printed in backtraces).
+NAME_START nterp_helper
+
+// Note: mterp also uses the common_* names below for helpers, but that's OK
+// as the assembler compiled each interpreter separately.
+common_errDivideByZero:
+    EXPORT_PC
+    bl art_quick_throw_div_zero
+
+// Expect index in w1, length in w3.
+common_errArrayIndex:
+    EXPORT_PC
+    mov x0, x1
+    mov x1, x3
+    bl art_quick_throw_array_bounds
+
+common_errNullObject:
+    EXPORT_PC
+    bl art_quick_throw_null_pointer_exception
+
+NterpCommonInvokeStatic:
+    COMMON_INVOKE_NON_RANGE is_static=1, suffix="invokeStatic"
+
+NterpCommonInvokeStaticRange:
+    COMMON_INVOKE_RANGE is_static=1, suffix="invokeStatic"
+
+NterpCommonInvokeInstance:
+    COMMON_INVOKE_NON_RANGE suffix="invokeInstance"
+
+NterpCommonInvokeInstanceRange:
+    COMMON_INVOKE_RANGE suffix="invokeInstance"
+
+NterpCommonInvokeInterface:
+    COMMON_INVOKE_NON_RANGE is_interface=1, suffix="invokeInterface"
+
+NterpCommonInvokeInterfaceRange:
+    COMMON_INVOKE_RANGE is_interface=1, suffix="invokeInterface"
+
+NterpCommonInvokePolymorphic:
+    COMMON_INVOKE_NON_RANGE is_polymorphic=1, suffix="invokePolymorphic"
+
+NterpCommonInvokePolymorphicRange:
+    COMMON_INVOKE_RANGE is_polymorphic=1, suffix="invokePolymorphic"
+
+NterpCommonInvokeCustom:
+    COMMON_INVOKE_NON_RANGE is_static=1, is_custom=1, suffix="invokeCustom"
+
+NterpCommonInvokeCustomRange:
+    COMMON_INVOKE_RANGE is_static=1, is_custom=1, suffix="invokeCustom"
+
+NterpHandleStringInit:
+   COMMON_INVOKE_NON_RANGE is_string_init=1, suffix="stringInit"
+
+NterpHandleStringInitRange:
+   COMMON_INVOKE_RANGE is_string_init=1, suffix="stringInit"
+
+NterpNewArray:
+   /* new-array vA, vB, class@CCCC */
+   EXPORT_PC
+   // Fast-path which gets the class from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x0, 2f
+   cbnz wMR, 3f
+1:
+   lsr     w1, wINST, #12              // w1<- B
+   GET_VREG w1, w1                     // w1<- vB (array length)
+   ldr lr, [xSELF, #THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET]
+   blr lr
+   ubfx    w1, wINST, #8, #4           // w1<- A
+   SET_VREG_OBJECT w0, w1
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+2:
+   mov x0, xSELF
+   ldr x1, [sp, 0]
+   mov x2, xPC
+   bl nterp_get_class_or_allocate_object
+   b 1b
+3:
+   bl art_quick_read_barrier_mark_reg00
+   b 1b
+
+NterpHandleHotnessOverflow:
+    add x1, xPC, xINST, lsl #1
+    mov x2, xFP
+    bl nterp_hot_method
+    cbnz x0, 1f
+    add     xPC, xPC, wINST, sxtw #1    // update xPC
+    FETCH wINST, 0                      // load wINST
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    GOTO_OPCODE ip                      // jump to next instruction
+1:
+    // Drop the current frame.
+    ldr ip, [xREFS, #-8]
+    mov sp, ip
+    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
+
+    // The transition frame of type SaveAllCalleeSaves saves x19 and x20,
+    // but not managed ABI. So we need to restore callee-saves of the nterp frame,
+    // and save managed ABI callee saves, which will be restored by the callee upon
+    // return.
+    RESTORE_ALL_CALLEE_SAVES
+    INCREASE_FRAME ((CALLEE_SAVES_SIZE) - 16)
+
+    // FP callee-saves
+    stp d8, d9, [sp, #0]
+    stp d10, d11, [sp, #16]
+    stp d12, d13, [sp, #32]
+    stp d14, d15, [sp, #48]
+
+    // GP callee-saves.
+    SAVE_TWO_REGS x21, x22, 64
+    SAVE_TWO_REGS x23, x24, 80
+    SAVE_TWO_REGS x25, x26, 96
+    SAVE_TWO_REGS x27, x28, 112
+    SAVE_TWO_REGS x29, lr, 128
+
+    // Setup the new frame
+    ldr x1, [x0, #OSR_DATA_FRAME_SIZE]
+    // Given stack size contains all callee saved registers, remove them.
+    sub x1, x1, #(CALLEE_SAVES_SIZE - 16)
+
+    // We know x1 cannot be 0, as it at least contains the ArtMethod.
+
+    // Remember CFA in a callee-save register.
+    mov xINST, sp
+    .cfi_def_cfa_register xINST
+
+    sub sp, sp, x1
+
+    add x2, x0, #OSR_DATA_MEMORY
+2:
+    sub x1, x1, #8
+    ldr ip, [x2, x1]
+    str ip, [sp, x1]
+    cbnz x1, 2b
+
+    // Fetch the native PC to jump to and save it in a callee-save register.
+    ldr xFP, [x0, #OSR_DATA_NATIVE_PC]
+
+    // Free the memory holding OSR Data.
+    bl free
+
+    // Jump to the compiled code.
+    br xFP
+
+// This is the logical end of ExecuteNterpImpl, where the frame info applies.
+// EndExecuteNterpImpl includes the methods below as we want the runtime to
+// see them as part of the Nterp PCs.
+.cfi_endproc
+
+nterp_to_nterp_static_non_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=1, is_string_init=0
+    .cfi_endproc
+
+nterp_to_nterp_string_init_non_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
+    .cfi_endproc
+
+nterp_to_nterp_instance_non_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
+    .cfi_endproc
+
+nterp_to_nterp_static_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=1
+    .cfi_endproc
+
+nterp_to_nterp_instance_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0
+    .cfi_endproc
+
+nterp_to_nterp_string_init_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
+    .cfi_endproc
+
+NAME_END nterp_helper
+
+// This is the end of PCs contained by the OatQuickMethodHeader created for the interpreter
+// entry point.
+    .type EndExecuteNterpImpl, #function
+    .hidden EndExecuteNterpImpl
+    .global EndExecuteNterpImpl
+EndExecuteNterpImpl:
+
+// Entrypoints into runtime.
+NTERP_TRAMPOLINE nterp_get_static_field, NterpGetStaticField
+NTERP_TRAMPOLINE nterp_get_instance_field_offset, NterpGetInstanceFieldOffset
+NTERP_TRAMPOLINE nterp_filled_new_array, NterpFilledNewArray
+NTERP_TRAMPOLINE nterp_filled_new_array_range, NterpFilledNewArrayRange
+NTERP_TRAMPOLINE nterp_get_class_or_allocate_object, NterpGetClassOrAllocateObject
+NTERP_TRAMPOLINE nterp_get_method, NterpGetMethod
+NTERP_TRAMPOLINE nterp_hot_method, NterpHotMethod
+NTERP_TRAMPOLINE nterp_load_object, NterpLoadObject
+
+// gen_mterp.py will inline the following definitions
+// within [ExecuteNterpImpl, EndExecuteNterpImpl).
+%def instruction_end():
+
+    .type artNterpAsmInstructionEnd, #function
+    .hidden artNterpAsmInstructionEnd
+    .global artNterpAsmInstructionEnd
+artNterpAsmInstructionEnd:
+    // artNterpAsmInstructionEnd is used as landing pad for exception handling.
+    FETCH_INST
+    GET_INST_OPCODE ip
+    GOTO_OPCODE ip
+
+%def instruction_start():
+
+    .type artNterpAsmInstructionStart, #function
+    .hidden artNterpAsmInstructionStart
+    .global artNterpAsmInstructionStart
+artNterpAsmInstructionStart = .L_op_nop
+    .text
+
+%def default_helper_prefix():
+%  return "nterp_"
+
+%def opcode_start():
+    NAME_START nterp_${opcode}
+%def opcode_end():
+    NAME_END nterp_${opcode}
+%def helper_start(name):
+    NAME_START ${name}
+%def helper_end(name):
+    NAME_END ${name}
diff --git a/runtime/interpreter/mterp/arm64ng/object.S b/runtime/interpreter/mterp/arm64ng/object.S
new file mode 100644
index 0000000..00490a7
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64ng/object.S
@@ -0,0 +1,405 @@
+%def op_check_cast():
+   // Fast-path which gets the class from thread-local cache.
+   EXPORT_PC
+   FETCH_FROM_THREAD_CACHE x1, 3f
+   cbnz    wMR, 4f
+1:
+   lsr     w2, wINST, #8               // w2<- A
+   GET_VREG w0, w2                     // w0<- vA (object)
+   cbz     w0, 2f
+   bl      art_quick_check_instance_of
+2:
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+3:
+   mov     x0, xSELF
+   ldr     x1, [sp]
+   mov     x2, xPC
+   bl      nterp_get_class_or_allocate_object
+   mov     x1, x0
+   b       1b
+4:
+   bl      art_quick_read_barrier_mark_reg01
+   b       1b
+
+%def op_instance_of():
+   /* instance-of vA, vB, class@CCCC */
+   // Fast-path which gets the class from thread-local cache.
+   EXPORT_PC
+   FETCH_FROM_THREAD_CACHE x1, 3f
+   cbnz    wMR, 4f
+1:
+   lsr     w2, wINST, #12              // w2<- B
+   GET_VREG w0, w2                     // w0<- vB (object)
+   cbz     w0, 2f
+   bl      artInstanceOfFromCode
+2:
+   ubfx    w1, wINST, #8, #4           // w1<- A
+   SET_VREG w0, w1
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+3:
+   mov     x0, xSELF
+   ldr     x1, [sp]
+   mov     x2, xPC
+   bl      nterp_get_class_or_allocate_object
+   mov     x1, x0
+   b       1b
+4:
+   bl      art_quick_read_barrier_mark_reg01
+   b       1b
+
+%def op_iget_boolean():
+%  op_iget(load="ldrb", volatile_load="ldarb", maybe_extend="", wide="0", is_object="0")
+
+%def op_iget_byte():
+%  op_iget(load="ldrsb", volatile_load="ldarb", maybe_extend="sxtb w0, w0", wide="0", is_object="0")
+
+%def op_iget_char():
+%  op_iget(load="ldrh", volatile_load="ldarh", maybe_extend="", wide="0", is_object="0")
+
+%def op_iget_short():
+%  op_iget(load="ldrsh", volatile_load="ldarh", maybe_extend="sxth w0, w0", wide="0", is_object="0")
+
+%def op_iget(load="ldr", volatile_load="ldar", maybe_extend="", wide="0", is_object="0"):
+%  slow_path = add_helper(lambda: op_iget_slow_path(volatile_load, maybe_extend, wide, is_object))
+   // Fast-path which gets the field from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x0, ${slow_path}
+.L${opcode}_resume:
+   lsr     w2, wINST, #12              // w2<- B
+   GET_VREG w3, w2                     // w3<- object we're operating on
+   ubfx    w2, wINST, #8, #4           // w2<- A
+   cbz     w3, common_errNullObject    // object was null
+   .if $wide
+   $load   x0, [x3, x0]
+   SET_VREG_WIDE x0, w2                // fp[A] <- value
+   .elseif $is_object
+   $load   w0, [x3, x0]
+   cbnz    wMR, .L${opcode}_read_barrier
+.L${opcode}_resume_after_read_barrier:
+   SET_VREG_OBJECT w0, w2              // fp[A] <- value
+   .else
+   $load   w0, [x3, x0]
+   SET_VREG w0, w2                     // fp[A] <- value
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+   .if $is_object
+.L${opcode}_read_barrier:
+   bl      art_quick_read_barrier_mark_reg00
+   b       .L${opcode}_resume_after_read_barrier
+   .endif
+
+%def op_iget_slow_path(volatile_load, maybe_extend, wide, is_object):
+   mov     x0, xSELF
+   ldr     x1, [sp]
+   mov     x2, xPC
+   mov     x3, #0
+   EXPORT_PC
+   bl      nterp_get_instance_field_offset
+   tbz     w0, #31, .L${opcode}_resume
+   CLEAR_INSTANCE_VOLATILE_MARKER w0
+   lsr     w2, wINST, #12              // w2<- B
+   GET_VREG w3, w2                     // w3<- object we're operating on
+   ubfx    w2, wINST, #8, #4           // w2<- A
+   cbz     w3, common_errNullObject    // object was null
+   add     x3, x3, x0
+   .if $wide
+   $volatile_load x0, [x3]
+   SET_VREG_WIDE x0, w2                // fp[A] <- value
+   .elseif $is_object
+   $volatile_load w0, [x3]
+   cbnz wMR, .L${opcode}_read_barrier
+   SET_VREG_OBJECT w0, w2              // fp[A] <- value
+   .else
+   $volatile_load w0, [x3]
+   $maybe_extend
+   SET_VREG w0, w2                     // fp[A] <- value
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+
+%def op_iget_wide():
+%  op_iget(load="ldr", volatile_load="ldar", maybe_extend="", wide="1", is_object="0")
+
+%def op_iget_object():
+%  op_iget(load="ldr", volatile_load="ldar", maybe_extend="", wide="0", is_object="1")
+
+%def op_iput_boolean():
+%  op_iput(store="strb", volatile_store="stlrb", wide="0", is_object="0")
+
+%def op_iput_byte():
+%  op_iput(store="strb", volatile_store="stlrb", wide="0", is_object="0")
+
+%def op_iput_char():
+%  op_iput(store="strh", volatile_store="stlrh", wide="0", is_object="0")
+
+%def op_iput_short():
+%  op_iput(store="strh", volatile_store="stlrh", wide="0", is_object="0")
+
+%def op_iput(store="str", volatile_store="stlr", wide="0", is_object="0"):
+   // Share slow paths for boolean and byte (strb) and slow paths for char and short (strh).
+   // It does not matter to which `.L${opcode}_resume` the slow path returns.
+%  slow_path = "nterp_op_iput_helper_" + store + wide + is_object
+%  add_helper(lambda: op_iput_slow_path(volatile_store, wide, is_object), slow_path)
+   ubfx    w1, wINST, #8, #4           // w1<- A
+   .if $wide
+   GET_VREG_WIDE x26, w1               // x26<- fp[A]/fp[A+1]
+   .else
+   GET_VREG w26, w1                    // w26 <- v[A]
+   .endif
+   // Fast-path which gets the field from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x0, ${slow_path}
+.L${opcode}_resume:
+   lsr     w2, wINST, #12              // w2<- B
+   GET_VREG w2, w2                     // vB (object we're operating on)
+   cbz w2, common_errNullObject
+   .if $wide
+   $store  x26, [x2, x0]
+   .else
+   $store  w26, [x2, x0]
+   WRITE_BARRIER_IF_OBJECT $is_object, w26, w2, .L${opcode}_skip_write_barrier
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+
+%def op_iput_slow_path(volatile_store, wide, is_object):
+   mov     x0, xSELF
+   ldr     x1, [sp]
+   mov     x2, xPC
+   .if $is_object
+   mov     x3, x26
+   .else
+   mov     x3, #0
+   .endif
+   EXPORT_PC
+   bl      nterp_get_instance_field_offset
+   .if $is_object
+   // Reload the value as it may have moved.
+   ubfx    w1, wINST, #8, #4           // w1<- A
+   GET_VREG w26, w1                    // w26 <- v[A]
+   .endif
+   tbz     w0, #31, .L${opcode}_resume
+   CLEAR_INSTANCE_VOLATILE_MARKER w0
+   lsr     w2, wINST, #12              // w2<- B
+   GET_VREG w2, w2                     // vB (object we're operating on)
+   cbz     w2, common_errNullObject
+   add     x3, x2, x0
+   .if $wide
+   $volatile_store x26, [x3]
+   .else
+   $volatile_store w26, [x3]
+   WRITE_BARRIER_IF_OBJECT $is_object, w26, w2, .L${opcode}_slow_path_skip_write_barrier
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+
+%def op_iput_wide():
+%  op_iput(store="str", volatile_store="stlr", wide="1", is_object="0")
+
+%def op_iput_object():
+%  op_iput(store="str", volatile_store="stlr", wide="0", is_object="1")
+
+%def op_sget_boolean():
+%  op_sget(load="ldrb", volatile_load="ldarb", maybe_extend="", wide="0", is_object="0")
+
+%def op_sget_byte():
+%  op_sget(load="ldrsb", volatile_load="ldarb", maybe_extend="sxtb w0, w0", wide="0", is_object="0")
+
+%def op_sget_char():
+%  op_sget(load="ldrh", volatile_load="ldarh", maybe_extend="", wide="0", is_object="0")
+
+%def op_sget_short():
+%  op_sget(load="ldrsh", volatile_load="ldarh", maybe_extend="sxth w0, w0", wide="0", is_object="0")
+
+%def op_sget(load="ldr", volatile_load="ldar", maybe_extend="", wide="0", is_object="0"):
+%  slow_path = add_helper(lambda: op_sget_slow_path(volatile_load, maybe_extend, wide, is_object))
+   // Fast-path which gets the field from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x0, ${slow_path}
+.L${opcode}_resume:
+   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
+   lsr     w2, wINST, #8               // w2 <- A
+   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
+   cbnz    wMR, .L${opcode}_read_barrier
+.L${opcode}_resume_after_read_barrier:
+   .if $wide
+   ldr     x0, [x0, x1]
+   SET_VREG_WIDE x0, w2                // fp[A] <- value
+   .elseif $is_object
+   $load   w0, [x0, x1]
+   // No need to check the marking register, we know it's not set here.
+.L${opcode}_after_reference_load:
+   SET_VREG_OBJECT w0, w2              // fp[A] <- value
+   .else
+   $load   w0, [x0, x1]
+   SET_VREG w0, w2                     // fp[A] <- value
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.L${opcode}_read_barrier:
+   bl      art_quick_read_barrier_mark_reg00
+   .if $is_object
+   $load   w0, [x0, x1]
+.L${opcode}_mark_after_load:
+   // Here, we know the marking register is set.
+   bl      art_quick_read_barrier_mark_reg00
+   b       .L${opcode}_after_reference_load
+   .else
+   b       .L${opcode}_resume_after_read_barrier
+   .endif
+
+%def op_sget_slow_path(volatile_load, maybe_extend, wide, is_object):
+   mov     x0, xSELF
+   ldr     x1, [sp]
+   mov     x2, xPC
+   mov     x3, #0
+   EXPORT_PC
+   bl      nterp_get_static_field
+   tbz     x0, #0, .L${opcode}_resume
+   CLEAR_STATIC_VOLATILE_MARKER x0
+   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
+   lsr     w2, wINST, #8               // w2 <- A
+   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
+   cbnz    wMR, .L${opcode}_slow_path_read_barrier
+.L${opcode}_slow_path_resume_after_read_barrier:
+   add     x0, x0, x1
+   .if $wide
+   ldar    x0, [x0]
+   SET_VREG_WIDE x0, w2                // fp[A] <- value
+   .elseif $is_object
+   $volatile_load w0, [x0]
+   cbnz    wMR, .L${opcode}_mark_after_load
+   SET_VREG_OBJECT w0, w2              // fp[A] <- value
+   .else
+   $volatile_load w0, [x0]
+   $maybe_extend
+   SET_VREG w0, w2                     // fp[A] <- value
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.L${opcode}_slow_path_read_barrier:
+   bl      art_quick_read_barrier_mark_reg00
+   b       .L${opcode}_slow_path_resume_after_read_barrier
+
+%def op_sget_wide():
+%  op_sget(load="ldr", volatile_load="ldar", maybe_extend="", wide="1", is_object="0")
+
+%def op_sget_object():
+%  op_sget(load="ldr", volatile_load="ldar", maybe_extend="", wide="0", is_object="1")
+
+%def op_sput_boolean():
+%  op_sput(store="strb", volatile_store="stlrb", wide="0", is_object="0")
+
+%def op_sput_byte():
+%  op_sput(store="strb", volatile_store="stlrb", wide="0", is_object="0")
+
+%def op_sput_char():
+%  op_sput(store="strh", volatile_store="stlrh", wide="0", is_object="0")
+
+%def op_sput_short():
+%  op_sput(store="strh", volatile_store="stlrh", wide="0", is_object="0")
+
+%def op_sput(store="str", volatile_store="stlr", wide="0", is_object="0"):
+   // Share slow paths for boolean and byte (strb) and slow paths for char and short (strh).
+   // It does not matter to which `.L${opcode}_resume` the slow path returns.
+%  slow_path = "nterp_op_sput_helper_" + store + wide + is_object
+%  add_helper(lambda: op_sput_slow_path(volatile_store, wide, is_object), slow_path)
+   lsr     w2, wINST, #8               // w2 <- A
+   .if $wide
+   GET_VREG_WIDE x26, w2               // x26 <- v[A]
+   .else
+   GET_VREG w26, w2                    // w26 <- v[A]
+   .endif
+   // Fast-path which gets the field from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x0, ${slow_path}
+.L${opcode}_resume:
+   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
+   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
+   cbnz    wMR, .L${opcode}_read_barrier
+.L${opcode}_resume_after_read_barrier:
+   .if $wide
+   $store  x26, [x0, x1]
+   .else
+   $store  w26, [x0, x1]
+   WRITE_BARRIER_IF_OBJECT $is_object, w26, w0, .L${opcode}_skip_write_barrier
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.L${opcode}_read_barrier:
+   bl      art_quick_read_barrier_mark_reg00
+   b       .L${opcode}_resume_after_read_barrier
+
+%def op_sput_slow_path(volatile_store, wide, is_object):
+   mov     x0, xSELF
+   ldr     x1, [sp]
+   mov     x2, xPC
+   .if $is_object
+   mov     x3, x26
+   .else
+   mov     x3, #0
+   .endif
+   EXPORT_PC
+   bl      nterp_get_static_field
+   .if $is_object
+   // Reload the value as it may have moved.
+   lsr     w2, wINST, #8               // w2 <- A
+   GET_VREG w26, w2                    // w26 <- v[A]
+   .endif
+   tbz     x0, #0, .L${opcode}_resume
+   CLEAR_STATIC_VOLATILE_MARKER x0
+   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
+   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
+   cbnz    wMR, .L${opcode}_slow_path_read_barrier
+.L${opcode}_slow_path_resume_after_read_barrier:
+   add     x1, x0, x1
+   .if $wide
+   $volatile_store    x26, [x1]
+   .else
+   $volatile_store    w26, [x1]
+   WRITE_BARRIER_IF_OBJECT $is_object, w26, w0, .L${opcode}_slow_path_skip_write_barrier
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.L${opcode}_slow_path_read_barrier:
+   bl      art_quick_read_barrier_mark_reg00
+   b       .L${opcode}_slow_path_resume_after_read_barrier
+
+%def op_sput_wide():
+%  op_sput(store="str", volatile_store="stlr", wide="1", is_object="0")
+
+%def op_sput_object():
+%  op_sput(store="str", volatile_store="stlr", wide="0", is_object="1")
+
+%def op_new_instance():
+   EXPORT_PC
+   // Fast-path which gets the class from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x0, 2f
+   cbnz    wMR, 3f
+4:
+   ldr     lr, [xSELF, #THREAD_ALLOC_OBJECT_ENTRYPOINT_OFFSET]
+   blr     lr
+1:
+   lsr     w1, wINST, #8               // w1 <- A
+   SET_VREG_OBJECT w0, w1              // fp[A] <- value
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+2:
+   mov     x0, xSELF
+   ldr     x1, [sp]
+   mov     x2, xPC
+   bl      nterp_get_class_or_allocate_object
+   b       1b
+3:
+   bl      art_quick_read_barrier_mark_reg00
+   b       4b
diff --git a/runtime/interpreter/mterp/arm64ng/other.S b/runtime/interpreter/mterp/arm64ng/other.S
new file mode 100644
index 0000000..caaec3d
--- /dev/null
+++ b/runtime/interpreter/mterp/arm64ng/other.S
@@ -0,0 +1,387 @@
+%def unused():
+    brk 42
+
+%def op_const():
+    /* const vAA, #+BBBBbbbb */
+    lsr     w3, wINST, #8               // w3<- AA
+    FETCH w0, 1                         // w0<- bbbb (low)
+    FETCH w1, 2                         // w1<- BBBB (high)
+    FETCH_ADVANCE_INST 3                // advance rPC, load wINST
+    orr     w0, w0, w1, lsl #16         // w0<- BBBBbbbb
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    SET_VREG w0, w3                     // vAA<- w0
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_const_16():
+    /* const/16 vAA, #+BBBB */
+    FETCH_S w0, 1                       // w0<- ssssBBBB (sign-extended)
+    lsr     w3, wINST, #8               // w3<- AA
+    FETCH_ADVANCE_INST 2                // advance xPC, load wINST
+    SET_VREG w0, w3                     // vAA<- w0
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_const_4():
+    /* const/4 vA, #+B */
+    sbfx    w1, wINST, #12, #4          // w1<- sssssssB
+    ubfx    w0, wINST, #8, #4           // w0<- A
+    FETCH_ADVANCE_INST 1                // advance xPC, load wINST
+    GET_INST_OPCODE ip                  // ip<- opcode from xINST
+    SET_VREG w1, w0                     // fp[A]<- w1
+    GOTO_OPCODE ip                      // execute next instruction
+
+%def op_const_high16():
+    /* const/high16 vAA, #+BBBB0000 */
+    FETCH   w0, 1                       // r0<- 0000BBBB (zero-extended)
+    lsr     w3, wINST, #8               // r3<- AA
+    lsl     w0, w0, #16                 // r0<- BBBB0000
+    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
+    SET_VREG w0, w3                     // vAA<- r0
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_const_object(jumbo="0", helper="nterp_load_object"):
+   // Fast-path which gets the object from thread-local cache.
+   FETCH_FROM_THREAD_CACHE x0, 2f
+   cbnz wMR, 3f
+1:
+   lsr     w1, wINST, #8               // w1<- AA
+   .if $jumbo
+   FETCH_ADVANCE_INST 3                // advance rPC, load wINST
+   .else
+   FETCH_ADVANCE_INST 2                // advance rPC, load wINST
+   .endif
+   GET_INST_OPCODE ip                  // extract opcode from wINST
+   SET_VREG_OBJECT w0, w1              // vAA <- value
+   GOTO_OPCODE ip                      // jump to next instruction
+2:
+   EXPORT_PC
+   mov x0, xSELF
+   ldr x1, [sp]
+   mov x2, xPC
+   bl $helper
+   b 1b
+3:
+   bl art_quick_read_barrier_mark_reg00
+   b 1b
+
+%def op_const_class():
+%  op_const_object(jumbo="0", helper="nterp_get_class_or_allocate_object")
+
+%def op_const_method_handle():
+%  op_const_object(jumbo="0")
+
+%def op_const_method_type():
+%  op_const_object(jumbo="0")
+
+%def op_const_string():
+   /* const/string vAA, String@BBBB */
+%  op_const_object(jumbo="0")
+
+%def op_const_string_jumbo():
+   /* const/string vAA, String@BBBBBBBB */
+%  op_const_object(jumbo="1")
+
+%def op_const_wide():
+    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
+    FETCH w0, 1                         // w0<- bbbb (low)
+    FETCH w1, 2                         // w1<- BBBB (low middle)
+    FETCH w2, 3                         // w2<- hhhh (high middle)
+    FETCH w3, 4                         // w3<- HHHH (high)
+    lsr     w4, wINST, #8               // r4<- AA
+    FETCH_ADVANCE_INST 5                // advance rPC, load wINST
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    orr     w0, w0, w1, lsl #16         // w0<-         BBBBbbbb
+    orr     x0, x0, x2, lsl #32         // w0<-     hhhhBBBBbbbb
+    orr     x0, x0, x3, lsl #48         // w0<- HHHHhhhhBBBBbbbb
+    SET_VREG_WIDE x0, w4
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_const_wide_16():
+    /* const-wide/16 vAA, #+BBBB */
+    FETCH_S x0, 1                       // x0<- ssssssssssssBBBB (sign-extended)
+    lsr     w3, wINST, #8               // w3<- AA
+    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    SET_VREG_WIDE x0, w3
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_const_wide_32():
+    /* const-wide/32 vAA, #+BBBBbbbb */
+    FETCH   w0, 1                       // x0<- 000000000000bbbb (low)
+    lsr     w3, wINST, #8               // w3<- AA
+    FETCH_S x2, 2                       // x2<- ssssssssssssBBBB (high)
+    FETCH_ADVANCE_INST 3                // advance rPC, load wINST
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    orr     x0, x0, x2, lsl #16         // x0<- ssssssssBBBBbbbb
+    SET_VREG_WIDE x0, w3
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_const_wide_high16():
+    /* const-wide/high16 vAA, #+BBBB000000000000 */
+    FETCH w0, 1                         // w0<- 0000BBBB (zero-extended)
+    lsr     w1, wINST, #8               // w1<- AA
+    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
+    lsl     x0, x0, #48
+    SET_VREG_WIDE x0, w1
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_monitor_enter():
+/*
+ * Synchronize on an object.
+ */
+    /* monitor-enter vAA */
+    EXPORT_PC
+    lsr      w2, wINST, #8               // w2<- AA
+    GET_VREG w0, w2
+    bl art_quick_lock_object
+    FETCH_ADVANCE_INST 1
+    GET_INST_OPCODE ip                   // extract opcode from rINST
+    GOTO_OPCODE ip                       // jump to next instruction
+
+%def op_monitor_exit():
+/*
+ * Unlock an object.
+ *
+ * Exceptions that occur when unlocking a monitor need to appear as
+ * if they happened at the following instruction.  See the Dalvik
+ * instruction spec.
+ */
+    /* monitor-exit vAA */
+    EXPORT_PC
+    lsr      w2, wINST, #8               // w2<- AA
+    GET_VREG w0, w2
+    bl art_quick_unlock_object
+    FETCH_ADVANCE_INST 1
+    GET_INST_OPCODE ip                   // extract opcode from rINST
+    GOTO_OPCODE ip                       // jump to next instruction
+
+%def op_move(is_object="0"):
+    /* for move, move-object, long-to-int */
+    /* op vA, vB */
+    lsr     w1, wINST, #12              // x1<- B from 15:12
+    ubfx    w0, wINST, #8, #4           // x0<- A from 11:8
+    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
+    GET_VREG w2, w1                     // x2<- fp[B]
+    GET_INST_OPCODE ip                  // ip<- opcode from wINST
+    .if $is_object
+    SET_VREG_OBJECT w2, w0              // fp[A]<- x2
+    .else
+    SET_VREG w2, w0                     // fp[A]<- x2
+    .endif
+    GOTO_OPCODE ip                      // execute next instruction
+
+%def op_move_16(is_object="0"):
+    /* for: move/16, move-object/16 */
+    /* op vAAAA, vBBBB */
+    FETCH w1, 2                         // w1<- BBBB
+    FETCH w0, 1                         // w0<- AAAA
+    FETCH_ADVANCE_INST 3                // advance xPC, load xINST
+    GET_VREG w2, w1                     // w2<- fp[BBBB]
+    GET_INST_OPCODE ip                  // extract opcode from xINST
+    .if $is_object
+    SET_VREG_OBJECT w2, w0              // fp[AAAA]<- w2
+    .else
+    SET_VREG w2, w0                     // fp[AAAA]<- w2
+    .endif
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_move_exception():
+    /* move-exception vAA */
+    lsr     w2, wINST, #8               // w2<- AA
+    ldr     x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
+    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
+    SET_VREG_OBJECT w3, w2              // fp[AA]<- exception obj
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    str     xzr, [xSELF, #THREAD_EXCEPTION_OFFSET]  // clear exception
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_move_from16(is_object="0"):
+    /* for: move/from16, move-object/from16 */
+    /* op vAA, vBBBB */
+    FETCH w1, 1                         // r1<- BBBB
+    lsr     w0, wINST, #8               // r0<- AA
+    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
+    GET_VREG w2, w1                     // r2<- fp[BBBB]
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    .if $is_object
+    SET_VREG_OBJECT w2, w0              // fp[AA]<- r2
+    .else
+    SET_VREG w2, w0                     // fp[AA]<- r2
+    .endif
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_move_object():
+%  op_move(is_object="1")
+
+%def op_move_object_16():
+%  op_move_16(is_object="1")
+
+%def op_move_object_from16():
+%  op_move_from16(is_object="1")
+
+%def op_move_result(is_object="0"):
+    /* for: move-result, move-result-object */
+    /* op vAA */
+    lsr     w2, wINST, #8               // r2<- AA
+    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    .if $is_object
+    SET_VREG_OBJECT w0, w2              // fp[AA]<- r0
+    .else
+    SET_VREG w0, w2                     // fp[AA]<- r0
+    .endif
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_move_result_object():
+%  op_move_result(is_object="1")
+
+%def op_move_result_wide():
+    /* for: move-result-wide */
+    /* op vAA */
+    lsr     w2, wINST, #8               // r2<- AA
+    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    SET_VREG_WIDE x0, w2                // fp[AA]<- r0
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_move_wide():
+    /* move-wide vA, vB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    lsr     w3, wINST, #12              // w3<- B
+    ubfx    w2, wINST, #8, #4           // w2<- A
+    GET_VREG_WIDE  x3, w3
+    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    SET_VREG_WIDE  x3, w2
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_move_wide_16():
+    /* move-wide/16 vAAAA, vBBBB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    FETCH w3, 2                         // w3<- BBBB
+    FETCH w2, 1                         // w2<- AAAA
+    GET_VREG_WIDE x3, w3
+    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
+    SET_VREG_WIDE x3, w2
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_move_wide_from16():
+    /* move-wide/from16 vAA, vBBBB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    FETCH w3, 1                         // w3<- BBBB
+    lsr     w2, wINST, #8               // w2<- AA
+    GET_VREG_WIDE x3, w3
+    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
+    GET_INST_OPCODE ip                  // extract opcode from wINST
+    SET_VREG_WIDE x3, w2
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_nop():
+    FETCH_ADVANCE_INST 1                // advance to next instr, load rINST
+    GET_INST_OPCODE ip                  // ip<- opcode from rINST
+    GOTO_OPCODE ip                      // execute it
+
+%def op_unused_3e():
+%  unused()
+
+%def op_unused_3f():
+%  unused()
+
+%def op_unused_40():
+%  unused()
+
+%def op_unused_41():
+%  unused()
+
+%def op_unused_42():
+%  unused()
+
+%def op_unused_43():
+%  unused()
+
+%def op_unused_73():
+%  unused()
+
+%def op_unused_79():
+%  unused()
+
+%def op_unused_7a():
+%  unused()
+
+%def op_unused_e3():
+%  unused()
+
+%def op_unused_e4():
+%  unused()
+
+%def op_unused_e5():
+%  unused()
+
+%def op_unused_e6():
+%  unused()
+
+%def op_unused_e7():
+%  unused()
+
+%def op_unused_e8():
+%  unused()
+
+%def op_unused_e9():
+%  unused()
+
+%def op_unused_ea():
+%  unused()
+
+%def op_unused_eb():
+%  unused()
+
+%def op_unused_ec():
+%  unused()
+
+%def op_unused_ed():
+%  unused()
+
+%def op_unused_ee():
+%  unused()
+
+%def op_unused_ef():
+%  unused()
+
+%def op_unused_f0():
+%  unused()
+
+%def op_unused_f1():
+%  unused()
+
+%def op_unused_f2():
+%  unused()
+
+%def op_unused_f3():
+%  unused()
+
+%def op_unused_f4():
+%  unused()
+
+%def op_unused_f5():
+%  unused()
+
+%def op_unused_f6():
+%  unused()
+
+%def op_unused_f7():
+%  unused()
+
+%def op_unused_f8():
+%  unused()
+
+%def op_unused_f9():
+%  unused()
+
+%def op_unused_fc():
+%  unused()
+
+%def op_unused_fd():
+%  unused()
diff --git a/runtime/interpreter/mterp/armng/arithmetic.S b/runtime/interpreter/mterp/armng/arithmetic.S
new file mode 100644
index 0000000..1cec598
--- /dev/null
+++ b/runtime/interpreter/mterp/armng/arithmetic.S
@@ -0,0 +1,986 @@
+%def binop(preinstr="", result="r0", chkzero="0", instr=""):
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG r1, r3                     @ r1<- vCC
+    GET_VREG r0, r2                     @ r0<- vBB
+    .if $chkzero
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    $preinstr                           @ optional op; may set condition codes
+    $instr                              @ $result<- op, r0-r3 changed
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG $result, r4                @ vAA<- $result
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 11-14 instructions */
+
+%def binop2addr(preinstr="", result="r0", chkzero="0", instr=""):
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    GET_VREG r1, r3                     @ r1<- vB
+    GET_VREG r0, r4                     @ r0<- vA
+    .if $chkzero
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+
+    $preinstr                           @ optional op; may set condition codes
+    $instr                              @ $result<- op, r0-r3 changed
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG $result, r4                @ vAA<- $result
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 10-13 instructions */
+
+%def binopLit16(result="r0", chkzero="0", instr=""):
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S r1, 1                       @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    GET_VREG r0, r2                     @ r0<- vB
+    .if $chkzero
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+
+    $instr                              @ $result<- op, r0-r3 changed
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG $result, r4                @ vAA<- $result
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 10-13 instructions */
+
+%def binopLit8(extract="asr     r1, r3, #8", result="r0", chkzero="0", instr=""):
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * You can override "extract" if the extraction of the literal value
+     * from r3 to r1 is not the default "asr r1, r3, #8". The extraction
+     * can be omitted completely if the shift is embedded in "instr".
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S r3, 1                       @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG r0, r2                     @ r0<- vBB
+    $extract                            @ optional; typically r1<- ssssssCC (sign extended)
+    .if $chkzero
+    @cmp     r1, #0                     @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+
+    $instr                              @ $result<- op, r0-r3 changed
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG $result, r4                @ vAA<- $result
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 10-12 instructions */
+
+%def binopWide(preinstr="", result0="r0", result1="r1", chkzero="0", instr=""):
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     rINST, rINST, lsr #8        @ rINST<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR r4, rINST        @ r4<- &fp[AA]
+    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &fp[BB]
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[CC]
+    GET_VREG_WIDE_BY_ADDR r0, r1, r2    @ r0/r1<- vBB/vBB+1
+    GET_VREG_WIDE_BY_ADDR r2, r3, r3    @ r2/r3<- vCC/vCC+1
+    .if $chkzero
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    CLEAR_SHADOW_PAIR rINST, lr, ip     @ Zero out the shadow regs
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    $preinstr                           @ optional op; may set condition codes
+    $instr                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR $result0,$result1,r4  @ vAA/vAA+1<,  $result0/$result1
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 14-17 instructions */
+
+%def binopWide2addr(preinstr="", result0="r0", result1="r1", chkzero="0", instr=""):
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    rINST, rINST, #8, #4        @ rINST<- A
+    VREG_INDEX_TO_ADDR r1, r1           @ r1<- &fp[B]
+    VREG_INDEX_TO_ADDR r4, rINST        @ r4<- &fp[A]
+    GET_VREG_WIDE_BY_ADDR r2, r3, r1    @ r2/r3<- vBB/vBB+1
+    GET_VREG_WIDE_BY_ADDR r0, r1, r4    @ r0/r1<- vAA/vAA+1
+    .if $chkzero
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    CLEAR_SHADOW_PAIR rINST, ip, lr     @ Zero shadow regs
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    $preinstr                           @ optional op; may set condition codes
+    $instr                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR $result0,$result1,r4  @ vAA/vAA+1<- $result0/$result1
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 12-15 instructions */
+
+%def unop(preinstr="", instr=""):
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    GET_VREG r0, r3                     @ r0<- vB
+    $preinstr                           @ optional op; may set condition codes
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    $instr                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r0, r4                     @ vAA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 8-9 instructions */
+
+%def unopNarrower(preinstr="", instr=""):
+    /*
+     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = op r0/r1", where
+     * "result" is a 32-bit quantity in r0.
+     *
+     * For: long-to-float
+     *
+     * (This would work for long-to-int, but that instruction is actually
+     * an exact match for op_move.)
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[B]
+    GET_VREG_WIDE_BY_ADDR r0, r1, r3    @ r0/r1<- vB/vB+1
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    $preinstr                           @ optional op; may set condition codes
+    $instr                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r0, r4                     @ vA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 9-10 instructions */
+
+%def unopWide(preinstr="", instr=""):
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    rINST, rINST, #8, #4        @ rINST<- A
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[B]
+    VREG_INDEX_TO_ADDR r4, rINST        @ r4<- &fp[A]
+    GET_VREG_WIDE_BY_ADDR r0, r1, r3    @ r0/r1<- vAA
+    CLEAR_SHADOW_PAIR rINST, ip, lr     @ Zero shadow regs
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    $preinstr                           @ optional op; may set condition codes
+    $instr                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r4    @ vAA<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 10-11 instructions */
+
+%def unopWider(preinstr="", instr=""):
+    /*
+     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = op r0", where
+     * "result" is a 64-bit quantity in r0/r1.
+     *
+     * For: int-to-long, int-to-double, float-to-long, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    rINST, rINST, #8, #4        @ rINST<- A
+    GET_VREG r0, r3                     @ r0<- vB
+    VREG_INDEX_TO_ADDR r4, rINST        @ r4<- &fp[A]
+    $preinstr                           @ optional op; may set condition codes
+    CLEAR_SHADOW_PAIR rINST, ip, lr     @ Zero shadow regs
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    $instr                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r4    @ vA/vA+1<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 9-10 instructions */
+
+%def op_add_int():
+%  binop(instr="add     r0, r0, r1")
+
+%def op_add_int_2addr():
+%  binop2addr(instr="add     r0, r0, r1")
+
+%def op_add_int_lit16():
+%  binopLit16(instr="add     r0, r0, r1")
+
+%def op_add_int_lit8():
+%  binopLit8(extract="", instr="add     r0, r0, r3, asr #8")
+
+%def op_add_long():
+%  binopWide(preinstr="adds    r0, r0, r2", instr="adc     r1, r1, r3")
+
+%def op_add_long_2addr():
+%  binopWide2addr(preinstr="adds    r0, r0, r2", instr="adc     r1, r1, r3")
+
+%def op_and_int():
+%  binop(instr="and     r0, r0, r1")
+
+%def op_and_int_2addr():
+%  binop2addr(instr="and     r0, r0, r1")
+
+%def op_and_int_lit16():
+%  binopLit16(instr="and     r0, r0, r1")
+
+%def op_and_int_lit8():
+%  binopLit8(extract="", instr="and     r0, r0, r3, asr #8")
+
+%def op_and_long():
+%  binopWide(preinstr="and     r0, r0, r2", instr="and     r1, r1, r3")
+
+%def op_and_long_2addr():
+%  binopWide2addr(preinstr="and     r0, r0, r2", instr="and     r1, r1, r3")
+
+%def op_cmp_long():
+    /*
+     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
+     * register based on the results of the comparison.
+     */
+    /* cmp-long vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &fp[BB]
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[CC]
+    GET_VREG_WIDE_BY_ADDR r0, r1, r2    @ r0/r1<- vBB/vBB+1
+    GET_VREG_WIDE_BY_ADDR r2, r3, r3    @ r2/r3<- vCC/vCC+1
+    cmp     r0, r2
+    sbcs    ip, r1, r3                  @ Sets correct CCs for checking LT (but not EQ/NE)
+    mov     r3, #-1
+    it      ge
+    movge   r3, #1
+    it      eq
+    cmpeq   r0, r2
+    it      eq
+    moveq   r3, #0
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    SET_VREG r3, r4                     @ vAA<- ip
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_div_int():
+    /*
+     * Specialized 32-bit binary operation
+     *
+     * Performs "r0 = r0 div r1". The selection between sdiv or the gcc helper
+     * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for
+     * ARMv7 CPUs that have hardware division support).
+     *
+     * div-int
+     *
+     */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG r1, r3                     @ r1<- vCC
+    GET_VREG r0, r2                     @ r0<- vBB
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+#ifdef __ARM_ARCH_EXT_IDIV__
+    sdiv    r0, r0, r1                  @ r0<- op
+#else
+    bl    __aeabi_idiv                  @ r0<- op, r0-r3 changed
+#endif
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r0, r4                     @ vAA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 11-14 instructions */
+
+%def op_div_int_2addr():
+    /*
+     * Specialized 32-bit binary operation
+     *
+     * Performs "r0 = r0 div r1". The selection between sdiv or the gcc helper
+     * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for
+     * ARMv7 CPUs that have hardware division support).
+     *
+     * div-int/2addr
+     *
+     */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    GET_VREG r1, r3                     @ r1<- vB
+    GET_VREG r0, r4                     @ r0<- vA
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+
+#ifdef __ARM_ARCH_EXT_IDIV__
+    sdiv    r0, r0, r1                  @ r0<- op
+#else
+    bl       __aeabi_idiv               @ r0<- op, r0-r3 changed
+#endif
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r0, r4                     @ vAA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 10-13 instructions */
+
+
+%def op_div_int_lit16():
+    /*
+     * Specialized 32-bit binary operation
+     *
+     * Performs "r0 = r0 div r1". The selection between sdiv or the gcc helper
+     * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for
+     * ARMv7 CPUs that have hardware division support).
+     *
+     * div-int/lit16
+     *
+     */
+    FETCH_S r1, 1                       @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    GET_VREG r0, r2                     @ r0<- vB
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+
+#ifdef __ARM_ARCH_EXT_IDIV__
+    sdiv    r0, r0, r1                  @ r0<- op
+#else
+    bl       __aeabi_idiv               @ r0<- op, r0-r3 changed
+#endif
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r0, r4                     @ vAA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 10-13 instructions */
+
+%def op_div_int_lit8():
+    /*
+     * Specialized 32-bit binary operation
+     *
+     * Performs "r0 = r0 div r1". The selection between sdiv or the gcc helper
+     * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for
+     * ARMv7 CPUs that have hardware division support).
+     *
+     * div-int/lit8
+     *
+     */
+    FETCH_S r3, 1                       @ r3<- ssssCCBB (sign-extended for CC
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG r0, r2                     @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    @cmp     r1, #0                     @ is second operand zero?
+    beq     common_errDivideByZero
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+
+#ifdef __ARM_ARCH_EXT_IDIV__
+    sdiv    r0, r0, r1                  @ r0<- op
+#else
+    bl   __aeabi_idiv                   @ r0<- op, r0-r3 changed
+#endif
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r0, r4                     @ vAA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 10-12 instructions */
+
+%def op_div_long():
+%  binopWide(instr="bl      __aeabi_ldivmod", chkzero="1")
+
+%def op_div_long_2addr():
+%  binopWide2addr(instr="bl      __aeabi_ldivmod", chkzero="1")
+
+%def op_int_to_byte():
+%  unop(instr="sxtb    r0, r0")
+
+%def op_int_to_char():
+%  unop(instr="uxth    r0, r0")
+
+%def op_int_to_long():
+%  unopWider(instr="mov     r1, r0, asr #31")
+
+%def op_int_to_short():
+%  unop(instr="sxth    r0, r0")
+
+%def op_long_to_int():
+/* we ignore the high word, making this equivalent to a 32-bit reg move */
+%  op_move()
+
+/*
+ * We use "mul r0, r1, r0" instead of "r0, r0, r1". The latter was illegal in old versions.
+ * Also, for T32, this operand order allows using a 16-bit instruction (encoding T1) while the
+ * other order would require 32-bit instruction (encoding T2).
+ */
+
+%def op_mul_int():
+%  binop(instr="mul     r0, r1, r0")
+
+%def op_mul_int_2addr():
+%  binop2addr(instr="mul     r0, r1, r0")
+
+%def op_mul_int_lit16():
+%  binopLit16(instr="mul     r0, r1, r0")
+
+%def op_mul_int_lit8():
+%  binopLit8(instr="mul     r0, r1, r0")
+
+%def op_mul_long():
+    /*
+     * Signed 64-bit integer multiply.
+     *
+     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
+     *        WX
+     *      x YZ
+     *  --------
+     *     ZW ZX
+     *  YW YX
+     *
+     * The low word of the result holds ZX, the high word holds
+     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
+     * it doesn't fit in the low 64 bits.
+     *
+     * Unlike most ARM math operations, multiply instructions have
+     * restrictions on using the same register more than once (Rd and Rn
+     * cannot be the same).
+     */
+    /* mul-long vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &fp[BB]
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[CC]
+    GET_VREG_WIDE_BY_ADDR r0, r1, r2    @ r0/r1<- vBB/vBB+1
+    GET_VREG_WIDE_BY_ADDR r2, r3, r3    @ r2/r3<- vCC/vCC+1
+    mul     ip, r0, r3                  @ ip<- YxX
+    umull   r0, lr, r2, r0              @ r0/lr <- ZxX RdLo == Rn - this is OK.
+    mla     r3, r1, r2, ip              @ r3<- YxX + (ZxW)
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    add     r1, r3, lr                  @ r1<- lr + low(ZxW + (YxX))
+    CLEAR_SHADOW_PAIR r4, lr, ip        @ Zero out the shadow regs
+    VREG_INDEX_TO_ADDR r4, r4           @ r2<- &fp[AA]
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1 , r4   @ vAA/vAA+1<- r1/r2
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_mul_long_2addr():
+    /*
+     * Signed 64-bit integer multiply, "/2addr" version.
+     *
+     * See op_mul_long for an explanation.
+     *
+     * We get a little tight on registers, so to avoid looking up &fp[A]
+     * again we stuff it into rINST.
+     */
+    /* mul-long/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    VREG_INDEX_TO_ADDR r1, r1           @ r1<- &fp[B]
+    VREG_INDEX_TO_ADDR rINST, r4        @ rINST<- &fp[A]
+    GET_VREG_WIDE_BY_ADDR r2, r3, r1    @ r2/r3<- vBB/vBB+1
+    GET_VREG_WIDE_BY_ADDR r0, r1, rINST @ r0/r1<- vAA/vAA+1
+    mul     ip, r0, r3                  @ ip<- YxX
+    umull   r0, lr, r2, r0              @ r0/lr <- ZxX RdLo == Rn - this is OK.
+    mla     r3, r1, r2, ip              @ r3<- YxX + (ZxW)
+    mov     r4, rINST                   @ Save vAA before FETCH_ADVANCE_INST
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    add     r1, r3, lr                  @ r1<- lr + low(ZxW + (YxX))
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r4    @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_neg_int():
+%  unop(instr="rsb     r0, r0, #0")
+
+%def op_neg_long():
+%  unopWide(preinstr="rsbs    r0, r0, #0", instr="rsc     r1, r1, #0")
+
+%def op_not_int():
+%  unop(instr="mvn     r0, r0")
+
+%def op_not_long():
+%  unopWide(preinstr="mvn     r0, r0", instr="mvn     r1, r1")
+
+%def op_or_int():
+%  binop(instr="orr     r0, r0, r1")
+
+%def op_or_int_2addr():
+%  binop2addr(instr="orr     r0, r0, r1")
+
+%def op_or_int_lit16():
+%  binopLit16(instr="orr     r0, r0, r1")
+
+%def op_or_int_lit8():
+%  binopLit8(extract="", instr="orr     r0, r0, r3, asr #8")
+
+%def op_or_long():
+%  binopWide(preinstr="orr     r0, r0, r2", instr="orr     r1, r1, r3")
+
+%def op_or_long_2addr():
+%  binopWide2addr(preinstr="orr     r0, r0, r2", instr="orr     r1, r1, r3")
+
+%def op_rem_int():
+    /*
+     * Specialized 32-bit binary operation
+     *
+     * Performs "r1 = r0 rem r1". The selection between sdiv block or the gcc helper
+     * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for
+     * ARMv7 CPUs that have hardware division support).
+     *
+     * NOTE: idivmod returns quotient in r0 and remainder in r1
+     *
+     * rem-int
+     *
+     */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG r1, r3                     @ r1<- vCC
+    GET_VREG r0, r2                     @ r0<- vBB
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+#ifdef __ARM_ARCH_EXT_IDIV__
+    sdiv    r2, r0, r1
+    mls     r1, r1, r2, r0                 @ r1<- op, r0-r2 changed
+#else
+    bl      __aeabi_idivmod                @ r1<- op, r0-r3 changed
+#endif
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r1, r4                     @ vAA<- r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 11-14 instructions */
+
+%def op_rem_int_2addr():
+    /*
+     * Specialized 32-bit binary operation
+     *
+     * Performs "r1 = r0 rem r1". The selection between sdiv block or the gcc helper
+     * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for
+     * ARMv7 CPUs that have hardware division support).
+     *
+     * NOTE: idivmod returns quotient in r0 and remainder in r1
+     *
+     * rem-int/2addr
+     *
+     */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    GET_VREG r1, r3                     @ r1<- vB
+    GET_VREG r0, r4                     @ r0<- vA
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+
+#ifdef __ARM_ARCH_EXT_IDIV__
+    sdiv    r2, r0, r1
+    mls     r1, r1, r2, r0              @ r1<- op
+#else
+    bl      __aeabi_idivmod             @ r1<- op, r0-r3 changed
+#endif
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r1, r4                     @ vAA<- r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 10-13 instructions */
+
+
+%def op_rem_int_lit16():
+    /*
+     * Specialized 32-bit binary operation
+     *
+     * Performs "r1 = r0 rem r1". The selection between sdiv block or the gcc helper
+     * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for
+     * ARMv7 CPUs that have hardware division support).
+     *
+     * NOTE: idivmod returns quotient in r0 and remainder in r1
+     *
+     * rem-int/lit16
+     *
+     */
+    FETCH_S r1, 1                       @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    GET_VREG r0, r2                     @ r0<- vB
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+
+#ifdef __ARM_ARCH_EXT_IDIV__
+    sdiv    r2, r0, r1
+    mls     r1, r1, r2, r0              @ r1<- op
+#else
+    bl     __aeabi_idivmod              @ r1<- op, r0-r3 changed
+#endif
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r1, r4                     @ vAA<- r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 10-13 instructions */
+
+%def op_rem_int_lit8():
+    /*
+     * Specialized 32-bit binary operation
+     *
+     * Performs "r1 = r0 rem r1". The selection between sdiv block or the gcc helper
+     * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for
+     * ARMv7 CPUs that have hardware division support).
+     *
+     * NOTE: idivmod returns quotient in r0 and remainder in r1
+     *
+     * rem-int/lit8
+     *
+     */
+    FETCH_S r3, 1                       @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG r0, r2                     @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    @cmp     r1, #0                     @ is second operand zero?
+    beq     common_errDivideByZero
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+
+#ifdef __ARM_ARCH_EXT_IDIV__
+    sdiv    r2, r0, r1
+    mls     r1, r1, r2, r0              @ r1<- op
+#else
+    bl       __aeabi_idivmod            @ r1<- op, r0-r3 changed
+#endif
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r1, r4                     @ vAA<- r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+    /* 10-12 instructions */
+
+%def op_rem_long():
+/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
+%  binopWide(instr="bl      __aeabi_ldivmod", result0="r2", result1="r3", chkzero="1")
+
+%def op_rem_long_2addr():
+/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
+%  binopWide2addr(instr="bl      __aeabi_ldivmod", result0="r2", result1="r3", chkzero="1")
+
+%def op_rsub_int():
+/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
+%  binopLit16(instr="rsb     r0, r0, r1")
+
+%def op_rsub_int_lit8():
+%  binopLit8(extract="", instr="rsb     r0, r0, r3, asr #8")
+
+%def op_shl_int():
+%  binop(preinstr="and     r1, r1, #31", instr="mov     r0, r0, lsl r1")
+
+%def op_shl_int_2addr():
+%  binop2addr(preinstr="and     r1, r1, #31", instr="mov     r0, r0, lsl r1")
+
+%def op_shl_int_lit8():
+%  binopLit8(extract="ubfx    r1, r3, #8, #5", instr="mov     r0, r0, lsl r1")
+
+%def op_shl_long():
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
+     * 6 bits of the shift distance.
+     */
+    /* shl-long vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r3, r0, #255                @ r3<- BB
+    mov     r0, r0, lsr #8              @ r0<- CC
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[BB]
+    GET_VREG r2, r0                     @ r2<- vCC
+    GET_VREG_WIDE_BY_ADDR r0, r1, r3    @ r0/r1<- vBB/vBB+1
+    CLEAR_SHADOW_PAIR r4, lr, ip        @ Zero out the shadow regs
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[AA]
+    mov     r1, r1, asl r2              @ r1<- r1 << r2
+    rsb     r3, r2, #32                 @ r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @ r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @ ip<- r2 - 32
+    it      pl
+    movpl   r1, r0, asl ip              @ if r2 >= 32, r1<- r0 << (r2-32)
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    mov     r0, r0, asl r2              @ r0<- r0 << r2
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r4    @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_shl_long_2addr():
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* shl-long/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    GET_VREG r2, r3                     @ r2<- vB
+    CLEAR_SHADOW_PAIR r4, lr, ip        @ Zero out the shadow regs
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    GET_VREG_WIDE_BY_ADDR r0, r1, r4    @ r0/r1<- vAA/vAA+1
+    mov     r1, r1, asl r2              @ r1<- r1 << r2
+    rsb     r3, r2, #32                 @ r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @ r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @ ip<- r2 - 32
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    it      pl
+    movpl   r1, r0, asl ip              @ if r2 >= 32, r1<- r0 << (r2-32)
+    mov     r0, r0, asl r2              @ r0<- r0 << r2
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r4    @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_shr_int():
+%  binop(preinstr="and     r1, r1, #31", instr="mov     r0, r0, asr r1")
+
+%def op_shr_int_2addr():
+%  binop2addr(preinstr="and     r1, r1, #31", instr="mov     r0, r0, asr r1")
+
+%def op_shr_int_lit8():
+%  binopLit8(extract="ubfx    r1, r3, #8, #5", instr="mov     r0, r0, asr r1")
+
+%def op_shr_long():
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
+     * 6 bits of the shift distance.
+     */
+    /* shr-long vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r3, r0, #255                @ r3<- BB
+    mov     r0, r0, lsr #8              @ r0<- CC
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[BB]
+    GET_VREG r2, r0                     @ r2<- vCC
+    GET_VREG_WIDE_BY_ADDR r0, r1, r3    @ r0/r1<- vBB/vBB+1
+    CLEAR_SHADOW_PAIR r4, lr, ip        @ Zero out the shadow regs
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[AA]
+    mov     r0, r0, lsr r2              @ r0<- r2 >> r2
+    rsb     r3, r2, #32                 @ r3<- 32 - r2
+    orr     r0, r0, r1, lsl r3          @ r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @ ip<- r2 - 32
+    it      pl
+    movpl   r0, r1, asr ip              @ if r2 >= 32, r0<-r1 >> (r2-32)
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    mov     r1, r1, asr r2              @ r1<- r1 >> r2
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r4    @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_shr_long_2addr():
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* shr-long/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    GET_VREG r2, r3                     @ r2<- vB
+    CLEAR_SHADOW_PAIR r4, lr, ip        @ Zero out the shadow regs
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    GET_VREG_WIDE_BY_ADDR r0, r1, r4    @ r0/r1<- vAA/vAA+1
+    mov     r0, r0, lsr r2              @ r0<- r2 >> r2
+    rsb     r3, r2, #32                 @ r3<- 32 - r2
+    orr     r0, r0, r1, lsl r3          @ r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @ ip<- r2 - 32
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    it      pl
+    movpl   r0, r1, asr ip              @ if r2 >= 32, r0<-r1 >> (r2-32)
+    mov     r1, r1, asr r2              @ r1<- r1 >> r2
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r4    @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_sub_int():
+%  binop(instr="sub     r0, r0, r1")
+
+%def op_sub_int_2addr():
+%  binop2addr(instr="sub     r0, r0, r1")
+
+%def op_sub_long():
+%  binopWide(preinstr="subs    r0, r0, r2", instr="sbc     r1, r1, r3")
+
+%def op_sub_long_2addr():
+%  binopWide2addr(preinstr="subs    r0, r0, r2", instr="sbc     r1, r1, r3")
+
+%def op_ushr_int():
+%  binop(preinstr="and     r1, r1, #31", instr="mov     r0, r0, lsr r1")
+
+%def op_ushr_int_2addr():
+%  binop2addr(preinstr="and     r1, r1, #31", instr="mov     r0, r0, lsr r1")
+
+%def op_ushr_int_lit8():
+%  binopLit8(extract="ubfx    r1, r3, #8, #5", instr="mov     r0, r0, lsr r1")
+
+%def op_ushr_long():
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
+     * 6 bits of the shift distance.
+     */
+    /* ushr-long vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r3, r0, #255                @ r3<- BB
+    mov     r0, r0, lsr #8              @ r0<- CC
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[BB]
+    GET_VREG r2, r0                     @ r2<- vCC
+    GET_VREG_WIDE_BY_ADDR r0, r1, r3    @ r0/r1<- vBB/vBB+1
+    CLEAR_SHADOW_PAIR r4, lr, ip        @ Zero out the shadow regs
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[AA]
+    mov     r0, r0, lsr r2              @ r0<- r2 >> r2
+    rsb     r3, r2, #32                 @ r3<- 32 - r2
+    orr     r0, r0, r1, lsl r3          @ r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @ ip<- r2 - 32
+    it      pl
+    movpl   r0, r1, lsr ip              @ if r2 >= 32, r0<-r1 >>> (r2-32)
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    mov     r1, r1, lsr r2              @ r1<- r1 >>> r2
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r4    @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_ushr_long_2addr():
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* ushr-long/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    GET_VREG r2, r3                     @ r2<- vB
+    CLEAR_SHADOW_PAIR r4, lr, ip        @ Zero out the shadow regs
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    GET_VREG_WIDE_BY_ADDR r0, r1, r4    @ r0/r1<- vAA/vAA+1
+    mov     r0, r0, lsr r2              @ r0<- r2 >> r2
+    rsb     r3, r2, #32                 @ r3<- 32 - r2
+    orr     r0, r0, r1, lsl r3          @ r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @ ip<- r2 - 32
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    it      pl
+    movpl   r0, r1, lsr ip              @ if r2 >= 32, r0<-r1 >>> (r2-32)
+    mov     r1, r1, lsr r2              @ r1<- r1 >>> r2
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r4    @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_xor_int():
+%  binop(instr="eor     r0, r0, r1")
+
+%def op_xor_int_2addr():
+%  binop2addr(instr="eor     r0, r0, r1")
+
+%def op_xor_int_lit16():
+%  binopLit16(instr="eor     r0, r0, r1")
+
+%def op_xor_int_lit8():
+%  binopLit8(extract="", instr="eor     r0, r0, r3, asr #8")
+
+%def op_xor_long():
+%  binopWide(preinstr="eor     r0, r0, r2", instr="eor     r1, r1, r3")
+
+%def op_xor_long_2addr():
+%  binopWide2addr(preinstr="eor     r0, r0, r2", instr="eor     r1, r1, r3")
diff --git a/runtime/interpreter/mterp/armng/array.S b/runtime/interpreter/mterp/armng/array.S
new file mode 100644
index 0000000..93f11c6
--- /dev/null
+++ b/runtime/interpreter/mterp/armng/array.S
@@ -0,0 +1,171 @@
+%def op_aget(load="ldr", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="0"):
+/*
+ * Array get.  vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
+ *
+ */
+    FETCH_B r2, 1, 0                    @ r2<- BB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    FETCH_B r3, 1, 1                    @ r3<- CC
+    GET_VREG r0, r2                     @ r0<- vBB (array object)
+    GET_VREG r1, r3                     @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #$shift     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    .if $wide
+    CLEAR_SHADOW_PAIR r4, lr, ip        @ Zero out the shadow regs
+    ldrd    r2, [r0, #$data_offset]     @ r2/r3<- vBB[vCC]
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[AA]
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r2, r3, r4    @ vAA/vAA+1<- r2/r3
+    GOTO_OPCODE ip                      @ jump to next instruction
+    .elseif $is_object
+    $load   r2, [r0, #$data_offset]     @ w2<- vBB[vCC]
+    cmp rMR, #0
+    bne 2f
+1:
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_OBJECT r2, r4              @ vAA<- w2
+    GOTO_OPCODE ip                      @ jump to next instruction
+2:
+    bl art_quick_read_barrier_mark_reg02
+    b 1b
+    .else
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    $load   r2, [r0, #$data_offset]     @ r2<- vBB[vCC]
+    SET_VREG r2, r4                     @ vAA<- r2
+    GOTO_OPCODE ip                      @ jump to next instruction
+    .endif
+
+%def op_aget_boolean():
+%  op_aget(load="ldrb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aget_byte():
+%  op_aget(load="ldrsb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aget_char():
+%  op_aget(load="ldrh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aget_object():
+%  op_aget(load="ldr", shift="2", data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET", wide="0", is_object="1")
+
+%def op_aget_short():
+%  op_aget(load="ldrsh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aget_wide():
+%  op_aget(load="ldrd", shift="3", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1", is_object="0")
+
+%def op_aput(store="str", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="0"):
+/*
+ * Array put.  vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
+ *
+ */
+    FETCH_B r2, 1, 0                    @ r2<- BB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    FETCH_B r3, 1, 1                    @ r3<- CC
+    GET_VREG r0, r2                     @ r0<- vBB (array object)
+    GET_VREG r1, r3                     @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET]     @ r3<- arrayObj->length
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    .if $is_object
+    EXPORT_PC                           // Export PC before overwriting it.
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    GET_VREG r2, r4                     @ r2<- vAA
+    bl art_quick_aput_obj
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    .elseif $wide
+    add     r0, r0, r1, lsl #$shift     @ r0<- arrayObj + index*width
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[AA]
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    GET_VREG_WIDE_BY_ADDR r2, r3, r4    @ r2/r3<- vAA/vAA+1
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    strd    r2, [r0, #$data_offset]     @ r2/r3<- vBB[vCC]
+    .else
+    add     r0, r0, r1, lsl #$shift     @ r0<- arrayObj + index*width
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    GET_VREG r2, r4                     @ r2<- vAA
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    $store  r2, [r0, #$data_offset]     @ vBB[vCC]<- r2
+    .endif
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_aput_boolean():
+%  op_aput(store="strb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aput_byte():
+%  op_aput(store="strb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aput_char():
+%  op_aput(store="strh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aput_short():
+%  op_aput(store="strh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET", wide="0", is_object="0")
+
+%def op_aput_wide():
+%  op_aput(store="str", shift="3", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1", is_object="0")
+
+%def op_aput_object():
+%  op_aput(store="str", shift="2", data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET", wide="0", is_object="1")
+
+%def op_array_length():
+    /*
+     * Return the length of an array.
+     */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    GET_VREG r0, r1                     @ r0<- vB (object ref)
+    cmp     r0, #0                      @ is object null?
+    beq     common_errNullObject        @ yup, fail
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    ldr     r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET]    @ r3<- array length
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r3, r2                     @ vB<- length
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_fill_array_data():
+    /* fill-array-data vAA, +BBBBBBBB */
+    EXPORT_PC
+    FETCH r0, 1                         @ r0<- bbbb (lo)
+    FETCH r1, 2                         @ r1<- BBBB (hi)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
+    GET_VREG r1, r3                     @ r1<- vAA (array object)
+    add     r0, rPC, r0, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
+    bl      art_quick_handle_fill_data  @ (payload, object)
+    FETCH_ADVANCE_INST 3                @ advance rPC, load rINST
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_filled_new_array(helper="nterp_filled_new_array"):
+/*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
+    EXPORT_PC
+    mov     r0, rSELF
+    ldr     r1, [sp]
+    mov     r2, rFP
+    mov     r3, rPC
+    bl      $helper
+    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    GOTO_OPCODE ip                      // jump to next instruction
+
+%def op_filled_new_array_range():
+%  op_filled_new_array(helper="nterp_filled_new_array_range")
+
+%def op_new_array():
+  b NterpNewArray
diff --git a/runtime/interpreter/mterp/armng/control_flow.S b/runtime/interpreter/mterp/armng/control_flow.S
new file mode 100644
index 0000000..ab05228
--- /dev/null
+++ b/runtime/interpreter/mterp/armng/control_flow.S
@@ -0,0 +1,187 @@
+%def bincmp(condition=""):
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "condition"
+     * fragment that specifies the comparison to perform.
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    GET_VREG r3, r1                     @ r3<- vB
+    GET_VREG r0, r0                     @ r0<- vA
+    FETCH_S rINST, 1                    @ rINST<- branch offset, in code units
+    cmp     r0, r3                      @ compare (vA, vB)
+    b${condition} 1f
+    FETCH_ADVANCE_INST 2
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    GOTO_OPCODE ip                      // jump to next instruction
+1:
+    FETCH_S rINST, 1                    // rINST<- branch offset, in code units
+    BRANCH
+
+%def zcmp(condition=""):
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "condition"
+     * fragment that specifies the comparison to perform.
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG r0, r0                     @ r0<- vAA
+    FETCH_S rINST, 1                    @ rINST<- branch offset, in code units
+    cmp     r0, #0                      // compare (vA, 0)
+    b${condition} 1f
+    FETCH_ADVANCE_INST 2
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    GOTO_OPCODE ip                      // jump to next instruction
+1:
+    FETCH_S rINST, 1                    // rINST<- branch offset, in code units
+    BRANCH
+
+%def op_goto():
+/*
+ * Unconditional branch, 8-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+    /* goto +AA */
+    sbfx    rINST, rINST, #8, #8           // rINST<- ssssssAA (sign-extended)
+    BRANCH
+
+%def op_goto_16():
+/*
+ * Unconditional branch, 16-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+    /* goto/16 +AAAA */
+    FETCH_S rINST, 1                    // wINST<- ssssAAAA (sign-extended)
+    BRANCH
+
+%def op_goto_32():
+/*
+ * Unconditional branch, 32-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ *
+ * Because we need the SF bit set, we'll use an adds
+ * to convert from Dalvik offset to byte offset.
+ */
+    /* goto/32 +AAAAAAAA */
+    FETCH r0, 1                         // r0<- aaaa (lo)
+    FETCH r1, 2                         // r1<- AAAA (hi)
+    orrs     rINST, r0, r1, lsl #16      // wINST<- AAAAaaaa
+    BRANCH
+
+%def op_if_eq():
+%  bincmp(condition="eq")
+
+%def op_if_eqz():
+%  zcmp(condition="eq")
+
+%def op_if_ge():
+%  bincmp(condition="ge")
+
+%def op_if_gez():
+%  zcmp(condition="ge")
+
+%def op_if_gt():
+%  bincmp(condition="gt")
+
+%def op_if_gtz():
+%  zcmp(condition="gt")
+
+%def op_if_le():
+%  bincmp(condition="le")
+
+%def op_if_lez():
+%  zcmp(condition="le")
+
+%def op_if_lt():
+%  bincmp(condition="lt")
+
+%def op_if_ltz():
+%  zcmp(condition="lt")
+
+%def op_if_ne():
+%  bincmp(condition="ne")
+
+%def op_if_nez():
+%  zcmp(condition="ne")
+
+%def op_packed_switch(func="NterpDoPackedSwitch"):
+/*
+ * Handle a packed-switch or sparse-switch instruction.  In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+    /* op vAA, +BBBB */
+    FETCH r0, 1                         @ r0<- bbbb (lo)
+    FETCH r1, 2                         @ r1<- BBBB (hi)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
+    GET_VREG r1, r3                     @ r1<- vAA
+    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
+    bl      $func                       @ r0<- code-unit branch offset
+    mov     rINST, r0
+    BRANCH
+
+%def op_sparse_switch():
+%  op_packed_switch(func="NterpDoSparseSwitch")
+
+/*
+ * Return a 32-bit value.
+ */
+%def op_return(is_object="0", is_void="0", is_wide="0"):
+    .if $is_void
+      // Thread fence for constructor
+      dmb ishst
+    .else
+      mov     r2, rINST, lsr #8           @ r2<- AA
+      .if $is_wide
+        VREG_INDEX_TO_ADDR r2, r2
+        GET_VREG_WIDE_BY_ADDR r0, r1, r2 // r0,r1 <- vAA
+        // In case we're going back to compiled code, put the
+        // result also in d0.
+        vmov d0, r0, r1
+      .else
+        GET_VREG r0, r2                     // r0<- vAA
+        .if !$is_object
+        // In case we're going back to compiled code, put the
+        // result also in s0.
+        vmov s0, r0
+        .endif
+      .endif
+    .endif
+    .cfi_remember_state
+    ldr ip, [rREFS, #-4]
+    mov sp, ip
+    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
+    RESTORE_ALL_CALLEE_SAVES lr_to_pc=1
+    .cfi_restore_state
+
+%def op_return_object():
+%  op_return(is_object="1", is_void="0", is_wide="0")
+
+%def op_return_void():
+%  op_return(is_object="0", is_void="1", is_wide="0")
+
+%def op_return_wide():
+%  op_return(is_object="0", is_void="0", is_wide="1")
+
+%def op_throw():
+  EXPORT_PC
+  mov      r2, rINST, lsr #8           @ r2<- AA
+  GET_VREG r0, r2                      @ r0<- vAA (exception object)
+  mov r1, rSELF
+  bl art_quick_deliver_exception
+  bkpt 0
diff --git a/runtime/interpreter/mterp/armng/floating_point.S b/runtime/interpreter/mterp/armng/floating_point.S
new file mode 100644
index 0000000..5052f13
--- /dev/null
+++ b/runtime/interpreter/mterp/armng/floating_point.S
@@ -0,0 +1,424 @@
+%def fbinop(instr=""):
+    /*
+     * Generic 32-bit floating-point operation.  Provide an "instr" line that
+     * specifies an instruction that performs "s2 = s0 op s1".  Because we
+     * use the "softfp" ABI, this must be an instruction, not a function call.
+     *
+     * For: add-float, sub-float, mul-float, div-float
+     */
+    /* floatop vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
+    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
+    GET_VREG_FLOAT_BY_ADDR s1, r3       @ s1<- vCC
+    GET_VREG_FLOAT_BY_ADDR s0, r2       @ s0<- vBB
+
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    $instr                              @ s2<- op
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_FLOAT s2, r4, lr           @ vAA<- s2
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def fbinop2addr(instr=""):
+    /*
+     * Generic 32-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "s2 = s0 op s1".
+     *
+     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vB
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &vA
+    GET_VREG_FLOAT_BY_ADDR s1, r3       @ s1<- vB
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    GET_VREG_FLOAT_BY_ADDR s0, r4       @ s0<- vA
+    $instr                              @ s2<- op
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_FLOAT_BY_ADDR s2, r4       @ vAA<- s2 No need to clear as it's 2addr
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def fbinopWide(instr=""):
+    /*
+     * Generic 64-bit double-precision floating point binary operation.
+     * Provide an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * for: add-double, sub-double, mul-double, div-double
+     */
+    /* doubleop vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
+    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
+    GET_VREG_DOUBLE_BY_ADDR d1, r3      @ d1<- vCC
+    GET_VREG_DOUBLE_BY_ADDR d0, r2      @ d0<- vBB
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    $instr                              @ d2<- op
+    CLEAR_SHADOW_PAIR r4, ip, lr        @ Zero shadow regs
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &vAA
+    SET_VREG_DOUBLE_BY_ADDR d2, r4      @ vAA<- d2
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def fbinopWide2addr(instr=""):
+    /*
+     * Generic 64-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+     *      div-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vB
+    CLEAR_SHADOW_PAIR r4, ip, r0        @ Zero out shadow regs
+    GET_VREG_DOUBLE_BY_ADDR d1, r3      @ d1<- vB
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &vA
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    GET_VREG_DOUBLE_BY_ADDR d0, r4      @ d0<- vA
+    $instr                              @ d2<- op
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_DOUBLE_BY_ADDR d2, r4      @ vAA<- d2
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def funop(instr=""):
+    /*
+     * Generic 32-bit unary floating-point operation.  Provide an "instr"
+     * line that specifies an instruction that performs "s1 = op s0".
+     *
+     * for: int-to-float, float-to-int
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vB
+    GET_VREG_FLOAT_BY_ADDR s0, r3       @ s0<- vB
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    $instr                              @ s1<- op
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_FLOAT s1, r4, lr           @ vA<- s1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def funopNarrower(instr=""):
+    /*
+     * Generic 64bit-to-32bit unary floating point operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vB
+    GET_VREG_DOUBLE_BY_ADDR d0, r3      @ d0<- vB
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    $instr                              @ s0<- op
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_FLOAT s0, r4, lr           @ vA<- s0
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def funopWider(instr=""):
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vB
+    GET_VREG_FLOAT_BY_ADDR s0, r3       @ s0<- vB
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    $instr                              @ d0<- op
+    CLEAR_SHADOW_PAIR r4, ip, lr        @ Zero shadow regs
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &vA
+    SET_VREG_DOUBLE_BY_ADDR d0, r4      @ vA<- d0
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_add_double():
+%  fbinopWide(instr="faddd   d2, d0, d1")
+
+%def op_add_double_2addr():
+%  fbinopWide2addr(instr="faddd   d2, d0, d1")
+
+%def op_add_float():
+%  fbinop(instr="fadds   s2, s0, s1")
+
+%def op_add_float_2addr():
+%  fbinop2addr(instr="fadds   s2, s0, s1")
+
+%def op_cmpg_double():
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
+    GET_VREG_DOUBLE_BY_ADDR d0, r2      @ d0<- vBB
+    GET_VREG_DOUBLE_BY_ADDR d1, r3      @ d1<- vCC
+    vcmpe.f64 d0, d1                    @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    mvn     r0, #0                      @ r0<- -1 (default)
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    fmstat
+    it      hi
+    movhi   r0, #1                      @ (greater than, or unordered) r0<- 1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    SET_VREG r0, r4                     @ vAA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_cmpg_float():
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
+    GET_VREG_FLOAT_BY_ADDR s0, r2       @ s0<- vBB
+    GET_VREG_FLOAT_BY_ADDR s1, r3       @ s1<- vCC
+    vcmpe.f32 s0, s1                    @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    mvn     r0, #0                      @ r0<- -1 (default)
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    fmstat
+    it      hi
+    movhi   r0, #1                      @ (greater than, or unordered) r0<- 1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    SET_VREG r0, r4                     @ vAA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_cmpl_double():
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
+    GET_VREG_DOUBLE_BY_ADDR d0, r2      @ d0<- vBB
+    GET_VREG_DOUBLE_BY_ADDR d1, r3      @ d1<- vCC
+    vcmpe.f64 d0, d1                    @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    mvn     r0, #0                      @ r0<- -1 (default)
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    fmstat                              @ export status flags
+    it gt
+    movgt   r0, #1                      @ (greater than) r1<- 1
+    it eq
+    moveq   r0, #0                      @ (equal) r1<- 0
+    SET_VREG r0, r4                     @ vAA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_cmpl_float():
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH r0, 1                         @ r0<- CCBB
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
+    GET_VREG_FLOAT_BY_ADDR s0, r2       @ s0<- vBB
+    GET_VREG_FLOAT_BY_ADDR s1, r3       @ s1<- vCC
+    vcmpe.f32  s0, s1                   @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    mvn     r0, #0                      @ r0<- -1 (default)
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    fmstat                              @ export status flags
+    it gt
+    movgt   r0, #1                      @ (greater than) r1<- 1
+    it eq
+    moveq   r0, #0                      @ (equal) r1<- 0
+    SET_VREG r0, r4                     @ vAA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_div_double():
+%  fbinopWide(instr="fdivd   d2, d0, d1")
+
+%def op_div_double_2addr():
+%  fbinopWide2addr(instr="fdivd   d2, d0, d1")
+
+%def op_div_float():
+%  fbinop(instr="fdivs   s2, s0, s1")
+
+%def op_div_float_2addr():
+%  fbinop2addr(instr="fdivs   s2, s0, s1")
+
+%def op_double_to_float():
+%  funopNarrower(instr="vcvt.f32.f64  s0, d0")
+
+%def op_double_to_int():
+%  funopNarrower(instr="vcvt.s32.f64  s0, d0")
+
+%def op_double_to_long():
+%  unopWide(instr="bl      nterp_d2l_doconv")
+
+%def op_float_to_double():
+%  funopWider(instr="vcvt.f64.f32  d0, s0")
+
+%def op_float_to_int():
+%  funop(instr="vcvt.s32.f32 s1, s0")
+
+%def op_float_to_long():
+%  unopWider(instr="bl      nterp_f2l_doconv")
+
+%def op_int_to_double():
+%  funopWider(instr="vcvt.f64.s32  d0, s0")
+
+%def op_int_to_float():
+%  funop(instr="vcvt.f32.s32  s1, s0")
+
+%def op_long_to_double():
+    /*
+     * Specialised 64-bit floating point operation.
+     *
+     * Note: The result will be returned in d2.
+     *
+     * For: long-to-double
+     */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r4, rINST, #8, #4           @ r4<- A
+    CLEAR_SHADOW_PAIR r4, ip, lr        @ Zero shadow regs
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[B]
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[A]
+    GET_VREG_DOUBLE_BY_ADDR d0, r3      @ d0<- vBB
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+
+    vcvt.f64.s32    d1, s1              @ d1<- (double)(vAAh)
+    vcvt.f64.u32    d2, s0              @ d2<- (double)(vAAl)
+    vldr            d3, constval$opcode
+    vmla.f64        d2, d1, d3          @ d2<- vAAh*2^32 + vAAl
+
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_DOUBLE_BY_ADDR d2, r4      @ vAA<- d2
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+    /* literal pool helper */
+constval${opcode}:
+    .8byte          0x41f0000000000000
+
+%def op_long_to_float():
+%  unopNarrower(instr="bl      __aeabi_l2f")
+
+%def op_mul_double():
+%  fbinopWide(instr="fmuld   d2, d0, d1")
+
+%def op_mul_double_2addr():
+%  fbinopWide2addr(instr="fmuld   d2, d0, d1")
+
+%def op_mul_float():
+%  fbinop(instr="fmuls   s2, s0, s1")
+
+%def op_mul_float_2addr():
+%  fbinop2addr(instr="fmuls   s2, s0, s1")
+
+%def op_neg_double():
+%  unopWide(instr="add     r1, r1, #0x80000000")
+
+%def op_neg_float():
+%  unop(instr="add     r0, r0, #0x80000000")
+
+%def op_rem_double():
+/* EABI doesn't define a double remainder function, but libm does */
+%  binopWide(instr="bl      fmod")
+
+%def op_rem_double_2addr():
+/* EABI doesn't define a double remainder function, but libm does */
+%  binopWide2addr(instr="bl      fmod")
+
+%def op_rem_float():
+/* EABI doesn't define a float remainder function, but libm does */
+%  binop(instr="bl      fmodf")
+
+%def op_rem_float_2addr():
+/* EABI doesn't define a float remainder function, but libm does */
+%  binop2addr(instr="bl      fmodf")
+
+%def op_sub_double():
+%  fbinopWide(instr="fsubd   d2, d0, d1")
+
+%def op_sub_double_2addr():
+%  fbinopWide2addr(instr="fsubd   d2, d0, d1")
+
+%def op_sub_float():
+%  fbinop(instr="fsubs   s2, s0, s1")
+
+%def op_sub_float_2addr():
+%  fbinop2addr(instr="fsubs   s2, s0, s1")
diff --git a/runtime/interpreter/mterp/armng/invoke.S b/runtime/interpreter/mterp/armng/invoke.S
new file mode 100644
index 0000000..d373147
--- /dev/null
+++ b/runtime/interpreter/mterp/armng/invoke.S
@@ -0,0 +1,180 @@
+%def op_invoke_custom():
+   EXPORT_PC
+   FETCH r0, 1 // call_site index, first argument of runtime call.
+   b NterpCommonInvokeCustom
+
+%def op_invoke_custom_range():
+   EXPORT_PC
+   FETCH r0, 1 // call_site index, first argument of runtime call.
+   b NterpCommonInvokeCustomRange
+
+%def invoke_direct_or_super(helper="", range="", is_super=""):
+   EXPORT_PC
+   // Fast-path which gets the method from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r0, 2f
+1:
+   // Load the first argument (the 'this' pointer).
+   FETCH r1, 2
+   .if !$range
+   and r1, r1, #0xf
+   .endif
+   GET_VREG r1, r1
+   cmp r1, #0
+   beq common_errNullObject    // bail if null
+   b $helper
+2:
+   mov r0, rSELF
+   ldr r1, [sp]
+   mov r2, rPC
+   bl nterp_get_method
+   .if $is_super
+   b 1b
+   .else
+   tst r0, #1
+   beq 1b
+   and r0, r0, #-2 // Remove the extra bit that marks it's a String.<init> method.
+   .if $range
+   b NterpHandleStringInitRange
+   .else
+   b NterpHandleStringInit
+   .endif
+   .endif
+
+%def op_invoke_direct():
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="0")
+
+%def op_invoke_direct_range():
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="0")
+
+%def op_invoke_super():
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1")
+
+%def op_invoke_super_range():
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1")
+
+%def op_invoke_polymorphic():
+   EXPORT_PC
+   // No need to fetch the target method.
+   // Load the first argument (the 'this' pointer).
+   FETCH r1, 2
+   and r1, r1, #0xf
+   GET_VREG r1, r1
+   cmp r1, #0
+   beq common_errNullObject    // bail if null
+   b NterpCommonInvokePolymorphic
+
+%def op_invoke_polymorphic_range():
+   EXPORT_PC
+   // No need to fetch the target method.
+   // Load the first argument (the 'this' pointer).
+   FETCH r1, 2
+   GET_VREG r1, r1
+   cmp r1, #0
+   beq common_errNullObject    // bail if null
+   b NterpCommonInvokePolymorphicRange
+
+%def invoke_interface(range=""):
+%  slow_path = add_helper(lambda: op_invoke_interface_slow_path())
+   EXPORT_PC
+   // Fast-path which gets the method from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r4, ${slow_path}
+.L${opcode}_resume:
+   // First argument is the 'this' pointer.
+   FETCH r1, 2
+   .if !$range
+   and r1, r1, #0xf
+   .endif
+   GET_VREG r1, r1
+   // Note: if r1 is null, this will be handled by our SIGSEGV handler.
+   ldr r2, [r1, #MIRROR_OBJECT_CLASS_OFFSET]
+   // Test the first two bits of the fetched ArtMethod:
+   // - If the first bit is set, this is a method on j.l.Object
+   // - If the second bit is set, this is a default method.
+   tst r4, #3
+   bne 2f
+   ldrh r3, [r4, #ART_METHOD_IMT_INDEX_OFFSET]
+1:
+   ldr r2, [r2, #MIRROR_CLASS_IMT_PTR_OFFSET_32]
+   ldr r0, [r2, r3, lsl #2]
+   .if $range
+   b NterpCommonInvokeInterfaceRange
+   .else
+   b NterpCommonInvokeInterface
+   .endif
+2:
+   tst r4, #1
+   bne 3f
+   and r4, r4, #-4
+   ldrh r3, [r4, #ART_METHOD_METHOD_INDEX_OFFSET]
+   and r3, r3, #ART_METHOD_IMT_MASK
+   b 1b
+3:
+   lsr r4, r4, #16
+   add r2, r2, #MIRROR_CLASS_VTABLE_OFFSET_32
+   ldr r0, [r2, r4, lsl #2]
+   .if $range
+   b NterpCommonInvokeInstanceRange
+   .else
+   b NterpCommonInvokeInstance
+   .endif
+
+%def op_invoke_interface_slow_path():
+   mov r0, rSELF
+   ldr r1, [sp]
+   mov r2, rPC
+   bl nterp_get_method
+   mov r4, r0
+   b .L${opcode}_resume
+
+%def op_invoke_interface():
+%  invoke_interface(range="0")
+
+%def op_invoke_interface_range():
+%  invoke_interface(range="1")
+
+%def invoke_static(helper=""):
+   EXPORT_PC
+   // Fast-path which gets the method from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r0, 1f
+   b $helper
+1:
+   mov r0, rSELF
+   ldr r1, [sp]
+   mov r2, rPC
+   bl nterp_get_method
+   b $helper
+
+%def op_invoke_static():
+%  invoke_static(helper="NterpCommonInvokeStatic")
+
+%def op_invoke_static_range():
+%  invoke_static(helper="NterpCommonInvokeStaticRange")
+
+%def invoke_virtual(helper="", range=""):
+   EXPORT_PC
+   // Fast-path which gets the vtable offset from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r2, 2f
+1:
+   FETCH r1, 2
+   .if !$range
+   and r1, r1, #0xf
+   .endif
+   GET_VREG r1, r1
+   // Note: if r1 is null, this will be handled by our SIGSEGV handler.
+   ldr r0, [r1, #MIRROR_OBJECT_CLASS_OFFSET]
+   add r0, r0, #MIRROR_CLASS_VTABLE_OFFSET_32
+   ldr r0, [r0, r2, lsl #2]
+   b $helper
+2:
+   mov r0, rSELF
+   ldr r1, [sp]
+   mov r2, rPC
+   bl nterp_get_method
+   mov r2, r0
+   b 1b
+
+%def op_invoke_virtual():
+%  invoke_virtual(helper="NterpCommonInvokeInstance", range="0")
+
+%def op_invoke_virtual_range():
+%  invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1")
diff --git a/runtime/interpreter/mterp/armng/main.S b/runtime/interpreter/mterp/armng/main.S
new file mode 100644
index 0000000..4427908
--- /dev/null
+++ b/runtime/interpreter/mterp/armng/main.S
@@ -0,0 +1,2014 @@
+%def header():
+/*
+ * Copyright (C) 2020 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.
+ */
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "asm_support.h"
+#include "arch/arm/asm_support_arm.S"
+
+/**
+ * ARM EABI general notes:
+ *
+ * r0-r3 hold first 4 args to a method; they are not preserved across method calls
+ * r4-r8 are available for general use
+ * r9 is given special treatment in some situations, but not for us
+ * r10 (sl) seems to be generally available
+ * r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
+ * r12 (ip) is scratch -- not preserved across method calls
+ * r13 (sp) should be managed carefully in case a signal arrives
+ * r14 (lr) must be preserved
+ * r15 (pc) can be tinkered with directly
+ *
+ * r0 holds returns of <= 4 bytes
+ * r0-r1 hold returns of 8 bytes, low word in r0
+ *
+ * Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
+ * is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
+ * s0-s15 (d0-d7, q0-a3) do not need to be.
+ *
+ * Stack is "full descending".  Only the arguments that don't fit in the first 4
+ * registers are placed on the stack.  "sp" points at the first stacked argument
+ * (i.e. the 5th arg).
+ *
+ * Native ABI uses soft-float, single-precision results are in r0,
+ * double-precision results in r0-r1.
+ *
+ * In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
+ * 64-bit quantities (long long, double) must be 64-bit aligned.
+ *
+ * Nterp notes:
+ *
+ * The following registers have fixed assignments:
+ *
+ *   reg nick      purpose
+ *   r5  rFP       interpreted frame pointer, used for accessing locals and args
+ *   r6  rREFS     base of object references of dex registers
+ *   r7  rINST     first 16-bit code unit of current instruction
+ *   r8  rMR       marking register
+ *   r9  rSELF     self (Thread) pointer
+ *   r10 rIBASE    interpreted instruction base pointer, used for computed goto
+ *   r11 rPC       interpreted program counter, used for fetching instructions
+ *
+ *   r4, ip, and lr can be used as temporary
+ *
+ * Note that r4 is a callee-save register in ARM EABI, but not in managed code.
+ *
+ */
+
+/* single-purpose registers, given names for clarity */
+#define CFI_DEX  11 // DWARF register number of the register holding dex-pc (rPC).
+#define CFI_TMP  0  // DWARF register number of the first argument register (r0).
+#define CFI_REFS 6
+#define rFP      r5
+#define rREFS    r6
+#define rINST    r7
+#define rSELF    r9
+#define rIBASE   r10
+#define rPC      r11
+
+// To avoid putting ifdefs arond the use of rMR, make sure it's defined.
+// IsNterpSupported returns false for configurations that don't have rMR (typically CMS).
+#ifndef rMR
+#define rMR r8
+#endif
+
+// Temporary registers while setting up a frame.
+#define rNEW_FP   r8
+#define rNEW_REFS r10
+#define CFI_NEW_REFS 10
+
+#define CALLEE_SAVES_SIZE (9 * 4 + 16 * 4)
+
+// +4 for the ArtMethod of the caller.
+#define OFFSET_TO_FIRST_ARGUMENT_IN_STACK (CALLEE_SAVES_SIZE + 4)
+
+/*
+ * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
+ */
+.macro FETCH_INST
+    ldrh    rINST, [rPC]
+.endm
+
+/*
+ * Fetch the next instruction from the specified offset.  Advances rPC
+ * to point to the next instruction.  "count" is in 16-bit code units.
+ *
+ * Because of the limited size of immediate constants on ARM, this is only
+ * suitable for small forward movements (i.e. don't try to implement "goto"
+ * with this).
+ *
+ * This must come AFTER anything that can throw an exception, or the
+ * exception catch may miss.  (This also implies that it must come after
+ * EXPORT_PC.)
+ */
+.macro FETCH_ADVANCE_INST count
+    ldrh    rINST, [rPC, #((\count)*2)]!
+.endm
+
+/*
+ * Similar to FETCH_ADVANCE_INST, but does not update xPC.  Used to load
+ * rINST ahead of possible exception point.  Be sure to manually advance xPC
+ * later.
+ */
+.macro PREFETCH_INST count
+    ldrh    rINST, [rPC, #((\count)*2)]
+.endm
+
+/* Advance xPC by some number of code units. */
+.macro ADVANCE count
+  add  rPC, #((\count)*2)
+.endm
+
+/*
+ * Fetch the next instruction from an offset specified by "reg" and advance xPC.
+ * xPC to point to the next instruction.  "reg" must specify the distance
+ * in bytes, *not* 16-bit code units, and may be a signed value.
+ */
+.macro FETCH_ADVANCE_INST_RB reg
+    ldrh    rINST, [rPC, \reg]!
+.endm
+
+/*
+ * Fetch a half-word code unit from an offset past the current PC.  The
+ * "count" value is in 16-bit code units.  Does not advance xPC.
+ *
+ * The "_S" variant works the same but treats the value as signed.
+ */
+.macro FETCH reg, count
+    ldrh    \reg, [rPC, #((\count)*2)]
+.endm
+
+.macro FETCH_S reg, count
+    ldrsh   \reg, [rPC, #((\count)*2)]
+.endm
+
+/*
+ * Fetch one byte from an offset past the current PC.  Pass in the same
+ * "count" as you would for FETCH, and an additional 0/1 indicating which
+ * byte of the halfword you want (lo/hi).
+ */
+.macro FETCH_B reg, count, byte
+    ldrb     \reg, [rPC, #((\count)*2+(\byte))]
+.endm
+
+/*
+ * Put the instruction's opcode field into the specified register.
+ */
+.macro GET_INST_OPCODE reg
+    and     \reg, rINST, #255
+.endm
+
+/*
+ * Begin executing the opcode in _reg.  Clobbers reg
+ */
+
+.macro GOTO_OPCODE reg
+    add     pc, rIBASE, \reg, lsl #${handler_size_bits}
+.endm
+
+/*
+ * Get/set value from a Dalvik register.
+ */
+.macro GET_VREG reg, vreg
+    ldr     \reg, [rFP, \vreg, lsl #2]
+.endm
+.macro GET_VREG_OBJECT reg, vreg
+    ldr     \reg, [rREFS, \vreg, lsl #2]
+.endm
+.macro SET_VREG reg, vreg
+    str     \reg, [rFP, \vreg, lsl #2]
+    mov     \reg, #0
+    str     \reg, [rREFS, \vreg, lsl #2]
+.endm
+.macro SET_VREG_OBJECT reg, vreg
+    str     \reg, [rFP, \vreg, lsl #2]
+    str     \reg, [rREFS, \vreg, lsl #2]
+.endm
+.macro SET_VREG_FLOAT reg, vreg, tmpreg
+    add     \tmpreg, rFP, \vreg, lsl #2
+    vstr    \reg, [\tmpreg]
+    mov     \tmpreg, #0
+    str     \tmpreg, [rREFS, \vreg, lsl #2]
+.endm
+.macro GET_VREG_WIDE_BY_ADDR reg0, reg1, addr
+    ldmia \addr, {\reg0, \reg1}
+.endm
+.macro SET_VREG_WIDE_BY_ADDR reg0, reg1, addr
+    stmia \addr, {\reg0, \reg1}
+.endm
+.macro GET_VREG_FLOAT sreg, vreg
+    ldr  \vreg, [rFP, \vreg, lsl #2]
+    vmov \sreg, \vreg
+.endm
+.macro GET_VREG_FLOAT_BY_ADDR reg, addr
+    vldr \reg, [\addr]
+.endm
+.macro SET_VREG_FLOAT_BY_ADDR reg, addr
+    vstr \reg, [\addr]
+.endm
+.macro GET_VREG_DOUBLE_BY_ADDR reg, addr
+    vldr \reg, [\addr]
+.endm
+.macro SET_VREG_DOUBLE_BY_ADDR reg, addr
+    vstr \reg, [\addr]
+.endm
+.macro SET_VREG_SHADOW reg, vreg
+    str     \reg, [rREFS, \vreg, lsl #2]
+.endm
+.macro CLEAR_SHADOW_PAIR vreg, tmp1, tmp2
+    mov     \tmp1, #0
+    add     \tmp2, \vreg, #1
+    SET_VREG_SHADOW \tmp1, \vreg
+    SET_VREG_SHADOW \tmp1, \tmp2
+.endm
+.macro VREG_INDEX_TO_ADDR reg, vreg
+    add     \reg, rFP, \vreg, lsl #2
+.endm
+
+// An assembly entry that has a OatQuickMethodHeader prefix.
+.macro OAT_ENTRY name, end
+    .arm
+    .type \name, #function
+    .hidden \name
+    .global \name
+    .balign 16
+    // Padding of 3 * 8 bytes to get 16 bytes alignment of code entry.
+    .long 0
+    .long 0
+    .long 0
+    // OatQuickMethodHeader. Note that the top two bits must be clear.
+    .long (\end - \name)
+\name:
+.endm
+
+.macro SIZE name
+    .size \name, .-\name
+.endm
+
+.macro NAME_START name
+    .arm
+    .type \name, #function
+    .hidden \name  // Hide this as a global symbol, so we do not incur plt calls.
+    .global \name
+    /* Cache alignment for function entry */
+    .balign 16
+\name:
+.endm
+
+.macro NAME_END name
+  SIZE \name
+.endm
+
+// Macro for defining entrypoints into runtime. We don't need to save registers
+// (we're not holding references there), but there is no
+// kDontSave runtime method. So just use the kSaveRefsOnly runtime method.
+.macro NTERP_TRAMPOLINE name, helper
+ENTRY \name
+  SETUP_SAVE_REFS_ONLY_FRAME ip
+  bl \helper
+  RESTORE_SAVE_REFS_ONLY_FRAME
+  REFRESH_MARKING_REGISTER
+  RETURN_OR_DELIVER_PENDING_EXCEPTION
+END \name
+.endm
+
+.macro CLEAR_STATIC_VOLATILE_MARKER reg
+  and \reg, \reg, #-2
+.endm
+
+.macro CLEAR_INSTANCE_VOLATILE_MARKER reg
+  rsb \reg, \reg, #0
+.endm
+
+.macro EXPORT_PC
+    str    rPC, [rREFS, #-8]
+.endm
+
+.macro BRANCH
+    // Update method counter and do a suspend check if the branch is negative.
+    cmp rINST, #0
+    blt 2f
+1:
+    add r2, rINST, rINST                // r2<- byte offset
+    FETCH_ADVANCE_INST_RB r2            // update xPC, load rINST
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    GOTO_OPCODE ip                      // jump to next instruction
+2:
+    ldr r0, [sp]
+    ldrh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
+    add r2, r2, #1
+    ubfx r2, r2, #0, #NTERP_HOTNESS_BITS
+    strh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
+    // If the counter overflows, handle this in the runtime.
+    cmp r2, #0
+    beq NterpHandleHotnessOverflow
+    // Otherwise, do a suspend check.
+    ldr r0, [rSELF, #THREAD_FLAGS_OFFSET]
+    ands r0, r0, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
+    beq 1b
+    EXPORT_PC
+    bl    art_quick_test_suspend
+    b 1b
+.endm
+
+// Expects:
+// - ip and lr to be available.
+// Outputs:
+// - \registers contains the dex registers size
+// - \outs contains the outs size
+// - if load_ins is 1, \ins contains the ins
+// - \code_item is replaced with a pointer to the instructions
+.macro FETCH_CODE_ITEM_INFO code_item, registers, outs, ins, load_ins
+    tst \code_item, #1
+    beq 5f
+    bic \code_item, \code_item, #1 // Remove the extra bit that marks it's a compact dex file
+    ldrh lr, [\code_item, #COMPACT_CODE_ITEM_FIELDS_OFFSET]
+    ubfx \registers, lr, #COMPACT_CODE_ITEM_REGISTERS_SIZE_SHIFT, #4
+    ubfx \outs, lr, #COMPACT_CODE_ITEM_OUTS_SIZE_SHIFT, #4
+    .if \load_ins
+    ubfx \ins, lr, #COMPACT_CODE_ITEM_INS_SIZE_SHIFT, #4
+    .else
+    ubfx ip, lr, #COMPACT_CODE_ITEM_INS_SIZE_SHIFT, #4
+    add \registers, \registers, ip
+    .endif
+
+    ldrh lr, [\code_item, #COMPACT_CODE_ITEM_FLAGS_OFFSET]
+    tst lr, #COMPACT_CODE_ITEM_REGISTERS_INS_OUTS_FLAGS
+    beq 4f
+    mov ip, \code_item
+    tst lr, #COMPACT_CODE_ITEM_INSNS_FLAG
+    beq 1f
+    sub ip, ip, #4
+1:
+    tst lr, #COMPACT_CODE_ITEM_REGISTERS_FLAG
+    beq 2f
+    ldrh lr, [ip, #-2]!
+    add \registers, \registers, lr
+    ldrh lr, [\code_item, #COMPACT_CODE_ITEM_FLAGS_OFFSET]
+2:
+    tst lr, #COMPACT_CODE_ITEM_INS_FLAG
+    beq 3f
+    ldrh lr, [ip, #-2]!
+    .if \load_ins
+    add \ins, \ins, lr
+    .else
+    add \registers, \registers, lr
+    .endif
+    ldrh lr, [\code_item, #COMPACT_CODE_ITEM_FLAGS_OFFSET]
+3:
+    tst lr, #COMPACT_CODE_ITEM_OUTS_FLAG
+    beq 4f
+    ldrh lr, [ip, #-2]!
+    add \outs, \outs, lr
+4:
+    .if \load_ins
+    add \registers, \registers, \ins
+    .endif
+    add \code_item, \code_item, #COMPACT_CODE_ITEM_INSNS_OFFSET
+    b 6f
+5:
+    // Fetch dex register size.
+    ldrh \registers, [\code_item, #CODE_ITEM_REGISTERS_SIZE_OFFSET]
+    // Fetch outs size.
+    ldrh \outs, [\code_item, #CODE_ITEM_OUTS_SIZE_OFFSET]
+    .if \load_ins
+    ldrh \ins, [\code_item, #CODE_ITEM_INS_SIZE_OFFSET]
+    .endif
+    add \code_item, \code_item, #CODE_ITEM_INSNS_OFFSET
+6:
+.endm
+
+// Setup the stack to start executing the method. Expects:
+// - r0 to contain the ArtMethod
+// - \code_item to already contain the code item
+// - rINST, ip, lr to be available
+//
+// Outputs
+// - rINST contains the dex registers size
+// - ip contains the old stack pointer.
+// - \code_item is replaced with a pointer to the instructions
+// - if load_ins is 1, r4 contains the ins
+//
+.macro SETUP_STACK_FRAME code_item, refs, fp, cfi_refs, load_ins
+    FETCH_CODE_ITEM_INFO \code_item, rINST, \refs, r4, \load_ins
+
+    // Compute required frame size: ((2 * rINST) + \refs) * 4 + 12
+    // 12 is for saving the previous frame, pc, and method being executed.
+    add ip, \refs, rINST, lsl #1
+
+    // Compute new stack pointer in lr
+    sub lr, sp, #12
+    sub lr, lr, ip, lsl #2
+    // Alignment
+    and lr, lr, #-16
+
+    // Set reference and dex registers.
+    add \refs, lr, \refs, lsl #2
+    add \refs, \refs, #12
+    add \fp, \refs, rINST, lsl #2
+
+    // Now setup the stack pointer.
+    mov ip, sp
+    .cfi_def_cfa_register ip
+    mov sp, lr
+    str ip, [\refs, #-4]
+    CFI_DEF_CFA_BREG_PLUS_UCONST \cfi_refs, -4, CALLEE_SAVES_SIZE
+
+    // Save the ArtMethod, and use r0 as a temporary.
+    str r0, [sp]
+
+    // Put nulls in reference frame.
+    cmp rINST, #0
+    beq 2f
+    mov lr, \refs
+    mov r0, #0
+1:
+    str r0, [lr], #4
+    str r0, [lr], #4  // May clear vreg[0].
+    cmp lr, \fp
+    blo 1b
+2:
+    ldr r0, [sp]  // Reload the ArtMethod, expected by the callers.
+.endm
+
+// Increase method hotness and do suspend check before starting executing the method.
+.macro START_EXECUTING_INSTRUCTIONS
+    ldr r0, [sp]
+    ldrh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
+    add r2, r2, #1
+    ubfx r2, r2, #0, #NTERP_HOTNESS_BITS
+    strh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
+    // If the counter overflows, handle this in the runtime.
+    cmp r2, #0
+    beq 2f
+    ldr r0, [rSELF, #THREAD_FLAGS_OFFSET]
+    tst r0, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
+    bne 3f
+1:
+    FETCH_INST
+    GET_INST_OPCODE ip
+    GOTO_OPCODE ip
+2:
+    mov r1, #0
+    mov r2, rFP
+    bl nterp_hot_method
+    b 1b
+3:
+    EXPORT_PC
+    bl art_quick_test_suspend
+    b 1b
+.endm
+
+.macro SPILL_ALL_CALLEE_SAVES
+    SPILL_ALL_CALLEE_SAVE_GPRS                    @ 9 words (36 bytes) of callee saves.
+    vpush {s16-s31}                               @ 16 words (64 bytes) of floats.
+    .cfi_adjust_cfa_offset 64
+.endm
+
+.macro RESTORE_ALL_CALLEE_SAVES lr_to_pc=0
+    vpop {s16-s31}
+    .cfi_adjust_cfa_offset -64
+    pop {r4-r7}
+    .cfi_adjust_cfa_offset -16
+    .cfi_restore r4
+    .cfi_restore r5
+    .cfi_restore r6
+    .cfi_restore r7
+    // Don't restore r8, the marking register gets updated when coming back from runtime.
+    add sp, sp, #4
+    .cfi_adjust_cfa_offset -4
+    .if \lr_to_pc
+    pop {r9-r11, pc}  @ 9 words of callee saves and args.
+    .else
+    pop {r9-r11, lr}  @ 9 words of callee saves and args.
+    .cfi_adjust_cfa_offset -16
+    .cfi_restore r9
+    .cfi_restore r10
+    .cfi_restore r11
+    .cfi_restore lr
+    .endif
+.endm
+
+// Helper to setup the stack after doing a nterp to nterp call. This will setup:
+// - rNEW_FP: the new pointer to dex registers
+// - rNEW_REFS: the new pointer to references
+// - rPC: the new PC pointer to execute
+// - r2: value in instruction to decode the number of arguments.
+// - r3: first dex register for range invokes, up to 4 arguments for non-range invokes.
+// - r4: top of dex register array
+//
+// The method expects:
+// - r0 to contain the ArtMethod
+// - r4 to contain the code item
+.macro SETUP_STACK_FOR_INVOKE
+   // We do the same stack overflow check as the compiler. See CanMethodUseNterp
+   // in how we limit the maximum nterp frame size.
+   sub ip, sp, #STACK_OVERFLOW_RESERVED_BYTES
+   ldr ip, [ip]
+
+   // Spill all callee saves to have a consistent stack frame whether we
+   // are called by compiled code or nterp.
+   SPILL_ALL_CALLEE_SAVES
+
+   // Setup the frame.
+   SETUP_STACK_FRAME r4, rNEW_REFS, rNEW_FP, CFI_NEW_REFS, load_ins=0
+
+   // Fetch instruction information before replacing rPC.
+   FETCH_B r2, 0, 1
+   FETCH r3, 2
+
+   // Set the dex pc pointer.
+   mov rPC, r4
+
+   // Make r4 point to the top of the dex register array.
+   add r4, rNEW_FP, rINST, lsl #2
+
+   CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
+.endm
+
+// Setup arguments based on a non-range nterp to nterp call, and start executing
+// the method. We expect:
+// - rNEW_FP: the new pointer to dex registers
+// - rPC: the new PC pointer to execute
+// - r2: number of arguments (bits 4-7), 5th argument if any (bits 0-3)
+// - r3: up to four dex register arguments
+// - r4: top of dex register array
+// - r1: receiver if non-static.
+//
+// Uses r0 and rINST as temporaries.
+.macro SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
+   // /* op vA, vB, {vC...vG} */
+   .if \is_static
+   asrs   r0, r2, #4
+   beq    6f
+   .else
+   asr    r0, r2, #4
+   .endif
+   mov rINST, #-4
+   cmp r0, #2
+   blt 1f
+   beq 2f
+   cmp r0, #4
+   blt 3f
+   beq 4f
+
+  // We use a decrementing rINST to store references relative
+  // to rNEW_FP and dex registers relative to r4
+  //
+  // TODO: We could set up rINST as the number of registers (this can be an additional output from
+  // SETUP_STACK_FOR_INVOKE) and then just decrement it by one before copying each arg.
+  // Maybe even introduce macros NEW_VREG_ADDRESS/NEW_VREG_REF_ADDRESS.
+5:
+   and         r2, r2, #15
+   GET_VREG_OBJECT r0, r2
+   str         r0, [rNEW_FP, rINST]
+   GET_VREG    r0, r2
+   str         r0, [r4, rINST]
+   sub         rINST, rINST, #4
+4:
+   asr         r2, r3, #12
+   GET_VREG_OBJECT r0, r2
+   str         r0, [rNEW_FP, rINST]
+   GET_VREG    r0, r2
+   str         r0, [r4, rINST]
+   sub         rINST, rINST, #4
+3:
+   ubfx        r2, r3, #8, #4
+   GET_VREG_OBJECT r0, r2
+   str         r0, [rNEW_FP, rINST]
+   GET_VREG    r0, r2
+   str         r0, [r4, rINST]
+   sub         rINST, rINST, #4
+2:
+   ubfx        r2, r3, #4, #4
+   GET_VREG_OBJECT r0, r2
+   str         r0, [rNEW_FP, rINST]
+   GET_VREG    r0, r2
+   str         r0, [r4, rINST]
+   .if !\is_string_init
+   sub         rINST, rINST, #4
+   .endif
+1:
+   .if \is_string_init
+   // Ignore the first argument
+   .elseif \is_static
+   and         r2, r3, #0xf
+   GET_VREG_OBJECT r0, r2
+   str         r0, [rNEW_FP, rINST]
+   GET_VREG    r0, r2
+   str         r0, [r4, rINST]
+   .else
+   str         r1, [rNEW_FP, rINST]
+   str         r1, [r4, rINST]
+   .endif
+
+6:
+   // Start executing the method.
+   mov rFP, rNEW_FP
+   mov rREFS, rNEW_REFS
+   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -4, CALLEE_SAVES_SIZE
+   // r8 was used for setting up the frame, restore it now.
+   REFRESH_MARKING_REGISTER
+   // Branch to the main handler, which will reload rIBASE,
+   // that was used for setting up the frame.
+   b .Lexecute_instructions
+.endm
+
+// Setup arguments based on a range nterp to nterp call, and start executing
+// the method.
+// - rNEW_FP: the new pointer to dex registers
+// - rNEW_REFS: the new pointer to references
+// - rPC: the new PC pointer to execute
+// - r2: number of arguments
+// - r3: first dex register
+// - r4: top of dex register array
+// - r1: receiver if non-static.
+//
+// Expects r0 to be available.
+.macro SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
+   mov r0, #-4
+   .if \is_string_init
+   // Ignore the first argument
+   sub r2, r2, #1
+   add r3, r3, #1
+   .elseif !\is_static
+   sub r2, r2, #1
+   add r3, r3, #1
+   .endif
+
+   cmp r2, #0
+   beq 2f
+   add rREFS, rREFS, r3, lsl #2  // pointer to first argument in reference array
+   add rREFS, rREFS, r2, lsl #2    // pointer to last argument in reference array
+   add rFP, rFP, r3, lsl #2     // pointer to first argument in register array
+   add rFP, rFP, r2, lsl #2      // pointer to last argument in register array
+1:
+   ldr  r3, [rREFS, #-4]!
+   str  r3, [rNEW_FP, r0]
+   subs r2, r2, 1
+   ldr  r3, [rFP, #-4]!
+   str  r3, [r4, r0]
+   sub r0, r0, 4
+   bne 1b
+2:
+   .if \is_string_init
+   // Ignore first argument
+   .elseif !\is_static
+   str r1, [rNEW_FP, r0]
+   str r1, [r4, r0]
+   .endif
+   mov rFP, rNEW_FP
+   mov rREFS, rNEW_REFS
+   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -4, CALLEE_SAVES_SIZE
+   // r8 was used for setting up the frame, restore it now.
+   REFRESH_MARKING_REGISTER
+   // Branch to the main handler, which will reload rIBASE,
+   // that was used for setting up the frame.
+   b .Lexecute_instructions
+.endm
+
+.macro GET_SHORTY dest, is_interface, is_polymorphic, is_custom
+   push {r0-r3}
+   .if \is_polymorphic
+   ldr r0, [sp, #16]
+   mov r1, rPC
+   bl NterpGetShortyFromInvokePolymorphic
+   .elseif \is_custom
+   ldr r0, [sp, #16]
+   mov r1, rPC
+   bl NterpGetShortyFromInvokeCustom
+   .elseif \is_interface
+   ldr r0, [sp, #16]
+   FETCH r1, 1
+   bl NterpGetShortyFromMethodId
+   .else
+   bl NterpGetShorty
+   .endif
+   mov \dest, r0
+   pop {r0-r3}
+.endm
+
+// Input:  r0 contains the ArtMethod
+// Output: r4 contains the code item
+.macro GET_CODE_ITEM
+   ldr r4, [r0, #ART_METHOD_DATA_OFFSET_32]
+.endm
+
+.macro DO_ENTRY_POINT_CHECK call_compiled_code, name
+   // On entry, the method is r0, the instance is r1
+   ldr r2, .Lfetch_nterp_\name
+.Lfetch_location_\name:
+   // Note that this won't work for thumb.
+   sub r2, pc, r2
+   ldr r3, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
+   cmp r2, r3
+   bne  \call_compiled_code
+.endm
+
+// Expects ip and lr to be available.
+.macro UPDATE_REGISTERS_FOR_STRING_INIT old_value, new_value
+   mov ip, #0
+1:
+   GET_VREG_OBJECT lr, ip
+   cmp lr, \old_value
+   bne 2f
+   SET_VREG_OBJECT \new_value, ip
+2:
+   add ip, ip, #1
+   add lr, rREFS, ip, lsl #2
+   cmp lr, rFP
+   bne 1b
+.endm
+
+// Puts the next floating point argument into the expected register,
+// fetching values based on a non-range invoke.
+// Uses ip and lr.
+.macro LOOP_OVER_SHORTY_LOADING_FPS dreg, sreg, inst, shorty, arg_index, finished, if_double
+1: // LOOP
+    ldrb ip, [\shorty], #1          // Load next character in shorty, and increment.
+    cmp ip, #0
+    beq \finished                   // if (ip == '\0') goto finished
+    cmp ip, #68                    // if (ip == 'D') goto FOUND_DOUBLE
+    beq 2f
+    cmp ip, #70                    // if (ip == 'F') goto FOUND_FLOAT
+    beq 3f
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    //  Handle extra argument in arg array taken by a long.
+    cmp ip, #74                   // if (ip != 'J') goto LOOP
+    bne 1b
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 1b                        // goto LOOP
+2:  // FOUND_DOUBLE
+    and ip, \inst, #0xf
+    GET_VREG ip, ip
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    cmp \arg_index, #4
+    beq 5f
+    and lr, \inst, #0xf
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 6f
+5:
+    FETCH_B lr, 0, 1
+    and lr, lr, #0xf
+6:
+    GET_VREG lr, lr
+    vmov \dreg, ip, lr
+    b \if_double
+3:  // FOUND_FLOAT
+    cmp \arg_index, #4
+    beq 7f
+    and ip, \inst, #0xf
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 8f
+7:
+    FETCH_B ip, 0, 1
+    and ip, ip, #0xf
+8:
+    GET_VREG_FLOAT \sreg, ip
+.endm
+
+// Puts the next int/long/object argument in the expected register,
+// fetching values based on a non-range invoke.
+// Uses ip.
+.macro LOOP_OVER_SHORTY_LOADING_GPRS gpr_reg, inst, shorty, arg_index, finished, if_long, is_r3
+1: // LOOP
+    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
+    cmp ip, #0
+    beq \finished                   // if (ip == '\0') goto finished
+    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
+    beq 2f
+    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
+    beq 3f
+    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
+    beq 4f
+    cmp \arg_index, #4
+    beq 7f
+    and ip, \inst, #0xf
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 8f
+7:
+    FETCH_B ip, 0, 1
+    and ip, ip, #0xf
+8:
+    GET_VREG \gpr_reg, ip
+    b 5f
+2:  // FOUND_LONG
+    .if \is_r3
+    // Put back shorty and exit
+    sub \shorty, \shorty, #1
+    b 5f
+    .endif
+    and ip, \inst, #0xf
+    GET_VREG ip, ip
+    // The only one possible for non-range long is r2-r3
+    mov r2, ip
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    cmp \arg_index, #4
+    beq 9f
+    and ip, \inst, #0xf
+    lsr \inst, \inst, #4
+    b 10f
+9:
+    FETCH_B ip, 0, 1
+    and ip, ip, #0xf
+10:
+    GET_VREG ip, ip
+    // The only one possible for non-range long is r2-r3
+    mov r3, ip
+    add \arg_index, \arg_index, #1
+    b \if_long
+3:  // SKIP_FLOAT
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 1b
+4:  // SKIP_DOUBLE
+    lsr \inst, \inst, #8
+    add \arg_index, \arg_index, #2
+    b 1b
+5:
+.endm
+
+// Puts the next int/long/object argument in the expected stack slot,
+// fetching values based on a non-range invoke.
+// Uses ip as temporary.
+.macro LOOP_OVER_SHORTY_LOADING_INTs shorty, inst, arg_index, finished, is_string_init
+1: // LOOP
+    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
+    cmp ip, #0
+    beq \finished                  // if (ip == '\0') goto finished
+    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
+    beq 2f
+    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
+    beq 3f
+    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
+    beq 4f
+    .if \is_string_init
+    cmp \arg_index, #4
+    .else
+    cmp \arg_index, #(4+1)         // +1 for ArtMethod
+    .endif
+    beq 7f
+    and ip, \inst, #0xf
+    lsr \inst, \inst, #4
+    b 8f
+7:
+    FETCH_B ip, 0, 1
+    and ip, ip, #0xf
+8:
+    GET_VREG ip, ip
+    str ip, [sp, \arg_index, lsl #2]
+    add \arg_index, \arg_index, #1
+    b 1b
+2:  // FOUND_LONG
+    and ip, \inst, #0xf
+    GET_VREG ip, ip
+    str ip, [sp, \arg_index, lsl #2]
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    .if \is_string_init
+    cmp \arg_index, #4
+    .else
+    cmp \arg_index, #(4+1)         // +1 for ArtMethod
+    .endif
+    beq 9f
+    and ip, \inst, #0xf
+    lsr \inst, \inst, #4
+    b 10f
+9:
+    FETCH_B ip, 0, 1
+    and ip, ip, #0xf
+10:
+    GET_VREG ip, ip
+    str ip, [sp, \arg_index, lsl #2]
+    add \arg_index, \arg_index, #1
+    b 1b
+3:  // SKIP_FLOAT
+    lsr \inst, \inst, #4
+    add \arg_index, \arg_index, #1
+    b 1b
+4:  // SKIP_DOUBLE
+    lsr \inst, \inst, #8
+    add \arg_index, \arg_index, #2
+    b 1b
+.endm
+
+.macro SETUP_RETURN_VALUE shorty
+   ldrb ip, [\shorty]
+   cmp ip, #68       // Test if result type char == 'D'.
+   beq 1f
+   cmp ip, #70       // Test if result type char == 'F'.
+   bne 2f
+   vmov r0, s0
+   b 2f
+1:
+   vmov r0, r1, d0
+2:
+.endm
+
+.macro GET_SHORTY_SLOW_PATH dest, is_interface
+   // Save all registers that can hold arguments in the fast path.
+   vpush {s0}
+   push {r0-r2}
+   .if \is_interface
+   ldr r0, [sp, #16]
+   FETCH r1, 1
+   bl NterpGetShortyFromMethodId
+   .else
+   bl NterpGetShorty
+   .endif
+   mov \dest, r0
+   pop {r0-r2}
+   vpop {s0}
+.endm
+
+.macro COMMON_INVOKE_NON_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0
+   .if \is_polymorphic
+   // We always go to compiled code for polymorphic calls.
+   .elseif \is_custom
+   // We always go to compiled code for custom calls.
+   .else
+     DO_ENTRY_POINT_CHECK .Lcall_compiled_code_\suffix, \suffix
+     GET_CODE_ITEM
+     .if \is_string_init
+     bl nterp_to_nterp_string_init_non_range
+     .elseif \is_static
+     bl nterp_to_nterp_static_non_range
+     .else
+     bl nterp_to_nterp_instance_non_range
+     .endif
+     b .Ldone_return_\suffix
+.Lfetch_nterp_\suffix:
+    .word   (.Lfetch_location_\suffix+8) - ExecuteNterpImpl
+   .endif
+
+.Lcall_compiled_code_\suffix:
+   .if \is_polymorphic
+   // No fast path for polymorphic calls.
+   .elseif \is_custom
+   // No fast path for custom calls.
+   .elseif \is_string_init
+   // No fast path for string.init.
+   .else
+     ldr ip, [r0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
+     tst ip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG
+     beq .Lfast_path_with_few_args_\suffix
+     FETCH_B rINST, 0, 1
+     .if \is_static
+     asrs lr, rINST, #4
+     beq .Linvoke_fast_path_\suffix
+     .else
+     asr lr, rINST, #4
+     cmp lr, #1
+     beq .Linvoke_fast_path_\suffix
+     .endif
+     FETCH ip, 2
+     cmp lr, #2
+     .if \is_static
+     blt .Lone_arg_fast_path_\suffix
+     .endif
+     beq .Ltwo_args_fast_path_\suffix
+     cmp lr, #4
+     blt .Lthree_args_fast_path_\suffix
+     beq .Lfour_args_fast_path_\suffix
+     and         rINST, rINST, #15
+     GET_VREG    rINST, rINST
+     str         rINST, [sp, #(4 + 4 * 4)]
+.Lfour_args_fast_path_\suffix:
+     asr         rINST, ip, #12
+     GET_VREG    rINST, rINST
+     str         rINST, [sp, #(4 + 3 * 4)]
+.Lthree_args_fast_path_\suffix:
+     ubfx        rINST, ip, #8, #4
+     GET_VREG    r3, rINST
+.Ltwo_args_fast_path_\suffix:
+     ubfx        rINST, ip, #4, #4
+     GET_VREG    r2, rINST
+.Lone_arg_fast_path_\suffix:
+     .if \is_static
+     and         rINST, ip, #0xf
+     GET_VREG    r1, rINST
+     .else
+     // First argument already in r1.
+     .endif
+.Linvoke_fast_path_\suffix:
+     .if \is_interface
+     // Setup hidden argument.
+     mov ip, r4
+     .endif
+     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
+     blx lr
+     FETCH_ADVANCE_INST 3
+     GET_INST_OPCODE ip
+     GOTO_OPCODE ip
+
+.Lfast_path_with_few_args_\suffix:
+     // Fast path when we have zero or one argument (modulo 'this'). If there
+     // is one argument, we can put it in both floating point and core register.
+     FETCH_B r2, 0, 1
+     asr r2, r2, #4  // number of arguments
+     .if \is_static
+     cmp r2, #1
+     blt .Linvoke_with_few_args_\suffix
+     bne .Lget_shorty_\suffix
+     FETCH r2, 2
+     and r2, r2, #0xf  // dex register of first argument
+     GET_VREG r1, r2
+     vmov s0, r1
+     .else
+     cmp r2, #2
+     blt .Linvoke_with_few_args_\suffix
+     bne .Lget_shorty_\suffix
+     FETCH r2, 2
+     ubfx r2, r2, #4, #4  // dex register of second argument
+     GET_VREG r2, r2
+     vmov s0, r2
+     .endif
+.Linvoke_with_few_args_\suffix:
+     // Check if the next instruction is move-result or move-result-wide.
+     // If it is, we fetch the shorty and jump to the regular invocation.
+     FETCH r3, 3
+     and r3, r3, #0xfe
+     cmp r3, #0x0a
+     beq .Lget_shorty_and_invoke_\suffix
+     .if \is_interface
+     // Setup hidden argument.
+     mov ip, r4
+     .endif
+     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
+     blx lr
+     FETCH_ADVANCE_INST 3
+     GET_INST_OPCODE ip
+     GOTO_OPCODE ip
+.Lget_shorty_and_invoke_\suffix:
+     .if \is_interface
+     // Save hidden argument.
+     vmov s16, r4
+     .endif
+     GET_SHORTY_SLOW_PATH rINST, \is_interface
+     b .Lgpr_setup_finished_\suffix
+   .endif
+
+.Lget_shorty_\suffix:
+   .if \is_interface
+   // Save hidden argument.
+   vmov s16, r4
+   .endif
+   GET_SHORTY rINST, \is_interface, \is_polymorphic, \is_custom
+   // From this point:
+   // - rINST contains shorty (in callee-save to switch over return value after call).
+   // - r0 contains method
+   // - r1 contains 'this' pointer for instance method.
+   // We need three registers.
+   add r3, rINST, #1  // shorty + 1  ; ie skip return arg character
+   FETCH r2, 2 // arguments
+   .if \is_string_init
+   lsr r2, r2, #4
+   mov r4, #1       // ignore first argument
+   .elseif \is_static
+   mov r4, #0      // arg_index
+   .else
+   lsr r2, r2, #4
+   mov r4, #1       // ignore first argument
+   .endif
+   LOOP_OVER_SHORTY_LOADING_FPS d0, s0, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Ld1_s2_\suffix
+.Ld1_s1_\suffix:
+   LOOP_OVER_SHORTY_LOADING_FPS d1, s1, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Ld2_s1_\suffix
+.Ld1_s2_\suffix:
+   LOOP_OVER_SHORTY_LOADING_FPS d1, s2, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Ls4_\suffix
+.Ld2_s3_\suffix:
+   LOOP_OVER_SHORTY_LOADING_FPS d2, s3, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Lxmm_setup_finished_\suffix
+   b .Ls4_\suffix
+.Ld2_s1_\suffix:
+   LOOP_OVER_SHORTY_LOADING_FPS d2, s1, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Lxmm_setup_finished_\suffix
+.Ls4_\suffix:
+   // If we arrive here, we can only have a float.
+   LOOP_OVER_SHORTY_LOADING_FPS d2, s4, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Lxmm_setup_finished_\suffix
+.Lxmm_setup_finished_\suffix:
+   add r4, rINST, #1  // shorty + 1  ; ie skip return arg character
+   FETCH r8, 2 // arguments
+   .if \is_string_init
+   lsr r8, r8, #4
+   mov lr, #1       // ignore first argument
+   LOOP_OVER_SHORTY_LOADING_GPRS r1, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=0
+   .elseif \is_static
+   mov lr, #0      // arg_index
+   LOOP_OVER_SHORTY_LOADING_GPRS r1, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=0
+   .else
+   lsr r8, r8, #4
+   mov lr, #1       // ignore first argument
+   .endif
+   LOOP_OVER_SHORTY_LOADING_GPRS r2, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=0
+   LOOP_OVER_SHORTY_LOADING_GPRS r3, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=1
+.Lif_long_\suffix:
+   // Store in the outs array (stored above the ArtMethod in the stack). We only do this for non-string-init
+   // calls as the index is already adjusted above.
+   .if !\is_string_init
+   add lr, lr, #1
+   .endif
+   LOOP_OVER_SHORTY_LOADING_INTs r4, r8, lr, .Lgpr_setup_finished_\suffix, \is_string_init
+.Lgpr_setup_finished_\suffix:
+   REFRESH_MARKING_REGISTER // r8 was used when setting parameters, restore it.
+   .if \is_polymorphic
+   bl art_quick_invoke_polymorphic
+   .elseif \is_custom
+   bl art_quick_invoke_custom
+   .else
+      .if \is_interface
+      // Setup hidden argument.
+      vmov ip, s16
+      .endif
+      ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
+      blx lr
+   .endif
+   SETUP_RETURN_VALUE rINST
+.Ldone_return_\suffix:
+   /* resume execution of caller */
+   .if \is_string_init
+   FETCH ip, 2 // arguments
+   and ip, ip, #0xf
+   GET_VREG r1, ip
+   UPDATE_REGISTERS_FOR_STRING_INIT r1, r0
+   .endif
+
+   .if \is_polymorphic
+   FETCH_ADVANCE_INST 4
+   .else
+   FETCH_ADVANCE_INST 3
+   .endif
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.endm
+
+// Puts the next int/long/object argument in the expected register,
+// fetching values based on a range invoke.
+// Uses ip as temporary.
+.macro LOOP_RANGE_OVER_SHORTY_LOADING_GPRS reg32, shorty, arg_index, stack_index, finished, if_long, is_r3
+1: // LOOP
+    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
+    cmp ip, #0
+    beq \finished                  // if (ip == '\0') goto finished
+    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
+    beq 2f
+    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
+    beq 3f
+    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
+    beq 4f
+    GET_VREG \reg32, \arg_index
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 5f
+2:  // FOUND_LONG
+    .if \is_r3
+    // Put back shorty and jump to \if_long
+    sub \shorty, \shorty, #1
+    .else
+    GET_VREG r2, \arg_index
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    GET_VREG r3, \arg_index
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    .endif
+    b \if_long
+3:  // SKIP_FLOAT
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 1b
+4:  // SKIP_DOUBLE
+    add \arg_index, \arg_index, #2
+    add \stack_index, \stack_index, #2
+    b 1b
+5:
+.endm
+
+// Puts the next int/long/object argument in the expected stack slot,
+// fetching values based on a range invoke.
+// Uses ip as temporary.
+.macro LOOP_RANGE_OVER_INTs shorty, arg_index, stack_index, finished
+1: // LOOP
+    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
+    cmp ip, #0
+    beq \finished                     // if (ip == '\0') goto finished
+    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
+    beq 2f
+    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
+    beq 3f
+    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
+    beq 4f
+    GET_VREG ip, \arg_index
+    str ip, [sp, \stack_index, lsl #2]
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 1b
+2:  // FOUND_LONG
+    GET_VREG ip, \arg_index
+    str ip, [sp, \stack_index, lsl #2]
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    GET_VREG ip, \arg_index
+    str ip, [sp, \stack_index, lsl #2]
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 1b
+3:  // SKIP_FLOAT
+    add \arg_index, \arg_index, #1
+    add \stack_index, \stack_index, #1
+    b 1b
+4:  // SKIP_DOUBLE
+    add \arg_index, \arg_index, #2
+    add \stack_index, \stack_index, #2
+    b 1b
+.endm
+
+.macro COMMON_INVOKE_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0
+   .if \is_polymorphic
+   // We always go to compiled code for polymorphic calls.
+   .elseif \is_custom
+   // We always go to compiled code for custom calls.
+   .else
+     DO_ENTRY_POINT_CHECK .Lcall_compiled_code_range_\suffix, range_\suffix
+     GET_CODE_ITEM
+     .if \is_string_init
+     bl nterp_to_nterp_string_init_range
+     .elseif \is_static
+     bl nterp_to_nterp_static_range
+     .else
+     bl nterp_to_nterp_instance_range
+     .endif
+     b .Ldone_return_range_\suffix
+.Lfetch_nterp_range_\suffix:
+    .word   (.Lfetch_location_range_\suffix+8) - ExecuteNterpImpl
+   .endif
+
+.Lcall_compiled_code_range_\suffix:
+   .if \is_polymorphic
+   // No fast path for polymorphic calls.
+   .elseif \is_custom
+   // No fast path for custom calls.
+   .elseif \is_string_init
+   // No fast path for string.init.
+   .else
+     ldr ip, [r0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
+     tst ip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG
+     beq .Lfast_path_with_few_args_range_\suffix
+     FETCH_B ip, 0, 1  // Number of arguments
+     .if \is_static
+     cmp ip, #0
+     .else
+     cmp ip, #1
+     .endif
+     beq .Linvoke_fast_path_range_\suffix
+     FETCH lr, 2  // dex register of first argument
+     add lr, rFP, lr, lsl #2  // location of first dex register value.
+     .if \is_static
+     cmp ip, #2
+     blt .Lone_arg_fast_path_range_\suffix
+     beq .Ltwo_args_fast_path_range_\suffix
+     cmp ip, #3
+     .else
+     cmp ip, #3
+     blt .Ltwo_args_fast_path_range_\suffix
+     .endif
+     beq .Lthree_args_fast_path_range_\suffix
+     add rINST, sp, #4  // Add space for the ArtMethod
+
+.Lloop_over_fast_path_range_\suffix:
+     sub ip, ip, #1
+     ldr r3, [lr, ip, lsl #2]
+     str r3, [rINST, ip, lsl #2]
+     cmp ip, #3
+     bne .Lloop_over_fast_path_range_\suffix
+
+.Lthree_args_fast_path_range_\suffix:
+     ldr r3, [lr, #8]
+.Ltwo_args_fast_path_range_\suffix:
+     ldr r2, [lr, #4]
+.Lone_arg_fast_path_range_\suffix:
+     .if \is_static
+     ldr r1, [lr, #0]
+     .else
+     // First argument already in r1.
+     .endif
+.Linvoke_fast_path_range_\suffix:
+     .if \is_interface
+     // Setup hidden argument.
+     mov ip, r4
+     .endif
+     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
+     blx lr
+     FETCH_ADVANCE_INST 3
+     GET_INST_OPCODE ip
+     GOTO_OPCODE ip
+
+.Lfast_path_with_few_args_range_\suffix:
+     // Fast path when we have zero or one argument (modulo 'this'). If there
+     // is one argument, we can put it in both floating point and core register.
+     FETCH_B r2, 0, 1 // number of arguments
+     .if \is_static
+     cmp r2, #1
+     blt .Linvoke_with_few_args_range_\suffix
+     bne .Lget_shorty_range_\suffix
+     FETCH r3, 2  // dex register of first argument
+     GET_VREG r1, r3
+     vmov s0, r1
+     .else
+     cmp r2, #2
+     blt .Linvoke_with_few_args_range_\suffix
+     bne .Lget_shorty_range_\suffix
+     FETCH r3, 2  // dex register of first argument
+     add r3, r3, #1  // Add 1 for next argument
+     GET_VREG r2, r3
+     vmov s0, r2
+     .endif
+.Linvoke_with_few_args_range_\suffix:
+     // Check if the next instruction is move-result or move-result-wide.
+     // If it is, we fetch the shorty and jump to the regular invocation.
+     FETCH r3, 3
+     and r3, r3, #0xfe
+     cmp r3, #0x0a
+     beq .Lget_shorty_and_invoke_range_\suffix
+     .if \is_interface
+     // Setup hidden argument.
+     mov ip, r4
+     .endif
+     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
+     blx lr
+     FETCH_ADVANCE_INST 3
+     GET_INST_OPCODE ip
+     GOTO_OPCODE ip
+.Lget_shorty_and_invoke_range_\suffix:
+     .if \is_interface
+     // Save hidden argument.
+     vmov s16, r4
+     .endif
+     GET_SHORTY_SLOW_PATH rINST, \is_interface
+     b .Lgpr_setup_finished_range_\suffix
+   .endif
+
+.Lget_shorty_range_\suffix:
+   .if \is_interface
+   // Save hidden argument.
+   vmov s16, r4
+   .endif
+   GET_SHORTY rINST, \is_interface, \is_polymorphic, \is_custom
+   // From this point:
+   // - rINST contains shorty (in callee-save to switch over return value after call).
+   // - r0 contains method
+   // - r1 contains 'this' pointer for instance method.
+   //
+   // Save r0 and r1 before calling NterpSetupArm32Fprs.
+   push {r0, r1}
+   add r0, rINST, #1  // shorty + 1  ; ie skip return arg character
+   FETCH r1, 2 // arguments
+   .if \is_string_init
+   add r1, r1, #1  // arg start index
+   mov r2, #1       // index in stack
+   .elseif \is_static
+   mov r2, #0       // index in stack
+   .else
+   add r1, r1, #1  // arg start index
+   mov r2, #1       // index in stack
+   .endif
+   vpush {s0-s15}
+   mov r3, sp
+   // Pass the stack address for arguments, +16 for fprs, +2 for saved registers,
+   // +1 for ArtMethod.
+   add lr, sp, #((16 + 2 + 1) * 4)
+   push {rFP, lr}
+   bl NterpSetupArm32Fprs
+   add sp, sp, #8
+   vpop {s0-s15}
+   pop {r0, r1}
+.Lxmm_setup_finished_range_\suffix:
+   add r8, rINST, #1  // shorty + 1  ; ie skip return arg character
+   FETCH lr, 2 // arguments
+   .if \is_string_init
+   add lr, lr, #1  // arg start index
+   mov r4, #0      // index in stack
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r1, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=0
+   .elseif \is_static
+   mov r4, #0      // index in stack
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r1, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=0
+   .else
+   add lr, lr, #1  // arg start index
+   mov r4, #1       // index in stack
+   .endif
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r2, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=0
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r3, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=1
+.Lif_long_range_\suffix:
+   // Add 1 word for the ArtMethod stored before the outs.
+   add r4, r4, #1
+   LOOP_RANGE_OVER_INTs r8, lr, r4, .Lgpr_setup_finished_range_\suffix
+.Lgpr_setup_finished_range_\suffix:
+   REFRESH_MARKING_REGISTER // r8 was used when setting parameters, restore it.
+   .if \is_polymorphic
+   bl art_quick_invoke_polymorphic
+   .elseif \is_custom
+   bl art_quick_invoke_custom
+   .else
+      .if \is_interface
+      // Setup hidden argument.
+      vmov ip, s16
+      .endif
+      ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
+      blx lr
+   .endif
+   SETUP_RETURN_VALUE rINST
+.Ldone_return_range_\suffix:
+   /* resume execution of caller */
+   .if \is_string_init
+   FETCH ip, 2 // arguments
+   GET_VREG r1, ip
+   UPDATE_REGISTERS_FOR_STRING_INIT r1, r0
+   .endif
+
+   .if \is_polymorphic
+    FETCH_ADVANCE_INST 4
+   .else
+   FETCH_ADVANCE_INST 3
+   .endif
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.endm
+
+.macro WRITE_BARRIER_IF_OBJECT is_object, value, holder, label, tmp
+   .if \is_object
+   // In T32, we would use `SMART_CBZ \value, \label`
+   cmp     \value, #0
+   beq     \label
+   ldr     ip, [rSELF, #THREAD_CARD_TABLE_OFFSET]
+   lsr     \tmp, \holder, #CARD_TABLE_CARD_SHIFT
+   strb    ip, [ip, \tmp]
+\label:
+   .endif
+.endm
+
+.macro LDREXD_STREXD_LOOP addr, load1, load2, store1, store2, tmp, label
+\label:
+   ldrexd  \load1, \load2, [\addr]
+   strexd  \tmp, \store1, \store2, [\addr]
+   cmp     \tmp, #0
+   bne     \label
+.endm
+
+.macro ATOMIC_LOAD64 addr, load1, load2, tmp, label
+   LDREXD_STREXD_LOOP \addr, \load1, \load2, \load1, \load2, \tmp, \label
+.endm
+
+.macro ATOMIC_STORE64 addr, store1, store2, tmp1, tmp2, label
+   LDREXD_STREXD_LOOP \addr, \tmp1, \tmp2, \store1, \store2, \tmp1, \label
+.endm
+
+// Fetch some information from the thread cache.
+// Uses ip and lr as temporaries.
+.macro FETCH_FROM_THREAD_CACHE dest_reg, slow_path
+   add      ip, rSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
+   ubfx     lr, rPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
+   add      ip, ip, lr, lsl #3             // entry address within the cache
+   // In T32, we would use `ldrd ip, \dest_reg, [ip]`
+   ldr      \dest_reg, [ip, #4]            // value (offset)
+   ldr      ip, [ip]                       // entry key (pc)
+   cmp      ip, rPC
+   bne \slow_path
+.endm
+
+// Puts the next int/long/object parameter passed in physical register
+// in the expected dex register array entry, and in case of object in the
+// expected reference array entry.
+// Uses ip as temporary.
+.macro LOOP_OVER_SHORTY_STORING_GPRS gpr_32, shorty, arg_offset, regs, refs, finished, if_long, is_r3
+1: // LOOP
+    ldrb ip, [\shorty], #1       // Load next character in shorty, and increment.
+    cmp ip, #0
+    beq \finished            // if (ip == '\0') goto finished
+    cmp ip, #74                  // if (ip == 'J') goto FOUND_LONG
+    beq 2f
+    cmp ip, #70                  // if (ip == 'F') goto SKIP_FLOAT
+    beq 3f
+    cmp ip, #68                  // if (ip == 'D') goto SKIP_DOUBLE
+    beq 4f
+    str \gpr_32, [\regs, \arg_offset]
+    cmp ip, #76                  // if (ip != 'L') goto NOT_REFERENCE
+    bne 6f
+    str \gpr_32, [\refs, \arg_offset]
+6:  // NOT_REFERENCE
+    add \arg_offset, \arg_offset, #4
+    b 5f
+2:  // FOUND_LONG
+    .if \is_r3
+    // Put back shorty and jump to \if_long
+    sub \shorty, \shorty, #1
+    .else
+    // A long can only be in r2, r3
+    str r2, [\regs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    str r3, [\regs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    .endif
+    b \if_long
+3:  // SKIP_FLOAT
+    add \arg_offset, \arg_offset, #4
+    b 1b
+4:  // SKIP_DOUBLE
+    add \arg_offset, \arg_offset, #8
+    b 1b
+5:
+.endm
+
+// Puts the next int/long/object parameter passed in stack
+// in the expected dex register array entry, and in case of object in the
+// expected reference array entry.
+.macro LOOP_OVER_INTs shorty, arg_offset, regs, refs, stack_ptr, tmp1, tmp2, finished
+1: // LOOP
+    ldrb \tmp1, [\shorty], #1       // Load next character in shorty, and increment.
+    cmp \tmp1, #0
+    beq \finished                   // if (\tmp1 == '\0') goto finished
+    cmp \tmp1, #74                  // if (\tmp1 == 'J') goto FOUND_LONG
+    beq 2f
+    cmp \tmp1, #70                  // if (\tmp1 == 'F') goto SKIP_FLOAT
+    beq 3f
+    cmp \tmp1, #68                  // if (\tmp1 == 'D') goto SKIP_DOUBLE
+    beq 4f
+    add \tmp2, \stack_ptr, \arg_offset
+    ldr \tmp2, [\tmp2,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
+    str \tmp2, [\regs, \arg_offset]
+    cmp \tmp1, #76                  // if (\tmp1 != 'L') goto loop
+    bne 3f
+    str \tmp2, [\refs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    b 1b
+2:  // FOUND_LONG
+    add \tmp1, \stack_ptr, \arg_offset
+    ldr \tmp1, [\tmp1,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
+    str \tmp1, [\regs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    add \tmp1, \stack_ptr, \arg_offset
+    ldr \tmp1, [\tmp1,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
+    str \tmp1, [\regs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    b 1b
+3:  // SKIP_FLOAT
+    add \arg_offset, \arg_offset, #4
+    b 1b
+4:  // SKIP_DOUBLE
+    add \arg_offset, \arg_offset, #8
+    b 1b
+.endm
+
+.macro SETUP_REFERENCE_PARAMETER_IN_GPR gpr32, regs, refs, ins, arg_offset, finished
+    str \gpr32, [\regs, \arg_offset]
+    subs \ins, \ins, #1
+    str \gpr32, [\refs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    beq \finished
+.endm
+
+.macro SETUP_REFERENCE_PARAMETERS_IN_STACK regs, refs, ins, stack_ptr, arg_offset
+1:
+    ldr ip, [\stack_ptr, \arg_offset]
+    subs \ins, \ins, #1
+    str ip, [\regs, \arg_offset]
+    str ip, [\refs, \arg_offset]
+    add \arg_offset, \arg_offset, #4
+    bne 1b
+.endm
+
+%def entry():
+/*
+ * ArtMethod entry point.
+ *
+ * On entry:
+ *  r0   ArtMethod* callee
+ *  rest  method parameters
+ */
+
+OAT_ENTRY ExecuteNterpImpl, EndExecuteNterpImpl
+    .cfi_startproc
+    sub ip, sp, #STACK_OVERFLOW_RESERVED_BYTES
+    ldr ip, [ip]
+    /* Spill callee save regs */
+    SPILL_ALL_CALLEE_SAVES
+
+    ldr rPC, [r0, #ART_METHOD_DATA_OFFSET_32]
+
+    // Setup the stack for executing the method.
+    SETUP_STACK_FRAME rPC, rREFS, rFP, CFI_REFS, load_ins=1
+
+    // Setup the parameters
+    cmp r4, #0
+    beq .Lxmm_setup_finished
+
+    sub rINST, rINST, r4
+    ldr r8, [r0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
+    lsl rINST, rINST, #2 // rINST is now the offset for inputs into the registers array.
+    mov rIBASE, ip // rIBASE contains the old stack pointer
+
+    tst r8, #ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG
+    beq .Lsetup_slow_path
+    // Setup pointer to inputs in FP and pointer to inputs in REFS
+    add lr, rFP, rINST
+    add r8, rREFS, rINST
+    mov r0, #0
+    SETUP_REFERENCE_PARAMETER_IN_GPR r1, lr, r8, r4, r0, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR r2, lr, r8, r4, r0, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR r3, lr, r8, r4, r0, .Lxmm_setup_finished
+    add rIBASE, rIBASE, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK
+    SETUP_REFERENCE_PARAMETERS_IN_STACK lr, r8, r4, rIBASE, r0
+    b .Lxmm_setup_finished
+
+.Lsetup_slow_path:
+    // If the method is not static and there is one argument ('this'), we don't need to fetch the
+    // shorty.
+    tst r8, #ART_METHOD_IS_STATIC_FLAG
+    bne .Lsetup_with_shorty
+    str r1, [rFP, rINST]
+    str r1, [rREFS, rINST]
+    cmp r4, #1
+    beq .Lxmm_setup_finished
+
+.Lsetup_with_shorty:
+    // Save arguments that were passed before calling into the runtime.
+    // No need to save r0 (ArtMethod) as we're not using it later in this code.
+    // Save r4 for stack aligment.
+    // TODO: Get shorty in a better way and remove below
+    push {r1-r4}
+    vpush {s0-s15}
+    bl NterpGetShorty
+    vpop {s0-s15}
+    pop {r1-r4}
+
+    mov ip, r8
+    add r8, rREFS, rINST
+    add r7, rFP, rINST
+    mov r4, #0
+    // Setup shorty, pointer to inputs in FP and pointer to inputs in REFS
+    add lr, r0, #1  // shorty + 1  ; ie skip return arg character
+    tst ip, #ART_METHOD_IS_STATIC_FLAG
+    bne .Lhandle_static_method
+    add r7, r7, #4
+    add r8, r8, #4
+    add rIBASE, rIBASE, #4
+    b .Lcontinue_setup_gprs
+.Lhandle_static_method:
+    LOOP_OVER_SHORTY_STORING_GPRS r1, lr, r4, r7, r8, .Lgpr_setup_finished, .Lif_long, is_r3=0
+.Lcontinue_setup_gprs:
+    LOOP_OVER_SHORTY_STORING_GPRS r2, lr, r4, r7, r8, .Lgpr_setup_finished, .Lif_long, is_r3=0
+    LOOP_OVER_SHORTY_STORING_GPRS r3, lr, r4, r7, r8, .Lgpr_setup_finished, .Lif_long, is_r3=1
+.Lif_long:
+    LOOP_OVER_INTs lr, r4, r7, r8, rIBASE, ip, r1, .Lgpr_setup_finished
+.Lgpr_setup_finished:
+    add r0, r0, #1  // shorty + 1  ; ie skip return arg character
+    mov r1, r7
+    add r2, rIBASE, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK
+    vpush {s0-s15}
+    mov r3, sp
+    bl NterpStoreArm32Fprs
+    add sp, sp, #(16 * 4)
+.Lxmm_setup_finished:
+    CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
+    // r8 was used for setting up the frame, restore it now.
+    REFRESH_MARKING_REGISTER
+.Lexecute_instructions:
+    // Set rIBASE
+    adr rIBASE, artNterpAsmInstructionStart
+    /* start executing the instruction at rPC */
+    START_EXECUTING_INSTRUCTIONS
+    /* NOTE: no fallthrough */
+    // cfi info continues, and covers the whole nterp implementation.
+    SIZE ExecuteNterpImpl
+
+%def opcode_pre():
+
+%def helpers():
+
+%def footer():
+/*
+ * ===========================================================================
+ *  Common subroutines and data
+ * ===========================================================================
+ */
+
+    .text
+    .align  2
+
+// Enclose all code below in a symbol (which gets printed in backtraces).
+NAME_START nterp_helper
+
+// Note: mterp also uses the common_* names below for helpers, but that's OK
+// as the assembler compiled each interpreter separately.
+common_errDivideByZero:
+    EXPORT_PC
+    bl art_quick_throw_div_zero
+
+// Expect index in r1, length in r3
+common_errArrayIndex:
+    EXPORT_PC
+    mov r0, r1
+    mov r1, r3
+    bl art_quick_throw_array_bounds
+
+common_errNullObject:
+    EXPORT_PC
+    bl art_quick_throw_null_pointer_exception
+
+NterpCommonInvokeStatic:
+    COMMON_INVOKE_NON_RANGE is_static=1, suffix="invokeStatic"
+
+NterpCommonInvokeStaticRange:
+    COMMON_INVOKE_RANGE is_static=1, suffix="invokeStatic"
+
+NterpCommonInvokeInstance:
+    COMMON_INVOKE_NON_RANGE suffix="invokeInstance"
+
+NterpCommonInvokeInstanceRange:
+    COMMON_INVOKE_RANGE suffix="invokeInstance"
+
+NterpCommonInvokeInterface:
+    COMMON_INVOKE_NON_RANGE is_interface=1, suffix="invokeInterface"
+
+NterpCommonInvokeInterfaceRange:
+    COMMON_INVOKE_RANGE is_interface=1, suffix="invokeInterface"
+
+NterpCommonInvokePolymorphic:
+    COMMON_INVOKE_NON_RANGE is_polymorphic=1, suffix="invokePolymorphic"
+
+NterpCommonInvokePolymorphicRange:
+    COMMON_INVOKE_RANGE is_polymorphic=1, suffix="invokePolymorphic"
+
+NterpCommonInvokeCustom:
+    COMMON_INVOKE_NON_RANGE is_static=1, is_custom=1, suffix="invokeCustom"
+
+NterpCommonInvokeCustomRange:
+    COMMON_INVOKE_RANGE is_static=1, is_custom=1, suffix="invokeCustom"
+
+NterpHandleStringInit:
+   COMMON_INVOKE_NON_RANGE is_string_init=1, suffix="stringInit"
+
+NterpHandleStringInitRange:
+   COMMON_INVOKE_RANGE is_string_init=1, suffix="stringInit"
+
+NterpNewArray:
+   /* new-array vA, vB, class@CCCC */
+   EXPORT_PC
+   // Fast-path which gets the class from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r0, 2f
+   cmp rMR, #0
+   bne 3f
+1:
+   lsr     r1, rINST, #12              // r1<- B
+   GET_VREG r1, r1                     // r1<- vB (array length)
+   ldr lr, [rSELF, #THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET]
+   blx lr
+   ubfx    r1, rINST, #8, #4           // r1<- A
+   SET_VREG_OBJECT r0, r1
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+2:
+   mov r0, rSELF
+   ldr r1, [sp]
+   mov r2, rPC
+   bl nterp_get_class_or_allocate_object
+   b 1b
+3:
+   bl art_quick_read_barrier_mark_reg00
+   b 1b
+
+
+NterpHandleHotnessOverflow:
+    add r1, rPC, rINST, lsl #1
+    mov r2, rFP
+    bl nterp_hot_method
+    cmp r0, #0
+    bne 1f
+    add r2, rINST, rINST                // w2<- byte offset
+    FETCH_ADVANCE_INST_RB r2            // update rPC, load rINST
+    GET_INST_OPCODE ip                  // extract opcode from rINST
+    GOTO_OPCODE ip                      // jump to next instruction
+1:
+    // Drop the current frame.
+    ldr ip, [rREFS, #-4]
+    mov sp, ip
+    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
+
+    // The transition frame of type SaveAllCalleeSaves saves r4, r8, and r9,
+    // but not managed ABI. So we need to restore callee-saves of the nterp frame,
+    // and save managed ABI callee saves, which will be restored by the callee upon
+    // return.
+
+    RESTORE_ALL_CALLEE_SAVES
+    push {r5-r7, r10-r11, lr}
+   .cfi_adjust_cfa_offset 24
+   .cfi_rel_offset r5, 0
+   .cfi_rel_offset r6, 4
+   .cfi_rel_offset r7, 8
+   .cfi_rel_offset r10, 12
+   .cfi_rel_offset r11, 16
+   .cfi_rel_offset lr, 20
+    vpush {s16-s31}
+    .cfi_adjust_cfa_offset 64
+
+    // Setup the new frame
+    ldr r1, [r0, #OSR_DATA_FRAME_SIZE]
+    // Given stack size contains all callee saved registers, remove them.
+    sub r1, r1, #(CALLEE_SAVES_SIZE - 12)
+
+    // We know r1 cannot be 0, as it at least contains the ArtMethod.
+
+    // Remember CFA in a callee-save register.
+    mov rINST, sp
+    .cfi_def_cfa_register rINST
+
+    sub sp, sp, r1
+
+    add r2, r0, #OSR_DATA_MEMORY
+2:
+    sub r1, r1, #4
+    ldr ip, [r2, r1]
+    str ip, [sp, r1]
+    cmp r1, #0
+    bne 2b
+
+    // Fetch the native PC to jump to and save it in a callee-save register.
+    ldr rFP, [r0, #OSR_DATA_NATIVE_PC]
+
+    // Free the memory holding OSR Data.
+    bl free
+
+    // Jump to the compiled code.
+    bx rFP
+// This is the logical end of ExecuteNterpImpl, where the frame info applies.
+// EndExecuteNterpImpl includes the methods below as we want the runtime to
+// see them as part of the Nterp PCs.
+.cfi_endproc
+
+nterp_to_nterp_static_non_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=1, is_string_init=0
+    .cfi_endproc
+
+nterp_to_nterp_string_init_non_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
+    .cfi_endproc
+
+nterp_to_nterp_instance_non_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
+    .cfi_endproc
+
+nterp_to_nterp_static_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=1, is_string_init=0
+    .cfi_endproc
+
+nterp_to_nterp_string_init_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
+    .cfi_endproc
+
+nterp_to_nterp_instance_range:
+    .cfi_startproc
+    SETUP_STACK_FOR_INVOKE
+    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
+    .cfi_endproc
+
+NAME_END nterp_helper
+
+// This is the end of PCs contained by the OatQuickMethodHeader created for the interpreter
+// entry point.
+    .type EndExecuteNterpImpl, #function
+    .hidden EndExecuteNterpImpl
+    .global EndExecuteNterpImpl
+EndExecuteNterpImpl:
+
+/*
+ * Convert the double in r0/r1 to a long in r0/r1.
+ *
+ * We have to clip values to long min/max per the specification.  The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer.  The EABI convert function isn't doing this for us.
+ */
+nterp_d2l_doconv:
+    ubfx    r2, r1, #20, #11            @ grab the exponent
+    movw    r3, #0x43e
+    cmp     r2, r3                      @ MINLONG < x > MAXLONG?
+    bhs     d2l_special_cases
+    b       __aeabi_d2lz                @ tail call to convert double to long
+d2l_special_cases:
+    movw    r3, #0x7ff
+    cmp     r2, r3
+    beq     d2l_maybeNaN                @ NaN?
+d2l_notNaN:
+    adds    r1, r1, r1                  @ sign bit to carry
+    mov     r0, #0xffffffff             @ assume maxlong for lsw
+    mov     r1, #0x7fffffff             @ assume maxlong for msw
+    adc     r0, r0, #0
+    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
+    bx      lr                          @ return
+d2l_maybeNaN:
+    orrs    r3, r0, r1, lsl #12
+    beq     d2l_notNaN                  @ if fraction is non-zero, it's a NaN
+    mov     r0, #0
+    mov     r1, #0
+    bx      lr                          @ return 0 for NaN
+
+/*
+ * Convert the float in r0 to a long in r0/r1.
+ *
+ * We have to clip values to long min/max per the specification.  The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer.  The EABI convert function isn't doing this for us.
+ */
+nterp_f2l_doconv:
+    ubfx    r2, r0, #23, #8             @ grab the exponent
+    cmp     r2, #0xbe                   @ MININT < x > MAXINT?
+    bhs     f2l_special_cases
+    b       __aeabi_f2lz                @ tail call to convert float to long
+f2l_special_cases:
+    cmp     r2, #0xff                   @ NaN or infinity?
+    beq     f2l_maybeNaN
+f2l_notNaN:
+    adds    r0, r0, r0                  @ sign bit to carry
+    mov     r0, #0xffffffff             @ assume maxlong for lsw
+    mov     r1, #0x7fffffff             @ assume maxlong for msw
+    adc     r0, r0, #0
+    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
+    bx      lr                          @ return
+f2l_maybeNaN:
+    lsls    r3, r0, #9
+    beq     f2l_notNaN                  @ if fraction is non-zero, it's a NaN
+    mov     r0, #0
+    mov     r1, #0
+    bx      lr                          @ return 0 for NaN
+
+// Entrypoints into runtime.
+NTERP_TRAMPOLINE nterp_get_static_field, NterpGetStaticField
+NTERP_TRAMPOLINE nterp_get_instance_field_offset, NterpGetInstanceFieldOffset
+NTERP_TRAMPOLINE nterp_filled_new_array, NterpFilledNewArray
+NTERP_TRAMPOLINE nterp_filled_new_array_range, NterpFilledNewArrayRange
+NTERP_TRAMPOLINE nterp_get_class_or_allocate_object, NterpGetClassOrAllocateObject
+NTERP_TRAMPOLINE nterp_get_method, NterpGetMethod
+NTERP_TRAMPOLINE nterp_hot_method, NterpHotMethod
+NTERP_TRAMPOLINE nterp_load_object, NterpLoadObject
+
+// gen_mterp.py will inline the following definitions
+// within [ExecuteNterpImpl, EndExecuteNterpImpl).
+%def instruction_end():
+
+    .type artNterpAsmInstructionEnd, #object
+    .hidden artNterpAsmInstructionEnd
+    .global artNterpAsmInstructionEnd
+artNterpAsmInstructionEnd:
+    // artNterpAsmInstructionEnd is used as landing pad for exception handling.
+    FETCH_INST
+    GET_INST_OPCODE ip
+    GOTO_OPCODE ip
+
+%def instruction_start():
+
+    .type artNterpAsmInstructionStart, #object
+    .hidden artNterpAsmInstructionStart
+    .global artNterpAsmInstructionStart
+artNterpAsmInstructionStart = .L_op_nop
+    .text
+
+%def default_helper_prefix():
+%  return "nterp_"
+
+%def opcode_start():
+    NAME_START nterp_${opcode}
+%def opcode_end():
+    NAME_END nterp_${opcode}
+%def helper_start(name):
+    NAME_START ${name}
+%def helper_end(name):
+    NAME_END ${name}
diff --git a/runtime/interpreter/mterp/armng/object.S b/runtime/interpreter/mterp/armng/object.S
new file mode 100644
index 0000000..c56ec05
--- /dev/null
+++ b/runtime/interpreter/mterp/armng/object.S
@@ -0,0 +1,462 @@
+%def op_check_cast():
+   // Fast-path which gets the class from thread-local cache.
+   EXPORT_PC
+   FETCH_FROM_THREAD_CACHE r1, 3f
+   cmp     rMR, #0
+   bne     4f
+1:
+   lsr     r2, rINST, #8               // r2<- A
+   GET_VREG r0, r2                     // r0<- vA (object)
+   cmp     r0, #0
+   beq     2f
+   bl      art_quick_check_instance_of
+2:
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+3:
+   mov     r0, rSELF
+   ldr     r1, [sp]
+   mov     r2, rPC
+   bl      nterp_get_class_or_allocate_object
+   mov     r1, r0
+   b       1b
+4:
+   bl      art_quick_read_barrier_mark_reg01
+   b       1b
+
+%def op_instance_of():
+   /* instance-of vA, vB, class@CCCC */
+   // Fast-path which gets the class from thread-local cache.
+   EXPORT_PC
+   FETCH_FROM_THREAD_CACHE r1, 3f
+   cmp     rMR, #0
+   bne     4f
+1:
+   lsr     r2, rINST, #12              // r2<- B
+   GET_VREG r0, r2                     // r0<- vB (object)
+   cmp     r0, #0
+   beq     2f
+   bl      artInstanceOfFromCode
+2:
+   ubfx    r1, rINST, #8, #4           // r1<- A
+   SET_VREG r0, r1
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+3:
+   mov     r0, rSELF
+   ldr     r1, [sp]
+   mov     r2, rPC
+   bl      nterp_get_class_or_allocate_object
+   mov     r1, r0
+   b       1b
+4:
+   bl      art_quick_read_barrier_mark_reg01
+   b       1b
+
+%def op_iget_boolean():
+%  op_iget(load="ldrb", wide="0", is_object="0")
+
+%def op_iget_byte():
+%  op_iget(load="ldrsb", wide="0", is_object="0")
+
+%def op_iget_char():
+%  op_iget(load="ldrh", wide="0", is_object="0")
+
+%def op_iget_short():
+%  op_iget(load="ldrsh", wide="0", is_object="0")
+
+%def op_iget(load="ldr", wide="0", is_object="0"):
+%  slow_path = add_helper(lambda: op_iget_slow_path(load, wide, is_object))
+   // Fast-path which gets the field from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r0, ${slow_path}
+.L${opcode}_resume:
+   lsr     r2, rINST, #12              // r2<- B
+   GET_VREG r3, r2                     // r3<- object we're operating on
+   ubfx    r2, rINST, #8, #4           // r2<- A
+   cmp     r3, #0
+   beq     common_errNullObject        // object was null
+   .if $wide
+   add     r3, r3, r0
+   ldrd    r0, r1, [r3]
+   CLEAR_SHADOW_PAIR r2, ip, lr
+   VREG_INDEX_TO_ADDR r2, r2
+   SET_VREG_WIDE_BY_ADDR r0, r1, r2    // fp[A] <- value
+   .elseif $is_object
+   $load   r0, [r3, r0]
+   cmp     rMR, #0
+   bne     .L${opcode}_read_barrier
+.L${opcode}_resume_after_read_barrier:
+   SET_VREG_OBJECT r0, r2              // fp[A] <- value
+   .else
+   $load   r0, [r3, r0]
+   SET_VREG r0, r2                     // fp[A] <- value
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+   .if $is_object
+.L${opcode}_read_barrier:
+   bl      art_quick_read_barrier_mark_reg00
+   b       .L${opcode}_resume_after_read_barrier
+   .endif
+
+%def op_iget_slow_path(load, wide, is_object):
+   mov     r0, rSELF
+   ldr     r1, [sp]
+   mov     r2, rPC
+   mov     r3, #0
+   EXPORT_PC
+   bl      nterp_get_instance_field_offset
+   cmp     r0, #0
+   bge     .L${opcode}_resume
+   CLEAR_INSTANCE_VOLATILE_MARKER r0
+   lsr     r2, rINST, #12              // r2<- B
+   GET_VREG r3, r2                     // r3<- object we're operating on
+   ubfx    r2, rINST, #8, #4           // r2<- A
+   cmp     r3, #0
+   beq     common_errNullObject            // object was null
+   .if $wide
+   add     ip, r3, r0
+   ATOMIC_LOAD64 ip, r0, r1, r3, .L${opcode}_slow_path_atomic_load
+   dmb     ish
+   CLEAR_SHADOW_PAIR r2, ip, lr
+   VREG_INDEX_TO_ADDR r2, r2
+   SET_VREG_WIDE_BY_ADDR r0, r1, r2    // fp[A] <- value
+   .else
+   $load   r0, [r3, r0]
+   dmb     ish
+   .if $is_object
+   cmp     rMR, #0
+   bne     .L${opcode}_read_barrier
+   SET_VREG_OBJECT r0, r2              // fp[A] <- value
+   .else
+   SET_VREG r0, r2                     // fp[A] <- value
+   .endif
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+
+%def op_iget_wide():
+%  op_iget(load="ldr", wide="1", is_object="0")
+
+%def op_iget_object():
+%  op_iget(load="ldr", wide="0", is_object="1")
+
+%def op_iput_boolean():
+%  op_iput(store="strb", wide="0", is_object="0")
+
+%def op_iput_byte():
+%  op_iput(store="strb", wide="0", is_object="0")
+
+%def op_iput_char():
+%  op_iput(store="strh", wide="0", is_object="0")
+
+%def op_iput_short():
+%  op_iput(store="strh", wide="0", is_object="0")
+
+%def op_iput(store="str", wide="0", is_object="0"):
+   // Share slow paths for boolean and byte (strb) and slow paths for char and short (strh).
+   // It does not matter to which `.L${opcode}_resume` the slow path returns.
+%  slow_path = "nterp_op_iput_helper_" + store + wide + is_object
+%  add_helper(lambda: op_iput_slow_path(store, wide, is_object), slow_path)
+   .if !$wide
+   ubfx    r4, rINST, #8, #4           // r4<- A
+   GET_VREG r4, r4                     // r4 <- v[A]
+   .endif
+   // Fast-path which gets the field from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r0, ${slow_path}
+.L${opcode}_resume:
+   lsr     r1, rINST, #12              // r1<- B
+   GET_VREG r1, r1                     // vB (object we're operating on)
+   cmp     r1, #0
+   beq     common_errNullObject
+   .if $wide
+   ubfx    r4, rINST, #8, #4           // r4<- A
+   VREG_INDEX_TO_ADDR r4, r4
+   GET_VREG_WIDE_BY_ADDR r2, r3, r4      // fp[A] <- value
+   add     r1, r1, r0
+   strd    r2, r3, [r1]
+   .else
+   $store  r4, [r1, r0]
+   WRITE_BARRIER_IF_OBJECT $is_object, r4, r1, .L${opcode}_skip_write_barrier, r0
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+
+%def op_iput_slow_path(store, wide, is_object):
+   mov     r0, rSELF
+   ldr     r1, [sp]
+   mov     r2, rPC
+   .if $is_object
+   mov     r3, r4
+   .else
+   mov     r3, #0
+   .endif
+   EXPORT_PC
+   bl      nterp_get_instance_field_offset
+   .if $is_object
+   // Reload the value as it may have moved.
+   ubfx    r4, rINST, #8, #4           // r4<- A
+   GET_VREG r4, r4                     // r4 <- v[A]
+   .endif
+   cmp     r0, #0
+   bge     .L${opcode}_resume
+   CLEAR_INSTANCE_VOLATILE_MARKER r0
+   .if $wide
+   lsr     r4, rINST, #12              // r4<- B
+   ubfx    r1, rINST, #8, #4           // r1<- A
+   GET_VREG r4, r4                     // vB (object we're operating on)
+   cmp     r4, #0
+   beq     common_errNullObject
+   VREG_INDEX_TO_ADDR r1, r1
+   GET_VREG_WIDE_BY_ADDR r2, r3, r1
+   add     ip, r4, r0
+   dmb     ish
+   ATOMIC_STORE64 ip, r2, r3, r0, r1, .L${opcode}_slow_path_atomic_store
+   dmb     ish
+   .else
+   lsr     r1, rINST, #12              // r4<- B
+   GET_VREG r1, r1                     // vB (object we're operating on)
+   cmp     r1, #0
+   beq     common_errNullObject
+   dmb     ish
+   $store  r4, [r1, r0]
+   dmb     ish
+   WRITE_BARRIER_IF_OBJECT $is_object, r4, r1, .L${opcode}_slow_path_skip_write_barrier, r0
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+
+%def op_iput_wide():
+%  op_iput(store="str", wide="1", is_object="0")
+
+%def op_iput_object():
+%  op_iput(store="str", wide="0", is_object="1")
+
+%def op_sget_boolean():
+%  op_sget(load="ldrb", wide="0", is_object="0")
+
+%def op_sget_byte():
+%  op_sget(load="ldrsb", wide="0", is_object="0")
+
+%def op_sget_char():
+%  op_sget(load="ldrh", wide="0", is_object="0")
+
+%def op_sget_short():
+%  op_sget(load="ldrsh", wide="0", is_object="0")
+
+%def op_sget(load="ldr", wide="0", is_object="0"):
+%  slow_path = add_helper(lambda: op_sget_slow_path(load, wide, is_object))
+   // Fast-path which gets the field from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r0, ${slow_path}
+.L${opcode}_resume:
+   ldr     r1, [r0, #ART_FIELD_OFFSET_OFFSET]
+   lsr     r2, rINST, #8               // r2 <- A
+   ldr     r0, [r0, #ART_FIELD_DECLARING_CLASS_OFFSET]
+   cmp     rMR, #0
+   bne     .L${opcode}_read_barrier
+.L${opcode}_resume_after_read_barrier:
+   .if $wide
+   add     r0, r0, r1
+   ldrd    r0, r1, [r0]
+   CLEAR_SHADOW_PAIR r2, ip, lr
+   VREG_INDEX_TO_ADDR r2, r2
+   SET_VREG_WIDE_BY_ADDR r0, r1, r2    // fp[A] <- value
+   .elseif $is_object
+   $load   r0, [r0, r1]
+   // No need to check the marking register, we know it's not set here.
+.L${opcode}_after_reference_load:
+   SET_VREG_OBJECT r0, r2              // fp[A] <- value
+   .else
+   $load   r0, [r0, r1]
+   SET_VREG r0, r2                     // fp[A] <- value
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.L${opcode}_read_barrier:
+   bl      art_quick_read_barrier_mark_reg00
+   .if $is_object
+   ldr     r0, [r0, r1]
+.L${opcode}_mark_after_load:
+   // Here, we know the marking register is set.
+   bl      art_quick_read_barrier_mark_reg00
+   b       .L${opcode}_after_reference_load
+   .else
+   b       .L${opcode}_resume_after_read_barrier
+   .endif
+
+%def op_sget_slow_path(load="ldr", wide="0", is_object="0"):
+   mov     r0, rSELF
+   ldr     r1, [sp]
+   mov     r2, rPC
+   mov     r3, #0
+   EXPORT_PC
+   bl      nterp_get_static_field
+   tst     r0, #1
+   beq     .L${opcode}_resume
+   CLEAR_STATIC_VOLATILE_MARKER r0
+   ldr     r1, [r0, #ART_FIELD_OFFSET_OFFSET]
+   lsr     r2, rINST, #8               // r2 <- A
+   ldr     r0, [r0, #ART_FIELD_DECLARING_CLASS_OFFSET]
+   cmp     rMR, #0
+   bne     .L${opcode}_slow_path_read_barrier
+.L${opcode}_slow_path_resume_after_read_barrier:
+   .if $wide
+   add     ip, r0, r1
+   ATOMIC_LOAD64 ip, r0, r1, r3, .L${opcode}_slow_path_atomic_load
+   dmb     ish
+   CLEAR_SHADOW_PAIR r2, ip, lr
+   VREG_INDEX_TO_ADDR r2, r2
+   SET_VREG_WIDE_BY_ADDR r0, r1, r2    // fp[A] <- value
+   .else
+   $load   r0, [r0, r1]
+   dmb     ish
+   .if $is_object
+   cmp     rMR, #0
+   bne     .L${opcode}_mark_after_load
+   SET_VREG_OBJECT r0, r2              // fp[A] <- value
+   .else
+   SET_VREG r0, r2                     // fp[A] <- value
+   .endif
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.L${opcode}_slow_path_read_barrier:
+   bl      art_quick_read_barrier_mark_reg00
+   b       .L${opcode}_slow_path_resume_after_read_barrier
+
+%def op_sget_wide():
+%  op_sget(load="ldr", wide="1", is_object="0")
+
+%def op_sget_object():
+%  op_sget(load="ldr", wide="0", is_object="1")
+
+%def op_sput_boolean():
+%  op_sput(store="strb", wide="0", is_object="0")
+
+%def op_sput_byte():
+%  op_sput(store="strb", wide="0", is_object="0")
+
+%def op_sput_char():
+%  op_sput(store="strh", wide="0", is_object="0")
+
+%def op_sput_short():
+%  op_sput(store="strh", wide="0", is_object="0")
+
+%def op_sput(store="str", wide="0", is_object="0"):
+   // Share slow paths for boolean and byte (strb) and slow paths for char and short (strh).
+   // It does not matter to which `.L${opcode}_resume` the slow path returns.
+%  slow_path = "nterp_op_sput_helper_" + store + wide + is_object
+%  add_helper(lambda: op_sput_slow_path(store, wide, is_object), slow_path)
+   .if !$wide
+   lsr     r4, rINST, #8               // r4 <- A
+   GET_VREG r4, r4                     // r4 <- v[A]
+   .endif
+   // Fast-path which gets the field from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r0, ${slow_path}
+.L${opcode}_resume:
+   ldr     r1, [r0, #ART_FIELD_OFFSET_OFFSET]
+   ldr     r0, [r0, #ART_FIELD_DECLARING_CLASS_OFFSET]
+   cmp     rMR, #0
+   bne     .L${opcode}_read_barrier
+.L${opcode}_resume_after_read_barrier:
+   .if $wide
+   lsr     r2, rINST, #8               // r2 <- A
+   VREG_INDEX_TO_ADDR r2, r2
+   GET_VREG_WIDE_BY_ADDR r2, r3, r2    // fp[A] <- value
+   add     r0, r0, r1
+   strd    r2, r3, [r0]
+   .else
+   $store  r4, [r0, r1]
+   WRITE_BARRIER_IF_OBJECT $is_object, r4, r0, .L${opcode}_skip_write_barrier, r1
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.L${opcode}_read_barrier:
+   bl      art_quick_read_barrier_mark_reg00
+   b       .L${opcode}_resume_after_read_barrier
+
+%def op_sput_slow_path(store, wide, is_object):
+   mov     r0, rSELF
+   ldr     r1, [sp]
+   mov     r2, rPC
+   .if $is_object
+   mov     r3, r4
+   .else
+   mov     r3, #0
+   .endif
+   EXPORT_PC
+   bl      nterp_get_static_field
+   .if $is_object
+   // Reload the value as it may have moved.
+   lsr     r4, rINST, #8               // r4 <- A
+   GET_VREG r4, r4                     // r4 <- v[A]
+   .endif
+   tst     r0, #1
+   beq     .L${opcode}_resume
+   CLEAR_STATIC_VOLATILE_MARKER r0
+   ldr     r1, [r0, #ART_FIELD_OFFSET_OFFSET]
+   ldr     r0, [r0, #ART_FIELD_DECLARING_CLASS_OFFSET]
+   cmp     rMR, #0
+   bne     .L${opcode}_slow_path_read_barrier
+.L${opcode}_slow_path_resume_after_read_barrier:
+   .if $wide
+   lsr     r2, rINST, #8               // r2 <- A
+   VREG_INDEX_TO_ADDR r2, r2
+   GET_VREG_WIDE_BY_ADDR r2, r3, r2
+   add     ip, r0, r1
+   dmb     ish
+   ATOMIC_STORE64 ip, r2, r3, r0, r1, .L${opcode}_slow_path_atomic_store
+   dmb     ish
+   .else
+   dmb     ish
+   $store  r4, [r0, r1]
+   dmb     ish
+   WRITE_BARRIER_IF_OBJECT $is_object, r4, r0, .L${opcode}_slow_path_skip_write_barrier, r1
+   .endif
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+.L${opcode}_slow_path_read_barrier:
+   bl      art_quick_read_barrier_mark_reg00
+   b       .L${opcode}_slow_path_resume_after_read_barrier
+
+%def op_sput_wide():
+%  op_sput(store="str", wide="1", is_object="0")
+
+%def op_sput_object():
+%  op_sput(store="str", wide="0", is_object="1")
+
+%def op_new_instance():
+   // The routine is too big to fit in a handler, so jump to it.
+   EXPORT_PC
+   // Fast-path which gets the class from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r0, 2f
+   cmp     rMR, #0
+   bne     3f
+4:
+   ldr     lr, [rSELF, #THREAD_ALLOC_OBJECT_ENTRYPOINT_OFFSET]
+   blx     lr
+1:
+   lsr     r1, rINST, #8                    // r1 <- A
+   SET_VREG_OBJECT r0, r1               // fp[A] <- value
+   FETCH_ADVANCE_INST 2
+   GET_INST_OPCODE ip
+   GOTO_OPCODE ip
+2:
+   mov     r0, rSELF
+   ldr     r1, [sp]
+   mov     r2, rPC
+   bl      nterp_get_class_or_allocate_object
+   b       1b
+3:
+   bl      art_quick_read_barrier_mark_reg00
+   b       4b
diff --git a/runtime/interpreter/mterp/armng/other.S b/runtime/interpreter/mterp/armng/other.S
new file mode 100644
index 0000000..063be34
--- /dev/null
+++ b/runtime/interpreter/mterp/armng/other.S
@@ -0,0 +1,409 @@
+%def unused():
+    bkpt
+
+%def op_const():
+    /* const vAA, #+BBBBbbbb */
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH r0, 1                         @ r0<- bbbb (low)
+    FETCH r1, 2                         @ r1<- BBBB (high)
+    FETCH_ADVANCE_INST 3                @ advance rPC, load rINST
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG r0, r3                     @ vAA<- r0
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_const_16():
+    /* const/16 vAA, #+BBBB */
+    FETCH_S r0, 1                       @ r0<- ssssBBBB (sign-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    SET_VREG r0, r3                     @ vAA<- r0
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_const_4():
+    /* const/4 vA, #+B */
+    sbfx    r1, rINST, #12, #4          @ r1<- sssssssB (sign-extended)
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    GET_INST_OPCODE ip                  @ ip<- opcode from rINST
+    SET_VREG r1, r0                     @ fp[A]<- r1
+    GOTO_OPCODE ip                      @ execute next instruction
+
+%def op_const_high16():
+    /* const/high16 vAA, #+BBBB0000 */
+    FETCH r0, 1                         @ r0<- 0000BBBB (zero-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    mov     r0, r0, lsl #16             @ r0<- BBBB0000
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    SET_VREG r0, r3                     @ vAA<- r0
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_const_object(jumbo="0", helper="nterp_load_object"):
+   // Fast-path which gets the object from thread-local cache.
+   FETCH_FROM_THREAD_CACHE r0, 2f
+   cmp rMR, #0
+   bne 3f
+1:
+   mov     r1, rINST, lsr #8           @ r1<- AA
+   .if $jumbo
+   FETCH_ADVANCE_INST 3                // advance rPC, load rINST
+   .else
+   FETCH_ADVANCE_INST 2                // advance rPC, load rINST
+   .endif
+   GET_INST_OPCODE ip                  // extract opcode from rINST
+   SET_VREG_OBJECT r0, r1              // vAA <- value
+   GOTO_OPCODE ip                      // jump to next instruction
+2:
+   EXPORT_PC
+   mov r0, rSELF
+   ldr r1, [sp]
+   mov r2, rPC
+   bl $helper
+   b 1b
+3:
+   bl art_quick_read_barrier_mark_reg00
+   b 1b
+
+%def op_const_class():
+%  op_const_object(jumbo="0", helper="nterp_get_class_or_allocate_object")
+
+%def op_const_method_handle():
+%  op_const_object(jumbo="0")
+
+%def op_const_method_type():
+%  op_const_object(jumbo="0")
+
+%def op_const_string():
+   /* const/string vAA, String@BBBB */
+%  op_const_object(jumbo="0")
+
+%def op_const_string_jumbo():
+   /* const/string vAA, String@BBBBBBBB */
+%  op_const_object(jumbo="1")
+
+%def op_const_wide():
+    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
+    FETCH r0, 1                         @ r0<- bbbb (low)
+    FETCH r1, 2                         @ r1<- BBBB (low middle)
+    FETCH r2, 3                         @ r2<- hhhh (high middle)
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
+    FETCH r3, 4                         @ r3<- HHHH (high)
+    mov     r4, rINST, lsr #8           @ r4<- AA
+    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
+    CLEAR_SHADOW_PAIR r4, r2, r3        @ Zero out the shadow regs
+    FETCH_ADVANCE_INST 5                @ advance rPC, load rINST
+    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[AA]
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r4    @ vAA<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_const_wide_16():
+    /* const-wide/16 vAA, #+BBBB */
+    FETCH_S r0, 1                       @ r0<- ssssBBBB (sign-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    mov     r1, r0, asr #31             @ r1<- ssssssss
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    CLEAR_SHADOW_PAIR r3, r2, lr        @ Zero out the shadow regs
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[AA]
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r3    @ vAA<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_const_wide_32():
+    /* const-wide/32 vAA, #+BBBBbbbb */
+    FETCH r0, 1                         @ r0<- 0000bbbb (low)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH_S r2, 2                       @ r2<- ssssBBBB (high)
+    FETCH_ADVANCE_INST 3                @ advance rPC, load rINST
+    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
+    CLEAR_SHADOW_PAIR r3, r2, lr        @ Zero out the shadow regs
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[AA]
+    mov     r1, r0, asr #31             @ r1<- ssssssss
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r3    @ vAA<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_const_wide_high16():
+    /* const-wide/high16 vAA, #+BBBB000000000000 */
+    FETCH r1, 1                         @ r1<- 0000BBBB (zero-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    mov     r0, #0                      @ r0<- 00000000
+    mov     r1, r1, lsl #16             @ r1<- BBBB0000
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    CLEAR_SHADOW_PAIR r3, r0, r2        @ Zero shadow regs
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[AA]
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r3    @ vAA<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_monitor_enter():
+    /*
+     * Synchronize on an object.
+     */
+    /* monitor-enter vAA */
+    EXPORT_PC
+    mov      r2, rINST, lsr #8           @ r2<- AA
+    GET_VREG r0, r2                      @ r0<- vAA (object)
+    bl       art_quick_lock_object
+    FETCH_ADVANCE_INST 1
+    GET_INST_OPCODE ip                   @ extract opcode from rINST
+    GOTO_OPCODE ip                       @ jump to next instruction
+
+%def op_monitor_exit():
+    /*
+     * Unlock an object.
+     *
+     * Exceptions that occur when unlocking a monitor need to appear as
+     * if they happened at the following instruction.  See the Dalvik
+     * instruction spec.
+     */
+    /* monitor-exit vAA */
+    EXPORT_PC
+    mov      r2, rINST, lsr #8          @ r2<- AA
+    GET_VREG r0, r2                     @ r0<- vAA (object)
+    bl       art_quick_unlock_object
+    FETCH_ADVANCE_INST 1                @ before throw: advance rPC, load rINST
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_move(is_object="0"):
+    /* for move, move-object, long-to-int */
+    /* op vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
+    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    GET_VREG r2, r1                     @ r2<- fp[B]
+    GET_INST_OPCODE ip                  @ ip<- opcode from rINST
+    .if $is_object
+    SET_VREG_OBJECT r2, r0              @ fp[A]<- r2
+    .else
+    SET_VREG r2, r0                     @ fp[A]<- r2
+    .endif
+    GOTO_OPCODE ip                      @ execute next instruction
+
+%def op_move_16(is_object="0"):
+    /* for: move/16, move-object/16 */
+    /* op vAAAA, vBBBB */
+    FETCH r1, 2                         @ r1<- BBBB
+    FETCH r0, 1                         @ r0<- AAAA
+    FETCH_ADVANCE_INST 3                @ advance rPC, load rINST
+    GET_VREG r2, r1                     @ r2<- fp[BBBB]
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    .if $is_object
+    SET_VREG_OBJECT r2, r0              @ fp[AAAA]<- r2
+    .else
+    SET_VREG r2, r0                     @ fp[AAAA]<- r2
+    .endif
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_move_exception():
+    /* move-exception vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    ldr     r3, [rSELF, #THREAD_EXCEPTION_OFFSET]
+    mov     r1, #0                      @ r1<- 0
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    SET_VREG_OBJECT r3, r2              @ fp[AA]<- exception obj
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    str     r1, [rSELF, #THREAD_EXCEPTION_OFFSET]  @ clear exception
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_move_from16(is_object="0"):
+    /* for: move/from16, move-object/from16 */
+    /* op vAA, vBBBB */
+    FETCH r1, 1                         @ r1<- BBBB
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    GET_VREG r2, r1                     @ r2<- fp[BBBB]
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    .if $is_object
+    SET_VREG_OBJECT r2, r0              @ fp[AA]<- r2
+    .else
+    SET_VREG r2, r0                     @ fp[AA]<- r2
+    .endif
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_move_object():
+%  op_move(is_object="1")
+
+%def op_move_object_16():
+%  op_move_16(is_object="1")
+
+%def op_move_object_from16():
+%  op_move_from16(is_object="1")
+
+%def op_move_result(is_object="0"):
+    /* for: move-result, move-result-object */
+    /* op vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    .if $is_object
+    SET_VREG_OBJECT r0, r2              @ fp[AA]<- r0
+    .else
+    SET_VREG r0, r2                     @ fp[AA]<- r0
+    .endif
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_move_result_object():
+%  op_move_result(is_object="1")
+
+%def op_move_result_wide():
+    /* move-result-wide vAA */
+    mov     rINST, rINST, lsr #8        @ rINST<- AA
+    VREG_INDEX_TO_ADDR r2, rINST        @ r2<- &fp[AA]
+    CLEAR_SHADOW_PAIR rINST, ip, lr     @ Zero out the shadow regs
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r2    @ fp[AA]<- r0/r1
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_move_wide():
+    /* move-wide vA, vB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    rINST, rINST, #8, #4        @ rINST<- A
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[B]
+    VREG_INDEX_TO_ADDR r2, rINST        @ r2<- &fp[A]
+    GET_VREG_WIDE_BY_ADDR r0, r1, r3    @ r0/r1<- fp[B]
+    CLEAR_SHADOW_PAIR rINST, ip, lr     @ Zero out the shadow regs
+    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r2    @ fp[A]<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_move_wide_16():
+    /* move-wide/16 vAAAA, vBBBB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    FETCH r3, 2                         @ r3<- BBBB
+    FETCH r2, 1                         @ r2<- AAAA
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[BBBB]
+    VREG_INDEX_TO_ADDR lr, r2           @ r2<- &fp[AAAA]
+    GET_VREG_WIDE_BY_ADDR r0, r1, r3    @ r0/r1<- fp[BBBB]
+    FETCH_ADVANCE_INST 3                @ advance rPC, load rINST
+    CLEAR_SHADOW_PAIR r2, r3, ip        @ Zero out the shadow regs
+    SET_VREG_WIDE_BY_ADDR r0, r1, lr    @ fp[AAAA]<- r0/r1
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_move_wide_from16():
+    /* move-wide/from16 vAA, vBBBB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    FETCH r3, 1                         @ r3<- BBBB
+    mov     rINST, rINST, lsr #8        @ rINST<- AA
+    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[BBBB]
+    VREG_INDEX_TO_ADDR r2, rINST        @ r2<- &fp[AA]
+    GET_VREG_WIDE_BY_ADDR r0, r1, r3    @ r0/r1<- fp[BBBB]
+    CLEAR_SHADOW_PAIR rINST, ip, lr     @ Zero out the shadow regs
+    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
+    GET_INST_OPCODE ip                  @ extract opcode from rINST
+    SET_VREG_WIDE_BY_ADDR r0, r1, r2    @ fp[AA]<- r0/r1
+    GOTO_OPCODE ip                      @ jump to next instruction
+
+%def op_nop():
+    FETCH_ADVANCE_INST 1                @ advance to next instr, load rINST
+    GET_INST_OPCODE ip                  @ ip<- opcode from rINST
+    GOTO_OPCODE ip                      @ execute it
+
+%def op_unused_3e():
+%  unused()
+
+%def op_unused_3f():
+%  unused()
+
+%def op_unused_40():
+%  unused()
+
+%def op_unused_41():
+%  unused()
+
+%def op_unused_42():
+%  unused()
+
+%def op_unused_43():
+%  unused()
+
+%def op_unused_73():
+%  unused()
+
+%def op_unused_79():
+%  unused()
+
+%def op_unused_7a():
+%  unused()
+
+%def op_unused_e3():
+%  unused()
+
+%def op_unused_e4():
+%  unused()
+
+%def op_unused_e5():
+%  unused()
+
+%def op_unused_e6():
+%  unused()
+
+%def op_unused_e7():
+%  unused()
+
+%def op_unused_e8():
+%  unused()
+
+%def op_unused_e9():
+%  unused()
+
+%def op_unused_ea():
+%  unused()
+
+%def op_unused_eb():
+%  unused()
+
+%def op_unused_ec():
+%  unused()
+
+%def op_unused_ed():
+%  unused()
+
+%def op_unused_ee():
+%  unused()
+
+%def op_unused_ef():
+%  unused()
+
+%def op_unused_f0():
+%  unused()
+
+%def op_unused_f1():
+%  unused()
+
+%def op_unused_f2():
+%  unused()
+
+%def op_unused_f3():
+%  unused()
+
+%def op_unused_f4():
+%  unused()
+
+%def op_unused_f5():
+%  unused()
+
+%def op_unused_f6():
+%  unused()
+
+%def op_unused_f7():
+%  unused()
+
+%def op_unused_f8():
+%  unused()
+
+%def op_unused_f9():
+%  unused()
+
+%def op_unused_fc():
+%  unused()
+
+%def op_unused_fd():
+%  unused()
diff --git a/runtime/interpreter/mterp/common/gen_setup.py b/runtime/interpreter/mterp/common/gen_setup.py
index 2684ab2..4d18136 100644
--- a/runtime/interpreter/mterp/common/gen_setup.py
+++ b/runtime/interpreter/mterp/common/gen_setup.py
@@ -19,7 +19,7 @@
 # the templated snippets. Those define all the helper functions used below.
 
 import sys, re
-from cStringIO import StringIO
+from io import StringIO
 
 out = StringIO()  # File-like in-memory buffer.
 handler_size_bytes = "MTERP_HANDLER_SIZE"
@@ -52,7 +52,7 @@
 # The output is temporarily redirected to in-memory buffer.
 def add_helper(write_helper, name = None):
   if name == None:
-    name = "mterp_" + opcode + "_helper"
+    name = default_helper_prefix() + opcode + "_helper"
   global out
   old_out = out
   out = StringIO()
diff --git a/runtime/interpreter/mterp/gen_mterp.py b/runtime/interpreter/mterp/gen_mterp.py
index 5d25955..b8bc2e6 100755
--- a/runtime/interpreter/mterp/gen_mterp.py
+++ b/runtime/interpreter/mterp/gen_mterp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2016 The Android Open Source Project
 #
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 import sys, re, os
-from cStringIO import StringIO
+from io import StringIO
 
 SCRIPT_DIR = os.path.dirname(sys.argv[0])
 # This file is included verbatim at the start of the in-memory python script.
@@ -37,9 +37,8 @@
   opcode_fp.close()
 
   if len(opcodes) != NUM_PACKED_OPCODES:
-    print "ERROR: found %d opcodes in Interp.h (expected %d)" \
-        % (len(opcodes), NUM_PACKED_OPCODES)
-    raise SyntaxError, "bad opcode count"
+    print("ERROR: found ", len(opcodes), " opcodes in Interp.h (expected ", NUM_PACKED_OPCODES, ")")
+    raise SyntaxError("bad opcode count")
   return opcodes
 
 indent_re = re.compile(r"^%( *)")
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index c6d3258..ae5e470 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -147,7 +147,6 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   const Runtime* const runtime = Runtime::Current();
   return
-      runtime->IsStarted() &&
       !runtime->IsAotCompiler() &&
       !runtime->GetInstrumentation()->IsActive() &&
       // mterp only knows how to deal with the normal exits. It cannot handle any of the
@@ -160,61 +159,45 @@
       (runtime->GetJit() == nullptr || !runtime->GetJit()->JitAtFirstUse());
 }
 
-
-extern "C" size_t MterpInvokeVirtual(Thread* self,
-                                     ShadowFrame* shadow_frame,
-                                     uint16_t* dex_pc_ptr,
-                                     uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kVirtual, /*is_range=*/ false, /*do_access_check=*/ false, /*is_mterp=*/ true>(
-      self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
+#define MTERP_INVOKE(Name)                                                                         \
+extern "C" size_t MterpInvoke##Name(Thread* self,                                                  \
+                                    ShadowFrame* shadow_frame,                                     \
+                                    uint16_t* dex_pc_ptr,                                          \
+                                    uint16_t inst_data)                                            \
+    REQUIRES_SHARED(Locks::mutator_lock_) {                                                        \
+  JValue* result_register = shadow_frame->GetResultRegister();                                     \
+  const Instruction* inst = Instruction::At(dex_pc_ptr);                                           \
+  if (shadow_frame->GetMethod()->SkipAccessChecks()) {                                             \
+    return DoInvoke<k##Name, /*is_range=*/ false, /*do_access_check=*/ false, /*is_mterp=*/ true>( \
+        self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;                          \
+  } else {                                                                                         \
+    return DoInvoke<k##Name, /*is_range=*/ false, /*do_access_check=*/ true, /*is_mterp=*/ true>(  \
+        self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;                          \
+  }                                                                                                \
+}                                                                                                  \
+extern "C" size_t MterpInvoke##Name##Range(Thread* self,                                           \
+                                           ShadowFrame* shadow_frame,                              \
+                                           uint16_t* dex_pc_ptr,                                   \
+                                           uint16_t inst_data)                                     \
+    REQUIRES_SHARED(Locks::mutator_lock_) {                                                        \
+  JValue* result_register = shadow_frame->GetResultRegister();                                     \
+  const Instruction* inst = Instruction::At(dex_pc_ptr);                                           \
+  if (shadow_frame->GetMethod()->SkipAccessChecks()) {                                             \
+    return DoInvoke<k##Name, /*is_range=*/ true, /*do_access_check=*/ false, /*is_mterp=*/ true>(  \
+        self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;                          \
+  } else {                                                                                         \
+    return DoInvoke<k##Name, /*is_range=*/ true, /*do_access_check=*/ true, /*is_mterp=*/ true>(   \
+        self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;                          \
+  }                                                                                                \
 }
 
-extern "C" size_t MterpInvokeSuper(Thread* self,
-                                   ShadowFrame* shadow_frame,
-                                   uint16_t* dex_pc_ptr,
-                                   uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kSuper, /*is_range=*/ false, /*do_access_check=*/ false, /*is_mterp=*/ true>(
-      self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
+MTERP_INVOKE(Virtual)
+MTERP_INVOKE(Super)
+MTERP_INVOKE(Interface)
+MTERP_INVOKE(Direct)
+MTERP_INVOKE(Static)
 
-extern "C" size_t MterpInvokeInterface(Thread* self,
-                                       ShadowFrame* shadow_frame,
-                                       uint16_t* dex_pc_ptr,
-                                       uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kInterface, /*is_range=*/ false, /*do_access_check=*/ false, /*is_mterp=*/ true>(
-      self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
-
-extern "C" size_t MterpInvokeDirect(Thread* self,
-                                    ShadowFrame* shadow_frame,
-                                    uint16_t* dex_pc_ptr,
-                                    uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kDirect, /*is_range=*/ false, /*do_access_check=*/ false, /*is_mterp=*/ true>(
-      self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
-
-extern "C" size_t MterpInvokeStatic(Thread* self,
-                                    ShadowFrame* shadow_frame,
-                                    uint16_t* dex_pc_ptr,
-                                    uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kStatic, /*is_range=*/ false, /*do_access_check=*/ false, /*is_mterp=*/ true>(
-      self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
+#undef MTERP_INVOKE
 
 extern "C" size_t MterpInvokeCustom(Thread* self,
                                     ShadowFrame* shadow_frame,
@@ -238,61 +221,6 @@
       self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
 }
 
-extern "C" size_t MterpInvokeVirtualRange(Thread* self,
-                                          ShadowFrame* shadow_frame,
-                                          uint16_t* dex_pc_ptr,
-                                          uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kVirtual, /*is_range=*/ true, /*do_access_check=*/ false, /*is_mterp=*/ true>(
-      self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
-
-extern "C" size_t MterpInvokeSuperRange(Thread* self,
-                                        ShadowFrame* shadow_frame,
-                                        uint16_t* dex_pc_ptr,
-                                        uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kSuper, /*is_range=*/ true, /*do_access_check=*/ false, /*is_mterp=*/ true>(
-      self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
-
-extern "C" size_t MterpInvokeInterfaceRange(Thread* self,
-                                            ShadowFrame* shadow_frame,
-                                            uint16_t* dex_pc_ptr,
-                                            uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kInterface, /*is_range=*/ true, /*do_access_check=*/ false, /*is_mterp=*/ true>(
-      self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
-
-extern "C" size_t MterpInvokeDirectRange(Thread* self,
-                                         ShadowFrame* shadow_frame,
-                                         uint16_t* dex_pc_ptr,
-                                         uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kDirect, /*is_range=*/ true, /*do_access_check=*/ false, /*is_mterp=*/ true>(
-      self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
-
-extern "C" size_t MterpInvokeStaticRange(Thread* self,
-                                         ShadowFrame* shadow_frame,
-                                         uint16_t* dex_pc_ptr,
-                                         uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kStatic, /*is_range=*/ true, /*do_access_check=*/ false, /*is_mterp=*/ true>(
-      self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
-
 extern "C" size_t MterpInvokeCustomRange(Thread* self,
                                          ShadowFrame* shadow_frame,
                                          uint16_t* dex_pc_ptr,
@@ -315,28 +243,6 @@
       self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
 }
 
-extern "C" size_t MterpInvokeVirtualQuick(Thread* self,
-                                          ShadowFrame* shadow_frame,
-                                          uint16_t* dex_pc_ptr,
-                                          uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kVirtual, /*is_range=*/ false, /*do_access_check=*/ false, /*is_mterp=*/ true,
-      /*is_quick=*/ true>(self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
-
-extern "C" size_t MterpInvokeVirtualQuickRange(Thread* self,
-                                               ShadowFrame* shadow_frame,
-                                               uint16_t* dex_pc_ptr,
-                                               uint16_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue* result_register = shadow_frame->GetResultRegister();
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoInvoke<kVirtual, /*is_range=*/ true, /*do_access_check=*/ false, /*is_mterp=*/ true,
-      /*is_quick=*/ true>(self, *shadow_frame, inst, inst_data, result_register) ? 1u : 0u;
-}
-
 extern "C" void MterpThreadFenceForConstructor() {
   QuasiAtomic::ThreadFenceForConstructor();
 }
@@ -359,11 +265,12 @@
                                   ShadowFrame* shadow_frame,
                                   Thread* self)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(index),
-                                                   shadow_frame->GetMethod(),
-                                                   self,
-                                                   /* can_run_clinit= */ false,
-                                                   /* verify_access= */ false);
+  ObjPtr<mirror::Class> c =
+      ResolveVerifyAndClinit(dex::TypeIndex(index),
+                             shadow_frame->GetMethod(),
+                             self,
+                             /* can_run_clinit= */ false,
+                             !shadow_frame->GetMethod()->SkipAccessChecks());
   if (UNLIKELY(c == nullptr)) {
     return 1u;
   }
@@ -403,11 +310,12 @@
                                  art::ArtMethod* method,
                                  Thread* self)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(index),
-                                                   method,
-                                                   self,
-                                                   false,
-                                                   false);
+  ObjPtr<mirror::Class> c =
+      ResolveVerifyAndClinit(dex::TypeIndex(index),
+                             method,
+                             self,
+                             /* can_run_clinit= */ false,
+                             !method->SkipAccessChecks());
   if (UNLIKELY(c == nullptr)) {
     return 1u;
   }
@@ -428,8 +336,8 @@
   ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(index),
                                                    method,
                                                    self,
-                                                   false,
-                                                   false);
+                                                   /* can_run_clinit= */ false,
+                                                   !method->SkipAccessChecks());
   if (UNLIKELY(c == nullptr)) {
     return 0u;  // Caller will check for pending exception.  Return value unimportant.
   }
@@ -448,11 +356,12 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
   ObjPtr<mirror::Object> obj = nullptr;
-  ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
-                                                   shadow_frame->GetMethod(),
-                                                   self,
-                                                   /* can_run_clinit= */ false,
-                                                   /* verify_access= */ false);
+  ObjPtr<mirror::Class> c =
+      ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
+                             shadow_frame->GetMethod(),
+                             self,
+                             /* can_run_clinit= */ false,
+                             !shadow_frame->GetMethod()->SkipAccessChecks());
   if (LIKELY(c != nullptr)) {
     if (UNLIKELY(c->IsStringClass())) {
       gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
@@ -469,14 +378,6 @@
   return 1u;
 }
 
-extern "C" size_t MterpIputObjectQuick(ShadowFrame* shadow_frame,
-                                       uint16_t* dex_pc_ptr,
-                                       uint32_t inst_data)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoIPutQuick<Primitive::kPrimNot, false>(*shadow_frame, inst, inst_data) ? 1u : 0u;
-}
-
 extern "C" size_t MterpAputObject(ShadowFrame* shadow_frame,
                                   uint16_t* dex_pc_ptr,
                                   uint32_t inst_data)
@@ -501,8 +402,24 @@
                                       Thread* self)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoFilledNewArray<false, false, false>(inst, *shadow_frame, self,
-                                               shadow_frame->GetResultRegister()) ? 1u : 0u;
+  JValue* result_register = shadow_frame->GetResultRegister();
+  bool res = false;
+  if (shadow_frame->GetMethod()->SkipAccessChecks()) {
+    res = DoFilledNewArray</*is_range=*/false,
+                           /*do_access_check=*/false,
+                           /*transaction_active=*/false>(inst,
+                                                         *shadow_frame,
+                                                         self,
+                                                         result_register);
+  } else {
+    res = DoFilledNewArray</*is_range=*/false,
+                           /*do_access_check=*/true,
+                           /*transaction_active=*/false>(inst,
+                                                         *shadow_frame,
+                                                         self,
+                                                         result_register);
+  }
+  return res ? 1u : 0u;
 }
 
 extern "C" size_t MterpFilledNewArrayRange(ShadowFrame* shadow_frame,
@@ -510,8 +427,24 @@
                                            Thread* self)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   const Instruction* inst = Instruction::At(dex_pc_ptr);
-  return DoFilledNewArray<true, false, false>(inst, *shadow_frame, self,
-                                              shadow_frame->GetResultRegister()) ? 1u : 0u;
+  JValue* result_register = shadow_frame->GetResultRegister();
+  bool res = false;
+  if (shadow_frame->GetMethod()->SkipAccessChecks()) {
+    res = DoFilledNewArray</*is_range=*/true,
+                           /*do_access_check=*/false,
+                           /*transaction_active=*/false>(inst,
+                                                         *shadow_frame,
+                                                         self,
+                                                         result_register);
+  } else {
+    res = DoFilledNewArray</*is_range=*/true,
+                           /*do_access_check=*/true,
+                           /*transaction_active=*/false>(inst,
+                                                         *shadow_frame,
+                                                         self,
+                                                         result_register);
+  }
+  return res ? 1u : 0u;
 }
 
 extern "C" size_t MterpNewArray(ShadowFrame* shadow_frame,
@@ -520,11 +453,23 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   const Instruction* inst = Instruction::At(dex_pc_ptr);
   int32_t length = shadow_frame->GetVReg(inst->VRegB_22c(inst_data));
-  ObjPtr<mirror::Object> obj = AllocArrayFromCode</*kAccessCheck=*/ false>(
-      dex::TypeIndex(inst->VRegC_22c()), length, shadow_frame->GetMethod(), self,
-      Runtime::Current()->GetHeap()->GetCurrentAllocator());
+  gc::AllocatorType allocator = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+  ObjPtr<mirror::Object> obj;
+  if (shadow_frame->GetMethod()->SkipAccessChecks()) {
+    obj = AllocArrayFromCode</*kAccessCheck=*/ false>(dex::TypeIndex(inst->VRegC_22c()),
+                                                      length,
+                                                      shadow_frame->GetMethod(),
+                                                      self,
+                                                      allocator);
+  } else {
+    obj = AllocArrayFromCode</*kAccessCheck=*/ true>(dex::TypeIndex(inst->VRegC_22c()),
+                                                     length,
+                                                     shadow_frame->GetMethod(),
+                                                     self,
+                                                     allocator);
+  }
   if (UNLIKELY(obj == nullptr)) {
-      return 0u;
+    return 0u;
   }
   shadow_frame->SetVRegReference(inst->VRegA_22c(inst_data), obj);
   return 1u;
@@ -711,7 +656,7 @@
   }
 }
 
-template<typename PrimType, FindFieldType kAccessType>
+template<typename PrimType, FindFieldType kAccessType, bool do_access_checks>
 NO_INLINE bool MterpFieldAccessSlow(Instruction* inst,
                                     uint16_t inst_data,
                                     ShadowFrame* shadow_frame,
@@ -724,12 +669,21 @@
   shadow_frame->SetDexPCPtr(reinterpret_cast<uint16_t*>(inst));
   ArtMethod* referrer = shadow_frame->GetMethod();
   uint32_t field_idx = kIsStatic ? inst->VRegB_21c() : inst->VRegC_22c();
-  ArtField* field = FindFieldFromCode<kAccessType, /* access_checks= */ false>(
+  ArtField* field = FindFieldFromCode<kAccessType, do_access_checks>(
       field_idx, referrer, self, sizeof(PrimType));
   if (UNLIKELY(field == nullptr)) {
     DCHECK(self->IsExceptionPending());
     return false;
   }
+  constexpr bool kIsPrimitive = (kAccessType & FindFieldFlags::PrimitiveBit) != 0;
+  if (!kIsPrimitive && !kIsRead) {
+    uint16_t vRegA = kIsStatic ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
+    ObjPtr<mirror::Object> value = shadow_frame->GetVRegReference(vRegA);
+    if (value != nullptr && field->ResolveType() == nullptr) {
+      DCHECK(self->IsExceptionPending());
+      return false;
+    }
+  }
   ObjPtr<mirror::Object> obj = kIsStatic
       ? field->GetDeclaringClass().Ptr()
       : shadow_frame->GetVRegReference(inst->VRegB_22c(inst_data));
@@ -743,10 +697,7 @@
 }
 
 // This methods is called from assembly to handle field access instructions.
-//
-// This method is fairly hot.  It is long, but it has been carefully optimized.
-// It contains only fully inlined methods -> no spills -> no prologue/epilogue.
-template<typename PrimType, FindFieldType kAccessType>
+template<typename PrimType, FindFieldType kAccessType, bool do_access_checks>
 ALWAYS_INLINE bool MterpFieldAccessFast(Instruction* inst,
                                         uint16_t inst_data,
                                         ShadowFrame* shadow_frame,
@@ -765,7 +716,7 @@
         : tls_value;
     if (kIsDebugBuild) {
       uint32_t field_idx = kIsStatic ? inst->VRegB_21c() : inst->VRegC_22c();
-      ArtField* field = FindFieldFromCode<kAccessType, /* access_checks= */ false>(
+      ArtField* field = FindFieldFromCode<kAccessType, do_access_checks>(
           field_idx, shadow_frame->GetMethod(), self, sizeof(PrimType));
       DCHECK_EQ(offset, field->GetOffset().SizeValue());
     }
@@ -781,7 +732,7 @@
 
   // This effectively inlines the fast path from ArtMethod::GetDexCache.
   ArtMethod* referrer = shadow_frame->GetMethod();
-  if (LIKELY(!referrer->IsObsolete())) {
+  if (LIKELY(!referrer->IsObsolete() && !do_access_checks)) {
     // Avoid read barriers, since we need only the pointer to the native (non-movable)
     // DexCache field array which we can get even through from-space objects.
     ObjPtr<mirror::Class> klass = referrer->GetDeclaringClass<kWithoutReadBarrier>();
@@ -790,16 +741,18 @@
 
     // Try to find the desired field in DexCache.
     uint32_t field_idx = kIsStatic ? inst->VRegB_21c() : inst->VRegC_22c();
-    ArtField* field = dex_cache->GetResolvedField(field_idx, kRuntimePointerSize);
+    ArtField* field = dex_cache->GetResolvedField(field_idx);
     if (LIKELY(field != nullptr)) {
       bool visibly_initialized = !kIsStatic || field->GetDeclaringClass()->IsVisiblyInitialized();
       if (LIKELY(visibly_initialized)) {
-        DCHECK_EQ(field, (FindFieldFromCode<kAccessType, /* access_checks= */ false>(
+        DCHECK_EQ(field, (FindFieldFromCode<kAccessType, do_access_checks>(
             field_idx, referrer, self, sizeof(PrimType))));
         ObjPtr<mirror::Object> obj = kIsStatic
             ? field->GetDeclaringClass().Ptr()
             : shadow_frame->GetVRegReference(inst->VRegB_22c(inst_data));
-        if (LIKELY(kIsStatic || obj != nullptr)) {
+        // We check if nterp is supported as nterp and mterp use the cache in an
+        // incompatible way.
+        if (!IsNterpSupported() && LIKELY(kIsStatic || obj != nullptr)) {
           // Only non-volatile fields are allowed in the thread-local cache.
           if (LIKELY(!field->IsVolatile())) {
             if (kIsStatic) {
@@ -817,13 +770,18 @@
   }
 
   // Slow path. Last and with identical arguments so that it becomes single instruction tail call.
-  return MterpFieldAccessSlow<PrimType, kAccessType>(inst, inst_data, shadow_frame, self);
+  return MterpFieldAccessSlow<PrimType, kAccessType, do_access_checks>(
+      inst, inst_data, shadow_frame, self);
 }
 
 #define MTERP_FIELD_ACCESSOR(Name, PrimType, AccessType)                                          \
 extern "C" bool Name(Instruction* inst, uint16_t inst_data, ShadowFrame* sf, Thread* self)        \
     REQUIRES_SHARED(Locks::mutator_lock_) {                                                       \
-  return MterpFieldAccessFast<PrimType, AccessType>(inst, inst_data, sf, self);                   \
+  if (sf->GetMethod()->SkipAccessChecks()) {                                                      \
+    return MterpFieldAccessFast<PrimType, AccessType, false>(inst, inst_data, sf, self);          \
+  } else {                                                                                        \
+    return MterpFieldAccessFast<PrimType, AccessType, true>(inst, inst_data, sf, self);           \
+  }                                                                                               \
 }
 
 #define MTERP_FIELD_ACCESSORS_FOR_TYPE(Sufix, PrimType, Kind)                                     \
diff --git a/runtime/interpreter/mterp/mterp.h b/runtime/interpreter/mterp/mterp.h
index 7813fca..bc057c2 100644
--- a/runtime/interpreter/mterp/mterp.h
+++ b/runtime/interpreter/mterp/mterp.h
@@ -28,24 +28,15 @@
 extern "C" void* artMterpAsmInstructionStart[];
 extern "C" void* artMterpAsmInstructionEnd[];
 
-extern "C" void* artNterpAsmInstructionStart[];
-extern "C" void* artNterpAsmInstructionEnd[];
-
 namespace art {
 
-class ArtMethod;
 class Thread;
 
 namespace interpreter {
 
 void InitMterpTls(Thread* self);
 void CheckMterpAsmConstants();
-void CheckNterpAsmConstants();
 bool CanUseMterp();
-bool IsNterpSupported();
-bool CanRuntimeUseNterp();
-bool CanMethodUseNterp(ArtMethod* method);
-const void* GetNterpEntryPoint();
 
 // Poison value for TestExportPC.  If we segfault with this value, it means that a mterp
 // handler for a recent opcode failed to export the Dalvik PC prior to a possible exit from
@@ -56,9 +47,6 @@
 
 constexpr size_t kMterpHandlerSize = 128;
 
-// The maximum we will allow an nterp frame to be.
-constexpr size_t kMaxNterpFrame = 3 * KB;
-
 }  // namespace interpreter
 }  // namespace art
 
diff --git a/runtime/interpreter/mterp/mterp_stub.cc b/runtime/interpreter/mterp/mterp_stub.cc
index e515ec4..ec02909 100644
--- a/runtime/interpreter/mterp/mterp_stub.cc
+++ b/runtime/interpreter/mterp/mterp_stub.cc
@@ -26,7 +26,7 @@
  * are still correct.
  */
 void CheckMterpAsmConstants() {
-  // Dummy version when mterp not implemented.
+  // Nothing to check when mterp is not implemented.
 }
 
 void InitMterpTls(Thread* self) {
diff --git a/runtime/interpreter/mterp/nterp.cc b/runtime/interpreter/mterp/nterp.cc
index d51b0ae..f45e45c 100644
--- a/runtime/interpreter/mterp/nterp.cc
+++ b/runtime/interpreter/mterp/nterp.cc
@@ -17,7 +17,7 @@
 /*
  * Mterp entry point and support functions.
  */
-#include "mterp.h"
+#include "nterp.h"
 
 #include "base/quasi_atomic.h"
 #include "dex/dex_instruction_utils.h"
@@ -37,15 +37,13 @@
 }
 
 bool CanRuntimeUseNterp() REQUIRES_SHARED(Locks::mutator_lock_) {
-  // Nterp has the same restrictions as Mterp.
-  return IsNterpSupported() && CanUseMterp();
-}
-
-bool CanMethodUseNterp(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
-  return method->SkipAccessChecks() &&
-      !method->IsNative() &&
-      method->GetDexFile()->IsStandardDexFile() &&
-      NterpGetFrameSize(method) < kMaxNterpFrame;
+  Runtime* runtime = Runtime::Current();
+  instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
+  // Nterp shares the same restrictions as Mterp.
+  // If the runtime is interpreter only, we currently don't use nterp as some
+  // parts of the runtime (like instrumentation) make assumption on an
+  // interpreter-only runtime to always be in a switch-like interpreter.
+  return IsNterpSupported() && CanUseMterp() && !instr->InterpretOnly();
 }
 
 const void* GetNterpEntryPoint() {
@@ -69,6 +67,27 @@
       LOG(FATAL) << "ERROR: unexpected asm interp size " << interp_size
                  << "(did an instruction handler exceed " << width << " bytes?)";
   }
+  static_assert(IsPowerOfTwo(kNterpHotnessMask + 1), "Hotness mask must be a (power of 2) - 1");
+  static_assert(IsPowerOfTwo(kTieredHotnessMask + 1),
+                "Tiered hotness mask must be a (power of 2) - 1");
+}
+
+inline void UpdateHotness(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
+  // The hotness we will add to a method when we perform a
+  // field/method/class/string lookup.
+  constexpr uint16_t kNterpHotnessLookup = 0xf;
+
+  // Convert to uint32_t to handle uint16_t overflow.
+  uint32_t counter = method->GetCounter();
+  uint32_t new_counter = counter + kNterpHotnessLookup;
+  if (new_counter > kNterpHotnessMask) {
+    // Let the nterp code actually call the compilation: we want to make sure
+    // there's at least a second execution of the method or a back-edge to avoid
+    // compiling straightline initialization methods.
+    method->SetCounter(kNterpHotnessMask);
+  } else {
+    method->SetCounter(new_counter);
+  }
 }
 
 template<typename T>
@@ -87,6 +106,111 @@
   UpdateCache(self, dex_pc_ptr, reinterpret_cast<size_t>(value));
 }
 
+#ifdef __arm__
+
+extern "C" void NterpStoreArm32Fprs(const char* shorty,
+                                    uint32_t* registers,
+                                    uint32_t* stack_args,
+                                    const uint32_t* fprs) {
+  // Note `shorty` has already the returned type removed.
+  ScopedAssertNoThreadSuspension sants("In nterp");
+  uint32_t arg_index = 0;
+  uint32_t fpr_double_index = 0;
+  uint32_t fpr_index = 0;
+  for (uint32_t shorty_index = 0; shorty[shorty_index] != '\0'; ++shorty_index) {
+    char arg_type = shorty[shorty_index];
+    switch (arg_type) {
+      case 'D': {
+        // Double should not overlap with float.
+        fpr_double_index = std::max(fpr_double_index, RoundUp(fpr_index, 2));
+        if (fpr_double_index < 16) {
+          registers[arg_index] = fprs[fpr_double_index++];
+          registers[arg_index + 1] = fprs[fpr_double_index++];
+        } else {
+          registers[arg_index] = stack_args[arg_index];
+          registers[arg_index + 1] = stack_args[arg_index + 1];
+        }
+        arg_index += 2;
+        break;
+      }
+      case 'F': {
+        if (fpr_index % 2 == 0) {
+          fpr_index = std::max(fpr_double_index, fpr_index);
+        }
+        if (fpr_index < 16) {
+          registers[arg_index] = fprs[fpr_index++];
+        } else {
+          registers[arg_index] = stack_args[arg_index];
+        }
+        arg_index++;
+        break;
+      }
+      case 'J': {
+        arg_index += 2;
+        break;
+      }
+      default: {
+        arg_index++;
+        break;
+      }
+    }
+  }
+}
+
+extern "C" void NterpSetupArm32Fprs(const char* shorty,
+                                    uint32_t dex_register,
+                                    uint32_t stack_index,
+                                    uint32_t* fprs,
+                                    uint32_t* registers,
+                                    uint32_t* stack_args) {
+  // Note `shorty` has already the returned type removed.
+  ScopedAssertNoThreadSuspension sants("In nterp");
+  uint32_t fpr_double_index = 0;
+  uint32_t fpr_index = 0;
+  for (uint32_t shorty_index = 0; shorty[shorty_index] != '\0'; ++shorty_index) {
+    char arg_type = shorty[shorty_index];
+    switch (arg_type) {
+      case 'D': {
+        // Double should not overlap with float.
+        fpr_double_index = std::max(fpr_double_index, RoundUp(fpr_index, 2));
+        if (fpr_double_index < 16) {
+          fprs[fpr_double_index++] = registers[dex_register++];
+          fprs[fpr_double_index++] = registers[dex_register++];
+          stack_index += 2;
+        } else {
+          stack_args[stack_index++] = registers[dex_register++];
+          stack_args[stack_index++] = registers[dex_register++];
+        }
+        break;
+      }
+      case 'F': {
+        if (fpr_index % 2 == 0) {
+          fpr_index = std::max(fpr_double_index, fpr_index);
+        }
+        if (fpr_index < 16) {
+          fprs[fpr_index++] = registers[dex_register++];
+          stack_index++;
+        } else {
+          stack_args[stack_index++] = registers[dex_register++];
+        }
+        break;
+      }
+      case 'J': {
+        stack_index += 2;
+        dex_register += 2;
+        break;
+      }
+      default: {
+        stack_index++;
+        dex_register++;
+        break;
+      }
+    }
+  }
+}
+
+#endif
+
 extern "C" const dex::CodeItem* NterpGetCodeItem(ArtMethod* method)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   ScopedAssertNoThreadSuspension sants("In nterp");
@@ -129,6 +253,7 @@
 
 extern "C" size_t NterpGetMethod(Thread* self, ArtMethod* caller, uint16_t* dex_pc_ptr)
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  UpdateHotness(caller);
   const Instruction* inst = Instruction::At(dex_pc_ptr);
   InvokeType invoke_type = kStatic;
   uint16_t method_index = 0;
@@ -247,19 +372,28 @@
   }
 
   if (invoke_type == kInterface) {
+    size_t result = 0u;
     if (resolved_method->GetDeclaringClass()->IsObjectClass()) {
-      // Don't update the cache and return a value with high bit set to notify the
-      // interpreter it should do a vtable call instead.
+      // Set the low bit to notify the interpreter it should do a vtable call.
       DCHECK_LT(resolved_method->GetMethodIndex(), 0x10000);
-      return resolved_method->GetMethodIndex() | (1U << 31);
+      result = (resolved_method->GetMethodIndex() << 16) | 1U;
     } else {
       DCHECK(resolved_method->GetDeclaringClass()->IsInterface());
-      UpdateCache(self, dex_pc_ptr, resolved_method->GetImtIndex());
-      return resolved_method->GetImtIndex();
+      DCHECK(!resolved_method->IsCopied());
+      if (!resolved_method->IsAbstract()) {
+        // Set the second bit to notify the interpreter this is a default
+        // method.
+        result = reinterpret_cast<size_t>(resolved_method) | 2U;
+      } else {
+        result = reinterpret_cast<size_t>(resolved_method);
+      }
     }
+    UpdateCache(self, dex_pc_ptr, result);
+    return result;
   } else if (resolved_method->GetDeclaringClass()->IsStringClass()
              && !resolved_method->IsStatic()
              && resolved_method->IsConstructor()) {
+    CHECK_NE(invoke_type, kSuper);
     resolved_method = WellKnownClasses::StringInitToStringFactory(resolved_method);
     // Or the result with 1 to notify to nterp this is a string init method. We
     // also don't cache the result as we don't want nterp to have its fast path always
@@ -280,7 +414,8 @@
                                               uint16_t field_index,
                                               ArtMethod* caller,
                                               bool is_static,
-                                              bool is_put)
+                                              bool is_put,
+                                              size_t resolve_field_type)  // Resolve if not zero
     REQUIRES_SHARED(Locks::mutator_lock_) {
   if (caller->SkipAccessChecks()) {
     return class_linker->ResolveField(field_index, caller, is_static);
@@ -315,11 +450,19 @@
     ThrowIllegalAccessErrorFinalField(caller, resolved_field);
     return nullptr;
   }
+  if (resolve_field_type != 0u && resolved_field->ResolveType() == nullptr) {
+    DCHECK(self->IsExceptionPending());
+    return nullptr;
+  }
   return resolved_field;
 }
 
-extern "C" size_t NterpGetStaticField(Thread* self, ArtMethod* caller, uint16_t* dex_pc_ptr)
+extern "C" size_t NterpGetStaticField(Thread* self,
+                                      ArtMethod* caller,
+                                      uint16_t* dex_pc_ptr,
+                                      size_t resolve_field_type)  // Resolve if not zero
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  UpdateHotness(caller);
   const Instruction* inst = Instruction::At(dex_pc_ptr);
   uint16_t field_index = inst->VRegB_21c();
   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
@@ -329,7 +472,8 @@
       field_index,
       caller,
       /* is_static */ true,
-      /* is_put */ IsInstructionSPut(inst->Opcode()));
+      /* is_put */ IsInstructionSPut(inst->Opcode()),
+      resolve_field_type);
 
   if (resolved_field == nullptr) {
     DCHECK(self->IsExceptionPending());
@@ -358,8 +502,10 @@
 
 extern "C" uint32_t NterpGetInstanceFieldOffset(Thread* self,
                                                 ArtMethod* caller,
-                                                uint16_t* dex_pc_ptr)
+                                                uint16_t* dex_pc_ptr,
+                                                size_t resolve_field_type)  // Resolve if not zero
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  UpdateHotness(caller);
   const Instruction* inst = Instruction::At(dex_pc_ptr);
   uint16_t field_index = inst->VRegC_22c();
   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
@@ -369,7 +515,8 @@
       field_index,
       caller,
       /* is_static */ false,
-      /* is_put */ IsInstructionIPut(inst->Opcode()));
+      /* is_put */ IsInstructionIPut(inst->Opcode()),
+      resolve_field_type);
   if (resolved_field == nullptr) {
     DCHECK(self->IsExceptionPending());
     return 0;
@@ -387,6 +534,7 @@
                                                          ArtMethod* caller,
                                                          uint16_t* dex_pc_ptr)
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  UpdateHotness(caller);
   const Instruction* inst = Instruction::At(dex_pc_ptr);
   dex::TypeIndex index;
   switch (inst->Opcode()) {
@@ -446,6 +594,7 @@
   switch (inst->Opcode()) {
     case Instruction::CONST_STRING:
     case Instruction::CONST_STRING_JUMBO: {
+      UpdateHotness(caller);
       dex::StringIndex string_index(
           (inst->Opcode() == Instruction::CONST_STRING)
               ? inst->VRegB_21c()
@@ -482,7 +631,7 @@
 static mirror::Object* DoFilledNewArray(Thread* self,
                                         ArtMethod* caller,
                                         uint16_t* dex_pc_ptr,
-                                        int32_t* regs,
+                                        uint32_t* regs,
                                         bool is_range)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   const Instruction* inst = Instruction::At(dex_pc_ptr);
@@ -500,11 +649,12 @@
     DCHECK_LE(length, 5);
   }
   uint16_t type_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
-  ObjPtr<mirror::Class> array_class = ResolveVerifyAndClinit(dex::TypeIndex(type_idx),
-                                                             caller,
-                                                             self,
-                                                             /* can_run_clinit= */ true,
-                                                             /* verify_access= */ false);
+  ObjPtr<mirror::Class> array_class =
+      ResolveVerifyAndClinit(dex::TypeIndex(type_idx),
+                             caller,
+                             self,
+                             /* can_run_clinit= */ true,
+                             /* verify_access= */ !caller->SkipAccessChecks());
   if (UNLIKELY(array_class == nullptr)) {
     DCHECK(self->IsExceptionPending());
     return nullptr;
@@ -555,7 +705,7 @@
 
 extern "C" mirror::Object* NterpFilledNewArray(Thread* self,
                                                ArtMethod* caller,
-                                               int32_t* registers,
+                                               uint32_t* registers,
                                                uint16_t* dex_pc_ptr)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   return DoFilledNewArray(self, caller, dex_pc_ptr, registers, /* is_range= */ false);
@@ -563,7 +713,7 @@
 
 extern "C" mirror::Object* NterpFilledNewArrayRange(Thread* self,
                                                     ArtMethod* caller,
-                                                    int32_t* registers,
+                                                    uint32_t* registers,
                                                     uint16_t* dex_pc_ptr)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   return DoFilledNewArray(self, caller, dex_pc_ptr, registers, /* is_range= */ true);
@@ -573,7 +723,7 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   ScopedAssertNoThreadSuspension sants("In nterp");
   jit::Jit* jit = Runtime::Current()->GetJit();
-  if (jit != nullptr) {
+  if (jit != nullptr && jit->UseJitCompilation()) {
     // Nterp passes null on entry where we don't want to OSR.
     if (dex_pc_ptr != nullptr) {
       // This could be a loop back edge, check if we can OSR.
@@ -593,12 +743,14 @@
 extern "C" ssize_t MterpDoPackedSwitch(const uint16_t* switchData, int32_t testVal);
 extern "C" ssize_t NterpDoPackedSwitch(const uint16_t* switchData, int32_t testVal)
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  ScopedAssertNoThreadSuspension sants("In nterp");
   return MterpDoPackedSwitch(switchData, testVal);
 }
 
 extern "C" ssize_t MterpDoSparseSwitch(const uint16_t* switchData, int32_t testVal);
 extern "C" ssize_t NterpDoSparseSwitch(const uint16_t* switchData, int32_t testVal)
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  ScopedAssertNoThreadSuspension sants("In nterp");
   return MterpDoSparseSwitch(switchData, testVal);
 }
 
diff --git a/runtime/interpreter/mterp/nterp.h b/runtime/interpreter/mterp/nterp.h
new file mode 100644
index 0000000..97dee8c
--- /dev/null
+++ b/runtime/interpreter/mterp/nterp.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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_INTERPRETER_MTERP_NTERP_H_
+#define ART_RUNTIME_INTERPRETER_MTERP_NTERP_H_
+
+#include "base/globals.h"
+
+extern "C" void* artNterpAsmInstructionStart[];
+extern "C" void* artNterpAsmInstructionEnd[];
+
+namespace art {
+
+class ArtMethod;
+
+namespace interpreter {
+
+void CheckNterpAsmConstants();
+bool IsNterpSupported();
+bool CanRuntimeUseNterp();
+const void* GetNterpEntryPoint();
+
+// The hotness threshold where we trigger JIT compilation or OSR.
+constexpr uint16_t kNterpHotnessMask = 0xffff;
+
+// The hotness threshold for the baseline compiler to trigger optimized
+// compilation.
+constexpr uint16_t kTieredHotnessMask = 0xffff;
+
+// The maximum we allow an nterp frame to be.
+constexpr size_t kNterpMaxFrame = 3 * KB;
+
+// The maximum size for each nterp opcode handler.
+constexpr size_t kNterpHandlerSize = 128;
+
+}  // namespace interpreter
+}  // namespace art
+
+#endif  // ART_RUNTIME_INTERPRETER_MTERP_NTERP_H_
diff --git a/runtime/interpreter/mterp/nterp_stub.cc b/runtime/interpreter/mterp/nterp_stub.cc
index c1b1ec3..95d11c2 100644
--- a/runtime/interpreter/mterp/nterp_stub.cc
+++ b/runtime/interpreter/mterp/nterp_stub.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "base/enums.h"
 #include "base/locks.h"
 
 /*
@@ -34,10 +35,6 @@
   return false;
 }
 
-bool CanMethodUseNterp(ArtMethod* method ATTRIBUTE_UNUSED) {
-  return false;
-}
-
 const void* GetNterpEntryPoint() {
   return nullptr;
 }
diff --git a/runtime/interpreter/mterp/x86/control_flow.S b/runtime/interpreter/mterp/x86/control_flow.S
index 74b4fad..08dc866 100644
--- a/runtime/interpreter/mterp/x86/control_flow.S
+++ b/runtime/interpreter/mterp/x86/control_flow.S
@@ -174,17 +174,6 @@
     xorl    %ecx, %ecx
     jmp     MterpReturn
 
-%def op_return_void_no_barrier():
-    movl    rSELF, %eax
-    testl   $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
-    jz      1f
-    movl    %eax, OUT_ARG0(%esp)
-    call    SYMBOL(MterpSuspendCheck)
-1:
-    xorl    %eax, %eax
-    xorl    %ecx, %ecx
-    jmp     MterpReturn
-
 %def op_return_wide():
 /*
  * Return a 64-bit value.
diff --git a/runtime/interpreter/mterp/x86/invoke.S b/runtime/interpreter/mterp/x86/invoke.S
index 06cd904..7f51880 100644
--- a/runtime/interpreter/mterp/x86/invoke.S
+++ b/runtime/interpreter/mterp/x86/invoke.S
@@ -111,11 +111,5 @@
     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
 
-%def op_invoke_virtual_quick():
-%  invoke(helper="MterpInvokeVirtualQuick")
-
 %def op_invoke_virtual_range():
 %  invoke(helper="MterpInvokeVirtualRange")
-
-%def op_invoke_virtual_range_quick():
-%  invoke(helper="MterpInvokeVirtualQuickRange")
diff --git a/runtime/interpreter/mterp/x86/main.S b/runtime/interpreter/mterp/x86/main.S
index 8df75d2..2afef52 100644
--- a/runtime/interpreter/mterp/x86/main.S
+++ b/runtime/interpreter/mterp/x86/main.S
@@ -448,7 +448,6 @@
 /* Transfer stub to alternate interpreter */
     jmp     MterpFallback
 
-
 %def helpers():
     ENTRY MterpHelpers
 
@@ -794,6 +793,9 @@
 SYMBOL(artMterpAsmInstructionStart) = .L_op_nop
     .text
 
+%def default_helper_prefix():
+%  return "mterp_"
+
 %def opcode_start():
     ENTRY mterp_${opcode}
 %def opcode_end():
diff --git a/runtime/interpreter/mterp/x86/object.S b/runtime/interpreter/mterp/x86/object.S
index a47fa3a..6ab1931 100644
--- a/runtime/interpreter/mterp/x86/object.S
+++ b/runtime/interpreter/mterp/x86/object.S
@@ -42,79 +42,21 @@
 %def op_iget_boolean():
 %  op_iget(helper="MterpIGetU8")
 
-%def op_iget_boolean_quick():
-%  op_iget_quick(load="movsbl")
-
 %def op_iget_byte():
 %  op_iget(helper="MterpIGetI8")
 
-%def op_iget_byte_quick():
-%  op_iget_quick(load="movsbl")
-
 %def op_iget_char():
 %  op_iget(helper="MterpIGetU16")
 
-%def op_iget_char_quick():
-%  op_iget_quick(load="movzwl")
-
 %def op_iget_object():
 %  op_iget(is_object="1", helper="MterpIGetObj")
 
-%def op_iget_object_quick():
-    /* For: iget-object-quick */
-    /* op vA, vB, offset@CCCC */
-    movzbl  rINSTbl, %ecx                   # ecx <- BA
-    sarl    $$4, %ecx                       # ecx <- B
-    GET_VREG %ecx, %ecx                     # vB (object we're operating on)
-    movzwl  2(rPC), %eax                    # eax <- field byte offset
-    movl    %ecx, OUT_ARG0(%esp)
-    movl    %eax, OUT_ARG1(%esp)
-    EXPORT_PC
-    call    SYMBOL(artIGetObjectFromMterp)  # (obj, offset)
-    movl    rSELF, %ecx
-    RESTORE_IBASE_FROM_SELF %ecx
-    cmpl    $$0, THREAD_EXCEPTION_OFFSET(%ecx)
-    jnz     MterpException                  # bail out
-    andb    $$0xf,rINSTbl                   # rINST <- A
-    SET_VREG_OBJECT %eax, rINST             # fp[A] <- value
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
-%def op_iget_quick(load="movl"):
-    /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
-    /* op vA, vB, offset@CCCC */
-    movzbl  rINSTbl, %ecx                   # ecx <- BA
-    sarl    $$4, %ecx                       # ecx <- B
-    GET_VREG %ecx, %ecx                     # vB (object we're operating on)
-    movzwl  2(rPC), %eax                    # eax <- field byte offset
-    testl   %ecx, %ecx                      # is object null?
-    je      common_errNullObject
-    ${load} (%ecx,%eax,1), %eax
-    andb    $$0xf,rINSTbl                   # rINST <- A
-    SET_VREG %eax, rINST                    # fp[A] <- value
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
 %def op_iget_short():
 %  op_iget(helper="MterpIGetI16")
 
-%def op_iget_short_quick():
-%  op_iget_quick(load="movswl")
-
 %def op_iget_wide():
 %  op_iget(helper="MterpIGetU64")
 
-%def op_iget_wide_quick():
-    /* iget-wide-quick vA, vB, offset@CCCC */
-    movzbl  rINSTbl, %ecx                   # ecx <- BA
-    sarl    $$4, %ecx                       # ecx <- B
-    GET_VREG %ecx, %ecx                     # vB (object we're operating on)
-    movzwl  2(rPC), %eax                    # eax <- field byte offset
-    testl   %ecx, %ecx                      # is object null?
-    je      common_errNullObject
-    movq    (%ecx,%eax,1), %xmm0
-    andb    $$0xf, rINSTbl                  # rINST <- A
-    SET_WIDE_FP_VREG %xmm0, rINST
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
 %def op_instance_of():
 /*
  * Check to see if an object reference is an instance of a class.
@@ -149,74 +91,21 @@
 %def op_iput_boolean():
 %  op_iput(helper="MterpIPutU8")
 
-%def op_iput_boolean_quick():
-%  op_iput_quick(reg="rINSTbl", store="movb")
-
 %def op_iput_byte():
 %  op_iput(helper="MterpIPutI8")
 
-%def op_iput_byte_quick():
-%  op_iput_quick(reg="rINSTbl", store="movb")
-
 %def op_iput_char():
 %  op_iput(helper="MterpIPutU16")
 
-%def op_iput_char_quick():
-%  op_iput_quick(reg="rINSTw", store="movw")
-
 %def op_iput_object():
 %  op_iput(is_object="1", helper="MterpIPutObj")
 
-%def op_iput_object_quick():
-    EXPORT_PC
-    leal    OFF_FP_SHADOWFRAME(rFP), %eax
-    movl    %eax, OUT_ARG0(%esp)
-    movl    rPC, OUT_ARG1(%esp)
-    REFRESH_INST ${opnum}
-    movl    rINST, OUT_ARG2(%esp)
-    call    SYMBOL(MterpIputObjectQuick)
-    testb   %al, %al
-    jz      MterpException
-    RESTORE_IBASE
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
-%def op_iput_quick(reg="rINST", store="movl"):
-    /* For: iput-quick, iput-object-quick */
-    /* op vA, vB, offset@CCCC */
-    movzbl  rINSTbl, %ecx                   # ecx <- BA
-    sarl    $$4, %ecx                       # ecx <- B
-    GET_VREG %ecx, %ecx                     # vB (object we're operating on)
-    testl   %ecx, %ecx                      # is object null?
-    je      common_errNullObject
-    andb    $$0xf, rINSTbl                  # rINST <- A
-    GET_VREG rINST, rINST                   # rINST <- v[A]
-    movzwl  2(rPC), %eax                    # eax <- field byte offset
-    ${store}    ${reg}, (%ecx,%eax,1)
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
 %def op_iput_short():
 %  op_iput(helper="MterpIPutI16")
 
-%def op_iput_short_quick():
-%  op_iput_quick(reg="rINSTw", store="movw")
-
 %def op_iput_wide():
 %  op_iput(helper="MterpIPutU64")
 
-%def op_iput_wide_quick():
-    /* iput-wide-quick vA, vB, offset@CCCC */
-    movzbl    rINSTbl, %ecx                 # ecx<- BA
-    sarl      $$4, %ecx                     # ecx<- B
-    GET_VREG  %ecx, %ecx                    # vB (object we're operating on)
-    testl     %ecx, %ecx                    # is object null?
-    je        common_errNullObject
-    movzwl    2(rPC), %eax                  # eax<- field byte offset
-    leal      (%ecx,%eax,1), %ecx           # ecx<- Address of 64-bit target
-    andb      $$0xf, rINSTbl                # rINST<- A
-    GET_WIDE_FP_VREG %xmm0, rINST           # xmm0<- fp[A]/fp[A+1]
-    movq      %xmm0, (%ecx)                 # obj.field<- r0/r1
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
 %def op_new_instance():
 /*
  * Create a new instance of a class.
diff --git a/runtime/interpreter/mterp/x86/other.S b/runtime/interpreter/mterp/x86/other.S
index 270ccb6..b0fd1ec 100644
--- a/runtime/interpreter/mterp/x86/other.S
+++ b/runtime/interpreter/mterp/x86/other.S
@@ -294,12 +294,63 @@
 %def op_unused_43():
 %  unused()
 
+%def op_unused_73():
+%  unused()
+
 %def op_unused_79():
 %  unused()
 
 %def op_unused_7a():
 %  unused()
 
+%def op_unused_e3():
+%  unused()
+
+%def op_unused_e4():
+%  unused()
+
+%def op_unused_e5():
+%  unused()
+
+%def op_unused_e6():
+%  unused()
+
+%def op_unused_e7():
+%  unused()
+
+%def op_unused_e8():
+%  unused()
+
+%def op_unused_e9():
+%  unused()
+
+%def op_unused_ea():
+%  unused()
+
+%def op_unused_eb():
+%  unused()
+
+%def op_unused_ec():
+%  unused()
+
+%def op_unused_ed():
+%  unused()
+
+%def op_unused_ee():
+%  unused()
+
+%def op_unused_ef():
+%  unused()
+
+%def op_unused_f0():
+%  unused()
+
+%def op_unused_f1():
+%  unused()
+
+%def op_unused_f2():
+%  unused()
+
 %def op_unused_f3():
 %  unused()
 
diff --git a/runtime/interpreter/mterp/x86_64/control_flow.S b/runtime/interpreter/mterp/x86_64/control_flow.S
index 2f3b5e5..3b52c62 100644
--- a/runtime/interpreter/mterp/x86_64/control_flow.S
+++ b/runtime/interpreter/mterp/x86_64/control_flow.S
@@ -165,15 +165,6 @@
     xorq    %rax, %rax
     jmp     MterpReturn
 
-%def op_return_void_no_barrier():
-    movq    rSELF, OUT_ARG0
-    testl   $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(OUT_ARG0)
-    jz      1f
-    call    SYMBOL(MterpSuspendCheck)
-1:
-    xorq    %rax, %rax
-    jmp     MterpReturn
-
 %def op_return_wide():
 /*
  * Return a 64-bit value.
diff --git a/runtime/interpreter/mterp/x86_64/invoke.S b/runtime/interpreter/mterp/x86_64/invoke.S
index 15b48c9..a723096 100644
--- a/runtime/interpreter/mterp/x86_64/invoke.S
+++ b/runtime/interpreter/mterp/x86_64/invoke.S
@@ -105,11 +105,5 @@
     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
 
-%def op_invoke_virtual_quick():
-%  invoke(helper="MterpInvokeVirtualQuick")
-
 %def op_invoke_virtual_range():
 %  invoke(helper="MterpInvokeVirtualRange")
-
-%def op_invoke_virtual_range_quick():
-%  invoke(helper="MterpInvokeVirtualQuickRange")
diff --git a/runtime/interpreter/mterp/x86_64/main.S b/runtime/interpreter/mterp/x86_64/main.S
index 5f1fd2d..4aeebad 100644
--- a/runtime/interpreter/mterp/x86_64/main.S
+++ b/runtime/interpreter/mterp/x86_64/main.S
@@ -431,7 +431,6 @@
 /* Transfer stub to alternate interpreter */
     jmp     MterpFallback
 
-
 %def helpers():
     ENTRY MterpHelpers
 
@@ -749,6 +748,9 @@
 SYMBOL(artMterpAsmInstructionStart) = .L_op_nop
     .text
 
+%def default_helper_prefix():
+%  return "mterp_"
+
 %def opcode_start():
     ENTRY mterp_${opcode}
 %def opcode_end():
diff --git a/runtime/interpreter/mterp/x86_64/object.S b/runtime/interpreter/mterp/x86_64/object.S
index fa85f69..643c6da 100644
--- a/runtime/interpreter/mterp/x86_64/object.S
+++ b/runtime/interpreter/mterp/x86_64/object.S
@@ -34,72 +34,21 @@
 %def op_iget_boolean():
 %  op_iget(helper="MterpIGetU8")
 
-%def op_iget_boolean_quick():
-%  op_iget_quick(load="movsbl")
-
 %def op_iget_byte():
 %  op_iget(helper="MterpIGetI8")
 
-%def op_iget_byte_quick():
-%  op_iget_quick(load="movsbl")
-
 %def op_iget_char():
 %  op_iget(helper="MterpIGetU16")
 
-%def op_iget_char_quick():
-%  op_iget_quick(load="movzwl")
-
 %def op_iget_object():
 %  op_iget(is_object="1", helper="MterpIGetObj")
 
-%def op_iget_object_quick():
-    /* For: iget-object-quick */
-    /* op vA, vB, offset@CCCC */
-    .extern artIGetObjectFromMterp
-    movzbq  rINSTbl, %rcx                   # rcx <- BA
-    sarl    $$4, %ecx                       # ecx <- B
-    GET_VREG OUT_32_ARG0, %rcx              # vB (object we're operating on)
-    movzwl  2(rPC), OUT_32_ARG1             # eax <- field byte offset
-    EXPORT_PC
-    callq   SYMBOL(artIGetObjectFromMterp)  # (obj, offset)
-    movq    rSELF, %rcx
-    cmpq    $$0, THREAD_EXCEPTION_OFFSET(%rcx)
-    jnz     MterpException                  # bail out
-    andb    $$0xf, rINSTbl                  # rINST <- A
-    SET_VREG_OBJECT %eax, rINSTq            # fp[A] <- value
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
-%def op_iget_quick(load="movl", wide="0"):
-    /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick, iget-wide-quick */
-    /* op vA, vB, offset@CCCC */
-    movl    rINST, %ecx                     # rcx <- BA
-    sarl    $$4, %ecx                       # ecx <- B
-    GET_VREG %ecx, %rcx                     # vB (object we're operating on)
-    movzwq  2(rPC), %rax                    # eax <- field byte offset
-    testl   %ecx, %ecx                      # is object null?
-    je      common_errNullObject
-    andb    $$0xf,rINSTbl                   # rINST <- A
-    .if $wide
-    movq (%rcx,%rax,1), %rax
-    SET_WIDE_VREG %rax, rINSTq              # fp[A] <- value
-    .else
-    ${load} (%rcx,%rax,1), %eax
-    SET_VREG %eax, rINSTq                   # fp[A] <- value
-    .endif
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
 %def op_iget_short():
 %  op_iget(helper="MterpIGetI16")
 
-%def op_iget_short_quick():
-%  op_iget_quick(load="movswl")
-
 %def op_iget_wide():
 %  op_iget(helper="MterpIGetU64")
 
-%def op_iget_wide_quick():
-%  op_iget_quick(load="movswl", wide="1")
-
 %def op_instance_of():
 /*
  * Check to see if an object reference is an instance of a class.
@@ -130,72 +79,21 @@
 %def op_iput_boolean():
 %  op_iput(helper="MterpIPutU8")
 
-%def op_iput_boolean_quick():
-%  op_iput_quick(reg="rINSTbl", store="movb")
-
 %def op_iput_byte():
 %  op_iput(helper="MterpIPutI8")
 
-%def op_iput_byte_quick():
-%  op_iput_quick(reg="rINSTbl", store="movb")
-
 %def op_iput_char():
 %  op_iput(helper="MterpIPutU16")
 
-%def op_iput_char_quick():
-%  op_iput_quick(reg="rINSTw", store="movw")
-
 %def op_iput_object():
 %  op_iput(is_object="1", helper="MterpIPutObj")
 
-%def op_iput_object_quick():
-    EXPORT_PC
-    leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
-    movq    rPC, OUT_ARG1
-    REFRESH_INST ${opnum}
-    movl    rINST, OUT_32_ARG2
-    call    SYMBOL(MterpIputObjectQuick)
-    testb   %al, %al
-    jz      MterpException
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
-%def op_iput_quick(reg="rINST", store="movl"):
-    /* For: iput-quick, iput-object-quick */
-    /* op vA, vB, offset@CCCC */
-    movzbq  rINSTbl, %rcx                   # rcx <- BA
-    sarl    $$4, %ecx                       # ecx <- B
-    GET_VREG %ecx, %rcx                     # vB (object we're operating on)
-    testl   %ecx, %ecx                      # is object null?
-    je      common_errNullObject
-    andb    $$0xf, rINSTbl                  # rINST <- A
-    GET_VREG rINST, rINSTq                  # rINST <- v[A]
-    movzwq  2(rPC), %rax                    # rax <- field byte offset
-    ${store}    ${reg}, (%rcx,%rax,1)
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
 %def op_iput_short():
 %  op_iput(helper="MterpIPutI16")
 
-%def op_iput_short_quick():
-%  op_iput_quick(reg="rINSTw", store="movw")
-
 %def op_iput_wide():
 %  op_iput(helper="MterpIPutU64")
 
-%def op_iput_wide_quick():
-    /* iput-wide-quick vA, vB, offset@CCCC */
-    movzbq    rINSTbl, %rcx                 # rcx<- BA
-    sarl      $$4, %ecx                     # ecx<- B
-    GET_VREG  %ecx, %rcx                    # vB (object we're operating on)
-    testl     %ecx, %ecx                    # is object null?
-    je        common_errNullObject
-    movzwq    2(rPC), %rax                  # rax<- field byte offset
-    leaq      (%rcx,%rax,1), %rcx           # ecx<- Address of 64-bit target
-    andb      $$0xf, rINSTbl                # rINST<- A
-    GET_WIDE_VREG %rax, rINSTq              # rax<- fp[A]/fp[A+1]
-    movq      %rax, (%rcx)                  # obj.field<- r0/r1
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
 %def op_new_instance():
 /*
  * Create a new instance of a class.
diff --git a/runtime/interpreter/mterp/x86_64/other.S b/runtime/interpreter/mterp/x86_64/other.S
index 412389f..83e14f0 100644
--- a/runtime/interpreter/mterp/x86_64/other.S
+++ b/runtime/interpreter/mterp/x86_64/other.S
@@ -263,12 +263,63 @@
 %def op_unused_43():
 %  unused()
 
+%def op_unused_73():
+%  unused()
+
 %def op_unused_79():
 %  unused()
 
 %def op_unused_7a():
 %  unused()
 
+%def op_unused_e3():
+%  unused()
+
+%def op_unused_e4():
+%  unused()
+
+%def op_unused_e5():
+%  unused()
+
+%def op_unused_e6():
+%  unused()
+
+%def op_unused_e7():
+%  unused()
+
+%def op_unused_e8():
+%  unused()
+
+%def op_unused_e9():
+%  unused()
+
+%def op_unused_ea():
+%  unused()
+
+%def op_unused_eb():
+%  unused()
+
+%def op_unused_ec():
+%  unused()
+
+%def op_unused_ed():
+%  unused()
+
+%def op_unused_ee():
+%  unused()
+
+%def op_unused_ef():
+%  unused()
+
+%def op_unused_f0():
+%  unused()
+
+%def op_unused_f1():
+%  unused()
+
+%def op_unused_f2():
+%  unused()
+
 %def op_unused_f3():
 %  unused()
 
diff --git a/runtime/interpreter/mterp/x86_64ng/array.S b/runtime/interpreter/mterp/x86_64ng/array.S
index baf5f30..c8dd8b0 100644
--- a/runtime/interpreter/mterp/x86_64ng/array.S
+++ b/runtime/interpreter/mterp/x86_64ng/array.S
@@ -93,6 +93,7 @@
 %  op_aput(rINST_reg="rINSTq", store="movq", shift="8", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1")
 
 %def op_aput_object():
+    EXPORT_PC                               # for the art_quick_aput_obj call
     movzbq  2(rPC), %rax                    # rax <- BB
     movzbq  3(rPC), %rcx                    # rcx <- CC
     GET_VREG %edi, %rax                     # edi <- vBB (array object)
diff --git a/runtime/interpreter/mterp/x86_64ng/control_flow.S b/runtime/interpreter/mterp/x86_64ng/control_flow.S
index 35276d4..e6116dd 100644
--- a/runtime/interpreter/mterp/x86_64ng/control_flow.S
+++ b/runtime/interpreter/mterp/x86_64ng/control_flow.S
@@ -153,9 +153,6 @@
     ret
     CFI_RESTORE_STATE
 
-%def op_return_void_no_barrier():
-%  op_return_void()
-
 %def op_return_wide():
     GET_WIDE_VREG %rax, rINSTq   # eax <- vAA
     // In case we're going back to compiled code, put the
diff --git a/runtime/interpreter/mterp/x86_64ng/invoke.S b/runtime/interpreter/mterp/x86_64ng/invoke.S
index dba1caa..2e3d297 100644
--- a/runtime/interpreter/mterp/x86_64ng/invoke.S
+++ b/runtime/interpreter/mterp/x86_64ng/invoke.S
@@ -11,7 +11,7 @@
    movzwl 2(rPC), %edi // call_site index, first argument of runtime call.
    jmp NterpCommonInvokeCustomRange
 
-%def invoke_direct_or_super(helper="", range=""):
+%def invoke_direct_or_super(helper="", range="", is_super=""):
    EXPORT_PC
    // Fast-path which gets the method from thread-local cache.
    FETCH_FROM_THREAD_CACHE %rdi, 2f
@@ -31,6 +31,9 @@
    movq rPC, %rdx
    call nterp_get_method
    movq %rax, %rdi
+   .if $is_super
+   jmp 1b
+   .else
    testl MACRO_LITERAL(1), %eax
    je 1b
    andq $$-2, %rdi  // Remove the extra bit that marks it's a String.<init> method.
@@ -39,12 +42,13 @@
    .else
    jmp NterpHandleStringInit
    .endif
+   .endif
 
 %def op_invoke_direct():
-%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0")
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="0")
 
 %def op_invoke_direct_range():
-%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1")
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="0")
 
 %def op_invoke_polymorphic():
    EXPORT_PC
@@ -68,10 +72,11 @@
    jmp NterpCommonInvokePolymorphicRange
 
 %def invoke_interface(helper="", range=""):
+%  slow_path = add_helper(lambda: op_invoke_interface_slow_path())
    EXPORT_PC
-   // Fast-path which gets the method from thread-local cache.
-   FETCH_FROM_THREAD_CACHE %rax, 2f
-1:
+   // Fast-path which gets the interface method from thread-local cache.
+   FETCH_FROM_THREAD_CACHE %rax, ${slow_path}
+.L${opcode}_resume:
    // First argument is the 'this' pointer.
    movzwl 4(rPC), %r11d // arguments
    .if !$range
@@ -79,23 +84,35 @@
    .endif
    movl (rFP, %r11, 4), %esi
    movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
+   // Test the first two bits of the fetched ArtMethod:
+   // - If the first bit is set, this is a method on j.l.Object
+   // - If the second bit is set, this is a default method.
+   testl $$3, %eax
+   jne 2f
+   movzw ART_METHOD_IMT_INDEX_OFFSET(%rax), %ecx
+1:
    movq MIRROR_CLASS_IMT_PTR_OFFSET_64(%edx), %rdx
-   movq (%rdx, %rax, 8), %rdi
+   movq (%rdx, %rcx, 8), %rdi
    jmp $helper
 2:
+   testl $$1, %eax
+   .if $range
+   jne NterpHandleInvokeInterfaceOnObjectMethodRange
+   .else
+   jne NterpHandleInvokeInterfaceOnObjectMethod
+   .endif
+   // Default method
+   andq $$-4, %rax
+   movzw ART_METHOD_METHOD_INDEX_OFFSET(%rax), %ecx
+   andl $$ART_METHOD_IMT_MASK, %ecx
+   jmp 1b
+
+%def op_invoke_interface_slow_path():
    movq rSELF:THREAD_SELF_OFFSET, %rdi
    movq 0(%rsp), %rsi
    movq rPC, %rdx
    call nterp_get_method
-   testl %eax, %eax
-   jns 1b
-   // For j.l.Object interface calls, the high bit is set. Also the method index is 16bits.
-   andl LITERAL(0xffff), %eax
-   .if $range
-   jmp NterpHandleInvokeInterfaceOnObjectMethodRange
-   .else
-   jmp NterpHandleInvokeInterfaceOnObjectMethod
-   .endif
+   jmp .L${opcode}_resume
 
 %def op_invoke_interface():
 %  invoke_interface(helper="NterpCommonInvokeInterface", range="0")
@@ -123,10 +140,10 @@
 %  invoke_static(helper="NterpCommonInvokeStaticRange")
 
 %def op_invoke_super():
-%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0")
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1")
 
 %def op_invoke_super_range():
-%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1")
+%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1")
 
 %def invoke_virtual(helper="", range=""):
    EXPORT_PC
@@ -154,28 +171,5 @@
 %def op_invoke_virtual():
 %  invoke_virtual(helper="NterpCommonInvokeInstance", range="0")
 
-%def op_invoke_virtual_quick():
-   EXPORT_PC
-   movzwl 2(rPC), %eax // offset
-   // First argument is the 'this' pointer.
-   movzwl 4(rPC), %r11d // arguments
-   andq $$0xf, %r11
-   movl (rFP, %r11, 4), %esi
-   // Note: if esi is null, this will be handled by our SIGSEGV handler.
-   movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
-   movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %eax, 8), %rdi
-   jmp NterpCommonInvokeInstance
-
 %def op_invoke_virtual_range():
 %  invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1")
-
-%def op_invoke_virtual_range_quick():
-   EXPORT_PC
-   movzwl 2(rPC), %eax // offset
-   // First argument is the 'this' pointer.
-   movzwl 4(rPC), %r11d // arguments
-   movl (rFP, %r11, 4), %esi
-   // Note: if esi is null, this will be handled by our SIGSEGV handler.
-   movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
-   movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %eax, 8), %rdi
-   jmp NterpCommonInvokeInstanceRange
diff --git a/runtime/interpreter/mterp/x86_64ng/main.S b/runtime/interpreter/mterp/x86_64ng/main.S
index 4eaf95e..71df9e1 100644
--- a/runtime/interpreter/mterp/x86_64ng/main.S
+++ b/runtime/interpreter/mterp/x86_64ng/main.S
@@ -21,7 +21,6 @@
  */
 #include "asm_support.h"
 #include "arch/x86_64/asm_support_x86_64.S"
-#include "interpreter/cfi_asm_support.h"
 
 /**
  * x86_64 ABI general notes:
@@ -74,11 +73,13 @@
 #define rINSTbl  %bl
 #define rIBASE   %r14
 #define rREFS    %r15
+#define rREFS32  %r15d
 #define CFI_REFS 15 // DWARF register number of the reference array (r15).
 
 // Temporary registers while setting up a frame.
 #define rNEW_FP   %r8
 #define rNEW_REFS %r9
+#define rNEW_REFS32 %r9d
 #define CFI_NEW_REFS 9
 
 /*
@@ -207,7 +208,11 @@
     ASM_HIDDEN SYMBOL(\name)
     .global SYMBOL(\name)
     .balign 16
+    // Padding of 3 * 8 bytes to get 16 bytes alignment of code entry.
     .long 0
+    .long 0
+    .long 0
+    // OatQuickMethodHeader. Note that the top two bits must be clear.
     .long (SYMBOL(\end) - SYMBOL(\name))
 SYMBOL(\name):
 .endm
@@ -256,8 +261,9 @@
 3:
     movq (%rsp), %rdi
     addw $$1, ART_METHOD_HOTNESS_COUNT_OFFSET(%rdi)
+    andw $$(NTERP_HOTNESS_MASK), ART_METHOD_HOTNESS_COUNT_OFFSET(%rdi)
     // If the counter overflows, handle this in the runtime.
-    jo NterpHandleHotnessOverflow
+    jz NterpHandleHotnessOverflow
     // Otherwise, do a suspend check.
     testl   $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), rSELF:THREAD_FLAGS_OFFSET
     jz      2b
@@ -266,6 +272,80 @@
     jmp 2b
 .endm
 
+// Expects:
+// - r10, and r11 to be available.
+// Outputs:
+// - \registers contains the dex registers size
+// - \outs contains the outs size
+// - if load_ins is 1, \ins contains the ins
+// - \code_item is replace with a pointer to the instructions
+.macro FETCH_CODE_ITEM_INFO code_item, registers, outs, ins, load_ins
+    testq MACRO_LITERAL(1), \code_item
+    je 5f
+    andq $$-2, \code_item  // Remove the extra bit that marks it's a compact dex file.
+    movzwl COMPACT_CODE_ITEM_FIELDS_OFFSET(\code_item), %r10d
+    movl %r10d, \registers
+    sarl $$COMPACT_CODE_ITEM_REGISTERS_SIZE_SHIFT, \registers
+    andl $$0xf, \registers
+    movl %r10d, \outs
+    sarl $$COMPACT_CODE_ITEM_OUTS_SIZE_SHIFT, \outs
+    andl $$0xf, \outs
+    .if \load_ins
+    movl %r10d, \ins
+    sarl $$COMPACT_CODE_ITEM_INS_SIZE_SHIFT, \ins
+    andl $$0xf, \ins
+    .else
+    movl %r10d, %r11d
+    sarl $$COMPACT_CODE_ITEM_INS_SIZE_SHIFT, %r11d
+    andl $$0xf, %r11d
+    addl %r11d, \registers
+    .endif
+    testw $$COMPACT_CODE_ITEM_REGISTERS_INS_OUTS_FLAGS, COMPACT_CODE_ITEM_FLAGS_OFFSET(\code_item)
+    je 4f
+    movq \code_item, %r11
+    testw $$COMPACT_CODE_ITEM_INSNS_FLAG, COMPACT_CODE_ITEM_FLAGS_OFFSET(\code_item)
+    je 1f
+    subq $$4, %r11
+1:
+    testw $$COMPACT_CODE_ITEM_REGISTERS_FLAG, COMPACT_CODE_ITEM_FLAGS_OFFSET(\code_item)
+    je 2f
+    subq $$2, %r11
+    movzwl (%r11), %r10d
+    addl %r10d, \registers
+2:
+    testw $$COMPACT_CODE_ITEM_INS_FLAG, COMPACT_CODE_ITEM_FLAGS_OFFSET(\code_item)
+    je 3f
+    subq $$2, %r11
+    movzwl (%r11), %r10d
+    .if \load_ins
+    addl %r10d, \ins
+    .else
+    addl %r10d, \registers
+    .endif
+3:
+    testw $$COMPACT_CODE_ITEM_OUTS_FLAG, COMPACT_CODE_ITEM_FLAGS_OFFSET(\code_item)
+    je 4f
+    subq $$2, %r11
+    movzwl (%r11), %r10d
+    addl %r10d, \outs
+4:
+    .if \load_ins
+    addl \ins, \registers
+    .endif
+    addq $$COMPACT_CODE_ITEM_INSNS_OFFSET, \code_item
+    jmp 6f
+5:
+    // Fetch dex register size.
+    movzwl CODE_ITEM_REGISTERS_SIZE_OFFSET(\code_item), \registers
+    // Fetch outs size.
+    movzwl CODE_ITEM_OUTS_SIZE_OFFSET(\code_item), \outs
+    .if \load_ins
+    movzwl CODE_ITEM_INS_SIZE_OFFSET(\code_item), \ins
+    .endif
+    addq $$CODE_ITEM_INSNS_OFFSET, \code_item
+6:
+.endm
+
 // Setup the stack to start executing the method. Expects:
 // - rdi to contain the ArtMethod
 // - rbx, r10, r11 to be available.
@@ -273,11 +353,10 @@
 // Outputs
 // - rbx contains the dex registers size
 // - r11 contains the old stack pointer.
-.macro SETUP_STACK_FRAME code_item, refs, fp, cfi_refs
-    // Fetch dex register size.
-    movzwl CODE_ITEM_REGISTERS_SIZE_OFFSET(\code_item), %ebx
-    // Fetch outs size.
-    movzwq CODE_ITEM_OUTS_SIZE_OFFSET(\code_item), \refs
+// - \code_item is replace with a pointer to the instructions
+// - if load_ins is 1, r14 contains the ins
+.macro SETUP_STACK_FRAME code_item, refs, refs32, fp, cfi_refs, load_ins
+    FETCH_CODE_ITEM_INFO \code_item, %ebx, \refs32, %r14d, \load_ins
 
     // Compute required frame size for dex registers: ((2 * ebx) + refs)
     leaq (\refs, %rbx, 2), %r11
@@ -288,10 +367,13 @@
     leaq -24(%rsp), %r10
     subq %r11, %r10
     // Alignment
+    // Note: There may be two pieces of alignment but there is no need to align
+    // out args to `kPointerSize` separately before aligning to kStackAlignment.
     andq $$-16, %r10
 
-    // Set reference and dex registers.
-    leaq 24(%r10, \refs, 4), \refs
+    // Set reference and dex registers, align to pointer size for previous frame and dex pc.
+    leaq 24 + 4(%r10, \refs, 4), \refs
+    andq LITERAL(-__SIZEOF_POINTER__), \refs
     leaq (\refs, %rbx, 4), \fp
 
     // Now setup the stack pointer.
@@ -299,7 +381,7 @@
     CFI_DEF_CFA_REGISTER(r11)
     movq %r10, %rsp
     movq %r11, -8(\refs)
-    CFI_DEFINE_CFA_DEREF(\cfi_refs, -8, (6 + 4 + 1) * 8)
+    CFI_DEF_CFA_BREG_PLUS_UCONST \cfi_refs, -8, ((6 + 4 + 1) * 8)
 
     // Put nulls in reference frame.
     testl %ebx, %ebx
@@ -386,7 +468,7 @@
 // Uses rax as temporary.
 .macro LOOP_OVER_SHORTY_LOADING_GPRS gpr_reg64, gpr_reg32, inst, shorty, arg_index, finished
 1: // LOOP
-    movb (REG_VAR(shorty)), %al   // bl := *shorty
+    movb (REG_VAR(shorty)), %al   // al := *shorty
     addq MACRO_LITERAL(1), REG_VAR(shorty)  // shorty++
     cmpb MACRO_LITERAL(0), %al    // if (al == '\0') goto finished
     je  VAR(finished)
@@ -453,7 +535,7 @@
 // Uses rax as temporary.
 .macro LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm_reg, shorty, arg_index, stack_index, finished
 1: // LOOP
-    movb (REG_VAR(shorty)), %al             // bl := *shorty
+    movb (REG_VAR(shorty)), %al             // al := *shorty
     addq MACRO_LITERAL(1), REG_VAR(shorty)  // shorty++
     cmpb MACRO_LITERAL(0), %al              // if (al == '\0') goto finished
     je VAR(finished)
@@ -527,7 +609,7 @@
 // Uses rax as temporary.
 .macro LOOP_RANGE_OVER_SHORTY_LOADING_GPRS gpr_reg64, gpr_reg32, shorty, arg_index, stack_index, finished
 1: // LOOP
-    movb (REG_VAR(shorty)), %al             // bl := *shorty
+    movb (REG_VAR(shorty)), %al             // al := *shorty
     addq MACRO_LITERAL(1), REG_VAR(shorty)  // shorty++
     cmpb MACRO_LITERAL(0), %al    // if (al == '\0') goto finished
     je  VAR(finished)
@@ -606,19 +688,19 @@
     je 2f
     cmpb MACRO_LITERAL(70), %al             // if (al == 'F') goto FOUND_FLOAT
     je 3f
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
     //  Handle extra argument in arg array taken by a long.
     cmpb MACRO_LITERAL(74), %al   // if (al != 'J') goto LOOP
     jne 1b
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
     jmp 1b                        // goto LOOP
 2:  // FOUND_DOUBLE
-    movsd REG_VAR(xmm_reg),(REG_VAR(fp), REG_VAR(arg_index), 1)
-    addq MACRO_LITERAL(8), REG_VAR(arg_index)
+    movsd REG_VAR(xmm_reg),(REG_VAR(fp), REG_VAR(arg_index), 4)
+    addq MACRO_LITERAL(2), REG_VAR(arg_index)
     jmp 4f
 3:  // FOUND_FLOAT
-    movss REG_VAR(xmm_reg), (REG_VAR(fp), REG_VAR(arg_index), 1)
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    movss REG_VAR(xmm_reg), (REG_VAR(fp), REG_VAR(arg_index), 4)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
 4:
 .endm
 
@@ -628,7 +710,7 @@
 // Uses rax as temporary.
 .macro LOOP_OVER_SHORTY_STORING_GPRS gpr_reg64, gpr_reg32, shorty, arg_index, regs, refs, finished
 1: // LOOP
-    movb (REG_VAR(shorty)), %al             // bl := *shorty
+    movb (REG_VAR(shorty)), %al             // al := *shorty
     addq MACRO_LITERAL(1), REG_VAR(shorty)  // shorty++
     cmpb MACRO_LITERAL(0), %al    // if (al == '\0') goto finished
     je  VAR(finished)
@@ -638,22 +720,22 @@
     je 3f
     cmpb MACRO_LITERAL(68), %al   // if (al == 'D') goto SKIP_DOUBLE
     je 4f
-    movl REG_VAR(gpr_reg32), (REG_VAR(regs), REG_VAR(arg_index), 1)
+    movl REG_VAR(gpr_reg32), (REG_VAR(regs), REG_VAR(arg_index), 4)
     cmpb MACRO_LITERAL(76), %al   // if (al != 'L') goto NOT_REFERENCE
     jne 6f
-    movl REG_VAR(gpr_reg32), (REG_VAR(refs), REG_VAR(arg_index), 1)
+    movl REG_VAR(gpr_reg32), (REG_VAR(refs), REG_VAR(arg_index), 4)
 6:  // NOT_REFERENCE
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
     jmp 5f
 2:  // FOUND_LONG
-    movq REG_VAR(gpr_reg64), (REG_VAR(regs), REG_VAR(arg_index), 1)
-    addq MACRO_LITERAL(8), REG_VAR(arg_index)
+    movq REG_VAR(gpr_reg64), (REG_VAR(regs), REG_VAR(arg_index), 4)
+    addq MACRO_LITERAL(2), REG_VAR(arg_index)
     jmp 5f
 3:  // SKIP_FLOAT
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
     jmp 1b
 4:  // SKIP_DOUBLE
-    addq MACRO_LITERAL(8), REG_VAR(arg_index)
+    addq MACRO_LITERAL(2), REG_VAR(arg_index)
     jmp 1b
 5:
 .endm
@@ -668,7 +750,7 @@
 // (The trade-off is different for passing arguments and receiving them.)
 .macro LOOP_OVER_FPs shorty, arg_index, regs, stack_ptr, finished
 1: // LOOP
-    movb (REG_VAR(shorty)), %al             // bl := *shorty
+    movb (REG_VAR(shorty)), %al             // al := *shorty
     addq MACRO_LITERAL(1), REG_VAR(shorty)  // shorty++
     cmpb MACRO_LITERAL(0), %al              // if (al == '\0') goto finished
     je VAR(finished)
@@ -676,21 +758,21 @@
     je 2f
     cmpb MACRO_LITERAL(70), %al             // if (al == 'F') goto FOUND_FLOAT
     je 3f
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
     //  Handle extra argument in arg array taken by a long.
     cmpb MACRO_LITERAL(74), %al   // if (al != 'J') goto LOOP
     jne 1b
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
     jmp 1b                        // goto LOOP
 2:  // FOUND_DOUBLE
-    movq OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 1), %rax
-    movq %rax, (REG_VAR(regs), REG_VAR(arg_index), 1)
-    addq MACRO_LITERAL(8), REG_VAR(arg_index)
+    movq OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 4), %rax
+    movq %rax, (REG_VAR(regs), REG_VAR(arg_index), 4)
+    addq MACRO_LITERAL(2), REG_VAR(arg_index)
     jmp 1b
 3:  // FOUND_FLOAT
-    movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 1), %eax
-    movl %eax, (REG_VAR(regs), REG_VAR(arg_index), 1)
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 4), %eax
+    movl %eax, (REG_VAR(regs), REG_VAR(arg_index), 4)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
     jmp 1b
 .endm
 
@@ -700,7 +782,7 @@
 // Uses rax as temporary.
 .macro LOOP_OVER_INTs shorty, arg_index, regs, refs, stack_ptr, finished
 1: // LOOP
-    movb (REG_VAR(shorty)), %al             // bl := *shorty
+    movb (REG_VAR(shorty)), %al             // al := *shorty
     addq MACRO_LITERAL(1), REG_VAR(shorty)  // shorty++
     cmpb MACRO_LITERAL(0), %al    // if (al == '\0') goto finished
     je  VAR(finished)
@@ -712,26 +794,26 @@
     je 3f
     cmpb MACRO_LITERAL(68), %al   // if (al == 'D') goto SKIP_DOUBLE
     je 4f
-    movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 1), %eax
-    movl %eax, (REG_VAR(regs), REG_VAR(arg_index), 1)
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 4), %eax
+    movl %eax, (REG_VAR(regs), REG_VAR(arg_index), 4)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
     jmp 1b
 6:  // FOUND_REFERENCE
-    movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 1), %eax
-    movl %eax, (REG_VAR(regs), REG_VAR(arg_index), 1)
-    movl %eax, (REG_VAR(refs), REG_VAR(arg_index), 1)
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 4), %eax
+    movl %eax, (REG_VAR(regs), REG_VAR(arg_index), 4)
+    movl %eax, (REG_VAR(refs), REG_VAR(arg_index), 4)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
     jmp 1b
 2:  // FOUND_LONG
-    movq OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 1), %rax
-    movq %rax, (REG_VAR(regs), REG_VAR(arg_index), 1)
-    addq MACRO_LITERAL(8), REG_VAR(arg_index)
+    movq OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 4), %rax
+    movq %rax, (REG_VAR(regs), REG_VAR(arg_index), 4)
+    addq MACRO_LITERAL(2), REG_VAR(arg_index)
     jmp 1b
 3:  // SKIP_FLOAT
-    addq MACRO_LITERAL(4), REG_VAR(arg_index)
+    addq MACRO_LITERAL(1), REG_VAR(arg_index)
     jmp 1b
 4:  // SKIP_DOUBLE
-    addq MACRO_LITERAL(8), REG_VAR(arg_index)
+    addq MACRO_LITERAL(2), REG_VAR(arg_index)
     jmp 1b
 .endm
 
@@ -739,7 +821,8 @@
 .macro START_EXECUTING_INSTRUCTIONS
    movq (%rsp), %rdi
    addw $$1, ART_METHOD_HOTNESS_COUNT_OFFSET(%rdi)
-   jo 2f
+   andw $$(NTERP_HOTNESS_MASK), ART_METHOD_HOTNESS_COUNT_OFFSET(%rdi)
+   jz 2f
    testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), rSELF:THREAD_FLAGS_OFFSET
    jz 1f
    EXPORT_PC
@@ -780,6 +863,9 @@
 // - rPC: the new PC pointer to execute
 // - edi: number of arguments
 // - ecx: first dex register
+//
+// This helper expects:
+// - rax to contain the code item
 .macro SETUP_STACK_FOR_INVOKE
    // We do the same stack overflow check as the compiler. See CanMethodUseNterp
    // in how we limit the maximum nterp frame size.
@@ -790,7 +876,7 @@
    SPILL_ALL_CALLEE_SAVES
 
    // Setup the frame.
-   SETUP_STACK_FRAME %rax, rNEW_REFS, rNEW_FP, CFI_NEW_REFS
+   SETUP_STACK_FRAME %rax, rNEW_REFS, rNEW_REFS32, rNEW_FP, CFI_NEW_REFS, load_ins=0
    // Make r11 point to the top of the dex register array.
    leaq (rNEW_FP, %rbx, 4), %r11
 
@@ -799,7 +885,7 @@
    movzwl 4(rPC), %ecx
 
    // Set the dex pc pointer.
-   leaq CODE_ITEM_INSNS_OFFSET(%rax), rPC
+   movq %rax, rPC
    CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
 .endm
 
@@ -886,7 +972,7 @@
    // Start executing the method.
    movq rNEW_FP, rFP
    movq rNEW_REFS, rREFS
-   CFI_DEFINE_CFA_DEREF(CFI_REFS, -8, (6 + 4 + 1) * 8)
+   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, ((6 + 4 + 1) * 8)
    START_EXECUTING_INSTRUCTIONS
 .endm
 
@@ -932,7 +1018,7 @@
    .endif
    movq rNEW_FP, rFP
    movq rNEW_REFS, rREFS
-   CFI_DEFINE_CFA_DEREF(CFI_REFS, -8, (6 + 4 + 1) * 8)
+   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, ((6 + 4 + 1) * 8)
    START_EXECUTING_INSTRUCTIONS
 .endm
 
@@ -959,19 +1045,36 @@
    movq %rax, \dest
 .endm
 
-.macro DO_ENTRY_POINT_CHECK call_compiled_code
-   // On entry, the method is %rdi, the instance is %rsi
-   leaq ExecuteNterpImpl(%rip), %rax
-   cmpq %rax, ART_METHOD_QUICK_CODE_OFFSET_64(%rdi)
-   jne  VAR(call_compiled_code)
-
-   // TODO: Get code item in a better way and remove below
+.macro GET_SHORTY_SLOW_PATH dest, is_interface
+   // Save all registers that can hold arguments in the fast path.
    push %rdi
    push %rsi
-   call SYMBOL(NterpGetCodeItem)
+   push %rdx
+   subq MACRO_LITERAL(8), %rsp
+   mov %xmm0, (%rsp)
+   .if \is_interface
+   movq 32(%rsp), %rdi
+   movzwl 2(rPC), %esi
+   call SYMBOL(NterpGetShortyFromMethodId)
+   .else
+   call SYMBOL(NterpGetShorty)
+   .endif
+   mov (%rsp), %xmm0
+   addq MACRO_LITERAL(8), %rsp
+   pop %rdx
    pop %rsi
    pop %rdi
-   // TODO: Get code item in a better way and remove above
+   movq %rax, \dest
+.endm
+
+// Uses r9 as temporary.
+.macro DO_ENTRY_POINT_CHECK call_compiled_code
+   // On entry, the method is %rdi, the instance is %rsi
+   leaq ExecuteNterpImpl(%rip), %r9
+   cmpq %r9, ART_METHOD_QUICK_CODE_OFFSET_64(%rdi)
+   jne  VAR(call_compiled_code)
+
+   movq ART_METHOD_DATA_OFFSET_64(%rdi), %rax
 .endm
 
 // Uses r9 and r10 as temporary
@@ -1008,6 +1111,107 @@
    .endif
 
 .Lcall_compiled_code_\suffix:
+   .if \is_polymorphic
+   // No fast path for polymorphic calls.
+   .elseif \is_custom
+   // No fast path for custom calls.
+   .elseif \is_string_init
+   // No fast path for string.init.
+   .else
+     testl $$ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi)
+     je .Lfast_path_with_few_args_\suffix
+     movzbl 1(rPC), %r9d
+     movl %r9d, %ebp
+     shrl MACRO_LITERAL(4), %ebp # Number of arguments
+     .if \is_static
+     jz .Linvoke_fast_path_\suffix  # shl sets the Z flag
+     .else
+     cmpl MACRO_LITERAL(1), %ebp
+     je .Linvoke_fast_path_\suffix
+     .endif
+     movzwl 4(rPC), %r11d
+     cmpl MACRO_LITERAL(2), %ebp
+     .if \is_static
+     jl .Lone_arg_fast_path_\suffix
+     .endif
+     je .Ltwo_args_fast_path_\suffix
+     cmpl MACRO_LITERAL(4), %ebp
+     jl .Lthree_args_fast_path_\suffix
+     je .Lfour_args_fast_path_\suffix
+
+     andl        MACRO_LITERAL(0xf), %r9d
+     GET_VREG    %r9d, %r9
+.Lfour_args_fast_path_\suffix:
+     movl        %r11d, %r8d
+     shrl        MACRO_LITERAL(12), %r8d
+     GET_VREG    %r8d, %r8
+.Lthree_args_fast_path_\suffix:
+     movl        %r11d, %ecx
+     shrl        MACRO_LITERAL(8), %ecx
+     andl        MACRO_LITERAL(0xf), %ecx
+     GET_VREG    %ecx, %rcx
+.Ltwo_args_fast_path_\suffix:
+     movl        %r11d, %edx
+     shrl        MACRO_LITERAL(4), %edx
+     andl        MACRO_LITERAL(0xf), %edx
+     GET_VREG    %edx, %rdx
+.Lone_arg_fast_path_\suffix:
+     .if \is_static
+     andl        MACRO_LITERAL(0xf), %r11d
+     GET_VREG    %esi, %r11
+     .else
+     // First argument already in %esi.
+     .endif
+.Linvoke_fast_path_\suffix:
+     call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
+     ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+.Lfast_path_with_few_args_\suffix:
+     // Fast path when we have zero or one argument (modulo 'this'). If there
+     // is one argument, we can put it in both floating point and core register.
+     movzbl 1(rPC), %r9d
+     shrl MACRO_LITERAL(4), %r9d # Number of arguments
+     .if \is_static
+     cmpl MACRO_LITERAL(1), %r9d
+     jl .Linvoke_with_few_args_\suffix
+     jne .Lget_shorty_\suffix
+     movzwl 4(rPC), %r9d
+     andl MACRO_LITERAL(0xf), %r9d  // dex register of first argument
+     GET_VREG %esi, %r9
+     movd %esi, %xmm0
+     .else
+     cmpl MACRO_LITERAL(2), %r9d
+     jl .Linvoke_with_few_args_\suffix
+     jne .Lget_shorty_\suffix
+     movzwl 4(rPC), %r9d
+     shrl MACRO_LITERAL(4), %r9d
+     andl MACRO_LITERAL(0xf), %r9d  // dex register of second argument
+     GET_VREG %edx, %r9
+     movd %edx, %xmm0
+     .endif
+.Linvoke_with_few_args_\suffix:
+     // Check if the next instruction is move-result or move-result-wide.
+     // If it is, we fetch the shorty and jump to the regular invocation.
+     movzwq  6(rPC), %r9
+     andl MACRO_LITERAL(0xfe), %r9d
+     cmpl MACRO_LITERAL(0x0a), %r9d
+     je .Lget_shorty_and_invoke_\suffix
+     call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
+     ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+.Lget_shorty_and_invoke_\suffix:
+     .if \is_interface
+     // Save interface method, used for conflict resolution, in a callee-save register.
+     movq %rax, %xmm12
+     .endif
+     GET_SHORTY_SLOW_PATH rINSTq, \is_interface
+     jmp .Lgpr_setup_finished_\suffix
+   .endif
+
+.Lget_shorty_\suffix:
+   .if \is_interface
+   // Save interface method, used for conflict resolution, in a callee-save register.
+   movq %rax, %xmm12
+   .endif
    GET_SHORTY rINSTq, \is_interface, \is_polymorphic, \is_custom
    // From this point:
    // - rISNTq contains shorty (in callee-save to switch over return value after call).
@@ -1054,7 +1258,7 @@
    call SYMBOL(art_quick_invoke_custom)
    .else
       .if \is_interface
-      movzwl 2(rPC), %eax
+      movq %xmm12, %rax
       .endif
       call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
    .endif
@@ -1101,6 +1305,104 @@
    .endif
 
 .Lcall_compiled_code_range_\suffix:
+   .if \is_polymorphic
+   // No fast path for polymorphic calls.
+   .elseif \is_custom
+   // No fast path for custom calls.
+   .elseif \is_string_init
+   // No fast path for string.init.
+   .else
+     testl $$ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi)
+     je .Lfast_path_with_few_args_range_\suffix
+     movzbl 1(rPC), %r9d  // number of arguments
+     .if \is_static
+     testl %r9d, %r9d
+     je .Linvoke_fast_path_range_\suffix
+     .else
+     cmpl MACRO_LITERAL(1), %r9d
+     je .Linvoke_fast_path_range_\suffix
+     .endif
+     movzwl 4(rPC), %r11d  // dex register of first argument
+     leaq (rFP, %r11, 4), %r11  // location of first dex register value
+     cmpl MACRO_LITERAL(2), %r9d
+     .if \is_static
+     jl .Lone_arg_fast_path_range_\suffix
+     .endif
+     je .Ltwo_args_fast_path_range_\suffix
+     cmp MACRO_LITERAL(4), %r9d
+     jl .Lthree_args_fast_path_range_\suffix
+     je .Lfour_args_fast_path_range_\suffix
+     cmp MACRO_LITERAL(5), %r9d
+     je .Lfive_args_fast_path_range_\suffix
+
+.Lloop_over_fast_path_range_\suffix:
+     subl MACRO_LITERAL(1), %r9d
+     movl (%r11, %r9, 4), %r8d
+     movl %r8d, 8(%rsp, %r9, 4)  // Add 8 for the ArtMethod
+     cmpl MACRO_LITERAL(5), %r9d
+     jne .Lloop_over_fast_path_range_\suffix
+
+.Lfive_args_fast_path_range_\suffix:
+     movl 16(%r11), %r9d
+.Lfour_args_fast_path_range_\suffix:
+     movl 12(%r11), %r8d
+.Lthree_args_fast_path_range_\suffix:
+     movl 8(%r11), %ecx
+.Ltwo_args_fast_path_range_\suffix:
+     movl 4(%r11), %edx
+.Lone_arg_fast_path_range_\suffix:
+     .if \is_static
+     movl 0(%r11), %esi
+     .else
+     // First argument already in %esi.
+     .endif
+.Linvoke_fast_path_range_\suffix:
+     call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
+     ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+.Lfast_path_with_few_args_range_\suffix:
+     // Fast path when we have zero or one argument (modulo 'this'). If there
+     // is one argument, we can put it in both floating point and core register.
+     movzbl 1(rPC), %r9d # Number of arguments
+     .if \is_static
+     cmpl MACRO_LITERAL(1), %r9d
+     jl .Linvoke_with_few_args_range_\suffix
+     jne .Lget_shorty_range_\suffix
+     movzwl 4(rPC), %r9d  // Dex register of first argument
+     GET_VREG %esi, %r9
+     movd %esi, %xmm0
+     .else
+     cmpl MACRO_LITERAL(2), %r9d
+     jl .Linvoke_with_few_args_range_\suffix
+     jne .Lget_shorty_range_\suffix
+     movzwl 4(rPC), %r9d
+     addl MACRO_LITERAL(1), %r9d  // dex register of second argument
+     GET_VREG %edx, %r9
+     movd %edx, %xmm0
+     .endif
+.Linvoke_with_few_args_range_\suffix:
+     // Check if the next instruction is move-result or move-result-wide.
+     // If it is, we fetch the shorty and jump to the regular invocation.
+     movzwq  6(rPC), %r9
+     and MACRO_LITERAL(0xfe), %r9d
+     cmpl MACRO_LITERAL(0x0a), %r9d
+     je .Lget_shorty_and_invoke_range_\suffix
+     call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
+     ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+.Lget_shorty_and_invoke_range_\suffix:
+     .if \is_interface
+     // Save interface method, used for conflict resolution, in a callee-save register.
+     movq %rax, %xmm12
+     .endif
+     GET_SHORTY_SLOW_PATH rINSTq, \is_interface
+     jmp .Lgpr_setup_finished_range_\suffix
+   .endif
+
+.Lget_shorty_range_\suffix:
+   .if \is_interface
+   // Save interface method, used for conflict resolution, in a callee-saved register.
+   movq %rax, %xmm12
+   .endif
    GET_SHORTY rINSTq, \is_interface, \is_polymorphic, \is_custom
    // From this point:
    // - rINSTq contains shorty (in callee-save to switch over return value after call).
@@ -1132,10 +1434,10 @@
    .if \is_string_init
    addq $$1, %r10       // arg start index
    movq $$1, %rbp       // index in stack
-   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS rsi, esi, r11, r10, rbp, .Lgpr_setup_finished_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS rsi, esi, r11, r10, rbp, .Lgpr_setup_finished_range_\suffix
    .elseif \is_static
    movq $$0, %rbp // index in stack
-   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS rsi, esi, r11, r10, rbp, .Lgpr_setup_finished_\suffix
+   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS rsi, esi, r11, r10, rbp, .Lgpr_setup_finished_range_\suffix
    .else
    addq $$1, %r10       // arg start index
    movq $$1, %rbp // index in stack
@@ -1153,7 +1455,8 @@
    call SYMBOL(art_quick_invoke_custom)
    .else
      .if \is_interface
-     movzwl 2(rPC), %eax
+     // Set the hidden argument for conflict resolution.
+     movq %xmm12, %rax
      .endif
      call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
    .endif
@@ -1213,10 +1516,11 @@
    .endif
    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
 2:
+   EXPORT_PC
    movq rSELF:THREAD_SELF_OFFSET, %rdi
    movq 0(%rsp), %rsi
    movq rPC, %rdx
-   EXPORT_PC
+   movq $$0, %rcx
    call nterp_get_static_field
    // Clear the marker that we put for volatile fields. The x86 memory
    // model doesn't require a barrier.
@@ -1245,10 +1549,11 @@
    \store    \rINST_reg, (%rax,%rdx,1)
    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
 2:
+   EXPORT_PC
    movq rSELF:THREAD_SELF_OFFSET, %rdi
    movq 0(%rsp), %rsi
    movq rPC, %rdx
-   EXPORT_PC
+   movq $$0, %rcx
    call nterp_get_static_field
    testq MACRO_LITERAL(1), %rax
    je 1b
@@ -1300,10 +1605,11 @@
    OP_IPUT_INTERNAL \rINST_reg, \store, \wide
    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
 2:
+   EXPORT_PC
    movq rSELF:THREAD_SELF_OFFSET, %rdi
    movq 0(%rsp), %rsi
    movq rPC, %rdx
-   EXPORT_PC
+   movq $$0, %rcx
    call nterp_get_instance_field_offset
    testl %eax, %eax
    jns 1b
@@ -1333,10 +1639,11 @@
    .endif
    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
 2:
+   EXPORT_PC
    movq rSELF:THREAD_SELF_OFFSET, %rdi
    movq 0(%rsp), %rsi
    movq rPC, %rdx
-   EXPORT_PC
+   movq $$0, %rcx
    call nterp_get_instance_field_offset
    testl %eax, %eax
    jns 1b
@@ -1344,6 +1651,25 @@
    jmp 1b
 .endm
 
+.macro SETUP_REFERENCE_PARAMETER_IN_GPR gpr32, regs, refs, ins, arg_offset, finished
+    movl REG_VAR(gpr32), (REG_VAR(regs), REG_VAR(arg_offset))
+    movl REG_VAR(gpr32), (REG_VAR(refs), REG_VAR(arg_offset))
+    addq MACRO_LITERAL(4), REG_VAR(arg_offset)
+    subl MACRO_LITERAL(1), REG_VAR(ins)
+    je \finished
+.endm
+
+// Uses eax as temporary
+.macro SETUP_REFERENCE_PARAMETERS_IN_STACK regs, refs, ins, stack_ptr, arg_offset
+1:
+    movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_offset)), %eax
+    movl %eax, (REG_VAR(regs), REG_VAR(arg_offset))
+    movl %eax, (REG_VAR(refs), REG_VAR(arg_offset))
+    addq MACRO_LITERAL(4), REG_VAR(arg_offset)
+    subl MACRO_LITERAL(1), REG_VAR(ins)
+    jne 1b
+.endm
+
 %def entry():
 /*
  * ArtMethod entry point.
@@ -1360,17 +1686,55 @@
     /* Spill callee save regs */
     SPILL_ALL_CALLEE_SAVES
 
+    movq ART_METHOD_DATA_OFFSET_64(%rdi), rPC
+
+    // Setup the stack for executing the method.
+    SETUP_STACK_FRAME rPC, rREFS, rREFS32, rFP, CFI_REFS, load_ins=1
+
+    // Setup the parameters
+    testl %r14d, %r14d
+    je .Lxmm_setup_finished
+
+    subq %r14, %rbx
+    salq $$2, %rbx // rbx is now the offset for inputs into the registers array.
+
+    testl $$ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi)
+    je .Lsetup_slow_path
+    leaq (rFP, %rbx, 1), %rdi
+    leaq (rREFS, %rbx, 1), %rbx
+    movq $$0, %r10
+
+    SETUP_REFERENCE_PARAMETER_IN_GPR esi, rdi, rbx, r14d, r10, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR edx, rdi, rbx, r14d, r10, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR ecx, rdi, rbx, r14d, r10, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR r8d, rdi, rbx, r14d, r10, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETER_IN_GPR r9d, rdi, rbx, r14d, r10, .Lxmm_setup_finished
+    SETUP_REFERENCE_PARAMETERS_IN_STACK rdi, rbx, r14d, r11, r10
+    jmp .Lxmm_setup_finished
+
+.Lsetup_slow_path:
+    // If the method is not static and there is one argument ('this'), we don't need to fetch the
+    // shorty.
+    testl $$ART_METHOD_IS_STATIC_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi)
+    jne .Lsetup_with_shorty
+
+    movl %esi, (rFP, %rbx)
+    movl %esi, (rREFS, %rbx)
+
+    cmpl $$1, %r14d
+    je .Lxmm_setup_finished
+
+.Lsetup_with_shorty:
     // TODO: Get shorty in a better way and remove below
-    PUSH rdi
-    PUSH rsi
-    PUSH rdx
-    PUSH rcx
-    PUSH r8
-    PUSH r9
+    push %rdi
+    push %rsi
+    push %rdx
+    push %rcx
+    push %r8
+    push %r9
 
     // Save xmm registers + alignment.
     subq MACRO_LITERAL(8 * 8 + 8), %rsp
-    CFI_ADJUST_CFA_OFFSET(8 * 8 + 8)
     movq %xmm0, 0(%rsp)
     movq %xmm1, 8(%rsp)
     movq %xmm2, 16(%rsp)
@@ -1380,14 +1744,9 @@
     movq %xmm6, 48(%rsp)
     movq %xmm7, 56(%rsp)
 
-    // Save method in callee-save rbx.
-    movq %rdi, %rbx
     call SYMBOL(NterpGetShorty)
     // Save shorty in callee-save rbp.
     movq %rax, %rbp
-    movq %rbx, %rdi
-    call SYMBOL(NterpGetCodeItem)
-    movq %rax, rPC
 
     // Restore xmm registers + alignment.
     movq 0(%rsp), %xmm0
@@ -1399,44 +1758,31 @@
     movq 48(%rsp), %xmm6
     movq 56(%rsp), %xmm7
     addq MACRO_LITERAL(8 * 8 + 8), %rsp
-    CFI_ADJUST_CFA_OFFSET(-8 * 8 - 8)
 
-    POP r9
-    POP r8
-    POP rcx
-    POP rdx
-    POP rsi
-    POP rdi
+    pop %r9
+    pop %r8
+    pop %rcx
+    pop %rdx
+    pop %rsi
+    pop %rdi
+    // Reload the old stack pointer, which used to be stored in %r11, which is not callee-saved.
+    movq -8(rREFS), %r11
     // TODO: Get shorty in a better way and remove above
 
-    // Setup the stack for executing the method.
-    SETUP_STACK_FRAME rPC, rREFS, rFP, CFI_REFS
-
-    // Setup the parameters
-    movzwl CODE_ITEM_INS_SIZE_OFFSET(rPC), %r14d
-    testl %r14d, %r14d
-    je .Lxmm_setup_finished
-
-    subq %r14, %rbx
-    salq $$2, %rbx // rbx is now the offset for inputs into the registers array.
-
+    movq $$0, %r14
     testl $$ART_METHOD_IS_STATIC_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi)
 
-    // Available: rdi, r10, r14
+    // Available: rdi, r10
     // Note the leaq below don't change the flags.
     leaq 1(%rbp), %r10  // shorty + 1  ; ie skip return arg character
     leaq (rFP, %rbx, 1), %rdi
     leaq (rREFS, %rbx, 1), %rbx
     jne .Lhandle_static_method
-    movl %esi, (%rdi)
-    movl %esi, (%rbx)
     addq $$4, %rdi
     addq $$4, %rbx
     addq $$4, %r11
-    movq $$0, %r14
     jmp .Lcontinue_setup_gprs
 .Lhandle_static_method:
-    movq $$0, %r14
     LOOP_OVER_SHORTY_STORING_GPRS rsi, esi, r10, r14, rdi, rbx, .Lgpr_setup_finished
 .Lcontinue_setup_gprs:
     LOOP_OVER_SHORTY_STORING_GPRS rdx, edx, r10, r14, rdi, rbx, .Lgpr_setup_finished
@@ -1457,8 +1803,6 @@
     LOOP_OVER_SHORTY_STORING_XMMS xmm7, r10, r14, rdi, .Lxmm_setup_finished
     LOOP_OVER_FPs r10, r14, rdi, r11, .Lxmm_setup_finished
 .Lxmm_setup_finished:
-    // Set the dex pc pointer.
-    addq $$CODE_ITEM_INSNS_OFFSET, rPC
     CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
 
     // Set rIBASE
@@ -1483,12 +1827,16 @@
     .text
     .align  2
 
+// Enclose all code below in a symbol (which gets printed in backtraces).
+ENTRY nterp_helper
+
 // Note: mterp also uses the common_* names below for helpers, but that's OK
 // as the C compiler compiled each interpreter separately.
 common_errDivideByZero:
     EXPORT_PC
     call art_quick_throw_div_zero
 
+// Expect array in edi, index in esi.
 common_errArrayIndex:
     EXPORT_PC
     movl MIRROR_ARRAY_LENGTH_OFFSET(%edi), %eax
@@ -1586,22 +1934,22 @@
    jmp 1b
 
 NterpPutObjectInstanceField:
+   movl    rINST, %ebp                     # rbp <- BA
+   andl    $$0xf, %ebp                     # rbp <- A
+   GET_VREG %ecx, %rbp                     # ecx <- v[A]
+   sarl    $$4, rINST
    // Fast-path which gets the field from thread-local cache.
    FETCH_FROM_THREAD_CACHE %rax, 2f
 1:
-   movzbq  rINSTbl, %rcx                   # rcx <- BA
-   sarl    $$4, %ecx                       # ecx <- B
-   GET_VREG %ecx, %rcx                     # vB (object we're operating on)
-   testl   %ecx, %ecx                      # is object null?
+   GET_VREG rINST, rINSTq                  # vB (object we're operating on)
+   testl   rINST, rINST                    # is object null?
    je      common_errNullObject
-   andb    $$0xf, rINSTbl                  # rINST <- A
-   GET_VREG rINST, rINSTq                  # rINST <- v[A]
-   movl rINST, (%rcx,%rax,1)
-   testl rINST, rINST
+   movl %ecx, (rINSTq,%rax,1)
+   testl %ecx, %ecx
    je 4f
    movq rSELF:THREAD_CARD_TABLE_OFFSET, %rax
-   shrq $$CARD_TABLE_CARD_SHIFT, %rcx
-   movb %al, (%rax, %rcx, 1)
+   shrq $$CARD_TABLE_CARD_SHIFT, rINSTq
+   movb %al, (%rax, rINSTq, 1)
 4:
    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
 2:
@@ -1609,24 +1957,22 @@
    movq rSELF:THREAD_SELF_OFFSET, %rdi
    movq 0(%rsp), %rsi
    movq rPC, %rdx
-   EXPORT_PC
+   // %rcx is already set.
    call nterp_get_instance_field_offset
+   // Reload the value as it may have moved.
+   GET_VREG %ecx, %rbp                     # ecx <- v[A]
    testl %eax, %eax
    jns 1b
-   negl %eax
-   movzbq  rINSTbl, %rcx                   # rcx <- BA
-   sarl    $$4, %ecx                       # ecx <- B
-   GET_VREG %ecx, %rcx                     # vB (object we're operating on)
-   testl   %ecx, %ecx                      # is object null?
+   GET_VREG rINST, rINSTq                  # vB (object we're operating on)
+   testl   rINST, rINST                    # is object null?
    je      common_errNullObject
-   andb    $$0xf, rINSTbl                  # rINST <- A
-   GET_VREG rINST, rINSTq                  # rINST <- v[A]
-   movl rINST, (%rcx,%rax,1)
-   testl rINST, rINST
+   negl %eax
+   movl %ecx, (rINSTq,%rax,1)
+   testl %ecx, %ecx
    je 5f
    movq rSELF:THREAD_CARD_TABLE_OFFSET, %rax
-   shrq $$CARD_TABLE_CARD_SHIFT, %rcx
-   movb %al, (%rcx, %rax, 1)
+   shrq $$CARD_TABLE_CARD_SHIFT, rINSTq
+   movb %al, (%rax, rINSTq, 1)
 5:
    lock addl $$0, (%rsp)
    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
@@ -1652,7 +1998,7 @@
    movq rSELF:THREAD_SELF_OFFSET, %rdi
    movq 0(%rsp), %rsi
    movq rPC, %rdx
-   EXPORT_PC
+   movq $$0, %rcx
    call nterp_get_instance_field_offset
    testl %eax, %eax
    jns 1b
@@ -1666,6 +2012,7 @@
    jmp 4b
 
 NterpPutObjectStaticField:
+   GET_VREG %ebp, rINSTq
    // Fast-path which gets the field from thread-local cache.
    FETCH_FROM_THREAD_CACHE %rax, 2f
 1:
@@ -1674,9 +2021,8 @@
    cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET
    jne 3f
 5:
-   GET_VREG %ecx, rINSTq
-   movl %ecx, (%eax, %edx, 1)
-   testl %ecx, %ecx
+   movl %ebp, (%eax, %edx, 1)
+   testl %ebp, %ebp
    je 4f
    movq rSELF:THREAD_CARD_TABLE_OFFSET, %rcx
    shrq $$CARD_TABLE_CARD_SHIFT, %rax
@@ -1684,11 +2030,14 @@
 4:
    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
 2:
+   EXPORT_PC
    movq rSELF:THREAD_SELF_OFFSET, %rdi
    movq 0(%rsp), %rsi
    movq rPC, %rdx
-   EXPORT_PC
+   movq %rbp, %rcx
    call nterp_get_static_field
+   // Reload the value as it may have moved.
+   GET_VREG %ebp, rINSTq
    testq MACRO_LITERAL(1), %rax
    je 1b
    CLEAR_VOLATILE_MARKER %rax
@@ -1697,10 +2046,8 @@
    cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET
    jne 7f
 6:
-   movzbl rINSTbl, %ecx
-   GET_VREG %ecx, %rcx
-   movl %ecx, (%eax, %edx, 1)
-   testl %ecx, %ecx
+   movl %ebp, (%eax, %edx, 1)
+   testl %ebp, %ebp
    je 8f
    movq rSELF:THREAD_CARD_TABLE_OFFSET, %rcx
    shrq $$CARD_TABLE_CARD_SHIFT, %rax
@@ -1731,10 +2078,11 @@
    SET_VREG_OBJECT %eax, rINSTq            # fp[A] <- value
    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
 2:
+   EXPORT_PC
    movq rSELF:THREAD_SELF_OFFSET, %rdi
    movq 0(%rsp), %rsi
    movq rPC, %rdx
-   EXPORT_PC
+   movq $$0, %rcx
    call nterp_get_static_field
    andq $$-2, %rax
    jmp 1b
@@ -1906,21 +2254,12 @@
     jmp *%rbx
 
 NterpHandleInvokeInterfaceOnObjectMethodRange:
-   // First argument is the 'this' pointer.
-   movzwl 4(rPC), %r11d // arguments
-   movl (rFP, %r11, 4), %esi
-   // Note: if esi is null, this will be handled by our SIGSEGV handler.
-   movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
+   shrl $$16, %eax
    movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %eax, 8), %rdi
    jmp NterpCommonInvokeInstanceRange
 
 NterpHandleInvokeInterfaceOnObjectMethod:
-   // First argument is the 'this' pointer.
-   movzwl 4(rPC), %r11d // arguments
-   andq MACRO_LITERAL(0xf), %r11
-   movl (rFP, %r11, 4), %esi
-   // Note: if esi is null, this will be handled by our SIGSEGV handler.
-   movl MIRROR_OBJECT_CLASS_OFFSET(%esi), %edx
+   shrl $$16, %eax
    movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %eax, 8), %rdi
    jmp NterpCommonInvokeInstance
 
@@ -1971,6 +2310,8 @@
     SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
     .cfi_endproc
 
+END nterp_helper
+
 // This is the end of PCs contained by the OatQuickMethodHeader created for the interpreter
 // entry point.
     FUNCTION_TYPE(EndExecuteNterpImpl)
@@ -2008,6 +2349,9 @@
 SYMBOL(artNterpAsmInstructionStart) = .L_op_nop
     .text
 
+%def default_helper_prefix():
+%  return "nterp_"
+
 %def opcode_start():
     ENTRY nterp_${opcode}
 %def opcode_end():
diff --git a/runtime/interpreter/mterp/x86_64ng/object.S b/runtime/interpreter/mterp/x86_64ng/object.S
index cb231e3..2b4e12c 100644
--- a/runtime/interpreter/mterp/x86_64ng/object.S
+++ b/runtime/interpreter/mterp/x86_64ng/object.S
@@ -4,74 +4,21 @@
 %def op_iget_boolean():
    jmp NterpGetBooleanInstanceField
 
-%def op_iget_boolean_quick():
-%  op_iget_quick(load="movsbl")
-
 %def op_iget_byte():
    jmp NterpGetByteInstanceField
 
-%def op_iget_byte_quick():
-%  op_iget_quick(load="movsbl")
-
 %def op_iget_char():
    jmp NterpGetCharInstanceField
 
-%def op_iget_char_quick():
-%  op_iget_quick(load="movzwl")
-
 %def op_iget_object():
     jmp NterpGetObjectInstanceField
 
-%def op_iget_object_quick():
-   movzwq  2(rPC), %rax                    # eax <- field byte offset
-   movl    rINST, %ecx                     # rcx <- BA
-   sarl    $$4, %ecx                       # ecx <- B
-   GET_VREG %ecx, %rcx                     # vB (object we're operating on)
-   testl   %ecx, %ecx                      # is object null?
-   je      common_errNullObject
-   testb $$READ_BARRIER_TEST_VALUE, GRAY_BYTE_OFFSET(%ecx)
-   movl (%rcx,%rax,1), %eax
-   jnz 2f
-1:
-   andb    $$0xf,rINSTbl                   # rINST <- A
-   SET_VREG_OBJECT %eax, rINSTq            # fp[A] <- value
-   ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-2:
-   // reg00 is eax
-   call art_quick_read_barrier_mark_reg00
-   jmp 1b
-
-%def op_iget_quick(load="movl", wide="0"):
-    /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick, iget-wide-quick */
-    /* op vA, vB, offset@CCCC */
-    movl    rINST, %ecx                     # rcx <- BA
-    sarl    $$4, %ecx                       # ecx <- B
-    GET_VREG %ecx, %rcx                     # vB (object we're operating on)
-    movzwq  2(rPC), %rax                    # eax <- field byte offset
-    testl   %ecx, %ecx                      # is object null?
-    je      common_errNullObject
-    andb    $$0xf,rINSTbl                   # rINST <- A
-    .if $wide
-    movq (%rcx,%rax,1), %rax
-    SET_WIDE_VREG %rax, rINSTq              # fp[A] <- value
-    .else
-    ${load} (%rcx,%rax,1), %eax
-    SET_VREG %eax, rINSTq                   # fp[A] <- value
-    .endif
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
 %def op_iget_short():
    jmp NterpGetShortInstanceField
 
-%def op_iget_short_quick():
-%  op_iget_quick(load="movswl")
-
 %def op_iget_wide():
    jmp NterpGetWideInstanceField
 
-%def op_iget_wide_quick():
-%  op_iget_quick(load="movq", wide="1")
-
 %def op_instance_of():
    jmp NterpInstanceOf
 
@@ -84,79 +31,21 @@
 %def op_iput_boolean():
    jmp NterpPutBooleanInstanceField
 
-%def op_iput_boolean_quick():
-%  op_iput_quick(reg="rINSTbl", store="movb")
-
 %def op_iput_byte():
    jmp NterpPutByteInstanceField
 
-%def op_iput_byte_quick():
-%  op_iput_quick(reg="rINSTbl", store="movb")
-
 %def op_iput_char():
    jmp NterpPutCharInstanceField
 
-%def op_iput_char_quick():
-%  op_iput_quick(reg="rINSTw", store="movw")
-
 %def op_iput_object():
     jmp NterpPutObjectInstanceField
 
-%def op_iput_object_quick():
-   movzwq  2(rPC), %rax                    # eax <- field byte offset
-   movzbq  rINSTbl, %rcx                   # rcx <- BA
-   sarl    $$4, %ecx                       # ecx <- B
-   GET_VREG %ecx, %rcx                     # vB (object we're operating on)
-   testl   %ecx, %ecx                      # is object null?
-   je      common_errNullObject
-   andb    $$0xf, rINSTbl                  # rINST <- A
-   GET_VREG rINST, rINSTq                  # rINST <- v[A]
-   movl rINST, (%rcx,%rax,1)
-   testl rINST, rINST
-   je 1f
-   movq rSELF:THREAD_CARD_TABLE_OFFSET, %rax
-   shrq $$CARD_TABLE_CARD_SHIFT, %rcx
-   movb %al, (%rcx, %rax, 1)
-1:
-   ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
-%def op_iput_quick(reg="rINST", store="movl"):
-    /* For: iput-quick, iput-object-quick */
-    /* op vA, vB, offset@CCCC */
-    movzbq  rINSTbl, %rcx                   # rcx <- BA
-    sarl    $$4, %ecx                       # ecx <- B
-    GET_VREG %ecx, %rcx                     # vB (object we're operating on)
-    testl   %ecx, %ecx                      # is object null?
-    je      common_errNullObject
-    andb    $$0xf, rINSTbl                  # rINST <- A
-    GET_VREG rINST, rINSTq                  # rINST <- v[A]
-    movzwq  2(rPC), %rax                    # rax <- field byte offset
-    ${store}    ${reg}, (%rcx,%rax,1)
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
 %def op_iput_short():
    jmp NterpPutShortInstanceField
 
-%def op_iput_short_quick():
-%  op_iput_quick(reg="rINSTw", store="movw")
-
 %def op_iput_wide():
    jmp NterpPutWideInstanceField
 
-%def op_iput_wide_quick():
-    /* iput-wide-quick vA, vB, offset@CCCC */
-    movzbq    rINSTbl, %rcx                 # rcx<- BA
-    sarl      $$4, %ecx                     # ecx<- B
-    GET_VREG  %ecx, %rcx                    # vB (object we're operating on)
-    testl     %ecx, %ecx                    # is object null?
-    je        common_errNullObject
-    movzwq    2(rPC), %rax                  # rax<- field byte offset
-    leaq      (%rcx,%rax,1), %rcx           # ecx<- Address of 64-bit target
-    andb      $$0xf, rINSTbl                # rINST<- A
-    GET_WIDE_VREG %rax, rINSTq              # rax<- fp[A]/fp[A+1]
-    movq      %rax, (%rcx)                  # obj.field<- r0/r1
-    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
-
 %def op_sget(load="movl", wide="0"):
    jmp NterpGetIntStaticField
 
diff --git a/runtime/interpreter/mterp/x86_64ng/other.S b/runtime/interpreter/mterp/x86_64ng/other.S
index 7d82c3b..078fac5 100644
--- a/runtime/interpreter/mterp/x86_64ng/other.S
+++ b/runtime/interpreter/mterp/x86_64ng/other.S
@@ -239,12 +239,63 @@
 %def op_unused_43():
 %  unused()
 
+%def op_unused_73():
+%  unused()
+
 %def op_unused_79():
 %  unused()
 
 %def op_unused_7a():
 %  unused()
 
+%def op_unused_e3():
+%  unused()
+
+%def op_unused_e4():
+%  unused()
+
+%def op_unused_e5():
+%  unused()
+
+%def op_unused_e6():
+%  unused()
+
+%def op_unused_e7():
+%  unused()
+
+%def op_unused_e8():
+%  unused()
+
+%def op_unused_e9():
+%  unused()
+
+%def op_unused_ea():
+%  unused()
+
+%def op_unused_eb():
+%  unused()
+
+%def op_unused_ec():
+%  unused()
+
+%def op_unused_ed():
+%  unused()
+
+%def op_unused_ee():
+%  unused()
+
+%def op_unused_ef():
+%  unused()
+
+%def op_unused_f0():
+%  unused()
+
+%def op_unused_f1():
+%  unused()
+
+%def op_unused_f2():
+%  unused()
+
 %def op_unused_f3():
 %  unused()
 
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 5986982..73fffe8 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -24,7 +24,6 @@
 #include <initializer_list>
 #include <limits>
 #include <locale>
-#include <unordered_map>
 
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
@@ -32,6 +31,7 @@
 #include "art_method-inl.h"
 #include "base/casts.h"
 #include "base/enums.h"
+#include "base/hash_map.h"
 #include "base/macros.h"
 #include "base/quasi_atomic.h"
 #include "base/zip_archive.h"
@@ -48,7 +48,7 @@
 #include "mirror/array-inl.h"
 #include "mirror/class-alloc-inl.h"
 #include "mirror/executable-inl.h"
-#include "mirror/field-inl.h"
+#include "mirror/field.h"
 #include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-alloc-inl.h"
@@ -60,6 +60,7 @@
 #include "reflection.h"
 #include "thread-inl.h"
 #include "transaction.h"
+#include "unstarted_runtime_list.h"
 #include "well_known_classes.h"
 
 namespace art {
@@ -126,24 +127,17 @@
 }
 
 // Helper function to deal with class loading in an unstarted runtime.
-static void UnstartedRuntimeFindClass(Thread* self, Handle<mirror::String> className,
-                                      Handle<mirror::ClassLoader> class_loader, JValue* result,
-                                      const std::string& method_name, bool initialize_class,
-                                      bool abort_if_not_found)
+static void UnstartedRuntimeFindClass(Thread* self,
+                                      Handle<mirror::String> className,
+                                      Handle<mirror::ClassLoader> class_loader,
+                                      JValue* result,
+                                      bool initialize_class)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   CHECK(className != nullptr);
   std::string descriptor(DotToDescriptor(className->ToModifiedUtf8().c_str()));
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
 
   ObjPtr<mirror::Class> found = class_linker->FindClass(self, descriptor.c_str(), class_loader);
-  if (found == nullptr && abort_if_not_found) {
-    if (!self->IsExceptionPending()) {
-      AbortTransactionOrFail(self, "%s failed in un-started runtime for class: %s",
-                             method_name.c_str(),
-                             PrettyDescriptor(descriptor.c_str()).c_str());
-    }
-    return;
-  }
   if (found != nullptr && initialize_class) {
     StackHandleScope<1> hs(self);
     HandleWrapperObjPtr<mirror::Class> h_class = hs.NewHandleWrapper(&found);
@@ -163,9 +157,23 @@
 static void CheckExceptionGenerateClassNotFound(Thread* self)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   if (self->IsExceptionPending()) {
-    // If it is not the transaction abort exception, wrap it.
-    std::string type(mirror::Object::PrettyTypeOf(self->GetException()));
-    if (type != Transaction::kAbortExceptionDescriptor) {
+    Runtime* runtime = Runtime::Current();
+    DCHECK_EQ(runtime->IsTransactionAborted(),
+              self->GetException()->GetClass()->DescriptorEquals(
+                  Transaction::kAbortExceptionDescriptor))
+        << self->GetException()->GetClass()->PrettyDescriptor();
+    if (runtime->IsActiveTransaction()) {
+      // The boot class path at run time may contain additional dex files with
+      // the required class definition(s). We cannot throw a normal exception at
+      // compile time because a class initializer could catch it and successfully
+      // initialize a class differently than when executing at run time.
+      // If we're not aborting the transaction yet, abort now. b/183691501
+      if (!runtime->IsTransactionAborted()) {
+        AbortTransactionF(self, "ClassNotFoundException");
+      }
+    } else {
+      // If not in a transaction, it cannot be the transaction abort exception. Wrap it.
+      DCHECK(!runtime->IsTransactionAborted());
       self->ThrowNewWrappedException("Ljava/lang/ClassNotFoundException;",
                                      "ClassNotFoundException");
     }
@@ -205,8 +213,7 @@
                                                    ShadowFrame* shadow_frame,
                                                    JValue* result,
                                                    size_t arg_offset,
-                                                   bool long_form,
-                                                   const char* caller) {
+                                                   bool long_form) {
   ObjPtr<mirror::String> class_name = GetClassName(self, shadow_frame, arg_offset);
   if (class_name == nullptr) {
     return;
@@ -238,20 +245,18 @@
                             h_class_name,
                             ScopedNullHandle<mirror::ClassLoader>(),
                             result,
-                            caller,
-                            initialize_class,
-                            false);
+                            initialize_class);
   CheckExceptionGenerateClassNotFound(self);
 }
 
 void UnstartedRuntime::UnstartedClassForName(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
-  UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, false, "Class.forName");
+  UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, /*long_form=*/ false);
 }
 
 void UnstartedRuntime::UnstartedClassForNameLong(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
-  UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, true, "Class.forName");
+  UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, /*long_form=*/ true);
 }
 
 void UnstartedRuntime::UnstartedClassGetPrimitiveClass(
@@ -270,7 +275,7 @@
 
 void UnstartedRuntime::UnstartedClassClassForName(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
-  UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, true, "Class.classForName");
+  UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, /*long_form=*/ true);
 }
 
 void UnstartedRuntime::UnstartedClassNewInstance(
@@ -360,26 +365,7 @@
                            klass->PrettyDescriptor().c_str());
     return;
   }
-  Runtime* runtime = Runtime::Current();
-  PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
-  ObjPtr<mirror::Field> field;
-  if (runtime->IsActiveTransaction()) {
-    if (pointer_size == PointerSize::k64) {
-      field = mirror::Field::CreateFromArtField<PointerSize::k64, true>(
-          self, found, true);
-    } else {
-      field = mirror::Field::CreateFromArtField<PointerSize::k32, true>(
-          self, found, true);
-    }
-  } else {
-    if (pointer_size == PointerSize::k64) {
-      field = mirror::Field::CreateFromArtField<PointerSize::k64, false>(
-          self, found, true);
-    } else {
-      field = mirror::Field::CreateFromArtField<PointerSize::k32, false>(
-          self, found, true);
-    }
-  }
+  ObjPtr<mirror::Field> field = mirror::Field::CreateFromArtField(self, found, true);
   result->SetL(field);
 }
 
@@ -395,28 +381,13 @@
   ObjPtr<mirror::String> name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
   ObjPtr<mirror::ObjectArray<mirror::Class>> args =
       shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<mirror::Class>();
-  Runtime* runtime = Runtime::Current();
-  bool transaction = runtime->IsActiveTransaction();
-  PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
+  PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
   auto fn_hiddenapi_access_context = GetHiddenapiAccessContextFunction(shadow_frame);
-  ObjPtr<mirror::Method> method;
-  if (transaction) {
-    if (pointer_size == PointerSize::k64) {
-      method = mirror::Class::GetDeclaredMethodInternal<PointerSize::k64, true>(
-          self, klass, name, args, fn_hiddenapi_access_context);
-    } else {
-      method = mirror::Class::GetDeclaredMethodInternal<PointerSize::k32, true>(
-          self, klass, name, args, fn_hiddenapi_access_context);
-    }
-  } else {
-    if (pointer_size == PointerSize::k64) {
-      method = mirror::Class::GetDeclaredMethodInternal<PointerSize::k64, false>(
-          self, klass, name, args, fn_hiddenapi_access_context);
-    } else {
-      method = mirror::Class::GetDeclaredMethodInternal<PointerSize::k32, false>(
-          self, klass, name, args, fn_hiddenapi_access_context);
-    }
-  }
+  ObjPtr<mirror::Method> method = (pointer_size == PointerSize::k64)
+      ? mirror::Class::GetDeclaredMethodInternal<PointerSize::k64>(
+            self, klass, name, args, fn_hiddenapi_access_context)
+      : mirror::Class::GetDeclaredMethodInternal<PointerSize::k32>(
+            self, klass, name, args, fn_hiddenapi_access_context);
   if (method != nullptr && ShouldDenyAccessToMember(method->GetArtMethod(), shadow_frame)) {
     method = nullptr;
   }
@@ -433,27 +404,10 @@
   }
   ObjPtr<mirror::ObjectArray<mirror::Class>> args =
       shadow_frame->GetVRegReference(arg_offset + 1)->AsObjectArray<mirror::Class>();
-  Runtime* runtime = Runtime::Current();
-  bool transaction = runtime->IsActiveTransaction();
-  PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
-  ObjPtr<mirror::Constructor> constructor;
-  if (transaction) {
-    if (pointer_size == PointerSize::k64) {
-      constructor = mirror::Class::GetDeclaredConstructorInternal<PointerSize::k64,
-                                                                  true>(self, klass, args);
-    } else {
-      constructor = mirror::Class::GetDeclaredConstructorInternal<PointerSize::k32,
-                                                                  true>(self, klass, args);
-    }
-  } else {
-    if (pointer_size == PointerSize::k64) {
-      constructor = mirror::Class::GetDeclaredConstructorInternal<PointerSize::k64,
-                                                                  false>(self, klass, args);
-    } else {
-      constructor = mirror::Class::GetDeclaredConstructorInternal<PointerSize::k32,
-                                                                  false>(self, klass, args);
-    }
-  }
+  PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+  ObjPtr<mirror::Constructor> constructor = (pointer_size == PointerSize::k64)
+      ? mirror::Class::GetDeclaredConstructorInternal<PointerSize::k64>(self, klass, args)
+      : mirror::Class::GetDeclaredConstructorInternal<PointerSize::k32>(self, klass, args);
   if (constructor != nullptr &&
       ShouldDenyAccessToMember(constructor->GetArtMethod(), shadow_frame)) {
     constructor = nullptr;
@@ -738,7 +692,12 @@
                                        soa.AddLocalReference<jobject>(receiver.Get()));
     ScopedLocalRef<jobject> args_ref(self->GetJniEnv(),
                                      soa.AddLocalReference<jobject>(args.Get()));
-    InvokeMethod(soa, method_ref.get(), object_ref.get(), args_ref.get(), 2);
+    PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+    if (pointer_size == PointerSize::k64) {
+      InvokeMethod<PointerSize::k64>(soa, method_ref.get(), object_ref.get(), args_ref.get(), 2);
+    } else {
+      InvokeMethod<PointerSize::k32>(soa, method_ref.get(), object_ref.get(), args_ref.get(), 2);
+    }
   }
   if (self->IsExceptionPending()) {
     AbortTransactionOrFail(self, "Failed running constructor");
@@ -755,13 +714,27 @@
   StackHandleScope<2> hs(self);
   Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
   Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
-  UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result,
-                            "VMClassLoader.findLoadedClass", false, false);
+  UnstartedRuntimeFindClass(self,
+                            h_class_name,
+                            h_class_loader,
+                            result,
+                            /*initialize_class=*/ false);
   // This might have an error pending. But semantics are to just return null.
   if (self->IsExceptionPending()) {
-    // If it is an InternalError, keep it. See CheckExceptionGenerateClassNotFound.
-    std::string type(mirror::Object::PrettyTypeOf(self->GetException()));
-    if (type != "java.lang.InternalError") {
+    Runtime* runtime = Runtime::Current();
+    DCHECK_EQ(runtime->IsTransactionAborted(),
+              self->GetException()->GetClass()->DescriptorEquals(
+                  Transaction::kAbortExceptionDescriptor))
+        << self->GetException()->GetClass()->PrettyDescriptor();
+    if (runtime->IsActiveTransaction()) {
+      // If we're not aborting the transaction yet, abort now. b/183691501
+      // See CheckExceptionGenerateClassNotFound() for more detailed explanation.
+      if (!runtime->IsTransactionAborted()) {
+        AbortTransactionF(self, "ClassNotFoundException");
+      }
+    } else {
+      // If not in a transaction, it cannot be the transaction abort exception. Clear it.
+      DCHECK(!runtime->IsTransactionAborted());
       self->ClearException();
     }
   }
@@ -1416,7 +1389,7 @@
 // This allows statically initializing ConcurrentHashMap and SynchronousQueue.
 void UnstartedRuntime::UnstartedReferenceGetReferent(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
-  const ObjPtr<mirror::Reference> ref = down_cast<mirror::Reference*>(
+  const ObjPtr<mirror::Reference> ref = ObjPtr<mirror::Reference>::DownCast(
       shadow_frame->GetVRegReference(arg_offset));
   if (ref == nullptr) {
     AbortTransactionOrFail(self, "Reference.getReferent() with null object");
@@ -1427,6 +1400,22 @@
   result->SetL(referent);
 }
 
+void UnstartedRuntime::UnstartedReferenceRefersTo(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
+  // Use the naive implementation that may block and needlessly extend the lifetime
+  // of the referenced object.
+  const ObjPtr<mirror::Reference> ref = ObjPtr<mirror::Reference>::DownCast(
+      shadow_frame->GetVRegReference(arg_offset));
+  if (ref == nullptr) {
+    AbortTransactionOrFail(self, "Reference.refersTo() with null object");
+    return;
+  }
+  const ObjPtr<mirror::Object> referent =
+      Runtime::Current()->GetHeap()->GetReferenceProcessor()->GetReferent(self, ref);
+  const ObjPtr<mirror::Object> o = shadow_frame->GetVRegReference(arg_offset + 1);
+  result->SetZ(o == referent);
+}
+
 // This allows statically initializing ConcurrentHashMap and SynchronousQueue. We use a somewhat
 // conservative upper bound. We restrict the callers to SynchronousQueue and ConcurrentHashMap,
 // where we can predict the behavior (somewhat).
@@ -1695,8 +1684,17 @@
   ScopedLocalRef<jobject> java_args(env,
       java_args_obj == nullptr ? nullptr : env->AddLocalReference<jobject>(java_args_obj));
 
+  PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
   ScopedLocalRef<jobject> result_jobj(env,
-      InvokeMethod(soa, java_method.get(), java_receiver.get(), java_args.get()));
+      (pointer_size == PointerSize::k64)
+          ? InvokeMethod<PointerSize::k64>(soa,
+                                           java_method.get(),
+                                           java_receiver.get(),
+                                           java_args.get())
+          : InvokeMethod<PointerSize::k32>(soa,
+                                           java_method.get(),
+                                           java_receiver.get(),
+                                           java_args.get()));
 
   result->SetL(self->DecodeJObject(result_jobj.get()));
 
@@ -1885,17 +1883,8 @@
     Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
     uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
   ScopedObjectAccessUnchecked soa(self);
-  if (Runtime::Current()->IsActiveTransaction()) {
-    result->SetL(soa.Decode<mirror::Object>(self->CreateInternalStackTrace<true>(soa)));
-  } else {
-    result->SetL(soa.Decode<mirror::Object>(self->CreateInternalStackTrace<false>(soa)));
-  }
-}
-
-void UnstartedRuntime::UnstartedJNIByteOrderIsLittleEndian(
-    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
-    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
-  result->SetZ(JNI_TRUE);
+  ScopedLocalRef<jobject> stack_trace(self->GetJniEnv(), self->CreateInternalStackTrace(soa));
+  result->SetL(soa.Decode<mirror::Object>(stack_trace.get()));
 }
 
 void UnstartedRuntime::UnstartedJNIUnsafeCompareAndSwapInt(
@@ -2012,47 +2001,104 @@
                            uint32_t* args,
                            JValue* result);
 
-static bool tables_initialized_ = false;
-static std::unordered_map<std::string, InvokeHandler> invoke_handlers_;
-static std::unordered_map<std::string, JNIHandler> jni_handlers_;
+#define ONE_PLUS(ShortNameIgnored, DescriptorIgnored, NameIgnored, SignatureIgnored) 1 +
+static constexpr size_t kInvokeHandlersSize = UNSTARTED_RUNTIME_DIRECT_LIST(ONE_PLUS) 0;
+static constexpr size_t kJniHandlersSize = UNSTARTED_RUNTIME_JNI_LIST(ONE_PLUS) 0;
+#undef ONE_PLUS
 
-void UnstartedRuntime::InitializeInvokeHandlers() {
-#define UNSTARTED_DIRECT(ShortName, Sig) \
-  invoke_handlers_.insert(std::make_pair(Sig, & UnstartedRuntime::Unstarted ## ShortName));
-#include "unstarted_runtime_list.h"
-  UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
-#undef UNSTARTED_RUNTIME_DIRECT_LIST
-#undef UNSTARTED_RUNTIME_JNI_LIST
-#undef UNSTARTED_DIRECT
+// The actual value of `kMinLoadFactor` is irrelevant because the HashMap<>s below
+// are never resized, but we still need to pass a reasonable value to the constructor.
+static constexpr double kMinLoadFactor = 0.5;
+static constexpr double kMaxLoadFactor = 0.7;
+
+constexpr size_t BufferSize(size_t size) {
+  // Note: ceil() is not suitable for constexpr, so cast to size_t and adjust by 1 if needed.
+  const size_t estimate = static_cast<size_t>(size / kMaxLoadFactor);
+  return static_cast<size_t>(estimate * kMaxLoadFactor) == size ? estimate : estimate + 1u;
 }
 
-void UnstartedRuntime::InitializeJNIHandlers() {
-#define UNSTARTED_JNI(ShortName, Sig) \
-  jni_handlers_.insert(std::make_pair(Sig, & UnstartedRuntime::UnstartedJNI ## ShortName));
-#include "unstarted_runtime_list.h"
+static constexpr size_t kInvokeHandlersBufferSize = BufferSize(kInvokeHandlersSize);
+static_assert(
+    static_cast<size_t>(kInvokeHandlersBufferSize * kMaxLoadFactor) == kInvokeHandlersSize);
+static constexpr size_t kJniHandlersBufferSize = BufferSize(kJniHandlersSize);
+static_assert(static_cast<size_t>(kJniHandlersBufferSize * kMaxLoadFactor) == kJniHandlersSize);
+
+static bool tables_initialized_ = false;
+static std::pair<ArtMethod*, InvokeHandler> kInvokeHandlersBuffer[kInvokeHandlersBufferSize];
+static HashMap<ArtMethod*, InvokeHandler> invoke_handlers_(
+    kMinLoadFactor, kMaxLoadFactor, kInvokeHandlersBuffer, kInvokeHandlersBufferSize);
+static std::pair<ArtMethod*, JNIHandler> kJniHandlersBuffer[kJniHandlersBufferSize];
+static HashMap<ArtMethod*, JNIHandler> jni_handlers_(
+    kMinLoadFactor, kMaxLoadFactor, kJniHandlersBuffer, kJniHandlersBufferSize);
+
+static ArtMethod* FindMethod(Thread* self,
+                             ClassLinker* class_linker,
+                             const char* descriptor,
+                             std::string_view name,
+                             std::string_view signature) REQUIRES_SHARED(Locks::mutator_lock_) {
+  ObjPtr<mirror::Class> klass = class_linker->FindSystemClass(self, descriptor);
+  DCHECK(klass != nullptr) << descriptor;
+  ArtMethod* method = klass->FindClassMethod(name, signature, class_linker->GetImagePointerSize());
+  DCHECK(method != nullptr) << descriptor << "." << name << signature;
+  return method;
+}
+
+void UnstartedRuntime::InitializeInvokeHandlers(Thread* self) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+#define UNSTARTED_DIRECT(ShortName, Descriptor, Name, Signature) \
+  { \
+    ArtMethod* method = FindMethod(self, class_linker, Descriptor, Name, Signature); \
+    invoke_handlers_.insert(std::make_pair(method, & UnstartedRuntime::Unstarted ## ShortName)); \
+  }
+  UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
+#undef UNSTARTED_DIRECT
+  DCHECK_EQ(invoke_handlers_.NumBuckets(), kInvokeHandlersBufferSize);
+}
+
+void UnstartedRuntime::InitializeJNIHandlers(Thread* self) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+#define UNSTARTED_JNI(ShortName, Descriptor, Name, Signature) \
+  { \
+    ArtMethod* method = FindMethod(self, class_linker, Descriptor, Name, Signature); \
+    jni_handlers_.insert(std::make_pair(method, & UnstartedRuntime::UnstartedJNI ## ShortName)); \
+  }
   UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
-#undef UNSTARTED_RUNTIME_DIRECT_LIST
-#undef UNSTARTED_RUNTIME_JNI_LIST
 #undef UNSTARTED_JNI
+  DCHECK_EQ(jni_handlers_.NumBuckets(), kJniHandlersBufferSize);
 }
 
 void UnstartedRuntime::Initialize() {
   CHECK(!tables_initialized_);
 
-  InitializeInvokeHandlers();
-  InitializeJNIHandlers();
+  ScopedObjectAccess soa(Thread::Current());
+  InitializeInvokeHandlers(soa.Self());
+  InitializeJNIHandlers(soa.Self());
 
   tables_initialized_ = true;
 }
 
+void UnstartedRuntime::Reinitialize() {
+  CHECK(tables_initialized_);
+
+  // Note: HashSet::clear() abandons the pre-allocated storage which we need to keep.
+  while (!invoke_handlers_.empty()) {
+    invoke_handlers_.erase(invoke_handlers_.begin());
+  }
+  while (!jni_handlers_.empty()) {
+    jni_handlers_.erase(jni_handlers_.begin());
+  }
+
+  tables_initialized_ = false;
+  Initialize();
+}
+
 void UnstartedRuntime::Invoke(Thread* self, const CodeItemDataAccessor& accessor,
                               ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   // In a runtime that's not started we intercept certain methods to avoid complicated dependency
   // problems in core libraries.
   CHECK(tables_initialized_);
 
-  std::string name(ArtMethod::PrettyMethod(shadow_frame->GetMethod()));
-  const auto& iter = invoke_handlers_.find(name);
+  const auto& iter = invoke_handlers_.find(shadow_frame->GetMethod());
   if (iter != invoke_handlers_.end()) {
     // Clear out the result in case it's not zeroed out.
     result->SetL(nullptr);
@@ -2072,15 +2118,14 @@
 // Hand select a number of methods to be run in a not yet started runtime without using JNI.
 void UnstartedRuntime::Jni(Thread* self, ArtMethod* method, mirror::Object* receiver,
                            uint32_t* args, JValue* result) {
-  std::string name(ArtMethod::PrettyMethod(method));
-  const auto& iter = jni_handlers_.find(name);
+  const auto& iter = jni_handlers_.find(method);
   if (iter != jni_handlers_.end()) {
     // Clear out the result in case it's not zeroed out.
     result->SetL(nullptr);
     (*iter->second)(self, method, receiver, args, result);
   } else if (Runtime::Current()->IsActiveTransaction()) {
     AbortTransactionF(self, "Attempt to invoke native method in non-started runtime: %s",
-                      name.c_str());
+                      ArtMethod::PrettyMethod(method).c_str());
   } else {
     LOG(FATAL) << "Calling native method " << ArtMethod::PrettyMethod(method) << " in an unstarted "
         "non-transactional runtime";
diff --git a/runtime/interpreter/unstarted_runtime.h b/runtime/interpreter/unstarted_runtime.h
index b38c685..8b31f8f 100644
--- a/runtime/interpreter/unstarted_runtime.h
+++ b/runtime/interpreter/unstarted_runtime.h
@@ -21,6 +21,7 @@
 
 #include "dex/dex_file.h"
 #include "jvalue.h"
+#include "unstarted_runtime_list.h"
 
 namespace art {
 
@@ -48,6 +49,10 @@
  public:
   static void Initialize();
 
+  // For testing. When we destroy the Runtime and create a new one,
+  // we need to reinitialize maps with new `ArtMethod*` keys.
+  static void Reinitialize();
+
   static void Invoke(Thread* self,
                      const CodeItemDataAccessor& accessor,
                      ShadowFrame* shadow_frame,
@@ -64,41 +69,34 @@
 
  private:
   // Methods that intercept available libcore implementations.
-#define UNSTARTED_DIRECT(ShortName, SigIgnored)                 \
-  static void Unstarted ## ShortName(Thread* self,              \
-                                     ShadowFrame* shadow_frame, \
-                                     JValue* result,            \
-                                     size_t arg_offset)         \
+#define UNSTARTED_DIRECT(ShortName, DescriptorIgnored, NameIgnored, SignatureIgnored) \
+  static void Unstarted ## ShortName(Thread* self,                                    \
+                                     ShadowFrame* shadow_frame,                       \
+                                     JValue* result,                                  \
+                                     size_t arg_offset)                               \
       REQUIRES_SHARED(Locks::mutator_lock_);
-#include "unstarted_runtime_list.h"
   UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
-#undef UNSTARTED_RUNTIME_DIRECT_LIST
-#undef UNSTARTED_RUNTIME_JNI_LIST
 #undef UNSTARTED_DIRECT
 
   // Methods that are native.
-#define UNSTARTED_JNI(ShortName, SigIgnored)                       \
-  static void UnstartedJNI ## ShortName(Thread* self,              \
-                                        ArtMethod* method, \
-                                        mirror::Object* receiver,  \
-                                        uint32_t* args,            \
-                                        JValue* result)            \
+#define UNSTARTED_JNI(ShortName, DescriptorIgnored, NameIgnored, SignatureIgnored) \
+  static void UnstartedJNI ## ShortName(Thread* self,                              \
+                                        ArtMethod* method,                         \
+                                        mirror::Object* receiver,                  \
+                                        uint32_t* args,                            \
+                                        JValue* result)                            \
       REQUIRES_SHARED(Locks::mutator_lock_);
-#include "unstarted_runtime_list.h"
   UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
-#undef UNSTARTED_RUNTIME_DIRECT_LIST
-#undef UNSTARTED_RUNTIME_JNI_LIST
 #undef UNSTARTED_JNI
 
   static void UnstartedClassForNameCommon(Thread* self,
                                           ShadowFrame* shadow_frame,
                                           JValue* result,
                                           size_t arg_offset,
-                                          bool long_form,
-                                          const char* caller) REQUIRES_SHARED(Locks::mutator_lock_);
+                                          bool long_form) REQUIRES_SHARED(Locks::mutator_lock_);
 
-  static void InitializeInvokeHandlers();
-  static void InitializeJNIHandlers();
+  static void InitializeInvokeHandlers(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
+  static void InitializeJNIHandlers(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
 
   friend class UnstartedRuntimeTest;
 
diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h
index 3cc598a..95313e8 100644
--- a/runtime/interpreter/unstarted_runtime_list.h
+++ b/runtime/interpreter/unstarted_runtime_list.h
@@ -19,92 +19,90 @@
 
 // Methods that intercept available libcore implementations.
 #define UNSTARTED_RUNTIME_DIRECT_LIST(V)    \
-  V(CharacterToLowerCase, "int java.lang.Character.toLowerCase(int)") \
-  V(CharacterToUpperCase, "int java.lang.Character.toUpperCase(int)") \
-  V(ClassForName, "java.lang.Class java.lang.Class.forName(java.lang.String)") \
-  V(ClassForNameLong, "java.lang.Class java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader)") \
-  V(ClassGetPrimitiveClass, "java.lang.Class java.lang.Class.getPrimitiveClass(java.lang.String)") \
-  V(ClassClassForName, "java.lang.Class java.lang.Class.classForName(java.lang.String, boolean, java.lang.ClassLoader)") \
-  V(ClassNewInstance, "java.lang.Object java.lang.Class.newInstance()") \
-  V(ClassGetDeclaredField, "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") \
-  V(ClassGetDeclaredMethod, "java.lang.reflect.Method java.lang.Class.getDeclaredMethodInternal(java.lang.String, java.lang.Class[])") \
-  V(ClassGetDeclaredConstructor, "java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructorInternal(java.lang.Class[])") \
-  V(ClassGetDeclaringClass, "java.lang.Class java.lang.Class.getDeclaringClass()") \
-  V(ClassGetEnclosingClass, "java.lang.Class java.lang.Class.getEnclosingClass()") \
-  V(ClassGetInnerClassFlags, "int java.lang.Class.getInnerClassFlags(int)") \
-  V(ClassGetSignatureAnnotation, "java.lang.String[] java.lang.Class.getSignatureAnnotation()") \
-  V(ClassIsAnonymousClass, "boolean java.lang.Class.isAnonymousClass()") \
-  V(ClassLoaderGetResourceAsStream, "java.io.InputStream java.lang.ClassLoader.getResourceAsStream(java.lang.String)") \
-  V(ConstructorNewInstance0, "java.lang.Object java.lang.reflect.Constructor.newInstance0(java.lang.Object[])") \
-  V(VmClassLoaderFindLoadedClass, "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") \
-  V(SystemArraycopy, "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)") \
-  V(SystemArraycopyByte, "void java.lang.System.arraycopy(byte[], int, byte[], int, int)") \
-  V(SystemArraycopyChar, "void java.lang.System.arraycopy(char[], int, char[], int, int)") \
-  V(SystemArraycopyInt, "void java.lang.System.arraycopy(int[], int, int[], int, int)") \
-  V(SystemGetSecurityManager, "java.lang.SecurityManager java.lang.System.getSecurityManager()") \
-  V(SystemGetProperty, "java.lang.String java.lang.System.getProperty(java.lang.String)") \
-  V(SystemGetPropertyWithDefault, "java.lang.String java.lang.System.getProperty(java.lang.String, java.lang.String)") \
-  V(ThreadLocalGet, "java.lang.Object java.lang.ThreadLocal.get()") \
-  V(MathCeil, "double java.lang.Math.ceil(double)") \
-  V(MathFloor, "double java.lang.Math.floor(double)") \
-  V(MathSin, "double java.lang.Math.sin(double)") \
-  V(MathCos, "double java.lang.Math.cos(double)") \
-  V(MathPow, "double java.lang.Math.pow(double, double)") \
-  V(ObjectHashCode, "int java.lang.Object.hashCode()") \
-  V(DoubleDoubleToRawLongBits, "long java.lang.Double.doubleToRawLongBits(double)") \
-  V(MemoryPeekByte, "byte libcore.io.Memory.peekByte(long)") \
-  V(MemoryPeekShort, "short libcore.io.Memory.peekShortNative(long)") \
-  V(MemoryPeekInt, "int libcore.io.Memory.peekIntNative(long)") \
-  V(MemoryPeekLong, "long libcore.io.Memory.peekLongNative(long)") \
-  V(MemoryPeekByteArray, "void libcore.io.Memory.peekByteArray(long, byte[], int, int)") \
-  V(MethodInvoke, "java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[])") \
-  V(ReferenceGetReferent, "java.lang.Object java.lang.ref.Reference.getReferent()") \
-  V(RuntimeAvailableProcessors, "int java.lang.Runtime.availableProcessors()") \
-  V(StringGetCharsNoCheck, "void java.lang.String.getCharsNoCheck(int, int, char[], int)") \
-  V(StringCharAt, "char java.lang.String.charAt(int)") \
-  V(StringDoReplace, "java.lang.String java.lang.String.doReplace(char, char)") \
-  V(StringFactoryNewStringFromChars, "java.lang.String java.lang.StringFactory.newStringFromChars(int, int, char[])") \
-  V(StringFactoryNewStringFromString, "java.lang.String java.lang.StringFactory.newStringFromString(java.lang.String)") \
-  V(StringFastSubstring, "java.lang.String java.lang.String.fastSubstring(int, int)") \
-  V(StringToCharArray, "char[] java.lang.String.toCharArray()") \
-  V(ThreadCurrentThread, "java.lang.Thread java.lang.Thread.currentThread()") \
-  V(ThreadGetNativeState, "int java.lang.Thread.nativeGetStatus(boolean)") \
-  V(UnsafeCompareAndSwapLong, "boolean sun.misc.Unsafe.compareAndSwapLong(java.lang.Object, long, long, long)") \
-  V(UnsafeCompareAndSwapObject, "boolean sun.misc.Unsafe.compareAndSwapObject(java.lang.Object, long, java.lang.Object, java.lang.Object)") \
-  V(UnsafeGetObjectVolatile, "java.lang.Object sun.misc.Unsafe.getObjectVolatile(java.lang.Object, long)") \
-  V(UnsafePutObjectVolatile, "void sun.misc.Unsafe.putObjectVolatile(java.lang.Object, long, java.lang.Object)") \
-  V(UnsafePutOrderedObject, "void sun.misc.Unsafe.putOrderedObject(java.lang.Object, long, java.lang.Object)") \
-  V(IntegerParseInt, "int java.lang.Integer.parseInt(java.lang.String)") \
-  V(LongParseLong, "long java.lang.Long.parseLong(java.lang.String)") \
-  V(SystemIdentityHashCode, "int java.lang.System.identityHashCode(java.lang.Object)")
+  V(CharacterToLowerCase, "Ljava/lang/Character;", "toLowerCase", "(I)I") \
+  V(CharacterToUpperCase, "Ljava/lang/Character;", "toUpperCase", "(I)I") \
+  V(ClassForName, "Ljava/lang/Class;", "forName", "(Ljava/lang/String;)Ljava/lang/Class;") \
+  V(ClassForNameLong, "Ljava/lang/Class;", "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;") \
+  V(ClassGetPrimitiveClass, "Ljava/lang/Class;", "getPrimitiveClass", "(Ljava/lang/String;)Ljava/lang/Class;") \
+  V(ClassClassForName, "Ljava/lang/Class;", "classForName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;") \
+  V(ClassNewInstance, "Ljava/lang/Class;", "newInstance", "()Ljava/lang/Object;") \
+  V(ClassGetDeclaredField, "Ljava/lang/Class;", "getDeclaredField", "(Ljava/lang/String;)Ljava/lang/reflect/Field;") \
+  V(ClassGetDeclaredMethod, "Ljava/lang/Class;", "getDeclaredMethodInternal", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;") \
+  V(ClassGetDeclaredConstructor, "Ljava/lang/Class;", "getDeclaredConstructorInternal", "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;") \
+  V(ClassGetDeclaringClass, "Ljava/lang/Class;", "getDeclaringClass", "()Ljava/lang/Class;") \
+  V(ClassGetEnclosingClass, "Ljava/lang/Class;", "getEnclosingClass", "()Ljava/lang/Class;") \
+  V(ClassGetInnerClassFlags, "Ljava/lang/Class;", "getInnerClassFlags", "(I)I") \
+  V(ClassGetSignatureAnnotation, "Ljava/lang/Class;", "getSignatureAnnotation", "()[Ljava/lang/String;") \
+  V(ClassIsAnonymousClass, "Ljava/lang/Class;", "isAnonymousClass", "()Z") \
+  V(ClassLoaderGetResourceAsStream, "Ljava/lang/ClassLoader;", "getResourceAsStream", "(Ljava/lang/String;)Ljava/io/InputStream;") \
+  V(ConstructorNewInstance0, "Ljava/lang/reflect/Constructor;", "newInstance0", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VmClassLoaderFindLoadedClass, "Ljava/lang/VMClassLoader;", "findLoadedClass", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;") \
+  V(SystemArraycopy, "Ljava/lang/System;", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V") \
+  V(SystemArraycopyByte, "Ljava/lang/System;", "arraycopy", "([BI[BII)V") \
+  V(SystemArraycopyChar, "Ljava/lang/System;", "arraycopy", "([CI[CII)V") \
+  V(SystemArraycopyInt, "Ljava/lang/System;", "arraycopy", "([II[III)V") \
+  V(SystemGetSecurityManager, "Ljava/lang/System;", "getSecurityManager", "()Ljava/lang/SecurityManager;") \
+  V(SystemGetProperty, "Ljava/lang/System;", "getProperty", "(Ljava/lang/String;)Ljava/lang/String;") \
+  V(SystemGetPropertyWithDefault, "Ljava/lang/System;", "getProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;") \
+  V(ThreadLocalGet, "Ljava/lang/ThreadLocal;", "get", "()Ljava/lang/Object;") \
+  V(MathCeil, "Ljava/lang/Math;", "ceil", "(D)D") \
+  V(MathFloor, "Ljava/lang/Math;", "floor", "(D)D") \
+  V(MathSin, "Ljava/lang/Math;", "sin", "(D)D") \
+  V(MathCos, "Ljava/lang/Math;", "cos", "(D)D") \
+  V(MathPow, "Ljava/lang/Math;", "pow", "(DD)D") \
+  V(ObjectHashCode, "Ljava/lang/Object;", "hashCode", "()I") \
+  V(DoubleDoubleToRawLongBits, "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J") \
+  V(MemoryPeekByte, "Llibcore/io/Memory;", "peekByte", "(J)B") \
+  V(MemoryPeekShort, "Llibcore/io/Memory;", "peekShortNative", "(J)S") \
+  V(MemoryPeekInt, "Llibcore/io/Memory;", "peekIntNative", "(J)I") \
+  V(MemoryPeekLong, "Llibcore/io/Memory;", "peekLongNative", "(J)J") \
+  V(MemoryPeekByteArray, "Llibcore/io/Memory;", "peekByteArray", "(J[BII)V") \
+  V(MethodInvoke, "Ljava/lang/reflect/Method;", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(ReferenceGetReferent, "Ljava/lang/ref/Reference;", "getReferent", "()Ljava/lang/Object;") \
+  V(ReferenceRefersTo, "Ljava/lang/ref/Reference;", "refersTo", "(Ljava/lang/Object;)Z") \
+  V(RuntimeAvailableProcessors, "Ljava/lang/Runtime;", "availableProcessors", "()I") \
+  V(StringGetCharsNoCheck, "Ljava/lang/String;", "getCharsNoCheck", "(II[CI)V") \
+  V(StringCharAt, "Ljava/lang/String;", "charAt", "(I)C") \
+  V(StringDoReplace, "Ljava/lang/String;", "doReplace", "(CC)Ljava/lang/String;") \
+  V(StringFactoryNewStringFromChars, "Ljava/lang/StringFactory;", "newStringFromChars", "(II[C)Ljava/lang/String;") \
+  V(StringFactoryNewStringFromString, "Ljava/lang/StringFactory;", "newStringFromString", "(Ljava/lang/String;)Ljava/lang/String;") \
+  V(StringFastSubstring, "Ljava/lang/String;", "fastSubstring", "(II)Ljava/lang/String;") \
+  V(StringToCharArray, "Ljava/lang/String;", "toCharArray", "()[C") \
+  V(ThreadCurrentThread, "Ljava/lang/Thread;", "currentThread", "()Ljava/lang/Thread;") \
+  V(ThreadGetNativeState, "Ljava/lang/Thread;", "nativeGetStatus", "(Z)I") \
+  V(UnsafeCompareAndSwapLong, "Lsun/misc/Unsafe;", "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z") \
+  V(UnsafeCompareAndSwapObject, "Lsun/misc/Unsafe;", "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
+  V(UnsafeGetObjectVolatile, "Lsun/misc/Unsafe;", "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
+  V(UnsafePutObjectVolatile, "Lsun/misc/Unsafe;", "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+  V(UnsafePutOrderedObject, "Lsun/misc/Unsafe;", "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+  V(IntegerParseInt, "Ljava/lang/Integer;", "parseInt", "(Ljava/lang/String;)I") \
+  V(LongParseLong, "Ljava/lang/Long;", "parseLong", "(Ljava/lang/String;)J") \
+  V(SystemIdentityHashCode, "Ljava/lang/System;", "identityHashCode", "(Ljava/lang/Object;)I")
 
 // Methods that are native.
 #define UNSTARTED_RUNTIME_JNI_LIST(V)           \
-  V(VMRuntimeIs64Bit, "boolean dalvik.system.VMRuntime.is64Bit()") \
-  V(VMRuntimeNewUnpaddedArray, "java.lang.Object dalvik.system.VMRuntime.newUnpaddedArray(java.lang.Class, int)") \
-  V(VMStackGetCallingClassLoader, "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()") \
-  V(VMStackGetStackClass2, "java.lang.Class dalvik.system.VMStack.getStackClass2()") \
-  V(MathLog, "double java.lang.Math.log(double)") \
-  V(MathExp, "double java.lang.Math.exp(double)") \
-  V(AtomicLongVMSupportsCS8, "boolean java.util.concurrent.atomic.AtomicLong.VMSupportsCS8()") \
-  V(ClassGetNameNative, "java.lang.String java.lang.Class.getNameNative()") \
-  V(DoubleLongBitsToDouble, "double java.lang.Double.longBitsToDouble(long)") \
-  V(FloatFloatToRawIntBits, "int java.lang.Float.floatToRawIntBits(float)") \
-  V(FloatIntBitsToFloat, "float java.lang.Float.intBitsToFloat(int)") \
-  V(ObjectInternalClone, "java.lang.Object java.lang.Object.internalClone()") \
-  V(ObjectNotifyAll, "void java.lang.Object.notifyAll()") \
-  V(StringCompareTo, "int java.lang.String.compareTo(java.lang.String)") \
-  V(StringIntern, "java.lang.String java.lang.String.intern()") \
-  V(ArrayCreateMultiArray, "java.lang.Object java.lang.reflect.Array.createMultiArray(java.lang.Class, int[])") \
-  V(ArrayCreateObjectArray, "java.lang.Object java.lang.reflect.Array.createObjectArray(java.lang.Class, int)") \
-  V(ThrowableNativeFillInStackTrace, "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()") \
-  V(ByteOrderIsLittleEndian, "boolean java.nio.ByteOrder.isLittleEndian()") \
-  V(UnsafeCompareAndSwapInt, "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") \
-  V(UnsafeGetIntVolatile, "int sun.misc.Unsafe.getIntVolatile(java.lang.Object, long)") \
-  V(UnsafePutObject, "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") \
-  V(UnsafeGetArrayBaseOffsetForComponentType, "int sun.misc.Unsafe.getArrayBaseOffsetForComponentType(java.lang.Class)") \
-  V(UnsafeGetArrayIndexScaleForComponentType, "int sun.misc.Unsafe.getArrayIndexScaleForComponentType(java.lang.Class)")
+  V(VMRuntimeIs64Bit, "Ldalvik/system/VMRuntime;", "is64Bit", "()Z") \
+  V(VMRuntimeNewUnpaddedArray, "Ldalvik/system/VMRuntime;", "newUnpaddedArray", "(Ljava/lang/Class;I)Ljava/lang/Object;") \
+  V(VMStackGetCallingClassLoader, "Ldalvik/system/VMStack;", "getCallingClassLoader", "()Ljava/lang/ClassLoader;") \
+  V(VMStackGetStackClass2, "Ldalvik/system/VMStack;", "getStackClass2", "()Ljava/lang/Class;") \
+  V(MathLog, "Ljava/lang/Math;", "log", "(D)D") \
+  V(MathExp, "Ljava/lang/Math;", "exp", "(D)D") \
+  V(AtomicLongVMSupportsCS8, "Ljava/util/concurrent/atomic/AtomicLong;", "VMSupportsCS8", "()Z") \
+  V(ClassGetNameNative, "Ljava/lang/Class;", "getNameNative", "()Ljava/lang/String;") \
+  V(DoubleLongBitsToDouble, "Ljava/lang/Double;", "longBitsToDouble", "(J)D") \
+  V(FloatFloatToRawIntBits, "Ljava/lang/Float;", "floatToRawIntBits", "(F)I") \
+  V(FloatIntBitsToFloat, "Ljava/lang/Float;", "intBitsToFloat", "(I)F") \
+  V(ObjectInternalClone, "Ljava/lang/Object;", "internalClone", "()Ljava/lang/Object;") \
+  V(ObjectNotifyAll, "Ljava/lang/Object;", "notifyAll", "()V") \
+  V(StringCompareTo, "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I") \
+  V(StringIntern, "Ljava/lang/String;", "intern", "()Ljava/lang/String;") \
+  V(ArrayCreateMultiArray, "Ljava/lang/reflect/Array;", "createMultiArray", "(Ljava/lang/Class;[I)Ljava/lang/Object;") \
+  V(ArrayCreateObjectArray, "Ljava/lang/reflect/Array;", "createObjectArray", "(Ljava/lang/Class;I)Ljava/lang/Object;") \
+  V(ThrowableNativeFillInStackTrace, "Ljava/lang/Throwable;", "nativeFillInStackTrace", "()Ljava/lang/Object;") \
+  V(UnsafeCompareAndSwapInt, "Lsun/misc/Unsafe;", "compareAndSwapInt", "(Ljava/lang/Object;JII)Z") \
+  V(UnsafeGetIntVolatile, "Lsun/misc/Unsafe;", "getIntVolatile", "(Ljava/lang/Object;J)I") \
+  V(UnsafePutObject, "Lsun/misc/Unsafe;", "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+  V(UnsafeGetArrayBaseOffsetForComponentType, "Lsun/misc/Unsafe;", "getArrayBaseOffsetForComponentType", "(Ljava/lang/Class;)I") \
+  V(UnsafeGetArrayIndexScaleForComponentType, "Lsun/misc/Unsafe;", "getArrayIndexScaleForComponentType", "(Ljava/lang/Class;)I")
 
 #endif  // ART_RUNTIME_INTERPRETER_UNSTARTED_RUNTIME_LIST_H_
-// the guard in this file is just for cpplint
-#undef ART_RUNTIME_INTERPRETER_UNSTARTED_RUNTIME_LIST_H_
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 4429f63..ecee216 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -23,7 +23,7 @@
 #include "base/enums.h"
 #include "base/memory_tool.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_runtime_test.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_instruction.h"
@@ -42,6 +42,7 @@
 #include "shadow_frame-inl.h"
 #include "thread.h"
 #include "transaction.h"
+#include "unstarted_runtime_list.h"
 
 namespace art {
 namespace interpreter {
@@ -64,34 +65,28 @@
   // test friends.
 
   // Methods that intercept available libcore implementations.
-#define UNSTARTED_DIRECT(Name, SigIgnored)                 \
-  static void Unstarted ## Name(Thread* self,              \
-                                ShadowFrame* shadow_frame, \
-                                JValue* result,            \
-                                size_t arg_offset)         \
-      REQUIRES_SHARED(Locks::mutator_lock_) {        \
+#define UNSTARTED_DIRECT(Name, DescriptorIgnored, NameIgnored, SignatureIgnored)              \
+  static void Unstarted ## Name(Thread* self,                                                 \
+                                ShadowFrame* shadow_frame,                                    \
+                                JValue* result,                                               \
+                                size_t arg_offset)                                            \
+      REQUIRES_SHARED(Locks::mutator_lock_) {                                                 \
     interpreter::UnstartedRuntime::Unstarted ## Name(self, shadow_frame, result, arg_offset); \
   }
-#include "unstarted_runtime_list.h"
   UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
-#undef UNSTARTED_RUNTIME_DIRECT_LIST
-#undef UNSTARTED_RUNTIME_JNI_LIST
 #undef UNSTARTED_DIRECT
 
   // Methods that are native.
-#define UNSTARTED_JNI(Name, SigIgnored)                       \
-  static void UnstartedJNI ## Name(Thread* self,              \
-                                   ArtMethod* method,         \
-                                   mirror::Object* receiver,  \
-                                   uint32_t* args,            \
-                                   JValue* result)            \
-      REQUIRES_SHARED(Locks::mutator_lock_) {           \
+#define UNSTARTED_JNI(Name, DescriptorIgnored, NameIgnored, SignatureIgnored)                  \
+  static void UnstartedJNI ## Name(Thread* self,                                               \
+                                   ArtMethod* method,                                          \
+                                   mirror::Object* receiver,                                   \
+                                   uint32_t* args,                                             \
+                                   JValue* result)                                             \
+      REQUIRES_SHARED(Locks::mutator_lock_) {                                                  \
     interpreter::UnstartedRuntime::UnstartedJNI ## Name(self, method, receiver, args, result); \
   }
-#include "unstarted_runtime_list.h"
   UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
-#undef UNSTARTED_RUNTIME_DIRECT_LIST
-#undef UNSTARTED_RUNTIME_JNI_LIST
 #undef UNSTARTED_JNI
 
   UniqueDeoptShadowFramePtr CreateShadowFrame(uint32_t num_vregs,
@@ -221,7 +216,7 @@
   void PrepareForAborts() REQUIRES_SHARED(Locks::mutator_lock_) {
     ObjPtr<mirror::Object> result = Runtime::Current()->GetClassLinker()->FindClass(
         Thread::Current(),
-        Transaction::kAbortExceptionSignature,
+        Transaction::kAbortExceptionDescriptor,
         ScopedNullHandle<mirror::ClassLoader>());
     CHECK(result != nullptr);
   }
@@ -1322,19 +1317,13 @@
   Handle<mirror::String> input = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "abd"));
 
   // Find the constructor.
-  ArtMethod* throw_cons = throw_class->FindConstructor(
-      "(Ljava/lang/String;)V", class_linker->GetImagePointerSize());
+  PointerSize pointer_size = class_linker->GetImagePointerSize();
+  ArtMethod* throw_cons = throw_class->FindConstructor("(Ljava/lang/String;)V", pointer_size);
   ASSERT_TRUE(throw_cons != nullptr);
-  Handle<mirror::Constructor> cons;
-  if (class_linker->GetImagePointerSize() == PointerSize::k64) {
-     cons = hs.NewHandle(
-        mirror::Constructor::CreateFromArtMethod<PointerSize::k64, false>(self, throw_cons));
-    ASSERT_TRUE(cons != nullptr);
-  } else {
-    cons = hs.NewHandle(
-        mirror::Constructor::CreateFromArtMethod<PointerSize::k32, false>(self, throw_cons));
-    ASSERT_TRUE(cons != nullptr);
-  }
+  Handle<mirror::Constructor> cons = hs.NewHandle((pointer_size == PointerSize::k64)
+      ? mirror::Constructor::CreateFromArtMethod<PointerSize::k64>(self, throw_cons)
+      : mirror::Constructor::CreateFromArtMethod<PointerSize::k32>(self, throw_cons));
+  ASSERT_TRUE(cons != nullptr);
 
   Handle<mirror::ObjectArray<mirror::Object>> args = hs.NewHandle(
       mirror::ObjectArray<mirror::Object>::Alloc(
diff --git a/runtime/intrinsics_list.h b/runtime/intrinsics_list.h
index fc4734e..c0ef1c9 100644
--- a/runtime/intrinsics_list.h
+++ b/runtime/intrinsics_list.h
@@ -49,197 +49,201 @@
 
 // Intrinsics for methods with signature polymorphic behaviours.
 #define SIGNATURE_POLYMORPHIC_INTRINSICS_LIST(V) \
-  V(MethodHandleInvokeExact, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/MethodHandle;", "invokeExact", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(MethodHandleInvoke, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/MethodHandle;", "invoke", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleCompareAndExchange, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "compareAndExchange", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleCompareAndExchangeAcquire, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "compareAndExchangeAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleCompareAndExchangeRelease, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "compareAndExchangeRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleCompareAndSet, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "compareAndSet", "([Ljava/lang/Object;)Z") \
-  V(VarHandleGet, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "get", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAcquire, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndAdd, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndAdd", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndAddAcquire, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndAddAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndAddRelease, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndAddRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndBitwiseAnd, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseAnd", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndBitwiseAndAcquire, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseAndAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndBitwiseAndRelease, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseAndRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndBitwiseOr, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseOr", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndBitwiseOrAcquire, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseOrAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndBitwiseOrRelease, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseOrRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndBitwiseXor, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseXor", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndBitwiseXorAcquire, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseXorAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndBitwiseXorRelease, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseXorRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndSet, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndSet", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndSetAcquire, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndSetAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetAndSetRelease, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndSetRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetOpaque, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getOpaque", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleGetVolatile, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getVolatile", "([Ljava/lang/Object;)Ljava/lang/Object;") \
-  V(VarHandleSet, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "set", "([Ljava/lang/Object;)V") \
-  V(VarHandleSetOpaque, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "setOpaque", "([Ljava/lang/Object;)V") \
-  V(VarHandleSetRelease, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "setRelease", "([Ljava/lang/Object;)V") \
-  V(VarHandleSetVolatile, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "setVolatile", "([Ljava/lang/Object;)V") \
-  V(VarHandleWeakCompareAndSet, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSet", "([Ljava/lang/Object;)Z") \
-  V(VarHandleWeakCompareAndSetAcquire, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSetAcquire", "([Ljava/lang/Object;)Z") \
-  V(VarHandleWeakCompareAndSetPlain, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSetPlain", "([Ljava/lang/Object;)Z") \
-  V(VarHandleWeakCompareAndSetRelease, kPolymorphic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSetRelease", "([Ljava/lang/Object;)Z")
+  V(MethodHandleInvokeExact, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/MethodHandle;", "invokeExact", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(MethodHandleInvoke, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/MethodHandle;", "invoke", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleCompareAndExchange, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "compareAndExchange", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleCompareAndExchangeAcquire, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "compareAndExchangeAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleCompareAndExchangeRelease, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "compareAndExchangeRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleCompareAndSet, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "compareAndSet", "([Ljava/lang/Object;)Z") \
+  V(VarHandleGet, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "get", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAcquire, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndAdd, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndAdd", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndAddAcquire, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndAddAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndAddRelease, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndAddRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndBitwiseAnd, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseAnd", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndBitwiseAndAcquire, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseAndAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndBitwiseAndRelease, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseAndRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndBitwiseOr, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseOr", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndBitwiseOrAcquire, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseOrAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndBitwiseOrRelease, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseOrRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndBitwiseXor, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseXor", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndBitwiseXorAcquire, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseXorAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndBitwiseXorRelease, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndBitwiseXorRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndSet, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndSet", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndSetAcquire, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndSetAcquire", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetAndSetRelease, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getAndSetRelease", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetOpaque, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getOpaque", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleGetVolatile, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "getVolatile", "([Ljava/lang/Object;)Ljava/lang/Object;") \
+  V(VarHandleSet, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "set", "([Ljava/lang/Object;)V") \
+  V(VarHandleSetOpaque, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "setOpaque", "([Ljava/lang/Object;)V") \
+  V(VarHandleSetRelease, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "setRelease", "([Ljava/lang/Object;)V") \
+  V(VarHandleSetVolatile, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "setVolatile", "([Ljava/lang/Object;)V") \
+  V(VarHandleWeakCompareAndSet, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSet", "([Ljava/lang/Object;)Z") \
+  V(VarHandleWeakCompareAndSetAcquire, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSetAcquire", "([Ljava/lang/Object;)Z") \
+  V(VarHandleWeakCompareAndSetPlain, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSetPlain", "([Ljava/lang/Object;)Z") \
+  V(VarHandleWeakCompareAndSetRelease, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSetRelease", "([Ljava/lang/Object;)Z")
 
 // The complete list of intrinsics.
 #define INTRINSICS_LIST(V) \
-  V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J") \
-  V(DoubleDoubleToLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToLongBits", "(D)J") \
-  V(DoubleIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isInfinite", "(D)Z") \
-  V(DoubleIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isNaN", "(D)Z") \
-  V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "longBitsToDouble", "(J)D") \
-  V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToRawIntBits", "(F)I") \
-  V(FloatFloatToIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToIntBits", "(F)I") \
-  V(FloatIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isInfinite", "(F)Z") \
-  V(FloatIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isNaN", "(F)Z") \
-  V(FloatIntBitsToFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "intBitsToFloat", "(I)F") \
-  V(IntegerReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverse", "(I)I") \
-  V(IntegerReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverseBytes", "(I)I") \
-  V(IntegerBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "bitCount", "(I)I") \
-  V(IntegerCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "compare", "(II)I") \
-  V(IntegerHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "highestOneBit", "(I)I") \
-  V(IntegerLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "lowestOneBit", "(I)I") \
-  V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfLeadingZeros", "(I)I") \
-  V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfTrailingZeros", "(I)I") \
-  V(IntegerRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateRight", "(II)I") \
-  V(IntegerRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateLeft", "(II)I") \
-  V(IntegerSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "signum", "(I)I") \
-  V(LongReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverse", "(J)J") \
-  V(LongReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverseBytes", "(J)J") \
-  V(LongBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "bitCount", "(J)I") \
-  V(LongCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "compare", "(JJ)I") \
-  V(LongHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "highestOneBit", "(J)J") \
-  V(LongLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "lowestOneBit", "(J)J") \
-  V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfLeadingZeros", "(J)I") \
-  V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfTrailingZeros", "(J)I") \
-  V(LongRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateRight", "(JI)J") \
-  V(LongRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateLeft", "(JI)J") \
-  V(LongSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "signum", "(J)I") \
-  V(ShortReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Short;", "reverseBytes", "(S)S") \
-  V(MathAbsDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(D)D") \
-  V(MathAbsFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(F)F") \
-  V(MathAbsLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(J)J") \
-  V(MathAbsInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(I)I") \
-  V(MathMinDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(DD)D") \
-  V(MathMinFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(FF)F") \
-  V(MathMinLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(JJ)J") \
-  V(MathMinIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(II)I") \
-  V(MathMaxDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(DD)D") \
-  V(MathMaxFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(FF)F") \
-  V(MathMaxLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(JJ)J") \
-  V(MathMaxIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(II)I") \
-  V(MathCos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cos", "(D)D") \
-  V(MathSin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sin", "(D)D") \
-  V(MathAcos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "acos", "(D)D") \
-  V(MathAsin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "asin", "(D)D") \
-  V(MathAtan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "atan", "(D)D") \
-  V(MathAtan2, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "atan2", "(DD)D") \
-  V(MathPow, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "pow", "(DD)D") \
-  V(MathCbrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cbrt", "(D)D") \
-  V(MathCosh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cosh", "(D)D") \
-  V(MathExp, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "exp", "(D)D") \
-  V(MathExpm1, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "expm1", "(D)D") \
-  V(MathHypot, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "hypot", "(DD)D") \
-  V(MathLog, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "log", "(D)D") \
-  V(MathLog10, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "log10", "(D)D") \
-  V(MathNextAfter, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "nextAfter", "(DD)D") \
-  V(MathSinh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sinh", "(D)D") \
-  V(MathTan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "tan", "(D)D") \
-  V(MathTanh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "tanh", "(D)D") \
-  V(MathSqrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sqrt", "(D)D") \
-  V(MathCeil, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "ceil", "(D)D") \
-  V(MathFloor, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "floor", "(D)D") \
-  V(MathRint, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "rint", "(D)D") \
-  V(MathRoundDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "round", "(D)J") \
-  V(MathRoundFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "round", "(F)I") \
-  V(SystemArrayCopyChar, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/System;", "arraycopy", "([CI[CII)V") \
-  V(SystemArrayCopy, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/System;", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V") \
-  V(ThreadCurrentThread, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Thread;", "currentThread", "()Ljava/lang/Thread;") \
-  V(MemoryPeekByte, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekByte", "(J)B") \
-  V(MemoryPeekIntNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekIntNative", "(J)I") \
-  V(MemoryPeekLongNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekLongNative", "(J)J") \
-  V(MemoryPeekShortNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekShortNative", "(J)S") \
-  V(MemoryPokeByte, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeByte", "(JB)V") \
-  V(MemoryPokeIntNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeIntNative", "(JI)V") \
-  V(MemoryPokeLongNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeLongNative", "(JJ)V") \
-  V(MemoryPokeShortNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeShortNative", "(JS)V") \
-  V(FP16Ceil, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "ceil", "(S)S") \
-  V(FP16Floor, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "floor", "(S)S") \
-  V(FP16Rint, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "rint", "(S)S") \
-  V(FP16ToFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "toFloat", "(S)F") \
-  V(FP16ToHalf, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "toHalf", "(F)S") \
-  V(FP16Greater, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "greater", "(SS)Z") \
-  V(FP16GreaterEquals, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "greaterEquals", "(SS)Z") \
-  V(FP16Less, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "less", "(SS)Z") \
-  V(FP16LessEquals, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "lessEquals", "(SS)Z") \
-  V(StringCharAt, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "charAt", "(I)C") \
-  V(StringCompareTo, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I") \
-  V(StringEquals, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z") \
-  V(StringGetCharsNoCheck, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "getCharsNoCheck", "(II[CI)V") \
-  V(StringIndexOf, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "indexOf", "(I)I") \
-  V(StringIndexOfAfter, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "indexOf", "(II)I") \
-  V(StringStringIndexOf, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(Ljava/lang/String;)I") \
-  V(StringStringIndexOfAfter, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(Ljava/lang/String;I)I") \
-  V(StringIsEmpty, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "isEmpty", "()Z") \
-  V(StringLength, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "length", "()I") \
-  V(StringNewStringFromBytes, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromBytes", "([BIII)Ljava/lang/String;") \
-  V(StringNewStringFromChars, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromChars", "(II[C)Ljava/lang/String;") \
-  V(StringNewStringFromString, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromString", "(Ljava/lang/String;)Ljava/lang/String;") \
-  V(StringBufferAppend, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuffer;", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;") \
-  V(StringBufferLength, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kNoThrow, "Ljava/lang/StringBuffer;", "length", "()I") \
-  V(StringBufferToString, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuffer;", "toString", "()Ljava/lang/String;") \
-  V(StringBuilderAppendObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(Ljava/lang/Object;)Ljava/lang/StringBuilder;") \
-  V(StringBuilderAppendString, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;") \
-  V(StringBuilderAppendCharSequence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(Ljava/lang/CharSequence;)Ljava/lang/StringBuilder;") \
-  V(StringBuilderAppendCharArray, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "([C)Ljava/lang/StringBuilder;") \
-  V(StringBuilderAppendBoolean, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(Z)Ljava/lang/StringBuilder;") \
-  V(StringBuilderAppendChar, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(C)Ljava/lang/StringBuilder;") \
-  V(StringBuilderAppendInt, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(I)Ljava/lang/StringBuilder;") \
-  V(StringBuilderAppendLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(J)Ljava/lang/StringBuilder;") \
-  V(StringBuilderAppendFloat, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(F)Ljava/lang/StringBuilder;") \
-  V(StringBuilderAppendDouble, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(D)Ljava/lang/StringBuilder;") \
-  V(StringBuilderLength, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/StringBuilder;", "length", "()I") \
-  V(StringBuilderToString, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "toString", "()Ljava/lang/String;") \
-  V(UnsafeCASInt, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapInt", "(Ljava/lang/Object;JII)Z") \
-  V(UnsafeCASLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z") \
-  V(UnsafeCASObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
-  V(UnsafeGet, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getInt", "(Ljava/lang/Object;J)I") \
-  V(UnsafeGetVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getIntVolatile", "(Ljava/lang/Object;J)I") \
-  V(UnsafeGetObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
-  V(UnsafeGetObjectVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
-  V(UnsafeGetLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getLong", "(Ljava/lang/Object;J)J") \
-  V(UnsafeGetLongVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getLongVolatile", "(Ljava/lang/Object;J)J") \
-  V(UnsafePut, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putInt", "(Ljava/lang/Object;JI)V") \
-  V(UnsafePutOrdered, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedInt", "(Ljava/lang/Object;JI)V") \
-  V(UnsafePutVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putIntVolatile", "(Ljava/lang/Object;JI)V") \
-  V(UnsafePutObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
-  V(UnsafePutObjectOrdered, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
-  V(UnsafePutObjectVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
-  V(UnsafePutLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putLong", "(Ljava/lang/Object;JJ)V") \
-  V(UnsafePutLongOrdered, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedLong", "(Ljava/lang/Object;JJ)V") \
-  V(UnsafePutLongVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putLongVolatile", "(Ljava/lang/Object;JJ)V") \
-  V(UnsafeGetAndAddInt, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndAddInt", "(Ljava/lang/Object;JI)I") \
-  V(UnsafeGetAndAddLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndAddLong", "(Ljava/lang/Object;JJ)J") \
-  V(UnsafeGetAndSetInt, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetInt", "(Ljava/lang/Object;JI)I") \
-  V(UnsafeGetAndSetLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetLong", "(Ljava/lang/Object;JJ)J") \
-  V(UnsafeGetAndSetObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetObject", "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;") \
-  V(UnsafeLoadFence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "loadFence", "()V") \
-  V(UnsafeStoreFence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "storeFence", "()V") \
-  V(UnsafeFullFence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "fullFence", "()V") \
-  V(ReferenceGetReferent, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/ref/Reference;", "getReferent", "()Ljava/lang/Object;") \
-  V(IntegerValueOf, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "valueOf", "(I)Ljava/lang/Integer;") \
-  V(ThreadInterrupted, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kNoThrow, "Ljava/lang/Thread;", "interrupted", "()Z") \
-  V(VarHandleFullFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "fullFence", "()V") \
-  V(VarHandleAcquireFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "acquireFence", "()V") \
-  V(VarHandleReleaseFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "releaseFence", "()V") \
-  V(VarHandleLoadLoadFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "loadLoadFence", "()V") \
-  V(VarHandleStoreStoreFence, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "storeStoreFence", "()V") \
-  V(ReachabilityFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/ref/Reference;", "reachabilityFence", "(Ljava/lang/Object;)V") \
-  V(CRC32Update, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/util/zip/CRC32;", "update", "(II)I") \
-  V(CRC32UpdateBytes, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/util/zip/CRC32;", "updateBytes", "(I[BII)I") \
-  V(CRC32UpdateByteBuffer, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/util/zip/CRC32;", "updateByteBuffer", "(IJII)I") \
+  V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J") \
+  V(DoubleDoubleToLongBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToLongBits", "(D)J") \
+  V(DoubleIsInfinite, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isInfinite", "(D)Z") \
+  V(DoubleIsNaN, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isNaN", "(D)Z") \
+  V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "longBitsToDouble", "(J)D") \
+  V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToRawIntBits", "(F)I") \
+  V(FloatFloatToIntBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToIntBits", "(F)I") \
+  V(FloatIsInfinite, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isInfinite", "(F)Z") \
+  V(FloatIsNaN, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isNaN", "(F)Z") \
+  V(FloatIntBitsToFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "intBitsToFloat", "(I)F") \
+  V(IntegerReverse, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverse", "(I)I") \
+  V(IntegerReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverseBytes", "(I)I") \
+  V(IntegerBitCount, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "bitCount", "(I)I") \
+  V(IntegerCompare, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "compare", "(II)I") \
+  V(IntegerDivideUnsigned, kStatic, kNeedsEnvironment, kNoSideEffects, kCanThrow, "Ljava/lang/Integer;", "divideUnsigned", "(II)I") \
+  V(IntegerHighestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "highestOneBit", "(I)I") \
+  V(IntegerLowestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "lowestOneBit", "(I)I") \
+  V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfLeadingZeros", "(I)I") \
+  V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfTrailingZeros", "(I)I") \
+  V(IntegerRotateRight, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateRight", "(II)I") \
+  V(IntegerRotateLeft, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateLeft", "(II)I") \
+  V(IntegerSignum, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "signum", "(I)I") \
+  V(LongReverse, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverse", "(J)J") \
+  V(LongReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverseBytes", "(J)J") \
+  V(LongBitCount, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "bitCount", "(J)I") \
+  V(LongCompare, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "compare", "(JJ)I") \
+  V(LongDivideUnsigned, kStatic, kNeedsEnvironment, kNoSideEffects, kCanThrow, "Ljava/lang/Long;", "divideUnsigned", "(JJ)J") \
+  V(LongHighestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "highestOneBit", "(J)J") \
+  V(LongLowestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "lowestOneBit", "(J)J") \
+  V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfLeadingZeros", "(J)I") \
+  V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfTrailingZeros", "(J)I") \
+  V(LongRotateRight, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateRight", "(JI)J") \
+  V(LongRotateLeft, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateLeft", "(JI)J") \
+  V(LongSignum, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "signum", "(J)I") \
+  V(ShortReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Short;", "reverseBytes", "(S)S") \
+  V(MathAbsDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(D)D") \
+  V(MathAbsFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(F)F") \
+  V(MathAbsLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(J)J") \
+  V(MathAbsInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(I)I") \
+  V(MathMinDoubleDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(DD)D") \
+  V(MathMinFloatFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(FF)F") \
+  V(MathMinLongLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(JJ)J") \
+  V(MathMinIntInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(II)I") \
+  V(MathMaxDoubleDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(DD)D") \
+  V(MathMaxFloatFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(FF)F") \
+  V(MathMaxLongLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(JJ)J") \
+  V(MathMaxIntInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(II)I") \
+  V(MathCos, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cos", "(D)D") \
+  V(MathSin, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sin", "(D)D") \
+  V(MathAcos, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "acos", "(D)D") \
+  V(MathAsin, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "asin", "(D)D") \
+  V(MathAtan, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "atan", "(D)D") \
+  V(MathAtan2, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "atan2", "(DD)D") \
+  V(MathPow, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "pow", "(DD)D") \
+  V(MathCbrt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cbrt", "(D)D") \
+  V(MathCosh, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cosh", "(D)D") \
+  V(MathExp, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "exp", "(D)D") \
+  V(MathExpm1, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "expm1", "(D)D") \
+  V(MathHypot, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "hypot", "(DD)D") \
+  V(MathLog, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "log", "(D)D") \
+  V(MathLog10, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "log10", "(D)D") \
+  V(MathNextAfter, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "nextAfter", "(DD)D") \
+  V(MathSinh, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sinh", "(D)D") \
+  V(MathTan, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "tan", "(D)D") \
+  V(MathTanh, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "tanh", "(D)D") \
+  V(MathSqrt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sqrt", "(D)D") \
+  V(MathCeil, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "ceil", "(D)D") \
+  V(MathFloor, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "floor", "(D)D") \
+  V(MathRint, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "rint", "(D)D") \
+  V(MathRoundDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "round", "(D)J") \
+  V(MathRoundFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "round", "(F)I") \
+  V(MathMultiplyHigh, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "multiplyHigh", "(JJ)J") \
+  V(SystemArrayCopyChar, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/System;", "arraycopy", "([CI[CII)V") \
+  V(SystemArrayCopy, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/System;", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V") \
+  V(ThreadCurrentThread, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Thread;", "currentThread", "()Ljava/lang/Thread;") \
+  V(MemoryPeekByte, kStatic, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekByte", "(J)B") \
+  V(MemoryPeekIntNative, kStatic, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekIntNative", "(J)I") \
+  V(MemoryPeekLongNative, kStatic, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekLongNative", "(J)J") \
+  V(MemoryPeekShortNative, kStatic, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekShortNative", "(J)S") \
+  V(MemoryPokeByte, kStatic, kNeedsEnvironment, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeByte", "(JB)V") \
+  V(MemoryPokeIntNative, kStatic, kNeedsEnvironment, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeIntNative", "(JI)V") \
+  V(MemoryPokeLongNative, kStatic, kNeedsEnvironment, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeLongNative", "(JJ)V") \
+  V(MemoryPokeShortNative, kStatic, kNeedsEnvironment, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeShortNative", "(JS)V") \
+  V(FP16Ceil, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "ceil", "(S)S") \
+  V(FP16Floor, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "floor", "(S)S") \
+  V(FP16Rint, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "rint", "(S)S") \
+  V(FP16ToFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "toFloat", "(S)F") \
+  V(FP16ToHalf, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "toHalf", "(F)S") \
+  V(FP16Greater, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "greater", "(SS)Z") \
+  V(FP16GreaterEquals, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "greaterEquals", "(SS)Z") \
+  V(FP16Less, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "less", "(SS)Z") \
+  V(FP16LessEquals, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "lessEquals", "(SS)Z") \
+  V(StringCharAt, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "charAt", "(I)C") \
+  V(StringCompareTo, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I") \
+  V(StringEquals, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z") \
+  V(StringGetCharsNoCheck, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "getCharsNoCheck", "(II[CI)V") \
+  V(StringIndexOf, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "indexOf", "(I)I") \
+  V(StringIndexOfAfter, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "indexOf", "(II)I") \
+  V(StringStringIndexOf, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(Ljava/lang/String;)I") \
+  V(StringStringIndexOfAfter, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(Ljava/lang/String;I)I") \
+  V(StringIsEmpty, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "isEmpty", "()Z") \
+  V(StringLength, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "length", "()I") \
+  V(StringNewStringFromBytes, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromBytes", "([BIII)Ljava/lang/String;") \
+  V(StringNewStringFromChars, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromChars", "(II[C)Ljava/lang/String;") \
+  V(StringNewStringFromString, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromString", "(Ljava/lang/String;)Ljava/lang/String;") \
+  V(StringBufferAppend, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuffer;", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;") \
+  V(StringBufferLength, kVirtual, kNeedsEnvironment, kAllSideEffects, kNoThrow, "Ljava/lang/StringBuffer;", "length", "()I") \
+  V(StringBufferToString, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuffer;", "toString", "()Ljava/lang/String;") \
+  V(StringBuilderAppendObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(Ljava/lang/Object;)Ljava/lang/StringBuilder;") \
+  V(StringBuilderAppendString, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;") \
+  V(StringBuilderAppendCharSequence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(Ljava/lang/CharSequence;)Ljava/lang/StringBuilder;") \
+  V(StringBuilderAppendCharArray, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "([C)Ljava/lang/StringBuilder;") \
+  V(StringBuilderAppendBoolean, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(Z)Ljava/lang/StringBuilder;") \
+  V(StringBuilderAppendChar, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(C)Ljava/lang/StringBuilder;") \
+  V(StringBuilderAppendInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(I)Ljava/lang/StringBuilder;") \
+  V(StringBuilderAppendLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(J)Ljava/lang/StringBuilder;") \
+  V(StringBuilderAppendFloat, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(F)Ljava/lang/StringBuilder;") \
+  V(StringBuilderAppendDouble, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "append", "(D)Ljava/lang/StringBuilder;") \
+  V(StringBuilderLength, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/StringBuilder;", "length", "()I") \
+  V(StringBuilderToString, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringBuilder;", "toString", "()Ljava/lang/String;") \
+  V(UnsafeCASInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapInt", "(Ljava/lang/Object;JII)Z") \
+  V(UnsafeCASLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z") \
+  V(UnsafeCASObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
+  V(UnsafeGet, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getInt", "(Ljava/lang/Object;J)I") \
+  V(UnsafeGetVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getIntVolatile", "(Ljava/lang/Object;J)I") \
+  V(UnsafeGetObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
+  V(UnsafeGetObjectVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
+  V(UnsafeGetLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getLong", "(Ljava/lang/Object;J)J") \
+  V(UnsafeGetLongVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getLongVolatile", "(Ljava/lang/Object;J)J") \
+  V(UnsafePut, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putInt", "(Ljava/lang/Object;JI)V") \
+  V(UnsafePutOrdered, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedInt", "(Ljava/lang/Object;JI)V") \
+  V(UnsafePutVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putIntVolatile", "(Ljava/lang/Object;JI)V") \
+  V(UnsafePutObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+  V(UnsafePutObjectOrdered, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+  V(UnsafePutObjectVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+  V(UnsafePutLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putLong", "(Ljava/lang/Object;JJ)V") \
+  V(UnsafePutLongOrdered, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedLong", "(Ljava/lang/Object;JJ)V") \
+  V(UnsafePutLongVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putLongVolatile", "(Ljava/lang/Object;JJ)V") \
+  V(UnsafeGetAndAddInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndAddInt", "(Ljava/lang/Object;JI)I") \
+  V(UnsafeGetAndAddLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndAddLong", "(Ljava/lang/Object;JJ)J") \
+  V(UnsafeGetAndSetInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetInt", "(Ljava/lang/Object;JI)I") \
+  V(UnsafeGetAndSetLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetLong", "(Ljava/lang/Object;JJ)J") \
+  V(UnsafeGetAndSetObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetObject", "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;") \
+  V(UnsafeLoadFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "loadFence", "()V") \
+  V(UnsafeStoreFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "storeFence", "()V") \
+  V(UnsafeFullFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "fullFence", "()V") \
+  V(ReferenceGetReferent, kDirect, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/ref/Reference;", "getReferent", "()Ljava/lang/Object;") \
+  V(ReferenceRefersTo, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/ref/Reference;", "refersTo", "(Ljava/lang/Object;)Z") \
+  V(IntegerValueOf, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "valueOf", "(I)Ljava/lang/Integer;") \
+  V(ThreadInterrupted, kStatic, kNeedsEnvironment, kAllSideEffects, kNoThrow, "Ljava/lang/Thread;", "interrupted", "()Z") \
+  V(VarHandleFullFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "fullFence", "()V") \
+  V(VarHandleAcquireFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "acquireFence", "()V") \
+  V(VarHandleReleaseFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "releaseFence", "()V") \
+  V(VarHandleLoadLoadFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "loadLoadFence", "()V") \
+  V(VarHandleStoreStoreFence, kStatic, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "storeStoreFence", "()V") \
+  V(ReachabilityFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/ref/Reference;", "reachabilityFence", "(Ljava/lang/Object;)V") \
+  V(CRC32Update, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/util/zip/CRC32;", "update", "(II)I") \
+  V(CRC32UpdateBytes, kStatic, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/util/zip/CRC32;", "updateBytes", "(I[BII)I") \
+  V(CRC32UpdateByteBuffer, kStatic, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/util/zip/CRC32;", "updateByteBuffer", "(IJII)I") \
   SIGNATURE_POLYMORPHIC_INTRINSICS_LIST(V)
 
 #endif  // ART_RUNTIME_INTRINSICS_LIST_H_
diff --git a/runtime/java_frame_root_info.h b/runtime/java_frame_root_info.h
index c21eee1..c2b4493 100644
--- a/runtime/java_frame_root_info.h
+++ b/runtime/java_frame_root_info.h
@@ -41,6 +41,8 @@
   static constexpr size_t kMethodDeclaringClass = -3;
   // The root is from the argument to a Proxy invoke.
   static constexpr size_t kProxyReferenceArgument = -4;
+  // The root is from the argument to a native invoke.
+  static constexpr size_t kNativeReferenceArgument = -5;
   // The maximum precise vreg number
   static constexpr size_t kMaxVReg = std::numeric_limits<uint16_t>::max();
 
diff --git a/runtime/javaheapprof/javaheapsampler.cc b/runtime/javaheapprof/javaheapsampler.cc
new file mode 100644
index 0000000..a73ed0b
--- /dev/null
+++ b/runtime/javaheapprof/javaheapsampler.cc
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2020 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 "base/atomic.h"
+#include "base/locks.h"
+#include "gc/heap.h"
+#include "javaheapprof/javaheapsampler.h"
+#ifdef ART_TARGET_ANDROID
+#include "perfetto/heap_profile.h"
+#endif
+#include "runtime.h"
+
+namespace art {
+
+size_t HeapSampler::NextGeoDistRandSample() {
+  // Make sure that rng_ and geo_dist are thread safe by acquiring a lock to access.
+  art::MutexLock mu(art::Thread::Current(), geo_dist_rng_lock_);
+  size_t nsample = geo_dist_(rng_);
+  if (nsample == 0) {
+    // Geometric distribution results in +ve values but could have zero.
+    // In the zero case, return 1.
+    nsample = 1;
+  }
+  return nsample;
+}
+
+size_t HeapSampler::PickAndAdjustNextSample(size_t sample_adjust_bytes) {
+  size_t bytes_until_sample;
+  if (GetSamplingInterval() == 1) {
+    bytes_until_sample = 1;
+    return bytes_until_sample;
+  }
+  bytes_until_sample = NextGeoDistRandSample();
+  VLOG(heap) << "JHP:PickAndAdjustNextSample, sample_adjust_bytes: "
+             << sample_adjust_bytes
+             << " bytes_until_sample: " << bytes_until_sample;
+  // Adjust the sample bytes
+  if (sample_adjust_bytes > 0 && bytes_until_sample > sample_adjust_bytes) {
+    bytes_until_sample -= sample_adjust_bytes;
+    VLOG(heap) << "JHP:PickAndAdjustNextSample, final bytes_until_sample: "
+               << bytes_until_sample;
+  }
+  return bytes_until_sample;
+}
+
+// Report to Perfetto an allocation sample.
+// Samples can only be reported after the allocation is done.
+// Also bytes_until_sample can only be updated after the allocation and reporting is done.
+// Thus next bytes_until_sample is previously calculated (before allocation) to be able to
+// get the next tlab_size, but only saved/updated here.
+void HeapSampler::ReportSample(art::mirror::Object* obj, size_t allocation_size) {
+  VLOG(heap) << "JHP:***Report Perfetto Allocation: alloc_size: " << allocation_size;
+  uint64_t perf_alloc_id = reinterpret_cast<uint64_t>(obj);
+  VLOG(heap) << "JHP:***Report Perfetto Allocation: obj: " << perf_alloc_id;
+#ifdef ART_TARGET_ANDROID
+  AHeapProfile_reportSample(perfetto_heap_id_, perf_alloc_id, allocation_size);
+#endif
+}
+
+// Check whether we should take a sample or not at this allocation and calculate the sample
+// offset to use in the expand Tlab calculation. Thus the offset from current pos to the next
+// sample.
+// tlab_used = pos - start
+size_t HeapSampler::GetSampleOffset(size_t alloc_size,
+                                    size_t tlab_used,
+                                    bool* take_sample,
+                                    size_t* temp_bytes_until_sample) {
+  size_t exhausted_size = alloc_size + tlab_used;
+  VLOG(heap) << "JHP:GetSampleOffset: exhausted_size = " << exhausted_size;
+  // Note bytes_until_sample is used as an offset from the start point
+  size_t bytes_until_sample = *GetBytesUntilSample();
+  ssize_t diff = bytes_until_sample - exhausted_size;
+  VLOG(heap) << "JHP:GetSampleOffset: diff = " << diff << " bytes_until_sample = "
+             << bytes_until_sample;
+  if (diff <= 0) {
+    *take_sample = true;
+    // Compute a new bytes_until_sample
+    size_t sample_adj_bytes = -diff;
+    size_t next_bytes_until_sample = PickAndAdjustNextSample(sample_adj_bytes);
+    VLOG(heap) << "JHP:GetSampleOffset: Take sample, next_bytes_until_sample = "
+               << next_bytes_until_sample;
+    next_bytes_until_sample += tlab_used;
+    VLOG(heap) << "JHP:GetSampleOffset:Next sample offset = "
+               << (next_bytes_until_sample - tlab_used);
+    // This function is called before the actual allocation happens so we cannot update
+    // the bytes_until_sample till after the allocation happens, save it to temp which
+    // will be saved after the allocation by the calling function.
+    *temp_bytes_until_sample = next_bytes_until_sample;
+    return (next_bytes_until_sample - tlab_used);
+    // original bytes_until_sample, not offseted
+  } else {
+    *take_sample = false;
+    // The following 2 lines are used in the NonTlab case but have no effect on the
+    // Tlab case, because we will only use the temp_bytes_until_sample if the
+    // take_sample was true (after returning from this function in Tlab case in the
+    // SetBytesUntilSample).
+    size_t next_bytes_until_sample = bytes_until_sample - alloc_size;
+    *temp_bytes_until_sample = next_bytes_until_sample;
+    VLOG(heap) << "JHP:GetSampleOffset: No sample, next_bytes_until_sample= "
+               << next_bytes_until_sample << " alloc= " << alloc_size;
+    return diff;
+  }
+}
+
+// We are tracking the location of samples from the start location of the Tlab
+// We need to adjust how to calculate the sample position in cases where ResetTlab.
+// Adjustment is the new reference position adjustment, usually the new pos-start.
+void HeapSampler::AdjustSampleOffset(size_t adjustment) {
+  size_t* bytes_until_sample = GetBytesUntilSample();
+  size_t cur_bytes_until_sample = *bytes_until_sample;
+  if (cur_bytes_until_sample < adjustment) {
+    VLOG(heap) << "JHP:AdjustSampleOffset:No Adjustment";
+    return;
+  }
+  size_t next_bytes_until_sample = cur_bytes_until_sample - adjustment;
+  *bytes_until_sample = next_bytes_until_sample;
+  VLOG(heap) << "JHP:AdjustSampleOffset: adjustment = " << adjustment
+             << " next_bytes_until_sample = " << next_bytes_until_sample;
+}
+
+bool HeapSampler::IsEnabled() {
+  return enabled_.load(std::memory_order_acquire);
+}
+
+int HeapSampler::GetSamplingInterval() {
+  return p_sampling_interval_.load(std::memory_order_acquire);
+}
+
+void HeapSampler::SetSamplingInterval(int sampling_interval) {
+  // Make sure that rng_ and geo_dist are thread safe by acquiring a lock to access.
+  art::MutexLock mu(art::Thread::Current(), geo_dist_rng_lock_);
+  p_sampling_interval_.store(sampling_interval, std::memory_order_release);
+  geo_dist_.param(std::geometric_distribution<size_t>::param_type(1.0/p_sampling_interval_));
+}
+
+}  // namespace art
diff --git a/runtime/javaheapprof/javaheapsampler.h b/runtime/javaheapprof/javaheapsampler.h
new file mode 100644
index 0000000..618893c
--- /dev/null
+++ b/runtime/javaheapprof/javaheapsampler.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2020 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_JAVAHEAPPROF_JAVAHEAPSAMPLER_H_
+#define ART_RUNTIME_JAVAHEAPPROF_JAVAHEAPSAMPLER_H_
+
+#include <random>
+#include "base/locks.h"
+#include "base/mutex.h"
+#include "mirror/object.h"
+
+namespace art {
+
+class HeapSampler {
+ public:
+  HeapSampler() : rng_(/*seed=*/std::minstd_rand::default_seed),
+                  geo_dist_(1.0 / /*expected value=4KB*/ 4096),
+                  geo_dist_rng_lock_("Heap Sampler RNG Geometric Dist lock",
+                                     art::LockLevel::kGenericBottomLock) {}
+
+  // Set the bytes until sample.
+  void SetBytesUntilSample(size_t bytes) {
+    *GetBytesUntilSample() = bytes;
+  }
+  // Get the bytes until sample.
+  size_t* GetBytesUntilSample() {
+    // Initialization should happen only once the first time the function is called.
+    // However there will always be a slot allocated for it at thread creation.
+    thread_local size_t bytes_until_sample = 0;
+    return &bytes_until_sample;
+  }
+  void SetHeapID(uint32_t heap_id) {
+    perfetto_heap_id_ = heap_id;
+  }
+  void EnableHeapSampler() {
+    enabled_.store(true, std::memory_order_release);
+  }
+  void DisableHeapSampler() {
+    enabled_.store(false, std::memory_order_release);
+  }
+  // Report a sample to Perfetto.
+  void ReportSample(art::mirror::Object* obj, size_t allocation_size);
+  // Check whether we should take a sample or not at this allocation, and return the
+  // number of bytes from current pos to the next sample to use in the expand Tlab
+  // calculation.
+  // Update state of both take_sample and temp_bytes_until_sample.
+  // tlab_used = pos - start
+  // Note: we do not update bytes until sample here. It will be saved after the allocation
+  // happens. This function can be called before the actual allocation happens.
+  size_t GetSampleOffset(size_t alloc_size,
+                         size_t tlab_used,
+                         bool* take_sample,
+                         size_t* temp_bytes_until_sample) REQUIRES(!geo_dist_rng_lock_);
+  // Adjust the sample offset value with the adjustment usually (pos - start)
+  // of new Tlab after Reset.
+  void AdjustSampleOffset(size_t adjustment);
+  // Is heap sampler enabled?
+  bool IsEnabled();
+  // Set the sampling interval.
+  void SetSamplingInterval(int sampling_interval) REQUIRES(!geo_dist_rng_lock_);
+  // Return the sampling interval.
+  int GetSamplingInterval();
+
+ private:
+  size_t NextGeoDistRandSample() REQUIRES(!geo_dist_rng_lock_);
+  // Choose, save, and return the number of bytes until the next sample,
+  // possibly decreasing sample intervals by sample_adj_bytes.
+  size_t PickAndAdjustNextSample(size_t sample_adj_bytes = 0) REQUIRES(!geo_dist_rng_lock_);
+
+  std::atomic<bool> enabled_;
+  // Default sampling interval is 4kb.
+  // Writes guarded by geo_dist_rng_lock_.
+  std::atomic<int> p_sampling_interval_{4 * 1024};
+  uint32_t perfetto_heap_id_ = 0;
+  // std random number generator.
+  std::minstd_rand rng_ GUARDED_BY(geo_dist_rng_lock_);  // Holds the state
+  // std geometric distribution
+  std::geometric_distribution</*result_type=*/size_t> geo_dist_ GUARDED_BY(geo_dist_rng_lock_);
+  // Multiple threads can access the geometric distribution and the random number
+  // generator concurrently and thus geo_dist_rng_lock_ is used for thread safety.
+  art::Mutex geo_dist_rng_lock_;
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_JAVAHEAPPROF_JAVAHEAPSAMPLER_H_
diff --git a/runtime/jdwp_provider.h b/runtime/jdwp_provider.h
index 9cd3145..c7711ec 100644
--- a/runtime/jdwp_provider.h
+++ b/runtime/jdwp_provider.h
@@ -51,7 +51,7 @@
   return JdwpProvider::kUnsetNonDebuggable;
 }
 
-std::ostream& operator<<(std::ostream& os, const JdwpProvider& rhs);
+std::ostream& operator<<(std::ostream& os, JdwpProvider rhs);
 
 }  // namespace art
 #endif  // ART_RUNTIME_JDWP_PROVIDER_H_
diff --git a/runtime/jit/debugger_interface.cc b/runtime/jit/debugger_interface.cc
index cecf533..986003b 100644
--- a/runtime/jit/debugger_interface.cc
+++ b/runtime/jit/debugger_interface.cc
@@ -25,6 +25,7 @@
 #include "base/time_utils.h"
 #include "base/utils.h"
 #include "dex/dex_file.h"
+#include "elf/elf_debug_reader.h"
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
 #include "jit/jit_memory_region.h"
@@ -101,7 +102,14 @@
 // Some writes are synchronized so libunwindstack can read the memory safely from another process.
 constexpr std::memory_order kNonRacingRelaxed = std::memory_order_relaxed;
 
+// Size of JIT code range covered by each packed JITCodeEntry.
+constexpr uint32_t kJitRepackGroupSize = 64 * KB;
+
+// Automatically call the repack method every 'n' new entries.
+constexpr uint32_t kJitRepackFrequency = 64;
+
 // Public binary interface between ART and native tools (gdb, libunwind, etc).
+// The fields below need to be exported and have special names as per the gdb api.
 extern "C" {
   enum JITAction {
     JIT_NOACTION = 0,
@@ -191,6 +199,18 @@
   JITDescriptor __dex_debug_descriptor GUARDED_BY(g_dex_debug_lock) {};
 }
 
+// The fields below are internal, but we keep them here anyway for consistency.
+// Their state is related to the static state above and it must be kept in sync.
+
+// Used only in debug builds to check that we are not adding duplicate entries.
+static std::unordered_set<const void*> g_dcheck_all_jit_functions GUARDED_BY(g_jit_debug_lock);
+
+// Methods that have been marked for deletion on the next repack pass.
+static std::vector<const void*> g_removed_jit_functions GUARDED_BY(g_jit_debug_lock);
+
+// Number of small (single symbol) ELF files. Used to trigger repacking.
+static uint32_t g_jit_num_unpacked_entries = 0;
+
 struct DexNativeInfo {
   static constexpr bool kCopySymfileData = false;  // Just reference DEX files.
   static JITDescriptor& Descriptor() { return __dex_debug_descriptor; }
@@ -390,7 +410,10 @@
 void AddNativeDebugInfoForDex(Thread* self, const DexFile* dexfile) {
   MutexLock mu(self, g_dex_debug_lock);
   DCHECK(dexfile != nullptr);
-  const ArrayRef<const uint8_t> symfile(dexfile->Begin(), dexfile->Size());
+  // Compact dex files may store data past the size defined in the header.
+  const DexFile::Header& header = dexfile->GetHeader();
+  uint32_t size = std::max(header.file_size_, header.data_off_ + header.data_size_);
+  const ArrayRef<const uint8_t> symfile(dexfile->Begin(), size);
   CreateJITCodeEntryInternal<DexNativeInfo>(symfile);
 }
 
@@ -459,13 +482,6 @@
   descriptor.free_entries_ = nullptr;  // Don't reuse zygote's entries.
 }
 
-// Size of JIT code range covered by each packed JITCodeEntry.
-static constexpr uint32_t kJitRepackGroupSize = 64 * KB;
-
-// Automatically call the repack method every 'n' new entries.
-static constexpr uint32_t kJitRepackFrequency = 64;
-static uint32_t g_jit_num_unpacked_entries = 0;
-
 // Split the JIT code cache into groups of fixed size and create single JITCodeEntry for each group.
 // The start address of method's code determines which group it belongs to.  The end is irrelevant.
 // New mini debug infos will be merged if possible, and entries for GCed functions will be removed.
@@ -549,11 +565,23 @@
   g_jit_num_unpacked_entries = 0;
 }
 
+void RepackNativeDebugInfoForJitLocked() REQUIRES(g_jit_debug_lock);
+
 void AddNativeDebugInfoForJit(const void* code_ptr,
                               const std::vector<uint8_t>& symfile,
                               bool allow_packing) {
   MutexLock mu(Thread::Current(), g_jit_debug_lock);
   DCHECK_NE(symfile.size(), 0u);
+  if (kIsDebugBuild && code_ptr != nullptr) {
+    DCHECK(g_dcheck_all_jit_functions.insert(code_ptr).second) << code_ptr << " already added";
+  }
+
+  // Remove all methods which have been marked for removal.  The JIT GC should
+  // force repack, so this should happen only rarely for various corner cases.
+  // Must be done before addition in case the added code_ptr is in the removed set.
+  if (!g_removed_jit_functions.empty()) {
+    RepackNativeDebugInfoForJitLocked();
+  }
 
   CreateJITCodeEntryInternal<JitNativeInfo>(ArrayRef<const uint8_t>(symfile),
                                             /*addr=*/ code_ptr,
@@ -575,9 +603,22 @@
   }
 }
 
-void RemoveNativeDebugInfoForJit(ArrayRef<const void*> removed) {
+void RemoveNativeDebugInfoForJit(const void* code_ptr) {
   MutexLock mu(Thread::Current(), g_jit_debug_lock);
-  RepackEntries(/*compress_entries=*/ true, removed);
+  g_dcheck_all_jit_functions.erase(code_ptr);
+
+  // Method removal is very expensive since we need to decompress and read ELF files.
+  // Collet methods to be removed and do the removal in bulk later.
+  g_removed_jit_functions.push_back(code_ptr);
+
+  VLOG(jit) << "JIT mini-debug-info removed for " << code_ptr;
+}
+
+void RepackNativeDebugInfoForJitLocked() {
+  // Remove entries which are inside packed and compressed ELF files.
+  std::vector<const void*>& removed = g_removed_jit_functions;
+  std::sort(removed.begin(), removed.end());
+  RepackEntries(/*compress_entries=*/ true, ArrayRef<const void*>(removed));
 
   // Remove entries which are not allowed to be packed (containing single method each).
   for (const JITCodeEntry* it = __jit_debug_descriptor.head_; it != nullptr;) {
@@ -587,6 +628,14 @@
     }
     it = next;
   }
+
+  removed.clear();
+  removed.shrink_to_fit();
+}
+
+void RepackNativeDebugInfoForJit() {
+  MutexLock mu(Thread::Current(), g_jit_debug_lock);
+  RepackNativeDebugInfoForJitLocked();
 }
 
 size_t GetJitMiniDebugInfoMemUsage() {
@@ -602,4 +651,19 @@
   return &g_jit_debug_lock;
 }
 
+void ForEachNativeDebugSymbol(std::function<void(const void*, size_t, const char*)> cb) {
+  MutexLock mu(Thread::Current(), g_jit_debug_lock);
+  using ElfRuntimeTypes = std::conditional<sizeof(void*) == 4, ElfTypes32, ElfTypes64>::type;
+  const JITCodeEntry* end = __jit_debug_descriptor.zygote_head_entry_;
+  for (const JITCodeEntry* it = __jit_debug_descriptor.head_; it != end; it = it->next_) {
+    ArrayRef<const uint8_t> buffer(it->symfile_addr_, it->symfile_size_);
+    if (!buffer.empty()) {
+      ElfDebugReader<ElfRuntimeTypes> reader(buffer);
+      reader.VisitFunctionSymbols([&](ElfRuntimeTypes::Sym sym, const char* name) {
+        cb(reinterpret_cast<const void*>(sym.st_value), sym.st_size, name);
+      });
+    }
+  }
+}
+
 }  // namespace art
diff --git a/runtime/jit/debugger_interface.h b/runtime/jit/debugger_interface.h
index 477d58c..62288de 100644
--- a/runtime/jit/debugger_interface.h
+++ b/runtime/jit/debugger_interface.h
@@ -57,7 +57,11 @@
     REQUIRES_SHARED(Locks::jit_lock_);  // Might need JIT code cache to allocate memory.
 
 // Notify native tools (e.g. libunwind) that JIT code has been garbage collected.
-void RemoveNativeDebugInfoForJit(ArrayRef<const void*> removed_code_ptrs)
+// The actual removal might be lazy. Removal of address that was not added is no-op.
+void RemoveNativeDebugInfoForJit(const void* code_ptr);
+
+// Merge and compress entries to save space.
+void RepackNativeDebugInfoForJit()
     REQUIRES_SHARED(Locks::jit_lock_);  // Might need JIT code cache to allocate memory.
 
 // Returns approximate memory used by debug info for JIT code.
@@ -68,6 +72,10 @@
 // TODO: Unwinding should be race-free. Remove this.
 Mutex* GetNativeDebugInfoLock();
 
+// Call given callback for every non-zygote symbol.
+// The callback parameters are (address, size, name).
+void ForEachNativeDebugSymbol(std::function<void(const void*, size_t, const char*)> cb);
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_JIT_DEBUGGER_INTERFACE_H_
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 8d434b8..5ee8871 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -27,7 +27,8 @@
 #include "base/runtime_debug.h"
 #include "base/scoped_flock.h"
 #include "base/utils.h"
-#include "class_root.h"
+#include "class_root-inl.h"
+#include "compilation_kind.h"
 #include "debugger.h"
 #include "dex/type_lookup_table.h"
 #include "gc/space/image_space.h"
@@ -89,8 +90,8 @@
 JitOptions* JitOptions::CreateFromRuntimeArguments(const RuntimeArgumentMap& options) {
   auto* jit_options = new JitOptions;
   jit_options->use_jit_compilation_ = options.GetOrDefault(RuntimeArgumentMap::UseJitCompilation);
-  jit_options->use_tiered_jit_compilation_ =
-      options.GetOrDefault(RuntimeArgumentMap::UseTieredJitCompilation);
+  jit_options->use_profiled_jit_compilation_ =
+      options.GetOrDefault(RuntimeArgumentMap::UseProfiledJitCompilation);
 
   jit_options->code_cache_initial_capacity_ =
       options.GetOrDefault(RuntimeArgumentMap::JITCodeCacheInitialCapacity);
@@ -102,8 +103,10 @@
       options.GetOrDefault(RuntimeArgumentMap::ProfileSaverOpts);
   jit_options->thread_pool_pthread_priority_ =
       options.GetOrDefault(RuntimeArgumentMap::JITPoolThreadPthreadPriority);
+  jit_options->zygote_thread_pool_pthread_priority_ =
+      options.GetOrDefault(RuntimeArgumentMap::JITZygotePoolThreadPthreadPriority);
 
-  // Set default compile threshold to aide with sanity checking defaults.
+  // Set default compile threshold to aid with checking defaults.
   jit_options->compile_threshold_ =
       kIsDebugBuild
       ? (Jit::kSlowMode
@@ -114,7 +117,7 @@
   // When not running in slow-mode, thresholds are quantized to kJitSamplesbatchsize.
   const uint32_t kJitThresholdStep = Jit::kSlowMode ? 1u : kJitSamplesBatchSize;
 
-  // Set default warm-up threshold to aide with sanity checking defaults.
+  // Set default warm-up threshold to aid with checking defaults.
   jit_options->warmup_threshold_ =
       kIsDebugBuild ? (Jit::kSlowMode
                        ? kJitSlowStressDefaultWarmUpThreshold
@@ -289,7 +292,10 @@
   return true;
 }
 
-bool Jit::CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr, bool prejit) {
+bool Jit::CompileMethod(ArtMethod* method,
+                        Thread* self,
+                        CompilationKind compilation_kind,
+                        bool prejit) {
   DCHECK(Runtime::Current()->UseJitCompilation());
   DCHECK(!method->IsRuntimeMethod());
 
@@ -319,7 +325,7 @@
   }
 
   JitMemoryRegion* region = GetCodeCache()->GetCurrentRegion();
-  if (osr && GetCodeCache()->IsSharedRegion(*region)) {
+  if ((compilation_kind == CompilationKind::kOsr) && GetCodeCache()->IsSharedRegion(*region)) {
     VLOG(jit) << "JIT not osr compiling "
               << method->PrettyMethod()
               << " due to using shared region";
@@ -329,20 +335,19 @@
   // If we get a request to compile a proxy method, we pass the actual Java method
   // of that proxy method, as the compiler does not expect a proxy method.
   ArtMethod* method_to_compile = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
-  if (!code_cache_->NotifyCompilationOf(method_to_compile, self, osr, prejit, baseline, region)) {
+  if (!code_cache_->NotifyCompilationOf(method_to_compile, self, compilation_kind, prejit)) {
     return false;
   }
 
   VLOG(jit) << "Compiling method "
             << ArtMethod::PrettyMethod(method_to_compile)
-            << " osr=" << std::boolalpha << osr
-            << " baseline=" << std::boolalpha << baseline;
-  bool success = jit_compiler_->CompileMethod(self, region, method_to_compile, baseline, osr);
-  code_cache_->DoneCompiling(method_to_compile, self, osr);
+            << " kind=" << compilation_kind;
+  bool success = jit_compiler_->CompileMethod(self, region, method_to_compile, compilation_kind);
+  code_cache_->DoneCompiling(method_to_compile, self, compilation_kind);
   if (!success) {
     VLOG(jit) << "Failed to compile method "
               << ArtMethod::PrettyMethod(method_to_compile)
-              << " osr=" << std::boolalpha << osr;
+              << " kind=" << compilation_kind;
   }
   if (kIsDebugBuild) {
     if (self->IsExceptionPending()) {
@@ -385,10 +390,15 @@
   }
 }
 
-void Jit::StartProfileSaver(const std::string& filename,
-                            const std::vector<std::string>& code_paths) {
+void Jit::StartProfileSaver(const std::string& profile_filename,
+                            const std::vector<std::string>& code_paths,
+                            const std::string& ref_profile_filename) {
   if (options_->GetSaveProfilingInfo()) {
-    ProfileSaver::Start(options_->GetProfileSaverOptions(), filename, code_cache_, code_paths);
+    ProfileSaver::Start(options_->GetProfileSaverOptions(),
+                        profile_filename,
+                        code_cache_,
+                        code_paths,
+                        ref_profile_filename);
   }
 }
 
@@ -756,14 +766,12 @@
 class JitCompileTask final : public Task {
  public:
   enum class TaskKind {
-    kAllocateProfile,
     kCompile,
-    kCompileBaseline,
-    kCompileOsr,
     kPreCompile,
   };
 
-  JitCompileTask(ArtMethod* method, TaskKind kind) : method_(method), kind_(kind), klass_(nullptr) {
+  JitCompileTask(ArtMethod* method, TaskKind task_kind, CompilationKind compilation_kind)
+      : method_(method), kind_(task_kind), compilation_kind_(compilation_kind), klass_(nullptr) {
     ScopedObjectAccess soa(Thread::Current());
     // For a non-bootclasspath class, add a global ref to the class to prevent class unloading
     // until compilation is done.
@@ -787,24 +795,15 @@
     {
       ScopedObjectAccess soa(self);
       switch (kind_) {
-        case TaskKind::kPreCompile:
         case TaskKind::kCompile:
-        case TaskKind::kCompileBaseline:
-        case TaskKind::kCompileOsr: {
+        case TaskKind::kPreCompile: {
           Runtime::Current()->GetJit()->CompileMethod(
               method_,
               self,
-              /* baseline= */ (kind_ == TaskKind::kCompileBaseline),
-              /* osr= */ (kind_ == TaskKind::kCompileOsr),
+              compilation_kind_,
               /* prejit= */ (kind_ == TaskKind::kPreCompile));
           break;
         }
-        case TaskKind::kAllocateProfile: {
-          if (ProfilingInfo::Create(self, method_, /* retry_allocation= */ true)) {
-            VLOG(jit) << "Start profiling " << ArtMethod::PrettyMethod(method_);
-          }
-          break;
-        }
       }
     }
     ProfileSaver::NotifyJitActivity();
@@ -817,6 +816,7 @@
  private:
   ArtMethod* const method_;
   const TaskKind kind_;
+  const CompilationKind compilation_kind_;
   jobject klass_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(JitCompileTask);
@@ -914,7 +914,8 @@
           continue;
         }
         ++number_of_classes;
-        if (linker->VerifyClass(self, klass) == verifier::FailureKind::kHardFailure) {
+        if (linker->VerifyClass(self, /* verifier_deps= */ nullptr, klass) ==
+                verifier::FailureKind::kHardFailure) {
           DCHECK(self->IsExceptionPending());
           LOG(FATAL) << "Methods in the boot classpath failed to verify: "
                      << self->GetException()->Dump();
@@ -1069,8 +1070,26 @@
     LOG(WARNING) << "Failed to create child mapping of boot image methods: " << error_str;
     return;
   }
+  //  We are going to mremap the child mapping into the image:
+  //
+  //                            ImageSection       ChildMappingMethods
+  //
+  //         section start -->  -----------
+  //                            |         |
+  //                            |         |
+  //            page_start -->  |         |   <-----   -----------
+  //                            |         |            |         |
+  //                            |         |            |         |
+  //                            |         |            |         |
+  //                            |         |            |         |
+  //                            |         |            |         |
+  //                            |         |            |         |
+  //                            |         |            |         |
+  //             page_end  -->  |         |   <-----   -----------
+  //                            |         |
+  //         section end   -->  -----------
+  //
   size_t offset = 0;
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
     const ImageHeader& header = space->GetImageHeader();
     const ImageSection& section = header.GetMethodsSection();
@@ -1082,86 +1101,48 @@
       continue;
     }
     uint64_t capacity = page_end - page_start;
-    // Walk over methods in the boot image, and check for ones whose class is
-    // not initialized in the process, but are in the zygote process. For
-    // such methods, we need their entrypoints to be stubs that do the
-    // initialization check.
+    // Walk over methods in the boot image, and check for:
+    // 1) methods whose class is not initialized in the process, but are in the
+    // zygote process. For such methods, we need their entrypoints to be stubs
+    // that do the initialization check.
+    // 2) native methods whose data pointer is different than the one in the
+    // zygote. Such methods may have had custom native implementation provided
+    // by JNI RegisterNatives.
     header.VisitPackedArtMethods([&](ArtMethod& method) NO_THREAD_SAFETY_ANALYSIS {
+      // Methods in the boot image should never have their single
+      // implementation flag set (and therefore never have a `data_` pointing
+      // to an ArtMethod for single implementation).
+      CHECK(method.IsIntrinsic() || !method.HasSingleImplementationFlag());
       if (method.IsRuntimeMethod()) {
         return;
       }
-      if (method.GetDeclaringClassUnchecked()->IsVisiblyInitialized() ||
-          !method.IsStatic() ||
-          method.IsConstructor()) {
-        // Method does not need any stub.
-        return;
+
+      // Pointer to the method we're currently using.
+      uint8_t* pointer = reinterpret_cast<uint8_t*>(&method);
+      // The data pointer of that method that we want to keep.
+      uint8_t* data_pointer = pointer + ArtMethod::DataOffset(kRuntimePointerSize).Int32Value();
+      if (method.IsNative() && data_pointer >= page_start && data_pointer < page_end) {
+        // The data pointer of the ArtMethod in the shared memory we are going to remap into our
+        // own mapping. This is the data that we will see after the remap.
+        uint8_t* new_data_pointer =
+            child_mapping_methods.Begin() + offset + (data_pointer - page_start);
+        CopyIfDifferent(new_data_pointer, data_pointer, sizeof(void*));
       }
 
-      //  We are going to mremap the child mapping into the image:
-      //
-      //                            ImageSection       ChildMappingMethods
-      //
-      //         section start -->  -----------
-      //                            |         |
-      //                            |         |
-      //            page_start -->  |         |   <-----   -----------
-      //                            |         |            |         |
-      //                            |         |            |         |
-      //                            |         |            |         |
-      //                            |         |            |         |
-      //                            |         |            |         |
-      //                            |         |            |         |
-      //                            |         |            |         |
-      //             page_end  -->  |         |   <-----   -----------
-      //                            |         |
-      //         section end   -->  -----------
-
-
-      uint8_t* pointer = reinterpret_cast<uint8_t*>(&method);
-      // Note: We could refactor this to only check if the ArtMethod entrypoint is inside the
-      // page region. This would remove the need for the edge case handling below.
-      if (pointer >= page_start && pointer + sizeof(ArtMethod) < page_end) {
-        // For all the methods in the mapping, put the entrypoint to the
-        // resolution stub.
-        ArtMethod* new_method = reinterpret_cast<ArtMethod*>(
-            child_mapping_methods.Begin() + offset + (pointer - page_start));
-        const void* code = new_method->GetEntryPointFromQuickCompiledCode();
-        if (!class_linker->IsQuickGenericJniStub(code) &&
-            !class_linker->IsQuickToInterpreterBridge(code) &&
-            !class_linker->IsQuickResolutionStub(code)) {
-          LOG(INFO) << "Putting back the resolution stub to an ArtMethod";
-          new_method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionStub());
-        }
-      } else if (pointer < page_start && (pointer + sizeof(ArtMethod)) > page_start) {
-        LOG(INFO) << "Copying parts of the contents of an ArtMethod spanning page_start";
-        // If the method spans `page_start`, copy the contents of the child
-        // into the pages we are going to remap into the image.
-        //
-        //         section start -->  -----------
-        //                            |         |
-        //                            |         |
-        //            page_start -->  |/////////|            -----------
-        //                            |/////////| -> copy -> |/////////|
-        //                            |         |            |         |
-        //
-        CopyIfDifferent(child_mapping_methods.Begin() + offset,
-                        page_start,
-                        pointer + sizeof(ArtMethod) - page_start);
-      } else if (pointer < page_end && (pointer + sizeof(ArtMethod)) > page_end) {
-        LOG(INFO) << "Copying parts of the contents of an ArtMethod spanning page_end";
-        // If the method spans `page_end`, copy the contents of the child
-        // into the pages we are going to remap into the image.
-        //
-        //                            |         |            |         |
-        //                            |/////////| -> copy -> |/////////|
-        //             page_end  -->  |/////////|            -----------
-        //                            |         |
-        //         section end   -->  -----------
-        //
-        size_t bytes_to_copy = (page_end - pointer);
-        CopyIfDifferent(child_mapping_methods.Begin() + offset + capacity - bytes_to_copy,
-                        page_end - bytes_to_copy,
-                        bytes_to_copy);
+      // The entrypoint of the method we're currently using and that we want to
+      // keep.
+      uint8_t* entry_point_pointer = pointer +
+          ArtMethod::EntryPointFromQuickCompiledCodeOffset(kRuntimePointerSize).Int32Value();
+      if (!method.GetDeclaringClassUnchecked()->IsVisiblyInitialized() &&
+          method.IsStatic() &&
+          !method.IsConstructor() &&
+          entry_point_pointer >= page_start &&
+          entry_point_pointer < page_end) {
+        // The entry point of the ArtMethod in the shared memory we are going to remap into our
+        // own mapping. This is the entrypoint that we will see after the remap.
+        uint8_t* new_entry_point_pointer =
+            child_mapping_methods.Begin() + offset + (entry_point_pointer - page_start);
+        CopyIfDifferent(new_entry_point_pointer, entry_point_pointer, sizeof(void*));
       }
     }, space->Begin(), kRuntimePointerSize);
 
@@ -1193,6 +1174,11 @@
   return false;
 }
 
+bool Jit::InZygoteUsingJit() {
+  Runtime* runtime = Runtime::Current();
+  return runtime->IsZygote() && HasImageWithProfile() && runtime->UseJitCompilation();
+}
+
 void Jit::CreateThreadPool() {
   // There is a DCHECK in the 'AddSamples' method to ensure the tread pool
   // is not null when we instrument.
@@ -1201,10 +1187,13 @@
   constexpr bool kJitPoolNeedsPeers = true;
   thread_pool_.reset(new ThreadPool("Jit thread pool", 1, kJitPoolNeedsPeers));
 
-  thread_pool_->SetPthreadPriority(options_->GetThreadPoolPthreadPriority());
+  Runtime* runtime = Runtime::Current();
+  thread_pool_->SetPthreadPriority(
+      runtime->IsZygote()
+          ? options_->GetZygoteThreadPoolPthreadPriority()
+          : options_->GetThreadPoolPthreadPriority());
   Start();
 
-  Runtime* runtime = Runtime::Current();
   if (runtime->IsZygote()) {
     // To speed up class lookups, generate a type lookup table for
     // dex files not backed by oat file.
@@ -1222,7 +1211,7 @@
     thread_pool_->AddTask(Thread::Current(), new ZygoteVerificationTask());
   }
 
-  if (runtime->IsZygote() && HasImageWithProfile() && UseJitCompilation()) {
+  if (InZygoteUsingJit()) {
     // If we have an image with a profile, request a JIT task to
     // compile all methods in that profile.
     thread_pool_->AddTask(Thread::Current(), new ZygoteTask());
@@ -1305,7 +1294,9 @@
   Runtime* runtime = Runtime::Current();
   // If the runtime is debuggable, no need to precompile methods.
   if (runtime->IsSystemServer() &&
-      UseJitCompilation() && HasImageWithProfile() &&
+      UseJitCompilation() &&
+      options_->UseProfiledJitCompilation() &&
+      HasImageWithProfile() &&
       !runtime->IsJavaDebuggable()) {
     thread_pool_->AddTask(Thread::Current(), new JitProfileTask(dex_files, class_loader));
   }
@@ -1334,14 +1325,16 @@
   const void* entry_point = method->GetEntryPointFromQuickCompiledCode();
   if (class_linker->IsQuickToInterpreterBridge(entry_point) ||
       class_linker->IsQuickGenericJniStub(entry_point) ||
+      (entry_point == interpreter::GetNterpEntryPoint()) ||
       // We explicitly check for the stub. The trampoline is for methods backed by
       // a .oat file that has a compiled version of the method.
       (entry_point == GetQuickResolutionStub())) {
     method->SetPreCompiled();
     if (!add_to_queue) {
-      CompileMethod(method, self, /* baseline= */ false, /* osr= */ false, /* prejit= */ true);
+      CompileMethod(method, self, CompilationKind::kOptimized, /* prejit= */ true);
     } else {
-      Task* task = new JitCompileTask(method, JitCompileTask::TaskKind::kPreCompile);
+      Task* task = new JitCompileTask(
+          method, JitCompileTask::TaskKind::kPreCompile, CompilationKind::kOptimized);
       if (compile_after_boot) {
         MutexLock mu(Thread::Current(), boot_completed_lock_);
         if (!boot_completed_) {
@@ -1475,7 +1468,7 @@
   return added_to_queue;
 }
 
-static bool IgnoreSamplesForMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
+bool Jit::IgnoreSamplesForMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
   if (method->IsClassInitializer() || !method->IsCompilable() || method->IsPreCompiled()) {
     // We do not want to compile such methods.
     return true;
@@ -1528,40 +1521,14 @@
   DCHECK_GE(PriorityThreadWeight(), 1);
   DCHECK_LE(PriorityThreadWeight(), HotMethodThreshold());
 
-  if (old_count < WarmMethodThreshold() && new_count >= WarmMethodThreshold()) {
-    // Note: Native method have no "warm" state or profiling info.
-    if (!method->IsNative() &&
-        (method->GetProfilingInfo(kRuntimePointerSize) == nullptr) &&
-        code_cache_->CanAllocateProfilingInfo() &&
-        !options_->UseTieredJitCompilation()) {
-      bool success = ProfilingInfo::Create(self, method, /* retry_allocation= */ false);
-      if (success) {
-        VLOG(jit) << "Start profiling " << method->PrettyMethod();
-      }
-
-      if (thread_pool_ == nullptr) {
-        // Calling ProfilingInfo::Create might put us in a suspended state, which could
-        // lead to the thread pool being deleted when we are shutting down.
-        return false;
-      }
-
-      if (!success) {
-        // We failed allocating. Instead of doing the collection on the Java thread, we push
-        // an allocation to a compiler thread, that will do the collection.
-        thread_pool_->AddTask(
-            self, new JitCompileTask(method, JitCompileTask::TaskKind::kAllocateProfile));
-      }
-    }
-  }
   if (UseJitCompilation()) {
     if (old_count < HotMethodThreshold() && new_count >= HotMethodThreshold()) {
       if (!code_cache_->ContainsPc(method->GetEntryPointFromQuickCompiledCode())) {
         DCHECK(thread_pool_ != nullptr);
-        JitCompileTask::TaskKind kind =
-            (options_->UseTieredJitCompilation() || options_->UseBaselineCompiler())
-                ? JitCompileTask::TaskKind::kCompileBaseline
-                : JitCompileTask::TaskKind::kCompile;
-        thread_pool_->AddTask(self, new JitCompileTask(method, kind));
+        thread_pool_->AddTask(
+            self,
+            new JitCompileTask(
+                method, JitCompileTask::TaskKind::kCompile, CompilationKind::kBaseline));
       }
     }
     if (old_count < OSRMethodThreshold() && new_count >= OSRMethodThreshold()) {
@@ -1572,7 +1539,8 @@
       if (!code_cache_->IsOsrCompiled(method)) {
         DCHECK(thread_pool_ != nullptr);
         thread_pool_->AddTask(
-            self, new JitCompileTask(method, JitCompileTask::TaskKind::kCompileOsr));
+            self,
+            new JitCompileTask(method, JitCompileTask::TaskKind::kCompile, CompilationKind::kOsr));
       }
     }
   }
@@ -1584,11 +1552,14 @@
     return;
   }
   // We arrive here after a baseline compiled code has reached its baseline
-  // hotness threshold. If tiered compilation is enabled, enqueue a compilation
+  // hotness threshold. If we're not only using the baseline compiler, enqueue a compilation
   // task that will compile optimize the method.
-  if (options_->UseTieredJitCompilation()) {
+  if (!options_->UseBaselineCompiler()) {
     thread_pool_->AddTask(
-        self, new JitCompileTask(method, JitCompileTask::TaskKind::kCompile));
+        self,
+        new JitCompileTask(method,
+                           JitCompileTask::TaskKind::kCompile,
+                           CompilationKind::kOptimized));
   }
 }
 
@@ -1613,13 +1584,10 @@
   if (UNLIKELY(runtime->UseJitCompilation() && JitAtFirstUse())) {
     ArtMethod* np_method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
     if (np_method->IsCompilable()) {
-      if (!np_method->IsNative() && GetCodeCache()->CanAllocateProfilingInfo()) {
-        // The compiler requires a ProfilingInfo object for non-native methods.
-        ProfilingInfo::Create(thread, np_method, /* retry_allocation= */ true);
-      }
       // TODO(ngeoffray): For JIT at first use, use kPreCompile. Currently we don't due to
       // conflicts with jitzygote optimizations.
-      JitCompileTask compile_task(method, JitCompileTask::TaskKind::kCompile);
+      JitCompileTask compile_task(
+          method, JitCompileTask::TaskKind::kCompile, CompilationKind::kOptimized);
       // Fake being in a runtime thread so that class-load behavior will be the same as normal jit.
       ScopedSetRuntimeThread ssrt(thread);
       compile_task.Run(thread);
@@ -1627,30 +1595,7 @@
     return;
   }
 
-  ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize);
-  // Update the entrypoint if the ProfilingInfo has one. The interpreter will call it
-  // instead of interpreting the method. We don't update it for instrumentation as the entrypoint
-  // must remain the instrumentation entrypoint.
-  if ((profiling_info != nullptr) &&
-      (profiling_info->GetSavedEntryPoint() != nullptr) &&
-      (method->GetEntryPointFromQuickCompiledCode() != GetQuickInstrumentationEntryPoint())) {
-    Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
-        method, profiling_info->GetSavedEntryPoint());
-  } else {
-    AddSamples(thread, method, 1, /* with_backedges= */false);
-  }
-}
-
-void Jit::InvokeVirtualOrInterface(ObjPtr<mirror::Object> this_object,
-                                   ArtMethod* caller,
-                                   uint32_t dex_pc,
-                                   ArtMethod* callee ATTRIBUTE_UNUSED) {
-  ScopedAssertNoThreadSuspension ants(__FUNCTION__);
-  DCHECK(this_object != nullptr);
-  ProfilingInfo* info = caller->GetProfilingInfo(kRuntimePointerSize);
-  if (info != nullptr) {
-    info->AddInvokeInfo(dex_pc, this_object->GetClass());
-  }
+  AddSamples(thread, method, 1, /* with_backedges= */false);
 }
 
 void Jit::WaitForCompilationToFinish(Thread* self) {
@@ -1775,10 +1720,11 @@
 }
 
 void Jit::PostZygoteFork() {
+  Runtime* runtime = Runtime::Current();
   if (thread_pool_ == nullptr) {
     // If this is a child zygote, check if we need to remap the boot image
     // methods.
-    if (Runtime::Current()->IsZygote() &&
+    if (runtime->IsZygote() &&
         fd_methods_ != -1 &&
         code_cache_->GetZygoteMap()->IsCompilationNotified()) {
       ScopedSuspendAll ssa(__FUNCTION__);
@@ -1786,8 +1732,7 @@
     }
     return;
   }
-  if (Runtime::Current()->IsZygote() &&
-      code_cache_->GetZygoteMap()->IsCompilationDoneButNotNotified()) {
+  if (runtime->IsZygote() && code_cache_->GetZygoteMap()->IsCompilationDoneButNotNotified()) {
     // Copy the boot image methods data to the mappings we created to share
     // with the children. We do this here as we are the only thread running and
     // we don't risk other threads concurrently updating the ArtMethod's.
@@ -1796,6 +1741,10 @@
     CHECK(code_cache_->GetZygoteMap()->IsCompilationNotified());
   }
   thread_pool_->CreateThreads();
+  thread_pool_->SetPthreadPriority(
+      runtime->IsZygote()
+          ? options_->GetZygoteThreadPoolPthreadPriority()
+          : options_->GetThreadPoolPthreadPriority());
 }
 
 void Jit::BootCompleted() {
@@ -1848,16 +1797,20 @@
     // If we already have compiled code for it, nterp may be stuck in a loop.
     // Compile OSR.
     thread_pool_->AddTask(
-        self, new JitCompileTask(method, JitCompileTask::TaskKind::kCompileOsr));
+        self,
+        new JitCompileTask(method, JitCompileTask::TaskKind::kCompile, CompilationKind::kOsr));
     return;
   }
   if (GetCodeCache()->CanAllocateProfilingInfo()) {
-    ProfilingInfo::Create(self, method, /* retry_allocation= */ false);
     thread_pool_->AddTask(
-        self, new JitCompileTask(method, JitCompileTask::TaskKind::kCompileBaseline));
+        self,
+        new JitCompileTask(method, JitCompileTask::TaskKind::kCompile, CompilationKind::kBaseline));
   } else {
     thread_pool_->AddTask(
-        self, new JitCompileTask(method, JitCompileTask::TaskKind::kCompile));
+        self,
+        new JitCompileTask(method,
+                           JitCompileTask::TaskKind::kCompile,
+                           CompilationKind::kOptimized));
   }
 }
 
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index e9fd915..a6e484f 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -24,9 +24,10 @@
 #include "base/mutex.h"
 #include "base/runtime_debug.h"
 #include "base/timing_logger.h"
+#include "compilation_kind.h"
 #include "handle.h"
 #include "offsets.h"
-#include "interpreter/mterp/mterp.h"
+#include "interpreter/mterp/nterp.h"
 #include "jit/debugger_interface.h"
 #include "jit/profile_saver_options.h"
 #include "obj_ptr.h"
@@ -60,6 +61,10 @@
 // At what priority to schedule jit threads. 9 is the lowest foreground priority on device.
 // See android/os/Process.java.
 static constexpr int kJitPoolThreadPthreadDefaultPriority = 9;
+// At what priority to schedule jit zygote threads compiling profiles in the background.
+// 19 is the lowest background priority on device.
+// See android/os/Process.java.
+static constexpr int kJitZygotePoolThreadPthreadDefaultPriority = 19;
 // We check whether to jit-compile the method every Nth invoke.
 // The tests often use threshold of 1000 (and thus 500 to start profiling).
 static constexpr uint32_t kJitSamplesBatchSize = 512;  // Must be power of 2.
@@ -112,18 +117,16 @@
     return thread_pool_pthread_priority_;
   }
 
+  int GetZygoteThreadPoolPthreadPriority() const {
+    return zygote_thread_pool_pthread_priority_;
+  }
+
   bool UseJitCompilation() const {
     return use_jit_compilation_;
   }
 
-  bool UseTieredJitCompilation() const {
-    return use_tiered_jit_compilation_;
-  }
-
-  bool CanCompileBaseline() const {
-    return use_tiered_jit_compilation_ ||
-           use_baseline_compiler_ ||
-           interpreter::IsNterpSupported();
+  bool UseProfiledJitCompilation() const {
+    return use_profiled_jit_compilation_;
   }
 
   void SetUseJitCompilation(bool b) {
@@ -157,7 +160,7 @@
   static uint32_t RoundUpThreshold(uint32_t threshold);
 
   bool use_jit_compilation_;
-  bool use_tiered_jit_compilation_;
+  bool use_profiled_jit_compilation_;
   bool use_baseline_compiler_;
   size_t code_cache_initial_capacity_;
   size_t code_cache_max_capacity_;
@@ -168,11 +171,12 @@
   uint16_t invoke_transition_weight_;
   bool dump_info_on_shutdown_;
   int thread_pool_pthread_priority_;
+  int zygote_thread_pool_pthread_priority_;
   ProfileSaverOptions profile_saver_options_;
 
   JitOptions()
       : use_jit_compilation_(false),
-        use_tiered_jit_compilation_(false),
+        use_profiled_jit_compilation_(false),
         use_baseline_compiler_(false),
         code_cache_initial_capacity_(0),
         code_cache_max_capacity_(0),
@@ -182,7 +186,8 @@
         priority_thread_weight_(0),
         invoke_transition_weight_(0),
         dump_info_on_shutdown_(false),
-        thread_pool_pthread_priority_(kJitPoolThreadPthreadDefaultPriority) {}
+        thread_pool_pthread_priority_(kJitPoolThreadPthreadDefaultPriority),
+        zygote_thread_pool_pthread_priority_(kJitZygotePoolThreadPthreadDefaultPriority) {}
 
   DISALLOW_COPY_AND_ASSIGN(JitOptions);
 };
@@ -192,7 +197,7 @@
  public:
   virtual ~JitCompilerInterface() {}
   virtual bool CompileMethod(
-      Thread* self, JitMemoryRegion* region, ArtMethod* method, bool baseline, bool osr)
+      Thread* self, JitMemoryRegion* region, ArtMethod* method, CompilationKind compilation_kind)
       REQUIRES_SHARED(Locks::mutator_lock_) = 0;
   virtual void TypesLoaded(mirror::Class**, size_t count)
       REQUIRES_SHARED(Locks::mutator_lock_) = 0;
@@ -243,7 +248,7 @@
   // Create JIT itself.
   static Jit* Create(JitCodeCache* code_cache, JitOptions* options);
 
-  bool CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr, bool prejit)
+  bool CompileMethod(ArtMethod* method, Thread* self, CompilationKind compilation_kind, bool prejit)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   const JitCodeCache* GetCodeCache() const {
@@ -272,6 +277,10 @@
       REQUIRES(!lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  int GetThreadPoolPthreadPriority() const {
+    return options_->GetThreadPoolPthreadPriority();
+  }
+
   uint16_t OSRMethodThreshold() const {
     return options_->GetOsrThreshold();
   }
@@ -311,27 +320,30 @@
                                 bool with_backedges)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void InvokeVirtualOrInterface(ObjPtr<mirror::Object> this_object,
-                                ArtMethod* caller,
-                                uint32_t dex_pc,
-                                ArtMethod* callee)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    AddSamples(self, caller, options_->GetInvokeTransitionWeight(), false);
+    if (!IgnoreSamplesForMethod(caller)) {
+      AddSamples(self, caller, options_->GetInvokeTransitionWeight(), false);
+    }
   }
 
   void NotifyCompiledCodeToInterpreterTransition(Thread* self, ArtMethod* callee)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    AddSamples(self, callee, options_->GetInvokeTransitionWeight(), false);
+    if (!IgnoreSamplesForMethod(callee)) {
+      AddSamples(self, callee, options_->GetInvokeTransitionWeight(), false);
+    }
   }
 
   // Starts the profile saver if the config options allow profile recording.
-  // The profile will be stored in the specified `filename` and will contain
+  // The profile will be stored in the specified `profile_filename` and will contain
   // information collected from the given `code_paths` (a set of dex locations).
-  void StartProfileSaver(const std::string& filename,
-                         const std::vector<std::string>& code_paths);
+  //
+  // The `ref_profile_filename` denotes the path to the reference profile which
+  // might be queried to determine if an initial save should be done earlier.
+  // It can be empty indicating there is no reference profile.
+  void StartProfileSaver(const std::string& profile_filename,
+                         const std::vector<std::string>& code_paths,
+                         const std::string& ref_profile_filename);
   void StopProfileSaver();
 
   void DumpForSigQuit(std::ostream& os) REQUIRES(!lock_);
@@ -393,6 +405,9 @@
   // Called when system finishes booting.
   void BootCompleted();
 
+  // Are we in a zygote using JIT compilation?
+  static bool InZygoteUsingJit();
+
   // Compile methods from the given profile (.prof extension). If `add_to_queue`
   // is true, methods in the profile are added to the JIT queue. Otherwise they are compiled
   // directly.
@@ -444,6 +459,10 @@
  private:
   Jit(JitCodeCache* code_cache, JitOptions* options);
 
+  // Whether we should not add hotness counts for the given method.
+  bool IgnoreSamplesForMethod(ArtMethod* method)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   // Compile an individual method listed in a profile. If `add_to_queue` is
   // true and the method was resolved, return true. Otherwise return false.
   bool CompileMethodFromProfile(Thread* self,
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 8383002..9d9a7d3 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -43,6 +43,7 @@
 #include "gc/allocator/dlmalloc.h"
 #include "gc/scoped_gc_critical_section.h"
 #include "handle.h"
+#include "handle_scope-inl.h"
 #include "instrumentation.h"
 #include "intern_table.h"
 #include "jit/jit.h"
@@ -173,17 +174,21 @@
     return methods_;
   }
 
-  void RemoveMethodsIn(const LinearAlloc& alloc) {
-    auto kept_end = std::remove_if(
+  void RemoveMethodsIn(const LinearAlloc& alloc) REQUIRES_SHARED(Locks::mutator_lock_) {
+    auto kept_end = std::partition(
         methods_.begin(),
         methods_.end(),
-        [&alloc](ArtMethod* method) { return alloc.ContainsUnsafe(method); });
+        [&alloc](ArtMethod* method) { return !alloc.ContainsUnsafe(method); });
+    for (auto it = kept_end; it != methods_.end(); it++) {
+      VLOG(jit) << "JIT removed (JNI) " << (*it)->PrettyMethod() << ": " << code_;
+    }
     methods_.erase(kept_end, methods_.end());
   }
 
-  bool RemoveMethod(ArtMethod* method) {
+  bool RemoveMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
     auto it = std::find(methods_.begin(), methods_.end(), method);
     if (it != methods_.end()) {
+      VLOG(jit) << "JIT removed (JNI) " << (*it)->PrettyMethod() << ": " << code_;
       methods_.erase(it);
       return true;
     } else {
@@ -263,7 +268,8 @@
       collection_in_progress_(false),
       last_collection_increased_code_cache_(false),
       garbage_collect_code_(true),
-      number_of_compilations_(0),
+      number_of_baseline_compilations_(0),
+      number_of_optimized_compilations_(0),
       number_of_osr_compilations_(0),
       number_of_collections_(0),
       histogram_stack_map_memory_use_("Memory used for stack maps", 16),
@@ -281,17 +287,6 @@
   return PrivateRegionContainsPc(ptr) || shared_region_.IsInExecSpace(ptr);
 }
 
-bool JitCodeCache::WillExecuteJitCode(ArtMethod* method) {
-  ScopedObjectAccess soa(art::Thread::Current());
-  ScopedAssertNoThreadSuspension sants(__FUNCTION__);
-  if (ContainsPc(method->GetEntryPointFromQuickCompiledCode())) {
-    return true;
-  } else if (method->GetEntryPointFromQuickCompiledCode() == GetQuickInstrumentationEntryPoint()) {
-    return FindCompiledCodeForInstrumentation(method) != nullptr;
-  }
-  return false;
-}
-
 bool JitCodeCache::ContainsMethod(ArtMethod* method) {
   MutexLock mu(Thread::Current(), *Locks::jit_lock_);
   if (UNLIKELY(method->IsNative())) {
@@ -327,22 +322,6 @@
   return nullptr;
 }
 
-const void* JitCodeCache::FindCompiledCodeForInstrumentation(ArtMethod* method) {
-  // If jit-gc is still on we use the SavedEntryPoint field for doing that and so cannot use it to
-  // find the instrumentation entrypoint.
-  if (LIKELY(GetGarbageCollectCode())) {
-    return nullptr;
-  }
-  ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
-  if (info == nullptr) {
-    return nullptr;
-  }
-  // When GC is disabled for trampoline tracing we will use SavedEntrypoint to hold the actual
-  // jit-compiled version of the method. If jit-gc is disabled for other reasons this will just be
-  // nullptr.
-  return info->GetSavedEntryPoint();
-}
-
 const void* JitCodeCache::GetSavedEntryPointOfPreCompiledMethod(ArtMethod* method) {
   if (method->IsPreCompiled()) {
     const void* code_ptr = nullptr;
@@ -377,6 +356,11 @@
   return reinterpret_cast<uintptr_t>(code) - RoundUp(sizeof(OatQuickMethodHeader), alignment);
 }
 
+static const void* FromAllocationToCode(const uint8_t* alloc) {
+  size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
+  return reinterpret_cast<const void*>(alloc + RoundUp(sizeof(OatQuickMethodHeader), alignment));
+}
+
 static uint32_t GetNumberOfRoots(const uint8_t* stack_map) {
   // The length of the table is stored just before the stack map (and therefore at the end of
   // the table itself), in order to be able to fetch it from a `stack_map` pointer.
@@ -449,7 +433,8 @@
     }
   }
   // Walk over inline caches to clear entries containing unloaded classes.
-  for (ProfilingInfo* info : profiling_infos_) {
+  for (auto it : profiling_infos_) {
+    ProfilingInfo* info = it.second;
     for (size_t i = 0; i < info->number_of_inline_caches_; ++i) {
       InlineCache* cache = &info->cache_[i];
       for (size_t j = 0; j < InlineCache::kIndividualCacheSize; ++j) {
@@ -459,22 +444,18 @@
   }
 }
 
-void JitCodeCache::FreeCodeAndData(const void* code_ptr, bool free_debug_info) {
+void JitCodeCache::FreeCodeAndData(const void* code_ptr) {
   if (IsInZygoteExecSpace(code_ptr)) {
     // No need to free, this is shared memory.
     return;
   }
   uintptr_t allocation = FromCodeToAllocation(code_ptr);
-  if (free_debug_info) {
-    // Remove compressed mini-debug info for the method.
-    // TODO: This is expensive, so we should always do it in the caller in bulk.
-    RemoveNativeDebugInfoForJit(ArrayRef<const void*>(&code_ptr, 1));
-  }
+  const uint8_t* data = nullptr;
   if (OatQuickMethodHeader::FromCodePointer(code_ptr)->IsOptimized()) {
-    private_region_.FreeData(GetRootTable(code_ptr));
+    data = GetRootTable(code_ptr);
   }  // else this is a JNI stub without any data.
 
-  private_region_.FreeCode(reinterpret_cast<uint8_t*>(allocation));
+  FreeLocked(&private_region_, reinterpret_cast<uint8_t*>(allocation), data);
 }
 
 void JitCodeCache::FreeAllMethodHeaders(
@@ -483,25 +464,42 @@
   // first since once we do FreeCode() below, the memory can be reused
   // so it's possible for the same method_header to start representing
   // different compile code.
-  MutexLock mu(Thread::Current(), *Locks::jit_lock_);
   {
     MutexLock mu2(Thread::Current(), *Locks::cha_lock_);
     Runtime::Current()->GetClassLinker()->GetClassHierarchyAnalysis()
         ->RemoveDependentsWithMethodHeaders(method_headers);
   }
 
-  // Remove compressed mini-debug info for the methods.
-  std::vector<const void*> removed_symbols;
-  removed_symbols.reserve(method_headers.size());
-  for (const OatQuickMethodHeader* method_header : method_headers) {
-    removed_symbols.push_back(method_header->GetCode());
-  }
-  std::sort(removed_symbols.begin(), removed_symbols.end());
-  RemoveNativeDebugInfoForJit(ArrayRef<const void*>(removed_symbols));
-
   ScopedCodeCacheWrite scc(private_region_);
   for (const OatQuickMethodHeader* method_header : method_headers) {
-    FreeCodeAndData(method_header->GetCode(), /*free_debug_info=*/ false);
+    FreeCodeAndData(method_header->GetCode());
+  }
+
+  // We have potentially removed a lot of debug info. Do maintenance pass to save space.
+  RepackNativeDebugInfoForJit();
+
+  // Check that the set of compiled methods exactly matches native debug information.
+  // Does not check zygote methods since they can change concurrently.
+  if (kIsDebugBuild && !Runtime::Current()->IsZygote()) {
+    std::map<const void*, ArtMethod*> compiled_methods;
+    VisitAllMethods([&](const void* addr, ArtMethod* method) {
+      if (!IsInZygoteExecSpace(addr)) {
+        CHECK(addr != nullptr && method != nullptr);
+        compiled_methods.emplace(addr, method);
+      }
+    });
+    std::set<const void*> debug_info;
+    ForEachNativeDebugSymbol([&](const void* addr, size_t, const char* name) {
+      addr = AlignDown(addr, GetInstructionSetInstructionAlignment(kRuntimeISA));  // Thumb-bit.
+      CHECK(debug_info.emplace(addr).second) << "Duplicate debug info: " << addr << " " << name;
+      CHECK_EQ(compiled_methods.count(addr), 1u) << "Extra debug info: " << addr << " " << name;
+    });
+    if (!debug_info.empty()) {  // If debug-info generation is enabled.
+      for (auto it : compiled_methods) {
+        CHECK_EQ(debug_info.count(it.first), 1u) << "No debug info: " << it.second->PrettyMethod();
+      }
+      CHECK_EQ(compiled_methods.size(), debug_info.size());
+    }
   }
 }
 
@@ -531,6 +529,7 @@
       for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
         if (alloc.ContainsUnsafe(it->second)) {
           method_headers.insert(OatQuickMethodHeader::FromCodePointer(it->first));
+          VLOG(jit) << "JIT removed " << it->second->PrettyMethod() << ": " << it->first;
           it = method_code_map_.erase(it);
         } else {
           ++it;
@@ -547,17 +546,16 @@
       }
     }
     for (auto it = profiling_infos_.begin(); it != profiling_infos_.end();) {
-      ProfilingInfo* info = *it;
+      ProfilingInfo* info = it->second;
       if (alloc.ContainsUnsafe(info->GetMethod())) {
-        info->GetMethod()->SetProfilingInfo(nullptr);
         private_region_.FreeWritableData(reinterpret_cast<uint8_t*>(info));
         it = profiling_infos_.erase(it);
       } else {
         ++it;
       }
     }
+    FreeAllMethodHeaders(method_headers);
   }
-  FreeAllMethodHeaders(method_headers);
 }
 
 bool JitCodeCache::IsWeakAccessEnabled(Thread* self) const {
@@ -594,17 +592,20 @@
   is_weak_access_enabled_.store(false, std::memory_order_seq_cst);
 }
 
-void JitCodeCache::CopyInlineCacheInto(const InlineCache& ic,
-                                       Handle<mirror::ObjectArray<mirror::Class>> array) {
+void JitCodeCache::CopyInlineCacheInto(
+    const InlineCache& ic,
+    /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes) {
+  static_assert(arraysize(ic.classes_) == InlineCache::kIndividualCacheSize);
+  DCHECK_EQ(classes->NumberOfReferences(), InlineCache::kIndividualCacheSize);
+  DCHECK_EQ(classes->RemainingSlots(), InlineCache::kIndividualCacheSize);
   WaitUntilInlineCacheAccessible(Thread::Current());
   // Note that we don't need to lock `lock_` here, the compiler calling
   // this method has already ensured the inline cache will not be deleted.
-  for (size_t in_cache = 0, in_array = 0;
-       in_cache < InlineCache::kIndividualCacheSize;
-       ++in_cache) {
-    mirror::Class* object = ic.classes_[in_cache].Read();
+  for (const GcRoot<mirror::Class>& root : ic.classes_) {
+    mirror::Class* object = root.Read();
     if (object != nullptr) {
-      array->Set(in_array++, object);
+      DCHECK_NE(classes->RemainingSlots(), 0u);
+      classes->NewHandle(object);
     }
   }
 }
@@ -642,10 +643,12 @@
                           ArrayRef<const uint8_t> reserved_data,
                           const std::vector<Handle<mirror::Object>>& roots,
                           ArrayRef<const uint8_t> stack_map,
-                          bool osr,
+                          const std::vector<uint8_t>& debug_info,
+                          bool is_full_debug_info,
+                          CompilationKind compilation_kind,
                           bool has_should_deoptimize_flag,
                           const ArenaSet<ArtMethod*>& cha_single_implementation_list) {
-  DCHECK(!method->IsNative() || !osr);
+  DCHECK(!method->IsNative() || (compilation_kind != CompilationKind::kOsr));
 
   if (!method->IsNative()) {
     // We need to do this before grabbing the lock_ because it needs to be able to see the string
@@ -673,7 +676,24 @@
     return false;
   }
 
-  number_of_compilations_++;
+  switch (compilation_kind) {
+    case CompilationKind::kOsr:
+      number_of_osr_compilations_++;
+      break;
+    case CompilationKind::kBaseline:
+      number_of_baseline_compilations_++;
+      break;
+    case CompilationKind::kOptimized:
+      number_of_optimized_compilations_++;
+      break;
+  }
+
+  // We need to update the debug info before the entry point gets set.
+  // At the same time we want to do under JIT lock so that debug info and JIT maps are in sync.
+  if (!debug_info.empty()) {
+    // NB: Don't allow packing of full info since it would remove non-backtrace data.
+    AddNativeDebugInfoForJit(code_ptr, debug_info, /*allow_packing=*/ !is_full_debug_info);
+  }
 
   // We need to update the entry point in the runnable state for the instrumentation.
   {
@@ -721,8 +741,7 @@
       } else {
         method_code_map_.Put(code_ptr, method);
       }
-      if (osr) {
-        number_of_osr_compilations_++;
+      if (compilation_kind == CompilationKind::kOsr) {
         osr_code_map_.Put(method, code_ptr);
       } else if (NeedsClinitCheckBeforeCall(method) &&
                  !method->GetDeclaringClass()->IsVisiblyInitialized()) {
@@ -745,7 +764,7 @@
       GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(code_ptr));
     }
     VLOG(jit)
-        << "JIT added (osr=" << std::boolalpha << osr << std::noboolalpha << ") "
+        << "JIT added (kind=" << compilation_kind << ") "
         << ArtMethod::PrettyMethod(method) << "@" << method
         << " ccache_size=" << PrettySize(CodeCacheSizeLocked()) << ": "
         << " dcache_size=" << PrettySize(DataCacheSizeLocked()) << ": "
@@ -788,11 +807,10 @@
 
 bool JitCodeCache::RemoveMethodLocked(ArtMethod* method, bool release_memory) {
   if (LIKELY(!method->IsNative())) {
-    ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
-    if (info != nullptr) {
-      RemoveElement(profiling_infos_, info);
+    auto it = profiling_infos_.find(method);
+    if (it != profiling_infos_.end()) {
+      profiling_infos_.erase(it);
     }
-    method->SetProfilingInfo(nullptr);
   }
 
   bool in_cache = false;
@@ -817,6 +835,7 @@
         if (release_memory) {
           FreeCodeAndData(it->first);
         }
+        VLOG(jit) << "JIT removed " << it->second->PrettyMethod() << ": " << it->first;
         it = method_code_map_.erase(it);
       } else {
         ++it;
@@ -856,19 +875,6 @@
     }
     return;
   }
-  // Update ProfilingInfo to the new one and remove it from the old_method.
-  if (old_method->GetProfilingInfo(kRuntimePointerSize) != nullptr) {
-    DCHECK_EQ(old_method->GetProfilingInfo(kRuntimePointerSize)->GetMethod(), old_method);
-    ProfilingInfo* info = old_method->GetProfilingInfo(kRuntimePointerSize);
-    old_method->SetProfilingInfo(nullptr);
-    // Since the JIT should be paused and all threads suspended by the time this is called these
-    // checks should always pass.
-    DCHECK(!info->IsInUseByCompiler());
-    new_method->SetProfilingInfo(info);
-    // Get rid of the old saved entrypoint if it is there.
-    info->SetSavedEntryPoint(nullptr);
-    info->method_ = new_method;
-  }
   // Update method_code_map_ to point to the new method.
   for (auto& it : method_code_map_) {
     if (it.second == old_method) {
@@ -936,8 +942,8 @@
 
   const uint8_t* code;
   const uint8_t* data;
-  // We might need to try the allocation twice (with GC in between to free up memory).
-  for (int i = 0; i < 2; i++) {
+  while (true) {
+    bool at_max_capacity = false;
     {
       ScopedThreadSuspension sts(self, kSuspended);
       MutexLock mu(self, *Locks::jit_lock_);
@@ -945,18 +951,23 @@
       ScopedCodeCacheWrite ccw(*region);
       code = region->AllocateCode(code_size);
       data = region->AllocateData(data_size);
+      at_max_capacity = IsAtMaxCapacity();
     }
-    if (code == nullptr || data == nullptr) {
-      Free(self, region, code, data);
-      if (i == 0) {
-        GarbageCollectCache(self);
-        continue;  // Retry after GC.
-      } else {
-        return false;  // Fail.
-      }
+    if (code != nullptr && data != nullptr) {
+      break;
     }
-    break;  // Success.
+    Free(self, region, code, data);
+    if (at_max_capacity) {
+      VLOG(jit) << "JIT failed to allocate code of size "
+                << PrettySize(code_size)
+                << ", and data of size "
+                << PrettySize(data_size);
+      return false;
+    }
+    // Run a code cache collection and try again.
+    GarbageCollectCache(self);
   }
+
   *reserved_code = ArrayRef<const uint8_t>(code, code_size);
   *reserved_data = ArrayRef<const uint8_t>(data, data_size);
 
@@ -984,7 +995,12 @@
                         const uint8_t* data) {
   MutexLock mu(self, *Locks::jit_lock_);
   ScopedCodeCacheWrite ccw(*region);
+  FreeLocked(region, code, data);
+}
+
+void JitCodeCache::FreeLocked(JitMemoryRegion* region, const uint8_t* code, const uint8_t* data) {
   if (code != nullptr) {
+    RemoveNativeDebugInfoForJit(reinterpret_cast<const void*>(FromAllocationToCode(code)));
     region->FreeCode(code);
   }
   if (data != nullptr) {
@@ -1021,7 +1037,7 @@
     if (kIsDebugBuild) {
       // The stack walking code queries the side instrumentation stack if it
       // sees an instrumentation exit pc, so the JIT code of methods in that stack
-      // must have been seen. We sanity check this below.
+      // must have been seen. We check this below.
       for (const auto& it : *thread->GetInstrumentationStack()) {
         // The 'method_' in InstrumentationStackFrame is the one that has return_pc_ in
         // its stack frame, it is not the method owning return_pc_. We just pass null to
@@ -1061,8 +1077,12 @@
   }
 }
 
+bool JitCodeCache::IsAtMaxCapacity() const {
+  return private_region_.GetCurrentCapacity() == private_region_.GetMaxCapacity();
+}
+
 bool JitCodeCache::ShouldDoFullCollection() {
-  if (private_region_.GetCurrentCapacity() == private_region_.GetMaxCapacity()) {
+  if (IsAtMaxCapacity()) {
     // Always do a full collection when the code cache is full.
     return true;
   } else if (private_region_.GetCurrentCapacity() < kReservedCapacity) {
@@ -1138,25 +1158,8 @@
 
       // Start polling the liveness of compiled code to prepare for the next full collection.
       if (next_collection_will_be_full) {
-        if (Runtime::Current()->GetJITOptions()->CanCompileBaseline()) {
-          for (ProfilingInfo* info : profiling_infos_) {
-            info->SetBaselineHotnessCount(0);
-          }
-        } else {
-          // Save the entry point of methods we have compiled, and update the entry
-          // point of those methods to the interpreter. If the method is invoked, the
-          // interpreter will update its entry point to the compiled code and call it.
-          for (ProfilingInfo* info : profiling_infos_) {
-            const void* entry_point = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
-            if (!IsInZygoteDataSpace(info) && ContainsPc(entry_point)) {
-              info->SetSavedEntryPoint(entry_point);
-              // Don't call Instrumentation::UpdateMethodsCode(), as it can check the declaring
-              // class of the method. We may be concurrently running a GC which makes accessing
-              // the class unsafe. We know it is OK to bypass the instrumentation as we've just
-              // checked that the current entry point is JIT compiled code.
-              info->GetMethod()->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
-            }
-          }
+        for (auto it : profiling_infos_) {
+          it.second->SetBaselineHotnessCount(0);
         }
 
         // Change entry points of native methods back to the GenericJNI entrypoint.
@@ -1199,6 +1202,9 @@
         ++it;
       } else {
         method_headers.insert(OatQuickMethodHeader::FromCodePointer(data->GetCode()));
+        for (ArtMethod* method : data->GetMethods()) {
+          VLOG(jit) << "JIT removed (JNI) " << method->PrettyMethod() << ": " << data->GetCode();
+        }
         it = jni_stubs_map_.erase(it);
       }
     }
@@ -1210,11 +1216,12 @@
       } else {
         OatQuickMethodHeader* header = OatQuickMethodHeader::FromCodePointer(code_ptr);
         method_headers.insert(header);
+        VLOG(jit) << "JIT removed " << it->second->PrettyMethod() << ": " << it->first;
         it = method_code_map_.erase(it);
       }
     }
+    FreeAllMethodHeaders(method_headers);
   }
-  FreeAllMethodHeaders(method_headers);
 }
 
 bool JitCodeCache::GetGarbageCollectCode() {
@@ -1225,71 +1232,81 @@
 void JitCodeCache::SetGarbageCollectCode(bool value) {
   Thread* self = Thread::Current();
   MutexLock mu(self, *Locks::jit_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;
+  // Update the flag while holding the lock to ensure no thread will try to GC.
+  garbage_collect_code_ = value;
+}
+
+void JitCodeCache::RemoveMethodBeingCompiled(ArtMethod* method, CompilationKind kind) {
+  DCHECK(IsMethodBeingCompiled(method, kind));
+  switch (kind) {
+    case CompilationKind::kOsr:
+      current_osr_compilations_.erase(method);
+      break;
+    case CompilationKind::kBaseline:
+      current_baseline_compilations_.erase(method);
+      break;
+    case CompilationKind::kOptimized:
+      current_optimized_compilations_.erase(method);
+      break;
   }
 }
 
+void JitCodeCache::AddMethodBeingCompiled(ArtMethod* method, CompilationKind kind) {
+  DCHECK(!IsMethodBeingCompiled(method, kind));
+  switch (kind) {
+    case CompilationKind::kOsr:
+      current_osr_compilations_.insert(method);
+      break;
+    case CompilationKind::kBaseline:
+      current_baseline_compilations_.insert(method);
+      break;
+    case CompilationKind::kOptimized:
+      current_optimized_compilations_.insert(method);
+      break;
+  }
+}
+
+bool JitCodeCache::IsMethodBeingCompiled(ArtMethod* method, CompilationKind kind) {
+  switch (kind) {
+    case CompilationKind::kOsr:
+      return ContainsElement(current_osr_compilations_, method);
+    case CompilationKind::kBaseline:
+      return ContainsElement(current_baseline_compilations_, method);
+    case CompilationKind::kOptimized:
+      return ContainsElement(current_optimized_compilations_, method);
+  }
+}
+
+bool JitCodeCache::IsMethodBeingCompiled(ArtMethod* method) {
+  return ContainsElement(current_optimized_compilations_, method) ||
+      ContainsElement(current_osr_compilations_, method) ||
+      ContainsElement(current_baseline_compilations_, method);
+}
+
 void JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) {
   ScopedTrace trace(__FUNCTION__);
   {
     MutexLock mu(self, *Locks::jit_lock_);
 
-    if (Runtime::Current()->GetJITOptions()->CanCompileBaseline()) {
-      // Update to interpreter the methods that have baseline entrypoints and whose baseline
-      // hotness count is zero.
-      // Note that these methods may be in thread stack or concurrently revived
-      // between. That's OK, as the thread executing it will mark it.
-      for (ProfilingInfo* info : profiling_infos_) {
-        if (info->GetBaselineHotnessCount() == 0) {
-          const void* entry_point = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
-          if (ContainsPc(entry_point)) {
-            OatQuickMethodHeader* method_header =
-                OatQuickMethodHeader::FromEntryPoint(entry_point);
-            if (CodeInfo::IsBaseline(method_header->GetOptimizedCodeInfoPtr())) {
-              info->GetMethod()->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
-            }
+    // Update to interpreter the methods that have baseline entrypoints and whose baseline
+    // hotness count is zero.
+    // Note that these methods may be in thread stack or concurrently revived
+    // between. That's OK, as the thread executing it will mark it.
+    for (auto it : profiling_infos_) {
+      ProfilingInfo* info = it.second;
+      if (info->GetBaselineHotnessCount() == 0) {
+        const void* entry_point = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
+        if (ContainsPc(entry_point)) {
+          OatQuickMethodHeader* method_header =
+              OatQuickMethodHeader::FromEntryPoint(entry_point);
+          if (CodeInfo::IsBaseline(method_header->GetOptimizedCodeInfoPtr())) {
+            info->GetMethod()->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
           }
         }
       }
-      // TODO: collect profiling info
-      // TODO: collect optimized code?
-    } else {
-      if (collect_profiling_info) {
-        // Clear the profiling info of methods that do not have compiled code as entrypoint.
-        // Also remove the saved entry point from the ProfilingInfo objects.
-        for (ProfilingInfo* info : profiling_infos_) {
-          const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
-          if (!ContainsPc(ptr) && !info->IsInUseByCompiler() && !IsInZygoteDataSpace(info)) {
-            info->GetMethod()->SetProfilingInfo(nullptr);
-          }
-
-          if (info->GetSavedEntryPoint() != nullptr) {
-            info->SetSavedEntryPoint(nullptr);
-            // We are going to move this method back to interpreter. Clear the counter now to
-            // give it a chance to be hot again.
-            ClearMethodCounter(info->GetMethod(), /*was_warm=*/ true);
-          }
-        }
-      } else if (kIsDebugBuild) {
-        // Sanity check that the profiling infos do not have a dangling entry point.
-        for (ProfilingInfo* info : profiling_infos_) {
-          DCHECK(!Runtime::Current()->IsZygote());
-          const void* entry_point = info->GetSavedEntryPoint();
-          DCHECK(entry_point == nullptr || IsInZygoteExecSpace(entry_point));
-        }
-      }
     }
+    // TODO: collect profiling info
+    // TODO: collect optimized code
 
     // Mark compiled code that are entrypoints of ArtMethods. Compiled code that is not
     // an entry point is either:
@@ -1335,28 +1352,7 @@
   RemoveUnmarkedCode(self);
 
   if (collect_profiling_info) {
-    MutexLock mu(self, *Locks::jit_lock_);
-    // Free all profiling infos of methods not compiled nor being compiled.
-    auto profiling_kept_end = std::remove_if(profiling_infos_.begin(), profiling_infos_.end(),
-      [this] (ProfilingInfo* info) NO_THREAD_SAFETY_ANALYSIS {
-        const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
-        // We have previously cleared the ProfilingInfo pointer in the ArtMethod in the hope
-        // that the compiled code would not get revived. As mutator threads run concurrently,
-        // they may have revived the compiled code, and now we are in the situation where
-        // a method has compiled code but no ProfilingInfo.
-        // We make sure compiled methods have a ProfilingInfo object. It is needed for
-        // code cache collection.
-        if (ContainsPc(ptr) &&
-            info->GetMethod()->GetProfilingInfo(kRuntimePointerSize) == nullptr) {
-          info->GetMethod()->SetProfilingInfo(info);
-        } else if (info->GetMethod()->GetProfilingInfo(kRuntimePointerSize) != info) {
-          // No need for this ProfilingInfo object anymore.
-          private_region_.FreeWritableData(reinterpret_cast<uint8_t*>(info));
-          return true;
-        }
-        return false;
-      });
-    profiling_infos_.erase(profiling_kept_end, profiling_infos_.end());
+    // TODO: Collect unused profiling infos.
   }
 }
 
@@ -1440,30 +1436,18 @@
 
 ProfilingInfo* JitCodeCache::AddProfilingInfo(Thread* self,
                                               ArtMethod* method,
-                                              const std::vector<uint32_t>& entries,
-                                              bool retry_allocation)
-    // No thread safety analysis as we are using TryLock/Unlock explicitly.
-    NO_THREAD_SAFETY_ANALYSIS {
+                                              const std::vector<uint32_t>& entries) {
   DCHECK(CanAllocateProfilingInfo());
   ProfilingInfo* info = nullptr;
-  if (!retry_allocation) {
-    // If we are allocating for the interpreter, just try to lock, to avoid
-    // lock contention with the JIT.
-    if (Locks::jit_lock_->ExclusiveTryLock(self)) {
-      info = AddProfilingInfoInternal(self, method, entries);
-      Locks::jit_lock_->ExclusiveUnlock(self);
-    }
-  } else {
-    {
-      MutexLock mu(self, *Locks::jit_lock_);
-      info = AddProfilingInfoInternal(self, method, entries);
-    }
+  {
+    MutexLock mu(self, *Locks::jit_lock_);
+    info = AddProfilingInfoInternal(self, method, entries);
+  }
 
-    if (info == nullptr) {
-      GarbageCollectCache(self);
-      MutexLock mu(self, *Locks::jit_lock_);
-      info = AddProfilingInfoInternal(self, method, entries);
-    }
+  if (info == nullptr) {
+    GarbageCollectCache(self);
+    MutexLock mu(self, *Locks::jit_lock_);
+    info = AddProfilingInfoInternal(self, method, entries);
   }
   return info;
 }
@@ -1471,29 +1455,24 @@
 ProfilingInfo* JitCodeCache::AddProfilingInfoInternal(Thread* self ATTRIBUTE_UNUSED,
                                                       ArtMethod* method,
                                                       const std::vector<uint32_t>& entries) {
+  // Check whether some other thread has concurrently created it.
+  auto it = profiling_infos_.find(method);
+  if (it != profiling_infos_.end()) {
+    return it->second;
+  }
+
   size_t profile_info_size = RoundUp(
       sizeof(ProfilingInfo) + sizeof(InlineCache) * entries.size(),
       sizeof(void*));
 
-  // Check whether some other thread has concurrently created it.
-  ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
-  if (info != nullptr) {
-    return info;
-  }
-
   const uint8_t* data = private_region_.AllocateData(profile_info_size);
   if (data == nullptr) {
     return nullptr;
   }
   uint8_t* writable_data = private_region_.GetWritableDataAddress(data);
-  info = new (writable_data) ProfilingInfo(method, entries);
+  ProfilingInfo* info = new (writable_data) ProfilingInfo(method, entries);
 
-  // Make sure other threads see the data in the profiling info object before the
-  // store in the ArtMethod's ProfilingInfo pointer.
-  std::atomic_thread_fence(std::memory_order_release);
-
-  method->SetProfilingInfo(info);
-  profiling_infos_.push_back(info);
+  profiling_infos_.Put(method, info);
   histogram_profiling_info_memory_use_.AddValue(profile_info_size);
   return info;
 }
@@ -1511,7 +1490,8 @@
   MutexLock mu(self, *Locks::jit_lock_);
   ScopedTrace trace(__FUNCTION__);
   uint16_t jit_compile_threshold = Runtime::Current()->GetJITOptions()->GetCompileThreshold();
-  for (const ProfilingInfo* info : profiling_infos_) {
+  for (auto it : profiling_infos_) {
+    ProfilingInfo* info = it.second;
     ArtMethod* method = info->GetMethod();
     const DexFile* dex_file = method->GetDexFile();
     const std::string base_location = DexFileLoader::GetBaseLocation(dex_file->GetLocation());
@@ -1595,19 +1575,18 @@
 
 bool JitCodeCache::NotifyCompilationOf(ArtMethod* method,
                                        Thread* self,
-                                       bool osr,
-                                       bool prejit,
-                                       bool baseline,
-                                       JitMemoryRegion* region) {
+                                       CompilationKind compilation_kind,
+                                       bool prejit) {
   const void* existing_entry_point = method->GetEntryPointFromQuickCompiledCode();
-  if (!osr && ContainsPc(existing_entry_point)) {
+  if (compilation_kind != CompilationKind::kOsr && ContainsPc(existing_entry_point)) {
     OatQuickMethodHeader* method_header =
         OatQuickMethodHeader::FromEntryPoint(existing_entry_point);
-    if (CodeInfo::IsBaseline(method_header->GetOptimizedCodeInfoPtr()) == baseline) {
+    bool is_baseline = (compilation_kind == CompilationKind::kBaseline);
+    if (CodeInfo::IsBaseline(method_header->GetOptimizedCodeInfoPtr()) == is_baseline) {
       VLOG(jit) << "Not compiling "
                 << method->PrettyMethod()
                 << " because it has already been compiled"
-                << " baseline=" << std::boolalpha << baseline;
+                << " kind=" << compilation_kind;
       return false;
     }
   }
@@ -1635,7 +1614,7 @@
     }
   }
 
-  if (osr) {
+  if (compilation_kind == CompilationKind::kOsr) {
     MutexLock mu(self, *Locks::jit_lock_);
     if (osr_code_map_.find(method) != osr_code_map_.end()) {
       return false;
@@ -1671,53 +1650,52 @@
     }
     return new_compilation;
   } else {
-    ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
-    if (CanAllocateProfilingInfo() && baseline && info == nullptr) {
-      // We can retry allocation here as we're the JIT thread.
-      if (ProfilingInfo::Create(self, method, /* retry_allocation= */ true)) {
-        info = method->GetProfilingInfo(kRuntimePointerSize);
+    if (CanAllocateProfilingInfo() && (compilation_kind == CompilationKind::kBaseline)) {
+      bool has_profiling_info = false;
+      {
+        MutexLock mu(self, *Locks::jit_lock_);
+        has_profiling_info = (profiling_infos_.find(method) != profiling_infos_.end());
+      }
+      if (!has_profiling_info) {
+        if (ProfilingInfo::Create(self, method) == nullptr) {
+          VLOG(jit) << method->PrettyMethod() << " needs a ProfilingInfo to be compiled baseline";
+          ClearMethodCounter(method, /*was_warm=*/ false);
+          return false;
+        }
       }
     }
-    if (info == nullptr) {
-      // When prejitting, we don't allocate a profiling info.
-      if (!prejit && !IsSharedRegion(*region)) {
-        VLOG(jit) << method->PrettyMethod() << " needs a ProfilingInfo to be compiled";
-        // Because the counter is not atomic, there are some rare cases where we may not hit the
-        // threshold for creating the ProfilingInfo. Reset the counter now to "correct" this.
-        ClearMethodCounter(method, /*was_warm=*/ false);
-        return false;
-      }
-    } else {
-      MutexLock mu(self, *Locks::jit_lock_);
-      if (info->IsMethodBeingCompiled(osr)) {
-        return false;
-      }
-      info->SetIsMethodBeingCompiled(true, osr);
+    MutexLock mu(self, *Locks::jit_lock_);
+    if (IsMethodBeingCompiled(method, compilation_kind)) {
+      return false;
     }
+    AddMethodBeingCompiled(method, compilation_kind);
     return true;
   }
 }
 
 ProfilingInfo* JitCodeCache::NotifyCompilerUse(ArtMethod* method, Thread* self) {
   MutexLock mu(self, *Locks::jit_lock_);
-  ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
-  if (info != nullptr) {
-    if (!info->IncrementInlineUse()) {
-      // Overflow of inlining uses, just bail.
-      return nullptr;
-    }
+  auto it = profiling_infos_.find(method);
+  if (it == profiling_infos_.end()) {
+    return nullptr;
   }
-  return info;
+  if (!it->second->IncrementInlineUse()) {
+    // Overflow of inlining uses, just bail.
+    return nullptr;
+  }
+  return it->second;
 }
 
 void JitCodeCache::DoneCompilerUse(ArtMethod* method, Thread* self) {
   MutexLock mu(self, *Locks::jit_lock_);
-  ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
-  DCHECK(info != nullptr);
-  info->DecrementInlineUse();
+  auto it = profiling_infos_.find(method);
+  DCHECK(it != profiling_infos_.end());
+  it->second->DecrementInlineUse();
 }
 
-void JitCodeCache::DoneCompiling(ArtMethod* method, Thread* self, bool osr) {
+void JitCodeCache::DoneCompiling(ArtMethod* method,
+                                 Thread* self,
+                                 CompilationKind compilation_kind) {
   DCHECK_EQ(Thread::Current(), self);
   MutexLock mu(self, *Locks::jit_lock_);
   if (UNLIKELY(method->IsNative())) {
@@ -1730,48 +1708,32 @@
       jni_stubs_map_.erase(it);  // Remove the entry added in NotifyCompilationOf().
     }  // else Commit() updated entrypoints of all methods in the JniStubData.
   } else {
-    ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
-    if (info != nullptr) {
-      DCHECK(info->IsMethodBeingCompiled(osr));
-      info->SetIsMethodBeingCompiled(false, osr);
-    }
+    RemoveMethodBeingCompiled(method, compilation_kind);
   }
 }
 
 void JitCodeCache::InvalidateAllCompiledCode() {
   art::MutexLock mu(Thread::Current(), *Locks::jit_lock_);
-  size_t cnt = profiling_infos_.size();
-  size_t osr_size = osr_code_map_.size();
-  for (ProfilingInfo* pi : profiling_infos_) {
-    // NB Due to OSR we might run this on some methods multiple times but this should be fine.
-    ArtMethod* meth = pi->GetMethod();
-    pi->SetSavedEntryPoint(nullptr);
-    // We had a ProfilingInfo so we must be warm.
+  VLOG(jit) << "Invalidating all compiled code";
+  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  for (auto it : method_code_map_) {
+    ArtMethod* meth = it.second;
+    // We were compiled, so we must be warm.
     ClearMethodCounter(meth, /*was_warm=*/true);
-    ClassLinker* linker = Runtime::Current()->GetClassLinker();
     if (meth->IsObsolete()) {
       linker->SetEntryPointsForObsoleteMethod(meth);
     } else {
       linker->SetEntryPointsToInterpreter(meth);
     }
   }
+  saved_compiled_methods_map_.clear();
   osr_code_map_.clear();
-  VLOG(jit) << "Invalidated the compiled code of " << (cnt - osr_size) << " methods and "
-            << osr_size << " OSRs.";
 }
 
 void JitCodeCache::InvalidateCompiledCodeFor(ArtMethod* method,
                                              const OatQuickMethodHeader* header) {
   DCHECK(!method->IsNative());
-  ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize);
   const void* method_entrypoint = method->GetEntryPointFromQuickCompiledCode();
-  if ((profiling_info != nullptr) &&
-      (profiling_info->GetSavedEntryPoint() == header->GetEntryPoint())) {
-    // When instrumentation is set, the actual entrypoint is the one in the profiling info.
-    method_entrypoint = profiling_info->GetSavedEntryPoint();
-    // Prevent future uses of the compiled code.
-    profiling_info->SetSavedEntryPoint(nullptr);
-  }
 
   // Clear the method counter if we are running jitted code since we might want to jit this again in
   // the future.
@@ -1780,7 +1742,7 @@
     // and clear the counter to get the method Jitted again.
     Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
         method, GetQuickToInterpreterBridge());
-    ClearMethodCounter(method, /*was_warm=*/ profiling_info != nullptr);
+    ClearMethodCounter(method, /*was_warm=*/ true);
   } else {
     MutexLock mu(Thread::Current(), *Locks::jit_lock_);
     auto it = osr_code_map_.find(method);
@@ -1817,7 +1779,8 @@
      << "Current JIT capacity: " << PrettySize(GetCurrentRegion()->GetCurrentCapacity()) << "\n"
      << "Current number of JIT JNI stub entries: " << jni_stubs_map_.size() << "\n"
      << "Current number of JIT code cache entries: " << method_code_map_.size() << "\n"
-     << "Total number of JIT compilations: " << number_of_compilations_ << "\n"
+     << "Total number of JIT baseline compilations: " << number_of_baseline_compilations_ << "\n"
+     << "Total number of JIT optimized compilations: " << number_of_optimized_compilations_ << "\n"
      << "Total number of JIT compilations for on stack replacement: "
         << number_of_osr_compilations_ << "\n"
      << "Total number of JIT code cache collections: " << number_of_collections_ << std::endl;
@@ -1851,7 +1814,8 @@
   }
 
   // Reset all statistics to be specific to this process.
-  number_of_compilations_ = 0;
+  number_of_baseline_compilations_ = 0;
+  number_of_optimized_compilations_ = 0;
   number_of_osr_compilations_ = 0;
   number_of_collections_ = 0;
   histogram_stack_map_memory_use_.Reset();
@@ -1874,6 +1838,28 @@
   return Runtime::Current()->IsZygote() ? &shared_region_ : &private_region_;
 }
 
+void JitCodeCache::VisitAllMethods(const std::function<void(const void*, ArtMethod*)>& cb) {
+  for (const auto& it : jni_stubs_map_) {
+    const JniStubData& data = it.second;
+    if (data.IsCompiled()) {
+      for (ArtMethod* method : data.GetMethods()) {
+        cb(data.GetCode(), method);
+      }
+    }
+  }
+  for (auto it : method_code_map_) {  // Includes OSR methods.
+    cb(it.first, it.second);
+  }
+  for (auto it : saved_compiled_methods_map_) {
+    cb(it.second, it.first);
+  }
+  for (auto it : zygote_map_) {
+    if (it.code_ptr != nullptr && it.method != nullptr) {
+      cb(it.code_ptr, it.method);
+    }
+  }
+}
+
 void ZygoteMap::Initialize(uint32_t number_of_methods) {
   MutexLock mu(Thread::Current(), *Locks::jit_lock_);
   // Allocate for 40-80% capacity. This will offer OK lookup times, and termination
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index f13e05c..76b7f77 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -32,7 +32,9 @@
 #include "base/mem_map.h"
 #include "base/mutex.h"
 #include "base/safe_map.h"
+#include "compilation_kind.h"
 #include "jit_memory_region.h"
+#include "profiling_info.h"
 
 namespace art {
 
@@ -195,10 +197,8 @@
 
   bool NotifyCompilationOf(ArtMethod* method,
                            Thread* self,
-                           bool osr,
-                           bool prejit,
-                           bool baseline,
-                           JitMemoryRegion* region)
+                           CompilationKind compilation_kind,
+                           bool prejit)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::jit_lock_);
 
@@ -214,7 +214,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::jit_lock_);
 
-  void DoneCompiling(ArtMethod* method, Thread* self, bool osr)
+  void DoneCompiling(ArtMethod* method, Thread* self, CompilationKind compilation_kind)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::jit_lock_);
 
@@ -228,10 +228,6 @@
   // Return true if the code cache contains this pc in the private region (i.e. not from zygote).
   bool PrivateRegionContainsPc(const void* pc) const;
 
-  // Returns true if either the method's entrypoint is JIT compiled code or it is the
-  // instrumentation entrypoint and we can jump to jit code for this method. For testing use only.
-  bool WillExecuteJitCode(ArtMethod* method) REQUIRES(!Locks::jit_lock_);
-
   // Return true if the code cache contains this method.
   bool ContainsMethod(ArtMethod* method) REQUIRES(!Locks::jit_lock_);
 
@@ -266,7 +262,9 @@
               ArrayRef<const uint8_t> reserved_data,  // Uninitialized destination.
               const std::vector<Handle<mirror::Object>>& roots,
               ArrayRef<const uint8_t> stack_map,      // Compiler output (source).
-              bool osr,
+              const std::vector<uint8_t>& debug_info,
+              bool is_full_debug_info,
+              CompilationKind compilation_kind,
               bool has_should_deoptimize_flag,
               const ArenaSet<ArtMethod*>& cha_single_implementation_list)
       REQUIRES_SHARED(Locks::mutator_lock_)
@@ -276,15 +274,18 @@
   void Free(Thread* self, JitMemoryRegion* region, const uint8_t* code, const uint8_t* data)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::jit_lock_);
+  void FreeLocked(JitMemoryRegion* region, const uint8_t* code, const uint8_t* data)
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(Locks::jit_lock_);
 
   // Perform a collection on the code cache.
   void GarbageCollectCache(Thread* self)
       REQUIRES(!Locks::jit_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Given the 'pc', try to find the JIT compiled code associated with it.
-  // Return null if 'pc' is not in the code cache. 'method' is passed for
-  // sanity check.
+  // Given the 'pc', try to find the JIT compiled code associated with it.  'method' may be null
+  // when LookupMethodHeader is called from MarkCodeClosure::Run() in debug builds.  Return null
+  // if 'pc' is not in the code cache.
   OatQuickMethodHeader* LookupMethodHeader(uintptr_t pc, ArtMethod* method)
       REQUIRES(!Locks::jit_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -305,16 +306,15 @@
       REQUIRES(!Locks::jit_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void CopyInlineCacheInto(const InlineCache& ic, Handle<mirror::ObjectArray<mirror::Class>> array)
+  void CopyInlineCacheInto(const InlineCache& ic,
+                           /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes)
       REQUIRES(!Locks::jit_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Create a 'ProfileInfo' for 'method'. If 'retry_allocation' is true,
-  // will collect and retry if the first allocation is unsuccessful.
+  // Create a 'ProfileInfo' for 'method'.
   ProfilingInfo* AddProfilingInfo(Thread* self,
                                   ArtMethod* method,
-                                  const std::vector<uint32_t>& entries,
-                                  bool retry_allocation)
+                                  const std::vector<uint32_t>& entries)
       REQUIRES(!Locks::jit_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -370,12 +370,6 @@
     return &zygote_map_;
   }
 
-  // If Jit-gc has been disabled (and instrumentation has been enabled) this will return the
-  // jit-compiled entrypoint for this method.  Otherwise it will return null.
-  const void* FindCompiledCodeForInstrumentation(ArtMethod* method)
-      REQUIRES(!Locks::jit_lock_)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Fetch the code of a method that was JITted, but the JIT could not
   // update its entrypoint due to the resolution trampoline.
   const void* GetSavedEntryPointOfPreCompiledMethod(ArtMethod* method)
@@ -427,7 +421,8 @@
 
   // Remove CHA dependents and underlying allocations for entries in `method_headers`.
   void FreeAllMethodHeaders(const std::unordered_set<OatQuickMethodHeader*>& method_headers)
-      REQUIRES(!Locks::jit_lock_)
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(Locks::jit_lock_)
       REQUIRES(!Locks::cha_lock_);
 
   // Removes method from the cache. The caller must ensure that all threads
@@ -436,10 +431,15 @@
       REQUIRES(Locks::jit_lock_)
       REQUIRES(Locks::mutator_lock_);
 
-  // Free code and data allocations for `code_ptr`.
-  void FreeCodeAndData(const void* code_ptr, bool free_debug_info = true)
+  // Call given callback for every compiled method in the code cache.
+  void VisitAllMethods(const std::function<void(const void*, ArtMethod*)>& cb)
       REQUIRES(Locks::jit_lock_);
 
+  // Free code and data allocations for `code_ptr`.
+  void FreeCodeAndData(const void* code_ptr)
+      REQUIRES(Locks::jit_lock_)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   // Number of bytes allocated in the code cache.
   size_t CodeCacheSize() REQUIRES(!Locks::jit_lock_);
 
@@ -455,6 +455,9 @@
   // Notify all waiting threads that a collection is done.
   void NotifyCollectionDone(Thread* self) REQUIRES(Locks::jit_lock_);
 
+  // Return whether the code cache's capacity is at its maximum.
+  bool IsAtMaxCapacity() const REQUIRES(Locks::jit_lock_);
+
   // Return whether we should do a full collection given the current state of the cache.
   bool ShouldDoFullCollection()
       REQUIRES(Locks::jit_lock_)
@@ -485,6 +488,21 @@
       REQUIRES(!Locks::jit_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  // Record that `method` is being compiled with the given mode.
+  void AddMethodBeingCompiled(ArtMethod* method, CompilationKind compilation_kind)
+      REQUIRES(Locks::jit_lock_);
+
+  // Remove `method` from the list of methods meing compiled with the given mode.
+  void RemoveMethodBeingCompiled(ArtMethod* method, CompilationKind compilation_kind)
+      REQUIRES(Locks::jit_lock_);
+
+  // Return whether `method` is being compiled with the given mode.
+  bool IsMethodBeingCompiled(ArtMethod* method, CompilationKind compilation_kind)
+      REQUIRES(Locks::jit_lock_);
+
+  // Return whether `method` is being compiled in any mode.
+  bool IsMethodBeingCompiled(ArtMethod* method) REQUIRES(Locks::jit_lock_);
+
   class JniStubKey;
   class JniStubData;
 
@@ -520,7 +538,12 @@
   SafeMap<ArtMethod*, const void*> osr_code_map_ GUARDED_BY(Locks::jit_lock_);
 
   // ProfilingInfo objects we have allocated.
-  std::vector<ProfilingInfo*> profiling_infos_ GUARDED_BY(Locks::jit_lock_);
+  SafeMap<ArtMethod*, ProfilingInfo*> profiling_infos_ GUARDED_BY(Locks::jit_lock_);
+
+  // Methods we are currently compiling, one set for each kind of compilation.
+  std::set<ArtMethod*> current_optimized_compilations_ GUARDED_BY(Locks::jit_lock_);
+  std::set<ArtMethod*> current_osr_compilations_ GUARDED_BY(Locks::jit_lock_);
+  std::set<ArtMethod*> current_baseline_compilations_ GUARDED_BY(Locks::jit_lock_);
 
   // Methods that the zygote has compiled and can be shared across processes
   // forked from the zygote.
@@ -545,8 +568,11 @@
 
   // ---------------- JIT statistics -------------------------------------- //
 
-  // Number of compilations done throughout the lifetime of the JIT.
-  size_t number_of_compilations_ GUARDED_BY(Locks::jit_lock_);
+  // Number of baseline compilations done throughout the lifetime of the JIT.
+  size_t number_of_baseline_compilations_ GUARDED_BY(Locks::jit_lock_);
+
+  // Number of optimized compilations done throughout the lifetime of the JIT.
+  size_t number_of_optimized_compilations_ GUARDED_BY(Locks::jit_lock_);
 
   // Number of compilations for on-stack-replacement done throughout the lifetime of the JIT.
   size_t number_of_osr_compilations_ GUARDED_BY(Locks::jit_lock_);
diff --git a/runtime/jit/jit_memory_region.cc b/runtime/jit/jit_memory_region.cc
index 09980c8..58a4041 100644
--- a/runtime/jit/jit_memory_region.cc
+++ b/runtime/jit/jit_memory_region.cc
@@ -199,7 +199,7 @@
       // is never executable.
       std::string name = exec_cache_name + "-rw";
       non_exec_pages = MemMap::MapFile(exec_capacity,
-                                       kProtR,
+                                       kIsDebugBuild ? kProtR : kProtRW,
                                        base_flags,
                                        mem_fd,
                                        /* start= */ data_capacity,
@@ -285,13 +285,12 @@
   if (code_heap != nullptr) {
     // Make all pages reserved for the code heap writable. The mspace allocator, that manages the
     // heap, will take and initialize pages in create_mspace_with_base().
-    CheckedCall(mprotect, "create code heap", code_heap->Begin(), code_heap->Size(), kProtRW);
-    exec_mspace_ = create_mspace_with_base(code_heap->Begin(), exec_end_, false /*locked*/);
+    {
+      ScopedCodeCacheWrite scc(*this);
+      exec_mspace_ = create_mspace_with_base(code_heap->Begin(), exec_end_, false /*locked*/);
+    }
     CHECK(exec_mspace_ != nullptr) << "create_mspace_with_base (exec) failed";
     SetFootprintLimit(current_capacity_);
-    // Protect pages containing heap metadata. Updates to the code heap toggle write permission to
-    // perform the update and there are no other times write access is required.
-    CheckedCall(mprotect, "protect code heap", code_heap->Begin(), code_heap->Size(), kProtR);
   } else {
     exec_mspace_ = nullptr;
     SetFootprintLimit(current_capacity_);
@@ -378,9 +377,7 @@
   // Write the header.
   OatQuickMethodHeader* method_header =
       OatQuickMethodHeader::FromCodePointer(w_memory + header_size);
-  new (method_header) OatQuickMethodHeader(
-      (stack_map != nullptr) ? result - stack_map : 0u,
-      code.size());
+  new (method_header) OatQuickMethodHeader((stack_map != nullptr) ? result - stack_map : 0u);
   if (has_should_deoptimize_flag) {
     method_header->SetHasShouldDeoptimizeFlag();
   }
@@ -534,9 +531,9 @@
   LOG(INFO) << "Falling back to ashmem implementation for JIT zygote mapping";
 
   int fd;
-  PaletteStatus status = PaletteAshmemCreateRegion(kRegionName, capacity, &fd);
-  if (status != PaletteStatus::kOkay) {
-    CHECK_EQ(status, PaletteStatus::kCheckErrno);
+  palette_status_t status = PaletteAshmemCreateRegion(kRegionName, capacity, &fd);
+  if (status != PALETTE_STATUS_OK) {
+    CHECK_EQ(status, PALETTE_STATUS_CHECK_ERRNO);
     std::ostringstream oss;
     oss << "Failed to create zygote mapping: " << strerror(errno);
     *error_msg = oss.str();
@@ -555,9 +552,9 @@
       return false;
     }
   } else {
-    PaletteStatus status = PaletteAshmemSetProtRegion(fd, PROT_READ);
-    if (status != PaletteStatus::kOkay) {
-      CHECK_EQ(status, PaletteStatus::kCheckErrno);
+    palette_status_t status = PaletteAshmemSetProtRegion(fd, PROT_READ);
+    if (status != PALETTE_STATUS_OK) {
+      CHECK_EQ(status, PALETTE_STATUS_CHECK_ERRNO);
       std::ostringstream oss;
       oss << "Failed to protect zygote mapping: " << strerror(errno);
       *error_msg = oss.str();
diff --git a/runtime/jit/jit_scoped_code_cache_write.h b/runtime/jit/jit_scoped_code_cache_write.h
index ea99bdf..e2adebf 100644
--- a/runtime/jit/jit_scoped_code_cache_write.h
+++ b/runtime/jit/jit_scoped_code_cache_write.h
@@ -38,20 +38,24 @@
   explicit ScopedCodeCacheWrite(const JitMemoryRegion& region)
       : ScopedTrace("ScopedCodeCacheWrite"),
         region_(region) {
-    ScopedTrace trace("mprotect all");
-    const MemMap* const updatable_pages = region.GetUpdatableCodeMapping();
-    if (updatable_pages != nullptr) {
-      int prot = region.HasDualCodeMapping() ? kProtRW : kProtRWX;
-      CheckedCall(mprotect, "Cache +W", updatable_pages->Begin(), updatable_pages->Size(), prot);
+    if (kIsDebugBuild || !region.HasDualCodeMapping()) {
+      ScopedTrace trace("mprotect all");
+      const MemMap* const updatable_pages = region.GetUpdatableCodeMapping();
+      if (updatable_pages != nullptr) {
+        int prot = region.HasDualCodeMapping() ? kProtRW : kProtRWX;
+        CheckedCall(mprotect, "Cache +W", updatable_pages->Begin(), updatable_pages->Size(), prot);
+      }
     }
   }
 
   ~ScopedCodeCacheWrite() {
-    ScopedTrace trace("mprotect code");
-    const MemMap* const updatable_pages = region_.GetUpdatableCodeMapping();
-    if (updatable_pages != nullptr) {
-      int prot = region_.HasDualCodeMapping() ? kProtR : kProtRX;
-      CheckedCall(mprotect, "Cache -W", updatable_pages->Begin(), updatable_pages->Size(), prot);
+    if (kIsDebugBuild || !region_.HasDualCodeMapping()) {
+      ScopedTrace trace("mprotect code");
+      const MemMap* const updatable_pages = region_.GetUpdatableCodeMapping();
+      if (updatable_pages != nullptr) {
+        int prot = region_.HasDualCodeMapping() ? kProtR : kProtRX;
+        CheckedCall(mprotect, "Cache -W", updatable_pages->Begin(), updatable_pages->Size(), prot);
+      }
     }
   }
 
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index fe551f3..425eadc 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -20,10 +20,12 @@
 #include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include "android-base/strings.h"
 
 #include "art_method-inl.h"
+#include "base/compiler_filter.h"
 #include "base/enums.h"
 #include "base/logging.h"  // For VLOG.
 #include "base/scoped_arena_containers.h"
@@ -31,12 +33,10 @@
 #include "base/systrace.h"
 #include "base/time_utils.h"
 #include "class_table-inl.h"
-#include "compiler_filter.h"
 #include "dex/dex_file_loader.h"
 #include "dex_reference_collection.h"
 #include "gc/collector_type.h"
 #include "gc/gc_cause.h"
-#include "gc/scoped_gc_critical_section.h"
 #include "jit/jit.h"
 #include "jit/profiling_info.h"
 #include "oat_file_manager.h"
@@ -81,10 +81,7 @@
 #endif
 }
 
-ProfileSaver::ProfileSaver(const ProfileSaverOptions& options,
-                           const std::string& output_filename,
-                           jit::JitCodeCache* jit_code_cache,
-                           const std::vector<std::string>& code_paths)
+ProfileSaver::ProfileSaver(const ProfileSaverOptions& options, jit::JitCodeCache* jit_code_cache)
     : jit_code_cache_(jit_code_cache),
       shutting_down_(false),
       last_time_ns_saver_woke_up_(0),
@@ -102,7 +99,6 @@
       total_number_of_wake_ups_(0),
       options_(options) {
   DCHECK(options_.IsEnabled());
-  AddTrackedLocations(output_filename, code_paths);
 }
 
 ProfileSaver::~ProfileSaver() {
@@ -128,6 +124,10 @@
   // under mutex, but should drop it.
   Locks::profiler_lock_->ExclusiveUnlock(self);
 
+  bool check_for_first_save =
+      options_.GetMinFirstSaveMs() != ProfileSaverOptions::kMinFirstSaveMsNotSet;
+  bool force_early_first_save = check_for_first_save && IsFirstSave();
+
   // Fetch the resolved classes for the app images after sleeping for
   // options_.GetSaveResolvedClassesDelayMs().
   // TODO(calin) This only considers the case of the primary profile file.
@@ -135,7 +135,10 @@
   // classes save (unless they started before the initial saving was done).
   {
     MutexLock mu(self, wait_lock_);
-    const uint64_t end_time = NanoTime() + MsToNs(options_.GetSaveResolvedClassesDelayMs());
+
+    const uint64_t end_time = NanoTime() + MsToNs(force_early_first_save
+      ? options_.GetMinFirstSaveMs()
+      : options_.GetSaveResolvedClassesDelayMs());
     while (!Runtime::Current()->GetStartupCompleted()) {
       const uint64_t current_time = NanoTime();
       if (current_time >= end_time) {
@@ -155,10 +158,16 @@
   // exponential back off policy bounded by max_wait_without_jit.
   uint32_t max_wait_without_jit = options_.GetMinSavePeriodMs() * 16;
   uint64_t cur_wait_without_jit = options_.GetMinSavePeriodMs();
+
   // Loop for the profiled methods.
   while (!ShuttingDown(self)) {
-    uint64_t sleep_start = NanoTime();
-    {
+    // Sleep only if we don't have to force an early first save configured
+    // with GetMinFirstSaveMs().
+    // If we do have to save early, move directly to the processing part
+    // since we already slept before fetching and resolving the startup
+    // classes.
+    if (!force_early_first_save) {
+      uint64_t sleep_start = NanoTime();
       uint64_t sleep_time = 0;
       {
         MutexLock mu(self, wait_lock_);
@@ -180,7 +189,7 @@
       // We might have been woken up by a huge number of notifications to guarantee saving.
       // If we didn't meet the minimum saving period go back to sleep (only if missed by
       // a reasonable margin).
-      uint64_t min_save_period_ns = MsToNs(options_.GetMinSavePeriodMs());
+      uint64_t min_save_period_ns = options_.GetMinSavePeriodMs();
       while (min_save_period_ns * 0.9 > sleep_time) {
         {
           MutexLock mu(self, wait_lock_);
@@ -193,8 +202,8 @@
         }
         total_number_of_wake_ups_++;
       }
+      total_ms_of_sleep_ += NsToMs(NanoTime() - sleep_start);
     }
-    total_ms_of_sleep_ += NsToMs(NanoTime() - sleep_start);
 
     if (ShuttingDown(self)) {
       break;
@@ -202,7 +211,16 @@
 
     uint16_t number_of_new_methods = 0;
     uint64_t start_work = NanoTime();
-    bool profile_saved_to_disk = ProcessProfilingInfo(/*force_save=*/false, &number_of_new_methods);
+    // If we force an early_first_save do not run FetchAndCacheResolvedClassesAndMethods
+    // again. We just did it. So pass true to skip_class_and_method_fetching.
+    bool profile_saved_to_disk = ProcessProfilingInfo(
+        /*force_save=*/ false,
+        /*skip_class_and_method_fetching=*/ force_early_first_save,
+        &number_of_new_methods);
+
+    // Reset the flag, so we can continue on the normal schedule.
+    force_early_first_save = false;
+
     // Update the notification counter based on result. Note that there might be contention on this
     // but we don't care about to be 100% precise.
     if (!profile_saved_to_disk) {
@@ -215,6 +233,53 @@
   }
 }
 
+// Checks if the profile file is empty.
+// Return true if the size of the profile file is 0 or if there were errors when
+// trying to open the file.
+static bool IsProfileEmpty(const std::string& location) {
+  if (location.empty()) {
+    return true;
+  }
+
+  struct stat stat_buffer;
+  if (stat(location.c_str(), &stat_buffer) != 0) {
+    if (VLOG_IS_ON(profiler)) {
+      PLOG(WARNING) << "Failed to stat profile location for IsFirstUse: " << location;
+    }
+    return true;
+  }
+
+  VLOG(profiler) << "Profile " << location << " size=" << stat_buffer.st_size;
+  return stat_buffer.st_size == 0;
+}
+
+bool ProfileSaver::IsFirstSave() {
+  Thread* self = Thread::Current();
+  SafeMap<std::string, std::string> tracked_locations;
+  {
+    // Make a copy so that we don't hold the lock while doing I/O.
+    MutexLock mu(self, *Locks::profiler_lock_);
+    tracked_locations = tracked_profiles_;
+  }
+
+  for (const auto& it : tracked_locations) {
+    if (ShuttingDown(self)) {
+      return false;
+    }
+    const std::string& cur_profile = it.first;
+    const std::string& ref_profile = it.second;
+
+    // Check if any profile is non empty. If so, then this is not the first save.
+    if (!IsProfileEmpty(cur_profile) || !IsProfileEmpty(ref_profile)) {
+      return false;
+    }
+  }
+
+  // All locations are empty. Assume this is the first use.
+  VLOG(profiler) << "All profile locations are empty. This is considered to be first save";
+  return true;
+}
+
 void ProfileSaver::NotifyJitActivity() {
   MutexLock mu(Thread::Current(), *Locks::profiler_lock_);
   if (instance_ == nullptr || instance_->shutting_down_) {
@@ -249,7 +314,7 @@
   }
 }
 
-class ScopedDefaultPriority {
+class ProfileSaver::ScopedDefaultPriority {
  public:
   explicit ScopedDefaultPriority(pthread_t thread) : thread_(thread) {
     SetProfileSaverThreadPriority(thread_, GetDefaultThreadPriority());
@@ -263,146 +328,430 @@
   const pthread_t thread_;
 };
 
-// GetClassLoadersVisitor takes a snapshot of the class loaders and stores them in the out
-// class_loaders argument. Not affected by class unloading since there are no suspend points in
-// the caller.
-class GetClassLoadersVisitor : public ClassLoaderVisitor {
+class ProfileSaver::GetClassesAndMethodsHelper {
  public:
-  explicit GetClassLoadersVisitor(VariableSizedHandleScope* hs,
-                                  std::vector<Handle<mirror::ClassLoader>>* class_loaders)
-      : hs_(hs),
-        class_loaders_(class_loaders) {}
+  GetClassesAndMethodsHelper(bool startup,
+                             const ProfileSaverOptions& options,
+                             const ProfileCompilationInfo::ProfileSampleAnnotation& annotation)
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      : startup_(startup),
+        profile_boot_class_path_(options.GetProfileBootClassPath()),
+        hot_method_sample_threshold_(CalculateHotMethodSampleThreshold(startup, options)),
+        extra_flags_(GetExtraMethodHotnessFlags(options)),
+        annotation_(annotation),
+        arena_stack_(Runtime::Current()->GetArenaPool()),
+        allocator_(&arena_stack_),
+        class_loaders_(std::nullopt),
+        dex_file_records_map_(allocator_.Adapter(kArenaAllocProfile)),
+        number_of_hot_methods_(0u),
+        number_of_sampled_methods_(0u) {
+    std::fill_n(max_primitive_array_dimensions_.data(), max_primitive_array_dimensions_.size(), 0u);
+  }
 
-  void Visit(ObjPtr<mirror::ClassLoader> class_loader)
-      REQUIRES_SHARED(Locks::classlinker_classes_lock_, Locks::mutator_lock_) override {
-    class_loaders_->push_back(hs_->NewHandle(class_loader));
+  ~GetClassesAndMethodsHelper() REQUIRES_SHARED(Locks::mutator_lock_) {
+    // The `class_loaders_` member destructor needs the mutator lock.
+    // We need to destroy arena-allocated dex file records.
+    for (const auto& entry : dex_file_records_map_) {
+      delete entry.second;
+    }
+  }
+
+  void CollectClasses(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
+  void UpdateProfile(const std::set<std::string>& locations, ProfileCompilationInfo* profile_info);
+
+  uint32_t GetHotMethodSampleThreshold() const {
+    return hot_method_sample_threshold_;
+  }
+
+  size_t GetNumberOfHotMethods() const {
+    return number_of_hot_methods_;
+  }
+
+  size_t GetNumberOfSampledMethods() const {
+    return number_of_sampled_methods_;
   }
 
  private:
-  VariableSizedHandleScope* const hs_;
-  std::vector<Handle<mirror::ClassLoader>>* const class_loaders_;
+  // GetClassLoadersVisitor collects visited class loaders.
+  class GetClassLoadersVisitor : public ClassLoaderVisitor {
+   public:
+    explicit GetClassLoadersVisitor(VariableSizedHandleScope* class_loaders)
+        : class_loaders_(class_loaders) {}
+
+    void Visit(ObjPtr<mirror::ClassLoader> class_loader)
+        REQUIRES_SHARED(Locks::classlinker_classes_lock_, Locks::mutator_lock_) override {
+      DCHECK(class_loader != nullptr);
+      class_loaders_->NewHandle(class_loader);
+    }
+
+   private:
+    VariableSizedHandleScope* const class_loaders_;
+  };
+
+  class CollectInternalVisitor {
+   public:
+    explicit CollectInternalVisitor(GetClassesAndMethodsHelper* helper)
+        : helper_(helper) {}
+
+    void VisitRootIfNonNull(StackReference<mirror::Object>* ref)
+        REQUIRES_SHARED(Locks::mutator_lock_) {
+      if (!ref->IsNull()) {
+        helper_->CollectInternal</*kBootClassLoader=*/ false>(ref->AsMirrorPtr()->AsClassLoader());
+      }
+    }
+
+   private:
+    GetClassesAndMethodsHelper* helper_;
+  };
+
+  struct ClassRecord {
+    dex::TypeIndex type_index;
+    uint16_t array_dimension;
+    uint32_t copied_methods_start;
+    LengthPrefixedArray<ArtMethod>* methods;
+  };
+
+  struct DexFileRecords : public DeletableArenaObject<kArenaAllocProfile> {
+    explicit DexFileRecords(ScopedArenaAllocator* allocator)
+        : class_records(allocator->Adapter(kArenaAllocProfile)),
+          copied_methods(allocator->Adapter(kArenaAllocProfile)) {
+      class_records.reserve(kInitialClassRecordsReservation);
+    }
+
+    static constexpr size_t kInitialClassRecordsReservation = 512;
+
+    ScopedArenaVector<ClassRecord> class_records;
+    ScopedArenaVector<ArtMethod*> copied_methods;
+  };
+
+  using DexFileRecordsMap = ScopedArenaHashMap<const DexFile*, DexFileRecords*>;
+
+  static uint32_t CalculateHotMethodSampleThreshold(bool startup,
+                                                    const ProfileSaverOptions& options) {
+    Runtime* runtime = Runtime::Current();
+    if (startup) {
+      const bool is_low_ram = runtime->GetHeap()->IsLowMemoryMode();
+      return options.GetHotStartupMethodSamples(is_low_ram);
+    } else if (runtime->GetJit() != nullptr) {
+      return runtime->GetJit()->WarmMethodThreshold();
+    } else {
+      return std::numeric_limits<uint32_t>::max();
+    }
+  }
+
+  ALWAYS_INLINE static bool ShouldCollectClasses(bool startup) {
+    // We only record classes for the startup case. This may change in the future.
+    return startup;
+  }
+
+  // Collect classes and methods from one class loader.
+  template <bool kBootClassLoader>
+  void CollectInternal(ObjPtr<mirror::ClassLoader> class_loader) NO_INLINE
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  const bool startup_;
+  const bool profile_boot_class_path_;
+  const uint32_t hot_method_sample_threshold_;
+  const uint32_t extra_flags_;
+  const ProfileCompilationInfo::ProfileSampleAnnotation annotation_;
+  ArenaStack arena_stack_;
+  ScopedArenaAllocator allocator_;
+  std::optional<VariableSizedHandleScope> class_loaders_;
+  DexFileRecordsMap dex_file_records_map_;
+
+  static_assert(Primitive::kPrimLast == Primitive::kPrimVoid);  // There are no arrays of void.
+  std::array<uint8_t, static_cast<size_t>(Primitive::kPrimLast)> max_primitive_array_dimensions_;
+
+  size_t number_of_hot_methods_;
+  size_t number_of_sampled_methods_;
 };
 
-// GetClassesVisitor takes a snapshot of the loaded classes that we may want to visit and stores
-// them in the out argument. Not affected by class unloading since there are no suspend points in
-// the caller.
-class GetClassesVisitor : public ClassVisitor {
- public:
-  explicit GetClassesVisitor(bool profile_boot_class_path,
-                             ScopedArenaVector<ObjPtr<mirror::Class>>* out)
-      : profile_boot_class_path_(profile_boot_class_path),
-        out_(out) {}
+template <bool kBootClassLoader>
+void ProfileSaver::GetClassesAndMethodsHelper::CollectInternal(
+    ObjPtr<mirror::ClassLoader> class_loader) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
+  DCHECK_EQ(kBootClassLoader, class_loader == nullptr);
 
-  bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (klass->IsProxyClass() ||
-        klass->IsArrayClass() ||
-        klass->IsPrimitive() ||
-        !klass->IsResolved() ||
-        klass->IsErroneousResolved() ||
-        (!profile_boot_class_path_ && klass->GetClassLoader() == nullptr)) {
+  // If the class loader has not loaded any classes, it may have a null table.
+  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+  ClassTable* const table =
+      class_linker->ClassTableForClassLoader(kBootClassLoader ? nullptr : class_loader);
+  if (table == nullptr) {
+    return;
+  }
+
+  // Move members to local variables to allow the compiler to optimize this properly.
+  const bool startup = startup_;
+  table->Visit([&](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (kBootClassLoader ? (!klass->IsBootStrapClassLoaded())
+                         : (klass->GetClassLoader() != class_loader)) {
+      // To avoid processing a class more than once, we process each class only
+      // when we encounter it in the defining class loader's class table.
+      // This class has a different defining class loader, skip it.
       return true;
     }
-    out_->push_back(klass);
+
+    uint16_t dim = 0u;
+    ObjPtr<mirror::Class> k = klass;
+    if (klass->IsArrayClass()) {
+      DCHECK_EQ(klass->NumMethods(), 0u);  // No methods to collect.
+      if (!ShouldCollectClasses(startup)) {
+        return true;
+      }
+      do {
+        DCHECK(k->IsResolved());  // Array classes are always resolved.
+        ++dim;
+        // At the time of array class creation, the element type is already either
+        // resolved or erroneous unresoved and either shall remain an invariant.
+        // Similarly, the access flag indicating a proxy class is an invariant.
+        // Read barrier is unnecessary for reading a chain of constant references
+        // in order to read primitive fields to check such invariants, or to read
+        // other constant primitive fields (dex file, primitive type) below.
+        k = k->GetComponentType<kDefaultVerifyFlags, kWithoutReadBarrier>();
+      } while (k->IsArrayClass());
+
+      DCHECK(kBootClassLoader || !k->IsPrimitive());
+      if (kBootClassLoader && UNLIKELY(k->IsPrimitive())) {
+        size_t index = enum_cast<size_t>(k->GetPrimitiveType());
+        DCHECK_LT(index, max_primitive_array_dimensions_.size());
+        if (dim > max_primitive_array_dimensions_[index]) {
+          // Enforce an upper limit of 255 for primitive array dimensions.
+          max_primitive_array_dimensions_[index] =
+              std::min<size_t>(dim, std::numeric_limits<uint8_t>::max());
+        }
+        return true;
+      }
+
+      // Attribute the array class to the defining dex file of the element class.
+      DCHECK_EQ(klass->GetCopiedMethodsStartOffset(), 0u);
+      DCHECK(klass->GetMethodsPtr() == nullptr);
+    } else {
+      // Non-array class. There is no need to collect primitive types.
+      DCHECK(kBootClassLoader || !k->IsPrimitive());
+      if (kBootClassLoader && UNLIKELY(klass->IsPrimitive())) {
+        DCHECK(profile_boot_class_path_);
+        DCHECK_EQ(klass->NumMethods(), 0u);  // No methods to collect.
+        return true;
+      }
+    }
+
+    if (!k->IsResolved() || k->IsProxyClass()) {
+      return true;
+    }
+
+    const DexFile& dex_file = k->GetDexFile();
+    dex::TypeIndex type_index = k->GetDexTypeIndex();
+    uint32_t copied_methods_start = klass->GetCopiedMethodsStartOffset();
+    LengthPrefixedArray<ArtMethod>* methods = klass->GetMethodsPtr();
+
+    DexFileRecords* dex_file_records;
+    auto it = dex_file_records_map_.find(&dex_file);
+    if (it != dex_file_records_map_.end()) {
+      dex_file_records = it->second;
+    } else {
+      dex_file_records = new (&allocator_) DexFileRecords(&allocator_);
+      dex_file_records_map_.insert(std::make_pair(&dex_file, dex_file_records));
+    }
+    dex_file_records->class_records.push_back(
+        ClassRecord{type_index, dim, copied_methods_start, methods});
     return true;
-  }
+  });
+}
 
- private:
-  const bool profile_boot_class_path_;
-  ScopedArenaVector<ObjPtr<mirror::Class>>* const out_;
-};
+void ProfileSaver::GetClassesAndMethodsHelper::CollectClasses(Thread* self) {
+  ScopedTrace trace(__PRETTY_FUNCTION__);
 
-using MethodReferenceCollection = DexReferenceCollection<uint16_t, ScopedArenaAllocatorAdapter>;
-using TypeReferenceCollection = DexReferenceCollection<dex::TypeIndex,
-                                                       ScopedArenaAllocatorAdapter>;
-
-// Iterate over all of the loaded classes and visit each one. For each class, add it to the
-// resolved_classes out argument if startup is true.
-// Add methods to the hot_methods out argument if the number of samples is greater or equal to
-// hot_method_sample_threshold, add it to sampled_methods if it has at least one sample.
-static void SampleClassesAndExecutedMethods(pthread_t profiler_pthread,
-                                            bool profile_boot_class_path,
-                                            ScopedArenaAllocator* allocator,
-                                            uint32_t hot_method_sample_threshold,
-                                            bool startup,
-                                            TypeReferenceCollection* resolved_classes,
-                                            MethodReferenceCollection* hot_methods,
-                                            MethodReferenceCollection* sampled_methods) {
-  Thread* const self = Thread::Current();
-  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
-  // Restore profile saver thread priority during the GC critical section. This helps prevent
-  // priority inversions blocking the GC for long periods of time.
-  std::unique_ptr<ScopedDefaultPriority> sdp;
-  // Only restore default priority if we are the profile saver thread. Other threads that call this
-  // are threads calling Stop and the signal catcher (for SIGUSR1).
-  if (pthread_self() == profiler_pthread) {
-    sdp.reset(new ScopedDefaultPriority(profiler_pthread));
-  }
-
-  // Do ScopedGCCriticalSection before acquiring mutator lock to prevent the GC running and
-  // blocking threads during thread root flipping. Since the GC is a background thread, blocking it
-  // is not a problem.
-  ScopedObjectAccess soa(self);
-  gc::ScopedGCCriticalSection sgcs(self,
-                                   gc::kGcCauseProfileSaver,
-                                   gc::kCollectorTypeCriticalSection);
-  VariableSizedHandleScope hs(soa.Self());
-  std::vector<Handle<mirror::ClassLoader>> class_loaders;
-  if (profile_boot_class_path) {
-    // First add the boot class loader since visit classloaders doesn't visit it.
-    class_loaders.push_back(hs.NewHandle<mirror::ClassLoader>(nullptr));
-  }
-  GetClassLoadersVisitor class_loader_visitor(&hs, &class_loaders);
+  // Collect class loaders into a `VariableSizedHandleScope` to prevent contention
+  // problems on the class_linker_classes_lock. Hold those class loaders in
+  // a member variable to keep them alive and prevent unloading their classes,
+  // so that methods referenced in collected `DexFileRecords` remain valid.
+  class_loaders_.emplace(self);
   {
-    // Read the class loaders into a temporary array to prevent contention problems on the
-    // class_linker_classes_lock.
-    ScopedTrace trace2("Get class loaders");
-    ReaderMutexLock mu(soa.Self(), *Locks::classlinker_classes_lock_);
+    GetClassLoadersVisitor class_loader_visitor(&class_loaders_.value());
+    ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+    ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
     class_linker->VisitClassLoaders(&class_loader_visitor);
   }
-  ScopedArenaVector<ObjPtr<mirror::Class>> classes(allocator->Adapter());
-  for (Handle<mirror::ClassLoader> class_loader : class_loaders) {
-    ClassTable* table = class_linker->ClassTableForClassLoader(class_loader.Get());
-    if (table == nullptr) {
-      // If the class loader has not loaded any classes, it may have a null table.
-      continue;
-    }
-    GetClassesVisitor get_classes_visitor(profile_boot_class_path, &classes);
-    {
-      // Collect the classes into a temporary array to prevent lock contention on the class
-      // table lock. We want to avoid blocking class loading in other threads as much as
-      // possible.
-      ScopedTrace trace3("Visiting class table");
-      table->Visit(get_classes_visitor);
-    }
-    for (ObjPtr<mirror::Class> klass : classes) {
-      if (startup) {
-        // We only record classes for the startup case. This may change in the future.
-        resolved_classes->AddReference(&klass->GetDexFile(), klass->GetDexTypeIndex());
+
+  // Collect classes and their method array pointers.
+  if (profile_boot_class_path_) {
+    // Collect classes from the boot class loader since visit classloaders doesn't visit it.
+    CollectInternal</*kBootClassLoader=*/ true>(/*class_loader=*/ nullptr);
+  }
+  {
+    CollectInternalVisitor visitor(this);
+    class_loaders_->VisitRoots(visitor);
+  }
+
+  // Attribute copied methods to defining dex files while holding the mutator lock.
+  for (const auto& entry : dex_file_records_map_) {
+    const DexFile* dex_file = entry.first;
+    DexFileRecords* dex_file_records = entry.second;
+
+    for (const ClassRecord& class_record : dex_file_records->class_records) {
+      LengthPrefixedArray<ArtMethod>* methods = class_record.methods;
+      if (methods == nullptr) {
+        continue;
       }
-      // Visit all of the methods in the class to see which ones were executed.
-      for (ArtMethod& method : klass->GetMethods(kRuntimePointerSize)) {
-        if (!method.IsNative() && !method.IsAbstract()) {
-          DCHECK(!method.IsProxyMethod());
-          const uint16_t counter = method.GetCounter();
-          // Mark startup methods as hot if they have more than hot_method_sample_threshold
-          // samples. This means they will get compiled by the compiler driver.
-          if (method.GetProfilingInfo(kRuntimePointerSize) != nullptr ||
-              method.PreviouslyWarm() ||
-              counter >= hot_method_sample_threshold) {
-            hot_methods->AddReference(method.GetDexFile(), method.GetDexMethodIndex());
-          } else if (counter != 0) {
-            sampled_methods->AddReference(method.GetDexFile(), method.GetDexMethodIndex());
+      const size_t methods_size = methods->size();
+      for (size_t index = class_record.copied_methods_start; index != methods_size; ++index) {
+        // Note: Using `ArtMethod` array with implicit `kRuntimePointerSize`.
+        ArtMethod& method = methods->At(index);
+        DCHECK(method.IsCopied());
+        DCHECK(!method.IsNative());
+        if (method.IsInvokable()) {
+          const DexFile* method_dex_file = method.GetDexFile();
+          DexFileRecords* method_dex_file_records = dex_file_records;
+          if (method_dex_file != dex_file) {
+            auto it = dex_file_records_map_.find(method_dex_file);
+            if (it == dex_file_records_map_.end()) {
+              // We have not seen any class in the dex file that defines the interface with this
+              // copied method. This can happen if the interface is in the boot class path and
+              // we are not profiling boot class path; or when we first visit classes for the
+              // interface's defining class loader before it has any resolved classes and then
+              // the interface is resolved and an implementing class is defined in a child class
+              // loader before we visit that child class loader's classes.
+              continue;
+            }
+            method_dex_file_records = it->second;
           }
-        } else {
-          // We do not record native methods. Once we AOT-compile the app, all native
-          // methods shall have their thunks compiled.
+          method_dex_file_records->copied_methods.push_back(&method);
         }
       }
     }
-    classes.clear();
   }
 }
 
+void ProfileSaver::GetClassesAndMethodsHelper::UpdateProfile(const std::set<std::string>& locations,
+                                                             ProfileCompilationInfo* profile_info) {
+  // Move members to local variables to allow the compiler to optimize this properly.
+  const bool startup = startup_;
+  const uint32_t hot_method_sample_threshold = hot_method_sample_threshold_;
+  const uint32_t base_flags =
+      (startup ? Hotness::kFlagStartup : Hotness::kFlagPostStartup) | extra_flags_;
+
+  // Collect the number of hot and sampled methods.
+  size_t number_of_hot_methods = 0u;
+  size_t number_of_sampled_methods = 0u;
+
+  auto get_method_flags = [&](ArtMethod& method) {
+    // Mark methods as hot if they have more than hot_method_sample_threshold
+    // samples. This means they will get compiled by the compiler driver.
+    const uint16_t counter = method.GetCounter();
+    if (method.PreviouslyWarm() || counter >= hot_method_sample_threshold) {
+      ++number_of_hot_methods;
+      return enum_cast<ProfileCompilationInfo::MethodHotness::Flag>(base_flags | Hotness::kFlagHot);
+    } else if (counter != 0u) {
+      ++number_of_sampled_methods;
+      return enum_cast<ProfileCompilationInfo::MethodHotness::Flag>(base_flags);
+    } else {
+      return enum_cast<ProfileCompilationInfo::MethodHotness::Flag>(0u);
+    }
+  };
+
+  // Use a single string for array descriptors to avoid too many reallocations.
+  std::string array_class_descriptor;
+
+  // Process classes and methods.
+  for (const auto& entry : dex_file_records_map_) {
+    const DexFile* dex_file = entry.first;
+    const DexFileRecords* dex_file_records = entry.second;
+
+    // Check if this is a profiled dex file.
+    const std::string base_location = DexFileLoader::GetBaseLocation(dex_file->GetLocation());
+    if (locations.find(base_location) == locations.end()) {
+      continue;
+    }
+
+    // Get the profile index.
+    ProfileCompilationInfo::ProfileIndexType profile_index =
+        profile_info->FindOrAddDexFile(*dex_file, annotation_);
+    if (profile_index == ProfileCompilationInfo::MaxProfileIndex()) {
+      // Error adding dex file to the `profile_info`.
+      continue;
+    }
+
+    for (const ClassRecord& class_record : dex_file_records->class_records) {
+      if (class_record.array_dimension != 0u) {
+        DCHECK(ShouldCollectClasses(startup));
+        DCHECK(class_record.methods == nullptr);  // No methods to process.
+        array_class_descriptor.assign(class_record.array_dimension, '[');
+        array_class_descriptor += dex_file->StringByTypeIdx(class_record.type_index);
+        dex::TypeIndex type_index =
+            profile_info->FindOrCreateTypeIndex(*dex_file, array_class_descriptor.c_str());
+        if (type_index.IsValid()) {
+          profile_info->AddClass(profile_index, type_index);
+        }
+      } else {
+        // Non-array class.
+        if (ShouldCollectClasses(startup)) {
+          profile_info->AddClass(profile_index, class_record.type_index);
+        }
+        const size_t num_declared_methods = class_record.copied_methods_start;
+        LengthPrefixedArray<ArtMethod>* methods = class_record.methods;
+        for (size_t index = 0; index != num_declared_methods; ++index) {
+          // Note: Using `ArtMethod` array with implicit `kRuntimePointerSize`.
+          ArtMethod& method = methods->At(index);
+          DCHECK(!method.IsCopied());
+          // We do not record native methods. Once we AOT-compile the app,
+          // all native methods shall have their JNI stubs compiled.
+          if (method.IsInvokable() && !method.IsNative()) {
+            ProfileCompilationInfo::MethodHotness::Flag flags = get_method_flags(method);
+            if (flags != 0u) {
+              profile_info->AddMethod(profile_index, method.GetDexMethodIndex(), flags);
+            }
+          }
+        }
+      }
+    }
+
+    for (ArtMethod* method : dex_file_records->copied_methods) {
+      DCHECK(method->IsCopied());
+      DCHECK(method->IsInvokable());
+      DCHECK(!method->IsNative());
+      ProfileCompilationInfo::MethodHotness::Flag flags = get_method_flags(*method);
+      if (flags != 0u) {
+        profile_info->AddMethod(profile_index, method->GetDexMethodIndex(), flags);
+      }
+    }
+  }
+
+  if (profile_boot_class_path_) {
+    // Attribute primitive arrays to the first dex file in the boot class path (should
+    // be core-oj). We collect primitive array types to know the needed dimensions.
+    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+    DCHECK(!class_linker->GetBootClassPath().empty());
+    const DexFile* dex_file = class_linker->GetBootClassPath().front();
+    ProfileCompilationInfo::ProfileIndexType profile_index =
+        profile_info->FindOrAddDexFile(*dex_file, annotation_);
+    if (profile_index != ProfileCompilationInfo::MaxProfileIndex()) {
+      for (size_t i = 0; i != max_primitive_array_dimensions_.size(); ++i) {
+        size_t max_dim = max_primitive_array_dimensions_[i];
+        // Insert descriptors for all dimensions up to `max_dim`.
+        for (size_t dim = 1; dim <= max_dim; ++dim) {
+          array_class_descriptor.assign(dim, '[');
+          array_class_descriptor += Primitive::Descriptor(enum_cast<Primitive::Type>(i));
+          dex::TypeIndex type_index =
+              profile_info->FindOrCreateTypeIndex(*dex_file, array_class_descriptor.c_str());
+          if (type_index.IsValid()) {
+            profile_info->AddClass(profile_index, type_index);
+          }
+        }
+      }
+    } else {
+      // Error adding dex file to the `profile_info`.
+    }
+  } else {
+    DCHECK(std::all_of(max_primitive_array_dimensions_.begin(),
+                       max_primitive_array_dimensions_.end(),
+                       [](uint8_t dim) { return dim == 0u; }));
+  }
+
+  // Store the number of hot and sampled methods.
+  number_of_hot_methods_ = number_of_hot_methods;
+  number_of_sampled_methods_ = number_of_sampled_methods;
+}
+
 void ProfileSaver::FetchAndCacheResolvedClassesAndMethods(bool startup) {
   ScopedTrace trace(__PRETTY_FUNCTION__);
   const uint64_t start_time = NanoTime();
@@ -411,107 +760,70 @@
   ResolveTrackedLocations();
 
   Thread* const self = Thread::Current();
-  Runtime* const runtime = Runtime::Current();
-  ArenaStack stack(runtime->GetArenaPool());
-  ScopedArenaAllocator allocator(&stack);
-  MethodReferenceCollection hot_methods(allocator.Adapter(), allocator.Adapter());
-  MethodReferenceCollection sampled_methods(allocator.Adapter(), allocator.Adapter());
-  TypeReferenceCollection resolved_classes(allocator.Adapter(), allocator.Adapter());
-  const bool is_low_ram = Runtime::Current()->GetHeap()->IsLowMemoryMode();
   pthread_t profiler_pthread;
   {
     MutexLock mu(self, *Locks::profiler_lock_);
     profiler_pthread = profiler_pthread_;
   }
-  uint32_t hot_method_sample_threshold = std::numeric_limits<uint32_t>::max();
-  if (startup) {
-    hot_method_sample_threshold = options_.GetHotStartupMethodSamples(is_low_ram);
-  } else if (Runtime::Current()->GetJit() != nullptr) {
-    hot_method_sample_threshold = Runtime::Current()->GetJit()->WarmMethodThreshold();
-  }
-  SampleClassesAndExecutedMethods(profiler_pthread,
-                                  options_.GetProfileBootClassPath(),
-                                  &allocator,
-                                  hot_method_sample_threshold,
-                                  startup,
-                                  &resolved_classes,
-                                  &hot_methods,
-                                  &sampled_methods);
-  MutexLock mu(self, *Locks::profiler_lock_);
 
-  for (const auto& it : tracked_dex_base_locations_) {
-    const std::string& filename = it.first;
-    auto info_it = profile_cache_.find(filename);
-    if (info_it == profile_cache_.end()) {
-      info_it = profile_cache_.Put(
-          filename,
-          new ProfileCompilationInfo(
-              Runtime::Current()->GetArenaPool(), options_.GetProfileBootClassPath()));
+  uint32_t hot_method_sample_threshold = 0u;
+  size_t number_of_hot_methods = 0u;
+  size_t number_of_sampled_methods = 0u;
+  {
+    // Restore profile saver thread priority while holding the mutator lock. This helps
+    // prevent priority inversions blocking the GC for long periods of time.
+    // Only restore default priority if we are the profile saver thread. Other threads
+    // that call this are threads calling Stop and the signal catcher (for SIGUSR1).
+    std::optional<ScopedDefaultPriority> sdp = std::nullopt;
+    if (pthread_self() == profiler_pthread) {
+      sdp.emplace(profiler_pthread);
     }
-    ProfileCompilationInfo* cached_info = info_it->second;
 
-    const std::set<std::string>& locations = it.second;
-    VLOG(profiler) << "Locations for " << it.first << " " << android::base::Join(locations, ':');
+    ScopedObjectAccess soa(self);
+    GetClassesAndMethodsHelper helper(startup, options_, GetProfileSampleAnnotation());
+    hot_method_sample_threshold = helper.GetHotMethodSampleThreshold();
+    helper.CollectClasses(self);
 
-    for (const auto& pair : hot_methods.GetMap()) {
-      const DexFile* const dex_file = pair.first;
-      const std::string base_location = DexFileLoader::GetBaseLocation(dex_file->GetLocation());
-      const MethodReferenceCollection::IndexVector& indices = pair.second;
-      VLOG(profiler) << "Location " << dex_file->GetLocation()
-                     << " base_location=" << base_location
-                     << " found=" << (locations.find(base_location) != locations.end())
-                     << " indices size=" << indices.size();
-      if (locations.find(base_location) != locations.end()) {
-        uint32_t flags = Hotness::kFlagHot;
-        flags |= startup ? Hotness::kFlagStartup : Hotness::kFlagPostStartup;
-        cached_info->AddMethodsForDex(
-            AnnotateSampleFlags(flags),
-            dex_file,
-            indices.begin(),
-            indices.end(),
-            GetProfileSampleAnnotation());
+    // Release the mutator lock. We shall need to re-acquire the lock for a moment to
+    // destroy the `VariableSizedHandleScope` inside the `helper` which shall be
+    // conveniently handled by destroying `sts`, then `helper` and then `soa`.
+    ScopedThreadSuspension sts(self, kNative);
+    // Get back to the previous thread priority. We shall not increase the priority
+    // for the short time we need to re-acquire mutator lock for `helper` destructor.
+    sdp.reset();
+
+    MutexLock mu(self, *Locks::profiler_lock_);
+    for (const auto& it : tracked_dex_base_locations_) {
+      const std::string& filename = it.first;
+      auto info_it = profile_cache_.find(filename);
+      if (info_it == profile_cache_.end()) {
+        info_it = profile_cache_.Put(
+            filename,
+            new ProfileCompilationInfo(
+                Runtime::Current()->GetArenaPool(), options_.GetProfileBootClassPath()));
       }
-    }
-    for (const auto& pair : sampled_methods.GetMap()) {
-      const DexFile* const dex_file = pair.first;
-      const std::string base_location = DexFileLoader::GetBaseLocation(dex_file->GetLocation());
-      const MethodReferenceCollection::IndexVector& indices = pair.second;
-      VLOG(profiler) << "Location " << base_location
-                     << " found=" << (locations.find(base_location) != locations.end())
-                     << " indices size=" << indices.size();
-      if (locations.find(base_location) != locations.end()) {
-        cached_info->AddMethodsForDex(
-            AnnotateSampleFlags(startup ? Hotness::kFlagStartup : Hotness::kFlagPostStartup),
-            dex_file,
-            indices.begin(),
-            indices.end(),
-            GetProfileSampleAnnotation());
-      }
-    }
-    for (const auto& pair : resolved_classes.GetMap()) {
-      const DexFile* const dex_file = pair.first;
-      const std::string base_location = DexFileLoader::GetBaseLocation(dex_file->GetLocation());
-      if (locations.find(base_location) != locations.end()) {
-        const TypeReferenceCollection::IndexVector& classes = pair.second;
-        VLOG(profiler) << "Added " << classes.size() << " classes for location "
-                       << base_location
-                       << " (" << dex_file->GetLocation() << ")";
-        cached_info->AddClassesForDex(dex_file,
-                                      classes.begin(),
-                                      classes.end(),
-                                      GetProfileSampleAnnotation());
-      } else {
-        VLOG(profiler) << "Location not found " << base_location;
-      }
+      ProfileCompilationInfo* cached_info = info_it->second;
+
+      const std::set<std::string>& locations = it.second;
+      VLOG(profiler) << "Locations for " << it.first << " " << android::base::Join(locations, ':');
+      helper.UpdateProfile(locations, cached_info);
+
+      // Update statistics. Note that a method shall be counted for each
+      // tracked location that covers the dex file where it is defined.
+      number_of_hot_methods += helper.GetNumberOfHotMethods();
+      number_of_sampled_methods += helper.GetNumberOfSampledMethods();
     }
   }
-  VLOG(profiler) << "Profile saver recorded " << hot_methods.NumReferences() << " hot methods and "
-                 << sampled_methods.NumReferences() << " sampled methods with threshold "
-                 << hot_method_sample_threshold << " in "
-                 << PrettyDuration(NanoTime() - start_time);
+  VLOG(profiler) << "Profile saver recorded " << number_of_hot_methods
+                 << " hot methods and " << number_of_sampled_methods
+                 << " sampled methods with threshold " << hot_method_sample_threshold
+                 << " in " << PrettyDuration(NanoTime() - start_time);
 }
 
-bool ProfileSaver::ProcessProfilingInfo(bool force_save, /*out*/uint16_t* number_of_new_methods) {
+bool ProfileSaver::ProcessProfilingInfo(
+        bool force_save,
+        bool skip_class_and_method_fetching,
+        /*out*/uint16_t* number_of_new_methods) {
   ScopedTrace trace(__PRETTY_FUNCTION__);
 
   // Resolve any new registered locations.
@@ -529,9 +841,11 @@
     *number_of_new_methods = 0;
   }
 
-  // We only need to do this once, not once per dex location.
-  // TODO: Figure out a way to only do it when stuff has changed? It takes 30-50ms.
-  FetchAndCacheResolvedClassesAndMethods(/*startup=*/ false);
+  if (!skip_class_and_method_fetching) {
+    // We only need to do this once, not once per dex location.
+    // TODO: Figure out a way to only do it when stuff has changed? It takes 30-50ms.
+    FetchAndCacheResolvedClassesAndMethods(/*startup=*/ false);
+  }
 
   for (const auto& it : tracked_locations) {
     if (!force_save && ShuttingDown(Thread::Current())) {
@@ -553,20 +867,12 @@
       total_number_of_code_cache_queries_++;
     }
     {
-      ProfileCompilationInfo info(Runtime::Current()->GetArenaPool());
+      ProfileCompilationInfo info(Runtime::Current()->GetArenaPool(),
+                                  /*for_boot_image=*/ options_.GetProfileBootClassPath());
       if (!info.Load(filename, /*clear_if_invalid=*/ true)) {
         LOG(WARNING) << "Could not forcefully load profile " << filename;
         continue;
       }
-      if (options_.GetProfileBootClassPath() != info.IsForBootImage()) {
-        // If we enabled boot class path profiling but the profile is a regular one,
-        // (or the opposite), clear the profile. We do not support cross-version merges.
-        LOG(WARNING) << "Adjust profile version: for_boot_classpath="
-            << options_.GetProfileBootClassPath();
-        info.ClearDataAndAdjustVersion(options_.GetProfileBootClassPath());
-        // For saving to ensure we persist the new version.
-        force_save = true;
-      }
       uint64_t last_save_number_of_methods = info.GetNumberOfMethods();
       uint64_t last_save_number_of_classes = info.GetNumberOfResolvedClasses();
       VLOG(profiler) << "last_save_number_of_methods=" << last_save_number_of_methods
@@ -586,64 +892,67 @@
         force_save = true;
       }
 
-      auto profile_cache_it = profile_cache_.find(filename);
-      if (profile_cache_it != profile_cache_.end()) {
-        if (!info.MergeWith(*(profile_cache_it->second))) {
-          LOG(WARNING) << "Could not merge the profile. Clearing the profile data.";
-          info.ClearData();
-          force_save = true;
-        }
-      } else if (VLOG_IS_ON(profiler)) {
-        LOG(INFO) << "Failed to find cached profile for " << filename;
-        for (auto&& pair : profile_cache_) {
-          LOG(INFO) << "Cached profile " << pair.first;
-        }
-      }
-
-      int64_t delta_number_of_methods =
-          info.GetNumberOfMethods() - last_save_number_of_methods;
-      int64_t delta_number_of_classes =
-          info.GetNumberOfResolvedClasses() - last_save_number_of_classes;
-
-      if (!force_save &&
-          delta_number_of_methods < options_.GetMinMethodsToSave() &&
-          delta_number_of_classes < options_.GetMinClassesToSave()) {
-        VLOG(profiler) << "Not enough information to save to: " << filename
-                       << " Number of methods: " << delta_number_of_methods
-                       << " Number of classes: " << delta_number_of_classes;
-        total_number_of_skipped_writes_++;
-        continue;
-      }
-
-      if (number_of_new_methods != nullptr) {
-        *number_of_new_methods =
-            std::max(static_cast<uint16_t>(delta_number_of_methods),
-                     *number_of_new_methods);
-      }
-      uint64_t bytes_written;
-      // Force the save. In case the profile data is corrupted or the the profile
-      // has the wrong version this will "fix" the file to the correct format.
-      if (info.Save(filename, &bytes_written)) {
-        // We managed to save the profile. Clear the cache stored during startup.
+      {
+        MutexLock mu(Thread::Current(), *Locks::profiler_lock_);
+        auto profile_cache_it = profile_cache_.find(filename);
         if (profile_cache_it != profile_cache_.end()) {
-          ProfileCompilationInfo *cached_info = profile_cache_it->second;
-          profile_cache_.erase(profile_cache_it);
-          delete cached_info;
+          if (!info.MergeWith(*(profile_cache_it->second))) {
+            LOG(WARNING) << "Could not merge the profile. Clearing the profile data.";
+            info.ClearData();
+            force_save = true;
+          }
+        } else if (VLOG_IS_ON(profiler)) {
+          LOG(INFO) << "Failed to find cached profile for " << filename;
+          for (auto&& pair : profile_cache_) {
+            LOG(INFO) << "Cached profile " << pair.first;
+          }
         }
-        if (bytes_written > 0) {
-          total_number_of_writes_++;
-          total_bytes_written_ += bytes_written;
-          profile_file_saved = true;
-        } else {
-          // At this point we could still have avoided the write.
-          // We load and merge the data from the file lazily at its first ever
-          // save attempt. So, whatever we are trying to save could already be
-          // in the file.
+
+        int64_t delta_number_of_methods =
+            info.GetNumberOfMethods() - last_save_number_of_methods;
+        int64_t delta_number_of_classes =
+            info.GetNumberOfResolvedClasses() - last_save_number_of_classes;
+
+        if (!force_save &&
+            delta_number_of_methods < options_.GetMinMethodsToSave() &&
+            delta_number_of_classes < options_.GetMinClassesToSave()) {
+          VLOG(profiler) << "Not enough information to save to: " << filename
+                        << " Number of methods: " << delta_number_of_methods
+                        << " Number of classes: " << delta_number_of_classes;
           total_number_of_skipped_writes_++;
+          continue;
         }
-      } else {
-        LOG(WARNING) << "Could not save profiling info to " << filename;
-        total_number_of_failed_writes_++;
+
+        if (number_of_new_methods != nullptr) {
+          *number_of_new_methods =
+              std::max(static_cast<uint16_t>(delta_number_of_methods),
+                      *number_of_new_methods);
+        }
+        uint64_t bytes_written;
+        // Force the save. In case the profile data is corrupted or the profile
+        // has the wrong version this will "fix" the file to the correct format.
+        if (info.Save(filename, &bytes_written)) {
+          // We managed to save the profile. Clear the cache stored during startup.
+          if (profile_cache_it != profile_cache_.end()) {
+            ProfileCompilationInfo *cached_info = profile_cache_it->second;
+            profile_cache_.erase(profile_cache_it);
+            delete cached_info;
+          }
+          if (bytes_written > 0) {
+            total_number_of_writes_++;
+            total_bytes_written_ += bytes_written;
+            profile_file_saved = true;
+          } else {
+            // At this point we could still have avoided the write.
+            // We load and merge the data from the file lazily at its first ever
+            // save attempt. So, whatever we are trying to save could already be
+            // in the file.
+            total_number_of_skipped_writes_++;
+          }
+        } else {
+          LOG(WARNING) << "Could not save profiling info to " << filename;
+          total_number_of_failed_writes_++;
+        }
       }
     }
   }
@@ -705,9 +1014,10 @@
 }
 
 void  ProfileSaver::Start(const ProfileSaverOptions& options,
-                         const std::string& output_filename,
-                         jit::JitCodeCache* jit_code_cache,
-                         const std::vector<std::string>& code_paths) {
+                          const std::string& output_filename,
+                          jit::JitCodeCache* jit_code_cache,
+                          const std::vector<std::string>& code_paths,
+                          const std::string& ref_profile_filename) {
   Runtime* const runtime = Runtime::Current();
   DCHECK(options.IsEnabled());
   DCHECK(runtime->GetJit() != nullptr);
@@ -760,17 +1070,16 @@
     // apps which share the same runtime).
     DCHECK_EQ(instance_->jit_code_cache_, jit_code_cache);
     // Add the code_paths to the tracked locations.
-    instance_->AddTrackedLocations(output_filename, code_paths_to_profile);
+    instance_->AddTrackedLocations(output_filename, code_paths_to_profile, ref_profile_filename);
     return;
   }
 
   VLOG(profiler) << "Starting profile saver using output file: " << output_filename
-      << ". Tracking: " << android::base::Join(code_paths_to_profile, ':');
+      << ". Tracking: " << android::base::Join(code_paths_to_profile, ':')
+      << ". With reference profile: " << ref_profile_filename;
 
-  instance_ = new ProfileSaver(options,
-                               output_filename,
-                               jit_code_cache,
-                               code_paths_to_profile);
+  instance_ = new ProfileSaver(options, jit_code_cache);
+  instance_->AddTrackedLocations(output_filename, code_paths_to_profile, ref_profile_filename);
 
   // Create a new thread which does the saving.
   CHECK_PTHREAD_CALL(
@@ -809,7 +1118,10 @@
 
   // Force save everything before destroying the thread since we want profiler_pthread_ to remain
   // valid.
-  profile_saver->ProcessProfilingInfo(/*force_save=*/true, /*number_of_new_methods=*/nullptr);
+  profile_saver->ProcessProfilingInfo(
+      /*force_ save=*/ true,
+      /*skip_class_and_method_fetching=*/ false,
+      /*number_of_new_methods=*/ nullptr);
 
   // Wait for the saver thread to stop.
   CHECK_PTHREAD_CALL(pthread_join, (profiler_pthread, nullptr), "profile saver thread shutdown");
@@ -874,7 +1186,14 @@
 }
 
 void ProfileSaver::AddTrackedLocations(const std::string& output_filename,
-                                       const std::vector<std::string>& code_paths) {
+                                       const std::vector<std::string>& code_paths,
+                                       const std::string& ref_profile_filename) {
+  // Register the output profile and its reference profile.
+  auto it = tracked_profiles_.find(output_filename);
+  if (it == tracked_profiles_.end()) {
+    tracked_profiles_.Put(output_filename, ref_profile_filename);
+  }
+
   // Add the code paths to the list of tracked location.
   AddTrackedLocationsToMap(output_filename, code_paths, &tracked_dex_base_locations_);
   // The code paths may contain symlinks which could fool the profiler.
@@ -921,23 +1240,13 @@
   // but we only use this in testing when we now this won't happen.
   // Refactor the way we handle the instance so that we don't end up in this situation.
   if (saver != nullptr) {
-    saver->ProcessProfilingInfo(/*force_save=*/true, /*number_of_new_methods=*/nullptr);
+    saver->ProcessProfilingInfo(
+        /*force_save=*/ true,
+        /*skip_class_and_method_fetching=*/ false,
+        /*number_of_new_methods=*/ nullptr);
   }
 }
 
-bool ProfileSaver::HasSeenMethod(const std::string& profile, bool hot, MethodReference ref) {
-  MutexLock mu(Thread::Current(), *Locks::profiler_lock_);
-  if (instance_ != nullptr) {
-    ProfileCompilationInfo info(Runtime::Current()->GetArenaPool());
-    if (!info.Load(profile, /*clear_if_invalid=*/false)) {
-      return false;
-    }
-    const ProfileCompilationInfo::MethodHotness hotness = info.GetMethodHotness(ref);
-    return hot ? hotness.IsHot() : hotness.IsInProfile();
-  }
-  return false;
-}
-
 void ProfileSaver::ResolveTrackedLocations() {
   SafeMap<std::string, std::set<std::string>> locations_to_be_resolved;
   {
@@ -988,15 +1297,20 @@
       : ProfileCompilationInfo::ProfileSampleAnnotation::kNone;
 }
 
-Hotness::Flag ProfileSaver::AnnotateSampleFlags(uint32_t flags) {
-  uint32_t extra_flags = 0;
+uint32_t ProfileSaver::GetExtraMethodHotnessFlags(const ProfileSaverOptions& options) {
   // We only add the extra flags for the boot image profile because individual apps do not use
   // this information.
-  if (options_.GetProfileBootClassPath()) {
-    extra_flags = Is64BitInstructionSet(Runtime::Current()->GetInstructionSet())
+  if (options.GetProfileBootClassPath()) {
+    return Is64BitInstructionSet(Runtime::Current()->GetInstructionSet())
         ? Hotness::kFlag64bit
         : Hotness::kFlag32bit;
+  } else {
+    return 0u;
   }
+}
+
+Hotness::Flag ProfileSaver::AnnotateSampleFlags(uint32_t flags) {
+  uint32_t extra_flags = GetExtraMethodHotnessFlags(options_);
   return static_cast<Hotness::Flag>(flags | extra_flags);
 }
 
diff --git a/runtime/jit/profile_saver.h b/runtime/jit/profile_saver.h
index 60959d2..b5fb1e6 100644
--- a/runtime/jit/profile_saver.h
+++ b/runtime/jit/profile_saver.h
@@ -30,10 +30,15 @@
  public:
   // Starts the profile saver thread if not already started.
   // If the saver is already running it adds (output_filename, code_paths) to its tracked locations.
+  //
+  // The `ref_profile_filename` denotes the path to the reference profile which
+  // might be queried to determine if an initial save should be done earlier.
+  // It can be empty indicating there is no reference profile.
   static void Start(const ProfileSaverOptions& options,
                     const std::string& output_filename,
                     jit::JitCodeCache* jit_code_cache,
-                    const std::vector<std::string>& code_paths)
+                    const std::vector<std::string>& code_paths,
+                    const std::string& ref_profile_filename)
       REQUIRES(!Locks::profiler_lock_, !instance_->wait_lock_);
 
   // Stops the profile saver thread.
@@ -50,18 +55,15 @@
   // For testing or manual purposes (SIGUSR1).
   static void ForceProcessProfiles() REQUIRES(!Locks::profiler_lock_, !Locks::mutator_lock_);
 
-  // Just for testing purposes.
-  static bool HasSeenMethod(const std::string& profile, bool hot, MethodReference ref)
-      REQUIRES(!Locks::profiler_lock_);
-
   // Notify that startup has completed.
   static void NotifyStartupCompleted() REQUIRES(!Locks::profiler_lock_, !instance_->wait_lock_);
 
  private:
-  ProfileSaver(const ProfileSaverOptions& options,
-               const std::string& output_filename,
-               jit::JitCodeCache* jit_code_cache,
-               const std::vector<std::string>& code_paths);
+  // Helper classes for collecting classes and methods.
+  class GetClassesAndMethodsHelper;
+  class ScopedDefaultPriority;
+
+  ProfileSaver(const ProfileSaverOptions& options, jit::JitCodeCache* jit_code_cache);
   ~ProfileSaver();
 
   static void* RunProfileSaverThread(void* arg)
@@ -78,7 +80,10 @@
   // written to disk.
   // If force_save is true, the saver will ignore any constraints which limit IO (e.g. will write
   // the profile to disk even if it's just one new method).
-  bool ProcessProfilingInfo(bool force_save, /*out*/uint16_t* number_of_new_methods)
+  bool ProcessProfilingInfo(
+        bool force_save,
+        bool skip_class_and_method_fetching,
+        /*out*/uint16_t* number_of_new_methods)
       REQUIRES(!Locks::profiler_lock_)
       REQUIRES(!Locks::mutator_lock_);
 
@@ -89,7 +94,8 @@
   bool ShuttingDown(Thread* self) REQUIRES(!Locks::profiler_lock_);
 
   void AddTrackedLocations(const std::string& output_filename,
-                           const std::vector<std::string>& code_paths)
+                           const std::vector<std::string>& code_paths,
+                           const std::string& ref_profile_filename)
       REQUIRES(Locks::profiler_lock_);
 
   // Fetches the current resolved classes and methods from the ClassLinker and stores them in the
@@ -106,6 +112,9 @@
   // profile saver session.
   ProfileCompilationInfo::ProfileSampleAnnotation GetProfileSampleAnnotation();
 
+  // Get extra global flags if necessary (e.g. the running architecture), otherwise 0.
+  static uint32_t GetExtraMethodHotnessFlags(const ProfileSaverOptions& options);
+
   // Extends the given set of flags with global flags if necessary (e.g. the running architecture).
   ProfileCompilationInfo::MethodHotness::Flag AnnotateSampleFlags(uint32_t flags);
 
@@ -127,6 +136,13 @@
   SafeMap<std::string, std::set<std::string>> tracked_dex_base_locations_to_be_resolved_
       GUARDED_BY(Locks::profiler_lock_);
 
+  // Collection of output profiles that the profile tracks.
+  // It maps output profile locations to reference profiles, and is used
+  // to determine if any profile is non-empty at the start of the ProfileSaver.
+  // This influences the time of the first ever save.
+  SafeMap<std::string, std::string> tracked_profiles_
+      GUARDED_BY(Locks::profiler_lock_);
+
   bool shutting_down_ GUARDED_BY(Locks::profiler_lock_);
   uint64_t last_time_ns_saver_woke_up_ GUARDED_BY(wait_lock_);
   uint32_t jit_activity_notifications_;
@@ -136,7 +152,13 @@
   // we don't hammer the disk to save them right away.
   // The size of this cache is usually very small and tops
   // to just a few hundreds entries in the ProfileCompilationInfo objects.
-  SafeMap<std::string, ProfileCompilationInfo*> profile_cache_;
+  SafeMap<std::string, ProfileCompilationInfo*> profile_cache_ GUARDED_BY(Locks::profiler_lock_);
+
+  // Whether or not this is the first ever profile save.
+  // Note this is an approximation and is not 100% precise. It relies on checking
+  // whether or not the profiles are empty which is not a precise indication
+  // of being the first save (they could have been cleared in the meantime).
+  bool IsFirstSave() REQUIRES(!Locks::profiler_lock_);
 
   // Save period condition support.
   Mutex wait_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
diff --git a/runtime/jit/profile_saver_options.h b/runtime/jit/profile_saver_options.h
index 1cff713..7492054 100644
--- a/runtime/jit/profile_saver_options.h
+++ b/runtime/jit/profile_saver_options.h
@@ -21,6 +21,9 @@
 struct ProfileSaverOptions {
  public:
   static constexpr uint32_t kMinSavePeriodMs = 40 * 1000;  // 40 seconds
+  // Default value for the min save period on first use, indicating that the
+  // period is not configured.
+  static constexpr uint32_t kMinFirstSaveMsNotSet = 0;
   static constexpr uint32_t kSaveResolvedClassesDelayMs = 5 * 1000;  // 5 seconds
   // Minimum number of JIT samples during launch to mark a method as hot in the profile.
   static constexpr uint32_t kHotStartupMethodSamples = 1;
@@ -34,6 +37,7 @@
   ProfileSaverOptions() :
     enabled_(false),
     min_save_period_ms_(kMinSavePeriodMs),
+    min_first_save_ms_(kMinFirstSaveMsNotSet),
     save_resolved_classes_delay_ms_(kSaveResolvedClassesDelayMs),
     hot_startup_method_samples_(kHotStartupMethodSamplesNotSet),
     min_methods_to_save_(kMinMethodsToSave),
@@ -48,6 +52,7 @@
   ProfileSaverOptions(
       bool enabled,
       uint32_t min_save_period_ms,
+      uint32_t min_first_save_ms,
       uint32_t save_resolved_classes_delay_ms,
       uint32_t hot_startup_method_samples,
       uint32_t min_methods_to_save,
@@ -60,6 +65,7 @@
       bool wait_for_jit_notifications_to_save = true)
   : enabled_(enabled),
     min_save_period_ms_(min_save_period_ms),
+    min_first_save_ms_(min_first_save_ms),
     save_resolved_classes_delay_ms_(save_resolved_classes_delay_ms),
     hot_startup_method_samples_(hot_startup_method_samples),
     min_methods_to_save_(min_methods_to_save),
@@ -81,6 +87,9 @@
   uint32_t GetMinSavePeriodMs() const {
     return min_save_period_ms_;
   }
+  uint32_t GetMinFirstSaveMs() const {
+    return min_first_save_ms_;
+  }
   uint32_t GetSaveResolvedClassesDelayMs() const {
     return save_resolved_classes_delay_ms_;
   }
@@ -122,6 +131,7 @@
   friend std::ostream & operator<<(std::ostream &os, const ProfileSaverOptions& pso) {
     os << "enabled_" << pso.enabled_
         << ", min_save_period_ms_" << pso.min_save_period_ms_
+        << ", min_first_save_ms_" << pso.min_first_save_ms_
         << ", save_resolved_classes_delay_ms_" << pso.save_resolved_classes_delay_ms_
         << ", hot_startup_method_samples_" << pso.hot_startup_method_samples_
         << ", min_methods_to_save_" << pso.min_methods_to_save_
@@ -136,6 +146,7 @@
 
   bool enabled_;
   uint32_t min_save_period_ms_;
+  uint32_t min_first_save_ms_;
   uint32_t save_resolved_classes_delay_ms_;
   // Do not access hot_startup_method_samples_ directly for reading since it may be set to the
   // placeholder default.
diff --git a/runtime/jit/profile_saver_test.cc b/runtime/jit/profile_saver_test.cc
index 9a866a3..e737b7c 100644
--- a/runtime/jit/profile_saver_test.cc
+++ b/runtime/jit/profile_saver_test.cc
@@ -40,13 +40,9 @@
   void PostRuntimeCreate() override {
     // Create a profile saver.
     Runtime* runtime = Runtime::Current();
-    const std::vector<std::string> code_paths;
-    const std::string fake_file = "fake_file";
     profile_saver_ = new ProfileSaver(
         runtime->GetJITOptions()->GetProfileSaverOptions(),
-        fake_file,
-        runtime->GetJitCodeCache(),
-        code_paths);
+        runtime->GetJitCodeCache());
   }
 
   ~ProfileSaverTest() {
diff --git a/runtime/jit/profiling_info.cc b/runtime/jit/profiling_info.cc
index 8c88760..e101f9a 100644
--- a/runtime/jit/profiling_info.cc
+++ b/runtime/jit/profiling_info.cc
@@ -28,18 +28,15 @@
 ProfilingInfo::ProfilingInfo(ArtMethod* method, const std::vector<uint32_t>& entries)
       : baseline_hotness_count_(0),
         method_(method),
-        saved_entry_point_(nullptr),
         number_of_inline_caches_(entries.size()),
-        current_inline_uses_(0),
-        is_method_being_compiled_(false),
-        is_osr_method_being_compiled_(false) {
+        current_inline_uses_(0) {
   memset(&cache_, 0, number_of_inline_caches_ * sizeof(InlineCache));
   for (size_t i = 0; i < number_of_inline_caches_; ++i) {
     cache_[i].dex_pc_ = entries[i];
   }
 }
 
-bool ProfilingInfo::Create(Thread* self, ArtMethod* method, bool retry_allocation) {
+ProfilingInfo* ProfilingInfo::Create(Thread* self, ArtMethod* method) {
   // Walk over the dex instructions of the method and keep track of
   // instructions we are interested in profiling.
   DCHECK(!method->IsNative());
@@ -49,8 +46,6 @@
     switch (inst->Opcode()) {
       case Instruction::INVOKE_VIRTUAL:
       case Instruction::INVOKE_VIRTUAL_RANGE:
-      case Instruction::INVOKE_VIRTUAL_QUICK:
-      case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
       case Instruction::INVOKE_INTERFACE:
       case Instruction::INVOKE_INTERFACE_RANGE:
         entries.push_back(inst.DexPc());
@@ -66,7 +61,7 @@
 
   // Allocate the `ProfilingInfo` object int the JIT's data space.
   jit::JitCodeCache* code_cache = Runtime::Current()->GetJit()->GetCodeCache();
-  return code_cache->AddProfilingInfo(self, method, entries, retry_allocation) != nullptr;
+  return code_cache->AddProfilingInfo(self, method, entries);
 }
 
 InlineCache* ProfilingInfo::GetInlineCache(uint32_t dex_pc) {
@@ -76,6 +71,7 @@
       return &cache_[i];
     }
   }
+  ScopedObjectAccess soa(Thread::Current());
   LOG(FATAL) << "No inline cache found for "  << ArtMethod::PrettyMethod(method_) << "@" << dex_pc;
   UNREACHABLE();
 }
@@ -110,4 +106,19 @@
   // as the garbage collector might clear the entries concurrently.
 }
 
+ScopedProfilingInfoUse::ScopedProfilingInfoUse(jit::Jit* jit, ArtMethod* method, Thread* self)
+    : jit_(jit),
+      method_(method),
+      self_(self),
+      // Fetch the profiling info ahead of using it. If it's null when fetching,
+      // we should not call JitCodeCache::DoneCompilerUse.
+      profiling_info_(jit->GetCodeCache()->NotifyCompilerUse(method, self)) {
+}
+
+ScopedProfilingInfoUse::~ScopedProfilingInfoUse() {
+  if (profiling_info_ != nullptr) {
+    jit_->GetCodeCache()->DoneCompilerUse(method_, self_);
+  }
+}
+
 }  // namespace art
diff --git a/runtime/jit/profiling_info.h b/runtime/jit/profiling_info.h
index 14d76d2..b1ea227 100644
--- a/runtime/jit/profiling_info.h
+++ b/runtime/jit/profiling_info.h
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/value_object.h"
 #include "gc_root.h"
 #include "offsets.h"
 
@@ -29,6 +30,7 @@
 class ProfilingInfo;
 
 namespace jit {
+class Jit;
 class JitCodeCache;
 }  // namespace jit
 
@@ -63,9 +65,8 @@
  */
 class ProfilingInfo {
  public:
-  // Create a ProfilingInfo for 'method'. Return whether it succeeded, or if it is
-  // not needed in case the method does not have virtual/interface invocations.
-  static bool Create(Thread* self, ArtMethod* method, bool retry_allocation)
+  // Create a ProfilingInfo for 'method'.
+  static ProfilingInfo* Create(Thread* self, ArtMethod* method)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Add information from an executed INVOKE instruction to the profile.
@@ -79,31 +80,7 @@
     return method_;
   }
 
-  // Mutator lock only required for debugging output.
-  InlineCache* GetInlineCache(uint32_t dex_pc)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  bool IsMethodBeingCompiled(bool osr) const {
-    return osr
-        ? is_osr_method_being_compiled_
-        : is_method_being_compiled_;
-  }
-
-  void SetIsMethodBeingCompiled(bool value, bool osr) {
-    if (osr) {
-      is_osr_method_being_compiled_ = value;
-    } else {
-      is_method_being_compiled_ = value;
-    }
-  }
-
-  void SetSavedEntryPoint(const void* entry_point) {
-    saved_entry_point_ = entry_point;
-  }
-
-  const void* GetSavedEntryPoint() const {
-    return saved_entry_point_;
-  }
+  InlineCache* GetInlineCache(uint32_t dex_pc);
 
   // Increments the number of times this method is currently being inlined.
   // Returns whether it was successful, that is it could increment without
@@ -122,8 +99,7 @@
   }
 
   bool IsInUseByCompiler() const {
-    return IsMethodBeingCompiled(/*osr=*/ true) || IsMethodBeingCompiled(/*osr=*/ false) ||
-        (current_inline_uses_ > 0);
+    return current_inline_uses_ > 0;
   }
 
   static constexpr MemberOffset BaselineHotnessCountOffset() {
@@ -151,10 +127,6 @@
   // See JitCodeCache::MoveObsoleteMethod.
   ArtMethod* method_;
 
-  // Entry point of the corresponding ArtMethod, while the JIT code cache
-  // is poking for the liveness of compiled code.
-  const void* saved_entry_point_;
-
   // Number of instructions we are profiling in the ArtMethod.
   const uint32_t number_of_inline_caches_;
 
@@ -162,12 +134,6 @@
   // it updates this counter so that the GC does not try to clear the inline caches.
   uint16_t current_inline_uses_;
 
-  // Whether the ArtMethod is currently being compiled. This flag
-  // is implicitly guarded by the JIT code cache lock.
-  // TODO: Make the JIT code cache lock global.
-  bool is_method_being_compiled_;
-  bool is_osr_method_being_compiled_;
-
   // Dynamically allocated array of size `number_of_inline_caches_`.
   InlineCache cache_[0];
 
@@ -176,6 +142,22 @@
   DISALLOW_COPY_AND_ASSIGN(ProfilingInfo);
 };
 
+class ScopedProfilingInfoUse : public ValueObject {
+ public:
+  ScopedProfilingInfoUse(jit::Jit* jit, ArtMethod* method, Thread* self);
+  ~ScopedProfilingInfoUse();
+
+  ProfilingInfo* GetProfilingInfo() const { return profiling_info_; }
+
+ private:
+  jit::Jit* const jit_;
+  ArtMethod* const method_;
+  Thread* const self_;
+  ProfilingInfo* const profiling_info_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedProfilingInfoUse);
+};
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_JIT_PROFILING_INFO_H_
diff --git a/runtime/jit/profiling_info_test.cc b/runtime/jit/profiling_info_test.cc
index 319a3e1..ce0a30f 100644
--- a/runtime/jit/profiling_info_test.cc
+++ b/runtime/jit/profiling_info_test.cc
@@ -30,6 +30,7 @@
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "profile/profile_compilation_info.h"
+#include "profile/profile_test_helper.h"
 #include "scoped_thread_state_change-inl.h"
 
 namespace art {
@@ -154,35 +155,6 @@
     return used_inline_caches.back().get();
   }
 
-  ProfileCompilationInfo::OfflineProfileMethodInfo ConvertProfileMethodInfo(
-        const ProfileMethodInfo& pmi) {
-    ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap();
-    ProfileCompilationInfo::OfflineProfileMethodInfo offline_pmi(ic_map);
-    SafeMap<DexFile*, uint8_t> dex_map;  // dex files to profile index
-    for (const auto& inline_cache : pmi.inline_caches) {
-      ProfileCompilationInfo::DexPcData& dex_pc_data =
-          ic_map->FindOrAdd(
-              inline_cache.dex_pc, ProfileCompilationInfo::DexPcData(allocator_.get()))->second;
-      if (inline_cache.is_missing_types) {
-        dex_pc_data.SetIsMissingTypes();
-      }
-      for (const auto& class_ref : inline_cache.classes) {
-        uint8_t dex_profile_index = dex_map.FindOrAdd(const_cast<DexFile*>(class_ref.dex_file),
-                                                      static_cast<uint8_t>(dex_map.size()))->second;
-        dex_pc_data.AddClass(dex_profile_index, class_ref.TypeIndex());
-        if (dex_profile_index >= offline_pmi.dex_references.size()) {
-          // This is a new dex.
-          const std::string& dex_key = ProfileCompilationInfo::GetProfileDexFileBaseKey(
-              class_ref.dex_file->GetLocation());
-          offline_pmi.dex_references.emplace_back(dex_key,
-                                                  class_ref.dex_file->GetLocationChecksum(),
-                                                  class_ref.dex_file->NumMethodIds());
-        }
-      }
-    }
-    return offline_pmi;
-  }
-
   // Cannot sizeof the actual arrays so hard code the values here.
   // They should not change anyway.
   static constexpr int kProfileMagicSize = 4;
@@ -236,7 +208,6 @@
 
   // Check that what we saved is in the profile (methods form Main and Second).
   ProfileCompilationInfo info2;
-  ASSERT_TRUE(profile.GetFile()->ResetOffset());
   ASSERT_TRUE(info2.Load(GetFd(profile)));
   ASSERT_EQ(info2.GetNumberOfMethods(), main_methods.size() + second_methods.size());
   {
@@ -287,12 +258,10 @@
       ASSERT_TRUE(h.IsHot());
       ASSERT_TRUE(h.IsStartup());
       const ProfileMethodInfo& pmi = profile_methods_map.find(m)->second;
-      std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> offline_pmi =
-          info.GetHotMethodInfo(method_ref);
-      ASSERT_TRUE(offline_pmi != nullptr);
-      ProfileCompilationInfo::OfflineProfileMethodInfo converted_pmi =
-          ConvertProfileMethodInfo(pmi);
-      ASSERT_EQ(converted_pmi, *offline_pmi);
+      ProfileCompilationInfo::MethodHotness offline_hotness = info.GetMethodHotness(method_ref);
+      ASSERT_TRUE(offline_hotness.IsHot());
+      ASSERT_TRUE(ProfileTestHelper::EqualInlineCaches(
+                      pmi.inline_caches, method_ref.dex_file, offline_hotness, info));
     }
   }
 }
diff --git a/runtime/jni/check_jni.cc b/runtime/jni/check_jni.cc
index 4a8453a..4c7b1aa 100644
--- a/runtime/jni/check_jni.cc
+++ b/runtime/jni/check_jni.cc
@@ -31,10 +31,11 @@
 #include "base/time_utils.h"
 #include "class_linker-inl.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
 #include "gc/space/space.h"
+#include "indirect_reference_table-inl.h"
 #include "java_vm_ext.h"
 #include "jni_internal.h"
 #include "mirror/class-inl.h"
@@ -50,6 +51,20 @@
 #include "well_known_classes.h"
 
 namespace art {
+
+// This helper cannot be in the anonymous namespace because it needs to be
+// declared as a friend by JniVmExt and JniEnvExt.
+inline IndirectReferenceTable* GetIndirectReferenceTable(ScopedObjectAccess& soa,
+                                                         IndirectRefKind kind) {
+  DCHECK_NE(kind, kJniTransitionOrInvalid);
+  JNIEnvExt* env = soa.Env();
+  IndirectReferenceTable* irt =
+      (kind == kLocal) ? &env->locals_
+                       : ((kind == kGlobal) ? &env->vm_->globals_ : &env->vm_->weak_globals_);
+  DCHECK_EQ(irt->GetKind(), kind);
+  return irt;
+}
+
 namespace {
 
 using android::base::StringAppendF;
@@ -703,11 +718,14 @@
     return true;
   }
 
-  bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
+  bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
     IndirectRefKind found_kind;
     if (expected_kind == kLocal) {
       found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
-      if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
+      if (found_kind == kJniTransitionOrInvalid &&
+          obj != nullptr &&
+          self->IsJniTransitionReference(obj)) {
         found_kind = kLocal;
       }
     } else {
@@ -842,26 +860,59 @@
       }
     }
 
-    ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
-    if (obj == nullptr) {
-      // Either java_object is invalid or is a cleared weak.
-      IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
-      bool okay;
-      if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
+    ObjPtr<mirror::Object> obj = nullptr;
+    IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
+    IndirectRefKind ref_kind = IndirectReferenceTable::GetIndirectRefKind(ref);
+    bool expect_null = false;
+    bool okay = true;
+    std::string error_msg;
+    if (ref_kind == kJniTransitionOrInvalid) {
+      if (!soa.Self()->IsJniTransitionReference(java_object)) {
         okay = false;
+        error_msg = "use of invalid jobject";
       } else {
-        obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
-        okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
+        obj = soa.Decode<mirror::Object>(java_object);
       }
-      if (!okay) {
-        AbortF("%s is an invalid %s: %p (%p)",
-               what,
-               GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
-               java_object,
-               obj.Ptr());
-        return false;
+    } else {
+      IndirectReferenceTable* irt = GetIndirectReferenceTable(soa, ref_kind);
+      okay = irt->IsValidReference(java_object, &error_msg);
+      DCHECK_EQ(okay, error_msg.empty());
+      if (okay) {
+        // Note: The `IsValidReference()` checks for null but we do not prevent races,
+        // so the null check below can still fail. Even if it succeeds, another thread
+        // could delete the global or weak global before it's used by JNI.
+        if (ref_kind == kLocal) {
+          // Local references do not need a read barrier.
+          obj = irt->Get<kWithoutReadBarrier>(ref);
+        } else if (ref_kind == kGlobal) {
+          obj = soa.Env()->GetVm()->DecodeGlobal(ref);
+        } else {
+          obj = soa.Env()->GetVm()->DecodeWeakGlobal(soa.Self(), ref);
+          if (Runtime::Current()->IsClearedJniWeakGlobal(obj)) {
+            obj = nullptr;
+            expect_null = true;
+          }
+        }
       }
     }
+    if (okay) {
+      if (!expect_null && obj == nullptr) {
+        okay = false;
+        error_msg = "deleted reference";
+      }
+      if (expect_null && !null_ok) {
+        okay = false;
+        error_msg = "cleared weak reference";
+      }
+    }
+    if (!okay) {
+      AbortF("JNI ERROR (app bug): %s is an invalid %s: %p (%s)",
+             what,
+             ToStr<IndirectRefKind>(ref_kind).c_str(),
+             java_object,
+             error_msg.c_str());
+      return false;
+    }
 
     if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
@@ -873,7 +924,6 @@
       return false;
     }
 
-    bool okay = true;
     switch (kind) {
     case kClass:
       okay = obj->IsClass();
@@ -2729,8 +2779,8 @@
     JniValueType args[2] = {{.E = env}, {.L = buf}};
     if (sc.Check(soa, true, "EL", args)) {
       JniValueType result;
-      // Note: this is implemented in the base environment by a GetLongField which will sanity
-      // check the type of buf in GetLongField above.
+      // Note: this is implemented in the base environment by a GetLongField which will check the
+      // type of buf in GetLongField above.
       result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
       if (sc.Check(soa, false, "p", &result)) {
         return const_cast<void*>(result.p);
@@ -2746,8 +2796,8 @@
     JniValueType args[2] = {{.E = env}, {.L = buf}};
     if (sc.Check(soa, true, "EL", args)) {
       JniValueType result;
-      // Note: this is implemented in the base environment by a GetIntField which will sanity
-      // check the type of buf in GetIntField above.
+      // Note: this is implemented in the base environment by a GetIntField which will check the
+      // type of buf in GetIntField above.
       result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
       if (sc.Check(soa, false, "J", &result)) {
         return result.J;
diff --git a/runtime/jni/java_vm_ext.cc b/runtime/jni/java_vm_ext.cc
index e5b3d4d..e085cd9 100644
--- a/runtime/jni/java_vm_ext.cc
+++ b/runtime/jni/java_vm_ext.cc
@@ -59,9 +59,11 @@
 using android::base::StringAppendF;
 using android::base::StringAppendV;
 
-static constexpr size_t kGlobalsMax = 51200;  // Arbitrary sanity check. (Must fit in 16 bits.)
+// Maximum number of global references (must fit in 16 bits).
+static constexpr size_t kGlobalsMax = 51200;
 
-static constexpr size_t kWeakGlobalsMax = 51200;  // Arbitrary sanity check. (Must fit in 16 bits.)
+// Maximum number of weak global references (must fit in 16 bits).
+static constexpr size_t kWeakGlobalsMax = 51200;
 
 bool JavaVMExt::IsBadJniVersion(int version) {
   // We don't support JNI_VERSION_1_1. These are the only other valid versions.
diff --git a/runtime/jni/java_vm_ext.h b/runtime/jni/java_vm_ext.h
index 6f7e546..015f85c 100644
--- a/runtime/jni/java_vm_ext.h
+++ b/runtime/jni/java_vm_ext.h
@@ -37,6 +37,7 @@
 class ParsedOptions;
 class Runtime;
 struct RuntimeArgumentMap;
+class ScopedObjectAccess;
 
 class JavaVMExt;
 // Hook definition for runtime plugins.
@@ -263,6 +264,9 @@
   std::atomic<bool> allocation_tracking_enabled_;
   std::atomic<bool> old_allocation_tracking_state_;
 
+  friend IndirectReferenceTable* GetIndirectReferenceTable(ScopedObjectAccess& soa,
+                                                           IndirectRefKind kind);
+
   DISALLOW_COPY_AND_ASSIGN(JavaVMExt);
 };
 
diff --git a/runtime/jni/java_vm_ext_test.cc b/runtime/jni/java_vm_ext_test.cc
index 4a7b1ca..0363cdb 100644
--- a/runtime/jni/java_vm_ext_test.cc
+++ b/runtime/jni/java_vm_ext_test.cc
@@ -151,7 +151,7 @@
   ASSERT_EQ(JNI_OK, ok);
 
   std::vector<jobject> global_refs_;
-  jobject local_ref = env->NewStringUTF("Dummy");
+  jobject local_ref = env->NewStringUTF("Hello");
   for (size_t i = 0; i < 2000; ++i) {
     global_refs_.push_back(env->NewGlobalRef(local_ref));
   }
diff --git a/runtime/jni/jni_env_ext.cc b/runtime/jni/jni_env_ext.cc
index cf6a22c..6e46c24 100644
--- a/runtime/jni/jni_env_ext.cc
+++ b/runtime/jni/jni_env_ext.cc
@@ -40,7 +40,7 @@
 using android::base::StringPrintf;
 
 static constexpr size_t kMonitorsInitial = 32;  // Arbitrary.
-static constexpr size_t kMonitorsMax = 4096;  // Arbitrary sanity check.
+static constexpr size_t kMonitorsMax = 4096;  // Maximum number of monitors held by JNI code.
 
 const JNINativeInterface* JNIEnvExt::table_override_ = nullptr;
 
diff --git a/runtime/jni/jni_env_ext.h b/runtime/jni/jni_env_ext.h
index 2c7ba3b..2fae8d2 100644
--- a/runtime/jni/jni_env_ext.h
+++ b/runtime/jni/jni_env_ext.h
@@ -30,6 +30,7 @@
 class ArtMethod;
 class ArtField;
 class JavaVMExt;
+class ScopedObjectAccess;
 class ScopedObjectAccessAlreadyRunnable;
 
 namespace mirror {
@@ -37,7 +38,7 @@
 }  // namespace mirror
 
 // Number of local references in the indirect reference table. The value is arbitrary but
-// low enough that it forces sanity checks.
+// low enough that it forces integrity checks.
 static constexpr size_t kLocalsInitial = 512;
 
 class JNIEnvExt : public JNIEnv {
@@ -212,6 +213,8 @@
   template<bool kEnableIndexIds> friend class JNI;
   friend class ScopedJniEnvLocalRefState;
   friend class Thread;
+  friend IndirectReferenceTable* GetIndirectReferenceTable(ScopedObjectAccess& soa,
+                                                           IndirectRefKind kind);
   friend void ThreadResetFunctionTable(Thread* thread, void* arg);
   ART_FRIEND_TEST(JniInternalTest, JNIEnvExtOffsets);
 };
diff --git a/runtime/jni/jni_id_manager.cc b/runtime/jni/jni_id_manager.cc
index 8070505..402259b 100644
--- a/runtime/jni/jni_id_manager.cc
+++ b/runtime/jni/jni_id_manager.cc
@@ -27,6 +27,7 @@
 #include "base/globals.h"
 #include "base/locks.h"
 #include "base/mutex.h"
+#include "class_root-inl.h"
 #include "gc/allocation_listener.h"
 #include "gc/heap.h"
 #include "jni/jni_internal.h"
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index 67073a8..f483ad3 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -17,6 +17,7 @@
 #include "jni_internal.h"
 
 #include <cstdarg>
+#include <log/log.h>
 #include <memory>
 #include <utility>
 
@@ -24,6 +25,7 @@
 #include "art_method-inl.h"
 #include "base/allocator.h"
 #include "base/atomic.h"
+#include "base/casts.h"
 #include "base/enums.h"
 #include "base/file_utils.h"
 #include "base/logging.h"  // For VLOG.
@@ -31,9 +33,9 @@
 #include "base/safe_map.h"
 #include "base/stl_util.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/dex_file-inl.h"
-#include "dex/utf.h"
+#include "dex/utf-inl.h"
 #include "fault_handler.h"
 #include "hidden_api.h"
 #include "gc/accounting/card_table-inl.h"
@@ -47,7 +49,7 @@
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache-inl.h"
-#include "mirror/field-inl.h"
+#include "mirror/field.h"
 #include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-alloc-inl.h"
@@ -63,7 +65,10 @@
 #include "thread.h"
 #include "well_known_classes.h"
 
+namespace art {
+
 namespace {
+
 // Frees the given va_list upon destruction.
 // This also guards the returns from inside of the CHECK_NON_NULL_ARGUMENTs.
 struct ScopedVAArgs {
@@ -76,28 +81,108 @@
   va_list* args;
 };
 
-}  // namespace
+constexpr char kBadUtf8ReplacementChar[] = "?";
 
-namespace art {
+// This is a modified version of CountModifiedUtf8Chars() from utf.cc
+// with extra checks and different output options.
+//
+// The `good` functor can process valid characters.
+// The `bad` functor is called when we find an invalid character and
+// returns true to abort processing, or false to continue processing.
+//
+// When aborted, VisitModifiedUtf8Chars() returns 0, otherwise the
+// number of UTF-16 chars.
+template <typename GoodFunc, typename BadFunc>
+size_t VisitModifiedUtf8Chars(const char* utf8, size_t byte_count, GoodFunc good, BadFunc bad) {
+  DCHECK_LE(byte_count, strlen(utf8));
+  size_t len = 0;
+  const char* end = utf8 + byte_count;
+  while (utf8 != end) {
+    int ic = *utf8;
+    if (LIKELY((ic & 0x80) == 0)) {
+      // One-byte encoding.
+      good(utf8, 1u);
+      utf8 += 1u;
+      len += 1u;
+      continue;
+    }
+    auto is_ascii = [utf8]() {
+      const char* ptr = utf8;  // Make a copy that can be modified by GetUtf16FromUtf8().
+      return mirror::String::IsASCII(dchecked_integral_cast<uint16_t>(GetUtf16FromUtf8(&ptr)));
+    };
+    // Note: Neither CountModifiedUtf8Chars() nor GetUtf16FromUtf8() checks whether
+    // the bit 0x40 is correctly set in the leading byte of a multi-byte sequence.
+    if ((ic & 0x20) == 0) {
+      // Two-byte encoding.
+      if (static_cast<size_t>(end - utf8) < 2u) {
+        return bad() ? 0u : len + 1u;  // Reached end of sequence
+      }
+      if (mirror::kUseStringCompression && is_ascii()) {
+        if (bad()) {
+          return 0u;
+        }
+      } else {
+        good(utf8, 2u);
+      }
+      utf8 += 2u;
+      len += 1u;
+      continue;
+    }
+    if ((ic & 0x10) == 0) {
+      // Three-byte encoding.
+      if (static_cast<size_t>(end - utf8) < 3u) {
+        return bad() ? 0u : len + 1u;  // Reached end of sequence
+      }
+      if (mirror::kUseStringCompression && is_ascii()) {
+        if (bad()) {
+          return 0u;
+        }
+      } else {
+        good(utf8, 3u);
+      }
+      utf8 += 3u;
+      len += 1u;
+      continue;
+    }
+
+    // Four-byte encoding: needs to be converted into a surrogate pair.
+    // The decoded chars are never ASCII.
+    if (static_cast<size_t>(end - utf8) < 4u) {
+      return bad() ? 0u : len + 1u;  // Reached end of sequence
+    }
+    good(utf8, 4u);
+    utf8 += 4u;
+    len += 2u;
+  }
+  return len;
+}
+
+}  // namespace
 
 // Consider turning this on when there is errors which could be related to JNI array copies such as
 // things not rendering correctly. E.g. b/16858794
 static constexpr bool kWarnJniAbort = false;
 
+static hiddenapi::AccessContext GetJniAccessContext(Thread* self)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  // Construct AccessContext from the first calling class on stack.
+  // If the calling class cannot be determined, e.g. unattached threads,
+  // we conservatively assume the caller is trusted.
+  ObjPtr<mirror::Class> caller = GetCallingClass(self, /* num_frames= */ 1);
+  return caller.IsNull() ? hiddenapi::AccessContext(/* is_trusted= */ true)
+                         : hiddenapi::AccessContext(caller);
+}
+
 template<typename T>
-ALWAYS_INLINE static bool ShouldDenyAccessToMember(T* member, Thread* self)
+ALWAYS_INLINE static bool ShouldDenyAccessToMember(
+    T* member,
+    Thread* self,
+    hiddenapi::AccessMethod access_kind = hiddenapi::AccessMethod::kJNI)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   return hiddenapi::ShouldDenyAccessToMember(
       member,
-      [&]() REQUIRES_SHARED(Locks::mutator_lock_) {
-        // Construct AccessContext from the first calling class on stack.
-        // If the calling class cannot be determined, e.g. unattached threads,
-        // we conservatively assume the caller is trusted.
-        ObjPtr<mirror::Class> caller = GetCallingClass(self, /* num_frames */ 1);
-        return caller.IsNull() ? hiddenapi::AccessContext(/* is_trusted= */ true)
-                               : hiddenapi::AccessContext(caller);
-      },
-      hiddenapi::AccessMethod::kJNI);
+      [self]() REQUIRES_SHARED(Locks::mutator_lock_) { return GetJniAccessContext(self); },
+      access_kind);
 }
 
 // Helpers to call instrumentation functions for fields. These take jobjects so we don't need to set
@@ -327,8 +412,22 @@
   } else {
     method = c->FindClassMethod(name, sig, pointer_size);
   }
-  if (method != nullptr && ShouldDenyAccessToMember(method, soa.Self())) {
-    method = nullptr;
+  if (method != nullptr &&
+      ShouldDenyAccessToMember(method, soa.Self(), hiddenapi::AccessMethod::kNone)) {
+    // The resolved method that we have found cannot be accessed due to
+    // hiddenapi (typically it is declared up the hierarchy and is not an SDK
+    // method). Try to find an interface method from the implemented interfaces which is
+    // accessible.
+    ArtMethod* itf_method = c->FindAccessibleInterfaceMethod(method, pointer_size);
+    if (itf_method == nullptr) {
+      // No interface method. Call ShouldDenyAccessToMember again but this time
+      // with AccessMethod::kJNI to ensure that an appropriate warning is
+      // logged.
+      ShouldDenyAccessToMember(method, soa.Self(), hiddenapi::AccessMethod::kJNI);
+      method = nullptr;
+    } else {
+      // We found an interface method that is accessible, continue with the resolved method.
+    }
   }
   if (method == nullptr || method->IsStatic() != is_static) {
     ThrowNoSuchMethodError(soa, c, name, sig, is_static ? "static" : "non-static");
@@ -531,11 +630,10 @@
     ArtMethod* m = jni::DecodeArtMethod(mid);
     ObjPtr<mirror::Executable> method;
     DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
-    DCHECK(!Runtime::Current()->IsActiveTransaction());
     if (m->IsConstructor()) {
-      method = mirror::Constructor::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), m);
+      method = mirror::Constructor::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), m);
     } else {
-      method = mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), m);
+      method = mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), m);
     }
     return soa.AddLocalReference<jobject>(method);
   }
@@ -545,7 +643,7 @@
     ScopedObjectAccess soa(env);
     ArtField* f = jni::DecodeArtField(fid);
     return soa.AddLocalReference<jobject>(
-        mirror::Field::CreateFromArtField<kRuntimePointerSize>(soa.Self(), f, true));
+        mirror::Field::CreateFromArtField(soa.Self(), f, true));
   }
 
   static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
@@ -1812,8 +1910,62 @@
     if (utf == nullptr) {
       return nullptr;
     }
+
+    // The input may come from an untrusted source, so we need to validate it.
+    // We do not perform full validation, only as much as necessary to avoid reading
+    // beyond the terminating null character or breaking string compression invariants.
+    // CheckJNI performs stronger validation.
+    size_t utf8_length = strlen(utf);
+    if (UNLIKELY(utf8_length > static_cast<uint32_t>(std::numeric_limits<int32_t>::max()))) {
+      // Converting the utf8_length to int32_t for String::AllocFromModifiedUtf8() would
+      // overflow. Throw OOME eagerly to avoid 2GiB allocation when trying to replace
+      // invalid sequences (even if such replacements could reduce the size below 2GiB).
+      std::string error =
+          android::base::StringPrintf("NewStringUTF input is 2 GiB or more: %zu", utf8_length);
+      ScopedObjectAccess soa(env);
+      soa.Self()->ThrowOutOfMemoryError(error.c_str());
+      return nullptr;
+    }
+    std::optional<std::string> replacement_utf;
+    size_t utf16_length = VisitModifiedUtf8Chars(
+        utf,
+        utf8_length,
+        /*good=*/ [](const char* ptr ATTRIBUTE_UNUSED, size_t length ATTRIBUTE_UNUSED) {},
+        /*bad=*/ []() { return true; });  // Abort processing and return 0 for bad characters.
+    if (UNLIKELY(utf8_length != 0u && utf16_length == 0u)) {
+      // VisitModifiedUtf8Chars() aborted for a bad character.
+      android_errorWriteLog(0x534e4554, "172655291");  // Report to SafetyNet.
+      // Report the error to logcat but avoid too much spam.
+      static const uint64_t kMinDelay = UINT64_C(10000000000);  // 10s
+      static std::atomic<uint64_t> prev_bad_input_time(UINT64_C(0));
+      uint64_t prev_time = prev_bad_input_time.load(std::memory_order_relaxed);
+      uint64_t now = NanoTime();
+      if ((prev_time == 0u || now - prev_time >= kMinDelay) &&
+          prev_bad_input_time.compare_exchange_strong(prev_time, now, std::memory_order_relaxed)) {
+        LOG(ERROR) << "Invalid UTF-8 input to JNI::NewStringUTF()";
+      }
+      // Copy the input to the `replacement_utf` and replace bad characters.
+      replacement_utf.emplace();
+      replacement_utf->reserve(utf8_length);
+      utf16_length = VisitModifiedUtf8Chars(
+          utf,
+          utf8_length,
+          /*good=*/ [&](const char* ptr, size_t length) {
+            replacement_utf->append(ptr, length);
+          },
+          /*bad=*/ [&]() {
+            replacement_utf->append(kBadUtf8ReplacementChar, sizeof(kBadUtf8ReplacementChar) - 1u);
+            return false;  // Continue processing.
+          });
+      utf = replacement_utf->c_str();
+      utf8_length = replacement_utf->length();
+    }
+    DCHECK_LE(utf16_length, utf8_length);
+    DCHECK_LE(utf8_length, static_cast<uint32_t>(std::numeric_limits<int32_t>::max()));
+
     ScopedObjectAccess soa(env);
-    ObjPtr<mirror::String> result = mirror::String::AllocFromModifiedUtf8(soa.Self(), utf);
+    ObjPtr<mirror::String> result =
+        mirror::String::AllocFromModifiedUtf8(soa.Self(), utf16_length, utf, utf8_length);
     return soa.AddLocalReference<jstring>(result);
   }
 
@@ -1839,8 +1991,9 @@
     } else {
       CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
       if (s->IsCompressed()) {
+        const uint8_t* src = s->GetValueCompressed() + start;
         for (int i = 0; i < length; ++i) {
-          buf[i] = static_cast<jchar>(s->CharAt(start+i));
+          buf[i] = static_cast<jchar>(src[i]);
         }
       } else {
         const jchar* chars = static_cast<jchar*>(s->GetValue());
@@ -1858,14 +2011,21 @@
       ThrowSIOOBE(soa, start, length, s->GetLength());
     } else {
       CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
+      if (length == 0 && buf == nullptr) {
+        // Don't touch anything when length is 0 and null buffer.
+        return;
+      }
       if (s->IsCompressed()) {
+        const uint8_t* src = s->GetValueCompressed() + start;
         for (int i = 0; i < length; ++i) {
-          buf[i] = s->CharAt(start+i);
+          buf[i] = static_cast<jchar>(src[i]);
         }
+        buf[length] = '\0';
       } else {
         const jchar* chars = s->GetValue();
         size_t bytes = CountUtf8Bytes(chars + start, length);
         ConvertUtf16ToModifiedUtf8(buf, bytes, chars + start, length);
+        buf[bytes] = '\0';
       }
     }
   }
@@ -1879,8 +2039,9 @@
       jchar* chars = new jchar[s->GetLength()];
       if (s->IsCompressed()) {
         int32_t length = s->GetLength();
+        const uint8_t* src = s->GetValueCompressed();
         for (int i = 0; i < length; ++i) {
-          chars[i] = s->CharAt(i);
+          chars[i] = static_cast<jchar>(src[i]);
         }
       } else {
         memcpy(chars, s->GetValue(), sizeof(jchar) * s->GetLength());
@@ -1910,28 +2071,29 @@
     ScopedObjectAccess soa(env);
     ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_string);
     gc::Heap* heap = Runtime::Current()->GetHeap();
-    if (heap->IsMovableObject(s)) {
-      StackHandleScope<1> hs(soa.Self());
-      HandleWrapperObjPtr<mirror::String> h(hs.NewHandleWrapper(&s));
-      if (!kUseReadBarrier) {
-        heap->IncrementDisableMovingGC(soa.Self());
-      } else {
-        // For the CC collector, we only need to wait for the thread flip rather than the whole GC
-        // to occur thanks to the to-space invariant.
-        heap->IncrementDisableThreadFlip(soa.Self());
-      }
-    }
     if (s->IsCompressed()) {
       if (is_copy != nullptr) {
         *is_copy = JNI_TRUE;
       }
       int32_t length = s->GetLength();
+      const uint8_t* src = s->GetValueCompressed();
       jchar* chars = new jchar[length];
       for (int i = 0; i < length; ++i) {
-        chars[i] = s->CharAt(i);
+        chars[i] = static_cast<jchar>(src[i]);
       }
       return chars;
     } else {
+      if (heap->IsMovableObject(s)) {
+        StackHandleScope<1> hs(soa.Self());
+        HandleWrapperObjPtr<mirror::String> h(hs.NewHandleWrapper(&s));
+        if (!kUseReadBarrier) {
+          heap->IncrementDisableMovingGC(soa.Self());
+        } else {
+          // For the CC collector, we only need to wait for the thread flip rather
+          // than the whole GC to occur thanks to the to-space invariant.
+          heap->IncrementDisableThreadFlip(soa.Self());
+        }
+      }
       if (is_copy != nullptr) {
         *is_copy = JNI_FALSE;
       }
@@ -1946,14 +2108,16 @@
     ScopedObjectAccess soa(env);
     gc::Heap* heap = Runtime::Current()->GetHeap();
     ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_string);
-    if (heap->IsMovableObject(s)) {
+    if (!s->IsCompressed() && heap->IsMovableObject(s)) {
       if (!kUseReadBarrier) {
         heap->DecrementDisableMovingGC(soa.Self());
       } else {
         heap->DecrementDisableThreadFlip(soa.Self());
       }
     }
-    if (s->IsCompressed() || (s->IsCompressed() == false && s->GetValue() != chars)) {
+    // TODO: For uncompressed strings GetStringCritical() always returns `s->GetValue()`.
+    // Should we report an error if the user passes a different `chars`?
+    if (s->IsCompressed() || (!s->IsCompressed() && s->GetValue() != chars)) {
       delete[] chars;
     }
   }
@@ -1971,8 +2135,9 @@
     char* bytes = new char[byte_count + 1];
     CHECK(bytes != nullptr);  // bionic aborts anyway.
     if (s->IsCompressed()) {
+      const uint8_t* src = s->GetValueCompressed();
       for (size_t i = 0; i < byte_count; ++i) {
-        bytes[i] = s->CharAt(i);
+        bytes[i] = src[i];
       }
     } else {
       const uint16_t* chars = s->GetValue();
@@ -2305,6 +2470,7 @@
       return JNI_ERR;  // Not reached except in unit tests.
     }
     CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", java_class, JNI_ERR);
+    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     ScopedObjectAccess soa(env);
     StackHandleScope<1> hs(soa.Self());
     Handle<mirror::Class> c = hs.NewHandle(soa.Decode<mirror::Class>(java_class));
@@ -2421,7 +2587,7 @@
         // TODO: make this a hard register error in the future.
       }
 
-      const void* final_function_ptr = m->RegisterNative(fnPtr);
+      const void* final_function_ptr = class_linker->RegisterNative(soa.Self(), m, fnPtr);
       UNUSED(final_function_ptr);
     }
     return JNI_OK;
@@ -2435,10 +2601,11 @@
     VLOG(jni) << "[Unregistering JNI native methods for " << mirror::Class::PrettyClass(c) << "]";
 
     size_t unregistered_count = 0;
-    auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+    auto pointer_size = class_linker->GetImagePointerSize();
     for (auto& m : c->GetMethods(pointer_size)) {
       if (m.IsNative()) {
-        m.UnregisterNative();
+        class_linker->UnregisterNative(soa.Self(), &m);
         unregistered_count++;
       }
     }
@@ -2519,13 +2686,45 @@
   }
 
   static void* GetDirectBufferAddress(JNIEnv* env, jobject java_buffer) {
+    // Return null if |java_buffer| is not defined.
+    if (java_buffer == nullptr) {
+      return nullptr;
+    }
+
+    // Return null if |java_buffer| is not a java.nio.Buffer instance.
+    if (!IsInstanceOf(env, java_buffer, WellKnownClasses::java_nio_Buffer)) {
+      return nullptr;
+    }
+
+    // Buffer.address is non-null when the |java_buffer| is direct.
     return reinterpret_cast<void*>(env->GetLongField(
-        java_buffer, WellKnownClasses::java_nio_DirectByteBuffer_effectiveDirectAddress));
+        java_buffer, WellKnownClasses::java_nio_Buffer_address));
   }
 
   static jlong GetDirectBufferCapacity(JNIEnv* env, jobject java_buffer) {
+    if (java_buffer == nullptr) {
+      return -1;
+    }
+
+    if (!IsInstanceOf(env, java_buffer, WellKnownClasses::java_nio_Buffer)) {
+      return -1;
+    }
+
+    // When checking the buffer capacity, it's important to note that a zero-sized direct buffer
+    // may have a null address field which means we can't tell whether it is direct or not.
+    // We therefore call Buffer.isDirect(). One path that creates such a buffer is
+    // FileChannel.map() if the file size is zero.
+    //
+    // NB GetDirectBufferAddress() does not need to call Buffer.isDirect() since it is only
+    // able return a valid address if the Buffer address field is not-null.
+    jboolean direct = env->CallBooleanMethod(java_buffer,
+                                             WellKnownClasses::java_nio_Buffer_isDirect);
+    if (!direct) {
+      return -1;
+    }
+
     return static_cast<jlong>(env->GetIntField(
-        java_buffer, WellKnownClasses::java_nio_DirectByteBuffer_capacity));
+        java_buffer, WellKnownClasses::java_nio_Buffer_capacity));
   }
 
   static jobjectRefType GetObjectRefType(JNIEnv* env ATTRIBUTE_UNUSED, jobject java_object) {
@@ -2543,8 +2742,8 @@
       return JNIGlobalRefType;
     case kWeakGlobal:
       return JNIWeakGlobalRefType;
-    case kHandleScopeOrInvalid:
-      // Assume value is in a handle scope.
+    case kJniTransitionOrInvalid:
+      // Assume value is in a JNI transition frame.
       return JNILocalRefType;
     }
     LOG(FATAL) << "IndirectRefKind[" << kind << "]";
@@ -2651,7 +2850,7 @@
     bool is_copy = array_data != elements;
     size_t bytes = array->GetLength() * component_size;
     if (is_copy) {
-      // Sanity check: If elements is not the same as the java array's data, it better not be a
+      // Integrity check: If elements is not the same as the java array's data, it better not be a
       // heap address. TODO: This might be slow to check, may be worth keeping track of which
       // copies we make?
       if (heap->IsNonDiscontinuousSpaceHeapAddress(elements)) {
diff --git a/runtime/jni/jni_internal_test.cc b/runtime/jni/jni_internal_test.cc
index a4b3801..ed84397 100644
--- a/runtime/jni/jni_internal_test.cc
+++ b/runtime/jni/jni_internal_test.cc
@@ -19,6 +19,7 @@
 #include "android-base/stringprintf.h"
 
 #include "art_method-inl.h"
+#include "base/mem_map.h"
 #include "common_runtime_test.h"
 #include "indirect_reference_table.h"
 #include "java_vm_ext.h"
@@ -784,7 +785,7 @@
   jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
   jclass jncrbc = env_->FindClass("java/nio/channels/ReadableByteChannel");
 
-  // Sanity check that no exceptions are pending.
+  // Check that no exceptions are pending.
   ASSERT_FALSE(env_->ExceptionCheck());
 
   // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
@@ -905,7 +906,7 @@
   jclass jlobject = env_->FindClass("java/lang/Object");
   jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
 
-  // Sanity check that no exceptions are pending
+  // Check that no exceptions are pending
   ASSERT_FALSE(env_->ExceptionCheck());
 
   // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
@@ -1035,7 +1036,7 @@
   jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
   void* native_function = reinterpret_cast<void*>(BogusMethod);
 
-  // Sanity check that no exceptions are pending.
+  // Check that no exceptions are pending.
   ASSERT_FALSE(env_->ExceptionCheck());
 
   // The following can print errors to the log we'd like to ignore.
@@ -1550,6 +1551,114 @@
   EXPECT_EQ(13, env_->GetStringUTFLength(s));
 }
 
+TEST_F(JniInternalTest, NewStringUTF_Validation) {
+  // For the following tests, allocate two pages, one R/W and the next inaccessible.
+  std::string error_msg;
+  MemMap head_map = MemMap::MapAnonymous(
+      "head", 2 * kPageSize, PROT_READ | PROT_WRITE, /*low_4gb=*/ false, &error_msg);
+  ASSERT_TRUE(head_map.IsValid()) << error_msg;
+  MemMap tail_map = head_map.RemapAtEnd(
+      head_map.Begin() + kPageSize, "tail", PROT_NONE, &error_msg);
+  ASSERT_TRUE(tail_map.IsValid()) << error_msg;
+  char* utf_src = reinterpret_cast<char*>(head_map.Begin());
+
+  // Prepare for checking the `count` field.
+  jclass c = env_->FindClass("java/lang/String");
+  ASSERT_NE(c, nullptr);
+  jfieldID count_fid = env_->GetFieldID(c, "count", "I");
+  ASSERT_TRUE(count_fid != nullptr);
+
+  // Prepare for testing with the unchecked interface.
+  const JNINativeInterface* base_env = down_cast<JNIEnvExt*>(env_)->GetUncheckedFunctions();
+
+  // Start with a simple ASCII string consisting of 4095 characters 'x'.
+  memset(utf_src, 'x', kPageSize - 1u);
+  utf_src[kPageSize - 1u] = 0u;
+  jstring s = base_env->NewStringUTF(env_, utf_src);
+  ASSERT_EQ(mirror::String::GetFlaggedCount(kPageSize - 1u, /* compressible= */ true),
+            env_->GetIntField(s, count_fid));
+  const char* chars = env_->GetStringUTFChars(s, nullptr);
+  for (size_t pos = 0; pos != kPageSize - 1u; ++pos) {
+    ASSERT_EQ('x', chars[pos]) << pos;
+  }
+  env_->ReleaseStringUTFChars(s, chars);
+
+  // Replace the last character with invalid character that requires continuation.
+  for (char invalid : { '\xc0', '\xe0', '\xf0' }) {
+    utf_src[kPageSize - 2u] = invalid;
+    s = base_env->NewStringUTF(env_, utf_src);
+    ASSERT_EQ(mirror::String::GetFlaggedCount(kPageSize - 1u, /* compressible= */ true),
+              env_->GetIntField(s, count_fid));
+    chars = env_->GetStringUTFChars(s, nullptr);
+    for (size_t pos = 0; pos != kPageSize - 2u; ++pos) {
+      ASSERT_EQ('x', chars[pos]) << pos;
+    }
+    EXPECT_EQ('?', chars[kPageSize - 2u]);
+    env_->ReleaseStringUTFChars(s, chars);
+  }
+
+  // Replace the first two characters with a valid two-byte sequence yielding one character.
+  utf_src[0] = '\xc2';
+  utf_src[1] = '\x80';
+  s = base_env->NewStringUTF(env_, utf_src);
+  ASSERT_EQ(mirror::String::GetFlaggedCount(kPageSize - 2u, /* compressible= */ false),
+            env_->GetIntField(s, count_fid));
+  const jchar* jchars = env_->GetStringChars(s, nullptr);
+  EXPECT_EQ(jchars[0], 0x80u);
+  for (size_t pos = 1; pos != kPageSize - 3u; ++pos) {
+    ASSERT_EQ('x', jchars[pos]) << pos;
+  }
+  EXPECT_EQ('?', jchars[kPageSize - 3u]);
+  env_->ReleaseStringChars(s, jchars);
+
+  // Replace the leading two-byte sequence with a two-byte sequence that decodes as ASCII (0x40).
+  // The sequence shall be replaced if string compression is used.
+  utf_src[0] = '\xc1';
+  utf_src[1] = '\x80';
+  s = base_env->NewStringUTF(env_, utf_src);
+  // Note: All invalid characters are replaced by ASCII replacement character.
+  ASSERT_EQ(mirror::String::GetFlaggedCount(kPageSize - 2u, /* compressible= */ true),
+            env_->GetIntField(s, count_fid));
+  jchars = env_->GetStringChars(s, nullptr);
+  EXPECT_EQ(mirror::kUseStringCompression ? '?' : '\x40', jchars[0]);
+  for (size_t pos = 1; pos != kPageSize - 3u; ++pos) {
+    ASSERT_EQ('x', jchars[pos]) << pos;
+  }
+  EXPECT_EQ('?', jchars[kPageSize - 3u]);
+  env_->ReleaseStringChars(s, jchars);
+
+  // Replace the leading three bytes with a three-byte sequence that decodes as ASCII (0x40).
+  // The sequence shall be replaced if string compression is used.
+  utf_src[0] = '\xe0';
+  utf_src[1] = '\x81';
+  utf_src[2] = '\x80';
+  s = base_env->NewStringUTF(env_, utf_src);
+  // Note: All invalid characters are replaced by ASCII replacement character.
+  ASSERT_EQ(mirror::String::GetFlaggedCount(kPageSize - 3u, /* compressible= */ true),
+            env_->GetIntField(s, count_fid));
+  jchars = env_->GetStringChars(s, nullptr);
+  EXPECT_EQ(mirror::kUseStringCompression ? '?' : '\x40', jchars[0]);
+  for (size_t pos = 1; pos != kPageSize - 4u; ++pos) {
+    ASSERT_EQ('x', jchars[pos]) << pos;
+  }
+  EXPECT_EQ('?', jchars[kPageSize - 4u]);
+  env_->ReleaseStringChars(s, jchars);
+
+  // Replace the last two characters with a valid two-byte sequence that decodes as 0.
+  utf_src[kPageSize - 3u] = '\xc0';
+  utf_src[kPageSize - 2u] = '\x80';
+  s = base_env->NewStringUTF(env_, utf_src);
+  ASSERT_EQ(mirror::String::GetFlaggedCount(kPageSize - 4u, /* compressible= */ false),
+            env_->GetIntField(s, count_fid));
+  jchars = env_->GetStringChars(s, nullptr);
+  EXPECT_EQ(mirror::kUseStringCompression ? '?' : '\x40', jchars[0]);
+  for (size_t pos = 1; pos != kPageSize - 5u; ++pos) {
+    ASSERT_EQ('x', jchars[pos]) << pos;
+  }
+  EXPECT_EQ('\0', jchars[kPageSize - 5u]);
+  env_->ReleaseStringChars(s, jchars);
+}
+
 TEST_F(JniInternalTest, NewString) {
   jchar chars[] = { 'h', 'i' };
   jstring s;
@@ -1637,18 +1746,27 @@
   env_->GetStringUTFRegion(s, 0x7fffffff, 0x7fffffff, nullptr);
   ExpectException(sioobe_);
 
-  char bytes[4] = { 'x', 'x', 'x', 'x' };
+  char bytes[5] = { 'x', 'x', 'x', 'x', 'x' };
   env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
   EXPECT_EQ('x', bytes[0]);
   EXPECT_EQ('e', bytes[1]);
   EXPECT_EQ('l', bytes[2]);
-  EXPECT_EQ('x', bytes[3]);
+  // NB: The output string is null terminated so this slot is overwritten.
+  EXPECT_EQ('\0', bytes[3]);
+  EXPECT_EQ('x', bytes[4]);
 
   // It's okay for the buffer to be null as long as the length is 0.
   env_->GetStringUTFRegion(s, 2, 0, nullptr);
   // Even if the offset is invalid...
   env_->GetStringUTFRegion(s, 123, 0, nullptr);
   ExpectException(sioobe_);
+  // If not null we still have a 0 length string
+  env_->GetStringUTFRegion(s, 1, 0, &bytes[1]);
+  EXPECT_EQ('x', bytes[0]);
+  EXPECT_EQ('\0', bytes[1]);
+  EXPECT_EQ('l', bytes[2]);
+  EXPECT_EQ('\0', bytes[3]);
+  EXPECT_EQ('x', bytes[4]);
 }
 
 TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
@@ -1987,17 +2105,12 @@
   ASSERT_NE(s, nullptr);
   env_->DeleteLocalRef(s);
 
-  // Currently, deleting an already-deleted reference is just a CheckJNI warning.
+  // Currently, deleting an already-deleted reference is just a CheckJNI abort.
   {
-    bool old_check_jni = vm_->SetCheckJniEnabled(false);
-    {
-      CheckJniAbortCatcher check_jni_abort_catcher;
-      env_->DeleteLocalRef(s);
-    }
+    bool old_check_jni = vm_->SetCheckJniEnabled(true);
     CheckJniAbortCatcher check_jni_abort_catcher;
-    EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
     env_->DeleteLocalRef(s);
-    std::string expected(StringPrintf("use of deleted local reference %p", s));
+    std::string expected = StringPrintf("jobject is an invalid local reference: %p", s);
     check_jni_abort_catcher.Check(expected.c_str());
     EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
   }
@@ -2052,7 +2165,7 @@
     {
       CheckJniAbortCatcher check_jni_abort_catcher;
       EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
-      check_jni_abort_catcher.Check("use of deleted local reference");
+      check_jni_abort_catcher.Check("jobject is an invalid local reference");
     }
 
     // Our local reference for the survivor is invalid because the survivor
@@ -2060,7 +2173,7 @@
     {
       CheckJniAbortCatcher check_jni_abort_catcher;
       EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
-      check_jni_abort_catcher.Check("use of deleted local reference");
+      check_jni_abort_catcher.Check("jobject is an invalid local reference");
     }
 
     EXPECT_EQ(env_->PopLocalFrame(nullptr), nullptr);
@@ -2068,11 +2181,11 @@
   EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
   CheckJniAbortCatcher check_jni_abort_catcher;
   EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
-  check_jni_abort_catcher.Check("use of deleted local reference");
+  check_jni_abort_catcher.Check("jobject is an invalid local reference");
   EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
-  check_jni_abort_catcher.Check("use of deleted local reference");
+  check_jni_abort_catcher.Check("jobject is an invalid local reference");
   EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
-  check_jni_abort_catcher.Check("use of deleted local reference");
+  check_jni_abort_catcher.Check("jobject is an invalid local reference");
 }
 
 TEST_F(JniInternalTest, PushLocalFrame_LimitAndOverflow) {
@@ -2126,17 +2239,12 @@
   ASSERT_NE(o, nullptr);
   env_->DeleteGlobalRef(o);
 
-  // Currently, deleting an already-deleted reference is just a CheckJNI warning.
+  // Currently, deleting an already-deleted reference is just a CheckJNI abort.
   {
-    bool old_check_jni = vm_->SetCheckJniEnabled(false);
-    {
-      CheckJniAbortCatcher check_jni_abort_catcher;
-      env_->DeleteGlobalRef(o);
-    }
+    bool old_check_jni = vm_->SetCheckJniEnabled(true);
     CheckJniAbortCatcher check_jni_abort_catcher;
-    EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
     env_->DeleteGlobalRef(o);
-    std::string expected(StringPrintf("use of deleted global reference %p", o));
+    std::string expected = StringPrintf("jobject is an invalid global reference: %p", o);
     check_jni_abort_catcher.Check(expected.c_str());
     EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
   }
@@ -2179,17 +2287,12 @@
   ASSERT_NE(o, nullptr);
   env_->DeleteWeakGlobalRef(o);
 
-  // Currently, deleting an already-deleted reference is just a CheckJNI warning.
+  // Currently, deleting an already-deleted reference is just a CheckJNI abort.
   {
-    bool old_check_jni = vm_->SetCheckJniEnabled(false);
-    {
-      CheckJniAbortCatcher check_jni_abort_catcher;
-      env_->DeleteWeakGlobalRef(o);
-    }
+    bool old_check_jni = vm_->SetCheckJniEnabled(true);
     CheckJniAbortCatcher check_jni_abort_catcher;
-    EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
     env_->DeleteWeakGlobalRef(o);
-    std::string expected(StringPrintf("use of deleted weak global reference %p", o));
+    std::string expected(StringPrintf("jobject is an invalid weak global reference: %p", o));
     check_jni_abort_catcher.Check(expected.c_str());
     EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
   }
@@ -2281,11 +2384,30 @@
   ASSERT_NE(buffer_class, nullptr);
 
   char bytes[1024];
-  jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
-  ASSERT_NE(buffer, nullptr);
-  ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class));
-  ASSERT_EQ(env_->GetDirectBufferAddress(buffer), bytes);
-  ASSERT_EQ(env_->GetDirectBufferCapacity(buffer), static_cast<jlong>(sizeof(bytes)));
+  jobject direct_buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
+  ASSERT_NE(direct_buffer, nullptr);
+  ASSERT_TRUE(env_->IsInstanceOf(direct_buffer, buffer_class));
+  ASSERT_EQ(env_->GetDirectBufferAddress(direct_buffer), bytes);
+  ASSERT_EQ(env_->GetDirectBufferCapacity(direct_buffer), static_cast<jlong>(sizeof(bytes)));
+
+  // Check we don't crash if a nullptr is passed to field accessors.
+  ASSERT_EQ(env_->GetDirectBufferAddress(nullptr), nullptr);
+  ASSERT_EQ(env_->GetDirectBufferCapacity(nullptr), -1L);
+
+  // Check if j.n.Buffer types backed by heap memory return the invalid values described in the
+  // RETURNS clauses of JNI spec for GetDirectBufferAddress() and GetDirectBufferCapacity().
+  ScopedLocalRef<jclass> bb(env_, env_->FindClass("java/nio/ByteBuffer"));
+  jmethodID bb_allocate = env_->GetStaticMethodID(bb.get(), "allocate", "(I)Ljava/nio/ByteBuffer;");
+  jobject heap_buffer = env_->CallStaticObjectMethod(bb.get(), bb_allocate, 128);
+  ASSERT_NE(heap_buffer, nullptr);
+  ASSERT_EQ(env_->GetDirectBufferAddress(heap_buffer), nullptr);
+  ASSERT_EQ(env_->GetDirectBufferCapacity(heap_buffer), -1L);
+
+  // Check invalid values are returned if the buffer argument has an object type is not a sub-type
+  // of j.n.Buffer.
+  jobject not_buffer = env_->NewStringUTF("A String");
+  ASSERT_EQ(env_->GetDirectBufferAddress(not_buffer), nullptr);
+  ASSERT_EQ(env_->GetDirectBufferCapacity(not_buffer), -1L);
 
   {
     CheckJniAbortCatcher check_jni_abort_catcher;
diff --git a/runtime/jni_id_type.h b/runtime/jni_id_type.h
index 3f952b6..a8908fc 100644
--- a/runtime/jni_id_type.h
+++ b/runtime/jni_id_type.h
@@ -35,7 +35,7 @@
   kDefault = kPointer,
 };
 
-std::ostream& operator<<(std::ostream& os, const JniIdType& rhs);
+std::ostream& operator<<(std::ostream& os, JniIdType rhs);
 
 }  // namespace art
 #endif  // ART_RUNTIME_JNI_ID_TYPE_H_
diff --git a/runtime/linear_alloc.h b/runtime/linear_alloc.h
index 87086f2..1d01f84 100644
--- a/runtime/linear_alloc.h
+++ b/runtime/linear_alloc.h
@@ -24,7 +24,7 @@
 
 class ArenaPool;
 
-// TODO: Support freeing if we add poor man's class unloading.
+// TODO: Support freeing if we add class unloading.
 class LinearAlloc {
  public:
   explicit LinearAlloc(ArenaPool* pool);
diff --git a/runtime/lock_word.h b/runtime/lock_word.h
index 30559a0..84f45c2 100644
--- a/runtime/lock_word.h
+++ b/runtime/lock_word.h
@@ -316,7 +316,7 @@
   // The encoded value holding all the state.
   uint32_t value_;
 };
-std::ostream& operator<<(std::ostream& os, const LockWord::LockState& code);
+std::ostream& operator<<(std::ostream& os, LockWord::LockState code);
 
 }  // namespace art
 
diff --git a/runtime/managed_stack.cc b/runtime/managed_stack.cc
deleted file mode 100644
index be609c3..0000000
--- a/runtime/managed_stack.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-#include "managed_stack-inl.h"
-
-#include "android-base/stringprintf.h"
-
-#include "art_method.h"
-#include "mirror/object.h"
-#include "stack_reference.h"
-
-namespace art {
-
-size_t ManagedStack::NumJniShadowFrameReferences() const {
-  size_t count = 0;
-  for (const ManagedStack* current_fragment = this; current_fragment != nullptr;
-       current_fragment = current_fragment->GetLink()) {
-    for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_;
-         current_frame != nullptr;
-         current_frame = current_frame->GetLink()) {
-      if (current_frame->GetMethod()->IsNative()) {
-        // The JNI ShadowFrame only contains references. (For indirect reference.)
-        count += current_frame->NumberOfVRegs();
-      }
-    }
-  }
-  return count;
-}
-
-bool ManagedStack::ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const {
-  for (const ManagedStack* current_fragment = this; current_fragment != nullptr;
-       current_fragment = current_fragment->GetLink()) {
-    for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_;
-         current_frame != nullptr;
-         current_frame = current_frame->GetLink()) {
-      if (current_frame->Contains(shadow_frame_entry)) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-}  // namespace art
diff --git a/runtime/managed_stack.h b/runtime/managed_stack.h
index 3fb83ac..04a27fe 100644
--- a/runtime/managed_stack.h
+++ b/runtime/managed_stack.h
@@ -119,10 +119,6 @@
     return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_);
   }
 
-  size_t NumJniShadowFrameReferences() const REQUIRES_SHARED(Locks::mutator_lock_);
-
-  bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const;
-
  private:
   // Encodes the top quick frame (which must be at least 4-byte aligned)
   // and a flag that marks the GenericJNI trampoline.
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 2dc9f67..78e7561 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -18,7 +18,7 @@
 
 #include "android-base/stringprintf.h"
 
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_dex_operations.h"
 #include "common_throws.h"
 #include "interpreter/shadow_frame-inl.h"
diff --git a/runtime/method_handles_test.cc b/runtime/method_handles_test.cc
index 688febc..eb3f2ad 100644
--- a/runtime/method_handles_test.cc
+++ b/runtime/method_handles_test.cc
@@ -17,7 +17,7 @@
 #include "method_handles.h"
 
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_runtime_test.h"
 #include "handle_scope-inl.h"
 #include "jvalue-inl.h"
diff --git a/runtime/metrics/reporter.cc b/runtime/metrics/reporter.cc
new file mode 100644
index 0000000..a44066e
--- /dev/null
+++ b/runtime/metrics/reporter.cc
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2021 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 "reporter.h"
+
+#include <algorithm>
+
+#include <android-base/parseint.h>
+
+#include "base/flags.h"
+#include "oat_file_manager.h"
+#include "runtime.h"
+#include "runtime_options.h"
+#include "statsd.h"
+#include "thread-current-inl.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+namespace art {
+namespace metrics {
+
+std::unique_ptr<MetricsReporter> MetricsReporter::Create(
+    const ReportingConfig& config, Runtime* runtime) {
+  // We can't use std::make_unique here because the MetricsReporter constructor is private.
+  return std::unique_ptr<MetricsReporter>{new MetricsReporter{std::move(config), runtime}};
+}
+
+MetricsReporter::MetricsReporter(const ReportingConfig& config, Runtime* runtime)
+    : config_{config},
+      runtime_{runtime},
+      startup_reported_{false},
+      report_interval_index_{0} {}
+
+MetricsReporter::~MetricsReporter() { MaybeStopBackgroundThread(); }
+
+void MetricsReporter::ReloadConfig(const ReportingConfig& config) {
+  DCHECK(!thread_.has_value()) << "The config cannot be reloaded after the background "
+                                  "reporting thread is started.";
+  config_ = config;
+}
+
+bool MetricsReporter::IsMetricsReportingEnabled(const SessionData& session_data) const {
+  return session_data.session_id % config_.reporting_num_mods < config_.reporting_mods;
+}
+
+bool MetricsReporter::MaybeStartBackgroundThread(SessionData session_data) {
+  CHECK(!thread_.has_value());
+
+  session_data_ = session_data;
+  LOG_STREAM(DEBUG) << "Received session metadata: " << session_data_.session_id;
+
+  if (!IsMetricsReportingEnabled(session_data_)) {
+    return false;
+  }
+
+  thread_.emplace(&MetricsReporter::BackgroundThreadRun, this);
+  return true;
+}
+
+void MetricsReporter::MaybeStopBackgroundThread() {
+  if (thread_.has_value()) {
+    messages_.SendMessage(ShutdownRequestedMessage{});
+    thread_->join();
+    thread_.reset();
+  }
+}
+
+void MetricsReporter::NotifyStartupCompleted() {
+  if (ShouldReportAtStartup() && thread_.has_value()) {
+    messages_.SendMessage(StartupCompletedMessage{});
+  }
+}
+
+void MetricsReporter::NotifyAppInfoUpdated(AppInfo* app_info) {
+  std::string compilation_reason;
+  std::string compiler_filter;
+
+  app_info->GetPrimaryApkOptimizationStatus(
+      &compiler_filter, &compilation_reason);
+
+  SetCompilationInfo(
+      CompilationReasonFromName(compilation_reason),
+      CompilerFilterReportingFromName(compiler_filter));
+}
+
+void MetricsReporter::RequestMetricsReport(bool synchronous) {
+  if (thread_.has_value()) {
+    messages_.SendMessage(RequestMetricsReportMessage{synchronous});
+    if (synchronous) {
+      thread_to_host_messages_.ReceiveMessage();
+    }
+  }
+}
+
+void MetricsReporter::SetCompilationInfo(CompilationReason compilation_reason,
+                                         CompilerFilterReporting compiler_filter) {
+  if (thread_.has_value()) {
+    messages_.SendMessage(CompilationInfoMessage{compilation_reason, compiler_filter});
+  }
+}
+
+void MetricsReporter::BackgroundThreadRun() {
+  LOG_STREAM(DEBUG) << "Metrics reporting thread started";
+
+  // AttachCurrentThread is needed so we can safely use the ART concurrency primitives within the
+  // messages_ MessageQueue.
+  const bool attached = runtime_->AttachCurrentThread(kBackgroundThreadName,
+                                                      /*as_daemon=*/true,
+                                                      runtime_->GetSystemThreadGroup(),
+                                                      /*create_peer=*/true);
+  bool running = true;
+
+  // Configure the backends
+  if (config_.dump_to_logcat) {
+    backends_.emplace_back(new LogBackend(LogSeverity::INFO));
+  }
+  if (config_.dump_to_file.has_value()) {
+    backends_.emplace_back(new FileBackend(config_.dump_to_file.value()));
+  }
+  if (config_.dump_to_statsd) {
+    auto backend = CreateStatsdBackend();
+    if (backend != nullptr) {
+      backends_.emplace_back(std::move(backend));
+    }
+  }
+
+  MaybeResetTimeout();
+
+  while (running) {
+    messages_.SwitchReceive(
+        [&]([[maybe_unused]] ShutdownRequestedMessage message) {
+          LOG_STREAM(DEBUG) << "Shutdown request received " << session_data_.session_id;
+          running = false;
+
+          ReportMetrics();
+        },
+        [&](RequestMetricsReportMessage message) {
+          LOG_STREAM(DEBUG) << "Explicit report request received " << session_data_.session_id;
+          ReportMetrics();
+          if (message.synchronous) {
+            thread_to_host_messages_.SendMessage(ReportCompletedMessage{});
+          }
+        },
+        [&]([[maybe_unused]] TimeoutExpiredMessage message) {
+          LOG_STREAM(DEBUG) << "Timer expired, reporting metrics " << session_data_.session_id;
+
+          ReportMetrics();
+          MaybeResetTimeout();
+        },
+        [&]([[maybe_unused]] StartupCompletedMessage message) {
+          LOG_STREAM(DEBUG) << "App startup completed, reporting metrics "
+              << session_data_.session_id;
+          ReportMetrics();
+          startup_reported_ = true;
+          MaybeResetTimeout();
+        },
+        [&](CompilationInfoMessage message) {
+          LOG_STREAM(DEBUG) << "Compilation info received " << session_data_.session_id;
+          session_data_.compilation_reason = message.compilation_reason;
+          session_data_.compiler_filter = message.compiler_filter;
+
+          UpdateSessionInBackends();
+        });
+  }
+
+  if (attached) {
+    runtime_->DetachCurrentThread();
+  }
+  LOG_STREAM(DEBUG) << "Metrics reporting thread terminating " << session_data_.session_id;
+}
+
+void MetricsReporter::MaybeResetTimeout() {
+  if (ShouldContinueReporting()) {
+    messages_.SetTimeout(SecondsToMs(GetNextPeriodSeconds()));
+  }
+}
+
+const ArtMetrics* MetricsReporter::GetMetrics() {
+  return runtime_->GetMetrics();
+}
+
+void MetricsReporter::ReportMetrics() {
+  const ArtMetrics* metrics = GetMetrics();
+
+  if (!session_started_) {
+    for (auto& backend : backends_) {
+      backend->BeginOrUpdateSession(session_data_);
+    }
+    session_started_ = true;
+  }
+
+  for (auto& backend : backends_) {
+    metrics->ReportAllMetrics(backend.get());
+  }
+}
+
+void MetricsReporter::UpdateSessionInBackends() {
+  if (session_started_) {
+    for (auto& backend : backends_) {
+      backend->BeginOrUpdateSession(session_data_);
+    }
+  }
+}
+
+bool MetricsReporter::ShouldReportAtStartup() const {
+  return IsMetricsReportingEnabled(session_data_) &&
+      config_.period_spec.has_value() &&
+      config_.period_spec->report_startup_first;
+}
+
+bool MetricsReporter::ShouldContinueReporting() const {
+  bool result =
+      // Only if the reporting is enabled
+      IsMetricsReportingEnabled(session_data_) &&
+      // and if we have period spec
+      config_.period_spec.has_value() &&
+      // and the periods are non empty
+      !config_.period_spec->periods_seconds.empty() &&
+      // and we already reported startup or not required to report startup
+      (startup_reported_ || !config_.period_spec->report_startup_first) &&
+      // and we still have unreported intervals or we are asked to report continuously.
+      (config_.period_spec->continuous_reporting ||
+              (report_interval_index_ < config_.period_spec->periods_seconds.size()));
+  return result;
+}
+
+uint32_t MetricsReporter::GetNextPeriodSeconds() {
+  DCHECK(ShouldContinueReporting());
+
+  // The index is either the current report_interval_index or the last index
+  // if we are in continuous mode and reached the end.
+  uint32_t index = std::min(
+      report_interval_index_,
+      static_cast<uint32_t>(config_.period_spec->periods_seconds.size() - 1));
+
+  uint32_t result = config_.period_spec->periods_seconds[index];
+
+  // Advance the index if we didn't get to the end.
+  if (report_interval_index_ < config_.period_spec->periods_seconds.size()) {
+    report_interval_index_++;
+  }
+  return result;
+}
+
+ReportingConfig ReportingConfig::FromFlags(bool is_system_server) {
+  std::optional<std::string> spec_str = is_system_server
+      ? gFlags.MetricsReportingSpecSystemServer.GetValueOptional()
+      : gFlags.MetricsReportingSpec.GetValueOptional();
+
+  std::optional<ReportingPeriodSpec> period_spec = std::nullopt;
+
+  if (spec_str.has_value()) {
+    std::string error;
+    period_spec = ReportingPeriodSpec::Parse(spec_str.value(), &error);
+    if (!period_spec.has_value()) {
+      LOG(ERROR) << "Failed to create metrics reporting spec from: " << spec_str.value()
+          << " with error: " << error;
+    }
+  }
+
+  uint32_t reporting_num_mods = is_system_server
+      ? gFlags.MetricsReportingNumModsServer()
+      : gFlags.MetricsReportingNumMods();
+  uint32_t reporting_mods = is_system_server
+      ? gFlags.MetricsReportingModsServer()
+      : gFlags.MetricsReportingMods();
+
+  if (reporting_mods > reporting_num_mods || reporting_num_mods == 0) {
+    LOG(ERROR) << "Invalid metrics reporting mods: " << reporting_mods
+        << " num modes=" << reporting_num_mods
+        << ". The reporting is disabled";
+    reporting_mods = 0;
+    reporting_num_mods = 100;
+  }
+
+  return {
+      .dump_to_logcat = gFlags.MetricsWriteToLogcat(),
+      .dump_to_file = gFlags.MetricsWriteToFile.GetValueOptional(),
+      .dump_to_statsd = gFlags.MetricsWriteToStatsd(),
+      .period_spec = period_spec,
+      .reporting_num_mods = reporting_num_mods,
+      .reporting_mods = reporting_mods,
+  };
+}
+
+std::optional<ReportingPeriodSpec> ReportingPeriodSpec::Parse(
+    const std::string& spec_str, std::string* error_msg) {
+  *error_msg = "";
+  if (spec_str.empty()) {
+    *error_msg = "Invalid empty spec.";
+    return std::nullopt;
+  }
+
+  // Split the string. Each element is separated by comma.
+  std::vector<std::string> elems;
+  Split(spec_str, ',', &elems);
+
+  // Check the startup marker (front) and the continuous one (back).
+  std::optional<ReportingPeriodSpec> spec = std::make_optional(ReportingPeriodSpec());
+  spec->spec = spec_str;
+  spec->report_startup_first = elems.front() == "S";
+  spec->continuous_reporting = elems.back() == "*";
+
+  // Compute the indices for the period values.
+  size_t start_interval_idx = spec->report_startup_first ? 1 : 0;
+  size_t end_interval_idx = spec->continuous_reporting ? (elems.size() - 1) : elems.size();
+
+  // '*' needs a numeric interval before in order to be valid.
+  if (spec->continuous_reporting &&
+      end_interval_idx == start_interval_idx) {
+    *error_msg = "Invalid period value in spec: " + spec_str;
+    return std::nullopt;
+  }
+
+  // Parse the periods.
+  for (size_t i = start_interval_idx; i < end_interval_idx; i++) {
+    uint32_t period;
+    if (!android::base::ParseUint(elems[i], &period)) {
+        *error_msg = "Invalid period value in spec: " + spec_str;
+        return std::nullopt;
+    }
+    spec->periods_seconds.push_back(period);
+  }
+
+  return spec;
+}
+
+}  // namespace metrics
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
diff --git a/runtime/metrics/reporter.h b/runtime/metrics/reporter.h
new file mode 100644
index 0000000..ed7022d
--- /dev/null
+++ b/runtime/metrics/reporter.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2021 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_METRICS_REPORTER_H_
+#define ART_RUNTIME_METRICS_REPORTER_H_
+
+#include "app_info.h"
+#include "base/message_queue.h"
+#include "base/metrics/metrics.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+namespace art {
+namespace metrics {
+
+/**
+ * Encapsulates the specification of the metric reporting periods.
+ *
+ * The period spec follows the following regex: "(S,)?(\d+,)*\*?"
+ * with the following semantics:
+ *   "S"         - will only report at startup.
+ *
+ *   "S,1,1"     - will report startup, than 1 second later, then another
+ *                 second later.
+ *
+ *   "S,1,2,4  " - will report at Startup time, then 1 seconds later,
+ *                 then 2, then finally 4 seconds later. After that, the
+ *                 reporting will stop.
+ *
+ *   "S,1,2,4,*" - same as above, but after the final 4s period, the
+ *                 reporting will continue every other 4s.
+ *                 '*' is an indication we should report continuously
+ *                 every N seconds, where N is the last period.
+ *
+ *   "2,*"       - will report every 2 seconds
+ *
+ * Note that "", "*", or "S,*" are not valid specs, and 'S' can only occur
+ * in the beginning.
+ */
+struct ReportingPeriodSpec {
+  static std::optional<ReportingPeriodSpec> Parse(
+      const std::string& spec_str, std::string* error_msg);
+
+  // The original spec.
+  std::string spec;
+  // The intervals when we should report.
+  std::vector<uint32_t> periods_seconds;
+  // Whether or not the reporting is continuous (contains a '*').
+  bool continuous_reporting{false};
+  // Whether or not the reporting should start after startup event (starts with an 'S').
+  bool report_startup_first{false};
+};
+
+// Defines the set of options for how metrics reporting happens.
+struct ReportingConfig {
+  static ReportingConfig FromFlags(bool is_system_server = false);
+
+  // Causes metrics to be written to the log, which makes them show up in logcat.
+  bool dump_to_logcat{false};
+
+  // Causes metrics to be written to statsd, which causes them to be uploaded to Westworld.
+  bool dump_to_statsd{false};
+
+  // If set, provides a file name to enable metrics logging to a file.
+  std::optional<std::string> dump_to_file;
+
+  // The reporting period configuration.
+  std::optional<ReportingPeriodSpec> period_spec;
+
+  // The mods that should report metrics. Together with reporting_num_mods, they
+  // dictate what percentage of the runtime execution will report metrics.
+  // If the `session_id (a random number) % reporting_num_mods < reporting_mods`
+  // then the runtime session will report metrics.
+  uint32_t reporting_mods{0};
+  uint32_t reporting_num_mods{100};
+};
+
+// MetricsReporter handles periodically reporting ART metrics.
+class MetricsReporter {
+ public:
+  // Creates a MetricsReporter instance that matches the options selected in ReportingConfig.
+  static std::unique_ptr<MetricsReporter> Create(const ReportingConfig& config, Runtime* runtime);
+
+  virtual ~MetricsReporter();
+
+  // Creates and runs the background reporting thread.
+  //
+  // Does nothing if the reporting config does not have any outputs enabled.
+  //
+  // Returns true if the thread was started, false otherwise.
+  bool MaybeStartBackgroundThread(SessionData session_data);
+
+  // Sends a request to the background thread to shutdown.
+  void MaybeStopBackgroundThread();
+
+  // Causes metrics to be reported so we can see a snapshot of the metrics after app startup
+  // completes.
+  void NotifyStartupCompleted();
+
+  // Notifies the reporter that the app info was updated. This is used to detect / infer
+  // the compiler filter / reason of primary apks.
+  void NotifyAppInfoUpdated(AppInfo* app_info);
+
+  // Requests a metrics report
+  //
+  // If synchronous is set to true, this function will block until the report has completed.
+  void RequestMetricsReport(bool synchronous = true);
+
+  // Reloads the metrics config from the given value.
+  // Can only be called before starting the background thread.
+  void ReloadConfig(const ReportingConfig& config);
+
+  void SetCompilationInfo(CompilationReason compilation_reason,
+                          CompilerFilterReporting compiler_filter);
+
+  static constexpr const char* kBackgroundThreadName = "Metrics Background Reporting Thread";
+
+ protected:
+  // Returns the metrics to be reported.
+  // This exists only for testing purposes so that we can verify reporting with minimum
+  // runtime interference.
+  virtual const ArtMetrics* GetMetrics();
+
+  MetricsReporter(const ReportingConfig& config, Runtime* runtime);
+
+ private:
+  // Whether or not we should reporting metrics according to the sampling rate.
+  bool IsMetricsReportingEnabled(const SessionData& session_data) const;
+
+  // The background reporting thread main loop.
+  void BackgroundThreadRun();
+
+  // Calls messages_.SetTimeout if needed.
+  void MaybeResetTimeout();
+
+  // Outputs the current state of the metrics to the destination set by config_.
+  void ReportMetrics();
+
+  // Updates the session data in all the backends.
+  void UpdateSessionInBackends();
+
+  // Whether or not we should wait for startup before reporting for the first time.
+  bool ShouldReportAtStartup() const;
+
+  // Whether or not we should continue reporting (either because we still
+  // have periods to report, or because we are in continuous mode).
+  bool ShouldContinueReporting() const;
+
+  // Returns the next reporting period.
+  // Must be called only if ShouldContinueReporting() is true.
+  uint32_t GetNextPeriodSeconds();
+
+  ReportingConfig config_;
+  Runtime* runtime_;
+  std::vector<std::unique_ptr<MetricsBackend>> backends_;
+  std::optional<std::thread> thread_;
+  // Whether or not we reported the startup event.
+  bool startup_reported_;
+  // The index into period_spec.periods_seconds which tells the next delay in
+  // seconds for the next reporting.
+  uint32_t report_interval_index_;
+
+  // A message indicating that the reporting thread should shut down.
+  struct ShutdownRequestedMessage {};
+
+  // A message indicating that app startup has completed.
+  struct StartupCompletedMessage {};
+
+  // A message requesting an explicit metrics report.
+  //
+  // The synchronous field specifies whether the reporting thread will send a message back when
+  // reporting is complete.
+  struct RequestMetricsReportMessage {
+    bool synchronous;
+  };
+
+  struct CompilationInfoMessage {
+    CompilationReason compilation_reason;
+    CompilerFilterReporting compiler_filter;
+  };
+
+  MessageQueue<ShutdownRequestedMessage,
+               StartupCompletedMessage,
+               RequestMetricsReportMessage,
+               CompilationInfoMessage>
+      messages_;
+
+  // A message indicating a requested report has been finished.
+  struct ReportCompletedMessage {};
+
+  MessageQueue<ReportCompletedMessage> thread_to_host_messages_;
+
+  SessionData session_data_{};
+  bool session_started_{false};
+
+  friend class MetricsReporterTest;
+};
+
+}  // namespace metrics
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
+
+#endif  // ART_RUNTIME_METRICS_REPORTER_H_
diff --git a/runtime/metrics/reporter_test.cc b/runtime/metrics/reporter_test.cc
new file mode 100644
index 0000000..3807c77
--- /dev/null
+++ b/runtime/metrics/reporter_test.cc
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2021 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 "reporter.h"
+
+#include "gtest/gtest.h"
+
+#include "common_runtime_test.h"
+#include "base/metrics/metrics.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+namespace art {
+namespace metrics {
+
+// Helper class to verify the metrics reporter.
+// The functionality is identical to the MetricsReporter with the exception of
+// the metrics source. Instead of taking its metrics from the current Runtime,
+// this class will keep its own copy so that it does not get interference from
+// other runtime setup logic.
+class MockMetricsReporter : public MetricsReporter {
+ protected:
+  MockMetricsReporter(const ReportingConfig& config, Runtime* runtime) :
+      MetricsReporter(config, runtime),
+      art_metrics_(new ArtMetrics()) {}
+
+  const ArtMetrics* GetMetrics() override {
+    return art_metrics_.get();
+  }
+
+  std::unique_ptr<ArtMetrics> art_metrics_;
+
+  friend class MetricsReporterTest;
+};
+
+// A test backend which keeps track of all metrics reporting.
+class TestBackend : public MetricsBackend {
+ public:
+  struct Report {
+    uint64_t timestamp_millis;
+    SafeMap<DatumId, uint64_t> data;
+  };
+
+  void BeginOrUpdateSession(const SessionData& session_data) override {
+    session_data_ = session_data;
+  }
+
+  void BeginReport(uint64_t timestamp_millis) override {
+    current_report_.reset(new Report());
+    current_report_->timestamp_millis = timestamp_millis;
+  }
+
+  void ReportCounter(DatumId counter_type, uint64_t value) override {
+    current_report_->data.Put(counter_type, value);
+  }
+
+  void ReportHistogram(DatumId histogram_type ATTRIBUTE_UNUSED,
+                       int64_t low_value ATTRIBUTE_UNUSED,
+                       int64_t high_value ATTRIBUTE_UNUSED,
+                       const std::vector<uint32_t>& buckets ATTRIBUTE_UNUSED) override {
+    // TODO: nothing yet. We should implement and test histograms as well.
+  }
+
+  void EndReport() override {
+    reports_.push_back(*current_report_);
+    current_report_ = nullptr;
+  }
+
+  const std::vector<Report>& GetReports() {
+    return reports_;
+  }
+
+  const SessionData& GetSessionData() {
+    return session_data_;
+  }
+
+ private:
+  SessionData session_data_;
+  std::vector<Report> reports_;
+  std::unique_ptr<Report> current_report_;
+};
+
+// The actual metrics test class
+class MetricsReporterTest : public CommonRuntimeTest {
+ protected:
+  void SetUp() override {
+    // Do the normal setup.
+    CommonRuntimeTest::SetUp();
+
+    // We need to start the runtime in order to run threads.
+    Thread::Current()->TransitionFromSuspendedToRunnable();
+    bool started = runtime_->Start();
+    CHECK(started);
+  }
+
+  // Configures the metric reporting.
+  void SetupReporter(const char* period_spec,
+                     uint32_t session_id = 1,
+                     uint32_t reporting_mods = 100) {
+    ReportingConfig config;
+    if (period_spec != nullptr) {
+      std::string error;
+      config.reporting_mods = reporting_mods;
+      config.period_spec = ReportingPeriodSpec::Parse(period_spec, &error);
+      ASSERT_TRUE(config.period_spec.has_value());
+    }
+
+    reporter_.reset(new MockMetricsReporter(std::move(config), Runtime::Current()));
+    backend_ = new TestBackend();
+    reporter_->backends_.emplace_back(backend_);
+
+    session_data_ = metrics::SessionData::CreateDefault();
+    session_data_.session_id = session_id;
+  }
+
+  void TearDown() override {
+    reporter_ = nullptr;
+    backend_ = nullptr;
+  }
+
+  bool ShouldReportAtStartup() {
+    return reporter_->ShouldReportAtStartup();
+  }
+
+  bool ShouldContinueReporting() {
+    return reporter_->ShouldContinueReporting();
+  }
+
+  uint32_t GetNextPeriodSeconds() {
+    return reporter_->GetNextPeriodSeconds();
+  }
+
+  void ReportMetrics() {
+    reporter_->ReportMetrics();
+  }
+
+  void NotifyStartupCompleted() {
+    reporter_->NotifyStartupCompleted();
+  }
+
+  // Starts the reporting thread and adds some metrics if necessary.
+  bool MaybeStartBackgroundThread(bool add_metrics) {
+    // TODO: set session_data.compilation_reason and session_data.compiler_filter
+    bool result = reporter_->MaybeStartBackgroundThread(session_data_);
+    if (add_metrics) {
+      reporter_->art_metrics_->JitMethodCompileCount()->Add(1);
+      reporter_->art_metrics_->ClassVerificationCount()->Add(2);
+    }
+    return result;
+  }
+
+  // Right now we either:
+  //   1) don't add metrics (with_metrics = false)
+  //   2) or always add the same metrics (see MaybeStartBackgroundThread)
+  // So we can write a global verify method.
+  void VerifyReports(
+        uint32_t size,
+        bool with_metrics,
+        CompilerFilterReporting filter = CompilerFilterReporting::kUnknown,
+        CompilationReason reason = CompilationReason::kUnknown) {
+    // TODO: we should iterate through all the other metrics to make sure they were not
+    // reported. However, we don't have an easy to use iteration mechanism over metrics yet.
+    // We should ads one
+    ASSERT_EQ(backend_->GetReports().size(), size);
+    for (auto report : backend_->GetReports()) {
+      ASSERT_EQ(report.data.Get(DatumId::kClassVerificationCount), with_metrics ? 2u : 0u);
+      ASSERT_EQ(report.data.Get(DatumId::kJitMethodCompileCount), with_metrics ? 1u : 0u);
+    }
+
+    ASSERT_EQ(backend_->GetSessionData().compiler_filter, filter);
+    ASSERT_EQ(backend_->GetSessionData().compilation_reason, reason);
+  }
+
+  // Sleeps until the backend received the give number of reports.
+  void WaitForReport(uint32_t report_count, uint32_t sleep_period_ms) {
+    while (true) {
+      if (backend_->GetReports().size() == report_count) {
+        return;
+      }
+      usleep(sleep_period_ms * 1000);
+    }
+  }
+
+  void NotifyAppInfoUpdated(AppInfo* app_info) {
+    reporter_->NotifyAppInfoUpdated(app_info);
+  }
+
+ private:
+  std::unique_ptr<MockMetricsReporter> reporter_;
+  TestBackend* backend_;
+  metrics::SessionData session_data_;
+};
+
+// Verifies startup reporting.
+TEST_F(MetricsReporterTest, StartupOnly) {
+  SetupReporter("S");
+
+  // Verify startup conditions
+  ASSERT_TRUE(ShouldReportAtStartup());
+  ASSERT_FALSE(ShouldContinueReporting());
+
+  // Start the thread and notify the startup. This will advance the state.
+  MaybeStartBackgroundThread(/*add_metrics=*/ true);
+
+  NotifyStartupCompleted();
+  WaitForReport(/*report_count=*/ 1, /*sleep_period_ms=*/ 50);
+  VerifyReports(/*size=*/ 1, /*with_metrics*/ true);
+
+  // We still should not report at period.
+  ASSERT_FALSE(ShouldContinueReporting());
+}
+
+// LARGE TEST: This test takes 1s to run.
+// Verifies startup reporting, followed by a fixed, one time only reporting.
+TEST_F(MetricsReporterTest, StartupAndPeriod) {
+  SetupReporter("S,1");
+
+  // Verify startup conditions
+  ASSERT_TRUE(ShouldReportAtStartup());
+  ASSERT_FALSE(ShouldContinueReporting());
+
+  // Start the thread and notify the startup. This will advance the state.
+  MaybeStartBackgroundThread(/*add_metrics=*/ true);
+  NotifyStartupCompleted();
+
+  // We're waiting for 2 reports: the startup one, and the 1s one.
+  WaitForReport(/*report_count=*/ 2, /*sleep_period_ms=*/ 500);
+  VerifyReports(/*size=*/ 2, /*with_metrics*/ true);
+
+  // We should not longer report at period.
+  ASSERT_FALSE(ShouldContinueReporting());
+}
+
+// LARGE TEST: This takes take 2s to run.
+// Verifies startup reporting, followed by continuous reporting.
+TEST_F(MetricsReporterTest, StartupAndPeriodContinuous) {
+  SetupReporter("S,1,*");
+
+  // Verify startup conditions
+  ASSERT_TRUE(ShouldReportAtStartup());
+  ASSERT_FALSE(ShouldContinueReporting());
+
+  // Start the thread and notify the startup. This will advance the state.
+  MaybeStartBackgroundThread(/*add_metrics=*/ true);
+  NotifyStartupCompleted();
+
+  // We're waiting for 3 reports: the startup one, and the 1s one.
+  WaitForReport(/*report_count=*/ 3, /*sleep_period_ms=*/ 500);
+  VerifyReports(/*size=*/ 3, /*with_metrics*/ true);
+
+  // We should keep reporting at period.
+  ASSERT_TRUE(ShouldContinueReporting());
+}
+
+// LARGE TEST: This test takes 1s to run.
+// Verifies a fixed, one time only reporting.
+TEST_F(MetricsReporterTest, OneTime) {
+  SetupReporter("1");
+
+  // Verify startup conditions
+  ASSERT_FALSE(ShouldReportAtStartup());
+  ASSERT_TRUE(ShouldContinueReporting());
+
+  // Start the thread and notify the startup. This will advance the state.
+  MaybeStartBackgroundThread(/*add_metrics=*/ true);
+
+  // We're waiting for 1 report
+  WaitForReport(/*report_count=*/ 1, /*sleep_period_ms=*/ 500);
+  VerifyReports(/*size=*/ 1, /*with_metrics*/ true);
+
+  // We should not longer report at period.
+  ASSERT_FALSE(ShouldContinueReporting());
+}
+
+// LARGE TEST: This takes take 5s to run.
+// Verifies a sequence of reporting, at different interval of times.
+TEST_F(MetricsReporterTest, PeriodContinuous) {
+  SetupReporter("1,2,*");
+
+  // Verify startup conditions
+  ASSERT_FALSE(ShouldReportAtStartup());
+  ASSERT_TRUE(ShouldContinueReporting());
+
+  // Start the thread and notify the startup. This will advance the state.
+  MaybeStartBackgroundThread(/*add_metrics=*/ true);
+  NotifyStartupCompleted();
+
+  // We're waiting for 2 reports: the startup one, and the 1s one.
+  WaitForReport(/*report_count=*/ 3, /*sleep_period_ms=*/ 500);
+  VerifyReports(/*size=*/ 3, /*with_metrics*/ true);
+
+  // We should keep reporting at period.
+  ASSERT_TRUE(ShouldContinueReporting());
+}
+
+// LARGE TEST: This test takes 1s to run.
+// Verifies reporting when no metrics where recorded.
+TEST_F(MetricsReporterTest, NoMetrics) {
+  SetupReporter("1");
+
+  // Verify startup conditions
+  ASSERT_FALSE(ShouldReportAtStartup());
+  ASSERT_TRUE(ShouldContinueReporting());
+
+  // Start the thread and notify the startup. This will advance the state.
+  MaybeStartBackgroundThread(/*add_metrics=*/ false);
+
+  // We're waiting for 1 report
+  WaitForReport(/*report_count=*/ 1, /*sleep_period_ms=*/ 500);
+  VerifyReports(/*size=*/ 1, /*with_metrics*/ false);
+
+  // We should not longer report at period.
+  ASSERT_FALSE(ShouldContinueReporting());
+}
+
+// Verify we don't start reporting if the sample rate is set to 0.
+TEST_F(MetricsReporterTest, SampleRateDisable) {
+  SetupReporter("1", /*session_id=*/ 1, /*reporting_mods=*/ 0);
+
+  // The background thread should not start.
+  ASSERT_FALSE(MaybeStartBackgroundThread(/*add_metrics=*/ false));
+
+  ASSERT_FALSE(ShouldReportAtStartup());
+  ASSERT_FALSE(ShouldContinueReporting());
+}
+
+// Verify we don't start reporting if the sample rate is low and the session does
+// not meet conditions.
+TEST_F(MetricsReporterTest, SampleRateDisable24) {
+  SetupReporter("1", /*session_id=*/ 125, /*reporting_mods=*/ 24);
+
+  // The background thread should not start.
+  ASSERT_FALSE(MaybeStartBackgroundThread(/*add_metrics=*/ false));
+
+  ASSERT_FALSE(ShouldReportAtStartup());
+  ASSERT_FALSE(ShouldContinueReporting());
+}
+
+// Verify we start reporting if the sample rate and the session meet
+// reporting conditions
+TEST_F(MetricsReporterTest, SampleRateEnable50) {
+  SetupReporter("1", /*session_id=*/ 125, /*reporting_mods=*/ 50);
+
+  // The background thread should not start.
+  ASSERT_TRUE(MaybeStartBackgroundThread(/*add_metrics=*/ false));
+
+  ASSERT_FALSE(ShouldReportAtStartup());
+  ASSERT_TRUE(ShouldContinueReporting());
+}
+
+// Verify we start reporting if the sample rate and the session meet
+// reporting conditions
+TEST_F(MetricsReporterTest, SampleRateEnableAll) {
+  SetupReporter("1", /*session_id=*/ 1099, /*reporting_mods=*/ 100);
+
+  // The background thread should start.
+  ASSERT_TRUE(MaybeStartBackgroundThread(/*add_metrics=*/ false));
+
+  ASSERT_FALSE(ShouldReportAtStartup());
+  ASSERT_TRUE(ShouldContinueReporting());
+}
+
+TEST_F(MetricsReporterTest, CompilerFilter) {
+  SetupReporter("1", /*session_id=*/ 1099, /*reporting_mods=*/ 100);
+  ASSERT_TRUE(MaybeStartBackgroundThread(/*add_metrics=*/ true));
+
+  AppInfo app_info;
+  app_info.RegisterOdexStatus(
+      "code_location",
+      "verify",
+      "install",
+      "odex_status");
+  app_info.RegisterAppInfo(
+      "package_name",
+      std::vector<std::string>({"code_location"}),
+      "",
+      "",
+      AppInfo::CodeType::kPrimaryApk);
+  NotifyAppInfoUpdated(&app_info);
+
+  WaitForReport(/*report_count=*/ 1, /*sleep_period_ms=*/ 500);
+  VerifyReports(
+      /*size=*/ 1,
+      /*with_metrics*/ true,
+      CompilerFilterReporting::kVerify,
+      CompilationReason::kInstall);
+}
+
+// Test class for period spec parsing
+class ReportingPeriodSpecTest : public testing::Test {
+ public:
+  void VerifyFalse(const std::string& spec_str) {
+    Verify(spec_str, false, false, false, {});
+  }
+
+  void VerifyTrue(
+      const std::string& spec_str,
+      bool startup_first,
+      bool continuous,
+      std::vector<uint32_t> periods) {
+    Verify(spec_str, true, startup_first, continuous, periods);
+  }
+
+  void Verify(
+      const std::string& spec_str,
+      bool valid,
+      bool startup_first,
+      bool continuous,
+      std::vector<uint32_t> periods) {
+    std::string error_msg;
+    std::optional<ReportingPeriodSpec> spec = ReportingPeriodSpec::Parse(spec_str, &error_msg);
+
+    ASSERT_EQ(valid, spec.has_value()) << spec_str;
+    if (valid) {
+        ASSERT_EQ(spec->spec, spec_str) << spec_str;
+        ASSERT_EQ(spec->report_startup_first, startup_first) << spec_str;
+        ASSERT_EQ(spec->continuous_reporting, continuous) << spec_str;
+        ASSERT_EQ(spec->periods_seconds, periods) << spec_str;
+    }
+  }
+};
+
+TEST_F(ReportingPeriodSpecTest, ParseTestsInvalid) {
+  VerifyFalse("");
+  VerifyFalse("*");
+  VerifyFalse("S,*");
+  VerifyFalse("foo");
+  VerifyFalse("-1");
+  VerifyFalse("1,S");
+  VerifyFalse("*,1");
+  VerifyFalse("1,2,3,-1,3");
+  VerifyFalse("1,*,2");
+  VerifyFalse("1,S,2");
+}
+
+TEST_F(ReportingPeriodSpecTest, ParseTestsValid) {
+  VerifyTrue("S", true, false, {});
+  VerifyTrue("S,1", true, false, {1});
+  VerifyTrue("S,1,2,3,4", true, false, {1, 2, 3, 4});
+  VerifyTrue("S,1,*", true, true, {1});
+  VerifyTrue("S,1,2,3,4,*", true, true, {1, 2, 3, 4});
+
+  VerifyTrue("1", false, false, {1});
+  VerifyTrue("1,2,3,4", false, false, {1, 2, 3, 4});
+  VerifyTrue("1,*", false, true, {1});
+  VerifyTrue("1,2,3,4,*", false, true, {1, 2, 3, 4});
+}
+
+}  // namespace metrics
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
diff --git a/runtime/metrics/statsd.cc b/runtime/metrics/statsd.cc
new file mode 100644
index 0000000..bcf1a14
--- /dev/null
+++ b/runtime/metrics/statsd.cc
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2021 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 "statsd.h"
+
+#include "arch/instruction_set.h"
+#include "base/compiler_filter.h"
+#include "base/metrics/metrics.h"
+#include "statslog_art.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+namespace art {
+namespace metrics {
+
+namespace {
+
+// EncodeDatumId returns a std::optional that provides a enum value from atoms.proto if the datum is
+// one that we support logging to statsd. The list of datums that ART collects is a superset of what
+// we report to statsd. Therefore, we only have mappings for the DatumIds that statsd recognizes.
+// Also it must be noted that histograms are not handled yet by statsd yet.
+//
+// Other code can use whether the result of this function has a value to decide whether to report
+// the atom to statsd.
+//
+// To report additional measurements to statsd, first add an entry in atoms.proto and then add an
+// entry to this function as well.
+constexpr std::optional<int32_t> EncodeDatumId(DatumId datum_id) {
+  switch (datum_id) {
+    case DatumId::kClassVerificationTotalTime:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_CLASS_VERIFICATION_TIME_COUNTER_MICROS);
+    case DatumId::kJitMethodCompileTotalTime:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_JIT_METHOD_COMPILE_TIME_MICROS);
+    case DatumId::kClassLoadingTotalTime:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_CLASS_LOADING_TIME_COUNTER_MICROS);
+    case DatumId::kClassVerificationCount:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_CLASS_VERIFICATION_COUNT);
+    case DatumId::kWorldStopTimeDuringGCAvg:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_WORLD_STOP_TIME_AVG_MICROS);
+    case DatumId::kYoungGcCount:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_COLLECTION_COUNT);
+    case DatumId::kFullGcCount:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_COLLECTION_COUNT);
+    case DatumId::kTotalBytesAllocated:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_TOTAL_BYTES_ALLOCATED);
+    case DatumId::kYoungGcCollectionTime:
+      return std::make_optional(
+          statsd::
+              ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_COLLECTION_TIME_HISTO_MILLIS);
+    case DatumId::kFullGcCollectionTime:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_COLLECTION_TIME_HISTO_MILLIS);
+    case DatumId::kYoungGcThroughput:
+      return std::make_optional(
+          statsd::
+              ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_COLLECTION_THROUGHPUT_HISTO_MB_PER_SEC);
+    case DatumId::kFullGcThroughput:
+      return std::make_optional(
+          statsd::
+              ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_COLLECTION_THROUGHPUT_HISTO_MB_PER_SEC);
+    case DatumId::kJitMethodCompileCount:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_JIT_METHOD_COMPILE_COUNT);
+    case DatumId::kYoungGcTracingThroughput:
+      return std::make_optional(
+          statsd::
+              ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_TRACING_THROUGHPUT_HISTO_MB_PER_SEC);
+    case DatumId::kFullGcTracingThroughput:
+      return std::make_optional(
+          statsd::
+              ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_TRACING_THROUGHPUT_HISTO_MB_PER_SEC);
+    case DatumId::kTotalGcCollectionTime:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_TOTAL_COLLECTION_TIME_MS);
+    case DatumId::kYoungGcThroughputAvg:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_COLLECTION_THROUGHPUT_AVG_MB_PER_SEC);
+    case DatumId::kFullGcThroughputAvg:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_COLLECTION_THROUGHPUT_AVG_MB_PER_SEC);
+    case DatumId::kYoungGcTracingThroughputAvg:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_TRACING_THROUGHPUT_AVG_MB_PER_SEC);
+    case DatumId::kFullGcTracingThroughputAvg:
+      return std::make_optional(
+          statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_TRACING_THROUGHPUT_AVG_MB_PER_SEC);
+  }
+}
+
+constexpr int32_t EncodeCompileFilter(CompilerFilterReporting filter) {
+  switch (filter) {
+    case CompilerFilterReporting::kAssumeVerified:
+      return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ASSUMED_VERIFIED;
+    case CompilerFilterReporting::kExtract:
+      return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EXTRACT;
+    case CompilerFilterReporting::kVerify:
+      return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_VERIFY;
+    case CompilerFilterReporting::kSpaceProfile:
+      return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE_PROFILE;
+    case CompilerFilterReporting::kSpace:
+      return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE;
+    case CompilerFilterReporting::kSpeedProfile:
+      return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED_PROFILE;
+    case CompilerFilterReporting::kSpeed:
+      return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED;
+    case CompilerFilterReporting::kEverythingProfile:
+      return statsd::
+          ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING_PROFILE;
+    case CompilerFilterReporting::kEverything:
+      return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING;
+    case CompilerFilterReporting::kError:
+      return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ERROR;
+    case CompilerFilterReporting::kUnknown:
+       return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_UNKNOWN;
+    case CompilerFilterReporting::kRunFromApk:
+       return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK;
+    case CompilerFilterReporting::kRunFromApkFallback:
+       return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK;
+  }
+}
+
+constexpr int32_t EncodeCompilationReason(CompilationReason reason) {
+  switch (reason) {
+    case CompilationReason::kUnknown:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN;
+    case CompilationReason::kABOTA:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_AB_OTA;
+    case CompilationReason::kBgDexopt:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BG_DEXOPT;
+    case CompilationReason::kError:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_ERROR;
+    case CompilationReason::kFirstBoot:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_FIRST_BOOT;
+    case CompilationReason::kInactive:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INACTIVE;
+    case CompilationReason::kInstall:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL;
+    case CompilationReason::kInstallWithDexMetadata:
+      return statsd::
+          ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA;
+    case CompilationReason::kShared:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_SHARED;
+    case CompilationReason::kPostBoot:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_POST_BOOT;
+    case CompilationReason::kInstallBulk:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK;
+    case CompilationReason::kInstallBulkSecondary:
+      return statsd::
+          ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY;
+    case CompilationReason::kInstallBulkDowngraded:
+      return statsd::
+          ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED;
+    case CompilationReason::kInstallBulkSecondaryDowngraded:
+      return statsd::
+          ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
+    case CompilationReason::kBootAfterOTA:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BOOT_AFTER_OTA;
+    case CompilationReason::kInstallFast:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_FAST;
+    case CompilationReason::kPrebuilt:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_PREBUILT;
+    case CompilationReason::kCmdLine:
+      return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_CMDLINE;
+  }
+}
+
+constexpr int32_t EncodeInstructionSet(InstructionSet isa) {
+  switch (isa) {
+    case InstructionSet::kArm:
+      // Fall-through.
+    case InstructionSet::kThumb2:
+      return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_ARM;
+    case InstructionSet::kArm64:
+      return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_ARM64;
+    case InstructionSet::kX86:
+      return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_X86;
+    case InstructionSet::kX86_64:
+      return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_X86_64;
+    case InstructionSet::kNone:
+      return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_UNKNOWN;
+  }
+}
+
+class StatsdBackend : public MetricsBackend {
+ public:
+  void BeginOrUpdateSession(const SessionData& session_data) override {
+    session_data_ = session_data;
+  }
+
+ protected:
+  void BeginReport(uint64_t timestamp_since_start_ms) override {
+    current_timestamp_ = static_cast<int64_t>(timestamp_since_start_ms);
+  }
+
+  void ReportCounter(DatumId counter_type, uint64_t value) override {
+    std::optional<int32_t> datum_id = EncodeDatumId(counter_type);
+    if (datum_id.has_value()) {
+      statsd::stats_write(
+          statsd::ART_DATUM_REPORTED,
+          session_data_.session_id,
+          session_data_.uid,
+          EncodeCompileFilter(session_data_.compiler_filter),
+          EncodeCompilationReason(session_data_.compilation_reason),
+          current_timestamp_,
+          /*thread_type=*/0,  // TODO: collect and report thread type (0 means UNKNOWN, but that
+                              // constant is not present in all branches)
+          datum_id.value(),
+          static_cast<int64_t>(value),
+          statsd::ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN,
+          statsd::ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_UNKNOWN,
+          EncodeInstructionSet(kRuntimeISA));
+    }
+  }
+
+  void ReportHistogram(DatumId /*histogram_type*/,
+                       int64_t /*low_value*/,
+                       int64_t /*high_value*/,
+                       const std::vector<uint32_t>& /*buckets*/) override {
+    // TODO: implement this once ArtDatumReported in atoms.proto supports histograms.
+    LOG_STREAM(DEBUG) << "Attempting to write histogram to statsd. This is not supported yet.";
+  }
+
+  void EndReport() override {}
+
+ private:
+  SessionData session_data_;
+  // The timestamp provided to the last call to BeginReport
+  int64_t current_timestamp_;
+};
+
+}  // namespace
+
+std::unique_ptr<MetricsBackend> CreateStatsdBackend() { return std::make_unique<StatsdBackend>(); }
+
+}  // namespace metrics
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
diff --git a/runtime/metrics/statsd.h b/runtime/metrics/statsd.h
new file mode 100644
index 0000000..a99d510
--- /dev/null
+++ b/runtime/metrics/statsd.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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_METRICS_STATSD_H_
+#define ART_RUNTIME_METRICS_STATSD_H_
+
+#include <memory>
+
+namespace art {
+namespace metrics {
+
+class MetricsBackend;
+
+// Statsd is only supported on Android
+#ifdef __ANDROID__
+std::unique_ptr<MetricsBackend> CreateStatsdBackend();
+#else
+inline std::unique_ptr<MetricsBackend> CreateStatsdBackend() { return nullptr; }
+#endif
+
+}  // namespace metrics
+}  // namespace art
+
+#endif  // ART_RUNTIME_METRICS_STATSD_H_
diff --git a/runtime/mirror/accessible_object.h b/runtime/mirror/accessible_object.h
index 9660bf0..7c0d91a 100644
--- a/runtime/mirror/accessible_object.h
+++ b/runtime/mirror/accessible_object.h
@@ -27,6 +27,8 @@
 // C++ mirror of java.lang.reflect.AccessibleObject
 class MANAGED AccessibleObject : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/reflect/AccessibleObject;");
+
   static MemberOffset FlagOffset() {
     return OFFSET_OF_OBJECT_MEMBER(AccessibleObject, flag_);
   }
@@ -38,8 +40,6 @@
  private:
   // We only use the field indirectly using the FlagOffset() method.
   uint8_t flag_ ATTRIBUTE_UNUSED;
-  // Padding required for correct alignment of subclasses like Executable, Field, etc.
-  uint8_t padding_[1] ATTRIBUTE_UNUSED;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(AccessibleObject);
 };
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 3f1cb16..b0e77b4 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -22,6 +22,7 @@
 #include <android-base/logging.h>
 
 #include "base/bit_utils.h"
+#include "base/casts.h"
 #include "class.h"
 #include "obj_ptr-inl.h"
 #include "runtime.h"
@@ -44,7 +45,7 @@
   // Don't need to check this since we already check this in GetClass.
   int32_t component_count =
       GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>();
-  // This is safe from overflow because the array was already allocated, so we know it's sane.
+  // This is safe from overflow because the array was already allocated.
   size_t header_size = DataOffset(1U << component_size_shift).SizeValue();
   size_t data_size = component_count << component_size_shift;
   return header_size + data_size;
@@ -259,23 +260,22 @@
   return GetElementPtrSize<T, PointerSize::k32, kVerifyFlags>(idx);
 }
 
-template<bool kTransactionActive, bool kUnchecked>
+template<bool kTransactionActive, bool kCheckTransaction, bool kUnchecked>
 inline void PointerArray::SetElementPtrSize(uint32_t idx, uint64_t element, PointerSize ptr_size) {
   if (ptr_size == PointerSize::k64) {
     (kUnchecked ? ObjPtr<LongArray>::DownCast(ObjPtr<Object>(this)) : AsLongArray())->
-        SetWithoutChecks<kTransactionActive>(idx, element);
+        SetWithoutChecks<kTransactionActive, kCheckTransaction>(idx, element);
   } else {
-    DCHECK_LE(element, static_cast<uint64_t>(0xFFFFFFFFu));
+    uint32_t element32 = dchecked_integral_cast<uint32_t>(element);
     (kUnchecked ? ObjPtr<IntArray>::DownCast(ObjPtr<Object>(this)) : AsIntArray())
-        ->SetWithoutChecks<kTransactionActive>(idx, static_cast<uint32_t>(element));
+        ->SetWithoutChecks<kTransactionActive, kCheckTransaction>(idx, element32);
   }
 }
 
-template<bool kTransactionActive, bool kUnchecked, typename T>
+template<bool kTransactionActive, bool kCheckTransaction, bool kUnchecked, typename T>
 inline void PointerArray::SetElementPtrSize(uint32_t idx, T* element, PointerSize ptr_size) {
-  SetElementPtrSize<kTransactionActive, kUnchecked>(idx,
-                                                    reinterpret_cast<uintptr_t>(element),
-                                                    ptr_size);
+  SetElementPtrSize<kTransactionActive, kCheckTransaction, kUnchecked>(
+      idx, reinterpret_cast<uintptr_t>(element), ptr_size);
 }
 
 template <VerifyObjectFlags kVerifyFlags, typename Visitor>
@@ -286,7 +286,9 @@
     void* ptr = GetElementPtrSize<void*, kVerifyFlags>(i, pointer_size);
     void* new_ptr = visitor(ptr);
     if (ptr != new_ptr) {
-      dest->SetElementPtrSize<false, true>(i, new_ptr, pointer_size);
+      dest->SetElementPtrSize</*kActiveTransaction=*/ false,
+                              /*kCheckTransaction=*/ true,
+                              /*kUnchecked=*/ true>(i, new_ptr, pointer_size);
     }
   }
 }
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index e011e1c..bd9f9ca 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -21,7 +21,7 @@
 #include "class-inl.h"
 #include "class.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_throws.h"
 #include "dex/dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 19f9a92..717d1de 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -149,6 +149,15 @@
 template<typename T>
 class MANAGED PrimitiveArray : public Array {
  public:
+  MIRROR_CLASS("[Z");
+  MIRROR_CLASS("[B");
+  MIRROR_CLASS("[C");
+  MIRROR_CLASS("[S");
+  MIRROR_CLASS("[I");
+  MIRROR_CLASS("[J");
+  MIRROR_CLASS("[F");
+  MIRROR_CLASS("[D");
+
   typedef T ElementType;
 
   static ObjPtr<PrimitiveArray<T>> Alloc(Thread* self, size_t length)
@@ -241,10 +250,13 @@
                                     static_cast<size_t>(ptr_size) * index);
   }
 
-  template<bool kTransactionActive = false, bool kUnchecked = false>
+  template<bool kTransactionActive = false, bool kCheckTransaction = true, bool kUnchecked = false>
   void SetElementPtrSize(uint32_t idx, uint64_t element, PointerSize ptr_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
-  template<bool kTransactionActive = false, bool kUnchecked = false, typename T>
+  template<bool kTransactionActive = false,
+           bool kCheckTransaction = true,
+           bool kUnchecked = false,
+           typename T>
   void SetElementPtrSize(uint32_t idx, T* element, PointerSize ptr_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
diff --git a/runtime/mirror/call_site.h b/runtime/mirror/call_site.h
index ca9a9ee..88387a3 100644
--- a/runtime/mirror/call_site.h
+++ b/runtime/mirror/call_site.h
@@ -29,6 +29,8 @@
 // C++ mirror of java.lang.invoke.CallSite
 class MANAGED CallSite : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/invoke/CallSite;");
+
   ObjPtr<MethodHandle> GetTarget() REQUIRES_SHARED(Locks::mutator_lock_);
 
  private:
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index a7f013c..3f9d41c 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -32,7 +32,7 @@
 #include "class_ext-inl.h"
 #include "class_linker-inl.h"
 #include "class_loader.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_annotations.h"
@@ -72,40 +72,9 @@
   if (IsPrimitive() || IsArrayClass() || IsProxyClass()) {
     return true;
   }
-  // TODO Have this list automatically populated.
-  std::unordered_set<std::string_view> mirror_types = {
-    "Ljava/lang/Class;",
-    "Ljava/lang/ClassLoader;",
-    "Ljava/lang/ClassNotFoundException;",
-    "Ljava/lang/DexCache;",
-    "Ljava/lang/Object;",
-    "Ljava/lang/StackTraceElement;",
-    "Ljava/lang/String;",
-    "Ljava/lang/Throwable;",
-    "Ljava/lang/invoke/ArrayElementVarHandle;",
-    "Ljava/lang/invoke/ByteArrayViewVarHandle;",
-    "Ljava/lang/invoke/ByteBufferViewVarHandle;",
-    "Ljava/lang/invoke/CallSite;",
-    "Ljava/lang/invoke/FieldVarHandle;",
-    "Ljava/lang/invoke/MethodHandle;",
-    "Ljava/lang/invoke/MethodHandleImpl;",
-    "Ljava/lang/invoke/MethodHandles$Lookup;",
-    "Ljava/lang/invoke/MethodType;",
-    "Ljava/lang/invoke/VarHandle;",
-    "Ljava/lang/ref/FinalizerReference;",
-    "Ljava/lang/ref/Reference;",
-    "Ljava/lang/reflect/AccessibleObject;",
-    "Ljava/lang/reflect/Constructor;",
-    "Ljava/lang/reflect/Executable;",
-    "Ljava/lang/reflect/Field;",
-    "Ljava/lang/reflect/Method;",
-    "Ljava/lang/reflect/Proxy;",
-    "Ldalvik/system/ClassExt;",
-    "Ldalvik/system/EmulatedStackFrame;",
-  };
   std::string name_storage;
-  const std::string name(this->GetDescriptor(&name_storage));
-  return mirror_types.find(name) != mirror_types.end();
+  const std::string_view name(this->GetDescriptor(&name_storage));
+  return IsMirroredDescriptor(name);
 }
 
 ObjPtr<mirror::Class> Class::GetPrimitiveClass(ObjPtr<mirror::String> name) {
@@ -496,8 +465,8 @@
 
 void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
   if (kIsDebugBuild && new_reference_offsets != kClassWalkSuper) {
-    // Sanity check that the number of bits set in the reference offset bitmap
-    // agrees with the number of references
+    // Check that the number of bits set in the reference offset bitmap
+    // agrees with the number of references.
     uint32_t count = 0;
     for (ObjPtr<Class> c = this; c != nullptr; c = c->GetSuperClass()) {
       count += c->NumReferenceInstanceFieldsDuringLinking();
@@ -1447,7 +1416,7 @@
   return false;
 }
 
-template <PointerSize kPointerSize, bool kTransactionActive>
+template <PointerSize kPointerSize>
 ObjPtr<Method> Class::GetDeclaredMethodInternal(
     Thread* self,
     ObjPtr<Class> klass,
@@ -1488,7 +1457,7 @@
     bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);
     if (!m_hidden && !m.IsSynthetic()) {
       // Non-hidden, virtual, non-synthetic. Best possible result, exit early.
-      return Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
+      return Method::CreateFromArtMethod<kPointerSize>(self, &m);
     } else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
       // Remember as potential result.
       result = &m;
@@ -1527,7 +1496,7 @@
         // Non-hidden, direct, non-synthetic. Any virtual result could only have been
         // hidden, therefore this is the best possible match. Exit now.
         DCHECK((result == nullptr) || result_hidden);
-        return Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
+        return Method::CreateFromArtMethod<kPointerSize>(self, &m);
       } else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
         // Remember as potential result.
         result = &m;
@@ -1537,40 +1506,26 @@
   }
 
   return result != nullptr
-      ? Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, result)
+      ? Method::CreateFromArtMethod<kPointerSize>(self, result)
       : nullptr;
 }
 
 template
-ObjPtr<Method> Class::GetDeclaredMethodInternal<PointerSize::k32, false>(
+ObjPtr<Method> Class::GetDeclaredMethodInternal<PointerSize::k32>(
     Thread* self,
     ObjPtr<Class> klass,
     ObjPtr<String> name,
     ObjPtr<ObjectArray<Class>> args,
     const std::function<hiddenapi::AccessContext()>& fn_get_access_context);
 template
-ObjPtr<Method> Class::GetDeclaredMethodInternal<PointerSize::k32, true>(
-    Thread* self,
-    ObjPtr<Class> klass,
-    ObjPtr<String> name,
-    ObjPtr<ObjectArray<Class>> args,
-    const std::function<hiddenapi::AccessContext()>& fn_get_access_context);
-template
-ObjPtr<Method> Class::GetDeclaredMethodInternal<PointerSize::k64, false>(
-    Thread* self,
-    ObjPtr<Class> klass,
-    ObjPtr<String> name,
-    ObjPtr<ObjectArray<Class>> args,
-    const std::function<hiddenapi::AccessContext()>& fn_get_access_context);
-template
-ObjPtr<Method> Class::GetDeclaredMethodInternal<PointerSize::k64, true>(
+ObjPtr<Method> Class::GetDeclaredMethodInternal<PointerSize::k64>(
     Thread* self,
     ObjPtr<Class> klass,
     ObjPtr<String> name,
     ObjPtr<ObjectArray<Class>> args,
     const std::function<hiddenapi::AccessContext()>& fn_get_access_context);
 
-template <PointerSize kPointerSize, bool kTransactionActive>
+template <PointerSize kPointerSize>
 ObjPtr<Constructor> Class::GetDeclaredConstructorInternal(
     Thread* self,
     ObjPtr<Class> klass,
@@ -1578,29 +1533,19 @@
   StackHandleScope<1> hs(self);
   ArtMethod* result = klass->GetDeclaredConstructor(self, hs.NewHandle(args), kPointerSize);
   return result != nullptr
-      ? Constructor::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, result)
+      ? Constructor::CreateFromArtMethod<kPointerSize>(self, result)
       : nullptr;
 }
 
 // Constructor::CreateFromArtMethod<kTransactionActive>(self, result)
 
 template
-ObjPtr<Constructor> Class::GetDeclaredConstructorInternal<PointerSize::k32, false>(
+ObjPtr<Constructor> Class::GetDeclaredConstructorInternal<PointerSize::k32>(
     Thread* self,
     ObjPtr<Class> klass,
     ObjPtr<ObjectArray<Class>> args);
 template
-ObjPtr<Constructor> Class::GetDeclaredConstructorInternal<PointerSize::k32, true>(
-    Thread* self,
-    ObjPtr<Class> klass,
-    ObjPtr<ObjectArray<Class>> args);
-template
-ObjPtr<Constructor> Class::GetDeclaredConstructorInternal<PointerSize::k64, false>(
-    Thread* self,
-    ObjPtr<Class> klass,
-    ObjPtr<ObjectArray<Class>> args);
-template
-ObjPtr<Constructor> Class::GetDeclaredConstructorInternal<PointerSize::k64, true>(
+ObjPtr<Constructor> Class::GetDeclaredConstructorInternal<PointerSize::k64>(
     Thread* self,
     ObjPtr<Class> klass,
     ObjPtr<ObjectArray<Class>> args);
@@ -1818,5 +1763,29 @@
   return res;
 }
 
+ArtMethod* Class::FindAccessibleInterfaceMethod(ArtMethod* implementation_method,
+                                                PointerSize pointer_size)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  ObjPtr<mirror::IfTable> iftable = GetIfTable();
+  for (int32_t i = 0, iftable_count = iftable->Count(); i < iftable_count; ++i) {
+    ObjPtr<mirror::PointerArray> methods = iftable->GetMethodArrayOrNull(i);
+    if (methods == nullptr) {
+      continue;
+    }
+    for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
+      if (implementation_method == methods->GetElementPtrSize<ArtMethod*>(j, pointer_size)) {
+        ObjPtr<mirror::Class> iface = iftable->GetInterface(i);
+        ArtMethod* interface_method = &iface->GetVirtualMethodsSlice(pointer_size)[j];
+        // If the interface method is part of the public SDK, return it.
+        if ((hiddenapi::GetRuntimeFlags(interface_method) & kAccPublicApi) != 0) {
+          return interface_method;
+        }
+      }
+    }
+  }
+  return nullptr;
+}
+
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 30a64b1..cc2924e 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -81,6 +81,8 @@
 // C++ mirror of java.lang.Class
 class MANAGED Class final : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/Class;");
+
   // A magic value for reference_instance_offsets_. Ignore the bits and walk the super chain when
   // this is the value.
   // [This is an unlikely "natural" value, since it would be 30 non-ref instance fields followed by
@@ -523,7 +525,7 @@
   };
 
   // Creates a raw object instance but does not invoke the default constructor.
-  // kCheckAddFinalizer controls whether we use a DCHECK to sanity check that we create a
+  // kCheckAddFinalizer controls whether we use a DCHECK to check that we create a
   // finalizer-reference if needed. This should only be disabled when doing structural class
   // redefinition.
   template <bool kIsInstrumented = true,
@@ -751,7 +753,7 @@
         PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  template <PointerSize kPointerSize, bool kTransactionActive>
+  template <PointerSize kPointerSize>
   static ObjPtr<Method> GetDeclaredMethodInternal(
       Thread* self,
       ObjPtr<Class> klass,
@@ -760,7 +762,7 @@
       const std::function<hiddenapi::AccessContext()>& fn_get_access_context)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  template <PointerSize kPointerSize, bool kTransactionActive>
+  template <PointerSize kPointerSize>
   static ObjPtr<Constructor> GetDeclaredConstructorInternal(Thread* self,
                                                             ObjPtr<Class> klass,
                                                             ObjPtr<ObjectArray<Class>> args)
@@ -774,6 +776,9 @@
         PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  // The index in the methods_ array where the first copied method is.
+  ALWAYS_INLINE uint32_t GetCopiedMethodsStartOffset() REQUIRES_SHARED(Locks::mutator_lock_);
+
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ALWAYS_INLINE ArraySlice<ArtMethod> GetCopiedMethodsSlice(PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -923,6 +928,12 @@
                                  PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  // Return the first public SDK method from the list of interfaces implemented by
+  // this class.
+  ArtMethod* FindAccessibleInterfaceMethod(ArtMethod* implementation_method,
+                                           PointerSize pointer_size)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   // Find a method with the given name and signature in a non-interface class.
   //
   // Search for the method in the class, following the JLS rules which conflict with the RI
@@ -1388,9 +1399,6 @@
   // The index in the methods_ array where the first direct method is.
   ALWAYS_INLINE uint32_t GetDirectMethodsStartOffset() REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // The index in the methods_ array where the first copied method is.
-  ALWAYS_INLINE uint32_t GetCopiedMethodsStartOffset() REQUIRES_SHARED(Locks::mutator_lock_);
-
   bool ProxyDescriptorEquals(const char* match) REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags>
diff --git a/runtime/mirror/class_ext-inl.h b/runtime/mirror/class_ext-inl.h
index 99f7f49..b8493c1 100644
--- a/runtime/mirror/class_ext-inl.h
+++ b/runtime/mirror/class_ext-inl.h
@@ -23,7 +23,6 @@
 #include "art_method-inl.h"
 #include "base/enums.h"
 #include "base/globals.h"
-#include "class_root.h"
 #include "handle_scope.h"
 #include "jni/jni_internal.h"
 #include "jni_id_type.h"
diff --git a/runtime/mirror/class_ext.cc b/runtime/mirror/class_ext.cc
index ba1ae5f..7543ab6 100644
--- a/runtime/mirror/class_ext.cc
+++ b/runtime/mirror/class_ext.cc
@@ -22,7 +22,7 @@
 #include "base/utils.h"
 #include "class-alloc-inl.h"
 #include "class-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
 #include "mirror/object.h"
diff --git a/runtime/mirror/class_ext.h b/runtime/mirror/class_ext.h
index fa4e87a..2fd8c39 100644
--- a/runtime/mirror/class_ext.h
+++ b/runtime/mirror/class_ext.h
@@ -33,6 +33,8 @@
 // C++ mirror of dalvik.system.ClassExt
 class MANAGED ClassExt : public Object {
  public:
+  MIRROR_CLASS("Ldalvik/system/ClassExt;");
+
   static uint32_t ClassSize(PointerSize pointer_size);
 
   // Size of an instance of dalvik.system.ClassExt.
diff --git a/runtime/mirror/class_loader.h b/runtime/mirror/class_loader.h
index c90a3da..197172c 100644
--- a/runtime/mirror/class_loader.h
+++ b/runtime/mirror/class_loader.h
@@ -35,6 +35,8 @@
 // C++ mirror of java.lang.ClassLoader
 class MANAGED ClassLoader : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/ClassLoader;");
+
   // Size of an instance of java.lang.ClassLoader.
   static constexpr uint32_t InstanceSize() {
     return sizeof(ClassLoader);
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index d5e1362..1ca4202 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -63,12 +63,11 @@
 }
 
 template <typename T>
-inline void NativeDexCachePair<T>::Initialize(std::atomic<NativeDexCachePair<T>>* dex_cache,
-                                              PointerSize pointer_size) {
+inline void NativeDexCachePair<T>::Initialize(std::atomic<NativeDexCachePair<T>>* dex_cache) {
   NativeDexCachePair<T> first_elem;
   first_elem.object = nullptr;
   first_elem.index = InvalidIndexForSlot(0);
-  DexCache::SetNativePairPtrSize(dex_cache, 0, first_elem, pointer_size);
+  DexCache::SetNativePair(dex_cache, 0, first_elem);
 }
 
 inline uint32_t DexCache::ClassSize(PointerSize pointer_size) {
@@ -244,29 +243,15 @@
   return slot_idx;
 }
 
-inline ArtField* DexCache::GetResolvedField(uint32_t field_idx, PointerSize ptr_size) {
-  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
-  auto pair = GetNativePairPtrSize(GetResolvedFields(), FieldSlotIndex(field_idx), ptr_size);
+inline ArtField* DexCache::GetResolvedField(uint32_t field_idx) {
+  auto pair = GetNativePair(GetResolvedFields(), FieldSlotIndex(field_idx));
   return pair.GetObjectForIndex(field_idx);
 }
 
-inline void DexCache::SetResolvedField(uint32_t field_idx, ArtField* field, PointerSize ptr_size) {
-  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
+inline void DexCache::SetResolvedField(uint32_t field_idx, ArtField* field) {
   DCHECK(field != nullptr);
   FieldDexCachePair pair(field, field_idx);
-  SetNativePairPtrSize(GetResolvedFields(), FieldSlotIndex(field_idx), pair, ptr_size);
-}
-
-inline void DexCache::ClearResolvedField(uint32_t field_idx, PointerSize ptr_size) {
-  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
-  uint32_t slot_idx = FieldSlotIndex(field_idx);
-  auto* resolved_fields = GetResolvedFields();
-  // This is racy but should only be called from the single-threaded ImageWriter.
-  DCHECK(Runtime::Current()->IsAotCompiler());
-  if (GetNativePairPtrSize(resolved_fields, slot_idx, ptr_size).index == field_idx) {
-    FieldDexCachePair cleared(nullptr, FieldDexCachePair::InvalidIndexForSlot(slot_idx));
-    SetNativePairPtrSize(resolved_fields, slot_idx, cleared, ptr_size);
-  }
+  SetNativePair(GetResolvedFields(), FieldSlotIndex(field_idx), pair);
 }
 
 inline uint32_t DexCache::MethodSlotIndex(uint32_t method_idx) {
@@ -276,38 +261,21 @@
   return slot_idx;
 }
 
-inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx, PointerSize ptr_size) {
-  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
-  auto pair = GetNativePairPtrSize(GetResolvedMethods(), MethodSlotIndex(method_idx), ptr_size);
+inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx) {
+  auto pair = GetNativePair(GetResolvedMethods(), MethodSlotIndex(method_idx));
   return pair.GetObjectForIndex(method_idx);
 }
 
-inline void DexCache::SetResolvedMethod(uint32_t method_idx,
-                                        ArtMethod* method,
-                                        PointerSize ptr_size) {
-  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
+inline void DexCache::SetResolvedMethod(uint32_t method_idx, ArtMethod* method) {
   DCHECK(method != nullptr);
   MethodDexCachePair pair(method, method_idx);
-  SetNativePairPtrSize(GetResolvedMethods(), MethodSlotIndex(method_idx), pair, ptr_size);
-}
-
-inline void DexCache::ClearResolvedMethod(uint32_t method_idx, PointerSize ptr_size) {
-  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
-  uint32_t slot_idx = MethodSlotIndex(method_idx);
-  auto* resolved_methods = GetResolvedMethods();
-  // This is racy but should only be called from the single-threaded ImageWriter.
-  DCHECK(Runtime::Current()->IsAotCompiler());
-  if (GetNativePairPtrSize(resolved_methods, slot_idx, ptr_size).index == method_idx) {
-    MethodDexCachePair cleared(nullptr, MethodDexCachePair::InvalidIndexForSlot(slot_idx));
-    SetNativePairPtrSize(resolved_methods, slot_idx, cleared, ptr_size);
-  }
+  SetNativePair(GetResolvedMethods(), MethodSlotIndex(method_idx), pair);
 }
 
 template <typename T>
-NativeDexCachePair<T> DexCache::GetNativePairPtrSize(std::atomic<NativeDexCachePair<T>>* pair_array,
-                                                     size_t idx,
-                                                     PointerSize ptr_size) {
-  if (ptr_size == PointerSize::k64) {
+NativeDexCachePair<T> DexCache::GetNativePair(std::atomic<NativeDexCachePair<T>>* pair_array,
+                                              size_t idx) {
+  if (kRuntimePointerSize == PointerSize::k64) {
     auto* array = reinterpret_cast<std::atomic<ConversionPair64>*>(pair_array);
     ConversionPair64 value = AtomicLoadRelaxed16B(&array[idx]);
     return NativeDexCachePair<T>(reinterpret_cast64<T*>(value.first),
@@ -320,11 +288,10 @@
 }
 
 template <typename T>
-void DexCache::SetNativePairPtrSize(std::atomic<NativeDexCachePair<T>>* pair_array,
-                                    size_t idx,
-                                    NativeDexCachePair<T> pair,
-                                    PointerSize ptr_size) {
-  if (ptr_size == PointerSize::k64) {
+void DexCache::SetNativePair(std::atomic<NativeDexCachePair<T>>* pair_array,
+                             size_t idx,
+                             NativeDexCachePair<T> pair) {
+  if (kRuntimePointerSize == PointerSize::k64) {
     auto* array = reinterpret_cast<std::atomic<ConversionPair64>*>(pair_array);
     ConversionPair64 v(reinterpret_cast64<uint64_t>(pair.object), pair.index);
     AtomicStoreRelease16B(&array[idx], v);
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index 40997f6..1b9558e 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -30,95 +30,60 @@
 #include "runtime_globals.h"
 #include "string.h"
 #include "thread.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
 #include "write_barrier.h"
 
 namespace art {
 namespace mirror {
 
-void DexCache::InitializeDexCache(Thread* self,
-                                  ObjPtr<mirror::DexCache> dex_cache,
-                                  ObjPtr<mirror::String> location,
-                                  const DexFile* dex_file,
-                                  LinearAlloc* linear_alloc,
-                                  PointerSize image_pointer_size) {
-  DCHECK(dex_file != nullptr);
+template<typename T>
+static T* AllocArray(Thread* self, LinearAlloc* alloc, size_t num) {
+  if (num == 0) {
+    return nullptr;
+  }
+  return reinterpret_cast<T*>(alloc->AllocAlign16(self, RoundUp(num * sizeof(T), 16)));
+}
+
+void DexCache::InitializeNativeFields(const DexFile* dex_file, LinearAlloc* linear_alloc) {
+  DCHECK(GetDexFile() == nullptr);
+  DCHECK(GetStrings() == nullptr);
+  DCHECK(GetResolvedTypes() == nullptr);
+  DCHECK(GetResolvedMethods() == nullptr);
+  DCHECK(GetResolvedFields() == nullptr);
+  DCHECK(GetResolvedMethodTypes() == nullptr);
+  DCHECK(GetResolvedCallSites() == nullptr);
+
   ScopedAssertNoThreadSuspension sants(__FUNCTION__);
-  DexCacheArraysLayout layout(image_pointer_size, dex_file);
-  uint8_t* raw_arrays = nullptr;
+  Thread* self = Thread::Current();
 
-  if (dex_file->NumStringIds() != 0u ||
-      dex_file->NumTypeIds() != 0u ||
-      dex_file->NumMethodIds() != 0u ||
-      dex_file->NumFieldIds() != 0u) {
-    static_assert(ArenaAllocator::kAlignment == 8, "Expecting arena alignment of 8.");
-    DCHECK(layout.Alignment() == 8u || layout.Alignment() == 16u);
-    // Zero-initialized.
-    raw_arrays = (layout.Alignment() == 16u)
-        ? reinterpret_cast<uint8_t*>(linear_alloc->AllocAlign16(self, layout.Size()))
-        : reinterpret_cast<uint8_t*>(linear_alloc->Alloc(self, layout.Size()));
-  }
+  size_t num_strings = std::min<size_t>(kDexCacheStringCacheSize, dex_file->NumStringIds());
+  size_t num_types = std::min<size_t>(kDexCacheTypeCacheSize, dex_file->NumTypeIds());
+  size_t num_fields = std::min<size_t>(kDexCacheFieldCacheSize, dex_file->NumFieldIds());
+  size_t num_methods = std::min<size_t>(kDexCacheMethodCacheSize, dex_file->NumMethodIds());
+  size_t num_method_types = std::min<size_t>(kDexCacheMethodTypeCacheSize, dex_file->NumProtoIds());
+  size_t num_call_sites = dex_file->NumCallSiteIds();  // Full size.
 
-  StringDexCacheType* strings = (dex_file->NumStringIds() == 0u) ? nullptr :
-      reinterpret_cast<StringDexCacheType*>(raw_arrays + layout.StringsOffset());
-  TypeDexCacheType* types = (dex_file->NumTypeIds() == 0u) ? nullptr :
-      reinterpret_cast<TypeDexCacheType*>(raw_arrays + layout.TypesOffset());
-  MethodDexCacheType* methods = (dex_file->NumMethodIds() == 0u) ? nullptr :
-      reinterpret_cast<MethodDexCacheType*>(raw_arrays + layout.MethodsOffset());
-  FieldDexCacheType* fields = (dex_file->NumFieldIds() == 0u) ? nullptr :
-      reinterpret_cast<FieldDexCacheType*>(raw_arrays + layout.FieldsOffset());
+  static_assert(ArenaAllocator::kAlignment == 8, "Expecting arena alignment of 8.");
+  StringDexCacheType* strings =
+      AllocArray<StringDexCacheType>(self, linear_alloc, num_strings);
+  TypeDexCacheType* types =
+      AllocArray<TypeDexCacheType>(self, linear_alloc, num_types);
+  MethodDexCacheType* methods =
+      AllocArray<MethodDexCacheType>(self, linear_alloc, num_methods);
+  FieldDexCacheType* fields =
+      AllocArray<FieldDexCacheType>(self, linear_alloc, num_fields);
+  MethodTypeDexCacheType* method_types =
+      AllocArray<MethodTypeDexCacheType>(self, linear_alloc, num_method_types);
+  GcRoot<mirror::CallSite>* call_sites =
+      AllocArray<GcRoot<CallSite>>(self, linear_alloc, num_call_sites);
 
-  size_t num_strings = kDexCacheStringCacheSize;
-  if (dex_file->NumStringIds() < num_strings) {
-    num_strings = dex_file->NumStringIds();
-  }
-  size_t num_types = kDexCacheTypeCacheSize;
-  if (dex_file->NumTypeIds() < num_types) {
-    num_types = dex_file->NumTypeIds();
-  }
-  size_t num_fields = kDexCacheFieldCacheSize;
-  if (dex_file->NumFieldIds() < num_fields) {
-    num_fields = dex_file->NumFieldIds();
-  }
-  size_t num_methods = kDexCacheMethodCacheSize;
-  if (dex_file->NumMethodIds() < num_methods) {
-    num_methods = dex_file->NumMethodIds();
-  }
-
-  // Note that we allocate the method type dex caches regardless of this flag,
-  // and we make sure here that they're not used by the runtime. This is in the
-  // interest of simplicity and to avoid extensive compiler and layout class changes.
-  //
-  // If this needs to be mitigated in a production system running this code,
-  // DexCache::kDexCacheMethodTypeCacheSize can be set to zero.
-  MethodTypeDexCacheType* method_types = nullptr;
-  size_t num_method_types = 0;
-
-  if (dex_file->NumProtoIds() < kDexCacheMethodTypeCacheSize) {
-    num_method_types = dex_file->NumProtoIds();
-  } else {
-    num_method_types = kDexCacheMethodTypeCacheSize;
-  }
-
-  if (num_method_types > 0) {
-    method_types = reinterpret_cast<MethodTypeDexCacheType*>(
-        raw_arrays + layout.MethodTypesOffset());
-  }
-
-  GcRoot<mirror::CallSite>* call_sites = (dex_file->NumCallSiteIds() == 0)
-      ? nullptr
-      : reinterpret_cast<GcRoot<CallSite>*>(raw_arrays + layout.CallSitesOffset());
-
-  DCHECK_ALIGNED(raw_arrays, alignof(StringDexCacheType)) <<
-                 "Expected raw_arrays to align to StringDexCacheType.";
-  DCHECK_ALIGNED(layout.StringsOffset(), alignof(StringDexCacheType)) <<
+  DCHECK_ALIGNED(types, alignof(StringDexCacheType)) <<
                  "Expected StringsOffset() to align to StringDexCacheType.";
   DCHECK_ALIGNED(strings, alignof(StringDexCacheType)) <<
                  "Expected strings to align to StringDexCacheType.";
   static_assert(alignof(StringDexCacheType) == 8u,
                 "Expected StringDexCacheType to have align of 8.");
   if (kIsDebugBuild) {
-    // Sanity check to make sure all the dex cache arrays are empty. b/28992179
+    // Consistency check to make sure all the dex cache arrays are empty. b/28992179
     for (size_t i = 0; i < num_strings; ++i) {
       CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u);
       CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull());
@@ -128,12 +93,12 @@
       CHECK(types[i].load(std::memory_order_relaxed).object.IsNull());
     }
     for (size_t i = 0; i < num_methods; ++i) {
-      CHECK_EQ(GetNativePairPtrSize(methods, i, image_pointer_size).index, 0u);
-      CHECK(GetNativePairPtrSize(methods, i, image_pointer_size).object == nullptr);
+      CHECK_EQ(GetNativePair(methods, i).index, 0u);
+      CHECK(GetNativePair(methods, i).object == nullptr);
     }
     for (size_t i = 0; i < num_fields; ++i) {
-      CHECK_EQ(GetNativePairPtrSize(fields, i, image_pointer_size).index, 0u);
-      CHECK(GetNativePairPtrSize(fields, i, image_pointer_size).object == nullptr);
+      CHECK_EQ(GetNativePair(fields, i).index, 0u);
+      CHECK(GetNativePair(fields, i).object == nullptr);
     }
     for (size_t i = 0; i < num_method_types; ++i) {
       CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u);
@@ -150,17 +115,16 @@
     mirror::TypeDexCachePair::Initialize(types);
   }
   if (fields != nullptr) {
-    mirror::FieldDexCachePair::Initialize(fields, image_pointer_size);
+    mirror::FieldDexCachePair::Initialize(fields);
   }
   if (methods != nullptr) {
-    mirror::MethodDexCachePair::Initialize(methods, image_pointer_size);
+    mirror::MethodDexCachePair::Initialize(methods);
   }
   if (method_types != nullptr) {
     mirror::MethodTypeDexCachePair::Initialize(method_types);
   }
-  dex_cache->Init(dex_file,
-                  location,
-                  strings,
+  SetDexFile(dex_file);
+  SetNativeArrays(strings,
                   num_strings,
                   types,
                   num_types,
@@ -171,13 +135,18 @@
                   method_types,
                   num_method_types,
                   call_sites,
-                  dex_file->NumCallSiteIds());
+                  num_call_sites);
+}
+
+void DexCache::ResetNativeFields() {
+  SetDexFile(nullptr);
+  SetNativeArrays(nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0);
 }
 
 void DexCache::VisitReflectiveTargets(ReflectiveValueVisitor* visitor) {
   bool wrote = false;
   for (size_t i = 0; i < NumResolvedFields(); i++) {
-    auto pair(GetNativePairPtrSize(GetResolvedFields(), i, kRuntimePointerSize));
+    auto pair(GetNativePair(GetResolvedFields(), i));
     if (pair.index == FieldDexCachePair::InvalidIndexForSlot(i)) {
       continue;
     }
@@ -189,12 +158,12 @@
       } else {
         pair.object = new_val;
       }
-      SetNativePairPtrSize(GetResolvedFields(), i, pair, kRuntimePointerSize);
+      SetNativePair(GetResolvedFields(), i, pair);
       wrote = true;
     }
   }
   for (size_t i = 0; i < NumResolvedMethods(); i++) {
-    auto pair(GetNativePairPtrSize(GetResolvedMethods(), i, kRuntimePointerSize));
+    auto pair(GetNativePair(GetResolvedMethods(), i));
     if (pair.index == MethodDexCachePair::InvalidIndexForSlot(i)) {
       continue;
     }
@@ -206,7 +175,7 @@
       } else {
         pair.object = new_val;
       }
-      SetNativePairPtrSize(GetResolvedMethods(), i, pair, kRuntimePointerSize);
+      SetNativePair(GetResolvedMethods(), i, pair);
       wrote = true;
     }
   }
@@ -238,31 +207,24 @@
   return true;
 }
 
-void DexCache::Init(const DexFile* dex_file,
-                    ObjPtr<String> location,
-                    StringDexCacheType* strings,
-                    uint32_t num_strings,
-                    TypeDexCacheType* resolved_types,
-                    uint32_t num_resolved_types,
-                    MethodDexCacheType* resolved_methods,
-                    uint32_t num_resolved_methods,
-                    FieldDexCacheType* resolved_fields,
-                    uint32_t num_resolved_fields,
-                    MethodTypeDexCacheType* resolved_method_types,
-                    uint32_t num_resolved_method_types,
-                    GcRoot<CallSite>* resolved_call_sites,
-                    uint32_t num_resolved_call_sites) {
-  CHECK(dex_file != nullptr);
-  CHECK(location != nullptr);
+void DexCache::SetNativeArrays(StringDexCacheType* strings,
+                               uint32_t num_strings,
+                               TypeDexCacheType* resolved_types,
+                               uint32_t num_resolved_types,
+                               MethodDexCacheType* resolved_methods,
+                               uint32_t num_resolved_methods,
+                               FieldDexCacheType* resolved_fields,
+                               uint32_t num_resolved_fields,
+                               MethodTypeDexCacheType* resolved_method_types,
+                               uint32_t num_resolved_method_types,
+                               GcRoot<CallSite>* resolved_call_sites,
+                               uint32_t num_resolved_call_sites) {
   CHECK_EQ(num_strings != 0u, strings != nullptr);
   CHECK_EQ(num_resolved_types != 0u, resolved_types != nullptr);
   CHECK_EQ(num_resolved_methods != 0u, resolved_methods != nullptr);
   CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr);
   CHECK_EQ(num_resolved_method_types != 0u, resolved_method_types != nullptr);
   CHECK_EQ(num_resolved_call_sites != 0u, resolved_call_sites != nullptr);
-
-  SetDexFile(dex_file);
-  SetLocation(location);
   SetStrings(strings);
   SetResolvedTypes(resolved_types);
   SetResolvedMethods(resolved_methods);
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 6067c76..ea52785 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -97,7 +97,7 @@
   NativeDexCachePair(const NativeDexCachePair<T>&) = default;
   NativeDexCachePair& operator=(const NativeDexCachePair<T>&) = default;
 
-  static void Initialize(std::atomic<NativeDexCachePair<T>>* dex_cache, PointerSize pointer_size);
+  static void Initialize(std::atomic<NativeDexCachePair<T>>* dex_cache);
 
   static uint32_t InvalidIndexForSlot(uint32_t slot) {
     // Since the cache size is a power of two, 0 will always map to slot 0.
@@ -132,6 +132,8 @@
 // C++ mirror of java.lang.DexCache.
 class MANAGED DexCache final : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/DexCache;");
+
   // Size of java.lang.DexCache.class.
   static uint32_t ClassSize(PointerSize pointer_size);
 
@@ -186,15 +188,14 @@
     return sizeof(DexCache);
   }
 
-  static void InitializeDexCache(Thread* self,
-                                 ObjPtr<mirror::DexCache> dex_cache,
-                                 ObjPtr<mirror::String> location,
-                                 const DexFile* dex_file,
-                                 LinearAlloc* linear_alloc,
-                                 PointerSize image_pointer_size)
+  // Initialize native fields and allocate memory.
+  void InitializeNativeFields(const DexFile* dex_file, LinearAlloc* linear_alloc)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(Locks::dex_lock_);
 
+  // Clear all native fields.
+  void ResetNativeFields() REQUIRES_SHARED(Locks::mutator_lock_);
+
   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
   void FixupStrings(StringDexCacheType* dest, const Visitor& visitor)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -298,24 +299,16 @@
 
   void ClearResolvedType(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE ArtMethod* GetResolvedMethod(uint32_t method_idx, PointerSize ptr_size)
+  ALWAYS_INLINE ArtMethod* GetResolvedMethod(uint32_t method_idx)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE void SetResolvedMethod(uint32_t method_idx,
-                                       ArtMethod* resolved,
-                                       PointerSize ptr_size)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  ALWAYS_INLINE void ClearResolvedMethod(uint32_t method_idx, PointerSize ptr_size)
+  ALWAYS_INLINE void SetResolvedMethod(uint32_t method_idx, ArtMethod* resolved)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Pointer sized variant, used for patching.
-  ALWAYS_INLINE ArtField* GetResolvedField(uint32_t idx, PointerSize ptr_size)
+  ALWAYS_INLINE ArtField* GetResolvedField(uint32_t idx)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Pointer sized variant, used for patching.
-  ALWAYS_INLINE void SetResolvedField(uint32_t idx, ArtField* field, PointerSize ptr_size)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  ALWAYS_INLINE void ClearResolvedField(uint32_t idx, PointerSize ptr_size)
+  ALWAYS_INLINE void SetResolvedField(uint32_t idx, ArtField* field)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   MethodType* GetResolvedMethodType(dex::ProtoIndex proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -455,15 +448,13 @@
   void SetLocation(ObjPtr<String> location) REQUIRES_SHARED(Locks::mutator_lock_);
 
   template <typename T>
-  static NativeDexCachePair<T> GetNativePairPtrSize(std::atomic<NativeDexCachePair<T>>* pair_array,
-                                                    size_t idx,
-                                                    PointerSize ptr_size);
+  static NativeDexCachePair<T> GetNativePair(std::atomic<NativeDexCachePair<T>>* pair_array,
+                                             size_t idx);
 
   template <typename T>
-  static void SetNativePairPtrSize(std::atomic<NativeDexCachePair<T>>* pair_array,
-                                   size_t idx,
-                                   NativeDexCachePair<T> pair,
-                                   PointerSize ptr_size);
+  static void SetNativePair(std::atomic<NativeDexCachePair<T>>* pair_array,
+                            size_t idx,
+                            NativeDexCachePair<T> pair);
 
   static size_t PreResolvedStringsSize(size_t num_strings) {
     return sizeof(GcRoot<mirror::String>) * num_strings;
@@ -483,20 +474,18 @@
   void SetClassLoader(ObjPtr<ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_);
 
  private:
-  void Init(const DexFile* dex_file,
-            ObjPtr<String> location,
-            StringDexCacheType* strings,
-            uint32_t num_strings,
-            TypeDexCacheType* resolved_types,
-            uint32_t num_resolved_types,
-            MethodDexCacheType* resolved_methods,
-            uint32_t num_resolved_methods,
-            FieldDexCacheType* resolved_fields,
-            uint32_t num_resolved_fields,
-            MethodTypeDexCacheType* resolved_method_types,
-            uint32_t num_resolved_method_types,
-            GcRoot<CallSite>* resolved_call_sites,
-            uint32_t num_resolved_call_sites)
+  void SetNativeArrays(StringDexCacheType* strings,
+                       uint32_t num_strings,
+                       TypeDexCacheType* resolved_types,
+                       uint32_t num_resolved_types,
+                       MethodDexCacheType* resolved_methods,
+                       uint32_t num_resolved_methods,
+                       FieldDexCacheType* resolved_fields,
+                       uint32_t num_resolved_fields,
+                       MethodTypeDexCacheType* resolved_method_types,
+                       uint32_t num_resolved_method_types,
+                       GcRoot<CallSite>* resolved_call_sites,
+                       uint32_t num_resolved_call_sites)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // std::pair<> is not trivially copyable and as such it is unsuitable for atomic operations,
diff --git a/runtime/mirror/emulated_stack_frame.cc b/runtime/mirror/emulated_stack_frame.cc
index cfdab8f..19e40dc 100644
--- a/runtime/mirror/emulated_stack_frame.cc
+++ b/runtime/mirror/emulated_stack_frame.cc
@@ -19,7 +19,7 @@
 #include "array-alloc-inl.h"
 #include "array-inl.h"
 #include "class-alloc-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "handle.h"
 #include "jvalue-inl.h"
 #include "method_handles-inl.h"
diff --git a/runtime/mirror/emulated_stack_frame.h b/runtime/mirror/emulated_stack_frame.h
index 626215e..b63ccaa 100644
--- a/runtime/mirror/emulated_stack_frame.h
+++ b/runtime/mirror/emulated_stack_frame.h
@@ -34,6 +34,8 @@
 // C++ mirror of dalvik.system.EmulatedStackFrame
 class MANAGED EmulatedStackFrame : public Object {
  public:
+  MIRROR_CLASS("Ldalvik/system/EmulatedStackFrame;");
+
   // Creates an emulated stack frame whose type is |frame_type| from
   // a shadow frame.
   static ObjPtr<mirror::EmulatedStackFrame> CreateFromShadowFrameAndArgs(
diff --git a/runtime/mirror/executable.cc b/runtime/mirror/executable.cc
index d2a2ec5..3996f49 100644
--- a/runtime/mirror/executable.cc
+++ b/runtime/mirror/executable.cc
@@ -22,22 +22,24 @@
 namespace art {
 namespace mirror {
 
-template <PointerSize kPointerSize, bool kTransactionActive>
-bool Executable::CreateFromArtMethod(ArtMethod* method) {
+template <PointerSize kPointerSize>
+void Executable::InitializeFromArtMethod(ArtMethod* method) {
+  // We're initializing a newly allocated object, so we do not need to record that under
+  // a transaction. If the transaction is aborted, the whole object shall be unreachable.
   auto* interface_method = method->GetInterfaceMethodIfProxy(kPointerSize);
-  SetArtMethod<kTransactionActive>(method);
-  SetFieldObject<kTransactionActive>(DeclaringClassOffset(), method->GetDeclaringClass());
-  SetFieldObject<kTransactionActive>(
+  SetArtMethod</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(method);
+  SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+      DeclaringClassOffset(), method->GetDeclaringClass());
+  SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
       DeclaringClassOfOverriddenMethodOffset(), interface_method->GetDeclaringClass());
-  SetField32<kTransactionActive>(AccessFlagsOffset(), method->GetAccessFlags());
-  SetField32<kTransactionActive>(DexMethodIndexOffset(), method->GetDexMethodIndex());
-  return true;
+  SetField32</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+      AccessFlagsOffset(), method->GetAccessFlags());
+  SetField32</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+      DexMethodIndexOffset(), method->GetDexMethodIndex());
 }
 
-template bool Executable::CreateFromArtMethod<PointerSize::k32, false>(ArtMethod* method);
-template bool Executable::CreateFromArtMethod<PointerSize::k32, true>(ArtMethod* method);
-template bool Executable::CreateFromArtMethod<PointerSize::k64, false>(ArtMethod* method);
-template bool Executable::CreateFromArtMethod<PointerSize::k64, true>(ArtMethod* method);
+template void Executable::InitializeFromArtMethod<PointerSize::k32>(ArtMethod* method);
+template void Executable::InitializeFromArtMethod<PointerSize::k64>(ArtMethod* method);
 
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/executable.h b/runtime/mirror/executable.h
index 750a167..dc4ec95 100644
--- a/runtime/mirror/executable.h
+++ b/runtime/mirror/executable.h
@@ -32,10 +32,7 @@
 // C++ mirror of java.lang.reflect.Executable.
 class MANAGED Executable : public AccessibleObject {
  public:
-  // Called from Constructor::CreateFromArtMethod, Method::CreateFromArtMethod.
-  template <PointerSize kPointerSize, bool kTransactionActive>
-  bool CreateFromArtMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Roles::uninterruptible_);
+  MIRROR_CLASS("Ljava/lang/reflect/Executable;");
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ArtMethod* GetArtMethod() REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -56,8 +53,19 @@
     return MemberOffset(OFFSETOF_MEMBER(Executable, art_method_));
   }
 
+ protected:
+  // Called from Constructor::CreateFromArtMethod, Method::CreateFromArtMethod.
+  template <PointerSize kPointerSize>
+  void InitializeFromArtMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!Roles::uninterruptible_);
+
+
  private:
-  uint16_t has_real_parameter_data_;
+  uint8_t has_real_parameter_data_;
+
+  // Padding required for matching alignment with the Java peer.
+  uint8_t padding_[2] ATTRIBUTE_UNUSED;
+
   HeapReference<mirror::Class> declaring_class_;
   HeapReference<mirror::Class> declaring_class_of_overridden_method_;
   HeapReference<mirror::Array> parameters_;
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index 8a9cec4..f1f8b25 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -21,8 +21,7 @@
 
 #include "art_field-inl.h"
 #include "class-alloc-inl.h"
-#include "class_root.h"
-#include "dex_cache-inl.h"
+#include "class_root-inl.h"
 #include "object-inl.h"
 
 namespace art {
@@ -41,72 +40,14 @@
   return GetFieldObject<mirror::Class>(OFFSET_OF_OBJECT_MEMBER(Field, type_));
 }
 
-template <PointerSize kPointerSize, bool kTransactionActive>
-inline ObjPtr<mirror::Field> Field::CreateFromArtField(Thread* self,
-                                                       ArtField* field,
-                                                       bool force_resolve) {
-  StackHandleScope<2> hs(self);
-  // Try to resolve type before allocating since this is a thread suspension point.
-  Handle<mirror::Class> type = hs.NewHandle(field->ResolveType());
-
-  if (type == nullptr) {
-    if (force_resolve) {
-      if (kIsDebugBuild) {
-        self->AssertPendingException();
-      }
-      return nullptr;
-    } else {
-      // Can't resolve, clear the exception if it isn't OOME and continue with a null type.
-      mirror::Throwable* exception = self->GetException();
-      if (exception->GetClass()->DescriptorEquals("Ljava/lang/OutOfMemoryError;")) {
-        return nullptr;
-      }
-      self->ClearException();
-    }
-  }
-  auto ret = hs.NewHandle(ObjPtr<Field>::DownCast(GetClassRoot<Field>()->AllocObject(self)));
-  if (UNLIKELY(ret == nullptr)) {
-    self->AssertPendingOOMException();
-    return nullptr;
-  }
-  auto dex_field_index = field->GetDexFieldIndex();
-  auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index, kPointerSize);
-  if (field->GetDeclaringClass()->IsProxyClass()) {
-    DCHECK(field->IsStatic());
-    DCHECK_LT(dex_field_index, 2U);
-    // The two static fields (interfaces, throws) of all proxy classes
-    // share the same dex file indices 0 and 1. So, we can't resolve
-    // them in the dex cache.
-  } else {
-    if (resolved_field != nullptr) {
-      DCHECK_EQ(resolved_field, field);
-    } else {
-      // We rely on the field being resolved so that we can back to the ArtField
-      // (i.e. FromReflectedMethod).
-      field->GetDexCache()->SetResolvedField(dex_field_index, field, kPointerSize);
-    }
-  }
-  ret->SetType<kTransactionActive>(type.Get());
-  ret->SetDeclaringClass<kTransactionActive>(field->GetDeclaringClass());
-  ret->SetAccessFlags<kTransactionActive>(field->GetAccessFlags());
-  auto iter_range = field->IsStatic() ? field->GetDeclaringClass()->GetSFields()
-                                      : field->GetDeclaringClass()->GetIFields();
-  auto position = std::find_if(
-      iter_range.begin(), iter_range.end(), [&](const auto& f) { return &f == field; });
-  DCHECK(position != iter_range.end());
-  ret->SetArtFieldIndex<kTransactionActive>(std::distance(iter_range.begin(), position));
-  ret->SetOffset<kTransactionActive>(field->GetOffset().Int32Value());
-  return ret.Get();
+template<bool kTransactionActive, bool kCheckTransaction>
+inline void Field::SetDeclaringClass(ObjPtr<Class> c) {
+  SetFieldObject<kTransactionActive, kCheckTransaction>(DeclaringClassOffset(), c);
 }
 
-template<bool kTransactionActive>
-inline void Field::SetDeclaringClass(ObjPtr<mirror::Class> c) {
-  SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), c);
-}
-
-template<bool kTransactionActive>
-inline void Field::SetType(ObjPtr<mirror::Class> type) {
-  SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, type_), type);
+template<bool kTransactionActive, bool kCheckTransaction>
+inline void Field::SetType(ObjPtr<Class> type) {
+  SetFieldObject<kTransactionActive, kCheckTransaction>(TypeOffset(), type);
 }
 
 }  // namespace mirror
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
index e9669b8..7faa55c 100644
--- a/runtime/mirror/field.cc
+++ b/runtime/mirror/field.cc
@@ -45,14 +45,58 @@
 
 ArtField* Field::GetArtField() {
   ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
-  DCHECK_LT(GetArtFieldIndex(),
-            IsStatic() ? declaring_class->NumStaticFields() : declaring_class->NumInstanceFields());
   if (IsStatic()) {
+    DCHECK_LT(GetArtFieldIndex(), declaring_class->NumStaticFields());
     return declaring_class->GetStaticField(GetArtFieldIndex());
   } else {
+    DCHECK_LT(GetArtFieldIndex(), declaring_class->NumInstanceFields());
     return declaring_class->GetInstanceField(GetArtFieldIndex());
   }
 }
 
+ObjPtr<mirror::Field> Field::CreateFromArtField(Thread* self,
+                                                ArtField* field,
+                                                bool force_resolve) {
+  StackHandleScope<2> hs(self);
+  // Try to resolve type before allocating since this is a thread suspension point.
+  Handle<mirror::Class> type = hs.NewHandle(field->ResolveType());
+
+  if (type == nullptr) {
+    DCHECK(self->IsExceptionPending());
+    if (force_resolve) {
+      return nullptr;
+    } else {
+      // Can't resolve, clear the exception if it isn't OOME and continue with a null type.
+      mirror::Throwable* exception = self->GetException();
+      if (exception->GetClass()->DescriptorEquals("Ljava/lang/OutOfMemoryError;")) {
+        return nullptr;
+      }
+      self->ClearException();
+    }
+  }
+  auto ret = hs.NewHandle(ObjPtr<Field>::DownCast(GetClassRoot<Field>()->AllocObject(self)));
+  if (UNLIKELY(ret == nullptr)) {
+    self->AssertPendingOOMException();
+    return nullptr;
+  }
+  // We're initializing a newly allocated object, so we do not need to record that under
+  // a transaction. If the transaction is aborted, the whole object shall be unreachable.
+  ret->SetType</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(type.Get());
+  ret->SetDeclaringClass</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+      field->GetDeclaringClass());
+  ret->SetAccessFlags</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+      field->GetAccessFlags());
+  auto iter_range = field->IsStatic() ? field->GetDeclaringClass()->GetSFields()
+                                      : field->GetDeclaringClass()->GetIFields();
+  auto position = std::find_if(
+      iter_range.begin(), iter_range.end(), [&](const auto& f) { return &f == field; });
+  DCHECK(position != iter_range.end());
+  ret->SetArtFieldIndex</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+      std::distance(iter_range.begin(), position));
+  ret->SetOffset</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+      field->GetOffset().Int32Value());
+  return ret.Get();
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
index dd5ee76..bbae8ce 100644
--- a/runtime/mirror/field.h
+++ b/runtime/mirror/field.h
@@ -39,15 +39,11 @@
 // C++ mirror of java.lang.reflect.Field.
 class MANAGED Field : public AccessibleObject {
  public:
+  MIRROR_CLASS("Ljava/lang/reflect/Field;");
+
   ALWAYS_INLINE uint32_t GetArtFieldIndex() REQUIRES_SHARED(Locks::mutator_lock_) {
     return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, art_field_index_));
   }
-  // Public for use by class redefinition code.
-  template<bool kTransactionActive>
-  void SetArtFieldIndex(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_) {
-    SetField32<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, art_field_index_), idx);
-  }
-
 
   ObjPtr<mirror::Class> GetDeclaringClass() REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -77,7 +73,6 @@
 
   ArtField* GetArtField() REQUIRES_SHARED(Locks::mutator_lock_);
 
-  template <PointerSize kPointerSize, bool kTransactionActive = false>
   static ObjPtr<mirror::Field> CreateFromArtField(Thread* self,
                                                   ArtField* field,
                                                   bool force_resolve)
@@ -90,7 +85,7 @@
 
  private:
   // Padding required for matching alignment with the Java peer.
-  uint8_t padding_[2];
+  uint8_t padding_[3];
 
   HeapReference<mirror::Class> declaring_class_;
   HeapReference<mirror::Class> type_;
@@ -98,20 +93,45 @@
   int32_t art_field_index_;
   int32_t offset_;
 
-  template<bool kTransactionActive>
-  void SetDeclaringClass(ObjPtr<mirror::Class> c) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  template<bool kTransactionActive>
-  void SetType(ObjPtr<mirror::Class> type) REQUIRES_SHARED(Locks::mutator_lock_);
-
-  template<bool kTransactionActive>
-  void SetAccessFlags(uint32_t flags) REQUIRES_SHARED(Locks::mutator_lock_) {
-    SetField32<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), flags);
+  static constexpr MemberOffset DeclaringClassOffset() {
+    return OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_);
   }
 
-  template<bool kTransactionActive>
+  static constexpr MemberOffset TypeOffset() {
+    return OFFSET_OF_OBJECT_MEMBER(Field, type_);
+  }
+
+  static constexpr MemberOffset AccessFlagsOffset() {
+    return OFFSET_OF_OBJECT_MEMBER(Field, access_flags_);
+  }
+
+  static constexpr MemberOffset ArtFieldIndexOffset() {
+    return OFFSET_OF_OBJECT_MEMBER(Field, art_field_index_);
+  }
+
+  static constexpr MemberOffset OffsetOffset() {
+    return OFFSET_OF_OBJECT_MEMBER(Field, offset_);
+  }
+
+  template<bool kTransactionActive, bool kCheckTransaction = true>
+  void SetDeclaringClass(ObjPtr<Class> c) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive, bool kCheckTransaction = true>
+  void SetType(ObjPtr<Class> type) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive, bool kCheckTransaction = true>
+  void SetAccessFlags(uint32_t access_flags) REQUIRES_SHARED(Locks::mutator_lock_) {
+    SetField32<kTransactionActive, kCheckTransaction>(AccessFlagsOffset(), access_flags);
+  }
+
+  template<bool kTransactionActive, bool kCheckTransaction = true>
+  void SetArtFieldIndex(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_) {
+    SetField32<kTransactionActive, kCheckTransaction>(ArtFieldIndexOffset(), idx);
+  }
+
+  template<bool kTransactionActive, bool kCheckTransaction = true>
   void SetOffset(uint32_t offset) REQUIRES_SHARED(Locks::mutator_lock_) {
-    SetField32<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, offset_), offset);
+    SetField32<kTransactionActive, kCheckTransaction>(OffsetOffset(), offset);
   }
 
   friend struct art::FieldOffsets;  // for verifying offset information
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
index 20a6979..f83f03c 100644
--- a/runtime/mirror/method.cc
+++ b/runtime/mirror/method.cc
@@ -17,7 +17,7 @@
 #include "method.h"
 
 #include "art_method.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "mirror/class-alloc-inl.h"
 #include "mirror/object-inl.h"
 #include "obj_ptr-inl.h"
@@ -25,43 +25,35 @@
 namespace art {
 namespace mirror {
 
-template <PointerSize kPointerSize, bool kTransactionActive>
+template <PointerSize kPointerSize>
 ObjPtr<Method> Method::CreateFromArtMethod(Thread* self, ArtMethod* method) {
   DCHECK(!method->IsConstructor()) << method->PrettyMethod();
   ObjPtr<Method> ret = ObjPtr<Method>::DownCast(GetClassRoot<Method>()->AllocObject(self));
   if (LIKELY(ret != nullptr)) {
-    ret->Executable::CreateFromArtMethod<kPointerSize, kTransactionActive>(method);
+    ret->InitializeFromArtMethod<kPointerSize>(method);
   }
   return ret;
 }
 
-template ObjPtr<Method> Method::CreateFromArtMethod<PointerSize::k32, false>(
+template ObjPtr<Method> Method::CreateFromArtMethod<PointerSize::k32>(
     Thread* self, ArtMethod* method);
-template ObjPtr<Method> Method::CreateFromArtMethod<PointerSize::k32, true>(
-    Thread* self, ArtMethod* method);
-template ObjPtr<Method> Method::CreateFromArtMethod<PointerSize::k64, false>(
-    Thread* self, ArtMethod* method);
-template ObjPtr<Method> Method::CreateFromArtMethod<PointerSize::k64, true>(
+template ObjPtr<Method> Method::CreateFromArtMethod<PointerSize::k64>(
     Thread* self, ArtMethod* method);
 
-template <PointerSize kPointerSize, bool kTransactionActive>
+template <PointerSize kPointerSize>
 ObjPtr<Constructor> Constructor::CreateFromArtMethod(Thread* self, ArtMethod* method) {
   DCHECK(method->IsConstructor()) << method->PrettyMethod();
   ObjPtr<Constructor> ret =
       ObjPtr<Constructor>::DownCast(GetClassRoot<Constructor>()->AllocObject(self));
   if (LIKELY(ret != nullptr)) {
-    ret->Executable::CreateFromArtMethod<kPointerSize, kTransactionActive>(method);
+    ret->InitializeFromArtMethod<kPointerSize>(method);
   }
   return ret;
 }
 
-template ObjPtr<Constructor> Constructor::CreateFromArtMethod<PointerSize::k32, false>(
+template ObjPtr<Constructor> Constructor::CreateFromArtMethod<PointerSize::k32>(
     Thread* self, ArtMethod* method);
-template ObjPtr<Constructor> Constructor::CreateFromArtMethod<PointerSize::k32, true>(
-    Thread* self, ArtMethod* method);
-template ObjPtr<Constructor> Constructor::CreateFromArtMethod<PointerSize::k64, false>(
-    Thread* self, ArtMethod* method);
-template ObjPtr<Constructor> Constructor::CreateFromArtMethod<PointerSize::k64, true>(
+template ObjPtr<Constructor> Constructor::CreateFromArtMethod<PointerSize::k64>(
     Thread* self, ArtMethod* method);
 
 }  // namespace mirror
diff --git a/runtime/mirror/method.h b/runtime/mirror/method.h
index a73cd45..4b8dcff 100644
--- a/runtime/mirror/method.h
+++ b/runtime/mirror/method.h
@@ -30,7 +30,9 @@
 // C++ mirror of java.lang.reflect.Method.
 class MANAGED Method : public Executable {
  public:
-  template <PointerSize kPointerSize, bool kTransactionActive>
+  MIRROR_CLASS("Ljava/lang/reflect/Method;");
+
+  template <PointerSize kPointerSize>
   static ObjPtr<Method> CreateFromArtMethod(Thread* self, ArtMethod* method)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
@@ -41,7 +43,9 @@
 // C++ mirror of java.lang.reflect.Constructor.
 class MANAGED Constructor: public Executable {
  public:
-  template <PointerSize kPointerSize, bool kTransactionActive>
+  MIRROR_CLASS("Ljava/lang/reflect/Constructor;");
+
+  template <PointerSize kPointerSize>
   static ObjPtr<Constructor> CreateFromArtMethod(Thread* self, ArtMethod* method)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
diff --git a/runtime/mirror/method_handle_impl.cc b/runtime/mirror/method_handle_impl.cc
index dd25fc9..4f1a18b 100644
--- a/runtime/mirror/method_handle_impl.cc
+++ b/runtime/mirror/method_handle_impl.cc
@@ -17,7 +17,7 @@
 #include "method_handle_impl-inl.h"
 
 #include "class-alloc-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 
 namespace art {
 namespace mirror {
diff --git a/runtime/mirror/method_handle_impl.h b/runtime/mirror/method_handle_impl.h
index a0f02f6..6ba6e25 100644
--- a/runtime/mirror/method_handle_impl.h
+++ b/runtime/mirror/method_handle_impl.h
@@ -35,6 +35,8 @@
 // C++ mirror of java.lang.invoke.MethodHandle
 class MANAGED MethodHandle : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/invoke/MethodHandle;");
+
   // Defines the behaviour of a given method handle. The behaviour
   // of a handle of a given kind is identical to the dex bytecode behaviour
   // of the equivalent instruction.
@@ -125,6 +127,8 @@
 // C++ mirror of java.lang.invoke.MethodHandleImpl
 class MANAGED MethodHandleImpl : public MethodHandle {
  public:
+  MIRROR_CLASS("Ljava/lang/invoke/MethodHandleImpl;");
+
   static ObjPtr<mirror::MethodHandleImpl> Create(Thread* const self,
                                                  uintptr_t art_field_or_method,
                                                  MethodHandle::Kind kind,
diff --git a/runtime/mirror/method_handles_lookup.cc b/runtime/mirror/method_handles_lookup.cc
index e0e7b06..e9c41f9 100644
--- a/runtime/mirror/method_handles_lookup.cc
+++ b/runtime/mirror/method_handles_lookup.cc
@@ -17,7 +17,7 @@
 #include "method_handles_lookup.h"
 
 #include "class-alloc-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/modifiers.h"
 #include "handle_scope.h"
 #include "jni/jni_internal.h"
diff --git a/runtime/mirror/method_handles_lookup.h b/runtime/mirror/method_handles_lookup.h
index d4dbf83..3ed150a 100644
--- a/runtime/mirror/method_handles_lookup.h
+++ b/runtime/mirror/method_handles_lookup.h
@@ -35,6 +35,8 @@
 // C++ mirror of java.lang.invoke.MethodHandles.Lookup
 class MANAGED MethodHandlesLookup : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/invoke/MethodHandles$Lookup;");
+
   static ObjPtr<mirror::MethodHandlesLookup> Create(Thread* const self, Handle<Class> lookup_class)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
diff --git a/runtime/mirror/method_type.cc b/runtime/mirror/method_type.cc
index 1d88d85..821de7b 100644
--- a/runtime/mirror/method_type.cc
+++ b/runtime/mirror/method_type.cc
@@ -17,7 +17,7 @@
 #include "method_type-inl.h"
 
 #include "class-alloc-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "method_handles.h"
 #include "obj_ptr-inl.h"
 #include "object_array-alloc-inl.h"
diff --git a/runtime/mirror/method_type.h b/runtime/mirror/method_type.h
index 13edf29..872c07b 100644
--- a/runtime/mirror/method_type.h
+++ b/runtime/mirror/method_type.h
@@ -30,6 +30,8 @@
 // C++ mirror of java.lang.invoke.MethodType
 class MANAGED MethodType : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/invoke/MethodType;");
+
   static ObjPtr<MethodType> Create(Thread* const self,
                                    Handle<Class> return_type,
                                    Handle<ObjectArray<Class>> param_types)
diff --git a/runtime/mirror/method_type_test.cc b/runtime/mirror/method_type_test.cc
index 4e9ba51..742960b 100644
--- a/runtime/mirror/method_type_test.cc
+++ b/runtime/mirror/method_type_test.cc
@@ -22,7 +22,7 @@
 #include "class-inl.h"
 #include "class_linker-inl.h"
 #include "class_loader.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_runtime_test.h"
 #include "handle_scope-inl.h"
 #include "object_array-alloc-inl.h"
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 2eff560..a3fc552 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -76,6 +76,8 @@
 // C++ mirror of java.lang.Object
 class MANAGED LOCKABLE Object {
  public:
+  MIRROR_CLASS("Ljava/lang/Object;");
+
   // The number of vtable entries in java.lang.Object.
   static constexpr size_t kVTableLength = 11;
 
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index e58787c..a20c86b 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -34,6 +34,8 @@
 template<class T>
 class MANAGED ObjectArray: public Array {
  public:
+  MIRROR_CLASS("[Ljava/lang/Object;");
+
   // The size of Object[].class.
   static uint32_t ClassSize(PointerSize pointer_size) {
     return Array::ClassSize(pointer_size);
diff --git a/runtime/mirror/object_reference.h b/runtime/mirror/object_reference.h
index f01bcbd..adeb29c 100644
--- a/runtime/mirror/object_reference.h
+++ b/runtime/mirror/object_reference.h
@@ -17,6 +17,9 @@
 #ifndef ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
 #define ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
 
+#include <array>
+#include <string_view>
+
 #include "base/atomic.h"
 #include "base/locks.h"  // For Locks::mutator_lock_.
 #include "heap_poisoning.h"
@@ -31,6 +34,59 @@
 // Classes shared with the managed side of the world need to be packed so that they don't have
 // extra platform specific padding.
 #define MANAGED PACKED(4)
+#define MIRROR_CLASS(desc) \
+  static_assert(::art::mirror::IsMirroredDescriptor(desc), \
+                desc " is not a known mirror class. Please update" \
+                " IsMirroredDescriptor to include it!")
+
+constexpr bool IsMirroredDescriptor(std::string_view desc) {
+  if (desc[0] != 'L') {
+    // All primitives and arrays are mirrored
+    return true;
+  }
+#define MIRROR_DESCRIPTORS(vis)                       \
+    vis("Ljava/lang/Class;")                          \
+    vis("Ljava/lang/ClassLoader;")                    \
+    vis("Ljava/lang/ClassNotFoundException;")         \
+    vis("Ljava/lang/DexCache;")                       \
+    vis("Ljava/lang/Object;")                         \
+    vis("Ljava/lang/StackTraceElement;")              \
+    vis("Ljava/lang/String;")                         \
+    vis("Ljava/lang/Throwable;")                      \
+    vis("Ljava/lang/invoke/ArrayElementVarHandle;")   \
+    vis("Ljava/lang/invoke/ByteArrayViewVarHandle;")  \
+    vis("Ljava/lang/invoke/ByteBufferViewVarHandle;") \
+    vis("Ljava/lang/invoke/CallSite;")                \
+    vis("Ljava/lang/invoke/FieldVarHandle;")          \
+    vis("Ljava/lang/invoke/MethodHandle;")            \
+    vis("Ljava/lang/invoke/MethodHandleImpl;")        \
+    vis("Ljava/lang/invoke/MethodHandles$Lookup;")    \
+    vis("Ljava/lang/invoke/MethodType;")              \
+    vis("Ljava/lang/invoke/VarHandle;")               \
+    vis("Ljava/lang/ref/FinalizerReference;")         \
+    vis("Ljava/lang/ref/Reference;")                  \
+    vis("Ljava/lang/reflect/AccessibleObject;")       \
+    vis("Ljava/lang/reflect/Constructor;")            \
+    vis("Ljava/lang/reflect/Executable;")             \
+    vis("Ljava/lang/reflect/Field;")                  \
+    vis("Ljava/lang/reflect/Method;")                 \
+    vis("Ljava/lang/reflect/Proxy;")                  \
+    vis("Ldalvik/system/ClassExt;")                   \
+    vis("Ldalvik/system/EmulatedStackFrame;")
+  // TODO: Once we are C++ 20 we can just have a constexpr array and std::find.
+  // constexpr std::array<std::string_view, 28> kMirrorTypes{
+  //    // Fill in
+  // };
+  // return std::find(kMirrorTypes.begin(), kMirrorTypes.end(), desc) != kMirrorTypes.end();
+#define CHECK_DESCRIPTOR(descriptor)          \
+  if (std::string_view(descriptor) == desc) { \
+    return true;                              \
+  }
+  MIRROR_DESCRIPTORS(CHECK_DESCRIPTOR)
+#undef CHECK_DESCRIPTOR
+  return false;
+#undef MIRROR_DESCRIPTORS
+}
 
 template<bool kPoisonReferences, class MirrorType>
 class PtrCompression {
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 8ef7025..80ed832 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -30,7 +30,7 @@
 #include "class-inl.h"
 #include "class_linker-inl.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_runtime_test.h"
 #include "dex/dex_file.h"
 #include "entrypoints/entrypoint_utils-inl.h"
diff --git a/runtime/mirror/proxy.h b/runtime/mirror/proxy.h
index 7775de3..3291669 100644
--- a/runtime/mirror/proxy.h
+++ b/runtime/mirror/proxy.h
@@ -28,6 +28,8 @@
 // C++ mirror of java.lang.reflect.Proxy.
 class MANAGED Proxy final : public Object {
  private:
+  MIRROR_CLASS("Ljava/lang/reflect/Proxy;");
+
   HeapReference<Object> h_;
 
   friend struct art::ProxyOffsets;  // for verifying offset information
diff --git a/runtime/mirror/reference.h b/runtime/mirror/reference.h
index 9ace4f7..ef6d273 100644
--- a/runtime/mirror/reference.h
+++ b/runtime/mirror/reference.h
@@ -41,6 +41,8 @@
 // C++ mirror of java.lang.ref.Reference
 class MANAGED Reference : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/ref/Reference;");
+
   // Size of java.lang.ref.Reference.class.
   static uint32_t ClassSize(PointerSize pointer_size);
 
@@ -117,6 +119,8 @@
 // C++ mirror of java.lang.ref.FinalizerReference
 class MANAGED FinalizerReference : public Reference {
  public:
+  MIRROR_CLASS("Ljava/lang/ref/FinalizerReference;");
+
   static MemberOffset ZombieOffset() {
     return OFFSET_OF_OBJECT_MEMBER(FinalizerReference, zombie_);
   }
diff --git a/runtime/mirror/stack_trace_element.cc b/runtime/mirror/stack_trace_element.cc
index 2a272d3..7fc6c09 100644
--- a/runtime/mirror/stack_trace_element.cc
+++ b/runtime/mirror/stack_trace_element.cc
@@ -18,7 +18,7 @@
 
 #include "class-alloc-inl.h"
 #include "class.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "gc/accounting/card_table-inl.h"
 #include "handle_scope-inl.h"
 #include "object-inl.h"
diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h
index 67eedbc..c07e63d 100644
--- a/runtime/mirror/stack_trace_element.h
+++ b/runtime/mirror/stack_trace_element.h
@@ -29,6 +29,8 @@
 // C++ mirror of java.lang.StackTraceElement
 class MANAGED StackTraceElement final : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/StackTraceElement;");
+
   ObjPtr<String> GetDeclaringClass() REQUIRES_SHARED(Locks::mutator_lock_);
 
   ObjPtr<String> GetMethodName() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/string-alloc-inl.h b/runtime/mirror/string-alloc-inl.h
index e2b0805..5f3abd7 100644
--- a/runtime/mirror/string-alloc-inl.h
+++ b/runtime/mirror/string-alloc-inl.h
@@ -23,7 +23,7 @@
 #include "array.h"
 #include "base/bit_utils.h"
 #include "class.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "gc/allocator_type.h"
 #include "gc/heap-inl.h"
 #include "obj_ptr.h"
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index f04a8aa..dd28036 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -84,6 +84,14 @@
   return result;
 }
 
+inline int32_t String::GetUtfLength() {
+  if (IsCompressed()) {
+    return GetLength();
+  } else {
+    return CountUtf8Bytes(GetValue(), GetLength());
+  }
+}
+
 template<typename MemoryType>
 inline bool String::AllASCII(const MemoryType* chars, const int length) {
   static_assert(std::is_unsigned<MemoryType>::value, "Expecting unsigned MemoryType");
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index 0356080..0ce45b8 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -59,14 +59,6 @@
   return hash_code;
 }
 
-int32_t String::GetUtfLength() {
-  if (IsCompressed()) {
-    return GetLength();
-  } else {
-    return CountUtf8Bytes(GetValue(), GetLength());
-  }
-}
-
 inline bool String::AllASCIIExcept(const uint16_t* chars, int32_t length, uint16_t non_ascii) {
   DCHECK(!IsASCII(non_ascii));
   for (int32_t i = 0; i < length; ++i) {
@@ -88,74 +80,75 @@
       (src->IsCompressed() || (!IsASCII(old_c) && AllASCIIExcept(src->value_, length, old_c)));
   gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
   const int32_t length_with_flag = String::GetFlaggedCount(length, compressible);
-  SetStringCountVisitor visitor(length_with_flag);
-  ObjPtr<String> string = Alloc(self, length_with_flag, allocator_type, visitor);
-  if (UNLIKELY(string == nullptr)) {
-    return nullptr;
-  }
-  if (compressible) {
-    auto replace = [old_c, new_c](uint16_t c) {
-      return dchecked_integral_cast<uint8_t>((old_c != c) ? c : new_c);
-    };
-    uint8_t* out = string->value_compressed_;
-    if (LIKELY(src->IsCompressed())) {  // LIKELY(compressible == src->IsCompressed())
-      std::transform(src->value_compressed_, src->value_compressed_ + length, out, replace);
+
+  auto visitor = [=](ObjPtr<Object> obj, size_t usable_size) REQUIRES_SHARED(Locks::mutator_lock_) {
+    SetStringCountVisitor set_string_count_visitor(length_with_flag);
+    set_string_count_visitor(obj, usable_size);
+    ObjPtr<String> new_string = obj->AsString();
+    if (compressible) {
+      auto replace = [old_c, new_c](uint16_t c) {
+        return dchecked_integral_cast<uint8_t>((old_c != c) ? c : new_c);
+      };
+      uint8_t* out = new_string->value_compressed_;
+      if (LIKELY(src->IsCompressed())) {  // LIKELY(compressible == src->IsCompressed())
+        std::transform(src->value_compressed_, src->value_compressed_ + length, out, replace);
+      } else {
+        std::transform(src->value_, src->value_ + length, out, replace);
+      }
+      DCHECK(kUseStringCompression && AllASCII(out, length));
     } else {
-      std::transform(src->value_, src->value_ + length, out, replace);
+      auto replace = [old_c, new_c](uint16_t c) {
+        return (old_c != c) ? c : new_c;
+      };
+      uint16_t* out = new_string->value_;
+      if (UNLIKELY(src->IsCompressed())) {  // LIKELY(compressible == src->IsCompressed())
+        std::transform(src->value_compressed_, src->value_compressed_ + length, out, replace);
+      } else {
+        std::transform(src->value_, src->value_ + length, out, replace);
+      }
+      DCHECK(!kUseStringCompression || !AllASCII(out, length));
     }
-    DCHECK(kUseStringCompression && AllASCII(out, length));
-  } else {
-    auto replace = [old_c, new_c](uint16_t c) {
-      return (old_c != c) ? c : new_c;
-    };
-    uint16_t* out = string->value_;
-    if (UNLIKELY(src->IsCompressed())) {  // LIKELY(compressible == src->IsCompressed())
-      std::transform(src->value_compressed_, src->value_compressed_ + length, out, replace);
-    } else {
-      std::transform(src->value_, src->value_ + length, out, replace);
-    }
-    DCHECK(!kUseStringCompression || !AllASCII(out, length));
-  }
-  return string;
+  };
+  return Alloc(self, length_with_flag, allocator_type, visitor);
 }
 
-ObjPtr<String> String::AllocFromStrings(Thread* self,
-                                        Handle<String> string,
-                                        Handle<String> string2) {
-  int32_t length = string->GetLength();
-  int32_t length2 = string2->GetLength();
+ObjPtr<String> String::DoConcat(Thread* self, Handle<String> h_this, Handle<String> h_arg) {
+  int32_t length_this = h_this->GetLength();
+  int32_t length_arg = h_arg->GetLength();
   gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
-  const bool compressible = kUseStringCompression &&
-      (string->IsCompressed() && string2->IsCompressed());
-  const int32_t length_with_flag = String::GetFlaggedCount(length + length2, compressible);
+  const bool compressible =
+      kUseStringCompression && (h_this->IsCompressed() && h_arg->IsCompressed());
+  const int32_t length_with_flag = String::GetFlaggedCount(length_this + length_arg, compressible);
 
-  SetStringCountVisitor visitor(length_with_flag);
-  ObjPtr<String> new_string = Alloc(self, length_with_flag, allocator_type, visitor);
-  if (UNLIKELY(new_string == nullptr)) {
-    return nullptr;
-  }
-  if (compressible) {
-    uint8_t* new_value = new_string->GetValueCompressed();
-    memcpy(new_value, string->GetValueCompressed(), length * sizeof(uint8_t));
-    memcpy(new_value + length, string2->GetValueCompressed(), length2 * sizeof(uint8_t));
-  } else {
-    uint16_t* new_value = new_string->GetValue();
-    if (string->IsCompressed()) {
-      for (int i = 0; i < length; ++i) {
-        new_value[i] = string->CharAt(i);
-      }
+  auto visitor = [=](ObjPtr<Object> obj, size_t usable_size) REQUIRES_SHARED(Locks::mutator_lock_) {
+    SetStringCountVisitor set_string_count_visitor(length_with_flag);
+    set_string_count_visitor(obj, usable_size);
+    ObjPtr<String> new_string = obj->AsString();
+    if (compressible) {
+      uint8_t* new_value = new_string->GetValueCompressed();
+      memcpy(new_value, h_this->GetValueCompressed(), length_this * sizeof(uint8_t));
+      memcpy(new_value + length_this, h_arg->GetValueCompressed(), length_arg * sizeof(uint8_t));
     } else {
-      memcpy(new_value, string->GetValue(), length * sizeof(uint16_t));
-    }
-    if (string2->IsCompressed()) {
-      for (int i = 0; i < length2; ++i) {
-        new_value[i+length] = string2->CharAt(i);
+      uint16_t* new_value = new_string->GetValue();
+      if (h_this->IsCompressed()) {
+        const uint8_t* value_this = h_this->GetValueCompressed();
+        for (int i = 0; i < length_this; ++i) {
+          new_value[i] = value_this[i];
+        }
+      } else {
+        memcpy(new_value, h_this->GetValue(), length_this * sizeof(uint16_t));
       }
-    } else {
-      memcpy(new_value + length, string2->GetValue(), length2 * sizeof(uint16_t));
+      if (h_arg->IsCompressed()) {
+        const uint8_t* value_arg = h_arg->GetValueCompressed();
+        for (int i = 0; i < length_arg; ++i) {
+          new_value[i + length_this] = value_arg[i];
+        }
+      } else {
+        memcpy(new_value + length_this, h_arg->GetValue(), length_arg * sizeof(uint16_t));
+      }
     }
-  }
-  return new_string;
+  };
+  return Alloc(self, length_with_flag, allocator_type, visitor);
 }
 
 ObjPtr<String> String::AllocFromUtf16(Thread* self,
@@ -166,20 +159,21 @@
   const bool compressible = kUseStringCompression &&
                             String::AllASCII<uint16_t>(utf16_data_in, utf16_length);
   int32_t length_with_flag = String::GetFlaggedCount(utf16_length, compressible);
-  SetStringCountVisitor visitor(length_with_flag);
-  ObjPtr<String> string = Alloc(self, length_with_flag, allocator_type, visitor);
-  if (UNLIKELY(string == nullptr)) {
-    return nullptr;
-  }
-  if (compressible) {
-    for (int i = 0; i < utf16_length; ++i) {
-      string->GetValueCompressed()[i] = static_cast<uint8_t>(utf16_data_in[i]);
+
+  auto visitor = [=](ObjPtr<Object> obj, size_t usable_size) REQUIRES_SHARED(Locks::mutator_lock_) {
+    SetStringCountVisitor set_string_count_visitor(length_with_flag);
+    set_string_count_visitor(obj, usable_size);
+    ObjPtr<String> new_string = obj->AsString();
+    if (compressible) {
+      uint8_t* value = new_string->GetValueCompressed();
+      for (int i = 0; i < utf16_length; ++i) {
+        value[i] = static_cast<uint8_t>(utf16_data_in[i]);
+      }
+    } else {
+      memcpy(new_string->GetValue(), utf16_data_in, utf16_length * sizeof(uint16_t));
     }
-  } else {
-    uint16_t* array = string->GetValue();
-    memcpy(array, utf16_data_in, utf16_length * sizeof(uint16_t));
-  }
-  return string;
+  };
+  return Alloc(self, length_with_flag, allocator_type, visitor);
 }
 
 ObjPtr<String> String::AllocFromModifiedUtf8(Thread* self, const char* utf) {
@@ -201,19 +195,20 @@
                                              int32_t utf8_length) {
   gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
   const bool compressible = kUseStringCompression && (utf16_length == utf8_length);
-  const int32_t utf16_length_with_flag = String::GetFlaggedCount(utf16_length, compressible);
-  SetStringCountVisitor visitor(utf16_length_with_flag);
-  ObjPtr<String> string = Alloc(self, utf16_length_with_flag, allocator_type, visitor);
-  if (UNLIKELY(string == nullptr)) {
-    return nullptr;
-  }
-  if (compressible) {
-    memcpy(string->GetValueCompressed(), utf8_data_in, utf16_length * sizeof(uint8_t));
-  } else {
-    uint16_t* utf16_data_out = string->GetValue();
-    ConvertModifiedUtf8ToUtf16(utf16_data_out, utf16_length, utf8_data_in, utf8_length);
-  }
-  return string;
+  const int32_t length_with_flag = String::GetFlaggedCount(utf16_length, compressible);
+
+  auto visitor = [=](ObjPtr<Object> obj, size_t usable_size) REQUIRES_SHARED(Locks::mutator_lock_) {
+    SetStringCountVisitor set_string_count_visitor(length_with_flag);
+    set_string_count_visitor(obj, usable_size);
+    ObjPtr<String> new_string = obj->AsString();
+    if (compressible) {
+      memcpy(new_string->GetValueCompressed(), utf8_data_in, utf16_length * sizeof(uint8_t));
+    } else {
+      uint16_t* utf16_data_out = new_string->GetValue();
+      ConvertModifiedUtf8ToUtf16(utf16_data_out, utf16_length, utf8_data_in, utf8_length);
+    }
+  };
+  return Alloc(self, length_with_flag, allocator_type, visitor);
 }
 
 bool String::Equals(ObjPtr<String> that) {
@@ -223,23 +218,27 @@
   } else if (that == nullptr) {
     // Null isn't an instanceof anything
     return false;
-  } else if (this->GetLength() != that->GetLength()) {
-    // Quick length inequality test
+  } else if (this->GetCount() != that->GetCount()) {
+    // Quick length and compression inequality test
     return false;
   } else {
     // Note: don't short circuit on hash code as we're presumably here as the
     // hash code was already equal
-    for (int32_t i = 0; i < that->GetLength(); ++i) {
-      if (this->CharAt(i) != that->CharAt(i)) {
-        return false;
-      }
+    if (this->IsCompressed()) {
+      return memcmp(this->GetValueCompressed(), that->GetValueCompressed(), this->GetLength()) == 0;
+    } else {
+      return memcmp(this->GetValue(), that->GetValue(), sizeof(uint16_t) * this->GetLength()) == 0;
     }
-    return true;
   }
 }
 
 bool String::Equals(const char* modified_utf8) {
   const int32_t length = GetLength();
+  if (IsCompressed()) {
+    return strlen(modified_utf8) == dchecked_integral_cast<uint32_t>(length) &&
+           memcmp(modified_utf8, GetValueCompressed(), length) == 0;
+  }
+  const uint16_t* value = GetValue();
   int32_t i = 0;
   while (i < length) {
     const uint32_t ch = GetUtf16FromUtf8(&modified_utf8);
@@ -247,7 +246,7 @@
       return false;
     }
 
-    if (GetLeadingUtf16Char(ch) != CharAt(i++)) {
+    if (GetLeadingUtf16Char(ch) != value[i++]) {
       return false;
     }
 
@@ -257,7 +256,7 @@
         return false;
       }
 
-      if (CharAt(i++) != trailing) {
+      if (value[i++] != trailing) {
         return false;
       }
     }
@@ -267,17 +266,14 @@
 
 // Create a modified UTF-8 encoded std::string from a java/lang/String object.
 std::string String::ToModifiedUtf8() {
-  size_t byte_count = GetUtfLength();
-  std::string result(byte_count, static_cast<char>(0));
   if (IsCompressed()) {
-    for (size_t i = 0; i < byte_count; ++i) {
-      result[i] = static_cast<char>(CharAt(i));
-    }
+    return std::string(reinterpret_cast<const char*>(GetValueCompressed()), GetLength());
   } else {
-    const uint16_t* chars = GetValue();
-    ConvertUtf16ToModifiedUtf8(&result[0], byte_count, chars, GetLength());
+    size_t byte_count = GetUtfLength();
+    std::string result(byte_count, static_cast<char>(0));
+    ConvertUtf16ToModifiedUtf8(&result[0], byte_count, GetValue(), GetLength());
+    return result;
   }
-  return result;
 }
 
 int32_t String::CompareTo(ObjPtr<String> rhs) {
@@ -328,8 +324,10 @@
   if (result != nullptr) {
     if (h_this->IsCompressed()) {
       int32_t length = h_this->GetLength();
+      const uint8_t* src = h_this->GetValueCompressed();
+      uint16_t* dest = result->GetData();
       for (int i = 0; i < length; ++i) {
-        result->GetData()[i] = h_this->CharAt(i);
+        dest[i] = src[i];
       }
     } else {
       memcpy(result->GetData(), h_this->GetValue(), h_this->GetLength() * sizeof(uint16_t));
@@ -342,13 +340,16 @@
 
 void String::GetChars(int32_t start, int32_t end, Handle<CharArray> array, int32_t index) {
   uint16_t* data = array->GetData() + index;
+  DCHECK_LE(start, end);
+  int32_t length = end - start;
   if (IsCompressed()) {
-    for (int i = start; i < end; ++i) {
-      data[i-start] = CharAt(i);
+    const uint8_t* value = GetValueCompressed() + start;
+    for (int i = 0; i < length; ++i) {
+      data[i] = value[i];
     }
   } else {
     uint16_t* value = GetValue() + start;
-    memcpy(data, value, (end - start) * sizeof(uint16_t));
+    memcpy(data, value, length * sizeof(uint16_t));
   }
 }
 
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 0e3c500..338a1af 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -46,6 +46,8 @@
 // C++ mirror of java.lang.String
 class MANAGED String final : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/String;");
+
   // Size of java.lang.String.class.
   static uint32_t ClassSize(PointerSize pointer_size);
 
@@ -148,9 +150,7 @@
                                                        gc::AllocatorType allocator_type)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
-  static ObjPtr<String> AllocFromStrings(Thread* self,
-                                         Handle<String> string,
-                                         Handle<String> string2)
+  static ObjPtr<String> DoConcat(Thread* self, Handle<String> h_this, Handle<String> h_arg)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
   static ObjPtr<String> AllocFromUtf16(Thread* self,
@@ -237,13 +237,13 @@
   std::string PrettyStringDescriptor()
       REQUIRES_SHARED(Locks::mutator_lock_);
 
- private:
   static constexpr bool IsASCII(uint16_t c) {
     // Valid ASCII characters are in range 1..0x7f. Zero is not considered ASCII
     // because it would complicate the detection of ASCII strings in Modified-UTF8.
     return (c - 1u) < 0x7fu;
   }
 
+ private:
   static bool AllASCIIExcept(const uint16_t* chars, int32_t length, uint16_t non_ascii);
 
   void SetHashCode(int32_t new_hash_code) REQUIRES_SHARED(Locks::mutator_lock_) {
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index faa605c..a03277c 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -22,7 +22,7 @@
 #include "base/enums.h"
 #include "base/utils.h"
 #include "class-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
 #include "obj_ptr-inl.h"
diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h
index 68c176a..50db34c 100644
--- a/runtime/mirror/throwable.h
+++ b/runtime/mirror/throwable.h
@@ -31,6 +31,8 @@
 // C++ mirror of java.lang.Throwable
 class MANAGED Throwable : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/Throwable;");
+
   void SetDetailMessage(ObjPtr<String> new_detail_message) REQUIRES_SHARED(Locks::mutator_lock_);
 
   ObjPtr<String> GetDetailMessage() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/var_handle.cc b/runtime/mirror/var_handle.cc
index 6d5ff2c..7970c62 100644
--- a/runtime/mirror/var_handle.cc
+++ b/runtime/mirror/var_handle.cc
@@ -21,7 +21,7 @@
 #include "base/casts.h"
 #include "class-inl.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "intrinsics_enum.h"
 #include "jni/jni_internal.h"
 #include "jvalue-inl.h"
@@ -92,102 +92,9 @@
   { "weakCompareAndSetRelease", VarHandle::AccessMode::kWeakCompareAndSetRelease },
 };
 
-// Enumeration for describing the parameter and return types of an AccessMode.
-enum class AccessModeTemplate : uint32_t {
-  kGet,                 // T Op(C0..CN)
-  kSet,                 // void Op(C0..CN, T)
-  kCompareAndSet,       // boolean Op(C0..CN, T, T)
-  kCompareAndExchange,  // T Op(C0..CN, T, T)
-  kGetAndUpdate,        // T Op(C0..CN, T)
-};
-
-// Look up the AccessModeTemplate for a given VarHandle
-// AccessMode. This simplifies finding the correct signature for a
-// VarHandle accessor method.
-AccessModeTemplate GetAccessModeTemplate(VarHandle::AccessMode access_mode) {
-  switch (access_mode) {
-    case VarHandle::AccessMode::kGet:
-      return AccessModeTemplate::kGet;
-    case VarHandle::AccessMode::kSet:
-      return AccessModeTemplate::kSet;
-    case VarHandle::AccessMode::kGetVolatile:
-      return AccessModeTemplate::kGet;
-    case VarHandle::AccessMode::kSetVolatile:
-      return AccessModeTemplate::kSet;
-    case VarHandle::AccessMode::kGetAcquire:
-      return AccessModeTemplate::kGet;
-    case VarHandle::AccessMode::kSetRelease:
-      return AccessModeTemplate::kSet;
-    case VarHandle::AccessMode::kGetOpaque:
-      return AccessModeTemplate::kGet;
-    case VarHandle::AccessMode::kSetOpaque:
-      return AccessModeTemplate::kSet;
-    case VarHandle::AccessMode::kCompareAndSet:
-      return AccessModeTemplate::kCompareAndSet;
-    case VarHandle::AccessMode::kCompareAndExchange:
-      return AccessModeTemplate::kCompareAndExchange;
-    case VarHandle::AccessMode::kCompareAndExchangeAcquire:
-      return AccessModeTemplate::kCompareAndExchange;
-    case VarHandle::AccessMode::kCompareAndExchangeRelease:
-      return AccessModeTemplate::kCompareAndExchange;
-    case VarHandle::AccessMode::kWeakCompareAndSetPlain:
-      return AccessModeTemplate::kCompareAndSet;
-    case VarHandle::AccessMode::kWeakCompareAndSet:
-      return AccessModeTemplate::kCompareAndSet;
-    case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
-      return AccessModeTemplate::kCompareAndSet;
-    case VarHandle::AccessMode::kWeakCompareAndSetRelease:
-      return AccessModeTemplate::kCompareAndSet;
-    case VarHandle::AccessMode::kGetAndSet:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndSetAcquire:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndSetRelease:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndAdd:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndAddAcquire:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndAddRelease:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndBitwiseOr:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndBitwiseOrRelease:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndBitwiseAnd:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndBitwiseAndRelease:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndBitwiseXor:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndBitwiseXorRelease:
-      return AccessModeTemplate::kGetAndUpdate;
-    case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
-      return AccessModeTemplate::kGetAndUpdate;
-  }
-}
-
-int32_t GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template) {
-  switch (access_mode_template) {
-    case AccessModeTemplate::kGet:
-      return 0;
-    case AccessModeTemplate::kSet:
-    case AccessModeTemplate::kGetAndUpdate:
-      return 1;
-    case AccessModeTemplate::kCompareAndSet:
-    case AccessModeTemplate::kCompareAndExchange:
-      return 2;
-  }
-  UNREACHABLE();
-}
-
 // Returns the number of parameters associated with an
 // AccessModeTemplate and the supplied coordinate types.
-int32_t GetNumberOfParameters(AccessModeTemplate access_mode_template,
+int32_t GetNumberOfParameters(VarHandle::AccessModeTemplate access_mode_template,
                               ObjPtr<Class> coordinateType0,
                               ObjPtr<Class> coordinateType1) {
   int32_t count = 0;
@@ -197,7 +104,7 @@
       count++;
     }
   }
-  return count + GetNumberOfVarTypeParameters(access_mode_template);
+  return count + VarHandle::GetNumberOfVarTypeParameters(access_mode_template);
 }
 
 void ThrowNullPointerExceptionForCoordinate() REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -225,8 +132,7 @@
 // Returns true if access_mode only entails a memory read. False if
 // access_mode may write to memory.
 bool IsReadOnlyAccessMode(VarHandle::AccessMode access_mode) {
-  AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
-  return access_mode_template == AccessModeTemplate::kGet;
+  return VarHandle::GetAccessModeTemplate(access_mode) == VarHandle::AccessModeTemplate::kGet;
 }
 
 // Writes the parameter types associated with the AccessModeTemplate
@@ -234,7 +140,7 @@
 // variable type and coordinate types. Returns the number of
 // parameters written.
 int32_t BuildParameterArray(ObjPtr<Class> (&parameters)[VarHandle::kMaxAccessorParameters],
-                            AccessModeTemplate access_mode_template,
+                            VarHandle::AccessModeTemplate access_mode_template,
                             ObjPtr<Class> varType,
                             ObjPtr<Class> coordinateType0,
                             ObjPtr<Class> coordinateType1)
@@ -251,34 +157,35 @@
   }
 
   switch (access_mode_template) {
-    case AccessModeTemplate::kCompareAndExchange:
-    case AccessModeTemplate::kCompareAndSet:
+    case VarHandle::AccessModeTemplate::kCompareAndExchange:
+    case VarHandle::AccessModeTemplate::kCompareAndSet:
       parameters[index++] = varType;
       parameters[index++] = varType;
       return index;
-    case AccessModeTemplate::kGet:
+    case VarHandle::AccessModeTemplate::kGet:
       return index;
-    case AccessModeTemplate::kGetAndUpdate:
-    case AccessModeTemplate::kSet:
+    case VarHandle::AccessModeTemplate::kGetAndUpdate:
+    case VarHandle::AccessModeTemplate::kSet:
       parameters[index++] = varType;
       return index;
   }
   return -1;
 }
 
-// Returns the return type associated with an AccessModeTemplate based
+// Returns the return type associated with an VarHandle::AccessModeTemplate based
 // on the template and the variable type specified.
-static ObjPtr<Class> GetReturnType(AccessModeTemplate access_mode_template, ObjPtr<Class> varType)
+static ObjPtr<Class> GetReturnType(VarHandle::AccessModeTemplate access_mode_template,
+                                   ObjPtr<Class> varType)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   DCHECK(varType != nullptr);
   switch (access_mode_template) {
-    case AccessModeTemplate::kCompareAndSet:
+    case VarHandle::AccessModeTemplate::kCompareAndSet:
       return GetClassRoot(ClassRoot::kPrimitiveBoolean);
-    case AccessModeTemplate::kCompareAndExchange:
-    case AccessModeTemplate::kGet:
-    case AccessModeTemplate::kGetAndUpdate:
+    case VarHandle::AccessModeTemplate::kCompareAndExchange:
+    case VarHandle::AccessModeTemplate::kGet:
+    case VarHandle::AccessModeTemplate::kGetAndUpdate:
       return varType;
-    case AccessModeTemplate::kSet:
+    case VarHandle::AccessModeTemplate::kSet:
       return GetClassRoot(ClassRoot::kPrimitiveVoid);
   }
   return nullptr;
@@ -1429,18 +1336,19 @@
   ObjPtr<VarHandle> vh = this;
   ObjPtr<Class> var_type = vh->GetVarType();
   ObjPtr<Class> mt_rtype = method_type->GetRType();
+  ObjPtr<Class> void_type = WellKnownClasses::ToClass(WellKnownClasses::java_lang_Void);
   AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
 
-  // Check return type first. If the return type of the method
-  // of the VarHandle is immaterial.
-  if (mt_rtype->GetPrimitiveType() != Primitive::Type::kPrimVoid) {
-    ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type);
-    if (vh_rtype != mt_rtype) {
-      if (!IsReturnTypeConvertible(vh_rtype, mt_rtype)) {
-        return MatchKind::kNone;
-      }
-      match = MatchKind::kWithConversions;
+  // Check return type first.
+  ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type);
+  if (mt_rtype->GetPrimitiveType() != Primitive::Type::kPrimVoid &&
+      !mt_rtype->IsAssignableFrom(vh_rtype)) {
+    // Call-site is an expression (expects a return value) and the value returned by the accessor
+    // is not assignable to the expected return type.
+    if (!IsReturnTypeConvertible(vh_rtype, mt_rtype)) {
+      return MatchKind::kNone;
     }
+    match = MatchKind::kWithConversions;
   }
 
   // Check the number of parameters matches.
@@ -1457,7 +1365,12 @@
   // Check the parameter types are compatible.
   ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
   for (int32_t i = 0; i < vh_ptypes_count; ++i) {
-    if (mt_ptypes->Get(i) == vh_ptypes[i]) {
+    if (vh_ptypes[i]->IsAssignableFrom(mt_ptypes->Get(i))) {
+      continue;
+    }
+    if (mt_ptypes->Get(i) == void_type && !vh_ptypes[i]->IsPrimitive()) {
+      // The expected parameter is a reference and the parameter type from the call site is j.l.Void
+      // which means the value is null. It is always valid for a reference parameter to be null.
       continue;
     }
     if (!IsParameterTypeConvertible(mt_ptypes->Get(i), vh_ptypes[i])) {
@@ -1468,47 +1381,6 @@
   return match;
 }
 
-bool VarHandle::IsInvokerMethodTypeCompatible(AccessMode access_mode,
-                                              ObjPtr<MethodType> method_type) {
-  StackHandleScope<3> hs(Thread::Current());
-  Handle<Class> mt_rtype(hs.NewHandle(method_type->GetRType()));
-  Handle<VarHandle> vh(hs.NewHandle(this));
-  Handle<Class> var_type(hs.NewHandle(vh->GetVarType()));
-  AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
-
-  // Check return type first.
-  if (mt_rtype->GetPrimitiveType() == Primitive::Type::kPrimVoid) {
-    // The result of the operation will be discarded. The return type
-    // of the VarHandle is immaterial.
-  } else {
-    ObjPtr<Class> vh_rtype(GetReturnType(access_mode_template, var_type.Get()));
-    if (!IsReturnTypeConvertible(vh_rtype, mt_rtype.Get())) {
-      return false;
-    }
-  }
-
-  // Check the number of parameters matches (ignoring the VarHandle parameter).
-  static const int32_t kVarHandleParameters = 1;
-  ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters];
-  const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes,
-                                                      access_mode_template,
-                                                      var_type.Get(),
-                                                      GetCoordinateType0(),
-                                                      GetCoordinateType1());
-  if (vh_ptypes_count != method_type->GetPTypes()->GetLength() - kVarHandleParameters) {
-    return false;
-  }
-
-  // Check the parameter types are compatible (ignoring the VarHandle parameter).
-  ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
-  for (int32_t i = 0; i < vh_ptypes_count; ++i) {
-    if (!IsParameterTypeConvertible(mt_ptypes->Get(i + kVarHandleParameters), vh_ptypes[i])) {
-      return false;
-    }
-  }
-  return true;
-}
-
 ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self,
                                                          ObjPtr<VarHandle> var_handle,
                                                          AccessMode access_mode) {
@@ -1668,7 +1540,8 @@
   if (method_name == nullptr) {
     return false;
   }
-  VarHandleAccessorToAccessModeEntry target = { method_name, /*dummy*/VarHandle::AccessMode::kGet };
+  const auto kUnusedAccessMode = VarHandle::AccessMode::kGet;  // arbitrary value.
+  VarHandleAccessorToAccessModeEntry target = { method_name, kUnusedAccessMode };
   auto last = std::cend(kAccessorToAccessMode);
   auto it = std::lower_bound(std::cbegin(kAccessorToAccessMode),
                              last,
@@ -1681,6 +1554,95 @@
   return true;
 }
 
+// Look up the AccessModeTemplate for a given VarHandle
+// AccessMode. This simplifies finding the correct signature for a
+// VarHandle accessor method.
+VarHandle::AccessModeTemplate VarHandle::GetAccessModeTemplate(VarHandle::AccessMode access_mode) {
+  switch (access_mode) {
+    case VarHandle::AccessMode::kGet:
+      return AccessModeTemplate::kGet;
+    case VarHandle::AccessMode::kSet:
+      return AccessModeTemplate::kSet;
+    case VarHandle::AccessMode::kGetVolatile:
+      return AccessModeTemplate::kGet;
+    case VarHandle::AccessMode::kSetVolatile:
+      return AccessModeTemplate::kSet;
+    case VarHandle::AccessMode::kGetAcquire:
+      return AccessModeTemplate::kGet;
+    case VarHandle::AccessMode::kSetRelease:
+      return AccessModeTemplate::kSet;
+    case VarHandle::AccessMode::kGetOpaque:
+      return AccessModeTemplate::kGet;
+    case VarHandle::AccessMode::kSetOpaque:
+      return AccessModeTemplate::kSet;
+    case VarHandle::AccessMode::kCompareAndSet:
+      return AccessModeTemplate::kCompareAndSet;
+    case VarHandle::AccessMode::kCompareAndExchange:
+      return AccessModeTemplate::kCompareAndExchange;
+    case VarHandle::AccessMode::kCompareAndExchangeAcquire:
+      return AccessModeTemplate::kCompareAndExchange;
+    case VarHandle::AccessMode::kCompareAndExchangeRelease:
+      return AccessModeTemplate::kCompareAndExchange;
+    case VarHandle::AccessMode::kWeakCompareAndSetPlain:
+      return AccessModeTemplate::kCompareAndSet;
+    case VarHandle::AccessMode::kWeakCompareAndSet:
+      return AccessModeTemplate::kCompareAndSet;
+    case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
+      return AccessModeTemplate::kCompareAndSet;
+    case VarHandle::AccessMode::kWeakCompareAndSetRelease:
+      return AccessModeTemplate::kCompareAndSet;
+    case VarHandle::AccessMode::kGetAndSet:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndSetAcquire:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndSetRelease:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndAdd:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndAddAcquire:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndAddRelease:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndBitwiseOr:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndBitwiseOrRelease:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndBitwiseAnd:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndBitwiseAndRelease:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndBitwiseXor:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndBitwiseXorRelease:
+      return AccessModeTemplate::kGetAndUpdate;
+    case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
+      return AccessModeTemplate::kGetAndUpdate;
+  }
+}
+
+VarHandle::AccessModeTemplate VarHandle::GetAccessModeTemplateByIntrinsic(Intrinsics ordinal) {
+  AccessMode access_mode = GetAccessModeByIntrinsic(ordinal);
+  return GetAccessModeTemplate(access_mode);
+}
+
+int32_t VarHandle::GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template) {
+  switch (access_mode_template) {
+    case AccessModeTemplate::kGet:
+      return 0;
+    case AccessModeTemplate::kSet:
+    case AccessModeTemplate::kGetAndUpdate:
+      return 1;
+    case AccessModeTemplate::kCompareAndSet:
+    case AccessModeTemplate::kCompareAndExchange:
+      return 2;
+  }
+  UNREACHABLE();
+}
+
 ArtField* FieldVarHandle::GetField() {
   return reinterpret_cast64<ArtField*>(GetField64(ArtFieldOffset()));
 }
diff --git a/runtime/mirror/var_handle.h b/runtime/mirror/var_handle.h
index 02a0d8c..fd225e0 100644
--- a/runtime/mirror/var_handle.h
+++ b/runtime/mirror/var_handle.h
@@ -47,6 +47,8 @@
 // C++ mirror of java.lang.invoke.VarHandle
 class MANAGED VarHandle : public Object {
  public:
+  MIRROR_CLASS("Ljava/lang/invoke/VarHandle;");
+
   // The maximum number of parameters a VarHandle accessor method can
   // take. The Worst case is equivalent to a compare-and-swap
   // operation on an array element which requires four parameters
@@ -57,6 +59,12 @@
   // method can take.
   static constexpr size_t kMaxVarTypeParameters = 2;
 
+  // The minimum number of CoordinateType parameters a VarHandle acessor method may take.
+  static constexpr size_t kMinCoordinateTypes = 0;
+
+  // The maximum number of CoordinateType parameters a VarHandle acessor method may take.
+  static constexpr size_t kMaxCoordinateTypes = 2;
+
   // Enumeration of the possible access modes. This mirrors the enum
   // in java.lang.invoke.VarHandle.
   enum class AccessMode : uint32_t {
@@ -95,6 +103,15 @@
   };
   constexpr static size_t kNumberOfAccessModes = static_cast<size_t>(AccessMode::kLast) + 1u;
 
+  // Enumeration for describing the parameter and return types of an AccessMode.
+  enum class AccessModeTemplate : uint32_t {
+    kGet,                 // T Op(C0..CN)
+    kSet,                 // void Op(C0..CN, T)
+    kCompareAndSet,       // boolean Op(C0..CN, T, T)
+    kCompareAndExchange,  // T Op(C0..CN, T, T)
+    kGetAndUpdate,        // T Op(C0..CN, T)
+  };
+
   // Returns true if the AccessMode specified is a supported operation.
   bool IsAccessModeSupported(AccessMode accessMode) REQUIRES_SHARED(Locks::mutator_lock_) {
     return (GetAccessModesBitMask() & (1u << static_cast<uint32_t>(accessMode))) != 0;
@@ -111,13 +128,6 @@
   MatchKind GetMethodTypeMatchForAccessMode(AccessMode access_mode, ObjPtr<MethodType> method_type)
         REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Returns true if the MethodType specified is compatible with the
-  // specified access_mode if the first parameter of method_type is
-  // ignored. This is useful for comparing MethodType instances when
-  // invoking a VarHandleAccessor via a MethodHandle invoker.
-  bool IsInvokerMethodTypeCompatible(AccessMode access_mode, ObjPtr<MethodType> method_type)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Allocates and returns the MethodType associated with the
   // AccessMode. No check is made for whether the AccessMode is a
   // supported operation so the MethodType can be used when raising a
@@ -150,15 +160,14 @@
   // VarHandle access method, such as "setOpaque". Returns false otherwise.
   static bool GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode);
 
- private:
-  ObjPtr<Class> GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_);
-  ObjPtr<Class> GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_);
-  int32_t GetAccessModesBitMask() REQUIRES_SHARED(Locks::mutator_lock_);
+  // Returns the AccessModeTemplate for a given mode.
+  static AccessModeTemplate GetAccessModeTemplate(AccessMode access_mode);
 
-  static ObjPtr<MethodType> GetMethodTypeForAccessMode(Thread* self,
-                                                       ObjPtr<VarHandle> var_handle,
-                                                       AccessMode access_mode)
-      REQUIRES_SHARED(Locks::mutator_lock_);
+  // Returns the AccessModeTemplate corresponding to a VarHandle accessor intrinsic.
+  static AccessModeTemplate GetAccessModeTemplateByIntrinsic(Intrinsics ordinal);
+
+  // Returns the number of VarType parameters for an access mode template.
+  static int32_t GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template);
 
   static MemberOffset VarTypeOffset() {
     return MemberOffset(OFFSETOF_MEMBER(VarHandle, var_type_));
@@ -176,6 +185,16 @@
     return MemberOffset(OFFSETOF_MEMBER(VarHandle, access_modes_bit_mask_));
   }
 
+ private:
+  ObjPtr<Class> GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<Class> GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_);
+  int32_t GetAccessModesBitMask() REQUIRES_SHARED(Locks::mutator_lock_);
+
+  static ObjPtr<MethodType> GetMethodTypeForAccessMode(Thread* self,
+                                                       ObjPtr<VarHandle> var_handle,
+                                                       AccessMode access_mode)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   HeapReference<mirror::Class> coordinate_type0_;
   HeapReference<mirror::Class> coordinate_type1_;
   HeapReference<mirror::Class> var_type_;
@@ -190,6 +209,8 @@
 // The corresponding managed class in libart java.lang.invoke.FieldVarHandle.
 class MANAGED FieldVarHandle : public VarHandle {
  public:
+  MIRROR_CLASS("Ljava/lang/invoke/FieldVarHandle;");
+
   bool Access(AccessMode access_mode,
               ShadowFrame* shadow_frame,
               const InstructionOperands* const operands,
@@ -201,11 +222,11 @@
   // Used for updating var-handles to obsolete fields.
   void VisitTarget(ReflectiveValueVisitor* v) REQUIRES(Locks::mutator_lock_);
 
- private:
   static MemberOffset ArtFieldOffset() {
     return MemberOffset(OFFSETOF_MEMBER(FieldVarHandle, art_field_));
   }
 
+ private:
   // ArtField instance corresponding to variable for accessors.
   int64_t art_field_;
 
@@ -233,6 +254,8 @@
 // The corresponding managed class in libart java.lang.invoke.ByteArrayViewVarHandle.
 class MANAGED ByteArrayViewVarHandle : public VarHandle {
  public:
+  MIRROR_CLASS("Ljava/lang/invoke/ByteArrayViewVarHandle;");
+
   bool Access(AccessMode access_mode,
               ShadowFrame* shadow_frame,
               const InstructionOperands* const operands,
@@ -241,11 +264,11 @@
 
   bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
 
- private:
   static MemberOffset NativeByteOrderOffset() {
     return MemberOffset(OFFSETOF_MEMBER(ByteArrayViewVarHandle, native_byte_order_));
   }
 
+ private:
   // Flag indicating that accessors should use native byte-ordering.
   uint8_t native_byte_order_;
 
@@ -258,6 +281,8 @@
 // The corresponding managed class in libart java.lang.invoke.ByteBufferViewVarHandle.
 class MANAGED ByteBufferViewVarHandle : public VarHandle {
  public:
+  MIRROR_CLASS("Ljava/lang/invoke/ByteBufferViewVarHandle;");
+
   bool Access(AccessMode access_mode,
               ShadowFrame* shadow_frame,
               const InstructionOperands* const operands,
diff --git a/runtime/mirror/var_handle_test.cc b/runtime/mirror/var_handle_test.cc
index 6c765d6..5e763dd 100644
--- a/runtime/mirror/var_handle_test.cc
+++ b/runtime/mirror/var_handle_test.cc
@@ -24,7 +24,7 @@
 #include "class-inl.h"
 #include "class_linker-inl.h"
 #include "class_loader.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_runtime_test.h"
 #include "handle_scope-inl.h"
 #include "jvalue-inl.h"
@@ -417,6 +417,65 @@
   }
 }
 
+TEST_F(VarHandleTest, AccessModeTemplate) {
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGet));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kSet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kSet));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetVolatile));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kSet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kSetVolatile));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAcquire));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kSet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kSetRelease));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetOpaque));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kSet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kSetOpaque));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndSet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kCompareAndSet));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndExchange,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kCompareAndExchange));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndExchange,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kCompareAndExchangeAcquire));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndExchange,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kCompareAndExchangeRelease));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndSet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kWeakCompareAndSetPlain));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndSet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kWeakCompareAndSet));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndSet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kWeakCompareAndSetAcquire));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndSet,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kWeakCompareAndSetRelease));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndSet));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndSetAcquire));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndSetRelease));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseOr));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseOrRelease));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseOrAcquire));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseAnd));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseAndRelease));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseAndAcquire));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseXor));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseXorRelease));
+  EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate,
+            VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseXorAcquire));
+}
+
 TEST_F(VarHandleTest, StaticFieldVarHandle) {
   Thread * const self = Thread::Current();
   ScopedObjectAccess soa(self);
diff --git a/runtime/module_exclusion_test.cc b/runtime/module_exclusion_test.cc
index 1f5f87e..b62fc01 100644
--- a/runtime/module_exclusion_test.cc
+++ b/runtime/module_exclusion_test.cc
@@ -178,14 +178,14 @@
                                                    jar_name,
                                                    &error_msg));
   ASSERT_TRUE(odex_file != nullptr) << error_msg;
-  // Check that no classes have been resolved.
+  // Check that no classes have been initialized.
   for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
     std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
     ASSERT_TRUE(dex_file != nullptr);
     for (size_t i = 0, num_class_defs = dex_file->NumClassDefs(); i != num_class_defs; ++i) {
       ClassStatus status = oat_dex_file->GetOatClass(i).GetStatus();
       ASSERT_FALSE(mirror::Class::IsErroneous(status));
-      ASSERT_LT(status, ClassStatus::kResolved);
+      ASSERT_LE(status, ClassStatus::kVerified);
     }
   }
 }
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 8190960..f2189e1 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -31,6 +31,7 @@
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_types.h"
 #include "dex/dex_instruction-inl.h"
+#include "entrypoints/entrypoint_utils-inl.h"
 #include "lock_word-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
@@ -41,6 +42,9 @@
 #include "thread_list.h"
 #include "verifier/method_verifier.h"
 #include "well_known_classes.h"
+#include <android-base/properties.h>
+
+static_assert(ART_USE_FUTEXES);
 
 namespace art {
 
@@ -113,6 +117,11 @@
   // with the owner unlocking the thin-lock.
   CHECK(owner == nullptr || owner == self || owner->IsSuspended());
   // The identity hash code is set for the life time of the monitor.
+
+  bool monitor_timeout_enabled = Runtime::Current()->IsMonitorTimeoutEnabled();
+  if (monitor_timeout_enabled) {
+    MaybeEnableTimeout();
+  }
 }
 
 Monitor::Monitor(Thread* self,
@@ -141,6 +150,11 @@
   // with the owner unlocking the thin-lock.
   CHECK(owner == nullptr || owner == self || owner->IsSuspended());
   // The identity hash code is set for the life time of the monitor.
+
+  bool monitor_timeout_enabled = Runtime::Current()->IsMonitorTimeoutEnabled();
+  if (monitor_timeout_enabled) {
+    MaybeEnableTimeout();
+  }
 }
 
 int32_t Monitor::GetHashCode() {
@@ -215,7 +229,7 @@
   // than what clang thread safety analysis understands.
   // Monitor is not yet public.
   Thread* owner = owner_.load(std::memory_order_relaxed);
-  CHECK(owner == nullptr || owner == self || (ART_USE_FUTEXES && owner->IsSuspended()));
+  CHECK(owner == nullptr || owner == self || owner->IsSuspended());
   // Propagate the lock state.
   LockWord lw(GetObject()->GetLockWord(false));
   switch (lw.GetState()) {
@@ -224,11 +238,7 @@
       CHECK_EQ(owner->GetThreadId(), lw.ThinLockOwner());
       DCHECK_EQ(monitor_lock_.GetExclusiveOwnerTid(), 0) << " my tid = " << SafeGetTid(self);
       lock_count_ = lw.ThinLockCount();
-#if ART_USE_FUTEXES
       monitor_lock_.ExclusiveLockUncontendedFor(owner);
-#else
-      monitor_lock_.ExclusiveLock(owner);
-#endif
       DCHECK_EQ(monitor_lock_.GetExclusiveOwnerTid(), owner->GetTid())
           << " my tid = " << SafeGetTid(self);
       LockWord fat(this, lw.GCState());
@@ -240,13 +250,7 @@
         }
         return true;
       } else {
-#if ART_USE_FUTEXES
         monitor_lock_.ExclusiveUnlockUncontended();
-#else
-        for (uint32_t i = 0; i <= lockCount; ++i) {
-          monitor_lock_.ExclusiveUnlock(owner);
-        }
-#endif
         return false;
       }
     }
@@ -1102,12 +1106,9 @@
   obj = FakeLock(obj);
   uint32_t thread_id = self->GetThreadId();
   size_t contention_count = 0;
+  constexpr size_t kExtraSpinIters = 100;
   StackHandleScope<1> hs(self);
   Handle<mirror::Object> h_obj(hs.NewHandle(obj));
-#if !ART_USE_FUTEXES
-  // In this case we cannot inflate an unowned monitor, so we sometimes defer inflation.
-  bool should_inflate = false;
-#endif
   while (true) {
     // We initially read the lockword with ordinary Java/relaxed semantics. When stronger
     // semantics are needed, we address it below. Since GetLockWord bottoms out to a relaxed load,
@@ -1118,11 +1119,6 @@
         // No ordering required for preceding lockword read, since we retest.
         LockWord thin_locked(LockWord::FromThinLockId(thread_id, 0, lock_word.GCState()));
         if (h_obj->CasLockWord(lock_word, thin_locked, CASMode::kWeak, std::memory_order_acquire)) {
-#if !ART_USE_FUTEXES
-          if (should_inflate) {
-            InflateThinLocked(self, h_obj, lock_word, 0);
-          }
-#endif
           AtraceMonitorLock(self, h_obj.Get(), /* is_wait= */ false);
           return h_obj.Get();  // Success!
         }
@@ -1166,27 +1162,19 @@
           // Contention.
           contention_count++;
           Runtime* runtime = Runtime::Current();
-          if (contention_count <= runtime->GetMaxSpinsBeforeThinLockInflation()) {
+          if (contention_count
+              <= kExtraSpinIters + runtime->GetMaxSpinsBeforeThinLockInflation()) {
             // TODO: Consider switching the thread state to kWaitingForLockInflation when we are
             // yielding.  Use sched_yield instead of NanoSleep since NanoSleep can wait much longer
             // than the parameter you pass in. This can cause thread suspension to take excessively
             // long and make long pauses. See b/16307460.
-            // TODO: We should literally spin first, without sched_yield. Sched_yield either does
-            // nothing (at significant expense), or guarantees that we wait at least microseconds.
-            // If the owner is running, I would expect the median lock hold time to be hundreds
-            // of nanoseconds or less.
-            sched_yield();
+            if (contention_count > kExtraSpinIters) {
+              sched_yield();
+            }
           } else {
-#if ART_USE_FUTEXES
             contention_count = 0;
             // No ordering required for initial lockword read. Install rereads it anyway.
             InflateThinLocked(self, h_obj, lock_word, 0);
-#else
-            // Can't inflate from non-owning thread. Keep waiting. Bad for power, but this code
-            // isn't used on-device.
-            should_inflate = true;
-            usleep(10);
-#endif
           }
         }
         continue;  // Start from the beginning.
@@ -1464,9 +1452,21 @@
   // TODO: use the JNI implementation's table of explicit MonitorEnter calls and dump those too.
   if (m->IsNative()) {
     if (m->IsSynchronized()) {
-      ObjPtr<mirror::Object> jni_this =
-          stack_visitor->GetCurrentHandleScope(sizeof(void*))->GetReference(0);
-      callback(jni_this, callback_context);
+      DCHECK(!m->IsCriticalNative());
+      DCHECK(!m->IsFastNative());
+      ObjPtr<mirror::Object> lock;
+      if (m->IsStatic()) {
+        // Static methods synchronize on the declaring class object.
+        lock = m->GetDeclaringClass();
+      } else {
+        // Instance methods synchronize on the `this` object.
+        // The `this` reference is stored in the first out vreg in the caller's frame.
+        uint8_t* sp = reinterpret_cast<uint8_t*>(stack_visitor->GetCurrentQuickFrame());
+        size_t frame_size = stack_visitor->GetCurrentQuickFrameInfo().FrameSizeInBytes();
+        lock = reinterpret_cast<StackReference<mirror::Object>*>(
+            sp + frame_size + static_cast<size_t>(kRuntimePointerSize))->AsMirrorPtr();
+      }
+      callback(lock, callback_context);
     }
     return;
   }
@@ -1541,7 +1541,7 @@
       // Nothing to check.
       return true;
     case LockWord::kThinLocked:
-      // Basic sanity check of owner.
+      // Basic consistency check of owner.
       return lock_word.ThinLockOwner() != ThreadList::kInvalidThreadId;
     case LockWord::kFatLocked: {
       // Check the  monitor appears in the monitor list.
@@ -1734,4 +1734,13 @@
   }
 }
 
+void Monitor::MaybeEnableTimeout() {
+  std::string current_package = Runtime::Current()->GetProcessPackageName();
+  bool enabled_for_app = android::base::GetBoolProperty("debug.art.monitor.app", false);
+  if (current_package == "android" || enabled_for_app) {
+    monitor_lock_.setEnableMonitorTimeout();
+    monitor_lock_.setMonitorId(monitor_id_);
+  }
+}
+
 }  // namespace art
diff --git a/runtime/monitor.h b/runtime/monitor.h
index 0714da1..99e071e 100644
--- a/runtime/monitor.h
+++ b/runtime/monitor.h
@@ -61,6 +61,12 @@
   // a lock word. See Runtime::max_spins_before_thin_lock_inflation_.
   constexpr static size_t kDefaultMaxSpinsBeforeThinLockInflation = 50;
 
+  static constexpr int kDefaultMonitorTimeoutMs = 500;
+
+  static constexpr int kMonitorTimeoutMinMs = 200;
+
+  static constexpr int kMonitorTimeoutMaxMs = 1000;  // 1 second
+
   ~Monitor();
 
   static void Init(uint32_t lock_profiling_threshold, uint32_t stack_dump_lock_profiling_threshold);
@@ -350,11 +356,11 @@
   // - If contention reporting is enabled, we use the lock_owner_request_ field to have the
   //   contending thread request them. The current owner then sets them when releasing the monitor,
   //   making them available when the contending thread acquires the monitor.
-  // - If both are enabled, we blindly do both. This usually prevents us from switching between
-  //   reporting the end and beginning of critical sections for contention logging when tracing is
-  //   enabled.  We expect that tracing overhead is normally much higher than for contention
-  //   logging, so the added cost should be small. It also minimizes glitches when enabling and
-  //   disabling traces.
+  // - If tracing and contention reporting are enabled, we do both. This usually prevents us from
+  //   switching between reporting the end and beginning of critical sections for contention logging
+  //   when tracing is enabled.  We expect that tracing overhead is normally much higher than for
+  //   contention logging, so the added cost should be small. It also minimizes glitches when
+  //   enabling and disabling traces.
   // We're tolerant of missing information. E.g. when tracing is initially turned on, we may
   // not have the lock holder information if the holder acquired the lock with tracing off.
   //
@@ -413,6 +419,8 @@
   void CheckLockOwnerRequest(Thread* self)
       REQUIRES(monitor_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
 
+  void MaybeEnableTimeout() REQUIRES(Locks::mutator_lock_);
+
   // The denser encoded version of this monitor as stored in the lock word.
   MonitorId monitor_id_;
 
diff --git a/runtime/mutator_gc_coord.md b/runtime/mutator_gc_coord.md
new file mode 100644
index 0000000..84327c0
--- /dev/null
+++ b/runtime/mutator_gc_coord.md
@@ -0,0 +1,146 @@
+Mechanisms for Coordination Between Garbage Collector and Mutator
+-----------------------------------------------------------------
+
+Most garbage collection work can proceed concurrently with the client or
+mutator Java threads. But in certain places, for example while tracing from
+thread stacks, the garbage collector needs to ensure that Java data processed
+by the collector is consistent and complete. At these points, the mutators
+should not hold references to the heap that are invisible to the garbage
+collector. And they should not be modifying the data that is visible to the
+collector.
+
+Logically, the collector and mutator share a reader-writer lock on the Java
+heap and associated data structures. Mutators hold the lock in reader or shared mode
+while running Java code or touching heap-related data structures. The collector
+holds the lock in writer or exclusive mode while it needs the heap data
+structures to be stable. However, this reader-writer lock has a very customized
+implementation that also provides additional facilities, such as the ability
+to exclude only a single thread, so that we can specifically examine its heap
+references.
+
+In order to ensure consistency of the Java data, the compiler inserts "suspend
+points", sometimes also called "safe points" into the code. These allow a thread
+to respond to external requests.
+
+Whenever a thread is runnable, i.e. whenever a thread logically holds the
+mutator lock in shared mode, it is expected to regularly execute such a suspend
+point, and check for pending requests. They are currently implemented by
+setting a flag in the thread structure[^1], which is then explicitly tested by the
+compiler-generated code.
+
+A thread responds to suspend requests only when it is "runnable", i.e. logically
+running Java code. When it runs native code, or is blocked in a kernel call, it
+logically releases the mutator lock. When the garbage collector needs mutator
+cooperation, and the thread is not runnable, it is assured that the mutator is
+not touching Java data, and hence the collector can safely perform the required
+action itself, on the mutator thread's behalf.
+
+Normally, when a thread makes a JNI call, it is not considered runnable while
+executing native code. This makes the transitions to and from running native JNI
+code somewhat expensive (see below). But these transitions are necessary to
+ensure that such code, which does not execute "suspend points", and can thus not
+cooperate with the GC, doesn't delay GC completion. `@FastNative` and
+`@CriticalNative` calls avoid these transitions, instead allowing the thread to
+remain "runnable", at the expense of potentially delaying GC operations for the
+duration of the call.
+
+Although we say that a thread is "suspended" when it is not running Java code,
+it may in fact still be running native code and touching data structures that
+are not considered "Java data". This distinction can be a fine line. For
+example, a Java thread blocked on a Java monitor will normally be "suspended"
+and blocked on a mutex contained in the monitor data structure. But it may wake
+up for reasons beyond ARTs control, which will normally result in touching the
+mutex. The monitor code must be quite careful to ensure that this does not cause
+problems, especially if the ART runtime was shut down in the interim and the
+monitor data structure has been reclaimed.
+
+Calls to change thread state
+----------------------------
+
+When a thread changes between running Java and native code, it has to
+correspondingly change its state between "runnable" and one of several
+other states, all of which are considered to be "suspended" for our purposes.
+When a Java thread starts to execute native code, and may thus not respond
+promptly to suspend requests, it will normally create an object of type
+`ScopedThreadSuspension`. `ScopedThreadSuspension`'s constructor changes state to
+the "suspended" state given as an argument, logically releasing the mutator lock
+and promising to no longer touch Java data structures. It also handles any
+pending suspension requests that slid in just before it changed state.
+
+Conversely, `ScopedThreadSuspension`'s destructor waits until the GC has finished
+any actions it is currently performing on the thread's behalf and effectively
+released the mutator exclusive lock, and then returns to runnable state,
+re-acquiring the mutator lock.
+
+Occasionally a thread running native code needs to temporarily again access Java
+data structures, performing the above transitions in the opposite order.
+`ScopedObjectAccess` is a similar RAII object whose constructor and destructor
+perform those transitions in the reverse order from `ScopedThreadSuspension`.
+
+Mutator lock implementation
+---------------------------
+
+The mutator lock is not implemented as a conventional mutex. But it plays by the
+rules of our normal static thread-safety analysis. Thus a function that is
+expected to be called in runnable state, with the ability to access Java data,
+should be annotated with `REQUIRES_SHARED(Locks::mutator_lock_)`.
+
+There is an explicit `mutator_lock_` object, of type `MutatorMutex`. `MutatorMutex` is
+seemingly a minor refinement of `ReaderWriterMutex`, but it is used entirely
+differently. It is acquired explicitly by clients that need to hold it
+exclusively, and in a small number of cases, it is acquired in shared mode, e.g.
+via `SharedTryLock()`, or by the GC itself. However, more commonly
+`MutatorMutex::TransitionFromSuspendedToRunnable()`, is used to logically acquire
+the mutator mutex, e.g. as part of `ScopedObjectAccess` construction.
+
+`TransitionFromSuspendedToRunnable()` does not physically acquire the
+`ReaderWriterMutex` in shared mode. Thus any thread acquiring the lock in exclusive mode
+must, in addition, explicitly arrange for mutator threads to be suspended via the
+thread suspension mechanism, and then make them runnable again on release.
+
+Logically the mutator lock is held in shared/reader mode if ***either*** the
+underlying reader-writer lock is held in shared mode, ***or*** if a mutator is in
+runnable state.
+
+Suspension and checkpoint API
+-----------------------------
+
+Suspend point checks enable three kinds of communication with mutator threads:
+
+**Checkpoints**
+: Checkpoint requests are used to get a thread to perform an action
+on our behalf. `RequestCheckpoint()` asks a specific thread to execute the closure
+supplied as an argument at its leisure. `RequestSynchronousCheckpoint()` in
+addition waits for the thread to complete running the closure, and handles
+suspended threads by running the closure on their behalf. In addition to these
+functions provided by `Thread`, `ThreadList` provides the `RunCheckpoint()` function
+that runs a checkpoint function on behalf of each thread, either by using
+`RequestCheckpoint()` to run it inside a running thread, or by ensuring that a
+suspended thread stays suspended, and then running the function on its behalf.
+`RunCheckpoint()` does not wait for completion of the function calls triggered by
+the resulting `RequestCheckpoint()` invocations.
+
+**Empty Checkpoints**
+: ThreadList provides `RunEmptyCheckpoint()`, which waits until
+all threads have either passed a suspend point, or have been suspended. This
+ensures that no thread is still executing Java code inside the same
+suspend-point-delimited code interval it was executing before the call. For
+example, a read-barrier started before a `RunEmptyCheckpoint()` call will have
+finished before the call returns.
+
+**Thread suspension**
+: ThreadList provides a number of `SuspendThread...()` calls and
+a `SuspendAll()` call to suspend one or all threads until they are resumed by
+`Resume()` or `ResumeAll()`. The `Suspend...` calls guarantee that the target
+thread(s) are suspended (again, only in the sense of not running Java code)
+when the call returns.
+
+[^1]: Some comments in the code refer to a not-yet-really-implemented scheme in
+which the compiler-generated code would load through the address at
+`tlsPtr_.suspend_trigger`. A thread suspension is requested by setting this to
+null, triggering a `SIGSEGV`, causing that thread to check for GC cooperation
+requests. The real mechanism instead sets an appropriate `ThreadFlag` entry to
+request suspension or a checkpoint. Note that the actual checkpoint function
+value is set, along with the flag, while holding `suspend_count_lock_`. If the
+target thread notices that a checkpoint is requested, it then acquires
+the `suspend_count_lock_` to read the checkpoint function.
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index d2b5edf..f8ad7f1 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -18,9 +18,11 @@
 
 #include <sstream>
 
+#include "android-base/file.h"
 #include "android-base/stringprintf.h"
 
 #include "base/casts.h"
+#include "base/compiler_filter.h"
 #include "base/file_utils.h"
 #include "base/hiddenapi_domain.h"
 #include "base/logging.h"
@@ -31,11 +33,11 @@
 #include "class_linker.h"
 #include "class_loader_context.h"
 #include "common_throws.h"
-#include "compiler_filter.h"
 #include "dex/art_dex_file_loader.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
+#include "gc/space/image_space.h"
 #include "handle_scope-inl.h"
 #include "jit/debugger_interface.h"
 #include "jni/jni_internal.h"
@@ -325,27 +327,10 @@
   return CreateCookieFromOatFileManagerResult(env, dex_files, oat_file, error_msgs);
 }
 
-static jstring DexFile_getClassLoaderContext(JNIEnv* env,
-                                            jclass,
-                                            jobject class_loader,
-                                            jobjectArray dex_elements) {
-  CHECK(class_loader != nullptr);
-  constexpr const char* kBaseDir = "";
-  std::unique_ptr<ClassLoaderContext> context =
-  ClassLoaderContext::CreateContextForClassLoader(class_loader, dex_elements);
-  if (context == nullptr || !context->OpenDexFiles(kRuntimeISA, kBaseDir)) {
-    LOG(WARNING) << "Could not establish class loader context";
-    return nullptr;
-  }
-  std::string str_context = context->EncodeContextForOatFile(kBaseDir);
-  return env->NewStringUTF(str_context.c_str());
-}
-
 static void DexFile_verifyInBackgroundNative(JNIEnv* env,
                                              jclass,
                                              jobject cookie,
-                                             jobject class_loader,
-                                             jstring class_loader_context) {
+                                             jobject class_loader) {
   CHECK(cookie != nullptr);
   CHECK(class_loader != nullptr);
 
@@ -358,17 +343,10 @@
   }
   CHECK(oat_file == nullptr) << "Called verifyInBackground on a dex file backed by oat";
 
-  ScopedUtfChars class_loader_context_utf(env, class_loader_context);
-  if (env->ExceptionCheck()) {
-    LOG(ERROR) << "Failed to unwrap class loader context string";
-    return;
-  }
-
   // Hand over to OatFileManager to spawn a verification thread.
   Runtime::Current()->GetOatFileManager().RunBackgroundVerification(
       dex_files,
-      class_loader,
-      class_loader_context_utf.c_str());
+      class_loader);
 }
 
 static jboolean DexFile_closeDexFile(JNIEnv* env, jclass, jobject cookie) {
@@ -564,22 +542,26 @@
       env->ThrowNew(iae.get(), message.c_str());
       return -1;
     }
+    std::vector<int> context_fds;
+    context->OpenDexFiles(android::base::Dirname(filename),
+                          context_fds,
+                          /*only_read_checksums*/ true);
   }
 
   // TODO: Verify the dex location is well formed, and throw an IOException if
   // not?
 
-  OatFileAssistant oat_file_assistant(filename, target_instruction_set, false);
+  OatFileAssistant oat_file_assistant(filename,
+                                      target_instruction_set,
+                                      context.get(),
+                                      /* load_executable= */ false);
 
   // Always treat elements of the bootclasspath as up-to-date.
   if (oat_file_assistant.IsInBootClassPath()) {
     return OatFileAssistant::kNoDexOptNeeded;
   }
 
-  std::vector<int> context_fds;
   return oat_file_assistant.GetDexOptNeeded(filter,
-                                            context.get(),
-                                            context_fds,
                                             profile_changed,
                                             downgrade);
 }
@@ -607,7 +589,9 @@
     return nullptr;
   }
 
-  OatFileAssistant oat_file_assistant(filename.c_str(), target_instruction_set,
+  OatFileAssistant oat_file_assistant(filename.c_str(),
+                                      target_instruction_set,
+                                      /* context= */ nullptr,
                                       /* load_executable= */ false);
   return env->NewStringUTF(oat_file_assistant.GetStatusDump().c_str());
 }
@@ -714,7 +698,10 @@
     return JNI_FALSE;
   }
 
-  OatFileAssistant oat_file_assistant(filename, kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(filename,
+                                      kRuntimeISA,
+                                      /* context= */ nullptr,
+                                      /* load_executable= */ false);
   return oat_file_assistant.IsUpToDate() ? JNI_FALSE : JNI_TRUE;
 }
 
@@ -829,17 +816,43 @@
     return nullptr;
   }
 
-  OatFileAssistant oat_file_assistant(filename.c_str(),
-                                      target_instruction_set,
-                                      /* load_executable= */ false);
-
-  std::unique_ptr<OatFile> best_oat_file = oat_file_assistant.GetBestOatFile();
-  if (best_oat_file == nullptr) {
-    return nullptr;
+  std::string oat_filename;
+  std::string vdex_filename;
+  // Check if the file is in the boot classpath by looking at image spaces which
+  // have oat files.
+  for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
+    const OatFile* oat_file = space->GetOatFile();
+    if (oat_file != nullptr) {
+      const std::vector<const OatDexFile*>& oat_dex_files = oat_file->GetOatDexFiles();
+      for (const OatDexFile* oat_dex_file : oat_dex_files) {
+        if (DexFileLoader::GetBaseLocation(oat_dex_file->GetDexFileLocation()) ==
+                filename.c_str()) {
+          oat_filename = GetSystemImageFilename(oat_file->GetLocation().c_str(),
+                                                target_instruction_set);
+          break;
+        }
+      }
+      if (!oat_filename.empty()) {
+        break;
+      }
+    }
   }
 
-  std::string oat_filename = best_oat_file->GetLocation();
-  std::string vdex_filename = GetVdexFilename(best_oat_file->GetLocation());
+  // If we did not find a boot classpath oat file, lookup the oat file for an app.
+  if (oat_filename.empty()) {
+    OatFileAssistant oat_file_assistant(filename.c_str(),
+                                        target_instruction_set,
+                                        /* context= */ nullptr,
+                                        /* load_executable= */ false);
+
+    std::unique_ptr<OatFile> best_oat_file = oat_file_assistant.GetBestOatFile();
+    if (best_oat_file == nullptr) {
+      return nullptr;
+    }
+
+    oat_filename = best_oat_file->GetLocation();
+  }
+  vdex_filename = GetVdexFilename(oat_filename);
 
   ScopedLocalRef<jstring> jvdexFilename(env, env->NewStringUTF(vdex_filename.c_str()));
   if (jvdexFilename.get() == nullptr) {
@@ -928,14 +941,9 @@
                 "Ljava/lang/ClassLoader;"
                 "[Ldalvik/system/DexPathList$Element;"
                 ")Ljava/lang/Object;"),
-  NATIVE_METHOD(DexFile, getClassLoaderContext,
-                "(Ljava/lang/ClassLoader;"
-                "[Ldalvik/system/DexPathList$Element;"
-                ")Ljava/lang/String;"),
   NATIVE_METHOD(DexFile, verifyInBackgroundNative,
                 "(Ljava/lang/Object;"
                 "Ljava/lang/ClassLoader;"
-                "Ljava/lang/String;"
                 ")V"),
   NATIVE_METHOD(DexFile, isValidCompilerFilter, "(Ljava/lang/String;)Z"),
   NATIVE_METHOD(DexFile, isProfileGuidedCompilerFilter, "(Ljava/lang/String;)Z"),
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index de43c4f..5c8bd84 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -161,16 +161,6 @@
   Trace::Stop();
 }
 
-static void VMDebug_startEmulatorTracing(JNIEnv*, jclass) {
-  UNIMPLEMENTED(WARNING);
-  // dvmEmulatorTraceStart();
-}
-
-static void VMDebug_stopEmulatorTracing(JNIEnv*, jclass) {
-  UNIMPLEMENTED(WARNING);
-  // dvmEmulatorTraceStop();
-}
-
 static jboolean VMDebug_isDebuggerConnected(JNIEnv*, jclass) {
   // This function will be replaced by the debugger when it's connected. See
   // external/oj-libjdwp/src/share/vmDebug.c for implementation when debugger is connected.
@@ -188,27 +178,6 @@
   return -1;
 }
 
-static void ThrowUnsupportedOperationException(JNIEnv* env) {
-  ScopedObjectAccess soa(env);
-  soa.Self()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", nullptr);
-}
-
-static void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
-  ThrowUnsupportedOperationException(env);
-}
-
-static void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
-  ThrowUnsupportedOperationException(env);
-}
-
-static void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) {
-  ThrowUnsupportedOperationException(env);
-}
-
-static void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
-  ThrowUnsupportedOperationException(env);
-}
-
 static void VMDebug_printLoadedClasses(JNIEnv* env, jclass, jint flags) {
   class DumpClassVisitor : public ClassVisitor {
    public:
@@ -285,14 +254,6 @@
   LOG(INFO) << "---";
 }
 
-static void VMDebug_crash(JNIEnv*, jclass) {
-  LOG(FATAL) << "Crashing runtime on request";
-}
-
-static void VMDebug_infopoint(JNIEnv*, jclass, jint id) {
-  LOG(INFO) << "VMDebug infopoint " << id << " hit";
-}
-
 static jlong VMDebug_countInstancesOfClass(JNIEnv* env,
                                            jclass,
                                            jclass javaClass,
@@ -342,115 +303,6 @@
   return soa.AddLocalReference<jlongArray>(long_counts);
 }
 
-static jobjectArray VMDebug_getInstancesOfClasses(JNIEnv* env,
-                                                  jclass,
-                                                  jobjectArray javaClasses,
-                                                  jboolean includeAssignable) {
-  ScopedObjectAccess soa(env);
-  StackHandleScope<2> hs(soa.Self());
-  Handle<mirror::ObjectArray<mirror::Class>> classes = hs.NewHandle(
-      soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses));
-  if (classes == nullptr) {
-    return nullptr;
-  }
-
-  jclass object_array_class = env->FindClass("[Ljava/lang/Object;");
-  if (env->ExceptionCheck() == JNI_TRUE) {
-    return nullptr;
-  }
-  CHECK(object_array_class != nullptr);
-
-  size_t num_classes = classes->GetLength();
-  jobjectArray result = env->NewObjectArray(num_classes, object_array_class, nullptr);
-  if (env->ExceptionCheck() == JNI_TRUE) {
-    return nullptr;
-  }
-
-  gc::Heap* const heap = Runtime::Current()->GetHeap();
-  MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
-  for (size_t i = 0; i < num_classes; ++i) {
-    h_class.Assign(classes->Get(i));
-
-    VariableSizedHandleScope hs2(soa.Self());
-    std::vector<Handle<mirror::Object>> raw_instances;
-    heap->GetInstances(hs2, h_class, includeAssignable, /* max_count= */ 0, raw_instances);
-    jobjectArray array = env->NewObjectArray(raw_instances.size(),
-                                             WellKnownClasses::java_lang_Object,
-                                             nullptr);
-    if (env->ExceptionCheck() == JNI_TRUE) {
-      return nullptr;
-    }
-
-    for (size_t j = 0; j < raw_instances.size(); ++j) {
-      env->SetObjectArrayElement(array, j, raw_instances[j].ToJObject());
-    }
-    env->SetObjectArrayElement(result, i, array);
-  }
-  return result;
-}
-
-// We export the VM internal per-heap-space size/alloc/free metrics
-// for the zygote space, alloc space (application heap), and the large
-// object space for dumpsys meminfo. The other memory region data such
-// as PSS, private/shared dirty/shared data are available via
-// /proc/<pid>/smaps.
-static void VMDebug_getHeapSpaceStats(JNIEnv* env, jclass, jlongArray data) {
-  jlong* arr = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(data, nullptr));
-  if (arr == nullptr || env->GetArrayLength(data) < 9) {
-    return;
-  }
-
-  size_t allocSize = 0;
-  size_t allocUsed = 0;
-  size_t zygoteSize = 0;
-  size_t zygoteUsed = 0;
-  size_t largeObjectsSize = 0;
-  size_t largeObjectsUsed = 0;
-  gc::Heap* heap = Runtime::Current()->GetHeap();
-  {
-    ScopedObjectAccess soa(env);
-    for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) {
-      if (space->IsImageSpace()) {
-        // Currently don't include the image space.
-      } else if (space->IsZygoteSpace()) {
-        gc::space::ZygoteSpace* zygote_space = space->AsZygoteSpace();
-        zygoteSize += zygote_space->Size();
-        zygoteUsed += zygote_space->GetBytesAllocated();
-      } else if (space->IsMallocSpace()) {
-        // This is a malloc space.
-        gc::space::MallocSpace* malloc_space = space->AsMallocSpace();
-        allocSize += malloc_space->GetFootprint();
-        allocUsed += malloc_space->GetBytesAllocated();
-      } else if (space->IsBumpPointerSpace()) {
-        gc::space::BumpPointerSpace* bump_pointer_space = space->AsBumpPointerSpace();
-        allocSize += bump_pointer_space->Size();
-        allocUsed += bump_pointer_space->GetBytesAllocated();
-      }
-    }
-    for (gc::space::DiscontinuousSpace* space : heap->GetDiscontinuousSpaces()) {
-      if (space->IsLargeObjectSpace()) {
-        largeObjectsSize += space->AsLargeObjectSpace()->GetBytesAllocated();
-        largeObjectsUsed += largeObjectsSize;
-      }
-    }
-  }
-  size_t allocFree = allocSize - allocUsed;
-  size_t zygoteFree = zygoteSize - zygoteUsed;
-  size_t largeObjectsFree = largeObjectsSize - largeObjectsUsed;
-
-  int j = 0;
-  arr[j++] = allocSize;
-  arr[j++] = allocUsed;
-  arr[j++] = allocFree;
-  arr[j++] = zygoteSize;
-  arr[j++] = zygoteUsed;
-  arr[j++] = zygoteFree;
-  arr[j++] = largeObjectsSize;
-  arr[j++] = largeObjectsUsed;
-  arr[j++] = largeObjectsFree;
-  env->ReleasePrimitiveArrayCritical(data, arr, 0);
-}
-
 // The runtime stat names for VMDebug.getRuntimeStat().
 enum class VMDebugRuntimeStatId {
   kArtGcGcCount = 0,
@@ -461,6 +313,8 @@
   kArtGcBlockingGcTime,
   kArtGcGcCountRateHistogram,
   kArtGcBlockingGcCountRateHistogram,
+  kArtGcObjectsAllocated,
+  kArtGcTotalTimeWaitingForGc,
   kNumRuntimeStats,
 };
 
@@ -501,6 +355,14 @@
       heap->DumpBlockingGcCountRateHistogram(output);
       return env->NewStringUTF(output.str().c_str());
     }
+    case VMDebugRuntimeStatId::kArtGcObjectsAllocated: {
+      std::string output = std::to_string(heap->GetObjectsAllocated());
+      return env->NewStringUTF(output.c_str());
+    }
+    case VMDebugRuntimeStatId::kArtGcTotalTimeWaitingForGc: {
+      std::string output = std::to_string(heap->GetTotalTimeWaitingForGC());
+      return env->NewStringUTF(output.c_str());
+    }
     default:
       return nullptr;
   }
@@ -630,33 +492,23 @@
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
   NATIVE_METHOD(VMDebug, countInstancesOfClasses, "([Ljava/lang/Class;Z)[J"),
-  NATIVE_METHOD(VMDebug, crash, "()V"),
   NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;I)V"),
   NATIVE_METHOD(VMDebug, dumpHprofDataDdms, "()V"),
   NATIVE_METHOD(VMDebug, dumpReferenceTables, "()V"),
   NATIVE_METHOD(VMDebug, getAllocCount, "(I)I"),
-  NATIVE_METHOD(VMDebug, getHeapSpaceStats, "([J)V"),
-  NATIVE_METHOD(VMDebug, getInstancesOfClasses, "([Ljava/lang/Class;Z)[[Ljava/lang/Object;"),
-  NATIVE_METHOD(VMDebug, getInstructionCount, "([I)V"),
   FAST_NATIVE_METHOD(VMDebug, getLoadedClassCount, "()I"),
   NATIVE_METHOD(VMDebug, getVmFeatureList, "()[Ljava/lang/String;"),
-  NATIVE_METHOD(VMDebug, infopoint, "(I)V"),
   FAST_NATIVE_METHOD(VMDebug, isDebuggerConnected, "()Z"),
   FAST_NATIVE_METHOD(VMDebug, isDebuggingEnabled, "()Z"),
   NATIVE_METHOD(VMDebug, getMethodTracingMode, "()I"),
   FAST_NATIVE_METHOD(VMDebug, lastDebuggerActivity, "()J"),
   FAST_NATIVE_METHOD(VMDebug, printLoadedClasses, "(I)V"),
   NATIVE_METHOD(VMDebug, resetAllocCount, "(I)V"),
-  NATIVE_METHOD(VMDebug, resetInstructionCount, "()V"),
   NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
-  NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
-  NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
   NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"),
   NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;IIIZIZ)V"),
   NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;IIZI)V"),
   NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
-  NATIVE_METHOD(VMDebug, stopEmulatorTracing, "()V"),
-  NATIVE_METHOD(VMDebug, stopInstructionCounting, "()V"),
   NATIVE_METHOD(VMDebug, stopMethodTracing, "()V"),
   FAST_NATIVE_METHOD(VMDebug, threadCpuTimeNanos, "()J"),
   NATIVE_METHOD(VMDebug, getRuntimeStatInternal, "(I)Ljava/lang/String;"),
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index efaa3d9..8425904 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -76,12 +76,6 @@
   Runtime::Current()->GetHeap()->SetTargetHeapUtilization(target);
 }
 
-static void VMRuntime_startJitCompilation(JNIEnv*, jobject) {
-}
-
-static void VMRuntime_disableJitCompilation(JNIEnv*, jobject) {
-}
-
 static void VMRuntime_setHiddenApiExemptions(JNIEnv* env,
                                             jclass,
                                             jobjectArray exemptions) {
@@ -283,7 +277,7 @@
   for (int i = 0; i < length; i++) {
     disabled_compat_changes_set.insert(static_cast<uint64_t>(elements[i]));
   }
-  Runtime::Current()->SetDisabledCompatChanges(disabled_compat_changes_set);
+  Runtime::Current()->GetCompatFramework().SetDisabledCompatChanges(disabled_compat_changes_set);
 }
 
 static inline size_t clamp_to_size_t(jlong n) {
@@ -342,18 +336,16 @@
   Runtime::Current()->GetHeap()->Trim(ThreadForEnv(env));
 }
 
-static void VMRuntime_concurrentGC(JNIEnv* env, jobject) {
-  Runtime::Current()->GetHeap()->ConcurrentGC(ThreadForEnv(env), gc::kGcCauseBackground, true);
-}
-
 static void VMRuntime_requestHeapTrim(JNIEnv* env, jobject) {
   Runtime::Current()->GetHeap()->RequestTrim(ThreadForEnv(env));
 }
 
 static void VMRuntime_requestConcurrentGC(JNIEnv* env, jobject) {
-  Runtime::Current()->GetHeap()->RequestConcurrentGC(ThreadForEnv(env),
-                                                     gc::kGcCauseBackground,
-                                                     true);
+  gc::Heap *heap = Runtime::Current()->GetHeap();
+  heap->RequestConcurrentGC(ThreadForEnv(env),
+                            gc::kGcCauseBackground,
+                            true,
+                            heap->GetCurrentGcNum());
 }
 
 static void VMRuntime_startHeapTaskProcessor(JNIEnv* env, jobject) {
@@ -368,282 +360,21 @@
   Runtime::Current()->GetHeap()->GetTaskProcessor()->RunAllTasks(ThreadForEnv(env));
 }
 
-using StringTable = std::map<std::string, ObjPtr<mirror::String>>;
-
-class PreloadDexCachesStringsVisitor : public SingleRootVisitor {
- public:
-  explicit PreloadDexCachesStringsVisitor(StringTable* table) : table_(table) { }
-
-  void VisitRoot(mirror::Object* root, const RootInfo& info ATTRIBUTE_UNUSED)
-      override REQUIRES_SHARED(Locks::mutator_lock_) {
-    ObjPtr<mirror::String> string = root->AsString();
-    table_->operator[](string->ToModifiedUtf8()) = string;
-  }
-
- private:
-  StringTable* const table_;
-};
-
-// Based on ClassLinker::ResolveString.
-static void PreloadDexCachesResolveString(
-    ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx, StringTable& strings)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  uint32_t slot_idx = dex_cache->StringSlotIndex(string_idx);
-  auto pair = dex_cache->GetStrings()[slot_idx].load(std::memory_order_relaxed);
-  if (!pair.object.IsNull()) {
-    return;  // The entry already contains some String.
-  }
-  const DexFile* dex_file = dex_cache->GetDexFile();
-  const char* utf8 = dex_file->StringDataByIdx(string_idx);
-  ObjPtr<mirror::String> string = strings[utf8];
-  if (string == nullptr) {
-    return;
-  }
-  dex_cache->SetResolvedString(string_idx, string);
+static void VMRuntime_preloadDexCaches(JNIEnv* env ATTRIBUTE_UNUSED, jobject) {
 }
 
-// Based on ClassLinker::ResolveType.
-static void PreloadDexCachesResolveType(Thread* self,
-                                        ObjPtr<mirror::DexCache> dex_cache,
-                                        dex::TypeIndex type_idx)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  uint32_t slot_idx = dex_cache->TypeSlotIndex(type_idx);
-  auto pair = dex_cache->GetResolvedTypes()[slot_idx].load(std::memory_order_relaxed);
-  if (!pair.object.IsNull()) {
-    return;  // The entry already contains some Class.
-  }
-  const DexFile* dex_file = dex_cache->GetDexFile();
-  const char* class_name = dex_file->StringByTypeIdx(type_idx);
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  ObjPtr<mirror::Class> klass = (class_name[1] == '\0')
-      ? linker->LookupPrimitiveClass(class_name[0])
-      : linker->LookupClass(self, class_name, nullptr);
-  if (klass == nullptr || !klass->IsResolved()) {
-    return;
-  }
-  dex_cache->SetResolvedType(type_idx, klass);
-}
-
-// Based on ClassLinker::ResolveField.
-static void PreloadDexCachesResolveField(ObjPtr<mirror::DexCache> dex_cache,
-                                         uint32_t field_idx,
-                                         bool is_static)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  uint32_t slot_idx = dex_cache->FieldSlotIndex(field_idx);
-  auto pair = mirror::DexCache::GetNativePairPtrSize(dex_cache->GetResolvedFields(),
-                                                     slot_idx,
-                                                     kRuntimePointerSize);
-  if (pair.object != nullptr) {
-    return;  // The entry already contains some ArtField.
-  }
-  const DexFile* dex_file = dex_cache->GetDexFile();
-  const dex::FieldId& field_id = dex_file->GetFieldId(field_idx);
-  ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->LookupResolvedType(
-      field_id.class_idx_, dex_cache, /* class_loader= */ nullptr);
-  if (klass == nullptr) {
-    return;
-  }
-  ArtField* field = is_static
-      ? mirror::Class::FindStaticField(Thread::Current(), klass, dex_cache, field_idx)
-      : klass->FindInstanceField(dex_cache, field_idx);
-  if (field == nullptr) {
-    return;
-  }
-  dex_cache->SetResolvedField(field_idx, field, kRuntimePointerSize);
-}
-
-// Based on ClassLinker::ResolveMethod.
-static void PreloadDexCachesResolveMethod(ObjPtr<mirror::DexCache> dex_cache, uint32_t method_idx)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  uint32_t slot_idx = dex_cache->MethodSlotIndex(method_idx);
-  auto pair = mirror::DexCache::GetNativePairPtrSize(dex_cache->GetResolvedMethods(),
-                                                     slot_idx,
-                                                     kRuntimePointerSize);
-  if (pair.object != nullptr) {
-    return;  // The entry already contains some ArtMethod.
-  }
-  const DexFile* dex_file = dex_cache->GetDexFile();
-  const dex::MethodId& method_id = dex_file->GetMethodId(method_idx);
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-
-  ObjPtr<mirror::Class> klass = class_linker->LookupResolvedType(
-      method_id.class_idx_, dex_cache, /* class_loader= */ nullptr);
-  if (klass == nullptr) {
-    return;
-  }
-  // Call FindResolvedMethod to populate the dex cache.
-  class_linker->FindResolvedMethod(klass, dex_cache, /* class_loader= */ nullptr, method_idx);
-}
-
-struct DexCacheStats {
-    uint32_t num_strings;
-    uint32_t num_types;
-    uint32_t num_fields;
-    uint32_t num_methods;
-    DexCacheStats() : num_strings(0),
-                      num_types(0),
-                      num_fields(0),
-                      num_methods(0) {}
-};
-
-static const bool kPreloadDexCachesEnabled = true;
-
-// Disabled because it takes a long time (extra half second) but
-// gives almost no benefit in terms of saving private dirty pages.
-static const bool kPreloadDexCachesStrings = false;
-
-static const bool kPreloadDexCachesTypes = true;
-static const bool kPreloadDexCachesFieldsAndMethods = true;
-
-static const bool kPreloadDexCachesCollectStats = true;
-
-static void PreloadDexCachesStatsTotal(DexCacheStats* total) {
-  if (!kPreloadDexCachesCollectStats) {
-    return;
-  }
-
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath();
-  for (size_t i = 0; i< boot_class_path.size(); i++) {
-    const DexFile* dex_file = boot_class_path[i];
-    CHECK(dex_file != nullptr);
-    total->num_strings += dex_file->NumStringIds();
-    total->num_fields += dex_file->NumFieldIds();
-    total->num_methods += dex_file->NumMethodIds();
-    total->num_types += dex_file->NumTypeIds();
-  }
-}
-
-static void PreloadDexCachesStatsFilled(DexCacheStats* filled)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  if (!kPreloadDexCachesCollectStats) {
-    return;
-  }
-  // TODO: Update for hash-based DexCache arrays.
-  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
-  Thread* const self = Thread::Current();
-  for (const DexFile* dex_file : class_linker->GetBootClassPath()) {
-    CHECK(dex_file != nullptr);
-    // In fallback mode, not all boot classpath components might be registered, yet.
-    if (!class_linker->IsDexFileRegistered(self, *dex_file)) {
-      continue;
-    }
-    const ObjPtr<mirror::DexCache> dex_cache = class_linker->FindDexCache(self, *dex_file);
-    DCHECK(dex_cache != nullptr);  // Boot class path dex caches are never unloaded.
-    for (size_t j = 0, num_strings = dex_cache->NumStrings(); j < num_strings; ++j) {
-      auto pair = dex_cache->GetStrings()[j].load(std::memory_order_relaxed);
-      if (!pair.object.IsNull()) {
-        filled->num_strings++;
-      }
-    }
-    for (size_t j = 0, num_types = dex_cache->NumResolvedTypes(); j < num_types; ++j) {
-      auto pair = dex_cache->GetResolvedTypes()[j].load(std::memory_order_relaxed);
-      if (!pair.object.IsNull()) {
-        filled->num_types++;
-      }
-    }
-    for (size_t j = 0, num_fields = dex_cache->NumResolvedFields(); j < num_fields; ++j) {
-      auto pair = mirror::DexCache::GetNativePairPtrSize(dex_cache->GetResolvedFields(),
-                                                         j,
-                                                         kRuntimePointerSize);
-      if (pair.object != nullptr) {
-        filled->num_fields++;
-      }
-    }
-    for (size_t j = 0, num_methods = dex_cache->NumResolvedMethods(); j < num_methods; ++j) {
-      auto pair = mirror::DexCache::GetNativePairPtrSize(dex_cache->GetResolvedMethods(),
-                                                         j,
-                                                         kRuntimePointerSize);
-      if (pair.object != nullptr) {
-        filled->num_methods++;
-      }
-    }
-  }
-}
-
-// TODO: http://b/11309598 This code was ported over based on the
-// Dalvik version. However, ART has similar code in other places such
-// as the CompilerDriver. This code could probably be refactored to
-// serve both uses.
-static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) {
-  if (!kPreloadDexCachesEnabled) {
-    return;
-  }
-
-  ScopedObjectAccess soa(env);
-
-  DexCacheStats total;
-  DexCacheStats before;
-  if (kPreloadDexCachesCollectStats) {
-    LOG(INFO) << "VMRuntime.preloadDexCaches starting";
-    PreloadDexCachesStatsTotal(&total);
-    PreloadDexCachesStatsFilled(&before);
-  }
-
-  Runtime* runtime = Runtime::Current();
-  ClassLinker* linker = runtime->GetClassLinker();
-
-  // We use a std::map to avoid heap allocating StringObjects to lookup in gDvm.literalStrings
-  StringTable strings;
-  if (kPreloadDexCachesStrings) {
-    PreloadDexCachesStringsVisitor visitor(&strings);
-    runtime->GetInternTable()->VisitRoots(&visitor, kVisitRootFlagAllRoots);
-  }
-
-  const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath();
-  for (size_t i = 0; i < boot_class_path.size(); i++) {
-    const DexFile* dex_file = boot_class_path[i];
-    CHECK(dex_file != nullptr);
-    ObjPtr<mirror::DexCache> dex_cache = linker->RegisterDexFile(*dex_file, nullptr);
-    CHECK(dex_cache != nullptr);  // Boot class path dex caches are never unloaded.
-    if (kPreloadDexCachesStrings) {
-      for (size_t j = 0; j < dex_cache->NumStrings(); j++) {
-        PreloadDexCachesResolveString(dex_cache, dex::StringIndex(j), strings);
-      }
-    }
-
-    if (kPreloadDexCachesTypes) {
-      for (size_t j = 0; j < dex_cache->NumResolvedTypes(); j++) {
-        PreloadDexCachesResolveType(soa.Self(), dex_cache, dex::TypeIndex(j));
-      }
-    }
-
-    if (kPreloadDexCachesFieldsAndMethods) {
-      for (ClassAccessor accessor : dex_file->GetClasses()) {
-        for (const ClassAccessor::Field& field : accessor.GetFields()) {
-          PreloadDexCachesResolveField(dex_cache, field.GetIndex(), field.IsStatic());
-        }
-        for (const ClassAccessor::Method& method : accessor.GetMethods()) {
-          PreloadDexCachesResolveMethod(dex_cache, method.GetIndex());
-        }
-      }
-    }
-  }
-
-  if (kPreloadDexCachesCollectStats) {
-    DexCacheStats after;
-    PreloadDexCachesStatsFilled(&after);
-    LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches strings total=%d before=%d after=%d",
-                              total.num_strings, before.num_strings, after.num_strings);
-    LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches types total=%d before=%d after=%d",
-                              total.num_types, before.num_types, after.num_types);
-    LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches fields total=%d before=%d after=%d",
-                              total.num_fields, before.num_fields, after.num_fields);
-    LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches methods total=%d before=%d after=%d",
-                              total.num_methods, before.num_methods, after.num_methods);
-    LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches finished");
-  }
-}
-
-
 /*
- * This is called by the framework when it knows the application directory and
- * process name.
+ * This is called by the framework after it loads a code path on behalf of the app.
+ * The code_path_type indicates the type of the apk being loaded and can be used
+ * for more precise telemetry (e.g. is the split apk odex up to date?) and debugging.
  */
 static void VMRuntime_registerAppInfo(JNIEnv* env,
                                       jclass clazz ATTRIBUTE_UNUSED,
-                                      jstring profile_file,
-                                      jobjectArray code_paths) {
+                                      jstring package_name,
+                                      jstring cur_profile_file,
+                                      jstring ref_profile_file,
+                                      jobjectArray code_paths,
+                                      jint code_path_type) {
   std::vector<std::string> code_paths_vec;
   int code_paths_length = env->GetArrayLength(code_paths);
   for (int i = 0; i < code_paths_length; i++) {
@@ -653,14 +384,24 @@
     env->ReleaseStringUTFChars(code_path, raw_code_path);
   }
 
-  const char* raw_profile_file = env->GetStringUTFChars(profile_file, nullptr);
-  std::string profile_file_str(raw_profile_file);
-  env->ReleaseStringUTFChars(profile_file, raw_profile_file);
+  const char* raw_cur_profile_file = env->GetStringUTFChars(cur_profile_file, nullptr);
+  std::string cur_profile_file_str(raw_cur_profile_file);
+  env->ReleaseStringUTFChars(cur_profile_file, raw_cur_profile_file);
 
-  Runtime::Current()->RegisterAppInfo(code_paths_vec, profile_file_str);
-}
+  const char* raw_ref_profile_file = env->GetStringUTFChars(ref_profile_file, nullptr);
+  std::string ref_profile_file_str(raw_ref_profile_file);
+  env->ReleaseStringUTFChars(ref_profile_file, raw_ref_profile_file);
 
-static void VMRuntime_doNotInitializeInAot() {
+  const char* raw_package_name = env->GetStringUTFChars(package_name, nullptr);
+  std::string package_name_str(raw_package_name);
+  env->ReleaseStringUTFChars(package_name, raw_package_name);
+
+  Runtime::Current()->RegisterAppInfo(
+      package_name_str,
+      code_paths_vec,
+      cur_profile_file_str,
+      ref_profile_file_str,
+      static_cast<int32_t>(code_path_type));
 }
 
 static jboolean VMRuntime_isBootClassPathOnDisk(JNIEnv* env, jclass, jstring java_instruction_set) {
@@ -682,11 +423,6 @@
   return env->NewStringUTF(GetInstructionSetString(kRuntimeISA));
 }
 
-static jboolean VMRuntime_didPruneDalvikCache(JNIEnv* env ATTRIBUTE_UNUSED,
-                                              jclass klass ATTRIBUTE_UNUSED) {
-  return Runtime::Current()->GetPrunedDalvikCache() ? JNI_TRUE : JNI_FALSE;
-}
-
 static void VMRuntime_setSystemDaemonThreadPriority(JNIEnv* env ATTRIBUTE_UNUSED,
                                                     jclass klass ATTRIBUTE_UNUSED) {
 #ifdef ART_TARGET_ANDROID
@@ -722,11 +458,6 @@
   Runtime::Current()->SetProcessDataDirectory(data_dir.c_str());
 }
 
-static jboolean VMRuntime_hasBootImageSpaces(JNIEnv* env ATTRIBUTE_UNUSED,
-                                             jclass klass ATTRIBUTE_UNUSED) {
-  return Runtime::Current()->GetHeap()->HasBootImageSpace() ? JNI_TRUE : JNI_FALSE;
-}
-
 static void VMRuntime_bootCompleted(JNIEnv* env ATTRIBUTE_UNUSED,
                                     jclass klass ATTRIBUTE_UNUSED) {
   jit::Jit* jit = Runtime::Current()->GetJit();
@@ -781,9 +512,6 @@
   NATIVE_METHOD(VMRuntime, clampGrowthLimit, "()V"),
   NATIVE_METHOD(VMRuntime, classPath, "()Ljava/lang/String;"),
   NATIVE_METHOD(VMRuntime, clearGrowthLimit, "()V"),
-  NATIVE_METHOD(VMRuntime, concurrentGC, "()V"),
-  NATIVE_METHOD(VMRuntime, disableJitCompilation, "()V"),
-  FAST_NATIVE_METHOD(VMRuntime, hasBootImageSpaces, "()Z"),  // Could be CRITICAL.
   NATIVE_METHOD(VMRuntime, setHiddenApiExemptions, "([Ljava/lang/String;)V"),
   NATIVE_METHOD(VMRuntime, setHiddenApiAccessLogSamplingRate, "(I)V"),
   NATIVE_METHOD(VMRuntime, getTargetHeapUtilization, "()F"),
@@ -807,7 +535,6 @@
   NATIVE_METHOD(VMRuntime, runHeapTasks, "()V"),
   NATIVE_METHOD(VMRuntime, updateProcessState, "(I)V"),
   NATIVE_METHOD(VMRuntime, startHeapTaskProcessor, "()V"),
-  NATIVE_METHOD(VMRuntime, startJitCompilation, "()V"),
   NATIVE_METHOD(VMRuntime, stopHeapTaskProcessor, "()V"),
   NATIVE_METHOD(VMRuntime, trimHeap, "()V"),
   NATIVE_METHOD(VMRuntime, vmVersion, "()Ljava/lang/String;"),
@@ -816,11 +543,10 @@
   FAST_NATIVE_METHOD(VMRuntime, is64Bit, "()Z"),
   FAST_NATIVE_METHOD(VMRuntime, isCheckJniEnabled, "()Z"),
   NATIVE_METHOD(VMRuntime, preloadDexCaches, "()V"),
-  NATIVE_METHOD(VMRuntime, registerAppInfo, "(Ljava/lang/String;[Ljava/lang/String;)V"),
-  CRITICAL_NATIVE_METHOD(VMRuntime, doNotInitializeInAot, "()V"),
+  NATIVE_METHOD(VMRuntime, registerAppInfo,
+      "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;I)V"),
   NATIVE_METHOD(VMRuntime, isBootClassPathOnDisk, "(Ljava/lang/String;)Z"),
   NATIVE_METHOD(VMRuntime, getCurrentInstructionSet, "()Ljava/lang/String;"),
-  NATIVE_METHOD(VMRuntime, didPruneDalvikCache, "()Z"),
   NATIVE_METHOD(VMRuntime, setSystemDaemonThreadPriority, "()V"),
   NATIVE_METHOD(VMRuntime, setDedupeHiddenApiWarnings, "(Z)V"),
   NATIVE_METHOD(VMRuntime, setProcessPackageName, "(Ljava/lang/String;)V"),
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
index 32733a8..9d2dfac 100644
--- a/runtime/native/dalvik_system_VMStack.cc
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -84,7 +84,7 @@
   ScopedFastNativeObjectAccess soa(env);
   auto fn = [](Thread* thread, const ScopedFastNativeObjectAccess& soaa)
       REQUIRES_SHARED(Locks::mutator_lock_) -> jobject {
-    return thread->CreateInternalStackTrace<false>(soaa);
+    return thread->CreateInternalStackTrace(soaa);
   };
   jobject trace = GetThreadStack(soa, javaThread, fn);
   if (trace == nullptr) {
@@ -151,7 +151,7 @@
   ScopedFastNativeObjectAccess soa(env);
   auto fn = [](Thread* thread, const ScopedFastNativeObjectAccess& soaa)
      REQUIRES_SHARED(Locks::mutator_lock_) -> jobject {
-    return thread->CreateInternalStackTrace<false>(soaa);
+    return thread->CreateInternalStackTrace(soaa);
   };
   jobject trace = GetThreadStack(soa, javaThread, fn);
   if (trace == nullptr) {
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index c37b8bb..050233d 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -144,7 +144,7 @@
   DEBUG_NATIVE_DEBUGGABLE             = 1 << 7,
   DEBUG_JAVA_DEBUGGABLE               = 1 << 8,
   DISABLE_VERIFIER                    = 1 << 9,
-  ONLY_USE_SYSTEM_OAT_FILES           = 1 << 10,
+  ONLY_USE_TRUSTED_OAT_FILES          = 1 << 10,  // Formerly ONLY_USE_SYSTEM_OAT_FILES
   DEBUG_GENERATE_MINI_DEBUG_INFO      = 1 << 11,
   HIDDEN_API_ENFORCEMENT_POLICY_MASK  = (1 << 12)
                                       | (1 << 13),
@@ -153,6 +153,7 @@
   USE_APP_IMAGE_STARTUP_CACHE         = 1 << 16,
   DEBUG_IGNORE_APP_SIGNAL_HANDLER     = 1 << 17,
   DISABLE_TEST_API_ENFORCEMENT_POLICY = 1 << 18,
+  PROFILEABLE                         = 1 << 24,
 
   // bits to shift (flags & HIDDEN_API_ENFORCEMENT_POLICY_MASK) by to get a value
   // corresponding to hiddenapi::EnforcementPolicy
@@ -245,6 +246,8 @@
 
   runtime->SetProfileableFromShell((runtime_flags & PROFILE_FROM_SHELL) != 0);
   runtime_flags &= ~PROFILE_FROM_SHELL;
+  runtime->SetProfileable((runtime_flags & PROFILEABLE) != 0);
+  runtime_flags &= ~PROFILEABLE;
 
   return runtime_flags;
 }
@@ -266,6 +269,9 @@
 static void ZygoteHooks_nativePostForkSystemServer(JNIEnv* env ATTRIBUTE_UNUSED,
                                                    jclass klass ATTRIBUTE_UNUSED,
                                                    jint runtime_flags) {
+  // Reload the current flags first. In case we need to take actions based on them.
+  Runtime::Current()->ReloadAllFlags(__FUNCTION__);
+
   // Set the runtime state as the first thing, in case JIT and other services
   // start querying it.
   Runtime::Current()->SetAsSystemServer();
@@ -293,7 +299,9 @@
                                             jboolean is_zygote,
                                             jstring instruction_set) {
   DCHECK(!(is_system_server && is_zygote));
-  // Set the runtime state as the first thing, in case JIT and other services
+  // Reload the current flags first. In case we need to take any updated actions.
+  Runtime::Current()->ReloadAllFlags(__FUNCTION__);
+  // Then, set the runtime state, in case JIT and other services
   // start querying it.
   Runtime::Current()->SetAsZygoteChild(is_system_server, is_zygote);
 
@@ -310,9 +318,9 @@
     runtime_flags &= ~DISABLE_VERIFIER;
   }
 
-  if ((runtime_flags & ONLY_USE_SYSTEM_OAT_FILES) != 0 || is_system_server) {
-    runtime->GetOatFileManager().SetOnlyUseSystemOatFiles();
-    runtime_flags &= ~ONLY_USE_SYSTEM_OAT_FILES;
+  if ((runtime_flags & ONLY_USE_TRUSTED_OAT_FILES) != 0 || is_system_server) {
+    runtime->GetOatFileManager().SetOnlyUseTrustedOatFiles();
+    runtime_flags &= ~ONLY_USE_TRUSTED_OAT_FILES;
   }
 
   api_enforcement_policy = hiddenapi::EnforcementPolicyFromInt(
@@ -434,11 +442,26 @@
   Runtime::Current()->SetZygoteNoThreadSection(false);
 }
 
+static jboolean ZygoteHooks_nativeZygoteLongSuspendOk(JNIEnv* env ATTRIBUTE_UNUSED,
+                                                    jclass klass ATTRIBUTE_UNUSED) {
+  // Indefinite thread suspensions are not OK if we're supposed to be JIT-compiling for other
+  // processes.  We only care about JIT compilation that affects other processes.  The zygote
+  // itself doesn't run appreciable amounts of Java code when running single-threaded, so
+  // suspending the JIT in non-jit-zygote mode is OK.
+  // TODO: Make this potentially return true once we're done with JIT compilation in JIT Zygote.
+  // Only called in zygote. Thus static is OK here.
+  static bool isJitZygote = jit::Jit::InZygoteUsingJit();
+  static bool explicitlyDisabled = Runtime::Current()->IsJavaZygoteForkLoopRequired();
+  return (isJitZygote || explicitlyDisabled) ? JNI_FALSE : JNI_TRUE;
+}
+
+
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(ZygoteHooks, nativePreFork, "()J"),
   NATIVE_METHOD(ZygoteHooks, nativePostZygoteFork, "()V"),
   NATIVE_METHOD(ZygoteHooks, nativePostForkSystemServer, "(I)V"),
   NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JIZZLjava/lang/String;)V"),
+  NATIVE_METHOD(ZygoteHooks, nativeZygoteLongSuspendOk, "()Z"),
   NATIVE_METHOD(ZygoteHooks, startZygoteNoThreadCreation, "()V"),
   NATIVE_METHOD(ZygoteHooks, stopZygoteNoThreadCreation, "()V"),
 };
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 2c537c6..776b14f 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -22,8 +22,9 @@
 #include "art_method-inl.h"
 #include "base/enums.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "common_throws.h"
+#include "compat_framework.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_annotations.h"
@@ -33,7 +34,7 @@
 #include "mirror/class-alloc-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
-#include "mirror/field-inl.h"
+#include "mirror/field.h"
 #include "mirror/method.h"
 #include "mirror/method_handles_lookup.h"
 #include "mirror/object-inl.h"
@@ -56,9 +57,9 @@
 
 namespace art {
 
-// Should be the same as dalvik.system.VMRuntime.PREVENT_META_REFLECTION_BLACKLIST_ACCESS.
+// Should be the same as dalvik.system.VMRuntime.PREVENT_META_REFLECTION_BLOCKLIST_ACCESS.
 // Corresponds to a bug id.
-static constexpr uint64_t kPreventMetaReflectionBlacklistAccess = 142365358;
+static constexpr uint64_t kPreventMetaReflectionBlocklistAccess = 142365358;
 
 // Walks the stack, finds the caller of this reflective call and returns
 // a hiddenapi AccessContext formed from its declaring class.
@@ -104,8 +105,9 @@
         // and walking over this frame would cause a null pointer dereference
         // (e.g. in 691-hiddenapi-proxy).
         ObjPtr<mirror::Class> proxy_class = GetClassRoot<mirror::Proxy>();
+        CompatFramework& compat_framework = Runtime::Current()->GetCompatFramework();
         if (declaring_class->IsInSamePackage(proxy_class) && declaring_class != proxy_class) {
-          if (Runtime::Current()->isChangeEnabled(kPreventMetaReflectionBlacklistAccess)) {
+          if (compat_framework.IsChangeEnabled(kPreventMetaReflectionBlocklistAccess)) {
             return true;
           }
         }
@@ -312,7 +314,7 @@
   for (ArtField& field : ifields) {
     if (IsDiscoverable(public_only, hiddenapi_context, &field)) {
       ObjPtr<mirror::Field> reflect_field =
-          mirror::Field::CreateFromArtField<kRuntimePointerSize>(self, &field, force_resolve);
+          mirror::Field::CreateFromArtField(self, &field, force_resolve);
       if (reflect_field == nullptr) {
         if (kIsDebugBuild) {
           self->AssertPendingException();
@@ -326,7 +328,7 @@
   for (ArtField& field : sfields) {
     if (IsDiscoverable(public_only, hiddenapi_context, &field)) {
       ObjPtr<mirror::Field> reflect_field =
-          mirror::Field::CreateFromArtField<kRuntimePointerSize>(self, &field, force_resolve);
+          mirror::Field::CreateFromArtField(self, &field, force_resolve);
       if (reflect_field == nullptr) {
         if (kIsDebugBuild) {
           self->AssertPendingException();
@@ -417,11 +419,11 @@
   }
   ArtField* art_field = FindFieldByName(name, c->GetIFieldsPtr());
   if (art_field != nullptr) {
-    return mirror::Field::CreateFromArtField<kRuntimePointerSize>(self, art_field, true);
+    return mirror::Field::CreateFromArtField(self, art_field, true);
   }
   art_field = FindFieldByName(name, c->GetSFieldsPtr());
   if (art_field != nullptr) {
-    return mirror::Field::CreateFromArtField<kRuntimePointerSize>(self, art_field, true);
+    return mirror::Field::CreateFromArtField(self, art_field, true);
   }
   return nullptr;
 }
@@ -540,10 +542,10 @@
     return nullptr;
   }
   Handle<mirror::Constructor> result = hs.NewHandle(
-      mirror::Class::GetDeclaredConstructorInternal<kRuntimePointerSize, false>(
-      soa.Self(),
-      klass,
-      soa.Decode<mirror::ObjectArray<mirror::Class>>(args)));
+      mirror::Class::GetDeclaredConstructorInternal<kRuntimePointerSize>(
+          soa.Self(),
+          klass,
+          soa.Decode<mirror::ObjectArray<mirror::Class>>(args)));
   if (result == nullptr || ShouldDenyAccessToMember(result->GetArtMethod(), soa.Self())) {
     return nullptr;
   }
@@ -588,7 +590,7 @@
       DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
       DCHECK(!Runtime::Current()->IsActiveTransaction());
       ObjPtr<mirror::Constructor> constructor =
-          mirror::Constructor::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), &m);
+          mirror::Constructor::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), &m);
       if (UNLIKELY(constructor == nullptr)) {
         soa.Self()->AssertPendingOOMException();
         return nullptr;
@@ -611,7 +613,7 @@
     return nullptr;
   }
   Handle<mirror::Method> result = hs.NewHandle(
-      mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(
+      mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize>(
           soa.Self(),
           klass,
           soa.Decode<mirror::String>(name),
@@ -659,7 +661,7 @@
       DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
       DCHECK(!Runtime::Current()->IsActiveTransaction());
       ObjPtr<mirror::Method> method =
-          mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), &m);
+          mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), &m);
       if (method == nullptr) {
         soa.Self()->AssertPendingException();
         return nullptr;
diff --git a/runtime/native/java_lang_String.cc b/runtime/native/java_lang_String.cc
index 7c7c553..86f9329 100644
--- a/runtime/native/java_lang_String.cc
+++ b/runtime/native/java_lang_String.cc
@@ -60,8 +60,7 @@
   int32_t length_this = string_this->GetLength();
   int32_t length_arg = string_arg->GetLength();
   if (length_arg > 0 && length_this > 0) {
-    ObjPtr<mirror::String> result =
-        mirror::String::AllocFromStrings(soa.Self(), string_this, string_arg);
+    ObjPtr<mirror::String> result = mirror::String::DoConcat(soa.Self(), string_this, string_arg);
     return soa.AddLocalReference<jstring>(result);
   }
   jobject string_original = (length_this == 0) ? java_string_arg : java_this;
diff --git a/runtime/native/java_lang_StringFactory.cc b/runtime/native/java_lang_StringFactory.cc
index 178d5da..9086ee9 100644
--- a/runtime/native/java_lang_StringFactory.cc
+++ b/runtime/native/java_lang_StringFactory.cc
@@ -89,10 +89,186 @@
   return soa.AddLocalReference<jstring>(result);
 }
 
+static jstring StringFactory_newStringFromUtf8Bytes(JNIEnv* env, jclass, jbyteArray java_data,
+                                                    jint offset, jint byte_count) {
+  // Local Define in here
+  static const jchar kReplacementChar = 0xfffd;
+  static const int kDefaultBufferSize = 256;
+  static const int kTableUtf8Needed[] = {
+    //      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
+    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 0xc0 - 0xcf
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 0xd0 - 0xdf
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,  // 0xe0 - 0xef
+    3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 0xf0 - 0xff
+  };
+
+  ScopedFastNativeObjectAccess soa(env);
+  if (UNLIKELY(java_data == nullptr)) {
+    ThrowNullPointerException("data == null");
+    return nullptr;
+  }
+
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::ByteArray> byte_array(hs.NewHandle(soa.Decode<mirror::ByteArray>(java_data)));
+  int32_t data_size = byte_array->GetLength();
+  if ((offset | byte_count) < 0 || byte_count > data_size - offset) {
+    soa.Self()->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;",
+        "length=%d; regionStart=%d; regionLength=%d", data_size,
+        offset, byte_count);
+    return nullptr;
+  }
+
+  /*
+   * This code converts a UTF-8 byte sequence to a Java String (UTF-16).
+   * It implements the W3C recommended UTF-8 decoder.
+   * https://www.w3.org/TR/encoding/#utf-8-decoder
+   *
+   * Unicode 3.2 Well-Formed UTF-8 Byte Sequences
+   * Code Points        First  Second Third Fourth
+   * U+0000..U+007F     00..7F
+   * U+0080..U+07FF     C2..DF 80..BF
+   * U+0800..U+0FFF     E0     A0..BF 80..BF
+   * U+1000..U+CFFF     E1..EC 80..BF 80..BF
+   * U+D000..U+D7FF     ED     80..9F 80..BF
+   * U+E000..U+FFFF     EE..EF 80..BF 80..BF
+   * U+10000..U+3FFFF   F0     90..BF 80..BF 80..BF
+   * U+40000..U+FFFFF   F1..F3 80..BF 80..BF 80..BF
+   * U+100000..U+10FFFF F4     80..8F 80..BF 80..BF
+   *
+   * Please refer to Unicode as the authority.
+   * p.126 Table 3-7 in http://www.unicode.org/versions/Unicode10.0.0/ch03.pdf
+   *
+   * Handling Malformed Input
+   * The maximal subpart should be replaced by a single U+FFFD. Maximal subpart is
+   * the longest code unit subsequence starting at an unconvertible offset that is either
+   * 1) the initial subsequence of a well-formed code unit sequence, or
+   * 2) a subsequence of length one:
+   * One U+FFFD should be emitted for every sequence of bytes that is an incomplete prefix
+   * of a valid sequence, and with the conversion to restart after the incomplete sequence.
+   *
+   * For example, in byte sequence "41 C0 AF 41 F4 80 80 41", the maximal subparts are
+   * "C0", "AF", and "F4 80 80". "F4 80 80" can be the initial subsequence of "F4 80 80 80",
+   * but "C0" can't be the initial subsequence of any well-formed code unit sequence.
+   * Thus, the output should be "A\ufffd\ufffdA\ufffdA".
+   *
+   * Please refer to section "Best Practices for Using U+FFFD." in
+   * http://www.unicode.org/versions/Unicode10.0.0/ch03.pdf
+   */
+
+  // Initial value
+  jchar stack_buffer[kDefaultBufferSize];
+  std::unique_ptr<jchar[]> allocated_buffer;
+  jchar* v;
+  if (byte_count <= kDefaultBufferSize) {
+    v = stack_buffer;
+  } else {
+    allocated_buffer.reset(new jchar[byte_count]);
+    v = allocated_buffer.get();
+  }
+
+  jbyte* d = byte_array->GetData();
+  DCHECK(d != nullptr);
+
+  int idx = offset;
+  int last = offset + byte_count;
+  int s = 0;
+
+  int code_point = 0;
+  int utf8_bytes_seen = 0;
+  int utf8_bytes_needed = 0;
+  int lower_bound = 0x80;
+  int upper_bound = 0xbf;
+  while (idx < last) {
+    int b = d[idx++] & 0xff;
+    if (utf8_bytes_needed == 0) {
+      if ((b & 0x80) == 0) {  // ASCII char. 0xxxxxxx
+        v[s++] = (jchar) b;
+        continue;
+      }
+
+      if ((b & 0x40) == 0) {  // 10xxxxxx is illegal as first byte
+        v[s++] = kReplacementChar;
+        continue;
+      }
+
+      // 11xxxxxx
+      int tableLookupIndex = b & 0x3f;
+      utf8_bytes_needed = kTableUtf8Needed[tableLookupIndex];
+      if (utf8_bytes_needed == 0) {
+        v[s++] = kReplacementChar;
+        continue;
+      }
+
+      // utf8_bytes_needed
+      // 1: b & 0x1f
+      // 2: b & 0x0f
+      // 3: b & 0x07
+      code_point = b & (0x3f >> utf8_bytes_needed);
+      if (b == 0xe0) {
+        lower_bound = 0xa0;
+      } else if (b == 0xed) {
+        upper_bound = 0x9f;
+      } else if (b == 0xf0) {
+        lower_bound = 0x90;
+      } else if (b == 0xf4) {
+        upper_bound = 0x8f;
+      }
+    } else {
+      if (b < lower_bound || b > upper_bound) {
+        // The bytes seen are ill-formed. Substitute them with U+FFFD
+        v[s++] = kReplacementChar;
+        code_point = 0;
+        utf8_bytes_needed = 0;
+        utf8_bytes_seen = 0;
+        lower_bound = 0x80;
+        upper_bound = 0xbf;
+        /*
+         * According to the Unicode Standard,
+         * "a UTF-8 conversion process is required to never consume well-formed
+         * subsequences as part of its error handling for ill-formed subsequences"
+         * The current byte could be part of well-formed subsequences. Reduce the
+         * index by 1 to parse it in next loop.
+         */
+        idx--;
+        continue;
+      }
+
+      lower_bound = 0x80;
+      upper_bound = 0xbf;
+      code_point = (code_point << 6) | (b & 0x3f);
+      utf8_bytes_seen++;
+      if (utf8_bytes_needed != utf8_bytes_seen) {
+        continue;
+      }
+
+      // Encode chars from U+10000 up as surrogate pairs
+      if (code_point < 0x10000) {
+        v[s++] = (jchar) code_point;
+      } else {
+        v[s++] = (jchar) ((code_point >> 10) + 0xd7c0);
+        v[s++] = (jchar) ((code_point & 0x3ff) + 0xdc00);
+      }
+
+      utf8_bytes_seen = 0;
+      utf8_bytes_needed = 0;
+      code_point = 0;
+    }
+  }
+
+  // The bytes seen are ill-formed. Substitute them by U+FFFD
+  if (utf8_bytes_needed != 0) {
+    v[s++] = kReplacementChar;
+  }
+
+  ObjPtr<mirror::String> result = mirror::String::AllocFromUtf16(soa.Self(), s, v);
+  return soa.AddLocalReference<jstring>(result);
+}
+
 static JNINativeMethod gMethods[] = {
   FAST_NATIVE_METHOD(StringFactory, newStringFromBytes, "([BIII)Ljava/lang/String;"),
   FAST_NATIVE_METHOD(StringFactory, newStringFromChars, "(II[C)Ljava/lang/String;"),
   FAST_NATIVE_METHOD(StringFactory, newStringFromString, "(Ljava/lang/String;)Ljava/lang/String;"),
+  FAST_NATIVE_METHOD(StringFactory, newStringFromUtf8Bytes, "([BII)Ljava/lang/String;"),
 };
 
 void register_java_lang_StringFactory(JNIEnv* env) {
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index 5f21998..37b3fe6 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -112,13 +112,6 @@
   return -1;  // Unreachable.
 }
 
-static jint Thread_getNativeTid(JNIEnv* env, jobject java_thread) {
-  ScopedFastNativeObjectAccess soa(env);
-  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
-  Thread* thread = Thread::FromManagedThread(soa, java_thread);
-  return (thread != nullptr) ? thread->GetTid() : 0;
-}
-
 static jboolean Thread_holdsLock(JNIEnv* env, jclass, jobject java_object) {
   ScopedObjectAccess soa(env);
   ObjPtr<mirror::Object> object = soa.Decode<mirror::Object>(java_object);
@@ -205,7 +198,6 @@
   FAST_NATIVE_METHOD(Thread, currentThread, "()Ljava/lang/Thread;"),
   FAST_NATIVE_METHOD(Thread, interrupted, "()Z"),
   FAST_NATIVE_METHOD(Thread, isInterrupted, "()Z"),
-  FAST_NATIVE_METHOD(Thread, getNativeTid, "()I"),
   NATIVE_METHOD(Thread, nativeCreate, "(Ljava/lang/Thread;JZ)V"),
   NATIVE_METHOD(Thread, nativeGetStatus, "(Z)I"),
   NATIVE_METHOD(Thread, holdsLock, "(Ljava/lang/Object;)Z"),
diff --git a/runtime/native/java_lang_Throwable.cc b/runtime/native/java_lang_Throwable.cc
index b5ef7d8..b89e287 100644
--- a/runtime/native/java_lang_Throwable.cc
+++ b/runtime/native/java_lang_Throwable.cc
@@ -27,7 +27,7 @@
 
 static jobject Throwable_nativeFillInStackTrace(JNIEnv* env, jclass) {
   ScopedFastNativeObjectAccess soa(env);
-  return soa.Self()->CreateInternalStackTrace<false>(soa);
+  return soa.Self()->CreateInternalStackTrace(soa);
 }
 
 static jobjectArray Throwable_nativeGetStackTrace(JNIEnv* env, jclass, jobject javaStackState) {
diff --git a/runtime/native/java_lang_invoke_MethodHandleImpl.cc b/runtime/native/java_lang_invoke_MethodHandleImpl.cc
index 0b26bd7..45d9a8a 100644
--- a/runtime/native/java_lang_invoke_MethodHandleImpl.cc
+++ b/runtime/native/java_lang_invoke_MethodHandleImpl.cc
@@ -40,23 +40,18 @@
   // a Method for method invokers and a Constructor for constructors.
   const mirror::MethodHandle::Kind handle_kind = handle->GetHandleKind();
 
-  // We check this here because we pass false to CreateFromArtField and
-  // CreateFromArtMethod.
-  DCHECK(!Runtime::Current()->IsActiveTransaction());
-
   MutableHandle<mirror::Object> h_object(hs.NewHandle<mirror::Object>(nullptr));
   if (handle_kind >= mirror::MethodHandle::kFirstAccessorKind) {
     ArtField* const field = handle->GetTargetField();
-    h_object.Assign(mirror::Field::CreateFromArtField<kRuntimePointerSize, false>(
-        soa.Self(), field, /* force_resolve= */ false));
+    h_object.Assign(
+        mirror::Field::CreateFromArtField(soa.Self(), field, /* force_resolve= */ false));
   } else {
     ArtMethod* const method = handle->GetTargetMethod();
     if (method->IsConstructor()) {
-      h_object.Assign(mirror::Constructor::CreateFromArtMethod<kRuntimePointerSize, false>(
-          soa.Self(), method));
+      h_object.Assign(
+          mirror::Constructor::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), method));
     } else {
-      h_object.Assign(mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(
-          soa.Self(), method));
+      h_object.Assign(mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), method));
     }
   }
 
diff --git a/runtime/native/java_lang_ref_Reference.cc b/runtime/native/java_lang_ref_Reference.cc
index b241b1d..f23010b 100644
--- a/runtime/native/java_lang_ref_Reference.cc
+++ b/runtime/native/java_lang_ref_Reference.cc
@@ -36,6 +36,37 @@
   return soa.AddLocalReference<jobject>(referent);
 }
 
+static jboolean Reference_refersTo0(JNIEnv* env, jobject javaThis, jobject o) {
+  if (kUseReadBarrier && !kUseBakerReadBarrier) {
+    // Fall back to naive implementation that may block and needlessly preserve javaThis.
+    return env->IsSameObject(Reference_getReferent(env, javaThis), o);
+  }
+  ScopedFastNativeObjectAccess soa(env);
+  const ObjPtr<mirror::Reference> ref = soa.Decode<mirror::Reference>(javaThis);
+  const ObjPtr<mirror::Object> other = soa.Decode<mirror::Reference>(o);
+  const ObjPtr<mirror::Object> referent = ref->template GetReferent<kWithoutReadBarrier>();
+  if (referent == other) {
+      return JNI_TRUE;
+  }
+  if (!kUseReadBarrier || referent.IsNull() || other.IsNull()) {
+    return JNI_FALSE;
+  }
+  // Explicitly handle the case in which referent is a from-space pointer.  Don't use a
+  // read-barrier, since that could easily mark an object we no longer need and, since it
+  // creates new gray objects, may not be safe without blocking.
+  //
+  // ConcurrentCopying::Copy ensure that whenever a pointer to a to_space object is published,
+  // the forwarding pointer is also visible. We need that guarantee to ensure that if referent
+  // == other and referent is in from-space, then referent has a forwarding pointer. In order to
+  // use that guarantee, we need to ensure that the forwarding pointer is loaded after we
+  // retrieved other. Hence this fence:
+  atomic_thread_fence(std::memory_order_acquire);
+  // Note: On ARM, the above could be replaced by an asm fake-dependency hack to make
+  // referent appear to depend on other. That would be faster and uglier.
+  return gc::collector::ConcurrentCopying::GetFwdPtrUnchecked(referent.Ptr()) == other.Ptr() ?
+      JNI_TRUE : JNI_FALSE;
+}
+
 static void Reference_clearReferent(JNIEnv* env, jobject javaThis) {
   ScopedFastNativeObjectAccess soa(env);
   const ObjPtr<mirror::Reference> ref = soa.Decode<mirror::Reference>(javaThis);
@@ -45,6 +76,7 @@
 static JNINativeMethod gMethods[] = {
   FAST_NATIVE_METHOD(Reference, getReferent, "()Ljava/lang/Object;"),
   FAST_NATIVE_METHOD(Reference, clearReferent, "()V"),
+  FAST_NATIVE_METHOD(Reference, refersTo0, "(Ljava/lang/Object;)Z"),
 };
 
 void register_java_lang_ref_Reference(JNIEnv* env) {
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index f9cdc36..1d362c0 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -21,7 +21,7 @@
 #include "art_method-inl.h"
 #include "base/enums.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/dex_file_annotations.h"
 #include "jni/jni_internal.h"
 #include "mirror/class-alloc-inl.h"
@@ -105,7 +105,7 @@
 
   // String constructor is replaced by a StringFactory method in InvokeMethod.
   if (UNLIKELY(c->IsStringClass())) {
-    return InvokeMethod(soa, javaMethod, nullptr, javaArgs, 2);
+    return InvokeMethod<kRuntimePointerSize>(soa, javaMethod, nullptr, javaArgs, 2);
   }
 
   ObjPtr<mirror::Object> receiver =
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index 2ce56b5..fef16b9 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -20,7 +20,7 @@
 #include "nativehelper/jni_macros.h"
 
 #include "art_method-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/dex_file_annotations.h"
 #include "handle.h"
 #include "jni/jni_internal.h"
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 42b6c22..cfc4a29 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -26,6 +26,7 @@
 #include "common_throws.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_annotations.h"
+#include "gc/reference_processor.h"
 #include "jni/jni_internal.h"
 #include "jvalue-inl.h"
 #include "mirror/class-inl.h"
@@ -74,7 +75,8 @@
 }
 
 template<bool kAllowReferences>
-ALWAYS_INLINE inline static bool GetFieldValue(ObjPtr<mirror::Object> o,
+ALWAYS_INLINE inline static bool GetFieldValue(const ScopedFastNativeObjectAccess& soa,
+                                               ObjPtr<mirror::Object> o,
                                                ObjPtr<mirror::Field> f,
                                                Primitive::Type field_type,
                                                JValue* value)
@@ -105,8 +107,20 @@
       return true;
     case Primitive::kPrimNot:
       if (kAllowReferences) {
-        value->SetL(is_volatile ? o->GetFieldObjectVolatile<mirror::Object>(offset) :
-            o->GetFieldObject<mirror::Object>(offset));
+        // We need to ensure that a Reference-type object's referent is fetched
+        // via GetReferent and not directly using a read-barrier (See b/174433134)
+        const uint32_t class_flags = o->GetClass()->GetClassFlags();
+        if (UNLIKELY((class_flags & mirror::kClassFlagReference) != 0 &&
+                     mirror::Reference::ReferentOffset() == offset)) {
+          // PhantomReference's get() always returns null.
+          value->SetL((class_flags & mirror::kClassFlagPhantomReference) != 0
+                          ? nullptr
+                          : Runtime::Current()->GetHeap()->GetReferenceProcessor()->GetReferent(
+                                  soa.Self(), o->AsReference()));
+        } else {
+          value->SetL(is_volatile ? o->GetFieldObjectVolatile<mirror::Object>(offset) :
+                      o->GetFieldObject<mirror::Object>(offset));
+        }
         return true;
       }
       // Else break to report an error.
@@ -169,7 +183,7 @@
   // Get the field's value, boxing if necessary.
   Primitive::Type field_type = f->GetTypeAsPrimitiveType();
   JValue value;
-  if (!GetFieldValue<true>(o, f, field_type, &value)) {
+  if (!GetFieldValue<true>(soa, o, f, field_type, &value)) {
     DCHECK(soa.Self()->IsExceptionPending());
     return nullptr;
   }
@@ -200,13 +214,13 @@
   JValue field_value;
   if (field_type == kPrimitiveType) {
     // This if statement should get optimized out since we only pass in valid primitive types.
-    if (UNLIKELY(!GetFieldValue<false>(o, f, kPrimitiveType, &field_value))) {
+    if (UNLIKELY(!GetFieldValue<false>(soa, o, f, kPrimitiveType, &field_value))) {
       DCHECK(soa.Self()->IsExceptionPending());
       return JValue();
     }
     return field_value;
   }
-  if (!GetFieldValue<false>(o, f, field_type, &field_value)) {
+  if (!GetFieldValue<false>(soa, o, f, field_type, &field_value)) {
     DCHECK(soa.Self()->IsExceptionPending());
     return JValue();
   }
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 0d9a257..2c0dd80 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -22,7 +22,7 @@
 #include "base/enums.h"
 #include "class_linker-inl.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "dex/dex_file_annotations.h"
 #include "jni/jni_internal.h"
 #include "mirror/class-inl.h"
@@ -83,7 +83,7 @@
 static jobject Method_invoke(JNIEnv* env, jobject javaMethod, jobject javaReceiver,
                              jobjectArray javaArgs) {
   ScopedFastNativeObjectAccess soa(env);
-  return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs);
+  return InvokeMethod<kRuntimePointerSize>(soa, javaMethod, javaReceiver, javaArgs);
 }
 
 static JNINativeMethod gMethods[] = {
diff --git a/runtime/native/libcore_util_CharsetUtils.cc b/runtime/native/libcore_util_CharsetUtils.cc
index 95e0d79..f0764f1 100644
--- a/runtime/native/libcore_util_CharsetUtils.cc
+++ b/runtime/native/libcore_util_CharsetUtils.cc
@@ -30,87 +30,6 @@
 
 namespace art {
 
-/**
- * Approximates java.lang.UnsafeByteSequence so we don't have to pay the cost of calling back into
- * Java when converting a char[] to a UTF-8 byte[]. This lets us have UTF-8 conversions slightly
- * faster than ICU for large char[]s without paying for the NIO overhead with small char[]s.
- *
- * We could avoid this by keeping the UTF-8 bytes on the native heap until we're done and only
- * creating a byte[] on the Java heap when we know how big it needs to be, but one shouldn't lie
- * to the garbage collector (nor hide potentially large allocations from it).
- *
- * Because a call to append might require an allocation, it might fail. Callers should always
- * check the return value of append.
- */
-class NativeUnsafeByteSequence {
- public:
-  explicit NativeUnsafeByteSequence(JNIEnv* env)
-    : mEnv(env), mJavaArray(nullptr), mRawArray(nullptr), mSize(-1), mOffset(0) {
-  }
-
-  ~NativeUnsafeByteSequence() {
-    // Release our pointer to the raw array, copying changes back to the Java heap.
-    if (mRawArray != nullptr) {
-      mEnv->ReleaseByteArrayElements(mJavaArray, mRawArray, 0);
-    }
-  }
-
-  bool append(jbyte b) {
-    if (mOffset == mSize && !resize(mSize * 2)) {
-      return false;
-    }
-    mRawArray[mOffset++] = b;
-    return true;
-  }
-
-  bool resize(int newSize) {
-    if (newSize == mSize) {
-      return true;
-    }
-
-    // Allocate a new array.
-    jbyteArray newJavaArray = mEnv->NewByteArray(newSize);
-    if (newJavaArray == nullptr) {
-      return false;
-    }
-    jbyte* newRawArray = mEnv->GetByteArrayElements(newJavaArray, nullptr);
-    if (newRawArray == nullptr) {
-      return false;
-    }
-
-    // Copy data out of the old array and then let go of it.
-    // Note that we may be trimming the array.
-    if (mRawArray != nullptr) {
-      memcpy(newRawArray, mRawArray, mOffset);
-      mEnv->ReleaseByteArrayElements(mJavaArray, mRawArray, JNI_ABORT);
-      mEnv->DeleteLocalRef(mJavaArray);
-    }
-
-    // Point ourselves at the new array.
-    mJavaArray = newJavaArray;
-    mRawArray = newRawArray;
-    mSize = newSize;
-    return true;
-  }
-
-  jbyteArray toByteArray() {
-    // Trim any unused space, if necessary.
-    bool okay = resize(mOffset);
-    return okay ? mJavaArray : nullptr;
-  }
-
- private:
-  JNIEnv* mEnv;
-  jbyteArray mJavaArray;
-  jbyte* mRawArray;
-  jint mSize;
-  jint mOffset;
-
-  // Disallow copy and assignment.
-  NativeUnsafeByteSequence(const NativeUnsafeByteSequence&);
-  void operator=(const NativeUnsafeByteSequence&);
-};
-
 static void CharsetUtils_asciiBytesToChars(JNIEnv* env, jclass, jbyteArray javaBytes, jint offset,
                                            jint length, jcharArray javaChars) {
   ScopedByteArrayRO bytes(env, javaBytes);
@@ -156,29 +75,30 @@
  */
 static jbyteArray charsToBytes(JNIEnv* env, jstring java_string, jint offset, jint length,
                                jchar maxValidChar) {
-  ScopedObjectAccess soa(env);
+  ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
   Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String>(java_string)));
   if (string == nullptr) {
     return nullptr;
   }
 
-  jbyteArray javaBytes = env->NewByteArray(length);
-  ScopedByteArrayRW bytes(env, javaBytes);
-  if (bytes.get() == nullptr) {
+  ObjPtr<mirror::ByteArray> result = mirror::ByteArray::Alloc(soa.Self(), length);
+  if (result == nullptr) {
     return nullptr;
   }
 
-  jbyte* dst = &bytes[0];
-  for (int i = 0; i < length; ++i) {
-    jchar ch = string->CharAt(offset + i);
-    if (ch > maxValidChar) {
-      ch = '?';
-    }
-    *dst++ = static_cast<jbyte>(ch);
+  if (string->IsCompressed()) {
+    // All characters in a compressed string are ASCII and therefore do not need a replacement.
+    DCHECK_GE(maxValidChar, 0x7f);
+    memcpy(result->GetData(), string->GetValueCompressed() + offset, length);
+  } else {
+    const uint16_t* src = string->GetValue() + offset;
+    auto clamp = [maxValidChar](uint16_t c) {
+      return static_cast<jbyte>(dchecked_integral_cast<uint8_t>((c > maxValidChar) ? '?' : c));
+    };
+    std::transform(src, src + length, result->GetData(), clamp);
   }
-
-  return javaBytes;
+  return soa.AddLocalReference<jbyteArray>(result);
 }
 
 static jbyteArray CharsetUtils_toAsciiBytes(JNIEnv* env, jclass, jstring java_string, jint offset,
@@ -193,63 +113,74 @@
 
 static jbyteArray CharsetUtils_toUtf8Bytes(JNIEnv* env, jclass, jstring java_string, jint offset,
                                            jint length) {
-  ScopedObjectAccess soa(env);
+  ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
   Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String>(java_string)));
   if (string == nullptr) {
     return nullptr;
   }
 
-  NativeUnsafeByteSequence out(env);
-  if (!out.resize(length)) {
+  DCHECK_GE(offset, 0);
+  DCHECK_LE(offset, string->GetLength());
+  DCHECK_GE(length, 0);
+  DCHECK_LE(length, string->GetLength() - offset);
+
+  auto visit_chars16 = [string, offset, length](auto append) REQUIRES_SHARED(Locks::mutator_lock_) {
+    const uint16_t* chars16 = string->GetValue() + offset;
+    for (int i = 0; i < length; ++i) {
+      jint ch = chars16[i];
+      if (ch < 0x80) {
+        // One byte.
+        append(ch);
+      } else if (ch < 0x800) {
+        // Two bytes.
+        append((ch >> 6) | 0xc0);
+        append((ch & 0x3f) | 0x80);
+      } else if (U16_IS_SURROGATE(ch)) {
+        // A supplementary character.
+        jchar high = static_cast<jchar>(ch);
+        jchar low = (i + 1 != length) ? chars16[i + 1] : 0;
+        if (!U16_IS_SURROGATE_LEAD(high) || !U16_IS_SURROGATE_TRAIL(low)) {
+          append('?');
+          continue;
+        }
+        // Now we know we have a *valid* surrogate pair, we can consume the low surrogate.
+        ++i;
+        ch = U16_GET_SUPPLEMENTARY(high, low);
+        // Four bytes.
+        append((ch >> 18) | 0xf0);
+        append(((ch >> 12) & 0x3f) | 0x80);
+        append(((ch >> 6) & 0x3f) | 0x80);
+        append((ch & 0x3f) | 0x80);
+      } else {
+        // Three bytes.
+        append((ch >> 12) | 0xe0);
+        append(((ch >> 6) & 0x3f) | 0x80);
+        append((ch & 0x3f) | 0x80);
+      }
+    }
+  };
+
+  bool compressed = string->IsCompressed();
+  size_t utf8_length = 0;
+  if (compressed) {
+    utf8_length = length;
+  } else {
+    visit_chars16([&utf8_length](jbyte c ATTRIBUTE_UNUSED) { ++utf8_length; });
+  }
+  ObjPtr<mirror::ByteArray> result =
+      mirror::ByteArray::Alloc(soa.Self(), dchecked_integral_cast<int32_t>(utf8_length));
+  if (result == nullptr) {
     return nullptr;
   }
 
-  const int end = offset + length;
-  for (int i = offset; i < end; ++i) {
-    jint ch = string->CharAt(i);
-    if (ch < 0x80) {
-      // One byte.
-      if (!out.append(ch)) {
-        return nullptr;
-      }
-    } else if (ch < 0x800) {
-      // Two bytes.
-      if (!out.append((ch >> 6) | 0xc0) || !out.append((ch & 0x3f) | 0x80)) {
-        return nullptr;
-      }
-    } else if (U16_IS_SURROGATE(ch)) {
-      // A supplementary character.
-      jchar high = static_cast<jchar>(ch);
-      jchar low = (i + 1 != end) ? string->CharAt(i + 1) : 0;
-      if (!U16_IS_SURROGATE_LEAD(high) || !U16_IS_SURROGATE_TRAIL(low)) {
-        if (!out.append('?')) {
-          return nullptr;
-        }
-        continue;
-      }
-      // Now we know we have a *valid* surrogate pair, we can consume the low surrogate.
-      ++i;
-      ch = U16_GET_SUPPLEMENTARY(high, low);
-      // Four bytes.
-      jbyte b1 = (ch >> 18) | 0xf0;
-      jbyte b2 = ((ch >> 12) & 0x3f) | 0x80;
-      jbyte b3 = ((ch >> 6) & 0x3f) | 0x80;
-      jbyte b4 = (ch & 0x3f) | 0x80;
-      if (!out.append(b1) || !out.append(b2) || !out.append(b3) || !out.append(b4)) {
-        return nullptr;
-      }
-    } else {
-      // Three bytes.
-      jbyte b1 = (ch >> 12) | 0xe0;
-      jbyte b2 = ((ch >> 6) & 0x3f) | 0x80;
-      jbyte b3 = (ch & 0x3f) | 0x80;
-      if (!out.append(b1) || !out.append(b2) || !out.append(b3)) {
-        return nullptr;
-      }
-    }
+  if (compressed) {
+    memcpy(result->GetData(), string->GetValueCompressed() + offset, length);
+  } else {
+    int8_t* data = result->GetData();
+    visit_chars16([&data](jbyte c) { *data++ = c; });
   }
-  return out.toByteArray();
+  return soa.AddLocalReference<jbyteArray>(result);
 }
 
 static JNINativeMethod gMethods[] = {
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
index d405735..f74e120 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
@@ -33,21 +33,16 @@
 
 namespace art {
 
-static Thread* GetSelf(JNIEnv* env) {
-  return static_cast<JNIEnvExt*>(env)->GetSelf();
-}
-
-static void DdmVmInternal_enableRecentAllocations(JNIEnv*, jclass, jboolean enable) {
+static void DdmVmInternal_setRecentAllocationsTrackingEnabled(JNIEnv*, jclass, jboolean enable) {
   Dbg::SetAllocTrackingEnabled(enable);
 }
 
-static jbyteArray DdmVmInternal_getRecentAllocations(JNIEnv* env, jclass) {
-  ScopedFastNativeObjectAccess soa(env);
-  return Dbg::GetRecentAllocations();
+static void DdmVmInternal_setThreadNotifyEnabled(JNIEnv*, jclass, jboolean enable) {
+  Dbg::DdmSetThreadNotification(enable);
 }
 
-static jboolean DdmVmInternal_getRecentAllocationStatus(JNIEnv*, jclass) {
-  return Runtime::Current()->GetHeap()->IsAllocTrackingEnabled();
+static Thread* GetSelf(JNIEnv* env) {
+  return static_cast<JNIEnvExt*>(env)->GetSelf();
 }
 
 /*
@@ -60,7 +55,7 @@
   if (static_cast<uint32_t>(thin_lock_id) == self->GetThreadId()) {
     // No need to suspend ourself to build stacktrace.
     ScopedObjectAccess soa(env);
-    jobject internal_trace = self->CreateInternalStackTrace<false>(soa);
+    jobject internal_trace = self->CreateInternalStackTrace(soa);
     trace = Thread::InternalStackTraceToStackTraceElementArray(soa, internal_trace);
   } else {
     ThreadList* thread_list = Runtime::Current()->GetThreadList();
@@ -78,7 +73,7 @@
     if (thread != nullptr) {
       {
         ScopedObjectAccess soa(env);
-        jobject internal_trace = thread->CreateInternalStackTrace<false>(soa);
+        jobject internal_trace = thread->CreateInternalStackTrace(soa);
         trace = Thread::InternalStackTraceToStackTraceElementArray(soa, internal_trace);
       }
       // Restart suspended thread.
@@ -214,28 +209,11 @@
   return result;
 }
 
-static jboolean DdmVmInternal_heapInfoNotify(JNIEnv* env, jclass, jint when) {
-  ScopedFastNativeObjectAccess soa(env);
-  return Dbg::DdmHandleHpifChunk(static_cast<Dbg::HpifWhen>(when));
-}
-
-static jboolean DdmVmInternal_heapSegmentNotify(JNIEnv*, jclass, jint when, jint what, jboolean native) {
-  return Dbg::DdmHandleHpsgNhsgChunk(static_cast<Dbg::HpsgWhen>(when), static_cast<Dbg::HpsgWhat>(what), native);
-}
-
-static void DdmVmInternal_threadNotify(JNIEnv*, jclass, jboolean enable) {
-  Dbg::DdmSetThreadNotification(enable);
-}
-
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(DdmVmInternal, enableRecentAllocations, "(Z)V"),
-  FAST_NATIVE_METHOD(DdmVmInternal, getRecentAllocations, "()[B"),
-  FAST_NATIVE_METHOD(DdmVmInternal, getRecentAllocationStatus, "()Z"),
+  NATIVE_METHOD(DdmVmInternal, setRecentAllocationsTrackingEnabled, "(Z)V"),
+  NATIVE_METHOD(DdmVmInternal, setThreadNotifyEnabled, "(Z)V"),
   NATIVE_METHOD(DdmVmInternal, getStackTraceById, "(I)[Ljava/lang/StackTraceElement;"),
   NATIVE_METHOD(DdmVmInternal, getThreadStats, "()[B"),
-  FAST_NATIVE_METHOD(DdmVmInternal, heapInfoNotify, "(I)Z"),
-  NATIVE_METHOD(DdmVmInternal, heapSegmentNotify, "(IIZ)Z"),
-  NATIVE_METHOD(DdmVmInternal, threadNotify, "(Z)V"),
 };
 
 void register_org_apache_harmony_dalvik_ddmc_DdmVmInternal(JNIEnv* env) {
diff --git a/runtime/native_stack_dump.cc b/runtime/native_stack_dump.cc
index 74d9033..6b6663a 100644
--- a/runtime/native_stack_dump.cc
+++ b/runtime/native_stack_dump.cc
@@ -69,14 +69,12 @@
 static constexpr bool kUseAddr2line = !kIsTargetBuild;
 
 std::string FindAddr2line() {
-  if (!kIsTargetBuild) {
-    constexpr const char* kAddr2linePrebuiltPath =
-      "/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/bin/x86_64-linux-addr2line";
-    const char* env_value = getenv("ANDROID_BUILD_TOP");
-    if (env_value != nullptr) {
-      return std::string(env_value) + kAddr2linePrebuiltPath;
-    }
+#ifdef ART_CLANG_PATH
+  const char* env_value = getenv("ANDROID_BUILD_TOP");
+  if (env_value != nullptr) {
+    return std::string(env_value) + "/" + ART_CLANG_PATH + "/bin/llvm-addr2line";
   }
+#endif
   return std::string("/usr/bin/addr2line");
 }
 
@@ -274,7 +272,7 @@
   }
 
   // Send the offset.
-  const std::string hex_offset = StringPrintf("%zx\n", offset);
+  const std::string hex_offset = StringPrintf("0x%zx\n", offset);
 
   if (!pipe_ptr->out.WriteFully(hex_offset.data(), hex_offset.length())) {
     // Error. :-(
diff --git a/runtime/nterp_helpers.cc b/runtime/nterp_helpers.cc
index a2ec882..9670e6e 100644
--- a/runtime/nterp_helpers.cc
+++ b/runtime/nterp_helpers.cc
@@ -17,7 +17,7 @@
 #include "art_method-inl.h"
 #include "dex/code_item_accessors.h"
 #include "entrypoints/quick/callee_save_frame.h"
-#include "interpreter/interpreter_mterp_impl.h"
+#include "interpreter/mterp/nterp.h"
 #include "nterp_helpers.h"
 #include "oat_quick_method_header.h"
 #include "quick/quick_method_frame_info.h"
@@ -59,6 +59,8 @@
  *    ----------------      registers array for easy access from nterp when returning.
  *    |  dex_pc_ptr  |      Pointer to the dex instruction being executed.
  *    ----------------      Stored whenever nterp goes into the runtime.
+ *    |  alignment   |      Pointer aligment for dex_pc_ptr and caller_fp.
+ *    ----------------
  *    |              |      In case nterp calls compiled code, we reserve space
  *    |     out      |      for out registers. This space will be used for
  *    |   registers  |      arguments passed on stack.
@@ -83,27 +85,55 @@
 
 static constexpr size_t kPointerSize = static_cast<size_t>(kRuntimePointerSize);
 
-static constexpr size_t NterpGetFrameEntrySize() {
-  uint32_t core_spills =
-      RuntimeCalleeSaveFrame::GetCoreSpills(CalleeSaveType::kSaveAllCalleeSaves);
-  uint32_t fp_spills =
-      RuntimeCalleeSaveFrame::GetFpSpills(CalleeSaveType::kSaveAllCalleeSaves);
+static constexpr size_t NterpGetFrameEntrySize(InstructionSet isa) {
+  uint32_t core_spills = 0;
+  uint32_t fp_spills = 0;
   // Note: the return address is considered part of the callee saves.
-  return (POPCOUNT(core_spills) + POPCOUNT(fp_spills)) * kPointerSize;
+  switch (isa) {
+    case InstructionSet::kX86:
+      core_spills = x86::X86CalleeSaveFrame::GetCoreSpills(CalleeSaveType::kSaveAllCalleeSaves);
+      fp_spills = x86::X86CalleeSaveFrame::GetFpSpills(CalleeSaveType::kSaveAllCalleeSaves);
+      break;
+    case InstructionSet::kX86_64:
+      core_spills =
+          x86_64::X86_64CalleeSaveFrame::GetCoreSpills(CalleeSaveType::kSaveAllCalleeSaves);
+      fp_spills = x86_64::X86_64CalleeSaveFrame::GetFpSpills(CalleeSaveType::kSaveAllCalleeSaves);
+      break;
+    case InstructionSet::kArm:
+    case InstructionSet::kThumb2:
+      core_spills = arm::ArmCalleeSaveFrame::GetCoreSpills(CalleeSaveType::kSaveAllCalleeSaves);
+      fp_spills = arm::ArmCalleeSaveFrame::GetFpSpills(CalleeSaveType::kSaveAllCalleeSaves);
+      break;
+    case InstructionSet::kArm64:
+      core_spills = arm64::Arm64CalleeSaveFrame::GetCoreSpills(CalleeSaveType::kSaveAllCalleeSaves);
+      fp_spills = arm64::Arm64CalleeSaveFrame::GetFpSpills(CalleeSaveType::kSaveAllCalleeSaves);
+      break;
+    default:
+      InstructionSetAbort(isa);
+  }
+  // Note: the return address is considered part of the callee saves.
+  return (POPCOUNT(core_spills) + POPCOUNT(fp_spills)) *
+      static_cast<size_t>(InstructionSetPointerSize(isa));
 }
 
-size_t NterpGetFrameSize(ArtMethod* method) {
+size_t NterpGetFrameSize(ArtMethod* method, InstructionSet isa) {
   CodeItemDataAccessor accessor(method->DexInstructionData());
   const uint16_t num_regs = accessor.RegistersSize();
   const uint16_t out_regs = accessor.OutsSize();
+  size_t pointer_size = static_cast<size_t>(InstructionSetPointerSize(isa));
 
+  // Note: There may be two pieces of alignment but there is no need to align
+  // out args to `kPointerSize` separately before aligning to kStackAlignment.
+  DCHECK(IsAlignedParam(kStackAlignment, pointer_size));
+  DCHECK(IsAlignedParam(NterpGetFrameEntrySize(isa), pointer_size));
+  DCHECK(IsAlignedParam(kVRegSize * 2, pointer_size));
   size_t frame_size =
-      NterpGetFrameEntrySize() +
+      NterpGetFrameEntrySize(isa) +
       (num_regs * kVRegSize) * 2 +  // dex registers and reference registers
-      kPointerSize +  // previous frame
-      kPointerSize +  // saved dex pc
+      pointer_size +  // previous frame
+      pointer_size +  // saved dex pc
       (out_regs * kVRegSize) +  // out arguments
-      kPointerSize;  // method
+      pointer_size;  // method
   return RoundUp(frame_size, kStackAlignment);
 }
 
@@ -128,7 +158,7 @@
   // The references array is just above the saved frame pointer.
   return reinterpret_cast<uintptr_t>(frame) +
       kPointerSize +  // method
-      (out_regs * kVRegSize) +  // out arguments
+      RoundUp(out_regs * kVRegSize, kPointerSize) +  // out arguments and pointer alignment
       kPointerSize +  // saved dex pc
       kPointerSize;  // previous frame.
 }
@@ -138,7 +168,7 @@
   const uint16_t out_regs = accessor.OutsSize();
   uintptr_t dex_pc_ptr = reinterpret_cast<uintptr_t>(frame) +
       kPointerSize +  // method
-      (out_regs * kVRegSize);  // out arguments
+      RoundUp(out_regs * kVRegSize, kPointerSize);  // out arguments and pointer alignment
   CodeItemInstructionAccessor instructions((*frame)->DexInstructions());
   return *reinterpret_cast<const uint16_t**>(dex_pc_ptr) - instructions.Insns();
 }
@@ -157,4 +187,16 @@
   return reinterpret_cast<uintptr_t>(artNterpAsmInstructionEnd);
 }
 
+bool CanMethodUseNterp(ArtMethod* method, InstructionSet isa) {
+  return !method->IsNative() &&
+      method->IsInvokable() &&
+      // Nterp supports the same methods the compiler supports.
+      method->IsCompilable() &&
+      !method->MustCountLocks() &&
+      // Proxy methods do not go through the JIT like other methods, so we don't
+      // run them with nterp.
+      !method->IsProxyMethod() &&
+      NterpGetFrameSize(method, isa) <= interpreter::kNterpMaxFrame;
+}
+
 }  // namespace art
diff --git a/runtime/nterp_helpers.h b/runtime/nterp_helpers.h
index aacd178..0f9e758 100644
--- a/runtime/nterp_helpers.h
+++ b/runtime/nterp_helpers.h
@@ -26,7 +26,7 @@
 /**
  * The frame size nterp will use for the given method.
  */
-size_t NterpGetFrameSize(ArtMethod* method)
+size_t NterpGetFrameSize(ArtMethod* method, InstructionSet isa = kRuntimeISA)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 /**
@@ -74,6 +74,13 @@
 uint32_t NterpGetVRegReference(ArtMethod** frame, uint16_t vreg)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
+/**
+ * Returns whether the given method can run with nterp. The instruction set can
+ * be passed for cross-compilation.
+ */
+bool CanMethodUseNterp(ArtMethod* method, InstructionSet isa = kRuntimeISA)
+    REQUIRES_SHARED(Locks::mutator_lock_);
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_NTERP_HELPERS_H_
diff --git a/runtime/oat.cc b/runtime/oat.cc
index 17c797a..3698ddf 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -77,12 +77,13 @@
       quick_generic_jni_trampoline_offset_(0),
       quick_imt_conflict_trampoline_offset_(0),
       quick_resolution_trampoline_offset_(0),
-      quick_to_interpreter_bridge_offset_(0) {
+      quick_to_interpreter_bridge_offset_(0),
+      nterp_trampoline_offset_(0) {
   // Don't want asserts in header as they would be checked in each file that includes it. But the
   // fields are private, so we check inside a method.
-  static_assert(sizeof(magic_) == sizeof(kOatMagic),
+  static_assert(decltype(magic_)().size() == kOatMagic.size(),
                 "Oat magic and magic_ have different lengths.");
-  static_assert(sizeof(version_) == sizeof(kOatVersion),
+  static_assert(decltype(version_)().size() == kOatVersion.size(),
                 "Oat version and version_ have different lengths.");
 
   magic_ = kOatMagic;
@@ -112,13 +113,13 @@
 
 std::string OatHeader::GetValidationErrorMessage() const {
   if (magic_ != kOatMagic) {
-    static_assert(sizeof(kOatMagic) == 4, "kOatMagic has unexpected length");
+    static_assert(kOatMagic.size() == 4, "kOatMagic has unexpected length");
     return StringPrintf("Invalid oat magic, expected 0x%02x%02x%02x%02x, got 0x%02x%02x%02x%02x.",
                         kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3],
                         magic_[0], magic_[1], magic_[2], magic_[3]);
   }
   if (version_ != kOatVersion) {
-    static_assert(sizeof(kOatVersion) == 4, "kOatVersion has unexpected length");
+    static_assert(kOatVersion.size() == 4, "kOatVersion has unexpected length");
     return StringPrintf("Invalid oat version, expected 0x%02x%02x%02x%02x, got 0x%02x%02x%02x%02x.",
                         kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3],
                         version_[0], version_[1], version_[2], version_[3]);
@@ -306,6 +307,24 @@
   quick_to_interpreter_bridge_offset_ = offset;
 }
 
+const void* OatHeader::GetNterpTrampoline() const {
+  return GetTrampoline(*this, GetNterpTrampolineOffset());
+}
+
+uint32_t OatHeader::GetNterpTrampolineOffset() const {
+  DCHECK(IsValid());
+  CHECK_GE(nterp_trampoline_offset_, quick_to_interpreter_bridge_offset_);
+  return nterp_trampoline_offset_;
+}
+
+void OatHeader::SetNterpTrampolineOffset(uint32_t offset) {
+  CHECK(offset == 0 || offset >= quick_to_interpreter_bridge_offset_);
+  DCHECK(IsValid());
+  DCHECK_EQ(nterp_trampoline_offset_, 0U) << offset;
+
+  nterp_trampoline_offset_ = offset;
+}
+
 uint32_t OatHeader::GetKeyValueStoreSize() const {
   CHECK(IsValid());
   return key_value_store_size_;
@@ -316,65 +335,66 @@
   return key_value_store_;
 }
 
-// Advance start until it is either end or \0.
-static const char* ParseString(const char* start, const char* end) {
-  while (start < end && *start != 0) {
-    start++;
-  }
-  return start;
-}
-
 const char* OatHeader::GetStoreValueByKey(const char* key) const {
+  std::string_view key_view(key);
   const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
   const char* end = ptr + key_value_store_size_;
 
   while (ptr < end) {
     // Scan for a closing zero.
-    const char* str_end = ParseString(ptr, end);
-    if (str_end < end) {
-      if (strcmp(key, ptr) == 0) {
-        // Same as key. Check if value is OK.
-        if (ParseString(str_end + 1, end) < end) {
-          return str_end + 1;
-        }
-      } else {
-        // Different from key. Advance over the value.
-        ptr = ParseString(str_end + 1, end) + 1;
-      }
-    } else {
-      break;
+    const char* str_end = reinterpret_cast<const char*>(memchr(ptr, 0, end - ptr));
+    if (UNLIKELY(str_end == nullptr)) {
+      LOG(WARNING) << "OatHeader: Unterminated key in key value store.";
+      return nullptr;
     }
+    const char* value_start = str_end + 1;
+    const char* value_end =
+        reinterpret_cast<const char*>(memchr(value_start, 0, end - value_start));
+    if (UNLIKELY(value_end == nullptr)) {
+      LOG(WARNING) << "OatHeader: Unterminated value in key value store.";
+      return nullptr;
+    }
+    if (key_view == std::string_view(ptr, str_end - ptr)) {
+      // Same as key.
+      return value_start;
+    }
+    // Different from key. Advance over the value.
+    ptr = value_end + 1;
   }
   // Not found.
   return nullptr;
 }
 
-bool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key,
+bool OatHeader::GetStoreKeyValuePairByIndex(size_t index,
+                                            const char** key,
                                             const char** value) const {
   const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
   const char* end = ptr + key_value_store_size_;
-  ssize_t counter = static_cast<ssize_t>(index);
+  size_t counter = index;
 
-  while (ptr < end && counter >= 0) {
+  while (ptr < end) {
     // Scan for a closing zero.
-    const char* str_end = ParseString(ptr, end);
-    if (str_end < end) {
-      const char* maybe_key = ptr;
-      ptr = ParseString(str_end + 1, end) + 1;
-      if (ptr <= end) {
-        if (counter == 0) {
-          *key = maybe_key;
-          *value = str_end + 1;
-          return true;
-        } else {
-          counter--;
-        }
-      } else {
-        return false;
-      }
-    } else {
-      break;
+    const char* str_end = reinterpret_cast<const char*>(memchr(ptr, 0, end - ptr));
+    if (UNLIKELY(str_end == nullptr)) {
+      LOG(WARNING) << "OatHeader: Unterminated key in key value store.";
+      return false;
     }
+    const char* value_start = str_end + 1;
+    const char* value_end =
+        reinterpret_cast<const char*>(memchr(value_start, 0, end - value_start));
+    if (UNLIKELY(value_end == nullptr)) {
+      LOG(WARNING) << "OatHeader: Unterminated value in key value store.";
+      return false;
+    }
+    if (counter == 0) {
+      *key = ptr;
+      *value = value_start;
+      return true;
+    } else {
+      --counter;
+    }
+    // Advance over the value.
+    ptr = value_end + 1;
   }
   // Not found.
   return false;
@@ -396,6 +416,10 @@
   return IsKeyEnabled(OatHeader::kNativeDebuggableKey);
 }
 
+bool OatHeader::RequiresImage() const {
+  return IsKeyEnabled(OatHeader::kRequiresImage);
+}
+
 CompilerFilter::Filter OatHeader::GetCompilerFilter() const {
   CompilerFilter::Filter filter;
   const char* key_value = GetStoreValueByKey(kCompilerFilter);
diff --git a/runtime/oat.h b/runtime/oat.h
index 080a706..ab45b84 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -20,9 +20,9 @@
 #include <array>
 #include <vector>
 
+#include "base/compiler_filter.h"
 #include "base/macros.h"
 #include "base/safe_map.h"
-#include "compiler_filter.h"
 
 namespace art {
 
@@ -32,8 +32,8 @@
 class PACKED(4) OatHeader {
  public:
   static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } };
-  // Last oat version changed reason: Change ClassStatus bits with kVerifiedNeedsAccessChecks.
-  static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '8', '3', '\0' } };
+  // Last oat version changed reason: Apex versions in key/value store.
+  static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '9', '5', '\0' } };
 
   static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
   static constexpr const char* kDebuggableKey = "debuggable";
@@ -42,8 +42,10 @@
   static constexpr const char* kClassPathKey = "classpath";
   static constexpr const char* kBootClassPathKey = "bootclasspath";
   static constexpr const char* kBootClassPathChecksumsKey = "bootclasspath-checksums";
+  static constexpr const char* kApexVersionsKey = "apex-versions";
   static constexpr const char* kConcurrentCopying = "concurrent-copying";
   static constexpr const char* kCompilationReasonKey = "compilation-reason";
+  static constexpr const char* kRequiresImage = "requires-image";
 
   static constexpr const char kTrueValue[] = "true";
   static constexpr const char kFalseValue[] = "false";
@@ -88,6 +90,9 @@
   const void* GetQuickToInterpreterBridge() const;
   uint32_t GetQuickToInterpreterBridgeOffset() const;
   void SetQuickToInterpreterBridgeOffset(uint32_t offset);
+  const void* GetNterpTrampoline() const;
+  uint32_t GetNterpTrampolineOffset() const;
+  void SetNterpTrampolineOffset(uint32_t offset);
 
   InstructionSet GetInstructionSet() const;
   uint32_t GetInstructionSetFeaturesBitmap() const;
@@ -102,6 +107,7 @@
   bool IsNativeDebuggable() const;
   CompilerFilter::Filter GetCompilerFilter() const;
   bool IsConcurrentCopying() const;
+  bool RequiresImage() const;
 
  private:
   bool KeyHasValue(const char* key, const char* value, size_t value_size) const;
@@ -131,6 +137,7 @@
   uint32_t quick_imt_conflict_trampoline_offset_;
   uint32_t quick_resolution_trampoline_offset_;
   uint32_t quick_to_interpreter_bridge_offset_;
+  uint32_t nterp_trampoline_offset_;
 
   uint32_t key_value_store_size_;
   uint8_t key_value_store_[0];  // note variable width data at end
diff --git a/runtime/oat_file-inl.h b/runtime/oat_file-inl.h
index b71c4e8..29b361b 100644
--- a/runtime/oat_file-inl.h
+++ b/runtime/oat_file-inl.h
@@ -41,14 +41,6 @@
   return reinterpret_cast<const uint8_t*>(method_header) - begin_;
 }
 
-inline uint32_t OatFile::OatMethod::GetQuickCodeSizeOffset() const {
-  const OatQuickMethodHeader* method_header = GetOatQuickMethodHeader();
-  if (method_header == nullptr) {
-    return 0u;
-  }
-  return reinterpret_cast<const uint8_t*>(method_header->GetCodeSizeAddr()) - begin_;
-}
-
 inline size_t OatFile::OatMethod::GetFrameSizeInBytes() const {
   const void* code = EntryPointToCodePointer(GetQuickCode());
   if (code == nullptr) {
@@ -78,20 +70,12 @@
   return static_cast<uint32_t>(vmap_table != nullptr ? vmap_table - begin_ : 0u);
 }
 
-inline uint32_t OatFile::OatMethod::GetVmapTableOffsetOffset() const {
-  const OatQuickMethodHeader* method_header = GetOatQuickMethodHeader();
-  if (method_header == nullptr) {
-    return 0u;
-  }
-  return reinterpret_cast<const uint8_t*>(method_header->GetVmapTableOffsetAddr()) - begin_;
-}
-
 inline const uint8_t* OatFile::OatMethod::GetVmapTable() const {
   const void* code = EntryPointToCodePointer(GetOatPointer<const void*>(code_offset_));
   if (code == nullptr) {
     return nullptr;
   }
-  uint32_t offset = reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].GetVmapTableOffset();
+  uint32_t offset = reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].GetCodeInfoOffset();
   if (UNLIKELY(offset == 0u)) {
     return nullptr;
   }
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index d72fc7e..8f653c2 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -31,6 +31,7 @@
 // dlopen_ext support from bionic.
 #ifdef ART_TARGET_ANDROID
 #include "android/dlext.h"
+#include "nativeloader/dlext_namespaces.h"
 #endif
 
 #include <android-base/logging.h>
@@ -166,7 +167,8 @@
   virtual void PreSetup(const std::string& elf_filename) = 0;
 
   bool Setup(int zip_fd, ArrayRef<const std::string> dex_filenames, std::string* error_msg);
-  bool Setup(const std::vector<const DexFile*>& dex_files);
+
+  void Setup(const std::vector<const DexFile*>& dex_files);
 
   // Setters exposed for ElfOatFile.
 
@@ -275,7 +277,17 @@
   // We sometimes load oat files without a runtime (eg oatdump) and don't want to do anything in
   // that case. If we are debuggable there are no -quick opcodes to unquicken. If the runtime is not
   // debuggable we don't care whether there are -quick opcodes or not so no need to do anything.
-  return Runtime::Current() != nullptr && !IsDebuggable() && Runtime::Current()->IsJavaDebuggable();
+  Runtime* runtime = Runtime::Current();
+  return (runtime != nullptr && runtime->IsJavaDebuggable()) &&
+         // Note: This is called before `OatFileBase::Setup()` where we validate the
+         // oat file contents. Check that we have at least a valid header, including
+         // oat file version, to avoid parsing the key-value store for a different
+         // version (out-of-date oat file) which can lead to crashes. b/179221298.
+         // TODO: While this is a poor workaround and the correct solution would be
+         // to postpone the unquickening check until after `OatFileBase::Setup()`,
+         // we prefer to avoid larger rewrites because quickening is deprecated and
+         // should be removed completely anyway. b/170086509
+         (GetOatHeader().IsValid() && !IsDebuggable());
 }
 
 bool OatFileBase::LoadVdex(const std::string& vdex_filename,
@@ -464,13 +476,28 @@
   return true;
 }
 
-bool OatFileBase::Setup(const std::vector<const DexFile*>& dex_files) {
+void OatFileBase::Setup(const std::vector<const DexFile*>& dex_files) {
+  uint32_t i = 0;
+  const uint8_t* type_lookup_table_start = nullptr;
   for (const DexFile* dex_file : dex_files) {
+    type_lookup_table_start = vdex_->GetNextTypeLookupTableData(type_lookup_table_start, i++);
     std::string dex_location = dex_file->GetLocation();
     std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location.c_str());
 
+    const uint8_t* type_lookup_table_data = nullptr;
+    if (type_lookup_table_start != nullptr &&
+        (reinterpret_cast<uint32_t*>(type_lookup_table_start[0]) != 0)) {
+      type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
+    }
     // Create an OatDexFile and add it to the owning container.
-    OatDexFile* oat_dex_file = new OatDexFile(this, dex_file, dex_location, canonical_location);
+    OatDexFile* oat_dex_file = new OatDexFile(
+        this,
+        dex_file->Begin(),
+        dex_file->GetLocationChecksum(),
+        dex_location,
+        canonical_location,
+        type_lookup_table_data);
+    dex_file->SetOatDexFile(oat_dex_file);
     oat_dex_files_storage_.push_back(oat_dex_file);
 
     // Add the location and canonical location (if different) to the oat_dex_files_ table.
@@ -481,8 +508,6 @@
       oat_dex_files_.Put(canonical_key, oat_dex_file);
     }
   }
-
-  return true;
 }
 
 bool OatFileBase::Setup(int zip_fd,
@@ -778,20 +803,18 @@
     const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer);
     if (UNLIKELY(!valid_magic)) {
       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
-                                    "dex file magic '%s'",
+                                    "dex file magic",
                                 GetLocation().c_str(),
                                 i,
-                                dex_file_location.c_str(),
-                                dex_file_pointer);
+                                dex_file_location.c_str());
       return false;
     }
     if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_pointer))) {
       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
-                                    "dex file version '%s'",
+                                    "dex file version",
                                 GetLocation().c_str(),
                                 i,
-                                dex_file_location.c_str(),
-                                dex_file_pointer);
+                                dex_file_location.c_str());
       return false;
     }
     const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
@@ -850,11 +873,11 @@
       return false;
     }
     const uint8_t* lookup_table_data = lookup_table_offset != 0u
-        ? Begin() + lookup_table_offset
+        ? DexBegin() + lookup_table_offset
         : nullptr;
     if (lookup_table_offset != 0u &&
-        (UNLIKELY(lookup_table_offset > Size()) ||
-            UNLIKELY(Size() - lookup_table_offset <
+        (UNLIKELY(lookup_table_offset > DexSize()) ||
+            UNLIKELY(DexSize() - lookup_table_offset <
                      TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
                                     "type lookup table, offset %u of %zu, class defs %u",
@@ -882,12 +905,18 @@
 
     const IndexBssMapping* method_bss_mapping;
     const IndexBssMapping* type_bss_mapping;
+    const IndexBssMapping* public_type_bss_mapping;
+    const IndexBssMapping* package_type_bss_mapping;
     const IndexBssMapping* string_bss_mapping;
     if (!ReadIndexBssMapping(
             this, &oat, i, dex_file_location, "method", &method_bss_mapping, error_msg) ||
         !ReadIndexBssMapping(
             this, &oat, i, dex_file_location, "type", &type_bss_mapping, error_msg) ||
         !ReadIndexBssMapping(
+            this, &oat, i, dex_file_location, "type", &public_type_bss_mapping, error_msg) ||
+        !ReadIndexBssMapping(
+            this, &oat, i, dex_file_location, "type", &package_type_bss_mapping, error_msg) ||
+        !ReadIndexBssMapping(
             this, &oat, i, dex_file_location, "string", &string_bss_mapping, error_msg)) {
       return false;
     }
@@ -902,6 +931,8 @@
         lookup_table_data,
         method_bss_mapping,
         type_bss_mapping,
+        public_type_bss_mapping,
+        package_type_bss_mapping,
         string_bss_mapping,
         class_offsets_pointer,
         dex_layout_sections);
@@ -1024,7 +1055,7 @@
   // Guarded by host_dlopen_handles_lock_;
   static std::unordered_set<void*> host_dlopen_handles_;
 
-  // Reservation and dummy memory map objects corresponding to the regions mapped by dlopen.
+  // Reservation and placeholder memory map objects corresponding to the regions mapped by dlopen.
   // Note: Must be destroyed after dlclose() as it can hold the owning reservation.
   std::vector<MemMap> dlopen_mmaps_;
 
@@ -1106,6 +1137,26 @@
   return success;
 }
 
+#ifdef ART_TARGET_ANDROID
+static struct android_namespace_t* GetSystemLinkerNamespace() {
+  static struct android_namespace_t* system_ns = []() {
+    // The system namespace is called "default" for binaries in /system and
+    // "system" for those in the ART APEX. Try "system" first since "default"
+    // always exists.
+    // TODO(b/185587109): Get rid of this error prone logic.
+    struct android_namespace_t* ns = android_get_exported_namespace("system");
+    if (ns == nullptr) {
+      ns = android_get_exported_namespace("default");
+      if (ns == nullptr) {
+        LOG(FATAL) << "Failed to get system namespace for loading OAT files";
+      }
+    }
+    return ns;
+  }();
+  return system_ns;
+}
+#endif  // ART_TARGET_ANDROID
+
 bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
                            /*inout*/MemMap* reservation,
                            /*out*/std::string* error_msg) {
@@ -1135,6 +1186,19 @@
       extinfo.reserved_addr = reservation->Begin();
       extinfo.reserved_size = reservation->Size();
     }
+
+    if (strncmp(kAndroidArtApexDefaultPath,
+                absolute_path.get(),
+                sizeof(kAndroidArtApexDefaultPath) - 1) != 0 ||
+        absolute_path.get()[sizeof(kAndroidArtApexDefaultPath) - 1] != '/') {
+      // Use the system namespace for OAT files outside the ART APEX. Search
+      // paths and links don't matter here, but permitted paths do, and the
+      // system namespace is configured to allow loading from all appropriate
+      // locations.
+      extinfo.flags |= ANDROID_DLEXT_USE_NAMESPACE;
+      extinfo.library_namespace = GetSystemLinkerNamespace();
+    }
+
     dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
     if (reservation != nullptr && dlopen_handle_ != nullptr) {
       // Find used pages from the reservation.
@@ -1231,7 +1295,7 @@
   LOG(FATAL) << "Should not reach here.";
   UNREACHABLE();
 #else
-  struct DummyMapData {
+  struct PlaceholderMapData {
     const char* name;
     uint8_t* vaddr;
     size_t memsz;
@@ -1263,7 +1327,7 @@
           }
         }
       }
-      // Add dummy mmaps for this file.
+      // Add placeholder mmaps for this file.
       if (contains_begin) {
         for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
           if (info->dlpi_phdr[i].p_type == PT_LOAD) {
@@ -1271,17 +1335,19 @@
                 info->dlpi_phdr[i].p_vaddr);
             size_t memsz = info->dlpi_phdr[i].p_memsz;
             size_t name_size = strlen(info->dlpi_name) + 1u;
-            std::vector<char>* dummy_maps_names = context->dummy_maps_names_;
+            std::vector<char>* placeholder_maps_names = context->placeholder_maps_names_;
             // We must not allocate any memory in the callback, see b/156312036 .
-            if (name_size < dummy_maps_names->capacity() - dummy_maps_names->size() &&
-                context->dummy_maps_data_->size() < context->dummy_maps_data_->capacity()) {
-              dummy_maps_names->insert(
-                  dummy_maps_names->end(), info->dlpi_name, info->dlpi_name + name_size);
-              const char* name = &(*dummy_maps_names)[dummy_maps_names->size() - name_size];
-              context->dummy_maps_data_->push_back({ name, vaddr, memsz });
+            if (name_size < placeholder_maps_names->capacity() - placeholder_maps_names->size() &&
+                context->placeholder_maps_data_->size() <
+                    context->placeholder_maps_data_->capacity()) {
+              placeholder_maps_names->insert(
+                  placeholder_maps_names->end(), info->dlpi_name, info->dlpi_name + name_size);
+              const char* name =
+                  &(*placeholder_maps_names)[placeholder_maps_names->size() - name_size];
+              context->placeholder_maps_data_->push_back({ name, vaddr, memsz });
             }
-            context->num_dummy_maps_ += 1u;
-            context->dummy_maps_names_size_ += name_size;
+            context->num_placeholder_maps_ += 1u;
+            context->placeholder_maps_names_size_ += name_size;
           }
         }
         return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
@@ -1289,27 +1355,27 @@
       return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
     }
     const uint8_t* const begin_;
-    std::vector<DummyMapData>* dummy_maps_data_;
-    size_t num_dummy_maps_;
-    std::vector<char>* dummy_maps_names_;
-    size_t dummy_maps_names_size_;
+    std::vector<PlaceholderMapData>* placeholder_maps_data_;
+    size_t num_placeholder_maps_;
+    std::vector<char>* placeholder_maps_names_;
+    size_t placeholder_maps_names_size_;
     size_t shared_objects_before;
     size_t shared_objects_seen;
   };
 
   // We must not allocate any memory in the callback, see b/156312036 .
-  // Therefore we pre-allocate storage for the data we need for creating the dummy maps.
-  std::vector<DummyMapData> dummy_maps_data;
-  dummy_maps_data.reserve(32);  // 32 should be enough. If not, we'll retry.
-  std::vector<char> dummy_maps_names;
-  dummy_maps_names.reserve(4 * KB);  // 4KiB should be enough. If not, we'll retry.
+  // Therefore we pre-allocate storage for the data we need for creating the placeholder maps.
+  std::vector<PlaceholderMapData> placeholder_maps_data;
+  placeholder_maps_data.reserve(32);  // 32 should be enough. If not, we'll retry.
+  std::vector<char> placeholder_maps_names;
+  placeholder_maps_names.reserve(4 * KB);  // 4KiB should be enough. If not, we'll retry.
 
   dl_iterate_context context = {
       Begin(),
-      &dummy_maps_data,
-      /*num_dummy_maps_*/ 0u,
-      &dummy_maps_names,
-      /*dummy_maps_names_size_*/ 0u,
+      &placeholder_maps_data,
+      /*num_placeholder_maps_*/ 0u,
+      &placeholder_maps_names,
+      /*placeholder_maps_names_size_*/ 0u,
       shared_objects_before_,
       /*shared_objects_seen*/ 0u
   };
@@ -1319,10 +1385,10 @@
     // before giving up. This should be unusual.
     VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
               << shared_objects_before_;
-    DCHECK(dummy_maps_data.empty());
-    DCHECK_EQ(context.num_dummy_maps_, 0u);
-    DCHECK(dummy_maps_names.empty());
-    DCHECK_EQ(context.dummy_maps_names_size_, 0u);
+    DCHECK(placeholder_maps_data.empty());
+    DCHECK_EQ(context.num_placeholder_maps_, 0u);
+    DCHECK(placeholder_maps_names.empty());
+    DCHECK_EQ(context.placeholder_maps_names_size_, 0u);
     context.shared_objects_before = 0u;
     context.shared_objects_seen = 0u;
     if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
@@ -1332,26 +1398,27 @@
     }
   }
 
-  if (dummy_maps_data.size() < context.num_dummy_maps_) {
+  if (placeholder_maps_data.size() < context.num_placeholder_maps_) {
     // Insufficient capacity. Reserve more space and retry.
-    dummy_maps_data.clear();
-    dummy_maps_data.reserve(context.num_dummy_maps_);
-    context.num_dummy_maps_ = 0u;
-    dummy_maps_names.clear();
-    dummy_maps_names.reserve(context.dummy_maps_names_size_);
-    context.dummy_maps_names_size_ = 0u;
+    placeholder_maps_data.clear();
+    placeholder_maps_data.reserve(context.num_placeholder_maps_);
+    context.num_placeholder_maps_ = 0u;
+    placeholder_maps_names.clear();
+    placeholder_maps_names.reserve(context.placeholder_maps_names_size_);
+    context.placeholder_maps_names_size_ = 0u;
     context.shared_objects_before = 0u;
     context.shared_objects_seen = 0u;
     bool success = (dl_iterate_phdr(dl_iterate_context::callback, &context) != 0);
     CHECK(success);
   }
 
-  CHECK_EQ(dummy_maps_data.size(), context.num_dummy_maps_);
-  CHECK_EQ(dummy_maps_names.size(), context.dummy_maps_names_size_);
-  DCHECK_EQ(static_cast<size_t>(std::count(dummy_maps_names.begin(), dummy_maps_names.end(), '\0')),
-            context.num_dummy_maps_);
-  for (const DummyMapData& data : dummy_maps_data) {
-    MemMap mmap = MemMap::MapDummy(data.name, data.vaddr, data.memsz);
+  CHECK_EQ(placeholder_maps_data.size(), context.num_placeholder_maps_);
+  CHECK_EQ(placeholder_maps_names.size(), context.placeholder_maps_names_size_);
+  DCHECK_EQ(static_cast<size_t>(std::count(placeholder_maps_names.begin(),
+                                           placeholder_maps_names.end(), '\0')),
+            context.num_placeholder_maps_);
+  for (const PlaceholderMapData& data : placeholder_maps_data) {
+    MemMap mmap = MemMap::MapPlaceholder(data.name, data.vaddr, data.memsz);
     dlopen_mmaps_.push_back(std::move(mmap));
   }
 #endif
@@ -1512,49 +1579,107 @@
                                    std::unique_ptr<VdexFile>&& vdex_file,
                                    const std::string& location) {
     std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(location));
-    oat_file->Initialize(dex_files, std::move(vdex_file));
+    // SetVdex will take ownership of the VdexFile.
+    oat_file->SetVdex(vdex_file.release());
+    oat_file->SetupHeader(dex_files.size());
+    // Initialize OatDexFiles.
+    oat_file->Setup(dex_files);
     return oat_file.release();
   }
 
-  void Initialize(const std::vector<const DexFile*>& dex_files,
-                  std::unique_ptr<VdexFile>&& vdex_file) {
+  static OatFileBackedByVdex* Open(int zip_fd,
+                                   std::unique_ptr<VdexFile>&& unique_vdex_file,
+                                   const std::string& dex_location,
+                                   std::string* error_msg) {
+    VdexFile* vdex_file = unique_vdex_file.get();
+    std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(vdex_file->GetName()));
+    // SetVdex will take ownership of the VdexFile.
+    oat_file->SetVdex(unique_vdex_file.release());
+    if (vdex_file->HasDexSection()) {
+      uint32_t i = 0;
+      const uint8_t* type_lookup_table_start = nullptr;
+      for (const uint8_t* dex_file_start = vdex_file->GetNextDexFileData(nullptr, i);
+           dex_file_start != nullptr;
+           dex_file_start = vdex_file->GetNextDexFileData(dex_file_start, ++i)) {
+        if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_start))) {
+          *error_msg =
+              StringPrintf("In vdex file '%s' found dex file with invalid dex file version",
+                           dex_location.c_str());
+          return nullptr;
+        }
+        // Create the OatDexFile and add it to the owning container.
+        std::string location = DexFileLoader::GetMultiDexLocation(i, dex_location.c_str());
+        std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(location.c_str());
+        type_lookup_table_start = vdex_file->GetNextTypeLookupTableData(type_lookup_table_start, i);
+        const uint8_t* type_lookup_table_data = nullptr;
+        if (type_lookup_table_start != nullptr &&
+            (reinterpret_cast<uint32_t*>(type_lookup_table_start[0]) != 0)) {
+          type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
+        }
+        OatDexFile* oat_dex_file = new OatDexFile(oat_file.get(),
+                                                  dex_file_start,
+                                                  vdex_file->GetLocationChecksum(i),
+                                                  location,
+                                                  canonical_location,
+                                                  type_lookup_table_data);
+        oat_file->oat_dex_files_storage_.push_back(oat_dex_file);
+
+        std::string_view key(oat_dex_file->GetDexFileLocation());
+        oat_file->oat_dex_files_.Put(key, oat_dex_file);
+        if (canonical_location != location) {
+          std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
+          oat_file->oat_dex_files_.Put(canonical_key, oat_dex_file);
+        }
+      }
+      oat_file->SetupHeader(oat_file->oat_dex_files_storage_.size());
+    } else {
+      // No need for any verification when loading dex files as we already have
+      // a vdex file.
+      const ArtDexFileLoader dex_file_loader;
+      bool loaded = false;
+      if (zip_fd != -1) {
+        loaded = dex_file_loader.OpenZip(zip_fd,
+                                         dex_location,
+                                         /*verify=*/ false,
+                                         /*verify_checksum=*/ false,
+                                         error_msg,
+                                         &oat_file->external_dex_files_);
+      } else {
+        loaded = dex_file_loader.Open(dex_location.c_str(),
+                                      dex_location,
+                                      /*verify=*/ false,
+                                      /*verify_checksum=*/ false,
+                                      error_msg,
+                                      &oat_file->external_dex_files_);
+      }
+      if (!loaded) {
+        return nullptr;
+      }
+      oat_file->SetupHeader(oat_file->external_dex_files_.size());
+      oat_file->Setup(MakeNonOwningPointerVector(oat_file->external_dex_files_));
+    }
+
+    return oat_file.release();
+  }
+
+  void SetupHeader(size_t number_of_dex_files) {
     DCHECK(!IsExecutable());
 
-    // SetVdex will take ownership of the VdexFile.
-    SetVdex(vdex_file.release());
-
-    // Create a dummy OatHeader with a key store containing only the compiler
-    // filter (it helps debugging and is required by
-    // OatHeader::GetCompilerFilter).
+    // Create a fake OatHeader with a key store to help debugging.
     std::unique_ptr<const InstructionSetFeatures> isa_features =
         InstructionSetFeatures::FromCppDefines();
     SafeMap<std::string, std::string> store;
     store.Put(OatHeader::kCompilerFilter, CompilerFilter::NameOfFilter(CompilerFilter::kVerify));
+    store.Put(OatHeader::kCompilationReasonKey, "vdex");
+    store.Put(OatHeader::kConcurrentCopying,
+              kUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
     oat_header_.reset(OatHeader::Create(kRuntimeISA,
                                         isa_features.get(),
-                                        dex_files.size(),
+                                        number_of_dex_files,
                                         &store));
     const uint8_t* begin = reinterpret_cast<const uint8_t*>(oat_header_.get());
     SetBegin(begin);
     SetEnd(begin + oat_header_->GetHeaderSize());
-
-    // Load VerifierDeps from VDEX and copy bit vectors of verified classes.
-    ArrayRef<const uint8_t> deps_data = GetVdexFile()->GetVerifierDepsData();
-    verified_classes_per_dex_ = verifier::VerifierDeps::ParseVerifiedClasses(dex_files, deps_data);
-
-    // Initialize OatDexFiles.
-    Setup(dex_files);
-  }
-
-  bool IsClassVerifiedInVdex(const OatDexFile& oat_dex_file, uint16_t class_def_index) const {
-    // Determine the index of the DexFile, assuming the order of OatDexFiles
-    // in `oat_dex_files_storage_` is the same.
-    const std::vector<const OatDexFile*>& oat_dex_files = GetOatDexFiles();
-    auto oat_dex_file_it = std::find(oat_dex_files.begin(), oat_dex_files.end(), &oat_dex_file);
-    DCHECK(oat_dex_file_it != oat_dex_files.end());
-    size_t dex_index = oat_dex_file_it - oat_dex_files.begin();
-    // Check the bitvector of verified classes from the vdex.
-    return verified_classes_per_dex_[dex_index][class_def_index];
   }
 
  protected:
@@ -1590,7 +1715,6 @@
 
  private:
   std::unique_ptr<OatHeader> oat_header_;
-  std::vector<std::vector<bool>> verified_classes_per_dex_;
 
   DISALLOW_COPY_AND_ASSIGN(OatFileBackedByVdex);
 };
@@ -1617,13 +1741,12 @@
 
   std::string vdex_filename = GetVdexFilename(oat_filename);
 
-  // Check that the files even exist, fast-fail.
+  // Check that the vdex file even exists, fast-fail. We don't check the odex
+  // file as we use the absence of an odex file for test the functionality of
+  // vdex-only.
   if (!OS::FileExists(vdex_filename.c_str())) {
     *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
     return nullptr;
-  } else if (!OS::FileExists(oat_filename.c_str())) {
-    *error_msg = StringPrintf("File %s does not exist.", oat_filename.c_str());
-    return nullptr;
   }
 
   // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
@@ -1639,6 +1762,17 @@
                                                                  reservation,
                                                                  error_msg);
   if (with_dlopen != nullptr) {
+    Runtime* runtime = Runtime::Current();
+    // The runtime might not be available at this point if we're running
+    // dex2oat or oatdump.
+    if (runtime != nullptr) {
+      size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeOdex();
+      Runtime::MadviseFileForRange(madvise_size_limit,
+                                   with_dlopen->Size(),
+                                   with_dlopen->Begin(),
+                                   with_dlopen->End(),
+                                   oat_location);
+    }
     return with_dlopen;
   }
   if (kPrintDlOpenErrorMessage) {
@@ -1704,6 +1838,14 @@
   return OatFileBackedByVdex::Open(dex_files, std::move(vdex_file), location);
 }
 
+OatFile* OatFile::OpenFromVdex(int zip_fd,
+                               std::unique_ptr<VdexFile>&& vdex_file,
+                               const std::string& location,
+                               std::string* error_msg) {
+  CheckLocation(location);
+  return OatFileBackedByVdex::Open(zip_fd, std::move(vdex_file), location, error_msg);
+}
+
 OatFile::OatFile(const std::string& location, bool is_executable)
     : location_(location),
       vdex_(nullptr),
@@ -1856,6 +1998,8 @@
                        const uint8_t* lookup_table_data,
                        const IndexBssMapping* method_bss_mapping_data,
                        const IndexBssMapping* type_bss_mapping_data,
+                       const IndexBssMapping* public_type_bss_mapping_data,
+                       const IndexBssMapping* package_type_bss_mapping_data,
                        const IndexBssMapping* string_bss_mapping_data,
                        const uint32_t* oat_class_offsets_pointer,
                        const DexLayoutSections* dex_layout_sections)
@@ -1867,16 +2011,24 @@
       lookup_table_data_(lookup_table_data),
       method_bss_mapping_(method_bss_mapping_data),
       type_bss_mapping_(type_bss_mapping_data),
+      public_type_bss_mapping_(public_type_bss_mapping_data),
+      package_type_bss_mapping_(package_type_bss_mapping_data),
       string_bss_mapping_(string_bss_mapping_data),
       oat_class_offsets_pointer_(oat_class_offsets_pointer),
       lookup_table_(),
       dex_layout_sections_(dex_layout_sections) {
+  InitializeTypeLookupTable();
+  DCHECK(!IsBackedByVdexOnly());
+}
+
+void OatDexFile::InitializeTypeLookupTable() {
   // Initialize TypeLookupTable.
   if (lookup_table_data_ != nullptr) {
     // Peek the number of classes from the DexFile.
     const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
     const uint32_t num_class_defs = dex_header->class_defs_size_;
-    if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) > GetOatFile()->End()) {
+    if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) >
+            GetOatFile()->DexEnd()) {
       LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
     } else {
       const uint8_t* dex_data = dex_file_pointer_;
@@ -1887,19 +2039,21 @@
       lookup_table_ = TypeLookupTable::Open(dex_data, lookup_table_data_, num_class_defs);
     }
   }
-  DCHECK(!IsBackedByVdexOnly());
 }
 
 OatDexFile::OatDexFile(const OatFile* oat_file,
-                       const DexFile* dex_file,
+                       const uint8_t* dex_file_pointer,
+                       uint32_t dex_file_location_checksum,
                        const std::string& dex_file_location,
-                       const std::string& canonical_dex_file_location)
+                       const std::string& canonical_dex_file_location,
+                       const uint8_t* lookup_table_data)
     : oat_file_(oat_file),
       dex_file_location_(dex_file_location),
       canonical_dex_file_location_(canonical_dex_file_location),
-      dex_file_location_checksum_(dex_file->GetLocationChecksum()),
-      dex_file_pointer_(reinterpret_cast<const uint8_t*>(dex_file)) {
-  dex_file->SetOatDexFile(this);
+      dex_file_location_checksum_(dex_file_location_checksum),
+      dex_file_pointer_(dex_file_pointer),
+      lookup_table_data_(lookup_table_data) {
+  InitializeTypeLookupTable();
   DCHECK(IsBackedByVdexOnly());
 }
 
@@ -1943,69 +2097,64 @@
 }
 
 OatFile::OatClass OatDexFile::GetOatClass(uint16_t class_def_index) const {
-  // If this is an OatFileBackedByVdex, initialize the OatClass using the vdex's VerifierDeps.
   if (IsBackedByVdexOnly()) {
-    bool is_vdex_verified = down_cast<const OatFileBackedByVdex*>(oat_file_)->IsClassVerifiedInVdex(
-        *this,
-        class_def_index);
+    // If there is only a vdex file, return that the class is not ready. The
+    // caller will have to call `VdexFile::ComputeClassStatus` to compute the
+    // actual class status, because we need to do the assignability type checks.
     return OatFile::OatClass(oat_file_,
-                             is_vdex_verified ? ClassStatus::kVerified : ClassStatus::kNotReady,
-                             /* type= */ kOatClassNoneCompiled,
+                             ClassStatus::kNotReady,
+                             /* type= */ OatClassType::kNoneCompiled,
                              /* bitmap_size= */ 0u,
                              /* bitmap_pointer= */ nullptr,
                              /* methods_pointer= */ nullptr);
   }
 
   uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
+  CHECK_GE(oat_class_offset, sizeof(OatHeader)) << oat_file_->GetLocation();
+  CHECK_LT(oat_class_offset, oat_file_->Size()) << oat_file_->GetLocation();
+  CHECK_LE(/* status */ sizeof(uint16_t) + /* type */ sizeof(uint16_t),
+           oat_file_->Size() - oat_class_offset) << oat_file_->GetLocation();
+  const uint8_t* current_pointer = oat_file_->Begin() + oat_class_offset;
 
-  const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset;
-  CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation();
+  uint16_t status_value = *reinterpret_cast<const uint16_t*>(current_pointer);
+  current_pointer += sizeof(uint16_t);
+  uint16_t type_value = *reinterpret_cast<const uint16_t*>(current_pointer);
+  current_pointer += sizeof(uint16_t);
+  CHECK_LE(status_value, enum_cast<uint8_t>(ClassStatus::kLast))
+      << static_cast<uint32_t>(status_value) << " at " << oat_file_->GetLocation();
+  CHECK_LT(type_value, enum_cast<uint8_t>(OatClassType::kOatClassMax)) << oat_file_->GetLocation();
+  ClassStatus status = enum_cast<ClassStatus>(status_value);
+  OatClassType type = enum_cast<OatClassType>(type_value);
 
-  const uint8_t* status_pointer = oat_class_pointer;
-  CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation();
-  ClassStatus status = enum_cast<ClassStatus>(*reinterpret_cast<const int16_t*>(status_pointer));
-  CHECK_LE(status, ClassStatus::kLast) << static_cast<uint32_t>(status)
-      << " at " << oat_file_->GetLocation();
-
-  const uint8_t* type_pointer = status_pointer + sizeof(uint16_t);
-  CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation();
-  OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer));
-  CHECK_LT(type, kOatClassMax) << oat_file_->GetLocation();
-
-  const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t);
-  CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation();
-
-  uint32_t bitmap_size = 0;
-  const uint8_t* bitmap_pointer = nullptr;
-  const uint8_t* methods_pointer = nullptr;
-  if (type != kOatClassNoneCompiled) {
-    if (type == kOatClassSomeCompiled) {
-      bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer));
-      bitmap_pointer = after_type_pointer + sizeof(bitmap_size);
-      CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation();
-      methods_pointer = bitmap_pointer + bitmap_size;
+  uint32_t num_methods = 0;
+  const uint32_t* bitmap_pointer = nullptr;
+  const OatMethodOffsets* methods_pointer = nullptr;
+  if (type != OatClassType::kNoneCompiled) {
+    CHECK_LE(sizeof(uint32_t), static_cast<size_t>(oat_file_->End() - current_pointer))
+        << oat_file_->GetLocation();
+    num_methods = *reinterpret_cast<const uint32_t*>(current_pointer);
+    current_pointer += sizeof(uint32_t);
+    CHECK_NE(num_methods, 0u) << oat_file_->GetLocation();
+    uint32_t num_method_offsets;
+    if (type == OatClassType::kSomeCompiled) {
+      uint32_t bitmap_size = BitVector::BitsToWords(num_methods) * BitVector::kWordBytes;
+      CHECK_LE(bitmap_size, static_cast<size_t>(oat_file_->End() - current_pointer))
+          << oat_file_->GetLocation();
+      bitmap_pointer = reinterpret_cast<const uint32_t*>(current_pointer);
+      current_pointer += bitmap_size;
+      // Note: The bits in range [num_methods, bitmap_size * kBitsPerByte)
+      // should be zero but we're not verifying that.
+      num_method_offsets = BitVector::NumSetBits(bitmap_pointer, num_methods);
     } else {
-      methods_pointer = after_type_pointer;
+      num_method_offsets = num_methods;
     }
-    CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation();
+    CHECK_LE(num_method_offsets,
+             static_cast<size_t>(oat_file_->End() - current_pointer) / sizeof(OatMethodOffsets))
+        << oat_file_->GetLocation();
+    methods_pointer = reinterpret_cast<const OatMethodOffsets*>(current_pointer);
   }
 
-  return OatFile::OatClass(oat_file_,
-                           status,
-                           type,
-                           bitmap_size,
-                           reinterpret_cast<const uint32_t*>(bitmap_pointer),
-                           reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
-}
-
-ArrayRef<const uint8_t> OatDexFile::GetQuickenedInfoOf(const DexFile& dex_file,
-                                                       uint32_t dex_method_idx) const {
-  const OatFile* oat_file = GetOatFile();
-  if (oat_file == nullptr) {
-    return ArrayRef<const uint8_t>();
-  } else  {
-    return oat_file->GetVdexFile()->GetQuickenedInfoOf(dex_file, dex_method_idx);
-  }
+  return OatFile::OatClass(oat_file_, status, type, num_methods, bitmap_pointer, methods_pointer);
 }
 
 const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file,
@@ -2018,9 +2167,10 @@
   if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) {
     used_lookup_table = true;
     const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash);
-    lookup_table_classdef = (class_def_idx != dex::kDexNoIndex)
-        ? &dex_file.GetClassDef(class_def_idx)
-        : nullptr;
+    if (class_def_idx != dex::kDexNoIndex) {
+      CHECK_LT(class_def_idx, dex_file.NumClassDefs()) << oat_dex_file->GetOatFile()->GetLocation();
+      lookup_table_classdef = &dex_file.GetClassDef(class_def_idx);
+    }
     if (!kIsDebugBuild) {
       return lookup_table_classdef;
     }
@@ -2063,43 +2213,29 @@
   if (oat_dex_file != nullptr) {
     // Should always be there.
     const DexLayoutSections* const sections = oat_dex_file->GetDexLayoutSections();
-    CHECK(sections != nullptr);
-    sections->Madvise(&dex_file, state);
+    if (sections != nullptr) {
+      sections->Madvise(&dex_file, state);
+    } else {
+      DCHECK(oat_dex_file->IsBackedByVdexOnly());
+    }
   }
 }
 
 OatFile::OatClass::OatClass(const OatFile* oat_file,
                             ClassStatus status,
                             OatClassType type,
-                            uint32_t bitmap_size,
+                            uint32_t num_methods,
                             const uint32_t* bitmap_pointer,
                             const OatMethodOffsets* methods_pointer)
-    : oat_file_(oat_file), status_(status), type_(type),
-      bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) {
-    switch (type_) {
-      case kOatClassAllCompiled: {
-        CHECK_EQ(0U, bitmap_size);
-        CHECK(bitmap_pointer == nullptr);
-        CHECK(methods_pointer != nullptr);
-        break;
-      }
-      case kOatClassSomeCompiled: {
-        CHECK_NE(0U, bitmap_size);
-        CHECK(bitmap_pointer != nullptr);
-        CHECK(methods_pointer != nullptr);
-        break;
-      }
-      case kOatClassNoneCompiled: {
-        CHECK_EQ(0U, bitmap_size);
-        CHECK(bitmap_pointer == nullptr);
-        CHECK(methods_pointer_ == nullptr);
-        break;
-      }
-      case kOatClassMax: {
-        LOG(FATAL) << "Invalid OatClassType " << type_;
-        UNREACHABLE();
-      }
-    }
+    : oat_file_(oat_file),
+      status_(status),
+      type_(type),
+      num_methods_(num_methods),
+      bitmap_(bitmap_pointer),
+      methods_pointer_(methods_pointer) {
+  DCHECK_EQ(num_methods != 0u, type != OatClassType::kNoneCompiled);
+  DCHECK_EQ(bitmap_pointer != nullptr, type == OatClassType::kSomeCompiled);
+  DCHECK_EQ(methods_pointer != nullptr, type != OatClassType::kNoneCompiled);
 }
 
 uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
@@ -2111,23 +2247,31 @@
 }
 
 const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
-  // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index.
+  // NOTE: We don't keep the number of methods for `kNoneCompiled` and cannot do
+  // a bounds check for `method_index` in that case.
   if (methods_pointer_ == nullptr) {
-    CHECK_EQ(kOatClassNoneCompiled, type_);
+    CHECK_EQ(OatClassType::kNoneCompiled, type_);
     return nullptr;
   }
+  CHECK_LT(method_index, num_methods_) << oat_file_->GetLocation();
   size_t methods_pointer_index;
   if (bitmap_ == nullptr) {
-    CHECK_EQ(kOatClassAllCompiled, type_);
+    CHECK_EQ(OatClassType::kAllCompiled, type_);
     methods_pointer_index = method_index;
   } else {
-    CHECK_EQ(kOatClassSomeCompiled, type_);
+    CHECK_EQ(OatClassType::kSomeCompiled, type_);
     if (!BitVector::IsBitSet(bitmap_, method_index)) {
       return nullptr;
     }
     size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
     methods_pointer_index = num_set_bits;
   }
+  if (kIsDebugBuild) {
+    size_t size_until_end = dchecked_integral_cast<size_t>(
+        oat_file_->End() - reinterpret_cast<const uint8_t*>(methods_pointer_));
+    CHECK_LE(methods_pointer_index, size_until_end / sizeof(OatMethodOffsets))
+        << oat_file_->GetLocation();
+  }
   const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
   return &oat_method_offsets;
 }
@@ -2176,6 +2320,8 @@
   return oat_dex_file->GetOatClass(class_def_idx);
 }
 
+bool OatFile::RequiresImage() const { return GetOatHeader().RequiresImage(); }
+
 static void DCheckIndexToBssMapping(const OatFile* oat_file,
                                     uint32_t number_of_indexes,
                                     size_t slot_size,
@@ -2255,4 +2401,8 @@
   CHECK(Runtime::Current()->IsAotCompiler());
 }
 
+bool OatFile::IsBackedByVdexOnly() const {
+  return oat_dex_files_storage_.size() >= 1 && oat_dex_files_storage_[0]->IsBackedByVdexOnly();
+}
+
 }  // namespace art
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index dce34d9..0fd7032 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -23,12 +23,12 @@
 #include <vector>
 
 #include "base/array_ref.h"
+#include "base/compiler_filter.h"
 #include "base/mutex.h"
 #include "base/os.h"
 #include "base/safe_map.h"
 #include "base/tracking_safe_map.h"
 #include "class_status.h"
-#include "compiler_filter.h"
 #include "dex/dex_file_layout.h"
 #include "dex/type_lookup_table.h"
 #include "dex/utf.h"
@@ -55,7 +55,7 @@
 
 namespace gc {
 namespace collector {
-class DummyOatFile;
+class FakeOatFile;
 }  // namespace collector
 }  // namespace gc
 
@@ -63,14 +63,14 @@
 // save even one OatMethodOffsets struct, the more complicated encoding
 // using a bitmap pays for itself since few classes will have 160
 // methods.
-enum OatClassType {
-  kOatClassAllCompiled = 0,   // OatClass is followed by an OatMethodOffsets for each method.
-  kOatClassSomeCompiled = 1,  // A bitmap of OatMethodOffsets that are present follows the OatClass.
-  kOatClassNoneCompiled = 2,  // All methods are interpreted so no OatMethodOffsets are necessary.
+enum class OatClassType : uint8_t {
+  kAllCompiled = 0,   // OatClass is followed by an OatMethodOffsets for each method.
+  kSomeCompiled = 1,  // A bitmap of OatMethodOffsets that are present follows the OatClass.
+  kNoneCompiled = 2,  // All methods are interpreted so no OatMethodOffsets are necessary.
   kOatClassMax = 3,
 };
 
-std::ostream& operator<<(std::ostream& os, const OatClassType& rhs);
+std::ostream& operator<<(std::ostream& os, OatClassType rhs);
 
 class PACKED(4) OatMethodOffsets {
  public:
@@ -94,9 +94,6 @@
 
 class OatFile {
  public:
-  // Special classpath that skips shared library check.
-  static constexpr const char* kSpecialSharedLibrary = "&";
-
   // Open an oat file. Returns null on failure.
   // The `dex_filenames` argument, if provided, overrides the dex locations
   // from oat file when opening the dex files if they are not embedded in the
@@ -163,6 +160,16 @@
                                std::unique_ptr<VdexFile>&& vdex_file,
                                const std::string& location);
 
+  // Initialize OatFile instance from an already loaded VdexFile. The dex files
+  // will be opened through `zip_fd` or `dex_location` if `zip_fd` is -1.
+  static OatFile* OpenFromVdex(int zip_fd,
+                               std::unique_ptr<VdexFile>&& vdex_file,
+                               const std::string& location,
+                               std::string* error_msg);
+
+  // Return whether the `OatFile` uses a vdex-only file.
+  bool IsBackedByVdexOnly() const;
+
   virtual ~OatFile();
 
   bool IsExecutable() const {
@@ -192,7 +199,6 @@
 
     // Returns size of quick code.
     uint32_t GetQuickCodeSize() const;
-    uint32_t GetQuickCodeSizeOffset() const;
 
     // Returns OatQuickMethodHeader for debugging. Most callers should
     // use more specific methods such as GetQuickCodeSize.
@@ -205,7 +211,6 @@
 
     const uint8_t* GetVmapTable() const;
     uint32_t GetVmapTableOffset() const;
-    uint32_t GetVmapTableOffsetOffset() const;
 
     // Create an OatMethod with offsets relative to the given base address
     OatMethod(const uint8_t* base, const uint32_t code_offset)
@@ -268,7 +273,7 @@
     static OatClass Invalid() {
       return OatClass(/* oat_file= */ nullptr,
                       ClassStatus::kErrorUnresolved,
-                      kOatClassNoneCompiled,
+                      OatClassType::kNoneCompiled,
                       /* bitmap_size= */ 0,
                       /* bitmap_pointer= */ nullptr,
                       /* methods_pointer= */ nullptr);
@@ -278,18 +283,15 @@
     OatClass(const OatFile* oat_file,
              ClassStatus status,
              OatClassType type,
-             uint32_t bitmap_size,
+             uint32_t num_methods,
              const uint32_t* bitmap_pointer,
              const OatMethodOffsets* methods_pointer);
 
     const OatFile* const oat_file_;
-
     const ClassStatus status_;
-
     const OatClassType type_;
-
+    const uint32_t num_methods_;
     const uint32_t* const bitmap_;
-
     const OatMethodOffsets* const methods_pointer_;
 
     friend class art::OatDexFile;
@@ -378,6 +380,9 @@
     return external_dex_files_.empty();
   }
 
+  // Returns whether an image (e.g. app image) is required to safely execute this OAT file.
+  bool RequiresImage() const;
+
  protected:
   OatFile(const std::string& filename, bool executable);
 
@@ -460,10 +465,11 @@
   // by the `dex_filenames` parameter, in case the OatFile does not embed the dex code.
   std::vector<std::unique_ptr<const DexFile>> external_dex_files_;
 
-  friend class gc::collector::DummyOatFile;  // For modifying begin_ and end_.
+  friend class gc::collector::FakeOatFile;  // For modifying begin_ and end_.
   friend class OatClass;
   friend class art::OatDexFile;
   friend class OatDumper;  // For GetBase and GetLimit
+  friend class OatFileBackedByVdex;
   friend class OatFileBase;
   DISALLOW_COPY_AND_ASSIGN(OatFile);
 };
@@ -519,6 +525,14 @@
     return type_bss_mapping_;
   }
 
+  const IndexBssMapping* GetPublicTypeBssMapping() const {
+    return public_type_bss_mapping_;
+  }
+
+  const IndexBssMapping* GetPackageTypeBssMapping() const {
+    return package_type_bss_mapping_;
+  }
+
   const IndexBssMapping* GetStringBssMapping() const {
     return string_bss_mapping_;
   }
@@ -527,9 +541,6 @@
     return dex_file_pointer_;
   }
 
-  ArrayRef<const uint8_t> GetQuickenedInfoOf(const DexFile& dex_file,
-                                             uint32_t dex_method_idx) const;
-
   // Looks up a class definition by its class descriptor. Hash must be
   // ComputeModifiedUtf8Hash(descriptor).
   static const dex::ClassDef* FindClassDef(const DexFile& dex_file,
@@ -562,6 +573,8 @@
              const uint8_t* lookup_table_data,
              const IndexBssMapping* method_bss_mapping,
              const IndexBssMapping* type_bss_mapping,
+             const IndexBssMapping* public_type_bss_mapping,
+             const IndexBssMapping* package_type_bss_mapping,
              const IndexBssMapping* string_bss_mapping,
              const uint32_t* oat_class_offsets_pointer,
              const DexLayoutSections* dex_layout_sections);
@@ -569,11 +582,14 @@
   // Create an OatDexFile wrapping an existing DexFile. Will set the OatDexFile
   // pointer in the DexFile.
   OatDexFile(const OatFile* oat_file,
-             const DexFile* dex_file,
+             const uint8_t* dex_file_pointer,
+             uint32_t dex_file_checksum,
              const std::string& dex_file_location,
-             const std::string& canonical_dex_file_location);
+             const std::string& canonical_dex_file_location,
+             const uint8_t* lookup_table_data);
 
   bool IsBackedByVdexOnly() const;
+  void InitializeTypeLookupTable();
 
   static void AssertAotCompiler();
 
@@ -585,6 +601,8 @@
   const uint8_t* const lookup_table_data_ = nullptr;
   const IndexBssMapping* const method_bss_mapping_ = nullptr;
   const IndexBssMapping* const type_bss_mapping_ = nullptr;
+  const IndexBssMapping* const public_type_bss_mapping_ = nullptr;
+  const IndexBssMapping* const package_type_bss_mapping_ = nullptr;
   const IndexBssMapping* const string_bss_mapping_ = nullptr;
   const uint32_t* const oat_class_offsets_pointer_ = nullptr;
   TypeLookupTable lookup_table_;
@@ -592,6 +610,7 @@
 
   friend class OatFile;
   friend class OatFileBase;
+  friend class OatFileBackedByVdex;
   DISALLOW_COPY_AND_ASSIGN(OatDexFile);
 };
 
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index f374883..2cbc1ea 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -21,9 +21,11 @@
 #include <sys/stat.h>
 #include "zlib.h"
 
+#include "android-base/file.h"
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
 
+#include "base/compiler_filter.h"
 #include "base/file_utils.h"
 #include "base/logging.h"  // For VLOG.
 #include "base/macros.h"
@@ -34,7 +36,6 @@
 #include "base/utils.h"
 #include "class_linker.h"
 #include "class_loader_context.h"
-#include "compiler_filter.h"
 #include "dex/art_dex_file_loader.h"
 #include "dex/dex_file_loader.h"
 #include "exec_utils.h"
@@ -67,8 +68,9 @@
     case OatFileAssistant::kOatUpToDate:
       stream << "kOatUpToDate";
       break;
-    default:
-      UNREACHABLE();
+    case OatFileAssistant::kOatContextOutOfDate:
+      stream << "kOaContextOutOfDate";
+      break;
   }
 
   return stream;
@@ -76,12 +78,14 @@
 
 OatFileAssistant::OatFileAssistant(const char* dex_location,
                                    const InstructionSet isa,
+                                   ClassLoaderContext* context,
                                    bool load_executable,
-                                   bool only_load_system_executable)
+                                   bool only_load_trusted_executable)
     : OatFileAssistant(dex_location,
                        isa,
+                       context,
                        load_executable,
-                       only_load_system_executable,
+                       only_load_trusted_executable,
                        /*vdex_fd=*/ -1,
                        /*oat_fd=*/ -1,
                        /*zip_fd=*/ -1) {}
@@ -89,24 +93,32 @@
 
 OatFileAssistant::OatFileAssistant(const char* dex_location,
                                    const InstructionSet isa,
+                                   ClassLoaderContext* context,
                                    bool load_executable,
-                                   bool only_load_system_executable,
+                                   bool only_load_trusted_executable,
                                    int vdex_fd,
                                    int oat_fd,
                                    int zip_fd)
-    : isa_(isa),
+    : context_(context),
+      isa_(isa),
       load_executable_(load_executable),
-      only_load_system_executable_(only_load_system_executable),
+      only_load_trusted_executable_(only_load_trusted_executable),
       odex_(this, /*is_oat_location=*/ false),
       oat_(this, /*is_oat_location=*/ true),
+      vdex_for_odex_(this, /*is_oat_location=*/ false),
+      vdex_for_oat_(this, /*is_oat_location=*/ true),
       zip_fd_(zip_fd) {
   CHECK(dex_location != nullptr) << "OatFileAssistant: null dex location";
+  CHECK(!load_executable || context != nullptr) << "Loading executable without a context";
 
   if (zip_fd < 0) {
     CHECK_LE(oat_fd, 0) << "zip_fd must be provided with valid oat_fd. zip_fd=" << zip_fd
       << " oat_fd=" << oat_fd;
     CHECK_LE(vdex_fd, 0) << "zip_fd must be provided with valid vdex_fd. zip_fd=" << zip_fd
       << " vdex_fd=" << vdex_fd;;
+    CHECK(!UseFdToReadFiles());
+  } else {
+    CHECK(UseFdToReadFiles());
   }
 
   dex_location_.assign(dex_location);
@@ -122,6 +134,13 @@
   std::string odex_file_name;
   if (DexLocationToOdexFilename(dex_location_, isa_, &odex_file_name, &error_msg)) {
     odex_.Reset(odex_file_name, UseFdToReadFiles(), zip_fd, vdex_fd, oat_fd);
+    std::string vdex_file_name = GetVdexFilename(odex_file_name);
+    // We dup FDs as the odex_ will claim ownership.
+    vdex_for_odex_.Reset(vdex_file_name,
+                         UseFdToReadFiles(),
+                         DupCloexec(zip_fd),
+                         DupCloexec(vdex_fd),
+                         DupCloexec(oat_fd));
   } else {
     LOG(WARNING) << "Failed to determine odex file name: " << error_msg;
   }
@@ -131,6 +150,8 @@
     std::string oat_file_name;
     if (DexLocationToOatFilename(dex_location_, isa_, &oat_file_name, &error_msg)) {
       oat_.Reset(oat_file_name, /*use_fd=*/ false);
+      std::string vdex_file_name = GetVdexFilename(oat_file_name);
+      vdex_for_oat_.Reset(vdex_file_name, UseFdToReadFiles(), zip_fd, vdex_fd, oat_fd);
     } else {
       LOG(WARNING) << "Failed to determine oat file name for dex location "
                    << dex_location_ << ": " << error_msg;
@@ -156,13 +177,6 @@
   }
 }
 
-OatFileAssistant::~OatFileAssistant() {
-  // Clean up the lock file.
-  if (flock_.get() != nullptr) {
-    unlink(flock_->GetPath().c_str());
-  }
-}
-
 bool OatFileAssistant::UseFdToReadFiles() {
   return zip_fd_ >= 0;
 }
@@ -185,14 +199,10 @@
 }
 
 int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target,
-                                      ClassLoaderContext* class_loader_context,
-                                      const std::vector<int>& context_fds,
                                       bool profile_changed,
                                       bool downgrade) {
   OatFileInfo& info = GetBestInfo();
   DexOptNeeded dexopt_needed = info.GetDexOptNeeded(target,
-                                                    class_loader_context,
-                                                    context_fds,
                                                     profile_changed,
                                                     downgrade);
   if (info.IsOatLocation() || dexopt_needed == kDex2OatFromScratch) {
@@ -305,8 +315,8 @@
   return true;
 }
 
-bool OatFileAssistant::HasOriginalDexFiles() {
-  ScopedTrace trace("HasOriginalDexFiles");
+bool OatFileAssistant::HasDexFiles() {
+  ScopedTrace trace("HasDexFiles");
   // Ensure GetRequiredDexChecksums has been run so that
   // has_original_dex_files_ is initialized. We don't care about the result of
   // GetRequiredDexChecksums.
@@ -330,7 +340,7 @@
     return true;
   }
 
-  uint32_t number_of_dex_files = file.GetVerifierDepsHeader().GetNumberOfDexFiles();
+  uint32_t number_of_dex_files = file.GetNumberOfDexFiles();
   if (required_dex_checksums->size() != number_of_dex_files) {
     *error_msg = StringPrintf("expected %zu dex files but found %u",
                               required_dex_checksums->size(),
@@ -390,6 +400,19 @@
   return true;
 }
 
+static bool ValidateApexVersions(const OatFile& oat_file) {
+  const char* oat_apex_versions =
+      oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kApexVersionsKey);
+  if (oat_apex_versions == nullptr) {
+    return false;
+  }
+  // Some dex files get compiled with a subset of the boot classpath (for
+  // example currently system server is compiled with DEX2OAT_BOOTCLASSPATH).
+  // For such cases, the oat apex versions will be a prefix of the runtime apex
+  // versions.
+  return android::base::StartsWith(Runtime::Current()->GetApexVersions(), oat_apex_versions);
+}
+
 OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& file) {
   // Verify the ART_USE_READ_BARRIER state.
   // TODO: Don't fully reject files due to read barrier state. If they contain
@@ -413,19 +436,25 @@
   CompilerFilter::Filter current_compiler_filter = file.GetCompilerFilter();
 
   // Verify the image checksum
-  if (CompilerFilter::DependsOnImageChecksum(current_compiler_filter)) {
+  if (file.IsBackedByVdexOnly()) {
+    VLOG(oat) << "Image checksum test skipped for vdex file " << file.GetLocation();
+  } else if (CompilerFilter::DependsOnImageChecksum(current_compiler_filter)) {
     if (!ValidateBootClassPathChecksums(file)) {
       VLOG(oat) << "Oat image checksum does not match image checksum.";
       return kOatBootImageOutOfDate;
     }
+    if (!ValidateApexVersions(file)) {
+      VLOG(oat) << "Apex versions do not match.";
+      return kOatBootImageOutOfDate;
+    }
   } else {
     VLOG(oat) << "Image checksum test skipped for compiler filter " << current_compiler_filter;
   }
 
   // zip_file_only_contains_uncompressed_dex_ is only set during fetching the dex checksums.
   DCHECK(required_dex_checksums_attempted_);
-  if (only_load_system_executable_ &&
-      !LocationIsOnSystem(file.GetLocation().c_str()) &&
+  if (only_load_trusted_executable_ &&
+      !LocationIsTrusted(file.GetLocation(), !Runtime::Current()->DenyArtApexDataFiles()) &&
       file.ContainsDexCode() &&
       zip_file_only_contains_uncompressed_dex_) {
     LOG(ERROR) << "Not loading "
@@ -434,12 +463,15 @@
     return kOatDexOutOfDate;
   }
 
+  if (!ClassLoaderContextIsOkay(file)) {
+    return kOatContextOutOfDate;
+  }
+
   return kOatUpToDate;
 }
 
 bool OatFileAssistant::AnonymousDexVdexLocation(const std::vector<const DexFile::Header*>& headers,
                                                 InstructionSet isa,
-                                                /* out */ uint32_t* location_checksum,
                                                 /* out */ std::string* dex_location,
                                                 /* out */ std::string* vdex_filename) {
   uint32_t checksum = adler32(0L, Z_NULL, 0);
@@ -448,7 +480,6 @@
                                header->checksum_,
                                header->file_size_ - DexFile::kNumNonChecksumBytes);
   }
-  *location_checksum = checksum;
 
   const std::string& data_dir = Runtime::Current()->GetProcessDataDirectory();
   if (data_dir.empty() || Runtime::Current()->IsZygote()) {
@@ -485,12 +516,10 @@
   return true;
 }
 
-static bool DexLocationToOdexNames(const std::string& location,
-                                   InstructionSet isa,
-                                   std::string* odex_filename,
-                                   std::string* oat_dir,
-                                   std::string* isa_dir,
-                                   std::string* error_msg) {
+bool OatFileAssistant::DexLocationToOdexFilename(const std::string& location,
+                                                 InstructionSet isa,
+                                                 std::string* odex_filename,
+                                                 std::string* error_msg) {
   CHECK(odex_filename != nullptr);
   CHECK(error_msg != nullptr);
 
@@ -509,14 +538,9 @@
   std::string dir = location.substr(0, pos+1);
   // Add the oat directory.
   dir += "oat";
-  if (oat_dir != nullptr) {
-    *oat_dir = dir;
-  }
+
   // Add the isa directory
   dir += "/" + std::string(GetInstructionSetString(isa));
-  if (isa_dir != nullptr) {
-    *isa_dir = dir;
-  }
 
   // Get the base part of the file without the extension.
   std::string file = location.substr(pos+1);
@@ -531,13 +555,6 @@
   return true;
 }
 
-bool OatFileAssistant::DexLocationToOdexFilename(const std::string& location,
-                                                 InstructionSet isa,
-                                                 std::string* odex_filename,
-                                                 std::string* error_msg) {
-  return DexLocationToOdexNames(location, isa, odex_filename, nullptr, nullptr, error_msg);
-}
-
 bool OatFileAssistant::DexLocationToOatFilename(const std::string& location,
                                                 InstructionSet isa,
                                                 std::string* oat_filename,
@@ -545,6 +562,18 @@
   CHECK(oat_filename != nullptr);
   CHECK(error_msg != nullptr);
 
+  // Check if `location` could have an oat file in the ART APEX data directory. If so, and the
+  // file exists, use it.
+  const std::string apex_data_file = GetApexDataOdexFilename(location, isa);
+  if (!apex_data_file.empty() && !Runtime::Current()->DenyArtApexDataFiles()) {
+    if (OS::FileExists(apex_data_file.c_str(), /*check_file_type=*/true)) {
+      *oat_filename = apex_data_file;
+      return true;
+    } else if (errno != ENOENT) {
+      PLOG(ERROR) << "Could not check odex file " << apex_data_file;
+    }
+  }
+
   // If ANDROID_DATA is not set, return false instead of aborting.
   // This can occur for preopt when using a class loader context.
   if (GetAndroidDataSafe(error_msg).empty()) {
@@ -552,8 +581,17 @@
     return false;
   }
 
-  std::string cache_dir = GetDalvikCache(GetInstructionSetString(isa));
-  if (cache_dir.empty()) {
+  std::string dalvik_cache;
+  bool have_android_data = false;
+  bool dalvik_cache_exists = false;
+  bool is_global_cache = false;
+  GetDalvikCache(GetInstructionSetString(isa),
+                  /*create_if_absent=*/ true,
+                  &dalvik_cache,
+                  &have_android_data,
+                  &dalvik_cache_exists,
+                  &is_global_cache);
+  if (!dalvik_cache_exists) {
     *error_msg = "Dalvik cache directory does not exist";
     return false;
   }
@@ -561,7 +599,7 @@
   // TODO: The oat file assistant should be the definitive place for
   // determining the oat file name from the dex location, not
   // GetDalvikCacheFilename.
-  return GetDalvikCacheFilename(location.c_str(), cache_dir.c_str(), oat_filename, error_msg);
+  return GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(), oat_filename, error_msg);
 }
 
 const std::vector<uint32_t>* OatFileAssistant::GetRequiredDexChecksums() {
@@ -571,33 +609,20 @@
     cached_required_dex_checksums_.clear();
     std::string error_msg;
     const ArtDexFileLoader dex_file_loader;
+    std::vector<std::string> dex_locations_ignored;
     if (dex_file_loader.GetMultiDexChecksums(dex_location_.c_str(),
                                              &cached_required_dex_checksums_,
+                                             &dex_locations_ignored,
                                              &error_msg,
                                              zip_fd_,
                                              &zip_file_only_contains_uncompressed_dex_)) {
       required_dex_checksums_found_ = true;
       has_original_dex_files_ = true;
     } else {
-      // This can happen if the original dex file has been stripped from the
-      // apk.
-      VLOG(oat) << "OatFileAssistant: " << error_msg;
+      // The only valid case here is for APKs without dex files.
+      required_dex_checksums_found_ = false;
       has_original_dex_files_ = false;
-
-      // Get the checksums from the odex if we can.
-      const OatFile* odex_file = odex_.GetFile();
-      if (odex_file != nullptr) {
-        required_dex_checksums_found_ = true;
-        for (size_t i = 0; i < odex_file->GetOatHeader().GetDexFileCount(); i++) {
-          std::string dex = DexFileLoader::GetMultiDexLocation(i, dex_location_.c_str());
-          const OatDexFile* odex_dex_file = odex_file->GetOatDexFile(dex.c_str(), nullptr);
-          if (odex_dex_file == nullptr) {
-            required_dex_checksums_found_ = false;
-            break;
-          }
-          cached_required_dex_checksums_.push_back(odex_dex_file->GetDexFileLocationChecksum());
-        }
-      }
+      VLOG(oat) << "Could not get required checksum: " << error_msg;
     }
   }
   return required_dex_checksums_found_ ? &cached_required_dex_checksums_ : nullptr;
@@ -621,32 +646,27 @@
 
   Runtime* runtime = Runtime::Current();
   std::string error_msg;
-  bool result = gc::space::ImageSpace::VerifyBootClassPathChecksums(
-      oat_boot_class_path_checksums_view,
-      oat_boot_class_path_view,
-      runtime->GetImageLocation(),
-      ArrayRef<const std::string>(runtime->GetBootClassPathLocations()),
-      ArrayRef<const std::string>(runtime->GetBootClassPath()),
-      isa_,
-      runtime->GetImageSpaceLoadingOrder(),
-      &error_msg);
+  bool result = false;
+  // Fast path when the runtime boot classpath cheksums and boot classpath
+  // locations directly match.
+  if (oat_boot_class_path_checksums_view == runtime->GetBootClassPathChecksums() &&
+      isa_ == kRuntimeISA &&
+      oat_boot_class_path_view == android::base::Join(runtime->GetBootClassPathLocations(), ":")) {
+    result = true;
+  } else {
+    result = gc::space::ImageSpace::VerifyBootClassPathChecksums(
+        oat_boot_class_path_checksums_view,
+        oat_boot_class_path_view,
+        runtime->GetImageLocation(),
+        ArrayRef<const std::string>(runtime->GetBootClassPathLocations()),
+        ArrayRef<const std::string>(runtime->GetBootClassPath()),
+        isa_,
+        &error_msg);
+  }
   if (!result) {
     VLOG(oat) << "Failed to verify checksums of oat file " << oat_file.GetLocation()
         << " error: " << error_msg;
-
-    if (HasOriginalDexFiles()) {
-      return false;
-    }
-
-    // If there is no original dex file to fall back to, grudgingly accept
-    // the oat file. This could technically lead to crashes, but there's no
-    // way we could find a better oat file to use for this dex location,
-    // and it's better than being stuck in a boot loop with no way out.
-    // The problem will hopefully resolve itself the next time the runtime
-    // starts up.
-    LOG(WARNING) << "Dex location " << dex_location_ << " does not seem to include dex file. "
-        << "Allow oat file use. This is potentially dangerous.";
-    return true;
+    return false;
   }
 
   // This checksum has been validated, so save it.
@@ -666,33 +686,41 @@
     // apps gets installed or when they load private, secondary dex file.
     // For apps on the system partition the odex location will not be
     // writable and thus the oat location might be more up to date.
+
+    // If the odex is not useable, and we have a useable vdex, return the vdex
+    // instead.
+    if (!odex_.IsUseable() && vdex_for_odex_.IsUseable()) {
+      return vdex_for_odex_;
+    }
     return odex_;
   }
 
   // We cannot write to the odex location. This must be a system app.
 
-  // If the oat location is usable take it.
+  // If the oat location is useable take it.
   if (oat_.IsUseable()) {
     return oat_;
   }
 
-  // The oat file is not usable but the odex file might be up to date.
+  // The oat file is not useable but the odex file might be up to date.
   // This is an indication that we are dealing with an up to date prebuilt
   // (that doesn't need relocation).
-  if (odex_.Status() == kOatUpToDate) {
+  if (odex_.IsUseable()) {
     return odex_;
   }
 
-  // The oat file is not usable and the odex file is not up to date.
-  // However we have access to the original dex file which means we can make
-  // the oat location up to date.
-  if (HasOriginalDexFiles()) {
-    return oat_;
+  // Look for a useable vdex file.
+  if (vdex_for_oat_.IsUseable()) {
+    return vdex_for_oat_;
+  }
+  if (vdex_for_odex_.IsUseable()) {
+    return vdex_for_odex_;
   }
 
   // We got into the worst situation here:
-  // - the oat location is not usable
+  // - the oat location is not useable
   // - the prebuild odex location is not up to date
+  // - the vdex-only file is not useable
   // - and we don't have the original dex file anymore (stripped).
   // Pick the odex if it exists, or the oat if not.
   return (odex_.Status() == kOatCannotOpen) ? oat_ : odex_;
@@ -732,6 +760,7 @@
   switch (Status()) {
     case kOatCannotOpen:
     case kOatDexOutOfDate:
+    case kOatContextOutOfDate:
     case kOatBootImageOutOfDate: return false;
 
     case kOatUpToDate: return true;
@@ -745,47 +774,7 @@
     status_attempted_ = true;
     const OatFile* file = GetFile();
     if (file == nullptr) {
-      // Check to see if there is a vdex file we can make use of.
-      std::string error_msg;
-      std::string vdex_filename = GetVdexFilename(filename_);
-      std::unique_ptr<VdexFile> vdex;
-      if (use_fd_) {
-        if (vdex_fd_ >= 0) {
-          struct stat s;
-          int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd_, &s));
-          if (rc == -1) {
-            error_msg = StringPrintf("Failed getting length of the vdex file %s.", strerror(errno));
-          } else {
-            vdex = VdexFile::Open(vdex_fd_,
-                                  s.st_size,
-                                  vdex_filename,
-                                  /*writable=*/ false,
-                                  /*low_4gb=*/ false,
-                                  /*unquicken=*/ false,
-                                  &error_msg);
-          }
-        }
-      } else {
-        vdex = VdexFile::Open(vdex_filename,
-                              /*writable=*/ false,
-                              /*low_4gb=*/ false,
-                              /*unquicken=*/ false,
-                              &error_msg);
-      }
-      if (vdex == nullptr) {
-        status_ = kOatCannotOpen;
-        VLOG(oat) << "unable to open vdex file " << vdex_filename << ": " << error_msg;
-      } else {
-        if (oat_file_assistant_->DexChecksumUpToDate(*vdex, &error_msg)) {
-          // The vdex file does not contain enough information to determine
-          // whether it is up to date with respect to the boot image, so we
-          // assume it is out of date.
-          VLOG(oat) << error_msg;
-          status_ = kOatBootImageOutOfDate;
-        } else {
-          status_ = kOatDexOutOfDate;
-        }
-      }
+      status_ = kOatCannotOpen;
     } else {
       status_ = oat_file_assistant_->GivenOatFileStatus(*file);
       VLOG(oat) << file->GetLocation() << " is " << status_
@@ -797,81 +786,116 @@
 
 OatFileAssistant::DexOptNeeded OatFileAssistant::OatFileInfo::GetDexOptNeeded(
     CompilerFilter::Filter target,
-    ClassLoaderContext* context,
-    const std::vector<int>& context_fds,
     bool profile_changed,
     bool downgrade) {
 
-  bool filter_okay = CompilerFilterIsOkay(target, profile_changed, downgrade);
-  bool class_loader_context_okay = ClassLoaderContextIsOkay(context, context_fds);
-
-  // Only check the filter and relocation if the class loader context is ok.
-  // If it is not, we will return kDex2OatFromScratch as the compilation needs to be redone.
-  if (class_loader_context_okay) {
-    if (filter_okay && Status() == kOatUpToDate) {
-      // The oat file is in good shape as is.
-      return kNoDexOptNeeded;
-    }
-
-    if (IsUseable()) {
-      return kDex2OatForFilter;
-    }
-
-    if (Status() == kOatBootImageOutOfDate) {
-      return kDex2OatForBootImage;
-    }
+  if (IsUseable()) {
+    return CompilerFilterIsOkay(target, profile_changed, downgrade)
+        ? kNoDexOptNeeded
+        : kDex2OatForFilter;
   }
 
-  if (oat_file_assistant_->HasOriginalDexFiles()) {
+  if (Status() == kOatBootImageOutOfDate) {
+    return kDex2OatForBootImage;
+  }
+
+  if (oat_file_assistant_->HasDexFiles()) {
     return kDex2OatFromScratch;
   } else {
-    // Otherwise there is nothing we can do, even if we want to.
+    // No dex file, there is nothing we need to do.
     return kNoDexOptNeeded;
   }
 }
 
 const OatFile* OatFileAssistant::OatFileInfo::GetFile() {
   CHECK(!file_released_) << "GetFile called after oat file released.";
-  if (!load_attempted_) {
-    load_attempted_ = true;
-    if (filename_provided_) {
-      bool executable = oat_file_assistant_->load_executable_;
-      if (executable && oat_file_assistant_->only_load_system_executable_) {
-        executable = LocationIsOnSystem(filename_.c_str());
-      }
-      VLOG(oat) << "Loading " << filename_ << " with executable: " << executable;
-      std::string error_msg;
-      if (use_fd_) {
-        if (oat_fd_ >= 0 && vdex_fd_ >= 0) {
-          ArrayRef<const std::string> dex_locations(&oat_file_assistant_->dex_location_,
-                                                    /*size=*/ 1u);
-          file_.reset(OatFile::Open(zip_fd_,
-                                    vdex_fd_,
-                                    oat_fd_,
-                                    filename_.c_str(),
-                                    executable,
-                                    /*low_4gb=*/ false,
-                                    dex_locations,
-                                    /*reservation=*/ nullptr,
-                                    &error_msg));
+  if (load_attempted_) {
+    return file_.get();
+  }
+  load_attempted_ = true;
+  if (!filename_provided_) {
+    return nullptr;
+  }
+
+  if (LocationIsOnArtApexData(filename_) && Runtime::Current()->DenyArtApexDataFiles()) {
+    LOG(WARNING) << "OatFileAssistant rejected file " << filename_
+                 << ": ART apexdata is untrusted.";
+    return nullptr;
+  }
+
+  std::string error_msg;
+  bool executable = oat_file_assistant_->load_executable_;
+  if (android::base::EndsWith(filename_, kVdexExtension)) {
+    executable = false;
+    // Check to see if there is a vdex file we can make use of.
+    std::unique_ptr<VdexFile> vdex;
+    if (use_fd_) {
+      if (vdex_fd_ >= 0) {
+        struct stat s;
+        int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd_, &s));
+        if (rc == -1) {
+          error_msg = StringPrintf("Failed getting length of the vdex file %s.", strerror(errno));
+        } else {
+          vdex = VdexFile::Open(vdex_fd_,
+                                s.st_size,
+                                filename_,
+                                /*writable=*/ false,
+                                /*low_4gb=*/ false,
+                                /*unquicken=*/ false,
+                                &error_msg);
         }
-      } else {
-        file_.reset(OatFile::Open(/*zip_fd=*/ -1,
-                                  filename_.c_str(),
+      }
+    } else {
+      vdex = VdexFile::Open(filename_,
+                            /*writable=*/ false,
+                            /*low_4gb=*/ false,
+                            /*unquicken=*/ false,
+                            &error_msg);
+    }
+    if (vdex == nullptr) {
+      VLOG(oat) << "unable to open vdex file " << filename_ << ": " << error_msg;
+    } else {
+      file_.reset(OatFile::OpenFromVdex(zip_fd_,
+                                        std::move(vdex),
+                                        oat_file_assistant_->dex_location_,
+                                        &error_msg));
+    }
+  } else {
+    if (executable && oat_file_assistant_->only_load_trusted_executable_) {
+      executable = LocationIsTrusted(filename_, /*trust_art_apex_data_files=*/ true);
+    }
+    VLOG(oat) << "Loading " << filename_ << " with executable: " << executable;
+    if (use_fd_) {
+      if (oat_fd_ >= 0 && vdex_fd_ >= 0) {
+        ArrayRef<const std::string> dex_locations(&oat_file_assistant_->dex_location_,
+                                                  /*size=*/ 1u);
+        file_.reset(OatFile::Open(zip_fd_,
+                                  vdex_fd_,
+                                  oat_fd_,
                                   filename_.c_str(),
                                   executable,
                                   /*low_4gb=*/ false,
-                                  oat_file_assistant_->dex_location_,
+                                  dex_locations,
+                                  /*reservation=*/ nullptr,
                                   &error_msg));
       }
-      if (file_.get() == nullptr) {
-        VLOG(oat) << "OatFileAssistant test for existing oat file "
-          << filename_ << ": " << error_msg;
-      } else {
-        VLOG(oat) << "Successfully loaded " << filename_ << " with executable: " << executable;
-      }
+    } else {
+      file_.reset(OatFile::Open(/*zip_fd=*/ -1,
+                                filename_.c_str(),
+                                filename_.c_str(),
+                                executable,
+                                /*low_4gb=*/ false,
+                                oat_file_assistant_->dex_location_,
+                                &error_msg));
     }
   }
+  if (file_.get() == nullptr) {
+    VLOG(oat) << "OatFileAssistant test for existing oat file "
+              << filename_
+              << ": " << error_msg;
+  } else {
+    VLOG(oat) << "Successfully loaded " << filename_ << " with executable: " << executable;
+  }
   return file_.get();
 }
 
@@ -891,46 +915,36 @@
     CompilerFilter::IsAsGoodAs(current, target);
 }
 
-bool OatFileAssistant::OatFileInfo::ClassLoaderContextIsOkay(ClassLoaderContext* context,
-                                                             const std::vector<int>& context_fds) {
-  const OatFile* file = GetFile();
-  if (file == nullptr) {
-    // No oat file means we have nothing to verify.
+bool OatFileAssistant::ClassLoaderContextIsOkay(const OatFile& oat_file) const {
+  if (oat_file.IsBackedByVdexOnly()) {
+    // Only a vdex file, we don't depend on the class loader context.
     return true;
   }
 
-  if (!CompilerFilter::IsVerificationEnabled(file->GetCompilerFilter())) {
+  if (!CompilerFilter::IsVerificationEnabled(oat_file.GetCompilerFilter())) {
     // If verification is not enabled we don't need to verify the class loader context and we
     // assume it's ok.
     return true;
   }
 
-
-  if (context == nullptr) {
-    // TODO(calin): stop using null for the unkown contexts.
-    // b/148494302 introduces runtime encoding for unknown context which will make this possible.
-    VLOG(oat) << "ClassLoaderContext check failed: uknown(null) context";
-    return false;
+  if (context_ == nullptr) {
+    // When no class loader context is provided (which happens for deprecated
+    // DexFile APIs), just assume it is OK.
+    return true;
   }
 
-  size_t dir_index = oat_file_assistant_->dex_location_.rfind('/');
-  std::string classpath_dir = (dir_index != std::string::npos)
-      ? oat_file_assistant_->dex_location_.substr(0, dir_index)
-      : "";
-
-  if (!context->OpenDexFiles(oat_file_assistant_->isa_, classpath_dir, context_fds)) {
-    VLOG(oat) << "ClassLoaderContext check failed: dex files from the context could not be opened";
-    return false;
-  }
-
-  const bool result = context->VerifyClassLoaderContextMatch(file->GetClassLoaderContext()) !=
-      ClassLoaderContext::VerificationResult::kMismatch;
-  if (!result) {
+  ClassLoaderContext::VerificationResult matches = context_->VerifyClassLoaderContextMatch(
+      oat_file.GetClassLoaderContext(),
+      /*verify_names=*/ true,
+      /*verify_checksums=*/ true);
+  if (matches == ClassLoaderContext::VerificationResult::kMismatch) {
     VLOG(oat) << "ClassLoaderContext check failed. Context was "
-              << file->GetClassLoaderContext()
-              << ". The expected context is " << context->EncodeContextForOatFile(classpath_dir);
+              << oat_file.GetClassLoaderContext()
+              << ". The expected context is "
+              << context_->EncodeContextForOatFile(android::base::Dirname(dex_location_));
+    return false;
   }
-  return result;
+  return true;
 }
 
 bool OatFileAssistant::OatFileInfo::IsExecutable() {
@@ -969,27 +983,6 @@
     return ReleaseFile();
   }
 
-  VLOG(oat) << "Oat File Assistant: No relocated oat file found,"
-    << " attempting to fall back to interpreting oat file instead.";
-
-  switch (Status()) {
-    case kOatBootImageOutOfDate:
-      // OutOfDate may be either a mismatched image, or a missing image.
-      if (oat_file_assistant_->HasOriginalDexFiles()) {
-        // If there are original dex files, it is better to use them (to avoid a potential
-        // quickening mismatch because the boot image changed).
-        break;
-      }
-      // If we do not accept the oat file, we may not have access to dex bytecode at all. Grudgingly
-      // go forward.
-      FALLTHROUGH_INTENDED;
-
-    case kOatUpToDate:
-    case kOatCannotOpen:
-    case kOatDexOutOfDate:
-      break;
-  }
-
   return std::unique_ptr<OatFile>();
 }
 
@@ -1003,38 +996,72 @@
     std::string* out_compilation_reason) {
   // It may not be possible to load an oat file executable (e.g., selinux restrictions). Load
   // non-executable and check the status manually.
-  OatFileAssistant oat_file_assistant(filename.c_str(), isa, /*load_executable=*/ false);
-  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
+  OatFileAssistant oat_file_assistant(filename.c_str(),
+                                      isa,
+                                      /* context= */ nullptr,
+                                      /*load_executable=*/ false);
+  std::string out_odex_location;  // unused
+  std::string out_odex_status;  // unused
+  oat_file_assistant.GetOptimizationStatus(
+      &out_odex_location,
+      out_compilation_filter,
+      out_compilation_reason,
+      &out_odex_status);
+}
+
+void OatFileAssistant::GetOptimizationStatus(
+    std::string* out_odex_location,
+    std::string* out_compilation_filter,
+    std::string* out_compilation_reason,
+    std::string* out_odex_status) {
+  OatFileInfo& oat_file_info = GetBestInfo();
+  const OatFile* oat_file = GetBestInfo().GetFile();
 
   if (oat_file == nullptr) {
+    *out_odex_location = "error";
     *out_compilation_filter = "run-from-apk";
     *out_compilation_reason = "unknown";
+    // This mostly happens when we cannot open the oat file.
+    // Note that it's different than kOatCannotOpen.
+    // TODO: The design of getting the BestInfo is not ideal,
+    // as it's not very clear what's the difference between
+    // a nullptr and kOatcannotOpen. The logic should be revised
+    // and improved.
+    *out_odex_status = "io-error-no-oat";
     return;
   }
 
-  OatStatus status = oat_file_assistant.GivenOatFileStatus(*oat_file);
+  *out_odex_location = oat_file->GetLocation();
+  OatStatus status = oat_file_info.Status();
   const char* reason = oat_file->GetCompilationReason();
   *out_compilation_reason = reason == nullptr ? "unknown" : reason;
   switch (status) {
-    case OatStatus::kOatUpToDate:
+    case kOatUpToDate:
       *out_compilation_filter = CompilerFilter::NameOfFilter(oat_file->GetCompilerFilter());
+      *out_odex_status = "up-to-date";
       return;
 
     case kOatCannotOpen:  // This should never happen, but be robust.
       *out_compilation_filter = "error";
       *out_compilation_reason = "error";
+      // This mostly happens when we cannot open the vdex file,
+      // or the file is corrupt.
+      *out_odex_status = "io-error-or-corruption";
       return;
 
-    // kOatBootImageOutOfDate - The oat file is up to date with respect to the
-    // dex file, but is out of date with respect to the boot image.
     case kOatBootImageOutOfDate:
-      FALLTHROUGH_INTENDED;
+      *out_compilation_filter = "run-from-apk-fallback";
+      *out_odex_status = "boot-image-more-recent";
+      return;
+
+    case kOatContextOutOfDate:
+      *out_compilation_filter = "run-from-apk-fallback";
+      *out_odex_status = "context-mismatch";
+      return;
+
     case kOatDexOutOfDate:
-      if (oat_file_assistant.HasOriginalDexFiles()) {
-        *out_compilation_filter = "run-from-apk-fallback";
-      } else {
-        *out_compilation_filter = "run-from-vdex-fallback";
-      }
+      *out_compilation_filter = "run-from-apk-fallback";
+      *out_odex_status = "apk-more-recent";
       return;
   }
   LOG(FATAL) << "Unreachable";
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index aa4d83b..9cfa781 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -22,11 +22,11 @@
 #include <sstream>
 #include <string>
 
+#include "base/compiler_filter.h"
 #include "arch/instruction_set.h"
 #include "base/os.h"
 #include "base/scoped_flock.h"
 #include "base/unix_file/fd_file.h"
-#include "compiler_filter.h"
 #include "class_loader_context.h"
 #include "oat_file.h"
 
@@ -80,6 +80,10 @@
     // dex file, but is out of date with respect to the boot image.
     kOatBootImageOutOfDate,
 
+    // kOatContextOutOfDate - The context in the oat file is out of date with
+    // respect to the class loader context.
+    kOatContextOutOfDate,
+
     // kOatUpToDate - The oat file is completely up to date with respect to
     // the dex file and boot image.
     kOatUpToDate,
@@ -103,26 +107,27 @@
   // load_executable should be true if the caller intends to try and load
   // executable code for this dex location.
   //
-  // only_load_system_executable should be true if the caller intends to have
-  // only oat files from /system loaded executable.
+  // only_load_trusted_executable should be true if the caller intends to have
+  // only oat files from trusted locations loaded executable. See IsTrustedLocation() for
+  // details on trusted locations.
   OatFileAssistant(const char* dex_location,
                    const InstructionSet isa,
+                   ClassLoaderContext* context,
                    bool load_executable,
-                   bool only_load_system_executable = false);
+                   bool only_load_trusted_executable = false);
 
   // Similar to this(const char*, const InstructionSet, bool), however, if a valid zip_fd is
   // provided, vdex, oat, and zip files will be read from vdex_fd, oat_fd and zip_fd respectively.
   // Otherwise, dex_location will be used to construct necessary filenames.
   OatFileAssistant(const char* dex_location,
                    const InstructionSet isa,
+                   ClassLoaderContext* context,
                    bool load_executable,
-                   bool only_load_system_executable,
+                   bool only_load_trusted_executable,
                    int vdex_fd,
                    int oat_fd,
                    int zip_fd);
 
-  ~OatFileAssistant();
-
   // Returns true if the dex location refers to an element of the boot class
   // path.
   bool IsInBootClassPath();
@@ -144,8 +149,6 @@
   // the oat location. Returns a negative status code if the status refers to
   // the oat file in the odex location.
   int GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
-                      ClassLoaderContext* context,
-                      const std::vector<int>& context_fds,
                       bool profile_changed = false,
                       bool downgrade = false);
 
@@ -167,13 +170,22 @@
 
   // Computes the optimization status of the given dex file. The result is
   // returned via the two output parameters.
+  //   - out_odex_location: the location of the (best) odex that will be used
+  //        for loading. See GetBestInfo().
   //   - out_compilation_filter: the level of optimizations (compiler filter)
   //   - out_compilation_reason: the optimization reason. The reason might
   //        be "unknown" if the compiler artifacts were not annotated during optimizations.
+  //   - out_odex_status: a human readable refined status of the validity of the odex file.
+  //        E.g. up-to-date, boot-image-more-recent, apk-more-recent.
   //
   // This method will try to mimic the runtime effect of loading the dex file.
   // For example, if there is no usable oat file, the compiler filter will be set
   // to "run-from-apk".
+  void GetOptimizationStatus(std::string* out_odex_location,
+                             std::string* out_compilation_filter,
+                             std::string* out_compilation_reason,
+                             std::string* out_odex_status);
+
   static void GetOptimizationStatus(const std::string& filename,
                                     InstructionSet isa,
                                     std::string* out_compilation_filter,
@@ -200,11 +212,8 @@
                            const std::string& dex_location,
                            std::vector<std::unique_ptr<const DexFile>>* out_dex_files);
 
-  // Returns true if there are dex files in the original dex location that can
-  // be compiled with dex2oat for this dex location.
-  // Returns false if there is no original dex file, or if the original dex
-  // file is an apk/zip without a classes.dex entry.
-  bool HasOriginalDexFiles();
+  // Returns whether this is an apk/zip wit a classes.dex entry.
+  bool HasDexFiles();
 
   // If the dex file has been installed with a compiled oat file alongside
   // it, the compiled oat file will have the extension .odex, and is referred
@@ -223,6 +232,10 @@
   // Returns the status of the oat file for the dex location.
   OatStatus OatFileStatus();
 
+  OatStatus GetBestStatus() {
+    return GetBestInfo().Status();
+  }
+
   // Constructs the odex file name for the given dex location.
   // Returns true on success, in which case odex_filename is set to the odex
   // file name.
@@ -245,14 +258,12 @@
                                        std::string* oat_filename,
                                        std::string* error_msg);
 
-  // Computes the location checksum, dex location and vdex filename by combining
-  // the checksums of the individual dex files. If the data directory of the process
+  // Computes the dex location and vdex filename. If the data directory of the process
   // is known, creates an absolute path in that directory and tries to infer path
   // of a corresponding vdex file. Otherwise only creates a basename dex_location
   // from the combined checksums. Returns true if all out-arguments have been set.
   static bool AnonymousDexVdexLocation(const std::vector<const DexFile::Header*>& dex_headers,
                                        InstructionSet isa,
-                                       /* out */ uint32_t* location_checksum,
                                        /* out */ std::string* dex_location,
                                        /* out */ std::string* vdex_filename);
 
@@ -260,6 +271,8 @@
   // anonymous dex file(s) created by AnonymousDexVdexLocation.
   static bool IsAnonymousVdexBasename(const std::string& basename);
 
+  bool ClassLoaderContextIsOkay(const OatFile& oat_file) const;
+
  private:
   class OatFileInfo {
    public:
@@ -292,8 +305,6 @@
     // downgrade should be true if the purpose of dexopt is to downgrade the
     // compiler filter.
     DexOptNeeded GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
-                                 ClassLoaderContext* context,
-                                 const std::vector<int>& context_fds,
                                  bool profile_changed,
                                  bool downgrade);
 
@@ -336,8 +347,6 @@
     // compiler filter.
     bool CompilerFilterIsOkay(CompilerFilter::Filter target, bool profile_changed, bool downgrade);
 
-    bool ClassLoaderContextIsOkay(ClassLoaderContext* context, const std::vector<int>& context_fds);
-
     // Release the loaded oat file.
     // Returns null if the oat file hasn't been loaded.
     //
@@ -403,13 +412,10 @@
   // Validates the boot class path checksum of an OatFile.
   bool ValidateBootClassPathChecksums(const OatFile& oat_file);
 
-  // To implement Lock(), we lock a dummy file where the oat file would go
-  // (adding ".flock" to the target file name) and retain the lock for the
-  // remaining lifetime of the OatFileAssistant object.
-  ScopedFlock flock_;
-
   std::string dex_location_;
 
+  ClassLoaderContext* context_;
+
   // Whether or not the parent directory of the dex file is writable.
   bool dex_parent_writable_ = false;
 
@@ -420,8 +426,8 @@
   // Whether we will attempt to load oat files executable.
   bool load_executable_ = false;
 
-  // Whether only oat files on /system are loaded executable.
-  const bool only_load_system_executable_ = false;
+  // Whether only oat files from trusted locations are loaded executable.
+  const bool only_load_trusted_executable_ = false;
   // Whether the potential zip file only contains uncompressed dex.
   // Will be set during GetRequiredDexChecksums.
   bool zip_file_only_contains_uncompressed_dex_ = true;
@@ -433,9 +439,19 @@
   bool required_dex_checksums_found_;
   bool has_original_dex_files_;
 
+  // The AOT-compiled file of an app when the APK of the app is in /data.
   OatFileInfo odex_;
+  // The AOT-compiled file of an app when the APK of the app is on a read-only partition
+  // (for example /system).
   OatFileInfo oat_;
 
+  // The vdex-only file next to `odex_` when `odex_' cannot be used (for example
+  // it is out of date).
+  OatFileInfo vdex_for_odex_;
+  // The vdex-only file next to 'oat_` when `oat_' cannot be used (for example
+  // it is out of date).
+  OatFileInfo vdex_for_oat_;
+
   // File descriptor corresponding to apk, dex file, or zip.
   int zip_fd_;
 
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index ed47ca3..68ae83d 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -44,23 +44,49 @@
 
 class OatFileAssistantTest : public DexoptTest {
  public:
-  void VerifyOptimizationStatus(const std::string& file,
+  void VerifyOptimizationStatus(OatFileAssistant* assistant,
+                                const std::string& file,
                                 const std::string& expected_filter,
-                                const std::string& expected_reason) {
-    std::string compilation_filter;
-    std::string compilation_reason;
-    OatFileAssistant::GetOptimizationStatus(
-        file, kRuntimeISA, &compilation_filter, &compilation_reason);
+                                const std::string& expected_reason,
+                                const std::string& expected_odex_status) {
+    // Verify the static methods (called from PM for dexOptNeeded).
+    std::string compilation_filter1;
+    std::string compilation_reason1;
 
-    ASSERT_EQ(expected_filter, compilation_filter);
-    ASSERT_EQ(expected_reason, compilation_reason);
+    OatFileAssistant::GetOptimizationStatus(
+        file, kRuntimeISA, &compilation_filter1, &compilation_reason1);
+
+    ASSERT_EQ(expected_filter, compilation_filter1);
+    ASSERT_EQ(expected_reason, compilation_reason1);
+
+    // Verify the instance methods (called at runtime for systrace).
+    std::string odex_location2;  // ignored
+    std::string compilation_filter2;
+    std::string compilation_reason2;
+    std::string odex_status2;
+
+    assistant->GetOptimizationStatus(
+        &odex_location2,
+        &compilation_filter2,
+        &compilation_reason2,
+        &odex_status2);
+
+    ASSERT_EQ(expected_filter, compilation_filter2);
+    ASSERT_EQ(expected_reason, compilation_reason2);
+    ASSERT_EQ(expected_odex_status, odex_status2);
   }
 
-  void VerifyOptimizationStatus(const std::string& file,
+  void VerifyOptimizationStatus(OatFileAssistant* assistant,
+                                const std::string& file,
                                 CompilerFilter::Filter expected_filter,
-                                const std::string& expected_reason) {
+                                const std::string& expected_reason,
+                                const std::string& expected_odex_status) {
       VerifyOptimizationStatus(
-          file, CompilerFilter::NameOfFilter(expected_filter), expected_reason);
+          assistant,
+          file,
+          CompilerFilter::NameOfFilter(expected_filter),
+          expected_reason,
+          expected_odex_status);
   }
 
   void InsertNewBootClasspathEntry() {
@@ -72,32 +98,24 @@
     }
   }
 
-  int GetDexOptNeeded(OatFileAssistant* assistant,
-                      CompilerFilter::Filter compiler_filter,
-                      bool profile_changed) {
-    std::vector<int> context_fds;
-    return GetDexOptNeeded(assistant,
-        compiler_filter,
-        ClassLoaderContext::Default(),
-        context_fds,
-        profile_changed,
-        /*downgrade=*/ false);
-  }
-
   int GetDexOptNeeded(
       OatFileAssistant* assistant,
       CompilerFilter::Filter compiler_filter,
-      const std::unique_ptr<ClassLoaderContext>& context = ClassLoaderContext::Default(),
-      const std::vector<int>& context_fds = std::vector<int>(),
       bool profile_changed = false,
       bool downgrade = false) {
     return assistant->GetDexOptNeeded(
         compiler_filter,
-        context.get(),
-        context_fds,
         profile_changed,
         downgrade);
   }
+
+  static std::unique_ptr<ClassLoaderContext> InitializeDefaultContext() {
+    auto context = ClassLoaderContext::Default();
+    context->OpenDexFiles();
+    return context;
+  }
+
+  std::unique_ptr<ClassLoaderContext> default_context_ = InitializeDefaultContext();
 };
 
 class ScopedNonWritable {
@@ -155,7 +173,10 @@
   ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
 
   // Verify we can load both dex files.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -172,12 +193,12 @@
   Copy(GetDexSrc1(), dex_location);
   Copy(GetDexSrc2(), context_location);
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
-
   std::string context_str = "PCL[" + context_location + "]";
   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
   ASSERT_TRUE(context != nullptr);
-  ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
+
+  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, context.get(), false);
 
   std::string error_msg;
   std::vector<std::string> args;
@@ -187,7 +208,8 @@
   ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
-  EXPECT_NE(nullptr, oat_file.get());
+  ASSERT_NE(nullptr, oat_file.get());
+  ASSERT_NE(nullptr, oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
   EXPECT_EQ(context->EncodeContextForOatFile(""),
             oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
 }
@@ -199,27 +221,27 @@
   Copy(GetDexSrc1(), dex_location);
   Copy(GetDexSrc2(), context_location);
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  // A relative context simulates a dependent split context.
+  std::unique_ptr<ClassLoaderContext> relative_context =
+      ClassLoaderContext::Create("PCL[ContextDex.jar]");
+  ASSERT_TRUE(relative_context != nullptr);
+  std::vector<int> context_fds;
+  ASSERT_TRUE(relative_context->OpenDexFiles(GetScratchDir(), context_fds));
 
-  std::string context_str = "PCL[" + context_location + "]";
-  std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
-  ASSERT_TRUE(context != nullptr);
-  ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      relative_context.get(),
+                                      false);
 
   std::string error_msg;
   std::vector<std::string> args;
   args.push_back("--dex-file=" + dex_location);
   args.push_back("--oat-file=" + odex_location);
-  args.push_back("--class-loader-context=" + context_str);
+  args.push_back("--class-loader-context=PCL[" + context_location + "]");
   ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
 
-  // A relative context simulates a dependent split context.
-  std::unique_ptr<ClassLoaderContext> relative_context =
-      ClassLoaderContext::Create("PCL[ContextDex.jar]");
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-            GetDexOptNeeded(&oat_file_assistant,
-                CompilerFilter::kDefaultCompilerFilter,
-                relative_context));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kDefaultCompilerFilter));
 }
 
 // Case: We have a DEX file, but no OAT file for it.
@@ -228,12 +250,15 @@
   std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
   Copy(GetDexSrc1(), dex_location);
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile));
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
@@ -242,9 +267,14 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 
-  VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
+  VerifyOptimizationStatus(
+      &oat_file_assistant,
+      dex_location,
+      "run-from-apk",
+      "unknown",
+      "io-error-no-oat");
 }
 
 // Case: We have no DEX file and no OAT file.
@@ -252,11 +282,14 @@
 TEST_F(OatFileAssistantTest, NoDexNoOat) {
   std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
-  EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_FALSE(oat_file_assistant.HasDexFiles());
 
   // Trying to get the best oat file should fail, but not crash.
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
@@ -273,12 +306,15 @@
 
   // Force the use of oat location by making the dex parent not writable.
   OatFileAssistant oat_file_assistant(
-      dex_location.c_str(), kRuntimeISA, /*load_executable=*/ false);
+      dex_location.c_str(),
+      kRuntimeISA,
+      default_context_.get(),
+      /*load_executable=*/ false);
 
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
             GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
             GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
@@ -287,9 +323,14 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 
-  VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install");
+  VerifyOptimizationStatus(
+      &oat_file_assistant,
+      dex_location,
+      CompilerFilter::kSpeed,
+      "install",
+      "up-to-date");
 }
 
 // Case: We have an ODEX file compiled against partial boot image.
@@ -305,12 +346,15 @@
 
   // Force the use of oat location by making the dex parent not writable.
   OatFileAssistant oat_file_assistant(
-      dex_location.c_str(), kRuntimeISA, /*load_executable=*/ false);
+      dex_location.c_str(),
+      kRuntimeISA,
+      default_context_.get(),
+      /*load_executable=*/ false);
 
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
             GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
             GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
@@ -319,9 +363,14 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 
-  VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install");
+  VerifyOptimizationStatus(
+      &oat_file_assistant,
+      dex_location,
+      CompilerFilter::kSpeed,
+      "install",
+      "up-to-date");
 }
 
 // Case: We have a DEX file and a PIC ODEX file, but no OAT file. We load the dex
@@ -340,12 +389,15 @@
   ASSERT_EQ(0, symlink(scratch_dir.c_str(), link.c_str()));
   dex_location = link + "/OdexUpToDate.jar";
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
@@ -354,7 +406,7 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 }
 
 // Case: We have a DEX file and up-to-date OAT file for it.
@@ -374,12 +426,15 @@
   ScopedNonWritable scoped_non_writable(dex_location);
   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
@@ -388,9 +443,14 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 
-  VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "unknown");
+  VerifyOptimizationStatus(
+      &oat_file_assistant,
+      dex_location,
+      CompilerFilter::kSpeed,
+      "unknown",
+      "up-to-date");
 }
 
 // Case: Passing valid file descriptors of updated odex/vdex files along with the dex file.
@@ -412,6 +472,7 @@
 
   OatFileAssistant oat_file_assistant(dex_location.c_str(),
                                       kRuntimeISA,
+                                      default_context_.get(),
                                       false,
                                       false,
                                       vdex_fd.get(),
@@ -420,7 +481,7 @@
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
@@ -429,7 +490,7 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 }
 
 // Case: Passing invalid odex fd and valid vdex and zip fds.
@@ -450,20 +511,23 @@
 
   OatFileAssistant oat_file_assistant(dex_location.c_str(),
                                       kRuntimeISA,
+                                      default_context_.get(),
                                       false,
                                       false,
                                       vdex_fd.get(),
                                       /* oat_fd= */ -1,
                                       zip_fd.get());
-  EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
+  EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
+  EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
-  EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
+  EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
-  EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus());
+  EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 }
 
 // Case: Passing invalid vdex fd and valid odex and zip fds.
@@ -483,6 +547,7 @@
 
   OatFileAssistant oat_file_assistant(dex_location.c_str(),
                                       kRuntimeISA,
+                                      default_context_.get(),
                                       false,
                                       false,
                                       /* vdex_fd= */ -1,
@@ -494,7 +559,7 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 }
 
 // Case: Passing invalid vdex and odex fd with valid zip fd.
@@ -507,6 +572,7 @@
   android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
   OatFileAssistant oat_file_assistant(dex_location.c_str(),
                                       kRuntimeISA,
+                                      default_context_.get(),
                                       false,
                                       false,
                                       /* vdex_fd= */ -1,
@@ -518,7 +584,7 @@
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
 }
 
-// Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no
+// Case: We have a DEX file and up-to-date VDEX file for it, but no
 // ODEX file.
 TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
   std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
@@ -531,21 +597,26 @@
   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
   ASSERT_EQ(0, unlink(odex_location.c_str()));
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
-  // Even though the vdex file is up to date, because we don't have the oat
-  // file, we can't know that the vdex depends on the boot image and is up to
-  // date with respect to the boot image. Instead we must assume the vdex file
-  // depends on the boot image and is out of date with respect to the boot
-  // image.
-  EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
+  EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
+  EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   // Make sure we don't crash in this case when we dump the status. We don't
   // care what the actual dumped value is.
   oat_file_assistant.GetStatusDump();
 
-  VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
+  VerifyOptimizationStatus(
+      &oat_file_assistant,
+      dex_location,
+      "verify",
+      "vdex",
+      "up-to-date");
 }
 
 // Case: We have a DEX file and empty VDEX and ODEX files.
@@ -558,7 +629,10 @@
   ScratchFile vdex_file(vdex_location.c_str());
   ScratchFile odex_file(odex_location.c_str());
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 }
@@ -584,14 +658,12 @@
 
   ScopedNonWritable scoped_non_writable(dex_location);
   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
-  // Even though the vdex file is up to date, because we don't have the oat
-  // file, we can't know that the vdex depends on the boot image and is up to
-  // date with respect to the boot image. Instead we must assume the vdex file
-  // depends on the boot image and is out of date with respect to the boot
-  // image.
-  EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
+  EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 }
 
@@ -612,21 +684,24 @@
   ScopedNonWritable scoped_non_writable(dex_location);
   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile, false));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken, false));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify, false));
   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile, true));
   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken, true));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify, true));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 }
 
 // Case: We have a MultiDEX file and up-to-date OAT file for it.
@@ -645,10 +720,13 @@
   ScopedNonWritable scoped_non_writable(dex_location);
   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 
   // Verify we can load both dex files.
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
@@ -681,41 +759,13 @@
   ScopedNonWritable scoped_non_writable(dex_location);
   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
-}
-
-// Case: We have a stripped MultiDEX file where the non-main multidex entry is
-// out of date with respect to the odex file.
-TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) {
-  std::string dex_location = GetScratchDir() + "/StrippedMultiDexNonMainOutOfDate.jar";
-  std::string odex_location = GetOdexDir() + "/StrippedMultiDexNonMainOutOfDate.odex";
-
-  // Compile the oat from GetMultiDexSrc1.
-  Copy(GetMultiDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
-
-  // Compile the odex from GetMultiDexSrc2, which has a different non-main
-  // dex checksum.
-  Copy(GetMultiDexSrc2(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken);
-
-  // Strip the dex file.
-  Copy(GetStrippedDexSrc1(), dex_location);
-
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, /*load_executable=*/false);
-
-  // Because the dex file is stripped, the odex file is considered the source
-  // of truth for the dex checksums. The oat file should be considered
-  // unusable.
-  std::unique_ptr<OatFile> best_file = oat_file_assistant.GetBestOatFile();
-  ASSERT_TRUE(best_file.get() != nullptr);
-  EXPECT_EQ(best_file->GetLocation(), odex_location);
-  EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
-  EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
-  EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 }
 
 // Case: We have a DEX file and an OAT file out of date with respect to the
@@ -738,7 +788,10 @@
   ScopedNonWritable scoped_non_writable(dex_location);
   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
@@ -747,7 +800,14 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
+
+  VerifyOptimizationStatus(
+      &oat_file_assistant,
+      dex_location,
+      "run-from-apk-fallback",
+      "unknown",
+      "apk-more-recent");
 }
 
 // Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
@@ -761,7 +821,10 @@
   ASSERT_EQ(0, unlink(odex_location.c_str()));
   Copy(GetDexSrc2(), dex_location);
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
@@ -778,7 +841,10 @@
   ASSERT_EQ(0, unlink(odex_location.c_str()));
   Copy(GetMultiDexSrc2(), dex_location);
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
@@ -803,18 +869,28 @@
   ScopedNonWritable scoped_non_writable(dex_location);
   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
-  EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
-  EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
-  EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
+  EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
+
+  VerifyOptimizationStatus(
+      &oat_file_assistant,
+      dex_location,
+      "verify",
+      "vdex",
+      "up-to-date");
 }
 
 // Case: We have a DEX file and a verify-at-runtime OAT file out of date with
@@ -838,16 +914,19 @@
   ScopedNonWritable scoped_non_writable(dex_location);
   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 }
 
 // Case: We have a DEX file and an ODEX file, but no OAT file.
@@ -860,7 +939,10 @@
   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
 
   // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
@@ -870,106 +952,37 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 
   // We should still be able to get the non-executable odex file to run from.
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
 }
 
-// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
-TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
-  std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
-  std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
-
-  // Create the dex and odex files
-  Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
-
-  // Strip the dex file
-  Copy(GetStrippedDexSrc1(), dex_location);
-
-  // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
-
-  EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
-
-  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
-  EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
-  EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
-
-  // Verify we can load the dex files from it.
-  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
-  ASSERT_TRUE(oat_file.get() != nullptr);
-  EXPECT_TRUE(oat_file->IsExecutable());
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
-  EXPECT_EQ(1u, dex_files.size());
-}
-
-// Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file.
-TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
-  std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
-  std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
-
-  // Create the oat file from a different dex file so it looks out of date.
-  Copy(GetDexSrc2(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
-
-  // Create the odex file
-  Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
-
-  // Strip the dex file.
-  Copy(GetStrippedDexSrc1(), dex_location);
-
-  // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
-
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
-  EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,  // Compiling from the .vdex file
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
-
-  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
-  EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
-  EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
-  EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
-
-  // Verify we can load the dex files from it.
-  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
-  ASSERT_TRUE(oat_file.get() != nullptr);
-  EXPECT_TRUE(oat_file->IsExecutable());
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
-  EXPECT_EQ(1u, dex_files.size());
-}
-
-// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
+// Case: We have a resource-only DEX file, no ODEX file and no
 // OAT file. Expect: The status is kNoDexOptNeeded.
 TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
   std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
 
-  Copy(GetStrippedDexSrc1(), dex_location);
+  Copy(GetResourceOnlySrc1(), dex_location);
 
   // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_FALSE(oat_file_assistant.HasDexFiles());
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
@@ -977,7 +990,7 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_FALSE(oat_file_assistant.HasDexFiles());
 }
 
 // Case: We have a DEX file, an ODEX file and an OAT file.
@@ -992,7 +1005,10 @@
   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
 
   // Verify things don't go bad.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
             GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
@@ -1000,7 +1016,7 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1022,7 +1038,10 @@
   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
 
   // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
@@ -1032,7 +1051,7 @@
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_TRUE(oat_file_assistant.HasDexFiles());
 }
 
 // Case: We have a DEX file and up-to-date OAT file for it.
@@ -1053,7 +1072,10 @@
   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
 
   // Load the oat using an oat file assistant.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1075,13 +1097,16 @@
   std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
 
   Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
+  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kVerify);
 
   ScopedNonWritable scoped_non_writable(dex_location);
   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
 
   // Load the oat using an oat file assistant.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1110,7 +1135,10 @@
   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
 
   // Load the oat using an oat file assistant.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1163,7 +1191,10 @@
   Copy(GetDexSrc1(), abs_dex_location);
 
   std::string dex_location = MakePathRelative(abs_dex_location);
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
@@ -1177,14 +1208,17 @@
 TEST_F(OatFileAssistantTest, ShortDexLocation) {
   std::string dex_location = "/xx";
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
-  EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
+  EXPECT_FALSE(oat_file_assistant.HasDexFiles());
 }
 
 // Case: Non-standard extension for dex file.
@@ -1193,7 +1227,10 @@
   std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
   Copy(GetDexSrc1(), dex_location);
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      false);
 
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
       GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
@@ -1299,7 +1336,7 @@
 
 // Case: We have a DEX file and an ODEX file, and no OAT file,
 // Expect: We should load the odex file executable.
-TEST_F(DexoptTest, LoadDexOdexNoOat) {
+TEST_F(OatFileAssistantTest, LoadDexOdexNoOat) {
   std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
   std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
 
@@ -1308,7 +1345,10 @@
   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
 
   // Load the oat using an executable oat file assistant.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1320,7 +1360,7 @@
 
 // Case: We have a MultiDEX file and an ODEX file, and no OAT file.
 // Expect: We should load the odex file executable.
-TEST_F(DexoptTest, LoadMultiDexOdexNoOat) {
+TEST_F(OatFileAssistantTest, LoadMultiDexOdexNoOat) {
   std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
   std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
 
@@ -1329,7 +1369,10 @@
   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
 
   // Load the oat using an executable oat file assistant.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+                                      kRuntimeISA,
+                                      default_context_.get(),
+                                      true);
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1396,7 +1439,7 @@
 
   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
   ASSERT_TRUE(context != nullptr);
-  ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
+  ASSERT_TRUE(context->OpenDexFiles());
 
   std::string error_msg;
   std::vector<std::string> args;
@@ -1411,24 +1454,39 @@
   {
     std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
     ASSERT_TRUE(updated_context != nullptr);
-    OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
-    // DexOptNeeded should advise compilation from scratch when the context changes.
-    EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-              GetDexOptNeeded(&oat_file_assistant,
-                    CompilerFilter::kDefaultCompilerFilter,
-                    updated_context));
+    std::vector<int> context_fds;
+    ASSERT_TRUE(updated_context->OpenDexFiles("", context_fds,  /*only_read_checksums*/ true));
+    OatFileAssistant oat_file_assistant(
+        dex_location.c_str(), kRuntimeISA, updated_context.get(), false);
+    // DexOptNeeded should advise compilation for filter when the context changes.
+    EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
+              GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kDefaultCompilerFilter));
   }
   {
     std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
     ASSERT_TRUE(updated_context != nullptr);
-    OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+    std::vector<int> context_fds;
+    ASSERT_TRUE(updated_context->OpenDexFiles("", context_fds,  /*only_read_checksums*/ true));
+    OatFileAssistant oat_file_assistant(
+        dex_location.c_str(), kRuntimeISA, updated_context.get(), false);
     // Now check that DexOptNeeded does not advise compilation if we only extracted the file.
     args.push_back("--compiler-filter=extract");
     ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
     EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-              GetDexOptNeeded(&oat_file_assistant,
-                    CompilerFilter::kExtract,
-                    updated_context));
+              GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
+  }
+  {
+    std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
+    ASSERT_TRUE(updated_context != nullptr);
+    std::vector<int> context_fds;
+    ASSERT_TRUE(updated_context->OpenDexFiles("", context_fds,  /*only_read_checksums*/ true));
+    OatFileAssistant oat_file_assistant(
+        dex_location.c_str(), kRuntimeISA, updated_context.get(), false);
+    // Now check that DexOptNeeded does not advise compilation if we only verify the file.
+    args.push_back("--compiler-filter=verify");
+    ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
+    EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
+              GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   }
 }
 
@@ -1437,6 +1495,7 @@
 TEST_F(OatFileAssistantTest, GetDexLocation) {
   std::string dex_location = GetScratchDir() + "/TestDex.jar";
   std::string oat_location = GetOdexDir() + "/TestDex.odex";
+  std::string art_location = GetOdexDir() + "/TestDex.art";
 
   // Start the runtime to initialize the system's class loader.
   Thread::Current()->TransitionFromSuspendedToRunnable();
@@ -1463,6 +1522,7 @@
     args.push_back("--dex-file=" + dex_location);
     args.push_back("--dex-location=TestDex.jar");
     args.push_back("--oat-file=" + oat_location);
+    args.push_back("--app-image-file=" + art_location);
     std::string error_msg;
     ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
   }
@@ -1490,8 +1550,12 @@
   odex_dir = odex_dir + std::string(GetInstructionSetString(kRuntimeISA));
   mkdir(odex_dir.c_str(), 0700);
   std::string oat_location = odex_dir + "/" + filebase + ".odex";
+  std::string vdex_location = odex_dir + "/" + filebase + ".vdex";
+  std::string art_location = odex_dir + "/" + filebase + ".art";
   // Clean up in case previous run crashed.
   remove(oat_location.c_str());
+  remove(vdex_location.c_str());
+  remove(art_location.c_str());
 
   // Start the runtime to initialize the system's class loader.
   Thread::Current()->TransitionFromSuspendedToRunnable();
@@ -1527,6 +1591,7 @@
     args.push_back("--dex-file=" + dex_location);
     args.push_back("--dex-location=" + filebase + ".jar");
     args.push_back("--oat-file=" + oat_location);
+    args.push_back("--app-image-file=" + art_location);
     std::string error_msg;
     ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
   }
@@ -1554,6 +1619,89 @@
   EXPECT_EQ(0, remove(oat_location.c_str()));
 }
 
+// Make sure OAT files that require app images are not loaded as executable.
+TEST_F(OatFileAssistantTest, LoadOatNoArt) {
+  std::string dex_location = GetScratchDir() + "/TestDex.jar";
+  std::string odex_location = GetOdexDir() + "/TestDex.odex";
+  std::string art_location = GetOdexDir() + "/TestDex.art";
+  Copy(GetDexSrc1(), dex_location);
+  GenerateOdexForTest(dex_location,
+                      odex_location,
+                      CompilerFilter::kSpeed,
+                      "install",
+                      {
+                          "--app-image-file=" + art_location,
+                      });
+
+  unlink(art_location.c_str());
+
+  std::vector<std::string> error_msgs;
+  const OatFile* oat_file = nullptr;
+
+  // Start the runtime to initialize the system's class loader.
+  Thread::Current()->TransitionFromSuspendedToRunnable();
+  runtime_->Start();
+
+  const auto dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
+      dex_location.c_str(),
+      Runtime::Current()->GetSystemClassLoader(),
+      /*dex_elements=*/nullptr,
+      &oat_file,
+      &error_msgs);
+
+  EXPECT_FALSE(dex_files.empty());
+  ASSERT_NE(oat_file, nullptr);
+  EXPECT_FALSE(oat_file->IsExecutable());
+}
+
+TEST_F(OatFileAssistantTest, GetDexOptNeededWithApexVersions) {
+  std::string dex_location = GetScratchDir() + "/TestDex.jar";
+  std::string odex_location = GetOdexDir() + "/TestDex.odex";
+  Copy(GetDexSrc1(), dex_location);
+
+  // Test that using the current's runtime apex versions works.
+  {
+    std::string error_msg;
+    std::vector<std::string> args;
+    args.push_back("--dex-file=" + dex_location);
+    args.push_back("--oat-file=" + odex_location);
+    args.push_back("--apex-versions=" + Runtime::Current()->GetApexVersions());
+    ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
+
+    OatFileAssistant oat_file_assistant(
+        dex_location.c_str(), kRuntimeISA, default_context_.get(), false);
+    EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
+  }
+
+  // Test that a subset of apex versions works.
+  {
+    std::string error_msg;
+    std::vector<std::string> args;
+    args.push_back("--dex-file=" + dex_location);
+    args.push_back("--oat-file=" + odex_location);
+    args.push_back("--apex-versions=" + Runtime::Current()->GetApexVersions().substr(0, 1));
+    ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
+
+    OatFileAssistant oat_file_assistant(
+        dex_location.c_str(), kRuntimeISA, default_context_.get(), false);
+    EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
+  }
+
+  // Test that different apex versions require to recompile.
+  {
+    std::string error_msg;
+    std::vector<std::string> args;
+    args.push_back("--dex-file=" + dex_location);
+    args.push_back("--oat-file=" + odex_location);
+    args.push_back("--apex-versions=/1/2/3/4");
+    ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
+
+    OatFileAssistant oat_file_assistant(
+        dex_location.c_str(), kRuntimeISA, default_context_.get(), false);
+    EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage, oat_file_assistant.OdexFileStatus());
+  }
+}
+
 // TODO: More Tests:
 //  * Test class linker falls back to unquickened dex for DexNoOat
 //  * Test class linker falls back to unquickened dex for MultiDexNoOat
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 118dd01..542ea09 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -21,6 +21,7 @@
 #include <vector>
 #include <sys/stat.h>
 
+#include "android-base/file.h"
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
 
@@ -65,9 +66,13 @@
 static constexpr bool kEnableAppImage = true;
 
 const OatFile* OatFileManager::RegisterOatFile(std::unique_ptr<const OatFile> oat_file) {
+  // Use class_linker vlog to match the log for dex file registration.
+  VLOG(class_linker) << "Registered oat file " << oat_file->GetLocation();
+  PaletteNotifyOatFileLoaded(oat_file->GetLocation().c_str());
+
   WriterMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
   CHECK(!only_use_system_oat_files_ ||
-        LocationIsOnSystem(oat_file->GetLocation().c_str()) ||
+        LocationIsTrusted(oat_file->GetLocation(), !Runtime::Current()->DenyArtApexDataFiles()) ||
         !oat_file->IsExecutable())
       << "Registering a non /system oat file: " << oat_file->GetLocation();
   DCHECK(oat_file != nullptr);
@@ -136,20 +141,6 @@
   return oat_files;
 }
 
-const OatFile* OatFileManager::GetPrimaryOatFile() const {
-  ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
-  std::vector<const OatFile*> boot_oat_files = GetBootOatFiles();
-  if (!boot_oat_files.empty()) {
-    for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
-      if (std::find(boot_oat_files.begin(), boot_oat_files.end(), oat_file.get()) ==
-          boot_oat_files.end()) {
-        return oat_file.get();
-      }
-    }
-  }
-  return nullptr;
-}
-
 OatFileManager::OatFileManager()
     : only_use_system_oat_files_(false) {}
 
@@ -169,286 +160,9 @@
   return oat_files;
 }
 
-class TypeIndexInfo {
- public:
-  explicit TypeIndexInfo(const DexFile* dex_file)
-      : type_indexes_(GenerateTypeIndexes(dex_file)),
-        iter_(type_indexes_.Indexes().begin()),
-        end_(type_indexes_.Indexes().end()) { }
-
-  BitVector& GetTypeIndexes() {
-    return type_indexes_;
-  }
-  BitVector::IndexIterator& GetIterator() {
-    return iter_;
-  }
-  BitVector::IndexIterator& GetIteratorEnd() {
-    return end_;
-  }
-  void AdvanceIterator() {
-    iter_++;
-  }
-
- private:
-  static BitVector GenerateTypeIndexes(const DexFile* dex_file) {
-    BitVector type_indexes(/*start_bits=*/0, /*expandable=*/true, Allocator::GetMallocAllocator());
-    for (uint16_t i = 0; i < dex_file->NumClassDefs(); ++i) {
-      const dex::ClassDef& class_def = dex_file->GetClassDef(i);
-      uint16_t type_idx = class_def.class_idx_.index_;
-      type_indexes.SetBit(type_idx);
-    }
-    return type_indexes;
-  }
-
-  // BitVector with bits set for the type indexes of all classes in the input dex file.
-  BitVector type_indexes_;
-  BitVector::IndexIterator iter_;
-  BitVector::IndexIterator end_;
-};
-
-class DexFileAndClassPair : ValueObject {
- public:
-  DexFileAndClassPair(const DexFile* dex_file, TypeIndexInfo* type_info, bool from_loaded_oat)
-     : type_info_(type_info),
-       dex_file_(dex_file),
-       cached_descriptor_(dex_file_->StringByTypeIdx(dex::TypeIndex(*type_info->GetIterator()))),
-       from_loaded_oat_(from_loaded_oat) {
-    type_info_->AdvanceIterator();
-  }
-
-  DexFileAndClassPair(const DexFileAndClassPair& rhs) = default;
-
-  DexFileAndClassPair& operator=(const DexFileAndClassPair& rhs) = default;
-
-  const char* GetCachedDescriptor() const {
-    return cached_descriptor_;
-  }
-
-  bool operator<(const DexFileAndClassPair& rhs) const {
-    const int cmp = strcmp(cached_descriptor_, rhs.cached_descriptor_);
-    if (cmp != 0) {
-      // Note that the order must be reversed. We want to iterate over the classes in dex files.
-      // They are sorted lexicographically. Thus, the priority-queue must be a min-queue.
-      return cmp > 0;
-    }
-    return dex_file_ < rhs.dex_file_;
-  }
-
-  bool DexFileHasMoreClasses() const {
-    return type_info_->GetIterator() != type_info_->GetIteratorEnd();
-  }
-
-  void Next() {
-    cached_descriptor_ = dex_file_->StringByTypeIdx(dex::TypeIndex(*type_info_->GetIterator()));
-    type_info_->AdvanceIterator();
-  }
-
-  bool FromLoadedOat() const {
-    return from_loaded_oat_;
-  }
-
-  const DexFile* GetDexFile() const {
-    return dex_file_;
-  }
-
- private:
-  TypeIndexInfo* type_info_;
-  const DexFile* dex_file_;
-  const char* cached_descriptor_;
-  bool from_loaded_oat_;  // We only need to compare mismatches between what we load now
-                          // and what was loaded before. Any old duplicates must have been
-                          // OK, and any new "internal" duplicates are as well (they must
-                          // be from multidex, which resolves correctly).
-};
-
-static void AddDexFilesFromOat(
-    const OatFile* oat_file,
-    /*out*/std::vector<const DexFile*>* dex_files,
-    std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
-  for (const OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) {
-    std::string error;
-    std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error);
-    if (dex_file == nullptr) {
-      LOG(WARNING) << "Could not create dex file from oat file: " << error;
-    } else if (dex_file->NumClassDefs() > 0U) {
-      dex_files->push_back(dex_file.get());
-      opened_dex_files->push_back(std::move(dex_file));
-    }
-  }
-}
-
-static void AddNext(/*inout*/DexFileAndClassPair& original,
-                    /*inout*/std::priority_queue<DexFileAndClassPair>& heap) {
-  if (original.DexFileHasMoreClasses()) {
-    original.Next();
-    heap.push(std::move(original));
-  }
-}
-
-static bool CheckClassCollision(const OatFile* oat_file,
-    const ClassLoaderContext* context,
-    std::string* error_msg /*out*/) {
-  std::vector<const DexFile*> dex_files_loaded = context->FlattenOpenedDexFiles();
-
-  // Vector that holds the newly opened dex files live, this is done to prevent leaks.
-  std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
-
-  ScopedTrace st("Collision check");
-  // Add dex files from the oat file to check.
-  std::vector<const DexFile*> dex_files_unloaded;
-  AddDexFilesFromOat(oat_file, &dex_files_unloaded, &opened_dex_files);
-
-  // Generate type index information for each dex file.
-  std::vector<TypeIndexInfo> loaded_types;
-  loaded_types.reserve(dex_files_loaded.size());
-  for (const DexFile* dex_file : dex_files_loaded) {
-    loaded_types.push_back(TypeIndexInfo(dex_file));
-  }
-  std::vector<TypeIndexInfo> unloaded_types;
-  unloaded_types.reserve(dex_files_unloaded.size());
-  for (const DexFile* dex_file : dex_files_unloaded) {
-    unloaded_types.push_back(TypeIndexInfo(dex_file));
-  }
-
-  // Populate the queue of dex file and class pairs with the loaded and unloaded dex files.
-  std::priority_queue<DexFileAndClassPair> queue;
-  for (size_t i = 0; i < dex_files_loaded.size(); ++i) {
-    if (loaded_types[i].GetIterator() != loaded_types[i].GetIteratorEnd()) {
-      queue.emplace(dex_files_loaded[i], &loaded_types[i], /*from_loaded_oat=*/true);
-    }
-  }
-  for (size_t i = 0; i < dex_files_unloaded.size(); ++i) {
-    if (unloaded_types[i].GetIterator() != unloaded_types[i].GetIteratorEnd()) {
-      queue.emplace(dex_files_unloaded[i], &unloaded_types[i], /*from_loaded_oat=*/false);
-    }
-  }
-
-  // Now drain the queue.
-  bool has_duplicates = false;
-  error_msg->clear();
-  while (!queue.empty()) {
-    // Modifying the top element is only safe if we pop right after.
-    DexFileAndClassPair compare_pop(queue.top());
-    queue.pop();
-
-    // Compare against the following elements.
-    while (!queue.empty()) {
-      DexFileAndClassPair top(queue.top());
-      if (strcmp(compare_pop.GetCachedDescriptor(), top.GetCachedDescriptor()) == 0) {
-        // Same descriptor. Check whether it's crossing old-oat-files to new-oat-files.
-        if (compare_pop.FromLoadedOat() != top.FromLoadedOat()) {
-          error_msg->append(
-              StringPrintf("Found duplicated class when checking oat files: '%s' in %s and %s\n",
-                           compare_pop.GetCachedDescriptor(),
-                           compare_pop.GetDexFile()->GetLocation().c_str(),
-                           top.GetDexFile()->GetLocation().c_str()));
-          if (!VLOG_IS_ON(oat)) {
-            return true;
-          }
-          has_duplicates = true;
-        }
-        queue.pop();
-        AddNext(top, queue);
-      } else {
-        // Something else. Done here.
-        break;
-      }
-    }
-    AddNext(compare_pop, queue);
-  }
-
-  return has_duplicates;
-}
-
-// Check for class-def collisions in dex files.
-//
-// This first walks the class loader chain present in the given context, getting all the dex files
-// from the class loader.
-//
-// If the context is null (which means the initial class loader was null or unsupported)
-// this returns false. b/37777332.
-//
-// This first checks whether all class loaders in the context have the same type and
-// classpath. If so, we exit early. Otherwise, we do the collision check.
-//
-// The collision check works by maintaining a heap with one class from each dex file, sorted by the
-// class descriptor. Then a dex-file/class pair is continually removed from the heap and compared
-// against the following top element. If the descriptor is the same, it is now checked whether
-// the two elements agree on whether their dex file was from an already-loaded oat-file or the
-// new oat file. Any disagreement indicates a collision.
-OatFileManager::CheckCollisionResult OatFileManager::CheckCollision(
-    const OatFile* oat_file,
-    const ClassLoaderContext* context,
-    /*out*/ std::string* error_msg) const {
-  DCHECK(oat_file != nullptr);
-  DCHECK(error_msg != nullptr);
-
-  // The context might be null if there are unrecognized class loaders in the chain or they
-  // don't meet sensible sanity conditions. In this case we assume that the app knows what it's
-  // doing and accept the oat file.
-  // Note that this has correctness implications as we cannot guarantee that the class resolution
-  // used during compilation is OK (b/37777332).
-  if (context == nullptr) {
-    LOG(WARNING) << "Skipping duplicate class check due to unsupported classloader";
-    return CheckCollisionResult::kSkippedUnsupportedClassLoader;
-  }
-
-  if (!CompilerFilter::IsVerificationEnabled(oat_file->GetCompilerFilter())) {
-    // If verification is not enabled we don't need to check for collisions as the oat file
-    // is either extracted or assumed verified.
-    return CheckCollisionResult::kSkippedVerificationDisabled;
-  }
-
-  // If the oat file loading context matches the context used during compilation then we accept
-  // the oat file without addition checks
-  ClassLoaderContext::VerificationResult result = context->VerifyClassLoaderContextMatch(
-      oat_file->GetClassLoaderContext(),
-      /*verify_names=*/ true,
-      /*verify_checksums=*/ true);
-  switch (result) {
-    case ClassLoaderContext::VerificationResult::kForcedToSkipChecks:
-      return CheckCollisionResult::kSkippedClassLoaderContextSharedLibrary;
-    case ClassLoaderContext::VerificationResult::kMismatch:
-      // Mismatched context, do the actual collision check.
-      break;
-    case ClassLoaderContext::VerificationResult::kVerifies:
-      return CheckCollisionResult::kClassLoaderContextMatches;
-  }
-
-  // The class loader context does not match. Perform a full duplicate classes check.
-  return CheckClassCollision(oat_file, context, error_msg)
-      ? CheckCollisionResult::kPerformedHasCollisions : CheckCollisionResult::kNoCollisions;
-}
-
-bool OatFileManager::AcceptOatFile(CheckCollisionResult result) const {
-  // Take the file only if it has no collisions, or we must take it because of preopting.
-  // Also accept oat files for shared libraries and unsupported class loaders.
-  return result != CheckCollisionResult::kPerformedHasCollisions;
-}
-
-bool OatFileManager::ShouldLoadAppImage(CheckCollisionResult check_collision_result,
-                                        const OatFile* source_oat_file,
-                                        ClassLoaderContext* context,
-                                        std::string* error_msg) {
+bool OatFileManager::ShouldLoadAppImage(const OatFile* source_oat_file) const {
   Runtime* const runtime = Runtime::Current();
-  if (kEnableAppImage && (!runtime->IsJavaDebuggable() || source_oat_file->IsDebuggable())) {
-    // If we verified the class loader context (skipping due to the special marker doesn't
-    // count), then also avoid the collision check.
-    bool load_image = check_collision_result == CheckCollisionResult::kNoCollisions
-        || check_collision_result == CheckCollisionResult::kClassLoaderContextMatches;
-    // If we skipped the collision check, we need to reverify to be sure its OK to load the
-    // image.
-    if (!load_image &&
-        check_collision_result ==
-            CheckCollisionResult::kSkippedClassLoaderContextSharedLibrary) {
-      // We can load the app image only if there are no collisions. If we know the
-      // class loader but didn't do the full collision check in HasCollisions(),
-      // do it now. b/77342775
-      load_image = !CheckClassCollision(source_oat_file, context, error_msg);
-    }
-    return load_image;
-  }
-  return false;
+  return kEnableAppImage && (!runtime->IsJavaDebuggable() || source_oat_file->IsDebuggable());
 }
 
 std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
@@ -457,198 +171,234 @@
     jobjectArray dex_elements,
     const OatFile** out_oat_file,
     std::vector<std::string>* error_msgs) {
-  ScopedTrace trace(__FUNCTION__);
+  ScopedTrace trace(StringPrintf("%s(%s)", __FUNCTION__, dex_location));
   CHECK(dex_location != nullptr);
   CHECK(error_msgs != nullptr);
 
-  // Verify we aren't holding the mutator lock, which could starve GC if we
-  // have to generate or relocate an oat file.
+  // Verify we aren't holding the mutator lock, which could starve GC when
+  // hitting the disk.
   Thread* const self = Thread::Current();
   Locks::mutator_lock_->AssertNotHeld(self);
   Runtime* const runtime = Runtime::Current();
 
-  std::unique_ptr<ClassLoaderContext> context;
+  std::vector<std::unique_ptr<const DexFile>> dex_files;
+  std::unique_ptr<ClassLoaderContext> context(
+      ClassLoaderContext::CreateContextForClassLoader(class_loader, dex_elements));
+
   // If the class_loader is null there's not much we can do. This happens if a dex files is loaded
   // directly with DexFile APIs instead of using class loaders.
   if (class_loader == nullptr) {
     LOG(WARNING) << "Opening an oat file without a class loader. "
                  << "Are you using the deprecated DexFile APIs?";
-    context = nullptr;
-  } else {
-    context = ClassLoaderContext::CreateContextForClassLoader(class_loader, dex_elements);
-  }
+  } else if (context != nullptr) {
+    OatFileAssistant oat_file_assistant(dex_location,
+                                        kRuntimeISA,
+                                        context.get(),
+                                        runtime->GetOatFilesExecutable(),
+                                        only_use_system_oat_files_);
 
-  OatFileAssistant oat_file_assistant(dex_location,
-                                      kRuntimeISA,
-                                      runtime->GetOatFilesExecutable(),
-                                      only_use_system_oat_files_);
+    // Get the current optimization status for trace debugging.
+    // Implementation detail note: GetOptimizationStatus will select the same
+    // oat file as GetBestOatFile used below, and in doing so it already pre-populates
+    // some OatFileAssistant internal fields.
+    std::string odex_location;
+    std::string compilation_filter;
+    std::string compilation_reason;
+    std::string odex_status;
+    oat_file_assistant.GetOptimizationStatus(
+        &odex_location,
+        &compilation_filter,
+        &compilation_reason,
+        &odex_status);
 
-  // Get the oat file on disk.
-  std::unique_ptr<const OatFile> oat_file(oat_file_assistant.GetBestOatFile().release());
-  VLOG(oat) << "OatFileAssistant(" << dex_location << ").GetBestOatFile()="
-            << reinterpret_cast<uintptr_t>(oat_file.get())
-            << " (executable=" << (oat_file != nullptr ? oat_file->IsExecutable() : false) << ")";
+    Runtime::Current()->GetAppInfo()->RegisterOdexStatus(
+        dex_location,
+        compilation_filter,
+        compilation_reason,
+        odex_status);
 
-  const OatFile* source_oat_file = nullptr;
-  CheckCollisionResult check_collision_result = CheckCollisionResult::kPerformedHasCollisions;
-  std::string error_msg;
-  if ((class_loader != nullptr || dex_elements != nullptr) && oat_file != nullptr) {
-    // Prevent oat files from being loaded if no class_loader or dex_elements are provided.
-    // This can happen when the deprecated DexFile.<init>(String) is called directly, and it
-    // could load oat files without checking the classpath, which would be incorrect.
-    // Take the file only if it has no collisions, or we must take it because of preopting.
-    check_collision_result = CheckCollision(oat_file.get(), context.get(), /*out*/ &error_msg);
-    bool accept_oat_file = AcceptOatFile(check_collision_result);
-    if (!accept_oat_file) {
-      // Failed the collision check. Print warning.
-      if (runtime->IsDexFileFallbackEnabled()) {
-        if (!oat_file_assistant.HasOriginalDexFiles()) {
-          // We need to fallback but don't have original dex files. We have to
-          // fallback to opening the existing oat file. This is potentially
-          // unsafe so we warn about it.
-          accept_oat_file = true;
+    ScopedTrace odex_loading(StringPrintf(
+        "location=%s status=%s filter=%s reason=%s",
+        odex_location.c_str(),
+        odex_status.c_str(),
+        compilation_filter.c_str(),
+        compilation_reason.c_str()));
 
-          LOG(WARNING) << "Dex location " << dex_location << " does not seem to include dex file. "
-                       << "Allow oat file use. This is potentially dangerous.";
-        } else {
-          // We have to fallback and found original dex files - extract them from an APK.
-          // Also warn about this operation because it's potentially wasteful.
-          LOG(WARNING) << "Found duplicate classes, falling back to extracting from APK : "
-                       << dex_location;
-          LOG(WARNING) << "NOTE: This wastes RAM and hurts startup performance.";
+    // Proceed with oat file loading.
+    std::unique_ptr<const OatFile> oat_file(oat_file_assistant.GetBestOatFile().release());
+    VLOG(oat) << "OatFileAssistant(" << dex_location << ").GetBestOatFile()="
+              << (oat_file != nullptr ? oat_file->GetLocation() : "")
+              << " (executable=" << (oat_file != nullptr ? oat_file->IsExecutable() : false) << ")";
+
+    CHECK(oat_file == nullptr || odex_location == oat_file->GetLocation())
+        << "OatFileAssistant non-determinism in choosing best oat files. "
+        << "optimization-status-location=" << odex_location
+        << " best_oat_file-location=" << oat_file->GetLocation();
+
+    if (oat_file != nullptr) {
+      // Load the dex files from the oat file.
+      bool added_image_space = false;
+      if (oat_file->IsExecutable()) {
+        ScopedTrace app_image_timing("AppImage:Loading");
+
+        // We need to throw away the image space if we are debuggable but the oat-file source of the
+        // image is not otherwise we might get classes with inlined methods or other such things.
+        std::unique_ptr<gc::space::ImageSpace> image_space;
+        if (ShouldLoadAppImage(oat_file.get())) {
+          image_space = oat_file_assistant.OpenImageSpace(oat_file.get());
         }
-      } else {
-        // TODO: We should remove this. The fact that we're here implies -Xno-dex-file-fallback
-        // was set, which means that we should never fallback. If we don't have original dex
-        // files, we should just fail resolution as the flag intended.
-        if (!oat_file_assistant.HasOriginalDexFiles()) {
-          accept_oat_file = true;
-        }
-
-        LOG(WARNING) << "Found duplicate classes, dex-file-fallback disabled, will be failing to "
-                        " load classes for " << dex_location;
-      }
-
-      LOG(WARNING) << error_msg;
-    }
-
-    if (accept_oat_file) {
-      VLOG(class_linker) << "Registering " << oat_file->GetLocation();
-      source_oat_file = RegisterOatFile(std::move(oat_file));
-      *out_oat_file = source_oat_file;
-    }
-  }
-
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-
-  // Load the dex files from the oat file.
-  if (source_oat_file != nullptr) {
-    bool added_image_space = false;
-    if (source_oat_file->IsExecutable()) {
-      ScopedTrace app_image_timing("AppImage:Loading");
-
-      // We need to throw away the image space if we are debuggable but the oat-file source of the
-      // image is not otherwise we might get classes with inlined methods or other such things.
-      std::unique_ptr<gc::space::ImageSpace> image_space;
-      if (ShouldLoadAppImage(check_collision_result,
-                             source_oat_file,
-                             context.get(),
-                             &error_msg)) {
-        image_space = oat_file_assistant.OpenImageSpace(source_oat_file);
-      }
-      if (image_space != nullptr) {
-        ScopedObjectAccess soa(self);
-        StackHandleScope<1> hs(self);
-        Handle<mirror::ClassLoader> h_loader(
-            hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
-        // Can not load app image without class loader.
-        if (h_loader != nullptr) {
-          std::string temp_error_msg;
-          // Add image space has a race condition since other threads could be reading from the
-          // spaces array.
-          {
-            ScopedThreadSuspension sts(self, kSuspended);
-            gc::ScopedGCCriticalSection gcs(self,
-                                            gc::kGcCauseAddRemoveAppImageSpace,
-                                            gc::kCollectorTypeAddRemoveAppImageSpace);
-            ScopedSuspendAll ssa("Add image space");
-            runtime->GetHeap()->AddSpace(image_space.get());
-          }
-          {
-            ScopedTrace trace2(StringPrintf("Adding image space for location %s", dex_location));
-            added_image_space = runtime->GetClassLinker()->AddImageSpace(image_space.get(),
-                                                                         h_loader,
-                                                                         /*out*/&dex_files,
-                                                                         /*out*/&temp_error_msg);
-          }
-          if (added_image_space) {
-            // Successfully added image space to heap, release the map so that it does not get
-            // freed.
-            image_space.release();  // NOLINT b/117926937
-
-            // Register for tracking.
-            for (const auto& dex_file : dex_files) {
-              dex::tracking::RegisterDexFile(dex_file.get());
-            }
-          } else {
-            LOG(INFO) << "Failed to add image file " << temp_error_msg;
-            dex_files.clear();
+        if (image_space != nullptr) {
+          ScopedObjectAccess soa(self);
+          StackHandleScope<1> hs(self);
+          Handle<mirror::ClassLoader> h_loader(
+              hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
+          // Can not load app image without class loader.
+          if (h_loader != nullptr) {
+            std::string temp_error_msg;
+            // Add image space has a race condition since other threads could be reading from the
+            // spaces array.
             {
               ScopedThreadSuspension sts(self, kSuspended);
               gc::ScopedGCCriticalSection gcs(self,
                                               gc::kGcCauseAddRemoveAppImageSpace,
                                               gc::kCollectorTypeAddRemoveAppImageSpace);
-              ScopedSuspendAll ssa("Remove image space");
-              runtime->GetHeap()->RemoveSpace(image_space.get());
+              ScopedSuspendAll ssa("Add image space");
+              runtime->GetHeap()->AddSpace(image_space.get());
             }
-            // Non-fatal, don't update error_msg.
+            {
+              ScopedTrace image_space_timing("Adding image space");
+              added_image_space = runtime->GetClassLinker()->AddImageSpace(image_space.get(),
+                                                                           h_loader,
+                                                                           /*out*/&dex_files,
+                                                                           /*out*/&temp_error_msg);
+            }
+            if (added_image_space) {
+              // Successfully added image space to heap, release the map so that it does not get
+              // freed.
+              image_space.release();  // NOLINT b/117926937
+
+              // Register for tracking.
+              for (const auto& dex_file : dex_files) {
+                dex::tracking::RegisterDexFile(dex_file.get());
+              }
+            } else {
+              LOG(INFO) << "Failed to add image file " << temp_error_msg;
+              dex_files.clear();
+              {
+                ScopedThreadSuspension sts(self, kSuspended);
+                gc::ScopedGCCriticalSection gcs(self,
+                                                gc::kGcCauseAddRemoveAppImageSpace,
+                                                gc::kCollectorTypeAddRemoveAppImageSpace);
+                ScopedSuspendAll ssa("Remove image space");
+                runtime->GetHeap()->RemoveSpace(image_space.get());
+              }
+              // Non-fatal, don't update error_msg.
+            }
           }
         }
       }
-    }
-    if (!added_image_space) {
-      DCHECK(dex_files.empty());
-      dex_files = oat_file_assistant.LoadDexFiles(*source_oat_file, dex_location);
+      if (!added_image_space) {
+        DCHECK(dex_files.empty());
 
-      // Register for tracking.
-      for (const auto& dex_file : dex_files) {
-        dex::tracking::RegisterDexFile(dex_file.get());
+        if (oat_file->RequiresImage()) {
+          LOG(WARNING) << "Loading "
+                       << oat_file->GetLocation()
+                       << "non-executable as it requires an image which we failed to load";
+          // file as non-executable.
+          OatFileAssistant nonexecutable_oat_file_assistant(dex_location,
+                                                            kRuntimeISA,
+                                                            context.get(),
+                                                            /*load_executable=*/false,
+                                                            only_use_system_oat_files_);
+          oat_file.reset(nonexecutable_oat_file_assistant.GetBestOatFile().release());
+
+          // The file could be deleted concurrently (for example background
+          // dexopt, or secondary oat file being deleted by the app).
+          if (oat_file == nullptr) {
+            LOG(WARNING) << "Failed to reload oat file non-executable " << dex_location;
+          }
+        }
+
+        if (oat_file != nullptr) {
+          dex_files = oat_file_assistant.LoadDexFiles(*oat_file.get(), dex_location);
+
+          // Register for tracking.
+          for (const auto& dex_file : dex_files) {
+            dex::tracking::RegisterDexFile(dex_file.get());
+          }
+        }
       }
-    }
-    if (dex_files.empty()) {
-      error_msgs->push_back("Failed to open dex files from " + source_oat_file->GetLocation());
+      if (dex_files.empty()) {
+        ScopedTrace failed_to_open_dex_files("FailedToOpenDexFilesFromOat");
+        error_msgs->push_back("Failed to open dex files from " + odex_location);
+      } else {
+        // Opened dex files from an oat file, madvise them to their loaded state.
+         for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+           OatDexFile::MadviseDexFile(*dex_file, MadviseState::kMadviseStateAtLoad);
+         }
+      }
+
+      if (oat_file != nullptr) {
+        VLOG(class_linker) << "Registering " << oat_file->GetLocation();
+        *out_oat_file = RegisterOatFile(std::move(oat_file));
+      }
     } else {
-      // Opened dex files from an oat file, madvise them to their loaded state.
-       for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
-         OatDexFile::MadviseDexFile(*dex_file, MadviseState::kMadviseStateAtLoad);
-       }
+      // oat_file == nullptr
+      // Verify if any of the dex files being loaded is already in the class path.
+      // If so, report an error with the current stack trace.
+      // Most likely the developer didn't intend to do this because it will waste
+      // performance and memory.
+      if (oat_file_assistant.GetBestStatus() == OatFileAssistant::kOatContextOutOfDate) {
+        std::set<const DexFile*> already_exists_in_classpath =
+            context->CheckForDuplicateDexFiles(MakeNonOwningPointerVector(dex_files));
+        if (!already_exists_in_classpath.empty()) {
+          ScopedTrace duplicate_dex_files("DuplicateDexFilesInContext");
+          auto duplicate_it = already_exists_in_classpath.begin();
+          std::string duplicates = (*duplicate_it)->GetLocation();
+          for (duplicate_it++ ; duplicate_it != already_exists_in_classpath.end(); duplicate_it++) {
+            duplicates += "," + (*duplicate_it)->GetLocation();
+          }
+
+          std::ostringstream out;
+          out << "Trying to load dex files which is already loaded in the same ClassLoader "
+              << "hierarchy.\n"
+              << "This is a strong indication of bad ClassLoader construct which leads to poor "
+              << "performance and wastes memory.\n"
+              << "The list of duplicate dex files is: " << duplicates << "\n"
+              << "The current class loader context is: "
+              << context->EncodeContextForOatFile("") << "\n"
+              << "Java stack trace:\n";
+
+          {
+            ScopedObjectAccess soa(self);
+            self->DumpJavaStack(out);
+          }
+
+          // We log this as an ERROR to stress the fact that this is most likely unintended.
+          // Note that ART cannot do anything about it. It is up to the app to fix their logic.
+          // Here we are trying to give a heads up on why the app might have performance issues.
+          LOG(ERROR) << out.str();
+        }
+      }
     }
   }
 
-  // Fall back to running out of the original dex file if we couldn't load any
-  // dex_files from the oat file.
+  // If we arrive here with an empty dex files list, it means we fail to load
+  // it/them through an .oat file.
   if (dex_files.empty()) {
-    if (oat_file_assistant.HasOriginalDexFiles()) {
-      if (Runtime::Current()->IsDexFileFallbackEnabled()) {
-        static constexpr bool kVerifyChecksum = true;
-        const ArtDexFileLoader dex_file_loader;
-        if (!dex_file_loader.Open(dex_location,
-                                  dex_location,
-                                  Runtime::Current()->IsVerificationEnabled(),
-                                  kVerifyChecksum,
-                                  /*out*/ &error_msg,
-                                  &dex_files)) {
-          LOG(WARNING) << error_msg;
-          error_msgs->push_back("Failed to open dex files from " + std::string(dex_location)
-                                + " because: " + error_msg);
-        }
-      } else {
-        error_msgs->push_back("Fallback mode disabled, skipping dex files.");
-      }
-    } else {
-      std::string msg = StringPrintf("No original dex files found for dex location (%s) %s",
-          GetInstructionSetString(kRuntimeISA), dex_location);
-      error_msgs->push_back(msg);
+    std::string error_msg;
+    static constexpr bool kVerifyChecksum = true;
+    const ArtDexFileLoader dex_file_loader;
+    if (!dex_file_loader.Open(dex_location,
+                              dex_location,
+                              Runtime::Current()->IsVerificationEnabled(),
+                              kVerifyChecksum,
+                              /*out*/ &error_msg,
+                              &dex_files)) {
+      ScopedTrace fail_to_open_dex_from_apk("FailedToOpenDexFilesFromApk");
+      LOG(WARNING) << error_msg;
+      error_msgs->push_back("Failed to open dex files from " + std::string(dex_location)
+                            + " because: " + error_msg);
     }
   }
 
@@ -656,42 +406,10 @@
     Runtime::Current()->GetJit()->RegisterDexFiles(dex_files, class_loader);
   }
 
-  // Verify if any of the dex files being loaded is already in the class path.
-  // If so, report an error with the current stack trace.
-  // Most likely the developer didn't intend to do this because it will waste
-  // performance and memory.
-  // We perform the check only if the class loader context match failed or did
-  // not run (e.g. not that we do not run the check if we don't have an oat file).
-  if (context != nullptr
-          && check_collision_result != CheckCollisionResult::kClassLoaderContextMatches) {
-    std::set<const DexFile*> already_exists_in_classpath =
-        context->CheckForDuplicateDexFiles(MakeNonOwningPointerVector(dex_files));
-    if (!already_exists_in_classpath.empty()) {
-      auto duplicate_it = already_exists_in_classpath.begin();
-      std::string duplicates = (*duplicate_it)->GetLocation();
-      for (duplicate_it++ ; duplicate_it != already_exists_in_classpath.end(); duplicate_it++) {
-        duplicates += "," + (*duplicate_it)->GetLocation();
-      }
+  // Now that we loaded the dex/odex files, notify the runtime.
+  // Note that we do this everytime we load dex files.
+  Runtime::Current()->NotifyDexFileLoaded();
 
-      std::ostringstream out;
-      out << "Trying to load dex files which is already loaded in the same ClassLoader hierarchy.\n"
-        << "This is a strong indication of bad ClassLoader construct which leads to poor "
-        << "performance and wastes memory.\n"
-        << "The list of duplicate dex files is: " << duplicates << "\n"
-        << "The current class loader context is: " << context->EncodeContextForOatFile("") << "\n"
-        << "Java stack trace:\n";
-
-      {
-        ScopedObjectAccess soa(self);
-        self->DumpJavaStack(out);
-      }
-
-      // We log this as an ERROR to stress the fact that this is most likely unintended.
-      // Note that ART cannot do anything about it. It is up to the app to fix their logic.
-      // Here we are trying to give a heads up on why the app might have performance issues.
-      LOG(ERROR) << out.str();
-    }
-  }
   return dex_files;
 }
 
@@ -705,16 +423,6 @@
   return headers;
 }
 
-static std::vector<const DexFile::Header*> GetDexFileHeaders(
-    const std::vector<const DexFile*>& dex_files) {
-  std::vector<const DexFile::Header*> headers;
-  headers.reserve(dex_files.size());
-  for (const DexFile* dex_file : dex_files) {
-    headers.push_back(&dex_file->GetHeader());
-  }
-  return headers;
-}
-
 std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
     std::vector<MemMap>&& dex_mem_maps,
     jobject class_loader,
@@ -759,12 +467,10 @@
   const std::vector<const DexFile::Header*> dex_headers = GetDexFileHeaders(dex_mem_maps);
 
   // Determine dex/vdex locations and the combined location checksum.
-  uint32_t location_checksum;
   std::string dex_location;
   std::string vdex_path;
   bool has_vdex = OatFileAssistant::AnonymousDexVdexLocation(dex_headers,
                                                              kRuntimeISA,
-                                                             &location_checksum,
                                                              &dex_location,
                                                              &vdex_path);
 
@@ -792,7 +498,7 @@
     const ArtDexFileLoader dex_file_loader;
     std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(
         DexFileLoader::GetMultiDexLocation(i, dex_location.c_str()),
-        location_checksum,
+        dex_headers[i]->checksum_,
         std::move(dex_mem_maps[i]),
         /* verify= */ (vdex_file == nullptr) && Runtime::Current()->IsVerificationEnabled(),
         kVerifyChecksum,
@@ -821,25 +527,17 @@
     LOG(ERROR) << "Could not create class loader context for " << vdex_path;
     return dex_files;
   }
-  DCHECK(context->OpenDexFiles(kRuntimeISA, ""))
+  DCHECK(context->OpenDexFiles())
       << "Context created from already opened dex files should not attempt to open again";
 
-  // Check that we can use the vdex against this boot class path and in this class loader context.
-  // Note 1: We do not need a class loader collision check because there is no compiled code.
-  // Note 2: If these checks fail, we cannot fast-verify because the vdex does not contain
-  //         full VerifierDeps.
-  if (!vdex_file->MatchesBootClassPathChecksums() ||
-      !vdex_file->MatchesClassLoaderContext(*context.get())) {
-    return dex_files;
-  }
-
   // Initialize an OatFile instance backed by the loaded vdex.
   std::unique_ptr<OatFile> oat_file(OatFile::OpenFromVdex(MakeNonOwningPointerVector(dex_files),
                                                           std::move(vdex_file),
                                                           dex_location));
-  DCHECK(oat_file != nullptr);
-  VLOG(class_linker) << "Registering " << oat_file->GetLocation();
-  *out_oat_file = RegisterOatFile(std::move(oat_file));
+  if (oat_file != nullptr) {
+    VLOG(class_linker) << "Registering " << oat_file->GetLocation();
+    *out_oat_file = RegisterOatFile(std::move(oat_file));
+  }
   return dex_files;
 }
 
@@ -848,6 +546,12 @@
 // recently used one(s) (according to stat-reported atime).
 static bool UnlinkLeastRecentlyUsedVdexIfNeeded(const std::string& vdex_path_to_add,
                                                 std::string* error_msg) {
+  std::string basename = android::base::Basename(vdex_path_to_add);
+  if (!OatFileAssistant::IsAnonymousVdexBasename(basename)) {
+    // File is not for in memory dex files.
+    return true;
+  }
+
   if (OS::FileExists(vdex_path_to_add.c_str())) {
     // File already exists and will be overwritten.
     // This will not change the number of entries in the cache.
@@ -874,7 +578,7 @@
     if (de->d_type != DT_REG) {
       continue;
     }
-    std::string basename = de->d_name;
+    basename = de->d_name;
     if (!OatFileAssistant::IsAnonymousVdexBasename(basename)) {
       continue;
     }
@@ -912,10 +616,8 @@
  public:
   BackgroundVerificationTask(const std::vector<const DexFile*>& dex_files,
                              jobject class_loader,
-                             const char* class_loader_context,
                              const std::string& vdex_path)
       : dex_files_(dex_files),
-        class_loader_context_(class_loader_context),
         vdex_path_(vdex_path) {
     Thread* const self = Thread::Current();
     ScopedObjectAccess soa(self);
@@ -964,7 +666,7 @@
         }
 
         CHECK(h_class->IsResolved()) << h_class->PrettyDescriptor();
-        class_linker->VerifyClass(self, h_class);
+        class_linker->VerifyClass(self, &verifier_deps, h_class);
         if (h_class->IsErroneous()) {
           // ClassLinker::VerifyClass throws, which isn't useful here.
           CHECK(soa.Self()->IsExceptionPending());
@@ -990,7 +692,6 @@
     if (!VdexFile::WriteToDisk(vdex_path_,
                                dex_files_,
                                verifier_deps,
-                               class_loader_context_,
                                &error_msg)) {
       LOG(ERROR) << "Could not write anonymous vdex " << vdex_path_ << ": " << error_msg;
       return;
@@ -1004,15 +705,13 @@
  private:
   const std::vector<const DexFile*> dex_files_;
   jobject class_loader_;
-  const std::string class_loader_context_;
   const std::string vdex_path_;
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundVerificationTask);
 };
 
 void OatFileManager::RunBackgroundVerification(const std::vector<const DexFile*>& dex_files,
-                                               jobject class_loader,
-                                               const char* class_loader_context) {
+                                               jobject class_loader) {
   Runtime* const runtime = Runtime::Current();
   Thread* const self = Thread::Current();
 
@@ -1033,25 +732,47 @@
     return;
   }
 
-  uint32_t location_checksum;
-  std::string dex_location;
-  std::string vdex_path;
-  if (OatFileAssistant::AnonymousDexVdexLocation(GetDexFileHeaders(dex_files),
-                                                 kRuntimeISA,
-                                                 &location_checksum,
-                                                 &dex_location,
-                                                 &vdex_path)) {
+  if (dex_files.size() < 1) {
+    // Nothing to verify.
+    return;
+  }
+
+  std::string dex_location = dex_files[0]->GetLocation();
+  const std::string& data_dir = Runtime::Current()->GetProcessDataDirectory();
+  if (!android::base::StartsWith(dex_location, data_dir)) {
+    // For now, we only run background verification for secondary dex files.
+    // Running it for primary or split APKs could have some undesirable
+    // side-effects, like overloading the device on app startup.
+    return;
+  }
+
+  std::string error_msg;
+  std::string odex_filename;
+  if (!OatFileAssistant::DexLocationToOdexFilename(dex_location,
+                                                   kRuntimeISA,
+                                                   &odex_filename,
+                                                   &error_msg)) {
+    LOG(WARNING) << "Could not get odex filename for " << dex_location << ": " << error_msg;
+    return;
+  }
+
+  if (LocationIsOnArtApexData(odex_filename) && Runtime::Current()->DenyArtApexDataFiles()) {
+    // Ignore vdex file associated with this odex file as the odex file is not trustworthy.
+    return;
+  }
+
+  {
+    WriterMutexLock mu(self, *Locks::oat_file_manager_lock_);
     if (verification_thread_pool_ == nullptr) {
       verification_thread_pool_.reset(
           new ThreadPool("Verification thread pool", /* num_threads= */ 1));
       verification_thread_pool_->StartWorkers(self);
     }
-    verification_thread_pool_->AddTask(self, new BackgroundVerificationTask(
-        dex_files,
-        class_loader,
-        class_loader_context,
-        vdex_path));
   }
+  verification_thread_pool_->AddTask(self, new BackgroundVerificationTask(
+      dex_files,
+      class_loader,
+      GetVdexFilename(odex_filename)));
 }
 
 void OatFileManager::WaitForWorkersToBeCreated() {
@@ -1074,7 +795,7 @@
   }
 }
 
-void OatFileManager::SetOnlyUseSystemOatFiles() {
+void OatFileManager::SetOnlyUseTrustedOatFiles() {
   ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
   // Make sure all files that were loaded up to this point are on /system.
   // Skip the image files as they can encode locations that don't exist (eg not
@@ -1084,7 +805,18 @@
 
   for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
     if (boot_set.find(oat_file.get()) == boot_set.end()) {
-      CHECK(LocationIsOnSystem(oat_file->GetLocation().c_str())) << oat_file->GetLocation();
+      // This method is called during runtime initialization before we can call
+      // Runtime::Current()->DenyArtApexDataFiles(). Since we don't want to fail hard if
+      // the ART APEX data files are untrusted, just treat them as trusted for the check here.
+      const bool trust_art_apex_data_files = true;
+      if (!LocationIsTrusted(oat_file->GetLocation(), trust_art_apex_data_files)) {
+        // When the file is not in a trusted location, we check whether the oat file has any
+        // AOT or DEX code. It is a fatal error if it has.
+        if (CompilerFilter::IsAotCompilationEnabled(oat_file->GetCompilerFilter()) ||
+            oat_file->ContainsDexCode()) {
+          LOG(FATAL) << "Executing untrusted code from " << oat_file->GetLocation();
+        }
+      }
     }
   }
   only_use_system_oat_files_ = true;
diff --git a/runtime/oat_file_manager.h b/runtime/oat_file_manager.h
index 9c3a38a..abf4ea0 100644
--- a/runtime/oat_file_manager.h
+++ b/runtime/oat_file_manager.h
@@ -23,6 +23,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "base/compiler_filter.h"
 #include "base/locks.h"
 #include "base/macros.h"
 #include "jni.h"
@@ -70,9 +71,6 @@
   // Returns the boot image oat files.
   std::vector<const OatFile*> GetBootOatFiles() const;
 
-  // Returns the first non-image oat file in the class path.
-  const OatFile* GetPrimaryOatFile() const REQUIRES(!Locks::oat_file_manager_lock_);
-
   // Returns the oat files for the images, registers the oat files.
   // Takes ownership of the imagespace's underlying oat files.
   std::vector<const OatFile*> RegisterImageOatFiles(
@@ -120,12 +118,11 @@
 
   void DumpForSigQuit(std::ostream& os);
 
-  void SetOnlyUseSystemOatFiles();
+  void SetOnlyUseTrustedOatFiles();
 
   // Spawn a background thread which verifies all classes in the given dex files.
   void RunBackgroundVerification(const std::vector<const DexFile*>& dex_files,
-                                 jobject class_loader,
-                                 const char* class_loader_context);
+                                 jobject class_loader);
 
   // Wait for thread pool workers to be created. This is used during shutdown as
   // threads are not allowed to attach while runtime is in shutdown lock.
@@ -141,15 +138,6 @@
   static constexpr size_t kAnonymousVdexCacheSize = 8u;
 
  private:
-  enum class CheckCollisionResult {
-    kSkippedUnsupportedClassLoader,
-    kSkippedClassLoaderContextSharedLibrary,
-    kSkippedVerificationDisabled,
-    kNoCollisions,
-    kPerformedHasCollisions,
-    kClassLoaderContextMatches
-  };
-
   std::vector<std::unique_ptr<const DexFile>> OpenDexFilesFromOat_Impl(
       std::vector<MemMap>&& dex_mem_maps,
       jobject class_loader,
@@ -158,31 +146,11 @@
       /*out*/ std::vector<std::string>* error_msgs)
       REQUIRES(!Locks::oat_file_manager_lock_, !Locks::mutator_lock_);
 
-  // Check that the class loader context of the given oat file matches the given context.
-  // This will perform a check that all class loaders in the chain have the same type and
-  // classpath.
-  // If the context is null (which means the initial class loader was null or unsupported)
-  // this returns kSkippedUnsupportedClassLoader.
-  // If the context does not validate the method will check for duplicate class definitions of
-  // the given oat file against the oat files (either from the class loaders if possible or all
-  // non-boot oat files otherwise).
-  // Return kPerformedHasCollisions if there are any class definition collisions in the oat_file.
-  CheckCollisionResult CheckCollision(const OatFile* oat_file,
-                                      const ClassLoaderContext* context,
-                                      /*out*/ std::string* error_msg) const
-      REQUIRES(!Locks::oat_file_manager_lock_);
-
   const OatFile* FindOpenedOatFileFromOatLocationLocked(const std::string& oat_location) const
       REQUIRES(Locks::oat_file_manager_lock_);
 
-  // Return true if we should accept the oat file.
-  bool AcceptOatFile(CheckCollisionResult result) const;
-
   // Return true if we should attempt to load the app image.
-  bool ShouldLoadAppImage(CheckCollisionResult check_collision_result,
-                          const OatFile* source_oat_file,
-                          ClassLoaderContext* context,
-                          std::string* error_msg);
+  bool ShouldLoadAppImage(const OatFile* source_oat_file) const;
 
   std::set<std::unique_ptr<const OatFile>> oat_files_ GUARDED_BY(Locks::oat_file_manager_lock_);
 
diff --git a/runtime/oat_file_test.cc b/runtime/oat_file_test.cc
index 8222a8aa..f332357 100644
--- a/runtime/oat_file_test.cc
+++ b/runtime/oat_file_test.cc
@@ -57,7 +57,7 @@
   std::string dex_location = GetScratchDir() + "/MultiDexUncompressedAligned.jar";
 
   Copy(GetTestDexFileName("MultiDexUncompressedAligned"), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
+  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kVerify);
 
   std::string oat_location;
   std::string error_msg;
diff --git a/runtime/oat_quick_method_header.cc b/runtime/oat_quick_method_header.cc
index ebb868b..543ff72 100644
--- a/runtime/oat_quick_method_header.cc
+++ b/runtime/oat_quick_method_header.cc
@@ -16,10 +16,11 @@
 
 #include "oat_quick_method_header.h"
 
+#include "arch/instruction_set.h"
 #include "art_method.h"
 #include "dex/dex_file_types.h"
 #include "interpreter/interpreter_mterp_impl.h"
-#include "interpreter/mterp/mterp.h"
+#include "interpreter/mterp/nterp.h"
 #include "nterp_helpers.h"
 #include "scoped_thread_state_change-inl.h"
 #include "stack_map.h"
@@ -88,12 +89,19 @@
   return UINTPTR_MAX;
 }
 
-OatQuickMethodHeader* OatQuickMethodHeader::NterpMethodHeader =
-    (interpreter::IsNterpSupported()
-        ? reinterpret_cast<OatQuickMethodHeader*>(
-              reinterpret_cast<uintptr_t>(interpreter::GetNterpEntryPoint()) -
-                  sizeof(OatQuickMethodHeader))
-        : nullptr);
+static inline OatQuickMethodHeader* GetNterpMethodHeader() {
+  if (!interpreter::IsNterpSupported()) {
+    return nullptr;
+  }
+  uintptr_t nterp_entrypoint = reinterpret_cast<uintptr_t>(interpreter::GetNterpEntryPoint());
+  uintptr_t nterp_code_pointer = (kRuntimeISA == InstructionSet::kArm)
+      // Remove the Thumb mode bit if present on ARM.
+      ? nterp_entrypoint & ~static_cast<uintptr_t>(1)
+      : nterp_entrypoint;
+  return reinterpret_cast<OatQuickMethodHeader*>(nterp_code_pointer - sizeof(OatQuickMethodHeader));
+}
+
+OatQuickMethodHeader* OatQuickMethodHeader::NterpMethodHeader = GetNterpMethodHeader();
 
 bool OatQuickMethodHeader::IsNterpMethodHeader() const {
   return interpreter::IsNterpSupported() ? (this == NterpMethodHeader) : false;
diff --git a/runtime/oat_quick_method_header.h b/runtime/oat_quick_method_header.h
index 9a1133e..c2f1c4c 100644
--- a/runtime/oat_quick_method_header.h
+++ b/runtime/oat_quick_method_header.h
@@ -31,11 +31,8 @@
 // OatQuickMethodHeader precedes the raw code chunk generated by the compiler.
 class PACKED(4) OatQuickMethodHeader {
  public:
-  OatQuickMethodHeader() = default;
-  OatQuickMethodHeader(uint32_t vmap_table_offset,
-                       uint32_t code_size)
-      : vmap_table_offset_(vmap_table_offset),
-        code_size_(code_size) {
+  OatQuickMethodHeader(uint32_t code_info_offset = 0) {
+    SetCodeInfoOffset(code_info_offset);
   }
 
   static OatQuickMethodHeader* NterpMethodHeader;
@@ -66,51 +63,43 @@
     return pc - reinterpret_cast<uintptr_t>(GetEntryPoint());
   }
 
-  bool IsOptimized() const {
-    return GetCodeSize() != 0 && vmap_table_offset_ != 0;
+  ALWAYS_INLINE bool IsOptimized() const {
+    uintptr_t code = reinterpret_cast<uintptr_t>(code_);
+    DCHECK_NE(data_, 0u) << std::hex << code;          // Probably a padding of native code.
+    DCHECK_NE(data_, 0xFFFFFFFF) << std::hex << code;  // Probably a stub or trampoline.
+    return (data_ & kIsCodeInfoMask) != 0;
   }
 
-  const uint8_t* GetOptimizedCodeInfoPtr() const {
-    DCHECK(IsOptimized());
-    return code_ - vmap_table_offset_;
+  ALWAYS_INLINE const uint8_t* GetOptimizedCodeInfoPtr() const {
+    uint32_t offset = GetCodeInfoOffset();
+    DCHECK_NE(offset, 0u);
+    return code_ - offset;
   }
 
-  uint8_t* GetOptimizedCodeInfoPtr() {
-    DCHECK(IsOptimized());
-    return code_ - vmap_table_offset_;
+  ALWAYS_INLINE uint8_t* GetOptimizedCodeInfoPtr() {
+    uint32_t offset = GetCodeInfoOffset();
+    DCHECK_NE(offset, 0u);
+    return code_ - offset;
   }
 
-  const uint8_t* GetCode() const {
+  ALWAYS_INLINE const uint8_t* GetCode() const {
     return code_;
   }
 
-  uint32_t GetCodeSize() const {
-    // ART compiled method are prefixed with header, but we can also easily
-    // accidentally use a function pointer to one of the stubs/trampolines.
-    // We prefix those with 0xFF in the aseembly so that we can do DCHECKs.
-    CHECK_NE(code_size_, 0xFFFFFFFF) << code_size_;
-    return code_size_ & kCodeSizeMask;
+  ALWAYS_INLINE uint32_t GetCodeSize() const {
+    return LIKELY(IsOptimized())
+        ? CodeInfo::DecodeCodeSize(GetOptimizedCodeInfoPtr())
+        : (data_ & kCodeSizeMask);
   }
 
-  const uint32_t* GetCodeSizeAddr() const {
-    return &code_size_;
+  ALWAYS_INLINE uint32_t GetCodeInfoOffset() const {
+    DCHECK(IsOptimized());
+    return data_ & kCodeInfoMask;
   }
 
-  uint32_t GetVmapTableOffset() const {
-    return vmap_table_offset_;
-  }
-
-  void SetVmapTableOffset(uint32_t offset) {
-    vmap_table_offset_ = offset;
-  }
-
-  const uint32_t* GetVmapTableOffsetAddr() const {
-    return &vmap_table_offset_;
-  }
-
-  const uint8_t* GetVmapTable() const {
-    CHECK(!IsOptimized()) << "Unimplemented vmap table for optimizing compiler";
-    return (vmap_table_offset_ == 0) ? nullptr : code_ - vmap_table_offset_;
+  void SetCodeInfoOffset(uint32_t offset) {
+    data_ = kIsCodeInfoMask | offset;
+    DCHECK_EQ(GetCodeInfoOffset(), offset);
   }
 
   bool Contains(uintptr_t pc) const {
@@ -160,25 +149,22 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   void SetHasShouldDeoptimizeFlag() {
-    DCHECK_EQ(code_size_ & kShouldDeoptimizeMask, 0u);
-    code_size_ |= kShouldDeoptimizeMask;
+    DCHECK(!HasShouldDeoptimizeFlag());
+    data_ |= kShouldDeoptimizeMask;
   }
 
   bool HasShouldDeoptimizeFlag() const {
-    return (code_size_ & kShouldDeoptimizeMask) != 0;
+    return (data_ & kShouldDeoptimizeMask) != 0;
   }
 
  private:
   static constexpr uint32_t kShouldDeoptimizeMask = 0x80000000;
-  static constexpr uint32_t kCodeSizeMask = ~kShouldDeoptimizeMask;
+  static constexpr uint32_t kIsCodeInfoMask       = 0x40000000;
+  static constexpr uint32_t kCodeInfoMask         = 0x3FFFFFFF;  // If kIsCodeInfoMask is set.
+  static constexpr uint32_t kCodeSizeMask         = 0x3FFFFFFF;  // If kIsCodeInfoMask is clear.
 
-  // The offset in bytes from the start of the vmap table to the end of the header.
-  uint32_t vmap_table_offset_ = 0u;
-  // The code size in bytes. The highest bit is used to signify if the compiled
-  // code with the method header has should_deoptimize flag.
-  uint32_t code_size_ = 0u;
-  // The actual code.
-  uint8_t code_[0];
+  uint32_t data_ = 0u;  // Combination of fields using the above masks.
+  uint8_t code_[0];     // The actual method code.
 };
 
 }  // namespace art
diff --git a/runtime/offsets.h b/runtime/offsets.h
index 2f36fe6..cc18bf4 100644
--- a/runtime/offsets.h
+++ b/runtime/offsets.h
@@ -40,6 +40,9 @@
   constexpr bool operator==(Offset o) const {
     return SizeValue() == o.SizeValue();
   }
+  constexpr bool operator!=(Offset o) const {
+    return !(*this == o);
+  }
 
  protected:
   size_t val_;
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index c62caa9..3e1fd4f 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -23,6 +23,8 @@
 #include <android-base/strings.h>
 
 #include "base/file_utils.h"
+#include "base/flags.h"
+#include "base/indenter.h"
 #include "base/macros.h"
 #include "base/utils.h"
 #include "debugger.h"
@@ -81,54 +83,59 @@
             static_cast<size_t>(hiddenapi::EnforcementPolicy::kMax) + 1);
 
   parser_builder->
-       Define("-Xzygote")
-          .IntoKey(M::Zygote)
-      .Define("-Xprimaryzygote")
-          .IntoKey(M::PrimaryZygote)
-      .Define("-help")
+       SetCategory("standard")
+      .Define({"-classpath _", "-cp _"})
+          .WithHelp("The classpath, separated by ':'")
+          .WithType<std::string>()
+          .IntoKey(M::ClassPath)
+      .Define("-D_")
+          .WithType<std::vector<std::string>>().AppendValues()
+          .IntoKey(M::PropertiesList)
+      .Define("-verbose:_")
+          .WithHelp("Switches for advanced logging. Multiple categories can be enabled separated by ','. Eg: -verbose:class,deopt")
+          .WithType<LogVerbosity>()
+          .IntoKey(M::Verbose)
+      .Define({"-help", "-h"})
+          .WithHelp("Print this help text.")
           .IntoKey(M::Help)
       .Define("-showversion")
           .IntoKey(M::ShowVersion)
-      .Define("-Xbootclasspath:_")
-          .WithType<ParseStringList<':'>>()  // std::vector<std::string>, split by :
-          .IntoKey(M::BootClassPath)
-      .Define("-Xbootclasspath-locations:_")
-          .WithType<ParseStringList<':'>>()  // std::vector<std::string>, split by :
-          .IntoKey(M::BootClassPathLocations)
-      .Define({"-classpath _", "-cp _"})
-          .WithType<std::string>()
-          .IntoKey(M::ClassPath)
-      .Define("-Ximage:_")
-          .WithType<std::string>()
-          .IntoKey(M::Image)
-      .Define("-Ximage-load-order:_")
-          .WithType<gc::space::ImageSpaceLoadingOrder>()
-          .WithValueMap({{"system", gc::space::ImageSpaceLoadingOrder::kSystemFirst},
-                         {"data", gc::space::ImageSpaceLoadingOrder::kDataFirst}})
-          .IntoKey(M::ImageSpaceLoadingOrder)
-      .Define("-Xcheck:jni")
-          .IntoKey(M::CheckJni)
-      .Define("-Xjniopts:forcecopy")
-          .IntoKey(M::JniOptsForceCopy)
-      .Define("-XjdwpProvider:_")
-          .WithType<JdwpProvider>()
-          .IntoKey(M::JdwpProvider)
-      .Define("-XjdwpOptions:_")
-          .WithType<std::string>()
-          .IntoKey(M::JdwpOptions)
       // TODO Re-enable -agentlib: once I have a good way to transform the values.
       // .Define("-agentlib:_")
       //     .WithType<std::vector<ti::Agent>>().AppendValues()
       //     .IntoKey(M::AgentLib)
       .Define("-agentpath:_")
+          .WithHelp("Load native agents.")
           .WithType<std::list<ti::AgentSpec>>().AppendValues()
           .IntoKey(M::AgentPath)
+      .SetCategory("extended")
+      .Define("-Xbootclasspath:_")
+          .WithType<ParseStringList<':'>>()  // std::vector<std::string>, split by :
+          .IntoKey(M::BootClassPath)
+      .Define("-Xcheck:jni")
+          .IntoKey(M::CheckJni)
       .Define("-Xms_")
           .WithType<MemoryKiB>()
           .IntoKey(M::MemoryInitialSize)
       .Define("-Xmx_")
           .WithType<MemoryKiB>()
           .IntoKey(M::MemoryMaximumSize)
+      .Define("-Xss_")
+          .WithType<Memory<1>>()
+          .IntoKey(M::StackSize)
+      .Define("-Xint")
+          .WithValue(true)
+          .IntoKey(M::Interpret)
+      .SetCategory("Dalvik")
+      .Define("-Xzygote")
+          .WithHelp("Start as zygote")
+          .IntoKey(M::Zygote)
+      .Define("-Xjnitrace:_")
+          .WithType<std::string>()
+          .IntoKey(M::JniTrace)
+      .Define("-Xgc:_")
+          .WithType<XGcOption>()
+          .IntoKey(M::GcOption)
       .Define("-XX:HeapGrowthLimit=_")
           .WithType<MemoryKiB>()
           .IntoKey(M::HeapGrowthLimit)
@@ -141,15 +148,45 @@
       .Define("-XX:NonMovingSpaceCapacity=_")
           .WithType<MemoryKiB>()
           .IntoKey(M::NonMovingSpaceCapacity)
-      .Define("-XX:StopForNativeAllocs=_")
-          .WithType<MemoryKiB>()
-          .IntoKey(M::StopForNativeAllocs)
       .Define("-XX:HeapTargetUtilization=_")
           .WithType<double>().WithRange(0.1, 0.9)
           .IntoKey(M::HeapTargetUtilization)
       .Define("-XX:ForegroundHeapGrowthMultiplier=_")
           .WithType<double>().WithRange(0.1, 5.0)
           .IntoKey(M::ForegroundHeapGrowthMultiplier)
+      .Define("-XX:LowMemoryMode")
+          .IntoKey(M::LowMemoryMode)
+      .Define("-Xprofile:_")
+          .WithType<TraceClockSource>()
+          .WithValueMap({{"threadcpuclock", TraceClockSource::kThreadCpu},
+                         {"wallclock",      TraceClockSource::kWall},
+                         {"dualclock",      TraceClockSource::kDual}})
+          .IntoKey(M::ProfileClock)
+      .Define("-Xjitthreshold:_")
+          .WithType<unsigned int>()
+          .IntoKey(M::JITCompileThreshold)
+      .SetCategory("ART")
+      .Define("-Ximage:_")
+          .WithType<std::string>()
+          .IntoKey(M::Image)
+      .Define("-Xprimaryzygote")
+          .IntoKey(M::PrimaryZygote)
+      .Define("-Xbootclasspath-locations:_")
+          .WithType<ParseStringList<':'>>()  // std::vector<std::string>, split by :
+          .IntoKey(M::BootClassPathLocations)
+      .Define("-Xjniopts:forcecopy")
+          .IntoKey(M::JniOptsForceCopy)
+      .Define("-XjdwpProvider:_")
+          .WithType<JdwpProvider>()
+          .IntoKey(M::JdwpProvider)
+      .Define("-XjdwpOptions:_")
+          .WithMetavar("OPTION[,OPTION...]")
+          .WithHelp("JDWP options. Eg suspend=n,server=y.")
+          .WithType<std::string>()
+          .IntoKey(M::JdwpOptions)
+      .Define("-XX:StopForNativeAllocs=_")
+          .WithType<MemoryKiB>()
+          .IntoKey(M::StopForNativeAllocs)
       .Define("-XX:ParallelGCThreads=_")
           .WithType<unsigned int>()
           .IntoKey(M::ParallelGCThreads)
@@ -159,9 +196,6 @@
       .Define("-XX:FinalizerTimeoutMs=_")
           .WithType<unsigned int>()
           .IntoKey(M::FinalizerTimeoutMs)
-      .Define("-Xss_")
-          .WithType<Memory<1>>()
-          .IntoKey(M::StackSize)
       .Define("-XX:MaxSpinsBeforeThinLockInflation=_")
           .WithType<unsigned int>()
           .IntoKey(M::MaxSpinsBeforeThinLockInflation)
@@ -181,8 +215,11 @@
           .IntoKey(M::DumpJITInfoOnShutdown)
       .Define("-XX:IgnoreMaxFootprint")
           .IntoKey(M::IgnoreMaxFootprint)
-      .Define("-XX:LowMemoryMode")
-          .IntoKey(M::LowMemoryMode)
+      .Define("-XX:AlwaysLogExplicitGcs:_")
+          .WithHelp("Allows one to control the logging of explicit GCs. Defaults to 'true'")
+          .WithType<bool>()
+          .WithValueMap({{"false", false}, {"true", true}})
+          .IntoKey(M::AlwaysLogExplicitGcs)
       .Define("-XX:UseTLAB")
           .WithValue(true)
           .IntoKey(M::UseTLAB)
@@ -197,23 +234,29 @@
           .WithType<bool>()
           .WithValueMap({{"false", false}, {"true", true}})
           .IntoKey(M::MadviseRandomAccess)
+      .Define("-XMadviseWillNeedVdexFileSize:_")
+          .WithType<unsigned int>()
+          .IntoKey(M::MadviseWillNeedVdexFileSize)
+      .Define("-XMadviseWillNeedOdexFileSize:_")
+          .WithType<unsigned int>()
+          .IntoKey(M::MadviseWillNeedOdexFileSize)
+      .Define("-XMadviseWillNeedArtFileSize:_")
+          .WithType<unsigned int>()
+          .IntoKey(M::MadviseWillNeedArtFileSize)
       .Define("-Xusejit:_")
           .WithType<bool>()
           .WithValueMap({{"false", false}, {"true", true}})
           .IntoKey(M::UseJitCompilation)
-      .Define("-Xusetieredjit:_")
+      .Define("-Xuseprofiledjit:_")
           .WithType<bool>()
           .WithValueMap({{"false", false}, {"true", true}})
-          .IntoKey(M::UseTieredJitCompilation)
+          .IntoKey(M::UseProfiledJitCompilation)
       .Define("-Xjitinitialsize:_")
           .WithType<MemoryKiB>()
           .IntoKey(M::JITCodeCacheInitialCapacity)
       .Define("-Xjitmaxsize:_")
           .WithType<MemoryKiB>()
           .IntoKey(M::JITCodeCacheMaxCapacity)
-      .Define("-Xjitthreshold:_")
-          .WithType<unsigned int>()
-          .IntoKey(M::JITCompileThreshold)
       .Define("-Xjitwarmupthreshold:_")
           .WithType<unsigned int>()
           .IntoKey(M::JITWarmupThreshold)
@@ -229,35 +272,44 @@
       .Define("-Xjitpthreadpriority:_")
           .WithType<int>()
           .IntoKey(M::JITPoolThreadPthreadPriority)
+      .Define("-Xjitzygotepthreadpriority:_")
+          .WithType<int>()
+          .IntoKey(M::JITZygotePoolThreadPthreadPriority)
       .Define("-Xjitsaveprofilinginfo")
           .WithType<ProfileSaverOptions>()
           .AppendValues()
           .IntoKey(M::ProfileSaverOpts)
-      .Define("-Xps-_")  // profile saver options -Xps-<key>:<value>
+      // .Define("-Xps-_")  // profile saver options -Xps-<key>:<value>
+      //     .WithType<ProfileSaverOptions>()
+      //     .AppendValues()
+      //     .IntoKey(M::ProfileSaverOpts)  // NOTE: Appends into same key as -Xjitsaveprofilinginfo
+      // profile saver options -Xps-<key>:<value> but are split-out for better help messages.
+      // The order of these is important. We want the wildcard one to be the
+      // only one actually matched so it needs to be first.
+      // TODO This should be redone.
+      .Define({"-Xps-_",
+               "-Xps-min-save-period-ms:_",
+               "-Xps-min-first-save-ms:_",
+               "-Xps-save-resolved-classes-delayed-ms:_",
+               "-Xps-hot-startup-method-samples:_",
+               "-Xps-min-methods-to-save:_",
+               "-Xps-min-classes-to-save:_",
+               "-Xps-min-notification-before-wake:_",
+               "-Xps-max-notification-before-wake:_",
+               "-Xps-profile-path:_"})
+          .WithHelp("profile-saver options -Xps-<key>:<value>")
           .WithType<ProfileSaverOptions>()
           .AppendValues()
           .IntoKey(M::ProfileSaverOpts)  // NOTE: Appends into same key as -Xjitsaveprofilinginfo
       .Define("-XX:HspaceCompactForOOMMinIntervalMs=_")  // in ms
           .WithType<MillisecondsToNanoseconds>()  // store as ns
           .IntoKey(M::HSpaceCompactForOOMMinIntervalsMs)
-      .Define("-D_")
-          .WithType<std::vector<std::string>>().AppendValues()
-          .IntoKey(M::PropertiesList)
-      .Define("-Xjnitrace:_")
-          .WithType<std::string>()
-          .IntoKey(M::JniTrace)
       .Define({"-Xrelocate", "-Xnorelocate"})
           .WithValues({true, false})
           .IntoKey(M::Relocate)
       .Define({"-Ximage-dex2oat", "-Xnoimage-dex2oat"})
           .WithValues({true, false})
           .IntoKey(M::ImageDex2Oat)
-      .Define("-Xint")
-          .WithValue(true)
-          .IntoKey(M::Interpret)
-      .Define("-Xgc:_")
-          .WithType<XGcOption>()
-          .IntoKey(M::GcOption)
       .Define("-XX:LargeObjectSpace=_")
           .WithType<gc::space::LargeObjectSpaceType>()
           .WithValueMap({{"disabled", gc::space::LargeObjectSpaceType::kDisabled},
@@ -272,9 +324,6 @@
           .IntoKey(M::BackgroundGc)
       .Define("-XX:+DisableExplicitGC")
           .IntoKey(M::DisableExplicitGC)
-      .Define("-verbose:_")
-          .WithType<LogVerbosity>()
-          .IntoKey(M::Verbose)
       .Define("-Xlockprofthreshold:_")
           .WithType<unsigned int>()
           .IntoKey(M::LockProfThreshold)
@@ -291,12 +340,6 @@
           .IntoKey(M::MethodTraceFileSize)
       .Define("-Xmethod-trace-stream")
           .IntoKey(M::MethodTraceStreaming)
-      .Define("-Xprofile:_")
-          .WithType<TraceClockSource>()
-          .WithValueMap({{"threadcpuclock", TraceClockSource::kThreadCpu},
-                         {"wallclock",      TraceClockSource::kWall},
-                         {"dualclock",      TraceClockSource::kDual}})
-          .IntoKey(M::ProfileClock)
       .Define("-Xcompiler:_")
           .WithType<std::string>()
           .IntoKey(M::Compiler)
@@ -321,8 +364,6 @@
       .Define("-Xzygote-max-boot-retry=_")
           .WithType<unsigned int>()
           .IntoKey(M::ZygoteMaxFailedBoots)
-      .Define("-Xno-dex-file-fallback")
-          .IntoKey(M::NoDexFileFallback)
       .Define("-Xno-sig-chain")
           .IntoKey(M::NoSigChain)
       .Define("--cpu-abilist=_")
@@ -338,11 +379,19 @@
       .Define("-Xforce-nb-testing")
           .IntoKey(M::ForceNativeBridge)
       .Define("-Xplugin:_")
+          .WithHelp("Load and initialize the specified art-plugin.")
           .WithType<std::vector<Plugin>>().AppendValues()
           .IntoKey(M::Plugins)
       .Define("-XX:ThreadSuspendTimeout=_")  // in ms
           .WithType<MillisecondsToNanoseconds>()  // store as ns
           .IntoKey(M::ThreadSuspendTimeout)
+      .Define("-XX:MonitorTimeoutEnable=_")
+          .WithType<bool>()
+          .WithValueMap({{"false", false}, {"true", true}})
+          .IntoKey(M::MonitorTimeoutEnable)
+      .Define("-XX:MonitorTimeout=_")  // in ms
+          .WithType<int>()
+          .IntoKey(M::MonitorTimeout)
       .Define("-XX:GlobalRefAllocStackTraceLimit=_")  // Number of free slots to enable tracing.
           .WithType<unsigned int>()
           .IntoKey(M::GlobalRefAllocStackTraceLimit)
@@ -364,7 +413,9 @@
       .Define("-Xuse-stderr-logger")
           .IntoKey(M::UseStderrLogger)
       .Define("-Xonly-use-system-oat-files")
-          .IntoKey(M::OnlyUseSystemOatFiles)
+          .IntoKey(M::OnlyUseTrustedOatFiles)
+      .Define("-Xdeny-art-apex-data-files")
+          .IntoKey(M::DenyArtApexDataFiles)
       .Define("-Xverifier-logging-threshold=_")
           .WithType<unsigned int>()
           .IntoKey(M::VerifierLoggingThreshold)
@@ -373,6 +424,7 @@
           .WithValueMap({{"false", false}, {"true", true}})
           .IntoKey(M::FastClassNotFoundException)
       .Define("-Xopaque-jni-ids:_")
+          .WithHelp("Control the representation of jmethodID and jfieldID values")
           .WithType<JniIdType>()
           .WithValueMap({{"true", JniIdType::kIndices},
                          {"false", JniIdType::kPointer},
@@ -389,20 +441,32 @@
           .WithType<bool>()
           .WithValueMap({{"false", false}, {"true", true}})
           .IntoKey(M::VerifierMissingKThrowFatal)
+      .Define("-XX:ForceJavaZygoteForkLoop=_")
+          .WithType<bool>()
+          .WithValueMap({{"false", false}, {"true", true}})
+          .IntoKey(M::ForceJavaZygoteForkLoop)
       .Define("-XX:PerfettoHprof=_")
           .WithType<bool>()
           .WithValueMap({{"false", false}, {"true", true}})
           .IntoKey(M::PerfettoHprof)
-      .Ignore({
+      .Define("-XX:PerfettoJavaHeapStackProf=_")
+          .WithType<bool>()
+          .WithValueMap({{"false", false}, {"true", true}})
+          .IntoKey(M::PerfettoJavaHeapStackProf);
+
+      FlagBase::AddFlagsToCmdlineParser(parser_builder.get());
+
+      parser_builder->Ignore({
           "-ea", "-da", "-enableassertions", "-disableassertions", "--runtime-arg", "-esa",
           "-dsa", "-enablesystemassertions", "-disablesystemassertions", "-Xrs", "-Xint:_",
           "-Xdexopt:_", "-Xnoquithandler", "-Xjnigreflimit:_", "-Xgenregmap", "-Xnogenregmap",
           "-Xverifyopt:_", "-Xcheckdexsum", "-Xincludeselectedop", "-Xjitop:_",
-          "-Xincludeselectedmethod", "-Xjitthreshold:_",
+          "-Xincludeselectedmethod",
           "-Xjitblocking", "-Xjitmethod:_", "-Xjitclass:_", "-Xjitoffset:_",
           "-Xjitconfig:_", "-Xjitcheckcg", "-Xjitverbose", "-Xjitprofile",
           "-Xjitdisableopt", "-Xjitsuspendpoll", "-XX:mainThreadStackSize=_"})
-      .IgnoreUnrecognized(ignore_unrecognized);
+      .IgnoreUnrecognized(ignore_unrecognized)
+      .OrderCategories({"standard", "extended", "Dalvik", "ART"});
 
   // TODO: Move Usage information into this DSL.
 
@@ -509,6 +573,7 @@
   //  gLogVerbosity.deopt = true;  // TODO: don't check this in!
   //  gLogVerbosity.gc = true;  // TODO: don't check this in!
   //  gLogVerbosity.heap = true;  // TODO: don't check this in!
+  //  gLogVerbosity.image = true;  // TODO: don't check this in!
   //  gLogVerbosity.interpreter = true;  // TODO: don't check this in!
   //  gLogVerbosity.jdwp = true;  // TODO: don't check this in!
   //  gLogVerbosity.jit = true;  // TODO: don't check this in!
@@ -660,7 +725,9 @@
   }
 
   if (!args.Exists(M::CompilerCallbacksPtr) && !args.Exists(M::Image)) {
-    std::string image = GetDefaultBootImageLocation(GetAndroidRoot());
+    const bool deny_art_apex_data_files = args.Exists(M::DenyArtApexDataFiles);
+    std::string image =
+        GetDefaultBootImageLocation(GetAndroidRoot(), deny_art_apex_data_files);
     args.Set(M::Image, image);
   }
 
@@ -707,147 +774,12 @@
   const char* program = "dalvikvm";
   UsageMessage(stream, "%s: [options] class [argument ...]\n", program);
   UsageMessage(stream, "\n");
-  UsageMessage(stream, "The following standard options are supported:\n");
-  UsageMessage(stream, "  -classpath classpath (-cp classpath)\n");
-  UsageMessage(stream, "  -Dproperty=value\n");
-  UsageMessage(stream, "  -verbose:tag[,tag...] (currently valid tags: 'agents', 'class',\n"
-                       "    'collector', 'compiler', 'deopt', 'dex', 'gc', 'heap', 'image',\n"
-                       "    'interpreter', 'jdwp', 'jit', 'jni', 'monitor', 'oat', 'profiler',\n"
-                       "    'signals', 'simulator', 'startup', 'systrace-locks',\n"
-                       "    'third-party-jni', 'threads', 'verifier', 'verifier-debug')\n");
-  UsageMessage(stream, "  -showversion\n");
-  UsageMessage(stream, "  -help\n");
-  // TODO add back in once -agentlib actually does something.
-  // UsageMessage(stream, "  -agentlib:library=options (Experimental feature, "
-  //                      "requires -Xexperimental:agent, some features might not be supported)\n");
-  UsageMessage(stream, "  -agentpath:library_path=options (Experimental feature, requires\n"
-                       "    -Xexperimental:agent, some features might not be supported)\n");
-  UsageMessage(stream, "\n");
 
-  UsageMessage(stream, "The following extended options are supported:\n");
-  UsageMessage(stream, "  -Xbootclasspath:bootclasspath\n");
-  UsageMessage(stream, "  -Xcheck:tag  (e.g. 'jni')\n");
-  UsageMessage(stream, "  -XmsN (min heap, must be multiple of 1K, >= 1MB)\n");
-  UsageMessage(stream, "  -XmxN (max heap, must be multiple of 1K, >= 2MB)\n");
-  UsageMessage(stream, "  -XssN (stack size)\n");
-  UsageMessage(stream, "  -Xint\n");
-  UsageMessage(stream, "\n");
-
-  UsageMessage(stream, "The following Dalvik options are supported:\n");
-  UsageMessage(stream, "  -Xzygote\n");
-  UsageMessage(stream, "  -Xjnitrace:substring (eg NativeClass or nativeMethod)\n");
-  UsageMessage(stream, "  -Xgc:[no]preverify\n");
-  UsageMessage(stream, "  -Xgc:[no]postverify\n");
-  UsageMessage(stream, "  -XX:HeapGrowthLimit=N\n");
-  UsageMessage(stream, "  -XX:HeapMinFree=N\n");
-  UsageMessage(stream, "  -XX:HeapMaxFree=N\n");
-  UsageMessage(stream, "  -XX:NonMovingSpaceCapacity=N\n");
-  UsageMessage(stream, "  -XX:HeapTargetUtilization=doublevalue\n");
-  UsageMessage(stream, "  -XX:ForegroundHeapGrowthMultiplier=doublevalue\n");
-  UsageMessage(stream, "  -XX:LowMemoryMode\n");
-  UsageMessage(stream, "  -Xprofile:{threadcpuclock,wallclock,dualclock}\n");
-  UsageMessage(stream, "  -Xjitthreshold:integervalue\n");
-  UsageMessage(stream, "\n");
-
-  UsageMessage(stream, "The following unique to ART options are supported:\n");
-  UsageMessage(stream, "  -Xgc:[no]preverify_rosalloc\n");
-  UsageMessage(stream, "  -Xgc:[no]postsweepingverify_rosalloc\n");
-  UsageMessage(stream, "  -Xgc:[no]postverify_rosalloc\n");
-  UsageMessage(stream, "  -Xgc:[no]presweepingverify\n");
-  UsageMessage(stream, "  -Xgc:[no]generational_cc\n");
-  UsageMessage(stream, "  -Ximage:filename\n");
-  UsageMessage(stream, "  -Xbootclasspath-locations:bootclasspath\n"
-                       "     (override the dex locations of the -Xbootclasspath files)\n");
-  UsageMessage(stream, "  -XX:+DisableExplicitGC\n");
-  UsageMessage(stream, "  -XX:ParallelGCThreads=integervalue\n");
-  UsageMessage(stream, "  -XX:ConcGCThreads=integervalue\n");
-  UsageMessage(stream, "  -XX:FinalizerTimeoutMs=integervalue\n");
-  UsageMessage(stream, "  -XX:MaxSpinsBeforeThinLockInflation=integervalue\n");
-  UsageMessage(stream, "  -XX:LongPauseLogThreshold=integervalue\n");
-  UsageMessage(stream, "  -XX:LongGCLogThreshold=integervalue\n");
-  UsageMessage(stream, "  -XX:ThreadSuspendTimeout=integervalue\n");
-  UsageMessage(stream, "  -XX:DumpGCPerformanceOnShutdown\n");
-  UsageMessage(stream, "  -XX:DumpJITInfoOnShutdown\n");
-  UsageMessage(stream, "  -XX:IgnoreMaxFootprint\n");
-  UsageMessage(stream, "  -XX:UseTLAB\n");
-  UsageMessage(stream, "  -XX:BackgroundGC=none\n");
-  UsageMessage(stream, "  -XX:LargeObjectSpace={disabled,map,freelist}\n");
-  UsageMessage(stream, "  -XX:LargeObjectThreshold=N\n");
-  UsageMessage(stream, "  -XX:StopForNativeAllocs=N\n");
-  UsageMessage(stream, "  -XX:DumpNativeStackOnSigQuit=booleanvalue\n");
-  UsageMessage(stream, "  -XX:MadviseRandomAccess:booleanvalue\n");
-  UsageMessage(stream, "  -XX:SlowDebug={false,true}\n");
-  UsageMessage(stream, "  -Xmethod-trace\n");
-  UsageMessage(stream, "  -Xmethod-trace-file:filename\n");
-  UsageMessage(stream, "  -Xmethod-trace-file-size:integervalue\n");
-  UsageMessage(stream, "  -Xps-min-save-period-ms:integervalue\n");
-  UsageMessage(stream, "  -Xps-save-resolved-classes-delay-ms:integervalue\n");
-  UsageMessage(stream, "  -Xps-hot-startup-method-samples:integervalue\n");
-  UsageMessage(stream, "  -Xps-min-methods-to-save:integervalue\n");
-  UsageMessage(stream, "  -Xps-min-classes-to-save:integervalue\n");
-  UsageMessage(stream, "  -Xps-min-notification-before-wake:integervalue\n");
-  UsageMessage(stream, "  -Xps-max-notification-before-wake:integervalue\n");
-  UsageMessage(stream, "  -Xps-profile-path:file-path\n");
-  UsageMessage(stream, "  -Xcompiler:filename\n");
-  UsageMessage(stream, "  -Xcompiler-option dex2oat-option\n");
-  UsageMessage(stream, "  -Ximage-compiler-option dex2oat-option\n");
-  UsageMessage(stream, "  -Xusejit:booleanvalue\n");
-  UsageMessage(stream, "  -Xjitinitialsize:N\n");
-  UsageMessage(stream, "  -Xjitmaxsize:N\n");
-  UsageMessage(stream, "  -Xjitwarmupthreshold:integervalue\n");
-  UsageMessage(stream, "  -Xjitosrthreshold:integervalue\n");
-  UsageMessage(stream, "  -Xjitprithreadweight:integervalue\n");
-  UsageMessage(stream, "  -X[no]relocate\n");
-  UsageMessage(stream, "  -X[no]dex2oat (Whether to invoke dex2oat on the application)\n");
-  UsageMessage(stream, "  -X[no]image-dex2oat (Whether to create and use a boot image)\n");
-  UsageMessage(stream, "  -Xno-dex-file-fallback "
-                       "(Don't fall back to dex files without oat files)\n");
-  UsageMessage(stream, "  -Xplugin:<library.so> "
-                       "(Load a runtime plugin, requires -Xexperimental:runtime-plugins)\n");
-  UsageMessage(stream, "  -Xexperimental:runtime-plugins"
-                       "(Enable new and experimental agent support)\n");
-  UsageMessage(stream, "  -Xexperimental:agents"
-                       "(Enable new and experimental agent support)\n");
-  UsageMessage(stream, "  -Xopaque-jni-ids:{true,false,swapable}");
-  UsageMessage(stream, "(Use opauque integers for jni ids, yes, no or punt for later)\n");
-  UsageMessage(stream, "\n");
-
-  UsageMessage(stream, "The following previously supported Dalvik options are ignored:\n");
-  UsageMessage(stream, "  -ea[:<package name>... |:<class name>]\n");
-  UsageMessage(stream, "  -da[:<package name>... |:<class name>]\n");
-  UsageMessage(stream, "   (-enableassertions, -disableassertions)\n");
-  UsageMessage(stream, "  -esa\n");
-  UsageMessage(stream, "  -dsa\n");
-  UsageMessage(stream, "   (-enablesystemassertions, -disablesystemassertions)\n");
-  UsageMessage(stream, "  -Xverify:{none,remote,all,softfail}\n");
-  UsageMessage(stream, "  -Xrs\n");
-  UsageMessage(stream, "  -Xint:portable, -Xint:fast, -Xint:jit\n");
-  UsageMessage(stream, "  -Xdexopt:{none,verified,all,full}\n");
-  UsageMessage(stream, "  -Xnoquithandler\n");
-  UsageMessage(stream, "  -Xjniopts:{warnonly,forcecopy}\n");
-  UsageMessage(stream, "  -Xjnigreflimit:integervalue\n");
-  UsageMessage(stream, "  -Xgc:[no]precise\n");
-  UsageMessage(stream, "  -Xgc:[no]verifycardtable\n");
-  UsageMessage(stream, "  -X[no]genregmap\n");
-  UsageMessage(stream, "  -Xverifyopt:[no]checkmon\n");
-  UsageMessage(stream, "  -Xcheckdexsum\n");
-  UsageMessage(stream, "  -Xincludeselectedop\n");
-  UsageMessage(stream, "  -Xjitop:hexopvalue[-endvalue][,hexopvalue[-endvalue]]*\n");
-  UsageMessage(stream, "  -Xincludeselectedmethod\n");
-  UsageMessage(stream, "  -Xjitblocking\n");
-  UsageMessage(stream, "  -Xjitmethod:signature[,signature]* (eg Ljava/lang/String\\;replace)\n");
-  UsageMessage(stream, "  -Xjitclass:classname[,classname]*\n");
-  UsageMessage(stream, "  -Xjitcodecachesize:N\n");
-  UsageMessage(stream, "  -Xjitoffset:offset[,offset]\n");
-  UsageMessage(stream, "  -Xjitconfig:filename\n");
-  UsageMessage(stream, "  -Xjitcheckcg\n");
-  UsageMessage(stream, "  -Xjitverbose\n");
-  UsageMessage(stream, "  -Xjitprofile\n");
-  UsageMessage(stream, "  -Xjitdisableopt\n");
-  UsageMessage(stream, "  -Xjitsuspendpoll\n");
-  UsageMessage(stream, "  -XX:mainThreadStackSize=N\n");
-  UsageMessage(stream, "\n");
-
+  std::stringstream oss;
+  VariableIndentationOutputStream vios(&oss);
+  auto parser = MakeParser(false);
+  parser->DumpHelp(vios);
+  UsageMessage(stream, oss.str().c_str());
   Exit((error) ? 1 : 0);
 }
 
diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h
index 39ce4ce..608805b 100644
--- a/runtime/parsed_options.h
+++ b/runtime/parsed_options.h
@@ -18,13 +18,13 @@
 #define ART_RUNTIME_PARSED_OPTIONS_H_
 
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include <jni.h>
 
 #include "arch/instruction_set.h"
 #include "gc/collector_type.h"
-#include "gc/space/image_space_loading_order.h"
 #include "gc/space/large_object_space.h"
 // #include "jit/profile_saver_options.h"
 #include "runtime_globals.h"
diff --git a/runtime/prebuilt_tools_test.cc b/runtime/prebuilt_tools_test.cc
index 158d9d6..e05a8e4 100644
--- a/runtime/prebuilt_tools_test.cc
+++ b/runtime/prebuilt_tools_test.cc
@@ -26,39 +26,24 @@
 #ifndef ART_TARGET_ANDROID
 
 class PrebuiltToolsTest : public CommonRuntimeTest {
-};
-
-static void CheckToolsExist(const std::string& tools_dir) {
-  const char* tools[] = { "as", "objcopy", "objdump" };
-  for (const char* tool : tools) {
-    struct stat exec_st;
-    std::string exec_path = tools_dir + tool;
-    if (stat(exec_path.c_str(), &exec_st) != 0) {
-      ADD_FAILURE() << "Cannot find " << tool << " in " << tools_dir;
+ public:
+  static void CheckToolsExist(InstructionSet isa) {
+    const char* tools[] = { "clang", "llvm-addr2line", "llvm-dwarfdump", "llvm-objdump" };
+    for (const char* tool : tools) {
+      std::string path = GetAndroidTool(tool, isa);
+      ASSERT_TRUE(OS::FileExists(path.c_str())) << path;
     }
   }
-}
+};
 
 TEST_F(PrebuiltToolsTest, CheckHostTools) {
-  std::string tools_dir = GetAndroidHostToolsDir();
-  if (tools_dir.empty()) {
-    ADD_FAILURE() << "Cannot find Android tools directory for host";
-  } else {
-    CheckToolsExist(tools_dir);
-  }
+  CheckToolsExist(InstructionSet::kX86);
+  CheckToolsExist(InstructionSet::kX86_64);
 }
 
 TEST_F(PrebuiltToolsTest, CheckTargetTools) {
-  // Other prebuilts are missing from the build server's repo manifest.
-  InstructionSet isas[] = { InstructionSet::kThumb2 };
-  for (InstructionSet isa : isas) {
-    std::string tools_dir = GetAndroidTargetToolsDir(isa);
-    if (tools_dir.empty()) {
-      ADD_FAILURE() << "Cannot find Android tools directory for " << isa;
-    } else {
-      CheckToolsExist(tools_dir);
-    }
-  }
+  CheckToolsExist(InstructionSet::kThumb2);
+  CheckToolsExist(InstructionSet::kArm64);
 }
 
 #endif  // ART_TARGET_ANDROID
diff --git a/runtime/process_state.h b/runtime/process_state.h
index e8797d6..aee200a 100644
--- a/runtime/process_state.h
+++ b/runtime/process_state.h
@@ -26,7 +26,7 @@
   kProcessStateJankImperceptible = 1,
 };
 
-std::ostream& operator<<(std::ostream& os, const ProcessState& process_state);
+std::ostream& operator<<(std::ostream& os, ProcessState process_state);
 
 }  // namespace art
 
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index b78855f..d8e170b 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -20,7 +20,7 @@
 #include "art_field-inl.h"
 #include "base/enums.h"
 #include "common_runtime_test.h"
-#include "mirror/field-inl.h"
+#include "mirror/field.h"
 #include "proxy_test.h"
 #include "scoped_thread_state_change-inl.h"
 #include "well_known_classes.h"
@@ -173,17 +173,13 @@
   ASSERT_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
   ASSERT_FALSE(Runtime::Current()->IsActiveTransaction());
   Handle<mirror::Field> field00 =
-      hs.NewHandle(mirror::Field::CreateFromArtField<kRuntimePointerSize, false>(
-          soa.Self(), &static_fields0->At(0), true));
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields0->At(0), true));
   Handle<mirror::Field> field01 =
-      hs.NewHandle(mirror::Field::CreateFromArtField<kRuntimePointerSize, false>(
-          soa.Self(), &static_fields0->At(1), true));
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields0->At(1), true));
   Handle<mirror::Field> field10 =
-      hs.NewHandle(mirror::Field::CreateFromArtField<kRuntimePointerSize, false>(
-          soa.Self(), &static_fields1->At(0), true));
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields1->At(0), true));
   Handle<mirror::Field> field11 =
-      hs.NewHandle(mirror::Field::CreateFromArtField<kRuntimePointerSize, false>(
-          soa.Self(), &static_fields1->At(1), true));
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields1->At(1), true));
   EXPECT_EQ(field00->GetArtField(), &static_fields0->At(0));
   EXPECT_EQ(field01->GetArtField(), &static_fields0->At(1));
   EXPECT_EQ(field10->GetArtField(), &static_fields1->At(0));
diff --git a/runtime/proxy_test.h b/runtime/proxy_test.h
index 23e536d..9a01441 100644
--- a/runtime/proxy_test.h
+++ b/runtime/proxy_test.h
@@ -22,7 +22,7 @@
 
 #include "art_method-inl.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/method.h"
 #include "obj_ptr-inl.h"
@@ -33,11 +33,11 @@
 // Generate a proxy class with the given name and interfaces. This is a simplification from what
 // libcore does to fit to our test needs. We do not check for duplicated interfaces or methods and
 // we do not declare exceptions.
-ObjPtr<mirror::Class> GenerateProxyClass(ScopedObjectAccess& soa,
-                                         jobject jclass_loader,
-                                         ClassLinker* class_linker,
-                                         const char* className,
-                                         const std::vector<Handle<mirror::Class>>& interfaces)
+inline ObjPtr<mirror::Class> GenerateProxyClass(ScopedObjectAccess& soa,
+                                                jobject jclass_loader,
+                                                ClassLinker* class_linker,
+                                                const char* className,
+                                                const std::vector<Handle<mirror::Class>>& interfaces)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   StackHandleScope<1> hs(soa.Self());
   Handle<mirror::Class> javaLangObject = hs.NewHandle(GetClassRoot<mirror::Object>());
@@ -76,14 +76,14 @@
   DCHECK(!Runtime::Current()->IsActiveTransaction());
   soa.Env()->SetObjectArrayElement(
       proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
-          mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method)));
+          mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), method)));
   method = javaLangObject->FindClassMethod("hashCode", "()I", kRuntimePointerSize);
   CHECK(method != nullptr);
   CHECK(!method->IsDirect());
   CHECK(method->GetDeclaringClass() == javaLangObject.Get());
   soa.Env()->SetObjectArrayElement(
       proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
-          mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method)));
+          mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), method)));
   method = javaLangObject->FindClassMethod(
       "toString", "()Ljava/lang/String;", kRuntimePointerSize);
   CHECK(method != nullptr);
@@ -91,13 +91,13 @@
   CHECK(method->GetDeclaringClass() == javaLangObject.Get());
   soa.Env()->SetObjectArrayElement(
       proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
-          mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), method)));
+          mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), method)));
   // Now adds all interfaces virtual methods.
   for (Handle<mirror::Class> interface : interfaces) {
     for (auto& m : interface->GetDeclaredVirtualMethods(kRuntimePointerSize)) {
       soa.Env()->SetObjectArrayElement(
           proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
-              mirror::Method::CreateFromArtMethod<kRuntimePointerSize, false>(soa.Self(), &m)));
+              mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), &m)));
     }
   }
   CHECK_EQ(array_index, methods_count);
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 90732e1..5f497af 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -15,10 +15,12 @@
  */
 
 #include "quick_exception_handler.h"
+#include <ios>
 
 #include "arch/context.h"
 #include "art_method-inl.h"
 #include "base/enums.h"
+#include "base/globals.h"
 #include "base/logging.h"  // For VLOG_IS_ON.
 #include "base/systrace.h"
 #include "dex/dex_file_types.h"
@@ -465,7 +467,12 @@
         ? code_info.GetInlineDexRegisterMapOf(stack_map, GetCurrentInlinedFrame())
         : code_info.GetDexRegisterMapOf(stack_map);
 
-    DCHECK_EQ(vreg_map.size(), number_of_vregs);
+    if (kIsDebugBuild || UNLIKELY(Runtime::Current()->IsJavaDebuggable())) {
+      CHECK_EQ(vreg_map.size(), number_of_vregs) << *Thread::Current()
+                                                 << "Deopting: " << m->PrettyMethod()
+                                                 << " inlined? "
+                                                 << std::boolalpha << IsInInlinedFrame();
+    }
     if (vreg_map.empty()) {
       return;
     }
@@ -497,7 +504,7 @@
         case DexRegisterLocation::Kind::kInFpuRegister:
         case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
           uint32_t reg = vreg_map[vreg].GetMachineRegister();
-          bool result = GetRegisterIfAccessible(reg, ToVRegKind(location), &value);
+          bool result = GetRegisterIfAccessible(reg, location, &value);
           CHECK(result);
           if (location == DexRegisterLocation::Kind::kInRegister) {
             if (((1u << reg) & register_mask) != 0) {
diff --git a/runtime/quicken_info.h b/runtime/quicken_info.h
index 6c18590..83dc5f1 100644
--- a/runtime/quicken_info.h
+++ b/runtime/quicken_info.h
@@ -57,7 +57,7 @@
 
   // Returns true if the dex instruction has an index in the table. (maybe dequickenable).
   static bool NeedsIndexForInstruction(const Instruction* inst) {
-    return inst->IsQuickened() || inst->Opcode() == Instruction::NOP;
+    return inst->IsQuickened();
   }
 
   static size_t NumberOfIndices(size_t bytes) {
diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc
index e5c1e6a..7a1e668 100644
--- a/runtime/reference_table_test.cc
+++ b/runtime/reference_table_test.cc
@@ -109,7 +109,7 @@
     EXPECT_EQ(oss.str().find("short[]"), std::string::npos) << oss.str();
   }
 
-  // Add a second object 10 times and check dumping is sane.
+  // Add a second object 10 times so we can then check dumping works as expected.
   Handle<mirror::ShortArray> o2 = hs.NewHandle(mirror::ShortArray::Alloc(soa.Self(), 0));
   for (size_t i = 0; i < 10; ++i) {
     rt.Add(o2.Get());
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 469d329..f642bcb 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -494,18 +494,26 @@
 
   // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early.
   if (soa.Self()->IsExceptionPending()) {
-    // If we get another exception when we are trying to wrap, then just use that instead.
-    ScopedLocalRef<jthrowable> th(soa.Env(), soa.Env()->ExceptionOccurred());
-    soa.Self()->ClearException();
-    jobject exception_instance =
-        soa.Env()->NewObject(WellKnownClasses::java_lang_reflect_InvocationTargetException,
-                             WellKnownClasses::java_lang_reflect_InvocationTargetException_init,
-                             th.get());
-    if (exception_instance == nullptr) {
-      soa.Self()->AssertPendingException();
-      return false;
+    // To abort a transaction we use a fake exception that should never be caught by the bytecode
+    // and therefore it makes no sense to wrap it.
+    if (Runtime::Current()->IsTransactionAborted()) {
+      DCHECK(soa.Self()->GetException()->GetClass()->DescriptorEquals(
+                  "Ldalvik/system/TransactionAbortError;"))
+          << soa.Self()->GetException()->GetClass()->PrettyDescriptor();
+    } else {
+      // If we get another exception when we are trying to wrap, then just use that instead.
+      ScopedLocalRef<jthrowable> th(soa.Env(), soa.Env()->ExceptionOccurred());
+      soa.Self()->ClearException();
+      jobject exception_instance =
+          soa.Env()->NewObject(WellKnownClasses::java_lang_reflect_InvocationTargetException,
+                               WellKnownClasses::java_lang_reflect_InvocationTargetException_init,
+                               th.get());
+      if (exception_instance == nullptr) {
+        soa.Self()->AssertPendingException();
+        return false;
+      }
+      soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance));
     }
-    soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance));
     return false;
   }
 
@@ -683,6 +691,7 @@
   return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, jni::DecodeArtMethod(mid), args);
 }
 
+template <PointerSize kPointerSize>
 jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaMethod,
                      jobject javaReceiver, jobject javaArgs, size_t num_frames) {
   // We want to make sure that the stack is not within a small distance from the
@@ -725,14 +734,14 @@
       }
 
       // Find the actual implementation of the virtual method.
-      m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m, kRuntimePointerSize);
+      m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m, kPointerSize);
     }
   }
 
   // Get our arrays of arguments and their types, and check they're the same size.
   ObjPtr<mirror::ObjectArray<mirror::Object>> objects =
       soa.Decode<mirror::ObjectArray<mirror::Object>>(javaArgs);
-  auto* np_method = m->GetInterfaceMethodIfProxy(kRuntimePointerSize);
+  auto* np_method = m->GetInterfaceMethodIfProxy(kPointerSize);
   if (!CheckArgsForInvokeMethod(np_method, objects)) {
     return nullptr;
   }
@@ -764,6 +773,19 @@
   return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result));
 }
 
+template
+jobject InvokeMethod<PointerSize::k32>(const ScopedObjectAccessAlreadyRunnable& soa,
+                                       jobject javaMethod,
+                                       jobject javaReceiver,
+                                       jobject javaArgs,
+                                       size_t num_frames);
+template
+jobject InvokeMethod<PointerSize::k64>(const ScopedObjectAccessAlreadyRunnable& soa,
+                                       jobject javaMethod,
+                                       jobject javaReceiver,
+                                       jobject javaArgs,
+                                       size_t num_frames);
+
 void InvokeConstructor(const ScopedObjectAccessAlreadyRunnable& soa,
                        ArtMethod* constructor,
                        ObjPtr<mirror::Object> receiver,
@@ -1045,8 +1067,8 @@
   IndirectRefKind kind = IndirectReferenceTable::GetIndirectRefKind(ref);
   if (kind == kLocal) {
     self->GetJniEnv()->UpdateLocal(obj, result);
-  } else if (kind == kHandleScopeOrInvalid) {
-    LOG(FATAL) << "Unsupported UpdateReference for kind kHandleScopeOrInvalid";
+  } else if (kind == kJniTransitionOrInvalid) {
+    LOG(FATAL) << "Unsupported UpdateReference for kind kJniTransitionOrInvalid";
   } else if (kind == kGlobal) {
     self->GetJniEnv()->GetVm()->UpdateGlobal(self, ref, result);
   } else {
diff --git a/runtime/reflection.h b/runtime/reflection.h
index 5a2da35..b0e27da 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_REFLECTION_H_
 #define ART_RUNTIME_REFLECTION_H_
 
+#include "base/enums.h"
 #include "base/locks.h"
 #include "dex/primitive.h"
 #include "jni.h"
@@ -97,6 +98,7 @@
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 // num_frames is number of frames we look up for access check.
+template<PointerSize pointer_size>
 jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa,
                      jobject method,
                      jobject receiver,
diff --git a/runtime/reflective_value_visitor.h b/runtime/reflective_value_visitor.h
index 3a72760..87c5fe7 100644
--- a/runtime/reflective_value_visitor.h
+++ b/runtime/reflective_value_visitor.h
@@ -98,7 +98,7 @@
   kSourceDexCacheResolvedField,
   kSourceMiscInternal,
 };
-std::ostream& operator<<(std::ostream& os, const ReflectionSourceType& type);
+std::ostream& operator<<(std::ostream& os, ReflectionSourceType type);
 
 class ReflectionSourceInfo : public ValueObject {
  public:
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 7c6e34c..433f564 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -34,6 +34,7 @@
 #include <cstdio>
 #include <cstdlib>
 #include <limits>
+#include <string.h>
 #include <thread>
 #include <unordered_set>
 #include <vector>
@@ -56,6 +57,7 @@
 #include "base/dumpable.h"
 #include "base/enums.h"
 #include "base/file_utils.h"
+#include "base/flags.h"
 #include "base/malloc_arena_pool.h"
 #include "base/mem_map_arena_pool.h"
 #include "base/memory_tool.h"
@@ -68,7 +70,7 @@
 #include "base/unix_file/fd_file.h"
 #include "base/utils.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "compiler_callbacks.h"
 #include "debugger.h"
 #include "dex/art_dex_file_loader.h"
@@ -150,6 +152,7 @@
 #include "oat_file_manager.h"
 #include "oat_quick_method_header.h"
 #include "object_callbacks.h"
+#include "odr_statslog/odr_statslog.h"
 #include "parsed_options.h"
 #include "quick/quick_method_frame_info.h"
 #include "reflection.h"
@@ -172,6 +175,9 @@
 
 #ifdef ART_TARGET_ANDROID
 #include <android/set_abort_message.h>
+#include "com_android_apex.h"
+namespace apex = com::android::apex;
+
 #endif
 
 // Static asserts to check the values of generated assembly-support macros.
@@ -268,8 +274,8 @@
       dump_gc_performance_on_shutdown_(false),
       preinitialization_transactions_(),
       verify_(verifier::VerifyMode::kNone),
-      allow_dex_file_fallback_(true),
       target_sdk_version_(static_cast<uint32_t>(SdkVersion::kUnset)),
+      compat_framework_(),
       implicit_null_checks_(false),
       implicit_so_checks_(false),
       implicit_suspend_checks_(false),
@@ -280,10 +286,15 @@
       async_exceptions_thrown_(false),
       non_standard_exits_enabled_(false),
       is_java_debuggable_(false),
+      monitor_timeout_enable_(false),
+      monitor_timeout_ns_(0),
       zygote_max_failed_boots_(0),
       experimental_flags_(ExperimentalFlags::kNone),
       oat_file_manager_(nullptr),
       is_low_memory_mode_(false),
+      madvise_willneed_vdex_filesize_(0),
+      madvise_willneed_odex_filesize_(0),
+      madvise_willneed_art_filesize_(0),
       safe_mode_(false),
       hidden_api_policy_(hiddenapi::EnforcementPolicy::kDisabled),
       core_platform_api_policy_(hiddenapi::EnforcementPolicy::kDisabled),
@@ -291,13 +302,13 @@
       dedupe_hidden_api_warnings_(true),
       hidden_api_access_event_log_rate_(0),
       dump_native_stack_on_sig_quit_(true),
-      pruned_dalvik_cache_(false),
       // Initially assume we perceive jank in case the process state is never updated.
       process_state_(kProcessStateJankPerceptible),
       zygote_no_threads_(false),
       verifier_logging_threshold_ms_(100),
       verifier_missing_kthrow_fatal_(false),
-      perfetto_hprof_enabled_(false) {
+      perfetto_hprof_enabled_(false),
+      perfetto_javaheapprof_enabled_(false) {
   static_assert(Runtime::kCalleeSaveSize ==
                     static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType), "Unexpected size");
   CheckConstants();
@@ -440,6 +451,9 @@
   delete signal_catcher_;
   signal_catcher_ = nullptr;
 
+  // Shutdown metrics reporting.
+  metrics_reporter_.reset();
+
   // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
   // Also wait for daemon threads to quiesce, so that in addition to being "suspended", they
   // no longer access monitor and thread list data structures. We leak user daemon threads
@@ -686,8 +700,14 @@
 }
 
 void Runtime::PostZygoteFork() {
-  if (GetJit() != nullptr) {
-    GetJit()->PostZygoteFork();
+  jit::Jit* jit = GetJit();
+  if (jit != nullptr) {
+    jit->PostZygoteFork();
+    // Ensure that the threads in the JIT pool have been created with the right
+    // priority.
+    if (kIsDebugBuild && jit->GetThreadPool() != nullptr) {
+      jit->GetThreadPool()->CheckPthreadPriority(jit->GetThreadPoolPthreadPriority());
+    }
   }
   // Reset all stats.
   ResetStats(0xFFFFFFFF);
@@ -985,7 +1005,19 @@
       !jit_options_->GetProfileSaverOptions().GetProfilePath().empty()) {
     std::vector<std::string> dex_filenames;
     Split(class_path_string_, ':', &dex_filenames);
-    RegisterAppInfo(dex_filenames, jit_options_->GetProfileSaverOptions().GetProfilePath());
+
+    // We pass "" as the package name because at this point we don't know it. It could be the
+    // Zygote or it could be a dalvikvm cmd line execution. The package name will be re-set during
+    // post-fork or during RegisterAppInfo.
+    //
+    // Also, it's ok to pass "" to the ref profile filename. It indicates we don't have
+    // a reference profile.
+    RegisterAppInfo(
+        /*package_name=*/ "",
+        dex_filenames,
+        jit_options_->GetProfileSaverOptions().GetProfilePath(),
+        /*ref_profile_filename=*/ "",
+        kVMRuntimePrimaryApk);
   }
 
   return true;
@@ -1031,13 +1063,31 @@
 
   DCHECK(!IsZygote());
 
-  if (is_system_server && profile_system_server) {
+  if (is_system_server) {
+    // Register the system server code paths.
+    // TODO: Ideally this should be done by the VMRuntime#RegisterAppInfo. However, right now
+    // the method is only called when we set up the profile. It should be called all the time
+    // (simillar to the apps). Once that's done this manual registration can be removed.
+    const char* system_server_classpath = getenv("SYSTEMSERVERCLASSPATH");
+    if (system_server_classpath == nullptr || (strlen(system_server_classpath) == 0)) {
+      LOG(WARNING) << "System server class path not set";
+    } else {
+      std::vector<std::string> jars = android::base::Split(system_server_classpath, ":");
+      app_info_.RegisterAppInfo("android",
+                                jars,
+                                /*cur_profile_path=*/ "",
+                                /*ref_profile_path=*/ "",
+                                AppInfo::CodeType::kPrimaryApk);
+    }
+
     // Set the system server package name to "android".
     // This is used to tell the difference between samples provided by system server
     // and samples generated by other apps when processing boot image profiles.
     SetProcessPackageName("android");
-    jit_options_->SetWaitForJitNotificationsToSaveProfile(false);
-    VLOG(profiler) << "Enabling system server profiles";
+    if (profile_system_server) {
+      jit_options_->SetWaitForJitNotificationsToSaveProfile(false);
+      VLOG(profiler) << "Enabling system server profiles";
+    }
   }
 
   // Create the thread pools.
@@ -1056,15 +1106,34 @@
     thread_pool_->StartWorkers(Thread::Current());
   }
 
-  // Reset the gc performance data at zygote fork so that the GCs
+  // Reset the gc performance data and metrics at zygote fork so that the events from
   // before fork aren't attributed to an app.
   heap_->ResetGcPerformanceInfo();
+  GetMetrics()->Reset();
+
+  if (metrics_reporter_ != nullptr) {
+    // Now that we know if we are an app or system server, reload the metrics reporter config
+    // in case there are any difference.
+    metrics::ReportingConfig metrics_config =
+        metrics::ReportingConfig::FromFlags(is_system_server);
+
+    metrics_reporter_->ReloadConfig(metrics_config);
+
+    metrics::SessionData session_data{metrics::SessionData::CreateDefault()};
+    // Start the session id from 1 to avoid clashes with the default value.
+    // (better for debugability)
+    session_data.session_id = GetRandomNumber<int64_t>(1, std::numeric_limits<int64_t>::max());
+    // TODO: set session_data.compilation_reason and session_data.compiler_filter
+    metrics_reporter_->MaybeStartBackgroundThread(session_data);
+    // Also notify about any updates to the app info.
+    metrics_reporter_->NotifyAppInfoUpdated(&app_info_);
+  }
 
   StartSignalCatcher();
 
   ScopedObjectAccess soa(Thread::Current());
   if (IsPerfettoHprofEnabled() &&
-      (Dbg::IsJdwpAllowed() || IsProfileableFromShell() || IsJavaDebuggable() ||
+      (Dbg::IsJdwpAllowed() || IsProfileable() || IsProfileableFromShell() || IsJavaDebuggable() ||
        Runtime::Current()->IsSystemServer())) {
     std::string err;
     ScopedTrace tr("perfetto_hprof init.");
@@ -1073,6 +1142,22 @@
       LOG(WARNING) << "Failed to load perfetto_hprof: " << err;
     }
   }
+  if (IsPerfettoJavaHeapStackProfEnabled() &&
+      (Dbg::IsJdwpAllowed() || IsProfileable() || IsProfileableFromShell() || IsJavaDebuggable() ||
+       Runtime::Current()->IsSystemServer())) {
+    // Marker used for dev tracing similar to above markers.
+    ScopedTrace tr("perfetto_javaheapprof init.");
+  }
+  if (Runtime::Current()->IsSystemServer()) {
+    std::string err;
+    ScopedTrace tr("odrefresh stats logging");
+    ScopedThreadSuspension sts(Thread::Current(), ThreadState::kNative);
+    // Report stats if available. This should be moved into ART Services when they are ready.
+    if (!odrefresh::UploadStatsIfAvailable(&err)) {
+      LOG(WARNING) << "Failed to upload odrefresh metrics: " << err;
+    }
+  }
+
   if (LIKELY(automatically_set_jni_ids_indirection_) && CanSetJniIdType()) {
     if (IsJavaDebuggable()) {
       SetJniIdType(JniIdType::kIndices);
@@ -1080,6 +1165,9 @@
       SetJniIdType(JniIdType::kPointer);
     }
   }
+  ATraceIntegerValue(
+      "profilebootclasspath",
+      static_cast<int>(jit_options_->GetProfileSaverOptions().GetProfileBootClassPath()));
   // Start the JDWP thread. If the command-line debugger flags specified "suspend=y",
   // this will pause the runtime (in the internal debugger implementation), so we probably want
   // this to come last.
@@ -1183,6 +1271,62 @@
   detailMessageField->SetObject</* kTransactionActive= */ false>(exception->Read(), message);
 }
 
+void Runtime::InitializeApexVersions() {
+  std::vector<std::string_view> bcp_apexes;
+  for (std::string_view jar : Runtime::Current()->GetBootClassPathLocations()) {
+    if (LocationIsOnApex(jar)) {
+      size_t start = jar.find('/', 1);
+      if (start == std::string::npos) {
+        continue;
+      }
+      size_t end = jar.find('/', start + 1);
+      if (end == std::string::npos) {
+        continue;
+      }
+      std::string_view apex = jar.substr(start + 1, end - start - 1);
+      bcp_apexes.push_back(apex);
+    }
+  }
+  std::string result;
+  static const char* kApexFileName = "/apex/apex-info-list.xml";
+  // When running on host or chroot, we just encode empty markers.
+  if (!kIsTargetBuild || !OS::FileExists(kApexFileName)) {
+    for (uint32_t i = 0; i < bcp_apexes.size(); ++i) {
+      result += '/';
+    }
+  } else {
+#ifdef ART_TARGET_ANDROID
+    auto info_list = apex::readApexInfoList(kApexFileName);
+    CHECK(info_list.has_value());
+    std::map<std::string_view, const apex::ApexInfo*> apex_infos;
+    for (const apex::ApexInfo& info : info_list->getApexInfo()) {
+      if (info.getIsActive()) {
+        apex_infos.emplace(info.getModuleName(), &info);
+      }
+    }
+    for (const std::string_view& str : bcp_apexes) {
+      auto info = apex_infos.find(str);
+      if (info == apex_infos.end() || info->second->getIsFactory()) {
+        result += '/';
+      } else {
+        // In case lastUpdateMillis field is populated in apex-info-list.xml, we
+        // prefer to use it as version scheme. If the field is missing we
+        // fallback to the version code of the APEX.
+        uint64_t version = info->second->hasLastUpdateMillis()
+            ? info->second->getLastUpdateMillis()
+            : info->second->getVersionCode();
+        android::base::StringAppendF(&result, "/%" PRIu64, version);
+      }
+    }
+#endif
+  }
+  apex_versions_ = result;
+}
+
+void Runtime::ReloadAllFlags(const std::string& caller) {
+  FlagBase::ReloadAllFlags(caller);
+}
+
 bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
   // (b/30160149): protect subprocesses from modifications to LD_LIBRARY_PATH, etc.
   // Take a snapshot of the environment at the time the runtime was created, for use by Exec, etc.
@@ -1191,7 +1335,16 @@
   using Opt = RuntimeArgumentMap;
   Opt runtime_options(std::move(runtime_options_in));
   ScopedTrace trace(__FUNCTION__);
-  CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
+  CHECK_EQ(static_cast<size_t>(sysconf(_SC_PAGE_SIZE)), kPageSize);
+
+  // Reload all the flags value (from system properties and device configs).
+  ReloadAllFlags(__FUNCTION__);
+
+  deny_art_apex_data_files_ = runtime_options.Exists(Opt::DenyArtApexDataFiles);
+  if (deny_art_apex_data_files_) {
+    // We will run slower without those files if the system has taken an ART APEX update.
+    LOG(WARNING) << "ART APEX data files are untrusted.";
+  }
 
   // Early override for logging output.
   if (runtime_options.Exists(Opt::UseStderrLogger)) {
@@ -1201,7 +1354,9 @@
   MemMap::Init();
 
   verifier_missing_kthrow_fatal_ = runtime_options.GetOrDefault(Opt::VerifierMissingKThrowFatal);
+  force_java_zygote_fork_loop_ = runtime_options.GetOrDefault(Opt::ForceJavaZygoteForkLoop);
   perfetto_hprof_enabled_ = runtime_options.GetOrDefault(Opt::PerfettoHprof);
+  perfetto_javaheapprof_enabled_ = runtime_options.GetOrDefault(Opt::PerfettoJavaHeapStackProf);
 
   // Try to reserve a dedicated fault page. This is allocated for clobbered registers and sentinels.
   // If we cannot reserve it, log a warning.
@@ -1255,7 +1410,21 @@
     }
     std::string system_oat_filename = ImageHeader::GetOatLocationFromImageLocation(
         GetSystemImageFilename(image_location_.c_str(), instruction_set_));
-    std::string system_oat_location = ImageHeader::GetOatLocationFromImageLocation(image_location_);
+    std::string system_oat_location = ImageHeader::GetOatLocationFromImageLocation(
+        image_location_);
+
+    if (deny_art_apex_data_files_ && (LocationIsOnArtApexData(system_oat_filename) ||
+                                      LocationIsOnArtApexData(system_oat_location))) {
+      // This code path exists for completeness, but we don't expect it to be hit.
+      //
+      // `deny_art_apex_data_files` defaults to false unless set at the command-line. The image
+      // locations come from the -Ximage argument and it would need to be specified as being on
+      // the ART APEX data directory. This combination of flags would say apexdata is compromised,
+      // use apexdata to load image files, which is obviously not a good idea.
+      LOG(ERROR) << "Could not open boot oat file from untrusted location: " << system_oat_filename;
+      return false;
+    }
+
     std::string error_msg;
     std::unique_ptr<OatFile> oat_file(OatFile::Open(/*zip_fd=*/ -1,
                                                     system_oat_filename,
@@ -1314,8 +1483,19 @@
   thread_list_ = new ThreadList(runtime_options.GetOrDefault(Opt::ThreadSuspendTimeout));
   intern_table_ = new InternTable;
 
+  monitor_timeout_enable_ = runtime_options.GetOrDefault(Opt::MonitorTimeoutEnable);
+  int monitor_timeout_ms = runtime_options.GetOrDefault(Opt::MonitorTimeout);
+  if (monitor_timeout_ms < Monitor::kMonitorTimeoutMinMs) {
+    LOG(WARNING) << "Monitor timeout too short: Increasing";
+    monitor_timeout_ms = Monitor::kMonitorTimeoutMinMs;
+  }
+  if (monitor_timeout_ms >= Monitor::kMonitorTimeoutMaxMs) {
+    LOG(WARNING) << "Monitor timeout too long: Decreasing";
+    monitor_timeout_ms = Monitor::kMonitorTimeoutMaxMs - 1;
+  }
+  monitor_timeout_ns_ = MsToNs(monitor_timeout_ms);
+
   verify_ = runtime_options.GetOrDefault(Opt::Verify);
-  allow_dex_file_fallback_ = !runtime_options.Exists(Opt::NoDexFileFallback);
 
   target_sdk_version_ = runtime_options.GetOrDefault(Opt::TargetSdkVersion);
 
@@ -1350,6 +1530,9 @@
   experimental_flags_ = runtime_options.GetOrDefault(Opt::Experimental);
   is_low_memory_mode_ = runtime_options.Exists(Opt::LowMemoryMode);
   madvise_random_access_ = runtime_options.GetOrDefault(Opt::MadviseRandomAccess);
+  madvise_willneed_vdex_filesize_ = runtime_options.GetOrDefault(Opt::MadviseWillNeedVdexFileSize);
+  madvise_willneed_odex_filesize_ = runtime_options.GetOrDefault(Opt::MadviseWillNeedOdexFileSize);
+  madvise_willneed_art_filesize_ = runtime_options.GetOrDefault(Opt::MadviseWillNeedArtFileSize);
 
   jni_ids_indirection_ = runtime_options.GetOrDefault(Opt::OpaqueJniIds);
   automatically_set_jni_ids_indirection_ =
@@ -1376,8 +1559,6 @@
   // Generational CC collection is currently only compatible with Baker read barriers.
   bool use_generational_cc = kUseBakerReadBarrier && xgc_option.generational_cc;
 
-  image_space_loading_order_ = runtime_options.GetOrDefault(Opt::ImageSpaceLoadingOrder);
-
   heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),
                        runtime_options.GetOrDefault(Opt::HeapGrowthLimit),
                        runtime_options.GetOrDefault(Opt::HeapMinFree),
@@ -1403,6 +1584,7 @@
                        runtime_options.GetOrDefault(Opt::LongPauseLogThreshold),
                        runtime_options.GetOrDefault(Opt::LongGCLogThreshold),
                        runtime_options.Exists(Opt::IgnoreMaxFootprint),
+                       runtime_options.GetOrDefault(Opt::AlwaysLogExplicitGcs),
                        runtime_options.GetOrDefault(Opt::UseTLAB),
                        xgc_option.verify_pre_gc_heap_,
                        xgc_option.verify_pre_sweeping_heap_,
@@ -1416,16 +1598,11 @@
                        use_generational_cc,
                        runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs),
                        runtime_options.Exists(Opt::DumpRegionInfoBeforeGC),
-                       runtime_options.Exists(Opt::DumpRegionInfoAfterGC),
-                       image_space_loading_order_);
-
-  if (!heap_->HasBootImageSpace() && !allow_dex_file_fallback_) {
-    LOG(ERROR) << "Dex file fallback disabled, cannot continue without image.";
-    return false;
-  }
+                       runtime_options.Exists(Opt::DumpRegionInfoAfterGC));
 
   dump_gc_performance_on_shutdown_ = runtime_options.Exists(Opt::DumpGCPerformanceOnShutdown);
 
+  bool has_explicit_jdwp_options = runtime_options.Get(Opt::JdwpOptions) != nullptr;
   jdwp_options_ = runtime_options.GetOrDefault(Opt::JdwpOptions);
   jdwp_provider_ = CanonicalizeJdwpProvider(runtime_options.GetOrDefault(Opt::JdwpProvider),
                                             IsJavaDebuggable());
@@ -1436,11 +1613,13 @@
         bool has_transport = jdwp_options_.find("transport") != std::string::npos;
         std::string adb_connection_args =
             std::string("  -XjdwpProvider:adbconnection -XjdwpOptions:") + jdwp_options_;
-        LOG(WARNING) << "Jdwp options given when jdwp is disabled! You probably want to enable "
-                     << "jdwp with one of:" << std::endl
-                     << "  -Xplugin:libopenjdkjvmti" << (kIsDebugBuild ? "d" : "") << ".so "
-                     << "-agentpath:libjdwp.so=" << jdwp_options_ << std::endl
-                     << (has_transport ? "" : adb_connection_args);
+        if (has_explicit_jdwp_options) {
+          LOG(WARNING) << "Jdwp options given when jdwp is disabled! You probably want to enable "
+                      << "jdwp with one of:" << std::endl
+                      << "  -Xplugin:libopenjdkjvmti" << (kIsDebugBuild ? "d" : "") << ".so "
+                      << "-agentpath:libjdwp.so=" << jdwp_options_ << std::endl
+                      << (has_transport ? "" : adb_connection_args);
+        }
       }
       break;
     }
@@ -1586,10 +1765,13 @@
         GetInternTable()->AddImageStringsToTable(image_space, VoidFunctor());
       }
     }
-    if (heap_->GetBootImageSpaces().size() != GetBootClassPath().size()) {
+
+    const size_t total_components = gc::space::ImageSpace::GetNumberOfComponents(
+        ArrayRef<gc::space::ImageSpace* const>(heap_->GetBootImageSpaces()));
+    if (total_components != GetBootClassPath().size()) {
       // The boot image did not contain all boot class path components. Load the rest.
-      DCHECK_LT(heap_->GetBootImageSpaces().size(), GetBootClassPath().size());
-      size_t start = heap_->GetBootImageSpaces().size();
+      CHECK_LT(total_components, GetBootClassPath().size());
+      size_t start = total_components;
       DCHECK_LT(start, GetBootClassPath().size());
       std::vector<std::unique_ptr<const DexFile>> extra_boot_class_path;
       if (runtime_options.Exists(Opt::BootClassPathDexList)) {
@@ -1632,6 +1814,16 @@
     }
   }
 
+  // Now that the boot image space is set, cache the boot classpath checksums,
+  // to be used when validating oat files.
+  ArrayRef<gc::space::ImageSpace* const> image_spaces(GetHeap()->GetBootImageSpaces());
+  ArrayRef<const DexFile* const> bcp_dex_files(GetClassLinker()->GetBootClassPath());
+  boot_class_path_checksums_ = gc::space::ImageSpace::GetBootClassPathChecksums(image_spaces,
+                                                                                bcp_dex_files);
+
+  // Cache the apex versions.
+  InitializeApexVersions();
+
   CHECK(class_linker_ != nullptr);
 
   verifier::ClassVerifier::Init(class_linker_);
@@ -1708,6 +1900,8 @@
   // Class-roots are setup, we can now finish initializing the JniIdManager.
   GetJniIdManager()->Init(self);
 
+  InitMetrics();
+
   // Runtime initialization is largely done now.
   // We load plugins first since that can modify the runtime state slightly.
   // Load all plugins
@@ -1790,7 +1984,7 @@
 
   if (IsZygote() && IsPerfettoHprofEnabled()) {
     constexpr const char* plugin_name = kIsDebugBuild ?
-    "libperfetto_hprofd.so" : "libperfetto_hprof.so";
+        "libperfetto_hprofd.so" : "libperfetto_hprof.so";
     // Load eagerly in Zygote to improve app startup times. This will make
     // subsequent dlopens for the library no-ops.
     dlopen(plugin_name, RTLD_NOW | RTLD_LOCAL);
@@ -1798,14 +1992,25 @@
 
   VLOG(startup) << "Runtime::Init exiting";
 
-  // Set OnlyUseSystemOatFiles only after boot classpath has been set up.
-  if (runtime_options.Exists(Opt::OnlyUseSystemOatFiles)) {
-    oat_file_manager_->SetOnlyUseSystemOatFiles();
+  // Set OnlyUseTrustedOatFiles only after the boot classpath has been set up.
+  if (runtime_options.Exists(Opt::OnlyUseTrustedOatFiles)) {
+    oat_file_manager_->SetOnlyUseTrustedOatFiles();
   }
 
   return true;
 }
 
+void Runtime::InitMetrics() {
+  metrics::ReportingConfig metrics_config = metrics::ReportingConfig::FromFlags();
+  metrics_reporter_ = metrics::MetricsReporter::Create(metrics_config, this);
+}
+
+void Runtime::RequestMetricsReport(bool synchronous) {
+  if (metrics_reporter_) {
+    metrics_reporter_->RequestMetricsReport(synchronous);
+  }
+}
+
 bool Runtime::EnsurePluginLoaded(const char* plugin_name, std::string* error_msg) {
   // Is the plugin already loaded?
   for (const Plugin& p : plugins_) {
@@ -1893,6 +2098,10 @@
   // a regular JNI libraries with a regular JNI_OnLoad. Most JNI libraries can
   // just use System.loadLibrary, but libcore can't because it's the library
   // that implements System.loadLibrary!
+  //
+  // By setting calling class to java.lang.Object, the caller location for these
+  // JNI libs is core-oj.jar in the ART APEX, and hence they are loaded from the
+  // com_android_art linker namespace.
 
   // libicu_jni has to be initialized before libopenjdk{d} due to runtime dependency from
   // libopenjdk{d} to Icu4cMetadata native methods in libicu_jni. See http://b/143888405
@@ -2023,6 +2232,7 @@
   }
   DumpDeoptimizations(os);
   TrackedAllocators::Dump(os);
+  GetMetrics()->DumpForSigQuit(os);
   os << "\n";
 
   thread_list_->DumpForSigQuit(os);
@@ -2307,8 +2517,10 @@
   if (IsAotCompiler()) {
     PointerSize pointer_size = GetInstructionSetPointerSize(instruction_set_);
     method->SetEntryPointFromQuickCompiledCodePtrSize(nullptr, pointer_size);
+    method->SetEntryPointFromJniPtrSize(nullptr, pointer_size);
   } else {
     method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionStub());
+    method->SetEntryPointFromJni(GetJniDlsymLookupCriticalStub());
   }
   return method;
 }
@@ -2406,8 +2618,22 @@
   }
 }
 
-void Runtime::RegisterAppInfo(const std::vector<std::string>& code_paths,
-                              const std::string& profile_output_filename) {
+void Runtime::RegisterAppInfo(const std::string& package_name,
+                              const std::vector<std::string>& code_paths,
+                              const std::string& profile_output_filename,
+                              const std::string& ref_profile_filename,
+                              int32_t code_type) {
+  app_info_.RegisterAppInfo(
+      package_name,
+      code_paths,
+      profile_output_filename,
+      ref_profile_filename,
+      AppInfo::FromVMRuntimeConstants(code_type));
+
+  if (metrics_reporter_ != nullptr) {
+    metrics_reporter_->NotifyAppInfoUpdated(&app_info_);
+  }
+
   if (jit_.get() == nullptr) {
     // We are not JITing. Nothing to do.
     return;
@@ -2415,6 +2641,7 @@
 
   VLOG(profiler) << "Register app with " << profile_output_filename
       << " " << android::base::Join(code_paths, ':');
+  VLOG(profiler) << "Reference profile is: " << ref_profile_filename;
 
   if (profile_output_filename.empty()) {
     LOG(WARNING) << "JIT profile information will not be recorded: profile filename is empty.";
@@ -2429,7 +2656,7 @@
     return;
   }
 
-  jit_->StartProfileSaver(profile_output_filename, code_paths);
+  jit_->StartProfileSaver(profile_output_filename, code_paths, ref_profile_filename);
 }
 
 // Transaction support.
@@ -2884,27 +3111,6 @@
       jit->GetCodeCache()->TransitionToDebuggable();
     }
   }
-  // Also de-quicken all -quick opcodes. We do this for both BCP and non-bcp so if we are swapping
-  // debuggable during startup by a plugin (eg JVMTI) even non-BCP code has its vdex files deopted.
-  std::unordered_set<const VdexFile*> vdexs;
-  GetClassLinker()->VisitKnownDexFiles(Thread::Current(), [&](const art::DexFile* df) {
-    const OatDexFile* odf = df->GetOatDexFile();
-    if (odf == nullptr) {
-      return;
-    }
-    const OatFile* of = odf->GetOatFile();
-    if (of == nullptr || of->IsDebuggable()) {
-      // no Oat or already debuggable so no -quick.
-      return;
-    }
-    vdexs.insert(of->GetVdexFile());
-  });
-  LOG(INFO) << "Unquickening " << vdexs.size() << " vdex files!";
-  for (const VdexFile* vf : vdexs) {
-    vf->AllowWriting(true);
-    vf->UnquickenInPlace(/*decompile_return_instruction=*/true);
-    vf->AllowWriting(false);
-  }
 }
 
 Runtime::ScopedThreadPoolUsage::ScopedThreadPoolUsage()
@@ -2961,14 +3167,6 @@
     {
       ScopedTrace trace("Releasing app image spaces metadata");
       ScopedObjectAccess soa(Thread::Current());
-      for (gc::space::ContinuousSpace* space : runtime->GetHeap()->GetContinuousSpaces()) {
-        if (space->IsImageSpace()) {
-          gc::space::ImageSpace* image_space = space->AsImageSpace();
-          if (image_space->GetImageHeader().IsAppImage()) {
-            image_space->DisablePreResolvedStrings();
-          }
-        }
-      }
       // Request empty checkpoints to make sure no threads are accessing the image space metadata
       // section when we madvise it. Use GC exclusion to prevent deadlocks that may happen if
       // multiple threads are attempting to run empty checkpoints at the same time.
@@ -3007,6 +3205,8 @@
     return;
   }
 
+  VLOG(startup) << app_info_;
+
   VLOG(startup) << "Adding NotifyStartupCompleted task";
   // Use the heap task processor since we want to be exclusive with the GC and we don't want to
   // block the caller if the GC is running.
@@ -3016,6 +3216,16 @@
 
   // Notify the profiler saver that startup is now completed.
   ProfileSaver::NotifyStartupCompleted();
+
+  if (metrics_reporter_ != nullptr) {
+    metrics_reporter_->NotifyStartupCompleted();
+  }
+}
+
+void Runtime::NotifyDexFileLoaded() {
+  if (metrics_reporter_ != nullptr) {
+    metrics_reporter_->NotifyAppInfoUpdated(&app_info_);
+  }
 }
 
 bool Runtime::GetStartupCompleted() const {
@@ -3065,4 +3275,50 @@
   }
 }
 
+void Runtime::MadviseFileForRange(size_t madvise_size_limit_bytes,
+                                  size_t map_size_bytes,
+                                  const uint8_t* map_begin,
+                                  const uint8_t* map_end,
+                                  const std::string& file_name) {
+  // Ideal blockTransferSize for madvising files (128KiB)
+  static constexpr size_t kIdealIoTransferSizeBytes = 128*1024;
+
+  size_t target_size_bytes = std::min<size_t>(map_size_bytes, madvise_size_limit_bytes);
+
+  if (target_size_bytes > 0) {
+    ScopedTrace madvising_trace("madvising "
+                                + file_name
+                                + " size="
+                                + std::to_string(target_size_bytes));
+
+    // Based on requested size (target_size_bytes)
+    const uint8_t* target_pos = map_begin + target_size_bytes;
+
+    // Clamp endOfFile if its past map_end
+    if (target_pos > map_end) {
+        target_pos = map_end;
+    }
+
+    // Madvise the whole file up to target_pos in chunks of
+    // kIdealIoTransferSizeBytes (to MADV_WILLNEED)
+    // Note:
+    // madvise(MADV_WILLNEED) will prefetch max(fd readahead size, optimal
+    // block size for device) per call, hence the need for chunks. (128KB is a
+    // good default.)
+    for (const uint8_t* madvise_start = map_begin;
+         madvise_start < target_pos;
+         madvise_start += kIdealIoTransferSizeBytes) {
+      void* madvise_addr = const_cast<void*>(reinterpret_cast<const void*>(madvise_start));
+      size_t madvise_length = std::min(kIdealIoTransferSizeBytes,
+                                       static_cast<size_t>(target_pos - madvise_start));
+      int status = madvise(madvise_addr, madvise_length, MADV_WILLNEED);
+      // In case of error we stop madvising rest of the file
+      if (status < 0) {
+        LOG(ERROR) << "Failed to madvise file:" << file_name << " for size:" << map_size_bytes;
+        break;
+      }
+    }
+  }
+}
+
 }  // namespace art
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 822c0ac..68456cd 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -21,25 +21,28 @@
 #include <stdio.h>
 
 #include <iosfwd>
+#include <memory>
 #include <set>
 #include <string>
 #include <utility>
-#include <memory>
 #include <vector>
 
+#include "app_info.h"
 #include "base/locks.h"
 #include "base/macros.h"
 #include "base/mem_map.h"
+#include "base/metrics/metrics.h"
 #include "base/string_view_cpp20.h"
+#include "compat_framework.h"
 #include "deoptimization_kind.h"
 #include "dex/dex_file_types.h"
 #include "experimental_flags.h"
-#include "gc/space/image_space_loading_order.h"
 #include "gc_root.h"
 #include "instrumentation.h"
 #include "jdwp_provider.h"
 #include "jni/jni_id_manager.h"
 #include "jni_id_type.h"
+#include "metrics/reporter.h"
 #include "obj_ptr.h"
 #include "offsets.h"
 #include "process_state.h"
@@ -284,6 +287,12 @@
     return boot_class_path_locations_.empty() ? boot_class_path_ : boot_class_path_locations_;
   }
 
+  // Returns the checksums for the boot image, extensions and extra boot class path dex files,
+  // based on the image spaces and boot class path dex files loaded in memory.
+  const std::string& GetBootClassPathChecksums() const {
+    return boot_class_path_checksums_;
+  }
+
   const std::string& GetClassPathString() const {
     return class_path_string_;
   }
@@ -522,8 +531,11 @@
     return &instrumentation_;
   }
 
-  void RegisterAppInfo(const std::vector<std::string>& code_paths,
-                       const std::string& profile_output_filename);
+  void RegisterAppInfo(const std::string& package_name,
+                       const std::vector<std::string>& code_paths,
+                       const std::string& profile_output_filename,
+                       const std::string& ref_profile_filename,
+                       int32_t code_type);
 
   // Transaction support.
   bool IsActiveTransaction() const;
@@ -656,10 +668,6 @@
     }
   }
 
-  bool IsDexFileFallbackEnabled() const {
-    return allow_dex_file_fallback_;
-  }
-
   const std::vector<std::string>& GetCpuAbilist() const {
     return cpu_abilist_;
   }
@@ -676,17 +684,8 @@
     return target_sdk_version_;
   }
 
-  void SetDisabledCompatChanges(const std::set<uint64_t>& disabled_changes) {
-    disabled_compat_changes_ = disabled_changes;
-  }
-
-  std::set<uint64_t> GetDisabledCompatChanges() const {
-    return disabled_compat_changes_;
-  }
-
-  bool isChangeEnabled(uint64_t change_id) const {
-    // TODO(145743810): add an up call to java to log to statsd
-    return disabled_compat_changes_.count(change_id) == 0;
+  CompatFramework& GetCompatFramework() {
+    return compat_framework_;
   }
 
   uint32_t GetZygoteMaxFailedBoots() const {
@@ -734,6 +733,14 @@
     return is_profileable_from_shell_;
   }
 
+  void SetProfileable(bool value) {
+    is_profileable_ = value;
+  }
+
+  bool IsProfileable() const {
+    return is_profileable_;
+  }
+
   void SetJavaDebuggable(bool value);
 
   // Deoptimize the boot image, called for Java debuggable apps.
@@ -824,14 +831,6 @@
     return dump_native_stack_on_sig_quit_;
   }
 
-  bool GetPrunedDalvikCache() const {
-    return pruned_dalvik_cache_;
-  }
-
-  void SetPrunedDalvikCache(bool pruned) {
-    pruned_dalvik_cache_ = pruned;
-  }
-
   void UpdateProcessState(ProcessState process_state);
 
   // Returns true if we currently care about long mutator pause.
@@ -897,12 +896,28 @@
     return result;
   }
 
+  bool DenyArtApexDataFiles() const {
+    return deny_art_apex_data_files_;
+  }
+
   // Whether or not we use MADV_RANDOM on files that are thought to have random access patterns.
   // This is beneficial for low RAM devices since it reduces page cache thrashing.
   bool MAdviseRandomAccess() const {
     return madvise_random_access_;
   }
 
+  size_t GetMadviseWillNeedSizeVdex() const {
+    return madvise_willneed_vdex_filesize_;
+  }
+
+  size_t GetMadviseWillNeedSizeOdex() const {
+    return madvise_willneed_odex_filesize_;
+  }
+
+  size_t GetMadviseWillNeedSizeArt() const {
+    return madvise_willneed_art_filesize_;
+  }
+
   const std::string& GetJdwpOptions() {
     return jdwp_options_;
   }
@@ -965,24 +980,66 @@
   // first call.
   void NotifyStartupCompleted();
 
+  // Notify the runtime that the application finished loading some dex/odex files. This is
+  // called everytime we load a set of dex files in a class loader.
+  void NotifyDexFileLoaded();
+
   // Return true if startup is already completed.
   bool GetStartupCompleted() const;
 
-  gc::space::ImageSpaceLoadingOrder GetImageSpaceLoadingOrder() const {
-    return image_space_loading_order_;
-  }
-
   bool IsVerifierMissingKThrowFatal() const {
     return verifier_missing_kthrow_fatal_;
   }
 
+  bool IsJavaZygoteForkLoopRequired() const {
+    return force_java_zygote_fork_loop_;
+  }
+
   bool IsPerfettoHprofEnabled() const {
     return perfetto_hprof_enabled_;
   }
 
+  bool IsPerfettoJavaHeapStackProfEnabled() const {
+    return perfetto_javaheapprof_enabled_;
+  }
+
+  bool IsMonitorTimeoutEnabled() const {
+    return monitor_timeout_enable_;
+  }
+
+  uint64_t GetMonitorTimeoutNs() const {
+    return monitor_timeout_ns_;
+  }
   // Return true if we should load oat files as executable or not.
   bool GetOatFilesExecutable() const;
 
+  metrics::ArtMetrics* GetMetrics() { return &metrics_; }
+
+  AppInfo* GetAppInfo() { return &app_info_; }
+
+  void RequestMetricsReport(bool synchronous = true);
+
+  static void MadviseFileForRange(size_t madvise_size_limit_bytes,
+                                  size_t map_size_bytes,
+                                  const uint8_t* map_begin,
+                                  const uint8_t* map_end,
+                                  const std::string& file_name);
+
+  const std::string& GetApexVersions() const {
+    return apex_versions_;
+  }
+
+  // Trigger a flag reload from system properties or device congfigs.
+  //
+  // Should only be called from runtime init and zygote post fork as
+  // we don't want to change the runtime config midway during execution.
+  //
+  // The caller argument should be the name of the function making this call
+  // and will be used to enforce the appropriate names.
+  //
+  // See Flags::ReloadAllFlags as well.
+  static void ReloadAllFlags(const std::string& caller);
+
  private:
   static void InitPlatformSignalHandlers();
 
@@ -994,6 +1051,7 @@
       SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
   void InitNativeMethods() REQUIRES(!Locks::mutator_lock_);
   void RegisterRuntimeNativeMethods(JNIEnv* env);
+  void InitMetrics();
 
   void StartDaemonThreads();
   void StartSignalCatcher();
@@ -1022,6 +1080,10 @@
   ThreadPool* AcquireThreadPool() REQUIRES(!Locks::runtime_thread_pool_lock_);
   void ReleaseThreadPool() REQUIRES(!Locks::runtime_thread_pool_lock_);
 
+  // Parses /apex/apex-info-list.xml to initialize a string containing versions
+  // of boot classpath jars and encoded into .oat files.
+  void InitializeApexVersions();
+
   // A pointer to the active runtime or null.
   static Runtime* instance_;
 
@@ -1066,6 +1128,7 @@
 
   std::vector<std::string> boot_class_path_;
   std::vector<std::string> boot_class_path_locations_;
+  std::string boot_class_path_checksums_;
   std::string class_path_string_;
   std::vector<std::string> properties_;
 
@@ -1172,18 +1235,14 @@
   // If kNone, verification is disabled. kEnable by default.
   verifier::VerifyMode verify_;
 
-  // If true, the runtime may use dex files directly with the interpreter if an oat file is not
-  // available/usable.
-  bool allow_dex_file_fallback_;
-
   // List of supported cpu abis.
   std::vector<std::string> cpu_abilist_;
 
   // Specifies target SDK version to allow workarounds for certain API levels.
   uint32_t target_sdk_version_;
 
-  // A set of disabled compat changes for the running app, all other changes are enabled.
-  std::set<uint64_t> disabled_compat_changes_;
+  // ART counterpart for the compat framework (go/compat-framework).
+  CompatFramework compat_framework_;
 
   // Implicit checks flags.
   bool implicit_null_checks_;       // NullPointer checks are implicit.
@@ -1223,8 +1282,17 @@
   // Whether Java code needs to be debuggable.
   bool is_java_debuggable_;
 
+  bool monitor_timeout_enable_;
+  uint64_t monitor_timeout_ns_;
+
+  // Whether or not this application can be profiled by the shell user,
+  // even when running on a device that is running in user mode.
   bool is_profileable_from_shell_ = false;
 
+  // Whether or not this application can be profiled by system services on a
+  // device running in user mode, but not necessarily by the shell user.
+  bool is_profileable_ = false;
+
   // The maximum number of failed boots we allow before pruning the dalvik cache
   // and trying again. This option is only inspected when we're running as a
   // zygote.
@@ -1249,6 +1317,18 @@
   // This is beneficial for low RAM devices since it reduces page cache thrashing.
   bool madvise_random_access_;
 
+  // Limiting size (in bytes) for applying MADV_WILLNEED on vdex files
+  // A 0 for this will turn off madvising to MADV_WILLNEED
+  size_t madvise_willneed_vdex_filesize_;
+
+  // Limiting size (in bytes) for applying MADV_WILLNEED on odex files
+  // A 0 for this will turn off madvising to MADV_WILLNEED
+  size_t madvise_willneed_odex_filesize_;
+
+  // Limiting size (in bytes) for applying MADV_WILLNEED on art files
+  // A 0 for this will turn off madvising to MADV_WILLNEED
+  size_t madvise_willneed_art_filesize_;
+
   // Whether the application should run in safe mode, that is, interpreter only.
   bool safe_mode_;
 
@@ -1282,9 +1362,6 @@
   // Whether threads should dump their native stack on SIGQUIT.
   bool dump_native_stack_on_sig_quit_;
 
-  // Whether the dalvik cache was pruned when initializing the runtime.
-  bool pruned_dalvik_cache_;
-
   // Whether or not we currently care about pause times.
   ProcessState process_state_;
 
@@ -1305,6 +1382,9 @@
   // indirection is changed. This is intended only for testing JNI id swapping.
   bool automatically_set_jni_ids_indirection_;
 
+  // True if files in /data/misc/apexdata/com.android.art are considered untrustworthy.
+  bool deny_art_apex_data_files_;
+
   // Saved environment.
   class EnvSnapshot {
    public:
@@ -1336,11 +1416,24 @@
   // If startup has completed, must happen at most once.
   std::atomic<bool> startup_completed_ = false;
 
-  gc::space::ImageSpaceLoadingOrder image_space_loading_order_ =
-      gc::space::ImageSpaceLoadingOrder::kSystemFirst;
-
   bool verifier_missing_kthrow_fatal_;
+  bool force_java_zygote_fork_loop_;
   bool perfetto_hprof_enabled_;
+  bool perfetto_javaheapprof_enabled_;
+
+  metrics::ArtMetrics metrics_;
+  std::unique_ptr<metrics::MetricsReporter> metrics_reporter_;
+
+  // Apex versions of boot classpath jars concatenated in a string. The format
+  // is of the type:
+  // '/apex1_version/apex2_version//'
+  //
+  // When the apex is the factory version, we don't encode it (for example in
+  // the third entry in the example above).
+  std::string apex_versions_;
+
+  // The info about the application code paths.
+  AppInfo app_info_;
 
   // Note: See comments on GetFaultMessage.
   friend std::string GetFaultMessageForAbortLogging();
@@ -1352,6 +1445,8 @@
   DISALLOW_COPY_AND_ASSIGN(Runtime);
 };
 
+inline metrics::ArtMetrics* GetMetrics() { return Runtime::Current()->GetMetrics(); }
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_RUNTIME_H_
diff --git a/runtime/runtime_callbacks_test.cc b/runtime/runtime_callbacks_test.cc
index 4a60c04..e49deae 100644
--- a/runtime/runtime_callbacks_test.cc
+++ b/runtime/runtime_callbacks_test.cc
@@ -118,6 +118,10 @@
 
   struct Callback : public ThreadLifecycleCallback {
     void ThreadStart(Thread* self) override {
+      {
+        ScopedObjectAccess soa(self);
+        LOG(DEBUG) << "ThreadStart callback for thread: " << self->GetThreadName();
+      }
       if (state == CallbackState::kBase) {
         state = CallbackState::kStarted;
         stored_self = self;
@@ -127,6 +131,10 @@
     }
 
     void ThreadDeath(Thread* self) override {
+      {
+        ScopedObjectAccess soa(self);
+        LOG(DEBUG) << "ThreadDeath callback for thread: " << self->GetThreadName();
+      }
       if (state == CallbackState::kStarted && self == stored_self) {
         state = CallbackState::kDied;
       } else {
@@ -150,6 +158,10 @@
   // Make sure the workers are done starting so we don't get callbacks for them.
   runtime_->WaitForThreadPoolWorkersToStart();
 
+  // The metrics reporting thread will sometimes be slow to start. Synchronously requesting a
+  // metrics report forces us to wait until the thread has started.
+  runtime_->RequestMetricsReport(/*synchronous=*/true);
+
   cb_.state = CallbackState::kBase;  // Ignore main thread attach.
 
   {
@@ -187,7 +199,7 @@
   env->CallVoidMethod(thread.get(), join_id);
   ASSERT_FALSE(env->ExceptionCheck());
 
-  EXPECT_TRUE(cb_.state == CallbackState::kDied) << static_cast<int>(cb_.state);
+  EXPECT_EQ(cb_.state, CallbackState::kDied);
 }
 
 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackAttach) {
@@ -300,8 +312,8 @@
       hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_y, class_loader)));
   ASSERT_TRUE(h_Y != nullptr);
 
-  bool expect1 = Expect({ "PreDefine:LY; <art-gtest-XandY.jar>",
-                          "PreDefine:LX; <art-gtest-XandY.jar>",
+  bool expect1 = Expect({ "PreDefine:LY; <art-gtest-jars-XandY.jar>",
+                          "PreDefine:LX; <art-gtest-jars-XandY.jar>",
                           "Load:LX;",
                           "Prepare:LX;[LX;]",
                           "Load:LY;",
@@ -312,7 +324,7 @@
 
   ASSERT_TRUE(class_linker_->EnsureInitialized(Thread::Current(), h_Y, true, true));
 
-  bool expect2 = Expect({ "PreDefine:LY$Z; <art-gtest-XandY.jar>",
+  bool expect2 = Expect({ "PreDefine:LY$Z; <art-gtest-jars-XandY.jar>",
                           "Load:LY$Z;",
                           "Prepare:LY$Z;[LY$Z;]" });
   EXPECT_TRUE(expect2);
diff --git a/runtime/runtime_intrinsics.cc b/runtime/runtime_intrinsics.cc
index 3295a86..1672c49 100644
--- a/runtime/runtime_intrinsics.cc
+++ b/runtime/runtime_intrinsics.cc
@@ -20,6 +20,7 @@
 #include "class_linker.h"
 #include "dex/invoke_type.h"
 #include "intrinsics_enum.h"
+#include "intrinsics_list.h"
 #include "mirror/class.h"
 #include "runtime.h"
 #include "scoped_thread_state_change-inl.h"
@@ -29,14 +30,10 @@
 
 namespace {
 
-// Initialize an intrinsic. Returns true if the intrinsic is already
-// initialized, false otherwise.
-bool InitializeIntrinsic(Thread* self,
-                         Intrinsics intrinsic,
-                         InvokeType invoke_type,
-                         const char* class_name,
-                         const char* method_name,
-                         const char* signature)
+ArtMethod* FindIntrinsicMethod(Thread* self,
+                               const char* class_name,
+                               const char* method_name,
+                               const char* signature)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   PointerSize image_size = class_linker->GetImagePointerSize();
@@ -50,6 +47,19 @@
     LOG(FATAL) << "Could not find method of intrinsic "
                << class_name << " " << method_name << " " << signature;
   }
+  return method;
+}
+
+// Initialize an intrinsic. Returns true if the intrinsic is already
+// initialized, false otherwise.
+bool InitializeIntrinsic(Thread* self,
+                         Intrinsics intrinsic,
+                         InvokeType invoke_type,
+                         const char* class_name,
+                         const char* method_name,
+                         const char* signature)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  ArtMethod* method = FindIntrinsicMethod(self, class_name, method_name, signature);
 
   CHECK_EQ(method->GetInvokeType(), invoke_type);
   if (method->IsIntrinsic()) {
@@ -61,24 +71,55 @@
   }
 }
 
+// Returns true if the intrinsic is already initialized, false otherwise.
+bool IsIntrinsicInitialized(Thread* self,
+                            Intrinsics intrinsic,
+                            InvokeType invoke_type,
+                            const char* class_name,
+                            const char* method_name,
+                            const char* signature)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  ArtMethod* method = FindIntrinsicMethod(self, class_name, method_name, signature);
+
+  CHECK_EQ(method->GetInvokeType(), invoke_type);
+  if (method->IsIntrinsic()) {
+    CHECK_EQ(method->GetIntrinsic(), static_cast<uint32_t>(intrinsic));
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool AreAllIntrinsicsInitialized() {
+  ScopedObjectAccess soa(Thread::Current());
+#define IS_INTRINSIC_INITIALIZED(Name, InvokeType, _, __, ___, ClassName, MethodName, Signature) \
+  IsIntrinsicInitialized(soa.Self(),                                                             \
+                         Intrinsics::k##Name,                                                    \
+                         InvokeType,                                                             \
+                         ClassName,                                                              \
+                         MethodName,                                                             \
+                         Signature) &&
+  bool result = INTRINSICS_LIST(IS_INTRINSIC_INITIALIZED) true;
+#undef IS_INTRINSIC_INITIALIZED
+  return result;
+}
+
 }  // namespace
 
 void InitializeIntrinsics() {
   ScopedObjectAccess soa(Thread::Current());
   // Initialization here uses the short-circuit operator || to stop
   // initializing if there's an already initialized intrinsic.
-#define SETUP_INTRINSICS(Name, InvokeType, _, __, ___, ClassName, MethodName, Signature) \
-  InitializeIntrinsic(soa.Self(),                                                        \
-                      Intrinsics::k##Name,                                               \
-                      InvokeType,                                                        \
-                      ClassName,                                                         \
-                      MethodName,                                                        \
+#define INITIALIZE_INTRINSIC(Name, InvokeType, _, __, ___, ClassName, MethodName, Signature) \
+  InitializeIntrinsic(soa.Self(),                                                            \
+                      Intrinsics::k##Name,                                                   \
+                      InvokeType,                                                            \
+                      ClassName,                                                             \
+                      MethodName,                                                            \
                       Signature) ||
-#include "intrinsics_list.h"
-  INTRINSICS_LIST(SETUP_INTRINSICS)
-#undef INTRINSICS_LIST
-#undef SETUP_INTRINSICS
-      true;
+  INTRINSICS_LIST(INITIALIZE_INTRINSIC) true;
+#undef INITIALIZE_INTRINSIC
+  DCHECK(AreAllIntrinsicsInitialized());
 }
 
 }  // namespace art
diff --git a/runtime/runtime_options.cc b/runtime/runtime_options.cc
index 12dab15..e21587a 100644
--- a/runtime/runtime_options.cc
+++ b/runtime/runtime_options.cc
@@ -18,6 +18,7 @@
 
 #include <memory>
 
+#include "base/fast_exit.h"
 #include "base/sdk_version.h"
 #include "base/utils.h"
 #include "debugger.h"
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index 5707a33..ddbbfec 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -44,7 +44,7 @@
 RUNTIME_OPTIONS_KEY (std::string,         Image)
 RUNTIME_OPTIONS_KEY (Unit,                CheckJni)
 RUNTIME_OPTIONS_KEY (Unit,                JniOptsForceCopy)
-RUNTIME_OPTIONS_KEY (std::string,         JdwpOptions, "")
+RUNTIME_OPTIONS_KEY (std::string,         JdwpOptions,                    "suspend=n,server=y")
 RUNTIME_OPTIONS_KEY (JdwpProvider,        JdwpProvider,                   JdwpProvider::kUnset)
 RUNTIME_OPTIONS_KEY (MemoryKiB,           MemoryMaximumSize,              gc::Heap::kDefaultMaximumSize)  // -Xmx
 RUNTIME_OPTIONS_KEY (MemoryKiB,           MemoryInitialSize,              gc::Heap::kDefaultInitialSize)  // -Xms
@@ -66,18 +66,24 @@
                                           LongGCLogThreshold,             gc::Heap::kDefaultLongGCLogThreshold)
 RUNTIME_OPTIONS_KEY (MillisecondsToNanoseconds, \
                                           ThreadSuspendTimeout,           ThreadList::kDefaultThreadSuspendTimeout)
+RUNTIME_OPTIONS_KEY (bool,                MonitorTimeoutEnable,           false)
+RUNTIME_OPTIONS_KEY (int,                 MonitorTimeout,                 Monitor::kDefaultMonitorTimeoutMs)
 RUNTIME_OPTIONS_KEY (Unit,                DumpGCPerformanceOnShutdown)
 RUNTIME_OPTIONS_KEY (Unit,                DumpRegionInfoBeforeGC)
 RUNTIME_OPTIONS_KEY (Unit,                DumpRegionInfoAfterGC)
 RUNTIME_OPTIONS_KEY (Unit,                DumpJITInfoOnShutdown)
 RUNTIME_OPTIONS_KEY (Unit,                IgnoreMaxFootprint)
+RUNTIME_OPTIONS_KEY (bool,                AlwaysLogExplicitGcs,           true)
 RUNTIME_OPTIONS_KEY (Unit,                LowMemoryMode)
 RUNTIME_OPTIONS_KEY (bool,                UseTLAB,                        (kUseTlab || kUseReadBarrier))
 RUNTIME_OPTIONS_KEY (bool,                EnableHSpaceCompactForOOM,      true)
 RUNTIME_OPTIONS_KEY (bool,                UseJitCompilation,              true)
-RUNTIME_OPTIONS_KEY (bool,                UseTieredJitCompilation,        interpreter::IsNterpSupported())
+RUNTIME_OPTIONS_KEY (bool,                UseProfiledJitCompilation,      false)
 RUNTIME_OPTIONS_KEY (bool,                DumpNativeStackOnSigQuit,       true)
 RUNTIME_OPTIONS_KEY (bool,                MadviseRandomAccess,            false)
+RUNTIME_OPTIONS_KEY (unsigned int,        MadviseWillNeedVdexFileSize,    0)
+RUNTIME_OPTIONS_KEY (unsigned int,        MadviseWillNeedOdexFileSize,    0)
+RUNTIME_OPTIONS_KEY (unsigned int,        MadviseWillNeedArtFileSize,     0)
 RUNTIME_OPTIONS_KEY (JniIdType,           OpaqueJniIds,                   JniIdType::kDefault)  // -Xopaque-jni-ids:{true, false, swapable}
 RUNTIME_OPTIONS_KEY (bool,                AutoPromoteOpaqueJniIds,        true)  // testing use only. -Xauto-promote-opaque-jni-ids:{true, false}
 RUNTIME_OPTIONS_KEY (unsigned int,        JITCompileThreshold)
@@ -86,6 +92,7 @@
 RUNTIME_OPTIONS_KEY (unsigned int,        JITPriorityThreadWeight)
 RUNTIME_OPTIONS_KEY (unsigned int,        JITInvokeTransitionWeight)
 RUNTIME_OPTIONS_KEY (int,                 JITPoolThreadPthreadPriority,   jit::kJitPoolThreadPthreadDefaultPriority)
+RUNTIME_OPTIONS_KEY (int,                 JITZygotePoolThreadPthreadPriority,   jit::kJitZygotePoolThreadPthreadDefaultPriority)
 RUNTIME_OPTIONS_KEY (MemoryKiB,           JITCodeCacheInitialCapacity,    jit::JitCodeCache::kInitialCapacity)
 RUNTIME_OPTIONS_KEY (MemoryKiB,           JITCodeCacheMaxCapacity,        jit::JitCodeCache::kMaxCapacity)
 RUNTIME_OPTIONS_KEY (MillisecondsToNanoseconds, \
@@ -133,7 +140,6 @@
                                           hiddenapi::EnforcementPolicy::kDisabled)
 RUNTIME_OPTIONS_KEY (std::string,         NativeBridge)
 RUNTIME_OPTIONS_KEY (unsigned int,        ZygoteMaxFailedBoots,           10)
-RUNTIME_OPTIONS_KEY (Unit,                NoDexFileFallback)
 RUNTIME_OPTIONS_KEY (std::string,         CpuAbiList)
 RUNTIME_OPTIONS_KEY (std::string,         Fingerprint)
 RUNTIME_OPTIONS_KEY (ExperimentalFlags,   Experimental,     ExperimentalFlags::kNone) // -Xexperimental:{...}
@@ -150,10 +156,10 @@
 RUNTIME_OPTIONS_KEY (bool (*)(),          HookIsSensitiveThread)
 RUNTIME_OPTIONS_KEY (int32_t (*)(FILE* stream, const char* format, va_list ap), \
                                           HookVfprintf,                   vfprintf)
-// Use _exit instead of exit so that we won't get DCHECK failures in global data
-// destructors. b/28106055.
+// Use `art::FastExit` instead of `exit` so that we won't get DCHECK failures
+// in global data destructors (see b/28106055).
 RUNTIME_OPTIONS_KEY (void (*)(int32_t status), \
-                                          HookExit,                       _exit)
+                                          HookExit,                       art::FastExit)
                                                                           // We don't call abort(3) by default; see
                                                                           // Runtime::Abort.
 RUNTIME_OPTIONS_KEY (void (*)(),          HookAbort,                      nullptr)
@@ -163,16 +169,17 @@
 RUNTIME_OPTIONS_KEY (unsigned int,        GlobalRefAllocStackTraceLimit,  0)  // 0 = off
 RUNTIME_OPTIONS_KEY (Unit,                UseStderrLogger)
 
-RUNTIME_OPTIONS_KEY (Unit,                OnlyUseSystemOatFiles)
+RUNTIME_OPTIONS_KEY (Unit,                OnlyUseTrustedOatFiles)
+RUNTIME_OPTIONS_KEY (Unit,                DenyArtApexDataFiles)
 RUNTIME_OPTIONS_KEY (unsigned int,        VerifierLoggingThreshold,       100)
 
-RUNTIME_OPTIONS_KEY (gc::space::ImageSpaceLoadingOrder, \
-                     ImageSpaceLoadingOrder, \
-                     gc::space::ImageSpaceLoadingOrder::kSystemFirst)
-
 RUNTIME_OPTIONS_KEY (bool,                FastClassNotFoundException,     true)
 RUNTIME_OPTIONS_KEY (bool,                VerifierMissingKThrowFatal,     true)
 
+// Setting this to true causes ART to disable Zygote native fork loop. ART also
+// internally enables this if ZygoteJit is enabled.
+RUNTIME_OPTIONS_KEY (bool,                ForceJavaZygoteForkLoop,        false)
+
 // Whether to allow loading of the perfetto hprof plugin.
 // Even with this option set, we will still only actually load the plugin
 // if we are on a userdebug build or the app is debuggable or profileable.
@@ -186,4 +193,7 @@
 // This is set to true in frameworks/base/core/jni/AndroidRuntime.cpp.
 RUNTIME_OPTIONS_KEY (bool,                PerfettoHprof,                  false)
 
+// This is to enable/disable Perfetto Java Heap Stack Profiling
+RUNTIME_OPTIONS_KEY (bool,                PerfettoJavaHeapStackProf,      false)
+
 #undef RUNTIME_OPTIONS_KEY
diff --git a/runtime/runtime_options.h b/runtime/runtime_options.h
index abc1fc0..8fec9ea 100644
--- a/runtime/runtime_options.h
+++ b/runtime/runtime_options.h
@@ -26,7 +26,6 @@
 #include "base/variant_map.h"
 #include "cmdline_types.h"  // TODO: don't need to include this file here
 #include "gc/collector_type.h"
-#include "gc/space/image_space_loading_order.h"
 #include "gc/space/large_object_space.h"
 #include "hidden_api.h"
 #include "jit/jit.h"
diff --git a/runtime/scoped_disable_public_sdk_checker.h b/runtime/scoped_disable_public_sdk_checker.h
new file mode 100644
index 0000000..4ec1af3
--- /dev/null
+++ b/runtime/scoped_disable_public_sdk_checker.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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_SCOPED_DISABLE_PUBLIC_SDK_CHECKER_H_
+#define ART_RUNTIME_SCOPED_DISABLE_PUBLIC_SDK_CHECKER_H_
+
+#include "class_linker.h"
+
+namespace art {
+
+// Utility class to disabled the public sdk checker within a scope (if installed).
+class ScopedDisablePublicSdkChecker : public ValueObject {
+ public:
+  ALWAYS_INLINE ScopedDisablePublicSdkChecker() {
+    Runtime* runtime = Runtime::Current();
+    if (UNLIKELY(runtime->IsAotCompiler())) {
+      runtime->GetClassLinker()->SetEnablePublicSdkChecks(false);
+    }
+  }
+
+  ALWAYS_INLINE ~ScopedDisablePublicSdkChecker() {
+    Runtime* runtime = Runtime::Current();
+    if (UNLIKELY(runtime->IsAotCompiler())) {
+      runtime->GetClassLinker()->SetEnablePublicSdkChecks(true);
+    }
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedDisablePublicSdkChecker);
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_SCOPED_DISABLE_PUBLIC_SDK_CHECKER_H_
diff --git a/runtime/sdk_checker.cc b/runtime/sdk_checker.cc
new file mode 100644
index 0000000..1dbe39c
--- /dev/null
+++ b/runtime/sdk_checker.cc
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2020 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 "sdk_checker.h"
+
+#include "art_method-inl.h"
+#include "base/utils.h"
+#include "dex/art_dex_file_loader.h"
+#include "mirror/class-inl.h"
+
+namespace art {
+
+SdkChecker::SdkChecker() : enabled_(true) {}
+
+SdkChecker* SdkChecker::Create(
+    const std::string& public_sdk, std::string* error_msg) {
+  std::vector<std::string> dex_file_paths;
+  Split(public_sdk, ':', &dex_file_paths);
+
+  ArtDexFileLoader dex_loader;
+
+  std::unique_ptr<SdkChecker> sdk_checker(new SdkChecker());
+  for (const std::string& path : dex_file_paths) {
+    if (!dex_loader.Open(path.c_str(),
+                         path,
+                         /*verify=*/ true,
+                         /*verify_checksum*/ false,
+                         error_msg,
+                         &sdk_checker->sdk_dex_files_)) {
+      return nullptr;
+    }
+  }
+  return sdk_checker.release();
+}
+
+bool SdkChecker::ShouldDenyAccess(ArtMethod* art_method) const {
+  if (!enabled_) {
+    return false;
+  }
+
+  bool found = false;
+  for (const std::unique_ptr<const DexFile>& dex_file : sdk_dex_files_) {
+    const dex::TypeId* declaring_type_id =
+        dex_file->FindTypeId(art_method->GetDeclaringClassDescriptor());
+    if (declaring_type_id == nullptr) {
+      continue;
+    }
+    const dex::StringId* name_id = dex_file->FindStringId(art_method->GetName());
+    if (name_id == nullptr) {
+      continue;
+    }
+
+    dex::TypeIndex return_type_idx;
+    std::vector<dex::TypeIndex> param_type_idxs;
+    if (!dex_file->CreateTypeList(
+            art_method->GetSignature().ToString().c_str(),
+            &return_type_idx,
+            &param_type_idxs)) {
+      continue;
+    }
+    const dex::ProtoId* proto_id = dex_file->FindProtoId(return_type_idx, param_type_idxs);
+    if (proto_id == nullptr) {
+      continue;
+    }
+
+    const dex::MethodId* method_id =
+        dex_file->FindMethodId(*declaring_type_id, *name_id, *proto_id);
+    if (method_id != nullptr) {
+      found = true;
+      break;
+    }
+  }
+
+  if (!found) {
+    VLOG(verifier) << "Deny for " << art_method->PrettyMethod(true);
+  }
+
+  // Deny access if we didn't find the descriptor in the public api dex files.
+  return !found;
+}
+
+bool SdkChecker::ShouldDenyAccess(ArtField* art_field) const {
+  if (!enabled_) {
+    return false;
+  }
+
+  bool found = false;
+  for (const std::unique_ptr<const DexFile>& dex_file : sdk_dex_files_) {
+    std::string declaring_class;
+
+    const dex::TypeId* declaring_type_id = dex_file->FindTypeId(
+        art_field->GetDeclaringClass()->GetDescriptor(&declaring_class));
+    if (declaring_type_id == nullptr) {
+      continue;
+    }
+    const dex::StringId* name_id = dex_file->FindStringId(art_field->GetName());
+    if (name_id == nullptr) {
+      continue;
+    }
+    const dex::TypeId* type_id = dex_file->FindTypeId(art_field->GetTypeDescriptor());
+    if (type_id == nullptr) {
+      continue;
+    }
+
+    const dex::FieldId* field_id = dex_file->FindFieldId(*declaring_type_id, *name_id, *type_id);
+    if (field_id != nullptr) {
+      found = true;
+      break;
+    }
+  }
+
+  if (!found) {
+    VLOG(verifier) << "Deny for " << ArtField::PrettyField(art_field, true);
+  }
+
+  // Deny access if we didn't find the descriptor in the public api dex files.
+  return !found;
+}
+
+bool SdkChecker::ShouldDenyAccess(const char* descriptor) const {
+  if (!enabled_) {
+    return false;
+  }
+
+  bool found = false;
+  for (const std::unique_ptr<const DexFile>& dex_file : sdk_dex_files_) {
+    const dex::TypeId* type_id = dex_file->FindTypeId(descriptor);
+    if (type_id != nullptr) {
+      dex::TypeIndex type_idx = dex_file->GetIndexForTypeId(*type_id);
+      if (dex_file->FindClassDef(type_idx) != nullptr) {
+        found = true;
+        break;
+      }
+    }
+  }
+
+  if (!found) {
+    VLOG(verifier) << "Deny for " << descriptor;
+  }
+
+  // Deny access if we didn't find the descriptor in the public api dex files.
+  return !found;
+}
+
+}  // namespace art
diff --git a/runtime/sdk_checker.h b/runtime/sdk_checker.h
new file mode 100644
index 0000000..8d82237
--- /dev/null
+++ b/runtime/sdk_checker.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 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_SDK_CHECKER_H_
+#define ART_RUNTIME_SDK_CHECKER_H_
+
+#include "art_field.h"
+#include "art_method.h"
+#include "base/locks.h"
+#include "dex/dex_file.h"
+
+namespace art {
+
+/**
+ * The SdkChecker verifies if a given symbol is present in a given classpath.
+ *
+ * For convenience and future extensibility the classpath is given as set of
+ * dex files, simillar to a regular classpath the APKs use.
+ *
+ * The symbol (method, field, class) is checked based on its descriptor and not
+ * according the any access check semantic.
+ *
+ * This class is intended to be used during off-device AOT verification when
+ * only some predefined symbols should be resolved (e.g. belonging to some public
+ * API classpath).
+ */
+class SdkChecker {
+ public:
+  // Constructs and SDK Checker from the given public sdk paths. The public_sdk
+  // format is the same as the classpath format (e.g. `dex1:dex2:dex3`). The
+  // method will attempt to open the dex files and if there are errors it will
+  // return a nullptr and set the error_msg appropriately.
+  static SdkChecker* Create(const std::string& public_sdk, std::string* error_msg);
+
+  // Verify if it should deny access to the given methods.
+  // The decision is based on whether or not any of the API dex files declares a method
+  // with the same signature.
+  //
+  // NOTE: This is an expensive check as it searches the dex files for the necessary type
+  // and string ids. This is OK because the functionality here is indended to be used
+  // only in AOT verification.
+  bool ShouldDenyAccess(ArtMethod* art_method) const REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Similar to ShouldDenyAccess(ArtMethod* art_method).
+  bool ShouldDenyAccess(ArtField* art_field) const REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Similar to ShouldDenyAccess(ArtMethod* art_method).
+  bool ShouldDenyAccess(const char* type_descriptor) const;
+
+  // Enabled/Disable the checks.
+  void SetEnabled(bool enabled) { enabled_ = enabled; }
+
+ private:
+  SdkChecker();
+
+  std::vector<std::unique_ptr<const DexFile>> sdk_dex_files_;
+
+  bool enabled_;
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_SDK_CHECKER_H_
diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc
index 9b3de2a..f76a0d0 100644
--- a/runtime/signal_catcher.cc
+++ b/runtime/signal_catcher.cc
@@ -105,11 +105,11 @@
 
 void SignalCatcher::Output(const std::string& s) {
   ScopedThreadStateChange tsc(Thread::Current(), kWaitingForSignalCatcherOutput);
-  PaletteStatus status = PaletteWriteCrashThreadStacks(s.data(), s.size());
-  if (status == PaletteStatus::kOkay) {
+  palette_status_t status = PaletteWriteCrashThreadStacks(s.data(), s.size());
+  if (status == PALETTE_STATUS_OK) {
     LOG(INFO) << "Wrote stack traces to tombstoned";
   } else {
-    CHECK(status == PaletteStatus::kFailedCheckLog);
+    CHECK(status == PALETTE_STATUS_FAILED_CHECK_LOG);
     LOG(ERROR) << "Failed to write stack traces to tombstoned";
   }
 }
diff --git a/runtime/signal_set.h b/runtime/signal_set.h
index 5361323..39e4c5f 100644
--- a/runtime/signal_set.h
+++ b/runtime/signal_set.h
@@ -21,24 +21,32 @@
 
 #include <android-base/logging.h>
 
+#if defined(__GLIBC__)
+#define sigset64_t sigset_t
+#define sigemptyset64 sigemptyset
+#define sigaddset64 sigaddset
+#define pthread_sigmask64 pthread_sigmask
+#define sigwait64 sigwait
+#endif
+
 namespace art {
 
 class SignalSet {
  public:
   SignalSet() {
-    if (sigemptyset(&set_) == -1) {
+    if (sigemptyset64(&set_) == -1) {
       PLOG(FATAL) << "sigemptyset failed";
     }
   }
 
   void Add(int signal) {
-    if (sigaddset(&set_, signal) == -1) {
+    if (sigaddset64(&set_, signal) == -1) {
       PLOG(FATAL) << "sigaddset " << signal << " failed";
     }
   }
 
   void Block() {
-    if (pthread_sigmask(SIG_BLOCK, &set_, nullptr) != 0) {
+    if (pthread_sigmask64(SIG_BLOCK, &set_, nullptr) != 0) {
       PLOG(FATAL) << "pthread_sigmask failed";
     }
   }
@@ -46,7 +54,7 @@
   int Wait() {
     // Sleep in sigwait() until a signal arrives. gdb causes EINTR failures.
     int signal_number;
-    int rc = TEMP_FAILURE_RETRY(sigwait(&set_, &signal_number));
+    int rc = TEMP_FAILURE_RETRY(sigwait64(&set_, &signal_number));
     if (rc != 0) {
       PLOG(FATAL) << "sigwait failed";
     }
@@ -54,7 +62,7 @@
   }
 
  private:
-  sigset_t set_;
+  sigset64_t set_;
 };
 
 }  // namespace art
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 58a73cc..233106e 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -30,6 +30,7 @@
 #include "entrypoints/runtime_asm_entrypoints.h"
 #include "gc/space/image_space.h"
 #include "gc/space/space-inl.h"
+#include "interpreter/mterp/nterp.h"
 #include "interpreter/shadow_frame-inl.h"
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
@@ -149,19 +150,11 @@
     return nullptr;
   } else if (m->IsNative()) {
     if (cur_quick_frame_ != nullptr) {
-      HandleScope* hs;
-      if (cur_oat_quick_method_header_ != nullptr) {
-        hs = reinterpret_cast<HandleScope*>(
-            reinterpret_cast<char*>(cur_quick_frame_) + sizeof(ArtMethod*));
-      } else {
-        // GenericJNI frames have the HandleScope under the managed frame.
-        uint32_t shorty_len;
-        const char* shorty = m->GetShorty(&shorty_len);
-        const size_t num_handle_scope_references =
-            /* this */ 1u + std::count(shorty + 1, shorty + shorty_len, 'L');
-        hs = GetGenericJniHandleScope(cur_quick_frame_, num_handle_scope_references);
-      }
-      return hs->GetReference(0);
+      // The `this` reference is stored in the first out vreg in the caller's frame.
+      const size_t frame_size = GetCurrentQuickFrameInfo().FrameSizeInBytes();
+      auto* stack_ref = reinterpret_cast<StackReference<mirror::Object>*>(
+          reinterpret_cast<uint8_t*>(cur_quick_frame_) + frame_size + sizeof(ArtMethod*));
+      return stack_ref->AsMirrorPtr();
     } else {
       return cur_shadow_frame_->GetVRegReference(0);
     }
@@ -240,7 +233,7 @@
         uint32_t val2 = *val;
         // The caller already known the register location, so we can use the faster overload
         // which does not decode the stack maps.
-        result = GetVRegFromOptimizedCode(location.value(), kind, val);
+        result = GetVRegFromOptimizedCode(location.value(), val);
         // Compare to the slower overload.
         DCHECK_EQ(result, GetVRegFromOptimizedCode(m, vreg, kind, &val2));
         DCHECK_EQ(*val, val2);
@@ -268,7 +261,9 @@
   }
 }
 
-bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKind kind,
+bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m,
+                                            uint16_t vreg,
+                                            VRegKind kind,
                                             uint32_t* val) const {
   DCHECK_EQ(m, GetMethod());
   // Can't be null or how would we compile its instructions?
@@ -308,7 +303,7 @@
       if (kind == kReferenceVReg && !(register_mask & (1 << reg))) {
         return false;
       }
-      return GetRegisterIfAccessible(reg, kind, val);
+      return GetRegisterIfAccessible(reg, location_kind, val);
     }
     case DexRegisterLocation::Kind::kInRegisterHigh:
     case DexRegisterLocation::Kind::kInFpuRegister:
@@ -317,7 +312,7 @@
         return false;
       }
       uint32_t reg = dex_register_map[vreg].GetMachineRegister();
-      return GetRegisterIfAccessible(reg, kind, val);
+      return GetRegisterIfAccessible(reg, location_kind, val);
     }
     case DexRegisterLocation::Kind::kConstant: {
       uint32_t result = dex_register_map[vreg].GetConstant();
@@ -335,9 +330,7 @@
   }
 }
 
-bool StackVisitor::GetVRegFromOptimizedCode(DexRegisterLocation location,
-                                            VRegKind kind,
-                                            uint32_t* val) const {
+bool StackVisitor::GetVRegFromOptimizedCode(DexRegisterLocation location, uint32_t* val) const {
   switch (location.GetKind()) {
     case DexRegisterLocation::Kind::kInvalid:
       break;
@@ -350,7 +343,7 @@
     case DexRegisterLocation::Kind::kInRegisterHigh:
     case DexRegisterLocation::Kind::kInFpuRegister:
     case DexRegisterLocation::Kind::kInFpuRegisterHigh:
-      return GetRegisterIfAccessible(location.GetMachineRegister(), kind, val);
+      return GetRegisterIfAccessible(location.GetMachineRegister(), location.GetKind(), val);
     case DexRegisterLocation::Kind::kConstant:
       *val = location.GetConstant();
       return true;
@@ -361,13 +354,18 @@
   UNREACHABLE();
 }
 
-bool StackVisitor::GetRegisterIfAccessible(uint32_t reg, VRegKind kind, uint32_t* val) const {
-  const bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
+bool StackVisitor::GetRegisterIfAccessible(uint32_t reg,
+                                           DexRegisterLocation::Kind location_kind,
+                                           uint32_t* val) const {
+  const bool is_float = (location_kind == DexRegisterLocation::Kind::kInFpuRegister) ||
+                        (location_kind == DexRegisterLocation::Kind::kInFpuRegisterHigh);
 
   if (kRuntimeISA == InstructionSet::kX86 && is_float) {
     // X86 float registers are 64-bit and each XMM register is provided as two separate
     // 32-bit registers by the context.
-    reg = (kind == kDoubleHiVReg) ? (2 * reg + 1) : (2 * reg);
+    reg = (location_kind == DexRegisterLocation::Kind::kInFpuRegisterHigh)
+        ? (2 * reg + 1)
+        : (2 * reg);
   }
 
   if (!IsAccessibleRegister(reg, is_float)) {
@@ -376,14 +374,10 @@
   uintptr_t ptr_val = GetRegister(reg, is_float);
   const bool target64 = Is64BitInstructionSet(kRuntimeISA);
   if (target64) {
-    const bool wide_lo = (kind == kLongLoVReg) || (kind == kDoubleLoVReg);
-    const bool wide_hi = (kind == kLongHiVReg) || (kind == kDoubleHiVReg);
+    const bool is_high = (location_kind == DexRegisterLocation::Kind::kInRegisterHigh) ||
+                         (location_kind == DexRegisterLocation::Kind::kInFpuRegisterHigh);
     int64_t value_long = static_cast<int64_t>(ptr_val);
-    if (wide_lo) {
-      ptr_val = static_cast<uintptr_t>(Low32Bits(value_long));
-    } else if (wide_hi) {
-      ptr_val = static_cast<uintptr_t>(High32Bits(value_long));
-    }
+    ptr_val = static_cast<uintptr_t>(is_high ? High32Bits(value_long) : Low32Bits(value_long));
   }
   *val = ptr_val;
   return true;
@@ -448,25 +442,6 @@
   return success;
 }
 
-bool StackVisitor::GetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi,
-                                               VRegKind kind_lo, uint64_t* val) const {
-  const bool is_float = (kind_lo == kDoubleLoVReg);
-  if (!IsAccessibleRegister(reg_lo, is_float) || !IsAccessibleRegister(reg_hi, is_float)) {
-    return false;
-  }
-  uintptr_t ptr_val_lo = GetRegister(reg_lo, is_float);
-  uintptr_t ptr_val_hi = GetRegister(reg_hi, is_float);
-  bool target64 = Is64BitInstructionSet(kRuntimeISA);
-  if (target64) {
-    int64_t value_long_lo = static_cast<int64_t>(ptr_val_lo);
-    int64_t value_long_hi = static_cast<int64_t>(ptr_val_hi);
-    ptr_val_lo = static_cast<uintptr_t>(Low32Bits(value_long_lo));
-    ptr_val_hi = static_cast<uintptr_t>(High32Bits(value_long_hi));
-  }
-  *val = (static_cast<uint64_t>(ptr_val_hi) << 32) | static_cast<uint32_t>(ptr_val_lo);
-  return true;
-}
-
 ShadowFrame* StackVisitor::PrepareSetVReg(ArtMethod* m, uint16_t vreg, bool wide) {
   CodeItemDataAccessor accessor(m->DexInstructionData());
   if (!accessor.HasCodeItem()) {
@@ -712,7 +687,7 @@
       << " code_size=" << code_size;
 }
 
-void StackVisitor::SanityCheckFrame() const {
+void StackVisitor::ValidateFrame() const {
   if (kIsDebugBuild) {
     ArtMethod* method = GetMethod();
     ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass();
@@ -728,8 +703,8 @@
     LinearAlloc* const linear_alloc = runtime->GetLinearAlloc();
     if (!linear_alloc->Contains(method)) {
       // Check class linker linear allocs.
-      // We get the canonical method as copied methods may have their declaring
-      // class from another class loader.
+      // We get the canonical method as copied methods may have been allocated
+      // by a different class loader.
       const PointerSize ptrSize = runtime->GetClassLinker()->GetImagePointerSize();
       ArtMethod* canonical = method->GetCanonicalMethod(ptrSize);
       ObjPtr<mirror::Class> klass = canonical->GetDeclaringClass();
@@ -757,7 +732,7 @@
     }
     if (cur_quick_frame_ != nullptr) {
       AssertPcIsWithinQuickCode(method, cur_quick_frame_pc_);
-      // Frame sanity.
+      // Frame consistency checks.
       size_t frame_size = GetCurrentQuickFrameInfo().FrameSizeInBytes();
       CHECK_NE(frame_size, 0u);
       // For compiled code, we could try to have a rough guess at an upper size we expect
@@ -766,7 +741,7 @@
       // 2 words HandleScope overhead
       // 3+3 register spills
       // const size_t kMaxExpectedFrameSize = (256 + 2 + 3 + 3) * sizeof(word);
-      const size_t kMaxExpectedFrameSize = interpreter::kMaxNterpFrame;
+      const size_t kMaxExpectedFrameSize = interpreter::kNterpMaxFrame;
       CHECK_LE(frame_size, kMaxExpectedFrameSize) << method->PrettyMethod();
       size_t return_pc_offset = GetCurrentQuickFrameInfo().GetReturnPcOffset();
       CHECK_LT(return_pc_offset, frame_size);
@@ -885,7 +860,7 @@
           cur_oat_quick_method_header_ = method->GetOatQuickMethodHeader(cur_quick_frame_pc_);
         }
         header_retrieved = false;  // Force header retrieval in next iteration.
-        SanityCheckFrame();
+        ValidateFrame();
 
         if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames)
             && (cur_oat_quick_method_header_ != nullptr)
@@ -979,7 +954,7 @@
       cur_oat_quick_method_header_ = nullptr;
     } else if (cur_shadow_frame_ != nullptr) {
       do {
-        SanityCheckFrame();
+        ValidateFrame();
         bool should_continue = VisitFrame();
         if (UNLIKELY(!should_continue)) {
           return;
diff --git a/runtime/stack.h b/runtime/stack.h
index af33e6c..2a6fdc2 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -54,7 +54,7 @@
   kImpreciseConstant,
   kUndefined,
 };
-std::ostream& operator<<(std::ostream& os, const VRegKind& rhs);
+std::ostream& operator<<(std::ostream& os, VRegKind rhs);
 
 // Size in bytes of the should_deoptimize flag on stack.
 // We just need 4 bytes for our purpose regardless of the architecture. Frame size
@@ -126,7 +126,7 @@
                StackWalkKind walk_kind,
                bool check_suspended = true);
 
-  bool GetRegisterIfAccessible(uint32_t reg, VRegKind kind, uint32_t* val) const
+  bool GetRegisterIfAccessible(uint32_t reg, DexRegisterLocation::Kind kind, uint32_t* val) const
       REQUIRES_SHARED(Locks::mutator_lock_);
 
  public:
@@ -282,12 +282,6 @@
     return cur_shadow_frame_;
   }
 
-  HandleScope* GetCurrentHandleScope(size_t pointer_size) const {
-    ArtMethod** sp = GetCurrentQuickFrame();
-    // Skip ArtMethod*; handle scope comes next;
-    return reinterpret_cast<HandleScope*>(reinterpret_cast<uintptr_t>(sp) + pointer_size);
-  }
-
   std::string DescribeLocation() const REQUIRES_SHARED(Locks::mutator_lock_);
 
   static size_t ComputeNumFrames(Thread* thread, StackWalkKind walk_kind)
@@ -326,27 +320,30 @@
 
   bool GetVRegFromDebuggerShadowFrame(uint16_t vreg, VRegKind kind, uint32_t* val) const
       REQUIRES_SHARED(Locks::mutator_lock_);
-  bool GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKind kind,
+  bool GetVRegFromOptimizedCode(ArtMethod* m,
+                                uint16_t vreg,
+                                VRegKind kind,
                                 uint32_t* val) const
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  bool GetVRegPairFromDebuggerShadowFrame(uint16_t vreg, VRegKind kind_lo, VRegKind kind_hi,
+  bool GetVRegPairFromDebuggerShadowFrame(uint16_t vreg,
+                                          VRegKind kind_lo,
+                                          VRegKind kind_hi,
                                           uint64_t* val) const
       REQUIRES_SHARED(Locks::mutator_lock_);
-  bool GetVRegPairFromOptimizedCode(ArtMethod* m, uint16_t vreg,
-                                    VRegKind kind_lo, VRegKind kind_hi,
+  bool GetVRegPairFromOptimizedCode(ArtMethod* m,
+                                    uint16_t vreg,
+                                    VRegKind kind_lo,
+                                    VRegKind kind_hi,
                                     uint64_t* val) const
       REQUIRES_SHARED(Locks::mutator_lock_);
-  bool GetVRegFromOptimizedCode(DexRegisterLocation location, VRegKind kind, uint32_t* val) const
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  bool GetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi, VRegKind kind_lo,
-                                   uint64_t* val) const
+  bool GetVRegFromOptimizedCode(DexRegisterLocation location, uint32_t* val) const
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   ShadowFrame* PrepareSetVReg(ArtMethod* m, uint16_t vreg, bool wide)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void SanityCheckFrame() const REQUIRES_SHARED(Locks::mutator_lock_);
+  void ValidateFrame() const REQUIRES_SHARED(Locks::mutator_lock_);
 
   ALWAYS_INLINE CodeInfo* GetCurrentInlineInfo() const;
   ALWAYS_INLINE StackMap* GetCurrentStackMap() const;
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index d813fd5..c160e2b 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -21,7 +21,7 @@
 
 #include "art_method.h"
 #include "base/indenter.h"
-#include "base/stats.h"
+#include "base/stats-inl.h"
 #include "oat_quick_method_header.h"
 #include "scoped_thread_state_change-inl.h"
 
@@ -61,13 +61,6 @@
 CodeInfo::CodeInfo(const OatQuickMethodHeader* header)
     : CodeInfo(header->GetOptimizedCodeInfoPtr()) {}
 
-QuickMethodFrameInfo CodeInfo::DecodeFrameInfo(const uint8_t* data) {
-  CodeInfo code_info(data);
-  return QuickMethodFrameInfo(code_info.packed_frame_size_ * kStackAlignment,
-                              code_info.core_spill_mask_,
-                              code_info.fp_spill_mask_);
-}
-
 CodeInfo CodeInfo::DecodeGcMasksOnly(const OatQuickMethodHeader* header) {
   CodeInfo code_info(header->GetOptimizedCodeInfoPtr());
   CodeInfo copy;  // Copy to dead-code-eliminate all fields that we do not need.
@@ -140,7 +133,7 @@
   return deduped_offset;
 }
 
-StackMap CodeInfo::GetStackMapForNativePcOffset(uint32_t pc, InstructionSet isa) const {
+StackMap CodeInfo::GetStackMapForNativePcOffset(uintptr_t pc, InstructionSet isa) const {
   uint32_t packed_pc = StackMap::PackNativePc(pc, isa);
   // Binary search.  All catch stack maps are stored separately at the end.
   auto it = std::partition_point(
@@ -223,26 +216,26 @@
 }
 
 // Decode the CodeInfo while collecting size statistics.
-void CodeInfo::CollectSizeStats(const uint8_t* code_info_data, /*out*/ Stats* parent) {
-  Stats* codeinfo_stats = parent->Child("CodeInfo");
+void CodeInfo::CollectSizeStats(const uint8_t* code_info_data, /*out*/ Stats& stats) {
   BitMemoryReader reader(code_info_data);
   reader.ReadInterleavedVarints<kNumHeaders>();
-  codeinfo_stats->Child("Header")->AddBits(reader.NumberOfReadBits());
+  stats["Header"].AddBits(reader.NumberOfReadBits());
   size_t num_bits;
   CodeInfo code_info(code_info_data, &num_bits, [&](size_t i, auto* table, BitMemoryRegion region) {
     if (!code_info.IsBitTableDeduped(i)) {
-      Stats* table_stats = codeinfo_stats->Child(table->GetName());
-      table_stats->AddBits(region.size_in_bits());
+      Stats& table_stats = stats[table->GetName()];
+      table_stats.AddBits(region.size_in_bits());
+      table_stats["Header"].AddBits(region.size_in_bits() - table->DataBitSize());
       const char* const* column_names = table->GetColumnNames();
       for (size_t c = 0; c < table->NumColumns(); c++) {
         if (table->NumColumnBits(c) > 0) {
-          Stats* column_stats = table_stats->Child(column_names[c]);
-          column_stats->AddBits(table->NumRows() * table->NumColumnBits(c), table->NumRows());
+          Stats& column_stats = table_stats[column_names[c]];
+          column_stats.AddBits(table->NumRows() * table->NumColumnBits(c), table->NumRows());
         }
       }
     }
   });
-  codeinfo_stats->AddBytes(BitsToBytesRoundUp(num_bits));
+  stats.AddBytes(BitsToBytesRoundUp(num_bits));
 }
 
 void DexRegisterMap::Dump(VariableIndentationOutputStream* vios) const {
@@ -262,7 +255,8 @@
                     uint32_t code_offset,
                     bool verbose,
                     InstructionSet instruction_set) const {
-  vios->Stream() << "CodeInfo "
+  vios->Stream() << "CodeInfo"
+    << " CodeSize:" << code_size_
     << " FrameSize:" << packed_frame_size_ * kStackAlignment
     << " CoreSpillMask:" << std::hex << core_spill_mask_
     << " FpSpillMask:" << std::hex << fp_spill_mask_
@@ -327,6 +321,12 @@
   for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
     vios->Stream() << stack_mask.LoadBit(e - i - 1);
   }
+  switch (static_cast<Kind>(GetKind())) {
+    case Kind::Default: break;
+    case Kind::Catch: vios->Stream() << ", Catch"; break;
+    case Kind::OSR: vios->Stream() << ", OSR"; break;
+    case Kind::Debug: vios->Stream() << ", Debug"; break;
+  }
   vios->Stream() << ")\n";
   code_info.GetDexRegisterMapOf(*this).Dump(vios);
   for (InlineInfo inline_info : code_info.GetInlineInfosOf(*this)) {
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 2065a79..103402b 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -296,10 +296,30 @@
   ALWAYS_INLINE explicit CodeInfo(const OatQuickMethodHeader* header);
 
   // The following methods decode only part of the data.
-  static QuickMethodFrameInfo DecodeFrameInfo(const uint8_t* data);
   static CodeInfo DecodeGcMasksOnly(const OatQuickMethodHeader* header);
   static CodeInfo DecodeInlineInfoOnly(const OatQuickMethodHeader* header);
 
+  ALWAYS_INLINE static uint32_t DecodeCodeSize(const uint8_t* code_info_data) {
+    return DecodeHeaderOnly(code_info_data).code_size_;
+  }
+
+  ALWAYS_INLINE static QuickMethodFrameInfo DecodeFrameInfo(const uint8_t* code_info_data) {
+    CodeInfo code_info = DecodeHeaderOnly(code_info_data);
+    return QuickMethodFrameInfo(code_info.packed_frame_size_ * kStackAlignment,
+                                code_info.core_spill_mask_,
+                                code_info.fp_spill_mask_);
+  }
+
+  ALWAYS_INLINE static CodeInfo DecodeHeaderOnly(const uint8_t* code_info_data) {
+    CodeInfo code_info;
+    BitMemoryReader reader(code_info_data);
+    std::array<uint32_t, kNumHeaders> header = reader.ReadInterleavedVarints<kNumHeaders>();
+    ForEachHeaderField([&code_info, &header](size_t i, auto member_pointer) {
+      code_info.*member_pointer = header[i];
+    });
+    return code_info;
+  }
+
   ALWAYS_INLINE const BitTable<StackMap>& GetStackMaps() const {
     return stack_maps_;
   }
@@ -413,7 +433,7 @@
     return stack_maps_.GetInvalidRow();
   }
 
-  StackMap GetStackMapForNativePcOffset(uint32_t pc, InstructionSet isa = kRuntimeISA) const;
+  StackMap GetStackMapForNativePcOffset(uintptr_t pc, InstructionSet isa = kRuntimeISA) const;
 
   // Dump this CodeInfo object on `vios`.
   // `code_offset` is the (absolute) native PC of the compiled method.
@@ -423,7 +443,7 @@
             InstructionSet instruction_set) const;
 
   // Accumulate code info size statistics into the given Stats tree.
-  static void CollectSizeStats(const uint8_t* code_info, /*out*/ Stats* parent);
+  static void CollectSizeStats(const uint8_t* code_info, /*out*/ Stats& parent);
 
   ALWAYS_INLINE static bool HasInlineInfo(const uint8_t* code_info_data) {
     return (*code_info_data & kHasInlineInfo) != 0;
@@ -447,6 +467,7 @@
   ALWAYS_INLINE static void ForEachHeaderField(Callback callback) {
     size_t index = 0;
     callback(index++, &CodeInfo::flags_);
+    callback(index++, &CodeInfo::code_size_);
     callback(index++, &CodeInfo::packed_frame_size_);
     callback(index++, &CodeInfo::core_spill_mask_);
     callback(index++, &CodeInfo::fp_spill_mask_);
@@ -480,8 +501,9 @@
   };
 
   // The CodeInfo starts with sequence of variable-length bit-encoded integers.
-  static constexpr size_t kNumHeaders = 6;
-  uint32_t flags_ = 0;
+  static constexpr size_t kNumHeaders = 7;
+  uint32_t flags_ = 0;      // Note that the space is limited to three bits.
+  uint32_t code_size_ = 0;  // The size of native PC range in bytes.
   uint32_t packed_frame_size_ = 0;  // Frame size in kStackAlignment units.
   uint32_t core_spill_mask_ = 0;
   uint32_t fp_spill_mask_ = 0;
diff --git a/runtime/suspend_reason.h b/runtime/suspend_reason.h
index 7f377d5..f45505a 100644
--- a/runtime/suspend_reason.h
+++ b/runtime/suspend_reason.h
@@ -30,7 +30,7 @@
   kForUserCode,
 };
 
-std::ostream& operator<<(std::ostream& os, const SuspendReason& thread);
+std::ostream& operator<<(std::ostream& os, SuspendReason thread);
 
 }  // namespace art
 
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index a6da16f..9d96e9d 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -202,7 +202,8 @@
     new_state_and_flags.as_struct.flags = old_state_and_flags.as_struct.flags;
     new_state_and_flags.as_struct.state = new_state;
 
-    // CAS the value with a memory ordering.
+    // CAS the value, ensuring that prior memory operations are visible to any thread
+    // that observes that we are suspended.
     bool done =
         tls32_.state_and_flags.as_atomic_int.CompareAndSetWeakRelease(old_state_and_flags.as_int,
                                                                         new_state_and_flags.as_int);
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 77b9f4f..46aa2b5 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -46,17 +46,17 @@
 #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"
 #include "base/stl_util.h"
 #include "base/systrace.h"
+#include "base/time_utils.h"
 #include "base/timing_logger.h"
 #include "base/to_str.h"
 #include "base/utils.h"
 #include "class_linker-inl.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "debugger.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
@@ -104,6 +104,7 @@
 #include "runtime.h"
 #include "runtime_callbacks.h"
 #include "scoped_thread_state_change-inl.h"
+#include "scoped_disable_public_sdk_checker.h"
 #include "stack.h"
 #include "stack_map.h"
 #include "thread-inl.h"
@@ -120,6 +121,9 @@
 #endif
 #endif  // ART_USE_FUTEXES
 
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
 namespace art {
 
 using android::base::StringAppendV;
@@ -162,7 +166,6 @@
   CHECK(kUseReadBarrier);
   tls32_.is_gc_marking = is_marking;
   UpdateReadBarrierEntrypoints(&tlsPtr_.quick_entrypoints, /* is_active= */ is_marking);
-  ResetQuickAllocEntryPointsForThread(is_marking);
 }
 
 void Thread::InitTlsEntryPoints() {
@@ -177,12 +180,8 @@
   InitEntryPoints(&tlsPtr_.jni_entrypoints, &tlsPtr_.quick_entrypoints);
 }
 
-void Thread::ResetQuickAllocEntryPointsForThread(bool is_marking) {
-  if (kUseReadBarrier && kRuntimeISA != InstructionSet::kX86_64) {
-    // Allocation entrypoint switching is currently only implemented for X86_64.
-    is_marking = true;
-  }
-  ResetQuickAllocEntryPoints(&tlsPtr_.quick_entrypoints, is_marking);
+void Thread::ResetQuickAllocEntryPointsForThread() {
+  ResetQuickAllocEntryPoints(&tlsPtr_.quick_entrypoints);
 }
 
 class DeoptimizationContextRecord {
@@ -345,7 +344,7 @@
       if (is_absolute) {
         // Time is millis when scheduled for an absolute time
         timespec.tv_nsec = (time % 1000) * 1000000;
-        timespec.tv_sec = time / 1000;
+        timespec.tv_sec = SaturatedTimeT(time / 1000);
         // This odd looking pattern is recommended by futex documentation to
         // wait until an absolute deadline, with otherwise identical behavior to
         // FUTEX_WAIT_PRIVATE. This also allows parkUntil() to return at the
@@ -355,10 +354,10 @@
                        /* sleep if val = */ kNoPermitWaiterWaiting,
                        &timespec,
                        nullptr,
-                       FUTEX_BITSET_MATCH_ANY);
+                       static_cast<int>(FUTEX_BITSET_MATCH_ANY));
       } else {
         // Time is nanos when scheduled for a relative time
-        timespec.tv_sec = time / 1000000000;
+        timespec.tv_sec = SaturatedTimeT(time / 1000000000);
         timespec.tv_nsec = time % 1000000000;
         result = futex(tls32_.park_state_.Address(),
                        FUTEX_WAIT_PRIVATE,
@@ -487,7 +486,7 @@
   for (FrameIdToShadowFrame* record = head; record != nullptr; record = record->GetNext()) {
     if (record->GetFrameId() == frame_id) {
       if (kIsDebugBuild) {
-        // Sanity check we have at most one record for this frame.
+        // Check we have at most one record for this frame.
         CHECK(found == nullptr) << "Multiple records for the frame " << frame_id;
         found = record;
       } else {
@@ -664,7 +663,7 @@
                                   ObjPtr<mirror::Object> thread_peer) {
   ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_Thread_nativePeer);
   Thread* result = reinterpret_cast64<Thread*>(f->GetLong(thread_peer));
-  // Sanity check that if we have a result it is either suspended or we hold the thread_list_lock_
+  // Check that if we have a result it is either suspended or we hold the thread_list_lock_
   // to stop it from going away.
   if (kIsDebugBuild) {
     MutexLock mu(soa.Self(), *Locks::thread_suspend_count_lock_);
@@ -742,7 +741,8 @@
   if (ProtectStack(/* fatal_on_error= */ false)) {
     // Tell the kernel that we won't be needing these pages any more.
     // NB. madvise will probably write zeroes into the memory (on linux it does).
-    uint32_t unwanted_size = stack_top - pregion - kPageSize;
+    size_t unwanted_size =
+        reinterpret_cast<uintptr_t>(stack_top) - reinterpret_cast<uintptr_t>(pregion) - kPageSize;
     madvise(pregion, unwanted_size, MADV_DONTNEED);
     return;
   }
@@ -814,7 +814,8 @@
 
   // Tell the kernel that we won't be needing these pages any more.
   // NB. madvise will probably write zeroes into the memory (on linux it does).
-  uint32_t unwanted_size = stack_top - pregion - kPageSize;
+  size_t unwanted_size =
+      reinterpret_cast<uintptr_t>(stack_top) - reinterpret_cast<uintptr_t>(pregion) - kPageSize;
   madvise(pregion, unwanted_size, MADV_DONTNEED);
 }
 
@@ -1048,11 +1049,14 @@
       self->CreatePeer(thread_name, as_daemon, thread_group);
       if (self->IsExceptionPending()) {
         // We cannot keep the exception around, as we're deleting self. Try to be helpful and log
-        // it.
+        // the failure but do not dump the exception details. If we fail to allocate the peer, we
+        // usually also fail to allocate an exception object and throw a pre-allocated OOME without
+        // any useful information. If we do manage to allocate the exception object, the memory
+        // information in the message could have been collected too late and therefore misleading.
         {
           ScopedObjectAccess soa(self);
-          LOG(ERROR) << "Exception creating thread peer:";
-          LOG(ERROR) << self->GetException()->Dump();
+          LOG(ERROR) << "Exception creating thread peer: "
+                     << ((thread_name != nullptr) ? thread_name : "<null>");
           self->ClearException();
         }
         return false;
@@ -1265,7 +1269,7 @@
   // If we're the main thread, check whether we were run with an unlimited stack. In that case,
   // glibc will have reported a 2GB stack for our 32-bit process, and our stack overflow detection
   // will be broken because we'll die long before we get close to 2GB.
-  bool is_main_thread = (::art::GetTid() == getpid());
+  bool is_main_thread = (::art::GetTid() == static_cast<uint32_t>(getpid()));
   if (is_main_thread) {
     rlimit stack_limit;
     if (getrlimit(RLIMIT_STACK, &stack_limit) == -1) {
@@ -1334,12 +1338,12 @@
 
     tlsPtr_.stack_begin += read_guard_size + kStackOverflowProtectedSize;
     tlsPtr_.stack_end += read_guard_size + kStackOverflowProtectedSize;
-    tlsPtr_.stack_size -= read_guard_size;
+    tlsPtr_.stack_size -= read_guard_size + kStackOverflowProtectedSize;
 
     InstallImplicitProtection();
   }
 
-  // Sanity check.
+  // Consistency check.
   CHECK_GT(FindStackTop(), reinterpret_cast<void*>(tlsPtr_.stack_end));
 
   return true;
@@ -1384,7 +1388,8 @@
   pthread_getcpuclockid(tlsPtr_.pthread_self, &cpu_clock_id);
   timespec now;
   clock_gettime(cpu_clock_id, &now);
-  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_nsec / UINT64_C(1000);
+  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) +
+         static_cast<uint64_t>(now.tv_nsec) / UINT64_C(1000);
 #else  // __APPLE__
   UNIMPLEMENTED(WARNING);
   return -1;
@@ -1417,9 +1422,8 @@
                                         AtomicInteger* suspend_barrier,
                                         SuspendReason reason) {
   if (kIsDebugBuild) {
-    DCHECK(delta == -1 || delta == +1 || delta == -tls32_.debug_suspend_count)
-          << reason << " " << delta << " " << tls32_.debug_suspend_count << " " << this;
-    DCHECK_GE(tls32_.suspend_count, tls32_.debug_suspend_count) << this;
+    DCHECK(delta == -1 || delta == +1)
+          << reason << " " << delta << " " << this;
     Locks::thread_suspend_count_lock_->AssertHeld(self);
     if (this != self && !IsSuspended()) {
       Locks::thread_list_lock_->AssertHeld(self);
@@ -1851,8 +1855,8 @@
   } else if (thread != nullptr) {
     priority = thread->GetNativePriority();
   } else {
-    PaletteStatus status = PaletteSchedGetPriority(tid, &priority);
-    CHECK(status == PaletteStatus::kOkay || status == PaletteStatus::kCheckErrno);
+    palette_status_t status = PaletteSchedGetPriority(tid, &priority);
+    CHECK(status == PALETTE_STATUS_OK || status == PALETTE_STATUS_CHECK_ERRNO);
   }
 
   std::string scheduler_group_name(GetSchedulerGroupName(tid));
@@ -1882,7 +1886,7 @@
     auto suspend_log_fn = [&]() REQUIRES(Locks::thread_suspend_count_lock_) {
       os << "  | group=\"" << group_name << "\""
          << " sCount=" << thread->tls32_.suspend_count
-         << " dsCount=" << thread->tls32_.debug_suspend_count
+         << " ucsCount=" << thread->tls32_.user_code_suspend_count
          << " flags=" << thread->tls32_.state_and_flags.as_struct.flags
          << " obj=" << reinterpret_cast<void*>(thread->tlsPtr_.opeer)
          << " self=" << reinterpret_cast<const void*>(thread) << "\n";
@@ -1897,7 +1901,7 @@
   }
 
   os << "  | sysTid=" << tid
-     << " nice=" << getpriority(PRIO_PROCESS, tid)
+     << " nice=" << getpriority(PRIO_PROCESS, static_cast<id_t>(tid))
      << " cgrp=" << scheduler_group_name;
   if (thread != nullptr) {
     int policy;
@@ -2474,12 +2478,6 @@
   CHECK(tlsPtr_.flip_function == nullptr);
   CHECK_EQ(tls32_.is_transitioning_to_runnable, false);
 
-  if (kUseReadBarrier) {
-    Runtime::Current()->GetHeap()->ConcurrentCopyingCollector()
-        ->AssertNoThreadMarkStackMapping(this);
-    gc::accounting::AtomicStack<mirror::Object>* tl_mark_stack = GetThreadLocalMarkStack();
-    CHECK(tl_mark_stack == nullptr) << "mark-stack: " << tl_mark_stack;
-  }
   // Make sure we processed all deoptimization requests.
   CHECK(tlsPtr_.deoptimization_context_stack == nullptr) << "Missed deoptimization";
   CHECK(tlsPtr_.frame_id_to_shadow_frame == nullptr) <<
@@ -2543,19 +2541,85 @@
   }
 }
 
-bool Thread::HandleScopeContains(jobject obj) const {
-  StackReference<mirror::Object>* hs_entry =
-      reinterpret_cast<StackReference<mirror::Object>*>(obj);
-  for (BaseHandleScope* cur = tlsPtr_.top_handle_scope; cur!= nullptr; cur = cur->GetLink()) {
-    if (cur->Contains(hs_entry)) {
+template <bool kPointsToStack>
+class JniTransitionReferenceVisitor : public StackVisitor {
+ public:
+  JniTransitionReferenceVisitor(Thread* thread, void* obj) REQUIRES_SHARED(Locks::mutator_lock_)
+      : StackVisitor(thread, /*context=*/ nullptr, StackVisitor::StackWalkKind::kSkipInlinedFrames),
+        obj_(obj),
+        found_(false) {}
+
+  bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
+    ArtMethod* m = GetMethod();
+    if (!m->IsNative() || m->IsCriticalNative()) {
+      return true;
+    }
+    if (kPointsToStack) {
+      uint8_t* sp = reinterpret_cast<uint8_t*>(GetCurrentQuickFrame());
+      size_t frame_size = GetCurrentQuickFrameInfo().FrameSizeInBytes();
+      uint32_t* current_vreg = reinterpret_cast<uint32_t*>(sp + frame_size + sizeof(ArtMethod*));
+      if (!m->IsStatic()) {
+        if (current_vreg == obj_) {
+          found_ = true;
+          return false;
+        }
+        current_vreg += 1u;
+      }
+      const char* shorty = m->GetShorty();
+      for (size_t i = 1, len = strlen(shorty); i != len; ++i) {
+        switch (shorty[i]) {
+          case 'D':
+          case 'J':
+            current_vreg += 2u;
+            break;
+          case 'L':
+            if (current_vreg == obj_) {
+              found_ = true;
+              return false;
+            }
+            FALLTHROUGH_INTENDED;
+          default:
+            current_vreg += 1u;
+            break;
+        }
+      }
+      // Continue only if the object is somewhere higher on the stack.
+      return obj_ >= current_vreg;
+    } else {  // if (kPointsToStack)
+      if (m->IsStatic() && obj_ == m->GetDeclaringClassAddressWithoutBarrier()) {
+        found_ = true;
+        return false;
+      }
       return true;
     }
   }
-  // JNI code invoked from portable code uses shadow frames rather than the handle scope.
-  return tlsPtr_.managed_stack.ShadowFramesContain(hs_entry);
+
+  bool Found() const {
+    return found_;
+  }
+
+ private:
+  void* obj_;
+  bool found_;
+};
+
+bool Thread::IsJniTransitionReference(jobject obj) const {
+  DCHECK(obj != nullptr);
+  // We need a non-const pointer for stack walk even if we're not modifying the thread state.
+  Thread* thread = const_cast<Thread*>(this);
+  uint8_t* raw_obj = reinterpret_cast<uint8_t*>(obj);
+  if (static_cast<size_t>(raw_obj - tlsPtr_.stack_begin) < tlsPtr_.stack_size) {
+    JniTransitionReferenceVisitor</*kPointsToStack=*/ true> visitor(thread, raw_obj);
+    visitor.WalkStack();
+    return visitor.Found();
+  } else {
+    JniTransitionReferenceVisitor</*kPointsToStack=*/ false> visitor(thread, raw_obj);
+    visitor.WalkStack();
+    return visitor.Found();
+  }
 }
 
-void Thread::HandleScopeVisitRoots(RootVisitor* visitor, pid_t thread_id) {
+void Thread::HandleScopeVisitRoots(RootVisitor* visitor, uint32_t thread_id) {
   BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(
       visitor, RootInfo(kRootNativeStack, thread_id));
   for (BaseHandleScope* cur = tlsPtr_.top_handle_scope; cur; cur = cur->GetLink()) {
@@ -2576,18 +2640,13 @@
     IndirectReferenceTable& locals = tlsPtr_.jni_env->locals_;
     // Local references do not need a read barrier.
     result = locals.Get<kWithoutReadBarrier>(ref);
-  } else if (kind == kHandleScopeOrInvalid) {
-    // TODO: make stack indirect reference table lookup more efficient.
-    // Check if this is a local reference in the handle scope.
-    if (LIKELY(HandleScopeContains(obj))) {
-      // Read from handle scope.
-      result = reinterpret_cast<StackReference<mirror::Object>*>(obj)->AsMirrorPtr();
-      VerifyObject(result);
-    } else {
-      tlsPtr_.jni_env->vm_->JniAbortF(nullptr, "use of invalid jobject %p", obj);
-      expect_null = true;
-      result = nullptr;
-    }
+  } else if (kind == kJniTransitionOrInvalid) {
+    // The `jclass` for a static method points to the CompressedReference<> in the
+    // `ArtMethod::declaring_class_`. Other `jobject` arguments point to spilled stack
+    // references but a StackReference<> is just a subclass of CompressedReference<>.
+    DCHECK(IsJniTransitionReference(obj));
+    result = reinterpret_cast<mirror::CompressedReference<mirror::Object>*>(obj)->AsMirrorPtr();
+    VerifyObject(result);
   } else if (kind == kGlobal) {
     result = tlsPtr_.jni_env->vm_->DecodeGlobal(ref);
   } else {
@@ -2600,10 +2659,9 @@
     }
   }
 
-  if (UNLIKELY(!expect_null && result == nullptr)) {
-    tlsPtr_.jni_env->vm_->JniAbortF(nullptr, "use of deleted %s %p",
-                                   ToStr<IndirectRefKind>(kind).c_str(), obj);
-  }
+  DCHECK(expect_null || result != nullptr)
+      << "use of deleted " << ToStr<IndirectRefKind>(kind).c_str()
+      << " " << static_cast<const void*>(obj);
   return result;
 }
 
@@ -2716,16 +2774,15 @@
   DISALLOW_COPY_AND_ASSIGN(FetchStackTraceVisitor);
 };
 
-template<bool kTransactionActive>
 class BuildInternalStackTraceVisitor : public StackVisitor {
  public:
-  BuildInternalStackTraceVisitor(Thread* self, Thread* thread, int skip_depth)
+  BuildInternalStackTraceVisitor(Thread* self, Thread* thread, uint32_t skip_depth)
       : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
         self_(self),
         skip_depth_(skip_depth),
         pointer_size_(Runtime::Current()->GetClassLinker()->GetImagePointerSize()) {}
 
-  bool Init(int depth) REQUIRES_SHARED(Locks::mutator_lock_) ACQUIRE(Roles::uninterruptible_) {
+  bool Init(uint32_t depth) REQUIRES_SHARED(Locks::mutator_lock_) ACQUIRE(Roles::uninterruptible_) {
     // Allocate method trace as an object array where the first element is a pointer array that
     // contains the ArtMethod pointers and dex PCs. The rest of the elements are the declaring
     // class of the ArtMethod pointers.
@@ -2736,8 +2793,8 @@
     // The first element is the methods and dex pc array, the other elements are declaring classes
     // for the methods to ensure classes in the stack trace don't get unloaded.
     Handle<mirror::ObjectArray<mirror::Object>> trace(
-        hs.NewHandle(
-            mirror::ObjectArray<mirror::Object>::Alloc(hs.Self(), array_class, depth + 1)));
+        hs.NewHandle(mirror::ObjectArray<mirror::Object>::Alloc(
+            hs.Self(), array_class, static_cast<int32_t>(depth) + 1)));
     if (trace == nullptr) {
       // Acquire uninterruptible_ in all paths.
       self_->StartAssertNoThreadSuspension("Building internal stack trace");
@@ -2752,7 +2809,7 @@
       self_->AssertPendingOOMException();
       return false;
     }
-    trace->Set(0, methods_and_pcs);
+    trace->Set</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(0, methods_and_pcs);
     trace_ = trace.Get();
     // If We are called from native, use non-transactional mode.
     CHECK(last_no_suspend_cause == nullptr) << last_no_suspend_cause;
@@ -2780,15 +2837,15 @@
   }
 
   void AddFrame(ArtMethod* method, uint32_t dex_pc) REQUIRES_SHARED(Locks::mutator_lock_) {
-    ObjPtr<mirror::PointerArray> trace_methods_and_pcs = GetTraceMethodsAndPCs();
-    trace_methods_and_pcs->SetElementPtrSize<kTransactionActive>(count_, method, pointer_size_);
-    trace_methods_and_pcs->SetElementPtrSize<kTransactionActive>(
-        trace_methods_and_pcs->GetLength() / 2 + count_,
-        dex_pc,
-        pointer_size_);
+    ObjPtr<mirror::PointerArray> methods_and_pcs = GetTraceMethodsAndPCs();
+    methods_and_pcs->SetElementPtrSize</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+        count_, method, pointer_size_);
+    methods_and_pcs->SetElementPtrSize</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+        static_cast<uint32_t>(methods_and_pcs->GetLength()) / 2 + count_, dex_pc, pointer_size_);
     // Save the declaring class of the method to ensure that the declaring classes of the methods
     // do not get unloaded while the stack trace is live.
-    trace_->Set(count_ + 1, method->GetDeclaringClass());
+    trace_->Set</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
+        static_cast<int32_t>(count_) + 1, method->GetDeclaringClass());
     ++count_;
   }
 
@@ -2803,13 +2860,14 @@
  private:
   Thread* const self_;
   // How many more frames to skip.
-  int32_t skip_depth_;
+  uint32_t skip_depth_;
   // Current position down stack trace.
   uint32_t count_ = 0;
   // An object array where the first element is a pointer array that contains the ArtMethod
-  // pointers on the stack and dex PCs. The rest of the elements are the declaring
-  // class of the ArtMethod pointers. trace_[i+1] contains the declaring class of the ArtMethod of
-  // the i'th frame.
+  // pointers on the stack and dex PCs. The rest of the elements are the declaring class of
+  // the ArtMethod pointers. trace_[i+1] contains the declaring class of the ArtMethod of the
+  // i'th frame. We're initializing a newly allocated trace, so we do not need to record that
+  // under a transaction. If the transaction is aborted, the whole trace shall be unreachable.
   mirror::ObjectArray<mirror::Object>* trace_ = nullptr;
   // For cross compilation.
   const PointerSize pointer_size_;
@@ -2817,7 +2875,6 @@
   DISALLOW_COPY_AND_ASSIGN(BuildInternalStackTraceVisitor);
 };
 
-template<bool kTransactionActive>
 jobject Thread::CreateInternalStackTrace(const ScopedObjectAccessAlreadyRunnable& soa) const {
   // Compute depth of stack, save frames if possible to avoid needing to recompute many.
   constexpr size_t kMaxSavedFrames = 256;
@@ -2830,9 +2887,8 @@
   const uint32_t skip_depth = count_visitor.GetSkipDepth();
 
   // Build internal stack trace.
-  BuildInternalStackTraceVisitor<kTransactionActive> build_trace_visitor(soa.Self(),
-                                                                         const_cast<Thread*>(this),
-                                                                         skip_depth);
+  BuildInternalStackTraceVisitor build_trace_visitor(
+      soa.Self(), const_cast<Thread*>(this), skip_depth);
   if (!build_trace_visitor.Init(depth)) {
     return nullptr;  // Allocation failed.
   }
@@ -2858,10 +2914,6 @@
   }
   return soa.AddLocalReference<jobject>(trace);
 }
-template jobject Thread::CreateInternalStackTrace<false>(
-    const ScopedObjectAccessAlreadyRunnable& soa) const;
-template jobject Thread::CreateInternalStackTrace<true>(
-    const ScopedObjectAccessAlreadyRunnable& soa) const;
 
 bool Thread::IsExceptionThrownByCurrentMethod(ObjPtr<mirror::Throwable> exception) const {
   // Only count the depth since we do not pass a stack frame array as an argument.
@@ -2900,7 +2952,7 @@
       // Make the line_number field of StackTraceElement hold the dex pc.
       // source_name_object is intentionally left null if we failed to map the dex pc to
       // a line number (most probably because there is no debug info). See b/30183883.
-      line_number = dex_pc;
+      line_number = static_cast<int32_t>(dex_pc);
     } else {
       if (source_file != nullptr) {
         source_name_object.Assign(mirror::String::AllocFromModifiedUtf8(soa.Self(), source_file));
@@ -2949,7 +3001,7 @@
   } else {
     // Create java_trace array and place in local reference table
     ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> java_traces =
-        class_linker->AllocStackTraceElementArray(soa.Self(), depth);
+        class_linker->AllocStackTraceElementArray(soa.Self(), static_cast<size_t>(depth));
     if (java_traces == nullptr) {
       return nullptr;
     }
@@ -2960,7 +3012,7 @@
     *stack_depth = depth;
   }
 
-  for (int32_t i = 0; i < depth; ++i) {
+  for (uint32_t i = 0; i < static_cast<uint32_t>(depth); ++i) {
     ObjPtr<mirror::ObjectArray<mirror::Object>> decoded_traces =
         soa.Decode<mirror::Object>(internal)->AsObjectArray<mirror::Object>();
     // Methods and dex PC trace is element 0.
@@ -2970,13 +3022,14 @@
     // Prepare parameters for StackTraceElement(String cls, String method, String file, int line)
     ArtMethod* method = method_trace->GetElementPtrSize<ArtMethod*>(i, kRuntimePointerSize);
     uint32_t dex_pc = method_trace->GetElementPtrSize<uint32_t>(
-        i + method_trace->GetLength() / 2, kRuntimePointerSize);
+        i + static_cast<uint32_t>(method_trace->GetLength()) / 2, kRuntimePointerSize);
     const ObjPtr<mirror::StackTraceElement> obj = CreateStackTraceElement(soa, method, dex_pc);
     if (obj == nullptr) {
       return nullptr;
     }
     // We are called from native: use non-transactional mode.
-    soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>>(result)->Set<false>(i, obj);
+    soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>>(result)->Set<false>(
+        static_cast<int32_t>(i), obj);
   }
   return result;
 }
@@ -3115,7 +3168,7 @@
         soa.Self(), h_aste_class.Get(), "blockedOn", "Ljava/lang/Object;");
   DCHECK(blocked_on_field != nullptr);
 
-  size_t length = dumper.stack_trace_elements_.size();
+  int32_t length = static_cast<int32_t>(dumper.stack_trace_elements_.size());
   ObjPtr<mirror::ObjectArray<mirror::Object>> array =
       mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), h_aste_array_class.Get(), length);
   if (array == nullptr) {
@@ -3128,7 +3181,7 @@
   MutableHandle<mirror::Object> handle(hs.NewHandle<mirror::Object>(nullptr));
   MutableHandle<mirror::ObjectArray<mirror::Object>> handle2(
       hs.NewHandle<mirror::ObjectArray<mirror::Object>>(nullptr));
-  for (size_t i = 0; i != length; ++i) {
+  for (size_t i = 0; i != static_cast<size_t>(length); ++i) {
     handle.Assign(h_aste_class->AllocObject(soa.Self()));
     if (handle == nullptr) {
       soa.Self()->AssertPendingOOMException();
@@ -3141,9 +3194,8 @@
 
     // Create locked-on array.
     if (!dumper.lock_objects_[i].empty()) {
-      handle2.Assign(mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(),
-                                                                h_o_array_class.Get(),
-                                                                dumper.lock_objects_[i].size()));
+      handle2.Assign(mirror::ObjectArray<mirror::Object>::Alloc(
+          soa.Self(), h_o_array_class.Get(), static_cast<int32_t>(dumper.lock_objects_[i].size())));
       if (handle2 == nullptr) {
         soa.Self()->AssertPendingOOMException();
         return nullptr;
@@ -3169,7 +3221,7 @@
     }
 
     ScopedLocalRef<jobject> elem(soa.Env(), soa.AddLocalReference<jobject>(handle.Get()));
-    soa.Env()->SetObjectArrayElement(result.get(), i, elem.get());
+    soa.Env()->SetObjectArrayElement(result.get(), static_cast<jsize>(i), elem.get());
     DCHECK(!soa.Self()->IsExceptionPending());
   }
 
@@ -3210,6 +3262,16 @@
   DCHECK_EQ(this, Thread::Current());
   ScopedObjectAccessUnchecked soa(this);
   StackHandleScope<3> hs(soa.Self());
+
+  // Disable public sdk checks if we need to throw exceptions.
+  // The checks are only used in AOT compilation and may block (exception) class
+  // initialization if it needs access to private fields (e.g. serialVersionUID).
+  //
+  // Since throwing an exception will EnsureInitialization and the public sdk may
+  // block that, disable the checks. It's ok to do so, because the thrown exceptions
+  // are not part of the application code that needs to verified.
+  ScopedDisablePublicSdkChecker sdpsc;
+
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetCurrentClassLoader(soa.Self())));
   ScopedLocalRef<jobject> cause(GetJniEnv(), soa.AddLocalReference<jobject>(GetException()));
   ClearException();
@@ -3278,10 +3340,7 @@
     if (cause.get() != nullptr) {
       exception->SetCause(DecodeJObject(cause.get())->AsThrowable());
     }
-    ScopedLocalRef<jobject> trace(GetJniEnv(),
-                                  Runtime::Current()->IsActiveTransaction()
-                                      ? CreateInternalStackTrace<true>(soa)
-                                      : CreateInternalStackTrace<false>(soa));
+    ScopedLocalRef<jobject> trace(GetJniEnv(), CreateInternalStackTrace(soa));
     if (trace.get() != nullptr) {
       exception->SetStackState(DecodeJObject(trace.get()).Ptr());
     }
@@ -3817,8 +3876,63 @@
     ArtMethod* m = *cur_quick_frame;
     VisitDeclaringClass(m);
 
-    // Process register map (which native and runtime methods don't have)
-    if (!m->IsNative() && !m->IsRuntimeMethod() && (!m->IsProxyMethod() || m->IsConstructor())) {
+    if (m->IsNative()) {
+      // TODO: Spill the `this` reference in the AOT-compiled String.charAt()
+      // slow-path for throwing SIOOBE, so that we can remove this carve-out.
+      if (UNLIKELY(m->IsIntrinsic()) &&
+          m->GetIntrinsic() == enum_cast<uint32_t>(Intrinsics::kStringCharAt)) {
+        // The String.charAt() method is AOT-compiled with an intrinsic implementation
+        // instead of a JNI stub. It has a slow path that constructs a runtime frame
+        // for throwing SIOOBE and in that path we do not get the `this` pointer
+        // spilled on the stack, so there is nothing to visit. We can distinguish
+        // this from the GenericJni path by checking that the PC is in the boot image
+        // (PC shall be known thanks to the runtime frame for throwing SIOOBE).
+        // Note that JIT does not emit that intrinic implementation.
+        const void* pc = reinterpret_cast<const void*>(GetCurrentQuickFramePc());
+        if (pc != 0u && Runtime::Current()->GetHeap()->IsInBootImageOatFile(pc)) {
+          return;
+        }
+      }
+      // Native methods spill their arguments to the reserved vregs in the caller's frame
+      // and use pointers to these stack references as jobject, jclass, jarray, etc.
+      // Note: We can come here for a @CriticalNative method when it needs to resolve the
+      // target native function but there would be no references to visit below.
+      const size_t frame_size = GetCurrentQuickFrameInfo().FrameSizeInBytes();
+      const size_t method_pointer_size = static_cast<size_t>(kRuntimePointerSize);
+      uint32_t* current_vreg = reinterpret_cast<uint32_t*>(
+          reinterpret_cast<uint8_t*>(cur_quick_frame) + frame_size + method_pointer_size);
+      auto visit = [&]() REQUIRES_SHARED(Locks::mutator_lock_) {
+        auto* ref_addr = reinterpret_cast<StackReference<mirror::Object>*>(current_vreg);
+        mirror::Object* ref = ref_addr->AsMirrorPtr();
+        if (ref != nullptr) {
+          mirror::Object* new_ref = ref;
+          visitor_(&new_ref, /* vreg= */ JavaFrameRootInfo::kNativeReferenceArgument, this);
+          if (ref != new_ref) {
+            ref_addr->Assign(new_ref);
+          }
+        }
+      };
+      const char* shorty = m->GetShorty();
+      if (!m->IsStatic()) {
+        visit();
+        current_vreg += 1u;
+      }
+      for (shorty += 1u; *shorty != 0; ++shorty) {
+        switch (*shorty) {
+          case 'D':
+          case 'J':
+            current_vreg += 2u;
+            break;
+          case 'L':
+            visit();
+            FALLTHROUGH_INTENDED;
+          default:
+            current_vreg += 1u;
+            break;
+        }
+      }
+    } else if (!m->IsRuntimeMethod() && (!m->IsProxyMethod() || m->IsConstructor())) {
+      // Process register map (which native, runtime and proxy methods don't have)
       const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
       DCHECK(method_header->IsOptimized());
       StackReference<mirror::Object>* vreg_base =
@@ -3849,7 +3963,7 @@
       }
       // Visit callee-save registers that hold pointers.
       uint32_t register_mask = code_info.GetRegisterMaskOf(map);
-      for (size_t i = 0; i < BitSizeOf<uint32_t>(); ++i) {
+      for (uint32_t i = 0; i < BitSizeOf<uint32_t>(); ++i) {
         if (register_mask & (1 << i)) {
           mirror::Object** ref_addr = reinterpret_cast<mirror::Object**>(GetGPRAddress(i));
           if (kIsDebugBuild && ref_addr == nullptr) {
@@ -4012,7 +4126,7 @@
 
 template <bool kPrecise>
 void Thread::VisitRoots(RootVisitor* visitor) {
-  const pid_t thread_id = GetThreadId();
+  const uint32_t thread_id = GetThreadId();
   visitor->VisitRootIfNonNull(&tlsPtr_.opeer, RootInfo(kRootThreadObject, thread_id));
   if (tlsPtr_.exception != nullptr && tlsPtr_.exception != GetDeoptimizationException()) {
     visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&tlsPtr_.exception),
@@ -4166,6 +4280,15 @@
 }
 
 void Thread::ResetTlab() {
+  gc::Heap* const heap = Runtime::Current()->GetHeap();
+  if (heap->GetHeapSampler().IsEnabled()) {
+    // Note: We always ResetTlab before SetTlab, therefore we can do the sample
+    // offset adjustment here.
+    heap->AdjustSampleOffset(GetTlabPosOffset());
+    VLOG(heap) << "JHP: ResetTlab, Tid: " << GetTid()
+               << " adjustment = "
+               << (tlsPtr_.thread_local_pos - tlsPtr_.thread_local_start);
+  }
   SetTlab(nullptr, nullptr, nullptr);
 }
 
@@ -4326,14 +4449,14 @@
 }
 
 void Thread::SetNativePriority(int new_priority) {
-  PaletteStatus status = PaletteSchedSetPriority(GetTid(), new_priority);
-  CHECK(status == PaletteStatus::kOkay || status == PaletteStatus::kCheckErrno);
+  palette_status_t status = PaletteSchedSetPriority(GetTid(), new_priority);
+  CHECK(status == PALETTE_STATUS_OK || status == PALETTE_STATUS_CHECK_ERRNO);
 }
 
 int Thread::GetNativePriority() const {
   int priority = 0;
-  PaletteStatus status = PaletteSchedGetPriority(GetTid(), &priority);
-  CHECK(status == PaletteStatus::kOkay || status == PaletteStatus::kCheckErrno);
+  palette_status_t status = PaletteSchedGetPriority(GetTid(), &priority);
+  CHECK(status == PALETTE_STATUS_OK || status == PALETTE_STATUS_CHECK_ERRNO);
   return priority;
 }
 
@@ -4366,3 +4489,5 @@
 }
 
 }  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
diff --git a/runtime/thread.h b/runtime/thread.h
index 7129526..7a40802 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -36,6 +36,7 @@
 #include "handle.h"
 #include "handle_scope.h"
 #include "interpreter/interpreter_cache.h"
+#include "javaheapprof/javaheapsampler.h"
 #include "jvalue.h"
 #include "managed_stack.h"
 #include "offsets.h"
@@ -251,10 +252,6 @@
     return tls32_.user_code_suspend_count;
   }
 
-  int GetDebugSuspendCount() const REQUIRES(Locks::thread_suspend_count_lock_) {
-    return tls32_.debug_suspend_count;
-  }
-
   bool IsSuspended() const {
     union StateAndFlags state_and_flags;
     state_and_flags.as_int = tls32_.state_and_flags.as_int;
@@ -283,13 +280,18 @@
       WARN_UNUSED
       REQUIRES(Locks::thread_suspend_count_lock_);
 
-  // Requests a checkpoint closure to run on another thread. The closure will be run when the thread
-  // gets suspended. This will return true if the closure was added and will (eventually) be
-  // executed. It returns false otherwise.
+  // Requests a checkpoint closure to run on another thread. The closure will be run when the
+  // thread notices the request, either in an explicit runtime CheckSuspend() call, or in a call
+  // originating from a compiler generated suspend point check. This returns true if the closure
+  // was added and will (eventually) be executed. It returns false otherwise.
   //
-  // Since multiple closures can be queued and some closures can delay other threads from running no
-  // closure should attempt to suspend another thread while running.
+  // Since multiple closures can be queued and some closures can delay other threads from running,
+  // no closure should attempt to suspend another thread while running.
   // TODO We should add some debug option that verifies this.
+  //
+  // This guarantees that the RequestCheckpoint invocation happens-before the function invocation:
+  // RequestCheckpointFunction holds thread_suspend_count_lock_, and RunCheckpointFunction
+  // acquires it.
   bool RequestCheckpoint(Closure* function)
       REQUIRES(Locks::thread_suspend_count_lock_);
 
@@ -638,7 +640,6 @@
 
   // Create the internal representation of a stack trace, that is more time
   // and space efficient to compute than the StackTraceElement[].
-  template<bool kTransactionActive>
   jobject CreateInternalStackTrace(const ScopedObjectAccessAlreadyRunnable& soa) const
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -689,6 +690,13 @@
   }
 
   template<PointerSize pointer_size>
+  static constexpr ThreadOffset<pointer_size> WeakRefAccessEnabledOffset() {
+    return ThreadOffset<pointer_size>(
+        OFFSETOF_MEMBER(Thread, tls32_) +
+        OFFSETOF_MEMBER(tls_32bit_sized_values, weak_ref_access_enabled));
+  }
+
+  template<PointerSize pointer_size>
   static constexpr ThreadOffset<pointer_size> ThreadFlagsOffset() {
     return ThreadOffset<pointer_size>(
         OFFSETOF_MEMBER(Thread, tls32_) +
@@ -894,22 +902,22 @@
         ManagedStack::TopShadowFrameOffset());
   }
 
-  // Is the given obj in this thread's stack indirect reference table?
-  bool HandleScopeContains(jobject obj) const;
+  // Is the given obj in one of this thread's JNI transition frames?
+  bool IsJniTransitionReference(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void HandleScopeVisitRoots(RootVisitor* visitor, pid_t thread_id)
+  void HandleScopeVisitRoots(RootVisitor* visitor, uint32_t thread_id)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  BaseHandleScope* GetTopHandleScope() {
+  BaseHandleScope* GetTopHandleScope() REQUIRES_SHARED(Locks::mutator_lock_) {
     return tlsPtr_.top_handle_scope;
   }
 
-  void PushHandleScope(BaseHandleScope* handle_scope) {
+  void PushHandleScope(BaseHandleScope* handle_scope) REQUIRES_SHARED(Locks::mutator_lock_) {
     DCHECK_EQ(handle_scope->GetLink(), tlsPtr_.top_handle_scope);
     tlsPtr_.top_handle_scope = handle_scope;
   }
 
-  BaseHandleScope* PopHandleScope() {
+  BaseHandleScope* PopHandleScope() REQUIRES_SHARED(Locks::mutator_lock_) {
     BaseHandleScope* handle_scope = tlsPtr_.top_handle_scope;
     DCHECK(handle_scope != nullptr);
     tlsPtr_.top_handle_scope = tlsPtr_.top_handle_scope->GetLink();
@@ -1143,13 +1151,18 @@
     return tls32_.use_mterp.load();
   }
 
-  void ResetQuickAllocEntryPointsForThread(bool is_marking);
+  void ResetQuickAllocEntryPointsForThread();
 
   // Returns the remaining space in the TLAB.
   size_t TlabSize() const {
     return tlsPtr_.thread_local_end - tlsPtr_.thread_local_pos;
   }
 
+  // Returns pos offset from start.
+  size_t GetTlabPosOffset() const {
+    return tlsPtr_.thread_local_pos - tlsPtr_.thread_local_start;
+  }
+
   // Returns the remaining space in the TLAB if we were to expand it to maximum capacity.
   size_t TlabRemainingCapacity() const {
     return tlsPtr_.thread_local_limit - tlsPtr_.thread_local_pos;
@@ -1185,6 +1198,9 @@
   // Trigger a suspend check by making the suspend_trigger_ TLS value an invalid pointer.
   // The next time a suspend check is done, it will load from the value at this address
   // and trigger a SIGSEGV.
+  // Only needed if Runtime::implicit_suspend_checks_ is true and fully implemented.  It currently
+  // is always false. Client code currently just looks at the thread flags directly to determine
+  // whether we should suspend, so this call is currently unnecessary.
   void TriggerSuspend() {
     tlsPtr_.suspend_trigger = nullptr;
   }
@@ -1459,7 +1475,7 @@
   // Runs a single checkpoint function. If there are no more pending checkpoint functions it will
   // clear the kCheckpointRequest flag. The caller is responsible for calling this in a loop until
   // the kCheckpointRequest flag is cleared.
-  void RunCheckpointFunction();
+  void RunCheckpointFunction() REQUIRES(!Locks::thread_suspend_count_lock_);
   void RunEmptyCheckpoint();
 
   bool PassActiveSuspendBarriers(Thread* self)
@@ -1483,7 +1499,7 @@
     StateAndFlags() {}
     struct PACKED(4) {
       // Bitfield of flag values. Must be changed atomically so that flag values aren't lost. See
-      // ThreadFlags for bit field meanings.
+      // ThreadFlag for bit field meanings.
       volatile uint16_t flags;
       // Holds the ThreadState. May be changed non-atomically between Suspended (ie not Runnable)
       // transitions. Changing to Runnable requires that the suspend_request be part of the atomic
@@ -1537,7 +1553,6 @@
 
     explicit tls_32bit_sized_values(bool is_daemon)
         : suspend_count(0),
-          debug_suspend_count(0),
           thin_lock_thread_id(0),
           tid(0),
           daemon(is_daemon),
@@ -1565,10 +1580,6 @@
     // at the next poll.
     int suspend_count GUARDED_BY(Locks::thread_suspend_count_lock_);
 
-    // How much of 'suspend_count_' is by request of the debugger, used to set things right
-    // when the debugger detaches. Must be <= suspend_count_.
-    int debug_suspend_count GUARDED_BY(Locks::thread_suspend_count_lock_);
-
     // Thin lock thread id. This is a small integer used by the thin lock implementation.
     // This is not to be confused with the native thread's tid, nor is it the value returned
     // by java.lang.Thread.getId --- this is a distinct value, used only for locking. One
@@ -1872,7 +1883,8 @@
 
   // Custom TLS field that can be used by plugins or the runtime. Should not be accessed directly by
   // compiled code or entrypoints.
-  SafeMap<std::string, std::unique_ptr<TLSData>> custom_tls_ GUARDED_BY(Locks::custom_tls_lock_);
+  SafeMap<std::string, std::unique_ptr<TLSData>, std::less<>> custom_tls_
+      GUARDED_BY(Locks::custom_tls_lock_);
 
 #ifndef __BIONIC__
   __attribute__((tls_model("initial-exec")))
@@ -1894,6 +1906,7 @@
   friend class ThreadList;  // For ~Thread and Destroy.
 
   friend class EntrypointsOrderTest;  // To test the order of tls entries.
+  friend class JniCompilerTest;  // For intercepting JNI entrypoint calls.
 
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
@@ -2028,7 +2041,7 @@
 };
 
 std::ostream& operator<<(std::ostream& os, const Thread& thread);
-std::ostream& operator<<(std::ostream& os, const StackedShadowFrameType& thread);
+std::ostream& operator<<(std::ostream& os, StackedShadowFrameType thread);
 
 }  // namespace art
 
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index 5d1dd55..f8e99e8 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -118,15 +118,6 @@
   return find(list_.begin(), list_.end(), thread) != list_.end();
 }
 
-bool ThreadList::Contains(pid_t tid) {
-  for (const auto& thread : list_) {
-    if (thread->GetTid() == tid) {
-      return true;
-    }
-  }
-  return false;
-}
-
 pid_t ThreadList::GetLockOwner() {
   return Locks::thread_list_lock_->GetExclusiveOwnerTid();
 }
@@ -179,12 +170,12 @@
     char* end;
     pid_t tid = strtol(e->d_name, &end, 10);
     if (!*end) {
-      bool contains;
+      Thread* thread;
       {
         MutexLock mu(self, *Locks::thread_list_lock_);
-        contains = Contains(tid);
+        thread = FindThreadByTid(tid);
       }
-      if (!contains) {
+      if (thread == nullptr) {
         DumpUnattachedThread(os, tid, dump_native_stack);
       }
     }
@@ -326,7 +317,7 @@
   std::vector<Thread*> suspended_count_modified_threads;
   size_t count = 0;
   {
-    // Call a checkpoint function for each thread, threads which are suspend get their checkpoint
+    // Call a checkpoint function for each thread, threads which are suspended get their checkpoint
     // manually called.
     MutexLock mu(self, *Locks::thread_list_lock_);
     MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
@@ -1110,6 +1101,15 @@
   return nullptr;
 }
 
+Thread* ThreadList::FindThreadByTid(int tid) {
+  for (const auto& thread : list_) {
+    if (thread->GetTid() == tid) {
+      return thread;
+    }
+  }
+  return nullptr;
+}
+
 void ThreadList::WaitForOtherNonDaemonThreadsToExit(bool check_no_birth) {
   ScopedTrace trace(__PRETTY_FUNCTION__);
   Thread* self = Thread::Current();
@@ -1222,7 +1222,7 @@
   }
   // Assume all threads are either suspended or somehow wedged.
   // Wait again for all the now "suspended" threads to actually quiesce. (b)
-  static constexpr size_t kDaemonSleepTime = 200 * 1000;
+  static constexpr size_t kDaemonSleepTime = 400'000;
   usleep(kDaemonSleepTime);
   std::list<Thread*> list_copy;
   {
diff --git a/runtime/thread_list.h b/runtime/thread_list.h
index 8fc219b..87a4c8d 100644
--- a/runtime/thread_list.h
+++ b/runtime/thread_list.h
@@ -104,15 +104,20 @@
   // Find an existing thread (or self) by its thread id (not tid).
   Thread* FindThreadByThreadId(uint32_t thread_id) REQUIRES(Locks::thread_list_lock_);
 
+  // Find an existing thread (or self) by its tid (not thread id).
+  Thread* FindThreadByTid(int tid) REQUIRES(Locks::thread_list_lock_);
+
   // Does the thread list still contain the given thread, or one at the same address?
   // Used by Monitor to provide (mostly accurate) debugging information.
   bool Contains(Thread* thread) REQUIRES(Locks::thread_list_lock_);
 
-  // Run a checkpoint on threads, running threads are not suspended but run the checkpoint inside
-  // of the suspend check. Returns how many checkpoints that are expected to run, including for
-  // already suspended threads for b/24191051. Run the callback, if non-null, inside the
-  // thread_list_lock critical section after determining the runnable/suspended states of the
-  // threads.
+  // Run a checkpoint on all threads. Return the total number of threads for which the checkpoint
+  // function has been or will be called.
+  // Running threads are not suspended but run the checkpoint inside of the suspend check. The
+  // return value includes already suspended threads for b/24191051. Runs or requests the
+  // callback, if non-null, inside the thread_list_lock critical section after determining the
+  // runnable/suspended states of the threads. Does not wait for completion of the callbacks in
+  // running threads.
   size_t RunCheckpoint(Closure* checkpoint_function, Closure* callback = nullptr)
       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
 
@@ -189,7 +194,6 @@
   uint32_t AllocThreadId(Thread* self);
   void ReleaseThreadId(Thread* self, uint32_t id) REQUIRES(!Locks::allocated_thread_ids_lock_);
 
-  bool Contains(pid_t tid) REQUIRES(Locks::thread_list_lock_);
   size_t RunCheckpoint(Closure* checkpoint_function, bool includeSuspended)
       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
 
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc
index 2bca5a9..57d7f61 100644
--- a/runtime/thread_pool.cc
+++ b/runtime/thread_pool.cc
@@ -40,29 +40,43 @@
 
 static constexpr bool kMeasureWaitTime = false;
 
+#if defined(__BIONIC__)
+static constexpr bool kUseCustomThreadPoolStack = false;
+#else
+static constexpr bool kUseCustomThreadPoolStack = true;
+#endif
+
 ThreadPoolWorker::ThreadPoolWorker(ThreadPool* thread_pool, const std::string& name,
                                    size_t stack_size)
     : thread_pool_(thread_pool),
       name_(name) {
-  // Add an inaccessible page to catch stack overflow.
-  stack_size += kPageSize;
   std::string error_msg;
-  stack_ = MemMap::MapAnonymous(name.c_str(),
-                                stack_size,
-                                PROT_READ | PROT_WRITE,
-                                /*low_4gb=*/ false,
-                                &error_msg);
-  CHECK(stack_.IsValid()) << error_msg;
-  CHECK_ALIGNED(stack_.Begin(), kPageSize);
-  CheckedCall(mprotect,
-              "mprotect bottom page of thread pool worker stack",
-              stack_.Begin(),
-              kPageSize,
-              PROT_NONE);
+  // On Bionic, we know pthreads will give us a big-enough stack with
+  // a guard page, so don't do anything special on Bionic libc.
+  if (kUseCustomThreadPoolStack) {
+    // Add an inaccessible page to catch stack overflow.
+    stack_size += kPageSize;
+    stack_ = MemMap::MapAnonymous(name.c_str(),
+                                  stack_size,
+                                  PROT_READ | PROT_WRITE,
+                                  /*low_4gb=*/ false,
+                                  &error_msg);
+    CHECK(stack_.IsValid()) << error_msg;
+    CHECK_ALIGNED(stack_.Begin(), kPageSize);
+    CheckedCall(mprotect,
+                "mprotect bottom page of thread pool worker stack",
+                stack_.Begin(),
+                kPageSize,
+                PROT_NONE);
+  }
   const char* reason = "new thread pool worker thread";
   pthread_attr_t attr;
   CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason);
-  CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack_.Begin(), stack_.Size()), reason);
+  if (kUseCustomThreadPoolStack) {
+    CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack_.Begin(), stack_.Size()), reason);
+  } else {
+    CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), reason);
+  }
   CHECK_PTHREAD_CALL(pthread_create, (&pthread_, &attr, &Callback, this), reason);
   CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason);
 }
@@ -84,6 +98,14 @@
 #endif
 }
 
+int ThreadPoolWorker::GetPthreadPriority() {
+#if defined(ART_TARGET_ANDROID)
+  return getpriority(PRIO_PROCESS, pthread_gettid_np(pthread_));
+#else
+  return 0;
+#endif
+}
+
 void ThreadPoolWorker::Run() {
   Thread* self = Thread::Current();
   Task* task = nullptr;
@@ -142,7 +164,7 @@
                        bool create_peers,
                        size_t worker_stack_size)
   : name_(name),
-    task_queue_lock_("task queue lock"),
+    task_queue_lock_("task queue lock", kGenericBottomLock),
     task_queue_condition_("task queue condition", task_queue_lock_),
     completion_condition_("task completion condition", task_queue_lock_),
     started_(false),
@@ -301,4 +323,14 @@
   }
 }
 
+void ThreadPool::CheckPthreadPriority(int priority) {
+#if defined(ART_TARGET_ANDROID)
+  for (ThreadPoolWorker* worker : threads_) {
+    CHECK_EQ(worker->GetPthreadPriority(), priority);
+  }
+#else
+  UNUSED(priority);
+#endif
+}
+
 }  // namespace art
diff --git a/runtime/thread_pool.h b/runtime/thread_pool.h
index b04d4da..b9e5a97 100644
--- a/runtime/thread_pool.h
+++ b/runtime/thread_pool.h
@@ -83,9 +83,12 @@
 
   virtual ~ThreadPoolWorker();
 
-  // Set the "nice" priorty for this worker.
+  // Set the "nice" priority for this worker.
   void SetPthreadPriority(int priority);
 
+  // Get the "nice" priority for this worker.
+  int GetPthreadPriority();
+
   Thread* GetThread() const { return thread_; }
 
  protected:
@@ -160,9 +163,13 @@
   // thread count of the thread pool.
   void SetMaxActiveWorkers(size_t threads) REQUIRES(!task_queue_lock_);
 
-  // Set the "nice" priorty for threads in the pool.
+  // Set the "nice" priority for threads in the pool.
   void SetPthreadPriority(int priority);
 
+  // CHECK that the "nice" priority of threads in the pool is the given
+  // `priority`.
+  void CheckPthreadPriority(int priority);
+
   // Wait for workers to be created.
   void WaitForWorkersToBeCreated();
 
diff --git a/runtime/thread_state.h b/runtime/thread_state.h
index f36bc80..69b5b5d 100644
--- a/runtime/thread_state.h
+++ b/runtime/thread_state.h
@@ -57,7 +57,7 @@
   kNative,                          // RUNNABLE       TS_RUNNING   running in a JNI native method
   kSuspended,                       // RUNNABLE       TS_RUNNING   suspended by GC or debugger
 };
-std::ostream& operator<<(std::ostream& os, const ThreadState& rhs);
+std::ostream& operator<<(std::ostream& os, ThreadState rhs);
 
 }  // namespace art
 
diff --git a/runtime/trace.h b/runtime/trace.h
index eccf157..25bff51 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -57,7 +57,7 @@
   kMethodTracingActive,  // Trace activity synchronous with method progress.
   kSampleProfilingActive,  // Trace activity captured by sampling thread.
 };
-std::ostream& operator<<(std::ostream& os, const TracingMode& rhs);
+std::ostream& operator<<(std::ostream& os, TracingMode rhs);
 
 // File format:
 //     header
diff --git a/runtime/transaction.cc b/runtime/transaction.cc
index 5d9456b..0293d23 100644
--- a/runtime/transaction.cc
+++ b/runtime/transaction.cc
@@ -21,6 +21,7 @@
 #include "aot_class_linker.h"
 #include "base/mutex-inl.h"
 #include "base/stl_util.h"
+#include "dex/descriptors_names.h"
 #include "gc/accounting/card_table-inl.h"
 #include "gc/heap.h"
 #include "gc_root-inl.h"
@@ -90,16 +91,16 @@
 void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
   const bool rethrow = (abort_message == nullptr);
   if (kIsDebugBuild && rethrow) {
-    CHECK(IsAborted()) << "Rethrow " << Transaction::kAbortExceptionDescriptor
+    CHECK(IsAborted()) << "Rethrow " << DescriptorToDot(Transaction::kAbortExceptionDescriptor)
                        << " while transaction is not aborted";
   }
   if (rethrow) {
     // Rethrow an exception with the earlier abort message stored in the transaction.
-    self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
+    self->ThrowNewWrappedException(Transaction::kAbortExceptionDescriptor,
                                    GetAbortMessage().c_str());
   } else {
     // Throw an exception with the given abort message.
-    self->ThrowNewWrappedException(Transaction::kAbortExceptionSignature,
+    self->ThrowNewWrappedException(Transaction::kAbortExceptionDescriptor,
                                    abort_message->c_str());
   }
 }
diff --git a/runtime/transaction.h b/runtime/transaction.h
index 184280f..2fd0e2c 100644
--- a/runtime/transaction.h
+++ b/runtime/transaction.h
@@ -45,8 +45,7 @@
 
 class Transaction final {
  public:
-  static constexpr const char* kAbortExceptionDescriptor = "dalvik.system.TransactionAbortError";
-  static constexpr const char* kAbortExceptionSignature = "Ldalvik/system/TransactionAbortError;";
+  static constexpr const char* kAbortExceptionDescriptor = "Ldalvik/system/TransactionAbortError;";
 
   Transaction(bool strict, mirror::Class* root);
   ~Transaction();
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 74725c2..ee7c591 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -54,7 +54,7 @@
     ASSERT_TRUE(h_klass->IsInitialized());
 
     h_klass.Assign(class_linker_->FindSystemClass(soa.Self(),
-                                                  Transaction::kAbortExceptionSignature));
+                                                  Transaction::kAbortExceptionDescriptor));
     ASSERT_TRUE(h_klass != nullptr);
     class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
     ASSERT_TRUE(h_klass->IsInitialized());
@@ -63,13 +63,13 @@
     h_klass.Assign(class_linker_->FindClass(soa.Self(), "LTransaction$AbortHelperClass;",
                                             class_loader));
     ASSERT_TRUE(h_klass != nullptr);
-    class_linker_->VerifyClass(soa.Self(), h_klass);
+    class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
     ASSERT_TRUE(h_klass->IsVerified());
 
     // Load and verify tested class.
     h_klass.Assign(class_linker_->FindClass(soa.Self(), tested_class_signature, class_loader));
     ASSERT_TRUE(h_klass != nullptr);
-    class_linker_->VerifyClass(soa.Self(), h_klass);
+    class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
     ASSERT_TRUE(h_klass->IsVerified());
 
     ClassStatus old_status = h_klass->GetStatus();
@@ -543,7 +543,7 @@
       hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$EmptyStatic;",
                                             class_loader)));
   ASSERT_TRUE(h_klass != nullptr);
-  class_linker_->VerifyClass(soa.Self(), h_klass);
+  class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
   ASSERT_TRUE(h_klass->IsVerified());
 
   EnterTransactionMode();
@@ -566,7 +566,7 @@
       hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;",
                                             class_loader)));
   ASSERT_TRUE(h_klass != nullptr);
-  class_linker_->VerifyClass(soa.Self(), h_klass);
+  class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
   ASSERT_TRUE(h_klass->IsVerified());
 
   EnterTransactionMode();
@@ -599,6 +599,18 @@
   testTransactionAbort("LTransaction$MultipleNativeCallAbortClass;");
 }
 
+// Tests failing class initialization due to Class.forName() not finding the class,
+// even if an "all" catch handler catches the exception thrown when aborting the transaction.
+TEST_F(TransactionTest, CatchClassForNameAbortClass) {
+  testTransactionAbort("LTransaction$CatchClassForNameAbortClass;");
+}
+
+// Same as CatchClassForNameAbortClass but the class initializer tries to do the work twice.
+// This would trigger a DCHECK() if we continued executing bytecode with an aborted transaction.
+TEST_F(TransactionTest, CatchClassForNameAbortClassTwice) {
+  testTransactionAbort("LTransaction$CatchClassForNameAbortClassTwice;");
+}
+
 // Tests failing class initialization due to allocating instance of finalizable class.
 TEST_F(TransactionTest, FinalizableAbortClass) {
   testTransactionAbort("LTransaction$FinalizableAbortClass;");
@@ -655,31 +667,35 @@
   ASSERT_TRUE(instance_fields_test_object != nullptr);
   ASSERT_FALSE(heap->ObjectIsInBootImageSpace(instance_fields_test_object.Get()));
 
-  Handle<mirror::Class> long_array_dim2_class = hs.NewHandle(
-      class_linker_->FindClass(soa.Self(), "[[J", class_loader));
-  ASSERT_TRUE(long_array_dim2_class != nullptr);
-  ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array_dim2_class.Get()));
-  ASSERT_TRUE(heap->ObjectIsInBootImageSpace(long_array_dim2_class->GetComponentType()));
-  Handle<mirror::Array> long_array_dim2 = hs.NewHandle(mirror::Array::Alloc(
+  // The `long[].class` should be in the boot image but `long[][][].class` should not.
+  // (We have seen `long[][].class` both present and missing from the boot image,
+  // depending on the libcore code, so we do not use it for this test.)
+  Handle<mirror::Class> long_array_dim3_class = hs.NewHandle(
+      class_linker_->FindClass(soa.Self(), "[[[J", class_loader));
+  ASSERT_TRUE(long_array_dim3_class != nullptr);
+  ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array_dim3_class.Get()));
+  ASSERT_TRUE(heap->ObjectIsInBootImageSpace(
+      long_array_dim3_class->GetComponentType()->GetComponentType()));
+  Handle<mirror::Array> long_array_dim3 = hs.NewHandle(mirror::Array::Alloc(
       soa.Self(),
-      long_array_dim2_class.Get(),
+      long_array_dim3_class.Get(),
       /*component_count=*/ 1,
-      long_array_dim2_class->GetComponentSizeShift(),
+      long_array_dim3_class->GetComponentSizeShift(),
       heap->GetCurrentAllocator()));
-  ASSERT_TRUE(long_array_dim2 != nullptr);
-  ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array_dim2.Get()));
+  ASSERT_TRUE(long_array_dim3 != nullptr);
+  ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array_dim3.Get()));
   Handle<mirror::Array> long_array = hs.NewHandle(mirror::Array::Alloc(
       soa.Self(),
-      long_array_dim2_class->GetComponentType(),
+      long_array_dim3_class->GetComponentType()->GetComponentType(),
       /*component_count=*/ 1,
-      long_array_dim2_class->GetComponentType()->GetComponentSizeShift(),
+      long_array_dim3_class->GetComponentType()->GetComponentType()->GetComponentSizeShift(),
       heap->GetCurrentAllocator()));
   ASSERT_TRUE(long_array != nullptr);
   ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array.Get()));
 
   // Use the Array's IfTable as an array from the boot image.
   Handle<mirror::ObjectArray<mirror::Object>> array_iftable =
-      hs.NewHandle(long_array_dim2_class->GetIfTable());
+      hs.NewHandle(long_array_dim3_class->GetIfTable());
   ASSERT_TRUE(array_iftable != nullptr);
   ASSERT_TRUE(heap->ObjectIsInBootImageSpace(array_iftable.Get()));
 
@@ -698,12 +714,12 @@
   // Instance field or array element not in boot image.
   // Do not check ReadConstraint(), it expects only static fields (checks for class object).
   EXPECT_FALSE(transaction.WriteConstraint(soa.Self(), instance_fields_test_object.Get()));
-  EXPECT_FALSE(transaction.WriteConstraint(soa.Self(), long_array_dim2.Get()));
+  EXPECT_FALSE(transaction.WriteConstraint(soa.Self(), long_array_dim3.Get()));
   // Write value constraints.
   EXPECT_FALSE(transaction.WriteValueConstraint(soa.Self(), static_fields_test_class.Get()));
   EXPECT_FALSE(transaction.WriteValueConstraint(soa.Self(), instance_fields_test_object.Get()));
-  EXPECT_TRUE(transaction.WriteValueConstraint(soa.Self(), long_array_dim2->GetClass()));
-  EXPECT_TRUE(transaction.WriteValueConstraint(soa.Self(), long_array_dim2.Get()));
+  EXPECT_TRUE(transaction.WriteValueConstraint(soa.Self(), long_array_dim3->GetClass()));
+  EXPECT_TRUE(transaction.WriteValueConstraint(soa.Self(), long_array_dim3.Get()));
   EXPECT_FALSE(transaction.WriteValueConstraint(soa.Self(), long_array->GetClass()));
   EXPECT_FALSE(transaction.WriteValueConstraint(soa.Self(), long_array.Get()));
 
@@ -722,7 +738,7 @@
   // Instance field or array element not in boot image.
   // Do not check ReadConstraint(), it expects only static fields (checks for class object).
   EXPECT_FALSE(strict_transaction.WriteConstraint(soa.Self(), instance_fields_test_object.Get()));
-  EXPECT_FALSE(strict_transaction.WriteConstraint(soa.Self(), long_array_dim2.Get()));
+  EXPECT_FALSE(strict_transaction.WriteConstraint(soa.Self(), long_array_dim3.Get()));
   // Static field in the same class.
   EXPECT_FALSE(strict_transaction.WriteConstraint(soa.Self(), static_field_class.Get()));
   EXPECT_FALSE(strict_transaction.ReadConstraint(soa.Self(), static_field_class.Get()));
@@ -731,8 +747,8 @@
   EXPECT_FALSE(
       strict_transaction.WriteValueConstraint(soa.Self(), instance_fields_test_object.Get()));
   // TODO: The following may be revised, see a TODO in Transaction::WriteValueConstraint().
-  EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), long_array_dim2->GetClass()));
-  EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), long_array_dim2.Get()));
+  EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), long_array_dim3->GetClass()));
+  EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), long_array_dim3.Get()));
   EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), long_array->GetClass()));
   EXPECT_FALSE(strict_transaction.WriteValueConstraint(soa.Self(), long_array.Get()));
 }
diff --git a/runtime/utils/dex_cache_arrays_layout-inl.h b/runtime/utils/dex_cache_arrays_layout-inl.h
deleted file mode 100644
index 3512efe..0000000
--- a/runtime/utils/dex_cache_arrays_layout-inl.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2015 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_UTILS_DEX_CACHE_ARRAYS_LAYOUT_INL_H_
-#define ART_RUNTIME_UTILS_DEX_CACHE_ARRAYS_LAYOUT_INL_H_
-
-#include "dex_cache_arrays_layout.h"
-
-#include <android-base/logging.h>
-
-#include "base/bit_utils.h"
-#include "dex/primitive.h"
-#include "gc_root.h"
-#include "mirror/dex_cache.h"
-#include "runtime_globals.h"
-
-namespace art {
-
-inline DexCacheArraysLayout::DexCacheArraysLayout(PointerSize pointer_size,
-                                                  const DexFile::Header& header,
-                                                  uint32_t num_call_sites)
-    : pointer_size_(pointer_size),
-      /* types_offset_ is always 0u, so it's constexpr */
-      methods_offset_(
-          RoundUp(types_offset_ + TypesSize(header.type_ids_size_), MethodsAlignment())),
-      strings_offset_(
-          RoundUp(methods_offset_ + MethodsSize(header.method_ids_size_), StringsAlignment())),
-      fields_offset_(
-          RoundUp(strings_offset_ + StringsSize(header.string_ids_size_), FieldsAlignment())),
-      method_types_offset_(
-          RoundUp(fields_offset_ + FieldsSize(header.field_ids_size_), MethodTypesAlignment())),
-    call_sites_offset_(
-        RoundUp(method_types_offset_ + MethodTypesSize(header.proto_ids_size_),
-                MethodTypesAlignment())),
-      size_(RoundUp(call_sites_offset_ + CallSitesSize(num_call_sites), Alignment())) {
-}
-
-inline DexCacheArraysLayout::DexCacheArraysLayout(PointerSize pointer_size, const DexFile* dex_file)
-    : DexCacheArraysLayout(pointer_size, dex_file->GetHeader(), dex_file->NumCallSiteIds()) {
-}
-
-inline size_t DexCacheArraysLayout::Alignment() const {
-  return Alignment(pointer_size_);
-}
-
-inline constexpr size_t DexCacheArraysLayout::Alignment(PointerSize pointer_size) {
-  // mirror::Type/String/MethodTypeDexCacheType alignment is 8,
-  // i.e. higher than or equal to the pointer alignment.
-  static_assert(alignof(mirror::TypeDexCacheType) == 8,
-                "Expecting alignof(ClassDexCacheType) == 8");
-  static_assert(alignof(mirror::StringDexCacheType) == 8,
-                "Expecting alignof(StringDexCacheType) == 8");
-  static_assert(alignof(mirror::MethodTypeDexCacheType) == 8,
-                "Expecting alignof(MethodTypeDexCacheType) == 8");
-  // This is the same as alignof({Field,Method}DexCacheType) for the given pointer size.
-  return 2u * static_cast<size_t>(pointer_size);
-}
-
-template <typename T>
-constexpr PointerSize GcRootAsPointerSize() {
-  static_assert(sizeof(GcRoot<T>) == 4U, "Unexpected GcRoot size");
-  return PointerSize::k32;
-}
-
-inline size_t DexCacheArraysLayout::TypeOffset(dex::TypeIndex type_idx) const {
-  return types_offset_ + ElementOffset(PointerSize::k64,
-                                       type_idx.index_ % mirror::DexCache::kDexCacheTypeCacheSize);
-}
-
-inline size_t DexCacheArraysLayout::TypesSize(size_t num_elements) const {
-  size_t cache_size = mirror::DexCache::kDexCacheTypeCacheSize;
-  if (num_elements < cache_size) {
-    cache_size = num_elements;
-  }
-  return PairArraySize(GcRootAsPointerSize<mirror::Class>(), cache_size);
-}
-
-inline size_t DexCacheArraysLayout::TypesAlignment() const {
-  return alignof(GcRoot<mirror::Class>);
-}
-
-inline size_t DexCacheArraysLayout::MethodOffset(uint32_t method_idx) const {
-  return methods_offset_ + ElementOffset(pointer_size_, method_idx);
-}
-
-inline size_t DexCacheArraysLayout::MethodsSize(size_t num_elements) const {
-  size_t cache_size = mirror::DexCache::kDexCacheMethodCacheSize;
-  if (num_elements < cache_size) {
-    cache_size = num_elements;
-  }
-  return PairArraySize(pointer_size_, cache_size);
-}
-
-inline size_t DexCacheArraysLayout::MethodsAlignment() const {
-  return 2u * static_cast<size_t>(pointer_size_);
-}
-
-inline size_t DexCacheArraysLayout::StringOffset(uint32_t string_idx) const {
-  uint32_t string_hash = string_idx % mirror::DexCache::kDexCacheStringCacheSize;
-  return strings_offset_ + ElementOffset(PointerSize::k64, string_hash);
-}
-
-inline size_t DexCacheArraysLayout::StringsSize(size_t num_elements) const {
-  size_t cache_size = mirror::DexCache::kDexCacheStringCacheSize;
-  if (num_elements < cache_size) {
-    cache_size = num_elements;
-  }
-  return PairArraySize(GcRootAsPointerSize<mirror::String>(), cache_size);
-}
-
-inline size_t DexCacheArraysLayout::StringsAlignment() const {
-  static_assert(alignof(mirror::StringDexCacheType) == 8,
-                "Expecting alignof(StringDexCacheType) == 8");
-  return alignof(mirror::StringDexCacheType);
-}
-
-inline size_t DexCacheArraysLayout::FieldOffset(uint32_t field_idx) const {
-  uint32_t field_hash = field_idx % mirror::DexCache::kDexCacheFieldCacheSize;
-  return fields_offset_ + 2u * static_cast<size_t>(pointer_size_) * field_hash;
-}
-
-inline size_t DexCacheArraysLayout::FieldsSize(size_t num_elements) const {
-  size_t cache_size = mirror::DexCache::kDexCacheFieldCacheSize;
-  if (num_elements < cache_size) {
-    cache_size = num_elements;
-  }
-  return PairArraySize(pointer_size_, cache_size);
-}
-
-inline size_t DexCacheArraysLayout::FieldsAlignment() const {
-  return 2u * static_cast<size_t>(pointer_size_);
-}
-
-inline size_t DexCacheArraysLayout::MethodTypesSize(size_t num_elements) const {
-  size_t cache_size = mirror::DexCache::kDexCacheMethodTypeCacheSize;
-  if (num_elements < cache_size) {
-    cache_size = num_elements;
-  }
-
-  return ArraySize(PointerSize::k64, cache_size);
-}
-
-inline size_t DexCacheArraysLayout::MethodTypesAlignment() const {
-  static_assert(alignof(mirror::MethodTypeDexCacheType) == 8,
-                "Expecting alignof(MethodTypeDexCacheType) == 8");
-  return alignof(mirror::MethodTypeDexCacheType);
-}
-
-inline size_t DexCacheArraysLayout::CallSitesSize(size_t num_elements) const {
-  return ArraySize(GcRootAsPointerSize<mirror::CallSite>(), num_elements);
-}
-
-inline size_t DexCacheArraysLayout::CallSitesAlignment() const {
-  return alignof(GcRoot<mirror::CallSite>);
-}
-
-inline size_t DexCacheArraysLayout::ElementOffset(PointerSize element_size, uint32_t idx) {
-  return static_cast<size_t>(element_size) * idx;
-}
-
-inline size_t DexCacheArraysLayout::ArraySize(PointerSize element_size, uint32_t num_elements) {
-  return static_cast<size_t>(element_size) * num_elements;
-}
-
-inline size_t DexCacheArraysLayout::PairArraySize(PointerSize element_size, uint32_t num_elements) {
-  return 2u * static_cast<size_t>(element_size) * num_elements;
-}
-
-}  // namespace art
-
-#endif  // ART_RUNTIME_UTILS_DEX_CACHE_ARRAYS_LAYOUT_INL_H_
diff --git a/runtime/utils/dex_cache_arrays_layout.h b/runtime/utils/dex_cache_arrays_layout.h
deleted file mode 100644
index 6f689f3..0000000
--- a/runtime/utils/dex_cache_arrays_layout.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2015 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_UTILS_DEX_CACHE_ARRAYS_LAYOUT_H_
-#define ART_RUNTIME_UTILS_DEX_CACHE_ARRAYS_LAYOUT_H_
-
-#include "dex/dex_file.h"
-#include "dex/dex_file_types.h"
-
-namespace art {
-
-/**
- * @class DexCacheArraysLayout
- * @details This class provides the layout information for the type, method, field and
- * string arrays for a DexCache with a fixed arrays' layout (such as in the boot image),
- */
-class DexCacheArraysLayout {
- public:
-  // Construct an invalid layout.
-  DexCacheArraysLayout()
-      : /* types_offset_ is always 0u */
-        pointer_size_(kRuntimePointerSize),
-        methods_offset_(0u),
-        strings_offset_(0u),
-        fields_offset_(0u),
-        method_types_offset_(0u),
-        call_sites_offset_(0u),
-        size_(0u) {
-  }
-
-  // Construct a layout for a particular dex file header.
-  DexCacheArraysLayout(PointerSize pointer_size,
-                       const DexFile::Header& header,
-                       uint32_t num_call_sites);
-
-  // Construct a layout for a particular dex file.
-  DexCacheArraysLayout(PointerSize pointer_size, const DexFile* dex_file);
-
-  bool Valid() const {
-    return Size() != 0u;
-  }
-
-  size_t Size() const {
-    return size_;
-  }
-
-  size_t Alignment() const;
-
-  static constexpr size_t Alignment(PointerSize pointer_size);
-
-  size_t TypesOffset() const {
-    return types_offset_;
-  }
-
-  size_t TypeOffset(dex::TypeIndex type_idx) const;
-
-  size_t TypesSize(size_t num_elements) const;
-
-  size_t TypesAlignment() const;
-
-  size_t MethodsOffset() const {
-    return methods_offset_;
-  }
-
-  size_t MethodOffset(uint32_t method_idx) const;
-
-  size_t MethodsSize(size_t num_elements) const;
-
-  size_t MethodsAlignment() const;
-
-  size_t StringsOffset() const {
-    return strings_offset_;
-  }
-
-  size_t StringOffset(uint32_t string_idx) const;
-
-  size_t StringsSize(size_t num_elements) const;
-
-  size_t StringsAlignment() const;
-
-  size_t FieldsOffset() const {
-    return fields_offset_;
-  }
-
-  size_t FieldOffset(uint32_t field_idx) const;
-
-  size_t FieldsSize(size_t num_elements) const;
-
-  size_t FieldsAlignment() const;
-
-  size_t MethodTypesOffset() const {
-    return method_types_offset_;
-  }
-
-  size_t MethodTypesSize(size_t num_elements) const;
-
-  size_t MethodTypesAlignment() const;
-
-  size_t CallSitesOffset() const {
-    return call_sites_offset_;
-  }
-
-  size_t CallSitesSize(size_t num_elements) const;
-
-  size_t CallSitesAlignment() const;
-
- private:
-  static constexpr size_t types_offset_ = 0u;
-  const PointerSize pointer_size_;  // Must be first for construction initialization order.
-  const size_t methods_offset_;
-  const size_t strings_offset_;
-  const size_t fields_offset_;
-  const size_t method_types_offset_;
-  const size_t call_sites_offset_;
-  const size_t size_;
-
-  static size_t ElementOffset(PointerSize element_size, uint32_t idx);
-
-  static size_t ArraySize(PointerSize element_size, uint32_t num_elements);
-  static size_t PairArraySize(PointerSize element_size, uint32_t num_elements);
-};
-
-}  // namespace art
-
-#endif  // ART_RUNTIME_UTILS_DEX_CACHE_ARRAYS_LAYOUT_H_
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index d67a968..29efd40 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -34,65 +34,34 @@
 #include "dex/art_dex_file_loader.h"
 #include "dex/class_accessor-inl.h"
 #include "dex/dex_file_loader.h"
-#include "dex_to_dex_decompiler.h"
 #include "gc/heap.h"
 #include "gc/space/image_space.h"
+#include "mirror/class-inl.h"
 #include "quicken_info.h"
+#include "handle_scope-inl.h"
 #include "runtime.h"
 #include "verifier/verifier_deps.h"
 
 namespace art {
 
-constexpr uint8_t VdexFile::VerifierDepsHeader::kVdexInvalidMagic[4];
-constexpr uint8_t VdexFile::VerifierDepsHeader::kVdexMagic[4];
-constexpr uint8_t VdexFile::VerifierDepsHeader::kVerifierDepsVersion[4];
-constexpr uint8_t VdexFile::VerifierDepsHeader::kDexSectionVersion[4];
-constexpr uint8_t VdexFile::VerifierDepsHeader::kDexSectionVersionEmpty[4];
+constexpr uint8_t VdexFile::VdexFileHeader::kVdexInvalidMagic[4];
+constexpr uint8_t VdexFile::VdexFileHeader::kVdexMagic[4];
+constexpr uint8_t VdexFile::VdexFileHeader::kVdexVersion[4];
 
-bool VdexFile::VerifierDepsHeader::IsMagicValid() const {
+bool VdexFile::VdexFileHeader::IsMagicValid() const {
   return (memcmp(magic_, kVdexMagic, sizeof(kVdexMagic)) == 0);
 }
 
-bool VdexFile::VerifierDepsHeader::IsVerifierDepsVersionValid() const {
-  return (memcmp(verifier_deps_version_, kVerifierDepsVersion, sizeof(kVerifierDepsVersion)) == 0);
+bool VdexFile::VdexFileHeader::IsVdexVersionValid() const {
+  return (memcmp(vdex_version_, kVdexVersion, sizeof(kVdexVersion)) == 0);
 }
 
-bool VdexFile::VerifierDepsHeader::IsDexSectionVersionValid() const {
-  return (memcmp(dex_section_version_, kDexSectionVersion, sizeof(kDexSectionVersion)) == 0) ||
-      (memcmp(dex_section_version_, kDexSectionVersionEmpty, sizeof(kDexSectionVersionEmpty)) == 0);
-}
-
-bool VdexFile::VerifierDepsHeader::HasDexSection() const {
-  return (memcmp(dex_section_version_, kDexSectionVersion, sizeof(kDexSectionVersion)) == 0);
-}
-
-VdexFile::VerifierDepsHeader::VerifierDepsHeader(uint32_t number_of_dex_files,
-                                                 uint32_t verifier_deps_size,
-                                                 bool has_dex_section,
-                                                 uint32_t bootclasspath_checksums_size,
-                                                 uint32_t class_loader_context_size)
-    : number_of_dex_files_(number_of_dex_files),
-      verifier_deps_size_(verifier_deps_size),
-      bootclasspath_checksums_size_(bootclasspath_checksums_size),
-      class_loader_context_size_(class_loader_context_size) {
+VdexFile::VdexFileHeader::VdexFileHeader(bool has_dex_section ATTRIBUTE_UNUSED)
+    : number_of_sections_(static_cast<uint32_t>(VdexSection::kNumberOfSections)) {
   memcpy(magic_, kVdexMagic, sizeof(kVdexMagic));
-  memcpy(verifier_deps_version_, kVerifierDepsVersion, sizeof(kVerifierDepsVersion));
-  if (has_dex_section) {
-    memcpy(dex_section_version_, kDexSectionVersion, sizeof(kDexSectionVersion));
-  } else {
-    memcpy(dex_section_version_, kDexSectionVersionEmpty, sizeof(kDexSectionVersionEmpty));
-  }
+  memcpy(vdex_version_, kVdexVersion, sizeof(kVdexVersion));
   DCHECK(IsMagicValid());
-  DCHECK(IsVerifierDepsVersionValid());
-  DCHECK(IsDexSectionVersionValid());
-}
-
-VdexFile::DexSectionHeader::DexSectionHeader(uint32_t dex_size,
-                                             uint32_t dex_shared_data_size,
-                                             uint32_t quickening_info_size)
-    : dex_size_(dex_size),
-      dex_shared_data_size_(dex_shared_data_size),
-      quickening_info_size_(quickening_info_size) {
+  DCHECK(IsVdexVersionValid());
 }
 
 std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr,
@@ -180,54 +149,61 @@
     return nullptr;
   }
 
-  if (unquicken && vdex->HasDexSection()) {
-    std::vector<std::unique_ptr<const DexFile>> unique_ptr_dex_files;
-    if (!vdex->OpenAllDexFiles(&unique_ptr_dex_files, error_msg)) {
-      return nullptr;
-    }
-    // TODO: It would be nice to avoid doing the return-instruction stuff but then we end up not
-    // being able to tell if we need dequickening later. Instead just get rid of that too.
-    vdex->Unquicken(MakeNonOwningPointerVector(unique_ptr_dex_files),
-                    /* decompile_return_instruction= */ true);
-    // Update the quickening info size to pretend there isn't any.
-    size_t offset = vdex->GetDexSectionHeaderOffset();
-    reinterpret_cast<DexSectionHeader*>(vdex->mmap_.Begin() + offset)->quickening_info_size_ = 0;
-  }
-
   if (!writable) {
-    vdex->AllowWriting(false);
+    Runtime* runtime = Runtime::Current();
+    // The runtime might not be available at this point if we're running
+    // dex2oat or oatdump.
+    if (runtime != nullptr) {
+      size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeVdex();
+      Runtime::MadviseFileForRange(madvise_size_limit,
+                                   vdex->Size(),
+                                   vdex->Begin(),
+                                   vdex->End(),
+                                   vdex_filename);
+    }
   }
 
   return vdex;
 }
 
-const uint8_t* VdexFile::GetNextDexFileData(const uint8_t* cursor) const {
+const uint8_t* VdexFile::GetNextDexFileData(const uint8_t* cursor, uint32_t dex_file_index) const {
   DCHECK(cursor == nullptr || (cursor > Begin() && cursor <= End()));
   if (cursor == nullptr) {
     // Beginning of the iteration, return the first dex file if there is one.
-    return HasDexSection() ? DexBegin() + sizeof(QuickeningTableOffsetType) : nullptr;
+    return HasDexSection() ? DexBegin() : nullptr;
+  } else if (dex_file_index >= GetNumberOfDexFiles()) {
+    return nullptr;
   } else {
     // Fetch the next dex file. Return null if there is none.
     const uint8_t* data = cursor + reinterpret_cast<const DexFile::Header*>(cursor)->file_size_;
     // Dex files are required to be 4 byte aligned. the OatWriter makes sure they are, see
     // OatWriter::SeekToDexFiles.
-    data = AlignUp(data, 4);
-
-    return (data == DexEnd()) ? nullptr : data + sizeof(QuickeningTableOffsetType);
+    return AlignUp(data, 4);
   }
 }
 
-void VdexFile::AllowWriting(bool val) const {
-  CHECK(mmap_.Protect(val ? (PROT_READ | PROT_WRITE) : PROT_READ));
+const uint8_t* VdexFile::GetNextTypeLookupTableData(const uint8_t* cursor,
+                                                    uint32_t dex_file_index) const {
+  if (cursor == nullptr) {
+    // Beginning of the iteration, return the first dex file if there is one.
+    return HasTypeLookupTableSection() ? TypeLookupTableDataBegin() : nullptr;
+  } else if (dex_file_index >= GetNumberOfDexFiles()) {
+    return nullptr;
+  } else {
+    const uint8_t* data = cursor + sizeof(uint32_t) + reinterpret_cast<const uint32_t*>(cursor)[0];
+    // TypeLookupTables are required to be 4 byte aligned. the OatWriter makes sure they are.
+    CHECK_ALIGNED(data, 4);
+    return data;
+  }
 }
 
 bool VdexFile::OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
                                std::string* error_msg) const {
   const ArtDexFileLoader dex_file_loader;
   size_t i = 0;
-  for (const uint8_t* dex_file_start = GetNextDexFileData(nullptr);
+  for (const uint8_t* dex_file_start = GetNextDexFileData(nullptr, i);
        dex_file_start != nullptr;
-       dex_file_start = GetNextDexFileData(dex_file_start), ++i) {
+       dex_file_start = GetNextDexFileData(dex_file_start, ++i)) {
     size_t size = reinterpret_cast<const DexFile::Header*>(dex_file_start)->file_size_;
     // TODO: Supply the location information for a vdex file.
     static constexpr char kVdexLocation[] = "";
@@ -251,128 +227,6 @@
   return true;
 }
 
-void VdexFile::UnquickenInPlace(bool decompile_return_instruction) const {
-  CHECK_NE(mmap_.GetProtect() & PROT_WRITE, 0)
-      << "File not mapped writable. Cannot unquicken! " << mmap_;
-  if (HasDexSection()) {
-    std::vector<std::unique_ptr<const DexFile>> unique_ptr_dex_files;
-    std::string error_msg;
-    if (!OpenAllDexFiles(&unique_ptr_dex_files, &error_msg)) {
-      return;
-    }
-    Unquicken(MakeNonOwningPointerVector(unique_ptr_dex_files),
-              decompile_return_instruction);
-    // Update the quickening info size to pretend there isn't any.
-    size_t offset = GetDexSectionHeaderOffset();
-    reinterpret_cast<DexSectionHeader*>(mmap_.Begin() + offset)->quickening_info_size_ = 0;
-  }
-}
-
-void VdexFile::Unquicken(const std::vector<const DexFile*>& target_dex_files,
-                         bool decompile_return_instruction) const {
-  const uint8_t* source_dex = GetNextDexFileData(nullptr);
-  for (const DexFile* target_dex : target_dex_files) {
-    UnquickenDexFile(*target_dex, source_dex, decompile_return_instruction);
-    source_dex = GetNextDexFileData(source_dex);
-  }
-  DCHECK(source_dex == nullptr);
-}
-
-uint32_t VdexFile::GetQuickeningInfoTableOffset(const uint8_t* source_dex_begin) const {
-  DCHECK_GE(source_dex_begin, DexBegin());
-  DCHECK_LT(source_dex_begin, DexEnd());
-  return reinterpret_cast<const QuickeningTableOffsetType*>(source_dex_begin)[-1];
-}
-
-CompactOffsetTable::Accessor VdexFile::GetQuickenInfoOffsetTable(
-    const uint8_t* source_dex_begin,
-    const ArrayRef<const uint8_t>& quickening_info) const {
-  // The offset a is in preheader right before the dex file.
-  const uint32_t offset = GetQuickeningInfoTableOffset(source_dex_begin);
-  return CompactOffsetTable::Accessor(quickening_info.SubArray(offset).data());
-}
-
-CompactOffsetTable::Accessor VdexFile::GetQuickenInfoOffsetTable(
-    const DexFile& dex_file,
-    const ArrayRef<const uint8_t>& quickening_info) const {
-  return GetQuickenInfoOffsetTable(dex_file.Begin(), quickening_info);
-}
-
-static ArrayRef<const uint8_t> GetQuickeningInfoAt(const ArrayRef<const uint8_t>& quickening_info,
-                                                   uint32_t quickening_offset) {
-  // Subtract offset of one since 0 represents unused and cannot be in the table.
-  ArrayRef<const uint8_t> remaining = quickening_info.SubArray(quickening_offset - 1);
-  return remaining.SubArray(0u, QuickenInfoTable::SizeInBytes(remaining));
-}
-
-void VdexFile::UnquickenDexFile(const DexFile& target_dex_file,
-                                const DexFile& source_dex_file,
-                                bool decompile_return_instruction) const {
-  UnquickenDexFile(
-      target_dex_file, source_dex_file.Begin(), decompile_return_instruction);
-}
-
-void VdexFile::UnquickenDexFile(const DexFile& target_dex_file,
-                                const uint8_t* source_dex_begin,
-                                bool decompile_return_instruction) const {
-  ArrayRef<const uint8_t> quickening_info = GetQuickeningInfo();
-  if (quickening_info.empty()) {
-    // Bail early if there is no quickening info and no need to decompile. This means there is also
-    // no RETURN_VOID to decompile since the empty table takes a non zero amount of space.
-    return;
-  }
-  // Make sure to not unquicken the same code item multiple times.
-  std::unordered_set<const dex::CodeItem*> unquickened_code_item;
-  CompactOffsetTable::Accessor accessor(GetQuickenInfoOffsetTable(source_dex_begin,
-                                                                  quickening_info));
-  for (ClassAccessor class_accessor : target_dex_file.GetClasses()) {
-    for (const ClassAccessor::Method& method : class_accessor.GetMethods()) {
-      const dex::CodeItem* code_item = method.GetCodeItem();
-      if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) {
-        const uint32_t offset = accessor.GetOffset(method.GetIndex());
-        // Offset being 0 means not quickened.
-        if (offset != 0u) {
-          ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset);
-          optimizer::ArtDecompileDEX(
-              target_dex_file,
-              *code_item,
-              quicken_data,
-              decompile_return_instruction);
-        }
-      }
-    }
-  }
-}
-
-ArrayRef<const uint8_t> VdexFile::GetQuickenedInfoOf(const DexFile& dex_file,
-                                                     uint32_t dex_method_idx) const {
-  ArrayRef<const uint8_t> quickening_info = GetQuickeningInfo();
-  if (quickening_info.empty()) {
-    return ArrayRef<const uint8_t>();
-  }
-  CHECK_LT(dex_method_idx, dex_file.NumMethodIds());
-  const uint32_t quickening_offset =
-      GetQuickenInfoOffsetTable(dex_file, quickening_info).GetOffset(dex_method_idx);
-  if (quickening_offset == 0u) {
-    return ArrayRef<const uint8_t>();
-  }
-  return GetQuickeningInfoAt(quickening_info, quickening_offset);
-}
-
-static std::string ComputeBootClassPathChecksumString() {
-  Runtime* const runtime = Runtime::Current();
-  // Do not include boot image extension checksums, use their dex file checksums instead. Unlike
-  // oat files, vdex files do not reference anything in image spaces, so there is no reason why
-  // loading or not loading a boot image extension would affect the validity of the vdex file.
-  // Note: Update of a boot class path module such as conscrypt invalidates the vdex file anyway.
-  ArrayRef<gc::space::ImageSpace* const> image_spaces(runtime->GetHeap()->GetBootImageSpaces());
-  size_t boot_image_components =
-      image_spaces.empty() ? 0u : image_spaces[0]->GetImageHeader().GetComponentCount();
-  return gc::space::ImageSpace::GetBootClassPathChecksums(
-          image_spaces.SubArray(/*pos=*/ 0u, boot_image_components),
-          ArrayRef<const DexFile* const>(runtime->GetClassLinker()->GetBootClassPath()));
-}
-
 static bool CreateDirectories(const std::string& child_path, /* out */ std::string* error_msg) {
   size_t last_slash_pos = child_path.find_last_of('/');
   CHECK_NE(last_slash_pos, std::string::npos) << "Invalid path: " << child_path;
@@ -393,19 +247,47 @@
 bool VdexFile::WriteToDisk(const std::string& path,
                            const std::vector<const DexFile*>& dex_files,
                            const verifier::VerifierDeps& verifier_deps,
-                           const std::string& class_loader_context,
                            std::string* error_msg) {
   std::vector<uint8_t> verifier_deps_data;
   verifier_deps.Encode(dex_files, &verifier_deps_data);
+  uint32_t verifier_deps_size = verifier_deps_data.size();
+  // Add padding so the type lookup tables are 4 byte aligned.
+  uint32_t verifier_deps_with_padding_size = RoundUp(verifier_deps_data.size(), 4);
+  DCHECK_GE(verifier_deps_with_padding_size, verifier_deps_data.size());
+  verifier_deps_data.resize(verifier_deps_with_padding_size, 0);
 
-  std::string boot_checksum = ComputeBootClassPathChecksumString();
-  DCHECK_NE(boot_checksum, "");
+  size_t type_lookup_table_size = 0u;
+  for (const DexFile* dex_file : dex_files) {
+    type_lookup_table_size +=
+        sizeof(uint32_t) + TypeLookupTable::RawDataLength(dex_file->NumClassDefs());
+  }
 
-  VdexFile::VerifierDepsHeader deps_header(dex_files.size(),
-                                           verifier_deps_data.size(),
-                                           /* has_dex_section= */ false,
-                                           boot_checksum.size(),
-                                           class_loader_context.size());
+  VdexFile::VdexFileHeader vdex_header(/* has_dex_section= */ false);
+  VdexFile::VdexSectionHeader sections[static_cast<uint32_t>(VdexSection::kNumberOfSections)];
+
+  // Set checksum section.
+  sections[VdexSection::kChecksumSection].section_kind = VdexSection::kChecksumSection;
+  sections[VdexSection::kChecksumSection].section_offset = GetChecksumsOffset();
+  sections[VdexSection::kChecksumSection].section_size =
+      sizeof(VdexFile::VdexChecksum) * dex_files.size();
+
+  // Set dex section.
+  sections[VdexSection::kDexFileSection].section_kind = VdexSection::kDexFileSection;
+  sections[VdexSection::kDexFileSection].section_offset = 0u;
+  sections[VdexSection::kDexFileSection].section_size = 0u;
+
+  // Set VerifierDeps section.
+  sections[VdexSection::kVerifierDepsSection].section_kind = VdexSection::kVerifierDepsSection;
+  sections[VdexSection::kVerifierDepsSection].section_offset =
+      GetChecksumsOffset() + sections[kChecksumSection].section_size;
+  sections[VdexSection::kVerifierDepsSection].section_size = verifier_deps_size;
+
+  // Set TypeLookupTable section.
+  sections[VdexSection::kTypeLookupTableSection].section_kind =
+      VdexSection::kTypeLookupTableSection;
+  sections[VdexSection::kTypeLookupTableSection].section_offset =
+      sections[VdexSection::kVerifierDepsSection].section_offset + verifier_deps_with_padding_size;
+  sections[VdexSection::kTypeLookupTableSection].section_size = type_lookup_table_size;
 
   if (!CreateDirectories(path, error_msg)) {
     return false;
@@ -417,41 +299,54 @@
     return false;
   }
 
-  if (!out->WriteFully(reinterpret_cast<const char*>(&deps_header), sizeof(deps_header))) {
+  // Write header.
+  if (!out->WriteFully(reinterpret_cast<const char*>(&vdex_header), sizeof(vdex_header))) {
     *error_msg = "Could not write vdex header to " + path;
     out->Unlink();
     return false;
   }
 
+  // Write section infos.
+  if (!out->WriteFully(reinterpret_cast<const char*>(&sections), sizeof(sections))) {
+    *error_msg = "Could not write vdex sections to " + path;
+    out->Unlink();
+    return false;
+  }
+
+  // Write checksum section.
   for (const DexFile* dex_file : dex_files) {
-    const uint32_t* checksum_ptr = &dex_file->GetHeader().checksum_;
+    uint32_t checksum = dex_file->GetLocationChecksum();
+    const uint32_t* checksum_ptr = &checksum;
     static_assert(sizeof(*checksum_ptr) == sizeof(VdexFile::VdexChecksum));
     if (!out->WriteFully(reinterpret_cast<const char*>(checksum_ptr),
                          sizeof(VdexFile::VdexChecksum))) {
       *error_msg = "Could not write dex checksums to " + path;
       out->Unlink();
-    return false;
+      return false;
     }
   }
 
   if (!out->WriteFully(reinterpret_cast<const char*>(verifier_deps_data.data()),
-                       verifier_deps_data.size())) {
+                       verifier_deps_with_padding_size)) {
     *error_msg = "Could not write verifier deps to " + path;
     out->Unlink();
     return false;
   }
 
-  if (!out->WriteFully(boot_checksum.c_str(), boot_checksum.size())) {
-    *error_msg = "Could not write boot classpath checksum to " + path;
-    out->Unlink();
-    return false;
+  size_t written_type_lookup_table_size = 0;
+  for (const DexFile* dex_file : dex_files) {
+    TypeLookupTable type_lookup_table = TypeLookupTable::Create(*dex_file);
+    uint32_t size = type_lookup_table.RawDataLength();
+    DCHECK_ALIGNED(size, 4);
+    if (!out->WriteFully(reinterpret_cast<const char*>(&size), sizeof(uint32_t)) ||
+        !out->WriteFully(reinterpret_cast<const char*>(type_lookup_table.RawData()), size)) {
+      *error_msg = "Could not write type lookup table " + path;
+      out->Unlink();
+      return false;
+    }
+    written_type_lookup_table_size += sizeof(uint32_t) + size;
   }
-
-  if (!out->WriteFully(class_loader_context.c_str(), class_loader_context.size())) {
-    *error_msg = "Could not write class loader context to " + path;
-    out->Unlink();
-    return false;
-  }
+  DCHECK_EQ(written_type_lookup_table_size, type_lookup_table_size);
 
   if (out->FlushClose() != 0) {
     *error_msg = "Could not flush and close " + path;
@@ -464,13 +359,12 @@
 
 bool VdexFile::MatchesDexFileChecksums(const std::vector<const DexFile::Header*>& dex_headers)
     const {
-  const VerifierDepsHeader& header = GetVerifierDepsHeader();
-  if (dex_headers.size() != header.GetNumberOfDexFiles()) {
+  if (dex_headers.size() != GetNumberOfDexFiles()) {
     LOG(WARNING) << "Mismatch of number of dex files in vdex (expected="
-        << header.GetNumberOfDexFiles() << ", actual=" << dex_headers.size() << ")";
+        << GetNumberOfDexFiles() << ", actual=" << dex_headers.size() << ")";
     return false;
   }
-  const VdexChecksum* checksums = header.GetDexChecksumsArray();
+  const VdexChecksum* checksums = GetDexChecksumsArray();
   for (size_t i = 0; i < dex_headers.size(); ++i) {
     if (checksums[i] != dex_headers[i]->checksum_) {
       LOG(WARNING) << "Mismatch of dex file checksum in vdex (index=" << i << ")";
@@ -480,30 +374,144 @@
   return true;
 }
 
-bool VdexFile::MatchesBootClassPathChecksums() const {
-  ArrayRef<const uint8_t> data = GetBootClassPathChecksumData();
-  std::string vdex(reinterpret_cast<const char*>(data.data()), data.size());
-  std::string runtime = ComputeBootClassPathChecksumString();
-  if (vdex == runtime) {
-    return true;
+static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linker,
+                                                        Thread* self,
+                                                        const char* name,
+                                                        Handle<mirror::ClassLoader> class_loader)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  ObjPtr<mirror::Class> result = class_linker->FindClass(self, name, class_loader);
+  if (result == nullptr) {
+    DCHECK(self->IsExceptionPending());
+    self->ClearException();
+  }
+  return result;
+}
+
+static const char* GetStringFromId(const DexFile& dex_file,
+                                   dex::StringIndex string_id,
+                                   uint32_t number_of_extra_strings,
+                                   const uint32_t* extra_strings_offsets,
+                                   const uint8_t* verifier_deps) {
+  uint32_t num_ids_in_dex = dex_file.NumStringIds();
+  if (string_id.index_ < num_ids_in_dex) {
+    return dex_file.StringDataByIdx(string_id);
   } else {
-    LOG(WARNING) << "Mismatch of boot class path checksum in vdex (expected="
-        << vdex << ", actual=" << runtime << ")";
-    return false;
+    CHECK_LT(string_id.index_ - num_ids_in_dex, number_of_extra_strings);
+    uint32_t offset = extra_strings_offsets[string_id.index_ - num_ids_in_dex];
+    return reinterpret_cast<const char*>(verifier_deps) + offset;
   }
 }
 
-bool VdexFile::MatchesClassLoaderContext(const ClassLoaderContext& context) const {
-  ArrayRef<const uint8_t> data = GetClassLoaderContextData();
-  std::string spec(reinterpret_cast<const char*>(data.data()), data.size());
-  ClassLoaderContext::VerificationResult result = context.VerifyClassLoaderContextMatch(spec);
-  if (result != ClassLoaderContext::VerificationResult::kMismatch) {
-    return true;
-  } else {
-    LOG(WARNING) << "Mismatch of class loader context in vdex (expected="
-        << spec << ", actual=" << context.EncodeContextForOatFile("") << ")";
-    return false;
+// Returns an array of offsets where the assignability checks for each class
+// definition are stored.
+static const uint32_t* GetDexFileClassDefs(const uint8_t* verifier_deps, uint32_t index) {
+  uint32_t dex_file_offset = reinterpret_cast<const uint32_t*>(verifier_deps)[index];
+  return reinterpret_cast<const uint32_t*>(verifier_deps + dex_file_offset);
+}
+
+// Returns an array of offsets where extra strings are stored.
+static const uint32_t* GetExtraStringsOffsets(const DexFile& dex_file,
+                                              const uint8_t* verifier_deps,
+                                              const uint32_t* dex_file_class_defs,
+                                              /*out*/ uint32_t* number_of_extra_strings) {
+  // The information for strings is right after dex_file_class_defs, 4-byte
+  // aligned
+  uint32_t end_of_assignability_types = dex_file_class_defs[dex_file.NumClassDefs()];
+  const uint8_t* strings_data_start =
+      AlignUp(verifier_deps + end_of_assignability_types, sizeof(uint32_t));
+  // First entry is the number of extra strings for this dex file.
+  *number_of_extra_strings = *reinterpret_cast<const uint32_t*>(strings_data_start);
+  // Then an array of offsets in `verifier_deps` for the extra strings.
+  return reinterpret_cast<const uint32_t*>(strings_data_start + sizeof(uint32_t));
+}
+
+ClassStatus VdexFile::ComputeClassStatus(Thread* self, Handle<mirror::Class> cls) const {
+  const DexFile& dex_file = cls->GetDexFile();
+  uint16_t class_def_index = cls->GetDexClassDefIndex();
+
+  // Find which dex file index from within the vdex file.
+  uint32_t index = 0;
+  for (; index < GetNumberOfDexFiles(); ++index) {
+    if (dex_file.GetLocationChecksum() == GetLocationChecksum(index)) {
+      break;
+    }
   }
+
+  DCHECK_NE(index, GetNumberOfDexFiles());
+
+  const uint8_t* verifier_deps = GetVerifierDepsData().data();
+  const uint32_t* dex_file_class_defs = GetDexFileClassDefs(verifier_deps, index);
+
+  // Fetch type checks offsets.
+  uint32_t class_def_offset = dex_file_class_defs[class_def_index];
+  if (class_def_offset == verifier::VerifierDeps::kNotVerifiedMarker) {
+    // Return a status that needs re-verification.
+    return ClassStatus::kResolved;
+  }
+  // End offset for this class's type checks. We know there is one and the loop
+  // will terminate.
+  uint32_t end_offset = verifier::VerifierDeps::kNotVerifiedMarker;
+  for (uint32_t i = class_def_index + 1; i < dex_file.NumClassDefs() + 1; ++i) {
+    end_offset = dex_file_class_defs[i];
+    if (end_offset != verifier::VerifierDeps::kNotVerifiedMarker) {
+      break;
+    }
+  }
+  DCHECK_NE(end_offset, verifier::VerifierDeps::kNotVerifiedMarker);
+
+  uint32_t number_of_extra_strings = 0;
+  // Offset where extra strings are stored.
+  const uint32_t* extra_strings_offsets = GetExtraStringsOffsets(dex_file,
+                                                                 verifier_deps,
+                                                                 dex_file_class_defs,
+                                                                 &number_of_extra_strings);
+
+  // Loop over and perform each assignability check.
+  StackHandleScope<3> hs(self);
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(cls->GetClassLoader()));
+  MutableHandle<mirror::Class> source(hs.NewHandle<mirror::Class>(nullptr));
+  MutableHandle<mirror::Class> destination(hs.NewHandle<mirror::Class>(nullptr));
+
+  const uint8_t* cursor = verifier_deps + class_def_offset;
+  const uint8_t* end = verifier_deps + end_offset;
+  while (cursor < end) {
+    uint32_t destination_index;
+    uint32_t source_index;
+    if (UNLIKELY(!DecodeUnsignedLeb128Checked(&cursor, end, &destination_index) ||
+                 !DecodeUnsignedLeb128Checked(&cursor, end, &source_index))) {
+      // Error parsing the data, just return that we are not verified.
+      return ClassStatus::kResolved;
+    }
+    const char* destination_desc = GetStringFromId(dex_file,
+                                                   dex::StringIndex(destination_index),
+                                                   number_of_extra_strings,
+                                                   extra_strings_offsets,
+                                                   verifier_deps);
+    destination.Assign(
+        FindClassAndClearException(class_linker, self, destination_desc, class_loader));
+
+    const char* source_desc = GetStringFromId(dex_file,
+                                              dex::StringIndex(source_index),
+                                              number_of_extra_strings,
+                                              extra_strings_offsets,
+                                              verifier_deps);
+    source.Assign(FindClassAndClearException(class_linker, self, source_desc, class_loader));
+
+    if (destination == nullptr || source == nullptr) {
+      // The interpreter / compiler can handle a missing class.
+      continue;
+    }
+
+    DCHECK(destination->IsResolved() && source->IsResolved());
+    if (!destination->IsAssignableFrom(source.Get())) {
+      // An implicit assignability check is failing in the code, return that the
+      // class is not verified.
+      return ClassStatus::kResolved;
+    }
+  }
+
+  return ClassStatus::kVerifiedNeedsAccessChecks;
 }
 
 }  // namespace art
diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h
index d205904..eb8b817 100644
--- a/runtime/vdex_file.h
+++ b/runtime/vdex_file.h
@@ -24,13 +24,20 @@
 #include "base/macros.h"
 #include "base/mem_map.h"
 #include "base/os.h"
+#include "class_status.h"
 #include "dex/compact_offset_table.h"
 #include "dex/dex_file.h"
 #include "quicken_info.h"
+#include "handle.h"
 
 namespace art {
 
 class ClassLoaderContext;
+class Thread;
+
+namespace mirror {
+class Class;
+}
 
 namespace verifier {
 class VerifierDeps;
@@ -39,73 +46,75 @@
 // VDEX files contain extracted DEX files. The VdexFile class maps the file to
 // memory and provides tools for accessing its individual sections.
 //
+// In the description below, D is the number of dex files.
+//
 // File format:
-//   VdexFile::VerifierDepsHeader    fixed-length header
-//      Dex file checksums
+//   VdexFileHeader    fixed-length header
+//   VdexSectionHeader[kNumberOfSections]
+//
+//   Checksum section
+//     VdexChecksum[D]
 //
 //   Optionally:
-//      VdexFile::DexSectionHeader   fixed-length header
-//
-//      quicken_table_off[0]  offset into QuickeningInfo section for offset table for DEX[0].
-//      DEX[0]                array of the input DEX files, the bytecode may have been quickened.
-//      quicken_table_off[1]
-//      DEX[1]
-//      ...
-//      DEX[D]
+//      DexSection
+//          DEX[0]                array of the input DEX files
+//          DEX[1]
+//          ...
+//          DEX[D-1]
 //
 //   VerifierDeps
-//      uint8[D][]                 verification dependencies
-//
-//   Optionally:
-//      QuickeningInfo
-//        uint8[D][]                  quickening data
-//        uint32[D][]                 quickening data offset tables
+//      4-byte alignment
+//      uint32[D]                  DexFileDeps offsets for each dex file
+//      DexFileDeps[D][]           verification dependencies
+//        4-byte alignment
+//        uint32[class_def_size]     TypeAssignability offsets (kNotVerifiedMarker for a class
+//                                        that isn't verified)
+//        uint32                     Offset of end of AssignabilityType sets
+//        uint8[]                    AssignabilityType sets
+//        4-byte alignment
+//        uint32                     Number of strings
+//        uint32[]                   String data offsets for each string
+//        uint8[]                    String data
+
+
+enum VdexSection : uint32_t {
+  kChecksumSection = 0,
+  kDexFileSection = 1,
+  kVerifierDepsSection = 2,
+  kTypeLookupTableSection = 3,
+  kNumberOfSections = 4,
+};
 
 class VdexFile {
  public:
   using VdexChecksum = uint32_t;
-  using QuickeningTableOffsetType = uint32_t;
 
-  struct VerifierDepsHeader {
+  struct VdexSectionHeader {
+    VdexSection section_kind;
+    uint32_t section_offset;
+    uint32_t section_size;
+
+    VdexSectionHeader(VdexSection kind, uint32_t offset, uint32_t size)
+        : section_kind(kind), section_offset(offset), section_size(size) {}
+
+    VdexSectionHeader() {}
+  };
+
+  struct VdexFileHeader {
    public:
-    VerifierDepsHeader(uint32_t number_of_dex_files_,
-                       uint32_t verifier_deps_size,
-                       bool has_dex_section,
-                       uint32_t bootclasspath_checksums_size = 0,
-                       uint32_t class_loader_context_size = 0);
+    explicit VdexFileHeader(bool has_dex_section);
 
     const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); }
-    const char* GetVerifierDepsVersion() const {
-      return reinterpret_cast<const char*>(verifier_deps_version_);
+    const char* GetVdexVersion() const {
+      return reinterpret_cast<const char*>(vdex_version_);
     }
-    const char* GetDexSectionVersion() const {
-      return reinterpret_cast<const char*>(dex_section_version_);
+    uint32_t GetNumberOfSections() const {
+      return number_of_sections_;
     }
     bool IsMagicValid() const;
-    bool IsVerifierDepsVersionValid() const;
-    bool IsDexSectionVersionValid() const;
+    bool IsVdexVersionValid() const;
     bool IsValid() const {
-      return IsMagicValid() && IsVerifierDepsVersionValid() && IsDexSectionVersionValid();
-    }
-    bool HasDexSection() const;
-
-    uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; }
-    uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; }
-    uint32_t GetBootClassPathChecksumStringSize() const { return bootclasspath_checksums_size_; }
-    uint32_t GetClassLoaderContextStringSize() const { return class_loader_context_size_; }
-
-    size_t GetSizeOfChecksumsSection() const {
-      return sizeof(VdexChecksum) * GetNumberOfDexFiles();
-    }
-
-    const VdexChecksum* GetDexChecksumsArray() const {
-      return reinterpret_cast<const VdexChecksum*>(
-          reinterpret_cast<const uint8_t*>(this) + sizeof(VerifierDepsHeader));
-    }
-
-    VdexChecksum GetDexChecksumAtOffset(size_t idx) const {
-      DCHECK_LT(idx, GetNumberOfDexFiles());
-      return GetDexChecksumsArray()[idx];
+      return IsMagicValid() && IsVdexVersionValid();
     }
 
     static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' };
@@ -114,65 +123,66 @@
     static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };
 
     // The format version of the verifier deps header and the verifier deps.
-    // Last update: Add boot checksum, class loader context.
-    static constexpr uint8_t kVerifierDepsVersion[] = { '0', '2', '1', '\0' };
-
-    // The format version of the dex section header and the dex section, containing
-    // both the dex code and the quickening data.
-    // Last update: Add owned section for CompactDex.
-    static constexpr uint8_t kDexSectionVersion[] = { '0', '0', '2', '\0' };
-
-    // If the .vdex file has no dex section (hence no dex code nor quickening data),
-    // we encode this magic version.
-    static constexpr uint8_t kDexSectionVersionEmpty[] = { '0', '0', '0', '\0' };
+    // Last update: Introduce vdex sections.
+    static constexpr uint8_t kVdexVersion[] = { '0', '2', '7', '\0' };
 
     uint8_t magic_[4];
-    uint8_t verifier_deps_version_[4];
-    uint8_t dex_section_version_[4];
-    uint32_t number_of_dex_files_;
-    uint32_t verifier_deps_size_;
-    uint32_t bootclasspath_checksums_size_;
-    uint32_t class_loader_context_size_;
+    uint8_t vdex_version_[4];
+    uint32_t number_of_sections_;
   };
 
-  struct DexSectionHeader {
-   public:
-    DexSectionHeader(uint32_t dex_size,
-                     uint32_t dex_shared_data_size,
-                     uint32_t quickening_info_size);
+  const VdexSectionHeader& GetSectionHeaderAt(uint32_t index) const {
+    DCHECK_LT(index, GetVdexFileHeader().GetNumberOfSections());
+    return *reinterpret_cast<const VdexSectionHeader*>(
+        Begin() + sizeof(VdexFileHeader) + index * sizeof(VdexSectionHeader));
+  }
 
-    uint32_t GetDexSize() const { return dex_size_; }
-    uint32_t GetDexSharedDataSize() const { return dex_shared_data_size_; }
-    uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; }
+  const VdexSectionHeader& GetSectionHeader(VdexSection kind) const {
+    return GetSectionHeaderAt(static_cast<uint32_t>(kind));
+  }
 
-    size_t GetDexSectionSize() const {
-      return sizeof(DexSectionHeader) +
-           GetDexSize() +
-           GetDexSharedDataSize();
-    }
-
-   private:
-    uint32_t dex_size_;
-    uint32_t dex_shared_data_size_;
-    uint32_t quickening_info_size_;
-
-    friend class VdexFile;  // For updating quickening_info_size_.
-  };
+  static size_t GetChecksumsOffset() {
+    return sizeof(VdexFileHeader) +
+        static_cast<size_t>(VdexSection::kNumberOfSections) * sizeof(VdexSectionHeader);
+  }
 
   size_t GetComputedFileSize() const {
-    size_t size = sizeof(VerifierDepsHeader);
-    const VerifierDepsHeader& header = GetVerifierDepsHeader();
-    size += header.GetVerifierDepsSize();
-    size += header.GetSizeOfChecksumsSection();
-    if (header.HasDexSection()) {
-      size += GetDexSectionHeader().GetDexSectionSize();
-      size += GetDexSectionHeader().GetQuickeningInfoSize();
+    const VdexFileHeader& header = GetVdexFileHeader();
+    uint32_t size = sizeof(VdexFileHeader) +
+        header.GetNumberOfSections() * sizeof(VdexSectionHeader);
+    for (uint32_t i = 0; i < header.GetNumberOfSections(); ++i) {
+      size = std::max(size,
+                      GetSectionHeaderAt(i).section_offset + GetSectionHeaderAt(i).section_size);
     }
-    size += header.GetBootClassPathChecksumStringSize();
-    size += header.GetClassLoaderContextStringSize();
     return size;
   }
 
+  bool IsDexSectionValid() const;
+
+  bool HasDexSection() const {
+    return GetSectionHeader(VdexSection::kDexFileSection).section_size != 0u;
+  }
+  uint32_t GetVerifierDepsSize() const {
+    return GetSectionHeader(VdexSection::kVerifierDepsSection).section_size;
+  }
+  uint32_t GetNumberOfDexFiles() const {
+    return GetSectionHeader(VdexSection::kChecksumSection).section_size / sizeof(VdexChecksum);
+  }
+
+  bool HasTypeLookupTableSection() const {
+    return GetVdexFileHeader().GetNumberOfSections() >= (kTypeLookupTableSection + 1);
+  }
+
+  const VdexChecksum* GetDexChecksumsArray() const {
+    return reinterpret_cast<const VdexChecksum*>(
+        Begin() + GetSectionHeader(VdexSection::kChecksumSection).section_offset);
+  }
+
+  VdexChecksum GetDexChecksumAt(size_t idx) const {
+    DCHECK_LT(idx, GetNumberOfDexFiles());
+    return GetDexChecksumsArray()[idx];
+  }
+
   // Note: The file is called "primary" to match the naming with profiles.
   static const constexpr char* kVdexNameInDmFile = "primary.vdex";
 
@@ -242,98 +252,38 @@
   const uint8_t* End() const { return mmap_.End(); }
   size_t Size() const { return mmap_.Size(); }
 
-  const VerifierDepsHeader& GetVerifierDepsHeader() const {
-    return *reinterpret_cast<const VerifierDepsHeader*>(Begin());
-  }
-
-  uint32_t GetDexSectionHeaderOffset() const {
-    return sizeof(VerifierDepsHeader) + GetVerifierDepsHeader().GetSizeOfChecksumsSection();
-  }
-
-  const DexSectionHeader& GetDexSectionHeader() const {
-    DCHECK(GetVerifierDepsHeader().HasDexSection());
-    return *reinterpret_cast<const DexSectionHeader*>(Begin() + GetDexSectionHeaderOffset());
-  }
-
-  const uint8_t* GetVerifierDepsStart() const {
-    const uint8_t* result = Begin() + GetDexSectionHeaderOffset();
-    if (GetVerifierDepsHeader().HasDexSection()) {
-      // When there is a dex section, the verifier deps are after it, but before the quickening.
-      return result + GetDexSectionHeader().GetDexSectionSize();
-    } else {
-      // When there is no dex section, the verifier deps are just after the header.
-      return result;
-    }
+  const VdexFileHeader& GetVdexFileHeader() const {
+    return *reinterpret_cast<const VdexFileHeader*>(Begin());
   }
 
   ArrayRef<const uint8_t> GetVerifierDepsData() const {
     return ArrayRef<const uint8_t>(
-        GetVerifierDepsStart(),
-        GetVerifierDepsHeader().GetVerifierDepsSize());
-  }
-
-  ArrayRef<const uint8_t> GetQuickeningInfo() const {
-    return ArrayRef<const uint8_t>(
-        GetVerifierDepsData().end(),
-        GetVerifierDepsHeader().HasDexSection()
-            ? GetDexSectionHeader().GetQuickeningInfoSize() : 0);
-  }
-
-  ArrayRef<const uint8_t> GetBootClassPathChecksumData() const {
-    return ArrayRef<const uint8_t>(
-        GetQuickeningInfo().end(),
-        GetVerifierDepsHeader().GetBootClassPathChecksumStringSize());
-  }
-
-  ArrayRef<const uint8_t> GetClassLoaderContextData() const {
-    return ArrayRef<const uint8_t>(
-        GetBootClassPathChecksumData().end(),
-        GetVerifierDepsHeader().GetClassLoaderContextStringSize());
+        Begin() + GetSectionHeader(VdexSection::kVerifierDepsSection).section_offset,
+        GetSectionHeader(VdexSection::kVerifierDepsSection).section_size);
   }
 
   bool IsValid() const {
-    return mmap_.Size() >= sizeof(VerifierDepsHeader) && GetVerifierDepsHeader().IsValid();
+    return mmap_.Size() >= sizeof(VdexFileHeader) && GetVdexFileHeader().IsValid();
   }
 
   // This method is for iterating over the dex files in the vdex. If `cursor` is null,
   // the first dex file is returned. If `cursor` is not null, it must point to a dex
   // file and this method returns the next dex file if there is one, or null if there
   // is none.
-  const uint8_t* GetNextDexFileData(const uint8_t* cursor) const;
+  const uint8_t* GetNextDexFileData(const uint8_t* cursor, uint32_t dex_file_index) const;
+
+  const uint8_t* GetNextTypeLookupTableData(const uint8_t* cursor, uint32_t dex_file_index) const;
 
   // Get the location checksum of the dex file number `dex_file_index`.
   uint32_t GetLocationChecksum(uint32_t dex_file_index) const {
-    DCHECK_LT(dex_file_index, GetVerifierDepsHeader().GetNumberOfDexFiles());
-    return reinterpret_cast<const uint32_t*>(Begin() + sizeof(VerifierDepsHeader))[dex_file_index];
+    DCHECK_LT(dex_file_index, GetNumberOfDexFiles());
+    return GetDexChecksumAt(dex_file_index);
   }
 
   // Open all the dex files contained in this vdex file.
   bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
                        std::string* error_msg) const;
 
-  // In-place unquicken the given `dex_files` based on `quickening_info`.
-  // `decompile_return_instruction` controls if RETURN_VOID_BARRIER instructions are
-  // decompiled to RETURN_VOID instructions using the slower ClassAccessor instead of the faster
-  // QuickeningInfoIterator.
-  // Always unquickens using the vdex dex files as the source for quicken tables.
-  void Unquicken(const std::vector<const DexFile*>& target_dex_files,
-                 bool decompile_return_instruction) const;
-
-  void UnquickenInPlace(bool decompile_return_instruction) const;
-
-  // Fully unquicken `target_dex_file` based on `quickening_info`.
-  void UnquickenDexFile(const DexFile& target_dex_file,
-                        const DexFile& source_dex_file,
-                        bool decompile_return_instruction) const;
-
-  // Return the quickening info of a given method index (or null if it's empty).
-  ArrayRef<const uint8_t> GetQuickenedInfoOf(const DexFile& dex_file,
-                                             uint32_t dex_method_idx) const;
-
-  bool HasDexSection() const {
-    return GetVerifierDepsHeader().HasDexSection();
-  }
-
   // Writes a vdex into `path` and returns true on success.
   // The vdex will not contain a dex section but will store checksums of `dex_files`,
   // encoded `verifier_deps`, as well as the current boot class path cheksum and
@@ -341,7 +291,6 @@
   static bool WriteToDisk(const std::string& path,
                           const std::vector<const DexFile*>& dex_files,
                           const verifier::VerifierDeps& verifier_deps,
-                          const std::string& class_loader_context,
                           std::string* error_msg);
 
   // Returns true if the dex file checksums stored in the vdex header match
@@ -349,47 +298,29 @@
   // order must match too.
   bool MatchesDexFileChecksums(const std::vector<const DexFile::Header*>& dex_headers) const;
 
-  // Returns true if the boot class path checksum stored in the vdex matches
-  // the checksum of boot class path in the current runtime.
-  bool MatchesBootClassPathChecksums() const;
+  ClassStatus ComputeClassStatus(Thread* self, Handle<mirror::Class> cls) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Returns true if the class loader context stored in the vdex matches `context`.
-  bool MatchesClassLoaderContext(const ClassLoaderContext& context) const;
-
-  // Make the Vdex file & underlying dex-files RW or RO. Should only be used for in-place
-  // dequickening.
-  void AllowWriting(bool value) const;
+  // Return the name of the underlying `MemMap` of the vdex file, typically the
+  // location on disk of the vdex file.
+  const std::string& GetName() const {
+    return mmap_.GetName();
+  }
 
  private:
-  uint32_t GetQuickeningInfoTableOffset(const uint8_t* source_dex_begin) const;
-
-  // Source dex must be the in the vdex file.
-  void UnquickenDexFile(const DexFile& target_dex_file,
-                        const uint8_t* source_dex_begin,
-                        bool decompile_return_instruction) const;
-
-  CompactOffsetTable::Accessor GetQuickenInfoOffsetTable(
-        const DexFile& dex_file,
-        const ArrayRef<const uint8_t>& quickening_info) const;
-
-  CompactOffsetTable::Accessor GetQuickenInfoOffsetTable(
-      const uint8_t* source_dex_begin,
-      const ArrayRef<const uint8_t>& quickening_info) const;
-
   bool ContainsDexFile(const DexFile& dex_file) const;
 
   const uint8_t* DexBegin() const {
     DCHECK(HasDexSection());
-    return Begin() + GetDexSectionHeaderOffset() + sizeof(DexSectionHeader);
+    return Begin() + GetSectionHeader(VdexSection::kDexFileSection).section_offset;
   }
 
-  const uint8_t* DexEnd() const {
-    DCHECK(HasDexSection());
-    return DexBegin() + GetDexSectionHeader().GetDexSize();
+  const uint8_t* TypeLookupTableDataBegin() const {
+    DCHECK(HasTypeLookupTableSection());
+    return Begin() + GetSectionHeader(VdexSection::kTypeLookupTableSection).section_offset;
   }
 
-  // mutable for AllowWriting()
-  mutable MemMap mmap_;
+  MemMap mmap_;
 
   DISALLOW_COPY_AND_ASSIGN(VdexFile);
 };
diff --git a/runtime/verifier/class_verifier.cc b/runtime/verifier/class_verifier.cc
index ed83652..7559f98 100644
--- a/runtime/verifier/class_verifier.cc
+++ b/runtime/verifier/class_verifier.cc
@@ -113,6 +113,7 @@
   };
   DelayedVerifyCallback dvc;
   FailureKind res = CommonVerifyClass(self,
+                                      /*verifier_deps=*/nullptr,
                                       h_klass.Get(),
                                       /*callbacks=*/nullptr,
                                       &dvc,
@@ -128,6 +129,7 @@
 }
 
 FailureKind ClassVerifier::VerifyClass(Thread* self,
+                                       VerifierDeps* verifier_deps,
                                        ObjPtr<mirror::Class> klass,
                                        CompilerCallbacks* callbacks,
                                        bool allow_soft_failures,
@@ -139,6 +141,7 @@
   }
   StandardVerifyCallback svc;
   return CommonVerifyClass(self,
+                           verifier_deps,
                            klass,
                            callbacks,
                            &svc,
@@ -149,6 +152,7 @@
 }
 
 FailureKind ClassVerifier::CommonVerifyClass(Thread* self,
+                                             VerifierDeps* verifier_deps,
                                              ObjPtr<mirror::Class> klass,
                                              CompilerCallbacks* callbacks,
                                              VerifierCallback* verifier_callback,
@@ -184,6 +188,7 @@
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
   return VerifyClass(self,
+                     verifier_deps,
                      &dex_file,
                      dex_cache,
                      class_loader,
@@ -198,6 +203,7 @@
 
 
 FailureKind ClassVerifier::VerifyClass(Thread* self,
+                                       VerifierDeps* verifier_deps,
                                        const DexFile* dex_file,
                                        Handle<mirror::DexCache> dex_cache,
                                        Handle<mirror::ClassLoader> class_loader,
@@ -209,6 +215,7 @@
                                        std::string* error) {
   StandardVerifyCallback svc;
   return VerifyClass(self,
+                     verifier_deps,
                      dex_file,
                      dex_cache,
                      class_loader,
@@ -222,6 +229,7 @@
 }
 
 FailureKind ClassVerifier::VerifyClass(Thread* self,
+                                       VerifierDeps* verifier_deps,
                                        const DexFile* dex_file,
                                        Handle<mirror::DexCache> dex_cache,
                                        Handle<mirror::ClassLoader> class_loader,
@@ -242,6 +250,7 @@
 
   ClassAccessor accessor(*dex_file, class_def);
   SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(accessor.GetDescriptor());
+  metrics::AutoTimer timer{GetMetrics()->ClassVerificationTotalTime()};
 
   int64_t previous_method_idx[2] = { -1, -1 };
   MethodVerifier::FailureData failure_data;
@@ -272,6 +281,7 @@
         MethodVerifier::VerifyMethod(self,
                                      linker,
                                      Runtime::Current()->GetArenaPool(),
+                                     verifier_deps,
                                      method_idx,
                                      dex_file,
                                      dex_cache,
@@ -303,6 +313,11 @@
     }
     failure_data.Merge(result);
   }
+  uint64_t elapsed_time_microseconds = timer.Stop();
+  VLOG(verifier) << "VerifyClass took " << PrettyDuration(UsToNs(elapsed_time_microseconds))
+                 << ", class: " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+
+  GetMetrics()->ClassVerificationCount()->AddOne();
 
   if (failure_data.kind == FailureKind::kNoFailure) {
     return FailureKind::kNoFailure;
diff --git a/runtime/verifier/class_verifier.h b/runtime/verifier/class_verifier.h
index 0b22966..fa9dd97 100644
--- a/runtime/verifier/class_verifier.h
+++ b/runtime/verifier/class_verifier.h
@@ -49,6 +49,8 @@
 
 namespace verifier {
 
+class VerifierDeps;
+
 // Verifier that ensures the complete class is OK.
 class ClassVerifier {
  public:
@@ -64,6 +66,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
   // Verify a class. Returns "kNoFailure" on success.
   static FailureKind VerifyClass(Thread* self,
+                                 VerifierDeps* verifier_deps,
                                  ObjPtr<mirror::Class> klass,
                                  CompilerCallbacks* callbacks,
                                  bool allow_soft_failures,
@@ -72,6 +75,7 @@
                                  std::string* error)
       REQUIRES_SHARED(Locks::mutator_lock_);
   static FailureKind VerifyClass(Thread* self,
+                                 VerifierDeps* verifier_deps,
                                  const DexFile* dex_file,
                                  Handle<mirror::DexCache> dex_cache,
                                  Handle<mirror::ClassLoader> class_loader,
@@ -91,6 +95,7 @@
 
  private:
   static FailureKind CommonVerifyClass(Thread* self,
+                                       VerifierDeps* verifier_deps,
                                        ObjPtr<mirror::Class> klass,
                                        CompilerCallbacks* callbacks,
                                        VerifierCallback* verifier_callback,
@@ -101,6 +106,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   static FailureKind VerifyClass(Thread* self,
+                                 VerifierDeps* verifier_deps,
                                  const DexFile* dex_file,
                                  Handle<mirror::DexCache> dex_cache,
                                  Handle<mirror::ClassLoader> class_loader,
diff --git a/runtime/verifier/method_verifier-inl.h b/runtime/verifier/method_verifier-inl.h
index dd91a85..a9fb1a0 100644
--- a/runtime/verifier/method_verifier-inl.h
+++ b/runtime/verifier/method_verifier-inl.h
@@ -34,10 +34,6 @@
   return MethodReference(dex_file_, dex_method_idx_);
 }
 
-inline bool MethodVerifier::HasCheckCasts() const {
-  return has_check_casts_;
-}
-
 inline bool MethodVerifier::HasFailures() const {
   return !failure_messages_.empty();
 }
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index d695e08..12abed2 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -34,7 +34,7 @@
 #include "base/time_utils.h"
 #include "base/utils.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "compiler_callbacks.h"
 #include "dex/class_accessor-inl.h"
 #include "dex/descriptors_names.h"
@@ -153,6 +153,7 @@
   MethodVerifier(Thread* self,
                  ClassLinker* class_linker,
                  ArenaPool* arena_pool,
+                 VerifierDeps* verifier_deps,
                  const DexFile* dex_file,
                  const dex::CodeItem* code_item,
                  uint32_t method_idx,
@@ -172,7 +173,9 @@
      : art::verifier::MethodVerifier(self,
                                      class_linker,
                                      arena_pool,
+                                     verifier_deps,
                                      dex_file,
+                                     class_def,
                                      code_item,
                                      method_idx,
                                      can_load_classes,
@@ -184,7 +187,6 @@
        return_type_(nullptr),
        dex_cache_(dex_cache),
        class_loader_(class_loader),
-       class_def_(class_def),
        declaring_class_(nullptr),
        interesting_dex_pc_(-1),
        monitor_enter_dex_pcs_(nullptr),
@@ -257,7 +259,7 @@
    * Call this after widths have been set in "insn_flags".
    *
    * Returns "false" if something in the exception table looks fishy, but we're expecting the
-   * exception table to be somewhat sane.
+   * exception table to be valid.
    */
   bool ScanTryCatchBlocks() REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -732,32 +734,13 @@
   // Returns the method index of an invoke instruction.
   uint16_t GetMethodIdxOfInvoke(const Instruction* inst)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    switch (inst->Opcode()) {
-      case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
-      case Instruction::INVOKE_VIRTUAL_QUICK: {
-        DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_)
-            << dex_file_->PrettyMethod(dex_method_idx_, true) << "@" << work_insn_idx_;
-        DCHECK(method_being_verified_ != nullptr);
-        uint16_t method_idx = method_being_verified_->GetIndexFromQuickening(work_insn_idx_);
-        CHECK_NE(method_idx, DexFile::kDexNoIndex16);
-        return method_idx;
-      }
-      default: {
-        return inst->VRegB();
-      }
-    }
+    return inst->VRegB();
   }
   // Returns the field index of a field access instruction.
   uint16_t GetFieldIdxOfFieldAccess(const Instruction* inst, bool is_static)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     if (is_static) {
       return inst->VRegB_21c();
-    } else if (inst->IsQuickened()) {
-      DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_);
-      DCHECK(method_being_verified_ != nullptr);
-      uint16_t field_idx = method_being_verified_->GetIndexFromQuickening(work_insn_idx_);
-      CHECK_NE(field_idx, DexFile::kDexNoIndex16);
-      return field_idx;
     } else {
       return inst->VRegC_22c();
     }
@@ -793,7 +776,6 @@
   Handle<mirror::DexCache> dex_cache_ GUARDED_BY(Locks::mutator_lock_);
   // The class loader for the declaring class of the method.
   Handle<mirror::ClassLoader> class_loader_ GUARDED_BY(Locks::mutator_lock_);
-  const dex::ClassDef& class_def_;  // The class def of the declaring class of the method.
   const RegType* declaring_class_;  // Lazily computed reg type of the method's declaring class.
 
   // The dex PC of a FindLocksAtDexPc request, -1 otherwise.
@@ -952,6 +934,39 @@
       return false;
     }
 
+    // Test FastNative and CriticalNative annotations. We do this in the
+    // verifier for convenience.
+    if ((method_access_flags_ & kAccNative) != 0) {
+      // Fetch the flags from the annotations: the class linker hasn't processed
+      // them yet.
+      uint32_t native_access_flags = annotations::GetNativeMethodAnnotationAccessFlags(
+          *dex_file_, class_def_, dex_method_idx_);
+      if ((native_access_flags & kAccFastNative) != 0) {
+        if ((method_access_flags_ & kAccSynchronized) != 0) {
+          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "fast native methods cannot be synchronized";
+          return false;
+        }
+      }
+      if ((native_access_flags & kAccCriticalNative) != 0) {
+        if ((method_access_flags_ & kAccSynchronized) != 0) {
+          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "critical native methods cannot be synchronized";
+          return false;
+        }
+        if ((method_access_flags_ & kAccStatic) == 0) {
+          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "critical native methods must be static";
+          return false;
+        }
+        const char* shorty = dex_file_->GetMethodShorty(method_id);
+        for (size_t i = 0, len = strlen(shorty); i < len; ++i) {
+          if (Primitive::GetType(shorty[i]) == Primitive::kPrimNot) {
+            Fail(VERIFY_ERROR_BAD_CLASS_HARD) <<
+                "critical native methods must not have references as arguments or return type";
+            return false;
+          }
+        }
+      }
+    }
+
     // This should have been rejected by the dex file verifier. Only do in debug build.
     // Note: the above will also be rejected in the dex file verifier, starting in dex version 37.
     if (kIsDebugBuild) {
@@ -1036,7 +1051,8 @@
     }
   }
 
-  // Sanity-check the register counts. ins + locals = registers, so make sure that ins <= registers.
+  // Consistency-check of the register counts.
+  // ins + locals = registers, so make sure that ins <= registers.
   if (code_item_accessor_.InsSize() > code_item_accessor_.RegistersSize()) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad register counts (ins="
                                       << code_item_accessor_.InsSize()
@@ -1078,15 +1094,6 @@
     if (next.IsErrorState()) {
       break;
     }
-    Instruction::Code opcode = it->Opcode();
-    switch (opcode) {
-      case Instruction::APUT_OBJECT:
-      case Instruction::CHECK_CAST:
-        has_check_casts_ = true;
-        break;
-      default:
-        break;
-    }
     GetModifiableInstructionFlags(it.DexPc()).SetIsOpcode();
   }
 
@@ -1900,7 +1907,7 @@
       work_line_->CopyFromLine(reg_table_.GetLine(insn_idx));
     } else if (kIsDebugBuild) {
       /*
-       * Sanity check: retrieve the stored register line (assuming
+       * Consistency check: retrieve the stored register line (assuming
        * a full table) and make sure it actually matches.
        */
       RegisterLine* register_line = reg_table_.GetLine(insn_idx);
@@ -1986,20 +1993,6 @@
   return true;
 }
 
-// Returns the index of the first final instance field of the given class, or kDexNoIndex if there
-// is no such field.
-static uint32_t GetFirstFinalInstanceFieldIndex(const DexFile& dex_file, dex::TypeIndex type_idx) {
-  const dex::ClassDef* class_def = dex_file.FindClassDef(type_idx);
-  DCHECK(class_def != nullptr);
-  ClassAccessor accessor(dex_file, *class_def);
-  for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
-    if (field.IsFinal()) {
-      return field.GetIndex();
-    }
-  }
-  return dex::kDexNoIndex;
-}
-
 // Setup a register line for the given return instruction.
 template <bool kVerifierDebug>
 static void AdjustReturnLine(MethodVerifier<kVerifierDebug>* verifier,
@@ -2009,7 +2002,6 @@
 
   switch (opcode) {
     case Instruction::RETURN_VOID:
-    case Instruction::RETURN_VOID_NO_BARRIER:
       if (verifier->IsInstanceConstructor()) {
         // Before we mark all regs as conflicts, check that we don't have an uninitialized this.
         line->CheckConstructorReturn(verifier);
@@ -2229,7 +2221,8 @@
                                               << reg_type;
           } else if (!return_type.IsAssignableFrom(reg_type, this)) {
             if (reg_type.IsUnresolvedTypes() || return_type.IsUnresolvedTypes()) {
-              Fail(api_level_ > 29u ? VERIFY_ERROR_BAD_CLASS_SOFT : VERIFY_ERROR_NO_CLASS)
+              Fail(api_level_ > 29u
+                      ? VERIFY_ERROR_BAD_CLASS_SOFT : VERIFY_ERROR_UNRESOLVED_TYPE_CHECK)
                   << " can't resolve returned type '" << return_type << "' or '" << reg_type << "'";
             } else {
               bool soft_error = false;
@@ -2579,7 +2572,8 @@
         } else if (!res_type.IsReferenceTypes()) {
           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "thrown value of non-reference type " << res_type;
         } else {
-          Fail(res_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS : VERIFY_ERROR_BAD_CLASS_SOFT)
+          Fail(res_type.IsUnresolvedTypes()
+                  ? VERIFY_ERROR_UNRESOLVED_TYPE_CHECK : VERIFY_ERROR_BAD_CLASS_SOFT)
                 << "thrown class " << res_type << " not instanceof Throwable";
         }
       }
@@ -2835,61 +2829,47 @@
       break;
 
     case Instruction::IGET_BOOLEAN:
-    case Instruction::IGET_BOOLEAN_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Boolean(), true, false);
       break;
     case Instruction::IGET_BYTE:
-    case Instruction::IGET_BYTE_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Byte(), true, false);
       break;
     case Instruction::IGET_CHAR:
-    case Instruction::IGET_CHAR_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Char(), true, false);
       break;
     case Instruction::IGET_SHORT:
-    case Instruction::IGET_SHORT_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Short(), true, false);
       break;
     case Instruction::IGET:
-    case Instruction::IGET_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Integer(), true, false);
       break;
     case Instruction::IGET_WIDE:
-    case Instruction::IGET_WIDE_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.LongLo(), true, false);
       break;
     case Instruction::IGET_OBJECT:
-    case Instruction::IGET_OBJECT_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.JavaLangObject(false), false,
                                                     false);
       break;
 
     case Instruction::IPUT_BOOLEAN:
-    case Instruction::IPUT_BOOLEAN_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Boolean(), true, false);
       break;
     case Instruction::IPUT_BYTE:
-    case Instruction::IPUT_BYTE_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Byte(), true, false);
       break;
     case Instruction::IPUT_CHAR:
-    case Instruction::IPUT_CHAR_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Char(), true, false);
       break;
     case Instruction::IPUT_SHORT:
-    case Instruction::IPUT_SHORT_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Short(), true, false);
       break;
     case Instruction::IPUT:
-    case Instruction::IPUT_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Integer(), true, false);
       break;
     case Instruction::IPUT_WIDE:
-    case Instruction::IPUT_WIDE_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.LongLo(), true, false);
       break;
     case Instruction::IPUT_OBJECT:
-    case Instruction::IPUT_OBJECT_QUICK:
       VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.JavaLangObject(false), false,
                                                     false);
       break;
@@ -2943,12 +2923,9 @@
     case Instruction::INVOKE_VIRTUAL:
     case Instruction::INVOKE_VIRTUAL_RANGE:
     case Instruction::INVOKE_SUPER:
-    case Instruction::INVOKE_SUPER_RANGE:
-    case Instruction::INVOKE_VIRTUAL_QUICK:
-    case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
+    case Instruction::INVOKE_SUPER_RANGE: {
       bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE ||
-                       inst->Opcode() == Instruction::INVOKE_SUPER_RANGE ||
-                       inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
+                       inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
       bool is_super = (inst->Opcode() == Instruction::INVOKE_SUPER ||
                        inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
       MethodType type = is_super ? METHOD_SUPER : METHOD_VIRTUAL;
@@ -3425,42 +3402,10 @@
                                  false);
       break;
 
-    // Special instructions.
-    case Instruction::RETURN_VOID_NO_BARRIER:
-      if (IsConstructor() && !IsStatic()) {
-        const RegType& declaring_class = GetDeclaringClass();
-        if (declaring_class.IsUnresolvedReference()) {
-          // We must iterate over the fields, even if we cannot use mirror classes to do so. Do it
-          // manually over the underlying dex file.
-          uint32_t first_index = GetFirstFinalInstanceFieldIndex(*dex_file_,
-              dex_file_->GetMethodId(dex_method_idx_).class_idx_);
-          if (first_index != dex::kDexNoIndex) {
-            Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void-no-barrier not expected for field "
-                              << first_index;
-          }
-          break;
-        }
-        ObjPtr<mirror::Class> klass = declaring_class.GetClass();
-        for (uint32_t i = 0, num_fields = klass->NumInstanceFields(); i < num_fields; ++i) {
-          if (klass->GetInstanceField(i)->IsFinal()) {
-            Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void-no-barrier not expected for "
-                << klass->GetInstanceField(i)->PrettyField();
-            break;
-          }
-        }
-      }
-      // Handle this like a RETURN_VOID now. Code is duplicated to separate standard from
-      // quickened opcodes (otherwise this could be a fall-through).
-      if (!IsConstructor()) {
-        if (!GetMethodReturnType().IsConflict()) {
-          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void not expected";
-        }
-      }
-      break;
-
     /* These should never appear during verification. */
     case Instruction::UNUSED_3E ... Instruction::UNUSED_43:
-    case Instruction::UNUSED_F3 ... Instruction::UNUSED_F9:
+    case Instruction::UNUSED_E3 ... Instruction::UNUSED_F9:
+    case Instruction::UNUSED_73:
     case Instruction::UNUSED_79:
     case Instruction::UNUSED_7A:
       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Unexpected opcode " << inst->DumpString(dex_file_);
@@ -3755,9 +3700,6 @@
     return *result;
   }
 
-  // Record result of class resolution attempt.
-  VerifierDeps::MaybeRecordClassResolution(*dex_file_, class_idx, klass);
-
   // If requested, check if access is allowed. Unresolved types are included in this check, as the
   // interpreter only tests whether access is allowed when a class is not pre-verified and runs in
   // the access-checks interpreter. If result is primitive, skip the access check.
@@ -3849,7 +3791,8 @@
           return std::make_pair(false, unresolved);
         }
         // Soft-fail, but do not handle this with a synthetic throw.
-        Fail(VERIFY_ERROR_NO_CLASS, /*pending_exc=*/ false) << "Unresolved catch handler";
+        Fail(VERIFY_ERROR_UNRESOLVED_TYPE_CHECK, /*pending_exc=*/ false)
+            << "Unresolved catch handler";
         if (common_super != nullptr) {
           unresolved = &unresolved->Merge(*common_super, &reg_types_, this);
         }
@@ -3885,19 +3828,13 @@
   ObjPtr<mirror::Class> klass = klass_type.GetClass();
   const RegType& referrer = GetDeclaringClass();
   ClassLinker* class_linker = GetClassLinker();
-  PointerSize pointer_size = class_linker->GetImagePointerSize();
 
-  ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx, pointer_size);
+  ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx);
   if (res_method == nullptr) {
     res_method = class_linker->FindResolvedMethod(
         klass, dex_cache_.Get(), class_loader_.Get(), dex_method_idx);
   }
 
-  // Record result of method resolution attempt. The klass resolution has recorded whether
-  // the class is an interface or not and therefore the type of the lookup performed above.
-  // TODO: Maybe we should not record dependency if the invoke type does not match the lookup type.
-  VerifierDeps::MaybeRecordMethodResolution(*dex_file_, dex_method_idx, res_method);
-
   bool must_fail = false;
   // This is traditional and helps with screwy bytecode. It will tell you that, yes, a method
   // exists, but that it's called incorrectly. This significantly helps debugging, as locally it's
@@ -4084,7 +4021,7 @@
       }
       if (!res_method_class->IsAssignableFrom(adjusted_type, this)) {
         Fail(adjusted_type.IsUnresolvedTypes()
-                 ? VERIFY_ERROR_NO_CLASS
+                 ? VERIFY_ERROR_UNRESOLVED_TYPE_CHECK
                  : VERIFY_ERROR_BAD_CLASS_SOFT)
             << "'this' argument '" << actual_arg_type << "' not instance of '"
             << *res_method_class << "'";
@@ -4673,9 +4610,6 @@
   ClassLinker* class_linker = GetClassLinker();
   ArtField* field = class_linker->ResolveFieldJLS(field_idx, dex_cache_, class_loader_);
 
-  // Record result of the field resolution attempt.
-  VerifierDeps::MaybeRecordFieldResolution(*dex_file_, field_idx, field);
-
   if (field == nullptr) {
     VLOG(verifier) << "Unable to resolve static field " << field_idx << " ("
               << dex_file_->GetFieldName(field_id) << ") in "
@@ -4723,9 +4657,6 @@
   ClassLinker* class_linker = GetClassLinker();
   ArtField* field = class_linker->ResolveFieldJLS(field_idx, dex_cache_, class_loader_);
 
-  // Record result of the field resolution attempt.
-  VerifierDeps::MaybeRecordFieldResolution(*dex_file_, field_idx, field);
-
   if (field == nullptr) {
     VLOG(verifier) << "Unable to resolve instance field " << field_idx << " ("
               << dex_file_->GetFieldName(field_id) << ") in "
@@ -4762,7 +4693,7 @@
       bool is_aot = IsAotMode();
       if (is_aot && (field_klass.IsUnresolvedTypes() || obj_type.IsUnresolvedTypes())) {
         // Compiler & unresolved types involved, retry at runtime.
-        type = VerifyError::VERIFY_ERROR_NO_CLASS;
+        type = VerifyError::VERIFY_ERROR_UNRESOLVED_TYPE_CHECK;
       } else {
         // Classes known (resolved; and thus assignability check is precise), or we are at runtime
         // and still missing classes. This is a hard failure.
@@ -5063,7 +4994,9 @@
 MethodVerifier::MethodVerifier(Thread* self,
                                ClassLinker* class_linker,
                                ArenaPool* arena_pool,
+                               VerifierDeps* verifier_deps,
                                const DexFile* dex_file,
+                               const dex::ClassDef& class_def,
                                const dex::CodeItem* code_item,
                                uint32_t dex_method_idx,
                                bool can_load_classes,
@@ -5078,14 +5011,15 @@
       work_insn_idx_(dex::kDexNoIndex),
       dex_method_idx_(dex_method_idx),
       dex_file_(dex_file),
+      class_def_(class_def),
       code_item_accessor_(*dex_file, code_item),
       // TODO: make it designated initialization when we compile as C++20.
       flags_({false, false, false, false, aot_mode}),
       encountered_failure_types_(0),
       can_load_classes_(can_load_classes),
       allow_soft_failures_(allow_soft_failures),
-      has_check_casts_(false),
       class_linker_(class_linker),
+      verifier_deps_(verifier_deps),
       link_(nullptr) {
   self->PushVerifier(this);
 }
@@ -5098,6 +5032,7 @@
 MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
                                                          ClassLinker* class_linker,
                                                          ArenaPool* arena_pool,
+                                                         VerifierDeps* verifier_deps,
                                                          uint32_t method_idx,
                                                          const DexFile* dex_file,
                                                          Handle<mirror::DexCache> dex_cache,
@@ -5118,6 +5053,7 @@
     return VerifyMethod<true>(self,
                               class_linker,
                               arena_pool,
+                              verifier_deps,
                               method_idx,
                               dex_file,
                               dex_cache,
@@ -5138,6 +5074,7 @@
     return VerifyMethod<false>(self,
                                class_linker,
                                arena_pool,
+                               verifier_deps,
                                method_idx,
                                dex_file,
                                dex_cache,
@@ -5158,14 +5095,17 @@
 }
 
 // Return whether the runtime knows how to execute a method without needing to
-// re-verify it at runtime (and therefore save on first use of the class). We
-// currently only support it for access checks, where the runtime will mark the
-// methods as needing access checks and have the interpreter execute with them.
+// re-verify it at runtime (and therefore save on first use of the class).
 // The AOT/JIT compiled code is not affected.
 static inline bool CanRuntimeHandleVerificationFailure(uint32_t encountered_failure_types) {
   constexpr uint32_t unresolved_mask =
+      verifier::VerifyError::VERIFY_ERROR_UNRESOLVED_TYPE_CHECK |
+      verifier::VerifyError::VERIFY_ERROR_NO_CLASS |
+      verifier::VerifyError::VERIFY_ERROR_CLASS_CHANGE |
+      verifier::VerifyError::VERIFY_ERROR_INSTANTIATION |
       verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS |
       verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD |
+      verifier::VerifyError::VERIFY_ERROR_NO_METHOD |
       verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD;
   return (encountered_failure_types & (~unresolved_mask)) == 0;
 }
@@ -5174,6 +5114,7 @@
 MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
                                                          ClassLinker* class_linker,
                                                          ArenaPool* arena_pool,
+                                                         VerifierDeps* verifier_deps,
                                                          uint32_t method_idx,
                                                          const DexFile* dex_file,
                                                          Handle<mirror::DexCache> dex_cache,
@@ -5196,6 +5137,7 @@
   impl::MethodVerifier<kVerifierDebug> verifier(self,
                                                 class_linker,
                                                 arena_pool,
+                                                verifier_deps,
                                                 dex_file,
                                                 code_item,
                                                 method_idx,
@@ -5223,6 +5165,7 @@
     }
 
     bool set_dont_compile = false;
+    bool must_count_locks = false;
     if (verifier.failures_.size() != 0) {
       if (VLOG_IS_ON(verifier)) {
         verifier.DumpFailures(VLOG_STREAM(verifier) << "Soft verification failures in "
@@ -5233,35 +5176,23 @@
         verifier.Dump(LOG_STREAM(INFO));
       }
       if (CanRuntimeHandleVerificationFailure(verifier.encountered_failure_types_)) {
-        result.kind = FailureKind::kAccessChecksFailure;
+        if (verifier.encountered_failure_types_ & VERIFY_ERROR_UNRESOLVED_TYPE_CHECK) {
+          result.kind = FailureKind::kTypeChecksFailure;
+        } else {
+          result.kind = FailureKind::kAccessChecksFailure;
+        }
       } else {
         result.kind = FailureKind::kSoftFailure;
       }
-      if (method != nullptr &&
-          !CanCompilerHandleVerificationFailure(verifier.encountered_failure_types_)) {
+      if (!CanCompilerHandleVerificationFailure(verifier.encountered_failure_types_)) {
         set_dont_compile = true;
       }
-    }
-    if (method != nullptr) {
-      if (verifier.HasInstructionThatWillThrow()) {
-        set_dont_compile = true;
-        if (aot_mode && (callbacks != nullptr) && !callbacks->IsBootImage()) {
-          // When compiling apps, make HasInstructionThatWillThrow a soft error to trigger
-          // re-verification at runtime.
-          // The dead code after the throw is not verified and might be invalid. This may cause
-          // the JIT compiler to crash since it assumes that all the code is valid.
-          //
-          // There's a strong assumption that the entire boot image is verified and all its dex
-          // code is valid (even the dead and unverified one). As such this is done only for apps.
-          // (CompilerDriver DCHECKs in VerifyClassVisitor that methods from boot image are
-          // fully verified).
-          result.kind = FailureKind::kSoftFailure;
-        }
-      }
-      bool must_count_locks = false;
       if ((verifier.encountered_failure_types_ & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
         must_count_locks = true;
       }
+    }
+
+    if (method != nullptr) {
       verifier_callback->SetDontCompile(method, set_dont_compile);
       verifier_callback->SetMustCountLocks(method, must_count_locks);
     }
@@ -5351,6 +5282,7 @@
       new impl::MethodVerifier<false>(self,
                                       Runtime::Current()->GetClassLinker(),
                                       Runtime::Current()->GetArenaPool(),
+                                      /* verifier_deps= */ nullptr,
                                       method->GetDexFile(),
                                       method->GetCodeItem(),
                                       method->GetDexMethodIndex(),
@@ -5398,6 +5330,7 @@
       self,
       Runtime::Current()->GetClassLinker(),
       Runtime::Current()->GetArenaPool(),
+      /* verifier_deps= */ nullptr,
       dex_file,
       code_item,
       dex_method_idx,
@@ -5439,6 +5372,7 @@
   impl::MethodVerifier<false> verifier(hs.Self(),
                                        Runtime::Current()->GetClassLinker(),
                                        Runtime::Current()->GetArenaPool(),
+                                       /* verifier_deps= */ nullptr,
                                        m->GetDexFile(),
                                        m->GetCodeItem(),
                                        m->GetDexMethodIndex(),
@@ -5461,6 +5395,7 @@
 }
 
 MethodVerifier* MethodVerifier::CreateVerifier(Thread* self,
+                                               VerifierDeps* verifier_deps,
                                                const DexFile* dex_file,
                                                Handle<mirror::DexCache> dex_cache,
                                                Handle<mirror::ClassLoader> class_loader,
@@ -5478,6 +5413,7 @@
   return new impl::MethodVerifier<false>(self,
                                          Runtime::Current()->GetClassLinker(),
                                          Runtime::Current()->GetArenaPool(),
+                                         verifier_deps,
                                          dex_file,
                                          code_item,
                                          method_idx,
@@ -5519,31 +5455,15 @@
   if (pending_exc) {
     switch (error) {
       case VERIFY_ERROR_NO_CLASS:
-      case VERIFY_ERROR_NO_FIELD:
+      case VERIFY_ERROR_UNRESOLVED_TYPE_CHECK:
       case VERIFY_ERROR_NO_METHOD:
       case VERIFY_ERROR_ACCESS_CLASS:
       case VERIFY_ERROR_ACCESS_FIELD:
       case VERIFY_ERROR_ACCESS_METHOD:
       case VERIFY_ERROR_INSTANTIATION:
       case VERIFY_ERROR_CLASS_CHANGE:
-      case VERIFY_ERROR_FORCE_INTERPRETER:
-      case VERIFY_ERROR_LOCKING:
-        if (IsAotMode() || !can_load_classes_) {
-          if (error != VERIFY_ERROR_ACCESS_CLASS &&
-              error != VERIFY_ERROR_ACCESS_FIELD &&
-              error != VERIFY_ERROR_ACCESS_METHOD) {
-            // If we're optimistically running verification at compile time, turn NO_xxx,
-            // class change and instantiation errors into soft verification errors so that we
-            // re-verify at runtime. We may fail to find or to agree on access because of not yet
-            // available class loaders, or class loaders that will differ at runtime. In these
-            // cases, we don't want to affect the soundness of the code being compiled. Instead, the
-            // generated code runs "slow paths" that dynamically perform the verification and cause
-            // the behavior to be that akin to an interpreter.
-            error = VERIFY_ERROR_BAD_CLASS_SOFT;
-          }
-        } else {
-          // If we fail again at runtime, mark that this instruction would throw and force this
-          // method to be executed using the interpreter with checks.
+        if (!IsAotMode()) {
+          // If we fail again at runtime, mark that this instruction would throw.
           flags_.have_pending_runtime_throw_failure_ = true;
         }
         // How to handle runtime failures for instructions that are not flagged kThrow.
@@ -5568,15 +5488,27 @@
         }
         break;
 
-        // Indication that verification should be retried at runtime.
+      case VERIFY_ERROR_FORCE_INTERPRETER:
+        // This will be reported to the runtime as a soft failure.
+        break;
+
+      case VERIFY_ERROR_LOCKING:
+        if (!IsAotMode()) {
+          // If we fail again at runtime, mark that this instruction would throw.
+          flags_.have_pending_runtime_throw_failure_ = true;
+        }
+        // This will be reported to the runtime as a soft failure.
+        break;
+
+      // Indication that verification should be retried at runtime.
       case VERIFY_ERROR_BAD_CLASS_SOFT:
         if (!allow_soft_failures_) {
           flags_.have_pending_hard_failure_ = true;
         }
         break;
 
-        // Hard verification failures at compile time will still fail at runtime, so the class is
-        // marked as rejected to prevent it from being compiled.
+      // Hard verification failures at compile time will still fail at runtime, so the class is
+      // marked as rejected to prevent it from being compiled.
       case VERIFY_ERROR_BAD_CLASS_HARD: {
         flags_.have_pending_hard_failure_ = true;
         break;
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 83dafd3..1dfcaab 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -62,6 +62,7 @@
 using RegisterLineArenaUniquePtr = std::unique_ptr<RegisterLine, RegisterLineArenaDelete>;
 class RegType;
 struct ScopedNewLine;
+class VerifierDeps;
 
 // We don't need to store the register data for many instructions, because we either only need
 // it at branch points (for verification) or GC points and branches (for verification +
@@ -143,6 +144,10 @@
     return *dex_file_;
   }
 
+  const dex::ClassDef& GetClassDef() const {
+    return class_def_;
+  }
+
   RegTypeCache* GetRegTypeCache() {
     return &reg_types_;
   }
@@ -191,7 +196,6 @@
   ALWAYS_INLINE const InstructionFlags& GetInstructionFlags(size_t index) const;
 
   MethodReference GetMethodReference() const;
-  bool HasCheckCasts() const;
   bool HasFailures() const;
   bool HasInstructionThatWillThrow() const {
     return flags_.have_any_pending_runtime_throw_failure_;
@@ -200,11 +204,11 @@
   virtual const RegType& ResolveCheckedClass(dex::TypeIndex class_idx)
       REQUIRES_SHARED(Locks::mutator_lock_) = 0;
 
-  uint32_t GetEncounteredFailureTypes() {
+  uint32_t GetEncounteredFailureTypes() const {
     return encountered_failure_types_;
   }
 
-  ClassLinker* GetClassLinker() {
+  ClassLinker* GetClassLinker() const {
     return class_linker_;
   }
 
@@ -212,11 +216,17 @@
     return flags_.aot_mode_;
   }
 
+  VerifierDeps* GetVerifierDeps() const {
+    return verifier_deps_;
+  }
+
  protected:
   MethodVerifier(Thread* self,
                  ClassLinker* class_linker,
                  ArenaPool* arena_pool,
+                 VerifierDeps* verifier_deps,
                  const DexFile* dex_file,
+                 const dex::ClassDef& class_def,
                  const dex::CodeItem* code_item,
                  uint32_t dex_method_idx,
                  bool can_load_classes,
@@ -249,6 +259,7 @@
   static FailureData VerifyMethod(Thread* self,
                                   ClassLinker* class_linker,
                                   ArenaPool* arena_pool,
+                                  VerifierDeps* verifier_deps,
                                   uint32_t method_idx,
                                   const DexFile* dex_file,
                                   Handle<mirror::DexCache> dex_cache,
@@ -271,6 +282,7 @@
   static FailureData VerifyMethod(Thread* self,
                                   ClassLinker* class_linker,
                                   ArenaPool* arena_pool,
+                                  VerifierDeps* verifier_deps,
                                   uint32_t method_idx,
                                   const DexFile* dex_file,
                                   Handle<mirror::DexCache> dex_cache,
@@ -295,6 +307,7 @@
   // has an irrecoverable corruption.
   virtual bool Verify() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
   static MethodVerifier* CreateVerifier(Thread* self,
+                                        VerifierDeps* verifier_deps,
                                         const DexFile* dex_file,
                                         Handle<mirror::DexCache> dex_cache,
                                         Handle<mirror::ClassLoader> class_loader,
@@ -332,8 +345,9 @@
   // Storage for the register status we're saving for later.
   RegisterLineArenaUniquePtr saved_line_;
 
-  const uint32_t dex_method_idx_;  // The method we're working on.
-  const DexFile* const dex_file_;  // The dex file containing the method.
+  const uint32_t dex_method_idx_;   // The method we're working on.
+  const DexFile* const dex_file_;   // The dex file containing the method.
+  const dex::ClassDef& class_def_;  // The class being verified.
   const CodeItemDataAccessor code_item_accessor_;
 
   // Instruction widths and flags, one entry per code unit.
@@ -378,14 +392,13 @@
   // running and the verifier is called from the class linker.
   const bool allow_soft_failures_;
 
-  // Indicates the method being verified contains at least one check-cast or aput-object
-  // instruction. Aput-object operations implicitly check for array-store exceptions, similar to
-  // check-cast.
-  bool has_check_casts_;
-
   // Classlinker to use when resolving.
   ClassLinker* class_linker_;
 
+  // The verifier deps object we are going to report type assigability
+  // constraints to. Can be null for runtime verification.
+  VerifierDeps* verifier_deps_;
+
   // Link, for the method verifier root linked list.
   MethodVerifier* link_;
 
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index e56cde9..9761982 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -17,10 +17,11 @@
 #include "method_verifier.h"
 
 #include <stdio.h>
+
 #include <memory>
 
 #include "android-base/strings.h"
-
+#include "base/metrics/metrics_test.h"
 #include "base/utils.h"
 #include "class_linker-inl.h"
 #include "class_verifier.h"
@@ -32,6 +33,8 @@
 namespace art {
 namespace verifier {
 
+using metrics::test::CounterValue;
+
 class MethodVerifierTest : public CommonRuntimeTest {
  protected:
   void VerifyClass(const std::string& descriptor)
@@ -42,8 +45,14 @@
 
     // Verify the class
     std::string error_msg;
-    FailureKind failure = ClassVerifier::VerifyClass(
-        self, klass, nullptr, true, HardFailLogMode::kLogWarning, /* api_level= */ 0u, &error_msg);
+    FailureKind failure = ClassVerifier::VerifyClass(self,
+                                                     /* verifier_deps= */ nullptr,
+                                                     klass,
+                                                     nullptr,
+                                                     true,
+                                                     HardFailLogMode::kLogWarning,
+                                                     /* api_level= */ 0u,
+                                                     &error_msg);
 
     if (android::base::StartsWith(descriptor, "Ljava/lang/invoke")) {
       ASSERT_TRUE(failure == FailureKind::kSoftFailure ||
@@ -71,5 +80,18 @@
   VerifyDexFile(*java_lang_dex_file_);
 }
 
+// Make sure verification time metrics are collected.
+TEST_F(MethodVerifierTest, VerificationTimeMetrics) {
+  ScopedObjectAccess soa(Thread::Current());
+  ASSERT_TRUE(java_lang_dex_file_ != nullptr);
+  auto* class_verification_total_time = GetMetrics()->ClassVerificationTotalTime();
+  auto* class_verification_count = GetMetrics()->ClassVerificationCount();
+  const uint64_t original_time = CounterValue(*class_verification_total_time);
+  const uint64_t original_count = CounterValue(*class_verification_count);
+  VerifyDexFile(*java_lang_dex_file_);
+  ASSERT_GT(CounterValue(*class_verification_total_time), original_time);
+  ASSERT_GT(CounterValue(*class_verification_count), original_count);
+}
+
 }  // namespace verifier
 }  // namespace art
diff --git a/runtime/verifier/reg_type-inl.h b/runtime/verifier/reg_type-inl.h
index 9e12d63..efe03a8 100644
--- a/runtime/verifier/reg_type-inl.h
+++ b/runtime/verifier/reg_type-inl.h
@@ -115,12 +115,24 @@
           bool result = lhs.GetClass()->IsAssignableFrom(rhs.GetClass());
           // Record assignability dependency. The `verifier` is null during unit tests and
           // VerifiedMethod::GenerateSafeCastSet.
-          if (verifier != nullptr) {
-            VerifierDeps::MaybeRecordAssignability(
-                verifier->GetDexFile(), lhs.GetClass(), rhs.GetClass(), strict, result);
+          if (verifier != nullptr && result) {
+            VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
+                                                   verifier->GetDexFile(),
+                                                   verifier->GetClassDef(),
+                                                   lhs.GetClass(),
+                                                   rhs.GetClass());
           }
           return result;
         } else {
+          // For unresolved types, we don't know if they are assignable, and the
+          // verifier will continue assuming they are. We need to record that.
+          if (verifier != nullptr) {
+            VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
+                                                   verifier->GetDexFile(),
+                                                   verifier->GetClassDef(),
+                                                   lhs,
+                                                   rhs);
+          }
           // Unresolved types are only assignable for null and equality.
           // Null cannot be the left-hand side.
           return false;
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 2d17030..5af2d4b 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -901,16 +901,16 @@
       // Record the dependency that both `GetClass()` and `incoming_type.GetClass()`
       // are assignable to `join_class`. The `verifier` is null during unit tests.
       if (verifier != nullptr) {
-        VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
+        VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
+                                               verifier->GetDexFile(),
+                                               verifier->GetClassDef(),
                                                join_class,
-                                               GetClass(),
-                                               /* is_strict= */ true,
-                                               /* is_assignable= */ true);
-        VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
+                                               GetClass());
+        VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
+                                               verifier->GetDexFile(),
+                                               verifier->GetClassDef(),
                                                join_class,
-                                               incoming_type.GetClass(),
-                                               /* is_strict= */ true,
-                                               /* is_assignable= */ true);
+                                               incoming_type.GetClass());
       }
       if (GetClass() == join_class && !IsPreciseReference()) {
         return *this;
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index f634645..e8a7a80 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -1142,6 +1142,8 @@
 
   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
 
+  const RegTypeCache* GetRegTypeCache() const { return reg_type_cache_; }
+
  private:
   void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override;
 
diff --git a/runtime/verifier/reg_type_cache-inl.h b/runtime/verifier/reg_type_cache-inl.h
index f62e8b6..a3f3ff8 100644
--- a/runtime/verifier/reg_type_cache-inl.h
+++ b/runtime/verifier/reg_type_cache-inl.h
@@ -17,8 +17,9 @@
 #ifndef ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_INL_H_
 #define ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_INL_H_
 
+#include "base/bit_vector-inl.h"
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/method_handle_impl.h"
 #include "mirror/method_type.h"
diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc
index 9cac5fb..207bb5d 100644
--- a/runtime/verifier/reg_type_test.cc
+++ b/runtime/verifier/reg_type_test.cc
@@ -69,7 +69,7 @@
   const RegType& precise_const = cache.FromCat1Const(static_cast<int32_t>(val >> 32), true);
   const RegType& long_lo = cache.LongLo();
   const RegType& long_hi = cache.LongHi();
-  // Check sanity of types.
+  // Check the expectations for types.
   EXPECT_TRUE(precise_lo.IsLowHalf());
   EXPECT_FALSE(precise_hi.IsLowHalf());
   EXPECT_FALSE(precise_lo.IsHighHalf());
diff --git a/runtime/verifier/register_line-inl.h b/runtime/verifier/register_line-inl.h
index 1e3416a..65a22df 100644
--- a/runtime/verifier/register_line-inl.h
+++ b/runtime/verifier/register_line-inl.h
@@ -142,7 +142,7 @@
       // Hard fail for uninitialized types, which don't match anything but themselves.
       fail_type = VERIFY_ERROR_BAD_CLASS_HARD;
     } else if (check_type.IsUnresolvedTypes() || src_type.IsUnresolvedTypes()) {
-      fail_type = VERIFY_ERROR_NO_CLASS;
+      fail_type = VERIFY_ERROR_UNRESOLVED_TYPE_CHECK;
     } else {
       fail_type = VERIFY_ERROR_BAD_CLASS_SOFT;
     }
diff --git a/runtime/verifier/verifier_compiler_binding.h b/runtime/verifier/verifier_compiler_binding.h
index 4f9a13f..2266d50 100644
--- a/runtime/verifier/verifier_compiler_binding.h
+++ b/runtime/verifier/verifier_compiler_binding.h
@@ -28,6 +28,10 @@
 ALWAYS_INLINE
 static inline bool CanCompilerHandleVerificationFailure(uint32_t encountered_failure_types) {
   constexpr uint32_t unresolved_mask = verifier::VerifyError::VERIFY_ERROR_NO_CLASS
+      | verifier::VerifyError::VERIFY_ERROR_UNRESOLVED_TYPE_CHECK
+      | verifier::VerifyError::VERIFY_ERROR_CLASS_CHANGE
+      | verifier::VerifyError::VERIFY_ERROR_NO_METHOD
+      | verifier::VerifyError::VERIFY_ERROR_INSTANTIATION
       | verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS
       | verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD
       | verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD;
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index 219627f..7d00f73 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -31,6 +31,8 @@
 #include "mirror/class_loader.h"
 #include "oat_file.h"
 #include "obj_ptr-inl.h"
+#include "reg_type.h"
+#include "reg_type_cache-inl.h"
 #include "runtime.h"
 
 namespace art {
@@ -45,9 +47,6 @@
   }
 }
 
-VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files)
-    : VerifierDeps(dex_files, /*output_only=*/ true) {}
-
 // Perform logical OR on two bit vectors and assign back to LHS, i.e. `to_update |= other`.
 // Size of the two vectors must be equal.
 // Size of `other` must be equal to size of `to_update`.
@@ -70,13 +69,13 @@
     // We currently collect extra strings only on the main `VerifierDeps`,
     // which should be the one passed as `this` in this method.
     DCHECK(other_deps.strings_.empty());
-    my_deps->assignable_types_.merge(other_deps.assignable_types_);
-    my_deps->unassignable_types_.merge(other_deps.unassignable_types_);
-    my_deps->classes_.merge(other_deps.classes_);
-    my_deps->fields_.merge(other_deps.fields_);
-    my_deps->methods_.merge(other_deps.methods_);
+    // Size is the number of class definitions in the dex file, and must be the
+    // same between the two `VerifierDeps`.
+    DCHECK_EQ(my_deps->assignable_types_.size(), other_deps.assignable_types_.size());
+    for (uint32_t i = 0; i < my_deps->assignable_types_.size(); ++i) {
+      my_deps->assignable_types_[i].merge(other_deps.assignable_types_[i]);
+    }
     BitVectorOr(my_deps->verified_classes_, other_deps.verified_classes_);
-    BitVectorOr(my_deps->redefined_classes_, other_deps.redefined_classes_);
   }
 }
 
@@ -90,22 +89,6 @@
   return (it == dex_deps_.end()) ? nullptr : it->second.get();
 }
 
-// Access flags that impact vdex verification.
-static constexpr uint32_t kAccVdexAccessFlags =
-    kAccPublic | kAccPrivate | kAccProtected | kAccStatic | kAccInterface;
-
-template <typename Ptr>
-uint16_t VerifierDeps::GetAccessFlags(Ptr element) {
-  static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
-  if (element == nullptr) {
-    return VerifierDeps::kUnresolvedMarker;
-  } else {
-    uint16_t access_flags = Low16Bits(element->GetAccessFlags()) & kAccVdexAccessFlags;
-    CHECK_NE(access_flags, VerifierDeps::kUnresolvedMarker);
-    return access_flags;
-  }
-}
-
 dex::StringIndex VerifierDeps::GetClassDescriptorStringId(const DexFile& dex_file,
                                                           ObjPtr<mirror::Class> klass) {
   DCHECK(klass != nullptr);
@@ -129,80 +112,18 @@
   return GetIdFromString(dex_file, klass->GetDescriptor(&temp));
 }
 
-// Try to find the string descriptor of the class. type_idx is a best guess of a matching string id.
-static dex::StringIndex TryGetClassDescriptorStringId(const DexFile& dex_file,
-                                                      dex::TypeIndex type_idx,
-                                                      ObjPtr<mirror::Class> klass)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  if (!klass->IsArrayClass()) {
-    const dex::TypeId& type_id = dex_file.GetTypeId(type_idx);
-    const DexFile& klass_dex = klass->GetDexFile();
-    const dex::TypeId& klass_type_id = klass_dex.GetTypeId(klass->GetClassDef()->class_idx_);
-    if (strcmp(dex_file.GetTypeDescriptor(type_id),
-               klass_dex.GetTypeDescriptor(klass_type_id)) == 0) {
-      return type_id.descriptor_idx_;
-    }
-  }
-  return dex::StringIndex::Invalid();
-}
-
-dex::StringIndex VerifierDeps::GetMethodDeclaringClassStringId(const DexFile& dex_file,
-                                                               uint32_t dex_method_index,
-                                                               ArtMethod* method) {
-  static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
-  if (method == nullptr) {
-    return dex::StringIndex(VerifierDeps::kUnresolvedMarker);
-  }
-  const dex::StringIndex string_id = TryGetClassDescriptorStringId(
-      dex_file,
-      dex_file.GetMethodId(dex_method_index).class_idx_,
-      method->GetDeclaringClass());
-  if (string_id.IsValid()) {
-    // Got lucky using the original dex file, return based on the input dex file.
-    DCHECK_EQ(GetClassDescriptorStringId(dex_file, method->GetDeclaringClass()), string_id);
-    return string_id;
-  }
-  return GetClassDescriptorStringId(dex_file, method->GetDeclaringClass());
-}
-
-dex::StringIndex VerifierDeps::GetFieldDeclaringClassStringId(const DexFile& dex_file,
-                                                              uint32_t dex_field_idx,
-                                                              ArtField* field) {
-  static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
-  if (field == nullptr) {
-    return dex::StringIndex(VerifierDeps::kUnresolvedMarker);
-  }
-  const dex::StringIndex string_id = TryGetClassDescriptorStringId(
-      dex_file,
-      dex_file.GetFieldId(dex_field_idx).class_idx_,
-      field->GetDeclaringClass());
-  if (string_id.IsValid()) {
-    // Got lucky using the original dex file, return based on the input dex file.
-    DCHECK_EQ(GetClassDescriptorStringId(dex_file, field->GetDeclaringClass()), string_id);
-    return string_id;
-  }
-  return GetClassDescriptorStringId(dex_file, field->GetDeclaringClass());
-}
-
-static inline VerifierDeps* GetMainVerifierDeps() {
+static inline VerifierDeps* GetMainVerifierDeps(VerifierDeps* local_deps) {
   // The main VerifierDeps is the one set in the compiler callbacks, which at the
   // end of verification will have all the per-thread VerifierDeps merged into it.
   CompilerCallbacks* callbacks = Runtime::Current()->GetCompilerCallbacks();
   if (callbacks == nullptr) {
-    return nullptr;
+    DCHECK(!Runtime::Current()->IsAotCompiler());
+    return local_deps;
   }
+  DCHECK(Runtime::Current()->IsAotCompiler());
   return callbacks->GetVerifierDeps();
 }
 
-static inline VerifierDeps* GetThreadLocalVerifierDeps() {
-  // During AOT, each thread has its own VerifierDeps, to avoid lock contention. At the end
-  // of full verification, these VerifierDeps will be merged into the main one.
-  if (!Runtime::Current()->IsAotCompiler()) {
-    return nullptr;
-  }
-  return Thread::Current()->GetVerifierDeps();
-}
-
 static bool FindExistingStringId(const std::vector<std::string>& strings,
                                  const std::string& str,
                                  uint32_t* found_id) {
@@ -228,7 +149,7 @@
 
   // We use the main `VerifierDeps` for adding new strings to simplify
   // synchronization/merging of these entries between threads.
-  VerifierDeps* singleton = GetMainVerifierDeps();
+  VerifierDeps* singleton = GetMainVerifierDeps(this);
   DexFileDeps* deps = singleton->GetDexFileDeps(dex_file);
   DCHECK(deps != nullptr);
 
@@ -268,151 +189,10 @@
   }
 }
 
-bool VerifierDeps::IsInClassPath(ObjPtr<mirror::Class> klass) const {
-  DCHECK(klass != nullptr);
-
-  // For array types, we return whether the non-array component type
-  // is in the classpath.
-  while (klass->IsArrayClass()) {
-    klass = klass->GetComponentType();
-  }
-
-  if (klass->IsPrimitive()) {
-    return true;
-  }
-
-  ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache();
-  DCHECK(dex_cache != nullptr);
-  const DexFile* dex_file = dex_cache->GetDexFile();
-  DCHECK(dex_file != nullptr);
-
-  // Test if the `dex_deps_` contains an entry for `dex_file`. If not, the dex
-  // file was not registered as being compiled and we assume `klass` is in the
-  // classpath.
-  return (GetDexFileDeps(*dex_file) == nullptr);
-}
-
-void VerifierDeps::AddClassResolution(const DexFile& dex_file,
-                                      dex::TypeIndex type_idx,
-                                      ObjPtr<mirror::Class> klass) {
-  DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
-  if (dex_deps == nullptr) {
-    // This invocation is from verification of a dex file which is not being compiled.
-    return;
-  }
-
-  if (klass != nullptr && !IsInClassPath(klass)) {
-    // Class resolved into one of the DEX files which are being compiled.
-    // This is not a classpath dependency.
-    return;
-  }
-
-  dex_deps->classes_.emplace(ClassResolution(type_idx, GetAccessFlags(klass)));
-}
-
-void VerifierDeps::AddFieldResolution(const DexFile& dex_file,
-                                      uint32_t field_idx,
-                                      ArtField* field) {
-  DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
-  if (dex_deps == nullptr) {
-    // This invocation is from verification of a dex file which is not being compiled.
-    return;
-  }
-
-  if (field != nullptr && !IsInClassPath(field->GetDeclaringClass())) {
-    // Field resolved into one of the DEX files which are being compiled.
-    // This is not a classpath dependency.
-    return;
-  }
-
-  dex_deps->fields_.emplace(FieldResolution(field_idx,
-                                            GetAccessFlags(field),
-                                            GetFieldDeclaringClassStringId(dex_file,
-                                                                           field_idx,
-                                                                           field)));
-}
-
-void VerifierDeps::AddMethodResolution(const DexFile& dex_file,
-                                       uint32_t method_idx,
-                                       ArtMethod* method) {
-  DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
-  if (dex_deps == nullptr) {
-    // This invocation is from verification of a dex file which is not being compiled.
-    return;
-  }
-
-  if (method != nullptr && !IsInClassPath(method->GetDeclaringClass())) {
-    // Method resolved into one of the DEX files which are being compiled.
-    // This is not a classpath dependency.
-    return;
-  }
-
-  MethodResolution method_tuple(method_idx,
-                                GetAccessFlags(method),
-                                GetMethodDeclaringClassStringId(dex_file, method_idx, method));
-  dex_deps->methods_.insert(method_tuple);
-}
-
-ObjPtr<mirror::Class> VerifierDeps::FindOneClassPathBoundaryForInterface(
-    ObjPtr<mirror::Class> destination,
-    ObjPtr<mirror::Class> source) const {
-  DCHECK(destination->IsInterface());
-  DCHECK(IsInClassPath(destination));
-  Thread* thread = Thread::Current();
-  ObjPtr<mirror::Class> current = source;
-  // Record the classes that are at the boundary between the compiled DEX files and
-  // the classpath. We will check those classes later to find one class that inherits
-  // `destination`.
-  std::vector<ObjPtr<mirror::Class>> boundaries;
-  // If the destination is a direct interface of a class defined in the DEX files being
-  // compiled, no need to record it.
-  while (!IsInClassPath(current)) {
-    for (size_t i = 0; i < current->NumDirectInterfaces(); ++i) {
-      ObjPtr<mirror::Class> direct = mirror::Class::GetDirectInterface(thread, current, i);
-      if (direct == destination) {
-        return nullptr;
-      } else if (IsInClassPath(direct)) {
-        boundaries.push_back(direct);
-      }
-    }
-    current = current->GetSuperClass();
-  }
-  DCHECK(current != nullptr);
-  boundaries.push_back(current);
-
-  // Check if we have an interface defined in the DEX files being compiled, direclty
-  // inheriting `destination`.
-  int32_t iftable_count = source->GetIfTableCount();
-  ObjPtr<mirror::IfTable> iftable = source->GetIfTable();
-  for (int32_t i = 0; i < iftable_count; ++i) {
-    ObjPtr<mirror::Class> itf = iftable->GetInterface(i);
-    if (!IsInClassPath(itf)) {
-      for (size_t j = 0; j < itf->NumDirectInterfaces(); ++j) {
-        ObjPtr<mirror::Class> direct = mirror::Class::GetDirectInterface(thread, itf, j);
-        if (direct == destination) {
-          return nullptr;
-        } else if (IsInClassPath(direct)) {
-          boundaries.push_back(direct);
-        }
-      }
-    }
-  }
-
-  // Find a boundary making `source` inherit from `destination`. We must find one.
-  for (const ObjPtr<mirror::Class>& boundary : boundaries) {
-    if (destination->IsAssignableFrom(boundary)) {
-      return boundary;
-    }
-  }
-  LOG(FATAL) << "Should have found a classpath boundary";
-  UNREACHABLE();
-}
-
 void VerifierDeps::AddAssignability(const DexFile& dex_file,
+                                    const dex::ClassDef& class_def,
                                     ObjPtr<mirror::Class> destination,
-                                    ObjPtr<mirror::Class> source,
-                                    bool is_strict,
-                                    bool is_assignable) {
+                                    ObjPtr<mirror::Class> source) {
   // Test that the method is only called on reference types.
   // Note that concurrent verification of `destination` and `source` may have
   // set their status to erroneous. However, the tests performed below rely
@@ -429,17 +209,8 @@
     return;
   }
 
-  if (source->IsObjectClass() && !is_assignable) {
-    // j.l.Object is trivially non-assignable to other types, don't
-    // record it.
-    return;
-  }
-
-  if (destination == source ||
-      destination->IsObjectClass() ||
-      (!is_strict && destination->IsInterface())) {
+  if (destination == source || destination->IsObjectClass()) {
     // Cases when `destination` is trivially assignable from `source`.
-    DCHECK(is_assignable);
     return;
   }
 
@@ -454,16 +225,11 @@
     // that they linked successfully, as required at the top of this method.
     if (destination_component->IsResolved() && source_component->IsResolved()) {
       AddAssignability(dex_file,
+                       class_def,
                        destination_component,
-                       source_component,
-                       /* is_strict= */ true,
-                       is_assignable);
+                       source_component);
       return;
     }
-  } else {
-    // We only do this check for non-array types, as arrays might have erroneous
-    // component types which makes the IsAssignableFrom check unreliable.
-    DCHECK_EQ(is_assignable, destination->IsAssignableFrom(source));
   }
 
   DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
@@ -472,65 +238,66 @@
     return;
   }
 
-  if (!IsInClassPath(destination) && !IsInClassPath(source)) {
-    // Both `destination` and `source` are defined in the compiled DEX files.
-    // No need to record a dependency.
-    return;
-  }
-
-  if (!IsInClassPath(source)) {
-    if (!destination->IsInterface() && !source->IsInterface()) {
-      // Find the super class at the classpath boundary. Only that class
-      // can change the assignability.
-      do {
-        source = source->GetSuperClass();
-      } while (!IsInClassPath(source));
-
-      // If that class is the actual destination, no need to record it.
-      if (source == destination) {
-        return;
-      }
-    } else if (is_assignable) {
-      source = FindOneClassPathBoundaryForInterface(destination, source);
-      if (source == nullptr) {
-        // There was no classpath boundary, no need to record.
-        return;
-      }
-      DCHECK(IsInClassPath(source));
-    }
-  }
-
-
   // Get string IDs for both descriptors and store in the appropriate set.
   dex::StringIndex destination_id = GetClassDescriptorStringId(dex_file, destination);
   dex::StringIndex source_id = GetClassDescriptorStringId(dex_file, source);
 
-  if (is_assignable) {
-    dex_deps->assignable_types_.emplace(TypeAssignability(destination_id, source_id));
+  uint16_t index = dex_file.GetIndexForClassDef(class_def);
+  dex_deps->assignable_types_[index].emplace(TypeAssignability(destination_id, source_id));
+}
+
+void VerifierDeps::AddAssignability(const DexFile& dex_file,
+                                    const dex::ClassDef& class_def,
+                                    const RegType& destination,
+                                    const RegType& source) {
+  DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
+  if (dex_deps == nullptr) {
+    // This invocation is from verification of a DEX file which is not being compiled.
+    return;
+  }
+
+  CHECK(destination.IsUnresolvedReference() || destination.HasClass());
+  CHECK(!destination.IsUnresolvedMergedReference());
+
+  if (source.IsUnresolvedReference() || source.HasClass()) {
+    // Get string IDs for both descriptors and store in the appropriate set.
+    dex::StringIndex destination_id =
+        GetIdFromString(dex_file, std::string(destination.GetDescriptor()));
+    dex::StringIndex source_id = GetIdFromString(dex_file, std::string(source.GetDescriptor()));
+    uint16_t index = dex_file.GetIndexForClassDef(class_def);
+    dex_deps->assignable_types_[index].emplace(TypeAssignability(destination_id, source_id));
+  } else if (source.IsZeroOrNull()) {
+    // Nothing to record, null is always assignable.
   } else {
-    dex_deps->unassignable_types_.emplace(TypeAssignability(destination_id, source_id));
+    CHECK(source.IsUnresolvedMergedReference()) << source.Dump();
+    const UnresolvedMergedType& merge = *down_cast<const UnresolvedMergedType*>(&source);
+    AddAssignability(dex_file, class_def, destination, merge.GetResolvedPart());
+    for (uint32_t idx : merge.GetUnresolvedTypes().Indexes()) {
+      AddAssignability(dex_file, class_def, destination, merge.GetRegTypeCache()->GetFromId(idx));
+    }
   }
 }
 
-void VerifierDeps::MaybeRecordClassRedefinition(const DexFile& dex_file,
-                                                const dex::ClassDef& class_def) {
-  VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
-  if (thread_deps != nullptr) {
-    DexFileDeps* dex_deps = thread_deps->GetDexFileDeps(dex_file);
-    DCHECK_EQ(dex_deps->redefined_classes_.size(), dex_file.NumClassDefs());
-    dex_deps->redefined_classes_[dex_file.GetIndexForClassDef(class_def)] = true;
-  }
-}
-
-void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file,
+void VerifierDeps::MaybeRecordVerificationStatus(VerifierDeps* verifier_deps,
+                                                 const DexFile& dex_file,
                                                  const dex::ClassDef& class_def,
                                                  FailureKind failure_kind) {
-  // The `verified_classes_` bit vector is initialized to `false`.
-  // Only continue if we are about to write `true`.
-  if (failure_kind == FailureKind::kNoFailure) {
-    VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
-    if (thread_deps != nullptr) {
-      thread_deps->RecordClassVerified(dex_file, class_def);
+  if (verifier_deps != nullptr) {
+    switch (failure_kind) {
+      case verifier::FailureKind::kHardFailure:
+      case verifier::FailureKind::kSoftFailure: {
+        // Class will be verified at runtime.
+        DexFileDeps* dex_deps = verifier_deps->GetDexFileDeps(dex_file);
+        uint16_t index = dex_file.GetIndexForClassDef(class_def);
+        dex_deps->assignable_types_[index].clear();
+        break;
+      }
+      case verifier::FailureKind::kAccessChecksFailure:
+      case verifier::FailureKind::kTypeChecksFailure:
+      case verifier::FailureKind::kNoFailure: {
+        verifier_deps->RecordClassVerified(dex_file, class_def);
+        break;
+      }
     }
   }
 }
@@ -541,77 +308,43 @@
   dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)] = true;
 }
 
-void VerifierDeps::MaybeRecordClassResolution(const DexFile& dex_file,
-                                              dex::TypeIndex type_idx,
-                                              ObjPtr<mirror::Class> klass) {
-  VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
-  if (thread_deps != nullptr) {
-    thread_deps->AddClassResolution(dex_file, type_idx, klass);
-  }
+bool VerifierDeps::HasRecordedVerifiedStatus(const DexFile& dex_file,
+                                             const dex::ClassDef& class_def) {
+  DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
+  DCHECK_EQ(dex_deps->verified_classes_.size(), dex_file.NumClassDefs());
+  return dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)];
 }
 
-void VerifierDeps::MaybeRecordFieldResolution(const DexFile& dex_file,
-                                              uint32_t field_idx,
-                                              ArtField* field) {
-  VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
-  if (thread_deps != nullptr) {
-    thread_deps->AddFieldResolution(dex_file, field_idx, field);
-  }
-}
-
-void VerifierDeps::MaybeRecordMethodResolution(const DexFile& dex_file,
-                                               uint32_t method_idx,
-                                               ArtMethod* method) {
-  VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
-  if (thread_deps != nullptr) {
-    thread_deps->AddMethodResolution(dex_file, method_idx, method);
-  }
-}
-
-void VerifierDeps::MaybeRecordAssignability(const DexFile& dex_file,
+void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps,
+                                            const DexFile& dex_file,
+                                            const dex::ClassDef& class_def,
                                             ObjPtr<mirror::Class> destination,
-                                            ObjPtr<mirror::Class> source,
-                                            bool is_strict,
-                                            bool is_assignable) {
-  VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
-  if (thread_deps != nullptr) {
-    thread_deps->AddAssignability(dex_file, destination, source, is_strict, is_assignable);
+                                            ObjPtr<mirror::Class> source) {
+  if (verifier_deps != nullptr) {
+    verifier_deps->AddAssignability(dex_file, class_def, destination, source);
+  }
+}
+
+void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps,
+                                            const DexFile& dex_file,
+                                            const dex::ClassDef& class_def,
+                                            const RegType& destination,
+                                            const RegType& source) {
+  if (verifier_deps != nullptr) {
+    verifier_deps->AddAssignability(dex_file, class_def, destination, source);
   }
 }
 
 namespace {
 
-static inline uint32_t DecodeUint32WithOverflowCheck(const uint8_t** in, const uint8_t* end) {
-  CHECK_LT(*in, end);
-  return DecodeUnsignedLeb128(in);
-}
-
 template<typename T> inline uint32_t Encode(T in);
 
-template<> inline uint32_t Encode<uint16_t>(uint16_t in) {
-  return in;
-}
-template<> inline uint32_t Encode<uint32_t>(uint32_t in) {
-  return in;
-}
-template<> inline uint32_t Encode<dex::TypeIndex>(dex::TypeIndex in) {
-  return in.index_;
-}
 template<> inline uint32_t Encode<dex::StringIndex>(dex::StringIndex in) {
   return in.index_;
 }
 
 template<typename T> inline T Decode(uint32_t in);
 
-template<> inline uint16_t Decode<uint16_t>(uint32_t in) {
-  return dchecked_integral_cast<uint16_t>(in);
-}
-template<> inline uint32_t Decode<uint32_t>(uint32_t in) {
-  return in;
-}
-template<> inline dex::TypeIndex Decode<dex::TypeIndex>(uint32_t in) {
-  return dex::TypeIndex(in);
-}
 template<> inline dex::StringIndex Decode<dex::StringIndex>(uint32_t in) {
   return dex::StringIndex(in);
 }
@@ -623,10 +356,14 @@
 }
 
 template<typename T1, typename T2>
-static inline void DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2>* t) {
-  T1 v1 = Decode<T1>(DecodeUint32WithOverflowCheck(in, end));
-  T2 v2 = Decode<T2>(DecodeUint32WithOverflowCheck(in, end));
-  *t = std::make_tuple(v1, v2);
+static inline bool DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2>* t) {
+  uint32_t v1, v2;
+  if (UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v1)) ||
+      UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v2))) {
+    return false;
+  }
+  *t = std::make_tuple(Decode<T1>(v1), Decode<T2>(v2));
+  return true;
 }
 
 template<typename T1, typename T2, typename T3>
@@ -637,62 +374,108 @@
 }
 
 template<typename T1, typename T2, typename T3>
-static inline void DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2, T3>* t) {
-  T1 v1 = Decode<T1>(DecodeUint32WithOverflowCheck(in, end));
-  T2 v2 = Decode<T2>(DecodeUint32WithOverflowCheck(in, end));
-  T3 v3 = Decode<T3>(DecodeUint32WithOverflowCheck(in, end));
-  *t = std::make_tuple(v1, v2, v3);
+static inline bool DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2, T3>* t) {
+  uint32_t v1, v2, v3;
+  if (UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v1)) ||
+      UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v2)) ||
+      UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v3))) {
+    return false;
+  }
+  *t = std::make_tuple(Decode<T1>(v1), Decode<T2>(v2), Decode<T3>(v3));
+  return true;
+}
+
+static void SetUint32InUint8Array(std::vector<uint8_t>* out,
+                                  uint32_t uint8_offset,
+                                  uint32_t uint32_offset,
+                                  uint32_t value) {
+  DCHECK(IsAligned<sizeof(uint32_t)>(out->data() + uint8_offset));
+  (reinterpret_cast<uint32_t*>(out->data() + uint8_offset))[uint32_offset] = value;
 }
 
 template<typename T>
-static inline void EncodeSet(std::vector<uint8_t>* out, const std::set<T>& set) {
-  EncodeUnsignedLeb128(out, set.size());
-  for (const T& entry : set) {
-    EncodeTuple(out, entry);
+static void EncodeSetVector(std::vector<uint8_t>* out,
+                            const std::vector<std::set<T>>& vector,
+                            const std::vector<bool>& verified_classes) {
+  uint32_t offsets_index = out->size();
+  // Make room for offsets for each class, +1 for marking the end of the
+  // assignability types data.
+  out->resize(out->size() + (vector.size() + 1) * sizeof(uint32_t));
+  uint32_t class_def_index = 0;
+  for (const std::set<T>& set : vector) {
+    if (verified_classes[class_def_index]) {
+      // Store the offset of the set for this class.
+      SetUint32InUint8Array(out, offsets_index, class_def_index, out->size());
+      for (const T& entry : set) {
+        EncodeTuple(out, entry);
+      }
+    } else {
+      SetUint32InUint8Array(out, offsets_index, class_def_index, VerifierDeps::kNotVerifiedMarker);
+    }
+    class_def_index++;
   }
+  SetUint32InUint8Array(out, offsets_index, class_def_index, out->size());
 }
 
-template<typename T>
-static inline void DecodeSet(const uint8_t** in, const uint8_t* end, std::set<T>* set) {
-  DCHECK(set->empty());
-  size_t num_entries = DecodeUint32WithOverflowCheck(in, end);
-  for (size_t i = 0; i < num_entries; ++i) {
-    T tuple;
-    DecodeTuple(in, end, &tuple);
-    set->emplace(tuple);
-  }
-}
-
-static inline void EncodeUint16SparseBitVector(std::vector<uint8_t>* out,
-                                               const std::vector<bool>& vector,
-                                               bool sparse_value) {
-  DCHECK(IsUint<16>(vector.size()));
-  EncodeUnsignedLeb128(out, std::count(vector.begin(), vector.end(), sparse_value));
-  for (uint16_t idx = 0; idx < vector.size(); ++idx) {
-    if (vector[idx] == sparse_value) {
-      EncodeUnsignedLeb128(out, Encode(idx));
+template<bool kFillSet, typename T>
+static bool DecodeSetVector(const uint8_t** cursor,
+                            const uint8_t* start,
+                            const uint8_t* end,
+                            std::vector<std::set<T>>* vector,
+                            std::vector<bool>* verified_classes,
+                            size_t num_class_defs) {
+  const uint32_t* offsets = reinterpret_cast<const uint32_t*>(*cursor);
+  uint32_t next_valid_offset_index = 1;
+  // Put the cursor after the offsets of each class, +1 for the offset of the
+  // end of the assignable types data.
+  *cursor += (num_class_defs + 1) * sizeof(uint32_t);
+  for (uint32_t i = 0; i < num_class_defs; ++i) {
+    uint32_t offset = offsets[i];
+    if (offset == VerifierDeps::kNotVerifiedMarker) {
+      (*verified_classes)[i] = false;
+      continue;
+    }
+    (*verified_classes)[i] = true;
+    *cursor = start + offset;
+    // Fetch the assignability checks.
+    std::set<T>& set = (*vector)[i];
+    // Find the offset of the next entry. This will tell us where to stop when
+    // reading the checks. Note that the last entry in the `offsets` array points
+    // to the end of the assignability types data, so the loop will terminate correctly.
+    while (next_valid_offset_index <= i ||
+           offsets[next_valid_offset_index] == VerifierDeps::kNotVerifiedMarker) {
+      next_valid_offset_index++;
+    }
+    const uint8_t* set_end = start + offsets[next_valid_offset_index];
+    // Decode each check.
+    while (*cursor < set_end) {
+      T tuple;
+      if (UNLIKELY(!DecodeTuple(cursor, end, &tuple))) {
+        return false;
+      }
+      if (kFillSet) {
+        set.emplace(tuple);
+      }
     }
   }
-}
-
-static inline void DecodeUint16SparseBitVector(const uint8_t** in,
-                                               const uint8_t* end,
-                                               std::vector<bool>* vector,
-                                               bool sparse_value) {
-  DCHECK(IsUint<16>(vector->size()));
-  std::fill(vector->begin(), vector->end(), !sparse_value);
-  size_t num_entries = DecodeUint32WithOverflowCheck(in, end);
-  for (size_t i = 0; i < num_entries; ++i) {
-    uint16_t idx = Decode<uint16_t>(DecodeUint32WithOverflowCheck(in, end));
-    DCHECK_LT(idx, vector->size());
-    (*vector)[idx] = sparse_value;
-  }
+  // Align the cursor to start decoding the strings.
+  *cursor = AlignUp(*cursor, sizeof(uint32_t));
+  return true;
 }
 
 static inline void EncodeStringVector(std::vector<uint8_t>* out,
                                       const std::vector<std::string>& strings) {
-  EncodeUnsignedLeb128(out, strings.size());
+  uint32_t offsets_index = out->size();
+  // Make room for offsets for each string, +1 for putting the number of
+  // strings.
+  out->resize(out->size() + (strings.size() + 1 ) * sizeof(uint32_t));
+  (reinterpret_cast<uint32_t*>(out->data() + offsets_index))[0] = strings.size();
+  uint32_t string_index = 1;
   for (const std::string& str : strings) {
+    // Store the offset of the string.
+    (reinterpret_cast<uint32_t*>(out->data() + offsets_index))[string_index++] = out->size();
+
+    // Store the string data.
     const uint8_t* data = reinterpret_cast<const uint8_t*>(str.c_str());
     size_t length = str.length() + 1;
     out->insert(out->end(), data, data + length);
@@ -700,97 +483,134 @@
   }
 }
 
-static inline void DecodeStringVector(const uint8_t** in,
+template<bool kFillVector>
+static inline bool DecodeStringVector(const uint8_t** cursor,
+                                      const uint8_t* start,
                                       const uint8_t* end,
                                       std::vector<std::string>* strings) {
   DCHECK(strings->empty());
-  size_t num_strings = DecodeUint32WithOverflowCheck(in, end);
-  strings->reserve(num_strings);
-  for (size_t i = 0; i < num_strings; ++i) {
-    CHECK_LT(*in, end);
-    const char* string_start = reinterpret_cast<const char*>(*in);
-    strings->emplace_back(std::string(string_start));
-    *in += strings->back().length() + 1;
+  uint32_t num_strings = reinterpret_cast<const uint32_t*>(*cursor)[0];
+  if (kFillVector) {
+    strings->reserve(num_strings);
   }
-}
-
-static inline std::string ToHex(uint32_t value) {
-  std::stringstream ss;
-  ss << std::hex << value << std::dec;
-  return ss.str();
+  const uint8_t* offsets = *cursor;
+  *cursor += sizeof(uint32_t) + num_strings * sizeof(uint32_t);
+  for (uint32_t i = 0; i < num_strings; ++i) {
+    uint32_t string_offset = reinterpret_cast<const uint32_t*>(offsets)[i + 1];
+    const char* string_start = reinterpret_cast<const char*>(start + string_offset);
+    const char* string_end = reinterpret_cast<const char*>(
+        memchr(string_start, 0, end - start - string_offset));
+    if (UNLIKELY(string_end == nullptr)) {
+      return false;
+    }
+    size_t string_length = string_end - string_start;
+    if (kFillVector) {
+      strings->emplace_back(string_start, string_length);
+    }
+    *cursor = reinterpret_cast<const uint8_t*>(string_end + 1);
+  }
+  return true;
 }
 
 }  // namespace
 
 void VerifierDeps::Encode(const std::vector<const DexFile*>& dex_files,
                           std::vector<uint8_t>* buffer) const {
+  DCHECK(buffer->empty());
+  buffer->resize(dex_files.size() * sizeof(uint32_t));
+  uint32_t dex_file_index = 0;
   for (const DexFile* dex_file : dex_files) {
+    // Four byte alignment before encoding the data.
+    buffer->resize(RoundUp(buffer->size(), sizeof(uint32_t)));
+    (reinterpret_cast<uint32_t*>(buffer->data()))[dex_file_index++] = buffer->size();
     const DexFileDeps& deps = *GetDexFileDeps(*dex_file);
+    EncodeSetVector(buffer, deps.assignable_types_, deps.verified_classes_);
+    // Four byte alignment before encoding strings.
+    buffer->resize(RoundUp(buffer->size(), sizeof(uint32_t)));
     EncodeStringVector(buffer, deps.strings_);
-    EncodeSet(buffer, deps.assignable_types_);
-    EncodeSet(buffer, deps.unassignable_types_);
-    EncodeSet(buffer, deps.classes_);
-    EncodeSet(buffer, deps.fields_);
-    EncodeSet(buffer, deps.methods_);
-    EncodeUint16SparseBitVector(buffer, deps.verified_classes_, /* sparse_value= */ false);
-    EncodeUint16SparseBitVector(buffer, deps.redefined_classes_, /* sparse_value= */ true);
   }
 }
 
-void VerifierDeps::DecodeDexFileDeps(DexFileDeps& deps,
-                                     const uint8_t** data_start,
-                                     const uint8_t* data_end) {
-  DecodeStringVector(data_start, data_end, &deps.strings_);
-  DecodeSet(data_start, data_end, &deps.assignable_types_);
-  DecodeSet(data_start, data_end, &deps.unassignable_types_);
-  DecodeSet(data_start, data_end, &deps.classes_);
-  DecodeSet(data_start, data_end, &deps.fields_);
-  DecodeSet(data_start, data_end, &deps.methods_);
-  DecodeUint16SparseBitVector(data_start,
-                              data_end,
-                              &deps.verified_classes_,
-                              /* sparse_value= */ false);
-  DecodeUint16SparseBitVector(data_start,
-                              data_end,
-                              &deps.redefined_classes_,
-                              /* sparse_value= */ true);
+template <bool kOnlyVerifiedClasses>
+bool VerifierDeps::DecodeDexFileDeps(DexFileDeps& deps,
+                                     const uint8_t** cursor,
+                                     const uint8_t* data_start,
+                                     const uint8_t* data_end,
+                                     size_t num_class_defs) {
+  return
+      DecodeSetVector</*kFillSet=*/ !kOnlyVerifiedClasses>(
+          cursor,
+          data_start,
+          data_end,
+          &deps.assignable_types_,
+          &deps.verified_classes_,
+          num_class_defs) &&
+      DecodeStringVector</*kFillVector=*/ !kOnlyVerifiedClasses>(
+          cursor, data_start, data_end, &deps.strings_);
 }
 
-VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files,
-                           ArrayRef<const uint8_t> data)
-    : VerifierDeps(dex_files, /*output_only=*/ false) {
+bool VerifierDeps::ParseStoredData(const std::vector<const DexFile*>& dex_files,
+                                   ArrayRef<const uint8_t> data) {
   if (data.empty()) {
     // Return eagerly, as the first thing we expect from VerifierDeps data is
     // the number of created strings, even if there is no dependency.
     // Currently, only the boot image does not have any VerifierDeps data.
-    return;
+    return true;
   }
   const uint8_t* data_start = data.data();
   const uint8_t* data_end = data_start + data.size();
+  const uint8_t* cursor = data_start;
+  uint32_t dex_file_index = 0;
   for (const DexFile* dex_file : dex_files) {
     DexFileDeps* deps = GetDexFileDeps(*dex_file);
-    DecodeDexFileDeps(*deps, &data_start, data_end);
+    // Fetch the offset of this dex file's verifier data.
+    cursor = data_start + reinterpret_cast<const uint32_t*>(data_start)[dex_file_index++];
+    size_t num_class_defs = dex_file->NumClassDefs();
+    if (UNLIKELY(!DecodeDexFileDeps</*kOnlyVerifiedClasses=*/ false>(*deps,
+                                                                     &cursor,
+                                                                     data_start,
+                                                                     data_end,
+                                                                     num_class_defs))) {
+      LOG(ERROR) << "Failed to parse dex file dependencies for " << dex_file->GetLocation();
+      return false;
+    }
   }
-  CHECK_LE(data_start, data_end);
+  // TODO: We should check that `data_start == data_end`. Why are we passing excessive data?
+  return true;
 }
 
-std::vector<std::vector<bool>> VerifierDeps::ParseVerifiedClasses(
+bool VerifierDeps::ParseVerifiedClasses(
     const std::vector<const DexFile*>& dex_files,
-    ArrayRef<const uint8_t> data) {
+    ArrayRef<const uint8_t> data,
+    /*out*/std::vector<std::vector<bool>>* verified_classes_per_dex) {
   DCHECK(!data.empty());
   DCHECK(!dex_files.empty());
+  DCHECK(verified_classes_per_dex->empty());
 
-  std::vector<std::vector<bool>> verified_classes_per_dex;
-  verified_classes_per_dex.reserve(dex_files.size());
+  verified_classes_per_dex->reserve(dex_files.size());
 
   const uint8_t* data_start = data.data();
   const uint8_t* data_end = data_start + data.size();
+  const uint8_t* cursor = data_start;
+  uint32_t dex_file_index = 0;
   for (const DexFile* dex_file : dex_files) {
-    DexFileDeps deps(dex_file->NumClassDefs());
-    DecodeDexFileDeps(deps, &data_start, data_end);
-    verified_classes_per_dex.push_back(std::move(deps.verified_classes_));
+    DexFileDeps deps(/*num_class_defs=*/ 0u);  // Do not initialize vectors.
+    // Fetch the offset of this dex file's verifier data.
+    cursor = data_start + reinterpret_cast<const uint32_t*>(data_start)[dex_file_index++];
+    size_t num_class_defs = dex_file->NumClassDefs();
+    deps.verified_classes_.resize(num_class_defs);
+    if (UNLIKELY(!DecodeDexFileDeps</*kOnlyVerifiedClasses=*/ true>(deps,
+                                                                    &cursor,
+                                                                    data_start,
+                                                                    data_end,
+                                                                    num_class_defs))) {
+      LOG(ERROR) << "Failed to parse dex file dependencies for " << dex_file->GetLocation();
+      return false;
+    }
+    verified_classes_per_dex->push_back(std::move(deps.verified_classes_));
   }
-  return verified_classes_per_dex;
+  // TODO: We should check that `data_start == data_end`. Why are we passing excessive data?
+  return true;
 }
 
 bool VerifierDeps::Equals(const VerifierDeps& rhs) const {
@@ -822,10 +642,6 @@
 bool VerifierDeps::DexFileDeps::Equals(const VerifierDeps::DexFileDeps& rhs) const {
   return (strings_ == rhs.strings_) &&
          (assignable_types_ == rhs.assignable_types_) &&
-         (unassignable_types_ == rhs.unassignable_types_) &&
-         (classes_ == rhs.classes_) &&
-         (fields_ == rhs.fields_) &&
-         (methods_ == rhs.methods_) &&
          (verified_classes_ == rhs.verified_classes_);
 }
 
@@ -856,62 +672,16 @@
       vios->Stream() << "Extra string: " << str << "\n";
     }
 
-    for (const TypeAssignability& entry : dep.second->assignable_types_) {
+    for (size_t idx = 0; idx < dep.second->assignable_types_.size(); idx++) {
       vios->Stream()
-        << GetStringFromId(dex_file, entry.GetSource())
-        << " must be assignable to "
-        << GetStringFromId(dex_file, entry.GetDestination())
-        << "\n";
-    }
-
-    for (const TypeAssignability& entry : dep.second->unassignable_types_) {
-      vios->Stream()
-        << GetStringFromId(dex_file, entry.GetSource())
-        << " must not be assignable to "
-        << GetStringFromId(dex_file, entry.GetDestination())
-        << "\n";
-    }
-
-    for (const ClassResolution& entry : dep.second->classes_) {
-      vios->Stream()
-          << dex_file.StringByTypeIdx(entry.GetDexTypeIndex())
-          << (entry.IsResolved() ? " must be resolved " : "must not be resolved ")
-          << " with access flags " << std::hex << entry.GetAccessFlags() << std::dec
-          << "\n";
-    }
-
-    for (const FieldResolution& entry : dep.second->fields_) {
-      const dex::FieldId& field_id = dex_file.GetFieldId(entry.GetDexFieldIndex());
-      vios->Stream()
-          << dex_file.GetFieldDeclaringClassDescriptor(field_id) << "->"
-          << dex_file.GetFieldName(field_id) << ":"
-          << dex_file.GetFieldTypeDescriptor(field_id)
-          << " is expected to be ";
-      if (!entry.IsResolved()) {
-        vios->Stream() << "unresolved\n";
-      } else {
+          << "Dependencies of "
+          << dex_file.GetClassDescriptor(dex_file.GetClassDef(idx))
+          << ":\n";
+      for (const TypeAssignability& entry : dep.second->assignable_types_[idx]) {
         vios->Stream()
-          << "in class "
-          << GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
-          << ", and have the access flags " << std::hex << entry.GetAccessFlags() << std::dec
-          << "\n";
-      }
-    }
-
-    for (const MethodResolution& method : dep.second->methods_) {
-      const dex::MethodId& method_id = dex_file.GetMethodId(method.GetDexMethodIndex());
-      vios->Stream()
-          << dex_file.GetMethodDeclaringClassDescriptor(method_id) << "->"
-          << dex_file.GetMethodName(method_id)
-          << dex_file.GetMethodSignature(method_id).ToString()
-          << " is expected to be ";
-      if (!method.IsResolved()) {
-        vios->Stream() << "unresolved\n";
-      } else {
-        vios->Stream()
-          << "in class "
-          << GetStringFromId(dex_file, method.GetDeclaringClassIndex())
-          << ", have the access flags " << std::hex << method.GetAccessFlags() << std::dec
+          << GetStringFromId(dex_file, entry.GetSource())
+          << " must be assignable to "
+          << GetStringFromId(dex_file, entry.GetDestination())
           << "\n";
       }
     }
@@ -928,10 +698,9 @@
 
 bool VerifierDeps::ValidateDependencies(Thread* self,
                                         Handle<mirror::ClassLoader> class_loader,
-                                        const std::vector<const DexFile*>& classpath,
                                         /* out */ std::string* error_msg) const {
   for (const auto& entry : dex_deps_) {
-    if (!VerifyDexFile(class_loader, *entry.first, *entry.second, classpath, self, error_msg)) {
+    if (!VerifyDexFile(class_loader, *entry.first, *entry.second, self, error_msg)) {
       return false;
     }
   }
@@ -955,8 +724,7 @@
 
 bool VerifierDeps::VerifyAssignability(Handle<mirror::ClassLoader> class_loader,
                                        const DexFile& dex_file,
-                                       const std::set<TypeAssignability>& assignables,
-                                       bool expected_assignability,
+                                       const std::vector<std::set<TypeAssignability>>& assignables,
                                        Thread* self,
                                        /* out */ std::string* error_msg) const {
   StackHandleScope<2> hs(self);
@@ -964,276 +732,42 @@
   MutableHandle<mirror::Class> source(hs.NewHandle<mirror::Class>(nullptr));
   MutableHandle<mirror::Class> destination(hs.NewHandle<mirror::Class>(nullptr));
 
-  for (const auto& entry : assignables) {
-    const std::string& destination_desc = GetStringFromId(dex_file, entry.GetDestination());
-    destination.Assign(
-        FindClassAndClearException(class_linker, self, destination_desc.c_str(), class_loader));
-    const std::string& source_desc = GetStringFromId(dex_file, entry.GetSource());
-    source.Assign(
-        FindClassAndClearException(class_linker, self, source_desc.c_str(), class_loader));
+  for (const auto& vec : assignables) {
+    for (const auto& entry : vec) {
+      const std::string& destination_desc = GetStringFromId(dex_file, entry.GetDestination());
+      destination.Assign(
+          FindClassAndClearException(class_linker, self, destination_desc.c_str(), class_loader));
+      const std::string& source_desc = GetStringFromId(dex_file, entry.GetSource());
+      source.Assign(
+          FindClassAndClearException(class_linker, self, source_desc.c_str(), class_loader));
 
-    if (destination == nullptr) {
-      *error_msg = "Could not resolve class " + destination_desc;
-      return false;
-    }
-
-    if (source == nullptr) {
-      *error_msg = "Could not resolve class " + source_desc;
-      return false;
-    }
-
-    DCHECK(destination->IsResolved() && source->IsResolved());
-    if (destination->IsAssignableFrom(source.Get()) != expected_assignability) {
-      *error_msg = "Class " + destination_desc + (expected_assignability ? " not " : " ") +
-          "assignable from " + source_desc;
-      return false;
-    }
-  }
-  return true;
-}
-
-bool VerifierDeps::VerifyClasses(Handle<mirror::ClassLoader> class_loader,
-                                 const DexFile& dex_file,
-                                 const std::set<ClassResolution>& classes,
-                                 Thread* self,
-                                 /* out */ std::string* error_msg) const {
-  StackHandleScope<1> hs(self);
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  MutableHandle<mirror::Class> cls(hs.NewHandle<mirror::Class>(nullptr));
-  for (const auto& entry : classes) {
-    std::string descriptor = dex_file.StringByTypeIdx(entry.GetDexTypeIndex());
-    cls.Assign(FindClassAndClearException(class_linker, self, descriptor, class_loader));
-
-    if (entry.IsResolved()) {
-      if (cls == nullptr) {
-        *error_msg = "Could not resolve class " + descriptor;
-        return false;
-      } else if (entry.GetAccessFlags() != GetAccessFlags(cls.Get())) {
-        *error_msg = "Unexpected access flags on class " + descriptor
-            + " (expected=" + ToHex(entry.GetAccessFlags())
-            + ", actual=" + ToHex(GetAccessFlags(cls.Get())) + ")";
-        return false;
-      }
-    } else if (cls != nullptr) {
-      *error_msg = "Unexpected successful resolution of class " + descriptor;
-      return false;
-    }
-  }
-  return true;
-}
-
-static std::string GetFieldDescription(const DexFile& dex_file, uint32_t index) {
-  const dex::FieldId& field_id = dex_file.GetFieldId(index);
-  return std::string(dex_file.GetFieldDeclaringClassDescriptor(field_id))
-      + "->"
-      + dex_file.GetFieldName(field_id)
-      + ":"
-      + dex_file.GetFieldTypeDescriptor(field_id);
-}
-
-bool VerifierDeps::VerifyFields(Handle<mirror::ClassLoader> class_loader,
-                                const DexFile& dex_file,
-                                const std::set<FieldResolution>& fields,
-                                Thread* self,
-                                /* out */ std::string* error_msg) const {
-  // Check recorded fields are resolved the same way, have the same recorded class,
-  // and have the same recorded flags.
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  for (const auto& entry : fields) {
-    const dex::FieldId& field_id = dex_file.GetFieldId(entry.GetDexFieldIndex());
-    std::string_view name(dex_file.StringDataByIdx(field_id.name_idx_));
-    std::string_view type(
-        dex_file.StringDataByIdx(dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_));
-    // Only use field_id.class_idx_ when the entry is unresolved, which is rare.
-    // Otherwise, we might end up resolving an application class, which is expensive.
-    std::string expected_decl_klass = entry.IsResolved()
-        ? GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
-        : dex_file.StringByTypeIdx(field_id.class_idx_);
-    ObjPtr<mirror::Class> cls = FindClassAndClearException(
-        class_linker, self, expected_decl_klass.c_str(), class_loader);
-    if (cls == nullptr) {
-      *error_msg = "Could not resolve class " + expected_decl_klass;
-      return false;
-    }
-    DCHECK(cls->IsResolved());
-
-    ArtField* field = mirror::Class::FindField(self, cls, name, type);
-    if (entry.IsResolved()) {
-      std::string temp;
-      if (field == nullptr) {
-        *error_msg = "Could not resolve field " +
-            GetFieldDescription(dex_file, entry.GetDexFieldIndex());
-        return false;
-      } else if (expected_decl_klass != field->GetDeclaringClass()->GetDescriptor(&temp)) {
-        *error_msg = "Unexpected declaring class for field resolution "
-            + GetFieldDescription(dex_file, entry.GetDexFieldIndex())
-            + " (expected=" + expected_decl_klass
-            + ", actual=" + field->GetDeclaringClass()->GetDescriptor(&temp) + ")";
-        return false;
-      } else if (entry.GetAccessFlags() != GetAccessFlags(field)) {
-        *error_msg = "Unexpected access flags for resolved field "
-            + GetFieldDescription(dex_file, entry.GetDexFieldIndex())
-            + " (expected=" + ToHex(entry.GetAccessFlags())
-            + ", actual=" + ToHex(GetAccessFlags(field)) + ")";
-        return false;
-      }
-    } else if (field != nullptr) {
-      *error_msg = "Unexpected successful resolution of field "
-          + GetFieldDescription(dex_file, entry.GetDexFieldIndex());
-      return false;
-    }
-  }
-  return true;
-}
-
-static std::string GetMethodDescription(const DexFile& dex_file, uint32_t index) {
-  const dex::MethodId& method_id = dex_file.GetMethodId(index);
-  return std::string(dex_file.GetMethodDeclaringClassDescriptor(method_id))
-      + "->"
-      + dex_file.GetMethodName(method_id)
-      + dex_file.GetMethodSignature(method_id).ToString();
-}
-
-bool VerifierDeps::VerifyMethods(Handle<mirror::ClassLoader> class_loader,
-                                 const DexFile& dex_file,
-                                 const std::set<MethodResolution>& methods,
-                                 Thread* self,
-                                 /* out */ std::string* error_msg) const {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  PointerSize pointer_size = class_linker->GetImagePointerSize();
-
-  for (const auto& entry : methods) {
-    const dex::MethodId& method_id = dex_file.GetMethodId(entry.GetDexMethodIndex());
-
-    const char* name = dex_file.GetMethodName(method_id);
-    const Signature signature = dex_file.GetMethodSignature(method_id);
-    // Only use method_id.class_idx_ when the entry is unresolved, which is rare.
-    // Otherwise, we might end up resolving an application class, which is expensive.
-    std::string expected_decl_klass = entry.IsResolved()
-        ? GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
-        : dex_file.StringByTypeIdx(method_id.class_idx_);
-
-    ObjPtr<mirror::Class> cls = FindClassAndClearException(
-        class_linker, self, expected_decl_klass.c_str(), class_loader);
-    if (cls == nullptr) {
-      *error_msg = "Could not resolve class " + expected_decl_klass;
-      return false;
-    }
-    DCHECK(cls->IsResolved());
-    ArtMethod* method = nullptr;
-    if (cls->IsInterface()) {
-      method = cls->FindInterfaceMethod(name, signature, pointer_size);
-    } else {
-      method = cls->FindClassMethod(name, signature, pointer_size);
-    }
-
-    if (entry.IsResolved()) {
-      std::string temp;
-      if (method == nullptr) {
-        *error_msg = "Could not resolve method "
-            + GetMethodDescription(dex_file, entry.GetDexMethodIndex());
-        return false;
-      } else if (expected_decl_klass != method->GetDeclaringClass()->GetDescriptor(&temp)) {
-        *error_msg = "Unexpected declaring class for method resolution "
-            + GetMethodDescription(dex_file, entry.GetDexMethodIndex())
-            + " (expected=" + expected_decl_klass
-            + ", actual=" + method->GetDeclaringClass()->GetDescriptor(&temp) + ")";
-        return false;
-      } else if (entry.GetAccessFlags() != GetAccessFlags(method)) {
-        *error_msg = "Unexpected access flags for resolved method resolution "
-            + GetMethodDescription(dex_file, entry.GetDexMethodIndex())
-            + " (expected=" + ToHex(entry.GetAccessFlags())
-            + ", actual=" + ToHex(GetAccessFlags(method)) + ")";
-        return false;
-      }
-    } else if (method != nullptr) {
-      *error_msg = "Unexpected successful resolution of method "
-          + GetMethodDescription(dex_file, entry.GetDexMethodIndex());
-      return false;
-    }
-  }
-  return true;
-}
-
-bool VerifierDeps::IsInDexFiles(const char* descriptor,
-                                size_t hash,
-                                const std::vector<const DexFile*>& dex_files,
-                                /* out */ const DexFile** out_dex_file) const {
-  for (const DexFile* dex_file : dex_files) {
-    if (OatDexFile::FindClassDef(*dex_file, descriptor, hash) != nullptr) {
-      *out_dex_file = dex_file;
-      return true;
-    }
-  }
-  return false;
-}
-
-bool VerifierDeps::VerifyInternalClasses(const DexFile& dex_file,
-                                         const std::vector<const DexFile*>& classpath,
-                                         const std::vector<bool>& verified_classes,
-                                         const std::vector<bool>& redefined_classes,
-                                         /* out */ std::string* error_msg) const {
-  const std::vector<const DexFile*>& boot_classpath =
-      Runtime::Current()->GetClassLinker()->GetBootClassPath();
-
-  for (ClassAccessor accessor : dex_file.GetClasses()) {
-    const char* descriptor = accessor.GetDescriptor();
-
-    const uint16_t class_def_index = accessor.GetClassDefIndex();
-    if (redefined_classes[class_def_index]) {
-      if (verified_classes[class_def_index]) {
-        *error_msg = std::string("Class ") + descriptor + " marked both verified and redefined";
-        return false;
+      if (destination == nullptr || source == nullptr) {
+        // We currently don't use assignability information for unresolved
+        // types, as the status of the class using unresolved types will be soft
+        // fail in the vdex.
+        continue;
       }
 
-      // Class was not verified under these dependencies. No need to check it further.
-      continue;
-    }
-
-    // Check that the class resolved into the same dex file. Otherwise there is
-    // a different class with the same descriptor somewhere in one of the parent
-    // class loaders.
-    const size_t hash = ComputeModifiedUtf8Hash(descriptor);
-    const DexFile* cp_dex_file = nullptr;
-    if (IsInDexFiles(descriptor, hash, boot_classpath, &cp_dex_file) ||
-        IsInDexFiles(descriptor, hash, classpath, &cp_dex_file)) {
-      *error_msg = std::string("Class ") + descriptor
-          + " redefines a class in the classpath "
-          + "(dexFile expected=" + dex_file.GetLocation()
-          + ", actual=" + cp_dex_file->GetLocation() + ")";
-      return false;
+      DCHECK(destination->IsResolved() && source->IsResolved());
+      if (!destination->IsAssignableFrom(source.Get())) {
+        *error_msg = "Class " + destination_desc + " not assignable from " + source_desc;
+        return false;
+      }
     }
   }
-
   return true;
 }
 
 bool VerifierDeps::VerifyDexFile(Handle<mirror::ClassLoader> class_loader,
                                  const DexFile& dex_file,
                                  const DexFileDeps& deps,
-                                 const std::vector<const DexFile*>& classpath,
                                  Thread* self,
                                  /* out */ std::string* error_msg) const {
-  return VerifyInternalClasses(dex_file,
-                               classpath,
-                               deps.verified_classes_,
-                               deps.redefined_classes_,
-                               error_msg) &&
-         VerifyAssignability(class_loader,
+  return VerifyAssignability(class_loader,
                              dex_file,
                              deps.assignable_types_,
-                             /* expected_assignability= */ true,
                              self,
-                             error_msg) &&
-         VerifyAssignability(class_loader,
-                             dex_file,
-                             deps.unassignable_types_,
-                             /* expected_assignability= */ false,
-                             self,
-                             error_msg) &&
-         VerifyClasses(class_loader, dex_file, deps.classes_, self, error_msg) &&
-         VerifyFields(class_loader, dex_file, deps.fields_, self, error_msg) &&
-         VerifyMethods(class_loader, dex_file, deps.methods_, self, error_msg);
+                             error_msg);
 }
 
 }  // namespace verifier
diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h
index 3980ca2..0c448f8 100644
--- a/runtime/verifier/verifier_deps.h
+++ b/runtime/verifier/verifier_deps.h
@@ -44,6 +44,8 @@
 
 namespace verifier {
 
+class RegType;
+
 // Verification dependencies collector class used by the MethodVerifier to record
 // resolution outcomes and type assignability tests of classes/methods/fields
 // not present in the set of compiled DEX files, that is classes/methods/fields
@@ -58,9 +60,14 @@
 // changes in the classpath.
 class VerifierDeps {
  public:
-  explicit VerifierDeps(const std::vector<const DexFile*>& dex_files);
+  explicit VerifierDeps(const std::vector<const DexFile*>& dex_files, bool output_only = true);
 
-  VerifierDeps(const std::vector<const DexFile*>& dex_files, ArrayRef<const uint8_t> data);
+  // Marker to know whether a class is verified. A non-verified class will have
+  // this marker as its offset entry in the encoded data.
+  static uint32_t constexpr kNotVerifiedMarker = std::numeric_limits<uint32_t>::max();
+
+  // Fill dependencies from stored data. Returns true on success, false on failure.
+  bool ParseStoredData(const std::vector<const DexFile*>& dex_files, ArrayRef<const uint8_t> data);
 
   // Merge `other` into this `VerifierDeps`'. `other` and `this` must be for the
   // same set of dex files.
@@ -73,48 +80,30 @@
       REQUIRES(!Locks::verifier_deps_lock_);
 
   // Record the verification status of the class defined in `class_def`.
-  static void MaybeRecordVerificationStatus(const DexFile& dex_file,
+  static void MaybeRecordVerificationStatus(VerifierDeps* verifier_deps,
+                                            const DexFile& dex_file,
                                             const dex::ClassDef& class_def,
                                             FailureKind failure_kind)
       REQUIRES(!Locks::verifier_deps_lock_);
 
-  // Record that class defined in `class_def` was not verified because it redefines
-  // a class with the same descriptor which takes precedence in class resolution.
-  static void MaybeRecordClassRedefinition(const DexFile& dex_file, const dex::ClassDef& class_def)
-      REQUIRES(!Locks::verifier_deps_lock_);
-
-  // Record the outcome `klass` of resolving type `type_idx` from `dex_file`.
-  // If `klass` is null, the class is assumed unresolved.
-  static void MaybeRecordClassResolution(const DexFile& dex_file,
-                                         dex::TypeIndex type_idx,
-                                         ObjPtr<mirror::Class> klass)
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::verifier_deps_lock_);
-
-  // Record the outcome `field` of resolving field `field_idx` from `dex_file`.
-  // If `field` is null, the field is assumed unresolved.
-  static void MaybeRecordFieldResolution(const DexFile& dex_file,
-                                         uint32_t field_idx,
-                                         ArtField* field)
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::verifier_deps_lock_);
-
-  // Record the outcome `method` of resolving method `method_idx` from `dex_file`.
-  // If `method` is null, the method is assumed unresolved.
-  static void MaybeRecordMethodResolution(const DexFile& dex_file,
-                                          uint32_t method_idx,
-                                          ArtMethod* method)
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::verifier_deps_lock_);
-
   // Record the outcome `is_assignable` of type assignability test from `source`
   // to `destination` as defined by RegType::AssignableFrom. `dex_file` is the
   // owner of the method for which MethodVerifier performed the assignability test.
-  static void MaybeRecordAssignability(const DexFile& dex_file,
+  static void MaybeRecordAssignability(VerifierDeps* verifier_deps,
+                                       const DexFile& dex_file,
+                                       const dex::ClassDef& class_def,
                                        ObjPtr<mirror::Class> destination,
-                                       ObjPtr<mirror::Class> source,
-                                       bool is_strict,
-                                       bool is_assignable)
+                                       ObjPtr<mirror::Class> source)
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!Locks::verifier_deps_lock_);
+
+  // Record that `source` is assignable to `destination`. `dex_file` is the
+  // owner of the method for which MethodVerifier performed the assignability test.
+  static void MaybeRecordAssignability(VerifierDeps* verifier_deps,
+                                       const DexFile& dex_file,
+                                       const dex::ClassDef& class_def,
+                                       const RegType& destination,
+                                       const RegType& source)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::verifier_deps_lock_);
 
@@ -128,7 +117,6 @@
   // Verify the encoded dependencies of this `VerifierDeps` are still valid.
   bool ValidateDependencies(Thread* self,
                             Handle<mirror::ClassLoader> class_loader,
-                            const std::vector<const DexFile*>& classpath,
                             /* out */ std::string* error_msg) const
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -136,63 +124,25 @@
     return GetDexFileDeps(dex_file)->verified_classes_;
   }
 
-  const std::vector<bool>& GetRedefinedClasses(const DexFile& dex_file) const {
-    return GetDexFileDeps(dex_file)->redefined_classes_;
-  }
+  // Whether this `verifier_deps` has recorded that the given class is verified.
+  bool HasRecordedVerifiedStatus(const DexFile& dex_file, const dex::ClassDef& class_def)
+      REQUIRES(!Locks::verifier_deps_lock_);
 
   bool OutputOnly() const {
     return output_only_;
   }
 
+  bool ContainsDexFile(const DexFile& dex_file) const {
+    return GetDexFileDeps(dex_file) != nullptr;
+  }
+
   // Parses raw VerifierDeps data to extract bitvectors of which class def indices
   // were verified or not. The given `dex_files` must match the order and count of
   // dex files used to create the VerifierDeps.
-  static std::vector<std::vector<bool>> ParseVerifiedClasses(
+  static bool ParseVerifiedClasses(
       const std::vector<const DexFile*>& dex_files,
-      ArrayRef<const uint8_t> data);
-
- private:
-  static constexpr uint16_t kUnresolvedMarker = static_cast<uint16_t>(-1);
-
-  using ClassResolutionBase = std::tuple<dex::TypeIndex, uint16_t>;
-  struct ClassResolution : public ClassResolutionBase {
-    ClassResolution() = default;
-    ClassResolution(const ClassResolution&) = default;
-    ClassResolution(dex::TypeIndex type_idx, uint16_t access_flags)
-        : ClassResolutionBase(type_idx, access_flags) {}
-
-    bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
-    dex::TypeIndex GetDexTypeIndex() const { return std::get<0>(*this); }
-    uint16_t GetAccessFlags() const { return std::get<1>(*this); }
-  };
-
-  using FieldResolutionBase = std::tuple<uint32_t, uint16_t, dex::StringIndex>;
-  struct FieldResolution : public FieldResolutionBase {
-    FieldResolution() = default;
-    FieldResolution(const FieldResolution&) = default;
-    FieldResolution(uint32_t field_idx, uint16_t access_flags, dex::StringIndex declaring_class_idx)
-        : FieldResolutionBase(field_idx, access_flags, declaring_class_idx) {}
-
-    bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
-    uint32_t GetDexFieldIndex() const { return std::get<0>(*this); }
-    uint16_t GetAccessFlags() const { return std::get<1>(*this); }
-    dex::StringIndex GetDeclaringClassIndex() const { return std::get<2>(*this); }
-  };
-
-  using MethodResolutionBase = std::tuple<uint32_t, uint16_t, dex::StringIndex>;
-  struct MethodResolution : public MethodResolutionBase {
-    MethodResolution() = default;
-    MethodResolution(const MethodResolution&) = default;
-    MethodResolution(uint32_t method_idx,
-                     uint16_t access_flags,
-                     dex::StringIndex declaring_class_idx)
-        : MethodResolutionBase(method_idx, access_flags, declaring_class_idx) {}
-
-    bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
-    uint32_t GetDexMethodIndex() const { return std::get<0>(*this); }
-    uint16_t GetAccessFlags() const { return std::get<1>(*this); }
-    dex::StringIndex GetDeclaringClassIndex() const { return std::get<2>(*this); }
-  };
+      ArrayRef<const uint8_t> data,
+      /*out*/std::vector<std::vector<bool>>* verified_classes_per_dex);
 
   using TypeAssignabilityBase = std::tuple<dex::StringIndex, dex::StringIndex>;
   struct TypeAssignability : public TypeAssignabilityBase {
@@ -205,46 +155,37 @@
     dex::StringIndex GetSource() const { return std::get<1>(*this); }
   };
 
+ private:
   // Data structure representing dependencies collected during verification of
   // methods inside one DexFile.
   struct DexFileDeps {
     explicit DexFileDeps(size_t num_class_defs)
-        : verified_classes_(num_class_defs),
-          redefined_classes_(num_class_defs) {}
+        : assignable_types_(num_class_defs),
+          verified_classes_(num_class_defs) {}
 
     // Vector of strings which are not present in the corresponding DEX file.
     // These are referred to with ids starting with `NumStringIds()` of that DexFile.
     std::vector<std::string> strings_;
 
-    // Set of class pairs recording the outcome of assignability test from one
-    // of the two types to the other.
-    std::set<TypeAssignability> assignable_types_;
-    std::set<TypeAssignability> unassignable_types_;
-
-    // Sets of recorded class/field/method resolutions.
-    std::set<ClassResolution> classes_;
-    std::set<FieldResolution> fields_;
-    std::set<MethodResolution> methods_;
+    // Vector that contains for each class def defined in a dex file, a set of class pairs recording
+    // the outcome of assignability test from one of the two types to the other.
+    std::vector<std::set<TypeAssignability>> assignable_types_;
 
     // Bit vector indexed by class def indices indicating whether the corresponding
     // class was successfully verified.
     std::vector<bool> verified_classes_;
 
-    // Bit vector indexed by class def indices indicating whether the corresponding
-    // class resolved into a different class with the same descriptor (was eclipsed).
-    // The other class might have been both external (not covered by these VerifierDeps)
-    // and internal (same VerifierDeps, different DexFileDeps).
-    std::vector<bool> redefined_classes_;
-
     bool Equals(const DexFileDeps& rhs) const;
   };
 
-  VerifierDeps(const std::vector<const DexFile*>& dex_files, bool output_only);
-
   // Helper function to share DexFileDeps decoding code.
-  static void DecodeDexFileDeps(DexFileDeps& deps,
-                                const uint8_t** data_start,
-                                const uint8_t* data_end);
+  // Returns true on success, false on failure.
+  template <bool kOnlyVerifiedClasses>
+  static bool DecodeDexFileDeps(DexFileDeps& deps,
+                                const uint8_t** cursor,
+                                const uint8_t* data_start,
+                                const uint8_t* data_end,
+                                size_t num_class_defs);
 
   // Finds the DexFileDep instance associated with `dex_file`, or nullptr if
   // `dex_file` is not reported as being compiled.
@@ -252,18 +193,6 @@
 
   const DexFileDeps* GetDexFileDeps(const DexFile& dex_file) const;
 
-  // Returns true if `klass` is null or not defined in any of dex files which
-  // were reported as being compiled.
-  bool IsInClassPath(ObjPtr<mirror::Class> klass) const
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Finds the class in the classpath that makes `source` inherit` from `destination`.
-  // Returns null if a class defined in the compiled DEX files, and assignable to
-  // `source`, direclty inherits from `destination`.
-  ObjPtr<mirror::Class> FindOneClassPathBoundaryForInterface(ObjPtr<mirror::Class> destination,
-                                                             ObjPtr<mirror::Class> source) const
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Returns the index of `str`. If it is defined in `dex_file_`, this is the dex
   // string ID. If not, an ID is assigned to the string and cached in `strings_`
   // of the corresponding DexFileDeps structure (either provided or inferred from
@@ -274,51 +203,21 @@
   // Returns the string represented by `id`.
   std::string GetStringFromId(const DexFile& dex_file, dex::StringIndex string_id) const;
 
-  // Returns the bytecode access flags of `element` (bottom 16 bits), or
-  // `kUnresolvedMarker` if `element` is null.
-  template <typename Ptr>
-  static uint16_t GetAccessFlags(Ptr element)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Returns a string ID of the descriptor of the declaring class of `element`,
-  // or `kUnresolvedMarker` if `element` is null.
-  dex::StringIndex GetMethodDeclaringClassStringId(const DexFile& dex_file,
-                                                   uint32_t dex_method_idx,
-                                                   ArtMethod* method)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-  dex::StringIndex GetFieldDeclaringClassStringId(const DexFile& dex_file,
-                                                  uint32_t dex_field_idx,
-                                                  ArtField* field)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Returns a string ID of the descriptor of the class.
   dex::StringIndex GetClassDescriptorStringId(const DexFile& dex_file, ObjPtr<mirror::Class> klass)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::verifier_deps_lock_);
 
-  void AddClassResolution(const DexFile& dex_file,
-                          dex::TypeIndex type_idx,
-                          ObjPtr<mirror::Class> klass)
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::verifier_deps_lock_);
-
-  void AddFieldResolution(const DexFile& dex_file,
-                          uint32_t field_idx,
-                          ArtField* field)
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::verifier_deps_lock_);
-
-  void AddMethodResolution(const DexFile& dex_file,
-                           uint32_t method_idx,
-                           ArtMethod* method)
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::verifier_deps_lock_);
+  void AddAssignability(const DexFile& dex_file,
+                        const dex::ClassDef& class_def,
+                        ObjPtr<mirror::Class> destination,
+                        ObjPtr<mirror::Class> source)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
   void AddAssignability(const DexFile& dex_file,
-                        ObjPtr<mirror::Class> destination,
-                        ObjPtr<mirror::Class> source,
-                        bool is_strict,
-                        bool is_assignable)
+                        const dex::ClassDef& class_def,
+                        const RegType& destination,
+                        const RegType& source)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   bool Equals(const VerifierDeps& rhs) const;
@@ -329,7 +228,6 @@
   bool VerifyDexFile(Handle<mirror::ClassLoader> class_loader,
                      const DexFile& dex_file,
                      const DexFileDeps& deps,
-                     const std::vector<const DexFile*>& classpath,
                      Thread* self,
                      /* out */ std::string* error_msg) const
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -341,58 +239,13 @@
                     const std::vector<const DexFile*>& dex_files,
                     /* out */ const DexFile** cp_dex_file) const;
 
-  // Check that classes which are to be verified using these dependencies
-  // are not eclipsed by classes in parent class loaders, e.g. when vdex was
-  // created against SDK stubs and the app redefines a non-public class on
-  // boot classpath, or simply if a class is added during an OTA. In such cases,
-  // dependencies do not include the dependencies on the presumed-internal class
-  // and verification must fail unless the class was recorded to have been
-  // redefined during dependencies' generation too.
-  bool VerifyInternalClasses(const DexFile& dex_file,
-                             const std::vector<const DexFile*>& classpath,
-                             const std::vector<bool>& verified_classes,
-                             const std::vector<bool>& redefined_classes,
-                             /* out */ std::string* error_msg) const
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   bool VerifyAssignability(Handle<mirror::ClassLoader> class_loader,
                            const DexFile& dex_file,
-                           const std::set<TypeAssignability>& assignables,
-                           bool expected_assignability,
+                           const std::vector<std::set<TypeAssignability>>& assignables,
                            Thread* self,
                            /* out */ std::string* error_msg) const
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Verify that the set of resolved classes at the point of creation
-  // of this `VerifierDeps` is still the same.
-  bool VerifyClasses(Handle<mirror::ClassLoader> class_loader,
-                     const DexFile& dex_file,
-                     const std::set<ClassResolution>& classes,
-                     Thread* self,
-                     /* out */ std::string* error_msg) const
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
-  // Verify that the set of resolved fields at the point of creation
-  // of this `VerifierDeps` is still the same, and each field resolves to the
-  // same field holder and access flags.
-  bool VerifyFields(Handle<mirror::ClassLoader> class_loader,
-                    const DexFile& dex_file,
-                    const std::set<FieldResolution>& classes,
-                    Thread* self,
-                    /* out */ std::string* error_msg) const
-      REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(!Locks::verifier_deps_lock_);
-
-  // Verify that the set of resolved methods at the point of creation
-  // of this `VerifierDeps` is still the same, and each method resolves to the
-  // same method holder, access flags, and invocation kind.
-  bool VerifyMethods(Handle<mirror::ClassLoader> class_loader,
-                     const DexFile& dex_file,
-                     const std::set<MethodResolution>& methods,
-                     Thread* self,
-                     /* out */ std::string* error_msg) const
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Map from DexFiles into dependencies collected from verification of their methods.
   std::map<const DexFile*, std::unique_ptr<DexFileDeps>> dex_deps_;
 
diff --git a/runtime/verifier/verifier_enums.h b/runtime/verifier/verifier_enums.h
index 33eca4d..16bf004 100644
--- a/runtime/verifier/verifier_enums.h
+++ b/runtime/verifier/verifier_enums.h
@@ -33,10 +33,11 @@
 enum class FailureKind {
   kNoFailure,
   kAccessChecksFailure,
+  kTypeChecksFailure,
   kSoftFailure,
   kHardFailure,
 };
-std::ostream& operator<<(std::ostream& os, const FailureKind& rhs);
+std::ostream& operator<<(std::ostream& os, FailureKind rhs);
 
 // How to log hard failures during verification.
 enum class HardFailLogMode {
@@ -62,7 +63,7 @@
   METHOD_INTERFACE,   // interface
   METHOD_POLYMORPHIC  // polymorphic
 };
-std::ostream& operator<<(std::ostream& os, const MethodType& rhs);
+std::ostream& operator<<(std::ostream& os, MethodType rhs);
 
 /*
  * An enumeration of problems that can turn up during verification.
@@ -79,7 +80,7 @@
                                              // runtime.
 
   VERIFY_ERROR_NO_CLASS =          1 << 2,   // NoClassDefFoundError.
-  VERIFY_ERROR_NO_FIELD =          1 << 3,   // NoSuchFieldError.
+  VERIFY_ERROR_UNRESOLVED_TYPE_CHECK = 1 << 3,   // Missing class for doing a type check
   VERIFY_ERROR_NO_METHOD =         1 << 4,   // NoSuchMethodError.
   VERIFY_ERROR_ACCESS_CLASS =      1 << 5,   // IllegalAccessError.
   VERIFY_ERROR_ACCESS_FIELD =      1 << 6,   // IllegalAccessError.
@@ -101,7 +102,7 @@
                                              // code. May be removed once the compiler handles
                                              // unreachable code correctly.
 };
-std::ostream& operator<<(std::ostream& os, const VerifyError& rhs);
+std::ostream& operator<<(std::ostream& os, VerifyError rhs);
 
 }  // namespace verifier
 }  // namespace art
diff --git a/runtime/verify_object.cc b/runtime/verify_object.cc
index 2b8c7da..61b502d 100644
--- a/runtime/verify_object.cc
+++ b/runtime/verify_object.cc
@@ -30,8 +30,8 @@
     // Slow object verification, try the heap right away.
     Runtime::Current()->GetHeap()->VerifyObjectBody(obj);
   } else {
-    // Fast object verification, only call the heap if our quick sanity tests fail. The heap will
-    // print the diagnostic message.
+    // Fast object verification, only call the heap if our quick checks fail.
+    // The heap will print the diagnostic message.
     bool failed = !IsAligned<kObjectAlignment>(obj.Ptr());
     if (!failed) {
       mirror::Class* c = obj->GetClass<kVerifyNone>();
diff --git a/runtime/verify_object.h b/runtime/verify_object.h
index cc288e7..ae87cad 100644
--- a/runtime/verify_object.h
+++ b/runtime/verify_object.h
@@ -29,11 +29,11 @@
 class Object;
 }  // namespace mirror
 
-// How we want to sanity check the heap's correctness.
+// How we want to check the heap's correctness.
 enum VerifyObjectMode {
   kVerifyObjectModeDisabled,  // Heap verification is disabled.
-  kVerifyObjectModeFast,  // Sanity heap accesses quickly by using VerifyClassClass.
-  kVerifyObjectModeAll  // Sanity heap accesses thoroughly.
+  kVerifyObjectModeFast,  // Check heap accesses quickly by using VerifyClassClass.
+  kVerifyObjectModeAll  // Check heap accesses thoroughly.
 };
 
 enum VerifyObjectFlags {
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index fabd4db..3b3a1a3 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -75,6 +75,8 @@
 jclass WellKnownClasses::java_lang_Thread;
 jclass WellKnownClasses::java_lang_ThreadGroup;
 jclass WellKnownClasses::java_lang_Throwable;
+jclass WellKnownClasses::java_lang_Void;
+jclass WellKnownClasses::java_nio_Buffer;
 jclass WellKnownClasses::java_nio_ByteBuffer;
 jclass WellKnownClasses::java_nio_DirectByteBuffer;
 jclass WellKnownClasses::java_util_Collections;
@@ -96,7 +98,9 @@
 jmethodID WellKnownClasses::java_lang_Daemons_start;
 jmethodID WellKnownClasses::java_lang_Daemons_stop;
 jmethodID WellKnownClasses::java_lang_Daemons_waitForDaemonStart;
+jmethodID WellKnownClasses::java_lang_Double_doubleToRawLongBits;
 jmethodID WellKnownClasses::java_lang_Double_valueOf;
+jmethodID WellKnownClasses::java_lang_Float_floatToRawIntBits;
 jmethodID WellKnownClasses::java_lang_Float_valueOf;
 jmethodID WellKnownClasses::java_lang_Integer_valueOf;
 jmethodID WellKnownClasses::java_lang_invoke_MethodHandles_lookup;
@@ -116,6 +120,7 @@
 jmethodID WellKnownClasses::java_lang_Thread_run;
 jmethodID WellKnownClasses::java_lang_ThreadGroup_add;
 jmethodID WellKnownClasses::java_lang_ThreadGroup_removeThread;
+jmethodID WellKnownClasses::java_nio_Buffer_isDirect;
 jmethodID WellKnownClasses::java_nio_DirectByteBuffer_init;
 jmethodID WellKnownClasses::java_util_function_Consumer_accept;
 jmethodID WellKnownClasses::libcore_reflect_AnnotationFactory_createAnnotation;
@@ -131,7 +136,6 @@
 jfieldID WellKnownClasses::dalvik_system_DexPathList__Element_dexFile;
 jfieldID WellKnownClasses::dalvik_system_VMRuntime_nonSdkApiUsageConsumer;
 jfieldID WellKnownClasses::java_io_FileDescriptor_descriptor;
-jfieldID WellKnownClasses::java_io_FileDescriptor_ownerId;
 jfieldID WellKnownClasses::java_lang_Thread_parkBlocker;
 jfieldID WellKnownClasses::java_lang_Thread_daemon;
 jfieldID WellKnownClasses::java_lang_Thread_group;
@@ -153,6 +157,7 @@
 jfieldID WellKnownClasses::java_lang_Throwable_stackState;
 jfieldID WellKnownClasses::java_lang_Throwable_suppressedExceptions;
 jfieldID WellKnownClasses::java_nio_Buffer_address;
+jfieldID WellKnownClasses::java_nio_Buffer_capacity;
 jfieldID WellKnownClasses::java_nio_Buffer_elementSizeShift;
 jfieldID WellKnownClasses::java_nio_Buffer_limit;
 jfieldID WellKnownClasses::java_nio_Buffer_position;
@@ -161,8 +166,6 @@
 jfieldID WellKnownClasses::java_nio_ByteBuffer_isReadOnly;
 jfieldID WellKnownClasses::java_nio_ByteBuffer_limit;
 jfieldID WellKnownClasses::java_nio_ByteBuffer_offset;
-jfieldID WellKnownClasses::java_nio_DirectByteBuffer_capacity;
-jfieldID WellKnownClasses::java_nio_DirectByteBuffer_effectiveDirectAddress;
 jfieldID WellKnownClasses::java_util_Collections_EMPTY_LIST;
 jfieldID WellKnownClasses::libcore_util_EmptyArray_STACK_TRACE_ELEMENT;
 jfieldID WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_data;
@@ -364,6 +367,8 @@
   java_lang_Thread = CacheClass(env, "java/lang/Thread");
   java_lang_ThreadGroup = CacheClass(env, "java/lang/ThreadGroup");
   java_lang_Throwable = CacheClass(env, "java/lang/Throwable");
+  java_lang_Void = CacheClass(env, "java/lang/Void");
+  java_nio_Buffer = CacheClass(env, "java/nio/Buffer");
   java_nio_ByteBuffer = CacheClass(env, "java/nio/ByteBuffer");
   java_nio_DirectByteBuffer = CacheClass(env, "java/nio/DirectByteBuffer");
   java_util_Collections = CacheClass(env, "java/util/Collections");
@@ -405,6 +410,7 @@
   java_lang_Thread_run = CacheMethod(env, java_lang_Thread, false, "run", "()V");
   java_lang_ThreadGroup_add = CacheMethod(env, java_lang_ThreadGroup, false, "add", "(Ljava/lang/Thread;)V");
   java_lang_ThreadGroup_removeThread = CacheMethod(env, java_lang_ThreadGroup, false, "threadTerminated", "(Ljava/lang/Thread;)V");
+  java_nio_Buffer_isDirect = CacheMethod(env, java_nio_Buffer, false, "isDirect", "()Z");
   java_nio_DirectByteBuffer_init = CacheMethod(env, java_nio_DirectByteBuffer, false, "<init>", "(JI)V");
   java_util_function_Consumer_accept = CacheMethod(env, java_util_function_Consumer, false, "accept", "(Ljava/lang/Object;)V");
   libcore_reflect_AnnotationFactory_createAnnotation = CacheMethod(env, libcore_reflect_AnnotationFactory, true, "createAnnotation", "(Ljava/lang/Class;[Llibcore/reflect/AnnotationMember;)Ljava/lang/annotation/Annotation;");
@@ -422,7 +428,6 @@
 
   ScopedLocalRef<jclass> java_io_FileDescriptor(env, env->FindClass("java/io/FileDescriptor"));
   java_io_FileDescriptor_descriptor = CacheField(env, java_io_FileDescriptor.get(), false, "descriptor", "I");
-  java_io_FileDescriptor_ownerId = CacheField(env, java_io_FileDescriptor.get(), false, "ownerId", "J");
 
   java_lang_Thread_parkBlocker = CacheField(env, java_lang_Thread, false, "parkBlocker", "Ljava/lang/Object;");
   java_lang_Thread_daemon = CacheField(env, java_lang_Thread, false, "daemon", "Z");
@@ -445,19 +450,17 @@
   java_lang_Throwable_stackState = CacheField(env, java_lang_Throwable, false, "backtrace", "Ljava/lang/Object;");
   java_lang_Throwable_suppressedExceptions = CacheField(env, java_lang_Throwable, false, "suppressedExceptions", "Ljava/util/List;");
 
-  ScopedLocalRef<jclass> java_nio_Buffer(env, env->FindClass("java/nio/Buffer"));
-  java_nio_Buffer_address = CacheField(env, java_nio_Buffer.get(), false, "address", "J");
-  java_nio_Buffer_elementSizeShift = CacheField(env, java_nio_Buffer.get(), false, "_elementSizeShift", "I");
-  java_nio_Buffer_limit = CacheField(env, java_nio_Buffer.get(), false, "limit", "I");
-  java_nio_Buffer_position = CacheField(env, java_nio_Buffer.get(), false, "position", "I");
+  java_nio_Buffer_address = CacheField(env, java_nio_Buffer, false, "address", "J");
+  java_nio_Buffer_capacity = CacheField(env, java_nio_Buffer, false, "capacity", "I");
+  java_nio_Buffer_elementSizeShift = CacheField(env, java_nio_Buffer, false, "_elementSizeShift", "I");
+  java_nio_Buffer_limit = CacheField(env, java_nio_Buffer, false, "limit", "I");
+  java_nio_Buffer_position = CacheField(env, java_nio_Buffer, false, "position", "I");
 
   java_nio_ByteBuffer_address = CacheField(env, java_nio_ByteBuffer, false, "address", "J");
   java_nio_ByteBuffer_hb = CacheField(env, java_nio_ByteBuffer, false, "hb", "[B");
   java_nio_ByteBuffer_isReadOnly = CacheField(env, java_nio_ByteBuffer, false, "isReadOnly", "Z");
   java_nio_ByteBuffer_limit = CacheField(env, java_nio_ByteBuffer, false, "limit", "I");
   java_nio_ByteBuffer_offset = CacheField(env, java_nio_ByteBuffer, false, "offset", "I");
-  java_nio_DirectByteBuffer_capacity = CacheField(env, java_nio_DirectByteBuffer, false, "capacity", "I");
-  java_nio_DirectByteBuffer_effectiveDirectAddress = CacheField(env, java_nio_DirectByteBuffer, false, "address", "J");
   java_util_Collections_EMPTY_LIST = CacheField(env, java_util_Collections, true, "EMPTY_LIST", "Ljava/util/List;");
   libcore_util_EmptyArray_STACK_TRACE_ELEMENT = CacheField(env, libcore_util_EmptyArray, true, "STACK_TRACE_ELEMENT", "[Ljava/lang/StackTraceElement;");
   org_apache_harmony_dalvik_ddmc_Chunk_data = CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, false, "data", "[B");
@@ -473,6 +476,11 @@
   java_lang_Integer_valueOf = CachePrimitiveBoxingMethod(env, 'I', "java/lang/Integer");
   java_lang_Long_valueOf = CachePrimitiveBoxingMethod(env, 'J', "java/lang/Long");
   java_lang_Short_valueOf = CachePrimitiveBoxingMethod(env, 'S', "java/lang/Short");
+
+  java_lang_Double_doubleToRawLongBits =
+      CacheMethod(env, "java/lang/Double", /*is_static=*/ true, "doubleToRawLongBits", "(D)J");
+  java_lang_Float_floatToRawIntBits =
+      CacheMethod(env, "java/lang/Float", /*is_static=*/ true, "floatToRawIntBits", "(F)I");
 }
 
 void WellKnownClasses::LateInit(JNIEnv* env) {
@@ -537,7 +545,9 @@
   java_lang_Thread = nullptr;
   java_lang_ThreadGroup = nullptr;
   java_lang_Throwable = nullptr;
+  java_lang_Void = nullptr;
   java_util_Collections = nullptr;
+  java_nio_Buffer = nullptr;
   java_nio_ByteBuffer = nullptr;
   java_nio_DirectByteBuffer = nullptr;
   libcore_reflect_AnnotationFactory = nullptr;
@@ -550,7 +560,6 @@
   dalvik_system_VMRuntime_runFinalization = nullptr;
   dalvik_system_VMRuntime_hiddenApiUsed = nullptr;
   java_io_FileDescriptor_descriptor = nullptr;
-  java_io_FileDescriptor_ownerId = nullptr;
   java_lang_Boolean_valueOf = nullptr;
   java_lang_Byte_valueOf = nullptr;
   java_lang_Character_valueOf = nullptr;
@@ -558,7 +567,9 @@
   java_lang_ClassNotFoundException_init = nullptr;
   java_lang_Daemons_start = nullptr;
   java_lang_Daemons_stop = nullptr;
+  java_lang_Double_doubleToRawLongBits = nullptr;
   java_lang_Double_valueOf = nullptr;
+  java_lang_Float_floatToRawIntBits = nullptr;
   java_lang_Float_valueOf = nullptr;
   java_lang_Integer_valueOf = nullptr;
   java_lang_invoke_MethodHandles_lookup = nullptr;
@@ -578,6 +589,7 @@
   java_lang_Thread_run = nullptr;
   java_lang_ThreadGroup_add = nullptr;
   java_lang_ThreadGroup_removeThread = nullptr;
+  java_nio_Buffer_isDirect = nullptr;
   java_nio_DirectByteBuffer_init = nullptr;
   libcore_reflect_AnnotationFactory_createAnnotation = nullptr;
   libcore_reflect_AnnotationMember_init = nullptr;
@@ -617,8 +629,6 @@
   java_nio_ByteBuffer_isReadOnly = nullptr;
   java_nio_ByteBuffer_limit = nullptr;
   java_nio_ByteBuffer_offset = nullptr;
-  java_nio_DirectByteBuffer_capacity = nullptr;
-  java_nio_DirectByteBuffer_effectiveDirectAddress = nullptr;
   java_util_Collections_EMPTY_LIST = nullptr;
   libcore_util_EmptyArray_STACK_TRACE_ELEMENT = nullptr;
   org_apache_harmony_dalvik_ddmc_Chunk_data = nullptr;
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 6f67fde6..b2e01ae 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -88,6 +88,8 @@
   static jclass java_lang_Thread;
   static jclass java_lang_ThreadGroup;
   static jclass java_lang_Throwable;
+  static jclass java_lang_Void;
+  static jclass java_nio_Buffer;
   static jclass java_nio_ByteBuffer;
   static jclass java_nio_DirectByteBuffer;
   static jclass java_util_Collections;
@@ -109,7 +111,9 @@
   static jmethodID java_lang_Daemons_start;
   static jmethodID java_lang_Daemons_stop;
   static jmethodID java_lang_Daemons_waitForDaemonStart;
+  static jmethodID java_lang_Double_doubleToRawLongBits;
   static jmethodID java_lang_Double_valueOf;
+  static jmethodID java_lang_Float_floatToRawIntBits;
   static jmethodID java_lang_Float_valueOf;
   static jmethodID java_lang_Integer_valueOf;
   static jmethodID java_lang_invoke_MethodHandles_lookup;
@@ -129,6 +133,7 @@
   static jmethodID java_lang_Thread_run;
   static jmethodID java_lang_ThreadGroup_add;
   static jmethodID java_lang_ThreadGroup_removeThread;
+  static jmethodID java_nio_Buffer_isDirect;
   static jmethodID java_nio_DirectByteBuffer_init;
   static jmethodID java_util_function_Consumer_accept;
   static jmethodID libcore_reflect_AnnotationFactory_createAnnotation;
@@ -144,7 +149,6 @@
   static jfieldID dalvik_system_DexPathList__Element_dexFile;
   static jfieldID dalvik_system_VMRuntime_nonSdkApiUsageConsumer;
   static jfieldID java_io_FileDescriptor_descriptor;
-  static jfieldID java_io_FileDescriptor_ownerId;
   static jfieldID java_lang_Thread_parkBlocker;
   static jfieldID java_lang_Thread_daemon;
   static jfieldID java_lang_Thread_group;
@@ -166,6 +170,7 @@
   static jfieldID java_lang_Throwable_stackState;
   static jfieldID java_lang_Throwable_suppressedExceptions;
   static jfieldID java_nio_Buffer_address;
+  static jfieldID java_nio_Buffer_capacity;
   static jfieldID java_nio_Buffer_elementSizeShift;
   static jfieldID java_nio_Buffer_limit;
   static jfieldID java_nio_Buffer_position;
@@ -174,8 +179,6 @@
   static jfieldID java_nio_ByteBuffer_isReadOnly;
   static jfieldID java_nio_ByteBuffer_limit;
   static jfieldID java_nio_ByteBuffer_offset;
-  static jfieldID java_nio_DirectByteBuffer_capacity;
-  static jfieldID java_nio_DirectByteBuffer_effectiveDirectAddress;
 
   static jfieldID java_util_Collections_EMPTY_LIST;
   static jfieldID libcore_util_EmptyArray_STACK_TRACE_ELEMENT;
diff --git a/sigchainlib/Android.bp b/sigchainlib/Android.bp
index ac909a6..f8c8379 100644
--- a/sigchainlib/Android.bp
+++ b/sigchainlib/Android.bp
@@ -14,84 +14,94 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_library {
     name: "libsigchain",
     defaults: ["art_defaults"],
     visibility: [
-        // TODO(b/133140750): Clean this up.
         "//frameworks/base/cmds/app_process",
     ],
+    //  Make libsigchain symbols global, so that an app library which
+    //  is loaded in a classloader linker namespace looks for
+    //  libsigchain symbols before libc.
+    //  -z,global marks the binary with the DF_1_GLOBAL flag which puts the symbols
+    //  in the global group. It does not affect their visibilities like the version
+    //  script does.
+    ldflags: ["-Wl,-z,global"],
 
     host_supported: true,
     target: {
         linux: {
-            shared: {
-                srcs: ["sigchain_dummy.cc"],
-            },
-            static: {
-                srcs: ["sigchain.cc"],
-            },
+            srcs: ["sigchain.cc"],
         },
 
         darwin: {
-            srcs: ["sigchain_dummy.cc"],
+            srcs: ["sigchain_fake.cc"],
         },
 
         android: {
-            whole_static_libs: ["libasync_safe"],
+            static_libs: ["libasync_safe"],
         },
     },
 
     export_include_dirs: ["."],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
-        // TODO(b/142944931) Clean this up. This is due to the dependency from
-        // app_process
-        "//apex_available:platform",
     ],
+    stubs: {
+        symbol_file: "libsigchain.map.txt",
+        versions: ["1"],
+    },
 }
 
-// Create a dummy version of libsigchain which expose the necessary symbols
+// Create a fake version of libsigchain which expose the necessary symbols
 // but throws when called. This can be used to get static binaries which don't
 // need the real functionality of the sig chain but need to please the linker.
 cc_library_static {
-    name: "libsigchain_dummy",
+    name: "libsigchain_fake",
     host_supported: true,
     defaults: ["art_defaults"],
-    srcs: ["sigchain_dummy.cc"],
+    srcs: ["sigchain_fake.cc"],
     target: {
         android: {
-            whole_static_libs: ["libasync_safe"],
+            static_libs: ["libasync_safe"],
         },
     },
 
     export_include_dirs: ["."],
 }
 
+art_cc_defaults {
+    name: "art_sigchain_tests_defaults",
+    srcs: ["sigchain_test.cc"],
+    shared_libs: ["libsigchain"],
+}
+
+// Version of ART gtest `art_sigchain_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART gtests is complete.
 art_cc_test {
     name: "art_sigchain_tests",
     defaults: [
         "art_gtest_defaults",
+        "art_sigchain_tests_defaults",
     ],
-    srcs: ["sigchain_test.cc"],
-    whole_static_libs: ["libsigchain"],
 }
 
-filegroup {
-    name: "art_sigchain_version_script32.txt",
-    visibility: [
-        // TODO(b/133140750): Clean this up.
-        "//frameworks/base/cmds/app_process",
+// Standalone version of ART gtest `art_sigchain_tests`, not bundled with the ART APEX on target.
+art_cc_test {
+    name: "art_standalone_sigchain_tests",
+    defaults: [
+        "art_standalone_gtest_defaults",
+        "art_sigchain_tests_defaults",
     ],
-    srcs: ["version-script32.txt"],
-}
-
-filegroup {
-    name: "art_sigchain_version_script64.txt",
-    visibility: [
-        // TODO(b/133140750): Clean this up.
-        "//frameworks/base/cmds/app_process",
-    ],
-    srcs: ["version-script64.txt"],
 }
diff --git a/sigchainlib/OWNERS b/sigchainlib/OWNERS
index 450fc12..6062b9c 100644
--- a/sigchainlib/OWNERS
+++ b/sigchainlib/OWNERS
@@ -1,4 +1,5 @@
 # Default maintainers and code reviewers:
-jmgao@google.com
+calin@google.com
 dimitry@google.com
-sehr@google.com
+jmgao@google.com
+ngeoffray@google.com
diff --git a/sigchainlib/libsigchain.map.txt b/sigchainlib/libsigchain.map.txt
new file mode 100644
index 0000000..02c20c7
--- /dev/null
+++ b/sigchainlib/libsigchain.map.txt
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LIBSIGCHAIN_1 {
+  global:
+    # Export no symbols - the only external entry points are libc overrides.
+    # Since this section cannot be empty for APEX stubs generation we provide a
+    # phony entry.
+    LibsigchainNonexistentFunction;
+  local:
+    *;
+};
diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc
index f58fe21..1935d45 100644
--- a/sigchainlib/sigchain.cc
+++ b/sigchainlib/sigchain.cc
@@ -22,6 +22,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#if defined(__BIONIC__)
+#include <bionic/macros.h>
+#endif
+
 #include <algorithm>
 #include <initializer_list>
 #include <mutex>
@@ -39,6 +43,9 @@
 #define _XOPEN_SOURCE
 #endif
 
+#define SA_UNSUPPORTED 0x00000400
+#define SA_EXPOSE_TAGBITS 0x00000800
+
 #include <ucontext.h>
 
 // libsigchain provides an interception layer for signal handlers, to allow ART and others to give
@@ -204,13 +211,50 @@
 #endif
 
     handler_action.sa_sigaction = SignalChain::Handler;
-    handler_action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+    handler_action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK |
+                              SA_UNSUPPORTED | SA_EXPOSE_TAGBITS;
 
 #if defined(__BIONIC__)
     linked_sigaction64(signo, &handler_action, &action_);
+    linked_sigaction64(signo, nullptr, &handler_action);
 #else
     linked_sigaction(signo, &handler_action, &action_);
+    linked_sigaction(signo, nullptr, &handler_action);
 #endif
+
+    // Newer kernels clear unknown flags from sigaction.sa_flags in order to
+    // allow userspace to determine which flag bits are supported. We use this
+    // behavior in turn to implement the same flag bit support detection
+    // protocol regardless of kernel version. Due to the lack of a flag bit
+    // support detection protocol in older kernels we assume support for a base
+    // set of flags that have been supported since at least 2003 [1]. No flags
+    // were introduced since then until the introduction of SA_EXPOSE_TAGBITS
+    // handled below. glibc headers do not define SA_RESTORER so we define it
+    // ourselves.
+    //
+    // TODO(pcc): The new kernel behavior has been implemented in a kernel
+    // patch [2] that has not yet landed. Update the code if necessary once it
+    // lands.
+    //
+    // [1] https://github.com/mpe/linux-fullhistory/commit/c0f806c86fc8b07ad426df023f1a4bb0e53c64f6
+    // [2] https://lore.kernel.org/linux-arm-kernel/cover.1605235762.git.pcc@google.com/
+#if !defined(__BIONIC__)
+#define SA_RESTORER 0x04000000
+#endif
+    kernel_supported_flags_ = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO |
+                              SA_ONSTACK | SA_RESTART | SA_NODEFER |
+                              SA_RESETHAND | SA_RESTORER;
+
+    // Determine whether the kernel supports SA_EXPOSE_TAGBITS. For newer
+    // kernels we use the flag support detection protocol described above. In
+    // order to allow userspace to distinguish old and new kernels,
+    // SA_UNSUPPORTED has been reserved as an unsupported flag. If the kernel
+    // did not clear it then we know that we have an old kernel that would not
+    // support SA_EXPOSE_TAGBITS anyway.
+    if (!(handler_action.sa_flags & SA_UNSUPPORTED) &&
+        (handler_action.sa_flags & SA_EXPOSE_TAGBITS)) {
+      kernel_supported_flags_ |= SA_EXPOSE_TAGBITS;
+    }
   }
 
   template <typename SigactionType>
@@ -244,6 +288,7 @@
       memcpy(&action_.sa_mask, &new_action->sa_mask,
              std::min(sizeof(action_.sa_mask), sizeof(new_action->sa_mask)));
     }
+    action_.sa_flags &= kernel_supported_flags_;
   }
 
   void AddSpecialHandler(SigchainAction* sa) {
@@ -278,6 +323,7 @@
 
  private:
   bool claimed_;
+  int kernel_supported_flags_;
 #if defined(__BIONIC__)
   struct sigaction64 action_;
 #else
@@ -342,6 +388,17 @@
 #endif
 
   if ((handler_flags & SA_SIGINFO)) {
+    // If the chained handler is not expecting tag bits in the fault address,
+    // mask them out now.
+#if defined(__BIONIC__)
+    if (!(handler_flags & SA_EXPOSE_TAGBITS) &&
+        (signo == SIGILL || signo == SIGFPE || signo == SIGSEGV ||
+         signo == SIGBUS || signo == SIGTRAP) &&
+        siginfo->si_code > SI_USER && siginfo->si_code < SI_KERNEL &&
+        !(signo == SIGTRAP && siginfo->si_code == TRAP_HWBKPT)) {
+      siginfo->si_addr = untag_address(siginfo->si_addr);
+    }
+#endif
     chains[signo].action_.sa_sigaction(signo, siginfo, ucontext_raw);
   } else {
     auto handler = chains[signo].action_.sa_handler;
diff --git a/sigchainlib/sigchain.h b/sigchainlib/sigchain.h
index 9c24a6f..13ec85d 100644
--- a/sigchainlib/sigchain.h
+++ b/sigchainlib/sigchain.h
@@ -17,6 +17,10 @@
 #ifndef ART_SIGCHAINLIB_SIGCHAIN_H_
 #define ART_SIGCHAINLIB_SIGCHAIN_H_
 
+// TODO(b/142944043): Symbol changes here currently need to be reflected in
+// version scripts in frameworks/base/cmds/app_process. The plan is to convert
+// libsigchain to a shared lib to get rid of them.
+
 #include <signal.h>
 #include <stdint.h>
 
diff --git a/sigchainlib/sigchain_dummy.cc b/sigchainlib/sigchain_dummy.cc
deleted file mode 100644
index db72b58..0000000
--- a/sigchainlib/sigchain_dummy.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "log.h"
-#include "sigchain.h"
-
-#define ATTRIBUTE_UNUSED __attribute__((__unused__))
-
-// We cannot annotate the declarations, as they are not no-return in the non-dummy version.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunknown-pragmas"
-#pragma GCC diagnostic ignored "-Wmissing-noreturn"
-
-namespace art {
-
-extern "C" void EnsureFrontOfChain(int signal ATTRIBUTE_UNUSED) {
-  log("EnsureFrontOfChain is not exported by the main executable.");
-  abort();
-}
-
-extern "C" void AddSpecialSignalHandlerFn(int signal ATTRIBUTE_UNUSED,
-                                          SigchainAction* sa ATTRIBUTE_UNUSED) {
-  log("SetSpecialSignalHandlerFn is not exported by the main executable.");
-  abort();
-}
-
-extern "C" void RemoveSpecialSignalHandlerFn(int signal ATTRIBUTE_UNUSED,
-                                             bool (*fn)(int, siginfo_t*, void*) ATTRIBUTE_UNUSED) {
-  log("SetSpecialSignalHandlerFn is not exported by the main executable.");
-  abort();
-}
-
-extern "C" void SkipAddSignalHandler(bool value ATTRIBUTE_UNUSED) {
-  log("SkipAddSignalHandler is not exported by the main executable.");
-  abort();
-}
-
-#pragma GCC diagnostic pop
-
-}  // namespace art
diff --git a/sigchainlib/sigchain_fake.cc b/sigchainlib/sigchain_fake.cc
new file mode 100644
index 0000000..2386154
--- /dev/null
+++ b/sigchainlib/sigchain_fake.cc
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "log.h"
+#include "sigchain.h"
+
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+
+// We cannot annotate the declarations, as they are not no-return in the non-fake version.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#pragma GCC diagnostic ignored "-Wmissing-noreturn"
+
+namespace art {
+
+extern "C" void EnsureFrontOfChain(int signal ATTRIBUTE_UNUSED) {
+  log("EnsureFrontOfChain is not exported by the main executable.");
+  abort();
+}
+
+extern "C" void AddSpecialSignalHandlerFn(int signal ATTRIBUTE_UNUSED,
+                                          SigchainAction* sa ATTRIBUTE_UNUSED) {
+  log("SetSpecialSignalHandlerFn is not exported by the main executable.");
+  abort();
+}
+
+extern "C" void RemoveSpecialSignalHandlerFn(int signal ATTRIBUTE_UNUSED,
+                                             bool (*fn)(int, siginfo_t*, void*) ATTRIBUTE_UNUSED) {
+  log("SetSpecialSignalHandlerFn is not exported by the main executable.");
+  abort();
+}
+
+extern "C" void SkipAddSignalHandler(bool value ATTRIBUTE_UNUSED) {
+  log("SkipAddSignalHandler is not exported by the main executable.");
+  abort();
+}
+
+#pragma GCC diagnostic pop
+
+}  // namespace art
diff --git a/sigchainlib/sigchain_test.cc b/sigchainlib/sigchain_test.cc
index bb99787..249fff1 100644
--- a/sigchainlib/sigchain_test.cc
+++ b/sigchainlib/sigchain_test.cc
@@ -214,16 +214,20 @@
   void* libc = dlopen(kLibcSoName, RTLD_LAZY | RTLD_NOLOAD);
   ASSERT_TRUE(libc);
 
+  auto libc_sigaction = reinterpret_cast<decltype(&sigaction)>(dlsym(libc, "sigaction"));
+  ASSERT_TRUE(libc_sigaction);
+
   static sig_atomic_t called = 0;
   struct sigaction action = {};
   action.sa_flags = SA_SIGINFO;
   action.sa_sigaction = [](int, siginfo_t*, void*) { called = 1; };
 
-  ASSERT_EQ(0, sigaction(SIGSEGV, &action, nullptr));
+  ASSERT_EQ(0, libc_sigaction(SIGSEGV, &action, nullptr));
 
   // Try before EnsureFrontOfChain.
   RaiseHandled();
-  ASSERT_EQ(0, called);
+  ASSERT_EQ(1, called);
+  called = 0;
 
   RaiseUnhandled();
   ASSERT_EQ(1, called);
@@ -231,10 +235,39 @@
 
   // ...and after.
   art::EnsureFrontOfChain(SIGSEGV);
+  RaiseHandled();
   ASSERT_EQ(0, called);
-  called = 0;
 
   RaiseUnhandled();
   ASSERT_EQ(1, called);
   called = 0;
 }
+
+TEST_F(SigchainTest, fault_address_tag) {
+#define SA_EXPOSE_TAGBITS 0x00000800
+#if defined(__aarch64__)
+  struct sigaction action = {};
+  action.sa_flags = SA_SIGINFO;
+  action.sa_sigaction = [](int, siginfo_t* siginfo, void*) {
+    _exit(reinterpret_cast<uintptr_t>(siginfo->si_addr) >> 56);
+  };
+  ASSERT_EQ(0, sigaction(SIGSEGV, &action, nullptr));
+
+  auto* tagged_null = reinterpret_cast<int*>(0x2bULL << 56);
+  EXPECT_EXIT({ volatile int load __attribute__((unused)) = *tagged_null; },
+              testing::ExitedWithCode(0), "");
+
+  // Our sigaction implementation always implements the "clear unknown bits"
+  // semantics for oldact.sa_flags regardless of kernel version so we rely on it
+  // here to test for kernel support for SA_EXPOSE_TAGBITS.
+  action.sa_flags = SA_SIGINFO | SA_EXPOSE_TAGBITS;
+  ASSERT_EQ(0, sigaction(SIGSEGV, &action, nullptr));
+  ASSERT_EQ(0, sigaction(SIGSEGV, nullptr, &action));
+  if (action.sa_flags & SA_EXPOSE_TAGBITS) {
+    EXPECT_EXIT({ volatile int load __attribute__((unused)) = *tagged_null; },
+                testing::ExitedWithCode(0x2b), "");
+  }
+#else
+  GTEST_SKIP() << "arm64 only";
+#endif
+}
diff --git a/sigchainlib/version-script32.txt b/sigchainlib/version-script32.txt
deleted file mode 100644
index 70810e0..0000000
--- a/sigchainlib/version-script32.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-global:
-  EnsureFrontOfChain;
-  AddSpecialSignalHandlerFn;
-  RemoveSpecialSignalHandlerFn;
-  SkipAddSignalHandler;
-  bsd_signal;
-  sigaction;
-  sigaction64;
-  signal;
-  sigprocmask;
-  sigprocmask64;
-local:
-  *;
-};
diff --git a/sigchainlib/version-script64.txt b/sigchainlib/version-script64.txt
deleted file mode 100644
index 7bcd76b..0000000
--- a/sigchainlib/version-script64.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-global:
-  EnsureFrontOfChain;
-  AddSpecialSignalHandlerFn;
-  RemoveSpecialSignalHandlerFn;
-  SkipAddSignalHandler;
-  sigaction;
-  sigaction64;
-  signal;
-  sigprocmask;
-  sigprocmask64;
-local:
-  *;
-};
diff --git a/simulator/Android.bp b/simulator/Android.bp
index 1410444..d29319a 100644
--- a/simulator/Android.bp
+++ b/simulator/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_library_headers {
     name: "libart_simulator_headers",
     host_supported: true,
@@ -45,6 +54,8 @@
     shared_libs: [
         "libart",
         "libartbase",
+    ],
+    static_libs: [
         "libvixl",
     ],
 }
@@ -58,6 +69,8 @@
     shared_libs: [
         "libartd",
         "libartbased",
+    ],
+    static_libs: [
         "libvixld",
     ],
 }
diff --git a/simulator/code_simulator_arm64.cc b/simulator/code_simulator_arm64.cc
index a64bd0b..32ca005 100644
--- a/simulator/code_simulator_arm64.cc
+++ b/simulator/code_simulator_arm64.cc
@@ -40,7 +40,13 @@
     : CodeSimulator(), decoder_(nullptr), simulator_(nullptr) {
   DCHECK(kCanSimulate);
   decoder_ = new Decoder();
-  simulator_ = new Simulator(decoder_);
+
+  SimStack stack_builder;
+  stack_builder.SetLimitGuardSize(0x4000);
+  stack_builder.SetUsableSize(0x4000);
+  SimStack::Allocated stack = stack_builder.Allocate();
+
+  simulator_ = new Simulator(decoder_, stdout, std::move(stack));
 }
 
 CodeSimulatorArm64::~CodeSimulatorArm64() {
diff --git a/test.py b/test.py
index 9e54363..4ef6592 100755
--- a/test.py
+++ b/test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright 2017, The Android Open Source Project
 #
@@ -51,7 +51,7 @@
     run_test_args.append(arg)
 
   test_runner_cmd = [testrunner] + run_test_args
-  print test_runner_cmd
+  print(test_runner_cmd)
   if subprocess.call(test_runner_cmd) or options.help_runner:
     sys.exit(1)
 
@@ -62,9 +62,11 @@
   if options.target or not options.host:
     build_target += ' test-art-target-gtest'
 
-  build_command = 'm -j' + str(options.n_threads) + ' ' + build_target
-  print build_command
+  build_command = ANDROID_BUILD_TOP + '/build/soong/soong_ui.bash --make-mode'
+  build_command += ' -j' + str(options.n_threads)
+  build_command += ' ' + build_target
+  print(build_command)
   if subprocess.call(build_command.split(), cwd=ANDROID_BUILD_TOP):
-      sys.exit(1)
+    sys.exit(1)
 
 sys.exit(0)
diff --git a/test/001-Main/expected.txt b/test/000-nop/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/000-nop/expected-stderr.txt
diff --git a/test/000-nop/expected.txt b/test/000-nop/expected-stdout.txt
similarity index 100%
rename from test/000-nop/expected.txt
rename to test/000-nop/expected-stdout.txt
diff --git a/test/001-HelloWorld/Android.bp b/test/001-HelloWorld/Android.bp
new file mode 100644
index 0000000..15f4f58
--- /dev/null
+++ b/test/001-HelloWorld/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `001-HelloWorld`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-001-HelloWorld",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-001-HelloWorld-expected-stdout",
+        ":art-run-test-001-HelloWorld-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-001-HelloWorld-expected-stdout",
+    out: ["art-run-test-001-HelloWorld-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-001-HelloWorld-expected-stderr",
+    out: ["art-run-test-001-HelloWorld-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/001-HelloWorld/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/001-HelloWorld/expected-stderr.txt
diff --git a/test/001-HelloWorld/expected.txt b/test/001-HelloWorld/expected-stdout.txt
similarity index 100%
rename from test/001-HelloWorld/expected.txt
rename to test/001-HelloWorld/expected-stdout.txt
diff --git a/test/001-Main/Android.bp b/test/001-Main/Android.bp
new file mode 100644
index 0000000..450e4af
--- /dev/null
+++ b/test/001-Main/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `001-Main`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-001-Main",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-001-Main-expected-stdout",
+        ":art-run-test-001-Main-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-001-Main-expected-stdout",
+    out: ["art-run-test-001-Main-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-001-Main-expected-stderr",
+    out: ["art-run-test-001-Main-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/001-Main/expected-stderr.txt
similarity index 100%
rename from test/001-Main/expected.txt
rename to test/001-Main/expected-stderr.txt
diff --git a/test/001-Main/expected.txt b/test/001-Main/expected-stdout.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/001-Main/expected-stdout.txt
diff --git a/test/002-sleep/Android.bp b/test/002-sleep/Android.bp
new file mode 100644
index 0000000..ce16240
--- /dev/null
+++ b/test/002-sleep/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `002-sleep`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-002-sleep",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-002-sleep-expected-stdout",
+        ":art-run-test-002-sleep-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-002-sleep-expected-stdout",
+    out: ["art-run-test-002-sleep-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-002-sleep-expected-stderr",
+    out: ["art-run-test-002-sleep-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/002-sleep/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/002-sleep/expected-stderr.txt
diff --git a/test/002-sleep/expected.txt b/test/002-sleep/expected-stdout.txt
similarity index 100%
rename from test/002-sleep/expected.txt
rename to test/002-sleep/expected-stdout.txt
diff --git a/test/1901-get-bytecodes/expected.txt b/test/003-omnibus-opcodes/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/003-omnibus-opcodes/expected-stderr.txt
diff --git a/test/003-omnibus-opcodes/expected.txt b/test/003-omnibus-opcodes/expected-stdout.txt
similarity index 100%
rename from test/003-omnibus-opcodes/expected.txt
rename to test/003-omnibus-opcodes/expected-stdout.txt
diff --git a/test/004-InterfaceTest/Android.bp b/test/004-InterfaceTest/Android.bp
new file mode 100644
index 0000000..4ba1240
--- /dev/null
+++ b/test/004-InterfaceTest/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `004-InterfaceTest`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-004-InterfaceTest",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-004-InterfaceTest-expected-stdout",
+        ":art-run-test-004-InterfaceTest-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-004-InterfaceTest-expected-stdout",
+    out: ["art-run-test-004-InterfaceTest-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-004-InterfaceTest-expected-stderr",
+    out: ["art-run-test-004-InterfaceTest-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/507-boolean-test/expected.txt b/test/004-InterfaceTest/expected-stderr.txt
similarity index 100%
copy from test/507-boolean-test/expected.txt
copy to test/004-InterfaceTest/expected-stderr.txt
diff --git a/test/004-InterfaceTest/expected.txt b/test/004-InterfaceTest/expected-stdout.txt
similarity index 100%
rename from test/004-InterfaceTest/expected.txt
rename to test/004-InterfaceTest/expected-stdout.txt
diff --git a/test/001-Main/expected.txt b/test/004-JniTest/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/004-JniTest/expected-stderr.txt
diff --git a/test/004-JniTest/expected.txt b/test/004-JniTest/expected-stdout.txt
similarity index 100%
rename from test/004-JniTest/expected.txt
rename to test/004-JniTest/expected-stdout.txt
diff --git a/test/004-JniTest/jni_test.cc b/test/004-JniTest/jni_test.cc
index 540e6ce..429bd94 100644
--- a/test/004-JniTest/jni_test.cc
+++ b/test/004-JniTest/jni_test.cc
@@ -90,6 +90,35 @@
   CHECK(!env->ExceptionCheck());
 }
 
+extern "C" JNIEXPORT void JNICALL Java_Main_testUTFRegion(JNIEnv* env, jclass, jstring null_str) {
+  jstring foo_str = env->NewStringUTF("FOOBAR");
+  jstring emoji_str = env->NewStringUTF("SKI ⛷ SKI");
+  char buf[1024];
+  memset(buf, 'Y', sizeof(buf));
+  buf[1023] = '\0';
+
+  env->GetStringUTFRegion(foo_str, 3, 1, buf);
+  buf[1023] = '\0';
+  CHECK_EQ(strcmp("B", buf), 0) << buf;
+
+  // Null char on 0 len region
+  env->GetStringUTFRegion(foo_str, 3, 0, buf);
+  buf[1023] = '\0';
+  CHECK_EQ(strcmp("", buf), 0) << buf;
+
+  // No SEGV
+  env->GetStringUTFRegion(foo_str, 3, 0, nullptr);
+
+  env->GetStringUTFRegion(null_str, 1, 1, buf);
+  buf[1023] = '\0';
+  std::array<uint8_t, 3> nullbuf{ 0xc0, 0x80, 0x00 };
+  CHECK_EQ(memcmp(nullbuf.data(), buf, 3), 0);
+
+  env->GetStringUTFRegion(emoji_str, 1, 6, buf);
+  buf[1023] = '\0';
+  CHECK_EQ(strcmp("KI ⛷ S", buf), 0);
+}
+
 extern "C" JNIEXPORT jint JNICALL Java_Main_getFieldSubclass(JNIEnv* env,
                                                              jclass,
                                                              jobject f_obj,
@@ -801,11 +830,11 @@
 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isSlowDebug(JNIEnv*, jclass) {
   // Return whether slow-debug is on. Only relevant for debug builds.
   if (kIsDebugBuild) {
-    // Register a dummy flag and get the default value it should be initialized with.
-    static bool dummy_flag = false;
-    dummy_flag = RegisterRuntimeDebugFlag(&dummy_flag);
+    // Register a fake flag and get the default value it should be initialized with.
+    static bool fake_flag = false;
+    fake_flag = RegisterRuntimeDebugFlag(&fake_flag);
 
-    return dummy_flag ? JNI_TRUE : JNI_FALSE;
+    return fake_flag ? JNI_TRUE : JNI_FALSE;
   }
   // To pass the Java-side test, just so "on" for release builds.
   return JNI_TRUE;
diff --git a/test/004-JniTest/src/Main.java b/test/004-JniTest/src/Main.java
index f94dcf6..1539b9e 100644
--- a/test/004-JniTest/src/Main.java
+++ b/test/004-JniTest/src/Main.java
@@ -65,6 +65,9 @@
         testClinitMethodLookup();
 
         testDoubleLoad(args[0]);
+        testUTFRegion("\0\0\0");
+
+        testBadFastCriticalNatives();
     }
 
     static class ABC { public static int XYZ = 12; }
@@ -78,6 +81,8 @@
       }
     }
 
+    public static native void testUTFRegion(String null_str);
+
     public static native int getFieldSubclass(Field f, Class sub);
 
     private static native boolean registerNativesJniTest();
@@ -246,14 +251,14 @@
         void a();
     }
 
-    private static class DummyInvocationHandler implements InvocationHandler {
+    private static class MinimalInvocationHandler implements InvocationHandler {
         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
             return null;
         }
     }
 
     private static void testProxyGetMethodID() {
-        InvocationHandler handler = new DummyInvocationHandler();
+        InvocationHandler handler = new MinimalInvocationHandler();
         SimpleInterface proxy =
                 (SimpleInterface) Proxy.newProxyInstance(SimpleInterface.class.getClassLoader(),
                         new Class<?>[] {SimpleInterface.class}, handler);
@@ -417,6 +422,24 @@
       throw new RuntimeException(t);
     }
   }
+
+  private static void testBadFastCriticalNatives() {
+    testBadFastCriticalNative("BadFastNative");
+    testBadFastCriticalNative("BadCriticalNative");
+    testBadFastCriticalNative("BadCriticalNative2");
+    testBadFastCriticalNative("BadCriticalNative3");
+  }
+
+  private static void testBadFastCriticalNative(String className) {
+    try {
+      Class.forName(className);
+      throw new Error("Expected verification error");
+    } catch (VerifyError e) {
+      // Expected.
+    } catch (Throwable e) {
+      throw new Error("Expected verification error");
+    }
+  }
 }
 
 @FunctionalInterface
@@ -463,3 +486,23 @@
         nonstaticMethodSubCalled = true;
     }
 }
+
+class BadFastNative {
+  @FastNative
+  public static native synchronized void test();
+}
+
+class BadCriticalNative {
+  @CriticalNative
+  public static native synchronized void test();
+}
+
+class BadCriticalNative2 {
+  @CriticalNative
+  public native void test();
+}
+
+class BadCriticalNative3 {
+  @CriticalNative
+  public static native void test(Object o);
+}
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/004-NativeAllocations/expected-stderr.txt
similarity index 100%
copy from test/148-multithread-gc-annotations/expected.txt
copy to test/004-NativeAllocations/expected-stderr.txt
diff --git a/test/004-NativeAllocations/expected.txt b/test/004-NativeAllocations/expected-stdout.txt
similarity index 100%
rename from test/004-NativeAllocations/expected.txt
rename to test/004-NativeAllocations/expected-stdout.txt
diff --git a/test/001-Main/expected.txt b/test/004-ReferenceMap/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/004-ReferenceMap/expected-stderr.txt
diff --git a/test/004-ReferenceMap/expected.txt b/test/004-ReferenceMap/expected-stdout.txt
similarity index 100%
rename from test/004-ReferenceMap/expected.txt
rename to test/004-ReferenceMap/expected-stdout.txt
diff --git a/test/004-ReferenceMap/stack_walk_refmap_jni.cc b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
index 4c344a3..4317b5d 100644
--- a/test/004-ReferenceMap/stack_walk_refmap_jni.cc
+++ b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
@@ -20,17 +20,21 @@
 
 namespace art {
 
-#define CHECK_REGS_CONTAIN_REFS(dex_pc, abort_if_not_found, ...) do {                 \
-  int t[] = {__VA_ARGS__};                                                            \
-  int t_size = sizeof(t) / sizeof(*t);                                                \
-  const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();       \
-  uintptr_t native_quick_pc = method_header->ToNativeQuickPc(GetMethod(),             \
-                                                 dex_pc,                              \
-                                                 /* is_catch_handler */ false,        \
-                                                 abort_if_not_found);                 \
-  if (native_quick_pc != UINTPTR_MAX) {                                               \
-    CheckReferences(t, t_size, method_header->NativeQuickPcOffset(native_quick_pc));  \
-  }                                                                                   \
+#define CHECK_REGS_CONTAIN_REFS(dex_pc, abort_if_not_found, ...) do {                         \
+  int t[] = {__VA_ARGS__};                                                                    \
+  int t_size = sizeof(t) / sizeof(*t);                                                        \
+  const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();               \
+  uintptr_t native_quick_pc = method_header->ToNativeQuickPc(GetMethod(),                     \
+                                                 dex_pc,                                      \
+                                                 /* is_catch_handler */ false,                \
+                                                 abort_if_not_found);                         \
+  if (native_quick_pc != UINTPTR_MAX) {                                                       \
+    CheckReferences(t,                                                                        \
+                    t_size,                                                                   \
+                    dex_pc,                                                                   \
+                    method_header->NativeQuickPcOffset(native_quick_pc),                      \
+                    /* search_for_valid_stack_map= */ true);                                  \
+  }                                                                                           \
 } while (false);
 
 struct ReferenceMap2Visitor : public CheckReferenceMapVisitor {
diff --git a/test/004-SignalTest/Android.bp b/test/004-SignalTest/Android.bp
new file mode 100644
index 0000000..ce1d171
--- /dev/null
+++ b/test/004-SignalTest/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `004-SignalTest`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-004-SignalTest",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-004-SignalTest-expected-stdout",
+        ":art-run-test-004-SignalTest-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-004-SignalTest-expected-stdout",
+    out: ["art-run-test-004-SignalTest-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-004-SignalTest-expected-stderr",
+    out: ["art-run-test-004-SignalTest-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/004-SignalTest/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/004-SignalTest/expected-stderr.txt
diff --git a/test/004-SignalTest/expected.txt b/test/004-SignalTest/expected-stdout.txt
similarity index 100%
rename from test/004-SignalTest/expected.txt
rename to test/004-SignalTest/expected-stdout.txt
diff --git a/test/001-Main/expected.txt b/test/004-StackWalk/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/004-StackWalk/expected-stderr.txt
diff --git a/test/004-StackWalk/expected.txt b/test/004-StackWalk/expected-stdout.txt
similarity index 100%
rename from test/004-StackWalk/expected.txt
rename to test/004-StackWalk/expected-stdout.txt
diff --git a/test/004-StackWalk/stack_walk_jni.cc b/test/004-StackWalk/stack_walk_jni.cc
index 6e53f30..3ec0fa3 100644
--- a/test/004-StackWalk/stack_walk_jni.cc
+++ b/test/004-StackWalk/stack_walk_jni.cc
@@ -25,7 +25,8 @@
 #define CHECK_REGS_ARE_REFERENCES(...) do { \
   int t[] = {__VA_ARGS__}; \
   int t_size = sizeof(t) / sizeof(*t); \
-  CheckReferences(t, t_size, GetNativePcOffset()); \
+  CheckReferences( \
+      t, t_size, GetDexPc(), GetNativePcOffset(), /* search_for_valid_sack_map= */ false); \
 } while (false);
 
 static int gJava_StackWalk_refmap_calls = 0;
diff --git a/test/004-ThreadStress/check b/test/004-ThreadStress/check
index ecc5ea8..f389e6b 100755
--- a/test/004-ThreadStress/check
+++ b/test/004-ThreadStress/check
@@ -14,10 +14,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Do not compare numbers, so replace numbers with 'N'.
 # Remove all messages relating to failing to allocate a java-peer for the
 # shutdown thread. This can occasionally happen with this test but it is not
 # something we really need to worry about here.
 sed '-es/[0-9][0-9]*/N/g' "$2" \
-  | sed "/Exception creating thread peer:/,+3d" \
-  | diff --strip-trailing-cr -q "$1" - >/dev/null
+    | diff --strip-trailing-cr -q "$1" - >/dev/null \
+  && grep -v "Exception creating thread peer:" "$4" \
+    | diff --strip-trailing-cr -q "$3" - >/dev/null
diff --git a/test/607-daemon-stress/expected.txt b/test/004-ThreadStress/expected-stderr.txt
similarity index 100%
copy from test/607-daemon-stress/expected.txt
copy to test/004-ThreadStress/expected-stderr.txt
diff --git a/test/004-ThreadStress/expected.txt b/test/004-ThreadStress/expected-stdout.txt
similarity index 100%
rename from test/004-ThreadStress/expected.txt
rename to test/004-ThreadStress/expected-stdout.txt
diff --git a/test/004-ThreadStress/src-art/Main.java b/test/004-ThreadStress/src-art/Main.java
index e717852..d595749 100644
--- a/test/004-ThreadStress/src-art/Main.java
+++ b/test/004-ThreadStress/src-art/Main.java
@@ -638,8 +638,8 @@
                     : new Daemon(lock, t, operations, mainThread, startBarrier);
         }
 
-        // Enable to dump operation counts per thread to make sure its
-        // sane compared to frequencyMap.
+        // Enable to dump operation counts per thread to see that it is
+        // commensurate with the frequencyMap.
         if (DEBUG) {
             for (int t = 0; t < threadStresses.length; t++) {
                 Operation[] operations = threadStresses[t].operations;
diff --git a/test/004-UnsafeTest/Android.bp b/test/004-UnsafeTest/Android.bp
new file mode 100644
index 0000000..af9be61
--- /dev/null
+++ b/test/004-UnsafeTest/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `004-UnsafeTest`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-004-UnsafeTest",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-004-UnsafeTest-expected-stdout",
+        ":art-run-test-004-UnsafeTest-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-004-UnsafeTest-expected-stdout",
+    out: ["art-run-test-004-UnsafeTest-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-004-UnsafeTest-expected-stderr",
+    out: ["art-run-test-004-UnsafeTest-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/004-UnsafeTest/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/004-UnsafeTest/expected-stderr.txt
diff --git a/test/004-UnsafeTest/expected.txt b/test/004-UnsafeTest/expected-stdout.txt
similarity index 100%
rename from test/004-UnsafeTest/expected.txt
rename to test/004-UnsafeTest/expected-stdout.txt
diff --git a/test/004-checker-UnsafeTest18/Android.bp b/test/004-checker-UnsafeTest18/Android.bp
new file mode 100644
index 0000000..6270840
--- /dev/null
+++ b/test/004-checker-UnsafeTest18/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `004-checker-UnsafeTest18`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-004-checker-UnsafeTest18",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-004-checker-UnsafeTest18-expected-stdout",
+        ":art-run-test-004-checker-UnsafeTest18-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-004-checker-UnsafeTest18-expected-stdout",
+    out: ["art-run-test-004-checker-UnsafeTest18-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-004-checker-UnsafeTest18-expected-stderr",
+    out: ["art-run-test-004-checker-UnsafeTest18-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/004-checker-UnsafeTest18/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/004-checker-UnsafeTest18/expected-stderr.txt
diff --git a/test/004-checker-UnsafeTest18/expected.txt b/test/004-checker-UnsafeTest18/expected-stdout.txt
similarity index 100%
rename from test/004-checker-UnsafeTest18/expected.txt
rename to test/004-checker-UnsafeTest18/expected-stdout.txt
diff --git a/test/004-checker-UnsafeTest18/src/Main.java b/test/004-checker-UnsafeTest18/src/Main.java
index 927d0da..2f056ca 100644
--- a/test/004-checker-UnsafeTest18/src/Main.java
+++ b/test/004-checker-UnsafeTest18/src/Main.java
@@ -91,36 +91,27 @@
   //
 
   /// CHECK-START: void Main.load() builder (after)
-  /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeLoadFence
+  /// CHECK-NOT: InvokeVirtual
   //
-  /// CHECK-START: void Main.load() instruction_simplifier (after)
-  /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeLoadFence
-  //
-  /// CHECK-START: void Main.load() instruction_simplifier (after)
+  /// CHECK-START: void Main.load() builder (after)
   /// CHECK-DAG: MemoryBarrier kind:LoadAny
   private static void load() {
     unsafe.loadFence();
   }
 
   /// CHECK-START: void Main.store() builder (after)
-  /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeStoreFence
+  /// CHECK-NOT: InvokeVirtual
   //
-  /// CHECK-START: void Main.store() instruction_simplifier (after)
-  /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeStoreFence
-  //
-  /// CHECK-START: void Main.store() instruction_simplifier (after)
+  /// CHECK-START: void Main.store() builder (after)
   /// CHECK-DAG: MemoryBarrier kind:AnyStore
   private static void store() {
     unsafe.storeFence();
   }
 
   /// CHECK-START: void Main.full() builder (after)
-  /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeFullFence
+  /// CHECK-NOT: InvokeVirtual
   //
-  /// CHECK-START: void Main.full() instruction_simplifier (after)
-  /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeFullFence
-  //
-  /// CHECK-START: void Main.full() instruction_simplifier (after)
+  /// CHECK-START: void Main.full() builder (after)
   /// CHECK-DAG: MemoryBarrier kind:AnyAny
   private static void full() {
     unsafe.fullFence();
@@ -176,7 +167,7 @@
       throw new Error("No offset: " + e);
     }
 
-    // Some sanity on setters and adders within same thread.
+    // Some checks on setters and adders within same thread.
 
     set32(m, intOffset, 3);
     expectEqual32(3, m.i);
@@ -193,7 +184,7 @@
     add64(m, longOffset, 13L);
     expectEqual64(20L, m.l);
 
-    // Some sanity on setters within different threads.
+    // Some checks on setters within different threads.
 
     fork(new Runnable() {
       public void run() {
@@ -222,7 +213,7 @@
     join();
     expectEqualObj(sThreads[9], m.o);  // one thread's last value wins
 
-    // Some sanity on adders within different threads.
+    // Some checks on adders within different threads.
 
     fork(new Runnable() {
       public void run() {
@@ -242,8 +233,8 @@
     join();
     expectEqual64(659L, m.l);  // all values accounted for
 
-    // Some sanity on fences within same thread. Note that memory fences within one
-    // thread make little sense, but the sanity check ensures nothing bad happens.
+    // Some checks on fences within same thread. Note that memory fences within one
+    // thread make little sense, but the assertion ensures nothing bad happens.
 
     m.i = -1;
     m.l = -2L;
@@ -257,7 +248,7 @@
     expectEqual64(-2L, m.l);
     expectEqualObj(null, m.o);
 
-    // Some sanity on full fence within different threads. We write the non-volatile m.l after
+    // Some checks on full fence within different threads. We write the non-volatile m.l after
     // the fork(), which means there is no happens-before relation in the Java memory model
     // with respect to the read in the threads. This relation is enforced by the memory fences
     // and the weak-set() -> get() guard. Note that the guard semantics used here are actually
@@ -280,7 +271,7 @@
     while (!guard1.weakCompareAndSet(false, true));  // relaxed memory order
     join();
 
-    // Some sanity on release/acquire fences within different threads. We write the non-volatile
+    // Some checks on release/acquire fences within different threads. We write the non-volatile
     // m.l after the fork(), which means there is no happens-before relation in the Java memory
     // model with respect to the read in the threads. This relation is enforced by the memory fences
     // and the weak-set() -> get() guard. Note that the guard semantics used here are actually
@@ -303,9 +294,9 @@
     while (!guard2.weakCompareAndSet(false, true));  // relaxed memory order
     join();
 
-    // Some sanity on release/acquire fences within different threads using a test suggested by
-    // Hans Boehm. Even this test remains with the realm of sanity only, since having the threads
-    // read the same value consistently would be a valid outcome.
+    // Some checks on release/acquire fences within different threads using a test suggested by
+    // Hans Boehm. Even this test remains with the realm of soundness checking only, since having
+    // the threads read the same value consistently would be a valid outcome.
 
     m.x_value = -1;
     m.y_value = -1;
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/005-annotations/expected-stderr.txt
similarity index 100%
copy from test/148-multithread-gc-annotations/expected.txt
copy to test/005-annotations/expected-stderr.txt
diff --git a/test/005-annotations/expected.txt b/test/005-annotations/expected-stdout.txt
similarity index 100%
rename from test/005-annotations/expected.txt
rename to test/005-annotations/expected-stdout.txt
diff --git a/test/006-args/Android.bp b/test/006-args/Android.bp
new file mode 100644
index 0000000..dc56f81
--- /dev/null
+++ b/test/006-args/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `006-args`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-006-args",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-006-args-expected-stdout",
+        ":art-run-test-006-args-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-006-args-expected-stdout",
+    out: ["art-run-test-006-args-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-006-args-expected-stderr",
+    out: ["art-run-test-006-args-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/006-args/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/006-args/expected-stderr.txt
diff --git a/test/006-args/expected.txt b/test/006-args/expected-stdout.txt
similarity index 100%
rename from test/006-args/expected.txt
rename to test/006-args/expected-stdout.txt
diff --git a/test/007-count10/Android.bp b/test/007-count10/Android.bp
new file mode 100644
index 0000000..36e15df
--- /dev/null
+++ b/test/007-count10/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `007-count10`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-007-count10",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-007-count10-expected-stdout",
+        ":art-run-test-007-count10-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-007-count10-expected-stdout",
+    out: ["art-run-test-007-count10-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-007-count10-expected-stderr",
+    out: ["art-run-test-007-count10-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/007-count10/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/007-count10/expected-stderr.txt
diff --git a/test/007-count10/expected.txt b/test/007-count10/expected-stdout.txt
similarity index 100%
rename from test/007-count10/expected.txt
rename to test/007-count10/expected-stdout.txt
diff --git a/test/001-Main/expected.txt b/test/008-exceptions/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/008-exceptions/expected-stderr.txt
diff --git a/test/008-exceptions/expected.txt b/test/008-exceptions/expected-stdout.txt
similarity index 100%
rename from test/008-exceptions/expected.txt
rename to test/008-exceptions/expected-stdout.txt
diff --git a/test/008-exceptions/src-multidex/MultiDexBadInitWrapper2.java b/test/008-exceptions/src-multidex/MultiDexBadInitWrapper2.java
index f3953bd..a66d818 100644
--- a/test/008-exceptions/src-multidex/MultiDexBadInitWrapper2.java
+++ b/test/008-exceptions/src-multidex/MultiDexBadInitWrapper2.java
@@ -15,9 +15,9 @@
  */
 
 class MultiDexBadInitWrapper2 {
-    public static void setDummy(int value) {
+    public static void setIntField(int value) {
         if (doThrow) { throw new Error(); }
-        MultiDexBadInit.dummy = value;
+        MultiDexBadInit.intField = value;
     }
 
     public static boolean doThrow = false;
diff --git a/test/008-exceptions/src/Main.java b/test/008-exceptions/src/Main.java
index 008576a..0ba5f80 100644
--- a/test/008-exceptions/src/Main.java
+++ b/test/008-exceptions/src/Main.java
@@ -23,7 +23,7 @@
 
 // A class that throws BadError during static initialization.
 class BadInit {
-    static int dummy;
+    static int intField;
     static {
         System.out.println("Static Init");
         if (true) {
@@ -41,7 +41,7 @@
 
 // A class that throws BadErrorNoStringInit during static initialization.
 class BadInitNoStringInit {
-    static int dummy;
+    static int intField;
     static {
         System.out.println("Static BadInitNoStringInit");
         if (true) {
@@ -52,7 +52,7 @@
 
 // A class that throws BadError during static initialization, serving as a super class.
 class BadSuperClass {
- static int dummy;
+ static int intField;
  static {
      System.out.println("BadSuperClass Static Init");
      if (true) {
@@ -104,7 +104,7 @@
     private static void exceptionsRethrowClassInitFailure() {
         try {
             try {
-                BadInit.dummy = 1;
+                BadInit.intField = 1;
                 throw new IllegalStateException("Should not reach here.");
             } catch (BadError e) {
                 System.out.println(e);
@@ -113,7 +113,7 @@
             // Check if it works a second time.
 
             try {
-                BadInit.dummy = 1;
+                BadInit.intField = 1;
                 throw new IllegalStateException("Should not reach here.");
             } catch (NoClassDefFoundError e) {
                 System.out.println(e);
@@ -127,7 +127,7 @@
     private static void exceptionsRethrowClassInitFailureNoStringInit() {
         try {
             try {
-                BadInitNoStringInit.dummy = 1;
+                BadInitNoStringInit.intField = 1;
                 throw new IllegalStateException("Should not reach here.");
             } catch (BadErrorNoStringInit e) {
                 System.out.println(e);
@@ -136,7 +136,7 @@
             // Check if it works a second time.
 
             try {
-                BadInitNoStringInit.dummy = 1;
+                BadInitNoStringInit.intField = 1;
                 throw new IllegalStateException("Should not reach here.");
             } catch (NoClassDefFoundError e) {
                 System.out.println(e);
@@ -150,7 +150,7 @@
     private static void exceptionsForSuperClassInitFailure() {
         try {
             // Resolve DerivedFromBadSuperClass.
-            BadSuperClass.dummy = 1;
+            BadSuperClass.intField = 1;
             throw new IllegalStateException("Should not reach here.");
         } catch (BadError e) {
             System.out.println(e);
@@ -181,7 +181,7 @@
 
     private static void exceptionsInMultiDex() {
         try {
-            MultiDexBadInit.dummy = 1;
+            MultiDexBadInit.intField = 1;
             throw new IllegalStateException("Should not reach here.");
         } catch (Error e) {
             System.out.println(e);
@@ -194,7 +194,7 @@
         // wrapped in NoClassDefFoundError but the exception
         // from wrapper 2 would have been unwrapped.
         try {
-            MultiDexBadInitWrapper1.setDummy(1);
+            MultiDexBadInitWrapper1.setIntField(1);
             throw new IllegalStateException("Should not reach here.");
         } catch (NoClassDefFoundError ncdfe) {
             System.out.println(ncdfe);
@@ -203,7 +203,7 @@
             t.printStackTrace(System.out);
         }
         try {
-            MultiDexBadInitWrapper2.setDummy(1);
+            MultiDexBadInitWrapper2.setIntField(1);
             throw new IllegalStateException("Should not reach here.");
         } catch (NoClassDefFoundError ncdfe) {
             System.out.println(ncdfe);
diff --git a/test/008-exceptions/src/MultiDexBadInit.java b/test/008-exceptions/src/MultiDexBadInit.java
index e3ebb9c..e060323 100644
--- a/test/008-exceptions/src/MultiDexBadInit.java
+++ b/test/008-exceptions/src/MultiDexBadInit.java
@@ -15,7 +15,7 @@
  */
 
 class MultiDexBadInit {
-    static int dummy;
+    static int intField;
     static {
         System.out.println("MultiDexBadInit Static Init");
         if (true) {
diff --git a/test/008-exceptions/src/MultiDexBadInitWrapper1.java b/test/008-exceptions/src/MultiDexBadInitWrapper1.java
index 059e6a3..563e2c3 100644
--- a/test/008-exceptions/src/MultiDexBadInitWrapper1.java
+++ b/test/008-exceptions/src/MultiDexBadInitWrapper1.java
@@ -15,9 +15,9 @@
  */
 
 class MultiDexBadInitWrapper1 {
-    public static void setDummy(int value) {
+    public static void setIntField(int value) {
         if (doThrow) { throw new Error(); }
-        MultiDexBadInit.dummy = value;
+        MultiDexBadInit.intField = value;
     }
 
     public static boolean doThrow = false;
diff --git a/test/009-instanceof/Android.bp b/test/009-instanceof/Android.bp
new file mode 100644
index 0000000..5dcfc44
--- /dev/null
+++ b/test/009-instanceof/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `009-instanceof`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-009-instanceof",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-009-instanceof-expected-stdout",
+        ":art-run-test-009-instanceof-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-009-instanceof-expected-stdout",
+    out: ["art-run-test-009-instanceof-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-009-instanceof-expected-stderr",
+    out: ["art-run-test-009-instanceof-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/422-instanceof/expected.txt b/test/009-instanceof/expected-stderr.txt
similarity index 100%
copy from test/422-instanceof/expected.txt
copy to test/009-instanceof/expected-stderr.txt
diff --git a/test/009-instanceof/expected.txt b/test/009-instanceof/expected-stdout.txt
similarity index 100%
rename from test/009-instanceof/expected.txt
rename to test/009-instanceof/expected-stdout.txt
diff --git a/test/010-instance/Android.bp b/test/010-instance/Android.bp
new file mode 100644
index 0000000..f7515f8
--- /dev/null
+++ b/test/010-instance/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `010-instance`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-010-instance",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-010-instance-expected-stdout",
+        ":art-run-test-010-instance-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-010-instance-expected-stdout",
+    out: ["art-run-test-010-instance-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-010-instance-expected-stderr",
+    out: ["art-run-test-010-instance-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/435-new-instance/expected.txt b/test/010-instance/expected-stderr.txt
similarity index 100%
copy from test/435-new-instance/expected.txt
copy to test/010-instance/expected-stderr.txt
diff --git a/test/010-instance/expected.txt b/test/010-instance/expected-stdout.txt
similarity index 100%
rename from test/010-instance/expected.txt
rename to test/010-instance/expected-stdout.txt
diff --git a/test/011-array-copy/Android.bp b/test/011-array-copy/Android.bp
new file mode 100644
index 0000000..b0f0b90
--- /dev/null
+++ b/test/011-array-copy/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `011-array-copy`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-011-array-copy",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-011-array-copy-expected-stdout",
+        ":art-run-test-011-array-copy-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-011-array-copy-expected-stdout",
+    out: ["art-run-test-011-array-copy-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-011-array-copy-expected-stderr",
+    out: ["art-run-test-011-array-copy-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/610-arraycopy/expected.txt b/test/011-array-copy/expected-stderr.txt
similarity index 100%
copy from test/610-arraycopy/expected.txt
copy to test/011-array-copy/expected-stderr.txt
diff --git a/test/011-array-copy/expected.txt b/test/011-array-copy/expected-stdout.txt
similarity index 100%
rename from test/011-array-copy/expected.txt
rename to test/011-array-copy/expected-stdout.txt
diff --git a/test/012-math/Android.bp b/test/012-math/Android.bp
new file mode 100644
index 0000000..0e249b9
--- /dev/null
+++ b/test/012-math/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `012-math`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-012-math",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-012-math-expected-stdout",
+        ":art-run-test-012-math-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-012-math-expected-stdout",
+    out: ["art-run-test-012-math-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-012-math-expected-stderr",
+    out: ["art-run-test-012-math-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/012-math/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/012-math/expected-stderr.txt
diff --git a/test/012-math/expected.txt b/test/012-math/expected-stdout.txt
similarity index 100%
rename from test/012-math/expected.txt
rename to test/012-math/expected-stdout.txt
diff --git a/test/013-math2/Android.bp b/test/013-math2/Android.bp
new file mode 100644
index 0000000..ea74045
--- /dev/null
+++ b/test/013-math2/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `013-math2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-013-math2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-013-math2-expected-stdout",
+        ":art-run-test-013-math2-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-013-math2-expected-stdout",
+    out: ["art-run-test-013-math2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-013-math2-expected-stderr",
+    out: ["art-run-test-013-math2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/013-math2/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/013-math2/expected-stderr.txt
diff --git a/test/013-math2/expected.txt b/test/013-math2/expected-stdout.txt
similarity index 100%
rename from test/013-math2/expected.txt
rename to test/013-math2/expected-stdout.txt
diff --git a/test/014-math3/Android.bp b/test/014-math3/Android.bp
new file mode 100644
index 0000000..83624bd
--- /dev/null
+++ b/test/014-math3/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `014-math3`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-014-math3",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-014-math3-expected-stdout",
+        ":art-run-test-014-math3-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-014-math3-expected-stdout",
+    out: ["art-run-test-014-math3-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-014-math3-expected-stderr",
+    out: ["art-run-test-014-math3-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/014-math3/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/014-math3/expected-stderr.txt
diff --git a/test/014-math3/expected.txt b/test/014-math3/expected-stdout.txt
similarity index 100%
rename from test/014-math3/expected.txt
rename to test/014-math3/expected-stdout.txt
diff --git a/test/015-switch/Android.bp b/test/015-switch/Android.bp
new file mode 100644
index 0000000..6e66d1e
--- /dev/null
+++ b/test/015-switch/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `015-switch`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-015-switch",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-015-switch-expected-stdout",
+        ":art-run-test-015-switch-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-015-switch-expected-stdout",
+    out: ["art-run-test-015-switch-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-015-switch-expected-stderr",
+    out: ["art-run-test-015-switch-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/558-switch/expected.txt b/test/015-switch/expected-stderr.txt
similarity index 100%
copy from test/558-switch/expected.txt
copy to test/015-switch/expected-stderr.txt
diff --git a/test/015-switch/expected.txt b/test/015-switch/expected-stdout.txt
similarity index 100%
rename from test/015-switch/expected.txt
rename to test/015-switch/expected-stdout.txt
diff --git a/test/016-intern/Android.bp b/test/016-intern/Android.bp
new file mode 100644
index 0000000..ca6e73f
--- /dev/null
+++ b/test/016-intern/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `016-intern`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-016-intern",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-016-intern-expected-stdout",
+        ":art-run-test-016-intern-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-016-intern-expected-stdout",
+    out: ["art-run-test-016-intern-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-016-intern-expected-stderr",
+    out: ["art-run-test-016-intern-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/016-intern/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/016-intern/expected-stderr.txt
diff --git a/test/016-intern/expected.txt b/test/016-intern/expected-stdout.txt
similarity index 100%
rename from test/016-intern/expected.txt
rename to test/016-intern/expected-stdout.txt
diff --git a/test/017-float/Android.bp b/test/017-float/Android.bp
new file mode 100644
index 0000000..87e4ba8
--- /dev/null
+++ b/test/017-float/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `017-float`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-017-float",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-017-float-expected-stdout",
+        ":art-run-test-017-float-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-017-float-expected-stdout",
+    out: ["art-run-test-017-float-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-017-float-expected-stderr",
+    out: ["art-run-test-017-float-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/436-rem-float/expected.txt b/test/017-float/expected-stderr.txt
similarity index 100%
copy from test/436-rem-float/expected.txt
copy to test/017-float/expected-stderr.txt
diff --git a/test/017-float/expected.txt b/test/017-float/expected-stdout.txt
similarity index 100%
rename from test/017-float/expected.txt
rename to test/017-float/expected-stdout.txt
diff --git a/test/018-stack-overflow/Android.bp b/test/018-stack-overflow/Android.bp
new file mode 100644
index 0000000..504bdaa
--- /dev/null
+++ b/test/018-stack-overflow/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `018-stack-overflow`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-018-stack-overflow",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-018-stack-overflow-expected-stdout",
+        ":art-run-test-018-stack-overflow-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-018-stack-overflow-expected-stdout",
+    out: ["art-run-test-018-stack-overflow-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-018-stack-overflow-expected-stderr",
+    out: ["art-run-test-018-stack-overflow-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/402-optimizing-control-flow/expected.txt b/test/018-stack-overflow/expected-stderr.txt
similarity index 100%
copy from test/402-optimizing-control-flow/expected.txt
copy to test/018-stack-overflow/expected-stderr.txt
diff --git a/test/018-stack-overflow/expected.txt b/test/018-stack-overflow/expected-stdout.txt
similarity index 100%
rename from test/018-stack-overflow/expected.txt
rename to test/018-stack-overflow/expected-stdout.txt
diff --git a/test/019-wrong-array-type/Android.bp b/test/019-wrong-array-type/Android.bp
new file mode 100644
index 0000000..51db2d3
--- /dev/null
+++ b/test/019-wrong-array-type/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `019-wrong-array-type`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-019-wrong-array-type",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-019-wrong-array-type-expected-stdout",
+        ":art-run-test-019-wrong-array-type-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-019-wrong-array-type-expected-stdout",
+    out: ["art-run-test-019-wrong-array-type-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-019-wrong-array-type-expected-stderr",
+    out: ["art-run-test-019-wrong-array-type-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/477-checker-bound-type/expected.txt b/test/019-wrong-array-type/expected-stderr.txt
similarity index 100%
copy from test/477-checker-bound-type/expected.txt
copy to test/019-wrong-array-type/expected-stderr.txt
diff --git a/test/019-wrong-array-type/expected.txt b/test/019-wrong-array-type/expected-stdout.txt
similarity index 100%
rename from test/019-wrong-array-type/expected.txt
rename to test/019-wrong-array-type/expected-stdout.txt
diff --git a/test/020-string/Android.bp b/test/020-string/Android.bp
new file mode 100644
index 0000000..e588f2f
--- /dev/null
+++ b/test/020-string/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `020-string`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-020-string",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-020-string-expected-stdout",
+        ":art-run-test-020-string-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-020-string-expected-stdout",
+    out: ["art-run-test-020-string-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-020-string-expected-stderr",
+    out: ["art-run-test-020-string-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/020-string/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/020-string/expected-stderr.txt
diff --git a/test/020-string/expected.txt b/test/020-string/expected-stdout.txt
similarity index 100%
rename from test/020-string/expected.txt
rename to test/020-string/expected-stdout.txt
diff --git a/test/021-string2/Android.bp b/test/021-string2/Android.bp
new file mode 100644
index 0000000..7a6183c
--- /dev/null
+++ b/test/021-string2/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `021-string2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-021-string2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-021-string2-expected-stdout",
+        ":art-run-test-021-string2-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-021-string2-expected-stdout",
+    out: ["art-run-test-021-string2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-021-string2-expected-stderr",
+    out: ["art-run-test-021-string2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/021-string2/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/021-string2/expected-stderr.txt
diff --git a/test/021-string2/expected.txt b/test/021-string2/expected-stdout.txt
similarity index 100%
rename from test/021-string2/expected.txt
rename to test/021-string2/expected-stdout.txt
diff --git a/test/021-string2/src/Main.java b/test/021-string2/src/Main.java
index 141a089..39595f3 100644
--- a/test/021-string2/src/Main.java
+++ b/test/021-string2/src/Main.java
@@ -118,6 +118,7 @@
 
         testEqualsConstString();
         testConstStringEquals();
+        testStringConcat();
 
         // Regression tests for String.setCharAt() breaking string compression invariants.
         Locale en_US = new Locale("en", "US");
@@ -752,6 +753,13 @@
         Assert.assertTrue("A".equals(new String(new byte[] { (byte)'A' }, /* hibyte */ 0x100)));
     }
 
+    public static void testStringConcat() {
+        Assert.assertEquals("abcxyzw", "abc".concat("xyzw"));
+        Assert.assertEquals("abc\u0440", "abc".concat("\u0440"));
+        Assert.assertEquals("\u0440xyzw", "\u0440".concat("xyzw"));
+        Assert.assertEquals("abc\u0440xyzw\u0440", "abc\u0440".concat("xyzw\u0440"));
+    }
+
     public static boolean $noinline$equalsConstString0(String s) {
         return s.equals("");
     }
diff --git a/test/022-interface/Android.bp b/test/022-interface/Android.bp
new file mode 100644
index 0000000..7655279
--- /dev/null
+++ b/test/022-interface/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `022-interface`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-022-interface",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-022-interface-expected-stdout",
+        ":art-run-test-022-interface-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-022-interface-expected-stdout",
+    out: ["art-run-test-022-interface-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-022-interface-expected-stderr",
+    out: ["art-run-test-022-interface-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/423-invoke-interface/expected.txt b/test/022-interface/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/022-interface/expected-stderr.txt
diff --git a/test/022-interface/expected.txt b/test/022-interface/expected-stdout.txt
similarity index 100%
rename from test/022-interface/expected.txt
rename to test/022-interface/expected-stdout.txt
diff --git a/test/1901-get-bytecodes/expected.txt b/test/023-many-interfaces/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/023-many-interfaces/expected-stderr.txt
diff --git a/test/023-many-interfaces/expected.txt b/test/023-many-interfaces/expected-stdout.txt
similarity index 100%
rename from test/023-many-interfaces/expected.txt
rename to test/023-many-interfaces/expected-stdout.txt
diff --git a/test/607-daemon-stress/expected.txt b/test/024-illegal-access/expected-stderr.txt
similarity index 100%
copy from test/607-daemon-stress/expected.txt
copy to test/024-illegal-access/expected-stderr.txt
diff --git a/test/024-illegal-access/expected.txt b/test/024-illegal-access/expected-stdout.txt
similarity index 100%
rename from test/024-illegal-access/expected.txt
rename to test/024-illegal-access/expected-stdout.txt
diff --git a/test/025-access-controller/Android.bp b/test/025-access-controller/Android.bp
new file mode 100644
index 0000000..b02cf03
--- /dev/null
+++ b/test/025-access-controller/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `025-access-controller`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-025-access-controller",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-025-access-controller-expected-stdout",
+        ":art-run-test-025-access-controller-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-025-access-controller-expected-stdout",
+    out: ["art-run-test-025-access-controller-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-025-access-controller-expected-stderr",
+    out: ["art-run-test-025-access-controller-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/706-checker-scheduler/expected.txt b/test/025-access-controller/expected-stderr.txt
similarity index 100%
copy from test/706-checker-scheduler/expected.txt
copy to test/025-access-controller/expected-stderr.txt
diff --git a/test/025-access-controller/expected.txt b/test/025-access-controller/expected-stdout.txt
similarity index 100%
rename from test/025-access-controller/expected.txt
rename to test/025-access-controller/expected-stdout.txt
diff --git a/test/026-access/Android.bp b/test/026-access/Android.bp
new file mode 100644
index 0000000..74153c4
--- /dev/null
+++ b/test/026-access/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `026-access`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-026-access",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-026-access-expected-stdout",
+        ":art-run-test-026-access-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-026-access-expected-stdout",
+    out: ["art-run-test-026-access-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-026-access-expected-stderr",
+    out: ["art-run-test-026-access-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/026-access/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/026-access/expected-stderr.txt
diff --git a/test/026-access/expected.txt b/test/026-access/expected-stdout.txt
similarity index 100%
rename from test/026-access/expected.txt
rename to test/026-access/expected-stdout.txt
diff --git a/test/027-arithmetic/Android.bp b/test/027-arithmetic/Android.bp
new file mode 100644
index 0000000..bd16e9d
--- /dev/null
+++ b/test/027-arithmetic/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `027-arithmetic`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-027-arithmetic",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-027-arithmetic-expected-stdout",
+        ":art-run-test-027-arithmetic-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-027-arithmetic-expected-stdout",
+    out: ["art-run-test-027-arithmetic-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-027-arithmetic-expected-stderr",
+    out: ["art-run-test-027-arithmetic-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/027-arithmetic/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/027-arithmetic/expected-stderr.txt
diff --git a/test/027-arithmetic/expected.txt b/test/027-arithmetic/expected-stdout.txt
similarity index 100%
rename from test/027-arithmetic/expected.txt
rename to test/027-arithmetic/expected-stdout.txt
diff --git a/test/028-array-write/Android.bp b/test/028-array-write/Android.bp
new file mode 100644
index 0000000..1375c6e
--- /dev/null
+++ b/test/028-array-write/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `028-array-write`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-028-array-write",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-028-array-write-expected-stdout",
+        ":art-run-test-028-array-write-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-028-array-write-expected-stdout",
+    out: ["art-run-test-028-array-write-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-028-array-write-expected-stderr",
+    out: ["art-run-test-028-array-write-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/082-inline-execute/expected.txt b/test/028-array-write/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/028-array-write/expected-stderr.txt
diff --git a/test/028-array-write/expected.txt b/test/028-array-write/expected-stdout.txt
similarity index 100%
rename from test/028-array-write/expected.txt
rename to test/028-array-write/expected-stdout.txt
diff --git a/test/029-assert/Android.bp b/test/029-assert/Android.bp
new file mode 100644
index 0000000..466f134
--- /dev/null
+++ b/test/029-assert/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `029-assert`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-029-assert",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-029-assert-expected-stdout",
+        ":art-run-test-029-assert-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-029-assert-expected-stdout",
+    out: ["art-run-test-029-assert-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-029-assert-expected-stderr",
+    out: ["art-run-test-029-assert-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/029-assert/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/029-assert/expected-stderr.txt
diff --git a/test/029-assert/expected.txt b/test/029-assert/expected-stdout.txt
similarity index 100%
rename from test/029-assert/expected.txt
rename to test/029-assert/expected-stdout.txt
diff --git a/test/030-bad-finalizer/Android.bp b/test/030-bad-finalizer/Android.bp
new file mode 100644
index 0000000..c91ebc3
--- /dev/null
+++ b/test/030-bad-finalizer/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `030-bad-finalizer`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-030-bad-finalizer",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-030-bad-finalizer-expected-stdout",
+        ":art-run-test-030-bad-finalizer-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-030-bad-finalizer-expected-stdout",
+    out: ["art-run-test-030-bad-finalizer-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-030-bad-finalizer-expected-stderr",
+    out: ["art-run-test-030-bad-finalizer-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/718-zipfile-finalizer/expected.txt b/test/030-bad-finalizer/expected-stderr.txt
similarity index 100%
copy from test/718-zipfile-finalizer/expected.txt
copy to test/030-bad-finalizer/expected-stderr.txt
diff --git a/test/030-bad-finalizer/expected.txt b/test/030-bad-finalizer/expected-stdout.txt
similarity index 100%
rename from test/030-bad-finalizer/expected.txt
rename to test/030-bad-finalizer/expected-stdout.txt
diff --git a/test/542-bitfield-rotates/expected.txt b/test/031-class-attributes/expected-stderr.txt
similarity index 100%
copy from test/542-bitfield-rotates/expected.txt
copy to test/031-class-attributes/expected-stderr.txt
diff --git a/test/031-class-attributes/expected.txt b/test/031-class-attributes/expected-stdout.txt
similarity index 100%
rename from test/031-class-attributes/expected.txt
rename to test/031-class-attributes/expected-stdout.txt
diff --git a/test/001-Main/expected.txt b/test/032-concrete-sub/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/032-concrete-sub/expected-stderr.txt
diff --git a/test/032-concrete-sub/expected.txt b/test/032-concrete-sub/expected-stdout.txt
similarity index 100%
rename from test/032-concrete-sub/expected.txt
rename to test/032-concrete-sub/expected-stdout.txt
diff --git a/test/033-class-init-deadlock/Android.bp b/test/033-class-init-deadlock/Android.bp
new file mode 100644
index 0000000..5aae481
--- /dev/null
+++ b/test/033-class-init-deadlock/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `033-class-init-deadlock`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-033-class-init-deadlock",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-033-class-init-deadlock-expected-stdout",
+        ":art-run-test-033-class-init-deadlock-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-033-class-init-deadlock-expected-stdout",
+    out: ["art-run-test-033-class-init-deadlock-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-033-class-init-deadlock-expected-stderr",
+    out: ["art-run-test-033-class-init-deadlock-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/670-bitstring-type-check/expected.txt b/test/033-class-init-deadlock/expected-stderr.txt
similarity index 100%
copy from test/670-bitstring-type-check/expected.txt
copy to test/033-class-init-deadlock/expected-stderr.txt
diff --git a/test/033-class-init-deadlock/expected.txt b/test/033-class-init-deadlock/expected-stdout.txt
similarity index 100%
rename from test/033-class-init-deadlock/expected.txt
rename to test/033-class-init-deadlock/expected-stdout.txt
diff --git a/test/034-call-null/Android.bp b/test/034-call-null/Android.bp
new file mode 100644
index 0000000..13d71a4
--- /dev/null
+++ b/test/034-call-null/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `034-call-null`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-034-call-null",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-034-call-null-expected-stdout",
+        ":art-run-test-034-call-null-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-034-call-null-expected-stdout",
+    out: ["art-run-test-034-call-null-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-034-call-null-expected-stderr",
+    out: ["art-run-test-034-call-null-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/034-call-null/expected-stderr.txt b/test/034-call-null/expected-stderr.txt
new file mode 100644
index 0000000..4e0281e
--- /dev/null
+++ b/test/034-call-null/expected-stderr.txt
@@ -0,0 +1,2 @@
+Exception in thread "main" java.lang.NullPointerException: Attempt to invoke direct method 'void Main.doStuff(int, int[][], java.lang.String, java.lang.String[][])' on a null object reference
+	at Main.main(Main.java:26)
diff --git a/test/034-call-null/expected-stdout.txt b/test/034-call-null/expected-stdout.txt
new file mode 100644
index 0000000..a9bf5a0
--- /dev/null
+++ b/test/034-call-null/expected-stdout.txt
@@ -0,0 +1 @@
+exit status: 1
diff --git a/test/034-call-null/expected.txt b/test/034-call-null/expected.txt
deleted file mode 100644
index 11aefde..0000000
--- a/test/034-call-null/expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Exception in thread "main" java.lang.NullPointerException: Attempt to invoke direct method 'void Main.doStuff(int, int[][], java.lang.String, java.lang.String[][])' on a null object reference
-	at Main.main(Main.java:26)
-exit status: 1
diff --git a/test/035-enum/Android.bp b/test/035-enum/Android.bp
new file mode 100644
index 0000000..4041fea
--- /dev/null
+++ b/test/035-enum/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `035-enum`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-035-enum",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-035-enum-expected-stdout",
+        ":art-run-test-035-enum-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-035-enum-expected-stdout",
+    out: ["art-run-test-035-enum-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-035-enum-expected-stderr",
+    out: ["art-run-test-035-enum-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/035-enum/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/035-enum/expected-stderr.txt
diff --git a/test/035-enum/expected.txt b/test/035-enum/expected-stdout.txt
similarity index 100%
rename from test/035-enum/expected.txt
rename to test/035-enum/expected-stdout.txt
diff --git a/test/036-finalizer/Android.bp b/test/036-finalizer/Android.bp
new file mode 100644
index 0000000..6e2ca7a
--- /dev/null
+++ b/test/036-finalizer/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `036-finalizer`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-036-finalizer",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-036-finalizer-expected-stdout",
+        ":art-run-test-036-finalizer-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-036-finalizer-expected-stdout",
+    out: ["art-run-test-036-finalizer-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-036-finalizer-expected-stderr",
+    out: ["art-run-test-036-finalizer-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/718-zipfile-finalizer/expected.txt b/test/036-finalizer/expected-stderr.txt
similarity index 100%
copy from test/718-zipfile-finalizer/expected.txt
copy to test/036-finalizer/expected-stderr.txt
diff --git a/test/036-finalizer/expected.txt b/test/036-finalizer/expected-stdout.txt
similarity index 100%
rename from test/036-finalizer/expected.txt
rename to test/036-finalizer/expected-stdout.txt
diff --git a/test/037-inherit/Android.bp b/test/037-inherit/Android.bp
new file mode 100644
index 0000000..fc11a8e
--- /dev/null
+++ b/test/037-inherit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `037-inherit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-037-inherit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-037-inherit-expected-stdout",
+        ":art-run-test-037-inherit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-037-inherit-expected-stdout",
+    out: ["art-run-test-037-inherit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-037-inherit-expected-stderr",
+    out: ["art-run-test-037-inherit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/037-inherit/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/037-inherit/expected-stderr.txt
diff --git a/test/037-inherit/expected.txt b/test/037-inherit/expected-stdout.txt
similarity index 100%
rename from test/037-inherit/expected.txt
rename to test/037-inherit/expected-stdout.txt
diff --git a/test/038-inner-null/Android.bp b/test/038-inner-null/Android.bp
new file mode 100644
index 0000000..3787fe0
--- /dev/null
+++ b/test/038-inner-null/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `038-inner-null`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-038-inner-null",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-038-inner-null-expected-stdout",
+        ":art-run-test-038-inner-null-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-038-inner-null-expected-stdout",
+    out: ["art-run-test-038-inner-null-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-038-inner-null-expected-stderr",
+    out: ["art-run-test-038-inner-null-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/038-inner-null/expected-stderr.txt b/test/038-inner-null/expected-stderr.txt
new file mode 100644
index 0000000..5136a99
--- /dev/null
+++ b/test/038-inner-null/expected-stderr.txt
@@ -0,0 +1,3 @@
+Exception in thread "main" java.lang.NullPointerException: Attempt to invoke virtual method 'void Main$Blort.repaint()' on a null object reference
+	at Main$Special.callInner(Main.java:31)
+	at Main.main(Main.java:20)
diff --git a/test/038-inner-null/expected-stdout.txt b/test/038-inner-null/expected-stdout.txt
new file mode 100644
index 0000000..3d87b3f
--- /dev/null
+++ b/test/038-inner-null/expected-stdout.txt
@@ -0,0 +1,2 @@
+new Special()
+exit status: 1
diff --git a/test/038-inner-null/expected.txt b/test/038-inner-null/expected.txt
deleted file mode 100644
index d148eff..0000000
--- a/test/038-inner-null/expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-new Special()
-Exception in thread "main" java.lang.NullPointerException: Attempt to invoke virtual method 'void Main$Blort.repaint()' on a null object reference
-	at Main$Special.callInner(Main.java:31)
-	at Main.main(Main.java:20)
-exit status: 1
diff --git a/test/039-join-main/Android.bp b/test/039-join-main/Android.bp
new file mode 100644
index 0000000..a6f9df4
--- /dev/null
+++ b/test/039-join-main/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `039-join-main`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-039-join-main",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-039-join-main-expected-stdout",
+        ":art-run-test-039-join-main-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-039-join-main-expected-stdout",
+    out: ["art-run-test-039-join-main-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-039-join-main-expected-stderr",
+    out: ["art-run-test-039-join-main-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/039-join-main/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/039-join-main/expected-stderr.txt
diff --git a/test/039-join-main/expected.txt b/test/039-join-main/expected-stdout.txt
similarity index 100%
rename from test/039-join-main/expected.txt
rename to test/039-join-main/expected-stdout.txt
diff --git a/test/040-miranda/Android.bp b/test/040-miranda/Android.bp
new file mode 100644
index 0000000..ca965ab
--- /dev/null
+++ b/test/040-miranda/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `040-miranda`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-040-miranda",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-040-miranda-expected-stdout",
+        ":art-run-test-040-miranda-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-040-miranda-expected-stdout",
+    out: ["art-run-test-040-miranda-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-040-miranda-expected-stderr",
+    out: ["art-run-test-040-miranda-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/040-miranda/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/040-miranda/expected-stderr.txt
diff --git a/test/040-miranda/expected.txt b/test/040-miranda/expected-stdout.txt
similarity index 100%
rename from test/040-miranda/expected.txt
rename to test/040-miranda/expected-stdout.txt
diff --git a/test/041-narrowing/Android.bp b/test/041-narrowing/Android.bp
new file mode 100644
index 0000000..4ad0b9c
--- /dev/null
+++ b/test/041-narrowing/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `041-narrowing`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-041-narrowing",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-041-narrowing-expected-stdout",
+        ":art-run-test-041-narrowing-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-041-narrowing-expected-stdout",
+    out: ["art-run-test-041-narrowing-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-041-narrowing-expected-stderr",
+    out: ["art-run-test-041-narrowing-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/041-narrowing/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/041-narrowing/expected-stderr.txt
diff --git a/test/041-narrowing/expected.txt b/test/041-narrowing/expected-stdout.txt
similarity index 100%
rename from test/041-narrowing/expected.txt
rename to test/041-narrowing/expected-stdout.txt
diff --git a/test/435-new-instance/expected.txt b/test/042-new-instance/expected-stderr.txt
similarity index 100%
copy from test/435-new-instance/expected.txt
copy to test/042-new-instance/expected-stderr.txt
diff --git a/test/042-new-instance/expected.txt b/test/042-new-instance/expected-stdout.txt
similarity index 100%
rename from test/042-new-instance/expected.txt
rename to test/042-new-instance/expected-stdout.txt
diff --git a/test/043-privates/Android.bp b/test/043-privates/Android.bp
new file mode 100644
index 0000000..dd5b476
--- /dev/null
+++ b/test/043-privates/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `043-privates`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-043-privates",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-043-privates-expected-stdout",
+        ":art-run-test-043-privates-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-043-privates-expected-stdout",
+    out: ["art-run-test-043-privates-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-043-privates-expected-stderr",
+    out: ["art-run-test-043-privates-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/043-privates/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/043-privates/expected-stderr.txt
diff --git a/test/043-privates/expected.txt b/test/043-privates/expected-stdout.txt
similarity index 100%
rename from test/043-privates/expected.txt
rename to test/043-privates/expected-stdout.txt
diff --git a/test/044-proxy/Android.bp b/test/044-proxy/Android.bp
new file mode 100644
index 0000000..f241880
--- /dev/null
+++ b/test/044-proxy/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `044-proxy`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-044-proxy",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-044-proxy-expected-stdout",
+        ":art-run-test-044-proxy-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-044-proxy-expected-stdout",
+    out: ["art-run-test-044-proxy-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-044-proxy-expected-stderr",
+    out: ["art-run-test-044-proxy-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/044-proxy/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/044-proxy/expected-stderr.txt
diff --git a/test/044-proxy/expected.txt b/test/044-proxy/expected-stdout.txt
similarity index 100%
rename from test/044-proxy/expected.txt
rename to test/044-proxy/expected-stdout.txt
diff --git a/test/044-proxy/src/HotProxy.java b/test/044-proxy/src/HotProxy.java
new file mode 100644
index 0000000..0c5ec1c
--- /dev/null
+++ b/test/044-proxy/src/HotProxy.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+import java.lang.reflect.*;
+
+public class HotProxy {
+
+  public static final String testName = "HotProxy";
+
+  interface MyInterface {
+    void voidFoo();
+  }
+
+  static void check(boolean x) {
+    if (!x) {
+      throw new AssertionError(testName + " Check failed");
+    }
+  }
+
+  static class MyInvocationHandler implements InvocationHandler {
+    public Object invoke(Object proxy, Method method, Object[] args) {
+      check(proxy instanceof Proxy);
+      check(method.getDeclaringClass() == MyInterface.class);
+      return null;
+    }
+  }
+
+  static void testProxy() {
+    MyInvocationHandler myHandler = new MyInvocationHandler();
+    MyInterface proxyMyInterface =
+        (MyInterface)Proxy.newProxyInstance(HotProxy.class.getClassLoader(),
+                                            new Class<?>[] { MyInterface.class },
+                                            myHandler);
+    // Invoke the proxy method multiple times to ensure it becomes hot and the JIT handles it.
+    for (int i = 0; i < 0x10000; i++) {
+      proxyMyInterface.voidFoo();
+    }
+  }
+
+  public static void main(String args[]) {
+    testProxy();
+  }
+}
diff --git a/test/044-proxy/src/Main.java b/test/044-proxy/src/Main.java
index 7b70e65..8be09cf 100644
--- a/test/044-proxy/src/Main.java
+++ b/test/044-proxy/src/Main.java
@@ -33,6 +33,7 @@
         NativeProxy.main(args);
         ConstructorProxy.main();
         OOMEOnDispatch.main(args);
+        HotProxy.main(args);
     }
 
     // The following code maps from the actual proxy class names (eg $Proxy2) to their test output
diff --git a/test/044-proxy/src/OOMEOnDispatch.java b/test/044-proxy/src/OOMEOnDispatch.java
index 2ee5792..00110bc 100644
--- a/test/044-proxy/src/OOMEOnDispatch.java
+++ b/test/044-proxy/src/OOMEOnDispatch.java
@@ -26,6 +26,17 @@
 
     static ArrayList<Object> storage = new ArrayList<>(100000);
 
+    private static void exhaustJavaHeap(int size) {
+      Runtime.getRuntime().gc();
+      while (size > 0) {
+        try {
+          storage.add(new byte[size]);
+        } catch (OutOfMemoryError e) {
+          size = size/2;
+        }
+      }
+    }
+
     public static void main(String[] args) {
         InvocationHandler handler = new OOMEOnDispatch();
         OOMEInterface inf = (OOMEInterface)Proxy.newProxyInstance(
@@ -37,14 +48,17 @@
         Main.stopJit();
         Main.waitForCompilation();
 
-        int l = 1024 * 1024;
-        while (l > 8) {
-          try {
-            storage.add(new byte[l]);
-          } catch (OutOfMemoryError e) {
-            l = l/2;
-          }
-        }
+        // Make sure that there is no reclaimable memory in the heap. Otherwise we may throw
+        // OOME to prevent GC thrashing, even if later allocations may succeed.
+        Runtime.getRuntime().gc();
+        System.runFinalization();
+        // NOTE: There is a GC invocation in the exhaustJavaHeap(). So we don't need one here.
+
+        int initial_size = 1024 * 1024;
+        // Repeat to ensure there is no space left on the heap.
+        exhaustJavaHeap(initial_size);
+        exhaustJavaHeap(/*size*/ 4);
+        exhaustJavaHeap(/*size*/ 4);
 
         try {
             inf.foo();
diff --git a/test/045-reflect-array/Android.bp b/test/045-reflect-array/Android.bp
new file mode 100644
index 0000000..c10758c
--- /dev/null
+++ b/test/045-reflect-array/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `045-reflect-array`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-045-reflect-array",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-045-reflect-array-expected-stdout",
+        ":art-run-test-045-reflect-array-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-045-reflect-array-expected-stdout",
+    out: ["art-run-test-045-reflect-array-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-045-reflect-array-expected-stderr",
+    out: ["art-run-test-045-reflect-array-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/412-new-array/expected.txt b/test/045-reflect-array/expected-stderr.txt
similarity index 100%
copy from test/412-new-array/expected.txt
copy to test/045-reflect-array/expected-stderr.txt
diff --git a/test/045-reflect-array/expected.txt b/test/045-reflect-array/expected-stdout.txt
similarity index 100%
rename from test/045-reflect-array/expected.txt
rename to test/045-reflect-array/expected-stdout.txt
diff --git a/test/046-reflect/Android.bp b/test/046-reflect/Android.bp
new file mode 100644
index 0000000..4dcf475
--- /dev/null
+++ b/test/046-reflect/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `046-reflect`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-046-reflect",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-046-reflect-expected-stdout",
+        ":art-run-test-046-reflect-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-046-reflect-expected-stdout",
+    out: ["art-run-test-046-reflect-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-046-reflect-expected-stderr",
+    out: ["art-run-test-046-reflect-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/046-reflect/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/046-reflect/expected-stderr.txt
diff --git a/test/046-reflect/expected.txt b/test/046-reflect/expected-stdout.txt
similarity index 100%
rename from test/046-reflect/expected.txt
rename to test/046-reflect/expected-stdout.txt
diff --git a/test/046-reflect/src/Main.java b/test/046-reflect/src/Main.java
index 6d6cc13..6cd137d 100644
--- a/test/046-reflect/src/Main.java
+++ b/test/046-reflect/src/Main.java
@@ -502,12 +502,12 @@
     /*
      * Test some generic type stuff.
      */
-    public List<String> dummy;
+    public List<String> stringList;
     public Map<Integer,String> fancyMethod(ArrayList<String> blah) { return null; }
     public static void checkGeneric() {
         Field field;
         try {
-            field = Main.class.getField("dummy");
+            field = Main.class.getField("stringList");
         } catch (NoSuchFieldException nsfe) {
             throw new RuntimeException(nsfe);
         }
@@ -561,8 +561,8 @@
     public static void checkUnique() {
         Field field1, field2;
         try {
-            field1 = Main.class.getField("dummy");
-            field2 = Main.class.getField("dummy");
+            field1 = Main.class.getField("stringList");
+            field2 = Main.class.getField("stringList");
         } catch (NoSuchFieldException nsfe) {
             throw new RuntimeException(nsfe);
         }
diff --git a/test/047-returns/Android.bp b/test/047-returns/Android.bp
new file mode 100644
index 0000000..f6a3312
--- /dev/null
+++ b/test/047-returns/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `047-returns`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-047-returns",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-047-returns-expected-stdout",
+        ":art-run-test-047-returns-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-047-returns-expected-stdout",
+    out: ["art-run-test-047-returns-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-047-returns-expected-stderr",
+    out: ["art-run-test-047-returns-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/448-multiple-returns/expected.txt b/test/047-returns/expected-stderr.txt
similarity index 100%
copy from test/448-multiple-returns/expected.txt
copy to test/047-returns/expected-stderr.txt
diff --git a/test/047-returns/expected.txt b/test/047-returns/expected-stdout.txt
similarity index 100%
rename from test/047-returns/expected.txt
rename to test/047-returns/expected-stdout.txt
diff --git a/test/048-reflect-v8/Android.bp b/test/048-reflect-v8/Android.bp
new file mode 100644
index 0000000..799dcfb
--- /dev/null
+++ b/test/048-reflect-v8/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `048-reflect-v8`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-048-reflect-v8",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-048-reflect-v8-expected-stdout",
+        ":art-run-test-048-reflect-v8-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-048-reflect-v8-expected-stdout",
+    out: ["art-run-test-048-reflect-v8-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-048-reflect-v8-expected-stderr",
+    out: ["art-run-test-048-reflect-v8-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/048-reflect-v8/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/048-reflect-v8/expected-stderr.txt
diff --git a/test/048-reflect-v8/expected.txt b/test/048-reflect-v8/expected-stdout.txt
similarity index 100%
rename from test/048-reflect-v8/expected.txt
rename to test/048-reflect-v8/expected-stdout.txt
diff --git a/test/049-show-object/Android.bp b/test/049-show-object/Android.bp
new file mode 100644
index 0000000..75bda84
--- /dev/null
+++ b/test/049-show-object/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `049-show-object`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-049-show-object",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-049-show-object-expected-stdout",
+        ":art-run-test-049-show-object-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-049-show-object-expected-stdout",
+    out: ["art-run-test-049-show-object-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-049-show-object-expected-stderr",
+    out: ["art-run-test-049-show-object-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/152-dead-large-object/expected.txt b/test/049-show-object/expected-stderr.txt
similarity index 100%
copy from test/152-dead-large-object/expected.txt
copy to test/049-show-object/expected-stderr.txt
diff --git a/test/049-show-object/expected.txt b/test/049-show-object/expected-stdout.txt
similarity index 100%
rename from test/049-show-object/expected.txt
rename to test/049-show-object/expected-stdout.txt
diff --git a/test/050-sync-test/Android.bp b/test/050-sync-test/Android.bp
new file mode 100644
index 0000000..6959b05
--- /dev/null
+++ b/test/050-sync-test/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `050-sync-test`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-050-sync-test",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-050-sync-test-expected-stdout",
+        ":art-run-test-050-sync-test-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-050-sync-test-expected-stdout",
+    out: ["art-run-test-050-sync-test-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-050-sync-test-expected-stderr",
+    out: ["art-run-test-050-sync-test-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/507-boolean-test/expected.txt b/test/050-sync-test/expected-stderr.txt
similarity index 100%
copy from test/507-boolean-test/expected.txt
copy to test/050-sync-test/expected-stderr.txt
diff --git a/test/050-sync-test/expected.txt b/test/050-sync-test/expected-stdout.txt
similarity index 100%
rename from test/050-sync-test/expected.txt
rename to test/050-sync-test/expected-stdout.txt
diff --git a/test/051-thread/Android.bp b/test/051-thread/Android.bp
new file mode 100644
index 0000000..f1c658c
--- /dev/null
+++ b/test/051-thread/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `051-thread`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-051-thread",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-051-thread-expected-stdout",
+        ":art-run-test-051-thread-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-051-thread-expected-stdout",
+    out: ["art-run-test-051-thread-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-051-thread-expected-stderr",
+    out: ["art-run-test-051-thread-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/051-thread/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/051-thread/expected-stderr.txt
diff --git a/test/051-thread/expected.txt b/test/051-thread/expected-stdout.txt
similarity index 100%
rename from test/051-thread/expected.txt
rename to test/051-thread/expected-stdout.txt
diff --git a/test/052-verifier-fun/Android.bp b/test/052-verifier-fun/Android.bp
new file mode 100644
index 0000000..8c3da44
--- /dev/null
+++ b/test/052-verifier-fun/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `052-verifier-fun`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-052-verifier-fun",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-052-verifier-fun-expected-stdout",
+        ":art-run-test-052-verifier-fun-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-052-verifier-fun-expected-stdout",
+    out: ["art-run-test-052-verifier-fun-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-052-verifier-fun-expected-stderr",
+    out: ["art-run-test-052-verifier-fun-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/052-verifier-fun/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/052-verifier-fun/expected-stderr.txt
diff --git a/test/052-verifier-fun/expected.txt b/test/052-verifier-fun/expected-stdout.txt
similarity index 100%
rename from test/052-verifier-fun/expected.txt
rename to test/052-verifier-fun/expected-stdout.txt
diff --git a/test/053-wait-some/Android.bp b/test/053-wait-some/Android.bp
new file mode 100644
index 0000000..210cecb
--- /dev/null
+++ b/test/053-wait-some/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `053-wait-some`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-053-wait-some",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-053-wait-some-expected-stdout",
+        ":art-run-test-053-wait-some-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-053-wait-some-expected-stdout",
+    out: ["art-run-test-053-wait-some-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-053-wait-some-expected-stderr",
+    out: ["art-run-test-053-wait-some-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/202-thread-oome/expected.txt b/test/053-wait-some/expected-stderr.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/053-wait-some/expected-stderr.txt
diff --git a/test/053-wait-some/expected.txt b/test/053-wait-some/expected-stdout.txt
similarity index 100%
rename from test/053-wait-some/expected.txt
rename to test/053-wait-some/expected-stdout.txt
diff --git a/test/053-wait-some/src/Main.java b/test/053-wait-some/src/Main.java
index b8e6dfe..0fd9e8d 100644
--- a/test/053-wait-some/src/Main.java
+++ b/test/053-wait-some/src/Main.java
@@ -42,6 +42,7 @@
                 ie.printStackTrace(System.out);
             }
 
+            long total_extra_delay = 0;
             for (long delay : DELAYS) {
                 System.out.println("Waiting for " + delay + "ms...");
 
@@ -57,15 +58,19 @@
                 boolean showTime = timing;
 
                 if (! timing) {
-                    long epsilon = delay / 10;
-                    if (epsilon > 50) {
-                        epsilon = 50;
-                    }
-
-                    long min = delay - epsilon;
+                    // Allow a random scheduling delay of up to 600 msecs.
+                    // That value is empirically determined from failure logs.
+                    // We seem to get very occasional very long delays on host, perhaps due
+                    // to getting paged out.
+                    final long epsilon = 600;
+                    long min = delay - 1;
                     long max = delay + epsilon;
+                    total_extra_delay += elapsed - delay;
 
                     if (elapsed < min) {
+                        // This can legitimately happen due to premature wake-ups.
+                        // This seems rare and unexpected enough in practice that we should
+                        // still report.
                         System.out.println("  Elapsed time was too short");
                         showTime = true;
                     } else if (elapsed > max) {
@@ -80,6 +85,10 @@
                             + elapsed + "ms");
                 }
             }
+            if (total_extra_delay > 1000) {
+                System.out.println("  Total unrequested delay of " + total_extra_delay
+                    + "msecs was too long");
+            }
         }
     }
 }
diff --git a/test/054-uncaught/Android.bp b/test/054-uncaught/Android.bp
new file mode 100644
index 0000000..e017d48
--- /dev/null
+++ b/test/054-uncaught/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `054-uncaught`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-054-uncaught",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-054-uncaught-expected-stdout",
+        ":art-run-test-054-uncaught-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-054-uncaught-expected-stdout",
+    out: ["art-run-test-054-uncaught-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-054-uncaught-expected-stderr",
+    out: ["art-run-test-054-uncaught-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/054-uncaught/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/054-uncaught/expected-stderr.txt
diff --git a/test/054-uncaught/expected.txt b/test/054-uncaught/expected-stdout.txt
similarity index 100%
rename from test/054-uncaught/expected.txt
rename to test/054-uncaught/expected-stdout.txt
diff --git a/test/055-enum-performance/Android.bp b/test/055-enum-performance/Android.bp
new file mode 100644
index 0000000..57f3534
--- /dev/null
+++ b/test/055-enum-performance/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `055-enum-performance`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-055-enum-performance",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-055-enum-performance-expected-stdout",
+        ":art-run-test-055-enum-performance-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-055-enum-performance-expected-stdout",
+    out: ["art-run-test-055-enum-performance-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-055-enum-performance-expected-stderr",
+    out: ["art-run-test-055-enum-performance-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/435-new-instance/expected.txt b/test/055-enum-performance/expected-stderr.txt
similarity index 100%
copy from test/435-new-instance/expected.txt
copy to test/055-enum-performance/expected-stderr.txt
diff --git a/test/055-enum-performance/expected.txt b/test/055-enum-performance/expected-stdout.txt
similarity index 100%
rename from test/055-enum-performance/expected.txt
rename to test/055-enum-performance/expected-stdout.txt
diff --git a/test/001-Main/expected.txt b/test/056-const-string-jumbo/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/056-const-string-jumbo/expected-stderr.txt
diff --git a/test/056-const-string-jumbo/expected.txt b/test/056-const-string-jumbo/expected-stdout.txt
similarity index 100%
rename from test/056-const-string-jumbo/expected.txt
rename to test/056-const-string-jumbo/expected-stdout.txt
diff --git a/test/058-enum-order/Android.bp b/test/058-enum-order/Android.bp
new file mode 100644
index 0000000..7ee529e
--- /dev/null
+++ b/test/058-enum-order/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `058-enum-order`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-058-enum-order",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-058-enum-order-expected-stdout",
+        ":art-run-test-058-enum-order-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-058-enum-order-expected-stdout",
+    out: ["art-run-test-058-enum-order-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-058-enum-order-expected-stderr",
+    out: ["art-run-test-058-enum-order-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/429-ssa-builder/expected.txt b/test/058-enum-order/expected-stderr.txt
similarity index 100%
copy from test/429-ssa-builder/expected.txt
copy to test/058-enum-order/expected-stderr.txt
diff --git a/test/058-enum-order/expected.txt b/test/058-enum-order/expected-stdout.txt
similarity index 100%
rename from test/058-enum-order/expected.txt
rename to test/058-enum-order/expected-stdout.txt
diff --git a/test/059-finalizer-throw/Android.bp b/test/059-finalizer-throw/Android.bp
new file mode 100644
index 0000000..5bbac4b
--- /dev/null
+++ b/test/059-finalizer-throw/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `059-finalizer-throw`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-059-finalizer-throw",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-059-finalizer-throw-expected-stdout",
+        ":art-run-test-059-finalizer-throw-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-059-finalizer-throw-expected-stdout",
+    out: ["art-run-test-059-finalizer-throw-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-059-finalizer-throw-expected-stderr",
+    out: ["art-run-test-059-finalizer-throw-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/059-finalizer-throw/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/059-finalizer-throw/expected-stderr.txt
diff --git a/test/059-finalizer-throw/expected.txt b/test/059-finalizer-throw/expected-stdout.txt
similarity index 100%
rename from test/059-finalizer-throw/expected.txt
rename to test/059-finalizer-throw/expected-stdout.txt
diff --git a/test/061-out-of-memory/Android.bp b/test/061-out-of-memory/Android.bp
new file mode 100644
index 0000000..9e24314
--- /dev/null
+++ b/test/061-out-of-memory/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `061-out-of-memory`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-061-out-of-memory",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-061-out-of-memory-expected-stdout",
+        ":art-run-test-061-out-of-memory-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-061-out-of-memory-expected-stdout",
+    out: ["art-run-test-061-out-of-memory-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-061-out-of-memory-expected-stderr",
+    out: ["art-run-test-061-out-of-memory-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/061-out-of-memory/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/061-out-of-memory/expected-stderr.txt
diff --git a/test/061-out-of-memory/expected.txt b/test/061-out-of-memory/expected-stdout.txt
similarity index 100%
rename from test/061-out-of-memory/expected.txt
rename to test/061-out-of-memory/expected-stdout.txt
diff --git a/test/062-character-encodings/Android.bp b/test/062-character-encodings/Android.bp
new file mode 100644
index 0000000..413313b
--- /dev/null
+++ b/test/062-character-encodings/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `062-character-encodings`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-062-character-encodings",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-062-character-encodings-expected-stdout",
+        ":art-run-test-062-character-encodings-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-062-character-encodings-expected-stdout",
+    out: ["art-run-test-062-character-encodings-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-062-character-encodings-expected-stderr",
+    out: ["art-run-test-062-character-encodings-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/062-character-encodings/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/062-character-encodings/expected-stderr.txt
diff --git a/test/062-character-encodings/expected.txt b/test/062-character-encodings/expected-stdout.txt
similarity index 100%
rename from test/062-character-encodings/expected.txt
rename to test/062-character-encodings/expected-stdout.txt
diff --git a/test/063-process-manager/Android.bp b/test/063-process-manager/Android.bp
new file mode 100644
index 0000000..5992a62
--- /dev/null
+++ b/test/063-process-manager/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `063-process-manager`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-063-process-manager",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-063-process-manager-expected-stdout",
+        ":art-run-test-063-process-manager-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-063-process-manager-expected-stdout",
+    out: ["art-run-test-063-process-manager-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-063-process-manager-expected-stderr",
+    out: ["art-run-test-063-process-manager-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/419-long-parameter/expected.txt b/test/063-process-manager/expected-stderr.txt
similarity index 100%
copy from test/419-long-parameter/expected.txt
copy to test/063-process-manager/expected-stderr.txt
diff --git a/test/063-process-manager/expected.txt b/test/063-process-manager/expected-stdout.txt
similarity index 100%
rename from test/063-process-manager/expected.txt
rename to test/063-process-manager/expected-stdout.txt
diff --git a/test/064-field-access/expected-stderr.txt b/test/064-field-access/expected-stderr.txt
new file mode 100644
index 0000000..6e58782
--- /dev/null
+++ b/test/064-field-access/expected-stderr.txt
@@ -0,0 +1 @@
+Received OOME
diff --git a/test/064-field-access/expected-stdout.txt b/test/064-field-access/expected-stdout.txt
new file mode 100644
index 0000000..59694a1
--- /dev/null
+++ b/test/064-field-access/expected-stdout.txt
@@ -0,0 +1,4 @@
+JNI_OnLoad called
+good
+Got expected failure
+Got expected failure
diff --git a/test/064-field-access/expected.txt b/test/064-field-access/expected.txt
deleted file mode 100644
index 8e1af74..0000000
--- a/test/064-field-access/expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-JNI_OnLoad called
-good
-Got expected failure
-Got expected failure
-Received OOME
diff --git a/test/064-field-access/src/OOMEOnNullAccess.java b/test/064-field-access/src/OOMEOnNullAccess.java
index 9343cd6..fbcb613 100644
--- a/test/064-field-access/src/OOMEOnNullAccess.java
+++ b/test/064-field-access/src/OOMEOnNullAccess.java
@@ -36,20 +36,35 @@
 
     static ArrayList<Object> storage = new ArrayList<>(100000);
 
+    private static void exhaustJavaHeap(int size) {
+      Runtime.getRuntime().gc();
+      while (size > 0) {
+        try {
+          storage.add(new byte[size]);
+        } catch (OutOfMemoryError e) {
+          size = size/2;
+        }
+      }
+    }
+
     public static void main(String[] args) {
         // Stop the JIT to be sure nothing is running that could be resolving classes or causing
         // verification.
         Main.stopJit();
         Main.waitForCompilation();
 
-        int l = 1024 * 1024;
-        while (l > 8) {
-          try {
-            storage.add(new byte[l]);
-          } catch (OutOfMemoryError e) {
-            l = l/2;
-          }
-        }
+        // Make sure that there is no reclaimable memory in the heap. Otherwise we may throw
+        // OOME to prevent GC thrashing, even if later allocations may succeed.
+        Runtime.getRuntime().gc();
+        System.runFinalization();
+        // NOTE: There is a GC invocation in the exhaustJavaHeap(). So we don't need one here.
+
+        int initial_size = 1024 * 1024;
+        // Repeat to ensure there is no space left on the heap.
+        exhaustJavaHeap(initial_size);
+        exhaustJavaHeap(/*size*/ 4);
+        exhaustJavaHeap(/*size*/ 4);
+
 
         try {
             nullAccess(null);
diff --git a/test/484-checker-register-hints/expected.txt b/test/065-mismatched-implements/expected-stderr.txt
similarity index 100%
copy from test/484-checker-register-hints/expected.txt
copy to test/065-mismatched-implements/expected-stderr.txt
diff --git a/test/065-mismatched-implements/expected.txt b/test/065-mismatched-implements/expected-stdout.txt
similarity index 100%
rename from test/065-mismatched-implements/expected.txt
rename to test/065-mismatched-implements/expected-stdout.txt
diff --git a/test/551-invoke-super/expected.txt b/test/066-mismatched-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/066-mismatched-super/expected-stderr.txt
diff --git a/test/066-mismatched-super/expected.txt b/test/066-mismatched-super/expected-stdout.txt
similarity index 100%
rename from test/066-mismatched-super/expected.txt
rename to test/066-mismatched-super/expected-stdout.txt
diff --git a/test/067-preemptive-unpark/Android.bp b/test/067-preemptive-unpark/Android.bp
new file mode 100644
index 0000000..26a62f8
--- /dev/null
+++ b/test/067-preemptive-unpark/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `067-preemptive-unpark`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-067-preemptive-unpark",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-067-preemptive-unpark-expected-stdout",
+        ":art-run-test-067-preemptive-unpark-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-067-preemptive-unpark-expected-stdout",
+    out: ["art-run-test-067-preemptive-unpark-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-067-preemptive-unpark-expected-stderr",
+    out: ["art-run-test-067-preemptive-unpark-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/067-preemptive-unpark/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/067-preemptive-unpark/expected-stderr.txt
diff --git a/test/067-preemptive-unpark/expected.txt b/test/067-preemptive-unpark/expected-stdout.txt
similarity index 100%
rename from test/067-preemptive-unpark/expected.txt
rename to test/067-preemptive-unpark/expected-stdout.txt
diff --git a/test/067-preemptive-unpark/src/Main.java b/test/067-preemptive-unpark/src/Main.java
index b674690..475f544 100644
--- a/test/067-preemptive-unpark/src/Main.java
+++ b/test/067-preemptive-unpark/src/Main.java
@@ -30,7 +30,6 @@
 
         test.start();
         UNSAFE.unpark(test);
-        clearStack(10);
 
         System.out.println("GC'ing");
         System.gc();
@@ -52,6 +51,11 @@
             System.out.println("Test succeeded!");
         } else {
             System.out.println("Test failed.");
+            test.printTimes();
+            System.out.println("Value of success = " + test.success);
+            Thread.sleep(3000);
+            System.out.println("Value of success after sleeping = " + test.success);
+            test.printTimes();  // In case they weren't ready the first time.
         }
     }
 
@@ -78,30 +82,12 @@
         UNSAFE = (Unsafe) field.get(null);
     }
 
-    /**
-     * Scribbles on the stack to help ensure we don't have a fake
-     * pointer that would keep would-be garbage alive.
-     */
-    private static void clearStack(int depth) {
-        int a = 0;
-        int b = 0;
-        int c = 0;
-        int d = 0;
-        int e = 0;
-        int f = 0;
-        int g = 0;
-        int h = 0;
-        int i = 0;
-        int j = 0;
-
-        if (depth > 0) {
-            clearStack(depth - 1);
-        }
-    }
-
     private static class ParkTester extends Thread {
         public volatile boolean parkNow = false;
         public volatile boolean success = false;
+        public volatile long startTime = 0;
+        public volatile long elapsedTime = 0;
+        public volatile long finishTime = 0;
 
         public void run() {
             while (!parkNow) {
@@ -117,12 +103,22 @@
             long elapsed = System.currentTimeMillis() - start;
 
             if (elapsed > 200) {
-                System.out.println("park()ed for " + elapsed + " msec");
                 success = false;
+                System.out.println("park()ed for " + elapsed + " msec");
             } else {
-                System.out.println("park() returned quickly");
                 success = true;
+                // println is occasionally very slow.
+                // But output still appears before main thread output.
+                System.out.println("park() returned quickly");
+                finishTime = System.currentTimeMillis();
+                startTime = start;
+                elapsedTime = elapsed;
             }
         }
+
+        public void printTimes() {
+          System.out.println("Started at " + startTime + "ms, took " + elapsedTime
+              + "ms, signalled at " + finishTime + "ms");
+        }
     }
 }
diff --git a/test/429-ssa-builder/expected.txt b/test/068-classloader/expected-stderr.txt
similarity index 100%
copy from test/429-ssa-builder/expected.txt
copy to test/068-classloader/expected-stderr.txt
diff --git a/test/068-classloader/expected.txt b/test/068-classloader/expected-stdout.txt
similarity index 100%
rename from test/068-classloader/expected.txt
rename to test/068-classloader/expected-stdout.txt
diff --git a/test/477-checker-bound-type/expected.txt b/test/069-field-type/expected-stderr.txt
similarity index 100%
copy from test/477-checker-bound-type/expected.txt
copy to test/069-field-type/expected-stderr.txt
diff --git a/test/069-field-type/expected.txt b/test/069-field-type/expected-stdout.txt
similarity index 100%
rename from test/069-field-type/expected.txt
rename to test/069-field-type/expected-stdout.txt
diff --git a/test/070-nio-buffer/Android.bp b/test/070-nio-buffer/Android.bp
new file mode 100644
index 0000000..cc2b763
--- /dev/null
+++ b/test/070-nio-buffer/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `070-nio-buffer`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-070-nio-buffer",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-070-nio-buffer-expected-stdout",
+        ":art-run-test-070-nio-buffer-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-070-nio-buffer-expected-stdout",
+    out: ["art-run-test-070-nio-buffer-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-070-nio-buffer-expected-stderr",
+    out: ["art-run-test-070-nio-buffer-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/507-referrer/expected.txt b/test/070-nio-buffer/expected-stderr.txt
similarity index 100%
copy from test/507-referrer/expected.txt
copy to test/070-nio-buffer/expected-stderr.txt
diff --git a/test/070-nio-buffer/expected.txt b/test/070-nio-buffer/expected-stdout.txt
similarity index 100%
rename from test/070-nio-buffer/expected.txt
rename to test/070-nio-buffer/expected-stdout.txt
diff --git a/test/082-inline-execute/expected.txt b/test/071-dexfile-get-static-size/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/071-dexfile-get-static-size/expected-stderr.txt
diff --git a/test/071-dexfile-get-static-size/expected.txt b/test/071-dexfile-get-static-size/expected-stdout.txt
similarity index 100%
rename from test/071-dexfile-get-static-size/expected.txt
rename to test/071-dexfile-get-static-size/expected-stdout.txt
diff --git a/test/001-Main/expected.txt b/test/071-dexfile-map-clean/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/071-dexfile-map-clean/expected-stderr.txt
diff --git a/test/071-dexfile-map-clean/expected.txt b/test/071-dexfile-map-clean/expected-stdout.txt
similarity index 100%
rename from test/071-dexfile-map-clean/expected.txt
rename to test/071-dexfile-map-clean/expected-stdout.txt
diff --git a/test/438-volatile/expected.txt b/test/071-dexfile/expected-stderr.txt
similarity index 100%
copy from test/438-volatile/expected.txt
copy to test/071-dexfile/expected-stderr.txt
diff --git a/test/071-dexfile/expected.txt b/test/071-dexfile/expected-stdout.txt
similarity index 100%
rename from test/071-dexfile/expected.txt
rename to test/071-dexfile/expected-stdout.txt
diff --git a/test/072-precise-gc/Android.bp b/test/072-precise-gc/Android.bp
new file mode 100644
index 0000000..4ea8c2b
--- /dev/null
+++ b/test/072-precise-gc/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `072-precise-gc`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-072-precise-gc",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-072-precise-gc-expected-stdout",
+        ":art-run-test-072-precise-gc-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-072-precise-gc-expected-stdout",
+    out: ["art-run-test-072-precise-gc-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-072-precise-gc-expected-stderr",
+    out: ["art-run-test-072-precise-gc-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/072-precise-gc/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/072-precise-gc/expected-stderr.txt
diff --git a/test/072-precise-gc/expected.txt b/test/072-precise-gc/expected-stdout.txt
similarity index 100%
rename from test/072-precise-gc/expected.txt
rename to test/072-precise-gc/expected-stdout.txt
diff --git a/test/072-reachability-fence/Android.bp b/test/072-reachability-fence/Android.bp
new file mode 100644
index 0000000..f079377
--- /dev/null
+++ b/test/072-reachability-fence/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `072-reachability-fence`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-072-reachability-fence",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-072-reachability-fence-expected-stdout",
+        ":art-run-test-072-reachability-fence-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-072-reachability-fence-expected-stdout",
+    out: ["art-run-test-072-reachability-fence-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-072-reachability-fence-expected-stderr",
+    out: ["art-run-test-072-reachability-fence-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/435-new-instance/expected.txt b/test/072-reachability-fence/expected-stderr.txt
similarity index 100%
copy from test/435-new-instance/expected.txt
copy to test/072-reachability-fence/expected-stderr.txt
diff --git a/test/072-reachability-fence/expected.txt b/test/072-reachability-fence/expected-stdout.txt
similarity index 100%
rename from test/072-reachability-fence/expected.txt
rename to test/072-reachability-fence/expected-stdout.txt
diff --git a/test/072-reachability-fence/src/Main.java b/test/072-reachability-fence/src/Main.java
index ac1e131..900ee34 100644
--- a/test/072-reachability-fence/src/Main.java
+++ b/test/072-reachability-fence/src/Main.java
@@ -31,7 +31,7 @@
         wrefs[2] = new WeakReference(str2);
         wrefs[3] = new WeakReference(str3);
         wrefs[4] = new WeakReference(str4);
-        // Clear a couple as a sanity check.
+        // Clear a couple as a soundness check.
         str1 = null;
         str2 = null;
         // str<n> dead here; in the future we will possibly reuse the registers.
diff --git a/test/001-Main/expected.txt b/test/073-mismatched-field/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/073-mismatched-field/expected-stderr.txt
diff --git a/test/073-mismatched-field/expected.txt b/test/073-mismatched-field/expected-stdout.txt
similarity index 100%
rename from test/073-mismatched-field/expected.txt
rename to test/073-mismatched-field/expected-stdout.txt
diff --git a/test/074-gc-thrash/Android.bp b/test/074-gc-thrash/Android.bp
new file mode 100644
index 0000000..b6b99db
--- /dev/null
+++ b/test/074-gc-thrash/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `074-gc-thrash`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-074-gc-thrash",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-074-gc-thrash-expected-stdout",
+        ":art-run-test-074-gc-thrash-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-074-gc-thrash-expected-stdout",
+    out: ["art-run-test-074-gc-thrash-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-074-gc-thrash-expected-stderr",
+    out: ["art-run-test-074-gc-thrash-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/074-gc-thrash/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/074-gc-thrash/expected-stderr.txt
diff --git a/test/074-gc-thrash/expected.txt b/test/074-gc-thrash/expected-stdout.txt
similarity index 100%
rename from test/074-gc-thrash/expected.txt
rename to test/074-gc-thrash/expected-stdout.txt
diff --git a/test/074-gc-thrash/src/Main.java b/test/074-gc-thrash/src/Main.java
index 5165df7..828184e 100644
--- a/test/074-gc-thrash/src/Main.java
+++ b/test/074-gc-thrash/src/Main.java
@@ -195,7 +195,7 @@
  * Allocates useless objects in recursive calls.
  */
 class Deep extends Thread {
-    private static final int MAX_DEPTH = 61;
+    private static final int MAX_DEPTH = 50;
 
     private static String strong[] = new String[MAX_DEPTH];
     private static WeakReference weak[] = new WeakReference[MAX_DEPTH];
diff --git a/test/587-inline-class-error/expected.txt b/test/075-verification-error/expected-stderr.txt
similarity index 100%
copy from test/587-inline-class-error/expected.txt
copy to test/075-verification-error/expected-stderr.txt
diff --git a/test/075-verification-error/expected.txt b/test/075-verification-error/expected-stdout.txt
similarity index 100%
rename from test/075-verification-error/expected.txt
rename to test/075-verification-error/expected-stdout.txt
diff --git a/test/076-boolean-put/Android.bp b/test/076-boolean-put/Android.bp
new file mode 100644
index 0000000..5fa8baf
--- /dev/null
+++ b/test/076-boolean-put/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `076-boolean-put`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-076-boolean-put",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-076-boolean-put-expected-stdout",
+        ":art-run-test-076-boolean-put-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-076-boolean-put-expected-stdout",
+    out: ["art-run-test-076-boolean-put-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-076-boolean-put-expected-stderr",
+    out: ["art-run-test-076-boolean-put-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/076-boolean-put/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/076-boolean-put/expected-stderr.txt
diff --git a/test/076-boolean-put/expected.txt b/test/076-boolean-put/expected-stdout.txt
similarity index 100%
rename from test/076-boolean-put/expected.txt
rename to test/076-boolean-put/expected-stdout.txt
diff --git a/test/082-inline-execute/expected.txt b/test/077-method-override/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/077-method-override/expected-stderr.txt
diff --git a/test/077-method-override/expected.txt b/test/077-method-override/expected-stdout.txt
similarity index 100%
rename from test/077-method-override/expected.txt
rename to test/077-method-override/expected-stdout.txt
diff --git a/test/078-polymorphic-virtual/Android.bp b/test/078-polymorphic-virtual/Android.bp
new file mode 100644
index 0000000..e71ab37
--- /dev/null
+++ b/test/078-polymorphic-virtual/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `078-polymorphic-virtual`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-078-polymorphic-virtual",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-078-polymorphic-virtual-expected-stdout",
+        ":art-run-test-078-polymorphic-virtual-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-078-polymorphic-virtual-expected-stdout",
+    out: ["art-run-test-078-polymorphic-virtual-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-078-polymorphic-virtual-expected-stderr",
+    out: ["art-run-test-078-polymorphic-virtual-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/535-regression-const-val/expected.txt b/test/078-polymorphic-virtual/expected-stderr.txt
similarity index 100%
copy from test/535-regression-const-val/expected.txt
copy to test/078-polymorphic-virtual/expected-stderr.txt
diff --git a/test/078-polymorphic-virtual/expected.txt b/test/078-polymorphic-virtual/expected-stdout.txt
similarity index 100%
rename from test/078-polymorphic-virtual/expected.txt
rename to test/078-polymorphic-virtual/expected-stdout.txt
diff --git a/test/079-phantom/Android.bp b/test/079-phantom/Android.bp
new file mode 100644
index 0000000..11c978b
--- /dev/null
+++ b/test/079-phantom/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `079-phantom`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-079-phantom",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-079-phantom-expected-stdout",
+        ":art-run-test-079-phantom-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-079-phantom-expected-stdout",
+    out: ["art-run-test-079-phantom-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-079-phantom-expected-stderr",
+    out: ["art-run-test-079-phantom-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/079-phantom/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/079-phantom/expected-stderr.txt
diff --git a/test/079-phantom/expected.txt b/test/079-phantom/expected-stdout.txt
similarity index 100%
rename from test/079-phantom/expected.txt
rename to test/079-phantom/expected-stdout.txt
diff --git a/test/080-oom-fragmentation/Android.bp b/test/080-oom-fragmentation/Android.bp
new file mode 100644
index 0000000..c81f798
--- /dev/null
+++ b/test/080-oom-fragmentation/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `080-oom-fragmentation`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-080-oom-fragmentation",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-080-oom-fragmentation-expected-stdout",
+        ":art-run-test-080-oom-fragmentation-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-080-oom-fragmentation-expected-stdout",
+    out: ["art-run-test-080-oom-fragmentation-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-080-oom-fragmentation-expected-stderr",
+    out: ["art-run-test-080-oom-fragmentation-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-fragmentation/expected.txt b/test/080-oom-fragmentation/expected-stderr.txt
similarity index 100%
rename from test/080-oom-fragmentation/expected.txt
rename to test/080-oom-fragmentation/expected-stderr.txt
diff --git a/test/080-oom-fragmentation/expected.txt b/test/080-oom-fragmentation/expected-stdout.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/080-oom-fragmentation/expected-stdout.txt
diff --git a/test/080-oom-throw-with-finalizer/Android.bp b/test/080-oom-throw-with-finalizer/Android.bp
new file mode 100644
index 0000000..7f7668e
--- /dev/null
+++ b/test/080-oom-throw-with-finalizer/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `080-oom-throw-with-finalizer`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-080-oom-throw-with-finalizer",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-080-oom-throw-with-finalizer-expected-stdout",
+        ":art-run-test-080-oom-throw-with-finalizer-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-080-oom-throw-with-finalizer-expected-stdout",
+    out: ["art-run-test-080-oom-throw-with-finalizer-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-080-oom-throw-with-finalizer-expected-stderr",
+    out: ["art-run-test-080-oom-throw-with-finalizer-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-throw-with-finalizer/expected.txt b/test/080-oom-throw-with-finalizer/expected-stderr.txt
similarity index 100%
rename from test/080-oom-throw-with-finalizer/expected.txt
rename to test/080-oom-throw-with-finalizer/expected-stderr.txt
diff --git a/test/080-oom-throw-with-finalizer/expected.txt b/test/080-oom-throw-with-finalizer/expected-stdout.txt
similarity index 100%
copy from test/080-oom-throw-with-finalizer/expected.txt
copy to test/080-oom-throw-with-finalizer/expected-stdout.txt
diff --git a/test/080-oom-throw/Android.bp b/test/080-oom-throw/Android.bp
new file mode 100644
index 0000000..840a49c
--- /dev/null
+++ b/test/080-oom-throw/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `080-oom-throw`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-080-oom-throw",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-080-oom-throw-expected-stdout",
+        ":art-run-test-080-oom-throw-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-080-oom-throw-expected-stdout",
+    out: ["art-run-test-080-oom-throw-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-080-oom-throw-expected-stderr",
+    out: ["art-run-test-080-oom-throw-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-throw-with-finalizer/expected.txt b/test/080-oom-throw/expected-stderr.txt
similarity index 100%
copy from test/080-oom-throw-with-finalizer/expected.txt
copy to test/080-oom-throw/expected-stderr.txt
diff --git a/test/080-oom-throw/expected.txt b/test/080-oom-throw/expected-stdout.txt
similarity index 100%
rename from test/080-oom-throw/expected.txt
rename to test/080-oom-throw/expected-stdout.txt
diff --git a/test/080-oom-throw/src/Main.java b/test/080-oom-throw/src/Main.java
index 3d5d062..cd36eff 100644
--- a/test/080-oom-throw/src/Main.java
+++ b/test/080-oom-throw/src/Main.java
@@ -53,9 +53,28 @@
         }
     }
 
+    private static int exhaustJavaHeap(Object[] data, int index, int size) {
+        Runtime.getRuntime().gc();
+        while (index != data.length && size != 0) {
+            try {
+                data[index] = new byte[size];
+                ++index;
+            } catch (OutOfMemoryError oome) {
+                size /= 2;
+            }
+        }
+        return index;
+    }
+
     public static Object eatAllMemory() {
         Object[] result = null;
         int size = 1000000;
+        // Make sure that there is no reclaimable memory in the heap. Otherwise we may throw
+        // OOME to prevent GC thrashing, even if later allocations may succeed.
+        Runtime.getRuntime().gc();
+        System.runFinalization();
+        // NOTE: There is a GC invocation in exhaustJavaHeap. So we don't need one here.
+
         while (result == null && size != 0) {
             try {
                 result = new Object[size];
@@ -65,14 +84,10 @@
         }
         if (result != null) {
             int index = 0;
-            while (index != result.length && size != 0) {
-                try {
-                    result[index] = new byte[size];
-                    ++index;
-                } catch (OutOfMemoryError oome) {
-                    size /= 2;
-                }
-            }
+            // Repeat to ensure there is no space left on the heap.
+            index = exhaustJavaHeap(result, index, size);
+            index = exhaustJavaHeap(result, index, /*size*/ 4);
+            index = exhaustJavaHeap(result, index, /*size*/ 4);
         }
         return result;
     }
diff --git a/test/081-hot-exceptions/Android.bp b/test/081-hot-exceptions/Android.bp
new file mode 100644
index 0000000..4d4bb04
--- /dev/null
+++ b/test/081-hot-exceptions/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `081-hot-exceptions`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-081-hot-exceptions",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-081-hot-exceptions-expected-stdout",
+        ":art-run-test-081-hot-exceptions-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-081-hot-exceptions-expected-stdout",
+    out: ["art-run-test-081-hot-exceptions-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-081-hot-exceptions-expected-stderr",
+    out: ["art-run-test-081-hot-exceptions-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/082-inline-execute/expected.txt b/test/081-hot-exceptions/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/081-hot-exceptions/expected-stderr.txt
diff --git a/test/081-hot-exceptions/expected.txt b/test/081-hot-exceptions/expected-stdout.txt
similarity index 100%
rename from test/081-hot-exceptions/expected.txt
rename to test/081-hot-exceptions/expected-stdout.txt
diff --git a/test/082-inline-execute/Android.bp b/test/082-inline-execute/Android.bp
new file mode 100644
index 0000000..492bbff
--- /dev/null
+++ b/test/082-inline-execute/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `082-inline-execute`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-082-inline-execute",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-082-inline-execute-expected-stdout",
+        ":art-run-test-082-inline-execute-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-082-inline-execute-expected-stdout",
+    out: ["art-run-test-082-inline-execute-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-082-inline-execute-expected-stderr",
+    out: ["art-run-test-082-inline-execute-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/082-inline-execute/expected.txt b/test/082-inline-execute/expected-stderr.txt
similarity index 100%
rename from test/082-inline-execute/expected.txt
rename to test/082-inline-execute/expected-stderr.txt
diff --git a/test/082-inline-execute/expected.txt b/test/082-inline-execute/expected-stdout.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/082-inline-execute/expected-stdout.txt
diff --git a/test/082-inline-execute/src/Main.java b/test/082-inline-execute/src/Main.java
index 072f0e6..f4a234b 100644
--- a/test/082-inline-execute/src/Main.java
+++ b/test/082-inline-execute/src/Main.java
@@ -44,6 +44,7 @@
     test_Math_isNaN_F();
     test_Math_isInfinite_D();
     test_Math_isInfinite_F();
+    test_Math_multiplyHigh();
     test_Short_reverseBytes();
     test_Integer_reverseBytes();
     test_Long_reverseBytes();
@@ -82,6 +83,8 @@
     test_Memory_pokeShort();
     test_Memory_pokeInt();
     test_Memory_pokeLong();
+    test_Integer_divideUnsigned();
+    test_Long_divideUnsigned();
     test_Integer_numberOfTrailingZeros();
     test_Long_numberOfTrailingZeros();
     test_Integer_rotateRight();
@@ -976,6 +979,12 @@
     Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x80000001)));
   }
 
+  public static void test_Math_multiplyHigh() {
+    Math.multiplyHigh(2L, 3L);
+    Assert.assertEquals(Math.multiplyHigh(2L, 3L), 0L);
+    Assert.assertEquals(Math.multiplyHigh(Long.MAX_VALUE, Long.MAX_VALUE), 4611686018427387903L);
+  }
+
   public static void test_StrictMath_abs_I() {
     StrictMath.abs(-1);
     Assert.assertEquals(StrictMath.abs(0), 0);
@@ -1376,6 +1385,65 @@
     return 0;
   }
 
+  public static void test_Integer_divideUnsigned() {
+    Assert.assertEquals(Integer.divideUnsigned(100, 10), 10);
+    Assert.assertEquals(Integer.divideUnsigned(100, 1), 100);
+    Assert.assertEquals(Integer.divideUnsigned(1024, 128), 8);
+    Assert.assertEquals(Integer.divideUnsigned(12345678, 264), 46763);
+    Assert.assertEquals(Integer.divideUnsigned(13, 5), 2);
+    Assert.assertEquals(Integer.divideUnsigned(-2, 2), Integer.MAX_VALUE);
+    Assert.assertEquals(Integer.divideUnsigned(-1, 2), Integer.MAX_VALUE);
+    Assert.assertEquals(Integer.divideUnsigned(100000, -1), 0);
+    Assert.assertEquals(Integer.divideUnsigned(Integer.MAX_VALUE, -1), 0);
+    Assert.assertEquals(Integer.divideUnsigned(-2, -1), 0);
+    Assert.assertEquals(Integer.divideUnsigned(-1, -2), 1);
+    Assert.assertEquals(Integer.divideUnsigned(-173448, 13), 330368757);
+    Assert.assertEquals(Integer.divideUnsigned(Integer.MIN_VALUE, 2), (1 << 30));
+    Assert.assertEquals(Integer.divideUnsigned(-1, Integer.MIN_VALUE), 1);
+    Assert.assertEquals(Integer.divideUnsigned(Integer.MAX_VALUE, Integer.MIN_VALUE), 0);
+    Assert.assertEquals(Integer.divideUnsigned(Integer.MIN_VALUE, Integer.MAX_VALUE), 1);
+
+    try {
+      Integer.divideUnsigned(1, 0);
+      Assert.fail("Unreachable");
+    } catch (ArithmeticException expected) {
+    }
+  }
+
+
+  private static final long BIG_LONG_VALUE = 739287620162442240L;
+
+  public static void test_Long_divideUnsigned() {
+    Assert.assertEquals(Long.divideUnsigned(100L, 10L), 10L);
+    Assert.assertEquals(Long.divideUnsigned(100L, 1L), 100L);
+    Assert.assertEquals(Long.divideUnsigned(1024L, 128L), 8L);
+    Assert.assertEquals(Long.divideUnsigned(12345678L, 264L), 46763L);
+    Assert.assertEquals(Long.divideUnsigned(13L, 5L), 2L);
+    Assert.assertEquals(Long.divideUnsigned(-2L, 2L), Long.MAX_VALUE);
+    Assert.assertEquals(Long.divideUnsigned(-1L, 2L), Long.MAX_VALUE);
+    Assert.assertEquals(Long.divideUnsigned(100000L, -1L), 0L);
+    Assert.assertEquals(Long.divideUnsigned(Long.MAX_VALUE, -1L), 0L);
+    Assert.assertEquals(Long.divideUnsigned(-2L, -1L), 0L);
+    Assert.assertEquals(Long.divideUnsigned(-1L, -2L), 1L);
+    Assert.assertEquals(Long.divideUnsigned(-173448L, 13L), 1418980313362259859L);
+    Assert.assertEquals(Long.divideUnsigned(Long.MIN_VALUE, 2L), (1L << 62));
+    Assert.assertEquals(Long.divideUnsigned(-1L, Long.MIN_VALUE), 1L);
+    Assert.assertEquals(Long.divideUnsigned(Long.MAX_VALUE, Long.MIN_VALUE), 0L);
+    Assert.assertEquals(Long.divideUnsigned(Long.MIN_VALUE, Long.MAX_VALUE), 1L);
+    Assert.assertEquals(Long.divideUnsigned(Long.MAX_VALUE, 1L), Long.MAX_VALUE);
+    Assert.assertEquals(Long.divideUnsigned(Long.MIN_VALUE, 1L), Long.MIN_VALUE);
+    Assert.assertEquals(Long.divideUnsigned(BIG_LONG_VALUE, BIG_LONG_VALUE), 1L);
+    Assert.assertEquals(Long.divideUnsigned(BIG_LONG_VALUE, 1L), BIG_LONG_VALUE);
+    Assert.assertEquals(Long.divideUnsigned(BIG_LONG_VALUE, 1024L), 721960566564885L);
+    Assert.assertEquals(Long.divideUnsigned(BIG_LONG_VALUE, 0x1FFFFFFFFL), 86064406L);
+
+    try {
+      Long.divideUnsigned(1L, 0L);
+      Assert.fail("Unreachable");
+    } catch (ArithmeticException expected) {
+    }
+  }
+
   public static void test_Integer_numberOfLeadingZeros() {
     Assert.assertEquals(Integer.numberOfLeadingZeros(0), Integer.SIZE);
     Assert.assertEquals(Integer.numberOfLeadingZeros(1), Integer.SIZE - 1);
diff --git a/test/083-compiler-regressions/Android.bp b/test/083-compiler-regressions/Android.bp
new file mode 100644
index 0000000..cd98573
--- /dev/null
+++ b/test/083-compiler-regressions/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `083-compiler-regressions`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-083-compiler-regressions",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-083-compiler-regressions-expected-stdout",
+        ":art-run-test-083-compiler-regressions-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-083-compiler-regressions-expected-stdout",
+    out: ["art-run-test-083-compiler-regressions-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-083-compiler-regressions-expected-stderr",
+    out: ["art-run-test-083-compiler-regressions-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-fragmentation/expected.txt b/test/083-compiler-regressions/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/083-compiler-regressions/expected-stderr.txt
diff --git a/test/083-compiler-regressions/expected.txt b/test/083-compiler-regressions/expected-stdout.txt
similarity index 100%
rename from test/083-compiler-regressions/expected.txt
rename to test/083-compiler-regressions/expected-stdout.txt
diff --git a/test/083-compiler-regressions/src/Main.java b/test/083-compiler-regressions/src/Main.java
index 285c360..9de3f5a 100644
--- a/test/083-compiler-regressions/src/Main.java
+++ b/test/083-compiler-regressions/src/Main.java
@@ -277,13 +277,13 @@
         sum += foo.getBar0();
         foo.setBar5ReturnBarArg(1,2,3,4,sum);
         sum += foo.getBar0();
-        foo.setBar2ReturnDummyArg1(1,sum);
+        foo.setBar2ReturnArg1(1,sum);
         sum += foo.getBar0();
-        foo.setBar3ReturnDummyArg2(1,2,sum);
+        foo.setBar3ReturnArg2(1,2,sum);
         sum += foo.getBar0();
-        foo.setBar4ReturnDummyArg3(1,2,3,sum);
+        foo.setBar4ReturnArg3(1,2,3,sum);
         sum += foo.getBar0();
-        foo.setBar5ReturnDummyArg4(1,2,3,4,sum);
+        foo.setBar5ReturnArg4(1,2,3,4,sum);
         sum += foo.getBar0();
         Foo nullFoo = Foo.getNullFoo();
         try {
@@ -337,22 +337,22 @@
             sum += 10 * 404;
         }
         try {
-            nullFoo.setBar2ReturnDummyArg1(1, sum);
+            nullFoo.setBar2ReturnArg1(1, sum);
         } catch(NullPointerException npe) {
             sum += 11 * 404;
         }
         try {
-            nullFoo.setBar3ReturnDummyArg2(1, 2, sum);
+            nullFoo.setBar3ReturnArg2(1, 2, sum);
         } catch(NullPointerException npe) {
             sum += 12 * 404;
         }
         try {
-            nullFoo.setBar4ReturnDummyArg3(1, 2, 3, sum);
+            nullFoo.setBar4ReturnArg3(1, 2, 3, sum);
         } catch(NullPointerException npe) {
             sum += 13 * 404;
         }
         try {
-            nullFoo.setBar5ReturnDummyArg4(1, 2, 3, 4, sum);
+            nullFoo.setBar5ReturnArg4(1, 2, 3, 4, sum);
         } catch(NullPointerException npe) {
             sum += 14 * 404;
         }
@@ -369,7 +369,7 @@
     static void setterTestWithReturnArgUseReturn() {
         Foo foo = new Foo();
         int sum = foo.getBar0();
-        int sumDummy = 0;
+        int sumTally = 0;
         sum += foo.getBar0();
         Foo foo2 = foo.setBar1ReturnThis(sum);
         sum += foo2.getBar0();
@@ -391,13 +391,13 @@
         sum += foo.getBar0();
         sum += foo.setBar5ReturnBarArg(1,2,3,4,sum);
         sum += foo.getBar0();
-        sumDummy += foo.setBar2ReturnDummyArg1(1,sum);
+        sumTally += foo.setBar2ReturnArg1(1,sum);
         sum += foo.getBar0();
-        sumDummy += foo.setBar3ReturnDummyArg2(1,2,sum);
+        sumTally += foo.setBar3ReturnArg2(1,2,sum);
         sum += foo.getBar0();
-        sumDummy += foo.setBar4ReturnDummyArg3(1,2,3,sum);
+        sumTally += foo.setBar4ReturnArg3(1,2,3,sum);
         sum += foo.getBar0();
-        sumDummy += foo.setBar5ReturnDummyArg4(1,2,3,4,sum);
+        sumTally += foo.setBar5ReturnArg4(1,2,3,4,sum);
         sum += foo.getBar0();
         Foo nullFoo = Foo.getNullFoo();
         try {
@@ -451,34 +451,34 @@
             sum += 10 * 404;
         }
         try {
-            sumDummy += nullFoo.setBar2ReturnDummyArg1(1, sum);
+            sumTally += nullFoo.setBar2ReturnArg1(1, sum);
         } catch(NullPointerException npe) {
             sum += 11 * 404;
         }
         try {
-            sumDummy += nullFoo.setBar3ReturnDummyArg2(1, 2, sum);
+            sumTally += nullFoo.setBar3ReturnArg2(1, 2, sum);
         } catch(NullPointerException npe) {
             sum += 12 * 404;
         }
         try {
-            sumDummy += nullFoo.setBar4ReturnDummyArg3(1, 2, 3, sum);
+            sumTally += nullFoo.setBar4ReturnArg3(1, 2, 3, sum);
         } catch(NullPointerException npe) {
             sum += 13 * 404;
         }
         try {
-            sumDummy += nullFoo.setBar5ReturnDummyArg4(1, 2, 3, 4, sum);
+            sumTally += nullFoo.setBar5ReturnArg4(1, 2, 3, 4, sum);
         } catch(NullPointerException npe) {
             sum += 14 * 404;
         }
         int expected = (1234 << 10) * 3 * 3 * 3 * 3 * 3 + 404 * (15 * 14 / 2);
-        int expectedDummy = 5 * 4 / 2;
-        if (sum == expected && sumDummy == expectedDummy) {
+        int expectedTally = 5 * 4 / 2;
+        if (sum == expected && sumTally == expectedTally) {
             System.out.println("setterTestWithReturnArgUseReturn passes");
         }
         else {
             System.out.println("setterTestWithReturnArgUseReturn fails: " + sum +
-                               " (expecting " + expected + "), sumDummy = " + sumDummy +
-                               "(expecting " + expectedDummy + ")");
+                               " (expecting " + expected + "), sumTally = " + sumTally +
+                               "(expecting " + expectedTally + ")");
         }
     }
 
@@ -514,21 +514,21 @@
         sum += foo.wideGetBar0();
         foo.wideSetBar5iReturnBarArg(1,2,3,4,sum);
         sum += foo.wideGetBar0();
-        foo.wideSetBar2ReturnDummyArg1(1,sum);
+        foo.wideSetBar2ReturnArg1(1,sum);
         sum += foo.wideGetBar0();
-        foo.wideSetBar3ReturnDummyArg2(1,2,sum);
+        foo.wideSetBar3ReturnArg2(1,2,sum);
         sum += foo.wideGetBar0();
-        foo.wideSetBar4ReturnDummyArg3(1,2,3,sum);
+        foo.wideSetBar4ReturnArg3(1,2,3,sum);
         sum += foo.wideGetBar0();
-        foo.wideSetBar5ReturnDummyArg4(1,2,3,4,sum);
+        foo.wideSetBar5ReturnArg4(1,2,3,4,sum);
         sum += foo.wideGetBar0();
-        foo.wideSetBar2iReturnDummyArg1(1,sum);
+        foo.wideSetBar2iReturnArg1(1,sum);
         sum += foo.wideGetBar0();
-        foo.wideSetBar3iReturnDummyArg2(1,2,sum);
+        foo.wideSetBar3iReturnArg2(1,2,sum);
         sum += foo.wideGetBar0();
-        foo.wideSetBar4iReturnDummyArg3(1,2,3,sum);
+        foo.wideSetBar4iReturnArg3(1,2,3,sum);
         sum += foo.wideGetBar0();
-        foo.wideSetBar5iReturnDummyArg4(1,2,3,4,sum);
+        foo.wideSetBar5iReturnArg4(1,2,3,4,sum);
         sum += foo.wideGetBar0();
         Foo nullFoo = Foo.getNullFoo();
         try {
@@ -602,42 +602,42 @@
             sum += 14 * 404;
         }
         try {
-            nullFoo.wideSetBar2ReturnDummyArg1(1, sum);
+            nullFoo.wideSetBar2ReturnArg1(1, sum);
         } catch(NullPointerException npe) {
             sum += 15 * 404;
         }
         try {
-            nullFoo.wideSetBar3ReturnDummyArg2(1, 2, sum);
+            nullFoo.wideSetBar3ReturnArg2(1, 2, sum);
         } catch(NullPointerException npe) {
             sum += 16 * 404;
         }
         try {
-            nullFoo.wideSetBar4ReturnDummyArg3(1, 2, 3, sum);
+            nullFoo.wideSetBar4ReturnArg3(1, 2, 3, sum);
         } catch(NullPointerException npe) {
             sum += 17 * 404;
         }
         try {
-            nullFoo.wideSetBar5ReturnDummyArg4(1, 2, 3, 4, sum);
+            nullFoo.wideSetBar5ReturnArg4(1, 2, 3, 4, sum);
         } catch(NullPointerException npe) {
             sum += 18 * 404;
         }
         try {
-            nullFoo.wideSetBar2iReturnDummyArg1(1, sum);
+            nullFoo.wideSetBar2iReturnArg1(1, sum);
         } catch(NullPointerException npe) {
             sum += 19 * 404;
         }
         try {
-            nullFoo.wideSetBar3iReturnDummyArg2(1, 2, sum);
+            nullFoo.wideSetBar3iReturnArg2(1, 2, sum);
         } catch(NullPointerException npe) {
             sum += 20 * 404;
         }
         try {
-            nullFoo.wideSetBar4iReturnDummyArg3(1, 2, 3, sum);
+            nullFoo.wideSetBar4iReturnArg3(1, 2, 3, sum);
         } catch(NullPointerException npe) {
             sum += 21 * 404;
         }
         try {
-            nullFoo.wideSetBar5iReturnDummyArg4(1, 2, 3, 4, sum);
+            nullFoo.wideSetBar5iReturnArg4(1, 2, 3, 4, sum);
         } catch(NullPointerException npe) {
             sum += 22 * 404;
         }
@@ -654,7 +654,7 @@
     static void wideSetterTestWithReturnArgUseReturn() {
         Foo foo = new Foo();
         long sum = foo.wideGetBar0();
-        long sumDummy = 0;
+        long sumTally = 0;
         sum += foo.wideGetBar0();
         Foo foo2 = foo.wideSetBar1ReturnThis(sum);
         sum += foo2.wideGetBar0();
@@ -684,21 +684,21 @@
         sum += foo.wideGetBar0();
         sum += foo.wideSetBar5iReturnBarArg(1,2,3,4,sum);
         sum += foo.wideGetBar0();
-        sumDummy += foo.wideSetBar2ReturnDummyArg1(1,sum);
+        sumTally += foo.wideSetBar2ReturnArg1(1,sum);
         sum += foo.wideGetBar0();
-        sumDummy += foo.wideSetBar3ReturnDummyArg2(1,2,sum);
+        sumTally += foo.wideSetBar3ReturnArg2(1,2,sum);
         sum += foo.wideGetBar0();
-        sumDummy += foo.wideSetBar4ReturnDummyArg3(1,2,3,sum);
+        sumTally += foo.wideSetBar4ReturnArg3(1,2,3,sum);
         sum += foo.wideGetBar0();
-        sumDummy += foo.wideSetBar5ReturnDummyArg4(1,2,3,4,sum);
+        sumTally += foo.wideSetBar5ReturnArg4(1,2,3,4,sum);
         sum += foo.wideGetBar0();
-        sumDummy += foo.wideSetBar2iReturnDummyArg1(1,sum);
+        sumTally += foo.wideSetBar2iReturnArg1(1,sum);
         sum += foo.wideGetBar0();
-        sumDummy += foo.wideSetBar3iReturnDummyArg2(1,2,sum);
+        sumTally += foo.wideSetBar3iReturnArg2(1,2,sum);
         sum += foo.wideGetBar0();
-        sumDummy += foo.wideSetBar4iReturnDummyArg3(1,2,3,sum);
+        sumTally += foo.wideSetBar4iReturnArg3(1,2,3,sum);
         sum += foo.wideGetBar0();
-        sumDummy += foo.wideSetBar5iReturnDummyArg4(1,2,3,4,sum);
+        sumTally += foo.wideSetBar5iReturnArg4(1,2,3,4,sum);
         sum += foo.wideGetBar0();
         Foo nullFoo = Foo.getNullFoo();
         try {
@@ -772,54 +772,54 @@
             sum += 14 * 404;
         }
         try {
-            sumDummy += nullFoo.wideSetBar2ReturnDummyArg1(1, sum);
+            sumTally += nullFoo.wideSetBar2ReturnArg1(1, sum);
         } catch(NullPointerException npe) {
             sum += 15 * 404;
         }
         try {
-            sumDummy += nullFoo.wideSetBar3ReturnDummyArg2(1, 2, sum);
+            sumTally += nullFoo.wideSetBar3ReturnArg2(1, 2, sum);
         } catch(NullPointerException npe) {
             sum += 16 * 404;
         }
         try {
-            sumDummy += nullFoo.wideSetBar4ReturnDummyArg3(1, 2, 3, sum);
+            sumTally += nullFoo.wideSetBar4ReturnArg3(1, 2, 3, sum);
         } catch(NullPointerException npe) {
             sum += 17 * 404;
         }
         try {
-            sumDummy += nullFoo.wideSetBar5ReturnDummyArg4(1, 2, 3, 4, sum);
+            sumTally += nullFoo.wideSetBar5ReturnArg4(1, 2, 3, 4, sum);
         } catch(NullPointerException npe) {
             sum += 18 * 404;
         }
         try {
-            sumDummy += nullFoo.wideSetBar2iReturnDummyArg1(1, sum);
+            sumTally += nullFoo.wideSetBar2iReturnArg1(1, sum);
         } catch(NullPointerException npe) {
             sum += 19 * 404;
         }
         try {
-            sumDummy += nullFoo.wideSetBar3iReturnDummyArg2(1, 2, sum);
+            sumTally += nullFoo.wideSetBar3iReturnArg2(1, 2, sum);
         } catch(NullPointerException npe) {
             sum += 20 * 404;
         }
         try {
-            sumDummy += nullFoo.wideSetBar4iReturnDummyArg3(1, 2, 3, sum);
+            sumTally += nullFoo.wideSetBar4iReturnArg3(1, 2, 3, sum);
         } catch(NullPointerException npe) {
             sum += 21 * 404;
         }
         try {
-            sumDummy += nullFoo.wideSetBar5iReturnDummyArg4(1, 2, 3, 4, sum);
+            sumTally += nullFoo.wideSetBar5iReturnArg4(1, 2, 3, 4, sum);
         } catch(NullPointerException npe) {
             sum += 22 * 404;
         }
         long expected = (1234L << 14) * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3  + 404 * (23 * 22 / 2);
-        long expectedDummy = 2 * (5 * 4 / 2);
-        if (sum == expected && sumDummy == expectedDummy) {
+        long expectedTally = 2 * (5 * 4 / 2);
+        if (sum == expected && sumTally == expectedTally) {
             System.out.println("wideSetterTestWithReturnArgUseReturn passes");
         }
         else {
             System.out.println("wideSetterTestWithReturnArgUseReturn fails: " + sum +
-                               " (expecting " + expected + "), sumDummy = " + sumDummy +
-                               "(expecting " + expectedDummy + ")");
+                               " (expecting " + expected + "), sumTally = " + sumTally +
+                               "(expecting " + expectedTally + ")");
         }
     }
 
@@ -9632,51 +9632,51 @@
         lbar = a5;
         return a5;
     }
-    public int setBar2ReturnDummyArg1(int a1, int a2) {
+    public int setBar2ReturnArg1(int a1, int a2) {
         bar = a2;
         return a1;
     }
-    public int setBar3ReturnDummyArg2(int a1, int a2, int a3) {
+    public int setBar3ReturnArg2(int a1, int a2, int a3) {
         bar = a3;
         return a2;
     }
-    public int setBar4ReturnDummyArg3(int a1, int a2, int a3, int a4) {
+    public int setBar4ReturnArg3(int a1, int a2, int a3, int a4) {
         bar = a4;
         return a3;
     }
-    public int setBar5ReturnDummyArg4(int a1, int a2, int a3, int a4, int a5) {
+    public int setBar5ReturnArg4(int a1, int a2, int a3, int a4, int a5) {
         bar = a5;
         return a4;
     }
-    public long wideSetBar2ReturnDummyArg1(long a1, long a2) {
+    public long wideSetBar2ReturnArg1(long a1, long a2) {
         lbar = a2;
         return a1;
     }
-    public long wideSetBar3ReturnDummyArg2(long a1, long a2, long a3) {
+    public long wideSetBar3ReturnArg2(long a1, long a2, long a3) {
         lbar = a3;
         return a2;
     }
-    public long wideSetBar4ReturnDummyArg3(long a1, long a2, long a3, long a4) {
+    public long wideSetBar4ReturnArg3(long a1, long a2, long a3, long a4) {
         lbar = a4;
         return a3;
     }
-    public long wideSetBar5ReturnDummyArg4(long a1, long a2, long a3, long a4, long a5) {
+    public long wideSetBar5ReturnArg4(long a1, long a2, long a3, long a4, long a5) {
         lbar = a5;
         return a4;
     }
-    public int wideSetBar2iReturnDummyArg1(int a1, long a2) {
+    public int wideSetBar2iReturnArg1(int a1, long a2) {
         lbar = a2;
         return a1;
     }
-    public int wideSetBar3iReturnDummyArg2(int a1, int a2, long a3) {
+    public int wideSetBar3iReturnArg2(int a1, int a2, long a3) {
         lbar = a3;
         return a2;
     }
-    public int wideSetBar4iReturnDummyArg3(int a1, int a2, int a3, long a4) {
+    public int wideSetBar4iReturnArg3(int a1, int a2, int a3, long a4) {
         lbar = a4;
         return a3;
     }
-    public int wideSetBar5iReturnDummyArg4(int a1, int a2, int a3, int a4, long a5) {
+    public int wideSetBar5iReturnArg4(int a1, int a2, int a3, int a4, long a5) {
         lbar = a5;
         return a4;
     }
diff --git a/test/084-class-init/Android.bp b/test/084-class-init/Android.bp
new file mode 100644
index 0000000..dd89fda
--- /dev/null
+++ b/test/084-class-init/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `084-class-init`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-084-class-init",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-084-class-init-expected-stdout",
+        ":art-run-test-084-class-init-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-084-class-init-expected-stdout",
+    out: ["art-run-test-084-class-init-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-084-class-init-expected-stderr",
+    out: ["art-run-test-084-class-init-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/529-long-split/expected.txt b/test/084-class-init/expected-stderr.txt
similarity index 100%
copy from test/529-long-split/expected.txt
copy to test/084-class-init/expected-stderr.txt
diff --git a/test/084-class-init/expected.txt b/test/084-class-init/expected-stdout.txt
similarity index 100%
rename from test/084-class-init/expected.txt
rename to test/084-class-init/expected-stdout.txt
diff --git a/test/519-bound-load-class/expected.txt b/test/085-old-style-inner-class/expected-stderr.txt
similarity index 100%
copy from test/519-bound-load-class/expected.txt
copy to test/085-old-style-inner-class/expected-stderr.txt
diff --git a/test/085-old-style-inner-class/expected.txt b/test/085-old-style-inner-class/expected-stdout.txt
similarity index 100%
rename from test/085-old-style-inner-class/expected.txt
rename to test/085-old-style-inner-class/expected-stdout.txt
diff --git a/test/086-null-super/Android.bp b/test/086-null-super/Android.bp
new file mode 100644
index 0000000..512000a
--- /dev/null
+++ b/test/086-null-super/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `086-null-super`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-086-null-super",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-086-null-super-expected-stdout",
+        ":art-run-test-086-null-super-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-086-null-super-expected-stdout",
+    out: ["art-run-test-086-null-super-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-086-null-super-expected-stderr",
+    out: ["art-run-test-086-null-super-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/551-invoke-super/expected.txt b/test/086-null-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/086-null-super/expected-stderr.txt
diff --git a/test/086-null-super/expected.txt b/test/086-null-super/expected-stdout.txt
similarity index 100%
rename from test/086-null-super/expected.txt
rename to test/086-null-super/expected-stdout.txt
diff --git a/test/087-gc-after-link/Android.bp b/test/087-gc-after-link/Android.bp
new file mode 100644
index 0000000..02a8190
--- /dev/null
+++ b/test/087-gc-after-link/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `087-gc-after-link`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-087-gc-after-link",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-087-gc-after-link-expected-stdout",
+        ":art-run-test-087-gc-after-link-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-087-gc-after-link-expected-stdout",
+    out: ["art-run-test-087-gc-after-link-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-087-gc-after-link-expected-stderr",
+    out: ["art-run-test-087-gc-after-link-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/087-gc-after-link/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/087-gc-after-link/expected-stderr.txt
diff --git a/test/087-gc-after-link/expected.txt b/test/087-gc-after-link/expected-stdout.txt
similarity index 100%
rename from test/087-gc-after-link/expected.txt
rename to test/087-gc-after-link/expected-stdout.txt
diff --git a/test/080-oom-fragmentation/expected.txt b/test/088-monitor-verification/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/088-monitor-verification/expected-stderr.txt
diff --git a/test/088-monitor-verification/expected.txt b/test/088-monitor-verification/expected-stdout.txt
similarity index 100%
rename from test/088-monitor-verification/expected.txt
rename to test/088-monitor-verification/expected-stdout.txt
diff --git a/test/089-many-methods/check b/test/089-many-methods/check
index e09a291..c45bd9c 100755
--- a/test/089-many-methods/check
+++ b/test/089-many-methods/check
@@ -14,9 +14,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
+# Check that a build failure happened (the test is not expected to run).
 EXPECTED_ERROR="Cannot fit requested classes in a single dex"
-if ! grep -q "$EXPECTED_ERROR" "$2"; then
-  exit 1
-else
-  exit 0
-fi
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && grep -q "$EXPECTED_ERROR" "$4"
diff --git a/test/089-many-methods/expected.txt b/test/089-many-methods/expected-stderr.txt
similarity index 100%
rename from test/089-many-methods/expected.txt
rename to test/089-many-methods/expected-stderr.txt
diff --git a/test/406-fields/expected.txt b/test/089-many-methods/expected-stdout.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/089-many-methods/expected-stdout.txt
diff --git a/test/090-loop-formation/Android.bp b/test/090-loop-formation/Android.bp
new file mode 100644
index 0000000..7e908c7
--- /dev/null
+++ b/test/090-loop-formation/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `090-loop-formation`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-090-loop-formation",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-090-loop-formation-expected-stdout",
+        ":art-run-test-090-loop-formation-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-090-loop-formation-expected-stdout",
+    out: ["art-run-test-090-loop-formation-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-090-loop-formation-expected-stderr",
+    out: ["art-run-test-090-loop-formation-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-fragmentation/expected.txt b/test/090-loop-formation/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/090-loop-formation/expected-stderr.txt
diff --git a/test/090-loop-formation/expected.txt b/test/090-loop-formation/expected-stdout.txt
similarity index 100%
rename from test/090-loop-formation/expected.txt
rename to test/090-loop-formation/expected-stdout.txt
diff --git a/test/470-huge-method/expected.txt b/test/091-override-package-private-method/expected-stderr.txt
similarity index 100%
copy from test/470-huge-method/expected.txt
copy to test/091-override-package-private-method/expected-stderr.txt
diff --git a/test/091-override-package-private-method/expected.txt b/test/091-override-package-private-method/expected-stdout.txt
similarity index 100%
rename from test/091-override-package-private-method/expected.txt
rename to test/091-override-package-private-method/expected-stdout.txt
diff --git a/test/092-locale/Android.bp b/test/092-locale/Android.bp
new file mode 100644
index 0000000..cc3f6f2
--- /dev/null
+++ b/test/092-locale/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `092-locale`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-092-locale",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-092-locale-expected-stdout",
+        ":art-run-test-092-locale-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-092-locale-expected-stdout",
+    out: ["art-run-test-092-locale-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-092-locale-expected-stderr",
+    out: ["art-run-test-092-locale-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/092-locale/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/092-locale/expected-stderr.txt
diff --git a/test/092-locale/expected.txt b/test/092-locale/expected-stdout.txt
similarity index 100%
rename from test/092-locale/expected.txt
rename to test/092-locale/expected-stdout.txt
diff --git a/test/093-serialization/Android.bp b/test/093-serialization/Android.bp
new file mode 100644
index 0000000..83ae42a
--- /dev/null
+++ b/test/093-serialization/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `093-serialization`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-093-serialization",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-093-serialization-expected-stdout",
+        ":art-run-test-093-serialization-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-093-serialization-expected-stdout",
+    out: ["art-run-test-093-serialization-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-093-serialization-expected-stderr",
+    out: ["art-run-test-093-serialization-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/469-condition-materialization/expected.txt b/test/093-serialization/expected-stderr.txt
similarity index 100%
copy from test/469-condition-materialization/expected.txt
copy to test/093-serialization/expected-stderr.txt
diff --git a/test/093-serialization/expected.txt b/test/093-serialization/expected-stdout.txt
similarity index 100%
rename from test/093-serialization/expected.txt
rename to test/093-serialization/expected-stdout.txt
diff --git a/test/094-pattern/Android.bp b/test/094-pattern/Android.bp
new file mode 100644
index 0000000..892154c
--- /dev/null
+++ b/test/094-pattern/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `094-pattern`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-094-pattern",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-094-pattern-expected-stdout",
+        ":art-run-test-094-pattern-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-094-pattern-expected-stdout",
+    out: ["art-run-test-094-pattern-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-094-pattern-expected-stderr",
+    out: ["art-run-test-094-pattern-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/094-pattern/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/094-pattern/expected-stderr.txt
diff --git a/test/094-pattern/expected.txt b/test/094-pattern/expected-stdout.txt
similarity index 100%
rename from test/094-pattern/expected.txt
rename to test/094-pattern/expected-stdout.txt
diff --git a/test/095-switch-MAX_INT/Android.bp b/test/095-switch-MAX_INT/Android.bp
new file mode 100644
index 0000000..0210d4f
--- /dev/null
+++ b/test/095-switch-MAX_INT/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `095-switch-MAX_INT`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-095-switch-MAX_INT",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-095-switch-MAX_INT-expected-stdout",
+        ":art-run-test-095-switch-MAX_INT-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-095-switch-MAX_INT-expected-stdout",
+    out: ["art-run-test-095-switch-MAX_INT-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-095-switch-MAX_INT-expected-stderr",
+    out: ["art-run-test-095-switch-MAX_INT-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/095-switch-MAX_INT/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/095-switch-MAX_INT/expected-stderr.txt
diff --git a/test/095-switch-MAX_INT/expected.txt b/test/095-switch-MAX_INT/expected-stdout.txt
similarity index 100%
rename from test/095-switch-MAX_INT/expected.txt
rename to test/095-switch-MAX_INT/expected-stdout.txt
diff --git a/test/096-array-copy-concurrent-gc/Android.bp b/test/096-array-copy-concurrent-gc/Android.bp
new file mode 100644
index 0000000..1921041
--- /dev/null
+++ b/test/096-array-copy-concurrent-gc/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `096-array-copy-concurrent-gc`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-096-array-copy-concurrent-gc",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-096-array-copy-concurrent-gc-expected-stdout",
+        ":art-run-test-096-array-copy-concurrent-gc-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-096-array-copy-concurrent-gc-expected-stdout",
+    out: ["art-run-test-096-array-copy-concurrent-gc-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-096-array-copy-concurrent-gc-expected-stderr",
+    out: ["art-run-test-096-array-copy-concurrent-gc-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/096-array-copy-concurrent-gc/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/096-array-copy-concurrent-gc/expected-stderr.txt
diff --git a/test/096-array-copy-concurrent-gc/expected.txt b/test/096-array-copy-concurrent-gc/expected-stdout.txt
similarity index 100%
rename from test/096-array-copy-concurrent-gc/expected.txt
rename to test/096-array-copy-concurrent-gc/expected-stdout.txt
diff --git a/test/096-array-copy-concurrent-gc/src/Main.java b/test/096-array-copy-concurrent-gc/src/Main.java
index c8e538b..eddde11 100644
--- a/test/096-array-copy-concurrent-gc/src/Main.java
+++ b/test/096-array-copy-concurrent-gc/src/Main.java
@@ -42,7 +42,16 @@
         }
     }
 
-    Object [] array = new Object[10000];
+    Object [] array = new Object[8000];
+
+    void allocateFourStrings() {
+      for (int i = 0; i < 4; i++) {
+        String str = new String("Creating some garbage" + Math.random());
+        if (str.length() < 22) {
+          System.out.println("bad length");
+        }
+      }
+    }
 
     void stressArray(boolean doLog) {
         // We want many references in the array
@@ -63,20 +72,14 @@
             Object obj = array[array.length - 1];
             System.arraycopy(array, 0, array, 1, array.length - 1);
             array[0] = obj;
-            new String("Creating some garbage" + Math.random());
-            new String("Creating some garbage" + Math.random());
-            new String("Creating some garbage" + Math.random());
-            new String("Creating some garbage" + Math.random());
+            allocateFourStrings();
         }
 
         for (int j = 0; j < array.length; j++) {
             Object obj = array[0];
             System.arraycopy(array, 1, array, 0, array.length - 1);
             array[array.length - 1] = obj;
-            new String("Creating some garbage" + Math.random());
-            new String("Creating some garbage" + Math.random());
-            new String("Creating some garbage" + Math.random());
-            new String("Creating some garbage" + Math.random());
+            allocateFourStrings();
         }
 
         if (doLog) {
diff --git a/test/470-huge-method/expected.txt b/test/097-duplicate-method/expected-stderr.txt
similarity index 100%
copy from test/470-huge-method/expected.txt
copy to test/097-duplicate-method/expected-stderr.txt
diff --git a/test/097-duplicate-method/expected.txt b/test/097-duplicate-method/expected-stdout.txt
similarity index 100%
rename from test/097-duplicate-method/expected.txt
rename to test/097-duplicate-method/expected-stdout.txt
diff --git a/test/098-ddmc/expected.txt b/test/098-ddmc/expected.txt
deleted file mode 100644
index f8cda4c..0000000
--- a/test/098-ddmc/expected.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-Confirm empty
-empty=Allocations[message header len: 15 entry header len: 9 stack frame len: 8 number of entries: 0 offset to string table from start of message: 15 number of class name strings: 0 number of method name strings: 0 number of source file name strings: 0]
-Confirm enable
-status=false
-status=true
-Capture some allocations (note just this causes allocations)
-before > 0=true
-Confirm when we overflow, we don't roll over to zero. b/17392248
-before < overflowAllocations=true
-after > before=true
-after.numberOfEntries=65535
-Disable and confirm back to empty
-status=false
-reset=Allocations[message header len: 15 entry header len: 9 stack frame len: 8 number of entries: 0 offset to string table from start of message: 15 number of class name strings: 0 number of method name strings: 0 number of source file name strings: 0]
-Confirm we can disable twice in a row
-status=false
-status=false
-Confirm we can reenable twice in a row without losing allocations
-status=true
-status=true
-second > first =true
-Goodbye
-goodbye=Allocations[message header len: 15 entry header len: 9 stack frame len: 8 number of entries: 0 offset to string table from start of message: 15 number of class name strings: 0 number of method name strings: 0 number of source file name strings: 0]
diff --git a/test/098-ddmc/info.txt b/test/098-ddmc/info.txt
deleted file mode 100644
index 39d26db..0000000
--- a/test/098-ddmc/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Tests of private org.apache.harmony.dalvik.ddmc.* APIs used for ddms support.
diff --git a/test/098-ddmc/src/Main.java b/test/098-ddmc/src/Main.java
deleted file mode 100644
index e9a11d7..0000000
--- a/test/098-ddmc/src/Main.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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.
- */
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-
-public class Main {
-    public static void main(String[] args) throws Exception {
-        String name = System.getProperty("java.vm.name");
-        if (!"Dalvik".equals(name)) {
-            System.out.println("This test is not supported on " + name);
-            return;
-        }
-        testRecentAllocationTracking();
-    }
-
-    private static ArrayList<Object> staticHolder = new ArrayList<>(100000);
-
-    private static void testRecentAllocationTracking() throws Exception {
-        System.out.println("Confirm empty");
-        Allocations empty = new Allocations(DdmVmInternal.getRecentAllocations());
-        System.out.println("empty=" + empty);
-
-        System.out.println("Confirm enable");
-        System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
-        DdmVmInternal.enableRecentAllocations(true);
-        System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
-
-        System.out.println("Capture some allocations (note just this causes allocations)");
-        Allocations before = new Allocations(DdmVmInternal.getRecentAllocations());
-        System.out.println("before > 0=" + (before.numberOfEntries > 0));
-
-        System.out.println("Confirm when we overflow, we don't roll over to zero. b/17392248");
-        final int overflowAllocations = 64 * 1024;  // Won't fit in unsigned 16-bit value.
-        for (int i = 0; i < overflowAllocations; i++) {
-            allocate(i, 0);
-        }
-        Allocations after = new Allocations(DdmVmInternal.getRecentAllocations());
-        System.out.println("before < overflowAllocations=" + (before.numberOfEntries < overflowAllocations));
-        System.out.println("after > before=" + (after.numberOfEntries > before.numberOfEntries));
-        System.out.println("after.numberOfEntries=" + after.numberOfEntries);
-
-        staticHolder.clear();  // Free the allocated objects.
-
-        System.out.println("Disable and confirm back to empty");
-        DdmVmInternal.enableRecentAllocations(false);
-        System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
-        Allocations reset = new Allocations(DdmVmInternal.getRecentAllocations());
-        System.out.println("reset=" + reset);
-
-        System.out.println("Confirm we can disable twice in a row");
-        DdmVmInternal.enableRecentAllocations(false);
-        System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
-        DdmVmInternal.enableRecentAllocations(false);
-        System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
-
-        System.out.println("Confirm we can reenable twice in a row without losing allocations");
-        DdmVmInternal.enableRecentAllocations(true);
-        System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
-        for (int i = 0; i < 16 * 1024; i++) {
-            staticHolder.add(new String("fnord"));
-        }
-        Allocations first = new Allocations(DdmVmInternal.getRecentAllocations());
-        DdmVmInternal.enableRecentAllocations(true);
-        System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
-        Allocations second = new Allocations(DdmVmInternal.getRecentAllocations());
-        System.out.println("second > first =" + (second.numberOfEntries > first.numberOfEntries));
-
-        System.out.println("Goodbye");
-        DdmVmInternal.enableRecentAllocations(false);
-        Allocations goodbye = new Allocations(DdmVmInternal.getRecentAllocations());
-        System.out.println("goodbye=" + goodbye);
-    }
-
-    // Allocate a simple object. Use depth for a reasonably deep stack.
-    private static final int ALLOCATE1_DEPTH = 50;
-
-    private static Object createProxy() {
-        try {
-            InvocationHandler handler = new InvocationHandler() {
-                public Object invoke(Object proxy, Method method, Object[] args) {
-                    // Don't expect to be invoked.
-                    return null;
-                }
-            };
-            return Proxy.newProxyInstance(Main.class.getClassLoader(),
-                    new Class[] { Runnable.class }, handler);
-        } catch (Exception e) {
-            // We don't really expect exceptions here.
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static void allocate(int i, int depth) {
-        if (depth >= ALLOCATE1_DEPTH) {
-            // Mix proxies, int arrays and Objects to test the different descriptor paths.
-            switch (i) {
-                case 0:
-                    staticHolder.add(createProxy());
-                    break;
-
-                case 1:
-                    staticHolder.add(new int[0]);
-                    break;
-
-                case 2:
-                    staticHolder.add(new Object[0]);
-                    break;
-
-                default:
-                    staticHolder.add(new Object());
-                    break;
-            }
-        } else {
-            allocate(i, depth + 1);
-        }
-    }
-
-    private static class Allocations {
-        final int messageHeaderLen;
-        final int entryHeaderLen;
-        final int stackFrameLen;
-        final int numberOfEntries;
-        final int offsetToStringTableFromStartOfMessage;
-        final int numberOfClassNameStrings;
-        final int numberOfMethodNameStrings;
-        final int numberOfSourceFileNameStrings;
-
-        Allocations(byte[] allocations) {
-            ByteBuffer b = ByteBuffer.wrap(allocations);
-            messageHeaderLen = b.get() & 0xff;
-            if (messageHeaderLen != 15) {
-                throw new IllegalArgumentException("Unexpected messageHeaderLen " + messageHeaderLen);
-            }
-            entryHeaderLen = b.get() & 0xff;
-            if (entryHeaderLen != 9) {
-                throw new IllegalArgumentException("Unexpected entryHeaderLen " + entryHeaderLen);
-            }
-            stackFrameLen = b.get() & 0xff;
-            if (stackFrameLen != 8) {
-                throw new IllegalArgumentException("Unexpected messageHeaderLen " + stackFrameLen);
-            }
-            numberOfEntries = b.getShort() & 0xffff;
-            offsetToStringTableFromStartOfMessage = b.getInt();
-            numberOfClassNameStrings = b.getShort() & 0xffff;
-            numberOfMethodNameStrings = b.getShort() & 0xffff;
-            numberOfSourceFileNameStrings = b.getShort() & 0xffff;
-        }
-
-        public String toString() {
-            return ("Allocations[message header len: " + messageHeaderLen +
-                    " entry header len: " + entryHeaderLen +
-                    " stack frame len: " + stackFrameLen +
-                    " number of entries: " + numberOfEntries +
-                    " offset to string table from start of message: " + offsetToStringTableFromStartOfMessage +
-                    " number of class name strings: " + numberOfClassNameStrings +
-                    " number of method name strings: " + numberOfMethodNameStrings +
-                    " number of source file name strings: " + numberOfSourceFileNameStrings +
-                    "]");
-        }
-    }
-
-    private static class DdmVmInternal {
-        private static final Method enableRecentAllocationsMethod;
-        private static final Method getRecentAllocationStatusMethod;
-        private static final Method getRecentAllocationsMethod;
-        static {
-            try {
-                Class<?> c = Class.forName("org.apache.harmony.dalvik.ddmc.DdmVmInternal");
-                enableRecentAllocationsMethod = c.getDeclaredMethod("enableRecentAllocations",
-                                                                    Boolean.TYPE);
-                getRecentAllocationStatusMethod = c.getDeclaredMethod("getRecentAllocationStatus");
-                getRecentAllocationsMethod = c.getDeclaredMethod("getRecentAllocations");
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        public static void enableRecentAllocations(boolean enable) throws Exception {
-            enableRecentAllocationsMethod.invoke(null, enable);
-        }
-        public static boolean getRecentAllocationStatus() throws Exception {
-            return (boolean) getRecentAllocationStatusMethod.invoke(null);
-        }
-        public static byte[] getRecentAllocations() throws Exception {
-            return (byte[]) getRecentAllocationsMethod.invoke(null);
-        }
-    }
-}
diff --git a/test/099-vmdebug/Android.bp b/test/099-vmdebug/Android.bp
new file mode 100644
index 0000000..b83cf96
--- /dev/null
+++ b/test/099-vmdebug/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `099-vmdebug`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-099-vmdebug",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-099-vmdebug-expected-stdout",
+        ":art-run-test-099-vmdebug-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-099-vmdebug-expected-stdout",
+    out: ["art-run-test-099-vmdebug-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-099-vmdebug-expected-stderr",
+    out: ["art-run-test-099-vmdebug-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/099-vmdebug/check b/test/099-vmdebug/check
index 6a3fed5..3d92188 100755
--- a/test/099-vmdebug/check
+++ b/test/099-vmdebug/check
@@ -14,7 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Strip the process pids and line numbers from exact error messages.
-sed -e '/^.*dalvikvm\(\|32\|64\) E.*\] /d' "$2" > "$2.tmp"
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
 
-diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null
+# Strip the process pids and line numbers from exact error messages.
+sed -e '/^.*dalvikvm\(\|32\|64\) E.*\] /d' "$4" > "$4.tmp"
+
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4.tmp" >/dev/null
diff --git a/test/408-move-bug/expected.txt b/test/099-vmdebug/expected-stderr.txt
similarity index 100%
copy from test/408-move-bug/expected.txt
copy to test/099-vmdebug/expected-stderr.txt
diff --git a/test/099-vmdebug/expected-stdout.txt b/test/099-vmdebug/expected-stdout.txt
new file mode 100644
index 0000000..b8d72f6
--- /dev/null
+++ b/test/099-vmdebug/expected-stdout.txt
@@ -0,0 +1,25 @@
+Confirm enable/disable
+status=0
+status=1
+status=0
+Confirm sampling
+status=2
+status=0
+Test starting when already started
+status=1
+status=1
+Test stopping when already stopped
+status=0
+status=0
+Test tracing with empty filename
+Got expected exception
+Test tracing with bogus (< 1024 && != 0) filesize
+Got expected exception
+Test sampling with bogus (<= 0) interval
+Got expected exception
+Instances of ClassA 2
+Instances of ClassB 1
+Instances of null 0
+Instances of ClassA assignable 3
+Array counts [2, 1, 0]
+Array counts assignable [3, 1, 0]
diff --git a/test/099-vmdebug/expected.txt b/test/099-vmdebug/expected.txt
deleted file mode 100644
index f7801de..0000000
--- a/test/099-vmdebug/expected.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-Confirm enable/disable
-status=0
-status=1
-status=0
-Confirm sampling
-status=2
-status=0
-Test starting when already started
-status=1
-status=1
-Test stopping when already stopped
-status=0
-status=0
-Test tracing with empty filename
-Got expected exception
-Test tracing with bogus (< 1024 && != 0) filesize
-Got expected exception
-Test sampling with bogus (<= 0) interval
-Got expected exception
-Instances of ClassA 2
-Instances of ClassB 1
-Instances of null 0
-Instances of ClassA assignable 3
-Array counts [2, 1, 0]
-Array counts assignable [3, 1, 0]
-ClassD got 3, combined mask: 13
-ClassE got 2, combined mask: 18
-null got 0
-ClassD assignable got 5, combined mask: 31
-ClassE assignable got 2, combined mask: 18
-null assignable got 0
diff --git a/test/099-vmdebug/src/Main.java b/test/099-vmdebug/src/Main.java
index e0d829a..8fed123 100644
--- a/test/099-vmdebug/src/Main.java
+++ b/test/099-vmdebug/src/Main.java
@@ -33,7 +33,6 @@
         }
         testMethodTracing();
         testCountInstances();
-        testGetInstances();
         testRuntimeStat();
         testRuntimeStats();
     }
@@ -264,45 +263,6 @@
         }
     }
 
-    private static void testGetInstances() throws Exception {
-        ArrayList<Object> l = new ArrayList<Object>();
-        l.add(new ClassD(0x01));
-        l.add(new ClassE(0x02));
-        l.add(new ClassD(0x04));
-        l.add(new ClassD(0x08));
-        l.add(new ClassE(0x10));
-        Runtime.getRuntime().gc();
-        Class<?>[] classes = new Class<?>[] {ClassD.class, ClassE.class, null};
-        Object[][] instances = VMDebug.getInstancesOfClasses(classes, false);
-
-        int mask = 0;
-        for (Object instance : instances[0]) {
-            mask |= ((ClassD)instance).mask;
-        }
-        System.out.println("ClassD got " + instances[0].length + ", combined mask: " + mask);
-
-        mask = 0;
-        for (Object instance : instances[1]) {
-            mask |= ((ClassD)instance).mask;
-        }
-        System.out.println("ClassE got " + instances[1].length + ", combined mask: " + mask);
-        System.out.println("null got " + instances[2].length);
-
-        instances = VMDebug.getInstancesOfClasses(classes, true);
-        mask = 0;
-        for (Object instance : instances[0]) {
-            mask |= ((ClassD)instance).mask;
-        }
-        System.out.println("ClassD assignable got " + instances[0].length + ", combined mask: " + mask);
-
-        mask = 0;
-        for (Object instance : instances[1]) {
-            mask |= ((ClassD)instance).mask;
-        }
-        System.out.println("ClassE assignable got " + instances[1].length + ", combined mask: " + mask);
-        System.out.println("null assignable got " + instances[2].length);
-    }
-
     private static class VMDebug {
         private static final Method startMethodTracingMethod;
         private static final Method stopMethodTracingMethod;
@@ -311,7 +271,6 @@
         private static final Method getRuntimeStatsMethod;
         private static final Method countInstancesOfClassMethod;
         private static final Method countInstancesOfClassesMethod;
-        private static final Method getInstancesOfClassesMethod;
         static {
             try {
                 Class<?> c = Class.forName("dalvik.system.VMDebug");
@@ -325,8 +284,6 @@
                         Class.class, Boolean.TYPE);
                 countInstancesOfClassesMethod = c.getDeclaredMethod("countInstancesOfClasses",
                         Class[].class, Boolean.TYPE);
-                getInstancesOfClassesMethod = c.getDeclaredMethod("getInstancesOfClasses",
-                        Class[].class, Boolean.TYPE);
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
@@ -357,9 +314,5 @@
             return (long[]) countInstancesOfClassesMethod.invoke(
                     null, new Object[]{classes, assignable});
         }
-        public static Object[][] getInstancesOfClasses(Class<?>[] classes, boolean assignable) throws Exception {
-            return (Object[][]) getInstancesOfClassesMethod.invoke(
-                    null, new Object[]{classes, assignable});
-        }
     }
 }
diff --git a/test/100-reflect2/Android.bp b/test/100-reflect2/Android.bp
new file mode 100644
index 0000000..c2ed58f
--- /dev/null
+++ b/test/100-reflect2/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `100-reflect2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-100-reflect2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-100-reflect2-expected-stdout",
+        ":art-run-test-100-reflect2-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-100-reflect2-expected-stdout",
+    out: ["art-run-test-100-reflect2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-100-reflect2-expected-stderr",
+    out: ["art-run-test-100-reflect2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/100-reflect2/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/100-reflect2/expected-stderr.txt
diff --git a/test/100-reflect2/expected.txt b/test/100-reflect2/expected-stdout.txt
similarity index 100%
rename from test/100-reflect2/expected.txt
rename to test/100-reflect2/expected-stdout.txt
diff --git a/test/160-read-barrier-stress/expected.txt b/test/1000-non-moving-space-stress/expected-stderr.txt
similarity index 100%
copy from test/160-read-barrier-stress/expected.txt
copy to test/1000-non-moving-space-stress/expected-stderr.txt
diff --git a/test/1000-non-moving-space-stress/expected.txt b/test/1000-non-moving-space-stress/expected-stdout.txt
similarity index 100%
rename from test/1000-non-moving-space-stress/expected.txt
rename to test/1000-non-moving-space-stress/expected-stdout.txt
diff --git a/test/121-modifiers/expected.txt b/test/1001-app-image-regions/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/1001-app-image-regions/expected-stderr.txt
diff --git a/test/1001-app-image-regions/expected.txt b/test/1001-app-image-regions/expected-stdout.txt
similarity index 100%
rename from test/1001-app-image-regions/expected.txt
rename to test/1001-app-image-regions/expected-stdout.txt
diff --git a/test/1001-app-image-regions/src/Main.java b/test/1001-app-image-regions/src/Main.java
index c41a606..cda2194 100644
--- a/test/1001-app-image-regions/src/Main.java
+++ b/test/1001-app-image-regions/src/Main.java
@@ -21,7 +21,7 @@
 class Main {
   public static void main(String[] args) {
     System.loadLibrary(args[0]);
-    System.out.println("App image loaded " + checkAppImageLoaded());
+    System.out.println("App image loaded " + checkAppImageLoaded("1001-app-image-regions"));
     int regionSize = getRegionSize();
     int objectsSectionSize = checkAppImageSectionSize(Main.class);
     System.out.println("Region size " + regionSize);
@@ -31,7 +31,7 @@
     }
   }
 
-  public static native boolean checkAppImageLoaded();
+  public static native boolean checkAppImageLoaded(String name);
   public static native int getRegionSize();
   public static native int checkAppImageSectionSize(Class c);
 }
diff --git a/test/1002-notify-startup/check b/test/1002-notify-startup/check
index 9d8f464..eadb559 100644
--- a/test/1002-notify-startup/check
+++ b/test/1002-notify-startup/check
@@ -14,7 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Oat file manager will complain about duplicate dex files. Ignore.
-sed -e '/.*oat_file_manager.*/d' "$2" > "$2.tmp"
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
 
-diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null
+# Oat file manager will complain about duplicate dex files. Ignore.
+sed -e '/.*oat_file_manager.*/d' "$4" > "$4.tmp"
+
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4.tmp" >/dev/null
diff --git a/test/114-ParallelGC/expected.txt b/test/1002-notify-startup/expected-stderr.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/1002-notify-startup/expected-stderr.txt
diff --git a/test/1002-notify-startup/expected.txt b/test/1002-notify-startup/expected-stdout.txt
similarity index 100%
rename from test/1002-notify-startup/expected.txt
rename to test/1002-notify-startup/expected-stdout.txt
diff --git a/test/121-modifiers/expected.txt b/test/1003-metadata-section-strings/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/1003-metadata-section-strings/expected-stderr.txt
diff --git a/test/1003-metadata-section-strings/expected.txt b/test/1003-metadata-section-strings/expected-stdout.txt
similarity index 100%
rename from test/1003-metadata-section-strings/expected.txt
rename to test/1003-metadata-section-strings/expected-stdout.txt
diff --git a/test/1003-metadata-section-strings/src-art/Main.java b/test/1003-metadata-section-strings/src-art/Main.java
index 99e1fbd..339d6d6 100644
--- a/test/1003-metadata-section-strings/src-art/Main.java
+++ b/test/1003-metadata-section-strings/src-art/Main.java
@@ -29,7 +29,7 @@
   }
 
   private static void runTest() {
-    // Test that reference equality is sane regarding the cache.
+    // Test that reference equality works regarding the cache.
     System.out.println(Other.getString(1) == "string1");
     System.out.println(Other.getString(2000) == "string2000");
     System.out.println(Other.getString(3000) == "string3000");
diff --git a/test/1004-checker-volatile-ref-load/Android.bp b/test/1004-checker-volatile-ref-load/Android.bp
new file mode 100644
index 0000000..4245faf
--- /dev/null
+++ b/test/1004-checker-volatile-ref-load/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1004-checker-volatile-ref-load`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1004-checker-volatile-ref-load",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1004-checker-volatile-ref-load-expected-stdout",
+        ":art-run-test-1004-checker-volatile-ref-load-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1004-checker-volatile-ref-load-expected-stdout",
+    out: ["art-run-test-1004-checker-volatile-ref-load-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1004-checker-volatile-ref-load-expected-stderr",
+    out: ["art-run-test-1004-checker-volatile-ref-load-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/114-ParallelGC/expected.txt b/test/1004-checker-volatile-ref-load/expected-stderr.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/1004-checker-volatile-ref-load/expected-stderr.txt
diff --git a/test/1004-checker-volatile-ref-load/expected.txt b/test/1004-checker-volatile-ref-load/expected-stdout.txt
similarity index 100%
rename from test/1004-checker-volatile-ref-load/expected.txt
rename to test/1004-checker-volatile-ref-load/expected-stdout.txt
diff --git a/test/101-fibonacci/Android.bp b/test/101-fibonacci/Android.bp
new file mode 100644
index 0000000..3a37d1f
--- /dev/null
+++ b/test/101-fibonacci/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `101-fibonacci`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-101-fibonacci",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-101-fibonacci-expected-stdout",
+        ":art-run-test-101-fibonacci-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-101-fibonacci-expected-stdout",
+    out: ["art-run-test-101-fibonacci-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-101-fibonacci-expected-stderr",
+    out: ["art-run-test-101-fibonacci-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/114-ParallelGC/expected.txt b/test/101-fibonacci/expected-stderr.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/101-fibonacci/expected-stderr.txt
diff --git a/test/101-fibonacci/expected.txt b/test/101-fibonacci/expected-stdout.txt
similarity index 100%
rename from test/101-fibonacci/expected.txt
rename to test/101-fibonacci/expected-stdout.txt
diff --git a/test/102-concurrent-gc/Android.bp b/test/102-concurrent-gc/Android.bp
new file mode 100644
index 0000000..2409aef
--- /dev/null
+++ b/test/102-concurrent-gc/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `102-concurrent-gc`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-102-concurrent-gc",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-102-concurrent-gc-expected-stdout",
+        ":art-run-test-102-concurrent-gc-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-102-concurrent-gc-expected-stdout",
+    out: ["art-run-test-102-concurrent-gc-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-102-concurrent-gc-expected-stderr",
+    out: ["art-run-test-102-concurrent-gc-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/102-concurrent-gc/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/102-concurrent-gc/expected-stderr.txt
diff --git a/test/102-concurrent-gc/expected.txt b/test/102-concurrent-gc/expected-stdout.txt
similarity index 100%
rename from test/102-concurrent-gc/expected.txt
rename to test/102-concurrent-gc/expected-stdout.txt
diff --git a/test/103-string-append/Android.bp b/test/103-string-append/Android.bp
new file mode 100644
index 0000000..ccef18a
--- /dev/null
+++ b/test/103-string-append/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `103-string-append`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-103-string-append",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-103-string-append-expected-stdout",
+        ":art-run-test-103-string-append-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-103-string-append-expected-stdout",
+    out: ["art-run-test-103-string-append-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-103-string-append-expected-stderr",
+    out: ["art-run-test-103-string-append-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/103-string-append/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/103-string-append/expected-stderr.txt
diff --git a/test/103-string-append/expected.txt b/test/103-string-append/expected-stdout.txt
similarity index 100%
rename from test/103-string-append/expected.txt
rename to test/103-string-append/expected-stdout.txt
diff --git a/test/104-growth-limit/Android.bp b/test/104-growth-limit/Android.bp
new file mode 100644
index 0000000..8820472
--- /dev/null
+++ b/test/104-growth-limit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `104-growth-limit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-104-growth-limit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-104-growth-limit-expected-stdout",
+        ":art-run-test-104-growth-limit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-104-growth-limit-expected-stdout",
+    out: ["art-run-test-104-growth-limit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-104-growth-limit-expected-stderr",
+    out: ["art-run-test-104-growth-limit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/529-long-split/expected.txt b/test/104-growth-limit/expected-stderr.txt
similarity index 100%
copy from test/529-long-split/expected.txt
copy to test/104-growth-limit/expected-stderr.txt
diff --git a/test/104-growth-limit/expected.txt b/test/104-growth-limit/expected-stdout.txt
similarity index 100%
rename from test/104-growth-limit/expected.txt
rename to test/104-growth-limit/expected-stdout.txt
diff --git a/test/105-invoke/Android.bp b/test/105-invoke/Android.bp
new file mode 100644
index 0000000..89c9bdf
--- /dev/null
+++ b/test/105-invoke/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `105-invoke`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-105-invoke",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-105-invoke-expected-stdout",
+        ":art-run-test-105-invoke-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-105-invoke-expected-stdout",
+    out: ["art-run-test-105-invoke-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-105-invoke-expected-stderr",
+    out: ["art-run-test-105-invoke-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/105-invoke/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/105-invoke/expected-stderr.txt
diff --git a/test/105-invoke/expected.txt b/test/105-invoke/expected-stdout.txt
similarity index 100%
rename from test/105-invoke/expected.txt
rename to test/105-invoke/expected-stdout.txt
diff --git a/test/106-exceptions2/Android.bp b/test/106-exceptions2/Android.bp
new file mode 100644
index 0000000..e5c3427
--- /dev/null
+++ b/test/106-exceptions2/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `106-exceptions2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-106-exceptions2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-106-exceptions2-expected-stdout",
+        ":art-run-test-106-exceptions2-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-106-exceptions2-expected-stdout",
+    out: ["art-run-test-106-exceptions2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-106-exceptions2-expected-stderr",
+    out: ["art-run-test-106-exceptions2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/114-ParallelGC/expected.txt b/test/106-exceptions2/expected-stderr.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/106-exceptions2/expected-stderr.txt
diff --git a/test/106-exceptions2/expected.txt b/test/106-exceptions2/expected-stdout.txt
similarity index 100%
rename from test/106-exceptions2/expected.txt
rename to test/106-exceptions2/expected-stdout.txt
diff --git a/test/107-int-math2/Android.bp b/test/107-int-math2/Android.bp
new file mode 100644
index 0000000..930909f
--- /dev/null
+++ b/test/107-int-math2/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `107-int-math2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-107-int-math2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-107-int-math2-expected-stdout",
+        ":art-run-test-107-int-math2-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-107-int-math2-expected-stdout",
+    out: ["art-run-test-107-int-math2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-107-int-math2-expected-stderr",
+    out: ["art-run-test-107-int-math2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/114-ParallelGC/expected.txt b/test/107-int-math2/expected-stderr.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/107-int-math2/expected-stderr.txt
diff --git a/test/107-int-math2/expected.txt b/test/107-int-math2/expected-stdout.txt
similarity index 100%
rename from test/107-int-math2/expected.txt
rename to test/107-int-math2/expected-stdout.txt
diff --git a/test/108-check-cast/Android.bp b/test/108-check-cast/Android.bp
new file mode 100644
index 0000000..fa5d730
--- /dev/null
+++ b/test/108-check-cast/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `108-check-cast`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-108-check-cast",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-108-check-cast-expected-stdout",
+        ":art-run-test-108-check-cast-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-108-check-cast-expected-stdout",
+    out: ["art-run-test-108-check-cast-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-108-check-cast-expected-stderr",
+    out: ["art-run-test-108-check-cast-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/424-checkcast/expected.txt b/test/108-check-cast/expected-stderr.txt
similarity index 100%
copy from test/424-checkcast/expected.txt
copy to test/108-check-cast/expected-stderr.txt
diff --git a/test/108-check-cast/expected.txt b/test/108-check-cast/expected-stdout.txt
similarity index 100%
rename from test/108-check-cast/expected.txt
rename to test/108-check-cast/expected-stdout.txt
diff --git a/test/109-suspend-check/Android.bp b/test/109-suspend-check/Android.bp
new file mode 100644
index 0000000..133d965
--- /dev/null
+++ b/test/109-suspend-check/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `109-suspend-check`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-109-suspend-check",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-109-suspend-check-expected-stdout",
+        ":art-run-test-109-suspend-check-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-109-suspend-check-expected-stdout",
+    out: ["art-run-test-109-suspend-check-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-109-suspend-check-expected-stderr",
+    out: ["art-run-test-109-suspend-check-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/670-bitstring-type-check/expected.txt b/test/109-suspend-check/expected-stderr.txt
similarity index 100%
copy from test/670-bitstring-type-check/expected.txt
copy to test/109-suspend-check/expected-stderr.txt
diff --git a/test/109-suspend-check/expected.txt b/test/109-suspend-check/expected-stdout.txt
similarity index 100%
rename from test/109-suspend-check/expected.txt
rename to test/109-suspend-check/expected-stdout.txt
diff --git a/test/110-field-access/Android.bp b/test/110-field-access/Android.bp
new file mode 100644
index 0000000..3e67fac
--- /dev/null
+++ b/test/110-field-access/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `110-field-access`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-110-field-access",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-110-field-access-expected-stdout",
+        ":art-run-test-110-field-access-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-110-field-access-expected-stdout",
+    out: ["art-run-test-110-field-access-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-110-field-access-expected-stderr",
+    out: ["art-run-test-110-field-access-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/607-daemon-stress/expected.txt b/test/110-field-access/expected-stderr.txt
similarity index 100%
copy from test/607-daemon-stress/expected.txt
copy to test/110-field-access/expected-stderr.txt
diff --git a/test/110-field-access/expected.txt b/test/110-field-access/expected-stdout.txt
similarity index 100%
rename from test/110-field-access/expected.txt
rename to test/110-field-access/expected-stdout.txt
diff --git a/test/080-oom-fragmentation/expected.txt b/test/111-unresolvable-exception/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/111-unresolvable-exception/expected-stderr.txt
diff --git a/test/111-unresolvable-exception/expected.txt b/test/111-unresolvable-exception/expected-stdout.txt
similarity index 100%
rename from test/111-unresolvable-exception/expected.txt
rename to test/111-unresolvable-exception/expected-stdout.txt
diff --git a/test/112-double-math/Android.bp b/test/112-double-math/Android.bp
new file mode 100644
index 0000000..2c16776
--- /dev/null
+++ b/test/112-double-math/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `112-double-math`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-112-double-math",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-112-double-math-expected-stdout",
+        ":art-run-test-112-double-math-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-112-double-math-expected-stdout",
+    out: ["art-run-test-112-double-math-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-112-double-math-expected-stderr",
+    out: ["art-run-test-112-double-math-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/114-ParallelGC/expected.txt b/test/112-double-math/expected-stderr.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/112-double-math/expected-stderr.txt
diff --git a/test/112-double-math/expected.txt b/test/112-double-math/expected-stdout.txt
similarity index 100%
rename from test/112-double-math/expected.txt
rename to test/112-double-math/expected-stdout.txt
diff --git a/test/114-ParallelGC/expected.txt b/test/113-multidex/expected-stderr.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/113-multidex/expected-stderr.txt
diff --git a/test/113-multidex/expected.txt b/test/113-multidex/expected-stdout.txt
similarity index 100%
rename from test/113-multidex/expected.txt
rename to test/113-multidex/expected-stdout.txt
diff --git a/test/114-ParallelGC/Android.bp b/test/114-ParallelGC/Android.bp
new file mode 100644
index 0000000..bae03cc
--- /dev/null
+++ b/test/114-ParallelGC/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `114-ParallelGC`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-114-ParallelGC",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-114-ParallelGC-expected-stdout",
+        ":art-run-test-114-ParallelGC-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-114-ParallelGC-expected-stdout",
+    out: ["art-run-test-114-ParallelGC-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-114-ParallelGC-expected-stderr",
+    out: ["art-run-test-114-ParallelGC-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/114-ParallelGC/expected.txt b/test/114-ParallelGC/expected-stderr.txt
similarity index 100%
rename from test/114-ParallelGC/expected.txt
rename to test/114-ParallelGC/expected-stderr.txt
diff --git a/test/114-ParallelGC/expected.txt b/test/114-ParallelGC/expected-stdout.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/114-ParallelGC/expected-stdout.txt
diff --git a/test/115-native-bridge/Android.bp b/test/115-native-bridge/Android.bp
new file mode 100644
index 0000000..be77457
--- /dev/null
+++ b/test/115-native-bridge/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `115-native-bridge`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-115-native-bridge",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-115-native-bridge-expected-stdout",
+        ":art-run-test-115-native-bridge-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-115-native-bridge-expected-stdout",
+    out: ["art-run-test-115-native-bridge-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-115-native-bridge-expected-stderr",
+    out: ["art-run-test-115-native-bridge-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/115-native-bridge/check b/test/115-native-bridge/check
index 1ecf334..e01de91 100755
--- a/test/115-native-bridge/check
+++ b/test/115-native-bridge/check
@@ -14,7 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # ASAN prints a warning here.
 
-sed -e '/WARNING: ASan is ignoring requested __asan_handle_no_return/,+2d' "$2" | \
-    diff --strip-trailing-cr -q "$1" - >/dev/null
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && sed -e '/WARNING: ASan is ignoring requested __asan_handle_no_return/,+2d' "$4" \
+       | diff --strip-trailing-cr -q "$3" - >/dev/null
diff --git a/test/1337-gc-coverage/expected.txt b/test/115-native-bridge/expected-stderr.txt
similarity index 100%
copy from test/1337-gc-coverage/expected.txt
copy to test/115-native-bridge/expected-stderr.txt
diff --git a/test/115-native-bridge/expected.txt b/test/115-native-bridge/expected-stdout.txt
similarity index 100%
rename from test/115-native-bridge/expected.txt
rename to test/115-native-bridge/expected-stdout.txt
diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc
index 754cb00..3209449 100644
--- a/test/115-native-bridge/nativebridge.cc
+++ b/test/115-native-bridge/nativebridge.cc
@@ -579,7 +579,7 @@
   return true;
 }
 
-// A dummy special handler, continueing after the faulting location. This code comes from
+// A placeholder special handler, continueing after the faulting location. This code comes from
 // 004-SignalTest.
 static bool nb_signalhandler(int sig, siginfo_t* info, void* context) {
   printf("NB signal handler with signal %d.\n", sig);
diff --git a/test/116-nodex2oat/Android.bp b/test/116-nodex2oat/Android.bp
new file mode 100644
index 0000000..090856b
--- /dev/null
+++ b/test/116-nodex2oat/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `116-nodex2oat`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-116-nodex2oat",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-116-nodex2oat-expected-stdout",
+        ":art-run-test-116-nodex2oat-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-116-nodex2oat-expected-stdout",
+    out: ["art-run-test-116-nodex2oat-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-116-nodex2oat-expected-stderr",
+    out: ["art-run-test-116-nodex2oat-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/436-rem-float/expected.txt b/test/116-nodex2oat/expected-stderr.txt
similarity index 100%
copy from test/436-rem-float/expected.txt
copy to test/116-nodex2oat/expected-stderr.txt
diff --git a/test/116-nodex2oat/expected.txt b/test/116-nodex2oat/expected-stdout.txt
similarity index 100%
rename from test/116-nodex2oat/expected.txt
rename to test/116-nodex2oat/expected-stdout.txt
diff --git a/test/118-noimage-dex2oat/check b/test/118-noimage-dex2oat/check
index 4f46083..90ffdf8 100755
--- a/test/118-noimage-dex2oat/check
+++ b/test/118-noimage-dex2oat/check
@@ -14,7 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Strip the process pids and line numbers from exact error messages.
-sed -e '/^dalvikvm.* E.*\] /d' "$2" > "$2.tmp"
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
 
-diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null
+# Strip the process pids and line numbers from exact error messages.
+sed -e '/^dalvikvm.* E.*\] /d' "$4" > "$4.tmp"
+
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4.tmp" >/dev/null
diff --git a/test/436-rem-float/expected.txt b/test/118-noimage-dex2oat/expected-stderr.txt
similarity index 100%
copy from test/436-rem-float/expected.txt
copy to test/118-noimage-dex2oat/expected-stderr.txt
diff --git a/test/118-noimage-dex2oat/expected-stdout.txt b/test/118-noimage-dex2oat/expected-stdout.txt
new file mode 100644
index 0000000..8946a86
--- /dev/null
+++ b/test/118-noimage-dex2oat/expected-stdout.txt
@@ -0,0 +1,12 @@
+Run -Xnoimage-dex2oat
+JNI_OnLoad called
+Has image is false, is image dex2oat enabled is false, is BOOTCLASSPATH on disk is false.
+testB18485243 PASS
+Run -Ximage-dex2oat
+JNI_OnLoad called
+Has image is true, is image dex2oat enabled is true, is BOOTCLASSPATH on disk is true.
+testB18485243 PASS
+Run default
+JNI_OnLoad called
+Has image is true, is image dex2oat enabled is true, is BOOTCLASSPATH on disk is true.
+testB18485243 PASS
diff --git a/test/118-noimage-dex2oat/expected.txt b/test/118-noimage-dex2oat/expected.txt
deleted file mode 100644
index 166481e..0000000
--- a/test/118-noimage-dex2oat/expected.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-Run -Xnoimage-dex2oat
-JNI_OnLoad called
-Has image is false, is image dex2oat enabled is false, is BOOTCLASSPATH on disk is false.
-testB18485243 PASS
-Run -Xnoimage-dex2oat -Xno-dex-file-fallback
-Failed to initialize runtime (check log for details)
-Run -Ximage-dex2oat
-JNI_OnLoad called
-Has image is true, is image dex2oat enabled is true, is BOOTCLASSPATH on disk is true.
-testB18485243 PASS
-Run default
-JNI_OnLoad called
-Has image is true, is image dex2oat enabled is true, is BOOTCLASSPATH on disk is true.
-testB18485243 PASS
diff --git a/test/118-noimage-dex2oat/run b/test/118-noimage-dex2oat/run
index d1b9725..1b6251d 100644
--- a/test/118-noimage-dex2oat/run
+++ b/test/118-noimage-dex2oat/run
@@ -37,21 +37,15 @@
 ${RUN} ${flags} --runtime-option -Xnoimage-dex2oat
 return_status1=$?
 
-# Make sure we cannot run without an oat file without fallback.
-echo "Run -Xnoimage-dex2oat -Xno-dex-file-fallback"
-${RUN} ${flags} --runtime-option -Xnoimage-dex2oat \
-  --runtime-option -Xno-dex-file-fallback
-return_status2=$?
-
 # Make sure we can run with the oat file.
 echo "Run -Ximage-dex2oat"
 ${RUN} ${flags} --runtime-option -Ximage-dex2oat
-return_status3=$?
+return_status2=$?
 
 # Make sure we can run with the default settings.
 echo "Run default"
 ${RUN} ${flags}
-return_status4=$?
+return_status3=$?
 
 # Make sure we don't silently ignore an early failure.
-(exit $return_status1) && (exit $return_status2) && (exit $return_status3) && (exit $return_status4)
+(exit $return_status1) && (exit $return_status2) && (exit $return_status3)
diff --git a/test/120-hashcode/Android.bp b/test/120-hashcode/Android.bp
new file mode 100644
index 0000000..453893a
--- /dev/null
+++ b/test/120-hashcode/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `120-hashcode`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-120-hashcode",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-120-hashcode-expected-stdout",
+        ":art-run-test-120-hashcode-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-120-hashcode-expected-stdout",
+    out: ["art-run-test-120-hashcode-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-120-hashcode-expected-stderr",
+    out: ["art-run-test-120-hashcode-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/120-hashcode/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/120-hashcode/expected-stderr.txt
diff --git a/test/120-hashcode/expected.txt b/test/120-hashcode/expected-stdout.txt
similarity index 100%
rename from test/120-hashcode/expected.txt
rename to test/120-hashcode/expected-stdout.txt
diff --git a/test/121-modifiers/expected.txt b/test/121-modifiers/expected-stderr.txt
similarity index 100%
rename from test/121-modifiers/expected.txt
rename to test/121-modifiers/expected-stderr.txt
diff --git a/test/121-modifiers/expected.txt b/test/121-modifiers/expected-stdout.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/121-modifiers/expected-stdout.txt
diff --git a/test/121-simple-suspend-check/Android.bp b/test/121-simple-suspend-check/Android.bp
new file mode 100644
index 0000000..22821fe
--- /dev/null
+++ b/test/121-simple-suspend-check/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `121-simple-suspend-check`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-121-simple-suspend-check",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-121-simple-suspend-check-expected-stdout",
+        ":art-run-test-121-simple-suspend-check-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-121-simple-suspend-check-expected-stdout",
+    out: ["art-run-test-121-simple-suspend-check-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-121-simple-suspend-check-expected-stderr",
+    out: ["art-run-test-121-simple-suspend-check-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/670-bitstring-type-check/expected.txt b/test/121-simple-suspend-check/expected-stderr.txt
similarity index 100%
copy from test/670-bitstring-type-check/expected.txt
copy to test/121-simple-suspend-check/expected-stderr.txt
diff --git a/test/121-simple-suspend-check/expected.txt b/test/121-simple-suspend-check/expected-stdout.txt
similarity index 100%
rename from test/121-simple-suspend-check/expected.txt
rename to test/121-simple-suspend-check/expected-stdout.txt
diff --git a/test/122-npe/Android.bp b/test/122-npe/Android.bp
new file mode 100644
index 0000000..fba593d
--- /dev/null
+++ b/test/122-npe/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `122-npe`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-122-npe",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-122-npe-expected-stdout",
+        ":art-run-test-122-npe-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-122-npe-expected-stdout",
+    out: ["art-run-test-122-npe-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-122-npe-expected-stderr",
+    out: ["art-run-test-122-npe-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/122-npe/expected-stderr.txt
similarity index 100%
rename from test/122-npe/expected.txt
rename to test/122-npe/expected-stderr.txt
diff --git a/test/122-npe/expected.txt b/test/122-npe/expected-stdout.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/122-npe/expected-stdout.txt
diff --git a/test/122-npe/src/Main.java b/test/122-npe/src/Main.java
index 8f68205..9cd163f 100644
--- a/test/122-npe/src/Main.java
+++ b/test/122-npe/src/Main.java
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+import java.lang.ref.WeakReference;
+
 /**
  * Test that null pointer exceptions are thrown by the VM.
  */
@@ -38,7 +40,7 @@
   static void methodTwo() {
     NullPointerException npe = null;
 
-    int thisLine = 41;
+    int thisLine = 43;
 
     new Object().getClass(); // Ensure compiled.
     try {
@@ -547,6 +549,14 @@
       npe = e;
     }
     check(npe, thisLine += 14);
+
+    npe = null;
+    try {
+      useInt(((WeakReference<Object>) null).refersTo(null) ? 1 : 0);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 8);
   }
 
   static void check(NullPointerException npe, int firstLine) {
@@ -558,8 +568,8 @@
     }
     StackTraceElement[] trace = npe.getStackTrace();
     checkElement(trace[0], "Main", "methodTwo", "Main.java", firstLine);
-    checkElement(trace[1], "Main", "methodOne", "Main.java", 27);
-    checkElement(trace[2], "Main", "main", "Main.java", 23);
+    checkElement(trace[1], "Main", "methodOne", "Main.java", 29);
+    checkElement(trace[2], "Main", "main", "Main.java", 25);
   }
 
   static void checkElement(StackTraceElement element,
diff --git a/test/123-compiler-regressions-mt/Android.bp b/test/123-compiler-regressions-mt/Android.bp
new file mode 100644
index 0000000..7c50958
--- /dev/null
+++ b/test/123-compiler-regressions-mt/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `123-compiler-regressions-mt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-123-compiler-regressions-mt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-123-compiler-regressions-mt-expected-stdout",
+        ":art-run-test-123-compiler-regressions-mt-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-123-compiler-regressions-mt-expected-stdout",
+    out: ["art-run-test-123-compiler-regressions-mt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-123-compiler-regressions-mt-expected-stderr",
+    out: ["art-run-test-123-compiler-regressions-mt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/123-compiler-regressions-mt/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/123-compiler-regressions-mt/expected-stderr.txt
diff --git a/test/123-compiler-regressions-mt/expected.txt b/test/123-compiler-regressions-mt/expected-stdout.txt
similarity index 100%
rename from test/123-compiler-regressions-mt/expected.txt
rename to test/123-compiler-regressions-mt/expected-stdout.txt
diff --git a/test/123-inline-execute2/Android.bp b/test/123-inline-execute2/Android.bp
new file mode 100644
index 0000000..146d9c2
--- /dev/null
+++ b/test/123-inline-execute2/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `123-inline-execute2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-123-inline-execute2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-123-inline-execute2-expected-stdout",
+        ":art-run-test-123-inline-execute2-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-123-inline-execute2-expected-stdout",
+    out: ["art-run-test-123-inline-execute2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-123-inline-execute2-expected-stderr",
+    out: ["art-run-test-123-inline-execute2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/123-inline-execute2/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/123-inline-execute2/expected-stderr.txt
diff --git a/test/123-inline-execute2/expected.txt b/test/123-inline-execute2/expected-stdout.txt
similarity index 100%
rename from test/123-inline-execute2/expected.txt
rename to test/123-inline-execute2/expected-stdout.txt
diff --git a/test/123-inline-execute2/info.txt b/test/123-inline-execute2/info.txt
index 4a728a7..6cd5be0 100644
--- a/test/123-inline-execute2/info.txt
+++ b/test/123-inline-execute2/info.txt
@@ -1 +1 @@
-Sanity checks for added InlineNative methods.
+Checks for added InlineNative methods.
diff --git a/test/907-get-loaded-classes/expected.txt b/test/124-missing-classes/expected-stderr.txt
similarity index 100%
copy from test/907-get-loaded-classes/expected.txt
copy to test/124-missing-classes/expected-stderr.txt
diff --git a/test/124-missing-classes/expected.txt b/test/124-missing-classes/expected-stdout.txt
similarity index 100%
rename from test/124-missing-classes/expected.txt
rename to test/124-missing-classes/expected-stdout.txt
diff --git a/test/125-gc-and-classloading/Android.bp b/test/125-gc-and-classloading/Android.bp
new file mode 100644
index 0000000..64a7a55
--- /dev/null
+++ b/test/125-gc-and-classloading/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `125-gc-and-classloading`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-125-gc-and-classloading",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-125-gc-and-classloading-expected-stdout",
+        ":art-run-test-125-gc-and-classloading-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-125-gc-and-classloading-expected-stdout",
+    out: ["art-run-test-125-gc-and-classloading-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-125-gc-and-classloading-expected-stderr",
+    out: ["art-run-test-125-gc-and-classloading-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/304-method-tracing/expected.txt b/test/125-gc-and-classloading/expected-stderr.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/125-gc-and-classloading/expected-stderr.txt
diff --git a/test/125-gc-and-classloading/expected.txt b/test/125-gc-and-classloading/expected-stdout.txt
similarity index 100%
rename from test/125-gc-and-classloading/expected.txt
rename to test/125-gc-and-classloading/expected-stdout.txt
diff --git a/test/981-dedup-original-dex/expected.txt b/test/126-miranda-multidex/expected-stderr.txt
similarity index 100%
copy from test/981-dedup-original-dex/expected.txt
copy to test/126-miranda-multidex/expected-stderr.txt
diff --git a/test/126-miranda-multidex/expected.txt b/test/126-miranda-multidex/expected-stdout.txt
similarity index 100%
rename from test/126-miranda-multidex/expected.txt
rename to test/126-miranda-multidex/expected-stdout.txt
diff --git a/test/126-miranda-multidex/src/MirandaClass.java b/test/126-miranda-multidex/src/MirandaClass.java
index 7bb37e7..38e729a 100644
--- a/test/126-miranda-multidex/src/MirandaClass.java
+++ b/test/126-miranda-multidex/src/MirandaClass.java
@@ -34,19 +34,19 @@
     }
 
     // Better not hit any of these...
-    public void inInterfaceDummy1() {
-        System.out.println("inInterfaceDummy1");
+    public void inInterfaceUnused1() {
+        System.out.println("inInterfaceUnused1");
     }
-    public void inInterfaceDummy2() {
-        System.out.println("inInterfaceDummy2");
+    public void inInterfaceUnused2() {
+        System.out.println("inInterfaceUnused2");
     }
-    public void inInterfaceDummy3() {
-        System.out.println("inInterfaceDummy3");
+    public void inInterfaceUnused3() {
+        System.out.println("inInterfaceUnused3");
     }
-    public void inInterfaceDummy4() {
-        System.out.println("inInterfaceDummy4");
+    public void inInterfaceUnused4() {
+        System.out.println("inInterfaceUnused4");
     }
-    public void inInterfaceDummy5() {
-        System.out.println("inInterfaceDummy5");
+    public void inInterfaceUnused5() {
+        System.out.println("inInterfaceUnused5");
     }
 }
diff --git a/test/126-miranda-multidex/src/MirandaClass2.java b/test/126-miranda-multidex/src/MirandaClass2.java
index 797ead2..cdc1a80 100644
--- a/test/126-miranda-multidex/src/MirandaClass2.java
+++ b/test/126-miranda-multidex/src/MirandaClass2.java
@@ -24,19 +24,19 @@
     }
 
     // Better not hit any of these...
-    public void inInterfaceDummy1() {
-        System.out.println("inInterfaceDummy1");
+    public void inInterfaceUnused1() {
+        System.out.println("inInterfaceUnused1");
     }
-    public void inInterfaceDummy2() {
-        System.out.println("inInterfaceDummy2");
+    public void inInterfaceUnused2() {
+        System.out.println("inInterfaceUnused2");
     }
-    public void inInterfaceDummy3() {
-        System.out.println("inInterfaceDummy3");
+    public void inInterfaceUnused3() {
+        System.out.println("inInterfaceUnused3");
     }
-    public void inInterfaceDummy4() {
-        System.out.println("inInterfaceDummy4");
+    public void inInterfaceUnused4() {
+        System.out.println("inInterfaceUnused4");
     }
-    public void inInterfaceDummy5() {
-        System.out.println("inInterfaceDummy5");
+    public void inInterfaceUnused5() {
+        System.out.println("inInterfaceUnused5");
     }
 }
diff --git a/test/126-miranda-multidex/src/MirandaInterface.java b/test/126-miranda-multidex/src/MirandaInterface.java
index df12fcc..29b5c1d 100644
--- a/test/126-miranda-multidex/src/MirandaInterface.java
+++ b/test/126-miranda-multidex/src/MirandaInterface.java
@@ -21,11 +21,11 @@
 
     public boolean inInterface();
 
-    // A couple of dummy methods to fill the method table.
-    public void inInterfaceDummy1();
-    public void inInterfaceDummy2();
-    public void inInterfaceDummy3();
-    public void inInterfaceDummy4();
-    public void inInterfaceDummy5();
+    // Otherwise unused methods to fill the method table.
+    public void inInterfaceUnused1();
+    public void inInterfaceUnused2();
+    public void inInterfaceUnused3();
+    public void inInterfaceUnused4();
+    public void inInterfaceUnused5();
 
 }
diff --git a/test/121-modifiers/expected.txt b/test/127-checker-secondarydex/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/127-checker-secondarydex/expected-stderr.txt
diff --git a/test/127-checker-secondarydex/expected.txt b/test/127-checker-secondarydex/expected-stdout.txt
similarity index 100%
rename from test/127-checker-secondarydex/expected.txt
rename to test/127-checker-secondarydex/expected-stdout.txt
diff --git a/test/128-reg-spill-on-implicit-nullcheck/Android.bp b/test/128-reg-spill-on-implicit-nullcheck/Android.bp
new file mode 100644
index 0000000..2dea4ad
--- /dev/null
+++ b/test/128-reg-spill-on-implicit-nullcheck/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `128-reg-spill-on-implicit-nullcheck`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-128-reg-spill-on-implicit-nullcheck",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-128-reg-spill-on-implicit-nullcheck-expected-stdout",
+        ":art-run-test-128-reg-spill-on-implicit-nullcheck-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-128-reg-spill-on-implicit-nullcheck-expected-stdout",
+    out: ["art-run-test-128-reg-spill-on-implicit-nullcheck-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-128-reg-spill-on-implicit-nullcheck-expected-stderr",
+    out: ["art-run-test-128-reg-spill-on-implicit-nullcheck-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/479-regression-implicit-null-check/expected.txt b/test/128-reg-spill-on-implicit-nullcheck/expected-stderr.txt
similarity index 100%
copy from test/479-regression-implicit-null-check/expected.txt
copy to test/128-reg-spill-on-implicit-nullcheck/expected-stderr.txt
diff --git a/test/128-reg-spill-on-implicit-nullcheck/expected.txt b/test/128-reg-spill-on-implicit-nullcheck/expected-stdout.txt
similarity index 100%
rename from test/128-reg-spill-on-implicit-nullcheck/expected.txt
rename to test/128-reg-spill-on-implicit-nullcheck/expected-stdout.txt
diff --git a/test/129-ThreadGetId/Android.bp b/test/129-ThreadGetId/Android.bp
new file mode 100644
index 0000000..85f6400
--- /dev/null
+++ b/test/129-ThreadGetId/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `129-ThreadGetId`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-129-ThreadGetId",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-129-ThreadGetId-expected-stdout",
+        ":art-run-test-129-ThreadGetId-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-129-ThreadGetId-expected-stdout",
+    out: ["art-run-test-129-ThreadGetId-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-129-ThreadGetId-expected-stderr",
+    out: ["art-run-test-129-ThreadGetId-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/129-ThreadGetId/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/129-ThreadGetId/expected-stderr.txt
diff --git a/test/129-ThreadGetId/expected.txt b/test/129-ThreadGetId/expected-stdout.txt
similarity index 100%
rename from test/129-ThreadGetId/expected.txt
rename to test/129-ThreadGetId/expected-stdout.txt
diff --git a/test/129-ThreadGetId/src/Main.java b/test/129-ThreadGetId/src/Main.java
index 4e48e0e..50e8c09 100644
--- a/test/129-ThreadGetId/src/Main.java
+++ b/test/129-ThreadGetId/src/Main.java
@@ -18,11 +18,11 @@
 import java.util.Map;
 
 public class Main implements Runnable {
-    static final int numberOfThreads = 5;
-    static final int totalOperations = 1000;
+    static final int NUMBER_OF_THREADS = 5;
+    static final int TOTAL_OPERATIONS = 900;
 
     public static void main(String[] args) throws Exception {
-        final Thread[] threads = new Thread[numberOfThreads];
+        final Thread[] threads = new Thread[NUMBER_OF_THREADS];
         for (int t = 0; t < threads.length; t++) {
             threads[t] = new Thread(new Main());
             threads[t].start();
@@ -87,7 +87,7 @@
     }
 
     public void run() {
-        for (int i = 0; i < totalOperations; ++i) {
+        for (int i = 0; i < TOTAL_OPERATIONS; ++i) {
             test_getId();
         }
     }
diff --git a/test/122-npe/expected.txt b/test/130-hprof/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/130-hprof/expected-stderr.txt
diff --git a/test/130-hprof/expected.txt b/test/130-hprof/expected-stdout.txt
similarity index 100%
rename from test/130-hprof/expected.txt
rename to test/130-hprof/expected-stdout.txt
diff --git a/test/130-hprof/run b/test/130-hprof/run
new file mode 100644
index 0000000..73a984e
--- /dev/null
+++ b/test/130-hprof/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2020 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.
+
+# Currently app images aren't unloaded when dex files are unloaded.
+exec ${RUN} $@ --no-secondary-app-image
diff --git a/test/130-hprof/src/Main.java b/test/130-hprof/src/Main.java
index a8597f1..38e004f 100644
--- a/test/130-hprof/src/Main.java
+++ b/test/130-hprof/src/Main.java
@@ -117,10 +117,10 @@
         if (klass == null) {
             throw new AssertionError("Couldn't find path class loader class");
         }
-        Method enableMethod = klass.getDeclaredMethod("enableRecentAllocations",
-                Boolean.TYPE);
+        Method enableMethod = klass.getDeclaredMethod("setRecentAllocationsTrackingEnabled",
+            boolean.class);
         if (enableMethod == null) {
-            throw new AssertionError("Couldn't find path class loader class");
+            throw new AssertionError("Couldn't find setRecentAllocationsTrackingEnabled method");
         }
         enableMethod.invoke(null, true);
         Object o = allocInDifferentLoader();
diff --git a/test/132-daemon-locks-shutdown/Android.bp b/test/132-daemon-locks-shutdown/Android.bp
new file mode 100644
index 0000000..e442181
--- /dev/null
+++ b/test/132-daemon-locks-shutdown/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `132-daemon-locks-shutdown`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-132-daemon-locks-shutdown",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-132-daemon-locks-shutdown-expected-stdout",
+        ":art-run-test-132-daemon-locks-shutdown-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-132-daemon-locks-shutdown-expected-stdout",
+    out: ["art-run-test-132-daemon-locks-shutdown-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-132-daemon-locks-shutdown-expected-stderr",
+    out: ["art-run-test-132-daemon-locks-shutdown-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/132-daemon-locks-shutdown/expected.txt b/test/132-daemon-locks-shutdown/expected-stderr.txt
similarity index 100%
rename from test/132-daemon-locks-shutdown/expected.txt
rename to test/132-daemon-locks-shutdown/expected-stderr.txt
diff --git a/test/132-daemon-locks-shutdown/expected.txt b/test/132-daemon-locks-shutdown/expected-stdout.txt
similarity index 100%
copy from test/132-daemon-locks-shutdown/expected.txt
copy to test/132-daemon-locks-shutdown/expected-stdout.txt
diff --git a/test/133-static-invoke-super/Android.bp b/test/133-static-invoke-super/Android.bp
new file mode 100644
index 0000000..5b24c4e
--- /dev/null
+++ b/test/133-static-invoke-super/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `133-static-invoke-super`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-133-static-invoke-super",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-133-static-invoke-super-expected-stdout",
+        ":art-run-test-133-static-invoke-super-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-133-static-invoke-super-expected-stdout",
+    out: ["art-run-test-133-static-invoke-super-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-133-static-invoke-super-expected-stderr",
+    out: ["art-run-test-133-static-invoke-super-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/551-invoke-super/expected.txt b/test/133-static-invoke-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/133-static-invoke-super/expected-stderr.txt
diff --git a/test/133-static-invoke-super/expected.txt b/test/133-static-invoke-super/expected-stdout.txt
similarity index 100%
rename from test/133-static-invoke-super/expected.txt
rename to test/133-static-invoke-super/expected-stdout.txt
diff --git a/test/1336-short-finalizer-timeout/Android.bp b/test/1336-short-finalizer-timeout/Android.bp
new file mode 100644
index 0000000..ad8e8be
--- /dev/null
+++ b/test/1336-short-finalizer-timeout/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1336-short-finalizer-timeout`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1336-short-finalizer-timeout",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1336-short-finalizer-timeout-expected-stdout",
+        ":art-run-test-1336-short-finalizer-timeout-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1336-short-finalizer-timeout-expected-stdout",
+    out: ["art-run-test-1336-short-finalizer-timeout-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1336-short-finalizer-timeout-expected-stderr",
+    out: ["art-run-test-1336-short-finalizer-timeout-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/132-daemon-locks-shutdown/expected.txt b/test/1336-short-finalizer-timeout/expected-stderr.txt
similarity index 100%
copy from test/132-daemon-locks-shutdown/expected.txt
copy to test/1336-short-finalizer-timeout/expected-stderr.txt
diff --git a/test/1336-short-finalizer-timeout/expected.txt b/test/1336-short-finalizer-timeout/expected-stdout.txt
similarity index 100%
rename from test/1336-short-finalizer-timeout/expected.txt
rename to test/1336-short-finalizer-timeout/expected-stdout.txt
diff --git a/test/1337-gc-coverage/Android.bp b/test/1337-gc-coverage/Android.bp
new file mode 100644
index 0000000..97cb8d0
--- /dev/null
+++ b/test/1337-gc-coverage/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1337-gc-coverage`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1337-gc-coverage",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1337-gc-coverage-expected-stdout",
+        ":art-run-test-1337-gc-coverage-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1337-gc-coverage-expected-stdout",
+    out: ["art-run-test-1337-gc-coverage-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1337-gc-coverage-expected-stderr",
+    out: ["art-run-test-1337-gc-coverage-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1337-gc-coverage/check b/test/1337-gc-coverage/check
index 842bdc6..67fcafb 100755
--- a/test/1337-gc-coverage/check
+++ b/test/1337-gc-coverage/check
@@ -14,9 +14,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Check that the string "error" isn't present
-if grep error "$2"; then
-    exit 1
-else
-    exit 0
-fi
+grep -vq error "$2"  \
+  && diff --strip-trailing-cr -q "$3" "$4" >/dev/null
diff --git a/test/1337-gc-coverage/expected.txt b/test/1337-gc-coverage/expected-stderr.txt
similarity index 100%
rename from test/1337-gc-coverage/expected.txt
rename to test/1337-gc-coverage/expected-stderr.txt
diff --git a/test/1337-gc-coverage/expected.txt b/test/1337-gc-coverage/expected-stdout.txt
similarity index 100%
copy from test/1337-gc-coverage/expected.txt
copy to test/1337-gc-coverage/expected-stdout.txt
diff --git a/test/121-modifiers/expected.txt b/test/1338-gc-no-los/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/1338-gc-no-los/expected-stderr.txt
diff --git a/test/1338-gc-no-los/expected.txt b/test/1338-gc-no-los/expected-stdout.txt
similarity index 100%
rename from test/1338-gc-no-los/expected.txt
rename to test/1338-gc-no-los/expected-stdout.txt
diff --git a/test/1339-dead-reference-safe/Android.bp b/test/1339-dead-reference-safe/Android.bp
new file mode 100644
index 0000000..17beb40
--- /dev/null
+++ b/test/1339-dead-reference-safe/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1339-dead-reference-safe`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1339-dead-reference-safe",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1339-dead-reference-safe-expected-stdout",
+        ":art-run-test-1339-dead-reference-safe-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1339-dead-reference-safe-expected-stdout",
+    out: ["art-run-test-1339-dead-reference-safe-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1339-dead-reference-safe-expected-stderr",
+    out: ["art-run-test-1339-dead-reference-safe-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1339-dead-reference-safe/check b/test/1339-dead-reference-safe/check
index 795cfac..e7f5f96 100644
--- a/test/1339-dead-reference-safe/check
+++ b/test/1339-dead-reference-safe/check
@@ -14,7 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # DeadReferenceSafe result differs for interpreted mode. A real failure
 # will produce an extra line anyway.
 
-diff --ignore-matching-lines="DeadReferenceSafe count:" -q $1 $2
+diff --ignore-matching-lines="DeadReferenceSafe count:" -q $1 $2 \
+  && diff --strip-trailing-cr -q "$3" "$4" >/dev/null
diff --git a/test/1337-gc-coverage/expected.txt b/test/1339-dead-reference-safe/expected-stderr.txt
similarity index 100%
copy from test/1337-gc-coverage/expected.txt
copy to test/1339-dead-reference-safe/expected-stderr.txt
diff --git a/test/1339-dead-reference-safe/expected.txt b/test/1339-dead-reference-safe/expected-stdout.txt
similarity index 100%
rename from test/1339-dead-reference-safe/expected.txt
rename to test/1339-dead-reference-safe/expected-stdout.txt
diff --git a/test/134-nodex2oat-nofallback/check b/test/134-nodex2oat-nofallback/check
deleted file mode 100755
index d929c8f..0000000
--- a/test/134-nodex2oat-nofallback/check
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-# The head of the log.
-HEAD=$(head -n 1 "$2")
-EXPECTED_HEAD="Unable to locate class 'Main'"
-
-# Content somewhere inside the output.
-grep 'Suppressed: java.io.IOException: Fallback mode disabled, skipping dex files.' "$2" >/dev/null
-MSG_FOUND=$?
-
-if [[ "$HEAD" != "$EXPECTED_HEAD" || $MSG_FOUND -ne 0 ]] ; then
-  # Print out the log and return with error.
-  cat "$2"
-  exit 1
-fi
-
-# Success.
-exit 0
\ No newline at end of file
diff --git a/test/134-nodex2oat-nofallback/expected.txt b/test/134-nodex2oat-nofallback/expected.txt
deleted file mode 100644
index 9b6c846..0000000
--- a/test/134-nodex2oat-nofallback/expected.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-# This file isn't used, but gives an example of the output we expect.
-Unable to locate class 'Main'
-java.lang.ClassNotFoundException: Didn't find class "Main" on path: DexPathList[[zip file "/tmp/user/test-12345/134-nodex2oat-nofallback.jar"],nativeLibraryDirectories=[/ssd2/aosp-master3/out/host/linux-x86/lib]]
-       at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
-       at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
-       at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
-       Suppressed: java.io.IOException: Fallback mode disabled, skipping dex files.
-               at dalvik.system.DexFile.openDexFileNative(Native Method)
-               at dalvik.system.DexFile.openDexFile(DexFile.java:295)
-               at dalvik.system.DexFile.<init>(DexFile.java:80)
-               at dalvik.system.DexFile.<init>(DexFile.java:59)
-               at dalvik.system.DexPathList.loadDexFile(DexPathList.java:262)
-               at dalvik.system.DexPathList.makeDexElements(DexPathList.java:231)
-               at dalvik.system.DexPathList.<init>(DexPathList.java:109)
-               at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:48)
-               at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:38)
-               at java.lang.ClassLoader.createSystemClassLoader(ClassLoader.java:128)
-               at java.lang.ClassLoader.access$000(ClassLoader.java:65)
-               at java.lang.ClassLoader$SystemClassLoader.<clinit>(ClassLoader.java:81)
-               at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:137)
-       Caused by: java.io.IOException: Failed to open oat file from dex location '/tmp/user/test-12345/134-nodex2oat-nofallback.jar'
-               ... 13 more
-       Caused by: java.io.IOException: Failed to open oat file from /tmp/user/test-12345/x86/134-nodex2oat-nofallback.odex (error Failed to open oat filename for reading: No such file or directory) (no dalvik_cache availible) and relocation failed.
-               ... 13 more
-       Caused by: java.io.IOException 
-               ... 13 more
-       Suppressed: java.lang.ClassNotFoundException: Main
-               at java.lang.Class.classForName(Native Method)
-               at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
-               at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
-               at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
-               ... 1 more
-       Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
-java.lang.ClassNotFoundException: Didn't find class "Main" on path: DexPathList[[zip file "/tmp/user/test-12345/134-nodex2oat-nofallback.jar"],nativeLibraryDirectories=[/ssd2/aosp-master3/out/host/linux-x86/lib]]
-       at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
-       at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
-       at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
-       Suppressed: java.io.IOException: Fallback mode disabled, skipping dex files.
-               at dalvik.system.DexFile.openDexFileNative(Native Method)
-               at dalvik.system.DexFile.openDexFile(DexFile.java:295)
-               at dalvik.system.DexFile.<init>(DexFile.java:80)
-               at dalvik.system.DexFile.<init>(DexFile.java:59)
-               at dalvik.system.DexPathList.loadDexFile(DexPathList.java:262)
-               at dalvik.system.DexPathList.makeDexElements(DexPathList.java:231)
-               at dalvik.system.DexPathList.<init>(DexPathList.java:109)
-               at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:48)
-               at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:38)
-               at java.lang.ClassLoader.createSystemClassLoader(ClassLoader.java:128)
-               at java.lang.ClassLoader.access$000(ClassLoader.java:65)
-               at java.lang.ClassLoader$SystemClassLoader.<clinit>(ClassLoader.java:81)
-               at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:137)
-       Caused by: java.io.IOException: Failed to open oat file from dex location '/tmp/user/test-12345/134-nodex2oat-nofallback.jar'
-               ... 13 more
-       Caused by: java.io.IOException: Failed to open oat file from /tmp/user/test-12345/x86/134-nodex2oat-nofallback.odex (error Failed to open oat filename for reading: No such file or directory) (no dalvik_cache availible) and relocation failed.
-               ... 13 more
-       Caused by: java.io.IOException: 
-               ... 13 more
-       Suppressed: java.lang.ClassNotFoundException: Main
-               at java.lang.Class.classForName(Native Method)
-               at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
-               at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
-               at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
-               ... 1 more
-       Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
diff --git a/test/134-nodex2oat-nofallback/info.txt b/test/134-nodex2oat-nofallback/info.txt
deleted file mode 100644
index 3004729..0000000
--- a/test/134-nodex2oat-nofallback/info.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Test that disables dex2oat'ing the application, and disable fallback. This is derived from test
-116. It needs it separate test as it needs a custom check script.
\ No newline at end of file
diff --git a/test/134-nodex2oat-nofallback/run b/test/134-nodex2oat-nofallback/run
deleted file mode 100755
index bf61d45..0000000
--- a/test/134-nodex2oat-nofallback/run
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-flags="${@}"
-
-# Make sure we cannot run without an oat file without fallback.
-${RUN} ${flags} --runtime-option -Xno-dex-file-fallback --runtime-option -XX:FastClassNotFoundException=false
-# Suppress the exit value. This isn't expected to be successful.
-echo "Exit status:" $?
diff --git a/test/134-nodex2oat-nofallback/src/Main.java b/test/134-nodex2oat-nofallback/src/Main.java
deleted file mode 100644
index 73f67c4..0000000
--- a/test/134-nodex2oat-nofallback/src/Main.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.
- */
-
-public class Main {
-  public static void main(String[] args) {
-    System.loadLibrary(args[0]);
-    System.out.println("Has oat is " + hasOat());
-  }
-
-  private native static boolean hasOat();
-}
diff --git a/test/134-reg-promotion/expected.txt b/test/134-reg-promotion/expected-stderr.txt
similarity index 100%
rename from test/134-reg-promotion/expected.txt
rename to test/134-reg-promotion/expected-stderr.txt
diff --git a/test/134-reg-promotion/expected.txt b/test/134-reg-promotion/expected-stdout.txt
similarity index 100%
copy from test/134-reg-promotion/expected.txt
copy to test/134-reg-promotion/expected-stdout.txt
diff --git a/test/542-inline-trycatch/expected.txt b/test/135-MirandaDispatch/expected-stderr.txt
similarity index 100%
copy from test/542-inline-trycatch/expected.txt
copy to test/135-MirandaDispatch/expected-stderr.txt
diff --git a/test/135-MirandaDispatch/expected.txt b/test/135-MirandaDispatch/expected-stdout.txt
similarity index 100%
rename from test/135-MirandaDispatch/expected.txt
rename to test/135-MirandaDispatch/expected-stdout.txt
diff --git a/test/136-daemon-jni-shutdown/Android.bp b/test/136-daemon-jni-shutdown/Android.bp
new file mode 100644
index 0000000..747c98e
--- /dev/null
+++ b/test/136-daemon-jni-shutdown/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `136-daemon-jni-shutdown`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-136-daemon-jni-shutdown",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-136-daemon-jni-shutdown-expected-stdout",
+        ":art-run-test-136-daemon-jni-shutdown-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-136-daemon-jni-shutdown-expected-stdout",
+    out: ["art-run-test-136-daemon-jni-shutdown-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-136-daemon-jni-shutdown-expected-stderr",
+    out: ["art-run-test-136-daemon-jni-shutdown-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/132-daemon-locks-shutdown/expected.txt b/test/136-daemon-jni-shutdown/expected-stderr.txt
similarity index 100%
copy from test/132-daemon-locks-shutdown/expected.txt
copy to test/136-daemon-jni-shutdown/expected-stderr.txt
diff --git a/test/136-daemon-jni-shutdown/expected.txt b/test/136-daemon-jni-shutdown/expected-stdout.txt
similarity index 100%
rename from test/136-daemon-jni-shutdown/expected.txt
rename to test/136-daemon-jni-shutdown/expected-stdout.txt
diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc
index aeb996c..fe227ac 100644
--- a/test/137-cfi/cfi.cc
+++ b/test/137-cfi/cfi.cc
@@ -63,7 +63,16 @@
 #if __linux__
   // Get our command line so that we can use it to start identical process.
   std::string cmdline;  // null-separated and null-terminated arguments.
-  android::base::ReadFileToString("/proc/self/cmdline", &cmdline);
+  if (!android::base::ReadFileToString("/proc/self/cmdline", &cmdline)) {
+    LOG(FATAL) << "Failed to read /proc/self/cmdline.";
+  }
+  if (cmdline.empty()) {
+    LOG(FATAL) << "No data was read from /proc/self/cmdline.";
+  }
+  // Workaround for b/150189787.
+  if (cmdline.back() != '\0') {
+    cmdline += '\0';
+  }
   cmdline = cmdline + "--secondary" + '\0';  // Let the child know it is a helper.
 
   // Split the string into individual arguments suitable for execv.
@@ -101,19 +110,36 @@
   size_t cur_search_index = 0;  // The currently active index in seq.
   CHECK_GT(seq.size(), 0U);
 
-  for (Backtrace::const_iterator it = bt->begin(); it != bt->end(); ++it) {
-    if (BacktraceMap::IsValid(it->map)) {
-      LOG(INFO) << "Got " << it->func_name << ", looking for " << seq[cur_search_index];
-      if (it->func_name.find(seq[cur_search_index]) != std::string::npos) {
-        cur_search_index++;
-        if (cur_search_index == seq.size()) {
-          return true;
+  bool any_empty_name = false;
+  for (size_t i = 0; i < bt->NumFrames(); i++) {
+    const backtrace_frame_data_t* frame = bt->GetFrame(i);
+    if (BacktraceMap::IsValid(frame->map)) {
+      if (cur_search_index < seq.size()) {
+        LOG(INFO) << "Got " << frame->func_name << ", looking for " << seq[cur_search_index];
+        if (frame->func_name.find(seq[cur_search_index]) != std::string::npos) {
+          cur_search_index++;
         }
       }
     }
+    any_empty_name |= frame->func_name.empty();
+    if (frame->func_name == "main") {
+      break;
+    }
   }
 
-  printf("Cannot find %s in backtrace:\n", seq[cur_search_index].c_str());
+  if (cur_search_index < seq.size()) {
+    printf("Cannot find %s in backtrace:\n", seq[cur_search_index].c_str());
+  } else if (any_empty_name) {
+#if defined(__BIONIC__ ) && !defined(__ANDROID__)
+    // TODO(b/182810709): Unwinding is broken on host-bionic so we expect some empty frames.
+    return true;
+#else
+    printf("Missing frames in backtrace:\n");
+#endif
+  } else {
+    return true;
+  }
+
   for (Backtrace::const_iterator it = bt->begin(); it != bt->end(); ++it) {
     if (BacktraceMap::IsValid(it->map)) {
       printf("  %s\n", Backtrace::FormatFrameData(&*it).c_str());
diff --git a/test/122-npe/expected.txt b/test/137-cfi/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/137-cfi/expected-stderr.txt
diff --git a/test/137-cfi/expected-stdout.txt b/test/137-cfi/expected-stdout.txt
new file mode 100644
index 0000000..54f35a3
--- /dev/null
+++ b/test/137-cfi/expected-stdout.txt
@@ -0,0 +1,28 @@
+args: --test-local --test-remote
+JNI_OnLoad called
+Java_Main_unwindInProcess
+PASS
+Java_Main_startSecondaryProcess
+Java_Main_unwindOtherProcess
+args: --test-local --test-remote --secondary
+JNI_OnLoad called
+Java_Main_sigstop
+PASS
+args: --test-local --test-remote
+JNI_OnLoad called
+Java_Main_unwindInProcess
+PASS
+Java_Main_startSecondaryProcess
+Java_Main_unwindOtherProcess
+args: --test-local --test-remote --secondary
+JNI_OnLoad called
+Java_Main_sigstop
+PASS
+args: --test-remote
+JNI_OnLoad called
+Java_Main_startSecondaryProcess
+Java_Main_unwindOtherProcess
+args: --test-remote --secondary
+JNI_OnLoad called
+Java_Main_sigstop
+PASS
diff --git a/test/137-cfi/expected.txt b/test/137-cfi/expected.txt
deleted file mode 100644
index 9411154..0000000
--- a/test/137-cfi/expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-args: --test-local --test-remote
-JNI_OnLoad called
-Java_Main_unwindInProcess
-PASS
-Java_Main_startSecondaryProcess
-Java_Main_unwindOtherProcess
-args: --test-local --test-remote --secondary
-JNI_OnLoad called
-Java_Main_sigstop
-PASS
-args: --test-remote
-JNI_OnLoad called
-Java_Main_startSecondaryProcess
-Java_Main_unwindOtherProcess
-args: --test-remote --secondary
-JNI_OnLoad called
-Java_Main_sigstop
-PASS
diff --git a/test/137-cfi/run b/test/137-cfi/run
index 4096b89..f09765f 100755
--- a/test/137-cfi/run
+++ b/test/137-cfi/run
@@ -16,12 +16,16 @@
 
 # Test with full DWARF debugging information.
 # Check full signatures of methods.
+${RUN} "$@" -Xcompiler-option --generate-debug-info \
+  --args --test-local --args --test-remote
+return_status1=$?
+
 # The option jitthreshold:0 ensures that if we run the test in JIT mode,
 # there will be JITed frames on the callstack (it synchronously JITs on first use).
 ${RUN} "$@" -Xcompiler-option --generate-debug-info \
   --runtime-option -Xjitthreshold:0 \
   --args --test-local --args --test-remote
-return_status1=$?
+return_status2=$?
 
 # Test with minimal compressed debugging information.
 # Check only method names (parameters are omitted to save space).
@@ -29,7 +33,7 @@
 ${RUN} "$@" -Xcompiler-option --generate-mini-debug-info \
   --runtime-option -Xjitthreshold:0 \
   --args --test-remote
-return_status2=$?
+return_status3=$?
 
 # Make sure we don't silently ignore an early failure.
-(exit $return_status1) && (exit $return_status2)
+(exit $return_status1) && (exit $return_status2) && (exit $return_status3)
diff --git a/test/542-unresolved-access-check/expected.txt b/test/138-duplicate-classes-check/expected-stderr.txt
similarity index 100%
copy from test/542-unresolved-access-check/expected.txt
copy to test/138-duplicate-classes-check/expected-stderr.txt
diff --git a/test/138-duplicate-classes-check/expected.txt b/test/138-duplicate-classes-check/expected-stdout.txt
similarity index 100%
rename from test/138-duplicate-classes-check/expected.txt
rename to test/138-duplicate-classes-check/expected-stdout.txt
diff --git a/test/138-duplicate-classes-check/src-art/Main.java b/test/138-duplicate-classes-check/src-art/Main.java
index b32f0bc..35d0209 100644
--- a/test/138-duplicate-classes-check/src-art/Main.java
+++ b/test/138-duplicate-classes-check/src-art/Main.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-import dalvik.system.DexClassLoader;
+import dalvik.system.PathClassLoader;
 import java.io.File;
 import java.lang.reflect.Method;
 
@@ -32,9 +32,8 @@
         // Now run the class from the -ex file.
 
         String dexPath = System.getenv("DEX_LOCATION") + "/138-duplicate-classes-check-ex.jar";
-        String optimizedDirectory = System.getenv("DEX_LOCATION");
         String librarySearchPath = null;
-        DexClassLoader loader = new DexClassLoader(dexPath, optimizedDirectory, librarySearchPath,
+        PathClassLoader loader = new PathClassLoader(dexPath, librarySearchPath,
                 getClass().getClassLoader());
 
         try {
diff --git a/test/132-daemon-locks-shutdown/expected.txt b/test/138-duplicate-classes-check2/expected-stderr.txt
similarity index 100%
copy from test/132-daemon-locks-shutdown/expected.txt
copy to test/138-duplicate-classes-check2/expected-stderr.txt
diff --git a/test/138-duplicate-classes-check2/expected.txt b/test/138-duplicate-classes-check2/expected-stdout.txt
similarity index 100%
rename from test/138-duplicate-classes-check2/expected.txt
rename to test/138-duplicate-classes-check2/expected-stdout.txt
diff --git a/test/139-register-natives/Android.bp b/test/139-register-natives/Android.bp
new file mode 100644
index 0000000..b80fb44
--- /dev/null
+++ b/test/139-register-natives/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `139-register-natives`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-139-register-natives",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-139-register-natives-expected-stdout",
+        ":art-run-test-139-register-natives-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-139-register-natives-expected-stdout",
+    out: ["art-run-test-139-register-natives-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-139-register-natives-expected-stderr",
+    out: ["art-run-test-139-register-natives-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/139-register-natives/check b/test/139-register-natives/check
index 265ad85..098d3c5 100755
--- a/test/139-register-natives/check
+++ b/test/139-register-natives/check
@@ -14,7 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Strip any JNI registration error messages
-sed -e '/java_vm_ext/d' -e '/jni_internal.cc/d' "$2" > "$2.tmp"
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
 
-diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null
+# Strip any JNI registration error messages
+sed -e '/java_vm_ext/d' -e '/jni_internal.cc/d' "$4" > "$4.tmp"
+
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4.tmp" >/dev/null
diff --git a/test/1901-get-bytecodes/expected.txt b/test/139-register-natives/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/139-register-natives/expected-stderr.txt
diff --git a/test/139-register-natives/expected.txt b/test/139-register-natives/expected-stdout.txt
similarity index 100%
rename from test/139-register-natives/expected.txt
rename to test/139-register-natives/expected-stdout.txt
diff --git a/test/140-dce-regression/Android.bp b/test/140-dce-regression/Android.bp
new file mode 100644
index 0000000..796fe3c
--- /dev/null
+++ b/test/140-dce-regression/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `140-dce-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-140-dce-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-140-dce-regression-expected-stdout",
+        ":art-run-test-140-dce-regression-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-140-dce-regression-expected-stdout",
+    out: ["art-run-test-140-dce-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-140-dce-regression-expected-stderr",
+    out: ["art-run-test-140-dce-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/413-regalloc-regression/expected.txt b/test/140-dce-regression/expected-stderr.txt
similarity index 100%
copy from test/413-regalloc-regression/expected.txt
copy to test/140-dce-regression/expected-stderr.txt
diff --git a/test/140-dce-regression/expected.txt b/test/140-dce-regression/expected-stdout.txt
similarity index 100%
rename from test/140-dce-regression/expected.txt
rename to test/140-dce-regression/expected-stdout.txt
diff --git a/test/140-field-packing/Android.bp b/test/140-field-packing/Android.bp
new file mode 100644
index 0000000..82ce2f9
--- /dev/null
+++ b/test/140-field-packing/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `140-field-packing`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-140-field-packing",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-140-field-packing-expected-stdout",
+        ":art-run-test-140-field-packing-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-140-field-packing-expected-stdout",
+    out: ["art-run-test-140-field-packing-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-140-field-packing-expected-stderr",
+    out: ["art-run-test-140-field-packing-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/304-method-tracing/expected.txt b/test/140-field-packing/expected-stderr.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/140-field-packing/expected-stderr.txt
diff --git a/test/140-field-packing/expected.txt b/test/140-field-packing/expected-stdout.txt
similarity index 100%
rename from test/140-field-packing/expected.txt
rename to test/140-field-packing/expected-stdout.txt
diff --git a/test/1902-suspend/expected.txt b/test/141-class-unload/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/141-class-unload/expected-stderr.txt
diff --git a/test/141-class-unload/expected.txt b/test/141-class-unload/expected-stdout.txt
similarity index 100%
rename from test/141-class-unload/expected.txt
rename to test/141-class-unload/expected-stdout.txt
diff --git a/test/141-class-unload/run b/test/141-class-unload/run
new file mode 100644
index 0000000..73a984e
--- /dev/null
+++ b/test/141-class-unload/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2020 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.
+
+# Currently app images aren't unloaded when dex files are unloaded.
+exec ${RUN} $@ --no-secondary-app-image
diff --git a/test/446-checker-inliner2/expected.txt b/test/142-classloader2/expected-stderr.txt
similarity index 100%
copy from test/446-checker-inliner2/expected.txt
copy to test/142-classloader2/expected-stderr.txt
diff --git a/test/142-classloader2/expected.txt b/test/142-classloader2/expected-stdout.txt
similarity index 100%
rename from test/142-classloader2/expected.txt
rename to test/142-classloader2/expected-stdout.txt
diff --git a/test/143-string-value/Android.bp b/test/143-string-value/Android.bp
new file mode 100644
index 0000000..86d2877
--- /dev/null
+++ b/test/143-string-value/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `143-string-value`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-143-string-value",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-143-string-value-expected-stdout",
+        ":art-run-test-143-string-value-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-143-string-value-expected-stdout",
+    out: ["art-run-test-143-string-value-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-143-string-value-expected-stderr",
+    out: ["art-run-test-143-string-value-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/143-string-value/check b/test/143-string-value/check
index b5e51ce..0691e88 100755
--- a/test/143-string-value/check
+++ b/test/143-string-value/check
@@ -14,7 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Strip error log messages.
-sed -e '/^.*dalvikvm\(\|32\|64\) E.*\] /d' "$2" > "$2.tmp"
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
 
-diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null
+# Strip error log messages.
+sed -e '/^.*dalvikvm\(\|32\|64\) E.*\] /d' "$4" > "$4.tmp"
+
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4.tmp" >/dev/null
diff --git a/test/143-string-value/expected.txt b/test/143-string-value/expected-stderr.txt
similarity index 100%
rename from test/143-string-value/expected.txt
rename to test/143-string-value/expected-stderr.txt
diff --git a/test/122-npe/expected.txt b/test/143-string-value/expected-stdout.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/143-string-value/expected-stdout.txt
diff --git a/test/144-static-field-sigquit/Android.bp b/test/144-static-field-sigquit/Android.bp
new file mode 100644
index 0000000..0c21c07
--- /dev/null
+++ b/test/144-static-field-sigquit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `144-static-field-sigquit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-144-static-field-sigquit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-144-static-field-sigquit-expected-stdout",
+        ":art-run-test-144-static-field-sigquit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-144-static-field-sigquit-expected-stdout",
+    out: ["art-run-test-144-static-field-sigquit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-144-static-field-sigquit-expected-stderr",
+    out: ["art-run-test-144-static-field-sigquit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/152-dead-large-object/expected.txt b/test/144-static-field-sigquit/expected-stderr.txt
similarity index 100%
copy from test/152-dead-large-object/expected.txt
copy to test/144-static-field-sigquit/expected-stderr.txt
diff --git a/test/144-static-field-sigquit/expected.txt b/test/144-static-field-sigquit/expected-stdout.txt
similarity index 100%
rename from test/144-static-field-sigquit/expected.txt
rename to test/144-static-field-sigquit/expected-stdout.txt
diff --git a/test/160-read-barrier-stress/expected.txt b/test/145-alloc-tracking-stress/expected-stderr.txt
similarity index 100%
copy from test/160-read-barrier-stress/expected.txt
copy to test/145-alloc-tracking-stress/expected-stderr.txt
diff --git a/test/145-alloc-tracking-stress/expected.txt b/test/145-alloc-tracking-stress/expected-stdout.txt
similarity index 100%
rename from test/145-alloc-tracking-stress/expected.txt
rename to test/145-alloc-tracking-stress/expected-stdout.txt
diff --git a/test/145-alloc-tracking-stress/src-art/Main.java b/test/145-alloc-tracking-stress/src-art/Main.java
index cf82d78..990fef7 100644
--- a/test/145-alloc-tracking-stress/src-art/Main.java
+++ b/test/145-alloc-tracking-stress/src-art/Main.java
@@ -38,10 +38,10 @@
       if (klass == null) {
           throw new AssertionError("Couldn't find DdmVmInternal class");
       }
-      enableAllocTrackingMethod = klass.getDeclaredMethod("enableRecentAllocations",
-              Boolean.TYPE);
+      enableAllocTrackingMethod = klass.getDeclaredMethod("setRecentAllocationsTrackingEnabled",
+          boolean.class);
       if (enableAllocTrackingMethod == null) {
-          throw new AssertionError("Couldn't find enableRecentAllocations method");
+          throw new AssertionError("Couldn't find setRecentAllocationsTrackingEnabled method");
       }
 
       final Thread[] threads = new Thread[numberOfThreads];
diff --git a/test/146-bad-interface/check b/test/146-bad-interface/check
index 9d8f464..eadb559 100644
--- a/test/146-bad-interface/check
+++ b/test/146-bad-interface/check
@@ -14,7 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Oat file manager will complain about duplicate dex files. Ignore.
-sed -e '/.*oat_file_manager.*/d' "$2" > "$2.tmp"
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
 
-diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null
+# Oat file manager will complain about duplicate dex files. Ignore.
+sed -e '/.*oat_file_manager.*/d' "$4" > "$4.tmp"
+
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4.tmp" >/dev/null
diff --git a/test/423-invoke-interface/expected.txt b/test/146-bad-interface/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/146-bad-interface/expected-stderr.txt
diff --git a/test/146-bad-interface/expected.txt b/test/146-bad-interface/expected-stdout.txt
similarity index 100%
rename from test/146-bad-interface/expected.txt
rename to test/146-bad-interface/expected-stdout.txt
diff --git a/test/146-bad-interface/run b/test/146-bad-interface/run
index ceef6b8..937b4fd 100755
--- a/test/146-bad-interface/run
+++ b/test/146-bad-interface/run
@@ -14,6 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# We want to run as no-dex-file-fallback to confirm that even though the -ex file has a symbolic
-# reference to A, there's no class-def, so we don't detect a collision.
 exec ${RUN} --secondary "${@}"
diff --git a/test/147-stripped-dex-fallback/expected.txt b/test/147-stripped-dex-fallback/expected.txt
deleted file mode 100644
index af5626b..0000000
--- a/test/147-stripped-dex-fallback/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-Hello, world!
diff --git a/test/147-stripped-dex-fallback/info.txt b/test/147-stripped-dex-fallback/info.txt
deleted file mode 100644
index 72a2ca8..0000000
--- a/test/147-stripped-dex-fallback/info.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Verify that we fallback to running out of dex code in the oat file if there is
-no image and the original dex code has been stripped.
diff --git a/test/147-stripped-dex-fallback/run b/test/147-stripped-dex-fallback/run
deleted file mode 100755
index 1f1d22e..0000000
--- a/test/147-stripped-dex-fallback/run
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-# ensure flags includes prebuild.
-flags="$@"
-if [[ "${flags}" == *--no-prebuild* ]] ; then
-  echo "Test 147-stripped-dex-fallback is not intended to run in no-prebuild mode."
-  exit 1
-fi
-
-${RUN} ${flags} --strip-dex
diff --git a/test/147-stripped-dex-fallback/src/Main.java b/test/147-stripped-dex-fallback/src/Main.java
deleted file mode 100644
index 1ef6289..0000000
--- a/test/147-stripped-dex-fallback/src/Main.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-
-public class Main {
-  public static void main(String[] args) {
-    System.out.println("Hello, world!");
-  }
-}
diff --git a/test/148-multithread-gc-annotations/Android.bp b/test/148-multithread-gc-annotations/Android.bp
new file mode 100644
index 0000000..c55e8dd
--- /dev/null
+++ b/test/148-multithread-gc-annotations/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `148-multithread-gc-annotations`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-148-multithread-gc-annotations",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-148-multithread-gc-annotations-expected-stdout",
+        ":art-run-test-148-multithread-gc-annotations-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-148-multithread-gc-annotations-expected-stdout",
+    out: ["art-run-test-148-multithread-gc-annotations-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-148-multithread-gc-annotations-expected-stderr",
+    out: ["art-run-test-148-multithread-gc-annotations-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/148-multithread-gc-annotations/check b/test/148-multithread-gc-annotations/check
index 842bdc6..67fcafb 100755
--- a/test/148-multithread-gc-annotations/check
+++ b/test/148-multithread-gc-annotations/check
@@ -14,9 +14,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Check that the string "error" isn't present
-if grep error "$2"; then
-    exit 1
-else
-    exit 0
-fi
+grep -vq error "$2"  \
+  && diff --strip-trailing-cr -q "$3" "$4" >/dev/null
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/148-multithread-gc-annotations/expected-stderr.txt
similarity index 100%
rename from test/148-multithread-gc-annotations/expected.txt
rename to test/148-multithread-gc-annotations/expected-stderr.txt
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/148-multithread-gc-annotations/expected-stdout.txt
similarity index 100%
copy from test/148-multithread-gc-annotations/expected.txt
copy to test/148-multithread-gc-annotations/expected-stdout.txt
diff --git a/test/149-suspend-all-stress/Android.bp b/test/149-suspend-all-stress/Android.bp
new file mode 100644
index 0000000..1960717
--- /dev/null
+++ b/test/149-suspend-all-stress/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `149-suspend-all-stress`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-149-suspend-all-stress",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-149-suspend-all-stress-expected-stdout",
+        ":art-run-test-149-suspend-all-stress-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-149-suspend-all-stress-expected-stdout",
+    out: ["art-run-test-149-suspend-all-stress-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-149-suspend-all-stress-expected-stderr",
+    out: ["art-run-test-149-suspend-all-stress-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/149-suspend-all-stress/check b/test/149-suspend-all-stress/check
index d30b888..0386d58 100755
--- a/test/149-suspend-all-stress/check
+++ b/test/149-suspend-all-stress/check
@@ -14,5 +14,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Only compare the last line.
-tail -n 1 "$2" | diff --strip-trailing-cr -q "$1" - >/dev/null
\ No newline at end of file
+tail -n 1 "$2" | diff --strip-trailing-cr -q "$1" - >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4" >/dev/null
+
diff --git a/test/160-read-barrier-stress/expected.txt b/test/149-suspend-all-stress/expected-stderr.txt
similarity index 100%
copy from test/160-read-barrier-stress/expected.txt
copy to test/149-suspend-all-stress/expected-stderr.txt
diff --git a/test/149-suspend-all-stress/expected.txt b/test/149-suspend-all-stress/expected-stdout.txt
similarity index 100%
rename from test/149-suspend-all-stress/expected.txt
rename to test/149-suspend-all-stress/expected-stdout.txt
diff --git a/test/150-loadlibrary/Android.bp b/test/150-loadlibrary/Android.bp
new file mode 100644
index 0000000..0a69263
--- /dev/null
+++ b/test/150-loadlibrary/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `150-loadlibrary`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-150-loadlibrary",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-150-loadlibrary-expected-stdout",
+        ":art-run-test-150-loadlibrary-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-150-loadlibrary-expected-stdout",
+    out: ["art-run-test-150-loadlibrary-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-150-loadlibrary-expected-stderr",
+    out: ["art-run-test-150-loadlibrary-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/688-shared-library/expected.txt b/test/150-loadlibrary/expected-stderr.txt
similarity index 100%
copy from test/688-shared-library/expected.txt
copy to test/150-loadlibrary/expected-stderr.txt
diff --git a/test/150-loadlibrary/expected.txt b/test/150-loadlibrary/expected-stdout.txt
similarity index 100%
rename from test/150-loadlibrary/expected.txt
rename to test/150-loadlibrary/expected-stdout.txt
diff --git a/test/151-OpenFileLimit/Android.bp b/test/151-OpenFileLimit/Android.bp
new file mode 100644
index 0000000..946be83
--- /dev/null
+++ b/test/151-OpenFileLimit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `151-OpenFileLimit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-151-OpenFileLimit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-151-OpenFileLimit-expected-stdout",
+        ":art-run-test-151-OpenFileLimit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-151-OpenFileLimit-expected-stdout",
+    out: ["art-run-test-151-OpenFileLimit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-151-OpenFileLimit-expected-stderr",
+    out: ["art-run-test-151-OpenFileLimit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/529-long-split/expected.txt b/test/151-OpenFileLimit/expected-stderr.txt
similarity index 100%
copy from test/529-long-split/expected.txt
copy to test/151-OpenFileLimit/expected-stderr.txt
diff --git a/test/151-OpenFileLimit/expected.txt b/test/151-OpenFileLimit/expected-stdout.txt
similarity index 100%
rename from test/151-OpenFileLimit/expected.txt
rename to test/151-OpenFileLimit/expected-stdout.txt
diff --git a/test/152-dead-large-object/Android.bp b/test/152-dead-large-object/Android.bp
new file mode 100644
index 0000000..010deb8
--- /dev/null
+++ b/test/152-dead-large-object/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `152-dead-large-object`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-152-dead-large-object",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-152-dead-large-object-expected-stdout",
+        ":art-run-test-152-dead-large-object-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-152-dead-large-object-expected-stdout",
+    out: ["art-run-test-152-dead-large-object-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-152-dead-large-object-expected-stderr",
+    out: ["art-run-test-152-dead-large-object-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/152-dead-large-object/expected.txt b/test/152-dead-large-object/expected-stderr.txt
similarity index 100%
rename from test/152-dead-large-object/expected.txt
rename to test/152-dead-large-object/expected-stderr.txt
diff --git a/test/152-dead-large-object/expected.txt b/test/152-dead-large-object/expected-stdout.txt
similarity index 100%
copy from test/152-dead-large-object/expected.txt
copy to test/152-dead-large-object/expected-stdout.txt
diff --git a/test/153-reference-stress/Android.bp b/test/153-reference-stress/Android.bp
new file mode 100644
index 0000000..ec9c6e9
--- /dev/null
+++ b/test/153-reference-stress/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `153-reference-stress`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-153-reference-stress",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-153-reference-stress-expected-stdout",
+        ":art-run-test-153-reference-stress-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-153-reference-stress-expected-stdout",
+    out: ["art-run-test-153-reference-stress-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-153-reference-stress-expected-stderr",
+    out: ["art-run-test-153-reference-stress-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/160-read-barrier-stress/expected.txt b/test/153-reference-stress/expected-stderr.txt
similarity index 100%
copy from test/160-read-barrier-stress/expected.txt
copy to test/153-reference-stress/expected-stderr.txt
diff --git a/test/153-reference-stress/expected.txt b/test/153-reference-stress/expected-stdout.txt
similarity index 100%
rename from test/153-reference-stress/expected.txt
rename to test/153-reference-stress/expected-stdout.txt
diff --git a/test/154-gc-loop/Android.bp b/test/154-gc-loop/Android.bp
new file mode 100644
index 0000000..7346c2e
--- /dev/null
+++ b/test/154-gc-loop/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `154-gc-loop`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-154-gc-loop",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-154-gc-loop-expected-stdout",
+        ":art-run-test-154-gc-loop-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-154-gc-loop-expected-stdout",
+    out: ["art-run-test-154-gc-loop-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-154-gc-loop-expected-stderr",
+    out: ["art-run-test-154-gc-loop-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/696-loop/expected.txt b/test/154-gc-loop/expected-stderr.txt
similarity index 100%
copy from test/696-loop/expected.txt
copy to test/154-gc-loop/expected-stderr.txt
diff --git a/test/154-gc-loop/expected.txt b/test/154-gc-loop/expected-stdout.txt
similarity index 100%
rename from test/154-gc-loop/expected.txt
rename to test/154-gc-loop/expected-stdout.txt
diff --git a/test/477-checker-bound-type/expected.txt b/test/155-java-set-resolved-type/expected-stderr.txt
similarity index 100%
copy from test/477-checker-bound-type/expected.txt
copy to test/155-java-set-resolved-type/expected-stderr.txt
diff --git a/test/155-java-set-resolved-type/expected.txt b/test/155-java-set-resolved-type/expected-stdout.txt
similarity index 100%
rename from test/155-java-set-resolved-type/expected.txt
rename to test/155-java-set-resolved-type/expected-stdout.txt
diff --git a/test/155-java-set-resolved-type/src/Main.java b/test/155-java-set-resolved-type/src/Main.java
index 44278a1..45f6737 100644
--- a/test/155-java-set-resolved-type/src/Main.java
+++ b/test/155-java-set-resolved-type/src/Main.java
@@ -26,7 +26,7 @@
             System.loadLibrary(args[0]);
         } catch (ClassNotFoundException e) {
             usingRI = true;
-            // Add expected JNI_OnLoad log line to match expected.txt.
+            // Add expected JNI_OnLoad log line to match expected-stdout.txt.
             System.out.println("JNI_OnLoad called");
         }
         try {
diff --git a/test/156-register-dex-file-multi-loader/Android.bp b/test/156-register-dex-file-multi-loader/Android.bp
new file mode 100644
index 0000000..0f49bfe
--- /dev/null
+++ b/test/156-register-dex-file-multi-loader/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `156-register-dex-file-multi-loader`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-156-register-dex-file-multi-loader",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-156-register-dex-file-multi-loader-expected-stdout",
+        ":art-run-test-156-register-dex-file-multi-loader-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-156-register-dex-file-multi-loader-expected-stdout",
+    out: ["art-run-test-156-register-dex-file-multi-loader-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-156-register-dex-file-multi-loader-expected-stderr",
+    out: ["art-run-test-156-register-dex-file-multi-loader-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/156-register-dex-file-multi-loader/expected.txt b/test/156-register-dex-file-multi-loader/expected-stderr.txt
similarity index 100%
rename from test/156-register-dex-file-multi-loader/expected.txt
rename to test/156-register-dex-file-multi-loader/expected-stderr.txt
diff --git a/test/156-register-dex-file-multi-loader/expected.txt b/test/156-register-dex-file-multi-loader/expected-stdout.txt
similarity index 100%
copy from test/156-register-dex-file-multi-loader/expected.txt
copy to test/156-register-dex-file-multi-loader/expected-stdout.txt
diff --git a/test/519-bound-load-class/expected.txt b/test/157-void-class/expected-stderr.txt
similarity index 100%
copy from test/519-bound-load-class/expected.txt
copy to test/157-void-class/expected-stderr.txt
diff --git a/test/157-void-class/expected.txt b/test/157-void-class/expected-stdout.txt
similarity index 100%
rename from test/157-void-class/expected.txt
rename to test/157-void-class/expected-stdout.txt
diff --git a/test/157-void-class/src-art/Main.java b/test/157-void-class/src-art/Main.java
index 322b705..25e3eba 100644
--- a/test/157-void-class/src-art/Main.java
+++ b/test/157-void-class/src-art/Main.java
@@ -24,7 +24,7 @@
             System.loadLibrary(args[0]);
         } catch (ClassNotFoundException e) {
             usingRI = true;
-            // Add expected JNI_OnLoad log line to match expected.txt.
+            // Add expected JNI_OnLoad log line to match expected-stdout.txt.
             System.out.println("JNI_OnLoad called");
         }
         try {
diff --git a/test/158-app-image-class-table/Android.bp b/test/158-app-image-class-table/Android.bp
new file mode 100644
index 0000000..ac34d66
--- /dev/null
+++ b/test/158-app-image-class-table/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `158-app-image-class-table`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-158-app-image-class-table",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-158-app-image-class-table-expected-stdout",
+        ":art-run-test-158-app-image-class-table-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-158-app-image-class-table-expected-stdout",
+    out: ["art-run-test-158-app-image-class-table-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-158-app-image-class-table-expected-stderr",
+    out: ["art-run-test-158-app-image-class-table-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1911-get-local-var-table/expected.txt b/test/158-app-image-class-table/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/158-app-image-class-table/expected-stderr.txt
diff --git a/test/158-app-image-class-table/expected.txt b/test/158-app-image-class-table/expected-stdout.txt
similarity index 100%
rename from test/158-app-image-class-table/expected.txt
rename to test/158-app-image-class-table/expected-stdout.txt
diff --git a/test/158-app-image-class-table/src/Main.java b/test/158-app-image-class-table/src/Main.java
index 97aa14d..f427431 100644
--- a/test/158-app-image-class-table/src/Main.java
+++ b/test/158-app-image-class-table/src/Main.java
@@ -23,7 +23,7 @@
             System.loadLibrary(args[0]);
         } catch (ClassNotFoundException e) {
             usingRI = true;
-            // Add expected JNI_OnLoad log line to match expected.txt.
+            // Add expected JNI_OnLoad log line to match expected-stdout.txt.
             System.out.println("JNI_OnLoad called");
         }
         try {
diff --git a/test/159-app-image-fields/Android.bp b/test/159-app-image-fields/Android.bp
new file mode 100644
index 0000000..89d35ef
--- /dev/null
+++ b/test/159-app-image-fields/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `159-app-image-fields`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-159-app-image-fields",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-159-app-image-fields-expected-stdout",
+        ":art-run-test-159-app-image-fields-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-159-app-image-fields-expected-stdout",
+    out: ["art-run-test-159-app-image-fields-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-159-app-image-fields-expected-stderr",
+    out: ["art-run-test-159-app-image-fields-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/406-fields/expected.txt b/test/159-app-image-fields/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/159-app-image-fields/expected-stderr.txt
diff --git a/test/159-app-image-fields/expected.txt b/test/159-app-image-fields/expected-stdout.txt
similarity index 100%
rename from test/159-app-image-fields/expected.txt
rename to test/159-app-image-fields/expected-stdout.txt
diff --git a/test/159-app-image-fields/src/Main.java b/test/159-app-image-fields/src/Main.java
index 47d0116..e7db1e1 100644
--- a/test/159-app-image-fields/src/Main.java
+++ b/test/159-app-image-fields/src/Main.java
@@ -61,29 +61,44 @@
         }
     }
 
+    private static int exhaustJavaHeap(Object[] data, int index, int size) {
+        Runtime.getRuntime().gc();
+        while (index != data.length && size != 0) {
+            try {
+                data[index] = new byte[size];
+                ++index;
+            } catch (OutOfMemoryError oome) {
+                size /= 2;
+            }
+        }
+        return index;
+    }
+
     public static Object eatAllMemory() {
-      Object[] result = null;
-      int size = 1000000;
-      while (result == null && size != 0) {
-          try {
-              result = new Object[size];
-          } catch (OutOfMemoryError oome) {
-              size /= 2;
-          }
-      }
-      if (result != null) {
-          int index = 0;
-          while (index != result.length && size != 0) {
-              try {
-                  result[index] = new byte[size];
-                  ++index;
-              } catch (OutOfMemoryError oome) {
-                  size /= 2;
-              }
-          }
-      }
-      return result;
-  }
+        Object[] result = null;
+        int size = 1000000;
+        // Make sure that there is no reclaimable memory in the heap. Otherwise we may throw
+        // OOME to prevent GC thrashing, even if later allocations may succeed.
+        Runtime.getRuntime().gc();
+        System.runFinalization();
+        // NOTE: There is a GC invocation in exhaustJavaHeap. So we don't need one here.
+
+        while (result == null && size != 0) {
+            try {
+                result = new Object[size];
+            } catch (OutOfMemoryError oome) {
+                size /= 2;
+            }
+        }
+        if (result != null) {
+            int index = 0;
+            // Repeat to ensure there is no space left on the heap.
+            index = exhaustJavaHeap(result, index, size);
+            index = exhaustJavaHeap(result, index, /*size*/ 4);
+            index = exhaustJavaHeap(result, index, /*size*/ 4);
+        }
+        return result;
+    }
 }
 
 // The naming is deliberate to take into account two different situations:
diff --git a/test/160-read-barrier-stress/build b/test/160-read-barrier-stress/build
new file mode 100755
index 0000000..90b6b95
--- /dev/null
+++ b/test/160-read-barrier-stress/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2020 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.
+
+./default-build "$@" --experimental var-handles
diff --git a/test/160-read-barrier-stress/expected.txt b/test/160-read-barrier-stress/expected-stderr.txt
similarity index 100%
rename from test/160-read-barrier-stress/expected.txt
rename to test/160-read-barrier-stress/expected-stderr.txt
diff --git a/test/160-read-barrier-stress/expected.txt b/test/160-read-barrier-stress/expected-stdout.txt
similarity index 100%
copy from test/160-read-barrier-stress/expected.txt
copy to test/160-read-barrier-stress/expected-stdout.txt
diff --git a/test/160-read-barrier-stress/src/Main.java b/test/160-read-barrier-stress/src/Main.java
index 5e49e66..ab23358 100644
--- a/test/160-read-barrier-stress/src/Main.java
+++ b/test/160-read-barrier-stress/src/Main.java
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.ref.WeakReference;
 import java.lang.reflect.Field;
 import sun.misc.Unsafe;
 
@@ -26,6 +29,10 @@
         testUnsafeGet();
         testUnsafeCas();
         testUnsafeCasRegression();
+        testVarHandleCompareAndSet();
+        testVarHandleCompareAndExchange();
+        testVarHandleGetAndSet();
+        testReferenceRefersTo();
     }
 
     public static void testFieldReads() {
@@ -279,6 +286,151 @@
         }
     }
 
+    public static void testVarHandleCompareAndSet() throws Exception {
+        // Initialize local variables for comparison.
+        Object f0000 = manyFields.testField0000;
+        Object f1024 = manyFields.testField1024;
+        Object f4444 = manyFields.testField4444;
+        Object f4999 = manyFields.testField4999;
+        // Initialize VarHandle objects.
+        VarHandle f0000vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField0000", Object.class);
+        VarHandle f0001vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField0001", Object.class);
+        VarHandle f1024vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField1024", Object.class);
+        VarHandle f4444vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField4444", Object.class);
+        VarHandle f4998vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField4998", Object.class);
+        VarHandle f4999vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField4999", Object.class);
+
+        // Continually check VarHandle.compareAndSet() while allocating
+        // over 64MiB memory (with heap size limited to 16MiB), ensuring we run GC and
+        // stress the read barrier implementation if concurrent collector is enabled.
+        for (int i = 0; i != 64 * 1024; ++i) {
+            allocateAtLeast1KiB();
+            ManyFields mf = manyFields;  // Load the volatile `manyFields` once on each iteration.
+            // Test VarHandle.compareAndSet().
+            assertEqual(false, f0000vh.compareAndSet(mf, f1024, f4444));
+            assertEqual(false, f0001vh.compareAndSet(mf, f1024, f4444));
+            assertEqual(true, f1024vh.compareAndSet(mf, f1024, f4444));
+            assertEqual(true, f1024vh.compareAndSet(mf, f4444, f1024));
+            assertEqual(false, f1024vh.compareAndSet(mf, f4444, f1024));
+            assertEqual(false, f4444vh.compareAndSet(mf, f1024, f4444));
+            assertEqual(false, f4998vh.compareAndSet(mf, f1024, f4444));
+            assertEqual(false, f4999vh.compareAndSet(mf, f1024, f4444));
+        }
+    }
+
+    public static void testVarHandleCompareAndExchange() throws Exception {
+        // Initialize local variables for comparison.
+        Object f0000 = manyFields.testField0000;
+        Object f0001 = manyFields.testField0001;
+        Object f1024 = manyFields.testField1024;
+        Object f4444 = manyFields.testField4444;
+        Object f4998 = manyFields.testField4998;
+        Object f4999 = manyFields.testField4999;
+        // Initialize VarHandle objects.
+        VarHandle f0000vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField0000", Object.class);
+        VarHandle f0001vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField0001", Object.class);
+        VarHandle f1024vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField1024", Object.class);
+        VarHandle f4444vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField4444", Object.class);
+        VarHandle f4998vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField4998", Object.class);
+        VarHandle f4999vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField4999", Object.class);
+
+        // Continually check VarHandle.compareAndExchange() while allocating
+        // over 64MiB memory (with heap size limited to 16MiB), ensuring we run GC and
+        // stress the read barrier implementation if concurrent collector is enabled.
+        for (int i = 0; i != 64 * 1024; ++i) {
+            allocateAtLeast1KiB();
+            ManyFields mf = manyFields;  // Load the volatile `manyFields` once on each iteration.
+            // Test VarHandle.compareAndExchange(). Use reference comparison, not equals().
+            assertSameObject(f0000, f0000vh.compareAndExchange(mf, f1024, f4444));  // Unchanged.
+            assertSameObject(f0001, f0001vh.compareAndExchange(mf, f1024, f4444));  // Unchanged.
+            assertSameObject(f1024, f1024vh.compareAndExchange(mf, f1024, f4444));  // Replaced.
+            assertSameObject(f4444, f1024vh.compareAndExchange(mf, f4444, f1024));  // Replaced.
+            assertSameObject(f1024, f1024vh.compareAndExchange(mf, f4444, f1024));  // Unchanged.
+            assertSameObject(f4444, f4444vh.compareAndExchange(mf, f1024, f4444));  // Unchanged.
+            assertSameObject(f4998, f4998vh.compareAndExchange(mf, f1024, f4444));  // Unchanged.
+            assertSameObject(f4999, f4999vh.compareAndExchange(mf, f1024, f4444));  // Unchanged.
+        }
+    }
+
+    public static void testVarHandleGetAndSet() throws Exception {
+        // Initialize local variables for comparison.
+        Object f0000 = manyFields.testField0000;
+        Object f0001 = manyFields.testField0001;
+        Object f1024 = manyFields.testField1024;
+        Object f4444 = manyFields.testField4444;
+        Object f4998 = manyFields.testField4998;
+        Object f4999 = manyFields.testField4999;
+        // Initialize VarHandle objects.
+        VarHandle f0000vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField0000", Object.class);
+        VarHandle f0001vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField0001", Object.class);
+        VarHandle f1024vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField1024", Object.class);
+        VarHandle f4444vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField4444", Object.class);
+        VarHandle f4998vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField4998", Object.class);
+        VarHandle f4999vh =
+            MethodHandles.lookup().findVarHandle(ManyFields.class, "testField4999", Object.class);
+
+        // Continually check VarHandle.getAndSet() while allocating
+        // over 64MiB memory (with heap size limited to 16MiB), ensuring we run GC and
+        // stress the read barrier implementation if concurrent collector is enabled.
+        for (int i = 0; i != 64 * 1024; ++i) {
+            allocateAtLeast1KiB();
+            ManyFields mf = manyFields;  // Load the volatile `manyFields` once on each iteration.
+            // Test VarHandle.getAndSet(). Use reference comparison, not equals().
+            assertSameObject(f0000, f0000vh.getAndSet(mf, f0000));  // Unchanged.
+            assertSameObject(f0001, f0001vh.getAndSet(mf, f0001));  // Unchanged.
+            assertSameObject(f1024, f1024vh.getAndSet(mf, f4444));  // Replaced.
+            assertSameObject(f4444, f1024vh.getAndSet(mf, f1024));  // Replaced.
+            assertSameObject(f1024, f1024vh.getAndSet(mf, f1024));  // Unchanged.
+            assertSameObject(f4444, f4444vh.getAndSet(mf, f4444));  // Unchanged.
+            assertSameObject(f4998, f4998vh.getAndSet(mf, f4998));  // Unchanged.
+            assertSameObject(f4999, f4999vh.getAndSet(mf, f4999));  // Unchanged.
+        }
+    }
+
+    public static void testReferenceRefersTo() throws Exception {
+        // Initialize local variables for comparison.
+        manyFields.testField0000 = new Object();
+        manyFields.testField1024 = new Object();
+        manyFields.testField4444 = new Object();
+        manyFields.testField4999 = new Object();
+        WeakReference<Object> f0000 = new WeakReference<Object>(manyFields.testField0000);
+        WeakReference<Object> f1024 = new WeakReference<Object>(manyFields.testField1024);
+        WeakReference<Object> f4444 = new WeakReference<Object>(manyFields.testField4444);
+        WeakReference<Object> f4999 = new WeakReference<Object>(manyFields.testField4999);
+
+        // Continually check reads from `manyFields` while allocating
+        // over 64MiB memory (with heap size limited to 16MiB), ensuring we run GC and stress the
+        // read barrier implementation in Reference.refersTo() if concurrent collector is enabled.
+        for (int i = 0; i != 64 * 1024; ++i) {
+            allocateAtLeast1KiB();
+            ManyFields mf = manyFields;  // Load the volatile `manyFields` once on each iteration.
+            // Test Reference.refersTo() with reference field access.
+            assertEqual(true, f0000.refersTo(mf.testField0000));
+            assertEqual(false, f0000.refersTo(mf.testField0001));
+            assertEqual(true, f1024.refersTo(mf.testField1024));
+            assertEqual(true, f4444.refersTo(mf.testField4444));
+            assertEqual(false, f4999.refersTo(mf.testField4998));
+            assertEqual(true, f4999.refersTo(mf.testField4999));
+        }
+    }
+
     public static int $noinline$foo() { return 42; }
 
     public static void assertDifferentObject(Object lhs, Object rhs) {
diff --git a/test/631-checker-get-class/expected.txt b/test/161-final-abstract-class/expected-stderr.txt
similarity index 100%
copy from test/631-checker-get-class/expected.txt
copy to test/161-final-abstract-class/expected-stderr.txt
diff --git a/test/161-final-abstract-class/expected.txt b/test/161-final-abstract-class/expected-stdout.txt
similarity index 100%
rename from test/161-final-abstract-class/expected.txt
rename to test/161-final-abstract-class/expected-stdout.txt
diff --git a/test/134-reg-promotion/expected.txt b/test/162-method-resolution/expected-stderr.txt
similarity index 100%
copy from test/134-reg-promotion/expected.txt
copy to test/162-method-resolution/expected-stderr.txt
diff --git a/test/162-method-resolution/expected-stdout.txt b/test/162-method-resolution/expected-stdout.txt
new file mode 100644
index 0000000..4f3f443
--- /dev/null
+++ b/test/162-method-resolution/expected-stdout.txt
@@ -0,0 +1,47 @@
+Calling Test1Derived.test():
+Test1Derived.foo()
+Calling Test1User.test():
+Caught java.lang.reflect.InvocationTargetException
+  caused by java.lang.IllegalAccessError
+Calling Test1User2.test():
+Caught java.lang.reflect.InvocationTargetException
+  caused by java.lang.IllegalAccessError
+Calling Test2User.test():
+Caught java.lang.reflect.InvocationTargetException
+  caused by java.lang.IncompatibleClassChangeError
+Calling Test2User2.test():
+Test2Base.foo()
+Calling Test3User.test():
+Caught java.lang.reflect.InvocationTargetException
+  caused by java.lang.IncompatibleClassChangeError
+Calling Test4User.test():
+Test4Derived@...
+Calling Test5User.test():
+Test5Derived.foo()
+Calling Test5User2.test():
+Caught java.lang.reflect.InvocationTargetException
+  caused by java.lang.IncompatibleClassChangeError
+Calling Test6User.test():
+Test6Derived@...
+Calling Test6User2.test():
+Caught java.lang.reflect.InvocationTargetException
+  caused by java.lang.IncompatibleClassChangeError
+Calling Test7User.test():
+Test7Interface.foo()
+Calling Test7User2.test():
+Test7Interface.foo()
+Calling Test8User.test():
+Test8Derived.foo()
+Calling Test8User2.test():
+Caught java.lang.reflect.InvocationTargetException
+  caused by java.lang.IncompatibleClassChangeError
+Calling Test9User.test():
+Test9Derived.foo()
+Calling Test9User2.test():
+Caught java.lang.reflect.InvocationTargetException
+  caused by java.lang.IncompatibleClassChangeError
+Calling Test10User.test():
+Caught java.lang.reflect.InvocationTargetException
+  caused by java.lang.IncompatibleClassChangeError
+Calling Test11User.test():
+Test11Base.<init>("Test")
diff --git a/test/162-method-resolution/expected.txt b/test/162-method-resolution/expected.txt
deleted file mode 100644
index 9b48a4c..0000000
--- a/test/162-method-resolution/expected.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-Calling Test1Derived.test():
-Test1Derived.foo()
-Calling Test1User.test():
-Caught java.lang.reflect.InvocationTargetException
-  caused by java.lang.IllegalAccessError
-Calling Test1User2.test():
-Caught java.lang.reflect.InvocationTargetException
-  caused by java.lang.IllegalAccessError
-Calling Test2User.test():
-Caught java.lang.reflect.InvocationTargetException
-  caused by java.lang.IncompatibleClassChangeError
-Calling Test2User2.test():
-Test2Base.foo()
-Calling Test3User.test():
-Caught java.lang.reflect.InvocationTargetException
-  caused by java.lang.IncompatibleClassChangeError
-Calling Test4User.test():
-Test4Derived@...
-Calling Test5User.test():
-Test5Derived.foo()
-Calling Test5User2.test():
-Caught java.lang.reflect.InvocationTargetException
-  caused by java.lang.IncompatibleClassChangeError
-Calling Test6User.test():
-Test6Derived@...
-Calling Test6User2.test():
-Caught java.lang.reflect.InvocationTargetException
-  caused by java.lang.IncompatibleClassChangeError
-Calling Test7User.test():
-Test7Interface.foo()
-Calling Test7User2.test():
-Caught java.lang.reflect.InvocationTargetException
-  caused by java.lang.IllegalAccessError
-Calling Test8User.test():
-Test8Derived.foo()
-Calling Test8User2.test():
-Caught java.lang.reflect.InvocationTargetException
-  caused by java.lang.IncompatibleClassChangeError
-Calling Test9User.test():
-Test9Derived.foo()
-Calling Test9User2.test():
-Caught java.lang.reflect.InvocationTargetException
-  caused by java.lang.IncompatibleClassChangeError
-Calling Test10User.test():
-Caught java.lang.reflect.InvocationTargetException
-  caused by java.lang.IncompatibleClassChangeError
diff --git a/test/162-method-resolution/jasmin/Test11User.j b/test/162-method-resolution/jasmin/Test11User.j
new file mode 100644
index 0000000..ded6e7a
--- /dev/null
+++ b/test/162-method-resolution/jasmin/Test11User.j
@@ -0,0 +1,25 @@
+; Copyright (C) 2021 The Android Open Source Project
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;      http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+
+.class public Test11User
+.super java/lang/Object
+
+.method public static test()V
+    .limit stack 2
+    .limit locals 2
+    new Test11Derived
+    ldc "Test"
+    invokespecial Test11Derived.<init>(Ljava/lang/String;)V
+    return
+.end method
diff --git a/test/162-method-resolution/src/Main.java b/test/162-method-resolution/src/Main.java
index 864c878..e0ad6b8 100644
--- a/test/162-method-resolution/src/Main.java
+++ b/test/162-method-resolution/src/Main.java
@@ -37,6 +37,7 @@
             test8();
             test9();
             test10();
+            test11();
 
             // TODO: How to test that interface method resolution returns the unique
             // maximally-specific non-abstract superinterface method if there is one?
@@ -291,14 +292,16 @@
      * and superinterfaces are included in the search. ART follows the JLS behavior.
      *
      * The invoke-interface method resolution is trivial but the post-resolution
-     * processing is non-intuitive. According to the JLS 15.12.4.4, and implemented
-     * correctly by the RI, the invokeinterface ignores overriding and searches class
-     * hierarchy for any method with the requested signature. Thus it finds the private
-     * Test7Base.foo()V and throws IllegalAccessError. Unfortunately, ART does not comply
-     * and simply calls Test7Interface.foo()V. Bug: 63624936.
+     * processing is non-intuitive. According to older versions of JLS 15.12.4.4, and
+     * implemented by older RI, the invokeinterface ignores overriding and searches
+     * class hierarchy for any method with the requested signature, finds the private
+     * Test7Base.foo()V and throws IllegalAccessError. However, newer versions of JLS
+     * limit the search to overriding methods, thus excluding private methods, and
+     * therefore find and call Test7Interface.foo()V just like ART. Bug: 63624936.
      *
      * Files:
      *   src/Test7User.java          - calls invoke-virtual Test7Derived.foo()V.
+     *   src/Test7User2.java         - calls invoke-interface Test7Interface.foo()V.
      *   src/Test7Base.java          - defines private foo()V.
      *   src/Test7Interface.java     - defines default foo()V.
      *   src/Test7Derived.java       - extends Test7Base, implements Test7Interface.
@@ -308,15 +311,10 @@
             // For RI, just print the expected output to hide the deliberate divergence.
             System.out.println("Calling Test7User.test():\n" +
                                "Test7Interface.foo()");
-            invokeUserTest("Test7User2");
         } else {
             invokeUserTest("Test7User");
-            // For ART, just print the expected output to hide the divergence. Bug: 63624936.
-            // The expected.txt lists the desired behavior, not the current behavior.
-            System.out.println("Calling Test7User2.test():\n" +
-                               "Caught java.lang.reflect.InvocationTargetException\n" +
-                               "  caused by java.lang.IllegalAccessError");
         }
+        invokeUserTest("Test7User2");
     }
 
     /*
@@ -379,12 +377,12 @@
 
     /*
      * Test10
-     * -----
+     * ------
      * Tested function:
      *     public class Test10Base implements Test10Interface { }
      *     public interface Test10Interface { }
      * Tested invokes:
-     *     invoke-interface Test10Interface.clone()Ljava/lang/Object; from Test10Caller in first dex
+     *     invoke-interface Test10Interface.clone()Ljava/lang/Object; from Test10User in first dex
      *         TODO b/64274113 This should throw a NSME (JLS 13.4.12) but actually throws an ICCE.
      *         expected: Throws NoSuchMethodError (JLS 13.4.12)
      *         actual: Throws IncompatibleClassChangeError
@@ -394,12 +392,51 @@
      * 13.4.12 is expected to be binary incompatible and throw a NoSuchMethodError.
      *
      * Files:
+     *   src/Test10Interface.java     - defines empty interface
      *   jasmin/Test10Base.j          - implements Test10Interface
-     *   jasmin/Test10Interface.java  - defines empty interface
      *   jasmin/Test10User.j          - invokeinterface Test10Interface.clone()Ljava/lang/Object;
      */
     private static void test10() throws Exception {
-        invokeUserTest("Test10User");
+        if (usingRI) {
+            // For RI, just print the expected output to hide the divergence.
+            System.out.println("Calling Test10User.test():\n" +
+                               "Caught java.lang.reflect.InvocationTargetException\n" +
+                               "  caused by java.lang.IncompatibleClassChangeError");
+        } else {
+            invokeUserTest("Test10User");
+        }
+    }
+
+    /*
+     * Test11
+     * ------
+     * Tested function:
+     *     public class Test11Base {
+     *         Test11Base(String) { ... }
+     *     }
+     *     public class Test11Derived extends Test11Base {
+     *         Test11Derived() { Test11Base("Test"); }
+     *     }
+     * Tested invokes:
+     *     invoke-direct Test11Derived.<init>(Ljava/lang/String;)V from Test11User in first dex
+     *         TODO b/183485797 This should throw a NSME (constructors are never inherited, JLS 8.8)
+     *                          but actually calls the superclass constructor.
+     *         expected: Throws NoSuchMethodError
+     *         actual: Successful construction of a Test11Derived instance.
+     *
+     * Files:
+     *   src/Test11Base.java          - defines Test11Base with <init>(Ljava/lang/String;)V
+     *   src/Test11Derived.java       - defines Test11Derived with <init>()V
+     *   jasmin/Test11User.j          - invokespecial Test11Derived.<init>(Ljava/lang/String;)V
+     */
+    private static void test11() throws Exception {
+        if (usingRI) {
+            // For RI, just print the expected output to hide the divergence for now.
+            System.out.println("Calling Test11User.test():\n" +
+                               "Test11Base.<init>(\"Test\")");
+        } else {
+            invokeUserTest("Test11User");
+        }
     }
 
     private static void invokeUserTest(String userName) throws Exception {
diff --git a/test/162-method-resolution/src/Test11Base.java b/test/162-method-resolution/src/Test11Base.java
new file mode 100644
index 0000000..20fab3a
--- /dev/null
+++ b/test/162-method-resolution/src/Test11Base.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 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 Test11Base {
+    Test11Base(String message) {
+        System.out.println("Test11Base.<init>(\"" + message + "\")");
+    }
+}
diff --git a/test/162-method-resolution/src/Test11Derived.java b/test/162-method-resolution/src/Test11Derived.java
new file mode 100644
index 0000000..ab0e8ae
--- /dev/null
+++ b/test/162-method-resolution/src/Test11Derived.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 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 Test11Derived extends Test11Base {
+    Test11Derived() {
+        super("Test11Derived");
+    }
+}
diff --git a/test/163-app-image-methods/Android.bp b/test/163-app-image-methods/Android.bp
new file mode 100644
index 0000000..5737662
--- /dev/null
+++ b/test/163-app-image-methods/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `163-app-image-methods`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-163-app-image-methods",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-163-app-image-methods-expected-stdout",
+        ":art-run-test-163-app-image-methods-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-163-app-image-methods-expected-stdout",
+    out: ["art-run-test-163-app-image-methods-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-163-app-image-methods-expected-stderr",
+    out: ["art-run-test-163-app-image-methods-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/160-read-barrier-stress/expected.txt b/test/163-app-image-methods/expected-stderr.txt
similarity index 100%
copy from test/160-read-barrier-stress/expected.txt
copy to test/163-app-image-methods/expected-stderr.txt
diff --git a/test/163-app-image-methods/expected.txt b/test/163-app-image-methods/expected-stdout.txt
similarity index 100%
rename from test/163-app-image-methods/expected.txt
rename to test/163-app-image-methods/expected-stdout.txt
diff --git a/test/163-app-image-methods/src/Main.java b/test/163-app-image-methods/src/Main.java
index 33590fc..2b57634 100644
--- a/test/163-app-image-methods/src/Main.java
+++ b/test/163-app-image-methods/src/Main.java
@@ -62,9 +62,30 @@
         }
     }
 
+    private static int exhaustJavaHeap(Object[] data, int index, int size) {
+        Runtime.getRuntime().gc();
+        // Let out-of-bound exception be thrown if we go past the array length. This should
+        // never happen if the logic in the caller is right. The exception acts as an assertion.
+        while (size != 0) {
+            try {
+                data[index] = new byte[size];
+                ++index;
+            } catch (OutOfMemoryError oome) {
+                size /= 2;
+            }
+        }
+        return index;
+    }
+
     public static Object eatAllMemory() {
       Object[] result = null;
       int size = 1000000;
+      // Make sure that there is no reclaimable memory in the heap. Otherwise we may throw
+      // OOME to prevent GC thrashing, even if later allocations may succeed.
+      Runtime.getRuntime().gc();
+      System.runFinalization();
+      // NOTE: There is a GC invocation in exhaustJavaHeap. So we don't need one here.
+
       while (result == null && size != 0) {
           try {
               result = new Object[size];
@@ -74,14 +95,10 @@
       }
       if (result != null) {
           int index = 0;
-          while (index != result.length && size != 0) {
-              try {
-                  result[index] = new byte[size];
-                  ++index;
-              } catch (OutOfMemoryError oome) {
-                  size /= 2;
-              }
-          }
+          // Repeat to ensure there is no space left on the heap.
+          index = exhaustJavaHeap(result, index, size);
+          index = exhaustJavaHeap(result, index, /*size*/ 4);
+          index = exhaustJavaHeap(result, index, /*size*/ 4);
       }
       return result;
   }
diff --git a/test/122-npe/expected.txt b/test/164-resolution-trampoline-dex-cache/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/164-resolution-trampoline-dex-cache/expected-stderr.txt
diff --git a/test/164-resolution-trampoline-dex-cache/expected.txt b/test/164-resolution-trampoline-dex-cache/expected-stdout.txt
similarity index 100%
rename from test/164-resolution-trampoline-dex-cache/expected.txt
rename to test/164-resolution-trampoline-dex-cache/expected-stdout.txt
diff --git a/test/165-lock-owner-proxy/Android.bp b/test/165-lock-owner-proxy/Android.bp
new file mode 100644
index 0000000..dc30150
--- /dev/null
+++ b/test/165-lock-owner-proxy/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `165-lock-owner-proxy`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-165-lock-owner-proxy",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-165-lock-owner-proxy-expected-stdout",
+        ":art-run-test-165-lock-owner-proxy-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-165-lock-owner-proxy-expected-stdout",
+    out: ["art-run-test-165-lock-owner-proxy-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-165-lock-owner-proxy-expected-stderr",
+    out: ["art-run-test-165-lock-owner-proxy-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/165-lock-owner-proxy/expected.txt b/test/165-lock-owner-proxy/expected-stderr.txt
similarity index 100%
rename from test/165-lock-owner-proxy/expected.txt
rename to test/165-lock-owner-proxy/expected-stderr.txt
diff --git a/test/165-lock-owner-proxy/expected.txt b/test/165-lock-owner-proxy/expected-stdout.txt
similarity index 100%
copy from test/165-lock-owner-proxy/expected.txt
copy to test/165-lock-owner-proxy/expected-stdout.txt
diff --git a/test/551-invoke-super/expected.txt b/test/166-bad-interface-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/166-bad-interface-super/expected-stderr.txt
diff --git a/test/166-bad-interface-super/expected.txt b/test/166-bad-interface-super/expected-stdout.txt
similarity index 100%
rename from test/166-bad-interface-super/expected.txt
rename to test/166-bad-interface-super/expected-stdout.txt
diff --git a/test/167-visit-locks/expected-stderr.txt b/test/167-visit-locks/expected-stderr.txt
new file mode 100644
index 0000000..802c8d9
--- /dev/null
+++ b/test/167-visit-locks/expected-stderr.txt
@@ -0,0 +1,2 @@
+First
+Second
diff --git a/test/139-register-natives/expected.txt b/test/167-visit-locks/expected-stdout.txt
similarity index 100%
copy from test/139-register-natives/expected.txt
copy to test/167-visit-locks/expected-stdout.txt
diff --git a/test/167-visit-locks/expected.txt b/test/167-visit-locks/expected.txt
deleted file mode 100644
index 5157c64..0000000
--- a/test/167-visit-locks/expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-JNI_OnLoad called
-First
-Second
diff --git a/test/168-vmstack-annotated/Android.bp b/test/168-vmstack-annotated/Android.bp
new file mode 100644
index 0000000..34f22d8
--- /dev/null
+++ b/test/168-vmstack-annotated/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `168-vmstack-annotated`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-168-vmstack-annotated",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-168-vmstack-annotated-expected-stdout",
+        ":art-run-test-168-vmstack-annotated-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-168-vmstack-annotated-expected-stdout",
+    out: ["art-run-test-168-vmstack-annotated-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-168-vmstack-annotated-expected-stderr",
+    out: ["art-run-test-168-vmstack-annotated-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/168-vmstack-annotated/expected.txt b/test/168-vmstack-annotated/expected-stderr.txt
similarity index 100%
rename from test/168-vmstack-annotated/expected.txt
rename to test/168-vmstack-annotated/expected-stderr.txt
diff --git a/test/168-vmstack-annotated/expected.txt b/test/168-vmstack-annotated/expected-stdout.txt
similarity index 100%
copy from test/168-vmstack-annotated/expected.txt
copy to test/168-vmstack-annotated/expected-stdout.txt
diff --git a/test/169-threadgroup-jni/Android.bp b/test/169-threadgroup-jni/Android.bp
new file mode 100644
index 0000000..a0fb5e9
--- /dev/null
+++ b/test/169-threadgroup-jni/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `169-threadgroup-jni`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-169-threadgroup-jni",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-169-threadgroup-jni-expected-stdout",
+        ":art-run-test-169-threadgroup-jni-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-169-threadgroup-jni-expected-stdout",
+    out: ["art-run-test-169-threadgroup-jni-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-169-threadgroup-jni-expected-stderr",
+    out: ["art-run-test-169-threadgroup-jni-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/114-ParallelGC/expected.txt b/test/169-threadgroup-jni/expected-stderr.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/169-threadgroup-jni/expected-stderr.txt
diff --git a/test/169-threadgroup-jni/expected.txt b/test/169-threadgroup-jni/expected-stdout.txt
similarity index 100%
rename from test/169-threadgroup-jni/expected.txt
rename to test/169-threadgroup-jni/expected-stdout.txt
diff --git a/test/170-interface-init/Android.bp b/test/170-interface-init/Android.bp
new file mode 100644
index 0000000..60d5e49
--- /dev/null
+++ b/test/170-interface-init/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `170-interface-init`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-170-interface-init",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-170-interface-init-expected-stdout",
+        ":art-run-test-170-interface-init-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-170-interface-init-expected-stdout",
+    out: ["art-run-test-170-interface-init-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-170-interface-init-expected-stderr",
+    out: ["art-run-test-170-interface-init-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/551-checker-clinit/expected.txt b/test/170-interface-init/expected-stderr.txt
similarity index 100%
copy from test/551-checker-clinit/expected.txt
copy to test/170-interface-init/expected-stderr.txt
diff --git a/test/170-interface-init/expected.txt b/test/170-interface-init/expected-stdout.txt
similarity index 100%
rename from test/170-interface-init/expected.txt
rename to test/170-interface-init/expected-stdout.txt
diff --git a/test/122-npe/expected.txt b/test/171-init-aste/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/171-init-aste/expected-stderr.txt
diff --git a/test/171-init-aste/expected.txt b/test/171-init-aste/expected-stdout.txt
similarity index 100%
rename from test/171-init-aste/expected.txt
rename to test/171-init-aste/expected-stdout.txt
diff --git a/test/172-app-image-twice/Android.bp b/test/172-app-image-twice/Android.bp
new file mode 100644
index 0000000..be8d202
--- /dev/null
+++ b/test/172-app-image-twice/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `172-app-image-twice`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-172-app-image-twice",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-172-app-image-twice-expected-stdout",
+        ":art-run-test-172-app-image-twice-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-172-app-image-twice-expected-stdout",
+    out: ["art-run-test-172-app-image-twice-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-172-app-image-twice-expected-stderr",
+    out: ["art-run-test-172-app-image-twice-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/172-app-image-twice/check b/test/172-app-image-twice/check
index 26a97a4..228bcb5 100755
--- a/test/172-app-image-twice/check
+++ b/test/172-app-image-twice/check
@@ -14,5 +14,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Remove all lines not containing "passed".
-grep "^passed" "$2" | diff --strip-trailing-cr -q "$1" - >/dev/null
+grep "^passed" "$2" | diff --strip-trailing-cr -q "$1" - >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4" >/dev/null
diff --git a/test/122-npe/expected.txt b/test/172-app-image-twice/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/172-app-image-twice/expected-stderr.txt
diff --git a/test/172-app-image-twice/expected.txt b/test/172-app-image-twice/expected-stdout.txt
similarity index 100%
rename from test/172-app-image-twice/expected.txt
rename to test/172-app-image-twice/expected-stdout.txt
diff --git a/test/172-app-image-twice/run b/test/172-app-image-twice/run
index aa28190..2987b4b 100644
--- a/test/172-app-image-twice/run
+++ b/test/172-app-image-twice/run
@@ -14,15 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Build an app image with TestClass (specified by profile) and class loader
-# context that skips the duplicate class checks.
+# Build an app image with TestClass (specified by profile).
 
-# Target and host use a different shell, and we need to special case the
-# passing of the class loader context marker.
-if [[ "$@" = *" --host "* ]]; then
-  ${RUN} $@ --profile -Xcompiler-option --compiler-filter=speed-profile \
-      -Xcompiler-option --class-loader-context=\&
-else
-  ${RUN} $@ --profile -Xcompiler-option --compiler-filter=speed-profile \
-      -Xcompiler-option '--class-loader-context=\&'
-fi
+${RUN} $@ --profile -Xcompiler-option --compiler-filter=speed-profile
diff --git a/test/477-checker-bound-type/expected.txt b/test/173-missing-field-type/expected-stderr.txt
similarity index 100%
copy from test/477-checker-bound-type/expected.txt
copy to test/173-missing-field-type/expected-stderr.txt
diff --git a/test/477-checker-bound-type/expected.txt b/test/173-missing-field-type/expected-stdout.txt
similarity index 100%
copy from test/477-checker-bound-type/expected.txt
copy to test/173-missing-field-type/expected-stdout.txt
diff --git a/test/173-missing-field-type/expected.txt b/test/173-missing-field-type/expected.txt
deleted file mode 100644
index b0aad4d..0000000
--- a/test/173-missing-field-type/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-passed
diff --git a/test/173-missing-field-type/smali/BadField.smali b/test/173-missing-field-type/smali/BadField.smali
index 851e8fe..7593983 100644
--- a/test/173-missing-field-type/smali/BadField.smali
+++ b/test/173-missing-field-type/smali/BadField.smali
@@ -16,8 +16,9 @@
 .class public LBadField;
 .super Ljava/lang/Object;
 
-# This is a bad field since there is no class Widget in this test.
+# These are bad fields since there is no class Widget in this test.
 .field public static widget:LWidget;
+.field public iwidget:LWidget;
 
 .method public constructor <init>()V
     .registers 2
@@ -25,10 +26,36 @@
     return-void
 .end method
 
-.method public static constructor <clinit>()V
+.method public static storeStaticObject()V
     .registers 1
     new-instance v0, Ljava/lang/Object;
     invoke-direct {v0}, Ljava/lang/Object;-><init>()V
     sput-object v0, LBadField;->widget:LWidget;
     return-void
-.end method
\ No newline at end of file
+.end method
+
+.method public static storeStaticNull()V
+    .registers 1
+    const/4 v0, 0
+    sput-object v0, LBadField;->widget:LWidget;
+    return-void
+.end method
+
+.method public static storeInstanceObject()V
+    .registers 2
+    new-instance v1, LBadField;
+    invoke-direct {v1}, LBadField;-><init>()V
+    new-instance v0, Ljava/lang/Object;
+    invoke-direct {v0}, Ljava/lang/Object;-><init>()V
+    iput-object v0, v1, LBadField;->iwidget:LWidget;
+    return-void
+.end method
+
+.method public static storeInstanceNull()V
+    .registers 2
+    new-instance v1, LBadField;
+    invoke-direct {v1}, LBadField;-><init>()V
+    const/4 v0, 0
+    iput-object v0, v1, LBadField;->iwidget:LWidget;
+    return-void
+.end method
diff --git a/test/173-missing-field-type/smali/BadFieldGet.smali b/test/173-missing-field-type/smali/BadFieldGet.smali
new file mode 100644
index 0000000..9e9d948
--- /dev/null
+++ b/test/173-missing-field-type/smali/BadFieldGet.smali
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LBadFieldGet;
+.super Ljava/lang/Object;
+
+# These are bad fields since there is no class Widget in this test.
+.field public static widget:LWidget;
+
+.method public constructor <init>()V
+    .registers 2
+    invoke-direct {v1}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method
+
+.method public static loadStatic()Ljava/lang/Object;
+    .registers 1
+    # Put an object in the register used for sget-object, the bug in mterp checked it was
+    # non-null.
+    new-instance v0, LBadFieldGet;
+    invoke-direct {v0}, LBadFieldGet;-><init>()V
+    sget-object v0, LBadField;->widget:LWidget;
+    return-object v0
+.end method
+
+.method public static forceAccessChecks()V
+    .registers 0
+    invoke-static {}, LMain;->privateMethod()V
+    return-void
+.end method
diff --git a/test/173-missing-field-type/src-art/Main.java b/test/173-missing-field-type/src-art/Main.java
index 61bb918..35dbbea 100644
--- a/test/173-missing-field-type/src-art/Main.java
+++ b/test/173-missing-field-type/src-art/Main.java
@@ -14,21 +14,47 @@
  * limitations under the License.
  */
 
+import java.lang.reflect.InvocationTargetException;
 
 public class Main {
     public static void main(String[] args) throws Throwable {
+        // Class BadField is defined in BadField.smali.
+        Class<?> c = Class.forName("BadField");
+
+        // Storing null is OK.
+        c.getMethod("storeStaticNull").invoke(null);
+        c.getMethod("storeInstanceNull").invoke(null);
+
+        // Storing anything else should throw an exception.
+        testStoreObject(c, "storeStaticObject");
+        testStoreObject(c, "storeInstanceObject");
+
+        // Loading is OK.
+        c = Class.forName("BadFieldGet");
+        testLoadObject(c, "loadStatic");
+    }
+
+    public static void testLoadObject(Class<?> c, String methodName) throws Throwable {
+      c.getMethod(methodName).invoke(null);
+    }
+
+    public static void testStoreObject(Class<?> c, String methodName) throws Throwable {
         try {
-            // Class BadField is defined in BadField.smali.
-            Class<?> c = Class.forName("BadField");
-            System.out.println("Not reached");
-            c.newInstance();
-        } catch (NoClassDefFoundError expected) {
+          c.getMethod(methodName).invoke(null);
+          throw new Error("Expected NoClassDefFoundError");
+        } catch (InvocationTargetException expected) {
+          Throwable e = expected.getCause();
+          if (e instanceof NoClassDefFoundError) {
             // The NoClassDefFoundError is for the field widget in class BadField.
-            if (expected.getMessage().equals("Failed resolution of: LWidget;")) {
-                System.out.println("passed");
-            } else {
-                System.out.println("failed: " + expected.getMessage());
+            if (!e.getMessage().equals("Failed resolution of: LWidget;")) {
+                throw new Error("Unexpected " + e);
             }
+          } else {
+            throw new Error("Unexpected " + e);
+          }
         }
     }
+
+    private static void privateMethod() {
+    }
 }
diff --git a/test/173-missing-field-type/src/Main.java b/test/173-missing-field-type/src/Main.java
index 172d6a6..b821c96 100644
--- a/test/173-missing-field-type/src/Main.java
+++ b/test/173-missing-field-type/src/Main.java
@@ -17,6 +17,5 @@
 public class Main {
     // Allow test to pass on RI without adding to knownfailures.json file.
     public static void main(String args[]) throws Exception {
-        System.out.println("passed");
     }
 }
diff --git a/test/174-escaping-instance-of-bad-class/Android.bp b/test/174-escaping-instance-of-bad-class/Android.bp
new file mode 100644
index 0000000..f319930
--- /dev/null
+++ b/test/174-escaping-instance-of-bad-class/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `174-escaping-instance-of-bad-class`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-174-escaping-instance-of-bad-class",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-174-escaping-instance-of-bad-class-expected-stdout",
+        ":art-run-test-174-escaping-instance-of-bad-class-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-174-escaping-instance-of-bad-class-expected-stdout",
+    out: ["art-run-test-174-escaping-instance-of-bad-class-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-174-escaping-instance-of-bad-class-expected-stderr",
+    out: ["art-run-test-174-escaping-instance-of-bad-class-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/519-bound-load-class/expected.txt b/test/174-escaping-instance-of-bad-class/expected-stderr.txt
similarity index 100%
copy from test/519-bound-load-class/expected.txt
copy to test/174-escaping-instance-of-bad-class/expected-stderr.txt
diff --git a/test/174-escaping-instance-of-bad-class/expected-stdout.txt b/test/174-escaping-instance-of-bad-class/expected-stdout.txt
new file mode 100644
index 0000000..4da6a09
--- /dev/null
+++ b/test/174-escaping-instance-of-bad-class/expected-stdout.txt
@@ -0,0 +1,21 @@
+Bad.foo()
+Bad.instanceValue = 33
+Caught NoClassDefFoundError.
+Bad.bar()
+Caught NoClassDefFoundError.
+Bad.$noinline$testResolutionTrampolineCallee()
+BadSuper.foo()
+BadSuper.superInstanceValue = 1
+Caught NoClassDefFoundError.
+BadSub.bar()
+BadSub.subInstanceValue = 11
+BadSub.subStaticValue = 4242
+BadSuper.superInstanceValue = 111
+Caught NoClassDefFoundError.
+BadSub.bar()
+BadSub.subInstanceValue = -1
+BadSub.subStaticValue = 4242
+BadSuper.superInstanceValue = -2
+Caught NoClassDefFoundError.
+BadSub.allocSuper(.)
+Caught NoClassDefFoundError.
diff --git a/test/174-escaping-instance-of-bad-class/expected.txt b/test/174-escaping-instance-of-bad-class/expected.txt
deleted file mode 100644
index 611d698..0000000
--- a/test/174-escaping-instance-of-bad-class/expected.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Bad.foo()
-Bad.instanceValue = 33
-Caught NoClassDefFoundError.
-Bad.bar()
-Caught NoClassDefFoundError.
-BadSuper.foo()
-BadSuper.superInstanceValue = 1
-Caught NoClassDefFoundError.
-BadSub.bar()
-BadSub.subInstanceValue = 11
-BadSub.subStaticValue = 4242
-BadSuper.superInstanceValue = 111
-Caught NoClassDefFoundError.
-BadSub.bar()
-BadSub.subInstanceValue = -1
-BadSub.subStaticValue = 4242
-BadSuper.superInstanceValue = -2
-Caught NoClassDefFoundError.
-BadSub.allocSuper(.)
-Caught NoClassDefFoundError.
diff --git a/test/174-escaping-instance-of-bad-class/src/Main.java b/test/174-escaping-instance-of-bad-class/src/Main.java
index 4f66a31..cee978a 100644
--- a/test/174-escaping-instance-of-bad-class/src/Main.java
+++ b/test/174-escaping-instance-of-bad-class/src/Main.java
@@ -50,6 +50,9 @@
         ncdfe.printStackTrace();
       }
     }
+
+    // Test that we handle bad instance correctly in the resolution trampoline.
+    bad.$noinline$testResolutionTrampoline();
   }
 
   public static void hierarchyTest() {
@@ -141,6 +144,15 @@
       return Bad.staticValue;
     }
   }
+
+  public void $noinline$testResolutionTrampoline() {
+    // The first call to private method uses the resolution trampoline when AOT-compiled.
+    $noinline$testResolutionTrampolineCallee();
+  }
+
+  private void $noinline$testResolutionTrampolineCallee() {
+    System.out.println("Bad.$noinline$testResolutionTrampolineCallee()");
+  }
 }
 
 class BadSuper {
diff --git a/test/175-alloc-big-bignums/Android.bp b/test/175-alloc-big-bignums/Android.bp
new file mode 100644
index 0000000..20ae278
--- /dev/null
+++ b/test/175-alloc-big-bignums/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `175-alloc-big-bignums`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-175-alloc-big-bignums",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-175-alloc-big-bignums-expected-stdout",
+        ":art-run-test-175-alloc-big-bignums-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-175-alloc-big-bignums-expected-stdout",
+    out: ["art-run-test-175-alloc-big-bignums-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-175-alloc-big-bignums-expected-stderr",
+    out: ["art-run-test-175-alloc-big-bignums-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/175-alloc-big-bignums/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/175-alloc-big-bignums/expected-stderr.txt
diff --git a/test/175-alloc-big-bignums/expected.txt b/test/175-alloc-big-bignums/expected-stdout.txt
similarity index 100%
rename from test/175-alloc-big-bignums/expected.txt
rename to test/175-alloc-big-bignums/expected-stdout.txt
diff --git a/test/176-app-image-string/Android.bp b/test/176-app-image-string/Android.bp
new file mode 100644
index 0000000..3dae355
--- /dev/null
+++ b/test/176-app-image-string/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `176-app-image-string`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-176-app-image-string",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-176-app-image-string-expected-stdout",
+        ":art-run-test-176-app-image-string-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-176-app-image-string-expected-stdout",
+    out: ["art-run-test-176-app-image-string-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-176-app-image-string-expected-stderr",
+    out: ["art-run-test-176-app-image-string-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/304-method-tracing/expected.txt b/test/176-app-image-string/expected-stderr.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/176-app-image-string/expected-stderr.txt
diff --git a/test/176-app-image-string/expected.txt b/test/176-app-image-string/expected-stdout.txt
similarity index 100%
rename from test/176-app-image-string/expected.txt
rename to test/176-app-image-string/expected-stdout.txt
diff --git a/test/177-visibly-initialized-deadlock/Android.bp b/test/177-visibly-initialized-deadlock/Android.bp
new file mode 100644
index 0000000..2b7106b
--- /dev/null
+++ b/test/177-visibly-initialized-deadlock/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `177-visibly-initialized-deadlock`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-177-visibly-initialized-deadlock",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-177-visibly-initialized-deadlock-expected-stdout",
+        ":art-run-test-177-visibly-initialized-deadlock-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-177-visibly-initialized-deadlock-expected-stdout",
+    out: ["art-run-test-177-visibly-initialized-deadlock-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-177-visibly-initialized-deadlock-expected-stderr",
+    out: ["art-run-test-177-visibly-initialized-deadlock-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/479-regression-implicit-null-check/expected.txt b/test/177-visibly-initialized-deadlock/expected-stderr.txt
similarity index 100%
copy from test/479-regression-implicit-null-check/expected.txt
copy to test/177-visibly-initialized-deadlock/expected-stderr.txt
diff --git a/test/177-visibly-initialized-deadlock/expected.txt b/test/177-visibly-initialized-deadlock/expected-stdout.txt
similarity index 100%
rename from test/177-visibly-initialized-deadlock/expected.txt
rename to test/177-visibly-initialized-deadlock/expected-stdout.txt
diff --git a/test/178-app-image-native-method/Android.bp b/test/178-app-image-native-method/Android.bp
new file mode 100644
index 0000000..2757eb7
--- /dev/null
+++ b/test/178-app-image-native-method/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `178-app-image-native-method`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-178-app-image-native-method",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-178-app-image-native-method-expected-stdout",
+        ":art-run-test-178-app-image-native-method-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-178-app-image-native-method-expected-stdout",
+    out: ["art-run-test-178-app-image-native-method-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-178-app-image-native-method-expected-stderr",
+    out: ["art-run-test-178-app-image-native-method-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/178-app-image-native-method/check b/test/178-app-image-native-method/check
index 5336295..45d3654 100755
--- a/test/178-app-image-native-method/check
+++ b/test/178-app-image-native-method/check
@@ -14,5 +14,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Filter out error messages for missing native methods.
-grep -v 'No implementation found for ' "$2" | diff -q "$1" - >/dev/null
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && grep -v 'No implementation found for ' "$4" | diff -q "$3" - >/dev/null
diff --git a/test/470-huge-method/expected.txt b/test/178-app-image-native-method/expected-stderr.txt
similarity index 100%
copy from test/470-huge-method/expected.txt
copy to test/178-app-image-native-method/expected-stderr.txt
diff --git a/test/178-app-image-native-method/expected-stdout.txt b/test/178-app-image-native-method/expected-stdout.txt
new file mode 100644
index 0000000..c6014b6
--- /dev/null
+++ b/test/178-app-image-native-method/expected-stdout.txt
@@ -0,0 +1,36 @@
+JNI_OnLoad called
+test
+testFast
+testCritical
+testMissing
+testMissingFast
+testMissingCritical
+testCriticalSignatures
+test
+testFast
+testCritical
+testMissing
+testMissingFast
+testMissingCritical
+testCriticalSignatures
+testCriticalClinitCheck passed
+initializingCriticalClinitCheck finished
+testCriticalClinitCheck passed
+JNI_OnLoad called
+test
+testFast
+testCritical
+testMissing
+testMissingFast
+testMissingCritical
+testCriticalSignatures
+test
+testFast
+testCritical
+testMissing
+testMissingFast
+testMissingCritical
+testCriticalSignatures
+testCriticalClinitCheck passed
+initializingCriticalClinitCheck finished
+testCriticalClinitCheck passed
diff --git a/test/178-app-image-native-method/expected.txt b/test/178-app-image-native-method/expected.txt
deleted file mode 100644
index 30cc336..0000000
--- a/test/178-app-image-native-method/expected.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-JNI_OnLoad called
-test
-testFast
-testCritical
-testMissing
-testMissingFast
-testMissingCritical
-JNI_OnLoad called
-test
-testFast
-testCritical
-testMissing
-testMissingFast
-testMissingCritical
diff --git a/test/178-app-image-native-method/native_methods.cc b/test/178-app-image-native-method/native_methods.cc
index 794a78a..709c5df 100644
--- a/test/178-app-image-native-method/native_methods.cc
+++ b/test/178-app-image-native-method/native_methods.cc
@@ -14,8 +14,16 @@
  * limitations under the License.
  */
 
+#include <sstream>
+
 #include "jni.h"
 
+#include "arch/context.h"
+#include "monitor.h"
+#include "scoped_thread_state_change-inl.h"
+#include "stack.h"
+#include "thread-current-inl.h"
+
 namespace art {
 
 static inline bool VerifyManyParameters(
@@ -127,4 +135,571 @@
   return ok ? 42 : -1;
 }
 
+extern "C" JNIEXPORT jint JNICALL Java_CriticalSignatures_nativeILFFFFD(
+    jint i,
+    jlong l,
+    jfloat f1,
+    jfloat f2,
+    jfloat f3,
+    jfloat f4,
+    jdouble d) {
+  if (i != 1) return -1;
+  if (l != INT64_C(0xf00000002)) return -2;
+  if (f1 != 3.0f) return -3;
+  if (f2 != 4.0f) return -4;
+  if (f3 != 5.0f) return -5;
+  if (f4 != 6.0f) return -6;
+  if (d != 7.0) return -7;
+  return 42;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_CriticalSignatures_nativeLIFFFFD(
+    jlong l,
+    jint i,
+    jfloat f1,
+    jfloat f2,
+    jfloat f3,
+    jfloat f4,
+    jdouble d) {
+  if (l != INT64_C(0xf00000007)) return -1;
+  if (i != 6) return -2;
+  if (f1 != 5.0f) return -3;
+  if (f2 != 4.0f) return -4;
+  if (f3 != 3.0f) return -5;
+  if (f4 != 2.0f) return -6;
+  if (d != 1.0) return -7;
+  return 42;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_CriticalSignatures_nativeFLIFFFD(
+    jfloat f1,
+    jlong l,
+    jint i,
+    jfloat f2,
+    jfloat f3,
+    jfloat f4,
+    jdouble d) {
+  if (f1 != 1.0f) return -3;
+  if (l != INT64_C(0xf00000002)) return -1;
+  if (i != 3) return -2;
+  if (f2 != 4.0f) return -4;
+  if (f3 != 5.0f) return -5;
+  if (f4 != 6.0f) return -6;
+  if (d != 7.0) return -7;
+  return 42;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_CriticalSignatures_nativeDDIIIIII(
+    jdouble d1,
+    jdouble d2,
+    jint i1,
+    jint i2,
+    jint i3,
+    jint i4,
+    jint i5,
+    jint i6) {
+  if (d1 != 8.0) return -1;
+  if (d2 != 7.0) return -2;
+  if (i1 != 6) return -3;
+  if (i2 != 5) return -4;
+  if (i3 != 4) return -5;
+  if (i4 != 3) return -6;
+  if (i5 != 2) return -7;
+  if (i6 != 1) return -8;
+  return 42;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_CriticalSignatures_nativeDFFILIII(
+    jdouble d,
+    jfloat f1,
+    jfloat f2,
+    jint i1,
+    jlong l,
+    jint i2,
+    jint i3,
+    jint i4) {
+  if (d != 1.0) return -1;
+  if (f1 != 2.0f) return -2;
+  if (f2 != 3.0f) return -3;
+  if (i1 != 4) return -4;
+  if (l != INT64_C(0xf00000005)) return -5;
+  if (i2 != 6) return -6;
+  if (i3 != 7) return -7;
+  if (i4 != 8) return -8;
+  return 42;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_CriticalSignatures_nativeDDFILIII(
+    jdouble d1,
+    jdouble d2,
+    jfloat f,
+    jint i1,
+    jlong l,
+    jint i2,
+    jint i3,
+    jint i4) {
+  if (d1 != 8.0) return -1;
+  if (d2 != 7.0) return -2;
+  if (f != 6.0f) return -3;
+  if (i1 != 5) return -4;
+  if (l != INT64_C(0xf00000004)) return -5;
+  if (i2 != 3) return -6;
+  if (i3 != 2) return -7;
+  if (i4 != 1) return -8;
+  return 42;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_CriticalSignatures_nativeDDIFII(
+    jdouble d1,
+    jdouble d2,
+    jint i1,
+    jfloat f,
+    jint i2,
+    jint i3) {
+  if (d1 != 1.0) return -1;
+  if (d2 != 2.0) return -2;
+  if (i1 != 3) return -3;
+  if (f != 4.0f) return -4;
+  if (i2 != 5) return -5;
+  if (i3 != 6) return -6;
+  return 42;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_CriticalSignatures_nativeFullArgs(
+    // Generated by script (then modified to close argument list):
+    //   for i in {0..84}; do echo "    jlong l$((i*3)),"; echo "    jint i$((i*3+2)),"; done
+    jlong l0,
+    jint i2,
+    jlong l3,
+    jint i5,
+    jlong l6,
+    jint i8,
+    jlong l9,
+    jint i11,
+    jlong l12,
+    jint i14,
+    jlong l15,
+    jint i17,
+    jlong l18,
+    jint i20,
+    jlong l21,
+    jint i23,
+    jlong l24,
+    jint i26,
+    jlong l27,
+    jint i29,
+    jlong l30,
+    jint i32,
+    jlong l33,
+    jint i35,
+    jlong l36,
+    jint i38,
+    jlong l39,
+    jint i41,
+    jlong l42,
+    jint i44,
+    jlong l45,
+    jint i47,
+    jlong l48,
+    jint i50,
+    jlong l51,
+    jint i53,
+    jlong l54,
+    jint i56,
+    jlong l57,
+    jint i59,
+    jlong l60,
+    jint i62,
+    jlong l63,
+    jint i65,
+    jlong l66,
+    jint i68,
+    jlong l69,
+    jint i71,
+    jlong l72,
+    jint i74,
+    jlong l75,
+    jint i77,
+    jlong l78,
+    jint i80,
+    jlong l81,
+    jint i83,
+    jlong l84,
+    jint i86,
+    jlong l87,
+    jint i89,
+    jlong l90,
+    jint i92,
+    jlong l93,
+    jint i95,
+    jlong l96,
+    jint i98,
+    jlong l99,
+    jint i101,
+    jlong l102,
+    jint i104,
+    jlong l105,
+    jint i107,
+    jlong l108,
+    jint i110,
+    jlong l111,
+    jint i113,
+    jlong l114,
+    jint i116,
+    jlong l117,
+    jint i119,
+    jlong l120,
+    jint i122,
+    jlong l123,
+    jint i125,
+    jlong l126,
+    jint i128,
+    jlong l129,
+    jint i131,
+    jlong l132,
+    jint i134,
+    jlong l135,
+    jint i137,
+    jlong l138,
+    jint i140,
+    jlong l141,
+    jint i143,
+    jlong l144,
+    jint i146,
+    jlong l147,
+    jint i149,
+    jlong l150,
+    jint i152,
+    jlong l153,
+    jint i155,
+    jlong l156,
+    jint i158,
+    jlong l159,
+    jint i161,
+    jlong l162,
+    jint i164,
+    jlong l165,
+    jint i167,
+    jlong l168,
+    jint i170,
+    jlong l171,
+    jint i173,
+    jlong l174,
+    jint i176,
+    jlong l177,
+    jint i179,
+    jlong l180,
+    jint i182,
+    jlong l183,
+    jint i185,
+    jlong l186,
+    jint i188,
+    jlong l189,
+    jint i191,
+    jlong l192,
+    jint i194,
+    jlong l195,
+    jint i197,
+    jlong l198,
+    jint i200,
+    jlong l201,
+    jint i203,
+    jlong l204,
+    jint i206,
+    jlong l207,
+    jint i209,
+    jlong l210,
+    jint i212,
+    jlong l213,
+    jint i215,
+    jlong l216,
+    jint i218,
+    jlong l219,
+    jint i221,
+    jlong l222,
+    jint i224,
+    jlong l225,
+    jint i227,
+    jlong l228,
+    jint i230,
+    jlong l231,
+    jint i233,
+    jlong l234,
+    jint i236,
+    jlong l237,
+    jint i239,
+    jlong l240,
+    jint i242,
+    jlong l243,
+    jint i245,
+    jlong l246,
+    jint i248,
+    jlong l249,
+    jint i251,
+    jlong l252,
+    jint i254) {
+  jlong l = INT64_C(0xf00000000);
+  // Generated by script (then modified to close argument list):
+  //   for i in {0..84}; do \
+  //     echo "  if (l$((i*3)) != l + $(($i*3))) return -$(($i*3));"; \
+  //     echo "  if (i$(($i*3+2)) != $(($i*3+2))) return -$(($i*3+2));"; \
+  //  done
+  if (l0 != l + 0) return -0;
+  if (i2 != 2) return -2;
+  if (l3 != l + 3) return -3;
+  if (i5 != 5) return -5;
+  if (l6 != l + 6) return -6;
+  if (i8 != 8) return -8;
+  if (l9 != l + 9) return -9;
+  if (i11 != 11) return -11;
+  if (l12 != l + 12) return -12;
+  if (i14 != 14) return -14;
+  if (l15 != l + 15) return -15;
+  if (i17 != 17) return -17;
+  if (l18 != l + 18) return -18;
+  if (i20 != 20) return -20;
+  if (l21 != l + 21) return -21;
+  if (i23 != 23) return -23;
+  if (l24 != l + 24) return -24;
+  if (i26 != 26) return -26;
+  if (l27 != l + 27) return -27;
+  if (i29 != 29) return -29;
+  if (l30 != l + 30) return -30;
+  if (i32 != 32) return -32;
+  if (l33 != l + 33) return -33;
+  if (i35 != 35) return -35;
+  if (l36 != l + 36) return -36;
+  if (i38 != 38) return -38;
+  if (l39 != l + 39) return -39;
+  if (i41 != 41) return -41;
+  if (l42 != l + 42) return -42;
+  if (i44 != 44) return -44;
+  if (l45 != l + 45) return -45;
+  if (i47 != 47) return -47;
+  if (l48 != l + 48) return -48;
+  if (i50 != 50) return -50;
+  if (l51 != l + 51) return -51;
+  if (i53 != 53) return -53;
+  if (l54 != l + 54) return -54;
+  if (i56 != 56) return -56;
+  if (l57 != l + 57) return -57;
+  if (i59 != 59) return -59;
+  if (l60 != l + 60) return -60;
+  if (i62 != 62) return -62;
+  if (l63 != l + 63) return -63;
+  if (i65 != 65) return -65;
+  if (l66 != l + 66) return -66;
+  if (i68 != 68) return -68;
+  if (l69 != l + 69) return -69;
+  if (i71 != 71) return -71;
+  if (l72 != l + 72) return -72;
+  if (i74 != 74) return -74;
+  if (l75 != l + 75) return -75;
+  if (i77 != 77) return -77;
+  if (l78 != l + 78) return -78;
+  if (i80 != 80) return -80;
+  if (l81 != l + 81) return -81;
+  if (i83 != 83) return -83;
+  if (l84 != l + 84) return -84;
+  if (i86 != 86) return -86;
+  if (l87 != l + 87) return -87;
+  if (i89 != 89) return -89;
+  if (l90 != l + 90) return -90;
+  if (i92 != 92) return -92;
+  if (l93 != l + 93) return -93;
+  if (i95 != 95) return -95;
+  if (l96 != l + 96) return -96;
+  if (i98 != 98) return -98;
+  if (l99 != l + 99) return -99;
+  if (i101 != 101) return -101;
+  if (l102 != l + 102) return -102;
+  if (i104 != 104) return -104;
+  if (l105 != l + 105) return -105;
+  if (i107 != 107) return -107;
+  if (l108 != l + 108) return -108;
+  if (i110 != 110) return -110;
+  if (l111 != l + 111) return -111;
+  if (i113 != 113) return -113;
+  if (l114 != l + 114) return -114;
+  if (i116 != 116) return -116;
+  if (l117 != l + 117) return -117;
+  if (i119 != 119) return -119;
+  if (l120 != l + 120) return -120;
+  if (i122 != 122) return -122;
+  if (l123 != l + 123) return -123;
+  if (i125 != 125) return -125;
+  if (l126 != l + 126) return -126;
+  if (i128 != 128) return -128;
+  if (l129 != l + 129) return -129;
+  if (i131 != 131) return -131;
+  if (l132 != l + 132) return -132;
+  if (i134 != 134) return -134;
+  if (l135 != l + 135) return -135;
+  if (i137 != 137) return -137;
+  if (l138 != l + 138) return -138;
+  if (i140 != 140) return -140;
+  if (l141 != l + 141) return -141;
+  if (i143 != 143) return -143;
+  if (l144 != l + 144) return -144;
+  if (i146 != 146) return -146;
+  if (l147 != l + 147) return -147;
+  if (i149 != 149) return -149;
+  if (l150 != l + 150) return -150;
+  if (i152 != 152) return -152;
+  if (l153 != l + 153) return -153;
+  if (i155 != 155) return -155;
+  if (l156 != l + 156) return -156;
+  if (i158 != 158) return -158;
+  if (l159 != l + 159) return -159;
+  if (i161 != 161) return -161;
+  if (l162 != l + 162) return -162;
+  if (i164 != 164) return -164;
+  if (l165 != l + 165) return -165;
+  if (i167 != 167) return -167;
+  if (l168 != l + 168) return -168;
+  if (i170 != 170) return -170;
+  if (l171 != l + 171) return -171;
+  if (i173 != 173) return -173;
+  if (l174 != l + 174) return -174;
+  if (i176 != 176) return -176;
+  if (l177 != l + 177) return -177;
+  if (i179 != 179) return -179;
+  if (l180 != l + 180) return -180;
+  if (i182 != 182) return -182;
+  if (l183 != l + 183) return -183;
+  if (i185 != 185) return -185;
+  if (l186 != l + 186) return -186;
+  if (i188 != 188) return -188;
+  if (l189 != l + 189) return -189;
+  if (i191 != 191) return -191;
+  if (l192 != l + 192) return -192;
+  if (i194 != 194) return -194;
+  if (l195 != l + 195) return -195;
+  if (i197 != 197) return -197;
+  if (l198 != l + 198) return -198;
+  if (i200 != 200) return -200;
+  if (l201 != l + 201) return -201;
+  if (i203 != 203) return -203;
+  if (l204 != l + 204) return -204;
+  if (i206 != 206) return -206;
+  if (l207 != l + 207) return -207;
+  if (i209 != 209) return -209;
+  if (l210 != l + 210) return -210;
+  if (i212 != 212) return -212;
+  if (l213 != l + 213) return -213;
+  if (i215 != 215) return -215;
+  if (l216 != l + 216) return -216;
+  if (i218 != 218) return -218;
+  if (l219 != l + 219) return -219;
+  if (i221 != 221) return -221;
+  if (l222 != l + 222) return -222;
+  if (i224 != 224) return -224;
+  if (l225 != l + 225) return -225;
+  if (i227 != 227) return -227;
+  if (l228 != l + 228) return -228;
+  if (i230 != 230) return -230;
+  if (l231 != l + 231) return -231;
+  if (i233 != 233) return -233;
+  if (l234 != l + 234) return -234;
+  if (i236 != 236) return -236;
+  if (l237 != l + 237) return -237;
+  if (i239 != 239) return -239;
+  if (l240 != l + 240) return -240;
+  if (i242 != 242) return -242;
+  if (l243 != l + 243) return -243;
+  if (i245 != 245) return -245;
+  if (l246 != l + 246) return -246;
+  if (i248 != 248) return -248;
+  if (l249 != l + 249) return -249;
+  if (i251 != 251) return -251;
+  if (l252 != l + 252) return -252;
+  if (i254 != 254) return -254;
+  return 42;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_CriticalClinitCheck_nativeMethodVoid() {
+  return 42;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_CriticalClinitCheck_nativeMethod(jint i) {
+  return i;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_CriticalClinitCheck_nativeMethodWithManyParameters(
+    jint i1, jlong l1, jfloat f1, jdouble d1,
+    jint i2, jlong l2, jfloat f2, jdouble d2,
+    jint i3, jlong l3, jfloat f3, jdouble d3,
+    jint i4, jlong l4, jfloat f4, jdouble d4,
+    jint i5, jlong l5, jfloat f5, jdouble d5,
+    jint i6, jlong l6, jfloat f6, jdouble d6,
+    jint i7, jlong l7, jfloat f7, jdouble d7,
+    jint i8, jlong l8, jfloat f8, jdouble d8) {
+  bool ok = VerifyManyParameters(
+      i1, l1, f1, d1,
+      i2, l2, f2, d2,
+      i3, l3, f3, d3,
+      i4, l4, f4, d4,
+      i5, l5, f5, d5,
+      i6, l6, f6, d6,
+      i7, l7, f7, d7,
+      i8, l8, f8, d8);
+  return ok ? 42 : -1;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_b189235039CallThrough(JNIEnv* env, jobject m) {
+  jclass main_klass = env->GetObjectClass(m);
+  jmethodID checkLocks = env->GetStaticMethodID(main_klass, "b189235039CheckLocks", "(ILMain;)I");
+  if (checkLocks == nullptr) {
+    return -1;
+  }
+  return env->CallStaticIntMethod(main_klass, checkLocks, 42, m);
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_b189235039CheckLocks(JNIEnv*,
+                                                                 jclass,
+                                                                 int arg,
+                                                                 jobject lock) {
+  // Check that we do not crash when visiting locks and that we find the right lock.
+  ScopedObjectAccess soa(Thread::Current());
+  class VisitLocks : public StackVisitor {
+   public:
+    VisitLocks(Thread* thread, Context* context, jobject expected_lock)
+        : StackVisitor(thread, context, StackWalkKind::kIncludeInlinedFrames),
+          expected_lock_(expected_lock) {
+    }
+
+    bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
+      ArtMethod* m = GetMethod();
+
+      // Ignore runtime methods.
+      if (m == nullptr || m->IsRuntimeMethod()) {
+        return true;
+      }
+
+      if (m->IsSynchronized()) {
+        // Interesting frame.
+        Monitor::VisitLocks(this, Callback, expected_lock_);
+        return false;
+      }
+
+      return true;
+    }
+
+   private:
+    static void Callback(ObjPtr<mirror::Object> obj, void* expected_lock)
+        REQUIRES_SHARED(Locks::mutator_lock_) {
+      CHECK(obj != nullptr);
+      CHECK(obj == Thread::Current()->DecodeJObject(reinterpret_cast<jobject>(expected_lock)));
+    }
+
+    jobject expected_lock_;
+  };
+  {
+    std::unique_ptr<Context> context(Context::Create());
+    VisitLocks vl(soa.Self(), context.get(), lock);
+    vl.WalkStack();
+  }
+  return arg;
+}
+
 }  // namespace art
diff --git a/test/178-app-image-native-method/profile b/test/178-app-image-native-method/profile
index 597dde1..1c25dee 100644
--- a/test/178-app-image-native-method/profile
+++ b/test/178-app-image-native-method/profile
@@ -1,8 +1,17 @@
 LMain;
 LTest;
-HSPLMain;->test()V
-HSPLMain;->testFast()V
-HSPLMain;->testCritical()V
-HSPLMain;->testMissing()V
-HSPLMain;->testMissingFast()V
-HSPLMain;->testMissingCritical()V
+LTestFast;
+LTestCritical;
+LTestMissing;
+LTestMissingFast;
+LTestMissingCritical;
+LCriticalSignatures;
+LCriticalClinitCheck;
+HSPLMain;->$noinline$opt$test()V
+HSPLMain;->$noinline$opt$testFast()V
+HSPLMain;->$noinline$opt$testCritical()V
+HSPLMain;->$noinline$opt$testMissing()V
+HSPLMain;->$noinline$opt$testMissingFast()V
+HSPLMain;->$noinline$opt$testMissingCritical()V
+HSPLMain;->$noinline$opt$testCriticalSignatures()V
+HSPLMain;->$noinline$opt$testCriticalClinitCheck()V
diff --git a/test/178-app-image-native-method/run b/test/178-app-image-native-method/run
index f4b07f0..7cd0d57 100644
--- a/test/178-app-image-native-method/run
+++ b/test/178-app-image-native-method/run
@@ -14,8 +14,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Use a profile to put specific classes in the app image.
-${RUN} $@ --profile -Xcompiler-option --compiler-filter=speed-profile
+# Use a profile to put specific classes in the app image. Increase the large
+# method threshold to compile Main.$noinline$opt$testCriticalSignatures().
+${RUN} $@ --profile -Xcompiler-option --compiler-filter=speed-profile \
+    -Xcompiler-option --large-method-max=2000
 return_status1=$?
 
 # Also run with the verify filter to avoid compiling JNI stubs.
diff --git a/test/178-app-image-native-method/src/Main.java b/test/178-app-image-native-method/src/Main.java
index 07990cb..294ad47 100644
--- a/test/178-app-image-native-method/src/Main.java
+++ b/test/178-app-image-native-method/src/Main.java
@@ -29,17 +29,36 @@
     new TestMissing();
     new TestMissingFast();
     new TestMissingCritical();
+    new CriticalSignatures();
     makeVisiblyInitialized();  // Make sure they are visibly initialized.
 
-    test();
-    testFast();
-    testCritical();
-    testMissing();
-    testMissingFast();
-    testMissingCritical();
+    $noinline$opt$test();
+    $noinline$opt$testFast();
+    $noinline$opt$testCritical();
+    $noinline$opt$testMissing();
+    $noinline$opt$testMissingFast();
+    $noinline$opt$testMissingCritical();
+    $noinline$opt$testCriticalSignatures();
+
+    // For calls from AOT-compiled code, the first call shall use the resolution method
+    // retrieved from the .bss and the second call should find the .bss entry populated
+    // with the target method. Re-run these tests to exercise the second path.
+    $noinline$opt$test();
+    $noinline$opt$testFast();
+    $noinline$opt$testCritical();
+    $noinline$opt$testMissing();
+    $noinline$opt$testMissingFast();
+    $noinline$opt$testMissingCritical();
+    $noinline$opt$testCriticalSignatures();
+
+    $noinline$regressionTestB181736463();
+    $noinline$regressionTestB189235039();
+
+    new CriticalClinitCheck();
+    sTestCriticalClinitCheckOtherThread.join();
   }
 
-  static void test() {
+  static void $noinline$opt$test() {
     System.out.println("test");
     assertEquals(42, Test.nativeMethodVoid());
     assertEquals(42, Test.nativeMethod(42));
@@ -54,7 +73,7 @@
         81, 82L, 83.0f, 84.0d));
   }
 
-  static void testFast() {
+  static void $noinline$opt$testFast() {
     System.out.println("testFast");
     assertEquals(42, TestFast.nativeMethodVoid());
     assertEquals(42, TestFast.nativeMethod(42));
@@ -69,7 +88,7 @@
         81, 82L, 83.0f, 84.0d));
   }
 
-  static void testCritical() {
+  static void $noinline$opt$testCritical() {
     System.out.println("testCritical");
     assertEquals(42, TestCritical.nativeMethodVoid());
     assertEquals(42, TestCritical.nativeMethod(42));
@@ -84,7 +103,7 @@
         81, 82L, 83.0f, 84.0d));
   }
 
-  static void testMissing() {
+  static void $noinline$opt$testMissing() {
     System.out.println("testMissing");
 
     try {
@@ -111,7 +130,7 @@
     } catch (LinkageError expected) {}
   }
 
-  static void testMissingFast() {
+  static void $noinline$opt$testMissingFast() {
     System.out.println("testMissingFast");
 
     try {
@@ -138,7 +157,7 @@
     } catch (LinkageError expected) {}
   }
 
-  static void testMissingCritical() {
+  static void $noinline$opt$testMissingCritical() {
     System.out.println("testMissingCritical");
 
     try {
@@ -165,6 +184,245 @@
     } catch (LinkageError expected) {}
   }
 
+  static void $noinline$opt$testCriticalSignatures() {
+    System.out.println("testCriticalSignatures");
+    long l = 0xf00000000L;
+    assertEquals(42, CriticalSignatures.nativeILFFFFD(1, l + 2L, 3.0f, 4.0f, 5.0f, 6.0f, 7.0));
+    assertEquals(42, CriticalSignatures.nativeLIFFFFD(l + 7L, 6, 5.0f, 4.0f, 3.0f, 2.0f, 1.0));
+    assertEquals(42, CriticalSignatures.nativeFLIFFFD(1.0f, l + 2L, 3, 4.0f, 5.0f, 6.0f, 7.0));
+    assertEquals(42, CriticalSignatures.nativeDDIIIIII(8.0, 7.0, 6, 5, 4, 3, 2, 1));
+    assertEquals(42, CriticalSignatures.nativeDFFILIII(1.0, 2.0f, 3.0f, 4, l + 5L, 6, 7, 8));
+    assertEquals(42, CriticalSignatures.nativeDDFILIII(8.0, 7.0, 6.0f, 5, l + 4L, 3, 2, 1));
+    assertEquals(42, CriticalSignatures.nativeDDIFII(1.0, 2.0, 3, 4.0f, 5, 6));
+    assertEquals(42, CriticalSignatures.nativeFullArgs(
+        // Generated by script (then modified to close argument list):
+        //   for i in {0..84}; \
+        //     do echo "        0xf00000000L + $((i*3))L,"; \
+        //     echo "        $((i*3+2)),"; \
+        //  done
+        0xf00000000L + 0L,
+        2,
+        0xf00000000L + 3L,
+        5,
+        0xf00000000L + 6L,
+        8,
+        0xf00000000L + 9L,
+        11,
+        0xf00000000L + 12L,
+        14,
+        0xf00000000L + 15L,
+        17,
+        0xf00000000L + 18L,
+        20,
+        0xf00000000L + 21L,
+        23,
+        0xf00000000L + 24L,
+        26,
+        0xf00000000L + 27L,
+        29,
+        0xf00000000L + 30L,
+        32,
+        0xf00000000L + 33L,
+        35,
+        0xf00000000L + 36L,
+        38,
+        0xf00000000L + 39L,
+        41,
+        0xf00000000L + 42L,
+        44,
+        0xf00000000L + 45L,
+        47,
+        0xf00000000L + 48L,
+        50,
+        0xf00000000L + 51L,
+        53,
+        0xf00000000L + 54L,
+        56,
+        0xf00000000L + 57L,
+        59,
+        0xf00000000L + 60L,
+        62,
+        0xf00000000L + 63L,
+        65,
+        0xf00000000L + 66L,
+        68,
+        0xf00000000L + 69L,
+        71,
+        0xf00000000L + 72L,
+        74,
+        0xf00000000L + 75L,
+        77,
+        0xf00000000L + 78L,
+        80,
+        0xf00000000L + 81L,
+        83,
+        0xf00000000L + 84L,
+        86,
+        0xf00000000L + 87L,
+        89,
+        0xf00000000L + 90L,
+        92,
+        0xf00000000L + 93L,
+        95,
+        0xf00000000L + 96L,
+        98,
+        0xf00000000L + 99L,
+        101,
+        0xf00000000L + 102L,
+        104,
+        0xf00000000L + 105L,
+        107,
+        0xf00000000L + 108L,
+        110,
+        0xf00000000L + 111L,
+        113,
+        0xf00000000L + 114L,
+        116,
+        0xf00000000L + 117L,
+        119,
+        0xf00000000L + 120L,
+        122,
+        0xf00000000L + 123L,
+        125,
+        0xf00000000L + 126L,
+        128,
+        0xf00000000L + 129L,
+        131,
+        0xf00000000L + 132L,
+        134,
+        0xf00000000L + 135L,
+        137,
+        0xf00000000L + 138L,
+        140,
+        0xf00000000L + 141L,
+        143,
+        0xf00000000L + 144L,
+        146,
+        0xf00000000L + 147L,
+        149,
+        0xf00000000L + 150L,
+        152,
+        0xf00000000L + 153L,
+        155,
+        0xf00000000L + 156L,
+        158,
+        0xf00000000L + 159L,
+        161,
+        0xf00000000L + 162L,
+        164,
+        0xf00000000L + 165L,
+        167,
+        0xf00000000L + 168L,
+        170,
+        0xf00000000L + 171L,
+        173,
+        0xf00000000L + 174L,
+        176,
+        0xf00000000L + 177L,
+        179,
+        0xf00000000L + 180L,
+        182,
+        0xf00000000L + 183L,
+        185,
+        0xf00000000L + 186L,
+        188,
+        0xf00000000L + 189L,
+        191,
+        0xf00000000L + 192L,
+        194,
+        0xf00000000L + 195L,
+        197,
+        0xf00000000L + 198L,
+        200,
+        0xf00000000L + 201L,
+        203,
+        0xf00000000L + 204L,
+        206,
+        0xf00000000L + 207L,
+        209,
+        0xf00000000L + 210L,
+        212,
+        0xf00000000L + 213L,
+        215,
+        0xf00000000L + 216L,
+        218,
+        0xf00000000L + 219L,
+        221,
+        0xf00000000L + 222L,
+        224,
+        0xf00000000L + 225L,
+        227,
+        0xf00000000L + 228L,
+        230,
+        0xf00000000L + 231L,
+        233,
+        0xf00000000L + 234L,
+        236,
+        0xf00000000L + 237L,
+        239,
+        0xf00000000L + 240L,
+        242,
+        0xf00000000L + 243L,
+        245,
+        0xf00000000L + 246L,
+        248,
+        0xf00000000L + 249L,
+        251,
+        0xf00000000L + 252L,
+        254));
+  }
+
+  static void $noinline$regressionTestB181736463() {
+    // Regression test for bug 181736463 (GenericJNI crashing when class initializer throws).
+    try {
+      BadClassB181736463.nativeMethodVoid();
+      throw new Error("Unreachable");
+    } catch (B181736463Error expected) {
+    }
+  }
+
+  static void $noinline$regressionTestB189235039() {
+    assertEquals(42, new Main().b189235039CallThrough());
+  }
+
+  static void initializingCriticalClinitCheck() {
+    // Called from CriticalClinitCheck.<clinit>().
+    // Test @CriticalNative calls on the initializing thread.
+    $noinline$opt$testCriticalClinitCheck();
+    sTestCriticalClinitCheckOtherThread = new Thread() {
+      public void run() {
+        $noinline$opt$testCriticalClinitCheck();
+      }
+    };
+    sTestCriticalClinitCheckOtherThread.start();
+    // Sleep for a second to give the other thread an opportunity to run.
+    // We're testing that it performs a clinit check and blocks until we
+    // exit the class initializer after writing the output below.
+    try {
+      Thread.sleep(1000);
+    } catch (InterruptedException ie) {
+      throw new Error(ie);
+    }
+    System.out.println("initializingCriticalClinitCheck finished");
+  }
+
+  static void $noinline$opt$testCriticalClinitCheck() {
+    assertEquals(42, CriticalClinitCheck.nativeMethodVoid());
+    assertEquals(42, CriticalClinitCheck.nativeMethod(42));
+    assertEquals(42, CriticalClinitCheck.nativeMethodWithManyParameters(
+        11, 12L, 13.0f, 14.0d,
+        21, 22L, 23.0f, 24.0d,
+        31, 32L, 33.0f, 34.0d,
+        41, 42L, 43.0f, 44.0d,
+        51, 52L, 53.0f, 54.0d,
+        61, 62L, 63.0f, 64.0d,
+        71, 72L, 73.0f, 74.0d,
+        81, 82L, 83.0f, 84.0d));
+    System.out.println("testCriticalClinitCheck passed");
+  }
+
+  static Thread sTestCriticalClinitCheckOtherThread = null;
+
   static void assertEquals(int expected, int actual) {
     if (expected != actual) {
       throw new AssertionError("Expected " + expected + " got " + actual);
@@ -172,6 +430,9 @@
   }
 
   public static native void makeVisiblyInitialized();
+
+  public native synchronized int b189235039CallThrough();
+  public static native int b189235039CheckLocks(int placeholder, Main m);
 }
 
 class Test {
@@ -281,3 +542,317 @@
       int i7, long l7, float f7, double d7,
       int i8, long l8, float f8, double d8);
 }
+
+class CriticalSignatures {
+  // The following signatures exercise ARM argument moving and serve
+  // as an example of the optimizations performed by the assembler.
+  // Moving arguments is a lot simpler for other architectures.
+
+  // JNI compiler does not emit the CFG, so we cannot CHECK the "dissassembly (after)".
+
+  // vstm sp, {d0-d2}         # f1, f2, f3, f4, d -- store floats as D regs together with double
+  // mov r4, r0               # hidden arg
+  // mov r0, r1               # i
+  //                          # l stays in r2-r3
+  @CriticalNative
+  public static native int nativeILFFFFD(
+      int i, long l, float f1, float f2, float f3, float f4, double d);
+
+  // vstm sp, {s1-s3}         # f2, f3, f4 -- store floats up to alignment gap
+  // vstr d2, [sp, #16]       # d
+  // mov r4, r0               # hidden arg
+  // mov r0, r2               # low(l)
+  // mov r1, r3               # high(l)
+  // ldr r2, [sp, #...]       # i
+  // vmov r3, s0              # f1
+  @CriticalNative
+  public static native int nativeLIFFFFD(
+      long l, int i, float f1, float f2, float f3, float f4, double d);
+
+  // ldr  ip, [sp, #...]      # i
+  // str  ip, [sp]            # i
+  // add  ip, sp, #4          # Spilling multiple floats at an offset from SP
+  // vstm ip, {s1-s5}         # f2, f3, f4, d
+  // mov r4, r0               # hidden arg
+  // vmov r0, s0              # f1
+  //                          # l stays in r2-r3
+  @CriticalNative
+  public static native int nativeFLIFFFD(
+      float f1, long l, int i, float f2, float f3, float f4, double d);
+
+  // stm sp, {r1,r2,r3}       # i1, i2, i3 -- store ints together
+  // ldrd r1, ip, [sp, #...]  # i4, i5
+  // strd r1, ip, [sp, #12]   # i4, i5
+  // ldr ip, [sp, #72]        # i6
+  // str ip, [sp, #20]        # i6
+  // mov r4, r0               # hidden arg
+  // vmov r0, r1, d0          # d1
+  // vmov r2, r3, d1          # d2
+  @CriticalNative
+  public static native int nativeDDIIIIII(
+      double d1, double d2, int i1, int i2, int i3, int i4, int i5, int i6);
+
+  // str r1, [sp]             # i1 -- cannot store with l due to alignment gap
+  // strd r2, r3, [sp, #8]    # l
+  // ldrd r1, ip, [sp, #...]  # i2, i3
+  // strd r1, ip, [sp, #16]   # i2, i3
+  // ldr ip, [sp, #...]       # i4
+  // str ip, [sp, #24]        # i4
+  // mov r4, r0               # hidden arg
+  // vmov r0, r1, d0          # d
+  // vmov r2, r3, d1          # f1, f2 -- move both floats together as double
+  @CriticalNative
+  public static native int nativeDFFILIII(
+      double d, float f1, float f2, int i1, long l, int i2, int i3, int i4);
+
+  // vstr s4, [sp]            # f
+  // add ip, sp, #4           # Spilling multiple core registers at an offset from SP
+  // stm ip, {r1,r2,r3}       # i1, l -- store int together with long
+  // ldrd r1, ip, [sp, #...]  # i2, i3
+  // strd r1, ip, [sp, #16]   # i2, i3
+  // ldr ip, [sp, #...]       # i4
+  // str ip, [sp, #24]        # i4
+  // mov r4, r0               # hidden arg
+  // vmov r0, r1, d0          # d1
+  // vmov r2, r3, d1          # d2
+  @CriticalNative
+  public static native int nativeDDFILIII(
+      double d1, double d2, float f, int i1, long l, int i2, int i3, int i4);
+
+  // str r1, [sp]             # i1
+  // vstr s4, [sp, #4]        # f
+  // strd r2, r3, [sp, #8]    # i2, i3 -- store ints together with STRD
+  // mov r4, r0               # hidden arg
+  // vmov r0, r1, d0          # d1
+  // vmov r2, r3, d1          # d2
+  @CriticalNative
+  public static native int nativeDDIFII(
+      double d1, double d2, int i1, float f, int i2, int i3);
+
+  // ...
+  // ldr ip, [sp, #2112]      # int
+  // str ip, [sp, #1000]      # int
+  // add r1, sp, #2048        # Prepare to use LDRD for loading long from a large offset
+  // ldrd r1, ip, [r1, #68]   # long
+  // strd r1, ip, [sp, #1008] # long
+  // ldr ip, [sp, #2124]      # int
+  // str ip, [sp, #1016]      # int
+  // ldr ip, [sp, #2128]      # low(long) -- copy the next long as two words because the offset
+  // str ip, [sp, #1024]      # low(long) -- is too large for STRD and we only use 2 temps (r1, ip)
+  // ldr ip, [sp, #2132]      # high(long)
+  // str ip, [sp, #1028]      # high(long)
+  // ...
+  @CriticalNative
+  public static native int nativeFullArgs(
+      // Note: Numbered by dalvik registers, 0-254 (max 255 regs for invoke-*-range)
+      //
+      // Generated by script (then modified to close the argument list):
+      //   for i in {0..84}; do echo "      long l$((i*3)),"; echo "      int i$(($i*3+2)),"; done
+      long l0,
+      int i2,
+      long l3,
+      int i5,
+      long l6,
+      int i8,
+      long l9,
+      int i11,
+      long l12,
+      int i14,
+      long l15,
+      int i17,
+      long l18,
+      int i20,
+      long l21,
+      int i23,
+      long l24,
+      int i26,
+      long l27,
+      int i29,
+      long l30,
+      int i32,
+      long l33,
+      int i35,
+      long l36,
+      int i38,
+      long l39,
+      int i41,
+      long l42,
+      int i44,
+      long l45,
+      int i47,
+      long l48,
+      int i50,
+      long l51,
+      int i53,
+      long l54,
+      int i56,
+      long l57,
+      int i59,
+      long l60,
+      int i62,
+      long l63,
+      int i65,
+      long l66,
+      int i68,
+      long l69,
+      int i71,
+      long l72,
+      int i74,
+      long l75,
+      int i77,
+      long l78,
+      int i80,
+      long l81,
+      int i83,
+      long l84,
+      int i86,
+      long l87,
+      int i89,
+      long l90,
+      int i92,
+      long l93,
+      int i95,
+      long l96,
+      int i98,
+      long l99,
+      int i101,
+      long l102,
+      int i104,
+      long l105,
+      int i107,
+      long l108,
+      int i110,
+      long l111,
+      int i113,
+      long l114,
+      int i116,
+      long l117,
+      int i119,
+      long l120,
+      int i122,
+      long l123,
+      int i125,
+      long l126,
+      int i128,
+      long l129,
+      int i131,
+      long l132,
+      int i134,
+      long l135,
+      int i137,
+      long l138,
+      int i140,
+      long l141,
+      int i143,
+      long l144,
+      int i146,
+      long l147,
+      int i149,
+      long l150,
+      int i152,
+      long l153,
+      int i155,
+      long l156,
+      int i158,
+      long l159,
+      int i161,
+      long l162,
+      int i164,
+      long l165,
+      int i167,
+      long l168,
+      int i170,
+      long l171,
+      int i173,
+      long l174,
+      int i176,
+      long l177,
+      int i179,
+      long l180,
+      int i182,
+      long l183,
+      int i185,
+      long l186,
+      int i188,
+      long l189,
+      int i191,
+      long l192,
+      int i194,
+      long l195,
+      int i197,
+      long l198,
+      int i200,
+      long l201,
+      int i203,
+      long l204,
+      int i206,
+      long l207,
+      int i209,
+      long l210,
+      int i212,
+      long l213,
+      int i215,
+      long l216,
+      int i218,
+      long l219,
+      int i221,
+      long l222,
+      int i224,
+      long l225,
+      int i227,
+      long l228,
+      int i230,
+      long l231,
+      int i233,
+      long l234,
+      int i236,
+      long l237,
+      int i239,
+      long l240,
+      int i242,
+      long l243,
+      int i245,
+      long l246,
+      int i248,
+      long l249,
+      int i251,
+      long l252,
+      int i254);
+}
+
+class CriticalClinitCheck {
+  @CriticalNative
+  public static native int nativeMethodVoid();
+
+  @CriticalNative
+  public static native int nativeMethod(int i);
+
+  @CriticalNative
+  public static native int nativeMethodWithManyParameters(
+      int i1, long l1, float f1, double d1,
+      int i2, long l2, float f2, double d2,
+      int i3, long l3, float f3, double d3,
+      int i4, long l4, float f4, double d4,
+      int i5, long l5, float f5, double d5,
+      int i6, long l6, float f6, double d6,
+      int i7, long l7, float f7, double d7,
+      int i8, long l8, float f8, double d8);
+
+  static {
+    Main.initializingCriticalClinitCheck();
+  }
+}
+
+class B181736463Error extends Error {
+}
+
+class BadClassB181736463 {
+  static {
+    // Deliberately throw from class initializer.
+    if (true) {
+      throw new B181736463Error();
+    }
+  }
+
+  public static native int nativeMethodVoid();
+}
diff --git a/test/179-nonvirtual-jni/Android.bp b/test/179-nonvirtual-jni/Android.bp
new file mode 100644
index 0000000..4ba6a89
--- /dev/null
+++ b/test/179-nonvirtual-jni/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `179-nonvirtual-jni`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-179-nonvirtual-jni",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-179-nonvirtual-jni-expected-stdout",
+        ":art-run-test-179-nonvirtual-jni-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-179-nonvirtual-jni-expected-stdout",
+    out: ["art-run-test-179-nonvirtual-jni-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-179-nonvirtual-jni-expected-stderr",
+    out: ["art-run-test-179-nonvirtual-jni-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/114-ParallelGC/expected.txt b/test/179-nonvirtual-jni/expected-stderr.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/179-nonvirtual-jni/expected-stderr.txt
diff --git a/test/179-nonvirtual-jni/expected-stdout.txt b/test/179-nonvirtual-jni/expected-stdout.txt
new file mode 100644
index 0000000..7b603b1
--- /dev/null
+++ b/test/179-nonvirtual-jni/expected-stdout.txt
@@ -0,0 +1,9 @@
+JNI_OnLoad called
+Call lookup: Base, caller: Base, Obj: Base
+Hello from Base
+Call lookup: Base, caller: Base, Obj: Ext
+Hello from Base
+Call lookup: Base, caller: Ext, Obj: Ext
+Hello from Base
+Call lookup: Ext, caller: Ext, Obj: Ext
+Hello from Ext
diff --git a/test/179-nonvirtual-jni/info.txt b/test/179-nonvirtual-jni/info.txt
new file mode 100644
index 0000000..528d3a4
--- /dev/null
+++ b/test/179-nonvirtual-jni/info.txt
@@ -0,0 +1 @@
+Ensure that calls to InvokeNonVirtual resolve correctly
diff --git a/test/179-nonvirtual-jni/nonvirtual-call.cc b/test/179-nonvirtual-jni/nonvirtual-call.cc
new file mode 100644
index 0000000..ef6c6c8
--- /dev/null
+++ b/test/179-nonvirtual-jni/nonvirtual-call.cc
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 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 <nativehelper/scoped_local_ref.h>
+#include <pthread.h>
+
+#include <android-base/logging.h>
+
+namespace art {
+
+extern "C" JNIEXPORT void JNICALL Java_Main_callSayHiMethodNonvirtualWith(
+    JNIEnv* env, jclass, jclass lookup, jclass caller, jobject recv) {
+  jmethodID meth = env->GetMethodID(lookup, "sayHi", "()V");
+  env->CallNonvirtualVoidMethod(recv, caller, meth);
+}
+
+}  // namespace art
diff --git a/test/179-nonvirtual-jni/src/Main.java b/test/179-nonvirtual-jni/src/Main.java
new file mode 100644
index 0000000..e809d41
--- /dev/null
+++ b/test/179-nonvirtual-jni/src/Main.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 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 class Base {
+    public void sayHi() {
+      System.out.println("Hello from Base");
+    }
+  }
+  public static class Ext extends Base{
+    public void sayHi() {
+      System.out.println("Hello from Ext");
+    }
+  }
+  public static void main(String[] args) throws Exception {
+    System.loadLibrary(args[0]);
+    try {
+      System.out.println("Call lookup: Base, caller: Base, Obj: Base");
+      callSayHiMethodNonvirtualWith(Base.class, Base.class, new Base());
+    } catch (Exception e) {
+      System.out.println("Caught exception " + e);
+    }
+    try {
+      System.out.println("Call lookup: Base, caller: Base, Obj: Ext");
+      callSayHiMethodNonvirtualWith(Base.class, Base.class, new Ext());
+    } catch (Exception e) {
+      System.out.println("Caught exception " + e);
+    }
+    try {
+      System.out.println("Call lookup: Base, caller: Ext, Obj: Ext");
+      callSayHiMethodNonvirtualWith(Base.class, Ext.class, new Ext());
+    } catch (Exception e) {
+      System.out.println("Caught exception " + e);
+    }
+    try {
+      System.out.println("Call lookup: Ext, caller: Ext, Obj: Ext");
+      callSayHiMethodNonvirtualWith(Ext.class, Ext.class, new Ext());
+    } catch (Exception e) {
+      System.out.println("Caught exception " + e);
+    }
+  }
+
+  private static native void callSayHiMethodNonvirtualWith(Class<?> lookup, Class<?> caller, Object recv);
+}
diff --git a/test/491-current-method/expected.txt b/test/180-native-default-method/expected-stderr.txt
similarity index 100%
copy from test/491-current-method/expected.txt
copy to test/180-native-default-method/expected-stderr.txt
diff --git a/test/180-native-default-method/expected.txt b/test/180-native-default-method/expected-stdout.txt
similarity index 100%
rename from test/180-native-default-method/expected.txt
rename to test/180-native-default-method/expected-stdout.txt
diff --git a/test/1900-track-alloc/Android.bp b/test/1900-track-alloc/Android.bp
new file mode 100644
index 0000000..bf8a29e
--- /dev/null
+++ b/test/1900-track-alloc/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1900-track-alloc`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1900-track-alloc",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1900-track-alloc-expected-stdout",
+        ":art-run-test-1900-track-alloc-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1900-track-alloc-expected-stdout",
+    out: ["art-run-test-1900-track-alloc-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1900-track-alloc-expected-stderr",
+    out: ["art-run-test-1900-track-alloc-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1900-track-alloc/expected-stderr.txt
similarity index 100%
rename from test/1900-track-alloc/expected.txt
rename to test/1900-track-alloc/expected-stderr.txt
diff --git a/test/1900-track-alloc/expected.txt b/test/1900-track-alloc/expected-stdout.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1900-track-alloc/expected-stdout.txt
diff --git a/test/1901-get-bytecodes/Android.bp b/test/1901-get-bytecodes/Android.bp
new file mode 100644
index 0000000..b037ec6
--- /dev/null
+++ b/test/1901-get-bytecodes/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1901-get-bytecodes`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1901-get-bytecodes",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1901-get-bytecodes-expected-stdout",
+        ":art-run-test-1901-get-bytecodes-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1901-get-bytecodes-expected-stdout",
+    out: ["art-run-test-1901-get-bytecodes-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1901-get-bytecodes-expected-stderr",
+    out: ["art-run-test-1901-get-bytecodes-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1901-get-bytecodes/expected-stderr.txt
similarity index 100%
rename from test/1901-get-bytecodes/expected.txt
rename to test/1901-get-bytecodes/expected-stderr.txt
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1901-get-bytecodes/expected-stdout.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/1901-get-bytecodes/expected-stdout.txt
diff --git a/test/1902-suspend/Android.bp b/test/1902-suspend/Android.bp
new file mode 100644
index 0000000..960b041
--- /dev/null
+++ b/test/1902-suspend/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1902-suspend`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1902-suspend",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1902-suspend-expected-stdout",
+        ":art-run-test-1902-suspend-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1902-suspend-expected-stdout",
+    out: ["art-run-test-1902-suspend-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1902-suspend-expected-stderr",
+    out: ["art-run-test-1902-suspend-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/1902-suspend/expected-stderr.txt
similarity index 100%
rename from test/1902-suspend/expected.txt
rename to test/1902-suspend/expected-stderr.txt
diff --git a/test/1902-suspend/expected.txt b/test/1902-suspend/expected-stdout.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/1902-suspend/expected-stdout.txt
diff --git a/test/1903-suspend-self/Android.bp b/test/1903-suspend-self/Android.bp
new file mode 100644
index 0000000..7d677b7
--- /dev/null
+++ b/test/1903-suspend-self/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1903-suspend-self`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1903-suspend-self",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1903-suspend-self-expected-stdout",
+        ":art-run-test-1903-suspend-self-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1903-suspend-self-expected-stdout",
+    out: ["art-run-test-1903-suspend-self-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1903-suspend-self-expected-stderr",
+    out: ["art-run-test-1903-suspend-self-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1903-suspend-self/expected.txt b/test/1903-suspend-self/expected-stderr.txt
similarity index 100%
rename from test/1903-suspend-self/expected.txt
rename to test/1903-suspend-self/expected-stderr.txt
diff --git a/test/1903-suspend-self/expected.txt b/test/1903-suspend-self/expected-stdout.txt
similarity index 100%
copy from test/1903-suspend-self/expected.txt
copy to test/1903-suspend-self/expected-stdout.txt
diff --git a/test/1904-double-suspend/Android.bp b/test/1904-double-suspend/Android.bp
new file mode 100644
index 0000000..19c386f
--- /dev/null
+++ b/test/1904-double-suspend/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1904-double-suspend`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1904-double-suspend",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1904-double-suspend-expected-stdout",
+        ":art-run-test-1904-double-suspend-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1904-double-suspend-expected-stdout",
+    out: ["art-run-test-1904-double-suspend-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1904-double-suspend-expected-stderr",
+    out: ["art-run-test-1904-double-suspend-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/1904-double-suspend/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/1904-double-suspend/expected-stderr.txt
diff --git a/test/1904-double-suspend/expected.txt b/test/1904-double-suspend/expected-stdout.txt
similarity index 100%
rename from test/1904-double-suspend/expected.txt
rename to test/1904-double-suspend/expected-stdout.txt
diff --git a/test/1905-suspend-native/Android.bp b/test/1905-suspend-native/Android.bp
new file mode 100644
index 0000000..1cd2879
--- /dev/null
+++ b/test/1905-suspend-native/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1905-suspend-native`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1905-suspend-native",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1905-suspend-native-expected-stdout",
+        ":art-run-test-1905-suspend-native-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1905-suspend-native-expected-stdout",
+    out: ["art-run-test-1905-suspend-native-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1905-suspend-native-expected-stderr",
+    out: ["art-run-test-1905-suspend-native-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1905-suspend-native/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1905-suspend-native/expected-stderr.txt
diff --git a/test/1905-suspend-native/expected.txt b/test/1905-suspend-native/expected-stdout.txt
similarity index 100%
rename from test/1905-suspend-native/expected.txt
rename to test/1905-suspend-native/expected-stdout.txt
diff --git a/test/1906-suspend-list-me-first/Android.bp b/test/1906-suspend-list-me-first/Android.bp
new file mode 100644
index 0000000..558949e
--- /dev/null
+++ b/test/1906-suspend-list-me-first/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1906-suspend-list-me-first`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1906-suspend-list-me-first",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1906-suspend-list-me-first-expected-stdout",
+        ":art-run-test-1906-suspend-list-me-first-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1906-suspend-list-me-first-expected-stdout",
+    out: ["art-run-test-1906-suspend-list-me-first-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1906-suspend-list-me-first-expected-stderr",
+    out: ["art-run-test-1906-suspend-list-me-first-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1906-suspend-list-me-first/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1906-suspend-list-me-first/expected-stderr.txt
diff --git a/test/1906-suspend-list-me-first/expected.txt b/test/1906-suspend-list-me-first/expected-stdout.txt
similarity index 100%
rename from test/1906-suspend-list-me-first/expected.txt
rename to test/1906-suspend-list-me-first/expected-stdout.txt
diff --git a/test/1907-suspend-list-self-twice/Android.bp b/test/1907-suspend-list-self-twice/Android.bp
new file mode 100644
index 0000000..8afa6c7
--- /dev/null
+++ b/test/1907-suspend-list-self-twice/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1907-suspend-list-self-twice`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1907-suspend-list-self-twice",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1907-suspend-list-self-twice-expected-stdout",
+        ":art-run-test-1907-suspend-list-self-twice-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1907-suspend-list-self-twice-expected-stdout",
+    out: ["art-run-test-1907-suspend-list-self-twice-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1907-suspend-list-self-twice-expected-stderr",
+    out: ["art-run-test-1907-suspend-list-self-twice-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/1907-suspend-list-self-twice/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/1907-suspend-list-self-twice/expected-stderr.txt
diff --git a/test/1907-suspend-list-self-twice/expected.txt b/test/1907-suspend-list-self-twice/expected-stdout.txt
similarity index 100%
rename from test/1907-suspend-list-self-twice/expected.txt
rename to test/1907-suspend-list-self-twice/expected-stdout.txt
diff --git a/test/1908-suspend-native-resume-self/Android.bp b/test/1908-suspend-native-resume-self/Android.bp
new file mode 100644
index 0000000..f2b97e4
--- /dev/null
+++ b/test/1908-suspend-native-resume-self/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1908-suspend-native-resume-self`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1908-suspend-native-resume-self",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1908-suspend-native-resume-self-expected-stdout",
+        ":art-run-test-1908-suspend-native-resume-self-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1908-suspend-native-resume-self-expected-stdout",
+    out: ["art-run-test-1908-suspend-native-resume-self-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1908-suspend-native-resume-self-expected-stderr",
+    out: ["art-run-test-1908-suspend-native-resume-self-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1903-suspend-self/expected.txt b/test/1908-suspend-native-resume-self/expected-stderr.txt
similarity index 100%
copy from test/1903-suspend-self/expected.txt
copy to test/1908-suspend-native-resume-self/expected-stderr.txt
diff --git a/test/1908-suspend-native-resume-self/expected.txt b/test/1908-suspend-native-resume-self/expected-stdout.txt
similarity index 100%
rename from test/1908-suspend-native-resume-self/expected.txt
rename to test/1908-suspend-native-resume-self/expected-stdout.txt
diff --git a/test/1909-per-agent-tls/Android.bp b/test/1909-per-agent-tls/Android.bp
new file mode 100644
index 0000000..09c61b1
--- /dev/null
+++ b/test/1909-per-agent-tls/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1909-per-agent-tls`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1909-per-agent-tls",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1909-per-agent-tls-expected-stdout",
+        ":art-run-test-1909-per-agent-tls-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1909-per-agent-tls-expected-stdout",
+    out: ["art-run-test-1909-per-agent-tls-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1909-per-agent-tls-expected-stderr",
+    out: ["art-run-test-1909-per-agent-tls-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1909-per-agent-tls/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/1909-per-agent-tls/expected-stderr.txt
diff --git a/test/1909-per-agent-tls/expected.txt b/test/1909-per-agent-tls/expected-stdout.txt
similarity index 100%
rename from test/1909-per-agent-tls/expected.txt
rename to test/1909-per-agent-tls/expected-stdout.txt
diff --git a/test/1910-transform-with-default/Android.bp b/test/1910-transform-with-default/Android.bp
new file mode 100644
index 0000000..469f9d1
--- /dev/null
+++ b/test/1910-transform-with-default/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1910-transform-with-default`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1910-transform-with-default",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1910-transform-with-default-expected-stdout",
+        ":art-run-test-1910-transform-with-default-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1910-transform-with-default-expected-stdout",
+    out: ["art-run-test-1910-transform-with-default-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1910-transform-with-default-expected-stderr",
+    out: ["art-run-test-1910-transform-with-default-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1910-transform-with-default/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1910-transform-with-default/expected-stderr.txt
diff --git a/test/1910-transform-with-default/expected.txt b/test/1910-transform-with-default/expected-stdout.txt
similarity index 100%
rename from test/1910-transform-with-default/expected.txt
rename to test/1910-transform-with-default/expected-stdout.txt
diff --git a/test/1911-get-local-var-table/Android.bp b/test/1911-get-local-var-table/Android.bp
new file mode 100644
index 0000000..a5c212e
--- /dev/null
+++ b/test/1911-get-local-var-table/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1911-get-local-var-table`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1911-get-local-var-table",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1911-get-local-var-table-expected-stdout",
+        ":art-run-test-1911-get-local-var-table-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1911-get-local-var-table-expected-stdout",
+    out: ["art-run-test-1911-get-local-var-table-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1911-get-local-var-table-expected-stderr",
+    out: ["art-run-test-1911-get-local-var-table-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1911-get-local-var-table/expected-stderr.txt
similarity index 100%
rename from test/1911-get-local-var-table/expected.txt
rename to test/1911-get-local-var-table/expected-stderr.txt
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1911-get-local-var-table/expected-stdout.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1911-get-local-var-table/expected-stdout.txt
diff --git a/test/1912-get-set-local-primitive/Android.bp b/test/1912-get-set-local-primitive/Android.bp
new file mode 100644
index 0000000..f4761e2
--- /dev/null
+++ b/test/1912-get-set-local-primitive/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1912-get-set-local-primitive`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1912-get-set-local-primitive",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1912-get-set-local-primitive-expected-stdout",
+        ":art-run-test-1912-get-set-local-primitive-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1912-get-set-local-primitive-expected-stdout",
+    out: ["art-run-test-1912-get-set-local-primitive-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1912-get-set-local-primitive-expected-stderr",
+    out: ["art-run-test-1912-get-set-local-primitive-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1912-get-set-local-primitive/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1912-get-set-local-primitive/expected-stderr.txt
diff --git a/test/1912-get-set-local-primitive/expected.txt b/test/1912-get-set-local-primitive/expected-stdout.txt
similarity index 100%
rename from test/1912-get-set-local-primitive/expected.txt
rename to test/1912-get-set-local-primitive/expected-stdout.txt
diff --git a/test/1913-get-set-local-objects/Android.bp b/test/1913-get-set-local-objects/Android.bp
new file mode 100644
index 0000000..dd77c47
--- /dev/null
+++ b/test/1913-get-set-local-objects/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1913-get-set-local-objects`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1913-get-set-local-objects",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1913-get-set-local-objects-expected-stdout",
+        ":art-run-test-1913-get-set-local-objects-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1913-get-set-local-objects-expected-stdout",
+    out: ["art-run-test-1913-get-set-local-objects-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1913-get-set-local-objects-expected-stderr",
+    out: ["art-run-test-1913-get-set-local-objects-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/698-selects/expected.txt b/test/1913-get-set-local-objects/expected-stderr.txt
similarity index 100%
copy from test/698-selects/expected.txt
copy to test/1913-get-set-local-objects/expected-stderr.txt
diff --git a/test/1913-get-set-local-objects/expected.txt b/test/1913-get-set-local-objects/expected-stdout.txt
similarity index 100%
rename from test/1913-get-set-local-objects/expected.txt
rename to test/1913-get-set-local-objects/expected-stdout.txt
diff --git a/test/1914-get-local-instance/Android.bp b/test/1914-get-local-instance/Android.bp
new file mode 100644
index 0000000..99f3854
--- /dev/null
+++ b/test/1914-get-local-instance/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1914-get-local-instance`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1914-get-local-instance",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1914-get-local-instance-expected-stdout",
+        ":art-run-test-1914-get-local-instance-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1914-get-local-instance-expected-stdout",
+    out: ["art-run-test-1914-get-local-instance-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1914-get-local-instance-expected-stderr",
+    out: ["art-run-test-1914-get-local-instance-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/435-new-instance/expected.txt b/test/1914-get-local-instance/expected-stderr.txt
similarity index 100%
copy from test/435-new-instance/expected.txt
copy to test/1914-get-local-instance/expected-stderr.txt
diff --git a/test/1914-get-local-instance/expected.txt b/test/1914-get-local-instance/expected-stdout.txt
similarity index 100%
rename from test/1914-get-local-instance/expected.txt
rename to test/1914-get-local-instance/expected-stdout.txt
diff --git a/test/1915-get-set-local-current-thread/Android.bp b/test/1915-get-set-local-current-thread/Android.bp
new file mode 100644
index 0000000..925ddc9
--- /dev/null
+++ b/test/1915-get-set-local-current-thread/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1915-get-set-local-current-thread`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1915-get-set-local-current-thread",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1915-get-set-local-current-thread-expected-stdout",
+        ":art-run-test-1915-get-set-local-current-thread-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1915-get-set-local-current-thread-expected-stdout",
+    out: ["art-run-test-1915-get-set-local-current-thread-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1915-get-set-local-current-thread-expected-stderr",
+    out: ["art-run-test-1915-get-set-local-current-thread-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1995-final-virtual-structural-multithread/expected.txt b/test/1915-get-set-local-current-thread/expected-stderr.txt
similarity index 100%
copy from test/1995-final-virtual-structural-multithread/expected.txt
copy to test/1915-get-set-local-current-thread/expected-stderr.txt
diff --git a/test/1915-get-set-local-current-thread/expected.txt b/test/1915-get-set-local-current-thread/expected-stdout.txt
similarity index 100%
rename from test/1915-get-set-local-current-thread/expected.txt
rename to test/1915-get-set-local-current-thread/expected-stdout.txt
diff --git a/test/1916-get-set-current-frame/Android.bp b/test/1916-get-set-current-frame/Android.bp
new file mode 100644
index 0000000..4777050
--- /dev/null
+++ b/test/1916-get-set-current-frame/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1916-get-set-current-frame`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1916-get-set-current-frame",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1916-get-set-current-frame-expected-stdout",
+        ":art-run-test-1916-get-set-current-frame-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1916-get-set-current-frame-expected-stdout",
+    out: ["art-run-test-1916-get-set-current-frame-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1916-get-set-current-frame-expected-stderr",
+    out: ["art-run-test-1916-get-set-current-frame-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/421-large-frame/expected.txt b/test/1916-get-set-current-frame/expected-stderr.txt
similarity index 100%
copy from test/421-large-frame/expected.txt
copy to test/1916-get-set-current-frame/expected-stderr.txt
diff --git a/test/1916-get-set-current-frame/expected.txt b/test/1916-get-set-current-frame/expected-stdout.txt
similarity index 100%
rename from test/1916-get-set-current-frame/expected.txt
rename to test/1916-get-set-current-frame/expected-stdout.txt
diff --git a/test/1917-get-stack-frame/Android.bp b/test/1917-get-stack-frame/Android.bp
new file mode 100644
index 0000000..63c6113
--- /dev/null
+++ b/test/1917-get-stack-frame/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1917-get-stack-frame`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1917-get-stack-frame",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1917-get-stack-frame-expected-stdout",
+        ":art-run-test-1917-get-stack-frame-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1917-get-stack-frame-expected-stdout",
+    out: ["art-run-test-1917-get-stack-frame-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1917-get-stack-frame-expected-stderr",
+    out: ["art-run-test-1917-get-stack-frame-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/421-large-frame/expected.txt b/test/1917-get-stack-frame/expected-stderr.txt
similarity index 100%
copy from test/421-large-frame/expected.txt
copy to test/1917-get-stack-frame/expected-stderr.txt
diff --git a/test/1917-get-stack-frame/expected.txt b/test/1917-get-stack-frame/expected-stdout.txt
similarity index 100%
rename from test/1917-get-stack-frame/expected.txt
rename to test/1917-get-stack-frame/expected-stdout.txt
diff --git a/test/1919-vminit-thread-start-timing/Android.bp b/test/1919-vminit-thread-start-timing/Android.bp
new file mode 100644
index 0000000..65748c2
--- /dev/null
+++ b/test/1919-vminit-thread-start-timing/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1919-vminit-thread-start-timing`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1919-vminit-thread-start-timing",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1919-vminit-thread-start-timing-expected-stdout",
+        ":art-run-test-1919-vminit-thread-start-timing-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1919-vminit-thread-start-timing-expected-stdout",
+    out: ["art-run-test-1919-vminit-thread-start-timing-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1919-vminit-thread-start-timing-expected-stderr",
+    out: ["art-run-test-1919-vminit-thread-start-timing-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1919-vminit-thread-start-timing/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1919-vminit-thread-start-timing/expected-stderr.txt
diff --git a/test/1919-vminit-thread-start-timing/expected.txt b/test/1919-vminit-thread-start-timing/expected-stdout.txt
similarity index 100%
rename from test/1919-vminit-thread-start-timing/expected.txt
rename to test/1919-vminit-thread-start-timing/expected-stdout.txt
diff --git a/test/1920-suspend-native-monitor/Android.bp b/test/1920-suspend-native-monitor/Android.bp
new file mode 100644
index 0000000..a0e112e
--- /dev/null
+++ b/test/1920-suspend-native-monitor/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1920-suspend-native-monitor`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1920-suspend-native-monitor",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1920-suspend-native-monitor-expected-stdout",
+        ":art-run-test-1920-suspend-native-monitor-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1920-suspend-native-monitor-expected-stdout",
+    out: ["art-run-test-1920-suspend-native-monitor-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1920-suspend-native-monitor-expected-stderr",
+    out: ["art-run-test-1920-suspend-native-monitor-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/404-optimizing-allocator/expected.txt b/test/1920-suspend-native-monitor/expected-stderr.txt
similarity index 100%
copy from test/404-optimizing-allocator/expected.txt
copy to test/1920-suspend-native-monitor/expected-stderr.txt
diff --git a/test/1920-suspend-native-monitor/expected.txt b/test/1920-suspend-native-monitor/expected-stdout.txt
similarity index 100%
rename from test/1920-suspend-native-monitor/expected.txt
rename to test/1920-suspend-native-monitor/expected-stdout.txt
diff --git a/test/1921-suspend-native-recursive-monitor/Android.bp b/test/1921-suspend-native-recursive-monitor/Android.bp
new file mode 100644
index 0000000..bfe3ede
--- /dev/null
+++ b/test/1921-suspend-native-recursive-monitor/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1921-suspend-native-recursive-monitor`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1921-suspend-native-recursive-monitor",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1921-suspend-native-recursive-monitor-expected-stdout",
+        ":art-run-test-1921-suspend-native-recursive-monitor-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1921-suspend-native-recursive-monitor-expected-stdout",
+    out: ["art-run-test-1921-suspend-native-recursive-monitor-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1921-suspend-native-recursive-monitor-expected-stderr",
+    out: ["art-run-test-1921-suspend-native-recursive-monitor-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1921-suspend-native-recursive-monitor/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1921-suspend-native-recursive-monitor/expected-stderr.txt
diff --git a/test/1921-suspend-native-recursive-monitor/expected.txt b/test/1921-suspend-native-recursive-monitor/expected-stdout.txt
similarity index 100%
rename from test/1921-suspend-native-recursive-monitor/expected.txt
rename to test/1921-suspend-native-recursive-monitor/expected-stdout.txt
diff --git a/test/1922-owned-monitors-info/Android.bp b/test/1922-owned-monitors-info/Android.bp
new file mode 100644
index 0000000..c6de1d7
--- /dev/null
+++ b/test/1922-owned-monitors-info/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1922-owned-monitors-info`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1922-owned-monitors-info",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1922-owned-monitors-info-expected-stdout",
+        ":art-run-test-1922-owned-monitors-info-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1922-owned-monitors-info-expected-stdout",
+    out: ["art-run-test-1922-owned-monitors-info-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1922-owned-monitors-info-expected-stderr",
+    out: ["art-run-test-1922-owned-monitors-info-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1922-owned-monitors-info/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1922-owned-monitors-info/expected-stderr.txt
diff --git a/test/1922-owned-monitors-info/expected.txt b/test/1922-owned-monitors-info/expected-stdout.txt
similarity index 100%
rename from test/1922-owned-monitors-info/expected.txt
rename to test/1922-owned-monitors-info/expected-stdout.txt
diff --git a/test/1923-frame-pop/Android.bp b/test/1923-frame-pop/Android.bp
new file mode 100644
index 0000000..397d60e
--- /dev/null
+++ b/test/1923-frame-pop/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1923-frame-pop`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1923-frame-pop",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1923-frame-pop-expected-stdout",
+        ":art-run-test-1923-frame-pop-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1923-frame-pop-expected-stdout",
+    out: ["art-run-test-1923-frame-pop-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1923-frame-pop-expected-stderr",
+    out: ["art-run-test-1923-frame-pop-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/1923-frame-pop/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/1923-frame-pop/expected-stderr.txt
diff --git a/test/1923-frame-pop/expected.txt b/test/1923-frame-pop/expected-stdout.txt
similarity index 100%
rename from test/1923-frame-pop/expected.txt
rename to test/1923-frame-pop/expected-stdout.txt
diff --git a/test/1924-frame-pop-toggle/Android.bp b/test/1924-frame-pop-toggle/Android.bp
new file mode 100644
index 0000000..2ad8423
--- /dev/null
+++ b/test/1924-frame-pop-toggle/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1924-frame-pop-toggle`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1924-frame-pop-toggle",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1924-frame-pop-toggle-expected-stdout",
+        ":art-run-test-1924-frame-pop-toggle-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1924-frame-pop-toggle-expected-stdout",
+    out: ["art-run-test-1924-frame-pop-toggle-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1924-frame-pop-toggle-expected-stderr",
+    out: ["art-run-test-1924-frame-pop-toggle-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1924-frame-pop-toggle/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1924-frame-pop-toggle/expected-stderr.txt
diff --git a/test/1924-frame-pop-toggle/expected.txt b/test/1924-frame-pop-toggle/expected-stdout.txt
similarity index 100%
rename from test/1924-frame-pop-toggle/expected.txt
rename to test/1924-frame-pop-toggle/expected-stdout.txt
diff --git a/test/1925-self-frame-pop/Android.bp b/test/1925-self-frame-pop/Android.bp
new file mode 100644
index 0000000..d3912cf
--- /dev/null
+++ b/test/1925-self-frame-pop/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1925-self-frame-pop`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1925-self-frame-pop",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1925-self-frame-pop-expected-stdout",
+        ":art-run-test-1925-self-frame-pop-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1925-self-frame-pop-expected-stdout",
+    out: ["art-run-test-1925-self-frame-pop-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1925-self-frame-pop-expected-stderr",
+    out: ["art-run-test-1925-self-frame-pop-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1925-self-frame-pop/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1925-self-frame-pop/expected-stderr.txt
diff --git a/test/1925-self-frame-pop/expected.txt b/test/1925-self-frame-pop/expected-stdout.txt
similarity index 100%
rename from test/1925-self-frame-pop/expected.txt
rename to test/1925-self-frame-pop/expected-stdout.txt
diff --git a/test/1926-missed-frame-pop/Android.bp b/test/1926-missed-frame-pop/Android.bp
new file mode 100644
index 0000000..2e08151
--- /dev/null
+++ b/test/1926-missed-frame-pop/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1926-missed-frame-pop`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1926-missed-frame-pop",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1926-missed-frame-pop-expected-stdout",
+        ":art-run-test-1926-missed-frame-pop-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1926-missed-frame-pop-expected-stdout",
+    out: ["art-run-test-1926-missed-frame-pop-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1926-missed-frame-pop-expected-stderr",
+    out: ["art-run-test-1926-missed-frame-pop-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1926-missed-frame-pop/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1926-missed-frame-pop/expected-stderr.txt
diff --git a/test/1926-missed-frame-pop/expected.txt b/test/1926-missed-frame-pop/expected-stdout.txt
similarity index 100%
rename from test/1926-missed-frame-pop/expected.txt
rename to test/1926-missed-frame-pop/expected-stdout.txt
diff --git a/test/1927-exception-event/Android.bp b/test/1927-exception-event/Android.bp
new file mode 100644
index 0000000..b793ed4
--- /dev/null
+++ b/test/1927-exception-event/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1927-exception-event`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1927-exception-event",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1927-exception-event-expected-stdout",
+        ":art-run-test-1927-exception-event-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1927-exception-event-expected-stdout",
+    out: ["art-run-test-1927-exception-event-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1927-exception-event-expected-stderr",
+    out: ["art-run-test-1927-exception-event-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/436-shift-constant/expected.txt b/test/1927-exception-event/expected-stderr.txt
similarity index 100%
copy from test/436-shift-constant/expected.txt
copy to test/1927-exception-event/expected-stderr.txt
diff --git a/test/1927-exception-event/expected.txt b/test/1927-exception-event/expected-stdout.txt
similarity index 100%
rename from test/1927-exception-event/expected.txt
rename to test/1927-exception-event/expected-stdout.txt
diff --git a/test/1928-exception-event-exception/Android.bp b/test/1928-exception-event-exception/Android.bp
new file mode 100644
index 0000000..11844b6
--- /dev/null
+++ b/test/1928-exception-event-exception/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1928-exception-event-exception`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1928-exception-event-exception",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1928-exception-event-exception-expected-stdout",
+        ":art-run-test-1928-exception-event-exception-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1928-exception-event-exception-expected-stdout",
+    out: ["art-run-test-1928-exception-event-exception-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1928-exception-event-exception-expected-stderr",
+    out: ["art-run-test-1928-exception-event-exception-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-fragmentation/expected.txt b/test/1928-exception-event-exception/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/1928-exception-event-exception/expected-stderr.txt
diff --git a/test/1928-exception-event-exception/expected.txt b/test/1928-exception-event-exception/expected-stdout.txt
similarity index 100%
rename from test/1928-exception-event-exception/expected.txt
rename to test/1928-exception-event-exception/expected-stdout.txt
diff --git a/test/080-oom-fragmentation/expected.txt b/test/1929-exception-catch-exception/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/1929-exception-catch-exception/expected-stderr.txt
diff --git a/test/1929-exception-catch-exception/expected.txt b/test/1929-exception-catch-exception/expected-stdout.txt
similarity index 100%
rename from test/1929-exception-catch-exception/expected.txt
rename to test/1929-exception-catch-exception/expected-stdout.txt
diff --git a/test/1930-monitor-info/Android.bp b/test/1930-monitor-info/Android.bp
new file mode 100644
index 0000000..4ee533e
--- /dev/null
+++ b/test/1930-monitor-info/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1930-monitor-info`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1930-monitor-info",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1930-monitor-info-expected-stdout",
+        ":art-run-test-1930-monitor-info-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1930-monitor-info-expected-stdout",
+    out: ["art-run-test-1930-monitor-info-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1930-monitor-info-expected-stderr",
+    out: ["art-run-test-1930-monitor-info-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1930-monitor-info/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1930-monitor-info/expected-stderr.txt
diff --git a/test/1930-monitor-info/expected.txt b/test/1930-monitor-info/expected-stdout.txt
similarity index 100%
rename from test/1930-monitor-info/expected.txt
rename to test/1930-monitor-info/expected-stdout.txt
diff --git a/test/1931-monitor-events/Android.bp b/test/1931-monitor-events/Android.bp
new file mode 100644
index 0000000..d0a25d4
--- /dev/null
+++ b/test/1931-monitor-events/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1931-monitor-events`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1931-monitor-events",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1931-monitor-events-expected-stdout",
+        ":art-run-test-1931-monitor-events-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1931-monitor-events-expected-stdout",
+    out: ["art-run-test-1931-monitor-events-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1931-monitor-events-expected-stderr",
+    out: ["art-run-test-1931-monitor-events-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1931-monitor-events/check b/test/1931-monitor-events/check
index 8a7f844..3f799cc 100644
--- a/test/1931-monitor-events/check
+++ b/test/1931-monitor-events/check
@@ -14,9 +14,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Art sends events for park/unpark, and the RI doesn't. Remove it from the expected output.
 if [[ "$TEST_RUNTIME" == "jvm" ]]; then
-  patch -p0 expected.txt < jvm-expected.patch >/dev/null
+  patch -p0 expected-stdout.txt < jvm-expected.patch >/dev/null
 fi
 
 ./default-check "$@"
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1931-monitor-events/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/1931-monitor-events/expected-stderr.txt
diff --git a/test/1931-monitor-events/expected.txt b/test/1931-monitor-events/expected-stdout.txt
similarity index 100%
rename from test/1931-monitor-events/expected.txt
rename to test/1931-monitor-events/expected-stdout.txt
diff --git a/test/1931-monitor-events/src/art/Test1931.java b/test/1931-monitor-events/src/art/Test1931.java
index f549789..b1fb841 100644
--- a/test/1931-monitor-events/src/art/Test1931.java
+++ b/test/1931-monitor-events/src/art/Test1931.java
@@ -29,6 +29,18 @@
 import java.util.function.Function;
 
 public class Test1931 {
+  private static Monitors.LockController CONTENTION_SUPPRESSED = null;
+
+  public static AutoCloseable SuppressContention(Monitors.LockController controller) {
+    if (CONTENTION_SUPPRESSED != null) {
+      throw new IllegalStateException("Only one contention suppression is possible at a time.");
+    }
+    CONTENTION_SUPPRESSED = controller;
+    return () -> {
+      CONTENTION_SUPPRESSED = null;
+    };
+  }
+
   public static void printStackTrace(Throwable t) {
     System.out.println("Caught exception: " + t);
     for (Throwable c = t.getCause(); c != null; c = c.getCause()) {
@@ -39,10 +51,16 @@
   }
 
   public static void handleMonitorEnter(Thread thd, Object lock) {
+    if (CONTENTION_SUPPRESSED != null && CONTENTION_SUPPRESSED.IsWorkerThread(thd)) {
+      return;
+    }
     System.out.println(thd.getName() + " contended-LOCKING " + lock);
   }
 
   public static void handleMonitorEntered(Thread thd, Object lock) {
+    if (CONTENTION_SUPPRESSED != null && CONTENTION_SUPPRESSED.IsWorkerThread(thd)) {
+      return;
+    }
     System.out.println(thd.getName() + " LOCKED " + lock);
   }
   public static void handleMonitorWait(Thread thd, Object lock, long timeout) {
@@ -170,10 +188,14 @@
     controller1.waitForLockToBeHeld();
     controller1.DoWait();
     controller1.waitForNotifySleep();
-    controller2.DoLock();
-    controller2.waitForLockToBeHeld();
-    controller2.DoNotifyAll();
-    controller2.DoUnlock();
+    try (AutoCloseable suppress = SuppressContention(controller2)) {
+      // If controller1 has a spurious wakeup we could see contention here. Suppress it so it won't
+      // cause the test to fail.
+      controller2.DoLock();
+      controller2.waitForLockToBeHeld();
+      controller2.DoNotifyAll();
+      controller2.DoUnlock();
+    }
     controller1.waitForLockToBeHeld();
     controller1.DoUnlock();
   }
@@ -187,10 +209,14 @@
     controller1.waitForLockToBeHeld();
     controller1.DoTimedWait();
     controller1.waitForNotifySleep();
-    controller2.DoLock();
-    controller2.waitForLockToBeHeld();
-    controller2.DoNotifyAll();
-    controller2.DoUnlock();
+    try (AutoCloseable suppress = SuppressContention(controller2)) {
+      // If controller1 has a spurious wakeup we could see contention here. Suppress it so it won't
+      // cause the test to fail.
+      controller2.DoLock();
+      controller2.waitForLockToBeHeld();
+      controller2.DoNotifyAll();
+      controller2.DoUnlock();
+    }
     controller1.waitForLockToBeHeld();
     controller1.DoUnlock();
   }
diff --git a/test/1932-monitor-events-misc/Android.bp b/test/1932-monitor-events-misc/Android.bp
new file mode 100644
index 0000000..d8124ff
--- /dev/null
+++ b/test/1932-monitor-events-misc/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1932-monitor-events-misc`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1932-monitor-events-misc",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1932-monitor-events-misc-expected-stdout",
+        ":art-run-test-1932-monitor-events-misc-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1932-monitor-events-misc-expected-stdout",
+    out: ["art-run-test-1932-monitor-events-misc-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1932-monitor-events-misc-expected-stderr",
+    out: ["art-run-test-1932-monitor-events-misc-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1932-monitor-events-misc/check b/test/1932-monitor-events-misc/check
index 8a84388..0fe4429 100644
--- a/test/1932-monitor-events-misc/check
+++ b/test/1932-monitor-events-misc/check
@@ -14,9 +14,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # The RI sends an extra event that art doesn't. Add it to the expected output.
 if [[ "$TEST_RUNTIME" == "jvm" ]]; then
-  patch -p0 expected.txt < jvm-expected.patch >/dev/null
+  patch -p0 expected-stdout.txt < jvm-expected.patch >/dev/null
 fi
 
 ./default-check "$@"
diff --git a/test/1900-track-alloc/expected.txt b/test/1932-monitor-events-misc/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1932-monitor-events-misc/expected-stderr.txt
diff --git a/test/1932-monitor-events-misc/expected.txt b/test/1932-monitor-events-misc/expected-stdout.txt
similarity index 100%
rename from test/1932-monitor-events-misc/expected.txt
rename to test/1932-monitor-events-misc/expected-stdout.txt
diff --git a/test/1932-monitor-events-misc/src/art/Test1932.java b/test/1932-monitor-events-misc/src/art/Test1932.java
index 7f66884..84f2059 100644
--- a/test/1932-monitor-events-misc/src/art/Test1932.java
+++ b/test/1932-monitor-events-misc/src/art/Test1932.java
@@ -219,9 +219,12 @@
     controller1.waitForLockToBeHeld();
     controller1.DoWait();
     controller1.waitForNotifySleep();
-    controller2.DoLock();
-    controller2.waitForLockToBeHeld();
-    controller2.DoNotifyAll();
+    try (AutoCloseable suppress = SuppressContention(controller2)) {
+      controller2.DoLock();
+      controller2.waitForLockToBeHeld();
+      controller2.DoNotifyAll();
+      // See comment in testWaitMonitorEnter.
+    }
     controller2.DoUnlock();
     controller1.waitForLockToBeHeld();
     controller1.DoUnlock();
@@ -246,9 +249,15 @@
     controller1.waitForLockToBeHeld();
     controller1.DoWait();
     controller1.waitForNotifySleep();
-    controller2.DoLock();
-    controller2.waitForLockToBeHeld();
-    controller2.DoNotifyAll();
+    // We've seen extra messages about contended locking here. They're OK if e.g. controller1
+    // wakes up spuriously before the notification, which is allowed. But in the normal case,
+    // we should not see contended locking here. And the extra messages seem rare enough that
+    // we can tolerate the spurious failures to catch more bugs. See b/149308087.
+    try (AutoCloseable suppress = SuppressContention(controller2)) {
+      controller2.DoLock();
+      controller2.waitForLockToBeHeld();
+      controller2.DoNotifyAll();
+    }
     controller2.DoUnlock();
     controller1.waitForLockToBeHeld();
     controller1.DoUnlock();
@@ -272,9 +281,12 @@
     controller2.waitForLockToBeHeld();
     controller2.DoWait();
     controller2.waitForNotifySleep();
-    controller1.DoLock();
-    controller1.waitForLockToBeHeld();
-    controller1.DoNotifyAll();
+    try (AutoCloseable suppress = SuppressContention(controller1)) {
+      controller1.DoLock();
+      controller1.waitForLockToBeHeld();
+      controller1.DoNotifyAll();
+      // See comment in testWaitMonitorEnter.
+    }
     controller2.waitForLockToBeHeld();
     controller2.DoUnlock();
   }
@@ -307,6 +319,7 @@
     controller1.DoLock();
     controller1.waitForLockToBeHeld();
     controller1.DoNotifyAll();
+    // See comment in testWaitMonitorEnter.
     controller1.DoUnlock();
     // Wait for controller3 to have locked.
     // We cannot use waitForLockToBeHeld since we could race with the HANDLER waitForLockToBeHeld
@@ -349,6 +362,7 @@
     controller1.DoLock();
     controller1.waitForLockToBeHeld();
     controller1.DoNotifyAll();
+    // See comment in testWaitMonitorEnter.
     controller1.DoUnlock();
     controller2.waitForLockToBeHeld();
     controller2.DoUnlock();
@@ -418,6 +432,7 @@
     controller2.DoLock();
     controller2.waitForLockToBeHeld();
     controller2.DoNotifyAll();
+    // See comment in testWaitMonitorEnter.
     controller2.DoUnlock();
     try {
       controller1.waitForLockToBeHeld();
@@ -594,7 +609,22 @@
     }
   }
 
+  public static AutoCloseable SuppressContention(Monitors.LockController controller) {
+    if (CONTENTION_SUPPRESSED != null) {
+      throw new IllegalStateException("Only one contention suppression is possible at a time.");
+    }
+    CONTENTION_SUPPRESSED = controller;
+    return () -> {
+      CONTENTION_SUPPRESSED = null;
+    };
+  }
+
+  private static Monitors.LockController CONTENTION_SUPPRESSED = null;
+
   public static void handleMonitorEnter(Thread thd, Object lock) {
+    if (CONTENTION_SUPPRESSED != null && CONTENTION_SUPPRESSED.IsWorkerThread(thd)) {
+      return;
+    }
     System.out.println(thd.getName() + " contended-LOCKING " + lock);
     if (HANDLER != null) {
       HANDLER.handleMonitorEnter(thd, lock);
@@ -602,6 +632,9 @@
   }
 
   public static void handleMonitorEntered(Thread thd, Object lock) {
+    if (CONTENTION_SUPPRESSED != null && CONTENTION_SUPPRESSED.IsWorkerThread(thd)) {
+      return;
+    }
     System.out.println(thd.getName() + " LOCKED " + lock);
     if (HANDLER != null) {
       HANDLER.handleMonitorEntered(thd, lock);
diff --git a/test/1933-monitor-current-contended/Android.bp b/test/1933-monitor-current-contended/Android.bp
new file mode 100644
index 0000000..8630325
--- /dev/null
+++ b/test/1933-monitor-current-contended/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1933-monitor-current-contended`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1933-monitor-current-contended",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1933-monitor-current-contended-expected-stdout",
+        ":art-run-test-1933-monitor-current-contended-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1933-monitor-current-contended-expected-stdout",
+    out: ["art-run-test-1933-monitor-current-contended-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1933-monitor-current-contended-expected-stderr",
+    out: ["art-run-test-1933-monitor-current-contended-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/168-vmstack-annotated/expected.txt b/test/1933-monitor-current-contended/expected-stderr.txt
similarity index 100%
copy from test/168-vmstack-annotated/expected.txt
copy to test/1933-monitor-current-contended/expected-stderr.txt
diff --git a/test/1933-monitor-current-contended/expected.txt b/test/1933-monitor-current-contended/expected-stdout.txt
similarity index 100%
rename from test/1933-monitor-current-contended/expected.txt
rename to test/1933-monitor-current-contended/expected-stdout.txt
diff --git a/test/1934-jvmti-signal-thread/Android.bp b/test/1934-jvmti-signal-thread/Android.bp
new file mode 100644
index 0000000..7579834
--- /dev/null
+++ b/test/1934-jvmti-signal-thread/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1934-jvmti-signal-thread`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1934-jvmti-signal-thread",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1934-jvmti-signal-thread-expected-stdout",
+        ":art-run-test-1934-jvmti-signal-thread-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1934-jvmti-signal-thread-expected-stdout",
+    out: ["art-run-test-1934-jvmti-signal-thread-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1934-jvmti-signal-thread-expected-stderr",
+    out: ["art-run-test-1934-jvmti-signal-thread-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/168-vmstack-annotated/expected.txt b/test/1934-jvmti-signal-thread/expected-stderr.txt
similarity index 100%
copy from test/168-vmstack-annotated/expected.txt
copy to test/1934-jvmti-signal-thread/expected-stderr.txt
diff --git a/test/1934-jvmti-signal-thread/expected.txt b/test/1934-jvmti-signal-thread/expected-stdout.txt
similarity index 100%
rename from test/1934-jvmti-signal-thread/expected.txt
rename to test/1934-jvmti-signal-thread/expected-stdout.txt
diff --git a/test/1935-get-set-current-frame-jit/Android.bp b/test/1935-get-set-current-frame-jit/Android.bp
new file mode 100644
index 0000000..0d863b9
--- /dev/null
+++ b/test/1935-get-set-current-frame-jit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1935-get-set-current-frame-jit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1935-get-set-current-frame-jit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1935-get-set-current-frame-jit-expected-stdout",
+        ":art-run-test-1935-get-set-current-frame-jit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1935-get-set-current-frame-jit-expected-stdout",
+    out: ["art-run-test-1935-get-set-current-frame-jit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1935-get-set-current-frame-jit-expected-stderr",
+    out: ["art-run-test-1935-get-set-current-frame-jit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/545-tracing-and-jit/expected.txt b/test/1935-get-set-current-frame-jit/expected-stderr.txt
similarity index 100%
copy from test/545-tracing-and-jit/expected.txt
copy to test/1935-get-set-current-frame-jit/expected-stderr.txt
diff --git a/test/1935-get-set-current-frame-jit/expected.txt b/test/1935-get-set-current-frame-jit/expected-stdout.txt
similarity index 100%
rename from test/1935-get-set-current-frame-jit/expected.txt
rename to test/1935-get-set-current-frame-jit/expected-stdout.txt
diff --git a/test/1936-thread-end-events/Android.bp b/test/1936-thread-end-events/Android.bp
new file mode 100644
index 0000000..3f29c7e
--- /dev/null
+++ b/test/1936-thread-end-events/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1936-thread-end-events`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1936-thread-end-events",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1936-thread-end-events-expected-stdout",
+        ":art-run-test-1936-thread-end-events-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1936-thread-end-events-expected-stdout",
+    out: ["art-run-test-1936-thread-end-events-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1936-thread-end-events-expected-stderr",
+    out: ["art-run-test-1936-thread-end-events-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1936-thread-end-events/check b/test/1936-thread-end-events/check
index 8a84388..0fe4429 100644
--- a/test/1936-thread-end-events/check
+++ b/test/1936-thread-end-events/check
@@ -14,9 +14,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # The RI sends an extra event that art doesn't. Add it to the expected output.
 if [[ "$TEST_RUNTIME" == "jvm" ]]; then
-  patch -p0 expected.txt < jvm-expected.patch >/dev/null
+  patch -p0 expected-stdout.txt < jvm-expected.patch >/dev/null
 fi
 
 ./default-check "$@"
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1936-thread-end-events/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/1936-thread-end-events/expected-stderr.txt
diff --git a/test/1936-thread-end-events/expected.txt b/test/1936-thread-end-events/expected-stdout.txt
similarity index 100%
rename from test/1936-thread-end-events/expected.txt
rename to test/1936-thread-end-events/expected-stdout.txt
diff --git a/test/1937-transform-soft-fail/Android.bp b/test/1937-transform-soft-fail/Android.bp
new file mode 100644
index 0000000..b8fbc0b
--- /dev/null
+++ b/test/1937-transform-soft-fail/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1937-transform-soft-fail`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1937-transform-soft-fail",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1937-transform-soft-fail-expected-stdout",
+        ":art-run-test-1937-transform-soft-fail-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1937-transform-soft-fail-expected-stdout",
+    out: ["art-run-test-1937-transform-soft-fail-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1937-transform-soft-fail-expected-stderr",
+    out: ["art-run-test-1937-transform-soft-fail-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1937-transform-soft-fail/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1937-transform-soft-fail/expected-stderr.txt
diff --git a/test/1937-transform-soft-fail/expected.txt b/test/1937-transform-soft-fail/expected-stdout.txt
similarity index 100%
rename from test/1937-transform-soft-fail/expected.txt
rename to test/1937-transform-soft-fail/expected-stdout.txt
diff --git a/test/1938-transform-abstract-single-impl/Android.bp b/test/1938-transform-abstract-single-impl/Android.bp
new file mode 100644
index 0000000..e4cdf2c
--- /dev/null
+++ b/test/1938-transform-abstract-single-impl/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1938-transform-abstract-single-impl`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1938-transform-abstract-single-impl",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1938-transform-abstract-single-impl-expected-stdout",
+        ":art-run-test-1938-transform-abstract-single-impl-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1938-transform-abstract-single-impl-expected-stdout",
+    out: ["art-run-test-1938-transform-abstract-single-impl-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1938-transform-abstract-single-impl-expected-stderr",
+    out: ["art-run-test-1938-transform-abstract-single-impl-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1938-transform-abstract-single-impl/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1938-transform-abstract-single-impl/expected-stderr.txt
diff --git a/test/1938-transform-abstract-single-impl/expected.txt b/test/1938-transform-abstract-single-impl/expected-stdout.txt
similarity index 100%
rename from test/1938-transform-abstract-single-impl/expected.txt
rename to test/1938-transform-abstract-single-impl/expected-stdout.txt
diff --git a/test/1939-proxy-frames/Android.bp b/test/1939-proxy-frames/Android.bp
new file mode 100644
index 0000000..f68aa24
--- /dev/null
+++ b/test/1939-proxy-frames/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1939-proxy-frames`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1939-proxy-frames",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1939-proxy-frames-expected-stdout",
+        ":art-run-test-1939-proxy-frames-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1939-proxy-frames-expected-stdout",
+    out: ["art-run-test-1939-proxy-frames-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1939-proxy-frames-expected-stderr",
+    out: ["art-run-test-1939-proxy-frames-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1939-proxy-frames/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/1939-proxy-frames/expected-stderr.txt
diff --git a/test/1939-proxy-frames/expected.txt b/test/1939-proxy-frames/expected-stdout.txt
similarity index 100%
rename from test/1939-proxy-frames/expected.txt
rename to test/1939-proxy-frames/expected-stdout.txt
diff --git a/test/1940-ddms-ext/ddm_ext.cc b/test/1940-ddms-ext/ddm_ext.cc
index 452187b..110ad64 100644
--- a/test/1940-ddms-ext/ddm_ext.cc
+++ b/test/1940-ddms-ext/ddm_ext.cc
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#include <queue>
+#include <vector>
+
 #include "jvmti.h"
 
 // Test infrastructure
@@ -33,10 +36,16 @@
                                      jint* len_data_out,
                                      jbyte** data_out);
 
+struct DdmCallbackData {
+ public:
+  DdmCallbackData(jint type, jint size, jbyte* data) : type_(type), data_(data, data + size) {}
+  jint type_;
+  std::vector<jbyte> data_;
+};
 struct DdmsTrackingData {
   DdmHandleChunk send_ddm_chunk;
-  jclass test_klass;
-  jmethodID publish_method;
+  jrawMonitorID callback_mon;
+  std::queue<DdmCallbackData> callbacks_received;
 };
 
 template <typename T>
@@ -111,21 +120,52 @@
   }
 }
 
-static void JNICALL PublishCB(jvmtiEnv* jvmti, JNIEnv* jnienv, jint type, jint size, jbyte* bytes) {
+extern "C" JNIEXPORT void JNICALL Java_art_Test1940_publishListen(JNIEnv* env,
+                                                                  jclass test_klass,
+                                                                  jobject publish) {
+  jmethodID publish_method = env->FromReflectedMethod(publish);
   DdmsTrackingData* data = nullptr;
-  if (JvmtiErrorToException(jnienv, jvmti,
-                            jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) {
+  if (JvmtiErrorToException(
+          env, jvmti_env, jvmti_env->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) {
     return;
   }
-  ScopedLocalRef<jbyteArray> res(jnienv, jnienv->NewByteArray(size));
-  jnienv->SetByteArrayRegion(res.get(), 0, size, bytes);
-  jnienv->CallStaticVoidMethod(data->test_klass, data->publish_method, type, res.get());
+  std::vector<DdmCallbackData> callbacks;
+  while (true) {
+    if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorEnter(data->callback_mon))) {
+      return;
+    }
+    while (data->callbacks_received.empty()) {
+      if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorWait(data->callback_mon, 0))) {
+        CHECK_EQ(JVMTI_ERROR_NONE, jvmti_env->RawMonitorExit(data->callback_mon));
+        return;
+      }
+    }
+    while (!data->callbacks_received.empty()) {
+      callbacks.emplace_back(std::move(data->callbacks_received.front()));
+      data->callbacks_received.pop();
+    }
+    if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(data->callback_mon))) {
+      return;
+    }
+    for (auto cb : callbacks) {
+      ScopedLocalRef<jbyteArray> res(env, env->NewByteArray(cb.data_.size()));
+      env->SetByteArrayRegion(res.get(), 0, cb.data_.size(), cb.data_.data());
+      env->CallStaticVoidMethod(test_klass, publish_method, cb.type_, res.get());
+    }
+    callbacks.clear();
+  }
 }
 
-extern "C" JNIEXPORT void JNICALL Java_art_Test1940_initializeTest(JNIEnv* env,
-                                                                   jclass,
-                                                                   jclass method_klass,
-                                                                   jobject publish_method) {
+static void JNICALL PublishCB(jvmtiEnv* jvmti, jint type, jint size, jbyte* bytes) {
+  DdmsTrackingData* data = nullptr;
+  CHECK_EQ(JVMTI_ERROR_NONE, jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)));
+  CHECK_EQ(JVMTI_ERROR_NONE, jvmti->RawMonitorEnter(data->callback_mon));
+  data->callbacks_received.emplace(type, size, bytes);
+  CHECK_EQ(JVMTI_ERROR_NONE, jvmti->RawMonitorNotifyAll(data->callback_mon));
+  CHECK_EQ(JVMTI_ERROR_NONE, jvmti->RawMonitorExit(data->callback_mon));
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test1940_initializeTest(JNIEnv* env, jclass) {
   void* old_data = nullptr;
   if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetEnvironmentLocalStorage(&old_data))) {
     return;
@@ -134,17 +174,16 @@
     env->ThrowNew(rt_exception.get(), "Environment already has local storage set!");
     return;
   }
-  DdmsTrackingData* data = nullptr;
+  void* mem = nullptr;
   if (JvmtiErrorToException(env,
                             jvmti_env,
                             jvmti_env->Allocate(sizeof(DdmsTrackingData),
-                                                reinterpret_cast<unsigned char**>(&data)))) {
+                                                reinterpret_cast<unsigned char**>(&mem)))) {
     return;
   }
-  memset(data, 0, sizeof(DdmsTrackingData));
-  data->test_klass = reinterpret_cast<jclass>(env->NewGlobalRef(method_klass));
-  data->publish_method = env->FromReflectedMethod(publish_method);
-  if (env->ExceptionCheck()) {
+  DdmsTrackingData* data = new (mem) DdmsTrackingData{};
+  if (JvmtiErrorToException(
+          env, jvmti_env, jvmti_env->CreateRawMonitor("callback-mon", &data->callback_mon))) {
     return;
   }
   // Get the extensions.
@@ -181,7 +220,7 @@
   }
   for (jint i = 0; i < n_ext; i++) {
     jvmtiExtensionEventInfo* cur_info = &events[i];
-    if (strcmp("com.android.art.internal.ddm.publish_chunk", cur_info->id) == 0) {
+    if (strcmp("com.android.art.internal.ddm.publish_chunk_safe", cur_info->id) == 0) {
       found_event = true;
       event_index = cur_info->extension_event_index;
     }
diff --git a/test/1902-suspend/expected.txt b/test/1940-ddms-ext/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/1940-ddms-ext/expected-stderr.txt
diff --git a/test/1940-ddms-ext/expected-stdout.txt b/test/1940-ddms-ext/expected-stdout.txt
new file mode 100644
index 0000000..99a2c52
--- /dev/null
+++ b/test/1940-ddms-ext/expected-stdout.txt
@@ -0,0 +1,24 @@
+Sending data [1, 2, 3, 4, 5, 6, 7, 8]
+MyDdmHandler: Chunk received: Chunk(Type: 0xDEADBEEF, Len: 8, data: [1, 2, 3, 4, 5, 6, 7, 8])
+MyDdmHandler: Putting value 0x800025
+MyDdmHandler: Chunk returned: Chunk(Type: 0xFADE7357, Len: 8, data: [0, 0, 0, 0, 0, -128, 0, 37])
+JVMTI returned chunk: Chunk(Type: 0xFADE7357, Len: 8, data: [0, 0, 0, 0, 0, -128, 0, 37])
+Sending empty data array
+MyDdmHandler: Chunk received: Chunk(Type: 0xDEADBEEF, Len: 0, data: [])
+MyDdmHandler: Putting value 0x1
+MyDdmHandler: Chunk returned: Chunk(Type: 0xFADE7357, Len: 8, data: [0, 0, 0, 0, 0, 0, 0, 1])
+JVMTI returned chunk: Chunk(Type: 0xFADE7357, Len: 8, data: [0, 0, 0, 0, 0, 0, 0, 1])
+Sending chunk: Chunk(Type: 0xDEADBEEF, Len: 8, data: [9, 10, 11, 12, 13, 14, 15, 16])
+Chunk published: Chunk(Type: 0xDEADBEEF, Len: 8, data: [9, 10, 11, 12, 13, 14, 15, 16])
+Sending data [1] to chunk handler -1412567295
+MyDdmHandler: Chunk received: Chunk(Type: 0xABCDEF01, Len: 1, data: [1])
+JVMTI returned chunk: Chunk(Type: 0xFADE7357, Len: 0, data: [])
+Sending data [1] to chunk handler 305419896
+MyDdmHandler: Chunk received: Chunk(Type: 0x12345678, Len: 1, data: [1])
+Got error: JVMTI_ERROR_INTERNAL
+threadNotify started!
+Target thread started!
+Target thread finished!
+threadNotify Disabled!
+Saw expected thread events.
+Expected chunk type published: 1297109829
diff --git a/test/1940-ddms-ext/expected.txt b/test/1940-ddms-ext/expected.txt
deleted file mode 100644
index 5af1116..0000000
--- a/test/1940-ddms-ext/expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-Sending data [1, 2, 3, 4, 5, 6, 7, 8]
-MyDdmHandler: Chunk received: Chunk(Type: 0xDEADBEEF, Len: 8, data: [1, 2, 3, 4, 5, 6, 7, 8])
-MyDdmHandler: Putting value 0x800025
-MyDdmHandler: Chunk returned: Chunk(Type: 0xFADE7357, Len: 8, data: [0, 0, 0, 0, 0, -128, 0, 37])
-JVMTI returned chunk: Chunk(Type: 0xFADE7357, Len: 8, data: [0, 0, 0, 0, 0, -128, 0, 37])
-Sending empty data array
-MyDdmHandler: Chunk received: Chunk(Type: 0xDEADBEEF, Len: 0, data: [])
-MyDdmHandler: Putting value 0x1
-MyDdmHandler: Chunk returned: Chunk(Type: 0xFADE7357, Len: 8, data: [0, 0, 0, 0, 0, 0, 0, 1])
-JVMTI returned chunk: Chunk(Type: 0xFADE7357, Len: 8, data: [0, 0, 0, 0, 0, 0, 0, 1])
-Sending chunk: Chunk(Type: 0xDEADBEEF, Len: 8, data: [9, 10, 11, 12, 13, 14, 15, 16])
-Chunk published: Chunk(Type: 0xDEADBEEF, Len: 8, data: [9, 10, 11, 12, 13, 14, 15, 16])
-Sending data [1] to chunk handler -1412567295
-MyDdmHandler: Chunk received: Chunk(Type: 0xABCDEF01, Len: 1, data: [1])
-JVMTI returned chunk: Chunk(Type: 0xFADE7357, Len: 0, data: [])
-Sending data [1] to chunk handler 305419896
-MyDdmHandler: Chunk received: Chunk(Type: 0x12345678, Len: 1, data: [1])
-Got error: JVMTI_ERROR_INTERNAL
-threadNotify started!
-Target thread started!
-Target thread finished!
-threadNotify Disabled!
-Saw expected thread events.
-Expected chunk type published: 1213221190
-Expected chunk type published: 1297109829
diff --git a/test/1940-ddms-ext/src-art/art/Test1940.java b/test/1940-ddms-ext/src-art/art/Test1940.java
index 2957f63..605e409 100644
--- a/test/1940-ddms-ext/src-art/art/Test1940.java
+++ b/test/1940-ddms-ext/src-art/art/Test1940.java
@@ -21,6 +21,7 @@
 
 import java.lang.reflect.Method;
 import java.util.Arrays;
+import java.util.function.*;
 import java.util.zip.Adler32;
 import java.nio.*;
 
@@ -36,7 +37,7 @@
   public static final boolean PRINT_ALL_CHUNKS = false;
 
   public static interface DdmHandler {
-    public void HandleChunk(int type, byte[] data);
+    public void HandleChunk(int type, byte[] data) throws Exception;
   }
 
   public static final class TestError extends Error {
@@ -49,6 +50,13 @@
     }
   }
 
+  private static boolean chunkEq(Chunk a, Chunk b) {
+    return a.type == b.type &&
+           a.offset == b.offset &&
+           a.length == b.length &&
+           Arrays.equals(a.data, b.data);
+  }
+
   private static String printChunk(Chunk k) {
     byte[] out = new byte[k.length];
     System.arraycopy(k.data, k.offset, out, 0, k.length);
@@ -57,8 +65,8 @@
   }
 
   private static final class MyDdmHandler extends ChunkHandler {
-    public void connected() {}
-    public void disconnected() {}
+    public void onConnected() {}
+    public void onDisconnected() {}
     public Chunk handleChunk(Chunk req) {
       System.out.println("MyDdmHandler: Chunk received: " + printChunk(req));
       if (req.type == MY_DDMS_TYPE) {
@@ -88,7 +96,7 @@
 
   public static DdmHandler CURRENT_HANDLER;
 
-  public static void HandlePublish(int type, byte[] data) {
+  public static void HandlePublish(int type, byte[] data) throws Exception {
     if (PRINT_ALL_CHUNKS) {
       System.out.println(
           "Unknown Chunk published: " + printChunk(new Chunk(type, data, 0, data.length)));
@@ -114,13 +122,43 @@
     return b.getInt() == (int) t.getId();
   }
 
+  public static final class AwaitChunkHandler implements DdmHandler {
+    public final Predicate<Chunk> needle;
+    public final DdmHandler chain;
+    private boolean found = false;
+    public AwaitChunkHandler(Predicate<Chunk> needle, DdmHandler chain) {
+      this.needle = needle;
+      this.chain = chain;
+    }
+    public void HandleChunk(int type, byte[] data) throws Exception {
+      chain.HandleChunk(type, data);
+      Chunk c = new Chunk(type, data, 0, data.length);
+      if (needle.test(c)) {
+        synchronized (this) {
+          found = true;
+          notifyAll();
+        }
+      }
+    }
+    public synchronized void Await() throws Exception {
+      while (!found) {
+        wait();
+      }
+    }
+  }
+
   public static void run() throws Exception {
-    CURRENT_HANDLER = (type, data) -> {
+    DdmHandler BaseHandler = (type, data) -> {
       System.out.println("Chunk published: " + printChunk(new Chunk(type, data, 0, data.length)));
     };
-    initializeTest(
-        Test1940.class,
-        Test1940.class.getDeclaredMethod("HandlePublish", Integer.TYPE, new byte[0].getClass()));
+    CURRENT_HANDLER = BaseHandler;
+    initializeTest();
+    Method publish = Test1940.class.getDeclaredMethod("HandlePublish",
+                                                      Integer.TYPE,
+                                                      new byte[0].getClass());
+    Thread listener = new Thread(() -> { Test1940.publishListen(publish); });
+    listener.setDaemon(true);
+    listener.start();
     // Test sending chunk directly.
     DdmServer.registerHandler(MY_DDMS_TYPE, SINGLE_HANDLER);
     DdmServer.registerHandler(MY_EMPTY_DDMS_TYPE, SINGLE_HANDLER);
@@ -139,8 +177,12 @@
     // Test sending chunk through DdmServer#sendChunk
     Chunk c = new Chunk(
         MY_DDMS_TYPE, new byte[] { 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }, 0, 8);
+    AwaitChunkHandler h = new AwaitChunkHandler((x) -> chunkEq(c, x), CURRENT_HANDLER);
+    CURRENT_HANDLER = h;
     System.out.println("Sending chunk: " + printChunk(c));
     DdmServer.sendChunk(c);
+    h.Await();
+    CURRENT_HANDLER = BaseHandler;
 
     // Test getting back an empty chunk.
     data = new byte[] { 0x1 };
@@ -161,31 +203,35 @@
 
     // Test thread chunks are sent.
     final boolean[] types_seen = new boolean[] { false, false, false };
-    CURRENT_HANDLER = (type, cdata) -> {
-      switch (type) {
-        case TYPE_THCR:
-          types_seen[0] = true;
-          break;
-        case TYPE_THNM:
-          types_seen[1] = true;
-          break;
-        case TYPE_THDE:
-          types_seen[2] = true;
-          break;
-        default:
-          // We don't want to print other types.
-          break;
-      }
-    };
-    DdmVmInternal.threadNotify(true);
+    AwaitChunkHandler wait_thd= new AwaitChunkHandler(
+      (x) -> types_seen[0] && types_seen[1] && types_seen[2],
+      (type, cdata) -> {
+        switch (type) {
+          case TYPE_THCR:
+            types_seen[0] = true;
+            break;
+          case TYPE_THNM:
+            types_seen[1] = true;
+            break;
+          case TYPE_THDE:
+            types_seen[2] = true;
+            break;
+          default:
+            // We don't want to print other types.
+            break;
+        }
+      });
+    CURRENT_HANDLER = wait_thd;
+    DdmVmInternal.setThreadNotifyEnabled(true);
     System.out.println("threadNotify started!");
     final Thread thr = new Thread(() -> { return; }, "THREAD");
     thr.start();
     System.out.println("Target thread started!");
     thr.join();
     System.out.println("Target thread finished!");
-    DdmVmInternal.threadNotify(false);
+    DdmVmInternal.setThreadNotifyEnabled(false);
     System.out.println("threadNotify Disabled!");
+    wait_thd.Await();
     // Make sure we saw at least one of Thread-create, Thread name, & thread death.
     if (!types_seen[0] || !types_seen[1] || !types_seen[2]) {
       System.out.println("Didn't see expected chunks for thread creation! got: " +
@@ -194,26 +240,14 @@
       System.out.println("Saw expected thread events.");
     }
 
-    // Test heap chunks are sent.
-    CURRENT_HANDLER = (type, cdata) -> {
-      // The actual data is far to noisy for this test as it includes information about global heap
-      // state.
-      if (type == TYPE_HPIF) {
-        System.out.println("Expected chunk type published: " + type);
-      }
-    };
-    final int HPIF_WHEN_NOW = 1;
-    if (!DdmVmInternal.heapInfoNotify(HPIF_WHEN_NOW)) {
-      System.out.println("Unexpected failure for heapInfoNotify!");
-    }
-
     // method Tracing
-    CURRENT_HANDLER = (type, cdata) -> {
+    AwaitChunkHandler mpse = new AwaitChunkHandler((x) -> x.type == TYPE_MPSE, (type, cdata) -> {
       // This chunk includes timing and thread information so we just check the type.
       if (type == TYPE_MPSE) {
         System.out.println("Expected chunk type published: " + type);
       }
-    };
+    });
+    CURRENT_HANDLER = mpse;
     VMDebug.startMethodTracingDdms(/*size: default*/0,
                                    /*flags: none*/ 0,
                                    /*sampling*/ false,
@@ -223,6 +257,7 @@
     doNothing();
     doNothing();
     VMDebug.stopMethodTracing();
+    mpse.Await();
   }
 
   private static void doNothing() {}
@@ -230,6 +265,7 @@
     return processChunk(new Chunk(MY_DDMS_TYPE, val, 0, val.length));
   }
 
-  private static native void initializeTest(Class<?> k, Method m);
+  private static native void initializeTest();
   private static native Chunk processChunk(Chunk val);
+  private static native void publishListen(Method publish);
 }
diff --git a/test/1941-dispose-stress/Android.bp b/test/1941-dispose-stress/Android.bp
new file mode 100644
index 0000000..57b604b
--- /dev/null
+++ b/test/1941-dispose-stress/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1941-dispose-stress`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1941-dispose-stress",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1941-dispose-stress-expected-stdout",
+        ":art-run-test-1941-dispose-stress-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1941-dispose-stress-expected-stdout",
+    out: ["art-run-test-1941-dispose-stress-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1941-dispose-stress-expected-stderr",
+    out: ["art-run-test-1941-dispose-stress-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/607-daemon-stress/expected.txt b/test/1941-dispose-stress/expected-stderr.txt
similarity index 100%
copy from test/607-daemon-stress/expected.txt
copy to test/1941-dispose-stress/expected-stderr.txt
diff --git a/test/1941-dispose-stress/expected.txt b/test/1941-dispose-stress/expected-stdout.txt
similarity index 100%
rename from test/1941-dispose-stress/expected.txt
rename to test/1941-dispose-stress/expected-stdout.txt
diff --git a/test/1942-suspend-raw-monitor-exit/Android.bp b/test/1942-suspend-raw-monitor-exit/Android.bp
new file mode 100644
index 0000000..01b8591
--- /dev/null
+++ b/test/1942-suspend-raw-monitor-exit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1942-suspend-raw-monitor-exit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1942-suspend-raw-monitor-exit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1942-suspend-raw-monitor-exit-expected-stdout",
+        ":art-run-test-1942-suspend-raw-monitor-exit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1942-suspend-raw-monitor-exit-expected-stdout",
+    out: ["art-run-test-1942-suspend-raw-monitor-exit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1942-suspend-raw-monitor-exit-expected-stderr",
+    out: ["art-run-test-1942-suspend-raw-monitor-exit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/522-checker-regression-monitor-exit/expected.txt b/test/1942-suspend-raw-monitor-exit/expected-stderr.txt
similarity index 100%
copy from test/522-checker-regression-monitor-exit/expected.txt
copy to test/1942-suspend-raw-monitor-exit/expected-stderr.txt
diff --git a/test/1942-suspend-raw-monitor-exit/expected.txt b/test/1942-suspend-raw-monitor-exit/expected-stdout.txt
similarity index 100%
rename from test/1942-suspend-raw-monitor-exit/expected.txt
rename to test/1942-suspend-raw-monitor-exit/expected-stdout.txt
diff --git a/test/1943-suspend-raw-monitor-wait/Android.bp b/test/1943-suspend-raw-monitor-wait/Android.bp
new file mode 100644
index 0000000..194423f
--- /dev/null
+++ b/test/1943-suspend-raw-monitor-wait/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1943-suspend-raw-monitor-wait`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1943-suspend-raw-monitor-wait",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1943-suspend-raw-monitor-wait-expected-stdout",
+        ":art-run-test-1943-suspend-raw-monitor-wait-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1943-suspend-raw-monitor-wait-expected-stdout",
+    out: ["art-run-test-1943-suspend-raw-monitor-wait-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1943-suspend-raw-monitor-wait-expected-stderr",
+    out: ["art-run-test-1943-suspend-raw-monitor-wait-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/152-dead-large-object/expected.txt b/test/1943-suspend-raw-monitor-wait/expected-stderr.txt
similarity index 100%
copy from test/152-dead-large-object/expected.txt
copy to test/1943-suspend-raw-monitor-wait/expected-stderr.txt
diff --git a/test/1943-suspend-raw-monitor-wait/expected.txt b/test/1943-suspend-raw-monitor-wait/expected-stdout.txt
similarity index 100%
rename from test/1943-suspend-raw-monitor-wait/expected.txt
rename to test/1943-suspend-raw-monitor-wait/expected-stdout.txt
diff --git a/test/1945-proxy-method-arguments/Android.bp b/test/1945-proxy-method-arguments/Android.bp
new file mode 100644
index 0000000..8e0b1fb
--- /dev/null
+++ b/test/1945-proxy-method-arguments/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1945-proxy-method-arguments`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1945-proxy-method-arguments",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1945-proxy-method-arguments-expected-stdout",
+        ":art-run-test-1945-proxy-method-arguments-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1945-proxy-method-arguments-expected-stdout",
+    out: ["art-run-test-1945-proxy-method-arguments-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1945-proxy-method-arguments-expected-stderr",
+    out: ["art-run-test-1945-proxy-method-arguments-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1945-proxy-method-arguments/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/1945-proxy-method-arguments/expected-stderr.txt
diff --git a/test/1945-proxy-method-arguments/expected.txt b/test/1945-proxy-method-arguments/expected-stdout.txt
similarity index 100%
rename from test/1945-proxy-method-arguments/expected.txt
rename to test/1945-proxy-method-arguments/expected-stdout.txt
diff --git a/test/121-modifiers/expected.txt b/test/1946-list-descriptors/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/1946-list-descriptors/expected-stderr.txt
diff --git a/test/1946-list-descriptors/expected.txt b/test/1946-list-descriptors/expected-stdout.txt
similarity index 100%
rename from test/1946-list-descriptors/expected.txt
rename to test/1946-list-descriptors/expected-stdout.txt
diff --git a/test/1947-breakpoint-redefine-deopt/Android.bp b/test/1947-breakpoint-redefine-deopt/Android.bp
new file mode 100644
index 0000000..d03fdad
--- /dev/null
+++ b/test/1947-breakpoint-redefine-deopt/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1947-breakpoint-redefine-deopt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1947-breakpoint-redefine-deopt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1947-breakpoint-redefine-deopt-expected-stdout",
+        ":art-run-test-1947-breakpoint-redefine-deopt-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1947-breakpoint-redefine-deopt-expected-stdout",
+    out: ["art-run-test-1947-breakpoint-redefine-deopt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1947-breakpoint-redefine-deopt-expected-stderr",
+    out: ["art-run-test-1947-breakpoint-redefine-deopt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/513-array-deopt/expected.txt b/test/1947-breakpoint-redefine-deopt/expected-stderr.txt
similarity index 100%
copy from test/513-array-deopt/expected.txt
copy to test/1947-breakpoint-redefine-deopt/expected-stderr.txt
diff --git a/test/1947-breakpoint-redefine-deopt/expected.txt b/test/1947-breakpoint-redefine-deopt/expected-stdout.txt
similarity index 100%
rename from test/1947-breakpoint-redefine-deopt/expected.txt
rename to test/1947-breakpoint-redefine-deopt/expected-stdout.txt
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1948-obsolete-const-method-handle/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1948-obsolete-const-method-handle/expected-stderr.txt
diff --git a/test/1948-obsolete-const-method-handle/expected.txt b/test/1948-obsolete-const-method-handle/expected-stdout.txt
similarity index 100%
rename from test/1948-obsolete-const-method-handle/expected.txt
rename to test/1948-obsolete-const-method-handle/expected-stdout.txt
diff --git a/test/1949-short-dex-file/Android.bp b/test/1949-short-dex-file/Android.bp
new file mode 100644
index 0000000..74980fb
--- /dev/null
+++ b/test/1949-short-dex-file/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1949-short-dex-file`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1949-short-dex-file",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1949-short-dex-file-expected-stdout",
+        ":art-run-test-1949-short-dex-file-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1949-short-dex-file-expected-stdout",
+    out: ["art-run-test-1949-short-dex-file-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1949-short-dex-file-expected-stderr",
+    out: ["art-run-test-1949-short-dex-file-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/438-volatile/expected.txt b/test/1949-short-dex-file/expected-stderr.txt
similarity index 100%
copy from test/438-volatile/expected.txt
copy to test/1949-short-dex-file/expected-stderr.txt
diff --git a/test/1949-short-dex-file/expected.txt b/test/1949-short-dex-file/expected-stdout.txt
similarity index 100%
rename from test/1949-short-dex-file/expected.txt
rename to test/1949-short-dex-file/expected-stdout.txt
diff --git a/test/1950-unprepared-transform/check b/test/1950-unprepared-transform/check
index 8a84388..0fe4429 100755
--- a/test/1950-unprepared-transform/check
+++ b/test/1950-unprepared-transform/check
@@ -14,9 +14,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # The RI sends an extra event that art doesn't. Add it to the expected output.
 if [[ "$TEST_RUNTIME" == "jvm" ]]; then
-  patch -p0 expected.txt < jvm-expected.patch >/dev/null
+  patch -p0 expected-stdout.txt < jvm-expected.patch >/dev/null
 fi
 
 ./default-check "$@"
diff --git a/test/114-ParallelGC/expected.txt b/test/1950-unprepared-transform/expected-stderr.txt
similarity index 100%
copy from test/114-ParallelGC/expected.txt
copy to test/1950-unprepared-transform/expected-stderr.txt
diff --git a/test/1950-unprepared-transform/expected.txt b/test/1950-unprepared-transform/expected-stdout.txt
similarity index 100%
rename from test/1950-unprepared-transform/expected.txt
rename to test/1950-unprepared-transform/expected-stdout.txt
diff --git a/test/1951-monitor-enter-no-suspend/Android.bp b/test/1951-monitor-enter-no-suspend/Android.bp
new file mode 100644
index 0000000..8e523f3
--- /dev/null
+++ b/test/1951-monitor-enter-no-suspend/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1951-monitor-enter-no-suspend`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1951-monitor-enter-no-suspend",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1951-monitor-enter-no-suspend-expected-stdout",
+        ":art-run-test-1951-monitor-enter-no-suspend-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1951-monitor-enter-no-suspend-expected-stdout",
+    out: ["art-run-test-1951-monitor-enter-no-suspend-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1951-monitor-enter-no-suspend-expected-stderr",
+    out: ["art-run-test-1951-monitor-enter-no-suspend-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/1951-monitor-enter-no-suspend/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/1951-monitor-enter-no-suspend/expected-stderr.txt
diff --git a/test/1951-monitor-enter-no-suspend/expected.txt b/test/1951-monitor-enter-no-suspend/expected-stdout.txt
similarity index 100%
rename from test/1951-monitor-enter-no-suspend/expected.txt
rename to test/1951-monitor-enter-no-suspend/expected-stdout.txt
diff --git a/test/1953-pop-frame/Android.bp b/test/1953-pop-frame/Android.bp
new file mode 100644
index 0000000..51da5cc
--- /dev/null
+++ b/test/1953-pop-frame/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1953-pop-frame`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1953-pop-frame",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1953-pop-frame-expected-stdout",
+        ":art-run-test-1953-pop-frame-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1953-pop-frame-expected-stdout",
+    out: ["art-run-test-1953-pop-frame-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1953-pop-frame-expected-stderr",
+    out: ["art-run-test-1953-pop-frame-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1953-pop-frame/check b/test/1953-pop-frame/check
index d552272..24bbf07 100755
--- a/test/1953-pop-frame/check
+++ b/test/1953-pop-frame/check
@@ -14,8 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # The RI has restrictions and bugs around some PopFrame behavior that ART lacks.
 # See b/116003018. Some configurations cannot handle the class load events in
 # quite the right way so they are disabled there too.
 ./default-check "$@" || \
-  (patch -p0 expected.txt < class-loading-expected.patch >/dev/null && ./default-check "$@")
+  (patch -p0 expected-stdout.txt < class-loading-expected.patch >/dev/null && ./default-check "$@")
diff --git a/test/1953-pop-frame/class-loading-expected.patch b/test/1953-pop-frame/class-loading-expected.patch
index 2edef15..1a5eda7 100644
--- a/test/1953-pop-frame/class-loading-expected.patch
+++ b/test/1953-pop-frame/class-loading-expected.patch
@@ -1,4 +1,19 @@
-74a75,94
+36a37,50
+> Test stopped during notifyFramePop without exception on pop of calledFunction
+> Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+> result is StandardTestObject { cnt: 2 } base-call count: 1
+> Test stopped during notifyFramePop without exception on pop of doNothing
+> Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+> result is StandardTestObject { cnt: 1 } base-call count: 1
+> Test stopped during notifyFramePop with exception on pop of calledFunction
+> Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
+> art.Test1953$ExceptionThrowTestObject$TestError thrown and caught!
+> result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
+> Test stopped during notifyFramePop with exception on pop of doThrow
+> Single call with PopFrame on ExceptionCatchTestObject { cnt: 0 } base-call-count: 0
+> art.Test1953$ExceptionCatchTestObject$TestError caught in called function.
+> result is ExceptionCatchTestObject { cnt: 1 } base-call count: 1
+60a75,94
 > Test stopped during a ClassLoad event.
 > Single call with PopFrame on ClassLoadObject { cnt: 0, curClass: 0} base-call-count: 0
 > Failed to pop frame due to java.lang.RuntimeException: JVMTI_ERROR_OPAQUE_FRAME
diff --git a/test/421-large-frame/expected.txt b/test/1953-pop-frame/expected-stderr.txt
similarity index 100%
copy from test/421-large-frame/expected.txt
copy to test/1953-pop-frame/expected-stderr.txt
diff --git a/test/1953-pop-frame/expected-stdout.txt b/test/1953-pop-frame/expected-stdout.txt
new file mode 100644
index 0000000..dafc6b4
--- /dev/null
+++ b/test/1953-pop-frame/expected-stdout.txt
@@ -0,0 +1,87 @@
+Test stopped using breakpoint
+Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+result is StandardTestObject { cnt: 2 } base-call count: 1
+Test stopped using breakpoint with declared synchronized function
+Single call with PopFrame on SynchronizedFunctionTestObject { cnt: 0 } base-call-count: 0
+result is SynchronizedFunctionTestObject { cnt: 2 } base-call count: 1
+Test stopped using breakpoint with synchronized block
+Single call with PopFrame on SynchronizedTestObject { cnt: 0 } base-call-count: 0
+result is SynchronizedTestObject { cnt: 2 } base-call count: 1
+Test stopped on single step
+Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+result is StandardTestObject { cnt: 2 } base-call count: 1
+Test stopped on field access
+Single call with PopFrame on FieldBasedTestObject { cnt: 0, TARGET_FIELD: 0 } base-call-count: 0
+result is FieldBasedTestObject { cnt: 2, TARGET_FIELD: 10 } base-call count: 1
+Test stopped on field modification
+Single call with PopFrame on FieldBasedTestObject { cnt: 0, TARGET_FIELD: 0 } base-call-count: 0
+result is FieldBasedTestObject { cnt: 2, TARGET_FIELD: 10 } base-call count: 1
+Test stopped during Method Exit of doNothing
+Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+result is StandardTestObject { cnt: 1 } base-call count: 1
+Test stopped during Method Enter of doNothing
+Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+result is StandardTestObject { cnt: 1 } base-call count: 1
+Test stopped during Method Exit of calledFunction
+Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+result is StandardTestObject { cnt: 2 } base-call count: 1
+Test stopped during Method Enter of calledFunction
+Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+result is StandardTestObject { cnt: 1 } base-call count: 1
+Test stopped during Method Exit due to exception thrown in same function
+Single call with PopFrame on ExceptionOnceObject { cnt: 0, throwInSub: false } base-call-count: 0
+result is ExceptionOnceObject { cnt: 2, throwInSub: false } base-call count: 1
+Test stopped during Method Exit due to exception thrown in subroutine
+Single call with PopFrame on ExceptionOnceObject { cnt: 0, throwInSub: true } base-call-count: 0
+result is ExceptionOnceObject { cnt: 2, throwInSub: true } base-call count: 1
+Test stopped during ExceptionCatch event of calledFunction (catch in called function, throw in called function)
+Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
+art.Test1953$ExceptionThrowTestObject$TestError caught in same function.
+result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
+Test stopped during ExceptionCatch event of calledFunction (catch in called function, throw in subroutine)
+Single call with PopFrame on ExceptionCatchTestObject { cnt: 0 } base-call-count: 0
+art.Test1953$ExceptionCatchTestObject$TestError caught in called function.
+result is ExceptionCatchTestObject { cnt: 2 } base-call count: 1
+Test stopped during Exception event of calledFunction (catch in calling function)
+Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
+art.Test1953$ExceptionThrowTestObject$TestError thrown and caught!
+result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
+Test stopped during Exception event of calledFunction (catch in called function)
+Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
+art.Test1953$ExceptionThrowTestObject$TestError caught in same function.
+result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
+Test stopped during Exception event of calledFunction (catch in parent of calling function)
+Single call with PopFrame on ExceptionThrowFarTestObject { cnt: 0 } base-call-count: 0
+art.Test1953$ExceptionThrowFarTestObject$TestError thrown and caught!
+result is ExceptionThrowFarTestObject { cnt: 2 } base-call count: 1
+Test stopped during Exception event of calledFunction (catch in called function)
+Single call with PopFrame on ExceptionThrowFarTestObject { cnt: 0 } base-call-count: 0
+art.Test1953$ExceptionThrowFarTestObject$TestError caught in same function.
+result is ExceptionThrowFarTestObject { cnt: 2 } base-call count: 1
+Test stopped during random Suspend.
+Single call with PopFrame on SuspendSuddenlyObject { cnt: 0 } base-call-count: 0
+result is SuspendSuddenlyObject { cnt: 2 } base-call count: 1
+Test redefining frame being popped.
+Single call with PopFrame on RedefineTestObject { states: [] current: ORIGINAL } base-call-count: 0
+result is RedefineTestObject { states: [ORIGINAL, REDEFINED] current: REDEFINED } base-call count: 1
+Test stopped during a native method fails
+Single call with PopFrame on NativeCalledObject { cnt: 0 } base-call-count: 0
+Failed to pop frame due to java.lang.RuntimeException: JVMTI_ERROR_OPAQUE_FRAME
+	art.Test1953.popFrame(Native Method)
+	art.Test1953.runTestOn(Test1953.java)
+	art.Test1953.runTestOn(Test1953.java)
+	art.Test1953.runTests(Test1953.java)
+	<Additional frames hidden>
+result is NativeCalledObject { cnt: 1 } base-call count: 1
+Test stopped in a method called by native fails
+Single call with PopFrame on NativeCallerObject { cnt: 0 } base-call-count: 0
+Failed to pop frame due to java.lang.RuntimeException: JVMTI_ERROR_OPAQUE_FRAME
+	art.Test1953.popFrame(Native Method)
+	art.Test1953.runTestOn(Test1953.java)
+	art.Test1953.runTestOn(Test1953.java)
+	art.Test1953.runTests(Test1953.java)
+	<Additional frames hidden>
+result is NativeCallerObject { cnt: 1 } base-call count: 1
+Test stopped with monitor in enclosing frame.
+Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+result is StandardTestObject { cnt: 2 } base-call count: 1
diff --git a/test/1953-pop-frame/expected.txt b/test/1953-pop-frame/expected.txt
deleted file mode 100644
index 079768d..0000000
--- a/test/1953-pop-frame/expected.txt
+++ /dev/null
@@ -1,101 +0,0 @@
-Test stopped using breakpoint
-Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
-result is StandardTestObject { cnt: 2 } base-call count: 1
-Test stopped using breakpoint with declared synchronized function
-Single call with PopFrame on SynchronizedFunctionTestObject { cnt: 0 } base-call-count: 0
-result is SynchronizedFunctionTestObject { cnt: 2 } base-call count: 1
-Test stopped using breakpoint with synchronized block
-Single call with PopFrame on SynchronizedTestObject { cnt: 0 } base-call-count: 0
-result is SynchronizedTestObject { cnt: 2 } base-call count: 1
-Test stopped on single step
-Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
-result is StandardTestObject { cnt: 2 } base-call count: 1
-Test stopped on field access
-Single call with PopFrame on FieldBasedTestObject { cnt: 0, TARGET_FIELD: 0 } base-call-count: 0
-result is FieldBasedTestObject { cnt: 2, TARGET_FIELD: 10 } base-call count: 1
-Test stopped on field modification
-Single call with PopFrame on FieldBasedTestObject { cnt: 0, TARGET_FIELD: 0 } base-call-count: 0
-result is FieldBasedTestObject { cnt: 2, TARGET_FIELD: 10 } base-call count: 1
-Test stopped during Method Exit of doNothing
-Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
-result is StandardTestObject { cnt: 1 } base-call count: 1
-Test stopped during Method Enter of doNothing
-Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
-result is StandardTestObject { cnt: 1 } base-call count: 1
-Test stopped during Method Exit of calledFunction
-Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
-result is StandardTestObject { cnt: 2 } base-call count: 1
-Test stopped during Method Enter of calledFunction
-Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
-result is StandardTestObject { cnt: 1 } base-call count: 1
-Test stopped during Method Exit due to exception thrown in same function
-Single call with PopFrame on ExceptionOnceObject { cnt: 0, throwInSub: false } base-call-count: 0
-result is ExceptionOnceObject { cnt: 2, throwInSub: false } base-call count: 1
-Test stopped during Method Exit due to exception thrown in subroutine
-Single call with PopFrame on ExceptionOnceObject { cnt: 0, throwInSub: true } base-call-count: 0
-result is ExceptionOnceObject { cnt: 2, throwInSub: true } base-call count: 1
-Test stopped during notifyFramePop without exception on pop of calledFunction
-Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
-result is StandardTestObject { cnt: 2 } base-call count: 1
-Test stopped during notifyFramePop without exception on pop of doNothing
-Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
-result is StandardTestObject { cnt: 1 } base-call count: 1
-Test stopped during notifyFramePop with exception on pop of calledFunction
-Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
-art.Test1953$ExceptionThrowTestObject$TestError thrown and caught!
-result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
-Test stopped during notifyFramePop with exception on pop of doThrow
-Single call with PopFrame on ExceptionCatchTestObject { cnt: 0 } base-call-count: 0
-art.Test1953$ExceptionCatchTestObject$TestError caught in called function.
-result is ExceptionCatchTestObject { cnt: 1 } base-call count: 1
-Test stopped during ExceptionCatch event of calledFunction (catch in called function, throw in called function)
-Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
-art.Test1953$ExceptionThrowTestObject$TestError caught in same function.
-result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
-Test stopped during ExceptionCatch event of calledFunction (catch in called function, throw in subroutine)
-Single call with PopFrame on ExceptionCatchTestObject { cnt: 0 } base-call-count: 0
-art.Test1953$ExceptionCatchTestObject$TestError caught in called function.
-result is ExceptionCatchTestObject { cnt: 2 } base-call count: 1
-Test stopped during Exception event of calledFunction (catch in calling function)
-Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
-art.Test1953$ExceptionThrowTestObject$TestError thrown and caught!
-result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
-Test stopped during Exception event of calledFunction (catch in called function)
-Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
-art.Test1953$ExceptionThrowTestObject$TestError caught in same function.
-result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
-Test stopped during Exception event of calledFunction (catch in parent of calling function)
-Single call with PopFrame on ExceptionThrowFarTestObject { cnt: 0 } base-call-count: 0
-art.Test1953$ExceptionThrowFarTestObject$TestError thrown and caught!
-result is ExceptionThrowFarTestObject { cnt: 2 } base-call count: 1
-Test stopped during Exception event of calledFunction (catch in called function)
-Single call with PopFrame on ExceptionThrowFarTestObject { cnt: 0 } base-call-count: 0
-art.Test1953$ExceptionThrowFarTestObject$TestError caught in same function.
-result is ExceptionThrowFarTestObject { cnt: 2 } base-call count: 1
-Test stopped during random Suspend.
-Single call with PopFrame on SuspendSuddenlyObject { cnt: 0 } base-call-count: 0
-result is SuspendSuddenlyObject { cnt: 2 } base-call count: 1
-Test redefining frame being popped.
-Single call with PopFrame on RedefineTestObject { states: [] current: ORIGINAL } base-call-count: 0
-result is RedefineTestObject { states: [ORIGINAL, REDEFINED] current: REDEFINED } base-call count: 1
-Test stopped during a native method fails
-Single call with PopFrame on NativeCalledObject { cnt: 0 } base-call-count: 0
-Failed to pop frame due to java.lang.RuntimeException: JVMTI_ERROR_OPAQUE_FRAME
-	art.Test1953.popFrame(Native Method)
-	art.Test1953.runTestOn(Test1953.java)
-	art.Test1953.runTestOn(Test1953.java)
-	art.Test1953.runTests(Test1953.java)
-	<Additional frames hidden>
-result is NativeCalledObject { cnt: 1 } base-call count: 1
-Test stopped in a method called by native fails
-Single call with PopFrame on NativeCallerObject { cnt: 0 } base-call-count: 0
-Failed to pop frame due to java.lang.RuntimeException: JVMTI_ERROR_OPAQUE_FRAME
-	art.Test1953.popFrame(Native Method)
-	art.Test1953.runTestOn(Test1953.java)
-	art.Test1953.runTestOn(Test1953.java)
-	art.Test1953.runTests(Test1953.java)
-	<Additional frames hidden>
-result is NativeCallerObject { cnt: 1 } base-call count: 1
-Test stopped with monitor in enclosing frame.
-Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
-result is StandardTestObject { cnt: 2 } base-call count: 1
diff --git a/test/1953-pop-frame/src/art/Test1953.java b/test/1953-pop-frame/src/art/Test1953.java
index ff41d24..366809e 100644
--- a/test/1953-pop-frame/src/art/Test1953.java
+++ b/test/1953-pop-frame/src/art/Test1953.java
@@ -37,6 +37,7 @@
 import static art.SuspendEvents.setupSuspendClassEvent;
 
 public class Test1953 {
+  private static boolean IS_ART = System.getProperty("java.vm.name").equals("Dalvik");
   public final boolean canRunClassLoadTests;
   public static void doNothing() {}
 
@@ -801,29 +802,34 @@
         (thr) -> setupSuspendMethodEvent(exceptionOnceCalledMethod, /*enter*/ false, thr),
         SuspendEvents::clearSuspendMethodEvent);
 
-    System.out.println("Test stopped during notifyFramePop without exception on pop of calledFunction");
-    runTestOn(new StandardTestObject(false),
-        (thr) -> setupSuspendPopFrameEvent(1, doNothingMethod, thr),
-        SuspendEvents::clearSuspendPopFrameEvent);
-
-    System.out.println("Test stopped during notifyFramePop without exception on pop of doNothing");
-    runTestOn(new StandardTestObject(false),
-        (thr) -> setupSuspendPopFrameEvent(0, doNothingMethod, thr),
-        SuspendEvents::clearSuspendPopFrameEvent);
-
     final Method exceptionThrowCalledMethod =
         ExceptionThrowTestObject.class.getDeclaredMethod("calledFunction");
-    System.out.println("Test stopped during notifyFramePop with exception on pop of calledFunction");
-    runTestOn(new ExceptionThrowTestObject(false),
-        (thr) -> setupSuspendPopFrameEvent(0, exceptionThrowCalledMethod, thr),
-        SuspendEvents::clearSuspendPopFrameEvent);
-
     final Method exceptionCatchThrowMethod =
         ExceptionCatchTestObject.class.getDeclaredMethod("doThrow");
-    System.out.println("Test stopped during notifyFramePop with exception on pop of doThrow");
-    runTestOn(new ExceptionCatchTestObject(),
-        (thr) -> setupSuspendPopFrameEvent(0, exceptionCatchThrowMethod, thr),
-        SuspendEvents::clearSuspendPopFrameEvent);
+    // Disable more often then we technically need to in order to avoid the need
+    // for a huge number of possible results and allow the test to be easily
+    // used in CTS.
+    if (IS_ART && canRunClassLoadTests && CanRunClassLoadingTests()) {
+      System.out.println("Test stopped during notifyFramePop without exception on pop of calledFunction");
+      runTestOn(new StandardTestObject(false),
+          (thr) -> setupSuspendPopFrameEvent(1, doNothingMethod, thr),
+          SuspendEvents::clearSuspendPopFrameEvent);
+
+      System.out.println("Test stopped during notifyFramePop without exception on pop of doNothing");
+      runTestOn(new StandardTestObject(false),
+          (thr) -> setupSuspendPopFrameEvent(0, doNothingMethod, thr),
+          SuspendEvents::clearSuspendPopFrameEvent);
+
+      System.out.println("Test stopped during notifyFramePop with exception on pop of calledFunction");
+      runTestOn(new ExceptionThrowTestObject(false),
+          (thr) -> setupSuspendPopFrameEvent(0, exceptionThrowCalledMethod, thr),
+          SuspendEvents::clearSuspendPopFrameEvent);
+
+      System.out.println("Test stopped during notifyFramePop with exception on pop of doThrow");
+      runTestOn(new ExceptionCatchTestObject(),
+          (thr) -> setupSuspendPopFrameEvent(0, exceptionCatchThrowMethod, thr),
+          SuspendEvents::clearSuspendPopFrameEvent);
+    }
 
     System.out.println("Test stopped during ExceptionCatch event of calledFunction " +
         "(catch in called function, throw in called function)");
diff --git a/test/1954-pop-frame-jit/Android.bp b/test/1954-pop-frame-jit/Android.bp
new file mode 100644
index 0000000..fd4398a
--- /dev/null
+++ b/test/1954-pop-frame-jit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1954-pop-frame-jit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1954-pop-frame-jit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1954-pop-frame-jit-expected-stdout",
+        ":art-run-test-1954-pop-frame-jit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1954-pop-frame-jit-expected-stdout",
+    out: ["art-run-test-1954-pop-frame-jit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1954-pop-frame-jit-expected-stderr",
+    out: ["art-run-test-1954-pop-frame-jit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1954-pop-frame-jit/check b/test/1954-pop-frame-jit/check
index 10b87cc..e25838a 100755
--- a/test/1954-pop-frame-jit/check
+++ b/test/1954-pop-frame-jit/check
@@ -14,8 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # The RI has restrictions and bugs around some PopFrame behavior that ART lacks.
 # See b/116003018. Some configurations cannot handle the class load events in
 # quite the right way so they are disabled there too.
 ./default-check "$@" || \
-  (patch -p0 expected.txt < jvm-expected.patch >/dev/null && ./default-check "$@")
+  (patch -p0 expected-stdout.txt < jvm-expected.patch >/dev/null && ./default-check "$@")
diff --git a/test/545-tracing-and-jit/expected.txt b/test/1954-pop-frame-jit/expected-stderr.txt
similarity index 100%
copy from test/545-tracing-and-jit/expected.txt
copy to test/1954-pop-frame-jit/expected-stderr.txt
diff --git a/test/1954-pop-frame-jit/expected.txt b/test/1954-pop-frame-jit/expected-stdout.txt
similarity index 100%
rename from test/1954-pop-frame-jit/expected.txt
rename to test/1954-pop-frame-jit/expected-stdout.txt
diff --git a/test/1954-pop-frame-jit/jvm-expected.patch b/test/1954-pop-frame-jit/jvm-expected.patch
index 718f8ad..6539d56 100644
--- a/test/1954-pop-frame-jit/jvm-expected.patch
+++ b/test/1954-pop-frame-jit/jvm-expected.patch
@@ -1,4 +1,19 @@
-75,94d74
+37,50d36
+< Test stopped during notifyFramePop without exception on pop of calledFunction
+< Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+< result is StandardTestObject { cnt: 2 } base-call count: 1
+< Test stopped during notifyFramePop without exception on pop of doNothing
+< Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+< result is StandardTestObject { cnt: 1 } base-call count: 1
+< Test stopped during notifyFramePop with exception on pop of calledFunction
+< Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
+< art.Test1953$ExceptionThrowTestObject$TestError thrown and caught!
+< result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
+< Test stopped during notifyFramePop with exception on pop of doThrow
+< Single call with PopFrame on ExceptionCatchTestObject { cnt: 0 } base-call-count: 0
+< art.Test1953$ExceptionCatchTestObject$TestError caught in called function.
+< result is ExceptionCatchTestObject { cnt: 1 } base-call count: 1
+75,94d60
 < Test stopped during a ClassLoad event.
 < Single call with PopFrame on ClassLoadObject { cnt: 0, curClass: 0} base-call-count: 0
 < Failed to pop frame due to java.lang.RuntimeException: JVMTI_ERROR_OPAQUE_FRAME
diff --git a/test/1955-pop-frame-jit-called/Android.bp b/test/1955-pop-frame-jit-called/Android.bp
new file mode 100644
index 0000000..4e59614
--- /dev/null
+++ b/test/1955-pop-frame-jit-called/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1955-pop-frame-jit-called`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1955-pop-frame-jit-called",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1955-pop-frame-jit-called-expected-stdout",
+        ":art-run-test-1955-pop-frame-jit-called-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1955-pop-frame-jit-called-expected-stdout",
+    out: ["art-run-test-1955-pop-frame-jit-called-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1955-pop-frame-jit-called-expected-stderr",
+    out: ["art-run-test-1955-pop-frame-jit-called-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1955-pop-frame-jit-called/check b/test/1955-pop-frame-jit-called/check
index 10b87cc..e25838a 100755
--- a/test/1955-pop-frame-jit-called/check
+++ b/test/1955-pop-frame-jit-called/check
@@ -14,8 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # The RI has restrictions and bugs around some PopFrame behavior that ART lacks.
 # See b/116003018. Some configurations cannot handle the class load events in
 # quite the right way so they are disabled there too.
 ./default-check "$@" || \
-  (patch -p0 expected.txt < jvm-expected.patch >/dev/null && ./default-check "$@")
+  (patch -p0 expected-stdout.txt < jvm-expected.patch >/dev/null && ./default-check "$@")
diff --git a/test/168-vmstack-annotated/expected.txt b/test/1955-pop-frame-jit-called/expected-stderr.txt
similarity index 100%
copy from test/168-vmstack-annotated/expected.txt
copy to test/1955-pop-frame-jit-called/expected-stderr.txt
diff --git a/test/1955-pop-frame-jit-called/expected.txt b/test/1955-pop-frame-jit-called/expected-stdout.txt
similarity index 100%
rename from test/1955-pop-frame-jit-called/expected.txt
rename to test/1955-pop-frame-jit-called/expected-stdout.txt
diff --git a/test/1955-pop-frame-jit-called/jvm-expected.patch b/test/1955-pop-frame-jit-called/jvm-expected.patch
index 718f8ad..6539d56 100644
--- a/test/1955-pop-frame-jit-called/jvm-expected.patch
+++ b/test/1955-pop-frame-jit-called/jvm-expected.patch
@@ -1,4 +1,19 @@
-75,94d74
+37,50d36
+< Test stopped during notifyFramePop without exception on pop of calledFunction
+< Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+< result is StandardTestObject { cnt: 2 } base-call count: 1
+< Test stopped during notifyFramePop without exception on pop of doNothing
+< Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+< result is StandardTestObject { cnt: 1 } base-call count: 1
+< Test stopped during notifyFramePop with exception on pop of calledFunction
+< Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
+< art.Test1953$ExceptionThrowTestObject$TestError thrown and caught!
+< result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
+< Test stopped during notifyFramePop with exception on pop of doThrow
+< Single call with PopFrame on ExceptionCatchTestObject { cnt: 0 } base-call-count: 0
+< art.Test1953$ExceptionCatchTestObject$TestError caught in called function.
+< result is ExceptionCatchTestObject { cnt: 1 } base-call count: 1
+75,94d60
 < Test stopped during a ClassLoad event.
 < Single call with PopFrame on ClassLoadObject { cnt: 0, curClass: 0} base-call-count: 0
 < Failed to pop frame due to java.lang.RuntimeException: JVMTI_ERROR_OPAQUE_FRAME
diff --git a/test/1956-pop-frame-jit-calling/Android.bp b/test/1956-pop-frame-jit-calling/Android.bp
new file mode 100644
index 0000000..c3c96bc
--- /dev/null
+++ b/test/1956-pop-frame-jit-calling/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1956-pop-frame-jit-calling`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1956-pop-frame-jit-calling",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1956-pop-frame-jit-calling-expected-stdout",
+        ":art-run-test-1956-pop-frame-jit-calling-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1956-pop-frame-jit-calling-expected-stdout",
+    out: ["art-run-test-1956-pop-frame-jit-calling-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1956-pop-frame-jit-calling-expected-stderr",
+    out: ["art-run-test-1956-pop-frame-jit-calling-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1956-pop-frame-jit-calling/check b/test/1956-pop-frame-jit-calling/check
index 10b87cc..e25838a 100755
--- a/test/1956-pop-frame-jit-calling/check
+++ b/test/1956-pop-frame-jit-calling/check
@@ -14,8 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # The RI has restrictions and bugs around some PopFrame behavior that ART lacks.
 # See b/116003018. Some configurations cannot handle the class load events in
 # quite the right way so they are disabled there too.
 ./default-check "$@" || \
-  (patch -p0 expected.txt < jvm-expected.patch >/dev/null && ./default-check "$@")
+  (patch -p0 expected-stdout.txt < jvm-expected.patch >/dev/null && ./default-check "$@")
diff --git a/test/2020-InvokeVirtual-Inlining/expected.txt b/test/1956-pop-frame-jit-calling/expected-stderr.txt
similarity index 100%
copy from test/2020-InvokeVirtual-Inlining/expected.txt
copy to test/1956-pop-frame-jit-calling/expected-stderr.txt
diff --git a/test/1956-pop-frame-jit-calling/expected.txt b/test/1956-pop-frame-jit-calling/expected-stdout.txt
similarity index 100%
rename from test/1956-pop-frame-jit-calling/expected.txt
rename to test/1956-pop-frame-jit-calling/expected-stdout.txt
diff --git a/test/1956-pop-frame-jit-calling/jvm-expected.patch b/test/1956-pop-frame-jit-calling/jvm-expected.patch
index 718f8ad..6539d56 100644
--- a/test/1956-pop-frame-jit-calling/jvm-expected.patch
+++ b/test/1956-pop-frame-jit-calling/jvm-expected.patch
@@ -1,4 +1,19 @@
-75,94d74
+37,50d36
+< Test stopped during notifyFramePop without exception on pop of calledFunction
+< Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+< result is StandardTestObject { cnt: 2 } base-call count: 1
+< Test stopped during notifyFramePop without exception on pop of doNothing
+< Single call with PopFrame on StandardTestObject { cnt: 0 } base-call-count: 0
+< result is StandardTestObject { cnt: 1 } base-call count: 1
+< Test stopped during notifyFramePop with exception on pop of calledFunction
+< Single call with PopFrame on ExceptionThrowTestObject { cnt: 0 } base-call-count: 0
+< art.Test1953$ExceptionThrowTestObject$TestError thrown and caught!
+< result is ExceptionThrowTestObject { cnt: 2 } base-call count: 1
+< Test stopped during notifyFramePop with exception on pop of doThrow
+< Single call with PopFrame on ExceptionCatchTestObject { cnt: 0 } base-call-count: 0
+< art.Test1953$ExceptionCatchTestObject$TestError caught in called function.
+< result is ExceptionCatchTestObject { cnt: 1 } base-call count: 1
+75,94d60
 < Test stopped during a ClassLoad event.
 < Single call with PopFrame on ClassLoadObject { cnt: 0, curClass: 0} base-call-count: 0
 < Failed to pop frame due to java.lang.RuntimeException: JVMTI_ERROR_OPAQUE_FRAME
diff --git a/test/1957-error-ext/Android.bp b/test/1957-error-ext/Android.bp
new file mode 100644
index 0000000..22a716a
--- /dev/null
+++ b/test/1957-error-ext/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1957-error-ext`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1957-error-ext",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1957-error-ext-expected-stdout",
+        ":art-run-test-1957-error-ext-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1957-error-ext-expected-stdout",
+    out: ["art-run-test-1957-error-ext-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1957-error-ext-expected-stderr",
+    out: ["art-run-test-1957-error-ext-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/1957-error-ext/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/1957-error-ext/expected-stderr.txt
diff --git a/test/1957-error-ext/expected.txt b/test/1957-error-ext/expected-stdout.txt
similarity index 100%
rename from test/1957-error-ext/expected.txt
rename to test/1957-error-ext/expected-stdout.txt
diff --git a/test/1958-transform-try-jit/Android.bp b/test/1958-transform-try-jit/Android.bp
new file mode 100644
index 0000000..c7b026e
--- /dev/null
+++ b/test/1958-transform-try-jit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1958-transform-try-jit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1958-transform-try-jit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1958-transform-try-jit-expected-stdout",
+        ":art-run-test-1958-transform-try-jit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1958-transform-try-jit-expected-stdout",
+    out: ["art-run-test-1958-transform-try-jit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1958-transform-try-jit-expected-stderr",
+    out: ["art-run-test-1958-transform-try-jit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/545-tracing-and-jit/expected.txt b/test/1958-transform-try-jit/expected-stderr.txt
similarity index 100%
copy from test/545-tracing-and-jit/expected.txt
copy to test/1958-transform-try-jit/expected-stderr.txt
diff --git a/test/1958-transform-try-jit/expected.txt b/test/1958-transform-try-jit/expected-stdout.txt
similarity index 100%
rename from test/1958-transform-try-jit/expected.txt
rename to test/1958-transform-try-jit/expected-stdout.txt
diff --git a/test/1959-redefine-object-instrument/Android.bp b/test/1959-redefine-object-instrument/Android.bp
new file mode 100644
index 0000000..143d5c6
--- /dev/null
+++ b/test/1959-redefine-object-instrument/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1959-redefine-object-instrument`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1959-redefine-object-instrument",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1959-redefine-object-instrument-expected-stdout",
+        ":art-run-test-1959-redefine-object-instrument-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1959-redefine-object-instrument-expected-stdout",
+    out: ["art-run-test-1959-redefine-object-instrument-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1959-redefine-object-instrument-expected-stderr",
+    out: ["art-run-test-1959-redefine-object-instrument-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1959-redefine-object-instrument/expected.txt b/test/1959-redefine-object-instrument/expected-stderr.txt
similarity index 100%
rename from test/1959-redefine-object-instrument/expected.txt
rename to test/1959-redefine-object-instrument/expected-stderr.txt
diff --git a/test/1959-redefine-object-instrument/expected.txt b/test/1959-redefine-object-instrument/expected-stdout.txt
similarity index 100%
copy from test/1959-redefine-object-instrument/expected.txt
copy to test/1959-redefine-object-instrument/expected-stdout.txt
diff --git a/test/1959-redefine-object-instrument/info.txt b/test/1959-redefine-object-instrument/info.txt
index d15c0e0..c16504d 100644
--- a/test/1959-redefine-object-instrument/info.txt
+++ b/test/1959-redefine-object-instrument/info.txt
@@ -3,7 +3,7 @@
 
 Redefining a class does not update the instrumentation stack of a thread.
 This is generally fine because the method pointer in the instrumentation
-stack is only used for some sanity-checks, logging and method-exit events
+stack is only used for some soundness checks, logging and method-exit events
 (where it being the non-obsolete version is advantageous). Unfortunately some
-of the checks fail to account for obsolete methods and can fail sanity
-checks.
\ No newline at end of file
+of the checks fail to account for obsolete methods and can fail soundness
+checks.
diff --git a/test/1959-redefine-object-instrument/src/Main.java b/test/1959-redefine-object-instrument/src/Main.java
index b3201f6..4aabd5f 100644
--- a/test/1959-redefine-object-instrument/src/Main.java
+++ b/test/1959-redefine-object-instrument/src/Main.java
@@ -39,7 +39,7 @@
 
   public static void doTest() throws Exception {
     final Object lock = new Object();
-    Breakpoint.Manager man = new Breakpoint.Manager();
+    Breakpoint.Manager manager = new Breakpoint.Manager();
     Breakpoint.startBreakpointWatch(
         Main.class,
         Main.class.getDeclaredMethod("notifyBreakpointReached", Thread.class, Executable.class, Long.TYPE),
@@ -56,15 +56,15 @@
       }
     });
     // set the breakpoint.
-    man.setBreakpoint(Main.class.getDeclaredMethod("doNothing"), 0l);
+    manager.setBreakpoint(Main.class.getDeclaredMethod("doNothing"), 0l);
     thr.start();
     while (!started || thr.getState() != Thread.State.TIMED_WAITING);
     // Redefine while thread is paused.
     forceRedefine(Object.class, Thread.currentThread());
     // Clear breakpoints.
-    man.clearAllBreakpoints();
+    manager.clearAllBreakpoints();
     // set the breakpoint again.
-    man.setBreakpoint(Main.class.getDeclaredMethod("doNothing"), 0l);
+    manager.setBreakpoint(Main.class.getDeclaredMethod("doNothing"), 0l);
     // Wakeup
     synchronized(lock) {
       lock.notifyAll();
diff --git a/test/1960-checker-bounds-codegen/Android.bp b/test/1960-checker-bounds-codegen/Android.bp
new file mode 100644
index 0000000..efb2b49
--- /dev/null
+++ b/test/1960-checker-bounds-codegen/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1960-checker-bounds-codegen`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1960-checker-bounds-codegen",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1960-checker-bounds-codegen-expected-stdout",
+        ":art-run-test-1960-checker-bounds-codegen-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1960-checker-bounds-codegen-expected-stdout",
+    out: ["art-run-test-1960-checker-bounds-codegen-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1960-checker-bounds-codegen-expected-stderr",
+    out: ["art-run-test-1960-checker-bounds-codegen-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/132-daemon-locks-shutdown/expected.txt b/test/1960-checker-bounds-codegen/expected-stderr.txt
similarity index 100%
copy from test/132-daemon-locks-shutdown/expected.txt
copy to test/1960-checker-bounds-codegen/expected-stderr.txt
diff --git a/test/1960-checker-bounds-codegen/expected.txt b/test/1960-checker-bounds-codegen/expected-stdout.txt
similarity index 100%
rename from test/1960-checker-bounds-codegen/expected.txt
rename to test/1960-checker-bounds-codegen/expected-stdout.txt
diff --git a/test/1960-obsolete-jit-multithread-native/Android.bp b/test/1960-obsolete-jit-multithread-native/Android.bp
new file mode 100644
index 0000000..6e6a8eb
--- /dev/null
+++ b/test/1960-obsolete-jit-multithread-native/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1960-obsolete-jit-multithread-native`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1960-obsolete-jit-multithread-native",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1960-obsolete-jit-multithread-native-expected-stdout",
+        ":art-run-test-1960-obsolete-jit-multithread-native-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1960-obsolete-jit-multithread-native-expected-stdout",
+    out: ["art-run-test-1960-obsolete-jit-multithread-native-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1960-obsolete-jit-multithread-native-expected-stderr",
+    out: ["art-run-test-1960-obsolete-jit-multithread-native-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/1960-obsolete-jit-multithread-native/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/1960-obsolete-jit-multithread-native/expected-stderr.txt
diff --git a/test/1960-obsolete-jit-multithread-native/expected.txt b/test/1960-obsolete-jit-multithread-native/expected-stdout.txt
similarity index 100%
rename from test/1960-obsolete-jit-multithread-native/expected.txt
rename to test/1960-obsolete-jit-multithread-native/expected-stdout.txt
diff --git a/test/1961-checker-loop-vectorizer/Android.bp b/test/1961-checker-loop-vectorizer/Android.bp
new file mode 100644
index 0000000..43bb4b9
--- /dev/null
+++ b/test/1961-checker-loop-vectorizer/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1961-checker-loop-vectorizer`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1961-checker-loop-vectorizer",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1961-checker-loop-vectorizer-expected-stdout",
+        ":art-run-test-1961-checker-loop-vectorizer-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1961-checker-loop-vectorizer-expected-stdout",
+    out: ["art-run-test-1961-checker-loop-vectorizer-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1961-checker-loop-vectorizer-expected-stderr",
+    out: ["art-run-test-1961-checker-loop-vectorizer-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-throw-with-finalizer/expected.txt b/test/1961-checker-loop-vectorizer/expected-stderr.txt
similarity index 100%
copy from test/080-oom-throw-with-finalizer/expected.txt
copy to test/1961-checker-loop-vectorizer/expected-stderr.txt
diff --git a/test/1961-checker-loop-vectorizer/expected.txt b/test/1961-checker-loop-vectorizer/expected-stdout.txt
similarity index 100%
rename from test/1961-checker-loop-vectorizer/expected.txt
rename to test/1961-checker-loop-vectorizer/expected-stdout.txt
diff --git a/test/1961-obsolete-jit-multithread/Android.bp b/test/1961-obsolete-jit-multithread/Android.bp
new file mode 100644
index 0000000..0e69c17
--- /dev/null
+++ b/test/1961-obsolete-jit-multithread/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1961-obsolete-jit-multithread`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1961-obsolete-jit-multithread",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1961-obsolete-jit-multithread-expected-stdout",
+        ":art-run-test-1961-obsolete-jit-multithread-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1961-obsolete-jit-multithread-expected-stdout",
+    out: ["art-run-test-1961-obsolete-jit-multithread-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1961-obsolete-jit-multithread-expected-stderr",
+    out: ["art-run-test-1961-obsolete-jit-multithread-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2001-virtual-structural-multithread/expected.txt b/test/1961-obsolete-jit-multithread/expected-stderr.txt
similarity index 100%
copy from test/2001-virtual-structural-multithread/expected.txt
copy to test/1961-obsolete-jit-multithread/expected-stderr.txt
diff --git a/test/1961-obsolete-jit-multithread/expected.txt b/test/1961-obsolete-jit-multithread/expected-stdout.txt
similarity index 100%
rename from test/1961-obsolete-jit-multithread/expected.txt
rename to test/1961-obsolete-jit-multithread/expected-stdout.txt
diff --git a/test/1962-multi-thread-events/Android.bp b/test/1962-multi-thread-events/Android.bp
new file mode 100644
index 0000000..f31b753
--- /dev/null
+++ b/test/1962-multi-thread-events/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1962-multi-thread-events`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1962-multi-thread-events",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1962-multi-thread-events-expected-stdout",
+        ":art-run-test-1962-multi-thread-events-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1962-multi-thread-events-expected-stdout",
+    out: ["art-run-test-1962-multi-thread-events-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1962-multi-thread-events-expected-stderr",
+    out: ["art-run-test-1962-multi-thread-events-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/1962-multi-thread-events/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/1962-multi-thread-events/expected-stderr.txt
diff --git a/test/1962-multi-thread-events/expected.txt b/test/1962-multi-thread-events/expected-stdout.txt
similarity index 100%
rename from test/1962-multi-thread-events/expected.txt
rename to test/1962-multi-thread-events/expected-stdout.txt
diff --git a/test/1963-add-to-dex-classloader-in-memory/Android.bp b/test/1963-add-to-dex-classloader-in-memory/Android.bp
new file mode 100644
index 0000000..50a1e16
--- /dev/null
+++ b/test/1963-add-to-dex-classloader-in-memory/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1963-add-to-dex-classloader-in-memory`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1963-add-to-dex-classloader-in-memory",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1963-add-to-dex-classloader-in-memory-expected-stdout",
+        ":art-run-test-1963-add-to-dex-classloader-in-memory-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1963-add-to-dex-classloader-in-memory-expected-stdout",
+    out: ["art-run-test-1963-add-to-dex-classloader-in-memory-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1963-add-to-dex-classloader-in-memory-expected-stderr",
+    out: ["art-run-test-1963-add-to-dex-classloader-in-memory-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1963-add-to-dex-classloader-in-memory/check b/test/1963-add-to-dex-classloader-in-memory/check
index ae1ebf3..d536891 100755
--- a/test/1963-add-to-dex-classloader-in-memory/check
+++ b/test/1963-add-to-dex-classloader-in-memory/check
@@ -14,6 +14,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Some of our test devices are so old that they don't have memfd_create and are setup in such a way
 # that tmpfile() doesn't work. In these cases this test cannot complete successfully.
 
diff --git a/test/1900-track-alloc/expected.txt b/test/1963-add-to-dex-classloader-in-memory/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1963-add-to-dex-classloader-in-memory/expected-stderr.txt
diff --git a/test/1963-add-to-dex-classloader-in-memory/expected.txt b/test/1963-add-to-dex-classloader-in-memory/expected-stdout.txt
similarity index 100%
rename from test/1963-add-to-dex-classloader-in-memory/expected.txt
rename to test/1963-add-to-dex-classloader-in-memory/expected-stdout.txt
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1964-add-to-dex-classloader-file/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1964-add-to-dex-classloader-file/expected-stderr.txt
diff --git a/test/1964-add-to-dex-classloader-file/expected.txt b/test/1964-add-to-dex-classloader-file/expected-stdout.txt
similarity index 100%
rename from test/1964-add-to-dex-classloader-file/expected.txt
rename to test/1964-add-to-dex-classloader-file/expected-stdout.txt
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1965-get-set-local-primitive-no-tables/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/1965-get-set-local-primitive-no-tables/expected-stderr.txt
diff --git a/test/1965-get-set-local-primitive-no-tables/expected.txt b/test/1965-get-set-local-primitive-no-tables/expected-stdout.txt
similarity index 100%
rename from test/1965-get-set-local-primitive-no-tables/expected.txt
rename to test/1965-get-set-local-primitive-no-tables/expected-stdout.txt
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1966-get-set-local-objects-no-table/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1966-get-set-local-objects-no-table/expected-stderr.txt
diff --git a/test/1966-get-set-local-objects-no-table/expected.txt b/test/1966-get-set-local-objects-no-table/expected-stdout.txt
similarity index 100%
rename from test/1966-get-set-local-objects-no-table/expected.txt
rename to test/1966-get-set-local-objects-no-table/expected-stdout.txt
diff --git a/test/1967-get-set-local-bad-slot/Android.bp b/test/1967-get-set-local-bad-slot/Android.bp
new file mode 100644
index 0000000..ff9ddbe
--- /dev/null
+++ b/test/1967-get-set-local-bad-slot/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1967-get-set-local-bad-slot`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1967-get-set-local-bad-slot",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1967-get-set-local-bad-slot-expected-stdout",
+        ":art-run-test-1967-get-set-local-bad-slot-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1967-get-set-local-bad-slot-expected-stdout",
+    out: ["art-run-test-1967-get-set-local-bad-slot-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1967-get-set-local-bad-slot-expected-stderr",
+    out: ["art-run-test-1967-get-set-local-bad-slot-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/152-dead-large-object/expected.txt b/test/1967-get-set-local-bad-slot/expected-stderr.txt
similarity index 100%
copy from test/152-dead-large-object/expected.txt
copy to test/1967-get-set-local-bad-slot/expected-stderr.txt
diff --git a/test/1967-get-set-local-bad-slot/expected.txt b/test/1967-get-set-local-bad-slot/expected-stdout.txt
similarity index 100%
rename from test/1967-get-set-local-bad-slot/expected.txt
rename to test/1967-get-set-local-bad-slot/expected-stdout.txt
diff --git a/test/1968-force-early-return/Android.bp b/test/1968-force-early-return/Android.bp
new file mode 100644
index 0000000..01abda0
--- /dev/null
+++ b/test/1968-force-early-return/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1968-force-early-return`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1968-force-early-return",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1968-force-early-return-expected-stdout",
+        ":art-run-test-1968-force-early-return-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1968-force-early-return-expected-stdout",
+    out: ["art-run-test-1968-force-early-return-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1968-force-early-return-expected-stderr",
+    out: ["art-run-test-1968-force-early-return-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/478-checker-inline-noreturn/expected.txt b/test/1968-force-early-return/expected-stderr.txt
similarity index 100%
copy from test/478-checker-inline-noreturn/expected.txt
copy to test/1968-force-early-return/expected-stderr.txt
diff --git a/test/1968-force-early-return/expected.txt b/test/1968-force-early-return/expected-stdout.txt
similarity index 100%
rename from test/1968-force-early-return/expected.txt
rename to test/1968-force-early-return/expected-stdout.txt
diff --git a/test/1969-force-early-return-void/Android.bp b/test/1969-force-early-return-void/Android.bp
new file mode 100644
index 0000000..dc4414b
--- /dev/null
+++ b/test/1969-force-early-return-void/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1969-force-early-return-void`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1969-force-early-return-void",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1969-force-early-return-void-expected-stdout",
+        ":art-run-test-1969-force-early-return-void-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1969-force-early-return-void-expected-stdout",
+    out: ["art-run-test-1969-force-early-return-void-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1969-force-early-return-void-expected-stderr",
+    out: ["art-run-test-1969-force-early-return-void-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1969-force-early-return-void/check b/test/1969-force-early-return-void/check
index d552272..24bbf07 100755
--- a/test/1969-force-early-return-void/check
+++ b/test/1969-force-early-return-void/check
@@ -14,8 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # The RI has restrictions and bugs around some PopFrame behavior that ART lacks.
 # See b/116003018. Some configurations cannot handle the class load events in
 # quite the right way so they are disabled there too.
 ./default-check "$@" || \
-  (patch -p0 expected.txt < class-loading-expected.patch >/dev/null && ./default-check "$@")
+  (patch -p0 expected-stdout.txt < class-loading-expected.patch >/dev/null && ./default-check "$@")
diff --git a/test/168-vmstack-annotated/expected.txt b/test/1969-force-early-return-void/expected-stderr.txt
similarity index 100%
copy from test/168-vmstack-annotated/expected.txt
copy to test/1969-force-early-return-void/expected-stderr.txt
diff --git a/test/1969-force-early-return-void/expected.txt b/test/1969-force-early-return-void/expected-stdout.txt
similarity index 100%
rename from test/1969-force-early-return-void/expected.txt
rename to test/1969-force-early-return-void/expected-stdout.txt
diff --git a/test/1970-force-early-return-long/Android.bp b/test/1970-force-early-return-long/Android.bp
new file mode 100644
index 0000000..fb24f51
--- /dev/null
+++ b/test/1970-force-early-return-long/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1970-force-early-return-long`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1970-force-early-return-long",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1970-force-early-return-long-expected-stdout",
+        ":art-run-test-1970-force-early-return-long-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1970-force-early-return-long-expected-stdout",
+    out: ["art-run-test-1970-force-early-return-long-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1970-force-early-return-long-expected-stderr",
+    out: ["art-run-test-1970-force-early-return-long-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1970-force-early-return-long/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1970-force-early-return-long/expected-stderr.txt
diff --git a/test/1970-force-early-return-long/expected.txt b/test/1970-force-early-return-long/expected-stdout.txt
similarity index 100%
rename from test/1970-force-early-return-long/expected.txt
rename to test/1970-force-early-return-long/expected-stdout.txt
diff --git a/test/1971-multi-force-early-return/Android.bp b/test/1971-multi-force-early-return/Android.bp
new file mode 100644
index 0000000..899bacd
--- /dev/null
+++ b/test/1971-multi-force-early-return/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1971-multi-force-early-return`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1971-multi-force-early-return",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1971-multi-force-early-return-expected-stdout",
+        ":art-run-test-1971-multi-force-early-return-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1971-multi-force-early-return-expected-stdout",
+    out: ["art-run-test-1971-multi-force-early-return-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1971-multi-force-early-return-expected-stderr",
+    out: ["art-run-test-1971-multi-force-early-return-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/478-checker-inline-noreturn/expected.txt b/test/1971-multi-force-early-return/expected-stderr.txt
similarity index 100%
copy from test/478-checker-inline-noreturn/expected.txt
copy to test/1971-multi-force-early-return/expected-stderr.txt
diff --git a/test/1971-multi-force-early-return/expected.txt b/test/1971-multi-force-early-return/expected-stdout.txt
similarity index 100%
rename from test/1971-multi-force-early-return/expected.txt
rename to test/1971-multi-force-early-return/expected-stdout.txt
diff --git a/test/1972-jni-id-swap-indices/Android.bp b/test/1972-jni-id-swap-indices/Android.bp
new file mode 100644
index 0000000..c405e2d
--- /dev/null
+++ b/test/1972-jni-id-swap-indices/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1972-jni-id-swap-indices`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1972-jni-id-swap-indices",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1972-jni-id-swap-indices-expected-stdout",
+        ":art-run-test-1972-jni-id-swap-indices-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1972-jni-id-swap-indices-expected-stdout",
+    out: ["art-run-test-1972-jni-id-swap-indices-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1972-jni-id-swap-indices-expected-stderr",
+    out: ["art-run-test-1972-jni-id-swap-indices-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1972-jni-id-swap-indices/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/1972-jni-id-swap-indices/expected-stderr.txt
diff --git a/test/1972-jni-id-swap-indices/expected.txt b/test/1972-jni-id-swap-indices/expected-stdout.txt
similarity index 100%
rename from test/1972-jni-id-swap-indices/expected.txt
rename to test/1972-jni-id-swap-indices/expected-stdout.txt
diff --git a/test/1973-jni-id-swap-pointer/Android.bp b/test/1973-jni-id-swap-pointer/Android.bp
new file mode 100644
index 0000000..1fef5f4
--- /dev/null
+++ b/test/1973-jni-id-swap-pointer/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1973-jni-id-swap-pointer`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1973-jni-id-swap-pointer",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1973-jni-id-swap-pointer-expected-stdout",
+        ":art-run-test-1973-jni-id-swap-pointer-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1973-jni-id-swap-pointer-expected-stdout",
+    out: ["art-run-test-1973-jni-id-swap-pointer-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1973-jni-id-swap-pointer-expected-stderr",
+    out: ["art-run-test-1973-jni-id-swap-pointer-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1973-jni-id-swap-pointer/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1973-jni-id-swap-pointer/expected-stderr.txt
diff --git a/test/1973-jni-id-swap-pointer/expected.txt b/test/1973-jni-id-swap-pointer/expected-stdout.txt
similarity index 100%
rename from test/1973-jni-id-swap-pointer/expected.txt
rename to test/1973-jni-id-swap-pointer/expected-stdout.txt
diff --git a/test/1974-resize-array/Android.bp b/test/1974-resize-array/Android.bp
new file mode 100644
index 0000000..e2d8f3c
--- /dev/null
+++ b/test/1974-resize-array/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1974-resize-array`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1974-resize-array",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1974-resize-array-expected-stdout",
+        ":art-run-test-1974-resize-array-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1974-resize-array-expected-stdout",
+    out: ["art-run-test-1974-resize-array-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1974-resize-array-expected-stderr",
+    out: ["art-run-test-1974-resize-array-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/412-new-array/expected.txt b/test/1974-resize-array/expected-stderr.txt
similarity index 100%
copy from test/412-new-array/expected.txt
copy to test/1974-resize-array/expected-stderr.txt
diff --git a/test/1974-resize-array/expected.txt b/test/1974-resize-array/expected-stdout.txt
similarity index 100%
rename from test/1974-resize-array/expected.txt
rename to test/1974-resize-array/expected-stdout.txt
diff --git a/test/1975-hello-structural-transformation/Android.bp b/test/1975-hello-structural-transformation/Android.bp
new file mode 100644
index 0000000..e96917d
--- /dev/null
+++ b/test/1975-hello-structural-transformation/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1975-hello-structural-transformation`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1975-hello-structural-transformation",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1975-hello-structural-transformation-expected-stdout",
+        ":art-run-test-1975-hello-structural-transformation-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1975-hello-structural-transformation-expected-stdout",
+    out: ["art-run-test-1975-hello-structural-transformation-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1975-hello-structural-transformation-expected-stderr",
+    out: ["art-run-test-1975-hello-structural-transformation-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-fragmentation/expected.txt b/test/1975-hello-structural-transformation/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/1975-hello-structural-transformation/expected-stderr.txt
diff --git a/test/1975-hello-structural-transformation/expected.txt b/test/1975-hello-structural-transformation/expected-stdout.txt
similarity index 100%
rename from test/1975-hello-structural-transformation/expected.txt
rename to test/1975-hello-structural-transformation/expected-stdout.txt
diff --git a/test/1976-hello-structural-static-methods/Android.bp b/test/1976-hello-structural-static-methods/Android.bp
new file mode 100644
index 0000000..16430df
--- /dev/null
+++ b/test/1976-hello-structural-static-methods/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1976-hello-structural-static-methods`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1976-hello-structural-static-methods",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1976-hello-structural-static-methods-expected-stdout",
+        ":art-run-test-1976-hello-structural-static-methods-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1976-hello-structural-static-methods-expected-stdout",
+    out: ["art-run-test-1976-hello-structural-static-methods-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1976-hello-structural-static-methods-expected-stderr",
+    out: ["art-run-test-1976-hello-structural-static-methods-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/1976-hello-structural-static-methods/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/1976-hello-structural-static-methods/expected-stderr.txt
diff --git a/test/1976-hello-structural-static-methods/expected.txt b/test/1976-hello-structural-static-methods/expected-stdout.txt
similarity index 100%
rename from test/1976-hello-structural-static-methods/expected.txt
rename to test/1976-hello-structural-static-methods/expected-stdout.txt
diff --git a/test/1977-hello-structural-obsolescence/Android.bp b/test/1977-hello-structural-obsolescence/Android.bp
new file mode 100644
index 0000000..4bb110e
--- /dev/null
+++ b/test/1977-hello-structural-obsolescence/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1977-hello-structural-obsolescence`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1977-hello-structural-obsolescence",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1977-hello-structural-obsolescence-expected-stdout",
+        ":art-run-test-1977-hello-structural-obsolescence-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1977-hello-structural-obsolescence-expected-stdout",
+    out: ["art-run-test-1977-hello-structural-obsolescence-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1977-hello-structural-obsolescence-expected-stderr",
+    out: ["art-run-test-1977-hello-structural-obsolescence-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1977-hello-structural-obsolescence/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1977-hello-structural-obsolescence/expected-stderr.txt
diff --git a/test/1977-hello-structural-obsolescence/expected.txt b/test/1977-hello-structural-obsolescence/expected-stdout.txt
similarity index 100%
rename from test/1977-hello-structural-obsolescence/expected.txt
rename to test/1977-hello-structural-obsolescence/expected-stdout.txt
diff --git a/test/1978-regular-obsolete-then-structural-obsolescence/Android.bp b/test/1978-regular-obsolete-then-structural-obsolescence/Android.bp
new file mode 100644
index 0000000..2decff6
--- /dev/null
+++ b/test/1978-regular-obsolete-then-structural-obsolescence/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1978-regular-obsolete-then-structural-obsolescence`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1978-regular-obsolete-then-structural-obsolescence",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1978-regular-obsolete-then-structural-obsolescence-expected-stdout",
+        ":art-run-test-1978-regular-obsolete-then-structural-obsolescence-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1978-regular-obsolete-then-structural-obsolescence-expected-stdout",
+    out: ["art-run-test-1978-regular-obsolete-then-structural-obsolescence-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1978-regular-obsolete-then-structural-obsolescence-expected-stderr",
+    out: ["art-run-test-1978-regular-obsolete-then-structural-obsolescence-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1978-regular-obsolete-then-structural-obsolescence/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1978-regular-obsolete-then-structural-obsolescence/expected-stderr.txt
diff --git a/test/1978-regular-obsolete-then-structural-obsolescence/expected.txt b/test/1978-regular-obsolete-then-structural-obsolescence/expected-stdout.txt
similarity index 100%
rename from test/1978-regular-obsolete-then-structural-obsolescence/expected.txt
rename to test/1978-regular-obsolete-then-structural-obsolescence/expected-stdout.txt
diff --git a/test/1979-threaded-structural-transformation/Android.bp b/test/1979-threaded-structural-transformation/Android.bp
new file mode 100644
index 0000000..d2dcf7f
--- /dev/null
+++ b/test/1979-threaded-structural-transformation/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1979-threaded-structural-transformation`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1979-threaded-structural-transformation",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1979-threaded-structural-transformation-expected-stdout",
+        ":art-run-test-1979-threaded-structural-transformation-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1979-threaded-structural-transformation-expected-stdout",
+    out: ["art-run-test-1979-threaded-structural-transformation-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1979-threaded-structural-transformation-expected-stderr",
+    out: ["art-run-test-1979-threaded-structural-transformation-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-fragmentation/expected.txt b/test/1979-threaded-structural-transformation/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/1979-threaded-structural-transformation/expected-stderr.txt
diff --git a/test/1979-threaded-structural-transformation/expected.txt b/test/1979-threaded-structural-transformation/expected-stdout.txt
similarity index 100%
rename from test/1979-threaded-structural-transformation/expected.txt
rename to test/1979-threaded-structural-transformation/expected-stdout.txt
diff --git a/test/1980-obsolete-object-cleared/Android.bp b/test/1980-obsolete-object-cleared/Android.bp
new file mode 100644
index 0000000..6404f85
--- /dev/null
+++ b/test/1980-obsolete-object-cleared/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1980-obsolete-object-cleared`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1980-obsolete-object-cleared",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1980-obsolete-object-cleared-expected-stdout",
+        ":art-run-test-1980-obsolete-object-cleared-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1980-obsolete-object-cleared-expected-stdout",
+    out: ["art-run-test-1980-obsolete-object-cleared-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1980-obsolete-object-cleared-expected-stderr",
+    out: ["art-run-test-1980-obsolete-object-cleared-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/168-vmstack-annotated/expected.txt b/test/1980-obsolete-object-cleared/expected-stderr.txt
similarity index 100%
copy from test/168-vmstack-annotated/expected.txt
copy to test/1980-obsolete-object-cleared/expected-stderr.txt
diff --git a/test/1980-obsolete-object-cleared/expected-stdout.txt b/test/1980-obsolete-object-cleared/expected-stdout.txt
new file mode 100644
index 0000000..7f0c981
--- /dev/null
+++ b/test/1980-obsolete-object-cleared/expected-stdout.txt
@@ -0,0 +1,440 @@
+JNI_OnLoad called
+Reading normally.
+	Original secret number is: 42
+	Original secret array is: [1, 2, 3, 4]
+Using unsafe to access values directly from memory.
+	Original secret number is: 42
+	Original secret array is: [1, 2, 3, 4]
+Reading normally post redefinition.
+	Post-redefinition secret number is: 42
+	Post-redefinition secret array is: [1, 2, 3, 4]
+Obsolete class is: class Main$Transform
+Using unsafe to access obsolete values directly from memory.
+	Obsolete secret number is: 0
+	Obsolete secret array is: null
+
+
+Using obsolete class object!
+
+
+Calling public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Class.isAssignableFrom(java.lang.Class)' on a null object reference
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) on (obsolete)class Main$Transform with [class java.lang.Object] = (obsolete)class Main$Transform
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) on (obsolete)class Main$Transform with [(obsolete)class Main$Transform] = (obsolete)class Main$Transform
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to Main$Transform
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to long
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to java.lang.Class
+Calling public java.lang.Object java.lang.Class.cast(java.lang.Object) with params: [[null, foo, NOT_USED_STRING, class Main$Transform]]
+public java.lang.Object java.lang.Class.cast(java.lang.Object) on (obsolete)class Main$Transform with [null] = null
+public java.lang.Object java.lang.Class.cast(java.lang.Object) with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.String to Main$Transform
+public java.lang.Object java.lang.Class.cast(java.lang.Object) with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.String to Main$Transform
+public java.lang.Object java.lang.Class.cast(java.lang.Object) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.Class to Main$Transform
+Calling public boolean java.lang.Class.desiredAssertionStatus() with params: []
+public boolean java.lang.Class.desiredAssertionStatus() on (obsolete)class Main$Transform with [] = false
+Calling public int java.lang.Class.getAccessFlags() with params: []
+public int java.lang.Class.getAccessFlags() on (obsolete)class Main$Transform with [] = 2621441
+Calling public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [class java.lang.Object] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.annotation.Annotation[] java.lang.Class.getAnnotations() with params: []
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotations() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: annotationClass
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class java.lang.Object] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.String java.lang.Class.getCanonicalName() with params: []
+public java.lang.String java.lang.Class.getCanonicalName() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.ClassLoader java.lang.Class.getClassLoader() with params: []
+public java.lang.ClassLoader java.lang.Class.getClassLoader() on (obsolete)class Main$Transform with [] = dalvik.system.PathClassLoader
+Calling public java.lang.Class[] java.lang.Class.getClasses() with params: []
+public java.lang.Class[] java.lang.Class.getClasses() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.Class java.lang.Class.getComponentType() with params: []
+public java.lang.Class java.lang.Class.getComponentType() on (obsolete)class Main$Transform with [] = null
+Calling public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[new java.lang.Object[0], new java.lang.Class[0], null]]
+public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getConstructor argument 1 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Constructor[] java.lang.Class.getConstructors() throws java.lang.SecurityException with params: []
+public java.lang.reflect.Constructor[] java.lang.Class.getConstructors() throws java.lang.SecurityException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [class java.lang.Object] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native java.lang.annotation.Annotation[] java.lang.Class.getDeclaredAnnotations() with params: []
+public native java.lang.annotation.Annotation[] java.lang.Class.getDeclaredAnnotations() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native java.lang.Class[] java.lang.Class.getDeclaredClasses() with params: []
+public native java.lang.Class[] java.lang.Class.getDeclaredClasses() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[new java.lang.Object[0], new java.lang.Class[0], null]]
+public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredConstructor argument 1 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Constructor[] java.lang.Class.getDeclaredConstructors() throws java.lang.SecurityException with params: []
+public java.lang.reflect.Constructor[] java.lang.Class.getDeclaredConstructors() throws java.lang.SecurityException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
+public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with [SECRET_ARRAY] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFields() with params: []
+public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFields() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) with params: [[true, false]]
+public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) with [true] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) with [false] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Method[] java.lang.Class.getDeclaredMethods() throws java.lang.SecurityException with params: []
+public java.lang.reflect.Method[] java.lang.Class.getDeclaredMethods() throws java.lang.SecurityException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) with params: [[true, false]]
+public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) with [true] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) with [false] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native java.lang.Class java.lang.Class.getDeclaringClass() with params: []
+public native java.lang.Class java.lang.Class.getDeclaringClass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native java.lang.Class java.lang.Class.getEnclosingClass() with params: []
+public native java.lang.Class java.lang.Class.getEnclosingClass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Constructor java.lang.Class.getEnclosingConstructor() with params: []
+public java.lang.reflect.Constructor java.lang.Class.getEnclosingConstructor() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Method java.lang.Class.getEnclosingMethod() with params: []
+public java.lang.reflect.Method java.lang.Class.getEnclosingMethod() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.Object[] java.lang.Class.getEnumConstants() with params: []
+public java.lang.Object[] java.lang.Class.getEnumConstants() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.Object[] java.lang.Class.getEnumConstantsShared() with params: []
+public java.lang.Object[] java.lang.Class.getEnumConstantsShared() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
+public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with [SECRET_ARRAY] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Field[] java.lang.Class.getFields() throws java.lang.SecurityException with params: []
+public java.lang.reflect.Field[] java.lang.Class.getFields() throws java.lang.SecurityException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Type[] java.lang.Class.getGenericInterfaces() with params: []
+public java.lang.reflect.Type[] java.lang.Class.getGenericInterfaces() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Type java.lang.Class.getGenericSuperclass() with params: []
+public java.lang.reflect.Type java.lang.Class.getGenericSuperclass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [NOT_USED_STRING, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [NOT_USED_STRING, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [foo, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [foo, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [SECRET_ARRAY, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [SECRET_ARRAY, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.Class[] java.lang.Class.getInterfaces() with params: []
+public java.lang.Class[] java.lang.Class.getInterfaces() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.reflect.Method[] java.lang.Class.getMethods() throws java.lang.SecurityException with params: []
+public java.lang.reflect.Method[] java.lang.Class.getMethods() throws java.lang.SecurityException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public int java.lang.Class.getModifiers() with params: []
+public int java.lang.Class.getModifiers() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.String java.lang.Class.getName() with params: []
+public java.lang.String java.lang.Class.getName() on (obsolete)class Main$Transform with [] = Main$Transform
+Calling public java.lang.Package java.lang.Class.getPackage() with params: []
+public java.lang.Package java.lang.Class.getPackage() on (obsolete)class Main$Transform with [] = null
+Calling public java.lang.String java.lang.Class.getPackageName() with params: []
+public java.lang.String java.lang.Class.getPackageName() on (obsolete)class Main$Transform with [] = 
+Calling public java.security.ProtectionDomain java.lang.Class.getProtectionDomain() with params: []
+public java.security.ProtectionDomain java.lang.Class.getProtectionDomain() on (obsolete)class Main$Transform with [] = null
+Calling public java.net.URL java.lang.Class.getResource(java.lang.String) with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
+public java.net.URL java.lang.Class.getResource(java.lang.String) on (obsolete)class Main$Transform with [NOT_USED_STRING] = null
+public java.net.URL java.lang.Class.getResource(java.lang.String) on (obsolete)class Main$Transform with [foo] = null
+public java.net.URL java.lang.Class.getResource(java.lang.String) on (obsolete)class Main$Transform with [SECRET_ARRAY] = null
+Calling public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
+public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on (obsolete)class Main$Transform with [NOT_USED_STRING] = null
+public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on (obsolete)class Main$Transform with [foo] = null
+public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on (obsolete)class Main$Transform with [SECRET_ARRAY] = null
+Calling public java.lang.Object[] java.lang.Class.getSigners() with params: []
+public java.lang.Object[] java.lang.Class.getSigners() on (obsolete)class Main$Transform with [] = null
+Calling public java.lang.String java.lang.Class.getSimpleName() with params: []
+public java.lang.String java.lang.Class.getSimpleName() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.Class java.lang.Class.getSuperclass() with params: []
+public java.lang.Class java.lang.Class.getSuperclass() on (obsolete)class Main$Transform with [] = class java.lang.Object
+Calling public java.lang.String java.lang.Class.getTypeName() with params: []
+public java.lang.String java.lang.Class.getTypeName() on (obsolete)class Main$Transform with [] = Main$Transform
+Calling public synchronized java.lang.reflect.TypeVariable[] java.lang.Class.getTypeParameters() with params: []
+public synchronized java.lang.reflect.TypeVariable[] java.lang.Class.getTypeParameters() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public boolean java.lang.Class.isAnnotation() with params: []
+public boolean java.lang.Class.isAnnotation() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: annotationClass == null
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [class java.lang.Object] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native boolean java.lang.Class.isAnonymousClass() with params: []
+public native boolean java.lang.Class.isAnonymousClass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public boolean java.lang.Class.isArray() with params: []
+public boolean java.lang.Class.isArray() on (obsolete)class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isAssignableFrom(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Class.isInterface()' on a null object reference
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on (obsolete)class Main$Transform with [class java.lang.Object] = false
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on (obsolete)class Main$Transform with [(obsolete)class Main$Transform] = true
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on (obsolete)class Main$Transform with [class Main$Transform] = false
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on (obsolete)class Main$Transform with [long] = false
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on (obsolete)class Main$Transform with [class java.lang.Class] = false
+Calling public boolean java.lang.Class.isEnum() with params: []
+public boolean java.lang.Class.isEnum() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public boolean java.lang.Class.isFinalizable() with params: []
+public boolean java.lang.Class.isFinalizable() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public boolean java.lang.Class.isInstance(java.lang.Object) with params: [[null, foo, NOT_USED_STRING, class Main$Transform]]
+public boolean java.lang.Class.isInstance(java.lang.Object) on (obsolete)class Main$Transform with [null] = false
+public boolean java.lang.Class.isInstance(java.lang.Object) on (obsolete)class Main$Transform with [foo] = false
+public boolean java.lang.Class.isInstance(java.lang.Object) on (obsolete)class Main$Transform with [NOT_USED_STRING] = false
+public boolean java.lang.Class.isInstance(java.lang.Object) on (obsolete)class Main$Transform with [class Main$Transform] = false
+Calling public boolean java.lang.Class.isInterface() with params: []
+public boolean java.lang.Class.isInterface() on (obsolete)class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isLocalClass() with params: []
+public boolean java.lang.Class.isLocalClass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public boolean java.lang.Class.isMemberClass() with params: []
+public boolean java.lang.Class.isMemberClass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public boolean java.lang.Class.isPrimitive() with params: []
+public boolean java.lang.Class.isPrimitive() on (obsolete)class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isProxy() with params: []
+public boolean java.lang.Class.isProxy() on (obsolete)class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isSynthetic() with params: []
+public boolean java.lang.Class.isSynthetic() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public native java.lang.Object java.lang.Class.newInstance() throws java.lang.InstantiationException,java.lang.IllegalAccessException with params: []
+public native java.lang.Object java.lang.Class.newInstance() throws java.lang.InstantiationException,java.lang.IllegalAccessException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.String java.lang.Class.toGenericString() with params: []
+public java.lang.String java.lang.Class.toGenericString() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+Calling public java.lang.String java.lang.Class.toString() with params: []
+public java.lang.String java.lang.Class.toString() on (obsolete)class Main$Transform with [] = class Main$Transform
+
+
+Using non-obsolete class object!
+
+
+Calling public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Class.isAssignableFrom(java.lang.Class)' on a null object reference
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) on class Main$Transform with [class java.lang.Object] = class Main$Transform
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to Main$Transform
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) on class Main$Transform with [class Main$Transform] = class Main$Transform
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to long
+public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to java.lang.Class
+Calling public java.lang.Object java.lang.Class.cast(java.lang.Object) with params: [[null, foo, NOT_USED_STRING, class Main$Transform]]
+public java.lang.Object java.lang.Class.cast(java.lang.Object) on class Main$Transform with [null] = null
+public java.lang.Object java.lang.Class.cast(java.lang.Object) with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.String to Main$Transform
+public java.lang.Object java.lang.Class.cast(java.lang.Object) with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.String to Main$Transform
+public java.lang.Object java.lang.Class.cast(java.lang.Object) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.Class to Main$Transform
+Calling public boolean java.lang.Class.desiredAssertionStatus() with params: []
+public boolean java.lang.Class.desiredAssertionStatus() on class Main$Transform with [] = false
+Calling public int java.lang.Class.getAccessFlags() with params: []
+public int java.lang.Class.getAccessFlags() on class Main$Transform with [] = 524289
+Calling public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) on class Main$Transform with [class java.lang.Object] = null
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) on class Main$Transform with [class Main$Transform] = null
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) on class Main$Transform with [long] = null
+public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) on class Main$Transform with [class java.lang.Class] = null
+Calling public java.lang.annotation.Annotation[] java.lang.Class.getAnnotations() with params: []
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotations() on class Main$Transform with [] = []
+Calling public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: annotationClass
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class java.lang.Object] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.lang.annotation.Annotation[]
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Main$Transform[] cannot be cast to java.lang.annotation.Annotation[]
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: long[] cannot be cast to java.lang.annotation.Annotation[]
+public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: java.lang.Class[] cannot be cast to java.lang.annotation.Annotation[]
+Calling public java.lang.String java.lang.Class.getCanonicalName() with params: []
+public java.lang.String java.lang.Class.getCanonicalName() on class Main$Transform with [] = Main.Transform
+Calling public java.lang.ClassLoader java.lang.Class.getClassLoader() with params: []
+public java.lang.ClassLoader java.lang.Class.getClassLoader() on class Main$Transform with [] = dalvik.system.PathClassLoader
+Calling public java.lang.Class[] java.lang.Class.getClasses() with params: []
+public java.lang.Class[] java.lang.Class.getClasses() on class Main$Transform with [] = []
+Calling public java.lang.Class java.lang.Class.getComponentType() with params: []
+public java.lang.Class java.lang.Class.getComponentType() on class Main$Transform with [] = null
+Calling public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[new java.lang.Object[0], new java.lang.Class[0], null]]
+public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getConstructor argument 1 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [new java.lang.Class[0]] = public Main$Transform()
+public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [null] = public Main$Transform()
+Calling public java.lang.reflect.Constructor[] java.lang.Class.getConstructors() throws java.lang.SecurityException with params: []
+public java.lang.reflect.Constructor[] java.lang.Class.getConstructors() throws java.lang.SecurityException on class Main$Transform with [] = [public Main$Transform()]
+Calling public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: annotationClass
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) on class Main$Transform with [class java.lang.Object] = null
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) on class Main$Transform with [(obsolete)class Main$Transform] = null
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) on class Main$Transform with [class Main$Transform] = null
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) on class Main$Transform with [long] = null
+public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) on class Main$Transform with [class java.lang.Class] = null
+Calling public native java.lang.annotation.Annotation[] java.lang.Class.getDeclaredAnnotations() with params: []
+public native java.lang.annotation.Annotation[] java.lang.Class.getDeclaredAnnotations() on class Main$Transform with [] = []
+Calling public native java.lang.Class[] java.lang.Class.getDeclaredClasses() with params: []
+public native java.lang.Class[] java.lang.Class.getDeclaredClasses() on class Main$Transform with [] = []
+Calling public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[new java.lang.Object[0], new java.lang.Class[0], null]]
+public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredConstructor argument 1 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [new java.lang.Class[0]] = public Main$Transform()
+public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [null] = public Main$Transform()
+Calling public java.lang.reflect.Constructor[] java.lang.Class.getDeclaredConstructors() throws java.lang.SecurityException with params: []
+public java.lang.reflect.Constructor[] java.lang.Class.getDeclaredConstructors() throws java.lang.SecurityException on class Main$Transform with [] = [public Main$Transform()]
+Calling public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
+public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchFieldException: No field NOT_USED_STRING in class LMain$Transform; (declaration of 'Main$Transform' appears in <transformed-jar>)
+public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchFieldException: No field foo in class LMain$Transform; (declaration of 'Main$Transform' appears in <transformed-jar>)
+public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException on class Main$Transform with [SECRET_ARRAY] = public static java.lang.Object Main$Transform.SECRET_ARRAY
+Calling public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFields() with params: []
+public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFields() on class Main$Transform with [] = [public static java.lang.Object Main$Transform.AAA_PADDING, public static java.lang.Object Main$Transform.SECRET_ARRAY, public static long Main$Transform.SECRET_NUMBER]
+Calling public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) with params: [[true, false]]
+public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) on class Main$Transform with [true] = [public static java.lang.Object Main$Transform.AAA_PADDING, public static java.lang.Object Main$Transform.SECRET_ARRAY, public static long Main$Transform.SECRET_NUMBER]
+public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) on class Main$Transform with [false] = [public static java.lang.Object Main$Transform.AAA_PADDING, public static java.lang.Object Main$Transform.SECRET_ARRAY, public static long Main$Transform.SECRET_NUMBER]
+Calling public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.NOT_USED_STRING []
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, null] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.NOT_USED_STRING []
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [foo, new java.lang.Class[0]] = public static void Main$Transform.foo()
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [foo, null] = public static void Main$Transform.foo()
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.SECRET_ARRAY []
+public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, null] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.SECRET_ARRAY []
+Calling public java.lang.reflect.Method[] java.lang.Class.getDeclaredMethods() throws java.lang.SecurityException with params: []
+public java.lang.reflect.Method[] java.lang.Class.getDeclaredMethods() throws java.lang.SecurityException on class Main$Transform with [] = [public static void Main$Transform.bar(), public static void Main$Transform.foo()]
+Calling public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) with params: [[true, false]]
+public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) on class Main$Transform with [true] = [public static void Main$Transform.bar(), public static void Main$Transform.foo()]
+public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) on class Main$Transform with [false] = [public static void Main$Transform.bar(), public static void Main$Transform.foo()]
+Calling public native java.lang.Class java.lang.Class.getDeclaringClass() with params: []
+public native java.lang.Class java.lang.Class.getDeclaringClass() on class Main$Transform with [] = class Main
+Calling public native java.lang.Class java.lang.Class.getEnclosingClass() with params: []
+public native java.lang.Class java.lang.Class.getEnclosingClass() on class Main$Transform with [] = class Main
+Calling public java.lang.reflect.Constructor java.lang.Class.getEnclosingConstructor() with params: []
+public java.lang.reflect.Constructor java.lang.Class.getEnclosingConstructor() on class Main$Transform with [] = null
+Calling public java.lang.reflect.Method java.lang.Class.getEnclosingMethod() with params: []
+public java.lang.reflect.Method java.lang.Class.getEnclosingMethod() on class Main$Transform with [] = null
+Calling public java.lang.Object[] java.lang.Class.getEnumConstants() with params: []
+public java.lang.Object[] java.lang.Class.getEnumConstants() on class Main$Transform with [] = null
+Calling public java.lang.Object[] java.lang.Class.getEnumConstantsShared() with params: []
+public java.lang.Object[] java.lang.Class.getEnumConstantsShared() on class Main$Transform with [] = null
+Calling public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
+public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchFieldException: NOT_USED_STRING
+public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchFieldException: foo
+public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException on class Main$Transform with [SECRET_ARRAY] = public static java.lang.Object Main$Transform.SECRET_ARRAY
+Calling public java.lang.reflect.Field[] java.lang.Class.getFields() throws java.lang.SecurityException with params: []
+public java.lang.reflect.Field[] java.lang.Class.getFields() throws java.lang.SecurityException on class Main$Transform with [] = [public static java.lang.Object Main$Transform.AAA_PADDING, public static java.lang.Object Main$Transform.SECRET_ARRAY, public static long Main$Transform.SECRET_NUMBER]
+Calling public java.lang.reflect.Type[] java.lang.Class.getGenericInterfaces() with params: []
+public java.lang.reflect.Type[] java.lang.Class.getGenericInterfaces() on class Main$Transform with [] = []
+Calling public java.lang.reflect.Type java.lang.Class.getGenericSuperclass() with params: []
+public java.lang.reflect.Type java.lang.Class.getGenericSuperclass() on class Main$Transform with [] = class java.lang.Object
+Calling public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [NOT_USED_STRING, new java.lang.Class[0]] = null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [NOT_USED_STRING, null] = null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [foo, new java.lang.Class[0]] = null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [foo, null] = null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [SECRET_ARRAY, new java.lang.Class[0]] = null
+public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [SECRET_ARRAY, null] = null
+Calling public java.lang.Class[] java.lang.Class.getInterfaces() with params: []
+public java.lang.Class[] java.lang.Class.getInterfaces() on class Main$Transform with [] = []
+Calling public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.NOT_USED_STRING []
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, null] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.NOT_USED_STRING []
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [foo, new java.lang.Class[0]] = public static void Main$Transform.foo()
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [foo, null] = public static void Main$Transform.foo()
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.SECRET_ARRAY []
+public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, null] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.SECRET_ARRAY []
+Calling public java.lang.reflect.Method[] java.lang.Class.getMethods() throws java.lang.SecurityException with params: []
+public java.lang.reflect.Method[] java.lang.Class.getMethods() throws java.lang.SecurityException on class Main$Transform with [] = [public static void Main$Transform.bar(), public boolean java.lang.Object.equals(java.lang.Object), public static void Main$Transform.foo(), public final java.lang.Class java.lang.Object.getClass(), public int java.lang.Object.hashCode(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll(), public java.lang.String java.lang.Object.toString(), public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException]
+Calling public int java.lang.Class.getModifiers() with params: []
+public int java.lang.Class.getModifiers() on class Main$Transform with [] = 9
+Calling public java.lang.String java.lang.Class.getName() with params: []
+public java.lang.String java.lang.Class.getName() on class Main$Transform with [] = Main$Transform
+Calling public java.lang.Package java.lang.Class.getPackage() with params: []
+public java.lang.Package java.lang.Class.getPackage() on class Main$Transform with [] = null
+Calling public java.lang.String java.lang.Class.getPackageName() with params: []
+public java.lang.String java.lang.Class.getPackageName() on class Main$Transform with [] = 
+Calling public java.security.ProtectionDomain java.lang.Class.getProtectionDomain() with params: []
+public java.security.ProtectionDomain java.lang.Class.getProtectionDomain() on class Main$Transform with [] = null
+Calling public java.net.URL java.lang.Class.getResource(java.lang.String) with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
+public java.net.URL java.lang.Class.getResource(java.lang.String) on class Main$Transform with [NOT_USED_STRING] = null
+public java.net.URL java.lang.Class.getResource(java.lang.String) on class Main$Transform with [foo] = null
+public java.net.URL java.lang.Class.getResource(java.lang.String) on class Main$Transform with [SECRET_ARRAY] = null
+Calling public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
+public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on class Main$Transform with [NOT_USED_STRING] = null
+public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on class Main$Transform with [foo] = null
+public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on class Main$Transform with [SECRET_ARRAY] = null
+Calling public java.lang.Object[] java.lang.Class.getSigners() with params: []
+public java.lang.Object[] java.lang.Class.getSigners() on class Main$Transform with [] = null
+Calling public java.lang.String java.lang.Class.getSimpleName() with params: []
+public java.lang.String java.lang.Class.getSimpleName() on class Main$Transform with [] = Transform
+Calling public java.lang.Class java.lang.Class.getSuperclass() with params: []
+public java.lang.Class java.lang.Class.getSuperclass() on class Main$Transform with [] = class java.lang.Object
+Calling public java.lang.String java.lang.Class.getTypeName() with params: []
+public java.lang.String java.lang.Class.getTypeName() on class Main$Transform with [] = Main$Transform
+Calling public synchronized java.lang.reflect.TypeVariable[] java.lang.Class.getTypeParameters() with params: []
+public synchronized java.lang.reflect.TypeVariable[] java.lang.Class.getTypeParameters() on class Main$Transform with [] = []
+Calling public boolean java.lang.Class.isAnnotation() with params: []
+public boolean java.lang.Class.isAnnotation() on class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: annotationClass == null
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) on class Main$Transform with [class java.lang.Object] = false
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) on class Main$Transform with [class Main$Transform] = false
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) on class Main$Transform with [long] = false
+public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) on class Main$Transform with [class java.lang.Class] = false
+Calling public native boolean java.lang.Class.isAnonymousClass() with params: []
+public native boolean java.lang.Class.isAnonymousClass() on class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isArray() with params: []
+public boolean java.lang.Class.isArray() on class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isAssignableFrom(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Class.isInterface()' on a null object reference
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on class Main$Transform with [class java.lang.Object] = false
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on class Main$Transform with [(obsolete)class Main$Transform] = false
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on class Main$Transform with [class Main$Transform] = true
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on class Main$Transform with [long] = false
+public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on class Main$Transform with [class java.lang.Class] = false
+Calling public boolean java.lang.Class.isEnum() with params: []
+public boolean java.lang.Class.isEnum() on class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isFinalizable() with params: []
+public boolean java.lang.Class.isFinalizable() on class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isInstance(java.lang.Object) with params: [[null, foo, NOT_USED_STRING, class Main$Transform]]
+public boolean java.lang.Class.isInstance(java.lang.Object) on class Main$Transform with [null] = false
+public boolean java.lang.Class.isInstance(java.lang.Object) on class Main$Transform with [foo] = false
+public boolean java.lang.Class.isInstance(java.lang.Object) on class Main$Transform with [NOT_USED_STRING] = false
+public boolean java.lang.Class.isInstance(java.lang.Object) on class Main$Transform with [class Main$Transform] = false
+Calling public boolean java.lang.Class.isInterface() with params: []
+public boolean java.lang.Class.isInterface() on class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isLocalClass() with params: []
+public boolean java.lang.Class.isLocalClass() on class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isMemberClass() with params: []
+public boolean java.lang.Class.isMemberClass() on class Main$Transform with [] = true
+Calling public boolean java.lang.Class.isPrimitive() with params: []
+public boolean java.lang.Class.isPrimitive() on class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isProxy() with params: []
+public boolean java.lang.Class.isProxy() on class Main$Transform with [] = false
+Calling public boolean java.lang.Class.isSynthetic() with params: []
+public boolean java.lang.Class.isSynthetic() on class Main$Transform with [] = false
+Calling public native java.lang.Object java.lang.Class.newInstance() throws java.lang.InstantiationException,java.lang.IllegalAccessException with params: []
+public native java.lang.Object java.lang.Class.newInstance() throws java.lang.InstantiationException,java.lang.IllegalAccessException on class Main$Transform with [] = Transform Instance
+Calling public java.lang.String java.lang.Class.toGenericString() with params: []
+public java.lang.String java.lang.Class.toGenericString() on class Main$Transform with [] = public static class Main$Transform
+Calling public java.lang.String java.lang.Class.toString() with params: []
+public java.lang.String java.lang.Class.toString() on class Main$Transform with [] = class Main$Transform
diff --git a/test/1980-obsolete-object-cleared/expected.txt b/test/1980-obsolete-object-cleared/expected.txt
deleted file mode 100644
index 77569ee..0000000
--- a/test/1980-obsolete-object-cleared/expected.txt
+++ /dev/null
@@ -1,440 +0,0 @@
-JNI_OnLoad called
-Reading normally.
-	Original secret number is: 42
-	Original secret array is: [1, 2, 3, 4]
-Using unsafe to access values directly from memory.
-	Original secret number is: 42
-	Original secret array is: [1, 2, 3, 4]
-Reading normally post redefinition.
-	Post-redefinition secret number is: 42
-	Post-redefinition secret array is: [1, 2, 3, 4]
-Obsolete class is: class Main$Transform
-Using unsafe to access obsolete values directly from memory.
-	Obsolete secret number is: 0
-	Obsolete secret array is: null
-
-
-Using obsolete class object!
-
-
-Calling public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Class.isAssignableFrom(java.lang.Class)' on a null object reference
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) on (obsolete)class Main$Transform with [class java.lang.Object] = (obsolete)class Main$Transform
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) on (obsolete)class Main$Transform with [(obsolete)class Main$Transform] = (obsolete)class Main$Transform
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to Main$Transform
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to long
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to java.lang.Class
-Calling public java.lang.Object java.lang.Class.cast(java.lang.Object) with params: [[null, foo, NOT_USED_STRING, class Main$Transform]]
-public java.lang.Object java.lang.Class.cast(java.lang.Object) on (obsolete)class Main$Transform with [null] = null
-public java.lang.Object java.lang.Class.cast(java.lang.Object) with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.String to Main$Transform
-public java.lang.Object java.lang.Class.cast(java.lang.Object) with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.String to Main$Transform
-public java.lang.Object java.lang.Class.cast(java.lang.Object) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.Class to Main$Transform
-Calling public boolean java.lang.Class.desiredAssertionStatus() with params: []
-public boolean java.lang.Class.desiredAssertionStatus() on (obsolete)class Main$Transform with [] = false
-Calling public int java.lang.Class.getAccessFlags() with params: []
-public int java.lang.Class.getAccessFlags() on (obsolete)class Main$Transform with [] = 2621441
-Calling public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [class java.lang.Object] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.annotation.Annotation[] java.lang.Class.getAnnotations() with params: []
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotations() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: annotationClass
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class java.lang.Object] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.String java.lang.Class.getCanonicalName() with params: []
-public java.lang.String java.lang.Class.getCanonicalName() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.ClassLoader java.lang.Class.getClassLoader() with params: []
-public java.lang.ClassLoader java.lang.Class.getClassLoader() on (obsolete)class Main$Transform with [] = dalvik.system.PathClassLoader
-Calling public java.lang.Class[] java.lang.Class.getClasses() with params: []
-public java.lang.Class[] java.lang.Class.getClasses() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.Class java.lang.Class.getComponentType() with params: []
-public java.lang.Class java.lang.Class.getComponentType() on (obsolete)class Main$Transform with [] = null
-Calling public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[new java.lang.Object[0], new java.lang.Class[0], null]]
-public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getConstructor argument 1 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Constructor[] java.lang.Class.getConstructors() throws java.lang.SecurityException with params: []
-public java.lang.reflect.Constructor[] java.lang.Class.getConstructors() throws java.lang.SecurityException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [class java.lang.Object] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native java.lang.annotation.Annotation[] java.lang.Class.getDeclaredAnnotations() with params: []
-public native java.lang.annotation.Annotation[] java.lang.Class.getDeclaredAnnotations() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native java.lang.Class[] java.lang.Class.getDeclaredClasses() with params: []
-public native java.lang.Class[] java.lang.Class.getDeclaredClasses() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[new java.lang.Object[0], new java.lang.Class[0], null]]
-public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredConstructor argument 1 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Constructor[] java.lang.Class.getDeclaredConstructors() throws java.lang.SecurityException with params: []
-public java.lang.reflect.Constructor[] java.lang.Class.getDeclaredConstructors() throws java.lang.SecurityException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
-public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with [SECRET_ARRAY] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFields() with params: []
-public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFields() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) with params: [[true, false]]
-public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) with [true] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) with [false] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Method[] java.lang.Class.getDeclaredMethods() throws java.lang.SecurityException with params: []
-public java.lang.reflect.Method[] java.lang.Class.getDeclaredMethods() throws java.lang.SecurityException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) with params: [[true, false]]
-public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) with [true] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) with [false] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native java.lang.Class java.lang.Class.getDeclaringClass() with params: []
-public native java.lang.Class java.lang.Class.getDeclaringClass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native java.lang.Class java.lang.Class.getEnclosingClass() with params: []
-public native java.lang.Class java.lang.Class.getEnclosingClass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Constructor java.lang.Class.getEnclosingConstructor() with params: []
-public java.lang.reflect.Constructor java.lang.Class.getEnclosingConstructor() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Method java.lang.Class.getEnclosingMethod() with params: []
-public java.lang.reflect.Method java.lang.Class.getEnclosingMethod() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.Object[] java.lang.Class.getEnumConstants() with params: []
-public java.lang.Object[] java.lang.Class.getEnumConstants() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.Object[] java.lang.Class.getEnumConstantsShared() with params: []
-public java.lang.Object[] java.lang.Class.getEnumConstantsShared() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
-public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with [SECRET_ARRAY] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Field[] java.lang.Class.getFields() throws java.lang.SecurityException with params: []
-public java.lang.reflect.Field[] java.lang.Class.getFields() throws java.lang.SecurityException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Type[] java.lang.Class.getGenericInterfaces() with params: []
-public java.lang.reflect.Type[] java.lang.Class.getGenericInterfaces() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Type java.lang.Class.getGenericSuperclass() with params: []
-public java.lang.reflect.Type java.lang.Class.getGenericSuperclass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [NOT_USED_STRING, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [NOT_USED_STRING, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [foo, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [foo, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [SECRET_ARRAY, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [SECRET_ARRAY, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.Class[] java.lang.Class.getInterfaces() with params: []
-public java.lang.Class[] java.lang.Class.getInterfaces() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, null] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.reflect.Method[] java.lang.Class.getMethods() throws java.lang.SecurityException with params: []
-public java.lang.reflect.Method[] java.lang.Class.getMethods() throws java.lang.SecurityException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public int java.lang.Class.getModifiers() with params: []
-public int java.lang.Class.getModifiers() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.String java.lang.Class.getName() with params: []
-public java.lang.String java.lang.Class.getName() on (obsolete)class Main$Transform with [] = Main$Transform
-Calling public java.lang.Package java.lang.Class.getPackage() with params: []
-public java.lang.Package java.lang.Class.getPackage() on (obsolete)class Main$Transform with [] = null
-Calling public java.lang.String java.lang.Class.getPackageName$() with params: []
-public java.lang.String java.lang.Class.getPackageName$() on (obsolete)class Main$Transform with [] = null
-Calling public java.security.ProtectionDomain java.lang.Class.getProtectionDomain() with params: []
-public java.security.ProtectionDomain java.lang.Class.getProtectionDomain() on (obsolete)class Main$Transform with [] = null
-Calling public java.net.URL java.lang.Class.getResource(java.lang.String) with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
-public java.net.URL java.lang.Class.getResource(java.lang.String) on (obsolete)class Main$Transform with [NOT_USED_STRING] = null
-public java.net.URL java.lang.Class.getResource(java.lang.String) on (obsolete)class Main$Transform with [foo] = null
-public java.net.URL java.lang.Class.getResource(java.lang.String) on (obsolete)class Main$Transform with [SECRET_ARRAY] = null
-Calling public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
-public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on (obsolete)class Main$Transform with [NOT_USED_STRING] = null
-public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on (obsolete)class Main$Transform with [foo] = null
-public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on (obsolete)class Main$Transform with [SECRET_ARRAY] = null
-Calling public java.lang.Object[] java.lang.Class.getSigners() with params: []
-public java.lang.Object[] java.lang.Class.getSigners() on (obsolete)class Main$Transform with [] = null
-Calling public java.lang.String java.lang.Class.getSimpleName() with params: []
-public java.lang.String java.lang.Class.getSimpleName() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.Class java.lang.Class.getSuperclass() with params: []
-public java.lang.Class java.lang.Class.getSuperclass() on (obsolete)class Main$Transform with [] = class java.lang.Object
-Calling public java.lang.String java.lang.Class.getTypeName() with params: []
-public java.lang.String java.lang.Class.getTypeName() on (obsolete)class Main$Transform with [] = Main$Transform
-Calling public synchronized java.lang.reflect.TypeVariable[] java.lang.Class.getTypeParameters() with params: []
-public synchronized java.lang.reflect.TypeVariable[] java.lang.Class.getTypeParameters() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public boolean java.lang.Class.isAnnotation() with params: []
-public boolean java.lang.Class.isAnnotation() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: annotationClass == null
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [class java.lang.Object] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native boolean java.lang.Class.isAnonymousClass() with params: []
-public native boolean java.lang.Class.isAnonymousClass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public boolean java.lang.Class.isArray() with params: []
-public boolean java.lang.Class.isArray() on (obsolete)class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isAssignableFrom(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Class.isInterface()' on a null object reference
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on (obsolete)class Main$Transform with [class java.lang.Object] = false
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on (obsolete)class Main$Transform with [(obsolete)class Main$Transform] = true
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on (obsolete)class Main$Transform with [class Main$Transform] = false
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on (obsolete)class Main$Transform with [long] = false
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on (obsolete)class Main$Transform with [class java.lang.Class] = false
-Calling public boolean java.lang.Class.isEnum() with params: []
-public boolean java.lang.Class.isEnum() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public boolean java.lang.Class.isFinalizable() with params: []
-public boolean java.lang.Class.isFinalizable() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public boolean java.lang.Class.isInstance(java.lang.Object) with params: [[null, foo, NOT_USED_STRING, class Main$Transform]]
-public boolean java.lang.Class.isInstance(java.lang.Object) on (obsolete)class Main$Transform with [null] = false
-public boolean java.lang.Class.isInstance(java.lang.Object) on (obsolete)class Main$Transform with [foo] = false
-public boolean java.lang.Class.isInstance(java.lang.Object) on (obsolete)class Main$Transform with [NOT_USED_STRING] = false
-public boolean java.lang.Class.isInstance(java.lang.Object) on (obsolete)class Main$Transform with [class Main$Transform] = false
-Calling public boolean java.lang.Class.isInterface() with params: []
-public boolean java.lang.Class.isInterface() on (obsolete)class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isLocalClass() with params: []
-public boolean java.lang.Class.isLocalClass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public boolean java.lang.Class.isMemberClass() with params: []
-public boolean java.lang.Class.isMemberClass() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public boolean java.lang.Class.isPrimitive() with params: []
-public boolean java.lang.Class.isPrimitive() on (obsolete)class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isProxy() with params: []
-public boolean java.lang.Class.isProxy() on (obsolete)class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isSynthetic() with params: []
-public boolean java.lang.Class.isSynthetic() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public native java.lang.Object java.lang.Class.newInstance() throws java.lang.InstantiationException,java.lang.IllegalAccessException with params: []
-public native java.lang.Object java.lang.Class.newInstance() throws java.lang.InstantiationException,java.lang.IllegalAccessException with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.String java.lang.Class.toGenericString() with params: []
-public java.lang.String java.lang.Class.toGenericString() with [] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-Calling public java.lang.String java.lang.Class.toString() with params: []
-public java.lang.String java.lang.Class.toString() on (obsolete)class Main$Transform with [] = class Main$Transform
-
-
-Using non-obsolete class object!
-
-
-Calling public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Class.isAssignableFrom(java.lang.Class)' on a null object reference
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) on class Main$Transform with [class java.lang.Object] = class Main$Transform
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to Main$Transform
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) on class Main$Transform with [class Main$Transform] = class Main$Transform
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to long
-public java.lang.Class java.lang.Class.asSubclass(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: class Main$Transform cannot be cast to java.lang.Class
-Calling public java.lang.Object java.lang.Class.cast(java.lang.Object) with params: [[null, foo, NOT_USED_STRING, class Main$Transform]]
-public java.lang.Object java.lang.Class.cast(java.lang.Object) on class Main$Transform with [null] = null
-public java.lang.Object java.lang.Class.cast(java.lang.Object) with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.String to Main$Transform
-public java.lang.Object java.lang.Class.cast(java.lang.Object) with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.String to Main$Transform
-public java.lang.Object java.lang.Class.cast(java.lang.Object) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Cannot cast java.lang.Class to Main$Transform
-Calling public boolean java.lang.Class.desiredAssertionStatus() with params: []
-public boolean java.lang.Class.desiredAssertionStatus() on class Main$Transform with [] = false
-Calling public int java.lang.Class.getAccessFlags() with params: []
-public int java.lang.Class.getAccessFlags() on class Main$Transform with [] = 524289
-Calling public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) on class Main$Transform with [class java.lang.Object] = null
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) on class Main$Transform with [class Main$Transform] = null
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) on class Main$Transform with [long] = null
-public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class) on class Main$Transform with [class java.lang.Class] = null
-Calling public java.lang.annotation.Annotation[] java.lang.Class.getAnnotations() with params: []
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotations() on class Main$Transform with [] = []
-Calling public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: annotationClass
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class java.lang.Object] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.lang.annotation.Annotation[]
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: Main$Transform[] cannot be cast to java.lang.annotation.Annotation[]
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [long] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: long[] cannot be cast to java.lang.annotation.Annotation[]
-public java.lang.annotation.Annotation[] java.lang.Class.getAnnotationsByType(java.lang.Class) with [class java.lang.Class] throws java.lang.reflect.InvocationTargetException: java.lang.ClassCastException: java.lang.Class[] cannot be cast to java.lang.annotation.Annotation[]
-Calling public java.lang.String java.lang.Class.getCanonicalName() with params: []
-public java.lang.String java.lang.Class.getCanonicalName() on class Main$Transform with [] = Main.Transform
-Calling public java.lang.ClassLoader java.lang.Class.getClassLoader() with params: []
-public java.lang.ClassLoader java.lang.Class.getClassLoader() on class Main$Transform with [] = dalvik.system.PathClassLoader
-Calling public java.lang.Class[] java.lang.Class.getClasses() with params: []
-public java.lang.Class[] java.lang.Class.getClasses() on class Main$Transform with [] = []
-Calling public java.lang.Class java.lang.Class.getComponentType() with params: []
-public java.lang.Class java.lang.Class.getComponentType() on class Main$Transform with [] = null
-Calling public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[new java.lang.Object[0], new java.lang.Class[0], null]]
-public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getConstructor argument 1 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [new java.lang.Class[0]] = public Main$Transform()
-public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [null] = public Main$Transform()
-Calling public java.lang.reflect.Constructor[] java.lang.Class.getConstructors() throws java.lang.SecurityException with params: []
-public java.lang.reflect.Constructor[] java.lang.Class.getConstructors() throws java.lang.SecurityException on class Main$Transform with [] = [public Main$Transform()]
-Calling public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: annotationClass
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) on class Main$Transform with [class java.lang.Object] = null
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) on class Main$Transform with [(obsolete)class Main$Transform] = null
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) on class Main$Transform with [class Main$Transform] = null
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) on class Main$Transform with [long] = null
-public native java.lang.annotation.Annotation java.lang.Class.getDeclaredAnnotation(java.lang.Class) on class Main$Transform with [class java.lang.Class] = null
-Calling public native java.lang.annotation.Annotation[] java.lang.Class.getDeclaredAnnotations() with params: []
-public native java.lang.annotation.Annotation[] java.lang.Class.getDeclaredAnnotations() on class Main$Transform with [] = []
-Calling public native java.lang.Class[] java.lang.Class.getDeclaredClasses() with params: []
-public native java.lang.Class[] java.lang.Class.getDeclaredClasses() on class Main$Transform with [] = []
-Calling public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[new java.lang.Object[0], new java.lang.Class[0], null]]
-public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredConstructor argument 1 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [new java.lang.Class[0]] = public Main$Transform()
-public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [null] = public Main$Transform()
-Calling public java.lang.reflect.Constructor[] java.lang.Class.getDeclaredConstructors() throws java.lang.SecurityException with params: []
-public java.lang.reflect.Constructor[] java.lang.Class.getDeclaredConstructors() throws java.lang.SecurityException on class Main$Transform with [] = [public Main$Transform()]
-Calling public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
-public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchFieldException: No field NOT_USED_STRING in class LMain$Transform; (declaration of 'Main$Transform' appears in <transformed-jar>)
-public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchFieldException: No field foo in class LMain$Transform; (declaration of 'Main$Transform' appears in <transformed-jar>)
-public native java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException on class Main$Transform with [SECRET_ARRAY] = public static java.lang.Object Main$Transform.SECRET_ARRAY
-Calling public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFields() with params: []
-public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFields() on class Main$Transform with [] = [public static java.lang.Object Main$Transform.AAA_PADDING, public static java.lang.Object Main$Transform.SECRET_ARRAY, public static long Main$Transform.SECRET_NUMBER]
-Calling public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) with params: [[true, false]]
-public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) on class Main$Transform with [true] = [public static java.lang.Object Main$Transform.AAA_PADDING, public static java.lang.Object Main$Transform.SECRET_ARRAY, public static long Main$Transform.SECRET_NUMBER]
-public native java.lang.reflect.Field[] java.lang.Class.getDeclaredFieldsUnchecked(boolean) on class Main$Transform with [false] = [public static java.lang.Object Main$Transform.AAA_PADDING, public static java.lang.Object Main$Transform.SECRET_ARRAY, public static long Main$Transform.SECRET_NUMBER]
-Calling public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.NOT_USED_STRING []
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, null] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.NOT_USED_STRING []
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [foo, new java.lang.Class[0]] = public static void Main$Transform.foo()
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [foo, null] = public static void Main$Transform.foo()
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getDeclaredMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.SECRET_ARRAY []
-public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, null] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.SECRET_ARRAY []
-Calling public java.lang.reflect.Method[] java.lang.Class.getDeclaredMethods() throws java.lang.SecurityException with params: []
-public java.lang.reflect.Method[] java.lang.Class.getDeclaredMethods() throws java.lang.SecurityException on class Main$Transform with [] = [public static void Main$Transform.bar(), public static void Main$Transform.foo()]
-Calling public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) with params: [[true, false]]
-public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) on class Main$Transform with [true] = [public static void Main$Transform.bar(), public static void Main$Transform.foo()]
-public native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethodsUnchecked(boolean) on class Main$Transform with [false] = [public static void Main$Transform.bar(), public static void Main$Transform.foo()]
-Calling public native java.lang.Class java.lang.Class.getDeclaringClass() with params: []
-public native java.lang.Class java.lang.Class.getDeclaringClass() on class Main$Transform with [] = class Main
-Calling public native java.lang.Class java.lang.Class.getEnclosingClass() with params: []
-public native java.lang.Class java.lang.Class.getEnclosingClass() on class Main$Transform with [] = class Main
-Calling public java.lang.reflect.Constructor java.lang.Class.getEnclosingConstructor() with params: []
-public java.lang.reflect.Constructor java.lang.Class.getEnclosingConstructor() on class Main$Transform with [] = null
-Calling public java.lang.reflect.Method java.lang.Class.getEnclosingMethod() with params: []
-public java.lang.reflect.Method java.lang.Class.getEnclosingMethod() on class Main$Transform with [] = null
-Calling public java.lang.Object[] java.lang.Class.getEnumConstants() with params: []
-public java.lang.Object[] java.lang.Class.getEnumConstants() on class Main$Transform with [] = null
-Calling public java.lang.Object[] java.lang.Class.getEnumConstantsShared() with params: []
-public java.lang.Object[] java.lang.Class.getEnumConstantsShared() on class Main$Transform with [] = null
-Calling public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
-public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with [NOT_USED_STRING] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchFieldException: NOT_USED_STRING
-public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException with [foo] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchFieldException: foo
-public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException on class Main$Transform with [SECRET_ARRAY] = public static java.lang.Object Main$Transform.SECRET_ARRAY
-Calling public java.lang.reflect.Field[] java.lang.Class.getFields() throws java.lang.SecurityException with params: []
-public java.lang.reflect.Field[] java.lang.Class.getFields() throws java.lang.SecurityException on class Main$Transform with [] = [public static java.lang.Object Main$Transform.AAA_PADDING, public static java.lang.Object Main$Transform.SECRET_ARRAY, public static long Main$Transform.SECRET_NUMBER]
-Calling public java.lang.reflect.Type[] java.lang.Class.getGenericInterfaces() with params: []
-public java.lang.reflect.Type[] java.lang.Class.getGenericInterfaces() on class Main$Transform with [] = []
-Calling public java.lang.reflect.Type java.lang.Class.getGenericSuperclass() with params: []
-public java.lang.reflect.Type java.lang.Class.getGenericSuperclass() on class Main$Transform with [] = class java.lang.Object
-Calling public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [NOT_USED_STRING, new java.lang.Class[0]] = null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [NOT_USED_STRING, null] = null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [foo, new java.lang.Class[0]] = null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [foo, null] = null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getInstanceMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [SECRET_ARRAY, new java.lang.Class[0]] = null
-public java.lang.reflect.Method java.lang.Class.getInstanceMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException on class Main$Transform with [SECRET_ARRAY, null] = null
-Calling public java.lang.Class[] java.lang.Class.getInterfaces() with params: []
-public java.lang.Class[] java.lang.Class.getInterfaces() on class Main$Transform with [] = []
-Calling public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with params: [[NOT_USED_STRING, foo, SECRET_ARRAY], [new java.lang.Object[0], new java.lang.Class[0], null]]
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.NOT_USED_STRING []
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [NOT_USED_STRING, null] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.NOT_USED_STRING []
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [foo, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [foo, new java.lang.Class[0]] = public static void Main$Transform.foo()
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException on class Main$Transform with [foo, null] = public static void Main$Transform.foo()
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Object[0]] throws java.lang.IllegalArgumentException: method java.lang.Class.getMethod argument 2 has type java.lang.Class[], got java.lang.Object[]: null
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, new java.lang.Class[0]] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.SECRET_ARRAY []
-public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException with [SECRET_ARRAY, null] throws java.lang.reflect.InvocationTargetException: java.lang.NoSuchMethodException: Main$Transform.SECRET_ARRAY []
-Calling public java.lang.reflect.Method[] java.lang.Class.getMethods() throws java.lang.SecurityException with params: []
-public java.lang.reflect.Method[] java.lang.Class.getMethods() throws java.lang.SecurityException on class Main$Transform with [] = [public static void Main$Transform.bar(), public boolean java.lang.Object.equals(java.lang.Object), public static void Main$Transform.foo(), public final java.lang.Class java.lang.Object.getClass(), public int java.lang.Object.hashCode(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll(), public java.lang.String java.lang.Object.toString(), public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException]
-Calling public int java.lang.Class.getModifiers() with params: []
-public int java.lang.Class.getModifiers() on class Main$Transform with [] = 9
-Calling public java.lang.String java.lang.Class.getName() with params: []
-public java.lang.String java.lang.Class.getName() on class Main$Transform with [] = Main$Transform
-Calling public java.lang.Package java.lang.Class.getPackage() with params: []
-public java.lang.Package java.lang.Class.getPackage() on class Main$Transform with [] = null
-Calling public java.lang.String java.lang.Class.getPackageName$() with params: []
-public java.lang.String java.lang.Class.getPackageName$() on class Main$Transform with [] = null
-Calling public java.security.ProtectionDomain java.lang.Class.getProtectionDomain() with params: []
-public java.security.ProtectionDomain java.lang.Class.getProtectionDomain() on class Main$Transform with [] = null
-Calling public java.net.URL java.lang.Class.getResource(java.lang.String) with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
-public java.net.URL java.lang.Class.getResource(java.lang.String) on class Main$Transform with [NOT_USED_STRING] = null
-public java.net.URL java.lang.Class.getResource(java.lang.String) on class Main$Transform with [foo] = null
-public java.net.URL java.lang.Class.getResource(java.lang.String) on class Main$Transform with [SECRET_ARRAY] = null
-Calling public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) with params: [[NOT_USED_STRING, foo, SECRET_ARRAY]]
-public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on class Main$Transform with [NOT_USED_STRING] = null
-public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on class Main$Transform with [foo] = null
-public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String) on class Main$Transform with [SECRET_ARRAY] = null
-Calling public java.lang.Object[] java.lang.Class.getSigners() with params: []
-public java.lang.Object[] java.lang.Class.getSigners() on class Main$Transform with [] = null
-Calling public java.lang.String java.lang.Class.getSimpleName() with params: []
-public java.lang.String java.lang.Class.getSimpleName() on class Main$Transform with [] = Transform
-Calling public java.lang.Class java.lang.Class.getSuperclass() with params: []
-public java.lang.Class java.lang.Class.getSuperclass() on class Main$Transform with [] = class java.lang.Object
-Calling public java.lang.String java.lang.Class.getTypeName() with params: []
-public java.lang.String java.lang.Class.getTypeName() on class Main$Transform with [] = Main$Transform
-Calling public synchronized java.lang.reflect.TypeVariable[] java.lang.Class.getTypeParameters() with params: []
-public synchronized java.lang.reflect.TypeVariable[] java.lang.Class.getTypeParameters() on class Main$Transform with [] = []
-Calling public boolean java.lang.Class.isAnnotation() with params: []
-public boolean java.lang.Class.isAnnotation() on class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: annotationClass == null
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) on class Main$Transform with [class java.lang.Object] = false
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) with [(obsolete)class Main$Transform] throws java.lang.reflect.InvocationTargetException: java.lang.RuntimeException: Obsolete Object!
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) on class Main$Transform with [class Main$Transform] = false
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) on class Main$Transform with [long] = false
-public boolean java.lang.Class.isAnnotationPresent(java.lang.Class) on class Main$Transform with [class java.lang.Class] = false
-Calling public native boolean java.lang.Class.isAnonymousClass() with params: []
-public native boolean java.lang.Class.isAnonymousClass() on class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isArray() with params: []
-public boolean java.lang.Class.isArray() on class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isAssignableFrom(java.lang.Class) with params: [[null, class java.lang.Object, (obsolete)class Main$Transform, class Main$Transform, long, class java.lang.Class]]
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) with [null] throws java.lang.reflect.InvocationTargetException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Class.isInterface()' on a null object reference
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on class Main$Transform with [class java.lang.Object] = false
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on class Main$Transform with [(obsolete)class Main$Transform] = false
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on class Main$Transform with [class Main$Transform] = true
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on class Main$Transform with [long] = false
-public boolean java.lang.Class.isAssignableFrom(java.lang.Class) on class Main$Transform with [class java.lang.Class] = false
-Calling public boolean java.lang.Class.isEnum() with params: []
-public boolean java.lang.Class.isEnum() on class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isFinalizable() with params: []
-public boolean java.lang.Class.isFinalizable() on class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isInstance(java.lang.Object) with params: [[null, foo, NOT_USED_STRING, class Main$Transform]]
-public boolean java.lang.Class.isInstance(java.lang.Object) on class Main$Transform with [null] = false
-public boolean java.lang.Class.isInstance(java.lang.Object) on class Main$Transform with [foo] = false
-public boolean java.lang.Class.isInstance(java.lang.Object) on class Main$Transform with [NOT_USED_STRING] = false
-public boolean java.lang.Class.isInstance(java.lang.Object) on class Main$Transform with [class Main$Transform] = false
-Calling public boolean java.lang.Class.isInterface() with params: []
-public boolean java.lang.Class.isInterface() on class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isLocalClass() with params: []
-public boolean java.lang.Class.isLocalClass() on class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isMemberClass() with params: []
-public boolean java.lang.Class.isMemberClass() on class Main$Transform with [] = true
-Calling public boolean java.lang.Class.isPrimitive() with params: []
-public boolean java.lang.Class.isPrimitive() on class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isProxy() with params: []
-public boolean java.lang.Class.isProxy() on class Main$Transform with [] = false
-Calling public boolean java.lang.Class.isSynthetic() with params: []
-public boolean java.lang.Class.isSynthetic() on class Main$Transform with [] = false
-Calling public native java.lang.Object java.lang.Class.newInstance() throws java.lang.InstantiationException,java.lang.IllegalAccessException with params: []
-public native java.lang.Object java.lang.Class.newInstance() throws java.lang.InstantiationException,java.lang.IllegalAccessException on class Main$Transform with [] = Transform Instance
-Calling public java.lang.String java.lang.Class.toGenericString() with params: []
-public java.lang.String java.lang.Class.toGenericString() on class Main$Transform with [] = public static class Main$Transform
-Calling public java.lang.String java.lang.Class.toString() with params: []
-public java.lang.String java.lang.Class.toString() on class Main$Transform with [] = class Main$Transform
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1981-structural-redef-private-method-handles/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/1981-structural-redef-private-method-handles/expected-stderr.txt
diff --git a/test/1981-structural-redef-private-method-handles/expected.txt b/test/1981-structural-redef-private-method-handles/expected-stdout.txt
similarity index 100%
rename from test/1981-structural-redef-private-method-handles/expected.txt
rename to test/1981-structural-redef-private-method-handles/expected-stdout.txt
diff --git a/test/1982-no-virtuals-structural-redefinition/Android.bp b/test/1982-no-virtuals-structural-redefinition/Android.bp
new file mode 100644
index 0000000..025bb7a
--- /dev/null
+++ b/test/1982-no-virtuals-structural-redefinition/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1982-no-virtuals-structural-redefinition`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1982-no-virtuals-structural-redefinition",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1982-no-virtuals-structural-redefinition-expected-stdout",
+        ":art-run-test-1982-no-virtuals-structural-redefinition-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1982-no-virtuals-structural-redefinition-expected-stdout",
+    out: ["art-run-test-1982-no-virtuals-structural-redefinition-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1982-no-virtuals-structural-redefinition-expected-stderr",
+    out: ["art-run-test-1982-no-virtuals-structural-redefinition-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/134-reg-promotion/expected.txt b/test/1982-no-virtuals-structural-redefinition/expected-stderr.txt
similarity index 100%
copy from test/134-reg-promotion/expected.txt
copy to test/1982-no-virtuals-structural-redefinition/expected-stderr.txt
diff --git a/test/1982-no-virtuals-structural-redefinition/expected.txt b/test/1982-no-virtuals-structural-redefinition/expected-stdout.txt
similarity index 100%
rename from test/1982-no-virtuals-structural-redefinition/expected.txt
rename to test/1982-no-virtuals-structural-redefinition/expected-stdout.txt
diff --git a/test/1901-get-bytecodes/expected.txt b/test/1983-structural-redefinition-failures/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/1983-structural-redefinition-failures/expected-stderr.txt
diff --git a/test/1983-structural-redefinition-failures/expected.txt b/test/1983-structural-redefinition-failures/expected-stdout.txt
similarity index 100%
rename from test/1983-structural-redefinition-failures/expected.txt
rename to test/1983-structural-redefinition-failures/expected-stdout.txt
diff --git a/test/1983-structural-redefinition-failures/info.txt b/test/1983-structural-redefinition-failures/info.txt
index 794f8eb..a839b52 100644
--- a/test/1983-structural-redefinition-failures/info.txt
+++ b/test/1983-structural-redefinition-failures/info.txt
@@ -1 +1 @@
-Sanity check for isStructurallyModifiable.
+Check for isStructurallyModifiable.
diff --git a/test/1984-structural-redefine-field-trace/Android.bp b/test/1984-structural-redefine-field-trace/Android.bp
new file mode 100644
index 0000000..18ff27b
--- /dev/null
+++ b/test/1984-structural-redefine-field-trace/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1984-structural-redefine-field-trace`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1984-structural-redefine-field-trace",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1984-structural-redefine-field-trace-expected-stdout",
+        ":art-run-test-1984-structural-redefine-field-trace-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1984-structural-redefine-field-trace-expected-stdout",
+    out: ["art-run-test-1984-structural-redefine-field-trace-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1984-structural-redefine-field-trace-expected-stderr",
+    out: ["art-run-test-1984-structural-redefine-field-trace-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/1984-structural-redefine-field-trace/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/1984-structural-redefine-field-trace/expected-stderr.txt
diff --git a/test/1984-structural-redefine-field-trace/expected.txt b/test/1984-structural-redefine-field-trace/expected-stdout.txt
similarity index 100%
rename from test/1984-structural-redefine-field-trace/expected.txt
rename to test/1984-structural-redefine-field-trace/expected-stdout.txt
diff --git a/test/1985-structural-redefine-stack-scope/Android.bp b/test/1985-structural-redefine-stack-scope/Android.bp
new file mode 100644
index 0000000..6200737
--- /dev/null
+++ b/test/1985-structural-redefine-stack-scope/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1985-structural-redefine-stack-scope`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1985-structural-redefine-stack-scope",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1985-structural-redefine-stack-scope-expected-stdout",
+        ":art-run-test-1985-structural-redefine-stack-scope-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1985-structural-redefine-stack-scope-expected-stdout",
+    out: ["art-run-test-1985-structural-redefine-stack-scope-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1985-structural-redefine-stack-scope-expected-stderr",
+    out: ["art-run-test-1985-structural-redefine-stack-scope-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/1985-structural-redefine-stack-scope/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/1985-structural-redefine-stack-scope/expected-stderr.txt
diff --git a/test/1985-structural-redefine-stack-scope/expected.txt b/test/1985-structural-redefine-stack-scope/expected-stdout.txt
similarity index 100%
rename from test/1985-structural-redefine-stack-scope/expected.txt
rename to test/1985-structural-redefine-stack-scope/expected-stdout.txt
diff --git a/test/1985-structural-redefine-stack-scope/stack_scope.cc b/test/1985-structural-redefine-stack-scope/stack_scope.cc
index 5c5215b..02d04dd 100644
--- a/test/1985-structural-redefine-stack-scope/stack_scope.cc
+++ b/test/1985-structural-redefine-stack-scope/stack_scope.cc
@@ -21,7 +21,7 @@
 #include <vector>
 
 #include "class_linker.h"
-#include "class_root.h"
+#include "class_root-inl.h"
 #include "jni.h"
 #include "jni/jni_internal.h"
 #include "mirror/class.h"
diff --git a/test/1986-structural-redefine-multi-thread-stack-scope/Android.bp b/test/1986-structural-redefine-multi-thread-stack-scope/Android.bp
new file mode 100644
index 0000000..559d134
--- /dev/null
+++ b/test/1986-structural-redefine-multi-thread-stack-scope/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1986-structural-redefine-multi-thread-stack-scope`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1986-structural-redefine-multi-thread-stack-scope",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1986-structural-redefine-multi-thread-stack-scope-expected-stdout",
+        ":art-run-test-1986-structural-redefine-multi-thread-stack-scope-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1986-structural-redefine-multi-thread-stack-scope-expected-stdout",
+    out: ["art-run-test-1986-structural-redefine-multi-thread-stack-scope-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1986-structural-redefine-multi-thread-stack-scope-expected-stderr",
+    out: ["art-run-test-1986-structural-redefine-multi-thread-stack-scope-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/1986-structural-redefine-multi-thread-stack-scope/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/1986-structural-redefine-multi-thread-stack-scope/expected-stderr.txt
diff --git a/test/1986-structural-redefine-multi-thread-stack-scope/expected.txt b/test/1986-structural-redefine-multi-thread-stack-scope/expected-stdout.txt
similarity index 100%
rename from test/1986-structural-redefine-multi-thread-stack-scope/expected.txt
rename to test/1986-structural-redefine-multi-thread-stack-scope/expected-stdout.txt
diff --git a/test/1987-structural-redefine-recursive-stack-scope/Android.bp b/test/1987-structural-redefine-recursive-stack-scope/Android.bp
new file mode 100644
index 0000000..70f64dd
--- /dev/null
+++ b/test/1987-structural-redefine-recursive-stack-scope/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1987-structural-redefine-recursive-stack-scope`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1987-structural-redefine-recursive-stack-scope",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1987-structural-redefine-recursive-stack-scope-expected-stdout",
+        ":art-run-test-1987-structural-redefine-recursive-stack-scope-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1987-structural-redefine-recursive-stack-scope-expected-stdout",
+    out: ["art-run-test-1987-structural-redefine-recursive-stack-scope-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1987-structural-redefine-recursive-stack-scope-expected-stderr",
+    out: ["art-run-test-1987-structural-redefine-recursive-stack-scope-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/1987-structural-redefine-recursive-stack-scope/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/1987-structural-redefine-recursive-stack-scope/expected-stderr.txt
diff --git a/test/1987-structural-redefine-recursive-stack-scope/expected.txt b/test/1987-structural-redefine-recursive-stack-scope/expected-stdout.txt
similarity index 100%
rename from test/1987-structural-redefine-recursive-stack-scope/expected.txt
rename to test/1987-structural-redefine-recursive-stack-scope/expected-stdout.txt
diff --git a/test/1988-multi-structural-redefine/Android.bp b/test/1988-multi-structural-redefine/Android.bp
new file mode 100644
index 0000000..57822b6
--- /dev/null
+++ b/test/1988-multi-structural-redefine/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1988-multi-structural-redefine`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1988-multi-structural-redefine",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1988-multi-structural-redefine-expected-stdout",
+        ":art-run-test-1988-multi-structural-redefine-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1988-multi-structural-redefine-expected-stdout",
+    out: ["art-run-test-1988-multi-structural-redefine-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1988-multi-structural-redefine-expected-stderr",
+    out: ["art-run-test-1988-multi-structural-redefine-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1911-get-local-var-table/expected.txt b/test/1988-multi-structural-redefine/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/1988-multi-structural-redefine/expected-stderr.txt
diff --git a/test/1988-multi-structural-redefine/expected.txt b/test/1988-multi-structural-redefine/expected-stdout.txt
similarity index 100%
rename from test/1988-multi-structural-redefine/expected.txt
rename to test/1988-multi-structural-redefine/expected-stdout.txt
diff --git a/test/1989-transform-bad-monitor/Android.bp b/test/1989-transform-bad-monitor/Android.bp
new file mode 100644
index 0000000..3aab06e
--- /dev/null
+++ b/test/1989-transform-bad-monitor/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1989-transform-bad-monitor`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1989-transform-bad-monitor",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1989-transform-bad-monitor-expected-stdout",
+        ":art-run-test-1989-transform-bad-monitor-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1989-transform-bad-monitor-expected-stdout",
+    out: ["art-run-test-1989-transform-bad-monitor-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1989-transform-bad-monitor-expected-stderr",
+    out: ["art-run-test-1989-transform-bad-monitor-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/404-optimizing-allocator/expected.txt b/test/1989-transform-bad-monitor/expected-stderr.txt
similarity index 100%
copy from test/404-optimizing-allocator/expected.txt
copy to test/1989-transform-bad-monitor/expected-stderr.txt
diff --git a/test/1989-transform-bad-monitor/expected.txt b/test/1989-transform-bad-monitor/expected-stdout.txt
similarity index 100%
rename from test/1989-transform-bad-monitor/expected.txt
rename to test/1989-transform-bad-monitor/expected-stdout.txt
diff --git a/test/1990-structural-bad-verify/Android.bp b/test/1990-structural-bad-verify/Android.bp
new file mode 100644
index 0000000..a312257
--- /dev/null
+++ b/test/1990-structural-bad-verify/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1990-structural-bad-verify`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1990-structural-bad-verify",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1990-structural-bad-verify-expected-stdout",
+        ":art-run-test-1990-structural-bad-verify-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1990-structural-bad-verify-expected-stdout",
+    out: ["art-run-test-1990-structural-bad-verify-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1990-structural-bad-verify-expected-stderr",
+    out: ["art-run-test-1990-structural-bad-verify-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/165-lock-owner-proxy/expected.txt b/test/1990-structural-bad-verify/expected-stderr.txt
similarity index 100%
copy from test/165-lock-owner-proxy/expected.txt
copy to test/1990-structural-bad-verify/expected-stderr.txt
diff --git a/test/1990-structural-bad-verify/expected.txt b/test/1990-structural-bad-verify/expected-stdout.txt
similarity index 100%
rename from test/1990-structural-bad-verify/expected.txt
rename to test/1990-structural-bad-verify/expected-stdout.txt
diff --git a/test/1991-hello-structural-retransform/Android.bp b/test/1991-hello-structural-retransform/Android.bp
new file mode 100644
index 0000000..ccb7696
--- /dev/null
+++ b/test/1991-hello-structural-retransform/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1991-hello-structural-retransform`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1991-hello-structural-retransform",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1991-hello-structural-retransform-expected-stdout",
+        ":art-run-test-1991-hello-structural-retransform-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1991-hello-structural-retransform-expected-stdout",
+    out: ["art-run-test-1991-hello-structural-retransform-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1991-hello-structural-retransform-expected-stderr",
+    out: ["art-run-test-1991-hello-structural-retransform-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1991-hello-structural-retransform/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1991-hello-structural-retransform/expected-stderr.txt
diff --git a/test/1991-hello-structural-retransform/expected.txt b/test/1991-hello-structural-retransform/expected-stdout.txt
similarity index 100%
rename from test/1991-hello-structural-retransform/expected.txt
rename to test/1991-hello-structural-retransform/expected-stdout.txt
diff --git a/test/1992-retransform-no-such-field/Android.bp b/test/1992-retransform-no-such-field/Android.bp
new file mode 100644
index 0000000..ac26018
--- /dev/null
+++ b/test/1992-retransform-no-such-field/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1992-retransform-no-such-field`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1992-retransform-no-such-field",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1992-retransform-no-such-field-expected-stdout",
+        ":art-run-test-1992-retransform-no-such-field-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1992-retransform-no-such-field-expected-stdout",
+    out: ["art-run-test-1992-retransform-no-such-field-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1992-retransform-no-such-field-expected-stderr",
+    out: ["art-run-test-1992-retransform-no-such-field-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/1992-retransform-no-such-field/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/1992-retransform-no-such-field/expected-stderr.txt
diff --git a/test/1992-retransform-no-such-field/expected.txt b/test/1992-retransform-no-such-field/expected-stdout.txt
similarity index 100%
rename from test/1992-retransform-no-such-field/expected.txt
rename to test/1992-retransform-no-such-field/expected-stdout.txt
diff --git a/test/1993-fallback-non-structural/Android.bp b/test/1993-fallback-non-structural/Android.bp
new file mode 100644
index 0000000..f5098a7
--- /dev/null
+++ b/test/1993-fallback-non-structural/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1993-fallback-non-structural`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1993-fallback-non-structural",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1993-fallback-non-structural-expected-stdout",
+        ":art-run-test-1993-fallback-non-structural-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1993-fallback-non-structural-expected-stdout",
+    out: ["art-run-test-1993-fallback-non-structural-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1993-fallback-non-structural-expected-stderr",
+    out: ["art-run-test-1993-fallback-non-structural-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1993-fallback-non-structural/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1993-fallback-non-structural/expected-stderr.txt
diff --git a/test/1993-fallback-non-structural/expected.txt b/test/1993-fallback-non-structural/expected-stdout.txt
similarity index 100%
rename from test/1993-fallback-non-structural/expected.txt
rename to test/1993-fallback-non-structural/expected-stdout.txt
diff --git a/test/1994-final-virtual-structural/Android.bp b/test/1994-final-virtual-structural/Android.bp
new file mode 100644
index 0000000..6f889b6
--- /dev/null
+++ b/test/1994-final-virtual-structural/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1994-final-virtual-structural`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1994-final-virtual-structural",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1994-final-virtual-structural-expected-stdout",
+        ":art-run-test-1994-final-virtual-structural-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1994-final-virtual-structural-expected-stdout",
+    out: ["art-run-test-1994-final-virtual-structural-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1994-final-virtual-structural-expected-stderr",
+    out: ["art-run-test-1994-final-virtual-structural-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1994-final-virtual-structural/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1994-final-virtual-structural/expected-stderr.txt
diff --git a/test/1994-final-virtual-structural/expected.txt b/test/1994-final-virtual-structural/expected-stdout.txt
similarity index 100%
rename from test/1994-final-virtual-structural/expected.txt
rename to test/1994-final-virtual-structural/expected-stdout.txt
diff --git a/test/1995-final-virtual-structural-multithread/Android.bp b/test/1995-final-virtual-structural-multithread/Android.bp
new file mode 100644
index 0000000..82a789f
--- /dev/null
+++ b/test/1995-final-virtual-structural-multithread/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1995-final-virtual-structural-multithread`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1995-final-virtual-structural-multithread",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1995-final-virtual-structural-multithread-expected-stdout",
+        ":art-run-test-1995-final-virtual-structural-multithread-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1995-final-virtual-structural-multithread-expected-stdout",
+    out: ["art-run-test-1995-final-virtual-structural-multithread-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1995-final-virtual-structural-multithread-expected-stderr",
+    out: ["art-run-test-1995-final-virtual-structural-multithread-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1995-final-virtual-structural-multithread/expected.txt b/test/1995-final-virtual-structural-multithread/expected-stderr.txt
similarity index 100%
rename from test/1995-final-virtual-structural-multithread/expected.txt
rename to test/1995-final-virtual-structural-multithread/expected-stderr.txt
diff --git a/test/1995-final-virtual-structural-multithread/expected.txt b/test/1995-final-virtual-structural-multithread/expected-stdout.txt
similarity index 100%
copy from test/1995-final-virtual-structural-multithread/expected.txt
copy to test/1995-final-virtual-structural-multithread/expected-stdout.txt
diff --git a/test/1996-final-override-virtual-structural/Android.bp b/test/1996-final-override-virtual-structural/Android.bp
new file mode 100644
index 0000000..e823c93
--- /dev/null
+++ b/test/1996-final-override-virtual-structural/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1996-final-override-virtual-structural`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1996-final-override-virtual-structural",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1996-final-override-virtual-structural-expected-stdout",
+        ":art-run-test-1996-final-override-virtual-structural-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1996-final-override-virtual-structural-expected-stdout",
+    out: ["art-run-test-1996-final-override-virtual-structural-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1996-final-override-virtual-structural-expected-stderr",
+    out: ["art-run-test-1996-final-override-virtual-structural-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1995-final-virtual-structural-multithread/expected.txt b/test/1996-final-override-virtual-structural/expected-stderr.txt
similarity index 100%
copy from test/1995-final-virtual-structural-multithread/expected.txt
copy to test/1996-final-override-virtual-structural/expected-stderr.txt
diff --git a/test/1996-final-override-virtual-structural/expected.txt b/test/1996-final-override-virtual-structural/expected-stdout.txt
similarity index 100%
rename from test/1996-final-override-virtual-structural/expected.txt
rename to test/1996-final-override-virtual-structural/expected-stdout.txt
diff --git a/test/1997-structural-shadow-method/Android.bp b/test/1997-structural-shadow-method/Android.bp
new file mode 100644
index 0000000..b7063b5
--- /dev/null
+++ b/test/1997-structural-shadow-method/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1997-structural-shadow-method`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1997-structural-shadow-method",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1997-structural-shadow-method-expected-stdout",
+        ":art-run-test-1997-structural-shadow-method-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1997-structural-shadow-method-expected-stdout",
+    out: ["art-run-test-1997-structural-shadow-method-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1997-structural-shadow-method-expected-stderr",
+    out: ["art-run-test-1997-structural-shadow-method-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/470-huge-method/expected.txt b/test/1997-structural-shadow-method/expected-stderr.txt
similarity index 100%
copy from test/470-huge-method/expected.txt
copy to test/1997-structural-shadow-method/expected-stderr.txt
diff --git a/test/1997-structural-shadow-method/expected.txt b/test/1997-structural-shadow-method/expected-stdout.txt
similarity index 100%
rename from test/1997-structural-shadow-method/expected.txt
rename to test/1997-structural-shadow-method/expected-stdout.txt
diff --git a/test/1998-structural-shadow-field/Android.bp b/test/1998-structural-shadow-field/Android.bp
new file mode 100644
index 0000000..ef3b418
--- /dev/null
+++ b/test/1998-structural-shadow-field/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1998-structural-shadow-field`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1998-structural-shadow-field",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1998-structural-shadow-field-expected-stdout",
+        ":art-run-test-1998-structural-shadow-field-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1998-structural-shadow-field-expected-stdout",
+    out: ["art-run-test-1998-structural-shadow-field-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1998-structural-shadow-field-expected-stderr",
+    out: ["art-run-test-1998-structural-shadow-field-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/168-vmstack-annotated/expected.txt b/test/1998-structural-shadow-field/expected-stderr.txt
similarity index 100%
copy from test/168-vmstack-annotated/expected.txt
copy to test/1998-structural-shadow-field/expected-stderr.txt
diff --git a/test/1998-structural-shadow-field/expected.txt b/test/1998-structural-shadow-field/expected-stdout.txt
similarity index 100%
rename from test/1998-structural-shadow-field/expected.txt
rename to test/1998-structural-shadow-field/expected-stdout.txt
diff --git a/test/1999-virtual-structural/Android.bp b/test/1999-virtual-structural/Android.bp
new file mode 100644
index 0000000..22fffdd
--- /dev/null
+++ b/test/1999-virtual-structural/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `1999-virtual-structural`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-1999-virtual-structural",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-1999-virtual-structural-expected-stdout",
+        ":art-run-test-1999-virtual-structural-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-1999-virtual-structural-expected-stdout",
+    out: ["art-run-test-1999-virtual-structural-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-1999-virtual-structural-expected-stderr",
+    out: ["art-run-test-1999-virtual-structural-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1900-track-alloc/expected.txt b/test/1999-virtual-structural/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/1999-virtual-structural/expected-stderr.txt
diff --git a/test/1999-virtual-structural/expected.txt b/test/1999-virtual-structural/expected-stdout.txt
similarity index 100%
rename from test/1999-virtual-structural/expected.txt
rename to test/1999-virtual-structural/expected-stdout.txt
diff --git a/test/202-thread-oome/expected.txt b/test/2000-virtual-list-structural/expected-stderr.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/2000-virtual-list-structural/expected-stderr.txt
diff --git a/test/2000-virtual-list-structural/expected.txt b/test/2000-virtual-list-structural/expected-stdout.txt
similarity index 100%
rename from test/2000-virtual-list-structural/expected.txt
rename to test/2000-virtual-list-structural/expected-stdout.txt
diff --git a/test/2001-virtual-structural-multithread/expected.txt b/test/2001-virtual-structural-multithread/expected-stderr.txt
similarity index 100%
rename from test/2001-virtual-structural-multithread/expected.txt
rename to test/2001-virtual-structural-multithread/expected-stderr.txt
diff --git a/test/2001-virtual-structural-multithread/expected.txt b/test/2001-virtual-structural-multithread/expected-stdout.txt
similarity index 100%
copy from test/2001-virtual-structural-multithread/expected.txt
copy to test/2001-virtual-structural-multithread/expected-stdout.txt
diff --git a/test/2019-constantcalculationsinking/expected.txt b/test/2002-virtual-structural-initializing/expected-stderr.txt
similarity index 100%
copy from test/2019-constantcalculationsinking/expected.txt
copy to test/2002-virtual-structural-initializing/expected-stderr.txt
diff --git a/test/2002-virtual-structural-initializing/expected.txt b/test/2002-virtual-structural-initializing/expected-stdout.txt
similarity index 100%
rename from test/2002-virtual-structural-initializing/expected.txt
rename to test/2002-virtual-structural-initializing/expected-stdout.txt
diff --git a/test/2003-double-virtual-structural/Android.bp b/test/2003-double-virtual-structural/Android.bp
new file mode 100644
index 0000000..2d23d91
--- /dev/null
+++ b/test/2003-double-virtual-structural/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2003-double-virtual-structural`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2003-double-virtual-structural",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2003-double-virtual-structural-expected-stdout",
+        ":art-run-test-2003-double-virtual-structural-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2003-double-virtual-structural-expected-stdout",
+    out: ["art-run-test-2003-double-virtual-structural-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2003-double-virtual-structural-expected-stderr",
+    out: ["art-run-test-2003-double-virtual-structural-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2001-virtual-structural-multithread/expected.txt b/test/2003-double-virtual-structural/expected-stderr.txt
similarity index 100%
copy from test/2001-virtual-structural-multithread/expected.txt
copy to test/2003-double-virtual-structural/expected-stderr.txt
diff --git a/test/2003-double-virtual-structural/expected.txt b/test/2003-double-virtual-structural/expected-stdout.txt
similarity index 100%
rename from test/2003-double-virtual-structural/expected.txt
rename to test/2003-double-virtual-structural/expected-stdout.txt
diff --git a/test/2004-double-virtual-structural-abstract/Android.bp b/test/2004-double-virtual-structural-abstract/Android.bp
new file mode 100644
index 0000000..4981920
--- /dev/null
+++ b/test/2004-double-virtual-structural-abstract/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2004-double-virtual-structural-abstract`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2004-double-virtual-structural-abstract",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2004-double-virtual-structural-abstract-expected-stdout",
+        ":art-run-test-2004-double-virtual-structural-abstract-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2004-double-virtual-structural-abstract-expected-stdout",
+    out: ["art-run-test-2004-double-virtual-structural-abstract-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2004-double-virtual-structural-abstract-expected-stderr",
+    out: ["art-run-test-2004-double-virtual-structural-abstract-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2001-virtual-structural-multithread/expected.txt b/test/2004-double-virtual-structural-abstract/expected-stderr.txt
similarity index 100%
copy from test/2001-virtual-structural-multithread/expected.txt
copy to test/2004-double-virtual-structural-abstract/expected-stderr.txt
diff --git a/test/2004-double-virtual-structural-abstract/expected.txt b/test/2004-double-virtual-structural-abstract/expected-stdout.txt
similarity index 100%
rename from test/2004-double-virtual-structural-abstract/expected.txt
rename to test/2004-double-virtual-structural-abstract/expected-stdout.txt
diff --git a/test/2005-pause-all-redefine-multithreaded/Android.bp b/test/2005-pause-all-redefine-multithreaded/Android.bp
new file mode 100644
index 0000000..ce54227
--- /dev/null
+++ b/test/2005-pause-all-redefine-multithreaded/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2005-pause-all-redefine-multithreaded`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2005-pause-all-redefine-multithreaded",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2005-pause-all-redefine-multithreaded-expected-stdout",
+        ":art-run-test-2005-pause-all-redefine-multithreaded-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2005-pause-all-redefine-multithreaded-expected-stdout",
+    out: ["art-run-test-2005-pause-all-redefine-multithreaded-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2005-pause-all-redefine-multithreaded-expected-stderr",
+    out: ["art-run-test-2005-pause-all-redefine-multithreaded-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2005-pause-all-redefine-multithreaded/expected.txt b/test/2005-pause-all-redefine-multithreaded/expected-stderr.txt
similarity index 100%
rename from test/2005-pause-all-redefine-multithreaded/expected.txt
rename to test/2005-pause-all-redefine-multithreaded/expected-stderr.txt
diff --git a/test/2005-pause-all-redefine-multithreaded/expected.txt b/test/2005-pause-all-redefine-multithreaded/expected-stdout.txt
similarity index 100%
copy from test/2005-pause-all-redefine-multithreaded/expected.txt
copy to test/2005-pause-all-redefine-multithreaded/expected-stdout.txt
diff --git a/test/2019-constantcalculationsinking/expected.txt b/test/2006-virtual-structural-finalizing/expected-stderr.txt
similarity index 100%
copy from test/2019-constantcalculationsinking/expected.txt
copy to test/2006-virtual-structural-finalizing/expected-stderr.txt
diff --git a/test/2006-virtual-structural-finalizing/expected.txt b/test/2006-virtual-structural-finalizing/expected-stdout.txt
similarity index 100%
rename from test/2006-virtual-structural-finalizing/expected.txt
rename to test/2006-virtual-structural-finalizing/expected-stdout.txt
diff --git a/test/1911-get-local-var-table/expected.txt b/test/2007-virtual-structural-finalizable/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/2007-virtual-structural-finalizable/expected-stderr.txt
diff --git a/test/2007-virtual-structural-finalizable/expected.txt b/test/2007-virtual-structural-finalizable/expected-stdout.txt
similarity index 100%
rename from test/2007-virtual-structural-finalizable/expected.txt
rename to test/2007-virtual-structural-finalizable/expected-stdout.txt
diff --git a/test/2008-redefine-then-old-reflect-field/Android.bp b/test/2008-redefine-then-old-reflect-field/Android.bp
new file mode 100644
index 0000000..f3d28fb
--- /dev/null
+++ b/test/2008-redefine-then-old-reflect-field/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2008-redefine-then-old-reflect-field`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2008-redefine-then-old-reflect-field",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2008-redefine-then-old-reflect-field-expected-stdout",
+        ":art-run-test-2008-redefine-then-old-reflect-field-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2008-redefine-then-old-reflect-field-expected-stdout",
+    out: ["art-run-test-2008-redefine-then-old-reflect-field-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2008-redefine-then-old-reflect-field-expected-stderr",
+    out: ["art-run-test-2008-redefine-then-old-reflect-field-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2001-virtual-structural-multithread/expected.txt b/test/2008-redefine-then-old-reflect-field/expected-stderr.txt
similarity index 100%
copy from test/2001-virtual-structural-multithread/expected.txt
copy to test/2008-redefine-then-old-reflect-field/expected-stderr.txt
diff --git a/test/2008-redefine-then-old-reflect-field/expected.txt b/test/2008-redefine-then-old-reflect-field/expected-stdout.txt
similarity index 100%
rename from test/2008-redefine-then-old-reflect-field/expected.txt
rename to test/2008-redefine-then-old-reflect-field/expected-stdout.txt
diff --git a/test/1903-suspend-self/expected.txt b/test/2009-structural-local-ref/expected-stderr.txt
similarity index 100%
copy from test/1903-suspend-self/expected.txt
copy to test/2009-structural-local-ref/expected-stderr.txt
diff --git a/test/2009-structural-local-ref/expected.txt b/test/2009-structural-local-ref/expected-stdout.txt
similarity index 100%
rename from test/2009-structural-local-ref/expected.txt
rename to test/2009-structural-local-ref/expected-stdout.txt
diff --git a/test/201-built-in-except-detail-messages/Android.bp b/test/201-built-in-except-detail-messages/Android.bp
new file mode 100644
index 0000000..894dfb0
--- /dev/null
+++ b/test/201-built-in-except-detail-messages/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `201-built-in-except-detail-messages`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-201-built-in-except-detail-messages",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-201-built-in-except-detail-messages-expected-stdout",
+        ":art-run-test-201-built-in-except-detail-messages-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-201-built-in-except-detail-messages-expected-stdout",
+    out: ["art-run-test-201-built-in-except-detail-messages-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-201-built-in-except-detail-messages-expected-stderr",
+    out: ["art-run-test-201-built-in-except-detail-messages-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/201-built-in-except-detail-messages/expected.txt b/test/201-built-in-except-detail-messages/expected-stderr.txt
similarity index 100%
rename from test/201-built-in-except-detail-messages/expected.txt
rename to test/201-built-in-except-detail-messages/expected-stderr.txt
diff --git a/test/201-built-in-except-detail-messages/expected.txt b/test/201-built-in-except-detail-messages/expected-stdout.txt
similarity index 100%
copy from test/201-built-in-except-detail-messages/expected.txt
copy to test/201-built-in-except-detail-messages/expected-stdout.txt
diff --git a/test/2011-stack-walk-concurrent-instrument/Android.bp b/test/2011-stack-walk-concurrent-instrument/Android.bp
new file mode 100644
index 0000000..95820f2
--- /dev/null
+++ b/test/2011-stack-walk-concurrent-instrument/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2011-stack-walk-concurrent-instrument`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2011-stack-walk-concurrent-instrument",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2011-stack-walk-concurrent-instrument-expected-stdout",
+        ":art-run-test-2011-stack-walk-concurrent-instrument-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2011-stack-walk-concurrent-instrument-expected-stdout",
+    out: ["art-run-test-2011-stack-walk-concurrent-instrument-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2011-stack-walk-concurrent-instrument-expected-stderr",
+    out: ["art-run-test-2011-stack-walk-concurrent-instrument-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1959-redefine-object-instrument/expected.txt b/test/2011-stack-walk-concurrent-instrument/expected-stderr.txt
similarity index 100%
copy from test/1959-redefine-object-instrument/expected.txt
copy to test/2011-stack-walk-concurrent-instrument/expected-stderr.txt
diff --git a/test/2011-stack-walk-concurrent-instrument/expected.txt b/test/2011-stack-walk-concurrent-instrument/expected-stdout.txt
similarity index 100%
rename from test/2011-stack-walk-concurrent-instrument/expected.txt
rename to test/2011-stack-walk-concurrent-instrument/expected-stdout.txt
diff --git a/test/2001-virtual-structural-multithread/expected.txt b/test/2012-structural-redefinition-failures-jni-id/expected-stderr.txt
similarity index 100%
copy from test/2001-virtual-structural-multithread/expected.txt
copy to test/2012-structural-redefinition-failures-jni-id/expected-stderr.txt
diff --git a/test/2012-structural-redefinition-failures-jni-id/expected.txt b/test/2012-structural-redefinition-failures-jni-id/expected-stdout.txt
similarity index 100%
rename from test/2012-structural-redefinition-failures-jni-id/expected.txt
rename to test/2012-structural-redefinition-failures-jni-id/expected-stdout.txt
diff --git a/test/2012-structural-redefinition-failures-jni-id/info.txt b/test/2012-structural-redefinition-failures-jni-id/info.txt
index 68520bf..106151b 100644
--- a/test/2012-structural-redefinition-failures-jni-id/info.txt
+++ b/test/2012-structural-redefinition-failures-jni-id/info.txt
@@ -1,3 +1,3 @@
-Sanity check for isStructurallyModifiable.
+Check for isStructurallyModifiable.
 
 Ensures that types being not-modifiable makes their supertypes not-modifiable.
diff --git a/test/2019-constantcalculationsinking/Android.bp b/test/2019-constantcalculationsinking/Android.bp
new file mode 100644
index 0000000..d9b323b
--- /dev/null
+++ b/test/2019-constantcalculationsinking/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2019-constantcalculationsinking`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2019-constantcalculationsinking",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2019-constantcalculationsinking-expected-stdout",
+        ":art-run-test-2019-constantcalculationsinking-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2019-constantcalculationsinking-expected-stdout",
+    out: ["art-run-test-2019-constantcalculationsinking-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2019-constantcalculationsinking-expected-stderr",
+    out: ["art-run-test-2019-constantcalculationsinking-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2019-constantcalculationsinking/expected.txt b/test/2019-constantcalculationsinking/expected-stderr.txt
similarity index 100%
rename from test/2019-constantcalculationsinking/expected.txt
rename to test/2019-constantcalculationsinking/expected-stderr.txt
diff --git a/test/2019-constantcalculationsinking/expected.txt b/test/2019-constantcalculationsinking/expected-stdout.txt
similarity index 100%
copy from test/2019-constantcalculationsinking/expected.txt
copy to test/2019-constantcalculationsinking/expected-stdout.txt
diff --git a/test/202-thread-oome/Android.bp b/test/202-thread-oome/Android.bp
new file mode 100644
index 0000000..d544432
--- /dev/null
+++ b/test/202-thread-oome/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `202-thread-oome`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-202-thread-oome",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-202-thread-oome-expected-stdout",
+        ":art-run-test-202-thread-oome-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-202-thread-oome-expected-stdout",
+    out: ["art-run-test-202-thread-oome-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-202-thread-oome-expected-stderr",
+    out: ["art-run-test-202-thread-oome-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/202-thread-oome/expected.txt b/test/202-thread-oome/expected-stderr.txt
similarity index 100%
rename from test/202-thread-oome/expected.txt
rename to test/202-thread-oome/expected-stderr.txt
diff --git a/test/202-thread-oome/expected.txt b/test/202-thread-oome/expected-stdout.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/202-thread-oome/expected-stdout.txt
diff --git a/test/2020-InvokeVirtual-Inlining/Android.bp b/test/2020-InvokeVirtual-Inlining/Android.bp
new file mode 100644
index 0000000..2e62ccb
--- /dev/null
+++ b/test/2020-InvokeVirtual-Inlining/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2020-InvokeVirtual-Inlining`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2020-InvokeVirtual-Inlining",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2020-InvokeVirtual-Inlining-expected-stdout",
+        ":art-run-test-2020-InvokeVirtual-Inlining-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2020-InvokeVirtual-Inlining-expected-stdout",
+    out: ["art-run-test-2020-InvokeVirtual-Inlining-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2020-InvokeVirtual-Inlining-expected-stderr",
+    out: ["art-run-test-2020-InvokeVirtual-Inlining-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2020-InvokeVirtual-Inlining/expected.txt b/test/2020-InvokeVirtual-Inlining/expected-stderr.txt
similarity index 100%
rename from test/2020-InvokeVirtual-Inlining/expected.txt
rename to test/2020-InvokeVirtual-Inlining/expected-stderr.txt
diff --git a/test/2020-InvokeVirtual-Inlining/expected.txt b/test/2020-InvokeVirtual-Inlining/expected-stdout.txt
similarity index 100%
copy from test/2020-InvokeVirtual-Inlining/expected.txt
copy to test/2020-InvokeVirtual-Inlining/expected-stdout.txt
diff --git a/test/2021-InvokeStatic-Inlining/Android.bp b/test/2021-InvokeStatic-Inlining/Android.bp
new file mode 100644
index 0000000..f9e265f
--- /dev/null
+++ b/test/2021-InvokeStatic-Inlining/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2021-InvokeStatic-Inlining`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2021-InvokeStatic-Inlining",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2021-InvokeStatic-Inlining-expected-stdout",
+        ":art-run-test-2021-InvokeStatic-Inlining-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2021-InvokeStatic-Inlining-expected-stdout",
+    out: ["art-run-test-2021-InvokeStatic-Inlining-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2021-InvokeStatic-Inlining-expected-stderr",
+    out: ["art-run-test-2021-InvokeStatic-Inlining-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2021-InvokeStatic-Inlining/expected.txt b/test/2021-InvokeStatic-Inlining/expected-stderr.txt
similarity index 100%
rename from test/2021-InvokeStatic-Inlining/expected.txt
rename to test/2021-InvokeStatic-Inlining/expected-stderr.txt
diff --git a/test/2021-InvokeStatic-Inlining/expected.txt b/test/2021-InvokeStatic-Inlining/expected-stdout.txt
similarity index 100%
copy from test/2021-InvokeStatic-Inlining/expected.txt
copy to test/2021-InvokeStatic-Inlining/expected-stdout.txt
diff --git a/test/2022-Invariantloops/Android.bp b/test/2022-Invariantloops/Android.bp
new file mode 100644
index 0000000..e477d90
--- /dev/null
+++ b/test/2022-Invariantloops/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2022-Invariantloops`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2022-Invariantloops",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2022-Invariantloops-expected-stdout",
+        ":art-run-test-2022-Invariantloops-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2022-Invariantloops-expected-stdout",
+    out: ["art-run-test-2022-Invariantloops-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2022-Invariantloops-expected-stderr",
+    out: ["art-run-test-2022-Invariantloops-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2022-Invariantloops/expected.txt b/test/2022-Invariantloops/expected-stderr.txt
similarity index 100%
rename from test/2022-Invariantloops/expected.txt
rename to test/2022-Invariantloops/expected-stderr.txt
diff --git a/test/2022-Invariantloops/expected.txt b/test/2022-Invariantloops/expected-stdout.txt
similarity index 100%
copy from test/2022-Invariantloops/expected.txt
copy to test/2022-Invariantloops/expected-stdout.txt
diff --git a/test/2023-InvariantLoops_typecast/Android.bp b/test/2023-InvariantLoops_typecast/Android.bp
new file mode 100644
index 0000000..27aa9bf
--- /dev/null
+++ b/test/2023-InvariantLoops_typecast/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2023-InvariantLoops_typecast`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2023-InvariantLoops_typecast",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2023-InvariantLoops_typecast-expected-stdout",
+        ":art-run-test-2023-InvariantLoops_typecast-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2023-InvariantLoops_typecast-expected-stdout",
+    out: ["art-run-test-2023-InvariantLoops_typecast-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2023-InvariantLoops_typecast-expected-stderr",
+    out: ["art-run-test-2023-InvariantLoops_typecast-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2023-InvariantLoops_typecast/expected.txt b/test/2023-InvariantLoops_typecast/expected-stderr.txt
similarity index 100%
rename from test/2023-InvariantLoops_typecast/expected.txt
rename to test/2023-InvariantLoops_typecast/expected-stderr.txt
diff --git a/test/2023-InvariantLoops_typecast/expected.txt b/test/2023-InvariantLoops_typecast/expected-stdout.txt
similarity index 100%
copy from test/2023-InvariantLoops_typecast/expected.txt
copy to test/2023-InvariantLoops_typecast/expected-stdout.txt
diff --git a/test/2024-InvariantNegativeLoop/Android.bp b/test/2024-InvariantNegativeLoop/Android.bp
new file mode 100644
index 0000000..707aab6
--- /dev/null
+++ b/test/2024-InvariantNegativeLoop/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2024-InvariantNegativeLoop`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2024-InvariantNegativeLoop",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2024-InvariantNegativeLoop-expected-stdout",
+        ":art-run-test-2024-InvariantNegativeLoop-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2024-InvariantNegativeLoop-expected-stdout",
+    out: ["art-run-test-2024-InvariantNegativeLoop-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2024-InvariantNegativeLoop-expected-stderr",
+    out: ["art-run-test-2024-InvariantNegativeLoop-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2024-InvariantNegativeLoop/expected.txt b/test/2024-InvariantNegativeLoop/expected-stderr.txt
similarity index 100%
rename from test/2024-InvariantNegativeLoop/expected.txt
rename to test/2024-InvariantNegativeLoop/expected-stderr.txt
diff --git a/test/2024-InvariantNegativeLoop/expected.txt b/test/2024-InvariantNegativeLoop/expected-stdout.txt
similarity index 100%
copy from test/2024-InvariantNegativeLoop/expected.txt
copy to test/2024-InvariantNegativeLoop/expected-stdout.txt
diff --git a/test/2025-ChangedArrayValue/Android.bp b/test/2025-ChangedArrayValue/Android.bp
new file mode 100644
index 0000000..451b862
--- /dev/null
+++ b/test/2025-ChangedArrayValue/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2025-ChangedArrayValue`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2025-ChangedArrayValue",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2025-ChangedArrayValue-expected-stdout",
+        ":art-run-test-2025-ChangedArrayValue-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2025-ChangedArrayValue-expected-stdout",
+    out: ["art-run-test-2025-ChangedArrayValue-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2025-ChangedArrayValue-expected-stderr",
+    out: ["art-run-test-2025-ChangedArrayValue-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2025-ChangedArrayValue/expected.txt b/test/2025-ChangedArrayValue/expected-stderr.txt
similarity index 100%
rename from test/2025-ChangedArrayValue/expected.txt
rename to test/2025-ChangedArrayValue/expected-stderr.txt
diff --git a/test/2025-ChangedArrayValue/expected.txt b/test/2025-ChangedArrayValue/expected-stdout.txt
similarity index 100%
copy from test/2025-ChangedArrayValue/expected.txt
copy to test/2025-ChangedArrayValue/expected-stdout.txt
diff --git a/test/2026-DifferentMemoryLSCouples/Android.bp b/test/2026-DifferentMemoryLSCouples/Android.bp
new file mode 100644
index 0000000..1bdad83
--- /dev/null
+++ b/test/2026-DifferentMemoryLSCouples/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2026-DifferentMemoryLSCouples`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2026-DifferentMemoryLSCouples",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2026-DifferentMemoryLSCouples-expected-stdout",
+        ":art-run-test-2026-DifferentMemoryLSCouples-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2026-DifferentMemoryLSCouples-expected-stdout",
+    out: ["art-run-test-2026-DifferentMemoryLSCouples-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2026-DifferentMemoryLSCouples-expected-stderr",
+    out: ["art-run-test-2026-DifferentMemoryLSCouples-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2026-DifferentMemoryLSCouples/expected.txt b/test/2026-DifferentMemoryLSCouples/expected-stderr.txt
similarity index 100%
rename from test/2026-DifferentMemoryLSCouples/expected.txt
rename to test/2026-DifferentMemoryLSCouples/expected-stderr.txt
diff --git a/test/2026-DifferentMemoryLSCouples/expected.txt b/test/2026-DifferentMemoryLSCouples/expected-stdout.txt
similarity index 100%
copy from test/2026-DifferentMemoryLSCouples/expected.txt
copy to test/2026-DifferentMemoryLSCouples/expected-stdout.txt
diff --git a/test/2026-DifferentMemoryLSCouples/src/Main.java b/test/2026-DifferentMemoryLSCouples/src/Main.java
index f5a305e..8425d86 100644
--- a/test/2026-DifferentMemoryLSCouples/src/Main.java
+++ b/test/2026-DifferentMemoryLSCouples/src/Main.java
@@ -16,11 +16,11 @@
 public class Main {
     class A {
         int fieldA;
-        int dummy;
+        int placeholder;
     }
 
     class B {
-        int dummy;
+        int placeholder;
         int fieldB;
     }
     public static void assertIntEquals(int expected, int result) {
diff --git a/test/2027-TwiceTheSameMemoryCouple/Android.bp b/test/2027-TwiceTheSameMemoryCouple/Android.bp
new file mode 100644
index 0000000..1c66124
--- /dev/null
+++ b/test/2027-TwiceTheSameMemoryCouple/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2027-TwiceTheSameMemoryCouple`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2027-TwiceTheSameMemoryCouple",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2027-TwiceTheSameMemoryCouple-expected-stdout",
+        ":art-run-test-2027-TwiceTheSameMemoryCouple-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2027-TwiceTheSameMemoryCouple-expected-stdout",
+    out: ["art-run-test-2027-TwiceTheSameMemoryCouple-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2027-TwiceTheSameMemoryCouple-expected-stderr",
+    out: ["art-run-test-2027-TwiceTheSameMemoryCouple-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2027-TwiceTheSameMemoryCouple/expected.txt b/test/2027-TwiceTheSameMemoryCouple/expected-stderr.txt
similarity index 100%
rename from test/2027-TwiceTheSameMemoryCouple/expected.txt
rename to test/2027-TwiceTheSameMemoryCouple/expected-stderr.txt
diff --git a/test/2027-TwiceTheSameMemoryCouple/expected.txt b/test/2027-TwiceTheSameMemoryCouple/expected-stdout.txt
similarity index 100%
copy from test/2027-TwiceTheSameMemoryCouple/expected.txt
copy to test/2027-TwiceTheSameMemoryCouple/expected-stdout.txt
diff --git a/test/2028-MultiBackward/Android.bp b/test/2028-MultiBackward/Android.bp
new file mode 100644
index 0000000..4e031e5
--- /dev/null
+++ b/test/2028-MultiBackward/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2028-MultiBackward`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2028-MultiBackward",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2028-MultiBackward-expected-stdout",
+        ":art-run-test-2028-MultiBackward-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2028-MultiBackward-expected-stdout",
+    out: ["art-run-test-2028-MultiBackward-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2028-MultiBackward-expected-stderr",
+    out: ["art-run-test-2028-MultiBackward-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2028-MultiBackward/expected.txt b/test/2028-MultiBackward/expected-stderr.txt
similarity index 100%
rename from test/2028-MultiBackward/expected.txt
rename to test/2028-MultiBackward/expected-stderr.txt
diff --git a/test/2028-MultiBackward/expected.txt b/test/2028-MultiBackward/expected-stdout.txt
similarity index 100%
copy from test/2028-MultiBackward/expected.txt
copy to test/2028-MultiBackward/expected-stdout.txt
diff --git a/test/2029-contended-monitors/Android.bp b/test/2029-contended-monitors/Android.bp
new file mode 100644
index 0000000..fd27d42
--- /dev/null
+++ b/test/2029-contended-monitors/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2029-contended-monitors`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2029-contended-monitors",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2029-contended-monitors-expected-stdout",
+        ":art-run-test-2029-contended-monitors-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2029-contended-monitors-expected-stdout",
+    out: ["art-run-test-2029-contended-monitors-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2029-contended-monitors-expected-stderr",
+    out: ["art-run-test-2029-contended-monitors-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/202-thread-oome/expected.txt b/test/2029-contended-monitors/expected-stderr.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/2029-contended-monitors/expected-stderr.txt
diff --git a/test/2029-contended-monitors/expected-stdout.txt b/test/2029-contended-monitors/expected-stdout.txt
new file mode 100644
index 0000000..4fa00bc
--- /dev/null
+++ b/test/2029-contended-monitors/expected-stdout.txt
@@ -0,0 +1,15 @@
+Starting
+Atomic increments
+Hold time 2, shared lock
+Hold time 20, shared lock
+Hold time 200, shared lock
+Hold time 2000, shared lock
+Hold time 20000, shared lock
+Hold time 200000, shared lock
+Hold time 2, pause time 18, shared lock
+Hold time 20, pause time 180, shared lock
+Hold time 200, pause time 1800, shared lock
+Hold time 2000, pause time 18000, shared lock
+Hold time 20000, pause time 180000, shared lock
+Hold for 2 msecs while sleeping, shared lock
+Hold for 2 msecs while sleeping, private lock
diff --git a/test/2029-contended-monitors/expected.txt b/test/2029-contended-monitors/expected.txt
deleted file mode 100644
index 1894ad7..0000000
--- a/test/2029-contended-monitors/expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-Starting
-Atomic increments
-Hold time 2, shared lock
-Hold time 20, shared lock
-Hold time 200, shared lock
-Hold time 2000, shared lock
-Hold time 20000, shared lock
-Hold time 200000, shared lock
-Hold for 2 msecs while sleeping, shared lock
-Hold for 2 msecs while sleeping, private lock
diff --git a/test/2029-contended-monitors/src/Main.java b/test/2029-contended-monitors/src/Main.java
index 78d2ae4..ffe8e73 100644
--- a/test/2029-contended-monitors/src/Main.java
+++ b/test/2029-contended-monitors/src/Main.java
@@ -44,7 +44,7 @@
     }
   }
 
-  // Increment counter by n, holding log for time roughly propertional to n.
+  // Increment counter by n, holding lock for time roughly propertional to n.
   // N must be even.
   private void holdFor(Object lock, int n) {
     synchronized(lock) {
@@ -56,6 +56,20 @@
     }
   }
 
+  // Increment local by an even number n in a way that takes time roughly proportional
+  // to n.
+  private void spinFor(int n) {
+    int y = -1;
+    int local_counter = 0;
+    for (int i = 0; i < n; ++i) {
+      local_counter += y;
+      y = nextInt(y);
+    }
+    if (local_counter != n) {
+      throw new Error();
+    }
+  }
+
   private class RepeatedLockHolder implements Runnable {
     RepeatedLockHolder(boolean shared, int n /* even */) {
       sharedLock = shared;
@@ -73,6 +87,24 @@
     private int holdTime;
   }
 
+  private class RepeatedIntermittentLockHolder implements Runnable {
+    RepeatedIntermittentLockHolder(boolean shared, int n /* even */) {
+      sharedLock = shared;
+      holdTime = n;
+    }
+    @Override
+    public void run() {
+      Object myLock = sharedLock ? lock : new Object();
+      int nIters = TOTAL_ITERS / 10 / currentThreadCount / holdTime;
+      for (int i = 0; i < nIters; ++i) {
+        spinFor(9 * holdTime);
+        holdFor(myLock, holdTime);
+      }
+    }
+    private boolean sharedLock;
+    private int holdTime;
+  }
+
   private class SleepyLockHolder implements Runnable {
     SleepyLockHolder(boolean shared) {
       sharedLock = shared;
@@ -154,11 +186,15 @@
   }
 
   private class CheckCounter implements Runnable {
+    private final int expected;
+    public CheckCounter(int e) {
+      expected = e;
+    }
     @Override
     public void run() {
-      if (counter != TOTAL_ITERS) {
+      if (counter != expected) {
         throw new AssertionError("Failed counter postcondition check for "
-            + currentThreadCount + " threads");
+            + currentThreadCount + " threads, expected " + expected + " got " + counter);
       }
     }
   }
@@ -172,7 +208,14 @@
     for (int i = 2; i <= MAX_HOLD_TIME; i *= 10) {
       // i * 8 (max thread count) divides TOTAL_ITERS
       System.out.println("Hold time " + i + ", shared lock");
-      runAll(new RepeatedLockHolder(true, i), () -> { counter = 0; }, new CheckCounter());
+      runAll(new RepeatedLockHolder(true, i), () -> { counter = 0; },
+          new CheckCounter(TOTAL_ITERS));
+    }
+    for (int i = 2; i <= MAX_HOLD_TIME / 10; i *= 10) {
+      // i * 8 (max thread count) divides TOTAL_ITERS
+      System.out.println("Hold time " + i + ", pause time " + (9 * i) + ", shared lock");
+      runAll(new RepeatedIntermittentLockHolder(true, i), () -> { counter = 0; },
+          new CheckCounter(TOTAL_ITERS / 10));
     }
     if (PRINT_TIMES) {
       for (int i = 2; i <= MAX_HOLD_TIME; i *= 1000) {
@@ -183,7 +226,7 @@
       }
     }
     System.out.println("Hold for 2 msecs while sleeping, shared lock");
-    runAll(new SleepyLockHolder(true), () -> { counter = 0; }, new CheckCounter());
+    runAll(new SleepyLockHolder(true), () -> { counter = 0; }, new CheckCounter(TOTAL_ITERS));
     System.out.println("Hold for 2 msecs while sleeping, private lock");
     runAll(new SleepyLockHolder(false), () -> { counter = 0; }, () -> {});
   }
diff --git a/test/2029-spaces-in-SimpleName/build b/test/2029-spaces-in-SimpleName/build
deleted file mode 100755
index 9c3cc79..0000000
--- a/test/2029-spaces-in-SimpleName/build
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/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.
-
-# Stop on failure and be verbose.
-set -e -x
-
-export ASM_JAR="${ANDROID_BUILD_TOP}/prebuilts/misc/common/asm/asm-6.0.jar"
-
-cd src
-
-# generate Java bytecode with ASM
-${JAVAC:-java} -cp "$ASM_JAR:." SpacesInSimpleName.java
-${JAVA:-java} -cp "$ASM_JAR:." SpacesInSimpleName
-
-# compile Java bytecode to DEX bytecode
-# TODO: replace DX with D8 when it adds support for spaces in SimpleName
-# ${D8} --min-api 10000 Main.class
-$ANDROID_HOST_OUT/bin/dx --dex --output=classes.dex Main.class
-
-# move the resulting DEX file and cleanup
-mv classes.dex ../classes.dex
-rm *.class
-
-cd ..
-
-# Use API level 10000 for spaces in SimpleName
-DESUGAR=false ./default-build "$@" --api-level 10000
diff --git a/test/2029-spaces-in-SimpleName/classes.dex b/test/2029-spaces-in-SimpleName/classes.dex
deleted file mode 100644
index 3804ca7..0000000
--- a/test/2029-spaces-in-SimpleName/classes.dex
+++ /dev/null
Binary files differ
diff --git a/test/203-multi-checkpoint/Android.bp b/test/203-multi-checkpoint/Android.bp
new file mode 100644
index 0000000..c04e106
--- /dev/null
+++ b/test/203-multi-checkpoint/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `203-multi-checkpoint`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-203-multi-checkpoint",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-203-multi-checkpoint-expected-stdout",
+        ":art-run-test-203-multi-checkpoint-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-203-multi-checkpoint-expected-stdout",
+    out: ["art-run-test-203-multi-checkpoint-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-203-multi-checkpoint-expected-stderr",
+    out: ["art-run-test-203-multi-checkpoint-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/528-long-hint/expected.txt b/test/203-multi-checkpoint/expected-stderr.txt
similarity index 100%
copy from test/528-long-hint/expected.txt
copy to test/203-multi-checkpoint/expected-stderr.txt
diff --git a/test/203-multi-checkpoint/expected.txt b/test/203-multi-checkpoint/expected-stdout.txt
similarity index 100%
rename from test/203-multi-checkpoint/expected.txt
rename to test/203-multi-checkpoint/expected-stdout.txt
diff --git a/test/2030-long-running-child/Android.bp b/test/2030-long-running-child/Android.bp
new file mode 100644
index 0000000..aeba519
--- /dev/null
+++ b/test/2030-long-running-child/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2030-long-running-child`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2030-long-running-child",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2030-long-running-child-expected-stdout",
+        ":art-run-test-2030-long-running-child-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2030-long-running-child-expected-stdout",
+    out: ["art-run-test-2030-long-running-child-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2030-long-running-child-expected-stderr",
+    out: ["art-run-test-2030-long-running-child-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2028-MultiBackward/expected.txt b/test/2030-long-running-child/expected-stderr.txt
similarity index 100%
copy from test/2028-MultiBackward/expected.txt
copy to test/2030-long-running-child/expected-stderr.txt
diff --git a/test/2030-long-running-child/expected.txt b/test/2030-long-running-child/expected-stdout.txt
similarity index 100%
rename from test/2030-long-running-child/expected.txt
rename to test/2030-long-running-child/expected-stdout.txt
diff --git a/test/2031-zygote-compiled-frame-deopt/Android.bp b/test/2031-zygote-compiled-frame-deopt/Android.bp
new file mode 100644
index 0000000..654cd49
--- /dev/null
+++ b/test/2031-zygote-compiled-frame-deopt/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2031-zygote-compiled-frame-deopt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2031-zygote-compiled-frame-deopt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2031-zygote-compiled-frame-deopt-expected-stdout",
+        ":art-run-test-2031-zygote-compiled-frame-deopt-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2031-zygote-compiled-frame-deopt-expected-stdout",
+    out: ["art-run-test-2031-zygote-compiled-frame-deopt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2031-zygote-compiled-frame-deopt-expected-stderr",
+    out: ["art-run-test-2031-zygote-compiled-frame-deopt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/513-array-deopt/expected.txt b/test/2031-zygote-compiled-frame-deopt/expected-stderr.txt
similarity index 100%
copy from test/513-array-deopt/expected.txt
copy to test/2031-zygote-compiled-frame-deopt/expected-stderr.txt
diff --git a/test/2031-zygote-compiled-frame-deopt/expected.txt b/test/2031-zygote-compiled-frame-deopt/expected-stdout.txt
similarity index 100%
rename from test/2031-zygote-compiled-frame-deopt/expected.txt
rename to test/2031-zygote-compiled-frame-deopt/expected-stdout.txt
diff --git a/test/2001-virtual-structural-multithread/expected.txt b/test/2032-default-method-private-override/expected-stderr.txt
similarity index 100%
copy from test/2001-virtual-structural-multithread/expected.txt
copy to test/2032-default-method-private-override/expected-stderr.txt
diff --git a/test/2032-default-method-private-override/expected.txt b/test/2032-default-method-private-override/expected-stdout.txt
similarity index 100%
rename from test/2032-default-method-private-override/expected.txt
rename to test/2032-default-method-private-override/expected-stdout.txt
diff --git a/test/2033-shutdown-mechanics/Android.bp b/test/2033-shutdown-mechanics/Android.bp
new file mode 100644
index 0000000..56867b3
--- /dev/null
+++ b/test/2033-shutdown-mechanics/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2033-shutdown-mechanics`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2033-shutdown-mechanics",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2033-shutdown-mechanics-expected-stdout",
+        ":art-run-test-2033-shutdown-mechanics-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2033-shutdown-mechanics-expected-stdout",
+    out: ["art-run-test-2033-shutdown-mechanics-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2033-shutdown-mechanics-expected-stderr",
+    out: ["art-run-test-2033-shutdown-mechanics-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2033-shutdown-mechanics/check b/test/2033-shutdown-mechanics/check
new file mode 100755
index 0000000..9523159
--- /dev/null
+++ b/test/2033-shutdown-mechanics/check
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# 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.
+
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
+# The daemon thread seems to occasionally get stopped before finishing.
+# Check that the actual output is a line-by-line prefix of expected.
+head -n $(wc -l < $2) $1 | diff --strip-trailing-cr -q - "$2" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4" >/dev/null
diff --git a/test/2022-Invariantloops/expected.txt b/test/2033-shutdown-mechanics/expected-stderr.txt
similarity index 100%
copy from test/2022-Invariantloops/expected.txt
copy to test/2033-shutdown-mechanics/expected-stderr.txt
diff --git a/test/2033-shutdown-mechanics/expected-stdout.txt b/test/2033-shutdown-mechanics/expected-stdout.txt
new file mode 100644
index 0000000..c95f39f
--- /dev/null
+++ b/test/2033-shutdown-mechanics/expected-stdout.txt
@@ -0,0 +1,6 @@
+JNI_OnLoad called
+Main Started
+Child started
+Main Finished
+Saw RuntimeShutdownFunctions
+Saw RuntimeDeleted
diff --git a/test/2033-shutdown-mechanics/info.txt b/test/2033-shutdown-mechanics/info.txt
new file mode 100644
index 0000000..d8b94e6
--- /dev/null
+++ b/test/2033-shutdown-mechanics/info.txt
@@ -0,0 +1,3 @@
+Check that when the main thread completes with a Daemon thread running
+in native code, the JNI environment is suitably adjusted so that we
+can avoid accessing deleted data structures.
diff --git a/test/2033-shutdown-mechanics/native_shutdown.cc b/test/2033-shutdown-mechanics/native_shutdown.cc
new file mode 100644
index 0000000..2b7546a
--- /dev/null
+++ b/test/2033-shutdown-mechanics/native_shutdown.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 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 "base/time_utils.h"
+#include "base/utils.h"
+#include "jni/jni_env_ext.h"
+#include "jni/jni_internal.h"
+
+#include "jni.h"
+
+#include <stdio.h>
+
+namespace art {
+
+static void MaybePrintTime() {
+  constexpr bool kPrintTime = false;
+  if (kPrintTime) {
+    printf("At %u msecs:", static_cast<int>(MilliTime()));
+  }
+}
+
+
+extern "C" [[noreturn]] JNIEXPORT void JNICALL Java_Main_monitorShutdown(
+    JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) {
+  bool found_shutdown = false;
+  bool found_runtime_deleted = false;
+  JNIEnvExt* const extEnv = down_cast<JNIEnvExt*>(env);
+  while (true) {
+    if (!found_shutdown && env->functions == GetRuntimeShutdownNativeInterface()) {
+      found_shutdown = true;
+      MaybePrintTime();
+      printf("Saw RuntimeShutdownFunctions\n");
+      fflush(stdout);
+    }
+    if (!found_runtime_deleted && extEnv->IsRuntimeDeleted()) {
+      found_runtime_deleted = true;
+      MaybePrintTime();
+      printf("Saw RuntimeDeleted\n");
+      fflush(stdout);
+    }
+    if (found_shutdown && found_runtime_deleted) {
+      // All JNI calls should now get rerouted to SleepForever();
+      (void) env->NewByteArray(17);
+      printf("Unexpectedly returned from JNI call\n");
+      fflush(stdout);
+      SleepForever();
+    }
+  }
+}
+
+}  // namespace art
+
+
diff --git a/test/2033-shutdown-mechanics/src/Main.java b/test/2033-shutdown-mechanics/src/Main.java
new file mode 100644
index 0000000..33548bd
--- /dev/null
+++ b/test/2033-shutdown-mechanics/src/Main.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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 {
+
+  private static class Child implements Runnable {
+    @Override
+    public void run() {
+      System.out.println("Child started");
+      // Enter native method and stay there, monitoring shutdown behavior.  Since we're a daemon,
+      // the process should shut down anyway, and we should be able to observe changes in the
+      // extended JNI environment.
+      monitorShutdown();
+    }
+  }
+
+  public static void main(String[] args) {
+    System.loadLibrary(args[0]);
+    System.out.println("Main Started");
+    Thread t = new Thread(new Child());
+    t.setDaemon(true);
+    t.start();
+    try {
+      Thread.sleep(400);
+    } catch (InterruptedException e) {
+      System.out.println("Unexpected interrupt");
+    }
+    System.out.println("Main Finished");
+  }
+
+  private static native void monitorShutdown();
+}
diff --git a/test/2034-spaces-in-SimpleName/build b/test/2034-spaces-in-SimpleName/build
new file mode 100755
index 0000000..940f6da
--- /dev/null
+++ b/test/2034-spaces-in-SimpleName/build
@@ -0,0 +1,29 @@
+#!/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.
+
+# Stop on failure and be verbose.
+set -e -x
+
+export ASM_JAR="${ANDROID_BUILD_TOP}/prebuilts/misc/common/asm/asm-6.0.jar"
+
+# generate Java bytecode with ASM
+cd src_gen
+${JAVA:-java} -cp "$ASM_JAR:." SpacesInSimpleName.java
+mkdir ../classes && mv Main.class ../classes/Main.class
+cd ..
+
+# Use API level 10000 for spaces in SimpleName
+DESUGAR=false ./default-build "$@" --api-level 10000
diff --git a/test/202-thread-oome/expected.txt b/test/2034-spaces-in-SimpleName/expected-stderr.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/2034-spaces-in-SimpleName/expected-stderr.txt
diff --git a/test/2029-spaces-in-SimpleName/expected.txt b/test/2034-spaces-in-SimpleName/expected-stdout.txt
similarity index 100%
rename from test/2029-spaces-in-SimpleName/expected.txt
rename to test/2034-spaces-in-SimpleName/expected-stdout.txt
diff --git a/test/2029-spaces-in-SimpleName/info.txt b/test/2034-spaces-in-SimpleName/info.txt
similarity index 100%
rename from test/2029-spaces-in-SimpleName/info.txt
rename to test/2034-spaces-in-SimpleName/info.txt
diff --git a/test/2029-spaces-in-SimpleName/src/SpacesInSimpleName.java b/test/2034-spaces-in-SimpleName/src_gen/SpacesInSimpleName.java
similarity index 100%
rename from test/2029-spaces-in-SimpleName/src/SpacesInSimpleName.java
rename to test/2034-spaces-in-SimpleName/src_gen/SpacesInSimpleName.java
diff --git a/test/470-huge-method/expected.txt b/test/2035-structural-native-method/expected-stderr.txt
similarity index 100%
copy from test/470-huge-method/expected.txt
copy to test/2035-structural-native-method/expected-stderr.txt
diff --git a/test/2035-structural-native-method/expected.txt b/test/2035-structural-native-method/expected-stdout.txt
similarity index 100%
rename from test/2035-structural-native-method/expected.txt
rename to test/2035-structural-native-method/expected-stdout.txt
diff --git a/test/2036-jni-filechannel/Android.bp b/test/2036-jni-filechannel/Android.bp
new file mode 100644
index 0000000..1de73dd
--- /dev/null
+++ b/test/2036-jni-filechannel/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2036-jni-filechannel`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2036-jni-filechannel",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2036-jni-filechannel-expected-stdout",
+        ":art-run-test-2036-jni-filechannel-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2036-jni-filechannel-expected-stdout",
+    out: ["art-run-test-2036-jni-filechannel-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2036-jni-filechannel-expected-stderr",
+    out: ["art-run-test-2036-jni-filechannel-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/202-thread-oome/expected.txt b/test/2036-jni-filechannel/expected-stderr.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/2036-jni-filechannel/expected-stderr.txt
diff --git a/test/2036-jni-filechannel/expected-stdout.txt b/test/2036-jni-filechannel/expected-stdout.txt
new file mode 100644
index 0000000..98ea70a
--- /dev/null
+++ b/test/2036-jni-filechannel/expected-stdout.txt
@@ -0,0 +1,2 @@
+JNI_OnLoad called
+Expected 0 got 0 PASS
diff --git a/test/2036-jni-filechannel/info.txt b/test/2036-jni-filechannel/info.txt
new file mode 100644
index 0000000..2d3ac28
--- /dev/null
+++ b/test/2036-jni-filechannel/info.txt
@@ -0,0 +1,2 @@
+Test that GetDirectBufferCapacity works correctly for a mapped buffer
+from a zero length file.
diff --git a/test/2036-jni-filechannel/jni_filechannel.cc b/test/2036-jni-filechannel/jni_filechannel.cc
new file mode 100644
index 0000000..edaee32
--- /dev/null
+++ b/test/2036-jni-filechannel/jni_filechannel.cc
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 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 <iostream>
+#include <jni.h>
+
+extern "C" JNIEXPORT void Java_Main_checkBufferCapacity(JNIEnv* env,
+                                                        jclass /*clazz*/,
+                                                        jobject buffer,
+                                                        jint expectedCapacity) {
+  jlong capacity = env->GetDirectBufferCapacity(buffer);
+  const char* status = (capacity == expectedCapacity) ? "PASS" : "FAIL";
+  std::cout << "Expected " << expectedCapacity
+            << " got " << capacity
+            << " " << status << std::endl;
+}
diff --git a/test/2036-jni-filechannel/src/Main.java b/test/2036-jni-filechannel/src/Main.java
new file mode 100644
index 0000000..204cde7
--- /dev/null
+++ b/test/2036-jni-filechannel/src/Main.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 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.nio.channels.FileChannel;
+import java.nio.file.*;
+import java.nio.Buffer;
+import java.nio.MappedByteBuffer;
+
+public class Main {
+    public static void main(String[] args) throws Exception {
+        System.loadLibrary(args[0]);
+
+        FileChannel channel = FileChannel.open(Paths.get("/dev", "null"),
+                                               StandardOpenOption.READ);
+        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, 0);
+        checkBufferCapacity(buffer, 0);
+    }
+
+    static native void checkBufferCapacity(Buffer buffer, int expectedCapacity);
+}
diff --git a/test/2001-virtual-structural-multithread/expected.txt b/test/2036-structural-subclass-shadow/expected-stderr.txt
similarity index 100%
copy from test/2001-virtual-structural-multithread/expected.txt
copy to test/2036-structural-subclass-shadow/expected-stderr.txt
diff --git a/test/2036-structural-subclass-shadow/expected-stdout.txt b/test/2036-structural-subclass-shadow/expected-stdout.txt
new file mode 100644
index 0000000..7fb86e3
--- /dev/null
+++ b/test/2036-structural-subclass-shadow/expected-stdout.txt
@@ -0,0 +1,8 @@
+value-getter is 42
+value is 42
+static-call is 1337
+static-value is 3.14
+value-getter is 0
+value is 0
+static-call is -559038737
+static-value is 0.0
diff --git a/test/2036-structural-subclass-shadow/info.txt b/test/2036-structural-subclass-shadow/info.txt
new file mode 100644
index 0000000..317dbf8
--- /dev/null
+++ b/test/2036-structural-subclass-shadow/info.txt
@@ -0,0 +1,5 @@
+Tests dex-cache invalidation with structural redefinition.
+
+Regression test for b/161846143. Structural redefinition was incorrectly
+failing to invalidate some dex-cache entries causing incorrect field/method
+resolution in limited cases.
diff --git a/test/2036-structural-subclass-shadow/run b/test/2036-structural-subclass-shadow/run
new file mode 100755
index 0000000..ff387ff
--- /dev/null
+++ b/test/2036-structural-subclass-shadow/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2020 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.
+
+./default-run "$@" --jvmti --runtime-option -Xopaque-jni-ids:true
diff --git a/test/2036-structural-subclass-shadow/src-art/Main.java b/test/2036-structural-subclass-shadow/src-art/Main.java
new file mode 100644
index 0000000..d707701
--- /dev/null
+++ b/test/2036-structural-subclass-shadow/src-art/Main.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 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) throws Exception {
+    art.Test2036.run();
+  }
+}
diff --git a/test/941-recurive-obsolete-jit/src/art/Redefinition.java b/test/2036-structural-subclass-shadow/src-art/art/Redefinition.java
similarity index 100%
copy from test/941-recurive-obsolete-jit/src/art/Redefinition.java
copy to test/2036-structural-subclass-shadow/src-art/art/Redefinition.java
diff --git a/test/2036-structural-subclass-shadow/src-art/art/Test2036.java b/test/2036-structural-subclass-shadow/src-art/art/Test2036.java
new file mode 100644
index 0000000..8ca8e2a
--- /dev/null
+++ b/test/2036-structural-subclass-shadow/src-art/art/Test2036.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package art;
+
+import java.util.Base64;
+
+public class Test2036 {
+  public static class Transform {
+    public Transform() {}
+  }
+
+  public static class SubTransform extends Transform {
+    public SubTransform() {}
+
+    public static int FooBar() {
+      return 1337;
+    }
+
+    public int foo = 42;
+    public static double STATIC_FOO = 3.14d;
+  }
+
+  public static class SubSubTransform extends SubTransform {
+    public SubSubTransform() {}
+  }
+
+  public static class SubSubSubTransform extends SubSubTransform {
+    public SubSubSubTransform() {}
+
+    public int getFoo() {
+      return this.foo;
+    }
+  }
+  /*
+   * base64 encoded class/dex file for
+   * Base64 generated using:
+   * % javac Test2036.java
+   * % d8 Test2035\$Transform.class
+   * % base64 classes.dex| sed 's:^:":' | sed 's:$:" +:'
+   *
+   * package art;
+   * public static class Transform {
+   *   public Transform() {}
+   *   public int bar;
+   * }
+   */
+  private static final byte[] DEX_BYTES =
+      Base64.getDecoder()
+          .decode(
+              "ZGV4CjAzNQAZlSz5hewOnpRnplr0AnEqh8+AKNc2qhp0AwAAcAAAAHhWNBIAAAAAAAAAALwCAAAP"
+                  + "AAAAcAAAAAcAAACsAAAAAQAAAMgAAAABAAAA1AAAAAIAAADcAAAAAQAAAOwAAABoAgAADAEAACgB"
+                  + "AAAwAQAAMwEAAE0BAABdAQAAgQEAAKEBAAC1AQAAxAEAAM8BAADSAQAA3wEAAOQBAADqAQAA8QEA"
+                  + "AAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAkAAAAJAAAABgAAAAAAAAABAAAACwAAAAEAAAAAAAAA"
+                  + "BQAAAAAAAAABAAAAAQAAAAUAAAAAAAAABwAAAKwCAACOAgAAAAAAAAEAAQABAAAAJAEAAAQAAABw"
+                  + "EAEAAAAOABgADgAGPGluaXQ+AAFJABhMYXJ0L1Rlc3QyMDM2JFRyYW5zZm9ybTsADkxhcnQvVGVz"
+                  + "dDIwMzY7ACJMZGFsdmlrL2Fubm90YXRpb24vRW5jbG9zaW5nQ2xhc3M7AB5MZGFsdmlrL2Fubm90"
+                  + "YXRpb24vSW5uZXJDbGFzczsAEkxqYXZhL2xhbmcvT2JqZWN0OwANVGVzdDIwMzYuamF2YQAJVHJh"
+                  + "bnNmb3JtAAFWAAthY2Nlc3NGbGFncwADYmFyAARuYW1lAAV2YWx1ZQCLAX5+RDh7ImNvbXBpbGF0"
+                  + "aW9uLW1vZGUiOiJkZWJ1ZyIsImhhcy1jaGVja3N1bXMiOmZhbHNlLCJtaW4tYXBpIjoxLCJzaGEt"
+                  + "MSI6IjJkMDE0MjEyNjVlMjUxMWM5MGUxZTY2NTU0NWEzMzliM2M5OWMwYWYiLCJ2ZXJzaW9uIjoi"
+                  + "Mi4yLjMtZGV2In0AAgMBDRgCAgQCCgQJDBcIAAEBAAABAIGABIwCAAAAAAAAAgAAAH8CAACFAgAA"
+                  + "oAIAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAACAAAABwAAAKwAAAAD"
+                  + "AAAAAQAAAMgAAAAEAAAAAQAAANQAAAAFAAAAAgAAANwAAAAGAAAAAQAAAOwAAAABIAAAAQAAAAwB"
+                  + "AAADIAAAAQAAACQBAAACIAAADwAAACgBAAAEIAAAAgAAAH8CAAAAIAAAAQAAAI4CAAADEAAAAgAA"
+                  + "AJwCAAAGIAAAAQAAAKwCAAAAEAAAAQAAALwCAAA=");
+  /*
+   * base64 encoded class/dex file for
+   * Base64 generated using:
+   * % javac Test2036.java
+   * % d8 Test2035\$SubSubTransform.class
+   * % base64 classes.dex| sed 's:^:":' | sed 's:$:" +:'
+   *
+   * package art;
+   * public static class SubSubTransform extends SubTransform {
+   *   public SubTransform() {}
+   *   public static int FooBar() { return 0xDEADBEEF; }
+   *   public int foo;
+   *   public static double STATIC_FOO;
+   * }
+   */
+  private static final byte[] DEX_BYTES_SUB_SUB =
+      Base64.getDecoder()
+          .decode(
+              "ZGV4CjAzNQATpeOoP5d8wSzfcaS99KwXbb1DsEne1tDsAwAAcAAAAHhWNBIAAAAAAAAAADQDAAAS"
+                  + "AAAAcAAAAAgAAAC4AAAAAgAAANgAAAACAAAA8AAAAAMAAAAAAQAAAQAAABgBAAC0AgAAOAEAAHAB"
+                  + "AAB4AQAAewEAAIMBAACGAQAApgEAAMMBAADTAQAA9wEAABcCAAAjAgAANAIAAEMCAABGAgAAUwIA"
+                  + "AFgCAABeAgAAZQIAAAEAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAMAAAAAwAAAAEAAAAAAAAA"
+                  + "DAAAAAcAAAAAAAAAAgAAAAkAAAACAAEADgAAAAIAAQAAAAAAAgAAAAIAAAADAAEAAAAAAAIAAAAB"
+                  + "AAAAAwAAAAAAAAALAAAAJAMAAAIDAAAAAAAAAQAAAAAAAABoAQAABAAAABQA776t3g8AAQABAAEA"
+                  + "AABsAQAABAAAAHAQAgAAAA4AIQAOACAADgAGPGluaXQ+AAFEAAZGb29CYXIAAUkAHkxhcnQvVGVz"
+                  + "dDIwMzYkU3ViU3ViVHJhbnNmb3JtOwAbTGFydC9UZXN0MjAzNiRTdWJUcmFuc2Zvcm07AA5MYXJ0"
+                  + "L1Rlc3QyMDM2OwAiTGRhbHZpay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAeTGRhbHZpay9h"
+                  + "bm5vdGF0aW9uL0lubmVyQ2xhc3M7AApTVEFUSUNfRk9PAA9TdWJTdWJUcmFuc2Zvcm0ADVRlc3Qy"
+                  + "MDM2LmphdmEAAVYAC2FjY2Vzc0ZsYWdzAANmb28ABG5hbWUABXZhbHVlAIsBfn5EOHsiY29tcGls"
+                  + "YXRpb24tbW9kZSI6ImRlYnVnIiwiaGFzLWNoZWNrc3VtcyI6ZmFsc2UsIm1pbi1hcGkiOjEsInNo"
+                  + "YS0xIjoiMmQwMTQyMTI2NWUyNTExYzkwZTFlNjY1NTQ1YTMzOWIzYzk5YzBhZiIsInZlcnNpb24i"
+                  + "OiIyLjIuMy1kZXYifQACBQEQGAQCBgINBAkPFwoBAQIAAAkBAQCBgATQAgEJuAIAAAAAAgAAAPMC"
+                  + "AAD5AgAAGAMAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAQAAAAAAAAABAAAAEgAAAHAAAAACAAAACAAA"
+                  + "ALgAAAADAAAAAgAAANgAAAAEAAAAAgAAAPAAAAAFAAAAAwAAAAABAAAGAAAAAQAAABgBAAABIAAA"
+                  + "AgAAADgBAAADIAAAAgAAAGgBAAACIAAAEgAAAHABAAAEIAAAAgAAAPMCAAAAIAAAAQAAAAIDAAAD"
+                  + "EAAAAgAAABQDAAAGIAAAAQAAACQDAAAAEAAAAQAAADQDAAA=");
+
+  public static void run() throws Exception {
+    Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE);
+    doTest();
+  }
+
+  public static void doTest() throws Exception {
+    SubSubSubTransform t = new SubSubSubTransform();
+    System.out.println("value-getter is " + t.getFoo());
+    System.out.println("value is " + t.foo);
+    System.out.println("static-call is " + SubSubSubTransform.FooBar());
+    System.out.println("static-value is " + SubSubSubTransform.STATIC_FOO);
+    Redefinition.doMultiStructuralClassRedefinition(
+        new Redefinition.DexOnlyClassDefinition(Transform.class, DEX_BYTES),
+        new Redefinition.DexOnlyClassDefinition(SubSubTransform.class, DEX_BYTES_SUB_SUB));
+    System.out.println("value-getter is " + t.getFoo());
+    System.out.println("value is " + t.foo);
+    System.out.println("static-call is " + SubSubSubTransform.FooBar());
+    System.out.println("static-value is " + SubSubSubTransform.STATIC_FOO);
+  }
+}
diff --git a/test/2036-structural-subclass-shadow/src/Main.java b/test/2036-structural-subclass-shadow/src/Main.java
new file mode 100644
index 0000000..e0477b0
--- /dev/null
+++ b/test/2036-structural-subclass-shadow/src/Main.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 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) throws Exception {
+    System.out.println("FAIL: Test is only for art!");
+  }
+}
diff --git a/test/2037-thread-name-inherit/Android.bp b/test/2037-thread-name-inherit/Android.bp
new file mode 100644
index 0000000..2fcfddc
--- /dev/null
+++ b/test/2037-thread-name-inherit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2037-thread-name-inherit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2037-thread-name-inherit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2037-thread-name-inherit-expected-stdout",
+        ":art-run-test-2037-thread-name-inherit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2037-thread-name-inherit-expected-stdout",
+    out: ["art-run-test-2037-thread-name-inherit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2037-thread-name-inherit-expected-stderr",
+    out: ["art-run-test-2037-thread-name-inherit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/202-thread-oome/expected.txt b/test/2037-thread-name-inherit/expected-stderr.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/2037-thread-name-inherit/expected-stderr.txt
diff --git a/test/655-jit-clinit/expected.txt b/test/2037-thread-name-inherit/expected-stdout.txt
similarity index 100%
copy from test/655-jit-clinit/expected.txt
copy to test/2037-thread-name-inherit/expected-stdout.txt
diff --git a/test/2037-thread-name-inherit/info.txt b/test/2037-thread-name-inherit/info.txt
new file mode 100644
index 0000000..f659e84
--- /dev/null
+++ b/test/2037-thread-name-inherit/info.txt
@@ -0,0 +1 @@
+Test that thread's names are correctly inherited.
diff --git a/test/2037-thread-name-inherit/src/Main.java b/test/2037-thread-name-inherit/src/Main.java
new file mode 100644
index 0000000..18049d7
--- /dev/null
+++ b/test/2037-thread-name-inherit/src/Main.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 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.util.function.*;
+
+public class Main {
+  public static final boolean IS_ART = System.getProperty("java.vm.name").equals("Dalvik");
+
+  public static final class Names {
+    public final String native_name;
+    public final String java_name;
+
+    public Names(String ntv, String java) {
+      this.native_name = ntv;
+      this.java_name = java;
+    }
+
+    public boolean equals(Object o) {
+      if (o instanceof Names) {
+        Names on = (Names) o;
+        return on.native_name.equals(native_name) && on.java_name.equals(java_name);
+      } else {
+        return false;
+      }
+    }
+
+    public String toString() {
+      return "Names{native: \"" + native_name + "\", java: \"" + java_name + "\"}";
+    }
+  }
+
+  public static void checkDefaultNames(Names res) {
+    if (IS_ART) {
+      if (!res.native_name.matches("Thread-[0-9]+")) {
+        throw new Error("Bad thread name! " + res);
+      }
+    } else {
+      if (!res.native_name.equals("native-thread")) {
+        throw new Error("Bad thread name! " + res);
+      }
+    }
+    if (!res.java_name.matches("Thread-[0-9]+")) {
+      throw new Error("Bad thread name! " + res);
+    }
+  }
+
+  public static void checkNames(Names res, Names art_exp, Names ri_exp) {
+    if (IS_ART) {
+      if (!res.equals(art_exp)) {
+        throw new Error("Not equal " + res + " != " + art_exp);
+      }
+    } else {
+      if (!res.equals(ri_exp)) {
+        throw new Error("Not equal " + res + " != " + ri_exp);
+      }
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    System.loadLibrary(args[0]);
+    Names[] name = new Names[1];
+    BiConsumer<String, Thread> thdResult =
+        (String native_name, Thread jthread) -> {
+          name[0] = new Names(native_name, jthread.getName());
+        };
+
+    runThreadTest(thdResult);
+    checkDefaultNames(name[0]);
+
+    runThreadTestWithName(thdResult);
+    checkNames(
+        name[0],
+        new Names("java-native-thr", "java-native-thread"),
+        new Names("native-thread", "java-native-thread"));
+
+    runThreadTestSetJava(thdResult);
+    checkNames(
+        name[0],
+        new Names("native-thread-s", "native-thread-set-java"),
+        new Names("native-thread", "native-thread-set-java"));
+  }
+
+  public static native void runThreadTest(BiConsumer<String, Thread> results);
+
+  public static native void runThreadTestWithName(BiConsumer<String, Thread> results);
+
+  public static native void runThreadTestSetJava(BiConsumer<String, Thread> results);
+}
diff --git a/test/2037-thread-name-inherit/thread_name_inherit.cc b/test/2037-thread-name-inherit/thread_name_inherit.cc
new file mode 100644
index 0000000..1cca514
--- /dev/null
+++ b/test/2037-thread-name-inherit/thread_name_inherit.cc
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2020 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 <iostream>
+
+#include "android-base/logging.h"
+
+struct ThreadArgs {
+  JavaVM* jvm;
+  jobject consumer;
+  JavaVMAttachArgs* attach_args;
+  bool set_in_java;
+};
+
+// The main method of the test thread. The ThreadArgs controls what this does.
+void* ThreadMain(void* arg) {
+  ThreadArgs* args = reinterpret_cast<ThreadArgs*>(arg);
+  JNIEnv* env = nullptr;
+  pthread_t self = pthread_self();
+
+  int err = pthread_setname_np(self, "native-thread");
+  CHECK_EQ(err, 0);
+
+  args->jvm->AttachCurrentThread(&env, args->attach_args);
+
+  jclass thread_class = env->FindClass("java/lang/Thread");
+  jclass consumer_class = env->FindClass("java/util/function/BiConsumer");
+  jmethodID current_thread_method =
+      env->GetStaticMethodID(thread_class, "currentThread", "()Ljava/lang/Thread;");
+  jmethodID accept_method =
+      env->GetMethodID(consumer_class, "accept", "(Ljava/lang/Object;Ljava/lang/Object;)V");
+  jobject current_thread = env->CallStaticObjectMethod(thread_class, current_thread_method);
+  if (args->set_in_java) {
+    jmethodID set_name_method = env->GetMethodID(thread_class, "setName", "(Ljava/lang/String;)V");
+    jobject str_name = env->NewStringUTF("native-thread-set-java");
+    env->CallVoidMethod(current_thread, set_name_method, str_name);
+  }
+
+  char name_chars[1024];
+  err = pthread_getname_np(self, name_chars, sizeof(name_chars));
+  CHECK_EQ(err, 0);
+  jobject str_name = env->NewStringUTF(name_chars);
+
+  env->CallVoidMethod(args->consumer, accept_method, str_name, current_thread);
+
+  args->jvm->DetachCurrentThread();
+
+  return nullptr;
+}
+
+extern "C" JNIEXPORT void Java_Main_runThreadTestWithName(JNIEnv* env,
+                                                          jclass /*clazz*/,
+                                                          jobject consumer) {
+  jobject global_consumer = env->NewGlobalRef(consumer);
+  JavaVMAttachArgs args;
+  args.group = nullptr;
+  args.name = "java-native-thread";
+  args.version = JNI_VERSION_1_6;
+  ThreadArgs ta {
+    .jvm = nullptr, .consumer = global_consumer, .attach_args = &args, .set_in_java = false
+  };
+  env->GetJavaVM(&ta.jvm);
+  pthread_t child;
+  pthread_create(&child, nullptr, ThreadMain, &ta);
+  void* ret;
+  pthread_join(child, &ret);
+  env->DeleteGlobalRef(ta.consumer);
+}
+
+extern "C" JNIEXPORT void Java_Main_runThreadTest(JNIEnv* env, jclass /*clazz*/, jobject consumer) {
+  jobject global_consumer = env->NewGlobalRef(consumer);
+  ThreadArgs ta {
+    .jvm = nullptr, .consumer = global_consumer, .attach_args = nullptr, .set_in_java = false
+  };
+  env->GetJavaVM(&ta.jvm);
+  pthread_t child;
+  pthread_create(&child, nullptr, ThreadMain, &ta);
+  void* ret;
+  pthread_join(child, &ret);
+  env->DeleteGlobalRef(ta.consumer);
+}
+
+extern "C" JNIEXPORT void Java_Main_runThreadTestSetJava(JNIEnv* env,
+                                                         jclass /*clazz*/,
+                                                         jobject consumer) {
+  jobject global_consumer = env->NewGlobalRef(consumer);
+  ThreadArgs ta {
+    .jvm = nullptr, .consumer = global_consumer, .attach_args = nullptr, .set_in_java = true
+  };
+  env->GetJavaVM(&ta.jvm);
+  pthread_t child;
+  pthread_create(&child, nullptr, ThreadMain, &ta);
+  void* ret;
+  pthread_join(child, &ret);
+  env->DeleteGlobalRef(ta.consumer);
+}
diff --git a/test/2038-hiddenapi-jvmti-ext/build b/test/2038-hiddenapi-jvmti-ext/build
new file mode 100644
index 0000000..f4b029f
--- /dev/null
+++ b/test/2038-hiddenapi-jvmti-ext/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+USE_HIDDENAPI=true ./default-build "$@"
diff --git a/test/202-thread-oome/expected.txt b/test/2038-hiddenapi-jvmti-ext/expected-stderr.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/2038-hiddenapi-jvmti-ext/expected-stderr.txt
diff --git a/test/004-UnsafeTest/expected.txt b/test/2038-hiddenapi-jvmti-ext/expected-stdout.txt
similarity index 100%
copy from test/004-UnsafeTest/expected.txt
copy to test/2038-hiddenapi-jvmti-ext/expected-stdout.txt
diff --git a/test/2038-hiddenapi-jvmti-ext/hiddenapi-flags.csv b/test/2038-hiddenapi-jvmti-ext/hiddenapi-flags.csv
new file mode 100644
index 0000000..6b31be6
--- /dev/null
+++ b/test/2038-hiddenapi-jvmti-ext/hiddenapi-flags.csv
@@ -0,0 +1,2 @@
+Lart/Test2038;->foo()V,blocked
+Lart/Test2038;->bar:I,blocked
diff --git a/test/2038-hiddenapi-jvmti-ext/hiddenapi_ext.cc b/test/2038-hiddenapi-jvmti-ext/hiddenapi_ext.cc
new file mode 100644
index 0000000..c012b11
--- /dev/null
+++ b/test/2038-hiddenapi-jvmti-ext/hiddenapi_ext.cc
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2020 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 <queue>
+#include <vector>
+
+#include "jvmti.h"
+
+// Test infrastructure
+#include "jvmti_helper.h"
+#include "nativehelper/scoped_local_ref.h"
+#include "nativehelper/scoped_primitive_array.h"
+#include "test_env.h"
+
+namespace art {
+namespace Test2038HiddenApiExt {
+
+template <typename T>
+static void Dealloc(T* t) {
+  jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(t));
+}
+
+template <typename T, typename... Rest>
+static void Dealloc(T* t, Rest... rs) {
+  Dealloc(t);
+  Dealloc(rs...);
+}
+
+static void DeallocParams(jvmtiParamInfo* params, jint n_params) {
+  for (jint i = 0; i < n_params; i++) {
+    Dealloc(params[i].name);
+  }
+}
+
+static constexpr std::string_view kDisablePolicyName =
+    "com.android.art.misc.disable_hidden_api_enforcement_policy";
+static constexpr std::string_view kGetPolicyName =
+    "com.android.art.misc.get_hidden_api_enforcement_policy";
+static constexpr std::string_view kSetPolicyName =
+    "com.android.art.misc.set_hidden_api_enforcement_policy";
+using GetPolicy = jvmtiError (*)(jvmtiEnv*, jint*);
+using SetPolicy = jvmtiError (*)(jvmtiEnv*, jint);
+using DisablePolicy = jvmtiError (*)(jvmtiEnv*);
+
+void* GetExtension(JNIEnv* env, const std::string_view& name) {
+  // Get the extensions.
+  jint n_ext = 0;
+  void* result = nullptr;
+  jvmtiExtensionFunctionInfo* infos = nullptr;
+  if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetExtensionFunctions(&n_ext, &infos))) {
+    return nullptr;
+  }
+  for (jint i = 0; i < n_ext; i++) {
+    jvmtiExtensionFunctionInfo* cur_info = &infos[i];
+    if (name == std::string_view(cur_info->id)) {
+      result = reinterpret_cast<void*>(cur_info->func);
+    }
+    // Cleanup the cur_info
+    DeallocParams(cur_info->params, cur_info->param_count);
+    Dealloc(cur_info->id, cur_info->short_description, cur_info->params, cur_info->errors);
+  }
+  // Cleanup the array.
+  Dealloc(infos);
+  if (result == nullptr) {
+    ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException"));
+    env->ThrowNew(rt_exception.get(), "Unable to find policy extensions.");
+    return nullptr;
+  }
+  return result;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_disablePolicy(JNIEnv* env, jclass) {
+  jint res;
+  GetPolicy get_policy = reinterpret_cast<GetPolicy>(GetExtension(env, kGetPolicyName));
+  if (get_policy == nullptr) {
+    return -1;
+  }
+  DisablePolicy disable_policy =
+      reinterpret_cast<DisablePolicy>(GetExtension(env, kDisablePolicyName));
+  if (disable_policy == nullptr) {
+    return -1;
+  }
+  if (JvmtiErrorToException(env, jvmti_env, get_policy(jvmti_env, &res))) {
+    return -1;
+  }
+  JvmtiErrorToException(env, jvmti_env, disable_policy(jvmti_env));
+  return res;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_setPolicy(JNIEnv* env, jclass, jint pol) {
+  jint res;
+  GetPolicy get_policy = reinterpret_cast<GetPolicy>(GetExtension(env, kGetPolicyName));
+  if (get_policy == nullptr) {
+    return -1;
+  }
+  SetPolicy set_policy = reinterpret_cast<SetPolicy>(GetExtension(env, kSetPolicyName));
+  if (set_policy == nullptr) {
+    return -1;
+  }
+  if (JvmtiErrorToException(env, jvmti_env, get_policy(jvmti_env, &res))) {
+    return -1;
+  }
+  JvmtiErrorToException(env, jvmti_env, set_policy(jvmti_env, pol));
+  return res;
+}
+
+}  // namespace Test2038HiddenApiExt
+}  // namespace art
diff --git a/test/2038-hiddenapi-jvmti-ext/info.txt b/test/2038-hiddenapi-jvmti-ext/info.txt
new file mode 100644
index 0000000..01c37e6
--- /dev/null
+++ b/test/2038-hiddenapi-jvmti-ext/info.txt
@@ -0,0 +1 @@
+Tests that the JVMTI set/get_hidden_api_enforcement_policy extensions work
diff --git a/test/941-recurive-obsolete-jit/run b/test/2038-hiddenapi-jvmti-ext/run
similarity index 100%
copy from test/941-recurive-obsolete-jit/run
copy to test/2038-hiddenapi-jvmti-ext/run
diff --git a/test/2038-hiddenapi-jvmti-ext/src-ex/Test2038.java b/test/2038-hiddenapi-jvmti-ext/src-ex/Test2038.java
new file mode 100644
index 0000000..07da43b
--- /dev/null
+++ b/test/2038-hiddenapi-jvmti-ext/src-ex/Test2038.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+package art;
+
+public class Test2038 {
+  public void foo() {
+    System.out.println("hello");
+  }
+
+  public int bar = 42;
+}
diff --git a/test/2038-hiddenapi-jvmti-ext/src/Main.java b/test/2038-hiddenapi-jvmti-ext/src/Main.java
new file mode 100644
index 0000000..b474c60
--- /dev/null
+++ b/test/2038-hiddenapi-jvmti-ext/src/Main.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.util.Base64;
+
+public class Main {
+  public static void main(String[] args) throws ClassNotFoundException {
+    System.loadLibrary(args[0]);
+
+    // Run the initialization routine. This will enable hidden API checks in
+    // the runtime, in case they are not enabled by default.
+    init();
+
+    // Load the '-ex' APK and attach it to the boot class path.
+    appendToBootClassLoader(DEX_EXTRA, /* isCorePlatform */ false);
+
+    // Find the test class in boot class loader and verify that its members are hidden.
+    Class<?> klass = Class.forName("art.Test2038", true, BOOT_CLASS_LOADER);
+    assertFieldIsHidden(klass, "before set-policy");
+    assertMethodIsHidden(klass, "before set-policy");
+
+    int old_policy = disablePolicy();
+
+    // Verify that the class members are not hidden.
+    assertFieldNotHidden(klass, "after disable-policy");
+    assertMethodNotHidden(klass, "after disable-policy");
+
+    setPolicy(old_policy);
+
+    assertFieldIsHidden(klass, "after set-policy 2");
+    assertMethodIsHidden(klass, "after set-policy 2");
+  }
+
+  private static void assertMethodNotHidden(Class<?> klass, String msg) {
+    try {
+      klass.getDeclaredMethod("foo");
+    } catch (NoSuchMethodException ex) {
+      // Unexpected. Should not have thrown NoSuchMethodException.
+      throw new RuntimeException("Method should be accessible " + msg);
+    }
+  }
+
+  private static void assertFieldNotHidden(Class<?> klass, String msg) {
+    try {
+      klass.getDeclaredField("bar");
+    } catch (NoSuchFieldException ex) {
+      // Unexpected. Should not have thrown NoSuchFieldException.
+      throw new RuntimeException("Field should be accessible " + msg);
+    }
+  }
+  private static void assertMethodIsHidden(Class<?> klass, String msg) {
+    try {
+      klass.getDeclaredMethod("foo");
+      // Unexpected. Should have thrown NoSuchMethodException.
+      throw new RuntimeException("Method should not be accessible " + msg);
+    } catch (NoSuchMethodException ex) {
+    }
+  }
+
+  private static void assertFieldIsHidden(Class<?> klass, String msg) {
+    try {
+      klass.getDeclaredField("bar");
+      // Unexpected. Should have thrown NoSuchFieldException.
+      throw new RuntimeException("Field should not be accessible " + msg);
+    } catch (NoSuchFieldException ex) {
+    }
+  }
+
+  private static final String DEX_EXTRA =
+      new File(System.getenv("DEX_LOCATION"), "2038-hiddenapi-jvmti-ext-ex.jar").getAbsolutePath();
+
+  private static ClassLoader BOOT_CLASS_LOADER = Object.class.getClassLoader();
+
+  // Native functions. Note that these are implemented in 674-hiddenapi/hiddenapi.cc.
+  private static native void appendToBootClassLoader(String dexPath, boolean isCorePlatform);
+  private static native void init();
+
+  // Native function implemented in hiddenapi_ext.cc
+  private static native int setPolicy(int new_policy);
+  private static native int disablePolicy();
+}
diff --git a/test/080-oom-throw-with-finalizer/expected.txt b/test/2039-load-transform-larger/expected-stderr.txt
similarity index 100%
copy from test/080-oom-throw-with-finalizer/expected.txt
copy to test/2039-load-transform-larger/expected-stderr.txt
diff --git a/test/934-load-transform/expected.txt b/test/2039-load-transform-larger/expected-stdout.txt
similarity index 100%
copy from test/934-load-transform/expected.txt
copy to test/2039-load-transform-larger/expected-stdout.txt
diff --git a/test/2039-load-transform-larger/info.txt b/test/2039-load-transform-larger/info.txt
new file mode 100644
index 0000000..ae7e715
--- /dev/null
+++ b/test/2039-load-transform-larger/info.txt
@@ -0,0 +1,3 @@
+Tests basic functions in the jvmti plugin.
+
+Test that making a class-object larger doesn't break anything.
diff --git a/test/2039-load-transform-larger/run b/test/2039-load-transform-larger/run
new file mode 100755
index 0000000..144c17d
--- /dev/null
+++ b/test/2039-load-transform-larger/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2021 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.
+
+./default-run "$@" --jvmti --no-app-image
diff --git a/test/2039-load-transform-larger/src-ex/TestMain.java b/test/2039-load-transform-larger/src-ex/TestMain.java
new file mode 100644
index 0000000..3ce664c
--- /dev/null
+++ b/test/2039-load-transform-larger/src-ex/TestMain.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 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 TestMain {
+  public static void runTest() {
+    new Transform().sayHi();
+  }
+}
diff --git a/test/2039-load-transform-larger/src-ex/Transform.java b/test/2039-load-transform-larger/src-ex/Transform.java
new file mode 100644
index 0000000..03dc782
--- /dev/null
+++ b/test/2039-load-transform-larger/src-ex/Transform.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class Transform {
+  public void sayHi() {
+    throw new Error("Should not be called!");
+  }
+}
diff --git a/test/2039-load-transform-larger/src/Main.java b/test/2039-load-transform-larger/src/Main.java
new file mode 100644
index 0000000..e235c56
--- /dev/null
+++ b/test/2039-load-transform-larger/src/Main.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2021 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 static art.Redefinition.addCommonTransformationResult;
+import static art.Redefinition.enableCommonRetransformation;
+import static art.Redefinition.setPopRetransformations;
+
+import java.lang.reflect.*;
+import java.util.Base64;
+
+class Main {
+  public static String TEST_NAME = "2039-load-transform-larger";
+
+  /**
+   * base64 encoded class/dex file for
+   * class Transform {
+   *   public static int PAD1;
+   *   public static int PAD2;
+   *   public static int PAD3;
+   *   public static int PAD4;
+   *   public static int PAD5;
+   *   public static int PAD6;
+   *   public static int PAD7;
+   *   public static int PAD8;
+   *   public static int PAD9;
+   *   public static int PAD10;
+   *   public static String TO_SAY = "Goodbye";
+   *   public void sayHi() {
+   *     System.out.println(TO_SAY);
+   *   }
+   * }
+   */
+  private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+    "yv66vgAAADcAQAoAEQAnCQAoACkJABAAKgoAKwAsCQAQAC0JABAALgkAEAAvCQAQADAJABAAMQkA" +
+    "EAAyCQAQADMJABAANAkAEAA1CQAQADYIADcHADgHADkBAARQQUQxAQABSQEABFBBRDIBAARQQUQz" +
+    "AQAEUEFENAEABFBBRDUBAARQQUQ2AQAEUEFENwEABFBBRDgBAARQQUQ5AQAFUEFEMTABAAZUT19T" +
+    "QVkBABJMamF2YS9sYW5nL1N0cmluZzsBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJl" +
+    "clRhYmxlAQAFc2F5SGkBAAg8Y2xpbml0PgEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQwA" +
+    "HwAgBwA6DAA7ADwMAB0AHgcAPQwAPgA/DAASABMMABQAEwwAFQATDAAWABMMABcAEwwAGAATDAAZ" +
+    "ABMMABoAEwwAGwATDAAcABMBAAdHb29kYnllAQAJVHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVj" +
+    "dAEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZh" +
+    "L2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgAgABAAEQAA" +
+    "AAsACQASABMAAAAJABQAEwAAAAkAFQATAAAACQAWABMAAAAJABcAEwAAAAkAGAATAAAACQAZABMA" +
+    "AAAJABoAEwAAAAkAGwATAAAACQAcABMAAAAJAB0AHgAAAAMAAAAfACAAAQAhAAAAHQABAAEAAAAF" +
+    "KrcAAbEAAAABACIAAAAGAAEAAAABAAEAIwAgAAEAIQAAACYAAgABAAAACrIAArIAA7YABLEAAAAB" +
+    "ACIAAAAKAAIAAAAOAAkADwAIACQAIAABACEAAABuAAEAAAAAAC4DswAFA7MABgOzAAcDswAIA7MA" +
+    "CQOzAAoDswALA7MADAOzAA0DswAOEg+zAAOxAAAAAQAiAAAALgALAAAAAgAEAAMACAAEAAwABQAQ" +
+    "AAYAFAAHABgACAAcAAkAIAAKACQACwAoAAwAAQAlAAAAAgAm");
+  private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+    "ZGV4CjAzNQDwqDsREETVXjkzn+/MRpRRrCJUZTv/xY28BAAAcAAAAHhWNBIAAAAAAAAAABAEAAAb" +
+    "AAAAcAAAAAcAAADcAAAAAgAAAPgAAAAMAAAAEAEAAAUAAABwAQAAAQAAAJgBAAAEAwAAuAEAAFIC" +
+    "AABcAgAAZAIAAG0CAABwAgAAfQIAAJQCAACoAgAAvAIAANACAADWAgAA3QIAAOMCAADpAgAA7wIA" +
+    "APUCAAD7AgAAAQMAAAcDAAANAwAAFQMAACUDAAAoAwAALAMAADEDAAA6AwAAQQMAAAMAAAAEAAAA" +
+    "BQAAAAYAAAAHAAAACAAAABUAAAAVAAAABgAAAAAAAAAWAAAABgAAAEwCAAABAAAACQAAAAEAAAAK" +
+    "AAAAAQAAAAsAAAABAAAADAAAAAEAAAANAAAAAQAAAA4AAAABAAAADwAAAAEAAAAQAAAAAQAAABEA" +
+    "AAABAAAAEgAAAAEABAATAAAABQACABcAAAABAAAAAAAAAAEAAAABAAAAAQAAABkAAAACAAEAGAAA" +
+    "AAMAAAABAAAAAQAAAAAAAAADAAAAAAAAABQAAAAAAAAA4AMAAAAAAAABAAAAAAAAADQCAAAaAAAA" +
+    "EgBnAAAAZwACAGcAAwBnAAQAZwAFAGcABgBnAAcAZwAIAGcACQBnAAEAGgACAGkACgAOAAEAAQAB" +
+    "AAAAQgIAAAQAAABwEAQAAAAOAAMAAQACAAAARgIAAAgAAABiAAsAYgEKAG4gAwAQAA4AAgAOPC0t" +
+    "LS0tLS0tLQABAA4ADgAOeAAAAQAAAAQACDxjbGluaXQ+AAY8aW5pdD4AB0dvb2RieWUAAUkAC0xU" +
+    "cmFuc2Zvcm07ABVMamF2YS9pby9QcmludFN0cmVhbTsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGph" +
+    "dmEvbGFuZy9TdHJpbmc7ABJMamF2YS9sYW5nL1N5c3RlbTsABFBBRDEABVBBRDEwAARQQUQyAARQ" +
+    "QUQzAARQQUQ0AARQQUQ1AARQQUQ2AARQQUQ3AARQQUQ4AARQQUQ5AAZUT19TQVkADlRyYW5zZm9y" +
+    "bS5qYXZhAAFWAAJWTAADb3V0AAdwcmludGxuAAVzYXlIaQCcAX5+RDh7ImJhY2tlbmQiOiJkZXgi" +
+    "LCJjb21waWxhdGlvbi1tb2RlIjoiZGVidWciLCJoYXMtY2hlY2tzdW1zIjpmYWxzZSwibWluLWFw" +
+    "aSI6MSwic2hhLTEiOiIzZmU0MDM4NDA1NTUyNTU3YzFjNjNhZTIxNjM5OGUzMzFiNWViZThkIiwi" +
+    "dmVyc2lvbiI6IjMuMC4zMC1kZXYifQALAAIBAAkBCQEJAQkBCQEJAQkBCQEJAQkBCQCIgAS4AwGA" +
+    "gAT8AwIBlAQAAAAAAAAOAAAAAAAAAAEAAAAAAAAAAQAAABsAAABwAAAAAgAAAAcAAADcAAAAAwAA" +
+    "AAIAAAD4AAAABAAAAAwAAAAQAQAABQAAAAUAAABwAQAABgAAAAEAAACYAQAAASAAAAMAAAC4AQAA" +
+    "AyAAAAMAAAA0AgAAARAAAAEAAABMAgAAAiAAABsAAABSAgAAACAAAAEAAADgAwAAAxAAAAEAAAAM" +
+    "BAAAABAAAAEAAAAQBAAA");
+
+  public static ClassLoader getClassLoaderFor(String location) throws Exception {
+    try {
+      Class<?> class_loader_class = Class.forName("dalvik.system.PathClassLoader");
+      Constructor<?> ctor = class_loader_class.getConstructor(String.class, ClassLoader.class);
+      /* on Dalvik, this is a DexFile; otherwise, it's null */
+      return (ClassLoader)ctor.newInstance(location + "/" + TEST_NAME + "-ex.jar",
+                                           Main.class.getClassLoader());
+    } catch (ClassNotFoundException e) {
+      // Running on RI. Use URLClassLoader.
+      return new java.net.URLClassLoader(
+          new java.net.URL[] { new java.net.URL("file://" + location + "/classes-ex/") });
+    }
+  }
+
+  public static void main(String[] args) {
+    // Don't pop transformations. Make sure that even if 2 threads race to define the class both
+    // will get the same result.
+    setPopRetransformations(false);
+    addCommonTransformationResult("Transform", CLASS_BYTES, DEX_BYTES);
+    enableCommonRetransformation(true);
+    try {
+      /* this is the "alternate" DEX/Jar file */
+      ClassLoader new_loader = getClassLoaderFor(System.getenv("DEX_LOCATION"));
+      Class<?> klass = (Class<?>)new_loader.loadClass("TestMain");
+      if (klass == null) {
+        throw new AssertionError("loadClass failed");
+      }
+      Method run_test = klass.getMethod("runTest");
+      run_test.invoke(null);
+    } catch (Exception e) {
+      System.out.println(e.toString());
+      e.printStackTrace(System.out);
+    }
+  }
+}
diff --git a/test/941-recurive-obsolete-jit/src/art/Redefinition.java b/test/2039-load-transform-larger/src/art/Redefinition.java
similarity index 100%
copy from test/941-recurive-obsolete-jit/src/art/Redefinition.java
copy to test/2039-load-transform-larger/src/art/Redefinition.java
diff --git a/test/160-read-barrier-stress/expected.txt b/test/2230-profile-save-hotness/expected-stderr.txt
similarity index 100%
copy from test/160-read-barrier-stress/expected.txt
copy to test/2230-profile-save-hotness/expected-stderr.txt
diff --git a/test/2230-profile-save-hotness/expected.txt b/test/2230-profile-save-hotness/expected-stdout.txt
similarity index 100%
rename from test/2230-profile-save-hotness/expected.txt
rename to test/2230-profile-save-hotness/expected-stdout.txt
diff --git a/test/2230-profile-save-hotness/src-art/Main.java b/test/2230-profile-save-hotness/src-art/Main.java
index 97177cc..f71a891 100644
--- a/test/2230-profile-save-hotness/src-art/Main.java
+++ b/test/2230-profile-save-hotness/src-art/Main.java
@@ -38,7 +38,12 @@
     try {
       file = createTempFile();
       String codePath = System.getenv("DEX_LOCATION") + "/2230-profile-save-hotness.jar";
-      VMRuntime.registerAppInfo(file.getPath(), new String[] {codePath});
+      VMRuntime.registerAppInfo(
+          "test.app",
+          file.getPath(),
+          file.getPath(),
+          new String[] {codePath},
+          VMRuntime.CODE_PATH_TYPE_PRIMARY_APK);
 
       // Test that the profile saves an app method with a profiling info.
       $noinline$hotnessCountWithLoop(10000);
@@ -71,7 +76,7 @@
   public static native boolean isAotCompiled(Class<?> cls, String methodName);
   public static native int getHotnessCounter(Class<?> cls, String methodName);
 
-  private static final String TEMP_FILE_NAME_PREFIX = "dummy";
+  private static final String TEMP_FILE_NAME_PREFIX = "temp";
   private static final String TEMP_FILE_NAME_SUFFIX = "-file";
 
   private static File createTempFile() throws Exception {
diff --git a/test/2231-checker-heap-poisoning/Android.bp b/test/2231-checker-heap-poisoning/Android.bp
new file mode 100644
index 0000000..b2623e3
--- /dev/null
+++ b/test/2231-checker-heap-poisoning/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2231-checker-heap-poisoning`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2231-checker-heap-poisoning",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2231-checker-heap-poisoning-expected-stdout",
+        ":art-run-test-2231-checker-heap-poisoning-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2231-checker-heap-poisoning-expected-stdout",
+    out: ["art-run-test-2231-checker-heap-poisoning-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2231-checker-heap-poisoning-expected-stderr",
+    out: ["art-run-test-2231-checker-heap-poisoning-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2020-InvokeVirtual-Inlining/expected.txt b/test/2231-checker-heap-poisoning/expected-stderr.txt
similarity index 100%
copy from test/2020-InvokeVirtual-Inlining/expected.txt
copy to test/2231-checker-heap-poisoning/expected-stderr.txt
diff --git a/test/591-new-instance-string/expected.txt b/test/2231-checker-heap-poisoning/expected-stdout.txt
similarity index 100%
copy from test/591-new-instance-string/expected.txt
copy to test/2231-checker-heap-poisoning/expected-stdout.txt
diff --git a/test/2231-checker-heap-poisoning/info.txt b/test/2231-checker-heap-poisoning/info.txt
new file mode 100644
index 0000000..81d7381
--- /dev/null
+++ b/test/2231-checker-heap-poisoning/info.txt
@@ -0,0 +1 @@
+Exercise Checker support for branching with heap poisoning.
diff --git a/test/2231-checker-heap-poisoning/src/Main.java b/test/2231-checker-heap-poisoning/src/Main.java
new file mode 100644
index 0000000..46b0f7c
--- /dev/null
+++ b/test/2231-checker-heap-poisoning/src/Main.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2020 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 {
+  Object field;
+
+  /// CHECK-START: java.lang.Object Main.testGetField() builder (after)
+  /// CHECK:       <<This:l\d+>>  ParameterValue
+  /// CHECK:                      InstanceFieldGet [<<This>>] field_name:Main.field
+
+  /// CHECK-START-ARM: java.lang.Object Main.testGetField() disassembly (after)
+  /// CHECK-IF: os.environ.get('ART_HEAP_POISONING') == 'true'
+  ///      CHECK-IF: os.environ.get('ART_READ_BARRIER_TYPE') != 'TABLELOOKUP'
+  ///           CHECK:  <<This:l\d+>>  ParameterValue
+  ///           CHECK:  <<Ref:l\d+>>   InstanceFieldGet [<<This>>] field_name:Main.field
+  ///           CHECK:                 ldr <<RefReg:r([0-8]|10|11)>>, [r1, #8]
+  ///           CHECK:                 rsbs <<RefReg>>, #0
+  ///           CHECK:                 Return [<<Ref>>]
+  ///      CHECK-FI:
+  /// CHECK-ELSE:
+  ///      CHECK-NOT: rsbs {{r\d+}}, #0
+  /// CHECK-FI:
+
+  /// CHECK-START-ARM64: java.lang.Object Main.testGetField() disassembly (after)
+  /// CHECK-IF: os.environ.get('ART_HEAP_POISONING') == 'true'
+  ///      CHECK-IF: os.environ.get('ART_READ_BARRIER_TYPE') != 'TABLELOOKUP'
+  ///           CHECK:  <<This:l\d+>>  ParameterValue
+  ///           CHECK:  <<Ref:l\d+>>   InstanceFieldGet [<<This>>] field_name:Main.field
+  ///           CHECK:                 ldr w0, [x1, #8]
+  ///           CHECK:                 neg w0, w0
+  ///           CHECK:                 Return [<<Ref>>]
+  ///           CHECK:                 ret
+  ///      CHECK-FI:
+  /// CHECK-ELSE:
+  ///      CHECK-NOT: neg {{w\d+}}, {{w\d+}}
+  /// CHECK-FI:
+
+  /// CHECK-START-X86: java.lang.Object Main.testGetField() disassembly (after)
+  /// CHECK-IF: os.environ.get('ART_HEAP_POISONING') == 'true'
+  ///      CHECK-IF: os.environ.get('ART_READ_BARRIER_TYPE') != 'TABLELOOKUP'
+  ///           CHECK:  <<This:l\d+>>  ParameterValue
+  ///           CHECK:  <<Ref:l\d+>>   InstanceFieldGet [<<This>>] field_name:Main.field
+  ///           CHECK:                 mov eax, [ecx + 8]
+  ///           CHECK:                 neg eax
+  ///           CHECK:                 Return [<<Ref>>]
+  ///           CHECK:                 ret
+  ///      CHECK-FI:
+  /// CHECK-ELSE:
+  ///      CHECK-NOT: neg {{[a-z]+}}
+  /// CHECK-FI:
+
+  /// CHECK-START-X86_64: java.lang.Object Main.testGetField() disassembly (after)
+  /// CHECK-IF: os.environ.get('ART_HEAP_POISONING') == 'true'
+  ///      CHECK-IF: os.environ.get('ART_READ_BARRIER_TYPE') != 'TABLELOOKUP'
+  ///           CHECK:  <<This:l\d+>>  ParameterValue
+  ///           CHECK:  <<Ref:l\d+>>   InstanceFieldGet [<<This>>] field_name:Main.field
+  ///           CHECK:                 mov eax, [rsi + 8]
+  ///           CHECK:                 neg eax
+  ///           CHECK:                 Return [<<Ref>>]
+  ///           CHECK:                 ret
+  ///      CHECK-FI:
+  /// CHECK-ELSE:
+  ///      CHECK-NOT: neg {{[a-z]+}}
+  /// CHECK-FI:
+
+  Object testGetField() {
+    return field;
+  }
+
+  /// CHECK-START: void Main.testSetField(java.lang.Object) builder (after)
+  /// CHECK:       <<This:l\d+>>  ParameterValue
+  /// CHECK:       <<Arg:l\d+>>   ParameterValue
+  /// CHECK:                      InstanceFieldSet [<<This>>,<<Arg>>] field_name:Main.field
+
+  /// CHECK-START-ARM: void Main.testSetField(java.lang.Object) disassembly (after)
+  /// CHECK-IF: os.environ.get('ART_HEAP_POISONING') == 'true'
+  ///      CHECK-IF: os.environ.get('ART_READ_BARRIER_TYPE') != 'TABLELOOKUP'
+  ///           CHECK:      <<This:l\d+>>  ParameterValue
+  ///           CHECK:      <<Arg:l\d+>>   ParameterValue
+  ///           CHECK:                     InstanceFieldSet [<<This>>,<<Arg>>] field_name:Main.field
+  ///           CHECK-NEXT:                mov <<Temp:r([0-8]|10|11)>>, r2
+  ///           CHECK-NEXT:                rsbs <<Temp>>, #0
+  ///           CHECK-NEXT:                str <<Temp>>, [r1, #8]
+  ///           CHECK:                     ReturnVoid
+  ///           CHECK-NEXT:                bx lr
+  ///      CHECK-FI:
+  /// CHECK-ELSE:
+  ///      CHECK-NOT: rsbs {{r\d+}}, #0
+  /// CHECK-FI:
+
+  /// CHECK-START-ARM64: void Main.testSetField(java.lang.Object) disassembly (after)
+  /// CHECK-IF: os.environ.get('ART_HEAP_POISONING') == 'true'
+  ///      CHECK-IF: os.environ.get('ART_READ_BARRIER_TYPE') != 'TABLELOOKUP'
+  ///           CHECK:      <<This:l\d+>>  ParameterValue
+  ///           CHECK:      <<Arg:l\d+>>   ParameterValue
+  ///           CHECK:                     InstanceFieldSet [<<This>>,<<Arg>>] field_name:Main.field
+  ///           CHECK-NEXT:                mov <<Temp:w1[67]>>, w2
+  ///           CHECK-NEXT:                neg <<Temp>>, <<Temp>>
+  ///           CHECK-NEXT:                str <<Temp>>, [x1, #8]
+  ///           CHECK:                     ReturnVoid
+  ///           CHECK-NEXT:                ret
+  ///      CHECK-FI:
+  /// CHECK-ELSE:
+  ///      CHECK-NOT: neg {{w\d+}}, {{w\d+}}
+  /// CHECK-FI:
+
+  /// CHECK-START-X86: void Main.testSetField(java.lang.Object) disassembly (after)
+  /// CHECK-IF: os.environ.get('ART_HEAP_POISONING') == 'true'
+  ///      CHECK-IF: os.environ.get('ART_READ_BARRIER_TYPE') != 'TABLELOOKUP'
+  ///           CHECK:      <<This:l\d+>>  ParameterValue
+  ///           CHECK:      <<Arg:l\d+>>   ParameterValue
+  ///           CHECK:                     ParallelMove
+  ///           CHECK-NEXT:                mov eax, ecx
+  ///           CHECK:                     InstanceFieldSet [<<This>>,<<Arg>>] field_name:Main.field
+  ///           CHECK-NEXT:                mov <<Temp:e([acdb]x|bp|si|di)>>, edx
+  ///           CHECK-NEXT:                neg <<Temp>>
+  ///           CHECK-NEXT:                mov [eax + 8], <<Temp>>
+  ///           CHECK:                     ReturnVoid
+  ///           CHECK-NEXT:                ret
+  ///      CHECK-FI:
+  /// CHECK-ELSE:
+  ///      CHECK-NOT: neg {{[a-z]+}}
+  /// CHECK-FI:
+
+  /// CHECK-START-X86_64: void Main.testSetField(java.lang.Object) disassembly (after)
+  /// CHECK-IF: os.environ.get('ART_HEAP_POISONING') == 'true'
+  ///      CHECK-IF: os.environ.get('ART_READ_BARRIER_TYPE') != 'TABLELOOKUP'
+  ///           CHECK:      <<This:l\d+>>  ParameterValue
+  ///           CHECK:      <<Arg:l\d+>>   ParameterValue
+  ///           CHECK:                     InstanceFieldSet [<<This>>,<<Arg>>] field_name:Main.field
+  ///           CHECK-NEXT:                mov <<Temp:e([acdb]x|bp|si|di)>>, edx
+  ///           CHECK-NEXT:                neg <<Temp>>
+  ///           CHECK-NEXT:                mov [rsi + 8], <<Temp>>
+  ///           CHECK:                     ReturnVoid
+  ///           CHECK-NEXT:                ret
+  ///      CHECK-FI:
+  /// CHECK-ELSE:
+  ///      CHECK-NOT: neg {{[a-z]+}}
+  /// CHECK-FI:
+
+  void testSetField(Object o) {
+    field = o;
+  }
+
+  public static void main(String[] args) {
+    Main m = new Main();
+    Object o = m.testGetField();
+    m.testSetField(o);
+    System.out.println("passed");
+  }
+}
diff --git a/test/2232-write-metrics-to-log/Android.bp b/test/2232-write-metrics-to-log/Android.bp
new file mode 100644
index 0000000..a64567e
--- /dev/null
+++ b/test/2232-write-metrics-to-log/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `2232-write-metrics-to-log`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-2232-write-metrics-to-log",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-2232-write-metrics-to-log-expected-stdout",
+        ":art-run-test-2232-write-metrics-to-log-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-2232-write-metrics-to-log-expected-stdout",
+    out: ["art-run-test-2232-write-metrics-to-log-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-2232-write-metrics-to-log-expected-stderr",
+    out: ["art-run-test-2232-write-metrics-to-log-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2232-write-metrics-to-log/check b/test/2232-write-metrics-to-log/check
new file mode 100755
index 0000000..d12e8b1
--- /dev/null
+++ b/test/2232-write-metrics-to-log/check
@@ -0,0 +1,34 @@
+#!/bin/bash
+#
+# Copyright (C) 2020 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.
+
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
+# Check that one of the metrics appears in stderr.
+grep 'ClassVerificationTotalTime' "$4" >/dev/null
+MSG_FOUND=$?
+
+if [[ $MSG_FOUND -ne 0 ]] ; then
+  # Print out the log and return with error.
+  cat "$4"
+  exit 1
+fi
+
+# Success.
+exit 0
diff --git a/test/202-thread-oome/expected.txt b/test/2232-write-metrics-to-log/expected-stderr.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/2232-write-metrics-to-log/expected-stderr.txt
diff --git a/test/202-thread-oome/expected.txt b/test/2232-write-metrics-to-log/expected-stdout.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/2232-write-metrics-to-log/expected-stdout.txt
diff --git a/test/2232-write-metrics-to-log/info.txt b/test/2232-write-metrics-to-log/info.txt
new file mode 100644
index 0000000..05bc66e
--- /dev/null
+++ b/test/2232-write-metrics-to-log/info.txt
@@ -0,0 +1 @@
+Checks that metrics can be written to logcat.
diff --git a/test/2232-write-metrics-to-log/run b/test/2232-write-metrics-to-log/run
new file mode 100755
index 0000000..d34ec6c
--- /dev/null
+++ b/test/2232-write-metrics-to-log/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2020 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.
+
+export ANDROID_LOG_TAGS="*:i"
+exec ${RUN} $@ --external-log-tags --runtime-option -Xmetrics-write-to-logcat:true --runtime-option -Xmetrics-reporting-mods:100
diff --git a/test/2232-write-metrics-to-log/src/Main.java b/test/2232-write-metrics-to-log/src/Main.java
new file mode 100644
index 0000000..0426192
--- /dev/null
+++ b/test/2232-write-metrics-to-log/src/Main.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 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) {
+  }
+}
diff --git a/test/300-package-override/Android.bp b/test/300-package-override/Android.bp
new file mode 100644
index 0000000..cbe94c4
--- /dev/null
+++ b/test/300-package-override/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `300-package-override`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-300-package-override",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-300-package-override-expected-stdout",
+        ":art-run-test-300-package-override-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-300-package-override-expected-stdout",
+    out: ["art-run-test-300-package-override-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-300-package-override-expected-stderr",
+    out: ["art-run-test-300-package-override-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/082-inline-execute/expected.txt b/test/300-package-override/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/300-package-override/expected-stderr.txt
diff --git a/test/300-package-override/expected.txt b/test/300-package-override/expected-stdout.txt
similarity index 100%
rename from test/300-package-override/expected.txt
rename to test/300-package-override/expected-stdout.txt
diff --git a/test/301-abstract-protected/Android.bp b/test/301-abstract-protected/Android.bp
new file mode 100644
index 0000000..02aae2d
--- /dev/null
+++ b/test/301-abstract-protected/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `301-abstract-protected`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-301-abstract-protected",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-301-abstract-protected-expected-stdout",
+        ":art-run-test-301-abstract-protected-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-301-abstract-protected-expected-stdout",
+    out: ["art-run-test-301-abstract-protected-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-301-abstract-protected-expected-stderr",
+    out: ["art-run-test-301-abstract-protected-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/168-vmstack-annotated/expected.txt b/test/301-abstract-protected/expected-stderr.txt
similarity index 100%
copy from test/168-vmstack-annotated/expected.txt
copy to test/301-abstract-protected/expected-stderr.txt
diff --git a/test/301-abstract-protected/expected.txt b/test/301-abstract-protected/expected-stdout.txt
similarity index 100%
rename from test/301-abstract-protected/expected.txt
rename to test/301-abstract-protected/expected-stdout.txt
diff --git a/test/302-float-conversion/Android.bp b/test/302-float-conversion/Android.bp
new file mode 100644
index 0000000..ae5c76e
--- /dev/null
+++ b/test/302-float-conversion/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `302-float-conversion`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-302-float-conversion",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-302-float-conversion-expected-stdout",
+        ":art-run-test-302-float-conversion-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-302-float-conversion-expected-stdout",
+    out: ["art-run-test-302-float-conversion-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-302-float-conversion-expected-stderr",
+    out: ["art-run-test-302-float-conversion-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/422-type-conversion/expected.txt b/test/302-float-conversion/expected-stderr.txt
similarity index 100%
copy from test/422-type-conversion/expected.txt
copy to test/302-float-conversion/expected-stderr.txt
diff --git a/test/302-float-conversion/expected.txt b/test/302-float-conversion/expected-stdout.txt
similarity index 100%
rename from test/302-float-conversion/expected.txt
rename to test/302-float-conversion/expected-stdout.txt
diff --git a/test/607-daemon-stress/expected.txt b/test/303-verification-stress/expected-stderr.txt
similarity index 100%
copy from test/607-daemon-stress/expected.txt
copy to test/303-verification-stress/expected-stderr.txt
diff --git a/test/303-verification-stress/expected.txt b/test/303-verification-stress/expected-stdout.txt
similarity index 100%
rename from test/303-verification-stress/expected.txt
rename to test/303-verification-stress/expected-stdout.txt
diff --git a/test/304-method-tracing/Android.bp b/test/304-method-tracing/Android.bp
new file mode 100644
index 0000000..e627603
--- /dev/null
+++ b/test/304-method-tracing/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `304-method-tracing`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-304-method-tracing",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-304-method-tracing-expected-stdout",
+        ":art-run-test-304-method-tracing-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-304-method-tracing-expected-stdout",
+    out: ["art-run-test-304-method-tracing-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-304-method-tracing-expected-stderr",
+    out: ["art-run-test-304-method-tracing-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/304-method-tracing/expected.txt b/test/304-method-tracing/expected-stderr.txt
similarity index 100%
rename from test/304-method-tracing/expected.txt
rename to test/304-method-tracing/expected-stderr.txt
diff --git a/test/304-method-tracing/expected.txt b/test/304-method-tracing/expected-stdout.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/304-method-tracing/expected-stdout.txt
diff --git a/test/305-other-fault-handler/Android.bp b/test/305-other-fault-handler/Android.bp
new file mode 100644
index 0000000..73e7455
--- /dev/null
+++ b/test/305-other-fault-handler/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `305-other-fault-handler`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-305-other-fault-handler",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-305-other-fault-handler-expected-stdout",
+        ":art-run-test-305-other-fault-handler-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-305-other-fault-handler-expected-stdout",
+    out: ["art-run-test-305-other-fault-handler-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-305-other-fault-handler-expected-stderr",
+    out: ["art-run-test-305-other-fault-handler-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/706-checker-scheduler/expected.txt b/test/305-other-fault-handler/expected-stderr.txt
similarity index 100%
copy from test/706-checker-scheduler/expected.txt
copy to test/305-other-fault-handler/expected-stderr.txt
diff --git a/test/305-other-fault-handler/expected.txt b/test/305-other-fault-handler/expected-stdout.txt
similarity index 100%
rename from test/305-other-fault-handler/expected.txt
rename to test/305-other-fault-handler/expected-stdout.txt
diff --git a/test/001-Main/expected.txt b/test/370-dex-v37/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/370-dex-v37/expected-stderr.txt
diff --git a/test/370-dex-v37/expected.txt b/test/370-dex-v37/expected-stdout.txt
similarity index 100%
rename from test/370-dex-v37/expected.txt
rename to test/370-dex-v37/expected-stdout.txt
diff --git a/test/401-optimizing-compiler/Android.bp b/test/401-optimizing-compiler/Android.bp
new file mode 100644
index 0000000..3335fca
--- /dev/null
+++ b/test/401-optimizing-compiler/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `401-optimizing-compiler`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-401-optimizing-compiler",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-401-optimizing-compiler-expected-stdout",
+        ":art-run-test-401-optimizing-compiler-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-401-optimizing-compiler-expected-stdout",
+    out: ["art-run-test-401-optimizing-compiler-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-401-optimizing-compiler-expected-stderr",
+    out: ["art-run-test-401-optimizing-compiler-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/419-long-parameter/expected.txt b/test/401-optimizing-compiler/expected-stderr.txt
similarity index 100%
copy from test/419-long-parameter/expected.txt
copy to test/401-optimizing-compiler/expected-stderr.txt
diff --git a/test/401-optimizing-compiler/expected.txt b/test/401-optimizing-compiler/expected-stdout.txt
similarity index 100%
rename from test/401-optimizing-compiler/expected.txt
rename to test/401-optimizing-compiler/expected-stdout.txt
diff --git a/test/402-optimizing-control-flow/Android.bp b/test/402-optimizing-control-flow/Android.bp
new file mode 100644
index 0000000..c2db8c6
--- /dev/null
+++ b/test/402-optimizing-control-flow/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `402-optimizing-control-flow`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-402-optimizing-control-flow",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-402-optimizing-control-flow-expected-stdout",
+        ":art-run-test-402-optimizing-control-flow-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-402-optimizing-control-flow-expected-stdout",
+    out: ["art-run-test-402-optimizing-control-flow-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-402-optimizing-control-flow-expected-stderr",
+    out: ["art-run-test-402-optimizing-control-flow-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/402-optimizing-control-flow/expected.txt b/test/402-optimizing-control-flow/expected-stderr.txt
similarity index 100%
rename from test/402-optimizing-control-flow/expected.txt
rename to test/402-optimizing-control-flow/expected-stderr.txt
diff --git a/test/402-optimizing-control-flow/expected.txt b/test/402-optimizing-control-flow/expected-stdout.txt
similarity index 100%
copy from test/402-optimizing-control-flow/expected.txt
copy to test/402-optimizing-control-flow/expected-stdout.txt
diff --git a/test/403-optimizing-long/Android.bp b/test/403-optimizing-long/Android.bp
new file mode 100644
index 0000000..fda0fbb
--- /dev/null
+++ b/test/403-optimizing-long/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `403-optimizing-long`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-403-optimizing-long",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-403-optimizing-long-expected-stdout",
+        ":art-run-test-403-optimizing-long-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-403-optimizing-long-expected-stdout",
+    out: ["art-run-test-403-optimizing-long-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-403-optimizing-long-expected-stderr",
+    out: ["art-run-test-403-optimizing-long-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/408-move-bug/expected.txt b/test/403-optimizing-long/expected-stderr.txt
similarity index 100%
copy from test/408-move-bug/expected.txt
copy to test/403-optimizing-long/expected-stderr.txt
diff --git a/test/403-optimizing-long/expected.txt b/test/403-optimizing-long/expected-stdout.txt
similarity index 100%
rename from test/403-optimizing-long/expected.txt
rename to test/403-optimizing-long/expected-stdout.txt
diff --git a/test/404-optimizing-allocator/Android.bp b/test/404-optimizing-allocator/Android.bp
new file mode 100644
index 0000000..0cbef46
--- /dev/null
+++ b/test/404-optimizing-allocator/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `404-optimizing-allocator`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-404-optimizing-allocator",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-404-optimizing-allocator-expected-stdout",
+        ":art-run-test-404-optimizing-allocator-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-404-optimizing-allocator-expected-stdout",
+    out: ["art-run-test-404-optimizing-allocator-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-404-optimizing-allocator-expected-stderr",
+    out: ["art-run-test-404-optimizing-allocator-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/404-optimizing-allocator/expected.txt b/test/404-optimizing-allocator/expected-stderr.txt
similarity index 100%
rename from test/404-optimizing-allocator/expected.txt
rename to test/404-optimizing-allocator/expected-stderr.txt
diff --git a/test/404-optimizing-allocator/expected.txt b/test/404-optimizing-allocator/expected-stdout.txt
similarity index 100%
copy from test/404-optimizing-allocator/expected.txt
copy to test/404-optimizing-allocator/expected-stdout.txt
diff --git a/test/405-optimizing-long-allocator/Android.bp b/test/405-optimizing-long-allocator/Android.bp
new file mode 100644
index 0000000..50445c9
--- /dev/null
+++ b/test/405-optimizing-long-allocator/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `405-optimizing-long-allocator`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-405-optimizing-long-allocator",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-405-optimizing-long-allocator-expected-stdout",
+        ":art-run-test-405-optimizing-long-allocator-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-405-optimizing-long-allocator-expected-stdout",
+    out: ["art-run-test-405-optimizing-long-allocator-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-405-optimizing-long-allocator-expected-stderr",
+    out: ["art-run-test-405-optimizing-long-allocator-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/405-optimizing-long-allocator/expected.txt b/test/405-optimizing-long-allocator/expected-stderr.txt
similarity index 100%
rename from test/405-optimizing-long-allocator/expected.txt
rename to test/405-optimizing-long-allocator/expected-stderr.txt
diff --git a/test/405-optimizing-long-allocator/expected.txt b/test/405-optimizing-long-allocator/expected-stdout.txt
similarity index 100%
copy from test/405-optimizing-long-allocator/expected.txt
copy to test/405-optimizing-long-allocator/expected-stdout.txt
diff --git a/test/406-fields/Android.bp b/test/406-fields/Android.bp
new file mode 100644
index 0000000..8e6b3d1
--- /dev/null
+++ b/test/406-fields/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `406-fields`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-406-fields",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-406-fields-expected-stdout",
+        ":art-run-test-406-fields-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-406-fields-expected-stdout",
+    out: ["art-run-test-406-fields-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-406-fields-expected-stderr",
+    out: ["art-run-test-406-fields-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/406-fields/expected.txt b/test/406-fields/expected-stderr.txt
similarity index 100%
rename from test/406-fields/expected.txt
rename to test/406-fields/expected-stderr.txt
diff --git a/test/406-fields/expected.txt b/test/406-fields/expected-stdout.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/406-fields/expected-stdout.txt
diff --git a/test/407-arrays/Android.bp b/test/407-arrays/Android.bp
new file mode 100644
index 0000000..20be07d
--- /dev/null
+++ b/test/407-arrays/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `407-arrays`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-407-arrays",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-407-arrays-expected-stdout",
+        ":art-run-test-407-arrays-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-407-arrays-expected-stdout",
+    out: ["art-run-test-407-arrays-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-407-arrays-expected-stderr",
+    out: ["art-run-test-407-arrays-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/407-arrays/expected.txt b/test/407-arrays/expected-stderr.txt
similarity index 100%
rename from test/407-arrays/expected.txt
rename to test/407-arrays/expected-stderr.txt
diff --git a/test/407-arrays/expected.txt b/test/407-arrays/expected-stdout.txt
similarity index 100%
copy from test/407-arrays/expected.txt
copy to test/407-arrays/expected-stdout.txt
diff --git a/test/408-move-bug/Android.bp b/test/408-move-bug/Android.bp
new file mode 100644
index 0000000..828f5c7
--- /dev/null
+++ b/test/408-move-bug/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `408-move-bug`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-408-move-bug",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-408-move-bug-expected-stdout",
+        ":art-run-test-408-move-bug-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-408-move-bug-expected-stdout",
+    out: ["art-run-test-408-move-bug-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-408-move-bug-expected-stderr",
+    out: ["art-run-test-408-move-bug-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/408-move-bug/expected.txt b/test/408-move-bug/expected-stderr.txt
similarity index 100%
rename from test/408-move-bug/expected.txt
rename to test/408-move-bug/expected-stderr.txt
diff --git a/test/408-move-bug/expected.txt b/test/408-move-bug/expected-stdout.txt
similarity index 100%
copy from test/408-move-bug/expected.txt
copy to test/408-move-bug/expected-stdout.txt
diff --git a/test/409-materialized-condition/Android.bp b/test/409-materialized-condition/Android.bp
new file mode 100644
index 0000000..2aabaf2
--- /dev/null
+++ b/test/409-materialized-condition/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `409-materialized-condition`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-409-materialized-condition",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-409-materialized-condition-expected-stdout",
+        ":art-run-test-409-materialized-condition-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-409-materialized-condition-expected-stdout",
+    out: ["art-run-test-409-materialized-condition-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-409-materialized-condition-expected-stderr",
+    out: ["art-run-test-409-materialized-condition-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/684-select-condition/expected.txt b/test/409-materialized-condition/expected-stderr.txt
similarity index 100%
copy from test/684-select-condition/expected.txt
copy to test/409-materialized-condition/expected-stderr.txt
diff --git a/test/409-materialized-condition/expected.txt b/test/409-materialized-condition/expected-stdout.txt
similarity index 100%
rename from test/409-materialized-condition/expected.txt
rename to test/409-materialized-condition/expected-stdout.txt
diff --git a/test/410-floats/Android.bp b/test/410-floats/Android.bp
new file mode 100644
index 0000000..4fa1ad4
--- /dev/null
+++ b/test/410-floats/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `410-floats`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-410-floats",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-410-floats-expected-stdout",
+        ":art-run-test-410-floats-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-410-floats-expected-stdout",
+    out: ["art-run-test-410-floats-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-410-floats-expected-stderr",
+    out: ["art-run-test-410-floats-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/410-floats/expected.txt b/test/410-floats/expected-stderr.txt
similarity index 100%
rename from test/410-floats/expected.txt
rename to test/410-floats/expected-stderr.txt
diff --git a/test/410-floats/expected.txt b/test/410-floats/expected-stdout.txt
similarity index 100%
copy from test/410-floats/expected.txt
copy to test/410-floats/expected-stdout.txt
diff --git a/test/411-checker-hdiv-hrem-const/Android.bp b/test/411-checker-hdiv-hrem-const/Android.bp
new file mode 100644
index 0000000..e8932a6
--- /dev/null
+++ b/test/411-checker-hdiv-hrem-const/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `411-checker-hdiv-hrem-const`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-411-checker-hdiv-hrem-const",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-411-checker-hdiv-hrem-const-expected-stdout",
+        ":art-run-test-411-checker-hdiv-hrem-const-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-411-checker-hdiv-hrem-const-expected-stdout",
+    out: ["art-run-test-411-checker-hdiv-hrem-const-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-411-checker-hdiv-hrem-const-expected-stderr",
+    out: ["art-run-test-411-checker-hdiv-hrem-const-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/411-checker-hdiv-hrem-pow2/expected.txt b/test/411-checker-hdiv-hrem-const/expected-stderr.txt
similarity index 100%
copy from test/411-checker-hdiv-hrem-pow2/expected.txt
copy to test/411-checker-hdiv-hrem-const/expected-stderr.txt
diff --git a/test/411-checker-hdiv-hrem-pow2/expected.txt b/test/411-checker-hdiv-hrem-const/expected-stdout.txt
similarity index 100%
copy from test/411-checker-hdiv-hrem-pow2/expected.txt
copy to test/411-checker-hdiv-hrem-const/expected-stdout.txt
diff --git a/test/411-checker-hdiv-hrem-const/info.txt b/test/411-checker-hdiv-hrem-const/info.txt
new file mode 100644
index 0000000..ce88f44
--- /dev/null
+++ b/test/411-checker-hdiv-hrem-const/info.txt
@@ -0,0 +1,2 @@
+Checker test for optimizations of integer division and remainder instructions when
+the denominator is a constant, not power of 2.
diff --git a/test/411-checker-hdiv-hrem-const/src/DivTest.java b/test/411-checker-hdiv-hrem-const/src/DivTest.java
new file mode 100644
index 0000000..60230c4
--- /dev/null
+++ b/test/411-checker-hdiv-hrem-const/src/DivTest.java
@@ -0,0 +1,972 @@
+/*
+ * Copyright (C) 2020 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 DivTest {
+  private static void expectEquals(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  private static void expectEquals(long expected, long result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  private static void expectEquals(String expected, String result) {
+    if (!expected.equals(result)) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  public static void main() {
+    divInt();
+    divLong();
+  }
+
+  private static void divInt() {
+    expectEquals(0, $noinline$IntDivBy18(0));
+    expectEquals(0, $noinline$IntDivBy18(1));
+    expectEquals(0, $noinline$IntDivBy18(-1));
+    expectEquals(1, $noinline$IntDivBy18(18));
+    expectEquals(-1, $noinline$IntDivBy18(-18));
+    expectEquals(3, $noinline$IntDivBy18(65));
+    expectEquals(-3, $noinline$IntDivBy18(-65));
+
+    expectEquals(0, $noinline$IntALenDivBy18(new int[0]));
+    expectEquals(0, $noinline$IntALenDivBy18(new int[1]));
+    expectEquals(1, $noinline$IntALenDivBy18(new int[18]));
+    expectEquals(3, $noinline$IntALenDivBy18(new int[65]));
+
+    expectEquals(0, $noinline$IntDivByMinus18(0));
+    expectEquals(0, $noinline$IntDivByMinus18(1));
+    expectEquals(0, $noinline$IntDivByMinus18(-1));
+    expectEquals(-1, $noinline$IntDivByMinus18(18));
+    expectEquals(1, $noinline$IntDivByMinus18(-18));
+    expectEquals(-3, $noinline$IntDivByMinus18(65));
+    expectEquals(3, $noinline$IntDivByMinus18(-65));
+
+    expectEquals(0, $noinline$IntDivBy7(0));
+    expectEquals(0, $noinline$IntDivBy7(1));
+    expectEquals(0, $noinline$IntDivBy7(-1));
+    expectEquals(1, $noinline$IntDivBy7(7));
+    expectEquals(-1, $noinline$IntDivBy7(-7));
+    expectEquals(3, $noinline$IntDivBy7(22));
+    expectEquals(-3, $noinline$IntDivBy7(-22));
+
+    expectEquals(0, $noinline$IntALenDivBy7(new int[0]));
+    expectEquals(0, $noinline$IntALenDivBy7(new int[1]));
+    expectEquals(1, $noinline$IntALenDivBy7(new int[7]));
+    expectEquals(3, $noinline$IntALenDivBy7(new int[22]));
+
+    expectEquals(0, $noinline$IntDivByMinus7(0));
+    expectEquals(0, $noinline$IntDivByMinus7(1));
+    expectEquals(0, $noinline$IntDivByMinus7(-1));
+    expectEquals(-1, $noinline$IntDivByMinus7(7));
+    expectEquals(1, $noinline$IntDivByMinus7(-7));
+    expectEquals(-3, $noinline$IntDivByMinus7(22));
+    expectEquals(3, $noinline$IntDivByMinus7(-22));
+
+    expectEquals(0, $noinline$IntDivBy6(0));
+    expectEquals(0, $noinline$IntDivBy6(1));
+    expectEquals(0, $noinline$IntDivBy6(-1));
+    expectEquals(1, $noinline$IntDivBy6(6));
+    expectEquals(-1, $noinline$IntDivBy6(-6));
+    expectEquals(3, $noinline$IntDivBy6(19));
+    expectEquals(-3, $noinline$IntDivBy6(-19));
+
+    expectEquals(0, $noinline$IntALenDivBy6(new int[0]));
+    expectEquals(0, $noinline$IntALenDivBy6(new int[1]));
+    expectEquals(1, $noinline$IntALenDivBy6(new int[6]));
+    expectEquals(3, $noinline$IntALenDivBy6(new int[19]));
+
+    expectEquals(0, $noinline$IntDivByMinus6(0));
+    expectEquals(0, $noinline$IntDivByMinus6(1));
+    expectEquals(0, $noinline$IntDivByMinus6(-1));
+    expectEquals(-1, $noinline$IntDivByMinus6(6));
+    expectEquals(1, $noinline$IntDivByMinus6(-6));
+    expectEquals(-3, $noinline$IntDivByMinus6(19));
+    expectEquals(3, $noinline$IntDivByMinus6(-19));
+
+    expectEquals(2, $noinline$UnsignedIntDiv01(12));
+    expectEquals(2, $noinline$UnsignedIntDiv02(12));
+    expectEquals(2, $noinline$UnsignedIntDiv03(12));
+    expectEquals(2, $noinline$UnsignedIntDiv04(12));
+    expectEquals("01", $noinline$UnsignedIntDiv05(10));
+    expectEquals("321", $noinline$UnsignedIntDiv05(123));
+    expectEquals(1, $noinline$UnsignedIntDiv06(101));
+    expectEquals(1, $noinline$UnsignedIntDiv07(10));
+    expectEquals(1, $noinline$UnsignedIntDiv07(100));
+    expectEquals(10, $noinline$UnsignedIntDiv08(100));
+    expectEquals(11, $noinline$UnsignedIntDiv08(101));
+
+    expectEquals(-2, $noinline$SignedIntDiv01(-12));
+    expectEquals(-2, $noinline$SignedIntDiv02(-12));
+    expectEquals(2, $noinline$SignedIntDiv03(-12));
+    expectEquals(2, $noinline$SignedIntDiv04(-12, true));
+    expectEquals(-2, $noinline$SignedIntDiv05(-12, 0,-13));
+    expectEquals(-2, $noinline$SignedIntDiv06(-12));
+  }
+
+  // A test case to check that 'lsr' and 'asr' are combined into one 'asr'.
+  // For divisor 18 seen in an MP3 decoding workload there is no need
+  // to correct the result of get_high(dividend * magic). So there are no
+  // instructions between 'lsr' and 'asr'. In such a case they can be combined
+  // into one 'asr'.
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$IntDivBy18(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$IntDivBy18(int v) {
+    int r = v / 18;
+    return r;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$IntALenDivBy18(int[]) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            lsr{{s?}} r{{\d+}}, r{{\d+}}, #2
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$IntALenDivBy18(int[]) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NOT:             add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$IntALenDivBy18(int[] arr) {
+    int r = arr.length / 18;
+    return r;
+  }
+
+  // A test case to check that 'lsr' and 'asr' are combined into one 'asr'.
+  // Divisor -18 has the same property as divisor 18: no need to correct the
+  // result of get_high(dividend * magic). So there are no
+  // instructions between 'lsr' and 'asr'. In such a case they can be combined
+  // into one 'asr'.
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$IntDivByMinus18(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$IntDivByMinus18(int v) {
+    int r = v / -18;
+    return r;
+  }
+
+  // A test case to check that 'lsr' and 'add' are combined into one 'adds'.
+  // For divisor 7 seen in the core library the result of get_high(dividend * magic)
+  // must be corrected by the 'add' instruction.
+  //
+  // The test case also checks 'add' and 'add_shift' are optimized into 'adds' and 'cinc'.
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$IntDivBy7(int) disassembly (after)
+  /// CHECK:                 adds x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #32
+  /// CHECK-NEXT:            asr  x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            cinc w{{\d+}}, w{{\d+}}, mi
+  private static int $noinline$IntDivBy7(int v) {
+    int r = v / 7;
+    return r;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$IntALenDivBy7(int[]) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            add{{s?}} r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            lsr{{s?}} r{{\d+}}, r{{\d+}}, #2
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$IntALenDivBy7(int[]) disassembly (after)
+  /// CHECK:                 adds x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #32
+  /// CHECK-NEXT:            lsr  x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NOT:             cinc w{{\d+}}, w{{\d+}}, mi
+  private static int $noinline$IntALenDivBy7(int[] arr) {
+    int r = arr.length / 7;
+    return r;
+  }
+
+  // A test case to check that 'lsr' and 'add' are combined into one 'adds'.
+  // Divisor -7 has the same property as divisor 7: the result of get_high(dividend * magic)
+  // must be corrected. In this case it is a 'sub' instruction.
+  //
+  // The test case also checks 'sub' and 'add_shift' are optimized into 'subs' and 'cinc'.
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$IntDivByMinus7(int) disassembly (after)
+  /// CHECK:                 subs x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #32
+  /// CHECK-NEXT:            asr  x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            cinc w{{\d+}}, w{{\d+}}, mi
+  private static int $noinline$IntDivByMinus7(int v) {
+    int r = v / -7;
+    return r;
+  }
+
+  // A test case to check that 'asr' is used to get the high 32 bits of the result of
+  // 'dividend * magic'.
+  // For divisor 6 seen in the core library there is no need to correct the result of
+  // get_high(dividend * magic). Also there is no 'asr' before the final 'add' instruction
+  // which uses only the high 32 bits of the result. In such a case 'asr' getting the high
+  // 32 bits can be used as well.
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$IntDivBy6(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$IntDivBy6(int v) {
+    int r = v / 6;
+    return r;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$IntALenDivBy6(int[]) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$IntALenDivBy6(int[]) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NOT:             add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$IntALenDivBy6(int[] arr) {
+    int r = arr.length / 6;
+    return r;
+  }
+
+  // A test case to check that 'asr' is used to get the high 32 bits of the result of
+  // 'dividend * magic'.
+  // Divisor -6 has the same property as divisor 6: no need to correct the result of
+  // get_high(dividend * magic) and no 'asr' before the final 'add' instruction
+  // which uses only the high 32 bits of the result. In such a case 'asr' getting the high
+  // 32 bits can be used as well.
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$IntDivByMinus6(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$IntDivByMinus6(int v) {
+    int r = v / -6;
+    return r;
+  }
+
+  private static int $noinline$Negate(int v) {
+    return -v;
+  }
+
+  private static int $noinline$Decrement(int v) {
+    return v - 1;
+  }
+
+  private static int $noinline$Increment(int v) {
+    return v + 1;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$UnsignedIntDiv01(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$UnsignedIntDiv01(int) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NOT:             add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$UnsignedIntDiv01(int v) {
+    int c = 0;
+    if (v > 0) {
+      c = v / 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$UnsignedIntDiv02(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$UnsignedIntDiv02(int) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NOT:             add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$UnsignedIntDiv02(int v) {
+    int c = 0;
+    if (0 < v) {
+      c = v / 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$UnsignedIntDiv03(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$UnsignedIntDiv03(int) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NOT:             add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$UnsignedIntDiv03(int v) {
+    int c = 0;
+    if (v >= 0) {
+      c = v / 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$UnsignedIntDiv04(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$UnsignedIntDiv04(int) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NOT:             add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$UnsignedIntDiv04(int v) {
+    int c = 0;
+    if (0 <= v) {
+      c = v / 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   java.lang.String DivTest.$noinline$UnsignedIntDiv05(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: java.lang.String DivTest.$noinline$UnsignedIntDiv05(int) disassembly (after)
+  /// CHECK:                 smull x{{\d+}}, w{{\d+}}, w{{\d+}}
+  /// CHECK:                 lsr   x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NOT:             add   w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static String $noinline$UnsignedIntDiv05(int v) {
+    String r = "";
+    while (v > 0) {
+      int d = v % 10;
+      r += (char)(d + '0');
+      v /= 10;
+    }
+    return r;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$UnsignedIntDiv06(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$UnsignedIntDiv06(int) disassembly (after)
+  /// CHECK:                 smull x{{\d+}}, w{{\d+}}, w{{\d+}}
+  /// CHECK:                 lsr   x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NOT:             add   w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$UnsignedIntDiv06(int v) {
+    int c = 0;
+    for(; v > 100; ++c) {
+      v /= 10;
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$UnsignedIntDiv07(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$UnsignedIntDiv07(int) disassembly (after)
+  /// CHECK:                 smull x{{\d+}}, w{{\d+}}, w{{\d+}}
+  /// CHECK:                 lsr   x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NOT:             add   w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$UnsignedIntDiv07(int v) {
+    while (v > 0 && (v % 10) == 0) {
+      v /= 10;
+    }
+    return v;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$UnsignedIntDiv08(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NOT:             sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$UnsignedIntDiv08(int) disassembly (after)
+  /// CHECK:                 smull x{{\d+}}, w{{\d+}}, w{{\d+}}
+  /// CHECK:                 lsr   x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NOT:             add   w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$UnsignedIntDiv08(int v) {
+    if (v < 10) {
+      v = $noinline$Negate(v); // This is to prevent from using Select.
+    } else {
+      v = (v % 10) + (v / 10);
+    }
+    return v;
+  }
+
+  // A test case to check that a correcting 'add' is generated for a negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$SignedIntDiv01(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$SignedIntDiv01(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntDiv01(int v) {
+    int c = 0;
+    if (v < 0) {
+      c = v / 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for a negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$SignedIntDiv02(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$SignedIntDiv02(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntDiv02(int v) {
+    int c = 0;
+    if (v <= 0) {
+      c = v / 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$SignedIntDiv03(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$SignedIntDiv03(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntDiv03(int v) {
+    boolean positive = (v > 0);
+    int c = v / 6;
+    if (!positive) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$SignedIntDiv04(int, boolean) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$SignedIntDiv04(int, boolean) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntDiv04(int v, boolean apply_div) {
+    int c = 0;
+    boolean positive = (v > 0);
+    if (apply_div) {
+      c = v / 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    if (!positive) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$SignedIntDiv05(int, int, int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$SignedIntDiv05(int, int, int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntDiv05(int v, int a, int b) {
+    int c = 0;
+
+    if (v < a)
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+
+    if (b < a)
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+
+    if (v > b) {
+      c = v / 6;
+    } else {
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+    }
+
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM:   int DivTest.$noinline$SignedIntDiv06(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  //
+  /// CHECK-START-ARM64: int DivTest.$noinline$SignedIntDiv06(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntDiv06(int v) {
+    int c = v / 6;
+
+    if (v > 0) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+
+    return c;
+  }
+
+  private static void divLong() {
+    expectEquals(0L, $noinline$LongDivBy18(0L));
+    expectEquals(0L, $noinline$LongDivBy18(1L));
+    expectEquals(0L, $noinline$LongDivBy18(-1L));
+    expectEquals(1L, $noinline$LongDivBy18(18L));
+    expectEquals(-1L, $noinline$LongDivBy18(-18L));
+    expectEquals(3L, $noinline$LongDivBy18(65L));
+    expectEquals(-3L, $noinline$LongDivBy18(-65L));
+
+    expectEquals(0L, $noinline$LongDivByMinus18(0L));
+    expectEquals(0L, $noinline$LongDivByMinus18(1L));
+    expectEquals(0L, $noinline$LongDivByMinus18(-1L));
+    expectEquals(-1L, $noinline$LongDivByMinus18(18L));
+    expectEquals(1L, $noinline$LongDivByMinus18(-18L));
+    expectEquals(-3L, $noinline$LongDivByMinus18(65L));
+    expectEquals(3L, $noinline$LongDivByMinus18(-65L));
+
+    expectEquals(0L, $noinline$LongDivBy7(0L));
+    expectEquals(0L, $noinline$LongDivBy7(1L));
+    expectEquals(0L, $noinline$LongDivBy7(-1L));
+    expectEquals(1L, $noinline$LongDivBy7(7L));
+    expectEquals(-1L, $noinline$LongDivBy7(-7L));
+    expectEquals(3L, $noinline$LongDivBy7(22L));
+    expectEquals(-3L, $noinline$LongDivBy7(-22L));
+
+    expectEquals(0L, $noinline$LongDivByMinus7(0L));
+    expectEquals(0L, $noinline$LongDivByMinus7(1L));
+    expectEquals(0L, $noinline$LongDivByMinus7(-1L));
+    expectEquals(-1L, $noinline$LongDivByMinus7(7L));
+    expectEquals(1L, $noinline$LongDivByMinus7(-7L));
+    expectEquals(-3L, $noinline$LongDivByMinus7(22L));
+    expectEquals(3L, $noinline$LongDivByMinus7(-22L));
+
+    expectEquals(0L, $noinline$LongDivBy6(0L));
+    expectEquals(0L, $noinline$LongDivBy6(1L));
+    expectEquals(0L, $noinline$LongDivBy6(-1L));
+    expectEquals(1L, $noinline$LongDivBy6(6L));
+    expectEquals(-1L, $noinline$LongDivBy6(-6L));
+    expectEquals(3L, $noinline$LongDivBy6(19L));
+    expectEquals(-3L, $noinline$LongDivBy6(-19L));
+
+    expectEquals(0L, $noinline$LongDivByMinus6(0L));
+    expectEquals(0L, $noinline$LongDivByMinus6(1L));
+    expectEquals(0L, $noinline$LongDivByMinus6(-1L));
+    expectEquals(-1L, $noinline$LongDivByMinus6(6L));
+    expectEquals(1L, $noinline$LongDivByMinus6(-6L));
+    expectEquals(-3L, $noinline$LongDivByMinus6(19L));
+    expectEquals(3L, $noinline$LongDivByMinus6(-19L));
+
+    expectEquals(0L, $noinline$LongDivBy100(0L));
+    expectEquals(0L, $noinline$LongDivBy100(1L));
+    expectEquals(0L, $noinline$LongDivBy100(-1L));
+    expectEquals(1L, $noinline$LongDivBy100(100L));
+    expectEquals(-1L, $noinline$LongDivBy100(-100L));
+    expectEquals(3L, $noinline$LongDivBy100(301L));
+    expectEquals(-3L, $noinline$LongDivBy100(-301L));
+
+    expectEquals(0L, $noinline$LongDivByMinus100(0L));
+    expectEquals(0L, $noinline$LongDivByMinus100(1L));
+    expectEquals(0L, $noinline$LongDivByMinus100(-1L));
+    expectEquals(-1L, $noinline$LongDivByMinus100(100L));
+    expectEquals(1L, $noinline$LongDivByMinus100(-100L));
+    expectEquals(-3L, $noinline$LongDivByMinus100(301L));
+    expectEquals(3L, $noinline$LongDivByMinus100(-301L));
+
+    expectEquals(2L, $noinline$UnsignedLongDiv01(12L));
+    expectEquals(2L, $noinline$UnsignedLongDiv02(12L));
+    expectEquals(2L, $noinline$UnsignedLongDiv03(12L));
+    expectEquals(2L, $noinline$UnsignedLongDiv04(12L));
+    expectEquals("01", $noinline$UnsignedLongDiv05(10L));
+    expectEquals("321", $noinline$UnsignedLongDiv05(123L));
+    expectEquals(1L, $noinline$UnsignedLongDiv06(101L));
+    expectEquals(1L, $noinline$UnsignedLongDiv07(10L));
+    expectEquals(1L, $noinline$UnsignedLongDiv07(100L));
+    expectEquals(10L, $noinline$UnsignedLongDiv08(100L));
+    expectEquals(11L, $noinline$UnsignedLongDiv08(101L));
+
+    expectEquals(-2L, $noinline$SignedLongDiv01(-12L));
+    expectEquals(-2L, $noinline$SignedLongDiv02(-12L));
+    expectEquals(2L, $noinline$SignedLongDiv03(-12L));
+    expectEquals(2L, $noinline$SignedLongDiv04(-12L, true));
+    expectEquals(-2L, $noinline$SignedLongDiv05(-12L, 0L,-13L));
+    expectEquals(-2L, $noinline$SignedLongDiv06(-12L));
+  }
+
+  // Test cases for Int64 HDiv/HRem to check that optimizations implemented for Int32 are not
+  // used for Int64. The same divisors 18, -18, 7, -7, 6 and -6 are used.
+
+  /// CHECK-START-ARM64: long DivTest.$noinline$LongDivBy18(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$LongDivBy18(long v) {
+    long r = v / 18L;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: long DivTest.$noinline$LongDivByMinus18(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$LongDivByMinus18(long v) {
+    long r = v / -18L;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: long DivTest.$noinline$LongDivBy7(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            asr x{{\d+}}, x{{\d+}}, #1
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$LongDivBy7(long v) {
+    long r = v / 7L;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: long DivTest.$noinline$LongDivByMinus7(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            asr x{{\d+}}, x{{\d+}}, #1
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$LongDivByMinus7(long v) {
+    long r = v / -7L;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: long DivTest.$noinline$LongDivBy6(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$LongDivBy6(long v) {
+    long r = v / 6L;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: long DivTest.$noinline$LongDivByMinus6(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$LongDivByMinus6(long v) {
+    long r = v / -6L;
+    return r;
+  }
+
+  // A test to check 'add' and 'add_shift' are optimized into 'adds' and 'cinc'.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$LongDivBy100(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            adds  x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            asr   x{{\d+}}, x{{\d+}}, #6
+  /// CHECK-NEXT:            cinc  x{{\d+}}, x{{\d+}}, mi
+  private static long $noinline$LongDivBy100(long v) {
+    long r = v / 100L;
+    return r;
+  }
+
+  // A test to check 'subs' and 'add_shift' are optimized into 'subs' and 'cinc'.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$LongDivByMinus100(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            subs  x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            asr   x{{\d+}}, x{{\d+}}, #6
+  /// CHECK-NEXT:            cinc  x{{\d+}}, x{{\d+}}, mi
+  private static long $noinline$LongDivByMinus100(long v) {
+    long r = v / -100L;
+    return r;
+  }
+
+  private static long $noinline$Negate(long v) {
+    return -v;
+  }
+
+  private static long $noinline$Decrement(long v) {
+    return v - 1;
+  }
+
+  private static long $noinline$Increment(long v) {
+    return v + 1;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$UnsignedLongDiv01(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NOT:             add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$UnsignedLongDiv01(long v) {
+    long c = 0;
+    if (v > 0) {
+      c = v / 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$UnsignedLongDiv02(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NOT:             add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$UnsignedLongDiv02(long v) {
+    long c = 0;
+    if (0 < v) {
+      c = v / 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$UnsignedLongDiv03(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NOT:             add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$UnsignedLongDiv03(long v) {
+    long c = 0;
+    if (v >= 0) {
+      c = v / 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$UnsignedLongDiv04(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NOT:             add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$UnsignedLongDiv04(long v) {
+    long c = 0;
+    if (0 <= v) {
+      c = v / 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: java.lang.String DivTest.$noinline$UnsignedLongDiv05(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            lsr   x{{\d+}}, x{{\d+}}, #2
+  /// CHECK-NOT:             add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static String $noinline$UnsignedLongDiv05(long v) {
+    String r = "";
+    while (v > 0) {
+      long d = v % 10;
+      r += (char)(d + '0');
+      v /= 10;
+    }
+    return r;
+  }
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: void DivTest.$noinline$UnsignedLongDiv05(java.lang.StringBuilder, long, long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            lsr   x{{\d+}}, x{{\d+}}, #2
+  /// CHECK-NOT:             add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static void $noinline$UnsignedLongDiv05(java.lang.StringBuilder sb, long w, long d) {
+    while (w > 0) {
+      sb.append((char)(d/w + '0'));
+      d = d % w;
+      w /= 10;
+    }
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$UnsignedLongDiv06(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NOT:             add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$UnsignedLongDiv06(long v) {
+    long c = 0;
+    for(; v > 100; ++c) {
+      v /= 10;
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$UnsignedLongDiv07(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NOT:             add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$UnsignedLongDiv07(long v) {
+    while (v > 0 && (v % 10) == 0) {
+      v /= 10;
+    }
+    return v;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$UnsignedLongDiv08(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NOT:             add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$UnsignedLongDiv08(long v) {
+    if (v < 10) {
+      v = $noinline$Negate(v); // This is to prevent from using Select.
+    } else {
+      v = (v % 10) + (v / 10);
+    }
+    return v;
+  }
+
+  // A test case to check that a correcting 'add' is generated for a negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$SignedLongDiv01(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$SignedLongDiv01(long v) {
+    long c = 0;
+    if (v < 0) {
+      c = v / 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for a negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$SignedLongDiv02(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$SignedLongDiv02(long v) {
+    long c = 0;
+    if (v <= 0) {
+      c = v / 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$SignedLongDiv03(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$SignedLongDiv03(long v) {
+    boolean positive = (v > 0);
+    long c = v / 6;
+    if (!positive) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$SignedLongDiv04(long, boolean) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$SignedLongDiv04(long v, boolean apply_div) {
+    long c = 0;
+    boolean positive = (v > 0);
+    if (apply_div) {
+      c = v / 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    if (!positive) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$SignedLongDiv05(long, long, long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$SignedLongDiv05(long v, long a, long b) {
+    long c = 0;
+
+    if (v < a)
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+
+    if (b < a)
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+
+    if (v > b) {
+      c = v / 6;
+    } else {
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+    }
+
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM64: long DivTest.$noinline$SignedLongDiv06(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  private static long $noinline$SignedLongDiv06(long v) {
+    long c = v / 6;
+
+    if (v > 0) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+
+    return c;
+  }
+}
diff --git a/test/411-checker-hdiv-hrem-const/src/Main.java b/test/411-checker-hdiv-hrem-const/src/Main.java
new file mode 100644
index 0000000..4b34bf1
--- /dev/null
+++ b/test/411-checker-hdiv-hrem-const/src/Main.java
@@ -0,0 +1,22 @@
+/*
+ * 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[]) {
+        DivTest.main();
+        RemTest.main();
+    }
+}
diff --git a/test/411-checker-hdiv-hrem-const/src/RemTest.java b/test/411-checker-hdiv-hrem-const/src/RemTest.java
new file mode 100644
index 0000000..f7117ec
--- /dev/null
+++ b/test/411-checker-hdiv-hrem-const/src/RemTest.java
@@ -0,0 +1,948 @@
+/*
+ * Copyright (C) 2020 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 RemTest {
+  private static void expectEquals(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  private static void expectEquals(long expected, long result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  public static void main() {
+    remInt();
+    remLong();
+  }
+
+  private static void remInt() {
+    expectEquals(0, $noinline$IntRemBy18(0));
+    expectEquals(1, $noinline$IntRemBy18(1));
+    expectEquals(-1, $noinline$IntRemBy18(-1));
+    expectEquals(0, $noinline$IntRemBy18(18));
+    expectEquals(0, $noinline$IntRemBy18(-18));
+    expectEquals(11, $noinline$IntRemBy18(65));
+    expectEquals(-11, $noinline$IntRemBy18(-65));
+
+    expectEquals(0, $noinline$IntALenRemBy18(new int[0]));
+    expectEquals(1, $noinline$IntALenRemBy18(new int[1]));
+    expectEquals(0, $noinline$IntALenRemBy18(new int[18]));
+    expectEquals(11, $noinline$IntALenRemBy18(new int[65]));
+
+    expectEquals(0, $noinline$IntRemByMinus18(0));
+    expectEquals(1, $noinline$IntRemByMinus18(1));
+    expectEquals(-1, $noinline$IntRemByMinus18(-1));
+    expectEquals(0, $noinline$IntRemByMinus18(18));
+    expectEquals(0, $noinline$IntRemByMinus18(-18));
+    expectEquals(11, $noinline$IntRemByMinus18(65));
+    expectEquals(-11, $noinline$IntRemByMinus18(-65));
+
+    expectEquals(0, $noinline$IntRemBy7(0));
+    expectEquals(1, $noinline$IntRemBy7(1));
+    expectEquals(-1, $noinline$IntRemBy7(-1));
+    expectEquals(0, $noinline$IntRemBy7(7));
+    expectEquals(0, $noinline$IntRemBy7(-7));
+    expectEquals(1, $noinline$IntRemBy7(22));
+    expectEquals(-1, $noinline$IntRemBy7(-22));
+
+    expectEquals(0, $noinline$IntALenRemBy7(new int[0]));
+    expectEquals(1, $noinline$IntALenRemBy7(new int[1]));
+    expectEquals(0, $noinline$IntALenRemBy7(new int[7]));
+    expectEquals(1, $noinline$IntALenRemBy7(new int[22]));
+
+    expectEquals(0, $noinline$IntRemByMinus7(0));
+    expectEquals(1, $noinline$IntRemByMinus7(1));
+    expectEquals(-1, $noinline$IntRemByMinus7(-1));
+    expectEquals(0, $noinline$IntRemByMinus7(7));
+    expectEquals(0, $noinline$IntRemByMinus7(-7));
+    expectEquals(1, $noinline$IntRemByMinus7(22));
+    expectEquals(-1, $noinline$IntRemByMinus7(-22));
+
+    expectEquals(0, $noinline$IntRemBy6(0));
+    expectEquals(1, $noinline$IntRemBy6(1));
+    expectEquals(-1, $noinline$IntRemBy6(-1));
+    expectEquals(0, $noinline$IntRemBy6(6));
+    expectEquals(0, $noinline$IntRemBy6(-6));
+    expectEquals(1, $noinline$IntRemBy6(19));
+    expectEquals(-1, $noinline$IntRemBy6(-19));
+
+    expectEquals(0, $noinline$IntALenRemBy6(new int[0]));
+    expectEquals(1, $noinline$IntALenRemBy6(new int[1]));
+    expectEquals(0, $noinline$IntALenRemBy6(new int[6]));
+    expectEquals(1, $noinline$IntALenRemBy6(new int[19]));
+
+    expectEquals(0, $noinline$IntRemByMinus6(0));
+    expectEquals(1, $noinline$IntRemByMinus6(1));
+    expectEquals(-1, $noinline$IntRemByMinus6(-1));
+    expectEquals(0, $noinline$IntRemByMinus6(6));
+    expectEquals(0, $noinline$IntRemByMinus6(-6));
+    expectEquals(1, $noinline$IntRemByMinus6(19));
+    expectEquals(-1, $noinline$IntRemByMinus6(-19));
+
+    expectEquals(1, $noinline$UnsignedIntRem01(13));
+    expectEquals(1, $noinline$UnsignedIntRem02(13));
+    expectEquals(1, $noinline$UnsignedIntRem03(13));
+    expectEquals(1, $noinline$UnsignedIntRem04(13));
+    expectEquals(1, $noinline$UnsignedIntRem05(101));
+    expectEquals(11, $noinline$UnsignedIntRem06(101));
+
+    expectEquals(-1, $noinline$SignedIntRem01(-13));
+    expectEquals(-1, $noinline$SignedIntRem02(-13));
+    expectEquals(1, $noinline$SignedIntRem03(-13));
+    expectEquals(1, $noinline$SignedIntRem04(-13, true));
+    expectEquals(0, $noinline$SignedIntRem05(-12, 0,-13));
+    expectEquals(-1, $noinline$SignedIntRem06(-13));
+  }
+
+  // A test case to check that 'lsr' and 'asr' are combined into one 'asr'.
+  // For divisor 18 seen in an MP3 decoding workload there is no need
+  // to correct the result of get_high(dividend * magic). So there are no
+  // instructions between 'lsr' and 'asr'. In such a case they can be combined
+  // into one 'asr'.
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$IntRemBy18(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  /// CHECK-NEXT:            mov w{{\d+}}, #0x12
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$IntRemBy18(int v) {
+    int r = v % 18;
+    return r;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$IntALenRemBy18(int[]) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            lsr{{s?}} r{{\d+}}, #2
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #18
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$IntALenRemBy18(int[]) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            mov w{{\d+}}, #0x12
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$IntALenRemBy18(int[] arr) {
+    int r = arr.length % 18;
+    return r;
+  }
+
+  // A test case to check that 'lsr' and 'asr' are combined into one 'asr'.
+  // Divisor -18 has the same property as divisor 18: no need to correct the
+  // result of get_high(dividend * magic). So there are no
+  // instructions between 'lsr' and 'asr'. In such a case they can be combined
+  // into one 'asr'.
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$IntRemByMinus18(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  /// CHECK-NEXT:            mov w{{\d+}}, #0xffffffee
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$IntRemByMinus18(int v) {
+    int r = v % -18;
+    return r;
+  }
+
+  // A test case to check that 'lsr' and 'add' are combined into one 'adds'.
+  // For divisor 7 seen in the core library the result of get_high(dividend * magic)
+  // must be corrected by the 'add' instruction.
+  //
+  // The test case also checks 'add' and 'add_shift' are optimized into 'adds' and 'cinc'.
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$IntRemBy7(int) disassembly (after)
+  /// CHECK:                 adds x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #32
+  /// CHECK-NEXT:            asr  x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            cinc w{{\d+}}, w{{\d+}}, mi
+  /// CHECK-NEXT:            mov w{{\d+}}, #0x7
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$IntRemBy7(int v) {
+    int r = v % 7;
+    return r;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$IntALenRemBy7(int[]) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            add{{s?}} r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            lsr{{s?}} r{{\d+}}, #2
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #7
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$IntALenRemBy7(int[]) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            mov w{{\d+}}, #0x7
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$IntALenRemBy7(int[] arr) {
+    int r = arr.length % 7;
+    return r;
+  }
+
+  // A test case to check that 'lsr' and 'add' are combined into one 'adds'.
+  // Divisor -7 has the same property as divisor 7: the result of get_high(dividend * magic)
+  // must be corrected. In this case it is a 'sub' instruction.
+  //
+  // The test case also checks 'sub' and 'add_shift' are optimized into 'subs' and 'cinc'.
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$IntRemByMinus7(int) disassembly (after)
+  /// CHECK:                 subs x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #32
+  /// CHECK-NEXT:            asr  x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            cinc w{{\d+}}, w{{\d+}}, mi
+  /// CHECK-NEXT:            mov w{{\d+}}, #0xfffffff9
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$IntRemByMinus7(int v) {
+    int r = v % -7;
+    return r;
+  }
+
+  // A test case to check that 'asr' is used to get the high 32 bits of the result of
+  // 'dividend * magic'.
+  // For divisor 6 seen in the core library there is no need to correct the result of
+  // get_high(dividend * magic). Also there is no 'asr' before the final 'add' instruction
+  // which uses only the high 32 bits of the result. In such a case 'asr' getting the high
+  // 32 bits can be used as well.
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$IntRemBy6(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  /// CHECK-NEXT:            mov w{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$IntRemBy6(int v) {
+    int r = v % 6;
+    return r;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$IntALenRemBy6(int[]) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$IntALenRemBy6(int[]) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            mov w{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$IntALenRemBy6(int[] arr) {
+    int r = arr.length % 6;
+    return r;
+  }
+
+  // A test case to check that 'asr' is used to get the high 32 bits of the result of
+  // 'dividend * magic'.
+  // Divisor -6 has the same property as divisor 6: no need to correct the result of
+  // get_high(dividend * magic) and no 'asr' before the final 'add' instruction
+  // which uses only the high 32 bits of the result. In such a case 'asr' getting the high
+  // 32 bits can be used as well.
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$IntRemByMinus6(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  /// CHECK-NEXT:            mov w{{\d+}}, #0xfffffffa
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$IntRemByMinus6(int v) {
+    int r = v % -6;
+    return r;
+  }
+
+  private static int $noinline$Negate(int v) {
+    return -v;
+  }
+
+  private static int $noinline$Decrement(int v) {
+    return v - 1;
+  }
+
+  private static int $noinline$Increment(int v) {
+    return v + 1;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem01(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem01(int) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            mov w{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$UnsignedIntRem01(int v) {
+    int c = 0;
+    if (v > 0) {
+      c = v % 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem02(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem02(int) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            mov w{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$UnsignedIntRem02(int v) {
+    int c = 0;
+    if (0 < v) {
+      c = v % 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem03(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem03(int) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            mov w{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$UnsignedIntRem03(int v) {
+    int c = 0;
+    if (v >= 0) {
+      c = v % 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem04(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem04(int) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            mov w{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$UnsignedIntRem04(int v) {
+    int c = 0;
+    if (0 <= v) {
+      c = v % 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem05(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            lsr{{s?}} r{{\d+}}, #2
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #10
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem05(int) disassembly (after)
+  /// CHECK:                 lsr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            mov w{{\d+}}, #0xa
+  /// CHECK-NEXT:            msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$UnsignedIntRem05(int v) {
+    int c = 0;
+    for(; v > 100; ++c) {
+      v %= 10;
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$UnsignedIntRem06(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            lsr{{s?}} r{{\d+}}, r{{\d+}}, #2
+  /// CHECK:                 mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem06(int) disassembly (after)
+  /// CHECK:                 smull x{{\d+}}, w{{\d+}}, w{{\d+}}
+  /// CHECK-NEXT:            lsr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK:                 msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static int $noinline$UnsignedIntRem06(int v) {
+    if (v < 10) {
+      v = $noinline$Negate(v); // This is to prevent from using Select.
+    } else {
+      v = (v % 10) + (v / 10);
+    }
+    return v;
+  }
+
+  // A test case to check that a correcting 'add' is generated for a negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem01(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem01(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntRem01(int v) {
+    int c = 0;
+    if (v < 0) {
+      c = v % 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for a negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem02(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem02(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntRem02(int v) {
+    int c = 0;
+    if (v <= 0) {
+      c = v % 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem03(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem03(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntRem03(int v) {
+    boolean positive = (v > 0);
+    int c = v % 6;
+    if (!positive) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem04(int, boolean) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem04(int, boolean) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntRem04(int v, boolean apply_rem) {
+    int c = 0;
+    boolean positive = (v > 0);
+    if (apply_rem) {
+      c = v % 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    if (!positive) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem05(int, int, int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem05(int, int, int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntRem05(int v, int a, int b) {
+    int c = 0;
+
+    if (v < a)
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+
+    if (b < a)
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+
+    if (v > b) {
+      c = v % 6;
+    } else {
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+    }
+
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM:   int RemTest.$noinline$SignedIntRem06(int) disassembly (after)
+  /// CHECK:                 smull     r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  /// CHECK-NEXT:            sub       r{{\d+}}, r{{\d+}}, asr #31
+  /// CHECK-NEXT:            mov{{s?}} r{{\d+}}, #6
+  /// CHECK-NEXT:            mls       r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
+  /// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem06(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #32
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  private static int $noinline$SignedIntRem06(int v) {
+    int c = v % 6;
+
+    if (v > 0) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+
+    return c;
+  }
+
+  private static void remLong() {
+    expectEquals(0L, $noinline$LongRemBy18(0L));
+    expectEquals(1L, $noinline$LongRemBy18(1L));
+    expectEquals(-1L, $noinline$LongRemBy18(-1L));
+    expectEquals(0L, $noinline$LongRemBy18(18L));
+    expectEquals(0L, $noinline$LongRemBy18(-18L));
+    expectEquals(11L, $noinline$LongRemBy18(65L));
+    expectEquals(-11L, $noinline$LongRemBy18(-65L));
+
+    expectEquals(0L, $noinline$LongRemByMinus18(0L));
+    expectEquals(1L, $noinline$LongRemByMinus18(1L));
+    expectEquals(-1L, $noinline$LongRemByMinus18(-1L));
+    expectEquals(0L, $noinline$LongRemByMinus18(18L));
+    expectEquals(0L, $noinline$LongRemByMinus18(-18L));
+    expectEquals(11L, $noinline$LongRemByMinus18(65L));
+    expectEquals(-11L, $noinline$LongRemByMinus18(-65L));
+
+    expectEquals(0L, $noinline$LongRemBy7(0L));
+    expectEquals(1L, $noinline$LongRemBy7(1L));
+    expectEquals(-1L, $noinline$LongRemBy7(-1L));
+    expectEquals(0L, $noinline$LongRemBy7(7L));
+    expectEquals(0L, $noinline$LongRemBy7(-7L));
+    expectEquals(1L, $noinline$LongRemBy7(22L));
+    expectEquals(-1L, $noinline$LongRemBy7(-22L));
+
+    expectEquals(0L, $noinline$LongRemByMinus7(0L));
+    expectEquals(1L, $noinline$LongRemByMinus7(1L));
+    expectEquals(-1L, $noinline$LongRemByMinus7(-1L));
+    expectEquals(0L, $noinline$LongRemByMinus7(7L));
+    expectEquals(0L, $noinline$LongRemByMinus7(-7L));
+    expectEquals(1L, $noinline$LongRemByMinus7(22L));
+    expectEquals(-1L, $noinline$LongRemByMinus7(-22L));
+
+    expectEquals(0L, $noinline$LongRemBy6(0L));
+    expectEquals(1L, $noinline$LongRemBy6(1L));
+    expectEquals(-1L, $noinline$LongRemBy6(-1L));
+    expectEquals(0L, $noinline$LongRemBy6(6L));
+    expectEquals(0L, $noinline$LongRemBy6(-6L));
+    expectEquals(1L, $noinline$LongRemBy6(19L));
+    expectEquals(-1L, $noinline$LongRemBy6(-19L));
+
+    expectEquals(0L, $noinline$LongRemByMinus6(0L));
+    expectEquals(1L, $noinline$LongRemByMinus6(1L));
+    expectEquals(-1L, $noinline$LongRemByMinus6(-1L));
+    expectEquals(0L, $noinline$LongRemByMinus6(6L));
+    expectEquals(0L, $noinline$LongRemByMinus6(-6L));
+    expectEquals(1L, $noinline$LongRemByMinus6(19L));
+    expectEquals(-1L, $noinline$LongRemByMinus6(-19L));
+
+    expectEquals(0L, $noinline$LongRemBy100(0L));
+    expectEquals(1L, $noinline$LongRemBy100(1L));
+    expectEquals(-1L, $noinline$LongRemBy100(-1L));
+    expectEquals(0L, $noinline$LongRemBy100(100L));
+    expectEquals(0L, $noinline$LongRemBy100(-100L));
+    expectEquals(1L, $noinline$LongRemBy100(101L));
+    expectEquals(-1L, $noinline$LongRemBy100(-101L));
+
+    expectEquals(0L, $noinline$LongRemByMinus100(0L));
+    expectEquals(1L, $noinline$LongRemByMinus100(1L));
+    expectEquals(-1L, $noinline$LongRemByMinus100(-1L));
+    expectEquals(0L, $noinline$LongRemByMinus100(100L));
+    expectEquals(0L, $noinline$LongRemByMinus100(-100L));
+    expectEquals(1L, $noinline$LongRemByMinus100(101L));
+    expectEquals(-1L, $noinline$LongRemByMinus100(-101L));
+
+    expectEquals(1L, $noinline$UnsignedLongRem01(13L));
+    expectEquals(1L, $noinline$UnsignedLongRem02(13L));
+    expectEquals(1L, $noinline$UnsignedLongRem03(13L));
+    expectEquals(1L, $noinline$UnsignedLongRem04(13L));
+    expectEquals(1L, $noinline$UnsignedLongRem05(101L));
+    expectEquals(11L, $noinline$UnsignedLongRem06(101L));
+
+    expectEquals(-1L, $noinline$SignedLongRem01(-13L));
+    expectEquals(-1L, $noinline$SignedLongRem02(-13L));
+    expectEquals(1L, $noinline$SignedLongRem03(-13L));
+    expectEquals(1L, $noinline$SignedLongRem04(-13L, true));
+    expectEquals(0L, $noinline$SignedLongRem05(-12L, 0L,-13L));
+    expectEquals(-1L, $noinline$SignedLongRem06(-13L));
+  }
+
+  // Test cases for Int64 HDiv/HRem to check that optimizations implemented for Int32 are not
+  // used for Int64. The same divisors 18, -18, 7, -7, 6 and -6 are used.
+
+  /// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy18(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x12
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$LongRemBy18(long v) {
+    long r = v % 18L;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus18(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0xffffffffffffffee
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$LongRemByMinus18(long v) {
+    long r = v % -18L;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy7(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            asr x{{\d+}}, x{{\d+}}, #1
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x7
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$LongRemBy7(long v) {
+    long r = v % 7L;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus7(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            asr x{{\d+}}, x{{\d+}}, #1
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0xfffffffffffffff9
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$LongRemByMinus7(long v) {
+    long r = v % -7L;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy6(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$LongRemBy6(long v) {
+    long r = v % 6L;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus6(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0xfffffffffffffffa
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$LongRemByMinus6(long v) {
+    long r = v % -6L;
+    return r;
+  }
+
+  // A test to check 'add' and 'add_shift' are optimized into 'adds' and 'cinc'.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy100(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            adds  x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            asr   x{{\d+}}, x{{\d+}}, #6
+  /// CHECK-NEXT:            cinc  x{{\d+}}, x{{\d+}}, mi
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x64
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$LongRemBy100(long v) {
+    long r = v % 100L;
+    return r;
+  }
+
+  // A test to check 'sub' and 'add_shift' are optimized into 'subs' and 'cinc'.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus100(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            subs  x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            asr   x{{\d+}}, x{{\d+}}, #6
+  /// CHECK-NEXT:            cinc  x{{\d+}}, x{{\d+}}, mi
+  /// CHECK-NEXT:            mov x{{\d+}}, #0xffffffffffffff9c
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$LongRemByMinus100(long v) {
+    long r = v % -100L;
+    return r;
+  }
+
+  private static long $noinline$Negate(long v) {
+    return -v;
+  }
+
+  private static long $noinline$Decrement(long v) {
+    return v - 1;
+  }
+
+  private static long $noinline$Increment(long v) {
+    return v + 1;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem01(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$UnsignedLongRem01(long v) {
+    long c = 0;
+    if (v > 0) {
+      c = v % 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem02(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$UnsignedLongRem02(long v) {
+    long c = 0;
+    if (0 < v) {
+      c = v % 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem03(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$UnsignedLongRem03(long v) {
+    long c = 0;
+    if (v >= 0) {
+      c = v % 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem04(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$UnsignedLongRem04(long v) {
+    long c = 0;
+    if (0 <= v) {
+      c = v % 6;
+    } else {
+      c = $noinline$Negate(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem05(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            lsr x{{\d+}}, x{{\d+}}, #2
+  /// CHECK-NEXT:            mov x{{\d+}}, #0xa
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$UnsignedLongRem05(long v) {
+    long c = 0;
+    for(; v > 100; ++c) {
+      v %= 10;
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is not generated for a non-negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem06(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            lsr x{{\d+}}, x{{\d+}}, #2
+  /// CHECK:                 msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$UnsignedLongRem06(long v) {
+    if (v < 10) {
+      v = $noinline$Negate(v); // This is to prevent from using Select.
+    } else {
+      v = (v % 10) + (v / 10);
+    }
+    return v;
+  }
+
+  // A test case to check that a correcting 'add' is generated for a negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem01(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$SignedLongRem01(long v) {
+    long c = 0;
+    if (v < 0) {
+      c = v % 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for a negative
+  // dividend and a positive divisor.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem02(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$SignedLongRem02(long v) {
+    long c = 0;
+    if (v <= 0) {
+      c = v % 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem03(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$SignedLongRem03(long v) {
+    boolean positive = (v > 0);
+    long c = v % 6;
+    if (!positive) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem04(long, boolean) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$SignedLongRem04(long v, boolean apply_rem) {
+    long c = 0;
+    boolean positive = (v > 0);
+    if (apply_rem) {
+      c = v % 6;
+    } else {
+      c = $noinline$Decrement(v); // This is to prevent from using Select.
+    }
+    if (!positive) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem05(long, long, long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$SignedLongRem05(long v, long a, long b) {
+    long c = 0;
+
+    if (v < a)
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+
+    if (b < a)
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+
+    if (v > b) {
+      c = v % 6;
+    } else {
+      c = $noinline$Increment(c); // This is to prevent from using Select.
+    }
+
+    return c;
+  }
+
+  // A test case to check that a correcting 'add' is generated for signed division.
+  //
+  /// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem06(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK-NEXT:            mov x{{\d+}}, #0x6
+  /// CHECK-NEXT:            msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long $noinline$SignedLongRem06(long v) {
+    long c = v % 6;
+
+    if (v > 0) {
+      c = $noinline$Negate(c); // This is to prevent from using Select.
+    }
+
+    return c;
+  }
+}
diff --git a/test/411-checker-hdiv-hrem-pow2/Android.bp b/test/411-checker-hdiv-hrem-pow2/Android.bp
new file mode 100644
index 0000000..734a28f
--- /dev/null
+++ b/test/411-checker-hdiv-hrem-pow2/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `411-checker-hdiv-hrem-pow2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-411-checker-hdiv-hrem-pow2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-411-checker-hdiv-hrem-pow2-expected-stdout",
+        ":art-run-test-411-checker-hdiv-hrem-pow2-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-411-checker-hdiv-hrem-pow2-expected-stdout",
+    out: ["art-run-test-411-checker-hdiv-hrem-pow2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-411-checker-hdiv-hrem-pow2-expected-stderr",
+    out: ["art-run-test-411-checker-hdiv-hrem-pow2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/411-checker-hdiv-hrem-pow2/expected.txt b/test/411-checker-hdiv-hrem-pow2/expected-stderr.txt
similarity index 100%
rename from test/411-checker-hdiv-hrem-pow2/expected.txt
rename to test/411-checker-hdiv-hrem-pow2/expected-stderr.txt
diff --git a/test/411-checker-hdiv-hrem-pow2/expected.txt b/test/411-checker-hdiv-hrem-pow2/expected-stdout.txt
similarity index 100%
copy from test/411-checker-hdiv-hrem-pow2/expected.txt
copy to test/411-checker-hdiv-hrem-pow2/expected-stdout.txt
diff --git a/test/411-checker-hdiv-hrem-pow2/info.txt b/test/411-checker-hdiv-hrem-pow2/info.txt
index df1c988..e6fe1de 100644
--- a/test/411-checker-hdiv-hrem-pow2/info.txt
+++ b/test/411-checker-hdiv-hrem-pow2/info.txt
@@ -1,2 +1,2 @@
 Test the optimization of integer division and remainder instructions when
-the denominator is power of 2 on arm64.
+the denominator is power of 2.
diff --git a/test/411-checker-hdiv-hrem-pow2/src/DivTest.java b/test/411-checker-hdiv-hrem-pow2/src/DivTest.java
index 1a086ef..0d09f3f 100644
--- a/test/411-checker-hdiv-hrem-pow2/src/DivTest.java
+++ b/test/411-checker-hdiv-hrem-pow2/src/DivTest.java
@@ -64,6 +64,64 @@
     expectEquals(0xc0000001, $noinline$IntDivByMinus2(Integer.MAX_VALUE));
     expectEquals(0x40000000, $noinline$IntDivByMinus2(Integer.MIN_VALUE));
 
+    expectEquals(0, $noinline$IntAbsDivBy2(0));
+    expectEquals(0, $noinline$IntAbsDivBy2(1));
+    expectEquals(0, $noinline$IntAbsDivBy2(-1));
+    expectEquals(1, $noinline$IntAbsDivBy2(2));
+    expectEquals(1, $noinline$IntAbsDivBy2(-2));
+    expectEquals(1, $noinline$IntAbsDivBy2(3));
+    expectEquals(1, $noinline$IntAbsDivBy2(-3));
+    expectEquals(3, $noinline$IntAbsDivBy2(7));
+    expectEquals(3, $noinline$IntAbsDivBy2(-7));
+    expectEquals(4, $noinline$IntAbsDivBy2(8));
+    expectEquals(4, $noinline$IntAbsDivBy2(-8));
+    expectEquals(7, $noinline$IntAbsDivBy2(0x0f));
+    expectEquals(0x007f, $noinline$IntAbsDivBy2(0x00ff));
+    expectEquals(0x07ff, $noinline$IntAbsDivBy2(0x0fff));
+    expectEquals(0x007fff, $noinline$IntAbsDivBy2(0x00ffff));
+    expectEquals(0x3fffffff, $noinline$IntAbsDivBy2(Integer.MAX_VALUE));
+    expectEquals(0xc0000000, $noinline$IntAbsDivBy2(Integer.MIN_VALUE));
+
+    expectEquals(0, $noinline$IntAbsDivByMinus2(0));
+    expectEquals(0, $noinline$IntAbsDivByMinus2(1));
+    expectEquals(0, $noinline$IntAbsDivByMinus2(-1));
+    expectEquals(-1, $noinline$IntAbsDivByMinus2(2));
+    expectEquals(-1, $noinline$IntAbsDivByMinus2(-2));
+    expectEquals(-1, $noinline$IntAbsDivByMinus2(3));
+    expectEquals(-1, $noinline$IntAbsDivByMinus2(-3));
+    expectEquals(-3, $noinline$IntAbsDivByMinus2(7));
+    expectEquals(-3, $noinline$IntAbsDivByMinus2(-7));
+    expectEquals(-4, $noinline$IntAbsDivByMinus2(8));
+    expectEquals(-4, $noinline$IntAbsDivByMinus2(-8));
+    expectEquals(-7, $noinline$IntAbsDivByMinus2(0x0f));
+    expectEquals(0xffffff81, $noinline$IntAbsDivByMinus2(0x00ff));
+    expectEquals(0xfffff801, $noinline$IntAbsDivByMinus2(0x0fff));
+    expectEquals(0xffff8001, $noinline$IntAbsDivByMinus2(0x00ffff));
+    expectEquals(0xc0000001, $noinline$IntAbsDivByMinus2(Integer.MAX_VALUE));
+    expectEquals(0x40000000, $noinline$IntAbsDivByMinus2(Integer.MIN_VALUE));
+
+    expectEquals(0, $noinline$IntALenDivBy2(new int[0]));
+    expectEquals(0, $noinline$IntALenDivBy2(new int[1]));
+    expectEquals(1, $noinline$IntALenDivBy2(new int[2]));
+    expectEquals(1, $noinline$IntALenDivBy2(new int[3]));
+    expectEquals(3, $noinline$IntALenDivBy2(new int[7]));
+    expectEquals(4, $noinline$IntALenDivBy2(new int[8]));
+    expectEquals(7, $noinline$IntALenDivBy2(new int[0x0f]));
+    expectEquals(0x007f, $noinline$IntALenDivBy2(new int[0x00ff]));
+    expectEquals(0x07ff, $noinline$IntALenDivBy2(new int[0x0fff]));
+    expectEquals(0x007fff, $noinline$IntALenDivBy2(new int[0x00ffff]));
+
+    expectEquals(0, $noinline$IntALenDivByMinus2(new int[0]));
+    expectEquals(0, $noinline$IntALenDivByMinus2(new int[1]));
+    expectEquals(-1, $noinline$IntALenDivByMinus2(new int[2]));
+    expectEquals(-1, $noinline$IntALenDivByMinus2(new int[3]));
+    expectEquals(-3, $noinline$IntALenDivByMinus2(new int[7]));
+    expectEquals(-4, $noinline$IntALenDivByMinus2(new int[8]));
+    expectEquals(-7, $noinline$IntALenDivByMinus2(new int[0x0f]));
+    expectEquals(0xffffff81, $noinline$IntALenDivByMinus2(new int[0x00ff]));
+    expectEquals(0xfffff801, $noinline$IntALenDivByMinus2(new int[0x0fff]));
+    expectEquals(0xffff8001, $noinline$IntALenDivByMinus2(new int[0x00ffff]));
+
     expectEquals(0, $noinline$IntDivBy16(0));
     expectEquals(1, $noinline$IntDivBy16(16));
     expectEquals(-1, $noinline$IntDivBy16(-16));
@@ -84,16 +142,61 @@
     expectEquals(0xf8000001, $noinline$IntDivByMinus16(Integer.MAX_VALUE));
     expectEquals(0x08000000, $noinline$IntDivByMinus16(Integer.MIN_VALUE));
 
+    expectEquals(0, $noinline$IntAbsDivBy16(0));
+    expectEquals(1, $noinline$IntAbsDivBy16(16));
+    expectEquals(1, $noinline$IntAbsDivBy16(-16));
+    expectEquals(2, $noinline$IntAbsDivBy16(33));
+    expectEquals(0x000f, $noinline$IntAbsDivBy16(0x00ff));
+    expectEquals(0x00ff, $noinline$IntAbsDivBy16(0x0fff));
+    expectEquals(0x000fff, $noinline$IntAbsDivBy16(0x00ffff));
+    expectEquals(0x07ffffff, $noinline$IntAbsDivBy16(Integer.MAX_VALUE));
+    expectEquals(0xf8000000, $noinline$IntAbsDivBy16(Integer.MIN_VALUE));
+
+    expectEquals(0, $noinline$IntAbsDivByMinus16(0));
+    expectEquals(-1, $noinline$IntAbsDivByMinus16(16));
+    expectEquals(-1, $noinline$IntAbsDivByMinus16(-16));
+    expectEquals(-2, $noinline$IntAbsDivByMinus16(33));
+    expectEquals(0xfffffff1, $noinline$IntAbsDivByMinus16(0x00ff));
+    expectEquals(0xffffff01, $noinline$IntAbsDivByMinus16(0x0fff));
+    expectEquals(0xfffff001, $noinline$IntAbsDivByMinus16(0x00ffff));
+    expectEquals(0xf8000001, $noinline$IntAbsDivByMinus16(Integer.MAX_VALUE));
+    expectEquals(0x08000000, $noinline$IntAbsDivByMinus16(Integer.MIN_VALUE));
+
+    expectEquals(0, $noinline$IntALenDivBy16(new int[0]));
+    expectEquals(1, $noinline$IntALenDivBy16(new int[16]));
+    expectEquals(2, $noinline$IntALenDivBy16(new int[33]));
+    expectEquals(0x000f, $noinline$IntALenDivBy16(new int[0x00ff]));
+    expectEquals(0x00ff, $noinline$IntALenDivBy16(new int[0x0fff]));
+    expectEquals(0x000fff, $noinline$IntALenDivBy16(new int[0x00ffff]));
+
+    expectEquals(0, $noinline$IntALenDivByMinus16(new int[0]));
+    expectEquals(-1, $noinline$IntALenDivByMinus16(new int[16]));
+    expectEquals(-2, $noinline$IntALenDivByMinus16(new int[33]));
+    expectEquals(0xfffffff1, $noinline$IntALenDivByMinus16(new int[0x00ff]));
+    expectEquals(0xffffff01, $noinline$IntALenDivByMinus16(new int[0x0fff]));
+    expectEquals(0xfffff001, $noinline$IntALenDivByMinus16(new int[0x00ffff]));
+
     expectEquals(0, $noinline$IntDivByIntMin(0));
     expectEquals(0, $noinline$IntDivByIntMin(1));
     expectEquals(0, $noinline$IntDivByIntMin(-1));
     expectEquals(1, $noinline$IntDivByIntMin(Integer.MIN_VALUE));
     expectEquals(0, $noinline$IntDivByIntMin(Integer.MAX_VALUE));
+
+    expectEquals(0, $noinline$IntAbsDivByIntMin(0));
+    expectEquals(0, $noinline$IntAbsDivByIntMin(1));
+    expectEquals(0, $noinline$IntAbsDivByIntMin(-1));
+    expectEquals(1, $noinline$IntAbsDivByIntMin(Integer.MIN_VALUE));
+    expectEquals(0, $noinline$IntAbsDivByIntMin(Integer.MAX_VALUE));
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntDivBy2(int) disassembly (after)
+  /// CHECK:                 add       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsr #31
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #1
+  //
   /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntDivBy2(int) disassembly (after)
   /// CHECK:                 add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
-  /// CHECK:                 asr w{{\d+}}, w{{\d+}}, #1
+  /// CHECK-NEXT:            asr w{{\d+}}, w{{\d+}}, #1
+  //
   /// CHECK-START-X86_64: java.lang.Integer DivTest.$noinline$IntDivBy2(int) disassembly (after)
   /// CHECK-NOT:             cmovnl/geq
   /// CHECK:                 add
@@ -102,9 +205,15 @@
     return r;
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntDivByMinus2(int) disassembly (after)
+  /// CHECK:                 add       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsr #31
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #1
+  /// CHECK-NEXT:            rsb{{s?}} r{{\d+}}, #0
+  //
   /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntDivByMinus2(int) disassembly (after)
   /// CHECK:                 add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
-  /// CHECK:                 neg w{{\d+}}, w{{\d+}}, asr #1
+  /// CHECK-NEXT:            neg w{{\d+}}, w{{\d+}}, asr #1
+  //
   /// CHECK-START-X86_64: java.lang.Integer DivTest.$noinline$IntDivByMinus2(int) disassembly (after)
   /// CHECK-NOT:             cmovnl/geq
   /// CHECK:                 add
@@ -113,37 +222,182 @@
     return r;
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntAbsDivBy2(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #1
+  //
+  /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntAbsDivBy2(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr w{{\d+}}, w{{\d+}}, #1
+  private static Integer $noinline$IntAbsDivBy2(int v) {
+    int r = Math.abs(v) / 2;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntAbsDivByMinus2(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #1
+  /// CHECK-NEXT:            rsb{{s?}} r{{\d+}}, #0
+  //
+  /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntAbsDivByMinus2(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            neg w{{\d+}}, w{{\d+}}, asr #1
+  private static Integer $noinline$IntAbsDivByMinus2(int v) {
+    int r = Math.abs(v) / -2;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntALenDivBy2(int[]) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #1
+  //
+  /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntALenDivBy2(int[]) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr w{{\d+}}, w{{\d+}}, #1
+  private static Integer $noinline$IntALenDivBy2(int[] arr) {
+    int r = arr.length / 2;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntALenDivByMinus2(int[]) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #1
+  /// CHECK-NEXT:            rsb{{s?}} r{{\d+}}, #0
+  //
+  /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntALenDivByMinus2(int[]) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            neg w{{\d+}}, w{{\d+}}, asr #1
+  private static Integer $noinline$IntALenDivByMinus2(int[] arr) {
+    int r = arr.length / -2;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntDivBy16(int) disassembly (after)
+  /// CHECK:                 asr{{s?}} r{{\d+}}, r{{\d+}}, #31
+  /// CHECK-NEXT:            add       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsr #28
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #4
+  //
   /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntDivBy16(int) disassembly (after)
-  /// CHECK:                add w{{\d+}}, w{{\d+}}, #0xf
-  /// CHECK:                cmp w{{\d+}}, #0x0
-  /// CHECK:                csel w{{\d+}}, w{{\d+}}, w{{\d+}}, lt
-  /// CHECK:                asr w{{\d+}}, w{{\d+}}, #4
+  /// CHECK:                 add w{{\d+}}, w{{\d+}}, #0xf
+  /// CHECK-NEXT:            cmp w{{\d+}}, #0x0
+  /// CHECK-NEXT:            csel w{{\d+}}, w{{\d+}}, w{{\d+}}, lt
+  /// CHECK-NEXT:            asr w{{\d+}}, w{{\d+}}, #4
   private static Integer $noinline$IntDivBy16(int v) {
     int r = v / 16;
     return r;
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntDivByMinus16(int) disassembly (after)
+  /// CHECK:                 asr{{s?}} r{{\d+}}, r{{\d+}}, #31
+  /// CHECK-NEXT:            add       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsr #28
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #4
+  /// CHECK-NEXT:            rsb{{s?}} r{{\d+}}, #0
+  //
   /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntDivByMinus16(int) disassembly (after)
-  /// CHECK:                add w{{\d+}}, w{{\d+}}, #0xf
-  /// CHECK:                cmp w{{\d+}}, #0x0
-  /// CHECK:                csel w{{\d+}}, w{{\d+}}, w{{\d+}}, lt
-  /// CHECK:                neg w{{\d+}}, w{{\d+}}, asr #4
+  /// CHECK:                 add w{{\d+}}, w{{\d+}}, #0xf
+  /// CHECK-NEXT:            cmp w{{\d+}}, #0x0
+  /// CHECK-NEXT:            csel w{{\d+}}, w{{\d+}}, w{{\d+}}, lt
+  /// CHECK-NEXT:            neg w{{\d+}}, w{{\d+}}, asr #4
   private static Integer $noinline$IntDivByMinus16(int v) {
     int r = v / -16;
     return r;
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntAbsDivBy16(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #4
+  //
+  /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntAbsDivBy16(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr w{{\d+}}, w{{\d+}}, #4
+  private static Integer $noinline$IntAbsDivBy16(int v) {
+    int r = Math.abs(v) / 16;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntAbsDivByMinus16(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #4
+  /// CHECK-NEXT:            rsb{{s?}} r{{\d+}}, #0
+  //
+  /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntAbsDivByMinus16(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            neg w{{\d+}}, w{{\d+}}, asr #4
+  private static Integer $noinline$IntAbsDivByMinus16(int v) {
+    int r = Math.abs(v) / -16;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntALenDivBy16(int[]) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #4
+  //
+  /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntALenDivBy16(int[]) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr w{{\d+}}, w{{\d+}}, #4
+  private static Integer $noinline$IntALenDivBy16(int[] arr) {
+    int r = arr.length / 16;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntALenDivByMinus16(int[]) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #4
+  /// CHECK-NEXT:            rsb{{s?}} r{{\d+}}, #0
+  //
+  /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntALenDivByMinus16(int[]) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            neg w{{\d+}}, w{{\d+}}, asr #4
+  private static Integer $noinline$IntALenDivByMinus16(int[] arr) {
+    int r = arr.length / -16;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntDivByIntMin(int) disassembly (after)
+  /// CHECK:                 asr{{s?}} r{{\d+}}, r{{\d+}}, #31
+  /// CHECK-NEXT:            add       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsr #1
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #31
+  /// CHECK-NEXT:            rsb{{s?}} r{{\d+}}, #0
+  //
   /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntDivByIntMin(int) disassembly (after)
-  /// CHECK:                mov w{{\d+}}, #0x7fffffff
-  /// CHECK:                add w{{\d+}}, w{{\d+}}, w{{\d+}}
-  /// CHECK:                cmp w{{\d+}}, #0x0
-  /// CHECK:                csel w{{\d+}}, w{{\d+}}, w{{\d+}}, lt
-  /// CHECK:                neg w{{\d+}}, w{{\d+}}, asr #31
+  /// CHECK:                 mov w{{\d+}}, #0x7fffffff
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}
+  /// CHECK-NEXT:            cmp w{{\d+}}, #0x0
+  /// CHECK-NEXT:            csel w{{\d+}}, w{{\d+}}, w{{\d+}}, lt
+  /// CHECK-NEXT:            neg w{{\d+}}, w{{\d+}}, asr #31
   private static Integer $noinline$IntDivByIntMin(int v) {
     int r = v / Integer.MIN_VALUE;
     return r;
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.$noinline$IntAbsDivByIntMin(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #31
+  /// CHECK-NEXT:            rsb{{s?}} r{{\d+}}, #0
+  //
+  /// CHECK-START-ARM64: java.lang.Integer DivTest.$noinline$IntAbsDivByIntMin(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            neg w{{\d+}}, w{{\d+}}, asr #31
+  private static Integer $noinline$IntAbsDivByIntMin(int v) {
+    int r = Math.abs(v) / Integer.MIN_VALUE;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer DivTest.unsignedDiv01(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr{{s?}} r{{\d+}}, #1
+  //
+  /// CHECK-START-ARM64: java.lang.Integer DivTest.unsignedDiv01(int) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr w{{\d+}}, w{{\d+}}, #1
+  private static Integer unsignedDiv01(int v) {
+    int l = 0;
+    for (int m = v - 1; m >= 0; m = m / 2 - 1) {
+      ++l;
+    }
+    return l;
+  }
+
   private static void divLong() {
     expectEquals(0L, $noinline$LongDivBy2(0L));
     expectEquals(0L, $noinline$LongDivBy2(1L));
@@ -181,6 +435,42 @@
     expectEquals(0xc000000000000001L, $noinline$LongDivByMinus2(Long.MAX_VALUE));
     expectEquals(0x4000000000000000L, $noinline$LongDivByMinus2(Long.MIN_VALUE));
 
+    expectEquals(0L, $noinline$LongAbsDivBy2(0L));
+    expectEquals(0L, $noinline$LongAbsDivBy2(1L));
+    expectEquals(0L, $noinline$LongAbsDivBy2(-1L));
+    expectEquals(1L, $noinline$LongAbsDivBy2(2L));
+    expectEquals(1L, $noinline$LongAbsDivBy2(-2L));
+    expectEquals(1L, $noinline$LongAbsDivBy2(3L));
+    expectEquals(1L, $noinline$LongAbsDivBy2(-3L));
+    expectEquals(3L, $noinline$LongAbsDivBy2(7L));
+    expectEquals(3L, $noinline$LongAbsDivBy2(-7L));
+    expectEquals(4L, $noinline$LongAbsDivBy2(8L));
+    expectEquals(4L, $noinline$LongAbsDivBy2(-8L));
+    expectEquals(7L, $noinline$LongAbsDivBy2(0x0fL));
+    expectEquals(0x007fL, $noinline$LongAbsDivBy2(0x00ffL));
+    expectEquals(0x07ffL, $noinline$LongAbsDivBy2(0x0fffL));
+    expectEquals(0x007fffL, $noinline$LongAbsDivBy2(0x00ffffL));
+    expectEquals(0x3fffffffffffffffL, $noinline$LongAbsDivBy2(Long.MAX_VALUE));
+    expectEquals(0xc000000000000000L, $noinline$LongAbsDivBy2(Long.MIN_VALUE));
+
+    expectEquals(0L, $noinline$LongAbsDivByMinus2(0));
+    expectEquals(0L, $noinline$LongAbsDivByMinus2(1L));
+    expectEquals(0L, $noinline$LongAbsDivByMinus2(-1L));
+    expectEquals(-1L, $noinline$LongAbsDivByMinus2(2L));
+    expectEquals(-1L, $noinline$LongAbsDivByMinus2(-2L));
+    expectEquals(-1L, $noinline$LongAbsDivByMinus2(3L));
+    expectEquals(-1L, $noinline$LongAbsDivByMinus2(-3L));
+    expectEquals(-3L, $noinline$LongAbsDivByMinus2(7L));
+    expectEquals(-3L, $noinline$LongAbsDivByMinus2(-7L));
+    expectEquals(-4L, $noinline$LongAbsDivByMinus2(8L));
+    expectEquals(-4L, $noinline$LongAbsDivByMinus2(-8L));
+    expectEquals(-7L, $noinline$LongAbsDivByMinus2(0x0fL));
+    expectEquals(0xffffffffffffff81L, $noinline$LongAbsDivByMinus2(0x00ffL));
+    expectEquals(0xfffffffffffff801L, $noinline$LongAbsDivByMinus2(0x0fffL));
+    expectEquals(0xffffffffffff8001L, $noinline$LongAbsDivByMinus2(0x00ffffL));
+    expectEquals(0xc000000000000001L, $noinline$LongAbsDivByMinus2(Long.MAX_VALUE));
+    expectEquals(0x4000000000000000L, $noinline$LongAbsDivByMinus2(Long.MIN_VALUE));
+
     expectEquals(0L, $noinline$LongDivBy16(0));
     expectEquals(1L, $noinline$LongDivBy16(16L));
     expectEquals(-1L, $noinline$LongDivBy16(-16L));
@@ -201,16 +491,43 @@
     expectEquals(0xf800000000000001L, $noinline$LongDivByMinus16(Long.MAX_VALUE));
     expectEquals(0x0800000000000000L, $noinline$LongDivByMinus16(Long.MIN_VALUE));
 
+    expectEquals(0L, $noinline$LongAbsDivBy16(0));
+    expectEquals(1L, $noinline$LongAbsDivBy16(16L));
+    expectEquals(1L, $noinline$LongAbsDivBy16(-16L));
+    expectEquals(2L, $noinline$LongAbsDivBy16(33L));
+    expectEquals(0x000fL, $noinline$LongAbsDivBy16(0x00ffL));
+    expectEquals(0x00ffL, $noinline$LongAbsDivBy16(0x0fffL));
+    expectEquals(0x000fffL, $noinline$LongAbsDivBy16(0x00ffffL));
+    expectEquals(0x07ffffffffffffffL, $noinline$LongAbsDivBy16(Long.MAX_VALUE));
+    expectEquals(0xf800000000000000L, $noinline$LongAbsDivBy16(Long.MIN_VALUE));
+
+    expectEquals(0L, $noinline$LongAbsDivByMinus16(0));
+    expectEquals(-1L, $noinline$LongAbsDivByMinus16(16L));
+    expectEquals(-1L, $noinline$LongAbsDivByMinus16(-16L));
+    expectEquals(-2L, $noinline$LongAbsDivByMinus16(33L));
+    expectEquals(0xfffffffffffffff1L, $noinline$LongAbsDivByMinus16(0x00ffL));
+    expectEquals(0xffffffffffffff01L, $noinline$LongAbsDivByMinus16(0x0fffL));
+    expectEquals(0xfffffffffffff001L, $noinline$LongAbsDivByMinus16(0x00ffffL));
+    expectEquals(0xf800000000000001L, $noinline$LongAbsDivByMinus16(Long.MAX_VALUE));
+    expectEquals(0x0800000000000000L, $noinline$LongAbsDivByMinus16(Long.MIN_VALUE));
+
     expectEquals(0L, $noinline$LongDivByLongMin(0));
     expectEquals(0L, $noinline$LongDivByLongMin(1));
     expectEquals(0L, $noinline$LongDivByLongMin(-1));
     expectEquals(1L, $noinline$LongDivByLongMin(Long.MIN_VALUE));
     expectEquals(0L, $noinline$LongDivByLongMin(Long.MAX_VALUE));
+
+    expectEquals(0L, $noinline$LongAbsDivByLongMin(0));
+    expectEquals(0L, $noinline$LongAbsDivByLongMin(1));
+    expectEquals(0L, $noinline$LongAbsDivByLongMin(-1));
+    expectEquals(1L, $noinline$LongAbsDivByLongMin(Long.MIN_VALUE));
+    expectEquals(0L, $noinline$LongAbsDivByLongMin(Long.MAX_VALUE));
   }
 
   /// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongDivBy2(long) disassembly (after)
   /// CHECK:                 add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
-  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #1
+  /// CHECK-NEXT:            asr x{{\d+}}, x{{\d+}}, #1
+  //
   /// CHECK-START-X86_64: java.lang.Long DivTest.$noinline$LongDivBy2(long) disassembly (after)
   /// CHECK-NOT:             cmovnl/geq
   /// CHECK:                 addq
@@ -221,7 +538,8 @@
 
   /// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongDivByMinus2(long) disassembly (after)
   /// CHECK:                 add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
-  /// CHECK:                 neg x{{\d+}}, x{{\d+}}, asr #1
+  /// CHECK-NEXT:            neg x{{\d+}}, x{{\d+}}, asr #1
+  //
   /// CHECK-START-X86_64: java.lang.Long DivTest.$noinline$LongDivByMinus2(long) disassembly (after)
   /// CHECK-NOT:             cmovnl/geq
   /// CHECK:                 addq
@@ -230,34 +548,74 @@
     return r;
   }
 
+  /// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongAbsDivBy2(long) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr x{{\d+}}, x{{\d+}}, #1
+  private static Long $noinline$LongAbsDivBy2(long v) {
+    long r = Math.abs(v) / 2;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongAbsDivByMinus2(long) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            neg x{{\d+}}, x{{\d+}}, asr #1
+  private static Long $noinline$LongAbsDivByMinus2(long v) {
+    long r = Math.abs(v) / -2;
+    return r;
+  }
+
   /// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongDivBy16(long) disassembly (after)
-  /// CHECK:                add x{{\d+}}, x{{\d+}}, #0xf
-  /// CHECK:                cmp x{{\d+}}, #0x0
-  /// CHECK:                csel x{{\d+}}, x{{\d+}}, x{{\d+}}, lt
-  /// CHECK:                asr x{{\d+}}, x{{\d+}}, #4
+  /// CHECK:                 add x{{\d+}}, x{{\d+}}, #0xf
+  /// CHECK-NEXT:            cmp x{{\d+}}, #0x0
+  /// CHECK-NEXT:            csel x{{\d+}}, x{{\d+}}, x{{\d+}}, lt
+  /// CHECK-NEXT:            asr x{{\d+}}, x{{\d+}}, #4
   private static Long $noinline$LongDivBy16(long v) {
     long r = v / 16;
     return r;
   }
 
   /// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongDivByMinus16(long) disassembly (after)
-  /// CHECK:                add x{{\d+}}, x{{\d+}}, #0xf
-  /// CHECK:                cmp x{{\d+}}, #0x0
-  /// CHECK:                csel x{{\d+}}, x{{\d+}}, x{{\d+}}, lt
-  /// CHECK:                neg x{{\d+}}, x{{\d+}}, asr #4
+  /// CHECK:                 add x{{\d+}}, x{{\d+}}, #0xf
+  /// CHECK-NEXT:            cmp x{{\d+}}, #0x0
+  /// CHECK-NEXT:            csel x{{\d+}}, x{{\d+}}, x{{\d+}}, lt
+  /// CHECK-NEXT:            neg x{{\d+}}, x{{\d+}}, asr #4
   private static Long $noinline$LongDivByMinus16(long v) {
     long r = v / -16;
     return r;
   }
 
+  /// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongAbsDivBy16(long) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            asr x{{\d+}}, x{{\d+}}, #4
+  private static Long $noinline$LongAbsDivBy16(long v) {
+    long r = Math.abs(v) / 16;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongAbsDivByMinus16(long) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            neg x{{\d+}}, x{{\d+}}, asr #4
+  private static Long $noinline$LongAbsDivByMinus16(long v) {
+    long r = Math.abs(v) / -16;
+    return r;
+  }
+
   /// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongDivByLongMin(long) disassembly (after)
-  /// CHECK:                mov x{{\d+}}, #0x7fffffffffffffff
-  /// CHECK:                add x{{\d+}}, x{{\d+}}, x{{\d+}}
-  /// CHECK:                cmp x{{\d+}}, #0x0
-  /// CHECK:                csel x{{\d+}}, x{{\d+}}, x{{\d+}}, lt
-  /// CHECK:                neg x{{\d+}}, x{{\d+}}, asr #63
+  /// CHECK:                 mov x{{\d+}}, #0x7fffffffffffffff
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            cmp x{{\d+}}, #0x0
+  /// CHECK-NEXT:            csel x{{\d+}}, x{{\d+}}, x{{\d+}}, lt
+  /// CHECK-NEXT:            neg x{{\d+}}, x{{\d+}}, asr #63
   private static Long $noinline$LongDivByLongMin(long v) {
     long r = v / Long.MIN_VALUE;
     return r;
   }
+
+  /// CHECK-START-ARM64: java.lang.Long DivTest.$noinline$LongAbsDivByLongMin(long) disassembly (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            neg x{{\d+}}, x{{\d+}}, asr #63
+  private static Long $noinline$LongAbsDivByLongMin(long v) {
+    long r = Math.abs(v) / Long.MIN_VALUE;
+    return r;
+  }
 }
diff --git a/test/411-checker-hdiv-hrem-pow2/src/RemTest.java b/test/411-checker-hdiv-hrem-pow2/src/RemTest.java
index 54d7847..2d09317 100644
--- a/test/411-checker-hdiv-hrem-pow2/src/RemTest.java
+++ b/test/411-checker-hdiv-hrem-pow2/src/RemTest.java
@@ -54,6 +54,48 @@
     expectEquals(1, $noinline$IntModMinus2(Integer.MAX_VALUE));
     expectEquals(0, $noinline$IntModMinus2(Integer.MIN_VALUE));
 
+    expectEquals(0, $noinline$IntAbsMod2(0));
+    expectEquals(1, $noinline$IntAbsMod2(1));
+    expectEquals(1, $noinline$IntAbsMod2(-1));
+    expectEquals(0, $noinline$IntAbsMod2(2));
+    expectEquals(0, $noinline$IntAbsMod2(-2));
+    expectEquals(1, $noinline$IntAbsMod2(3));
+    expectEquals(1, $noinline$IntAbsMod2(-3));
+    expectEquals(1, $noinline$IntAbsMod2(0x0f));
+    expectEquals(1, $noinline$IntAbsMod2(0x00ff));
+    expectEquals(1, $noinline$IntAbsMod2(0x00ffff));
+    expectEquals(1, $noinline$IntAbsMod2(Integer.MAX_VALUE));
+    expectEquals(0, $noinline$IntAbsMod2(Integer.MIN_VALUE));
+
+    expectEquals(0, $noinline$IntAbsModMinus2(0));
+    expectEquals(1, $noinline$IntAbsModMinus2(1));
+    expectEquals(1, $noinline$IntAbsModMinus2(-1));
+    expectEquals(0, $noinline$IntAbsModMinus2(2));
+    expectEquals(0, $noinline$IntAbsModMinus2(-2));
+    expectEquals(1, $noinline$IntAbsModMinus2(3));
+    expectEquals(1, $noinline$IntAbsModMinus2(-3));
+    expectEquals(1, $noinline$IntAbsModMinus2(0x0f));
+    expectEquals(1, $noinline$IntAbsModMinus2(0x00ff));
+    expectEquals(1, $noinline$IntAbsModMinus2(0x00ffff));
+    expectEquals(1, $noinline$IntAbsModMinus2(Integer.MAX_VALUE));
+    expectEquals(0, $noinline$IntAbsModMinus2(Integer.MIN_VALUE));
+
+    expectEquals(0, $noinline$IntALenMod2(new int[0]));
+    expectEquals(1, $noinline$IntALenMod2(new int[1]));
+    expectEquals(0, $noinline$IntALenMod2(new int[2]));
+    expectEquals(1, $noinline$IntALenMod2(new int[3]));
+    expectEquals(1, $noinline$IntALenMod2(new int[0x0f]));
+    expectEquals(1, $noinline$IntALenMod2(new int[0x00ff]));
+    expectEquals(1, $noinline$IntALenMod2(new int[0x00ffff]));
+
+    expectEquals(0, $noinline$IntALenModMinus2(new int[0]));
+    expectEquals(1, $noinline$IntALenModMinus2(new int[1]));
+    expectEquals(0, $noinline$IntALenModMinus2(new int[2]));
+    expectEquals(1, $noinline$IntALenModMinus2(new int[3]));
+    expectEquals(1, $noinline$IntALenModMinus2(new int[0x0f]));
+    expectEquals(1, $noinline$IntALenModMinus2(new int[0x00ff]));
+    expectEquals(1, $noinline$IntALenModMinus2(new int[0x00ffff]));
+
     expectEquals(0, $noinline$IntMod16(0));
     expectEquals(1, $noinline$IntMod16(1));
     expectEquals(1, $noinline$IntMod16(17));
@@ -78,6 +120,86 @@
     expectEquals(15, $noinline$IntModMinus16(Integer.MAX_VALUE));
     expectEquals(0, $noinline$IntModMinus16(Integer.MIN_VALUE));
 
+    expectEquals(0, $noinline$IntAbsMod16(0));
+    expectEquals(1, $noinline$IntAbsMod16(1));
+    expectEquals(1, $noinline$IntAbsMod16(17));
+    expectEquals(1, $noinline$IntAbsMod16(-1));
+    expectEquals(0, $noinline$IntAbsMod16(32));
+    expectEquals(0, $noinline$IntAbsMod16(-32));
+    expectEquals(0x0f, $noinline$IntAbsMod16(0x0f));
+    expectEquals(0x0f, $noinline$IntAbsMod16(0x00ff));
+    expectEquals(0x0f, $noinline$IntAbsMod16(0x00ffff));
+    expectEquals(15, $noinline$IntAbsMod16(Integer.MAX_VALUE));
+    expectEquals(0, $noinline$IntAbsMod16(Integer.MIN_VALUE));
+
+    expectEquals(0, $noinline$IntAbsModMinus16(0));
+    expectEquals(1, $noinline$IntAbsModMinus16(1));
+    expectEquals(1, $noinline$IntAbsModMinus16(17));
+    expectEquals(1, $noinline$IntAbsModMinus16(-1));
+    expectEquals(0, $noinline$IntAbsModMinus16(32));
+    expectEquals(0, $noinline$IntAbsModMinus16(-32));
+    expectEquals(0x0f, $noinline$IntAbsModMinus16(0x0f));
+    expectEquals(0x0f, $noinline$IntAbsModMinus16(0x00ff));
+    expectEquals(0x0f, $noinline$IntAbsModMinus16(0x00ffff));
+    expectEquals(15, $noinline$IntAbsModMinus16(Integer.MAX_VALUE));
+    expectEquals(0, $noinline$IntAbsModMinus16(Integer.MIN_VALUE));
+
+    expectEquals(0, $noinline$IntALenMod16(new int[0]));
+    expectEquals(1, $noinline$IntALenMod16(new int[1]));
+    expectEquals(1, $noinline$IntALenMod16(new int[17]));
+    expectEquals(0, $noinline$IntALenMod16(new int[32]));
+    expectEquals(0x0f, $noinline$IntALenMod16(new int[0x0f]));
+    expectEquals(0x0f, $noinline$IntALenMod16(new int[0x00ff]));
+    expectEquals(0x0f, $noinline$IntALenMod16(new int[0x00ffff]));
+
+    expectEquals(0, $noinline$IntALenModMinus16(new int[0]));
+    expectEquals(1, $noinline$IntALenModMinus16(new int[1]));
+    expectEquals(1, $noinline$IntALenModMinus16(new int[17]));
+    expectEquals(0, $noinline$IntALenModMinus16(new int[32]));
+    expectEquals(0x0f, $noinline$IntALenModMinus16(new int[0x0f]));
+    expectEquals(0x0f, $noinline$IntALenModMinus16(new int[0x00ff]));
+    expectEquals(0x0f, $noinline$IntALenModMinus16(new int[0x00ffff]));
+
+    expectEquals(0, $noinline$IntAbsMod1024(0));
+    expectEquals(1, $noinline$IntAbsMod1024(1));
+    expectEquals(1, $noinline$IntAbsMod1024(1025));
+    expectEquals(1, $noinline$IntAbsMod1024(-1));
+    expectEquals(0, $noinline$IntAbsMod1024(2048));
+    expectEquals(0, $noinline$IntAbsMod1024(-2048));
+    expectEquals(0x0f, $noinline$IntAbsMod1024(0x0f));
+    expectEquals(0x0ff, $noinline$IntAbsMod1024(0x00ff));
+    expectEquals(0x03ff, $noinline$IntAbsMod1024(0x00ffff));
+    expectEquals(0x03ff, $noinline$IntAbsMod1024(Integer.MAX_VALUE));
+    expectEquals(0, $noinline$IntAbsMod1024(Integer.MIN_VALUE));
+
+    expectEquals(0, $noinline$IntAbsModMinus1024(0));
+    expectEquals(1, $noinline$IntAbsModMinus1024(1));
+    expectEquals(1, $noinline$IntAbsModMinus1024(1025));
+    expectEquals(1, $noinline$IntAbsModMinus1024(-1));
+    expectEquals(0, $noinline$IntAbsModMinus1024(2048));
+    expectEquals(0, $noinline$IntAbsModMinus1024(-2048));
+    expectEquals(0x0f, $noinline$IntAbsModMinus1024(0x0f));
+    expectEquals(0x0ff, $noinline$IntAbsModMinus1024(0x00ff));
+    expectEquals(0x03ff, $noinline$IntAbsModMinus1024(0x00ffff));
+    expectEquals(0x03ff, $noinline$IntAbsModMinus1024(Integer.MAX_VALUE));
+    expectEquals(0, $noinline$IntAbsModMinus1024(Integer.MIN_VALUE));
+
+    expectEquals(0, $noinline$IntALenMod1024(new int[0]));
+    expectEquals(1, $noinline$IntALenMod1024(new int[1]));
+    expectEquals(1, $noinline$IntALenMod1024(new int[1025]));
+    expectEquals(0, $noinline$IntALenMod1024(new int[2048]));
+    expectEquals(0x0f, $noinline$IntALenMod1024(new int[0x0f]));
+    expectEquals(0x0ff, $noinline$IntALenMod1024(new int[0x00ff]));
+    expectEquals(0x03ff, $noinline$IntALenMod1024(new int[0x00ffff]));
+
+    expectEquals(0, $noinline$IntALenModMinus1024(new int[0]));
+    expectEquals(1, $noinline$IntALenModMinus1024(new int[1]));
+    expectEquals(1, $noinline$IntALenModMinus1024(new int[1025]));
+    expectEquals(0, $noinline$IntALenModMinus1024(new int[2048]));
+    expectEquals(0x0f, $noinline$IntALenModMinus1024(new int[0x0f]));
+    expectEquals(0x0ff, $noinline$IntALenModMinus1024(new int[0x00ff]));
+    expectEquals(0x03ff, $noinline$IntALenModMinus1024(new int[0x00ffff]));
+
     expectEquals(0, $noinline$IntModIntMin(0));
     expectEquals(1, $noinline$IntModIntMin(1));
     expectEquals(0, $noinline$IntModIntMin(Integer.MIN_VALUE));
@@ -86,12 +208,27 @@
     expectEquals(0x00ff, $noinline$IntModIntMin(0x00ff));
     expectEquals(0x00ffff, $noinline$IntModIntMin(0x00ffff));
     expectEquals(Integer.MAX_VALUE, $noinline$IntModIntMin(Integer.MAX_VALUE));
+
+    expectEquals(0, $noinline$IntAbsModIntMin(0));
+    expectEquals(1, $noinline$IntAbsModIntMin(1));
+    expectEquals(0, $noinline$IntAbsModIntMin(Integer.MIN_VALUE));
+    expectEquals(1, $noinline$IntAbsModIntMin(-1));
+    expectEquals(0x0f, $noinline$IntAbsModIntMin(0x0f));
+    expectEquals(0x00ff, $noinline$IntAbsModIntMin(0x00ff));
+    expectEquals(0x00ffff, $noinline$IntAbsModIntMin(0x00ffff));
+    expectEquals(Integer.MAX_VALUE, $noinline$IntAbsModIntMin(Integer.MAX_VALUE));
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntMod2(int) disassembly (after)
+  /// CHECK:                 add       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsr #31
+  /// CHECK-NEXT:            bfc       r{{\d+}}, #0, #1
+  /// CHECK-NEXT:            sub{{s?}} r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
   /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntMod2(int) disassembly (after)
   /// CHECK:                 cmp w{{\d+}}, #0x0
-  /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0x1
-  /// CHECK:                 cneg w{{\d+}}, w{{\d+}}, lt
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x1
+  /// CHECK-NEXT:            cneg w{{\d+}}, w{{\d+}}, lt
+  //
   /// CHECK-START-X86_64: java.lang.Integer RemTest.$noinline$IntMod2(int) disassembly (after)
   /// CHECK:          Rem [{{i\d+}},{{i\d+}}]
   /// CHECK-NOT:      imul
@@ -108,10 +245,16 @@
     return r;
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntModMinus2(int) disassembly (after)
+  /// CHECK:                 add       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsr #31
+  /// CHECK-NEXT:            bfc       r{{\d+}}, #0, #1
+  /// CHECK-NEXT:            sub{{s?}} r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
   /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntModMinus2(int) disassembly (after)
   /// CHECK:                 cmp w{{\d+}}, #0x0
-  /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0x1
-  /// CHECK:                 cneg w{{\d+}}, w{{\d+}}, lt
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x1
+  /// CHECK-NEXT:            cneg w{{\d+}}, w{{\d+}}, lt
+  //
   /// CHECK-START-X86_64: java.lang.Integer RemTest.$noinline$IntModMinus2(int) disassembly (after)
   /// CHECK:          Rem [{{i\d+}},{{i\d+}}]
   /// CHECK-NOT:      imul
@@ -128,11 +271,66 @@
     return r;
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntAbsMod2(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and{{s?}} r{{\d+}}, r{{\d+}}, #0x1
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntAbsMod2(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x1
+  private static Integer $noinline$IntAbsMod2(int v) {
+    int r = Math.abs(v) % 2;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntAbsModMinus2(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and{{s?}} r{{\d+}}, r{{\d+}}, #0x1
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntAbsModMinus2(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x1
+  private static Integer $noinline$IntAbsModMinus2(int v) {
+    int r = Math.abs(v) % -2;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntALenMod2(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and{{s?}} r{{\d+}}, r{{\d+}}, #0x1
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntALenMod2(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x1
+  private static Integer $noinline$IntALenMod2(int[] arr) {
+    int r = arr.length % 2;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntALenModMinus2(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and{{s?}} r{{\d+}}, r{{\d+}}, #0x1
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntALenModMinus2(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x1
+  private static Integer $noinline$IntALenModMinus2(int[] arr) {
+    int r = arr.length % -2;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntMod16(int) disassembly (after)
+  /// CHECK:                 asr{{s?}} r{{\d+}}, r{{\d+}}, #31
+  /// CHECK-NEXT:            add       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsr #28
+  /// CHECK-NEXT:            bfc       r{{\d+}}, #0, #4
+  /// CHECK-NEXT:            sub{{s?}} r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
   /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntMod16(int) disassembly (after)
   /// CHECK:                 negs w{{\d+}}, w{{\d+}}
-  /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0xf
-  /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0xf
-  /// CHECK:                 csneg w{{\d+}}, w{{\d+}}, mi
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0xf
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0xf
+  /// CHECK-NEXT:            csneg w{{\d+}}, w{{\d+}}, mi
+  //
   /// CHECK-START-X86_64: java.lang.Integer RemTest.$noinline$IntMod16(int) disassembly (after)
   /// CHECK:          Rem [{{i\d+}},{{i\d+}}]
   /// CHECK-NOT:      imul
@@ -149,11 +347,18 @@
     return r;
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntModMinus16(int) disassembly (after)
+  /// CHECK:                 asr{{s?}} r{{\d+}}, r{{\d+}}, #31
+  /// CHECK-NEXT:            add       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsr #28
+  /// CHECK-NEXT:            bfc       r{{\d+}}, #0, #4
+  /// CHECK-NEXT:            sub{{s?}} r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
   /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntModMinus16(int) disassembly (after)
   /// CHECK:                 negs w{{\d+}}, w{{\d+}}
-  /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0xf
-  /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0xf
-  /// CHECK:                 csneg w{{\d+}}, w{{\d+}}, mi
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0xf
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0xf
+  /// CHECK-NEXT:            csneg w{{\d+}}, w{{\d+}}, mi
+  //
   /// CHECK-START-X86_64: java.lang.Integer RemTest.$noinline$IntModMinus16(int) disassembly (after)
   /// CHECK:          Rem [{{i\d+}},{{i\d+}}]
   /// CHECK-NOT:      imul
@@ -170,11 +375,114 @@
     return r;
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntAbsMod16(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and{{s?}} r{{\d+}}, r{{\d+}}, #0xf
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntAbsMod16(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0xf
+  private static Integer $noinline$IntAbsMod16(int v) {
+    int r = Math.abs(v) % 16;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntAbsModMinus16(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and{{s?}} r{{\d+}}, r{{\d+}}, #0xf
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntAbsModMinus16(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0xf
+  private static Integer $noinline$IntAbsModMinus16(int v) {
+    int r = Math.abs(v) % -16;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntALenMod16(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and{{s?}} r{{\d+}}, r{{\d+}}, #0xf
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntALenMod16(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0xf
+  private static Integer $noinline$IntALenMod16(int[] arr) {
+    int r = arr.length % 16;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntALenModMinus16(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and{{s?}} r{{\d+}}, r{{\d+}}, #0xf
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntALenModMinus16(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0xf
+  private static Integer $noinline$IntALenModMinus16(int[] arr) {
+    int r = arr.length % -16;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntAbsMod1024(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            ubfx r{{\d+}}, r{{\d+}}, #0, #10
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntAbsMod1024(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x3ff
+  private static Integer $noinline$IntAbsMod1024(int v) {
+    int r = Math.abs(v) % 1024;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntAbsModMinus1024(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            ubfx r{{\d+}}, r{{\d+}}, #0, #10
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntAbsModMinus1024(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x3ff
+  private static Integer $noinline$IntAbsModMinus1024(int v) {
+    int r = Math.abs(v) % -1024;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntALenMod1024(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            ubfx r{{\d+}}, r{{\d+}}, #0, #10
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntALenMod1024(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x3ff
+  private static Integer $noinline$IntALenMod1024(int[] arr) {
+    int r = arr.length % 1024;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntALenModMinus1024(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            ubfx r{{\d+}}, r{{\d+}}, #0, #10
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntALenModMinus1024(int[]) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x3ff
+  private static Integer $noinline$IntALenModMinus1024(int[] arr) {
+    int r = arr.length % -1024;
+    return r;
+  }
+
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntModIntMin(int) disassembly (after)
+  /// CHECK:                 asr{{s?}} r{{\d+}}, r{{\d+}}, #31
+  /// CHECK-NEXT:            add       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsr #1
+  /// CHECK-NEXT:            bfc       r{{\d+}}, #0, #31
+  /// CHECK-NEXT:            sub{{s?}} r{{\d+}}, r{{\d+}}, r{{\d+}}
+  //
   /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntModIntMin(int) disassembly (after)
   /// CHECK:                 negs w{{\d+}}, w{{\d+}}
-  /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0x7fffffff
-  /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0x7fffffff
-  /// CHECK:                 csneg w{{\d+}}, w{{\d+}}, mi
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x7fffffff
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x7fffffff
+  /// CHECK-NEXT:            csneg w{{\d+}}, w{{\d+}}, mi
+  //
   /// CHECK-START-X86_64: java.lang.Integer RemTest.$noinline$IntModIntMin(int) disassembly (after)
   /// CHECK:          Rem [{{i\d+}},{{i\d+}}]
   /// CHECK-NOT:      imul
@@ -191,6 +499,18 @@
     return r;
   }
 
+  /// CHECK-START-ARM:   java.lang.Integer RemTest.$noinline$IntAbsModIntMin(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            ubfx r{{\d+}}, r{{\d+}}, #0, #31
+  //
+  /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntAbsModIntMin(int) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and w{{\d+}}, w{{\d+}}, #0x7fffffff
+  private static Integer $noinline$IntAbsModIntMin(int v) {
+    int r = Math.abs(v) % Integer.MIN_VALUE;
+    return r;
+  }
+
   private static void remLong() {
     expectEquals(0L, $noinline$LongMod2(0));
     expectEquals(1L, $noinline$LongMod2(1));
@@ -222,6 +542,36 @@
     expectEquals(1L, $noinline$LongModMinus2(Long.MAX_VALUE));
     expectEquals(0L, $noinline$LongModMinus2(Long.MIN_VALUE));
 
+    expectEquals(0L, $noinline$LongAbsMod2(0));
+    expectEquals(1L, $noinline$LongAbsMod2(1));
+    expectEquals(1L, $noinline$LongAbsMod2(-1));
+    expectEquals(0L, $noinline$LongAbsMod2(2));
+    expectEquals(0L, $noinline$LongAbsMod2(-2));
+    expectEquals(1L, $noinline$LongAbsMod2(3));
+    expectEquals(1L, $noinline$LongAbsMod2(-3));
+    expectEquals(1L, $noinline$LongAbsMod2(0x0f));
+    expectEquals(1L, $noinline$LongAbsMod2(0x00ff));
+    expectEquals(1L, $noinline$LongAbsMod2(0x00ffff));
+    expectEquals(1L, $noinline$LongAbsMod2(0x00ffffff));
+    expectEquals(1L, $noinline$LongAbsMod2(0x00ffffffffL));
+    expectEquals(1L, $noinline$LongAbsMod2(Long.MAX_VALUE));
+    expectEquals(0L, $noinline$LongAbsMod2(Long.MIN_VALUE));
+
+    expectEquals(0L, $noinline$LongAbsModMinus2(0));
+    expectEquals(1L, $noinline$LongAbsModMinus2(1));
+    expectEquals(1L, $noinline$LongAbsModMinus2(-1));
+    expectEquals(0L, $noinline$LongAbsModMinus2(2));
+    expectEquals(0L, $noinline$LongAbsModMinus2(-2));
+    expectEquals(1L, $noinline$LongAbsModMinus2(3));
+    expectEquals(1L, $noinline$LongAbsModMinus2(-3));
+    expectEquals(1L, $noinline$LongAbsModMinus2(0x0f));
+    expectEquals(1L, $noinline$LongAbsModMinus2(0x00ff));
+    expectEquals(1L, $noinline$LongAbsModMinus2(0x00ffff));
+    expectEquals(1L, $noinline$LongAbsModMinus2(0x00ffffff));
+    expectEquals(1L, $noinline$LongAbsModMinus2(0x00ffffffffL));
+    expectEquals(1L, $noinline$LongAbsModMinus2(Long.MAX_VALUE));
+    expectEquals(0L, $noinline$LongAbsModMinus2(Long.MIN_VALUE));
+
     expectEquals(0L, $noinline$LongMod16(0));
     expectEquals(1L, $noinline$LongMod16(1));
     expectEquals(1L, $noinline$LongMod16(17));
@@ -250,6 +600,34 @@
     expectEquals(15L, $noinline$LongModMinus16(Long.MAX_VALUE));
     expectEquals(0L, $noinline$LongModMinus16(Long.MIN_VALUE));
 
+    expectEquals(0L, $noinline$LongAbsMod16(0));
+    expectEquals(1L, $noinline$LongAbsMod16(1));
+    expectEquals(1L, $noinline$LongAbsMod16(17));
+    expectEquals(1L, $noinline$LongAbsMod16(-1));
+    expectEquals(0L, $noinline$LongAbsMod16(32));
+    expectEquals(0L, $noinline$LongAbsMod16(-32));
+    expectEquals(0x0fL, $noinline$LongAbsMod16(0x0f));
+    expectEquals(0x0fL, $noinline$LongAbsMod16(0x00ff));
+    expectEquals(0x0fL, $noinline$LongAbsMod16(0x00ffff));
+    expectEquals(0x0fL, $noinline$LongAbsMod16(0x00ffffff));
+    expectEquals(0x0fL, $noinline$LongAbsMod16(0x00ffffffffL));
+    expectEquals(15L, $noinline$LongAbsMod16(Long.MAX_VALUE));
+    expectEquals(0L, $noinline$LongAbsMod16(Long.MIN_VALUE));
+
+    expectEquals(0L, $noinline$LongAbsModMinus16(0));
+    expectEquals(1L, $noinline$LongAbsModMinus16(1));
+    expectEquals(1L, $noinline$LongAbsModMinus16(17));
+    expectEquals(1L, $noinline$LongAbsModMinus16(-1));
+    expectEquals(0L, $noinline$LongAbsModMinus16(32));
+    expectEquals(0L, $noinline$LongAbsModMinus16(-32));
+    expectEquals(0x0fL, $noinline$LongAbsModMinus16(0x0f));
+    expectEquals(0x0fL, $noinline$LongAbsModMinus16(0x00ff));
+    expectEquals(0x0fL, $noinline$LongAbsModMinus16(0x00ffff));
+    expectEquals(0x0fL, $noinline$LongAbsModMinus16(0x00ffffff));
+    expectEquals(0x0fL, $noinline$LongAbsModMinus16(0x00ffffffffL));
+    expectEquals(15L, $noinline$LongAbsModMinus16(Long.MAX_VALUE));
+    expectEquals(0L, $noinline$LongAbsModMinus16(Long.MIN_VALUE));
+
     expectEquals(0L, $noinline$LongModLongMin(0));
     expectEquals(1L, $noinline$LongModLongMin(1));
     expectEquals(0L, $noinline$LongModLongMin(Long.MIN_VALUE));
@@ -260,12 +638,24 @@
     expectEquals(0x00ffffffL, $noinline$LongModLongMin(0x00ffffff));
     expectEquals(0x00ffffffffL, $noinline$LongModLongMin(0x00ffffffffL));
     expectEquals(Long.MAX_VALUE, $noinline$LongModLongMin(Long.MAX_VALUE));
+
+    expectEquals(0L, $noinline$LongAbsModLongMin(0));
+    expectEquals(1L, $noinline$LongAbsModLongMin(1));
+    expectEquals(0L, $noinline$LongAbsModLongMin(Long.MIN_VALUE));
+    expectEquals(1L, $noinline$LongAbsModLongMin(-1));
+    expectEquals(0x0fL, $noinline$LongAbsModLongMin(0x0f));
+    expectEquals(0x00ffL, $noinline$LongAbsModLongMin(0x00ff));
+    expectEquals(0x00ffffL, $noinline$LongAbsModLongMin(0x00ffff));
+    expectEquals(0x00ffffffL, $noinline$LongAbsModLongMin(0x00ffffff));
+    expectEquals(0x00ffffffffL, $noinline$LongAbsModLongMin(0x00ffffffffL));
+    expectEquals(Long.MAX_VALUE, $noinline$LongAbsModLongMin(Long.MAX_VALUE));
   }
 
   /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongMod2(long) disassembly (after)
   /// CHECK:                 cmp x{{\d+}}, #0x0
-  /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0x1
-  /// CHECK:                 cneg x{{\d+}}, x{{\d+}}, lt
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0x1
+  /// CHECK-NEXT:            cneg x{{\d+}}, x{{\d+}}, lt
+  //
   /// CHECK-START-X86_64: java.lang.Long RemTest.$noinline$LongMod2(long) disassembly (after)
   /// CHECK:          Rem [{{j\d+}},{{j\d+}}]
   /// CHECK-NOT:      imul
@@ -285,8 +675,9 @@
 
   /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongModMinus2(long) disassembly (after)
   /// CHECK:                 cmp x{{\d+}}, #0x0
-  /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0x1
-  /// CHECK:                 cneg x{{\d+}}, x{{\d+}}, lt
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0x1
+  /// CHECK-NEXT:            cneg x{{\d+}}, x{{\d+}}, lt
+  //
   /// CHECK-START-X86_64: java.lang.Long RemTest.$noinline$LongModMinus2(long) disassembly (after)
   /// CHECK:          Rem [{{j\d+}},{{j\d+}}]
   /// CHECK-NOT:      imul
@@ -304,11 +695,27 @@
     return r;
   }
 
+  /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongAbsMod2(long) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0x1
+  private static Long $noinline$LongAbsMod2(long v) {
+    long r = Math.abs(v) % 2;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongAbsModMinus2(long) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0x1
+  private static Long $noinline$LongAbsModMinus2(long v) {
+    long r = Math.abs(v) % -2;
+    return r;
+  }
+
   /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongMod16(long) disassembly (after)
   /// CHECK:                 negs x{{\d+}}, x{{\d+}}
-  /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0xf
-  /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0xf
-  /// CHECK:                 csneg x{{\d+}}, x{{\d+}}, mi
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0xf
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0xf
+  /// CHECK-NEXT:            csneg x{{\d+}}, x{{\d+}}, mi
 
   /// CHECK-START-X86_64: java.lang.Long RemTest.$noinline$LongMod16(long) disassembly (after)
   /// CHECK:          Rem [{{j\d+}},{{j\d+}}]
@@ -329,9 +736,10 @@
 
   /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongModMinus16(long) disassembly (after)
   /// CHECK:                 negs x{{\d+}}, x{{\d+}}
-  /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0xf
-  /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0xf
-  /// CHECK:                 csneg x{{\d+}}, x{{\d+}}, mi
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0xf
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0xf
+  /// CHECK-NEXT:            csneg x{{\d+}}, x{{\d+}}, mi
+  //
   /// CHECK-START-X86_64: java.lang.Long RemTest.$noinline$LongModMinus16(long) disassembly (after)
   /// CHECK:          Rem [{{j\d+}},{{j\d+}}]
   /// CHECK-NOT:      imul
@@ -349,11 +757,28 @@
     return r;
   }
 
+  /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongAbsMod16(long) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0xf
+  private static Long $noinline$LongAbsMod16(long v) {
+    long r = Math.abs(v) % 16;
+    return r;
+  }
+
+  /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongAbsModMinus16(long) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0xf
+  private static Long $noinline$LongAbsModMinus16(long v) {
+    long r = Math.abs(v) % -16;
+    return r;
+  }
+
   /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongModLongMin(long) disassembly (after)
   /// CHECK:                 negs x{{\d+}}, x{{\d+}}
-  /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0x7fffffffffffffff
-  /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0x7fffffffffffffff
-  /// CHECK:                 csneg x{{\d+}}, x{{\d+}}, mi
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0x7fffffffffffffff
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0x7fffffffffffffff
+  /// CHECK-NEXT:            csneg x{{\d+}}, x{{\d+}}, mi
+  //
   /// CHECK-START-X86_64: java.lang.Long RemTest.$noinline$LongModLongMin(long) disassembly (after)
   /// CHECK:          Rem [{{j\d+}},{{j\d+}}]
   /// CHECK-NOT:      imul
@@ -370,4 +795,12 @@
     long r = v % Long.MIN_VALUE;
     return r;
   }
+
+  /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongAbsModLongMin(long) disassembly (after)
+  /// CHECK:                 Rem
+  /// CHECK-NEXT:            and x{{\d+}}, x{{\d+}}, #0x7fffffffffffffff
+  private static Long $noinline$LongAbsModLongMin(long v) {
+    long r = Math.abs(v) % Long.MIN_VALUE;
+    return r;
+  }
 }
diff --git a/test/411-checker-instruct-simplifier-hrem/Android.bp b/test/411-checker-instruct-simplifier-hrem/Android.bp
new file mode 100644
index 0000000..2d2a221
--- /dev/null
+++ b/test/411-checker-instruct-simplifier-hrem/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `411-checker-instruct-simplifier-hrem`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-411-checker-instruct-simplifier-hrem",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-411-checker-instruct-simplifier-hrem-expected-stdout",
+        ":art-run-test-411-checker-instruct-simplifier-hrem-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-411-checker-instruct-simplifier-hrem-expected-stdout",
+    out: ["art-run-test-411-checker-instruct-simplifier-hrem-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-411-checker-instruct-simplifier-hrem-expected-stderr",
+    out: ["art-run-test-411-checker-instruct-simplifier-hrem-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/411-checker-hdiv-hrem-pow2/expected.txt b/test/411-checker-instruct-simplifier-hrem/expected-stderr.txt
similarity index 100%
copy from test/411-checker-hdiv-hrem-pow2/expected.txt
copy to test/411-checker-instruct-simplifier-hrem/expected-stderr.txt
diff --git a/test/411-checker-hdiv-hrem-pow2/expected.txt b/test/411-checker-instruct-simplifier-hrem/expected-stdout.txt
similarity index 100%
copy from test/411-checker-hdiv-hrem-pow2/expected.txt
copy to test/411-checker-instruct-simplifier-hrem/expected-stdout.txt
diff --git a/test/411-checker-instruct-simplifier-hrem/info.txt b/test/411-checker-instruct-simplifier-hrem/info.txt
new file mode 100644
index 0000000..6ad871e
--- /dev/null
+++ b/test/411-checker-instruct-simplifier-hrem/info.txt
@@ -0,0 +1 @@
+Checker test for instruction_simplifier optimizations of integer remainder instructions.
diff --git a/test/411-checker-instruct-simplifier-hrem/src/Main.java b/test/411-checker-instruct-simplifier-hrem/src/Main.java
new file mode 100644
index 0000000..e6853dd
--- /dev/null
+++ b/test/411-checker-instruct-simplifier-hrem/src/Main.java
@@ -0,0 +1,843 @@
+/*
+ * Copyright (C) 2020 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 {
+  private static void expectEquals(long expected, long result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  private static void expectEquals(long[] div_rem_expected, long[] result) {
+    expectEquals(div_rem_expected[0], result[0]);
+    expectEquals(div_rem_expected[1], result[1]);
+  }
+
+  private static void remInt() {
+    expectEquals(1L, $noinline$IntDivRemBy18(1));
+    expectEquals(1L << 32 | 2L, $noinline$IntDivRemBy18(20));
+
+    expectEquals(1L, $noinline$IntRemDivBy18(1));
+    expectEquals(1L << 32 | 2L, $noinline$IntRemDivBy18(20));
+
+    expectEquals(1L, $noinline$IntDivRemBy18(1, false));
+    expectEquals(1L << 32 | 2L, $noinline$IntDivRemBy18(20, true));
+
+    expectEquals(1L, $noinline$IntDivRemByMinus18(1));
+    expectEquals(-1L, $noinline$IntDivRemBy18(-1));
+    expectEquals((-1L << 32) | 2L, $noinline$IntDivRemByMinus18(20));
+    expectEquals((1L << 32) | (-2L & 0x00000000ffffffff), $noinline$IntDivRemByMinus18(-20));
+
+    expectEquals(0L, $noinline$IntDivRemBy5(0));
+    expectEquals(1L, $noinline$IntDivRemBy5(1));
+    expectEquals(1L << 32, $noinline$IntDivRemBy5(5));
+    expectEquals((1L << 32) | 1L, $noinline$IntDivRemBy5(6));
+    expectEquals((-1L << 32) | 0x00000000ffffffff, $noinline$IntDivRemBy5(-6));
+    expectEquals(-1L << 32, $noinline$IntDivRemBy5(-5));
+    expectEquals(0x00000000ffffffff, $noinline$IntDivRemBy5(-1));
+
+    expectEquals(0L, $noinline$IntDivRemByMinus5(0));
+    expectEquals(1L, $noinline$IntDivRemByMinus5(1));
+    expectEquals(-1L << 32, $noinline$IntDivRemByMinus5(5));
+    expectEquals((-1L << 32) | 1L, $noinline$IntDivRemByMinus5(6));
+    expectEquals((1L << 32) | 0x00000000ffffffff, $noinline$IntDivRemByMinus5(-6));
+    expectEquals(1L << 32, $noinline$IntDivRemByMinus5(-5));
+    expectEquals(0x00000000ffffffff, $noinline$IntDivRemByMinus5(-1));
+
+    expectEquals(0L, $noinline$IntDivRemBy7(0));
+    expectEquals(1L, $noinline$IntDivRemBy7(1));
+    expectEquals(1L << 32, $noinline$IntDivRemBy7(7));
+    expectEquals((1L << 32) | 1L, $noinline$IntDivRemBy7(8));
+    expectEquals((-1L << 32) | 0x00000000ffffffff, $noinline$IntDivRemBy7(-8));
+    expectEquals(-1L << 32, $noinline$IntDivRemBy7(-7));
+    expectEquals(0x00000000ffffffff, $noinline$IntDivRemBy7(-1));
+
+    expectEquals(0L, $noinline$IntDivRemByMinus7(0));
+    expectEquals(1L, $noinline$IntDivRemByMinus7(1));
+    expectEquals(-1L << 32, $noinline$IntDivRemByMinus7(7));
+    expectEquals((-1L << 32) | 1L, $noinline$IntDivRemByMinus7(8));
+    expectEquals((1L << 32) | 0x00000000ffffffff, $noinline$IntDivRemByMinus7(-8));
+    expectEquals(1L << 32, $noinline$IntDivRemByMinus7(-7));
+    expectEquals(0x00000000ffffffff, $noinline$IntDivRemByMinus7(-1));
+
+    expectEquals(0L, $noinline$IntDivRemByMaxInt(0));
+    expectEquals(1L, $noinline$IntDivRemByMaxInt(1));
+    expectEquals(1L << 32, $noinline$IntDivRemByMaxInt(Integer.MAX_VALUE));
+    expectEquals(Integer.MAX_VALUE - 1, $noinline$IntDivRemByMaxInt(Integer.MAX_VALUE - 1));
+    expectEquals((-1L << 32) | 0x00000000ffffffff, $noinline$IntDivRemByMaxInt(Integer.MIN_VALUE));
+    expectEquals(0x00000000ffffffff, $noinline$IntDivRemByMaxInt(-1));
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemBy18(int) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemBy18(int) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long Main.$noinline$IntDivRemBy18(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  /// CHECK:                 msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static long $noinline$IntDivRemBy18(int v) {
+    int q = v / 18;
+    int r = v % 18;
+    return ((long)q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemByMinus18(int) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemByMinus18(int) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long Main.$noinline$IntDivRemByMinus18(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  /// CHECK:                 msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static long $noinline$IntDivRemByMinus18(int v) {
+    int q = v / -18;
+    int r = v % -18;
+    return ((long)q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntRemDivBy18(int) instruction_simplifier (before)
+  /// CHECK:           Rem
+  /// CHECK:           Div
+  //
+  /// CHECK-START: long Main.$noinline$IntRemDivBy18(int) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long Main.$noinline$IntRemDivBy18(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  /// CHECK:                 msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static long $noinline$IntRemDivBy18(int v) {
+    int r = v % 18;
+    int q = v / 18;
+    return ((long)q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemBy5(int) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemBy5(int) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Shl
+  /// CHECK-NEXT:      Add
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long Main.$noinline$IntDivRemBy5(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #33
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  /// CHECK:                 add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsl #2
+  /// CHECK:                 sub w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static long $noinline$IntDivRemBy5(int v) {
+    int q = v / 5;
+    int r = v % 5;
+    return ((long)q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemByMinus5(int) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemByMinus5(int) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long Main.$noinline$IntDivRemByMinus5(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #33
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  /// CHECK:                 msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static long $noinline$IntDivRemByMinus5(int v) {
+    int q = v / -5;
+    int r = v % -5;
+    return ((long)q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemBy7(int) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemBy7(int) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Shl
+  /// CHECK-NEXT:      Sub
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long Main.$noinline$IntDivRemBy7(int) instruction_simplifier_arm64 (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            DataProcWithShifterOp
+  /// CHECK-NEXT:            Add
+  //
+  /// CHECK-START-ARM64: long Main.$noinline$IntDivRemBy7(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            cinc w{{\d+}}, w{{\d+}}, mi
+  /// CHECK:                 sub w{{\d+}}, w{{\d+}}, w{{\d+}}, lsl #3
+  /// CHECK:                 add w{{\d+}}, w{{\d+}}, w{{\d+}}
+  //
+  /// CHECK-START-ARM: long Main.$noinline$IntDivRemBy7(int) instruction_simplifier_arm (after)
+  /// CHECK:               Div
+  /// CHECK-NEXT:          DataProcWithShifterOp
+  /// CHECK-NEXT:          Add
+  //
+  /// CHECK-START-ARM: long Main.$noinline$IntDivRemBy7(int) disassembly (after)
+  /// CHECK:               asr{{s?}} r{{\d+}}, #2
+  /// CHECK-NEXT:          sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  /// CHECK:               sub       r{{\d+}}, r{{\d+}}, r{{\d+}}, lsl #3
+  /// CHECK:               add{{s?}} r{{\d+}}, r{{\d+}}, r{{\d+}}
+  private static long $noinline$IntDivRemBy7(int v) {
+    int q = v / 7;
+    int r = v % 7;
+    return ((long)q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemByMinus7(int) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemByMinus7(int) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long Main.$noinline$IntDivRemByMinus7(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #34
+  /// CHECK-NEXT:            cinc w{{\d+}}, w{{\d+}}, mi
+  /// CHECK:                 msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
+  private static long $noinline$IntDivRemByMinus7(int v) {
+    int q = v / -7;
+    int r = v % -7;
+    return ((long)q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemByMaxInt(int) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemByMaxInt(int) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Shl
+  /// CHECK-NEXT:      Sub
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long Main.$noinline$IntDivRemByMaxInt(int) instruction_simplifier_arm64 (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            DataProcWithShifterOp
+  /// CHECK-NEXT:            Add
+  //
+  /// CHECK-START-ARM64: long Main.$noinline$IntDivRemByMaxInt(int) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #61
+  /// CHECK-NEXT:            add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
+  /// CHECK:                 sub w{{\d+}}, w{{\d+}}, w{{\d+}}, lsl #31
+  /// CHECK:                 add w{{\d+}}, w{{\d+}}, w{{\d+}}
+  //
+  /// CHECK-START-ARM: long Main.$noinline$IntDivRemByMaxInt(int) instruction_simplifier_arm (after)
+  /// CHECK:               Div
+  /// CHECK-NEXT:          DataProcWithShifterOp
+  /// CHECK-NEXT:          Add
+  //
+  /// CHECK-START-ARM: long Main.$noinline$IntDivRemByMaxInt(int) disassembly (after)
+  /// CHECK:               asr{{s?}}  r{{\d+}}, #29
+  /// CHECK-NEXT:          sub        r{{\d+}}, r{{\d+}}, r{{\d+}}, asr #31
+  /// CHECK:               sub        r{{\d+}}, r{{\d+}}, r{{\d+}}, lsl #31
+  /// CHECK:               add{{s?}}  r{{\d+}}, r{{\d+}}, r{{\d+}}
+  private static long $noinline$IntDivRemByMaxInt(int v) {
+    int q = v / Integer.MAX_VALUE;
+    int r = v % Integer.MAX_VALUE;
+    return ((long)q << 32) | r;
+  }
+
+  // A test case to check:
+  //  HDiv with the same inputs as HRem but in another basic block is not reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemBy18(int, boolean) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRemBy18(int, boolean) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  private static long $noinline$IntDivRemBy18(int v, boolean do_division) {
+    long result = 0;
+    if (do_division) {
+      int q = v / 18;
+      result = (long)q << 32;
+    }
+    int r = v % 18;
+    return result | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRem(int, int) instruction_simplifier$after_gvn (before)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRem(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  private static long $noinline$IntDivRem(int v, int s) {
+    int q = v / s;
+    int r = v % s;
+    return ((long)q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntRemDiv(int, int) instruction_simplifier$after_gvn (before)
+  /// CHECK:           Rem
+  /// CHECK-NEXT:      Div
+  //
+  /// CHECK-START: long Main.$noinline$IntRemDiv(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  private static long $noinline$IntRemDiv(int v, int s) {
+    int r = v % s;
+    int q = v / s;
+    return ((long)q << 32) | r;
+  }
+
+  // A test case to check:
+  //  HDiv with the same inputs as HRem but in another basic block is not reused.
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRem(int, int, boolean) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$IntDivRem(int, int, boolean) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  private static long $noinline$IntDivRem(int v, int s, boolean do_division) {
+    long result = 0;
+    if (do_division) {
+      int q = v / s;
+      result = (long)q << 32;
+    }
+    int r = v % s;
+    return result | r;
+  }
+
+  // A test case to check:
+  //  If HRem is in a loop, the instruction simplifier postpones its optimization till
+  //  loop analysis/optimizations are done.
+  //
+  /// CHECK-START: int Main.$noinline$IntRemBy18InLoop(int) instruction_simplifier (before)
+  /// CHECK:           Div loop:B{{\d+}}
+  /// CHECK-NEXT:      Rem loop:B{{\d+}}
+  //
+  /// CHECK-START: int Main.$noinline$IntRemBy18InLoop(int) instruction_simplifier (after)
+  /// CHECK:           Div loop:B{{\d+}}
+  /// CHECK-NEXT:      Rem loop:B{{\d+}}
+  //
+  /// CHECK-START: int Main.$noinline$IntRemBy18InLoop(int) instruction_simplifier$after_bce (before)
+  /// CHECK:           Div loop:B{{\d+}}
+  /// CHECK-NEXT:      Rem loop:B{{\d+}}
+  //
+  /// CHECK-START: int Main.$noinline$IntRemBy18InLoop(int) instruction_simplifier$after_bce (after)
+  /// CHECK-NOT:       Rem
+  /// CHECK:           Div loop:B{{\d+}}
+  /// CHECK-NEXT:      Mul loop:B{{\d+}}
+  /// CHECK-NEXT:      Sub loop:B{{\d+}}
+  private static int $noinline$IntRemBy18InLoop(int v) {
+    int[] values = new int[v];
+    for (int i = 0; i < values.length; ++i) {
+      int q = i / 18;
+      int r = i % 18;
+      values[i] = q + r;
+    }
+    return values[v - 1];
+  }
+
+  // A test case to check:
+  //  FP type HRem is not optimized by the instruction simplifier.
+  //
+  /// CHECK-START: float Main.$noinline$FloatRemBy18(float) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  //
+  /// CHECK-START: float Main.$noinline$FloatRemBy18(float) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  private static float $noinline$FloatRemBy18(float v) {
+    float q = v / 18.0f;
+    float r = v % 18.0f;
+    return q + r;
+  }
+
+  // A test case to check:
+  //  FP type HRem is not optimized by the instruction simplifier.
+  //
+  /// CHECK-START: double Main.$noinline$DoubleRemBy18(double) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  //
+  /// CHECK-START: double Main.$noinline$DoubleRemBy18(double) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  private static double $noinline$DoubleRemBy18(double v) {
+    double q = v / 18.0;
+    double r = v % 18.0;
+    return q + r;
+  }
+
+  // A test case to check:
+  //  HRem with a divisor of power 2 is not optimized by the instruction simplifier because
+  //  the case is optimized by the code generator.
+  //
+  /// CHECK-START: int Main.$noinline$IntRemByIntMin(int) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  //
+  /// CHECK-START: int Main.$noinline$IntRemByIntMin(int) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  private static int $noinline$IntRemByIntMin(int v) {
+    int q = v / Integer.MIN_VALUE;
+    int r = v % Integer.MIN_VALUE;
+    return q + r;
+  }
+
+  private static void remLong() {
+    expectEquals(1L, $noinline$LongDivRemBy18(1L));
+    expectEquals(1L << 32 | 2L, $noinline$LongDivRemBy18(20L));
+
+    expectEquals(1L, $noinline$LongRemDivBy18(1L));
+    expectEquals(1L << 32 | 2L, $noinline$LongRemDivBy18(20L));
+
+    expectEquals(1L, $noinline$LongDivRemBy18(1L, false));
+    expectEquals(1L << 32 | 2L, $noinline$LongDivRemBy18(20L, true));
+
+    expectEquals(new long[] {0L, 1L}, $noinline$LongDivRemByMinus18(1));
+    expectEquals(new long[] {0L, -1L}, $noinline$LongDivRemByMinus18(-1));
+    expectEquals(new long[] {-1L, 2L}, $noinline$LongDivRemByMinus18(20));
+    expectEquals(new long[] {1L, -2L}, $noinline$LongDivRemByMinus18(-20));
+
+    expectEquals(new long[] {0L, 0L}, $noinline$LongDivRemBy5(0));
+    expectEquals(new long[] {0L, 1L}, $noinline$LongDivRemBy5(1));
+    expectEquals(new long[] {1L, 0L}, $noinline$LongDivRemBy5(5));
+    expectEquals(new long[] {1L, 1L}, $noinline$LongDivRemBy5(6));
+    expectEquals(new long[] {-1L, -1L}, $noinline$LongDivRemBy5(-6));
+    expectEquals(new long[] {-1L, 0L}, $noinline$LongDivRemBy5(-5));
+    expectEquals(new long[] {0L, -1L}, $noinline$LongDivRemBy5(-1));
+
+    expectEquals(new long[] {0L, 0L}, $noinline$LongDivRemByMinus5(0));
+    expectEquals(new long[] {0L, 1L}, $noinline$LongDivRemByMinus5(1));
+    expectEquals(new long[] {-1L, 0L}, $noinline$LongDivRemByMinus5(5));
+    expectEquals(new long[] {-1L, 1L}, $noinline$LongDivRemByMinus5(6));
+    expectEquals(new long[] {1L, -1L}, $noinline$LongDivRemByMinus5(-6));
+    expectEquals(new long[] {1L, 0L}, $noinline$LongDivRemByMinus5(-5));
+    expectEquals(new long[] {0L, -1L}, $noinline$LongDivRemByMinus5(-1));
+
+    expectEquals(new long[] {0L, 0L}, $noinline$LongDivRemBy7(0));
+    expectEquals(new long[] {0L, 1L}, $noinline$LongDivRemBy7(1));
+    expectEquals(new long[] {1L, 0L}, $noinline$LongDivRemBy7(7));
+    expectEquals(new long[] {1L, 1L}, $noinline$LongDivRemBy7(8));
+    expectEquals(new long[] {-1L, -1L}, $noinline$LongDivRemBy7(-8));
+    expectEquals(new long[] {-1L, 0L}, $noinline$LongDivRemBy7(-7));
+    expectEquals(new long[] {0L, -1L}, $noinline$LongDivRemBy7(-1));
+
+    expectEquals(new long[] {0L, 0L}, $noinline$LongDivRemByMinus7(0));
+    expectEquals(new long[] {0L, 1L}, $noinline$LongDivRemByMinus7(1));
+    expectEquals(new long[] {-1L, 0L}, $noinline$LongDivRemByMinus7(7));
+    expectEquals(new long[] {-1L, 1L}, $noinline$LongDivRemByMinus7(8));
+    expectEquals(new long[] {1L, -1L}, $noinline$LongDivRemByMinus7(-8));
+    expectEquals(new long[] {1L, 0L}, $noinline$LongDivRemByMinus7(-7));
+    expectEquals(new long[] {0L, -1L}, $noinline$LongDivRemByMinus7(-1));
+
+    expectEquals(new long[] {0L, 0L}, $noinline$LongDivRemByMaxLong(0));
+    expectEquals(new long[] {0L, 1L}, $noinline$LongDivRemByMaxLong(1));
+    expectEquals(new long[] {1L, 0L}, $noinline$LongDivRemByMaxLong(Long.MAX_VALUE));
+    expectEquals(new long[] {0L, Long.MAX_VALUE - 1},
+                 $noinline$LongDivRemByMaxLong(Long.MAX_VALUE - 1));
+    expectEquals(new long[] {-1L, -1L}, $noinline$LongDivRemByMaxLong(Long.MIN_VALUE));
+    expectEquals(new long[] {0L, -1L}, $noinline$LongDivRemByMaxLong(-1));
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$LongDivRemBy18(long) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$LongDivRemBy18(long) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  private static long $noinline$LongDivRemBy18(long v) {
+    long q = v / 18L;
+    long r = v % 18L;
+    return (q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemByMinus18(long) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemByMinus18(long) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long[] Main.$noinline$LongDivRemByMinus18(long) disassembly (after)
+  /// CHECK:                 smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
+  /// CHECK-NEXT:            add   x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK:                 msub  x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long[] $noinline$LongDivRemByMinus18(long v) {
+    long q = v / -18L;
+    long r = v % -18L;
+    return new long[] {q, r};
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$LongRemDivBy18(long) instruction_simplifier (before)
+  /// CHECK:           Rem
+  /// CHECK:           Div
+  //
+  /// CHECK-START: long Main.$noinline$LongRemDivBy18(long) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  private static long $noinline$LongRemDivBy18(long v) {
+    long r = v % 18L;
+    long q = v / 18L;
+    return (q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemBy5(long) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemBy5(long) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Shl
+  /// CHECK-NEXT:      Add
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long[] Main.$noinline$LongDivRemBy5(long) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #1
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK:                 add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #2
+  /// CHECK:                 sub x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long[] $noinline$LongDivRemBy5(long v) {
+    long q = v / 5L;
+    long r = v % 5L;
+    return new long[] {q, r};
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemByMinus5(long) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemByMinus5(long) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long[] Main.$noinline$LongDivRemByMinus5(long) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #1
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK:                 msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long[] $noinline$LongDivRemByMinus5(long v) {
+    long q = v / -5L;
+    long r = v % -5L;
+    return new long[] {q, r};
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemBy7(long) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemBy7(long) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Shl
+  /// CHECK-NEXT:      Sub
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long[] Main.$noinline$LongDivRemBy7(long) instruction_simplifier_arm64 (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            DataProcWithShifterOp
+  /// CHECK-NEXT:            Add
+  //
+  /// CHECK-START-ARM64: long[] Main.$noinline$LongDivRemBy7(long) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #1
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK:                 sub x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #3
+  /// CHECK:                 add x{{\d+}}, x{{\d+}}, x{{\d+}}
+  //
+  /// CHECK-START-ARM: long[] Main.$noinline$LongDivRemBy7(long) instruction_simplifier_arm (after)
+  /// CHECK:               Div
+  /// CHECK-NEXT:          DataProcWithShifterOp
+  /// CHECK-NEXT:          Add
+  //
+  /// CHECK-START-ARM: long[] Main.$noinline$LongDivRemBy7(long) disassembly (after)
+  /// CHECK:               blx lr
+  //  CHECK:               lsl ip, r{{\d}}, #3
+  //  CHECK-NEXT:          orr       ip, r{{\d}}, lsr #29
+  //  CHECK-NEXT:          sub       r{{\d}}, r{{\d}}, r{{\d}}, lsl #3
+  //  CHECK-NEXT:          sbc{{s?}} r{{\d}}, r{{\d}}, ip
+  /// CHECK:               add{{s?}} r{{\d}}, r{{\d}}
+  /// CHECK-NEXT:          adc{{s?}} r{{\d}}, r{{\d}}
+  private static long[] $noinline$LongDivRemBy7(long v) {
+    long q = v / 7L;
+    long r = v % 7L;
+    return new long[] {q, r};
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemByMinus7(long) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemByMinus7(long) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long[] Main.$noinline$LongDivRemByMinus7(long) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #1
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK:                 msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
+  private static long[] $noinline$LongDivRemByMinus7(long v) {
+    long q = v / -7L;
+    long r = v % -7L;
+    return new long[] {q, r};
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemByMaxLong(long) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long[] Main.$noinline$LongDivRemByMaxLong(long) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Shl
+  /// CHECK-NEXT:      Sub
+  /// CHECK-NEXT:      Sub
+  //
+  /// CHECK-START-ARM64: long[] Main.$noinline$LongDivRemByMaxLong(long) instruction_simplifier_arm64 (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      DataProcWithShifterOp
+  /// CHECK-NEXT:      Add
+  //
+  /// CHECK-START-ARM64: long[] Main.$noinline$LongDivRemByMaxLong(long) disassembly (after)
+  /// CHECK:                 asr x{{\d+}}, x{{\d+}}, #61
+  /// CHECK-NEXT:            add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
+  /// CHECK:                 sub x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #63
+  /// CHECK:                 add x{{\d+}}, x{{\d+}}, x{{\d+}}
+  //
+  /// CHECK-START-ARM: long[] Main.$noinline$LongDivRemByMaxLong(long) instruction_simplifier_arm (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      DataProcWithShifterOp
+  /// CHECK-NEXT:      Add
+  //
+  /// CHECK-START-ARM: long[] Main.$noinline$LongDivRemByMaxLong(long) disassembly (after)
+  /// CHECK:               blx lr
+  //  CHECK:               sub       r{{\d}}, r{{\d}}, r{{\d}}, lsl #31
+  //  CHECK-NEXT:          mov{{s?}} r{{\d}}, r{{\d}}
+  /// CHECK:               add{{s?}} r{{\d}}, r{{\d}}
+  /// CHECK-NEXT:          adc{{s?}} r{{\d}}, r{{\d}}
+  private static long[] $noinline$LongDivRemByMaxLong(long v) {
+    long q = v / Long.MAX_VALUE;
+    long r = v % Long.MAX_VALUE;
+    return new long[] {q, r};
+  }
+
+  // A test case to check:
+  //  HDiv with the same inputs as HRem but in another basic block is not reused.
+  //
+  /// CHECK-START: long Main.$noinline$LongDivRemBy18(long, boolean) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$LongDivRemBy18(long, boolean) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  private static long $noinline$LongDivRemBy18(long v, boolean do_division) {
+    long result = 0;
+    if (do_division) {
+      long q = v / 18L;
+      result = q << 32;
+    }
+    long r = v % 18L;
+    return result | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$LongDivRem(long, long) instruction_simplifier$after_gvn (before)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  //
+  /// CHECK-START: long Main.$noinline$LongDivRem(long, long) instruction_simplifier$after_gvn (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  private static long $noinline$LongDivRem(long v, long s) {
+    long q = v / s;
+    long r = v % s;
+    return (q << 32) | r;
+  }
+
+  // A test case to check:
+  //  If there is HDiv with the same inputs as HRem, it is reused.
+  //
+  /// CHECK-START: long Main.$noinline$LongRemDiv(long, long) instruction_simplifier$after_gvn (before)
+  /// CHECK:           Rem
+  /// CHECK-NEXT:      Div
+  //
+  /// CHECK-START: long Main.$noinline$LongRemDiv(long, long) instruction_simplifier$after_gvn (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Mul
+  /// CHECK-NEXT:      Sub
+  private static long $noinline$LongRemDiv(long v, long s) {
+    long r = v % s;
+    long q = v / s;
+    return (q << 32) | r;
+  }
+
+  // A test case to check:
+  //  HDiv with the same inputs as HRem but in another basic block is not reused.
+  //
+  /// CHECK-START: long Main.$noinline$LongDivRem(long, long, boolean) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  //
+  /// CHECK-START: long Main.$noinline$LongDivRem(long, long, boolean) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK:           Rem
+  private static long $noinline$LongDivRem(long v, long s, boolean do_division) {
+    long result = 0;
+    if (do_division) {
+      long q = v / s;
+      result = q << 32;
+    }
+    long r = v % s;
+    return result | r;
+  }
+
+  // A test case to check:
+  //  If HRem is in a loop, the instruction simplifier postpones its optimization till
+  //  loop analysis/optimizations are done.
+  //
+  /// CHECK-START: long Main.$noinline$LongRemBy18InLoop(long) instruction_simplifier (before)
+  /// CHECK:           Div loop:B{{\d+}}
+  /// CHECK-NEXT:      Rem loop:B{{\d+}}
+  //
+  /// CHECK-START: long Main.$noinline$LongRemBy18InLoop(long) instruction_simplifier (after)
+  /// CHECK:           Div loop:B{{\d+}}
+  /// CHECK-NEXT:      Rem loop:B{{\d+}}
+  //
+  /// CHECK-START: long Main.$noinline$LongRemBy18InLoop(long) instruction_simplifier$after_bce (before)
+  /// CHECK:           Div loop:B{{\d+}}
+  /// CHECK-NEXT:      Rem loop:B{{\d+}}
+  //
+  /// CHECK-START: long Main.$noinline$LongRemBy18InLoop(long) instruction_simplifier$after_bce (after)
+  /// CHECK-NOT:       Rem
+  /// CHECK:           Div loop:B{{\d+}}
+  /// CHECK-NEXT:      Mul loop:B{{\d+}}
+  /// CHECK-NEXT:      Sub loop:B{{\d+}}
+  private static long $noinline$LongRemBy18InLoop(long v) {
+    long[] values = new long[(int)v];
+    for (int i = 0; i < values.length; ++i) {
+      long d = (long)i;
+      long q = d / 18L;
+      long r = d % 18L;
+      values[i] = q + r;
+    }
+    return values[values.length - 1];
+  }
+
+  // A test case to check:
+  //  HRem with a divisor of power 2 is not optimized by the instruction simplifier because
+  //  the case is optimized by the code generator.
+  //
+  /// CHECK-START: long Main.$noinline$LongRemByLongMin(long) instruction_simplifier (before)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  //
+  /// CHECK-START: long Main.$noinline$LongRemByLongMin(long) instruction_simplifier (after)
+  /// CHECK:           Div
+  /// CHECK-NEXT:      Rem
+  private static long $noinline$LongRemByLongMin(long v) {
+    long q = v / Long.MIN_VALUE;
+    long r = v % Long.MIN_VALUE;
+    return q + r;
+  }
+
+  public static void main(String args[]) {
+    remInt();
+    remLong();
+  }
+}
diff --git a/test/411-optimizing-arith/Android.bp b/test/411-optimizing-arith/Android.bp
new file mode 100644
index 0000000..1a9b204
--- /dev/null
+++ b/test/411-optimizing-arith/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `411-optimizing-arith`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-411-optimizing-arith",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-411-optimizing-arith-expected-stdout",
+        ":art-run-test-411-optimizing-arith-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-411-optimizing-arith-expected-stdout",
+    out: ["art-run-test-411-optimizing-arith-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-411-optimizing-arith-expected-stderr",
+    out: ["art-run-test-411-optimizing-arith-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/411-optimizing-arith/expected.txt b/test/411-optimizing-arith/expected-stderr.txt
similarity index 100%
rename from test/411-optimizing-arith/expected.txt
rename to test/411-optimizing-arith/expected-stderr.txt
diff --git a/test/411-optimizing-arith/expected.txt b/test/411-optimizing-arith/expected-stdout.txt
similarity index 100%
copy from test/411-optimizing-arith/expected.txt
copy to test/411-optimizing-arith/expected-stdout.txt
diff --git a/test/412-new-array/expected.txt b/test/412-new-array/expected-stderr.txt
similarity index 100%
rename from test/412-new-array/expected.txt
rename to test/412-new-array/expected-stderr.txt
diff --git a/test/412-new-array/expected.txt b/test/412-new-array/expected-stdout.txt
similarity index 100%
copy from test/412-new-array/expected.txt
copy to test/412-new-array/expected-stdout.txt
diff --git a/test/413-regalloc-regression/Android.bp b/test/413-regalloc-regression/Android.bp
new file mode 100644
index 0000000..6ff8d95
--- /dev/null
+++ b/test/413-regalloc-regression/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `413-regalloc-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-413-regalloc-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-413-regalloc-regression-expected-stdout",
+        ":art-run-test-413-regalloc-regression-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-413-regalloc-regression-expected-stdout",
+    out: ["art-run-test-413-regalloc-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-413-regalloc-regression-expected-stderr",
+    out: ["art-run-test-413-regalloc-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/413-regalloc-regression/expected.txt b/test/413-regalloc-regression/expected-stderr.txt
similarity index 100%
rename from test/413-regalloc-regression/expected.txt
rename to test/413-regalloc-regression/expected-stderr.txt
diff --git a/test/413-regalloc-regression/expected.txt b/test/413-regalloc-regression/expected-stdout.txt
similarity index 100%
copy from test/413-regalloc-regression/expected.txt
copy to test/413-regalloc-regression/expected-stdout.txt
diff --git a/test/414-static-fields/Android.bp b/test/414-static-fields/Android.bp
new file mode 100644
index 0000000..7f105d4
--- /dev/null
+++ b/test/414-static-fields/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `414-static-fields`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-414-static-fields",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-414-static-fields-expected-stdout",
+        ":art-run-test-414-static-fields-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-414-static-fields-expected-stdout",
+    out: ["art-run-test-414-static-fields-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-414-static-fields-expected-stderr",
+    out: ["art-run-test-414-static-fields-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/414-static-fields/expected.txt b/test/414-static-fields/expected-stderr.txt
similarity index 100%
rename from test/414-static-fields/expected.txt
rename to test/414-static-fields/expected-stderr.txt
diff --git a/test/414-static-fields/expected.txt b/test/414-static-fields/expected-stdout.txt
similarity index 100%
copy from test/414-static-fields/expected.txt
copy to test/414-static-fields/expected-stdout.txt
diff --git a/test/416-optimizing-arith-not/expected.txt b/test/416-optimizing-arith-not/expected-stderr.txt
similarity index 100%
rename from test/416-optimizing-arith-not/expected.txt
rename to test/416-optimizing-arith-not/expected-stderr.txt
diff --git a/test/416-optimizing-arith-not/expected.txt b/test/416-optimizing-arith-not/expected-stdout.txt
similarity index 100%
copy from test/416-optimizing-arith-not/expected.txt
copy to test/416-optimizing-arith-not/expected-stdout.txt
diff --git a/test/418-const-string/Android.bp b/test/418-const-string/Android.bp
new file mode 100644
index 0000000..8a57f20
--- /dev/null
+++ b/test/418-const-string/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `418-const-string`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-418-const-string",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-418-const-string-expected-stdout",
+        ":art-run-test-418-const-string-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-418-const-string-expected-stdout",
+    out: ["art-run-test-418-const-string-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-418-const-string-expected-stderr",
+    out: ["art-run-test-418-const-string-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/304-method-tracing/expected.txt b/test/418-const-string/expected-stderr.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/418-const-string/expected-stderr.txt
diff --git a/test/418-const-string/expected.txt b/test/418-const-string/expected-stdout.txt
similarity index 100%
rename from test/418-const-string/expected.txt
rename to test/418-const-string/expected-stdout.txt
diff --git a/test/419-long-parameter/Android.bp b/test/419-long-parameter/Android.bp
new file mode 100644
index 0000000..5e3c417
--- /dev/null
+++ b/test/419-long-parameter/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `419-long-parameter`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-419-long-parameter",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-419-long-parameter-expected-stdout",
+        ":art-run-test-419-long-parameter-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-419-long-parameter-expected-stdout",
+    out: ["art-run-test-419-long-parameter-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-419-long-parameter-expected-stderr",
+    out: ["art-run-test-419-long-parameter-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/419-long-parameter/expected.txt b/test/419-long-parameter/expected-stderr.txt
similarity index 100%
rename from test/419-long-parameter/expected.txt
rename to test/419-long-parameter/expected-stderr.txt
diff --git a/test/419-long-parameter/expected.txt b/test/419-long-parameter/expected-stdout.txt
similarity index 100%
copy from test/419-long-parameter/expected.txt
copy to test/419-long-parameter/expected-stdout.txt
diff --git a/test/420-const-class/Android.bp b/test/420-const-class/Android.bp
new file mode 100644
index 0000000..11cd557
--- /dev/null
+++ b/test/420-const-class/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `420-const-class`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-420-const-class",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-420-const-class-expected-stdout",
+        ":art-run-test-420-const-class-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-420-const-class-expected-stdout",
+    out: ["art-run-test-420-const-class-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-420-const-class-expected-stderr",
+    out: ["art-run-test-420-const-class-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/606-erroneous-class/expected.txt b/test/420-const-class/expected-stderr.txt
similarity index 100%
copy from test/606-erroneous-class/expected.txt
copy to test/420-const-class/expected-stderr.txt
diff --git a/test/420-const-class/expected.txt b/test/420-const-class/expected-stdout.txt
similarity index 100%
rename from test/420-const-class/expected.txt
rename to test/420-const-class/expected-stdout.txt
diff --git a/test/421-exceptions/Android.bp b/test/421-exceptions/Android.bp
new file mode 100644
index 0000000..d1ee341
--- /dev/null
+++ b/test/421-exceptions/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `421-exceptions`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-421-exceptions",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-421-exceptions-expected-stdout",
+        ":art-run-test-421-exceptions-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-421-exceptions-expected-stdout",
+    out: ["art-run-test-421-exceptions-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-421-exceptions-expected-stderr",
+    out: ["art-run-test-421-exceptions-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/421-large-frame/expected.txt b/test/421-exceptions/expected-stderr.txt
similarity index 100%
copy from test/421-large-frame/expected.txt
copy to test/421-exceptions/expected-stderr.txt
diff --git a/test/421-exceptions/expected.txt b/test/421-exceptions/expected-stdout.txt
similarity index 100%
rename from test/421-exceptions/expected.txt
rename to test/421-exceptions/expected-stdout.txt
diff --git a/test/421-large-frame/Android.bp b/test/421-large-frame/Android.bp
new file mode 100644
index 0000000..68f12f8
--- /dev/null
+++ b/test/421-large-frame/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `421-large-frame`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-421-large-frame",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-421-large-frame-expected-stdout",
+        ":art-run-test-421-large-frame-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-421-large-frame-expected-stdout",
+    out: ["art-run-test-421-large-frame-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-421-large-frame-expected-stderr",
+    out: ["art-run-test-421-large-frame-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/421-large-frame/expected.txt b/test/421-large-frame/expected-stderr.txt
similarity index 100%
rename from test/421-large-frame/expected.txt
rename to test/421-large-frame/expected-stderr.txt
diff --git a/test/421-large-frame/expected.txt b/test/421-large-frame/expected-stdout.txt
similarity index 100%
copy from test/421-large-frame/expected.txt
copy to test/421-large-frame/expected-stdout.txt
diff --git a/test/421-large-frame/src/Main.java b/test/421-large-frame/src/Main.java
index 6717ba0..5f986a5 100644
--- a/test/421-large-frame/src/Main.java
+++ b/test/421-large-frame/src/Main.java
@@ -25,515 +25,515 @@
   }
 
   public static void main(String[] args) {
-    long dummy = 0L;
+    long value = 0L;
     // Sum[i = 0..499](i) = 499 * 500 / 2 = 124750L.
-    assertEquals(124750L, $opt$LargeFrame(dummy));
+    assertEquals(124750L, $opt$LargeFrame(value));
   }
 
-  static long $opt$LargeFrame(long dummy) {
-    // The argument `dummy` is used to defeat the constant folding
+  static long $opt$LargeFrame(long value) {
+    // The argument `value` is used to defeat the constant folding
     // optimization and force the compiler to allocate these variables
     // on the stack.
-    long l0 = 0L + dummy;
-    long l1 = 1L + dummy;
-    long l2 = 2L + dummy;
-    long l3 = 3L + dummy;
-    long l4 = 4L + dummy;
-    long l5 = 5L + dummy;
-    long l6 = 6L + dummy;
-    long l7 = 7L + dummy;
-    long l8 = 8L + dummy;
-    long l9 = 9L + dummy;
-    long l10 = 10L + dummy;
-    long l11 = 11L + dummy;
-    long l12 = 12L + dummy;
-    long l13 = 13L + dummy;
-    long l14 = 14L + dummy;
-    long l15 = 15L + dummy;
-    long l16 = 16L + dummy;
-    long l17 = 17L + dummy;
-    long l18 = 18L + dummy;
-    long l19 = 19L + dummy;
-    long l20 = 20L + dummy;
-    long l21 = 21L + dummy;
-    long l22 = 22L + dummy;
-    long l23 = 23L + dummy;
-    long l24 = 24L + dummy;
-    long l25 = 25L + dummy;
-    long l26 = 26L + dummy;
-    long l27 = 27L + dummy;
-    long l28 = 28L + dummy;
-    long l29 = 29L + dummy;
-    long l30 = 30L + dummy;
-    long l31 = 31L + dummy;
-    long l32 = 32L + dummy;
-    long l33 = 33L + dummy;
-    long l34 = 34L + dummy;
-    long l35 = 35L + dummy;
-    long l36 = 36L + dummy;
-    long l37 = 37L + dummy;
-    long l38 = 38L + dummy;
-    long l39 = 39L + dummy;
-    long l40 = 40L + dummy;
-    long l41 = 41L + dummy;
-    long l42 = 42L + dummy;
-    long l43 = 43L + dummy;
-    long l44 = 44L + dummy;
-    long l45 = 45L + dummy;
-    long l46 = 46L + dummy;
-    long l47 = 47L + dummy;
-    long l48 = 48L + dummy;
-    long l49 = 49L + dummy;
-    long l50 = 50L + dummy;
-    long l51 = 51L + dummy;
-    long l52 = 52L + dummy;
-    long l53 = 53L + dummy;
-    long l54 = 54L + dummy;
-    long l55 = 55L + dummy;
-    long l56 = 56L + dummy;
-    long l57 = 57L + dummy;
-    long l58 = 58L + dummy;
-    long l59 = 59L + dummy;
-    long l60 = 60L + dummy;
-    long l61 = 61L + dummy;
-    long l62 = 62L + dummy;
-    long l63 = 63L + dummy;
-    long l64 = 64L + dummy;
-    long l65 = 65L + dummy;
-    long l66 = 66L + dummy;
-    long l67 = 67L + dummy;
-    long l68 = 68L + dummy;
-    long l69 = 69L + dummy;
-    long l70 = 70L + dummy;
-    long l71 = 71L + dummy;
-    long l72 = 72L + dummy;
-    long l73 = 73L + dummy;
-    long l74 = 74L + dummy;
-    long l75 = 75L + dummy;
-    long l76 = 76L + dummy;
-    long l77 = 77L + dummy;
-    long l78 = 78L + dummy;
-    long l79 = 79L + dummy;
-    long l80 = 80L + dummy;
-    long l81 = 81L + dummy;
-    long l82 = 82L + dummy;
-    long l83 = 83L + dummy;
-    long l84 = 84L + dummy;
-    long l85 = 85L + dummy;
-    long l86 = 86L + dummy;
-    long l87 = 87L + dummy;
-    long l88 = 88L + dummy;
-    long l89 = 89L + dummy;
-    long l90 = 90L + dummy;
-    long l91 = 91L + dummy;
-    long l92 = 92L + dummy;
-    long l93 = 93L + dummy;
-    long l94 = 94L + dummy;
-    long l95 = 95L + dummy;
-    long l96 = 96L + dummy;
-    long l97 = 97L + dummy;
-    long l98 = 98L + dummy;
-    long l99 = 99L + dummy;
-    long l100 = 100L + dummy;
-    long l101 = 101L + dummy;
-    long l102 = 102L + dummy;
-    long l103 = 103L + dummy;
-    long l104 = 104L + dummy;
-    long l105 = 105L + dummy;
-    long l106 = 106L + dummy;
-    long l107 = 107L + dummy;
-    long l108 = 108L + dummy;
-    long l109 = 109L + dummy;
-    long l110 = 110L + dummy;
-    long l111 = 111L + dummy;
-    long l112 = 112L + dummy;
-    long l113 = 113L + dummy;
-    long l114 = 114L + dummy;
-    long l115 = 115L + dummy;
-    long l116 = 116L + dummy;
-    long l117 = 117L + dummy;
-    long l118 = 118L + dummy;
-    long l119 = 119L + dummy;
-    long l120 = 120L + dummy;
-    long l121 = 121L + dummy;
-    long l122 = 122L + dummy;
-    long l123 = 123L + dummy;
-    long l124 = 124L + dummy;
-    long l125 = 125L + dummy;
-    long l126 = 126L + dummy;
-    long l127 = 127L + dummy;
-    long l128 = 128L + dummy;
-    long l129 = 129L + dummy;
-    long l130 = 130L + dummy;
-    long l131 = 131L + dummy;
-    long l132 = 132L + dummy;
-    long l133 = 133L + dummy;
-    long l134 = 134L + dummy;
-    long l135 = 135L + dummy;
-    long l136 = 136L + dummy;
-    long l137 = 137L + dummy;
-    long l138 = 138L + dummy;
-    long l139 = 139L + dummy;
-    long l140 = 140L + dummy;
-    long l141 = 141L + dummy;
-    long l142 = 142L + dummy;
-    long l143 = 143L + dummy;
-    long l144 = 144L + dummy;
-    long l145 = 145L + dummy;
-    long l146 = 146L + dummy;
-    long l147 = 147L + dummy;
-    long l148 = 148L + dummy;
-    long l149 = 149L + dummy;
-    long l150 = 150L + dummy;
-    long l151 = 151L + dummy;
-    long l152 = 152L + dummy;
-    long l153 = 153L + dummy;
-    long l154 = 154L + dummy;
-    long l155 = 155L + dummy;
-    long l156 = 156L + dummy;
-    long l157 = 157L + dummy;
-    long l158 = 158L + dummy;
-    long l159 = 159L + dummy;
-    long l160 = 160L + dummy;
-    long l161 = 161L + dummy;
-    long l162 = 162L + dummy;
-    long l163 = 163L + dummy;
-    long l164 = 164L + dummy;
-    long l165 = 165L + dummy;
-    long l166 = 166L + dummy;
-    long l167 = 167L + dummy;
-    long l168 = 168L + dummy;
-    long l169 = 169L + dummy;
-    long l170 = 170L + dummy;
-    long l171 = 171L + dummy;
-    long l172 = 172L + dummy;
-    long l173 = 173L + dummy;
-    long l174 = 174L + dummy;
-    long l175 = 175L + dummy;
-    long l176 = 176L + dummy;
-    long l177 = 177L + dummy;
-    long l178 = 178L + dummy;
-    long l179 = 179L + dummy;
-    long l180 = 180L + dummy;
-    long l181 = 181L + dummy;
-    long l182 = 182L + dummy;
-    long l183 = 183L + dummy;
-    long l184 = 184L + dummy;
-    long l185 = 185L + dummy;
-    long l186 = 186L + dummy;
-    long l187 = 187L + dummy;
-    long l188 = 188L + dummy;
-    long l189 = 189L + dummy;
-    long l190 = 190L + dummy;
-    long l191 = 191L + dummy;
-    long l192 = 192L + dummy;
-    long l193 = 193L + dummy;
-    long l194 = 194L + dummy;
-    long l195 = 195L + dummy;
-    long l196 = 196L + dummy;
-    long l197 = 197L + dummy;
-    long l198 = 198L + dummy;
-    long l199 = 199L + dummy;
-    long l200 = 200L + dummy;
-    long l201 = 201L + dummy;
-    long l202 = 202L + dummy;
-    long l203 = 203L + dummy;
-    long l204 = 204L + dummy;
-    long l205 = 205L + dummy;
-    long l206 = 206L + dummy;
-    long l207 = 207L + dummy;
-    long l208 = 208L + dummy;
-    long l209 = 209L + dummy;
-    long l210 = 210L + dummy;
-    long l211 = 211L + dummy;
-    long l212 = 212L + dummy;
-    long l213 = 213L + dummy;
-    long l214 = 214L + dummy;
-    long l215 = 215L + dummy;
-    long l216 = 216L + dummy;
-    long l217 = 217L + dummy;
-    long l218 = 218L + dummy;
-    long l219 = 219L + dummy;
-    long l220 = 220L + dummy;
-    long l221 = 221L + dummy;
-    long l222 = 222L + dummy;
-    long l223 = 223L + dummy;
-    long l224 = 224L + dummy;
-    long l225 = 225L + dummy;
-    long l226 = 226L + dummy;
-    long l227 = 227L + dummy;
-    long l228 = 228L + dummy;
-    long l229 = 229L + dummy;
-    long l230 = 230L + dummy;
-    long l231 = 231L + dummy;
-    long l232 = 232L + dummy;
-    long l233 = 233L + dummy;
-    long l234 = 234L + dummy;
-    long l235 = 235L + dummy;
-    long l236 = 236L + dummy;
-    long l237 = 237L + dummy;
-    long l238 = 238L + dummy;
-    long l239 = 239L + dummy;
-    long l240 = 240L + dummy;
-    long l241 = 241L + dummy;
-    long l242 = 242L + dummy;
-    long l243 = 243L + dummy;
-    long l244 = 244L + dummy;
-    long l245 = 245L + dummy;
-    long l246 = 246L + dummy;
-    long l247 = 247L + dummy;
-    long l248 = 248L + dummy;
-    long l249 = 249L + dummy;
-    long l250 = 250L + dummy;
-    long l251 = 251L + dummy;
-    long l252 = 252L + dummy;
-    long l253 = 253L + dummy;
-    long l254 = 254L + dummy;
-    long l255 = 255L + dummy;
-    long l256 = 256L + dummy;
-    long l257 = 257L + dummy;
-    long l258 = 258L + dummy;
-    long l259 = 259L + dummy;
-    long l260 = 260L + dummy;
-    long l261 = 261L + dummy;
-    long l262 = 262L + dummy;
-    long l263 = 263L + dummy;
-    long l264 = 264L + dummy;
-    long l265 = 265L + dummy;
-    long l266 = 266L + dummy;
-    long l267 = 267L + dummy;
-    long l268 = 268L + dummy;
-    long l269 = 269L + dummy;
-    long l270 = 270L + dummy;
-    long l271 = 271L + dummy;
-    long l272 = 272L + dummy;
-    long l273 = 273L + dummy;
-    long l274 = 274L + dummy;
-    long l275 = 275L + dummy;
-    long l276 = 276L + dummy;
-    long l277 = 277L + dummy;
-    long l278 = 278L + dummy;
-    long l279 = 279L + dummy;
-    long l280 = 280L + dummy;
-    long l281 = 281L + dummy;
-    long l282 = 282L + dummy;
-    long l283 = 283L + dummy;
-    long l284 = 284L + dummy;
-    long l285 = 285L + dummy;
-    long l286 = 286L + dummy;
-    long l287 = 287L + dummy;
-    long l288 = 288L + dummy;
-    long l289 = 289L + dummy;
-    long l290 = 290L + dummy;
-    long l291 = 291L + dummy;
-    long l292 = 292L + dummy;
-    long l293 = 293L + dummy;
-    long l294 = 294L + dummy;
-    long l295 = 295L + dummy;
-    long l296 = 296L + dummy;
-    long l297 = 297L + dummy;
-    long l298 = 298L + dummy;
-    long l299 = 299L + dummy;
-    long l300 = 300L + dummy;
-    long l301 = 301L + dummy;
-    long l302 = 302L + dummy;
-    long l303 = 303L + dummy;
-    long l304 = 304L + dummy;
-    long l305 = 305L + dummy;
-    long l306 = 306L + dummy;
-    long l307 = 307L + dummy;
-    long l308 = 308L + dummy;
-    long l309 = 309L + dummy;
-    long l310 = 310L + dummy;
-    long l311 = 311L + dummy;
-    long l312 = 312L + dummy;
-    long l313 = 313L + dummy;
-    long l314 = 314L + dummy;
-    long l315 = 315L + dummy;
-    long l316 = 316L + dummy;
-    long l317 = 317L + dummy;
-    long l318 = 318L + dummy;
-    long l319 = 319L + dummy;
-    long l320 = 320L + dummy;
-    long l321 = 321L + dummy;
-    long l322 = 322L + dummy;
-    long l323 = 323L + dummy;
-    long l324 = 324L + dummy;
-    long l325 = 325L + dummy;
-    long l326 = 326L + dummy;
-    long l327 = 327L + dummy;
-    long l328 = 328L + dummy;
-    long l329 = 329L + dummy;
-    long l330 = 330L + dummy;
-    long l331 = 331L + dummy;
-    long l332 = 332L + dummy;
-    long l333 = 333L + dummy;
-    long l334 = 334L + dummy;
-    long l335 = 335L + dummy;
-    long l336 = 336L + dummy;
-    long l337 = 337L + dummy;
-    long l338 = 338L + dummy;
-    long l339 = 339L + dummy;
-    long l340 = 340L + dummy;
-    long l341 = 341L + dummy;
-    long l342 = 342L + dummy;
-    long l343 = 343L + dummy;
-    long l344 = 344L + dummy;
-    long l345 = 345L + dummy;
-    long l346 = 346L + dummy;
-    long l347 = 347L + dummy;
-    long l348 = 348L + dummy;
-    long l349 = 349L + dummy;
-    long l350 = 350L + dummy;
-    long l351 = 351L + dummy;
-    long l352 = 352L + dummy;
-    long l353 = 353L + dummy;
-    long l354 = 354L + dummy;
-    long l355 = 355L + dummy;
-    long l356 = 356L + dummy;
-    long l357 = 357L + dummy;
-    long l358 = 358L + dummy;
-    long l359 = 359L + dummy;
-    long l360 = 360L + dummy;
-    long l361 = 361L + dummy;
-    long l362 = 362L + dummy;
-    long l363 = 363L + dummy;
-    long l364 = 364L + dummy;
-    long l365 = 365L + dummy;
-    long l366 = 366L + dummy;
-    long l367 = 367L + dummy;
-    long l368 = 368L + dummy;
-    long l369 = 369L + dummy;
-    long l370 = 370L + dummy;
-    long l371 = 371L + dummy;
-    long l372 = 372L + dummy;
-    long l373 = 373L + dummy;
-    long l374 = 374L + dummy;
-    long l375 = 375L + dummy;
-    long l376 = 376L + dummy;
-    long l377 = 377L + dummy;
-    long l378 = 378L + dummy;
-    long l379 = 379L + dummy;
-    long l380 = 380L + dummy;
-    long l381 = 381L + dummy;
-    long l382 = 382L + dummy;
-    long l383 = 383L + dummy;
-    long l384 = 384L + dummy;
-    long l385 = 385L + dummy;
-    long l386 = 386L + dummy;
-    long l387 = 387L + dummy;
-    long l388 = 388L + dummy;
-    long l389 = 389L + dummy;
-    long l390 = 390L + dummy;
-    long l391 = 391L + dummy;
-    long l392 = 392L + dummy;
-    long l393 = 393L + dummy;
-    long l394 = 394L + dummy;
-    long l395 = 395L + dummy;
-    long l396 = 396L + dummy;
-    long l397 = 397L + dummy;
-    long l398 = 398L + dummy;
-    long l399 = 399L + dummy;
-    long l400 = 400L + dummy;
-    long l401 = 401L + dummy;
-    long l402 = 402L + dummy;
-    long l403 = 403L + dummy;
-    long l404 = 404L + dummy;
-    long l405 = 405L + dummy;
-    long l406 = 406L + dummy;
-    long l407 = 407L + dummy;
-    long l408 = 408L + dummy;
-    long l409 = 409L + dummy;
-    long l410 = 410L + dummy;
-    long l411 = 411L + dummy;
-    long l412 = 412L + dummy;
-    long l413 = 413L + dummy;
-    long l414 = 414L + dummy;
-    long l415 = 415L + dummy;
-    long l416 = 416L + dummy;
-    long l417 = 417L + dummy;
-    long l418 = 418L + dummy;
-    long l419 = 419L + dummy;
-    long l420 = 420L + dummy;
-    long l421 = 421L + dummy;
-    long l422 = 422L + dummy;
-    long l423 = 423L + dummy;
-    long l424 = 424L + dummy;
-    long l425 = 425L + dummy;
-    long l426 = 426L + dummy;
-    long l427 = 427L + dummy;
-    long l428 = 428L + dummy;
-    long l429 = 429L + dummy;
-    long l430 = 430L + dummy;
-    long l431 = 431L + dummy;
-    long l432 = 432L + dummy;
-    long l433 = 433L + dummy;
-    long l434 = 434L + dummy;
-    long l435 = 435L + dummy;
-    long l436 = 436L + dummy;
-    long l437 = 437L + dummy;
-    long l438 = 438L + dummy;
-    long l439 = 439L + dummy;
-    long l440 = 440L + dummy;
-    long l441 = 441L + dummy;
-    long l442 = 442L + dummy;
-    long l443 = 443L + dummy;
-    long l444 = 444L + dummy;
-    long l445 = 445L + dummy;
-    long l446 = 446L + dummy;
-    long l447 = 447L + dummy;
-    long l448 = 448L + dummy;
-    long l449 = 449L + dummy;
-    long l450 = 450L + dummy;
-    long l451 = 451L + dummy;
-    long l452 = 452L + dummy;
-    long l453 = 453L + dummy;
-    long l454 = 454L + dummy;
-    long l455 = 455L + dummy;
-    long l456 = 456L + dummy;
-    long l457 = 457L + dummy;
-    long l458 = 458L + dummy;
-    long l459 = 459L + dummy;
-    long l460 = 460L + dummy;
-    long l461 = 461L + dummy;
-    long l462 = 462L + dummy;
-    long l463 = 463L + dummy;
-    long l464 = 464L + dummy;
-    long l465 = 465L + dummy;
-    long l466 = 466L + dummy;
-    long l467 = 467L + dummy;
-    long l468 = 468L + dummy;
-    long l469 = 469L + dummy;
-    long l470 = 470L + dummy;
-    long l471 = 471L + dummy;
-    long l472 = 472L + dummy;
-    long l473 = 473L + dummy;
-    long l474 = 474L + dummy;
-    long l475 = 475L + dummy;
-    long l476 = 476L + dummy;
-    long l477 = 477L + dummy;
-    long l478 = 478L + dummy;
-    long l479 = 479L + dummy;
-    long l480 = 480L + dummy;
-    long l481 = 481L + dummy;
-    long l482 = 482L + dummy;
-    long l483 = 483L + dummy;
-    long l484 = 484L + dummy;
-    long l485 = 485L + dummy;
-    long l486 = 486L + dummy;
-    long l487 = 487L + dummy;
-    long l488 = 488L + dummy;
-    long l489 = 489L + dummy;
-    long l490 = 490L + dummy;
-    long l491 = 491L + dummy;
-    long l492 = 492L + dummy;
-    long l493 = 493L + dummy;
-    long l494 = 494L + dummy;
-    long l495 = 495L + dummy;
-    long l496 = 496L + dummy;
-    long l497 = 497L + dummy;
-    long l498 = 498L + dummy;
-    long l499 = 499L + dummy;
+    long l0 = 0L + value;
+    long l1 = 1L + value;
+    long l2 = 2L + value;
+    long l3 = 3L + value;
+    long l4 = 4L + value;
+    long l5 = 5L + value;
+    long l6 = 6L + value;
+    long l7 = 7L + value;
+    long l8 = 8L + value;
+    long l9 = 9L + value;
+    long l10 = 10L + value;
+    long l11 = 11L + value;
+    long l12 = 12L + value;
+    long l13 = 13L + value;
+    long l14 = 14L + value;
+    long l15 = 15L + value;
+    long l16 = 16L + value;
+    long l17 = 17L + value;
+    long l18 = 18L + value;
+    long l19 = 19L + value;
+    long l20 = 20L + value;
+    long l21 = 21L + value;
+    long l22 = 22L + value;
+    long l23 = 23L + value;
+    long l24 = 24L + value;
+    long l25 = 25L + value;
+    long l26 = 26L + value;
+    long l27 = 27L + value;
+    long l28 = 28L + value;
+    long l29 = 29L + value;
+    long l30 = 30L + value;
+    long l31 = 31L + value;
+    long l32 = 32L + value;
+    long l33 = 33L + value;
+    long l34 = 34L + value;
+    long l35 = 35L + value;
+    long l36 = 36L + value;
+    long l37 = 37L + value;
+    long l38 = 38L + value;
+    long l39 = 39L + value;
+    long l40 = 40L + value;
+    long l41 = 41L + value;
+    long l42 = 42L + value;
+    long l43 = 43L + value;
+    long l44 = 44L + value;
+    long l45 = 45L + value;
+    long l46 = 46L + value;
+    long l47 = 47L + value;
+    long l48 = 48L + value;
+    long l49 = 49L + value;
+    long l50 = 50L + value;
+    long l51 = 51L + value;
+    long l52 = 52L + value;
+    long l53 = 53L + value;
+    long l54 = 54L + value;
+    long l55 = 55L + value;
+    long l56 = 56L + value;
+    long l57 = 57L + value;
+    long l58 = 58L + value;
+    long l59 = 59L + value;
+    long l60 = 60L + value;
+    long l61 = 61L + value;
+    long l62 = 62L + value;
+    long l63 = 63L + value;
+    long l64 = 64L + value;
+    long l65 = 65L + value;
+    long l66 = 66L + value;
+    long l67 = 67L + value;
+    long l68 = 68L + value;
+    long l69 = 69L + value;
+    long l70 = 70L + value;
+    long l71 = 71L + value;
+    long l72 = 72L + value;
+    long l73 = 73L + value;
+    long l74 = 74L + value;
+    long l75 = 75L + value;
+    long l76 = 76L + value;
+    long l77 = 77L + value;
+    long l78 = 78L + value;
+    long l79 = 79L + value;
+    long l80 = 80L + value;
+    long l81 = 81L + value;
+    long l82 = 82L + value;
+    long l83 = 83L + value;
+    long l84 = 84L + value;
+    long l85 = 85L + value;
+    long l86 = 86L + value;
+    long l87 = 87L + value;
+    long l88 = 88L + value;
+    long l89 = 89L + value;
+    long l90 = 90L + value;
+    long l91 = 91L + value;
+    long l92 = 92L + value;
+    long l93 = 93L + value;
+    long l94 = 94L + value;
+    long l95 = 95L + value;
+    long l96 = 96L + value;
+    long l97 = 97L + value;
+    long l98 = 98L + value;
+    long l99 = 99L + value;
+    long l100 = 100L + value;
+    long l101 = 101L + value;
+    long l102 = 102L + value;
+    long l103 = 103L + value;
+    long l104 = 104L + value;
+    long l105 = 105L + value;
+    long l106 = 106L + value;
+    long l107 = 107L + value;
+    long l108 = 108L + value;
+    long l109 = 109L + value;
+    long l110 = 110L + value;
+    long l111 = 111L + value;
+    long l112 = 112L + value;
+    long l113 = 113L + value;
+    long l114 = 114L + value;
+    long l115 = 115L + value;
+    long l116 = 116L + value;
+    long l117 = 117L + value;
+    long l118 = 118L + value;
+    long l119 = 119L + value;
+    long l120 = 120L + value;
+    long l121 = 121L + value;
+    long l122 = 122L + value;
+    long l123 = 123L + value;
+    long l124 = 124L + value;
+    long l125 = 125L + value;
+    long l126 = 126L + value;
+    long l127 = 127L + value;
+    long l128 = 128L + value;
+    long l129 = 129L + value;
+    long l130 = 130L + value;
+    long l131 = 131L + value;
+    long l132 = 132L + value;
+    long l133 = 133L + value;
+    long l134 = 134L + value;
+    long l135 = 135L + value;
+    long l136 = 136L + value;
+    long l137 = 137L + value;
+    long l138 = 138L + value;
+    long l139 = 139L + value;
+    long l140 = 140L + value;
+    long l141 = 141L + value;
+    long l142 = 142L + value;
+    long l143 = 143L + value;
+    long l144 = 144L + value;
+    long l145 = 145L + value;
+    long l146 = 146L + value;
+    long l147 = 147L + value;
+    long l148 = 148L + value;
+    long l149 = 149L + value;
+    long l150 = 150L + value;
+    long l151 = 151L + value;
+    long l152 = 152L + value;
+    long l153 = 153L + value;
+    long l154 = 154L + value;
+    long l155 = 155L + value;
+    long l156 = 156L + value;
+    long l157 = 157L + value;
+    long l158 = 158L + value;
+    long l159 = 159L + value;
+    long l160 = 160L + value;
+    long l161 = 161L + value;
+    long l162 = 162L + value;
+    long l163 = 163L + value;
+    long l164 = 164L + value;
+    long l165 = 165L + value;
+    long l166 = 166L + value;
+    long l167 = 167L + value;
+    long l168 = 168L + value;
+    long l169 = 169L + value;
+    long l170 = 170L + value;
+    long l171 = 171L + value;
+    long l172 = 172L + value;
+    long l173 = 173L + value;
+    long l174 = 174L + value;
+    long l175 = 175L + value;
+    long l176 = 176L + value;
+    long l177 = 177L + value;
+    long l178 = 178L + value;
+    long l179 = 179L + value;
+    long l180 = 180L + value;
+    long l181 = 181L + value;
+    long l182 = 182L + value;
+    long l183 = 183L + value;
+    long l184 = 184L + value;
+    long l185 = 185L + value;
+    long l186 = 186L + value;
+    long l187 = 187L + value;
+    long l188 = 188L + value;
+    long l189 = 189L + value;
+    long l190 = 190L + value;
+    long l191 = 191L + value;
+    long l192 = 192L + value;
+    long l193 = 193L + value;
+    long l194 = 194L + value;
+    long l195 = 195L + value;
+    long l196 = 196L + value;
+    long l197 = 197L + value;
+    long l198 = 198L + value;
+    long l199 = 199L + value;
+    long l200 = 200L + value;
+    long l201 = 201L + value;
+    long l202 = 202L + value;
+    long l203 = 203L + value;
+    long l204 = 204L + value;
+    long l205 = 205L + value;
+    long l206 = 206L + value;
+    long l207 = 207L + value;
+    long l208 = 208L + value;
+    long l209 = 209L + value;
+    long l210 = 210L + value;
+    long l211 = 211L + value;
+    long l212 = 212L + value;
+    long l213 = 213L + value;
+    long l214 = 214L + value;
+    long l215 = 215L + value;
+    long l216 = 216L + value;
+    long l217 = 217L + value;
+    long l218 = 218L + value;
+    long l219 = 219L + value;
+    long l220 = 220L + value;
+    long l221 = 221L + value;
+    long l222 = 222L + value;
+    long l223 = 223L + value;
+    long l224 = 224L + value;
+    long l225 = 225L + value;
+    long l226 = 226L + value;
+    long l227 = 227L + value;
+    long l228 = 228L + value;
+    long l229 = 229L + value;
+    long l230 = 230L + value;
+    long l231 = 231L + value;
+    long l232 = 232L + value;
+    long l233 = 233L + value;
+    long l234 = 234L + value;
+    long l235 = 235L + value;
+    long l236 = 236L + value;
+    long l237 = 237L + value;
+    long l238 = 238L + value;
+    long l239 = 239L + value;
+    long l240 = 240L + value;
+    long l241 = 241L + value;
+    long l242 = 242L + value;
+    long l243 = 243L + value;
+    long l244 = 244L + value;
+    long l245 = 245L + value;
+    long l246 = 246L + value;
+    long l247 = 247L + value;
+    long l248 = 248L + value;
+    long l249 = 249L + value;
+    long l250 = 250L + value;
+    long l251 = 251L + value;
+    long l252 = 252L + value;
+    long l253 = 253L + value;
+    long l254 = 254L + value;
+    long l255 = 255L + value;
+    long l256 = 256L + value;
+    long l257 = 257L + value;
+    long l258 = 258L + value;
+    long l259 = 259L + value;
+    long l260 = 260L + value;
+    long l261 = 261L + value;
+    long l262 = 262L + value;
+    long l263 = 263L + value;
+    long l264 = 264L + value;
+    long l265 = 265L + value;
+    long l266 = 266L + value;
+    long l267 = 267L + value;
+    long l268 = 268L + value;
+    long l269 = 269L + value;
+    long l270 = 270L + value;
+    long l271 = 271L + value;
+    long l272 = 272L + value;
+    long l273 = 273L + value;
+    long l274 = 274L + value;
+    long l275 = 275L + value;
+    long l276 = 276L + value;
+    long l277 = 277L + value;
+    long l278 = 278L + value;
+    long l279 = 279L + value;
+    long l280 = 280L + value;
+    long l281 = 281L + value;
+    long l282 = 282L + value;
+    long l283 = 283L + value;
+    long l284 = 284L + value;
+    long l285 = 285L + value;
+    long l286 = 286L + value;
+    long l287 = 287L + value;
+    long l288 = 288L + value;
+    long l289 = 289L + value;
+    long l290 = 290L + value;
+    long l291 = 291L + value;
+    long l292 = 292L + value;
+    long l293 = 293L + value;
+    long l294 = 294L + value;
+    long l295 = 295L + value;
+    long l296 = 296L + value;
+    long l297 = 297L + value;
+    long l298 = 298L + value;
+    long l299 = 299L + value;
+    long l300 = 300L + value;
+    long l301 = 301L + value;
+    long l302 = 302L + value;
+    long l303 = 303L + value;
+    long l304 = 304L + value;
+    long l305 = 305L + value;
+    long l306 = 306L + value;
+    long l307 = 307L + value;
+    long l308 = 308L + value;
+    long l309 = 309L + value;
+    long l310 = 310L + value;
+    long l311 = 311L + value;
+    long l312 = 312L + value;
+    long l313 = 313L + value;
+    long l314 = 314L + value;
+    long l315 = 315L + value;
+    long l316 = 316L + value;
+    long l317 = 317L + value;
+    long l318 = 318L + value;
+    long l319 = 319L + value;
+    long l320 = 320L + value;
+    long l321 = 321L + value;
+    long l322 = 322L + value;
+    long l323 = 323L + value;
+    long l324 = 324L + value;
+    long l325 = 325L + value;
+    long l326 = 326L + value;
+    long l327 = 327L + value;
+    long l328 = 328L + value;
+    long l329 = 329L + value;
+    long l330 = 330L + value;
+    long l331 = 331L + value;
+    long l332 = 332L + value;
+    long l333 = 333L + value;
+    long l334 = 334L + value;
+    long l335 = 335L + value;
+    long l336 = 336L + value;
+    long l337 = 337L + value;
+    long l338 = 338L + value;
+    long l339 = 339L + value;
+    long l340 = 340L + value;
+    long l341 = 341L + value;
+    long l342 = 342L + value;
+    long l343 = 343L + value;
+    long l344 = 344L + value;
+    long l345 = 345L + value;
+    long l346 = 346L + value;
+    long l347 = 347L + value;
+    long l348 = 348L + value;
+    long l349 = 349L + value;
+    long l350 = 350L + value;
+    long l351 = 351L + value;
+    long l352 = 352L + value;
+    long l353 = 353L + value;
+    long l354 = 354L + value;
+    long l355 = 355L + value;
+    long l356 = 356L + value;
+    long l357 = 357L + value;
+    long l358 = 358L + value;
+    long l359 = 359L + value;
+    long l360 = 360L + value;
+    long l361 = 361L + value;
+    long l362 = 362L + value;
+    long l363 = 363L + value;
+    long l364 = 364L + value;
+    long l365 = 365L + value;
+    long l366 = 366L + value;
+    long l367 = 367L + value;
+    long l368 = 368L + value;
+    long l369 = 369L + value;
+    long l370 = 370L + value;
+    long l371 = 371L + value;
+    long l372 = 372L + value;
+    long l373 = 373L + value;
+    long l374 = 374L + value;
+    long l375 = 375L + value;
+    long l376 = 376L + value;
+    long l377 = 377L + value;
+    long l378 = 378L + value;
+    long l379 = 379L + value;
+    long l380 = 380L + value;
+    long l381 = 381L + value;
+    long l382 = 382L + value;
+    long l383 = 383L + value;
+    long l384 = 384L + value;
+    long l385 = 385L + value;
+    long l386 = 386L + value;
+    long l387 = 387L + value;
+    long l388 = 388L + value;
+    long l389 = 389L + value;
+    long l390 = 390L + value;
+    long l391 = 391L + value;
+    long l392 = 392L + value;
+    long l393 = 393L + value;
+    long l394 = 394L + value;
+    long l395 = 395L + value;
+    long l396 = 396L + value;
+    long l397 = 397L + value;
+    long l398 = 398L + value;
+    long l399 = 399L + value;
+    long l400 = 400L + value;
+    long l401 = 401L + value;
+    long l402 = 402L + value;
+    long l403 = 403L + value;
+    long l404 = 404L + value;
+    long l405 = 405L + value;
+    long l406 = 406L + value;
+    long l407 = 407L + value;
+    long l408 = 408L + value;
+    long l409 = 409L + value;
+    long l410 = 410L + value;
+    long l411 = 411L + value;
+    long l412 = 412L + value;
+    long l413 = 413L + value;
+    long l414 = 414L + value;
+    long l415 = 415L + value;
+    long l416 = 416L + value;
+    long l417 = 417L + value;
+    long l418 = 418L + value;
+    long l419 = 419L + value;
+    long l420 = 420L + value;
+    long l421 = 421L + value;
+    long l422 = 422L + value;
+    long l423 = 423L + value;
+    long l424 = 424L + value;
+    long l425 = 425L + value;
+    long l426 = 426L + value;
+    long l427 = 427L + value;
+    long l428 = 428L + value;
+    long l429 = 429L + value;
+    long l430 = 430L + value;
+    long l431 = 431L + value;
+    long l432 = 432L + value;
+    long l433 = 433L + value;
+    long l434 = 434L + value;
+    long l435 = 435L + value;
+    long l436 = 436L + value;
+    long l437 = 437L + value;
+    long l438 = 438L + value;
+    long l439 = 439L + value;
+    long l440 = 440L + value;
+    long l441 = 441L + value;
+    long l442 = 442L + value;
+    long l443 = 443L + value;
+    long l444 = 444L + value;
+    long l445 = 445L + value;
+    long l446 = 446L + value;
+    long l447 = 447L + value;
+    long l448 = 448L + value;
+    long l449 = 449L + value;
+    long l450 = 450L + value;
+    long l451 = 451L + value;
+    long l452 = 452L + value;
+    long l453 = 453L + value;
+    long l454 = 454L + value;
+    long l455 = 455L + value;
+    long l456 = 456L + value;
+    long l457 = 457L + value;
+    long l458 = 458L + value;
+    long l459 = 459L + value;
+    long l460 = 460L + value;
+    long l461 = 461L + value;
+    long l462 = 462L + value;
+    long l463 = 463L + value;
+    long l464 = 464L + value;
+    long l465 = 465L + value;
+    long l466 = 466L + value;
+    long l467 = 467L + value;
+    long l468 = 468L + value;
+    long l469 = 469L + value;
+    long l470 = 470L + value;
+    long l471 = 471L + value;
+    long l472 = 472L + value;
+    long l473 = 473L + value;
+    long l474 = 474L + value;
+    long l475 = 475L + value;
+    long l476 = 476L + value;
+    long l477 = 477L + value;
+    long l478 = 478L + value;
+    long l479 = 479L + value;
+    long l480 = 480L + value;
+    long l481 = 481L + value;
+    long l482 = 482L + value;
+    long l483 = 483L + value;
+    long l484 = 484L + value;
+    long l485 = 485L + value;
+    long l486 = 486L + value;
+    long l487 = 487L + value;
+    long l488 = 488L + value;
+    long l489 = 489L + value;
+    long l490 = 490L + value;
+    long l491 = 491L + value;
+    long l492 = 492L + value;
+    long l493 = 493L + value;
+    long l494 = 494L + value;
+    long l495 = 495L + value;
+    long l496 = 496L + value;
+    long l497 = 497L + value;
+    long l498 = 498L + value;
+    long l499 = 499L + value;
     l1 += l0;
     l2 += l1;
     l3 += l2;
diff --git a/test/422-instanceof/Android.bp b/test/422-instanceof/Android.bp
new file mode 100644
index 0000000..983dbee
--- /dev/null
+++ b/test/422-instanceof/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `422-instanceof`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-422-instanceof",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-422-instanceof-expected-stdout",
+        ":art-run-test-422-instanceof-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-422-instanceof-expected-stdout",
+    out: ["art-run-test-422-instanceof-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-422-instanceof-expected-stderr",
+    out: ["art-run-test-422-instanceof-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/422-instanceof/expected.txt b/test/422-instanceof/expected-stderr.txt
similarity index 100%
rename from test/422-instanceof/expected.txt
rename to test/422-instanceof/expected-stderr.txt
diff --git a/test/422-instanceof/expected.txt b/test/422-instanceof/expected-stdout.txt
similarity index 100%
copy from test/422-instanceof/expected.txt
copy to test/422-instanceof/expected-stdout.txt
diff --git a/test/422-type-conversion/Android.bp b/test/422-type-conversion/Android.bp
new file mode 100644
index 0000000..737f06b
--- /dev/null
+++ b/test/422-type-conversion/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `422-type-conversion`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-422-type-conversion",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-422-type-conversion-expected-stdout",
+        ":art-run-test-422-type-conversion-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-422-type-conversion-expected-stdout",
+    out: ["art-run-test-422-type-conversion-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-422-type-conversion-expected-stderr",
+    out: ["art-run-test-422-type-conversion-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/422-type-conversion/expected.txt b/test/422-type-conversion/expected-stderr.txt
similarity index 100%
rename from test/422-type-conversion/expected.txt
rename to test/422-type-conversion/expected-stderr.txt
diff --git a/test/422-type-conversion/expected.txt b/test/422-type-conversion/expected-stdout.txt
similarity index 100%
copy from test/422-type-conversion/expected.txt
copy to test/422-type-conversion/expected-stdout.txt
diff --git a/test/422-type-conversion/src/Main.java b/test/422-type-conversion/src/Main.java
index 7754b75..eb4d462 100644
--- a/test/422-type-conversion/src/Main.java
+++ b/test/422-type-conversion/src/Main.java
@@ -629,67 +629,64 @@
     assertCharEquals((char)0, $opt$noinline$IntToChar(-2147483648));  // -(2^31)
   }
 
-  // A dummy value to defeat inlining of these routines.
-  static boolean doThrow = false;
-
   // These methods produce int-to-long Dex instructions.
-  static long $opt$noinline$ByteToLong(byte a) { if (doThrow) throw new Error(); return (long)a; }
-  static long $opt$noinline$ShortToLong(short a) { if (doThrow) throw new Error(); return (long)a; }
-  static long $opt$noinline$IntToLong(int a) { if (doThrow) throw new Error(); return (long)a; }
-  static long $opt$noinline$CharToLong(int a) { if (doThrow) throw new Error(); return (long)a; }
+  static long $opt$noinline$ByteToLong(byte a) { return (long)a; }
+  static long $opt$noinline$ShortToLong(short a) { return (long)a; }
+  static long $opt$noinline$IntToLong(int a) { return (long)a; }
+  static long $opt$noinline$CharToLong(int a) { return (long)a; }
 
   // These methods produce int-to-float Dex instructions.
-  static float $opt$noinline$ByteToFloat(byte a) { if (doThrow) throw new Error(); return (float)a; }
-  static float $opt$noinline$ShortToFloat(short a) { if (doThrow) throw new Error(); return (float)a; }
-  static float $opt$noinline$IntToFloat(int a) { if (doThrow) throw new Error(); return (float)a; }
-  static float $opt$noinline$CharToFloat(char a) { if (doThrow) throw new Error(); return (float)a; }
+  static float $opt$noinline$ByteToFloat(byte a) { return (float)a; }
+  static float $opt$noinline$ShortToFloat(short a) { return (float)a; }
+  static float $opt$noinline$IntToFloat(int a) { return (float)a; }
+  static float $opt$noinline$CharToFloat(char a) { return (float)a; }
 
   // These methods produce int-to-double Dex instructions.
-  static double $opt$noinline$ByteToDouble(byte a) { if (doThrow) throw new Error(); return (double)a; }
-  static double $opt$noinline$ShortToDouble(short a) { if (doThrow) throw new Error(); return (double)a; }
-  static double $opt$noinline$IntToDouble(int a) { if (doThrow) throw new Error(); return (double)a; }
-  static double $opt$noinline$CharToDouble(int a) { if (doThrow) throw new Error(); return (double)a; }
+  static double $opt$noinline$ByteToDouble(byte a) { return (double)a; }
+  static double $opt$noinline$ShortToDouble(short a) { return (double)a; }
+  static double $opt$noinline$IntToDouble(int a) { return (double)a; }
+  static double $opt$noinline$CharToDouble(int a) { return (double)a; }
 
   // These methods produce long-to-int Dex instructions.
-  static int $opt$noinline$LongToInt(long a) { if (doThrow) throw new Error(); return (int)a; }
-  static int $opt$noinline$LongLiteralToInt() { if (doThrow) throw new Error(); return (int)42L; }
+  static int $opt$noinline$LongToInt(long a) { return (int)a; }
+  static int $opt$noinline$LongLiteralToInt() { return (int)42L; }
 
   // This method produces a long-to-float Dex instruction.
-  static float $opt$noinline$LongToFloat(long a) { if (doThrow) throw new Error(); return (float)a; }
+  static float $opt$noinline$LongToFloat(long a) { return (float)a; }
 
   // This method produces a long-to-double Dex instruction.
-  static double $opt$noinline$LongToDouble(long a) { if (doThrow) throw new Error(); return (double)a; }
+  static double $opt$noinline$LongToDouble(long a) { return (double)a; }
 
   // This method produces a float-to-int Dex instruction.
-  static int $opt$noinline$FloatToInt(float a) { if (doThrow) throw new Error(); return (int)a; }
+  static int $opt$noinline$FloatToInt(float a) { return (int)a; }
 
   // This method produces a float-to-long Dex instruction.
-  static long $opt$noinline$FloatToLong(float a){ if (doThrow) throw new Error(); return (long)a; }
+  static long $opt$noinline$FloatToLong(float a){ return (long)a; }
 
   // This method produces a float-to-double Dex instruction.
-  static double $opt$noinline$FloatToDouble(float a) { if (doThrow) throw new Error(); return (double)a; }
+  static double $opt$noinline$FloatToDouble(float a) { return (double)a; }
 
   // This method produces a double-to-int Dex instruction.
-  static int $opt$noinline$DoubleToInt(double a){ if (doThrow) throw new Error(); return (int)a; }
+  static int $opt$noinline$DoubleToInt(double a){ return (int)a; }
 
   // This method produces a double-to-long Dex instruction.
-  static long $opt$noinline$DoubleToLong(double a){ if (doThrow) throw new Error(); return (long)a; }
+  static long $opt$noinline$DoubleToLong(double a){ return (long)a; }
 
   // This method produces a double-to-float Dex instruction.
-  static float $opt$noinline$DoubleToFloat(double a) { if (doThrow) throw new Error(); return (float)a; }
+  static float $opt$noinline$DoubleToFloat(double a) { return (float)a; }
 
   // These methods produce int-to-byte Dex instructions.
-  static byte $opt$noinline$ShortToByte(short a) { if (doThrow) throw new Error(); return (byte)a; }
-  static byte $opt$noinline$IntToByte(int a) { if (doThrow) throw new Error(); return (byte)a; }
-  static byte $opt$noinline$CharToByte(char a) { if (doThrow) throw new Error(); return (byte)a; }
+  static byte $opt$noinline$ShortToByte(short a) { return (byte)a; }
+  static byte $opt$noinline$IntToByte(int a) { return (byte)a; }
+  static byte $opt$noinline$CharToByte(char a) { return (byte)a; }
 
   // These methods produce int-to-short Dex instructions.
-  static short $opt$noinline$ByteToShort(byte a) { if (doThrow) throw new Error(); return (short)a; }
-  static short $opt$noinline$IntToShort(int a) { if (doThrow) throw new Error(); return (short)a; }
-  static short $opt$noinline$CharToShort(char a) { if (doThrow) throw new Error(); return (short)a; }
+  static short $opt$noinline$ByteToShort(byte a) { return (short)a; }
+  static short $opt$noinline$IntToShort(int a) { return (short)a; }
+  static short $opt$noinline$CharToShort(char a) { return (short)a; }
 
   // These methods produce int-to-char Dex instructions.
-  static char $opt$noinline$ByteToChar(byte a) { if (doThrow) throw new Error(); return (char)a; }
-  static char $opt$noinline$ShortToChar(short a) { if (doThrow) throw new Error(); return (char)a; }
-  static char $opt$noinline$IntToChar(int a) { if (doThrow) throw new Error(); return (char)a; }
+  static char $opt$noinline$ByteToChar(byte a) { return (char)a; }
+  static char $opt$noinline$ShortToChar(short a) { return (char)a; }
+  static char $opt$noinline$IntToChar(int a) { return (char)a; }
 }
diff --git a/test/423-invoke-interface/Android.bp b/test/423-invoke-interface/Android.bp
new file mode 100644
index 0000000..49a1311
--- /dev/null
+++ b/test/423-invoke-interface/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `423-invoke-interface`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-423-invoke-interface",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-423-invoke-interface-expected-stdout",
+        ":art-run-test-423-invoke-interface-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-423-invoke-interface-expected-stdout",
+    out: ["art-run-test-423-invoke-interface-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-423-invoke-interface-expected-stderr",
+    out: ["art-run-test-423-invoke-interface-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/423-invoke-interface/expected.txt b/test/423-invoke-interface/expected-stderr.txt
similarity index 100%
rename from test/423-invoke-interface/expected.txt
rename to test/423-invoke-interface/expected-stderr.txt
diff --git a/test/423-invoke-interface/expected.txt b/test/423-invoke-interface/expected-stdout.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/423-invoke-interface/expected-stdout.txt
diff --git a/test/424-checkcast/Android.bp b/test/424-checkcast/Android.bp
new file mode 100644
index 0000000..11684c3
--- /dev/null
+++ b/test/424-checkcast/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `424-checkcast`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-424-checkcast",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-424-checkcast-expected-stdout",
+        ":art-run-test-424-checkcast-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-424-checkcast-expected-stdout",
+    out: ["art-run-test-424-checkcast-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-424-checkcast-expected-stderr",
+    out: ["art-run-test-424-checkcast-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/424-checkcast/expected.txt b/test/424-checkcast/expected-stderr.txt
similarity index 100%
rename from test/424-checkcast/expected.txt
rename to test/424-checkcast/expected-stderr.txt
diff --git a/test/424-checkcast/expected.txt b/test/424-checkcast/expected-stdout.txt
similarity index 100%
copy from test/424-checkcast/expected.txt
copy to test/424-checkcast/expected-stdout.txt
diff --git a/test/551-invoke-super/expected.txt b/test/425-invoke-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/425-invoke-super/expected-stderr.txt
diff --git a/test/425-invoke-super/expected.txt b/test/425-invoke-super/expected-stdout.txt
similarity index 100%
rename from test/425-invoke-super/expected.txt
rename to test/425-invoke-super/expected-stdout.txt
diff --git a/test/426-monitor/Android.bp b/test/426-monitor/Android.bp
new file mode 100644
index 0000000..7bea5da
--- /dev/null
+++ b/test/426-monitor/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `426-monitor`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-426-monitor",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-426-monitor-expected-stdout",
+        ":art-run-test-426-monitor-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-426-monitor-expected-stdout",
+    out: ["art-run-test-426-monitor-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-426-monitor-expected-stderr",
+    out: ["art-run-test-426-monitor-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/427-bitwise/expected.txt b/test/426-monitor/expected-stderr.txt
similarity index 100%
copy from test/427-bitwise/expected.txt
copy to test/426-monitor/expected-stderr.txt
diff --git a/test/426-monitor/expected.txt b/test/426-monitor/expected-stdout.txt
similarity index 100%
rename from test/426-monitor/expected.txt
rename to test/426-monitor/expected-stdout.txt
diff --git a/test/427-bitwise/Android.bp b/test/427-bitwise/Android.bp
new file mode 100644
index 0000000..858aaf5
--- /dev/null
+++ b/test/427-bitwise/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `427-bitwise`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-427-bitwise",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-427-bitwise-expected-stdout",
+        ":art-run-test-427-bitwise-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-427-bitwise-expected-stdout",
+    out: ["art-run-test-427-bitwise-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-427-bitwise-expected-stderr",
+    out: ["art-run-test-427-bitwise-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/427-bitwise/expected.txt b/test/427-bitwise/expected-stderr.txt
similarity index 100%
rename from test/427-bitwise/expected.txt
rename to test/427-bitwise/expected-stderr.txt
diff --git a/test/427-bitwise/expected.txt b/test/427-bitwise/expected-stdout.txt
similarity index 100%
copy from test/427-bitwise/expected.txt
copy to test/427-bitwise/expected-stdout.txt
diff --git a/test/427-bounds/Android.bp b/test/427-bounds/Android.bp
new file mode 100644
index 0000000..606c186
--- /dev/null
+++ b/test/427-bounds/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `427-bounds`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-427-bounds",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-427-bounds-expected-stdout",
+        ":art-run-test-427-bounds-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-427-bounds-expected-stdout",
+    out: ["art-run-test-427-bounds-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-427-bounds-expected-stderr",
+    out: ["art-run-test-427-bounds-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/427-bounds/expected.txt b/test/427-bounds/expected-stderr.txt
similarity index 100%
rename from test/427-bounds/expected.txt
rename to test/427-bounds/expected-stderr.txt
diff --git a/test/427-bounds/expected.txt b/test/427-bounds/expected-stdout.txt
similarity index 100%
copy from test/427-bounds/expected.txt
copy to test/427-bounds/expected-stdout.txt
diff --git a/test/429-ssa-builder/Android.bp b/test/429-ssa-builder/Android.bp
new file mode 100644
index 0000000..4e7b263
--- /dev/null
+++ b/test/429-ssa-builder/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `429-ssa-builder`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-429-ssa-builder",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-429-ssa-builder-expected-stdout",
+        ":art-run-test-429-ssa-builder-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-429-ssa-builder-expected-stdout",
+    out: ["art-run-test-429-ssa-builder-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-429-ssa-builder-expected-stderr",
+    out: ["art-run-test-429-ssa-builder-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/429-ssa-builder/expected.txt b/test/429-ssa-builder/expected-stderr.txt
similarity index 100%
rename from test/429-ssa-builder/expected.txt
rename to test/429-ssa-builder/expected-stderr.txt
diff --git a/test/429-ssa-builder/expected.txt b/test/429-ssa-builder/expected-stdout.txt
similarity index 100%
copy from test/429-ssa-builder/expected.txt
copy to test/429-ssa-builder/expected-stdout.txt
diff --git a/test/430-live-register-slow-path/Android.bp b/test/430-live-register-slow-path/Android.bp
new file mode 100644
index 0000000..0295e46
--- /dev/null
+++ b/test/430-live-register-slow-path/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `430-live-register-slow-path`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-430-live-register-slow-path",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-430-live-register-slow-path-expected-stdout",
+        ":art-run-test-430-live-register-slow-path-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-430-live-register-slow-path-expected-stdout",
+    out: ["art-run-test-430-live-register-slow-path-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-430-live-register-slow-path-expected-stderr",
+    out: ["art-run-test-430-live-register-slow-path-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/430-live-register-slow-path/expected.txt b/test/430-live-register-slow-path/expected-stderr.txt
similarity index 100%
rename from test/430-live-register-slow-path/expected.txt
rename to test/430-live-register-slow-path/expected-stderr.txt
diff --git a/test/430-live-register-slow-path/expected.txt b/test/430-live-register-slow-path/expected-stdout.txt
similarity index 100%
copy from test/430-live-register-slow-path/expected.txt
copy to test/430-live-register-slow-path/expected-stdout.txt
diff --git a/test/505-simplifier-type-propagation/expected.txt b/test/431-type-propagation/expected-stderr.txt
similarity index 100%
copy from test/505-simplifier-type-propagation/expected.txt
copy to test/431-type-propagation/expected-stderr.txt
diff --git a/test/431-type-propagation/expected.txt b/test/431-type-propagation/expected-stdout.txt
similarity index 100%
rename from test/431-type-propagation/expected.txt
rename to test/431-type-propagation/expected-stdout.txt
diff --git a/test/432-optimizing-cmp/expected.txt b/test/432-optimizing-cmp/expected-stderr.txt
similarity index 100%
rename from test/432-optimizing-cmp/expected.txt
rename to test/432-optimizing-cmp/expected-stderr.txt
diff --git a/test/432-optimizing-cmp/expected.txt b/test/432-optimizing-cmp/expected-stdout.txt
similarity index 100%
copy from test/432-optimizing-cmp/expected.txt
copy to test/432-optimizing-cmp/expected-stdout.txt
diff --git a/test/433-gvn/Android.bp b/test/433-gvn/Android.bp
new file mode 100644
index 0000000..e4f6b9a
--- /dev/null
+++ b/test/433-gvn/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `433-gvn`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-433-gvn",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-433-gvn-expected-stdout",
+        ":art-run-test-433-gvn-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-433-gvn-expected-stdout",
+    out: ["art-run-test-433-gvn-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-433-gvn-expected-stderr",
+    out: ["art-run-test-433-gvn-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/433-gvn/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/433-gvn/expected-stderr.txt
diff --git a/test/433-gvn/expected.txt b/test/433-gvn/expected-stdout.txt
similarity index 100%
rename from test/433-gvn/expected.txt
rename to test/433-gvn/expected-stdout.txt
diff --git a/test/434-invoke-direct/expected.txt b/test/434-invoke-direct/expected-stderr.txt
similarity index 100%
rename from test/434-invoke-direct/expected.txt
rename to test/434-invoke-direct/expected-stderr.txt
diff --git a/test/434-invoke-direct/expected.txt b/test/434-invoke-direct/expected-stdout.txt
similarity index 100%
copy from test/434-invoke-direct/expected.txt
copy to test/434-invoke-direct/expected-stdout.txt
diff --git a/test/434-shifter-operand/Android.bp b/test/434-shifter-operand/Android.bp
new file mode 100644
index 0000000..4309d8a
--- /dev/null
+++ b/test/434-shifter-operand/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `434-shifter-operand`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-434-shifter-operand",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-434-shifter-operand-expected-stdout",
+        ":art-run-test-434-shifter-operand-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-434-shifter-operand-expected-stdout",
+    out: ["art-run-test-434-shifter-operand-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-434-shifter-operand-expected-stderr",
+    out: ["art-run-test-434-shifter-operand-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/551-checker-shifter-operand/expected.txt b/test/434-shifter-operand/expected-stderr.txt
similarity index 100%
copy from test/551-checker-shifter-operand/expected.txt
copy to test/434-shifter-operand/expected-stderr.txt
diff --git a/test/434-shifter-operand/expected.txt b/test/434-shifter-operand/expected-stdout.txt
similarity index 100%
rename from test/434-shifter-operand/expected.txt
rename to test/434-shifter-operand/expected-stdout.txt
diff --git a/test/435-new-instance/expected.txt b/test/435-new-instance/expected-stderr.txt
similarity index 100%
rename from test/435-new-instance/expected.txt
rename to test/435-new-instance/expected-stderr.txt
diff --git a/test/435-new-instance/expected.txt b/test/435-new-instance/expected-stdout.txt
similarity index 100%
copy from test/435-new-instance/expected.txt
copy to test/435-new-instance/expected-stdout.txt
diff --git a/test/435-try-finally-without-catch/Android.bp b/test/435-try-finally-without-catch/Android.bp
new file mode 100644
index 0000000..d8c0409
--- /dev/null
+++ b/test/435-try-finally-without-catch/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `435-try-finally-without-catch`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-435-try-finally-without-catch",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-435-try-finally-without-catch-expected-stdout",
+        ":art-run-test-435-try-finally-without-catch-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-435-try-finally-without-catch-expected-stdout",
+    out: ["art-run-test-435-try-finally-without-catch-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-435-try-finally-without-catch-expected-stderr",
+    out: ["art-run-test-435-try-finally-without-catch-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/510-checker-try-catch/expected.txt b/test/435-try-finally-without-catch/expected-stderr.txt
similarity index 100%
copy from test/510-checker-try-catch/expected.txt
copy to test/435-try-finally-without-catch/expected-stderr.txt
diff --git a/test/435-try-finally-without-catch/expected.txt b/test/435-try-finally-without-catch/expected-stdout.txt
similarity index 100%
rename from test/435-try-finally-without-catch/expected.txt
rename to test/435-try-finally-without-catch/expected-stdout.txt
diff --git a/test/436-rem-float/Android.bp b/test/436-rem-float/Android.bp
new file mode 100644
index 0000000..526f22f
--- /dev/null
+++ b/test/436-rem-float/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `436-rem-float`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-436-rem-float",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-436-rem-float-expected-stdout",
+        ":art-run-test-436-rem-float-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-436-rem-float-expected-stdout",
+    out: ["art-run-test-436-rem-float-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-436-rem-float-expected-stderr",
+    out: ["art-run-test-436-rem-float-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/436-rem-float/expected.txt b/test/436-rem-float/expected-stderr.txt
similarity index 100%
rename from test/436-rem-float/expected.txt
rename to test/436-rem-float/expected-stderr.txt
diff --git a/test/436-rem-float/expected.txt b/test/436-rem-float/expected-stdout.txt
similarity index 100%
copy from test/436-rem-float/expected.txt
copy to test/436-rem-float/expected-stdout.txt
diff --git a/test/436-shift-constant/Android.bp b/test/436-shift-constant/Android.bp
new file mode 100644
index 0000000..107e392
--- /dev/null
+++ b/test/436-shift-constant/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `436-shift-constant`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-436-shift-constant",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-436-shift-constant-expected-stdout",
+        ":art-run-test-436-shift-constant-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-436-shift-constant-expected-stdout",
+    out: ["art-run-test-436-shift-constant-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-436-shift-constant-expected-stderr",
+    out: ["art-run-test-436-shift-constant-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/436-shift-constant/expected.txt b/test/436-shift-constant/expected-stderr.txt
similarity index 100%
rename from test/436-shift-constant/expected.txt
rename to test/436-shift-constant/expected-stderr.txt
diff --git a/test/436-shift-constant/expected.txt b/test/436-shift-constant/expected-stdout.txt
similarity index 100%
copy from test/436-shift-constant/expected.txt
copy to test/436-shift-constant/expected-stdout.txt
diff --git a/test/437-inline/Android.bp b/test/437-inline/Android.bp
new file mode 100644
index 0000000..7596d03
--- /dev/null
+++ b/test/437-inline/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `437-inline`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-437-inline",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-437-inline-expected-stdout",
+        ":art-run-test-437-inline-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-437-inline-expected-stdout",
+    out: ["art-run-test-437-inline-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-437-inline-expected-stderr",
+    out: ["art-run-test-437-inline-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/437-inline/expected.txt b/test/437-inline/expected-stderr.txt
similarity index 100%
rename from test/437-inline/expected.txt
rename to test/437-inline/expected-stderr.txt
diff --git a/test/437-inline/expected.txt b/test/437-inline/expected-stdout.txt
similarity index 100%
copy from test/437-inline/expected.txt
copy to test/437-inline/expected-stdout.txt
diff --git a/test/438-volatile/Android.bp b/test/438-volatile/Android.bp
new file mode 100644
index 0000000..adc4a80
--- /dev/null
+++ b/test/438-volatile/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `438-volatile`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-438-volatile",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-438-volatile-expected-stdout",
+        ":art-run-test-438-volatile-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-438-volatile-expected-stdout",
+    out: ["art-run-test-438-volatile-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-438-volatile-expected-stderr",
+    out: ["art-run-test-438-volatile-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/438-volatile/expected.txt b/test/438-volatile/expected-stderr.txt
similarity index 100%
rename from test/438-volatile/expected.txt
rename to test/438-volatile/expected-stderr.txt
diff --git a/test/438-volatile/expected.txt b/test/438-volatile/expected-stdout.txt
similarity index 100%
copy from test/438-volatile/expected.txt
copy to test/438-volatile/expected-stdout.txt
diff --git a/test/439-npe/Android.bp b/test/439-npe/Android.bp
new file mode 100644
index 0000000..527b6cf
--- /dev/null
+++ b/test/439-npe/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `439-npe`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-439-npe",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-439-npe-expected-stdout",
+        ":art-run-test-439-npe-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-439-npe-expected-stdout",
+    out: ["art-run-test-439-npe-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-439-npe-expected-stderr",
+    out: ["art-run-test-439-npe-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/122-npe/expected.txt b/test/439-npe/expected-stderr.txt
similarity index 100%
copy from test/122-npe/expected.txt
copy to test/439-npe/expected-stderr.txt
diff --git a/test/439-npe/expected.txt b/test/439-npe/expected-stdout.txt
similarity index 100%
rename from test/439-npe/expected.txt
rename to test/439-npe/expected-stdout.txt
diff --git a/test/439-swap-double/Android.bp b/test/439-swap-double/Android.bp
new file mode 100644
index 0000000..f175231
--- /dev/null
+++ b/test/439-swap-double/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `439-swap-double`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-439-swap-double",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-439-swap-double-expected-stdout",
+        ":art-run-test-439-swap-double-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-439-swap-double-expected-stdout",
+    out: ["art-run-test-439-swap-double-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-439-swap-double-expected-stderr",
+    out: ["art-run-test-439-swap-double-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/438-volatile/expected.txt b/test/439-swap-double/expected-stderr.txt
similarity index 100%
copy from test/438-volatile/expected.txt
copy to test/439-swap-double/expected-stderr.txt
diff --git a/test/439-swap-double/expected.txt b/test/439-swap-double/expected-stdout.txt
similarity index 100%
rename from test/439-swap-double/expected.txt
rename to test/439-swap-double/expected-stdout.txt
diff --git a/test/440-stmp/Android.bp b/test/440-stmp/Android.bp
new file mode 100644
index 0000000..5ace2fc
--- /dev/null
+++ b/test/440-stmp/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `440-stmp`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-440-stmp",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-440-stmp-expected-stdout",
+        ":art-run-test-440-stmp-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-440-stmp-expected-stdout",
+    out: ["art-run-test-440-stmp-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-440-stmp-expected-stderr",
+    out: ["art-run-test-440-stmp-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/581-rtp/expected.txt b/test/440-stmp/expected-stderr.txt
similarity index 100%
copy from test/581-rtp/expected.txt
copy to test/440-stmp/expected-stderr.txt
diff --git a/test/440-stmp/expected.txt b/test/440-stmp/expected-stdout.txt
similarity index 100%
rename from test/440-stmp/expected.txt
rename to test/440-stmp/expected-stdout.txt
diff --git a/test/441-checker-inliner/Android.bp b/test/441-checker-inliner/Android.bp
new file mode 100644
index 0000000..f4eef68
--- /dev/null
+++ b/test/441-checker-inliner/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `441-checker-inliner`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-441-checker-inliner",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-441-checker-inliner-expected-stdout",
+        ":art-run-test-441-checker-inliner-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-441-checker-inliner-expected-stdout",
+    out: ["art-run-test-441-checker-inliner-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-441-checker-inliner-expected-stderr",
+    out: ["art-run-test-441-checker-inliner-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/441-checker-inliner/expected.txt b/test/441-checker-inliner/expected-stderr.txt
similarity index 100%
rename from test/441-checker-inliner/expected.txt
rename to test/441-checker-inliner/expected-stderr.txt
diff --git a/test/441-checker-inliner/expected.txt b/test/441-checker-inliner/expected-stdout.txt
similarity index 100%
copy from test/441-checker-inliner/expected.txt
copy to test/441-checker-inliner/expected-stdout.txt
diff --git a/test/441-checker-inliner/smali/Smali.smali b/test/441-checker-inliner/smali/Smali.smali
deleted file mode 100644
index 7e42755..0000000
--- a/test/441-checker-inliner/smali/Smali.smali
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-.class public LSmali;
-.super Ljava/lang/Object;
-.source "Smali.java"
-
-##  CHECK-START: int Smali.InlineWithControlFlow(boolean) inliner (before)
-##  CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
-##  CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
-##  CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
-##  CHECK-DAG:     <<Add:i\d+>>    InvokeStaticOrDirect [<<Const1>>,<<Const3>>{{(,[ij]\d+)?}}]
-##  CHECK-DAG:     <<Sub:i\d+>>    InvokeStaticOrDirect [<<Const5>>,<<Const3>>{{(,[ij]\d+)?}}]
-##  CHECK-DAG:     <<Phi:i\d+>>    Phi [<<Add>>,<<Sub>>]
-##  CHECK-DAG:                     Return [<<Phi>>]
-
-##  CHECK-START: int Smali.InlineWithControlFlow(boolean) inliner (after)
-##  CHECK-DAG:     <<Const4:i\d+>> IntConstant 4
-##  CHECK-DAG:     <<Const2:i\d+>> IntConstant 2
-##  CHECK-DAG:     <<Phi:i\d+>>    Phi [<<Const4>>,<<Const2>>]
-##  CHECK-DAG:                     Return [<<Phi>>]
-.method public static InlineWithControlFlow(Z)I
-
-    # int x, const1, const3, const5;
-    # const1 = 1;
-    # const3 = 3;
-    # const5 = 5;
-    # if (cond) {
-    #   x = returnAdd(const1, const3);
-    # } else {
-    #   x = returnSub(const5, const3);
-    # }
-    # return x;
-
-    .registers 5
-    .param p0, "cond"    # Z
-
-    .prologue
-    const/4 v0, 0x1
-
-    .local v0, "const1":I
-    const/4 v1, 0x3
-
-    .local v1, "const3":I
-    const/4 v2, 0x5
-
-    .local v2, "const5":I
-    if-eqz p0, :cond_a
-
-    invoke-static {v0, v1}, LSmali;->returnAdd(II)I
-
-    move-result v3
-
-    .local v3, "x":I
-    :goto_9
-    return v3
-
-    .end local v3    # "x":I
-    :cond_a
-    invoke-static {v2, v1}, LSmali;->returnSub(II)I
-
-    move-result v3
-
-    .restart local v3    # "x":I
-    goto :goto_9
-.end method
-
-.method private static returnAdd(II)I
-    .registers 3
-    .param p0, "a"    # I
-    .param p1, "b"    # I
-
-    add-int v0, p0, p1
-
-    return v0
-.end method
-
-.method private static returnSub(II)I
-    .registers 3
-    .param p0, "a"    # I
-    .param p1, "b"    # I
-
-    sub-int v0, p0, p1
-
-    return v0
-.end method
diff --git a/test/441-checker-inliner/src/Main.java b/test/441-checker-inliner/src/Main.java
index 6c75962..9507b9d 100644
--- a/test/441-checker-inliner/src/Main.java
+++ b/test/441-checker-inliner/src/Main.java
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import java.lang.reflect.Method;
 
 public class Main {
 
@@ -125,18 +124,36 @@
     return incCounter();
   }
 
+  /// CHECK-START: int Main.InlineWithControlFlow(boolean) inliner (before)
+  /// CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
+  /// CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
+  /// CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
+  /// CHECK-DAG:     <<Add:i\d+>>    InvokeStaticOrDirect [<<Const1>>,<<Const3>>{{(,[ij]\d+)?}}]
+  /// CHECK-DAG:     <<Sub:i\d+>>    InvokeStaticOrDirect [<<Const5>>,<<Const3>>{{(,[ij]\d+)?}}]
+  /// CHECK-DAG:     <<Phi:i\d+>>    Phi [<<Add>>,<<Sub>>]
+  /// CHECK-DAG:                     Return [<<Phi>>]
+
+  /// CHECK-START: int Main.InlineWithControlFlow(boolean) inliner (after)
+  /// CHECK-DAG:     <<Const4:i\d+>> IntConstant 4
+  /// CHECK-DAG:     <<Const2:i\d+>> IntConstant 2
+  /// CHECK-DAG:     <<Phi:i\d+>>    Phi [<<Const4>>,<<Const2>>]
+  /// CHECK-DAG:                     Return [<<Phi>>]
+
   public static int InlineWithControlFlow(boolean cond) {
-    try {
-      Class<?> c = Class.forName("Smali");
-      Method m = c.getMethod("InlineWithControlFlow", boolean.class);
-      return (Integer) m.invoke(null, cond);
-    } catch (Throwable t) {
-      throw new RuntimeException(t);
+    int x, const1, const3, const5;
+    const1 = 1;
+    const3 = 3;
+    const5 = 5;
+    if (cond) {
+      x = returnAdd(const1, const3);
+    } else {
+      x = returnSub(const5, const3);
     }
+    return x;
   }
 
   /// CHECK-START: int Main.returnAbs(int) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>>      InvokeStaticOrDirect intrinsic:MathAbsInt
+  /// CHECK-DAG:     <<Result:i\d+>>      Abs
   /// CHECK-DAG:                          Return [<<Result>>]
 
   private static int returnAbs(int i) {
diff --git a/test/442-checker-constant-folding/expected.txt b/test/442-checker-constant-folding/expected-stderr.txt
similarity index 100%
rename from test/442-checker-constant-folding/expected.txt
rename to test/442-checker-constant-folding/expected-stderr.txt
diff --git a/test/442-checker-constant-folding/expected.txt b/test/442-checker-constant-folding/expected-stdout.txt
similarity index 100%
copy from test/442-checker-constant-folding/expected.txt
copy to test/442-checker-constant-folding/expected-stdout.txt
diff --git a/test/443-not-bool-inline/Android.bp b/test/443-not-bool-inline/Android.bp
new file mode 100644
index 0000000..706c992
--- /dev/null
+++ b/test/443-not-bool-inline/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `443-not-bool-inline`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-443-not-bool-inline",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-443-not-bool-inline-expected-stdout",
+        ":art-run-test-443-not-bool-inline-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-443-not-bool-inline-expected-stdout",
+    out: ["art-run-test-443-not-bool-inline-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-443-not-bool-inline-expected-stderr",
+    out: ["art-run-test-443-not-bool-inline-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/437-inline/expected.txt b/test/443-not-bool-inline/expected-stderr.txt
similarity index 100%
copy from test/437-inline/expected.txt
copy to test/443-not-bool-inline/expected-stderr.txt
diff --git a/test/443-not-bool-inline/expected.txt b/test/443-not-bool-inline/expected-stdout.txt
similarity index 100%
rename from test/443-not-bool-inline/expected.txt
rename to test/443-not-bool-inline/expected-stdout.txt
diff --git a/test/444-checker-nce/Android.bp b/test/444-checker-nce/Android.bp
new file mode 100644
index 0000000..de79050
--- /dev/null
+++ b/test/444-checker-nce/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `444-checker-nce`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-444-checker-nce",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-444-checker-nce-expected-stdout",
+        ":art-run-test-444-checker-nce-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-444-checker-nce-expected-stdout",
+    out: ["art-run-test-444-checker-nce-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-444-checker-nce-expected-stderr",
+    out: ["art-run-test-444-checker-nce-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/444-checker-nce/expected.txt b/test/444-checker-nce/expected-stderr.txt
similarity index 100%
rename from test/444-checker-nce/expected.txt
rename to test/444-checker-nce/expected-stderr.txt
diff --git a/test/444-checker-nce/expected.txt b/test/444-checker-nce/expected-stdout.txt
similarity index 100%
copy from test/444-checker-nce/expected.txt
copy to test/444-checker-nce/expected-stdout.txt
diff --git a/test/444-checker-nce/src/Main.java b/test/444-checker-nce/src/Main.java
index ddc2f77..1a8360e 100644
--- a/test/444-checker-nce/src/Main.java
+++ b/test/444-checker-nce/src/Main.java
@@ -227,7 +227,7 @@
   }
 
   public Main() {}
-  public Main(int dummy) {}
+  public Main(int unused) {}
 
   private Main g() {
     // avoids inlining
diff --git a/test/445-checker-licm/Android.bp b/test/445-checker-licm/Android.bp
new file mode 100644
index 0000000..0932efb
--- /dev/null
+++ b/test/445-checker-licm/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `445-checker-licm`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-445-checker-licm",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-445-checker-licm-expected-stdout",
+        ":art-run-test-445-checker-licm-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-445-checker-licm-expected-stdout",
+    out: ["art-run-test-445-checker-licm-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-445-checker-licm-expected-stderr",
+    out: ["art-run-test-445-checker-licm-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/444-checker-nce/expected.txt b/test/445-checker-licm/expected-stderr.txt
similarity index 100%
copy from test/444-checker-nce/expected.txt
copy to test/445-checker-licm/expected-stderr.txt
diff --git a/test/445-checker-licm/expected.txt b/test/445-checker-licm/expected-stdout.txt
similarity index 100%
rename from test/445-checker-licm/expected.txt
rename to test/445-checker-licm/expected-stdout.txt
diff --git a/test/445-checker-licm/src/Main.java b/test/445-checker-licm/src/Main.java
index 517aacd..a1db185 100644
--- a/test/445-checker-licm/src/Main.java
+++ b/test/445-checker-licm/src/Main.java
@@ -15,7 +15,7 @@
  */
 
 public class Main {
-  static class Dummy {
+  static class ValueHolder {
     static int getValue() {
       return 1;
     }
@@ -128,7 +128,7 @@
     int i = 0;
     int sum = 0;
     do {
-      sum += Dummy.getValue();
+      sum += ValueHolder.getValue();
       i++;
     } while (i < 10);
     return sum;
@@ -153,9 +153,6 @@
     return result;
   }
 
-  /// CHECK-START: int Main.invariantBoundIntrinsic(int) instruction_simplifier (before)
-  /// CHECK-DAG: InvokeStaticOrDirect loop:{{B\d+}}
-  //
   /// CHECK-START: int Main.invariantBoundIntrinsic(int) licm (before)
   /// CHECK-DAG: Abs loop:{{B\d+}}
 
@@ -175,9 +172,6 @@
     return result;
   }
 
-  /// CHECK-START: int Main.invariantBodyIntrinsic(int, int) instruction_simplifier (before)
-  /// CHECK-DAG: InvokeStaticOrDirect loop:{{B\d+}}
-
   /// CHECK-START: int Main.invariantBodyIntrinsic(int, int) licm (before)
   /// CHECK-DAG: Max loop:{{B\d+}}
 
diff --git a/test/446-checker-inliner2/Android.bp b/test/446-checker-inliner2/Android.bp
new file mode 100644
index 0000000..6f2e554
--- /dev/null
+++ b/test/446-checker-inliner2/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `446-checker-inliner2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-446-checker-inliner2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-446-checker-inliner2-expected-stdout",
+        ":art-run-test-446-checker-inliner2-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-446-checker-inliner2-expected-stdout",
+    out: ["art-run-test-446-checker-inliner2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-446-checker-inliner2-expected-stderr",
+    out: ["art-run-test-446-checker-inliner2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/446-checker-inliner2/expected.txt b/test/446-checker-inliner2/expected-stderr.txt
similarity index 100%
rename from test/446-checker-inliner2/expected.txt
rename to test/446-checker-inliner2/expected-stderr.txt
diff --git a/test/446-checker-inliner2/expected.txt b/test/446-checker-inliner2/expected-stdout.txt
similarity index 100%
copy from test/446-checker-inliner2/expected.txt
copy to test/446-checker-inliner2/expected-stdout.txt
diff --git a/test/447-checker-inliner3/Android.bp b/test/447-checker-inliner3/Android.bp
new file mode 100644
index 0000000..ee3b41b
--- /dev/null
+++ b/test/447-checker-inliner3/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `447-checker-inliner3`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-447-checker-inliner3",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-447-checker-inliner3-expected-stdout",
+        ":art-run-test-447-checker-inliner3-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-447-checker-inliner3-expected-stdout",
+    out: ["art-run-test-447-checker-inliner3-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-447-checker-inliner3-expected-stderr",
+    out: ["art-run-test-447-checker-inliner3-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/447-checker-inliner3/expected.txt b/test/447-checker-inliner3/expected-stderr.txt
similarity index 100%
rename from test/447-checker-inliner3/expected.txt
rename to test/447-checker-inliner3/expected-stderr.txt
diff --git a/test/447-checker-inliner3/expected.txt b/test/447-checker-inliner3/expected-stdout.txt
similarity index 100%
copy from test/447-checker-inliner3/expected.txt
copy to test/447-checker-inliner3/expected-stdout.txt
diff --git a/test/448-multiple-returns/expected.txt b/test/448-multiple-returns/expected-stderr.txt
similarity index 100%
rename from test/448-multiple-returns/expected.txt
rename to test/448-multiple-returns/expected-stderr.txt
diff --git a/test/448-multiple-returns/expected.txt b/test/448-multiple-returns/expected-stdout.txt
similarity index 100%
copy from test/448-multiple-returns/expected.txt
copy to test/448-multiple-returns/expected-stdout.txt
diff --git a/test/449-checker-bce-rem/Android.bp b/test/449-checker-bce-rem/Android.bp
new file mode 100644
index 0000000..d6f10ee
--- /dev/null
+++ b/test/449-checker-bce-rem/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `449-checker-bce-rem`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-449-checker-bce-rem",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-449-checker-bce-rem-expected-stdout",
+        ":art-run-test-449-checker-bce-rem-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-449-checker-bce-rem-expected-stdout",
+    out: ["art-run-test-449-checker-bce-rem-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-449-checker-bce-rem-expected-stderr",
+    out: ["art-run-test-449-checker-bce-rem-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/561-divrem/expected.txt b/test/449-checker-bce-rem/expected-stderr.txt
similarity index 100%
copy from test/561-divrem/expected.txt
copy to test/449-checker-bce-rem/expected-stderr.txt
diff --git a/test/561-divrem/expected.txt b/test/449-checker-bce-rem/expected-stdout.txt
similarity index 100%
copy from test/561-divrem/expected.txt
copy to test/449-checker-bce-rem/expected-stdout.txt
diff --git a/test/449-checker-bce-rem/info.txt b/test/449-checker-bce-rem/info.txt
new file mode 100644
index 0000000..946f38f
--- /dev/null
+++ b/test/449-checker-bce-rem/info.txt
@@ -0,0 +1,2 @@
+Checker test for BCE optimizations of integer remainder operations which are optimized into
+HDiv+HMul+HSub or HDiv+HShl+HAdd+HSub or HDiv+HShl+HSub+HSub.
diff --git a/test/449-checker-bce-rem/src/Main.java b/test/449-checker-bce-rem/src/Main.java
new file mode 100644
index 0000000..261a5f4
--- /dev/null
+++ b/test/449-checker-bce-rem/src/Main.java
@@ -0,0 +1,660 @@
+/*
+ * Copyright (C) 2020 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 {
+  private static void expectEquals(long expected, long result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  private static void remInt() {
+    expectEquals(1L << 32, $noinline$IntRemBy3(3));
+    expectEquals((3L << 32) | 6, $noinline$IntRemBy7(27));
+    expectEquals((1L << 32) | 1, $noinline$IntRemBy12(13));
+    expectEquals((1L << 32) | 1, $noinline$IntRemBy12A(13));
+  }
+
+  // A test case to check:
+  //  BCE detects the optimized 'v % 3' and eliminates bounds checks.
+  //
+  /// CHECK-START:       long Main.$noinline$IntRemBy3(int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK:                 BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       long Main.$noinline$IntRemBy3(int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NOT:             BoundsCheck
+  /// CHECK:                 ArrayGet
+  private static long $noinline$IntRemBy3(int v) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 3;
+      int r = v % 3;
+      return ((long)q << 32) | values[r];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  BCE detects the optimized 'v % 7' and eliminates bounds checks.
+  //
+  /// CHECK-START:       long Main.$noinline$IntRemBy7(int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK:                 BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       long Main.$noinline$IntRemBy7(int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NOT:             BoundsCheck
+  /// CHECK:                 ArrayGet
+  private static long $noinline$IntRemBy7(int v) {
+    int[] values = {0, 1, 2, 3, 4, 5, 6};
+    if (v > 0) {
+      int q = v / 7;
+      int r = v % 7;
+      return ((long)q << 32) | values[r];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  BCE detects the optimized 'v % 12' and eliminates bounds checks.
+  //
+  /// CHECK-START:       long Main.$noinline$IntRemBy12(int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK:                 BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       long Main.$noinline$IntRemBy12(int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NOT:             BoundsCheck
+  /// CHECK:                 ArrayGet
+  private static long $noinline$IntRemBy12(int v) {
+    int[] values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    if (v > 0) {
+      int q = v / 12;
+      int r = v % 12;
+      return ((long)q << 32) | values[r];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  BCE detects the optimized 'v % 12' and eliminates bounds checks.
+  //
+  /// CHECK-START:       long Main.$noinline$IntRemBy12A(int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK:                 BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       long Main.$noinline$IntRemBy12A(int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NOT:             BoundsCheck
+  /// CHECK:                 ArrayGet
+  private static long $noinline$IntRemBy12A(int v) {
+    int[] values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    if (v > 0) {
+      int q = v / 12;
+      int t = q * 12;
+      int r = v  - t;
+      return ((long)q << 32) | values[r];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  BCE detects the optimized 'v % Integer.MAX_VALUE' and eliminates bounds checks.
+  //
+  /// CHECK-START:       int Main.$noinline$IntRemByMaxInt(int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK:                 BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$IntRemByMaxInt(int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NOT:             BoundsCheck
+  /// CHECK:                 ArrayGet
+  private static int $noinline$IntRemByMaxInt(int v) {
+    int[] values = new int[Integer.MAX_VALUE];
+    if (v > 0) {
+      int q = v / Integer.MAX_VALUE;
+      int r = v % Integer.MAX_VALUE;
+      return values[v % Integer.MAX_VALUE] + q;
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  BCE detects the optimized 'v % Integer.MIN_VALUE' and eliminates bounds checks.
+  //
+  /// CHECK-START:       int Main.$noinline$IntRemByMinInt(int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK:                 BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$IntRemByMinInt(int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NOT:             BoundsCheck
+  /// CHECK:                 ArrayGet
+  private static int $noinline$IntRemByMinInt(int v) {
+    int[] values = new int[Integer.MAX_VALUE];
+    if (v > 0) {
+      int q = v / Integer.MIN_VALUE;
+      int t = q * Integer.MIN_VALUE;
+      int r = v - t;
+      return values[r - 1];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem01(int, int) BCE (before)
+  /// CHECK:                 Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem01(int, int) BCE (after)
+  /// CHECK:                 Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem01(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int a = v * 10;
+      int b = s - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem02(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem02(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem02(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int a = q * s;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem03(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem03(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem03(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int a = q + s;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem04(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem04(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem04(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int t = q << s;
+      int a = q + t;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem05(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem05(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem05(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int t = s << 1;
+      int a = q + t;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem06(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem06(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem06(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int a = q * 11;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem07(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem07(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem07(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int t = q << 1;
+      int a = s + t;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem08(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem08(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem08(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int t = q << 31;
+      int a = q + t;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem09(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem09(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Add
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem09(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int t = q << 1;
+      int a = q + t;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem10(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem10(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem10(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int t = q << s;
+      int a = t - q;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem11(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem11(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem11(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int t = s << 1;
+      int a = t - q;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem12(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem12(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem12(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int t = q << 1;
+      int a = t - s;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem13(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem13(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Shl
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem13(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int t = q << 31;
+      int a = t - q;
+      int b = v - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem14(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem14(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem14(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int a = v / 10;
+      int b = s - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  // A test case to check:
+  //  Bounds checks are not eliminated if the checked value is not an optimized HDiv+HRem.
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem15(int, int) BCE (before)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  //
+  /// CHECK-START:       int Main.$noinline$NoRem15(int, int) BCE (after)
+  /// CHECK:                 Div
+  /// CHECK-NEXT:            Mul
+  /// CHECK-NEXT:            Sub
+  /// CHECK-NEXT:            BoundsCheck
+  /// CHECK-NEXT:            ArrayGet
+  private static int $noinline$NoRem15(int v, int s) {
+    int[] values = {0, 1, 2};
+    if (v > 0) {
+      int q = v / 10;
+      int a = q * 10;
+      int b = s - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  /// CHECK-START:       int Main.$noinline$noRemNonConst(int, int) BCE (after)
+  /// CHECK:                 BoundsCheck
+  private static int $noinline$noRemNonConst(int v, int s) {
+    // Regression test for compiler crash, b/169669115.
+    int[] values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    if (v > 0) {
+      int q = v / s;  // Non-constant divisor.
+      int a = q * 10;  // Constant unrelated to the divisor above.
+      int b = s - a;
+      return values[b];
+    } else {
+      return -1;
+    }
+  }
+
+  public static void main(String args[]) {
+    remInt();
+  }
+}
diff --git a/test/449-checker-bce/Android.bp b/test/449-checker-bce/Android.bp
new file mode 100644
index 0000000..178c100
--- /dev/null
+++ b/test/449-checker-bce/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `449-checker-bce`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-449-checker-bce",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-449-checker-bce-expected-stdout",
+        ":art-run-test-449-checker-bce-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-449-checker-bce-expected-stdout",
+    out: ["art-run-test-449-checker-bce-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-449-checker-bce-expected-stderr",
+    out: ["art-run-test-449-checker-bce-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/444-checker-nce/expected.txt b/test/449-checker-bce/expected-stderr.txt
similarity index 100%
copy from test/444-checker-nce/expected.txt
copy to test/449-checker-bce/expected-stderr.txt
diff --git a/test/449-checker-bce/expected.txt b/test/449-checker-bce/expected-stdout.txt
similarity index 100%
rename from test/449-checker-bce/expected.txt
rename to test/449-checker-bce/expected-stdout.txt
diff --git a/test/450-checker-types/Android.bp b/test/450-checker-types/Android.bp
new file mode 100644
index 0000000..1173b5a
--- /dev/null
+++ b/test/450-checker-types/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `450-checker-types`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-450-checker-types",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-450-checker-types-expected-stdout",
+        ":art-run-test-450-checker-types-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-450-checker-types-expected-stdout",
+    out: ["art-run-test-450-checker-types-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-450-checker-types-expected-stderr",
+    out: ["art-run-test-450-checker-types-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/450-checker-types/expected.txt b/test/450-checker-types/expected-stderr.txt
similarity index 100%
rename from test/450-checker-types/expected.txt
rename to test/450-checker-types/expected-stderr.txt
diff --git a/test/450-checker-types/expected.txt b/test/450-checker-types/expected-stdout.txt
similarity index 100%
copy from test/450-checker-types/expected.txt
copy to test/450-checker-types/expected-stdout.txt
diff --git a/test/450-checker-types/smali/Main2.smali b/test/450-checker-types/smali/Main2.smali
deleted file mode 100644
index 5f11be3..0000000
--- a/test/450-checker-types/smali/Main2.smali
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-.class LMain2;
-.super Ljava/lang/Object;
-.source "Main2.java"
-
-
-# direct methods
-.method constructor <init>()V
-    .registers 1
-
-    .prologue
-    .line 17
-    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
-
-    return-void
-.end method
-
-## CHECK-START: void Main2.testArraySimpleRemove() instruction_simplifier (before)
-## CHECK:         CheckCast
-
-## CHECK-START: void Main2.testArraySimpleRemove() instruction_simplifier (after)
-## CHECK-NOT:     CheckCast
-
-.method static testArraySimpleRemove()V
-    .registers 3
-
-    .prologue
-    .line 19
-    const/16 v2, 0xa
-
-    new-array v0, v2, [LSubclassA;
-
-    .local v0, "b":[LSuper;
-    move-object v1, v0
-
-    .line 20
-    check-cast v1, [LSubclassA;
-
-    .line 21
-    .local v1, "c":[LSubclassA;
-    return-void
-.end method
diff --git a/test/450-checker-types/src/Main.java b/test/450-checker-types/src/Main.java
index 2351c23..084a713 100644
--- a/test/450-checker-types/src/Main.java
+++ b/test/450-checker-types/src/Main.java
@@ -463,6 +463,16 @@
 
   public SubclassA $noinline$getSubclass() { throw new RuntimeException(); }
 
+  /// CHECK-START: void Main.testArraySimpleRemove() instruction_simplifier (before)
+  /// CHECK:         CheckCast
+
+  /// CHECK-START: void Main.testArraySimpleRemove() instruction_simplifier (after)
+  /// CHECK-NOT:     CheckCast
+  public void testArraySimpleRemove() {
+    Super[] b = new SubclassA[10];
+    SubclassA[] c = (SubclassA[])b;
+  }
+
   /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (before)
   /// CHECK:         CheckCast
 
@@ -676,7 +686,7 @@
   /// CHECK-DAG:     <<Null:l\d+>>  NullConstant
   /// CHECK-DAG:     <<Phi:l\d+>>   Phi [<<Arg>>,<<Null>>] klass:SubclassA
   /// CHECK-DAG:     <<NCPhi:l\d+>> NullCheck [<<Phi>>]
-  /// CHECK-DAG:                    InvokeVirtual [<<NCPhi>>] method_name:java.lang.Object.hashCode
+  /// CHECK-DAG:                    InvokeStaticOrDirect [<<NCPhi>>] method_name:java.lang.Object.hashCode
 
   public void testThisArgumentMoreSpecific(boolean cond) {
     // Inlining method from Super will build it with `this` typed as Super.
diff --git a/test/451-regression-add-float/Android.bp b/test/451-regression-add-float/Android.bp
new file mode 100644
index 0000000..26d7d0a
--- /dev/null
+++ b/test/451-regression-add-float/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `451-regression-add-float`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-451-regression-add-float",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-451-regression-add-float-expected-stdout",
+        ":art-run-test-451-regression-add-float-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-451-regression-add-float-expected-stdout",
+    out: ["art-run-test-451-regression-add-float-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-451-regression-add-float-expected-stderr",
+    out: ["art-run-test-451-regression-add-float-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/451-regression-add-float/expected.txt b/test/451-regression-add-float/expected-stderr.txt
similarity index 100%
rename from test/451-regression-add-float/expected.txt
rename to test/451-regression-add-float/expected-stderr.txt
diff --git a/test/451-regression-add-float/expected.txt b/test/451-regression-add-float/expected-stdout.txt
similarity index 100%
copy from test/451-regression-add-float/expected.txt
copy to test/451-regression-add-float/expected-stdout.txt
diff --git a/test/451-spill-splot/Android.bp b/test/451-spill-splot/Android.bp
new file mode 100644
index 0000000..d773673
--- /dev/null
+++ b/test/451-spill-splot/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `451-spill-splot`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-451-spill-splot",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-451-spill-splot-expected-stdout",
+        ":art-run-test-451-spill-splot-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-451-spill-splot-expected-stdout",
+    out: ["art-run-test-451-spill-splot-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-451-spill-splot-expected-stderr",
+    out: ["art-run-test-451-spill-splot-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/424-checkcast/expected.txt b/test/451-spill-splot/expected-stderr.txt
similarity index 100%
copy from test/424-checkcast/expected.txt
copy to test/451-spill-splot/expected-stderr.txt
diff --git a/test/451-spill-splot/expected.txt b/test/451-spill-splot/expected-stdout.txt
similarity index 100%
rename from test/451-spill-splot/expected.txt
rename to test/451-spill-splot/expected-stdout.txt
diff --git a/test/452-multiple-returns2/expected.txt b/test/452-multiple-returns2/expected-stderr.txt
similarity index 100%
rename from test/452-multiple-returns2/expected.txt
rename to test/452-multiple-returns2/expected-stderr.txt
diff --git a/test/452-multiple-returns2/expected.txt b/test/452-multiple-returns2/expected-stdout.txt
similarity index 100%
copy from test/452-multiple-returns2/expected.txt
copy to test/452-multiple-returns2/expected-stdout.txt
diff --git a/test/453-not-byte/expected.txt b/test/453-not-byte/expected-stderr.txt
similarity index 100%
rename from test/453-not-byte/expected.txt
rename to test/453-not-byte/expected-stderr.txt
diff --git a/test/453-not-byte/expected.txt b/test/453-not-byte/expected-stdout.txt
similarity index 100%
copy from test/453-not-byte/expected.txt
copy to test/453-not-byte/expected-stdout.txt
diff --git a/test/454-get-vreg/Android.bp b/test/454-get-vreg/Android.bp
new file mode 100644
index 0000000..5fcb974
--- /dev/null
+++ b/test/454-get-vreg/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `454-get-vreg`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-454-get-vreg",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-454-get-vreg-expected-stdout",
+        ":art-run-test-454-get-vreg-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-454-get-vreg-expected-stdout",
+    out: ["art-run-test-454-get-vreg-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-454-get-vreg-expected-stderr",
+    out: ["art-run-test-454-get-vreg-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/408-move-bug/expected.txt b/test/454-get-vreg/expected-stderr.txt
similarity index 100%
copy from test/408-move-bug/expected.txt
copy to test/454-get-vreg/expected-stderr.txt
diff --git a/test/454-get-vreg/expected.txt b/test/454-get-vreg/expected-stdout.txt
similarity index 100%
rename from test/454-get-vreg/expected.txt
rename to test/454-get-vreg/expected-stdout.txt
diff --git a/test/455-checker-gvn/Android.bp b/test/455-checker-gvn/Android.bp
new file mode 100644
index 0000000..2e36616
--- /dev/null
+++ b/test/455-checker-gvn/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `455-checker-gvn`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-455-checker-gvn",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-455-checker-gvn-expected-stdout",
+        ":art-run-test-455-checker-gvn-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-455-checker-gvn-expected-stdout",
+    out: ["art-run-test-455-checker-gvn-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-455-checker-gvn-expected-stderr",
+    out: ["art-run-test-455-checker-gvn-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/465-checker-clinit-gvn/expected.txt b/test/455-checker-gvn/expected-stderr.txt
similarity index 100%
copy from test/465-checker-clinit-gvn/expected.txt
copy to test/455-checker-gvn/expected-stderr.txt
diff --git a/test/455-checker-gvn/expected-stdout.txt b/test/455-checker-gvn/expected-stdout.txt
new file mode 100644
index 0000000..32dd8f5
--- /dev/null
+++ b/test/455-checker-gvn/expected-stdout.txt
@@ -0,0 +1,4 @@
+14
+0
+10
+45
diff --git a/test/455-checker-gvn/expected.txt b/test/455-checker-gvn/expected.txt
deleted file mode 100644
index c1679c7..0000000
--- a/test/455-checker-gvn/expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-14
-0
-10
diff --git a/test/455-checker-gvn/smali/Smali.smali b/test/455-checker-gvn/smali/Smali.smali
deleted file mode 100644
index fbeb4db..0000000
--- a/test/455-checker-gvn/smali/Smali.smali
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-.class public LSmali;
-.super Ljava/lang/Object;
-
-## CHECK-START: int Smali.foo(int, int) GVN (before)
-## CHECK: Add
-## CHECK: Add
-## CHECK: Add
-
-## CHECK-START: int Smali.foo(int, int) GVN (after)
-## CHECK: Add
-## CHECK: Add
-## CHECK-NOT: Add
-.method public static foo(II)I
-
-    # int sum1 = x + y;
-    # int sum2 = y + x;
-    # return sum1 + sum2;
-
-    .registers 5
-    .param p0, "x"    # I
-    .param p1, "y"    # I
-
-    add-int v0, p0, p1
-    add-int v1, p1, p0
-    add-int v2, v0, v1
-
-    return v2
-.end method
-
diff --git a/test/455-checker-gvn/src/Main.java b/test/455-checker-gvn/src/Main.java
index 74b1839..1177e40 100644
--- a/test/455-checker-gvn/src/Main.java
+++ b/test/455-checker-gvn/src/Main.java
@@ -21,22 +21,32 @@
   private static int mY = -3;
 
   public static void main(String[] args) {
-    System.out.println(foo(3, 4));
-    System.out.println(mulAndIntrinsic());
-    System.out.println(directIntrinsic(-5));
+    System.out.println($noinline$foo(3, 4));
+    System.out.println($noinline$mulAndIntrinsic());
+    System.out.println($noinline$directIntrinsic(-5));
+    System.out.println($noinline$deoptimizeArray(new int[100]));
   }
 
-  public static int foo(int x, int y) {
-   try {
-      Class<?> c = Class.forName("Smali");
-      Method m = c.getMethod("foo", int.class, int.class);
-      return (Integer) m.invoke(null, x, y);
-    } catch (Throwable t) {
-      throw new RuntimeException(t);
-    }
+  private static int $inline$add(int a, int b) {
+    return a + b;
   }
 
-  /// CHECK-START: int Main.mulAndIntrinsic() GVN (before)
+  /// CHECK-START: int Main.$noinline$foo(int, int) GVN (before)
+  /// CHECK: Add
+  /// CHECK: Add
+  /// CHECK: Add
+
+  /// CHECK-START: int Main.$noinline$foo(int, int) GVN (after)
+  /// CHECK: Add
+  /// CHECK: Add
+  /// CHECK-NOT: Add
+  public static int $noinline$foo(int x, int y) {
+    int sum1 = $inline$add(x, y);
+    int sum2 = $inline$add(y, x);
+    return sum1 + sum2;
+  }
+
+  /// CHECK-START: int Main.$noinline$mulAndIntrinsic() GVN (before)
   /// CHECK: StaticFieldGet
   /// CHECK: StaticFieldGet
   /// CHECK: Mul
@@ -46,7 +56,7 @@
   /// CHECK: Mul
   /// CHECK: Add
 
-  /// CHECK-START: int Main.mulAndIntrinsic() GVN (after)
+  /// CHECK-START: int Main.$noinline$mulAndIntrinsic() GVN (after)
   /// CHECK: StaticFieldGet
   /// CHECK: StaticFieldGet
   /// CHECK: Mul
@@ -56,7 +66,7 @@
   /// CHECK-NOT: Mul
   /// CHECK: Add
 
-  public static int mulAndIntrinsic() {
+  public static int $noinline$mulAndIntrinsic() {
     // The intermediate call to abs() does not kill
     // the common subexpression on the multiplication.
     int mul1 = mX * mY;
@@ -65,21 +75,53 @@
     return abs + mul2;
   }
 
-  /// CHECK-START: int Main.directIntrinsic(int) GVN (before)
+  /// CHECK-START: int Main.$noinline$directIntrinsic(int) GVN (before)
   /// CHECK: Abs
   /// CHECK: Abs
   /// CHECK: Add
 
-  /// CHECK-START: int Main.directIntrinsic(int) GVN (after)
+  /// CHECK-START: int Main.$noinline$directIntrinsic(int) GVN (after)
   /// CHECK: Abs
   /// CHECK-NOT: Abs
   /// CHECK: Add
 
-  public static int directIntrinsic(int x) {
+  public static int $noinline$directIntrinsic(int x) {
     // Here, the two calls to abs() themselves can be replaced with just one.
     int abs1 = Math.abs(x);
     int abs2 = Math.abs(x);
     return abs1 + abs2;
   }
 
+  public static class MyList {
+    public int[] arr;
+  }
+
+  // The 4 deoptimize are pairs of checking for null and array-length. The
+  // repetition is due to the two loops.
+  // NB This is a very degenerate example and improvements to our analysis could
+  // allow for this entire function to be removed.
+  /// CHECK-START: int Main.$noinline$deoptimizeArray(int[]) GVN$after_arch (before)
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: Deoptimize
+  // Get rid of redundant deoptimizes
+  /// CHECK-START: int Main.$noinline$deoptimizeArray(int[]) GVN$after_arch (after)
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: Deoptimize
+  public static int $noinline$deoptimizeArray(int[] arr) {
+    if (arr == null) {
+      arr = new int[100];
+    }
+    for (int i = 0; i < 10; i++) {
+      arr[i] = i;
+    }
+    int sum = 0;
+    for (int i = 0; i < 10; i++) {
+      sum += arr[i];
+    }
+    return sum;
+  }
 }
diff --git a/test/456-baseline-array-set/Android.bp b/test/456-baseline-array-set/Android.bp
new file mode 100644
index 0000000..28d83d0
--- /dev/null
+++ b/test/456-baseline-array-set/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `456-baseline-array-set`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-456-baseline-array-set",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-456-baseline-array-set-expected-stdout",
+        ":art-run-test-456-baseline-array-set-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-456-baseline-array-set-expected-stdout",
+    out: ["art-run-test-456-baseline-array-set-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-456-baseline-array-set-expected-stderr",
+    out: ["art-run-test-456-baseline-array-set-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/456-baseline-array-set/expected.txt b/test/456-baseline-array-set/expected-stderr.txt
similarity index 100%
rename from test/456-baseline-array-set/expected.txt
rename to test/456-baseline-array-set/expected-stderr.txt
diff --git a/test/456-baseline-array-set/expected.txt b/test/456-baseline-array-set/expected-stdout.txt
similarity index 100%
copy from test/456-baseline-array-set/expected.txt
copy to test/456-baseline-array-set/expected-stdout.txt
diff --git a/test/406-fields/expected.txt b/test/457-regs/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/457-regs/expected-stderr.txt
diff --git a/test/457-regs/expected-stdout.txt b/test/457-regs/expected-stdout.txt
new file mode 100644
index 0000000..8db7853
--- /dev/null
+++ b/test/457-regs/expected-stdout.txt
@@ -0,0 +1,2 @@
+JNI_OnLoad called
+JNI_OnLoad called
diff --git a/test/457-regs/run b/test/457-regs/run
new file mode 100644
index 0000000..2591855
--- /dev/null
+++ b/test/457-regs/run
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# Copyright (C) 2020 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.
+
+${RUN} "$@"
+return_status1=$?
+
+# Force baseline JIT compilation as the test explicitly requests JIT
+# compilation, which by default is 'optimizing'.
+${RUN} "$@" -Xcompiler-option --baseline
+return_status2=$?
+
+# Make sure we don't silently ignore an early failure.
+(exit $return_status1) && (exit $return_status2)
diff --git a/test/457-regs/src/Main.java b/test/457-regs/src/Main.java
index 3b8df44..428c913 100644
--- a/test/457-regs/src/Main.java
+++ b/test/457-regs/src/Main.java
@@ -27,17 +27,29 @@
     Class<?> c = Class.forName("PhiLiveness");
     Method m = c.getMethod("mergeOk", boolean.class, byte.class);
     m.invoke(null, new Boolean(true), new Byte((byte)2));
+    ensureMethodJitCompiled(m);
+    m.invoke(null, new Boolean(true), new Byte((byte)2));
 
     m = c.getMethod("mergeNotOk", boolean.class, float.class);
     m.invoke(null, new Boolean(true), new Float(4.0f));
+    ensureMethodJitCompiled(m);
+    m.invoke(null, new Boolean(true), new Float(4.0f));
 
     m = c.getMethod("mergeReferences", Main.class);
     m.invoke(null, new Main());
+    ensureMethodJitCompiled(m);
+    m.invoke(null, new Main());
 
     m = c.getMethod("phiEquivalent");
     m.invoke(null);
+    ensureMethodJitCompiled(m);
+    m.invoke(null);
 
     m = c.getMethod("phiAllEquivalents", Main.class);
     m.invoke(null, new Main());
+    ensureMethodJitCompiled(m);
+    m.invoke(null, new Main());
   }
+
+  public native static void ensureMethodJitCompiled(Method method);
 }
diff --git a/test/458-checker-instruct-simplification/expected.txt b/test/458-checker-instruct-simplification/expected-stderr.txt
similarity index 100%
rename from test/458-checker-instruct-simplification/expected.txt
rename to test/458-checker-instruct-simplification/expected-stderr.txt
diff --git a/test/458-checker-instruct-simplification/expected.txt b/test/458-checker-instruct-simplification/expected-stdout.txt
similarity index 100%
copy from test/458-checker-instruct-simplification/expected.txt
copy to test/458-checker-instruct-simplification/expected-stdout.txt
diff --git a/test/458-long-to-fpu/Android.bp b/test/458-long-to-fpu/Android.bp
new file mode 100644
index 0000000..efd612e
--- /dev/null
+++ b/test/458-long-to-fpu/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `458-long-to-fpu`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-458-long-to-fpu",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-458-long-to-fpu-expected-stdout",
+        ":art-run-test-458-long-to-fpu-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-458-long-to-fpu-expected-stdout",
+    out: ["art-run-test-458-long-to-fpu-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-458-long-to-fpu-expected-stderr",
+    out: ["art-run-test-458-long-to-fpu-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/450-checker-types/expected.txt b/test/458-long-to-fpu/expected-stderr.txt
similarity index 100%
copy from test/450-checker-types/expected.txt
copy to test/458-long-to-fpu/expected-stderr.txt
diff --git a/test/458-long-to-fpu/expected.txt b/test/458-long-to-fpu/expected-stdout.txt
similarity index 100%
rename from test/458-long-to-fpu/expected.txt
rename to test/458-long-to-fpu/expected-stdout.txt
diff --git a/test/458-long-to-fpu/src/Main.java b/test/458-long-to-fpu/src/Main.java
index d1615dc..1e1df87 100644
--- a/test/458-long-to-fpu/src/Main.java
+++ b/test/458-long-to-fpu/src/Main.java
@@ -20,24 +20,13 @@
     System.out.println($noinline$DoubleConvert(false));
   }
 
-  // A dummy value to defeat inlining of these routines.
-  static boolean doThrow = false;
-
   public static long $noinline$FloatConvert(boolean flag) {
-    // Try defeating inlining.
-    if (doThrow) {
-      throw new Error();
-    }
     long l = myLong;
     myFloat = (float)l;
     return l;
   }
 
   public static long $noinline$DoubleConvert(boolean flag) {
-    // Try defeating inlining.
-    if (doThrow) {
-      throw new Error();
-    }
     long l = myLong;
     myDouble = (double)l;
     return l;
diff --git a/test/453-not-byte/expected.txt b/test/459-dead-phi/expected-stderr.txt
similarity index 100%
copy from test/453-not-byte/expected.txt
copy to test/459-dead-phi/expected-stderr.txt
diff --git a/test/459-dead-phi/expected.txt b/test/459-dead-phi/expected-stdout.txt
similarity index 100%
rename from test/459-dead-phi/expected.txt
rename to test/459-dead-phi/expected-stdout.txt
diff --git a/test/460-multiple-returns3/expected.txt b/test/460-multiple-returns3/expected-stderr.txt
similarity index 100%
rename from test/460-multiple-returns3/expected.txt
rename to test/460-multiple-returns3/expected-stderr.txt
diff --git a/test/460-multiple-returns3/expected.txt b/test/460-multiple-returns3/expected-stdout.txt
similarity index 100%
copy from test/460-multiple-returns3/expected.txt
copy to test/460-multiple-returns3/expected-stdout.txt
diff --git a/test/461-get-reference-vreg/Android.bp b/test/461-get-reference-vreg/Android.bp
new file mode 100644
index 0000000..3793c59
--- /dev/null
+++ b/test/461-get-reference-vreg/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `461-get-reference-vreg`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-461-get-reference-vreg",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-461-get-reference-vreg-expected-stdout",
+        ":art-run-test-461-get-reference-vreg-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-461-get-reference-vreg-expected-stdout",
+    out: ["art-run-test-461-get-reference-vreg-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-461-get-reference-vreg-expected-stderr",
+    out: ["art-run-test-461-get-reference-vreg-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/408-move-bug/expected.txt b/test/461-get-reference-vreg/expected-stderr.txt
similarity index 100%
copy from test/408-move-bug/expected.txt
copy to test/461-get-reference-vreg/expected-stderr.txt
diff --git a/test/461-get-reference-vreg/expected.txt b/test/461-get-reference-vreg/expected-stdout.txt
similarity index 100%
rename from test/461-get-reference-vreg/expected.txt
rename to test/461-get-reference-vreg/expected-stdout.txt
diff --git a/test/462-checker-inlining-dex-files/expected.txt b/test/462-checker-inlining-dex-files/expected-stderr.txt
similarity index 100%
rename from test/462-checker-inlining-dex-files/expected.txt
rename to test/462-checker-inlining-dex-files/expected-stderr.txt
diff --git a/test/462-checker-inlining-dex-files/expected.txt b/test/462-checker-inlining-dex-files/expected-stdout.txt
similarity index 100%
copy from test/462-checker-inlining-dex-files/expected.txt
copy to test/462-checker-inlining-dex-files/expected-stdout.txt
diff --git a/test/463-checker-boolean-simplifier/expected.txt b/test/463-checker-boolean-simplifier/expected-stderr.txt
similarity index 100%
rename from test/463-checker-boolean-simplifier/expected.txt
rename to test/463-checker-boolean-simplifier/expected-stderr.txt
diff --git a/test/463-checker-boolean-simplifier/expected.txt b/test/463-checker-boolean-simplifier/expected-stdout.txt
similarity index 100%
copy from test/463-checker-boolean-simplifier/expected.txt
copy to test/463-checker-boolean-simplifier/expected-stdout.txt
diff --git a/test/464-checker-inline-sharpen-calls/Android.bp b/test/464-checker-inline-sharpen-calls/Android.bp
new file mode 100644
index 0000000..aeff431
--- /dev/null
+++ b/test/464-checker-inline-sharpen-calls/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `464-checker-inline-sharpen-calls`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-464-checker-inline-sharpen-calls",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-464-checker-inline-sharpen-calls-expected-stdout",
+        ":art-run-test-464-checker-inline-sharpen-calls-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-464-checker-inline-sharpen-calls-expected-stdout",
+    out: ["art-run-test-464-checker-inline-sharpen-calls-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-464-checker-inline-sharpen-calls-expected-stderr",
+    out: ["art-run-test-464-checker-inline-sharpen-calls-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/464-checker-inline-sharpen-calls/expected.txt b/test/464-checker-inline-sharpen-calls/expected-stderr.txt
similarity index 100%
rename from test/464-checker-inline-sharpen-calls/expected.txt
rename to test/464-checker-inline-sharpen-calls/expected-stderr.txt
diff --git a/test/464-checker-inline-sharpen-calls/expected.txt b/test/464-checker-inline-sharpen-calls/expected-stdout.txt
similarity index 100%
copy from test/464-checker-inline-sharpen-calls/expected.txt
copy to test/464-checker-inline-sharpen-calls/expected-stdout.txt
diff --git a/test/465-checker-clinit-gvn/Android.bp b/test/465-checker-clinit-gvn/Android.bp
new file mode 100644
index 0000000..eef374c
--- /dev/null
+++ b/test/465-checker-clinit-gvn/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `465-checker-clinit-gvn`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-465-checker-clinit-gvn",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-465-checker-clinit-gvn-expected-stdout",
+        ":art-run-test-465-checker-clinit-gvn-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-465-checker-clinit-gvn-expected-stdout",
+    out: ["art-run-test-465-checker-clinit-gvn-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-465-checker-clinit-gvn-expected-stderr",
+    out: ["art-run-test-465-checker-clinit-gvn-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/465-checker-clinit-gvn/expected.txt b/test/465-checker-clinit-gvn/expected-stderr.txt
similarity index 100%
rename from test/465-checker-clinit-gvn/expected.txt
rename to test/465-checker-clinit-gvn/expected-stderr.txt
diff --git a/test/465-checker-clinit-gvn/expected.txt b/test/465-checker-clinit-gvn/expected-stdout.txt
similarity index 100%
copy from test/465-checker-clinit-gvn/expected.txt
copy to test/465-checker-clinit-gvn/expected-stdout.txt
diff --git a/test/466-get-live-vreg/Android.bp b/test/466-get-live-vreg/Android.bp
new file mode 100644
index 0000000..f4707f4
--- /dev/null
+++ b/test/466-get-live-vreg/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `466-get-live-vreg`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-466-get-live-vreg",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-466-get-live-vreg-expected-stdout",
+        ":art-run-test-466-get-live-vreg-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-466-get-live-vreg-expected-stdout",
+    out: ["art-run-test-466-get-live-vreg-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-466-get-live-vreg-expected-stderr",
+    out: ["art-run-test-466-get-live-vreg-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/408-move-bug/expected.txt b/test/466-get-live-vreg/expected-stderr.txt
similarity index 100%
copy from test/408-move-bug/expected.txt
copy to test/466-get-live-vreg/expected-stderr.txt
diff --git a/test/466-get-live-vreg/expected.txt b/test/466-get-live-vreg/expected-stdout.txt
similarity index 100%
rename from test/466-get-live-vreg/expected.txt
rename to test/466-get-live-vreg/expected-stdout.txt
diff --git a/test/429-ssa-builder/expected.txt b/test/467-regalloc-pair/expected-stderr.txt
similarity index 100%
copy from test/429-ssa-builder/expected.txt
copy to test/467-regalloc-pair/expected-stderr.txt
diff --git a/test/467-regalloc-pair/expected.txt b/test/467-regalloc-pair/expected-stdout.txt
similarity index 100%
rename from test/467-regalloc-pair/expected.txt
rename to test/467-regalloc-pair/expected-stdout.txt
diff --git a/test/468-checker-bool-simplif-regression/expected.txt b/test/468-checker-bool-simplif-regression/expected-stderr.txt
similarity index 100%
rename from test/468-checker-bool-simplif-regression/expected.txt
rename to test/468-checker-bool-simplif-regression/expected-stderr.txt
diff --git a/test/468-checker-bool-simplif-regression/expected.txt b/test/468-checker-bool-simplif-regression/expected-stdout.txt
similarity index 100%
copy from test/468-checker-bool-simplif-regression/expected.txt
copy to test/468-checker-bool-simplif-regression/expected-stdout.txt
diff --git a/test/469-condition-materialization/Android.bp b/test/469-condition-materialization/Android.bp
new file mode 100644
index 0000000..c986141
--- /dev/null
+++ b/test/469-condition-materialization/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `469-condition-materialization`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-469-condition-materialization",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-469-condition-materialization-expected-stdout",
+        ":art-run-test-469-condition-materialization-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-469-condition-materialization-expected-stdout",
+    out: ["art-run-test-469-condition-materialization-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-469-condition-materialization-expected-stderr",
+    out: ["art-run-test-469-condition-materialization-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/469-condition-materialization/expected.txt b/test/469-condition-materialization/expected-stderr.txt
similarity index 100%
rename from test/469-condition-materialization/expected.txt
rename to test/469-condition-materialization/expected-stderr.txt
diff --git a/test/469-condition-materialization/expected.txt b/test/469-condition-materialization/expected-stdout.txt
similarity index 100%
copy from test/469-condition-materialization/expected.txt
copy to test/469-condition-materialization/expected-stdout.txt
diff --git a/test/470-huge-method/Android.bp b/test/470-huge-method/Android.bp
new file mode 100644
index 0000000..e5cabea
--- /dev/null
+++ b/test/470-huge-method/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `470-huge-method`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-470-huge-method",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-470-huge-method-expected-stdout",
+        ":art-run-test-470-huge-method-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-470-huge-method-expected-stdout",
+    out: ["art-run-test-470-huge-method-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-470-huge-method-expected-stderr",
+    out: ["art-run-test-470-huge-method-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/470-huge-method/expected.txt b/test/470-huge-method/expected-stderr.txt
similarity index 100%
rename from test/470-huge-method/expected.txt
rename to test/470-huge-method/expected-stderr.txt
diff --git a/test/470-huge-method/expected.txt b/test/470-huge-method/expected-stdout.txt
similarity index 100%
copy from test/470-huge-method/expected.txt
copy to test/470-huge-method/expected-stdout.txt
diff --git a/test/471-deopt-environment/Android.bp b/test/471-deopt-environment/Android.bp
new file mode 100644
index 0000000..d0eaca3
--- /dev/null
+++ b/test/471-deopt-environment/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `471-deopt-environment`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-471-deopt-environment",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-471-deopt-environment-expected-stdout",
+        ":art-run-test-471-deopt-environment-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-471-deopt-environment-expected-stdout",
+    out: ["art-run-test-471-deopt-environment-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-471-deopt-environment-expected-stderr",
+    out: ["art-run-test-471-deopt-environment-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/471-deopt-environment/expected.txt b/test/471-deopt-environment/expected-stderr.txt
similarity index 100%
rename from test/471-deopt-environment/expected.txt
rename to test/471-deopt-environment/expected-stderr.txt
diff --git a/test/471-deopt-environment/expected.txt b/test/471-deopt-environment/expected-stdout.txt
similarity index 100%
copy from test/471-deopt-environment/expected.txt
copy to test/471-deopt-environment/expected-stdout.txt
diff --git a/test/471-uninitialized-locals/expected.txt b/test/471-uninitialized-locals/expected-stderr.txt
similarity index 100%
rename from test/471-uninitialized-locals/expected.txt
rename to test/471-uninitialized-locals/expected-stderr.txt
diff --git a/test/471-uninitialized-locals/expected.txt b/test/471-uninitialized-locals/expected-stdout.txt
similarity index 100%
copy from test/471-uninitialized-locals/expected.txt
copy to test/471-uninitialized-locals/expected-stdout.txt
diff --git a/test/472-type-propagation/Android.bp b/test/472-type-propagation/Android.bp
new file mode 100644
index 0000000..247e222
--- /dev/null
+++ b/test/472-type-propagation/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `472-type-propagation`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-472-type-propagation",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-472-type-propagation-expected-stdout",
+        ":art-run-test-472-type-propagation-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-472-type-propagation-expected-stdout",
+    out: ["art-run-test-472-type-propagation-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-472-type-propagation-expected-stderr",
+    out: ["art-run-test-472-type-propagation-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/505-simplifier-type-propagation/expected.txt b/test/472-type-propagation/expected-stderr.txt
similarity index 100%
copy from test/505-simplifier-type-propagation/expected.txt
copy to test/472-type-propagation/expected-stderr.txt
diff --git a/test/472-type-propagation/expected.txt b/test/472-type-propagation/expected-stdout.txt
similarity index 100%
rename from test/472-type-propagation/expected.txt
rename to test/472-type-propagation/expected-stdout.txt
diff --git a/test/413-regalloc-regression/expected.txt b/test/472-unreachable-if-regression/expected-stderr.txt
similarity index 100%
copy from test/413-regalloc-regression/expected.txt
copy to test/472-unreachable-if-regression/expected-stderr.txt
diff --git a/test/472-unreachable-if-regression/expected.txt b/test/472-unreachable-if-regression/expected-stdout.txt
similarity index 100%
rename from test/472-unreachable-if-regression/expected.txt
rename to test/472-unreachable-if-regression/expected-stdout.txt
diff --git a/test/473-checker-inliner-constants/Android.bp b/test/473-checker-inliner-constants/Android.bp
new file mode 100644
index 0000000..4768c70
--- /dev/null
+++ b/test/473-checker-inliner-constants/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `473-checker-inliner-constants`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-473-checker-inliner-constants",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-473-checker-inliner-constants-expected-stdout",
+        ":art-run-test-473-checker-inliner-constants-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-473-checker-inliner-constants-expected-stdout",
+    out: ["art-run-test-473-checker-inliner-constants-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-473-checker-inliner-constants-expected-stderr",
+    out: ["art-run-test-473-checker-inliner-constants-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/473-checker-inliner-constants/expected.txt b/test/473-checker-inliner-constants/expected-stderr.txt
similarity index 100%
rename from test/473-checker-inliner-constants/expected.txt
rename to test/473-checker-inliner-constants/expected-stderr.txt
diff --git a/test/473-checker-inliner-constants/expected.txt b/test/473-checker-inliner-constants/expected-stdout.txt
similarity index 100%
copy from test/473-checker-inliner-constants/expected.txt
copy to test/473-checker-inliner-constants/expected-stdout.txt
diff --git a/test/473-remove-dead-block/Android.bp b/test/473-remove-dead-block/Android.bp
new file mode 100644
index 0000000..ea41453
--- /dev/null
+++ b/test/473-remove-dead-block/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `473-remove-dead-block`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-473-remove-dead-block",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-473-remove-dead-block-expected-stdout",
+        ":art-run-test-473-remove-dead-block-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-473-remove-dead-block-expected-stdout",
+    out: ["art-run-test-473-remove-dead-block-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-473-remove-dead-block-expected-stderr",
+    out: ["art-run-test-473-remove-dead-block-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/470-huge-method/expected.txt b/test/473-remove-dead-block/expected-stderr.txt
similarity index 100%
copy from test/470-huge-method/expected.txt
copy to test/473-remove-dead-block/expected-stderr.txt
diff --git a/test/473-remove-dead-block/expected.txt b/test/473-remove-dead-block/expected-stdout.txt
similarity index 100%
rename from test/473-remove-dead-block/expected.txt
rename to test/473-remove-dead-block/expected-stdout.txt
diff --git a/test/474-checker-boolean-input/Android.bp b/test/474-checker-boolean-input/Android.bp
new file mode 100644
index 0000000..505d4c2
--- /dev/null
+++ b/test/474-checker-boolean-input/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `474-checker-boolean-input`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-474-checker-boolean-input",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-474-checker-boolean-input-expected-stdout",
+        ":art-run-test-474-checker-boolean-input-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-474-checker-boolean-input-expected-stdout",
+    out: ["art-run-test-474-checker-boolean-input-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-474-checker-boolean-input-expected-stderr",
+    out: ["art-run-test-474-checker-boolean-input-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/474-checker-boolean-input/expected.txt b/test/474-checker-boolean-input/expected-stderr.txt
similarity index 100%
rename from test/474-checker-boolean-input/expected.txt
rename to test/474-checker-boolean-input/expected-stderr.txt
diff --git a/test/474-checker-boolean-input/expected.txt b/test/474-checker-boolean-input/expected-stdout.txt
similarity index 100%
copy from test/474-checker-boolean-input/expected.txt
copy to test/474-checker-boolean-input/expected-stdout.txt
diff --git a/test/474-fp-sub-neg/Android.bp b/test/474-fp-sub-neg/Android.bp
new file mode 100644
index 0000000..2d61503
--- /dev/null
+++ b/test/474-fp-sub-neg/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `474-fp-sub-neg`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-474-fp-sub-neg",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-474-fp-sub-neg-expected-stdout",
+        ":art-run-test-474-fp-sub-neg-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-474-fp-sub-neg-expected-stdout",
+    out: ["art-run-test-474-fp-sub-neg-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-474-fp-sub-neg-expected-stderr",
+    out: ["art-run-test-474-fp-sub-neg-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/408-move-bug/expected.txt b/test/474-fp-sub-neg/expected-stderr.txt
similarity index 100%
copy from test/408-move-bug/expected.txt
copy to test/474-fp-sub-neg/expected-stderr.txt
diff --git a/test/474-fp-sub-neg/expected.txt b/test/474-fp-sub-neg/expected-stdout.txt
similarity index 100%
rename from test/474-fp-sub-neg/expected.txt
rename to test/474-fp-sub-neg/expected-stdout.txt
diff --git a/test/475-regression-inliner-ids/expected.txt b/test/475-regression-inliner-ids/expected-stderr.txt
similarity index 100%
rename from test/475-regression-inliner-ids/expected.txt
rename to test/475-regression-inliner-ids/expected-stderr.txt
diff --git a/test/475-regression-inliner-ids/expected.txt b/test/475-regression-inliner-ids/expected-stdout.txt
similarity index 100%
copy from test/475-regression-inliner-ids/expected.txt
copy to test/475-regression-inliner-ids/expected-stdout.txt
diff --git a/test/475-simplify-mul-zero/Android.bp b/test/475-simplify-mul-zero/Android.bp
new file mode 100644
index 0000000..0e9dfd5
--- /dev/null
+++ b/test/475-simplify-mul-zero/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `475-simplify-mul-zero`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-475-simplify-mul-zero",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-475-simplify-mul-zero-expected-stdout",
+        ":art-run-test-475-simplify-mul-zero-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-475-simplify-mul-zero-expected-stdout",
+    out: ["art-run-test-475-simplify-mul-zero-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-475-simplify-mul-zero-expected-stderr",
+    out: ["art-run-test-475-simplify-mul-zero-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/583-checker-zero/expected.txt b/test/475-simplify-mul-zero/expected-stderr.txt
similarity index 100%
copy from test/583-checker-zero/expected.txt
copy to test/475-simplify-mul-zero/expected-stderr.txt
diff --git a/test/475-simplify-mul-zero/expected.txt b/test/475-simplify-mul-zero/expected-stdout.txt
similarity index 100%
rename from test/475-simplify-mul-zero/expected.txt
rename to test/475-simplify-mul-zero/expected-stdout.txt
diff --git a/test/476-checker-ctor-fence-redun-elim/Android.bp b/test/476-checker-ctor-fence-redun-elim/Android.bp
new file mode 100644
index 0000000..a3db914
--- /dev/null
+++ b/test/476-checker-ctor-fence-redun-elim/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `476-checker-ctor-fence-redun-elim`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-476-checker-ctor-fence-redun-elim",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-476-checker-ctor-fence-redun-elim-expected-stdout",
+        ":art-run-test-476-checker-ctor-fence-redun-elim-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-476-checker-ctor-fence-redun-elim-expected-stdout",
+    out: ["art-run-test-476-checker-ctor-fence-redun-elim-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-476-checker-ctor-fence-redun-elim-expected-stderr",
+    out: ["art-run-test-476-checker-ctor-fence-redun-elim-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/476-checker-ctor-fence-redun-elim/expected.txt b/test/476-checker-ctor-fence-redun-elim/expected-stderr.txt
similarity index 100%
rename from test/476-checker-ctor-fence-redun-elim/expected.txt
rename to test/476-checker-ctor-fence-redun-elim/expected-stderr.txt
diff --git a/test/476-checker-ctor-fence-redun-elim/expected.txt b/test/476-checker-ctor-fence-redun-elim/expected-stdout.txt
similarity index 100%
copy from test/476-checker-ctor-fence-redun-elim/expected.txt
copy to test/476-checker-ctor-fence-redun-elim/expected-stdout.txt
diff --git a/test/476-checker-ctor-memory-barrier/Android.bp b/test/476-checker-ctor-memory-barrier/Android.bp
new file mode 100644
index 0000000..ec92628
--- /dev/null
+++ b/test/476-checker-ctor-memory-barrier/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `476-checker-ctor-memory-barrier`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-476-checker-ctor-memory-barrier",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-476-checker-ctor-memory-barrier-expected-stdout",
+        ":art-run-test-476-checker-ctor-memory-barrier-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-476-checker-ctor-memory-barrier-expected-stdout",
+    out: ["art-run-test-476-checker-ctor-memory-barrier-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-476-checker-ctor-memory-barrier-expected-stderr",
+    out: ["art-run-test-476-checker-ctor-memory-barrier-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/476-checker-ctor-memory-barrier/expected.txt b/test/476-checker-ctor-memory-barrier/expected-stderr.txt
similarity index 100%
rename from test/476-checker-ctor-memory-barrier/expected.txt
rename to test/476-checker-ctor-memory-barrier/expected-stderr.txt
diff --git a/test/476-checker-ctor-memory-barrier/expected.txt b/test/476-checker-ctor-memory-barrier/expected-stdout.txt
similarity index 100%
copy from test/476-checker-ctor-memory-barrier/expected.txt
copy to test/476-checker-ctor-memory-barrier/expected-stdout.txt
diff --git a/test/476-clinit-inline-static-invoke/Android.bp b/test/476-clinit-inline-static-invoke/Android.bp
new file mode 100644
index 0000000..c1fc1dc
--- /dev/null
+++ b/test/476-clinit-inline-static-invoke/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `476-clinit-inline-static-invoke`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-476-clinit-inline-static-invoke",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-476-clinit-inline-static-invoke-expected-stdout",
+        ":art-run-test-476-clinit-inline-static-invoke-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-476-clinit-inline-static-invoke-expected-stdout",
+    out: ["art-run-test-476-clinit-inline-static-invoke-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-476-clinit-inline-static-invoke-expected-stderr",
+    out: ["art-run-test-476-clinit-inline-static-invoke-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/683-clinit-inline-static-invoke/expected.txt b/test/476-clinit-inline-static-invoke/expected-stderr.txt
similarity index 100%
copy from test/683-clinit-inline-static-invoke/expected.txt
copy to test/476-clinit-inline-static-invoke/expected-stderr.txt
diff --git a/test/476-clinit-inline-static-invoke/expected.txt b/test/476-clinit-inline-static-invoke/expected-stdout.txt
similarity index 100%
rename from test/476-clinit-inline-static-invoke/expected.txt
rename to test/476-clinit-inline-static-invoke/expected-stdout.txt
diff --git a/test/477-checker-bound-type/Android.bp b/test/477-checker-bound-type/Android.bp
new file mode 100644
index 0000000..72bf2a6
--- /dev/null
+++ b/test/477-checker-bound-type/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `477-checker-bound-type`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-477-checker-bound-type",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-477-checker-bound-type-expected-stdout",
+        ":art-run-test-477-checker-bound-type-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-477-checker-bound-type-expected-stdout",
+    out: ["art-run-test-477-checker-bound-type-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-477-checker-bound-type-expected-stderr",
+    out: ["art-run-test-477-checker-bound-type-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/477-checker-bound-type/expected.txt b/test/477-checker-bound-type/expected-stderr.txt
similarity index 100%
rename from test/477-checker-bound-type/expected.txt
rename to test/477-checker-bound-type/expected-stderr.txt
diff --git a/test/477-checker-bound-type/expected.txt b/test/477-checker-bound-type/expected-stdout.txt
similarity index 100%
copy from test/477-checker-bound-type/expected.txt
copy to test/477-checker-bound-type/expected-stdout.txt
diff --git a/test/477-long-2-float-convers-precision/Android.bp b/test/477-long-2-float-convers-precision/Android.bp
new file mode 100644
index 0000000..baaf623
--- /dev/null
+++ b/test/477-long-2-float-convers-precision/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `477-long-2-float-convers-precision`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-477-long-2-float-convers-precision",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-477-long-2-float-convers-precision-expected-stdout",
+        ":art-run-test-477-long-2-float-convers-precision-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-477-long-2-float-convers-precision-expected-stdout",
+    out: ["art-run-test-477-long-2-float-convers-precision-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-477-long-2-float-convers-precision-expected-stderr",
+    out: ["art-run-test-477-long-2-float-convers-precision-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/477-long-2-float-convers-precision/expected.txt b/test/477-long-2-float-convers-precision/expected-stderr.txt
similarity index 100%
rename from test/477-long-2-float-convers-precision/expected.txt
rename to test/477-long-2-float-convers-precision/expected-stderr.txt
diff --git a/test/477-long-2-float-convers-precision/expected.txt b/test/477-long-2-float-convers-precision/expected-stdout.txt
similarity index 100%
copy from test/477-long-2-float-convers-precision/expected.txt
copy to test/477-long-2-float-convers-precision/expected-stdout.txt
diff --git a/test/478-checker-clinit-check-pruning/Android.bp b/test/478-checker-clinit-check-pruning/Android.bp
new file mode 100644
index 0000000..c7a0346
--- /dev/null
+++ b/test/478-checker-clinit-check-pruning/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `478-checker-clinit-check-pruning`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-478-checker-clinit-check-pruning",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-478-checker-clinit-check-pruning-expected-stdout",
+        ":art-run-test-478-checker-clinit-check-pruning-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-478-checker-clinit-check-pruning-expected-stdout",
+    out: ["art-run-test-478-checker-clinit-check-pruning-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-478-checker-clinit-check-pruning-expected-stderr",
+    out: ["art-run-test-478-checker-clinit-check-pruning-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/478-checker-inline-noreturn/expected.txt b/test/478-checker-clinit-check-pruning/expected-stderr.txt
similarity index 100%
copy from test/478-checker-inline-noreturn/expected.txt
copy to test/478-checker-clinit-check-pruning/expected-stderr.txt
diff --git a/test/478-checker-clinit-check-pruning/expected.txt b/test/478-checker-clinit-check-pruning/expected-stdout.txt
similarity index 100%
rename from test/478-checker-clinit-check-pruning/expected.txt
rename to test/478-checker-clinit-check-pruning/expected-stdout.txt
diff --git a/test/478-checker-inline-noreturn/Android.bp b/test/478-checker-inline-noreturn/Android.bp
new file mode 100644
index 0000000..a766f88
--- /dev/null
+++ b/test/478-checker-inline-noreturn/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `478-checker-inline-noreturn`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-478-checker-inline-noreturn",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-478-checker-inline-noreturn-expected-stdout",
+        ":art-run-test-478-checker-inline-noreturn-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-478-checker-inline-noreturn-expected-stdout",
+    out: ["art-run-test-478-checker-inline-noreturn-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-478-checker-inline-noreturn-expected-stderr",
+    out: ["art-run-test-478-checker-inline-noreturn-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/478-checker-inline-noreturn/expected.txt b/test/478-checker-inline-noreturn/expected-stderr.txt
similarity index 100%
rename from test/478-checker-inline-noreturn/expected.txt
rename to test/478-checker-inline-noreturn/expected-stderr.txt
diff --git a/test/478-checker-inline-noreturn/expected.txt b/test/478-checker-inline-noreturn/expected-stdout.txt
similarity index 100%
copy from test/478-checker-inline-noreturn/expected.txt
copy to test/478-checker-inline-noreturn/expected-stdout.txt
diff --git a/test/478-checker-inliner-nested-loop/Android.bp b/test/478-checker-inliner-nested-loop/Android.bp
new file mode 100644
index 0000000..afdcc16
--- /dev/null
+++ b/test/478-checker-inliner-nested-loop/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `478-checker-inliner-nested-loop`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-478-checker-inliner-nested-loop",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-478-checker-inliner-nested-loop-expected-stdout",
+        ":art-run-test-478-checker-inliner-nested-loop-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-478-checker-inliner-nested-loop-expected-stdout",
+    out: ["art-run-test-478-checker-inliner-nested-loop-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-478-checker-inliner-nested-loop-expected-stderr",
+    out: ["art-run-test-478-checker-inliner-nested-loop-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/478-checker-inliner-nested-loop/expected.txt b/test/478-checker-inliner-nested-loop/expected-stderr.txt
similarity index 100%
rename from test/478-checker-inliner-nested-loop/expected.txt
rename to test/478-checker-inliner-nested-loop/expected-stderr.txt
diff --git a/test/478-checker-inliner-nested-loop/expected.txt b/test/478-checker-inliner-nested-loop/expected-stdout.txt
similarity index 100%
copy from test/478-checker-inliner-nested-loop/expected.txt
copy to test/478-checker-inliner-nested-loop/expected-stdout.txt
diff --git a/test/479-regression-implicit-null-check/Android.bp b/test/479-regression-implicit-null-check/Android.bp
new file mode 100644
index 0000000..25d8907
--- /dev/null
+++ b/test/479-regression-implicit-null-check/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `479-regression-implicit-null-check`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-479-regression-implicit-null-check",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-479-regression-implicit-null-check-expected-stdout",
+        ":art-run-test-479-regression-implicit-null-check-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-479-regression-implicit-null-check-expected-stdout",
+    out: ["art-run-test-479-regression-implicit-null-check-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-479-regression-implicit-null-check-expected-stderr",
+    out: ["art-run-test-479-regression-implicit-null-check-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/479-regression-implicit-null-check/expected.txt b/test/479-regression-implicit-null-check/expected-stderr.txt
similarity index 100%
rename from test/479-regression-implicit-null-check/expected.txt
rename to test/479-regression-implicit-null-check/expected-stderr.txt
diff --git a/test/479-regression-implicit-null-check/expected.txt b/test/479-regression-implicit-null-check/expected-stdout.txt
similarity index 100%
copy from test/479-regression-implicit-null-check/expected.txt
copy to test/479-regression-implicit-null-check/expected-stdout.txt
diff --git a/test/480-checker-dead-blocks/Android.bp b/test/480-checker-dead-blocks/Android.bp
new file mode 100644
index 0000000..706a723
--- /dev/null
+++ b/test/480-checker-dead-blocks/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `480-checker-dead-blocks`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-480-checker-dead-blocks",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-480-checker-dead-blocks-expected-stdout",
+        ":art-run-test-480-checker-dead-blocks-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-480-checker-dead-blocks-expected-stdout",
+    out: ["art-run-test-480-checker-dead-blocks-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-480-checker-dead-blocks-expected-stderr",
+    out: ["art-run-test-480-checker-dead-blocks-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/480-checker-dead-blocks/expected.txt b/test/480-checker-dead-blocks/expected-stderr.txt
similarity index 100%
rename from test/480-checker-dead-blocks/expected.txt
rename to test/480-checker-dead-blocks/expected-stderr.txt
diff --git a/test/480-checker-dead-blocks/expected.txt b/test/480-checker-dead-blocks/expected-stdout.txt
similarity index 100%
copy from test/480-checker-dead-blocks/expected.txt
copy to test/480-checker-dead-blocks/expected-stdout.txt
diff --git a/test/480-checker-dead-blocks/smali/Smali.smali b/test/480-checker-dead-blocks/smali/Smali.smali
deleted file mode 100644
index b93d5ac..0000000
--- a/test/480-checker-dead-blocks/smali/Smali.smali
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-.class public LSmali;
-.super Ljava/lang/Object;
-
-##  CHECK-START: int Smali.testTrueBranch(int, int) dead_code_elimination$after_inlining (before)
-##  CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
-##  CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
-##  CHECK-DAG:                      If
-##  CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
-##  CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
-##  CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
-##  CHECK-DAG:                      Return [<<Phi>>]
-
-##  CHECK-START: int Smali.testTrueBranch(int, int) dead_code_elimination$after_inlining (after)
-##  CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
-##  CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
-##  CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
-##  CHECK-DAG:                      Return [<<Add>>]
-
-##  CHECK-START: int Smali.testTrueBranch(int, int) dead_code_elimination$after_inlining (after)
-##  CHECK-NOT:                      If
-##  CHECK-NOT:                      Sub
-##  CHECK-NOT:                      Phi
-.method public static testTrueBranch(II)I
-    # int z;
-    # if (inlineTrue()) {
-    #   z = x + y;
-    # } else {
-    #   z = x - y;
-    #   // Prevent HSelect simplification by having a branch with multiple instructions.
-    #   System.nanoTime();
-    # }
-    #return z;
-
-    .registers 4
-    .param p0, "x"    # I
-    .param p1, "y"    # I
-
-    invoke-static {}, LMain;->inlineTrue()Z
-
-    move-result v1
-
-    if-eqz v1, :cond_9
-
-    add-int v0, p0, p1
-
-    :goto_8
-    return v0
-
-    :cond_9
-    sub-int v0, p0, p1
-
-    invoke-static {}, Ljava/lang/System;->nanoTime()J
-
-    goto :goto_8
-.end method
-
-##  CHECK-START: int Smali.testFalseBranch(int, int) dead_code_elimination$after_inlining (before)
-##  CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
-##  CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
-##  CHECK-DAG:                      If
-##  CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
-##  CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
-##  CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
-##  CHECK-DAG:                      Return [<<Phi>>]
-
-##  CHECK-START: int Smali.testFalseBranch(int, int) dead_code_elimination$after_inlining (after)
-##  CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
-##  CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
-##  CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
-##  CHECK-DAG:                      Return [<<Sub>>]
-
-##  CHECK-START: int Smali.testFalseBranch(int, int) dead_code_elimination$after_inlining (after)
-##  CHECK-NOT:                      If
-##  CHECK-NOT:                      Add
-##  CHECK-NOT:                      Phi
-.method public static testFalseBranch(II)I
-    # int z;
-    # if (inlineFalse()) {
-    #   z = x + y;
-    # } else {
-    #   z = x - y;
-    #   // Prevent HSelect simplification by having a branch with multiple instructions.
-    #   System.nanoTime();
-    # }
-    # return z;
-
-    .registers 4
-    .param p0, "x"    # I
-    .param p1, "y"    # I
-
-    invoke-static {}, LMain;->inlineFalse()Z
-
-    move-result v1
-
-    if-eqz v1, :cond_9
-
-    add-int v0, p0, p1
-
-    :goto_8
-    return v0
-
-    :cond_9
-    sub-int v0, p0, p1
-
-    invoke-static {}, Ljava/lang/System;->nanoTime()J
-
-    goto :goto_8
-.end method
diff --git a/test/480-checker-dead-blocks/src/Main.java b/test/480-checker-dead-blocks/src/Main.java
index 485efd9..425e65d 100644
--- a/test/480-checker-dead-blocks/src/Main.java
+++ b/test/480-checker-dead-blocks/src/Main.java
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import java.lang.reflect.Method;
 
 public class Main {
 
@@ -23,32 +22,76 @@
     }
   }
 
-  public static boolean inlineTrue() {
+  public static boolean $inline$constantTrue() {
     return true;
   }
 
-  public static boolean inlineFalse() {
+  public static boolean $inline$constantFalse() {
     return false;
   }
 
+  /// CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination$after_inlining (before)
+  /// CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
+  /// CHECK-DAG:                      If
+  /// CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
+  /// CHECK-DAG:                      Return [<<Phi>>]
+
+  /// CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination$after_inlining (after)
+  /// CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:                      Return [<<Add>>]
+
+  /// CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination$after_inlining (after)
+  /// CHECK-NOT:                      If
+  /// CHECK-NOT:                      Sub
+  /// CHECK-NOT:                      Phi
+
   public static int testTrueBranch(int x, int y) {
-      try {
-      Class<?> c = Class.forName("Smali");
-      Method m = c.getMethod("testTrueBranch", int.class, int.class);
-      return (Integer) m.invoke(null, x, y);
-    } catch (Throwable t) {
-      throw new RuntimeException(t);
+    int z;
+    if ($inline$constantTrue()) {
+      z = x + y;
+    } else {
+      z = x - y;
+      // Prevent HSelect simplification by having a branch with multiple instructions.
+      System.nanoTime();
     }
+    return z;
   }
 
+  /// CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination$after_inlining (before)
+  /// CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
+  /// CHECK-DAG:                      If
+  /// CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
+  /// CHECK-DAG:                      Return [<<Phi>>]
+
+  /// CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination$after_inlining (after)
+  /// CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:                      Return [<<Sub>>]
+
+  /// CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination$after_inlining (after)
+  /// CHECK-NOT:                      If
+  /// CHECK-NOT:                      Add
+  /// CHECK-NOT:                      Phi
+
   public static int testFalseBranch(int x, int y) {
-      try {
-      Class<?> c = Class.forName("Smali");
-      Method m = c.getMethod("testFalseBranch", int.class, int.class);
-      return (Integer) m.invoke(null, x, y);
-    } catch (Throwable t) {
-      throw new RuntimeException(t);
+    int z;
+    if ($inline$constantFalse()) {
+      z = x + y;
+    } else {
+      z = x - y;
+      // Prevent HSelect simplification by having a branch with multiple instructions.
+      System.nanoTime();
     }
+    return z;
   }
 
   /// CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination$after_inlining (before)
@@ -58,7 +101,7 @@
   /// CHECK-NOT:                      Mul
 
   public static int testRemoveLoop(int x) {
-    if (inlineFalse()) {
+    if ($inline$constantFalse()) {
       for (int i = 0; i < x; ++i) {
         x *= x;
       }
@@ -75,7 +118,7 @@
   /// CHECK-NOT:                      Exit
 
   public static int testInfiniteLoop(int x) {
-    while (inlineTrue()) {
+    while ($inline$constantTrue()) {
       x++;
     }
     return x;
@@ -94,7 +137,7 @@
   /// CHECK-NOT:                      Add
 
   public static int testDeadLoop(int x) {
-    while (inlineFalse()) {
+    while ($inline$constantFalse()) {
       x++;
     }
     return x;
@@ -116,7 +159,7 @@
   public static int testUpdateLoopInformation(int x) {
     // Use of Or in the condition generates a dead loop where not all of its
     // blocks are removed. This forces DCE to update their loop information.
-    while (inlineFalse() || !inlineTrue()) {
+    while ($inline$constantFalse() || !$inline$constantTrue()) {
       x++;
     }
     return x;
@@ -137,7 +180,7 @@
     // Inner loop will leave behind the header with its SuspendCheck. DCE must
     // remove it, otherwise the outer loop would end up with two.
     while (y > 0) {
-      while (inlineFalse() || !inlineTrue()) {
+      while ($inline$constantFalse() || !$inline$constantTrue()) {
         x++;
       }
       y--;
diff --git a/test/481-regression-phi-cond/Android.bp b/test/481-regression-phi-cond/Android.bp
new file mode 100644
index 0000000..cf9e14a
--- /dev/null
+++ b/test/481-regression-phi-cond/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `481-regression-phi-cond`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-481-regression-phi-cond",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-481-regression-phi-cond-expected-stdout",
+        ":art-run-test-481-regression-phi-cond-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-481-regression-phi-cond-expected-stdout",
+    out: ["art-run-test-481-regression-phi-cond-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-481-regression-phi-cond-expected-stderr",
+    out: ["art-run-test-481-regression-phi-cond-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/481-regression-phi-cond/expected.txt b/test/481-regression-phi-cond/expected-stderr.txt
similarity index 100%
rename from test/481-regression-phi-cond/expected.txt
rename to test/481-regression-phi-cond/expected-stderr.txt
diff --git a/test/481-regression-phi-cond/expected.txt b/test/481-regression-phi-cond/expected-stdout.txt
similarity index 100%
copy from test/481-regression-phi-cond/expected.txt
copy to test/481-regression-phi-cond/expected-stdout.txt
diff --git a/test/482-checker-loop-back-edge-use/Android.bp b/test/482-checker-loop-back-edge-use/Android.bp
new file mode 100644
index 0000000..6dfdddf
--- /dev/null
+++ b/test/482-checker-loop-back-edge-use/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `482-checker-loop-back-edge-use`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-482-checker-loop-back-edge-use",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-482-checker-loop-back-edge-use-expected-stdout",
+        ":art-run-test-482-checker-loop-back-edge-use-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-482-checker-loop-back-edge-use-expected-stdout",
+    out: ["art-run-test-482-checker-loop-back-edge-use-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-482-checker-loop-back-edge-use-expected-stderr",
+    out: ["art-run-test-482-checker-loop-back-edge-use-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/482-checker-loop-back-edge-use/expected.txt b/test/482-checker-loop-back-edge-use/expected-stderr.txt
similarity index 100%
rename from test/482-checker-loop-back-edge-use/expected.txt
rename to test/482-checker-loop-back-edge-use/expected-stderr.txt
diff --git a/test/482-checker-loop-back-edge-use/expected.txt b/test/482-checker-loop-back-edge-use/expected-stdout.txt
similarity index 100%
copy from test/482-checker-loop-back-edge-use/expected.txt
copy to test/482-checker-loop-back-edge-use/expected-stdout.txt
diff --git a/test/483-dce-block/Android.bp b/test/483-dce-block/Android.bp
new file mode 100644
index 0000000..52ec2af
--- /dev/null
+++ b/test/483-dce-block/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `483-dce-block`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-483-dce-block",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-483-dce-block-expected-stdout",
+        ":art-run-test-483-dce-block-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-483-dce-block-expected-stdout",
+    out: ["art-run-test-483-dce-block-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-483-dce-block-expected-stderr",
+    out: ["art-run-test-483-dce-block-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/406-fields/expected.txt b/test/483-dce-block/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/483-dce-block/expected-stderr.txt
diff --git a/test/483-dce-block/expected.txt b/test/483-dce-block/expected-stdout.txt
similarity index 100%
rename from test/483-dce-block/expected.txt
rename to test/483-dce-block/expected-stdout.txt
diff --git a/test/484-checker-register-hints/expected.txt b/test/484-checker-register-hints/expected-stderr.txt
similarity index 100%
rename from test/484-checker-register-hints/expected.txt
rename to test/484-checker-register-hints/expected-stderr.txt
diff --git a/test/484-checker-register-hints/expected.txt b/test/484-checker-register-hints/expected-stdout.txt
similarity index 100%
copy from test/484-checker-register-hints/expected.txt
copy to test/484-checker-register-hints/expected-stdout.txt
diff --git a/test/485-checker-dce-loop-update/expected.txt b/test/485-checker-dce-loop-update/expected-stderr.txt
similarity index 100%
rename from test/485-checker-dce-loop-update/expected.txt
rename to test/485-checker-dce-loop-update/expected-stderr.txt
diff --git a/test/485-checker-dce-loop-update/expected.txt b/test/485-checker-dce-loop-update/expected-stdout.txt
similarity index 100%
copy from test/485-checker-dce-loop-update/expected.txt
copy to test/485-checker-dce-loop-update/expected-stdout.txt
diff --git a/test/485-checker-dce-switch/Android.bp b/test/485-checker-dce-switch/Android.bp
new file mode 100644
index 0000000..ea56461
--- /dev/null
+++ b/test/485-checker-dce-switch/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `485-checker-dce-switch`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-485-checker-dce-switch",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-485-checker-dce-switch-expected-stdout",
+        ":art-run-test-485-checker-dce-switch-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-485-checker-dce-switch-expected-stdout",
+    out: ["art-run-test-485-checker-dce-switch-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-485-checker-dce-switch-expected-stderr",
+    out: ["art-run-test-485-checker-dce-switch-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/485-checker-dce-switch/expected.txt b/test/485-checker-dce-switch/expected-stderr.txt
similarity index 100%
rename from test/485-checker-dce-switch/expected.txt
rename to test/485-checker-dce-switch/expected-stderr.txt
diff --git a/test/485-checker-dce-switch/expected.txt b/test/485-checker-dce-switch/expected-stdout.txt
similarity index 100%
copy from test/485-checker-dce-switch/expected.txt
copy to test/485-checker-dce-switch/expected-stdout.txt
diff --git a/test/486-checker-must-do-null-check/Android.bp b/test/486-checker-must-do-null-check/Android.bp
new file mode 100644
index 0000000..5c07c39
--- /dev/null
+++ b/test/486-checker-must-do-null-check/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `486-checker-must-do-null-check`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-486-checker-must-do-null-check",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-486-checker-must-do-null-check-expected-stdout",
+        ":art-run-test-486-checker-must-do-null-check-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-486-checker-must-do-null-check-expected-stdout",
+    out: ["art-run-test-486-checker-must-do-null-check-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-486-checker-must-do-null-check-expected-stderr",
+    out: ["art-run-test-486-checker-must-do-null-check-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/486-checker-must-do-null-check/expected.txt b/test/486-checker-must-do-null-check/expected-stderr.txt
similarity index 100%
rename from test/486-checker-must-do-null-check/expected.txt
rename to test/486-checker-must-do-null-check/expected-stderr.txt
diff --git a/test/486-checker-must-do-null-check/expected.txt b/test/486-checker-must-do-null-check/expected-stdout.txt
similarity index 100%
copy from test/486-checker-must-do-null-check/expected.txt
copy to test/486-checker-must-do-null-check/expected-stdout.txt
diff --git a/test/487-checker-inline-calls/Android.bp b/test/487-checker-inline-calls/Android.bp
new file mode 100644
index 0000000..42d64f4
--- /dev/null
+++ b/test/487-checker-inline-calls/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `487-checker-inline-calls`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-487-checker-inline-calls",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-487-checker-inline-calls-expected-stdout",
+        ":art-run-test-487-checker-inline-calls-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-487-checker-inline-calls-expected-stdout",
+    out: ["art-run-test-487-checker-inline-calls-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-487-checker-inline-calls-expected-stderr",
+    out: ["art-run-test-487-checker-inline-calls-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/464-checker-inline-sharpen-calls/expected.txt b/test/487-checker-inline-calls/expected-stderr.txt
similarity index 100%
copy from test/464-checker-inline-sharpen-calls/expected.txt
copy to test/487-checker-inline-calls/expected-stderr.txt
diff --git a/test/487-checker-inline-calls/expected.txt b/test/487-checker-inline-calls/expected-stdout.txt
similarity index 100%
rename from test/487-checker-inline-calls/expected.txt
rename to test/487-checker-inline-calls/expected-stdout.txt
diff --git a/test/488-checker-inline-recursive-calls/Android.bp b/test/488-checker-inline-recursive-calls/Android.bp
new file mode 100644
index 0000000..9a171ad
--- /dev/null
+++ b/test/488-checker-inline-recursive-calls/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `488-checker-inline-recursive-calls`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-488-checker-inline-recursive-calls",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-488-checker-inline-recursive-calls-expected-stdout",
+        ":art-run-test-488-checker-inline-recursive-calls-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-488-checker-inline-recursive-calls-expected-stdout",
+    out: ["art-run-test-488-checker-inline-recursive-calls-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-488-checker-inline-recursive-calls-expected-stderr",
+    out: ["art-run-test-488-checker-inline-recursive-calls-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/464-checker-inline-sharpen-calls/expected.txt b/test/488-checker-inline-recursive-calls/expected-stderr.txt
similarity index 100%
copy from test/464-checker-inline-sharpen-calls/expected.txt
copy to test/488-checker-inline-recursive-calls/expected-stderr.txt
diff --git a/test/488-checker-inline-recursive-calls/expected.txt b/test/488-checker-inline-recursive-calls/expected-stdout.txt
similarity index 100%
rename from test/488-checker-inline-recursive-calls/expected.txt
rename to test/488-checker-inline-recursive-calls/expected-stdout.txt
diff --git a/test/489-current-method-regression/Android.bp b/test/489-current-method-regression/Android.bp
new file mode 100644
index 0000000..27aae46
--- /dev/null
+++ b/test/489-current-method-regression/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `489-current-method-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-489-current-method-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-489-current-method-regression-expected-stdout",
+        ":art-run-test-489-current-method-regression-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-489-current-method-regression-expected-stdout",
+    out: ["art-run-test-489-current-method-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-489-current-method-regression-expected-stderr",
+    out: ["art-run-test-489-current-method-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/413-regalloc-regression/expected.txt b/test/489-current-method-regression/expected-stderr.txt
similarity index 100%
copy from test/413-regalloc-regression/expected.txt
copy to test/489-current-method-regression/expected-stderr.txt
diff --git a/test/489-current-method-regression/expected.txt b/test/489-current-method-regression/expected-stdout.txt
similarity index 100%
rename from test/489-current-method-regression/expected.txt
rename to test/489-current-method-regression/expected-stdout.txt
diff --git a/test/490-checker-inline/Android.bp b/test/490-checker-inline/Android.bp
new file mode 100644
index 0000000..70ca37f
--- /dev/null
+++ b/test/490-checker-inline/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `490-checker-inline`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-490-checker-inline",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-490-checker-inline-expected-stdout",
+        ":art-run-test-490-checker-inline-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-490-checker-inline-expected-stdout",
+    out: ["art-run-test-490-checker-inline-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-490-checker-inline-expected-stderr",
+    out: ["art-run-test-490-checker-inline-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/490-checker-inline/expected.txt b/test/490-checker-inline/expected-stderr.txt
similarity index 100%
rename from test/490-checker-inline/expected.txt
rename to test/490-checker-inline/expected-stderr.txt
diff --git a/test/490-checker-inline/expected.txt b/test/490-checker-inline/expected-stdout.txt
similarity index 100%
copy from test/490-checker-inline/expected.txt
copy to test/490-checker-inline/expected-stdout.txt
diff --git a/test/491-current-method/Android.bp b/test/491-current-method/Android.bp
new file mode 100644
index 0000000..af93f4b
--- /dev/null
+++ b/test/491-current-method/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `491-current-method`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-491-current-method",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-491-current-method-expected-stdout",
+        ":art-run-test-491-current-method-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-491-current-method-expected-stdout",
+    out: ["art-run-test-491-current-method-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-491-current-method-expected-stderr",
+    out: ["art-run-test-491-current-method-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/491-current-method/expected.txt b/test/491-current-method/expected-stderr.txt
similarity index 100%
rename from test/491-current-method/expected.txt
rename to test/491-current-method/expected-stderr.txt
diff --git a/test/491-current-method/expected.txt b/test/491-current-method/expected-stdout.txt
similarity index 100%
copy from test/491-current-method/expected.txt
copy to test/491-current-method/expected-stdout.txt
diff --git a/test/492-checker-inline-invoke-interface/Android.bp b/test/492-checker-inline-invoke-interface/Android.bp
new file mode 100644
index 0000000..06eecee
--- /dev/null
+++ b/test/492-checker-inline-invoke-interface/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `492-checker-inline-invoke-interface`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-492-checker-inline-invoke-interface",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-492-checker-inline-invoke-interface-expected-stdout",
+        ":art-run-test-492-checker-inline-invoke-interface-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-492-checker-inline-invoke-interface-expected-stdout",
+    out: ["art-run-test-492-checker-inline-invoke-interface-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-492-checker-inline-invoke-interface-expected-stderr",
+    out: ["art-run-test-492-checker-inline-invoke-interface-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/423-invoke-interface/expected.txt b/test/492-checker-inline-invoke-interface/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/492-checker-inline-invoke-interface/expected-stderr.txt
diff --git a/test/492-checker-inline-invoke-interface/expected.txt b/test/492-checker-inline-invoke-interface/expected-stdout.txt
similarity index 100%
rename from test/492-checker-inline-invoke-interface/expected.txt
rename to test/492-checker-inline-invoke-interface/expected-stdout.txt
diff --git a/test/493-checker-inline-invoke-interface/Android.bp b/test/493-checker-inline-invoke-interface/Android.bp
new file mode 100644
index 0000000..4b981bf
--- /dev/null
+++ b/test/493-checker-inline-invoke-interface/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `493-checker-inline-invoke-interface`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-493-checker-inline-invoke-interface",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-493-checker-inline-invoke-interface-expected-stdout",
+        ":art-run-test-493-checker-inline-invoke-interface-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-493-checker-inline-invoke-interface-expected-stdout",
+    out: ["art-run-test-493-checker-inline-invoke-interface-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-493-checker-inline-invoke-interface-expected-stderr",
+    out: ["art-run-test-493-checker-inline-invoke-interface-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/423-invoke-interface/expected.txt b/test/493-checker-inline-invoke-interface/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/493-checker-inline-invoke-interface/expected-stderr.txt
diff --git a/test/493-checker-inline-invoke-interface/expected.txt b/test/493-checker-inline-invoke-interface/expected-stdout.txt
similarity index 100%
rename from test/493-checker-inline-invoke-interface/expected.txt
rename to test/493-checker-inline-invoke-interface/expected-stdout.txt
diff --git a/test/494-checker-instanceof-tests/Android.bp b/test/494-checker-instanceof-tests/Android.bp
new file mode 100644
index 0000000..cd9c4c7
--- /dev/null
+++ b/test/494-checker-instanceof-tests/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `494-checker-instanceof-tests`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-494-checker-instanceof-tests",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-494-checker-instanceof-tests-expected-stdout",
+        ":art-run-test-494-checker-instanceof-tests-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-494-checker-instanceof-tests-expected-stdout",
+    out: ["art-run-test-494-checker-instanceof-tests-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-494-checker-instanceof-tests-expected-stderr",
+    out: ["art-run-test-494-checker-instanceof-tests-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/494-checker-instanceof-tests/expected.txt b/test/494-checker-instanceof-tests/expected-stderr.txt
similarity index 100%
rename from test/494-checker-instanceof-tests/expected.txt
rename to test/494-checker-instanceof-tests/expected-stderr.txt
diff --git a/test/494-checker-instanceof-tests/expected.txt b/test/494-checker-instanceof-tests/expected-stdout.txt
similarity index 100%
copy from test/494-checker-instanceof-tests/expected.txt
copy to test/494-checker-instanceof-tests/expected-stdout.txt
diff --git a/test/495-checker-checkcast-tests/Android.bp b/test/495-checker-checkcast-tests/Android.bp
new file mode 100644
index 0000000..019a6fd
--- /dev/null
+++ b/test/495-checker-checkcast-tests/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `495-checker-checkcast-tests`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-495-checker-checkcast-tests",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-495-checker-checkcast-tests-expected-stdout",
+        ":art-run-test-495-checker-checkcast-tests-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-495-checker-checkcast-tests-expected-stdout",
+    out: ["art-run-test-495-checker-checkcast-tests-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-495-checker-checkcast-tests-expected-stderr",
+    out: ["art-run-test-495-checker-checkcast-tests-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/495-checker-checkcast-tests/expected.txt b/test/495-checker-checkcast-tests/expected-stderr.txt
similarity index 100%
rename from test/495-checker-checkcast-tests/expected.txt
rename to test/495-checker-checkcast-tests/expected-stderr.txt
diff --git a/test/495-checker-checkcast-tests/expected.txt b/test/495-checker-checkcast-tests/expected-stdout.txt
similarity index 100%
copy from test/495-checker-checkcast-tests/expected.txt
copy to test/495-checker-checkcast-tests/expected-stdout.txt
diff --git a/test/496-checker-inlining-class-loader/Android.bp b/test/496-checker-inlining-class-loader/Android.bp
new file mode 100644
index 0000000..17e838d
--- /dev/null
+++ b/test/496-checker-inlining-class-loader/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `496-checker-inlining-class-loader`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-496-checker-inlining-class-loader",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-496-checker-inlining-class-loader-expected-stdout",
+        ":art-run-test-496-checker-inlining-class-loader-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-496-checker-inlining-class-loader-expected-stdout",
+    out: ["art-run-test-496-checker-inlining-class-loader-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-496-checker-inlining-class-loader-expected-stderr",
+    out: ["art-run-test-496-checker-inlining-class-loader-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/156-register-dex-file-multi-loader/expected.txt b/test/496-checker-inlining-class-loader/expected-stderr.txt
similarity index 100%
copy from test/156-register-dex-file-multi-loader/expected.txt
copy to test/496-checker-inlining-class-loader/expected-stderr.txt
diff --git a/test/496-checker-inlining-class-loader/expected.txt b/test/496-checker-inlining-class-loader/expected-stdout.txt
similarity index 100%
rename from test/496-checker-inlining-class-loader/expected.txt
rename to test/496-checker-inlining-class-loader/expected-stdout.txt
diff --git a/test/497-inlining-and-class-loader/Android.bp b/test/497-inlining-and-class-loader/Android.bp
new file mode 100644
index 0000000..e36ec78
--- /dev/null
+++ b/test/497-inlining-and-class-loader/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `497-inlining-and-class-loader`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-497-inlining-and-class-loader",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-497-inlining-and-class-loader-expected-stdout",
+        ":art-run-test-497-inlining-and-class-loader-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-497-inlining-and-class-loader-expected-stdout",
+    out: ["art-run-test-497-inlining-and-class-loader-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-497-inlining-and-class-loader-expected-stderr",
+    out: ["art-run-test-497-inlining-and-class-loader-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/497-inlining-and-class-loader/clear_dex_cache.cc b/test/497-inlining-and-class-loader/clear_dex_cache.cc
index 6c6a08f..36ec4eb 100644
--- a/test/497-inlining-and-class-loader/clear_dex_cache.cc
+++ b/test/497-inlining-and-class-loader/clear_dex_cache.cc
@@ -48,7 +48,7 @@
   CHECK(array != nullptr);
   ObjPtr<mirror::Array> decoded_array = soa.Decode<mirror::Array>(array);
   for (size_t i = 0; i != num_methods; ++i) {
-    auto pair = mirror::DexCache::GetNativePairPtrSize(methods, i, kRuntimePointerSize);
+    auto pair = mirror::DexCache::GetNativePair(methods, i);
     uint32_t index = pair.index;
     ArtMethod* method = pair.object;
     if (sizeof(void*) == 4) {
@@ -87,7 +87,7 @@
       method = reinterpret_cast64<ArtMethod*>(long_array->Get(2u * i + 1u));
     }
     mirror::MethodDexCachePair pair(method, index);
-    mirror::DexCache::SetNativePairPtrSize(methods, i, pair, kRuntimePointerSize);
+    mirror::DexCache::SetNativePair(methods, i, pair);
   }
 }
 
diff --git a/test/156-register-dex-file-multi-loader/expected.txt b/test/497-inlining-and-class-loader/expected-stderr.txt
similarity index 100%
copy from test/156-register-dex-file-multi-loader/expected.txt
copy to test/497-inlining-and-class-loader/expected-stderr.txt
diff --git a/test/497-inlining-and-class-loader/expected.txt b/test/497-inlining-and-class-loader/expected-stdout.txt
similarity index 100%
rename from test/497-inlining-and-class-loader/expected.txt
rename to test/497-inlining-and-class-loader/expected-stdout.txt
diff --git a/test/505-simplifier-type-propagation/expected.txt b/test/498-type-propagation/expected-stderr.txt
similarity index 100%
copy from test/505-simplifier-type-propagation/expected.txt
copy to test/498-type-propagation/expected-stderr.txt
diff --git a/test/498-type-propagation/expected.txt b/test/498-type-propagation/expected-stdout.txt
similarity index 100%
rename from test/498-type-propagation/expected.txt
rename to test/498-type-propagation/expected-stdout.txt
diff --git a/test/499-bce-phi-array-length/Android.bp b/test/499-bce-phi-array-length/Android.bp
new file mode 100644
index 0000000..1af6673
--- /dev/null
+++ b/test/499-bce-phi-array-length/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `499-bce-phi-array-length`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-499-bce-phi-array-length",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-499-bce-phi-array-length-expected-stdout",
+        ":art-run-test-499-bce-phi-array-length-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-499-bce-phi-array-length-expected-stdout",
+    out: ["art-run-test-499-bce-phi-array-length-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-499-bce-phi-array-length-expected-stderr",
+    out: ["art-run-test-499-bce-phi-array-length-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/499-bce-phi-array-length/expected.txt b/test/499-bce-phi-array-length/expected-stderr.txt
similarity index 100%
rename from test/499-bce-phi-array-length/expected.txt
rename to test/499-bce-phi-array-length/expected-stderr.txt
diff --git a/test/499-bce-phi-array-length/expected.txt b/test/499-bce-phi-array-length/expected-stdout.txt
similarity index 100%
copy from test/499-bce-phi-array-length/expected.txt
copy to test/499-bce-phi-array-length/expected-stdout.txt
diff --git a/test/500-instanceof/Android.bp b/test/500-instanceof/Android.bp
new file mode 100644
index 0000000..fdb48a7
--- /dev/null
+++ b/test/500-instanceof/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `500-instanceof`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-500-instanceof",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-500-instanceof-expected-stdout",
+        ":art-run-test-500-instanceof-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-500-instanceof-expected-stdout",
+    out: ["art-run-test-500-instanceof-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-500-instanceof-expected-stderr",
+    out: ["art-run-test-500-instanceof-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/500-instanceof/expected.txt b/test/500-instanceof/expected-stderr.txt
similarity index 100%
rename from test/500-instanceof/expected.txt
rename to test/500-instanceof/expected-stderr.txt
diff --git a/test/500-instanceof/expected.txt b/test/500-instanceof/expected-stdout.txt
similarity index 100%
copy from test/500-instanceof/expected.txt
copy to test/500-instanceof/expected-stdout.txt
diff --git a/test/548-checker-inlining-and-dce/expected.txt b/test/501-null-constant-dce/expected-stderr.txt
similarity index 100%
copy from test/548-checker-inlining-and-dce/expected.txt
copy to test/501-null-constant-dce/expected-stderr.txt
diff --git a/test/501-null-constant-dce/expected.txt b/test/501-null-constant-dce/expected-stdout.txt
similarity index 100%
rename from test/501-null-constant-dce/expected.txt
rename to test/501-null-constant-dce/expected-stdout.txt
diff --git a/test/501-regression-packed-switch/expected.txt b/test/501-regression-packed-switch/expected-stderr.txt
similarity index 100%
rename from test/501-regression-packed-switch/expected.txt
rename to test/501-regression-packed-switch/expected-stderr.txt
diff --git a/test/501-regression-packed-switch/expected.txt b/test/501-regression-packed-switch/expected-stdout.txt
similarity index 100%
copy from test/501-regression-packed-switch/expected.txt
copy to test/501-regression-packed-switch/expected-stdout.txt
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/503-dead-instructions/expected-stderr.txt
similarity index 100%
copy from test/148-multithread-gc-annotations/expected.txt
copy to test/503-dead-instructions/expected-stderr.txt
diff --git a/test/503-dead-instructions/expected.txt b/test/503-dead-instructions/expected-stdout.txt
similarity index 100%
rename from test/503-dead-instructions/expected.txt
rename to test/503-dead-instructions/expected-stdout.txt
diff --git a/test/504-regression-baseline-entry/expected.txt b/test/504-regression-baseline-entry/expected-stderr.txt
similarity index 100%
rename from test/504-regression-baseline-entry/expected.txt
rename to test/504-regression-baseline-entry/expected-stderr.txt
diff --git a/test/504-regression-baseline-entry/expected.txt b/test/504-regression-baseline-entry/expected-stdout.txt
similarity index 100%
copy from test/504-regression-baseline-entry/expected.txt
copy to test/504-regression-baseline-entry/expected-stdout.txt
diff --git a/test/505-simplifier-type-propagation/Android.bp b/test/505-simplifier-type-propagation/Android.bp
new file mode 100644
index 0000000..4e8ab74
--- /dev/null
+++ b/test/505-simplifier-type-propagation/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `505-simplifier-type-propagation`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-505-simplifier-type-propagation",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-505-simplifier-type-propagation-expected-stdout",
+        ":art-run-test-505-simplifier-type-propagation-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-505-simplifier-type-propagation-expected-stdout",
+    out: ["art-run-test-505-simplifier-type-propagation-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-505-simplifier-type-propagation-expected-stderr",
+    out: ["art-run-test-505-simplifier-type-propagation-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/505-simplifier-type-propagation/expected.txt b/test/505-simplifier-type-propagation/expected-stderr.txt
similarity index 100%
rename from test/505-simplifier-type-propagation/expected.txt
rename to test/505-simplifier-type-propagation/expected-stderr.txt
diff --git a/test/505-simplifier-type-propagation/expected.txt b/test/505-simplifier-type-propagation/expected-stdout.txt
similarity index 100%
copy from test/505-simplifier-type-propagation/expected.txt
copy to test/505-simplifier-type-propagation/expected-stdout.txt
diff --git a/test/507-boolean-test/expected.txt b/test/506-verify-aput/expected-stderr.txt
similarity index 100%
copy from test/507-boolean-test/expected.txt
copy to test/506-verify-aput/expected-stderr.txt
diff --git a/test/506-verify-aput/expected.txt b/test/506-verify-aput/expected-stdout.txt
similarity index 100%
rename from test/506-verify-aput/expected.txt
rename to test/506-verify-aput/expected-stdout.txt
diff --git a/test/507-boolean-test/Android.bp b/test/507-boolean-test/Android.bp
new file mode 100644
index 0000000..b1066bd
--- /dev/null
+++ b/test/507-boolean-test/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `507-boolean-test`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-507-boolean-test",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-507-boolean-test-expected-stdout",
+        ":art-run-test-507-boolean-test-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-507-boolean-test-expected-stdout",
+    out: ["art-run-test-507-boolean-test-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-507-boolean-test-expected-stderr",
+    out: ["art-run-test-507-boolean-test-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/507-boolean-test/expected.txt b/test/507-boolean-test/expected-stderr.txt
similarity index 100%
rename from test/507-boolean-test/expected.txt
rename to test/507-boolean-test/expected-stderr.txt
diff --git a/test/507-boolean-test/expected.txt b/test/507-boolean-test/expected-stdout.txt
similarity index 100%
copy from test/507-boolean-test/expected.txt
copy to test/507-boolean-test/expected-stdout.txt
diff --git a/test/507-referrer/Android.bp b/test/507-referrer/Android.bp
new file mode 100644
index 0000000..2062922
--- /dev/null
+++ b/test/507-referrer/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `507-referrer`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-507-referrer",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-507-referrer-expected-stdout",
+        ":art-run-test-507-referrer-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-507-referrer-expected-stdout",
+    out: ["art-run-test-507-referrer-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-507-referrer-expected-stderr",
+    out: ["art-run-test-507-referrer-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/507-referrer/expected.txt b/test/507-referrer/expected-stderr.txt
similarity index 100%
rename from test/507-referrer/expected.txt
rename to test/507-referrer/expected-stderr.txt
diff --git a/test/507-referrer/expected.txt b/test/507-referrer/expected-stdout.txt
similarity index 100%
copy from test/507-referrer/expected.txt
copy to test/507-referrer/expected-stdout.txt
diff --git a/test/508-checker-disassembly/Android.bp b/test/508-checker-disassembly/Android.bp
new file mode 100644
index 0000000..a657c16
--- /dev/null
+++ b/test/508-checker-disassembly/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `508-checker-disassembly`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-508-checker-disassembly",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-508-checker-disassembly-expected-stdout",
+        ":art-run-test-508-checker-disassembly-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-508-checker-disassembly-expected-stdout",
+    out: ["art-run-test-508-checker-disassembly-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-508-checker-disassembly-expected-stderr",
+    out: ["art-run-test-508-checker-disassembly-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/508-checker-disassembly/expected.txt b/test/508-checker-disassembly/expected-stderr.txt
similarity index 100%
rename from test/508-checker-disassembly/expected.txt
rename to test/508-checker-disassembly/expected-stderr.txt
diff --git a/test/508-checker-disassembly/expected.txt b/test/508-checker-disassembly/expected-stdout.txt
similarity index 100%
copy from test/508-checker-disassembly/expected.txt
copy to test/508-checker-disassembly/expected-stdout.txt
diff --git a/test/508-referrer-method/Android.bp b/test/508-referrer-method/Android.bp
new file mode 100644
index 0000000..0964765
--- /dev/null
+++ b/test/508-referrer-method/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `508-referrer-method`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-508-referrer-method",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-508-referrer-method-expected-stdout",
+        ":art-run-test-508-referrer-method-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-508-referrer-method-expected-stdout",
+    out: ["art-run-test-508-referrer-method-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-508-referrer-method-expected-stderr",
+    out: ["art-run-test-508-referrer-method-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/508-referrer-method/expected.txt b/test/508-referrer-method/expected-stderr.txt
similarity index 100%
rename from test/508-referrer-method/expected.txt
rename to test/508-referrer-method/expected-stderr.txt
diff --git a/test/508-referrer-method/expected.txt b/test/508-referrer-method/expected-stdout.txt
similarity index 100%
copy from test/508-referrer-method/expected.txt
copy to test/508-referrer-method/expected-stdout.txt
diff --git a/test/507-referrer/expected.txt b/test/509-pre-header/expected-stderr.txt
similarity index 100%
copy from test/507-referrer/expected.txt
copy to test/509-pre-header/expected-stderr.txt
diff --git a/test/509-pre-header/expected.txt b/test/509-pre-header/expected-stdout.txt
similarity index 100%
rename from test/509-pre-header/expected.txt
rename to test/509-pre-header/expected-stdout.txt
diff --git a/test/510-checker-try-catch/expected.txt b/test/510-checker-try-catch/expected-stderr.txt
similarity index 100%
rename from test/510-checker-try-catch/expected.txt
rename to test/510-checker-try-catch/expected-stderr.txt
diff --git a/test/510-checker-try-catch/expected.txt b/test/510-checker-try-catch/expected-stdout.txt
similarity index 100%
copy from test/510-checker-try-catch/expected.txt
copy to test/510-checker-try-catch/expected-stdout.txt
diff --git a/test/423-invoke-interface/expected.txt b/test/511-clinit-interface/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/511-clinit-interface/expected-stderr.txt
diff --git a/test/511-clinit-interface/expected.txt b/test/511-clinit-interface/expected-stdout.txt
similarity index 100%
rename from test/511-clinit-interface/expected.txt
rename to test/511-clinit-interface/expected-stdout.txt
diff --git a/test/513-array-deopt/Android.bp b/test/513-array-deopt/Android.bp
new file mode 100644
index 0000000..1ede9a8
--- /dev/null
+++ b/test/513-array-deopt/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `513-array-deopt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-513-array-deopt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-513-array-deopt-expected-stdout",
+        ":art-run-test-513-array-deopt-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-513-array-deopt-expected-stdout",
+    out: ["art-run-test-513-array-deopt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-513-array-deopt-expected-stderr",
+    out: ["art-run-test-513-array-deopt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/513-array-deopt/expected.txt b/test/513-array-deopt/expected-stderr.txt
similarity index 100%
rename from test/513-array-deopt/expected.txt
rename to test/513-array-deopt/expected-stderr.txt
diff --git a/test/513-array-deopt/expected.txt b/test/513-array-deopt/expected-stdout.txt
similarity index 100%
copy from test/513-array-deopt/expected.txt
copy to test/513-array-deopt/expected-stdout.txt
diff --git a/test/514-shifts/Android.bp b/test/514-shifts/Android.bp
new file mode 100644
index 0000000..e5bd604
--- /dev/null
+++ b/test/514-shifts/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `514-shifts`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-514-shifts",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-514-shifts-expected-stdout",
+        ":art-run-test-514-shifts-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-514-shifts-expected-stdout",
+    out: ["art-run-test-514-shifts-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-514-shifts-expected-stderr",
+    out: ["art-run-test-514-shifts-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/514-shifts/expected.txt b/test/514-shifts/expected-stderr.txt
similarity index 100%
rename from test/514-shifts/expected.txt
rename to test/514-shifts/expected-stderr.txt
diff --git a/test/514-shifts/expected.txt b/test/514-shifts/expected-stdout.txt
similarity index 100%
copy from test/514-shifts/expected.txt
copy to test/514-shifts/expected-stdout.txt
diff --git a/test/507-referrer/expected.txt b/test/515-dce-dominator/expected-stderr.txt
similarity index 100%
copy from test/507-referrer/expected.txt
copy to test/515-dce-dominator/expected-stderr.txt
diff --git a/test/515-dce-dominator/expected.txt b/test/515-dce-dominator/expected-stdout.txt
similarity index 100%
rename from test/515-dce-dominator/expected.txt
rename to test/515-dce-dominator/expected-stdout.txt
diff --git a/test/516-dead-move-result/expected.txt b/test/516-dead-move-result/expected-stderr.txt
similarity index 100%
rename from test/516-dead-move-result/expected.txt
rename to test/516-dead-move-result/expected-stderr.txt
diff --git a/test/516-dead-move-result/expected.txt b/test/516-dead-move-result/expected-stdout.txt
similarity index 100%
copy from test/516-dead-move-result/expected.txt
copy to test/516-dead-move-result/expected-stdout.txt
diff --git a/test/517-checker-builder-fallthrough/expected.txt b/test/517-checker-builder-fallthrough/expected-stderr.txt
similarity index 100%
rename from test/517-checker-builder-fallthrough/expected.txt
rename to test/517-checker-builder-fallthrough/expected-stderr.txt
diff --git a/test/517-checker-builder-fallthrough/expected.txt b/test/517-checker-builder-fallthrough/expected-stdout.txt
similarity index 100%
copy from test/517-checker-builder-fallthrough/expected.txt
copy to test/517-checker-builder-fallthrough/expected-stdout.txt
diff --git a/test/586-checker-null-array-get/expected.txt b/test/518-null-array-get/expected-stderr.txt
similarity index 100%
copy from test/586-checker-null-array-get/expected.txt
copy to test/518-null-array-get/expected-stderr.txt
diff --git a/test/518-null-array-get/expected.txt b/test/518-null-array-get/expected-stdout.txt
similarity index 100%
rename from test/518-null-array-get/expected.txt
rename to test/518-null-array-get/expected-stdout.txt
diff --git a/test/519-bound-load-class/Android.bp b/test/519-bound-load-class/Android.bp
new file mode 100644
index 0000000..5b0cbed
--- /dev/null
+++ b/test/519-bound-load-class/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `519-bound-load-class`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-519-bound-load-class",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-519-bound-load-class-expected-stdout",
+        ":art-run-test-519-bound-load-class-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-519-bound-load-class-expected-stdout",
+    out: ["art-run-test-519-bound-load-class-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-519-bound-load-class-expected-stderr",
+    out: ["art-run-test-519-bound-load-class-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/519-bound-load-class/expected.txt b/test/519-bound-load-class/expected-stderr.txt
similarity index 100%
rename from test/519-bound-load-class/expected.txt
rename to test/519-bound-load-class/expected-stderr.txt
diff --git a/test/519-bound-load-class/expected.txt b/test/519-bound-load-class/expected-stdout.txt
similarity index 100%
copy from test/519-bound-load-class/expected.txt
copy to test/519-bound-load-class/expected-stdout.txt
diff --git a/test/520-equivalent-phi/expected.txt b/test/520-equivalent-phi/expected-stderr.txt
similarity index 100%
rename from test/520-equivalent-phi/expected.txt
rename to test/520-equivalent-phi/expected-stderr.txt
diff --git a/test/520-equivalent-phi/expected.txt b/test/520-equivalent-phi/expected-stdout.txt
similarity index 100%
copy from test/520-equivalent-phi/expected.txt
copy to test/520-equivalent-phi/expected-stdout.txt
diff --git a/test/521-checker-array-set-null/Android.bp b/test/521-checker-array-set-null/Android.bp
new file mode 100644
index 0000000..1199d81
--- /dev/null
+++ b/test/521-checker-array-set-null/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `521-checker-array-set-null`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-521-checker-array-set-null",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-521-checker-array-set-null-expected-stdout",
+        ":art-run-test-521-checker-array-set-null-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-521-checker-array-set-null-expected-stdout",
+    out: ["art-run-test-521-checker-array-set-null-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-521-checker-array-set-null-expected-stderr",
+    out: ["art-run-test-521-checker-array-set-null-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/521-checker-array-set-null/expected.txt b/test/521-checker-array-set-null/expected-stderr.txt
similarity index 100%
rename from test/521-checker-array-set-null/expected.txt
rename to test/521-checker-array-set-null/expected-stderr.txt
diff --git a/test/521-checker-array-set-null/expected.txt b/test/521-checker-array-set-null/expected-stdout.txt
similarity index 100%
copy from test/521-checker-array-set-null/expected.txt
copy to test/521-checker-array-set-null/expected-stdout.txt
diff --git a/test/521-regression-integer-field-set/Android.bp b/test/521-regression-integer-field-set/Android.bp
new file mode 100644
index 0000000..b90141e
--- /dev/null
+++ b/test/521-regression-integer-field-set/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `521-regression-integer-field-set`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-521-regression-integer-field-set",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-521-regression-integer-field-set-expected-stdout",
+        ":art-run-test-521-regression-integer-field-set-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-521-regression-integer-field-set-expected-stdout",
+    out: ["art-run-test-521-regression-integer-field-set-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-521-regression-integer-field-set-expected-stderr",
+    out: ["art-run-test-521-regression-integer-field-set-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/521-regression-integer-field-set/expected.txt b/test/521-regression-integer-field-set/expected-stderr.txt
similarity index 100%
rename from test/521-regression-integer-field-set/expected.txt
rename to test/521-regression-integer-field-set/expected-stderr.txt
diff --git a/test/521-regression-integer-field-set/expected.txt b/test/521-regression-integer-field-set/expected-stdout.txt
similarity index 100%
copy from test/521-regression-integer-field-set/expected.txt
copy to test/521-regression-integer-field-set/expected-stdout.txt
diff --git a/test/522-checker-regression-monitor-exit/expected.txt b/test/522-checker-regression-monitor-exit/expected-stderr.txt
similarity index 100%
rename from test/522-checker-regression-monitor-exit/expected.txt
rename to test/522-checker-regression-monitor-exit/expected-stderr.txt
diff --git a/test/522-checker-regression-monitor-exit/expected.txt b/test/522-checker-regression-monitor-exit/expected-stdout.txt
similarity index 100%
copy from test/522-checker-regression-monitor-exit/expected.txt
copy to test/522-checker-regression-monitor-exit/expected-stdout.txt
diff --git a/test/523-checker-can-throw-regression/expected.txt b/test/523-checker-can-throw-regression/expected-stderr.txt
similarity index 100%
rename from test/523-checker-can-throw-regression/expected.txt
rename to test/523-checker-can-throw-regression/expected-stderr.txt
diff --git a/test/523-checker-can-throw-regression/expected.txt b/test/523-checker-can-throw-regression/expected-stdout.txt
similarity index 100%
copy from test/523-checker-can-throw-regression/expected.txt
copy to test/523-checker-can-throw-regression/expected-stdout.txt
diff --git a/test/524-boolean-simplifier-regression/Android.bp b/test/524-boolean-simplifier-regression/Android.bp
new file mode 100644
index 0000000..be075e8
--- /dev/null
+++ b/test/524-boolean-simplifier-regression/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `524-boolean-simplifier-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-524-boolean-simplifier-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-524-boolean-simplifier-regression-expected-stdout",
+        ":art-run-test-524-boolean-simplifier-regression-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-524-boolean-simplifier-regression-expected-stdout",
+    out: ["art-run-test-524-boolean-simplifier-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-524-boolean-simplifier-regression-expected-stderr",
+    out: ["art-run-test-524-boolean-simplifier-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/523-checker-can-throw-regression/expected.txt b/test/524-boolean-simplifier-regression/expected-stderr.txt
similarity index 100%
copy from test/523-checker-can-throw-regression/expected.txt
copy to test/524-boolean-simplifier-regression/expected-stderr.txt
diff --git a/test/524-boolean-simplifier-regression/expected.txt b/test/524-boolean-simplifier-regression/expected-stdout.txt
similarity index 100%
rename from test/524-boolean-simplifier-regression/expected.txt
rename to test/524-boolean-simplifier-regression/expected-stdout.txt
diff --git a/test/525-checker-arrays-fields1/Android.bp b/test/525-checker-arrays-fields1/Android.bp
new file mode 100644
index 0000000..8cfe2b0
--- /dev/null
+++ b/test/525-checker-arrays-fields1/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `525-checker-arrays-fields1`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-525-checker-arrays-fields1",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-525-checker-arrays-fields1-expected-stdout",
+        ":art-run-test-525-checker-arrays-fields1-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-525-checker-arrays-fields1-expected-stdout",
+    out: ["art-run-test-525-checker-arrays-fields1-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-525-checker-arrays-fields1-expected-stderr",
+    out: ["art-run-test-525-checker-arrays-fields1-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/520-equivalent-phi/expected.txt b/test/525-checker-arrays-fields1/expected-stderr.txt
similarity index 100%
copy from test/520-equivalent-phi/expected.txt
copy to test/525-checker-arrays-fields1/expected-stderr.txt
diff --git a/test/525-checker-arrays-fields1/expected.txt b/test/525-checker-arrays-fields1/expected-stdout.txt
similarity index 100%
rename from test/525-checker-arrays-fields1/expected.txt
rename to test/525-checker-arrays-fields1/expected-stdout.txt
diff --git a/test/525-checker-arrays-fields2/Android.bp b/test/525-checker-arrays-fields2/Android.bp
new file mode 100644
index 0000000..c6e165b
--- /dev/null
+++ b/test/525-checker-arrays-fields2/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `525-checker-arrays-fields2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-525-checker-arrays-fields2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-525-checker-arrays-fields2-expected-stdout",
+        ":art-run-test-525-checker-arrays-fields2-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-525-checker-arrays-fields2-expected-stdout",
+    out: ["art-run-test-525-checker-arrays-fields2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-525-checker-arrays-fields2-expected-stderr",
+    out: ["art-run-test-525-checker-arrays-fields2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/452-multiple-returns2/expected.txt b/test/525-checker-arrays-fields2/expected-stderr.txt
similarity index 100%
copy from test/452-multiple-returns2/expected.txt
copy to test/525-checker-arrays-fields2/expected-stderr.txt
diff --git a/test/525-checker-arrays-fields2/expected.txt b/test/525-checker-arrays-fields2/expected-stdout.txt
similarity index 100%
rename from test/525-checker-arrays-fields2/expected.txt
rename to test/525-checker-arrays-fields2/expected-stdout.txt
diff --git a/test/526-checker-caller-callee-regs/Android.bp b/test/526-checker-caller-callee-regs/Android.bp
new file mode 100644
index 0000000..d7087ac
--- /dev/null
+++ b/test/526-checker-caller-callee-regs/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `526-checker-caller-callee-regs`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-526-checker-caller-callee-regs",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-526-checker-caller-callee-regs-expected-stdout",
+        ":art-run-test-526-checker-caller-callee-regs-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-526-checker-caller-callee-regs-expected-stdout",
+    out: ["art-run-test-526-checker-caller-callee-regs-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-526-checker-caller-callee-regs-expected-stderr",
+    out: ["art-run-test-526-checker-caller-callee-regs-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/526-checker-caller-callee-regs/expected.txt b/test/526-checker-caller-callee-regs/expected-stderr.txt
similarity index 100%
rename from test/526-checker-caller-callee-regs/expected.txt
rename to test/526-checker-caller-callee-regs/expected-stderr.txt
diff --git a/test/526-checker-caller-callee-regs/expected.txt b/test/526-checker-caller-callee-regs/expected-stdout.txt
similarity index 100%
copy from test/526-checker-caller-callee-regs/expected.txt
copy to test/526-checker-caller-callee-regs/expected-stdout.txt
diff --git a/test/526-long-regalloc/Android.bp b/test/526-long-regalloc/Android.bp
new file mode 100644
index 0000000..34e4a2d
--- /dev/null
+++ b/test/526-long-regalloc/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `526-long-regalloc`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-526-long-regalloc",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-526-long-regalloc-expected-stdout",
+        ":art-run-test-526-long-regalloc-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-526-long-regalloc-expected-stdout",
+    out: ["art-run-test-526-long-regalloc-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-526-long-regalloc-expected-stderr",
+    out: ["art-run-test-526-long-regalloc-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/526-long-regalloc/expected.txt b/test/526-long-regalloc/expected-stderr.txt
similarity index 100%
rename from test/526-long-regalloc/expected.txt
rename to test/526-long-regalloc/expected-stderr.txt
diff --git a/test/526-long-regalloc/expected.txt b/test/526-long-regalloc/expected-stdout.txt
similarity index 100%
copy from test/526-long-regalloc/expected.txt
copy to test/526-long-regalloc/expected-stdout.txt
diff --git a/test/527-checker-array-access-simd/Android.bp b/test/527-checker-array-access-simd/Android.bp
new file mode 100644
index 0000000..96bb43a
--- /dev/null
+++ b/test/527-checker-array-access-simd/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `527-checker-array-access-simd`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-527-checker-array-access-simd",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-527-checker-array-access-simd-expected-stdout",
+        ":art-run-test-527-checker-array-access-simd-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-527-checker-array-access-simd-expected-stdout",
+    out: ["art-run-test-527-checker-array-access-simd-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-527-checker-array-access-simd-expected-stderr",
+    out: ["art-run-test-527-checker-array-access-simd-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/527-checker-array-access-simd/expected.txt b/test/527-checker-array-access-simd/expected-stderr.txt
similarity index 100%
rename from test/527-checker-array-access-simd/expected.txt
rename to test/527-checker-array-access-simd/expected-stderr.txt
diff --git a/test/527-checker-array-access-simd/expected.txt b/test/527-checker-array-access-simd/expected-stdout.txt
similarity index 100%
copy from test/527-checker-array-access-simd/expected.txt
copy to test/527-checker-array-access-simd/expected-stdout.txt
diff --git a/test/527-checker-array-access-simd/src/Main.java b/test/527-checker-array-access-simd/src/Main.java
index 8af5465..173165a 100644
--- a/test/527-checker-array-access-simd/src/Main.java
+++ b/test/527-checker-array-access-simd/src/Main.java
@@ -25,47 +25,105 @@
   /// CHECK-START-ARM64: void Main.checkIntCase(int[]) instruction_simplifier_arm64 (before)
   /// CHECK-DAG:             <<Array:l\d+>>         ParameterValue
   /// CHECK-DAG:             <<Const5:i\d+>>        IntConstant 5
-  /// CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
-  //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Index>>]
-  /// CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
-  /// CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Add>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>,{{j\d+}}]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Index>>,<<LoopP>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>,<<LoopP>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Add>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Index>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Add>>]
+  //
+  /// CHECK-FI:
 
   /// CHECK-START-ARM64: void Main.checkIntCase(int[]) instruction_simplifier_arm64 (after)
   /// CHECK-DAG:             <<Array:l\d+>>         ParameterValue
   /// CHECK-DAG:             <<Const5:i\d+>>        IntConstant 5
-  /// CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
-  /// CHECK-DAG:             <<Const2:i\d+>>        IntConstant 2
-  /// CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
-  //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
-  /// CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Address1>>]
-  /// CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
-  /// CHECK-DAG:             <<Address2:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
-  /// CHECK-DAG:                                    VecStore [<<Array>>,<<Address2>>,<<Add>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      IntermediateAddressIndex is not supported for SVE.
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>,{{j\d+}}]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Index>>,<<LoopP>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>,<<LoopP>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Add>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<Const2:i\d+>>        IntConstant 2
+  ///     CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Address1>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
+  ///     CHECK-DAG:             <<Address2:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Address2>>,<<Add>>]
+  //
+  /// CHECK-FI:
 
   /// CHECK-START-ARM64: void Main.checkIntCase(int[]) GVN$after_arch (after)
   /// CHECK-DAG:             <<Array:l\d+>>         ParameterValue
   /// CHECK-DAG:             <<Const5:i\d+>>        IntConstant 5
-  /// CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
-  /// CHECK-DAG:             <<Const2:i\d+>>        IntConstant 2
-  /// CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
-  //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
-  /// CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Address1>>]
-  /// CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
-  /// CHECK-NOT:                                    IntermediateAddress
-  /// CHECK-DAG:                                    VecStore [<<Array>>,<<Address1>>,<<Add>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      IntermediateAddressIndex is not supported for SVE.
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>,{{j\d+}}]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Index>>,<<LoopP>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>,<<LoopP>>]
+  ///     CHECK-NOT:                                    IntermediateAddress
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Add>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
+  ///     CHECK-DAG:             <<Const2:i\d+>>        IntConstant 2
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Address1>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
+  ///     CHECK-NOT:                                    IntermediateAddress
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Address1>>,<<Add>>]
+  //
+  /// CHECK-FI:
 
   /// CHECK-START-ARM64: void Main.checkIntCase(int[]) disassembly (after)
-  /// CHECK:                                        IntermediateAddressIndex
-  /// CHECK-NEXT:                                   add w{{[0-9]+}}, w{{[0-9]+}}, w{{[0-9]+}}, lsl #2
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      IntermediateAddressIndex is not supported for SVE.
+  ///     CHECK-NOT:                                    IntermediateAddressIndex
+  ///     CHECK-NOT:                                    IntermediateAddress
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK:                                        IntermediateAddressIndex
+  ///     CHECK-NEXT:                                   add w{{[0-9]+}}, w{{[0-9]+}}, w{{[0-9]+}}, lsl #2
+  //
+  /// CHECK-FI:
   public static void checkIntCase(int[] a) {
     for (int i = 0; i < 128; i++) {
       a[i] += 5;
@@ -75,51 +133,109 @@
   /// CHECK-START-ARM64: void Main.checkByteCase(byte[]) instruction_simplifier_arm64 (before)
   /// CHECK-DAG:             <<Array:l\d+>>         ParameterValue
   /// CHECK-DAG:             <<Const5:i\d+>>        IntConstant 5
-  /// CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
-  //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Index>>]
-  /// CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
-  /// CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Add>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>,{{j\d+}}]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Index>>,<<LoopP>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>,<<LoopP>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Add>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Index>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
+
+  //
+  /// CHECK-FI:
 
   /// CHECK-START-ARM64: void Main.checkByteCase(byte[]) instruction_simplifier_arm64 (after)
   /// CHECK-DAG:             <<Array:l\d+>>         ParameterValue
   /// CHECK-DAG:             <<Const0:i\d+>>        IntConstant 0
   /// CHECK-DAG:             <<Const5:i\d+>>        IntConstant 5
-  /// CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
-  /// CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
-  //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const0>>]
-  /// CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Address1>>]
-  /// CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
-  /// CHECK-DAG:             <<Address2:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const0>>]
-  /// CHECK-DAG:                                    VecStore [<<Array>>,<<Address2>>,<<Add>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      IntermediateAddressIndex is not supported for SVE.
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>,{{j\d+}}]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Index>>,<<LoopP>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>,<<LoopP>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Add>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const0>>]
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Address1>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
+  ///     CHECK-DAG:             <<Address2:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const0>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Address2>>,<<Add>>]
+  //
+  /// CHECK-FI:
 
   /// CHECK-START-ARM64: void Main.checkByteCase(byte[]) GVN$after_arch (after)
   /// CHECK-DAG:             <<Array:l\d+>>         ParameterValue
   /// CHECK-DAG:             <<Const0:i\d+>>        IntConstant 0
   /// CHECK-DAG:             <<Const5:i\d+>>        IntConstant 5
-  /// CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
-  /// CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
-  //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const0>>]
-  /// CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Address1>>]
-  /// CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
-  /// CHECK-NOT:                                    IntermediateAddress
-  /// CHECK-DAG:                                    VecStore [<<Array>>,<<Address1>>,<<Add>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      IntermediateAddressIndex is not supported for SVE.
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>,{{j\d+}}]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Index>>,<<LoopP>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>,<<LoopP>>]
+  ///     CHECK-NOT:                                    IntermediateAddress
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Add>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const0>>]
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array>>,<<Address1>>]
+  ///     CHECK-DAG:             <<Add:d\d+>>           VecAdd [<<Load>>,<<Repl>>]
+  ///     CHECK-NOT:                                    IntermediateAddress
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Address1>>,<<Add>>]
+  //
+  /// CHECK-FI:
 
   /// CHECK-START-ARM64: void Main.checkByteCase(byte[]) disassembly (after)
-  /// CHECK:                                        IntermediateAddressIndex
-  /// CHECK-NEXT:                                   add w{{[0-9]+}}, w{{[0-9]+}}, #0x{{[0-9a-fA-F]+}}
-  /// CHECK:                                        VecLoad
-  /// CHECK-NEXT:                                   ldr q{{[0-9]+}}, [x{{[0-9]+}}, x{{[0-9]+}}]
-  /// CHECK:                                        VecStore
-  /// CHECK-NEXT:                                   str q{{[0-9]+}}, [x{{[0-9]+}}, x{{[0-9]+}}]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      IntermediateAddressIndex is not supported for SVE.
+  ///     CHECK-NOT:                                    IntermediateAddressIndex
+  ///     CHECK-NOT:                                    IntermediateAddress
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK:                                        IntermediateAddressIndex
+  ///     CHECK-NEXT:                                   add w{{[0-9]+}}, w{{[0-9]+}}, #0x{{[0-9a-fA-F]+}}
+  ///     CHECK:                                        VecLoad
+  ///     CHECK-NEXT:                                   ldr q{{[0-9]+}}, [x{{[0-9]+}}, x{{[0-9]+}}]
+  ///     CHECK:                                        VecStore
+  ///     CHECK-NEXT:                                   str q{{[0-9]+}}, [x{{[0-9]+}}, x{{[0-9]+}}]
+  //
+  /// CHECK-FI:
   public static void checkByteCase(byte[] a) {
     for (int i = 0; i < 128; i++) {
       a[i] += 5;
@@ -129,21 +245,48 @@
   /// CHECK-START-ARM64: void Main.checkSingleAccess(int[]) instruction_simplifier_arm64 (before)
   /// CHECK-DAG:             <<Array:l\d+>>         ParameterValue
   /// CHECK-DAG:             <<Const5:i\d+>>        IntConstant 5
-  /// CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
-  //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Repl>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>,{{j\d+}}]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Repl>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Repl>>]
+  //
+  /// CHECK-FI:
 
   /// CHECK-START-ARM64: void Main.checkSingleAccess(int[]) instruction_simplifier_arm64 (after)
   /// CHECK-DAG:             <<Array:l\d+>>         ParameterValue
   /// CHECK-DAG:             <<Const0:i\d+>>        IntConstant 0
   /// CHECK-DAG:             <<Const5:i\d+>>        IntConstant 5
-  /// CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
-  //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Repl>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>,{{j\d+}}]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Repl>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<Repl:d\d+>>          VecReplicateScalar [<<Const5>>]
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:                                    VecStore [<<Array>>,<<Index>>,<<Repl>>]
+  //
+  /// CHECK-FI:
+  //
   /// CHECK-NOT:                                    IntermediateAddress
   public static void checkSingleAccess(int[] a) {
     for (int i = 0; i < 128; i++) {
@@ -155,43 +298,97 @@
   /// CHECK-DAG:             <<Array1:l\d+>>        ParameterValue
   /// CHECK-DAG:             <<Array2:l\d+>>        ParameterValue
   //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array1>>,<<Index>>]
-  /// CHECK-DAG:             <<Cnv:d\d+>>           VecCnv [<<Load>>]
-  /// CHECK-DAG:                                    VecStore [<<Array2>>,<<Index>>,<<Cnv>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array1>>,<<Index>>,<<LoopP>>]
+  ///     CHECK-DAG:             <<Cnv:d\d+>>           VecCnv [<<Load>>,<<LoopP>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array2>>,<<Index>>,<<Cnv>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array1>>,<<Index>>]
+  ///     CHECK-DAG:             <<Cnv:d\d+>>           VecCnv [<<Load>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array2>>,<<Index>>,<<Cnv>>]
+  //
+  /// CHECK-FI:
 
   /// CHECK-START-ARM64: void Main.checkInt2Float(int[], float[]) instruction_simplifier_arm64 (after)
   /// CHECK-DAG:             <<Array1:l\d+>>        ParameterValue
   /// CHECK-DAG:             <<Array2:l\d+>>        ParameterValue
-  /// CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
-  /// CHECK-DAG:             <<Const2:i\d+>>        IntConstant 2
-  //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
-  /// CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array1>>,<<Address1>>]
-  /// CHECK-DAG:             <<Cnv:d\d+>>           VecCnv [<<Load>>]
-  /// CHECK-DAG:             <<Address2:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
-  /// CHECK-DAG:                                    VecStore [<<Array2>>,<<Address2>>,<<Cnv>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      IntermediateAddressIndex is not supported for SVE.
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array1>>,<<Index>>,<<LoopP>>]
+  ///     CHECK-DAG:             <<Cnv:d\d+>>           VecCnv [<<Load>>,<<LoopP>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array2>>,<<Index>>,<<Cnv>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
+  ///     CHECK-DAG:             <<Const2:i\d+>>        IntConstant 2
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array1>>,<<Address1>>]
+  ///     CHECK-DAG:             <<Cnv:d\d+>>           VecCnv [<<Load>>]
+  ///     CHECK-DAG:             <<Address2:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
+  ///     CHECK-DAG:                                    VecStore [<<Array2>>,<<Address2>>,<<Cnv>>]
+  //
+  /// CHECK-FI:
 
   /// CHECK-START-ARM64: void Main.checkInt2Float(int[], float[]) GVN$after_arch (after)
   /// CHECK-DAG:             <<Array1:l\d+>>        ParameterValue
   /// CHECK-DAG:             <<Array2:l\d+>>        ParameterValue
-  /// CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
-  /// CHECK-DAG:             <<Const2:i\d+>>        IntConstant 2
-  //  -------------- Loop
-  /// CHECK-DAG:             <<Index:i\d+>>         Phi
-  /// CHECK-DAG:                                    If
-  /// CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
-  /// CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array1>>,<<Address1>>]
-  /// CHECK-DAG:             <<Cnv:d\d+>>           VecCnv [<<Load>>]
-  /// CHECK-NOT:                                    IntermediateAddress
-  /// CHECK-DAG:                                    VecStore [<<Array2>>,<<Address1>>,<<Cnv>>]
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      IntermediateAddressIndex is not supported for SVE.
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<LoopP:j\d+>>         VecPredWhile
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array1>>,<<Index>>,<<LoopP>>]
+  ///     CHECK-DAG:             <<Cnv:d\d+>>           VecCnv [<<Load>>,<<LoopP>>]
+  ///     CHECK-NOT:                                    IntermediateAddress
+  ///     CHECK-DAG:                                    VecStore [<<Array2>>,<<Index>>,<<Cnv>>,<<LoopP>>]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:             <<DataOffset:i\d+>>    IntConstant 12
+  ///     CHECK-DAG:             <<Const2:i\d+>>        IntConstant 2
+  //      -------------- Loop
+  ///     CHECK-DAG:             <<Index:i\d+>>         Phi
+  ///     CHECK-DAG:                                    If
+  ///     CHECK-DAG:             <<Address1:i\d+>>      IntermediateAddressIndex [<<Index>>,<<DataOffset>>,<<Const2>>]
+  ///     CHECK-DAG:             <<Load:d\d+>>          VecLoad [<<Array1>>,<<Address1>>]
+  ///     CHECK-DAG:             <<Cnv:d\d+>>           VecCnv [<<Load>>]
+  ///     CHECK-NOT:                                    IntermediateAddress
+  ///     CHECK-DAG:                                    VecStore [<<Array2>>,<<Address1>>,<<Cnv>>]
+  //
+  /// CHECK-FI:
 
   /// CHECK-START-ARM64: void Main.checkInt2Float(int[], float[]) disassembly (after)
-  /// CHECK:                                        IntermediateAddressIndex
-  /// CHECK-NEXT:                                   add w{{[0-9]+}}, w{{[0-9]+}}, w{{[0-9]+}}, lsl #2
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      IntermediateAddressIndex is not supported for SVE.
+  ///     CHECK-NOT:                                    IntermediateAddressIndex
+  ///     CHECK-NOT:                                    IntermediateAddress
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK:                                        IntermediateAddressIndex
+  ///     CHECK-NEXT:                                   add w{{[0-9]+}}, w{{[0-9]+}}, w{{[0-9]+}}, lsl #2
+  //
+  /// CHECK-FI:
   public static void checkInt2Float(int[] a, float[] b) {
     for (int i = 0; i < 128; i++) {
       b[i] = (float) a[i];
diff --git a/test/527-checker-array-access-split/Android.bp b/test/527-checker-array-access-split/Android.bp
new file mode 100644
index 0000000..849530a
--- /dev/null
+++ b/test/527-checker-array-access-split/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `527-checker-array-access-split`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-527-checker-array-access-split",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-527-checker-array-access-split-expected-stdout",
+        ":art-run-test-527-checker-array-access-split-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-527-checker-array-access-split-expected-stdout",
+    out: ["art-run-test-527-checker-array-access-split-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-527-checker-array-access-split-expected-stderr",
+    out: ["art-run-test-527-checker-array-access-split-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/527-checker-array-access-split/expected.txt b/test/527-checker-array-access-split/expected-stderr.txt
similarity index 100%
rename from test/527-checker-array-access-split/expected.txt
rename to test/527-checker-array-access-split/expected-stderr.txt
diff --git a/test/527-checker-array-access-split/expected.txt b/test/527-checker-array-access-split/expected-stdout.txt
similarity index 100%
copy from test/527-checker-array-access-split/expected.txt
copy to test/527-checker-array-access-split/expected-stdout.txt
diff --git a/test/528-long-hint/Android.bp b/test/528-long-hint/Android.bp
new file mode 100644
index 0000000..b3ddd56
--- /dev/null
+++ b/test/528-long-hint/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `528-long-hint`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-528-long-hint",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-528-long-hint-expected-stdout",
+        ":art-run-test-528-long-hint-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-528-long-hint-expected-stdout",
+    out: ["art-run-test-528-long-hint-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-528-long-hint-expected-stderr",
+    out: ["art-run-test-528-long-hint-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/528-long-hint/expected.txt b/test/528-long-hint/expected-stderr.txt
similarity index 100%
rename from test/528-long-hint/expected.txt
rename to test/528-long-hint/expected-stderr.txt
diff --git a/test/528-long-hint/expected.txt b/test/528-long-hint/expected-stdout.txt
similarity index 100%
copy from test/528-long-hint/expected.txt
copy to test/528-long-hint/expected-stdout.txt
diff --git a/test/585-inline-unresolved/expected.txt b/test/529-checker-unresolved/expected-stderr.txt
similarity index 100%
copy from test/585-inline-unresolved/expected.txt
copy to test/529-checker-unresolved/expected-stderr.txt
diff --git a/test/529-checker-unresolved/expected.txt b/test/529-checker-unresolved/expected-stdout.txt
similarity index 100%
rename from test/529-checker-unresolved/expected.txt
rename to test/529-checker-unresolved/expected-stdout.txt
diff --git a/test/529-long-split/Android.bp b/test/529-long-split/Android.bp
new file mode 100644
index 0000000..d607272
--- /dev/null
+++ b/test/529-long-split/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `529-long-split`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-529-long-split",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-529-long-split-expected-stdout",
+        ":art-run-test-529-long-split-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-529-long-split-expected-stdout",
+    out: ["art-run-test-529-long-split-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-529-long-split-expected-stderr",
+    out: ["art-run-test-529-long-split-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/529-long-split/expected.txt b/test/529-long-split/expected-stderr.txt
similarity index 100%
rename from test/529-long-split/expected.txt
rename to test/529-long-split/expected-stderr.txt
diff --git a/test/529-long-split/expected.txt b/test/529-long-split/expected-stdout.txt
similarity index 100%
copy from test/529-long-split/expected.txt
copy to test/529-long-split/expected-stdout.txt
diff --git a/test/463-checker-boolean-simplifier/expected.txt b/test/530-checker-instance-of-simplifier/expected-stderr.txt
similarity index 100%
copy from test/463-checker-boolean-simplifier/expected.txt
copy to test/530-checker-instance-of-simplifier/expected-stderr.txt
diff --git a/test/463-checker-boolean-simplifier/expected.txt b/test/530-checker-instance-of-simplifier/expected-stdout.txt
similarity index 100%
copy from test/463-checker-boolean-simplifier/expected.txt
copy to test/530-checker-instance-of-simplifier/expected-stdout.txt
diff --git a/test/530-checker-instance-of-simplifier/info.txt b/test/530-checker-instance-of-simplifier/info.txt
new file mode 100644
index 0000000..61b4741
--- /dev/null
+++ b/test/530-checker-instance-of-simplifier/info.txt
@@ -0,0 +1 @@
+Checker test for testing load-store elimination in presence of VecLoad and VecStore.
diff --git a/test/530-checker-instance-of-simplifier/jasmin/Foo.j b/test/530-checker-instance-of-simplifier/jasmin/Foo.j
new file mode 100644
index 0000000..f64b083
--- /dev/null
+++ b/test/530-checker-instance-of-simplifier/jasmin/Foo.j
@@ -0,0 +1,26 @@
+; Copyright (C) 2021 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.
+
+.source Foo.java
+.class public Foo
+.super java/lang/Object
+
+.field public intField I
+
+.method public <init>()V
+  .limit stack 3
+  aload_0
+  invokespecial java/lang/Object/<init>()V
+  return
+.end method
diff --git a/test/530-checker-instance-of-simplifier/jasmin/Main.j b/test/530-checker-instance-of-simplifier/jasmin/Main.j
new file mode 100644
index 0000000..83cb4fa
--- /dev/null
+++ b/test/530-checker-instance-of-simplifier/jasmin/Main.j
@@ -0,0 +1,139 @@
+; Copyright (C) 2021 The Android Open Source Project
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;      http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+
+.class public Main
+.super java/lang/Object
+
+; Just do simple check that we remove the instance-of. Well formedness
+; checks will be done in gtests.
+;; CHECK-START: int Main.$noinline$test(boolean) instruction_simplifier (before)
+;; CHECK-DAG: LoadClass
+;; CHECK-DAG: LoadClass
+;; CHECK-DAG: InstanceOf
+;
+;; CHECK-START: int Main.$noinline$test(boolean) instruction_simplifier (after)
+;; CHECK-DAG: LoadClass
+;; CHECK-DAG: LoadClass
+;
+;; CHECK-START: int Main.$noinline$test(boolean) instruction_simplifier (after)
+;; CHECK-NOT: InstanceOf
+;
+;; CHECK-START: int Main.$noinline$test(boolean) instruction_simplifier$before_codegen (after)
+;; CHECK-NOT: InstanceFieldSet
+;; CHECK-NOT: InstanceFieldGet
+;; CHECK-NOT: PredicatedInstanceFieldGet
+
+; public static int $noinline$test(boolean escape) {
+;   Foo f = new Foo();
+;   f.intField = 7
+;   if (escape) {
+;     if (f instanceof Bar) {
+;       $noinline$escape(f);
+;     }
+;   }
+;   return f.intField;
+; }
+.method public static $noinline$test(Z)I
+  .limit stack 3
+  new Foo
+  ; Stack: [f]
+  dup
+  ; Stack: [f, f]
+  invokespecial Foo/<init>()V
+  ; Stack: [f]
+  dup
+  ; Stack: [f, f]
+  ldc 7
+  ; Stack: [f, f, 7]
+  putfield Foo/intField I
+  ; Stack: [f]
+  iload_0
+  ; Stack: [f, escape]
+  ifeq finish
+  ; Stack: [f]
+  dup
+  ; Stack: [f, f]
+  ; NB Baz does not exist
+  instanceof Baz
+  ; Stack: [f, is_instance]
+  ifeq finish
+  ; Stack: [f]
+  dup
+  ; Stack: [f, f]
+  invokestatic Main/$noinline$escape(Ljava/lang/Object;)V
+  ; Stack: [f]
+finish:   ; Stack: [f]
+  getfield Foo/intField I
+  ; Stack: [f.intField]
+  ireturn
+.end method
+
+.method public static $noinline$escape(Ljava/lang/Object;)V
+  .limit stack 0
+  return
+.end method
+
+; public static void main(String[] args) {
+;   PrintStream out = System.out;
+;   int i = $noinline$test(false);
+;   if (i != 7) {
+;     out.print("FAIL! GOT ");
+;     out.println(i);
+;   }
+; }
+.method public static main([Ljava/lang/String;)V
+  .limit stack 5
+  ; Stack: []
+  ; locals: [args]
+  getstatic java/lang/System/out Ljava/io/PrintStream;
+  ; Stack: [out]
+  ; locals: [args]
+  astore_0
+  ; Stack: []
+  ; locals: [out]
+  bipush 0
+  ; Stack: [0]
+  ; locals: [out]
+  invokestatic Main/$noinline$test(Z)I
+  ; Stack: [res]
+  ; locals: [out]
+  dup
+  ; Stack: [res, res]
+  ; locals: [out]
+  bipush 7
+  ; Stack: [res, res, 7]
+  ; locals: [out]
+  if_icmpeq finish
+  ; Stack: [res]
+  ; locals: [out]
+  aload_0
+  ; Stack: [res, out]
+  ; locals: [out]
+  dup2
+  ; Stack: [res, out, res, out]
+  ; locals: [out]
+  ldc "FAIL! GOT "
+  ; Stack: [res, out, res, out, "FAIL! GOT "]
+  ; locals: [out]
+  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
+  ; Stack: [res, out, res]
+  ; locals: [out]
+  invokevirtual java/io/PrintStream/println(I)V
+  ; Stack: [res]
+  ; locals: [out]
+finish:
+  ; Stack: [res]
+  ; locals: [out]
+  return
+.end method
diff --git a/test/530-checker-loops1/Android.bp b/test/530-checker-loops1/Android.bp
new file mode 100644
index 0000000..6bbb5af
--- /dev/null
+++ b/test/530-checker-loops1/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-checker-loops1`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-checker-loops1",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-checker-loops1-expected-stdout",
+        ":art-run-test-530-checker-loops1-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-checker-loops1-expected-stdout",
+    out: ["art-run-test-530-checker-loops1-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-checker-loops1-expected-stderr",
+    out: ["art-run-test-530-checker-loops1-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-loops1/expected-stderr.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/530-checker-loops1/expected-stderr.txt
diff --git a/test/530-checker-loops1/expected.txt b/test/530-checker-loops1/expected-stdout.txt
similarity index 100%
rename from test/530-checker-loops1/expected.txt
rename to test/530-checker-loops1/expected-stdout.txt
diff --git a/test/530-checker-loops2/Android.bp b/test/530-checker-loops2/Android.bp
new file mode 100644
index 0000000..d196923
--- /dev/null
+++ b/test/530-checker-loops2/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-checker-loops2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-checker-loops2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-checker-loops2-expected-stdout",
+        ":art-run-test-530-checker-loops2-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-checker-loops2-expected-stdout",
+    out: ["art-run-test-530-checker-loops2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-checker-loops2-expected-stderr",
+    out: ["art-run-test-530-checker-loops2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-loops2/expected-stderr.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/530-checker-loops2/expected-stderr.txt
diff --git a/test/530-checker-loops2/expected.txt b/test/530-checker-loops2/expected-stdout.txt
similarity index 100%
rename from test/530-checker-loops2/expected.txt
rename to test/530-checker-loops2/expected-stdout.txt
diff --git a/test/530-checker-loops3/Android.bp b/test/530-checker-loops3/Android.bp
new file mode 100644
index 0000000..ef2f738
--- /dev/null
+++ b/test/530-checker-loops3/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-checker-loops3`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-checker-loops3",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-checker-loops3-expected-stdout",
+        ":art-run-test-530-checker-loops3-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-checker-loops3-expected-stdout",
+    out: ["art-run-test-530-checker-loops3-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-checker-loops3-expected-stderr",
+    out: ["art-run-test-530-checker-loops3-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-loops3/expected-stderr.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/530-checker-loops3/expected-stderr.txt
diff --git a/test/530-checker-loops3/expected.txt b/test/530-checker-loops3/expected-stdout.txt
similarity index 100%
rename from test/530-checker-loops3/expected.txt
rename to test/530-checker-loops3/expected-stdout.txt
diff --git a/test/530-checker-loops4/Android.bp b/test/530-checker-loops4/Android.bp
new file mode 100644
index 0000000..5401466
--- /dev/null
+++ b/test/530-checker-loops4/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-checker-loops4`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-checker-loops4",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-checker-loops4-expected-stdout",
+        ":art-run-test-530-checker-loops4-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-checker-loops4-expected-stdout",
+    out: ["art-run-test-530-checker-loops4-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-checker-loops4-expected-stderr",
+    out: ["art-run-test-530-checker-loops4-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-loops4/expected-stderr.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/530-checker-loops4/expected-stderr.txt
diff --git a/test/530-checker-loops4/expected.txt b/test/530-checker-loops4/expected-stdout.txt
similarity index 100%
rename from test/530-checker-loops4/expected.txt
rename to test/530-checker-loops4/expected-stdout.txt
diff --git a/test/530-checker-loops5/Android.bp b/test/530-checker-loops5/Android.bp
new file mode 100644
index 0000000..658e985
--- /dev/null
+++ b/test/530-checker-loops5/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-checker-loops5`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-checker-loops5",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-checker-loops5-expected-stdout",
+        ":art-run-test-530-checker-loops5-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-checker-loops5-expected-stdout",
+    out: ["art-run-test-530-checker-loops5-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-checker-loops5-expected-stderr",
+    out: ["art-run-test-530-checker-loops5-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-loops5/expected-stderr.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/530-checker-loops5/expected-stderr.txt
diff --git a/test/530-checker-loops5/expected.txt b/test/530-checker-loops5/expected-stdout.txt
similarity index 100%
rename from test/530-checker-loops5/expected.txt
rename to test/530-checker-loops5/expected-stdout.txt
diff --git a/test/530-checker-lse-ctor-fences/Android.bp b/test/530-checker-lse-ctor-fences/Android.bp
new file mode 100644
index 0000000..c42ed96
--- /dev/null
+++ b/test/530-checker-lse-ctor-fences/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-checker-lse-ctor-fences`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-checker-lse-ctor-fences",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-checker-lse-ctor-fences-expected-stdout",
+        ":art-run-test-530-checker-lse-ctor-fences-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-checker-lse-ctor-fences-expected-stdout",
+    out: ["art-run-test-530-checker-lse-ctor-fences-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-checker-lse-ctor-fences-expected-stderr",
+    out: ["art-run-test-530-checker-lse-ctor-fences-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-checker-lse-ctor-fences/expected.txt b/test/530-checker-lse-ctor-fences/expected-stderr.txt
similarity index 100%
rename from test/530-checker-lse-ctor-fences/expected.txt
rename to test/530-checker-lse-ctor-fences/expected-stderr.txt
diff --git a/test/530-checker-lse-ctor-fences/expected.txt b/test/530-checker-lse-ctor-fences/expected-stdout.txt
similarity index 100%
copy from test/530-checker-lse-ctor-fences/expected.txt
copy to test/530-checker-lse-ctor-fences/expected-stdout.txt
diff --git a/test/530-checker-lse-ctor-fences/smali/Smali.smali b/test/530-checker-lse-ctor-fences/smali/Smali.smali
deleted file mode 100644
index 856af96..0000000
--- a/test/530-checker-lse-ctor-fences/smali/Smali.smali
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-.class public LSmali;
-.super Ljava/lang/Object;
-
-##  CHECK-START: double Smali.calcCircleAreaOrCircumference(double, boolean) load_store_elimination (before)
-##  CHECK: NewInstance
-##  CHECK: InstanceFieldSet
-##  CHECK: ConstructorFence
-##  CHECK: InstanceFieldGet
-
-##  CHECK-START: double Smali.calcCircleAreaOrCircumference(double, boolean) load_store_elimination (after)
-##  CHECK: NewInstance
-##  CHECK-NOT: ConstructorFence
-
-#   The object allocation will not be eliminated by LSE because of aliased stores.
-#   However the object is still a singleton, so it never escapes the current thread.
-#   There should not be a constructor fence here after LSE.
-
-.method public static calcCircleAreaOrCircumference(DZ)D
-    .registers 7
-
-    # CalcCircleAreaOrCircumference calc =
-    #   new CalcCircleAreaOrCircumference(
-    #       area_or_circumference ? CalcCircleAreaOrCircumference.TYPE_AREA :
-    #       CalcCircleAreaOrCircumference.TYPE_CIRCUMFERENCE);
-
-    # if (area_or_circumference) {
-    #   // Area
-    #   calc.value = Math.PI * Math.PI * radius;
-    # } else {
-    #   // Circumference
-    #   calc.value = 2 * Math.PI * radius;
-    # }
-
-    # Please note that D8 would merge the iput togother which looks like :
-
-    # if (area_or_circumference) {
-    #   // Area
-    #   tmp = Math.PI * Math.PI * radius;
-    # } else {
-    #   // Circumference
-    #   tmp = 2 * Math.PI * radius;
-    # }
-    # calc.value = tmp;
-
-    # which makes the LSE valid and defeat the purpose of this test.
-
-    new-instance v0, LCalcCircleAreaOrCircumference;
-
-    if-eqz p2, :cond_15
-
-    const/4 v1, 0x0
-
-    :goto_5
-    invoke-direct {v0, v1}, LCalcCircleAreaOrCircumference;-><init>(I)V
-
-    if-eqz p2, :cond_17
-
-    const-wide v2, 0x4023bd3cc9be45deL    # 9.869604401089358
-
-    mul-double/2addr v2, p0
-
-    iput-wide v2, v0, LCalcCircleAreaOrCircumference;->value:D
-
-    :goto_12
-    iget-wide v2, v0, LCalcCircleAreaOrCircumference;->value:D
-
-    return-wide v2
-
-    :cond_15
-    const/4 v1, 0x1
-
-    goto :goto_5
-
-    :cond_17
-    const-wide v2, 0x401921fb54442d18L    # 6.283185307179586
-
-    mul-double/2addr v2, p0
-
-    iput-wide v2, v0, LCalcCircleAreaOrCircumference;->value:D
-
-    goto :goto_12
-.end method
-
diff --git a/test/530-checker-lse-ctor-fences/src/Main.java b/test/530-checker-lse-ctor-fences/src/Main.java
index c3796ea..fd0972f 100644
--- a/test/530-checker-lse-ctor-fences/src/Main.java
+++ b/test/530-checker-lse-ctor-fences/src/Main.java
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import java.lang.reflect.Method;
 
 // This base class has a single final field;
 // the constructor should have one fence.
@@ -113,13 +112,22 @@
     return new Ellipse(vertex, covertex).getArea();
   }
 
+  /// CHECK-START: double Main.calcCircleAreaOrCircumference(double, boolean) load_store_elimination (before)
+  /// CHECK-DAG: NewInstance
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: ConstructorFence
+  /// CHECK-DAG: InstanceFieldGet
+
   /// CHECK-START: double Main.calcCircleAreaOrCircumference(double, boolean) load_store_elimination (after)
+  /// CHECK:     Phi
+  /// CHECK-NOT: Phi
+
+  /// CHECK-START: double Main.calcCircleAreaOrCircumference(double, boolean) load_store_elimination (after)
+  /// CHECK-NOT: NewInstance
   /// CHECK-NOT: ConstructorFence
 
-  //
-  // The object allocation will not be eliminated by LSE because of aliased stores.
-  // However the object is still a singleton, so it never escapes the current thread.
-  // There should not be a constructor fence here after LSE.
+  // The object allocation shall be eliminated by LSE and the load shall be replaced
+  // by a Phi with the values that were previously being stored.
   static double calcCircleAreaOrCircumference(double radius, boolean area_or_circumference) {
     CalcCircleAreaOrCircumference calc =
       new CalcCircleAreaOrCircumference(
@@ -137,16 +145,6 @@
     return calc.value;
   }
 
-  static double calcCircleAreaOrCircumferenceSmali(double radius, boolean area_or_circumference) {
-    try {
-      Class<?> c = Class.forName("Smali");
-      Method m = c.getMethod("calcCircleAreaOrCircumference", double.class, boolean.class);
-      return (Double) m.invoke(null, radius, area_or_circumference);
-    } catch (Exception ex) {
-      throw new Error(ex);
-    }
-  }
-
   /// CHECK-START: Circle Main.makeCircle(double) load_store_elimination (after)
   /// CHECK: NewInstance
   /// CHECK: ConstructorFence
@@ -188,7 +186,6 @@
     assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI));
     assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcEllipseArea(Math.PI, Math.PI));
     assertDoubleEquals(2 * Math.PI * Math.PI, calcCircleAreaOrCircumference(Math.PI, false));
-    assertDoubleEquals(2 * Math.PI * Math.PI, calcCircleAreaOrCircumferenceSmali(Math.PI, false));
     assertInstanceOf(makeCircle(Math.PI), Circle.class);
   }
 
diff --git a/test/530-checker-lse-simd/Android.bp b/test/530-checker-lse-simd/Android.bp
new file mode 100644
index 0000000..cf08d41
--- /dev/null
+++ b/test/530-checker-lse-simd/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-checker-lse-simd`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-checker-lse-simd",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-checker-lse-simd-expected-stdout",
+        ":art-run-test-530-checker-lse-simd-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-checker-lse-simd-expected-stdout",
+    out: ["art-run-test-530-checker-lse-simd-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-checker-lse-simd-expected-stderr",
+    out: ["art-run-test-530-checker-lse-simd-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-lse-simd/expected-stderr.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/530-checker-lse-simd/expected-stderr.txt
diff --git a/test/530-checker-lse-simd/expected.txt b/test/530-checker-lse-simd/expected-stdout.txt
similarity index 100%
rename from test/530-checker-lse-simd/expected.txt
rename to test/530-checker-lse-simd/expected-stdout.txt
diff --git a/test/530-checker-lse-simd/src/Main.java b/test/530-checker-lse-simd/src/Main.java
index 12dd297..d6049d0 100644
--- a/test/530-checker-lse-simd/src/Main.java
+++ b/test/530-checker-lse-simd/src/Main.java
@@ -90,8 +90,7 @@
   /// CHECK-NEXT: ArrayLength
   /// CHECK-NEXT: BelowOrEqual
   //
-  /// CHECK:      ArrayGet loop:none
-  /// CHECK-NEXT: Return
+  /// CHECK:      Return
   static double $noinline$test02(double a[], int n) {
     double b[] = new double[n];
     a[0] = a[0] / 2;
@@ -103,7 +102,7 @@
       b[i] += a[i];
     }
 
-    norma = a[0];
+    norma = a[0]; // ArrayGet should be removed by LSE.
     return norma;
   }
 
@@ -145,19 +144,27 @@
   // Check LSE eliminates VecLoad.
   //
   /// CHECK-START-ARM64: double[] Main.$noinline$test04(int) load_store_elimination (before)
-  /// CHECK:             VecStore
-  /// CHECK-NEXT:        VecLoad
-  /// CHECK-NEXT:        VecAdd
-  /// CHECK-NEXT:        VecStore
-  /// CHECK-NEXT:        Add
-  /// CHECK-NEXT:        Goto loop:{{B\d+}}
+  /// CHECK:        VecStore
+  /// CHECK:        VecLoad
+  /// CHECK:        VecAdd
+  /// CHECK:        VecStore
+  /// CHECK:        Add
+  /// CHECK:        Goto loop:{{B\d+}}
 
   /// CHECK-START-ARM64: double[] Main.$noinline$test04(int) load_store_elimination (after)
-  /// CHECK:             VecStore
-  /// CHECK-NEXT:        VecAdd
-  /// CHECK-NEXT:        VecStore
-  /// CHECK-NEXT:        Add
-  /// CHECK-NEXT:        Goto loop:{{B\d+}}
+  /// CHECK-IF:     not hasIsaFeature("sve")
+  //
+  //      In NEON case there is a post-loop which prevents the store to be removed.
+  ///     CHECK:        VecStore
+  //
+  /// CHECK-FI:
+  //
+  /// CHECK:        VecAdd
+  /// CHECK:        VecStore
+  /// CHECK:        Add
+  /// CHECK:        Goto loop:{{B\d+}}
+  //
+  /// CHECK-NOT:    VecStore
   static double[] $noinline$test04(int n) {
     double a[] = new double[n];
     double b[] = new double[n];
@@ -179,18 +186,26 @@
   // Check LSE eliminates VecLoad.
   //
   /// CHECK-START-ARM64: double[] Main.$noinline$test05(int) load_store_elimination (before)
-  /// CHECK:             VecStore
-  /// CHECK-NEXT:        VecLoad
-  /// CHECK-NEXT:        VecStore
-  /// CHECK-NEXT:        VecStore
-  /// CHECK-NEXT:        Add
-  /// CHECK-NEXT:        Goto loop:{{B\d+}}
+  /// CHECK:        VecStore
+  /// CHECK:        VecLoad
+  /// CHECK:        VecStore
+  /// CHECK:        VecStore
+  /// CHECK:        Add
+  /// CHECK:        Goto loop:{{B\d+}}
 
   /// CHECK-START-ARM64: double[] Main.$noinline$test05(int) load_store_elimination (after)
-  /// CHECK:             VecStore
-  /// CHECK-NEXT:        VecStore
-  /// CHECK-NEXT:        Add
-  /// CHECK-NEXT:        Goto loop:{{B\d+}}
+  /// CHECK-IF:     not hasIsaFeature("sve")
+  //
+  //      In NEON case there is a post-loop which prevents the store to be removed.
+  ///     CHECK:        VecStore
+  //
+  /// CHECK-FI:
+  //
+  /// CHECK:        VecStore
+  /// CHECK:        Add
+  /// CHECK:        Goto loop:{{B\d+}}
+  //
+  /// CHECK-NOT:    VecStore
   static double[] $noinline$test05(int n) {
     double a[] = new double[n];
     double b[] = new double[n];
@@ -213,29 +228,30 @@
   // Check LSE eliminates VecLoad and ArrayGet in case of singletons and default values.
   //
   /// CHECK-START-ARM64: double[] Main.$noinline$test06(int) load_store_elimination (before)
-  /// CHECK:             BoundsCheck loop:none
-  /// CHECK-NEXT:        ArrayGet
-  /// CHECK-NEXT:        Add
-  /// CHECK-NEXT:        ArrayLength
+  /// CHECK:        BoundsCheck loop:none
+  /// CHECK:        ArrayGet
+  /// CHECK:        Add
+  /// CHECK:        ArrayLength
   //
-  /// CHECK:             VecLoad loop:{{B\d+}}
-  /// CHECK-NEXT:        VecStore
-  /// CHECK-NEXT:        VecLoad
-  /// CHECK-NEXT:        VecLoad
-  /// CHECK-NEXT:        VecAdd
-  /// CHECK-NEXT:        VecAdd
-  /// CHECK-NEXT:        VecStore
+  /// CHECK:        VecLoad loop:{{B\d+}}
+  /// CHECK:        VecStore
+  /// CHECK:        VecLoad
+  /// CHECK:        VecLoad
+  /// CHECK:        VecAdd
+  /// CHECK:        VecAdd
+  /// CHECK:        VecStore
 
   /// CHECK-START-ARM64: double[] Main.$noinline$test06(int) load_store_elimination (after)
-  /// CHECK:             BoundsCheck loop:none
-  /// CHECK-NEXT:        Add
-  /// CHECK-NEXT:        ArrayLength
+  /// CHECK:        BoundsCheck loop:none
+  /// CHECK:        Add
+  /// CHECK:        ArrayLength
   //
-  /// CHECK:             VecLoad loop:{{B\d+}}
-  /// CHECK-NEXT:        VecStore
-  /// CHECK-NEXT:        VecAdd
-  /// CHECK-NEXT:        VecAdd
-  /// CHECK-NEXT:        VecStore
+  /// CHECK:        VecLoad loop:{{B\d+}}
+  /// CHECK:        VecAdd
+  /// CHECK:        VecAdd
+  /// CHECK:        VecStore
+  //
+  /// CHECK-NOT:    VecStore
   static double[] $noinline$test06(int n) {
     double a[] = new double[n];
     double b[] = new double[n];
diff --git a/test/530-checker-lse/Android.bp b/test/530-checker-lse/Android.bp
new file mode 100644
index 0000000..ea8995e
--- /dev/null
+++ b/test/530-checker-lse/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-checker-lse`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-checker-lse",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-checker-lse-expected-stdout",
+        ":art-run-test-530-checker-lse-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-checker-lse-expected-stdout",
+    out: ["art-run-test-530-checker-lse-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-checker-lse-expected-stderr",
+    out: ["art-run-test-530-checker-lse-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-lse/expected-stderr.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/530-checker-lse/expected-stderr.txt
diff --git a/test/530-checker-lse/expected-stdout.txt b/test/530-checker-lse/expected-stdout.txt
new file mode 100644
index 0000000..90fcfc5
--- /dev/null
+++ b/test/530-checker-lse/expected-stdout.txt
@@ -0,0 +1,2 @@
+java.lang.ArrayIndexOutOfBoundsException
+Got NegativeArraySizeException.
diff --git a/test/530-checker-lse/expected.txt b/test/530-checker-lse/expected.txt
deleted file mode 100644
index fb67e22..0000000
--- a/test/530-checker-lse/expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-java.lang.ArrayIndexOutOfBoundsException: length=3; index=3
-Got NegativeArraySizeException.
diff --git a/test/530-checker-lse/smali/Main.smali b/test/530-checker-lse/smali/Main.smali
deleted file mode 100644
index 4c18266..0000000
--- a/test/530-checker-lse/smali/Main.smali
+++ /dev/null
@@ -1,292 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-.class public LMain2;
-.super Ljava/lang/Object;
-.source "Main.java"
-
-# direct methods
-
-## CHECK-START: int Main2.test4(TestClass, boolean) load_store_elimination (before)
-## CHECK: InstanceFieldSet
-## CHECK: InstanceFieldGet
-## CHECK: Return
-## CHECK: InstanceFieldSet
-
-## CHECK-START: int Main2.test4(TestClass, boolean) load_store_elimination (after)
-## CHECK: InstanceFieldSet
-## CHECK-NOT: NullCheck
-## CHECK-NOT: InstanceFieldGet
-## CHECK: Return
-## CHECK: InstanceFieldSet
-
-# Set and merge the same value in two branches.
-
-# Original java source:
-#
-#     static int test4(TestClass obj, boolean b) {
-#       if (b) {
-#         obj.i = 1;
-#       } else {
-#         obj.i = 1;
-#       }
-#       return obj.i;
-#     }
-
-.method public static test4(LTestClass;Z)I
-    .registers 3
-    .param p0, "obj"    # LTestClass;
-    .param p1, "b"    # Z
-
-    .prologue
-    const/4 v0, 0x1
-
-    .line 185
-    if-eqz p1, :cond_8
-
-    .line 186
-    iput v0, p0, LTestClass;->i:I
-
-    .line 190
-    :goto_5
-    iget v0, p0, LTestClass;->i:I
-
-    return v0
-
-    .line 188
-    :cond_8
-    iput v0, p0, LTestClass;->i:I
-
-    goto :goto_5
-.end method
-
-## CHECK-START: int Main2.test5(TestClass, boolean) load_store_elimination (before)
-## CHECK: InstanceFieldSet
-## CHECK: InstanceFieldGet
-## CHECK: Return
-## CHECK: InstanceFieldSet
-
-## CHECK-START: int Main2.test5(TestClass, boolean) load_store_elimination (after)
-## CHECK: InstanceFieldSet
-## CHECK: InstanceFieldGet
-## CHECK: Return
-## CHECK: InstanceFieldSet
-
-# Set and merge different values in two branches.
-# Original java source:
-#
-#     static int test5(TestClass obj, boolean b) {
-#       if (b) {
-#         obj.i = 1;
-#       } else {
-#         obj.i = 2;
-#       }
-#       return obj.i;
-#     }
-
-.method public static test5(LTestClass;Z)I
-    .registers 3
-    .param p0, "obj"    # LTestClass;
-    .param p1, "b"    # Z
-
-    .prologue
-    .line 207
-    if-eqz p1, :cond_8
-
-    .line 208
-    const/4 v0, 0x1
-
-    iput v0, p0, LTestClass;->i:I
-
-    .line 212
-    :goto_5
-    iget v0, p0, LTestClass;->i:I
-
-    return v0
-
-    .line 210
-    :cond_8
-    const/4 v0, 0x2
-
-    iput v0, p0, LTestClass;->i:I
-
-    goto :goto_5
-.end method
-
-## CHECK-START: int Main2.test10(TestClass) load_store_elimination (before)
-## CHECK: StaticFieldGet
-## CHECK: InstanceFieldGet
-## CHECK: StaticFieldSet
-## CHECK: InstanceFieldGet
-
-## CHECK-START: int Main2.test10(TestClass) load_store_elimination (after)
-## CHECK: StaticFieldGet
-## CHECK: InstanceFieldGet
-## CHECK: StaticFieldSet
-## CHECK-NOT: NullCheck
-## CHECK-NOT: InstanceFieldGet
-
-# Original java source:
-#
-#  // Static fields shouldn't alias with instance fields.
-#  static int test10(TestClass obj) {
-#    TestClass.si += obj.i;
-#    return obj.i;
-#  }
-
-.method public static test10(LTestClass;)I
-    .registers 3
-    .param p0, "obj"    # LTestClass;
-    sget                v0, LTestClass;->si:I
-    iget                v1, p0, LTestClass;->i:I
-    add-int/2addr       v0, v1
-    sput                v0, LTestClass;->si:I
-    iget                p0, p0, LTestClass;->i:I
-    return              p0
-.end method
-
-## CHECK-START: int Main2.test23(boolean) load_store_elimination (before)
-## CHECK: NewInstance
-## CHECK: InstanceFieldSet
-## CHECK: InstanceFieldGet
-## CHECK: InstanceFieldSet
-## CHECK: InstanceFieldGet
-## CHECK: Return
-## CHECK: InstanceFieldGet
-## CHECK: InstanceFieldSet
-
-## CHECK-START: int Main2.test23(boolean) load_store_elimination (after)
-## CHECK: NewInstance
-## CHECK-NOT: InstanceFieldSet
-## CHECK-NOT: InstanceFieldGet
-## CHECK: InstanceFieldSet
-## CHECK: InstanceFieldGet
-## CHECK: Return
-## CHECK-NOT: InstanceFieldGet
-## CHECK: InstanceFieldSet
-
-# Test store elimination on merging.
-
-# Original java source:
-#
-#     static int test23(boolean b) {
-#       TestClass obj = new TestClass();
-#       obj.i = 3;      // This store can be eliminated since the value flows into each branch.
-#       if (b) {
-#         obj.i += 1;   // This store cannot be eliminated due to the merge later.
-#       } else {
-#         obj.i += 2;   // This store cannot be eliminated due to the merge later.
-#       }
-#       return obj.i;
-#     }
-
-.method public static test23(Z)I
-    .registers 3
-    .param p0, "b"    # Z
-
-    .prologue
-    .line 582
-    new-instance v0, LTestClass;
-
-    invoke-direct {v0}, LTestClass;-><init>()V
-
-    .line 583
-    .local v0, "obj":LTestClass;
-    const/4 v1, 0x3
-
-    iput v1, v0, LTestClass;->i:I
-
-    .line 584
-    if-eqz p0, :cond_13
-
-    .line 585
-    iget v1, v0, LTestClass;->i:I
-
-    add-int/lit8 v1, v1, 0x1
-
-    iput v1, v0, LTestClass;->i:I
-
-    .line 589
-    :goto_10
-    iget v1, v0, LTestClass;->i:I
-
-    return v1
-
-    .line 587
-    :cond_13
-    iget v1, v0, LTestClass;->i:I
-
-    add-int/lit8 v1, v1, 0x2
-
-    iput v1, v0, LTestClass;->i:I
-
-    goto :goto_10
-.end method
-
-## CHECK-START: float Main2.test24() load_store_elimination (before)
-## CHECK-DAG:     <<True:i\d+>>     IntConstant 1
-## CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
-## CHECK-DAG:     <<Float42:f\d+>>  FloatConstant 42
-## CHECK-DAG:     <<Obj:l\d+>>      NewInstance
-## CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<True>>]
-## CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float8>>]
-## CHECK-DAG:     <<GetTest:z\d+>>  InstanceFieldGet [<<Obj>>]
-## CHECK-DAG:     <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
-## CHECK-DAG:     <<Select:f\d+>>   Select [<<Float42>>,<<GetField>>,<<GetTest>>]
-## CHECK-DAG:                       Return [<<Select>>]
-
-## CHECK-START: float Main2.test24() load_store_elimination (after)
-## CHECK-DAG:     <<True:i\d+>>     IntConstant 1
-## CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
-## CHECK-DAG:     <<Float42:f\d+>>  FloatConstant 42
-## CHECK-DAG:     <<Select:f\d+>>   Select [<<Float42>>,<<Float8>>,<<True>>]
-## CHECK-DAG:                       Return [<<Select>>]
-
-# Original java source:
-#
-#     static float test24() {
-#       float a = 42.0f;
-#       TestClass3 obj = new TestClass3();
-#       if (obj.test1) {
-#         a = obj.floatField;
-#       }
-#       return a;
-#     }
-
-.method public static test24()F
-    .registers 3
-
-    .prologue
-    .line 612
-    const/high16 v0, 0x42280000    # 42.0f
-
-    .line 613
-    .local v0, "a":F
-    new-instance v1, LTestClass3;
-
-    invoke-direct {v1}, LTestClass3;-><init>()V
-
-    .line 614
-    .local v1, "obj":LTestClass3;
-    iget-boolean v2, v1, LTestClass3;->test1:Z
-
-    if-eqz v2, :cond_d
-
-    .line 615
-    iget v0, v1, LTestClass3;->floatField:F
-
-    .line 617
-    :cond_d
-    return v0
-.end method
diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java
index 22bff0a..35f1dc2 100644
--- a/test/530-checker-lse/src/Main.java
+++ b/test/530-checker-lse/src/Main.java
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-import java.lang.reflect.Method;
-
 class Circle {
   Circle(double radius) {
     this.radius = radius;
@@ -44,6 +42,7 @@
   volatile int k;
   TestClass next;
   String str;
+  byte b;
   static int si;
   static TestClass sTestClassObj;
 }
@@ -55,6 +54,9 @@
 class TestClass2 {
   int i;
   int j;
+  int k;
+  int l;
+  int m;
 }
 
 class TestClass3 {
@@ -62,6 +64,20 @@
   boolean test1 = true;
 }
 
+// Chosen to have different values with (x + 1) * 10 and (x - 1) * 10. This
+// means we can easily make sure that different code is in fact executed on
+// escape and non-escape paths.
+// Negative so that high-bits will be set for all the 64-bit values allowing us
+// to easily check for truncation.
+class TestClass4 {
+  float floatField = -3.0f;
+  double doubleField = -3.0d;
+  short shortField = -3;
+  int intField = -3;
+  byte byteField = -3;
+  long longField = -3l;
+}
+
 class Finalizable {
   static boolean sVisited = false;
   static final int VALUE1 = 0xbeef;
@@ -81,6 +97,23 @@
 }
 
 public class Main {
+  static void $noinline$Escape4(TestClass4 o) {
+    o.floatField += 1.0f;
+    o.doubleField += 1.0d;
+    o.byteField += 1;
+    o.shortField += 1;
+    o.intField += 1;
+    o.longField += 1;
+  }
+
+  static Object ESCAPE = null;
+  static void $noinline$Escape(TestClass o) {
+    if (o == null) {
+      return;
+    }
+    ESCAPE = o;
+    o.next.i++;
+  }
 
   /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before)
   /// CHECK: NewInstance
@@ -140,6 +173,7 @@
   /// CHECK: InstanceFieldSet
   /// CHECK: InstanceFieldSet
   /// CHECK: InstanceFieldSet
+  /// CHECK: InstanceFieldSet
   /// CHECK: InstanceFieldGet
   /// CHECK: InstanceFieldGet
   /// CHECK: InstanceFieldGet
@@ -152,8 +186,10 @@
   /// CHECK: InstanceFieldSet
   /// CHECK: InstanceFieldSet
   /// CHECK: InstanceFieldSet
+  /// CHECK: InstanceFieldSet
+
+  /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after)
   /// CHECK-NOT: InstanceFieldGet
-  /// CHECK-NOT: StaticFieldGet
 
   // A new allocation (even non-singleton) shouldn't alias with pre-existing values.
   static int test3(TestClass obj) {
@@ -169,19 +205,83 @@
     return obj.i + obj1.j + obj2.i + obj2.j;
   }
 
+  /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before)
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldGet
+  /// CHECK-DAG: Return
+
+  /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: Return
+
+  /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:     NullCheck
+  /// CHECK:     NullCheck
+  /// CHECK-NOT: NullCheck
+
+  /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-NOT: InstanceFieldGet
+  /// CHECK-NOT: Phi
+
+  // Set and merge the same value in two branches.
+  static int test4(TestClass obj, boolean b) {
+    if (b) {
+      obj.i = 1;
+    } else {
+      obj.i = 1;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before)
+  /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
+  /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
+  /// CHECK-DAG:  <<Obj:l\d+>>       ParameterValue
+  /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int1>>]
+  /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int2>>]
+  /// CHECK-DAG:  <<GetField:i\d+>>  InstanceFieldGet [{{l\d+}}]
+  /// CHECK-DAG:                     Return [<<GetField>>]
+
+  /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
+  /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
+  /// CHECK-DAG:  <<Obj:l\d+>>       ParameterValue
+  /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int1>>]
+  /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int2>>]
+  /// CHECK-DAG:  <<Phi:i\d+>>       Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
+  /// CHECK-DAG:                     Return [<<Phi>>]
+  /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Int1>>","<<Int2>>"])
+
+  /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-NOT: InstanceFieldGet
+
+  // Set and merge different values in two branches.
+  static int test5(TestClass obj, boolean b) {
+    if (b) {
+      obj.i = 1;
+    } else {
+      obj.i = 2;
+    }
+    return obj.i;
+  }
+
   /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before)
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldGet
-  /// CHECK: InstanceFieldGet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldGet
+  /// CHECK-DAG: InstanceFieldGet
 
   /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after)
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldGet
+
+  /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after)
   /// CHECK: InstanceFieldGet
-  /// CHECK-NOT: NullCheck
   /// CHECK-NOT: InstanceFieldGet
 
   // Setting the same value doesn't clear the value for aliased locations.
@@ -251,6 +351,31 @@
     return obj2.i;
   }
 
+  /// CHECK-START: int Main.test10(TestClass) load_store_elimination (before)
+  /// CHECK-DAG: StaticFieldGet
+  /// CHECK-DAG: InstanceFieldGet
+  /// CHECK-DAG: StaticFieldSet
+  /// CHECK-DAG: InstanceFieldGet
+
+  /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after)
+  /// CHECK-DAG: StaticFieldGet
+  /// CHECK-DAG: InstanceFieldGet
+  /// CHECK-DAG: StaticFieldSet
+
+  /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after)
+  /// CHECK:     NullCheck
+  /// CHECK-NOT: NullCheck
+
+  /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after)
+  /// CHECK:     InstanceFieldGet
+  /// CHECK-NOT: InstanceFieldGet
+
+  // Static fields shouldn't alias with instance fields.
+  static int test10(TestClass obj) {
+    TestClass.si += obj.i;
+    return obj.i;
+  }
+
   /// CHECK-START: int Main.test11(TestClass) load_store_elimination (before)
   /// CHECK: InstanceFieldSet
   /// CHECK: InstanceFieldGet
@@ -261,7 +386,6 @@
   /// CHECK-NOT: InstanceFieldGet
 
   // Loop without heap writes.
-  // obj.i is actually hoisted to the loop pre-header by licm already.
   static int test11(TestClass obj) {
     obj.i = 1;
     int sum = 0;
@@ -336,9 +460,11 @@
   /// CHECK-START: int Main.test15() load_store_elimination (after)
   /// CHECK: <<Const2:i\d+>> IntConstant 2
   /// CHECK: StaticFieldSet
-  /// CHECK-NOT: StaticFieldGet
   /// CHECK: Return [<<Const2>>]
 
+  /// CHECK-START: int Main.test15() load_store_elimination (after)
+  /// CHECK-NOT: StaticFieldGet
+
   // Static field access from subclass's name.
   static int test15() {
     TestClass.si = 1;
@@ -436,23 +562,29 @@
   /// CHECK: InstanceFieldGet
 
   /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after)
-  /// CHECK: NewInstance
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldGet
-  /// CHECK: InstanceFieldGet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: Phi
+
+  /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after)
+  /// CHECK-NOT: NewInstance
+  /// CHECK-NOT: InstanceFieldGet
 
   // Loop side effects can kill heap values, stores need to be kept in that case.
   static void test21(TestClass obj0) {
     TestClass obj = new TestClass();
     obj0.str = "abc";
     obj.str = "abc";
+    // Note: This loop is transformed by the loop optimization pass, therefore we
+    // are not checking the exact number of InstanceFieldSet and Phi instructions.
     for (int i = 0; i < 2; i++) {
       // Generate some loop side effect that writes into obj.
       obj.str = "def";
     }
-    System.out.print(obj0.str.substring(0, 0) + obj.str.substring(0, 0));
+    $noinline$printSubstrings00(obj0.str, obj.str);
+  }
+
+  static void $noinline$printSubstrings00(String str1, String str2) {
+    System.out.print(str1.substring(0, 0) + str2.substring(0, 0));
   }
 
   /// CHECK-START: int Main.test22() load_store_elimination (before)
@@ -469,12 +601,6 @@
   /// CHECK-START: int Main.test22() load_store_elimination (after)
   /// CHECK-NOT: NewInstance
   /// CHECK-NOT: InstanceFieldSet
-  /// CHECK-NOT: NewInstance
-  /// CHECK-NOT: InstanceFieldSet
-  /// CHECK-NOT: InstanceFieldGet
-  /// CHECK-NOT: NewInstance
-  /// CHECK-NOT: InstanceFieldSet
-  /// CHECK-NOT: InstanceFieldGet
   /// CHECK-NOT: InstanceFieldGet
 
   // For a singleton, loop side effects can kill its field values only if:
@@ -495,6 +621,759 @@
     return sum;
   }
 
+  /// CHECK-START: int Main.test23(boolean) load_store_elimination (before)
+  /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
+  /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
+  /// CHECK-DAG:  <<Int3:i\d+>>      IntConstant 3
+  /// CHECK-DAG:  <<Obj:l\d+>>       NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet [<<Obj>>,<<Int3>>]
+  /// CHECK-DAG:  <<Add1:i\d+>>      Add [<<Get1:i\d+>>,<<Int1>>]
+  /// CHECK-DAG:  <<Get1>>           InstanceFieldGet [<<Obj>>]
+  /// CHECK-DAG:                     InstanceFieldSet [<<Obj>>,<<Add1>>]
+  /// CHECK-DAG:  <<Add2:i\d+>>      Add [<<Get2:i\d+>>,<<Int2>>]
+  /// CHECK-DAG:  <<Get2>>           InstanceFieldGet [<<Obj>>]
+  /// CHECK-DAG:                     InstanceFieldSet [<<Obj>>,<<Add2>>]
+  /// CHECK-DAG:                     Return [<<Get3:i\d+>>]
+  /// CHECK-DAG:  <<Get3>>           InstanceFieldGet [<<Obj>>]
+
+  /// CHECK-START: int Main.test23(boolean) load_store_elimination (after)
+  /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
+  /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
+  /// CHECK-DAG:  <<Int3:i\d+>>      IntConstant 3
+  /// CHECK-DAG:  <<Add1:i\d+>>      Add [<<Int3>>,<<Int1>>]
+  /// CHECK-DAG:  <<Add2:i\d+>>      Add [<<Int3>>,<<Int2>>]
+  /// CHECK-DAG:  <<Phi:i\d+>>       Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
+  /// CHECK-DAG:                     Return [<<Phi>>]
+  /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Add1>>","<<Add2>>"])
+
+  /// CHECK-START: int Main.test23(boolean) load_store_elimination (after)
+  /// CHECK-NOT: NewInstance
+  /// CHECK-NOT: InstanceFieldSet
+  /// CHECK-NOT: InstanceFieldGet
+
+  // Test heap value merging from multiple branches.
+  static int test23(boolean b) {
+    TestClass obj = new TestClass();
+    obj.i = 3;      // This store can be eliminated since the value flows into each branch.
+    if (b) {
+      obj.i += 1;   // This store can be eliminated after replacing the load below with a Phi.
+    } else {
+      obj.i += 2;   // This store can be eliminated after replacing the load below with a Phi.
+    }
+    return obj.i;   // This load is eliminated by creating a Phi.
+  }
+
+  /// CHECK-START: float Main.test24() load_store_elimination (before)
+  /// CHECK-DAG:     <<True:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
+  /// CHECK-DAG:     <<Float42:f\d+>>  FloatConstant 42
+  /// CHECK-DAG:     <<Obj:l\d+>>      NewInstance
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<True>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float8>>]
+  /// CHECK-DAG:     <<GetTest:z\d+>>  InstanceFieldGet [<<Obj>>]
+  /// CHECK-DAG:     <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
+  /// CHECK-DAG:     <<Select:f\d+>>   Select [<<Float42>>,<<GetField>>,<<GetTest>>]
+  /// CHECK-DAG:                       Return [<<Select>>]
+
+  /// CHECK-START: float Main.test24() load_store_elimination (after)
+  /// CHECK-DAG:     <<True:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
+  /// CHECK-DAG:     <<Float42:f\d+>>  FloatConstant 42
+  /// CHECK-DAG:     <<Select:f\d+>>   Select [<<Float42>>,<<Float8>>,<<True>>]
+  /// CHECK-DAG:                       Return [<<Select>>]
+
+  /// CHECK-START: float Main.test24() load_store_elimination (after)
+  /// CHECK-NOT:                       NewInstance
+  /// CHECK-NOT:                       InstanceFieldGet
+  static float test24() {
+    float a = 42.0f;
+    TestClass3 obj = new TestClass3();
+    if (obj.test1) {
+      a = obj.floatField;
+    }
+    return a;
+  }
+
+  /// CHECK-START: int Main.test25(boolean, boolean, boolean) load_store_elimination (before)
+  /// CHECK-DAG:     <<Int1:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<Int2:i\d+>>     IntConstant 2
+  /// CHECK-DAG:     <<Int3:i\d+>>     IntConstant 3
+  /// CHECK-DAG:     <<Int5:i\d+>>     IntConstant 5
+  /// CHECK-DAG:     <<Int6:i\d+>>     IntConstant 6
+  /// CHECK-DAG:     <<Obj:l\d+>>      NewInstance
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Int1>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Int2>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Int3>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Int5>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Int6>>]
+  /// CHECK-DAG:     <<GetField:i\d+>> InstanceFieldGet [<<Obj>>]
+  /// CHECK-DAG:                       Return [<<GetField>>]
+
+  /// CHECK-START: int Main.test25(boolean, boolean, boolean) load_store_elimination (after)
+  /// CHECK-DAG:     <<Int1:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<Int2:i\d+>>     IntConstant 2
+  /// CHECK-DAG:     <<Int3:i\d+>>     IntConstant 3
+  /// CHECK-DAG:     <<Int5:i\d+>>     IntConstant 5
+  /// CHECK-DAG:     <<Int6:i\d+>>     IntConstant 6
+  /// CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>,<<Arg4:i\d+>>,<<Arg5:i\d+>>]
+  /// CHECK-DAG:                       Return [<<Phi>>]
+  /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>","<<Arg4>>","<<Arg5>>"]) == set(["<<Int1>>","<<Int2>>","<<Int3>>","<<Int5>>","<<Int6>>"])
+
+  /// CHECK-START: int Main.test25(boolean, boolean, boolean) load_store_elimination (after)
+  /// CHECK-NOT:                       NewInstance
+  /// CHECK-NOT:                       InstanceFieldSet
+  /// CHECK-NOT:                       InstanceFieldGet
+
+  // Test heap value merging from nested branches.
+  static int test25(boolean b, boolean c, boolean d) {
+    TestClass obj = new TestClass();
+    if (b) {
+      if (c) {
+        obj.i = 1;
+      } else {
+        if (d) {
+          obj.i = 2;
+        } else {
+          obj.i = 3;
+        }
+      }
+    } else {
+      if (c) {
+        obj.i = 5;
+      } else {
+        obj.i = 6;
+      }
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: float Main.test26(int) load_store_elimination (before)
+  /// CHECK-DAG:     <<Float0:f\d+>>   FloatConstant 0
+  /// CHECK-DAG:     <<Float1:f\d+>>   FloatConstant 1
+  /// CHECK-DAG:     <<Float2:f\d+>>   FloatConstant 2
+  /// CHECK-DAG:     <<Float3:f\d+>>   FloatConstant 3
+  /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
+  /// CHECK-DAG:     <<Obj:l\d+>>      NewInstance
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float8>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float0>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float1>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float2>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float3>>]
+  /// CHECK-DAG:     <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
+  /// CHECK-DAG:                       Return [<<GetField>>]
+
+  /// CHECK-START: float Main.test26(int) load_store_elimination (after)
+  /// CHECK-DAG:     <<Float0:f\d+>>   FloatConstant 0
+  /// CHECK-DAG:     <<Float1:f\d+>>   FloatConstant 1
+  /// CHECK-DAG:     <<Float2:f\d+>>   FloatConstant 2
+  /// CHECK-DAG:     <<Float3:f\d+>>   FloatConstant 3
+  /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
+  /// CHECK-DAG:     <<Phi:f\d+>>      Phi [<<Arg1:f\d+>>,<<Arg2:f\d+>>,<<Arg3:f\d+>>,<<Arg4:f\d+>>]
+  /// CHECK-DAG:                       Return [<<Phi>>]
+  /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>","<<Arg4>>"]) == set(["<<Float0>>","<<Float1>>","<<Float2>>","<<Float3>>"])
+
+  /// CHECK-START: float Main.test26(int) load_store_elimination (after)
+  /// CHECK-NOT:                       NewInstance
+  /// CHECK-NOT:                       InstanceFieldSet
+  /// CHECK-NOT:                       InstanceFieldGet
+
+  // Test heap value merging from switch statement.
+  static float test26(int b) {
+    TestClass3 obj = new TestClass3();
+    switch (b) {
+      case 1:
+        obj.floatField = 3.0f;
+        break;
+      case 2:
+        obj.floatField = 2.0f;
+        break;
+      case 3:
+        obj.floatField = 1.0f;
+        break;
+      default:
+        obj.floatField = 0.0f;
+        break;
+    }
+    return obj.floatField;
+  }
+
+  /// CHECK-START: int Main.test27(boolean, boolean) load_store_elimination (before)
+  /// CHECK-DAG:   <<Int1:i\d+>>      IntConstant 1
+  /// CHECK-DAG:   <<Obj:l\d+>>       NewInstance
+  /// CHECK-DAG:                      InstanceFieldSet [<<Obj>>,<<Int1>>]
+  /// CHECK-DAG:                      InstanceFieldSet [<<Obj>>,<<Int1>>]
+  /// CHECK-DAG:                      InstanceFieldSet [<<Obj>>,<<Int1>>]
+  /// CHECK-DAG:                      InstanceFieldSet [<<Obj>>,<<Int1>>]
+  /// CHECK-DAG:   <<GetField:i\d+>>  InstanceFieldGet [<<Obj>>]
+  /// CHECK-DAG:                      Return [<<GetField>>]
+
+  /// CHECK-START: int Main.test27(boolean, boolean) load_store_elimination (after)
+  /// CHECK-DAG:   <<Int1:i\d+>>      IntConstant 1
+  /// CHECK-DAG:                      Return [<<Int1>>]
+
+  /// CHECK-START: int Main.test27(boolean, boolean) load_store_elimination (after)
+  /// CHECK-NOT:                      NewInstance
+  /// CHECK-NOT:                      InstanceFieldSet
+  /// CHECK-NOT:                      InstanceFieldGet
+  /// CHECK-NOT:                      Phi
+
+  // Test merging same value from nested branches.
+  static int test27(boolean b, boolean c) {
+    TestClass obj = new TestClass();
+    if (b) {
+      if (c) {
+        obj.i = 1;
+      } else {
+        obj.i = 1;
+      }
+    } else {
+      if (c) {
+        obj.i = 1;
+      } else {
+        obj.i = 1;
+      }
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.test28(boolean, boolean) load_store_elimination (before)
+  /// CHECK-DAG:   <<Int0:i\d+>>      IntConstant 0
+  /// CHECK-DAG:   <<Int5:i\d+>>      IntConstant 5
+  /// CHECK-DAG:   <<Int6:i\d+>>      IntConstant 6
+  /// CHECK-DAG:   <<Array:l\d+>>     NewArray
+  /// CHECK-DAG:                      ArraySet [<<Array>>,<<Int0>>,<<Int5>>]
+  /// CHECK-DAG:                      ArraySet [<<Array>>,<<Int0>>,<<Int6>>]
+  /// CHECK-DAG:   <<GetIndex:i\d+>>  ArrayGet [<<Array>>,<<Int0>>]
+  /// CHECK-DAG:                      Return [<<GetIndex>>]
+
+  /// CHECK-START: int Main.test28(boolean, boolean) load_store_elimination (after)
+  /// CHECK-DAG:   <<Int0:i\d+>>      IntConstant 0
+  /// CHECK-DAG:   <<Int5:i\d+>>      IntConstant 5
+  /// CHECK-DAG:   <<Int6:i\d+>>      IntConstant 6
+  /// CHECK-DAG:   <<Phi:i\d+>>       Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>]
+  /// CHECK-DAG:                      Return [<<Phi>>]
+  /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>"]) == set(["<<Int0>>","<<Int5>>","<<Int6>>"])
+
+  /// CHECK-START: int Main.test28(boolean, boolean) load_store_elimination (after)
+  /// CHECK-NOT:                       NewArray
+  /// CHECK-NOT:                       ArraySet
+  /// CHECK-NOT:                       ArrayGet
+
+  // Test merging array stores in branches.
+  static int test28(boolean b, boolean c) {
+    int[] array = new int[1];
+    if (b) {
+      if (c) {
+        array[0] = 5;
+      } else {
+        array[0] = 6;
+      }
+    } else { /* Default value: 0. */ }
+    return array[0];
+  }
+
+  /// CHECK-START: float Main.test29(boolean) load_store_elimination (before)
+  /// CHECK-DAG:     <<Float2:f\d+>>   FloatConstant 2
+  /// CHECK-DAG:     <<Float5:f\d+>>   FloatConstant 5
+  /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
+  /// CHECK-DAG:     <<Obj:l\d+>>      NewInstance
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float8>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float2>>]
+  /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float5>>]
+  /// CHECK-DAG:     <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
+  /// CHECK-DAG:                       Return [<<GetField>>]
+
+  /// CHECK-START: float Main.test29(boolean) load_store_elimination (after)
+  /// CHECK-DAG:     <<Float2:f\d+>>   FloatConstant 2
+  /// CHECK-DAG:     <<Float5:f\d+>>   FloatConstant 5
+  /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
+  /// CHECK-DAG:     <<Phi:f\d+>>      Phi [<<Arg1:f\d+>>,<<Arg2:f\d+>>]
+  /// CHECK-DAG:                       Return [<<Phi>>]
+  /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Float5>>","<<Float2>>"])
+
+  /// CHECK-START: float Main.test29(boolean) load_store_elimination (after)
+  /// CHECK-NOT:                       NewInstance
+  /// CHECK-NOT:                       InstanceFieldSet
+  /// CHECK-NOT:                       InstanceFieldGet
+
+  // Test implicit type conversion in branches.
+  static float test29(boolean b) {
+    TestClass3 obj = new TestClass3();
+    if (b) {
+      obj.floatField = 5; // Int
+    } else {
+      obj.floatField = 2L; // Long
+    }
+    return obj.floatField;
+  }
+
+  /// CHECK-START: int Main.test30(TestClass, boolean) load_store_elimination (before)
+  /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
+  /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
+  /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int1>>]
+  /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int2>>]
+  /// CHECK-DAG:  <<GetField:i\d+>>  InstanceFieldGet [{{l\d+}}]
+  /// CHECK-DAG:                     Return [<<GetField>>]
+
+  /// CHECK-START: int Main.test30(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
+  /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
+  /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int1>>]
+  /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int2>>]
+  /// CHECK-DAG:  <<GetField:i\d+>>  InstanceFieldGet [{{l\d+}}]
+  /// CHECK-DAG:                     Return [<<GetField>>]
+
+  /// CHECK-START: int Main.test30(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-NOT: Phi
+
+  // Don't merge different values in two branches for different variables.
+  static int test30(TestClass obj, boolean b) {
+    if (b) {
+      obj.i = 1;
+    } else {
+      obj.j = 2;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.test31(boolean, boolean) load_store_elimination (before)
+  /// CHECK-DAG:  <<Int2:i\d+>>  IntConstant 2
+  /// CHECK-DAG:  <<Int5:i\d+>>  IntConstant 5
+  /// CHECK-DAG:  <<Int6:i\d+>>  IntConstant 6
+  /// CHECK-DAG:                 InstanceFieldSet [{{l\d+}},<<Int5>>] field_name:{{.*TestClass.i}}
+  /// CHECK-DAG:                 InstanceFieldSet [{{l\d+}},<<Int6>>] field_name:{{.*TestClass.i}}
+  /// CHECK-DAG:  <<Get1:i\d+>>  InstanceFieldGet [{{l\d+}}] field_name:{{.*TestClass.i}}
+  /// CHECK-DAG:                 InstanceFieldSet [{{l\d+}},<<Get1>>] field_name:{{.*TestClass.j}}
+  /// CHECK-DAG:                 InstanceFieldSet [{{l\d+}},<<Int2>>] field_name:{{.*TestClass.i}}
+  /// CHECK-DAG:  <<Get2:i\d+>>  InstanceFieldGet [{{l\d+}}]
+  /// CHECK-DAG:                 Return [<<Get2>>]
+
+  /// CHECK-START: int Main.test31(boolean, boolean) load_store_elimination (after)
+  /// CHECK-DAG:  <<Int2:i\d+>>  IntConstant 2
+  /// CHECK-DAG:  <<Int5:i\d+>>  IntConstant 5
+  /// CHECK-DAG:  <<Int6:i\d+>>  IntConstant 6
+  /// CHECK-DAG:  <<Phi1:i\d+>>  Phi [<<Int5>>,<<Int6>>]
+  /// CHECK-DAG:  <<Phi2:i\d+>>  Phi [<<Phi1>>,<<Int2>>]
+  /// CHECK-DAG:                 Return [<<Phi2>>]
+
+  /// CHECK-START: int Main.test31(boolean, boolean) load_store_elimination (after)
+  /// CHECK-NOT:                 NewInstance
+  /// CHECK-NOT:                 InstanceFieldSet
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test nested branches that can't be flattened.
+  static int test31(boolean b, boolean c) {
+    TestClass obj = new TestClass();
+    if (b) {
+      if (c) {
+        obj.i = 5;
+      } else {
+        obj.i = 6;
+      }
+      obj.j = obj.i;
+    } else {
+      obj.i = 2;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.test32(int) load_store_elimination (before)
+  /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
+  /// CHECK-DAG:  <<Int10:i\d+>>     IntConstant 10
+  /// CHECK-DAG:  InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.i}}
+  /// CHECK-DAG:  InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.j}}
+  /// CHECK-DAG:  InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.k}}
+  /// CHECK-DAG:  InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.l}}
+  /// CHECK-DAG:  InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.m}}
+  /// CHECK-DAG:                     Return [<<Int10>>]
+
+  /// CHECK-START: int Main.test32(int) load_store_elimination (after)
+  /// CHECK-DAG:  <<Int10:i\d+>>     IntConstant 10
+  /// CHECK-DAG:                     Return [<<Int10>>]
+
+  /// CHECK-START: int Main.test32(int) load_store_elimination (after)
+  /// CHECK-NOT:                     NewInstance
+  /// CHECK-NOT:                     InstanceFieldGet
+  /// CHECK-NOT:                     InstanceFieldSet
+  /// CHECK-NOT:                     Phi
+
+  // Test no unused Phi instructions are created.
+  static int test32(int i) {
+    TestClass2 obj = new TestClass2();
+    // By default, i/j/k/l/m are initialized to 0.
+    switch (i) {
+      case 1: obj.i = 1; break;
+      case 2: obj.j = 1; break;
+      case 3: obj.k = 1; break;
+      case 4: obj.l = 1; break;
+      case 5: obj.m = 1; break;
+    }
+    // So here, each variable has value Phi [0,1,1,1,1,1].
+    // But since no heap values are used, we should not be creating these Phis.
+    return 10;
+  }
+
+  /// CHECK-START: int Main.test33(TestClass, boolean) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG: <<Phi:i\d+>>        Phi
+  /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Phi>>]
+
+  /// CHECK-START: int Main.test33(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+
+  /// CHECK-START: int Main.test33(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK-NOT:                     InstanceFieldSet
+
+  // Test eliminating non-observable stores.
+  static int test33(TestClass obj, boolean x) {
+    int phi;
+    if (x) {
+      obj.i = 1;
+      phi = 1;
+    } else {
+      obj.i = 2;
+      phi = 2;
+    }
+    obj.i = phi;
+    return phi;
+  }
+
+  /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG: <<Phi:i\d+>>        Phi
+  /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Phi>>]
+
+  /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+
+  /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK-NOT:                     InstanceFieldSet
+
+  // Test eliminating a store that writes a Phi equivalent to merged
+  // heap values of observable stores.
+  static int test34(TestClass obj, boolean x, boolean y) {
+    int phi;
+    if (x) {
+      obj.i = 1;
+      phi = 1;
+      if (y) {
+        return 3;
+      }
+    } else {
+      obj.i = 2;
+      phi = 2;
+      if (y) {
+        return 4;
+      }
+    }
+    obj.i = phi;
+    return phi;
+  }
+
+  /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+
+  /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (after)
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  // Test Phi creation for load elimination.
+  static int test35(TestClass obj, boolean x, boolean y) {
+    if (x) {
+      obj.i = 1;
+    } else {
+      obj.i = 2;
+    }
+    if (y) {
+      if (x) {
+        obj.i = 3;
+      }
+      obj.j = 5;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+
+  /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:                         Phi
+  /// CHECK-NOT:                     Phi
+
+  // Test Phi matching for load elimination.
+  static int test36(TestClass obj, boolean x) {
+    int phi;
+    if (x) {
+      obj.i = 1;
+      phi = 1;
+    } else {
+      obj.i = 2;
+      phi = 2;
+    }
+    // The load is replaced by the existing Phi instead of constructing a new one.
+    return obj.i + phi;
+  }
+
+  /// CHECK-START: int Main.test37(TestClass, boolean) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.test37(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  // Test preserving observable stores.
+  static int test37(TestClass obj, boolean x) {
+    if (x) {
+      obj.i = 1;
+    }
+    int tmp = obj.i;  // The store above must be kept.
+    obj.i = 2;
+    return tmp;
+  }
+
+  /// CHECK-START: int Main.test38(TestClass, boolean) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.test38(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK-NOT:                     InstanceFieldSet
+
+  // Test eliminating store of the same value after eliminating non-observable stores.
+  static int test38(TestClass obj, boolean x) {
+    obj.i = 1;
+    if (x) {
+      return 1;  // The store above must be kept.
+    }
+    obj.i = 2;  // Not observable, shall be eliminated.
+    obj.i = 3;  // Not observable, shall be eliminated.
+    obj.i = 1;  // After eliminating the non-observable stores above, this stores the
+                // same value that is already stored in `obj.i` and shall be eliminated.
+    return 2;
+  }
+
+  /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (before)
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldGet
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  // Test creating a reference Phi for load elimination.
+  static int test39(TestClass obj, boolean x) {
+    obj.next = new TestClass(1, 2);
+    if (x) {
+      obj.next = new SubTestClass();
+    }
+    return obj.next.i;
+  }
+
+  /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     TypeConversion
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+
+  /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         Phi
+  /// CHECK-NOT:                     Phi
+
+  // Test tracking values containing type conversion.
+  // Regression test for b/161521389 .
+  static int $noinline$testConversion1(TestClass obj, int x) {
+    obj.i = x;
+    if ((x & 1) != 0) {
+      obj.b = (byte) x;
+      obj.i = obj.b;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     TypeConversion
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     TypeConversion
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+
+  /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         Phi
+  /// CHECK:                         Phi
+  /// CHECK-NOT:                     Phi
+
+  /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         TypeConversion
+  /// CHECK-NOT:                     TypeConversion
+
+  /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  // Test moving type conversion when needed.
+  static int $noinline$testConversion2(TestClass obj, int x) {
+    int tmp = 0;
+    obj.i = x;
+    if ((x & 1) != 0) {
+      // The instruction simplifier can remove this TypeConversion if there are
+      // no environment uses. Currently, there is an environment use in NullCheck,
+      // so this TypeConversion remains and GVN removes the second TypeConversion
+      // below. Since we really want to test that the TypeConversion from below
+      // can be moved and used for the load of `obj.b`, we have a similar test
+      // written in smali in 530-checker-lse3, StoreLoad.test3(int), except that
+      // it's using static fields (which would not help with the environment use).
+      obj.b = (byte) x;
+      obj.i = obj.b;
+      tmp = (byte) x;
+    }
+    return obj.i + tmp;
+  }
+
+  /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     TypeConversion
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         Phi
+  /// CHECK:                         Phi
+  /// CHECK-NOT:                     Phi
+
+  /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         TypeConversion
+  /// CHECK-NOT:                     TypeConversion
+
+  /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  // Test tracking values containing type conversion with loop.
+  static int $noinline$testConversion3(TestClass obj, int x) {
+    obj.i = x;
+    for (int i = 0; i < x; ++i) {
+      obj.b = (byte) i;
+      obj.i = obj.b;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     TypeConversion
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     TypeConversion
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         Phi
+  /// CHECK:                         Phi
+  /// CHECK-NOT:                     Phi
+
+  /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         TypeConversion
+  /// CHECK-NOT:                     TypeConversion
+
+  /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  // Test moving type conversion when needed with loop.
+  static int $noinline$testConversion4(TestClass obj, int x) {
+    int tmp = x;
+    obj.i = x;
+    for (int i = 0; i < x; ++i) {
+      obj.b = (byte) i;
+      obj.i = obj.b;
+      tmp = (byte) i;
+    }
+    return obj.i + tmp;
+  }
+
   /// CHECK-START: void Main.testFinalizable() load_store_elimination (before)
   /// CHECK: NewInstance
   /// CHECK: InstanceFieldSet
@@ -557,9 +1436,6 @@
 
   // Test that HSelect creates alias.
   static int $noinline$testHSelect(boolean b) {
-    if (sFlag) {
-      throw new Error();
-    }
     TestClass obj = new TestClass();
     TestClass obj2 = null;
     obj.i = 0xdead;
@@ -580,11 +1456,11 @@
   }
 
   /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (before)
-  /// CHECK: NewInstance
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldGet
-  /// CHECK: InstanceFieldGet
+  /// CHECK-DAG: NewInstance
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldGet
+  /// CHECK-DAG: InstanceFieldGet
 
   /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (after)
   /// CHECK-NOT: NewInstance
@@ -680,6 +1556,9 @@
   /// CHECK: InstanceFieldSet
   /// CHECK-NOT: InstanceFieldSet
 
+  /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (after)
+  /// CHECK-NOT: Phi
+
   private static void testStoreStore3(TestClass2 obj, boolean flag) {
     obj.i = 41;
     obj.j = 42;    // redundant since it's overwritten in both branches below.
@@ -948,20 +1827,24 @@
   }
 
   /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (before)
-  /// CHECK: NewInstance
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldGet
-  /// CHECK: Return
-  /// CHECK: InstanceFieldSet
-  /// CHECK: Throw
+  /// CHECK-DAG: NewInstance
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldGet
+  /// CHECK-DAG: Return
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: Throw
 
   /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after)
-  /// CHECK-NOT: NewInstance
+  /// CHECK-DAG: Return
+  /// CHECK-DAG: Throw
+
+  /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after)
   /// CHECK-NOT: InstanceFieldSet
   /// CHECK-NOT: InstanceFieldGet
-  /// CHECK: Return
-  /// CHECK-NOT: InstanceFieldSet
-  /// CHECK: Throw
+
+  /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after)
+  /// CHECK: NewInstance
+  /// CHECK-NOT: NewInstance
   private static int testExitMerge(boolean cond) {
     TestClass obj = new TestClass();
     if (cond) {
@@ -969,16 +1852,16 @@
       return obj.i + 1;
     } else {
       obj.i = 2;
-      throw new Error();
+      throw new Error();  // Note: We have a NewInstance here.
     }
   }
 
   /// CHECK-START: int Main.testExitMerge2(boolean) load_store_elimination (before)
-  /// CHECK: NewInstance
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldGet
-  /// CHECK: InstanceFieldSet
-  /// CHECK: InstanceFieldGet
+  /// CHECK-DAG: NewInstance
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldGet
+  /// CHECK-DAG: InstanceFieldSet
+  /// CHECK-DAG: InstanceFieldGet
 
   /// CHECK-START: int Main.testExitMerge2(boolean) load_store_elimination (after)
   /// CHECK-NOT: NewInstance
@@ -1010,7 +1893,26 @@
     Object[] array = new Object[2];
     sArray = array;
     Object obj = array[0];
-    array[1] = obj;    // store the same value as the defaut value.
+    array[1] = obj;    // Store the same value as the default value.
+  }
+
+  /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG: <<Value:b\d+>>  ArrayGet
+  /// CHECK-DAG:                 Return [<<Value>>]
+
+  /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (after)
+  /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+  /// CHECK-DAG:                 Return [<<Const0>>]
+
+  /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (after)
+  /// CHECK-NOT:                 NewArray
+  /// CHECK-NOT:                 ArrayGet
+  /// CHECK-NOT:                 TypeConversion
+  private static int $noinline$testByteArrayDefaultValue() {
+    byte[] array = new byte[2];
+    array[1] = 1;  // FIXME: Without any stores, LSA tells LSE not to run.
+    return array[0];
   }
 
   static Object[] sArray;
@@ -1058,22 +1960,24 @@
   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const3>>]
   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [<<A>>,<<Const0>>]
   /// CHECK-DAG:                 Return [<<Get>>]
-  //
+
   /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (after)
-  /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
-  /// CHECK-DAG: <<A:l\d+>>      NewArray
-  /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [<<A>>,<<Const0>>]
-  /// CHECK-DAG:                 Return [<<Get>>]
-  //
+  /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
+  /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+  /// CHECK-DAG: <<Phi:i\d+>>    Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
+  /// CHECK-DAG:                 Return [<<Phi>>]
+  /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const2>>","<<Const3>>"])
+
   /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (after)
-  /// CHECK-DAG:                 ArraySet
-  /// CHECK-DAG:                 ArraySet
+  /// CHECK-NOT:                 NewArray
   /// CHECK-NOT:                 ArraySet
+  /// CHECK-NOT:                 ArrayGet
   private static int testLocalArrayMerge2(boolean x) {
     // The explicit store can be removed eventually even
     // though it is not equivalent to the default.
     int[] a = { 1 };
-    // The diamond pattern stores/load remain.
+    // The load after the diamond pattern is eliminated and replaced with a Phi,
+    // stores are then also eliminated.
     if (x) {
       a[0] = 2;
     } else {
@@ -1082,7 +1986,7 @@
     return a[0];
   }
 
-  /// CHECK-START: int Main.testLocalArrayMerge3(boolean) load_store_elimination (after)
+  /// CHECK-START: int Main.testLocalArrayMerge3(boolean) load_store_elimination (before)
   /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
   /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
   /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
@@ -1091,8 +1995,12 @@
   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const2>>]
   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [<<A>>,<<Const0>>]
   /// CHECK-DAG:                 Return [<<Get>>]
+
+  /// CHECK-START: int Main.testLocalArrayMerge3(boolean) load_store_elimination (after)
+  /// CHECK-NOT:                 NewArray
+  /// CHECK-NOT:                 ArraySet
+  /// CHECK-NOT:                 ArrayGet
   private static int testLocalArrayMerge3(boolean x) {
-    // All stores/load remain.
     int[] a = { 1 };
     if (x) {
       a[0] = 2;
@@ -1135,6 +2043,2178 @@
     return a[0] + (a[0] & 0xff);
   }
 
+  /// CHECK-START: int Main.testLocalArrayMerge5(int[], boolean) load_store_elimination (before)
+  /// CHECK:                     ArraySet
+  /// CHECK:                     ArraySet
+  /// CHECK:                     ArraySet
+
+  /// CHECK-START: int Main.testLocalArrayMerge5(int[], boolean) load_store_elimination (after)
+  /// CHECK-NOT:                 ArraySet
+
+  // Test eliminating store of the same value after eliminating non-observable stores.
+  private static int testLocalArrayMerge5(int[] a, boolean x) {
+    int old = a[0];
+    if (x) {
+      a[0] = 1;
+    } else {
+      a[0] = 1;
+    }
+    // This store makes the stores above dead and they will be eliminated.
+    // That makes this store unnecessary as we're storing the same value already
+    // present in this location, so it shall also be eliminated.
+    a[0] = old;
+    return old;
+  }
+
+  /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (before)
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+
+  /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after)
+  /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+  /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
+  /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG: <<Phi:i\d+>>    Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
+  /// CHECK-DAG:                 Return [<<Phi>>]
+  /// CHECK-DAG: <<Sub:i\d+>>    Sub [<<Const3>>,<<Phi>>]
+  /// CHECK-DAG:                 Return [<<Sub>>]
+  /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const1>>","<<Const2>>"])
+
+  /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after)
+  /// CHECK-NOT:                 ArrayGet
+
+  // Test that we create a single Phi for eliminating two loads in different blocks.
+  private static int testLocalArrayMerge6(int[] a, boolean x, boolean y) {
+    a[0] = 0;
+    if (x) {
+      a[0] = 1;
+    } else {
+      a[0] = 2;
+    }
+    // Phi for load elimination is created here.
+    if (y) {
+      return a[0];
+    } else {
+      return 3 - a[0];
+    }
+  }
+
+  /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (before)
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArrayGet
+
+  /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (after)
+  /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+  /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+  /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 Return [<<Phi2:i\d+>>]
+  /// CHECK-DAG: <<Phi2>>        Phi [<<Arg3:i\d+>>,<<Arg4:i\d+>>]
+  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
+  /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const1>>","<<Const2>>"])
+  /// CHECK-EVAL: set(["<<Arg3>>","<<Arg4>>"]) == set(["<<Const0>>","<<Phi1>>"])
+
+  /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (after)
+  /// CHECK-NOT:                 ArrayGet
+
+  // Test Phi creation for load elimination.
+  private static int testLocalArrayMerge7(int[] a, boolean x, boolean y) {
+    a[1] = 0;
+    if (x) {
+      if (y) {
+        a[0] = 1;
+      } else {
+        a[0] = 2;
+      }
+      a[1] = a[0];
+    }
+    return a[1];
+  }
+
+  /// CHECK-START: int Main.testLocalArrayMerge8(boolean) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+
+  /// CHECK-START: int Main.testLocalArrayMerge8(boolean) load_store_elimination (after)
+  /// CHECK-NOT:                 NewArray
+  /// CHECK-NOT:                 ArraySet
+  /// CHECK-NOT:                 ArrayGet
+
+  // Test Merging default value and an identical value.
+  private static int testLocalArrayMerge8(boolean x) {
+    int[] a = new int[2];
+    if (x) {
+      a[0] = 1;  // Make sure the store below is not eliminated immediately as
+                 // storing the same value already present in the heap location.
+      a[0] = 0;  // Store the same value as default value to test merging with
+                 // the default value from else-block.
+    } else {
+      // Do the same as then-block for a different heap location to avoid
+      // relying on block ordering. (Test both `default+0` and `0+default`.)
+      a[1] = 1;
+      a[1] = 0;
+    }
+    return a[0] + a[1];
+  }
+
+  /// CHECK-START: void Main.$noinline$testThrowingArraySet(java.lang.Object[], java.lang.Object) load_store_elimination (before)
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+
+  /// CHECK-START: void Main.$noinline$testThrowingArraySet(java.lang.Object[], java.lang.Object) load_store_elimination (after)
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+  private static void $noinline$testThrowingArraySet(Object[] a, Object o) {
+    Object olda0 = a[0];
+    a[0] = null;
+    a[1] = olda0;
+    a[0] = o;
+    a[1] = null;
+  }
+
+  /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 Phi
+
+  /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+
+  /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test Phi creation for load elimination with loop.
+  private static int testLoop1(TestClass obj, int n) {
+    obj.i = 0;
+    for (int i = 0; i < n; ++i) {
+      obj.i = i;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 Phi
+
+  /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test that we do not create any Phis for load elimination when
+  // the heap value was not modified in the loop.
+  private static int testLoop2(TestClass obj, int n) {
+    obj.i = 1;
+    for (int i = 0; i < n; ++i) {
+      obj.j = i;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldSet
+  /// CHECK-NOT:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test elimination of a store in the loop that stores the same value that was already
+  // stored before the loop and eliminating the load of that value after the loop.
+  private static int testLoop3(TestClass obj, int n) {
+    obj.i = 1;
+    for (int i = 0; i < n; ++i) {
+      obj.i = 1;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldSet
+  /// CHECK-NOT:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test store elimination in the loop that stores the same value that was already
+  // stored before the loop, without any loads of that value.
+  private static int testLoop4(TestClass obj, int n) {
+    obj.i = 1;
+    for (int i = 0; i < n; ++i) {
+      obj.i = 1;
+    }
+    return n;
+  }
+
+  /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldSet
+  /// CHECK:                     InstanceFieldSet
+  /// CHECK-NOT:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test eliminating loads and stores that just shuffle the same value between
+  // different heap locations.
+  private static int testLoop5(TestClass obj, int n) {
+    // Initialize both `obj.i` and `obj.j` to the same value and then swap these values
+    // in the loop. We should be able to determine that the values are always the same.
+    obj.i = n;
+    obj.j = n;
+    for (int i = 0; i < n; ++i) {
+      if ((i & 1) != 0) {
+        int tmp = obj.i;
+        obj.i = obj.j;
+        obj.j = tmp;
+      }
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldSet
+  /// CHECK:                     InstanceFieldSet
+  /// CHECK-NOT:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test eliminating loads and stores that just shuffle the same value between
+  // different heap locations, or store the same value.
+  private static int testLoop6(TestClass obj, int n) {
+    // Initialize both `obj.i` and `obj.j` to the same value and then swap these values
+    // in the loop or set `obj.i` to the same value. We should be able to determine
+    // that the values are always the same.
+    obj.i = n;
+    obj.j = n;
+    for (int i = 0; i < n; ++i) {
+      if ((i & 1) != 0) {
+        int tmp = obj.i;
+        obj.i = obj.j;
+        obj.j = tmp;
+      } else {
+        obj.i = n;
+      }
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testLoop7(int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewInstance
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop7(int) load_store_elimination (after)
+  /// CHECK-NOT:                 NewInstance
+  /// CHECK-NOT:                 InstanceFieldSet
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test eliminating loads and stores that just shuffle the default value between
+  // different heap locations, or store the same value.
+  private static int testLoop7(int n) {
+    // Leave both `obj.i` and `obj.j` initialized to the default value and then
+    // swap these values in the loop or set some to the identical value 0.
+    // We should be able to determine that the values are always the same.
+    TestClass obj = new TestClass();
+    for (int i = 0; i < n; ++i) {
+      if ((i & 1) != 0) {
+        int tmp = obj.i;
+        obj.i = obj.j;
+        obj.j = tmp;
+      } else {
+        obj.i = 0;
+      }
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testLoop8(int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewInstance
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop8(int) load_store_elimination (after)
+  /// CHECK-NOT:                 NewInstance
+  /// CHECK-NOT:                 InstanceFieldSet
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop8(int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test eliminating loads and stores that just shuffle the same value between
+  // different heap locations, or store the same value. The value is loaded
+  // after conditionally setting a different value after the loop to test that
+  // this does not cause creation of excessive Phis.
+  private static int testLoop8(int n) {
+    // Leave both `obj.i` and `obj.j` initialized to the default value and then
+    // swap these values in the loop or set some to the identical value 0.
+    // We should be able to determine that the values are always the same.
+    TestClass obj = new TestClass();
+    for (int i = 0; i < n; ++i) {
+      if ((i & 1) != 0) {
+        int tmp = obj.i;
+        obj.i = obj.j;
+        obj.j = tmp;
+      } else {
+        obj.i = 0;
+      }
+    }
+    // Up to this point, `obj.i` is always 0 but the Phi placeholder below
+    // must not be included in that determination despite using lazy search
+    // for Phi placeholders triggered by the `obj.i` load below.
+    if ((n & 1) == 0) {
+      obj.i = 1;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewInstance
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InvokeStaticOrDirect
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+
+  /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldSet
+  /// CHECK:                     InstanceFieldSet
+  /// CHECK-NOT:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 NewInstance
+
+  /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldGet
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test that unknown value flowing through a loop back-edge prevents
+  // elimination of a load but that load can be used as an input to a Phi
+  // created to eliminate another load.
+  private static int testLoop9(TestClass obj, int n) {
+    TestClass obj0 = new TestClass();
+    // Initialize both `obj.i` and `obj0.i` to the same value and then swap these values
+    // in the loop or clobber `obj.i`. We should determine that the `obj.i` load in the
+    // loop must be kept but the `obj0.i` load can be replaced by a Phi chain.
+    obj0.i = n;
+    obj.i = n;
+    for (int i = 0; i < n; ++i) {
+      if ((i & 1) != 0) {
+        int tmp = obj0.i;
+        obj0.i = obj.i;  // Load cannot be eliminated.
+        obj.i = tmp;
+      } else {
+        $noinline$clobberObservables();  // Makes obj.i unknown.
+      }
+    }
+    return obj0.i;
+  }
+
+  /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldGet
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test load elimination after finding a non-eliminated load depending
+  // on loop Phi placeholder.
+  private static int testLoop10(TestClass obj, int n) {
+    obj.i = 1;
+    for (int i = 0; i < n; ++i) {
+      $noinline$clobberObservables();
+    }
+    int i1 = obj.i;
+    obj.j = 2;  // Use write side effects to stop GVN from eliminating the load below.
+    int i2 = obj.i;
+    return i1 + i2;
+  }
+
+  /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+
+  /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test load elimination creating two Phis that depend on each other.
+  private static int testLoop11(TestClass obj, int n) {
+    obj.i = 1;
+    for (int i = 0; i < n; ++i) {
+      if ((i & 1) != 0) {
+        obj.i = 2;
+      } else {
+        obj.i = 3;
+      }
+      // There shall be a Phi created here for `obj.i` before the "++i".
+      // This Phi and the loop Phi that shall be created for `obj.i` depend on each other.
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test load elimination creating a single Phi with more than 2 inputs.
+  private static int testLoop12(TestClass obj, int n) {
+    obj.i = 1;
+    for (int i = 0; i < n; ) {
+      // Do the loop variable increment first, so that there are back-edges
+      // directly from the "then" and "else" blocks below.
+      ++i;
+      if ((i & 1) != 0) {
+        obj.i = 2;
+      } else {
+        obj.i = 3;
+      }
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArrayGet
+
+  /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 NewArray
+  /// CHECK-NOT:                 ArrayGet
+  /// CHECK-NOT:                 ArraySet
+
+  /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test eliminating array allocation, loads and stores and creating loop Phis.
+  private static int testLoop13(TestClass obj, int n) {
+    int[] a = new int[3];
+    for (int i = 0; i < n; ++i) {
+      a[0] = a[1];
+      a[1] = a[2];
+      a[2] = obj.i;
+    }
+    return a[0];
+  }
+
+  /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.i
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 InstanceFieldGet field_name:TestClass2.i
+  /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.j
+  /// CHECK-DAG:                 InstanceFieldGet field_name:TestClass2.i
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.k
+  /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.j
+  /// CHECK-DAG:                 InstanceFieldGet field_name:TestClass2.i
+  /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.k
+  /// CHECK-DAG:                 ArrayGet
+
+  /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.i
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet field_name:TestClass2.i
+  /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.j
+  /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.k
+  /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.j
+  /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.k
+
+  /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
+  /// CHECK-NOT:                 NewArray
+
+  /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldGet field_name:TestClass2.i
+  /// CHECK-NOT:                 InstanceFieldGet field_name:TestClass2.i
+
+  /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test load elimination in a loop after determing that the first field load
+  // (depending on loop Phi placeholder) cannot be eliminated.
+  private static int testLoop14(TestClass2 obj, int n) {
+    int[] a = new int[3];
+    obj.i = 1;
+    for (int i = 0; i < n; ++i) {
+      a[0] = a[1];
+      a[1] = a[2];
+      int i1 = obj.i;
+      obj.j = 2;  // Use write side effects to stop GVN from eliminating the load below.
+      int i2 = obj.i;
+      a[2] = i1;
+      if ((i & 2) != 0) {
+        obj.k = i2;
+      } else {
+        obj.j = 3;  // Use write side effects to stop GVN from eliminating the load below.
+        obj.k = obj.i;
+        $noinline$clobberObservables();  // Make obj.i unknown.
+      }
+    }
+    return a[0];
+  }
+
+  /// CHECK-START: int Main.testLoop15(int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG:                 VecPredWhile
+  ///     CHECK-DAG:                 VecStore
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:                 ArraySet
+  //
+  /// CHECK-FI:
+  //
+  /// CHECK-DAG:                 ArrayGet
+
+  /// CHECK-START: int Main.testLoop15(int) load_store_elimination (after)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG:                 VecPredWhile
+  ///     CHECK-DAG:                 VecStore
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:                 ArraySet
+  //
+  /// CHECK-FI:
+  //
+  /// CHECK-DAG:                 ArrayGet
+  // Test that aliasing array store in the loop is not eliminated
+  // when a loop Phi placeholder is marked for keeping.
+  private static int testLoop15(int n) {
+    int[] a = new int[n + 1];
+    for (int i = 0; i < n; ++i) {
+      a[i] = 1;  // Cannot be eliminated due to aliasing.
+    }
+    return a[0];
+  }
+
+  /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         Phi
+  /// CHECK-NOT:                     Phi
+
+  // Test that we match an existing loop Phi for eliminating a load.
+  static int testLoop16(TestClass obj, int n) {
+    obj.i = 0;
+    for (int i = 0; i < n; ) {
+      ++i;
+      obj.i = i;
+    }
+    // The load is replaced by the existing Phi instead of constructing a new one.
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+
+  /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         Phi
+  /// CHECK:                         Phi
+  /// CHECK-NOT:                     Phi
+
+  // Test that we match an existing non-loop Phi for eliminating a load,
+  // one input of the Phi being invariant across a preceding loop.
+  static int testLoop17(TestClass obj, int n) {
+    obj.i = 1;
+    int phi = 1;
+    for (int i = 0; i < n; ++i) {
+      obj.j = 2;  // Unrelated.
+    }
+    if ((n & 1) != 0) {
+      obj.i = 2;
+      phi = 2;
+    }
+    // The load is replaced by the existing Phi instead of constructing a new one.
+    return obj.i + phi;
+  }
+
+  /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     NewArray
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     ArrayGet
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     NewArray
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     ArrayGet
+
+  // Test eliminating a load of the default value in a loop
+  // with the array index being defined inside the loop.
+  static int testLoop18(TestClass obj, int n) {
+    // The NewArray is kept as it may throw for negative n.
+    // TODO: Eliminate constructor fence even though the NewArray is kept.
+    int[] a0 = new int[n];
+    for (int i = 0; i < n; ++i) {
+      obj.i = a0[i];
+    }
+    return n;
+  }
+
+  /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     NewArray
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     ArrayGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     ArraySet
+
+  /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     NewArray
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     ArrayGet
+  /// CHECK-NOT:                     ArraySet
+
+  // Test eliminating a load of the default value and store of an identical value
+  // in a loop with the array index being defined inside the loop.
+  static int testLoop19(TestClass obj, int n) {
+    // The NewArray is kept as it may throw for negative n.
+    // TODO: Eliminate constructor fence even though the NewArray is kept.
+    int[] a0 = new int[n];
+    for (int i = 0; i < n; ++i) {
+      obj.i = a0[i];
+      a0[i] = 0;  // Store the same value as default.
+    }
+    return n;
+  }
+
+  /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     NewArray
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     ArrayGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     ArraySet
+
+  /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     NewArray
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     ArrayGet
+  /// CHECK-NOT:                     ArraySet
+
+  // Test eliminating a load of the default value and a conditional store of an
+  // identical value in a loop with the array index being defined inside the loop.
+  static int testLoop20(TestClass obj, int n) {
+    // The NewArray is kept as it may throw for negative n.
+    // TODO: Eliminate constructor fence even though the NewArray is kept.
+    int[] a0 = new int[n];
+    for (int i = 0; i < n; ++i) {
+      obj.i = a0[i];
+      if ((i & 1) != 0) {
+        a0[i] = 0;  // Store the same value as default.
+      }
+    }
+    return n;
+  }
+
+  /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (before)
+  /// CHECK-NOT:                     Phi
+
+  /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK-NOT:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         Phi
+  /// CHECK-NOT:                     Phi
+
+  // Test load elimination when an instance field is used as the loop variable.
+  static int testLoop21(TestClass obj, int n) {
+    for (obj.i = 0; obj.i < n; ++obj.i) {
+      obj.j = 0;  // Use write side effects to stop GVN from eliminating the load below.
+      obj.j = obj.i;
+    }
+    return n;
+  }
+
+  /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (before)
+  /// CHECK-NOT:                     Phi
+
+  /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK-NOT:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         Phi
+  /// CHECK-NOT:                     Phi
+
+  // Test load and store elimination when an instance field is used as the loop
+  // variable and then overwritten after the loop.
+  static int testLoop22(TestClass obj, int n) {
+    for (obj.i = 0; obj.i < n; ++obj.i) {
+      obj.j = 0;  // Use write side effects to stop GVN from eliminating the load below.
+      obj.j = obj.i;
+    }
+    obj.i = 0;
+    return n;
+  }
+
+  /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK-NOT:                     InstanceFieldSet
+
+  // Test elimination of non-observable stores.
+  static int testLoop23(TestClass obj, int n) {
+    obj.i = -1;
+    int phi = -1;
+    for (int i = 0; i < n; ++i) {
+      obj.i = i;
+      phi = i;
+    }
+    if ((n & 1) != 0) {
+      obj.i = 2;
+      phi = 2;
+    }
+    obj.i = phi;  // This store shall be kept, the stores above shall be eliminated.
+    return phi;
+  }
+
+  /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+
+  /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK-NOT:                     InstanceFieldSet
+
+  // Test matching Phis for store elimination.
+  static int testLoop24(TestClass obj, int n) {
+    obj.i = -1;
+    int phi = -1;
+    for (int i = 0; i < n; ++i) {
+      obj.i = i;
+      phi = i;
+    }
+    if ((n & 1) != 0) {
+      obj.i = 2;
+      phi = 2;
+    }
+    if (n == 3) {
+      return -2;  // Make the above stores observable.
+    }
+    // As the stores above are observable and kept, we match the merged
+    // heap value with existing Phis and determine that we're storing
+    // the same value that's already there, so we eliminate this store.
+    obj.i = phi;
+    return phi;
+  }
+
+  /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  // Test that we do not match multiple dependent Phis for load and store elimination.
+  static int testLoop25(TestClass obj, int n) {
+    obj.i = 1;
+    int phi = 1;
+    for (int i = 0; i < n; ++i) {
+      if ((i & 1) != 0) {
+        obj.i = 2;
+        phi = 2;
+      }
+      // There is a Phi here for the variable `phi` before the "++i".
+      // This Phi and the loop Phi for `phi` depend on each other.
+    }
+    if (n == 3) {
+      return -1;  // Make above stores observable.
+    }
+    // We're not matching multiple Phi placeholders to existing Phis. Therefore the load
+    // below requires 2 extra Phis to be created and the store below shall not be eliminated
+    // even though it stores the same value that's already present in the heap location.
+    int tmp = obj.i;
+    obj.i = phi;
+    return tmp + phi;
+  }
+
+  /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldGet
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  // Test load elimination creating a reference Phi.
+  static int testLoop26(TestClass obj, int n) {
+    obj.next = new TestClass(1, 2);
+    for (int i = 0; i < n; ++i) {
+      obj.next = new SubTestClass();
+    }
+    return obj.next.i;
+  }
+
+  /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldGet
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     NewInstance
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldGet
+  /// CHECK-NOT:                     InstanceFieldGet
+
+  // Test load elimination creating two reference Phis that depend on each other.
+  static int testLoop27(TestClass obj, int n) {
+    obj.next = new TestClass(1, 2);
+    for (int i = 0; i < n; ++i) {
+      if ((i & 1) != 0) {
+        obj.next = new SubTestClass();
+      }
+      // There shall be a Phi created here for `obj.next` before the "++i".
+      // This Phi and the loop Phi that shall be created for `obj.next` depend on each other.
+    }
+    return obj.next.i;
+  }
+
+  /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArrayGet
+
+  /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 NewArray
+  /// CHECK-NOT:                 ArrayGet
+  /// CHECK-NOT:                 ArraySet
+
+  /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test eliminating array allocation, loads and stores and creating loop Phis
+  // after determining that a field load depending on loop Phi placeholder cannot
+  // be eliminated.
+  private static int testLoop28(TestClass obj, int n) {
+    obj.i = 1;
+    int[] a = new int[3];
+    for (int i = 0; i < n; ++i) {
+      a[0] = a[1];
+      a[1] = a[2];
+      a[2] = obj.i;
+      $noinline$clobberObservables();
+    }
+    return a[0];
+  }
+
+  /// CHECK-START: int Main.testLoop29(int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+
+  /// CHECK-START: int Main.testLoop29(int) load_store_elimination (after)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+
+  // Test that ArraySet with non-default value prevents matching ArrayGet for
+  // the same array to default value even when the ArraySet is using an index
+  // offset by one, making LSA declare that the two heap locations do not alias.
+  private static int testLoop29(int n) {
+    int[] a = new int[4];
+    int sum = 0;
+    for (int i = 0; i < n; ) {
+      int value = a[i] + 1;
+      sum += value;
+      ++i;
+      a[i] = value;
+    }
+    return sum;
+  }
+
+  /// CHECK-START: int Main.testLoop30(int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+
+  /// CHECK-START: int Main.testLoop30(int) load_store_elimination (after)
+  /// CHECK-NOT:                 ArrayGet
+  /// CHECK-NOT:                 ArraySet
+
+  // Test that ArraySet with default value does not prevent matching ArrayGet
+  // for the same array to the default value.
+  private static int testLoop30(int n) {
+    int[] a = new int[4];  // NewArray is kept due to environment use by Deoptimize.
+    int sum = 0;
+    for (int i = 0; i < n; ) {
+      int value = a[i] + 1;
+      sum += value;
+      ++i;
+      a[i] = 0;
+    }
+    return sum;
+  }
+
+  /// CHECK-START: int Main.testLoop31(int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+
+  /// CHECK-START: int Main.testLoop31(int) load_store_elimination (after)
+  /// CHECK-NOT:                 ArrayGet
+  /// CHECK-NOT:                 ArraySet
+
+  // Test that ArraySet with default value read from the array does not
+  // prevent matching ArrayGet for the same array to the default value.
+  private static int testLoop31(int n) {
+    int[] a = new int[4];  // NewArray is kept due to environment use by Deoptimize.
+    int sum = 0;
+    for (int i = 0; i < n; ) {
+      int value = a[i];
+      sum += value;
+      ++i;
+      a[i] = value;
+    }
+    return sum;
+  }
+
+  /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+
+  /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     Phi
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     InstanceFieldSet
+  /// CHECK-DAG:                     Phi
+
+  /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (after)
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK:                         InstanceFieldSet
+  /// CHECK-NOT:                     InstanceFieldSet
+
+  // Test matching Phis for store elimination.
+  static int testLoop32(TestClass obj, int n) {
+    obj.i = -1;
+    int phi = -1;
+    for (int i = 0; i < n; ) {
+      ++i;
+      if ((i & 1) != 0) {
+        obj.i = i;
+        phi = i;
+      }
+    }
+    if ((n & 1) != 0) {
+      obj.i = 2;
+      phi = 2;
+    }
+    if (n == 3) {
+      return -2;  // Make the above stores observable.
+    }
+    // As the stores above are observable and kept, we match the merged
+    // heap value with existing Phis and determine that we're storing
+    // the same value that's already there, so we eliminate this store.
+    obj.i = phi;
+    return phi;
+  }
+
+  // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (before)
+  // CHECK-DAG:                     InstanceFieldSet
+  // CHECK-DAG:                     NewArray
+  // CHECK-DAG:                     Phi
+  // CHECK-DAG:                     ArrayGet
+  // CHECK-DAG:                     InstanceFieldSet
+  // CHECK-DAG:                     Phi
+  // CHECK-DAG:                     ArrayGet
+  // CHECK-DAG:                     InstanceFieldGet
+  // CHECK-DAG:                     InstanceFieldSet
+  // CHECK-DAG:                     InstanceFieldGet
+
+  // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (after)
+  // CHECK-DAG:                     InstanceFieldSet
+  // CHECK-DAG:                     Phi
+  // CHECK-DAG:                     InstanceFieldSet
+  // CHECK-DAG:                     Phi
+  // CHECK-DAG:                     InstanceFieldGet
+  // CHECK-DAG:                     InstanceFieldSet
+  // CHECK-DAG:                     InstanceFieldGet
+
+  // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (after)
+  // CHECK-NOT:                     ArrayGet
+
+  // Test that when processing Phi placeholder with unknown input, we allow materialized
+  // default value in pre-header for array location with index defined in the loop.
+  static int testLoop33(TestClass obj, int n) {
+    obj.i = 0;
+    int[] a0 = new int[n];
+    for (int i = 0; i < n; ++i) {
+      obj.i = a0[i];
+      $noinline$clobberObservables();  // Make `obj.i` unknown.
+    }
+    for (int i = 0; i < n; ++i) {
+      int zero = a0[i];
+      int unknown = obj.i;
+      obj.j += zero + unknown;
+    }
+    return obj.j;
+  }
+
+  /// CHECK-START: int Main.testLoop34(int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+
+  /// CHECK-START: int Main.testLoop34(int) load_store_elimination (after)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+
+  // Test that ArraySet with non-default value prevents matching ArrayGet for
+  // the same array to default value even when the ArraySet is using an index
+  // offset by one, making LSA declare that the two heap locations do not alias.
+  // Also test that the ArraySet is not eliminated.
+  private static int testLoop34(int n) {
+    int[] a = new int[n + 1];
+    int sum = 0;
+    for (int i = 0; i < n; ) {
+      int value = a[i] + 1;
+      sum += value;
+      ++i;
+      a[i] = value;
+    }
+    return sum;
+  }
+
+  /// CHECK-START: int Main.testLoop35(int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArraySet
+
+  /// CHECK-START: int Main.testLoop35(int) load_store_elimination (after)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+
+  /// CHECK-START: int Main.testLoop35(int) load_store_elimination (after)
+  /// CHECK:                     ArraySet
+  /// CHECK-NOT:                 ArraySet
+
+  // Test that ArraySet with non-default value prevents matching ArrayGet for
+  // the same array to default value even when the ArraySet is using an index
+  // offset by one, making LSA declare that the two heap locations do not alias.
+  // Also test that the ArraySet is not eliminated and that a store after the
+  // loop is eliminated.
+  private static int testLoop35(int n) {
+    int[] a = new int[n + 1];
+    int sum = 0;
+    for (int i = 0; i < n; ) {
+      int value = a[i] + 1;
+      sum += value;
+      ++i;
+      a[i] = value;
+    }
+    a[0] = 1;
+    return sum;
+  }
+
+  /// CHECK-START: int Main.testLoop36(int) load_store_elimination (before)
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 Deoptimize
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+
+  /// CHECK-START: int Main.testLoop36(int) load_store_elimination (before)
+  /// CHECK-NOT:                 BoundsCheck
+
+  /// CHECK-START: int Main.testLoop36(int) load_store_elimination (after)
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 Deoptimize
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+
+  // Regression test for b/187487955.
+  // We previously failed a DCHECK() during the search for kept stores when
+  // we encountered two array locations for the same array and considered
+  // non-aliasing by LSA when only one of the array locations had index
+  // defined inside the loop. Note that this situation requires that BCE
+  // eliminates BoundsCheck instructions, otherwise LSA considers those
+  // locations aliasing.
+  private static int testLoop36(int n) {
+    int[] a = new int[n];
+    int zero = 0;
+    int i = 0;
+    for (; i < n; ++i) {
+      a[i] = i;
+      // Extra instructions to avoid loop unrolling.
+      zero = (((zero ^ 1) + 2) ^ 1) - 2;
+      zero = (((zero ^ 4) + 8) ^ 4) - 8;
+    }
+    // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`.
+    // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are
+    // the Phi plus/minus a constant, something that LSA considers non-aliasing
+    // with the Phi (LSA does not take different loop iterations into account)
+    // but LSE must consider aliasing across dfferent loop iterations.
+    return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero;
+  }
+
+  /// CHECK-START: int Main.testLoop37(int) load_store_elimination (before)
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 Deoptimize
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+
+  /// CHECK-START: int Main.testLoop37(int) load_store_elimination (before)
+  /// CHECK-NOT:                 BoundsCheck
+
+  /// CHECK-START: int Main.testLoop37(int) load_store_elimination (after)
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 Deoptimize
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+
+  // Similar to testLoop36 but the writes are done via a different reference to the same array.
+  // We previously used a reference comparison for back-edge aliasing analysis but this test
+  // has different references and therefore needs `HeapLocationCollector::CanReferencesAlias()`.
+  private static int testLoop37(int n) {
+    int[] a = new int[n];
+    int[] b = $noinline$returnArg(a);
+    int zero = 0;
+    int i = 0;
+    for (; i < n; ++i) {
+      b[i] = i;
+      // Extra instructions to avoid loop unrolling.
+      zero = (((zero ^ 1) + 2) ^ 1) - 2;
+      zero = (((zero ^ 4) + 8) ^ 4) - 8;
+    }
+    // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`.
+    // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are
+    // the Phi plus/minus a constant, something that LSA considers non-aliasing
+    // with the Phi (LSA does not take different loop iterations into account)
+    // but LSE must consider aliasing across dfferent loop iterations.
+    return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero;
+  }
+
+  private static int[] $noinline$returnArg(int[] a) {
+    return a;
+  }
+
+  /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (before)
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 Deoptimize
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+
+  /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (before)
+  /// CHECK-NOT:                 BoundsCheck
+
+  /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (after)
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 Deoptimize
+
+  /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (after)
+  /// CHECK-NOT:                 ArrayGet
+
+  // Similar to testLoop37 but writing to a different array that exists before allocating `a`,
+  // so that `HeapLocationCollector::CanReferencesAlias()` returns false and all the ArrayGet
+  // instructions are actually eliminated.
+  private static int testLoop38(int n, int[] b) {
+    int[] a = new int[n];
+    int zero = 0;
+    int i = 0;
+    for (; i < n; ++i) {
+      b[i] = i;
+      // Extra instructions to avoid loop unrolling.
+      zero = (((zero ^ 1) + 2) ^ 1) - 2;
+      zero = (((zero ^ 4) + 8) ^ 4) - 8;
+    }
+    // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`.
+    // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are
+    // the Phi plus/minus a constant, something that LSA considers non-aliasing
+    // with the Phi (LSA does not take different loop iterations into account)
+    // but LSE must consider aliasing across dfferent loop iterations.
+    return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero;
+  }
+
+  /// CHECK-START: int Main.testNestedLoop1(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop1(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  // Test heap value clobbering in nested loop.
+  private static int testNestedLoop1(TestClass obj, int n) {
+    obj.i = 1;
+    for (int i = 0; i < n; ++i) {
+      for (int j = i + 1; j < n; ++j) {
+        $noinline$clobberObservables();
+      }
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldGet
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test heap value clobbering in the nested loop and load elimination for a heap
+  // location then set to known value before the end of the outer loop.
+  private static int testNestedLoop2(TestClass obj, int n) {
+    obj.i = 1;
+    obj.j = 2;
+    for (int i = 0; i < n; ++i) {
+      int tmp = obj.j;
+      for (int j = i + 1; j < n; ++j) {
+        $noinline$clobberObservables();
+      }
+      obj.i = tmp;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldGet
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test heap value clobbering in the nested loop and load elimination for a heap
+  // location then set to known value before the end of the outer loop.
+  private static int testNestedLoop3(TestClass obj, int n) {
+    obj.i = 1;
+    for (int i = 0; i < n; ++i) {
+      obj.j = 2;
+      for (int j = i + 1; j < n; ++j) {
+        $noinline$clobberObservables();
+      }
+      obj.i = obj.j;
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test creating loop Phis for both inner and outer loop to eliminate a load.
+  private static int testNestedLoop4(TestClass obj, int n) {
+    obj.i = 1;
+    for (int i = 0; i < n; ++i) {
+      for (int j = i + 1; j < n; ++j) {
+        obj.i = 2;
+      }
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test creating a loop Phi for outer loop to eliminate a load.
+  private static int testNestedLoop5(TestClass obj, int n) {
+    obj.i = 1;
+    for (int i = 0; i < n; ++i) {
+      obj.i = 2;
+      for (int j = i + 1; j < n; ++j) {
+        obj.j = 3;  // Unrelated.
+      }
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldGet
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK:                     Phi
+  /// CHECK-NOT:                 Phi
+
+  // Test heap value clobbering in the nested loop and load elimination for a heap
+  // location then set to known value before the end of that inner loop.
+  private static int testNestedLoop6(TestClass obj, int n) {
+    obj.i = 1;
+    obj.j = 2;
+    for (int i = 0; i < n; ++i) {
+      for (int j = i + 1; j < n; ++j) {
+        int tmp = obj.j;
+        $noinline$clobberObservables();
+        obj.i = tmp;
+      }
+    }
+    return obj.i;
+  }
+
+  /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 InstanceFieldSet
+
+  /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (after)
+  /// CHECK-NOT:                 ArrayGet
+
+  // Test load elimination in inner loop reading default value that is loop invariant
+  // with an index defined inside the inner loop.
+  private static int testNestedLoop7(TestClass obj, int n) {
+    // The NewArray is kept as it may throw for negative n.
+    // TODO: Eliminate constructor fence even though the NewArray is kept.
+    int[] a0 = new int[n];
+    for (int i = 0; i < n; ++i) {
+      for (int j = i + 1; j < n; ++j) {
+        obj.i = a0[j];
+      }
+    }
+    return n;
+  }
+
+  /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewInstance
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 NewInstance
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (after)
+  /// CHECK-DAG:                 NewInstance
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 Phi
+  /// CHECK-DAG:                 NewInstance
+  /// CHECK-DAG:                 InstanceFieldSet
+  /// CHECK-DAG:                 InstanceFieldGet
+
+  /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (after)
+  /// CHECK:                     InstanceFieldGet
+  /// CHECK-NOT:                 InstanceFieldGet
+
+  // Test reference type propagation for Phis created for outer and inner loop.
+  private static int testNestedLoop8(TestClass obj, int n) {
+    obj.next = new SubTestClass();
+    for (int i = 0; i < n; ++i) {
+      for (int j = i + 1; j < n; ++j) {
+        obj.next = new TestClass();
+      }
+    }
+    // The Phis created in both loop headers for replacing `obj.next` depend on each other.
+    return obj.next.i;
+  }
+
+
+  /// CHECK-START: long Main.testOverlapLoop(int) load_store_elimination (before)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 If
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 Goto
+
+  /// CHECK-START: long Main.testOverlapLoop(int) load_store_elimination (after)
+  /// CHECK-DAG:                 NewArray
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 If
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArrayGet
+  /// CHECK-DAG:                 ArraySet
+  /// CHECK-DAG:                 Goto
+  /// CHECK-NOT:                 ArrayGet
+
+  // Test that we don't incorrectly remove writes needed by later loop iterations
+  // NB This is fibonacci numbers
+  private static long testOverlapLoop(int cnt) {
+    long[] w = new long[cnt];
+    w[1] = 1;
+    long t = 1;
+    for (int i = 2; i < cnt; ++i) {
+      w[i] = w[i - 1] + w[i - 2];
+      t = w[i];
+    }
+    return t;
+  }
+
+  private static boolean $noinline$getBoolean(boolean val) {
+    return val;
+  }
+
+  /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (before)
+  /// CHECK-DAG:     ParameterValue
+  /// CHECK-DAG:     NewInstance
+  /// CHECK-DAG:     InvokeStaticOrDirect
+  /// CHECK-DAG:     InstanceFieldSet
+  /// CHECK-DAG:     InvokeStaticOrDirect
+  /// CHECK-DAG:     InstanceFieldGet
+  /// CHECK-DAG:     InstanceFieldGet
+  /// CHECK-DAG:     InstanceFieldSet
+  /// CHECK-DAG:     InstanceFieldGet
+  /// CHECK-DAG:     InstanceFieldGet
+  /// CHECK-DAG:     Phi
+  //
+  /// CHECK-NOT:     NewInstance
+  /// CHECK-NOT:     InvokeStaticOrDirect
+  /// CHECK-NOT:     InstanceFieldSet
+  /// CHECK-NOT:     InstanceFieldGet
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-DAG:     ParameterValue
+  /// CHECK-DAG:     NewInstance
+  /// CHECK-DAG:     Phi
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:         InvokeStaticOrDirect
+  /// CHECK:         InvokeStaticOrDirect
+  //
+  /// CHECK-NOT:     InvokeStaticOrDirect
+
+  /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldSet
+  //
+  /// CHECK-NOT:     InstanceFieldSet
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldGet
+  /// CHECK:         InstanceFieldGet
+  /// CHECK:         InstanceFieldGet
+  //
+  /// CHECK-NOT:     InstanceFieldGet
+  private static int $noinline$testPartialEscape1(TestClass obj, boolean escape) {
+    TestClass i = new SubTestClass();
+    int res;
+    if ($noinline$getBoolean(escape)) {
+      i.next = obj;
+      $noinline$Escape(i);
+      res = i.next.i;
+    } else {
+      i.next = obj;
+      res = i.next.i;
+    }
+    return res;
+  }
+
+  /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (before)
+  /// CHECK-DAG:     ParameterValue
+  /// CHECK-DAG:     NewInstance
+  /// CHECK-DAG:     InvokeStaticOrDirect
+  /// CHECK-DAG:     InvokeStaticOrDirect
+  /// CHECK-DAG:     InvokeStaticOrDirect
+  /// CHECK-DAG:     InstanceFieldSet
+  /// CHECK-DAG:     InstanceFieldSet
+  /// CHECK-DAG:     InstanceFieldSet
+  /// CHECK-DAG:     InstanceFieldGet
+  /// CHECK-DAG:     InstanceFieldGet
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
+  /// CHECK-DAG:     ParameterValue
+  /// CHECK-DAG:     NewInstance
+  /// CHECK-DAG:     Phi
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:         InvokeStaticOrDirect
+  /// CHECK:         InvokeStaticOrDirect
+  /// CHECK:         InvokeStaticOrDirect
+  //
+  /// CHECK-NOT:     InvokeStaticOrDirect
+
+  /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldSet predicated:false
+  /// CHECK-NOT:     InstanceFieldSet predicated:false
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldSet predicated:true
+  /// CHECK-NOT:     InstanceFieldSet predicated:true
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldGet
+  //
+  /// CHECK-NOT:     InstanceFieldGet
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
+  /// CHECK:         PredicatedInstanceFieldGet
+  //
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  private static int $noinline$testPartialEscape2(TestClass obj, boolean escape) {
+    TestClass i = new SubTestClass();
+    if ($noinline$getBoolean(escape)) {
+      i.next = obj;
+      $noinline$Escape(i);
+    } else {
+      i.next = obj;
+    }
+    $noinline$clobberObservables();
+    // Predicated-get
+    TestClass res = i.next;
+    // Predicated-set
+    i.next = null;
+    return res.i;
+  }
+
+  /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (before)
+  /// CHECK-NOT:     Phi
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  //
+  /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (after)
+  /// CHECK:         Phi
+  /// CHECK:         Phi
+  /// CHECK-NOT:     Phi
+  //
+  /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldSet predicated:true
+  /// CHECK-NOT:     InstanceFieldSet predicated:true
+  //
+  /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (after)
+  /// CHECK:         PredicatedInstanceFieldGet
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  private static float $noinline$testPartialEscape3_float(boolean escape) {
+    TestClass4 tc = new TestClass4();
+    if ($noinline$getBoolean(escape)) {
+      $noinline$Escape4(tc);
+    } else {
+      tc.floatField -= 1f;
+    }
+    // Partial escape
+    $noinline$clobberObservables();
+    // Predicated set
+    tc.floatField *= 10;
+    // Predicated get
+    return tc.floatField;
+  }
+
+  /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (before)
+  /// CHECK-NOT:     Phi
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  //
+  /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (after)
+  /// CHECK:         Phi
+  /// CHECK:         Phi
+  /// CHECK-NOT:     Phi
+  //
+  /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldSet predicated:true
+  /// CHECK-NOT:     InstanceFieldSet predicated:true
+  //
+  /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (after)
+  /// CHECK:         PredicatedInstanceFieldGet
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  private static double $noinline$testPartialEscape3_double(boolean escape) {
+    TestClass4 tc = new TestClass4();
+    if ($noinline$getBoolean(escape)) {
+      $noinline$Escape4(tc);
+    } else {
+      tc.doubleField -= 1d;
+    }
+    // Partial escape
+    $noinline$clobberObservables();
+    // Predicated set
+    tc.doubleField *= 10;
+    // Predicated get
+    return tc.doubleField;
+  }
+
+  /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (before)
+  /// CHECK-NOT:     Phi
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  //
+  /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (after)
+  /// CHECK:         Phi
+  /// CHECK:         Phi
+  /// CHECK-NOT:     Phi
+  //
+  /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldSet predicated:true
+  /// CHECK-NOT:     InstanceFieldSet predicated:true
+  //
+  /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (after)
+  /// CHECK:         PredicatedInstanceFieldGet
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  private static short $noinline$testPartialEscape3_short(boolean escape) {
+    TestClass4 tc = new TestClass4();
+    if ($noinline$getBoolean(escape)) {
+      $noinline$Escape4(tc);
+    } else {
+      tc.shortField -= 1;
+    }
+    // Partial escape
+    $noinline$clobberObservables();
+    // Predicated set
+    tc.shortField *= 10;
+    // Predicated get
+    return tc.shortField;
+  }
+
+  /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (before)
+  /// CHECK-NOT:     Phi
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  //
+  /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (after)
+  /// CHECK:         Phi
+  /// CHECK:         Phi
+  /// CHECK-NOT:     Phi
+  //
+  /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldSet predicated:true
+  /// CHECK-NOT:     InstanceFieldSet predicated:true
+  //
+  /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (after)
+  /// CHECK:         PredicatedInstanceFieldGet
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  private static byte $noinline$testPartialEscape3_byte(boolean escape) {
+    TestClass4 tc = new TestClass4();
+    if ($noinline$getBoolean(escape)) {
+      $noinline$Escape4(tc);
+    } else {
+      tc.byteField -= 1;
+    }
+    // Partial escape
+    $noinline$clobberObservables();
+    // Predicated set
+    tc.byteField *= 10;
+    // Predicated get
+    return tc.byteField;
+  }
+
+  /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (before)
+  /// CHECK-NOT:     Phi
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (after)
+  /// CHECK:         Phi
+  /// CHECK:         Phi
+  /// CHECK-NOT:     Phi
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldSet predicated:true
+  /// CHECK-NOT:     InstanceFieldSet predicated:true
+  //
+  /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (after)
+  /// CHECK:         PredicatedInstanceFieldGet
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  private static int $noinline$testPartialEscape3_int(boolean escape) {
+    TestClass4 tc = new TestClass4();
+    if ($noinline$getBoolean(escape)) {
+      $noinline$Escape4(tc);
+    } else {
+      tc.intField -= 1;
+    }
+    // Partial escape
+    $noinline$clobberObservables();
+    // Predicated set
+    tc.intField *= 10;
+    // Predicated get
+    return tc.intField;
+  }
+
+  /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (before)
+  /// CHECK-NOT:     Phi
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  //
+  /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (after)
+  /// CHECK:         Phi
+  /// CHECK:         Phi
+  /// CHECK-NOT:     Phi
+  //
+  /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (after)
+  /// CHECK:         InstanceFieldSet predicated:true
+  /// CHECK-NOT:     InstanceFieldSet predicated:true
+  //
+  /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (after)
+  /// CHECK:         PredicatedInstanceFieldGet
+  /// CHECK-NOT:     PredicatedInstanceFieldGet
+  private static long $noinline$testPartialEscape3_long(boolean escape) {
+    TestClass4 tc = new TestClass4();
+    if ($noinline$getBoolean(escape)) {
+      $noinline$Escape4(tc);
+    } else {
+      tc.longField -= 1;
+    }
+    // Partial escape
+    $noinline$clobberObservables();
+    // Predicated set
+    tc.longField *= 10;
+    // Predicated get
+    return tc.longField;
+  }
+
+  private static void $noinline$clobberObservables() {}
+
+  static void assertLongEquals(long result, long expected) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
   static void assertIntEquals(int result, int expected) {
     if (expected != result) {
       throw new Error("Expected: " + expected + ", found: " + result);
@@ -1153,15 +4233,7 @@
     }
   }
 
-  public static void main(String[] args) throws Exception {
-
-    Class main2 = Class.forName("Main2");
-    Method test4 = main2.getMethod("test4", TestClass.class, boolean.class);
-    Method test5 = main2.getMethod("test5", TestClass.class, boolean.class);
-    Method test10 = main2.getMethod("test10", TestClass.class);
-    Method test23 = main2.getMethod("test23", boolean.class);
-    Method test24 = main2.getMethod("test24");
-
+  public static void main(String[] args) {
     assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI));
     assertIntEquals(test1(new TestClass(), new TestClass()), 3);
     assertIntEquals(test2(new TestClass()), 1);
@@ -1169,10 +4241,10 @@
     TestClass obj2 = new TestClass();
     obj1.next = obj2;
     assertIntEquals(test3(obj1), 10);
-    assertIntEquals((int)test4.invoke(null, new TestClass(), true), 1);
-    assertIntEquals((int)test4.invoke(null, new TestClass(), false), 1);
-    assertIntEquals((int)test5.invoke(null, new TestClass(), true), 1);
-    assertIntEquals((int)test5.invoke(null, new TestClass(), false), 2);
+    assertIntEquals(test4(new TestClass(), true), 1);
+    assertIntEquals(test4(new TestClass(), false), 1);
+    assertIntEquals(test5(new TestClass(), true), 1);
+    assertIntEquals(test5(new TestClass(), false), 2);
     assertIntEquals(test6(new TestClass(), new TestClass(), true), 4);
     assertIntEquals(test6(new TestClass(), new TestClass(), false), 2);
     assertIntEquals(test7(new TestClass()), 1);
@@ -1181,7 +4253,7 @@
     obj2 = new TestClass();
     obj1.next = obj2;
     assertIntEquals(test9(new TestClass()), 1);
-    assertIntEquals((int)test10.invoke(null, new TestClass(3, 4)), 3);
+    assertIntEquals(test10(new TestClass(3, 4)), 3);
     assertIntEquals(TestClass.si, 3);
     assertIntEquals(test11(new TestClass()), 10);
     assertIntEquals(test12(new TestClass(), new TestClass()), 10);
@@ -1198,9 +4270,44 @@
     assertFloatEquals(test20().i, 0);
     test21(new TestClass());
     assertIntEquals(test22(), 13);
-    assertIntEquals((int)test23.invoke(null, true), 4);
-    assertIntEquals((int)test23.invoke(null, false), 5);
-    assertFloatEquals((float)test24.invoke(null), 8.0f);
+    assertIntEquals(test23(true), 4);
+    assertIntEquals(test23(false), 5);
+    assertFloatEquals(test24(), 8.0f);
+    assertIntEquals(test25(false, true, true), 5);
+    assertIntEquals(test25(true, false, true), 2);
+    assertFloatEquals(test26(5), 0.0f);
+    assertFloatEquals(test26(3), 1.0f);
+    assertIntEquals(test27(false, true), 1);
+    assertIntEquals(test27(true, false), 1);
+    assertIntEquals(test28(false, true), 0);
+    assertIntEquals(test28(true, true), 5);
+    assertFloatEquals(test29(true), 5.0f);
+    assertFloatEquals(test29(false), 2.0f);
+    assertIntEquals(test30(new TestClass(), true), 1);
+    assertIntEquals(test30(new TestClass(), false), 0);
+    assertIntEquals(test31(true, true), 5);
+    assertIntEquals(test31(true, false), 6);
+    assertIntEquals(test32(1), 10);
+    assertIntEquals(test32(2), 10);
+    assertIntEquals(test33(new TestClass(), true), 1);
+    assertIntEquals(test33(new TestClass(), false), 2);
+    assertIntEquals(test34(new TestClass(), true, true), 3);
+    assertIntEquals(test34(new TestClass(), false, true), 4);
+    assertIntEquals(test34(new TestClass(), true, false), 1);
+    assertIntEquals(test34(new TestClass(), false, false), 2);
+    assertIntEquals(test35(new TestClass(), true, true), 3);
+    assertIntEquals(test35(new TestClass(), false, true), 2);
+    assertIntEquals(test35(new TestClass(), true, false), 1);
+    assertIntEquals(test35(new TestClass(), false, false), 2);
+    assertIntEquals(test36(new TestClass(), true), 2);
+    assertIntEquals(test36(new TestClass(), false), 4);
+    assertIntEquals(test37(new TestClass(), true), 1);
+    assertIntEquals(test37(new TestClass(), false), 0);
+    assertIntEquals(test38(new TestClass(), true), 1);
+    assertIntEquals(test38(new TestClass(), false), 2);
+    assertIntEquals(test39(new TestClass(), true), 0);
+    assertIntEquals(test39(new TestClass(), false), 1);
+
     testFinalizableByForcingGc();
     assertIntEquals($noinline$testHSelect(true), 0xdead);
     int[] array = {2, 5, 9, -1, -3, 10, 8, 4};
@@ -1210,12 +4317,25 @@
     assertDoubleEquals(Math.PI * Math.PI * Math.PI, getCircleArea(Math.PI, true));
     assertDoubleEquals(0d, getCircleArea(Math.PI, false));
 
+    assertIntEquals($noinline$testConversion1(new TestClass(), 300), 300);
+    assertIntEquals($noinline$testConversion1(new TestClass(), 301), 45);
+    assertIntEquals($noinline$testConversion2(new TestClass(), 300), 300);
+    assertIntEquals($noinline$testConversion2(new TestClass(), 301), 90);
+    assertIntEquals($noinline$testConversion3(new TestClass(), 0), 0);
+    assertIntEquals($noinline$testConversion3(new TestClass(), 1), 0);
+    assertIntEquals($noinline$testConversion3(new TestClass(), 128), 127);
+    assertIntEquals($noinline$testConversion3(new TestClass(), 129), -128);
+    assertIntEquals($noinline$testConversion4(new TestClass(), 0), 0);
+    assertIntEquals($noinline$testConversion4(new TestClass(), 1), 0);
+    assertIntEquals($noinline$testConversion4(new TestClass(), 128), 254);
+    assertIntEquals($noinline$testConversion4(new TestClass(), 129), -256);
+
     int[] iarray = {0, 0, 0};
     double[] darray = {0d, 0d, 0d};
     try {
       assertDoubleEquals(Math.PI * Math.PI * Math.PI, testDeoptimize(iarray, darray, Math.PI));
     } catch (Exception e) {
-      System.out.println(e);
+      System.out.println(e.getClass().getName());
     }
     assertIntEquals(iarray[0], 1);
     assertIntEquals(iarray[1], 1);
@@ -1278,6 +4398,8 @@
 
     assertIntEquals(testStoreStoreWithDeoptimize(new int[4]), 4);
 
+    assertIntEquals($noinline$testByteArrayDefaultValue(), 0);
+
     assertIntEquals(testLocalArrayMerge1(true), 1);
     assertIntEquals(testLocalArrayMerge1(false), 1);
     assertIntEquals(testLocalArrayMerge2(true), 2);
@@ -1286,7 +4408,224 @@
     assertIntEquals(testLocalArrayMerge3(false), 1);
     assertIntEquals(testLocalArrayMerge4(true), 2);
     assertIntEquals(testLocalArrayMerge4(false), 2);
-  }
+    assertIntEquals(testLocalArrayMerge5(new int[]{ 7 }, true), 7);
+    assertIntEquals(testLocalArrayMerge5(new int[]{ 9 }, false), 9);
+    assertIntEquals(testLocalArrayMerge6(new int[1], true, true), 1);
+    assertIntEquals(testLocalArrayMerge6(new int[1], true, false), 2);
+    assertIntEquals(testLocalArrayMerge6(new int[1], false, true), 2);
+    assertIntEquals(testLocalArrayMerge6(new int[1], false, false), 1);
+    assertIntEquals(testLocalArrayMerge7(new int[2], true, true), 1);
+    assertIntEquals(testLocalArrayMerge7(new int[2], true, false), 2);
+    assertIntEquals(testLocalArrayMerge7(new int[2], false, true), 0);
+    assertIntEquals(testLocalArrayMerge7(new int[2], false, false), 0);
+    assertIntEquals(testLocalArrayMerge8(true), 0);
+    assertIntEquals(testLocalArrayMerge8(false), 0);
 
-  static boolean sFlag;
+    TestClass[] tca = new TestClass[] { new TestClass(), null };
+    try {
+      $noinline$testThrowingArraySet(tca, new TestClass2());
+    } catch (ArrayStoreException expected) {
+      if (tca[0] != null) {
+        throw new Error("tca[0] is not null");
+      }
+      if (tca[1] == null) {
+        throw new Error("tca[1] is null");
+      }
+    }
+
+    assertIntEquals(testLoop1(new TestClass(), 0), 0);
+    assertIntEquals(testLoop1(new TestClass(), 1), 0);
+    assertIntEquals(testLoop1(new TestClass(), 2), 1);
+    assertIntEquals(testLoop1(new TestClass(), 3), 2);
+    assertIntEquals(testLoop2(new TestClass(), 0), 1);
+    assertIntEquals(testLoop2(new TestClass(), 1), 1);
+    assertIntEquals(testLoop2(new TestClass(), 2), 1);
+    assertIntEquals(testLoop2(new TestClass(), 3), 1);
+    assertIntEquals(testLoop3(new TestClass(), 0), 1);
+    assertIntEquals(testLoop3(new TestClass(), 1), 1);
+    assertIntEquals(testLoop3(new TestClass(), 2), 1);
+    assertIntEquals(testLoop3(new TestClass(), 3), 1);
+    assertIntEquals(testLoop4(new TestClass(), 0), 0);
+    assertIntEquals(testLoop4(new TestClass(), 1), 1);
+    assertIntEquals(testLoop4(new TestClass(), 2), 2);
+    assertIntEquals(testLoop4(new TestClass(), 3), 3);
+    assertIntEquals(testLoop5(new TestClass(), 0), 0);
+    assertIntEquals(testLoop5(new TestClass(), 1), 1);
+    assertIntEquals(testLoop5(new TestClass(), 2), 2);
+    assertIntEquals(testLoop5(new TestClass(), 3), 3);
+    assertIntEquals(testLoop6(new TestClass(), 0), 0);
+    assertIntEquals(testLoop6(new TestClass(), 1), 1);
+    assertIntEquals(testLoop6(new TestClass(), 2), 2);
+    assertIntEquals(testLoop6(new TestClass(), 3), 3);
+    assertIntEquals(testLoop7(0), 0);
+    assertIntEquals(testLoop7(1), 0);
+    assertIntEquals(testLoop7(2), 0);
+    assertIntEquals(testLoop7(3), 0);
+    assertIntEquals(testLoop8(0), 1);
+    assertIntEquals(testLoop8(1), 0);
+    assertIntEquals(testLoop8(2), 1);
+    assertIntEquals(testLoop8(3), 0);
+    assertIntEquals(testLoop9(new TestClass(), 0), 0);
+    assertIntEquals(testLoop9(new TestClass(), 1), 1);
+    assertIntEquals(testLoop9(new TestClass(), 2), 2);
+    assertIntEquals(testLoop9(new TestClass(), 3), 3);
+    assertIntEquals(testLoop10(new TestClass(), 0), 2);
+    assertIntEquals(testLoop10(new TestClass(), 1), 2);
+    assertIntEquals(testLoop10(new TestClass(), 2), 2);
+    assertIntEquals(testLoop10(new TestClass(), 3), 2);
+    assertIntEquals(testLoop11(new TestClass(), 0), 1);
+    assertIntEquals(testLoop11(new TestClass(), 1), 3);
+    assertIntEquals(testLoop11(new TestClass(), 2), 2);
+    assertIntEquals(testLoop11(new TestClass(), 3), 3);
+    assertIntEquals(testLoop12(new TestClass(), 0), 1);
+    assertIntEquals(testLoop12(new TestClass(), 1), 2);
+    assertIntEquals(testLoop12(new TestClass(), 2), 3);
+    assertIntEquals(testLoop12(new TestClass(), 3), 2);
+    assertIntEquals(testLoop13(new TestClass(1, 2), 0), 0);
+    assertIntEquals(testLoop13(new TestClass(1, 2), 1), 0);
+    assertIntEquals(testLoop13(new TestClass(1, 2), 2), 0);
+    assertIntEquals(testLoop13(new TestClass(1, 2), 3), 1);
+    assertIntEquals(testLoop14(new TestClass2(), 0), 0);
+    assertIntEquals(testLoop14(new TestClass2(), 1), 0);
+    assertIntEquals(testLoop14(new TestClass2(), 2), 0);
+    assertIntEquals(testLoop14(new TestClass2(), 3), 1);
+    assertIntEquals(testLoop15(0), 0);
+    assertIntEquals(testLoop15(1), 1);
+    assertIntEquals(testLoop15(2), 1);
+    assertIntEquals(testLoop15(3), 1);
+    assertIntEquals(testLoop16(new TestClass(), 0), 0);
+    assertIntEquals(testLoop16(new TestClass(), 1), 1);
+    assertIntEquals(testLoop16(new TestClass(), 2), 2);
+    assertIntEquals(testLoop16(new TestClass(), 3), 3);
+    assertIntEquals(testLoop17(new TestClass(), 0), 2);
+    assertIntEquals(testLoop17(new TestClass(), 1), 4);
+    assertIntEquals(testLoop17(new TestClass(), 2), 2);
+    assertIntEquals(testLoop17(new TestClass(), 3), 4);
+    assertIntEquals(testLoop18(new TestClass(), 0), 0);
+    assertIntEquals(testLoop18(new TestClass(), 1), 1);
+    assertIntEquals(testLoop18(new TestClass(), 2), 2);
+    assertIntEquals(testLoop18(new TestClass(), 3), 3);
+    assertIntEquals(testLoop19(new TestClass(), 0), 0);
+    assertIntEquals(testLoop19(new TestClass(), 1), 1);
+    assertIntEquals(testLoop19(new TestClass(), 2), 2);
+    assertIntEquals(testLoop19(new TestClass(), 3), 3);
+    assertIntEquals(testLoop20(new TestClass(), 0), 0);
+    assertIntEquals(testLoop20(new TestClass(), 1), 1);
+    assertIntEquals(testLoop20(new TestClass(), 2), 2);
+    assertIntEquals(testLoop20(new TestClass(), 3), 3);
+    assertIntEquals(testLoop21(new TestClass(), 0), 0);
+    assertIntEquals(testLoop21(new TestClass(), 1), 1);
+    assertIntEquals(testLoop21(new TestClass(), 2), 2);
+    assertIntEquals(testLoop21(new TestClass(), 3), 3);
+    assertIntEquals(testLoop22(new TestClass(), 0), 0);
+    assertIntEquals(testLoop22(new TestClass(), 1), 1);
+    assertIntEquals(testLoop22(new TestClass(), 2), 2);
+    assertIntEquals(testLoop22(new TestClass(), 3), 3);
+    assertIntEquals(testLoop23(new TestClass(), 0), -1);
+    assertIntEquals(testLoop23(new TestClass(), 1), 2);
+    assertIntEquals(testLoop23(new TestClass(), 2), 1);
+    assertIntEquals(testLoop23(new TestClass(), 3), 2);
+    assertIntEquals(testLoop24(new TestClass(), 0), -1);
+    assertIntEquals(testLoop24(new TestClass(), 1), 2);
+    assertIntEquals(testLoop24(new TestClass(), 2), 1);
+    assertIntEquals(testLoop24(new TestClass(), 3), -2);
+    assertIntEquals(testLoop25(new TestClass(), 0), 2);
+    assertIntEquals(testLoop25(new TestClass(), 1), 2);
+    assertIntEquals(testLoop25(new TestClass(), 2), 4);
+    assertIntEquals(testLoop25(new TestClass(), 3), -1);
+    assertIntEquals(testLoop26(new TestClass(), 0), 1);
+    assertIntEquals(testLoop26(new TestClass(), 1), 0);
+    assertIntEquals(testLoop26(new TestClass(), 2), 0);
+    assertIntEquals(testLoop26(new TestClass(), 3), 0);
+    assertIntEquals(testLoop27(new TestClass(), 0), 1);
+    assertIntEquals(testLoop27(new TestClass(), 1), 1);
+    assertIntEquals(testLoop27(new TestClass(), 2), 0);
+    assertIntEquals(testLoop27(new TestClass(), 3), 0);
+    assertIntEquals(testLoop28(new TestClass(1, 2), 0), 0);
+    assertIntEquals(testLoop28(new TestClass(1, 2), 1), 0);
+    assertIntEquals(testLoop28(new TestClass(1, 2), 2), 0);
+    assertIntEquals(testLoop28(new TestClass(1, 2), 3), 1);
+    assertIntEquals(testLoop29(0), 0);
+    assertIntEquals(testLoop29(1), 1);
+    assertIntEquals(testLoop29(2), 3);
+    assertIntEquals(testLoop29(3), 6);
+    assertIntEquals(testLoop30(0), 0);
+    assertIntEquals(testLoop30(1), 1);
+    assertIntEquals(testLoop30(2), 2);
+    assertIntEquals(testLoop30(3), 3);
+    assertIntEquals(testLoop31(0), 0);
+    assertIntEquals(testLoop31(1), 0);
+    assertIntEquals(testLoop31(2), 0);
+    assertIntEquals(testLoop31(3), 0);
+    assertIntEquals(testLoop32(new TestClass(), 0), -1);
+    assertIntEquals(testLoop32(new TestClass(), 1), 2);
+    assertIntEquals(testLoop32(new TestClass(), 2), 1);
+    assertIntEquals(testLoop32(new TestClass(), 3), -2);
+    assertIntEquals(testLoop33(new TestClass(), 0), 0);
+    assertIntEquals(testLoop33(new TestClass(), 1), 0);
+    assertIntEquals(testLoop33(new TestClass(), 2), 0);
+    assertIntEquals(testLoop33(new TestClass(), 3), 0);
+    assertIntEquals(testLoop34(0), 0);
+    assertIntEquals(testLoop34(1), 1);
+    assertIntEquals(testLoop34(2), 3);
+    assertIntEquals(testLoop34(3), 6);
+    assertIntEquals(testLoop35(0), 0);
+    assertIntEquals(testLoop35(1), 1);
+    assertIntEquals(testLoop35(2), 3);
+    assertIntEquals(testLoop35(3), 6);
+    assertIntEquals(testLoop36(4), 6);
+    assertIntEquals(testLoop37(4), 6);
+    assertIntEquals(testLoop38(4, new int[4]), 0);
+
+    assertIntEquals(testNestedLoop1(new TestClass(), 0), 1);
+    assertIntEquals(testNestedLoop1(new TestClass(), 1), 1);
+    assertIntEquals(testNestedLoop1(new TestClass(), 2), 1);
+    assertIntEquals(testNestedLoop1(new TestClass(), 3), 1);
+    assertIntEquals(testNestedLoop2(new TestClass(), 0), 1);
+    assertIntEquals(testNestedLoop2(new TestClass(), 1), 2);
+    assertIntEquals(testNestedLoop2(new TestClass(), 2), 2);
+    assertIntEquals(testNestedLoop2(new TestClass(), 3), 2);
+    assertIntEquals(testNestedLoop3(new TestClass(), 0), 1);
+    assertIntEquals(testNestedLoop3(new TestClass(), 1), 2);
+    assertIntEquals(testNestedLoop3(new TestClass(), 2), 2);
+    assertIntEquals(testNestedLoop3(new TestClass(), 3), 2);
+    assertIntEquals(testNestedLoop4(new TestClass(), 0), 1);
+    assertIntEquals(testNestedLoop4(new TestClass(), 1), 1);
+    assertIntEquals(testNestedLoop4(new TestClass(), 2), 2);
+    assertIntEquals(testNestedLoop4(new TestClass(), 3), 2);
+    assertIntEquals(testNestedLoop5(new TestClass(), 0), 1);
+    assertIntEquals(testNestedLoop5(new TestClass(), 1), 2);
+    assertIntEquals(testNestedLoop5(new TestClass(), 2), 2);
+    assertIntEquals(testNestedLoop5(new TestClass(), 3), 2);
+    assertIntEquals(testNestedLoop6(new TestClass(), 0), 1);
+    assertIntEquals(testNestedLoop6(new TestClass(), 1), 1);
+    assertIntEquals(testNestedLoop6(new TestClass(), 2), 2);
+    assertIntEquals(testNestedLoop6(new TestClass(), 3), 2);
+    assertIntEquals(testNestedLoop7(new TestClass(), 0), 0);
+    assertIntEquals(testNestedLoop7(new TestClass(), 1), 1);
+    assertIntEquals(testNestedLoop7(new TestClass(), 2), 2);
+    assertIntEquals(testNestedLoop7(new TestClass(), 3), 3);
+    assertIntEquals(testNestedLoop8(new TestClass(), 0), 0);
+    assertIntEquals(testNestedLoop8(new TestClass(), 1), 0);
+    assertIntEquals(testNestedLoop8(new TestClass(), 2), 0);
+    assertIntEquals(testNestedLoop8(new TestClass(), 3), 0);
+    assertLongEquals(testOverlapLoop(10), 34l);
+    assertLongEquals(testOverlapLoop(50), 7778742049l);
+    assertIntEquals($noinline$testPartialEscape1(new TestClass(), true), 1);
+    assertIntEquals($noinline$testPartialEscape1(new TestClass(), false), 0);
+    assertIntEquals($noinline$testPartialEscape2(new TestClass(), true), 1);
+    assertIntEquals($noinline$testPartialEscape2(new TestClass(), false), 0);
+    assertDoubleEquals($noinline$testPartialEscape3_double(true), -20d);
+    assertDoubleEquals($noinline$testPartialEscape3_double(false), -40d);
+    assertFloatEquals($noinline$testPartialEscape3_float(true), -20f);
+    assertFloatEquals($noinline$testPartialEscape3_float(false), -40f);
+    assertIntEquals($noinline$testPartialEscape3_int(true), -20);
+    assertIntEquals($noinline$testPartialEscape3_int(false), -40);
+    assertIntEquals($noinline$testPartialEscape3_byte(true), -20);
+    assertIntEquals($noinline$testPartialEscape3_byte(false), -40);
+    assertIntEquals($noinline$testPartialEscape3_short(true), -20);
+    assertIntEquals($noinline$testPartialEscape3_short(false), -40);
+    assertLongEquals($noinline$testPartialEscape3_long(true), -20);
+    assertLongEquals($noinline$testPartialEscape3_long(false), -40);
+  }
 }
diff --git a/test/530-checker-lse2/Android.bp b/test/530-checker-lse2/Android.bp
new file mode 100644
index 0000000..cb86299
--- /dev/null
+++ b/test/530-checker-lse2/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-checker-lse2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-checker-lse2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-checker-lse2-expected-stdout",
+        ":art-run-test-530-checker-lse2-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-checker-lse2-expected-stdout",
+    out: ["art-run-test-530-checker-lse2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-checker-lse2-expected-stderr",
+    out: ["art-run-test-530-checker-lse2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-lse2/expected-stderr.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/530-checker-lse2/expected-stderr.txt
diff --git a/test/530-checker-lse2/expected.txt b/test/530-checker-lse2/expected-stdout.txt
similarity index 100%
rename from test/530-checker-lse2/expected.txt
rename to test/530-checker-lse2/expected-stdout.txt
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-lse3/expected-stderr.txt
similarity index 100%
rename from test/530-checker-lse3/expected.txt
rename to test/530-checker-lse3/expected-stderr.txt
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-lse3/expected-stdout.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/530-checker-lse3/expected-stdout.txt
diff --git a/test/530-checker-lse3/smali/StoreLoad.smali b/test/530-checker-lse3/smali/StoreLoad.smali
index 7fb582c..0a5e363 100644
--- a/test/530-checker-lse3/smali/StoreLoad.smali
+++ b/test/530-checker-lse3/smali/StoreLoad.smali
@@ -58,5 +58,96 @@
     return v0
 .end method
 
+## CHECK-START: int StoreLoad.test3(int) load_store_elimination (before)
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     StaticFieldGet
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     TypeConversion
+## CHECK-DAG:                     Phi
+## CHECK-DAG:                     StaticFieldGet
+
+## CHECK-START: int StoreLoad.test3(int) load_store_elimination (after)
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     TypeConversion
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     Phi
+## CHECK-DAG:                     Phi
+
+## CHECK-START: int StoreLoad.test3(int) load_store_elimination (after)
+## CHECK:                         Phi
+## CHECK:                         Phi
+## CHECK-NOT:                     Phi
+
+## CHECK-START: int StoreLoad.test3(int) load_store_elimination (after)
+## CHECK:                         TypeConversion
+## CHECK-NOT:                     TypeConversion
+
+## CHECK-START: int StoreLoad.test3(int) load_store_elimination (after)
+## CHECK-NOT:                     StaticFieldGet
+.method public static test3(I)I
+    .registers 3
+    const/4 v0, 0
+    sput p0, LStoreLoad;->intField:I
+    and-int/lit8 v1, p0, 1
+    if-eqz v1, :skip
+
+    sput-byte p0, LStoreLoad;->byteField:B
+    sget-byte v1, LStoreLoad;->byteField:B
+    sput v1, LStoreLoad;->intField:I
+    # Test that this TypeConversion is moved and used for the
+    # sget-byte above instead of creating a new one.
+    int-to-byte v0, p0
+
+    :skip
+    sget v1, LStoreLoad;->intField:I
+    add-int v0, v1, v0
+    return v0
+.end method
+
+## CHECK-START: int StoreLoad.test4(int) load_store_elimination (before)
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     StaticFieldSet
+
+## CHECK-START: int StoreLoad.test4(int) load_store_elimination (after)
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     StaticFieldSet
+## CHECK-DAG:                     StaticFieldSet
+.method public static test4(I)I
+    # Test that stores are kept properly for an irreducible loop.
+    .registers 3
+    const/4 v0, 0
+    const/4 v1, 7
+    if-gt p0, v1, :skip1
+
+    const/4 v1, 1
+    sput v1, LStoreLoad;->intField:I
+    goto :irreducible_loop_middle
+
+    :skip1
+    const/4 v1, 2
+    sput v1, LStoreLoad;->intField:I
+    # Fall through to the irreducible loop
+
+    :irreducible_loop
+    const/4 v1, 3
+    sput v1, LStoreLoad;->intField:I
+    if-eq v0, p0, :end
+
+    :irreducible_loop_middle
+    const/4 v1, 4
+    sput v1, LStoreLoad;->intField:I
+    add-int/lit8 v0, v0, 1
+    goto :irreducible_loop
+
+    :end
+    return p0
+.end method
+
+.field public static intField:I
 .field public static byteField:B
 .field public static byteField2:B
diff --git a/test/530-checker-lse3/src/Main.java b/test/530-checker-lse3/src/Main.java
index caef0b3..0509e47 100644
--- a/test/530-checker-lse3/src/Main.java
+++ b/test/530-checker-lse3/src/Main.java
@@ -44,5 +44,23 @@
     if (b != (byte)0x78) {
       throw new Error("Expected 0xef, got " + b);
     }
+
+    m = c.getMethod("test3", int.class);
+    result = (Integer)m.invoke(null, 300);
+    assertIntEquals(result, 300);
+    result = (Integer)m.invoke(null, 301);
+    assertIntEquals(result, 90);
+
+    m = c.getMethod("test4", int.class);
+    result = (Integer)m.invoke(null, 5);
+    assertIntEquals(result, 5);
+    result = (Integer)m.invoke(null, 10);
+    assertIntEquals(result, 10);
+  }
+
+  private static void assertIntEquals(int result, int expected) {
+    if (result != expected) {
+      throw new Error("Expected " + expected + ", got " + result);
+    }
   }
 }
diff --git a/test/530-checker-lse3/expected.txt b/test/530-checker-peel-unroll/expected-stderr.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/530-checker-peel-unroll/expected-stderr.txt
diff --git a/test/530-checker-peel-unroll/expected.txt b/test/530-checker-peel-unroll/expected-stdout.txt
similarity index 100%
rename from test/530-checker-peel-unroll/expected.txt
rename to test/530-checker-peel-unroll/expected-stdout.txt
diff --git a/test/530-checker-regression-reftyp-final/expected.txt b/test/530-checker-regression-reftyp-final/expected-stderr.txt
similarity index 100%
rename from test/530-checker-regression-reftyp-final/expected.txt
rename to test/530-checker-regression-reftyp-final/expected-stderr.txt
diff --git a/test/530-checker-regression-reftyp-final/expected.txt b/test/530-checker-regression-reftyp-final/expected-stdout.txt
similarity index 100%
copy from test/530-checker-regression-reftyp-final/expected.txt
copy to test/530-checker-regression-reftyp-final/expected-stdout.txt
diff --git a/test/530-instanceof-checkcast/Android.bp b/test/530-instanceof-checkcast/Android.bp
new file mode 100644
index 0000000..3b782c4
--- /dev/null
+++ b/test/530-instanceof-checkcast/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-instanceof-checkcast`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-instanceof-checkcast",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-instanceof-checkcast-expected-stdout",
+        ":art-run-test-530-instanceof-checkcast-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-instanceof-checkcast-expected-stdout",
+    out: ["art-run-test-530-instanceof-checkcast-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-instanceof-checkcast-expected-stderr",
+    out: ["art-run-test-530-instanceof-checkcast-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-instanceof-checkcast/expected.txt b/test/530-instanceof-checkcast/expected-stderr.txt
similarity index 100%
rename from test/530-instanceof-checkcast/expected.txt
rename to test/530-instanceof-checkcast/expected-stderr.txt
diff --git a/test/530-instanceof-checkcast/expected.txt b/test/530-instanceof-checkcast/expected-stdout.txt
similarity index 100%
copy from test/530-instanceof-checkcast/expected.txt
copy to test/530-instanceof-checkcast/expected-stdout.txt
diff --git a/test/530-regression-lse/Android.bp b/test/530-regression-lse/Android.bp
new file mode 100644
index 0000000..e154810
--- /dev/null
+++ b/test/530-regression-lse/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `530-regression-lse`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-530-regression-lse",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-530-regression-lse-expected-stdout",
+        ":art-run-test-530-regression-lse-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-530-regression-lse-expected-stdout",
+    out: ["art-run-test-530-regression-lse-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-530-regression-lse-expected-stderr",
+    out: ["art-run-test-530-regression-lse-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/530-regression-lse/expected.txt b/test/530-regression-lse/expected-stderr.txt
similarity index 100%
rename from test/530-regression-lse/expected.txt
rename to test/530-regression-lse/expected-stderr.txt
diff --git a/test/530-regression-lse/expected.txt b/test/530-regression-lse/expected-stdout.txt
similarity index 100%
copy from test/530-regression-lse/expected.txt
copy to test/530-regression-lse/expected-stdout.txt
diff --git a/test/531-regression-debugphi/expected.txt b/test/531-regression-debugphi/expected-stderr.txt
similarity index 100%
rename from test/531-regression-debugphi/expected.txt
rename to test/531-regression-debugphi/expected-stderr.txt
diff --git a/test/531-regression-debugphi/expected.txt b/test/531-regression-debugphi/expected-stdout.txt
similarity index 100%
copy from test/531-regression-debugphi/expected.txt
copy to test/531-regression-debugphi/expected-stdout.txt
diff --git a/test/532-checker-nonnull-arrayset/Android.bp b/test/532-checker-nonnull-arrayset/Android.bp
new file mode 100644
index 0000000..5ada4c5
--- /dev/null
+++ b/test/532-checker-nonnull-arrayset/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `532-checker-nonnull-arrayset`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-532-checker-nonnull-arrayset",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-532-checker-nonnull-arrayset-expected-stdout",
+        ":art-run-test-532-checker-nonnull-arrayset-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-532-checker-nonnull-arrayset-expected-stdout",
+    out: ["art-run-test-532-checker-nonnull-arrayset-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-532-checker-nonnull-arrayset-expected-stderr",
+    out: ["art-run-test-532-checker-nonnull-arrayset-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/532-checker-nonnull-arrayset/expected.txt b/test/532-checker-nonnull-arrayset/expected-stderr.txt
similarity index 100%
rename from test/532-checker-nonnull-arrayset/expected.txt
rename to test/532-checker-nonnull-arrayset/expected-stderr.txt
diff --git a/test/532-checker-nonnull-arrayset/expected.txt b/test/532-checker-nonnull-arrayset/expected-stdout.txt
similarity index 100%
copy from test/532-checker-nonnull-arrayset/expected.txt
copy to test/532-checker-nonnull-arrayset/expected-stdout.txt
diff --git a/test/533-regression-debugphi/expected.txt b/test/533-regression-debugphi/expected-stderr.txt
similarity index 100%
rename from test/533-regression-debugphi/expected.txt
rename to test/533-regression-debugphi/expected-stderr.txt
diff --git a/test/533-regression-debugphi/expected.txt b/test/533-regression-debugphi/expected-stdout.txt
similarity index 100%
copy from test/533-regression-debugphi/expected.txt
copy to test/533-regression-debugphi/expected-stdout.txt
diff --git a/test/534-checker-bce-deoptimization/Android.bp b/test/534-checker-bce-deoptimization/Android.bp
new file mode 100644
index 0000000..7fcfce0
--- /dev/null
+++ b/test/534-checker-bce-deoptimization/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `534-checker-bce-deoptimization`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-534-checker-bce-deoptimization",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-534-checker-bce-deoptimization-expected-stdout",
+        ":art-run-test-534-checker-bce-deoptimization-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-534-checker-bce-deoptimization-expected-stdout",
+    out: ["art-run-test-534-checker-bce-deoptimization-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-534-checker-bce-deoptimization-expected-stderr",
+    out: ["art-run-test-534-checker-bce-deoptimization-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/536-checker-intrinsic-optimization/expected.txt b/test/534-checker-bce-deoptimization/expected-stderr.txt
similarity index 100%
copy from test/536-checker-intrinsic-optimization/expected.txt
copy to test/534-checker-bce-deoptimization/expected-stderr.txt
diff --git a/test/534-checker-bce-deoptimization/expected.txt b/test/534-checker-bce-deoptimization/expected-stdout.txt
similarity index 100%
rename from test/534-checker-bce-deoptimization/expected.txt
rename to test/534-checker-bce-deoptimization/expected-stdout.txt
diff --git a/test/535-deopt-and-inlining/Android.bp b/test/535-deopt-and-inlining/Android.bp
new file mode 100644
index 0000000..2429c1e
--- /dev/null
+++ b/test/535-deopt-and-inlining/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `535-deopt-and-inlining`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-535-deopt-and-inlining",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-535-deopt-and-inlining-expected-stdout",
+        ":art-run-test-535-deopt-and-inlining-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-535-deopt-and-inlining-expected-stdout",
+    out: ["art-run-test-535-deopt-and-inlining-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-535-deopt-and-inlining-expected-stderr",
+    out: ["art-run-test-535-deopt-and-inlining-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/535-deopt-and-inlining/expected.txt b/test/535-deopt-and-inlining/expected-stderr.txt
similarity index 100%
rename from test/535-deopt-and-inlining/expected.txt
rename to test/535-deopt-and-inlining/expected-stderr.txt
diff --git a/test/535-deopt-and-inlining/expected.txt b/test/535-deopt-and-inlining/expected-stdout.txt
similarity index 100%
copy from test/535-deopt-and-inlining/expected.txt
copy to test/535-deopt-and-inlining/expected-stdout.txt
diff --git a/test/535-regression-const-val/expected.txt b/test/535-regression-const-val/expected-stderr.txt
similarity index 100%
rename from test/535-regression-const-val/expected.txt
rename to test/535-regression-const-val/expected-stderr.txt
diff --git a/test/535-regression-const-val/expected.txt b/test/535-regression-const-val/expected-stdout.txt
similarity index 100%
copy from test/535-regression-const-val/expected.txt
copy to test/535-regression-const-val/expected-stdout.txt
diff --git a/test/536-checker-intrinsic-optimization/Android.bp b/test/536-checker-intrinsic-optimization/Android.bp
new file mode 100644
index 0000000..b9832af
--- /dev/null
+++ b/test/536-checker-intrinsic-optimization/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `536-checker-intrinsic-optimization`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-536-checker-intrinsic-optimization",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-536-checker-intrinsic-optimization-expected-stdout",
+        ":art-run-test-536-checker-intrinsic-optimization-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-536-checker-intrinsic-optimization-expected-stdout",
+    out: ["art-run-test-536-checker-intrinsic-optimization-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-536-checker-intrinsic-optimization-expected-stderr",
+    out: ["art-run-test-536-checker-intrinsic-optimization-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/536-checker-intrinsic-optimization/expected.txt b/test/536-checker-intrinsic-optimization/expected-stderr.txt
similarity index 100%
rename from test/536-checker-intrinsic-optimization/expected.txt
rename to test/536-checker-intrinsic-optimization/expected-stderr.txt
diff --git a/test/536-checker-intrinsic-optimization/expected.txt b/test/536-checker-intrinsic-optimization/expected-stdout.txt
similarity index 100%
copy from test/536-checker-intrinsic-optimization/expected.txt
copy to test/536-checker-intrinsic-optimization/expected-stdout.txt
diff --git a/test/536-checker-intrinsic-optimization/smali/SmaliTests.smali b/test/536-checker-intrinsic-optimization/smali/SmaliTests.smali
deleted file mode 100644
index 87aca6f..0000000
--- a/test/536-checker-intrinsic-optimization/smali/SmaliTests.smali
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-.class public LSmaliTests;
-.super Ljava/lang/Object;
-
-## CHECK-START: char SmaliTests.$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (before)
-## CHECK-DAG:  <<Char:c\d+>>     InvokeVirtual intrinsic:StringCharAt
-## CHECK-DAG:                    Return [<<Char>>]
-
-## CHECK-START: char SmaliTests.$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (after)
-## CHECK-DAG:  <<String:l\d+>>   ParameterValue
-## CHECK-DAG:  <<Pos:i\d+>>      ParameterValue
-## CHECK-DAG:  <<NullCk:l\d+>>   NullCheck [<<String>>]
-## CHECK-DAG:  <<Length:i\d+>>   ArrayLength [<<NullCk>>] is_string_length:true
-## CHECK-DAG:  <<Bounds:i\d+>>   BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
-## CHECK-DAG:  <<Char:c\d+>>     ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true
-## CHECK-DAG:                    Return [<<Char>>]
-
-## CHECK-START: char SmaliTests.$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (after)
-## CHECK-NOT:                    InvokeVirtual intrinsic:StringCharAt
-.method public static $noinline$stringCharAtCatch(Ljava/lang/String;I)C
-    .registers 4
-    .param p0, "s"    # Ljava/lang/String;
-    .param p1, "pos"    # I
-
-    .prologue
-
-  :try_start
-    # tmp = s.charAt(pos)
-    invoke-virtual {p0, p1}, Ljava/lang/String;->charAt(I)C
-  :try_end
-    .catch Ljava/lang/StringIndexOutOfBoundsException; {:try_start .. :try_end} :catch
-
-    # return tmp
-    move-result v1
-    return v1
-
-  :catch
-    # return '\0'
-    move-exception v0
-    const/4 v1, 0x0
-    return v1
-.end method
-
-##  CHECK-START: char SmaliTests.stringCharAtCatchPhiReturn(java.lang.String, int) instruction_simplifier (before)
-##  CHECK-DAG:  <<Int:i\d+>>      IntConstant 0
-##  CHECK-DAG:  <<Char:c\d+>>     InvokeVirtual intrinsic:StringCharAt
-##  CHECK-DAG:  <<Phi:i\d+>>      Phi [<<Char>>,<<Int>>]
-##  CHECK-DAG:                    Return [<<Phi>>]
-
-##  CHECK-START: char SmaliTests.stringCharAtCatchPhiReturn(java.lang.String, int) instruction_simplifier (after)
-##  CHECK-DAG:  <<String:l\d+>>   ParameterValue
-##  CHECK-DAG:  <<Pos:i\d+>>      ParameterValue
-##  CHECK-DAG:  <<Int:i\d+>>      IntConstant 0
-##  CHECK-DAG:  <<NullCk:l\d+>>   NullCheck [<<String>>]
-##  CHECK-DAG:  <<Length:i\d+>>   ArrayLength [<<NullCk>>] is_string_length:true
-##  CHECK-DAG:  <<Bounds:i\d+>>   BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
-##  CHECK-DAG:  <<Char:c\d+>>     ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true
-##  CHECK-DAG:  <<Phi:i\d+>>      Phi [<<Char>>,<<Int>>]
-##  CHECK-DAG:                    Return [<<Phi>>]
-
-##  CHECK-START: char SmaliTests.stringCharAtCatchPhiReturn(java.lang.String, int) instruction_simplifier (after)
-##  CHECK-NOT:                    InvokeVirtual intrinsic:StringCharAt
-.method public static stringCharAtCatchPhiReturn(Ljava/lang/String;I)C
-    .registers 4
-
-    sget-boolean v1, LMain;->doThrow:Z
-
-    if-eqz v1, :cond_a
-    new-instance v1, Ljava/lang/Error;
-    invoke-direct {v1}, Ljava/lang/Error;-><init>()V
-    throw v1
-
-    :cond_a
-    :try_start_a
-    invoke-virtual {p0, p1}, Ljava/lang/String;->charAt(I)C
-    :try_end_d
-    .catch Ljava/lang/StringIndexOutOfBoundsException; {:try_start_a .. :try_end_d} :catch_f
-
-    move-result v1
-
-    :goto_e
-    return v1
-
-    :catch_f
-    move-exception v0
-
-    const/4 v1, 0x0
-    goto :goto_e
-.end method
diff --git a/test/536-checker-intrinsic-optimization/src/Main.java b/test/536-checker-intrinsic-optimization/src/Main.java
index 980df70..c809278 100644
--- a/test/536-checker-intrinsic-optimization/src/Main.java
+++ b/test/536-checker-intrinsic-optimization/src/Main.java
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-import java.lang.reflect.Method;
-
 public class Main {
   public static String smallString = generateString(100);
   public static String mediumString = generateString(300);
@@ -127,9 +125,10 @@
     }
 
     assertCharEquals('7', $opt$noinline$stringCharAtCatch("0123456789", 7));
-    assertCharEquals('7', $noinline$runSmaliTest("$noinline$stringCharAtCatch", "0123456789", 7));
     assertCharEquals('\0', $opt$noinline$stringCharAtCatch("0123456789", 10));
-    assertCharEquals('\0', $noinline$runSmaliTest("$noinline$stringCharAtCatch","0123456789", 10));
+
+    assertCharEquals('7', $opt$noinline$stringCharAtCatchPhiReturn("0123456789", 7));
+    assertCharEquals('\0', $opt$noinline$stringCharAtCatchPhiReturn("0123456789", 10));
 
     assertIntEquals('a' + 'b' + 'c', $opt$noinline$stringSumChars("abc"));
     assertIntEquals('a' + 'b' + 'c', $opt$noinline$stringSumLeadingChars("abcdef", 3));
@@ -152,28 +151,20 @@
     }
   }
 
-  /// CHECK-START: int Main.$opt$noinline$getStringLength(java.lang.String) instruction_simplifier (before)
-  /// CHECK-DAG:  <<Length:i\d+>>   InvokeVirtual intrinsic:StringLength
-  /// CHECK-DAG:                    Return [<<Length>>]
-
-  /// CHECK-START: int Main.$opt$noinline$getStringLength(java.lang.String) instruction_simplifier (after)
+  /// CHECK-START: int Main.$opt$noinline$getStringLength(java.lang.String) builder (after)
   /// CHECK-DAG:  <<String:l\d+>>   ParameterValue
   /// CHECK-DAG:  <<NullCk:l\d+>>   NullCheck [<<String>>]
   /// CHECK-DAG:  <<Length:i\d+>>   ArrayLength [<<NullCk>>] is_string_length:true
   /// CHECK-DAG:                    Return [<<Length>>]
 
-  /// CHECK-START: int Main.$opt$noinline$getStringLength(java.lang.String) instruction_simplifier (after)
-  /// CHECK-NOT:                    InvokeVirtual intrinsic:StringLength
+  /// CHECK-START: int Main.$opt$noinline$getStringLength(java.lang.String) builder (after)
+  /// CHECK-NOT:                    InvokeVirtual
 
   static public int $opt$noinline$getStringLength(String s) {
     return s.length();
   }
 
-  /// CHECK-START: boolean Main.$opt$noinline$isStringEmpty(java.lang.String) instruction_simplifier (before)
-  /// CHECK-DAG:  <<IsEmpty:z\d+>>  InvokeVirtual intrinsic:StringIsEmpty
-  /// CHECK-DAG:                    Return [<<IsEmpty>>]
-
-  /// CHECK-START: boolean Main.$opt$noinline$isStringEmpty(java.lang.String) instruction_simplifier (after)
+  /// CHECK-START: boolean Main.$opt$noinline$isStringEmpty(java.lang.String) builder (after)
   /// CHECK-DAG:  <<String:l\d+>>   ParameterValue
   /// CHECK-DAG:  <<Const0:i\d+>>   IntConstant 0
   /// CHECK-DAG:  <<NullCk:l\d+>>   NullCheck [<<String>>]
@@ -181,18 +172,14 @@
   /// CHECK-DAG:  <<IsEmpty:z\d+>>  Equal [<<Length>>,<<Const0>>]
   /// CHECK-DAG:                    Return [<<IsEmpty>>]
 
-  /// CHECK-START: boolean Main.$opt$noinline$isStringEmpty(java.lang.String) instruction_simplifier (after)
-  /// CHECK-NOT:                    InvokeVirtual intrinsic:StringIsEmpty
+  /// CHECK-START: boolean Main.$opt$noinline$isStringEmpty(java.lang.String) builder (after)
+  /// CHECK-NOT:                    InvokeVirtual
 
   static public boolean $opt$noinline$isStringEmpty(String s) {
     return s.isEmpty();
   }
 
-  /// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) instruction_simplifier (before)
-  /// CHECK-DAG:  <<Char:c\d+>>     InvokeVirtual intrinsic:StringCharAt
-  /// CHECK-DAG:                    Return [<<Char>>]
-
-  /// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) instruction_simplifier (after)
+  /// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) builder (after)
   /// CHECK-DAG:  <<String:l\d+>>   ParameterValue
   /// CHECK-DAG:  <<Pos:i\d+>>      ParameterValue
   /// CHECK-DAG:  <<NullCk:l\d+>>   NullCheck [<<String>>]
@@ -201,34 +188,24 @@
   /// CHECK-DAG:  <<Char:c\d+>>     ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true
   /// CHECK-DAG:                    Return [<<Char>>]
 
-  /// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) instruction_simplifier (after)
-  /// CHECK-NOT:                    InvokeVirtual intrinsic:StringCharAt
+  /// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) builder (after)
+  /// CHECK-NOT:                    InvokeVirtual
 
   static public char $opt$noinline$stringCharAt(String s, int pos) {
     return s.charAt(pos);
   }
 
-  /// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (before)
-  /// CHECK-DAG:  <<Int:i\d+>>      IntConstant 0
-  /// CHECK-DAG:  <<Char:c\d+>>     InvokeVirtual intrinsic:StringCharAt
-
-  //                                The return value can come from a Phi should the two returns be merged.
-  //                                Please refer to the Smali code for a more detailed verification.
-
-  /// CHECK-DAG:                    Return [{{(c|i)\d+}}]
-
-  /// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (after)
+  /// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) builder (after)
   /// CHECK-DAG:  <<String:l\d+>>   ParameterValue
   /// CHECK-DAG:  <<Pos:i\d+>>      ParameterValue
-  /// CHECK-DAG:  <<Int:i\d+>>      IntConstant 0
   /// CHECK-DAG:  <<NullCk:l\d+>>   NullCheck [<<String>>]
   /// CHECK-DAG:  <<Length:i\d+>>   ArrayLength [<<NullCk>>] is_string_length:true
   /// CHECK-DAG:  <<Bounds:i\d+>>   BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
   /// CHECK-DAG:  <<Char:c\d+>>     ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true
   /// CHECK-DAG:                    Return [{{(c|i)\d+}}]
 
-  /// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (after)
-  /// CHECK-NOT:                    InvokeVirtual intrinsic:StringCharAt
+  /// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) builder (after)
+  /// CHECK-NOT:                    InvokeVirtual
 
   static public char $opt$noinline$stringCharAtCatch(String s, int pos) {
     try {
@@ -238,19 +215,38 @@
     }
   }
 
-  /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) instruction_simplifier (before)
-  /// CHECK-DAG:                    InvokeVirtual intrinsic:StringLength
-  /// CHECK-DAG:                    InvokeVirtual intrinsic:StringCharAt
+  /// CHECK-START: char Main.$opt$noinline$stringCharAtCatchPhiReturn(java.lang.String, int) builder (after)
+  /// CHECK-DAG:  <<String:l\d+>>   ParameterValue
+  /// CHECK-DAG:  <<Pos:i\d+>>      ParameterValue
+  /// CHECK-DAG:  <<Int:i\d+>>      IntConstant 0
+  /// CHECK-DAG:  <<NullCk:l\d+>>   NullCheck [<<String>>]
+  /// CHECK-DAG:  <<Length:i\d+>>   ArrayLength [<<NullCk>>] is_string_length:true
+  /// CHECK-DAG:  <<Bounds:i\d+>>   BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
+  /// CHECK-DAG:  <<Char:c\d+>>     ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true
+  /// CHECK-DAG:  <<Phi:i\d+>>      Phi [<<Char>>,<<Int>>]
+  /// CHECK-DAG:                    Return [<<Phi>>]
 
-  /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) instruction_simplifier (after)
+  /// CHECK-START: char Main.$opt$noinline$stringCharAtCatchPhiReturn(java.lang.String, int) instruction_simplifier (after)
+  /// CHECK-NOT:                    InvokeVirtual intrinsic:StringCharAt
+
+  static public char $opt$noinline$stringCharAtCatchPhiReturn(String s, int pos) {
+    char result;
+    try {
+      result = s.charAt(pos);
+    } catch (StringIndexOutOfBoundsException ignored) {
+      result = '\0';
+    }
+    return result;
+  }
+
+  /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) builder (after)
   /// CHECK-DAG:                    ArrayLength is_string_length:true
   /// CHECK-DAG:                    ArrayLength is_string_length:true
   /// CHECK-DAG:                    BoundsCheck is_string_char_at:true
   /// CHECK-DAG:                    ArrayGet is_string_char_at:true
 
-  /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) instruction_simplifier (after)
-  /// CHECK-NOT:                    InvokeVirtual intrinsic:StringLength
-  /// CHECK-NOT:                    InvokeVirtual intrinsic:StringCharAt
+  /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) builder (after)
+  /// CHECK-NOT:                    InvokeVirtual
 
   /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) GVN (after)
   /// CHECK-DAG:                    ArrayLength is_string_length:true
@@ -268,16 +264,13 @@
     return sum;
   }
 
-  /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) instruction_simplifier (before)
-  /// CHECK-DAG:                    InvokeVirtual intrinsic:StringCharAt
-
-  /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) instruction_simplifier (after)
+  /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) builder (after)
   /// CHECK-DAG:                    ArrayLength is_string_length:true
   /// CHECK-DAG:                    BoundsCheck is_string_char_at:true
   /// CHECK-DAG:                    ArrayGet is_string_char_at:true
 
-  /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) instruction_simplifier (after)
-  /// CHECK-NOT:                    InvokeVirtual intrinsic:StringCharAt
+  /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) builder (after)
+  /// CHECK-NOT:                    InvokeVirtual
 
   /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) BCE (after)
   /// CHECK-DAG:                    Deoptimize env:[[{{[^\]]*}}]]
@@ -293,13 +286,7 @@
     return sum;
   }
 
-  /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) instruction_simplifier (before)
-  /// CHECK-DAG:                    InvokeVirtual intrinsic:StringCharAt
-  /// CHECK-DAG:                    InvokeVirtual intrinsic:StringCharAt
-  /// CHECK-DAG:                    InvokeVirtual intrinsic:StringCharAt
-  /// CHECK-DAG:                    InvokeVirtual intrinsic:StringCharAt
-
-  /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) instruction_simplifier (after)
+  /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) builder (after)
   /// CHECK-DAG:                    ArrayLength is_string_length:true
   /// CHECK-DAG:                    BoundsCheck is_string_char_at:true
   /// CHECK-DAG:                    ArrayGet is_string_char_at:true
@@ -313,8 +300,8 @@
   /// CHECK-DAG:                    BoundsCheck is_string_char_at:true
   /// CHECK-DAG:                    ArrayGet is_string_char_at:true
 
-  /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) instruction_simplifier (after)
-  /// CHECK-NOT:                    InvokeVirtual intrinsic:StringCharAt
+  /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) builder (after)
+  /// CHECK-NOT:                    InvokeVirtual
 
   /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) BCE (after)
   /// CHECK-DAG:                    Deoptimize env:[[{{[^\]]*}}]]
@@ -436,16 +423,6 @@
   static String myString;
   static Object myObject;
 
-  public static char $noinline$runSmaliTest(String name, String str, int pos) {
-    try {
-      Class<?> c = Class.forName("SmaliTests");
-      Method m = c.getMethod(name, String.class, int.class);
-      return (Character) m.invoke(null, str, pos);
-    } catch (Exception ex) {
-      throw new Error(ex);
-    }
-  }
-
   public static String stringGetCharsAndBack(String src) {
     char[] dst = new char[src.length()];
     src.getChars(0, src.length(), dst, 0);
diff --git a/test/542-unresolved-access-check/expected.txt b/test/536-checker-needs-access-check/expected-stderr.txt
similarity index 100%
copy from test/542-unresolved-access-check/expected.txt
copy to test/536-checker-needs-access-check/expected-stderr.txt
diff --git a/test/536-checker-needs-access-check/expected-stdout.txt b/test/536-checker-needs-access-check/expected-stdout.txt
new file mode 100644
index 0000000..4992f43
--- /dev/null
+++ b/test/536-checker-needs-access-check/expected-stdout.txt
@@ -0,0 +1,5 @@
+Got expected error instanceof
+Got expected error instanceof null
+Got expected error checkcast null
+Got expected error checkcast object
+Got expected error instanceof (keep LoadClass with access check)
diff --git a/test/536-checker-needs-access-check/expected.txt b/test/536-checker-needs-access-check/expected.txt
deleted file mode 100644
index 4acae95..0000000
--- a/test/536-checker-needs-access-check/expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Got expected error instanceof
-Got expected error instanceof null
-Got expected error checkcast null
-Got expected error instanceof (keep LoadClass with access check)
diff --git a/test/536-checker-needs-access-check/src/Main.java b/test/536-checker-needs-access-check/src/Main.java
index 7bd49c1..bb402e5 100644
--- a/test/536-checker-needs-access-check/src/Main.java
+++ b/test/536-checker-needs-access-check/src/Main.java
@@ -38,20 +38,34 @@
         }
 
         try {
+            $noinline$testCheckCast(new Object());
+        } catch (IllegalAccessError e) {
+            System.out.println("Got expected error checkcast object");
+        }
+
+        try {
             testDontGvnLoadClassWithAccessChecks(new Object());
         } catch (IllegalAccessError e) {
             System.out.println("Got expected error instanceof (keep LoadClass with access check)");
         }
+
+        InaccessibleClassProxy.testGetReferrersClass();
+        InaccessibleClassProxy.testGetReferrersClassViaAnotherClass();
+
+        // Execute again now that classes have been initialized, and entrypoints may have been
+        // updated.
+        InaccessibleClassProxy.testGetReferrersClass();
+        InaccessibleClassProxy.testGetReferrersClassViaAnotherClass();
     }
 
     /// CHECK-START: boolean Main.testInstanceOf() register (after)
-    /// CHECK: InstanceOf
+    /// CHECK: LoadClass class_name:other.InaccessibleClass
     public static boolean testInstanceOf() {
         return ic instanceof InaccessibleClass;
     }
 
     /// CHECK-START: boolean Main.testInstanceOfNull() register (after)
-    /// CHECK: InstanceOf
+    /// CHECK: LoadClass class_name:other.InaccessibleClass
     public static boolean testInstanceOfNull() {
         return null instanceof InaccessibleClass;
     }
@@ -59,11 +73,17 @@
     // TODO: write a test for for CheckCast with not null constant (after RTP can parse arguments).
 
     /// CHECK-START: other.InaccessibleClass Main.testCheckCastNull() register (after)
-    /// CHECK: CheckCast
+    /// CHECK: LoadClass class_name:other.InaccessibleClass
     public static InaccessibleClass testCheckCastNull() {
         return (InaccessibleClass) null;
     }
 
+    /// CHECK-START: other.InaccessibleClass Main.$noinline$testCheckCast(java.lang.Object) register (after)
+    /// CHECK: LoadClass class_name:other.InaccessibleClass
+    public static InaccessibleClass $noinline$testCheckCast(Object o) {
+        return (InaccessibleClass) o;
+    }
+
     /// CHECK-START: boolean Main.testDontGvnLoadClassWithAccessChecks(java.lang.Object) inliner (before)
     /// CHECK: InvokeStaticOrDirect
 
diff --git a/test/536-checker-needs-access-check/src/other/InaccessibleClass.java b/test/536-checker-needs-access-check/src/other/InaccessibleClass.java
index de2e1d7..ab2c9dd 100644
--- a/test/536-checker-needs-access-check/src/other/InaccessibleClass.java
+++ b/test/536-checker-needs-access-check/src/other/InaccessibleClass.java
@@ -17,4 +17,13 @@
 package other;
 
 public class InaccessibleClass {
+  public static Class<?> $noinline$getReferrersClass() {
+    // The actual test is in src2/ .
+    throw new Error("Unreachable");
+  }
+
+  public static Class<?> $noinline$getReferrersClassViaAnotherClass() {
+    // The actual test is in src2/ .
+    throw new Error("Unreachable");
+  }
 }
diff --git a/test/536-checker-needs-access-check/src/other/InaccessibleClassProxy.java b/test/536-checker-needs-access-check/src/other/InaccessibleClassProxy.java
index 4c005e4..e69531b 100644
--- a/test/536-checker-needs-access-check/src/other/InaccessibleClassProxy.java
+++ b/test/536-checker-needs-access-check/src/other/InaccessibleClassProxy.java
@@ -20,4 +20,18 @@
   public static boolean test(Object o) {
     return o instanceof InaccessibleClass;
   }
+
+  public static void testGetReferrersClass() {
+    Class<?> klass = InaccessibleClass.$noinline$getReferrersClass();
+    if (klass == null) {
+      throw new Error("Expected non-null klass");
+    }
+  }
+
+  public static void testGetReferrersClassViaAnotherClass() {
+    Class<?> klass = InaccessibleClass.$noinline$getReferrersClassViaAnotherClass();
+    if (klass != null) {
+      throw new Error("Expected non-null klass");
+    }
+  }
 }
diff --git a/test/536-checker-needs-access-check/src/other2/GetInaccessibleClass.java b/test/536-checker-needs-access-check/src/other2/GetInaccessibleClass.java
new file mode 100644
index 0000000..172dbe5
--- /dev/null
+++ b/test/536-checker-needs-access-check/src/other2/GetInaccessibleClass.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package other2;
+
+import other.InaccessibleClass;
+
+public class GetInaccessibleClass {
+  // TODO: Make this method `$inline$` once we do not flag access check
+  // failures as soft-fail in the verifier. b/28313047
+  public static Class<?> get() {
+    return InaccessibleClass.class;
+  }
+}
diff --git a/test/536-checker-needs-access-check/src2/other/InaccessibleClass.java b/test/536-checker-needs-access-check/src2/other/InaccessibleClass.java
index 2732263..743d1ff 100644
--- a/test/536-checker-needs-access-check/src2/other/InaccessibleClass.java
+++ b/test/536-checker-needs-access-check/src2/other/InaccessibleClass.java
@@ -16,5 +16,26 @@
 
 package other;
 
+import other2.GetInaccessibleClass;
+
 /*package*/ class InaccessibleClass {
+  /// CHECK-START: java.lang.Class other.InaccessibleClass.$noinline$getReferrersClass() builder (after)
+  /// CHECK: LoadClass class_name:other.InaccessibleClass needs_access_check:false
+  public static Class<?> $noinline$getReferrersClass() {
+    return InaccessibleClass.class;
+  }
+
+  /// CHECK-START: java.lang.Class other.InaccessibleClass.$noinline$getReferrersClassViaAnotherClass() builder (after)
+  // CHECK: LoadClass class_name:other.InaccessibleClass needs_access_check:true
+  public static Class<?> $noinline$getReferrersClassViaAnotherClass() {
+    // TODO: Make the called method `$inline$` and enable the CHECK above
+    // once we do not flag access check failures as soft-fail in the verifier.
+    // b/28313047
+    Class<?> klass = null;
+    try {
+      klass = GetInaccessibleClass.get();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+    return klass;
+  }
 }
diff --git a/test/536-checker-needs-access-check/src2/other/InaccessibleClassProxy.java b/test/536-checker-needs-access-check/src2/other/InaccessibleClassProxy.java
deleted file mode 100644
index 4c005e4..0000000
--- a/test/536-checker-needs-access-check/src2/other/InaccessibleClassProxy.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-package other;
-
-public class InaccessibleClassProxy {
-  public static boolean test(Object o) {
-    return o instanceof InaccessibleClass;
-  }
-}
diff --git a/test/537-checker-arraycopy/Android.bp b/test/537-checker-arraycopy/Android.bp
new file mode 100644
index 0000000..83b7bd3
--- /dev/null
+++ b/test/537-checker-arraycopy/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `537-checker-arraycopy`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-537-checker-arraycopy",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-537-checker-arraycopy-expected-stdout",
+        ":art-run-test-537-checker-arraycopy-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-537-checker-arraycopy-expected-stdout",
+    out: ["art-run-test-537-checker-arraycopy-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-537-checker-arraycopy-expected-stderr",
+    out: ["art-run-test-537-checker-arraycopy-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/537-checker-arraycopy/expected.txt b/test/537-checker-arraycopy/expected-stderr.txt
similarity index 100%
rename from test/537-checker-arraycopy/expected.txt
rename to test/537-checker-arraycopy/expected-stderr.txt
diff --git a/test/537-checker-arraycopy/expected.txt b/test/537-checker-arraycopy/expected-stdout.txt
similarity index 100%
copy from test/537-checker-arraycopy/expected.txt
copy to test/537-checker-arraycopy/expected-stdout.txt
diff --git a/test/537-checker-debuggable/expected.txt b/test/537-checker-debuggable/expected-stderr.txt
similarity index 100%
rename from test/537-checker-debuggable/expected.txt
rename to test/537-checker-debuggable/expected-stderr.txt
diff --git a/test/537-checker-debuggable/expected.txt b/test/537-checker-debuggable/expected-stdout.txt
similarity index 100%
copy from test/537-checker-debuggable/expected.txt
copy to test/537-checker-debuggable/expected-stdout.txt
diff --git a/test/537-checker-inline-and-unverified/expected.txt b/test/537-checker-inline-and-unverified/expected-stderr.txt
similarity index 100%
rename from test/537-checker-inline-and-unverified/expected.txt
rename to test/537-checker-inline-and-unverified/expected-stderr.txt
diff --git a/test/537-checker-inline-and-unverified/expected.txt b/test/537-checker-inline-and-unverified/expected-stdout.txt
similarity index 100%
copy from test/537-checker-inline-and-unverified/expected.txt
copy to test/537-checker-inline-and-unverified/expected-stdout.txt
diff --git a/test/537-checker-jump-over-jump/Android.bp b/test/537-checker-jump-over-jump/Android.bp
new file mode 100644
index 0000000..e53a69f
--- /dev/null
+++ b/test/537-checker-jump-over-jump/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `537-checker-jump-over-jump`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-537-checker-jump-over-jump",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-537-checker-jump-over-jump-expected-stdout",
+        ":art-run-test-537-checker-jump-over-jump-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-537-checker-jump-over-jump-expected-stdout",
+    out: ["art-run-test-537-checker-jump-over-jump-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-537-checker-jump-over-jump-expected-stderr",
+    out: ["art-run-test-537-checker-jump-over-jump-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/537-checker-jump-over-jump/expected.txt b/test/537-checker-jump-over-jump/expected-stderr.txt
similarity index 100%
rename from test/537-checker-jump-over-jump/expected.txt
rename to test/537-checker-jump-over-jump/expected-stderr.txt
diff --git a/test/537-checker-jump-over-jump/expected.txt b/test/537-checker-jump-over-jump/expected-stdout.txt
similarity index 100%
copy from test/537-checker-jump-over-jump/expected.txt
copy to test/537-checker-jump-over-jump/expected-stdout.txt
diff --git a/test/537-checker-jump-over-jump/src/Main.java b/test/537-checker-jump-over-jump/src/Main.java
index 7a58e8b..7b361ba 100644
--- a/test/537-checker-jump-over-jump/src/Main.java
+++ b/test/537-checker-jump-over-jump/src/Main.java
@@ -19,14 +19,29 @@
   public static int FIBCOUNT = 64;
   public static int[] fibs;
 
+  /// CHECK-START-X86_64: int Main.test() licm (before)
+  /// CHECK-DAG:                        StaticFieldGet field_name:Main.fibs loop:none
+  /// CHECK-DAG:                        StaticFieldGet field_name:Main.fibs loop:B{{\d+}}
+
+  /// CHECK-START-X86_64: int Main.test() licm (after)
+  /// CHECK:                            StaticFieldGet field_name:Main.fibs loop:none
+  /// CHECK:                            StaticFieldGet field_name:Main.fibs loop:none
+
+  /// CHECK-START-X86_64: int Main.test() licm (after)
+  /// CHECK-NOT:                        StaticFieldGet field_name:Main.fibs loop:B{{\d+}}
+
+  /// CHECK-START-X86_64: int Main.test() load_store_elimination (after)
+  /// CHECK:                            StaticFieldGet field_name:Main.fibs
+  /// CHECK-NOT:                        StaticFieldGet field_name:Main.fibs
+
   /// CHECK-START-X86_64: int Main.test() disassembly (after)
   /// CHECK-DAG:   <<Zero:i\d+>>        IntConstant 0
+  /// CHECK-DAG:   <<Fibs:l\d+>>        StaticFieldGet field_name:Main.fibs
   //
   /// CHECK:                            If
   /// CHECK-NEXT:                       cmp
   /// CHECK-NEXT:                       jle/ng
   //
-  /// CHECK-DAG:   <<Fibs:l\d+>>        StaticFieldGet
   /// CHECK-DAG:                        NullCheck [<<Fibs>>]
   /// CHECK-NOT:                        jmp
   /// CHECK-DAG:   <<FibsAtZero:i\d+>>  ArrayGet [<<Fibs>>,<<Zero>>]
diff --git a/test/538-checker-embed-constants/Android.bp b/test/538-checker-embed-constants/Android.bp
new file mode 100644
index 0000000..5fa5a74
--- /dev/null
+++ b/test/538-checker-embed-constants/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `538-checker-embed-constants`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-538-checker-embed-constants",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-538-checker-embed-constants-expected-stdout",
+        ":art-run-test-538-checker-embed-constants-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-538-checker-embed-constants-expected-stdout",
+    out: ["art-run-test-538-checker-embed-constants-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-538-checker-embed-constants-expected-stderr",
+    out: ["art-run-test-538-checker-embed-constants-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/538-checker-embed-constants/expected.txt b/test/538-checker-embed-constants/expected-stderr.txt
similarity index 100%
rename from test/538-checker-embed-constants/expected.txt
rename to test/538-checker-embed-constants/expected-stderr.txt
diff --git a/test/538-checker-embed-constants/expected.txt b/test/538-checker-embed-constants/expected-stdout.txt
similarity index 100%
copy from test/538-checker-embed-constants/expected.txt
copy to test/538-checker-embed-constants/expected-stdout.txt
diff --git a/test/540-checker-rtp-bug/Android.bp b/test/540-checker-rtp-bug/Android.bp
new file mode 100644
index 0000000..413e55d
--- /dev/null
+++ b/test/540-checker-rtp-bug/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `540-checker-rtp-bug`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-540-checker-rtp-bug",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-540-checker-rtp-bug-expected-stdout",
+        ":art-run-test-540-checker-rtp-bug-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-540-checker-rtp-bug-expected-stdout",
+    out: ["art-run-test-540-checker-rtp-bug-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-540-checker-rtp-bug-expected-stderr",
+    out: ["art-run-test-540-checker-rtp-bug-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/408-move-bug/expected.txt b/test/540-checker-rtp-bug/expected-stderr.txt
similarity index 100%
copy from test/408-move-bug/expected.txt
copy to test/540-checker-rtp-bug/expected-stderr.txt
diff --git a/test/540-checker-rtp-bug/expected.txt b/test/540-checker-rtp-bug/expected-stdout.txt
similarity index 100%
rename from test/540-checker-rtp-bug/expected.txt
rename to test/540-checker-rtp-bug/expected-stdout.txt
diff --git a/test/541-regression-inlined-deopt/expected.txt b/test/541-regression-inlined-deopt/expected-stderr.txt
similarity index 100%
rename from test/541-regression-inlined-deopt/expected.txt
rename to test/541-regression-inlined-deopt/expected-stderr.txt
diff --git a/test/541-regression-inlined-deopt/expected.txt b/test/541-regression-inlined-deopt/expected-stdout.txt
similarity index 100%
copy from test/541-regression-inlined-deopt/expected.txt
copy to test/541-regression-inlined-deopt/expected-stdout.txt
diff --git a/test/542-bitfield-rotates/Android.bp b/test/542-bitfield-rotates/Android.bp
new file mode 100644
index 0000000..21f6999
--- /dev/null
+++ b/test/542-bitfield-rotates/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `542-bitfield-rotates`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-542-bitfield-rotates",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-542-bitfield-rotates-expected-stdout",
+        ":art-run-test-542-bitfield-rotates-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-542-bitfield-rotates-expected-stdout",
+    out: ["art-run-test-542-bitfield-rotates-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-542-bitfield-rotates-expected-stderr",
+    out: ["art-run-test-542-bitfield-rotates-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/542-bitfield-rotates/expected.txt b/test/542-bitfield-rotates/expected-stderr.txt
similarity index 100%
rename from test/542-bitfield-rotates/expected.txt
rename to test/542-bitfield-rotates/expected-stderr.txt
diff --git a/test/542-bitfield-rotates/expected.txt b/test/542-bitfield-rotates/expected-stdout.txt
similarity index 100%
copy from test/542-bitfield-rotates/expected.txt
copy to test/542-bitfield-rotates/expected-stdout.txt
diff --git a/test/542-inline-trycatch/Android.bp b/test/542-inline-trycatch/Android.bp
new file mode 100644
index 0000000..41ca049
--- /dev/null
+++ b/test/542-inline-trycatch/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `542-inline-trycatch`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-542-inline-trycatch",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-542-inline-trycatch-expected-stdout",
+        ":art-run-test-542-inline-trycatch-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-542-inline-trycatch-expected-stdout",
+    out: ["art-run-test-542-inline-trycatch-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-542-inline-trycatch-expected-stderr",
+    out: ["art-run-test-542-inline-trycatch-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/542-inline-trycatch/expected.txt b/test/542-inline-trycatch/expected-stderr.txt
similarity index 100%
rename from test/542-inline-trycatch/expected.txt
rename to test/542-inline-trycatch/expected-stderr.txt
diff --git a/test/542-inline-trycatch/expected.txt b/test/542-inline-trycatch/expected-stdout.txt
similarity index 100%
copy from test/542-inline-trycatch/expected.txt
copy to test/542-inline-trycatch/expected-stdout.txt
diff --git a/test/542-unresolved-access-check/Android.bp b/test/542-unresolved-access-check/Android.bp
new file mode 100644
index 0000000..cb77b50
--- /dev/null
+++ b/test/542-unresolved-access-check/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `542-unresolved-access-check`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-542-unresolved-access-check",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-542-unresolved-access-check-expected-stdout",
+        ":art-run-test-542-unresolved-access-check-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-542-unresolved-access-check-expected-stdout",
+    out: ["art-run-test-542-unresolved-access-check-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-542-unresolved-access-check-expected-stderr",
+    out: ["art-run-test-542-unresolved-access-check-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/542-unresolved-access-check/expected.txt b/test/542-unresolved-access-check/expected-stderr.txt
similarity index 100%
rename from test/542-unresolved-access-check/expected.txt
rename to test/542-unresolved-access-check/expected-stderr.txt
diff --git a/test/542-unresolved-access-check/expected.txt b/test/542-unresolved-access-check/expected-stdout.txt
similarity index 100%
copy from test/542-unresolved-access-check/expected.txt
copy to test/542-unresolved-access-check/expected-stdout.txt
diff --git a/test/543-checker-dce-trycatch/expected.txt b/test/543-checker-dce-trycatch/expected-stderr.txt
similarity index 100%
rename from test/543-checker-dce-trycatch/expected.txt
rename to test/543-checker-dce-trycatch/expected-stderr.txt
diff --git a/test/543-checker-dce-trycatch/expected.txt b/test/543-checker-dce-trycatch/expected-stdout.txt
similarity index 100%
copy from test/543-checker-dce-trycatch/expected.txt
copy to test/543-checker-dce-trycatch/expected-stdout.txt
diff --git a/test/500-instanceof/expected.txt b/test/543-env-long-ref/expected-stderr.txt
similarity index 100%
copy from test/500-instanceof/expected.txt
copy to test/543-env-long-ref/expected-stderr.txt
diff --git a/test/543-env-long-ref/expected.txt b/test/543-env-long-ref/expected-stdout.txt
similarity index 100%
rename from test/543-env-long-ref/expected.txt
rename to test/543-env-long-ref/expected-stdout.txt
diff --git a/test/545-tracing-and-jit/Android.bp b/test/545-tracing-and-jit/Android.bp
new file mode 100644
index 0000000..2615572
--- /dev/null
+++ b/test/545-tracing-and-jit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `545-tracing-and-jit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-545-tracing-and-jit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-545-tracing-and-jit-expected-stdout",
+        ":art-run-test-545-tracing-and-jit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-545-tracing-and-jit-expected-stdout",
+    out: ["art-run-test-545-tracing-and-jit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-545-tracing-and-jit-expected-stderr",
+    out: ["art-run-test-545-tracing-and-jit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/545-tracing-and-jit/expected.txt b/test/545-tracing-and-jit/expected-stderr.txt
similarity index 100%
rename from test/545-tracing-and-jit/expected.txt
rename to test/545-tracing-and-jit/expected-stderr.txt
diff --git a/test/545-tracing-and-jit/expected.txt b/test/545-tracing-and-jit/expected-stdout.txt
similarity index 100%
copy from test/545-tracing-and-jit/expected.txt
copy to test/545-tracing-and-jit/expected-stdout.txt
diff --git a/test/546-regression-simplify-catch/expected.txt b/test/546-regression-simplify-catch/expected-stderr.txt
similarity index 100%
rename from test/546-regression-simplify-catch/expected.txt
rename to test/546-regression-simplify-catch/expected-stderr.txt
diff --git a/test/546-regression-simplify-catch/expected.txt b/test/546-regression-simplify-catch/expected-stdout.txt
similarity index 100%
copy from test/546-regression-simplify-catch/expected.txt
copy to test/546-regression-simplify-catch/expected-stdout.txt
diff --git a/test/547-regression-trycatch-critic-edge/expected.txt b/test/547-regression-trycatch-critic-edge/expected-stderr.txt
similarity index 100%
rename from test/547-regression-trycatch-critic-edge/expected.txt
rename to test/547-regression-trycatch-critic-edge/expected-stderr.txt
diff --git a/test/547-regression-trycatch-critic-edge/expected.txt b/test/547-regression-trycatch-critic-edge/expected-stdout.txt
similarity index 100%
copy from test/547-regression-trycatch-critic-edge/expected.txt
copy to test/547-regression-trycatch-critic-edge/expected-stdout.txt
diff --git a/test/548-checker-inlining-and-dce/Android.bp b/test/548-checker-inlining-and-dce/Android.bp
new file mode 100644
index 0000000..eb4874a
--- /dev/null
+++ b/test/548-checker-inlining-and-dce/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `548-checker-inlining-and-dce`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-548-checker-inlining-and-dce",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-548-checker-inlining-and-dce-expected-stdout",
+        ":art-run-test-548-checker-inlining-and-dce-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-548-checker-inlining-and-dce-expected-stdout",
+    out: ["art-run-test-548-checker-inlining-and-dce-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-548-checker-inlining-and-dce-expected-stderr",
+    out: ["art-run-test-548-checker-inlining-and-dce-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/548-checker-inlining-and-dce/expected.txt b/test/548-checker-inlining-and-dce/expected-stderr.txt
similarity index 100%
rename from test/548-checker-inlining-and-dce/expected.txt
rename to test/548-checker-inlining-and-dce/expected-stderr.txt
diff --git a/test/548-checker-inlining-and-dce/expected.txt b/test/548-checker-inlining-and-dce/expected-stdout.txt
similarity index 100%
copy from test/548-checker-inlining-and-dce/expected.txt
copy to test/548-checker-inlining-and-dce/expected-stdout.txt
diff --git a/test/549-checker-types-merge/Android.bp b/test/549-checker-types-merge/Android.bp
new file mode 100644
index 0000000..6899fbc
--- /dev/null
+++ b/test/549-checker-types-merge/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `549-checker-types-merge`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-549-checker-types-merge",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-549-checker-types-merge-expected-stdout",
+        ":art-run-test-549-checker-types-merge-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-549-checker-types-merge-expected-stdout",
+    out: ["art-run-test-549-checker-types-merge-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-549-checker-types-merge-expected-stderr",
+    out: ["art-run-test-549-checker-types-merge-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/549-checker-types-merge/expected.txt b/test/549-checker-types-merge/expected-stderr.txt
similarity index 100%
rename from test/549-checker-types-merge/expected.txt
rename to test/549-checker-types-merge/expected-stderr.txt
diff --git a/test/549-checker-types-merge/expected.txt b/test/549-checker-types-merge/expected-stdout.txt
similarity index 100%
copy from test/549-checker-types-merge/expected.txt
copy to test/549-checker-types-merge/expected-stdout.txt
diff --git a/test/550-checker-multiply-accumulate/Android.bp b/test/550-checker-multiply-accumulate/Android.bp
new file mode 100644
index 0000000..12ad79b
--- /dev/null
+++ b/test/550-checker-multiply-accumulate/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `550-checker-multiply-accumulate`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-550-checker-multiply-accumulate",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-550-checker-multiply-accumulate-expected-stdout",
+        ":art-run-test-550-checker-multiply-accumulate-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-550-checker-multiply-accumulate-expected-stdout",
+    out: ["art-run-test-550-checker-multiply-accumulate-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-550-checker-multiply-accumulate-expected-stderr",
+    out: ["art-run-test-550-checker-multiply-accumulate-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/550-checker-multiply-accumulate/expected.txt b/test/550-checker-multiply-accumulate/expected-stderr.txt
similarity index 100%
rename from test/550-checker-multiply-accumulate/expected.txt
rename to test/550-checker-multiply-accumulate/expected-stderr.txt
diff --git a/test/550-checker-multiply-accumulate/expected.txt b/test/550-checker-multiply-accumulate/expected-stdout.txt
similarity index 100%
copy from test/550-checker-multiply-accumulate/expected.txt
copy to test/550-checker-multiply-accumulate/expected-stdout.txt
diff --git a/test/550-checker-multiply-accumulate/src/Main.java b/test/550-checker-multiply-accumulate/src/Main.java
index 55dd5b5..a07111b 100644
--- a/test/550-checker-multiply-accumulate/src/Main.java
+++ b/test/550-checker-multiply-accumulate/src/Main.java
@@ -16,9 +16,6 @@
 
 public class Main {
 
-  // A dummy value to defeat inlining of these routines.
-  static boolean doThrow = false;
-
   public static void assertIntEquals(int expected, int result) {
     if (expected != result) {
       throw new Error("Expected: " + expected + ", found: " + result);
@@ -80,7 +77,6 @@
   /// CHECK:                            mla r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
 
   public static int $opt$noinline$mulAdd(int acc, int left, int right) {
-    if (doThrow) throw new Error();
     return acc + left * right;
   }
 
@@ -122,7 +118,6 @@
   /// CHECK-NOT:                        MultiplyAccumulate
 
   public static long $opt$noinline$mulSub(long acc, long left, long right) {
-    if (doThrow) throw new Error();
     return acc - left * right;
   }
 
@@ -174,7 +169,6 @@
   /// CHECK-NOT:                        MultiplyAccumulate
 
   public static int $opt$noinline$multipleUses1(int acc, int left, int right) {
-    if (doThrow) throw new Error();
     int temp = left * right;
     return temp | (acc + temp);
   }
@@ -232,7 +226,6 @@
 
 
   public static long $opt$noinline$multipleUses2(long acc, long left, long right) {
-    if (doThrow) throw new Error();
     long temp = left * right;
     return (acc + temp) + (acc - temp);
   }
@@ -285,7 +278,6 @@
   /// CHECK:                            mla r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
 
   public static int $opt$noinline$mulPlusOne(int acc, int var) {
-    if (doThrow) throw new Error();
     return acc * (var + 1);
   }
 
@@ -326,7 +318,6 @@
   /// CHECK-START-ARM: long Main.$opt$noinline$mulMinusOne(long, long) instruction_simplifier_arm (after)
   /// CHECK-NOT:                        MultiplyAccumulate
   public static long $opt$noinline$mulMinusOne(long acc, long var) {
-    if (doThrow) throw new Error();
     return acc * (1 - var);
   }
 
@@ -373,7 +364,6 @@
   /// CHECK-NOT:                        MultiplyAccumulate
 
   public static int $opt$noinline$mulNeg(int left, int right) {
-    if (doThrow) throw new Error();
     return - (left * right);
   }
 
@@ -420,7 +410,6 @@
   /// CHECK-NOT:                        MultiplyAccumulate
 
   public static long $opt$noinline$mulNeg(long left, long right) {
-    if (doThrow) throw new Error();
     return - (left * right);
   }
 
diff --git a/test/550-checker-regression-wide-store/expected.txt b/test/550-checker-regression-wide-store/expected-stderr.txt
similarity index 100%
rename from test/550-checker-regression-wide-store/expected.txt
rename to test/550-checker-regression-wide-store/expected-stderr.txt
diff --git a/test/550-checker-regression-wide-store/expected.txt b/test/550-checker-regression-wide-store/expected-stdout.txt
similarity index 100%
copy from test/550-checker-regression-wide-store/expected.txt
copy to test/550-checker-regression-wide-store/expected-stdout.txt
diff --git a/test/550-new-instance-clinit/Android.bp b/test/550-new-instance-clinit/Android.bp
new file mode 100644
index 0000000..458aa58
--- /dev/null
+++ b/test/550-new-instance-clinit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `550-new-instance-clinit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-550-new-instance-clinit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-550-new-instance-clinit-expected-stdout",
+        ":art-run-test-550-new-instance-clinit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-550-new-instance-clinit-expected-stdout",
+    out: ["art-run-test-550-new-instance-clinit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-550-new-instance-clinit-expected-stderr",
+    out: ["art-run-test-550-new-instance-clinit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/550-new-instance-clinit/expected.txt b/test/550-new-instance-clinit/expected-stderr.txt
similarity index 100%
rename from test/550-new-instance-clinit/expected.txt
rename to test/550-new-instance-clinit/expected-stderr.txt
diff --git a/test/550-new-instance-clinit/expected.txt b/test/550-new-instance-clinit/expected-stdout.txt
similarity index 100%
copy from test/550-new-instance-clinit/expected.txt
copy to test/550-new-instance-clinit/expected-stdout.txt
diff --git a/test/551-checker-clinit/Android.bp b/test/551-checker-clinit/Android.bp
new file mode 100644
index 0000000..8004ade
--- /dev/null
+++ b/test/551-checker-clinit/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `551-checker-clinit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-551-checker-clinit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-551-checker-clinit-expected-stdout",
+        ":art-run-test-551-checker-clinit-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-551-checker-clinit-expected-stdout",
+    out: ["art-run-test-551-checker-clinit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-551-checker-clinit-expected-stderr",
+    out: ["art-run-test-551-checker-clinit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/551-checker-clinit/expected.txt b/test/551-checker-clinit/expected-stderr.txt
similarity index 100%
rename from test/551-checker-clinit/expected.txt
rename to test/551-checker-clinit/expected-stderr.txt
diff --git a/test/551-checker-clinit/expected.txt b/test/551-checker-clinit/expected-stdout.txt
similarity index 100%
copy from test/551-checker-clinit/expected.txt
copy to test/551-checker-clinit/expected-stdout.txt
diff --git a/test/551-checker-shifter-operand/Android.bp b/test/551-checker-shifter-operand/Android.bp
new file mode 100644
index 0000000..3a971ca
--- /dev/null
+++ b/test/551-checker-shifter-operand/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `551-checker-shifter-operand`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-551-checker-shifter-operand",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-551-checker-shifter-operand-expected-stdout",
+        ":art-run-test-551-checker-shifter-operand-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-551-checker-shifter-operand-expected-stdout",
+    out: ["art-run-test-551-checker-shifter-operand-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-551-checker-shifter-operand-expected-stderr",
+    out: ["art-run-test-551-checker-shifter-operand-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/551-checker-shifter-operand/expected.txt b/test/551-checker-shifter-operand/expected-stderr.txt
similarity index 100%
rename from test/551-checker-shifter-operand/expected.txt
rename to test/551-checker-shifter-operand/expected-stderr.txt
diff --git a/test/551-checker-shifter-operand/expected.txt b/test/551-checker-shifter-operand/expected-stdout.txt
similarity index 100%
copy from test/551-checker-shifter-operand/expected.txt
copy to test/551-checker-shifter-operand/expected-stdout.txt
diff --git a/test/551-checker-shifter-operand/src/Main.java b/test/551-checker-shifter-operand/src/Main.java
index 8311b60..4750028 100644
--- a/test/551-checker-shifter-operand/src/Main.java
+++ b/test/551-checker-shifter-operand/src/Main.java
@@ -16,9 +16,6 @@
 
 public class Main {
 
-  // A dummy value to defeat inlining of these routines.
-  static boolean doThrow = false;
-
   public static void assertByteEquals(byte expected, byte result) {
     if (expected != result) {
       throw new Error("Expected: " + expected + ", found: " + result);
@@ -50,26 +47,26 @@
   }
 
   // Non-inlinable type-casting helpers.
-  static  char $noinline$byteToChar   (byte v) { if (doThrow) throw new Error(); return  (char)v; }
-  static short $noinline$byteToShort  (byte v) { if (doThrow) throw new Error(); return (short)v; }
-  static   int $noinline$byteToInt    (byte v) { if (doThrow) throw new Error(); return   (int)v; }
-  static  long $noinline$byteToLong   (byte v) { if (doThrow) throw new Error(); return  (long)v; }
-  static  byte $noinline$charToByte   (char v) { if (doThrow) throw new Error(); return  (byte)v; }
-  static short $noinline$charToShort  (char v) { if (doThrow) throw new Error(); return (short)v; }
-  static   int $noinline$charToInt    (char v) { if (doThrow) throw new Error(); return   (int)v; }
-  static  long $noinline$charToLong   (char v) { if (doThrow) throw new Error(); return  (long)v; }
-  static  byte $noinline$shortToByte (short v) { if (doThrow) throw new Error(); return  (byte)v; }
-  static  char $noinline$shortToChar (short v) { if (doThrow) throw new Error(); return  (char)v; }
-  static   int $noinline$shortToInt  (short v) { if (doThrow) throw new Error(); return   (int)v; }
-  static  long $noinline$shortToLong (short v) { if (doThrow) throw new Error(); return  (long)v; }
-  static  byte $noinline$intToByte     (int v) { if (doThrow) throw new Error(); return  (byte)v; }
-  static  char $noinline$intToChar     (int v) { if (doThrow) throw new Error(); return  (char)v; }
-  static short $noinline$intToShort    (int v) { if (doThrow) throw new Error(); return (short)v; }
-  static  long $noinline$intToLong     (int v) { if (doThrow) throw new Error(); return  (long)v; }
-  static  byte $noinline$longToByte   (long v) { if (doThrow) throw new Error(); return  (byte)v; }
-  static  char $noinline$longToChar   (long v) { if (doThrow) throw new Error(); return  (char)v; }
-  static short $noinline$longToShort  (long v) { if (doThrow) throw new Error(); return (short)v; }
-  static   int $noinline$longToInt    (long v) { if (doThrow) throw new Error(); return   (int)v; }
+  static  char $noinline$byteToChar   (byte v) { return  (char)v; }
+  static short $noinline$byteToShort  (byte v) { return (short)v; }
+  static   int $noinline$byteToInt    (byte v) { return   (int)v; }
+  static  long $noinline$byteToLong   (byte v) { return  (long)v; }
+  static  byte $noinline$charToByte   (char v) { return  (byte)v; }
+  static short $noinline$charToShort  (char v) { return (short)v; }
+  static   int $noinline$charToInt    (char v) { return   (int)v; }
+  static  long $noinline$charToLong   (char v) { return  (long)v; }
+  static  byte $noinline$shortToByte (short v) { return  (byte)v; }
+  static  char $noinline$shortToChar (short v) { return  (char)v; }
+  static   int $noinline$shortToInt  (short v) { return   (int)v; }
+  static  long $noinline$shortToLong (short v) { return  (long)v; }
+  static  byte $noinline$intToByte     (int v) { return  (byte)v; }
+  static  char $noinline$intToChar     (int v) { return  (char)v; }
+  static short $noinline$intToShort    (int v) { return (short)v; }
+  static  long $noinline$intToLong     (int v) { return  (long)v; }
+  static  byte $noinline$longToByte   (long v) { return  (byte)v; }
+  static  char $noinline$longToChar   (long v) { return  (char)v; }
+  static short $noinline$longToShort  (long v) { return (short)v; }
+  static   int $noinline$longToInt    (long v) { return   (int)v; }
 
   /**
    * Basic test merging a bitfield move operation (here a type conversion) into
@@ -114,7 +111,6 @@
   /// CHECK:                            sub x{{\d+}}, x{{\d+}}, w{{\d+}}, sxtb
 
   public static long $opt$noinline$translate(long l, byte b) {
-    if (doThrow) throw new Error();
     long tmp = (long)b;
     return l - tmp;
   }
@@ -156,7 +152,6 @@
   /// CHECK-NOT:                        DataProcWithShifterOp
 
   public static int $opt$noinline$sameInput(int a) {
-    if (doThrow) throw new Error();
     int tmp = a << 2;
     return tmp + tmp;
   }
@@ -210,7 +205,6 @@
   /// CHECK-NOT:                        Add
 
   public static int $opt$noinline$multipleUses(int arg) {
-    if (doThrow) throw new Error();
     int tmp = arg << 23;
     switch (arg) {
       case 1:  return (arg | 1) + tmp;
@@ -247,7 +241,6 @@
   /// CHECK:                            and
 
   static void $opt$noinline$testAnd(long a, long b) {
-    if (doThrow) throw new Error();
     assertLongEquals((a & $noinline$LongShl(b, 5)) | (a & $noinline$longToByte(b)),
                      (a & (b << 5)) | (a & (byte)b));
   }
@@ -271,7 +264,6 @@
   /// CHECK:                            orr
 
   static void $opt$noinline$testOr(int a, int b) {
-    if (doThrow) throw new Error();
     assertIntEquals((a | $noinline$IntShr(b, 6)) | (a | $noinline$intToChar(b)),
                     (a | (b >> 6)) | (a | (char)b));
   }
@@ -295,7 +287,6 @@
   /// CHECK:                            eor
 
   static void $opt$noinline$testXor(long a, long b) {
-    if (doThrow) throw new Error();
     assertLongEquals((a ^ $noinline$LongUshr(b, 7)) | (a ^ $noinline$longToInt(b)),
                      (a ^ (b >>> 7)) | (a ^ (int)b));
   }
@@ -313,7 +304,6 @@
   /// CHECK:                            neg
 
   static void $opt$noinline$testNeg(int a) {
-    if (doThrow) throw new Error();
     assertIntEquals(-$noinline$IntShl(a, 8) | -$noinline$intToShort(a),
                     (-(a << 8)) | (-(short)a));
   }
@@ -632,15 +622,12 @@
 
 
   static int $noinline$IntShl(int b, int c) {
-    if (doThrow) throw new Error();
     return b << c;
   }
   static int $noinline$IntShr(int b, int c) {
-    if (doThrow) throw new Error();
     return b >> c;
   }
   static int $noinline$IntUshr(int b, int c) {
-    if (doThrow) throw new Error();
     return b >>> c;
   }
 
@@ -883,15 +870,12 @@
 
 
   static long $noinline$LongShl(long b, long c) {
-    if (doThrow) throw new Error();
     return b << c;
   }
   static long $noinline$LongShr(long b, long c) {
-    if (doThrow) throw new Error();
     return b >> c;
   }
   static long $noinline$LongUshr(long b, long c) {
-    if (doThrow) throw new Error();
     return b >>> c;
   }
 
diff --git a/test/551-implicit-null-checks/Android.bp b/test/551-implicit-null-checks/Android.bp
new file mode 100644
index 0000000..a29f36d
--- /dev/null
+++ b/test/551-implicit-null-checks/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `551-implicit-null-checks`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-551-implicit-null-checks",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-551-implicit-null-checks-expected-stdout",
+        ":art-run-test-551-implicit-null-checks-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-551-implicit-null-checks-expected-stdout",
+    out: ["art-run-test-551-implicit-null-checks-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-551-implicit-null-checks-expected-stderr",
+    out: ["art-run-test-551-implicit-null-checks-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/551-invoke-super/expected.txt b/test/551-implicit-null-checks/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/551-implicit-null-checks/expected-stderr.txt
diff --git a/test/551-implicit-null-checks/expected.txt b/test/551-implicit-null-checks/expected-stdout.txt
similarity index 100%
rename from test/551-implicit-null-checks/expected.txt
rename to test/551-implicit-null-checks/expected-stdout.txt
diff --git a/test/551-invoke-super/expected.txt b/test/551-invoke-super/expected-stderr.txt
similarity index 100%
rename from test/551-invoke-super/expected.txt
rename to test/551-invoke-super/expected-stderr.txt
diff --git a/test/551-invoke-super/expected.txt b/test/551-invoke-super/expected-stdout.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/551-invoke-super/expected-stdout.txt
diff --git a/test/552-checker-primitive-typeprop/expected.txt b/test/552-checker-primitive-typeprop/expected-stderr.txt
similarity index 100%
rename from test/552-checker-primitive-typeprop/expected.txt
rename to test/552-checker-primitive-typeprop/expected-stderr.txt
diff --git a/test/552-checker-primitive-typeprop/expected.txt b/test/552-checker-primitive-typeprop/expected-stdout.txt
similarity index 100%
copy from test/552-checker-primitive-typeprop/expected.txt
copy to test/552-checker-primitive-typeprop/expected-stdout.txt
diff --git a/test/552-checker-sharpening/Android.bp b/test/552-checker-sharpening/Android.bp
new file mode 100644
index 0000000..6b28722
--- /dev/null
+++ b/test/552-checker-sharpening/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `552-checker-sharpening`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-552-checker-sharpening",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-552-checker-sharpening-expected-stdout",
+        ":art-run-test-552-checker-sharpening-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-552-checker-sharpening-expected-stdout",
+    out: ["art-run-test-552-checker-sharpening-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-552-checker-sharpening-expected-stderr",
+    out: ["art-run-test-552-checker-sharpening-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/552-checker-sharpening/expected.txt b/test/552-checker-sharpening/expected-stderr.txt
similarity index 100%
rename from test/552-checker-sharpening/expected.txt
rename to test/552-checker-sharpening/expected-stderr.txt
diff --git a/test/552-checker-sharpening/expected.txt b/test/552-checker-sharpening/expected-stdout.txt
similarity index 100%
copy from test/552-checker-sharpening/expected.txt
copy to test/552-checker-sharpening/expected-stdout.txt
diff --git a/test/552-checker-x86-avx2-bit-manipulation/Android.bp b/test/552-checker-x86-avx2-bit-manipulation/Android.bp
new file mode 100644
index 0000000..505b631
--- /dev/null
+++ b/test/552-checker-x86-avx2-bit-manipulation/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `552-checker-x86-avx2-bit-manipulation`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-552-checker-x86-avx2-bit-manipulation",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-552-checker-x86-avx2-bit-manipulation-expected-stdout",
+        ":art-run-test-552-checker-x86-avx2-bit-manipulation-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-552-checker-x86-avx2-bit-manipulation-expected-stdout",
+    out: ["art-run-test-552-checker-x86-avx2-bit-manipulation-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-552-checker-x86-avx2-bit-manipulation-expected-stderr",
+    out: ["art-run-test-552-checker-x86-avx2-bit-manipulation-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/552-checker-x86-avx2-bit-manipulation/expected.txt b/test/552-checker-x86-avx2-bit-manipulation/expected-stderr.txt
similarity index 100%
rename from test/552-checker-x86-avx2-bit-manipulation/expected.txt
rename to test/552-checker-x86-avx2-bit-manipulation/expected-stderr.txt
diff --git a/test/552-checker-x86-avx2-bit-manipulation/expected.txt b/test/552-checker-x86-avx2-bit-manipulation/expected-stdout.txt
similarity index 100%
copy from test/552-checker-x86-avx2-bit-manipulation/expected.txt
copy to test/552-checker-x86-avx2-bit-manipulation/expected-stdout.txt
diff --git a/test/552-invoke-non-existent-super/expected.txt b/test/552-invoke-non-existent-super/expected-stderr.txt
similarity index 100%
rename from test/552-invoke-non-existent-super/expected.txt
rename to test/552-invoke-non-existent-super/expected-stderr.txt
diff --git a/test/552-invoke-non-existent-super/expected.txt b/test/552-invoke-non-existent-super/expected-stdout.txt
similarity index 100%
copy from test/552-invoke-non-existent-super/expected.txt
copy to test/552-invoke-non-existent-super/expected-stdout.txt
diff --git a/test/553-invoke-super/expected.txt b/test/553-invoke-super/expected-stderr.txt
similarity index 100%
rename from test/553-invoke-super/expected.txt
rename to test/553-invoke-super/expected-stderr.txt
diff --git a/test/553-invoke-super/expected.txt b/test/553-invoke-super/expected-stdout.txt
similarity index 100%
copy from test/553-invoke-super/expected.txt
copy to test/553-invoke-super/expected-stdout.txt
diff --git a/test/554-checker-rtp-checkcast/Android.bp b/test/554-checker-rtp-checkcast/Android.bp
new file mode 100644
index 0000000..7c4bf6c
--- /dev/null
+++ b/test/554-checker-rtp-checkcast/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `554-checker-rtp-checkcast`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-554-checker-rtp-checkcast",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-554-checker-rtp-checkcast-expected-stdout",
+        ":art-run-test-554-checker-rtp-checkcast-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-554-checker-rtp-checkcast-expected-stdout",
+    out: ["art-run-test-554-checker-rtp-checkcast-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-554-checker-rtp-checkcast-expected-stderr",
+    out: ["art-run-test-554-checker-rtp-checkcast-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/554-checker-rtp-checkcast/expected.txt b/test/554-checker-rtp-checkcast/expected-stderr.txt
similarity index 100%
rename from test/554-checker-rtp-checkcast/expected.txt
rename to test/554-checker-rtp-checkcast/expected-stderr.txt
diff --git a/test/554-checker-rtp-checkcast/expected.txt b/test/554-checker-rtp-checkcast/expected-stdout.txt
similarity index 100%
copy from test/554-checker-rtp-checkcast/expected.txt
copy to test/554-checker-rtp-checkcast/expected-stdout.txt
diff --git a/test/555-UnsafeGetLong-regression/Android.bp b/test/555-UnsafeGetLong-regression/Android.bp
new file mode 100644
index 0000000..8559b4a
--- /dev/null
+++ b/test/555-UnsafeGetLong-regression/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `555-UnsafeGetLong-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-555-UnsafeGetLong-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-555-UnsafeGetLong-regression-expected-stdout",
+        ":art-run-test-555-UnsafeGetLong-regression-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-555-UnsafeGetLong-regression-expected-stdout",
+    out: ["art-run-test-555-UnsafeGetLong-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-555-UnsafeGetLong-regression-expected-stderr",
+    out: ["art-run-test-555-UnsafeGetLong-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/413-regalloc-regression/expected.txt b/test/555-UnsafeGetLong-regression/expected-stderr.txt
similarity index 100%
copy from test/413-regalloc-regression/expected.txt
copy to test/555-UnsafeGetLong-regression/expected-stderr.txt
diff --git a/test/555-UnsafeGetLong-regression/expected.txt b/test/555-UnsafeGetLong-regression/expected-stdout.txt
similarity index 100%
rename from test/555-UnsafeGetLong-regression/expected.txt
rename to test/555-UnsafeGetLong-regression/expected-stdout.txt
diff --git a/test/556-invoke-super/expected.txt b/test/556-invoke-super/expected-stderr.txt
similarity index 100%
rename from test/556-invoke-super/expected.txt
rename to test/556-invoke-super/expected-stderr.txt
diff --git a/test/556-invoke-super/expected.txt b/test/556-invoke-super/expected-stdout.txt
similarity index 100%
copy from test/556-invoke-super/expected.txt
copy to test/556-invoke-super/expected-stdout.txt
diff --git a/test/557-checker-instruct-simplifier-ror/Android.bp b/test/557-checker-instruct-simplifier-ror/Android.bp
new file mode 100644
index 0000000..a424b8a
--- /dev/null
+++ b/test/557-checker-instruct-simplifier-ror/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `557-checker-instruct-simplifier-ror`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-557-checker-instruct-simplifier-ror",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-557-checker-instruct-simplifier-ror-expected-stdout",
+        ":art-run-test-557-checker-instruct-simplifier-ror-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-557-checker-instruct-simplifier-ror-expected-stdout",
+    out: ["art-run-test-557-checker-instruct-simplifier-ror-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-557-checker-instruct-simplifier-ror-expected-stderr",
+    out: ["art-run-test-557-checker-instruct-simplifier-ror-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/557-checker-instruct-simplifier-ror/expected.txt b/test/557-checker-instruct-simplifier-ror/expected-stderr.txt
similarity index 100%
rename from test/557-checker-instruct-simplifier-ror/expected.txt
rename to test/557-checker-instruct-simplifier-ror/expected-stderr.txt
diff --git a/test/557-checker-instruct-simplifier-ror/expected.txt b/test/557-checker-instruct-simplifier-ror/expected-stdout.txt
similarity index 100%
copy from test/557-checker-instruct-simplifier-ror/expected.txt
copy to test/557-checker-instruct-simplifier-ror/expected-stdout.txt
diff --git a/test/557-checker-instruct-simplifier-ror/src/Main.java b/test/557-checker-instruct-simplifier-ror/src/Main.java
index 3631353..5d4bb7a 100644
--- a/test/557-checker-instruct-simplifier-ror/src/Main.java
+++ b/test/557-checker-instruct-simplifier-ror/src/Main.java
@@ -28,84 +28,6 @@
     }
   }
 
-  /// CHECK-START: int Main.rotateIntegerRight(int, int) instruction_simplifier (before)
-  /// CHECK:          <<ArgValue:i\d+>>     ParameterValue
-  /// CHECK:          <<ArgDistance:i\d+>>  ParameterValue
-  /// CHECK:          <<Invoke:i\d+>>       InvokeStaticOrDirect intrinsic:IntegerRotateRight
-
-  /// CHECK-START: int Main.rotateIntegerRight(int, int) instruction_simplifier (after)
-  /// CHECK:          <<ArgValue:i\d+>>     ParameterValue
-  /// CHECK:          <<ArgDistance:i\d+>>  ParameterValue
-  /// CHECK:          <<Ror:i\d+>>          Ror [<<ArgValue>>,<<ArgDistance>>]
-  /// CHECK:                                Return [<<Ror>>]
-
-  /// CHECK-START: int Main.rotateIntegerRight(int, int) instruction_simplifier (after)
-  /// CHECK-NOT:      LoadClass
-  /// CHECK-NOT:      ClinitCheck
-  /// CHECK-NOT:      InvokeStaticOrDirect
-  public static int rotateIntegerRight(int value, int distance) {
-    return java.lang.Integer.rotateRight(value, distance);
-  }
-
-  /// CHECK-START: int Main.rotateIntegerLeft(int, int) instruction_simplifier (before)
-  /// CHECK:          <<ArgValue:i\d+>>     ParameterValue
-  /// CHECK:          <<ArgDistance:i\d+>>  ParameterValue
-  /// CHECK:          <<Invoke:i\d+>>       InvokeStaticOrDirect intrinsic:IntegerRotateLeft
-
-  /// CHECK-START: int Main.rotateIntegerLeft(int, int) instruction_simplifier (after)
-  /// CHECK:          <<ArgValue:i\d+>>     ParameterValue
-  /// CHECK:          <<ArgDistance:i\d+>>  ParameterValue
-  /// CHECK:          <<Neg:i\d+>>          Neg [<<ArgDistance>>]
-  /// CHECK:          <<Ror:i\d+>>          Ror [<<ArgValue>>,<<Neg>>]
-  /// CHECK:                                Return [<<Ror>>]
-
-  /// CHECK-START: int Main.rotateIntegerLeft(int, int) instruction_simplifier (after)
-  /// CHECK-NOT:      LoadClass
-  /// CHECK-NOT:      ClinitCheck
-  /// CHECK-NOT:      InvokeStaticOrDirect
-  public static int rotateIntegerLeft(int value, int distance) {
-    return java.lang.Integer.rotateLeft(value, distance);
-  }
-
-  /// CHECK-START: long Main.rotateLongRight(long, int) instruction_simplifier (before)
-  /// CHECK:          <<ArgValue:j\d+>>     ParameterValue
-  /// CHECK:          <<ArgDistance:i\d+>>  ParameterValue
-  /// CHECK:          <<Invoke:j\d+>>       InvokeStaticOrDirect intrinsic:LongRotateRight
-
-  /// CHECK-START: long Main.rotateLongRight(long, int) instruction_simplifier (after)
-  /// CHECK:          <<ArgValue:j\d+>>     ParameterValue
-  /// CHECK:          <<ArgDistance:i\d+>>  ParameterValue
-  /// CHECK:          <<Ror:j\d+>>          Ror [<<ArgValue>>,<<ArgDistance>>]
-  /// CHECK:                                Return [<<Ror>>]
-
-  /// CHECK-START: long Main.rotateLongRight(long, int) instruction_simplifier (after)
-  /// CHECK-NOT:      LoadClass
-  /// CHECK-NOT:      ClinitCheck
-  /// CHECK-NOT:      InvokeStaticOrDirect
-  public static long rotateLongRight(long value, int distance) {
-    return java.lang.Long.rotateRight(value, distance);
-  }
-
-  /// CHECK-START: long Main.rotateLongLeft(long, int) instruction_simplifier (before)
-  /// CHECK:          <<ArgValue:j\d+>>     ParameterValue
-  /// CHECK:          <<ArgDistance:i\d+>>  ParameterValue
-  /// CHECK:          <<Invoke:j\d+>>       InvokeStaticOrDirect intrinsic:LongRotateLeft
-
-  /// CHECK-START: long Main.rotateLongLeft(long, int) instruction_simplifier (after)
-  /// CHECK:          <<ArgValue:j\d+>>     ParameterValue
-  /// CHECK:          <<ArgDistance:i\d+>>  ParameterValue
-  /// CHECK:          <<Neg:i\d+>>          Neg [<<ArgDistance>>]
-  /// CHECK:          <<Ror:j\d+>>          Ror [<<ArgValue>>,<<Neg>>]
-  /// CHECK:                                Return [<<Ror>>]
-
-  /// CHECK-START: long Main.rotateLongLeft(long, int) instruction_simplifier (after)
-  /// CHECK-NOT:      LoadClass
-  /// CHECK-NOT:      ClinitCheck
-  /// CHECK-NOT:      InvokeStaticOrDirect
-  public static long rotateLongLeft(long value, int distance) {
-    return java.lang.Long.rotateLeft(value, distance);
-  }
-
   //  (i >>> #distance) | (i << #(reg_bits - distance))
 
   /// CHECK-START: int Main.ror_int_constant_c_c(int) instruction_simplifier (before)
diff --git a/test/557-checker-ref-equivalent/expected.txt b/test/557-checker-ref-equivalent/expected-stderr.txt
similarity index 100%
rename from test/557-checker-ref-equivalent/expected.txt
rename to test/557-checker-ref-equivalent/expected-stderr.txt
diff --git a/test/557-checker-ref-equivalent/expected.txt b/test/557-checker-ref-equivalent/expected-stdout.txt
similarity index 100%
copy from test/557-checker-ref-equivalent/expected.txt
copy to test/557-checker-ref-equivalent/expected-stdout.txt
diff --git a/test/558-switch/Android.bp b/test/558-switch/Android.bp
new file mode 100644
index 0000000..7c7ffdd
--- /dev/null
+++ b/test/558-switch/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `558-switch`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-558-switch",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-558-switch-expected-stdout",
+        ":art-run-test-558-switch-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-558-switch-expected-stdout",
+    out: ["art-run-test-558-switch-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-558-switch-expected-stderr",
+    out: ["art-run-test-558-switch-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/558-switch/expected.txt b/test/558-switch/expected-stderr.txt
similarity index 100%
rename from test/558-switch/expected.txt
rename to test/558-switch/expected-stderr.txt
diff --git a/test/558-switch/expected.txt b/test/558-switch/expected-stdout.txt
similarity index 100%
copy from test/558-switch/expected.txt
copy to test/558-switch/expected-stdout.txt
diff --git a/test/559-bce-ssa/Android.bp b/test/559-bce-ssa/Android.bp
new file mode 100644
index 0000000..025c7fe
--- /dev/null
+++ b/test/559-bce-ssa/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `559-bce-ssa`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-559-bce-ssa",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-559-bce-ssa-expected-stdout",
+        ":art-run-test-559-bce-ssa-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-559-bce-ssa-expected-stdout",
+    out: ["art-run-test-559-bce-ssa-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-559-bce-ssa-expected-stderr",
+    out: ["art-run-test-559-bce-ssa-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/559-bce-ssa/expected.txt b/test/559-bce-ssa/expected-stderr.txt
similarity index 100%
rename from test/559-bce-ssa/expected.txt
rename to test/559-bce-ssa/expected-stderr.txt
diff --git a/test/559-bce-ssa/expected.txt b/test/559-bce-ssa/expected-stdout.txt
similarity index 100%
copy from test/559-bce-ssa/expected.txt
copy to test/559-bce-ssa/expected-stdout.txt
diff --git a/test/559-checker-rtp-ifnotnull/expected.txt b/test/559-checker-irreducible-loop/expected-stderr.txt
similarity index 100%
copy from test/559-checker-rtp-ifnotnull/expected.txt
copy to test/559-checker-irreducible-loop/expected-stderr.txt
diff --git a/test/559-checker-irreducible-loop/expected.txt b/test/559-checker-irreducible-loop/expected-stdout.txt
similarity index 100%
rename from test/559-checker-irreducible-loop/expected.txt
rename to test/559-checker-irreducible-loop/expected-stdout.txt
diff --git a/test/559-checker-rtp-ifnotnull/Android.bp b/test/559-checker-rtp-ifnotnull/Android.bp
new file mode 100644
index 0000000..68bcb7e
--- /dev/null
+++ b/test/559-checker-rtp-ifnotnull/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `559-checker-rtp-ifnotnull`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-559-checker-rtp-ifnotnull",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-559-checker-rtp-ifnotnull-expected-stdout",
+        ":art-run-test-559-checker-rtp-ifnotnull-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-559-checker-rtp-ifnotnull-expected-stdout",
+    out: ["art-run-test-559-checker-rtp-ifnotnull-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-559-checker-rtp-ifnotnull-expected-stderr",
+    out: ["art-run-test-559-checker-rtp-ifnotnull-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/559-checker-rtp-ifnotnull/expected.txt b/test/559-checker-rtp-ifnotnull/expected-stderr.txt
similarity index 100%
rename from test/559-checker-rtp-ifnotnull/expected.txt
rename to test/559-checker-rtp-ifnotnull/expected-stderr.txt
diff --git a/test/559-checker-rtp-ifnotnull/expected.txt b/test/559-checker-rtp-ifnotnull/expected-stdout.txt
similarity index 100%
copy from test/559-checker-rtp-ifnotnull/expected.txt
copy to test/559-checker-rtp-ifnotnull/expected-stdout.txt
diff --git a/test/560-packed-switch/Android.bp b/test/560-packed-switch/Android.bp
new file mode 100644
index 0000000..418aa6d
--- /dev/null
+++ b/test/560-packed-switch/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `560-packed-switch`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-560-packed-switch",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-560-packed-switch-expected-stdout",
+        ":art-run-test-560-packed-switch-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-560-packed-switch-expected-stdout",
+    out: ["art-run-test-560-packed-switch-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-560-packed-switch-expected-stderr",
+    out: ["art-run-test-560-packed-switch-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/560-packed-switch/expected.txt b/test/560-packed-switch/expected-stderr.txt
similarity index 100%
rename from test/560-packed-switch/expected.txt
rename to test/560-packed-switch/expected-stderr.txt
diff --git a/test/560-packed-switch/expected.txt b/test/560-packed-switch/expected-stdout.txt
similarity index 100%
copy from test/560-packed-switch/expected.txt
copy to test/560-packed-switch/expected-stdout.txt
diff --git a/test/561-divrem/Android.bp b/test/561-divrem/Android.bp
new file mode 100644
index 0000000..b07e10e
--- /dev/null
+++ b/test/561-divrem/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `561-divrem`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-561-divrem",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-561-divrem-expected-stdout",
+        ":art-run-test-561-divrem-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-561-divrem-expected-stdout",
+    out: ["art-run-test-561-divrem-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-561-divrem-expected-stderr",
+    out: ["art-run-test-561-divrem-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/561-divrem/expected.txt b/test/561-divrem/expected-stderr.txt
similarity index 100%
rename from test/561-divrem/expected.txt
rename to test/561-divrem/expected-stderr.txt
diff --git a/test/561-divrem/expected.txt b/test/561-divrem/expected-stdout.txt
similarity index 100%
copy from test/561-divrem/expected.txt
copy to test/561-divrem/expected-stdout.txt
diff --git a/test/561-shared-slowpaths/Android.bp b/test/561-shared-slowpaths/Android.bp
new file mode 100644
index 0000000..1058c0c
--- /dev/null
+++ b/test/561-shared-slowpaths/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `561-shared-slowpaths`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-561-shared-slowpaths",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-561-shared-slowpaths-expected-stdout",
+        ":art-run-test-561-shared-slowpaths-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-561-shared-slowpaths-expected-stdout",
+    out: ["art-run-test-561-shared-slowpaths-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-561-shared-slowpaths-expected-stderr",
+    out: ["art-run-test-561-shared-slowpaths-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/561-divrem/expected.txt b/test/561-shared-slowpaths/expected-stderr.txt
similarity index 100%
copy from test/561-divrem/expected.txt
copy to test/561-shared-slowpaths/expected-stderr.txt
diff --git a/test/561-shared-slowpaths/expected.txt b/test/561-shared-slowpaths/expected-stdout.txt
similarity index 100%
rename from test/561-shared-slowpaths/expected.txt
rename to test/561-shared-slowpaths/expected-stdout.txt
diff --git a/test/562-bce-preheader/Android.bp b/test/562-bce-preheader/Android.bp
new file mode 100644
index 0000000..d7c9792
--- /dev/null
+++ b/test/562-bce-preheader/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `562-bce-preheader`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-562-bce-preheader",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-562-bce-preheader-expected-stdout",
+        ":art-run-test-562-bce-preheader-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-562-bce-preheader-expected-stdout",
+    out: ["art-run-test-562-bce-preheader-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-562-bce-preheader-expected-stderr",
+    out: ["art-run-test-562-bce-preheader-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/429-ssa-builder/expected.txt b/test/562-bce-preheader/expected-stderr.txt
similarity index 100%
copy from test/429-ssa-builder/expected.txt
copy to test/562-bce-preheader/expected-stderr.txt
diff --git a/test/562-bce-preheader/expected.txt b/test/562-bce-preheader/expected-stdout.txt
similarity index 100%
rename from test/562-bce-preheader/expected.txt
rename to test/562-bce-preheader/expected-stdout.txt
diff --git a/test/562-checker-no-intermediate/Android.bp b/test/562-checker-no-intermediate/Android.bp
new file mode 100644
index 0000000..36a4fd9
--- /dev/null
+++ b/test/562-checker-no-intermediate/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `562-checker-no-intermediate`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-562-checker-no-intermediate",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-562-checker-no-intermediate-expected-stdout",
+        ":art-run-test-562-checker-no-intermediate-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-562-checker-no-intermediate-expected-stdout",
+    out: ["art-run-test-562-checker-no-intermediate-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-562-checker-no-intermediate-expected-stderr",
+    out: ["art-run-test-562-checker-no-intermediate-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/562-checker-no-intermediate/expected.txt b/test/562-checker-no-intermediate/expected-stderr.txt
similarity index 100%
rename from test/562-checker-no-intermediate/expected.txt
rename to test/562-checker-no-intermediate/expected-stderr.txt
diff --git a/test/562-checker-no-intermediate/expected.txt b/test/562-checker-no-intermediate/expected-stdout.txt
similarity index 100%
copy from test/562-checker-no-intermediate/expected.txt
copy to test/562-checker-no-intermediate/expected-stdout.txt
diff --git a/test/563-checker-invoke-super/expected.txt b/test/563-checker-fakestring/expected-stderr.txt
similarity index 100%
copy from test/563-checker-invoke-super/expected.txt
copy to test/563-checker-fakestring/expected-stderr.txt
diff --git a/test/563-checker-fakestring/expected.txt b/test/563-checker-fakestring/expected-stdout.txt
similarity index 100%
rename from test/563-checker-fakestring/expected.txt
rename to test/563-checker-fakestring/expected-stdout.txt
diff --git a/test/563-checker-invoke-super/Android.bp b/test/563-checker-invoke-super/Android.bp
new file mode 100644
index 0000000..1097d85
--- /dev/null
+++ b/test/563-checker-invoke-super/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `563-checker-invoke-super`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-563-checker-invoke-super",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-563-checker-invoke-super-expected-stdout",
+        ":art-run-test-563-checker-invoke-super-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-563-checker-invoke-super-expected-stdout",
+    out: ["art-run-test-563-checker-invoke-super-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-563-checker-invoke-super-expected-stderr",
+    out: ["art-run-test-563-checker-invoke-super-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/563-checker-invoke-super/expected.txt b/test/563-checker-invoke-super/expected-stderr.txt
similarity index 100%
rename from test/563-checker-invoke-super/expected.txt
rename to test/563-checker-invoke-super/expected-stderr.txt
diff --git a/test/563-checker-invoke-super/expected.txt b/test/563-checker-invoke-super/expected-stdout.txt
similarity index 100%
copy from test/563-checker-invoke-super/expected.txt
copy to test/563-checker-invoke-super/expected-stdout.txt
diff --git a/test/564-checker-bitcount/Android.bp b/test/564-checker-bitcount/Android.bp
new file mode 100644
index 0000000..85c81bb
--- /dev/null
+++ b/test/564-checker-bitcount/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `564-checker-bitcount`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-564-checker-bitcount",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-564-checker-bitcount-expected-stdout",
+        ":art-run-test-564-checker-bitcount-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-564-checker-bitcount-expected-stdout",
+    out: ["art-run-test-564-checker-bitcount-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-564-checker-bitcount-expected-stderr",
+    out: ["art-run-test-564-checker-bitcount-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/564-checker-negbitwise/expected.txt b/test/564-checker-bitcount/expected-stderr.txt
similarity index 100%
copy from test/564-checker-negbitwise/expected.txt
copy to test/564-checker-bitcount/expected-stderr.txt
diff --git a/test/564-checker-bitcount/expected.txt b/test/564-checker-bitcount/expected-stdout.txt
similarity index 100%
rename from test/564-checker-bitcount/expected.txt
rename to test/564-checker-bitcount/expected-stdout.txt
diff --git a/test/564-checker-inline-loop/Android.bp b/test/564-checker-inline-loop/Android.bp
new file mode 100644
index 0000000..6f0a159
--- /dev/null
+++ b/test/564-checker-inline-loop/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `564-checker-inline-loop`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-564-checker-inline-loop",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-564-checker-inline-loop-expected-stdout",
+        ":art-run-test-564-checker-inline-loop-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-564-checker-inline-loop-expected-stdout",
+    out: ["art-run-test-564-checker-inline-loop-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-564-checker-inline-loop-expected-stderr",
+    out: ["art-run-test-564-checker-inline-loop-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/564-checker-inline-loop/expected.txt b/test/564-checker-inline-loop/expected-stderr.txt
similarity index 100%
rename from test/564-checker-inline-loop/expected.txt
rename to test/564-checker-inline-loop/expected-stderr.txt
diff --git a/test/564-checker-inline-loop/expected.txt b/test/564-checker-inline-loop/expected-stdout.txt
similarity index 100%
copy from test/564-checker-inline-loop/expected.txt
copy to test/564-checker-inline-loop/expected-stdout.txt
diff --git a/test/564-checker-inline-loop/expected.txt b/test/564-checker-irreducible-loop/expected-stderr.txt
similarity index 100%
copy from test/564-checker-inline-loop/expected.txt
copy to test/564-checker-irreducible-loop/expected-stderr.txt
diff --git a/test/564-checker-irreducible-loop/expected.txt b/test/564-checker-irreducible-loop/expected-stdout.txt
similarity index 100%
rename from test/564-checker-irreducible-loop/expected.txt
rename to test/564-checker-irreducible-loop/expected-stdout.txt
diff --git a/test/564-checker-negbitwise/Android.bp b/test/564-checker-negbitwise/Android.bp
new file mode 100644
index 0000000..8d658a1
--- /dev/null
+++ b/test/564-checker-negbitwise/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `564-checker-negbitwise`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-564-checker-negbitwise",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-564-checker-negbitwise-expected-stdout",
+        ":art-run-test-564-checker-negbitwise-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-564-checker-negbitwise-expected-stdout",
+    out: ["art-run-test-564-checker-negbitwise-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-564-checker-negbitwise-expected-stderr",
+    out: ["art-run-test-564-checker-negbitwise-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/564-checker-negbitwise/expected.txt b/test/564-checker-negbitwise/expected-stderr.txt
similarity index 100%
rename from test/564-checker-negbitwise/expected.txt
rename to test/564-checker-negbitwise/expected-stderr.txt
diff --git a/test/564-checker-negbitwise/expected.txt b/test/564-checker-negbitwise/expected-stdout.txt
similarity index 100%
copy from test/564-checker-negbitwise/expected.txt
copy to test/564-checker-negbitwise/expected-stdout.txt
diff --git a/test/564-checker-negbitwise/src/Main.java b/test/564-checker-negbitwise/src/Main.java
index a047d21..4f8242b 100644
--- a/test/564-checker-negbitwise/src/Main.java
+++ b/test/564-checker-negbitwise/src/Main.java
@@ -16,9 +16,6 @@
 
 public class Main {
 
-  // A dummy value to defeat inlining of these routines.
-  static boolean doThrow = false;
-
   public static void assertIntEquals(int expected, int result) {
     if (expected != result) {
       throw new Error("Expected: " + expected + ", found: " + result);
@@ -77,7 +74,6 @@
   /// CHECK:                            bic r{{\d+}}, r{{\d+}}, r{{\d+}}
 
   public static int $opt$noinline$notAnd(int base, int mask) {
-    if (doThrow) throw new Error();
     return base & ~mask;
   }
 
@@ -127,7 +123,6 @@
   /// CHECK:                            orn r{{\d+}}, r{{\d+}}, r{{\d+}}
 
   public static long $opt$noinline$notOr(long base, long mask) {
-    if (doThrow) throw new Error();
     return base | ~mask;
   }
 
@@ -174,7 +169,6 @@
   /// CHECK-NOT:                        BitwiseNegatedRight
 
   public static int $opt$noinline$notXor(int base, int mask) {
-    if (doThrow) throw new Error();
     return base ^ ~mask;
   }
 
@@ -210,7 +204,6 @@
   /// CHECK:                            Return [<<NegOp>>]
 
   public static int $opt$noinline$notAndConstant(int mask) {
-    if (doThrow) throw new Error();
     return 0xf & ~mask;
   }
 
@@ -266,7 +259,6 @@
   /// CHECK-NOT:                        BitwiseNegatedRight
 
   public static int $opt$noinline$notAndMultipleUses(int base, int mask) {
-    if (doThrow) throw new Error();
     int tmp = ~mask;
     return (tmp & 0x1) + (base & tmp);
   }
@@ -285,7 +277,6 @@
   /// CHECK-NOT:                        BitwiseNegatedRight
 
   public static int $opt$noinline$deMorganOr(int a, int b) {
-    if (doThrow) throw new Error();
     return ~a | ~b;
   }
 
diff --git a/test/565-checker-condition-liveness/Android.bp b/test/565-checker-condition-liveness/Android.bp
new file mode 100644
index 0000000..c70f56a
--- /dev/null
+++ b/test/565-checker-condition-liveness/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `565-checker-condition-liveness`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-565-checker-condition-liveness",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-565-checker-condition-liveness-expected-stdout",
+        ":art-run-test-565-checker-condition-liveness-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-565-checker-condition-liveness-expected-stdout",
+    out: ["art-run-test-565-checker-condition-liveness-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-565-checker-condition-liveness-expected-stderr",
+    out: ["art-run-test-565-checker-condition-liveness-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/565-checker-condition-liveness/expected.txt b/test/565-checker-condition-liveness/expected-stderr.txt
similarity index 100%
rename from test/565-checker-condition-liveness/expected.txt
rename to test/565-checker-condition-liveness/expected-stderr.txt
diff --git a/test/565-checker-condition-liveness/expected.txt b/test/565-checker-condition-liveness/expected-stdout.txt
similarity index 100%
copy from test/565-checker-condition-liveness/expected.txt
copy to test/565-checker-condition-liveness/expected-stdout.txt
diff --git a/test/565-checker-doublenegbitwise/expected.txt b/test/565-checker-doublenegbitwise/expected-stderr.txt
similarity index 100%
rename from test/565-checker-doublenegbitwise/expected.txt
rename to test/565-checker-doublenegbitwise/expected-stderr.txt
diff --git a/test/565-checker-doublenegbitwise/expected.txt b/test/565-checker-doublenegbitwise/expected-stdout.txt
similarity index 100%
copy from test/565-checker-doublenegbitwise/expected.txt
copy to test/565-checker-doublenegbitwise/expected-stdout.txt
diff --git a/test/565-checker-doublenegbitwise/smali/SmaliTests.smali b/test/565-checker-doublenegbitwise/smali/SmaliTests.smali
index ce69154..27412f6 100644
--- a/test/565-checker-doublenegbitwise/smali/SmaliTests.smali
+++ b/test/565-checker-doublenegbitwise/smali/SmaliTests.smali
@@ -46,13 +46,6 @@
     .param p1, "b"    # I
 
     .prologue
-    sget-boolean v0, LSmaliTests;->doThrow:Z
-    if-eqz v0, :cond_a
-    new-instance v0, Ljava/lang/Error;
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-    throw v0
-
-  :cond_a
     # return ~a & ~b;
     not-int v0, p0
     not-int v1, p1
@@ -95,13 +88,6 @@
     .param p1, "b"    # Z
 
     .prologue
-    sget-boolean v0, LSmaliTests;->doThrow:Z
-    if-eqz v0, :cond_a
-    new-instance v0, Ljava/lang/Error;
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-    throw v0
-
-  :cond_a
     # return !a & !b;
     xor-int/lit8 v0, p0, 0x1
     xor-int/lit8 v1, p1, 0x1
@@ -138,13 +124,6 @@
     .param p2, "b"    # J
 
     .prologue
-    sget-boolean v0, LSmaliTests;->doThrow:Z
-    if-eqz v0, :cond_a
-    new-instance v0, Ljava/lang/Error;
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-    throw v0
-
-  :cond_a
     # return ~a | ~b;
     not-long v0, p0
     not-long v2, p2
@@ -186,13 +165,6 @@
     .param p1, "b"    # Z
 
     .prologue
-    sget-boolean v0, LSmaliTests;->doThrow:Z
-    if-eqz v0, :cond_a
-    new-instance v0, Ljava/lang/Error;
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-    throw v0
-
-  :cond_a
     # return !a | !b;
     xor-int/lit8 v0, p0, 0x1
     xor-int/lit8 v1, p1, 0x1
@@ -238,13 +210,6 @@
     .param p1, "b"    # I
 
     .prologue
-    sget-boolean v4, LSmaliTests;->doThrow:Z
-    if-eqz v4, :cond_a
-    new-instance v4, Ljava/lang/Error;
-    invoke-direct {v4}, Ljava/lang/Error;-><init>()V
-    throw v4
-
-  :cond_a
     # int a1 = a + 1;
     add-int/lit8 v0, p0, 0x1
     # int not_a1 = ~a1;
@@ -284,13 +249,6 @@
     .param p1, "b"    # I
 
     .prologue
-    sget-boolean v0, LSmaliTests;->doThrow:Z
-    if-eqz v0, :cond_a
-    new-instance v0, Ljava/lang/Error;
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-    throw v0
-
-  :cond_a
     # return ~a ^ ~b;
     not-int v0, p0
     not-int v1, p1
@@ -327,13 +285,6 @@
     .param p1, "b"    # Z
 
     .prologue
-    sget-boolean v0, LSmaliTests;->doThrow:Z
-    if-eqz v0, :cond_a
-    new-instance v0, Ljava/lang/Error;
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-    throw v0
-
-  :cond_a
     # return !a ^ !b;
     xor-int/lit8 v0, p0, 0x1
     xor-int/lit8 v1, p1, 0x1
@@ -373,13 +324,6 @@
     .param p1, "b"    # I
 
     .prologue
-    sget-boolean v1, LSmaliTests;->doThrow:Z
-    if-eqz v1, :cond_a
-    new-instance v1, Ljava/lang/Error;
-    invoke-direct {v1}, Ljava/lang/Error;-><init>()V
-    throw v1
-
-  :cond_a
     # int tmp = ~b;
     not-int v0, p1
     # return (tmp & 0x1) + (~a & tmp);
@@ -390,20 +334,6 @@
     return v1
 .end method
 
-# static fields
-.field static doThrow:Z # boolean
-
-# direct methods
-.method static constructor <clinit>()V
-    .registers 1
-
-    .prologue
-    # doThrow = false
-    const/4 v0, 0x0
-    sput-boolean v0, LSmaliTests;->doThrow:Z
-    return-void
-.end method
-
 
 # Test transformation of Not/Not/And into Or/Not.
 
@@ -435,7 +365,6 @@
 # Original java source:
 #
 #     public static int $opt$noinline$andToOr(int a, int b) {
-#       if (doThrow) throw new Error();
 #       return ~a & ~b;
 #     }
 
@@ -446,18 +375,6 @@
 
     .prologue
     .line 85
-    sget-boolean v0, LMain;->doThrow:Z
-
-    if-eqz v0, :cond_a
-
-    new-instance v0, Ljava/lang/Error;
-
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-
-    throw v0
-
-    .line 86
-    :cond_a
     xor-int/lit8 v0, p0, -0x1
 
     xor-int/lit8 v1, p1, -0x1
@@ -501,7 +418,6 @@
 # Original java source:
 #
 #     public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) {
-#       if (doThrow) throw new Error();
 #       return !a & !b;
 #     }
 
@@ -516,18 +432,6 @@
     const/4 v1, 0x0
 
     .line 122
-    sget-boolean v2, LMain;->doThrow:Z
-
-    if-eqz v2, :cond_c
-
-    new-instance v0, Ljava/lang/Error;
-
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-
-    throw v0
-
-    .line 123
-    :cond_c
     if-nez p0, :cond_13
 
     move v2, v0
@@ -582,7 +486,6 @@
 # Original java source:
 #
 #     public static long $opt$noinline$orToAnd(long a, long b) {
-#       if (doThrow) throw new Error();
 #       return ~a | ~b;
 #     }
 
@@ -595,18 +498,6 @@
     const-wide/16 v2, -0x1
 
     .line 156
-    sget-boolean v0, LMain;->doThrow:Z
-
-    if-eqz v0, :cond_c
-
-    new-instance v0, Ljava/lang/Error;
-
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-
-    throw v0
-
-    .line 157
-    :cond_c
     xor-long v0, p0, v2
 
     xor-long/2addr v2, p2
@@ -649,7 +540,6 @@
 # Original java source:
 #
 #     public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) {
-#       if (doThrow) throw new Error();
 #       return !a | !b;
 #     }
 
@@ -664,18 +554,6 @@
     const/4 v1, 0x0
 
     .line 193
-    sget-boolean v2, LMain;->doThrow:Z
-
-    if-eqz v2, :cond_c
-
-    new-instance v0, Ljava/lang/Error;
-
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-
-    throw v0
-
-    .line 194
-    :cond_c
     if-nez p0, :cond_13
 
     move v2, v0
@@ -737,7 +615,6 @@
 # Original java source:
 #
 #     public static int $opt$noinline$regressInputsAway(int a, int b) {
-#       if (doThrow) throw new Error();
 #       int a1 = a + 1;
 #       int not_a1 = ~a1;
 #       int b1 = b + 1;
@@ -752,18 +629,6 @@
 
     .prologue
     .line 234
-    sget-boolean v4, LMain;->doThrow:Z
-
-    if-eqz v4, :cond_a
-
-    new-instance v4, Ljava/lang/Error;
-
-    invoke-direct {v4}, Ljava/lang/Error;-><init>()V
-
-    throw v4
-
-    .line 235
-    :cond_a
     add-int/lit8 v0, p0, 0x1
 
     .line 236
@@ -810,7 +675,6 @@
 # Original java source:
 #
 #     public static int $opt$noinline$notXorToXor(int a, int b) {
-#       if (doThrow) throw new Error();
 #       return ~a ^ ~b;
 #     }
 
@@ -821,18 +685,6 @@
 
     .prologue
     .line 266
-    sget-boolean v0, LMain;->doThrow:Z
-
-    if-eqz v0, :cond_a
-
-    new-instance v0, Ljava/lang/Error;
-
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-
-    throw v0
-
-    .line 267
-    :cond_a
     xor-int/lit8 v0, p0, -0x1
 
     xor-int/lit8 v1, p1, -0x1
@@ -871,7 +723,6 @@
 # Original java source:
 #
 #     public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) {
-#       if (doThrow) throw new Error();
 #       return !a ^ !b;
 #     }
 
@@ -886,18 +737,6 @@
     const/4 v1, 0x0
 
     .line 298
-    sget-boolean v2, LMain;->doThrow:Z
-
-    if-eqz v2, :cond_c
-
-    new-instance v0, Ljava/lang/Error;
-
-    invoke-direct {v0}, Ljava/lang/Error;-><init>()V
-
-    throw v0
-
-    .line 299
-    :cond_c
     if-nez p0, :cond_13
 
     move v2, v0
@@ -953,7 +792,6 @@
 # Original java source:
 #
 #     public static int $opt$noinline$notMultipleUses(int a, int b) {
-#       if (doThrow) throw new Error();
 #       int tmp = ~b;
 #       return (tmp & 0x1) + (~a & tmp);
 #     }
@@ -965,18 +803,6 @@
 
     .prologue
     .line 333
-    sget-boolean v1, LMain;->doThrow:Z
-
-    if-eqz v1, :cond_a
-
-    new-instance v1, Ljava/lang/Error;
-
-    invoke-direct {v1}, Ljava/lang/Error;-><init>()V
-
-    throw v1
-
-    .line 334
-    :cond_a
     xor-int/lit8 v0, p1, -0x1
 
     .line 335
diff --git a/test/565-checker-doublenegbitwise/src/Main.java b/test/565-checker-doublenegbitwise/src/Main.java
index 5121569..39ee0ce 100644
--- a/test/565-checker-doublenegbitwise/src/Main.java
+++ b/test/565-checker-doublenegbitwise/src/Main.java
@@ -18,9 +18,6 @@
 
 public class Main {
 
-  // A dummy value to defeat inlining of these routines.
-  static boolean doThrow = false;
-
   public static void assertIntEquals(int expected, int result) {
     if (expected != result) {
       throw new Error("Expected: " + expected + ", found: " + result);
@@ -40,8 +37,6 @@
   }
 
   public static <T> T $noinline$runSmaliTest(String name, Class<T> klass, T input1, T input2) {
-    if (doThrow) { throw new Error(); }
-
     Class<T> inputKlass = (Class<T>)input1.getClass();
     try {
       Class<?> c = Class.forName("SmaliTests");
diff --git a/test/565-checker-doublenegbitwise/expected.txt b/test/565-checker-irreducible-loop/expected-stderr.txt
similarity index 100%
copy from test/565-checker-doublenegbitwise/expected.txt
copy to test/565-checker-irreducible-loop/expected-stderr.txt
diff --git a/test/565-checker-irreducible-loop/expected.txt b/test/565-checker-irreducible-loop/expected-stdout.txt
similarity index 100%
rename from test/565-checker-irreducible-loop/expected.txt
rename to test/565-checker-irreducible-loop/expected-stdout.txt
diff --git a/test/565-checker-rotate/expected.txt b/test/565-checker-rotate/expected.txt
deleted file mode 100644
index b0aad4d..0000000
--- a/test/565-checker-rotate/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-passed
diff --git a/test/565-checker-rotate/info.txt b/test/565-checker-rotate/info.txt
deleted file mode 100644
index c6a8091..0000000
--- a/test/565-checker-rotate/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Unit test for 32-bit and 64-bit rotate operations.
diff --git a/test/565-checker-rotate/smali/Main2.smali b/test/565-checker-rotate/smali/Main2.smali
deleted file mode 100644
index 768c9d0..0000000
--- a/test/565-checker-rotate/smali/Main2.smali
+++ /dev/null
@@ -1,163 +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.
-
-.class public LMain2;
-.super Ljava/lang/Object;
-
-## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) builder (after)
-## CHECK:         <<ArgVal:z\d+>>  ParameterValue
-## CHECK:         <<ArgDist:i\d+>> ParameterValue
-## CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
-## CHECK-DAG:     <<One:i\d+>>     IntConstant 1
-## CHECK-DAG:     <<Val:i\d+>>     Phi [<<One>>,<<Zero>>]
-## CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<Val>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
-## CHECK-DAG:                      Return [<<Result>>]
-
-## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) instruction_simplifier (after)
-## CHECK:         <<ArgVal:z\d+>>  ParameterValue
-## CHECK:         <<ArgDist:i\d+>> ParameterValue
-## CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
-## CHECK-DAG:     <<One:i\d+>>     IntConstant 1
-## CHECK-DAG:     <<Val:i\d+>>     Phi [<<One>>,<<Zero>>]
-## CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
-## CHECK-DAG:     <<Result:i\d+>>  Ror [<<Val>>,<<NegDist>>]
-## CHECK-DAG:                      Return [<<Result>>]
-
-## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) instruction_simplifier (after)
-## CHECK-NOT:                      InvokeStaticOrDirect
-
-## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) select_generator (after)
-## CHECK:         <<ArgVal:z\d+>>  ParameterValue
-## CHECK:         <<ArgDist:i\d+>> ParameterValue
-## CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
-## CHECK-DAG:     <<One:i\d+>>     IntConstant 1
-## CHECK-DAG:     <<SelVal:i\d+>>  Select [<<Zero>>,<<One>>,<<ArgVal>>]
-## CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
-## CHECK-DAG:     <<Result:i\d+>>  Ror [<<SelVal>>,<<NegDist>>]
-## CHECK-DAG:                      Return [<<Result>>]
-
-## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) select_generator (after)
-## CHECK-NOT:                      Phi
-
-## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) instruction_simplifier$after_bce (after)
-## CHECK:         <<ArgVal:z\d+>>  ParameterValue
-## CHECK:         <<ArgDist:i\d+>> ParameterValue
-## CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
-## CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
-## CHECK-DAG:                      Return [<<Result>>]
-
-## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) instruction_simplifier$after_bce (after)
-## CHECK-NOT:                      Select
-
-# Original java source
-#
-#     private static int rotateLeftBoolean(boolean value, int distance) {
-#       return Integer.rotateLeft(value ? 1 : 0, distance);
-#     }
-
-.method public static rotateLeftBoolean(ZI)I
-    .registers 3
-    .param p0, "value"    # Z
-    .param p1, "distance"    # I
-
-    .prologue
-    .line 66
-    if-eqz p0, :cond_8
-
-    const/4 v0, 0x1
-
-    :goto_3
-    invoke-static {v0, p1}, Ljava/lang/Integer;->rotateLeft(II)I
-
-    move-result v0
-
-    return v0
-
-    :cond_8
-    const/4 v0, 0x0
-
-    goto :goto_3
-.end method
-
-## CHECK-START: int Main2.rotateRightBoolean(boolean, int) builder (after)
-## CHECK:         <<ArgVal:z\d+>>  ParameterValue
-## CHECK:         <<ArgDist:i\d+>> ParameterValue
-## CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
-## CHECK-DAG:     <<One:i\d+>>     IntConstant 1
-## CHECK-DAG:     <<Val:i\d+>>     Phi [<<One>>,<<Zero>>]
-## CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<Val>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
-## CHECK-DAG:                      Return [<<Result>>]
-
-## CHECK-START: int Main2.rotateRightBoolean(boolean, int) instruction_simplifier (after)
-## CHECK:         <<ArgVal:z\d+>>  ParameterValue
-## CHECK:         <<ArgDist:i\d+>> ParameterValue
-## CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
-## CHECK-DAG:     <<One:i\d+>>     IntConstant 1
-## CHECK-DAG:     <<Val:i\d+>>     Phi [<<One>>,<<Zero>>]
-## CHECK-DAG:     <<Result:i\d+>>  Ror [<<Val>>,<<ArgDist>>]
-## CHECK-DAG:                      Return [<<Result>>]
-
-## CHECK-START: int Main2.rotateRightBoolean(boolean, int) instruction_simplifier (after)
-## CHECK-NOT:                      InvokeStaticOrDirect
-
-## CHECK-START: int Main2.rotateRightBoolean(boolean, int) select_generator (after)
-## CHECK:         <<ArgVal:z\d+>>  ParameterValue
-## CHECK:         <<ArgDist:i\d+>> ParameterValue
-## CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
-## CHECK-DAG:     <<One:i\d+>>     IntConstant 1
-## CHECK-DAG:     <<SelVal:i\d+>>  Select [<<Zero>>,<<One>>,<<ArgVal>>]
-## CHECK-DAG:     <<Result:i\d+>>  Ror [<<SelVal>>,<<ArgDist>>]
-## CHECK-DAG:                      Return [<<Result>>]
-
-## CHECK-START: int Main2.rotateRightBoolean(boolean, int) select_generator (after)
-## CHECK-NOT:                     Phi
-
-## CHECK-START: int Main2.rotateRightBoolean(boolean, int) instruction_simplifier$after_bce (after)
-## CHECK:         <<ArgVal:z\d+>>  ParameterValue
-## CHECK:         <<ArgDist:i\d+>> ParameterValue
-## CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
-## CHECK-DAG:                      Return [<<Result>>]
-
-## CHECK-START: int Main2.rotateRightBoolean(boolean, int) instruction_simplifier$after_bce (after)
-## CHECK-NOT:                     Select
-
-# Original java source:
-#
-#     private static int rotateRightBoolean(boolean value, int distance) {
-#       return Integer.rotateRight(value ? 1 : 0, distance);
-#     }
-
-.method public static rotateRightBoolean(ZI)I
-    .registers 3
-    .param p0, "value"    # Z
-    .param p1, "distance"    # I
-
-    .prologue
-    .line 219
-    if-eqz p0, :cond_8
-
-    const/4 v0, 0x1
-
-    :goto_3
-    invoke-static {v0, p1}, Ljava/lang/Integer;->rotateRight(II)I
-
-    move-result v0
-
-    return v0
-
-    :cond_8
-    const/4 v0, 0x0
-
-    goto :goto_3
-.end method
diff --git a/test/565-checker-rotate/src-art/Main.java b/test/565-checker-rotate/src-art/Main.java
deleted file mode 100644
index 867feb8..0000000
--- a/test/565-checker-rotate/src-art/Main.java
+++ /dev/null
@@ -1,534 +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.
- */
-
-import java.lang.reflect.Method;
-
-public class Main {
-
-  private static Class main2;
-
-  /// CHECK-START: int Main.rotateLeftByte(byte, int) builder (after)
-  /// CHECK:         <<ArgVal:b\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateLeftByte(byte, int) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:b\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
-  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateLeftByte(byte, int) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static int rotateLeftByte(byte value, int distance) {
-    return Integer.rotateLeft(value, distance);
-  }
-
-  /// CHECK-START: int Main.rotateLeftShort(short, int) builder (after)
-  /// CHECK:         <<ArgVal:s\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateLeftShort(short, int) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:s\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
-  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateLeftShort(short, int) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static int rotateLeftShort(short value, int distance) {
-    return Integer.rotateLeft(value, distance);
-  }
-
-  /// CHECK-START: int Main.rotateLeftChar(char, int) builder (after)
-  /// CHECK:         <<ArgVal:c\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateLeftChar(char, int) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:c\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
-  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateLeftChar(char, int) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static int rotateLeftChar(char value, int distance) {
-    return Integer.rotateLeft(value, distance);
-  }
-
-  /// CHECK-START: int Main.rotateLeftInt(int, int) builder (after)
-  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateLeftInt(int, int) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
-  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateLeftInt(int, int) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static int rotateLeftInt(int value, int distance) {
-    return Integer.rotateLeft(value, distance);
-  }
-
-  /// CHECK-START: long Main.rotateLeftLong(long, int) builder (after)
-  /// CHECK:         <<ArgVal:j\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:j\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:LongRotateLeft
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: long Main.rotateLeftLong(long, int) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:j\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
-  /// CHECK-DAG:     <<Result:j\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: long Main.rotateLeftLong(long, int) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static long rotateLeftLong(long value, int distance) {
-    return Long.rotateLeft(value, distance);
-  }
-
-  /// CHECK-START: int Main.rotateRightByte(byte, int) builder (after)
-  /// CHECK:         <<ArgVal:b\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateRightByte(byte, int) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:b\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateRightByte(byte, int) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static int rotateRightByte(byte value, int distance) {
-    return Integer.rotateRight(value, distance);
-  }
-
-  /// CHECK-START: int Main.rotateRightShort(short, int) builder (after)
-  /// CHECK:         <<ArgVal:s\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateRightShort(short, int) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:s\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateRightShort(short, int) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static int rotateRightShort(short value, int distance) {
-    return Integer.rotateRight(value, distance);
-  }
-
-  /// CHECK-START: int Main.rotateRightChar(char, int) builder (after)
-  /// CHECK:         <<ArgVal:c\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateRightChar(char, int) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:c\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateRightChar(char, int) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static int rotateRightChar(char value, int distance) {
-    return Integer.rotateRight(value, distance);
-  }
-
-  /// CHECK-START: int Main.rotateRightInt(int, int) builder (after)
-  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateRightInt(int, int) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateRightInt(int, int) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static int rotateRightInt(int value, int distance) {
-    return Integer.rotateRight(value, distance);
-  }
-
-  /// CHECK-START: long Main.rotateRightLong(long, int) builder (after)
-  /// CHECK:         <<ArgVal:j\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:j\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:LongRotateRight
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: long Main.rotateRightLong(long, int) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:j\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:j\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: long Main.rotateRightLong(long, int) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static long rotateRightLong(long value, int distance) {
-    return Long.rotateRight(value, distance);
-  }
-
-
-  /// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) builder (after)
-  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:b\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateLeft
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:b\d+>> ParameterValue
-  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
-  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static int rotateLeftIntWithByteDistance(int value, byte distance) {
-    return Integer.rotateLeft(value, distance);
-  }
-
-  /// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) builder (after)
-  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:b\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>{{(,[ij]\d+)?}}] intrinsic:IntegerRotateRight
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) instruction_simplifier (after)
-  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
-  /// CHECK:         <<ArgDist:b\d+>> ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
-  /// CHECK-DAG:                      Return [<<Result>>]
-
-  /// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) instruction_simplifier (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  private static int rotateRightIntWithByteDistance(int value, byte distance) {
-    return Integer.rotateRight(value, distance);
-  }
-
-
-  public static void testRotateLeftBoolean() throws Exception {
-    Method rotateLeftBoolean = main2.getMethod("rotateLeftBoolean", boolean.class, int.class);
-    for (int i = 0; i < 40; i++) {  // overshoot a bit
-      int j = i & 31;
-      expectEqualsInt(0, (int)rotateLeftBoolean.invoke(null, false, i));
-      expectEqualsInt(1 << i, (int)rotateLeftBoolean.invoke(null, true, i));
-    }
-  }
-
-  public static void testRotateLeftByte() {
-    expectEqualsInt(0x00000001, rotateLeftByte((byte)0x01, 0));
-    expectEqualsInt(0x00000002, rotateLeftByte((byte)0x01, 1));
-    expectEqualsInt(0x80000000, rotateLeftByte((byte)0x01, 31));
-    expectEqualsInt(0x00000001, rotateLeftByte((byte)0x01, 32));  // overshoot
-    expectEqualsInt(0xFFFFFF03, rotateLeftByte((byte)0x81, 1));
-    expectEqualsInt(0xFFFFFE07, rotateLeftByte((byte)0x81, 2));
-    expectEqualsInt(0x00000120, rotateLeftByte((byte)0x12, 4));
-    expectEqualsInt(0xFFFF9AFF, rotateLeftByte((byte)0x9A, 8));
-    for (int i = 0; i < 40; i++) {  // overshoot a bit
-      int j = i & 31;
-      expectEqualsInt(0x00000000, rotateLeftByte((byte)0x0000, i));
-      expectEqualsInt(0xFFFFFFFF, rotateLeftByte((byte)0xFFFF, i));
-      expectEqualsInt((1 << j), rotateLeftByte((byte)0x0001, i));
-      expectEqualsInt((0x12 << j) | (0x12 >>> -j), rotateLeftByte((byte)0x12, i));
-    }
-  }
-
-  public static void testRotateLeftShort() {
-    expectEqualsInt(0x00000001, rotateLeftShort((short)0x0001, 0));
-    expectEqualsInt(0x00000002, rotateLeftShort((short)0x0001, 1));
-    expectEqualsInt(0x80000000, rotateLeftShort((short)0x0001, 31));
-    expectEqualsInt(0x00000001, rotateLeftShort((short)0x0001, 32));  // overshoot
-    expectEqualsInt(0xFFFF0003, rotateLeftShort((short)0x8001, 1));
-    expectEqualsInt(0xFFFE0007, rotateLeftShort((short)0x8001, 2));
-    expectEqualsInt(0x00012340, rotateLeftShort((short)0x1234, 4));
-    expectEqualsInt(0xFF9ABCFF, rotateLeftShort((short)0x9ABC, 8));
-    for (int i = 0; i < 40; i++) {  // overshoot a bit
-      int j = i & 31;
-      expectEqualsInt(0x00000000, rotateLeftShort((short)0x0000, i));
-      expectEqualsInt(0xFFFFFFFF, rotateLeftShort((short)0xFFFF, i));
-      expectEqualsInt((1 << j), rotateLeftShort((short)0x0001, i));
-      expectEqualsInt((0x1234 << j) | (0x1234 >>> -j), rotateLeftShort((short)0x1234, i));
-    }
-  }
-
-  public static void testRotateLeftChar() {
-    expectEqualsInt(0x00000001, rotateLeftChar((char)0x0001, 0));
-    expectEqualsInt(0x00000002, rotateLeftChar((char)0x0001, 1));
-    expectEqualsInt(0x80000000, rotateLeftChar((char)0x0001, 31));
-    expectEqualsInt(0x00000001, rotateLeftChar((char)0x0001, 32));  // overshoot
-    expectEqualsInt(0x00010002, rotateLeftChar((char)0x8001, 1));
-    expectEqualsInt(0x00020004, rotateLeftChar((char)0x8001, 2));
-    expectEqualsInt(0x00012340, rotateLeftChar((char)0x1234, 4));
-    expectEqualsInt(0x009ABC00, rotateLeftChar((char)0x9ABC, 8));
-    expectEqualsInt(0x00FF0000, rotateLeftChar((char)0xFF00, 8));
-    for (int i = 0; i < 40; i++) {  // overshoot a bit
-      int j = i & 31;
-      expectEqualsInt(0x00000000, rotateLeftChar((char)0x0000, i));
-      expectEqualsInt((1 << j), rotateLeftChar((char)0x0001, i));
-      expectEqualsInt((0x1234 << j) | (0x1234 >>> -j), rotateLeftChar((char)0x1234, i));
-    }
-  }
-
-  public static void testRotateLeftInt() {
-    expectEqualsInt(0x00000001, rotateLeftInt(0x00000001, 0));
-    expectEqualsInt(0x00000002, rotateLeftInt(0x00000001, 1));
-    expectEqualsInt(0x80000000, rotateLeftInt(0x00000001, 31));
-    expectEqualsInt(0x00000001, rotateLeftInt(0x00000001, 32));  // overshoot
-    expectEqualsInt(0x00000003, rotateLeftInt(0x80000001, 1));
-    expectEqualsInt(0x00000006, rotateLeftInt(0x80000001, 2));
-    expectEqualsInt(0x23456781, rotateLeftInt(0x12345678, 4));
-    expectEqualsInt(0xBCDEF09A, rotateLeftInt(0x9ABCDEF0, 8));
-    for (int i = 0; i < 40; i++) {  // overshoot a bit
-      int j = i & 31;
-      expectEqualsInt(0x00000000, rotateLeftInt(0x00000000, i));
-      expectEqualsInt(0xFFFFFFFF, rotateLeftInt(0xFFFFFFFF, i));
-      expectEqualsInt(1 << j, rotateLeftInt(0x00000001, i));
-      expectEqualsInt((0x12345678 << j) | (0x12345678 >>> -j), rotateLeftInt(0x12345678, i));
-    }
-  }
-
-  public static void testRotateLeftLong() {
-    expectEqualsLong(0x0000000000000001L, rotateLeftLong(0x0000000000000001L, 0));
-    expectEqualsLong(0x0000000000000002L, rotateLeftLong(0x0000000000000001L, 1));
-    expectEqualsLong(0x8000000000000000L, rotateLeftLong(0x0000000000000001L, 63));
-    expectEqualsLong(0x0000000000000001L, rotateLeftLong(0x0000000000000001L, 64));  // overshoot
-    expectEqualsLong(0x0000000000000003L, rotateLeftLong(0x8000000000000001L, 1));
-    expectEqualsLong(0x0000000000000006L, rotateLeftLong(0x8000000000000001L, 2));
-    expectEqualsLong(0x23456789ABCDEF01L, rotateLeftLong(0x123456789ABCDEF0L, 4));
-    expectEqualsLong(0x3456789ABCDEF012L, rotateLeftLong(0x123456789ABCDEF0L, 8));
-    for (int i = 0; i < 70; i++) {  // overshoot a bit
-      int j = i & 63;
-      expectEqualsLong(0x0000000000000000L, rotateLeftLong(0x0000000000000000L, i));
-      expectEqualsLong(0xFFFFFFFFFFFFFFFFL, rotateLeftLong(0xFFFFFFFFFFFFFFFFL, i));
-      expectEqualsLong(1L << j, rotateLeftLong(0x0000000000000001, i));
-      expectEqualsLong((0x123456789ABCDEF0L << j) | (0x123456789ABCDEF0L >>> -j),
-                       rotateLeftLong(0x123456789ABCDEF0L, i));
-    }
-  }
-
-  public static void testRotateRightBoolean() throws Exception {
-    Method rotateRightBoolean = main2.getMethod("rotateRightBoolean", boolean.class, int.class);
-    for (int i = 0; i < 40; i++) {  // overshoot a bit
-      int j = i & 31;
-      expectEqualsInt(0, (int)rotateRightBoolean.invoke(null, false, i));
-      expectEqualsInt(1 << (32 - i), (int)rotateRightBoolean.invoke(null, true, i));
-    }
-  }
-
-  public static void testRotateRightByte() {
-    expectEqualsInt(0xFFFFFF80, rotateRightByte((byte)0x80, 0));
-    expectEqualsInt(0x7FFFFFC0, rotateRightByte((byte)0x80, 1));
-    expectEqualsInt(0xFFFFFF01, rotateRightByte((byte)0x80, 31));
-    expectEqualsInt(0xFFFFFF80, rotateRightByte((byte)0x80, 32));  // overshoot
-    expectEqualsInt(0xFFFFFFC0, rotateRightByte((byte)0x81, 1));
-    expectEqualsInt(0x7FFFFFE0, rotateRightByte((byte)0x81, 2));
-    expectEqualsInt(0x20000001, rotateRightByte((byte)0x12, 4));
-    expectEqualsInt(0x9AFFFFFF, rotateRightByte((byte)0x9A, 8));
-    for (int i = 0; i < 40; i++) {  // overshoot a bit
-      int j = i & 31;
-      expectEqualsInt(0x00000000, rotateRightByte((byte)0x00, i));
-      expectEqualsInt(0xFFFFFFFF, rotateRightByte((byte)0xFF, i));
-      expectEqualsInt(1 << (32 - j), rotateRightByte((byte)0x01, i));
-      expectEqualsInt((0x12 >>> j) | (0x12 << -j), rotateRightByte((byte)0x12, i));
-    }
-  }
-
-  public static void testRotateRightShort() {
-    expectEqualsInt(0xFFFF8000, rotateRightShort((short)0x8000, 0));
-    expectEqualsInt(0x7FFFC000, rotateRightShort((short)0x8000, 1));
-    expectEqualsInt(0xFFFF0001, rotateRightShort((short)0x8000, 31));
-    expectEqualsInt(0xFFFF8000, rotateRightShort((short)0x8000, 32));  // overshoot
-    expectEqualsInt(0xFFFFC000, rotateRightShort((short)0x8001, 1));
-    expectEqualsInt(0x7FFFE000, rotateRightShort((short)0x8001, 2));
-    expectEqualsInt(0x40000123, rotateRightShort((short)0x1234, 4));
-    expectEqualsInt(0xBCFFFF9A, rotateRightShort((short)0x9ABC, 8));
-    for (int i = 0; i < 40; i++) {  // overshoot a bit
-      int j = i & 31;
-      expectEqualsInt(0x00000000, rotateRightShort((short)0x0000, i));
-      expectEqualsInt(0xFFFFFFFF, rotateRightShort((short)0xFFFF, i));
-      expectEqualsInt(1 << (32 - j), rotateRightShort((short)0x0001, i));
-      expectEqualsInt((0x1234 >>> j) | (0x1234 << -j), rotateRightShort((short)0x1234, i));
-    }
-  }
-
-  public static void testRotateRightChar() {
-    expectEqualsInt(0x00008000, rotateRightChar((char)0x8000, 0));
-    expectEqualsInt(0x00004000, rotateRightChar((char)0x8000, 1));
-    expectEqualsInt(0x00010000, rotateRightChar((char)0x8000, 31));
-    expectEqualsInt(0x00008000, rotateRightChar((char)0x8000, 32));  // overshoot
-    expectEqualsInt(0x80004000, rotateRightChar((char)0x8001, 1));
-    expectEqualsInt(0x40002000, rotateRightChar((char)0x8001, 2));
-    expectEqualsInt(0x40000123, rotateRightChar((char)0x1234, 4));
-    expectEqualsInt(0xBC00009A, rotateRightChar((char)0x9ABC, 8));
-    for (int i = 0; i < 40; i++) {  // overshoot a bit
-      int j = i & 31;
-      expectEqualsInt(0x00000000, rotateRightChar((char)0x0000, i));
-      expectEqualsInt(1 << (32 - j), rotateRightChar((char)0x0001, i));
-      expectEqualsInt((0x1234 >>> j) | (0x1234 << -j), rotateRightChar((char)0x1234, i));
-    }
-  }
-
-  public static void testRotateRightInt() {
-    expectEqualsInt(0x80000000, rotateRightInt(0x80000000, 0));
-    expectEqualsInt(0x40000000, rotateRightInt(0x80000000, 1));
-    expectEqualsInt(0x00000001, rotateRightInt(0x80000000, 31));
-    expectEqualsInt(0x80000000, rotateRightInt(0x80000000, 32));  // overshoot
-    expectEqualsInt(0xC0000000, rotateRightInt(0x80000001, 1));
-    expectEqualsInt(0x60000000, rotateRightInt(0x80000001, 2));
-    expectEqualsInt(0x81234567, rotateRightInt(0x12345678, 4));
-    expectEqualsInt(0xF09ABCDE, rotateRightInt(0x9ABCDEF0, 8));
-    for (int i = 0; i < 40; i++) {  // overshoot a bit
-      int j = i & 31;
-      expectEqualsInt(0x00000000, rotateRightInt(0x00000000, i));
-      expectEqualsInt(0xFFFFFFFF, rotateRightInt(0xFFFFFFFF, i));
-      expectEqualsInt(0x80000000 >>> j, rotateRightInt(0x80000000, i));
-      expectEqualsInt((0x12345678 >>> j) | (0x12345678 << -j), rotateRightInt(0x12345678, i));
-    }
-  }
-
-  public static void testRotateRightLong() {
-    expectEqualsLong(0x8000000000000000L, rotateRightLong(0x8000000000000000L, 0));
-    expectEqualsLong(0x4000000000000000L, rotateRightLong(0x8000000000000000L, 1));
-    expectEqualsLong(0x0000000000000001L, rotateRightLong(0x8000000000000000L, 63));
-    expectEqualsLong(0x8000000000000000L, rotateRightLong(0x8000000000000000L, 64));  // overshoot
-    expectEqualsLong(0xC000000000000000L, rotateRightLong(0x8000000000000001L, 1));
-    expectEqualsLong(0x6000000000000000L, rotateRightLong(0x8000000000000001L, 2));
-    expectEqualsLong(0x0123456789ABCDEFL, rotateRightLong(0x123456789ABCDEF0L, 4));
-    expectEqualsLong(0xF0123456789ABCDEL, rotateRightLong(0x123456789ABCDEF0L, 8));
-    for (int i = 0; i < 70; i++) {  // overshoot a bit
-      int j = i & 63;
-      expectEqualsLong(0x0000000000000000L, rotateRightLong(0x0000000000000000L, i));
-      expectEqualsLong(0xFFFFFFFFFFFFFFFFL, rotateRightLong(0xFFFFFFFFFFFFFFFFL, i));
-      expectEqualsLong(0x8000000000000000L >>> j, rotateRightLong(0x8000000000000000L, i));
-      expectEqualsLong((0x123456789ABCDEF0L >>> j) | (0x123456789ABCDEF0L << -j),
-                       rotateRightLong(0x123456789ABCDEF0L, i));
-    }
-  }
-
-
-  public static void testRotateLeftIntWithByteDistance() {
-    expectEqualsInt(0x00000001, rotateLeftIntWithByteDistance(0x00000001, (byte)0));
-    expectEqualsInt(0x00000002, rotateLeftIntWithByteDistance(0x00000001, (byte)1));
-    expectEqualsInt(0x80000000, rotateLeftIntWithByteDistance(0x00000001, (byte)31));
-    expectEqualsInt(0x00000001, rotateLeftIntWithByteDistance(0x00000001, (byte)32));  // overshoot
-    expectEqualsInt(0x00000003, rotateLeftIntWithByteDistance(0x80000001, (byte)1));
-    expectEqualsInt(0x00000006, rotateLeftIntWithByteDistance(0x80000001, (byte)2));
-    expectEqualsInt(0x23456781, rotateLeftIntWithByteDistance(0x12345678, (byte)4));
-    expectEqualsInt(0xBCDEF09A, rotateLeftIntWithByteDistance(0x9ABCDEF0, (byte)8));
-    for (byte i = 0; i < 40; i++) {  // overshoot a bit
-      byte j = (byte)(i & 31);
-      expectEqualsInt(0x00000000, rotateLeftIntWithByteDistance(0x00000000, i));
-      expectEqualsInt(0xFFFFFFFF, rotateLeftIntWithByteDistance(0xFFFFFFFF, i));
-      expectEqualsInt(1 << j, rotateLeftIntWithByteDistance(0x00000001, i));
-      expectEqualsInt((0x12345678 << j) | (0x12345678 >>> -j),
-                      rotateLeftIntWithByteDistance(0x12345678, i));
-    }
-  }
-
-  public static void testRotateRightIntWithByteDistance() {
-    expectEqualsInt(0x80000000, rotateRightIntWithByteDistance(0x80000000, (byte)0));
-    expectEqualsInt(0x40000000, rotateRightIntWithByteDistance(0x80000000, (byte)1));
-    expectEqualsInt(0x00000001, rotateRightIntWithByteDistance(0x80000000, (byte)31));
-    expectEqualsInt(0x80000000, rotateRightIntWithByteDistance(0x80000000, (byte)32));  // overshoot
-    expectEqualsInt(0xC0000000, rotateRightIntWithByteDistance(0x80000001, (byte)1));
-    expectEqualsInt(0x60000000, rotateRightIntWithByteDistance(0x80000001, (byte)2));
-    expectEqualsInt(0x81234567, rotateRightIntWithByteDistance(0x12345678, (byte)4));
-    expectEqualsInt(0xF09ABCDE, rotateRightIntWithByteDistance(0x9ABCDEF0, (byte)8));
-    for (byte i = 0; i < 40; i++) {  // overshoot a bit
-      byte j = (byte)(i & 31);
-      expectEqualsInt(0x00000000, rotateRightIntWithByteDistance(0x00000000, i));
-      expectEqualsInt(0xFFFFFFFF, rotateRightIntWithByteDistance(0xFFFFFFFF, i));
-      expectEqualsInt(0x80000000 >>> j, rotateRightIntWithByteDistance(0x80000000, i));
-      expectEqualsInt((0x12345678 >>> j) | (0x12345678 << -j),
-                      rotateRightIntWithByteDistance(0x12345678, i));
-    }
-  }
-
-
-  public static void main(String args[]) throws Exception {
-    main2 = Class.forName("Main2");
-
-    testRotateLeftBoolean();
-    testRotateLeftByte();
-    testRotateLeftShort();
-    testRotateLeftChar();
-    testRotateLeftInt();
-    testRotateLeftLong();
-
-    testRotateRightBoolean();
-    testRotateRightByte();
-    testRotateRightShort();
-    testRotateRightChar();
-    testRotateRightInt();
-    testRotateRightLong();
-
-    // Also exercise distance values with types other than int.
-    testRotateLeftIntWithByteDistance();
-    testRotateRightIntWithByteDistance();
-
-    System.out.println("passed");
-  }
-
-
-  private static void expectEqualsInt(int expected, int result) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
-
-  private static void expectEqualsLong(long expected, long result) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
-}
diff --git a/test/565-checker-rotate/src/Main.java b/test/565-checker-rotate/src/Main.java
deleted file mode 100644
index 79b8555..0000000
--- a/test/565-checker-rotate/src/Main.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-// This file is just for running on the RI as the test is ART specific.
-public class Main {
-  public static void main(String args[]) {
-    System.out.println("passed");
-  }
-}
\ No newline at end of file
diff --git a/test/566-checker-codegen-select/Android.bp b/test/566-checker-codegen-select/Android.bp
new file mode 100644
index 0000000..27c5f48
--- /dev/null
+++ b/test/566-checker-codegen-select/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `566-checker-codegen-select`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-566-checker-codegen-select",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-566-checker-codegen-select-expected-stdout",
+        ":art-run-test-566-checker-codegen-select-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-566-checker-codegen-select-expected-stdout",
+    out: ["art-run-test-566-checker-codegen-select-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-566-checker-codegen-select-expected-stderr",
+    out: ["art-run-test-566-checker-codegen-select-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/566-checker-codegen-select/expected.txt b/test/566-checker-codegen-select/expected-stderr.txt
similarity index 100%
rename from test/566-checker-codegen-select/expected.txt
rename to test/566-checker-codegen-select/expected-stderr.txt
diff --git a/test/566-checker-codegen-select/expected.txt b/test/566-checker-codegen-select/expected-stdout.txt
similarity index 100%
copy from test/566-checker-codegen-select/expected.txt
copy to test/566-checker-codegen-select/expected-stdout.txt
diff --git a/test/566-checker-signum/expected.txt b/test/566-checker-signum/expected.txt
deleted file mode 100644
index b0aad4d..0000000
--- a/test/566-checker-signum/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-passed
diff --git a/test/566-checker-signum/info.txt b/test/566-checker-signum/info.txt
deleted file mode 100644
index 328e494..0000000
--- a/test/566-checker-signum/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Unit test for 32-bit and 64-bit signum operations.
diff --git a/test/566-checker-signum/smali/Main2.smali b/test/566-checker-signum/smali/Main2.smali
deleted file mode 100644
index 767bed2..0000000
--- a/test/566-checker-signum/smali/Main2.smali
+++ /dev/null
@@ -1,82 +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.
-
-.class public LMain2;
-.super Ljava/lang/Object;
-
-## CHECK-START: int Main2.signBoolean(boolean) builder (after)
-## CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
-## CHECK-DAG:     <<One:i\d+>>    IntConstant 1
-## CHECK-DAG:     <<Phi:i\d+>>    Phi [<<One>>,<<Zero>>]
-## CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect [<<Phi>>{{(,[ij]\d+)?}}] intrinsic:IntegerSignum
-## CHECK-DAG:                     Return [<<Result>>]
-
-## CHECK-START: int Main2.signBoolean(boolean) instruction_simplifier (after)
-## CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
-## CHECK-DAG:     <<One:i\d+>>    IntConstant 1
-## CHECK-DAG:     <<Phi:i\d+>>    Phi [<<One>>,<<Zero>>]
-## CHECK-DAG:     <<Result:i\d+>> Compare [<<Phi>>,<<Zero>>]
-## CHECK-DAG:                     Return [<<Result>>]
-
-## CHECK-START: int Main2.signBoolean(boolean) instruction_simplifier (after)
-## CHECK-NOT:                     InvokeStaticOrDirect
-
-## CHECK-START: int Main2.signBoolean(boolean) select_generator (after)
-## CHECK-DAG:     <<Arg:z\d+>>    ParameterValue
-## CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
-## CHECK-DAG:     <<One:i\d+>>    IntConstant 1
-## CHECK-DAG:     <<Sel:i\d+>>    Select [<<Zero>>,<<One>>,<<Arg>>]
-## CHECK-DAG:     <<Result:i\d+>> Compare [<<Sel>>,<<Zero>>]
-## CHECK-DAG:                     Return [<<Result>>]
-
-## CHECK-START: int Main2.signBoolean(boolean) select_generator (after)
-## CHECK-NOT:                     Phi
-
-## CHECK-START: int Main2.signBoolean(boolean) instruction_simplifier$after_bce (after)
-## CHECK-DAG:     <<Arg:z\d+>>    ParameterValue
-## CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
-## CHECK-DAG:     <<Result:i\d+>> Compare [<<Arg>>,<<Zero>>]
-## CHECK-DAG:                     Return [<<Result>>]
-
-## CHECK-START: int Main2.signBoolean(boolean) instruction_simplifier$after_bce (after)
-## CHECK-NOT:                     Select
-
-# Original java source:
-#
-#     private static int signBoolean(boolean x) {
-#       return Integer.signum(x ? 1 : 0);
-#     }
-
-.method public static signBoolean(Z)I
-    .registers 2
-    .param p0, "x"    # Z
-
-    .prologue
-    .line 58
-    if-eqz p0, :cond_8
-
-    const/4 v0, 0x1
-
-    :goto_3
-    invoke-static {v0}, Ljava/lang/Integer;->signum(I)I
-
-    move-result v0
-
-    return v0
-
-    :cond_8
-    const/4 v0, 0x0
-
-    goto :goto_3
-.end method
diff --git a/test/566-checker-signum/src-art/Main.java b/test/566-checker-signum/src-art/Main.java
deleted file mode 100644
index ea01785..0000000
--- a/test/566-checker-signum/src-art/Main.java
+++ /dev/null
@@ -1,196 +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.
- */
-
-import java.lang.reflect.Method;
-
-public class Main {
-
-  /// CHECK-START: int Main.signByte(byte) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerSignum
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.signByte(byte) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.signByte(byte) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  private static int signByte(byte x) {
-    return Integer.signum(x);
-  }
-
-  /// CHECK-START: int Main.signShort(short) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerSignum
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.signShort(short) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.signShort(short) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  private static int signShort(short x) {
-    return Integer.signum(x);
-  }
-
-  /// CHECK-START: int Main.signChar(char) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerSignum
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.signChar(char) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.signChar(char) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  private static int signChar(char x) {
-    return Integer.signum(x);
-  }
-
-  /// CHECK-START: int Main.signInt(int) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerSignum
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.signInt(int) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.signInt(int) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  private static int signInt(int x) {
-    return Integer.signum(x);
-  }
-
-  /// CHECK-START: int Main.signLong(long) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongSignum
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.signLong(long) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.signLong(long) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  private static int signLong(long x) {
-    return Long.signum(x);
-  }
-
-
-  public static void testSignBoolean() throws Exception {
-    Method signBoolean = Class.forName("Main2").getMethod("signBoolean", boolean.class);
-    expectEquals(0, (int)signBoolean.invoke(null, false));
-    expectEquals(1, (int)signBoolean.invoke(null, true));
-  }
-
-  public static void testSignByte() {
-    expectEquals(-1, signByte((byte)Byte.MIN_VALUE));
-    expectEquals(-1, signByte((byte)-64));
-    expectEquals(-1, signByte((byte)-1));
-    expectEquals(0, signByte((byte)0));
-    expectEquals(1, signByte((byte)1));
-    expectEquals(1, signByte((byte)64));
-    expectEquals(1, signByte((byte)Byte.MAX_VALUE));
-  }
-
-  public static void testSignShort() {
-    expectEquals(-1, signShort((short)Short.MIN_VALUE));
-    expectEquals(-1, signShort((short)-12345));
-    expectEquals(-1, signShort((short)-1));
-    expectEquals(0, signShort((short)0));
-    expectEquals(1, signShort((short)1));
-    expectEquals(1, signShort((short)12345));
-    expectEquals(1, signShort((short)Short.MAX_VALUE));
-  }
-
-  public static void testSignChar() {
-    expectEquals(0, signChar((char)0));
-    expectEquals(1, signChar((char)1));
-    expectEquals(1, signChar((char)12345));
-    expectEquals(1, signChar((char)Character.MAX_VALUE));
-  }
-
-  public static void testSignInt() {
-    expectEquals(-1, signInt(Integer.MIN_VALUE));
-    expectEquals(-1, signInt(-12345));
-    expectEquals(-1, signInt(-1));
-    expectEquals(0, signInt(0));
-    expectEquals(1, signInt(1));
-    expectEquals(1, signInt(12345));
-    expectEquals(1, signInt(Integer.MAX_VALUE));
-
-    for (int i = -11; i <= 11; i++) {
-      int expected = 0;
-      if (i < 0) expected = -1;
-      else if (i > 0) expected = 1;
-      expectEquals(expected, signInt(i));
-    }
-  }
-
-  public static void testSignLong() {
-    expectEquals(-1, signLong(Long.MIN_VALUE));
-    expectEquals(-1, signLong(-12345L));
-    expectEquals(-1, signLong(-1L));
-    expectEquals(0, signLong(0L));
-    expectEquals(1, signLong(1L));
-    expectEquals(1, signLong(12345L));
-    expectEquals(1, signLong(Long.MAX_VALUE));
-
-    expectEquals(-1, signLong(0x800000007FFFFFFFL));
-    expectEquals(-1, signLong(0x80000000FFFFFFFFL));
-    expectEquals(1, signLong(0x000000007FFFFFFFL));
-    expectEquals(1, signLong(0x00000000FFFFFFFFL));
-    expectEquals(1, signLong(0x7FFFFFFF7FFFFFFFL));
-    expectEquals(1, signLong(0x7FFFFFFFFFFFFFFFL));
-
-    for (long i = -11L; i <= 11L; i++) {
-      int expected = 0;
-      if (i < 0) expected = -1;
-      else if (i > 0) expected = 1;
-      expectEquals(expected, signLong(i));
-    }
-
-    for (long i = Long.MIN_VALUE; i <= Long.MIN_VALUE + 11L; i++) {
-      expectEquals(-1, signLong(i));
-    }
-
-    for (long i = Long.MAX_VALUE; i >= Long.MAX_VALUE - 11L; i--) {
-      expectEquals(1, signLong(i));
-    }
-  }
-
-
-  public static void main(String args[]) throws Exception {
-    testSignBoolean();
-    testSignByte();
-    testSignShort();
-    testSignChar();
-    testSignInt();
-    testSignLong();
-
-    System.out.println("passed");
-  }
-
-  private static void expectEquals(int expected, int result) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
-}
diff --git a/test/566-checker-signum/src/Main.java b/test/566-checker-signum/src/Main.java
deleted file mode 100644
index fa8e5cd..0000000
--- a/test/566-checker-signum/src/Main.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-// This file is just for running on the RI as the test is ART specific.
-public class Main {
-  public static void main(String[] args) {
-    System.out.println("passed");
-  }
-}
diff --git a/test/566-polymorphic-inlining/Android.bp b/test/566-polymorphic-inlining/Android.bp
new file mode 100644
index 0000000..a506424
--- /dev/null
+++ b/test/566-polymorphic-inlining/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `566-polymorphic-inlining`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-566-polymorphic-inlining",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-566-polymorphic-inlining-expected-stdout",
+        ":art-run-test-566-polymorphic-inlining-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-566-polymorphic-inlining-expected-stdout",
+    out: ["art-run-test-566-polymorphic-inlining-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-566-polymorphic-inlining-expected-stderr",
+    out: ["art-run-test-566-polymorphic-inlining-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/576-polymorphic-inlining/expected.txt b/test/566-polymorphic-inlining/expected-stderr.txt
similarity index 100%
copy from test/576-polymorphic-inlining/expected.txt
copy to test/566-polymorphic-inlining/expected-stderr.txt
diff --git a/test/566-polymorphic-inlining/expected.txt b/test/566-polymorphic-inlining/expected-stdout.txt
similarity index 100%
rename from test/566-polymorphic-inlining/expected.txt
rename to test/566-polymorphic-inlining/expected-stdout.txt
diff --git a/test/566-polymorphic-inlining/polymorphic_inline.cc b/test/566-polymorphic-inlining/polymorphic_inline.cc
index 37d998c..34ec3ff 100644
--- a/test/566-polymorphic-inlining/polymorphic_inline.cc
+++ b/test/566-polymorphic-inlining/polymorphic_inline.cc
@@ -20,24 +20,25 @@
 #include "jit/jit_code_cache.h"
 #include "jit/profiling_info.h"
 #include "mirror/class.h"
+#include "nativehelper/ScopedUtfChars.h"
 #include "oat_quick_method_header.h"
 #include "scoped_thread_state_change-inl.h"
 #include "stack_map.h"
 
 namespace art {
 
-static void do_checks(jclass cls, const char* method_name) {
-  ScopedObjectAccess soa(Thread::Current());
-  ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
+static bool do_checks(ArtMethod* method, ScopedObjectAccess& soa)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
   jit::Jit* jit = Runtime::Current()->GetJit();
   jit::JitCodeCache* code_cache = jit->GetCodeCache();
-  ArtMethod* method = klass->FindDeclaredDirectMethodByName(method_name, kRuntimePointerSize);
 
   OatQuickMethodHeader* header = nullptr;
   // Infinite loop... Test harness will have its own timeout.
   while (true) {
     const void* pc = method->GetEntryPointFromQuickCompiledCode();
-    if (code_cache->ContainsPc(pc)) {
+    if (code_cache->ContainsPc(pc) &&
+        !CodeInfo::IsBaseline(
+            OatQuickMethodHeader::FromEntryPoint(pc)->GetOptimizedCodeInfoPtr())) {
       header = OatQuickMethodHeader::FromEntryPoint(pc);
       break;
     } else {
@@ -46,46 +47,36 @@
       usleep(1000);
     }
     // Will either ensure it's compiled or do the compilation itself.
-    jit->CompileMethod(method, soa.Self(), /*baseline=*/ false, /*osr=*/ false, /*prejit=*/ false);
+    jit->CompileMethod(method, soa.Self(), CompilationKind::kOptimized, /*prejit=*/ false);
   }
 
   CodeInfo info(header);
-  CHECK(info.HasInlineInfo()) << method->PrettyMethod();
+  return info.HasInlineInfo();
 }
 
-static void allocate_profiling_info(jclass cls, const char* method_name) {
+extern "C" JNIEXPORT bool JNICALL Java_Main_ensureJittedAndPolymorphicInline566(JNIEnv* env,
+                                                                                jclass cls,
+                                                                                jstring method_name) {
+  jit::Jit* jit = Runtime::Current()->GetJit();
+  if (jit == nullptr) {
+    return true;
+  }
+
+  // The test only works when we use tiered JIT.
+  if (jit->JitAtFirstUse()) {
+    return true;
+  }
+
   ScopedObjectAccess soa(Thread::Current());
-  ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
-  ArtMethod* method = klass->FindDeclaredDirectMethodByName(method_name, kRuntimePointerSize);
-  ProfilingInfo::Create(soa.Self(), method, /* retry_allocation */ true);
-}
+  ScopedUtfChars chars(env, method_name);
+  ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
+      chars.c_str(), kRuntimePointerSize);
 
-extern "C" JNIEXPORT void JNICALL Java_Main_ensureProfilingInfo566(JNIEnv*, jclass cls) {
-  jit::Jit* jit = Runtime::Current()->GetJit();
-  if (jit == nullptr) {
-    return;
+  if (method == nullptr) {
+    return false;
   }
 
-  allocate_profiling_info(cls, "$noinline$testInvokeVirtual");
-  allocate_profiling_info(cls, "$noinline$testInvokeInterface");
-  allocate_profiling_info(cls, "$noinline$testInlineToSameTarget");
-}
-
-extern "C" JNIEXPORT void JNICALL Java_Main_ensureJittedAndPolymorphicInline566(JNIEnv*, jclass cls) {
-  jit::Jit* jit = Runtime::Current()->GetJit();
-  if (jit == nullptr) {
-    return;
-  }
-
-  if (kIsDebugBuild) {
-    // A debug build might often compile the methods without profiling informations filled.
-    return;
-  }
-
-  do_checks(cls, "$noinline$testInvokeVirtual");
-  do_checks(cls, "$noinline$testInvokeInterface");
-  do_checks(cls, "$noinline$testInvokeInterface2");
-  do_checks(cls, "$noinline$testInlineToSameTarget");
+  return do_checks(method, soa);
 }
 
 }  // namespace art
diff --git a/test/566-polymorphic-inlining/src/Main.java b/test/566-polymorphic-inlining/src/Main.java
index f8354be..595a056 100644
--- a/test/566-polymorphic-inlining/src/Main.java
+++ b/test/566-polymorphic-inlining/src/Main.java
@@ -41,13 +41,10 @@
     itfs[1] = mains[1] = new Subclass();
     itfs[2] = mains[2] = new OtherSubclass();
 
-    // Create the profiling info eagerly to make sure they are filled.
-    ensureProfilingInfo566();
-
     // Make $noinline$testInvokeVirtual and $noinline$testInvokeInterface hot to get them jitted.
     // We pass Main and Subclass to get polymorphic inlining based on calling
     // the same method.
-    for (int i = 0; i < 1000000; ++i) {
+    for (int i = 0; i < 0x30000; ++i) {
       $noinline$testInvokeVirtual(mains[0]);
       $noinline$testInvokeVirtual(mains[1]);
       $noinline$testInvokeInterface(itfs[0]);
@@ -58,7 +55,10 @@
       $noinline$testInlineToSameTarget(mains[1]);
     }
 
-    ensureJittedAndPolymorphicInline566();
+    ensureJittedAndPolymorphicInline("$noinline$testInvokeVirtual");
+    ensureJittedAndPolymorphicInline("$noinline$testInvokeInterface");
+    ensureJittedAndPolymorphicInline("$noinline$testInvokeInterface2");
+    ensureJittedAndPolymorphicInline("$noinline$testInlineToSameTarget");
 
     // At this point, the JIT should have compiled both methods, and inline
     // sameInvokeVirtual and sameInvokeInterface.
@@ -78,7 +78,7 @@
 
     // Run this once to make sure we execute the JITted code.
     $noinline$testInlineToSameTarget(mains[0]);
-    assertEquals(2000001, counter);
+    assertEquals(0x60000 + 1, counter);
   }
 
   public Class<?> sameInvokeVirtual() {
@@ -124,8 +124,13 @@
 
   public Object field = new Object();
 
-  public static native void ensureJittedAndPolymorphicInline566();
-  public static native void ensureProfilingInfo566();
+  public static void ensureJittedAndPolymorphicInline(String methodName) {
+    if (!ensureJittedAndPolymorphicInline566(methodName)) {
+      throw new Error("Didn't find an inlined method in " + methodName);
+    }
+  }
+
+  public static native boolean ensureJittedAndPolymorphicInline566(String methodName);
 
   public void increment() {
     field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo
diff --git a/test/567-checker-builder-intrinsics/Android.bp b/test/567-checker-builder-intrinsics/Android.bp
new file mode 100644
index 0000000..5bf3c03
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `567-checker-builder-intrinsics`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-567-checker-builder-intrinsics",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-567-checker-builder-intrinsics-expected-stdout",
+        ":art-run-test-567-checker-builder-intrinsics-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-567-checker-builder-intrinsics-expected-stdout",
+    out: ["art-run-test-567-checker-builder-intrinsics-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-567-checker-builder-intrinsics-expected-stderr",
+    out: ["art-run-test-567-checker-builder-intrinsics-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/565-checker-condition-liveness/expected.txt b/test/567-checker-builder-intrinsics/expected-stderr.txt
similarity index 100%
copy from test/565-checker-condition-liveness/expected.txt
copy to test/567-checker-builder-intrinsics/expected-stderr.txt
diff --git a/test/567-checker-builder-intrinsics/expected-stdout.txt b/test/567-checker-builder-intrinsics/expected-stdout.txt
new file mode 100644
index 0000000..9554e0d
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/expected-stdout.txt
@@ -0,0 +1,8 @@
+TestRotate passed
+TestCompare passed
+TestSignum passed
+TestIsNan passed
+TestVarHandles passed
+TestMinMax passed
+TestAbs passed
+TestFpAbs passed
diff --git a/test/567-checker-builder-intrinsics/info.txt b/test/567-checker-builder-intrinsics/info.txt
new file mode 100644
index 0000000..7ad7aa8
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/info.txt
@@ -0,0 +1,2 @@
+Tests for creating intermediate representation in InstructionBuilder for simple
+intrinsics. It also tests some simplifications for these instructions.
diff --git a/test/567-checker-builder-intrinsics/src/Main.java b/test/567-checker-builder-intrinsics/src/Main.java
new file mode 100644
index 0000000..3320fb7
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/src/Main.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 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[]) {
+    TestRotate.main();
+    TestCompare.main();
+    TestSignum.main();
+    TestIsNan.main();
+    TestVarHandles.main();
+    TestMinMax.main();
+    TestAbs.main();
+    TestFpAbs.main();
+  }
+}
diff --git a/test/567-checker-builder-intrinsics/src/TestAbs.java b/test/567-checker-builder-intrinsics/src/TestAbs.java
new file mode 100644
index 0000000..defc988
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/src/TestAbs.java
@@ -0,0 +1,310 @@
+/*
+ * 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.
+ */
+
+/**
+ * Functional tests for detecting abs.
+ */
+public class TestAbs {
+
+  //
+  // Intrinsics.
+  //
+
+  /// CHECK-START: int TestAbs.absI(int) builder (after)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.absI(int) builder (after)
+  /// CHECK-NOT:              InvokeStaticOrDirect
+  public static int absI(int a) {
+    return Math.abs(a);
+  }
+
+  /// CHECK-START: long TestAbs.absL(long) builder (after)
+  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
+  /// CHECK-DAG: <<Abs:j\d+>> Abs [<<Par>>]
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: long TestAbs.absL(long) builder (after)
+  /// CHECK-NOT:              InvokeStaticOrDirect
+  public static long absL(long a) {
+    return Math.abs(a);
+  }
+
+  //
+  // Types.
+  //
+
+  /// CHECK-START: int TestAbs.abs1(int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
+  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Par>>,<<Zer>>]
+  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Neg>>,<<Par>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestAbs.abs1(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.abs1(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int abs1(int a) {
+    return a < 0 ? -a : a;
+  }
+
+  /// CHECK-START: int TestAbs.abs2(int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
+  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Par>>,<<Zer>>]
+  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Neg>>,<<Par>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestAbs.abs2(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.abs2(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int abs2(int a) {
+    return a <= 0 ? -a : a;
+  }
+
+  /// CHECK-START: int TestAbs.abs3(int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Par>>,<<Zer>>]
+  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Par>>,<<Neg>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestAbs.abs3(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.abs3(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int abs3(int a) {
+    return a > 0 ? a : -a;
+  }
+
+  /// CHECK-START: int TestAbs.abs4(int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Par>>,<<Zer>>]
+  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Par>>,<<Neg>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestAbs.abs4(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.abs4(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int abs4(int a) {
+    return a >= 0 ? a : -a;
+  }
+
+  /// CHECK-START: int TestAbs.abs5(short) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Par:s\d+>> ParameterValue
+  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Par>>,<<Zer>>]
+  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Par>>,<<Neg>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestAbs.abs5(short) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:s\d+>> ParameterValue
+  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.abs5(short) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int abs5(short a) {
+    return a >= 0 ? a : -a;
+  }
+
+  /// CHECK-START: int TestAbs.abs6(byte) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Par:b\d+>> ParameterValue
+  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Par>>,<<Zer>>]
+  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Par>>,<<Neg>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestAbs.abs6(byte) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:b\d+>> ParameterValue
+  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.abs6(byte) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int abs6(byte a) {
+    return a >= 0 ? a : -a;
+  }
+
+  /// CHECK-START: long TestAbs.abs7(long) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
+  /// CHECK-DAG: <<Zer:j\d+>> LongConstant 0
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Par>>,<<Zer>>]
+  /// CHECK-DAG: <<Neg:j\d+>> [<<Par>>]
+  /// CHECK-DAG: <<Sel:j\d+>> Select [<<Par>>,<<Neg>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: long TestAbs.abs7(long) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
+  /// CHECK-DAG: <<Abs:j\d+>> Abs [<<Par>>]
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: long TestAbs.abs7(long) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static long abs7(long a) {
+    return a >= 0 ? a : -a;
+  }
+
+  //
+  // Complications.
+  //
+
+  /// CHECK-START: int TestAbs.abs0(int[]) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
+  /// CHECK-DAG: <<Arr:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Arr>>,<<Zer>>]
+  /// CHECK-DAG: <<Neg:i\d+>> [<<Arr>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Arr>>,<<Neg>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestAbs.abs0(int[]) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Arr:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
+  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Arr>>]
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.abs0(int[]) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int abs0(int[] a) {
+    return a[0] >= 0 ? a[0] : -a[0];
+  }
+
+  //
+  // Nop zero extension.
+  //
+
+  /// CHECK-START: int TestAbs.zabs1(byte) instruction_simplifier (before)
+  /// CHECK-DAG: <<Par:b\d+>> ParameterValue
+  /// CHECK-DAG: <<Msk:i\d+>> IntConstant 255
+  /// CHECK-DAG: <<And:i\d+>> [<<Par>>,<<Msk>>]
+  /// CHECK-DAG: <<Abs:i\d+>> Abs
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.zabs1(byte) instruction_simplifier (after)
+  /// CHECK-DAG: <<Par:b\d+>> ParameterValue
+  /// CHECK-DAG: <<Cnv:a\d+>> TypeConversion [<<Par>>]
+  /// CHECK-DAG:              Return [<<Cnv>>]
+  //
+  /// CHECK-START: int TestAbs.zabs1(byte) instruction_simplifier (after)
+  /// CHECK-NOT:              Abs
+  public static int zabs1(byte a) {
+    return Math.abs(a & 0xff);
+  }
+
+  /// CHECK-START: int TestAbs.zabs2(short) instruction_simplifier (before)
+  /// CHECK-DAG: <<Par:s\d+>> ParameterValue
+  /// CHECK-DAG: <<Msk:i\d+>> IntConstant 65535
+  /// CHECK-DAG: <<And:i\d+>> [<<Msk>>,<<Par>>]
+  /// CHECK-DAG: <<Abs:i\d+>> Abs
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.zabs2(short) instruction_simplifier (after)
+  /// CHECK-DAG: <<Par:s\d+>> ParameterValue
+  /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<Par>>]
+  /// CHECK-DAG:              Return [<<Cnv>>]
+  //
+  /// CHECK-START: int TestAbs.zabs2(short) instruction_simplifier (after)
+  /// CHECK-NOT:              Abs
+  public static int zabs2(short a) {
+    return Math.abs(a & 0xffff);
+  }
+
+  /// CHECK-START: int TestAbs.zabs3(char) instruction_simplifier (before)
+  /// CHECK-DAG: <<Par:c\d+>> ParameterValue
+  /// CHECK-DAG: <<Abs:i\d+>> Abs
+  /// CHECK-DAG:              Return [<<Abs>>]
+  //
+  /// CHECK-START: int TestAbs.zabs3(char) instruction_simplifier (after)
+  /// CHECK-DAG: <<Par:c\d+>> ParameterValue
+  /// CHECK-DAG:              Return [<<Par>>]
+  //
+  /// CHECK-START: int TestAbs.zabs3(char) instruction_simplifier (after)
+  /// CHECK-NOT:              Abs
+  public static int zabs3(char a) {
+    return Math.abs(a);
+  }
+
+  public static void main() {
+    // Intrinsics.
+    expectEquals(10, absI(-10));
+    expectEquals(20, absI(20));
+    expectEquals(10L, absL(-10L));
+    expectEquals(20L, absL(20L));
+    // Types.
+    expectEquals(10, abs1(-10));
+    expectEquals(20, abs1(20));
+    expectEquals(10, abs2(-10));
+    expectEquals(20, abs2(20));
+    expectEquals(10, abs3(-10));
+    expectEquals(20, abs3(20));
+    expectEquals(10, abs4(-10));
+    expectEquals(20, abs4(20));
+    expectEquals(10, abs4((short) -10));
+    expectEquals(20, abs4((short) 20));
+    expectEquals(10, abs6((byte) -10));
+    expectEquals(20, abs6((byte) 20));
+    expectEquals(10L, abs7(-10L));
+    expectEquals(20L, abs7(20L));
+    // Complications.
+    int[] a = { 13 };
+    int[] b = { -11 };
+    expectEquals(13, abs0(a));
+    expectEquals(11, abs0(b));
+    // Nop zero extension.
+    expectEquals(1, zabs1((byte) 1));
+    expectEquals(0xff, zabs1((byte) -1));
+    expectEquals(1, zabs2((short) 1));
+    expectEquals(0xffff, zabs2((short) -1));
+    expectEquals(1, zabs3((char) 1));
+    expectEquals(0xffff, zabs3((char) -1));
+    System.out.println("TestAbs passed");
+  }
+
+  private static void expectEquals(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  private static void expectEquals(long expected, long result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+}
diff --git a/test/567-checker-builder-intrinsics/src/TestCompare.java b/test/567-checker-builder-intrinsics/src/TestCompare.java
new file mode 100644
index 0000000..185616a
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/src/TestCompare.java
@@ -0,0 +1,904 @@
+/*
+ * 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.
+ */
+
+public class TestCompare {
+
+  /// CHECK-START: void TestCompare.$opt$noinline$testReplaceInputWithItself(int) builder (after)
+  /// CHECK-DAG:     <<ArgX:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Cmp:i\d+>>    Compare [<<ArgX>>,<<Zero>>]
+  /// CHECK-DAG:                     GreaterThanOrEqual [<<Cmp>>,<<Zero>>]
+
+  /// CHECK-START: void TestCompare.$opt$noinline$testReplaceInputWithItself(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<ArgX:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
+  /// CHECK-DAG:                     GreaterThanOrEqual [<<ArgX>>,<<Zero>>]
+
+  public static void $opt$noinline$testReplaceInputWithItself(int x) {
+    // The instruction builder first replaces Integer.compare(x, 0) with Compare HIR
+    // and then the instruction simplifier merges the Compare into the GreaterThanOrEqual.
+    // This is a regression test to check that it is allowed to replace the second
+    // input of the GreaterThanOrEqual, i.e. <<Zero>>, with the very same instruction.
+    if (Integer.compare(x, 0) < 0) {
+      System.out.println("OOOPS");
+    }
+  }
+
+  /// CHECK-START: int TestCompare.compareBooleans(boolean, boolean) select_generator (after)
+  /// CHECK-NOT:                     Phi
+
+  /// CHECK-START: int TestCompare.compareBooleans(boolean, boolean) instruction_simplifier$after_bce (after)
+  /// CHECK:         <<ArgX:z\d+>>   ParameterValue
+  /// CHECK:         <<ArgY:z\d+>>   ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>> Compare [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareBooleans(boolean, boolean) instruction_simplifier$after_bce (after)
+  /// CHECK-NOT:                     Select
+
+  private static int compareBooleans(boolean x, boolean y) {
+    return Integer.compare((x ? 1 : 0), (y ? 1 : 0));
+  }
+
+  ///  CHECK-START: int TestCompare.compareBooleans2(boolean, boolean) builder (after)
+  ///  CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
+  ///  CHECK-DAG:     <<One:i\d+>>    IntConstant 1
+  ///  CHECK-DAG:     <<PhiX:i\d+>>   Phi [<<One>>,<<Zero>>]
+  ///  CHECK-DAG:     <<PhiY:i\d+>>   Phi [<<One>>,<<Zero>>]
+  ///  CHECK-DAG:     <<Result:i\d+>> Compare [<<PhiX>>,<<PhiY>>]
+  ///  CHECK-DAG:                     Return [<<Result>>]
+
+  ///  CHECK-START: int TestCompare.compareBooleans2(boolean, boolean) builder (after)
+  ///  CHECK-NOT:                     InvokeStaticOrDirect
+
+  ///  CHECK-START: int TestCompare.compareBooleans2(boolean, boolean) select_generator (after)
+  ///  CHECK:         <<ArgX:z\d+>>   ParameterValue
+  ///  CHECK:         <<ArgY:z\d+>>   ParameterValue
+  ///  CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
+  ///  CHECK-DAG:     <<One:i\d+>>    IntConstant 1
+  ///  CHECK-DAG:     <<SelX:i\d+>>   Select [<<Zero>>,<<One>>,<<ArgX>>]
+  ///  CHECK-DAG:     <<SelY:i\d+>>   Select [<<Zero>>,<<One>>,<<ArgY>>]
+  ///  CHECK-DAG:     <<Result:i\d+>> Compare [<<SelX>>,<<SelY>>]
+  ///  CHECK-DAG:                     Return [<<Result>>]
+
+  ///  CHECK-START: int TestCompare.compareBooleans2(boolean, boolean) select_generator (after)
+  ///  CHECK-NOT:                     Phi
+
+  ///  CHECK-START: int TestCompare.compareBooleans2(boolean, boolean) instruction_simplifier$after_bce (after)
+  ///  CHECK:         <<ArgX:z\d+>>   ParameterValue
+  ///  CHECK:         <<ArgY:z\d+>>   ParameterValue
+  ///  CHECK-DAG:     <<Result:i\d+>> Compare [<<ArgX>>,<<ArgY>>]
+  ///  CHECK-DAG:                     Return [<<Result>>]
+
+  ///  CHECK-START: int TestCompare.compareBooleans2(boolean, boolean) instruction_simplifier$after_bce (after)
+  ///  CHECK-NOT:                     Select
+
+  private static int compareBooleans2(boolean x, boolean y) {
+    // Note: D8 would replace the ternary expression `x ? 1 : 0` with `x`
+    // but explicit `if` is preserved.
+    int src_x;
+    if (x) {
+      src_x = 1;
+    } else {
+      src_x = 0;
+    }
+    int src_y;
+    if (y) {
+      src_y = 1;
+    } else {
+      src_y = 0;
+    }
+    return Integer.compare(src_x, src_y);
+  }
+
+  /// CHECK-START: int TestCompare.compareBytes(byte, byte) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareBytes(byte, byte) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  private static int compareBytes(byte x, byte y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareShorts(short, short) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareShorts(short, short) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  private static int compareShorts(short x, short y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareChars(char, char) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareChars(char, char) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  private static int compareChars(char x, char y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareInts(int, int) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareInts(int, int) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  private static int compareInts(int x, int y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareLongs(long, long) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareLongs(long, long) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  private static int compareLongs(long x, long y) {
+    return Long.compare(x, y);
+  }
+
+
+  /// CHECK-START: int TestCompare.compareByteShort(byte, short) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareByteShort(byte, short) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareByteShort(byte x, short y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareByteChar(byte, char) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareByteChar(byte, char) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareByteChar(byte x, char y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareByteInt(byte, int) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareByteInt(byte, int) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareByteInt(byte x, int y) {
+    return Integer.compare(x, y);
+  }
+
+
+  /// CHECK-START: int TestCompare.compareShortByte(short, byte) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareShortByte(short, byte) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareShortByte(short x, byte y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareShortChar(short, char) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareShortChar(short, char) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareShortChar(short x, char y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareShortInt(short, int) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareShortInt(short, int) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareShortInt(short x, int y) {
+    return Integer.compare(x, y);
+  }
+
+
+  /// CHECK-START: int TestCompare.compareCharByte(char, byte) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareCharByte(char, byte) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareCharByte(char x, byte y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareCharShort(char, short) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareCharShort(char, short) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareCharShort(char x, short y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareCharInt(char, int) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareCharInt(char, int) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareCharInt(char x, int y) {
+    return Integer.compare(x, y);
+  }
+
+
+  /// CHECK-START: int TestCompare.compareIntByte(int, byte) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareIntByte(int, byte) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareIntByte(int x, byte y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareIntShort(int, short) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareIntShort(int, short) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareIntShort(int x, short y) {
+    return Integer.compare(x, y);
+  }
+
+  /// CHECK-START: int TestCompare.compareIntChar(int, char) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestCompare.compareIntChar(int, char) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  public static int compareIntChar(int x, char y) {
+    return Integer.compare(x, y);
+  }
+
+
+  public static void testCompareBooleans() {
+    expectEquals(-1, compareBooleans(false, true));
+    expectEquals(-1, compareBooleans2(false, true));
+
+    expectEquals(0, compareBooleans(false, false));
+    expectEquals(0, compareBooleans(true, true));
+    expectEquals(0, compareBooleans2(false, false));
+    expectEquals(0, compareBooleans2(true, true));
+
+    expectEquals(1, compareBooleans(true, false));
+    expectEquals(1, compareBooleans2(true, false));
+  }
+
+  public static void testCompareBytes() {
+    expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)(Byte.MIN_VALUE + 1)));
+    expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)-1));
+    expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)0));
+    expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)1));
+    expectEquals(-1, compareBytes(Byte.MIN_VALUE, Byte.MAX_VALUE));
+    expectEquals(-1, compareBytes((byte)-1, (byte)0));
+    expectEquals(-1, compareBytes((byte)-1, (byte)1));
+    expectEquals(-1, compareBytes((byte)0, (byte)1));
+
+    expectEquals(0, compareBytes(Byte.MIN_VALUE, Byte.MIN_VALUE));
+    expectEquals(0, compareBytes((byte)-1, (byte)-1));
+    expectEquals(0, compareBytes((byte)0, (byte)0));
+    expectEquals(0, compareBytes((byte)1, (byte)1));
+    expectEquals(0, compareBytes(Byte.MAX_VALUE, Byte.MAX_VALUE));
+
+    expectEquals(1, compareBytes((byte)0, (byte)-1));
+    expectEquals(1, compareBytes((byte)1, (byte)-1));
+    expectEquals(1, compareBytes((byte)1, (byte)0));
+    expectEquals(1, compareBytes(Byte.MAX_VALUE, Byte.MIN_VALUE));
+    expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)-1));
+    expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)0));
+    expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)1));
+    expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
+
+    for (byte i = -11; i <= 11; i++) {
+      for (byte j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareBytes(i, j));
+      }
+    }
+  }
+
+  public static void testCompareShorts() {
+    expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)(Short.MIN_VALUE + 1)));
+    expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)-1));
+    expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)0));
+    expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)1));
+    expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)Short.MAX_VALUE));
+    expectEquals(-1, compareShorts((short)-1, (short)0));
+    expectEquals(-1, compareShorts((short)-1, (short)1));
+    expectEquals(-1, compareShorts((short)0, (short)1));
+
+    expectEquals(0, compareShorts(Short.MIN_VALUE, Short.MIN_VALUE));
+    expectEquals(0, compareShorts((short)-1, (short)-1));
+    expectEquals(0, compareShorts((short)0, (short)0));
+    expectEquals(0, compareShorts((short)1, (short)1));
+    expectEquals(0, compareShorts(Short.MAX_VALUE, Short.MAX_VALUE));
+
+    expectEquals(1, compareShorts((short)0, (short)-1));
+    expectEquals(1, compareShorts((short)1, (short)-1));
+    expectEquals(1, compareShorts((short)1, (short)0));
+    expectEquals(1, compareShorts(Short.MAX_VALUE, Short.MIN_VALUE));
+    expectEquals(1, compareShorts(Short.MAX_VALUE, (short)-1));
+    expectEquals(1, compareShorts(Short.MAX_VALUE, (short)0));
+    expectEquals(1, compareShorts(Short.MAX_VALUE, (short)1));
+    expectEquals(1, compareShorts(Short.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
+
+    for (short i = -11; i <= 11; i++) {
+      for (short j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareShorts(i, j));
+      }
+    }
+  }
+
+  public static void testCompareChars() {
+    expectEquals(-1, compareChars((char)0, Character.MAX_VALUE));
+    expectEquals(-1, compareChars((char)0, (char)1));
+
+    expectEquals(0, compareChars((char)0, (char)0));
+    expectEquals(0, compareChars((char)1, (char)1));
+    expectEquals(0, compareChars(Character.MAX_VALUE, Character.MAX_VALUE));
+
+    expectEquals(1, compareChars((char)1, (char)0));
+    expectEquals(1, compareChars(Character.MAX_VALUE, (char)0));
+    expectEquals(1, compareChars(Character.MAX_VALUE, (char)1));
+    expectEquals(1, compareChars(Character.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
+
+    for (char i = 0; i <= 11; i++) {
+      for (char j = 0; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareChars(i, j));
+      }
+    }
+  }
+
+  public static void testCompareInts() {
+    expectEquals(-1, compareInts(Integer.MIN_VALUE, Integer.MIN_VALUE + 1));
+    expectEquals(-1, compareInts(Integer.MIN_VALUE, -1));
+    expectEquals(-1, compareInts(Integer.MIN_VALUE, 0));
+    expectEquals(-1, compareInts(Integer.MIN_VALUE, 1));
+    expectEquals(-1, compareInts(Integer.MIN_VALUE, Integer.MAX_VALUE));
+    expectEquals(-1, compareInts(-1, 0));
+    expectEquals(-1, compareInts(-1, 1));
+    expectEquals(-1, compareInts(0, 1));
+
+    expectEquals(0, compareInts(Integer.MIN_VALUE, Integer.MIN_VALUE));
+    expectEquals(0, compareInts(-1, -1));
+    expectEquals(0, compareInts(0, 0));
+    expectEquals(0, compareInts(1, 1));
+    expectEquals(0, compareInts(Integer.MAX_VALUE, Integer.MAX_VALUE));
+
+    expectEquals(1, compareInts(0, -1));
+    expectEquals(1, compareInts(1, -1));
+    expectEquals(1, compareInts(1, 0));
+    expectEquals(1, compareInts(Integer.MAX_VALUE, Integer.MIN_VALUE));
+    expectEquals(1, compareInts(Integer.MAX_VALUE, -1));
+    expectEquals(1, compareInts(Integer.MAX_VALUE, 0));
+    expectEquals(1, compareInts(Integer.MAX_VALUE, 1));
+    expectEquals(1, compareInts(Integer.MAX_VALUE, Integer.MAX_VALUE - 1));
+
+    for (int i = -11; i <= 11; i++) {
+      for (int j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareInts(i, j));
+      }
+    }
+  }
+
+  public static void testCompareLongs() {
+    expectEquals(-1, compareLongs(Long.MIN_VALUE, Long.MIN_VALUE + 1L));
+    expectEquals(-1, compareLongs(Long.MIN_VALUE, -1L));
+    expectEquals(-1, compareLongs(Long.MIN_VALUE, 0L));
+    expectEquals(-1, compareLongs(Long.MIN_VALUE, 1L));
+    expectEquals(-1, compareLongs(Long.MIN_VALUE, Long.MAX_VALUE));
+    expectEquals(-1, compareLongs(-1L, 0L));
+    expectEquals(-1, compareLongs(-1L, 1L));
+    expectEquals(-1, compareLongs(0L, 1L));
+
+    expectEquals(0, compareLongs(Long.MIN_VALUE, Long.MIN_VALUE));
+    expectEquals(0, compareLongs(-1L, -1L));
+    expectEquals(0, compareLongs(0L, 0L));
+    expectEquals(0, compareLongs(1L, 1L));
+    expectEquals(0, compareLongs(Long.MAX_VALUE, Long.MAX_VALUE));
+
+    expectEquals(1, compareLongs(0L, -1L));
+    expectEquals(1, compareLongs(1L, -1L));
+    expectEquals(1, compareLongs(1L, 0L));
+    expectEquals(1, compareLongs(Long.MAX_VALUE, Long.MIN_VALUE));
+    expectEquals(1, compareLongs(Long.MAX_VALUE, -1L));
+    expectEquals(1, compareLongs(Long.MAX_VALUE, 0L));
+    expectEquals(1, compareLongs(Long.MAX_VALUE, 1L));
+    expectEquals(1, compareLongs(Long.MAX_VALUE, Long.MAX_VALUE - 1L));
+
+    expectEquals(-1, compareLongs(0x111111117FFFFFFFL, 0x11111111FFFFFFFFL));
+    expectEquals(0, compareLongs(0x111111117FFFFFFFL, 0x111111117FFFFFFFL));
+    expectEquals(1, compareLongs(0x11111111FFFFFFFFL, 0x111111117FFFFFFFL));
+
+    for (long i = -11L; i <= 11L; i++) {
+      for (long j = -11L; j <= 11L; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareLongs(i, j));
+      }
+    }
+
+    for (long i = Long.MIN_VALUE; i <= Long.MIN_VALUE + 11L; i++) {
+      expectEquals(-1, compareLongs(i, 0));
+    }
+
+    for (long i = Long.MAX_VALUE; i >= Long.MAX_VALUE - 11L; i--) {
+      expectEquals(1, compareLongs(i, 0));
+    }
+  }
+
+
+  public static void testCompareByteShort() {
+    expectEquals(-1, compareByteShort(Byte.MIN_VALUE, (short)-1));
+    expectEquals(-1, compareByteShort(Byte.MIN_VALUE, (short)0));
+    expectEquals(-1, compareByteShort(Byte.MIN_VALUE, (short)1));
+    expectEquals(-1, compareByteShort(Byte.MIN_VALUE, Short.MAX_VALUE));
+    expectEquals(-1, compareByteShort((byte)-1, (short)0));
+    expectEquals(-1, compareByteShort((byte)-1, (short)1));
+    expectEquals(-1, compareByteShort((byte)0, (short)1));
+    expectEquals(-1, compareByteShort(Byte.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
+    expectEquals(-1, compareByteShort(Byte.MAX_VALUE, Short.MAX_VALUE));
+
+    expectEquals(0, compareByteShort((byte)-1, (short)-1));
+    expectEquals(0, compareByteShort((byte)0, (short)0));
+    expectEquals(0, compareByteShort((byte)1, (short)1));
+
+    expectEquals(1, compareByteShort(Byte.MIN_VALUE, Short.MIN_VALUE));
+    expectEquals(1, compareByteShort(Byte.MIN_VALUE, (short)(Short.MIN_VALUE + 1)));
+    expectEquals(1, compareByteShort((byte)0, (short)-1));
+    expectEquals(1, compareByteShort((byte)1, (short)-1));
+    expectEquals(1, compareByteShort((byte)1, (short)0));
+    expectEquals(1, compareByteShort(Byte.MAX_VALUE, Short.MIN_VALUE));
+    expectEquals(1, compareByteShort(Byte.MAX_VALUE, (short)-1));
+    expectEquals(1, compareByteShort(Byte.MAX_VALUE, (short)0));
+    expectEquals(1, compareByteShort(Byte.MAX_VALUE, (short)1));
+
+    for (byte i = -11; i <= 11; i++) {
+      for (short j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareByteShort(i, j));
+      }
+    }
+  }
+
+  public static void testCompareByteChar() {
+    expectEquals(-1, compareByteChar(Byte.MIN_VALUE, (char)0));
+    expectEquals(-1, compareByteChar(Byte.MIN_VALUE, (char)1));
+    expectEquals(-1, compareByteChar(Byte.MIN_VALUE, Character.MAX_VALUE));
+    expectEquals(-1, compareByteChar((byte)-1, (char)0));
+    expectEquals(-1, compareByteChar((byte)-1, (char)1));
+    expectEquals(-1, compareByteChar((byte)0, (char)1));
+    expectEquals(-1, compareByteChar(Byte.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
+    expectEquals(-1, compareByteChar(Byte.MAX_VALUE, Character.MAX_VALUE));
+
+    expectEquals(0, compareByteChar((byte)0, (char)0));
+    expectEquals(0, compareByteChar((byte)1, (char)1));
+
+    expectEquals(1, compareByteChar((byte)1, (char)0));
+    expectEquals(1, compareByteChar(Byte.MAX_VALUE, (char)0));
+    expectEquals(1, compareByteChar(Byte.MAX_VALUE, (char)1));
+
+    for (byte i = -11; i <= 11; i++) {
+      for (char j = 0; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareByteChar(i, j));
+      }
+    }
+  }
+
+  public static void testCompareByteInt() {
+    expectEquals(-1, compareByteInt(Byte.MIN_VALUE, -1));
+    expectEquals(-1, compareByteInt(Byte.MIN_VALUE, 0));
+    expectEquals(-1, compareByteInt(Byte.MIN_VALUE, 1));
+    expectEquals(-1, compareByteInt(Byte.MIN_VALUE, Integer.MAX_VALUE));
+    expectEquals(-1, compareByteInt((byte)-1, 0));
+    expectEquals(-1, compareByteInt((byte)-1, 1));
+    expectEquals(-1, compareByteInt((byte)0, 1));
+    expectEquals(-1, compareByteInt(Byte.MAX_VALUE, Integer.MAX_VALUE - 1));
+    expectEquals(-1, compareByteInt(Byte.MAX_VALUE, Integer.MAX_VALUE));
+
+    expectEquals(0, compareByteInt((byte)-1, -1));
+    expectEquals(0, compareByteInt((byte)0, 0));
+    expectEquals(0, compareByteInt((byte)1, 1));
+
+    expectEquals(1, compareByteInt(Byte.MIN_VALUE, Integer.MIN_VALUE));
+    expectEquals(1, compareByteInt(Byte.MIN_VALUE, Integer.MIN_VALUE + 1));
+    expectEquals(1, compareByteInt((byte)0, -1));
+    expectEquals(1, compareByteInt((byte)1, -1));
+    expectEquals(1, compareByteInt((byte)1, 0));
+    expectEquals(1, compareByteInt(Byte.MAX_VALUE, Integer.MIN_VALUE));
+    expectEquals(1, compareByteInt(Byte.MAX_VALUE, -1));
+    expectEquals(1, compareByteInt(Byte.MAX_VALUE, 0));
+    expectEquals(1, compareByteInt(Byte.MAX_VALUE, 1));
+
+    for (byte i = -11; i <= 11; i++) {
+      for (int j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareByteInt(i, j));
+      }
+    }
+  }
+
+
+  public static void testCompareShortByte() {
+    expectEquals(-1, compareShortByte(Short.MIN_VALUE, Byte.MIN_VALUE));
+    expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)(Byte.MIN_VALUE + 1)));
+    expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)-1));
+    expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)0));
+    expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)1));
+    expectEquals(-1, compareShortByte(Short.MIN_VALUE, Byte.MAX_VALUE));
+    expectEquals(-1, compareShortByte((short)-1, (byte)0));
+    expectEquals(-1, compareShortByte((short)-1, (byte)1));
+    expectEquals(-1, compareShortByte((short)0, (byte)1));
+
+    expectEquals(0, compareShortByte((short)-1, (byte)-1));
+    expectEquals(0, compareShortByte((short)0, (byte)0));
+    expectEquals(0, compareShortByte((short)1, (byte)1));
+
+    expectEquals(1, compareShortByte((short)0, (byte)-1));
+    expectEquals(1, compareShortByte((short)1, (byte)-1));
+    expectEquals(1, compareShortByte((short)1, (byte)0));
+    expectEquals(1, compareShortByte(Short.MAX_VALUE, Byte.MIN_VALUE));
+    expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)-1));
+    expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)0));
+    expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)1));
+    expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
+    expectEquals(1, compareShortByte(Short.MAX_VALUE, Byte.MAX_VALUE));
+
+    for (short i = -11; i <= 11; i++) {
+      for (byte j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareShortByte(i, j));
+      }
+    }
+  }
+
+  public static void testCompareShortChar() {
+    expectEquals(-1, compareShortChar(Short.MIN_VALUE, (char)0));
+    expectEquals(-1, compareShortChar(Short.MIN_VALUE, (char)1));
+    expectEquals(-1, compareShortChar(Short.MIN_VALUE, Character.MAX_VALUE));
+    expectEquals(-1, compareShortChar((short)-1, (char)0));
+    expectEquals(-1, compareShortChar((short)-1, (char)1));
+    expectEquals(-1, compareShortChar((short)0, (char)1));
+    expectEquals(-1, compareShortChar(Short.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
+    expectEquals(-1, compareShortChar(Short.MAX_VALUE, Character.MAX_VALUE));
+
+    expectEquals(0, compareShortChar((short)0, (char)0));
+    expectEquals(0, compareShortChar((short)1, (char)1));
+
+    expectEquals(1, compareShortChar((short)1, (char)0));
+    expectEquals(1, compareShortChar(Short.MAX_VALUE, (char)0));
+    expectEquals(1, compareShortChar(Short.MAX_VALUE, (char)1));
+
+    for (short i = -11; i <= 11; i++) {
+      for (char j = 0; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareShortChar(i, j));
+      }
+    }
+  }
+
+  public static void testCompareShortInt() {
+    expectEquals(-1, compareShortInt(Short.MIN_VALUE, -1));
+    expectEquals(-1, compareShortInt(Short.MIN_VALUE, 0));
+    expectEquals(-1, compareShortInt(Short.MIN_VALUE, 1));
+    expectEquals(-1, compareShortInt(Short.MIN_VALUE, Integer.MAX_VALUE));
+    expectEquals(-1, compareShortInt((short)-1, 0));
+    expectEquals(-1, compareShortInt((short)-1, 1));
+    expectEquals(-1, compareShortInt((short)0, 1));
+    expectEquals(-1, compareShortInt(Short.MAX_VALUE, Integer.MAX_VALUE - 1));
+    expectEquals(-1, compareShortInt(Short.MAX_VALUE, Integer.MAX_VALUE));
+
+    expectEquals(0, compareShortInt((short)-1, -1));
+    expectEquals(0, compareShortInt((short)0, 0));
+    expectEquals(0, compareShortInt((short)1, 1));
+
+    expectEquals(1, compareShortInt(Short.MIN_VALUE, Integer.MIN_VALUE));
+    expectEquals(1, compareShortInt(Short.MIN_VALUE, Integer.MIN_VALUE + 1));
+    expectEquals(1, compareShortInt((short)0, -1));
+    expectEquals(1, compareShortInt((short)1, -1));
+    expectEquals(1, compareShortInt((short)1, 0));
+    expectEquals(1, compareShortInt(Short.MAX_VALUE, Integer.MIN_VALUE));
+    expectEquals(1, compareShortInt(Short.MAX_VALUE, -1));
+    expectEquals(1, compareShortInt(Short.MAX_VALUE, 0));
+    expectEquals(1, compareShortInt(Short.MAX_VALUE, 1));
+
+    for (short i = -11; i <= 11; i++) {
+      for (int j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareShortInt(i, j));
+      }
+    }
+  }
+
+
+  public static void testCompareCharByte() {
+    expectEquals(-1, compareCharByte((char)0, (byte)1));
+    expectEquals(-1, compareCharByte((char)0, Byte.MAX_VALUE));
+
+    expectEquals(0, compareCharByte((char)0, (byte)0));
+    expectEquals(0, compareCharByte((char)1, (byte)1));
+
+    expectEquals(1, compareCharByte((char)0, Byte.MIN_VALUE));
+    expectEquals(1, compareCharByte((char)0, (byte)(Byte.MIN_VALUE + 1)));
+    expectEquals(1, compareCharByte((char)0, (byte)-1));
+    expectEquals(1, compareCharByte((char)1, (byte)-1));
+    expectEquals(1, compareCharByte((char)1, (byte)0));
+    expectEquals(1, compareCharByte(Character.MAX_VALUE, Byte.MIN_VALUE));
+    expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)-1));
+    expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)0));
+    expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)1));
+    expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
+    expectEquals(1, compareCharByte(Character.MAX_VALUE, Byte.MAX_VALUE));
+
+    for (char i = 0; i <= 11; i++) {
+      for (byte j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareCharByte(i, j));
+      }
+    }
+  }
+
+  public static void testCompareCharShort() {
+    expectEquals(-1, compareCharShort((char)0, (short)1));
+    expectEquals(-1, compareCharShort((char)0, Short.MAX_VALUE));
+
+    expectEquals(0, compareCharShort((char)0, (short)0));
+    expectEquals(0, compareCharShort((char)1, (short)1));
+
+    expectEquals(1, compareCharShort((char)0, Short.MIN_VALUE));
+    expectEquals(1, compareCharShort((char)0, (short)(Short.MIN_VALUE + 1)));
+    expectEquals(1, compareCharShort((char)0, (short)-1));
+    expectEquals(1, compareCharShort((char)1, (short)-1));
+    expectEquals(1, compareCharShort((char)1, (short)0));
+    expectEquals(1, compareCharShort(Character.MAX_VALUE, Short.MIN_VALUE));
+    expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)-1));
+    expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)0));
+    expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)1));
+    expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
+    expectEquals(1, compareCharShort(Character.MAX_VALUE, Short.MAX_VALUE));
+
+    for (char i = 0; i <= 11; i++) {
+      for (short j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareCharShort(i, j));
+      }
+    }
+  }
+
+  public static void testCompareCharInt() {
+    expectEquals(-1, compareCharInt((char)0, 1));
+    expectEquals(-1, compareCharInt((char)0, Integer.MAX_VALUE));
+    expectEquals(-1, compareCharInt(Character.MAX_VALUE, Integer.MAX_VALUE - 1));
+    expectEquals(-1, compareCharInt(Character.MAX_VALUE, Integer.MAX_VALUE));
+
+    expectEquals(0, compareCharInt((char)0, 0));
+    expectEquals(0, compareCharInt((char)1, 1));
+
+    expectEquals(1, compareCharInt((char)0, Integer.MIN_VALUE));
+    expectEquals(1, compareCharInt((char)0, Integer.MIN_VALUE + 1));
+    expectEquals(1, compareCharInt((char)0, -1));
+    expectEquals(1, compareCharInt((char)1, -1));
+    expectEquals(1, compareCharInt((char)1, 0));
+    expectEquals(1, compareCharInt(Character.MAX_VALUE, Integer.MIN_VALUE));
+    expectEquals(1, compareCharInt(Character.MAX_VALUE, -1));
+    expectEquals(1, compareCharInt(Character.MAX_VALUE, 0));
+    expectEquals(1, compareCharInt(Character.MAX_VALUE, 1));
+
+    for (char i = 0; i <= 11; i++) {
+      for (int j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareCharInt(i, j));
+      }
+    }
+  }
+
+
+  public static void testCompareIntByte() {
+    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, Byte.MIN_VALUE));
+    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)(Byte.MIN_VALUE + 1)));
+    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)-1));
+    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)0));
+    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)1));
+    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, Byte.MAX_VALUE));
+    expectEquals(-1, compareIntByte(-1, (byte)0));
+    expectEquals(-1, compareIntByte(-1, (byte)1));
+    expectEquals(-1, compareIntByte(0, (byte)1));
+
+    expectEquals(0, compareIntByte(-1, (byte)-1));
+    expectEquals(0, compareIntByte(0, (byte)0));
+    expectEquals(0, compareIntByte(1, (byte)1));
+
+    expectEquals(1, compareIntByte(0, (byte)-1));
+    expectEquals(1, compareIntByte(1, (byte)-1));
+    expectEquals(1, compareIntByte(1, (byte)0));
+    expectEquals(1, compareIntByte(Integer.MAX_VALUE, Byte.MIN_VALUE));
+    expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)-1));
+    expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)0));
+    expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)1));
+    expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
+    expectEquals(1, compareIntByte(Integer.MAX_VALUE, Byte.MAX_VALUE));
+
+    for (int i = -11; i <= 11; i++) {
+      for (byte j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareIntByte(i, j));
+      }
+    }
+  }
+
+  public static void testCompareIntShort() {
+    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, Short.MIN_VALUE));
+    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)(Short.MIN_VALUE + 1)));
+    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)-1));
+    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)0));
+    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)1));
+    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, Short.MAX_VALUE));
+    expectEquals(-1, compareIntShort(-1, (short)0));
+    expectEquals(-1, compareIntShort(-1, (short)1));
+    expectEquals(-1, compareIntShort(0, (short)1));
+
+    expectEquals(0, compareIntShort(-1, (short)-1));
+    expectEquals(0, compareIntShort(0, (short)0));
+    expectEquals(0, compareIntShort(1, (short)1));
+
+    expectEquals(1, compareIntShort(0, (short)-1));
+    expectEquals(1, compareIntShort(1, (short)-1));
+    expectEquals(1, compareIntShort(1, (short)0));
+    expectEquals(1, compareIntShort(Integer.MAX_VALUE, Short.MIN_VALUE));
+    expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)-1));
+    expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)0));
+    expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)1));
+    expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
+    expectEquals(1, compareIntShort(Integer.MAX_VALUE, Short.MAX_VALUE));
+
+    for (int i = -11; i <= 11; i++) {
+      for (short j = -11; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareIntShort(i, j));
+      }
+    }
+  }
+
+  public static void testCompareIntChar() {
+    expectEquals(-1, compareIntChar(Integer.MIN_VALUE, (char)0));
+    expectEquals(-1, compareIntChar(Integer.MIN_VALUE, (char)1));
+    expectEquals(-1, compareIntChar(Integer.MIN_VALUE, Character.MAX_VALUE));
+    expectEquals(-1, compareIntChar(-1, (char)0));
+    expectEquals(-1, compareIntChar(-1, (char)1));
+    expectEquals(-1, compareIntChar(0, (char)1));
+
+    expectEquals(0, compareIntChar(0, (char)0));
+    expectEquals(0, compareIntChar(1, (char)1));
+
+    expectEquals(1, compareIntChar(1, (char)0));
+    expectEquals(1, compareIntChar(Integer.MAX_VALUE, (char)0));
+    expectEquals(1, compareIntChar(Integer.MAX_VALUE, (char)1));
+    expectEquals(1, compareIntChar(Integer.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
+    expectEquals(1, compareIntChar(Integer.MAX_VALUE, Character.MAX_VALUE));
+
+    for (int i = -11; i <= 11; i++) {
+      for (char j = 0; j <= 11; j++) {
+        int expected = 0;
+        if (i < j) expected = -1;
+        else if (i > j) expected = 1;
+        expectEquals(expected, compareIntChar(i, j));
+      }
+    }
+  }
+
+
+  public static void main() {
+    $opt$noinline$testReplaceInputWithItself(42);
+
+    testCompareBooleans();
+    testCompareBytes();
+    testCompareShorts();
+    testCompareChars();
+    testCompareInts();
+    testCompareLongs();
+
+    testCompareByteShort();
+    testCompareByteChar();
+    testCompareByteInt();
+
+    testCompareShortByte();
+    testCompareShortChar();
+    testCompareShortInt();
+
+    testCompareCharByte();
+    testCompareCharShort();
+    testCompareCharInt();
+
+    testCompareIntByte();
+    testCompareIntShort();
+    testCompareIntChar();
+
+    System.out.println("TestCompare passed");
+  }
+
+  private static void expectEquals(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+}
diff --git a/test/567-checker-builder-intrinsics/src/TestFpAbs.java b/test/567-checker-builder-intrinsics/src/TestFpAbs.java
new file mode 100644
index 0000000..e6c338d
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/src/TestFpAbs.java
@@ -0,0 +1,190 @@
+/*
+ * 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.
+ */
+
+/**
+ * A few tests of Math.abs for floating-point data.
+ *
+ * Note, as a "quality of implementation", rather than pure "spec compliance",
+ * we require that Math.abs() clears the sign bit (but changes nothing else)
+ * for all numbers, including NaN (signaling NaN may become quiet though).
+ */
+public class TestFpAbs {
+
+  private final static boolean isDalvik =
+      System.getProperty("java.vm.name").equals("Dalvik");
+
+  private static final int SPQUIET = 1 << 22;
+  private static final long DPQUIET = 1L << 51;
+
+  public static boolean doThrow = false;
+
+  /// CHECK-START: float TestFpAbs.$opt$noinline$absSP(float) builder (after)
+  /// CHECK-DAG: <<Result:f\d+>> Abs
+  /// CHECK-DAG:                 Return [<<Result>>]
+  private static float $opt$noinline$absSP(float f) {
+    return Math.abs(f);
+  }
+
+  /// CHECK-START: double TestFpAbs.$opt$noinline$absDP(double) builder (after)
+  /// CHECK-DAG: <<Result:d\d+>> Abs
+  /// CHECK-DAG:                 Return [<<Result>>]
+  private static double $opt$noinline$absDP(double d) {
+    return Math.abs(d);
+  }
+
+  public static void main() {
+    // A few obvious numbers.
+    for (float f = -100.0f; f < 0.0f; f += 0.5f) {
+      expectEqualsSP(-f, $opt$noinline$absSP(f));
+    }
+    for (float f = 0.0f; f <= 100.0f; f += 0.5f) {
+      expectEqualsSP(f, $opt$noinline$absSP(f));
+    }
+    for (float f = -1.5f; f <= -1.499f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) {
+      expectEqualsSP(-f, $opt$noinline$absSP(f));
+    }
+    for (float f = 1.499f; f <= 1.5f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) {
+      expectEqualsSP(f, $opt$noinline$absSP(f));
+    }
+
+    // Zero
+    expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(+0.0f)));
+    expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(-0.0f)));
+
+    // Inf.
+    expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.NEGATIVE_INFINITY));
+    expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.POSITIVE_INFINITY));
+
+    // A few NaN numbers.
+    int[] spnans = {
+      0x7f800001,  // signaling
+      0x7fa00000,
+      0x7fbfffff,
+      0x7fc00000,  // quiet
+      0x7fc00001,
+      0x7fffffff,
+      0xff800001,  // signaling
+      0xffa00000,
+      0xffbfffff,
+      0xffc00000,  // quiet
+      0xffffffff
+    };
+    for (int i = 0; i < spnans.length; i++) {
+      float f = Float.intBitsToFloat(spnans[i]);
+      expectEqualsNaN32(
+          spnans[i] & Integer.MAX_VALUE,
+          Float.floatToRawIntBits($opt$noinline$absSP(f)));
+    }
+
+    // A few obvious numbers.
+    for (double d = -100.0; d < 0.0; d += 0.5) {
+      expectEqualsDP(-d, $opt$noinline$absDP(d));
+    }
+    for (double d = 0.0; d <= 100.0; d += 0.5) {
+      expectEqualsDP(d, $opt$noinline$absDP(d));
+    }
+    for (double d = -1.5d; d <= -1.49999999999d; d = Math.nextAfter(d, Double.POSITIVE_INFINITY)) {
+      expectEqualsDP(-d, $opt$noinline$absDP(d));
+    }
+    for (double d = 1.49999999999d; d <= 1.5; d = Math.nextAfter(d, Double.POSITIVE_INFINITY)) {
+      expectEqualsDP(d, $opt$noinline$absDP(d));
+    }
+
+    // Zero
+    expectEquals64(0L, Double.doubleToRawLongBits($opt$noinline$absDP(+0.0f)));
+    expectEquals64(0L, Double.doubleToRawLongBits($opt$noinline$absDP(-0.0f)));
+
+    // Inf.
+    expectEqualsDP(Double.POSITIVE_INFINITY, $opt$noinline$absDP(Double.NEGATIVE_INFINITY));
+    expectEqualsDP(Double.POSITIVE_INFINITY, $opt$noinline$absDP(Double.POSITIVE_INFINITY));
+
+    // A few NaN numbers.
+    long[] dpnans = {
+      0x7ff0000000000001L,
+      0x7ff4000000000000L,
+      0x7ff8000000000000L,
+      0x7fffffffffffffffL,
+      0xfff0000000000001L,
+      0xfff4000000000000L,
+      0xfff8000000000000L,
+      0xffffffffffffffffL
+    };
+    for (int i = 0; i < dpnans.length; i++) {
+      double d = Double.longBitsToDouble(dpnans[i]);
+      expectEqualsNaN64(
+          dpnans[i] & Long.MAX_VALUE,
+          Double.doubleToRawLongBits($opt$noinline$absDP(d)));
+    }
+
+    System.out.println("TestFpAbs passed");
+  }
+
+  private static void expectEquals32(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: 0x" + Integer.toHexString(expected)
+          + ", found: 0x" + Integer.toHexString(result));
+    }
+  }
+
+  // We allow that an expected NaN result has become quiet.
+  private static void expectEqualsNaN32(int expected, int result) {
+    if (expected != result && (expected | SPQUIET) != result) {
+      if (!isDalvik) {
+        // If not on ART, relax the expected value more towards just
+        // "spec compliance" and allow sign bit to remain set for NaN.
+        if (expected == (result & Integer.MAX_VALUE)) {
+          return;
+        }
+      }
+      throw new Error("Expected: 0x" + Integer.toHexString(expected)
+          + ", found: 0x" + Integer.toHexString(result));
+    }
+  }
+
+  private static void expectEquals64(long expected, long result) {
+    if (expected != result) {
+      throw new Error("Expected: 0x" + Long.toHexString(expected)
+          + ", found: 0x" + Long.toHexString(result));
+    }
+  }
+
+  // We allow that an expected NaN result has become quiet.
+  private static void expectEqualsNaN64(long expected, long result) {
+    if (expected != result && (expected | DPQUIET) != result) {
+      if (!isDalvik) {
+        // If not on ART, relax the expected value more towards just
+        // "spec compliance" and allow sign bit to remain set for NaN.
+        if (expected == (result & Long.MAX_VALUE)) {
+          return;
+        }
+      }
+      throw new Error("Expected: 0x" + Long.toHexString(expected)
+          + ", found: 0x" + Long.toHexString(result));
+    }
+  }
+
+  private static void expectEqualsSP(float expected, float result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  private static void expectEqualsDP(double expected, double result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+}
diff --git a/test/567-checker-builder-intrinsics/src/TestIsNan.java b/test/567-checker-builder-intrinsics/src/TestIsNan.java
new file mode 100644
index 0000000..03b76d7
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/src/TestIsNan.java
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+public class TestIsNan {
+
+  /// CHECK-START: boolean TestIsNan.isNaN32(float) builder (after)
+  /// CHECK-DAG: <<Result:z\d+>> NotEqual
+  /// CHECK-DAG: Return [<<Result>>]
+  //
+  /// CHECK-START: boolean TestIsNan.isNaN32(float) builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect
+  private static boolean isNaN32(float x) {
+    return Float.isNaN(x);
+  }
+
+  /// CHECK-START: boolean TestIsNan.isNaN64(double) builder (after)
+  /// CHECK-DAG: <<Result:z\d+>> NotEqual
+  /// CHECK-DAG: Return [<<Result>>]
+  //
+  /// CHECK-START: boolean TestIsNan.isNaN64(double) builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect
+  private static boolean isNaN64(double x) {
+    return Double.isNaN(x);
+  }
+
+  public static void main() {
+    // A few distinct numbers.
+    expectFalse(isNaN32(Float.NEGATIVE_INFINITY));
+    expectFalse(isNaN32(-1.0f));
+    expectFalse(isNaN32(-0.0f));
+    expectFalse(isNaN32(0.0f));
+    expectFalse(isNaN32(1.0f));
+    expectFalse(isNaN32(Float.POSITIVE_INFINITY));
+
+    // A few distinct subnormal numbers.
+    expectFalse(isNaN32(Float.intBitsToFloat(0x00400000)));
+    expectFalse(isNaN32(Float.intBitsToFloat(0x80400000)));
+    expectFalse(isNaN32(Float.intBitsToFloat(0x00000001)));
+    expectFalse(isNaN32(Float.intBitsToFloat(0x80000001)));
+
+    // A few NaN numbers.
+    expectTrue(isNaN32(Float.NaN));
+    expectTrue(isNaN32(0.0f / 0.0f));
+    expectTrue(isNaN32((float)Math.sqrt(-1.0f)));
+    float[] fvals = {
+      Float.intBitsToFloat(0x7f800001),
+      Float.intBitsToFloat(0x7fa00000),
+      Float.intBitsToFloat(0x7fc00000),
+      Float.intBitsToFloat(0x7fffffff),
+      Float.intBitsToFloat(0xff800001),
+      Float.intBitsToFloat(0xffa00000),
+      Float.intBitsToFloat(0xffc00000),
+      Float.intBitsToFloat(0xffffffff)
+    };
+    for (int i = 0; i < fvals.length; i++) {
+      expectTrue(isNaN32(fvals[i]));
+    }
+
+    // A few distinct numbers.
+    expectFalse(isNaN64(Double.NEGATIVE_INFINITY));
+    expectFalse(isNaN32(-1.0f));
+    expectFalse(isNaN64(-0.0d));
+    expectFalse(isNaN64(0.0d));
+    expectFalse(isNaN64(1.0d));
+    expectFalse(isNaN64(Double.POSITIVE_INFINITY));
+
+    // A few distinct subnormal numbers.
+    expectFalse(isNaN64(Double.longBitsToDouble(0x0008000000000000l)));
+    expectFalse(isNaN64(Double.longBitsToDouble(0x8008000000000000l)));
+    expectFalse(isNaN64(Double.longBitsToDouble(0x0000000000000001l)));
+    expectFalse(isNaN64(Double.longBitsToDouble(0x8000000000000001l)));
+
+    // A few NaN numbers.
+    expectTrue(isNaN64(Double.NaN));
+    expectTrue(isNaN64(0.0d / 0.0d));
+    expectTrue(isNaN64(Math.sqrt(-1.0d)));
+    double[] dvals = {
+      Double.longBitsToDouble(0x7ff0000000000001L),
+      Double.longBitsToDouble(0x7ff4000000000000L),
+      Double.longBitsToDouble(0x7ff8000000000000L),
+      Double.longBitsToDouble(0x7fffffffffffffffL),
+      Double.longBitsToDouble(0xfff0000000000001L),
+      Double.longBitsToDouble(0xfff4000000000000L),
+      Double.longBitsToDouble(0xfff8000000000000L),
+      Double.longBitsToDouble(0xffffffffffffffffL)
+    };
+    for (int i = 0; i < dvals.length; i++) {
+      expectTrue(isNaN64(dvals[i]));
+    }
+
+    System.out.println("TestIsNan passed");
+  }
+
+  private static void expectTrue(boolean value) {
+    if (!value) {
+      throw new Error("Expected True");
+    }
+  }
+
+  private static void expectFalse(boolean value) {
+    if (value) {
+      throw new Error("Expected False");
+    }
+  }
+}
diff --git a/test/567-checker-builder-intrinsics/src/TestMinMax.java b/test/567-checker-builder-intrinsics/src/TestMinMax.java
new file mode 100644
index 0000000..0e88517
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/src/TestMinMax.java
@@ -0,0 +1,777 @@
+/*
+ * 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.
+ */
+
+/**
+ * Functional tests for detecting min/max.
+ */
+public class TestMinMax {
+
+  //
+  // Direct intrinsics.
+  //
+
+  /// CHECK-START: int TestMinMax.minI(int) builder (after)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Con:i\d+>> IntConstant 20
+  /// CHECK-DAG: <<Min:i\d+>> Min [<<Par>>,<<Con>>]
+  /// CHECK-DAG:              Return [<<Min>>]
+  //
+  /// CHECK-START: int TestMinMax.minI(int) builder (after)
+  /// CHECK-NOT:              InvokeStaticOrDirect
+  //
+  /// CHECK-START-ARM64: int TestMinMax.minI(int) disassembly (after)
+  /// CHECK-NOT:              mov {{w\d+}}, #0x14
+  /// CHECK:                  cmp {{w\d+}}, #0x14
+  //  Check that the constant generation was handled by VIXL.
+  /// CHECK:                  mov w16, #0x14
+  /// CHECK:                  csel {{w\d+}}, {{w\d+}}, w16, lt
+  public static int minI(int a) {
+    return Math.min(a, 20);
+  }
+
+  /// CHECK-START: long TestMinMax.minL(long) builder (after)
+  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
+  /// CHECK-DAG: <<Con:j\d+>> LongConstant 20
+  /// CHECK-DAG: <<Min:j\d+>> Min [<<Par>>,<<Con>>]
+  /// CHECK-DAG:              Return [<<Min>>]
+  //
+  /// CHECK-START: long TestMinMax.minL(long) builder (after)
+  /// CHECK-NOT:              InvokeStaticOrDirect
+  //
+  /// CHECK-START-ARM64: long TestMinMax.minL(long) disassembly (after)
+  /// CHECK-NOT:              mov {{x\d+}}, #0x14
+  /// CHECK:                  cmp {{x\d+}}, #0x14
+  //  Check that the constant generation was handled by VIXL.
+  /// CHECK:                  mov x16, #0x14
+  /// CHECK:                  csel {{x\d+}}, {{x\d+}}, x16, lt
+  public static long minL(long a) {
+    return Math.min(a, 20L);
+  }
+
+  /// CHECK-START: int TestMinMax.maxI(int) builder (after)
+  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Con:i\d+>> IntConstant 20
+  /// CHECK-DAG: <<Max:i\d+>> Max [<<Par>>,<<Con>>]
+  /// CHECK-DAG:              Return [<<Max>>]
+  //
+  /// CHECK-START: int TestMinMax.maxI(int) builder (after)
+  /// CHECK-NOT:              InvokeStaticOrDirect
+  //
+  /// CHECK-START-ARM64: int TestMinMax.maxI(int) disassembly (after)
+  /// CHECK-NOT:              mov {{w\d+}}, #0x14
+  /// CHECK:                  cmp {{w\d+}}, #0x14
+  //  Check that the constant generation was handled by VIXL.
+  /// CHECK:                  mov w16, #0x14
+  /// CHECK:                  csel {{w\d+}}, {{w\d+}}, w16, gt
+  public static int maxI(int a) {
+    return Math.max(a, 20);
+  }
+
+  /// CHECK-START: long TestMinMax.maxL(long) builder (after)
+  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
+  /// CHECK-DAG: <<Con:j\d+>> LongConstant 20
+  /// CHECK-DAG: <<Max:j\d+>> Max [<<Par>>,<<Con>>]
+  /// CHECK-DAG:              Return [<<Max>>]
+  //
+  /// CHECK-START: long TestMinMax.maxL(long) builder (after)
+  /// CHECK-NOT:              InvokeStaticOrDirect
+  //
+  /// CHECK-START-ARM64: long TestMinMax.maxL(long) disassembly (after)
+  /// CHECK-NOT:              mov {{x\d+}}, #0x14
+  /// CHECK:                  cmp {{x\d+}}, #0x14
+  //  Check that the constant generation was handled by VIXL.
+  /// CHECK:                  mov x16, #0x14
+  /// CHECK:                  csel {{x\d+}}, {{x\d+}}, x16, gt
+  public static long maxL(long a) {
+    return Math.max(a, 20L);
+  }
+
+  //
+  // Special Cases
+  //
+
+  /// CHECK-START-ARM64: int TestMinMax.minIntConstantZero(int) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{w\d+}}, #0x0
+  /// CHECK:            cmp {{w\d+}}, #0x0 (0)
+  /// CHECK:            csel {{w\d+}}, {{w\d+}}, wzr, lt
+  /// CHECK:            ret
+  public static int minIntConstantZero(int a) {
+    return Math.min(a, 0);
+  }
+
+  /// CHECK-START-ARM64: int TestMinMax.minIntConstantOne(int) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{w\d+}}, #0x1
+  /// CHECK:            cmp {{w\d+}}, #0x1 (1)
+  /// CHECK:            csinc {{w\d+}}, {{w\d+}}, wzr, lt
+  /// CHECK:            ret
+  public static int minIntConstantOne(int a) {
+    return Math.min(a, 1);
+  }
+
+  /// CHECK-START-ARM64: int TestMinMax.minIntConstantMinusOne(int) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{w\d+}}, #0xffffffff
+  /// CHECK:            cmn {{w\d+}}, #0x1 (1)
+  /// CHECK:            csinv {{w\d+}}, {{w\d+}}, wzr, lt
+  /// CHECK:            ret
+  public static int minIntConstantMinusOne(int a) {
+    return Math.min(a, -1);
+  }
+
+  /// CHECK-START-ARM64: long TestMinMax.minLongConstantZero(long) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{x\d+}}, #0x0
+  /// CHECK:            cmp {{x\d+}}, #0x0 (0)
+  /// CHECK:            csel {{x\d+}}, {{x\d+}}, xzr, lt
+  /// CHECK:            ret
+  public static long minLongConstantZero(long a) {
+    return Math.min(a, 0L);
+  }
+
+  /// CHECK-START-ARM64: long TestMinMax.minLongConstantOne(long) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{x\d+}}, #0x1
+  /// CHECK:            cmp {{x\d+}}, #0x1 (1)
+  /// CHECK:            csinc {{x\d+}}, {{x\d+}}, xzr, lt
+  /// CHECK:            ret
+  public static long minLongConstantOne(long a) {
+    return Math.min(a, 1L);
+  }
+
+  /// CHECK-START-ARM64: long TestMinMax.minLongConstantMinusOne(long) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{x\d+}}, #0xffffffffffffffff
+  /// CHECK:            cmn {{x\d+}}, #0x1 (1)
+  /// CHECK:            csinv {{x\d+}}, {{x\d+}}, xzr, lt
+  /// CHECK:            ret
+  public static long minLongConstantMinusOne(long a) {
+    return Math.min(a, -1L);
+  }
+
+  /// CHECK-START-ARM64: int TestMinMax.maxIntConstantZero(int) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{w\d+}}, #0x0
+  /// CHECK:            cmp {{w\d+}}, #0x0 (0)
+  /// CHECK:            csel {{w\d+}}, {{w\d+}}, wzr, gt
+  /// CHECK:            ret
+  public static int maxIntConstantZero(int a) {
+    return Math.max(a, 0);
+  }
+
+  /// CHECK-START-ARM64: int TestMinMax.maxIntConstantOne(int) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{w\d+}}, #0x1
+  /// CHECK:            cmp {{w\d+}}, #0x1 (1)
+  /// CHECK:            csinc {{w\d+}}, {{w\d+}}, wzr, gt
+  /// CHECK:            ret
+  public static int maxIntConstantOne(int a) {
+    return Math.max(a, 1);
+  }
+
+  /// CHECK-START-ARM64: int TestMinMax.maxIntConstantMinusOne(int) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{w\d+}}, #0xffffffff
+  /// CHECK:            cmn {{w\d+}}, #0x1 (1)
+  /// CHECK:            csinv {{w\d+}}, {{w\d+}}, wzr, gt
+  /// CHECK:            ret
+  public static int maxIntConstantMinusOne(int a) {
+    return Math.max(a, -1);
+  }
+
+  /// CHECK-START-ARM64: int TestMinMax.maxIntLargeConstant(int) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK:            mov {{w\d+}}, #0x2001
+  /// CHECK:            cmp {{w\d+}}, {{w\d+}}
+  //  Check that constant generation was not handled by VIXL.
+  /// CHECK-NOT:        mov {{w\d+}}, #0x2001
+  /// CHECK:            csel {{w\d+}}, {{w\d+}}, {{w\d+}}, gt
+  /// CHECK:            ret
+  public static int maxIntLargeConstant(int a) {
+    return Math.max(a, 8193);
+  }
+
+  /// CHECK-START-ARM64: long TestMinMax.maxLongConstantZero(long) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{x\d+}}, #0x0
+  /// CHECK:            cmp {{x\d+}}, #0x0 (0)
+  /// CHECK:            csel {{x\d+}}, {{x\d+}}, xzr, gt
+  /// CHECK:            ret
+  public static long maxLongConstantZero(long a) {
+    return Math.max(a, 0L);
+  }
+
+  /// CHECK-START-ARM64: long TestMinMax.maxLongConstantOne(long) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{x\d+}}, #0x1
+  /// CHECK:            cmp {{x\d+}}, #0x1 (1)
+  /// CHECK:            csinc {{x\d+}}, {{x\d+}}, xzr, gt
+  /// CHECK:            ret
+  public static long maxLongConstantOne(long a) {
+    return Math.max(a, 1L);
+  }
+
+  /// CHECK-START-ARM64: long TestMinMax.maxLongConstantMinusOne(long) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK-NOT:        mov {{x\d+}}, #0xffffffffffffffff
+  /// CHECK:            cmn {{x\d+}}, #0x1 (1)
+  /// CHECK:            csinv {{x\d+}}, {{x\d+}}, xzr, gt
+  /// CHECK:            ret
+  public static long maxLongConstantMinusOne(long a) {
+    return Math.max(a, -1L);
+  }
+
+  /// CHECK-START-ARM64: long TestMinMax.maxLongLargeConstant(long) disassembly (after)
+  /// CHECK-NOT:        InvokeStaticOrDirect
+  /// CHECK:            mov {{x\d+}}, #0x2001
+  /// CHECK:            cmp {{x\d+}}, {{x\d+}}
+  //  Check that constant generation was not handled by VIXL.
+  /// CHECK-NOT:        mov {{x\d+}}, #0x2001
+  /// CHECK:            csel {{x\d+}}, {{x\d+}}, {{x\d+}}, gt
+  /// CHECK:            ret
+  public static long maxLongLargeConstant(long a) {
+    return Math.max(a, 8193L);
+  }
+
+  //
+  // Different types.
+  //
+
+  /// CHECK-START: int TestMinMax.min1(int, int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.min1(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Min:i\d+>> Min
+  /// CHECK-DAG:              Return [<<Min>>]
+  //
+  /// CHECK-START: int TestMinMax.min1(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int min1(int a, int b) {
+    return a < b ? a : b;
+  }
+
+  /// CHECK-START: int TestMinMax.min2(int, int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.min2(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Min:i\d+>> Min
+  /// CHECK-DAG:              Return [<<Min>>]
+  //
+  /// CHECK-START: int TestMinMax.min2(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int min2(int a, int b) {
+    return a <= b ? a : b;
+  }
+
+  /// CHECK-START: int TestMinMax.min3(int, int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.min3(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Min:i\d+>> Min
+  /// CHECK-DAG:              Return [<<Min>>]
+  //
+  /// CHECK-START: int TestMinMax.min3(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int min3(int a, int b) {
+    return a > b ? b : a;
+  }
+
+  /// CHECK-START: int TestMinMax.min4(int, int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.min4(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Min:i\d+>> Min
+  /// CHECK-DAG:              Return [<<Min>>]
+  //
+  /// CHECK-START: int TestMinMax.min4(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int min4(int a, int b) {
+    return a >= b ? b : a;
+  }
+
+  /// CHECK-START: int TestMinMax.min5(short, short) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:s\d+>>,<<Op2:s\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.min5(short, short) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Min:i\d+>> Min
+  /// CHECK-DAG:              Return [<<Min>>]
+  //
+  /// CHECK-START: int TestMinMax.min5(short, short) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int min5(short a, short b) {
+    return a >= b ? b : a;
+  }
+
+  /// CHECK-START: int TestMinMax.min6(byte, byte) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:b\d+>>,<<Op2:b\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.min6(byte, byte) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Min:i\d+>> Min
+  /// CHECK-DAG:              Return [<<Min>>]
+  //
+  /// CHECK-START: int TestMinMax.min6(byte, byte) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int min6(byte a, byte b) {
+    return a >= b ? b : a;
+  }
+
+  /// CHECK-START: long TestMinMax.min7(long, long) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:j\d+>>,<<Op2:j\d+>>]
+  /// CHECK-DAG: <<Sel:j\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: long TestMinMax.min7(long, long) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Min:j\d+>> Min
+  /// CHECK-DAG:              Return [<<Min>>]
+  //
+  /// CHECK-START: long TestMinMax.min7(long, long) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static long min7(long a, long b) {
+    return a >= b ? b : a;
+  }
+
+  /// CHECK-START: int TestMinMax.max1(int, int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.max1(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Max:i\d+>> Max
+  /// CHECK-DAG:              Return [<<Max>>]
+  //
+  /// CHECK-START: int TestMinMax.max1(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int max1(int a, int b) {
+    return a < b ? b : a;
+  }
+
+  /// CHECK-START: int TestMinMax.max2(int, int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.max2(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Max:i\d+>> Max
+  /// CHECK-DAG:              Return [<<Max>>]
+  //
+  /// CHECK-START: int TestMinMax.max2(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int max2(int a, int b) {
+    return a <= b ? b : a;
+  }
+
+  /// CHECK-START: int TestMinMax.max3(int, int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.max3(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Max:i\d+>> Max
+  /// CHECK-DAG:              Return [<<Max>>]
+  //
+  /// CHECK-START: int TestMinMax.max3(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int max3(int a, int b) {
+    return a > b ? a : b;
+  }
+
+  /// CHECK-START: int TestMinMax.max4(int, int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.max4(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Max:i\d+>> Max
+  /// CHECK-DAG:              Return [<<Max>>]
+  //
+  /// CHECK-START: int TestMinMax.max4(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int max4(int a, int b) {
+    return a >= b ? a : b;
+  }
+
+  /// CHECK-START: int TestMinMax.max5(short, short) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:s\d+>>,<<Op2:s\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.max5(short, short) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Max:i\d+>> Max
+  /// CHECK-DAG:              Return [<<Max>>]
+  //
+  /// CHECK-START: int TestMinMax.max5(short, short) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int max5(short a, short b) {
+    return a >= b ? a : b;
+  }
+
+  /// CHECK-START: int TestMinMax.max6(byte, byte) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:b\d+>>,<<Op2:b\d+>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.max6(byte, byte) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Max:i\d+>> Max
+  /// CHECK-DAG:              Return [<<Max>>]
+  //
+  /// CHECK-START: int TestMinMax.max6(byte, byte) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int max6(byte a, byte b) {
+    return a >= b ? a : b;
+  }
+
+  /// CHECK-START: long TestMinMax.max7(long, long) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:j\d+>>,<<Op2:j\d+>>]
+  /// CHECK-DAG: <<Sel:j\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: long TestMinMax.max7(long, long) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Max:j\d+>> Max
+  /// CHECK-DAG:              Return [<<Max>>]
+  //
+  /// CHECK-START: long TestMinMax.max7(long, long) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static long max7(long a, long b) {
+    return a >= b ? a : b;
+  }
+
+  //
+  // Complications.
+  //
+
+  /// CHECK-START: int TestMinMax.min0(int[], int[]) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Ar1:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
+  /// CHECK-DAG: <<Ar2:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
+  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Ar1>>,<<Ar2>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Ar1>>,<<Ar2>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.min0(int[], int[]) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Min:i\d+>> Min
+  /// CHECK-DAG:              Return [<<Min>>]
+  //
+  /// CHECK-START: int TestMinMax.min0(int[], int[]) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int min0(int[] a, int[] b) {
+    // Repeat of array references needs finding the common subexpressions
+    // prior to doing the select and min/max recognition.
+    return a[0] <= b[0] ? a[0] : b[0];
+  }
+
+  /// CHECK-START: int TestMinMax.max0(int[], int[]) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Ar1:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
+  /// CHECK-DAG: <<Ar2:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
+  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Ar1>>,<<Ar2>>]
+  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Ar1>>,<<Ar2>>,<<Cnd>>]
+  /// CHECK-DAG:              Return [<<Sel>>]
+  //
+  /// CHECK-START: int TestMinMax.max0(int[], int[]) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Max:i\d+>> Max
+  /// CHECK-DAG:              Return [<<Max>>]
+  //
+  /// CHECK-START: int TestMinMax.max0(int[], int[]) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:              Select
+  public static int max0(int[] a, int[] b) {
+    // Repeat of array references needs finding the common subexpressions
+    // prior to doing the select and min/max recognition.
+    return a[0] >= b[0] ? a[0] : b[0];
+  }
+
+  /// CHECK-START: int TestMinMax.minmax1(int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
+  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
+  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
+  /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par>>,<<P100>>]
+  /// CHECK-DAG: <<Sel1:i\d+>> Select [<<P100>>,<<Par>>,<<Cnd1>>]
+  /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Sel1>>,<<M100>>]
+  /// CHECK-DAG: <<Sel2:i\d+>> Select [<<M100>>,<<Sel1>>,<<Cnd2>>]
+  /// CHECK-DAG:               Return [<<Sel2>>]
+  //
+  /// CHECK-START: int TestMinMax.minmax1(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
+  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
+  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
+  /// CHECK-DAG: <<Min:i\d+>>  Min [<<Par>>,<<P100>>]
+  /// CHECK-DAG: <<Max:i\d+>>  Max [<<Min>>,<<M100>>]
+  /// CHECK-DAG:               Return [<<Max>>]
+  //
+  /// CHECK-START: int TestMinMax.minmax1(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:               Select
+  public static int minmax1(int x) {
+    // Simple if-if gives clean select sequence.
+    if (x > 100) {
+      x = 100;
+    }
+    if (x < -100) {
+      x = -100;
+    }
+    return x;
+  }
+
+  /// CHECK-START: int TestMinMax.minmax2(int) instruction_simplifier$after_gvn (before)
+  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
+  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
+  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
+  /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par>>,<<P100>>]
+  /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Par>>,<<M100>>]
+  /// CHECK-DAG: <<Sel1:i\d+>> Select [<<M100>>,<<Par>>,<<Cnd2>>]
+  /// CHECK-DAG: <<Sel2:i\d+>> Select [<<P100>>,<<Sel1>>,<<Cnd1>>]
+  /// CHECK-DAG:               Return [<<Sel2>>]
+  //
+  /// CHECK-START: int TestMinMax.minmax2(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
+  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
+  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
+  /// CHECK-DAG: <<Max:i\d+>>  Max [<<Par>>,<<M100>>]
+  /// CHECK-DAG: <<Min:i\d+>>  Min [<<Max>>,<<P100>>]
+  /// CHECK-DAG:               Return [<<Min>>]
+  //
+  /// CHECK-START: int TestMinMax.minmax2(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:               Select
+  public static int minmax2(int x) {
+    // Simple if-else requires inspecting bounds of resulting selects.
+    if (x > 100) {
+      x = 100;
+    } else if (x < -100) {
+      x = -100;
+    }
+    return x;
+  }
+
+  /// CHECK-START: int TestMinMax.minmax3(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
+  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
+  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
+  /// CHECK-DAG: <<Max:i\d+>>  Max [<<Par>>,<<M100>>]
+  /// CHECK-DAG: <<Min:i\d+>>  Min [<<Max>>,<<P100>>]
+  /// CHECK-DAG:               Return [<<Min>>]
+  //
+  /// CHECK-START: int TestMinMax.minmax3(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:               Select
+  public static int minmax3(int x) {
+    return (x > 100) ? 100 : ((x < -100) ? -100 : x);
+  }
+
+  /// CHECK-START: int TestMinMax.minmax4(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
+  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
+  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
+  /// CHECK-DAG: <<Min:i\d+>>  Min [<<Par>>,<<P100>>]
+  /// CHECK-DAG: <<Max:i\d+>>  Max [<<Min>>,<<M100>>]
+  /// CHECK-DAG:               Return [<<Max>>]
+  //
+  /// CHECK-START: int TestMinMax.minmax4(int) instruction_simplifier$after_gvn (after)
+  /// CHECK-NOT:               Select
+  public static int minmax4(int x) {
+    return (x < -100) ? -100 : ((x > 100) ? 100 : x);
+  }
+
+  /// CHECK-START: int TestMinMax.minmaxCSEScalar(int, int) select_generator (after)
+  /// CHECK-DAG: <<Par1:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Par2:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual    [<<Par1>>,<<Par2>>]
+  /// CHECK-DAG: <<Sel1:i\d+>> Select             [<<Par1>>,<<Par2>>,<<Cnd1>>]
+  /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Par1>>,<<Par2>>]
+  /// CHECK-DAG: <<Sel2:i\d+>> Select             [<<Par1>>,<<Par2>>,<<Cnd2>>]
+  /// CHECK-DAG: <<Add1:i\d+>> Add                [<<Sel1>>,<<Sel2>>]
+  /// CHECK-DAG: <<Add2:i\d+>> Add                [<<Sel1>>,<<Add1>>]
+  /// CHECK-DAG: <<Add3:i\d+>> Add                [<<Sel2>>,<<Add2>>]
+  /// CHECK-DAG: <<Add4:i\d+>> Add                [<<Sel1>>,<<Add3>>]
+  /// CHECK-DAG: <<Add5:i\d+>> Add                [<<Sel2>>,<<Add4>>]
+  /// CHECK-DAG:               Return             [<<Add5>>]
+  //
+  /// CHECK-START: int TestMinMax.minmaxCSEScalar(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par1:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Par2:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Max:i\d+>>  Max    [<<Par1>>,<<Par2>>]
+  /// CHECK-DAG: <<Min:i\d+>>  Min    [<<Par1>>,<<Par2>>]
+  /// CHECK-DAG: <<Add1:i\d+>> Add    [<<Max>>,<<Min>>]
+  /// CHECK-DAG: <<Add2:i\d+>> Add    [<<Max>>,<<Add1>>]
+  /// CHECK-DAG: <<Add3:i\d+>> Add    [<<Min>>,<<Add2>>]
+  /// CHECK-DAG: <<Add4:i\d+>> Add    [<<Max>>,<<Add3>>]
+  /// CHECK-DAG: <<Add5:i\d+>> Add    [<<Min>>,<<Add4>>]
+  /// CHECK-DAG:               Return [<<Add5>>]
+  public static int minmaxCSEScalar(int x, int y) {
+    int t1 = (x > y) ? x : y;
+    int t2 = (x < y) ? x : y;
+    int t3 = (x > y) ? x : y;
+    int t4 = (x < y) ? x : y;
+    int t5 = (x > y) ? x : y;
+    int t6 = (x < y) ? x : y;
+    // Make sure min/max is CSEed.
+    return t1 + t2 + t3 + t4 + t5 + t6;
+  }
+
+  /// CHECK-START: int TestMinMax.minmaxCSEArray(int[], int[]) select_generator (after)
+  /// CHECK-DAG: <<Arr1:i\d+>> ArrayGet
+  /// CHECK-DAG: <<Arr2:i\d+>> ArrayGet
+  /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual    [<<Arr1>>,<<Arr2>>]
+  /// CHECK-DAG: <<Sel1:i\d+>> Select             [<<Arr1>>,<<Arr2>>,<<Cnd1>>]
+  /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Arr1>>,<<Arr2>>]
+  /// CHECK-DAG: <<Sel2:i\d+>> Select             [<<Arr1>>,<<Arr2>>,<<Cnd2>>]
+  /// CHECK-DAG: <<Add1:i\d+>> Add                [<<Sel1>>,<<Sel2>>]
+  /// CHECK-DAG: <<Add2:i\d+>> Add                [<<Sel1>>,<<Add1>>]
+  /// CHECK-DAG: <<Add3:i\d+>> Add                [<<Sel2>>,<<Add2>>]
+  /// CHECK-DAG: <<Add4:i\d+>> Add                [<<Sel1>>,<<Add3>>]
+  /// CHECK-DAG: <<Add5:i\d+>> Add                [<<Sel2>>,<<Add4>>]
+  /// CHECK-DAG:               Return             [<<Add5>>]
+  //
+  /// CHECK-START: int TestMinMax.minmaxCSEArray(int[], int[]) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Arr1:i\d+>> ArrayGet
+  /// CHECK-DAG: <<Arr2:i\d+>> ArrayGet
+  /// CHECK-DAG: <<Max:i\d+>>  Max    [<<Arr1>>,<<Arr2>>]
+  /// CHECK-DAG: <<Min:i\d+>>  Min    [<<Arr1>>,<<Arr2>>]
+  /// CHECK-DAG: <<Add1:i\d+>> Add    [<<Max>>,<<Min>>]
+  /// CHECK-DAG: <<Add2:i\d+>> Add    [<<Max>>,<<Add1>>]
+  /// CHECK-DAG: <<Add3:i\d+>> Add    [<<Min>>,<<Add2>>]
+  /// CHECK-DAG: <<Add4:i\d+>> Add    [<<Max>>,<<Add3>>]
+  /// CHECK-DAG: <<Add5:i\d+>> Add    [<<Min>>,<<Add4>>]
+  /// CHECK-DAG:               Return [<<Add5>>]
+  public static int minmaxCSEArray(int[] x, int[] y) {
+    int t1 = (x[0] > y[0]) ? x[0] : y[0];
+    int t2 = (x[0] < y[0]) ? x[0] : y[0];
+    int t3 = (x[0] > y[0]) ? x[0] : y[0];
+    int t4 = (x[0] < y[0]) ? x[0] : y[0];
+    int t5 = (x[0] > y[0]) ? x[0] : y[0];
+    int t6 = (x[0] < y[0]) ? x[0] : y[0];
+    // Make sure min/max is CSEed.
+    return t1 + t2 + t3 + t4 + t5 + t6;
+  }
+
+  /// CHECK-START: int TestMinMax.minmaxCSEScalarAndCond(int, int) instruction_simplifier$after_gvn (after)
+  /// CHECK-DAG: <<Par1:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Par2:i\d+>> ParameterValue
+  /// CHECK-DAG: <<Max:i\d+>>  Max    [<<Par1>>,<<Par2>>]
+  /// CHECK-DAG: <<Min:i\d+>>  Min    [<<Par1>>,<<Par2>>]
+  /// CHECK-DAG: <<Add:i\d+>>  Add    [<<Max>>,<<Min>>]
+  /// CHECK-DAG:               Return [<<Add>>]
+  /// CHECK-DAG: <<Add1:i\d+>> Add    [<<Max>>,<<Min>>]
+  /// CHECK-DAG: <<Add2:i\d+>> Add    [<<Max>>,<<Add1>>]
+  /// CHECK-DAG: <<Add3:i\d+>> Add    [<<Min>>,<<Add2>>]
+  /// CHECK-DAG:               Return [<<Add3>>]
+  public static int minmaxCSEScalarAndCond(int x, int y) {
+    int t1 = (x > y) ? x : y;
+    int t2 = (x < y) ? x : y;
+    if (x == y)
+      return t1 + t2;
+    int t3 = (x > y) ? x : y;
+    int t4 = (x < y) ? x : y;
+    // Make sure min/max is CSEed.
+    return t1 + t2 + t3 + t4;
+  }
+
+  public static void main() {
+    // Intrinsics.
+    expectEquals(10, minI(10));
+    expectEquals(20, minI(25));
+    expectEquals(-1, minIntConstantZero(-1));
+    expectEquals(0, minIntConstantZero(1));
+    expectEquals(0, minIntConstantOne(0));
+    expectEquals(1, minIntConstantOne(2));
+    expectEquals(-2, minIntConstantMinusOne(-2));
+    expectEquals(-1, minIntConstantMinusOne(0));
+    expectEquals(10L, minL(10L));
+    expectEquals(20L, minL(25L));
+    expectEquals(-1L, minLongConstantZero(-1L));
+    expectEquals(0L, minLongConstantZero(1L));
+    expectEquals(0L, minLongConstantOne(0L));
+    expectEquals(1L, minLongConstantOne(2L));
+    expectEquals(-2L, minLongConstantMinusOne(-2L));
+    expectEquals(-1L, minLongConstantMinusOne(0L));
+    expectEquals(20, maxI(10));
+    expectEquals(25, maxI(25));
+    expectEquals(0, maxIntConstantZero(-1));
+    expectEquals(1, maxIntConstantZero(1));
+    expectEquals(1, maxIntConstantOne(0));
+    expectEquals(2, maxIntConstantOne(2));
+    expectEquals(-1, maxIntConstantMinusOne(-2));
+    expectEquals(0, maxIntConstantMinusOne(0));
+    expectEquals(8193, maxIntLargeConstant(8192));
+    expectEquals(9000, maxIntLargeConstant(9000));
+    expectEquals(20L, maxL(10L));
+    expectEquals(25L, maxL(25L));
+    expectEquals(0L, maxLongConstantZero(-1L));
+    expectEquals(1L, maxLongConstantZero(1L));
+    expectEquals(1L, maxLongConstantOne(0L));
+    expectEquals(2L, maxLongConstantOne(2L));
+    expectEquals(-1L, maxLongConstantMinusOne(-2L));
+    expectEquals(0L, maxLongConstantMinusOne(0L));
+    expectEquals(8193L, maxLongLargeConstant(8192L));
+    expectEquals(9000L, maxLongLargeConstant(9000L));
+    // Types.
+    expectEquals(10, min1(10, 20));
+    expectEquals(10, min2(10, 20));
+    expectEquals(10, min3(10, 20));
+    expectEquals(10, min4(10, 20));
+    expectEquals(10, min5((short) 10, (short) 20));
+    expectEquals(10, min6((byte) 10, (byte) 20));
+    expectEquals(10L, min7(10L, 20L));
+    expectEquals(20, max1(10, 20));
+    expectEquals(20, max2(10, 20));
+    expectEquals(20, max3(10, 20));
+    expectEquals(20, max4(10, 20));
+    expectEquals(20, max5((short) 10, (short) 20));
+    expectEquals(20, max6((byte) 10, (byte) 20));
+    expectEquals(20L, max7(10L, 20L));
+    // Complications.
+    int[] a = { 10 };
+    int[] b = { 20 };
+    expectEquals(10, min0(a, b));
+    expectEquals(20, max0(a, b));
+    expectEquals(-100, minmax1(-200));
+    expectEquals(10, minmax1(10));
+    expectEquals(100, minmax1(200));
+    expectEquals(-100, minmax2(-200));
+    expectEquals(10, minmax2(10));
+    expectEquals(100, minmax2(200));
+    expectEquals(-100, minmax3(-200));
+    expectEquals(10, minmax3(10));
+    expectEquals(100, minmax3(200));
+    expectEquals(-100, minmax4(-200));
+    expectEquals(10, minmax4(10));
+    expectEquals(100, minmax4(200));
+    expectEquals(90, minmaxCSEScalar(10, 20));
+    expectEquals(90, minmaxCSEArray(a, b));
+    expectEquals(20, minmaxCSEScalarAndCond(10, 10));
+    expectEquals(60, minmaxCSEScalarAndCond(10, 20));
+    System.out.println("TestMinMax passed");
+  }
+
+  private static void expectEquals(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  private static void expectEquals(long expected, long result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+}
diff --git a/test/567-checker-builder-intrinsics/src/TestRotate.java b/test/567-checker-builder-intrinsics/src/TestRotate.java
new file mode 100644
index 0000000..0593e60
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/src/TestRotate.java
@@ -0,0 +1,546 @@
+/*
+ * 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.
+ */
+
+public class TestRotate {
+
+  /// CHECK-START: int TestRotate.rotateLeftByte(byte, int) builder (after)
+  /// CHECK:         <<ArgVal:b\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateLeftByte(byte, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateLeftByte(byte value, int distance) {
+    return Integer.rotateLeft(value, distance);
+  }
+
+  /// CHECK-START: int TestRotate.rotateLeftShort(short, int) builder (after)
+  /// CHECK:         <<ArgVal:s\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateLeftShort(short, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateLeftShort(short value, int distance) {
+    return Integer.rotateLeft(value, distance);
+  }
+
+  /// CHECK-START: int TestRotate.rotateLeftChar(char, int) builder (after)
+  /// CHECK:         <<ArgVal:c\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateLeftChar(char, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateLeftChar(char value, int distance) {
+    return Integer.rotateLeft(value, distance);
+  }
+
+  /// CHECK-START: int TestRotate.rotateLeftInt(int, int) builder (after)
+  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateLeftInt(int, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateLeftInt(int value, int distance) {
+    return Integer.rotateLeft(value, distance);
+  }
+
+  /// CHECK-START: long TestRotate.rotateLeftLong(long, int) builder (after)
+  /// CHECK:         <<ArgVal:j\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:j\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: long TestRotate.rotateLeftLong(long, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static long rotateLeftLong(long value, int distance) {
+    return Long.rotateLeft(value, distance);
+  }
+
+  /// CHECK-START: int TestRotate.rotateRightByte(byte, int) builder (after)
+  /// CHECK:         <<ArgVal:b\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateRightByte(byte, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateRightByte(byte value, int distance) {
+    return Integer.rotateRight(value, distance);
+  }
+
+  /// CHECK-START: int TestRotate.rotateRightShort(short, int) builder (after)
+  /// CHECK:         <<ArgVal:s\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateRightShort(short, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateRightShort(short value, int distance) {
+    return Integer.rotateRight(value, distance);
+  }
+
+  /// CHECK-START: int TestRotate.rotateRightChar(char, int) builder (after)
+  /// CHECK:         <<ArgVal:c\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateRightChar(char, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateRightChar(char value, int distance) {
+    return Integer.rotateRight(value, distance);
+  }
+
+  /// CHECK-START: int TestRotate.rotateRightInt(int, int) builder (after)
+  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateRightInt(int, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateRightInt(int value, int distance) {
+    return Integer.rotateRight(value, distance);
+  }
+
+  /// CHECK-START: long TestRotate.rotateRightLong(long, int) builder (after)
+  /// CHECK:         <<ArgVal:j\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:j\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: long TestRotate.rotateRightLong(long, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static long rotateRightLong(long value, int distance) {
+    return Long.rotateRight(value, distance);
+  }
+
+
+  /// CHECK-START: int TestRotate.rotateLeftIntWithByteDistance(int, byte) builder (after)
+  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:b\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateLeftIntWithByteDistance(int, byte) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateLeftIntWithByteDistance(int value, byte distance) {
+    return Integer.rotateLeft(value, distance);
+  }
+
+  /// CHECK-START: int TestRotate.rotateRightIntWithByteDistance(int, byte) builder (after)
+  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:b\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateRightIntWithByteDistance(int, byte) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateRightIntWithByteDistance(int value, byte distance) {
+    return Integer.rotateRight(value, distance);
+  }
+
+  /// CHECK-START: int TestRotate.rotateLeftBoolean(boolean, int) builder (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<Val:i\d+>>     Phi [<<One>>,<<Zero>>]
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<Val>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateLeftBoolean(boolean, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  /// CHECK-START: int TestRotate.rotateLeftBoolean(boolean, int) select_generator (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<SelVal:i\d+>>  Select [<<Zero>>,<<One>>,<<ArgVal>>]
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<SelVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateLeftBoolean(boolean, int) select_generator (after)
+  /// CHECK-NOT:                      Phi
+
+  /// CHECK-START: int TestRotate.rotateLeftBoolean(boolean, int) instruction_simplifier$after_bce (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateLeftBoolean(boolean, int) instruction_simplifier$after_bce (after)
+  /// CHECK-NOT:                      Select
+
+  private static int rotateLeftBoolean(boolean value, int distance) {
+    // Note: D8 would replace the ternary expression `value ? 1 : 0` with `value`
+    // but explicit `if` is preserved.
+    int src;
+    if (value) {
+      src = 1;
+    } else {
+      src = 0;
+    }
+    return Integer.rotateLeft(src, distance);
+  }
+
+  public static void testRotateLeftBoolean() {
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0, rotateLeftBoolean(false, i));
+      expectEqualsInt(1 << j, rotateLeftBoolean(true, i));
+    }
+  }
+
+  public static void testRotateLeftByte() {
+    expectEqualsInt(0x00000001, rotateLeftByte((byte)0x01, 0));
+    expectEqualsInt(0x00000002, rotateLeftByte((byte)0x01, 1));
+    expectEqualsInt(0x80000000, rotateLeftByte((byte)0x01, 31));
+    expectEqualsInt(0x00000001, rotateLeftByte((byte)0x01, 32));  // overshoot
+    expectEqualsInt(0xFFFFFF03, rotateLeftByte((byte)0x81, 1));
+    expectEqualsInt(0xFFFFFE07, rotateLeftByte((byte)0x81, 2));
+    expectEqualsInt(0x00000120, rotateLeftByte((byte)0x12, 4));
+    expectEqualsInt(0xFFFF9AFF, rotateLeftByte((byte)0x9A, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateLeftByte((byte)0x0000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateLeftByte((byte)0xFFFF, i));
+      expectEqualsInt((1 << j), rotateLeftByte((byte)0x0001, i));
+      expectEqualsInt((0x12 << j) | (0x12 >>> -j), rotateLeftByte((byte)0x12, i));
+    }
+  }
+
+  public static void testRotateLeftShort() {
+    expectEqualsInt(0x00000001, rotateLeftShort((short)0x0001, 0));
+    expectEqualsInt(0x00000002, rotateLeftShort((short)0x0001, 1));
+    expectEqualsInt(0x80000000, rotateLeftShort((short)0x0001, 31));
+    expectEqualsInt(0x00000001, rotateLeftShort((short)0x0001, 32));  // overshoot
+    expectEqualsInt(0xFFFF0003, rotateLeftShort((short)0x8001, 1));
+    expectEqualsInt(0xFFFE0007, rotateLeftShort((short)0x8001, 2));
+    expectEqualsInt(0x00012340, rotateLeftShort((short)0x1234, 4));
+    expectEqualsInt(0xFF9ABCFF, rotateLeftShort((short)0x9ABC, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateLeftShort((short)0x0000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateLeftShort((short)0xFFFF, i));
+      expectEqualsInt((1 << j), rotateLeftShort((short)0x0001, i));
+      expectEqualsInt((0x1234 << j) | (0x1234 >>> -j), rotateLeftShort((short)0x1234, i));
+    }
+  }
+
+  public static void testRotateLeftChar() {
+    expectEqualsInt(0x00000001, rotateLeftChar((char)0x0001, 0));
+    expectEqualsInt(0x00000002, rotateLeftChar((char)0x0001, 1));
+    expectEqualsInt(0x80000000, rotateLeftChar((char)0x0001, 31));
+    expectEqualsInt(0x00000001, rotateLeftChar((char)0x0001, 32));  // overshoot
+    expectEqualsInt(0x00010002, rotateLeftChar((char)0x8001, 1));
+    expectEqualsInt(0x00020004, rotateLeftChar((char)0x8001, 2));
+    expectEqualsInt(0x00012340, rotateLeftChar((char)0x1234, 4));
+    expectEqualsInt(0x009ABC00, rotateLeftChar((char)0x9ABC, 8));
+    expectEqualsInt(0x00FF0000, rotateLeftChar((char)0xFF00, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateLeftChar((char)0x0000, i));
+      expectEqualsInt((1 << j), rotateLeftChar((char)0x0001, i));
+      expectEqualsInt((0x1234 << j) | (0x1234 >>> -j), rotateLeftChar((char)0x1234, i));
+    }
+  }
+
+  public static void testRotateLeftInt() {
+    expectEqualsInt(0x00000001, rotateLeftInt(0x00000001, 0));
+    expectEqualsInt(0x00000002, rotateLeftInt(0x00000001, 1));
+    expectEqualsInt(0x80000000, rotateLeftInt(0x00000001, 31));
+    expectEqualsInt(0x00000001, rotateLeftInt(0x00000001, 32));  // overshoot
+    expectEqualsInt(0x00000003, rotateLeftInt(0x80000001, 1));
+    expectEqualsInt(0x00000006, rotateLeftInt(0x80000001, 2));
+    expectEqualsInt(0x23456781, rotateLeftInt(0x12345678, 4));
+    expectEqualsInt(0xBCDEF09A, rotateLeftInt(0x9ABCDEF0, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateLeftInt(0x00000000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateLeftInt(0xFFFFFFFF, i));
+      expectEqualsInt(1 << j, rotateLeftInt(0x00000001, i));
+      expectEqualsInt((0x12345678 << j) | (0x12345678 >>> -j), rotateLeftInt(0x12345678, i));
+    }
+  }
+
+  public static void testRotateLeftLong() {
+    expectEqualsLong(0x0000000000000001L, rotateLeftLong(0x0000000000000001L, 0));
+    expectEqualsLong(0x0000000000000002L, rotateLeftLong(0x0000000000000001L, 1));
+    expectEqualsLong(0x8000000000000000L, rotateLeftLong(0x0000000000000001L, 63));
+    expectEqualsLong(0x0000000000000001L, rotateLeftLong(0x0000000000000001L, 64));  // overshoot
+    expectEqualsLong(0x0000000000000003L, rotateLeftLong(0x8000000000000001L, 1));
+    expectEqualsLong(0x0000000000000006L, rotateLeftLong(0x8000000000000001L, 2));
+    expectEqualsLong(0x23456789ABCDEF01L, rotateLeftLong(0x123456789ABCDEF0L, 4));
+    expectEqualsLong(0x3456789ABCDEF012L, rotateLeftLong(0x123456789ABCDEF0L, 8));
+    for (int i = 0; i < 70; i++) {  // overshoot a bit
+      int j = i & 63;
+      expectEqualsLong(0x0000000000000000L, rotateLeftLong(0x0000000000000000L, i));
+      expectEqualsLong(0xFFFFFFFFFFFFFFFFL, rotateLeftLong(0xFFFFFFFFFFFFFFFFL, i));
+      expectEqualsLong(1L << j, rotateLeftLong(0x0000000000000001, i));
+      expectEqualsLong((0x123456789ABCDEF0L << j) | (0x123456789ABCDEF0L >>> -j),
+                       rotateLeftLong(0x123456789ABCDEF0L, i));
+    }
+  }
+
+  /// CHECK-START: int TestRotate.rotateRightBoolean(boolean, int) builder (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<Val:i\d+>>     Phi [<<One>>,<<Zero>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<Val>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateRightBoolean(boolean, int) builder (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  /// CHECK-START: int TestRotate.rotateRightBoolean(boolean, int) select_generator (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<SelVal:i\d+>>  Select [<<Zero>>,<<One>>,<<ArgVal>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<SelVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateRightBoolean(boolean, int) select_generator (after)
+  /// CHECK-NOT:                     Phi
+
+  /// CHECK-START: int TestRotate.rotateRightBoolean(boolean, int) instruction_simplifier$after_bce (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int TestRotate.rotateRightBoolean(boolean, int) instruction_simplifier$after_bce (after)
+  /// CHECK-NOT:                     Select
+
+  private static int rotateRightBoolean(boolean value, int distance) {
+    // Note: D8 would replace the ternary expression `value ? 1 : 0` with `value`
+    // but explicit `if` is preserved.
+    int src;
+    if (value) {
+      src = 1;
+    } else {
+      src = 0;
+    }
+    return Integer.rotateRight(src, distance);
+  }
+
+  public static void testRotateRightBoolean() {
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = (-i) & 31;
+      expectEqualsInt(0, rotateRightBoolean(false, i));
+      expectEqualsInt(1 << j, rotateRightBoolean(true, i));
+    }
+  }
+
+  public static void testRotateRightByte() {
+    expectEqualsInt(0xFFFFFF80, rotateRightByte((byte)0x80, 0));
+    expectEqualsInt(0x7FFFFFC0, rotateRightByte((byte)0x80, 1));
+    expectEqualsInt(0xFFFFFF01, rotateRightByte((byte)0x80, 31));
+    expectEqualsInt(0xFFFFFF80, rotateRightByte((byte)0x80, 32));  // overshoot
+    expectEqualsInt(0xFFFFFFC0, rotateRightByte((byte)0x81, 1));
+    expectEqualsInt(0x7FFFFFE0, rotateRightByte((byte)0x81, 2));
+    expectEqualsInt(0x20000001, rotateRightByte((byte)0x12, 4));
+    expectEqualsInt(0x9AFFFFFF, rotateRightByte((byte)0x9A, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateRightByte((byte)0x00, i));
+      expectEqualsInt(0xFFFFFFFF, rotateRightByte((byte)0xFF, i));
+      expectEqualsInt(1 << (32 - j), rotateRightByte((byte)0x01, i));
+      expectEqualsInt((0x12 >>> j) | (0x12 << -j), rotateRightByte((byte)0x12, i));
+    }
+  }
+
+  public static void testRotateRightShort() {
+    expectEqualsInt(0xFFFF8000, rotateRightShort((short)0x8000, 0));
+    expectEqualsInt(0x7FFFC000, rotateRightShort((short)0x8000, 1));
+    expectEqualsInt(0xFFFF0001, rotateRightShort((short)0x8000, 31));
+    expectEqualsInt(0xFFFF8000, rotateRightShort((short)0x8000, 32));  // overshoot
+    expectEqualsInt(0xFFFFC000, rotateRightShort((short)0x8001, 1));
+    expectEqualsInt(0x7FFFE000, rotateRightShort((short)0x8001, 2));
+    expectEqualsInt(0x40000123, rotateRightShort((short)0x1234, 4));
+    expectEqualsInt(0xBCFFFF9A, rotateRightShort((short)0x9ABC, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateRightShort((short)0x0000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateRightShort((short)0xFFFF, i));
+      expectEqualsInt(1 << (32 - j), rotateRightShort((short)0x0001, i));
+      expectEqualsInt((0x1234 >>> j) | (0x1234 << -j), rotateRightShort((short)0x1234, i));
+    }
+  }
+
+  public static void testRotateRightChar() {
+    expectEqualsInt(0x00008000, rotateRightChar((char)0x8000, 0));
+    expectEqualsInt(0x00004000, rotateRightChar((char)0x8000, 1));
+    expectEqualsInt(0x00010000, rotateRightChar((char)0x8000, 31));
+    expectEqualsInt(0x00008000, rotateRightChar((char)0x8000, 32));  // overshoot
+    expectEqualsInt(0x80004000, rotateRightChar((char)0x8001, 1));
+    expectEqualsInt(0x40002000, rotateRightChar((char)0x8001, 2));
+    expectEqualsInt(0x40000123, rotateRightChar((char)0x1234, 4));
+    expectEqualsInt(0xBC00009A, rotateRightChar((char)0x9ABC, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateRightChar((char)0x0000, i));
+      expectEqualsInt(1 << (32 - j), rotateRightChar((char)0x0001, i));
+      expectEqualsInt((0x1234 >>> j) | (0x1234 << -j), rotateRightChar((char)0x1234, i));
+    }
+  }
+
+  public static void testRotateRightInt() {
+    expectEqualsInt(0x80000000, rotateRightInt(0x80000000, 0));
+    expectEqualsInt(0x40000000, rotateRightInt(0x80000000, 1));
+    expectEqualsInt(0x00000001, rotateRightInt(0x80000000, 31));
+    expectEqualsInt(0x80000000, rotateRightInt(0x80000000, 32));  // overshoot
+    expectEqualsInt(0xC0000000, rotateRightInt(0x80000001, 1));
+    expectEqualsInt(0x60000000, rotateRightInt(0x80000001, 2));
+    expectEqualsInt(0x81234567, rotateRightInt(0x12345678, 4));
+    expectEqualsInt(0xF09ABCDE, rotateRightInt(0x9ABCDEF0, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateRightInt(0x00000000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateRightInt(0xFFFFFFFF, i));
+      expectEqualsInt(0x80000000 >>> j, rotateRightInt(0x80000000, i));
+      expectEqualsInt((0x12345678 >>> j) | (0x12345678 << -j), rotateRightInt(0x12345678, i));
+    }
+  }
+
+  public static void testRotateRightLong() {
+    expectEqualsLong(0x8000000000000000L, rotateRightLong(0x8000000000000000L, 0));
+    expectEqualsLong(0x4000000000000000L, rotateRightLong(0x8000000000000000L, 1));
+    expectEqualsLong(0x0000000000000001L, rotateRightLong(0x8000000000000000L, 63));
+    expectEqualsLong(0x8000000000000000L, rotateRightLong(0x8000000000000000L, 64));  // overshoot
+    expectEqualsLong(0xC000000000000000L, rotateRightLong(0x8000000000000001L, 1));
+    expectEqualsLong(0x6000000000000000L, rotateRightLong(0x8000000000000001L, 2));
+    expectEqualsLong(0x0123456789ABCDEFL, rotateRightLong(0x123456789ABCDEF0L, 4));
+    expectEqualsLong(0xF0123456789ABCDEL, rotateRightLong(0x123456789ABCDEF0L, 8));
+    for (int i = 0; i < 70; i++) {  // overshoot a bit
+      int j = i & 63;
+      expectEqualsLong(0x0000000000000000L, rotateRightLong(0x0000000000000000L, i));
+      expectEqualsLong(0xFFFFFFFFFFFFFFFFL, rotateRightLong(0xFFFFFFFFFFFFFFFFL, i));
+      expectEqualsLong(0x8000000000000000L >>> j, rotateRightLong(0x8000000000000000L, i));
+      expectEqualsLong((0x123456789ABCDEF0L >>> j) | (0x123456789ABCDEF0L << -j),
+                       rotateRightLong(0x123456789ABCDEF0L, i));
+    }
+  }
+
+
+  public static void testRotateLeftIntWithByteDistance() {
+    expectEqualsInt(0x00000001, rotateLeftIntWithByteDistance(0x00000001, (byte)0));
+    expectEqualsInt(0x00000002, rotateLeftIntWithByteDistance(0x00000001, (byte)1));
+    expectEqualsInt(0x80000000, rotateLeftIntWithByteDistance(0x00000001, (byte)31));
+    expectEqualsInt(0x00000001, rotateLeftIntWithByteDistance(0x00000001, (byte)32));  // overshoot
+    expectEqualsInt(0x00000003, rotateLeftIntWithByteDistance(0x80000001, (byte)1));
+    expectEqualsInt(0x00000006, rotateLeftIntWithByteDistance(0x80000001, (byte)2));
+    expectEqualsInt(0x23456781, rotateLeftIntWithByteDistance(0x12345678, (byte)4));
+    expectEqualsInt(0xBCDEF09A, rotateLeftIntWithByteDistance(0x9ABCDEF0, (byte)8));
+    for (byte i = 0; i < 40; i++) {  // overshoot a bit
+      byte j = (byte)(i & 31);
+      expectEqualsInt(0x00000000, rotateLeftIntWithByteDistance(0x00000000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateLeftIntWithByteDistance(0xFFFFFFFF, i));
+      expectEqualsInt(1 << j, rotateLeftIntWithByteDistance(0x00000001, i));
+      expectEqualsInt((0x12345678 << j) | (0x12345678 >>> -j),
+                      rotateLeftIntWithByteDistance(0x12345678, i));
+    }
+  }
+
+  public static void testRotateRightIntWithByteDistance() {
+    expectEqualsInt(0x80000000, rotateRightIntWithByteDistance(0x80000000, (byte)0));
+    expectEqualsInt(0x40000000, rotateRightIntWithByteDistance(0x80000000, (byte)1));
+    expectEqualsInt(0x00000001, rotateRightIntWithByteDistance(0x80000000, (byte)31));
+    expectEqualsInt(0x80000000, rotateRightIntWithByteDistance(0x80000000, (byte)32));  // overshoot
+    expectEqualsInt(0xC0000000, rotateRightIntWithByteDistance(0x80000001, (byte)1));
+    expectEqualsInt(0x60000000, rotateRightIntWithByteDistance(0x80000001, (byte)2));
+    expectEqualsInt(0x81234567, rotateRightIntWithByteDistance(0x12345678, (byte)4));
+    expectEqualsInt(0xF09ABCDE, rotateRightIntWithByteDistance(0x9ABCDEF0, (byte)8));
+    for (byte i = 0; i < 40; i++) {  // overshoot a bit
+      byte j = (byte)(i & 31);
+      expectEqualsInt(0x00000000, rotateRightIntWithByteDistance(0x00000000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateRightIntWithByteDistance(0xFFFFFFFF, i));
+      expectEqualsInt(0x80000000 >>> j, rotateRightIntWithByteDistance(0x80000000, i));
+      expectEqualsInt((0x12345678 >>> j) | (0x12345678 << -j),
+                      rotateRightIntWithByteDistance(0x12345678, i));
+    }
+  }
+
+
+  public static void main() {
+    testRotateLeftBoolean();
+    testRotateLeftByte();
+    testRotateLeftShort();
+    testRotateLeftChar();
+    testRotateLeftInt();
+    testRotateLeftLong();
+
+    testRotateRightBoolean();
+    testRotateRightByte();
+    testRotateRightShort();
+    testRotateRightChar();
+    testRotateRightInt();
+    testRotateRightLong();
+
+    // Also exercise distance values with types other than int.
+    testRotateLeftIntWithByteDistance();
+    testRotateRightIntWithByteDistance();
+
+    System.out.println("TestRotate passed");
+  }
+
+
+  private static void expectEqualsInt(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  private static void expectEqualsLong(long expected, long result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+}
diff --git a/test/567-checker-builder-intrinsics/src/TestSignum.java b/test/567-checker-builder-intrinsics/src/TestSignum.java
new file mode 100644
index 0000000..0a68ac2
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/src/TestSignum.java
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+
+public class TestSignum {
+
+  /// CHECK-START: int TestSignum.signByte(byte) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestSignum.signByte(byte) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  private static int signByte(byte x) {
+    return Integer.signum(x);
+  }
+
+  /// CHECK-START: int TestSignum.signShort(short) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestSignum.signShort(short) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  private static int signShort(short x) {
+    return Integer.signum(x);
+  }
+
+  /// CHECK-START: int TestSignum.signChar(char) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestSignum.signChar(char) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  private static int signChar(char x) {
+    return Integer.signum(x);
+  }
+
+  /// CHECK-START: int TestSignum.signInt(int) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestSignum.signInt(int) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  private static int signInt(int x) {
+    return Integer.signum(x);
+  }
+
+  /// CHECK-START: int TestSignum.signLong(long) builder (after)
+  /// CHECK-DAG:     <<Result:i\d+>> Compare
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestSignum.signLong(long) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  private static int signLong(long x) {
+    return Long.signum(x);
+  }
+
+  /// CHECK-START: int TestSignum.signBoolean(boolean) builder (after)
+  /// CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>    IntConstant 1
+  /// CHECK-DAG:     <<Phi:i\d+>>    Phi [<<One>>,<<Zero>>]
+  /// CHECK-DAG:     <<Result:i\d+>> Compare [<<Phi>>,<<Zero>>]
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestSignum.signBoolean(boolean) builder (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
+
+  /// CHECK-START: int TestSignum.signBoolean(boolean) select_generator (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>    ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>    IntConstant 1
+  /// CHECK-DAG:     <<Sel:i\d+>>    Select [<<Zero>>,<<One>>,<<Arg>>]
+  /// CHECK-DAG:     <<Result:i\d+>> Compare [<<Sel>>,<<Zero>>]
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestSignum.signBoolean(boolean) select_generator (after)
+  /// CHECK-NOT:                     Phi
+
+  /// CHECK-START: int TestSignum.signBoolean(boolean) instruction_simplifier$after_bce (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>    ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Result:i\d+>> Compare [<<Arg>>,<<Zero>>]
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int TestSignum.signBoolean(boolean) instruction_simplifier$after_bce (after)
+  /// CHECK-NOT:                     Select
+
+  private static int signBoolean(boolean x) {
+    // Note: D8 would replace the ternary expression `x ? 1 : 0` with `x`
+    // but explicit `if` is preserved.
+    int src_x;
+    if (x) {
+      src_x = 1;
+    } else {
+      src_x = 0;
+    }
+    return Integer.signum(src_x);
+  }
+
+  public static void testSignBoolean() {
+    expectEquals(0, signBoolean(false));
+    expectEquals(1, signBoolean(true));
+  }
+
+  public static void testSignByte() {
+    expectEquals(-1, signByte((byte)Byte.MIN_VALUE));
+    expectEquals(-1, signByte((byte)-64));
+    expectEquals(-1, signByte((byte)-1));
+    expectEquals(0, signByte((byte)0));
+    expectEquals(1, signByte((byte)1));
+    expectEquals(1, signByte((byte)64));
+    expectEquals(1, signByte((byte)Byte.MAX_VALUE));
+  }
+
+  public static void testSignShort() {
+    expectEquals(-1, signShort((short)Short.MIN_VALUE));
+    expectEquals(-1, signShort((short)-12345));
+    expectEquals(-1, signShort((short)-1));
+    expectEquals(0, signShort((short)0));
+    expectEquals(1, signShort((short)1));
+    expectEquals(1, signShort((short)12345));
+    expectEquals(1, signShort((short)Short.MAX_VALUE));
+  }
+
+  public static void testSignChar() {
+    expectEquals(0, signChar((char)0));
+    expectEquals(1, signChar((char)1));
+    expectEquals(1, signChar((char)12345));
+    expectEquals(1, signChar((char)Character.MAX_VALUE));
+  }
+
+  public static void testSignInt() {
+    expectEquals(-1, signInt(Integer.MIN_VALUE));
+    expectEquals(-1, signInt(-12345));
+    expectEquals(-1, signInt(-1));
+    expectEquals(0, signInt(0));
+    expectEquals(1, signInt(1));
+    expectEquals(1, signInt(12345));
+    expectEquals(1, signInt(Integer.MAX_VALUE));
+
+    for (int i = -11; i <= 11; i++) {
+      int expected = 0;
+      if (i < 0) expected = -1;
+      else if (i > 0) expected = 1;
+      expectEquals(expected, signInt(i));
+    }
+  }
+
+  public static void testSignLong() {
+    expectEquals(-1, signLong(Long.MIN_VALUE));
+    expectEquals(-1, signLong(-12345L));
+    expectEquals(-1, signLong(-1L));
+    expectEquals(0, signLong(0L));
+    expectEquals(1, signLong(1L));
+    expectEquals(1, signLong(12345L));
+    expectEquals(1, signLong(Long.MAX_VALUE));
+
+    expectEquals(-1, signLong(0x800000007FFFFFFFL));
+    expectEquals(-1, signLong(0x80000000FFFFFFFFL));
+    expectEquals(1, signLong(0x000000007FFFFFFFL));
+    expectEquals(1, signLong(0x00000000FFFFFFFFL));
+    expectEquals(1, signLong(0x7FFFFFFF7FFFFFFFL));
+    expectEquals(1, signLong(0x7FFFFFFFFFFFFFFFL));
+
+    for (long i = -11L; i <= 11L; i++) {
+      int expected = 0;
+      if (i < 0) expected = -1;
+      else if (i > 0) expected = 1;
+      expectEquals(expected, signLong(i));
+    }
+
+    for (long i = Long.MIN_VALUE; i <= Long.MIN_VALUE + 11L; i++) {
+      expectEquals(-1, signLong(i));
+    }
+
+    for (long i = Long.MAX_VALUE; i >= Long.MAX_VALUE - 11L; i--) {
+      expectEquals(1, signLong(i));
+    }
+  }
+
+
+  public static void main() {
+    testSignBoolean();
+    testSignByte();
+    testSignShort();
+    testSignChar();
+    testSignInt();
+    testSignLong();
+
+    System.out.println("TestSignum passed");
+  }
+
+  private static void expectEquals(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+}
diff --git a/test/567-checker-builder-intrinsics/src/TestVarHandles.java b/test/567-checker-builder-intrinsics/src/TestVarHandles.java
new file mode 100644
index 0000000..2a82c06
--- /dev/null
+++ b/test/567-checker-builder-intrinsics/src/TestVarHandles.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+import java.lang.invoke.VarHandle;
+
+/**
+ * Checker test on the 1.8 unsafe operations. Note, this is by no means an
+ * exhaustive unit test for these CAS (compare-and-swap) and fence operations.
+ * Instead, this test ensures the methods are recognized as intrinsic and behave
+ * as expected.
+ */
+public class TestVarHandles {
+
+  //
+  // Fences (native).
+  //
+
+  /// CHECK-START: void TestVarHandles.fullFence() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect
+  //
+  /// CHECK-START: void TestVarHandles.fullFence() builder (after)
+  /// CHECK-DAG: MemoryBarrier kind:AnyAny
+  private static void fullFence() {
+      VarHandle.fullFence();
+  }
+
+  /// CHECK-START: void TestVarHandles.acquireFence() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect
+  //
+  /// CHECK-START: void TestVarHandles.acquireFence() builder (after)
+  /// CHECK-DAG: MemoryBarrier kind:LoadAny
+  private static void acquireFence() {
+      VarHandle.acquireFence();
+  }
+
+  /// CHECK-START: void TestVarHandles.releaseFence() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect
+  //
+  /// CHECK-START: void TestVarHandles.releaseFence() builder (after)
+  /// CHECK-DAG: MemoryBarrier kind:AnyStore
+  private static void releaseFence() {
+      VarHandle.releaseFence();
+  }
+
+  /// CHECK-START: void TestVarHandles.loadLoadFence() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect
+  //
+  /// CHECK-START: void TestVarHandles.loadLoadFence() builder (after)
+  /// CHECK-DAG: MemoryBarrier kind:LoadAny
+  private static void loadLoadFence() {
+      VarHandle.loadLoadFence();
+  }
+
+  /// CHECK-START: void TestVarHandles.storeStoreFence() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect
+  //
+  /// CHECK-START: void TestVarHandles.storeStoreFence() builder (after)
+  /// CHECK-DAG: MemoryBarrier kind:StoreStore
+  private static void storeStoreFence() {
+      VarHandle.storeStoreFence();
+  }
+
+  //
+  // Driver.
+  //
+
+  public static void main() {
+    acquireFence();
+    releaseFence();
+    loadLoadFence();
+    storeStoreFence();
+    fullFence();
+    System.out.println("TestVarHandles passed");
+  }
+}
diff --git a/test/567-checker-compare/expected.txt b/test/567-checker-compare/expected.txt
deleted file mode 100644
index b0aad4d..0000000
--- a/test/567-checker-compare/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-passed
diff --git a/test/567-checker-compare/info.txt b/test/567-checker-compare/info.txt
deleted file mode 100644
index 5bac7b1..0000000
--- a/test/567-checker-compare/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Unit test for 32-bit and 64-bit compare operations.
diff --git a/test/567-checker-compare/smali/Smali.smali b/test/567-checker-compare/smali/Smali.smali
deleted file mode 100644
index fb6d241..0000000
--- a/test/567-checker-compare/smali/Smali.smali
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-.class public LSmali;
-.super Ljava/lang/Object;
-
-##  CHECK-START: int Smali.compareBooleans(boolean, boolean) builder (after)
-##  CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
-##  CHECK-DAG:     <<One:i\d+>>    IntConstant 1
-##  CHECK-DAG:     <<PhiX:i\d+>>   Phi [<<One>>,<<Zero>>]
-##  CHECK-DAG:     <<PhiY:i\d+>>   Phi [<<One>>,<<Zero>>]
-##  CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect [<<PhiX>>,<<PhiY>>{{(,[ij]\d+)?}}] intrinsic:IntegerCompare
-##  CHECK-DAG:                     Return [<<Result>>]
-
-##  CHECK-START: int Smali.compareBooleans(boolean, boolean) instruction_simplifier (after)
-##  CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
-##  CHECK-DAG:     <<One:i\d+>>    IntConstant 1
-##  CHECK-DAG:     <<PhiX:i\d+>>   Phi [<<One>>,<<Zero>>]
-##  CHECK-DAG:     <<PhiY:i\d+>>   Phi [<<One>>,<<Zero>>]
-##  CHECK-DAG:     <<Result:i\d+>> Compare [<<PhiX>>,<<PhiY>>]
-##  CHECK-DAG:                     Return [<<Result>>]
-
-##  CHECK-START: int Smali.compareBooleans(boolean, boolean) instruction_simplifier (after)
-##  CHECK-NOT:                     InvokeStaticOrDirect
-
-##  CHECK-START: int Smali.compareBooleans(boolean, boolean) select_generator (after)
-##  CHECK:         <<ArgX:z\d+>>   ParameterValue
-##  CHECK:         <<ArgY:z\d+>>   ParameterValue
-##  CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
-##  CHECK-DAG:     <<One:i\d+>>    IntConstant 1
-##  CHECK-DAG:     <<SelX:i\d+>>   Select [<<Zero>>,<<One>>,<<ArgX>>]
-##  CHECK-DAG:     <<SelY:i\d+>>   Select [<<Zero>>,<<One>>,<<ArgY>>]
-##  CHECK-DAG:     <<Result:i\d+>> Compare [<<SelX>>,<<SelY>>]
-##  CHECK-DAG:                     Return [<<Result>>]
-
-##  CHECK-START: int Smali.compareBooleans(boolean, boolean) select_generator (after)
-##  CHECK-NOT:                     Phi
-
-##  CHECK-START: int Smali.compareBooleans(boolean, boolean) instruction_simplifier$after_bce (after)
-##  CHECK:         <<ArgX:z\d+>>   ParameterValue
-##  CHECK:         <<ArgY:z\d+>>   ParameterValue
-##  CHECK-DAG:     <<Result:i\d+>> Compare [<<ArgX>>,<<ArgY>>]
-##  CHECK-DAG:                     Return [<<Result>>]
-
-##  CHECK-START: int Smali.compareBooleans(boolean, boolean) instruction_simplifier$after_bce (after)
-##  CHECK-NOT:                     Select
-
-#   Note: This test has been written in smali (in addition to the source version) because Dexers
-#         such as D8 can perform the same type of intrinsic replacements.
-.method public static compareBooleans(ZZ)I
-    # return Integer.compare((x ? 1 : 0), (y ? 1 : 0));
-    .registers 5
-    const/4 v0, 0x1
-
-    const/4 v1, 0x0
-
-    if-eqz p0, :cond_c
-
-    move v2, v0
-
-    :goto_5
-    if-eqz p1, :cond_e
-
-    :goto_7
-    invoke-static {v2, v0}, Ljava/lang/Integer;->compare(II)I
-
-    move-result v0
-
-    return v0
-
-    :cond_c
-    move v2, v1
-
-    goto :goto_5
-
-    :cond_e
-    move v0, v1
-
-    goto :goto_7
-.end method
diff --git a/test/567-checker-compare/src/Main.java b/test/567-checker-compare/src/Main.java
deleted file mode 100644
index 25d88aa..0000000
--- a/test/567-checker-compare/src/Main.java
+++ /dev/null
@@ -1,929 +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.
- */
-
-import java.lang.reflect.Method;
-
-public class Main {
-
-  /// CHECK-START: void Main.$opt$noinline$testReplaceInputWithItself(int) builder (after)
-  /// CHECK-DAG:     <<ArgX:i\d+>>   ParameterValue
-  /// CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
-  /// CHECK-DAG:     <<Cmp:i\d+>>    InvokeStaticOrDirect [<<ArgX>>,<<Zero>>{{(,[ij]\d+)?}}] intrinsic:IntegerCompare
-  /// CHECK-DAG:                     GreaterThanOrEqual [<<Cmp>>,<<Zero>>]
-
-  /// CHECK-START: void Main.$opt$noinline$testReplaceInputWithItself(int) instruction_simplifier (after)
-  /// CHECK-DAG:     <<ArgX:i\d+>>   ParameterValue
-  /// CHECK-DAG:     <<Zero:i\d+>>   IntConstant 0
-  /// CHECK-DAG:                     GreaterThanOrEqual [<<ArgX>>,<<Zero>>]
-
-  public static void $opt$noinline$testReplaceInputWithItself(int x) {
-    // The instruction simplifier first replaces Integer.compare(x, 0) with Compare HIR
-    // and then merges the Compare into the GreaterThanOrEqual. This is a regression
-    // test that to check that it is allowed to replace the second input of the
-    // GreaterThanOrEqual, i.e. <<Zero>>, with the very same instruction.
-    if (Integer.compare(x, 0) < 0) {
-      System.out.println("OOOPS");
-    }
-  }
-
-  /// CHECK-START: int Main.compareBooleans(boolean, boolean) select_generator (after)
-  /// CHECK-NOT:                     Phi
-
-  /// CHECK-START: int Main.compareBooleans(boolean, boolean) instruction_simplifier$after_bce (after)
-  /// CHECK:         <<ArgX:z\d+>>   ParameterValue
-  /// CHECK:         <<ArgY:z\d+>>   ParameterValue
-  /// CHECK-DAG:     <<Result:i\d+>> Compare [<<ArgX>>,<<ArgY>>]
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareBooleans(boolean, boolean) instruction_simplifier$after_bce (after)
-  /// CHECK-NOT:                     Select
-
-  private static int compareBooleans(boolean x, boolean y) {
-    return Integer.compare((x ? 1 : 0), (y ? 1 : 0));
-  }
-
-  private static int compareBooleansSmali(boolean x, boolean y) throws Exception {
-    Class<?> c = Class.forName("Smali");
-    Method m = c.getMethod("compareBooleans", boolean.class, boolean.class);
-    return (Integer) m.invoke(null, x, y);
-  }
-
-  /// CHECK-START: int Main.compareBytes(byte, byte) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareBytes(byte, byte) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareBytes(byte, byte) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  private static int compareBytes(byte x, byte y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareShorts(short, short) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareShorts(short, short) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareShorts(short, short) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  private static int compareShorts(short x, short y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareChars(char, char) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareChars(char, char) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareChars(char, char) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  private static int compareChars(char x, char y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareInts(int, int) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareInts(int, int) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareInts(int, int) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  private static int compareInts(int x, int y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareLongs(long, long) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareLongs(long, long) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareLongs(long, long) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  private static int compareLongs(long x, long y) {
-    return Long.compare(x, y);
-  }
-
-
-  /// CHECK-START: int Main.compareByteShort(byte, short) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareByteShort(byte, short) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareByteShort(byte, short) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareByteShort(byte x, short y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareByteChar(byte, char) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareByteChar(byte, char) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareByteChar(byte, char) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareByteChar(byte x, char y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareByteInt(byte, int) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareByteInt(byte, int) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareByteInt(byte, int) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareByteInt(byte x, int y) {
-    return Integer.compare(x, y);
-  }
-
-
-  /// CHECK-START: int Main.compareShortByte(short, byte) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareShortByte(short, byte) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareShortByte(short, byte) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareShortByte(short x, byte y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareShortChar(short, char) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareShortChar(short, char) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareShortChar(short, char) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareShortChar(short x, char y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareShortInt(short, int) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareShortInt(short, int) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareShortInt(short, int) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareShortInt(short x, int y) {
-    return Integer.compare(x, y);
-  }
-
-
-  /// CHECK-START: int Main.compareCharByte(char, byte) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareCharByte(char, byte) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareCharByte(char, byte) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareCharByte(char x, byte y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareCharShort(char, short) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareCharShort(char, short) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareCharShort(char, short) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareCharShort(char x, short y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareCharInt(char, int) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareCharInt(char, int) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareCharInt(char, int) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareCharInt(char x, int y) {
-    return Integer.compare(x, y);
-  }
-
-
-  /// CHECK-START: int Main.compareIntByte(int, byte) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareIntByte(int, byte) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareIntByte(int, byte) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareIntByte(int x, byte y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareIntShort(int, short) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareIntShort(int, short) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareIntShort(int, short) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareIntShort(int x, short y) {
-    return Integer.compare(x, y);
-  }
-
-  /// CHECK-START: int Main.compareIntChar(int, char) builder (after)
-  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareIntChar(int, char) instruction_simplifier (after)
-  /// CHECK-DAG:     <<Result:i\d+>> Compare
-  /// CHECK-DAG:                     Return [<<Result>>]
-
-  /// CHECK-START: int Main.compareIntChar(int, char) instruction_simplifier (after)
-  /// CHECK-NOT:                     InvokeStaticOrDirect
-
-  public static int compareIntChar(int x, char y) {
-    return Integer.compare(x, y);
-  }
-
-
-  public static void testCompareBooleans() throws Exception {
-    expectEquals(-1, compareBooleans(false, true));
-    expectEquals(-1, compareBooleansSmali(false, true));
-
-    expectEquals(0, compareBooleans(false, false));
-    expectEquals(0, compareBooleans(true, true));
-    expectEquals(0, compareBooleansSmali(false, false));
-    expectEquals(0, compareBooleansSmali(true, true));
-
-    expectEquals(1, compareBooleans(true, false));
-    expectEquals(1, compareBooleansSmali(true, false));
-  }
-
-  public static void testCompareBytes() {
-    expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)(Byte.MIN_VALUE + 1)));
-    expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)-1));
-    expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)0));
-    expectEquals(-1, compareBytes(Byte.MIN_VALUE, (byte)1));
-    expectEquals(-1, compareBytes(Byte.MIN_VALUE, Byte.MAX_VALUE));
-    expectEquals(-1, compareBytes((byte)-1, (byte)0));
-    expectEquals(-1, compareBytes((byte)-1, (byte)1));
-    expectEquals(-1, compareBytes((byte)0, (byte)1));
-
-    expectEquals(0, compareBytes(Byte.MIN_VALUE, Byte.MIN_VALUE));
-    expectEquals(0, compareBytes((byte)-1, (byte)-1));
-    expectEquals(0, compareBytes((byte)0, (byte)0));
-    expectEquals(0, compareBytes((byte)1, (byte)1));
-    expectEquals(0, compareBytes(Byte.MAX_VALUE, Byte.MAX_VALUE));
-
-    expectEquals(1, compareBytes((byte)0, (byte)-1));
-    expectEquals(1, compareBytes((byte)1, (byte)-1));
-    expectEquals(1, compareBytes((byte)1, (byte)0));
-    expectEquals(1, compareBytes(Byte.MAX_VALUE, Byte.MIN_VALUE));
-    expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)-1));
-    expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)0));
-    expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)1));
-    expectEquals(1, compareBytes(Byte.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
-
-    for (byte i = -11; i <= 11; i++) {
-      for (byte j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareBytes(i, j));
-      }
-    }
-  }
-
-  public static void testCompareShorts() {
-    expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)(Short.MIN_VALUE + 1)));
-    expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)-1));
-    expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)0));
-    expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)1));
-    expectEquals(-1, compareShorts(Short.MIN_VALUE, (short)Short.MAX_VALUE));
-    expectEquals(-1, compareShorts((short)-1, (short)0));
-    expectEquals(-1, compareShorts((short)-1, (short)1));
-    expectEquals(-1, compareShorts((short)0, (short)1));
-
-    expectEquals(0, compareShorts(Short.MIN_VALUE, Short.MIN_VALUE));
-    expectEquals(0, compareShorts((short)-1, (short)-1));
-    expectEquals(0, compareShorts((short)0, (short)0));
-    expectEquals(0, compareShorts((short)1, (short)1));
-    expectEquals(0, compareShorts(Short.MAX_VALUE, Short.MAX_VALUE));
-
-    expectEquals(1, compareShorts((short)0, (short)-1));
-    expectEquals(1, compareShorts((short)1, (short)-1));
-    expectEquals(1, compareShorts((short)1, (short)0));
-    expectEquals(1, compareShorts(Short.MAX_VALUE, Short.MIN_VALUE));
-    expectEquals(1, compareShorts(Short.MAX_VALUE, (short)-1));
-    expectEquals(1, compareShorts(Short.MAX_VALUE, (short)0));
-    expectEquals(1, compareShorts(Short.MAX_VALUE, (short)1));
-    expectEquals(1, compareShorts(Short.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
-
-    for (short i = -11; i <= 11; i++) {
-      for (short j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareShorts(i, j));
-      }
-    }
-  }
-
-  public static void testCompareChars() {
-    expectEquals(-1, compareChars((char)0, Character.MAX_VALUE));
-    expectEquals(-1, compareChars((char)0, (char)1));
-
-    expectEquals(0, compareChars((char)0, (char)0));
-    expectEquals(0, compareChars((char)1, (char)1));
-    expectEquals(0, compareChars(Character.MAX_VALUE, Character.MAX_VALUE));
-
-    expectEquals(1, compareChars((char)1, (char)0));
-    expectEquals(1, compareChars(Character.MAX_VALUE, (char)0));
-    expectEquals(1, compareChars(Character.MAX_VALUE, (char)1));
-    expectEquals(1, compareChars(Character.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
-
-    for (char i = 0; i <= 11; i++) {
-      for (char j = 0; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareChars(i, j));
-      }
-    }
-  }
-
-  public static void testCompareInts() {
-    expectEquals(-1, compareInts(Integer.MIN_VALUE, Integer.MIN_VALUE + 1));
-    expectEquals(-1, compareInts(Integer.MIN_VALUE, -1));
-    expectEquals(-1, compareInts(Integer.MIN_VALUE, 0));
-    expectEquals(-1, compareInts(Integer.MIN_VALUE, 1));
-    expectEquals(-1, compareInts(Integer.MIN_VALUE, Integer.MAX_VALUE));
-    expectEquals(-1, compareInts(-1, 0));
-    expectEquals(-1, compareInts(-1, 1));
-    expectEquals(-1, compareInts(0, 1));
-
-    expectEquals(0, compareInts(Integer.MIN_VALUE, Integer.MIN_VALUE));
-    expectEquals(0, compareInts(-1, -1));
-    expectEquals(0, compareInts(0, 0));
-    expectEquals(0, compareInts(1, 1));
-    expectEquals(0, compareInts(Integer.MAX_VALUE, Integer.MAX_VALUE));
-
-    expectEquals(1, compareInts(0, -1));
-    expectEquals(1, compareInts(1, -1));
-    expectEquals(1, compareInts(1, 0));
-    expectEquals(1, compareInts(Integer.MAX_VALUE, Integer.MIN_VALUE));
-    expectEquals(1, compareInts(Integer.MAX_VALUE, -1));
-    expectEquals(1, compareInts(Integer.MAX_VALUE, 0));
-    expectEquals(1, compareInts(Integer.MAX_VALUE, 1));
-    expectEquals(1, compareInts(Integer.MAX_VALUE, Integer.MAX_VALUE - 1));
-
-    for (int i = -11; i <= 11; i++) {
-      for (int j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareInts(i, j));
-      }
-    }
-  }
-
-  public static void testCompareLongs() {
-    expectEquals(-1, compareLongs(Long.MIN_VALUE, Long.MIN_VALUE + 1L));
-    expectEquals(-1, compareLongs(Long.MIN_VALUE, -1L));
-    expectEquals(-1, compareLongs(Long.MIN_VALUE, 0L));
-    expectEquals(-1, compareLongs(Long.MIN_VALUE, 1L));
-    expectEquals(-1, compareLongs(Long.MIN_VALUE, Long.MAX_VALUE));
-    expectEquals(-1, compareLongs(-1L, 0L));
-    expectEquals(-1, compareLongs(-1L, 1L));
-    expectEquals(-1, compareLongs(0L, 1L));
-
-    expectEquals(0, compareLongs(Long.MIN_VALUE, Long.MIN_VALUE));
-    expectEquals(0, compareLongs(-1L, -1L));
-    expectEquals(0, compareLongs(0L, 0L));
-    expectEquals(0, compareLongs(1L, 1L));
-    expectEquals(0, compareLongs(Long.MAX_VALUE, Long.MAX_VALUE));
-
-    expectEquals(1, compareLongs(0L, -1L));
-    expectEquals(1, compareLongs(1L, -1L));
-    expectEquals(1, compareLongs(1L, 0L));
-    expectEquals(1, compareLongs(Long.MAX_VALUE, Long.MIN_VALUE));
-    expectEquals(1, compareLongs(Long.MAX_VALUE, -1L));
-    expectEquals(1, compareLongs(Long.MAX_VALUE, 0L));
-    expectEquals(1, compareLongs(Long.MAX_VALUE, 1L));
-    expectEquals(1, compareLongs(Long.MAX_VALUE, Long.MAX_VALUE - 1L));
-
-    expectEquals(-1, compareLongs(0x111111117FFFFFFFL, 0x11111111FFFFFFFFL));
-    expectEquals(0, compareLongs(0x111111117FFFFFFFL, 0x111111117FFFFFFFL));
-    expectEquals(1, compareLongs(0x11111111FFFFFFFFL, 0x111111117FFFFFFFL));
-
-    for (long i = -11L; i <= 11L; i++) {
-      for (long j = -11L; j <= 11L; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareLongs(i, j));
-      }
-    }
-
-    for (long i = Long.MIN_VALUE; i <= Long.MIN_VALUE + 11L; i++) {
-      expectEquals(-1, compareLongs(i, 0));
-    }
-
-    for (long i = Long.MAX_VALUE; i >= Long.MAX_VALUE - 11L; i--) {
-      expectEquals(1, compareLongs(i, 0));
-    }
-  }
-
-
-  public static void testCompareByteShort() {
-    expectEquals(-1, compareByteShort(Byte.MIN_VALUE, (short)-1));
-    expectEquals(-1, compareByteShort(Byte.MIN_VALUE, (short)0));
-    expectEquals(-1, compareByteShort(Byte.MIN_VALUE, (short)1));
-    expectEquals(-1, compareByteShort(Byte.MIN_VALUE, Short.MAX_VALUE));
-    expectEquals(-1, compareByteShort((byte)-1, (short)0));
-    expectEquals(-1, compareByteShort((byte)-1, (short)1));
-    expectEquals(-1, compareByteShort((byte)0, (short)1));
-    expectEquals(-1, compareByteShort(Byte.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
-    expectEquals(-1, compareByteShort(Byte.MAX_VALUE, Short.MAX_VALUE));
-
-    expectEquals(0, compareByteShort((byte)-1, (short)-1));
-    expectEquals(0, compareByteShort((byte)0, (short)0));
-    expectEquals(0, compareByteShort((byte)1, (short)1));
-
-    expectEquals(1, compareByteShort(Byte.MIN_VALUE, Short.MIN_VALUE));
-    expectEquals(1, compareByteShort(Byte.MIN_VALUE, (short)(Short.MIN_VALUE + 1)));
-    expectEquals(1, compareByteShort((byte)0, (short)-1));
-    expectEquals(1, compareByteShort((byte)1, (short)-1));
-    expectEquals(1, compareByteShort((byte)1, (short)0));
-    expectEquals(1, compareByteShort(Byte.MAX_VALUE, Short.MIN_VALUE));
-    expectEquals(1, compareByteShort(Byte.MAX_VALUE, (short)-1));
-    expectEquals(1, compareByteShort(Byte.MAX_VALUE, (short)0));
-    expectEquals(1, compareByteShort(Byte.MAX_VALUE, (short)1));
-
-    for (byte i = -11; i <= 11; i++) {
-      for (short j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareByteShort(i, j));
-      }
-    }
-  }
-
-  public static void testCompareByteChar() {
-    expectEquals(-1, compareByteChar(Byte.MIN_VALUE, (char)0));
-    expectEquals(-1, compareByteChar(Byte.MIN_VALUE, (char)1));
-    expectEquals(-1, compareByteChar(Byte.MIN_VALUE, Character.MAX_VALUE));
-    expectEquals(-1, compareByteChar((byte)-1, (char)0));
-    expectEquals(-1, compareByteChar((byte)-1, (char)1));
-    expectEquals(-1, compareByteChar((byte)0, (char)1));
-    expectEquals(-1, compareByteChar(Byte.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
-    expectEquals(-1, compareByteChar(Byte.MAX_VALUE, Character.MAX_VALUE));
-
-    expectEquals(0, compareByteChar((byte)0, (char)0));
-    expectEquals(0, compareByteChar((byte)1, (char)1));
-
-    expectEquals(1, compareByteChar((byte)1, (char)0));
-    expectEquals(1, compareByteChar(Byte.MAX_VALUE, (char)0));
-    expectEquals(1, compareByteChar(Byte.MAX_VALUE, (char)1));
-
-    for (byte i = -11; i <= 11; i++) {
-      for (char j = 0; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareByteChar(i, j));
-      }
-    }
-  }
-
-  public static void testCompareByteInt() {
-    expectEquals(-1, compareByteInt(Byte.MIN_VALUE, -1));
-    expectEquals(-1, compareByteInt(Byte.MIN_VALUE, 0));
-    expectEquals(-1, compareByteInt(Byte.MIN_VALUE, 1));
-    expectEquals(-1, compareByteInt(Byte.MIN_VALUE, Integer.MAX_VALUE));
-    expectEquals(-1, compareByteInt((byte)-1, 0));
-    expectEquals(-1, compareByteInt((byte)-1, 1));
-    expectEquals(-1, compareByteInt((byte)0, 1));
-    expectEquals(-1, compareByteInt(Byte.MAX_VALUE, Integer.MAX_VALUE - 1));
-    expectEquals(-1, compareByteInt(Byte.MAX_VALUE, Integer.MAX_VALUE));
-
-    expectEquals(0, compareByteInt((byte)-1, -1));
-    expectEquals(0, compareByteInt((byte)0, 0));
-    expectEquals(0, compareByteInt((byte)1, 1));
-
-    expectEquals(1, compareByteInt(Byte.MIN_VALUE, Integer.MIN_VALUE));
-    expectEquals(1, compareByteInt(Byte.MIN_VALUE, Integer.MIN_VALUE + 1));
-    expectEquals(1, compareByteInt((byte)0, -1));
-    expectEquals(1, compareByteInt((byte)1, -1));
-    expectEquals(1, compareByteInt((byte)1, 0));
-    expectEquals(1, compareByteInt(Byte.MAX_VALUE, Integer.MIN_VALUE));
-    expectEquals(1, compareByteInt(Byte.MAX_VALUE, -1));
-    expectEquals(1, compareByteInt(Byte.MAX_VALUE, 0));
-    expectEquals(1, compareByteInt(Byte.MAX_VALUE, 1));
-
-    for (byte i = -11; i <= 11; i++) {
-      for (int j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareByteInt(i, j));
-      }
-    }
-  }
-
-
-  public static void testCompareShortByte() {
-    expectEquals(-1, compareShortByte(Short.MIN_VALUE, Byte.MIN_VALUE));
-    expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)(Byte.MIN_VALUE + 1)));
-    expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)-1));
-    expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)0));
-    expectEquals(-1, compareShortByte(Short.MIN_VALUE, (byte)1));
-    expectEquals(-1, compareShortByte(Short.MIN_VALUE, Byte.MAX_VALUE));
-    expectEquals(-1, compareShortByte((short)-1, (byte)0));
-    expectEquals(-1, compareShortByte((short)-1, (byte)1));
-    expectEquals(-1, compareShortByte((short)0, (byte)1));
-
-    expectEquals(0, compareShortByte((short)-1, (byte)-1));
-    expectEquals(0, compareShortByte((short)0, (byte)0));
-    expectEquals(0, compareShortByte((short)1, (byte)1));
-
-    expectEquals(1, compareShortByte((short)0, (byte)-1));
-    expectEquals(1, compareShortByte((short)1, (byte)-1));
-    expectEquals(1, compareShortByte((short)1, (byte)0));
-    expectEquals(1, compareShortByte(Short.MAX_VALUE, Byte.MIN_VALUE));
-    expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)-1));
-    expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)0));
-    expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)1));
-    expectEquals(1, compareShortByte(Short.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
-    expectEquals(1, compareShortByte(Short.MAX_VALUE, Byte.MAX_VALUE));
-
-    for (short i = -11; i <= 11; i++) {
-      for (byte j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareShortByte(i, j));
-      }
-    }
-  }
-
-  public static void testCompareShortChar() {
-    expectEquals(-1, compareShortChar(Short.MIN_VALUE, (char)0));
-    expectEquals(-1, compareShortChar(Short.MIN_VALUE, (char)1));
-    expectEquals(-1, compareShortChar(Short.MIN_VALUE, Character.MAX_VALUE));
-    expectEquals(-1, compareShortChar((short)-1, (char)0));
-    expectEquals(-1, compareShortChar((short)-1, (char)1));
-    expectEquals(-1, compareShortChar((short)0, (char)1));
-    expectEquals(-1, compareShortChar(Short.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
-    expectEquals(-1, compareShortChar(Short.MAX_VALUE, Character.MAX_VALUE));
-
-    expectEquals(0, compareShortChar((short)0, (char)0));
-    expectEquals(0, compareShortChar((short)1, (char)1));
-
-    expectEquals(1, compareShortChar((short)1, (char)0));
-    expectEquals(1, compareShortChar(Short.MAX_VALUE, (char)0));
-    expectEquals(1, compareShortChar(Short.MAX_VALUE, (char)1));
-
-    for (short i = -11; i <= 11; i++) {
-      for (char j = 0; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareShortChar(i, j));
-      }
-    }
-  }
-
-  public static void testCompareShortInt() {
-    expectEquals(-1, compareShortInt(Short.MIN_VALUE, -1));
-    expectEquals(-1, compareShortInt(Short.MIN_VALUE, 0));
-    expectEquals(-1, compareShortInt(Short.MIN_VALUE, 1));
-    expectEquals(-1, compareShortInt(Short.MIN_VALUE, Integer.MAX_VALUE));
-    expectEquals(-1, compareShortInt((short)-1, 0));
-    expectEquals(-1, compareShortInt((short)-1, 1));
-    expectEquals(-1, compareShortInt((short)0, 1));
-    expectEquals(-1, compareShortInt(Short.MAX_VALUE, Integer.MAX_VALUE - 1));
-    expectEquals(-1, compareShortInt(Short.MAX_VALUE, Integer.MAX_VALUE));
-
-    expectEquals(0, compareShortInt((short)-1, -1));
-    expectEquals(0, compareShortInt((short)0, 0));
-    expectEquals(0, compareShortInt((short)1, 1));
-
-    expectEquals(1, compareShortInt(Short.MIN_VALUE, Integer.MIN_VALUE));
-    expectEquals(1, compareShortInt(Short.MIN_VALUE, Integer.MIN_VALUE + 1));
-    expectEquals(1, compareShortInt((short)0, -1));
-    expectEquals(1, compareShortInt((short)1, -1));
-    expectEquals(1, compareShortInt((short)1, 0));
-    expectEquals(1, compareShortInt(Short.MAX_VALUE, Integer.MIN_VALUE));
-    expectEquals(1, compareShortInt(Short.MAX_VALUE, -1));
-    expectEquals(1, compareShortInt(Short.MAX_VALUE, 0));
-    expectEquals(1, compareShortInt(Short.MAX_VALUE, 1));
-
-    for (short i = -11; i <= 11; i++) {
-      for (int j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareShortInt(i, j));
-      }
-    }
-  }
-
-
-  public static void testCompareCharByte() {
-    expectEquals(-1, compareCharByte((char)0, (byte)1));
-    expectEquals(-1, compareCharByte((char)0, Byte.MAX_VALUE));
-
-    expectEquals(0, compareCharByte((char)0, (byte)0));
-    expectEquals(0, compareCharByte((char)1, (byte)1));
-
-    expectEquals(1, compareCharByte((char)0, Byte.MIN_VALUE));
-    expectEquals(1, compareCharByte((char)0, (byte)(Byte.MIN_VALUE + 1)));
-    expectEquals(1, compareCharByte((char)0, (byte)-1));
-    expectEquals(1, compareCharByte((char)1, (byte)-1));
-    expectEquals(1, compareCharByte((char)1, (byte)0));
-    expectEquals(1, compareCharByte(Character.MAX_VALUE, Byte.MIN_VALUE));
-    expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)-1));
-    expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)0));
-    expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)1));
-    expectEquals(1, compareCharByte(Character.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
-    expectEquals(1, compareCharByte(Character.MAX_VALUE, Byte.MAX_VALUE));
-
-    for (char i = 0; i <= 11; i++) {
-      for (byte j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareCharByte(i, j));
-      }
-    }
-  }
-
-  public static void testCompareCharShort() {
-    expectEquals(-1, compareCharShort((char)0, (short)1));
-    expectEquals(-1, compareCharShort((char)0, Short.MAX_VALUE));
-
-    expectEquals(0, compareCharShort((char)0, (short)0));
-    expectEquals(0, compareCharShort((char)1, (short)1));
-
-    expectEquals(1, compareCharShort((char)0, Short.MIN_VALUE));
-    expectEquals(1, compareCharShort((char)0, (short)(Short.MIN_VALUE + 1)));
-    expectEquals(1, compareCharShort((char)0, (short)-1));
-    expectEquals(1, compareCharShort((char)1, (short)-1));
-    expectEquals(1, compareCharShort((char)1, (short)0));
-    expectEquals(1, compareCharShort(Character.MAX_VALUE, Short.MIN_VALUE));
-    expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)-1));
-    expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)0));
-    expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)1));
-    expectEquals(1, compareCharShort(Character.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
-    expectEquals(1, compareCharShort(Character.MAX_VALUE, Short.MAX_VALUE));
-
-    for (char i = 0; i <= 11; i++) {
-      for (short j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareCharShort(i, j));
-      }
-    }
-  }
-
-  public static void testCompareCharInt() {
-    expectEquals(-1, compareCharInt((char)0, 1));
-    expectEquals(-1, compareCharInt((char)0, Integer.MAX_VALUE));
-    expectEquals(-1, compareCharInt(Character.MAX_VALUE, Integer.MAX_VALUE - 1));
-    expectEquals(-1, compareCharInt(Character.MAX_VALUE, Integer.MAX_VALUE));
-
-    expectEquals(0, compareCharInt((char)0, 0));
-    expectEquals(0, compareCharInt((char)1, 1));
-
-    expectEquals(1, compareCharInt((char)0, Integer.MIN_VALUE));
-    expectEquals(1, compareCharInt((char)0, Integer.MIN_VALUE + 1));
-    expectEquals(1, compareCharInt((char)0, -1));
-    expectEquals(1, compareCharInt((char)1, -1));
-    expectEquals(1, compareCharInt((char)1, 0));
-    expectEquals(1, compareCharInt(Character.MAX_VALUE, Integer.MIN_VALUE));
-    expectEquals(1, compareCharInt(Character.MAX_VALUE, -1));
-    expectEquals(1, compareCharInt(Character.MAX_VALUE, 0));
-    expectEquals(1, compareCharInt(Character.MAX_VALUE, 1));
-
-    for (char i = 0; i <= 11; i++) {
-      for (int j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareCharInt(i, j));
-      }
-    }
-  }
-
-
-  public static void testCompareIntByte() {
-    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, Byte.MIN_VALUE));
-    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)(Byte.MIN_VALUE + 1)));
-    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)-1));
-    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)0));
-    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, (byte)1));
-    expectEquals(-1, compareIntByte(Integer.MIN_VALUE, Byte.MAX_VALUE));
-    expectEquals(-1, compareIntByte(-1, (byte)0));
-    expectEquals(-1, compareIntByte(-1, (byte)1));
-    expectEquals(-1, compareIntByte(0, (byte)1));
-
-    expectEquals(0, compareIntByte(-1, (byte)-1));
-    expectEquals(0, compareIntByte(0, (byte)0));
-    expectEquals(0, compareIntByte(1, (byte)1));
-
-    expectEquals(1, compareIntByte(0, (byte)-1));
-    expectEquals(1, compareIntByte(1, (byte)-1));
-    expectEquals(1, compareIntByte(1, (byte)0));
-    expectEquals(1, compareIntByte(Integer.MAX_VALUE, Byte.MIN_VALUE));
-    expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)-1));
-    expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)0));
-    expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)1));
-    expectEquals(1, compareIntByte(Integer.MAX_VALUE, (byte)(Byte.MAX_VALUE - 1)));
-    expectEquals(1, compareIntByte(Integer.MAX_VALUE, Byte.MAX_VALUE));
-
-    for (int i = -11; i <= 11; i++) {
-      for (byte j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareIntByte(i, j));
-      }
-    }
-  }
-
-  public static void testCompareIntShort() {
-    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, Short.MIN_VALUE));
-    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)(Short.MIN_VALUE + 1)));
-    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)-1));
-    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)0));
-    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, (short)1));
-    expectEquals(-1, compareIntShort(Integer.MIN_VALUE, Short.MAX_VALUE));
-    expectEquals(-1, compareIntShort(-1, (short)0));
-    expectEquals(-1, compareIntShort(-1, (short)1));
-    expectEquals(-1, compareIntShort(0, (short)1));
-
-    expectEquals(0, compareIntShort(-1, (short)-1));
-    expectEquals(0, compareIntShort(0, (short)0));
-    expectEquals(0, compareIntShort(1, (short)1));
-
-    expectEquals(1, compareIntShort(0, (short)-1));
-    expectEquals(1, compareIntShort(1, (short)-1));
-    expectEquals(1, compareIntShort(1, (short)0));
-    expectEquals(1, compareIntShort(Integer.MAX_VALUE, Short.MIN_VALUE));
-    expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)-1));
-    expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)0));
-    expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)1));
-    expectEquals(1, compareIntShort(Integer.MAX_VALUE, (short)(Short.MAX_VALUE - 1)));
-    expectEquals(1, compareIntShort(Integer.MAX_VALUE, Short.MAX_VALUE));
-
-    for (int i = -11; i <= 11; i++) {
-      for (short j = -11; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareIntShort(i, j));
-      }
-    }
-  }
-
-  public static void testCompareIntChar() {
-    expectEquals(-1, compareIntChar(Integer.MIN_VALUE, (char)0));
-    expectEquals(-1, compareIntChar(Integer.MIN_VALUE, (char)1));
-    expectEquals(-1, compareIntChar(Integer.MIN_VALUE, Character.MAX_VALUE));
-    expectEquals(-1, compareIntChar(-1, (char)0));
-    expectEquals(-1, compareIntChar(-1, (char)1));
-    expectEquals(-1, compareIntChar(0, (char)1));
-
-    expectEquals(0, compareIntChar(0, (char)0));
-    expectEquals(0, compareIntChar(1, (char)1));
-
-    expectEquals(1, compareIntChar(1, (char)0));
-    expectEquals(1, compareIntChar(Integer.MAX_VALUE, (char)0));
-    expectEquals(1, compareIntChar(Integer.MAX_VALUE, (char)1));
-    expectEquals(1, compareIntChar(Integer.MAX_VALUE, (char)(Character.MAX_VALUE - 1)));
-    expectEquals(1, compareIntChar(Integer.MAX_VALUE, Character.MAX_VALUE));
-
-    for (int i = -11; i <= 11; i++) {
-      for (char j = 0; j <= 11; j++) {
-        int expected = 0;
-        if (i < j) expected = -1;
-        else if (i > j) expected = 1;
-        expectEquals(expected, compareIntChar(i, j));
-      }
-    }
-  }
-
-
-  public static void main(String args[]) throws Exception {
-    $opt$noinline$testReplaceInputWithItself(42);
-
-    testCompareBooleans();
-    testCompareBytes();
-    testCompareShorts();
-    testCompareChars();
-    testCompareInts();
-    testCompareLongs();
-
-    testCompareByteShort();
-    testCompareByteChar();
-    testCompareByteInt();
-
-    testCompareShortByte();
-    testCompareShortChar();
-    testCompareShortInt();
-
-    testCompareCharByte();
-    testCompareCharShort();
-    testCompareCharInt();
-
-    testCompareIntByte();
-    testCompareIntShort();
-    testCompareIntChar();
-
-    System.out.println("passed");
-  }
-
-  private static void expectEquals(int expected, int result) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
-}
diff --git a/test/568-checker-onebit/Android.bp b/test/568-checker-onebit/Android.bp
new file mode 100644
index 0000000..649b81c
--- /dev/null
+++ b/test/568-checker-onebit/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `568-checker-onebit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-568-checker-onebit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-568-checker-onebit-expected-stdout",
+        ":art-run-test-568-checker-onebit-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-568-checker-onebit-expected-stdout",
+    out: ["art-run-test-568-checker-onebit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-568-checker-onebit-expected-stderr",
+    out: ["art-run-test-568-checker-onebit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/529-long-split/expected.txt b/test/568-checker-onebit/expected-stderr.txt
similarity index 100%
copy from test/529-long-split/expected.txt
copy to test/568-checker-onebit/expected-stderr.txt
diff --git a/test/568-checker-onebit/expected.txt b/test/568-checker-onebit/expected-stdout.txt
similarity index 100%
rename from test/568-checker-onebit/expected.txt
rename to test/568-checker-onebit/expected-stdout.txt
diff --git a/test/569-checker-pattern-replacement/expected.txt b/test/569-checker-pattern-replacement/expected-stderr.txt
similarity index 100%
rename from test/569-checker-pattern-replacement/expected.txt
rename to test/569-checker-pattern-replacement/expected-stderr.txt
diff --git a/test/569-checker-pattern-replacement/expected.txt b/test/569-checker-pattern-replacement/expected-stdout.txt
similarity index 100%
copy from test/569-checker-pattern-replacement/expected.txt
copy to test/569-checker-pattern-replacement/expected-stdout.txt
diff --git a/test/569-checker-pattern-replacement/src-multidex/Base.java b/test/569-checker-pattern-replacement/src-multidex/Base.java
index f4d59af..62322e7 100644
--- a/test/569-checker-pattern-replacement/src-multidex/Base.java
+++ b/test/569-checker-pattern-replacement/src-multidex/Base.java
@@ -59,7 +59,7 @@
     this(0.0, objectValue);
   }
 
-  Base(int intValue, long dummy) {
+  Base(int intValue, long unused) {
     this(intValue, 0.0, null);
   }
 
diff --git a/test/569-checker-pattern-replacement/src-multidex/DerivedInSecondDex.java b/test/569-checker-pattern-replacement/src-multidex/DerivedInSecondDex.java
index 50266e8..05d63c2 100644
--- a/test/569-checker-pattern-replacement/src-multidex/DerivedInSecondDex.java
+++ b/test/569-checker-pattern-replacement/src-multidex/DerivedInSecondDex.java
@@ -24,7 +24,7 @@
     super(intValue);
   }
 
-  DerivedInSecondDex(long dummy) {
+  DerivedInSecondDex(long unused) {
     // Matched: Superclass in a different dex file has an IPUT that's pruned because we store 0.
     super(0);
   }
diff --git a/test/569-checker-pattern-replacement/src-multidex/Second.java b/test/569-checker-pattern-replacement/src-multidex/Second.java
index cba1dc8..7a209de 100644
--- a/test/569-checker-pattern-replacement/src-multidex/Second.java
+++ b/test/569-checker-pattern-replacement/src-multidex/Second.java
@@ -95,7 +95,7 @@
   public int instanceIntField = 42;
   public double instanceDoubleField = -42.0;
   public Object instanceObjectField = null;
-  public String instanceStringField = "dummy";
+  public String instanceStringField = "placeholder";
   public long instanceLongField = 0;  // Overwritten by setters.
 
   public static int staticIntField = 4242;
diff --git a/test/569-checker-pattern-replacement/src/Main.java b/test/569-checker-pattern-replacement/src/Main.java
index ce7cdb0..e2658a4 100644
--- a/test/569-checker-pattern-replacement/src/Main.java
+++ b/test/569-checker-pattern-replacement/src/Main.java
@@ -209,10 +209,11 @@
   /// CHECK:      {{d\d+}}            InvokeVirtual
 
   /// CHECK-START: double Main.getDoubleFromParam(Second) inliner (after)
-  /// CHECK:      {{d\d+}}            InvokeVirtual
+  /// CHECK:      {{d\d+}}            InvokeStaticOrDirect
 
   /// CHECK-START: double Main.getDoubleFromParam(Second) inliner (after)
   /// CHECK-NOT:                      InstanceFieldGet
+  /// CHECK-NOT:                      InvokeVirtual
 
   public static double getDoubleFromParam(Second s) {
     return s.getInstanceDoubleFieldFromParam(s);
@@ -222,11 +223,12 @@
   /// CHECK:      {{i\d+}}            InvokeVirtual
 
   /// CHECK-START: int Main.getStaticInt(Second) inliner (after)
-  /// CHECK:      {{i\d+}}            InvokeVirtual
+  /// CHECK:      {{i\d+}}            InvokeStaticOrDirect
 
   /// CHECK-START: int Main.getStaticInt(Second) inliner (after)
   /// CHECK-NOT:                      InstanceFieldGet
   /// CHECK-NOT:                      StaticFieldGet
+  /// CHECK-NOT:                      InvokeVirtual
 
   public static int getStaticInt(Second s) {
     return s.getStaticIntField();
@@ -287,10 +289,11 @@
   /// CHECK:                          InvokeVirtual
 
   /// CHECK-START: long Main.setLongThroughParam(Second, long) inliner (after)
-  /// CHECK:                          InvokeVirtual
+  /// CHECK:                          InvokeStaticOrDirect
 
   /// CHECK-START: long Main.setLongThroughParam(Second, long) inliner (after)
   /// CHECK-NOT:                      InstanceFieldSet
+  /// CHECK-NOT:                      InvokeVirtual
 
   public static long setLongThroughParam(Second s, long value) {
     s.setInstanceLongFieldThroughParam(s, value);
@@ -301,11 +304,12 @@
   /// CHECK:                          InvokeVirtual
 
   /// CHECK-START: float Main.setStaticFloat(Second, float) inliner (after)
-  /// CHECK:                          InvokeVirtual
+  /// CHECK:                          InvokeStaticOrDirect
 
   /// CHECK-START: float Main.setStaticFloat(Second, float) inliner (after)
   /// CHECK-NOT:                      InstanceFieldSet
   /// CHECK-NOT:                      StaticFieldSet
+  /// CHECK-NOT:                      InvokeVirtual
 
   public static float setStaticFloat(Second s, float value) {
     s.setStaticFloatField(value);
@@ -627,8 +631,8 @@
   /// CHECK-DAG:                      InstanceFieldSet
   /// CHECK-NOT:                      InstanceFieldSet
 
-  public static double constructBase(int intValue, long dummy) {
-    Base b = new Base(intValue, dummy);
+  public static double constructBase(int intValue, long placeholder) {
+    Base b = new Base(intValue, placeholder);
     return b.intField + b.doubleField;
   }
 
@@ -1145,8 +1149,8 @@
   /// CHECK-NOT:                      ConstructorFence
   /// CHECK-NOT:                      InstanceFieldSet
 
-  public static int constructDerivedInSecondDex(long dummy) {
-    DerivedInSecondDex d = new DerivedInSecondDex(dummy);
+  public static int constructDerivedInSecondDex(long placeholder) {
+    DerivedInSecondDex d = new DerivedInSecondDex(placeholder);
     return d.intField;
   }
 
@@ -1168,7 +1172,7 @@
     assertEquals(42, getInt(s));
     assertEquals(-42.0, getDouble(s));
     assertEquals(null, getObject(s));
-    assertEquals("dummy", getString(s));
+    assertEquals("placeholder", getString(s));
     // Not replaced IGET pattern.
     assertEquals(42, staticGetInt(s));
     assertEquals(-42.0, getDoubleFromParam(s));
@@ -1198,9 +1202,9 @@
     assertEquals(-34.0, constructBase(19, 15.0, null));
     assertEquals(-22.5, constructBaseWith0DoubleNull(22.5));
     assertEquals(-8.0, constructBase(2, 14.0, null, null));
-    assertEquals(-64.0, constructBase(4, 28.0, null, "dummy"));
+    assertEquals(-64.0, constructBase(4, 28.0, null, "placeholder"));
     assertEquals(13.0, constructBase(24, 2.0, new Object(), null));
-    assertEquals(30.0, constructBase(11, 4.0, new Object(), "dummy"));
+    assertEquals(30.0, constructBase(11, 4.0, new Object(), "placeholder"));
     assertEquals(43.0, constructBase(43.0));
     assertEquals(0.0, constructBaseWith0d());
     assertEquals(1.0, constructBase(new Object()));
@@ -1216,9 +1220,9 @@
     assertEquals(-7.0, constructDerived(5, 7.0, new Object()));
     assertEquals(-4.0, constructDerived(9, 4.0, null));
     assertEquals(0.0, constructDerived(1, 9.0, null, null));
-    assertEquals(0.0, constructDerived(2, 8.0, null, "dummy"));
+    assertEquals(0.0, constructDerived(2, 8.0, null, "placeholder"));
     assertEquals(0.0, constructDerived(3, 7.0, new Object(), null));
-    assertEquals(0.0, constructDerived(4, 6.0, new Object(), "dummy"));
+    assertEquals(0.0, constructDerived(4, 6.0, new Object(), "placeholder"));
     assertEquals(17.0, constructDerived(17.0f));
     assertEquals(-5.5, constructDerived(6, -7.0, new Object(), 6.5f));
 
diff --git a/test/570-checker-select/expected.txt b/test/570-checker-osr-locals/expected-stderr.txt
similarity index 100%
copy from test/570-checker-select/expected.txt
copy to test/570-checker-osr-locals/expected-stderr.txt
diff --git a/test/570-checker-osr-locals/expected.txt b/test/570-checker-osr-locals/expected-stdout.txt
similarity index 100%
rename from test/570-checker-osr-locals/expected.txt
rename to test/570-checker-osr-locals/expected-stdout.txt
diff --git a/test/570-checker-select/expected.txt b/test/570-checker-osr/expected-stderr.txt
similarity index 100%
copy from test/570-checker-select/expected.txt
copy to test/570-checker-osr/expected-stderr.txt
diff --git a/test/570-checker-osr/expected.txt b/test/570-checker-osr/expected-stdout.txt
similarity index 100%
rename from test/570-checker-osr/expected.txt
rename to test/570-checker-osr/expected-stdout.txt
diff --git a/test/570-checker-osr/osr.cc b/test/570-checker-osr/osr.cc
index 22423e2..d1caf3f 100644
--- a/test/570-checker-osr/osr.cc
+++ b/test/570-checker-osr/osr.cc
@@ -109,7 +109,7 @@
       method_name,
       [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
         ArtMethod* m = stack_visitor->GetMethod();
-        ProfilingInfo::Create(Thread::Current(), m, /* retry_allocation */ true);
+        ProfilingInfo::Create(Thread::Current(), m);
       });
 }
 
@@ -130,7 +130,7 @@
           usleep(1000);
           // Will either ensure it's compiled or do the compilation itself.
           jit->CompileMethod(
-              m, Thread::Current(), /*baseline=*/ false, /*osr=*/ true, /*prejit=*/ false);
+              m, Thread::Current(), CompilationKind::kOsr, /*prejit=*/ false);
         }
       });
 }
diff --git a/test/570-checker-select/Android.bp b/test/570-checker-select/Android.bp
new file mode 100644
index 0000000..e41303d
--- /dev/null
+++ b/test/570-checker-select/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `570-checker-select`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-570-checker-select",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-570-checker-select-expected-stdout",
+        ":art-run-test-570-checker-select-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-570-checker-select-expected-stdout",
+    out: ["art-run-test-570-checker-select-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-570-checker-select-expected-stderr",
+    out: ["art-run-test-570-checker-select-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/570-checker-select/expected.txt b/test/570-checker-select/expected-stderr.txt
similarity index 100%
rename from test/570-checker-select/expected.txt
rename to test/570-checker-select/expected-stderr.txt
diff --git a/test/570-checker-select/expected.txt b/test/570-checker-select/expected-stdout.txt
similarity index 100%
copy from test/570-checker-select/expected.txt
copy to test/570-checker-select/expected-stdout.txt
diff --git a/test/564-checker-inline-loop/expected.txt b/test/571-irreducible-loop/expected-stderr.txt
similarity index 100%
copy from test/564-checker-inline-loop/expected.txt
copy to test/571-irreducible-loop/expected-stderr.txt
diff --git a/test/571-irreducible-loop/expected.txt b/test/571-irreducible-loop/expected-stdout.txt
similarity index 100%
rename from test/571-irreducible-loop/expected.txt
rename to test/571-irreducible-loop/expected-stdout.txt
diff --git a/test/572-checker-array-get-regression/Android.bp b/test/572-checker-array-get-regression/Android.bp
new file mode 100644
index 0000000..415a9f1
--- /dev/null
+++ b/test/572-checker-array-get-regression/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `572-checker-array-get-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-572-checker-array-get-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-572-checker-array-get-regression-expected-stdout",
+        ":art-run-test-572-checker-array-get-regression-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-572-checker-array-get-regression-expected-stdout",
+    out: ["art-run-test-572-checker-array-get-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-572-checker-array-get-regression-expected-stderr",
+    out: ["art-run-test-572-checker-array-get-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/523-checker-can-throw-regression/expected.txt b/test/572-checker-array-get-regression/expected-stderr.txt
similarity index 100%
copy from test/523-checker-can-throw-regression/expected.txt
copy to test/572-checker-array-get-regression/expected-stderr.txt
diff --git a/test/572-checker-array-get-regression/expected.txt b/test/572-checker-array-get-regression/expected-stdout.txt
similarity index 100%
rename from test/572-checker-array-get-regression/expected.txt
rename to test/572-checker-array-get-regression/expected-stdout.txt
diff --git a/test/573-checker-checkcast-regression/Android.bp b/test/573-checker-checkcast-regression/Android.bp
new file mode 100644
index 0000000..cf7186f
--- /dev/null
+++ b/test/573-checker-checkcast-regression/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `573-checker-checkcast-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-573-checker-checkcast-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-573-checker-checkcast-regression-expected-stdout",
+        ":art-run-test-573-checker-checkcast-regression-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-573-checker-checkcast-regression-expected-stdout",
+    out: ["art-run-test-573-checker-checkcast-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-573-checker-checkcast-regression-expected-stderr",
+    out: ["art-run-test-573-checker-checkcast-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/523-checker-can-throw-regression/expected.txt b/test/573-checker-checkcast-regression/expected-stderr.txt
similarity index 100%
copy from test/523-checker-can-throw-regression/expected.txt
copy to test/573-checker-checkcast-regression/expected-stderr.txt
diff --git a/test/573-checker-checkcast-regression/expected.txt b/test/573-checker-checkcast-regression/expected-stdout.txt
similarity index 100%
rename from test/573-checker-checkcast-regression/expected.txt
rename to test/573-checker-checkcast-regression/expected-stdout.txt
diff --git a/test/574-irreducible-and-constant-area/expected.txt b/test/574-irreducible-and-constant-area/expected-stderr.txt
similarity index 100%
rename from test/574-irreducible-and-constant-area/expected.txt
rename to test/574-irreducible-and-constant-area/expected-stderr.txt
diff --git a/test/574-irreducible-and-constant-area/expected.txt b/test/574-irreducible-and-constant-area/expected-stdout.txt
similarity index 100%
copy from test/574-irreducible-and-constant-area/expected.txt
copy to test/574-irreducible-and-constant-area/expected-stdout.txt
diff --git a/test/575-checker-isnan/expected.txt b/test/575-checker-isnan/expected.txt
deleted file mode 100644
index b0aad4d..0000000
--- a/test/575-checker-isnan/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-passed
diff --git a/test/575-checker-isnan/info.txt b/test/575-checker-isnan/info.txt
deleted file mode 100644
index 5c48a6a..0000000
--- a/test/575-checker-isnan/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Unit test for float/double isNaN() operation.
diff --git a/test/575-checker-isnan/src/Main.java b/test/575-checker-isnan/src/Main.java
deleted file mode 100644
index cc71e5e..0000000
--- a/test/575-checker-isnan/src/Main.java
+++ /dev/null
@@ -1,126 +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.
- */
-
-public class Main {
-
-  /// CHECK-START: boolean Main.isNaN32(float) instruction_simplifier (before)
-  /// CHECK-DAG: <<Result:z\d+>> InvokeStaticOrDirect
-  /// CHECK-DAG: Return [<<Result>>]
-  //
-  /// CHECK-START: boolean Main.isNaN32(float) instruction_simplifier (after)
-  /// CHECK-DAG: <<Result:z\d+>> NotEqual
-  /// CHECK-DAG: Return [<<Result>>]
-  //
-  /// CHECK-START: boolean Main.isNaN32(float) instruction_simplifier (after)
-  /// CHECK-NOT: InvokeStaticOrDirect
-  private static boolean isNaN32(float x) {
-    return Float.isNaN(x);
-  }
-
-  /// CHECK-START: boolean Main.isNaN64(double) instruction_simplifier (before)
-  /// CHECK-DAG: <<Result:z\d+>> InvokeStaticOrDirect
-  /// CHECK-DAG: Return [<<Result>>]
-  //
-  /// CHECK-START: boolean Main.isNaN64(double) instruction_simplifier (after)
-  /// CHECK-DAG: <<Result:z\d+>> NotEqual
-  /// CHECK-DAG: Return [<<Result>>]
-  //
-  /// CHECK-START: boolean Main.isNaN64(double) instruction_simplifier (after)
-  /// CHECK-NOT: InvokeStaticOrDirect
-  private static boolean isNaN64(double x) {
-    return Double.isNaN(x);
-  }
-
-  public static void main(String args[]) {
-    // A few distinct numbers.
-    expectFalse(isNaN32(Float.NEGATIVE_INFINITY));
-    expectFalse(isNaN32(-1.0f));
-    expectFalse(isNaN32(-0.0f));
-    expectFalse(isNaN32(0.0f));
-    expectFalse(isNaN32(1.0f));
-    expectFalse(isNaN32(Float.POSITIVE_INFINITY));
-
-    // A few distinct subnormal numbers.
-    expectFalse(isNaN32(Float.intBitsToFloat(0x00400000)));
-    expectFalse(isNaN32(Float.intBitsToFloat(0x80400000)));
-    expectFalse(isNaN32(Float.intBitsToFloat(0x00000001)));
-    expectFalse(isNaN32(Float.intBitsToFloat(0x80000001)));
-
-    // A few NaN numbers.
-    expectTrue(isNaN32(Float.NaN));
-    expectTrue(isNaN32(0.0f / 0.0f));
-    expectTrue(isNaN32((float)Math.sqrt(-1.0f)));
-    float[] fvals = {
-      Float.intBitsToFloat(0x7f800001),
-      Float.intBitsToFloat(0x7fa00000),
-      Float.intBitsToFloat(0x7fc00000),
-      Float.intBitsToFloat(0x7fffffff),
-      Float.intBitsToFloat(0xff800001),
-      Float.intBitsToFloat(0xffa00000),
-      Float.intBitsToFloat(0xffc00000),
-      Float.intBitsToFloat(0xffffffff)
-    };
-    for (int i = 0; i < fvals.length; i++) {
-      expectTrue(isNaN32(fvals[i]));
-    }
-
-    // A few distinct numbers.
-    expectFalse(isNaN64(Double.NEGATIVE_INFINITY));
-    expectFalse(isNaN32(-1.0f));
-    expectFalse(isNaN64(-0.0d));
-    expectFalse(isNaN64(0.0d));
-    expectFalse(isNaN64(1.0d));
-    expectFalse(isNaN64(Double.POSITIVE_INFINITY));
-
-    // A few distinct subnormal numbers.
-    expectFalse(isNaN64(Double.longBitsToDouble(0x0008000000000000l)));
-    expectFalse(isNaN64(Double.longBitsToDouble(0x8008000000000000l)));
-    expectFalse(isNaN64(Double.longBitsToDouble(0x0000000000000001l)));
-    expectFalse(isNaN64(Double.longBitsToDouble(0x8000000000000001l)));
-
-    // A few NaN numbers.
-    expectTrue(isNaN64(Double.NaN));
-    expectTrue(isNaN64(0.0d / 0.0d));
-    expectTrue(isNaN64(Math.sqrt(-1.0d)));
-    double[] dvals = {
-      Double.longBitsToDouble(0x7ff0000000000001L),
-      Double.longBitsToDouble(0x7ff4000000000000L),
-      Double.longBitsToDouble(0x7ff8000000000000L),
-      Double.longBitsToDouble(0x7fffffffffffffffL),
-      Double.longBitsToDouble(0xfff0000000000001L),
-      Double.longBitsToDouble(0xfff4000000000000L),
-      Double.longBitsToDouble(0xfff8000000000000L),
-      Double.longBitsToDouble(0xffffffffffffffffL)
-    };
-    for (int i = 0; i < dvals.length; i++) {
-      expectTrue(isNaN64(dvals[i]));
-    }
-
-    System.out.println("passed");
-  }
-
-  private static void expectTrue(boolean value) {
-    if (!value) {
-      throw new Error("Expected True");
-    }
-  }
-
-  private static void expectFalse(boolean value) {
-    if (value) {
-      throw new Error("Expected False");
-    }
-  }
-}
diff --git a/test/514-shifts/expected.txt b/test/575-checker-string-init-alias/expected-stderr.txt
similarity index 100%
copy from test/514-shifts/expected.txt
copy to test/575-checker-string-init-alias/expected-stderr.txt
diff --git a/test/575-checker-string-init-alias/expected.txt b/test/575-checker-string-init-alias/expected-stdout.txt
similarity index 100%
rename from test/575-checker-string-init-alias/expected.txt
rename to test/575-checker-string-init-alias/expected-stdout.txt
diff --git a/test/576-polymorphic-inlining/Android.bp b/test/576-polymorphic-inlining/Android.bp
new file mode 100644
index 0000000..f40b51e
--- /dev/null
+++ b/test/576-polymorphic-inlining/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `576-polymorphic-inlining`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-576-polymorphic-inlining",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-576-polymorphic-inlining-expected-stdout",
+        ":art-run-test-576-polymorphic-inlining-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-576-polymorphic-inlining-expected-stdout",
+    out: ["art-run-test-576-polymorphic-inlining-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-576-polymorphic-inlining-expected-stderr",
+    out: ["art-run-test-576-polymorphic-inlining-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/576-polymorphic-inlining/expected.txt b/test/576-polymorphic-inlining/expected-stderr.txt
similarity index 100%
rename from test/576-polymorphic-inlining/expected.txt
rename to test/576-polymorphic-inlining/expected-stderr.txt
diff --git a/test/576-polymorphic-inlining/expected.txt b/test/576-polymorphic-inlining/expected-stdout.txt
similarity index 100%
copy from test/576-polymorphic-inlining/expected.txt
copy to test/576-polymorphic-inlining/expected-stdout.txt
diff --git a/test/577-checker-fp2int/Android.bp b/test/577-checker-fp2int/Android.bp
new file mode 100644
index 0000000..cd0a5d3
--- /dev/null
+++ b/test/577-checker-fp2int/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `577-checker-fp2int`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-577-checker-fp2int",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-577-checker-fp2int-expected-stdout",
+        ":art-run-test-577-checker-fp2int-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-577-checker-fp2int-expected-stdout",
+    out: ["art-run-test-577-checker-fp2int-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-577-checker-fp2int-expected-stderr",
+    out: ["art-run-test-577-checker-fp2int-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/528-long-hint/expected.txt b/test/577-checker-fp2int/expected-stderr.txt
similarity index 100%
copy from test/528-long-hint/expected.txt
copy to test/577-checker-fp2int/expected-stderr.txt
diff --git a/test/577-checker-fp2int/expected.txt b/test/577-checker-fp2int/expected-stdout.txt
similarity index 100%
rename from test/577-checker-fp2int/expected.txt
rename to test/577-checker-fp2int/expected-stdout.txt
diff --git a/test/578-bce-visit/Android.bp b/test/578-bce-visit/Android.bp
new file mode 100644
index 0000000..bddc53e
--- /dev/null
+++ b/test/578-bce-visit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `578-bce-visit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-578-bce-visit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-578-bce-visit-expected-stdout",
+        ":art-run-test-578-bce-visit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-578-bce-visit-expected-stdout",
+    out: ["art-run-test-578-bce-visit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-578-bce-visit-expected-stderr",
+    out: ["art-run-test-578-bce-visit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/529-long-split/expected.txt b/test/578-bce-visit/expected-stderr.txt
similarity index 100%
copy from test/529-long-split/expected.txt
copy to test/578-bce-visit/expected-stderr.txt
diff --git a/test/578-bce-visit/expected.txt b/test/578-bce-visit/expected-stdout.txt
similarity index 100%
rename from test/578-bce-visit/expected.txt
rename to test/578-bce-visit/expected-stdout.txt
diff --git a/test/578-polymorphic-inlining/Android.bp b/test/578-polymorphic-inlining/Android.bp
new file mode 100644
index 0000000..207c91b
--- /dev/null
+++ b/test/578-polymorphic-inlining/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `578-polymorphic-inlining`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-578-polymorphic-inlining",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-578-polymorphic-inlining-expected-stdout",
+        ":art-run-test-578-polymorphic-inlining-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-578-polymorphic-inlining-expected-stdout",
+    out: ["art-run-test-578-polymorphic-inlining-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-578-polymorphic-inlining-expected-stderr",
+    out: ["art-run-test-578-polymorphic-inlining-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/578-polymorphic-inlining/expected.txt b/test/578-polymorphic-inlining/expected-stderr.txt
similarity index 100%
rename from test/578-polymorphic-inlining/expected.txt
rename to test/578-polymorphic-inlining/expected-stderr.txt
diff --git a/test/578-polymorphic-inlining/expected.txt b/test/578-polymorphic-inlining/expected-stdout.txt
similarity index 100%
copy from test/578-polymorphic-inlining/expected.txt
copy to test/578-polymorphic-inlining/expected-stdout.txt
diff --git a/test/579-inline-infinite/Android.bp b/test/579-inline-infinite/Android.bp
new file mode 100644
index 0000000..39fce3f
--- /dev/null
+++ b/test/579-inline-infinite/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `579-inline-infinite`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-579-inline-infinite",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-579-inline-infinite-expected-stdout",
+        ":art-run-test-579-inline-infinite-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-579-inline-infinite-expected-stdout",
+    out: ["art-run-test-579-inline-infinite-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-579-inline-infinite-expected-stderr",
+    out: ["art-run-test-579-inline-infinite-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/579-inline-infinite/expected.txt b/test/579-inline-infinite/expected-stderr.txt
similarity index 100%
rename from test/579-inline-infinite/expected.txt
rename to test/579-inline-infinite/expected-stderr.txt
diff --git a/test/579-inline-infinite/expected.txt b/test/579-inline-infinite/expected-stdout.txt
similarity index 100%
copy from test/579-inline-infinite/expected.txt
copy to test/579-inline-infinite/expected-stdout.txt
diff --git a/test/580-checker-round/Android.bp b/test/580-checker-round/Android.bp
new file mode 100644
index 0000000..5a05b19
--- /dev/null
+++ b/test/580-checker-round/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `580-checker-round`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-580-checker-round",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-580-checker-round-expected-stdout",
+        ":art-run-test-580-checker-round-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-580-checker-round-expected-stdout",
+    out: ["art-run-test-580-checker-round-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-580-checker-round-expected-stderr",
+    out: ["art-run-test-580-checker-round-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/580-crc32/expected.txt b/test/580-checker-round/expected-stderr.txt
similarity index 100%
copy from test/580-crc32/expected.txt
copy to test/580-checker-round/expected-stderr.txt
diff --git a/test/580-checker-round/expected.txt b/test/580-checker-round/expected-stdout.txt
similarity index 100%
rename from test/580-checker-round/expected.txt
rename to test/580-checker-round/expected-stdout.txt
diff --git a/test/580-crc32/expected.txt b/test/580-checker-string-fact-intrinsics/expected-stderr.txt
similarity index 100%
copy from test/580-crc32/expected.txt
copy to test/580-checker-string-fact-intrinsics/expected-stderr.txt
diff --git a/test/580-checker-string-fact-intrinsics/expected.txt b/test/580-checker-string-fact-intrinsics/expected-stdout.txt
similarity index 100%
rename from test/580-checker-string-fact-intrinsics/expected.txt
rename to test/580-checker-string-fact-intrinsics/expected-stdout.txt
diff --git a/test/580-crc32/Android.bp b/test/580-crc32/Android.bp
new file mode 100644
index 0000000..7d20949
--- /dev/null
+++ b/test/580-crc32/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `580-crc32`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-580-crc32",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-580-crc32-expected-stdout",
+        ":art-run-test-580-crc32-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-580-crc32-expected-stdout",
+    out: ["art-run-test-580-crc32-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-580-crc32-expected-stderr",
+    out: ["art-run-test-580-crc32-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/580-crc32/expected.txt b/test/580-crc32/expected-stderr.txt
similarity index 100%
rename from test/580-crc32/expected.txt
rename to test/580-crc32/expected-stderr.txt
diff --git a/test/580-crc32/expected.txt b/test/580-crc32/expected-stdout.txt
similarity index 100%
copy from test/580-crc32/expected.txt
copy to test/580-crc32/expected-stdout.txt
diff --git a/test/580-fp16/expected.txt b/test/580-fp16/expected-stderr.txt
similarity index 100%
rename from test/580-fp16/expected.txt
rename to test/580-fp16/expected-stderr.txt
diff --git a/test/580-fp16/expected.txt b/test/580-fp16/expected-stdout.txt
similarity index 100%
copy from test/580-fp16/expected.txt
copy to test/580-fp16/expected-stdout.txt
diff --git a/test/581-rtp/Android.bp b/test/581-rtp/Android.bp
new file mode 100644
index 0000000..9966080
--- /dev/null
+++ b/test/581-rtp/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `581-rtp`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-581-rtp",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-581-rtp-expected-stdout",
+        ":art-run-test-581-rtp-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-581-rtp-expected-stdout",
+    out: ["art-run-test-581-rtp-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-581-rtp-expected-stderr",
+    out: ["art-run-test-581-rtp-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/581-rtp/expected.txt b/test/581-rtp/expected-stderr.txt
similarity index 100%
rename from test/581-rtp/expected.txt
rename to test/581-rtp/expected-stderr.txt
diff --git a/test/581-rtp/expected.txt b/test/581-rtp/expected-stdout.txt
similarity index 100%
copy from test/581-rtp/expected.txt
copy to test/581-rtp/expected-stdout.txt
diff --git a/test/582-checker-bce-length/Android.bp b/test/582-checker-bce-length/Android.bp
new file mode 100644
index 0000000..937fd2d
--- /dev/null
+++ b/test/582-checker-bce-length/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `582-checker-bce-length`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-582-checker-bce-length",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-582-checker-bce-length-expected-stdout",
+        ":art-run-test-582-checker-bce-length-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-582-checker-bce-length-expected-stdout",
+    out: ["art-run-test-582-checker-bce-length-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-582-checker-bce-length-expected-stderr",
+    out: ["art-run-test-582-checker-bce-length-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/499-bce-phi-array-length/expected.txt b/test/582-checker-bce-length/expected-stderr.txt
similarity index 100%
copy from test/499-bce-phi-array-length/expected.txt
copy to test/582-checker-bce-length/expected-stderr.txt
diff --git a/test/582-checker-bce-length/expected.txt b/test/582-checker-bce-length/expected-stdout.txt
similarity index 100%
rename from test/582-checker-bce-length/expected.txt
rename to test/582-checker-bce-length/expected-stdout.txt
diff --git a/test/583-checker-zero/Android.bp b/test/583-checker-zero/Android.bp
new file mode 100644
index 0000000..e920e2d
--- /dev/null
+++ b/test/583-checker-zero/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `583-checker-zero`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-583-checker-zero",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-583-checker-zero-expected-stdout",
+        ":art-run-test-583-checker-zero-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-583-checker-zero-expected-stdout",
+    out: ["art-run-test-583-checker-zero-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-583-checker-zero-expected-stderr",
+    out: ["art-run-test-583-checker-zero-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/583-checker-zero/expected.txt b/test/583-checker-zero/expected-stderr.txt
similarity index 100%
rename from test/583-checker-zero/expected.txt
rename to test/583-checker-zero/expected-stderr.txt
diff --git a/test/583-checker-zero/expected.txt b/test/583-checker-zero/expected-stdout.txt
similarity index 100%
copy from test/583-checker-zero/expected.txt
copy to test/583-checker-zero/expected-stdout.txt
diff --git a/test/584-checker-div-bool/Android.bp b/test/584-checker-div-bool/Android.bp
new file mode 100644
index 0000000..5e7f928
--- /dev/null
+++ b/test/584-checker-div-bool/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `584-checker-div-bool`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-584-checker-div-bool",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-584-checker-div-bool-expected-stdout",
+        ":art-run-test-584-checker-div-bool-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-584-checker-div-bool-expected-stdout",
+    out: ["art-run-test-584-checker-div-bool-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-584-checker-div-bool-expected-stderr",
+    out: ["art-run-test-584-checker-div-bool-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/584-checker-div-bool/expected.txt b/test/584-checker-div-bool/expected-stderr.txt
similarity index 100%
rename from test/584-checker-div-bool/expected.txt
rename to test/584-checker-div-bool/expected-stderr.txt
diff --git a/test/584-checker-div-bool/expected.txt b/test/584-checker-div-bool/expected-stdout.txt
similarity index 100%
copy from test/584-checker-div-bool/expected.txt
copy to test/584-checker-div-bool/expected-stdout.txt
diff --git a/test/585-inline-unresolved/expected.txt b/test/585-inline-unresolved/expected-stderr.txt
similarity index 100%
rename from test/585-inline-unresolved/expected.txt
rename to test/585-inline-unresolved/expected-stderr.txt
diff --git a/test/585-inline-unresolved/expected.txt b/test/585-inline-unresolved/expected-stdout.txt
similarity index 100%
copy from test/585-inline-unresolved/expected.txt
copy to test/585-inline-unresolved/expected-stdout.txt
diff --git a/test/586-checker-null-array-get/expected.txt b/test/586-checker-null-array-get/expected-stderr.txt
similarity index 100%
rename from test/586-checker-null-array-get/expected.txt
rename to test/586-checker-null-array-get/expected-stderr.txt
diff --git a/test/586-checker-null-array-get/expected.txt b/test/586-checker-null-array-get/expected-stdout.txt
similarity index 100%
copy from test/586-checker-null-array-get/expected.txt
copy to test/586-checker-null-array-get/expected-stdout.txt
diff --git a/test/587-inline-class-error/expected.txt b/test/587-inline-class-error/expected-stderr.txt
similarity index 100%
rename from test/587-inline-class-error/expected.txt
rename to test/587-inline-class-error/expected-stderr.txt
diff --git a/test/587-inline-class-error/expected.txt b/test/587-inline-class-error/expected-stdout.txt
similarity index 100%
copy from test/587-inline-class-error/expected.txt
copy to test/587-inline-class-error/expected-stdout.txt
diff --git a/test/1911-get-local-var-table/expected.txt b/test/588-checker-irreducib-lifetime-hole/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/588-checker-irreducib-lifetime-hole/expected-stderr.txt
diff --git a/test/588-checker-irreducib-lifetime-hole/expected.txt b/test/588-checker-irreducib-lifetime-hole/expected-stdout.txt
similarity index 100%
rename from test/588-checker-irreducib-lifetime-hole/expected.txt
rename to test/588-checker-irreducib-lifetime-hole/expected-stdout.txt
diff --git a/test/589-super-imt/Android.bp b/test/589-super-imt/Android.bp
new file mode 100644
index 0000000..5a79bc9
--- /dev/null
+++ b/test/589-super-imt/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `589-super-imt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-589-super-imt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-589-super-imt-expected-stdout",
+        ":art-run-test-589-super-imt-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-589-super-imt-expected-stdout",
+    out: ["art-run-test-589-super-imt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-589-super-imt-expected-stderr",
+    out: ["art-run-test-589-super-imt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/589-super-imt/expected.txt b/test/589-super-imt/expected-stderr.txt
similarity index 100%
rename from test/589-super-imt/expected.txt
rename to test/589-super-imt/expected-stderr.txt
diff --git a/test/589-super-imt/expected.txt b/test/589-super-imt/expected-stdout.txt
similarity index 100%
copy from test/589-super-imt/expected.txt
copy to test/589-super-imt/expected-stdout.txt
diff --git a/test/590-checker-arr-set-null-regression/Android.bp b/test/590-checker-arr-set-null-regression/Android.bp
new file mode 100644
index 0000000..e42602a
--- /dev/null
+++ b/test/590-checker-arr-set-null-regression/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `590-checker-arr-set-null-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-590-checker-arr-set-null-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-590-checker-arr-set-null-regression-expected-stdout",
+        ":art-run-test-590-checker-arr-set-null-regression-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-590-checker-arr-set-null-regression-expected-stdout",
+    out: ["art-run-test-590-checker-arr-set-null-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-590-checker-arr-set-null-regression-expected-stderr",
+    out: ["art-run-test-590-checker-arr-set-null-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/593-checker-long-2-float-regression/expected.txt b/test/590-checker-arr-set-null-regression/expected-stderr.txt
similarity index 100%
copy from test/593-checker-long-2-float-regression/expected.txt
copy to test/590-checker-arr-set-null-regression/expected-stderr.txt
diff --git a/test/590-checker-arr-set-null-regression/expected.txt b/test/590-checker-arr-set-null-regression/expected-stdout.txt
similarity index 100%
rename from test/590-checker-arr-set-null-regression/expected.txt
rename to test/590-checker-arr-set-null-regression/expected-stdout.txt
diff --git a/test/590-infinite-loop-with-nop/expected.txt b/test/590-infinite-loop-with-nop/expected-stderr.txt
similarity index 100%
rename from test/590-infinite-loop-with-nop/expected.txt
rename to test/590-infinite-loop-with-nop/expected-stderr.txt
diff --git a/test/590-infinite-loop-with-nop/expected.txt b/test/590-infinite-loop-with-nop/expected-stdout.txt
similarity index 100%
copy from test/590-infinite-loop-with-nop/expected.txt
copy to test/590-infinite-loop-with-nop/expected-stdout.txt
diff --git a/test/591-checker-regression-dead-loop/Android.bp b/test/591-checker-regression-dead-loop/Android.bp
new file mode 100644
index 0000000..b2138a8
--- /dev/null
+++ b/test/591-checker-regression-dead-loop/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `591-checker-regression-dead-loop`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-591-checker-regression-dead-loop",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-591-checker-regression-dead-loop-expected-stdout",
+        ":art-run-test-591-checker-regression-dead-loop-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-591-checker-regression-dead-loop-expected-stdout",
+    out: ["art-run-test-591-checker-regression-dead-loop-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-591-checker-regression-dead-loop-expected-stderr",
+    out: ["art-run-test-591-checker-regression-dead-loop-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/591-checker-regression-dead-loop/expected.txt b/test/591-checker-regression-dead-loop/expected-stderr.txt
similarity index 100%
rename from test/591-checker-regression-dead-loop/expected.txt
rename to test/591-checker-regression-dead-loop/expected-stderr.txt
diff --git a/test/591-checker-regression-dead-loop/expected.txt b/test/591-checker-regression-dead-loop/expected-stdout.txt
similarity index 100%
copy from test/591-checker-regression-dead-loop/expected.txt
copy to test/591-checker-regression-dead-loop/expected-stdout.txt
diff --git a/test/304-method-tracing/expected.txt b/test/591-new-instance-string/expected-stderr.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/591-new-instance-string/expected-stderr.txt
diff --git a/test/591-new-instance-string/expected.txt b/test/591-new-instance-string/expected-stdout.txt
similarity index 100%
rename from test/591-new-instance-string/expected.txt
rename to test/591-new-instance-string/expected-stdout.txt
diff --git a/test/592-checker-regression-bool-input/expected.txt b/test/592-checker-regression-bool-input/expected-stderr.txt
similarity index 100%
rename from test/592-checker-regression-bool-input/expected.txt
rename to test/592-checker-regression-bool-input/expected-stderr.txt
diff --git a/test/592-checker-regression-bool-input/expected.txt b/test/592-checker-regression-bool-input/expected-stdout.txt
similarity index 100%
copy from test/592-checker-regression-bool-input/expected.txt
copy to test/592-checker-regression-bool-input/expected-stdout.txt
diff --git a/test/593-checker-long-2-float-regression/expected.txt b/test/593-checker-boolean-2-integral-conv/expected-stderr.txt
similarity index 100%
copy from test/593-checker-long-2-float-regression/expected.txt
copy to test/593-checker-boolean-2-integral-conv/expected-stderr.txt
diff --git a/test/593-checker-boolean-2-integral-conv/expected.txt b/test/593-checker-boolean-2-integral-conv/expected-stdout.txt
similarity index 100%
rename from test/593-checker-boolean-2-integral-conv/expected.txt
rename to test/593-checker-boolean-2-integral-conv/expected-stdout.txt
diff --git a/test/593-checker-long-2-float-regression/Android.bp b/test/593-checker-long-2-float-regression/Android.bp
new file mode 100644
index 0000000..bc5adc7
--- /dev/null
+++ b/test/593-checker-long-2-float-regression/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `593-checker-long-2-float-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-593-checker-long-2-float-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-593-checker-long-2-float-regression-expected-stdout",
+        ":art-run-test-593-checker-long-2-float-regression-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-593-checker-long-2-float-regression-expected-stdout",
+    out: ["art-run-test-593-checker-long-2-float-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-593-checker-long-2-float-regression-expected-stderr",
+    out: ["art-run-test-593-checker-long-2-float-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/593-checker-long-2-float-regression/expected.txt b/test/593-checker-long-2-float-regression/expected-stderr.txt
similarity index 100%
rename from test/593-checker-long-2-float-regression/expected.txt
rename to test/593-checker-long-2-float-regression/expected-stderr.txt
diff --git a/test/593-checker-long-2-float-regression/expected.txt b/test/593-checker-long-2-float-regression/expected-stdout.txt
similarity index 100%
copy from test/593-checker-long-2-float-regression/expected.txt
copy to test/593-checker-long-2-float-regression/expected-stdout.txt
diff --git a/test/463-checker-boolean-simplifier/expected.txt b/test/593-checker-shift-and-simplifier/expected-stderr.txt
similarity index 100%
copy from test/463-checker-boolean-simplifier/expected.txt
copy to test/593-checker-shift-and-simplifier/expected-stderr.txt
diff --git a/test/593-checker-shift-and-simplifier/expected.txt b/test/593-checker-shift-and-simplifier/expected-stdout.txt
similarity index 100%
rename from test/593-checker-shift-and-simplifier/expected.txt
rename to test/593-checker-shift-and-simplifier/expected-stdout.txt
diff --git a/test/594-checker-array-alias/Android.bp b/test/594-checker-array-alias/Android.bp
new file mode 100644
index 0000000..82e5a88
--- /dev/null
+++ b/test/594-checker-array-alias/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `594-checker-array-alias`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-594-checker-array-alias",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-594-checker-array-alias-expected-stdout",
+        ":art-run-test-594-checker-array-alias-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-594-checker-array-alias-expected-stdout",
+    out: ["art-run-test-594-checker-array-alias-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-594-checker-array-alias-expected-stderr",
+    out: ["art-run-test-594-checker-array-alias-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/594-checker-irreducible-linorder/expected.txt b/test/594-checker-array-alias/expected-stderr.txt
similarity index 100%
copy from test/594-checker-irreducible-linorder/expected.txt
copy to test/594-checker-array-alias/expected-stderr.txt
diff --git a/test/594-checker-array-alias/expected.txt b/test/594-checker-array-alias/expected-stdout.txt
similarity index 100%
rename from test/594-checker-array-alias/expected.txt
rename to test/594-checker-array-alias/expected-stdout.txt
diff --git a/test/594-checker-irreducible-linorder/expected.txt b/test/594-checker-irreducible-linorder/expected-stderr.txt
similarity index 100%
rename from test/594-checker-irreducible-linorder/expected.txt
rename to test/594-checker-irreducible-linorder/expected-stderr.txt
diff --git a/test/594-checker-irreducible-linorder/expected.txt b/test/594-checker-irreducible-linorder/expected-stdout.txt
similarity index 100%
copy from test/594-checker-irreducible-linorder/expected.txt
copy to test/594-checker-irreducible-linorder/expected-stdout.txt
diff --git a/test/551-invoke-super/expected.txt b/test/594-invoke-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/594-invoke-super/expected-stderr.txt
diff --git a/test/594-invoke-super/expected.txt b/test/594-invoke-super/expected-stdout.txt
similarity index 100%
rename from test/594-invoke-super/expected.txt
rename to test/594-invoke-super/expected-stdout.txt
diff --git a/test/594-load-string-regression/Android.bp b/test/594-load-string-regression/Android.bp
new file mode 100644
index 0000000..b1a8644
--- /dev/null
+++ b/test/594-load-string-regression/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `594-load-string-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-594-load-string-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-594-load-string-regression-expected-stdout",
+        ":art-run-test-594-load-string-regression-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-594-load-string-regression-expected-stdout",
+    out: ["art-run-test-594-load-string-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-594-load-string-regression-expected-stderr",
+    out: ["art-run-test-594-load-string-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/413-regalloc-regression/expected.txt b/test/594-load-string-regression/expected-stderr.txt
similarity index 100%
copy from test/413-regalloc-regression/expected.txt
copy to test/594-load-string-regression/expected-stderr.txt
diff --git a/test/594-load-string-regression/expected.txt b/test/594-load-string-regression/expected-stdout.txt
similarity index 100%
rename from test/594-load-string-regression/expected.txt
rename to test/594-load-string-regression/expected-stdout.txt
diff --git a/test/519-bound-load-class/expected.txt b/test/595-error-class/expected-stderr.txt
similarity index 100%
copy from test/519-bound-load-class/expected.txt
copy to test/595-error-class/expected-stderr.txt
diff --git a/test/595-error-class/expected.txt b/test/595-error-class/expected-stdout.txt
similarity index 100%
rename from test/595-error-class/expected.txt
rename to test/595-error-class/expected-stdout.txt
diff --git a/test/595-profile-saving/Android.bp b/test/595-profile-saving/Android.bp
new file mode 100644
index 0000000..f062831
--- /dev/null
+++ b/test/595-profile-saving/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `595-profile-saving`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-595-profile-saving",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-595-profile-saving-expected-stdout",
+        ":art-run-test-595-profile-saving-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-595-profile-saving-expected-stdout",
+    out: ["art-run-test-595-profile-saving-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-595-profile-saving-expected-stderr",
+    out: ["art-run-test-595-profile-saving-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/304-method-tracing/expected.txt b/test/595-profile-saving/expected-stderr.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/595-profile-saving/expected-stderr.txt
diff --git a/test/595-profile-saving/expected.txt b/test/595-profile-saving/expected-stdout.txt
similarity index 100%
rename from test/595-profile-saving/expected.txt
rename to test/595-profile-saving/expected-stdout.txt
diff --git a/test/595-profile-saving/profile-saving.cc b/test/595-profile-saving/profile-saving.cc
index d6ca447..bec4ae9 100644
--- a/test/595-profile-saving/profile-saving.cc
+++ b/test/595-profile-saving/profile-saving.cc
@@ -39,7 +39,7 @@
   ScopedObjectAccess soa(env);
   ObjPtr<mirror::Executable> exec = soa.Decode<mirror::Executable>(method);
   ArtMethod* art_method = exec->GetArtMethod();
-  if (!ProfilingInfo::Create(soa.Self(), art_method, /* retry_allocation */ true)) {
+  if (ProfilingInfo::Create(soa.Self(), art_method) == nullptr) {
     LOG(ERROR) << "Failed to create profiling info for method " << art_method->PrettyMethod();
   }
 }
@@ -48,30 +48,38 @@
   ProfileSaver::ForceProcessProfiles();
 }
 
-extern "C" JNIEXPORT jboolean JNICALL Java_Main_presentInProfile(JNIEnv* env,
-                                                                 jclass,
-                                                                 jstring filename,
-                                                                 jobject method) {
-  ScopedUtfChars filename_chars(env, filename);
-  CHECK(filename_chars.c_str() != nullptr);
-  ScopedObjectAccess soa(env);
-  ObjPtr<mirror::Executable> exec = soa.Decode<mirror::Executable>(method);
-  ArtMethod* art_method = exec->GetArtMethod();
-  return ProfileSaver::HasSeenMethod(std::string(filename_chars.c_str()),
-                                     /*hot*/ true,
-                                     MethodReference(art_method->GetDexFile(),
-                                                     art_method->GetDexMethodIndex()));
-}
-
 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isForBootImage(JNIEnv* env,
                                                                jclass,
                                                                jstring filename) {
   ScopedUtfChars filename_chars(env, filename);
   CHECK(filename_chars.c_str() != nullptr);
 
-  ProfileCompilationInfo info;
-  info.Load(std::string(filename_chars.c_str()), /*clear_if_invalid=*/ false);
-  return info.IsForBootImage();
+  ProfileCompilationInfo info(/*for_boot_image=*/ true);
+  bool result = info.Load(std::string(filename_chars.c_str()), /*clear_if_invalid=*/ false);
+  return result ? JNI_TRUE : JNI_FALSE;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_presentInProfile(JNIEnv* env,
+                                                                 jclass c,
+                                                                 jstring filename,
+                                                                 jobject method) {
+  bool for_boot_image = Java_Main_isForBootImage(env, c, filename) == JNI_TRUE;
+  ScopedUtfChars filename_chars(env, filename);
+  CHECK(filename_chars.c_str() != nullptr);
+  ScopedObjectAccess soa(env);
+  ObjPtr<mirror::Executable> exec = soa.Decode<mirror::Executable>(method);
+  ArtMethod* art_method = exec->GetArtMethod();
+  MethodReference ref(art_method->GetDexFile(), art_method->GetDexMethodIndex());
+
+  ProfileCompilationInfo info(Runtime::Current()->GetArenaPool(), for_boot_image);
+  if (!info.Load(filename_chars.c_str(), /*clear_if_invalid=*/false)) {
+    LOG(ERROR) << "Failed to load profile from " << filename;
+    return JNI_FALSE;
+  }
+  const ProfileCompilationInfo::MethodHotness hotness = info.GetMethodHotness(ref);
+  // TODO: Why do we check `hotness.IsHot()` instead of `hotness.IsInProfile()`
+  // in a method named `presentInProfile()`?
+  return hotness.IsHot() ? JNI_TRUE : JNI_FALSE;
 }
 
 }  // namespace
diff --git a/test/595-profile-saving/src/Main.java b/test/595-profile-saving/src/Main.java
index e0952e1..e693006 100644
--- a/test/595-profile-saving/src/Main.java
+++ b/test/595-profile-saving/src/Main.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.Method;
@@ -27,8 +28,11 @@
       file = createTempFile();
       // String codePath = getDexBaseLocation();
       String codePath = System.getenv("DEX_LOCATION") + "/595-profile-saving.jar";
-      VMRuntime.registerAppInfo(file.getPath(),
-                                new String[] {codePath});
+      VMRuntime.registerAppInfo("test.app",
+                                file.getPath(),
+                                file.getPath(),
+                                new String[] {codePath},
+                                VMRuntime.CODE_PATH_TYPE_PRIMARY_APK);
 
       // Test that the profile saves an app method with a profiling info.
       Method appMethod = Main.class.getDeclaredMethod("testAddMethodToProfile",
@@ -70,7 +74,7 @@
   // Returns true if the profile is for the boot image.
   public static native boolean isForBootImage(String profile);
 
-  private static final String TEMP_FILE_NAME_PREFIX = "dummy";
+  private static final String TEMP_FILE_NAME_PREFIX = "temp";
   private static final String TEMP_FILE_NAME_SUFFIX = "-file";
 
   static native String getProfileInfoDump(
@@ -91,20 +95,32 @@
   }
 
   private static class VMRuntime {
+    public static final int CODE_PATH_TYPE_PRIMARY_APK = 1;
     private static final Method registerAppInfoMethod;
+
     static {
       try {
         Class<? extends Object> c = Class.forName("dalvik.system.VMRuntime");
         registerAppInfoMethod = c.getDeclaredMethod("registerAppInfo",
-            String.class, String[].class);
+            String.class, String.class, String.class, String[].class, int.class);
       } catch (Exception e) {
         throw new RuntimeException(e);
       }
     }
 
-    public static void registerAppInfo(String profile, String[] codePaths)
-        throws Exception {
-      registerAppInfoMethod.invoke(null, profile, codePaths);
+    public static void registerAppInfo(
+        String packageName,
+        String curProfile,
+        String refProfile,
+        String[] codePaths,
+        int codePathsType) throws Exception {
+      registerAppInfoMethod.invoke(
+          null,
+          packageName,
+          curProfile,
+          refProfile,
+          codePaths,
+          codePathsType);
     }
   }
 }
diff --git a/test/596-app-images/app_images.cc b/test/596-app-images/app_images.cc
index 498ea1d..1bc2c1e 100644
--- a/test/596-app-images/app_images.cc
+++ b/test/596-app-images/app_images.cc
@@ -27,6 +27,8 @@
 #include "gc/space/space-inl.h"
 #include "image.h"
 #include "mirror/class.h"
+#include "nativehelper/scoped_utf_chars.h"
+#include "oat_file.h"
 #include "runtime.h"
 #include "scoped_thread_state_change-inl.h"
 
@@ -34,13 +36,36 @@
 
 namespace {
 
-extern "C" JNIEXPORT jboolean JNICALL Java_Main_checkAppImageLoaded(JNIEnv*, jclass) {
+// Returns whether the extensionless basename of `location` is equal to name.
+// E.g. check_name("/foo/bar/baz.odex", "baz") == true,
+//      check_name("/foo/bar/baz.odex", "bar") == false
+static bool check_name(const std::string& location, const std::string& name) {
+  std::string loc_name = location;
+  size_t idx = loc_name.rfind('/');
+  if (idx != std::string::npos) {
+    loc_name = loc_name.substr(idx + 1);
+  }
+  idx = loc_name.rfind('.');
+  if (idx != std::string::npos) {
+    loc_name = loc_name.substr(0, idx);
+  }
+  return loc_name == name;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_checkAppImageLoaded(JNIEnv* env,
+                                                                    jclass,
+                                                                    jstring jimage_name) {
+  ScopedUtfChars image_name(env, jimage_name);
   ScopedObjectAccess soa(Thread::Current());
   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()) {
+      // Check that this is an app image associated with the dex file named
+      // `jname` by verifying the extensionless basename of the odex file
+      // location is equal to `jname`.
+      if (image_header.IsAppImage() &&
+          check_name(image_space->GetOatFile()->GetLocation(), image_name.c_str())) {
         return JNI_TRUE;
       }
     }
diff --git a/test/514-shifts/expected.txt b/test/596-app-images/expected-stderr.txt
similarity index 100%
copy from test/514-shifts/expected.txt
copy to test/596-app-images/expected-stderr.txt
diff --git a/test/596-app-images/expected-stdout.txt b/test/596-app-images/expected-stdout.txt
new file mode 100644
index 0000000..ff3be57
--- /dev/null
+++ b/test/596-app-images/expected-stdout.txt
@@ -0,0 +1,2 @@
+JNI_OnLoad called
+Secondary went
diff --git a/test/596-app-images/expected.txt b/test/596-app-images/expected.txt
deleted file mode 100644
index 6a5618e..0000000
--- a/test/596-app-images/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-JNI_OnLoad called
diff --git a/test/596-app-images/profile b/test/596-app-images/profile
new file mode 100644
index 0000000..2a3172c
--- /dev/null
+++ b/test/596-app-images/profile
@@ -0,0 +1,7 @@
+LMain$Inner;
+LMain$Nested;
+LStaticFields;
+LStaticFieldsInitSub;
+LStaticFieldsInit;
+LStaticInternString;
+LSecondary;
diff --git a/test/596-app-images/run b/test/596-app-images/run
new file mode 100644
index 0000000..dbdcd1c
--- /dev/null
+++ b/test/596-app-images/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2020 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.
+
+# We need a profile to tell dex2oat to include classes in the final app image
+exec ${RUN} --profile $@
diff --git a/test/596-app-images/src-art/Main.java b/test/596-app-images/src-art/Main.java
new file mode 100644
index 0000000..7da8b0b
--- /dev/null
+++ b/test/596-app-images/src-art/Main.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2020 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 dalvik.system.PathClassLoader;
+import java.lang.reflect.Field;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+class Main {
+  static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/596-app-images.jar";
+  static final String SECONDARY_DEX_FILE =
+    System.getenv("DEX_LOCATION") + "/596-app-images-ex.jar";
+  static final String LIBRARY_SEARCH_PATH = System.getProperty("java.library.path");
+
+  static class Inner {
+    final public static int abc = 10;
+  }
+
+  static class Nested {
+
+  }
+
+  public static void main(String[] args) throws Exception {
+    System.loadLibrary(args[0]);
+
+    testAppImageLoaded();
+    testInitializedClasses();
+    testInternedStrings();
+    testReloadInternedString();
+    testClassesOutsideAppImage();
+    testLoadingSecondaryAppImage();
+  }
+
+  public static native boolean checkAppImageLoaded(String name);
+  public static native boolean checkAppImageContains(Class<?> klass);
+  public static native boolean checkInitialized(Class<?> klass);
+
+  public static void testAppImageLoaded() throws Exception {
+    assertTrue("App image is loaded", checkAppImageLoaded("596-app-images"));
+    assertTrue("App image contains Inner", checkAppImageContains(Inner.class));
+  }
+
+  public static void testInitializedClasses() throws Exception {
+    assertInitialized(Inner.class);
+    assertInitialized(Nested.class);
+    assertInitialized(StaticFields.class);
+    assertInitialized(StaticFieldsInitSub.class);
+    assertInitialized(StaticFieldsInit.class);
+    assertInitialized(StaticInternString.class);
+  }
+
+  private static void assertInitialized(Class<?> klass) {
+    assertTrue(klass.toString() + " is preinitialized", checkInitialized(klass));
+  }
+
+  public static void testInternedStrings() throws Exception {
+    StringBuffer sb = new StringBuffer();
+    sb.append("java.");
+    sb.append("abc.");
+    sb.append("Action");
+
+    String tmp = sb.toString();
+    String intern = tmp.intern();
+
+    assertNotSame("Dynamically constructed string is not interned", tmp, intern);
+    assertEquals("Static string on initialized class is matches runtime interned string", intern,
+        StaticInternString.intent);
+    assertEquals("Static string on initialized class is pre-interned", BootInternedString.boot,
+        BootInternedString.boot.intern());
+
+    // TODO: Does this next check really provide us anything?
+    Field f = StaticInternString.class.getDeclaredField("intent");
+    assertEquals("String literals are interned properly", intern, f.get(null));
+
+    assertEquals("String literals are interned properly across classes",
+        StaticInternString.getIntent(), StaticInternString2.getIntent());
+  }
+
+  public static void testReloadInternedString() throws Exception {
+    // reload the class StaticInternString, check whether static strings interned properly
+    PathClassLoader loader = new PathClassLoader(DEX_FILE, LIBRARY_SEARCH_PATH, null);
+    Class<?> staticInternString = loader.loadClass("StaticInternString");
+    assertTrue("Class in app image isn't loaded a second time after loading dex file again",
+        checkAppImageContains(staticInternString));
+
+    Method getIntent = staticInternString.getDeclaredMethod("getIntent");
+    assertEquals("Interned strings are still interned after multiple dex loads",
+        StaticInternString.getIntent(), getIntent.invoke(staticInternString));
+  }
+
+  public static void testClassesOutsideAppImage() {
+    assertFalse("App image doesn't contain non-optimized class",
+        checkAppImageContains(NonOptimizedClass.class));
+    assertFalse("App image didn't pre-initialize non-optimized class",
+        checkInitialized(NonOptimizedClass.class));
+  }
+
+  public static void testLoadingSecondaryAppImage() throws Exception {
+    final ClassLoader parent = Main.class.getClassLoader();
+
+    // Initial check that the image isn't already loaded so we don't get bogus results below
+    assertFalse("Secondary app image isn't already loaded",
+        checkAppImageLoaded("596-app-images-ex"));
+
+    PathClassLoader pcl = new PathClassLoader(SECONDARY_DEX_FILE, parent);
+
+    assertTrue("Ensure app image is loaded if it should be",
+        checkAppImageLoaded("596-app-images-ex"));
+
+    Class<?> secondaryCls = pcl.loadClass("Secondary");
+    assertTrue("Ensure Secondary class is in the app image if the CLC is correct",
+        checkAppImageContains(secondaryCls));
+    assertTrue("Ensure Secondary class is preinitialized if the CLC is correct",
+        checkInitialized(secondaryCls));
+
+    secondaryCls.getDeclaredMethod("go").invoke(null);
+  }
+
+  private static void assertTrue(String message, boolean flag) {
+    if (flag) {
+      return;
+    }
+    throw new AssertionError(message);
+  }
+
+  private static void assertEquals(String message, Object a, Object b) {
+    StringBuilder sb = new StringBuilder(message != null ? message  : "");
+    if (sb.length() > 0) {
+      sb.append(" ");
+    }
+    sb.append("expected:<").append(a).append("> but was:<").append(b).append(">");
+    assertTrue(sb.toString(), (a == null && b == null) || (a != null && a.equals(b)));
+  }
+
+  private static void assertFalse(String message, boolean flag) {
+    assertTrue(message, !flag);
+  }
+
+  private static void assertNotSame(String message, Object a, Object b) {
+    StringBuilder sb = new StringBuilder(message != null ? message  : "");
+    if (sb.length() > 0) {
+      sb.append(" ");
+    }
+    sb.append("unexpected sameness, found:<").append(a).append("> and:<").append(b).append(">");
+    assertTrue(sb.toString(), a != b);
+  }
+}
+
+class StaticFields {
+  public static int abc;
+}
+
+class StaticFieldsInitSub extends StaticFieldsInit {
+  final public static int def = 10;
+}
+
+class StaticFieldsInit {
+  final public static int abc = 10;
+}
+
+class StaticInternString {
+  final public static String intent = "java.abc.Action";
+  static public String getIntent() {
+    return intent;
+  }
+}
+
+class BootInternedString {
+  final public static String boot = "double";
+}
+
+class StaticInternString2 {
+  final public static String intent = "java.abc.Action";
+
+  static String getIntent() {
+    return intent;
+  }
+}
+
+class NonOptimizedClass {}
diff --git a/test/596-app-images/src-ex/Secondary.java b/test/596-app-images/src-ex/Secondary.java
new file mode 100644
index 0000000..36eee88
--- /dev/null
+++ b/test/596-app-images/src-ex/Secondary.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 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 Secondary {
+  public static void go() {
+    System.out.println("Secondary went");
+  }
+}
diff --git a/test/596-app-images/src/Main.java b/test/596-app-images/src/Main.java
deleted file mode 100644
index 88d95f4..0000000
--- a/test/596-app-images/src/Main.java
+++ /dev/null
@@ -1,155 +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.
- */
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-
-class Main {
-  static class Inner {
-    final public static int abc = 10;
-  }
-
-  static class Nested {
-
-  }
-
-  public static void main(String[] args) {
-    System.loadLibrary(args[0]);
-    if (!checkAppImageLoaded()) {
-      System.out.println("App image is not loaded!");
-    } else if (!checkAppImageContains(Inner.class)) {
-      System.out.println("App image does not contain Inner!");
-    }
-
-    if (!checkInitialized(Inner.class))
-      System.out.println("Inner class is not initialized!");
-
-    if (!checkInitialized(Nested.class))
-      System.out.println("Nested class is not initialized!");
-
-    if (!checkInitialized(StaticFields.class))
-      System.out.println("StaticFields class is not initialized!");
-
-    if (!checkInitialized(StaticFieldsInitSub.class))
-      System.out.println("StaticFieldsInitSub class is not initialized!");
-
-    if (!checkInitialized(StaticFieldsInit.class))
-      System.out.println("StaticFieldsInit class is not initialized!");
-
-    if (!checkInitialized(StaticInternString.class))
-      System.out.println("StaticInternString class is not initialized!");
-
-    StringBuffer sb = new StringBuffer();
-    sb.append("java.");
-    sb.append("abc.");
-    sb.append("Action");
-
-    String tmp = sb.toString();
-    String intern = tmp.intern();
-
-    assertNotEqual(tmp, intern, "Dynamically constructed String, not interned.");
-    assertEqual(intern, StaticInternString.intent, "Static encoded literal String not interned.");
-    assertEqual(BootInternedString.boot, BootInternedString.boot.intern(),
-        "Static encoded literal String not moved back to runtime intern table.");
-
-    try {
-      Field f = StaticInternString.class.getDeclaredField("intent");
-      assertEqual(intern, f.get(null), "String Literals are not interned properly.");
-
-    } catch (Exception e) {
-      System.out.println("Exception");
-    }
-
-    assertEqual(StaticInternString.getIntent(), StaticInternString2.getIntent(),
-        "String Literals are not intenred properly, App image static strings duplicated.");
-
-    // reload the class StaticInternString, check whether static strings interned properly
-    final String DEX_FILE = System.getenv("DEX_LOCATION") + "/596-app-images.jar";
-    final String LIBRARY_SEARCH_PATH = System.getProperty("java.library.path");
-
-    try {
-      Class<?> pathClassLoader = Class.forName("dalvik.system.PathClassLoader");
-      if (pathClassLoader == null) {
-        throw new AssertionError("Counldn't find path class loader class");
-      }
-      Constructor<?> ctor =
-          pathClassLoader.getDeclaredConstructor(String.class, String.class, ClassLoader.class);
-      ClassLoader loader = (ClassLoader) ctor.newInstance(
-          DEX_FILE, LIBRARY_SEARCH_PATH, null);
-
-      Class<?> staticInternString = loader.loadClass("StaticInternString");
-
-      if (!checkAppImageContains(staticInternString)) {
-        System.out.println("Not loaded again.");
-      }
-      Method getIntent = staticInternString.getDeclaredMethod("getIntent");
-
-      assertEqual(StaticInternString.getIntent(), getIntent.invoke(staticInternString),
-          "Dynamically loaded app image's literal strings not interned properly.");
-    } catch (Exception e) {
-      e.printStackTrace(System.out);
-    }
-
-  }
-
-  public static native boolean checkAppImageLoaded();
-  public static native boolean checkAppImageContains(Class<?> klass);
-  public static native boolean checkInitialized(Class<?> klass);
-
-  public static void assertEqual(Object a, Object b, String msg) {
-    if (a != b)
-      System.out.println(msg);
-  }
-
-  public static void assertNotEqual(Object a, Object b, String msg) {
-    if (a == b)
-      System.out.println(msg);
-  }
-
-}
-
-class StaticFields{
-  public static int abc;
-}
-
-class StaticFieldsInitSub extends StaticFieldsInit {
-  final public static int def = 10;
-}
-
-class StaticFieldsInit{
-  final public static int abc = 10;
-}
-
-class StaticInternString {
-  final public static String intent = "java.abc.Action";
-  static public String getIntent() {
-    return intent;
-  }
-}
-
-class BootInternedString {
-  final public static String boot = "double";
-}
-
-class StaticInternString2 {
-  final public static String intent = "java.abc.Action";
-
-  static String getIntent() {
-    return intent;
-  }
-}
-
diff --git a/test/520-equivalent-phi/expected.txt b/test/596-checker-dead-phi/expected-stderr.txt
similarity index 100%
copy from test/520-equivalent-phi/expected.txt
copy to test/596-checker-dead-phi/expected-stderr.txt
diff --git a/test/596-checker-dead-phi/expected.txt b/test/596-checker-dead-phi/expected-stdout.txt
similarity index 100%
rename from test/596-checker-dead-phi/expected.txt
rename to test/596-checker-dead-phi/expected-stdout.txt
diff --git a/test/596-checker-dead-phi/src/Main.java b/test/596-checker-dead-phi/src/Main.java
index 5a3fffc..1a69078 100644
--- a/test/596-checker-dead-phi/src/Main.java
+++ b/test/596-checker-dead-phi/src/Main.java
@@ -23,7 +23,7 @@
   public static void main(String[] args) throws Exception {
     Class<?> c = Class.forName("IrreducibleLoop");
     // Note that we don't actually enter the loops in the 'liveness'
-    // method, so this is just a sanity check that part of the code we
+    // method, so this is just a verification that that part of the code we
     // generated for that method is correct.
     Method m = c.getMethod("liveness", int.class);
     Object[] arguments = { 42 };
diff --git a/test/080-oom-fragmentation/expected.txt b/test/596-monitor-inflation/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/596-monitor-inflation/expected-stderr.txt
diff --git a/test/596-monitor-inflation/expected.txt b/test/596-monitor-inflation/expected-stdout.txt
similarity index 100%
rename from test/596-monitor-inflation/expected.txt
rename to test/596-monitor-inflation/expected-stdout.txt
diff --git a/test/156-register-dex-file-multi-loader/expected.txt b/test/597-app-images-same-classloader/expected-stderr.txt
similarity index 100%
copy from test/156-register-dex-file-multi-loader/expected.txt
copy to test/597-app-images-same-classloader/expected-stderr.txt
diff --git a/test/597-app-images-same-classloader/expected-stdout.txt b/test/597-app-images-same-classloader/expected-stdout.txt
new file mode 100644
index 0000000..ff3be57
--- /dev/null
+++ b/test/597-app-images-same-classloader/expected-stdout.txt
@@ -0,0 +1,2 @@
+JNI_OnLoad called
+Secondary went
diff --git a/test/597-app-images-same-classloader/info.txt b/test/597-app-images-same-classloader/info.txt
new file mode 100644
index 0000000..38f6e70
--- /dev/null
+++ b/test/597-app-images-same-classloader/info.txt
@@ -0,0 +1,2 @@
+Tests that loading an app image into an already existent classloader works if
+the classloader context is correct.
diff --git a/test/597-app-images-same-classloader/profile b/test/597-app-images-same-classloader/profile
new file mode 100644
index 0000000..c7406e2
--- /dev/null
+++ b/test/597-app-images-same-classloader/profile
@@ -0,0 +1,2 @@
+LMain;
+LSecondary;
diff --git a/test/597-app-images-same-classloader/run b/test/597-app-images-same-classloader/run
new file mode 100644
index 0000000..496273f
--- /dev/null
+++ b/test/597-app-images-same-classloader/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2020 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.
+
+# We need a profile to tell dex2oat to include classes in the final app image
+exec ${RUN} --profile --secondary-class-loader-context "PCL[$DEX_LOCATION/$TEST_NAME.jar]" $@
diff --git a/test/597-app-images-same-classloader/src-art/Main.java b/test/597-app-images-same-classloader/src-art/Main.java
new file mode 100644
index 0000000..93fd40a
--- /dev/null
+++ b/test/597-app-images-same-classloader/src-art/Main.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 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 dalvik.system.PathClassLoader;
+
+class Main {
+  static final String TEST_NAME = "597-app-images-same-classloader";
+
+  static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/" + TEST_NAME + ".jar";
+  static final String LIBRARY_SEARCH_PATH = System.getProperty("java.library.path");
+
+  static final String SECONDARY_NAME = TEST_NAME + "-ex";
+  static final String SECONDARY_DEX_FILE =
+    System.getenv("DEX_LOCATION") + "/" + SECONDARY_NAME + ".jar";
+
+  public static void main(String[] args) throws Exception {
+    System.loadLibrary(args[0]);
+
+    testLoadingSecondaryAppImageInLoadedClassLoader();
+  }
+
+  public static native boolean checkAppImageLoaded(String name);
+  public static native boolean checkAppImageContains(Class<?> klass);
+  public static native boolean checkInitialized(Class<?> klass);
+
+  public static void testLoadingSecondaryAppImageInLoadedClassLoader() throws Exception {
+    // Initial check that the image isn't already loaded so we don't get bogus results below
+    assertFalse("Secondary app image isn't already loaded",
+        checkAppImageLoaded(SECONDARY_NAME));
+
+    PathClassLoader pcl = new PathClassLoader(DEX_FILE, LIBRARY_SEARCH_PATH, null);
+    pcl.addDexPath(SECONDARY_DEX_FILE);
+
+    assertTrue("Ensure app image is loaded if it should be",
+        checkAppImageLoaded(SECONDARY_NAME));
+
+    Class<?> secondaryCls = pcl.loadClass("Secondary");
+    assertTrue("Ensure Secondary class is in the app image",
+        checkAppImageContains(secondaryCls));
+    assertTrue("Ensure Secondary class is preinitialized", checkInitialized(secondaryCls));
+
+    secondaryCls.getDeclaredMethod("go").invoke(null);
+  }
+
+  private static void assertTrue(String message, boolean flag) {
+    if (flag) {
+      return;
+    }
+    throw new AssertionError(message);
+  }
+
+  private static void assertFalse(String message, boolean flag) {
+    assertTrue(message, !flag);
+  }
+}
diff --git a/test/597-app-images-same-classloader/src-ex/Secondary.java b/test/597-app-images-same-classloader/src-ex/Secondary.java
new file mode 100644
index 0000000..36eee88
--- /dev/null
+++ b/test/597-app-images-same-classloader/src-ex/Secondary.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 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 Secondary {
+  public static void go() {
+    System.out.println("Secondary went");
+  }
+}
diff --git a/test/597-deopt-busy-loop/Android.bp b/test/597-deopt-busy-loop/Android.bp
new file mode 100644
index 0000000..d1ee3f2
--- /dev/null
+++ b/test/597-deopt-busy-loop/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `597-deopt-busy-loop`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-597-deopt-busy-loop",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-597-deopt-busy-loop-expected-stdout",
+        ":art-run-test-597-deopt-busy-loop-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-597-deopt-busy-loop-expected-stdout",
+    out: ["art-run-test-597-deopt-busy-loop-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-597-deopt-busy-loop-expected-stderr",
+    out: ["art-run-test-597-deopt-busy-loop-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/696-loop/expected.txt b/test/597-deopt-busy-loop/expected-stderr.txt
similarity index 100%
copy from test/696-loop/expected.txt
copy to test/597-deopt-busy-loop/expected-stderr.txt
diff --git a/test/597-deopt-busy-loop/expected.txt b/test/597-deopt-busy-loop/expected-stdout.txt
similarity index 100%
rename from test/597-deopt-busy-loop/expected.txt
rename to test/597-deopt-busy-loop/expected-stdout.txt
diff --git a/test/597-deopt-invoke-stub/Android.bp b/test/597-deopt-invoke-stub/Android.bp
new file mode 100644
index 0000000..c47c62c
--- /dev/null
+++ b/test/597-deopt-invoke-stub/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `597-deopt-invoke-stub`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-597-deopt-invoke-stub",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-597-deopt-invoke-stub-expected-stdout",
+        ":art-run-test-597-deopt-invoke-stub-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-597-deopt-invoke-stub-expected-stdout",
+    out: ["art-run-test-597-deopt-invoke-stub-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-597-deopt-invoke-stub-expected-stderr",
+    out: ["art-run-test-597-deopt-invoke-stub-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/500-instanceof/expected.txt b/test/597-deopt-invoke-stub/expected-stderr.txt
similarity index 100%
copy from test/500-instanceof/expected.txt
copy to test/597-deopt-invoke-stub/expected-stderr.txt
diff --git a/test/597-deopt-invoke-stub/expected.txt b/test/597-deopt-invoke-stub/expected-stdout.txt
similarity index 100%
rename from test/597-deopt-invoke-stub/expected.txt
rename to test/597-deopt-invoke-stub/expected-stdout.txt
diff --git a/test/597-deopt-new-string/Android.bp b/test/597-deopt-new-string/Android.bp
new file mode 100644
index 0000000..c3716f2
--- /dev/null
+++ b/test/597-deopt-new-string/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `597-deopt-new-string`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-597-deopt-new-string",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-597-deopt-new-string-expected-stdout",
+        ":art-run-test-597-deopt-new-string-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-597-deopt-new-string-expected-stdout",
+    out: ["art-run-test-597-deopt-new-string-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-597-deopt-new-string-expected-stderr",
+    out: ["art-run-test-597-deopt-new-string-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/304-method-tracing/expected.txt b/test/597-deopt-new-string/expected-stderr.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/597-deopt-new-string/expected-stderr.txt
diff --git a/test/597-deopt-new-string/expected.txt b/test/597-deopt-new-string/expected-stdout.txt
similarity index 100%
rename from test/597-deopt-new-string/expected.txt
rename to test/597-deopt-new-string/expected-stdout.txt
diff --git a/test/598-checker-irreducible-dominance/expected.txt b/test/598-checker-irreducible-dominance/expected-stderr.txt
similarity index 100%
rename from test/598-checker-irreducible-dominance/expected.txt
rename to test/598-checker-irreducible-dominance/expected-stderr.txt
diff --git a/test/598-checker-irreducible-dominance/expected.txt b/test/598-checker-irreducible-dominance/expected-stdout.txt
similarity index 100%
copy from test/598-checker-irreducible-dominance/expected.txt
copy to test/598-checker-irreducible-dominance/expected-stdout.txt
diff --git a/test/564-checker-inline-loop/expected.txt b/test/599-checker-irreducible-loop/expected-stderr.txt
similarity index 100%
copy from test/564-checker-inline-loop/expected.txt
copy to test/599-checker-irreducible-loop/expected-stderr.txt
diff --git a/test/599-checker-irreducible-loop/expected.txt b/test/599-checker-irreducible-loop/expected-stdout.txt
similarity index 100%
rename from test/599-checker-irreducible-loop/expected.txt
rename to test/599-checker-irreducible-loop/expected-stdout.txt
diff --git a/test/599-checker-irreducible-loop/src/Main.java b/test/599-checker-irreducible-loop/src/Main.java
index b47721f..aefbc65 100644
--- a/test/599-checker-irreducible-loop/src/Main.java
+++ b/test/599-checker-irreducible-loop/src/Main.java
@@ -24,7 +24,7 @@
     Class<?> c = Class.forName("IrreducibleLoop");
     Method m = c.getMethod("test", int.class);
     Object[] arguments = { 42 };
-    // Invoke the code just for sanity checking.
+    // Invoke the code just for validation purposes.
     System.out.println(m.invoke(null, arguments));
   }
 }
diff --git a/test/606-erroneous-class/expected.txt b/test/600-verifier-fails/expected-stderr.txt
similarity index 100%
copy from test/606-erroneous-class/expected.txt
copy to test/600-verifier-fails/expected-stderr.txt
diff --git a/test/600-verifier-fails/expected.txt b/test/600-verifier-fails/expected-stdout.txt
similarity index 100%
rename from test/600-verifier-fails/expected.txt
rename to test/600-verifier-fails/expected-stdout.txt
diff --git a/test/607-daemon-stress/expected.txt b/test/601-method-access/expected-stderr.txt
similarity index 100%
copy from test/607-daemon-stress/expected.txt
copy to test/601-method-access/expected-stderr.txt
diff --git a/test/601-method-access/expected.txt b/test/601-method-access/expected-stdout.txt
similarity index 100%
rename from test/601-method-access/expected.txt
rename to test/601-method-access/expected-stdout.txt
diff --git a/test/602-deoptimizeable/Android.bp b/test/602-deoptimizeable/Android.bp
new file mode 100644
index 0000000..3aa61e5
--- /dev/null
+++ b/test/602-deoptimizeable/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `602-deoptimizeable`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-602-deoptimizeable",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-602-deoptimizeable-expected-stdout",
+        ":art-run-test-602-deoptimizeable-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-602-deoptimizeable-expected-stdout",
+    out: ["art-run-test-602-deoptimizeable-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-602-deoptimizeable-expected-stderr",
+    out: ["art-run-test-602-deoptimizeable-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/537-checker-debuggable/expected.txt b/test/602-deoptimizeable/expected-stderr.txt
similarity index 100%
copy from test/537-checker-debuggable/expected.txt
copy to test/602-deoptimizeable/expected-stderr.txt
diff --git a/test/602-deoptimizeable/expected.txt b/test/602-deoptimizeable/expected-stdout.txt
similarity index 100%
rename from test/602-deoptimizeable/expected.txt
rename to test/602-deoptimizeable/expected-stdout.txt
diff --git a/test/602-deoptimizeable/src/Main.java b/test/602-deoptimizeable/src/Main.java
index 46584b0..ba75f5a 100644
--- a/test/602-deoptimizeable/src/Main.java
+++ b/test/602-deoptimizeable/src/Main.java
@@ -19,16 +19,16 @@
 import java.util.Comparator;
 import java.util.HashMap;
 
-class DummyObject {
+class TestObject {
     public static boolean sHashCodeInvoked = false;
     private int i;
 
-    public DummyObject(int i) {
+    public TestObject(int i) {
         this.i = i;
     }
 
     public boolean equals(Object obj) {
-        return (obj instanceof DummyObject) && (i == ((DummyObject)obj).i);
+        return (obj instanceof TestObject) && (i == ((TestObject)obj).i);
     }
 
     public int hashCode() {
@@ -52,7 +52,7 @@
 
     public static void main(String[] args) throws Exception {
         System.loadLibrary(args[0]);
-        final HashMap<DummyObject, Long> map = new HashMap<DummyObject, Long>();
+        final HashMap<TestObject, Long> map = new HashMap<TestObject, Long>();
 
         // Single-frame deoptimization that covers partial fragment.
         execute(new Runnable() {
@@ -103,9 +103,9 @@
         execute(new Runnable() {
             public void run() {
                 try {
-                    map.put(new DummyObject(10), Long.valueOf(100));
-                    if (map.get(new DummyObject(10)) == null) {
-                        System.out.println("Expected map to contain DummyObject(10)");
+                    map.put(new TestObject(10), Long.valueOf(100));
+                    if (map.get(new TestObject(10)) == null) {
+                        System.out.println("Expected map to contain TestObject(10)");
                     }
                 } catch (Exception e) {
                     e.printStackTrace(System.out);
@@ -115,10 +115,10 @@
 
         undeoptimizeAll();  // Make compiled code useable again.
 
-        if (!DummyObject.sHashCodeInvoked) {
+        if (!TestObject.sHashCodeInvoked) {
             System.out.println("hashCode() method not invoked!");
         }
-        if (map.get(new DummyObject(10)) != 100) {
+        if (map.get(new TestObject(10)) != 100) {
             System.out.println("Wrong hashmap value!");
         }
         System.out.println("Finishing");
diff --git a/test/603-checker-instanceof/Android.bp b/test/603-checker-instanceof/Android.bp
new file mode 100644
index 0000000..3fcc54d
--- /dev/null
+++ b/test/603-checker-instanceof/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `603-checker-instanceof`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-603-checker-instanceof",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-603-checker-instanceof-expected-stdout",
+        ":art-run-test-603-checker-instanceof-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-603-checker-instanceof-expected-stdout",
+    out: ["art-run-test-603-checker-instanceof-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-603-checker-instanceof-expected-stderr",
+    out: ["art-run-test-603-checker-instanceof-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/603-checker-instanceof/expected.txt b/test/603-checker-instanceof/expected-stderr.txt
similarity index 100%
rename from test/603-checker-instanceof/expected.txt
rename to test/603-checker-instanceof/expected-stderr.txt
diff --git a/test/603-checker-instanceof/expected.txt b/test/603-checker-instanceof/expected-stdout.txt
similarity index 100%
copy from test/603-checker-instanceof/expected.txt
copy to test/603-checker-instanceof/expected-stdout.txt
diff --git a/test/604-hot-static-interface/Android.bp b/test/604-hot-static-interface/Android.bp
new file mode 100644
index 0000000..3657dc4
--- /dev/null
+++ b/test/604-hot-static-interface/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `604-hot-static-interface`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-604-hot-static-interface",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-604-hot-static-interface-expected-stdout",
+        ":art-run-test-604-hot-static-interface-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-604-hot-static-interface-expected-stdout",
+    out: ["art-run-test-604-hot-static-interface-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-604-hot-static-interface-expected-stderr",
+    out: ["art-run-test-604-hot-static-interface-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/423-invoke-interface/expected.txt b/test/604-hot-static-interface/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/604-hot-static-interface/expected-stderr.txt
diff --git a/test/604-hot-static-interface/expected.txt b/test/604-hot-static-interface/expected-stdout.txt
similarity index 100%
rename from test/604-hot-static-interface/expected.txt
rename to test/604-hot-static-interface/expected-stdout.txt
diff --git a/test/605-new-string-from-bytes/Android.bp b/test/605-new-string-from-bytes/Android.bp
new file mode 100644
index 0000000..4bbfa10
--- /dev/null
+++ b/test/605-new-string-from-bytes/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `605-new-string-from-bytes`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-605-new-string-from-bytes",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-605-new-string-from-bytes-expected-stdout",
+        ":art-run-test-605-new-string-from-bytes-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-605-new-string-from-bytes-expected-stdout",
+    out: ["art-run-test-605-new-string-from-bytes-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-605-new-string-from-bytes-expected-stderr",
+    out: ["art-run-test-605-new-string-from-bytes-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/605-new-string-from-bytes/expected.txt b/test/605-new-string-from-bytes/expected-stderr.txt
similarity index 100%
rename from test/605-new-string-from-bytes/expected.txt
rename to test/605-new-string-from-bytes/expected-stderr.txt
diff --git a/test/605-new-string-from-bytes/expected.txt b/test/605-new-string-from-bytes/expected-stdout.txt
similarity index 100%
copy from test/605-new-string-from-bytes/expected.txt
copy to test/605-new-string-from-bytes/expected-stdout.txt
diff --git a/test/606-erroneous-class/expected.txt b/test/606-erroneous-class/expected-stderr.txt
similarity index 100%
rename from test/606-erroneous-class/expected.txt
rename to test/606-erroneous-class/expected-stderr.txt
diff --git a/test/606-erroneous-class/expected.txt b/test/606-erroneous-class/expected-stdout.txt
similarity index 100%
copy from test/606-erroneous-class/expected.txt
copy to test/606-erroneous-class/expected-stdout.txt
diff --git a/test/607-daemon-stress/Android.bp b/test/607-daemon-stress/Android.bp
new file mode 100644
index 0000000..083bd7c
--- /dev/null
+++ b/test/607-daemon-stress/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `607-daemon-stress`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-607-daemon-stress",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-607-daemon-stress-expected-stdout",
+        ":art-run-test-607-daemon-stress-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-607-daemon-stress-expected-stdout",
+    out: ["art-run-test-607-daemon-stress-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-607-daemon-stress-expected-stderr",
+    out: ["art-run-test-607-daemon-stress-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/607-daemon-stress/expected.txt b/test/607-daemon-stress/expected-stderr.txt
similarity index 100%
rename from test/607-daemon-stress/expected.txt
rename to test/607-daemon-stress/expected-stderr.txt
diff --git a/test/607-daemon-stress/expected.txt b/test/607-daemon-stress/expected-stdout.txt
similarity index 100%
copy from test/607-daemon-stress/expected.txt
copy to test/607-daemon-stress/expected-stdout.txt
diff --git a/test/608-checker-unresolved-lse/expected.txt b/test/608-checker-unresolved-lse/expected-stderr.txt
similarity index 100%
rename from test/608-checker-unresolved-lse/expected.txt
rename to test/608-checker-unresolved-lse/expected-stderr.txt
diff --git a/test/608-checker-unresolved-lse/expected.txt b/test/608-checker-unresolved-lse/expected-stdout.txt
similarity index 100%
copy from test/608-checker-unresolved-lse/expected.txt
copy to test/608-checker-unresolved-lse/expected-stdout.txt
diff --git a/test/608-checker-unresolved-lse/src-dex2oat-unresolved/MissingInterface.java b/test/608-checker-unresolved-lse/src-dex2oat-unresolved/MissingInterface.java
new file mode 100644
index 0000000..307f7be
--- /dev/null
+++ b/test/608-checker-unresolved-lse/src-dex2oat-unresolved/MissingInterface.java
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+public interface MissingInterface {
+}
diff --git a/test/608-checker-unresolved-lse/src-dex2oat-unresolved/MissingSuperClass.java b/test/608-checker-unresolved-lse/src-dex2oat-unresolved/MissingSuperClass.java
deleted file mode 100644
index b11b9be..0000000
--- a/test/608-checker-unresolved-lse/src-dex2oat-unresolved/MissingSuperClass.java
+++ /dev/null
@@ -1,18 +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.
- */
-
-public class MissingSuperClass {
-}
diff --git a/test/608-checker-unresolved-lse/src/Main.java b/test/608-checker-unresolved-lse/src/Main.java
index a39dd51..2e4910f 100644
--- a/test/608-checker-unresolved-lse/src/Main.java
+++ b/test/608-checker-unresolved-lse/src/Main.java
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-// We make Main extend an unresolved super class. This will lead to an
-// unresolved access to Foo.field, as we won't know if Main can access
-// a package private field.
-public class Main extends MissingSuperClass {
+public class Main {
 
   public static void main(String[] args) {
     instanceFieldTest();
@@ -25,10 +22,7 @@
     instanceFieldTest2();
   }
 
-  /// CHECK-START: void Main.instanceFieldTest() inliner (before)
-  /// CHECK-NOT:    InstanceFieldSet
-
-  /// CHECK-START: void Main.instanceFieldTest() inliner (after)
+  /// CHECK-START: void Main.instanceFieldTest() load_store_elimination (before)
   /// CHECK:        InstanceFieldSet
   /// CHECK:        UnresolvedInstanceFieldGet
 
@@ -42,17 +36,15 @@
   /// CHECK:        InstanceFieldSet
   /// CHECK:        UnresolvedInstanceFieldGet
   public static void instanceFieldTest() {
-    Foo f = new Foo();
-    if (f.iField != 42) {
+    SubFoo sf = new SubFoo();
+    Foo f = sf;
+    f.iField = 42;
+    if (sf.iField != 42) {
       throw new Error("Expected 42, got " + f.iField);
     }
   }
 
-  /// CHECK-START: void Main.instanceFieldTest2() inliner (before)
-  /// CHECK-NOT:    InstanceFieldSet
-  /// CHECK-NOT:    InstanceFieldGet
-
-  /// CHECK-START: void Main.instanceFieldTest2() inliner (after)
+  /// CHECK-START: void Main.instanceFieldTest2() load_store_elimination (before)
   /// CHECK:        InstanceFieldSet
   /// CHECK:        InstanceFieldGet
   /// CHECK:        UnresolvedInstanceFieldSet
@@ -69,19 +61,18 @@
   /// CHECK:        UnresolvedInstanceFieldSet
   /// CHECK:        InstanceFieldGet
   public static void instanceFieldTest2() {
-    Foo f = new Foo();
-    int a = f.$inline$GetInstanceField();
-    f.iField = 43;
-    a = f.$inline$GetInstanceField();
+    SubFoo sf = new SubFoo();
+    Foo f = sf;
+    f.iField = 42;
+    int a = f.iField;
+    sf.iField = 43;
+    a = f.iField;
     if (a != 43) {
       throw new Error("Expected 43, got " + a);
     }
   }
 
-  /// CHECK-START: void Main.staticFieldTest() inliner (before)
-  /// CHECK-NOT:    StaticFieldSet
-
-  /// CHECK-START: void Main.staticFieldTest() inliner (after)
+  /// CHECK-START: void Main.staticFieldTest() load_store_elimination (before)
   /// CHECK:        StaticFieldSet
   /// CHECK:        StaticFieldSet
   /// CHECK:        UnresolvedStaticFieldGet
@@ -90,37 +81,21 @@
   /// CHECK:        StaticFieldSet
   /// CHECK:        UnresolvedStaticFieldGet
   public static void staticFieldTest() {
-    // Ensure Foo is initialized.
-    Foo f = new Foo();
-    f.$inline$StaticSet42();
-    f.$inline$StaticSet43();
-    if (Foo.sField != 43) {
-      throw new Error("Expected 43, got " + Foo.sField);
+    Foo.sField = 42;
+    Foo.sField = 43;
+    if (SubFoo.sField != 43) {
+      throw new Error("Expected 43, got " + SubFoo.sField);
     }
   }
 }
 
 class Foo {
-  // field needs to be package-private to make the access in Main.main
-  // unresolved.
-  int iField;
-  static int sField;
+  public int iField;
+  public static int sField;
+}
 
-  public void $inline$StaticSet42() {
-    sField = 42;
-  }
-
-  public void $inline$StaticSet43() {
-    sField = 43;
-  }
-
-  public int $inline$GetInstanceField() {
-    return iField;
-  }
-
-  // Constructor needs to be public to get it resolved in Main.main
-  // and therefore inlined.
-  public Foo() {
-    iField = 42;
-  }
+// We make SubFoo implement an unresolved interface, so the SubFoo
+// shall be unresolved and all field accesses through SubFoo shall
+// yield unresolved field access HIR.
+class SubFoo extends Foo implements MissingInterface {
 }
diff --git a/test/609-checker-inline-interface/Android.bp b/test/609-checker-inline-interface/Android.bp
new file mode 100644
index 0000000..33c2cac
--- /dev/null
+++ b/test/609-checker-inline-interface/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `609-checker-inline-interface`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-609-checker-inline-interface",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-609-checker-inline-interface-expected-stdout",
+        ":art-run-test-609-checker-inline-interface-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-609-checker-inline-interface-expected-stdout",
+    out: ["art-run-test-609-checker-inline-interface-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-609-checker-inline-interface-expected-stderr",
+    out: ["art-run-test-609-checker-inline-interface-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/609-checker-inline-interface/expected.txt b/test/609-checker-inline-interface/expected-stderr.txt
similarity index 100%
rename from test/609-checker-inline-interface/expected.txt
rename to test/609-checker-inline-interface/expected-stderr.txt
diff --git a/test/609-checker-inline-interface/expected.txt b/test/609-checker-inline-interface/expected-stdout.txt
similarity index 100%
copy from test/609-checker-inline-interface/expected.txt
copy to test/609-checker-inline-interface/expected-stdout.txt
diff --git a/test/609-checker-inline-interface/src/Main.java b/test/609-checker-inline-interface/src/Main.java
index 249b778..07709ea 100644
--- a/test/609-checker-inline-interface/src/Main.java
+++ b/test/609-checker-inline-interface/src/Main.java
@@ -32,7 +32,7 @@
       // Expected
     }
     try {
-      testInterfaceToVirtualCall();
+      testInterfaceToDirectCall();
     } catch (Error e) {
       // Expected.
     }
@@ -53,19 +53,19 @@
     methodWithInvokeInterface(itf);
   }
 
-  /// CHECK-START: void Main.testInterfaceToVirtualCall() inliner (before)
+  /// CHECK-START: void Main.testInterfaceToDirectCall() inliner (before)
   /// CHECK:                          InvokeStaticOrDirect method_name:Main.methodWithInvokeInterface
 
-  /// CHECK-START: void Main.testInterfaceToVirtualCall() inliner (before)
+  /// CHECK-START: void Main.testInterfaceToDirectCall() inliner (before)
   /// CHECK-NOT:                      InvokeInterface
 
-  /// CHECK-START: void Main.testInterfaceToVirtualCall() inliner (after)
-  /// CHECK:                          InvokeVirtual method_name:Main.doCall
+  /// CHECK-START: void Main.testInterfaceToDirectCall() inliner (after)
+  /// CHECK:                          InvokeStaticOrDirect method_name:Main.doCall
 
-  /// CHECK-START: void Main.testInterfaceToVirtualCall() inliner (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: void Main.testInterfaceToDirectCall() inliner (after)
+  /// CHECK-NOT:                      InvokeVirtual
   /// CHECK-NOT:                      InvokeInterface
-  public static void testInterfaceToVirtualCall() {
+  public static void testInterfaceToDirectCall() {
     methodWithInvokeInterface(m);
   }
 
diff --git a/test/609-checker-x86-bounds-check/Android.bp b/test/609-checker-x86-bounds-check/Android.bp
new file mode 100644
index 0000000..81591bc
--- /dev/null
+++ b/test/609-checker-x86-bounds-check/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `609-checker-x86-bounds-check`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-609-checker-x86-bounds-check",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-609-checker-x86-bounds-check-expected-stdout",
+        ":art-run-test-609-checker-x86-bounds-check-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-609-checker-x86-bounds-check-expected-stdout",
+    out: ["art-run-test-609-checker-x86-bounds-check-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-609-checker-x86-bounds-check-expected-stderr",
+    out: ["art-run-test-609-checker-x86-bounds-check-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/609-checker-inline-interface/expected.txt b/test/609-checker-x86-bounds-check/expected-stderr.txt
similarity index 100%
copy from test/609-checker-inline-interface/expected.txt
copy to test/609-checker-x86-bounds-check/expected-stderr.txt
diff --git a/test/609-checker-x86-bounds-check/expected.txt b/test/609-checker-x86-bounds-check/expected-stdout.txt
similarity index 100%
rename from test/609-checker-x86-bounds-check/expected.txt
rename to test/609-checker-x86-bounds-check/expected-stdout.txt
diff --git a/test/610-arraycopy/Android.bp b/test/610-arraycopy/Android.bp
new file mode 100644
index 0000000..c049136
--- /dev/null
+++ b/test/610-arraycopy/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `610-arraycopy`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-610-arraycopy",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-610-arraycopy-expected-stdout",
+        ":art-run-test-610-arraycopy-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-610-arraycopy-expected-stdout",
+    out: ["art-run-test-610-arraycopy-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-610-arraycopy-expected-stderr",
+    out: ["art-run-test-610-arraycopy-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/610-arraycopy/expected.txt b/test/610-arraycopy/expected-stderr.txt
similarity index 100%
rename from test/610-arraycopy/expected.txt
rename to test/610-arraycopy/expected-stderr.txt
diff --git a/test/610-arraycopy/expected.txt b/test/610-arraycopy/expected-stdout.txt
similarity index 100%
copy from test/610-arraycopy/expected.txt
copy to test/610-arraycopy/expected-stdout.txt
diff --git a/test/611-checker-simplify-if/Android.bp b/test/611-checker-simplify-if/Android.bp
new file mode 100644
index 0000000..7637af3
--- /dev/null
+++ b/test/611-checker-simplify-if/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `611-checker-simplify-if`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-611-checker-simplify-if",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-611-checker-simplify-if-expected-stdout",
+        ":art-run-test-611-checker-simplify-if-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-611-checker-simplify-if-expected-stdout",
+    out: ["art-run-test-611-checker-simplify-if-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-611-checker-simplify-if-expected-stderr",
+    out: ["art-run-test-611-checker-simplify-if-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/603-checker-instanceof/expected.txt b/test/611-checker-simplify-if/expected-stderr.txt
similarity index 100%
copy from test/603-checker-instanceof/expected.txt
copy to test/611-checker-simplify-if/expected-stderr.txt
diff --git a/test/611-checker-simplify-if/expected.txt b/test/611-checker-simplify-if/expected-stdout.txt
similarity index 100%
rename from test/611-checker-simplify-if/expected.txt
rename to test/611-checker-simplify-if/expected-stdout.txt
diff --git a/test/610-arraycopy/expected.txt b/test/612-jit-dex-cache/expected-stderr.txt
similarity index 100%
copy from test/610-arraycopy/expected.txt
copy to test/612-jit-dex-cache/expected-stderr.txt
diff --git a/test/612-jit-dex-cache/expected.txt b/test/612-jit-dex-cache/expected-stdout.txt
similarity index 100%
rename from test/612-jit-dex-cache/expected.txt
rename to test/612-jit-dex-cache/expected-stdout.txt
diff --git a/test/610-arraycopy/expected.txt b/test/613-inlining-dex-cache/expected-stderr.txt
similarity index 100%
copy from test/610-arraycopy/expected.txt
copy to test/613-inlining-dex-cache/expected-stderr.txt
diff --git a/test/613-inlining-dex-cache/expected.txt b/test/613-inlining-dex-cache/expected-stdout.txt
similarity index 100%
rename from test/613-inlining-dex-cache/expected.txt
rename to test/613-inlining-dex-cache/expected-stdout.txt
diff --git a/test/614-checker-dump-constant-location/Android.bp b/test/614-checker-dump-constant-location/Android.bp
new file mode 100644
index 0000000..566bdae
--- /dev/null
+++ b/test/614-checker-dump-constant-location/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `614-checker-dump-constant-location`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-614-checker-dump-constant-location",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-614-checker-dump-constant-location-expected-stdout",
+        ":art-run-test-614-checker-dump-constant-location-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-614-checker-dump-constant-location-expected-stdout",
+    out: ["art-run-test-614-checker-dump-constant-location-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-614-checker-dump-constant-location-expected-stderr",
+    out: ["art-run-test-614-checker-dump-constant-location-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/614-checker-dump-constant-location/expected.txt b/test/614-checker-dump-constant-location/expected-stderr.txt
similarity index 100%
rename from test/614-checker-dump-constant-location/expected.txt
rename to test/614-checker-dump-constant-location/expected-stderr.txt
diff --git a/test/614-checker-dump-constant-location/expected.txt b/test/614-checker-dump-constant-location/expected-stdout.txt
similarity index 100%
copy from test/614-checker-dump-constant-location/expected.txt
copy to test/614-checker-dump-constant-location/expected-stdout.txt
diff --git a/test/615-checker-arm64-store-zero/Android.bp b/test/615-checker-arm64-store-zero/Android.bp
new file mode 100644
index 0000000..bd5acd9
--- /dev/null
+++ b/test/615-checker-arm64-store-zero/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `615-checker-arm64-store-zero`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-615-checker-arm64-store-zero",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-615-checker-arm64-store-zero-expected-stdout",
+        ":art-run-test-615-checker-arm64-store-zero-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-615-checker-arm64-store-zero-expected-stdout",
+    out: ["art-run-test-615-checker-arm64-store-zero-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-615-checker-arm64-store-zero-expected-stderr",
+    out: ["art-run-test-615-checker-arm64-store-zero-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/615-checker-arm64-store-zero/expected.txt b/test/615-checker-arm64-store-zero/expected-stderr.txt
similarity index 100%
rename from test/615-checker-arm64-store-zero/expected.txt
rename to test/615-checker-arm64-store-zero/expected-stderr.txt
diff --git a/test/615-checker-arm64-store-zero/expected.txt b/test/615-checker-arm64-store-zero/expected-stdout.txt
similarity index 100%
copy from test/615-checker-arm64-store-zero/expected.txt
copy to test/615-checker-arm64-store-zero/expected-stdout.txt
diff --git a/test/616-cha-abstract/Android.bp b/test/616-cha-abstract/Android.bp
new file mode 100644
index 0000000..e681343
--- /dev/null
+++ b/test/616-cha-abstract/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `616-cha-abstract`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-616-cha-abstract",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-616-cha-abstract-expected-stdout",
+        ":art-run-test-616-cha-abstract-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-616-cha-abstract-expected-stdout",
+    out: ["art-run-test-616-cha-abstract-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-616-cha-abstract-expected-stderr",
+    out: ["art-run-test-616-cha-abstract-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/434-invoke-direct/expected.txt b/test/616-cha-abstract/expected-stderr.txt
similarity index 100%
copy from test/434-invoke-direct/expected.txt
copy to test/616-cha-abstract/expected-stderr.txt
diff --git a/test/616-cha-abstract/expected.txt b/test/616-cha-abstract/expected-stdout.txt
similarity index 100%
rename from test/616-cha-abstract/expected.txt
rename to test/616-cha-abstract/expected-stdout.txt
diff --git a/test/616-cha-abstract/src/Main.java b/test/616-cha-abstract/src/Main.java
index b33f575..c8093e6 100644
--- a/test/616-cha-abstract/src/Main.java
+++ b/test/616-cha-abstract/src/Main.java
@@ -55,7 +55,7 @@
 
   // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
   // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
-  // After Dummy.createMain2() which links in Main2, live testOverride() on stack
+  // After Helper.createMain2() which links in Main2, live testOverride() on stack
   // should be deoptimized.
   static void testOverride(boolean createMain2, boolean wait, boolean setHasJIT) {
     if (setHasJIT) {
@@ -76,7 +76,7 @@
       while (!sOtherThreadStarted);
       // Create an Main2 instance and assign it to sMain2.
       // sMain1 is kept the same.
-      sMain2 = Dummy.createMain2();
+      sMain2 = Helper.createMain2();
       // Wake up the other thread.
       synchronized(Main.class) {
         Main.class.notify();
@@ -94,7 +94,7 @@
     }
 
     // There should be a deoptimization here right after Main2 is linked by
-    // calling Dummy.createMain2(), even though sMain1 didn't change.
+    // calling Helper.createMain2(), even though sMain1 didn't change.
     // The behavior here would be different if inline-cache is used, which
     // doesn't deoptimize since sMain1 still hits the type cache.
     sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
@@ -152,7 +152,7 @@
 }
 
 // Put createMain2() in another class to avoid class loading due to verifier.
-class Dummy {
+class Helper {
   static Main1 createMain2() {
     return new Main2();
   }
diff --git a/test/516-dead-move-result/expected.txt b/test/616-cha-interface-default/expected-stderr.txt
similarity index 100%
copy from test/516-dead-move-result/expected.txt
copy to test/616-cha-interface-default/expected-stderr.txt
diff --git a/test/616-cha-interface-default/expected.txt b/test/616-cha-interface-default/expected-stdout.txt
similarity index 100%
rename from test/616-cha-interface-default/expected.txt
rename to test/616-cha-interface-default/expected-stdout.txt
diff --git a/test/616-cha-interface-default/src/Main.java b/test/616-cha-interface-default/src/Main.java
index 951607d..ce02cf0 100644
--- a/test/616-cha-interface-default/src/Main.java
+++ b/test/616-cha-interface-default/src/Main.java
@@ -55,7 +55,7 @@
 
   // sMain1.foo()/sMain2.foo() will be always be Base.foo() before Main3 is loaded/linked.
   // So sMain1.foo() can be devirtualized to Base.foo() and be inlined.
-  // After Dummy.createMain3() which links in Main3, live testImplement() on stack
+  // After Helper.createMain3() which links in Main3, live testImplement() on stack
   // should be deoptimized.
   static void testImplement(boolean createMain3, boolean wait, boolean setHasJIT) {
     if (setHasJIT) {
@@ -84,7 +84,7 @@
       while (!sOtherThreadStarted);
       // Create an Main2 instance and assign it to sMain2.
       // sMain1 is kept the same.
-      sMain3 = Dummy.createMain3();
+      sMain3 = Helper.createMain3();
       // Wake up the other thread.
       synchronized(Main.class) {
         Main.class.notify();
@@ -102,7 +102,7 @@
     }
 
     // There should be a deoptimization here right after Main3 is linked by
-    // calling Dummy.createMain3(), even though sMain1 didn't change.
+    // calling Helper.createMain3(), even though sMain1 didn't change.
     // The behavior here would be different if inline-cache is used, which
     // doesn't deoptimize since sMain1 still hits the type cache.
     if (sMain1.foo(getValue(sMain1.getClass())) != 11) {
@@ -169,7 +169,7 @@
 }
 
 // Put createMain3() in another class to avoid class loading due to verifier.
-class Dummy {
+class Helper {
   static Base createMain3() {
     return new Main3();
   }
diff --git a/test/616-cha-interface/Android.bp b/test/616-cha-interface/Android.bp
new file mode 100644
index 0000000..9cdb494
--- /dev/null
+++ b/test/616-cha-interface/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `616-cha-interface`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-616-cha-interface",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-616-cha-interface-expected-stdout",
+        ":art-run-test-616-cha-interface-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-616-cha-interface-expected-stdout",
+    out: ["art-run-test-616-cha-interface-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-616-cha-interface-expected-stderr",
+    out: ["art-run-test-616-cha-interface-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/423-invoke-interface/expected.txt b/test/616-cha-interface/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/616-cha-interface/expected-stderr.txt
diff --git a/test/616-cha-interface/expected.txt b/test/616-cha-interface/expected-stdout.txt
similarity index 100%
rename from test/616-cha-interface/expected.txt
rename to test/616-cha-interface/expected-stdout.txt
diff --git a/test/616-cha-interface/src/Main.java b/test/616-cha-interface/src/Main.java
index 3c93496..c55ed6e 100644
--- a/test/616-cha-interface/src/Main.java
+++ b/test/616-cha-interface/src/Main.java
@@ -68,7 +68,7 @@
 
   // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
   // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
-  // After Dummy.createMain2() which links in Main2, live testImplement() on stack
+  // After Helper.createMain2() which links in Main2, live testImplement() on stack
   // should be deoptimized.
   static void testImplement(boolean createMain2, boolean wait, boolean setHasJIT) {
     if (setHasJIT) {
@@ -90,7 +90,7 @@
       while (!sOtherThreadStarted);
       // Create an Main2 instance and assign it to sMain2.
       // sMain1 is kept the same.
-      sMain2 = Dummy.createMain2();
+      sMain2 = Helper.createMain2();
       // Wake up the other thread.
       synchronized(Main.class) {
         Main.class.notify();
@@ -108,7 +108,7 @@
     }
 
     // There should be a deoptimization here right after Main2 is linked by
-    // calling Dummy.createMain2(), even though sMain1 didn't change.
+    // calling Helper.createMain2(), even though sMain1 didn't change.
     // The behavior here would be different if inline-cache is used, which
     // doesn't deoptimize since sMain1 still hits the type cache.
     sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
@@ -166,7 +166,7 @@
 }
 
 // Put createMain2() in another class to avoid class loading due to verifier.
-class Dummy {
+class Helper {
   static Main1 createMain2() {
     return new Main2();
   }
diff --git a/test/616-cha-miranda/Android.bp b/test/616-cha-miranda/Android.bp
new file mode 100644
index 0000000..1acad4e
--- /dev/null
+++ b/test/616-cha-miranda/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `616-cha-miranda`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-616-cha-miranda",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-616-cha-miranda-expected-stdout",
+        ":art-run-test-616-cha-miranda-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-616-cha-miranda-expected-stdout",
+    out: ["art-run-test-616-cha-miranda-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-616-cha-miranda-expected-stderr",
+    out: ["art-run-test-616-cha-miranda-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/610-arraycopy/expected.txt b/test/616-cha-miranda/expected-stderr.txt
similarity index 100%
copy from test/610-arraycopy/expected.txt
copy to test/616-cha-miranda/expected-stderr.txt
diff --git a/test/616-cha-miranda/expected.txt b/test/616-cha-miranda/expected-stdout.txt
similarity index 100%
rename from test/616-cha-miranda/expected.txt
rename to test/616-cha-miranda/expected-stdout.txt
diff --git a/test/616-cha-miranda/src/Main.java b/test/616-cha-miranda/src/Main.java
index e548482..323e92e 100644
--- a/test/616-cha-miranda/src/Main.java
+++ b/test/616-cha-miranda/src/Main.java
@@ -59,7 +59,7 @@
 
   // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
   // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
-  // After Dummy.createMain2() which links in Main2, live testOverride() on stack
+  // After Helper.createMain2() which links in Main2, live testOverride() on stack
   // should be deoptimized.
   static void testOverride(boolean createMain2, boolean wait, boolean setHasJIT) {
     if (setHasJIT) {
@@ -80,7 +80,7 @@
       while (!sOtherThreadStarted);
       // Create an Main2 instance and assign it to sMain2.
       // sMain1 is kept the same.
-      sMain2 = Dummy.createMain2();
+      sMain2 = Helper.createMain2();
       // Wake up the other thread.
       synchronized(Main.class) {
         Main.class.notify();
@@ -98,7 +98,7 @@
     }
 
     // There should be a deoptimization here right after Main2 is linked by
-    // calling Dummy.createMain2(), even though sMain1 didn't change.
+    // calling Helper.createMain2(), even though sMain1 didn't change.
     // The behavior here would be different if inline-cache is used, which
     // doesn't deoptimize since sMain1 still hits the type cache.
     sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
@@ -156,7 +156,7 @@
 }
 
 // Put createMain2() in another class to avoid class loading due to verifier.
-class Dummy {
+class Helper {
   static Main1 createMain2() {
     return new Main2();
   }
diff --git a/test/616-cha-native/Android.bp b/test/616-cha-native/Android.bp
new file mode 100644
index 0000000..af46ac7
--- /dev/null
+++ b/test/616-cha-native/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `616-cha-native`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-616-cha-native",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-616-cha-native-expected-stdout",
+        ":art-run-test-616-cha-native-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-616-cha-native-expected-stdout",
+    out: ["art-run-test-616-cha-native-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-616-cha-native-expected-stderr",
+    out: ["art-run-test-616-cha-native-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/610-arraycopy/expected.txt b/test/616-cha-native/expected-stderr.txt
similarity index 100%
copy from test/610-arraycopy/expected.txt
copy to test/616-cha-native/expected-stderr.txt
diff --git a/test/616-cha-native/expected.txt b/test/616-cha-native/expected-stdout.txt
similarity index 100%
rename from test/616-cha-native/expected.txt
rename to test/616-cha-native/expected-stdout.txt
diff --git a/test/637-checker-throw-inline/expected.txt b/test/616-cha-proxy-method-inline/expected-stderr.txt
similarity index 100%
copy from test/637-checker-throw-inline/expected.txt
copy to test/616-cha-proxy-method-inline/expected-stderr.txt
diff --git a/test/616-cha-proxy-method-inline/expected.txt b/test/616-cha-proxy-method-inline/expected-stdout.txt
similarity index 100%
rename from test/616-cha-proxy-method-inline/expected.txt
rename to test/616-cha-proxy-method-inline/expected-stdout.txt
diff --git a/test/616-cha-regression-proxy-method/Android.bp b/test/616-cha-regression-proxy-method/Android.bp
new file mode 100644
index 0000000..035abb1
--- /dev/null
+++ b/test/616-cha-regression-proxy-method/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `616-cha-regression-proxy-method`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-616-cha-regression-proxy-method",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-616-cha-regression-proxy-method-expected-stdout",
+        ":art-run-test-616-cha-regression-proxy-method-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-616-cha-regression-proxy-method-expected-stdout",
+    out: ["art-run-test-616-cha-regression-proxy-method-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-616-cha-regression-proxy-method-expected-stderr",
+    out: ["art-run-test-616-cha-regression-proxy-method-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/619-checker-current-method/expected.txt b/test/616-cha-regression-proxy-method/expected-stderr.txt
similarity index 100%
copy from test/619-checker-current-method/expected.txt
copy to test/616-cha-regression-proxy-method/expected-stderr.txt
diff --git a/test/616-cha-regression-proxy-method/expected.txt b/test/616-cha-regression-proxy-method/expected-stdout.txt
similarity index 100%
rename from test/616-cha-regression-proxy-method/expected.txt
rename to test/616-cha-regression-proxy-method/expected-stdout.txt
diff --git a/test/616-cha-regression-proxy-method/src/Main.java b/test/616-cha-regression-proxy-method/src/Main.java
index 19c92be..176f80b 100644
--- a/test/616-cha-regression-proxy-method/src/Main.java
+++ b/test/616-cha-regression-proxy-method/src/Main.java
@@ -70,7 +70,7 @@
 
   // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
   // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
-  // After Dummy.createMain2() which links in Main2, live testOverride() on stack
+  // After Helper.createMain2() which links in Main2, live testOverride() on stack
   // should be deoptimized.
   static void testOverride() {
     sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
@@ -79,14 +79,14 @@
     while (!sOtherThreadStarted);
     // Create an Main2 instance and assign it to sMain2.
     // sMain1 is kept the same.
-    sMain2 = Dummy.createMain2();
+    sMain2 = Helper.createMain2();
     // Wake up the other thread.
     synchronized(Main.class) {
       Main.class.notify();
     }
 
     // There should be a deoptimization here right after Main2 is linked by
-    // calling Dummy.createMain2(), even though sMain1 didn't change.
+    // calling Helper.createMain2(), even though sMain1 didn't change.
     // The behavior here would be different if inline-cache is used, which
     // doesn't deoptimize since sMain1 still hits the type cache.
     sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
@@ -124,7 +124,7 @@
 }
 
 // Put createMain2() in another class to avoid class loading due to verifier.
-class Dummy {
+class Helper {
   static Main1 createMain2() {
     return new Main2();
   }
diff --git a/test/304-method-tracing/expected.txt b/test/616-cha-unloading/expected-stderr.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/616-cha-unloading/expected-stderr.txt
diff --git a/test/616-cha-unloading/expected.txt b/test/616-cha-unloading/expected-stdout.txt
similarity index 100%
rename from test/616-cha-unloading/expected.txt
rename to test/616-cha-unloading/expected-stdout.txt
diff --git a/test/616-cha/Android.bp b/test/616-cha/Android.bp
new file mode 100644
index 0000000..e6cc2da
--- /dev/null
+++ b/test/616-cha/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `616-cha`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-616-cha",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-616-cha-expected-stdout",
+        ":art-run-test-616-cha-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-616-cha-expected-stdout",
+    out: ["art-run-test-616-cha-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-616-cha-expected-stderr",
+    out: ["art-run-test-616-cha-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/668-aiobe/expected.txt b/test/616-cha/expected-stderr.txt
similarity index 100%
copy from test/668-aiobe/expected.txt
copy to test/616-cha/expected-stderr.txt
diff --git a/test/616-cha/expected.txt b/test/616-cha/expected-stdout.txt
similarity index 100%
rename from test/616-cha/expected.txt
rename to test/616-cha/expected-stdout.txt
diff --git a/test/616-cha/src/Main.java b/test/616-cha/src/Main.java
index 27da7cc..39f47fa 100644
--- a/test/616-cha/src/Main.java
+++ b/test/616-cha/src/Main.java
@@ -77,7 +77,7 @@
 
   // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
   // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
-  // After Dummy.createMain2() which links in Main2, live testOverride() on stack
+  // After Helper.createMain2() which links in Main2, live testOverride() on stack
   // should be deoptimized.
   static void testOverride(boolean createMain2, boolean wait, boolean setHasJIT) {
     if (setHasJIT) {
@@ -98,7 +98,7 @@
       while (!sOtherThreadStarted);
       // Create an Main2 instance and assign it to sMain2.
       // sMain1 is kept the same.
-      sMain2 = Dummy.createMain2();
+      sMain2 = Helper.createMain2();
       // Wake up the other thread.
       synchronized(Main.class) {
         Main.class.notify();
@@ -116,7 +116,7 @@
     }
 
     // There should be a deoptimization here right after Main2 is linked by
-    // calling Dummy.createMain2(), even though sMain1 didn't change.
+    // calling Helper.createMain2(), even though sMain1 didn't change.
     // The behavior here would be different if inline-cache is used, which
     // doesn't deoptimize since sMain1 still hits the type cache.
     sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
@@ -154,8 +154,8 @@
   static void testNoOverride() {
     sArray = new Main1[3];
     sArray[0] = new Main1();
-    sArray[1] = Dummy.createMain2();
-    sArray[2] = Dummy.createMain3();
+    sArray[1] = Helper.createMain2();
+    sArray[2] = Helper.createMain3();
     long sum = 0;
     // Loop enough to get methods JITed.
     for (int i=0; i<100; i++) {
@@ -243,7 +243,7 @@
 }
 
 // Put createMain2() in another class to avoid class loading due to verifier.
-class Dummy {
+class Helper {
   static Main1 createMain2() {
     return new Main2();
   }
diff --git a/test/617-clinit-oome/Android.bp b/test/617-clinit-oome/Android.bp
new file mode 100644
index 0000000..a58c888
--- /dev/null
+++ b/test/617-clinit-oome/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `617-clinit-oome`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-617-clinit-oome",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-617-clinit-oome-expected-stdout",
+        ":art-run-test-617-clinit-oome-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-617-clinit-oome-expected-stdout",
+    out: ["art-run-test-617-clinit-oome-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-617-clinit-oome-expected-stderr",
+    out: ["art-run-test-617-clinit-oome-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/202-thread-oome/expected.txt b/test/617-clinit-oome/expected-stderr.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/617-clinit-oome/expected-stderr.txt
diff --git a/test/617-clinit-oome/expected.txt b/test/617-clinit-oome/expected-stdout.txt
similarity index 100%
rename from test/617-clinit-oome/expected.txt
rename to test/617-clinit-oome/expected-stdout.txt
diff --git a/test/617-clinit-oome/src/Main.java b/test/617-clinit-oome/src/Main.java
index 94cb7ce..bab344f 100644
--- a/test/617-clinit-oome/src/Main.java
+++ b/test/617-clinit-oome/src/Main.java
@@ -15,24 +15,38 @@
  */
 
 public class Main {
+  private static int exhaustJavaHeap(Object[] data, int index, int size) {
+    Runtime.getRuntime().gc();
+    while (size > 0) {
+        try {
+            data[index] = new byte[size];
+            index++;
+        } catch (OutOfMemoryError e) {
+            size /= 2;
+        }
+    }
+    return index;
+  }
+
   public static void main(String[] args) {
     Class klass = Other.class;
     Object[] data = new Object[100000];
     try {
         System.out.println("Filling heap");
-        int size = 256 * 1024 * 1024;
+
+        // Make sure that there is no reclaimable memory in the heap. Otherwise we may throw
+        // OOME to prevent GC thrashing, even if later allocations may succeed.
+        Runtime.getRuntime().gc();
+        System.runFinalization();
+        // NOTE: There is a GC invocation in the exhaustJavaHeap(). So we don't need one here.
+
         int index = 0;
-        while (true) {
-            try {
-                data[index] = new byte[size];
-                index++;
-            } catch (OutOfMemoryError e) {
-                size /= 2;
-                if (size == 0) {
-                    break;
-                }
-            }
-        }
+        int initial_size = 256 * 1024 * 1024;
+        // Repeat to ensure there is no space left on the heap.
+        index = exhaustJavaHeap(data, index, initial_size);
+        index = exhaustJavaHeap(data, index, /*size*/ 4);
+        index = exhaustJavaHeap(data, index, /*size*/ 4);
+
         // Initialize now that the heap is full.
         Other.print();
     } catch (OutOfMemoryError e) {
diff --git a/test/618-checker-induction/Android.bp b/test/618-checker-induction/Android.bp
new file mode 100644
index 0000000..6d1a054
--- /dev/null
+++ b/test/618-checker-induction/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `618-checker-induction`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-618-checker-induction",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-618-checker-induction-expected-stdout",
+        ":art-run-test-618-checker-induction-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-618-checker-induction-expected-stdout",
+    out: ["art-run-test-618-checker-induction-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-618-checker-induction-expected-stderr",
+    out: ["art-run-test-618-checker-induction-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/684-select-condition/expected.txt b/test/618-checker-induction/expected-stderr.txt
similarity index 100%
copy from test/684-select-condition/expected.txt
copy to test/618-checker-induction/expected-stderr.txt
diff --git a/test/618-checker-induction/expected.txt b/test/618-checker-induction/expected-stdout.txt
similarity index 100%
rename from test/618-checker-induction/expected.txt
rename to test/618-checker-induction/expected-stdout.txt
diff --git a/test/619-checker-current-method/Android.bp b/test/619-checker-current-method/Android.bp
new file mode 100644
index 0000000..10e2d9a
--- /dev/null
+++ b/test/619-checker-current-method/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `619-checker-current-method`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-619-checker-current-method",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-619-checker-current-method-expected-stdout",
+        ":art-run-test-619-checker-current-method-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-619-checker-current-method-expected-stdout",
+    out: ["art-run-test-619-checker-current-method-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-619-checker-current-method-expected-stderr",
+    out: ["art-run-test-619-checker-current-method-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/619-checker-current-method/expected.txt b/test/619-checker-current-method/expected-stderr.txt
similarity index 100%
rename from test/619-checker-current-method/expected.txt
rename to test/619-checker-current-method/expected-stderr.txt
diff --git a/test/619-checker-current-method/expected.txt b/test/619-checker-current-method/expected-stdout.txt
similarity index 100%
copy from test/619-checker-current-method/expected.txt
copy to test/619-checker-current-method/expected-stdout.txt
diff --git a/test/620-checker-bce-intrinsics/Android.bp b/test/620-checker-bce-intrinsics/Android.bp
new file mode 100644
index 0000000..0014b03
--- /dev/null
+++ b/test/620-checker-bce-intrinsics/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `620-checker-bce-intrinsics`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-620-checker-bce-intrinsics",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-620-checker-bce-intrinsics-expected-stdout",
+        ":art-run-test-620-checker-bce-intrinsics-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-620-checker-bce-intrinsics-expected-stdout",
+    out: ["art-run-test-620-checker-bce-intrinsics-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-620-checker-bce-intrinsics-expected-stderr",
+    out: ["art-run-test-620-checker-bce-intrinsics-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/605-new-string-from-bytes/expected.txt b/test/620-checker-bce-intrinsics/expected-stderr.txt
similarity index 100%
copy from test/605-new-string-from-bytes/expected.txt
copy to test/620-checker-bce-intrinsics/expected-stderr.txt
diff --git a/test/620-checker-bce-intrinsics/expected.txt b/test/620-checker-bce-intrinsics/expected-stdout.txt
similarity index 100%
rename from test/620-checker-bce-intrinsics/expected.txt
rename to test/620-checker-bce-intrinsics/expected-stdout.txt
diff --git a/test/622-checker-bce-regressions/Android.bp b/test/622-checker-bce-regressions/Android.bp
new file mode 100644
index 0000000..b14a5a0
--- /dev/null
+++ b/test/622-checker-bce-regressions/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `622-checker-bce-regressions`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-622-checker-bce-regressions",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-622-checker-bce-regressions-expected-stdout",
+        ":art-run-test-622-checker-bce-regressions-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-622-checker-bce-regressions-expected-stdout",
+    out: ["art-run-test-622-checker-bce-regressions-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-622-checker-bce-regressions-expected-stderr",
+    out: ["art-run-test-622-checker-bce-regressions-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/622-checker-bce-regressions/expected-stderr.txt
similarity index 100%
copy from test/148-multithread-gc-annotations/expected.txt
copy to test/622-checker-bce-regressions/expected-stderr.txt
diff --git a/test/622-checker-bce-regressions/expected.txt b/test/622-checker-bce-regressions/expected-stdout.txt
similarity index 100%
rename from test/622-checker-bce-regressions/expected.txt
rename to test/622-checker-bce-regressions/expected-stdout.txt
diff --git a/test/622-simplifyifs-exception-edges/expected.txt b/test/622-simplifyifs-exception-edges/expected-stderr.txt
similarity index 100%
rename from test/622-simplifyifs-exception-edges/expected.txt
rename to test/622-simplifyifs-exception-edges/expected-stderr.txt
diff --git a/test/622-simplifyifs-exception-edges/expected.txt b/test/622-simplifyifs-exception-edges/expected-stdout.txt
similarity index 100%
copy from test/622-simplifyifs-exception-edges/expected.txt
copy to test/622-simplifyifs-exception-edges/expected-stdout.txt
diff --git a/test/622-simplifyifs-exception-edges/src/Main.java b/test/622-simplifyifs-exception-edges/src/Main.java
index 636f047..80faa4a 100644
--- a/test/622-simplifyifs-exception-edges/src/Main.java
+++ b/test/622-simplifyifs-exception-edges/src/Main.java
@@ -39,5 +39,5 @@
     }
 
     // Workaround for non-zero field ids offset in dex file with no fields. Bug: 18051191
-    static final boolean dummy = false;
+    static final boolean PLACEHOLDER = false;
 }
diff --git a/test/623-checker-loop-regressions/Android.bp b/test/623-checker-loop-regressions/Android.bp
new file mode 100644
index 0000000..95521d6
--- /dev/null
+++ b/test/623-checker-loop-regressions/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `623-checker-loop-regressions`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-623-checker-loop-regressions",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-623-checker-loop-regressions-expected-stdout",
+        ":art-run-test-623-checker-loop-regressions-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-623-checker-loop-regressions-expected-stdout",
+    out: ["art-run-test-623-checker-loop-regressions-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-623-checker-loop-regressions-expected-stderr",
+    out: ["art-run-test-623-checker-loop-regressions-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/623-checker-loop-regressions/expected-stderr.txt
similarity index 100%
copy from test/148-multithread-gc-annotations/expected.txt
copy to test/623-checker-loop-regressions/expected-stderr.txt
diff --git a/test/623-checker-loop-regressions/expected.txt b/test/623-checker-loop-regressions/expected-stdout.txt
similarity index 100%
rename from test/623-checker-loop-regressions/expected.txt
rename to test/623-checker-loop-regressions/expected-stdout.txt
diff --git a/test/623-checker-loop-regressions/src/Main.java b/test/623-checker-loop-regressions/src/Main.java
index 6fa38f8..3f3a12c 100644
--- a/test/623-checker-loop-regressions/src/Main.java
+++ b/test/623-checker-loop-regressions/src/Main.java
@@ -290,8 +290,17 @@
   /// CHECK-NOT: VecLoad
   //
   /// CHECK-START-ARM64: void Main.string2Bytes(char[], java.lang.String) loop_optimization (after)
-  /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      TODO: Support CharAt for SVE.
+  ///     CHECK-NOT: VecLoad
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   //
   // NOTE: should correctly deal with compressed and uncompressed cases.
   private static void string2Bytes(char[] a, String b) {
@@ -305,8 +314,17 @@
   /// CHECK-NOT: VecLoad
 
   /// CHECK-START-ARM64: void Main.$noinline$stringToShorts(short[], java.lang.String) loop_optimization (after)
-  /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      TODO: Support CharAt for SVE.
+  ///     CHECK-NOT: VecLoad
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void $noinline$stringToShorts(short[] dest, String src) {
     int min = Math.min(dest.length, src.length());
     for (int i = 0; i < min; ++i) {
@@ -350,9 +368,20 @@
   //
   /// CHECK-START-ARM64: void Main.oneBoth(short[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                             loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>]              loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>] loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<One>>,{{j\d+}}]               loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile                                        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi>>,<<Repl>>,<<LoopP>>]      loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<One>>]              loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>] loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi>>,<<Repl>>]      loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   //
   // Bug b/37764324: integral same-length packed types can be mixed freely.
   private static void oneBoth(short[] a, char[] b) {
@@ -382,6 +411,7 @@
   //
   /// CHECK-START-ARM: void Main.typeConv(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                         loop:none
+
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>]          loop:none
   /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1:i\d+>>]      loop:<<Loop1:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>]            loop:<<Loop1>>      outer_loop:none
@@ -393,14 +423,26 @@
   //
   /// CHECK-START-ARM64: void Main.typeConv(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                         loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>]          loop:none
-  /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1:i\d+>>]      loop:<<Loop1:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>]            loop:<<Loop1>>      outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>>      outer_loop:none
-  /// CHECK-DAG: <<Get:b\d+>>  ArrayGet [{{l\d+}},<<Phi2:i\d+>>]     loop:<<Loop2:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get>>,<<One>>]                 loop:<<Loop2>>      outer_loop:none
-  /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<Add>>]              loop:<<Loop2>>      outer_loop:none
-  /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>]  loop:<<Loop2>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<One>>,{{j\d+}}]           loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile                                    loop:<<Loop1:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>  VecLoad [{{l\d+}},<<Phi1:i\d+>>,<<LoopP>>]      loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG: <<Vadd:d\d+>>  VecAdd [<<Load>>,<<Repl>>,<<LoopP>>]            loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>,<<LoopP>>] loop:<<Loop1>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<One>>]          loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>  VecLoad [{{l\d+}},<<Phi1:i\d+>>]      loop:<<Loop1:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Vadd:d\d+>>  VecAdd [<<Load>>,<<Repl>>]            loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG: <<Get:b\d+>>   ArrayGet [{{l\d+}},<<Phi2:i\d+>>]     loop:<<Loop2:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Add:i\d+>>   Add [<<Get>>,<<One>>]                 loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: <<Cnv:b\d+>>   TypeConversion [<<Add>>]              loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG:                ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>]  loop:<<Loop2>>      outer_loop:none
+  //
+  /// CHECK-FI:
   //
   // Scalar code in cleanup loop uses correct byte type on array get and type conversion.
   private static void typeConv(byte[] a, byte[] b) {
@@ -577,6 +619,97 @@
            s24 + s25 + s26 + s27 + s28 + s29 + s30 + s31;
   }
 
+  // Ensure spilling saves regular FP values correctly when the graph HasSIMD()
+  // is true.
+  /// CHECK-START-ARM64: float Main.$noinline$ensureSlowPathFPSpillFill(float[], float[], float[], float[], int[]) loop_optimization (after)
+  //
+  //  Both regular and SIMD accesses are present.
+  /// CHECK-DAG: VecLoad
+  /// CHECK-DAG: ArrayGet
+  private static final float $noinline$ensureSlowPathFPSpillFill(float[] a,
+                                                                 float[] b,
+                                                                 float[] c,
+                                                                 float[] d,
+                                                                 int[] e) {
+    // This loop should be vectorized so the graph->HasSIMD() will be true.
+    // A power-of-2 number of iterations is chosen to avoid peeling/unrolling interference.
+    for (int i = 0; i < 64; i++) {
+      // The actual values of the array elements don't matter, just the
+      // presence of a SIMD loop.
+      e[i]++;
+    }
+
+    float f0 = 0;
+    float f1 = 0;
+    float f2 = 0;
+    float f3 = 0;
+    float f4 = 0;
+    float f5 = 0;
+    float f6 = 0;
+    float f7 = 0;
+    float f8 = 0;
+    float f9 = 0;
+    float f10 = 0;
+    float f11 = 0;
+    float f12 = 0;
+    float f13 = 0;
+    float f14 = 0;
+    float f15 = 0;
+    float f16 = 0;
+    float f17 = 0;
+    float f18 = 0;
+    float f19 = 0;
+    float f20 = 0;
+    float f21 = 0;
+    float f22 = 0;
+    float f23 = 0;
+    float f24 = 0;
+    float f25 = 0;
+    float f26 = 0;
+    float f27 = 0;
+    float f28 = 0;
+    float f29 = 0;
+    float f30 = 0;
+    float f31 = 0;
+    for (int i = 0; i < 100; i++) {
+      f0 += a[i];
+      f1 += b[i];
+      f2 += c[i];
+      f3 += d[i];
+      f4 += a[i];
+      f5 += b[i];
+      f6 += c[i];
+      f7 += d[i];
+      f8 += a[i];
+      f9 += b[i];
+      f10 += c[i];
+      f11 += d[i];
+      f12 += a[i];
+      f13 += b[i];
+      f14 += c[i];
+      f15 += d[i];
+      f16 += a[i];
+      f17 += b[i];
+      f18 += c[i];
+      f19 += d[i];
+      f20 += a[i];
+      f21 += b[i];
+      f22 += c[i];
+      f23 += d[i];
+      f24 += a[i];
+      f25 += b[i];
+      f26 += c[i];
+      f27 += d[i];
+      f28 += a[i];
+      f29 += b[i];
+      f30 += c[i];
+      f31 += d[i];
+    }
+    return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13 + f14 + f15 +
+           f16 + f17 + f18 + f19 + f20 + f21 + f22 + f23 +
+           f24 + f25 + f26 + f27 + f28 + f29 + f30 + f31;
+  }
+
   public static int reductionIntoReplication() {
     int[] a = { 1, 2, 3, 4 };
     int x = 0;
@@ -589,6 +722,279 @@
     return a[3];
   }
 
+  // Dot product and SAD vectorization idioms used to have a bug when some
+  // instruction in the loop was visited twice causing a compiler crash.
+  // It happened when two vectorization idioms' matched patterns had a common
+  // sub-expression.
+
+  // Idioms common sub-expression bug: DotProduct and ArraySet.
+  //
+  /// CHECK-START-ARM64: int Main.testDotProdAndSet(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-DAG:       VecDotProd
+  /// CHECK-DAG:       VecStore
+  public static final int testDotProdAndSet(byte[] a, byte[] b, byte[] c) {
+    int s = 1;
+    for (int i = 0; i < b.length; i++) {
+      int temp = a[i] * b[i];
+      c[i]= (byte)temp;
+      s += temp;
+    }
+    return s - 1;
+  }
+
+  // Idioms common sub-expression bug: DotProduct and DotProduct.
+  //
+  /// CHECK-START-ARM64: int Main.testDotProdAndDotProd(byte[], byte[]) loop_optimization (after)
+  /// CHECK-DAG:       VecDotProd
+  /// CHECK-DAG:       VecDotProd
+  public static final int testDotProdAndDotProd(byte[] a, byte[] b) {
+    int s0 = 1;
+    int s1 = 1;
+    for (int i = 0; i < b.length; i++) {
+      int temp = a[i] * b[i];
+      s0 += temp;
+      s1 += temp;
+    }
+    return s0 + s1;
+  }
+
+  // Idioms common sub-expression bug: SAD and ArraySet.
+  //
+  /// CHECK-START-ARM: int Main.testSADAndSet(int[], int[], int[]) loop_optimization (after)
+  /// CHECK-DAG:       VecSADAccumulate
+  /// CHECK-DAG:       VecStore
+  //
+  /// CHECK-START-ARM64: int Main.testSADAndSet(int[], int[], int[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      VecSADAccumulate is not supported for SVE.
+  ///     CHECK-NOT:       VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:       VecSADAccumulate
+  ///     CHECK-DAG:       VecStore
+  //
+  /// CHECK-FI:
+  public static int testSADAndSet(int[] x, int[] y, int[] z) {
+    int min_length = Math.min(x.length, y.length);
+    int sad = 0;
+    for (int i = 0; i < min_length; i++) {
+      int temp = Math.abs(x[i] - y[i]);
+      z[i] = temp;
+      sad += temp;
+    }
+    return sad;
+  }
+
+  // Idioms common sub-expression bug: SAD and SAD.
+  /// CHECK-START-ARM: int Main.testSADAndSAD(int[], int[]) loop_optimization (after)
+  /// CHECK-DAG:       VecSADAccumulate
+  /// CHECK-DAG:       VecSADAccumulate
+  //
+  /// CHECK-START-ARM64: int Main.testSADAndSAD(int[], int[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      VecSADAccumulate is not supported for SVE.
+  ///     CHECK-NOT:       VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:       VecSADAccumulate
+  ///     CHECK-DAG:       VecSADAccumulate
+  //
+  /// CHECK-FI:
+  public static final int testSADAndSAD(int[] x, int[] y) {
+    int s0 = 1;
+    int s1 = 1;
+    for (int i = 0; i < x.length; i++) {
+      int temp = Math.abs(x[i] - y[i]);
+      s0 += temp;
+      s1 += temp;
+    }
+    return s0 + s1;
+  }
+
+  // Idioms common sub-expression bug: DotProd and DotProd with extra mul.
+  //
+  /// CHECK-START-ARM64: int Main.testDotProdAndDotProdExtraMul0(byte[], byte[]) loop_optimization (after)
+  /// CHECK-DAG:       VecMul
+  /// CHECK-DAG:       VecDotProd
+  /// CHECK-DAG:       VecDotProd
+  public static final int testDotProdAndDotProdExtraMul0(byte[] a, byte[] b) {
+    int s0 = 1;
+    int s1 = 1;
+    for (int i = 0; i < b.length; i++) {
+      int temp0 = a[i] * b[i];
+      int temp1 = (byte)(temp0) * a[i];
+      s0 += temp1;
+      s1 += temp0;
+    }
+    return s0 + s1;
+  }
+
+  // Idioms common sub-expression bug: DotProd and DotProd with extra mul (reversed order).
+  //
+  /// CHECK-START-ARM64: int Main.testDotProdAndDotProdExtraMul1(byte[], byte[]) loop_optimization (after)
+  /// CHECK-DAG:       VecMul
+  /// CHECK-DAG:       VecDotProd
+  /// CHECK-DAG:       VecDotProd
+  public static final int testDotProdAndDotProdExtraMul1(byte[] a, byte[] b) {
+    int s0 = 1;
+    int s1 = 1;
+    for (int i = 0; i < b.length; i++) {
+      int temp0 = a[i] * b[i];
+      int temp1 = (byte)(temp0) * a[i];
+      s0 += temp0;
+      s1 += temp1;
+    }
+    return s0 + s1;
+  }
+
+  // Idioms common sub-expression bug: SAD and SAD with extra abs.
+  //
+  /// CHECK-START-ARM: int Main.testSADAndSADExtraAbs0(int[], int[]) loop_optimization (after)
+  /// CHECK-DAG:       VecSub
+  /// CHECK-DAG:       VecAbs
+  /// CHECK-DAG:       VecSADAccumulate
+  /// CHECK-DAG:       VecSADAccumulate
+  //
+  /// CHECK-START-ARM64: int Main.testSADAndSADExtraAbs0(int[], int[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      VecSADAccumulate is not supported for SVE.
+  ///     CHECK-NOT:       VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:       VecSub
+  ///     CHECK-DAG:       VecAbs
+  ///     CHECK-DAG:       VecSADAccumulate
+  ///     CHECK-DAG:       VecSADAccumulate
+  //
+  /// CHECK-FI:
+  public static final int testSADAndSADExtraAbs0(int[] x, int[] y) {
+    int s0 = 1;
+    int s1 = 1;
+    for (int i = 0; i < x.length; i++) {
+      int temp0 = Math.abs(x[i] - y[i]);
+      int temp1 = Math.abs(temp0 - y[i]);
+      s0 += temp1;
+      s1 += temp0;
+    }
+    return s0 + s1;
+  }
+
+  // Idioms common sub-expression bug: SAD and SAD with extra abs (reversed order).
+  //
+  /// CHECK-START-ARM: int Main.testSADAndSADExtraAbs1(int[], int[]) loop_optimization (after)
+  /// CHECK-DAG:       VecSub
+  /// CHECK-DAG:       VecAbs
+  /// CHECK-DAG:       VecSADAccumulate
+  /// CHECK-DAG:       VecSADAccumulate
+  //
+  /// CHECK-START-ARM64: int Main.testSADAndSADExtraAbs1(int[], int[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      VecSADAccumulate is not supported for SVE.
+  ///     CHECK-NOT:       VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:       VecSub
+  ///     CHECK-DAG:       VecAbs
+  ///     CHECK-DAG:       VecSADAccumulate
+  ///     CHECK-DAG:       VecSADAccumulate
+  //
+  /// CHECK-FI:
+  public static final int testSADAndSADExtraAbs1(int[] x, int[] y) {
+    int s0 = 1;
+    int s1 = 1;
+    for (int i = 0; i < x.length; i++) {
+      int temp0 = Math.abs(x[i] - y[i]);
+      int temp1 = Math.abs(temp0 - y[i]);
+      s0 += temp0;
+      s1 += temp1;
+    }
+    return s0 + s1;
+  }
+
+
+  // Idioms common sub-expression bug: SAD and DotProd combined.
+  //
+  /// CHECK-START-ARM64: int Main.testSADAndDotProdCombined0(byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      VecSADAccumulate is not supported for SVE.
+  ///     CHECK-NOT:       VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:       VecSub
+  ///     CHECK-DAG:       VecSADAccumulate
+  ///     CHECK-DAG:       VecDotProd
+  //
+  /// CHECK-FI:
+  public static final int testSADAndDotProdCombined0(byte[] x, byte[] y) {
+    int s0 = 1;
+    int s1 = 1;
+    for (int i = 0; i < x.length; i++) {
+      int temp0 = x[i] - y[i];
+      int temp1 = Math.abs(temp0);
+      int temp2 = x[i] * (byte)(temp0);
+
+      s0 += temp1;
+      s1 += temp2;
+    }
+    return s0 + s1;
+  }
+
+  // Idioms common sub-expression bug: SAD and DotProd combined (reversed order).
+  /// CHECK-START-ARM64: int Main.testSADAndDotProdCombined1(byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      VecSADAccumulate is not supported for SVE.
+  ///     CHECK-NOT:       VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:       VecSub
+  ///     CHECK-DAG:       VecSADAccumulate
+  ///     CHECK-DAG:       VecDotProd
+  //
+  /// CHECK-FI:
+  public static final int testSADAndDotProdCombined1(byte[] x, byte[] y) {
+    int s0 = 1;
+    int s1 = 1;
+    for (int i = 0; i < x.length; i++) {
+      int temp0 = x[i] - y[i];
+      int temp1 = Math.abs(temp0);
+      int temp2 = x[i] * (byte)(temp0);
+
+      s0 += temp2;
+      s1 += temp1;
+    }
+    return s0 + s1;
+  }
+
+  public static final int ARRAY_SIZE = 512;
+
+  private static byte[] createAndInitByteArray(int x) {
+    byte[] a = new byte[ARRAY_SIZE];
+    for (int i = 0; i < a.length; i++) {
+      a[i] = (byte)((~i) + x);
+    }
+    return a;
+  }
+
+  private static int[] createAndInitIntArray(int x) {
+    int[] a = new int[ARRAY_SIZE];
+    for (int i = 0; i < a.length; i++) {
+      a[i] = (~i) + x;
+    }
+    return a;
+  }
+
   public static void main(String[] args) {
     System.loadLibrary(args[0]);
 
@@ -777,9 +1183,77 @@
       }
       expectEquals(85800, reduction32Values(a1, a2, a3, a4));
     }
+    {
+      float[] a1 = new float[100];
+      float[] a2 = new float[100];
+      float[] a3 = new float[100];
+      float[] a4 = new float[100];
+      int[] a5 = new int[100];
+
+      for (int i = 0; i < 100; i++) {
+        a1[i] = (float)i;
+        a2[i] = (float)1;
+        a3[i] = (float)(100 - i);
+        a4[i] = (i % 16);
+      }
+      expectEquals(86608.0f, $noinline$ensureSlowPathFPSpillFill(a1, a2, a3, a4, a5));
+    }
 
     expectEquals(10, reductionIntoReplication());
 
+    {
+        byte[] b_a = createAndInitByteArray(1);
+        byte[] b_b = createAndInitByteArray(2);
+        byte[] b_c = createAndInitByteArray(3);
+        expectEquals(2731008, testDotProdAndSet(b_a, b_b, b_c));
+    }
+    {
+        byte[] b_a = createAndInitByteArray(1);
+        byte[] b_b = createAndInitByteArray(2);
+        expectEquals(5462018, testDotProdAndDotProd(b_a, b_b));
+    }
+    {
+        int[] i_a = createAndInitIntArray(1);
+        int[] i_b = createAndInitIntArray(2);
+        int[] i_c = createAndInitIntArray(3);
+        expectEquals(512, testSADAndSet(i_a, i_b, i_c));
+    }
+    {
+        int[] i_a = createAndInitIntArray(1);
+        int[] i_b = createAndInitIntArray(2);
+        expectEquals(1026, testSADAndSAD(i_a, i_b));
+    }
+    {
+        byte[] b_a = createAndInitByteArray(1);
+        byte[] b_b = createAndInitByteArray(2);
+        expectEquals(2731266, testDotProdAndDotProdExtraMul0(b_a, b_b));
+    }
+    {
+        byte[] b_a = createAndInitByteArray(1);
+        byte[] b_b = createAndInitByteArray(2);
+        expectEquals(2731266, testDotProdAndDotProdExtraMul1(b_a, b_b));
+    }
+    {
+        int[] i_a = createAndInitIntArray(1);
+        int[] i_b = createAndInitIntArray(2);
+        expectEquals(131330, testSADAndSADExtraAbs0(i_a, i_b));
+    }
+    {
+        int[] i_a = createAndInitIntArray(1);
+        int[] i_b = createAndInitIntArray(2);
+        expectEquals(131330, testSADAndSADExtraAbs1(i_a, i_b));
+    }
+    {
+        byte[] b_a = createAndInitByteArray(1);
+        byte[] b_b = createAndInitByteArray(2);
+        expectEquals(1278, testSADAndDotProdCombined0(b_a, b_b));
+    }
+    {
+        byte[] b_a = createAndInitByteArray(1);
+        byte[] b_b = createAndInitByteArray(2);
+        expectEquals(1278, testSADAndDotProdCombined1(b_a, b_b));
+    }
+
     System.out.println("passed");
   }
 
diff --git a/test/2022-Invariantloops/expected.txt b/test/624-checker-stringops/expected-stderr.txt
similarity index 100%
copy from test/2022-Invariantloops/expected.txt
copy to test/624-checker-stringops/expected-stderr.txt
diff --git a/test/624-checker-stringops/expected.txt b/test/624-checker-stringops/expected-stdout.txt
similarity index 100%
rename from test/624-checker-stringops/expected.txt
rename to test/624-checker-stringops/expected-stdout.txt
diff --git a/test/625-checker-licm-regressions/Android.bp b/test/625-checker-licm-regressions/Android.bp
new file mode 100644
index 0000000..95175b0
--- /dev/null
+++ b/test/625-checker-licm-regressions/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `625-checker-licm-regressions`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-625-checker-licm-regressions",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-625-checker-licm-regressions-expected-stdout",
+        ":art-run-test-625-checker-licm-regressions-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-625-checker-licm-regressions-expected-stdout",
+    out: ["art-run-test-625-checker-licm-regressions-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-625-checker-licm-regressions-expected-stderr",
+    out: ["art-run-test-625-checker-licm-regressions-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/625-checker-licm-regressions/expected-stderr.txt
similarity index 100%
copy from test/148-multithread-gc-annotations/expected.txt
copy to test/625-checker-licm-regressions/expected-stderr.txt
diff --git a/test/625-checker-licm-regressions/expected.txt b/test/625-checker-licm-regressions/expected-stdout.txt
similarity index 100%
rename from test/625-checker-licm-regressions/expected.txt
rename to test/625-checker-licm-regressions/expected-stdout.txt
diff --git a/test/419-long-parameter/expected.txt b/test/626-checker-arm64-scratch-register/expected-stderr.txt
similarity index 100%
copy from test/419-long-parameter/expected.txt
copy to test/626-checker-arm64-scratch-register/expected-stderr.txt
diff --git a/test/626-checker-arm64-scratch-register/expected.txt b/test/626-checker-arm64-scratch-register/expected-stdout.txt
similarity index 100%
rename from test/626-checker-arm64-scratch-register/expected.txt
rename to test/626-checker-arm64-scratch-register/expected-stdout.txt
diff --git a/test/2019-constantcalculationsinking/expected.txt b/test/626-const-class-linking/expected-stderr.txt
similarity index 100%
copy from test/2019-constantcalculationsinking/expected.txt
copy to test/626-const-class-linking/expected-stderr.txt
diff --git a/test/626-const-class-linking/expected.txt b/test/626-const-class-linking/expected-stdout.txt
similarity index 100%
rename from test/626-const-class-linking/expected.txt
rename to test/626-const-class-linking/expected-stdout.txt
diff --git a/test/626-const-class-linking/src/Main.java b/test/626-const-class-linking/src/Main.java
index 1bc94a7..1541ab3 100644
--- a/test/626-const-class-linking/src/Main.java
+++ b/test/626-const-class-linking/src/Main.java
@@ -28,7 +28,7 @@
             System.loadLibrary(args[0]);
         } catch (ClassNotFoundException e) {
             usingRI = true;
-            // Add expected JNI_OnLoad log line to match expected.txt.
+            // Add expected JNI_OnLoad log line to match expected-stdout.txt.
             System.out.println("JNI_OnLoad called");
         }
 
@@ -107,7 +107,7 @@
         } catch (InvocationTargetException ite) {
             String message = ite.getCause().getMessage();
             if (usingRI && "Test".equals(message)) {
-              // Replace RI message with dalvik message to match expected.txt.
+              // Replace RI message with dalvik message to match expected-stdout.txt.
               message = "Initiating class loader of type " +
                   misbehaving_loader.getClass().getName() +
                   " returned class Helper2 instead of Test.";
diff --git a/test/626-set-resolved-string/Android.bp b/test/626-set-resolved-string/Android.bp
new file mode 100644
index 0000000..dee4dde
--- /dev/null
+++ b/test/626-set-resolved-string/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `626-set-resolved-string`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-626-set-resolved-string",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-626-set-resolved-string-expected-stdout",
+        ":art-run-test-626-set-resolved-string-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-626-set-resolved-string-expected-stdout",
+    out: ["art-run-test-626-set-resolved-string-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-626-set-resolved-string-expected-stderr",
+    out: ["art-run-test-626-set-resolved-string-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/304-method-tracing/expected.txt b/test/626-set-resolved-string/expected-stderr.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/626-set-resolved-string/expected-stderr.txt
diff --git a/test/626-set-resolved-string/expected.txt b/test/626-set-resolved-string/expected-stdout.txt
similarity index 100%
rename from test/626-set-resolved-string/expected.txt
rename to test/626-set-resolved-string/expected-stdout.txt
diff --git a/test/627-checker-unroll/Android.bp b/test/627-checker-unroll/Android.bp
new file mode 100644
index 0000000..1c2baca
--- /dev/null
+++ b/test/627-checker-unroll/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `627-checker-unroll`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-627-checker-unroll",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-627-checker-unroll-expected-stdout",
+        ":art-run-test-627-checker-unroll-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-627-checker-unroll-expected-stdout",
+    out: ["art-run-test-627-checker-unroll-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-627-checker-unroll-expected-stderr",
+    out: ["art-run-test-627-checker-unroll-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/584-checker-div-bool/expected.txt b/test/627-checker-unroll/expected-stderr.txt
similarity index 100%
copy from test/584-checker-div-bool/expected.txt
copy to test/627-checker-unroll/expected-stderr.txt
diff --git a/test/627-checker-unroll/expected.txt b/test/627-checker-unroll/expected-stdout.txt
similarity index 100%
rename from test/627-checker-unroll/expected.txt
rename to test/627-checker-unroll/expected-stdout.txt
diff --git a/test/628-vdex/Android.bp b/test/628-vdex/Android.bp
new file mode 100644
index 0000000..7b768fc
--- /dev/null
+++ b/test/628-vdex/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `628-vdex`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-628-vdex",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-628-vdex-expected-stdout",
+        ":art-run-test-628-vdex-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-628-vdex-expected-stdout",
+    out: ["art-run-test-628-vdex-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-628-vdex-expected-stderr",
+    out: ["art-run-test-628-vdex-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/668-aiobe/expected.txt b/test/628-vdex/expected-stderr.txt
similarity index 100%
copy from test/668-aiobe/expected.txt
copy to test/628-vdex/expected-stderr.txt
diff --git a/test/628-vdex/expected.txt b/test/628-vdex/expected-stdout.txt
similarity index 100%
rename from test/628-vdex/expected.txt
rename to test/628-vdex/expected-stdout.txt
diff --git a/test/628-vdex/src/Main.java b/test/628-vdex/src/Main.java
index 7ceab2c..0a012f1 100644
--- a/test/628-vdex/src/Main.java
+++ b/test/628-vdex/src/Main.java
@@ -16,7 +16,6 @@
 
 public class Main {
   Main() {
-    // Will be quickened with RETURN_VOID_NO_BARRIER.
   }
 
   public static void main(String[] args) {
diff --git a/test/629-vdex-speed/Android.bp b/test/629-vdex-speed/Android.bp
new file mode 100644
index 0000000..00b00d8
--- /dev/null
+++ b/test/629-vdex-speed/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `629-vdex-speed`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-629-vdex-speed",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-629-vdex-speed-expected-stdout",
+        ":art-run-test-629-vdex-speed-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-629-vdex-speed-expected-stdout",
+    out: ["art-run-test-629-vdex-speed-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-629-vdex-speed-expected-stderr",
+    out: ["art-run-test-629-vdex-speed-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/629-vdex-speed/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/629-vdex-speed/expected-stderr.txt
diff --git a/test/629-vdex-speed/expected.txt b/test/629-vdex-speed/expected-stdout.txt
similarity index 100%
rename from test/629-vdex-speed/expected.txt
rename to test/629-vdex-speed/expected-stdout.txt
diff --git a/test/629-vdex-speed/run b/test/629-vdex-speed/run
index f1b0a95..1477e3d 100644
--- a/test/629-vdex-speed/run
+++ b/test/629-vdex-speed/run
@@ -14,4 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-exec ${RUN} --vdex "${@}"
+exec ${RUN} --vdex --vdex-filter speed "${@}"
diff --git a/test/630-safecast-array/expected.txt b/test/630-safecast-array/expected-stderr.txt
similarity index 100%
rename from test/630-safecast-array/expected.txt
rename to test/630-safecast-array/expected-stderr.txt
diff --git a/test/630-safecast-array/expected.txt b/test/630-safecast-array/expected-stdout.txt
similarity index 100%
copy from test/630-safecast-array/expected.txt
copy to test/630-safecast-array/expected-stdout.txt
diff --git a/test/631-checker-fp-abs/expected.txt b/test/631-checker-fp-abs/expected.txt
deleted file mode 100644
index b0aad4d..0000000
--- a/test/631-checker-fp-abs/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-passed
diff --git a/test/631-checker-fp-abs/info.txt b/test/631-checker-fp-abs/info.txt
deleted file mode 100644
index 0a1499e..0000000
--- a/test/631-checker-fp-abs/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Tests on floating-point Math.abs.
diff --git a/test/631-checker-fp-abs/src/Main.java b/test/631-checker-fp-abs/src/Main.java
deleted file mode 100644
index 2d04e36..0000000
--- a/test/631-checker-fp-abs/src/Main.java
+++ /dev/null
@@ -1,196 +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.
- */
-
-/**
- * A few tests of Math.abs for floating-point data.
- *
- * Note, as a "quality of implementation", rather than pure "spec compliance",
- * we require that Math.abs() clears the sign bit (but changes nothing else)
- * for all numbers, including NaN (signaling NaN may become quiet though).
- */
-public class Main {
-
-  private final static boolean isDalvik =
-      System.getProperty("java.vm.name").equals("Dalvik");
-
-  private static final int SPQUIET = 1 << 22;
-  private static final long DPQUIET = 1L << 51;
-
-  public static boolean doThrow = false;
-
-  /// CHECK-START: float Main.$opt$noinline$absSP(float) builder (after)
-  /// CHECK-DAG: <<Result:f\d+>> InvokeStaticOrDirect intrinsic:MathAbsFloat
-  /// CHECK-DAG:                 Return [<<Result>>]
-  private static float $opt$noinline$absSP(float f) {
-    if (doThrow) {
-      throw new Error("Something to prevent inlining");
-    }
-    return Math.abs(f);
-  }
-
-  /// CHECK-START: double Main.$opt$noinline$absDP(double) builder (after)
-  /// CHECK-DAG: <<Result:d\d+>> InvokeStaticOrDirect intrinsic:MathAbsDouble
-  /// CHECK-DAG:                 Return [<<Result>>]
-  private static double $opt$noinline$absDP(double d) {
-    if (doThrow) {
-      throw new Error("Something to prevent inlining");
-    }
-    return Math.abs(d);
-  }
-
-  public static void main(String args[]) {
-    // A few obvious numbers.
-    for (float f = -100.0f; f < 0.0f; f += 0.5f) {
-      expectEqualsSP(-f, $opt$noinline$absSP(f));
-    }
-    for (float f = 0.0f; f <= 100.0f; f += 0.5f) {
-      expectEqualsSP(f, $opt$noinline$absSP(f));
-    }
-    for (float f = -1.5f; f <= -1.499f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) {
-      expectEqualsSP(-f, $opt$noinline$absSP(f));
-    }
-    for (float f = 1.499f; f <= 1.5f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) {
-      expectEqualsSP(f, $opt$noinline$absSP(f));
-    }
-
-    // Zero
-    expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(+0.0f)));
-    expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(-0.0f)));
-
-    // Inf.
-    expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.NEGATIVE_INFINITY));
-    expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.POSITIVE_INFINITY));
-
-    // A few NaN numbers.
-    int[] spnans = {
-      0x7f800001,  // signaling
-      0x7fa00000,
-      0x7fbfffff,
-      0x7fc00000,  // quiet
-      0x7fc00001,
-      0x7fffffff,
-      0xff800001,  // signaling
-      0xffa00000,
-      0xffbfffff,
-      0xffc00000,  // quiet
-      0xffffffff
-    };
-    for (int i = 0; i < spnans.length; i++) {
-      float f = Float.intBitsToFloat(spnans[i]);
-      expectEqualsNaN32(
-          spnans[i] & Integer.MAX_VALUE,
-          Float.floatToRawIntBits($opt$noinline$absSP(f)));
-    }
-
-    // A few obvious numbers.
-    for (double d = -100.0; d < 0.0; d += 0.5) {
-      expectEqualsDP(-d, $opt$noinline$absDP(d));
-    }
-    for (double d = 0.0; d <= 100.0; d += 0.5) {
-      expectEqualsDP(d, $opt$noinline$absDP(d));
-    }
-    for (double d = -1.5d; d <= -1.49999999999d; d = Math.nextAfter(d, Double.POSITIVE_INFINITY)) {
-      expectEqualsDP(-d, $opt$noinline$absDP(d));
-    }
-    for (double d = 1.49999999999d; d <= 1.5; d = Math.nextAfter(d, Double.POSITIVE_INFINITY)) {
-      expectEqualsDP(d, $opt$noinline$absDP(d));
-    }
-
-    // Zero
-    expectEquals64(0L, Double.doubleToRawLongBits($opt$noinline$absDP(+0.0f)));
-    expectEquals64(0L, Double.doubleToRawLongBits($opt$noinline$absDP(-0.0f)));
-
-    // Inf.
-    expectEqualsDP(Double.POSITIVE_INFINITY, $opt$noinline$absDP(Double.NEGATIVE_INFINITY));
-    expectEqualsDP(Double.POSITIVE_INFINITY, $opt$noinline$absDP(Double.POSITIVE_INFINITY));
-
-    // A few NaN numbers.
-    long[] dpnans = {
-      0x7ff0000000000001L,
-      0x7ff4000000000000L,
-      0x7ff8000000000000L,
-      0x7fffffffffffffffL,
-      0xfff0000000000001L,
-      0xfff4000000000000L,
-      0xfff8000000000000L,
-      0xffffffffffffffffL
-    };
-    for (int i = 0; i < dpnans.length; i++) {
-      double d = Double.longBitsToDouble(dpnans[i]);
-      expectEqualsNaN64(
-          dpnans[i] & Long.MAX_VALUE,
-          Double.doubleToRawLongBits($opt$noinline$absDP(d)));
-    }
-
-    System.out.println("passed");
-  }
-
-  private static void expectEquals32(int expected, int result) {
-    if (expected != result) {
-      throw new Error("Expected: 0x" + Integer.toHexString(expected)
-          + ", found: 0x" + Integer.toHexString(result));
-    }
-  }
-
-  // We allow that an expected NaN result has become quiet.
-  private static void expectEqualsNaN32(int expected, int result) {
-    if (expected != result && (expected | SPQUIET) != result) {
-      if (!isDalvik) {
-        // If not on ART, relax the expected value more towards just
-        // "spec compliance" and allow sign bit to remain set for NaN.
-        if (expected == (result & Integer.MAX_VALUE)) {
-          return;
-        }
-      }
-      throw new Error("Expected: 0x" + Integer.toHexString(expected)
-          + ", found: 0x" + Integer.toHexString(result));
-    }
-  }
-
-  private static void expectEquals64(long expected, long result) {
-    if (expected != result) {
-      throw new Error("Expected: 0x" + Long.toHexString(expected)
-          + ", found: 0x" + Long.toHexString(result));
-    }
-  }
-
-  // We allow that an expected NaN result has become quiet.
-  private static void expectEqualsNaN64(long expected, long result) {
-    if (expected != result && (expected | DPQUIET) != result) {
-      if (!isDalvik) {
-        // If not on ART, relax the expected value more towards just
-        // "spec compliance" and allow sign bit to remain set for NaN.
-        if (expected == (result & Long.MAX_VALUE)) {
-          return;
-        }
-      }
-      throw new Error("Expected: 0x" + Long.toHexString(expected)
-          + ", found: 0x" + Long.toHexString(result));
-    }
-  }
-
-  private static void expectEqualsSP(float expected, float result) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
-
-  private static void expectEqualsDP(double expected, double result) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
-}
diff --git a/test/631-checker-get-class/Android.bp b/test/631-checker-get-class/Android.bp
new file mode 100644
index 0000000..f08cfe0
--- /dev/null
+++ b/test/631-checker-get-class/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `631-checker-get-class`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-631-checker-get-class",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-631-checker-get-class-expected-stdout",
+        ":art-run-test-631-checker-get-class-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-631-checker-get-class-expected-stdout",
+    out: ["art-run-test-631-checker-get-class-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-631-checker-get-class-expected-stderr",
+    out: ["art-run-test-631-checker-get-class-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/631-checker-get-class/expected.txt b/test/631-checker-get-class/expected-stderr.txt
similarity index 100%
rename from test/631-checker-get-class/expected.txt
rename to test/631-checker-get-class/expected-stderr.txt
diff --git a/test/631-checker-get-class/expected.txt b/test/631-checker-get-class/expected-stdout.txt
similarity index 100%
copy from test/631-checker-get-class/expected.txt
copy to test/631-checker-get-class/expected-stdout.txt
diff --git a/test/632-checker-char-at-bounds/Android.bp b/test/632-checker-char-at-bounds/Android.bp
new file mode 100644
index 0000000..d7f680a
--- /dev/null
+++ b/test/632-checker-char-at-bounds/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `632-checker-char-at-bounds`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-632-checker-char-at-bounds",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-632-checker-char-at-bounds-expected-stdout",
+        ":art-run-test-632-checker-char-at-bounds-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-632-checker-char-at-bounds-expected-stdout",
+    out: ["art-run-test-632-checker-char-at-bounds-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-632-checker-char-at-bounds-expected-stderr",
+    out: ["art-run-test-632-checker-char-at-bounds-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/632-checker-char-at-bounds/expected.txt b/test/632-checker-char-at-bounds/expected-stderr.txt
similarity index 100%
rename from test/632-checker-char-at-bounds/expected.txt
rename to test/632-checker-char-at-bounds/expected-stderr.txt
diff --git a/test/632-checker-char-at-bounds/expected.txt b/test/632-checker-char-at-bounds/expected-stdout.txt
similarity index 100%
copy from test/632-checker-char-at-bounds/expected.txt
copy to test/632-checker-char-at-bounds/expected-stdout.txt
diff --git a/test/631-checker-get-class/expected.txt b/test/633-checker-rtp-getclass/expected-stderr.txt
similarity index 100%
copy from test/631-checker-get-class/expected.txt
copy to test/633-checker-rtp-getclass/expected-stderr.txt
diff --git a/test/633-checker-rtp-getclass/expected.txt b/test/633-checker-rtp-getclass/expected-stdout.txt
similarity index 100%
rename from test/633-checker-rtp-getclass/expected.txt
rename to test/633-checker-rtp-getclass/expected-stdout.txt
diff --git a/test/082-inline-execute/expected.txt b/test/634-vdex-duplicate/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/634-vdex-duplicate/expected-stderr.txt
diff --git a/test/634-vdex-duplicate/expected.txt b/test/634-vdex-duplicate/expected-stdout.txt
similarity index 100%
rename from test/634-vdex-duplicate/expected.txt
rename to test/634-vdex-duplicate/expected-stdout.txt
diff --git a/test/635-checker-arm64-volatile-load-cc/Android.bp b/test/635-checker-arm64-volatile-load-cc/Android.bp
new file mode 100644
index 0000000..253abb1
--- /dev/null
+++ b/test/635-checker-arm64-volatile-load-cc/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `635-checker-arm64-volatile-load-cc`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-635-checker-arm64-volatile-load-cc",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-635-checker-arm64-volatile-load-cc-expected-stdout",
+        ":art-run-test-635-checker-arm64-volatile-load-cc-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-635-checker-arm64-volatile-load-cc-expected-stdout",
+    out: ["art-run-test-635-checker-arm64-volatile-load-cc-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-635-checker-arm64-volatile-load-cc-expected-stderr",
+    out: ["art-run-test-635-checker-arm64-volatile-load-cc-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/630-safecast-array/expected.txt b/test/635-checker-arm64-volatile-load-cc/expected-stderr.txt
similarity index 100%
copy from test/630-safecast-array/expected.txt
copy to test/635-checker-arm64-volatile-load-cc/expected-stderr.txt
diff --git a/test/635-checker-arm64-volatile-load-cc/expected.txt b/test/635-checker-arm64-volatile-load-cc/expected-stdout.txt
similarity index 100%
rename from test/635-checker-arm64-volatile-load-cc/expected.txt
rename to test/635-checker-arm64-volatile-load-cc/expected-stdout.txt
diff --git a/test/636-arm64-veneer-pool/Android.bp b/test/636-arm64-veneer-pool/Android.bp
new file mode 100644
index 0000000..9d8f7cc
--- /dev/null
+++ b/test/636-arm64-veneer-pool/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `636-arm64-veneer-pool`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-636-arm64-veneer-pool",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-636-arm64-veneer-pool-expected-stdout",
+        ":art-run-test-636-arm64-veneer-pool-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-636-arm64-veneer-pool-expected-stdout",
+    out: ["art-run-test-636-arm64-veneer-pool-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-636-arm64-veneer-pool-expected-stderr",
+    out: ["art-run-test-636-arm64-veneer-pool-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/584-checker-div-bool/expected.txt b/test/636-arm64-veneer-pool/expected-stderr.txt
similarity index 100%
copy from test/584-checker-div-bool/expected.txt
copy to test/636-arm64-veneer-pool/expected-stderr.txt
diff --git a/test/636-arm64-veneer-pool/expected.txt b/test/636-arm64-veneer-pool/expected-stdout.txt
similarity index 100%
rename from test/636-arm64-veneer-pool/expected.txt
rename to test/636-arm64-veneer-pool/expected-stdout.txt
diff --git a/test/631-checker-get-class/expected.txt b/test/636-wrong-static-access/expected-stderr.txt
similarity index 100%
copy from test/631-checker-get-class/expected.txt
copy to test/636-wrong-static-access/expected-stderr.txt
diff --git a/test/636-wrong-static-access/expected.txt b/test/636-wrong-static-access/expected-stdout.txt
similarity index 100%
rename from test/636-wrong-static-access/expected.txt
rename to test/636-wrong-static-access/expected-stdout.txt
diff --git a/test/637-checker-throw-inline/Android.bp b/test/637-checker-throw-inline/Android.bp
new file mode 100644
index 0000000..f44e64b
--- /dev/null
+++ b/test/637-checker-throw-inline/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `637-checker-throw-inline`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-637-checker-throw-inline",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-637-checker-throw-inline-expected-stdout",
+        ":art-run-test-637-checker-throw-inline-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-637-checker-throw-inline-expected-stdout",
+    out: ["art-run-test-637-checker-throw-inline-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-637-checker-throw-inline-expected-stderr",
+    out: ["art-run-test-637-checker-throw-inline-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/637-checker-throw-inline/expected.txt b/test/637-checker-throw-inline/expected-stderr.txt
similarity index 100%
rename from test/637-checker-throw-inline/expected.txt
rename to test/637-checker-throw-inline/expected-stderr.txt
diff --git a/test/637-checker-throw-inline/expected.txt b/test/637-checker-throw-inline/expected-stdout.txt
similarity index 100%
copy from test/637-checker-throw-inline/expected.txt
copy to test/637-checker-throw-inline/expected-stdout.txt
diff --git a/test/638-checker-inline-cache-intrinsic/Android.bp b/test/638-checker-inline-cache-intrinsic/Android.bp
new file mode 100644
index 0000000..9040ce3
--- /dev/null
+++ b/test/638-checker-inline-cache-intrinsic/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `638-checker-inline-cache-intrinsic`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-638-checker-inline-cache-intrinsic",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-638-checker-inline-cache-intrinsic-expected-stdout",
+        ":art-run-test-638-checker-inline-cache-intrinsic-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-638-checker-inline-cache-intrinsic-expected-stdout",
+    out: ["art-run-test-638-checker-inline-cache-intrinsic-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-638-checker-inline-cache-intrinsic-expected-stderr",
+    out: ["art-run-test-638-checker-inline-cache-intrinsic-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/638-checker-inline-caches/expected.txt b/test/638-checker-inline-cache-intrinsic/expected-stderr.txt
similarity index 100%
copy from test/638-checker-inline-caches/expected.txt
copy to test/638-checker-inline-cache-intrinsic/expected-stderr.txt
diff --git a/test/638-checker-inline-cache-intrinsic/expected.txt b/test/638-checker-inline-cache-intrinsic/expected-stdout.txt
similarity index 100%
rename from test/638-checker-inline-cache-intrinsic/expected.txt
rename to test/638-checker-inline-cache-intrinsic/expected-stdout.txt
diff --git a/test/638-checker-inline-cache-intrinsic/run b/test/638-checker-inline-cache-intrinsic/run
index 814181d..9016107 100644
--- a/test/638-checker-inline-cache-intrinsic/run
+++ b/test/638-checker-inline-cache-intrinsic/run
@@ -19,4 +19,4 @@
 # The test is for JIT, but we run in "optimizing" (AOT) mode, so that the Checker
 # stanzas in test/638-checker-inline-cache-intrinsic/src/Main.java will be checked.
 # Also pass a large JIT code cache size to avoid getting the inline caches GCed.
-exec ${RUN} --jit --runtime-option -Xjitinitialsize:32M --runtime-option -Xjitthreshold:1000 -Xcompiler-option --verbose-methods=inlineMonomorphic,knownReceiverType,stringEquals $@
+exec ${RUN} --jit --runtime-option -Xjitinitialsize:32M --runtime-option -Xjitthreshold:1000 -Xcompiler-option --verbose-methods=inlineMonomorphic,inlinePolymorphic,knownReceiverType,stringEquals $@
diff --git a/test/638-checker-inline-cache-intrinsic/src/Main.java b/test/638-checker-inline-cache-intrinsic/src/Main.java
index 5334487..f25d03a 100644
--- a/test/638-checker-inline-cache-intrinsic/src/Main.java
+++ b/test/638-checker-inline-cache-intrinsic/src/Main.java
@@ -32,6 +32,26 @@
     return cs.charAt(0);
   }
 
+  /// CHECK-START: char Main.$noinline$inlinePolymorphic(java.lang.CharSequence) inliner (before)
+  /// CHECK:       InvokeInterface method_name:java.lang.CharSequence.charAt
+
+  /// CHECK-START: char Main.$noinline$inlinePolymorphic(java.lang.CharSequence) inliner (after)
+  /// CHECK:       InvokeVirtual method_name:java.lang.String.charAt intrinsic:StringCharAt
+  /// CHECK:       Deoptimize
+
+  /// CHECK-START: char Main.$noinline$inlinePolymorphic(java.lang.CharSequence) instruction_simplifier$after_inlining (after)
+  /// CHECK:       Deoptimize
+
+  /// CHECK-START: char Main.$noinline$inlinePolymorphic(java.lang.CharSequence) instruction_simplifier$after_inlining (after)
+  /// CHECK-NOT:   InvokeInterface
+
+  /// CHECK-START: char Main.$noinline$inlinePolymorphic(java.lang.CharSequence) instruction_simplifier$after_inlining (after)
+  /// CHECK-NOT:   InvokeVirtual method_name:java.lang.String.charAt
+
+  public static char $noinline$inlinePolymorphic(CharSequence cs) {
+    return cs.charAt(0);
+  }
+
   /// CHECK-START: char Main.$noinline$knownReceiverType() inliner (before)
   /// CHECK:       InvokeInterface method_name:java.lang.CharSequence.charAt
 
@@ -63,19 +83,30 @@
   }
 
   public static void test() {
+    ensureJitBaselineCompiled(Main.class, "$noinline$stringEquals");
+    ensureJitBaselineCompiled(Main.class, "$noinline$inlineMonomorphic");
+    ensureJitBaselineCompiled(Main.class, "$noinline$knownReceiverType");
+    ensureJitBaselineCompiled(Main.class, "$noinline$inlinePolymorphic");
     // Warm up inline cache.
     for (int i = 0; i < 600000; i++) {
       $noinline$inlineMonomorphic(str);
-    }
-    for (int i = 0; i < 600000; i++) {
       $noinline$stringEquals(str);
+      $noinline$inlinePolymorphic(str);
+      $noinline$inlinePolymorphic(strBuilder);
     }
     ensureJitCompiled(Main.class, "$noinline$stringEquals");
     ensureJitCompiled(Main.class, "$noinline$inlineMonomorphic");
+    ensureJitCompiled(Main.class, "$noinline$inlinePolymorphic");
     ensureJitCompiled(Main.class, "$noinline$knownReceiverType");
     if ($noinline$inlineMonomorphic(str) != 'x') {
       throw new Error("Expected x");
     }
+    if ($noinline$inlinePolymorphic(str) != 'x') {
+      throw new Error("Expected x");
+    }
+    if ($noinline$inlinePolymorphic(strBuilder) != 'a') {
+      throw new Error("Expected a");
+    }
     if ($noinline$knownReceiverType() != 'b') {
       throw new Error("Expected b");
     }
@@ -90,6 +121,8 @@
   }
 
   static String str = "xyz";
+  static StringBuilder strBuilder = new StringBuilder("abc");
 
+  private static native void ensureJitBaselineCompiled(Class<?> itf, String method_name);
   private static native void ensureJitCompiled(Class<?> itf, String method_name);
 }
diff --git a/test/638-checker-inline-caches/expected.txt b/test/638-checker-inline-caches/expected-stderr.txt
similarity index 100%
rename from test/638-checker-inline-caches/expected.txt
rename to test/638-checker-inline-caches/expected-stderr.txt
diff --git a/test/638-checker-inline-caches/expected.txt b/test/638-checker-inline-caches/expected-stdout.txt
similarity index 100%
copy from test/638-checker-inline-caches/expected.txt
copy to test/638-checker-inline-caches/expected-stdout.txt
diff --git a/test/658-fp-read-barrier/expected.txt b/test/638-no-line-number/expected-stderr.txt
similarity index 100%
copy from test/658-fp-read-barrier/expected.txt
copy to test/638-no-line-number/expected-stderr.txt
diff --git a/test/638-no-line-number/expected.txt b/test/638-no-line-number/expected-stdout.txt
similarity index 100%
rename from test/638-no-line-number/expected.txt
rename to test/638-no-line-number/expected-stdout.txt
diff --git a/test/639-checker-code-sinking/Android.bp b/test/639-checker-code-sinking/Android.bp
new file mode 100644
index 0000000..9493934
--- /dev/null
+++ b/test/639-checker-code-sinking/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `639-checker-code-sinking`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-639-checker-code-sinking",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-639-checker-code-sinking-expected-stdout",
+        ":art-run-test-639-checker-code-sinking-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-639-checker-code-sinking-expected-stdout",
+    out: ["art-run-test-639-checker-code-sinking-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-639-checker-code-sinking-expected-stderr",
+    out: ["art-run-test-639-checker-code-sinking-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2019-constantcalculationsinking/expected.txt b/test/639-checker-code-sinking/expected-stderr.txt
similarity index 100%
copy from test/2019-constantcalculationsinking/expected.txt
copy to test/639-checker-code-sinking/expected-stderr.txt
diff --git a/test/639-checker-code-sinking/expected.txt b/test/639-checker-code-sinking/expected-stdout.txt
similarity index 100%
rename from test/639-checker-code-sinking/expected.txt
rename to test/639-checker-code-sinking/expected-stdout.txt
diff --git a/test/639-checker-code-sinking/src/Main.java b/test/639-checker-code-sinking/src/Main.java
index 8efac92..28fa57c 100644
--- a/test/639-checker-code-sinking/src/Main.java
+++ b/test/639-checker-code-sinking/src/Main.java
@@ -100,13 +100,20 @@
     }
   }
 
+  // NB It might seem that we'd move the allocation and ifield-set but those are
+  // already moved into the throw block by a combo of partial-LSE and DCE.
+  // Instead all that is actually moved is the LoadClass. Also note the
+  // LoadClass can only be moved since it refers to the 'Main' class itself,
+  // meaning there's no need for any clinit/actual loading.
+  //
   /// CHECK-START: void Main.testFieldStores(boolean) code_sinking (before)
   /// CHECK: <<Int42:i\d+>>       IntConstant 42
+  /// CHECK:                      begin_block
   /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
-  /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
-  /// CHECK:                      InstanceFieldSet [<<NewInstance>>,<<Int42>>]
   /// CHECK:                      If
   /// CHECK:                      begin_block
+  /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
+  /// CHECK:                      InstanceFieldSet [<<NewInstance>>,<<Int42>>]
   /// CHECK:                      Throw
 
   /// CHECK-START: void Main.testFieldStores(boolean) code_sinking (after)
@@ -114,15 +121,17 @@
   /// CHECK-NOT:                  NewInstance
   /// CHECK:                      If
   /// CHECK:                      begin_block
-  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
   /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
   /// CHECK-NOT:                  begin_block
   /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
   /// CHECK-NOT:                  begin_block
   /// CHECK:                      InstanceFieldSet [<<NewInstance>>,<<Int42>>]
   /// CHECK-NOT:                  begin_block
-  /// CHECK:                      NewInstance [<<Error>>]
-  /// CHECK:                      Throw
+  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
+  /// CHECK-NOT:                  begin_block
+  /// CHECK: <<Throw:l\d+>>       NewInstance [<<Error>>]
+  /// CHECK-NOT:                  begin_block
+  /// CHECK:                      Throw [<<Throw>>]
   public static void testFieldStores(boolean doThrow) {
     Main m = new Main();
     m.intField = 42;
@@ -306,16 +315,26 @@
   }
 
   // Test that we preserve the order of stores.
+  // NB It might seem that we'd move the allocation and ifield-set but those are
+  // already moved into the throw block by a combo of partial-LSE and DCE.
+  // Instead all that is actually moved is the LoadClass. Also note the
+  // LoadClass can only be moved since it refers to the 'Main' class itself,
+  // meaning there's no need for any clinit/actual loading.
+  //
   /// CHECK-START: void Main.testStoreStore(boolean) code_sinking (before)
   /// CHECK: <<Int42:i\d+>>       IntConstant 42
   /// CHECK: <<Int43:i\d+>>       IntConstant 43
   /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
-  /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
-  /// CHECK:                      InstanceFieldSet [<<NewInstance>>,<<Int42>>]
-  /// CHECK:                      InstanceFieldSet [<<NewInstance>>,<<Int43>>]
   /// CHECK:                      If
   /// CHECK:                      begin_block
+  // Moved to throw block by partial-LSE and DCE.
+  /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
+  // These were moved by partial LSE and order of sets is not observable and are
+  // in an arbitrary order.
+  /// CHECK-DAG:                  InstanceFieldSet [<<NewInstance>>,<<Int42>>]
+  /// CHECK-DAG:                  InstanceFieldSet [<<NewInstance>>,<<Int43>>]
   /// CHECK:                      Throw
+  /// CHECK-NOT:                  InstanceFieldSet
 
   /// CHECK-START: void Main.testStoreStore(boolean) code_sinking (after)
   /// CHECK: <<Int42:i\d+>>       IntConstant 42
@@ -323,17 +342,17 @@
   /// CHECK-NOT:                  NewInstance
   /// CHECK:                      If
   /// CHECK:                      begin_block
-  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
   /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
-  /// CHECK-NOT:                  begin_block
   /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
   /// CHECK-NOT:                  begin_block
-  /// CHECK:                      InstanceFieldSet [<<NewInstance>>,<<Int42>>]
+  /// CHECK-DAG:                  InstanceFieldSet [<<NewInstance>>,<<Int42>>]
+  /// CHECK-DAG:                  InstanceFieldSet [<<NewInstance>>,<<Int43>>]
   /// CHECK-NOT:                  begin_block
-  /// CHECK:                      InstanceFieldSet [<<NewInstance>>,<<Int43>>]
+  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
   /// CHECK-NOT:                  begin_block
   /// CHECK:                      NewInstance [<<Error>>]
   /// CHECK:                      Throw
+  /// CHECK-NOT:                  InstanceFieldSet
   public static void testStoreStore(boolean doThrow) {
     Main m = new Main();
     m.intField = 42;
diff --git a/test/640-checker-boolean-simd/Android.bp b/test/640-checker-boolean-simd/Android.bp
new file mode 100644
index 0000000..89e6ac7
--- /dev/null
+++ b/test/640-checker-boolean-simd/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `640-checker-boolean-simd`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-640-checker-boolean-simd",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-640-checker-boolean-simd-expected-stdout",
+        ":art-run-test-640-checker-boolean-simd-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-640-checker-boolean-simd-expected-stdout",
+    out: ["art-run-test-640-checker-boolean-simd-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-640-checker-boolean-simd-expected-stderr",
+    out: ["art-run-test-640-checker-boolean-simd-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/640-checker-integer-valueof/expected.txt b/test/640-checker-boolean-simd/expected-stderr.txt
similarity index 100%
copy from test/640-checker-integer-valueof/expected.txt
copy to test/640-checker-boolean-simd/expected-stderr.txt
diff --git a/test/640-checker-boolean-simd/expected.txt b/test/640-checker-boolean-simd/expected-stdout.txt
similarity index 100%
rename from test/640-checker-boolean-simd/expected.txt
rename to test/640-checker-boolean-simd/expected-stdout.txt
diff --git a/test/640-checker-integer-valueof/Android.bp b/test/640-checker-integer-valueof/Android.bp
new file mode 100644
index 0000000..aca0bb3
--- /dev/null
+++ b/test/640-checker-integer-valueof/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `640-checker-integer-valueof`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-640-checker-integer-valueof",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-640-checker-integer-valueof-expected-stdout",
+        ":art-run-test-640-checker-integer-valueof-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-640-checker-integer-valueof-expected-stdout",
+    out: ["art-run-test-640-checker-integer-valueof-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-640-checker-integer-valueof-expected-stderr",
+    out: ["art-run-test-640-checker-integer-valueof-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/640-checker-integer-valueof/expected.txt b/test/640-checker-integer-valueof/expected-stderr.txt
similarity index 100%
rename from test/640-checker-integer-valueof/expected.txt
rename to test/640-checker-integer-valueof/expected-stderr.txt
diff --git a/test/640-checker-integer-valueof/expected.txt b/test/640-checker-integer-valueof/expected-stdout.txt
similarity index 100%
copy from test/640-checker-integer-valueof/expected.txt
copy to test/640-checker-integer-valueof/expected-stdout.txt
diff --git a/test/640-checker-simd/Android.bp b/test/640-checker-simd/Android.bp
new file mode 100644
index 0000000..45d0885
--- /dev/null
+++ b/test/640-checker-simd/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `640-checker-simd`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-640-checker-simd",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-640-checker-simd-expected-stdout",
+        ":art-run-test-640-checker-simd-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-640-checker-simd-expected-stdout",
+    out: ["art-run-test-640-checker-simd-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-640-checker-simd-expected-stderr",
+    out: ["art-run-test-640-checker-simd-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/640-checker-integer-valueof/expected.txt b/test/640-checker-simd/expected-stderr.txt
similarity index 100%
copy from test/640-checker-integer-valueof/expected.txt
copy to test/640-checker-simd/expected-stderr.txt
diff --git a/test/640-checker-simd/expected.txt b/test/640-checker-simd/expected-stdout.txt
similarity index 100%
rename from test/640-checker-simd/expected.txt
rename to test/640-checker-simd/expected-stdout.txt
diff --git a/test/640-checker-simd/src/SimdByte.java b/test/640-checker-simd/src/SimdByte.java
index 5066136..385a6c3 100644
--- a/test/640-checker-simd/src/SimdByte.java
+++ b/test/640-checker-simd/src/SimdByte.java
@@ -142,7 +142,7 @@
   }
 
   //
-  // Shift sanity.
+  // Shift checks.
   //
 
   static void sar31() {
diff --git a/test/640-checker-simd/src/SimdChar.java b/test/640-checker-simd/src/SimdChar.java
index bb06b06..dd9c316 100644
--- a/test/640-checker-simd/src/SimdChar.java
+++ b/test/640-checker-simd/src/SimdChar.java
@@ -143,7 +143,7 @@
   }
 
   //
-  // Shift sanity.
+  // Shift checks.
   //
 
   static void sar31() {
diff --git a/test/640-checker-simd/src/SimdInt.java b/test/640-checker-simd/src/SimdInt.java
index 0276bca..065fc49 100644
--- a/test/640-checker-simd/src/SimdInt.java
+++ b/test/640-checker-simd/src/SimdInt.java
@@ -144,7 +144,7 @@
   }
 
   //
-  // Shift sanity.
+  // Shift checks.
   //
 
   // Expose constants to optimizing compiler, but not to front-end.
@@ -163,8 +163,17 @@
   /// CHECK-DAG:              ArraySet [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-{ARM,ARM64}: void SimdInt.shr32() loop_optimization (after)
-  /// CHECK-DAG: <<Get:d\d+>> VecLoad                              loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:              VecStore [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Get:d\d+>> VecLoad                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:              VecStore [{{l\d+}},{{i\d+}},<<Get>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get:d\d+>> VecLoad                              loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:              VecStore [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static void shr32() {
     // TODO: remove a[i] = a[i] altogether?
     for (int i = 0; i < 128; i++)
@@ -185,9 +194,19 @@
   //
   /// CHECK-START-{ARM,ARM64}: void SimdInt.shr33() loop_optimization (after)
   /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1                         loop:none
-  /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                                        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>,{{j\d+}}]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static void shr33() {
     for (int i = 0; i < 128; i++)
       a[i] >>>= $opt$inline$IntConstant33();  // 1, since & 31
@@ -207,9 +226,19 @@
   //
   /// CHECK-START-{ARM,ARM64}: void SimdInt.shrMinus254() loop_optimization (after)
   /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2                         loop:none
-  /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                                        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>,{{j\d+}}]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static void shrMinus254() {
     for (int i = 0; i < 128; i++)
       a[i] >>>= $opt$inline$IntConstantMinus254();  // 2, since & 31
diff --git a/test/640-checker-simd/src/SimdLong.java b/test/640-checker-simd/src/SimdLong.java
index c914b69..13ea9af 100644
--- a/test/640-checker-simd/src/SimdLong.java
+++ b/test/640-checker-simd/src/SimdLong.java
@@ -58,7 +58,17 @@
   //  Not directly supported for longs.
   //
   /// CHECK-START-ARM64: void SimdLong.mul(long) loop_optimization (after)
-  /// CHECK-NOT: VecMul
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: VecMul   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-NOT: VecMul
+  //
+  /// CHECK-FI:
   static void mul(long x) {
     for (int i = 0; i < 128; i++)
       a[i] *= x;
@@ -144,7 +154,7 @@
   }
 
   //
-  // Shift sanity.
+  // Shift checks.
   //
 
   // Expose constants to optimizing compiler, but not to front-end.
@@ -163,8 +173,17 @@
   /// CHECK-DAG:              ArraySet [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-ARM64: void SimdLong.shr64() loop_optimization (after)
-  /// CHECK-DAG: <<Get:d\d+>> VecLoad                              loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:              VecStore [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Get:d\d+>> VecLoad                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:              VecStore [{{l\d+}},{{i\d+}},<<Get>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get:d\d+>> VecLoad                              loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:              VecStore [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static void shr64() {
     // TODO: remove a[i] = a[i] altogether?
     for (int i = 0; i < 128; i++)
@@ -185,9 +204,19 @@
   //
   /// CHECK-START-ARM64: void SimdLong.shr65() loop_optimization (after)
   /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1                         loop:none
-  /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                                        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>,{{j\d+}}]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static void shr65() {
     for (int i = 0; i < 128; i++)
       a[i] >>>= $opt$inline$IntConstant65();  // 1, since & 63
@@ -207,9 +236,19 @@
   //
   /// CHECK-START-ARM64: void SimdLong.shrMinus254() loop_optimization (after)
   /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2                         loop:none
-  /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                                        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>,{{j\d+}}]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static void shrMinus254() {
     for (int i = 0; i < 128; i++)
       a[i] >>>= $opt$inline$IntConstantMinus254();  // 2, since & 63
diff --git a/test/640-checker-simd/src/SimdShort.java b/test/640-checker-simd/src/SimdShort.java
index 6b184a6..6fec754 100644
--- a/test/640-checker-simd/src/SimdShort.java
+++ b/test/640-checker-simd/src/SimdShort.java
@@ -143,7 +143,7 @@
   }
 
   //
-  // Shift sanity.
+  // Shift checks.
   //
 
   static void sar31() {
diff --git a/test/641-checker-arraycopy/Android.bp b/test/641-checker-arraycopy/Android.bp
new file mode 100644
index 0000000..fabb0fe
--- /dev/null
+++ b/test/641-checker-arraycopy/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `641-checker-arraycopy`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-641-checker-arraycopy",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-641-checker-arraycopy-expected-stdout",
+        ":art-run-test-641-checker-arraycopy-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-641-checker-arraycopy-expected-stdout",
+    out: ["art-run-test-641-checker-arraycopy-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-641-checker-arraycopy-expected-stderr",
+    out: ["art-run-test-641-checker-arraycopy-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/641-checker-arraycopy/expected.txt b/test/641-checker-arraycopy/expected-stderr.txt
similarity index 100%
rename from test/641-checker-arraycopy/expected.txt
rename to test/641-checker-arraycopy/expected-stderr.txt
diff --git a/test/641-checker-arraycopy/expected.txt b/test/641-checker-arraycopy/expected-stdout.txt
similarity index 100%
copy from test/641-checker-arraycopy/expected.txt
copy to test/641-checker-arraycopy/expected-stdout.txt
diff --git a/test/641-checker-arraycopy/src/Main.java b/test/641-checker-arraycopy/src/Main.java
index c2a95cc..939fc00 100644
--- a/test/641-checker-arraycopy/src/Main.java
+++ b/test/641-checker-arraycopy/src/Main.java
@@ -54,7 +54,7 @@
   }
 
   public static void main(String[] args) {
-    // Simple sanity checks.
+    // Simple checks.
     byte[] a = new byte[2];
     Object[] o = new Object[2];
 
diff --git a/test/637-checker-throw-inline/expected.txt b/test/641-irreducible-inline/expected-stderr.txt
similarity index 100%
copy from test/637-checker-throw-inline/expected.txt
copy to test/641-irreducible-inline/expected-stderr.txt
diff --git a/test/641-irreducible-inline/expected.txt b/test/641-irreducible-inline/expected-stdout.txt
similarity index 100%
rename from test/641-irreducible-inline/expected.txt
rename to test/641-irreducible-inline/expected-stdout.txt
diff --git a/test/641-iterations/Android.bp b/test/641-iterations/Android.bp
new file mode 100644
index 0000000..be127bb
--- /dev/null
+++ b/test/641-iterations/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `641-iterations`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-641-iterations",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-641-iterations-expected-stdout",
+        ":art-run-test-641-iterations-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-641-iterations-expected-stdout",
+    out: ["art-run-test-641-iterations-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-641-iterations-expected-stderr",
+    out: ["art-run-test-641-iterations-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/685-shifts/expected.txt b/test/641-iterations/expected-stderr.txt
similarity index 100%
copy from test/685-shifts/expected.txt
copy to test/641-iterations/expected-stderr.txt
diff --git a/test/641-iterations/expected.txt b/test/641-iterations/expected-stdout.txt
similarity index 100%
rename from test/641-iterations/expected.txt
rename to test/641-iterations/expected-stdout.txt
diff --git a/test/642-fp-callees/Android.bp b/test/642-fp-callees/Android.bp
new file mode 100644
index 0000000..0c7a886
--- /dev/null
+++ b/test/642-fp-callees/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `642-fp-callees`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-642-fp-callees",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-642-fp-callees-expected-stdout",
+        ":art-run-test-642-fp-callees-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-642-fp-callees-expected-stdout",
+    out: ["art-run-test-642-fp-callees-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-642-fp-callees-expected-stderr",
+    out: ["art-run-test-642-fp-callees-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/685-shifts/expected.txt b/test/642-fp-callees/expected-stderr.txt
similarity index 100%
copy from test/685-shifts/expected.txt
copy to test/642-fp-callees/expected-stderr.txt
diff --git a/test/642-fp-callees/expected.txt b/test/642-fp-callees/expected-stdout.txt
similarity index 100%
rename from test/642-fp-callees/expected.txt
rename to test/642-fp-callees/expected-stdout.txt
diff --git a/test/643-checker-bogus-ic/Android.bp b/test/643-checker-bogus-ic/Android.bp
new file mode 100644
index 0000000..ee2b7dc
--- /dev/null
+++ b/test/643-checker-bogus-ic/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `643-checker-bogus-ic`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-643-checker-bogus-ic",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-643-checker-bogus-ic-expected-stdout",
+        ":art-run-test-643-checker-bogus-ic-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-643-checker-bogus-ic-expected-stdout",
+    out: ["art-run-test-643-checker-bogus-ic-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-643-checker-bogus-ic-expected-stderr",
+    out: ["art-run-test-643-checker-bogus-ic-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/643-checker-bogus-ic/expected.txt b/test/643-checker-bogus-ic/expected-stderr.txt
similarity index 100%
rename from test/643-checker-bogus-ic/expected.txt
rename to test/643-checker-bogus-ic/expected-stderr.txt
diff --git a/test/643-checker-bogus-ic/expected.txt b/test/643-checker-bogus-ic/expected-stdout.txt
similarity index 100%
copy from test/643-checker-bogus-ic/expected.txt
copy to test/643-checker-bogus-ic/expected-stdout.txt
diff --git a/test/645-checker-abs-simd/Android.bp b/test/645-checker-abs-simd/Android.bp
new file mode 100644
index 0000000..bf29f92
--- /dev/null
+++ b/test/645-checker-abs-simd/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `645-checker-abs-simd`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-645-checker-abs-simd",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-645-checker-abs-simd-expected-stdout",
+        ":art-run-test-645-checker-abs-simd-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-645-checker-abs-simd-expected-stdout",
+    out: ["art-run-test-645-checker-abs-simd-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-645-checker-abs-simd-expected-stderr",
+    out: ["art-run-test-645-checker-abs-simd-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/527-checker-array-access-simd/expected.txt b/test/645-checker-abs-simd/expected-stderr.txt
similarity index 100%
copy from test/527-checker-array-access-simd/expected.txt
copy to test/645-checker-abs-simd/expected-stderr.txt
diff --git a/test/645-checker-abs-simd/expected.txt b/test/645-checker-abs-simd/expected-stdout.txt
similarity index 100%
rename from test/645-checker-abs-simd/expected.txt
rename to test/645-checker-abs-simd/expected-stdout.txt
diff --git a/test/645-checker-abs-simd/src/Main.java b/test/645-checker-abs-simd/src/Main.java
index 828b656..b1a1b81 100644
--- a/test/645-checker-abs-simd/src/Main.java
+++ b/test/645-checker-abs-simd/src/Main.java
@@ -31,7 +31,7 @@
   /// CHECK-DAG: Abs       loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: ArraySet  loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void Main.doitByte(byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void Main.doitByte(byte[]) loop_optimization (after)
   /// CHECK-DAG: VecLoad   loop:<<Loop1:B\d+>> outer_loop:none
   /// CHECK-DAG: VecAbs    loop:<<Loop1>>      outer_loop:none
   /// CHECK-DAG: VecStore  loop:<<Loop1>>      outer_loop:none
@@ -41,6 +41,27 @@
   //
   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
   //
+  /// CHECK-START-ARM64: void Main.doitByte(byte[]) loop_optimization (after)
+  /// CHECK-DAG: VecLoad   loop:<<Loop1:B\d+>> outer_loop:none
+  /// CHECK-DAG: VecAbs    loop:<<Loop1>>      outer_loop:none
+  /// CHECK-DAG: VecStore  loop:<<Loop1>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: VecPredWhile loop:<<Loop1>> outer_loop:none
+  ///     CHECK-NOT: ArrayGet
+  ///     CHECK-NOT: Abs
+  ///     CHECK-NOT: ArraySet
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: ArrayGet  loop:<<Loop2:B\d+>> outer_loop:none
+  ///     CHECK-DAG: Abs       loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: ArraySet  loop:<<Loop2>>      outer_loop:none
+  //
+  ///     CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  //
+  /// CHECK-FI:
+  //
   private static void doitByte(byte[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = (byte) Math.abs(x[i]);
@@ -65,7 +86,7 @@
   /// CHECK-DAG: Abs       loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: ArraySet  loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void Main.doitShort(short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void Main.doitShort(short[]) loop_optimization (after)
   /// CHECK-DAG: VecLoad   loop:<<Loop1:B\d+>> outer_loop:none
   /// CHECK-DAG: VecAbs    loop:<<Loop1>>      outer_loop:none
   /// CHECK-DAG: VecStore  loop:<<Loop1>>      outer_loop:none
@@ -75,6 +96,26 @@
   //
   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
   //
+  /// CHECK-START-ARM64: void Main.doitShort(short[]) loop_optimization (after)
+  /// CHECK-DAG: VecLoad   loop:<<Loop1:B\d+>> outer_loop:none
+  /// CHECK-DAG: VecAbs    loop:<<Loop1>>      outer_loop:none
+  /// CHECK-DAG: VecStore  loop:<<Loop1>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: VecPredWhile loop:<<Loop1>> outer_loop:none
+  ///     CHECK-NOT: ArrayGet
+  ///     CHECK-NOT: Abs
+  ///     CHECK-NOT: ArraySet
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: ArrayGet  loop:<<Loop2:B\d+>> outer_loop:none
+  ///     CHECK-DAG: Abs       loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: ArraySet  loop:<<Loop2>>      outer_loop:none
+  //
+  ///     CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  //
+  /// CHECK-FI:
   private static void doitShort(short[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = (short) Math.abs(x[i]);
@@ -91,12 +132,22 @@
   /// CHECK-DAG: VecLoad   loop:<<Loop1:B\d+>> outer_loop:none
   /// CHECK-DAG: VecAbs    loop:<<Loop1>>      outer_loop:none
   /// CHECK-DAG: VecStore  loop:<<Loop1>>      outer_loop:none
-  /// CHECK-DAG: ArrayGet  loop:<<Loop2:B\d+>> outer_loop:none
-  /// CHECK-DAG: Abs       loop:<<Loop2>>      outer_loop:none
-  /// CHECK-DAG: ArraySet  loop:<<Loop2>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  ///     CHECK-DAG: VecPredWhile loop:<<Loop1>> outer_loop:none
+  ///     CHECK-NOT: ArrayGet
+  ///     CHECK-NOT: Abs
+  ///     CHECK-NOT: ArraySet
   //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: ArrayGet  loop:<<Loop2:B\d+>> outer_loop:none
+  ///     CHECK-DAG: Abs       loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: ArraySet  loop:<<Loop2>>      outer_loop:none
+  //
+  ///     CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  //
+  /// CHECK-FI:
   private static void doitCastedChar(char[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = (char) Math.abs((short) x[i]);
@@ -109,7 +160,7 @@
   /// CHECK-DAG: Abs       loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: ArraySet  loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void Main.doitInt(int[]) loop_optimization (after)
+  /// CHECK-START-ARM: void Main.doitInt(int[]) loop_optimization (after)
   /// CHECK-DAG: VecLoad   loop:<<Loop1:B\d+>> outer_loop:none
   /// CHECK-DAG: VecAbs    loop:<<Loop1>>      outer_loop:none
   /// CHECK-DAG: VecStore  loop:<<Loop1>>      outer_loop:none
@@ -119,6 +170,26 @@
   //
   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
   //
+  /// CHECK-START-ARM64: void Main.doitInt(int[]) loop_optimization (after)
+  /// CHECK-DAG: VecLoad   loop:<<Loop1:B\d+>> outer_loop:none
+  /// CHECK-DAG: VecAbs    loop:<<Loop1>>      outer_loop:none
+  /// CHECK-DAG: VecStore  loop:<<Loop1>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: VecPredWhile loop:<<Loop1>> outer_loop:none
+  ///     CHECK-NOT: ArrayGet
+  ///     CHECK-NOT: Abs
+  ///     CHECK-NOT: ArraySet
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: ArrayGet  loop:<<Loop2:B\d+>> outer_loop:none
+  ///     CHECK-DAG: Abs       loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: ArraySet  loop:<<Loop2>>      outer_loop:none
+  //
+  ///     CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  //
+  /// CHECK-FI:
   private static void doitInt(int[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = Math.abs(x[i]);
@@ -135,12 +206,22 @@
   /// CHECK-DAG: VecLoad   loop:<<Loop1:B\d+>> outer_loop:none
   /// CHECK-DAG: VecAbs    loop:<<Loop1>>      outer_loop:none
   /// CHECK-DAG: VecStore  loop:<<Loop1>>      outer_loop:none
-  /// CHECK-DAG: ArrayGet  loop:<<Loop2:B\d+>> outer_loop:none
-  /// CHECK-DAG: Abs       loop:<<Loop2>>      outer_loop:none
-  /// CHECK-DAG: ArraySet  loop:<<Loop2>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  ///     CHECK-DAG: VecPredWhile loop:<<Loop1>> outer_loop:none
+  ///     CHECK-NOT: ArrayGet
+  ///     CHECK-NOT: Abs
+  ///     CHECK-NOT: ArraySet
   //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: ArrayGet  loop:<<Loop2:B\d+>> outer_loop:none
+  ///     CHECK-DAG: Abs       loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: ArraySet  loop:<<Loop2>>      outer_loop:none
+  //
+  ///     CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  //
+  /// CHECK-FI:
   private static void doitLong(long[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = Math.abs(x[i]);
@@ -157,12 +238,22 @@
   /// CHECK-DAG: VecLoad   loop:<<Loop1:B\d+>> outer_loop:none
   /// CHECK-DAG: VecAbs    loop:<<Loop1>>      outer_loop:none
   /// CHECK-DAG: VecStore  loop:<<Loop1>>      outer_loop:none
-  /// CHECK-DAG: ArrayGet  loop:<<Loop2:B\d+>> outer_loop:none
-  /// CHECK-DAG: Abs       loop:<<Loop2>>      outer_loop:none
-  /// CHECK-DAG: ArraySet  loop:<<Loop2>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  ///     CHECK-DAG: VecPredWhile loop:<<Loop1>> outer_loop:none
+  ///     CHECK-NOT: ArrayGet
+  ///     CHECK-NOT: Abs
+  ///     CHECK-NOT: ArraySet
   //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: ArrayGet  loop:<<Loop2:B\d+>> outer_loop:none
+  ///     CHECK-DAG: Abs       loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: ArraySet  loop:<<Loop2>>      outer_loop:none
+  //
+  ///     CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  //
+  /// CHECK-FI:
   private static void doitFloat(float[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = Math.abs(x[i]);
@@ -179,12 +270,22 @@
   /// CHECK-DAG: VecLoad    loop:<<Loop1:B\d+>> outer_loop:none
   /// CHECK-DAG: VecAbs     loop:<<Loop1>>      outer_loop:none
   /// CHECK-DAG: VecStore   loop:<<Loop1>>      outer_loop:none
-  /// CHECK-DAG: ArrayGet   loop:<<Loop2:B\d+>> outer_loop:none
-  /// CHECK-DAG: Abs        loop:<<Loop2>>      outer_loop:none
-  /// CHECK-DAG: ArraySet   loop:<<Loop2>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  ///     CHECK-DAG: VecPredWhile loop:<<Loop1>> outer_loop:none
+  ///     CHECK-NOT: ArrayGet
+  ///     CHECK-NOT: Abs
+  ///     CHECK-NOT: ArraySet
   //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: ArrayGet   loop:<<Loop2:B\d+>> outer_loop:none
+  ///     CHECK-DAG: Abs        loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: ArraySet   loop:<<Loop2>>      outer_loop:none
+  //
+  ///     CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  //
+  /// CHECK-FI:
   private static void doitDouble(double[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = Math.abs(x[i]);
diff --git a/test/646-checker-arraycopy-large-cst-pos/Android.bp b/test/646-checker-arraycopy-large-cst-pos/Android.bp
new file mode 100644
index 0000000..983c9df
--- /dev/null
+++ b/test/646-checker-arraycopy-large-cst-pos/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `646-checker-arraycopy-large-cst-pos`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-646-checker-arraycopy-large-cst-pos",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-646-checker-arraycopy-large-cst-pos-expected-stdout",
+        ":art-run-test-646-checker-arraycopy-large-cst-pos-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-646-checker-arraycopy-large-cst-pos-expected-stdout",
+    out: ["art-run-test-646-checker-arraycopy-large-cst-pos-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-646-checker-arraycopy-large-cst-pos-expected-stderr",
+    out: ["art-run-test-646-checker-arraycopy-large-cst-pos-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/605-new-string-from-bytes/expected.txt b/test/646-checker-arraycopy-large-cst-pos/expected-stderr.txt
similarity index 100%
copy from test/605-new-string-from-bytes/expected.txt
copy to test/646-checker-arraycopy-large-cst-pos/expected-stderr.txt
diff --git a/test/646-checker-arraycopy-large-cst-pos/expected.txt b/test/646-checker-arraycopy-large-cst-pos/expected-stdout.txt
similarity index 100%
rename from test/646-checker-arraycopy-large-cst-pos/expected.txt
rename to test/646-checker-arraycopy-large-cst-pos/expected-stdout.txt
diff --git a/test/646-checker-long-const-to-int/Android.bp b/test/646-checker-long-const-to-int/Android.bp
new file mode 100644
index 0000000..be5cf75
--- /dev/null
+++ b/test/646-checker-long-const-to-int/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `646-checker-long-const-to-int`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-646-checker-long-const-to-int",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-646-checker-long-const-to-int-expected-stdout",
+        ":art-run-test-646-checker-long-const-to-int-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-646-checker-long-const-to-int-expected-stdout",
+    out: ["art-run-test-646-checker-long-const-to-int-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-646-checker-long-const-to-int-expected-stderr",
+    out: ["art-run-test-646-checker-long-const-to-int-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/436-shift-constant/expected.txt b/test/646-checker-long-const-to-int/expected-stderr.txt
similarity index 100%
copy from test/436-shift-constant/expected.txt
copy to test/646-checker-long-const-to-int/expected-stderr.txt
diff --git a/test/646-checker-long-const-to-int/expected.txt b/test/646-checker-long-const-to-int/expected-stdout.txt
similarity index 100%
rename from test/646-checker-long-const-to-int/expected.txt
rename to test/646-checker-long-const-to-int/expected-stdout.txt
diff --git a/test/646-checker-simd-hadd/Android.bp b/test/646-checker-simd-hadd/Android.bp
new file mode 100644
index 0000000..12df43d
--- /dev/null
+++ b/test/646-checker-simd-hadd/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `646-checker-simd-hadd`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-646-checker-simd-hadd",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-646-checker-simd-hadd-expected-stdout",
+        ":art-run-test-646-checker-simd-hadd-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-646-checker-simd-hadd-expected-stdout",
+    out: ["art-run-test-646-checker-simd-hadd-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-646-checker-simd-hadd-expected-stderr",
+    out: ["art-run-test-646-checker-simd-hadd-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/641-checker-arraycopy/expected.txt b/test/646-checker-simd-hadd/expected-stderr.txt
similarity index 100%
copy from test/641-checker-arraycopy/expected.txt
copy to test/646-checker-simd-hadd/expected-stderr.txt
diff --git a/test/646-checker-simd-hadd/expected-stdout.txt b/test/646-checker-simd-hadd/expected-stdout.txt
new file mode 100644
index 0000000..e2b68e7
--- /dev/null
+++ b/test/646-checker-simd-hadd/expected-stdout.txt
@@ -0,0 +1,7 @@
+HaddAltByte passed
+HaddAltShort passed
+HaddAltChar passed
+HaddByte passed
+HaddShort passed
+HaddChar passed
+HaddOther passed
diff --git a/test/646-checker-simd-hadd/expected.txt b/test/646-checker-simd-hadd/expected.txt
deleted file mode 100644
index 93b1f4f..0000000
--- a/test/646-checker-simd-hadd/expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-HaddAltByte passed
-HaddAltShort passed
-HaddAltChar passed
-HaddByte passed
-HaddShort passed
-HaddChar passed
diff --git a/test/646-checker-simd-hadd/src/HaddAltByte.java b/test/646-checker-simd-hadd/src/HaddAltByte.java
index 28551ee..69d4602 100644
--- a/test/646-checker-simd-hadd/src/HaddAltByte.java
+++ b/test/646-checker-simd-hadd/src/HaddAltByte.java
@@ -39,11 +39,26 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltByte.halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltByte.halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int8 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltByte.halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int8 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_signed(byte[] b1, byte[] b2, byte[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -74,11 +89,26 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltByte.halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltByte.halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint8 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltByte.halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint8 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned(byte[] b1, byte[] b2, byte[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -97,11 +127,26 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltByte.rounding_halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltByte.rounding_halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int8 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltByte.rounding_halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int8 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_signed(byte[] b1, byte[] b2, byte[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -134,11 +179,26 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltByte.rounding_halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltByte.rounding_halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>]  packed_type:Uint8 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltByte.rounding_halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>]  packed_type:Uint8 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_unsigned(byte[] b1, byte[] b2, byte[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -156,12 +216,28 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltByte.halving_add_signed_constant(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltByte.halving_add_signed_constant(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<I127:i\d+>> IntConstant 127                       loop:none
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I127>>]         loop:none
   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Int8 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltByte.halving_add_signed_constant(byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<I127:i\d+>> IntConstant 127                       loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I127>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Int8 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_signed_constant(byte[] b1, byte[] bo) {
     int min_length = Math.min(bo.length, b1.length);
     for (int i = 0; i < min_length; i++) {
@@ -190,12 +266,28 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltByte.halving_add_unsigned_constant(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltByte.halving_add_unsigned_constant(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<I255:i\d+>> IntConstant 255                       loop:none
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I255>>]         loop:none
   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint8 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltByte.halving_add_unsigned_constant(byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<I255:i\d+>> IntConstant 255                       loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I255>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint8 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned_constant(byte[] b1, byte[] bo) {
     int min_length = Math.min(bo.length, b1.length);
     for (int i = 0; i < min_length; i++) {
diff --git a/test/646-checker-simd-hadd/src/HaddAltChar.java b/test/646-checker-simd-hadd/src/HaddAltChar.java
index 2dd812d..f9d40a9 100644
--- a/test/646-checker-simd-hadd/src/HaddAltChar.java
+++ b/test/646-checker-simd-hadd/src/HaddAltChar.java
@@ -39,11 +39,26 @@
   /// CHECK-DAG: <<Cnv:c\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltChar.halving_add_unsigned(char[], char[], char[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltChar.halving_add_unsigned(char[], char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltChar.halving_add_unsigned(char[], char[], char[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned(char[] b1, char[] b2, char[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -75,12 +90,27 @@
   /// CHECK-DAG: <<Cnv:c\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltChar.halving_add_also_unsigned(char[], char[], char[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltChar.halving_add_also_unsigned(char[], char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
   //
+  /// CHECK-START-ARM64: void HaddAltChar.halving_add_also_unsigned(char[], char[], char[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
+  //
   // Note: HAnd has no impact (already a zero extension).
   //
   private static void halving_add_also_unsigned(char[] b1, char[] b2, char[] bo) {
@@ -101,11 +131,26 @@
   /// CHECK-DAG: <<Cnv:c\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltChar.rounding_halving_add_unsigned(char[], char[], char[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltChar.rounding_halving_add_unsigned(char[], char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltChar.rounding_halving_add_unsigned(char[], char[], char[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_unsigned(char[] b1, char[] b2, char[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -138,12 +183,28 @@
   /// CHECK-DAG: <<Cnv:c\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltChar.rounding_halving_add_also_unsigned(char[], char[], char[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltChar.rounding_halving_add_also_unsigned(char[], char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
   //
+  //
+  /// CHECK-START-ARM64: void HaddAltChar.rounding_halving_add_also_unsigned(char[], char[], char[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
+  //
   // Note: HAnd has no impact (already a zero extension).
   //
   private static void rounding_halving_add_also_unsigned(char[] b1, char[] b2, char[] bo) {
@@ -163,12 +224,28 @@
   /// CHECK-DAG: <<Cnv:c\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltChar.halving_add_unsigned_constant(char[], char[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltChar.halving_add_unsigned_constant(char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltChar.halving_add_unsigned_constant(char[], char[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned_constant(char[] b1, char[] bo) {
     int min_length = Math.min(bo.length, b1.length);
     for (int i = 0; i < min_length; i++) {
@@ -197,13 +274,29 @@
   /// CHECK-DAG: <<Cnv:c\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltChar.halving_add_also_unsigned_constant(char[], char[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltChar.halving_add_also_unsigned_constant(char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
   //
+  /// CHECK-START-ARM64: void HaddAltChar.halving_add_also_unsigned_constant(char[], char[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
+  //
   // Note: HAnd has no impact (already a zero extension).
   //
   private static void halving_add_also_unsigned_constant(char[] b1, char[] bo) {
diff --git a/test/646-checker-simd-hadd/src/HaddAltShort.java b/test/646-checker-simd-hadd/src/HaddAltShort.java
index d7f4e40..3b19a26 100644
--- a/test/646-checker-simd-hadd/src/HaddAltShort.java
+++ b/test/646-checker-simd-hadd/src/HaddAltShort.java
@@ -39,11 +39,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltShort.halving_add_signed(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltShort.halving_add_signed(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltShort.halving_add_signed(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_signed(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -74,11 +89,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltShort.halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltShort.halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltShort.halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -99,11 +129,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltShort.rounding_halving_add_signed(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltShort.rounding_halving_add_signed(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltShort.rounding_halving_add_signed(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_signed(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -136,11 +181,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltShort.rounding_halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltShort.rounding_halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltShort.rounding_halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -160,12 +220,28 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltShort.halving_add_signed_constant(short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltShort.halving_add_signed_constant(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<SMAX:i\d+>> IntConstant 32767                     loop:none
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<SMAX>>]         loop:none
   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltShort.halving_add_signed_constant(short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<SMAX:i\d+>> IntConstant 32767                     loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<SMAX>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_signed_constant(short[] b1, short[] bo) {
     int min_length = Math.min(bo.length, b1.length);
     for (int i = 0; i < min_length; i++) {
@@ -194,12 +270,28 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<UShr>>]           loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddAltShort.halving_add_unsigned_constant(short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddAltShort.halving_add_unsigned_constant(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddAltShort.halving_add_unsigned_constant(short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned_constant(short[] b1, short[] bo) {
     int min_length = Math.min(bo.length, b1.length);
     for (int i = 0; i < min_length; i++) {
diff --git a/test/646-checker-simd-hadd/src/HaddByte.java b/test/646-checker-simd-hadd/src/HaddByte.java
index 9c99390..c8bb0aa 100644
--- a/test/646-checker-simd-hadd/src/HaddByte.java
+++ b/test/646-checker-simd-hadd/src/HaddByte.java
@@ -36,11 +36,26 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddByte.halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddByte.halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int8 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddByte.halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int8 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_signed(byte[] b1, byte[] b2, byte[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -71,11 +86,26 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddByte.halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddByte.halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint8 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddByte.halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint8 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned(byte[] b1, byte[] b2, byte[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -94,11 +124,26 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddByte.rounding_halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddByte.rounding_halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int8 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddByte.rounding_halving_add_signed(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int8 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_signed(byte[] b1, byte[] b2, byte[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -131,11 +176,26 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddByte.rounding_halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddByte.rounding_halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>]  packed_type:Uint8 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddByte.rounding_halving_add_unsigned(byte[], byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>]  packed_type:Uint8 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_unsigned(byte[] b1, byte[] b2, byte[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -153,12 +213,28 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddByte.halving_add_signed_constant(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddByte.halving_add_signed_constant(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<I127:i\d+>> IntConstant 127                       loop:none
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I127>>]         loop:none
   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Int8 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddByte.halving_add_signed_constant(byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<I127:i\d+>> IntConstant 127                       loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I127>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Int8 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_signed_constant(byte[] b1, byte[] bo) {
     int min_length = Math.min(bo.length, b1.length);
     for (int i = 0; i < min_length; i++) {
@@ -187,12 +263,28 @@
   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddByte.halving_add_unsigned_constant(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddByte.halving_add_unsigned_constant(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<I255:i\d+>> IntConstant 255                       loop:none
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I255>>]         loop:none
   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint8 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddByte.halving_add_unsigned_constant(byte[], byte[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<I255:i\d+>> IntConstant 255                       loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I255>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint8 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned_constant(byte[] b1, byte[] bo) {
     int min_length = Math.min(bo.length, b1.length);
     for (int i = 0; i < min_length; i++) {
diff --git a/test/646-checker-simd-hadd/src/HaddChar.java b/test/646-checker-simd-hadd/src/HaddChar.java
index 255863e..236b081 100644
--- a/test/646-checker-simd-hadd/src/HaddChar.java
+++ b/test/646-checker-simd-hadd/src/HaddChar.java
@@ -43,10 +43,19 @@
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-ARM64: void HaddChar.halving_add_unsigned(char[], char[], char[]) loop_optimization (after)
-  /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned(char[] b1, char[] b2, char[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -84,10 +93,19 @@
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-ARM64: void HaddChar.halving_add_also_unsigned(char[], char[], char[]) loop_optimization (after)
-  /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   //
   // Note: HAnd has no impact (already a zero extension).
   //
@@ -116,10 +134,19 @@
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-ARM64: void HaddChar.rounding_halving_add_unsigned(char[], char[], char[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_unsigned(char[] b1, char[] b2, char[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -159,10 +186,19 @@
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-ARM64: void HaddChar.rounding_halving_add_also_unsigned(char[], char[], char[]) loop_optimization (after)
-  /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   //
   // Note: HAnd has no impact (already a zero extension).
   //
@@ -191,10 +227,19 @@
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-ARM64: void HaddChar.halving_add_unsigned_constant(char[], char[]) loop_optimization (after)
-  /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
-  /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned_constant(char[] b1, char[] bo) {
     int min_length = Math.min(bo.length, b1.length);
     for (int i = 0; i < min_length; i++) {
@@ -231,11 +276,20 @@
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-ARM64: void HaddChar.halving_add_also_unsigned_constant(char[], char[]) loop_optimization (after)
-  /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
-  /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   //
   // Note: HAnd has no impact (already a zero extension).
   //
diff --git a/test/646-checker-simd-hadd/src/HaddOther.java b/test/646-checker-simd-hadd/src/HaddOther.java
new file mode 100644
index 0000000..139df83
--- /dev/null
+++ b/test/646-checker-simd-hadd/src/HaddOther.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2020 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 HaddOther {
+  private static final int N = 2 * 1024;
+  private static final int M = N + 31;
+
+  //  Should be just shift right, not halving add.
+  //
+  /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_short2short(short[], short[]) loop_optimization (after)
+  /// CHECK: VecShr
+
+  /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_short2short(short[], short[]) loop_optimization (after)
+  /// CHECK-NOT: VecHalvingAdd
+  private static void test_no_hadd_short2short(short[] a, short[] out) {
+    int min_length = Math.min(out.length, a.length);
+    for (int i = 0; i < min_length; i++) {
+      out[i] = (short) (a[i] >> 1);
+    }
+  }
+
+  //  This loop is not vectorized: shift right with a signed type is not supported.
+  //
+  /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_short2short_logical(short[], short[]) loop_optimization (after)
+  /// CHECK-NOT: VecLoad
+  /// CHECK-NOT: VecHalvingAdd
+  private static void test_no_hadd_short2short_logical(short[] a, short[] out) {
+    int min_length = Math.min(out.length, a.length);
+    for (int i = 0; i < min_length; i++) {
+      out[i] = (short) (a[i] >>> 1);
+    }
+  }
+
+  //  This loop is not vectorized: mismatched packed type size.
+  //
+  /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_int2short(int[], short[]) loop_optimization (after)
+  /// CHECK-NOT: VecLoad
+  /// CHECK-NOT: VecHalvingAdd
+  private static void test_no_hadd_int2short(int[] a, short[] out) {
+    int min_length = Math.min(out.length, a.length);
+    for (int i = 0; i < min_length; i++) {
+      out[i] = (short) (a[i] >> 1);
+    }
+  }
+
+  //  Should be just shift right, not halving add.
+  //
+  /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_int2int(int[], int[]) loop_optimization (after)
+  /// CHECK: VecShr
+
+  /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_int2int(int[], int[]) loop_optimization (after)
+  /// CHECK-NOT: VecHalvingAdd
+  private static void test_no_hadd_int2int(int[] a, int[] out) {
+    int min_length = Math.min(out.length, a.length);
+    for (int i = 0; i < min_length; i++) {
+      out[i] = a[i] >> 1;
+    }
+  }
+
+  //  Should be just add and shift right, not halving add.
+  //
+  /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_sum_casted(short[], short[], short[]) loop_optimization (after)
+  /// CHECK: VecAdd
+  /// CHECK: VecShr
+
+  /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_sum_casted(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-NOT: VecHalvingAdd
+  private static void test_no_hadd_sum_casted(short[] a, short[] b, short[] out) {
+    int min_length = Math.min(out.length, Math.min(a.length, b.length));
+    for (int i = 0; i < min_length; i++) {
+      out[i] = (short) (((short) (a[i] + b[i])) >> 1);
+    }
+  }
+
+  //  This loop is not vectorized: mismatched packed type size.
+  //
+  /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_sum_casted_ints(int[], int[], int[]) loop_optimization (after)
+  /// CHECK-NOT: VecLoad
+  /// CHECK-NOT: VecHalvingAdd
+  private static void test_no_hadd_sum_casted_ints(int[] a, int[] b, int[] out) {
+    int min_length = Math.min(out.length, Math.min(a.length, b.length));
+    for (int i = 0; i < min_length; i++) {
+      out[i] = (short) ((short) (a[i] + b[i]) >> 1);
+    }
+  }
+
+  //  Should be an add, followed by a halving add.
+  //
+  /// CHECK-START-ARM: void HaddOther.test_no_hadd_sum_casted_plus_const(short[], short[], short[]) loop_optimization (after)
+  /// CHECK: VecAdd
+  /// CHECK: VecHalvingAdd
+  //
+  /// CHECK-START-ARM64: void HaddOther.test_no_hadd_sum_casted_plus_const(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK: VecAdd
+  ///     CHECK: VecHalvingAdd
+  //
+  /// CHECK-FI:
+  private static void test_no_hadd_sum_casted_plus_const(short[] a, short[] b, short[] out) {
+    int min_length = Math.min(out.length, Math.min(a.length, b.length));
+    for (int i = 0; i < min_length; i++) {
+      out[i] = (short) (((short) (a[i] + b[i]) + 1) >> 1);
+    }
+  }
+
+  public static void main() {
+    short[] sA = new short[M];
+    short[] sB = new short[M];
+    short[] sOut = new short[M];
+    int[] iA = new int[M];
+    int[] iB = new int[M];
+    int[] iOut = new int[M];
+
+    // Some interesting values.
+    short[] interesting = {
+      (short) 0x0000,
+      (short) 0x0001,
+      (short) 0x0002,
+      (short) 0x1234,
+      (short) 0x8000,
+      (short) 0x8001,
+      (short) 0x7fff,
+      (short) 0xffff
+    };
+    // Initialize cross-values to test all cases, and also
+    // set up some extra values to exercise the cleanup loop.
+    for (int i = 0; i < M; i++) {
+      sA[i] = (short) i;
+      sB[i] = interesting[i & 7];
+      iA[i] = i;
+      iB[i] = interesting[i & 7];
+    }
+
+    test_no_hadd_short2short(sA, sOut);
+    for (int i = 0; i < M; i++) {
+      short e = (short) (sA[i] >> 1);
+      expectEquals(e, sOut[i]);
+    }
+    test_no_hadd_short2short_logical(sA, sOut);
+    for (int i = 0; i < M; i++) {
+      short e = (short) (sA[i] >>> 1);
+      expectEquals(e, sOut[i]);
+    }
+    test_no_hadd_int2short(iA, sOut);
+    for (int i = 0; i < M; i++) {
+      short e = (short) (iA[i] >> 1);
+      expectEquals(e, sOut[i]);
+    }
+    test_no_hadd_int2int(iA, iOut);
+    for (int i = 0; i < M; i++) {
+      int e = iA[i] >> 1;
+      expectEquals(e, iOut[i]);
+    }
+    test_no_hadd_sum_casted(sA, sB, sOut);
+    for (int i = 0; i < M; i++) {
+      short e = (short) (((short) (sA[i] + sB[i])) >> 1);
+      expectEquals(e, sOut[i]);
+    }
+    test_no_hadd_sum_casted_ints(iA, iB, iOut);
+    for (int i = 0; i < M; i++) {
+      int e = (short) ((short) (iA[i] + iB[i]) >> 1);
+      expectEquals(e, iOut[i]);
+    }
+    test_no_hadd_sum_casted_plus_const(sA, sB, sOut);
+    for (int i = 0; i < M; i++) {
+      short e = (short) (((short) (sA[i] + sB[i]) + 1) >> 1);
+      expectEquals(e, sOut[i]);
+    }
+
+    System.out.println("HaddOther passed");
+  }
+
+  private static void expectEquals(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+}
diff --git a/test/646-checker-simd-hadd/src/HaddShort.java b/test/646-checker-simd-hadd/src/HaddShort.java
index 4102efd..9880a7a 100644
--- a/test/646-checker-simd-hadd/src/HaddShort.java
+++ b/test/646-checker-simd-hadd/src/HaddShort.java
@@ -40,11 +40,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.halving_add_signed(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.halving_add_signed(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.halving_add_signed(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
+  /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_signed(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -66,11 +81,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.halving_add_signed_alt(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.halving_add_signed_alt(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.halving_add_signed_alt(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_signed_alt(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -102,11 +132,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -127,11 +172,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.rounding_halving_add_signed(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.rounding_halving_add_signed(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.rounding_halving_add_signed(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_signed(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -150,11 +210,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.rounding_halving_add_signed_alt(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.rounding_halving_add_signed_alt(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.rounding_halving_add_signed_alt(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_signed_alt(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -177,11 +252,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.rounding_halving_add_signed_alt2(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.rounding_halving_add_signed_alt2(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.rounding_halving_add_signed_alt2(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_signed_alt2(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -206,11 +296,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.rounding_halving_add_signed_alt3(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.rounding_halving_add_signed_alt3(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.rounding_halving_add_signed_alt3(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_signed_alt3(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -244,11 +349,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.rounding_halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.rounding_halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.rounding_halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -283,11 +403,26 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.rounding_halving_add_unsigned_alt(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.rounding_halving_add_unsigned_alt(short[], short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.rounding_halving_add_unsigned_alt(short[], short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void rounding_halving_add_unsigned_alt(short[] b1, short[] b2, short[] bo) {
     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     for (int i = 0; i < min_length; i++) {
@@ -308,12 +443,28 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.halving_add_signed_constant(short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.halving_add_signed_constant(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<SMAX:i\d+>> IntConstant 32767                     loop:none
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<SMAX>>]         loop:none
   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.halving_add_signed_constant(short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<SMAX:i\d+>> IntConstant 32767                     loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<SMAX>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_signed_constant(short[] b1, short[] bo) {
     int min_length = Math.min(bo.length, b1.length);
     for (int i = 0; i < min_length; i++) {
@@ -342,12 +493,28 @@
   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: void HaddShort.halving_add_unsigned_constant(short[], short[]) loop_optimization (after)
+  /// CHECK-START-ARM: void HaddShort.halving_add_unsigned_constant(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void HaddShort.halving_add_unsigned_constant(short[], short[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      HalvingAdd idiom is not supported for SVE.
+  ///     CHECK-NOT: VecHalvingAdd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
+  ///     CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void halving_add_unsigned_constant(short[] b1, short[] bo) {
     int min_length = Math.min(bo.length, b1.length);
     for (int i = 0; i < min_length; i++) {
diff --git a/test/646-checker-simd-hadd/src/Main.java b/test/646-checker-simd-hadd/src/Main.java
index c5ec7a7..1fb1de2 100644
--- a/test/646-checker-simd-hadd/src/Main.java
+++ b/test/646-checker-simd-hadd/src/Main.java
@@ -22,5 +22,6 @@
     HaddByte.main();
     HaddShort.main();
     HaddChar.main();
+    HaddOther.main();
   }
 }
diff --git a/test/647-jni-get-field-id/Android.bp b/test/647-jni-get-field-id/Android.bp
new file mode 100644
index 0000000..f3bb8a5
--- /dev/null
+++ b/test/647-jni-get-field-id/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `647-jni-get-field-id`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-647-jni-get-field-id",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-647-jni-get-field-id-expected-stdout",
+        ":art-run-test-647-jni-get-field-id-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-647-jni-get-field-id-expected-stdout",
+    out: ["art-run-test-647-jni-get-field-id-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-647-jni-get-field-id-expected-stderr",
+    out: ["art-run-test-647-jni-get-field-id-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/647-jni-get-field-id/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/647-jni-get-field-id/expected-stderr.txt
diff --git a/test/647-jni-get-field-id/expected.txt b/test/647-jni-get-field-id/expected-stdout.txt
similarity index 100%
rename from test/647-jni-get-field-id/expected.txt
rename to test/647-jni-get-field-id/expected-stdout.txt
diff --git a/test/689-multi-catch/expected.txt b/test/647-sinking-catch/expected-stderr.txt
similarity index 100%
copy from test/689-multi-catch/expected.txt
copy to test/647-sinking-catch/expected-stderr.txt
diff --git a/test/647-sinking-catch/expected.txt b/test/647-sinking-catch/expected-stdout.txt
similarity index 100%
rename from test/647-sinking-catch/expected.txt
rename to test/647-sinking-catch/expected-stdout.txt
diff --git a/test/585-inline-unresolved/expected.txt b/test/648-inline-caches-unresolved/expected-stderr.txt
similarity index 100%
copy from test/585-inline-unresolved/expected.txt
copy to test/648-inline-caches-unresolved/expected-stderr.txt
diff --git a/test/648-inline-caches-unresolved/expected.txt b/test/648-inline-caches-unresolved/expected-stdout.txt
similarity index 100%
rename from test/648-inline-caches-unresolved/expected.txt
rename to test/648-inline-caches-unresolved/expected-stdout.txt
diff --git a/test/406-fields/expected.txt b/test/648-many-direct-methods/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/648-many-direct-methods/expected-stderr.txt
diff --git a/test/648-many-direct-methods/expected.txt b/test/648-many-direct-methods/expected-stdout.txt
similarity index 100%
rename from test/648-many-direct-methods/expected.txt
rename to test/648-many-direct-methods/expected-stdout.txt
diff --git a/test/470-huge-method/expected.txt b/test/649-vdex-duplicate-method/expected-stderr.txt
similarity index 100%
copy from test/470-huge-method/expected.txt
copy to test/649-vdex-duplicate-method/expected-stderr.txt
diff --git a/test/649-vdex-duplicate-method/expected.txt b/test/649-vdex-duplicate-method/expected-stdout.txt
similarity index 100%
rename from test/649-vdex-duplicate-method/expected.txt
rename to test/649-vdex-duplicate-method/expected-stdout.txt
diff --git a/test/650-checker-inline-access-thunks/Android.bp b/test/650-checker-inline-access-thunks/Android.bp
new file mode 100644
index 0000000..2b98cce
--- /dev/null
+++ b/test/650-checker-inline-access-thunks/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `650-checker-inline-access-thunks`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-650-checker-inline-access-thunks",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-650-checker-inline-access-thunks-expected-stdout",
+        ":art-run-test-650-checker-inline-access-thunks-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-650-checker-inline-access-thunks-expected-stdout",
+    out: ["art-run-test-650-checker-inline-access-thunks-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-650-checker-inline-access-thunks-expected-stderr",
+    out: ["art-run-test-650-checker-inline-access-thunks-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/650-checker-inline-access-thunks/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/650-checker-inline-access-thunks/expected-stderr.txt
diff --git a/test/650-checker-inline-access-thunks/expected.txt b/test/650-checker-inline-access-thunks/expected-stdout.txt
similarity index 100%
rename from test/650-checker-inline-access-thunks/expected.txt
rename to test/650-checker-inline-access-thunks/expected-stdout.txt
diff --git a/test/652-deopt-intrinsic/Android.bp b/test/652-deopt-intrinsic/Android.bp
new file mode 100644
index 0000000..53f406a
--- /dev/null
+++ b/test/652-deopt-intrinsic/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `652-deopt-intrinsic`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-652-deopt-intrinsic",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-652-deopt-intrinsic-expected-stdout",
+        ":art-run-test-652-deopt-intrinsic-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-652-deopt-intrinsic-expected-stdout",
+    out: ["art-run-test-652-deopt-intrinsic-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-652-deopt-intrinsic-expected-stderr",
+    out: ["art-run-test-652-deopt-intrinsic-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/643-checker-bogus-ic/expected.txt b/test/652-deopt-intrinsic/expected-stderr.txt
similarity index 100%
copy from test/643-checker-bogus-ic/expected.txt
copy to test/652-deopt-intrinsic/expected-stderr.txt
diff --git a/test/652-deopt-intrinsic/expected.txt b/test/652-deopt-intrinsic/expected-stdout.txt
similarity index 100%
rename from test/652-deopt-intrinsic/expected.txt
rename to test/652-deopt-intrinsic/expected-stdout.txt
diff --git a/test/654-checker-periodic/Android.bp b/test/654-checker-periodic/Android.bp
new file mode 100644
index 0000000..79e38bb
--- /dev/null
+++ b/test/654-checker-periodic/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `654-checker-periodic`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-654-checker-periodic",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-654-checker-periodic-expected-stdout",
+        ":art-run-test-654-checker-periodic-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-654-checker-periodic-expected-stdout",
+    out: ["art-run-test-654-checker-periodic-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-654-checker-periodic-expected-stderr",
+    out: ["art-run-test-654-checker-periodic-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/643-checker-bogus-ic/expected.txt b/test/654-checker-periodic/expected-stderr.txt
similarity index 100%
copy from test/643-checker-bogus-ic/expected.txt
copy to test/654-checker-periodic/expected-stderr.txt
diff --git a/test/654-checker-periodic/expected.txt b/test/654-checker-periodic/expected-stdout.txt
similarity index 100%
rename from test/654-checker-periodic/expected.txt
rename to test/654-checker-periodic/expected-stdout.txt
diff --git a/test/655-checker-simd-arm-opt/Android.bp b/test/655-checker-simd-arm-opt/Android.bp
new file mode 100644
index 0000000..50f18fe
--- /dev/null
+++ b/test/655-checker-simd-arm-opt/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `655-checker-simd-arm-opt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-655-checker-simd-arm-opt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-655-checker-simd-arm-opt-expected-stdout",
+        ":art-run-test-655-checker-simd-arm-opt-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-655-checker-simd-arm-opt-expected-stdout",
+    out: ["art-run-test-655-checker-simd-arm-opt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-655-checker-simd-arm-opt-expected-stderr",
+    out: ["art-run-test-655-checker-simd-arm-opt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/513-array-deopt/expected.txt b/test/655-checker-simd-arm-opt/expected-stderr.txt
similarity index 100%
copy from test/513-array-deopt/expected.txt
copy to test/655-checker-simd-arm-opt/expected-stderr.txt
diff --git a/test/655-checker-simd-arm-opt/expected.txt b/test/655-checker-simd-arm-opt/expected-stdout.txt
similarity index 100%
rename from test/655-checker-simd-arm-opt/expected.txt
rename to test/655-checker-simd-arm-opt/expected-stdout.txt
diff --git a/test/655-checker-simd-arm-opt/src/Main.java b/test/655-checker-simd-arm-opt/src/Main.java
index 7b61dd7..980593d 100644
--- a/test/655-checker-simd-arm-opt/src/Main.java
+++ b/test/655-checker-simd-arm-opt/src/Main.java
@@ -27,49 +27,74 @@
 
   /// CHECK-START-ARM64: void Main.encodableConstants(byte[], short[], char[], int[], long[], float[], double[]) disassembly (after)
   /// CHECK-DAG: <<C1:i\d+>>   IntConstant 1
-  /// CHECK-DAG: <<C2:i\d+>>   IntConstant 2
-  /// CHECK-DAG: <<C3:i\d+>>   IntConstant 3
-  /// CHECK-DAG: <<C4:i\d+>>   IntConstant 4
-  /// CHECK-DAG: <<L5:j\d+>>   LongConstant 5
-  /// CHECK-DAG: <<F2:f\d+>>   FloatConstant 2
-  /// CHECK-DAG: <<D20:d\d+>>  DoubleConstant 20
+  /// CHECK-DAG: <<C2:i\d+>>   IntConstant -128
+  /// CHECK-DAG: <<C3:i\d+>>   IntConstant 127
+  /// CHECK-DAG: <<C4:i\d+>>   IntConstant -219
+  /// CHECK-DAG: <<C5:i\d+>>   IntConstant 219
+  /// CHECK-DAG: <<L6:j\d+>>   LongConstant 219
+  /// CHECK-DAG: <<F7:f\d+>>   FloatConstant 2
+  /// CHECK-DAG: <<F8:f\d+>>   FloatConstant 14.34
+  /// CHECK-DAG: <<D9:d\d+>>   DoubleConstant 20
+  /// CHECK-DAG: <<D10:d\d+>>  DoubleConstant 0
   //
-  /// CHECK-DAG:               VecReplicateScalar [<<C1>>]
-  /// CHECK-DAG:               movi v{{[0-9]+}}.16b, #0x1
-  /// CHECK-DAG:               VecReplicateScalar [<<C2>>]
-  /// CHECK-DAG:               movi v{{[0-9]+}}.8h, #0x2, lsl #0
-  /// CHECK-DAG:               VecReplicateScalar [<<C3>>]
-  /// CHECK-DAG:               movi v{{[0-9]+}}.8h, #0x3, lsl #0
-  /// CHECK-DAG:               VecReplicateScalar [<<C4>>]
-  /// CHECK-DAG:               movi v{{[0-9]+}}.4s, #0x4, lsl #0
-  /// CHECK-DAG:               VecReplicateScalar [<<L5>>]
-  /// CHECK-DAG:               dup v{{[0-9]+}}.2d, x{{[0-9]+}}
-  /// CHECK-DAG:               VecReplicateScalar [<<F2>>]
-  /// CHECK-DAG:               fmov v{{[0-9]+}}.4s, #0x0
-  /// CHECK-DAG:               VecReplicateScalar [<<D20>>]
-  /// CHECK-DAG:               fmov v{{[0-9]+}}.2d, #0x34
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG:               VecReplicateScalar [<<C1>>,{{j\d+}}]
+  ///     CHECK-DAG:               VecReplicateScalar [<<C2>>,{{j\d+}}]
+  ///     CHECK-DAG:               VecReplicateScalar [<<C3>>,{{j\d+}}]
+  ///     CHECK-DAG:               VecReplicateScalar [<<C4>>,{{j\d+}}]
+  ///     CHECK-DAG:               VecReplicateScalar [<<C5>>,{{j\d+}}]
+  ///     CHECK-DAG:               VecReplicateScalar [<<L6>>,{{j\d+}}]
+  ///     CHECK-DAG:               VecReplicateScalar [<<F7>>,{{j\d+}}]
+  ///     CHECK-DAG:               VecReplicateScalar [<<F8>>,{{j\d+}}]
+  ///     CHECK-DAG:               VecReplicateScalar [<<D9>>,{{j\d+}}]
+  ///     CHECK-DAG:               VecReplicateScalar [<<D10>>,{{j\d+}}]
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:               VecReplicateScalar [<<C1>>]
+  ///     CHECK-DAG:               VecReplicateScalar [<<C2>>]
+  ///     CHECK-DAG:               VecReplicateScalar [<<C3>>]
+  ///     CHECK-DAG:               VecReplicateScalar [<<C4>>]
+  ///     CHECK-DAG:               VecReplicateScalar [<<C5>>]
+  ///     CHECK-DAG:               VecReplicateScalar [<<L6>>]
+  ///     CHECK-DAG:               VecReplicateScalar [<<F7>>]
+  ///     CHECK-DAG:               VecReplicateScalar [<<F8>>]
+  ///     CHECK-DAG:               VecReplicateScalar [<<D9>>]
+  ///     CHECK-DAG:               VecReplicateScalar [<<D10>>]
+  //
+  /// CHECK-FI:
   private static void encodableConstants(byte[] b, short[] s, char[] c, int[] a, long[] l, float[] f, double[] d) {
     for (int i = 0; i < ARRAY_SIZE; i++) {
       b[i] += 1;
     }
     for (int i = 0; i < ARRAY_SIZE; i++) {
-      s[i] += 2;
+      s[i] += -128;
     }
     for (int i = 0; i < ARRAY_SIZE; i++) {
-      c[i] += 3;
+      c[i] += 127;
     }
     for (int i = 0; i < ARRAY_SIZE; i++) {
-      a[i] += 4;
+      a[i] += -219;
     }
     for (int i = 0; i < ARRAY_SIZE; i++) {
-      l[i] += 5;
+      a[i] += 219;
+    }
+    for (int i = 0; i < ARRAY_SIZE; i++) {
+      l[i] += 219;
     }
     for (int i = 0; i < ARRAY_SIZE; i++) {
       f[i] += 2.0f;
     }
     for (int i = 0; i < ARRAY_SIZE; i++) {
+      f[i] += 14.34f;
+    }
+    for (int i = 0; i < ARRAY_SIZE; i++) {
       d[i] += 20.0;
     }
+    for (int i = 0; i < ARRAY_SIZE; i++) {
+      d[i] += 0.0;
+    }
   }
 
   private static int sumArray(byte[] b, short[] s, char[] c, int[] a, long[] l, float[] f, double[] d) {
@@ -80,7 +105,7 @@
     return sum;
   }
 
-  public static final int ARRAY_SIZE = 100;
+  public static final int ARRAY_SIZE = 128;
 
   public static void main(String[] args) {
     byte[] b = new byte[ARRAY_SIZE];
@@ -92,7 +117,7 @@
     double[] d = new double[ARRAY_SIZE];
 
     encodableConstants(b, s, c, a, l, f, d);
-    expectEquals(3700, sumArray(b, s, c, a, l, f, d));
+    expectEquals(32640, sumArray(b, s, c, a, l, f, d));
 
     System.out.println("passed");
   }
diff --git a/test/655-jit-clinit/Android.bp b/test/655-jit-clinit/Android.bp
new file mode 100644
index 0000000..00e3365
--- /dev/null
+++ b/test/655-jit-clinit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `655-jit-clinit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-655-jit-clinit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-655-jit-clinit-expected-stdout",
+        ":art-run-test-655-jit-clinit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-655-jit-clinit-expected-stdout",
+    out: ["art-run-test-655-jit-clinit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-655-jit-clinit-expected-stderr",
+    out: ["art-run-test-655-jit-clinit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/551-checker-clinit/expected.txt b/test/655-jit-clinit/expected-stderr.txt
similarity index 100%
copy from test/551-checker-clinit/expected.txt
copy to test/655-jit-clinit/expected-stderr.txt
diff --git a/test/655-jit-clinit/expected.txt b/test/655-jit-clinit/expected-stdout.txt
similarity index 100%
rename from test/655-jit-clinit/expected.txt
rename to test/655-jit-clinit/expected-stdout.txt
diff --git a/test/656-annotation-lookup-generic-jni/check b/test/656-annotation-lookup-generic-jni/check
index 39a52d5..e02c84d 100755
--- a/test/656-annotation-lookup-generic-jni/check
+++ b/test/656-annotation-lookup-generic-jni/check
@@ -14,8 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # On gcstress configurations, an extra "JNI_OnUnload called" line may
 # be emitted. If so, remove it.
 sed -e '${/^JNI_OnUnload called$/d;}' "$2" > "$2.tmp"
 
-./default-check "$1" "$2.tmp"
+./default-check "$1" "$2.tmp" "$3" "$4"
diff --git a/test/658-fp-read-barrier/expected.txt b/test/656-annotation-lookup-generic-jni/expected-stderr.txt
similarity index 100%
copy from test/658-fp-read-barrier/expected.txt
copy to test/656-annotation-lookup-generic-jni/expected-stderr.txt
diff --git a/test/656-annotation-lookup-generic-jni/expected.txt b/test/656-annotation-lookup-generic-jni/expected-stdout.txt
similarity index 100%
rename from test/656-annotation-lookup-generic-jni/expected.txt
rename to test/656-annotation-lookup-generic-jni/expected-stdout.txt
diff --git a/test/656-annotation-lookup-generic-jni/src-art/Main.java b/test/656-annotation-lookup-generic-jni/src-art/Main.java
index 01b288a..ed37506 100644
--- a/test/656-annotation-lookup-generic-jni/src-art/Main.java
+++ b/test/656-annotation-lookup-generic-jni/src-art/Main.java
@@ -48,7 +48,7 @@
     Method nativeMethodWithAnnotation = testClass.getMethod("nativeMethodWithAnnotation");
     // Invoking the native method Test.nativeMethodWithAnnotation used
     // to crash the Generic JNI trampoline during the resolution of
-    // the method's annotations (DummyAnnotation) (see b/38454151).
+    // the method's annotations (SampleAnnotation) (see b/38454151).
     nativeMethodWithAnnotation.invoke(null);
 
     zipFile.close();
diff --git a/test/656-annotation-lookup-generic-jni/src-ex/DummyAnnotation.java b/test/656-annotation-lookup-generic-jni/src-ex/DummyAnnotation.java
deleted file mode 100644
index 6caac66..0000000
--- a/test/656-annotation-lookup-generic-jni/src-ex/DummyAnnotation.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2017 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 @interface DummyAnnotation {}
diff --git a/test/656-annotation-lookup-generic-jni/src-ex/SampleAnnotation.java b/test/656-annotation-lookup-generic-jni/src-ex/SampleAnnotation.java
new file mode 100644
index 0000000..775dd9c
--- /dev/null
+++ b/test/656-annotation-lookup-generic-jni/src-ex/SampleAnnotation.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2017 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 @interface SampleAnnotation {}
diff --git a/test/656-annotation-lookup-generic-jni/src-ex/Test.java b/test/656-annotation-lookup-generic-jni/src-ex/Test.java
index 838b4fe..359a9df 100644
--- a/test/656-annotation-lookup-generic-jni/src-ex/Test.java
+++ b/test/656-annotation-lookup-generic-jni/src-ex/Test.java
@@ -22,7 +22,7 @@
     System.loadLibrary(libname);
   }
 
-  @DummyAnnotation
+  @SampleAnnotation
   public static native void nativeMethodWithAnnotation();
 
 }
diff --git a/test/656-annotation-lookup-generic-jni/test.cc b/test/656-annotation-lookup-generic-jni/test.cc
index c8aa2af..172e046 100644
--- a/test/656-annotation-lookup-generic-jni/test.cc
+++ b/test/656-annotation-lookup-generic-jni/test.cc
@@ -20,7 +20,7 @@
 
 namespace art {
 
-// Native method annotated with `DummyAnnotation` in Java source.
+// Native method annotated with `SampleAnnotation` in Java source.
 extern "C" JNIEXPORT void JNICALL Java_Test_nativeMethodWithAnnotation(JNIEnv*, jclass) {
   std::cout << "Java_Test_nativeMethodWithAnnotation" << std::endl;
 }
diff --git a/test/656-checker-simd-opt/Android.bp b/test/656-checker-simd-opt/Android.bp
new file mode 100644
index 0000000..2b72352
--- /dev/null
+++ b/test/656-checker-simd-opt/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `656-checker-simd-opt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-656-checker-simd-opt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-656-checker-simd-opt-expected-stdout",
+        ":art-run-test-656-checker-simd-opt-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-656-checker-simd-opt-expected-stdout",
+    out: ["art-run-test-656-checker-simd-opt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-656-checker-simd-opt-expected-stderr",
+    out: ["art-run-test-656-checker-simd-opt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/513-array-deopt/expected.txt b/test/656-checker-simd-opt/expected-stderr.txt
similarity index 100%
copy from test/513-array-deopt/expected.txt
copy to test/656-checker-simd-opt/expected-stderr.txt
diff --git a/test/656-checker-simd-opt/expected.txt b/test/656-checker-simd-opt/expected-stdout.txt
similarity index 100%
rename from test/656-checker-simd-opt/expected.txt
rename to test/656-checker-simd-opt/expected-stdout.txt
diff --git a/test/656-checker-simd-opt/smali/Smali.smali b/test/656-checker-simd-opt/smali/Smali.smali
deleted file mode 100644
index 802bcab..0000000
--- a/test/656-checker-simd-opt/smali/Smali.smali
+++ /dev/null
@@ -1,121 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-.class public LSmali;
-.super Ljava/lang/Object;
-
-## CHECK-START: void Smali.stencilSubInt(int[], int[], int) loop_optimization (before)
-## CHECK-DAG: <<PAR3:i\d+>>  ParameterValue                       loop:none
-## CHECK-DAG: <<CP1:i\d+>>   IntConstant 1                        loop:none
-## CHECK-DAG: <<Sub1:i\d+>>  Sub [<<PAR3>>,<<CP1>>]               loop:none
-## CHECK-DAG: <<Phi:i\d+>>   Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-## CHECK-DAG: <<Sub2:i\d+>>  Sub [<<Phi>>,<<CP1>>]                loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get1:i\d+>>  ArrayGet [{{l\d+}},<<Sub2>>]         loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get2:i\d+>>  ArrayGet [{{l\d+}},<<Phi>>]          loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add1:i\d+>>  Add [<<Get1>>,<<Get2>>]              loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add2:i\d+>>  Add [<<Phi>>,<<CP1>>]                loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get3:i\d+>>  ArrayGet [{{l\d+}},<<Add2>>]         loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add3:i\d+>>  Add [<<Add1>>,<<Get3>>]              loop:<<Loop>>      outer_loop:none
-## CHECK-DAG:                ArraySet [{{l\d+}},<<Phi>>,<<Add3>>] loop:<<Loop>>      outer_loop:none
-
-## CHECK-START-ARM64: void Smali.stencilSubInt(int[], int[], int) loop_optimization (after)
-## CHECK-DAG: <<CP1:i\d+>>   IntConstant 1                         loop:none
-## CHECK-DAG: <<CP2:i\d+>>   IntConstant 2                         loop:none
-## CHECK-DAG: <<Phi:i\d+>>   Phi                                   loop:<<Loop:B\d+>> outer_loop:none
-## CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CP1>>]                 loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>]            loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get2:d\d+>>  VecLoad [{{l\d+}},<<Add1>>]           loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add2:d\d+>>  VecAdd [<<Get1>>,<<Get2>>]            loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP2>>]                 loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get3:d\d+>>  VecLoad [{{l\d+}},<<Add3>>]           loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add4:d\d+>>  VecAdd [<<Add2>>,<<Get3>>]            loop:<<Loop>>      outer_loop:none
-## CHECK-DAG:                VecStore [{{l\d+}},<<Add1>>,<<Add4>>] loop:<<Loop>>      outer_loop:none
-.method public static stencilSubInt([I[II)V
-    .registers 7
-
-    const/4 v0, 0x1
-
-    move v1, v0
-
-    :goto_2
-    sub-int v2, p2, v0
-
-    if-ge v1, v2, :cond_17
-
-    sub-int v2, v1, v0
-    aget v2, p1, v2
-    aget v3, p1, v1
-    add-int/2addr v2, v3
-    add-int v3, v1, v0
-    aget v3, p1, v3
-    add-int/2addr v2, v3
-    aput v2, p0, v1
-    add-int/lit8 v1, v1, 0x1
-
-    goto :goto_2
-
-    :cond_17
-    return-void
-.end method
-
-## CHECK-START: void Smali.stencilAddInt(int[], int[], int) loop_optimization (before)
-## CHECK-DAG: <<CP1:i\d+>>   IntConstant 1                        loop:none
-## CHECK-DAG: <<CM1:i\d+>>   IntConstant -1                       loop:none
-## CHECK-DAG: <<Phi:i\d+>>   Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-## CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CM1>>]                loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get1:i\d+>>  ArrayGet [{{l\d+}},<<Add1>>]         loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get2:i\d+>>  ArrayGet [{{l\d+}},<<Phi>>]          loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add2:i\d+>>  Add [<<Get1>>,<<Get2>>]              loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP1>>]                loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get3:i\d+>>  ArrayGet [{{l\d+}},<<Add3>>]         loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add4:i\d+>>  Add [<<Add2>>,<<Get3>>]              loop:<<Loop>>      outer_loop:none
-## CHECK-DAG:                ArraySet [{{l\d+}},<<Phi>>,<<Add4>>] loop:<<Loop>>      outer_loop:none
-
-## CHECK-START-ARM64: void Smali.stencilAddInt(int[], int[], int) loop_optimization (after)
-## CHECK-DAG: <<CP1:i\d+>>   IntConstant 1                         loop:none
-## CHECK-DAG: <<CP2:i\d+>>   IntConstant 2                         loop:none
-## CHECK-DAG: <<Phi:i\d+>>   Phi                                   loop:<<Loop:B\d+>> outer_loop:none
-## CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CP1>>]                 loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>]            loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get2:d\d+>>  VecLoad [{{l\d+}},<<Add1>>]           loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add2:d\d+>>  VecAdd [<<Get1>>,<<Get2>>]            loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP2>>]                 loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Get3:d\d+>>  VecLoad [{{l\d+}},<<Add3>>]           loop:<<Loop>>      outer_loop:none
-## CHECK-DAG: <<Add4:d\d+>>  VecAdd [<<Add2>>,<<Get3>>]            loop:<<Loop>>      outer_loop:none
-## CHECK-DAG:                VecStore [{{l\d+}},<<Add1>>,<<Add4>>] loop:<<Loop>>      outer_loop:none
-.method public static stencilAddInt([I[II)V
-    .registers 6
-
-    const/4 v0, 0x1
-
-    :goto_1
-    add-int/lit8 v1, p2, -0x1
-
-    if-ge v0, v1, :cond_16
-
-    add-int/lit8 v1, v0, -0x1
-    aget v1, p1, v1
-    aget v2, p1, v0
-    add-int/2addr v1, v2
-    add-int/lit8 v2, v0, 0x1
-    aget v2, p1, v2
-    add-int/2addr v1, v2
-    aput v1, p0, v0
-    add-int/lit8 v0, v0, 0x1
-
-    goto :goto_1
-
-    :cond_16
-    return-void
-.end method
diff --git a/test/656-checker-simd-opt/src/Main.java b/test/656-checker-simd-opt/src/Main.java
index 39a126f..be8c52f 100644
--- a/test/656-checker-simd-opt/src/Main.java
+++ b/test/656-checker-simd-opt/src/Main.java
@@ -30,18 +30,35 @@
   //
   /// CHECK-START-ARM64: void Main.unroll(float[], float[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons:f\d+>> FloatConstant 2.5                    loop:none
-  /// CHECK-DAG: <<Incr:i\d+>> IntConstant 4                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Cons>>]        loop:none
-  /// CHECK-NOT:               VecReplicateScalar
-  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Get1:d\d+>> VecLoad [{{l\d+}},<<Phi>>]           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Mul1:d\d+>> VecMul [<<Get1>>,<<Repl>>]           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Mul1>>] loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Add:i\d+>>  Add [<<Phi>>,<<Incr>>]               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get2:d\d+>> VecLoad [{{l\d+}},<<Add>>]           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Mul2:d\d+>> VecMul [<<Get2>>,<<Repl>>]           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Add>>,<<Mul2>>] loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:               Add [<<Add>>,<<Incr>>]               loop:<<Loop>>      outer_loop:none
+
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<Cons>>,{{j\d+}}]         loop:none
+  ///     CHECK-NOT:                VecReplicateScalar
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi                                            loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile [<<Phi>>,{{i\d+}}]                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>,<<LoopP>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Mul1:d\d+>>  VecMul [<<Get1>>,<<Repl>>,<<LoopP>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi>>,<<Mul1>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add:i\d+>>   Add [<<Phi>>,{{i\d+}}]                         loop:<<Loop>>      outer_loop:none
+  //      No unroll for SVE yet.
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Incr:i\d+>>  IntConstant 4                        loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<Cons>>]        loop:none
+  ///     CHECK-NOT:                VecReplicateScalar
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Mul1:d\d+>>  VecMul [<<Get1>>,<<Repl>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi>>,<<Mul1>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add:i\d+>>   Add [<<Phi>>,<<Incr>>]               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>>  VecLoad [{{l\d+}},<<Add>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Mul2:d\d+>>  VecMul [<<Get2>>,<<Repl>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Add>>,<<Mul2>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                Add [<<Add>>,<<Incr>>]               loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void unroll(float[] x, float[] y) {
     for (int i = 0; i < 100; i++) {
       x[i] = y[i] * 2.5f;
@@ -51,47 +68,145 @@
   /// CHECK-START-ARM64: void Main.stencil(int[], int[], int) loop_optimization (after)
   /// CHECK-DAG: <<CP1:i\d+>>   IntConstant 1                         loop:none
   /// CHECK-DAG: <<CP2:i\d+>>   IntConstant 2                         loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>   Phi                                   loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CP1>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>]            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get2:d\d+>>  VecLoad [{{l\d+}},<<Add1>>]           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Add2:d\d+>>  VecAdd [<<Get1>>,<<Get2>>]            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP2>>]                 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get3:d\d+>>  VecLoad [{{l\d+}},<<Add3>>]           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Add4:d\d+>>  VecAdd [<<Add2>>,<<Get3>>]            loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                VecStore [{{l\d+}},<<Add1>>,<<Add4>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi                                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile [<<Phi>>,{{i\d+}}]                 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CP1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>,<<LoopP>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>>  VecLoad [{{l\d+}},<<Add1>>,<<LoopP>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add2:d\d+>>  VecAdd [<<Get1>>,<<Get2>>,<<LoopP>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP2>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get3:d\d+>>  VecLoad [{{l\d+}},<<Add3>>,<<LoopP>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add4:d\d+>>  VecAdd [<<Add2>>,<<Get3>>,<<LoopP>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Add1>>,<<Add4>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CP1>>]                 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>>  VecLoad [{{l\d+}},<<Add1>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add2:d\d+>>  VecAdd [<<Get1>>,<<Get2>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP2>>]                 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get3:d\d+>>  VecLoad [{{l\d+}},<<Add3>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add4:d\d+>>  VecAdd [<<Add2>>,<<Get3>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Add1>>,<<Add4>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void stencil(int[] a, int[] b, int n) {
     for (int i = 1; i < n - 1; i++) {
       a[i] = b[i - 1] + b[i] + b[i + 1];
     }
   }
 
+  /// CHECK-START: void Main.stencilAddInt(int[], int[], int) loop_optimization (before)
+  /// CHECK-DAG: <<CP1:i\d+>>   IntConstant 1                        loop:none
+  /// CHECK-DAG: <<CM1:i\d+>>   IntConstant -1                       loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>   Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CM1>>]                loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Get1:i\d+>>  ArrayGet [{{l\d+}},<<Add1>>]         loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Get2:i\d+>>  ArrayGet [{{l\d+}},<<Phi>>]          loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Add2:i\d+>>  Add [<<Get1>>,<<Get2>>]              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP1>>]                loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Get3:i\d+>>  ArrayGet [{{l\d+}},<<Add3>>]         loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Add4:i\d+>>  Add [<<Add2>>,<<Get3>>]              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:                ArraySet [{{l\d+}},<<Phi>>,<<Add4>>] loop:<<Loop>>      outer_loop:none
+
+  /// CHECK-START-{X86_64,ARM64}: void Main.stencilAddInt(int[], int[], int) loop_optimization (after)
+  /// CHECK-DAG: <<CP1:i\d+>>   IntConstant 1                         loop:none
+  /// CHECK-DAG: <<CP2:i\d+>>   IntConstant 2                         loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi                                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile [<<Phi>>,{{i\d+}}]                 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CP1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>,<<LoopP>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>>  VecLoad [{{l\d+}},<<Add1>>,<<LoopP>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add2:d\d+>>  VecAdd [<<Get1>>,<<Get2>>,<<LoopP>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP2>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get3:d\d+>>  VecLoad [{{l\d+}},<<Add3>>,<<LoopP>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add4:d\d+>>  VecAdd [<<Add2>>,<<Get3>>,<<LoopP>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Add1>>,<<Add4>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CP1>>]                 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>>  VecLoad [{{l\d+}},<<Add1>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add2:d\d+>>  VecAdd [<<Get1>>,<<Get2>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP2>>]                 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get3:d\d+>>  VecLoad [{{l\d+}},<<Add3>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add4:d\d+>>  VecAdd [<<Add2>>,<<Get3>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Add1>>,<<Add4>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void stencilAddInt(int[] a, int[] b, int n) {
-    try {
-      Class<?> c = Class.forName("Smali");
-      Method m = c.getMethod("stencilAddInt",
-          Array.newInstance(int.class, 1).getClass(),
-          Array.newInstance(int.class, 1).getClass(),
-          int.class);
-      m.invoke(null, a, b, n);
-    } catch (Exception ex) {
-      throw new Error(ex);
+    int minus1 = $inline$constMinus1();
+    for (int i = 1; i < n + minus1; i++) {
+      a[i] = b[i + minus1] + b[i] + b[i + 1];
     }
   }
 
+  private static int $inline$constMinus1() {
+    return -1;
+  }
+
+  /// CHECK-START: void Main.stencilSubInt(int[], int[], int) loop_optimization (before)
+  /// CHECK-DAG: <<PAR3:i\d+>>  ParameterValue                       loop:none
+  /// CHECK-DAG: <<CP1:i\d+>>   IntConstant 1                        loop:none
+  /// CHECK-DAG: <<Sub1:i\d+>>  Sub [<<PAR3>>,<<CP1>>]               loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>   Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Sub2:i\d+>>  Sub [<<Phi>>,<<CP1>>]                loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Get1:i\d+>>  ArrayGet [{{l\d+}},<<Sub2>>]         loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Get2:i\d+>>  ArrayGet [{{l\d+}},<<Phi>>]          loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Add1:i\d+>>  Add [<<Get1>>,<<Get2>>]              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Add2:i\d+>>  Add [<<Phi>>,<<CP1>>]                loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Get3:i\d+>>  ArrayGet [{{l\d+}},<<Add2>>]         loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Add3:i\d+>>  Add [<<Add1>>,<<Get3>>]              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:                ArraySet [{{l\d+}},<<Phi>>,<<Add3>>] loop:<<Loop>>      outer_loop:none
+
+  /// CHECK-START-{X86_64,ARM64}: void Main.stencilSubInt(int[], int[], int) loop_optimization (after)
+  /// CHECK-DAG: <<CP1:i\d+>>   IntConstant 1                         loop:none
+  /// CHECK-DAG: <<CP2:i\d+>>   IntConstant 2                         loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi                                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile [<<Phi>>,{{i\d+}}]                 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CP1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>,<<LoopP>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>>  VecLoad [{{l\d+}},<<Add1>>,<<LoopP>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add2:d\d+>>  VecAdd [<<Get1>>,<<Get2>>,<<LoopP>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP2>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get3:d\d+>>  VecLoad [{{l\d+}},<<Add3>>,<<LoopP>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add4:d\d+>>  VecAdd [<<Add2>>,<<Get3>>,<<LoopP>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Add1>>,<<Add4>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Add1:i\d+>>  Add [<<Phi>>,<<CP1>>]                 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get1:d\d+>>  VecLoad [{{l\d+}},<<Phi>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get2:d\d+>>  VecLoad [{{l\d+}},<<Add1>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add2:d\d+>>  VecAdd [<<Get1>>,<<Get2>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add3:i\d+>>  Add [<<Phi>>,<<CP2>>]                 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Get3:d\d+>>  VecLoad [{{l\d+}},<<Add3>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add4:d\d+>>  VecAdd [<<Add2>>,<<Get3>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Add1>>,<<Add4>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void stencilSubInt(int[] a, int[] b, int n) {
-    try {
-      Class<?> c = Class.forName("Smali");
-      Method m = c.getMethod("stencilSubInt",
-          Array.newInstance(int.class, 1).getClass(),
-          Array.newInstance(int.class, 1).getClass(),
-          int.class);
-      m.invoke(null, a, b, n);
-    } catch (Exception ex) {
-      throw new Error(ex);
+    int plus1 = $inline$constPlus1();
+    for (int i = 1; i < n - plus1; i++) {
+      a[i] = b[i - plus1] + b[i] + b[i + 1];
     }
   }
 
+  private static int $inline$constPlus1() {
+    return 1;
+  }
+
   /// CHECK-START: long Main.longInductionReduction(long[]) loop_optimization (before)
   /// CHECK-DAG: <<L0:j\d+>>    LongConstant 0             loop:none
   /// CHECK-DAG: <<L1:j\d+>>    LongConstant 1             loop:none
@@ -105,15 +220,29 @@
   /// CHECK-START-ARM64: long Main.longInductionReduction(long[]) loop_optimization (after)
   /// CHECK-DAG: <<L0:j\d+>>    LongConstant 0               loop:none
   /// CHECK-DAG: <<L1:j\d+>>    LongConstant 1               loop:none
-  /// CHECK-DAG: <<L2:j\d+>>    LongConstant 2               loop:none
   /// CHECK-DAG: <<I0:i\d+>>    IntConstant 0                loop:none
   /// CHECK-DAG: <<Get:j\d+>>   ArrayGet [{{l\d+}},<<I0>>]   loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Get>>] loop:none
-  /// CHECK-DAG: <<Set:d\d+>>   VecSetScalars [<<L1>>]       loop:none
-  /// CHECK-DAG: <<Phi1:j\d+>>  Phi [<<L0>>,{{j\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>  Phi [<<Set>>,{{d\d+}}]       loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                VecAdd [<<Phi2>>,<<Rep>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                Add [<<Phi1>>,<<L2>>]        loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Get>>,{{j\d+}}]  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>   VecSetScalars [<<L1>>,{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi1:j\d+>>  Phi [<<L0>>,{{j\d+}}]                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>  Phi [<<Set>>,{{d\d+}}]                 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile [<<Phi1>>,{{j\d+}}]       loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecAdd [<<Phi2>>,<<Rep>>,<<LoopP>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                Add [<<Phi1>>,{{j\d+}}]                loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<L2:j\d+>>    LongConstant 2               loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Get>>] loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>   VecSetScalars [<<L1>>]       loop:none
+  ///     CHECK-DAG: <<Phi1:j\d+>>  Phi [<<L0>>,{{j\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>  Phi [<<Set>>,{{d\d+}}]       loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecAdd [<<Phi2>>,<<Rep>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                Add [<<Phi1>>,<<L2>>]        loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static long longInductionReduction(long[] y) {
     long x = 1;
     for (long i = 0; i < 10; i++) {
@@ -134,13 +263,25 @@
   /// CHECK-START-ARM64: void Main.intVectorLongInvariant(int[], long[]) loop_optimization (after)
   /// CHECK-DAG: <<I0:i\d+>>    IntConstant 0                       loop:none
   /// CHECK-DAG: <<I1:i\d+>>    IntConstant 1                       loop:none
-  /// CHECK-DAG: <<I4:i\d+>>    IntConstant 4                       loop:none
   /// CHECK-DAG: <<Get:j\d+>>   ArrayGet [{{l\d+}},<<I0>>]          loop:none
   /// CHECK-DAG: <<Cnv:i\d+>>   TypeConversion [<<Get>>]            loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Cnv>>]        loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<I0>>,{{i\d+}}]               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:                VecStore [{{l\d+}},<<Phi>>,<<Rep>>] loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                Add [<<Phi>>,<<I4>>]                loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Cnv>>,{{j\d+}}]         loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi [<<I0>>,{{i\d+}}]                         loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile [<<Phi>>,{{i\d+}}]               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi>>,<<Rep>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                Add [<<Phi>>,{{i\d+}}]                        loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<I4:i\d+>>    IntConstant 4                       loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Cnv>>]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi [<<I0>>,{{i\d+}}]               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi>>,<<Rep>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                Add [<<Phi>>,<<I4>>]                loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static void intVectorLongInvariant(int[] x, long[] y) {
     for (int i = 0; i < 100; i++) {
       x[i] = (int) y[0];
@@ -161,15 +302,29 @@
   //
   /// CHECK-START-ARM64: void Main.longCanBeDoneWithInt(int[], int[]) loop_optimization (after)
   /// CHECK-DAG: <<I0:i\d+>>    IntConstant 0                       loop:none
-  /// CHECK-DAG: <<I4:i\d+>>    IntConstant 4                       loop:none
   /// CHECK-DAG: <<L1:j\d+>>    LongConstant 1                      loop:none
   /// CHECK-DAG: <<Cnv:i\d+>>   TypeConversion [<<L1>>]             loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Cnv>>]        loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<I0>>,{{i\d+}}]               loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>  VecLoad [{{l\d+}},<<Phi>>]          loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Add:d\d+>>   VecAdd [<<Load>>,<<Rep>>]           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                VecStore [{{l\d+}},<<Phi>>,<<Add>>] loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                Add [<<Phi>>,<<I4>>]                loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Cnv>>,{{j\d+}}]         loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi [<<I0>>,{{i\d+}}]                         loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile [<<Phi>>,{{i\d+}}]               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>  VecLoad [{{l\d+}},<<Phi>>,<<LoopP>>]          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add:d\d+>>   VecAdd [<<Load>>,<<Rep>>,<<LoopP>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi>>,<<Add>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                Add [<<Phi>>,{{i\d+}}]                        loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<I4:i\d+>>    IntConstant 4                       loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Cnv>>]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>   Phi [<<I0>>,{{i\d+}}]               loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>  VecLoad [{{l\d+}},<<Phi>>]          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add:d\d+>>   VecAdd [<<Load>>,<<Rep>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                VecStore [{{l\d+}},<<Phi>>,<<Add>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                Add [<<Phi>>,<<I4>>]                loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static void longCanBeDoneWithInt(int[] x, int[] y) {
     for (int i = 0; i < 100; i++) {
       x[i] = (int) (y[i] + 1L);
diff --git a/test/656-loop-deopt/Android.bp b/test/656-loop-deopt/Android.bp
new file mode 100644
index 0000000..3ca3822
--- /dev/null
+++ b/test/656-loop-deopt/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `656-loop-deopt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-656-loop-deopt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-656-loop-deopt-expected-stdout",
+        ":art-run-test-656-loop-deopt-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-656-loop-deopt-expected-stdout",
+    out: ["art-run-test-656-loop-deopt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-656-loop-deopt-expected-stderr",
+    out: ["art-run-test-656-loop-deopt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/513-array-deopt/expected.txt b/test/656-loop-deopt/expected-stderr.txt
similarity index 100%
copy from test/513-array-deopt/expected.txt
copy to test/656-loop-deopt/expected-stderr.txt
diff --git a/test/656-loop-deopt/expected.txt b/test/656-loop-deopt/expected-stdout.txt
similarity index 100%
rename from test/656-loop-deopt/expected.txt
rename to test/656-loop-deopt/expected-stdout.txt
diff --git a/test/657-branches/Android.bp b/test/657-branches/Android.bp
new file mode 100644
index 0000000..70c422f
--- /dev/null
+++ b/test/657-branches/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `657-branches`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-657-branches",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-657-branches-expected-stdout",
+        ":art-run-test-657-branches-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-657-branches-expected-stdout",
+    out: ["art-run-test-657-branches-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-657-branches-expected-stderr",
+    out: ["art-run-test-657-branches-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/685-shifts/expected.txt b/test/657-branches/expected-stderr.txt
similarity index 100%
copy from test/685-shifts/expected.txt
copy to test/657-branches/expected-stderr.txt
diff --git a/test/657-branches/expected.txt b/test/657-branches/expected-stdout.txt
similarity index 100%
rename from test/657-branches/expected.txt
rename to test/657-branches/expected-stdout.txt
diff --git a/test/658-fp-read-barrier/Android.bp b/test/658-fp-read-barrier/Android.bp
new file mode 100644
index 0000000..fdb2b35
--- /dev/null
+++ b/test/658-fp-read-barrier/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `658-fp-read-barrier`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-658-fp-read-barrier",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-658-fp-read-barrier-expected-stdout",
+        ":art-run-test-658-fp-read-barrier-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-658-fp-read-barrier-expected-stdout",
+    out: ["art-run-test-658-fp-read-barrier-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-658-fp-read-barrier-expected-stderr",
+    out: ["art-run-test-658-fp-read-barrier-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/658-fp-read-barrier/expected.txt b/test/658-fp-read-barrier/expected-stderr.txt
similarity index 100%
rename from test/658-fp-read-barrier/expected.txt
rename to test/658-fp-read-barrier/expected-stderr.txt
diff --git a/test/658-fp-read-barrier/expected.txt b/test/658-fp-read-barrier/expected-stdout.txt
similarity index 100%
copy from test/658-fp-read-barrier/expected.txt
copy to test/658-fp-read-barrier/expected-stdout.txt
diff --git a/test/659-unpadded-array/expected.txt b/test/659-unpadded-array/expected-stderr.txt
similarity index 100%
rename from test/659-unpadded-array/expected.txt
rename to test/659-unpadded-array/expected-stderr.txt
diff --git a/test/659-unpadded-array/expected.txt b/test/659-unpadded-array/expected-stdout.txt
similarity index 100%
copy from test/659-unpadded-array/expected.txt
copy to test/659-unpadded-array/expected-stdout.txt
diff --git a/test/660-checker-sad/Android.bp b/test/660-checker-sad/Android.bp
new file mode 100644
index 0000000..76b8c7b
--- /dev/null
+++ b/test/660-checker-sad/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `660-checker-sad`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-660-checker-sad",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-660-checker-sad-expected-stdout",
+        ":art-run-test-660-checker-sad-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-660-checker-sad-expected-stdout",
+    out: ["art-run-test-660-checker-sad-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-660-checker-sad-expected-stderr",
+    out: ["art-run-test-660-checker-sad-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/660-store-8-16/expected.txt b/test/660-checker-sad/expected-stderr.txt
similarity index 100%
copy from test/660-store-8-16/expected.txt
copy to test/660-checker-sad/expected-stderr.txt
diff --git a/test/660-checker-sad/expected.txt b/test/660-checker-sad/expected-stdout.txt
similarity index 100%
rename from test/660-checker-sad/expected.txt
rename to test/660-checker-sad/expected-stdout.txt
diff --git a/test/660-checker-simd-sad/Android.bp b/test/660-checker-simd-sad/Android.bp
new file mode 100644
index 0000000..f751904
--- /dev/null
+++ b/test/660-checker-simd-sad/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `660-checker-simd-sad`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-660-checker-simd-sad",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-660-checker-simd-sad-expected-stdout",
+        ":art-run-test-660-checker-simd-sad-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-660-checker-simd-sad-expected-stdout",
+    out: ["art-run-test-660-checker-simd-sad-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-660-checker-simd-sad-expected-stderr",
+    out: ["art-run-test-660-checker-simd-sad-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/660-store-8-16/expected.txt b/test/660-checker-simd-sad/expected-stderr.txt
similarity index 100%
copy from test/660-store-8-16/expected.txt
copy to test/660-checker-simd-sad/expected-stderr.txt
diff --git a/test/660-checker-simd-sad/expected.txt b/test/660-checker-simd-sad/expected-stdout.txt
similarity index 100%
rename from test/660-checker-simd-sad/expected.txt
rename to test/660-checker-simd-sad/expected-stdout.txt
diff --git a/test/660-checker-simd-sad/src/SimdSadByte.java b/test/660-checker-simd-sad/src/SimdSadByte.java
index 11d0f21..0591fd1 100644
--- a/test/660-checker-simd-sad/src/SimdSadByte.java
+++ b/test/660-checker-simd-sad/src/SimdSadByte.java
@@ -101,14 +101,23 @@
   //
   /// CHECK-START-ARM64: int SimdSadByte.sadByte2Int(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons16:i\d+>> IntConstant 16                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons16>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons16:i\d+>> IntConstant 16                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons16>>]      loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadByte2Int(byte[] b1, byte[] b2) {
     int min_length = Math.min(b1.length, b2.length);
     int sad = 0;
@@ -132,14 +141,23 @@
   //
   /// CHECK-START-ARM64: int SimdSadByte.sadByte2IntAlt(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons16:i\d+>> IntConstant 16                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons16>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons16:i\d+>> IntConstant 16                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons16>>]      loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadByte2IntAlt(byte[] b1, byte[] b2) {
     int min_length = Math.min(b1.length, b2.length);
     int sad = 0;
@@ -165,14 +183,23 @@
   //
   /// CHECK-START-ARM64: int SimdSadByte.sadByte2IntAlt2(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons16:i\d+>> IntConstant 16                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons16>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons16:i\d+>> IntConstant 16                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons16>>]      loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadByte2IntAlt2(byte[] b1, byte[] b2) {
     int min_length = Math.min(b1.length, b2.length);
     int sad = 0;
@@ -190,6 +217,7 @@
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
+
   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<ConsL>>,{{j\d+}}]       loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Get1:b\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
@@ -203,15 +231,24 @@
   //
   /// CHECK-START-ARM64: long SimdSadByte.sadByte2Long(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons16:i\d+>> IntConstant 16                 loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons16>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons16:i\d+>> IntConstant 16                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons16>>]      loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadByte2Long(byte[] b1, byte[] b2) {
     int min_length = Math.min(b1.length, b2.length);
     long sad = 0;
@@ -240,15 +277,24 @@
   //
   /// CHECK-START-ARM64: long SimdSadByte.sadByte2LongAt1(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons16:i\d+>> IntConstant 16                 loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 1                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons16>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons16:i\d+>> IntConstant 16                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons16>>]      loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadByte2LongAt1(byte[] b1, byte[] b2) {
     int min_length = Math.min(b1.length, b2.length);
     long sad = 1;  // starts at 1
diff --git a/test/660-checker-simd-sad/src/SimdSadInt.java b/test/660-checker-simd-sad/src/SimdSadInt.java
index 08cdf98..74d87de 100644
--- a/test/660-checker-simd-sad/src/SimdSadInt.java
+++ b/test/660-checker-simd-sad/src/SimdSadInt.java
@@ -31,14 +31,32 @@
   /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: int SimdSadInt.sadInt2Int(int[], int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}                        loop:none
+  /// CHECK-START-ARM: int SimdSadInt.sadInt2Int(int[], int[]) loop_optimization (after)
+  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 2                              loop:none
   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]                   loop:none
   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                     loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Ld1:d\d+>>    VecLoad [{{l\d+}},<<I:i\d+>>]              loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Ld2:d\d+>>    VecLoad [{{l\d+}},<<I>>]                   loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi>>,<<Ld1>>,<<Ld2>>] loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]                       loop:<<Loop>> outer_loop:none
+  //
+  /// CHECK-START-ARM64: int SimdSadInt.sadInt2Int(int[], int[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons:i\d+>>   IntConstant 4                              loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]                   loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                     loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Ld1:d\d+>>    VecLoad [{{l\d+}},<<I:i\d+>>]              loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Ld2:d\d+>>    VecLoad [{{l\d+}},<<I>>]                   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi>>,<<Ld1>>,<<Ld2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,<<Cons>>]                       loop:<<Loop>> outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadInt2Int(int[] x, int[] y) {
     int min_length = Math.min(x.length, y.length);
     int sad = 0;
@@ -88,14 +106,32 @@
   /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: int SimdSadInt.sadInt2IntAlt2(int[], int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}                        loop:none
+  /// CHECK-START-ARM: int SimdSadInt.sadInt2IntAlt2(int[], int[]) loop_optimization (after)
+  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 2                              loop:none
   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]                   loop:none
   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                     loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Ld1:d\d+>>    VecLoad [{{l\d+}},<<I:i\d+>>]              loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Ld2:d\d+>>    VecLoad [{{l\d+}},<<I>>]                   loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi>>,<<Ld1>>,<<Ld2>>] loop:<<Loop>> outer_loop:none
   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]                       loop:<<Loop>> outer_loop:none
+  //
+  /// CHECK-START-ARM64: int SimdSadInt.sadInt2IntAlt2(int[], int[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons:i\d+>>   IntConstant 4                              loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]                   loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                     loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Ld1:d\d+>>    VecLoad [{{l\d+}},<<I:i\d+>>]              loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Ld2:d\d+>>    VecLoad [{{l\d+}},<<I>>]                   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi>>,<<Ld1>>,<<Ld2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,<<Cons>>]                       loop:<<Loop>> outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadInt2IntAlt2(int[] x, int[] y) {
     int min_length = Math.min(x.length, y.length);
     int sad = 0;
@@ -126,15 +162,24 @@
   //
   /// CHECK-START-ARM64: long SimdSadInt.sadInt2Long(int[], int[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons4:i\d+>>  IntConstant 4                  loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons4>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons4:i\d+>>  IntConstant 4                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons4>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadInt2Long(int[] x, int[] y) {
     int min_length = Math.min(x.length, y.length);
     long sad = 0;
@@ -163,15 +208,24 @@
   //
   /// CHECK-START-ARM64: long SimdSadInt.sadInt2LongAt1(int[], int[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons4:i\d+>>  IntConstant 4                  loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 1                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons4>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons4:i\d+>>  IntConstant 4                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons4>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadInt2LongAt1(int[] x, int[] y) {
     int min_length = Math.min(x.length, y.length);
     long sad = 1;  // starts at 1
diff --git a/test/660-checker-simd-sad/src/SimdSadLong.java b/test/660-checker-simd-sad/src/SimdSadLong.java
index 6a05963..149fad6 100644
--- a/test/660-checker-simd-sad/src/SimdSadLong.java
+++ b/test/660-checker-simd-sad/src/SimdSadLong.java
@@ -34,15 +34,24 @@
   //
   /// CHECK-START-ARM64: long SimdSadLong.sadLong2Long(long[], long[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                  loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons2>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons2>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadLong2Long(long[] x, long[] y) {
     int min_length = Math.min(x.length, y.length);
     long sad = 0;
@@ -96,15 +105,24 @@
   //
   /// CHECK-START-ARM64: long SimdSadLong.sadLong2LongAlt2(long[], long[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                  loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons2>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons2>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadLong2LongAlt2(long[] x, long[] y) {
     int min_length = Math.min(x.length, y.length);
     long sad = 0;
@@ -133,15 +151,24 @@
   //
   /// CHECK-START-ARM64: long SimdSadLong.sadLong2LongAt1(long[], long[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                  loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 1                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons2>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons2>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadLong2LongAt1(long[] x, long[] y) {
     int min_length = Math.min(x.length, y.length);
     long sad = 1;  // starts at 1
diff --git a/test/660-checker-simd-sad/src/SimdSadShort.java b/test/660-checker-simd-sad/src/SimdSadShort.java
index b6e4a14..0f1d08b 100644
--- a/test/660-checker-simd-sad/src/SimdSadShort.java
+++ b/test/660-checker-simd-sad/src/SimdSadShort.java
@@ -72,14 +72,23 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort.sadShort2Int(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2Int(short[] s1, short[] s2) {
     int min_length = Math.min(s1.length, s2.length);
     int sad = 0;
@@ -103,14 +112,23 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort.sadShort2IntAlt(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntAlt(short[] s1, short[] s2) {
     int min_length = Math.min(s1.length, s2.length);
     int sad = 0;
@@ -136,14 +154,23 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort.sadShort2IntAlt2(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntAlt2(short[] s1, short[] s2) {
     int min_length = Math.min(s1.length, s2.length);
     int sad = 0;
@@ -173,14 +200,23 @@
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 7                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Cons>>]  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Rep>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Cons>>]  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntConstant1(short[] s) {
     int sad = 0;
     for (int i = 0; i < s.length; i++) {
@@ -205,14 +241,23 @@
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 7                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Cons>>]  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Rep>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Cons>>]  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntConstant2(short[] s) {
     int sad = 0;
     for (int i = 0; i < s.length; i++) {
@@ -237,14 +282,23 @@
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant -7                 loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Cons>>]  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Rep>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Cons>>]  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntConstant3(short[] s) {
     int sad = 0;
     for (int i = 0; i < s.length; i++) {
@@ -270,15 +324,24 @@
   //
   /// CHECK-START-ARM64: long SimdSadShort.sadShort2Long(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadShort2Long(short[] s1, short[] s2) {
     int min_length = Math.min(s1.length, s2.length);
     long sad = 0;
@@ -307,15 +370,24 @@
   //
   /// CHECK-START-ARM64: long SimdSadShort.sadShort2LongAt1(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 1                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadShort2LongAt1(short[] s1, short[] s2) {
     int min_length = Math.min(s1.length, s2.length);
     long sad = 1;  // starts at 1
diff --git a/test/660-checker-simd-sad/src/SimdSadShort2.java b/test/660-checker-simd-sad/src/SimdSadShort2.java
index b110bb4..fdc073c 100644
--- a/test/660-checker-simd-sad/src/SimdSadShort2.java
+++ b/test/660-checker-simd-sad/src/SimdSadShort2.java
@@ -68,8 +68,8 @@
   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Cnv2:s\d+>>   TypeConversion [<<Get2>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Sub:i\d+>>    Sub [<<Cnv1>>,<<Cnv2>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Abs:i\d+>>    Abs [<<Sub>>]                  loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:                 Add [<<Phi2>>,<<Abs>>]         loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START: int SimdSadShort2.sadCastedChar2Int(char[], char[]) loop_optimization (before)
@@ -80,20 +80,29 @@
   /// CHECK-DAG: <<Get1:s\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Get2:s\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Sub:i\d+>>    Sub [<<Get1>>,<<Get2>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>]                  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Abs:i\d+>>    Abs [<<Sub>>]                  loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:                 Add [<<Phi2>>,<<Abs>>]         loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-ARM64: int SimdSadShort2.sadCastedChar2Int(char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadCastedChar2Int(char[] s1, char[] s2) {
     int min_length = Math.min(s1.length, s2.length);
     int sad = 0;
@@ -134,14 +143,23 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort2.sadCastedChar2IntAlt(char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadCastedChar2IntAlt(char[] s1, char[] s2) {
     int min_length = Math.min(s1.length, s2.length);
     int sad = 0;
@@ -158,8 +176,8 @@
   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<BC1:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<BC2:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<BC1:i\d+>>    BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<BC2:i\d+>>    BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Get1:c\d+>>   ArrayGet [{{l\d+}},<<BC1>>]    loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Get2:c\d+>>   ArrayGet [{{l\d+}},<<BC2>>]    loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
@@ -184,14 +202,23 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort2.sadCastedChar2IntAlt2(char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadCastedChar2IntAlt2(char[] s1, char[] s2) {
     int min_length = Math.min(s1.length, s2.length);
     int sad = 0;
@@ -211,8 +238,8 @@
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<ConsL>>,{{j\d+}}]       loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<BC1:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>     outer_loop:none
-  /// CHECK-DAG: <<BC2:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>     outer_loop:none
+  /// CHECK-DAG: <<BC1:i\d+>>    BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>     outer_loop:none
+  /// CHECK-DAG: <<BC2:i\d+>>    BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>     outer_loop:none
   /// CHECK-DAG: <<Get1:c\d+>>   ArrayGet [{{l\d+}},<<BC1>>]    loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Get2:c\d+>>   ArrayGet [{{l\d+}},<<BC2>>]    loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
@@ -220,8 +247,8 @@
   /// CHECK-DAG: <<Cnv3:j\d+>>   TypeConversion [<<Cnv1>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Cnv4:j\d+>>   TypeConversion [<<Cnv2>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Sub:j\d+>>    Sub [<<Cnv3>>,<<Cnv4>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Abs:j\d+>>    Abs [<<Sub>>]                  loop:<<Loop>> outer_loop:none
+  /// CHECK-DAG:                 Add [<<Phi2>>,<<Abs>>]         loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START: long SimdSadShort2.sadCastedChar2Long(char[], char[]) loop_optimization (before)
@@ -235,21 +262,30 @@
   /// CHECK-DAG: <<Cnv1:j\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Cnv2:j\d+>>   TypeConversion [<<Get2>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Sub:j\d+>>    Sub [<<Cnv1>>,<<Cnv2>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>]                  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Abs:j\d+>>    Abs [<<Sub>>]                  loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:                 Add [<<Phi2>>,<<Abs>>]         loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-ARM64: long SimdSadShort2.sadCastedChar2Long(char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadCastedChar2Long(char[] s1, char[] s2) {
     int min_length = Math.min(s1.length, s2.length);
     long sad = 0;
@@ -267,8 +303,8 @@
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 1                 loop:none
   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<ConsL>>,{{j\d+}}]       loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<BC1:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>     outer_loop:none
-  /// CHECK-DAG: <<BC2:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>     outer_loop:none
+  /// CHECK-DAG: <<BC1:i\d+>>    BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>     outer_loop:none
+  /// CHECK-DAG: <<BC2:i\d+>>    BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>     outer_loop:none
   /// CHECK-DAG: <<Get1:c\d+>>   ArrayGet [{{l\d+}},<<BC1>>]    loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Get2:c\d+>>   ArrayGet [{{l\d+}},<<BC2>>]    loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
@@ -276,8 +312,8 @@
   /// CHECK-DAG: <<Cnv3:j\d+>>   TypeConversion [<<Cnv1>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Cnv4:j\d+>>   TypeConversion [<<Cnv2>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Sub:j\d+>>    Sub [<<Cnv3>>,<<Cnv4>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Abs:j\d+>>    Abs [<<Sub>>]                  loop:<<Loop>> outer_loop:none
+  /// CHECK-DAG:                 Add [<<Phi2>>,<<Abs>>]         loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START: long SimdSadShort2.sadCastedChar2LongAt1(char[], char[]) loop_optimization (before)
@@ -291,21 +327,30 @@
   /// CHECK-DAG: <<Cnv1:j\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Cnv2:j\d+>>   TypeConversion [<<Get2>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Sub:j\d+>>    Sub [<<Cnv1>>,<<Cnv2>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>]                  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<Abs:j\d+>>    Abs [<<Sub>>]                  loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:                 Add [<<Phi2>>,<<Abs>>]         loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START-ARM64: long SimdSadShort2.sadCastedChar2LongAt1(char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 1                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static long sadCastedChar2LongAt1(char[] s1, char[] s2) {
     int min_length = Math.min(s1.length, s2.length);
     long sad = 1;  // starts at 1
diff --git a/test/660-checker-simd-sad/src/SimdSadShort3.java b/test/660-checker-simd-sad/src/SimdSadShort3.java
index bbe35d2..5977891 100644
--- a/test/660-checker-simd-sad/src/SimdSadShort3.java
+++ b/test/660-checker-simd-sad/src/SimdSadShort3.java
@@ -35,15 +35,24 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort3.sadShort2IntParamRight(short[], short) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<Param:s\d+>>  ParameterValue                 loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Param>>] loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Param>>] loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntParamRight(short[] s, short param) {
     int sad = 0;
     for (int i = 0; i < s.length; i++) {
@@ -66,15 +75,24 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort3.sadShort2IntParamLeft(short[], short) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<Param:s\d+>>  ParameterValue                 loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Param>>] loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Rep>>,<<Load>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Param>>] loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Rep>>,<<Load>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntParamLeft(short[] s, short param) {
     int sad = 0;
     for (int i = 0; i < s.length; i++) {
@@ -97,15 +115,24 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort3.sadShort2IntConstRight(short[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<ConsI:i\d+>>  IntConstant 32767              loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<ConsI>>] loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<ConsI>>] loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntConstRight(short[] s) {
     int sad = 0;
     for (int i = 0; i < s.length; i++) {
@@ -128,15 +155,24 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort3.sadShort2IntConstLeft(short[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<ConsI:i\d+>>  IntConstant 32767              loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<ConsI>>] loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Rep>>,<<Load>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<ConsI>>] loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Rep>>,<<Load>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntConstLeft(short[] s) {
     int sad = 0;
     for (int i = 0; i < s.length; i++) {
@@ -159,15 +195,24 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort3.sadShort2IntInvariantRight(short[], int) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<Conv:s\d+>>   TypeConversion [{{i\d+}}]      loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Conv>>]  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Conv>>]  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntInvariantRight(short[] s, int val) {
     int sad = 0;
     short x = (short) (val + 1);
@@ -191,15 +236,24 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort3.sadShort2IntInvariantLeft(short[], int) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<Conv:s\d+>>   TypeConversion [{{i\d+}}]      loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Conv>>]  loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Rep>>,<<Load>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<Conv>>]  loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Rep>>,<<Load>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntInvariantLeft(short[] s, int val) {
     int sad = 0;
     short x = (short) (val + 1);
@@ -225,16 +279,25 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort3.sadShort2IntCastedExprRight(short[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<ConsI:i\d+>>  IntConstant 110                loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<ConsI>>] loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Add:d\d+>>    VecAdd [<<Load>>,<<Rep>>]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load>>,<<Add>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<ConsI>>] loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add:d\d+>>    VecAdd [<<Load>>,<<Rep>>]      loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load>>,<<Add>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntCastedExprRight(short[] s) {
     int sad = 0;
     for (int i = 0; i < s.length; i++) {
@@ -260,16 +323,25 @@
   //
   /// CHECK-START-ARM64: int SimdSadShort3.sadShort2IntCastedExprLeft(short[]) loop_optimization (after)
   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
-  /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
   /// CHECK-DAG: <<ConsI:i\d+>>  IntConstant 110                loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<ConsI>>] loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Add:d\d+>>    VecAdd [<<Load>>,<<Rep>>]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Add>>,<<Load>>] loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      SAD idiom is not supported for SVE.
+  ///     CHECK-NOT: VecSADAccumulate
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>    VecReplicateScalar [<<ConsI>>] loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Add:d\d+>>    VecAdd [<<Load>>,<<Rep>>]      loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Add>>,<<Load>>] loop:<<Loop>> outer_loop:none
+  ///     CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static int sadShort2IntCastedExprLeft(short[] s) {
     int sad = 0;
     for (int i = 0; i < s.length; i++) {
diff --git a/test/660-clinit/Android.bp b/test/660-clinit/Android.bp
new file mode 100644
index 0000000..9ccd82d
--- /dev/null
+++ b/test/660-clinit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `660-clinit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-660-clinit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-660-clinit-expected-stdout",
+        ":art-run-test-660-clinit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-660-clinit-expected-stdout",
+    out: ["art-run-test-660-clinit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-660-clinit-expected-stderr",
+    out: ["art-run-test-660-clinit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/551-checker-clinit/expected.txt b/test/660-clinit/expected-stderr.txt
similarity index 100%
copy from test/551-checker-clinit/expected.txt
copy to test/660-clinit/expected-stderr.txt
diff --git a/test/660-clinit/expected.txt b/test/660-clinit/expected-stdout.txt
similarity index 100%
rename from test/660-clinit/expected.txt
rename to test/660-clinit/expected-stdout.txt
diff --git a/test/660-clinit/src/Main.java b/test/660-clinit/src/Main.java
index 5fb5fe5..0d6837e 100644
--- a/test/660-clinit/src/Main.java
+++ b/test/660-clinit/src/Main.java
@@ -21,7 +21,7 @@
   public static void main(String[] args) throws Exception {
     System.loadLibrary(args[0]);
 
-    if (!checkAppImageLoaded()) {
+    if (!checkAppImageLoaded("660-clinit")) {
       System.out.println("AppImage not loaded.");
     }
     if (!checkAppImageContains(ClInit.class)) {
@@ -90,7 +90,7 @@
     }
   }
 
-  public static native boolean checkAppImageLoaded();
+  public static native boolean checkAppImageLoaded(String name);
   public static native boolean checkAppImageContains(Class<?> klass);
   public static native boolean checkInitialized(Class<?> klass);
 }
diff --git a/test/660-store-8-16/expected.txt b/test/660-store-8-16/expected-stderr.txt
similarity index 100%
rename from test/660-store-8-16/expected.txt
rename to test/660-store-8-16/expected-stderr.txt
diff --git a/test/660-store-8-16/expected.txt b/test/660-store-8-16/expected-stdout.txt
similarity index 100%
copy from test/660-store-8-16/expected.txt
copy to test/660-store-8-16/expected-stdout.txt
diff --git a/test/661-checker-simd-reduc/Android.bp b/test/661-checker-simd-reduc/Android.bp
new file mode 100644
index 0000000..65e00c7
--- /dev/null
+++ b/test/661-checker-simd-reduc/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `661-checker-simd-reduc`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-661-checker-simd-reduc",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-661-checker-simd-reduc-expected-stdout",
+        ":art-run-test-661-checker-simd-reduc-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-661-checker-simd-reduc-expected-stdout",
+    out: ["art-run-test-661-checker-simd-reduc-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-661-checker-simd-reduc-expected-stderr",
+    out: ["art-run-test-661-checker-simd-reduc-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/643-checker-bogus-ic/expected.txt b/test/661-checker-simd-reduc/expected-stderr.txt
similarity index 100%
copy from test/643-checker-bogus-ic/expected.txt
copy to test/661-checker-simd-reduc/expected-stderr.txt
diff --git a/test/661-checker-simd-reduc/expected.txt b/test/661-checker-simd-reduc/expected-stdout.txt
similarity index 100%
rename from test/661-checker-simd-reduc/expected.txt
rename to test/661-checker-simd-reduc/expected-stdout.txt
diff --git a/test/661-checker-simd-reduc/src/Main.java b/test/661-checker-simd-reduc/src/Main.java
index 7c37d91..379e83e 100644
--- a/test/661-checker-simd-reduc/src/Main.java
+++ b/test/661-checker-simd-reduc/src/Main.java
@@ -62,8 +62,8 @@
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: int Main.reductionInt(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
+  /// CHECK-START-ARM: int Main.reductionInt(int[]) loop_optimization (after)
+  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 2                 loop:none
   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
@@ -72,11 +72,47 @@
   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
 
+  /// CHECK-START-ARM64: int Main.reductionInt(int[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<TrueC:i\d+>>     IntConstant 1                            loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>       VecSetScalars [{{i\d+}},{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>       Phi [<<Set>>,{{d\d+}}]                   loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>     VecPredWhile                             loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>      VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>]  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                    VecAdd [<<Phi>>,<<Load>>,<<LoopP>>]      loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                    Add [<<I>>,{{i\d+}}]                     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<PostLoopP:j\d+>> VecPredSetAll [<<TrueC>>]                loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>       VecReduce [<<Phi>>,<<PostLoopP>>]        loop:none
+  ///     CHECK-DAG: <<Extr:i\d+>>      VecExtractScalar [<<Red>>,<<PostLoopP>>] loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons:i\d+>>      IntConstant 4                            loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>       VecSetScalars [{{i\d+}}]                 loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>       Phi [<<Set>>,{{d\d+}}]                   loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>      VecLoad [{{l\d+}},<<I:i\d+>>]            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                    VecAdd [<<Phi>>,<<Load>>]                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                    Add [<<I>>,<<Cons>>]                     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>       VecReduce [<<Phi>>]                      loop:none
+  ///     CHECK-DAG: <<Extr:i\d+>>      VecExtractScalar [<<Red>>]               loop:none
+  //
+  /// CHECK-FI:
+  //
   //  Check that full 128-bit Q-Register are saved across SuspendCheck slow path.
   /// CHECK-START-ARM64: int Main.reductionInt(int[]) disassembly (after)
-  /// CHECK:                     SuspendCheckSlowPathARM64
-  /// CHECK:                       stur q<<RegNo:\d+>>, [sp, #<<Offset:\d+>>]
-  /// CHECK:                       ldur q<<RegNo>>, [sp, #<<Offset>>]
+  /// CHECK:                            SuspendCheckSlowPathARM64
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK:                                str z<<RegNo:\d+>>,
+  ///     CHECK:                                ldr z<<RegNo>>,
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK:                                stur q<<RegNo:\d+>>, [sp, #<<Offset:\d+>>]
+  ///     CHECK:                                ldur q<<RegNo>>, [sp, #<<Offset>>]
+  //
+  /// CHECK-FI:
   private static int reductionInt(int[] x) {
     int sum = 0;
     for (int i = 0; i < x.length; i++) {
@@ -102,7 +138,7 @@
   //
   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
   //
-  /// CHECK-START-{ARM,ARM64}: int Main.reductionIntChain() loop_optimization (after)
+  /// CHECK-START-ARM: int Main.reductionIntChain() loop_optimization (after)
   /// CHECK-DAG: <<Set1:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
   /// CHECK-DAG: <<Phi1:d\d+>>   Phi [<<Set1>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<I1:i\d+>>] loop:<<Loop1>>      outer_loop:none
@@ -120,6 +156,47 @@
   //
   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
   //
+  /// CHECK-START-ARM64: int Main.reductionIntChain() loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Set1:d\d+>>   VecSetScalars [{{i\d+}},{{j\d+}}]         loop:none
+  ///     CHECK-DAG: <<Phi1:d\d+>>   Phi [<<Set1>>,{{d\d+}}]                   loop:<<Loop1:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Loop1P:j\d+>> VecPredWhile                              loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<I1:i\d+>>,<<Loop1P>>] loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi1>>,<<Load1>>,<<Loop1P>>]    loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I1>>,{{i\d+}}]                     loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG: <<Red1:d\d+>>   VecReduce [<<Phi1>>,{{j\d+}}]             loop:none
+  ///     CHECK-DAG: <<Extr1:i\d+>>  VecExtractScalar [<<Red1>>,{{j\d+}}]      loop:none
+  ///     CHECK-DAG: <<Set2:d\d+>>   VecSetScalars [{{i\d+}},{{j\d+}}]         loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set2>>,{{d\d+}}]                   loop:<<Loop2:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Loop2P:j\d+>> VecPredWhile                              loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<I2:i\d+>>,<<Loop2P>>] loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load2>>,<<Loop2P>>]    loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I2>>,{{i\d+}}]                     loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: <<Red2:d\d+>>   VecReduce [<<Phi2>>,{{j\d+}}]             loop:none
+  ///     CHECK-DAG: <<Extr2:i\d+>>  VecExtractScalar [<<Red2>>,{{j\d+}}]      loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Set1:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
+  ///     CHECK-DAG: <<Phi1:d\d+>>   Phi [<<Set1>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<I1:i\d+>>] loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi1>>,<<Load1>>]    loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I1>>,{{i\d+}}]          loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG: <<Red1:d\d+>>   VecReduce [<<Phi1>>]           loop:none
+  ///     CHECK-DAG: <<Extr1:i\d+>>  VecExtractScalar [<<Red1>>]    loop:none
+  ///     CHECK-DAG: <<Set2:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set2>>,{{d\d+}}]        loop:<<Loop2:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<I2:i\d+>>] loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load2>>]    loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I2>>,{{i\d+}}]          loop:<<Loop2>>      outer_loop:none
+  ///     CHECK-DAG: <<Red2:d\d+>>   VecReduce [<<Phi2>>]           loop:none
+  ///     CHECK-DAG: <<Extr2:i\d+>>  VecExtractScalar [<<Red2>>]    loop:none
+  //
+  /// CHECK-FI:
+  //
+  /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+  //
   // NOTE: pattern is robust with respect to vector loop unrolling and peeling.
   private static int reductionIntChain() {
     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
@@ -146,8 +223,8 @@
   //
   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
   //
-  /// CHECK-START-{ARM,ARM64}: int Main.reductionIntToLoop(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
+  /// CHECK-START-ARM: int Main.reductionIntToLoop(int[]) loop_optimization (after)
+  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 2                 loop:none
   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop1>>      outer_loop:none
@@ -155,6 +232,31 @@
   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop1>>      outer_loop:none
   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  //
+  /// CHECK-START-ARM64: int Main.reductionIntToLoop(int[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}},{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                   loop:<<Loop1:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>  VecPredWhile                             loop:<<Loop1>>
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>]  loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>,<<LoopP>>]      loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                     loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]             loop:none
+  ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]      loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons:i\d+>>   IntConstant 4                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop1>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
+  ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  //
+  /// CHECK-FI:
   private static int reductionIntToLoop(int[] x) {
     int r = 0;
     for (int i = 0; i < 8; i++) {
@@ -178,14 +280,30 @@
   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
   //
   /// CHECK-START-ARM64: long Main.reductionLong(long[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
-  /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
-  /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant                              loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}},{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                   loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Loop1P:j\d+>> VecPredWhile                             loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<Loop1P>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>,<<Loop1P>>]     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]             loop:none
+  ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]      loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
+  ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  //
+  /// CHECK-FI:
   private static long reductionLong(long[] x) {
     long sum = 0;
     for (int i = 0; i < x.length; i++) {
@@ -229,8 +347,8 @@
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: int Main.reductionIntM1(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
+  /// CHECK-START-ARM: int Main.reductionIntM1(int[]) loop_optimization (after)
+  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 2                 loop:none
   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
@@ -238,6 +356,31 @@
   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  //
+  /// CHECK-START-ARM64: int Main.reductionIntM1(int[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}},{{j\d+}}]       loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>  VecPredWhile                            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>,<<LoopP>>]     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]            loop:none
+  ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]     loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons:i\d+>>   IntConstant 4                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
+  ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  //
+  /// CHECK-FI:
   private static int reductionIntM1(int[] x) {
     int sum = -1;
     for (int i = 0; i < x.length; i++) {
@@ -258,14 +401,29 @@
   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
   //
   /// CHECK-START-ARM64: long Main.reductionLongM1(long[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
-  /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
-  /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}},{{j\d+}}]       loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>  VecPredWhile                            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>,<<LoopP>>]     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]            loop:none
+  ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]     loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
+  ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  //
+  /// CHECK-FI:
   private static long reductionLongM1(long[] x) {
     long sum = -1L;
     for (int i = 0; i < x.length; i++) {
@@ -308,8 +466,8 @@
   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
   //
-  /// CHECK-START-{ARM,ARM64}: int Main.reductionMinusInt(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
+  /// CHECK-START-ARM: int Main.reductionMinusInt(int[]) loop_optimization (after)
+  /// CHECK-DAG: <<Cons:i\d+>>   IntConstant 2                 loop:none
   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
@@ -317,6 +475,31 @@
   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  //
+  /// CHECK-START-ARM64: int Main.reductionMinusInt(int[]) loop_optimization (after)
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}},{{j\d+}}]       loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>  VecPredWhile                            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>,<<LoopP>>]     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]            loop:none
+  ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]     loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons:i\d+>>   IntConstant 4                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
+  ///     CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  //
+  /// CHECK-FI:
   private static int reductionMinusInt(int[] x) {
     int sum = 0;
     for (int i = 0; i < x.length; i++) {
@@ -337,14 +520,29 @@
   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
   //
   /// CHECK-START-ARM64: long Main.reductionMinusLong(long[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
-  /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
-  /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}},{{j\d+}}]       loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>  VecPredWhile                            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>,<<LoopP>>]     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,{{i\d+}}]                    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>,{{j\d+}}]            loop:none
+  ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>,{{j\d+}}]     loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
+  ///     CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
+  ///     CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
+  //
+  /// CHECK-FI:
   private static long reductionMinusLong(long[] x) {
     long sum = 0;
     for (int i = 0; i < x.length; i++) {
diff --git a/test/404-optimizing-allocator/expected.txt b/test/661-classloader-allocator/expected-stderr.txt
similarity index 100%
copy from test/404-optimizing-allocator/expected.txt
copy to test/661-classloader-allocator/expected-stderr.txt
diff --git a/test/661-classloader-allocator/expected.txt b/test/661-classloader-allocator/expected-stdout.txt
similarity index 100%
rename from test/661-classloader-allocator/expected.txt
rename to test/661-classloader-allocator/expected-stdout.txt
diff --git a/test/661-oat-writer-layout/Android.bp b/test/661-oat-writer-layout/Android.bp
new file mode 100644
index 0000000..51e1cdd
--- /dev/null
+++ b/test/661-oat-writer-layout/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `661-oat-writer-layout`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-661-oat-writer-layout",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-661-oat-writer-layout-expected-stdout",
+        ":art-run-test-661-oat-writer-layout-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-661-oat-writer-layout-expected-stdout",
+    out: ["art-run-test-661-oat-writer-layout-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-661-oat-writer-layout-expected-stderr",
+    out: ["art-run-test-661-oat-writer-layout-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/660-store-8-16/expected.txt b/test/661-oat-writer-layout/expected-stderr.txt
similarity index 100%
copy from test/660-store-8-16/expected.txt
copy to test/661-oat-writer-layout/expected-stderr.txt
diff --git a/test/661-oat-writer-layout/expected.txt b/test/661-oat-writer-layout/expected-stdout.txt
similarity index 100%
rename from test/661-oat-writer-layout/expected.txt
rename to test/661-oat-writer-layout/expected-stdout.txt
diff --git a/test/661-oat-writer-layout/oat_writer_layout.cc b/test/661-oat-writer-layout/oat_writer_layout.cc
index 61996b2..4dd47a8 100644
--- a/test/661-oat-writer-layout/oat_writer_layout.cc
+++ b/test/661-oat-writer-layout/oat_writer_layout.cc
@@ -65,12 +65,12 @@
 
   OatClassType type = oat_class.GetType();
   switch (type) {
-    case kOatClassAllCompiled:
-    case kOatClassSomeCompiled:
+    case OatClassType::kAllCompiled:
+    case OatClassType::kSomeCompiled:
       return true;
 
-    case kOatClassNoneCompiled:
-    case kOatClassMax:
+    case OatClassType::kNoneCompiled:
+    case OatClassType::kOatClassMax:
       return false;
   }
 
diff --git a/test/662-regression-alias/Android.bp b/test/662-regression-alias/Android.bp
new file mode 100644
index 0000000..7d38415
--- /dev/null
+++ b/test/662-regression-alias/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `662-regression-alias`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-662-regression-alias",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-662-regression-alias-expected-stdout",
+        ":art-run-test-662-regression-alias-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-662-regression-alias-expected-stdout",
+    out: ["art-run-test-662-regression-alias-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-662-regression-alias-expected-stderr",
+    out: ["art-run-test-662-regression-alias-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/606-erroneous-class/expected.txt b/test/662-regression-alias/expected-stderr.txt
similarity index 100%
copy from test/606-erroneous-class/expected.txt
copy to test/662-regression-alias/expected-stderr.txt
diff --git a/test/662-regression-alias/expected.txt b/test/662-regression-alias/expected-stdout.txt
similarity index 100%
rename from test/662-regression-alias/expected.txt
rename to test/662-regression-alias/expected-stdout.txt
diff --git a/test/663-checker-select-generator/expected.txt b/test/663-checker-select-generator/expected-stderr.txt
similarity index 100%
rename from test/663-checker-select-generator/expected.txt
rename to test/663-checker-select-generator/expected-stderr.txt
diff --git a/test/663-checker-select-generator/expected.txt b/test/663-checker-select-generator/expected-stdout.txt
similarity index 100%
copy from test/663-checker-select-generator/expected.txt
copy to test/663-checker-select-generator/expected-stdout.txt
diff --git a/test/668-aiobe/expected.txt b/test/663-odd-dex-size/expected-stderr.txt
similarity index 100%
copy from test/668-aiobe/expected.txt
copy to test/663-odd-dex-size/expected-stderr.txt
diff --git a/test/663-odd-dex-size/expected-stdout.txt b/test/663-odd-dex-size/expected-stdout.txt
new file mode 100644
index 0000000..cd5a1ee
--- /dev/null
+++ b/test/663-odd-dex-size/expected-stdout.txt
@@ -0,0 +1,2 @@
+HelloWorld
+HelloWorld
diff --git a/test/663-odd-dex-size/expected.txt b/test/663-odd-dex-size/expected.txt
deleted file mode 100644
index 3da1ec2..0000000
--- a/test/663-odd-dex-size/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-HelloWorld
diff --git a/test/663-odd-dex-size/run b/test/663-odd-dex-size/run
new file mode 100644
index 0000000..51777ca
--- /dev/null
+++ b/test/663-odd-dex-size/run
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 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.
+
+# Run normally.
+${RUN} $@
+return_status1=$?
+
+# Run without cdex to trigger the unalignment in the vdex file.
+${RUN} ${@} -Xcompiler-option --compact-dex-level=none
+return_status2=$?
+
+(exit ${return_status1}) && (exit ${return_status2})
diff --git a/test/660-store-8-16/expected.txt b/test/663-odd-dex-size2/expected-stderr.txt
similarity index 100%
copy from test/660-store-8-16/expected.txt
copy to test/663-odd-dex-size2/expected-stderr.txt
diff --git a/test/663-odd-dex-size2/expected.txt b/test/663-odd-dex-size2/expected-stdout.txt
similarity index 100%
rename from test/663-odd-dex-size2/expected.txt
rename to test/663-odd-dex-size2/expected-stdout.txt
diff --git a/test/530-checker-lse3/expected.txt b/test/663-odd-dex-size3/expected-stderr.txt
similarity index 100%
copy from test/530-checker-lse3/expected.txt
copy to test/663-odd-dex-size3/expected-stderr.txt
diff --git a/test/663-odd-dex-size3/expected.txt b/test/663-odd-dex-size3/expected-stdout.txt
similarity index 100%
rename from test/663-odd-dex-size3/expected.txt
rename to test/663-odd-dex-size3/expected-stdout.txt
diff --git a/test/660-store-8-16/expected.txt b/test/663-odd-dex-size4/expected-stderr.txt
similarity index 100%
copy from test/660-store-8-16/expected.txt
copy to test/663-odd-dex-size4/expected-stderr.txt
diff --git a/test/663-odd-dex-size4/expected.txt b/test/663-odd-dex-size4/expected-stdout.txt
similarity index 100%
rename from test/663-odd-dex-size4/expected.txt
rename to test/663-odd-dex-size4/expected-stdout.txt
diff --git a/test/664-aget-verifier/Android.bp b/test/664-aget-verifier/Android.bp
new file mode 100644
index 0000000..9d54a59
--- /dev/null
+++ b/test/664-aget-verifier/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `664-aget-verifier`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-664-aget-verifier",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-664-aget-verifier-expected-stdout",
+        ":art-run-test-664-aget-verifier-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-664-aget-verifier-expected-stdout",
+    out: ["art-run-test-664-aget-verifier-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-664-aget-verifier-expected-stderr",
+    out: ["art-run-test-664-aget-verifier-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/658-fp-read-barrier/expected.txt b/test/664-aget-verifier/expected-stderr.txt
similarity index 100%
copy from test/658-fp-read-barrier/expected.txt
copy to test/664-aget-verifier/expected-stderr.txt
diff --git a/test/664-aget-verifier/expected.txt b/test/664-aget-verifier/expected-stdout.txt
similarity index 100%
rename from test/664-aget-verifier/expected.txt
rename to test/664-aget-verifier/expected-stdout.txt
diff --git a/test/665-checker-simd-zero/Android.bp b/test/665-checker-simd-zero/Android.bp
new file mode 100644
index 0000000..23e9f09
--- /dev/null
+++ b/test/665-checker-simd-zero/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `665-checker-simd-zero`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-665-checker-simd-zero",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-665-checker-simd-zero-expected-stdout",
+        ":art-run-test-665-checker-simd-zero-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-665-checker-simd-zero-expected-stdout",
+    out: ["art-run-test-665-checker-simd-zero-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-665-checker-simd-zero-expected-stderr",
+    out: ["art-run-test-665-checker-simd-zero-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/583-checker-zero/expected.txt b/test/665-checker-simd-zero/expected-stderr.txt
similarity index 100%
copy from test/583-checker-zero/expected.txt
copy to test/665-checker-simd-zero/expected-stderr.txt
diff --git a/test/665-checker-simd-zero/expected.txt b/test/665-checker-simd-zero/expected-stdout.txt
similarity index 100%
rename from test/665-checker-simd-zero/expected.txt
rename to test/665-checker-simd-zero/expected-stdout.txt
diff --git a/test/665-checker-simd-zero/src/Main.java b/test/665-checker-simd-zero/src/Main.java
index 66eea64..3960c40 100644
--- a/test/665-checker-simd-zero/src/Main.java
+++ b/test/665-checker-simd-zero/src/Main.java
@@ -26,9 +26,19 @@
   //
   /// CHECK-START-ARM64: void Main.zeroz(boolean[]) loop_optimization (after)
   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>,{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                           loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void zeroz(boolean[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = false;
@@ -42,9 +52,19 @@
   //
   /// CHECK-START-ARM64: void Main.zerob(byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>,{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                           loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void zerob(byte[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = 0;
@@ -58,9 +78,19 @@
   //
   /// CHECK-START-ARM64: void Main.zeroc(char[]) loop_optimization (after)
   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>,{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void zeroc(char[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = 0;
@@ -74,9 +104,19 @@
   //
   /// CHECK-START-ARM64: void Main.zeros(short[]) loop_optimization (after)
   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>,{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                           loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void zeros(short[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = 0;
@@ -90,9 +130,19 @@
   //
   /// CHECK-START-ARM64: void Main.zeroi(int[]) loop_optimization (after)
   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>,{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                           loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void zeroi(int[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = 0;
@@ -106,9 +156,19 @@
   //
   /// CHECK-START-ARM64: void Main.zerol(long[]) loop_optimization (after)
   /// CHECK-DAG: <<Zero:j\d+>> LongConstant 0                       loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>,{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                           loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void zerol(long[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = 0;
@@ -122,9 +182,19 @@
   //
   /// CHECK-START-ARM64: void Main.zerof(float[]) loop_optimization (after)
   /// CHECK-DAG: <<Zero:f\d+>> FloatConstant 0                      loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>,{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                           loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void zerof(float[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = 0;
@@ -138,9 +208,19 @@
   //
   /// CHECK-START-ARM64: void Main.zerod(double[]) loop_optimization (after)
   /// CHECK-DAG: <<Zero:d\d+>> DoubleConstant 0                     loop:none
-  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
-  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>,{{j\d+}}]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                           loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>,{{j\d+}}] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<Zero>>]        loop:none
+  ///     CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   private static void zerod(double[] x) {
     for (int i = 0; i < x.length; i++) {
       x[i] = 0;
diff --git a/test/666-dex-cache-itf/Android.bp b/test/666-dex-cache-itf/Android.bp
new file mode 100644
index 0000000..f7f27f6
--- /dev/null
+++ b/test/666-dex-cache-itf/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `666-dex-cache-itf`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-666-dex-cache-itf",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-666-dex-cache-itf-expected-stdout",
+        ":art-run-test-666-dex-cache-itf-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-666-dex-cache-itf-expected-stdout",
+    out: ["art-run-test-666-dex-cache-itf-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-666-dex-cache-itf-expected-stderr",
+    out: ["art-run-test-666-dex-cache-itf-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/666-dex-cache-itf/expected.txt b/test/666-dex-cache-itf/expected-stderr.txt
similarity index 100%
rename from test/666-dex-cache-itf/expected.txt
rename to test/666-dex-cache-itf/expected-stderr.txt
diff --git a/test/666-dex-cache-itf/expected.txt b/test/666-dex-cache-itf/expected-stdout.txt
similarity index 100%
copy from test/666-dex-cache-itf/expected.txt
copy to test/666-dex-cache-itf/expected-stdout.txt
diff --git a/test/667-checker-simd-alignment/Android.bp b/test/667-checker-simd-alignment/Android.bp
new file mode 100644
index 0000000..0426aac
--- /dev/null
+++ b/test/667-checker-simd-alignment/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `667-checker-simd-alignment`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-667-checker-simd-alignment",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-667-checker-simd-alignment-expected-stdout",
+        ":art-run-test-667-checker-simd-alignment-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-667-checker-simd-alignment-expected-stdout",
+    out: ["art-run-test-667-checker-simd-alignment-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-667-checker-simd-alignment-expected-stderr",
+    out: ["art-run-test-667-checker-simd-alignment-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/471-deopt-environment/expected.txt b/test/667-checker-simd-alignment/expected-stderr.txt
similarity index 100%
copy from test/471-deopt-environment/expected.txt
copy to test/667-checker-simd-alignment/expected-stderr.txt
diff --git a/test/667-checker-simd-alignment/expected.txt b/test/667-checker-simd-alignment/expected-stdout.txt
similarity index 100%
rename from test/667-checker-simd-alignment/expected.txt
rename to test/667-checker-simd-alignment/expected-stdout.txt
diff --git a/test/667-jit-jni-stub/Android.bp b/test/667-jit-jni-stub/Android.bp
new file mode 100644
index 0000000..2328e52
--- /dev/null
+++ b/test/667-jit-jni-stub/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `667-jit-jni-stub`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-667-jit-jni-stub",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-667-jit-jni-stub-expected-stdout",
+        ":art-run-test-667-jit-jni-stub-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-667-jit-jni-stub-expected-stdout",
+    out: ["art-run-test-667-jit-jni-stub-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-667-jit-jni-stub-expected-stderr",
+    out: ["art-run-test-667-jit-jni-stub-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/660-store-8-16/expected.txt b/test/667-jit-jni-stub/expected-stderr.txt
similarity index 100%
copy from test/660-store-8-16/expected.txt
copy to test/667-jit-jni-stub/expected-stderr.txt
diff --git a/test/667-jit-jni-stub/expected.txt b/test/667-jit-jni-stub/expected-stdout.txt
similarity index 100%
rename from test/667-jit-jni-stub/expected.txt
rename to test/667-jit-jni-stub/expected-stdout.txt
diff --git a/test/667-out-of-bounds/Android.bp b/test/667-out-of-bounds/Android.bp
new file mode 100644
index 0000000..9718596
--- /dev/null
+++ b/test/667-out-of-bounds/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `667-out-of-bounds`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-667-out-of-bounds",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-667-out-of-bounds-expected-stdout",
+        ":art-run-test-667-out-of-bounds-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-667-out-of-bounds-expected-stdout",
+    out: ["art-run-test-667-out-of-bounds-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-667-out-of-bounds-expected-stderr",
+    out: ["art-run-test-667-out-of-bounds-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/427-bounds/expected.txt b/test/667-out-of-bounds/expected-stderr.txt
similarity index 100%
copy from test/427-bounds/expected.txt
copy to test/667-out-of-bounds/expected-stderr.txt
diff --git a/test/667-out-of-bounds/expected.txt b/test/667-out-of-bounds/expected-stdout.txt
similarity index 100%
rename from test/667-out-of-bounds/expected.txt
rename to test/667-out-of-bounds/expected-stdout.txt
diff --git a/test/668-aiobe/expected.txt b/test/668-aiobe/expected-stderr.txt
similarity index 100%
rename from test/668-aiobe/expected.txt
rename to test/668-aiobe/expected-stderr.txt
diff --git a/test/668-aiobe/expected.txt b/test/668-aiobe/expected-stdout.txt
similarity index 100%
copy from test/668-aiobe/expected.txt
copy to test/668-aiobe/expected-stdout.txt
diff --git a/test/669-checker-break/Android.bp b/test/669-checker-break/Android.bp
new file mode 100644
index 0000000..0eb41a2
--- /dev/null
+++ b/test/669-checker-break/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `669-checker-break`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-669-checker-break",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-669-checker-break-expected-stdout",
+        ":art-run-test-669-checker-break-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-669-checker-break-expected-stdout",
+    out: ["art-run-test-669-checker-break-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-669-checker-break-expected-stderr",
+    out: ["art-run-test-669-checker-break-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/660-store-8-16/expected.txt b/test/669-checker-break/expected-stderr.txt
similarity index 100%
copy from test/660-store-8-16/expected.txt
copy to test/669-checker-break/expected-stderr.txt
diff --git a/test/669-checker-break/expected.txt b/test/669-checker-break/expected-stdout.txt
similarity index 100%
rename from test/669-checker-break/expected.txt
rename to test/669-checker-break/expected-stdout.txt
diff --git a/test/669-checker-break/src/Main.java b/test/669-checker-break/src/Main.java
index c40e4a6..9f7b24e 100644
--- a/test/669-checker-break/src/Main.java
+++ b/test/669-checker-break/src/Main.java
@@ -50,11 +50,22 @@
   /// CHECK-START-ARM64: int Main.breakLoop(int[]) loop_optimization (after)
   /// CHECK-DAG: <<Par:l\d+>>  ParameterValue                          loop:none
   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                           loop:none
-  /// CHECK-DAG: <<Four:i\d+>> IntConstant 4                           loop:none
   /// CHECK-DAG: <<Nil:l\d+>>  NullCheck [<<Par>>]                     loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>  VecReplicateScalar [<<One>>]            loop:none
-  /// CHECK-DAG:               VecStore [<<Nil>>,<<Phi:i\d+>>,<<Rep>>] loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:               Add [<<Phi>>,<<Four>>]                  loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<One>>,{{j\d+}}]             loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile                                      loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:                VecStore [<<Nil>>,<<Phi:i\d+>>,<<Rep>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                Add [<<Phi>>,{{i\d+}}]                            loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Four:i\d+>>  IntConstant 4                           loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<One>>]            loop:none
+  ///     CHECK-DAG:                VecStore [<<Nil>>,<<Phi:i\d+>>,<<Rep>>] loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:                Add [<<Phi>>,<<Four>>]                  loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static int breakLoop(int[] a) {
     int l = 0;
     int u = a.length - 1;
@@ -141,10 +152,21 @@
   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                          loop:none
   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                           loop:none
   /// CHECK-DAG: <<Three:i\d+>> IntConstant 3                           loop:none
-  /// CHECK-DAG: <<Four:i\d+>>  IntConstant 4                           loop:none
-  /// CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Three>>]          loop:none
-  /// CHECK-DAG:                VecStore [<<Par>>,<<Phi:i\d+>>,<<Rep>>] loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG:                Add [<<Phi>>,<<Four>>]                  loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Three>>,{{j\d+}}]           loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile                                      loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:                VecStore [<<Par>>,<<Phi:i\d+>>,<<Rep>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                Add [<<Phi>>,{{i\d+}}]                            loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Four:i\d+>>  IntConstant 4                           loop:none
+  ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Three>>]          loop:none
+  ///     CHECK-DAG:                VecStore [<<Par>>,<<Phi:i\d+>>,<<Rep>>] loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG:                Add [<<Phi>>,<<Four>>]                  loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static int breakLoopSafeConst(int[] a) {
     int l = Integer.MAX_VALUE - 16;
     int u = Integer.MAX_VALUE - 1;
@@ -262,10 +284,22 @@
   /// CHECK-START-ARM64: int Main.breakLoopReduction(int[]) loop_optimization (after)
   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue              loop:none
   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0               loop:none
-  /// CHECK-DAG: <<Exp:d\d+>>   VecSetScalars [<<Zero>>]    loop:none
-  /// CHECK-DAG: <<VPhi:d\d+>>  Phi [<<Exp>>,<<VAdd:d\d+>>] loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<VLoad:d\d+>> VecLoad                     loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd>>       VecAdd [<<VPhi>>,<<VLoad>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  ///     CHECK-DAG: <<Exp:d\d+>>   VecSetScalars [<<Zero>>,{{j\d+}}]     loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile                          loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<VPhi:d\d+>>  Phi [<<Exp>>,<<VAdd:d\d+>>]           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VLoad:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd>>       VecAdd [<<VPhi>>,<<VLoad>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Exp:d\d+>>   VecSetScalars [<<Zero>>]    loop:none
+  ///     CHECK-DAG: <<VPhi:d\d+>>  Phi [<<Exp>>,<<VAdd:d\d+>>] loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<VLoad:d\d+>> VecLoad                     loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd>>       VecAdd [<<VPhi>>,<<VLoad>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   static int breakLoopReduction(int[] a) {
     int l = 0;
     int u = a.length - 1;
diff --git a/test/670-bitstring-type-check/expected.txt b/test/670-bitstring-type-check/expected-stderr.txt
similarity index 100%
rename from test/670-bitstring-type-check/expected.txt
rename to test/670-bitstring-type-check/expected-stderr.txt
diff --git a/test/670-bitstring-type-check/expected.txt b/test/670-bitstring-type-check/expected-stdout.txt
similarity index 100%
copy from test/670-bitstring-type-check/expected.txt
copy to test/670-bitstring-type-check/expected-stdout.txt
diff --git a/test/671-npe-field-opts/Android.bp b/test/671-npe-field-opts/Android.bp
new file mode 100644
index 0000000..4fbdd96
--- /dev/null
+++ b/test/671-npe-field-opts/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `671-npe-field-opts`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-671-npe-field-opts",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-671-npe-field-opts-expected-stdout",
+        ":art-run-test-671-npe-field-opts-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-671-npe-field-opts-expected-stdout",
+    out: ["art-run-test-671-npe-field-opts-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-671-npe-field-opts-expected-stderr",
+    out: ["art-run-test-671-npe-field-opts-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/671-npe-field-opts/expected.txt b/test/671-npe-field-opts/expected-stderr.txt
similarity index 100%
rename from test/671-npe-field-opts/expected.txt
rename to test/671-npe-field-opts/expected-stderr.txt
diff --git a/test/671-npe-field-opts/expected.txt b/test/671-npe-field-opts/expected-stdout.txt
similarity index 100%
copy from test/671-npe-field-opts/expected.txt
copy to test/671-npe-field-opts/expected-stdout.txt
diff --git a/test/672-checker-throw-method/Android.bp b/test/672-checker-throw-method/Android.bp
new file mode 100644
index 0000000..612b37f
--- /dev/null
+++ b/test/672-checker-throw-method/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `672-checker-throw-method`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-672-checker-throw-method",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-672-checker-throw-method-expected-stdout",
+        ":art-run-test-672-checker-throw-method-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-672-checker-throw-method-expected-stdout",
+    out: ["art-run-test-672-checker-throw-method-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-672-checker-throw-method-expected-stderr",
+    out: ["art-run-test-672-checker-throw-method-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/470-huge-method/expected.txt b/test/672-checker-throw-method/expected-stderr.txt
similarity index 100%
copy from test/470-huge-method/expected.txt
copy to test/672-checker-throw-method/expected-stderr.txt
diff --git a/test/672-checker-throw-method/expected.txt b/test/672-checker-throw-method/expected-stdout.txt
similarity index 100%
rename from test/672-checker-throw-method/expected.txt
rename to test/672-checker-throw-method/expected-stdout.txt
diff --git a/test/672-checker-throw-method/src/Main.java b/test/672-checker-throw-method/src/Main.java
index 360b52c..c2344b2 100644
--- a/test/672-checker-throw-method/src/Main.java
+++ b/test/672-checker-throw-method/src/Main.java
@@ -70,7 +70,9 @@
   /// CHECK:                Throw
   /// CHECK: end_block
   static public void doit1(int[] a) {
-    String par = "a";
+    // Being in the boot image means we know the load string cannot throw. Create one that is
+    // unlikely to be there to ensure we handle that case.
+    String par = "stringUnlikelyToBeInBootImage";
     if (a == null)
       throw new Error("you are null: " + par);
     for (int i = 0; i < a.length; i++) {
@@ -98,7 +100,9 @@
   /// CHECK:                InvokeStaticOrDirect [<<Str>>] method_name:Main.doThrow
   /// CHECK: end_block
   static public void doit2(int[] a) {
-    String par = "a";
+    // Being in the boot image means we know the load string cannot throw. Create one that is
+    // unlikely to be there to ensure we handle that case.
+    String par = "stringUnlikelyToBeInBootImage";
     if (a == null)
       doThrow(par);
     for (int i = 0; i < a.length; i++) {
@@ -128,7 +132,9 @@
   /// CHECK:                Throw
   /// CHECK: end_block
   static public void doit3(int[] a) {
-    String par = "a";
+    // Being in the boot image means we know the load string cannot throw. Create one that is
+    // unlikely to be there to ensure we handle that case.
+    String par = "stringUnlikelyToBeInBootImage";
     checkNotNullDirect(a, par);
     for (int i = 0; i < a.length; i++) {
       a[i] = 3;
@@ -155,7 +161,9 @@
   /// CHECK:                InvokeStaticOrDirect [<<Str>>] method_name:Main.doThrow
   /// CHECK: end_block
   static public void doit4(int[] a) {
-    String par = "a";
+    // Being in the boot image means we know the load string cannot throw. Create one that is
+    // unlikely to be there to ensure we handle that case.
+    String par = "stringUnlikelyToBeInBootImage";
     checkNotNullSplit(a, par);  // resembles Kotlin runtime lib
                                 // (test is lined, doThrow is not)
     for (int i = 0; i < a.length; i++) {
@@ -166,7 +174,9 @@
   // Ensures Phi values are merged properly.
   static public int doit5(int[] a) {
     int t = 100;
-    String par = "a";
+    // Being in the boot image means we know the load string cannot throw. Create one that is
+    // unlikely to be there to ensure we handle that case.
+    String par = "stringUnlikelyToBeInBootImage";
     if (a == null) {
       doThrow(par);
     } else {
@@ -205,7 +215,7 @@
   /// CHECK-START: int Main.deleteNullCheck(int[]) dead_code_elimination$after_inlining (after)
   /// CHECK-NOT:              NullCheck
   static public int deleteNullCheck(int[] a) {
-    checkNotNullSplit(a, "a");
+    checkNotNullSplit(a, "stringUnlikelyToBeInBootImage");
     return a[0];
   }
 
@@ -215,7 +225,7 @@
   /// CHECK-START: int Main.deleteNullCheckAlt(int[]) dead_code_elimination$after_inlining (after)
   /// CHECK-NOT: NullCheck
   static public int deleteNullCheckAlt(int[] a) {
-    checkNotNullSplitAlt(a, "a");
+    checkNotNullSplitAlt(a, "stringUnlikeltyToBeInBootImage");
     return a[0];
   }
 
@@ -227,9 +237,9 @@
   /// CHECK-START: int Main.deleteNullChecks3(int[], int[], int[]) dead_code_elimination$after_inlining (after)
   /// CHECK-NOT: NullCheck
   static public int deleteNullChecks3(int[] a, int[] b, int[] c) {
-    checkNotNullSplit(a, "a");
-    checkNotNullSplit(b, "b");
-    checkNotNullSplit(c, "c");
+    checkNotNullSplit(a, "stringUnlikelytoBeInBootImage1");
+    checkNotNullSplit(b, "stringUnlikelytoBeInBootImage2");
+    checkNotNullSplit(c, "stringUnlikelytoBeInBootImage3");
     return a[0] + b[0] + c[0];
   }
 
diff --git a/test/673-checker-throw-vmethod/Android.bp b/test/673-checker-throw-vmethod/Android.bp
new file mode 100644
index 0000000..bfbccc4
--- /dev/null
+++ b/test/673-checker-throw-vmethod/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `673-checker-throw-vmethod`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-673-checker-throw-vmethod",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-673-checker-throw-vmethod-expected-stdout",
+        ":art-run-test-673-checker-throw-vmethod-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-673-checker-throw-vmethod-expected-stdout",
+    out: ["art-run-test-673-checker-throw-vmethod-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-673-checker-throw-vmethod-expected-stderr",
+    out: ["art-run-test-673-checker-throw-vmethod-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/470-huge-method/expected.txt b/test/673-checker-throw-vmethod/expected-stderr.txt
similarity index 100%
copy from test/470-huge-method/expected.txt
copy to test/673-checker-throw-vmethod/expected-stderr.txt
diff --git a/test/673-checker-throw-vmethod/expected.txt b/test/673-checker-throw-vmethod/expected-stdout.txt
similarity index 100%
rename from test/673-checker-throw-vmethod/expected.txt
rename to test/673-checker-throw-vmethod/expected-stdout.txt
diff --git a/test/673-checker-throw-vmethod/src/Main.java b/test/673-checker-throw-vmethod/src/Main.java
index 206dfaf..3979300 100644
--- a/test/673-checker-throw-vmethod/src/Main.java
+++ b/test/673-checker-throw-vmethod/src/Main.java
@@ -64,7 +64,9 @@
   /// CHECK:                Throw
   /// CHECK: end_block
   public void doit1(int[] a) {
-    String par = "a";
+    // Being in the boot image means we know the load string cannot throw. Create one that is
+    // unlikely to be there to ensure we handle that case.
+    String par = "stringUnlikelyToBeInBootImage";
     if (a == null)
       throw new Error("you are null: " + par);
     for (int i = 0; i < a.length; i++) {
@@ -79,7 +81,7 @@
   /// CHECK:                If [<<Tst>>]
   /// CHECK: end_block
   /// CHECK: begin_block
-  /// CHECK:                InvokeVirtual [{{l\d+}},<<Str>>] method_name:Main.doThrow
+  /// CHECK:                InvokeStaticOrDirect [{{l\d+}},<<Str>>] method_name:Main.doThrow
   /// CHECK: end_block
   //
   /// CHECK-START: void Main.doit2(int[]) code_sinking (after)
@@ -89,10 +91,12 @@
   /// CHECK: end_block
   /// CHECK: begin_block
   /// CHECK:   <<Str:l\d+>> LoadString
-  /// CHECK:                InvokeVirtual [{{l\d+}},<<Str>>] method_name:Main.doThrow
+  /// CHECK:                InvokeStaticOrDirect [{{l\d+}},<<Str>>] method_name:Main.doThrow
   /// CHECK: end_block
   public void doit2(int[] a) {
-    String par = "a";
+    // Being in the boot image means we know the load string cannot throw. Create one that is
+    // unlikely to be there to ensure we handle that case.
+    String par = "stringUnlikelyToBeInBootImage";
     if (a == null)
       doThrow(par);
     for (int i = 0; i < a.length; i++) {
@@ -122,7 +126,9 @@
   /// CHECK:                Throw
   /// CHECK: end_block
   public void doit3(int[] a) {
-    String par = "a";
+    // Being in the boot image means we know the load string cannot throw. Create one that is
+    // unlikely to be there to ensure we handle that case.
+    String par = "stringUnlikelyToBeInBootImage";
     checkNotNullDirect(a, par);
     for (int i = 0; i < a.length; i++) {
       a[i] = 3;
@@ -136,7 +142,7 @@
   /// CHECK:                If [<<Tst>>]
   /// CHECK: end_block
   /// CHECK: begin_block
-  /// CHECK:                InvokeVirtual [{{l\d+}},<<Str>>] method_name:Main.doThrow
+  /// CHECK:                InvokeStaticOrDirect [{{l\d+}},<<Str>>] method_name:Main.doThrow
   /// CHECK: end_block
   //
   /// CHECK-START: void Main.doit4(int[]) code_sinking (after)
@@ -146,10 +152,12 @@
   /// CHECK: end_block
   /// CHECK: begin_block
   /// CHECK:   <<Str:l\d+>> LoadString
-  /// CHECK:                InvokeVirtual [{{l\d+}},<<Str>>] method_name:Main.doThrow
+  /// CHECK:                InvokeStaticOrDirect [{{l\d+}},<<Str>>] method_name:Main.doThrow
   /// CHECK: end_block
   public void doit4(int[] a) {
-    String par = "a";
+    // Being in the boot image means we know the load string cannot throw. Create one that is
+    // unlikely to be there to ensure we handle that case.
+    String par = "stringUnlikelyToBeInBootImage";
     checkNotNullSplit(a, par);
     for (int i = 0; i < a.length; i++) {
       a[i] = 4;
diff --git a/test/674-HelloWorld-Dm/Android.bp b/test/674-HelloWorld-Dm/Android.bp
new file mode 100644
index 0000000..3c55af7
--- /dev/null
+++ b/test/674-HelloWorld-Dm/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `674-HelloWorld-Dm`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-674-HelloWorld-Dm",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-674-HelloWorld-Dm-expected-stdout",
+        ":art-run-test-674-HelloWorld-Dm-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-674-HelloWorld-Dm-expected-stdout",
+    out: ["art-run-test-674-HelloWorld-Dm-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-674-HelloWorld-Dm-expected-stderr",
+    out: ["art-run-test-674-HelloWorld-Dm-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/674-hiddenapi/expected.txt b/test/674-HelloWorld-Dm/expected-stderr.txt
similarity index 100%
copy from test/674-hiddenapi/expected.txt
copy to test/674-HelloWorld-Dm/expected-stderr.txt
diff --git a/test/674-HelloWorld-Dm/expected.txt b/test/674-HelloWorld-Dm/expected-stdout.txt
similarity index 100%
rename from test/674-HelloWorld-Dm/expected.txt
rename to test/674-HelloWorld-Dm/expected-stdout.txt
diff --git a/test/674-hiddenapi/check b/test/674-hiddenapi/check
index c319a0a..c8afc22 100644
--- a/test/674-hiddenapi/check
+++ b/test/674-hiddenapi/check
@@ -14,10 +14,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Remove pid and date from the log messages.
-grep -vE '^dalvikvm(32|64) E [^]]+]' "$2" \
-    | grep -v JNI_OnLoad \
+grep -v JNI_OnLoad "$2" \
     | grep -v JNI_OnUnload \
     > "$2.tmp"
+grep -vE '^dalvikvm(32|64) E [^]]+]' "$4" \
+    > "$4.tmp"
 
-./default-check "$1" "$2.tmp"
+./default-check "$1" "$2.tmp" "$3" "$4.tmp"
diff --git a/test/674-hiddenapi/expected.txt b/test/674-hiddenapi/expected-stderr.txt
similarity index 100%
rename from test/674-hiddenapi/expected.txt
rename to test/674-hiddenapi/expected-stderr.txt
diff --git a/test/674-hiddenapi/expected.txt b/test/674-hiddenapi/expected-stdout.txt
similarity index 100%
copy from test/674-hiddenapi/expected.txt
copy to test/674-hiddenapi/expected-stdout.txt
diff --git a/test/674-hiddenapi/hiddenapi-flags.csv b/test/674-hiddenapi/hiddenapi-flags.csv
index 42626f7..0eb17ef 100644
--- a/test/674-hiddenapi/hiddenapi-flags.csv
+++ b/test/674-hiddenapi/hiddenapi-flags.csv
@@ -1,108 +1,108 @@
-LNullaryConstructorBlacklistAndCorePlatformApi;-><init>()V,blacklist,core-platform-api
-LNullaryConstructorBlacklist;-><init>()V,blacklist
-LNullaryConstructorDarkGreylist;-><init>()V,greylist-max-o
-LNullaryConstructorLightGreylist;-><init>()V,greylist
-LParentClass;->fieldPackageBlacklistAndCorePlatformApi:I,blacklist,core-platform-api
-LParentClass;->fieldPackageBlacklist:I,blacklist
-LParentClass;->fieldPackageDarkGreylist:I,greylist-max-o
-LParentClass;->fieldPackageLightGreylist:I,greylist
-LParentClass;->fieldPackageStaticBlacklistAndCorePlatformApi:I,blacklist,core-platform-api
-LParentClass;->fieldPackageStaticBlacklist:I,blacklist
-LParentClass;->fieldPackageStaticDarkGreylist:I,greylist-max-o
-LParentClass;->fieldPackageStaticLightGreylist:I,greylist
-LParentClass;->fieldPrivateBlacklistAndCorePlatformApi:I,blacklist,core-platform-api
-LParentClass;->fieldPrivateBlacklist:I,blacklist
-LParentClass;->fieldPrivateDarkGreylist:I,greylist-max-o
-LParentClass;->fieldPrivateLightGreylist:I,greylist
-LParentClass;->fieldPrivateStaticBlacklistAndCorePlatformApi:I,blacklist,core-platform-api
-LParentClass;->fieldPrivateStaticBlacklist:I,blacklist
-LParentClass;->fieldPrivateStaticDarkGreylist:I,greylist-max-o
-LParentClass;->fieldPrivateStaticLightGreylist:I,greylist
-LParentClass;->fieldProtectedBlacklistAndCorePlatformApi:I,blacklist,core-platform-api
-LParentClass;->fieldProtectedBlacklist:I,blacklist
-LParentClass;->fieldProtectedDarkGreylist:I,greylist-max-o
-LParentClass;->fieldProtectedLightGreylist:I,greylist
-LParentClass;->fieldProtectedStaticBlacklistAndCorePlatformApi:I,blacklist,core-platform-api
-LParentClass;->fieldProtectedStaticBlacklist:I,blacklist
-LParentClass;->fieldProtectedStaticDarkGreylist:I,greylist-max-o
-LParentClass;->fieldProtectedStaticLightGreylist:I,greylist
-LParentClass;->fieldPublicBlacklistAndCorePlatformApiB:I,blacklist,core-platform-api
-LParentClass;->fieldPublicBlacklistAndCorePlatformApi:I,blacklist,core-platform-api
-LParentClass;->fieldPublicBlacklistB:I,blacklist
-LParentClass;->fieldPublicBlacklist:I,blacklist
-LParentClass;->fieldPublicDarkGreylistB:I,greylist-max-o
-LParentClass;->fieldPublicDarkGreylist:I,greylist-max-o
-LParentClass;->fieldPublicLightGreylistB:I,greylist
-LParentClass;->fieldPublicLightGreylist:I,greylist
-LParentClass;->fieldPublicStaticBlacklistAndCorePlatformApiB:I,blacklist,core-platform-api
-LParentClass;->fieldPublicStaticBlacklistAndCorePlatformApi:I,blacklist,core-platform-api
-LParentClass;->fieldPublicStaticBlacklistB:I,blacklist
-LParentClass;->fieldPublicStaticBlacklist:I,blacklist
-LParentClass;->fieldPublicStaticDarkGreylistB:I,greylist-max-o
-LParentClass;->fieldPublicStaticDarkGreylist:I,greylist-max-o
-LParentClass;->fieldPublicStaticLightGreylistB:I,greylist
-LParentClass;->fieldPublicStaticLightGreylist:I,greylist
-LParentClass;-><init>(DB)V,greylist-max-o
-LParentClass;-><init>(DC)V,blacklist
-LParentClass;-><init>(DI)V,blacklist,core-platform-api
-LParentClass;-><init>(DZ)V,greylist
-LParentClass;-><init>(FB)V,greylist-max-o
-LParentClass;-><init>(FC)V,blacklist
-LParentClass;-><init>(FI)V,blacklist,core-platform-api
-LParentClass;-><init>(FZ)V,greylist
-LParentClass;-><init>(IB)V,greylist-max-o
-LParentClass;-><init>(IC)V,blacklist
-LParentClass;-><init>(II)V,blacklist,core-platform-api
-LParentClass;-><init>(IZ)V,greylist
-LParentClass;-><init>(JB)V,greylist-max-o
-LParentClass;-><init>(JC)V,blacklist
-LParentClass;-><init>(JI)V,blacklist,core-platform-api
-LParentClass;-><init>(JZ)V,greylist
-LParentClass;->methodPackageBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentClass;->methodPackageBlacklist()I,blacklist
-LParentClass;->methodPackageDarkGreylist()I,greylist-max-o
-LParentClass;->methodPackageLightGreylist()I,greylist
-LParentClass;->methodPackageStaticBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentClass;->methodPackageStaticBlacklist()I,blacklist
-LParentClass;->methodPackageStaticDarkGreylist()I,greylist-max-o
-LParentClass;->methodPackageStaticLightGreylist()I,greylist
-LParentClass;->methodPrivateBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentClass;->methodPrivateBlacklist()I,blacklist
-LParentClass;->methodPrivateDarkGreylist()I,greylist-max-o
-LParentClass;->methodPrivateLightGreylist()I,greylist
-LParentClass;->methodPrivateStaticBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentClass;->methodPrivateStaticBlacklist()I,blacklist
-LParentClass;->methodPrivateStaticDarkGreylist()I,greylist-max-o
-LParentClass;->methodPrivateStaticLightGreylist()I,greylist
-LParentClass;->methodProtectedBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentClass;->methodProtectedBlacklist()I,blacklist
-LParentClass;->methodProtectedDarkGreylist()I,greylist-max-o
-LParentClass;->methodProtectedLightGreylist()I,greylist
-LParentClass;->methodProtectedStaticBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentClass;->methodProtectedStaticBlacklist()I,blacklist
-LParentClass;->methodProtectedStaticDarkGreylist()I,greylist-max-o
-LParentClass;->methodProtectedStaticLightGreylist()I,greylist
-LParentClass;->methodPublicBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentClass;->methodPublicBlacklist()I,blacklist
-LParentClass;->methodPublicDarkGreylist()I,greylist-max-o
-LParentClass;->methodPublicLightGreylist()I,greylist
-LParentClass;->methodPublicStaticBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentClass;->methodPublicStaticBlacklist()I,blacklist
-LParentClass;->methodPublicStaticDarkGreylist()I,greylist-max-o
-LParentClass;->methodPublicStaticLightGreylist()I,greylist
-LParentInterface;->fieldPublicStaticBlacklistAndCorePlatformApi:I,blacklist,core-platform-api
-LParentInterface;->fieldPublicStaticBlacklist:I,blacklist
-LParentInterface;->fieldPublicStaticDarkGreylist:I,greylist-max-o
-LParentInterface;->fieldPublicStaticLightGreylist:I,greylist
-LParentInterface;->methodPublicBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentInterface;->methodPublicBlacklist()I,blacklist
-LParentInterface;->methodPublicDarkGreylist()I,greylist-max-o
-LParentInterface;->methodPublicDefaultBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentInterface;->methodPublicDefaultBlacklist()I,blacklist
-LParentInterface;->methodPublicDefaultDarkGreylist()I,greylist-max-o
-LParentInterface;->methodPublicDefaultLightGreylist()I,greylist
-LParentInterface;->methodPublicLightGreylist()I,greylist
-LParentInterface;->methodPublicStaticBlacklistAndCorePlatformApi()I,blacklist,core-platform-api
-LParentInterface;->methodPublicStaticBlacklist()I,blacklist
-LParentInterface;->methodPublicStaticDarkGreylist()I,greylist-max-o
-LParentInterface;->methodPublicStaticLightGreylist()I,greylist
+LNullaryConstructorBlocklistAndCorePlatformApi;-><init>()V,blocked,core-platform-api
+LNullaryConstructorBlocklist;-><init>()V,blocked
+LNullaryConstructorConditionallyBlocked;-><init>()V,max-target-o
+LNullaryConstructorUnsupported;-><init>()V,unsupported
+LParentClass;->fieldPackageBlocklistAndCorePlatformApi:I,blocked,core-platform-api
+LParentClass;->fieldPackageBlocklist:I,blocked
+LParentClass;->fieldPackageConditionallyBlocked:I,max-target-o
+LParentClass;->fieldPackageUnsupported:I,unsupported
+LParentClass;->fieldPackageStaticBlocklistAndCorePlatformApi:I,blocked,core-platform-api
+LParentClass;->fieldPackageStaticBlocklist:I,blocked
+LParentClass;->fieldPackageStaticConditionallyBlocked:I,max-target-o
+LParentClass;->fieldPackageStaticUnsupported:I,unsupported
+LParentClass;->fieldPrivateBlocklistAndCorePlatformApi:I,blocked,core-platform-api
+LParentClass;->fieldPrivateBlocklist:I,blocked
+LParentClass;->fieldPrivateConditionallyBlocked:I,max-target-o
+LParentClass;->fieldPrivateUnsupported:I,unsupported
+LParentClass;->fieldPrivateStaticBlocklistAndCorePlatformApi:I,blocked,core-platform-api
+LParentClass;->fieldPrivateStaticBlocklist:I,blocked
+LParentClass;->fieldPrivateStaticConditionallyBlocked:I,max-target-o
+LParentClass;->fieldPrivateStaticUnsupported:I,unsupported
+LParentClass;->fieldProtectedBlocklistAndCorePlatformApi:I,blocked,core-platform-api
+LParentClass;->fieldProtectedBlocklist:I,blocked
+LParentClass;->fieldProtectedConditionallyBlocked:I,max-target-o
+LParentClass;->fieldProtectedUnsupported:I,unsupported
+LParentClass;->fieldProtectedStaticBlocklistAndCorePlatformApi:I,blocked,core-platform-api
+LParentClass;->fieldProtectedStaticBlocklist:I,blocked
+LParentClass;->fieldProtectedStaticConditionallyBlocked:I,max-target-o
+LParentClass;->fieldProtectedStaticUnsupported:I,unsupported
+LParentClass;->fieldPublicBlocklistAndCorePlatformApiB:I,blocked,core-platform-api
+LParentClass;->fieldPublicBlocklistAndCorePlatformApi:I,blocked,core-platform-api
+LParentClass;->fieldPublicBlocklistB:I,blocked
+LParentClass;->fieldPublicBlocklist:I,blocked
+LParentClass;->fieldPublicConditionallyBlockedB:I,max-target-o
+LParentClass;->fieldPublicConditionallyBlocked:I,max-target-o
+LParentClass;->fieldPublicUnsupportedB:I,unsupported
+LParentClass;->fieldPublicUnsupported:I,unsupported
+LParentClass;->fieldPublicStaticBlocklistAndCorePlatformApiB:I,blocked,core-platform-api
+LParentClass;->fieldPublicStaticBlocklistAndCorePlatformApi:I,blocked,core-platform-api
+LParentClass;->fieldPublicStaticBlocklistB:I,blocked
+LParentClass;->fieldPublicStaticBlocklist:I,blocked
+LParentClass;->fieldPublicStaticConditionallyBlockedB:I,max-target-o
+LParentClass;->fieldPublicStaticConditionallyBlocked:I,max-target-o
+LParentClass;->fieldPublicStaticUnsupportedB:I,unsupported
+LParentClass;->fieldPublicStaticUnsupported:I,unsupported
+LParentClass;-><init>(DB)V,max-target-o
+LParentClass;-><init>(DC)V,blocked
+LParentClass;-><init>(DI)V,blocked,core-platform-api
+LParentClass;-><init>(DZ)V,unsupported
+LParentClass;-><init>(FB)V,max-target-o
+LParentClass;-><init>(FC)V,blocked
+LParentClass;-><init>(FI)V,blocked,core-platform-api
+LParentClass;-><init>(FZ)V,unsupported
+LParentClass;-><init>(IB)V,max-target-o
+LParentClass;-><init>(IC)V,blocked
+LParentClass;-><init>(II)V,blocked,core-platform-api
+LParentClass;-><init>(IZ)V,unsupported
+LParentClass;-><init>(JB)V,max-target-o
+LParentClass;-><init>(JC)V,blocked
+LParentClass;-><init>(JI)V,blocked,core-platform-api
+LParentClass;-><init>(JZ)V,unsupported
+LParentClass;->methodPackageBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentClass;->methodPackageBlocklist()I,blocked
+LParentClass;->methodPackageConditionallyBlocked()I,max-target-o
+LParentClass;->methodPackageUnsupported()I,unsupported
+LParentClass;->methodPackageStaticBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentClass;->methodPackageStaticBlocklist()I,blocked
+LParentClass;->methodPackageStaticConditionallyBlocked()I,max-target-o
+LParentClass;->methodPackageStaticUnsupported()I,unsupported
+LParentClass;->methodPrivateBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentClass;->methodPrivateBlocklist()I,blocked
+LParentClass;->methodPrivateConditionallyBlocked()I,max-target-o
+LParentClass;->methodPrivateUnsupported()I,unsupported
+LParentClass;->methodPrivateStaticBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentClass;->methodPrivateStaticBlocklist()I,blocked
+LParentClass;->methodPrivateStaticConditionallyBlocked()I,max-target-o
+LParentClass;->methodPrivateStaticUnsupported()I,unsupported
+LParentClass;->methodProtectedBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentClass;->methodProtectedBlocklist()I,blocked
+LParentClass;->methodProtectedConditionallyBlocked()I,max-target-o
+LParentClass;->methodProtectedUnsupported()I,unsupported
+LParentClass;->methodProtectedStaticBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentClass;->methodProtectedStaticBlocklist()I,blocked
+LParentClass;->methodProtectedStaticConditionallyBlocked()I,max-target-o
+LParentClass;->methodProtectedStaticUnsupported()I,unsupported
+LParentClass;->methodPublicBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentClass;->methodPublicBlocklist()I,blocked
+LParentClass;->methodPublicConditionallyBlocked()I,max-target-o
+LParentClass;->methodPublicUnsupported()I,unsupported
+LParentClass;->methodPublicStaticBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentClass;->methodPublicStaticBlocklist()I,blocked
+LParentClass;->methodPublicStaticConditionallyBlocked()I,max-target-o
+LParentClass;->methodPublicStaticUnsupported()I,unsupported
+LParentInterface;->fieldPublicStaticBlocklistAndCorePlatformApi:I,blocked,core-platform-api
+LParentInterface;->fieldPublicStaticBlocklist:I,blocked
+LParentInterface;->fieldPublicStaticConditionallyBlocked:I,max-target-o
+LParentInterface;->fieldPublicStaticUnsupported:I,unsupported
+LParentInterface;->methodPublicBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentInterface;->methodPublicBlocklist()I,blocked
+LParentInterface;->methodPublicConditionallyBlocked()I,max-target-o
+LParentInterface;->methodPublicDefaultBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentInterface;->methodPublicDefaultBlocklist()I,blocked
+LParentInterface;->methodPublicDefaultConditionallyBlocked()I,max-target-o
+LParentInterface;->methodPublicDefaultUnsupported()I,unsupported
+LParentInterface;->methodPublicUnsupported()I,unsupported
+LParentInterface;->methodPublicStaticBlocklistAndCorePlatformApi()I,blocked,core-platform-api
+LParentInterface;->methodPublicStaticBlocklist()I,blocked
+LParentInterface;->methodPublicStaticConditionallyBlocked()I,max-target-o
+LParentInterface;->methodPublicStaticUnsupported()I,unsupported
diff --git a/test/674-hiddenapi/hiddenapi.cc b/test/674-hiddenapi/hiddenapi.cc
index 742b6b3..ebe9d10 100644
--- a/test/674-hiddenapi/hiddenapi.cc
+++ b/test/674-hiddenapi/hiddenapi.cc
@@ -27,8 +27,8 @@
 namespace art {
 namespace Test674HiddenApi {
 
-// Should be the same as dalvik.system.VMRuntime.PREVENT_META_REFLECTION_BLACKLIST_ACCESS
-static constexpr uint64_t kPreventMetaReflectionBlacklistAccess = 142365358;
+// Should be the same as dalvik.system.VMRuntime.PREVENT_META_REFLECTION_BLOCKLIST_ACCESS
+static constexpr uint64_t kPreventMetaReflectionBlocklistAccess = 142365358;
 
 std::vector<std::vector<std::unique_ptr<const DexFile>>> opened_dex_files;
 
@@ -37,7 +37,7 @@
   runtime->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
   runtime->SetCorePlatformApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
   runtime->SetTargetSdkVersion(
-      static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxO().GetMaxAllowedSdkVersion()));
+      static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetO().GetMaxAllowedSdkVersion()));
   runtime->SetDedupeHiddenApiWarnings(false);
 }
 
@@ -85,7 +85,7 @@
   return int_index;
 }
 
-extern "C" JNIEXPORT void JNICALL Java_Main_setWhitelistAll(JNIEnv*, jclass, jboolean value) {
+extern "C" JNIEXPORT void JNICALL Java_Main_setSdkAll(JNIEnv*, jclass, jboolean value) {
   std::vector<std::string> exemptions;
   if (value != JNI_FALSE) {
     exemptions.push_back("L");
@@ -321,15 +321,16 @@
 
 extern "C" JNIEXPORT void JNICALL Java_Reflection_setHiddenApiCheckHardening(JNIEnv*, jclass,
     jboolean value) {
-  std::set<uint64_t> disabled_changes = Runtime::Current()->GetDisabledCompatChanges();
+  CompatFramework& compat_framework = Runtime::Current()->GetCompatFramework();
+  std::set<uint64_t> disabled_changes = compat_framework.GetDisabledCompatChanges();
   if (value == JNI_TRUE) {
     // If hidden api check hardening is enabled, remove it from the set of disabled changes.
-    disabled_changes.erase(kPreventMetaReflectionBlacklistAccess);
+    disabled_changes.erase(kPreventMetaReflectionBlocklistAccess);
   } else {
     // If hidden api check hardening is disabled, add it to the set of disabled changes.
-    disabled_changes.insert(kPreventMetaReflectionBlacklistAccess);
+    disabled_changes.insert(kPreventMetaReflectionBlocklistAccess);
   }
-  Runtime::Current()->SetDisabledCompatChanges(disabled_changes);
+  compat_framework.SetDisabledCompatChanges(disabled_changes);
 }
 
 }  // namespace Test674HiddenApi
diff --git a/test/674-hiddenapi/run b/test/674-hiddenapi/run
index 2babeef..b57d10a 100755
--- a/test/674-hiddenapi/run
+++ b/test/674-hiddenapi/run
@@ -16,4 +16,7 @@
 
 # Make verification soft fail so that we can re-verify boot classpath
 # methods at runtime.
-exec ${RUN} $@ --verify-soft-fail
\ No newline at end of file
+#
+# N.B. Compilation of secondary dexes can prevent hidden API checks, e.g. if
+# a blacklisted field get is inlined.
+exec ${RUN} $@ --verify-soft-fail --no-secondary-compilation
diff --git a/test/674-hiddenapi/src-art/Main.java b/test/674-hiddenapi/src-art/Main.java
index c92d352..13c4e81 100644
--- a/test/674-hiddenapi/src-art/Main.java
+++ b/test/674-hiddenapi/src-art/Main.java
@@ -89,7 +89,7 @@
   }
 
   private static void doTest(DexDomain parentDomain, DexDomain childDomain,
-      boolean whitelistAllApis) throws Exception {
+      boolean addAllApisToSdk) throws Exception {
     // Load parent dex if it is not in boot class path.
     ClassLoader parentLoader = null;
     if (parentDomain == DexDomain.Application) {
@@ -114,17 +114,17 @@
     // be loaded once, but for some reason even classes from a class loader
     // cannot register their native methods against symbols in a shared library
     // loaded by their parent class loader.
-    String nativeLibCopy = createNativeLibCopy(parentDomain, childDomain, whitelistAllApis);
+    String nativeLibCopy = createNativeLibCopy(parentDomain, childDomain, addAllApisToSdk);
 
-    // Set exemptions to "L" (matches all classes) if we are testing whitelisting.
-    setWhitelistAll(whitelistAllApis);
+    // Set exemptions to "L" (matches all classes) if we are testing sdk APIs.
+    setSdkAll(addAllApisToSdk);
 
     // Invoke ChildClass.runTest
     Class<?> childClass = Class.forName("ChildClass", true, childLoader);
     Method runTestMethod = childClass.getDeclaredMethod(
         "runTest", String.class, Integer.TYPE, Integer.TYPE, Boolean.TYPE);
     runTestMethod.invoke(null, nativeLibCopy, parentDomain.ordinal(), childDomain.ordinal(),
-        whitelistAllApis);
+        addAllApisToSdk);
   }
 
   // Routine which tries to figure out the absolute path of our native library.
@@ -150,10 +150,10 @@
   // Copy native library to a new file with a unique name so it does not
   // conflict with other loaded instance of the same binary file.
   private static String createNativeLibCopy(DexDomain parentDomain, DexDomain childDomain,
-      boolean whitelistAllApis) throws Exception {
+      boolean addAllApisToSdk) throws Exception {
     String tempFileName = System.mapLibraryName(
         "hiddenapitest_" + (parentDomain.ordinal()) + (childDomain.ordinal()) +
-        (whitelistAllApis ? "1" : "0"));
+        (addAllApisToSdk ? "1" : "0"));
     File tempFile = new File(System.getenv("DEX_LOCATION"), tempFileName);
     Files.copy(new File(nativeLibFileName).toPath(), tempFile.toPath());
     return tempFile.getAbsolutePath();
@@ -181,5 +181,5 @@
   private static native int appendToBootClassLoader(String dexPath, boolean isCorePlatform);
   private static native void setDexDomain(int index, boolean isCorePlatform);
   private static native void init();
-  private static native void setWhitelistAll(boolean value);
+  private static native void setSdkAll(boolean value);
 }
diff --git a/test/674-hiddenapi/src-ex/ChildClass.java b/test/674-hiddenapi/src-ex/ChildClass.java
index 9295655..128d701 100644
--- a/test/674-hiddenapi/src-ex/ChildClass.java
+++ b/test/674-hiddenapi/src-ex/ChildClass.java
@@ -42,11 +42,11 @@
   }
 
   enum Hiddenness {
-    Whitelist(PrimitiveType.TShort),
-    LightGreylist(PrimitiveType.TBoolean),
-    DarkGreylist(PrimitiveType.TByte),
-    Blacklist(PrimitiveType.TCharacter),
-    BlacklistAndCorePlatformApi(PrimitiveType.TInteger);
+    Sdk(PrimitiveType.TShort),
+    Unsupported(PrimitiveType.TBoolean),
+    ConditionallyBlocked(PrimitiveType.TByte),
+    Blocklist(PrimitiveType.TCharacter),
+    BlocklistAndCorePlatformApi(PrimitiveType.TInteger);
 
     Hiddenness(PrimitiveType type) { mAssociatedType = type; }
     public PrimitiveType mAssociatedType;
@@ -78,14 +78,14 @@
   private static final boolean booleanValues[] = new boolean[] { false, true };
 
   public static void runTest(String libFileName, int parentDomainOrdinal,
-      int childDomainOrdinal, boolean everythingWhitelisted) throws Exception {
+      int childDomainOrdinal, boolean everythingSdked) throws Exception {
     System.load(libFileName);
 
     parentDomain = DexDomain.values()[parentDomainOrdinal];
     childDomain = DexDomain.values()[childDomainOrdinal];
 
     configMessage = "parentDomain=" + parentDomain.name() + ", childDomain=" + childDomain.name()
-        + ", everythingWhitelisted=" + everythingWhitelisted;
+        + ", everythingSdked=" + everythingSdked;
 
     // Check expectations about loading into boot class path.
     boolean isParentInBoot = (ParentClass.class.getClassLoader().getParent() == null);
@@ -100,10 +100,9 @@
       throw new RuntimeException("Expected ChildClass " + (expectedChildInBoot ? "" : "not ") +
                                  "in boot class path");
     }
-    ChildClass.everythingWhitelisted = everythingWhitelisted;
+    ChildClass.everythingSdked = everythingSdked;
 
     boolean isSameBoot = (isParentInBoot == isChildInBoot);
-    boolean isDebuggable = VMRuntime.getRuntime().isJavaDebuggable();
 
     // For compat reasons, meta-reflection should still be usable by apps if hidden api check
     // hardening is disabled (i.e. target SDK is Q or earlier). The only configuration where this
@@ -118,18 +117,18 @@
       final boolean invokesMemberCallback;
       // Warnings are now disabled whenever access is granted, even for
       // greylisted APIs. This is the behaviour for release builds.
-      if (everythingWhitelisted || hiddenness == Hiddenness.Whitelist) {
+      if (everythingSdked || hiddenness == Hiddenness.Sdk) {
         expected = Behaviour.Granted;
         invokesMemberCallback = false;
       } else if (parentDomain == DexDomain.CorePlatform && childDomain == DexDomain.Platform) {
-        expected = (hiddenness == Hiddenness.BlacklistAndCorePlatformApi)
+        expected = (hiddenness == Hiddenness.BlocklistAndCorePlatformApi)
             ? Behaviour.Granted : Behaviour.Denied;
         invokesMemberCallback = false;
       } else if (isSameBoot) {
         expected = Behaviour.Granted;
         invokesMemberCallback = false;
-      } else if (hiddenness == Hiddenness.Blacklist ||
-                 hiddenness == Hiddenness.BlacklistAndCorePlatformApi) {
+      } else if (hiddenness == Hiddenness.Blocklist ||
+                 hiddenness == Hiddenness.BlocklistAndCorePlatformApi) {
         expected = Behaviour.Denied;
         invokesMemberCallback = true;
       } else {
@@ -552,7 +551,7 @@
 
   private static DexDomain parentDomain;
   private static DexDomain childDomain;
-  private static boolean everythingWhitelisted;
+  private static boolean everythingSdked;
 
   private static String configMessage;
 }
diff --git a/test/674-hiddenapi/src-ex/Linking.java b/test/674-hiddenapi/src-ex/Linking.java
index 5aa3663..a370d14 100644
--- a/test/674-hiddenapi/src-ex/Linking.java
+++ b/test/674-hiddenapi/src-ex/Linking.java
@@ -38,266 +38,266 @@
 
 // INSTANCE FIELD GET
 
-class LinkFieldGetWhitelist {
+class LinkFieldGetSdk {
   public static int access() {
-    return new ParentClass().fieldPublicWhitelist;
+    return new ParentClass().fieldPublicSdk;
   }
 }
 
-class LinkFieldGetLightGreylist {
+class LinkFieldGetUnsupported {
   public static int access() {
-    return new ParentClass().fieldPublicLightGreylist;
+    return new ParentClass().fieldPublicUnsupported;
   }
 }
 
-class LinkFieldGetDarkGreylist {
+class LinkFieldGetConditionallyBlocked {
   public static int access() {
-    return new ParentClass().fieldPublicDarkGreylist;
+    return new ParentClass().fieldPublicConditionallyBlocked;
   }
 }
 
-class LinkFieldGetBlacklist {
+class LinkFieldGetBlocklist {
   public static int access() {
-    return new ParentClass().fieldPublicBlacklist;
+    return new ParentClass().fieldPublicBlocklist;
   }
 }
 
-class LinkFieldGetBlacklistAndCorePlatformApi {
+class LinkFieldGetBlocklistAndCorePlatformApi {
   public static int access() {
-    return new ParentClass().fieldPublicBlacklistAndCorePlatformApi;
+    return new ParentClass().fieldPublicBlocklistAndCorePlatformApi;
   }
 }
 
 // INSTANCE FIELD SET
 
-class LinkFieldSetWhitelist {
+class LinkFieldSetSdk {
   public static void access(int x) {
     // Need to use a different field from the getter to bypass DexCache.
-    new ParentClass().fieldPublicWhitelistB = x;
+    new ParentClass().fieldPublicSdkB = x;
   }
 }
 
-class LinkFieldSetLightGreylist {
+class LinkFieldSetUnsupported {
   public static void access(int x) {
     // Need to use a different field from the getter to bypass DexCache.
-    new ParentClass().fieldPublicLightGreylistB = x;
+    new ParentClass().fieldPublicUnsupportedB = x;
   }
 }
 
-class LinkFieldSetDarkGreylist {
+class LinkFieldSetConditionallyBlocked {
   public static void access(int x) {
     // Need to use a different field from the getter to bypass DexCache.
-    new ParentClass().fieldPublicDarkGreylistB = x;
+    new ParentClass().fieldPublicConditionallyBlockedB = x;
   }
 }
 
-class LinkFieldSetBlacklist {
+class LinkFieldSetBlocklist {
   public static void access(int x) {
     // Need to use a different field from the getter to bypass DexCache.
-    new ParentClass().fieldPublicBlacklistB = x;
+    new ParentClass().fieldPublicBlocklistB = x;
   }
 }
 
-class LinkFieldSetBlacklistAndCorePlatformApi {
+class LinkFieldSetBlocklistAndCorePlatformApi {
   public static void access(int x) {
     // Need to use a different field from the getter to bypass DexCache.
-    new ParentClass().fieldPublicBlacklistAndCorePlatformApiB = x;
+    new ParentClass().fieldPublicBlocklistAndCorePlatformApiB = x;
   }
 }
 
 // STATIC FIELD GET
 
-class LinkFieldGetStaticWhitelist {
+class LinkFieldGetStaticSdk {
   public static int access() {
-    return ParentClass.fieldPublicStaticWhitelist;
+    return ParentClass.fieldPublicStaticSdk;
   }
 }
 
-class LinkFieldGetStaticLightGreylist {
+class LinkFieldGetStaticUnsupported {
   public static int access() {
-    return ParentClass.fieldPublicStaticLightGreylist;
+    return ParentClass.fieldPublicStaticUnsupported;
   }
 }
 
-class LinkFieldGetStaticDarkGreylist {
+class LinkFieldGetStaticConditionallyBlocked {
   public static int access() {
-    return ParentClass.fieldPublicStaticDarkGreylist;
+    return ParentClass.fieldPublicStaticConditionallyBlocked;
   }
 }
 
-class LinkFieldGetStaticBlacklist {
+class LinkFieldGetStaticBlocklist {
   public static int access() {
-    return ParentClass.fieldPublicStaticBlacklist;
+    return ParentClass.fieldPublicStaticBlocklist;
   }
 }
 
-class LinkFieldGetStaticBlacklistAndCorePlatformApi {
+class LinkFieldGetStaticBlocklistAndCorePlatformApi {
   public static int access() {
-    return ParentClass.fieldPublicStaticBlacklistAndCorePlatformApi;
+    return ParentClass.fieldPublicStaticBlocklistAndCorePlatformApi;
   }
 }
 
 // STATIC FIELD SET
 
-class LinkFieldSetStaticWhitelist {
+class LinkFieldSetStaticSdk {
   public static void access(int x) {
     // Need to use a different field from the getter to bypass DexCache.
-    ParentClass.fieldPublicStaticWhitelistB = x;
+    ParentClass.fieldPublicStaticSdkB = x;
   }
 }
 
-class LinkFieldSetStaticLightGreylist {
+class LinkFieldSetStaticUnsupported {
   public static void access(int x) {
     // Need to use a different field from the getter to bypass DexCache.
-    ParentClass.fieldPublicStaticLightGreylistB = x;
+    ParentClass.fieldPublicStaticUnsupportedB = x;
   }
 }
 
-class LinkFieldSetStaticDarkGreylist {
+class LinkFieldSetStaticConditionallyBlocked {
   public static void access(int x) {
     // Need to use a different field from the getter to bypass DexCache.
-    ParentClass.fieldPublicStaticDarkGreylistB = x;
+    ParentClass.fieldPublicStaticConditionallyBlockedB = x;
   }
 }
 
-class LinkFieldSetStaticBlacklist {
+class LinkFieldSetStaticBlocklist {
   public static void access(int x) {
     // Need to use a different field from the getter to bypass DexCache.
-    ParentClass.fieldPublicStaticBlacklistB = x;
+    ParentClass.fieldPublicStaticBlocklistB = x;
   }
 }
 
-class LinkFieldSetStaticBlacklistAndCorePlatformApi {
+class LinkFieldSetStaticBlocklistAndCorePlatformApi {
   public static void access(int x) {
     // Need to use a different field from the getter to bypass DexCache.
-    ParentClass.fieldPublicStaticBlacklistAndCorePlatformApiB = x;
+    ParentClass.fieldPublicStaticBlocklistAndCorePlatformApiB = x;
   }
 }
 
 // INVOKE INSTANCE METHOD
 
-class LinkMethodWhitelist {
+class LinkMethodSdk {
   public static int access() {
-    return new ParentClass().methodPublicWhitelist();
+    return new ParentClass().methodPublicSdk();
   }
 }
 
-class LinkMethodLightGreylist {
+class LinkMethodUnsupported {
   public static int access() {
-    return new ParentClass().methodPublicLightGreylist();
+    return new ParentClass().methodPublicUnsupported();
   }
 }
 
-class LinkMethodDarkGreylist {
+class LinkMethodConditionallyBlocked {
   public static int access() {
-    return new ParentClass().methodPublicDarkGreylist();
+    return new ParentClass().methodPublicConditionallyBlocked();
   }
 }
 
-class LinkMethodBlacklist {
+class LinkMethodBlocklist {
   public static int access() {
-    return new ParentClass().methodPublicBlacklist();
+    return new ParentClass().methodPublicBlocklist();
   }
 }
 
-class LinkMethodBlacklistAndCorePlatformApi {
+class LinkMethodBlocklistAndCorePlatformApi {
   public static int access() {
-    return new ParentClass().methodPublicBlacklistAndCorePlatformApi();
+    return new ParentClass().methodPublicBlocklistAndCorePlatformApi();
   }
 }
 
 // INVOKE INSTANCE INTERFACE METHOD
 
-class LinkMethodInterfaceWhitelist {
+class LinkMethodInterfaceSdk {
   public static int access() {
-    return DummyClass.getInterfaceInstance().methodPublicWhitelist();
+    return SampleClass.getInterfaceInstance().methodPublicSdk();
   }
 }
 
-class LinkMethodInterfaceLightGreylist {
+class LinkMethodInterfaceUnsupported {
   public static int access() {
-    return DummyClass.getInterfaceInstance().methodPublicLightGreylist();
+    return SampleClass.getInterfaceInstance().methodPublicUnsupported();
   }
 }
 
-class LinkMethodInterfaceDarkGreylist {
+class LinkMethodInterfaceConditionallyBlocked {
   public static int access() {
-    return DummyClass.getInterfaceInstance().methodPublicDarkGreylist();
+    return SampleClass.getInterfaceInstance().methodPublicConditionallyBlocked();
   }
 }
 
-class LinkMethodInterfaceBlacklist {
+class LinkMethodInterfaceBlocklist {
   public static int access() {
-    return DummyClass.getInterfaceInstance().methodPublicBlacklist();
+    return SampleClass.getInterfaceInstance().methodPublicBlocklist();
   }
 }
 
-class LinkMethodInterfaceBlacklistAndCorePlatformApi {
+class LinkMethodInterfaceBlocklistAndCorePlatformApi {
   public static int access() {
-    return DummyClass.getInterfaceInstance().methodPublicBlacklistAndCorePlatformApi();
+    return SampleClass.getInterfaceInstance().methodPublicBlocklistAndCorePlatformApi();
   }
 }
 
 // INVOKE STATIC METHOD
 
-class LinkMethodStaticWhitelist {
+class LinkMethodStaticSdk {
   public static int access() {
-    return ParentClass.methodPublicStaticWhitelist();
+    return ParentClass.methodPublicStaticSdk();
   }
 }
 
-class LinkMethodStaticLightGreylist {
+class LinkMethodStaticUnsupported {
   public static int access() {
-    return ParentClass.methodPublicStaticLightGreylist();
+    return ParentClass.methodPublicStaticUnsupported();
   }
 }
 
-class LinkMethodStaticDarkGreylist {
+class LinkMethodStaticConditionallyBlocked {
   public static int access() {
-    return ParentClass.methodPublicStaticDarkGreylist();
+    return ParentClass.methodPublicStaticConditionallyBlocked();
   }
 }
 
-class LinkMethodStaticBlacklist {
+class LinkMethodStaticBlocklist {
   public static int access() {
-    return ParentClass.methodPublicStaticBlacklist();
+    return ParentClass.methodPublicStaticBlocklist();
   }
 }
 
-class LinkMethodStaticBlacklistAndCorePlatformApi {
+class LinkMethodStaticBlocklistAndCorePlatformApi {
   public static int access() {
-    return ParentClass.methodPublicStaticBlacklistAndCorePlatformApi();
+    return ParentClass.methodPublicStaticBlocklistAndCorePlatformApi();
   }
 }
 
 // INVOKE INTERFACE STATIC METHOD
 
-class LinkMethodInterfaceStaticWhitelist {
+class LinkMethodInterfaceStaticSdk {
   public static int access() {
-    return ParentInterface.methodPublicStaticWhitelist();
+    return ParentInterface.methodPublicStaticSdk();
   }
 }
 
-class LinkMethodInterfaceStaticLightGreylist {
+class LinkMethodInterfaceStaticUnsupported {
   public static int access() {
-    return ParentInterface.methodPublicStaticLightGreylist();
+    return ParentInterface.methodPublicStaticUnsupported();
   }
 }
 
-class LinkMethodInterfaceStaticDarkGreylist {
+class LinkMethodInterfaceStaticConditionallyBlocked {
   public static int access() {
-    return ParentInterface.methodPublicStaticDarkGreylist();
+    return ParentInterface.methodPublicStaticConditionallyBlocked();
   }
 }
 
-class LinkMethodInterfaceStaticBlacklist {
+class LinkMethodInterfaceStaticBlocklist {
   public static int access() {
-    return ParentInterface.methodPublicStaticBlacklist();
+    return ParentInterface.methodPublicStaticBlocklist();
   }
 }
 
-class LinkMethodInterfaceStaticBlacklistAndCorePlatformApi {
+class LinkMethodInterfaceStaticBlocklistAndCorePlatformApi {
   public static int access() {
-    return ParentInterface.methodPublicStaticBlacklistAndCorePlatformApi();
+    return ParentInterface.methodPublicStaticBlocklistAndCorePlatformApi();
   }
 }
diff --git a/test/674-hiddenapi/src/DummyClass.java b/test/674-hiddenapi/src/DummyClass.java
deleted file mode 100644
index afba747..0000000
--- a/test/674-hiddenapi/src/DummyClass.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2017 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 DummyClass implements ParentInterface {
-  public int methodPublicWhitelist() { return 1; }
-  public int methodPublicLightGreylist() { return 2; }
-  public int methodPublicDarkGreylist() { return 3; }
-  public int methodPublicBlacklist() { return 4; }
-  public int methodPublicBlacklistAndCorePlatformApi() { return 5; }
-
-  public static ParentInterface getInterfaceInstance() {
-    return new DummyClass();
-  }
-}
diff --git a/test/674-hiddenapi/src/NullaryConstructorBlacklist.java b/test/674-hiddenapi/src/NullaryConstructorBlacklist.java
deleted file mode 100644
index 5bf6278..0000000
--- a/test/674-hiddenapi/src/NullaryConstructorBlacklist.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2017 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 NullaryConstructorBlacklist {
-  public NullaryConstructorBlacklist() { x = 22; }
-  public NullaryConstructorBlacklist(int y) { x = y; }
-  protected int x;
-}
diff --git a/test/674-hiddenapi/src/NullaryConstructorBlacklistAndCorePlatformApi.java b/test/674-hiddenapi/src/NullaryConstructorBlacklistAndCorePlatformApi.java
deleted file mode 100644
index 86af29e..0000000
--- a/test/674-hiddenapi/src/NullaryConstructorBlacklistAndCorePlatformApi.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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 NullaryConstructorBlacklistAndCorePlatformApi {
-  public NullaryConstructorBlacklistAndCorePlatformApi() { x = 22; }
-  public NullaryConstructorBlacklistAndCorePlatformApi(int y) { x = y; }
-  protected int x;
-}
diff --git a/test/674-hiddenapi/src/NullaryConstructorBlocklist.java b/test/674-hiddenapi/src/NullaryConstructorBlocklist.java
new file mode 100644
index 0000000..62ec521
--- /dev/null
+++ b/test/674-hiddenapi/src/NullaryConstructorBlocklist.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 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 NullaryConstructorBlocklist {
+  public NullaryConstructorBlocklist() { x = 22; }
+  public NullaryConstructorBlocklist(int y) { x = y; }
+  protected int x;
+}
diff --git a/test/674-hiddenapi/src/NullaryConstructorBlocklistAndCorePlatformApi.java b/test/674-hiddenapi/src/NullaryConstructorBlocklistAndCorePlatformApi.java
new file mode 100644
index 0000000..4e993f5
--- /dev/null
+++ b/test/674-hiddenapi/src/NullaryConstructorBlocklistAndCorePlatformApi.java
@@ -0,0 +1,21 @@
+/*
+ * 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 NullaryConstructorBlocklistAndCorePlatformApi {
+  public NullaryConstructorBlocklistAndCorePlatformApi() { x = 22; }
+  public NullaryConstructorBlocklistAndCorePlatformApi(int y) { x = y; }
+  protected int x;
+}
diff --git a/test/674-hiddenapi/src/NullaryConstructorConditionallyBlocked.java b/test/674-hiddenapi/src/NullaryConstructorConditionallyBlocked.java
new file mode 100644
index 0000000..e80fe9b
--- /dev/null
+++ b/test/674-hiddenapi/src/NullaryConstructorConditionallyBlocked.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 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 NullaryConstructorConditionallyBlocked {
+  public NullaryConstructorConditionallyBlocked() { x = 22; }
+  public NullaryConstructorConditionallyBlocked(int y) { x = y; }
+  protected int x;
+}
diff --git a/test/674-hiddenapi/src/NullaryConstructorDarkGreylist.java b/test/674-hiddenapi/src/NullaryConstructorDarkGreylist.java
deleted file mode 100644
index c25a767..0000000
--- a/test/674-hiddenapi/src/NullaryConstructorDarkGreylist.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2017 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 NullaryConstructorDarkGreylist {
-  public NullaryConstructorDarkGreylist() { x = 22; }
-  public NullaryConstructorDarkGreylist(int y) { x = y; }
-  protected int x;
-}
diff --git a/test/674-hiddenapi/src/NullaryConstructorLightGreylist.java b/test/674-hiddenapi/src/NullaryConstructorLightGreylist.java
deleted file mode 100644
index d5dac8b..0000000
--- a/test/674-hiddenapi/src/NullaryConstructorLightGreylist.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2017 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 NullaryConstructorLightGreylist {
-  public NullaryConstructorLightGreylist() { x = 22; }
-  public NullaryConstructorLightGreylist(int y) { x = y; }
-  protected int x;
-}
diff --git a/test/674-hiddenapi/src/NullaryConstructorSdk.java b/test/674-hiddenapi/src/NullaryConstructorSdk.java
new file mode 100644
index 0000000..62f4fa7
--- /dev/null
+++ b/test/674-hiddenapi/src/NullaryConstructorSdk.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 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 NullaryConstructorSdk {
+  public NullaryConstructorSdk() { x = 22; }
+  public NullaryConstructorSdk(int y) { x = y; }
+  protected int x;
+}
diff --git a/test/674-hiddenapi/src/NullaryConstructorUnsupported.java b/test/674-hiddenapi/src/NullaryConstructorUnsupported.java
new file mode 100644
index 0000000..958472d
--- /dev/null
+++ b/test/674-hiddenapi/src/NullaryConstructorUnsupported.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 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 NullaryConstructorUnsupported {
+  public NullaryConstructorUnsupported() { x = 22; }
+  public NullaryConstructorUnsupported(int y) { x = y; }
+  protected int x;
+}
diff --git a/test/674-hiddenapi/src/NullaryConstructorWhitelist.java b/test/674-hiddenapi/src/NullaryConstructorWhitelist.java
deleted file mode 100644
index d101907..0000000
--- a/test/674-hiddenapi/src/NullaryConstructorWhitelist.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2017 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 NullaryConstructorWhitelist {
-  public NullaryConstructorWhitelist() { x = 22; }
-  public NullaryConstructorWhitelist(int y) { x = y; }
-  protected int x;
-}
diff --git a/test/674-hiddenapi/src/ParentClass.java b/test/674-hiddenapi/src/ParentClass.java
index 1442392..fc31bed 100644
--- a/test/674-hiddenapi/src/ParentClass.java
+++ b/test/674-hiddenapi/src/ParentClass.java
@@ -19,125 +19,125 @@
 
   // INSTANCE FIELD
 
-  public int fieldPublicWhitelist = 211;
-  int fieldPackageWhitelist = 212;
-  protected int fieldProtectedWhitelist = 213;
-  private int fieldPrivateWhitelist = 214;
-  public int fieldPublicWhitelistB = 215;
+  public int fieldPublicSdk = 211;
+  int fieldPackageSdk = 212;
+  protected int fieldProtectedSdk = 213;
+  private int fieldPrivateSdk = 214;
+  public int fieldPublicSdkB = 215;
 
-  public int fieldPublicLightGreylist = 221;
-  int fieldPackageLightGreylist = 222;
-  protected int fieldProtectedLightGreylist = 223;
-  private int fieldPrivateLightGreylist = 224;
-  public int fieldPublicLightGreylistB = 225;
+  public int fieldPublicUnsupported = 221;
+  int fieldPackageUnsupported = 222;
+  protected int fieldProtectedUnsupported = 223;
+  private int fieldPrivateUnsupported = 224;
+  public int fieldPublicUnsupportedB = 225;
 
-  public int fieldPublicDarkGreylist = 231;
-  int fieldPackageDarkGreylist = 232;
-  protected int fieldProtectedDarkGreylist = 233;
-  private int fieldPrivateDarkGreylist = 234;
-  public int fieldPublicDarkGreylistB = 235;
+  public int fieldPublicConditionallyBlocked = 231;
+  int fieldPackageConditionallyBlocked = 232;
+  protected int fieldProtectedConditionallyBlocked = 233;
+  private int fieldPrivateConditionallyBlocked = 234;
+  public int fieldPublicConditionallyBlockedB = 235;
 
-  public int fieldPublicBlacklist = 241;
-  int fieldPackageBlacklist = 242;
-  protected int fieldProtectedBlacklist = 243;
-  private int fieldPrivateBlacklist = 244;
-  public int fieldPublicBlacklistB = 245;
+  public int fieldPublicBlocklist = 241;
+  int fieldPackageBlocklist = 242;
+  protected int fieldProtectedBlocklist = 243;
+  private int fieldPrivateBlocklist = 244;
+  public int fieldPublicBlocklistB = 245;
 
-  public int fieldPublicBlacklistAndCorePlatformApi = 251;
-  int fieldPackageBlacklistAndCorePlatformApi = 252;
-  protected int fieldProtectedBlacklistAndCorePlatformApi = 253;
-  private int fieldPrivateBlacklistAndCorePlatformApi = 254;
-  public int fieldPublicBlacklistAndCorePlatformApiB = 255;
+  public int fieldPublicBlocklistAndCorePlatformApi = 251;
+  int fieldPackageBlocklistAndCorePlatformApi = 252;
+  protected int fieldProtectedBlocklistAndCorePlatformApi = 253;
+  private int fieldPrivateBlocklistAndCorePlatformApi = 254;
+  public int fieldPublicBlocklistAndCorePlatformApiB = 255;
 
   // STATIC FIELD
 
-  public static int fieldPublicStaticWhitelist = 111;
-  static int fieldPackageStaticWhitelist = 112;
-  protected static int fieldProtectedStaticWhitelist = 113;
-  private static int fieldPrivateStaticWhitelist = 114;
-  public static int fieldPublicStaticWhitelistB = 115;
+  public static int fieldPublicStaticSdk = 111;
+  static int fieldPackageStaticSdk = 112;
+  protected static int fieldProtectedStaticSdk = 113;
+  private static int fieldPrivateStaticSdk = 114;
+  public static int fieldPublicStaticSdkB = 115;
 
-  public static int fieldPublicStaticLightGreylist = 121;
-  static int fieldPackageStaticLightGreylist = 122;
-  protected static int fieldProtectedStaticLightGreylist = 123;
-  private static int fieldPrivateStaticLightGreylist = 124;
-  public static int fieldPublicStaticLightGreylistB = 125;
+  public static int fieldPublicStaticUnsupported = 121;
+  static int fieldPackageStaticUnsupported = 122;
+  protected static int fieldProtectedStaticUnsupported = 123;
+  private static int fieldPrivateStaticUnsupported = 124;
+  public static int fieldPublicStaticUnsupportedB = 125;
 
-  public static int fieldPublicStaticDarkGreylist = 131;
-  static int fieldPackageStaticDarkGreylist = 132;
-  protected static int fieldProtectedStaticDarkGreylist = 133;
-  private static int fieldPrivateStaticDarkGreylist = 134;
-  public static int fieldPublicStaticDarkGreylistB = 135;
+  public static int fieldPublicStaticConditionallyBlocked = 131;
+  static int fieldPackageStaticConditionallyBlocked = 132;
+  protected static int fieldProtectedStaticConditionallyBlocked = 133;
+  private static int fieldPrivateStaticConditionallyBlocked = 134;
+  public static int fieldPublicStaticConditionallyBlockedB = 135;
 
-  public static int fieldPublicStaticBlacklist = 141;
-  static int fieldPackageStaticBlacklist = 142;
-  protected static int fieldProtectedStaticBlacklist = 143;
-  private static int fieldPrivateStaticBlacklist = 144;
-  public static int fieldPublicStaticBlacklistB = 145;
+  public static int fieldPublicStaticBlocklist = 141;
+  static int fieldPackageStaticBlocklist = 142;
+  protected static int fieldProtectedStaticBlocklist = 143;
+  private static int fieldPrivateStaticBlocklist = 144;
+  public static int fieldPublicStaticBlocklistB = 145;
 
-  public static int fieldPublicStaticBlacklistAndCorePlatformApi = 151;
-  static int fieldPackageStaticBlacklistAndCorePlatformApi = 152;
-  protected static int fieldProtectedStaticBlacklistAndCorePlatformApi = 153;
-  private static int fieldPrivateStaticBlacklistAndCorePlatformApi = 154;
-  public static int fieldPublicStaticBlacklistAndCorePlatformApiB = 155;
+  public static int fieldPublicStaticBlocklistAndCorePlatformApi = 151;
+  static int fieldPackageStaticBlocklistAndCorePlatformApi = 152;
+  protected static int fieldProtectedStaticBlocklistAndCorePlatformApi = 153;
+  private static int fieldPrivateStaticBlocklistAndCorePlatformApi = 154;
+  public static int fieldPublicStaticBlocklistAndCorePlatformApiB = 155;
 
   // INSTANCE METHOD
 
-  public int methodPublicWhitelist() { return 411; }
-  int methodPackageWhitelist() { return 412; }
-  protected int methodProtectedWhitelist() { return 413; }
-  private int methodPrivateWhitelist() { return 414; }
+  public int methodPublicSdk() { return 411; }
+  int methodPackageSdk() { return 412; }
+  protected int methodProtectedSdk() { return 413; }
+  private int methodPrivateSdk() { return 414; }
 
-  public int methodPublicLightGreylist() { return 421; }
-  int methodPackageLightGreylist() { return 422; }
-  protected int methodProtectedLightGreylist() { return 423; }
-  private int methodPrivateLightGreylist() { return 424; }
+  public int methodPublicUnsupported() { return 421; }
+  int methodPackageUnsupported() { return 422; }
+  protected int methodProtectedUnsupported() { return 423; }
+  private int methodPrivateUnsupported() { return 424; }
 
-  public int methodPublicDarkGreylist() { return 431; }
-  int methodPackageDarkGreylist() { return 432; }
-  protected int methodProtectedDarkGreylist() { return 433; }
-  private int methodPrivateDarkGreylist() { return 434; }
+  public int methodPublicConditionallyBlocked() { return 431; }
+  int methodPackageConditionallyBlocked() { return 432; }
+  protected int methodProtectedConditionallyBlocked() { return 433; }
+  private int methodPrivateConditionallyBlocked() { return 434; }
 
-  public int methodPublicBlacklist() { return 441; }
-  int methodPackageBlacklist() { return 442; }
-  protected int methodProtectedBlacklist() { return 443; }
-  private int methodPrivateBlacklist() { return 444; }
+  public int methodPublicBlocklist() { return 441; }
+  int methodPackageBlocklist() { return 442; }
+  protected int methodProtectedBlocklist() { return 443; }
+  private int methodPrivateBlocklist() { return 444; }
 
-  public int methodPublicBlacklistAndCorePlatformApi() { return 451; }
-  int methodPackageBlacklistAndCorePlatformApi() { return 452; }
-  protected int methodProtectedBlacklistAndCorePlatformApi() { return 453; }
-  private int methodPrivateBlacklistAndCorePlatformApi() { return 454; }
+  public int methodPublicBlocklistAndCorePlatformApi() { return 451; }
+  int methodPackageBlocklistAndCorePlatformApi() { return 452; }
+  protected int methodProtectedBlocklistAndCorePlatformApi() { return 453; }
+  private int methodPrivateBlocklistAndCorePlatformApi() { return 454; }
 
   // STATIC METHOD
 
-  public static int methodPublicStaticWhitelist() { return 311; }
-  static int methodPackageStaticWhitelist() { return 312; }
-  protected static int methodProtectedStaticWhitelist() { return 313; }
-  private static int methodPrivateStaticWhitelist() { return 314; }
+  public static int methodPublicStaticSdk() { return 311; }
+  static int methodPackageStaticSdk() { return 312; }
+  protected static int methodProtectedStaticSdk() { return 313; }
+  private static int methodPrivateStaticSdk() { return 314; }
 
-  public static int methodPublicStaticLightGreylist() { return 321; }
-  static int methodPackageStaticLightGreylist() { return 322; }
-  protected static int methodProtectedStaticLightGreylist() { return 323; }
-  private static int methodPrivateStaticLightGreylist() { return 324; }
+  public static int methodPublicStaticUnsupported() { return 321; }
+  static int methodPackageStaticUnsupported() { return 322; }
+  protected static int methodProtectedStaticUnsupported() { return 323; }
+  private static int methodPrivateStaticUnsupported() { return 324; }
 
-  public static int methodPublicStaticDarkGreylist() { return 331; }
-  static int methodPackageStaticDarkGreylist() { return 332; }
-  protected static int methodProtectedStaticDarkGreylist() { return 333; }
-  private static int methodPrivateStaticDarkGreylist() { return 334; }
+  public static int methodPublicStaticConditionallyBlocked() { return 331; }
+  static int methodPackageStaticConditionallyBlocked() { return 332; }
+  protected static int methodProtectedStaticConditionallyBlocked() { return 333; }
+  private static int methodPrivateStaticConditionallyBlocked() { return 334; }
 
-  public static int methodPublicStaticBlacklist() { return 341; }
-  static int methodPackageStaticBlacklist() { return 342; }
-  protected static int methodProtectedStaticBlacklist() { return 343; }
-  private static int methodPrivateStaticBlacklist() { return 344; }
+  public static int methodPublicStaticBlocklist() { return 341; }
+  static int methodPackageStaticBlocklist() { return 342; }
+  protected static int methodProtectedStaticBlocklist() { return 343; }
+  private static int methodPrivateStaticBlocklist() { return 344; }
 
-  public static int methodPublicStaticBlacklistAndCorePlatformApi() { return 351; }
-  static int methodPackageStaticBlacklistAndCorePlatformApi() { return 352; }
-  protected static int methodProtectedStaticBlacklistAndCorePlatformApi() { return 353; }
-  private static int methodPrivateStaticBlacklistAndCorePlatformApi() { return 354; }
+  public static int methodPublicStaticBlocklistAndCorePlatformApi() { return 351; }
+  static int methodPackageStaticBlocklistAndCorePlatformApi() { return 352; }
+  protected static int methodProtectedStaticBlocklistAndCorePlatformApi() { return 353; }
+  private static int methodPrivateStaticBlocklistAndCorePlatformApi() { return 354; }
 
   // CONSTRUCTOR
 
-  // Whitelist
+  // Sdk
   public ParentClass(int x, short y) {}
   ParentClass(float x, short y) {}
   protected ParentClass(long x, short y) {}
@@ -155,13 +155,13 @@
   protected ParentClass(long x, byte y) {}
   private ParentClass(double x, byte y) {}
 
-  // Blacklist
+  // Blocklist
   public ParentClass(int x, char y) {}
   ParentClass(float x, char y) {}
   protected ParentClass(long x, char y) {}
   private ParentClass(double x, char y) {}
 
-  // Blacklist and CorePlatformApi
+  // Blocklist and CorePlatformApi
   public ParentClass(int x, int y) {}
   ParentClass(float x, int y) {}
   protected ParentClass(long x, int y) {}
@@ -169,31 +169,31 @@
 
   // HELPERS
 
-  public int callMethodPublicWhitelist() { return methodPublicWhitelist(); }
-  public int callMethodPackageWhitelist() { return methodPackageWhitelist(); }
-  public int callMethodProtectedWhitelist() { return methodProtectedWhitelist(); }
+  public int callMethodPublicSdk() { return methodPublicSdk(); }
+  public int callMethodPackageSdk() { return methodPackageSdk(); }
+  public int callMethodProtectedSdk() { return methodProtectedSdk(); }
 
-  public int callMethodPublicLightGreylist() { return methodPublicLightGreylist(); }
-  public int callMethodPackageLightGreylist() { return methodPackageLightGreylist(); }
-  public int callMethodProtectedLightGreylist() { return methodProtectedLightGreylist(); }
+  public int callMethodPublicUnsupported() { return methodPublicUnsupported(); }
+  public int callMethodPackageUnsupported() { return methodPackageUnsupported(); }
+  public int callMethodProtectedUnsupported() { return methodProtectedUnsupported(); }
 
-  public int callMethodPublicDarkGreylist() { return methodPublicDarkGreylist(); }
-  public int callMethodPackageDarkGreylist() { return methodPackageDarkGreylist(); }
-  public int callMethodProtectedDarkGreylist() { return methodProtectedDarkGreylist(); }
+  public int callMethodPublicConditionallyBlocked() { return methodPublicConditionallyBlocked(); }
+  public int callMethodPackageConditionallyBlocked() { return methodPackageConditionallyBlocked(); }
+  public int callMethodProtectedConditionallyBlocked() { return methodProtectedConditionallyBlocked(); }
 
-  public int callMethodPublicBlacklist() { return methodPublicBlacklist(); }
-  public int callMethodPackageBlacklist() { return methodPackageBlacklist(); }
-  public int callMethodProtectedBlacklist() { return methodProtectedBlacklist(); }
+  public int callMethodPublicBlocklist() { return methodPublicBlocklist(); }
+  public int callMethodPackageBlocklist() { return methodPackageBlocklist(); }
+  public int callMethodProtectedBlocklist() { return methodProtectedBlocklist(); }
 
-  public int callMethodPublicBlacklistAndCorePlatformApi() {
-    return methodPublicBlacklistAndCorePlatformApi();
+  public int callMethodPublicBlocklistAndCorePlatformApi() {
+    return methodPublicBlocklistAndCorePlatformApi();
   }
 
-  public int callMethodPackageBlacklistAndCorePlatformApi() {
-    return methodPackageBlacklistAndCorePlatformApi();
+  public int callMethodPackageBlocklistAndCorePlatformApi() {
+    return methodPackageBlocklistAndCorePlatformApi();
   }
 
-  public int callMethodProtectedBlacklistAndCorePlatformApi() {
-    return methodProtectedBlacklistAndCorePlatformApi();
+  public int callMethodProtectedBlocklistAndCorePlatformApi() {
+    return methodProtectedBlocklistAndCorePlatformApi();
   }
 }
diff --git a/test/674-hiddenapi/src/ParentInterface.java b/test/674-hiddenapi/src/ParentInterface.java
index 1c5b58f..08334c0 100644
--- a/test/674-hiddenapi/src/ParentInterface.java
+++ b/test/674-hiddenapi/src/ParentInterface.java
@@ -16,30 +16,30 @@
 
 public interface ParentInterface {
   // STATIC FIELD
-  static int fieldPublicStaticWhitelist = 11;
-  static int fieldPublicStaticLightGreylist = 12;
-  static int fieldPublicStaticDarkGreylist = 13;
-  static int fieldPublicStaticBlacklist = 14;
-  static int fieldPublicStaticBlacklistAndCorePlatformApi = 15;
+  static int fieldPublicStaticSdk = 11;
+  static int fieldPublicStaticUnsupported = 12;
+  static int fieldPublicStaticConditionallyBlocked = 13;
+  static int fieldPublicStaticBlocklist = 14;
+  static int fieldPublicStaticBlocklistAndCorePlatformApi = 15;
 
   // INSTANCE METHOD
-  int methodPublicWhitelist();
-  int methodPublicLightGreylist();
-  int methodPublicDarkGreylist();
-  int methodPublicBlacklist();
-  int methodPublicBlacklistAndCorePlatformApi();
+  int methodPublicSdk();
+  int methodPublicUnsupported();
+  int methodPublicConditionallyBlocked();
+  int methodPublicBlocklist();
+  int methodPublicBlocklistAndCorePlatformApi();
 
   // STATIC METHOD
-  static int methodPublicStaticWhitelist() { return 21; }
-  static int methodPublicStaticLightGreylist() { return 22; }
-  static int methodPublicStaticDarkGreylist() { return 23; }
-  static int methodPublicStaticBlacklist() { return 24; }
-  static int methodPublicStaticBlacklistAndCorePlatformApi() { return 25; }
+  static int methodPublicStaticSdk() { return 21; }
+  static int methodPublicStaticUnsupported() { return 22; }
+  static int methodPublicStaticConditionallyBlocked() { return 23; }
+  static int methodPublicStaticBlocklist() { return 24; }
+  static int methodPublicStaticBlocklistAndCorePlatformApi() { return 25; }
 
   // DEFAULT METHOD
-  default int methodPublicDefaultWhitelist() { return 31; }
-  default int methodPublicDefaultLightGreylist() { return 32; }
-  default int methodPublicDefaultDarkGreylist() { return 33; }
-  default int methodPublicDefaultBlacklist() { return 34; }
-  default int methodPublicDefaultBlacklistAndCorePlatformApi() { return 35; }
+  default int methodPublicDefaultSdk() { return 31; }
+  default int methodPublicDefaultUnsupported() { return 32; }
+  default int methodPublicDefaultConditionallyBlocked() { return 33; }
+  default int methodPublicDefaultBlocklist() { return 34; }
+  default int methodPublicDefaultBlocklistAndCorePlatformApi() { return 35; }
 }
diff --git a/test/674-hiddenapi/src/SampleClass.java b/test/674-hiddenapi/src/SampleClass.java
new file mode 100644
index 0000000..b7dd6ec
--- /dev/null
+++ b/test/674-hiddenapi/src/SampleClass.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 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 SampleClass implements ParentInterface {
+  public int methodPublicSdk() { return 1; }
+  public int methodPublicUnsupported() { return 2; }
+  public int methodPublicConditionallyBlocked() { return 3; }
+  public int methodPublicBlocklist() { return 4; }
+  public int methodPublicBlocklistAndCorePlatformApi() { return 5; }
+
+  public static ParentInterface getInterfaceInstance() {
+    return new SampleClass();
+  }
+}
diff --git a/test/674-hotness-compiled/Android.bp b/test/674-hotness-compiled/Android.bp
new file mode 100644
index 0000000..c11bc72
--- /dev/null
+++ b/test/674-hotness-compiled/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `674-hotness-compiled`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-674-hotness-compiled",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-674-hotness-compiled-expected-stdout",
+        ":art-run-test-674-hotness-compiled-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-674-hotness-compiled-expected-stdout",
+    out: ["art-run-test-674-hotness-compiled-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-674-hotness-compiled-expected-stderr",
+    out: ["art-run-test-674-hotness-compiled-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/674-hiddenapi/expected.txt b/test/674-hotness-compiled/expected-stderr.txt
similarity index 100%
copy from test/674-hiddenapi/expected.txt
copy to test/674-hotness-compiled/expected-stderr.txt
diff --git a/test/674-hotness-compiled/expected.txt b/test/674-hotness-compiled/expected-stdout.txt
similarity index 100%
rename from test/674-hotness-compiled/expected.txt
rename to test/674-hotness-compiled/expected-stdout.txt
diff --git a/test/607-daemon-stress/expected.txt b/test/674-vdex-uncompress/expected-stderr.txt
similarity index 100%
copy from test/607-daemon-stress/expected.txt
copy to test/674-vdex-uncompress/expected-stderr.txt
diff --git a/test/674-vdex-uncompress/expected.txt b/test/674-vdex-uncompress/expected-stdout.txt
similarity index 100%
rename from test/674-vdex-uncompress/expected.txt
rename to test/674-vdex-uncompress/expected-stdout.txt
diff --git a/test/674-vdex-uncompress/src/Main.java b/test/674-vdex-uncompress/src/Main.java
index 0a25b56..ce8b7b5 100644
--- a/test/674-vdex-uncompress/src/Main.java
+++ b/test/674-vdex-uncompress/src/Main.java
@@ -16,7 +16,6 @@
 
 public class Main {
   Main() {
-    // Will be quickened with RETURN_VOID_NO_BARRIER.
   }
 
   public static void main(String[] args) {
diff --git a/test/619-checker-current-method/expected.txt b/test/675-checker-unverified-method/expected-stderr.txt
similarity index 100%
copy from test/619-checker-current-method/expected.txt
copy to test/675-checker-unverified-method/expected-stderr.txt
diff --git a/test/675-checker-unverified-method/expected.txt b/test/675-checker-unverified-method/expected-stdout.txt
similarity index 100%
rename from test/675-checker-unverified-method/expected.txt
rename to test/675-checker-unverified-method/expected-stdout.txt
diff --git a/test/676-proxy-jit-at-first-use/Android.bp b/test/676-proxy-jit-at-first-use/Android.bp
new file mode 100644
index 0000000..f8ab7bb
--- /dev/null
+++ b/test/676-proxy-jit-at-first-use/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `676-proxy-jit-at-first-use`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-676-proxy-jit-at-first-use",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-676-proxy-jit-at-first-use-expected-stdout",
+        ":art-run-test-676-proxy-jit-at-first-use-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-676-proxy-jit-at-first-use-expected-stdout",
+    out: ["art-run-test-676-proxy-jit-at-first-use-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-676-proxy-jit-at-first-use-expected-stderr",
+    out: ["art-run-test-676-proxy-jit-at-first-use-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/482-checker-loop-back-edge-use/expected.txt b/test/676-proxy-jit-at-first-use/expected-stderr.txt
similarity index 100%
copy from test/482-checker-loop-back-edge-use/expected.txt
copy to test/676-proxy-jit-at-first-use/expected-stderr.txt
diff --git a/test/676-proxy-jit-at-first-use/expected.txt b/test/676-proxy-jit-at-first-use/expected-stdout.txt
similarity index 100%
rename from test/676-proxy-jit-at-first-use/expected.txt
rename to test/676-proxy-jit-at-first-use/expected-stdout.txt
diff --git a/test/477-checker-bound-type/expected.txt b/test/676-resolve-field-type/expected-stderr.txt
similarity index 100%
copy from test/477-checker-bound-type/expected.txt
copy to test/676-resolve-field-type/expected-stderr.txt
diff --git a/test/676-resolve-field-type/expected.txt b/test/676-resolve-field-type/expected-stdout.txt
similarity index 100%
rename from test/676-resolve-field-type/expected.txt
rename to test/676-resolve-field-type/expected-stdout.txt
diff --git a/test/677-fsi/check b/test/677-fsi/check
index 7b22bd1..8c7f18b 100644
--- a/test/677-fsi/check
+++ b/test/677-fsi/check
@@ -14,10 +14,18 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Only keep the lines we're interested in.
-sed -s '/^.*: oat file has dex code, but APK has uncompressed dex code\|Hello World/!d' "$2" > "$2.tmp"
+sed -s '/Hello World/!d' "$2" > "$2.tmp"
+sed -s '/^.*: oat file has dex code, but APK has uncompressed dex code/!d' "$4" > "$4.tmp"
 
 # Remove part of message containing filename.
-sed -s 's/^.*: //' "$2.tmp" > "$2.tmp2"
+sed -s 's/^.*: //' "$4.tmp" > "$4.tmp2"
 
-diff --strip-trailing-cr -q "$1" "$2.tmp2" >/dev/null
+diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4.tmp2" >/dev/null
diff --git a/test/677-fsi/expected-stderr.txt b/test/677-fsi/expected-stderr.txt
new file mode 100644
index 0000000..35c3918
--- /dev/null
+++ b/test/677-fsi/expected-stderr.txt
@@ -0,0 +1,2 @@
+oat file has dex code, but APK has uncompressed dex code
+oat file has dex code, but APK has uncompressed dex code
diff --git a/test/677-fsi2/expected.txt b/test/677-fsi/expected-stdout.txt
similarity index 100%
copy from test/677-fsi2/expected.txt
copy to test/677-fsi/expected-stdout.txt
diff --git a/test/677-fsi/expected.txt b/test/677-fsi/expected.txt
deleted file mode 100644
index 2b07343..0000000
--- a/test/677-fsi/expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-oat file has dex code, but APK has uncompressed dex code
-Hello World
diff --git a/test/677-fsi2/Android.bp b/test/677-fsi2/Android.bp
new file mode 100644
index 0000000..c95c227
--- /dev/null
+++ b/test/677-fsi2/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `677-fsi2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-677-fsi2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-677-fsi2-expected-stdout",
+        ":art-run-test-677-fsi2-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-677-fsi2-expected-stdout",
+    out: ["art-run-test-677-fsi2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-677-fsi2-expected-stderr",
+    out: ["art-run-test-677-fsi2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/580-crc32/expected.txt b/test/677-fsi2/expected-stderr.txt
similarity index 100%
copy from test/580-crc32/expected.txt
copy to test/677-fsi2/expected-stderr.txt
diff --git a/test/677-fsi2/expected.txt b/test/677-fsi2/expected-stdout.txt
similarity index 100%
rename from test/677-fsi2/expected.txt
rename to test/677-fsi2/expected-stdout.txt
diff --git a/test/552-checker-sharpening/expected.txt b/test/678-quickening/expected-stderr.txt
similarity index 100%
copy from test/552-checker-sharpening/expected.txt
copy to test/678-quickening/expected-stderr.txt
diff --git a/test/678-quickening/expected.txt b/test/678-quickening/expected-stdout.txt
similarity index 100%
rename from test/678-quickening/expected.txt
rename to test/678-quickening/expected-stdout.txt
diff --git a/test/679-checker-minmax/expected.txt b/test/679-checker-minmax/expected.txt
deleted file mode 100644
index b0aad4d..0000000
--- a/test/679-checker-minmax/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-passed
diff --git a/test/679-checker-minmax/info.txt b/test/679-checker-minmax/info.txt
deleted file mode 100644
index 4f7b9f5..0000000
--- a/test/679-checker-minmax/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Functional tests on detecting min/max.
diff --git a/test/679-checker-minmax/src/Main.java b/test/679-checker-minmax/src/Main.java
deleted file mode 100644
index 4b72656..0000000
--- a/test/679-checker-minmax/src/Main.java
+++ /dev/null
@@ -1,801 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Functional tests for detecting min/max.
- */
-public class Main {
-
-  //
-  // Direct intrinsics.
-  //
-
-  /// CHECK-START: int Main.minI(int) instruction_simplifier (before)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Con:i\d+>> IntConstant 20
-  /// CHECK-DAG: <<Min:i\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMinIntInt
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.minI(int) instruction_simplifier (after)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Con:i\d+>> IntConstant 20
-  /// CHECK-DAG: <<Min:i\d+>> Min [<<Par>>,<<Con>>]
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.minI(int) instruction_simplifier (after)
-  /// CHECK-NOT:              InvokeStaticOrDirect
-  //
-  /// CHECK-START-ARM64: int Main.minI(int) disassembly (after)
-  /// CHECK-NOT:              mov {{w\d+}}, #0x14
-  /// CHECK:                  cmp {{w\d+}}, #0x14
-  //  Check that the constant generation was handled by VIXL.
-  /// CHECK:                  mov w16, #0x14
-  /// CHECK:                  csel {{w\d+}}, {{w\d+}}, w16, lt
-  public static int minI(int a) {
-    return Math.min(a, 20);
-  }
-
-  /// CHECK-START: long Main.minL(long) instruction_simplifier (before)
-  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
-  /// CHECK-DAG: <<Con:j\d+>> LongConstant 20
-  /// CHECK-DAG: <<Min:j\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMinLongLong
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: long Main.minL(long) instruction_simplifier (after)
-  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
-  /// CHECK-DAG: <<Con:j\d+>> LongConstant 20
-  /// CHECK-DAG: <<Min:j\d+>> Min [<<Par>>,<<Con>>]
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: long Main.minL(long) instruction_simplifier (after)
-  /// CHECK-NOT:              InvokeStaticOrDirect
-  //
-  /// CHECK-START-ARM64: long Main.minL(long) disassembly (after)
-  /// CHECK-NOT:              mov {{x\d+}}, #0x14
-  /// CHECK:                  cmp {{x\d+}}, #0x14
-  //  Check that the constant generation was handled by VIXL.
-  /// CHECK:                  mov x16, #0x14
-  /// CHECK:                  csel {{x\d+}}, {{x\d+}}, x16, lt
-  public static long minL(long a) {
-    return Math.min(a, 20L);
-  }
-
-  /// CHECK-START: int Main.maxI(int) instruction_simplifier (before)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Con:i\d+>> IntConstant 20
-  /// CHECK-DAG: <<Max:i\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMaxIntInt
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.maxI(int) instruction_simplifier (after)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Con:i\d+>> IntConstant 20
-  /// CHECK-DAG: <<Max:i\d+>> Max [<<Par>>,<<Con>>]
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.maxI(int) instruction_simplifier (after)
-  /// CHECK-NOT:              InvokeStaticOrDirect
-  //
-  /// CHECK-START-ARM64: int Main.maxI(int) disassembly (after)
-  /// CHECK-NOT:              mov {{w\d+}}, #0x14
-  /// CHECK:                  cmp {{w\d+}}, #0x14
-  //  Check that the constant generation was handled by VIXL.
-  /// CHECK:                  mov w16, #0x14
-  /// CHECK:                  csel {{w\d+}}, {{w\d+}}, w16, gt
-  public static int maxI(int a) {
-    return Math.max(a, 20);
-  }
-
-  /// CHECK-START: long Main.maxL(long) instruction_simplifier (before)
-  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
-  /// CHECK-DAG: <<Con:j\d+>> LongConstant 20
-  /// CHECK-DAG: <<Max:j\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMaxLongLong
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: long Main.maxL(long) instruction_simplifier (after)
-  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
-  /// CHECK-DAG: <<Con:j\d+>> LongConstant 20
-  /// CHECK-DAG: <<Max:j\d+>> Max [<<Par>>,<<Con>>]
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: long Main.maxL(long) instruction_simplifier (after)
-  /// CHECK-NOT:              InvokeStaticOrDirect
-  //
-  /// CHECK-START-ARM64: long Main.maxL(long) disassembly (after)
-  /// CHECK-NOT:              mov {{x\d+}}, #0x14
-  /// CHECK:                  cmp {{x\d+}}, #0x14
-  //  Check that the constant generation was handled by VIXL.
-  /// CHECK:                  mov x16, #0x14
-  /// CHECK:                  csel {{x\d+}}, {{x\d+}}, x16, gt
-  public static long maxL(long a) {
-    return Math.max(a, 20L);
-  }
-
-  //
-  // Special Cases
-  //
-
-  /// CHECK-START-ARM64: int Main.minIntConstantZero(int) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{w\d+}}, #0x0
-  /// CHECK:            cmp {{w\d+}}, #0x0 (0)
-  /// CHECK:            csel {{w\d+}}, {{w\d+}}, wzr, lt
-  /// CHECK:            ret
-  public static int minIntConstantZero(int a) {
-    return Math.min(a, 0);
-  }
-
-  /// CHECK-START-ARM64: int Main.minIntConstantOne(int) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{w\d+}}, #0x1
-  /// CHECK:            cmp {{w\d+}}, #0x1 (1)
-  /// CHECK:            csinc {{w\d+}}, {{w\d+}}, wzr, lt
-  /// CHECK:            ret
-  public static int minIntConstantOne(int a) {
-    return Math.min(a, 1);
-  }
-
-  /// CHECK-START-ARM64: int Main.minIntConstantMinusOne(int) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{w\d+}}, #0xffffffff
-  /// CHECK:            cmn {{w\d+}}, #0x1 (1)
-  /// CHECK:            csinv {{w\d+}}, {{w\d+}}, wzr, lt
-  /// CHECK:            ret
-  public static int minIntConstantMinusOne(int a) {
-    return Math.min(a, -1);
-  }
-
-  /// CHECK-START-ARM64: long Main.minLongConstantZero(long) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{x\d+}}, #0x0
-  /// CHECK:            cmp {{x\d+}}, #0x0 (0)
-  /// CHECK:            csel {{x\d+}}, {{x\d+}}, xzr, lt
-  /// CHECK:            ret
-  public static long minLongConstantZero(long a) {
-    return Math.min(a, 0L);
-  }
-
-  /// CHECK-START-ARM64: long Main.minLongConstantOne(long) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{x\d+}}, #0x1
-  /// CHECK:            cmp {{x\d+}}, #0x1 (1)
-  /// CHECK:            csinc {{x\d+}}, {{x\d+}}, xzr, lt
-  /// CHECK:            ret
-  public static long minLongConstantOne(long a) {
-    return Math.min(a, 1L);
-  }
-
-  /// CHECK-START-ARM64: long Main.minLongConstantMinusOne(long) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{x\d+}}, #0xffffffffffffffff
-  /// CHECK:            cmn {{x\d+}}, #0x1 (1)
-  /// CHECK:            csinv {{x\d+}}, {{x\d+}}, xzr, lt
-  /// CHECK:            ret
-  public static long minLongConstantMinusOne(long a) {
-    return Math.min(a, -1L);
-  }
-
-  /// CHECK-START-ARM64: int Main.maxIntConstantZero(int) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{w\d+}}, #0x0
-  /// CHECK:            cmp {{w\d+}}, #0x0 (0)
-  /// CHECK:            csel {{w\d+}}, {{w\d+}}, wzr, gt
-  /// CHECK:            ret
-  public static int maxIntConstantZero(int a) {
-    return Math.max(a, 0);
-  }
-
-  /// CHECK-START-ARM64: int Main.maxIntConstantOne(int) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{w\d+}}, #0x1
-  /// CHECK:            cmp {{w\d+}}, #0x1 (1)
-  /// CHECK:            csinc {{w\d+}}, {{w\d+}}, wzr, gt
-  /// CHECK:            ret
-  public static int maxIntConstantOne(int a) {
-    return Math.max(a, 1);
-  }
-
-  /// CHECK-START-ARM64: int Main.maxIntConstantMinusOne(int) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{w\d+}}, #0xffffffff
-  /// CHECK:            cmn {{w\d+}}, #0x1 (1)
-  /// CHECK:            csinv {{w\d+}}, {{w\d+}}, wzr, gt
-  /// CHECK:            ret
-  public static int maxIntConstantMinusOne(int a) {
-    return Math.max(a, -1);
-  }
-
-  /// CHECK-START-ARM64: int Main.maxIntLargeConstant(int) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK:            mov {{w\d+}}, #0x2001
-  /// CHECK:            cmp {{w\d+}}, {{w\d+}}
-  //  Check that constant generation was not handled by VIXL.
-  /// CHECK-NOT:        mov {{w\d+}}, #0x2001
-  /// CHECK:            csel {{w\d+}}, {{w\d+}}, {{w\d+}}, gt
-  /// CHECK:            ret
-  public static int maxIntLargeConstant(int a) {
-    return Math.max(a, 8193);
-  }
-
-  /// CHECK-START-ARM64: long Main.maxLongConstantZero(long) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{x\d+}}, #0x0
-  /// CHECK:            cmp {{x\d+}}, #0x0 (0)
-  /// CHECK:            csel {{x\d+}}, {{x\d+}}, xzr, gt
-  /// CHECK:            ret
-  public static long maxLongConstantZero(long a) {
-    return Math.max(a, 0L);
-  }
-
-  /// CHECK-START-ARM64: long Main.maxLongConstantOne(long) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{x\d+}}, #0x1
-  /// CHECK:            cmp {{x\d+}}, #0x1 (1)
-  /// CHECK:            csinc {{x\d+}}, {{x\d+}}, xzr, gt
-  /// CHECK:            ret
-  public static long maxLongConstantOne(long a) {
-    return Math.max(a, 1L);
-  }
-
-  /// CHECK-START-ARM64: long Main.maxLongConstantMinusOne(long) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK-NOT:        mov {{x\d+}}, #0xffffffffffffffff
-  /// CHECK:            cmn {{x\d+}}, #0x1 (1)
-  /// CHECK:            csinv {{x\d+}}, {{x\d+}}, xzr, gt
-  /// CHECK:            ret
-  public static long maxLongConstantMinusOne(long a) {
-    return Math.max(a, -1L);
-  }
-
-  /// CHECK-START-ARM64: long Main.maxLongLargeConstant(long) disassembly (after)
-  /// CHECK-NOT:        InvokeStaticOrDirect
-  /// CHECK:            mov {{x\d+}}, #0x2001
-  /// CHECK:            cmp {{x\d+}}, {{x\d+}}
-  //  Check that constant generation was not handled by VIXL.
-  /// CHECK-NOT:        mov {{x\d+}}, #0x2001
-  /// CHECK:            csel {{x\d+}}, {{x\d+}}, {{x\d+}}, gt
-  /// CHECK:            ret
-  public static long maxLongLargeConstant(long a) {
-    return Math.max(a, 8193L);
-  }
-
-  //
-  // Different types.
-  //
-
-  /// CHECK-START: int Main.min1(int, int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.min1(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Min:i\d+>> Min
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.min1(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int min1(int a, int b) {
-    return a < b ? a : b;
-  }
-
-  /// CHECK-START: int Main.min2(int, int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.min2(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Min:i\d+>> Min
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.min2(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int min2(int a, int b) {
-    return a <= b ? a : b;
-  }
-
-  /// CHECK-START: int Main.min3(int, int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.min3(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Min:i\d+>> Min
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.min3(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int min3(int a, int b) {
-    return a > b ? b : a;
-  }
-
-  /// CHECK-START: int Main.min4(int, int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.min4(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Min:i\d+>> Min
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.min4(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int min4(int a, int b) {
-    return a >= b ? b : a;
-  }
-
-  /// CHECK-START: int Main.min5(short, short) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:s\d+>>,<<Op2:s\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.min5(short, short) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Min:i\d+>> Min
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.min5(short, short) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int min5(short a, short b) {
-    return a >= b ? b : a;
-  }
-
-  /// CHECK-START: int Main.min6(byte, byte) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:b\d+>>,<<Op2:b\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.min6(byte, byte) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Min:i\d+>> Min
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.min6(byte, byte) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int min6(byte a, byte b) {
-    return a >= b ? b : a;
-  }
-
-  /// CHECK-START: long Main.min7(long, long) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:j\d+>>,<<Op2:j\d+>>]
-  /// CHECK-DAG: <<Sel:j\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: long Main.min7(long, long) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Min:j\d+>> Min
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: long Main.min7(long, long) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static long min7(long a, long b) {
-    return a >= b ? b : a;
-  }
-
-  /// CHECK-START: int Main.max1(int, int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.max1(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Max:i\d+>> Max
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.max1(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int max1(int a, int b) {
-    return a < b ? b : a;
-  }
-
-  /// CHECK-START: int Main.max2(int, int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.max2(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Max:i\d+>> Max
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.max2(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int max2(int a, int b) {
-    return a <= b ? b : a;
-  }
-
-  /// CHECK-START: int Main.max3(int, int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.max3(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Max:i\d+>> Max
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.max3(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int max3(int a, int b) {
-    return a > b ? a : b;
-  }
-
-  /// CHECK-START: int Main.max4(int, int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:i\d+>>,<<Op2:i\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.max4(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Max:i\d+>> Max
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.max4(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int max4(int a, int b) {
-    return a >= b ? a : b;
-  }
-
-  /// CHECK-START: int Main.max5(short, short) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:s\d+>>,<<Op2:s\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.max5(short, short) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Max:i\d+>> Max
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.max5(short, short) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int max5(short a, short b) {
-    return a >= b ? a : b;
-  }
-
-  /// CHECK-START: int Main.max6(byte, byte) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:b\d+>>,<<Op2:b\d+>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.max6(byte, byte) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Max:i\d+>> Max
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.max6(byte, byte) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int max6(byte a, byte b) {
-    return a >= b ? a : b;
-  }
-
-  /// CHECK-START: long Main.max7(long, long) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:j\d+>>,<<Op2:j\d+>>]
-  /// CHECK-DAG: <<Sel:j\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: long Main.max7(long, long) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Max:j\d+>> Max
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: long Main.max7(long, long) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static long max7(long a, long b) {
-    return a >= b ? a : b;
-  }
-
-  //
-  // Complications.
-  //
-
-  /// CHECK-START: int Main.min0(int[], int[]) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Ar1:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
-  /// CHECK-DAG: <<Ar2:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
-  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Ar1>>,<<Ar2>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Ar1>>,<<Ar2>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.min0(int[], int[]) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Min:i\d+>> Min
-  /// CHECK-DAG:              Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.min0(int[], int[]) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int min0(int[] a, int[] b) {
-    // Repeat of array references needs finding the common subexpressions
-    // prior to doing the select and min/max recognition.
-    return a[0] <= b[0] ? a[0] : b[0];
-  }
-
-  /// CHECK-START: int Main.max0(int[], int[]) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Ar1:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
-  /// CHECK-DAG: <<Ar2:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Ar1>>,<<Ar2>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Ar1>>,<<Ar2>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.max0(int[], int[]) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Max:i\d+>> Max
-  /// CHECK-DAG:              Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.max0(int[], int[]) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int max0(int[] a, int[] b) {
-    // Repeat of array references needs finding the common subexpressions
-    // prior to doing the select and min/max recognition.
-    return a[0] >= b[0] ? a[0] : b[0];
-  }
-
-  /// CHECK-START: int Main.minmax1(int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
-  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
-  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
-  /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par>>,<<P100>>]
-  /// CHECK-DAG: <<Sel1:i\d+>> Select [<<P100>>,<<Par>>,<<Cnd1>>]
-  /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Sel1>>,<<M100>>]
-  /// CHECK-DAG: <<Sel2:i\d+>> Select [<<M100>>,<<Sel1>>,<<Cnd2>>]
-  /// CHECK-DAG:               Return [<<Sel2>>]
-  //
-  /// CHECK-START: int Main.minmax1(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
-  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
-  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
-  /// CHECK-DAG: <<Min:i\d+>>  Min [<<Par>>,<<P100>>]
-  /// CHECK-DAG: <<Max:i\d+>>  Max [<<Min>>,<<M100>>]
-  /// CHECK-DAG:               Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.minmax1(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:               Select
-  public static int minmax1(int x) {
-    // Simple if-if gives clean select sequence.
-    if (x > 100) {
-      x = 100;
-    }
-    if (x < -100) {
-      x = -100;
-    }
-    return x;
-  }
-
-  /// CHECK-START: int Main.minmax2(int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
-  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
-  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
-  /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par>>,<<P100>>]
-  /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Par>>,<<M100>>]
-  /// CHECK-DAG: <<Sel1:i\d+>> Select [<<M100>>,<<Par>>,<<Cnd2>>]
-  /// CHECK-DAG: <<Sel2:i\d+>> Select [<<P100>>,<<Sel1>>,<<Cnd1>>]
-  /// CHECK-DAG:               Return [<<Sel2>>]
-  //
-  /// CHECK-START: int Main.minmax2(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
-  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
-  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
-  /// CHECK-DAG: <<Max:i\d+>>  Max [<<Par>>,<<M100>>]
-  /// CHECK-DAG: <<Min:i\d+>>  Min [<<Max>>,<<P100>>]
-  /// CHECK-DAG:               Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.minmax2(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:               Select
-  public static int minmax2(int x) {
-    // Simple if-else requires inspecting bounds of resulting selects.
-    if (x > 100) {
-      x = 100;
-    } else if (x < -100) {
-      x = -100;
-    }
-    return x;
-  }
-
-  /// CHECK-START: int Main.minmax3(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
-  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
-  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
-  /// CHECK-DAG: <<Max:i\d+>>  Max [<<Par>>,<<M100>>]
-  /// CHECK-DAG: <<Min:i\d+>>  Min [<<Max>>,<<P100>>]
-  /// CHECK-DAG:               Return [<<Min>>]
-  //
-  /// CHECK-START: int Main.minmax3(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:               Select
-  public static int minmax3(int x) {
-    return (x > 100) ? 100 : ((x < -100) ? -100 : x);
-  }
-
-  /// CHECK-START: int Main.minmax4(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:i\d+>>  ParameterValue
-  /// CHECK-DAG: <<P100:i\d+>> IntConstant 100
-  /// CHECK-DAG: <<M100:i\d+>> IntConstant -100
-  /// CHECK-DAG: <<Min:i\d+>>  Min [<<Par>>,<<P100>>]
-  /// CHECK-DAG: <<Max:i\d+>>  Max [<<Min>>,<<M100>>]
-  /// CHECK-DAG:               Return [<<Max>>]
-  //
-  /// CHECK-START: int Main.minmax4(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:               Select
-  public static int minmax4(int x) {
-    return (x < -100) ? -100 : ((x > 100) ? 100 : x);
-  }
-
-  /// CHECK-START: int Main.minmaxCSEScalar(int, int) select_generator (after)
-  /// CHECK-DAG: <<Par1:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Par2:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual    [<<Par1>>,<<Par2>>]
-  /// CHECK-DAG: <<Sel1:i\d+>> Select             [<<Par1>>,<<Par2>>,<<Cnd1>>]
-  /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Par1>>,<<Par2>>]
-  /// CHECK-DAG: <<Sel2:i\d+>> Select             [<<Par1>>,<<Par2>>,<<Cnd2>>]
-  /// CHECK-DAG: <<Add1:i\d+>> Add                [<<Sel1>>,<<Sel2>>]
-  /// CHECK-DAG: <<Add2:i\d+>> Add                [<<Sel1>>,<<Add1>>]
-  /// CHECK-DAG: <<Add3:i\d+>> Add                [<<Sel2>>,<<Add2>>]
-  /// CHECK-DAG: <<Add4:i\d+>> Add                [<<Sel1>>,<<Add3>>]
-  /// CHECK-DAG: <<Add5:i\d+>> Add                [<<Sel2>>,<<Add4>>]
-  /// CHECK-DAG:               Return             [<<Add5>>]
-  //
-  /// CHECK-START: int Main.minmaxCSEScalar(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par1:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Par2:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Max:i\d+>>  Max    [<<Par1>>,<<Par2>>]
-  /// CHECK-DAG: <<Min:i\d+>>  Min    [<<Par1>>,<<Par2>>]
-  /// CHECK-DAG: <<Add1:i\d+>> Add    [<<Max>>,<<Min>>]
-  /// CHECK-DAG: <<Add2:i\d+>> Add    [<<Max>>,<<Add1>>]
-  /// CHECK-DAG: <<Add3:i\d+>> Add    [<<Min>>,<<Add2>>]
-  /// CHECK-DAG: <<Add4:i\d+>> Add    [<<Max>>,<<Add3>>]
-  /// CHECK-DAG: <<Add5:i\d+>> Add    [<<Min>>,<<Add4>>]
-  /// CHECK-DAG:               Return [<<Add5>>]
-  public static int minmaxCSEScalar(int x, int y) {
-    int t1 = (x > y) ? x : y;
-    int t2 = (x < y) ? x : y;
-    int t3 = (x > y) ? x : y;
-    int t4 = (x < y) ? x : y;
-    int t5 = (x > y) ? x : y;
-    int t6 = (x < y) ? x : y;
-    // Make sure min/max is CSEed.
-    return t1 + t2 + t3 + t4 + t5 + t6;
-  }
-
-  /// CHECK-START: int Main.minmaxCSEArray(int[], int[]) select_generator (after)
-  /// CHECK-DAG: <<Arr1:i\d+>> ArrayGet
-  /// CHECK-DAG: <<Arr2:i\d+>> ArrayGet
-  /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual    [<<Arr1>>,<<Arr2>>]
-  /// CHECK-DAG: <<Sel1:i\d+>> Select             [<<Arr1>>,<<Arr2>>,<<Cnd1>>]
-  /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Arr1>>,<<Arr2>>]
-  /// CHECK-DAG: <<Sel2:i\d+>> Select             [<<Arr1>>,<<Arr2>>,<<Cnd2>>]
-  /// CHECK-DAG: <<Add1:i\d+>> Add                [<<Sel1>>,<<Sel2>>]
-  /// CHECK-DAG: <<Add2:i\d+>> Add                [<<Sel1>>,<<Add1>>]
-  /// CHECK-DAG: <<Add3:i\d+>> Add                [<<Sel2>>,<<Add2>>]
-  /// CHECK-DAG: <<Add4:i\d+>> Add                [<<Sel1>>,<<Add3>>]
-  /// CHECK-DAG: <<Add5:i\d+>> Add                [<<Sel2>>,<<Add4>>]
-  /// CHECK-DAG:               Return             [<<Add5>>]
-  //
-  /// CHECK-START: int Main.minmaxCSEArray(int[], int[]) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Arr1:i\d+>> ArrayGet
-  /// CHECK-DAG: <<Arr2:i\d+>> ArrayGet
-  /// CHECK-DAG: <<Max:i\d+>>  Max    [<<Arr1>>,<<Arr2>>]
-  /// CHECK-DAG: <<Min:i\d+>>  Min    [<<Arr1>>,<<Arr2>>]
-  /// CHECK-DAG: <<Add1:i\d+>> Add    [<<Max>>,<<Min>>]
-  /// CHECK-DAG: <<Add2:i\d+>> Add    [<<Max>>,<<Add1>>]
-  /// CHECK-DAG: <<Add3:i\d+>> Add    [<<Min>>,<<Add2>>]
-  /// CHECK-DAG: <<Add4:i\d+>> Add    [<<Max>>,<<Add3>>]
-  /// CHECK-DAG: <<Add5:i\d+>> Add    [<<Min>>,<<Add4>>]
-  /// CHECK-DAG:               Return [<<Add5>>]
-  public static int minmaxCSEArray(int[] x, int[] y) {
-    int t1 = (x[0] > y[0]) ? x[0] : y[0];
-    int t2 = (x[0] < y[0]) ? x[0] : y[0];
-    int t3 = (x[0] > y[0]) ? x[0] : y[0];
-    int t4 = (x[0] < y[0]) ? x[0] : y[0];
-    int t5 = (x[0] > y[0]) ? x[0] : y[0];
-    int t6 = (x[0] < y[0]) ? x[0] : y[0];
-    // Make sure min/max is CSEed.
-    return t1 + t2 + t3 + t4 + t5 + t6;
-  }
-
-  /// CHECK-START: int Main.minmaxCSEScalarAndCond(int, int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par1:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Par2:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Max:i\d+>>  Max    [<<Par1>>,<<Par2>>]
-  /// CHECK-DAG: <<Min:i\d+>>  Min    [<<Par1>>,<<Par2>>]
-  /// CHECK-DAG: <<Add:i\d+>>  Add    [<<Max>>,<<Min>>]
-  /// CHECK-DAG:               Return [<<Add>>]
-  /// CHECK-DAG: <<Add1:i\d+>> Add    [<<Max>>,<<Min>>]
-  /// CHECK-DAG: <<Add2:i\d+>> Add    [<<Max>>,<<Add1>>]
-  /// CHECK-DAG: <<Add3:i\d+>> Add    [<<Min>>,<<Add2>>]
-  /// CHECK-DAG:               Return [<<Add3>>]
-  public static int minmaxCSEScalarAndCond(int x, int y) {
-    int t1 = (x > y) ? x : y;
-    int t2 = (x < y) ? x : y;
-    if (x == y)
-      return t1 + t2;
-    int t3 = (x > y) ? x : y;
-    int t4 = (x < y) ? x : y;
-    // Make sure min/max is CSEed.
-    return t1 + t2 + t3 + t4;
-  }
-
-  public static void main(String[] args) {
-    // Intrinsics.
-    expectEquals(10, minI(10));
-    expectEquals(20, minI(25));
-    expectEquals(-1, minIntConstantZero(-1));
-    expectEquals(0, minIntConstantZero(1));
-    expectEquals(0, minIntConstantOne(0));
-    expectEquals(1, minIntConstantOne(2));
-    expectEquals(-2, minIntConstantMinusOne(-2));
-    expectEquals(-1, minIntConstantMinusOne(0));
-    expectEquals(10L, minL(10L));
-    expectEquals(20L, minL(25L));
-    expectEquals(-1L, minLongConstantZero(-1L));
-    expectEquals(0L, minLongConstantZero(1L));
-    expectEquals(0L, minLongConstantOne(0L));
-    expectEquals(1L, minLongConstantOne(2L));
-    expectEquals(-2L, minLongConstantMinusOne(-2L));
-    expectEquals(-1L, minLongConstantMinusOne(0L));
-    expectEquals(20, maxI(10));
-    expectEquals(25, maxI(25));
-    expectEquals(0, maxIntConstantZero(-1));
-    expectEquals(1, maxIntConstantZero(1));
-    expectEquals(1, maxIntConstantOne(0));
-    expectEquals(2, maxIntConstantOne(2));
-    expectEquals(-1, maxIntConstantMinusOne(-2));
-    expectEquals(0, maxIntConstantMinusOne(0));
-    expectEquals(8193, maxIntLargeConstant(8192));
-    expectEquals(9000, maxIntLargeConstant(9000));
-    expectEquals(20L, maxL(10L));
-    expectEquals(25L, maxL(25L));
-    expectEquals(0L, maxLongConstantZero(-1L));
-    expectEquals(1L, maxLongConstantZero(1L));
-    expectEquals(1L, maxLongConstantOne(0L));
-    expectEquals(2L, maxLongConstantOne(2L));
-    expectEquals(-1L, maxLongConstantMinusOne(-2L));
-    expectEquals(0L, maxLongConstantMinusOne(0L));
-    expectEquals(8193L, maxLongLargeConstant(8192L));
-    expectEquals(9000L, maxLongLargeConstant(9000L));
-    // Types.
-    expectEquals(10, min1(10, 20));
-    expectEquals(10, min2(10, 20));
-    expectEquals(10, min3(10, 20));
-    expectEquals(10, min4(10, 20));
-    expectEquals(10, min5((short) 10, (short) 20));
-    expectEquals(10, min6((byte) 10, (byte) 20));
-    expectEquals(10L, min7(10L, 20L));
-    expectEquals(20, max1(10, 20));
-    expectEquals(20, max2(10, 20));
-    expectEquals(20, max3(10, 20));
-    expectEquals(20, max4(10, 20));
-    expectEquals(20, max5((short) 10, (short) 20));
-    expectEquals(20, max6((byte) 10, (byte) 20));
-    expectEquals(20L, max7(10L, 20L));
-    // Complications.
-    int[] a = { 10 };
-    int[] b = { 20 };
-    expectEquals(10, min0(a, b));
-    expectEquals(20, max0(a, b));
-    expectEquals(-100, minmax1(-200));
-    expectEquals(10, minmax1(10));
-    expectEquals(100, minmax1(200));
-    expectEquals(-100, minmax2(-200));
-    expectEquals(10, minmax2(10));
-    expectEquals(100, minmax2(200));
-    expectEquals(-100, minmax3(-200));
-    expectEquals(10, minmax3(10));
-    expectEquals(100, minmax3(200));
-    expectEquals(-100, minmax4(-200));
-    expectEquals(10, minmax4(10));
-    expectEquals(100, minmax4(200));
-    expectEquals(90, minmaxCSEScalar(10, 20));
-    expectEquals(90, minmaxCSEArray(a, b));
-    expectEquals(20, minmaxCSEScalarAndCond(10, 10));
-    expectEquals(60, minmaxCSEScalarAndCond(10, 20));
-    System.out.println("passed");
-  }
-
-  private static void expectEquals(int expected, int result) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
-
-  private static void expectEquals(long expected, long result) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
-}
diff --git a/test/679-locks/Android.bp b/test/679-locks/Android.bp
new file mode 100644
index 0000000..38b9c96
--- /dev/null
+++ b/test/679-locks/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `679-locks`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-679-locks",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-679-locks-expected-stdout",
+        ":art-run-test-679-locks-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-679-locks-expected-stdout",
+    out: ["art-run-test-679-locks-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-679-locks-expected-stderr",
+    out: ["art-run-test-679-locks-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/679-locks/expected-stderr.txt b/test/679-locks/expected-stderr.txt
new file mode 100644
index 0000000..0976159
--- /dev/null
+++ b/test/679-locks/expected-stderr.txt
@@ -0,0 +1 @@
+MyString
diff --git a/test/457-regs/expected.txt b/test/679-locks/expected-stdout.txt
similarity index 100%
rename from test/457-regs/expected.txt
rename to test/679-locks/expected-stdout.txt
diff --git a/test/679-locks/expected.txt b/test/679-locks/expected.txt
deleted file mode 100644
index 85a20be..0000000
--- a/test/679-locks/expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-JNI_OnLoad called
-MyString
diff --git a/test/680-checker-deopt-dex-pc-0/Android.bp b/test/680-checker-deopt-dex-pc-0/Android.bp
new file mode 100644
index 0000000..a198d26
--- /dev/null
+++ b/test/680-checker-deopt-dex-pc-0/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `680-checker-deopt-dex-pc-0`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-680-checker-deopt-dex-pc-0",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-680-checker-deopt-dex-pc-0-expected-stdout",
+        ":art-run-test-680-checker-deopt-dex-pc-0-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-680-checker-deopt-dex-pc-0-expected-stdout",
+    out: ["art-run-test-680-checker-deopt-dex-pc-0-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-680-checker-deopt-dex-pc-0-expected-stderr",
+    out: ["art-run-test-680-checker-deopt-dex-pc-0-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/684-select-condition/expected.txt b/test/680-checker-deopt-dex-pc-0/expected-stderr.txt
similarity index 100%
copy from test/684-select-condition/expected.txt
copy to test/680-checker-deopt-dex-pc-0/expected-stderr.txt
diff --git a/test/680-checker-deopt-dex-pc-0/expected.txt b/test/680-checker-deopt-dex-pc-0/expected-stdout.txt
similarity index 100%
rename from test/680-checker-deopt-dex-pc-0/expected.txt
rename to test/680-checker-deopt-dex-pc-0/expected-stdout.txt
diff --git a/test/680-sink-regression/Android.bp b/test/680-sink-regression/Android.bp
new file mode 100644
index 0000000..f55b8ae
--- /dev/null
+++ b/test/680-sink-regression/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `680-sink-regression`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-680-sink-regression",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-680-sink-regression-expected-stdout",
+        ":art-run-test-680-sink-regression-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-680-sink-regression-expected-stdout",
+    out: ["art-run-test-680-sink-regression-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-680-sink-regression-expected-stderr",
+    out: ["art-run-test-680-sink-regression-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/413-regalloc-regression/expected.txt b/test/680-sink-regression/expected-stderr.txt
similarity index 100%
copy from test/413-regalloc-regression/expected.txt
copy to test/680-sink-regression/expected-stderr.txt
diff --git a/test/680-sink-regression/expected.txt b/test/680-sink-regression/expected-stdout.txt
similarity index 100%
rename from test/680-sink-regression/expected.txt
rename to test/680-sink-regression/expected-stdout.txt
diff --git a/test/681-checker-abs/expected.txt b/test/681-checker-abs/expected.txt
deleted file mode 100644
index b0aad4d..0000000
--- a/test/681-checker-abs/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-passed
diff --git a/test/681-checker-abs/info.txt b/test/681-checker-abs/info.txt
deleted file mode 100644
index d36e76e..0000000
--- a/test/681-checker-abs/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Functional tests on detecting abs.
diff --git a/test/681-checker-abs/src/Main.java b/test/681-checker-abs/src/Main.java
deleted file mode 100644
index 00390c3..0000000
--- a/test/681-checker-abs/src/Main.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Functional tests for detecting abs.
- */
-public class Main {
-
-  //
-  // Intrinsics.
-  //
-
-  /// CHECK-START: int Main.absI(int) instruction_simplifier (before)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:i\d+>> InvokeStaticOrDirect [<<Par>>] intrinsic:MathAbsInt
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.absI(int) instruction_simplifier (after)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.absI(int) instruction_simplifier (after)
-  /// CHECK-NOT:              InvokeStaticOrDirect
-  public static int absI(int a) {
-    return Math.abs(a);
-  }
-
-  /// CHECK-START: long Main.absL(long) instruction_simplifier (before)
-  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:j\d+>> InvokeStaticOrDirect [<<Par>>] intrinsic:MathAbsLong
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: long Main.absL(long) instruction_simplifier (after)
-  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:j\d+>> Abs [<<Par>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: long Main.absL(long) instruction_simplifier (after)
-  /// CHECK-NOT:              InvokeStaticOrDirect
-  public static long absL(long a) {
-    return Math.abs(a);
-  }
-
-  //
-  // Types.
-  //
-
-  /// CHECK-START: int Main.abs1(int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
-  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Par>>,<<Zer>>]
-  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Neg>>,<<Par>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.abs1(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.abs1(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int abs1(int a) {
-    return a < 0 ? -a : a;
-  }
-
-  /// CHECK-START: int Main.abs2(int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
-  /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Par>>,<<Zer>>]
-  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Neg>>,<<Par>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.abs2(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.abs2(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int abs2(int a) {
-    return a <= 0 ? -a : a;
-  }
-
-  /// CHECK-START: int Main.abs3(int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Par>>,<<Zer>>]
-  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Par>>,<<Neg>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.abs3(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.abs3(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int abs3(int a) {
-    return a > 0 ? a : -a;
-  }
-
-  /// CHECK-START: int Main.abs4(int) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Par>>,<<Zer>>]
-  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Par>>,<<Neg>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.abs4(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:i\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.abs4(int) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int abs4(int a) {
-    return a >= 0 ? a : -a;
-  }
-
-  /// CHECK-START: int Main.abs5(short) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Par:s\d+>> ParameterValue
-  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Par>>,<<Zer>>]
-  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Par>>,<<Neg>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.abs5(short) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:s\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.abs5(short) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int abs5(short a) {
-    return a >= 0 ? a : -a;
-  }
-
-  /// CHECK-START: int Main.abs6(byte) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Par:b\d+>> ParameterValue
-  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Par>>,<<Zer>>]
-  /// CHECK-DAG: <<Neg:i\d+>> [<<Par>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Par>>,<<Neg>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.abs6(byte) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:b\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.abs6(byte) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int abs6(byte a) {
-    return a >= 0 ? a : -a;
-  }
-
-  /// CHECK-START: long Main.abs7(long) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
-  /// CHECK-DAG: <<Zer:j\d+>> LongConstant 0
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Par>>,<<Zer>>]
-  /// CHECK-DAG: <<Neg:j\d+>> [<<Par>>]
-  /// CHECK-DAG: <<Sel:j\d+>> Select [<<Par>>,<<Neg>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: long Main.abs7(long) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:j\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:j\d+>> Abs [<<Par>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: long Main.abs7(long) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static long abs7(long a) {
-    return a >= 0 ? a : -a;
-  }
-
-  //
-  // Complications.
-  //
-
-  /// CHECK-START: int Main.abs0(int[]) instruction_simplifier$after_gvn (before)
-  /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0
-  /// CHECK-DAG: <<Arr:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
-  /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Arr>>,<<Zer>>]
-  /// CHECK-DAG: <<Neg:i\d+>> [<<Arr>>]
-  /// CHECK-DAG: <<Sel:i\d+>> Select [<<Arr>>,<<Neg>>,<<Cnd>>]
-  /// CHECK-DAG:              Return [<<Sel>>]
-  //
-  /// CHECK-START: int Main.abs0(int[]) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Arr:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}]
-  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Arr>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.abs0(int[]) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              Select
-  public static int abs0(int[] a) {
-    return a[0] >= 0 ? a[0] : -a[0];
-  }
-
-  //
-  // Nop zero extension.
-  //
-
-  /// CHECK-START: int Main.zabs1(byte) instruction_simplifier (before)
-  /// CHECK-DAG: <<Par:b\d+>> ParameterValue
-  /// CHECK-DAG: <<Msk:i\d+>> IntConstant 255
-  /// CHECK-DAG: <<And:i\d+>> [<<Par>>,<<Msk>>]
-  /// CHECK-DAG: <<Abs:i\d+>> InvokeStaticOrDirect [<<And>>] intrinsic:MathAbsInt
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.zabs1(byte) instruction_simplifier (after)
-  /// CHECK-DAG: <<Par:b\d+>> ParameterValue
-  /// CHECK-DAG: <<Cnv:a\d+>> TypeConversion [<<Par>>]
-  /// CHECK-DAG:              Return [<<Cnv>>]
-  //
-  /// CHECK-START: int Main.zabs1(byte) instruction_simplifier (after)
-  /// CHECK-NOT:              InvokeStaticOrDirect
-  /// CHECK-NOT:              Abs
-  public static int zabs1(byte a) {
-    return Math.abs(a & 0xff);
-  }
-
-  /// CHECK-START: int Main.zabs2(short) instruction_simplifier (before)
-  /// CHECK-DAG: <<Par:s\d+>> ParameterValue
-  /// CHECK-DAG: <<Msk:i\d+>> IntConstant 65535
-  /// CHECK-DAG: <<And:i\d+>> [<<Msk>>,<<Par>>]
-  /// CHECK-DAG: <<Abs:i\d+>> InvokeStaticOrDirect [<<And>>] intrinsic:MathAbsInt
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.zabs2(short) instruction_simplifier (after)
-  /// CHECK-DAG: <<Par:s\d+>> ParameterValue
-  /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<Par>>]
-  /// CHECK-DAG:              Return [<<Cnv>>]
-  //
-  /// CHECK-START: int Main.zabs2(short) instruction_simplifier (after)
-  /// CHECK-NOT:              InvokeStaticOrDirect
-  /// CHECK-NOT:              Abs
-  public static int zabs2(short a) {
-    return Math.abs(a & 0xffff);
-  }
-
-  /// CHECK-START: int Main.zabs3(char) instruction_simplifier (before)
-  /// CHECK-DAG: <<Par:c\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:i\d+>> InvokeStaticOrDirect [<<Par>>] intrinsic:MathAbsInt
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.zabs3(char) instruction_simplifier (after)
-  /// CHECK-DAG: <<Par:c\d+>> ParameterValue
-  /// CHECK-DAG: <<Abs:i\d+>> Abs [<<Par>>]
-  /// CHECK-DAG:              Return [<<Abs>>]
-  //
-  /// CHECK-START: int Main.zabs3(char) instruction_simplifier$after_gvn (after)
-  /// CHECK-DAG: <<Par:c\d+>> ParameterValue
-  /// CHECK-DAG:              Return [<<Par>>]
-  //
-  /// CHECK-START: int Main.zabs3(char) instruction_simplifier$after_gvn (after)
-  /// CHECK-NOT:              InvokeStaticOrDirect
-  /// CHECK-NOT:              Abs
-  public static int zabs3(char a) {
-    return Math.abs(a);
-  }
-
-  public static void main(String[] args) {
-    // Intrinsics.
-    expectEquals(10, absI(-10));
-    expectEquals(20, absI(20));
-    expectEquals(10L, absL(-10L));
-    expectEquals(20L, absL(20L));
-    // Types.
-    expectEquals(10, abs1(-10));
-    expectEquals(20, abs1(20));
-    expectEquals(10, abs2(-10));
-    expectEquals(20, abs2(20));
-    expectEquals(10, abs3(-10));
-    expectEquals(20, abs3(20));
-    expectEquals(10, abs4(-10));
-    expectEquals(20, abs4(20));
-    expectEquals(10, abs4((short) -10));
-    expectEquals(20, abs4((short) 20));
-    expectEquals(10, abs6((byte) -10));
-    expectEquals(20, abs6((byte) 20));
-    expectEquals(10L, abs7(-10L));
-    expectEquals(20L, abs7(20L));
-    // Complications.
-    int[] a = { 13 };
-    int[] b = { -11 };
-    expectEquals(13, abs0(a));
-    expectEquals(11, abs0(b));
-    // Nop zero extension.
-    expectEquals(1, zabs1((byte) 1));
-    expectEquals(0xff, zabs1((byte) -1));
-    expectEquals(1, zabs2((short) 1));
-    expectEquals(0xffff, zabs2((short) -1));
-    expectEquals(1, zabs3((char) 1));
-    expectEquals(0xffff, zabs3((char) -1));
-    System.out.println("passed");
-  }
-
-  private static void expectEquals(int expected, int result) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
-
-  private static void expectEquals(long expected, long result) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
-}
diff --git a/test/520-equivalent-phi/expected.txt b/test/682-double-catch-phi/expected-stderr.txt
similarity index 100%
copy from test/520-equivalent-phi/expected.txt
copy to test/682-double-catch-phi/expected-stderr.txt
diff --git a/test/682-double-catch-phi/expected.txt b/test/682-double-catch-phi/expected-stdout.txt
similarity index 100%
rename from test/682-double-catch-phi/expected.txt
rename to test/682-double-catch-phi/expected-stdout.txt
diff --git a/test/683-clinit-inline-static-invoke/expected.txt b/test/683-clinit-inline-static-invoke/expected-stderr.txt
similarity index 100%
rename from test/683-clinit-inline-static-invoke/expected.txt
rename to test/683-clinit-inline-static-invoke/expected-stderr.txt
diff --git a/test/683-clinit-inline-static-invoke/expected.txt b/test/683-clinit-inline-static-invoke/expected-stdout.txt
similarity index 100%
copy from test/683-clinit-inline-static-invoke/expected.txt
copy to test/683-clinit-inline-static-invoke/expected-stdout.txt
diff --git a/test/683-clinit-inline-static-invoke/src/Main.java b/test/683-clinit-inline-static-invoke/src/Main.java
index b4ccfaa..ceccffb 100644
--- a/test/683-clinit-inline-static-invoke/src/Main.java
+++ b/test/683-clinit-inline-static-invoke/src/Main.java
@@ -26,6 +26,6 @@
     // TypeId in the current DexFile, we erroneously provided the type index from the
     // declaring DexFile and that caused a crash. This was fixed by changing the
     // ClinitCheck entrypoint to take the Class reference from LoadClass.
-    int dummy = MyTimeZone.getDefaultTimeZoneType();
+    int placeholder = MyTimeZone.getDefaultTimeZoneType();
   }
 }
diff --git a/test/684-checker-simd-dotprod/Android.bp b/test/684-checker-simd-dotprod/Android.bp
new file mode 100644
index 0000000..1410e91
--- /dev/null
+++ b/test/684-checker-simd-dotprod/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `684-checker-simd-dotprod`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-684-checker-simd-dotprod",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-684-checker-simd-dotprod-expected-stdout",
+        ":art-run-test-684-checker-simd-dotprod-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-684-checker-simd-dotprod-expected-stdout",
+    out: ["art-run-test-684-checker-simd-dotprod-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-684-checker-simd-dotprod-expected-stderr",
+    out: ["art-run-test-684-checker-simd-dotprod-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/684-select-condition/expected.txt b/test/684-checker-simd-dotprod/expected-stderr.txt
similarity index 100%
copy from test/684-select-condition/expected.txt
copy to test/684-checker-simd-dotprod/expected-stderr.txt
diff --git a/test/684-checker-simd-dotprod/expected.txt b/test/684-checker-simd-dotprod/expected-stdout.txt
similarity index 100%
rename from test/684-checker-simd-dotprod/expected.txt
rename to test/684-checker-simd-dotprod/expected-stdout.txt
diff --git a/test/684-checker-simd-dotprod/src/other/TestByte.java b/test/684-checker-simd-dotprod/src/other/TestByte.java
index 9acfc59..1d5e811 100644
--- a/test/684-checker-simd-dotprod/src/other/TestByte.java
+++ b/test/684-checker-simd-dotprod/src/other/TestByte.java
@@ -34,20 +34,50 @@
   /// CHECK-DAG:                  Add [<<Phi2>>,<<Mul>>]                                loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                  Add [<<Phi1>>,<<Const1>>]                             loop:<<Loop>>      outer_loop:none
 
-  /// CHECK-START-{ARM64}: int other.TestByte.testDotProdSimple(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdSimple(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Int8   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>,<<LoopP>>] type:Int8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>,{{j\d+}}]                                   loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>,{{j\d+}}]                          loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Int8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
+
+
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdSimple(byte[], byte[]) disassembly (after)
+  /// CHECK:        VecDotProd
+  /// CHECK-IF:     hasIsaFeature("sve")
+  ///               CHECK:        sdot z{{\d+}}.s, z{{\d+}}.b, z{{\d+}}.b
+  /// CHECK-ELIF:   hasIsaFeature("dotprod")
+  ///               CHECK-NEXT:   sdot v{{\d+}}.4s, v{{\d+}}.16b, v{{\d+}}.16b
+  /// CHECK-ELSE:
+  ///               CHECK-NOT:    sdot
+  ///               CHECK-NOT:    udot
+  /// CHECK-FI:
   public static final int testDotProdSimple(byte[] a, byte[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -72,23 +102,44 @@
   /// CHECK-DAG:                  Add [<<Phi2>>,<<Mul>>]                                loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                  Add [<<Phi1>>,<<Const1>>]                             loop:<<Loop>>      outer_loop:none
 
-  /// CHECK-START-{ARM64}: int other.TestByte.testDotProdComplex(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdComplex(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Int8   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>,{{j\d+}}]                        loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>,<<LoopP>>] type:Int8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>,{{j\d+}}]                                   loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>,{{j\d+}}]                          loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Int8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdComplex(byte[] a, byte[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -109,20 +160,49 @@
   /// CHECK-DAG:                  Add [<<Phi2>>,<<Mul>>]                                loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                  Add [<<Phi1>>,<<Const1>>]                             loop:<<Loop>>      outer_loop:none
 
-  /// CHECK-START-{ARM64}: int other.TestByte.testDotProdSimpleUnsigned(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdSimpleUnsigned(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Uint8  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>,<<LoopP>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>,{{j\d+}}]                                   loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>,{{j\d+}}]                          loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
+
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdSimpleUnsigned(byte[], byte[]) disassembly (after)
+  /// CHECK:        VecDotProd
+  /// CHECK-IF:     hasIsaFeature("sve")
+  ///               CHECK:        udot z{{\d+}}.s, z{{\d+}}.b, z{{\d+}}.b
+  /// CHECK-ELIF:   hasIsaFeature("dotprod")
+  ///               CHECK-NEXT:   udot v{{\d+}}.4s, v{{\d+}}.16b, v{{\d+}}.16b
+  /// CHECK-ELSE:
+  ///               CHECK-NOT:    sdot
+  ///               CHECK-NOT:    udot
+  /// CHECK-FI:
   public static final int testDotProdSimpleUnsigned(byte[] a, byte[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -147,23 +227,44 @@
   /// CHECK-DAG:                  Add [<<Phi2>>,<<Mul>>]                                loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                  Add [<<Phi1>>,<<Const1>>]                             loop:<<Loop>>      outer_loop:none
 
-  /// CHECK-START-{ARM64}: int other.TestByte.testDotProdComplexUnsigned(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdComplexUnsigned(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Uint8  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>,{{j\d+}}]                        loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>,<<LoopP>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>,{{j\d+}}]                                   loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>,{{j\d+}}]                          loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdComplexUnsigned(byte[] a, byte[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -188,23 +289,44 @@
   /// CHECK-DAG:                  Add [<<Phi2>>,<<Mul>>]                                loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                  Add [<<Phi1>>,<<Const1>>]                             loop:<<Loop>>      outer_loop:none
 
-  /// CHECK-START-{ARM64}: int other.TestByte.testDotProdComplexUnsignedCastedToSigned(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdComplexUnsignedCastedToSigned(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Int8   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>,{{j\d+}}]                        loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>,<<LoopP>>] type:Int8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>,{{j\d+}}]                                   loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>,{{j\d+}}]                          loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Int8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdComplexUnsignedCastedToSigned(byte[] a, byte[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -229,23 +351,44 @@
   /// CHECK-DAG:                  Add [<<Phi2>>,<<Mul>>]                                loop:<<Loop>>      outer_loop:none
   /// CHECK-DAG:                  Add [<<Phi1>>,<<Const1>>]                             loop:<<Loop>>      outer_loop:none
 
-  /// CHECK-START-{ARM64}: int other.TestByte.testDotProdComplexSignedCastedToUnsigned(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdComplexSignedCastedToUnsigned(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Uint8  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>,{{j\d+}}]                        loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>,<<LoopP>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>,{{j\d+}}]                                   loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>,{{j\d+}}]                          loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdComplexSignedCastedToUnsigned(byte[] a, byte[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -255,7 +398,7 @@
     return s - 1;
   }
 
-  /// CHECK-START-{ARM64}: int other.TestByte.testDotProdSignedWidening(byte[], byte[]) loop_optimization (after)
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdSignedWidening(byte[], byte[]) loop_optimization (after)
   /// CHECK-DAG:                  VecDotProd type:Int8
   public static final int testDotProdSignedWidening(byte[] a, byte[] b) {
     int s = 1;
@@ -266,7 +409,7 @@
     return s - 1;
   }
 
-  /// CHECK-START-{ARM64}: int other.TestByte.testDotProdParamSigned(int, byte[]) loop_optimization (after)
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdParamSigned(int, byte[]) loop_optimization (after)
   /// CHECK-DAG:                  VecDotProd type:Int8
   public static final int testDotProdParamSigned(int x, byte[] b) {
     int s = 1;
@@ -277,7 +420,7 @@
     return s - 1;
   }
 
-  /// CHECK-START-{ARM64}: int other.TestByte.testDotProdParamUnsigned(int, byte[]) loop_optimization (after)
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdParamUnsigned(int, byte[]) loop_optimization (after)
   /// CHECK-DAG:                  VecDotProd type:Uint8
   public static final int testDotProdParamUnsigned(int x, byte[] b) {
     int s = 1;
diff --git a/test/684-checker-simd-dotprod/src/other/TestCharShort.java b/test/684-checker-simd-dotprod/src/other/TestCharShort.java
index 9cb9db5..07a7960 100644
--- a/test/684-checker-simd-dotprod/src/other/TestCharShort.java
+++ b/test/684-checker-simd-dotprod/src/other/TestCharShort.java
@@ -37,17 +37,26 @@
   /// CHECK-START-{ARM64}: int other.TestCharShort.testDotProdSimple(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Int16  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Int16  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdSimple(short[] a, short[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -75,20 +84,29 @@
   /// CHECK-START-{ARM64}: int other.TestCharShort.testDotProdComplex(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Int16  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Int16  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdComplex(short[] a, short[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -112,17 +130,26 @@
   /// CHECK-START-{ARM64}: int other.TestCharShort.testDotProdSimpleUnsigned(char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Uint16 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Uint16 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdSimpleUnsigned(char[] a, char[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -150,20 +177,29 @@
   /// CHECK-START-{ARM64}: int other.TestCharShort.testDotProdComplexUnsigned(char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Uint16 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Uint16 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdComplexUnsigned(char[] a, char[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -191,20 +227,29 @@
   /// CHECK-START-{ARM64}: int other.TestCharShort.testDotProdComplexUnsignedCastedToSigned(char[], char[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Int16  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Int16  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdComplexUnsignedCastedToSigned(char[] a, char[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -232,20 +277,29 @@
   /// CHECK-START-{ARM64}: int other.TestCharShort.testDotProdComplexSignedCastedToUnsigned(short[], short[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Uint16 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const1>>]                       loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd1:d\d+>>   VecAdd [<<Load1>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<VAdd2:d\d+>>   VecAdd [<<Load2>>,<<Repl>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<VAdd1>>,<<VAdd2>>] type:Uint16 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdComplexSignedCastedToUnsigned(short[] a, short[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -256,7 +310,16 @@
   }
 
   /// CHECK-START-{ARM64}: int other.TestCharShort.testDotProdSignedToInt(short[], short[]) loop_optimization (after)
-  /// CHECK-DAG:                  VecDotProd type:Int16
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:                  VecDotProd type:Int16
+  //
+  /// CHECK-FI:
   public static final int testDotProdSignedToInt(short[] a, short[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -267,7 +330,16 @@
   }
 
   /// CHECK-START-{ARM64}: int other.TestCharShort.testDotProdParamSigned(int, short[]) loop_optimization (after)
-  /// CHECK-DAG:                  VecDotProd type:Int16
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:                  VecDotProd type:Int16
+  //
+  /// CHECK-FI:
   public static final int testDotProdParamSigned(int x, short[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -278,7 +350,16 @@
   }
 
   /// CHECK-START-{ARM64}: int other.TestCharShort.testDotProdParamUnsigned(int, char[]) loop_optimization (after)
-  /// CHECK-DAG:                  VecDotProd type:Uint16
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:                  VecDotProd type:Uint16
+  //
+  /// CHECK-FI:
   public static final int testDotProdParamUnsigned(int x, char[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -300,7 +381,16 @@
   }
 
   /// CHECK-START-{ARM64}: int other.TestCharShort.testDotProdSignedToChar(short[], short[]) loop_optimization (after)
-  /// CHECK-DAG:                  VecDotProd type:Uint16
+  /// CHECK-IF:     hasIsaFeature("sve")
+  //
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG:                  VecDotProd type:Uint16
+  //
+  /// CHECK-FI:
   public static final int testDotProdSignedToChar(short[] a, short[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
diff --git a/test/684-checker-simd-dotprod/src/other/TestVarious.java b/test/684-checker-simd-dotprod/src/other/TestVarious.java
index 3f46098..ef03da1 100644
--- a/test/684-checker-simd-dotprod/src/other/TestVarious.java
+++ b/test/684-checker-simd-dotprod/src/other/TestVarious.java
@@ -35,18 +35,36 @@
   /// CHECK-START-{ARM64}: int other.TestVarious.testDotProdConstRight(byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
   /// CHECK-DAG: <<Const89:i\d+>> IntConstant 89                                        loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const89>>]                      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>] type:Int8    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const89>>,{{j\d+}}]                       loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>,<<LoopP>>] type:Int8    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>,{{j\d+}}]                                   loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>,{{j\d+}}]                          loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const89>>]                      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>] type:Int8    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdConstRight(byte[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -70,18 +88,36 @@
   /// CHECK-START-{ARM64}: int other.TestVarious.testDotProdConstLeft(byte[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
   /// CHECK-DAG: <<Const89:i\d+>> IntConstant 89                                        loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const89>>]                      loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>] type:Uint8   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const89>>,{{j\d+}}]                       loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>,<<LoopP>>] type:Uint8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>,{{j\d+}}]                                   loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>,{{j\d+}}]                          loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const89>>]                      loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>] type:Uint8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdConstLeft(byte[] b) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -110,21 +146,40 @@
   /// CHECK-DAG: <<Param:i\d+>>   ParameterValue                                        loop:none
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
   /// CHECK-DAG: <<ConstL:i\d+>>  IntConstant 129                                       loop:none
   /// CHECK-DAG: <<AddP:i\d+>>    Add [<<Param>>,<<ConstL>>]                            loop:none
   /// CHECK-DAG: <<TypeCnv:b\d+>> TypeConversion [<<AddP>>]                             loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<TypeCnv>>]                      loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>] type:Int8    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<TypeCnv>>,{{j\d+}}]                       loop:none
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                          loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>,<<LoopP>>] type:Int8    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>,{{j\d+}}]                                   loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>,{{j\d+}}]                          loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<TypeCnv>>]                      loop:none
+  //
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>] type:Int8    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                                  loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]                         loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdLoopInvariantConvRight(byte[] b, int param) {
     int s = 1;
     for (int i = 0; i < b.length; i++) {
@@ -181,16 +236,34 @@
   /// CHECK-START-{ARM64}: int other.TestVarious.testDotProdInt32(int[], int[]) loop_optimization (after)
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                             loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                             loop:none
-  /// CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Mul:d\d+>>     VecMul [<<Load1>>,<<Load2>>]              loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecAdd [<<Phi2>>,<<Mul>>]                 loop:<<Loop>>      outer_loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                      loop:none
-  /// CHECK-DAG:                  VecExtractScalar [<<Reduce>>]             loop:none
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>,{{j\d+}}]                 loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                           loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                              loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Mul:d\d+>>     VecMul [<<Load1>>,<<Load2>>,<<LoopP>>]              loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecAdd [<<Phi2>>,<<Mul>>,<<LoopP>>]                 loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>,{{j\d+}}]                       loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>,{{j\d+}}]              loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Set:d\d+>>     VecSetScalars [<<Const1>>]                loop:none
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set>>,{{d\d+}}]                    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Mul:d\d+>>     VecMul [<<Load1>>,<<Load2>>]              loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecAdd [<<Phi2>>,<<Mul>>]                 loop:<<Loop>>      outer_loop:none
+  //
+  ///     CHECK-DAG: <<Reduce:d\d+>>  VecReduce [<<Phi2>>]                      loop:none
+  ///     CHECK-DAG:                  VecExtractScalar [<<Reduce>>]             loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdInt32(int[] a, int[] b) {
     int s = 1;
     for (int i = 0;  i < b.length; i++) {
@@ -221,18 +294,37 @@
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
   /// CHECK-DAG: <<Const2:i\d+>>  IntConstant 2                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
-  /// CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>]                            loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Int8   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load1>>,<<Load2>>] type:Uint8  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>,{{j\d+}}]                             loop:none
+  //
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>,<<LoopP>>] type:Int8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load1>>,<<Load2>>,<<LoopP>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>]                            loop:none
+  //
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Int8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load1>>,<<Load2>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdBothSignedUnsigned1(byte[] a, byte[] b) {
     int s1 = 1;
     int s2 = 2;
@@ -266,20 +358,40 @@
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
   /// CHECK-DAG: <<Const2:i\d+>>  IntConstant 2                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
   /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42                                        loop:none
-  /// CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const42>>]                      loop:none
-  /// CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>]                            loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load2>>,<<Load1>>] type:Uint8  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>] type:Int8    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const42>>,{{j\d+}}]                       loop:none
+  ///     CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>,{{j\d+}}]                             loop:none
+  //
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load2>>,<<Load1>>,<<LoopP>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>,<<LoopP>>] type:Int8    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Repl:d\d+>>    VecReplicateScalar [<<Const42>>]                      loop:none
+  ///     CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>]                            loop:none
+  //
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load2>>,<<Load1>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Repl>>] type:Int8    loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdBothSignedUnsigned2(byte[] a, byte[] b) {
     int s1 = 1;
     int s2 = 2;
@@ -313,20 +425,41 @@
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
   /// CHECK-DAG: <<Const2:i\d+>>  IntConstant 2                                         loop:none
-  /// CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
-  /// CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>]                            loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Int8   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load3:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load4:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load3>>,<<Load4>>] type:Uint8  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>,{{j\d+}}]                             loop:none
+  ///     CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>,{{j\d+}}]                             loop:none
+  //
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                                       loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi1>>,{{i\d+}}]                                loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>,<<LoopP>>] type:Int8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load3:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load4:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>,<<LoopP>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load3>>,<<Load4>>,<<LoopP>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,{{i\d+}}]                                         loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const16:i\d+>> IntConstant 16                                        loop:none
+  ///     CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>]                            loop:none
+  //
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Int8   loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load3:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load4:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load3>>,<<Load4>>] type:Uint8  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const16>>]                            loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdBothSignedUnsignedDoubleLoad(byte[] a, byte[] b) {
     int s1 = 1;
     int s2 = 2;
@@ -358,18 +491,27 @@
   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                                         loop:none
   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                                         loop:none
   /// CHECK-DAG: <<Const2:i\d+>>  IntConstant 2                                         loop:none
-  /// CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
-  /// CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>]                            loop:none
-  /// CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>]                            loop:none
+  /// CHECK-IF:     hasIsaFeature("sve")
   //
-  /// CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load1>>,<<Load2>>] type:Int16  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Uint16 loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  //      16-bit DotProd is not supported for SVE.
+  ///     CHECK-NOT:                  VecDotProd
+  //
+  /// CHECK-ELSE:
+  //
+  ///     CHECK-DAG: <<Const8:i\d+>>  IntConstant 8                                         loop:none
+  ///     CHECK-DAG: <<Set1:d\d+>>    VecSetScalars [<<Const1>>]                            loop:none
+  ///     CHECK-DAG: <<Set2:d\d+>>    VecSetScalars [<<Const2>>]                            loop:none
+  //
+  ///     CHECK-DAG: <<Phi1:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                             loop:<<Loop:B\d+>> outer_loop:none
+  ///     CHECK-DAG: <<Phi2:d\d+>>    Phi [<<Set1>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Phi3:d\d+>>    Phi [<<Set2>>,{{d\d+}}]                               loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG: <<Load2:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]                           loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi3>>,<<Load1>>,<<Load2>>] type:Int16  loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  VecDotProd [<<Phi2>>,<<Load1>>,<<Load2>>] type:Uint16 loop:<<Loop>>      outer_loop:none
+  ///     CHECK-DAG:                  Add [<<Phi1>>,<<Const8>>]                             loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-FI:
   public static final int testDotProdBothSignedUnsignedChar(char[] a, char[] b) {
     int s1 = 1;
     int s2 = 2;
diff --git a/test/684-select-condition/Android.bp b/test/684-select-condition/Android.bp
new file mode 100644
index 0000000..4360d5d
--- /dev/null
+++ b/test/684-select-condition/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `684-select-condition`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-684-select-condition",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-684-select-condition-expected-stdout",
+        ":art-run-test-684-select-condition-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-684-select-condition-expected-stdout",
+    out: ["art-run-test-684-select-condition-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-684-select-condition-expected-stderr",
+    out: ["art-run-test-684-select-condition-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/684-select-condition/expected.txt b/test/684-select-condition/expected-stderr.txt
similarity index 100%
rename from test/684-select-condition/expected.txt
rename to test/684-select-condition/expected-stderr.txt
diff --git a/test/684-select-condition/expected.txt b/test/684-select-condition/expected-stdout.txt
similarity index 100%
copy from test/684-select-condition/expected.txt
copy to test/684-select-condition/expected-stdout.txt
diff --git a/test/685-deoptimizeable/Android.bp b/test/685-deoptimizeable/Android.bp
new file mode 100644
index 0000000..c02392c
--- /dev/null
+++ b/test/685-deoptimizeable/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `685-deoptimizeable`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-685-deoptimizeable",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-685-deoptimizeable-expected-stdout",
+        ":art-run-test-685-deoptimizeable-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-685-deoptimizeable-expected-stdout",
+    out: ["art-run-test-685-deoptimizeable-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-685-deoptimizeable-expected-stderr",
+    out: ["art-run-test-685-deoptimizeable-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/685-shifts/expected.txt b/test/685-deoptimizeable/expected-stderr.txt
similarity index 100%
copy from test/685-shifts/expected.txt
copy to test/685-deoptimizeable/expected-stderr.txt
diff --git a/test/685-deoptimizeable/expected.txt b/test/685-deoptimizeable/expected-stdout.txt
similarity index 100%
rename from test/685-deoptimizeable/expected.txt
rename to test/685-deoptimizeable/expected-stdout.txt
diff --git a/test/685-deoptimizeable/src/Main.java b/test/685-deoptimizeable/src/Main.java
index fc7fdea..41dcfd1 100644
--- a/test/685-deoptimizeable/src/Main.java
+++ b/test/685-deoptimizeable/src/Main.java
@@ -19,16 +19,16 @@
 import java.util.Comparator;
 import java.util.HashMap;
 
-class DummyObject {
+class SampleObject {
     public static boolean sHashCodeInvoked = false;
     private int i;
 
-    public DummyObject(int i) {
+    public SampleObject(int i) {
         this.i = i;
     }
 
     public boolean equals(Object obj) {
-        return (obj instanceof DummyObject) && (i == ((DummyObject)obj).i);
+        return (obj instanceof SampleObject) && (i == ((SampleObject)obj).i);
     }
 
     public int hashCode() {
@@ -64,7 +64,7 @@
         ensureJitCompiled(Main.class, "$noinline$run2");
         ensureJitCompiled(Main.class, "$noinline$run3A");
         ensureJitCompiled(Main.class, "$noinline$run3B");
-        ensureJitCompiled(DummyObject.class, "hashCode");
+        ensureJitCompiled(SampleObject.class, "hashCode");
     }
 
     public static void main(String[] args) throws Exception {
@@ -76,7 +76,7 @@
 
         ensureAllJitCompiled();
 
-        final HashMap<DummyObject, Long> map = new HashMap<DummyObject, Long>();
+        final HashMap<SampleObject, Long> map = new HashMap<SampleObject, Long>();
 
         // Single-frame deoptimization that covers partial fragment.
         execute(new Runnable() {
@@ -156,7 +156,7 @@
             public void runInternal() {
                 try {
                     assertIsManaged();
-                    map.put(new DummyObject(10), Long.valueOf(100));
+                    map.put(new SampleObject(10), Long.valueOf(100));
                     assertIsInterpreted();  // Every deoptimizeable method is deoptimized.
                 } catch (Exception e) {
                     e.printStackTrace(System.out);
@@ -167,10 +167,10 @@
         undeoptimizeAll();  // Make compiled code useable again.
         ensureAllJitCompiled();
 
-        if (!DummyObject.sHashCodeInvoked) {
+        if (!SampleObject.sHashCodeInvoked) {
             System.out.println("hashCode() method not invoked!");
         }
-        if (map.get(new DummyObject(10)) != 100) {
+        if (map.get(new SampleObject(10)) != 100) {
             System.out.println("Wrong hashmap value!");
         }
         System.out.println("Finishing");
diff --git a/test/685-shifts/expected.txt b/test/685-shifts/expected-stderr.txt
similarity index 100%
rename from test/685-shifts/expected.txt
rename to test/685-shifts/expected-stderr.txt
diff --git a/test/685-shifts/expected.txt b/test/685-shifts/expected-stdout.txt
similarity index 100%
copy from test/685-shifts/expected.txt
copy to test/685-shifts/expected-stdout.txt
diff --git a/test/685-shifts/expected.txt b/test/686-get-this/expected-stderr.txt
similarity index 100%
copy from test/685-shifts/expected.txt
copy to test/686-get-this/expected-stderr.txt
diff --git a/test/686-get-this/expected.txt b/test/686-get-this/expected-stdout.txt
similarity index 100%
rename from test/686-get-this/expected.txt
rename to test/686-get-this/expected-stdout.txt
diff --git a/test/687-deopt/Android.bp b/test/687-deopt/Android.bp
new file mode 100644
index 0000000..42054c9
--- /dev/null
+++ b/test/687-deopt/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `687-deopt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-687-deopt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-687-deopt-expected-stdout",
+        ":art-run-test-687-deopt-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-687-deopt-expected-stdout",
+    out: ["art-run-test-687-deopt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-687-deopt-expected-stderr",
+    out: ["art-run-test-687-deopt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/513-array-deopt/expected.txt b/test/687-deopt/expected-stderr.txt
similarity index 100%
copy from test/513-array-deopt/expected.txt
copy to test/687-deopt/expected-stderr.txt
diff --git a/test/687-deopt/expected.txt b/test/687-deopt/expected-stdout.txt
similarity index 100%
rename from test/687-deopt/expected.txt
rename to test/687-deopt/expected-stdout.txt
diff --git a/test/688-shared-library/check b/test/688-shared-library/check
index 55847cd..8501835 100644
--- a/test/688-shared-library/check
+++ b/test/688-shared-library/check
@@ -14,9 +14,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Finalizers of DexFile will complain not being able to close
 # the main dex file, as it's still open. That's OK to ignore.
 # Oat file manager will also complain about duplicate dex files. Ignore.
-sed -e '/^E\/System/d' "$2" | sed -e '/.*oat_file_manager.*/d' > "$2.tmp"
+sed -e '/^E\/System/d' "$4" | sed -e '/.*oat_file_manager.*/d' > "$4.tmp"
 
-diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4.tmp" >/dev/null
diff --git a/test/688-shared-library/expected.txt b/test/688-shared-library/expected-stderr.txt
similarity index 100%
rename from test/688-shared-library/expected.txt
rename to test/688-shared-library/expected-stderr.txt
diff --git a/test/688-shared-library/expected.txt b/test/688-shared-library/expected-stdout.txt
similarity index 100%
copy from test/688-shared-library/expected.txt
copy to test/688-shared-library/expected-stdout.txt
diff --git a/test/689-multi-catch/Android.bp b/test/689-multi-catch/Android.bp
new file mode 100644
index 0000000..3dbf0fb
--- /dev/null
+++ b/test/689-multi-catch/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `689-multi-catch`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-689-multi-catch",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-689-multi-catch-expected-stdout",
+        ":art-run-test-689-multi-catch-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-689-multi-catch-expected-stdout",
+    out: ["art-run-test-689-multi-catch-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-689-multi-catch-expected-stderr",
+    out: ["art-run-test-689-multi-catch-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/689-multi-catch/expected.txt b/test/689-multi-catch/expected-stderr.txt
similarity index 100%
rename from test/689-multi-catch/expected.txt
rename to test/689-multi-catch/expected-stderr.txt
diff --git a/test/689-multi-catch/expected.txt b/test/689-multi-catch/expected-stdout.txt
similarity index 100%
copy from test/689-multi-catch/expected.txt
copy to test/689-multi-catch/expected-stdout.txt
diff --git a/test/689-zygote-jit-deopt/Android.bp b/test/689-zygote-jit-deopt/Android.bp
new file mode 100644
index 0000000..0abbea7
--- /dev/null
+++ b/test/689-zygote-jit-deopt/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `689-zygote-jit-deopt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-689-zygote-jit-deopt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-689-zygote-jit-deopt-expected-stdout",
+        ":art-run-test-689-zygote-jit-deopt-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-689-zygote-jit-deopt-expected-stdout",
+    out: ["art-run-test-689-zygote-jit-deopt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-689-zygote-jit-deopt-expected-stderr",
+    out: ["art-run-test-689-zygote-jit-deopt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/513-array-deopt/expected.txt b/test/689-zygote-jit-deopt/expected-stderr.txt
similarity index 100%
copy from test/513-array-deopt/expected.txt
copy to test/689-zygote-jit-deopt/expected-stderr.txt
diff --git a/test/689-zygote-jit-deopt/expected.txt b/test/689-zygote-jit-deopt/expected-stdout.txt
similarity index 100%
rename from test/689-zygote-jit-deopt/expected.txt
rename to test/689-zygote-jit-deopt/expected-stdout.txt
diff --git a/test/632-checker-char-at-bounds/expected.txt b/test/690-hiddenapi-same-name-methods/expected-stderr.txt
similarity index 100%
copy from test/632-checker-char-at-bounds/expected.txt
copy to test/690-hiddenapi-same-name-methods/expected-stderr.txt
diff --git a/test/690-hiddenapi-same-name-methods/expected.txt b/test/690-hiddenapi-same-name-methods/expected-stdout.txt
similarity index 100%
rename from test/690-hiddenapi-same-name-methods/expected.txt
rename to test/690-hiddenapi-same-name-methods/expected-stdout.txt
diff --git a/test/690-hiddenapi-same-name-methods/hiddenapi-flags.csv b/test/690-hiddenapi-same-name-methods/hiddenapi-flags.csv
index 001ab80..2179922 100644
--- a/test/690-hiddenapi-same-name-methods/hiddenapi-flags.csv
+++ b/test/690-hiddenapi-same-name-methods/hiddenapi-flags.csv
@@ -1,9 +1,9 @@
-LSpecificClass;->foo()Ljava/lang/Double;,blacklist
-LDirectMethods;->foo()Ljava/lang/Integer;,blacklist
-LDirectMethods;->foo()Ljava/lang/Boolean;,blacklist
-LVirtualMethods;->foo()Ljava/lang/Integer;,blacklist
-LVirtualMethods;->foo()Ljava/lang/Boolean;,blacklist
-LSyntheticMethods;->foo()Ljava/lang/Integer;,blacklist
-LSyntheticMethods;->foo()Ljava/lang/Boolean;,blacklist
-LNonSyntheticMethods;->foo()Ljava/lang/Integer;,blacklist
-LNonSyntheticMethods;->foo()Ljava/lang/Boolean;,blacklist
\ No newline at end of file
+LSpecificClass;->foo()Ljava/lang/Double;,blocked
+LDirectMethods;->foo()Ljava/lang/Integer;,blocked
+LDirectMethods;->foo()Ljava/lang/Boolean;,blocked
+LVirtualMethods;->foo()Ljava/lang/Integer;,blocked
+LVirtualMethods;->foo()Ljava/lang/Boolean;,blocked
+LSyntheticMethods;->foo()Ljava/lang/Integer;,blocked
+LSyntheticMethods;->foo()Ljava/lang/Boolean;,blocked
+LNonSyntheticMethods;->foo()Ljava/lang/Integer;,blocked
+LNonSyntheticMethods;->foo()Ljava/lang/Boolean;,blocked
\ No newline at end of file
diff --git a/test/165-lock-owner-proxy/expected.txt b/test/691-hiddenapi-proxy/expected-stderr.txt
similarity index 100%
copy from test/165-lock-owner-proxy/expected.txt
copy to test/691-hiddenapi-proxy/expected-stderr.txt
diff --git a/test/691-hiddenapi-proxy/expected.txt b/test/691-hiddenapi-proxy/expected-stdout.txt
similarity index 100%
rename from test/691-hiddenapi-proxy/expected.txt
rename to test/691-hiddenapi-proxy/expected-stdout.txt
diff --git a/test/691-hiddenapi-proxy/hiddenapi-flags.csv b/test/691-hiddenapi-proxy/hiddenapi-flags.csv
index cc00e16..042ea08 100644
--- a/test/691-hiddenapi-proxy/hiddenapi-flags.csv
+++ b/test/691-hiddenapi-proxy/hiddenapi-flags.csv
@@ -1 +1 @@
-LMyInterface;->hidden()V,blacklist
\ No newline at end of file
+LMyInterface;->hidden()V,blocked
\ No newline at end of file
diff --git a/test/156-register-dex-file-multi-loader/expected.txt b/test/692-vdex-inmem-loader/expected-stderr.txt
similarity index 100%
copy from test/156-register-dex-file-multi-loader/expected.txt
copy to test/692-vdex-inmem-loader/expected-stderr.txt
diff --git a/test/692-vdex-inmem-loader/expected.txt b/test/692-vdex-inmem-loader/expected-stdout.txt
similarity index 100%
rename from test/692-vdex-inmem-loader/expected.txt
rename to test/692-vdex-inmem-loader/expected-stdout.txt
diff --git a/test/692-vdex-inmem-loader/src-ex/DummyClass.java b/test/692-vdex-inmem-loader/src-ex/DummyClass.java
deleted file mode 100644
index 443d1fe..0000000
--- a/test/692-vdex-inmem-loader/src-ex/DummyClass.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * 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 DummyClass {
-}
diff --git a/test/692-vdex-inmem-loader/src-ex/EmptyClass.java b/test/692-vdex-inmem-loader/src-ex/EmptyClass.java
new file mode 100644
index 0000000..92d8000
--- /dev/null
+++ b/test/692-vdex-inmem-loader/src-ex/EmptyClass.java
@@ -0,0 +1,18 @@
+/*
+ * 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 EmptyClass {
+}
diff --git a/test/692-vdex-inmem-loader/src/Main.java b/test/692-vdex-inmem-loader/src/Main.java
index 3ebe2c1..d7701fb 100644
--- a/test/692-vdex-inmem-loader/src/Main.java
+++ b/test/692-vdex-inmem-loader/src/Main.java
@@ -103,12 +103,14 @@
     test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled,
         /*invokeMethod*/ true);
 
-    // Change boot classpath checksum.
+    // Change boot classpath checksum. vdex files can still be loaded.
     appendToBootClassLoader(DEX_EXTRA, /*isCorePlatform*/ false);
 
     loaders = multiLoader();
-    test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ false);
-    test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ true);
+    test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled,
+        /*invokeMethod*/ false);
+    test(loaders[1], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled,
+        /*invokeMethod*/ true);
 
     loaders = multiLoader();
     test(loaders[0], /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled,
diff --git a/test/692-vdex-inmem-loader/vdex_inmem_loader.cc b/test/692-vdex-inmem-loader/vdex_inmem_loader.cc
index a10e2e7..1c7b6e8 100644
--- a/test/692-vdex-inmem-loader/vdex_inmem_loader.cc
+++ b/test/692-vdex-inmem-loader/vdex_inmem_loader.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "base/file_utils.h"
 #include "class_loader_utils.h"
 #include "jni.h"
 #include "nativehelper/scoped_utf_chars.h"
@@ -81,25 +82,27 @@
   StackHandleScope<1> hs(soa.Self());
   Handle<mirror::ClassLoader> h_loader = hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader));
 
-  std::vector<const DexFile::Header*> dex_headers;
+  std::vector<const DexFile*> dex_files;
   VisitClassLoaderDexFiles(
       soa,
       h_loader,
       [&](const DexFile* dex_file) {
-        dex_headers.push_back(&dex_file->GetHeader());
+        dex_files.push_back(dex_file);
         return true;
       });
 
-  uint32_t location_checksum;
-  std::string dex_location;
-  std::string vdex_filename;
+  std::string dex_location = dex_files[0]->GetLocation();
+  std::string odex_filename;
   std::string error_msg;
-  return OatFileAssistant::AnonymousDexVdexLocation(dex_headers,
-                                                    kRuntimeISA,
-                                                    &location_checksum,
-                                                    &dex_location,
-                                                    &vdex_filename) &&
-         OS::FileExists(vdex_filename.c_str());
+  if (!OatFileAssistant::DexLocationToOdexFilename(dex_location,
+                                                   kRuntimeISA,
+                                                   &odex_filename,
+                                                   &error_msg)) {
+    LOG(WARNING) << "Could not get odex filename for " << dex_location << ": " << error_msg;
+    return false;
+  }
+
+  return OS::FileExists(GetVdexFilename(odex_filename).c_str());
 }
 
 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isBackedByOatFile(JNIEnv*,
@@ -158,7 +161,7 @@
 
       ClassStatus oat_file_class_status(ClassStatus::kNotReady);
       bool is_preverified = class_linker->VerifyClassUsingOatFile(
-          *dex_file, h_class.Get(), oat_file_class_status);
+          soa.Self(), *dex_file, h_class, oat_file_class_status);
 
       if (is_first) {
         all_preverified = is_preverified;
diff --git a/test/156-register-dex-file-multi-loader/expected.txt b/test/692-vdex-secondary-loader/expected-stderr.txt
similarity index 100%
copy from test/156-register-dex-file-multi-loader/expected.txt
copy to test/692-vdex-secondary-loader/expected-stderr.txt
diff --git a/test/692-vdex-secondary-loader/expected-stdout.txt b/test/692-vdex-secondary-loader/expected-stdout.txt
new file mode 100644
index 0000000..a22ac74
--- /dev/null
+++ b/test/692-vdex-secondary-loader/expected-stdout.txt
@@ -0,0 +1,8 @@
+JNI_OnLoad called
+Hello
+Hello
+Hello
+JNI_OnLoad called
+Hello
+Hello
+Hello
diff --git a/test/692-vdex-secondary-loader/info.txt b/test/692-vdex-secondary-loader/info.txt
new file mode 100644
index 0000000..db23562
--- /dev/null
+++ b/test/692-vdex-secondary-loader/info.txt
@@ -0,0 +1,3 @@
+Test that dex files loaded with PathClassClassLoader get verified and the verification results
+cached in a vdex file. Subsequent loads should initialize an instance of
+OatFile using the data in the vdex.
diff --git a/test/692-vdex-secondary-loader/run b/test/692-vdex-secondary-loader/run
new file mode 100644
index 0000000..35b55d6
--- /dev/null
+++ b/test/692-vdex-secondary-loader/run
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 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.
+
+# Disable dex2oat of secondary dex files.
+${RUN} "$@" --no-secondary-compilation
+return_status1=$?
+
+# Set low RAM to hit the Madvise code which used to crash
+${RUN} "$@" --runtime-option -XX:LowMemoryMode --no-secondary-compilation
+return_status2=$?
+
+# Make sure we don't silently ignore an early failure.
+(exit $return_status1) && (exit $return_status2)
diff --git a/test/692-vdex-secondary-loader/src-ex/art/ClassA.java b/test/692-vdex-secondary-loader/src-ex/art/ClassA.java
new file mode 100644
index 0000000..7236216
--- /dev/null
+++ b/test/692-vdex-secondary-loader/src-ex/art/ClassA.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package art;
+
+public class ClassA {
+  public static String getHello() {
+    return "Hello";
+  }
+}
diff --git a/test/692-vdex-secondary-loader/src-ex/art/ClassB.java b/test/692-vdex-secondary-loader/src-ex/art/ClassB.java
new file mode 100644
index 0000000..9d62c07
--- /dev/null
+++ b/test/692-vdex-secondary-loader/src-ex/art/ClassB.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package art;
+
+public class ClassB {
+  public static void printHello() {
+    System.out.println(ClassA.getHello());
+  }
+}
diff --git a/test/692-vdex-secondary-loader/src/Main.java b/test/692-vdex-secondary-loader/src/Main.java
new file mode 100644
index 0000000..ed53faf
--- /dev/null
+++ b/test/692-vdex-secondary-loader/src/Main.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 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 dalvik.system.PathClassLoader;
+import java.lang.reflect.Method;
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.Base64;
+
+public class Main {
+  private static void check(boolean expected, boolean actual, String message) {
+    if (expected != actual) {
+      System.err.println(
+          "ERROR: " + message + " (expected=" + expected + ", actual=" + actual + ")");
+      throw new Error("");
+    }
+  }
+
+  private static ClassLoader singleLoader() {
+    return new PathClassLoader(DEX_EXTRA, /*parent*/null);
+  }
+
+  private static void test(ClassLoader loader,
+                           boolean expectedHasVdexFile,
+                           boolean expectedBackedByOat,
+                           boolean invokeMethod) throws Exception {
+    // If ART created a vdex file, it must have verified all the classes.
+    // That happens if and only if we expect a vdex at the end of the test but
+    // do not expect it to have been loaded.
+    boolean expectedClassesVerified = expectedHasVdexFile && !expectedBackedByOat;
+
+    waitForVerifier();
+    check(expectedClassesVerified, areClassesVerified(loader), "areClassesVerified");
+    check(expectedHasVdexFile, hasVdexFile(loader), "hasVdexFile");
+    check(expectedBackedByOat, isBackedByOatFile(loader), "isBackedByOatFile");
+    check(expectedBackedByOat, areClassesPreverified(loader), "areClassesPreverified");
+
+    if (invokeMethod) {
+      loader.loadClass("art.ClassB").getDeclaredMethod("printHello").invoke(null);
+    }
+
+    if (expectedBackedByOat) {
+      String filter = getCompilerFilter(loader.loadClass("art.ClassB"));
+      if (!("verify".equals(filter))) {
+        throw new Error("Expected verify, got " + filter);
+      }
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    System.loadLibrary(args[0]);
+
+    // Feature is disabled in debuggable mode because runtime threads are not
+    // allowed to load classes.
+    boolean featureEnabled = !isDebuggable();
+
+    // SDK version not set. Background verification job should not have run
+    // and vdex should not have been created.
+    test(singleLoader(), /*hasVdex*/ false, /*backedByOat*/ false, /*invokeMethod*/ true);
+
+    // Feature only enabled for target SDK version Q and later.
+    setTargetSdkVersion(/* Q */ 29);
+
+    // SDK version directory is now set. Background verification job should have run,
+    // should have verified classes and written results to a vdex.
+    test(singleLoader(), /*hasVdex*/ featureEnabled, /*backedByOat*/ false, /*invokeMethod*/ true);
+    test(singleLoader(), /*hasVdex*/ featureEnabled, /*backedByOat*/ featureEnabled,
+        /*invokeMethod*/ true);
+  }
+
+  private static native boolean isDebuggable();
+  private static native int setTargetSdkVersion(int version);
+  private static native void waitForVerifier();
+  private static native boolean areClassesVerified(ClassLoader loader);
+  private static native boolean hasVdexFile(ClassLoader loader);
+  private static native boolean isBackedByOatFile(ClassLoader loader);
+  private static native boolean areClassesPreverified(ClassLoader loader);
+  private static native String getCompilerFilter(Class cls);
+
+  private static final String DEX_LOCATION = System.getenv("DEX_LOCATION");
+  private static final String DEX_EXTRA =
+      new File(DEX_LOCATION, "692-vdex-secondary-loader-ex.jar").getAbsolutePath();
+}
diff --git a/test/693-vdex-inmem-loader-evict/Android.bp b/test/693-vdex-inmem-loader-evict/Android.bp
new file mode 100644
index 0000000..ffc72cd
--- /dev/null
+++ b/test/693-vdex-inmem-loader-evict/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `693-vdex-inmem-loader-evict`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-693-vdex-inmem-loader-evict",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-693-vdex-inmem-loader-evict-expected-stdout",
+        ":art-run-test-693-vdex-inmem-loader-evict-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-693-vdex-inmem-loader-evict-expected-stdout",
+    out: ["art-run-test-693-vdex-inmem-loader-evict-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-693-vdex-inmem-loader-evict-expected-stderr",
+    out: ["art-run-test-693-vdex-inmem-loader-evict-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/152-dead-large-object/expected.txt b/test/693-vdex-inmem-loader-evict/expected-stderr.txt
similarity index 100%
copy from test/152-dead-large-object/expected.txt
copy to test/693-vdex-inmem-loader-evict/expected-stderr.txt
diff --git a/test/693-vdex-inmem-loader-evict/expected.txt b/test/693-vdex-inmem-loader-evict/expected-stdout.txt
similarity index 100%
rename from test/693-vdex-inmem-loader-evict/expected.txt
rename to test/693-vdex-inmem-loader-evict/expected-stdout.txt
diff --git a/test/694-clinit-jit/Android.bp b/test/694-clinit-jit/Android.bp
new file mode 100644
index 0000000..2f25ec0
--- /dev/null
+++ b/test/694-clinit-jit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `694-clinit-jit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-694-clinit-jit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-694-clinit-jit-expected-stdout",
+        ":art-run-test-694-clinit-jit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-694-clinit-jit-expected-stdout",
+    out: ["art-run-test-694-clinit-jit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-694-clinit-jit-expected-stderr",
+    out: ["art-run-test-694-clinit-jit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/529-long-split/expected.txt b/test/694-clinit-jit/expected-stderr.txt
similarity index 100%
copy from test/529-long-split/expected.txt
copy to test/694-clinit-jit/expected-stderr.txt
diff --git a/test/694-clinit-jit/expected.txt b/test/694-clinit-jit/expected-stdout.txt
similarity index 100%
rename from test/694-clinit-jit/expected.txt
rename to test/694-clinit-jit/expected-stdout.txt
diff --git a/test/695-simplify-throws/Android.bp b/test/695-simplify-throws/Android.bp
new file mode 100644
index 0000000..d6d7c7c
--- /dev/null
+++ b/test/695-simplify-throws/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `695-simplify-throws`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-695-simplify-throws",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-695-simplify-throws-expected-stdout",
+        ":art-run-test-695-simplify-throws-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-695-simplify-throws-expected-stdout",
+    out: ["art-run-test-695-simplify-throws-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-695-simplify-throws-expected-stderr",
+    out: ["art-run-test-695-simplify-throws-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/695-simplify-throws/expected.txt b/test/695-simplify-throws/expected-stderr.txt
similarity index 100%
rename from test/695-simplify-throws/expected.txt
rename to test/695-simplify-throws/expected-stderr.txt
diff --git a/test/695-simplify-throws/expected.txt b/test/695-simplify-throws/expected-stdout.txt
similarity index 100%
copy from test/695-simplify-throws/expected.txt
copy to test/695-simplify-throws/expected-stdout.txt
diff --git a/test/696-loop/Android.bp b/test/696-loop/Android.bp
new file mode 100644
index 0000000..b39271f
--- /dev/null
+++ b/test/696-loop/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `696-loop`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-696-loop",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-696-loop-expected-stdout",
+        ":art-run-test-696-loop-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-696-loop-expected-stdout",
+    out: ["art-run-test-696-loop-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-696-loop-expected-stderr",
+    out: ["art-run-test-696-loop-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/696-loop/expected.txt b/test/696-loop/expected-stderr.txt
similarity index 100%
rename from test/696-loop/expected.txt
rename to test/696-loop/expected-stderr.txt
diff --git a/test/696-loop/expected.txt b/test/696-loop/expected-stdout.txt
similarity index 100%
copy from test/696-loop/expected.txt
copy to test/696-loop/expected-stdout.txt
diff --git a/test/697-checker-string-append/Android.bp b/test/697-checker-string-append/Android.bp
new file mode 100644
index 0000000..767e970
--- /dev/null
+++ b/test/697-checker-string-append/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `697-checker-string-append`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-697-checker-string-append",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-697-checker-string-append-expected-stdout",
+        ":art-run-test-697-checker-string-append-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-697-checker-string-append-expected-stdout",
+    out: ["art-run-test-697-checker-string-append-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-697-checker-string-append-expected-stderr",
+    out: ["art-run-test-697-checker-string-append-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/697-checker-string-append/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/697-checker-string-append/expected-stderr.txt
diff --git a/test/697-checker-string-append/expected.txt b/test/697-checker-string-append/expected-stdout.txt
similarity index 100%
rename from test/697-checker-string-append/expected.txt
rename to test/697-checker-string-append/expected-stdout.txt
diff --git a/test/698-selects/Android.bp b/test/698-selects/Android.bp
new file mode 100644
index 0000000..a3be249
--- /dev/null
+++ b/test/698-selects/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `698-selects`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-698-selects",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-698-selects-expected-stdout",
+        ":art-run-test-698-selects-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-698-selects-expected-stdout",
+    out: ["art-run-test-698-selects-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-698-selects-expected-stderr",
+    out: ["art-run-test-698-selects-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/698-selects/expected.txt b/test/698-selects/expected-stderr.txt
similarity index 100%
rename from test/698-selects/expected.txt
rename to test/698-selects/expected-stderr.txt
diff --git a/test/698-selects/expected.txt b/test/698-selects/expected-stdout.txt
similarity index 100%
copy from test/698-selects/expected.txt
copy to test/698-selects/expected-stdout.txt
diff --git a/test/695-simplify-throws/expected.txt b/test/699-checker-string-append2/expected-stderr.txt
similarity index 100%
copy from test/695-simplify-throws/expected.txt
copy to test/699-checker-string-append2/expected-stderr.txt
diff --git a/test/699-checker-string-append2/expected.txt b/test/699-checker-string-append2/expected-stdout.txt
similarity index 100%
rename from test/699-checker-string-append2/expected.txt
rename to test/699-checker-string-append2/expected-stdout.txt
diff --git a/test/700-LoadArgRegs/Android.bp b/test/700-LoadArgRegs/Android.bp
new file mode 100644
index 0000000..bbaa28d
--- /dev/null
+++ b/test/700-LoadArgRegs/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `700-LoadArgRegs`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-700-LoadArgRegs",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-700-LoadArgRegs-expected-stdout",
+        ":art-run-test-700-LoadArgRegs-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-700-LoadArgRegs-expected-stdout",
+    out: ["art-run-test-700-LoadArgRegs-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-700-LoadArgRegs-expected-stderr",
+    out: ["art-run-test-700-LoadArgRegs-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/700-LoadArgRegs/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/700-LoadArgRegs/expected-stderr.txt
diff --git a/test/700-LoadArgRegs/expected.txt b/test/700-LoadArgRegs/expected-stdout.txt
similarity index 100%
rename from test/700-LoadArgRegs/expected.txt
rename to test/700-LoadArgRegs/expected-stdout.txt
diff --git a/test/701-easy-div-rem/build b/test/701-easy-div-rem/build
index affb432..6d114b6 100644
--- a/test/701-easy-div-rem/build
+++ b/test/701-easy-div-rem/build
@@ -19,6 +19,6 @@
 
 # Write out the source file.
 mkdir src
-python ./genMain.py
+python3 ./genMain.py
 
 ./default-build "$@"
diff --git a/test/561-divrem/expected.txt b/test/701-easy-div-rem/expected-stderr.txt
similarity index 100%
copy from test/561-divrem/expected.txt
copy to test/701-easy-div-rem/expected-stderr.txt
diff --git a/test/701-easy-div-rem/expected.txt b/test/701-easy-div-rem/expected-stdout.txt
similarity index 100%
rename from test/701-easy-div-rem/expected.txt
rename to test/701-easy-div-rem/expected-stdout.txt
diff --git a/test/456-baseline-array-set/expected.txt b/test/702-LargeBranchOffset/expected-stderr.txt
similarity index 100%
copy from test/456-baseline-array-set/expected.txt
copy to test/702-LargeBranchOffset/expected-stderr.txt
diff --git a/test/702-LargeBranchOffset/expected.txt b/test/702-LargeBranchOffset/expected-stdout.txt
similarity index 100%
rename from test/702-LargeBranchOffset/expected.txt
rename to test/702-LargeBranchOffset/expected-stdout.txt
diff --git a/test/703-floating-point-div/Android.bp b/test/703-floating-point-div/Android.bp
new file mode 100644
index 0000000..42ae166
--- /dev/null
+++ b/test/703-floating-point-div/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `703-floating-point-div`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-703-floating-point-div",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-703-floating-point-div-expected-stdout",
+        ":art-run-test-703-floating-point-div-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-703-floating-point-div-expected-stdout",
+    out: ["art-run-test-703-floating-point-div-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-703-floating-point-div-expected-stderr",
+    out: ["art-run-test-703-floating-point-div-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/706-checker-scheduler/expected.txt b/test/703-floating-point-div/expected-stderr.txt
similarity index 100%
copy from test/706-checker-scheduler/expected.txt
copy to test/703-floating-point-div/expected-stderr.txt
diff --git a/test/703-floating-point-div/expected.txt b/test/703-floating-point-div/expected-stdout.txt
similarity index 100%
rename from test/703-floating-point-div/expected.txt
rename to test/703-floating-point-div/expected-stdout.txt
diff --git a/test/704-multiply-accumulate/Android.bp b/test/704-multiply-accumulate/Android.bp
new file mode 100644
index 0000000..3cd5ba1
--- /dev/null
+++ b/test/704-multiply-accumulate/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `704-multiply-accumulate`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-704-multiply-accumulate",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-704-multiply-accumulate-expected-stdout",
+        ":art-run-test-704-multiply-accumulate-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-704-multiply-accumulate-expected-stdout",
+    out: ["art-run-test-704-multiply-accumulate-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-704-multiply-accumulate-expected-stderr",
+    out: ["art-run-test-704-multiply-accumulate-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/550-checker-multiply-accumulate/expected.txt b/test/704-multiply-accumulate/expected-stderr.txt
similarity index 100%
copy from test/550-checker-multiply-accumulate/expected.txt
copy to test/704-multiply-accumulate/expected-stderr.txt
diff --git a/test/704-multiply-accumulate/expected.txt b/test/704-multiply-accumulate/expected-stdout.txt
similarity index 100%
rename from test/704-multiply-accumulate/expected.txt
rename to test/704-multiply-accumulate/expected-stdout.txt
diff --git a/test/705-register-conflict/Android.bp b/test/705-register-conflict/Android.bp
new file mode 100644
index 0000000..6182c2f
--- /dev/null
+++ b/test/705-register-conflict/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `705-register-conflict`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-705-register-conflict",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-705-register-conflict-expected-stdout",
+        ":art-run-test-705-register-conflict-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-705-register-conflict-expected-stdout",
+    out: ["art-run-test-705-register-conflict-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-705-register-conflict-expected-stderr",
+    out: ["art-run-test-705-register-conflict-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/725-imt-conflict-object/expected.txt b/test/705-register-conflict/expected-stderr.txt
similarity index 100%
copy from test/725-imt-conflict-object/expected.txt
copy to test/705-register-conflict/expected-stderr.txt
diff --git a/test/705-register-conflict/expected.txt b/test/705-register-conflict/expected-stdout.txt
similarity index 100%
rename from test/705-register-conflict/expected.txt
rename to test/705-register-conflict/expected-stdout.txt
diff --git a/test/706-checker-scheduler/expected.txt b/test/706-checker-scheduler/expected-stderr.txt
similarity index 100%
rename from test/706-checker-scheduler/expected.txt
rename to test/706-checker-scheduler/expected-stderr.txt
diff --git a/test/706-checker-scheduler/expected.txt b/test/706-checker-scheduler/expected-stdout.txt
similarity index 100%
copy from test/706-checker-scheduler/expected.txt
copy to test/706-checker-scheduler/expected-stdout.txt
diff --git a/test/707-checker-invalid-profile/Android.bp b/test/707-checker-invalid-profile/Android.bp
new file mode 100644
index 0000000..8d813cc
--- /dev/null
+++ b/test/707-checker-invalid-profile/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `707-checker-invalid-profile`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-707-checker-invalid-profile",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-707-checker-invalid-profile-expected-stdout",
+        ":art-run-test-707-checker-invalid-profile-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-707-checker-invalid-profile-expected-stdout",
+    out: ["art-run-test-707-checker-invalid-profile-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-707-checker-invalid-profile-expected-stderr",
+    out: ["art-run-test-707-checker-invalid-profile-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/707-checker-invalid-profile/check b/test/707-checker-invalid-profile/check
index 976afc4..58d3a52 100755
--- a/test/707-checker-invalid-profile/check
+++ b/test/707-checker-invalid-profile/check
@@ -14,8 +14,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # When profile verification fails, dex2oat logs an error. The following
 # command strips out the error message.
 grep -v -f $1 $2 > $1
+grep -v -f $3 $4 > $3
 
 ./default-check "$@"
diff --git a/test/438-volatile/expected.txt b/test/707-checker-invalid-profile/expected-stderr.txt
similarity index 100%
copy from test/438-volatile/expected.txt
copy to test/707-checker-invalid-profile/expected-stderr.txt
diff --git a/test/707-checker-invalid-profile/expected.txt b/test/707-checker-invalid-profile/expected-stdout.txt
similarity index 100%
rename from test/707-checker-invalid-profile/expected.txt
rename to test/707-checker-invalid-profile/expected-stdout.txt
diff --git a/test/707-checker-invalid-profile/profile b/test/707-checker-invalid-profile/profile
index f142c40..171d656 100644
--- a/test/707-checker-invalid-profile/profile
+++ b/test/707-checker-invalid-profile/profile
@@ -1,4 +1,9 @@
 SHLMain;->attemptInlineMonomorphic(LMain;)I+invalid_class
 SHLMain;->attemptInlinePolymorphic(LMain;)I+LMain;,invalid_class
 SHLMain;->invalid_method
-invalid_class
\ No newline at end of file
+invalid_class
+
+# Invalid descriptor in inline cache spec causes the entire line to be rejected
+# and this test requires the methods to be present in the profile.
+SHLMain;->attemptInlineMonomorphic(LMain;)I
+SHLMain;->attemptInlinePolymorphic(LMain;)I
diff --git a/test/708-jit-cache-churn/Android.bp b/test/708-jit-cache-churn/Android.bp
new file mode 100644
index 0000000..883983f
--- /dev/null
+++ b/test/708-jit-cache-churn/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `708-jit-cache-churn`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-708-jit-cache-churn",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-708-jit-cache-churn-expected-stdout",
+        ":art-run-test-708-jit-cache-churn-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-708-jit-cache-churn-expected-stdout",
+    out: ["art-run-test-708-jit-cache-churn-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-708-jit-cache-churn-expected-stderr",
+    out: ["art-run-test-708-jit-cache-churn-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/708-jit-cache-churn/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/708-jit-cache-churn/expected-stderr.txt
diff --git a/test/708-jit-cache-churn/expected.txt b/test/708-jit-cache-churn/expected-stdout.txt
similarity index 100%
rename from test/708-jit-cache-churn/expected.txt
rename to test/708-jit-cache-churn/expected-stdout.txt
diff --git a/test/709-checker-varhandles/build b/test/709-checker-varhandles/build
deleted file mode 100755
index 2b0b2c1..0000000
--- a/test/709-checker-varhandles/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-# make us exit on a failure
-set -e
-
-./default-build "$@" --experimental method-handles
diff --git a/test/709-checker-varhandles/expected.txt b/test/709-checker-varhandles/expected.txt
deleted file mode 100644
index 651da72..0000000
--- a/test/709-checker-varhandles/expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-starting
-passed
diff --git a/test/709-checker-varhandles/info.txt b/test/709-checker-varhandles/info.txt
deleted file mode 100644
index 2221240..0000000
--- a/test/709-checker-varhandles/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test support for intrinsics in Java 9 java.lang.invoke.VarHandle.
diff --git a/test/709-checker-varhandles/src/Main.java b/test/709-checker-varhandles/src/Main.java
deleted file mode 100644
index d0ea834..0000000
--- a/test/709-checker-varhandles/src/Main.java
+++ /dev/null
@@ -1,104 +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.
- */
-
-import java.lang.invoke.VarHandle;
-
-/**
- * Checker test on the 1.8 unsafe operations. Note, this is by no means an
- * exhaustive unit test for these CAS (compare-and-swap) and fence operations.
- * Instead, this test ensures the methods are recognized as intrinsic and behave
- * as expected.
- */
-public class Main {
-
-  //
-  // Fences (native).
-  //
-
-  /// CHECK-START: void Main.fullFence() builder (after)
-  /// CHECK-DAG: InvokeStaticOrDirect intrinsic:VarHandleFullFence
-  //
-  /// CHECK-START: void Main.fullFence() instruction_simplifier (after)
-  /// CHECK-NOT: InvokeStaticOrDirect intrinsic:VarHandleFullFence
-  //
-  /// CHECK-START: void Main.fullFence() instruction_simplifier (after)
-  /// CHECK-DAG: MemoryBarrier kind:AnyAny
-  private static void fullFence() {
-      VarHandle.fullFence();
-  }
-
-  /// CHECK-START: void Main.acquireFence() builder (after)
-  /// CHECK-DAG: InvokeStaticOrDirect intrinsic:VarHandleAcquireFence
-  //
-  /// CHECK-START: void Main.acquireFence() instruction_simplifier (after)
-  /// CHECK-NOT: InvokeStaticOrDirect intrinsic:VarHandleAcquireFence
-  //
-  /// CHECK-START: void Main.acquireFence() instruction_simplifier (after)
-  /// CHECK-DAG: MemoryBarrier kind:LoadAny
-  private static void acquireFence() {
-      VarHandle.acquireFence();
-  }
-
-  /// CHECK-START: void Main.releaseFence() builder (after)
-  /// CHECK-DAG: InvokeStaticOrDirect intrinsic:VarHandleReleaseFence
-  //
-  /// CHECK-START: void Main.releaseFence() instruction_simplifier (after)
-  /// CHECK-NOT: InvokeStaticOrDirect intrinsic:VarHandleReleaseFence
-  //
-  /// CHECK-START: void Main.releaseFence() instruction_simplifier (after)
-  /// CHECK-DAG: MemoryBarrier kind:AnyStore
-  private static void releaseFence() {
-      VarHandle.releaseFence();
-  }
-
-  /// CHECK-START: void Main.loadLoadFence() builder (after)
-  /// CHECK-DAG: InvokeStaticOrDirect intrinsic:VarHandleLoadLoadFence
-  //
-  /// CHECK-START: void Main.loadLoadFence() instruction_simplifier (after)
-  /// CHECK-NOT: InvokeStaticOrDirect intrinsic:VarHandleLoadLoadFence
-  //
-  /// CHECK-START: void Main.loadLoadFence() instruction_simplifier (after)
-  /// CHECK-DAG: MemoryBarrier kind:LoadAny
-  private static void loadLoadFence() {
-      VarHandle.loadLoadFence();
-  }
-
-  /// CHECK-START: void Main.storeStoreFence() builder (after)
-  /// CHECK-DAG: InvokeStaticOrDirect intrinsic:VarHandleStoreStoreFence
-  //
-  /// CHECK-START: void Main.storeStoreFence() instruction_simplifier (after)
-  /// CHECK-NOT: InvokeStaticOrDirect intrinsic:VarHandleStoreStoreFence
-  //
-  /// CHECK-START: void Main.storeStoreFence() instruction_simplifier (after)
-  /// CHECK-DAG: MemoryBarrier kind:StoreStore
-  private static void storeStoreFence() {
-      VarHandle.storeStoreFence();
-  }
-
-  //
-  // Driver.
-  //
-
-  public static void main(String[] args) {
-    System.out.println("starting");
-    acquireFence();
-    releaseFence();
-    loadLoadFence();
-    storeStoreFence();
-    fullFence();
-    System.out.println("passed");
-  }
-}
diff --git a/test/080-oom-fragmentation/expected.txt b/test/710-varhandle-creation/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/710-varhandle-creation/expected-stderr.txt
diff --git a/test/710-varhandle-creation/expected.txt b/test/710-varhandle-creation/expected-stdout.txt
similarity index 100%
rename from test/710-varhandle-creation/expected.txt
rename to test/710-varhandle-creation/expected-stdout.txt
diff --git a/test/711-checker-type-conversion/Android.bp b/test/711-checker-type-conversion/Android.bp
new file mode 100644
index 0000000..f9ae9d0
--- /dev/null
+++ b/test/711-checker-type-conversion/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `711-checker-type-conversion`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-711-checker-type-conversion",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-711-checker-type-conversion-expected-stdout",
+        ":art-run-test-711-checker-type-conversion-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-711-checker-type-conversion-expected-stdout",
+    out: ["art-run-test-711-checker-type-conversion-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-711-checker-type-conversion-expected-stderr",
+    out: ["art-run-test-711-checker-type-conversion-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/711-checker-type-conversion/expected.txt b/test/711-checker-type-conversion/expected-stderr.txt
similarity index 100%
rename from test/711-checker-type-conversion/expected.txt
rename to test/711-checker-type-conversion/expected-stderr.txt
diff --git a/test/711-checker-type-conversion/expected.txt b/test/711-checker-type-conversion/expected-stdout.txt
similarity index 100%
copy from test/711-checker-type-conversion/expected.txt
copy to test/711-checker-type-conversion/expected-stdout.txt
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/712-varhandle-invocations/expected-stderr.txt
similarity index 100%
copy from test/148-multithread-gc-annotations/expected.txt
copy to test/712-varhandle-invocations/expected-stderr.txt
diff --git a/test/712-varhandle-invocations/expected-stdout.txt b/test/712-varhandle-invocations/expected-stdout.txt
new file mode 100644
index 0000000..a274e0b
--- /dev/null
+++ b/test/712-varhandle-invocations/expected-stdout.txt
@@ -0,0 +1,3341 @@
+FieldGetBoolean...OK
+FieldGetByte...OK
+FieldGetShort...OK
+FieldGetChar...OK
+FieldGetInt...OK
+FieldGetLong...OK
+FieldGetFloat...OK
+FieldGetDouble...OK
+FieldSetBoolean...OK
+FieldSetByte...OK
+FieldSetShort...OK
+FieldSetChar...OK
+FieldSetInt...OK
+FieldSetLong...OK
+FieldSetFloat...OK
+FieldSetDouble...OK
+FieldGetVolatileBoolean...OK
+FieldGetVolatileByte...OK
+FieldGetVolatileShort...OK
+FieldGetVolatileChar...OK
+FieldGetVolatileInt...OK
+FieldGetVolatileLong...OK
+FieldGetVolatileFloat...OK
+FieldGetVolatileDouble...OK
+FieldSetVolatileBoolean...OK
+FieldSetVolatileByte...OK
+FieldSetVolatileShort...OK
+FieldSetVolatileChar...OK
+FieldSetVolatileInt...OK
+FieldSetVolatileLong...OK
+FieldSetVolatileFloat...OK
+FieldSetVolatileDouble...OK
+FieldGetAcquireBoolean...OK
+FieldGetAcquireByte...OK
+FieldGetAcquireShort...OK
+FieldGetAcquireChar...OK
+FieldGetAcquireInt...OK
+FieldGetAcquireLong...OK
+FieldGetAcquireFloat...OK
+FieldGetAcquireDouble...OK
+FieldSetReleaseBoolean...OK
+FieldSetReleaseByte...OK
+FieldSetReleaseShort...OK
+FieldSetReleaseChar...OK
+FieldSetReleaseInt...OK
+FieldSetReleaseLong...OK
+FieldSetReleaseFloat...OK
+FieldSetReleaseDouble...OK
+FieldGetOpaqueBoolean...OK
+FieldGetOpaqueByte...OK
+FieldGetOpaqueShort...OK
+FieldGetOpaqueChar...OK
+FieldGetOpaqueInt...OK
+FieldGetOpaqueLong...OK
+FieldGetOpaqueFloat...OK
+FieldGetOpaqueDouble...OK
+FieldSetOpaqueBoolean...OK
+FieldSetOpaqueByte...OK
+FieldSetOpaqueShort...OK
+FieldSetOpaqueChar...OK
+FieldSetOpaqueInt...OK
+FieldSetOpaqueLong...OK
+FieldSetOpaqueFloat...OK
+FieldSetOpaqueDouble...OK
+FieldCompareAndSetBoolean...OK
+FieldCompareAndSetByte...OK
+FieldCompareAndSetShort...OK
+FieldCompareAndSetChar...OK
+FieldCompareAndSetInt...OK
+FieldCompareAndSetLong...OK
+FieldCompareAndSetFloat...OK
+FieldCompareAndSetDouble...OK
+FieldCompareAndExchangeBoolean...OK
+FieldCompareAndExchangeByte...OK
+FieldCompareAndExchangeShort...OK
+FieldCompareAndExchangeChar...OK
+FieldCompareAndExchangeInt...OK
+FieldCompareAndExchangeLong...OK
+FieldCompareAndExchangeFloat...OK
+FieldCompareAndExchangeDouble...OK
+FieldCompareAndExchangeAcquireBoolean...OK
+FieldCompareAndExchangeAcquireByte...OK
+FieldCompareAndExchangeAcquireShort...OK
+FieldCompareAndExchangeAcquireChar...OK
+FieldCompareAndExchangeAcquireInt...OK
+FieldCompareAndExchangeAcquireLong...OK
+FieldCompareAndExchangeAcquireFloat...OK
+FieldCompareAndExchangeAcquireDouble...OK
+FieldCompareAndExchangeReleaseBoolean...OK
+FieldCompareAndExchangeReleaseByte...OK
+FieldCompareAndExchangeReleaseShort...OK
+FieldCompareAndExchangeReleaseChar...OK
+FieldCompareAndExchangeReleaseInt...OK
+FieldCompareAndExchangeReleaseLong...OK
+FieldCompareAndExchangeReleaseFloat...OK
+FieldCompareAndExchangeReleaseDouble...OK
+FieldWeakCompareAndSetPlainBoolean...OK
+FieldWeakCompareAndSetPlainByte...OK
+FieldWeakCompareAndSetPlainShort...OK
+FieldWeakCompareAndSetPlainChar...OK
+FieldWeakCompareAndSetPlainInt...OK
+FieldWeakCompareAndSetPlainLong...OK
+FieldWeakCompareAndSetPlainFloat...OK
+FieldWeakCompareAndSetPlainDouble...OK
+FieldWeakCompareAndSetBoolean...OK
+FieldWeakCompareAndSetByte...OK
+FieldWeakCompareAndSetShort...OK
+FieldWeakCompareAndSetChar...OK
+FieldWeakCompareAndSetInt...OK
+FieldWeakCompareAndSetLong...OK
+FieldWeakCompareAndSetFloat...OK
+FieldWeakCompareAndSetDouble...OK
+FieldWeakCompareAndSetAcquireBoolean...OK
+FieldWeakCompareAndSetAcquireByte...OK
+FieldWeakCompareAndSetAcquireShort...OK
+FieldWeakCompareAndSetAcquireChar...OK
+FieldWeakCompareAndSetAcquireInt...OK
+FieldWeakCompareAndSetAcquireLong...OK
+FieldWeakCompareAndSetAcquireFloat...OK
+FieldWeakCompareAndSetAcquireDouble...OK
+FieldWeakCompareAndSetReleaseBoolean...OK
+FieldWeakCompareAndSetReleaseByte...OK
+FieldWeakCompareAndSetReleaseShort...OK
+FieldWeakCompareAndSetReleaseChar...OK
+FieldWeakCompareAndSetReleaseInt...OK
+FieldWeakCompareAndSetReleaseLong...OK
+FieldWeakCompareAndSetReleaseFloat...OK
+FieldWeakCompareAndSetReleaseDouble...OK
+FieldGetAndSetBoolean...OK
+FieldGetAndSetByte...OK
+FieldGetAndSetShort...OK
+FieldGetAndSetChar...OK
+FieldGetAndSetInt...OK
+FieldGetAndSetLong...OK
+FieldGetAndSetFloat...OK
+FieldGetAndSetDouble...OK
+FieldGetAndSetAcquireBoolean...OK
+FieldGetAndSetAcquireByte...OK
+FieldGetAndSetAcquireShort...OK
+FieldGetAndSetAcquireChar...OK
+FieldGetAndSetAcquireInt...OK
+FieldGetAndSetAcquireLong...OK
+FieldGetAndSetAcquireFloat...OK
+FieldGetAndSetAcquireDouble...OK
+FieldGetAndSetReleaseBoolean...OK
+FieldGetAndSetReleaseByte...OK
+FieldGetAndSetReleaseShort...OK
+FieldGetAndSetReleaseChar...OK
+FieldGetAndSetReleaseInt...OK
+FieldGetAndSetReleaseLong...OK
+FieldGetAndSetReleaseFloat...OK
+FieldGetAndSetReleaseDouble...OK
+FieldGetAndAddBoolean...OK
+FieldGetAndAddByte...OK
+FieldGetAndAddShort...OK
+FieldGetAndAddChar...OK
+FieldGetAndAddInt...OK
+FieldGetAndAddLong...OK
+FieldGetAndAddFloat...OK
+FieldGetAndAddDouble...OK
+FieldGetAndAddAcquireBoolean...OK
+FieldGetAndAddAcquireByte...OK
+FieldGetAndAddAcquireShort...OK
+FieldGetAndAddAcquireChar...OK
+FieldGetAndAddAcquireInt...OK
+FieldGetAndAddAcquireLong...OK
+FieldGetAndAddAcquireFloat...OK
+FieldGetAndAddAcquireDouble...OK
+FieldGetAndAddReleaseBoolean...OK
+FieldGetAndAddReleaseByte...OK
+FieldGetAndAddReleaseShort...OK
+FieldGetAndAddReleaseChar...OK
+FieldGetAndAddReleaseInt...OK
+FieldGetAndAddReleaseLong...OK
+FieldGetAndAddReleaseFloat...OK
+FieldGetAndAddReleaseDouble...OK
+FieldGetAndBitwiseOrBoolean...OK
+FieldGetAndBitwiseOrByte...OK
+FieldGetAndBitwiseOrShort...OK
+FieldGetAndBitwiseOrChar...OK
+FieldGetAndBitwiseOrInt...OK
+FieldGetAndBitwiseOrLong...OK
+FieldGetAndBitwiseOrFloat...OK
+FieldGetAndBitwiseOrDouble...OK
+FieldGetAndBitwiseOrReleaseBoolean...OK
+FieldGetAndBitwiseOrReleaseByte...OK
+FieldGetAndBitwiseOrReleaseShort...OK
+FieldGetAndBitwiseOrReleaseChar...OK
+FieldGetAndBitwiseOrReleaseInt...OK
+FieldGetAndBitwiseOrReleaseLong...OK
+FieldGetAndBitwiseOrReleaseFloat...OK
+FieldGetAndBitwiseOrReleaseDouble...OK
+FieldGetAndBitwiseOrAcquireBoolean...OK
+FieldGetAndBitwiseOrAcquireByte...OK
+FieldGetAndBitwiseOrAcquireShort...OK
+FieldGetAndBitwiseOrAcquireChar...OK
+FieldGetAndBitwiseOrAcquireInt...OK
+FieldGetAndBitwiseOrAcquireLong...OK
+FieldGetAndBitwiseOrAcquireFloat...OK
+FieldGetAndBitwiseOrAcquireDouble...OK
+FieldGetAndBitwiseAndBoolean...OK
+FieldGetAndBitwiseAndByte...OK
+FieldGetAndBitwiseAndShort...OK
+FieldGetAndBitwiseAndChar...OK
+FieldGetAndBitwiseAndInt...OK
+FieldGetAndBitwiseAndLong...OK
+FieldGetAndBitwiseAndFloat...OK
+FieldGetAndBitwiseAndDouble...OK
+FieldGetAndBitwiseAndReleaseBoolean...OK
+FieldGetAndBitwiseAndReleaseByte...OK
+FieldGetAndBitwiseAndReleaseShort...OK
+FieldGetAndBitwiseAndReleaseChar...OK
+FieldGetAndBitwiseAndReleaseInt...OK
+FieldGetAndBitwiseAndReleaseLong...OK
+FieldGetAndBitwiseAndReleaseFloat...OK
+FieldGetAndBitwiseAndReleaseDouble...OK
+FieldGetAndBitwiseAndAcquireBoolean...OK
+FieldGetAndBitwiseAndAcquireByte...OK
+FieldGetAndBitwiseAndAcquireShort...OK
+FieldGetAndBitwiseAndAcquireChar...OK
+FieldGetAndBitwiseAndAcquireInt...OK
+FieldGetAndBitwiseAndAcquireLong...OK
+FieldGetAndBitwiseAndAcquireFloat...OK
+FieldGetAndBitwiseAndAcquireDouble...OK
+FieldGetAndBitwiseXorBoolean...OK
+FieldGetAndBitwiseXorByte...OK
+FieldGetAndBitwiseXorShort...OK
+FieldGetAndBitwiseXorChar...OK
+FieldGetAndBitwiseXorInt...OK
+FieldGetAndBitwiseXorLong...OK
+FieldGetAndBitwiseXorFloat...OK
+FieldGetAndBitwiseXorDouble...OK
+FieldGetAndBitwiseXorReleaseBoolean...OK
+FieldGetAndBitwiseXorReleaseByte...OK
+FieldGetAndBitwiseXorReleaseShort...OK
+FieldGetAndBitwiseXorReleaseChar...OK
+FieldGetAndBitwiseXorReleaseInt...OK
+FieldGetAndBitwiseXorReleaseLong...OK
+FieldGetAndBitwiseXorReleaseFloat...OK
+FieldGetAndBitwiseXorReleaseDouble...OK
+FieldGetAndBitwiseXorAcquireBoolean...OK
+FieldGetAndBitwiseXorAcquireByte...OK
+FieldGetAndBitwiseXorAcquireShort...OK
+FieldGetAndBitwiseXorAcquireChar...OK
+FieldGetAndBitwiseXorAcquireInt...OK
+FieldGetAndBitwiseXorAcquireLong...OK
+FieldGetAndBitwiseXorAcquireFloat...OK
+FieldGetAndBitwiseXorAcquireDouble...OK
+FinalFieldGetBoolean...OK
+FinalFieldGetByte...OK
+FinalFieldGetShort...OK
+FinalFieldGetChar...OK
+FinalFieldGetInt...OK
+FinalFieldGetLong...OK
+FinalFieldGetFloat...OK
+FinalFieldGetDouble...OK
+FinalFieldSetBoolean...OK
+FinalFieldSetByte...OK
+FinalFieldSetShort...OK
+FinalFieldSetChar...OK
+FinalFieldSetInt...OK
+FinalFieldSetLong...OK
+FinalFieldSetFloat...OK
+FinalFieldSetDouble...OK
+FinalFieldGetVolatileBoolean...OK
+FinalFieldGetVolatileByte...OK
+FinalFieldGetVolatileShort...OK
+FinalFieldGetVolatileChar...OK
+FinalFieldGetVolatileInt...OK
+FinalFieldGetVolatileLong...OK
+FinalFieldGetVolatileFloat...OK
+FinalFieldGetVolatileDouble...OK
+FinalFieldSetVolatileBoolean...OK
+FinalFieldSetVolatileByte...OK
+FinalFieldSetVolatileShort...OK
+FinalFieldSetVolatileChar...OK
+FinalFieldSetVolatileInt...OK
+FinalFieldSetVolatileLong...OK
+FinalFieldSetVolatileFloat...OK
+FinalFieldSetVolatileDouble...OK
+FinalFieldGetAcquireBoolean...OK
+FinalFieldGetAcquireByte...OK
+FinalFieldGetAcquireShort...OK
+FinalFieldGetAcquireChar...OK
+FinalFieldGetAcquireInt...OK
+FinalFieldGetAcquireLong...OK
+FinalFieldGetAcquireFloat...OK
+FinalFieldGetAcquireDouble...OK
+FinalFieldSetReleaseBoolean...OK
+FinalFieldSetReleaseByte...OK
+FinalFieldSetReleaseShort...OK
+FinalFieldSetReleaseChar...OK
+FinalFieldSetReleaseInt...OK
+FinalFieldSetReleaseLong...OK
+FinalFieldSetReleaseFloat...OK
+FinalFieldSetReleaseDouble...OK
+FinalFieldGetOpaqueBoolean...OK
+FinalFieldGetOpaqueByte...OK
+FinalFieldGetOpaqueShort...OK
+FinalFieldGetOpaqueChar...OK
+FinalFieldGetOpaqueInt...OK
+FinalFieldGetOpaqueLong...OK
+FinalFieldGetOpaqueFloat...OK
+FinalFieldGetOpaqueDouble...OK
+FinalFieldSetOpaqueBoolean...OK
+FinalFieldSetOpaqueByte...OK
+FinalFieldSetOpaqueShort...OK
+FinalFieldSetOpaqueChar...OK
+FinalFieldSetOpaqueInt...OK
+FinalFieldSetOpaqueLong...OK
+FinalFieldSetOpaqueFloat...OK
+FinalFieldSetOpaqueDouble...OK
+FinalFieldCompareAndSetBoolean...OK
+FinalFieldCompareAndSetByte...OK
+FinalFieldCompareAndSetShort...OK
+FinalFieldCompareAndSetChar...OK
+FinalFieldCompareAndSetInt...OK
+FinalFieldCompareAndSetLong...OK
+FinalFieldCompareAndSetFloat...OK
+FinalFieldCompareAndSetDouble...OK
+FinalFieldCompareAndExchangeBoolean...OK
+FinalFieldCompareAndExchangeByte...OK
+FinalFieldCompareAndExchangeShort...OK
+FinalFieldCompareAndExchangeChar...OK
+FinalFieldCompareAndExchangeInt...OK
+FinalFieldCompareAndExchangeLong...OK
+FinalFieldCompareAndExchangeFloat...OK
+FinalFieldCompareAndExchangeDouble...OK
+FinalFieldCompareAndExchangeAcquireBoolean...OK
+FinalFieldCompareAndExchangeAcquireByte...OK
+FinalFieldCompareAndExchangeAcquireShort...OK
+FinalFieldCompareAndExchangeAcquireChar...OK
+FinalFieldCompareAndExchangeAcquireInt...OK
+FinalFieldCompareAndExchangeAcquireLong...OK
+FinalFieldCompareAndExchangeAcquireFloat...OK
+FinalFieldCompareAndExchangeAcquireDouble...OK
+FinalFieldCompareAndExchangeReleaseBoolean...OK
+FinalFieldCompareAndExchangeReleaseByte...OK
+FinalFieldCompareAndExchangeReleaseShort...OK
+FinalFieldCompareAndExchangeReleaseChar...OK
+FinalFieldCompareAndExchangeReleaseInt...OK
+FinalFieldCompareAndExchangeReleaseLong...OK
+FinalFieldCompareAndExchangeReleaseFloat...OK
+FinalFieldCompareAndExchangeReleaseDouble...OK
+FinalFieldWeakCompareAndSetPlainBoolean...OK
+FinalFieldWeakCompareAndSetPlainByte...OK
+FinalFieldWeakCompareAndSetPlainShort...OK
+FinalFieldWeakCompareAndSetPlainChar...OK
+FinalFieldWeakCompareAndSetPlainInt...OK
+FinalFieldWeakCompareAndSetPlainLong...OK
+FinalFieldWeakCompareAndSetPlainFloat...OK
+FinalFieldWeakCompareAndSetPlainDouble...OK
+FinalFieldWeakCompareAndSetBoolean...OK
+FinalFieldWeakCompareAndSetByte...OK
+FinalFieldWeakCompareAndSetShort...OK
+FinalFieldWeakCompareAndSetChar...OK
+FinalFieldWeakCompareAndSetInt...OK
+FinalFieldWeakCompareAndSetLong...OK
+FinalFieldWeakCompareAndSetFloat...OK
+FinalFieldWeakCompareAndSetDouble...OK
+FinalFieldWeakCompareAndSetAcquireBoolean...OK
+FinalFieldWeakCompareAndSetAcquireByte...OK
+FinalFieldWeakCompareAndSetAcquireShort...OK
+FinalFieldWeakCompareAndSetAcquireChar...OK
+FinalFieldWeakCompareAndSetAcquireInt...OK
+FinalFieldWeakCompareAndSetAcquireLong...OK
+FinalFieldWeakCompareAndSetAcquireFloat...OK
+FinalFieldWeakCompareAndSetAcquireDouble...OK
+FinalFieldWeakCompareAndSetReleaseBoolean...OK
+FinalFieldWeakCompareAndSetReleaseByte...OK
+FinalFieldWeakCompareAndSetReleaseShort...OK
+FinalFieldWeakCompareAndSetReleaseChar...OK
+FinalFieldWeakCompareAndSetReleaseInt...OK
+FinalFieldWeakCompareAndSetReleaseLong...OK
+FinalFieldWeakCompareAndSetReleaseFloat...OK
+FinalFieldWeakCompareAndSetReleaseDouble...OK
+FinalFieldGetAndSetBoolean...OK
+FinalFieldGetAndSetByte...OK
+FinalFieldGetAndSetShort...OK
+FinalFieldGetAndSetChar...OK
+FinalFieldGetAndSetInt...OK
+FinalFieldGetAndSetLong...OK
+FinalFieldGetAndSetFloat...OK
+FinalFieldGetAndSetDouble...OK
+FinalFieldGetAndSetAcquireBoolean...OK
+FinalFieldGetAndSetAcquireByte...OK
+FinalFieldGetAndSetAcquireShort...OK
+FinalFieldGetAndSetAcquireChar...OK
+FinalFieldGetAndSetAcquireInt...OK
+FinalFieldGetAndSetAcquireLong...OK
+FinalFieldGetAndSetAcquireFloat...OK
+FinalFieldGetAndSetAcquireDouble...OK
+FinalFieldGetAndSetReleaseBoolean...OK
+FinalFieldGetAndSetReleaseByte...OK
+FinalFieldGetAndSetReleaseShort...OK
+FinalFieldGetAndSetReleaseChar...OK
+FinalFieldGetAndSetReleaseInt...OK
+FinalFieldGetAndSetReleaseLong...OK
+FinalFieldGetAndSetReleaseFloat...OK
+FinalFieldGetAndSetReleaseDouble...OK
+FinalFieldGetAndAddBoolean...OK
+FinalFieldGetAndAddByte...OK
+FinalFieldGetAndAddShort...OK
+FinalFieldGetAndAddChar...OK
+FinalFieldGetAndAddInt...OK
+FinalFieldGetAndAddLong...OK
+FinalFieldGetAndAddFloat...OK
+FinalFieldGetAndAddDouble...OK
+FinalFieldGetAndAddAcquireBoolean...OK
+FinalFieldGetAndAddAcquireByte...OK
+FinalFieldGetAndAddAcquireShort...OK
+FinalFieldGetAndAddAcquireChar...OK
+FinalFieldGetAndAddAcquireInt...OK
+FinalFieldGetAndAddAcquireLong...OK
+FinalFieldGetAndAddAcquireFloat...OK
+FinalFieldGetAndAddAcquireDouble...OK
+FinalFieldGetAndAddReleaseBoolean...OK
+FinalFieldGetAndAddReleaseByte...OK
+FinalFieldGetAndAddReleaseShort...OK
+FinalFieldGetAndAddReleaseChar...OK
+FinalFieldGetAndAddReleaseInt...OK
+FinalFieldGetAndAddReleaseLong...OK
+FinalFieldGetAndAddReleaseFloat...OK
+FinalFieldGetAndAddReleaseDouble...OK
+FinalFieldGetAndBitwiseOrBoolean...OK
+FinalFieldGetAndBitwiseOrByte...OK
+FinalFieldGetAndBitwiseOrShort...OK
+FinalFieldGetAndBitwiseOrChar...OK
+FinalFieldGetAndBitwiseOrInt...OK
+FinalFieldGetAndBitwiseOrLong...OK
+FinalFieldGetAndBitwiseOrFloat...OK
+FinalFieldGetAndBitwiseOrDouble...OK
+FinalFieldGetAndBitwiseOrReleaseBoolean...OK
+FinalFieldGetAndBitwiseOrReleaseByte...OK
+FinalFieldGetAndBitwiseOrReleaseShort...OK
+FinalFieldGetAndBitwiseOrReleaseChar...OK
+FinalFieldGetAndBitwiseOrReleaseInt...OK
+FinalFieldGetAndBitwiseOrReleaseLong...OK
+FinalFieldGetAndBitwiseOrReleaseFloat...OK
+FinalFieldGetAndBitwiseOrReleaseDouble...OK
+FinalFieldGetAndBitwiseOrAcquireBoolean...OK
+FinalFieldGetAndBitwiseOrAcquireByte...OK
+FinalFieldGetAndBitwiseOrAcquireShort...OK
+FinalFieldGetAndBitwiseOrAcquireChar...OK
+FinalFieldGetAndBitwiseOrAcquireInt...OK
+FinalFieldGetAndBitwiseOrAcquireLong...OK
+FinalFieldGetAndBitwiseOrAcquireFloat...OK
+FinalFieldGetAndBitwiseOrAcquireDouble...OK
+FinalFieldGetAndBitwiseAndBoolean...OK
+FinalFieldGetAndBitwiseAndByte...OK
+FinalFieldGetAndBitwiseAndShort...OK
+FinalFieldGetAndBitwiseAndChar...OK
+FinalFieldGetAndBitwiseAndInt...OK
+FinalFieldGetAndBitwiseAndLong...OK
+FinalFieldGetAndBitwiseAndFloat...OK
+FinalFieldGetAndBitwiseAndDouble...OK
+FinalFieldGetAndBitwiseAndReleaseBoolean...OK
+FinalFieldGetAndBitwiseAndReleaseByte...OK
+FinalFieldGetAndBitwiseAndReleaseShort...OK
+FinalFieldGetAndBitwiseAndReleaseChar...OK
+FinalFieldGetAndBitwiseAndReleaseInt...OK
+FinalFieldGetAndBitwiseAndReleaseLong...OK
+FinalFieldGetAndBitwiseAndReleaseFloat...OK
+FinalFieldGetAndBitwiseAndReleaseDouble...OK
+FinalFieldGetAndBitwiseAndAcquireBoolean...OK
+FinalFieldGetAndBitwiseAndAcquireByte...OK
+FinalFieldGetAndBitwiseAndAcquireShort...OK
+FinalFieldGetAndBitwiseAndAcquireChar...OK
+FinalFieldGetAndBitwiseAndAcquireInt...OK
+FinalFieldGetAndBitwiseAndAcquireLong...OK
+FinalFieldGetAndBitwiseAndAcquireFloat...OK
+FinalFieldGetAndBitwiseAndAcquireDouble...OK
+FinalFieldGetAndBitwiseXorBoolean...OK
+FinalFieldGetAndBitwiseXorByte...OK
+FinalFieldGetAndBitwiseXorShort...OK
+FinalFieldGetAndBitwiseXorChar...OK
+FinalFieldGetAndBitwiseXorInt...OK
+FinalFieldGetAndBitwiseXorLong...OK
+FinalFieldGetAndBitwiseXorFloat...OK
+FinalFieldGetAndBitwiseXorDouble...OK
+FinalFieldGetAndBitwiseXorReleaseBoolean...OK
+FinalFieldGetAndBitwiseXorReleaseByte...OK
+FinalFieldGetAndBitwiseXorReleaseShort...OK
+FinalFieldGetAndBitwiseXorReleaseChar...OK
+FinalFieldGetAndBitwiseXorReleaseInt...OK
+FinalFieldGetAndBitwiseXorReleaseLong...OK
+FinalFieldGetAndBitwiseXorReleaseFloat...OK
+FinalFieldGetAndBitwiseXorReleaseDouble...OK
+FinalFieldGetAndBitwiseXorAcquireBoolean...OK
+FinalFieldGetAndBitwiseXorAcquireByte...OK
+FinalFieldGetAndBitwiseXorAcquireShort...OK
+FinalFieldGetAndBitwiseXorAcquireChar...OK
+FinalFieldGetAndBitwiseXorAcquireInt...OK
+FinalFieldGetAndBitwiseXorAcquireLong...OK
+FinalFieldGetAndBitwiseXorAcquireFloat...OK
+FinalFieldGetAndBitwiseXorAcquireDouble...OK
+StaticFieldGetBoolean...OK
+StaticFieldGetByte...OK
+StaticFieldGetShort...OK
+StaticFieldGetChar...OK
+StaticFieldGetInt...OK
+StaticFieldGetLong...OK
+StaticFieldGetFloat...OK
+StaticFieldGetDouble...OK
+StaticFieldSetBoolean...OK
+StaticFieldSetByte...OK
+StaticFieldSetShort...OK
+StaticFieldSetChar...OK
+StaticFieldSetInt...OK
+StaticFieldSetLong...OK
+StaticFieldSetFloat...OK
+StaticFieldSetDouble...OK
+StaticFieldGetVolatileBoolean...OK
+StaticFieldGetVolatileByte...OK
+StaticFieldGetVolatileShort...OK
+StaticFieldGetVolatileChar...OK
+StaticFieldGetVolatileInt...OK
+StaticFieldGetVolatileLong...OK
+StaticFieldGetVolatileFloat...OK
+StaticFieldGetVolatileDouble...OK
+StaticFieldSetVolatileBoolean...OK
+StaticFieldSetVolatileByte...OK
+StaticFieldSetVolatileShort...OK
+StaticFieldSetVolatileChar...OK
+StaticFieldSetVolatileInt...OK
+StaticFieldSetVolatileLong...OK
+StaticFieldSetVolatileFloat...OK
+StaticFieldSetVolatileDouble...OK
+StaticFieldGetAcquireBoolean...OK
+StaticFieldGetAcquireByte...OK
+StaticFieldGetAcquireShort...OK
+StaticFieldGetAcquireChar...OK
+StaticFieldGetAcquireInt...OK
+StaticFieldGetAcquireLong...OK
+StaticFieldGetAcquireFloat...OK
+StaticFieldGetAcquireDouble...OK
+StaticFieldSetReleaseBoolean...OK
+StaticFieldSetReleaseByte...OK
+StaticFieldSetReleaseShort...OK
+StaticFieldSetReleaseChar...OK
+StaticFieldSetReleaseInt...OK
+StaticFieldSetReleaseLong...OK
+StaticFieldSetReleaseFloat...OK
+StaticFieldSetReleaseDouble...OK
+StaticFieldGetOpaqueBoolean...OK
+StaticFieldGetOpaqueByte...OK
+StaticFieldGetOpaqueShort...OK
+StaticFieldGetOpaqueChar...OK
+StaticFieldGetOpaqueInt...OK
+StaticFieldGetOpaqueLong...OK
+StaticFieldGetOpaqueFloat...OK
+StaticFieldGetOpaqueDouble...OK
+StaticFieldSetOpaqueBoolean...OK
+StaticFieldSetOpaqueByte...OK
+StaticFieldSetOpaqueShort...OK
+StaticFieldSetOpaqueChar...OK
+StaticFieldSetOpaqueInt...OK
+StaticFieldSetOpaqueLong...OK
+StaticFieldSetOpaqueFloat...OK
+StaticFieldSetOpaqueDouble...OK
+StaticFieldCompareAndSetBoolean...OK
+StaticFieldCompareAndSetByte...OK
+StaticFieldCompareAndSetShort...OK
+StaticFieldCompareAndSetChar...OK
+StaticFieldCompareAndSetInt...OK
+StaticFieldCompareAndSetLong...OK
+StaticFieldCompareAndSetFloat...OK
+StaticFieldCompareAndSetDouble...OK
+StaticFieldCompareAndExchangeBoolean...OK
+StaticFieldCompareAndExchangeByte...OK
+StaticFieldCompareAndExchangeShort...OK
+StaticFieldCompareAndExchangeChar...OK
+StaticFieldCompareAndExchangeInt...OK
+StaticFieldCompareAndExchangeLong...OK
+StaticFieldCompareAndExchangeFloat...OK
+StaticFieldCompareAndExchangeDouble...OK
+StaticFieldCompareAndExchangeAcquireBoolean...OK
+StaticFieldCompareAndExchangeAcquireByte...OK
+StaticFieldCompareAndExchangeAcquireShort...OK
+StaticFieldCompareAndExchangeAcquireChar...OK
+StaticFieldCompareAndExchangeAcquireInt...OK
+StaticFieldCompareAndExchangeAcquireLong...OK
+StaticFieldCompareAndExchangeAcquireFloat...OK
+StaticFieldCompareAndExchangeAcquireDouble...OK
+StaticFieldCompareAndExchangeReleaseBoolean...OK
+StaticFieldCompareAndExchangeReleaseByte...OK
+StaticFieldCompareAndExchangeReleaseShort...OK
+StaticFieldCompareAndExchangeReleaseChar...OK
+StaticFieldCompareAndExchangeReleaseInt...OK
+StaticFieldCompareAndExchangeReleaseLong...OK
+StaticFieldCompareAndExchangeReleaseFloat...OK
+StaticFieldCompareAndExchangeReleaseDouble...OK
+StaticFieldWeakCompareAndSetPlainBoolean...OK
+StaticFieldWeakCompareAndSetPlainByte...OK
+StaticFieldWeakCompareAndSetPlainShort...OK
+StaticFieldWeakCompareAndSetPlainChar...OK
+StaticFieldWeakCompareAndSetPlainInt...OK
+StaticFieldWeakCompareAndSetPlainLong...OK
+StaticFieldWeakCompareAndSetPlainFloat...OK
+StaticFieldWeakCompareAndSetPlainDouble...OK
+StaticFieldWeakCompareAndSetBoolean...OK
+StaticFieldWeakCompareAndSetByte...OK
+StaticFieldWeakCompareAndSetShort...OK
+StaticFieldWeakCompareAndSetChar...OK
+StaticFieldWeakCompareAndSetInt...OK
+StaticFieldWeakCompareAndSetLong...OK
+StaticFieldWeakCompareAndSetFloat...OK
+StaticFieldWeakCompareAndSetDouble...OK
+StaticFieldWeakCompareAndSetAcquireBoolean...OK
+StaticFieldWeakCompareAndSetAcquireByte...OK
+StaticFieldWeakCompareAndSetAcquireShort...OK
+StaticFieldWeakCompareAndSetAcquireChar...OK
+StaticFieldWeakCompareAndSetAcquireInt...OK
+StaticFieldWeakCompareAndSetAcquireLong...OK
+StaticFieldWeakCompareAndSetAcquireFloat...OK
+StaticFieldWeakCompareAndSetAcquireDouble...OK
+StaticFieldWeakCompareAndSetReleaseBoolean...OK
+StaticFieldWeakCompareAndSetReleaseByte...OK
+StaticFieldWeakCompareAndSetReleaseShort...OK
+StaticFieldWeakCompareAndSetReleaseChar...OK
+StaticFieldWeakCompareAndSetReleaseInt...OK
+StaticFieldWeakCompareAndSetReleaseLong...OK
+StaticFieldWeakCompareAndSetReleaseFloat...OK
+StaticFieldWeakCompareAndSetReleaseDouble...OK
+StaticFieldGetAndSetBoolean...OK
+StaticFieldGetAndSetByte...OK
+StaticFieldGetAndSetShort...OK
+StaticFieldGetAndSetChar...OK
+StaticFieldGetAndSetInt...OK
+StaticFieldGetAndSetLong...OK
+StaticFieldGetAndSetFloat...OK
+StaticFieldGetAndSetDouble...OK
+StaticFieldGetAndSetAcquireBoolean...OK
+StaticFieldGetAndSetAcquireByte...OK
+StaticFieldGetAndSetAcquireShort...OK
+StaticFieldGetAndSetAcquireChar...OK
+StaticFieldGetAndSetAcquireInt...OK
+StaticFieldGetAndSetAcquireLong...OK
+StaticFieldGetAndSetAcquireFloat...OK
+StaticFieldGetAndSetAcquireDouble...OK
+StaticFieldGetAndSetReleaseBoolean...OK
+StaticFieldGetAndSetReleaseByte...OK
+StaticFieldGetAndSetReleaseShort...OK
+StaticFieldGetAndSetReleaseChar...OK
+StaticFieldGetAndSetReleaseInt...OK
+StaticFieldGetAndSetReleaseLong...OK
+StaticFieldGetAndSetReleaseFloat...OK
+StaticFieldGetAndSetReleaseDouble...OK
+StaticFieldGetAndAddBoolean...OK
+StaticFieldGetAndAddByte...OK
+StaticFieldGetAndAddShort...OK
+StaticFieldGetAndAddChar...OK
+StaticFieldGetAndAddInt...OK
+StaticFieldGetAndAddLong...OK
+StaticFieldGetAndAddFloat...OK
+StaticFieldGetAndAddDouble...OK
+StaticFieldGetAndAddAcquireBoolean...OK
+StaticFieldGetAndAddAcquireByte...OK
+StaticFieldGetAndAddAcquireShort...OK
+StaticFieldGetAndAddAcquireChar...OK
+StaticFieldGetAndAddAcquireInt...OK
+StaticFieldGetAndAddAcquireLong...OK
+StaticFieldGetAndAddAcquireFloat...OK
+StaticFieldGetAndAddAcquireDouble...OK
+StaticFieldGetAndAddReleaseBoolean...OK
+StaticFieldGetAndAddReleaseByte...OK
+StaticFieldGetAndAddReleaseShort...OK
+StaticFieldGetAndAddReleaseChar...OK
+StaticFieldGetAndAddReleaseInt...OK
+StaticFieldGetAndAddReleaseLong...OK
+StaticFieldGetAndAddReleaseFloat...OK
+StaticFieldGetAndAddReleaseDouble...OK
+StaticFieldGetAndBitwiseOrBoolean...OK
+StaticFieldGetAndBitwiseOrByte...OK
+StaticFieldGetAndBitwiseOrShort...OK
+StaticFieldGetAndBitwiseOrChar...OK
+StaticFieldGetAndBitwiseOrInt...OK
+StaticFieldGetAndBitwiseOrLong...OK
+StaticFieldGetAndBitwiseOrFloat...OK
+StaticFieldGetAndBitwiseOrDouble...OK
+StaticFieldGetAndBitwiseOrReleaseBoolean...OK
+StaticFieldGetAndBitwiseOrReleaseByte...OK
+StaticFieldGetAndBitwiseOrReleaseShort...OK
+StaticFieldGetAndBitwiseOrReleaseChar...OK
+StaticFieldGetAndBitwiseOrReleaseInt...OK
+StaticFieldGetAndBitwiseOrReleaseLong...OK
+StaticFieldGetAndBitwiseOrReleaseFloat...OK
+StaticFieldGetAndBitwiseOrReleaseDouble...OK
+StaticFieldGetAndBitwiseOrAcquireBoolean...OK
+StaticFieldGetAndBitwiseOrAcquireByte...OK
+StaticFieldGetAndBitwiseOrAcquireShort...OK
+StaticFieldGetAndBitwiseOrAcquireChar...OK
+StaticFieldGetAndBitwiseOrAcquireInt...OK
+StaticFieldGetAndBitwiseOrAcquireLong...OK
+StaticFieldGetAndBitwiseOrAcquireFloat...OK
+StaticFieldGetAndBitwiseOrAcquireDouble...OK
+StaticFieldGetAndBitwiseAndBoolean...OK
+StaticFieldGetAndBitwiseAndByte...OK
+StaticFieldGetAndBitwiseAndShort...OK
+StaticFieldGetAndBitwiseAndChar...OK
+StaticFieldGetAndBitwiseAndInt...OK
+StaticFieldGetAndBitwiseAndLong...OK
+StaticFieldGetAndBitwiseAndFloat...OK
+StaticFieldGetAndBitwiseAndDouble...OK
+StaticFieldGetAndBitwiseAndReleaseBoolean...OK
+StaticFieldGetAndBitwiseAndReleaseByte...OK
+StaticFieldGetAndBitwiseAndReleaseShort...OK
+StaticFieldGetAndBitwiseAndReleaseChar...OK
+StaticFieldGetAndBitwiseAndReleaseInt...OK
+StaticFieldGetAndBitwiseAndReleaseLong...OK
+StaticFieldGetAndBitwiseAndReleaseFloat...OK
+StaticFieldGetAndBitwiseAndReleaseDouble...OK
+StaticFieldGetAndBitwiseAndAcquireBoolean...OK
+StaticFieldGetAndBitwiseAndAcquireByte...OK
+StaticFieldGetAndBitwiseAndAcquireShort...OK
+StaticFieldGetAndBitwiseAndAcquireChar...OK
+StaticFieldGetAndBitwiseAndAcquireInt...OK
+StaticFieldGetAndBitwiseAndAcquireLong...OK
+StaticFieldGetAndBitwiseAndAcquireFloat...OK
+StaticFieldGetAndBitwiseAndAcquireDouble...OK
+StaticFieldGetAndBitwiseXorBoolean...OK
+StaticFieldGetAndBitwiseXorByte...OK
+StaticFieldGetAndBitwiseXorShort...OK
+StaticFieldGetAndBitwiseXorChar...OK
+StaticFieldGetAndBitwiseXorInt...OK
+StaticFieldGetAndBitwiseXorLong...OK
+StaticFieldGetAndBitwiseXorFloat...OK
+StaticFieldGetAndBitwiseXorDouble...OK
+StaticFieldGetAndBitwiseXorReleaseBoolean...OK
+StaticFieldGetAndBitwiseXorReleaseByte...OK
+StaticFieldGetAndBitwiseXorReleaseShort...OK
+StaticFieldGetAndBitwiseXorReleaseChar...OK
+StaticFieldGetAndBitwiseXorReleaseInt...OK
+StaticFieldGetAndBitwiseXorReleaseLong...OK
+StaticFieldGetAndBitwiseXorReleaseFloat...OK
+StaticFieldGetAndBitwiseXorReleaseDouble...OK
+StaticFieldGetAndBitwiseXorAcquireBoolean...OK
+StaticFieldGetAndBitwiseXorAcquireByte...OK
+StaticFieldGetAndBitwiseXorAcquireShort...OK
+StaticFieldGetAndBitwiseXorAcquireChar...OK
+StaticFieldGetAndBitwiseXorAcquireInt...OK
+StaticFieldGetAndBitwiseXorAcquireLong...OK
+StaticFieldGetAndBitwiseXorAcquireFloat...OK
+StaticFieldGetAndBitwiseXorAcquireDouble...OK
+StaticFinalFieldGetBoolean...OK
+StaticFinalFieldGetByte...OK
+StaticFinalFieldGetShort...OK
+StaticFinalFieldGetChar...OK
+StaticFinalFieldGetInt...OK
+StaticFinalFieldGetLong...OK
+StaticFinalFieldGetFloat...OK
+StaticFinalFieldGetDouble...OK
+StaticFinalFieldSetBoolean...OK
+StaticFinalFieldSetByte...OK
+StaticFinalFieldSetShort...OK
+StaticFinalFieldSetChar...OK
+StaticFinalFieldSetInt...OK
+StaticFinalFieldSetLong...OK
+StaticFinalFieldSetFloat...OK
+StaticFinalFieldSetDouble...OK
+StaticFinalFieldGetVolatileBoolean...OK
+StaticFinalFieldGetVolatileByte...OK
+StaticFinalFieldGetVolatileShort...OK
+StaticFinalFieldGetVolatileChar...OK
+StaticFinalFieldGetVolatileInt...OK
+StaticFinalFieldGetVolatileLong...OK
+StaticFinalFieldGetVolatileFloat...OK
+StaticFinalFieldGetVolatileDouble...OK
+StaticFinalFieldSetVolatileBoolean...OK
+StaticFinalFieldSetVolatileByte...OK
+StaticFinalFieldSetVolatileShort...OK
+StaticFinalFieldSetVolatileChar...OK
+StaticFinalFieldSetVolatileInt...OK
+StaticFinalFieldSetVolatileLong...OK
+StaticFinalFieldSetVolatileFloat...OK
+StaticFinalFieldSetVolatileDouble...OK
+StaticFinalFieldGetAcquireBoolean...OK
+StaticFinalFieldGetAcquireByte...OK
+StaticFinalFieldGetAcquireShort...OK
+StaticFinalFieldGetAcquireChar...OK
+StaticFinalFieldGetAcquireInt...OK
+StaticFinalFieldGetAcquireLong...OK
+StaticFinalFieldGetAcquireFloat...OK
+StaticFinalFieldGetAcquireDouble...OK
+StaticFinalFieldSetReleaseBoolean...OK
+StaticFinalFieldSetReleaseByte...OK
+StaticFinalFieldSetReleaseShort...OK
+StaticFinalFieldSetReleaseChar...OK
+StaticFinalFieldSetReleaseInt...OK
+StaticFinalFieldSetReleaseLong...OK
+StaticFinalFieldSetReleaseFloat...OK
+StaticFinalFieldSetReleaseDouble...OK
+StaticFinalFieldGetOpaqueBoolean...OK
+StaticFinalFieldGetOpaqueByte...OK
+StaticFinalFieldGetOpaqueShort...OK
+StaticFinalFieldGetOpaqueChar...OK
+StaticFinalFieldGetOpaqueInt...OK
+StaticFinalFieldGetOpaqueLong...OK
+StaticFinalFieldGetOpaqueFloat...OK
+StaticFinalFieldGetOpaqueDouble...OK
+StaticFinalFieldSetOpaqueBoolean...OK
+StaticFinalFieldSetOpaqueByte...OK
+StaticFinalFieldSetOpaqueShort...OK
+StaticFinalFieldSetOpaqueChar...OK
+StaticFinalFieldSetOpaqueInt...OK
+StaticFinalFieldSetOpaqueLong...OK
+StaticFinalFieldSetOpaqueFloat...OK
+StaticFinalFieldSetOpaqueDouble...OK
+StaticFinalFieldCompareAndSetBoolean...OK
+StaticFinalFieldCompareAndSetByte...OK
+StaticFinalFieldCompareAndSetShort...OK
+StaticFinalFieldCompareAndSetChar...OK
+StaticFinalFieldCompareAndSetInt...OK
+StaticFinalFieldCompareAndSetLong...OK
+StaticFinalFieldCompareAndSetFloat...OK
+StaticFinalFieldCompareAndSetDouble...OK
+StaticFinalFieldCompareAndExchangeBoolean...OK
+StaticFinalFieldCompareAndExchangeByte...OK
+StaticFinalFieldCompareAndExchangeShort...OK
+StaticFinalFieldCompareAndExchangeChar...OK
+StaticFinalFieldCompareAndExchangeInt...OK
+StaticFinalFieldCompareAndExchangeLong...OK
+StaticFinalFieldCompareAndExchangeFloat...OK
+StaticFinalFieldCompareAndExchangeDouble...OK
+StaticFinalFieldCompareAndExchangeAcquireBoolean...OK
+StaticFinalFieldCompareAndExchangeAcquireByte...OK
+StaticFinalFieldCompareAndExchangeAcquireShort...OK
+StaticFinalFieldCompareAndExchangeAcquireChar...OK
+StaticFinalFieldCompareAndExchangeAcquireInt...OK
+StaticFinalFieldCompareAndExchangeAcquireLong...OK
+StaticFinalFieldCompareAndExchangeAcquireFloat...OK
+StaticFinalFieldCompareAndExchangeAcquireDouble...OK
+StaticFinalFieldCompareAndExchangeReleaseBoolean...OK
+StaticFinalFieldCompareAndExchangeReleaseByte...OK
+StaticFinalFieldCompareAndExchangeReleaseShort...OK
+StaticFinalFieldCompareAndExchangeReleaseChar...OK
+StaticFinalFieldCompareAndExchangeReleaseInt...OK
+StaticFinalFieldCompareAndExchangeReleaseLong...OK
+StaticFinalFieldCompareAndExchangeReleaseFloat...OK
+StaticFinalFieldCompareAndExchangeReleaseDouble...OK
+StaticFinalFieldWeakCompareAndSetPlainBoolean...OK
+StaticFinalFieldWeakCompareAndSetPlainByte...OK
+StaticFinalFieldWeakCompareAndSetPlainShort...OK
+StaticFinalFieldWeakCompareAndSetPlainChar...OK
+StaticFinalFieldWeakCompareAndSetPlainInt...OK
+StaticFinalFieldWeakCompareAndSetPlainLong...OK
+StaticFinalFieldWeakCompareAndSetPlainFloat...OK
+StaticFinalFieldWeakCompareAndSetPlainDouble...OK
+StaticFinalFieldWeakCompareAndSetBoolean...OK
+StaticFinalFieldWeakCompareAndSetByte...OK
+StaticFinalFieldWeakCompareAndSetShort...OK
+StaticFinalFieldWeakCompareAndSetChar...OK
+StaticFinalFieldWeakCompareAndSetInt...OK
+StaticFinalFieldWeakCompareAndSetLong...OK
+StaticFinalFieldWeakCompareAndSetFloat...OK
+StaticFinalFieldWeakCompareAndSetDouble...OK
+StaticFinalFieldWeakCompareAndSetAcquireBoolean...OK
+StaticFinalFieldWeakCompareAndSetAcquireByte...OK
+StaticFinalFieldWeakCompareAndSetAcquireShort...OK
+StaticFinalFieldWeakCompareAndSetAcquireChar...OK
+StaticFinalFieldWeakCompareAndSetAcquireInt...OK
+StaticFinalFieldWeakCompareAndSetAcquireLong...OK
+StaticFinalFieldWeakCompareAndSetAcquireFloat...OK
+StaticFinalFieldWeakCompareAndSetAcquireDouble...OK
+StaticFinalFieldWeakCompareAndSetReleaseBoolean...OK
+StaticFinalFieldWeakCompareAndSetReleaseByte...OK
+StaticFinalFieldWeakCompareAndSetReleaseShort...OK
+StaticFinalFieldWeakCompareAndSetReleaseChar...OK
+StaticFinalFieldWeakCompareAndSetReleaseInt...OK
+StaticFinalFieldWeakCompareAndSetReleaseLong...OK
+StaticFinalFieldWeakCompareAndSetReleaseFloat...OK
+StaticFinalFieldWeakCompareAndSetReleaseDouble...OK
+StaticFinalFieldGetAndSetBoolean...OK
+StaticFinalFieldGetAndSetByte...OK
+StaticFinalFieldGetAndSetShort...OK
+StaticFinalFieldGetAndSetChar...OK
+StaticFinalFieldGetAndSetInt...OK
+StaticFinalFieldGetAndSetLong...OK
+StaticFinalFieldGetAndSetFloat...OK
+StaticFinalFieldGetAndSetDouble...OK
+StaticFinalFieldGetAndSetAcquireBoolean...OK
+StaticFinalFieldGetAndSetAcquireByte...OK
+StaticFinalFieldGetAndSetAcquireShort...OK
+StaticFinalFieldGetAndSetAcquireChar...OK
+StaticFinalFieldGetAndSetAcquireInt...OK
+StaticFinalFieldGetAndSetAcquireLong...OK
+StaticFinalFieldGetAndSetAcquireFloat...OK
+StaticFinalFieldGetAndSetAcquireDouble...OK
+StaticFinalFieldGetAndSetReleaseBoolean...OK
+StaticFinalFieldGetAndSetReleaseByte...OK
+StaticFinalFieldGetAndSetReleaseShort...OK
+StaticFinalFieldGetAndSetReleaseChar...OK
+StaticFinalFieldGetAndSetReleaseInt...OK
+StaticFinalFieldGetAndSetReleaseLong...OK
+StaticFinalFieldGetAndSetReleaseFloat...OK
+StaticFinalFieldGetAndSetReleaseDouble...OK
+StaticFinalFieldGetAndAddBoolean...OK
+StaticFinalFieldGetAndAddByte...OK
+StaticFinalFieldGetAndAddShort...OK
+StaticFinalFieldGetAndAddChar...OK
+StaticFinalFieldGetAndAddInt...OK
+StaticFinalFieldGetAndAddLong...OK
+StaticFinalFieldGetAndAddFloat...OK
+StaticFinalFieldGetAndAddDouble...OK
+StaticFinalFieldGetAndAddAcquireBoolean...OK
+StaticFinalFieldGetAndAddAcquireByte...OK
+StaticFinalFieldGetAndAddAcquireShort...OK
+StaticFinalFieldGetAndAddAcquireChar...OK
+StaticFinalFieldGetAndAddAcquireInt...OK
+StaticFinalFieldGetAndAddAcquireLong...OK
+StaticFinalFieldGetAndAddAcquireFloat...OK
+StaticFinalFieldGetAndAddAcquireDouble...OK
+StaticFinalFieldGetAndAddReleaseBoolean...OK
+StaticFinalFieldGetAndAddReleaseByte...OK
+StaticFinalFieldGetAndAddReleaseShort...OK
+StaticFinalFieldGetAndAddReleaseChar...OK
+StaticFinalFieldGetAndAddReleaseInt...OK
+StaticFinalFieldGetAndAddReleaseLong...OK
+StaticFinalFieldGetAndAddReleaseFloat...OK
+StaticFinalFieldGetAndAddReleaseDouble...OK
+StaticFinalFieldGetAndBitwiseOrBoolean...OK
+StaticFinalFieldGetAndBitwiseOrByte...OK
+StaticFinalFieldGetAndBitwiseOrShort...OK
+StaticFinalFieldGetAndBitwiseOrChar...OK
+StaticFinalFieldGetAndBitwiseOrInt...OK
+StaticFinalFieldGetAndBitwiseOrLong...OK
+StaticFinalFieldGetAndBitwiseOrFloat...OK
+StaticFinalFieldGetAndBitwiseOrDouble...OK
+StaticFinalFieldGetAndBitwiseOrReleaseBoolean...OK
+StaticFinalFieldGetAndBitwiseOrReleaseByte...OK
+StaticFinalFieldGetAndBitwiseOrReleaseShort...OK
+StaticFinalFieldGetAndBitwiseOrReleaseChar...OK
+StaticFinalFieldGetAndBitwiseOrReleaseInt...OK
+StaticFinalFieldGetAndBitwiseOrReleaseLong...OK
+StaticFinalFieldGetAndBitwiseOrReleaseFloat...OK
+StaticFinalFieldGetAndBitwiseOrReleaseDouble...OK
+StaticFinalFieldGetAndBitwiseOrAcquireBoolean...OK
+StaticFinalFieldGetAndBitwiseOrAcquireByte...OK
+StaticFinalFieldGetAndBitwiseOrAcquireShort...OK
+StaticFinalFieldGetAndBitwiseOrAcquireChar...OK
+StaticFinalFieldGetAndBitwiseOrAcquireInt...OK
+StaticFinalFieldGetAndBitwiseOrAcquireLong...OK
+StaticFinalFieldGetAndBitwiseOrAcquireFloat...OK
+StaticFinalFieldGetAndBitwiseOrAcquireDouble...OK
+StaticFinalFieldGetAndBitwiseAndBoolean...OK
+StaticFinalFieldGetAndBitwiseAndByte...OK
+StaticFinalFieldGetAndBitwiseAndShort...OK
+StaticFinalFieldGetAndBitwiseAndChar...OK
+StaticFinalFieldGetAndBitwiseAndInt...OK
+StaticFinalFieldGetAndBitwiseAndLong...OK
+StaticFinalFieldGetAndBitwiseAndFloat...OK
+StaticFinalFieldGetAndBitwiseAndDouble...OK
+StaticFinalFieldGetAndBitwiseAndReleaseBoolean...OK
+StaticFinalFieldGetAndBitwiseAndReleaseByte...OK
+StaticFinalFieldGetAndBitwiseAndReleaseShort...OK
+StaticFinalFieldGetAndBitwiseAndReleaseChar...OK
+StaticFinalFieldGetAndBitwiseAndReleaseInt...OK
+StaticFinalFieldGetAndBitwiseAndReleaseLong...OK
+StaticFinalFieldGetAndBitwiseAndReleaseFloat...OK
+StaticFinalFieldGetAndBitwiseAndReleaseDouble...OK
+StaticFinalFieldGetAndBitwiseAndAcquireBoolean...OK
+StaticFinalFieldGetAndBitwiseAndAcquireByte...OK
+StaticFinalFieldGetAndBitwiseAndAcquireShort...OK
+StaticFinalFieldGetAndBitwiseAndAcquireChar...OK
+StaticFinalFieldGetAndBitwiseAndAcquireInt...OK
+StaticFinalFieldGetAndBitwiseAndAcquireLong...OK
+StaticFinalFieldGetAndBitwiseAndAcquireFloat...OK
+StaticFinalFieldGetAndBitwiseAndAcquireDouble...OK
+StaticFinalFieldGetAndBitwiseXorBoolean...OK
+StaticFinalFieldGetAndBitwiseXorByte...OK
+StaticFinalFieldGetAndBitwiseXorShort...OK
+StaticFinalFieldGetAndBitwiseXorChar...OK
+StaticFinalFieldGetAndBitwiseXorInt...OK
+StaticFinalFieldGetAndBitwiseXorLong...OK
+StaticFinalFieldGetAndBitwiseXorFloat...OK
+StaticFinalFieldGetAndBitwiseXorDouble...OK
+StaticFinalFieldGetAndBitwiseXorReleaseBoolean...OK
+StaticFinalFieldGetAndBitwiseXorReleaseByte...OK
+StaticFinalFieldGetAndBitwiseXorReleaseShort...OK
+StaticFinalFieldGetAndBitwiseXorReleaseChar...OK
+StaticFinalFieldGetAndBitwiseXorReleaseInt...OK
+StaticFinalFieldGetAndBitwiseXorReleaseLong...OK
+StaticFinalFieldGetAndBitwiseXorReleaseFloat...OK
+StaticFinalFieldGetAndBitwiseXorReleaseDouble...OK
+StaticFinalFieldGetAndBitwiseXorAcquireBoolean...OK
+StaticFinalFieldGetAndBitwiseXorAcquireByte...OK
+StaticFinalFieldGetAndBitwiseXorAcquireShort...OK
+StaticFinalFieldGetAndBitwiseXorAcquireChar...OK
+StaticFinalFieldGetAndBitwiseXorAcquireInt...OK
+StaticFinalFieldGetAndBitwiseXorAcquireLong...OK
+StaticFinalFieldGetAndBitwiseXorAcquireFloat...OK
+StaticFinalFieldGetAndBitwiseXorAcquireDouble...OK
+ArrayElementGetBoolean...OK
+ArrayElementGetByte...OK
+ArrayElementGetShort...OK
+ArrayElementGetChar...OK
+ArrayElementGetInt...OK
+ArrayElementGetLong...OK
+ArrayElementGetFloat...OK
+ArrayElementGetDouble...OK
+ArrayElementSetBoolean...OK
+ArrayElementSetByte...OK
+ArrayElementSetShort...OK
+ArrayElementSetChar...OK
+ArrayElementSetInt...OK
+ArrayElementSetLong...OK
+ArrayElementSetFloat...OK
+ArrayElementSetDouble...OK
+ArrayElementGetVolatileBoolean...OK
+ArrayElementGetVolatileByte...OK
+ArrayElementGetVolatileShort...OK
+ArrayElementGetVolatileChar...OK
+ArrayElementGetVolatileInt...OK
+ArrayElementGetVolatileLong...OK
+ArrayElementGetVolatileFloat...OK
+ArrayElementGetVolatileDouble...OK
+ArrayElementSetVolatileBoolean...OK
+ArrayElementSetVolatileByte...OK
+ArrayElementSetVolatileShort...OK
+ArrayElementSetVolatileChar...OK
+ArrayElementSetVolatileInt...OK
+ArrayElementSetVolatileLong...OK
+ArrayElementSetVolatileFloat...OK
+ArrayElementSetVolatileDouble...OK
+ArrayElementGetAcquireBoolean...OK
+ArrayElementGetAcquireByte...OK
+ArrayElementGetAcquireShort...OK
+ArrayElementGetAcquireChar...OK
+ArrayElementGetAcquireInt...OK
+ArrayElementGetAcquireLong...OK
+ArrayElementGetAcquireFloat...OK
+ArrayElementGetAcquireDouble...OK
+ArrayElementSetReleaseBoolean...OK
+ArrayElementSetReleaseByte...OK
+ArrayElementSetReleaseShort...OK
+ArrayElementSetReleaseChar...OK
+ArrayElementSetReleaseInt...OK
+ArrayElementSetReleaseLong...OK
+ArrayElementSetReleaseFloat...OK
+ArrayElementSetReleaseDouble...OK
+ArrayElementGetOpaqueBoolean...OK
+ArrayElementGetOpaqueByte...OK
+ArrayElementGetOpaqueShort...OK
+ArrayElementGetOpaqueChar...OK
+ArrayElementGetOpaqueInt...OK
+ArrayElementGetOpaqueLong...OK
+ArrayElementGetOpaqueFloat...OK
+ArrayElementGetOpaqueDouble...OK
+ArrayElementSetOpaqueBoolean...OK
+ArrayElementSetOpaqueByte...OK
+ArrayElementSetOpaqueShort...OK
+ArrayElementSetOpaqueChar...OK
+ArrayElementSetOpaqueInt...OK
+ArrayElementSetOpaqueLong...OK
+ArrayElementSetOpaqueFloat...OK
+ArrayElementSetOpaqueDouble...OK
+ArrayElementCompareAndSetBoolean...OK
+ArrayElementCompareAndSetByte...OK
+ArrayElementCompareAndSetShort...OK
+ArrayElementCompareAndSetChar...OK
+ArrayElementCompareAndSetInt...OK
+ArrayElementCompareAndSetLong...OK
+ArrayElementCompareAndSetFloat...OK
+ArrayElementCompareAndSetDouble...OK
+ArrayElementCompareAndExchangeBoolean...OK
+ArrayElementCompareAndExchangeByte...OK
+ArrayElementCompareAndExchangeShort...OK
+ArrayElementCompareAndExchangeChar...OK
+ArrayElementCompareAndExchangeInt...OK
+ArrayElementCompareAndExchangeLong...OK
+ArrayElementCompareAndExchangeFloat...OK
+ArrayElementCompareAndExchangeDouble...OK
+ArrayElementCompareAndExchangeAcquireBoolean...OK
+ArrayElementCompareAndExchangeAcquireByte...OK
+ArrayElementCompareAndExchangeAcquireShort...OK
+ArrayElementCompareAndExchangeAcquireChar...OK
+ArrayElementCompareAndExchangeAcquireInt...OK
+ArrayElementCompareAndExchangeAcquireLong...OK
+ArrayElementCompareAndExchangeAcquireFloat...OK
+ArrayElementCompareAndExchangeAcquireDouble...OK
+ArrayElementCompareAndExchangeReleaseBoolean...OK
+ArrayElementCompareAndExchangeReleaseByte...OK
+ArrayElementCompareAndExchangeReleaseShort...OK
+ArrayElementCompareAndExchangeReleaseChar...OK
+ArrayElementCompareAndExchangeReleaseInt...OK
+ArrayElementCompareAndExchangeReleaseLong...OK
+ArrayElementCompareAndExchangeReleaseFloat...OK
+ArrayElementCompareAndExchangeReleaseDouble...OK
+ArrayElementWeakCompareAndSetPlainBoolean...OK
+ArrayElementWeakCompareAndSetPlainByte...OK
+ArrayElementWeakCompareAndSetPlainShort...OK
+ArrayElementWeakCompareAndSetPlainChar...OK
+ArrayElementWeakCompareAndSetPlainInt...OK
+ArrayElementWeakCompareAndSetPlainLong...OK
+ArrayElementWeakCompareAndSetPlainFloat...OK
+ArrayElementWeakCompareAndSetPlainDouble...OK
+ArrayElementWeakCompareAndSetBoolean...OK
+ArrayElementWeakCompareAndSetByte...OK
+ArrayElementWeakCompareAndSetShort...OK
+ArrayElementWeakCompareAndSetChar...OK
+ArrayElementWeakCompareAndSetInt...OK
+ArrayElementWeakCompareAndSetLong...OK
+ArrayElementWeakCompareAndSetFloat...OK
+ArrayElementWeakCompareAndSetDouble...OK
+ArrayElementWeakCompareAndSetAcquireBoolean...OK
+ArrayElementWeakCompareAndSetAcquireByte...OK
+ArrayElementWeakCompareAndSetAcquireShort...OK
+ArrayElementWeakCompareAndSetAcquireChar...OK
+ArrayElementWeakCompareAndSetAcquireInt...OK
+ArrayElementWeakCompareAndSetAcquireLong...OK
+ArrayElementWeakCompareAndSetAcquireFloat...OK
+ArrayElementWeakCompareAndSetAcquireDouble...OK
+ArrayElementWeakCompareAndSetReleaseBoolean...OK
+ArrayElementWeakCompareAndSetReleaseByte...OK
+ArrayElementWeakCompareAndSetReleaseShort...OK
+ArrayElementWeakCompareAndSetReleaseChar...OK
+ArrayElementWeakCompareAndSetReleaseInt...OK
+ArrayElementWeakCompareAndSetReleaseLong...OK
+ArrayElementWeakCompareAndSetReleaseFloat...OK
+ArrayElementWeakCompareAndSetReleaseDouble...OK
+ArrayElementGetAndSetBoolean...OK
+ArrayElementGetAndSetByte...OK
+ArrayElementGetAndSetShort...OK
+ArrayElementGetAndSetChar...OK
+ArrayElementGetAndSetInt...OK
+ArrayElementGetAndSetLong...OK
+ArrayElementGetAndSetFloat...OK
+ArrayElementGetAndSetDouble...OK
+ArrayElementGetAndSetAcquireBoolean...OK
+ArrayElementGetAndSetAcquireByte...OK
+ArrayElementGetAndSetAcquireShort...OK
+ArrayElementGetAndSetAcquireChar...OK
+ArrayElementGetAndSetAcquireInt...OK
+ArrayElementGetAndSetAcquireLong...OK
+ArrayElementGetAndSetAcquireFloat...OK
+ArrayElementGetAndSetAcquireDouble...OK
+ArrayElementGetAndSetReleaseBoolean...OK
+ArrayElementGetAndSetReleaseByte...OK
+ArrayElementGetAndSetReleaseShort...OK
+ArrayElementGetAndSetReleaseChar...OK
+ArrayElementGetAndSetReleaseInt...OK
+ArrayElementGetAndSetReleaseLong...OK
+ArrayElementGetAndSetReleaseFloat...OK
+ArrayElementGetAndSetReleaseDouble...OK
+ArrayElementGetAndAddBoolean...OK
+ArrayElementGetAndAddByte...OK
+ArrayElementGetAndAddShort...OK
+ArrayElementGetAndAddChar...OK
+ArrayElementGetAndAddInt...OK
+ArrayElementGetAndAddLong...OK
+ArrayElementGetAndAddFloat...OK
+ArrayElementGetAndAddDouble...OK
+ArrayElementGetAndAddAcquireBoolean...OK
+ArrayElementGetAndAddAcquireByte...OK
+ArrayElementGetAndAddAcquireShort...OK
+ArrayElementGetAndAddAcquireChar...OK
+ArrayElementGetAndAddAcquireInt...OK
+ArrayElementGetAndAddAcquireLong...OK
+ArrayElementGetAndAddAcquireFloat...OK
+ArrayElementGetAndAddAcquireDouble...OK
+ArrayElementGetAndAddReleaseBoolean...OK
+ArrayElementGetAndAddReleaseByte...OK
+ArrayElementGetAndAddReleaseShort...OK
+ArrayElementGetAndAddReleaseChar...OK
+ArrayElementGetAndAddReleaseInt...OK
+ArrayElementGetAndAddReleaseLong...OK
+ArrayElementGetAndAddReleaseFloat...OK
+ArrayElementGetAndAddReleaseDouble...OK
+ArrayElementGetAndBitwiseOrBoolean...OK
+ArrayElementGetAndBitwiseOrByte...OK
+ArrayElementGetAndBitwiseOrShort...OK
+ArrayElementGetAndBitwiseOrChar...OK
+ArrayElementGetAndBitwiseOrInt...OK
+ArrayElementGetAndBitwiseOrLong...OK
+ArrayElementGetAndBitwiseOrFloat...OK
+ArrayElementGetAndBitwiseOrDouble...OK
+ArrayElementGetAndBitwiseOrReleaseBoolean...OK
+ArrayElementGetAndBitwiseOrReleaseByte...OK
+ArrayElementGetAndBitwiseOrReleaseShort...OK
+ArrayElementGetAndBitwiseOrReleaseChar...OK
+ArrayElementGetAndBitwiseOrReleaseInt...OK
+ArrayElementGetAndBitwiseOrReleaseLong...OK
+ArrayElementGetAndBitwiseOrReleaseFloat...OK
+ArrayElementGetAndBitwiseOrReleaseDouble...OK
+ArrayElementGetAndBitwiseOrAcquireBoolean...OK
+ArrayElementGetAndBitwiseOrAcquireByte...OK
+ArrayElementGetAndBitwiseOrAcquireShort...OK
+ArrayElementGetAndBitwiseOrAcquireChar...OK
+ArrayElementGetAndBitwiseOrAcquireInt...OK
+ArrayElementGetAndBitwiseOrAcquireLong...OK
+ArrayElementGetAndBitwiseOrAcquireFloat...OK
+ArrayElementGetAndBitwiseOrAcquireDouble...OK
+ArrayElementGetAndBitwiseAndBoolean...OK
+ArrayElementGetAndBitwiseAndByte...OK
+ArrayElementGetAndBitwiseAndShort...OK
+ArrayElementGetAndBitwiseAndChar...OK
+ArrayElementGetAndBitwiseAndInt...OK
+ArrayElementGetAndBitwiseAndLong...OK
+ArrayElementGetAndBitwiseAndFloat...OK
+ArrayElementGetAndBitwiseAndDouble...OK
+ArrayElementGetAndBitwiseAndReleaseBoolean...OK
+ArrayElementGetAndBitwiseAndReleaseByte...OK
+ArrayElementGetAndBitwiseAndReleaseShort...OK
+ArrayElementGetAndBitwiseAndReleaseChar...OK
+ArrayElementGetAndBitwiseAndReleaseInt...OK
+ArrayElementGetAndBitwiseAndReleaseLong...OK
+ArrayElementGetAndBitwiseAndReleaseFloat...OK
+ArrayElementGetAndBitwiseAndReleaseDouble...OK
+ArrayElementGetAndBitwiseAndAcquireBoolean...OK
+ArrayElementGetAndBitwiseAndAcquireByte...OK
+ArrayElementGetAndBitwiseAndAcquireShort...OK
+ArrayElementGetAndBitwiseAndAcquireChar...OK
+ArrayElementGetAndBitwiseAndAcquireInt...OK
+ArrayElementGetAndBitwiseAndAcquireLong...OK
+ArrayElementGetAndBitwiseAndAcquireFloat...OK
+ArrayElementGetAndBitwiseAndAcquireDouble...OK
+ArrayElementGetAndBitwiseXorBoolean...OK
+ArrayElementGetAndBitwiseXorByte...OK
+ArrayElementGetAndBitwiseXorShort...OK
+ArrayElementGetAndBitwiseXorChar...OK
+ArrayElementGetAndBitwiseXorInt...OK
+ArrayElementGetAndBitwiseXorLong...OK
+ArrayElementGetAndBitwiseXorFloat...OK
+ArrayElementGetAndBitwiseXorDouble...OK
+ArrayElementGetAndBitwiseXorReleaseBoolean...OK
+ArrayElementGetAndBitwiseXorReleaseByte...OK
+ArrayElementGetAndBitwiseXorReleaseShort...OK
+ArrayElementGetAndBitwiseXorReleaseChar...OK
+ArrayElementGetAndBitwiseXorReleaseInt...OK
+ArrayElementGetAndBitwiseXorReleaseLong...OK
+ArrayElementGetAndBitwiseXorReleaseFloat...OK
+ArrayElementGetAndBitwiseXorReleaseDouble...OK
+ArrayElementGetAndBitwiseXorAcquireBoolean...OK
+ArrayElementGetAndBitwiseXorAcquireByte...OK
+ArrayElementGetAndBitwiseXorAcquireShort...OK
+ArrayElementGetAndBitwiseXorAcquireChar...OK
+ArrayElementGetAndBitwiseXorAcquireInt...OK
+ArrayElementGetAndBitwiseXorAcquireLong...OK
+ArrayElementGetAndBitwiseXorAcquireFloat...OK
+ArrayElementGetAndBitwiseXorAcquireDouble...OK
+ByteArrayViewLEGetShort...OK
+ByteArrayViewLEGetChar...OK
+ByteArrayViewLEGetInt...OK
+ByteArrayViewLEGetLong...OK
+ByteArrayViewLEGetFloat...OK
+ByteArrayViewLEGetDouble...OK
+ByteArrayViewLESetShort...OK
+ByteArrayViewLESetChar...OK
+ByteArrayViewLESetInt...OK
+ByteArrayViewLESetLong...OK
+ByteArrayViewLESetFloat...OK
+ByteArrayViewLESetDouble...OK
+ByteArrayViewLEGetVolatileShort...OK
+ByteArrayViewLEGetVolatileChar...OK
+ByteArrayViewLEGetVolatileInt...OK
+ByteArrayViewLEGetVolatileLong...OK
+ByteArrayViewLEGetVolatileFloat...OK
+ByteArrayViewLEGetVolatileDouble...OK
+ByteArrayViewLESetVolatileShort...OK
+ByteArrayViewLESetVolatileChar...OK
+ByteArrayViewLESetVolatileInt...OK
+ByteArrayViewLESetVolatileLong...OK
+ByteArrayViewLESetVolatileFloat...OK
+ByteArrayViewLESetVolatileDouble...OK
+ByteArrayViewLEGetAcquireShort...OK
+ByteArrayViewLEGetAcquireChar...OK
+ByteArrayViewLEGetAcquireInt...OK
+ByteArrayViewLEGetAcquireLong...OK
+ByteArrayViewLEGetAcquireFloat...OK
+ByteArrayViewLEGetAcquireDouble...OK
+ByteArrayViewLESetReleaseShort...OK
+ByteArrayViewLESetReleaseChar...OK
+ByteArrayViewLESetReleaseInt...OK
+ByteArrayViewLESetReleaseLong...OK
+ByteArrayViewLESetReleaseFloat...OK
+ByteArrayViewLESetReleaseDouble...OK
+ByteArrayViewLEGetOpaqueShort...OK
+ByteArrayViewLEGetOpaqueChar...OK
+ByteArrayViewLEGetOpaqueInt...OK
+ByteArrayViewLEGetOpaqueLong...OK
+ByteArrayViewLEGetOpaqueFloat...OK
+ByteArrayViewLEGetOpaqueDouble...OK
+ByteArrayViewLESetOpaqueShort...OK
+ByteArrayViewLESetOpaqueChar...OK
+ByteArrayViewLESetOpaqueInt...OK
+ByteArrayViewLESetOpaqueLong...OK
+ByteArrayViewLESetOpaqueFloat...OK
+ByteArrayViewLESetOpaqueDouble...OK
+ByteArrayViewLECompareAndSetShort...OK
+ByteArrayViewLECompareAndSetChar...OK
+ByteArrayViewLECompareAndSetInt...OK
+ByteArrayViewLECompareAndSetLong...OK
+ByteArrayViewLECompareAndSetFloat...OK
+ByteArrayViewLECompareAndSetDouble...OK
+ByteArrayViewLECompareAndExchangeShort...OK
+ByteArrayViewLECompareAndExchangeChar...OK
+ByteArrayViewLECompareAndExchangeInt...OK
+ByteArrayViewLECompareAndExchangeLong...OK
+ByteArrayViewLECompareAndExchangeFloat...OK
+ByteArrayViewLECompareAndExchangeDouble...OK
+ByteArrayViewLECompareAndExchangeAcquireShort...OK
+ByteArrayViewLECompareAndExchangeAcquireChar...OK
+ByteArrayViewLECompareAndExchangeAcquireInt...OK
+ByteArrayViewLECompareAndExchangeAcquireLong...OK
+ByteArrayViewLECompareAndExchangeAcquireFloat...OK
+ByteArrayViewLECompareAndExchangeAcquireDouble...OK
+ByteArrayViewLECompareAndExchangeReleaseShort...OK
+ByteArrayViewLECompareAndExchangeReleaseChar...OK
+ByteArrayViewLECompareAndExchangeReleaseInt...OK
+ByteArrayViewLECompareAndExchangeReleaseLong...OK
+ByteArrayViewLECompareAndExchangeReleaseFloat...OK
+ByteArrayViewLECompareAndExchangeReleaseDouble...OK
+ByteArrayViewLEWeakCompareAndSetPlainShort...OK
+ByteArrayViewLEWeakCompareAndSetPlainChar...OK
+ByteArrayViewLEWeakCompareAndSetPlainInt...OK
+ByteArrayViewLEWeakCompareAndSetPlainLong...OK
+ByteArrayViewLEWeakCompareAndSetPlainFloat...OK
+ByteArrayViewLEWeakCompareAndSetPlainDouble...OK
+ByteArrayViewLEWeakCompareAndSetShort...OK
+ByteArrayViewLEWeakCompareAndSetChar...OK
+ByteArrayViewLEWeakCompareAndSetInt...OK
+ByteArrayViewLEWeakCompareAndSetLong...OK
+ByteArrayViewLEWeakCompareAndSetFloat...OK
+ByteArrayViewLEWeakCompareAndSetDouble...OK
+ByteArrayViewLEWeakCompareAndSetAcquireShort...OK
+ByteArrayViewLEWeakCompareAndSetAcquireChar...OK
+ByteArrayViewLEWeakCompareAndSetAcquireInt...OK
+ByteArrayViewLEWeakCompareAndSetAcquireLong...OK
+ByteArrayViewLEWeakCompareAndSetAcquireFloat...OK
+ByteArrayViewLEWeakCompareAndSetAcquireDouble...OK
+ByteArrayViewLEWeakCompareAndSetReleaseShort...OK
+ByteArrayViewLEWeakCompareAndSetReleaseChar...OK
+ByteArrayViewLEWeakCompareAndSetReleaseInt...OK
+ByteArrayViewLEWeakCompareAndSetReleaseLong...OK
+ByteArrayViewLEWeakCompareAndSetReleaseFloat...OK
+ByteArrayViewLEWeakCompareAndSetReleaseDouble...OK
+ByteArrayViewLEGetAndSetShort...OK
+ByteArrayViewLEGetAndSetChar...OK
+ByteArrayViewLEGetAndSetInt...OK
+ByteArrayViewLEGetAndSetLong...OK
+ByteArrayViewLEGetAndSetFloat...OK
+ByteArrayViewLEGetAndSetDouble...OK
+ByteArrayViewLEGetAndSetAcquireShort...OK
+ByteArrayViewLEGetAndSetAcquireChar...OK
+ByteArrayViewLEGetAndSetAcquireInt...OK
+ByteArrayViewLEGetAndSetAcquireLong...OK
+ByteArrayViewLEGetAndSetAcquireFloat...OK
+ByteArrayViewLEGetAndSetAcquireDouble...OK
+ByteArrayViewLEGetAndSetReleaseShort...OK
+ByteArrayViewLEGetAndSetReleaseChar...OK
+ByteArrayViewLEGetAndSetReleaseInt...OK
+ByteArrayViewLEGetAndSetReleaseLong...OK
+ByteArrayViewLEGetAndSetReleaseFloat...OK
+ByteArrayViewLEGetAndSetReleaseDouble...OK
+ByteArrayViewLEGetAndAddShort...OK
+ByteArrayViewLEGetAndAddChar...OK
+ByteArrayViewLEGetAndAddInt...OK
+ByteArrayViewLEGetAndAddLong...OK
+ByteArrayViewLEGetAndAddFloat...OK
+ByteArrayViewLEGetAndAddDouble...OK
+ByteArrayViewLEGetAndAddAcquireShort...OK
+ByteArrayViewLEGetAndAddAcquireChar...OK
+ByteArrayViewLEGetAndAddAcquireInt...OK
+ByteArrayViewLEGetAndAddAcquireLong...OK
+ByteArrayViewLEGetAndAddAcquireFloat...OK
+ByteArrayViewLEGetAndAddAcquireDouble...OK
+ByteArrayViewLEGetAndAddReleaseShort...OK
+ByteArrayViewLEGetAndAddReleaseChar...OK
+ByteArrayViewLEGetAndAddReleaseInt...OK
+ByteArrayViewLEGetAndAddReleaseLong...OK
+ByteArrayViewLEGetAndAddReleaseFloat...OK
+ByteArrayViewLEGetAndAddReleaseDouble...OK
+ByteArrayViewLEGetAndBitwiseOrShort...OK
+ByteArrayViewLEGetAndBitwiseOrChar...OK
+ByteArrayViewLEGetAndBitwiseOrInt...OK
+ByteArrayViewLEGetAndBitwiseOrLong...OK
+ByteArrayViewLEGetAndBitwiseOrFloat...OK
+ByteArrayViewLEGetAndBitwiseOrDouble...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseShort...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseChar...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseInt...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseLong...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseFloat...OK
+ByteArrayViewLEGetAndBitwiseOrReleaseDouble...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireShort...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireChar...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireInt...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireLong...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireFloat...OK
+ByteArrayViewLEGetAndBitwiseOrAcquireDouble...OK
+ByteArrayViewLEGetAndBitwiseAndShort...OK
+ByteArrayViewLEGetAndBitwiseAndChar...OK
+ByteArrayViewLEGetAndBitwiseAndInt...OK
+ByteArrayViewLEGetAndBitwiseAndLong...OK
+ByteArrayViewLEGetAndBitwiseAndFloat...OK
+ByteArrayViewLEGetAndBitwiseAndDouble...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseShort...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseChar...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseInt...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseLong...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseFloat...OK
+ByteArrayViewLEGetAndBitwiseAndReleaseDouble...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireShort...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireChar...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireInt...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireLong...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireFloat...OK
+ByteArrayViewLEGetAndBitwiseAndAcquireDouble...OK
+ByteArrayViewLEGetAndBitwiseXorShort...OK
+ByteArrayViewLEGetAndBitwiseXorChar...OK
+ByteArrayViewLEGetAndBitwiseXorInt...OK
+ByteArrayViewLEGetAndBitwiseXorLong...OK
+ByteArrayViewLEGetAndBitwiseXorFloat...OK
+ByteArrayViewLEGetAndBitwiseXorDouble...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseShort...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseChar...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseInt...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseLong...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseFloat...OK
+ByteArrayViewLEGetAndBitwiseXorReleaseDouble...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireShort...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireChar...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireInt...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireLong...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireFloat...OK
+ByteArrayViewLEGetAndBitwiseXorAcquireDouble...OK
+ByteArrayViewBEGetShort...OK
+ByteArrayViewBEGetChar...OK
+ByteArrayViewBEGetInt...OK
+ByteArrayViewBEGetLong...OK
+ByteArrayViewBEGetFloat...OK
+ByteArrayViewBEGetDouble...OK
+ByteArrayViewBESetShort...OK
+ByteArrayViewBESetChar...OK
+ByteArrayViewBESetInt...OK
+ByteArrayViewBESetLong...OK
+ByteArrayViewBESetFloat...OK
+ByteArrayViewBESetDouble...OK
+ByteArrayViewBEGetVolatileShort...OK
+ByteArrayViewBEGetVolatileChar...OK
+ByteArrayViewBEGetVolatileInt...OK
+ByteArrayViewBEGetVolatileLong...OK
+ByteArrayViewBEGetVolatileFloat...OK
+ByteArrayViewBEGetVolatileDouble...OK
+ByteArrayViewBESetVolatileShort...OK
+ByteArrayViewBESetVolatileChar...OK
+ByteArrayViewBESetVolatileInt...OK
+ByteArrayViewBESetVolatileLong...OK
+ByteArrayViewBESetVolatileFloat...OK
+ByteArrayViewBESetVolatileDouble...OK
+ByteArrayViewBEGetAcquireShort...OK
+ByteArrayViewBEGetAcquireChar...OK
+ByteArrayViewBEGetAcquireInt...OK
+ByteArrayViewBEGetAcquireLong...OK
+ByteArrayViewBEGetAcquireFloat...OK
+ByteArrayViewBEGetAcquireDouble...OK
+ByteArrayViewBESetReleaseShort...OK
+ByteArrayViewBESetReleaseChar...OK
+ByteArrayViewBESetReleaseInt...OK
+ByteArrayViewBESetReleaseLong...OK
+ByteArrayViewBESetReleaseFloat...OK
+ByteArrayViewBESetReleaseDouble...OK
+ByteArrayViewBEGetOpaqueShort...OK
+ByteArrayViewBEGetOpaqueChar...OK
+ByteArrayViewBEGetOpaqueInt...OK
+ByteArrayViewBEGetOpaqueLong...OK
+ByteArrayViewBEGetOpaqueFloat...OK
+ByteArrayViewBEGetOpaqueDouble...OK
+ByteArrayViewBESetOpaqueShort...OK
+ByteArrayViewBESetOpaqueChar...OK
+ByteArrayViewBESetOpaqueInt...OK
+ByteArrayViewBESetOpaqueLong...OK
+ByteArrayViewBESetOpaqueFloat...OK
+ByteArrayViewBESetOpaqueDouble...OK
+ByteArrayViewBECompareAndSetShort...OK
+ByteArrayViewBECompareAndSetChar...OK
+ByteArrayViewBECompareAndSetInt...OK
+ByteArrayViewBECompareAndSetLong...OK
+ByteArrayViewBECompareAndSetFloat...OK
+ByteArrayViewBECompareAndSetDouble...OK
+ByteArrayViewBECompareAndExchangeShort...OK
+ByteArrayViewBECompareAndExchangeChar...OK
+ByteArrayViewBECompareAndExchangeInt...OK
+ByteArrayViewBECompareAndExchangeLong...OK
+ByteArrayViewBECompareAndExchangeFloat...OK
+ByteArrayViewBECompareAndExchangeDouble...OK
+ByteArrayViewBECompareAndExchangeAcquireShort...OK
+ByteArrayViewBECompareAndExchangeAcquireChar...OK
+ByteArrayViewBECompareAndExchangeAcquireInt...OK
+ByteArrayViewBECompareAndExchangeAcquireLong...OK
+ByteArrayViewBECompareAndExchangeAcquireFloat...OK
+ByteArrayViewBECompareAndExchangeAcquireDouble...OK
+ByteArrayViewBECompareAndExchangeReleaseShort...OK
+ByteArrayViewBECompareAndExchangeReleaseChar...OK
+ByteArrayViewBECompareAndExchangeReleaseInt...OK
+ByteArrayViewBECompareAndExchangeReleaseLong...OK
+ByteArrayViewBECompareAndExchangeReleaseFloat...OK
+ByteArrayViewBECompareAndExchangeReleaseDouble...OK
+ByteArrayViewBEWeakCompareAndSetPlainShort...OK
+ByteArrayViewBEWeakCompareAndSetPlainChar...OK
+ByteArrayViewBEWeakCompareAndSetPlainInt...OK
+ByteArrayViewBEWeakCompareAndSetPlainLong...OK
+ByteArrayViewBEWeakCompareAndSetPlainFloat...OK
+ByteArrayViewBEWeakCompareAndSetPlainDouble...OK
+ByteArrayViewBEWeakCompareAndSetShort...OK
+ByteArrayViewBEWeakCompareAndSetChar...OK
+ByteArrayViewBEWeakCompareAndSetInt...OK
+ByteArrayViewBEWeakCompareAndSetLong...OK
+ByteArrayViewBEWeakCompareAndSetFloat...OK
+ByteArrayViewBEWeakCompareAndSetDouble...OK
+ByteArrayViewBEWeakCompareAndSetAcquireShort...OK
+ByteArrayViewBEWeakCompareAndSetAcquireChar...OK
+ByteArrayViewBEWeakCompareAndSetAcquireInt...OK
+ByteArrayViewBEWeakCompareAndSetAcquireLong...OK
+ByteArrayViewBEWeakCompareAndSetAcquireFloat...OK
+ByteArrayViewBEWeakCompareAndSetAcquireDouble...OK
+ByteArrayViewBEWeakCompareAndSetReleaseShort...OK
+ByteArrayViewBEWeakCompareAndSetReleaseChar...OK
+ByteArrayViewBEWeakCompareAndSetReleaseInt...OK
+ByteArrayViewBEWeakCompareAndSetReleaseLong...OK
+ByteArrayViewBEWeakCompareAndSetReleaseFloat...OK
+ByteArrayViewBEWeakCompareAndSetReleaseDouble...OK
+ByteArrayViewBEGetAndSetShort...OK
+ByteArrayViewBEGetAndSetChar...OK
+ByteArrayViewBEGetAndSetInt...OK
+ByteArrayViewBEGetAndSetLong...OK
+ByteArrayViewBEGetAndSetFloat...OK
+ByteArrayViewBEGetAndSetDouble...OK
+ByteArrayViewBEGetAndSetAcquireShort...OK
+ByteArrayViewBEGetAndSetAcquireChar...OK
+ByteArrayViewBEGetAndSetAcquireInt...OK
+ByteArrayViewBEGetAndSetAcquireLong...OK
+ByteArrayViewBEGetAndSetAcquireFloat...OK
+ByteArrayViewBEGetAndSetAcquireDouble...OK
+ByteArrayViewBEGetAndSetReleaseShort...OK
+ByteArrayViewBEGetAndSetReleaseChar...OK
+ByteArrayViewBEGetAndSetReleaseInt...OK
+ByteArrayViewBEGetAndSetReleaseLong...OK
+ByteArrayViewBEGetAndSetReleaseFloat...OK
+ByteArrayViewBEGetAndSetReleaseDouble...OK
+ByteArrayViewBEGetAndAddShort...OK
+ByteArrayViewBEGetAndAddChar...OK
+ByteArrayViewBEGetAndAddInt...OK
+ByteArrayViewBEGetAndAddLong...OK
+ByteArrayViewBEGetAndAddFloat...OK
+ByteArrayViewBEGetAndAddDouble...OK
+ByteArrayViewBEGetAndAddAcquireShort...OK
+ByteArrayViewBEGetAndAddAcquireChar...OK
+ByteArrayViewBEGetAndAddAcquireInt...OK
+ByteArrayViewBEGetAndAddAcquireLong...OK
+ByteArrayViewBEGetAndAddAcquireFloat...OK
+ByteArrayViewBEGetAndAddAcquireDouble...OK
+ByteArrayViewBEGetAndAddReleaseShort...OK
+ByteArrayViewBEGetAndAddReleaseChar...OK
+ByteArrayViewBEGetAndAddReleaseInt...OK
+ByteArrayViewBEGetAndAddReleaseLong...OK
+ByteArrayViewBEGetAndAddReleaseFloat...OK
+ByteArrayViewBEGetAndAddReleaseDouble...OK
+ByteArrayViewBEGetAndBitwiseOrShort...OK
+ByteArrayViewBEGetAndBitwiseOrChar...OK
+ByteArrayViewBEGetAndBitwiseOrInt...OK
+ByteArrayViewBEGetAndBitwiseOrLong...OK
+ByteArrayViewBEGetAndBitwiseOrFloat...OK
+ByteArrayViewBEGetAndBitwiseOrDouble...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseShort...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseChar...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseInt...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseLong...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseFloat...OK
+ByteArrayViewBEGetAndBitwiseOrReleaseDouble...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireShort...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireChar...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireInt...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireLong...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireFloat...OK
+ByteArrayViewBEGetAndBitwiseOrAcquireDouble...OK
+ByteArrayViewBEGetAndBitwiseAndShort...OK
+ByteArrayViewBEGetAndBitwiseAndChar...OK
+ByteArrayViewBEGetAndBitwiseAndInt...OK
+ByteArrayViewBEGetAndBitwiseAndLong...OK
+ByteArrayViewBEGetAndBitwiseAndFloat...OK
+ByteArrayViewBEGetAndBitwiseAndDouble...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseShort...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseChar...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseInt...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseLong...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseFloat...OK
+ByteArrayViewBEGetAndBitwiseAndReleaseDouble...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireShort...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireChar...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireInt...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireLong...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireFloat...OK
+ByteArrayViewBEGetAndBitwiseAndAcquireDouble...OK
+ByteArrayViewBEGetAndBitwiseXorShort...OK
+ByteArrayViewBEGetAndBitwiseXorChar...OK
+ByteArrayViewBEGetAndBitwiseXorInt...OK
+ByteArrayViewBEGetAndBitwiseXorLong...OK
+ByteArrayViewBEGetAndBitwiseXorFloat...OK
+ByteArrayViewBEGetAndBitwiseXorDouble...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseShort...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseChar...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseInt...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseLong...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseFloat...OK
+ByteArrayViewBEGetAndBitwiseXorReleaseDouble...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireShort...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireChar...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireInt...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireLong...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireFloat...OK
+ByteArrayViewBEGetAndBitwiseXorAcquireDouble...OK
+DirectByteBufferViewLEGetShort...OK
+DirectByteBufferViewLEGetChar...OK
+DirectByteBufferViewLEGetInt...OK
+DirectByteBufferViewLEGetLong...OK
+DirectByteBufferViewLEGetFloat...OK
+DirectByteBufferViewLEGetDouble...OK
+DirectByteBufferViewLESetShort...OK
+DirectByteBufferViewLESetChar...OK
+DirectByteBufferViewLESetInt...OK
+DirectByteBufferViewLESetLong...OK
+DirectByteBufferViewLESetFloat...OK
+DirectByteBufferViewLESetDouble...OK
+DirectByteBufferViewLEGetVolatileShort...OK
+DirectByteBufferViewLEGetVolatileChar...OK
+DirectByteBufferViewLEGetVolatileInt...OK
+DirectByteBufferViewLEGetVolatileLong...OK
+DirectByteBufferViewLEGetVolatileFloat...OK
+DirectByteBufferViewLEGetVolatileDouble...OK
+DirectByteBufferViewLESetVolatileShort...OK
+DirectByteBufferViewLESetVolatileChar...OK
+DirectByteBufferViewLESetVolatileInt...OK
+DirectByteBufferViewLESetVolatileLong...OK
+DirectByteBufferViewLESetVolatileFloat...OK
+DirectByteBufferViewLESetVolatileDouble...OK
+DirectByteBufferViewLEGetAcquireShort...OK
+DirectByteBufferViewLEGetAcquireChar...OK
+DirectByteBufferViewLEGetAcquireInt...OK
+DirectByteBufferViewLEGetAcquireLong...OK
+DirectByteBufferViewLEGetAcquireFloat...OK
+DirectByteBufferViewLEGetAcquireDouble...OK
+DirectByteBufferViewLESetReleaseShort...OK
+DirectByteBufferViewLESetReleaseChar...OK
+DirectByteBufferViewLESetReleaseInt...OK
+DirectByteBufferViewLESetReleaseLong...OK
+DirectByteBufferViewLESetReleaseFloat...OK
+DirectByteBufferViewLESetReleaseDouble...OK
+DirectByteBufferViewLEGetOpaqueShort...OK
+DirectByteBufferViewLEGetOpaqueChar...OK
+DirectByteBufferViewLEGetOpaqueInt...OK
+DirectByteBufferViewLEGetOpaqueLong...OK
+DirectByteBufferViewLEGetOpaqueFloat...OK
+DirectByteBufferViewLEGetOpaqueDouble...OK
+DirectByteBufferViewLESetOpaqueShort...OK
+DirectByteBufferViewLESetOpaqueChar...OK
+DirectByteBufferViewLESetOpaqueInt...OK
+DirectByteBufferViewLESetOpaqueLong...OK
+DirectByteBufferViewLESetOpaqueFloat...OK
+DirectByteBufferViewLESetOpaqueDouble...OK
+DirectByteBufferViewLECompareAndSetShort...OK
+DirectByteBufferViewLECompareAndSetChar...OK
+DirectByteBufferViewLECompareAndSetInt...OK
+DirectByteBufferViewLECompareAndSetLong...OK
+DirectByteBufferViewLECompareAndSetFloat...OK
+DirectByteBufferViewLECompareAndSetDouble...OK
+DirectByteBufferViewLECompareAndExchangeShort...OK
+DirectByteBufferViewLECompareAndExchangeChar...OK
+DirectByteBufferViewLECompareAndExchangeInt...OK
+DirectByteBufferViewLECompareAndExchangeLong...OK
+DirectByteBufferViewLECompareAndExchangeFloat...OK
+DirectByteBufferViewLECompareAndExchangeDouble...OK
+DirectByteBufferViewLECompareAndExchangeAcquireShort...OK
+DirectByteBufferViewLECompareAndExchangeAcquireChar...OK
+DirectByteBufferViewLECompareAndExchangeAcquireInt...OK
+DirectByteBufferViewLECompareAndExchangeAcquireLong...OK
+DirectByteBufferViewLECompareAndExchangeAcquireFloat...OK
+DirectByteBufferViewLECompareAndExchangeAcquireDouble...OK
+DirectByteBufferViewLECompareAndExchangeReleaseShort...OK
+DirectByteBufferViewLECompareAndExchangeReleaseChar...OK
+DirectByteBufferViewLECompareAndExchangeReleaseInt...OK
+DirectByteBufferViewLECompareAndExchangeReleaseLong...OK
+DirectByteBufferViewLECompareAndExchangeReleaseFloat...OK
+DirectByteBufferViewLECompareAndExchangeReleaseDouble...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainShort...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainChar...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainInt...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainLong...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainFloat...OK
+DirectByteBufferViewLEWeakCompareAndSetPlainDouble...OK
+DirectByteBufferViewLEWeakCompareAndSetShort...OK
+DirectByteBufferViewLEWeakCompareAndSetChar...OK
+DirectByteBufferViewLEWeakCompareAndSetInt...OK
+DirectByteBufferViewLEWeakCompareAndSetLong...OK
+DirectByteBufferViewLEWeakCompareAndSetFloat...OK
+DirectByteBufferViewLEWeakCompareAndSetDouble...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireShort...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireChar...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireInt...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireLong...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireFloat...OK
+DirectByteBufferViewLEWeakCompareAndSetAcquireDouble...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseShort...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseChar...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseInt...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseLong...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseFloat...OK
+DirectByteBufferViewLEWeakCompareAndSetReleaseDouble...OK
+DirectByteBufferViewLEGetAndSetShort...OK
+DirectByteBufferViewLEGetAndSetChar...OK
+DirectByteBufferViewLEGetAndSetInt...OK
+DirectByteBufferViewLEGetAndSetLong...OK
+DirectByteBufferViewLEGetAndSetFloat...OK
+DirectByteBufferViewLEGetAndSetDouble...OK
+DirectByteBufferViewLEGetAndSetAcquireShort...OK
+DirectByteBufferViewLEGetAndSetAcquireChar...OK
+DirectByteBufferViewLEGetAndSetAcquireInt...OK
+DirectByteBufferViewLEGetAndSetAcquireLong...OK
+DirectByteBufferViewLEGetAndSetAcquireFloat...OK
+DirectByteBufferViewLEGetAndSetAcquireDouble...OK
+DirectByteBufferViewLEGetAndSetReleaseShort...OK
+DirectByteBufferViewLEGetAndSetReleaseChar...OK
+DirectByteBufferViewLEGetAndSetReleaseInt...OK
+DirectByteBufferViewLEGetAndSetReleaseLong...OK
+DirectByteBufferViewLEGetAndSetReleaseFloat...OK
+DirectByteBufferViewLEGetAndSetReleaseDouble...OK
+DirectByteBufferViewLEGetAndAddShort...OK
+DirectByteBufferViewLEGetAndAddChar...OK
+DirectByteBufferViewLEGetAndAddInt...OK
+DirectByteBufferViewLEGetAndAddLong...OK
+DirectByteBufferViewLEGetAndAddFloat...OK
+DirectByteBufferViewLEGetAndAddDouble...OK
+DirectByteBufferViewLEGetAndAddAcquireShort...OK
+DirectByteBufferViewLEGetAndAddAcquireChar...OK
+DirectByteBufferViewLEGetAndAddAcquireInt...OK
+DirectByteBufferViewLEGetAndAddAcquireLong...OK
+DirectByteBufferViewLEGetAndAddAcquireFloat...OK
+DirectByteBufferViewLEGetAndAddAcquireDouble...OK
+DirectByteBufferViewLEGetAndAddReleaseShort...OK
+DirectByteBufferViewLEGetAndAddReleaseChar...OK
+DirectByteBufferViewLEGetAndAddReleaseInt...OK
+DirectByteBufferViewLEGetAndAddReleaseLong...OK
+DirectByteBufferViewLEGetAndAddReleaseFloat...OK
+DirectByteBufferViewLEGetAndAddReleaseDouble...OK
+DirectByteBufferViewLEGetAndBitwiseOrShort...OK
+DirectByteBufferViewLEGetAndBitwiseOrChar...OK
+DirectByteBufferViewLEGetAndBitwiseOrInt...OK
+DirectByteBufferViewLEGetAndBitwiseOrLong...OK
+DirectByteBufferViewLEGetAndBitwiseOrFloat...OK
+DirectByteBufferViewLEGetAndBitwiseOrDouble...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseShort...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseChar...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseInt...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseLong...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseFloat...OK
+DirectByteBufferViewLEGetAndBitwiseOrReleaseDouble...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireShort...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireChar...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireInt...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireLong...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireFloat...OK
+DirectByteBufferViewLEGetAndBitwiseOrAcquireDouble...OK
+DirectByteBufferViewLEGetAndBitwiseAndShort...OK
+DirectByteBufferViewLEGetAndBitwiseAndChar...OK
+DirectByteBufferViewLEGetAndBitwiseAndInt...OK
+DirectByteBufferViewLEGetAndBitwiseAndLong...OK
+DirectByteBufferViewLEGetAndBitwiseAndFloat...OK
+DirectByteBufferViewLEGetAndBitwiseAndDouble...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseShort...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseChar...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseInt...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseLong...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseFloat...OK
+DirectByteBufferViewLEGetAndBitwiseAndReleaseDouble...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireShort...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireChar...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireInt...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireLong...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireFloat...OK
+DirectByteBufferViewLEGetAndBitwiseAndAcquireDouble...OK
+DirectByteBufferViewLEGetAndBitwiseXorShort...OK
+DirectByteBufferViewLEGetAndBitwiseXorChar...OK
+DirectByteBufferViewLEGetAndBitwiseXorInt...OK
+DirectByteBufferViewLEGetAndBitwiseXorLong...OK
+DirectByteBufferViewLEGetAndBitwiseXorFloat...OK
+DirectByteBufferViewLEGetAndBitwiseXorDouble...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseShort...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseChar...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseInt...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseLong...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseFloat...OK
+DirectByteBufferViewLEGetAndBitwiseXorReleaseDouble...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireShort...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireChar...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireInt...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireLong...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireFloat...OK
+DirectByteBufferViewLEGetAndBitwiseXorAcquireDouble...OK
+DirectByteBufferViewBEGetShort...OK
+DirectByteBufferViewBEGetChar...OK
+DirectByteBufferViewBEGetInt...OK
+DirectByteBufferViewBEGetLong...OK
+DirectByteBufferViewBEGetFloat...OK
+DirectByteBufferViewBEGetDouble...OK
+DirectByteBufferViewBESetShort...OK
+DirectByteBufferViewBESetChar...OK
+DirectByteBufferViewBESetInt...OK
+DirectByteBufferViewBESetLong...OK
+DirectByteBufferViewBESetFloat...OK
+DirectByteBufferViewBESetDouble...OK
+DirectByteBufferViewBEGetVolatileShort...OK
+DirectByteBufferViewBEGetVolatileChar...OK
+DirectByteBufferViewBEGetVolatileInt...OK
+DirectByteBufferViewBEGetVolatileLong...OK
+DirectByteBufferViewBEGetVolatileFloat...OK
+DirectByteBufferViewBEGetVolatileDouble...OK
+DirectByteBufferViewBESetVolatileShort...OK
+DirectByteBufferViewBESetVolatileChar...OK
+DirectByteBufferViewBESetVolatileInt...OK
+DirectByteBufferViewBESetVolatileLong...OK
+DirectByteBufferViewBESetVolatileFloat...OK
+DirectByteBufferViewBESetVolatileDouble...OK
+DirectByteBufferViewBEGetAcquireShort...OK
+DirectByteBufferViewBEGetAcquireChar...OK
+DirectByteBufferViewBEGetAcquireInt...OK
+DirectByteBufferViewBEGetAcquireLong...OK
+DirectByteBufferViewBEGetAcquireFloat...OK
+DirectByteBufferViewBEGetAcquireDouble...OK
+DirectByteBufferViewBESetReleaseShort...OK
+DirectByteBufferViewBESetReleaseChar...OK
+DirectByteBufferViewBESetReleaseInt...OK
+DirectByteBufferViewBESetReleaseLong...OK
+DirectByteBufferViewBESetReleaseFloat...OK
+DirectByteBufferViewBESetReleaseDouble...OK
+DirectByteBufferViewBEGetOpaqueShort...OK
+DirectByteBufferViewBEGetOpaqueChar...OK
+DirectByteBufferViewBEGetOpaqueInt...OK
+DirectByteBufferViewBEGetOpaqueLong...OK
+DirectByteBufferViewBEGetOpaqueFloat...OK
+DirectByteBufferViewBEGetOpaqueDouble...OK
+DirectByteBufferViewBESetOpaqueShort...OK
+DirectByteBufferViewBESetOpaqueChar...OK
+DirectByteBufferViewBESetOpaqueInt...OK
+DirectByteBufferViewBESetOpaqueLong...OK
+DirectByteBufferViewBESetOpaqueFloat...OK
+DirectByteBufferViewBESetOpaqueDouble...OK
+DirectByteBufferViewBECompareAndSetShort...OK
+DirectByteBufferViewBECompareAndSetChar...OK
+DirectByteBufferViewBECompareAndSetInt...OK
+DirectByteBufferViewBECompareAndSetLong...OK
+DirectByteBufferViewBECompareAndSetFloat...OK
+DirectByteBufferViewBECompareAndSetDouble...OK
+DirectByteBufferViewBECompareAndExchangeShort...OK
+DirectByteBufferViewBECompareAndExchangeChar...OK
+DirectByteBufferViewBECompareAndExchangeInt...OK
+DirectByteBufferViewBECompareAndExchangeLong...OK
+DirectByteBufferViewBECompareAndExchangeFloat...OK
+DirectByteBufferViewBECompareAndExchangeDouble...OK
+DirectByteBufferViewBECompareAndExchangeAcquireShort...OK
+DirectByteBufferViewBECompareAndExchangeAcquireChar...OK
+DirectByteBufferViewBECompareAndExchangeAcquireInt...OK
+DirectByteBufferViewBECompareAndExchangeAcquireLong...OK
+DirectByteBufferViewBECompareAndExchangeAcquireFloat...OK
+DirectByteBufferViewBECompareAndExchangeAcquireDouble...OK
+DirectByteBufferViewBECompareAndExchangeReleaseShort...OK
+DirectByteBufferViewBECompareAndExchangeReleaseChar...OK
+DirectByteBufferViewBECompareAndExchangeReleaseInt...OK
+DirectByteBufferViewBECompareAndExchangeReleaseLong...OK
+DirectByteBufferViewBECompareAndExchangeReleaseFloat...OK
+DirectByteBufferViewBECompareAndExchangeReleaseDouble...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainShort...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainChar...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainInt...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainLong...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainFloat...OK
+DirectByteBufferViewBEWeakCompareAndSetPlainDouble...OK
+DirectByteBufferViewBEWeakCompareAndSetShort...OK
+DirectByteBufferViewBEWeakCompareAndSetChar...OK
+DirectByteBufferViewBEWeakCompareAndSetInt...OK
+DirectByteBufferViewBEWeakCompareAndSetLong...OK
+DirectByteBufferViewBEWeakCompareAndSetFloat...OK
+DirectByteBufferViewBEWeakCompareAndSetDouble...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireShort...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireChar...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireInt...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireLong...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireFloat...OK
+DirectByteBufferViewBEWeakCompareAndSetAcquireDouble...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseShort...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseChar...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseInt...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseLong...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseFloat...OK
+DirectByteBufferViewBEWeakCompareAndSetReleaseDouble...OK
+DirectByteBufferViewBEGetAndSetShort...OK
+DirectByteBufferViewBEGetAndSetChar...OK
+DirectByteBufferViewBEGetAndSetInt...OK
+DirectByteBufferViewBEGetAndSetLong...OK
+DirectByteBufferViewBEGetAndSetFloat...OK
+DirectByteBufferViewBEGetAndSetDouble...OK
+DirectByteBufferViewBEGetAndSetAcquireShort...OK
+DirectByteBufferViewBEGetAndSetAcquireChar...OK
+DirectByteBufferViewBEGetAndSetAcquireInt...OK
+DirectByteBufferViewBEGetAndSetAcquireLong...OK
+DirectByteBufferViewBEGetAndSetAcquireFloat...OK
+DirectByteBufferViewBEGetAndSetAcquireDouble...OK
+DirectByteBufferViewBEGetAndSetReleaseShort...OK
+DirectByteBufferViewBEGetAndSetReleaseChar...OK
+DirectByteBufferViewBEGetAndSetReleaseInt...OK
+DirectByteBufferViewBEGetAndSetReleaseLong...OK
+DirectByteBufferViewBEGetAndSetReleaseFloat...OK
+DirectByteBufferViewBEGetAndSetReleaseDouble...OK
+DirectByteBufferViewBEGetAndAddShort...OK
+DirectByteBufferViewBEGetAndAddChar...OK
+DirectByteBufferViewBEGetAndAddInt...OK
+DirectByteBufferViewBEGetAndAddLong...OK
+DirectByteBufferViewBEGetAndAddFloat...OK
+DirectByteBufferViewBEGetAndAddDouble...OK
+DirectByteBufferViewBEGetAndAddAcquireShort...OK
+DirectByteBufferViewBEGetAndAddAcquireChar...OK
+DirectByteBufferViewBEGetAndAddAcquireInt...OK
+DirectByteBufferViewBEGetAndAddAcquireLong...OK
+DirectByteBufferViewBEGetAndAddAcquireFloat...OK
+DirectByteBufferViewBEGetAndAddAcquireDouble...OK
+DirectByteBufferViewBEGetAndAddReleaseShort...OK
+DirectByteBufferViewBEGetAndAddReleaseChar...OK
+DirectByteBufferViewBEGetAndAddReleaseInt...OK
+DirectByteBufferViewBEGetAndAddReleaseLong...OK
+DirectByteBufferViewBEGetAndAddReleaseFloat...OK
+DirectByteBufferViewBEGetAndAddReleaseDouble...OK
+DirectByteBufferViewBEGetAndBitwiseOrShort...OK
+DirectByteBufferViewBEGetAndBitwiseOrChar...OK
+DirectByteBufferViewBEGetAndBitwiseOrInt...OK
+DirectByteBufferViewBEGetAndBitwiseOrLong...OK
+DirectByteBufferViewBEGetAndBitwiseOrFloat...OK
+DirectByteBufferViewBEGetAndBitwiseOrDouble...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseShort...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseChar...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseInt...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseLong...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseFloat...OK
+DirectByteBufferViewBEGetAndBitwiseOrReleaseDouble...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireShort...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireChar...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireInt...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireLong...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireFloat...OK
+DirectByteBufferViewBEGetAndBitwiseOrAcquireDouble...OK
+DirectByteBufferViewBEGetAndBitwiseAndShort...OK
+DirectByteBufferViewBEGetAndBitwiseAndChar...OK
+DirectByteBufferViewBEGetAndBitwiseAndInt...OK
+DirectByteBufferViewBEGetAndBitwiseAndLong...OK
+DirectByteBufferViewBEGetAndBitwiseAndFloat...OK
+DirectByteBufferViewBEGetAndBitwiseAndDouble...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseShort...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseChar...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseInt...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseLong...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseFloat...OK
+DirectByteBufferViewBEGetAndBitwiseAndReleaseDouble...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireShort...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireChar...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireInt...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireLong...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireFloat...OK
+DirectByteBufferViewBEGetAndBitwiseAndAcquireDouble...OK
+DirectByteBufferViewBEGetAndBitwiseXorShort...OK
+DirectByteBufferViewBEGetAndBitwiseXorChar...OK
+DirectByteBufferViewBEGetAndBitwiseXorInt...OK
+DirectByteBufferViewBEGetAndBitwiseXorLong...OK
+DirectByteBufferViewBEGetAndBitwiseXorFloat...OK
+DirectByteBufferViewBEGetAndBitwiseXorDouble...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseShort...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseChar...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseInt...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseLong...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseFloat...OK
+DirectByteBufferViewBEGetAndBitwiseXorReleaseDouble...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireShort...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireChar...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireInt...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireLong...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireFloat...OK
+DirectByteBufferViewBEGetAndBitwiseXorAcquireDouble...OK
+HeapByteBufferViewLEGetShort...OK
+HeapByteBufferViewLEGetChar...OK
+HeapByteBufferViewLEGetInt...OK
+HeapByteBufferViewLEGetLong...OK
+HeapByteBufferViewLEGetFloat...OK
+HeapByteBufferViewLEGetDouble...OK
+HeapByteBufferViewLESetShort...OK
+HeapByteBufferViewLESetChar...OK
+HeapByteBufferViewLESetInt...OK
+HeapByteBufferViewLESetLong...OK
+HeapByteBufferViewLESetFloat...OK
+HeapByteBufferViewLESetDouble...OK
+HeapByteBufferViewLEGetVolatileShort...OK
+HeapByteBufferViewLEGetVolatileChar...OK
+HeapByteBufferViewLEGetVolatileInt...OK
+HeapByteBufferViewLEGetVolatileLong...OK
+HeapByteBufferViewLEGetVolatileFloat...OK
+HeapByteBufferViewLEGetVolatileDouble...OK
+HeapByteBufferViewLESetVolatileShort...OK
+HeapByteBufferViewLESetVolatileChar...OK
+HeapByteBufferViewLESetVolatileInt...OK
+HeapByteBufferViewLESetVolatileLong...OK
+HeapByteBufferViewLESetVolatileFloat...OK
+HeapByteBufferViewLESetVolatileDouble...OK
+HeapByteBufferViewLEGetAcquireShort...OK
+HeapByteBufferViewLEGetAcquireChar...OK
+HeapByteBufferViewLEGetAcquireInt...OK
+HeapByteBufferViewLEGetAcquireLong...OK
+HeapByteBufferViewLEGetAcquireFloat...OK
+HeapByteBufferViewLEGetAcquireDouble...OK
+HeapByteBufferViewLESetReleaseShort...OK
+HeapByteBufferViewLESetReleaseChar...OK
+HeapByteBufferViewLESetReleaseInt...OK
+HeapByteBufferViewLESetReleaseLong...OK
+HeapByteBufferViewLESetReleaseFloat...OK
+HeapByteBufferViewLESetReleaseDouble...OK
+HeapByteBufferViewLEGetOpaqueShort...OK
+HeapByteBufferViewLEGetOpaqueChar...OK
+HeapByteBufferViewLEGetOpaqueInt...OK
+HeapByteBufferViewLEGetOpaqueLong...OK
+HeapByteBufferViewLEGetOpaqueFloat...OK
+HeapByteBufferViewLEGetOpaqueDouble...OK
+HeapByteBufferViewLESetOpaqueShort...OK
+HeapByteBufferViewLESetOpaqueChar...OK
+HeapByteBufferViewLESetOpaqueInt...OK
+HeapByteBufferViewLESetOpaqueLong...OK
+HeapByteBufferViewLESetOpaqueFloat...OK
+HeapByteBufferViewLESetOpaqueDouble...OK
+HeapByteBufferViewLECompareAndSetShort...OK
+HeapByteBufferViewLECompareAndSetChar...OK
+HeapByteBufferViewLECompareAndSetInt...OK
+HeapByteBufferViewLECompareAndSetLong...OK
+HeapByteBufferViewLECompareAndSetFloat...OK
+HeapByteBufferViewLECompareAndSetDouble...OK
+HeapByteBufferViewLECompareAndExchangeShort...OK
+HeapByteBufferViewLECompareAndExchangeChar...OK
+HeapByteBufferViewLECompareAndExchangeInt...OK
+HeapByteBufferViewLECompareAndExchangeLong...OK
+HeapByteBufferViewLECompareAndExchangeFloat...OK
+HeapByteBufferViewLECompareAndExchangeDouble...OK
+HeapByteBufferViewLECompareAndExchangeAcquireShort...OK
+HeapByteBufferViewLECompareAndExchangeAcquireChar...OK
+HeapByteBufferViewLECompareAndExchangeAcquireInt...OK
+HeapByteBufferViewLECompareAndExchangeAcquireLong...OK
+HeapByteBufferViewLECompareAndExchangeAcquireFloat...OK
+HeapByteBufferViewLECompareAndExchangeAcquireDouble...OK
+HeapByteBufferViewLECompareAndExchangeReleaseShort...OK
+HeapByteBufferViewLECompareAndExchangeReleaseChar...OK
+HeapByteBufferViewLECompareAndExchangeReleaseInt...OK
+HeapByteBufferViewLECompareAndExchangeReleaseLong...OK
+HeapByteBufferViewLECompareAndExchangeReleaseFloat...OK
+HeapByteBufferViewLECompareAndExchangeReleaseDouble...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainShort...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainChar...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainInt...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainLong...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainFloat...OK
+HeapByteBufferViewLEWeakCompareAndSetPlainDouble...OK
+HeapByteBufferViewLEWeakCompareAndSetShort...OK
+HeapByteBufferViewLEWeakCompareAndSetChar...OK
+HeapByteBufferViewLEWeakCompareAndSetInt...OK
+HeapByteBufferViewLEWeakCompareAndSetLong...OK
+HeapByteBufferViewLEWeakCompareAndSetFloat...OK
+HeapByteBufferViewLEWeakCompareAndSetDouble...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireShort...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireChar...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireInt...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireLong...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireFloat...OK
+HeapByteBufferViewLEWeakCompareAndSetAcquireDouble...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseShort...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseChar...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseInt...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseLong...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseFloat...OK
+HeapByteBufferViewLEWeakCompareAndSetReleaseDouble...OK
+HeapByteBufferViewLEGetAndSetShort...OK
+HeapByteBufferViewLEGetAndSetChar...OK
+HeapByteBufferViewLEGetAndSetInt...OK
+HeapByteBufferViewLEGetAndSetLong...OK
+HeapByteBufferViewLEGetAndSetFloat...OK
+HeapByteBufferViewLEGetAndSetDouble...OK
+HeapByteBufferViewLEGetAndSetAcquireShort...OK
+HeapByteBufferViewLEGetAndSetAcquireChar...OK
+HeapByteBufferViewLEGetAndSetAcquireInt...OK
+HeapByteBufferViewLEGetAndSetAcquireLong...OK
+HeapByteBufferViewLEGetAndSetAcquireFloat...OK
+HeapByteBufferViewLEGetAndSetAcquireDouble...OK
+HeapByteBufferViewLEGetAndSetReleaseShort...OK
+HeapByteBufferViewLEGetAndSetReleaseChar...OK
+HeapByteBufferViewLEGetAndSetReleaseInt...OK
+HeapByteBufferViewLEGetAndSetReleaseLong...OK
+HeapByteBufferViewLEGetAndSetReleaseFloat...OK
+HeapByteBufferViewLEGetAndSetReleaseDouble...OK
+HeapByteBufferViewLEGetAndAddShort...OK
+HeapByteBufferViewLEGetAndAddChar...OK
+HeapByteBufferViewLEGetAndAddInt...OK
+HeapByteBufferViewLEGetAndAddLong...OK
+HeapByteBufferViewLEGetAndAddFloat...OK
+HeapByteBufferViewLEGetAndAddDouble...OK
+HeapByteBufferViewLEGetAndAddAcquireShort...OK
+HeapByteBufferViewLEGetAndAddAcquireChar...OK
+HeapByteBufferViewLEGetAndAddAcquireInt...OK
+HeapByteBufferViewLEGetAndAddAcquireLong...OK
+HeapByteBufferViewLEGetAndAddAcquireFloat...OK
+HeapByteBufferViewLEGetAndAddAcquireDouble...OK
+HeapByteBufferViewLEGetAndAddReleaseShort...OK
+HeapByteBufferViewLEGetAndAddReleaseChar...OK
+HeapByteBufferViewLEGetAndAddReleaseInt...OK
+HeapByteBufferViewLEGetAndAddReleaseLong...OK
+HeapByteBufferViewLEGetAndAddReleaseFloat...OK
+HeapByteBufferViewLEGetAndAddReleaseDouble...OK
+HeapByteBufferViewLEGetAndBitwiseOrShort...OK
+HeapByteBufferViewLEGetAndBitwiseOrChar...OK
+HeapByteBufferViewLEGetAndBitwiseOrInt...OK
+HeapByteBufferViewLEGetAndBitwiseOrLong...OK
+HeapByteBufferViewLEGetAndBitwiseOrFloat...OK
+HeapByteBufferViewLEGetAndBitwiseOrDouble...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseShort...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseChar...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseInt...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseLong...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseFloat...OK
+HeapByteBufferViewLEGetAndBitwiseOrReleaseDouble...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireShort...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireChar...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireInt...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireLong...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireFloat...OK
+HeapByteBufferViewLEGetAndBitwiseOrAcquireDouble...OK
+HeapByteBufferViewLEGetAndBitwiseAndShort...OK
+HeapByteBufferViewLEGetAndBitwiseAndChar...OK
+HeapByteBufferViewLEGetAndBitwiseAndInt...OK
+HeapByteBufferViewLEGetAndBitwiseAndLong...OK
+HeapByteBufferViewLEGetAndBitwiseAndFloat...OK
+HeapByteBufferViewLEGetAndBitwiseAndDouble...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseShort...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseChar...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseInt...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseLong...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseFloat...OK
+HeapByteBufferViewLEGetAndBitwiseAndReleaseDouble...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireShort...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireChar...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireInt...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireLong...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireFloat...OK
+HeapByteBufferViewLEGetAndBitwiseAndAcquireDouble...OK
+HeapByteBufferViewLEGetAndBitwiseXorShort...OK
+HeapByteBufferViewLEGetAndBitwiseXorChar...OK
+HeapByteBufferViewLEGetAndBitwiseXorInt...OK
+HeapByteBufferViewLEGetAndBitwiseXorLong...OK
+HeapByteBufferViewLEGetAndBitwiseXorFloat...OK
+HeapByteBufferViewLEGetAndBitwiseXorDouble...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseShort...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseChar...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseInt...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseLong...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseFloat...OK
+HeapByteBufferViewLEGetAndBitwiseXorReleaseDouble...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireShort...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireChar...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireInt...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireLong...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireFloat...OK
+HeapByteBufferViewLEGetAndBitwiseXorAcquireDouble...OK
+HeapByteBufferViewBEGetShort...OK
+HeapByteBufferViewBEGetChar...OK
+HeapByteBufferViewBEGetInt...OK
+HeapByteBufferViewBEGetLong...OK
+HeapByteBufferViewBEGetFloat...OK
+HeapByteBufferViewBEGetDouble...OK
+HeapByteBufferViewBESetShort...OK
+HeapByteBufferViewBESetChar...OK
+HeapByteBufferViewBESetInt...OK
+HeapByteBufferViewBESetLong...OK
+HeapByteBufferViewBESetFloat...OK
+HeapByteBufferViewBESetDouble...OK
+HeapByteBufferViewBEGetVolatileShort...OK
+HeapByteBufferViewBEGetVolatileChar...OK
+HeapByteBufferViewBEGetVolatileInt...OK
+HeapByteBufferViewBEGetVolatileLong...OK
+HeapByteBufferViewBEGetVolatileFloat...OK
+HeapByteBufferViewBEGetVolatileDouble...OK
+HeapByteBufferViewBESetVolatileShort...OK
+HeapByteBufferViewBESetVolatileChar...OK
+HeapByteBufferViewBESetVolatileInt...OK
+HeapByteBufferViewBESetVolatileLong...OK
+HeapByteBufferViewBESetVolatileFloat...OK
+HeapByteBufferViewBESetVolatileDouble...OK
+HeapByteBufferViewBEGetAcquireShort...OK
+HeapByteBufferViewBEGetAcquireChar...OK
+HeapByteBufferViewBEGetAcquireInt...OK
+HeapByteBufferViewBEGetAcquireLong...OK
+HeapByteBufferViewBEGetAcquireFloat...OK
+HeapByteBufferViewBEGetAcquireDouble...OK
+HeapByteBufferViewBESetReleaseShort...OK
+HeapByteBufferViewBESetReleaseChar...OK
+HeapByteBufferViewBESetReleaseInt...OK
+HeapByteBufferViewBESetReleaseLong...OK
+HeapByteBufferViewBESetReleaseFloat...OK
+HeapByteBufferViewBESetReleaseDouble...OK
+HeapByteBufferViewBEGetOpaqueShort...OK
+HeapByteBufferViewBEGetOpaqueChar...OK
+HeapByteBufferViewBEGetOpaqueInt...OK
+HeapByteBufferViewBEGetOpaqueLong...OK
+HeapByteBufferViewBEGetOpaqueFloat...OK
+HeapByteBufferViewBEGetOpaqueDouble...OK
+HeapByteBufferViewBESetOpaqueShort...OK
+HeapByteBufferViewBESetOpaqueChar...OK
+HeapByteBufferViewBESetOpaqueInt...OK
+HeapByteBufferViewBESetOpaqueLong...OK
+HeapByteBufferViewBESetOpaqueFloat...OK
+HeapByteBufferViewBESetOpaqueDouble...OK
+HeapByteBufferViewBECompareAndSetShort...OK
+HeapByteBufferViewBECompareAndSetChar...OK
+HeapByteBufferViewBECompareAndSetInt...OK
+HeapByteBufferViewBECompareAndSetLong...OK
+HeapByteBufferViewBECompareAndSetFloat...OK
+HeapByteBufferViewBECompareAndSetDouble...OK
+HeapByteBufferViewBECompareAndExchangeShort...OK
+HeapByteBufferViewBECompareAndExchangeChar...OK
+HeapByteBufferViewBECompareAndExchangeInt...OK
+HeapByteBufferViewBECompareAndExchangeLong...OK
+HeapByteBufferViewBECompareAndExchangeFloat...OK
+HeapByteBufferViewBECompareAndExchangeDouble...OK
+HeapByteBufferViewBECompareAndExchangeAcquireShort...OK
+HeapByteBufferViewBECompareAndExchangeAcquireChar...OK
+HeapByteBufferViewBECompareAndExchangeAcquireInt...OK
+HeapByteBufferViewBECompareAndExchangeAcquireLong...OK
+HeapByteBufferViewBECompareAndExchangeAcquireFloat...OK
+HeapByteBufferViewBECompareAndExchangeAcquireDouble...OK
+HeapByteBufferViewBECompareAndExchangeReleaseShort...OK
+HeapByteBufferViewBECompareAndExchangeReleaseChar...OK
+HeapByteBufferViewBECompareAndExchangeReleaseInt...OK
+HeapByteBufferViewBECompareAndExchangeReleaseLong...OK
+HeapByteBufferViewBECompareAndExchangeReleaseFloat...OK
+HeapByteBufferViewBECompareAndExchangeReleaseDouble...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainShort...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainChar...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainInt...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainLong...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainFloat...OK
+HeapByteBufferViewBEWeakCompareAndSetPlainDouble...OK
+HeapByteBufferViewBEWeakCompareAndSetShort...OK
+HeapByteBufferViewBEWeakCompareAndSetChar...OK
+HeapByteBufferViewBEWeakCompareAndSetInt...OK
+HeapByteBufferViewBEWeakCompareAndSetLong...OK
+HeapByteBufferViewBEWeakCompareAndSetFloat...OK
+HeapByteBufferViewBEWeakCompareAndSetDouble...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireShort...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireChar...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireInt...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireLong...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireFloat...OK
+HeapByteBufferViewBEWeakCompareAndSetAcquireDouble...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseShort...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseChar...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseInt...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseLong...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseFloat...OK
+HeapByteBufferViewBEWeakCompareAndSetReleaseDouble...OK
+HeapByteBufferViewBEGetAndSetShort...OK
+HeapByteBufferViewBEGetAndSetChar...OK
+HeapByteBufferViewBEGetAndSetInt...OK
+HeapByteBufferViewBEGetAndSetLong...OK
+HeapByteBufferViewBEGetAndSetFloat...OK
+HeapByteBufferViewBEGetAndSetDouble...OK
+HeapByteBufferViewBEGetAndSetAcquireShort...OK
+HeapByteBufferViewBEGetAndSetAcquireChar...OK
+HeapByteBufferViewBEGetAndSetAcquireInt...OK
+HeapByteBufferViewBEGetAndSetAcquireLong...OK
+HeapByteBufferViewBEGetAndSetAcquireFloat...OK
+HeapByteBufferViewBEGetAndSetAcquireDouble...OK
+HeapByteBufferViewBEGetAndSetReleaseShort...OK
+HeapByteBufferViewBEGetAndSetReleaseChar...OK
+HeapByteBufferViewBEGetAndSetReleaseInt...OK
+HeapByteBufferViewBEGetAndSetReleaseLong...OK
+HeapByteBufferViewBEGetAndSetReleaseFloat...OK
+HeapByteBufferViewBEGetAndSetReleaseDouble...OK
+HeapByteBufferViewBEGetAndAddShort...OK
+HeapByteBufferViewBEGetAndAddChar...OK
+HeapByteBufferViewBEGetAndAddInt...OK
+HeapByteBufferViewBEGetAndAddLong...OK
+HeapByteBufferViewBEGetAndAddFloat...OK
+HeapByteBufferViewBEGetAndAddDouble...OK
+HeapByteBufferViewBEGetAndAddAcquireShort...OK
+HeapByteBufferViewBEGetAndAddAcquireChar...OK
+HeapByteBufferViewBEGetAndAddAcquireInt...OK
+HeapByteBufferViewBEGetAndAddAcquireLong...OK
+HeapByteBufferViewBEGetAndAddAcquireFloat...OK
+HeapByteBufferViewBEGetAndAddAcquireDouble...OK
+HeapByteBufferViewBEGetAndAddReleaseShort...OK
+HeapByteBufferViewBEGetAndAddReleaseChar...OK
+HeapByteBufferViewBEGetAndAddReleaseInt...OK
+HeapByteBufferViewBEGetAndAddReleaseLong...OK
+HeapByteBufferViewBEGetAndAddReleaseFloat...OK
+HeapByteBufferViewBEGetAndAddReleaseDouble...OK
+HeapByteBufferViewBEGetAndBitwiseOrShort...OK
+HeapByteBufferViewBEGetAndBitwiseOrChar...OK
+HeapByteBufferViewBEGetAndBitwiseOrInt...OK
+HeapByteBufferViewBEGetAndBitwiseOrLong...OK
+HeapByteBufferViewBEGetAndBitwiseOrFloat...OK
+HeapByteBufferViewBEGetAndBitwiseOrDouble...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseShort...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseChar...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseInt...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseLong...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseFloat...OK
+HeapByteBufferViewBEGetAndBitwiseOrReleaseDouble...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireShort...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireChar...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireInt...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireLong...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireFloat...OK
+HeapByteBufferViewBEGetAndBitwiseOrAcquireDouble...OK
+HeapByteBufferViewBEGetAndBitwiseAndShort...OK
+HeapByteBufferViewBEGetAndBitwiseAndChar...OK
+HeapByteBufferViewBEGetAndBitwiseAndInt...OK
+HeapByteBufferViewBEGetAndBitwiseAndLong...OK
+HeapByteBufferViewBEGetAndBitwiseAndFloat...OK
+HeapByteBufferViewBEGetAndBitwiseAndDouble...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseShort...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseChar...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseInt...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseLong...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseFloat...OK
+HeapByteBufferViewBEGetAndBitwiseAndReleaseDouble...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireShort...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireChar...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireInt...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireLong...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireFloat...OK
+HeapByteBufferViewBEGetAndBitwiseAndAcquireDouble...OK
+HeapByteBufferViewBEGetAndBitwiseXorShort...OK
+HeapByteBufferViewBEGetAndBitwiseXorChar...OK
+HeapByteBufferViewBEGetAndBitwiseXorInt...OK
+HeapByteBufferViewBEGetAndBitwiseXorLong...OK
+HeapByteBufferViewBEGetAndBitwiseXorFloat...OK
+HeapByteBufferViewBEGetAndBitwiseXorDouble...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseShort...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseChar...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseInt...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseLong...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseFloat...OK
+HeapByteBufferViewBEGetAndBitwiseXorReleaseDouble...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireShort...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireChar...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireInt...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireLong...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireFloat...OK
+HeapByteBufferViewBEGetAndBitwiseXorAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEGetShort...OK
+HeapByteBufferReadOnlyViewLEGetChar...OK
+HeapByteBufferReadOnlyViewLEGetInt...OK
+HeapByteBufferReadOnlyViewLEGetLong...OK
+HeapByteBufferReadOnlyViewLEGetFloat...OK
+HeapByteBufferReadOnlyViewLEGetDouble...OK
+HeapByteBufferReadOnlyViewLESetShort...OK
+HeapByteBufferReadOnlyViewLESetChar...OK
+HeapByteBufferReadOnlyViewLESetInt...OK
+HeapByteBufferReadOnlyViewLESetLong...OK
+HeapByteBufferReadOnlyViewLESetFloat...OK
+HeapByteBufferReadOnlyViewLESetDouble...OK
+HeapByteBufferReadOnlyViewLEGetVolatileShort...OK
+HeapByteBufferReadOnlyViewLEGetVolatileChar...OK
+HeapByteBufferReadOnlyViewLEGetVolatileInt...OK
+HeapByteBufferReadOnlyViewLEGetVolatileLong...OK
+HeapByteBufferReadOnlyViewLEGetVolatileFloat...OK
+HeapByteBufferReadOnlyViewLEGetVolatileDouble...OK
+HeapByteBufferReadOnlyViewLESetVolatileShort...OK
+HeapByteBufferReadOnlyViewLESetVolatileChar...OK
+HeapByteBufferReadOnlyViewLESetVolatileInt...OK
+HeapByteBufferReadOnlyViewLESetVolatileLong...OK
+HeapByteBufferReadOnlyViewLESetVolatileFloat...OK
+HeapByteBufferReadOnlyViewLESetVolatileDouble...OK
+HeapByteBufferReadOnlyViewLEGetAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAcquireDouble...OK
+HeapByteBufferReadOnlyViewLESetReleaseShort...OK
+HeapByteBufferReadOnlyViewLESetReleaseChar...OK
+HeapByteBufferReadOnlyViewLESetReleaseInt...OK
+HeapByteBufferReadOnlyViewLESetReleaseLong...OK
+HeapByteBufferReadOnlyViewLESetReleaseFloat...OK
+HeapByteBufferReadOnlyViewLESetReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueShort...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueChar...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueInt...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueLong...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueFloat...OK
+HeapByteBufferReadOnlyViewLEGetOpaqueDouble...OK
+HeapByteBufferReadOnlyViewLESetOpaqueShort...OK
+HeapByteBufferReadOnlyViewLESetOpaqueChar...OK
+HeapByteBufferReadOnlyViewLESetOpaqueInt...OK
+HeapByteBufferReadOnlyViewLESetOpaqueLong...OK
+HeapByteBufferReadOnlyViewLESetOpaqueFloat...OK
+HeapByteBufferReadOnlyViewLESetOpaqueDouble...OK
+HeapByteBufferReadOnlyViewLECompareAndSetShort...OK
+HeapByteBufferReadOnlyViewLECompareAndSetChar...OK
+HeapByteBufferReadOnlyViewLECompareAndSetInt...OK
+HeapByteBufferReadOnlyViewLECompareAndSetLong...OK
+HeapByteBufferReadOnlyViewLECompareAndSetFloat...OK
+HeapByteBufferReadOnlyViewLECompareAndSetDouble...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeShort...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeChar...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeInt...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeLong...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeFloat...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeDouble...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireShort...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireChar...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireInt...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireLong...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireFloat...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireDouble...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseShort...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseChar...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseInt...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseLong...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseFloat...OK
+HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainShort...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainChar...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainInt...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainLong...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainFloat...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainDouble...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetShort...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetChar...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetInt...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetLong...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetFloat...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetDouble...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireShort...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireChar...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireInt...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireLong...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseShort...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseChar...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseInt...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseLong...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndSetShort...OK
+HeapByteBufferReadOnlyViewLEGetAndSetChar...OK
+HeapByteBufferReadOnlyViewLEGetAndSetInt...OK
+HeapByteBufferReadOnlyViewLEGetAndSetLong...OK
+HeapByteBufferReadOnlyViewLEGetAndSetFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndSetDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndSetAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseShort...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseChar...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseInt...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseLong...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndSetReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndAddShort...OK
+HeapByteBufferReadOnlyViewLEGetAndAddChar...OK
+HeapByteBufferReadOnlyViewLEGetAndAddInt...OK
+HeapByteBufferReadOnlyViewLEGetAndAddLong...OK
+HeapByteBufferReadOnlyViewLEGetAndAddFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndAddDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndAddAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseShort...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseChar...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseInt...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseLong...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndAddReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseDouble...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireShort...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireChar...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireInt...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireLong...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireFloat...OK
+HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEGetShort...OK
+HeapByteBufferReadOnlyViewBEGetChar...OK
+HeapByteBufferReadOnlyViewBEGetInt...OK
+HeapByteBufferReadOnlyViewBEGetLong...OK
+HeapByteBufferReadOnlyViewBEGetFloat...OK
+HeapByteBufferReadOnlyViewBEGetDouble...OK
+HeapByteBufferReadOnlyViewBESetShort...OK
+HeapByteBufferReadOnlyViewBESetChar...OK
+HeapByteBufferReadOnlyViewBESetInt...OK
+HeapByteBufferReadOnlyViewBESetLong...OK
+HeapByteBufferReadOnlyViewBESetFloat...OK
+HeapByteBufferReadOnlyViewBESetDouble...OK
+HeapByteBufferReadOnlyViewBEGetVolatileShort...OK
+HeapByteBufferReadOnlyViewBEGetVolatileChar...OK
+HeapByteBufferReadOnlyViewBEGetVolatileInt...OK
+HeapByteBufferReadOnlyViewBEGetVolatileLong...OK
+HeapByteBufferReadOnlyViewBEGetVolatileFloat...OK
+HeapByteBufferReadOnlyViewBEGetVolatileDouble...OK
+HeapByteBufferReadOnlyViewBESetVolatileShort...OK
+HeapByteBufferReadOnlyViewBESetVolatileChar...OK
+HeapByteBufferReadOnlyViewBESetVolatileInt...OK
+HeapByteBufferReadOnlyViewBESetVolatileLong...OK
+HeapByteBufferReadOnlyViewBESetVolatileFloat...OK
+HeapByteBufferReadOnlyViewBESetVolatileDouble...OK
+HeapByteBufferReadOnlyViewBEGetAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAcquireDouble...OK
+HeapByteBufferReadOnlyViewBESetReleaseShort...OK
+HeapByteBufferReadOnlyViewBESetReleaseChar...OK
+HeapByteBufferReadOnlyViewBESetReleaseInt...OK
+HeapByteBufferReadOnlyViewBESetReleaseLong...OK
+HeapByteBufferReadOnlyViewBESetReleaseFloat...OK
+HeapByteBufferReadOnlyViewBESetReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueShort...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueChar...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueInt...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueLong...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueFloat...OK
+HeapByteBufferReadOnlyViewBEGetOpaqueDouble...OK
+HeapByteBufferReadOnlyViewBESetOpaqueShort...OK
+HeapByteBufferReadOnlyViewBESetOpaqueChar...OK
+HeapByteBufferReadOnlyViewBESetOpaqueInt...OK
+HeapByteBufferReadOnlyViewBESetOpaqueLong...OK
+HeapByteBufferReadOnlyViewBESetOpaqueFloat...OK
+HeapByteBufferReadOnlyViewBESetOpaqueDouble...OK
+HeapByteBufferReadOnlyViewBECompareAndSetShort...OK
+HeapByteBufferReadOnlyViewBECompareAndSetChar...OK
+HeapByteBufferReadOnlyViewBECompareAndSetInt...OK
+HeapByteBufferReadOnlyViewBECompareAndSetLong...OK
+HeapByteBufferReadOnlyViewBECompareAndSetFloat...OK
+HeapByteBufferReadOnlyViewBECompareAndSetDouble...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeShort...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeChar...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeInt...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeLong...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeFloat...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeDouble...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireShort...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireChar...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireInt...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireLong...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireFloat...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireDouble...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseShort...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseChar...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseInt...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseLong...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseFloat...OK
+HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainShort...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainChar...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainInt...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainLong...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainFloat...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainDouble...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetShort...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetChar...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetInt...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetLong...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetFloat...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetDouble...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireShort...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireChar...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireInt...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireLong...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseShort...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseChar...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseInt...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseLong...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndSetShort...OK
+HeapByteBufferReadOnlyViewBEGetAndSetChar...OK
+HeapByteBufferReadOnlyViewBEGetAndSetInt...OK
+HeapByteBufferReadOnlyViewBEGetAndSetLong...OK
+HeapByteBufferReadOnlyViewBEGetAndSetFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndSetDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndSetAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseShort...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseChar...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseInt...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseLong...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndSetReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndAddShort...OK
+HeapByteBufferReadOnlyViewBEGetAndAddChar...OK
+HeapByteBufferReadOnlyViewBEGetAndAddInt...OK
+HeapByteBufferReadOnlyViewBEGetAndAddLong...OK
+HeapByteBufferReadOnlyViewBEGetAndAddFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndAddDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndAddAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseShort...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseChar...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseInt...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseLong...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndAddReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseDouble...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireShort...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireChar...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireInt...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireLong...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireFloat...OK
+HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireDouble...OK
+FieldGetWidget...OK
+FieldSetWidget...OK
+FieldGetVolatileWidget...OK
+FieldSetVolatileWidget...OK
+FieldGetAcquireWidget...OK
+FieldSetReleaseWidget...OK
+FieldGetOpaqueWidget...OK
+FieldSetOpaqueWidget...OK
+FieldCompareAndSetWidget...OK
+FieldCompareAndExchangeWidget...OK
+FieldCompareAndExchangeAcquireWidget...OK
+FieldCompareAndExchangeReleaseWidget...OK
+FieldWeakCompareAndSetPlainWidget...OK
+FieldWeakCompareAndSetWidget...OK
+FieldWeakCompareAndSetAcquireWidget...OK
+FieldWeakCompareAndSetReleaseWidget...OK
+FieldGetAndSetWidget...OK
+FieldGetAndSetAcquireWidget...OK
+FieldGetAndSetReleaseWidget...OK
+FieldGetAndAddWidget...OK
+FieldGetAndAddAcquireWidget...OK
+FieldGetAndAddReleaseWidget...OK
+FieldGetAndBitwiseOrWidget...OK
+FieldGetAndBitwiseOrReleaseWidget...OK
+FieldGetAndBitwiseOrAcquireWidget...OK
+FieldGetAndBitwiseAndWidget...OK
+FieldGetAndBitwiseAndReleaseWidget...OK
+FieldGetAndBitwiseAndAcquireWidget...OK
+FieldGetAndBitwiseXorWidget...OK
+FieldGetAndBitwiseXorReleaseWidget...OK
+FieldGetAndBitwiseXorAcquireWidget...OK
+FinalFieldGetWidget...OK
+FinalFieldSetWidget...OK
+FinalFieldGetVolatileWidget...OK
+FinalFieldSetVolatileWidget...OK
+FinalFieldGetAcquireWidget...OK
+FinalFieldSetReleaseWidget...OK
+FinalFieldGetOpaqueWidget...OK
+FinalFieldSetOpaqueWidget...OK
+FinalFieldCompareAndSetWidget...OK
+FinalFieldCompareAndExchangeWidget...OK
+FinalFieldCompareAndExchangeAcquireWidget...OK
+FinalFieldCompareAndExchangeReleaseWidget...OK
+FinalFieldWeakCompareAndSetPlainWidget...OK
+FinalFieldWeakCompareAndSetWidget...OK
+FinalFieldWeakCompareAndSetAcquireWidget...OK
+FinalFieldWeakCompareAndSetReleaseWidget...OK
+FinalFieldGetAndSetWidget...OK
+FinalFieldGetAndSetAcquireWidget...OK
+FinalFieldGetAndSetReleaseWidget...OK
+FinalFieldGetAndAddWidget...OK
+FinalFieldGetAndAddAcquireWidget...OK
+FinalFieldGetAndAddReleaseWidget...OK
+FinalFieldGetAndBitwiseOrWidget...OK
+FinalFieldGetAndBitwiseOrReleaseWidget...OK
+FinalFieldGetAndBitwiseOrAcquireWidget...OK
+FinalFieldGetAndBitwiseAndWidget...OK
+FinalFieldGetAndBitwiseAndReleaseWidget...OK
+FinalFieldGetAndBitwiseAndAcquireWidget...OK
+FinalFieldGetAndBitwiseXorWidget...OK
+FinalFieldGetAndBitwiseXorReleaseWidget...OK
+FinalFieldGetAndBitwiseXorAcquireWidget...OK
+StaticFieldGetWidget...OK
+StaticFieldSetWidget...OK
+StaticFieldGetVolatileWidget...OK
+StaticFieldSetVolatileWidget...OK
+StaticFieldGetAcquireWidget...OK
+StaticFieldSetReleaseWidget...OK
+StaticFieldGetOpaqueWidget...OK
+StaticFieldSetOpaqueWidget...OK
+StaticFieldCompareAndSetWidget...OK
+StaticFieldCompareAndExchangeWidget...OK
+StaticFieldCompareAndExchangeAcquireWidget...OK
+StaticFieldCompareAndExchangeReleaseWidget...OK
+StaticFieldWeakCompareAndSetPlainWidget...OK
+StaticFieldWeakCompareAndSetWidget...OK
+StaticFieldWeakCompareAndSetAcquireWidget...OK
+StaticFieldWeakCompareAndSetReleaseWidget...OK
+StaticFieldGetAndSetWidget...OK
+StaticFieldGetAndSetAcquireWidget...OK
+StaticFieldGetAndSetReleaseWidget...OK
+StaticFieldGetAndAddWidget...OK
+StaticFieldGetAndAddAcquireWidget...OK
+StaticFieldGetAndAddReleaseWidget...OK
+StaticFieldGetAndBitwiseOrWidget...OK
+StaticFieldGetAndBitwiseOrReleaseWidget...OK
+StaticFieldGetAndBitwiseOrAcquireWidget...OK
+StaticFieldGetAndBitwiseAndWidget...OK
+StaticFieldGetAndBitwiseAndReleaseWidget...OK
+StaticFieldGetAndBitwiseAndAcquireWidget...OK
+StaticFieldGetAndBitwiseXorWidget...OK
+StaticFieldGetAndBitwiseXorReleaseWidget...OK
+StaticFieldGetAndBitwiseXorAcquireWidget...OK
+StaticFinalFieldGetWidget...OK
+StaticFinalFieldSetWidget...OK
+StaticFinalFieldGetVolatileWidget...OK
+StaticFinalFieldSetVolatileWidget...OK
+StaticFinalFieldGetAcquireWidget...OK
+StaticFinalFieldSetReleaseWidget...OK
+StaticFinalFieldGetOpaqueWidget...OK
+StaticFinalFieldSetOpaqueWidget...OK
+StaticFinalFieldCompareAndSetWidget...OK
+StaticFinalFieldCompareAndExchangeWidget...OK
+StaticFinalFieldCompareAndExchangeAcquireWidget...OK
+StaticFinalFieldCompareAndExchangeReleaseWidget...OK
+StaticFinalFieldWeakCompareAndSetPlainWidget...OK
+StaticFinalFieldWeakCompareAndSetWidget...OK
+StaticFinalFieldWeakCompareAndSetAcquireWidget...OK
+StaticFinalFieldWeakCompareAndSetReleaseWidget...OK
+StaticFinalFieldGetAndSetWidget...OK
+StaticFinalFieldGetAndSetAcquireWidget...OK
+StaticFinalFieldGetAndSetReleaseWidget...OK
+StaticFinalFieldGetAndAddWidget...OK
+StaticFinalFieldGetAndAddAcquireWidget...OK
+StaticFinalFieldGetAndAddReleaseWidget...OK
+StaticFinalFieldGetAndBitwiseOrWidget...OK
+StaticFinalFieldGetAndBitwiseOrReleaseWidget...OK
+StaticFinalFieldGetAndBitwiseOrAcquireWidget...OK
+StaticFinalFieldGetAndBitwiseAndWidget...OK
+StaticFinalFieldGetAndBitwiseAndReleaseWidget...OK
+StaticFinalFieldGetAndBitwiseAndAcquireWidget...OK
+StaticFinalFieldGetAndBitwiseXorWidget...OK
+StaticFinalFieldGetAndBitwiseXorReleaseWidget...OK
+StaticFinalFieldGetAndBitwiseXorAcquireWidget...OK
+ArrayElementGetWidget...OK
+ArrayElementSetWidget...OK
+ArrayElementGetVolatileWidget...OK
+ArrayElementSetVolatileWidget...OK
+ArrayElementGetAcquireWidget...OK
+ArrayElementSetReleaseWidget...OK
+ArrayElementGetOpaqueWidget...OK
+ArrayElementSetOpaqueWidget...OK
+ArrayElementCompareAndSetWidget...OK
+ArrayElementCompareAndExchangeWidget...OK
+ArrayElementCompareAndExchangeAcquireWidget...OK
+ArrayElementCompareAndExchangeReleaseWidget...OK
+ArrayElementWeakCompareAndSetPlainWidget...OK
+ArrayElementWeakCompareAndSetWidget...OK
+ArrayElementWeakCompareAndSetAcquireWidget...OK
+ArrayElementWeakCompareAndSetReleaseWidget...OK
+ArrayElementGetAndSetWidget...OK
+ArrayElementGetAndSetAcquireWidget...OK
+ArrayElementGetAndSetReleaseWidget...OK
+ArrayElementGetAndAddWidget...OK
+ArrayElementGetAndAddAcquireWidget...OK
+ArrayElementGetAndAddReleaseWidget...OK
+ArrayElementGetAndBitwiseOrWidget...OK
+ArrayElementGetAndBitwiseOrReleaseWidget...OK
+ArrayElementGetAndBitwiseOrAcquireWidget...OK
+ArrayElementGetAndBitwiseAndWidget...OK
+ArrayElementGetAndBitwiseAndReleaseWidget...OK
+ArrayElementGetAndBitwiseAndAcquireWidget...OK
+ArrayElementGetAndBitwiseXorWidget...OK
+ArrayElementGetAndBitwiseXorReleaseWidget...OK
+ArrayElementGetAndBitwiseXorAcquireWidget...OK
+FieldGetWidgetInterface...OK
+FieldSetWidgetInterface...OK
+FieldGetVolatileWidgetInterface...OK
+FieldSetVolatileWidgetInterface...OK
+FieldGetAcquireWidgetInterface...OK
+FieldSetReleaseWidgetInterface...OK
+FieldGetOpaqueWidgetInterface...OK
+FieldSetOpaqueWidgetInterface...OK
+FieldCompareAndSetWidgetInterface...OK
+FieldCompareAndExchangeWidgetInterface...OK
+FieldCompareAndExchangeAcquireWidgetInterface...OK
+FieldCompareAndExchangeReleaseWidgetInterface...OK
+FieldWeakCompareAndSetPlainWidgetInterface...OK
+FieldWeakCompareAndSetWidgetInterface...OK
+FieldWeakCompareAndSetAcquireWidgetInterface...OK
+FieldWeakCompareAndSetReleaseWidgetInterface...OK
+FieldGetAndSetWidgetInterface...OK
+FieldGetAndSetAcquireWidgetInterface...OK
+FieldGetAndSetReleaseWidgetInterface...OK
+FieldGetAndAddWidgetInterface...OK
+FieldGetAndAddAcquireWidgetInterface...OK
+FieldGetAndAddReleaseWidgetInterface...OK
+FieldGetAndBitwiseOrWidgetInterface...OK
+FieldGetAndBitwiseOrReleaseWidgetInterface...OK
+FieldGetAndBitwiseOrAcquireWidgetInterface...OK
+FieldGetAndBitwiseAndWidgetInterface...OK
+FieldGetAndBitwiseAndReleaseWidgetInterface...OK
+FieldGetAndBitwiseAndAcquireWidgetInterface...OK
+FieldGetAndBitwiseXorWidgetInterface...OK
+FieldGetAndBitwiseXorReleaseWidgetInterface...OK
+FieldGetAndBitwiseXorAcquireWidgetInterface...OK
+FinalFieldGetWidgetInterface...OK
+FinalFieldSetWidgetInterface...OK
+FinalFieldGetVolatileWidgetInterface...OK
+FinalFieldSetVolatileWidgetInterface...OK
+FinalFieldGetAcquireWidgetInterface...OK
+FinalFieldSetReleaseWidgetInterface...OK
+FinalFieldGetOpaqueWidgetInterface...OK
+FinalFieldSetOpaqueWidgetInterface...OK
+FinalFieldCompareAndSetWidgetInterface...OK
+FinalFieldCompareAndExchangeWidgetInterface...OK
+FinalFieldCompareAndExchangeAcquireWidgetInterface...OK
+FinalFieldCompareAndExchangeReleaseWidgetInterface...OK
+FinalFieldWeakCompareAndSetPlainWidgetInterface...OK
+FinalFieldWeakCompareAndSetWidgetInterface...OK
+FinalFieldWeakCompareAndSetAcquireWidgetInterface...OK
+FinalFieldWeakCompareAndSetReleaseWidgetInterface...OK
+FinalFieldGetAndSetWidgetInterface...OK
+FinalFieldGetAndSetAcquireWidgetInterface...OK
+FinalFieldGetAndSetReleaseWidgetInterface...OK
+FinalFieldGetAndAddWidgetInterface...OK
+FinalFieldGetAndAddAcquireWidgetInterface...OK
+FinalFieldGetAndAddReleaseWidgetInterface...OK
+FinalFieldGetAndBitwiseOrWidgetInterface...OK
+FinalFieldGetAndBitwiseOrReleaseWidgetInterface...OK
+FinalFieldGetAndBitwiseOrAcquireWidgetInterface...OK
+FinalFieldGetAndBitwiseAndWidgetInterface...OK
+FinalFieldGetAndBitwiseAndReleaseWidgetInterface...OK
+FinalFieldGetAndBitwiseAndAcquireWidgetInterface...OK
+FinalFieldGetAndBitwiseXorWidgetInterface...OK
+FinalFieldGetAndBitwiseXorReleaseWidgetInterface...OK
+FinalFieldGetAndBitwiseXorAcquireWidgetInterface...OK
+StaticFieldGetWidgetInterface...OK
+StaticFieldSetWidgetInterface...OK
+StaticFieldGetVolatileWidgetInterface...OK
+StaticFieldSetVolatileWidgetInterface...OK
+StaticFieldGetAcquireWidgetInterface...OK
+StaticFieldSetReleaseWidgetInterface...OK
+StaticFieldGetOpaqueWidgetInterface...OK
+StaticFieldSetOpaqueWidgetInterface...OK
+StaticFieldCompareAndSetWidgetInterface...OK
+StaticFieldCompareAndExchangeWidgetInterface...OK
+StaticFieldCompareAndExchangeAcquireWidgetInterface...OK
+StaticFieldCompareAndExchangeReleaseWidgetInterface...OK
+StaticFieldWeakCompareAndSetPlainWidgetInterface...OK
+StaticFieldWeakCompareAndSetWidgetInterface...OK
+StaticFieldWeakCompareAndSetAcquireWidgetInterface...OK
+StaticFieldWeakCompareAndSetReleaseWidgetInterface...OK
+StaticFieldGetAndSetWidgetInterface...OK
+StaticFieldGetAndSetAcquireWidgetInterface...OK
+StaticFieldGetAndSetReleaseWidgetInterface...OK
+StaticFieldGetAndAddWidgetInterface...OK
+StaticFieldGetAndAddAcquireWidgetInterface...OK
+StaticFieldGetAndAddReleaseWidgetInterface...OK
+StaticFieldGetAndBitwiseOrWidgetInterface...OK
+StaticFieldGetAndBitwiseOrReleaseWidgetInterface...OK
+StaticFieldGetAndBitwiseOrAcquireWidgetInterface...OK
+StaticFieldGetAndBitwiseAndWidgetInterface...OK
+StaticFieldGetAndBitwiseAndReleaseWidgetInterface...OK
+StaticFieldGetAndBitwiseAndAcquireWidgetInterface...OK
+StaticFieldGetAndBitwiseXorWidgetInterface...OK
+StaticFieldGetAndBitwiseXorReleaseWidgetInterface...OK
+StaticFieldGetAndBitwiseXorAcquireWidgetInterface...OK
+StaticFinalFieldGetWidgetInterface...OK
+StaticFinalFieldSetWidgetInterface...OK
+StaticFinalFieldGetVolatileWidgetInterface...OK
+StaticFinalFieldSetVolatileWidgetInterface...OK
+StaticFinalFieldGetAcquireWidgetInterface...OK
+StaticFinalFieldSetReleaseWidgetInterface...OK
+StaticFinalFieldGetOpaqueWidgetInterface...OK
+StaticFinalFieldSetOpaqueWidgetInterface...OK
+StaticFinalFieldCompareAndSetWidgetInterface...OK
+StaticFinalFieldCompareAndExchangeWidgetInterface...OK
+StaticFinalFieldCompareAndExchangeAcquireWidgetInterface...OK
+StaticFinalFieldCompareAndExchangeReleaseWidgetInterface...OK
+StaticFinalFieldWeakCompareAndSetPlainWidgetInterface...OK
+StaticFinalFieldWeakCompareAndSetWidgetInterface...OK
+StaticFinalFieldWeakCompareAndSetAcquireWidgetInterface...OK
+StaticFinalFieldWeakCompareAndSetReleaseWidgetInterface...OK
+StaticFinalFieldGetAndSetWidgetInterface...OK
+StaticFinalFieldGetAndSetAcquireWidgetInterface...OK
+StaticFinalFieldGetAndSetReleaseWidgetInterface...OK
+StaticFinalFieldGetAndAddWidgetInterface...OK
+StaticFinalFieldGetAndAddAcquireWidgetInterface...OK
+StaticFinalFieldGetAndAddReleaseWidgetInterface...OK
+StaticFinalFieldGetAndBitwiseOrWidgetInterface...OK
+StaticFinalFieldGetAndBitwiseOrReleaseWidgetInterface...OK
+StaticFinalFieldGetAndBitwiseOrAcquireWidgetInterface...OK
+StaticFinalFieldGetAndBitwiseAndWidgetInterface...OK
+StaticFinalFieldGetAndBitwiseAndReleaseWidgetInterface...OK
+StaticFinalFieldGetAndBitwiseAndAcquireWidgetInterface...OK
+StaticFinalFieldGetAndBitwiseXorWidgetInterface...OK
+StaticFinalFieldGetAndBitwiseXorReleaseWidgetInterface...OK
+StaticFinalFieldGetAndBitwiseXorAcquireWidgetInterface...OK
+ArrayElementGetWidgetInterface...OK
+ArrayElementSetWidgetInterface...OK
+ArrayElementGetVolatileWidgetInterface...OK
+ArrayElementSetVolatileWidgetInterface...OK
+ArrayElementGetAcquireWidgetInterface...OK
+ArrayElementSetReleaseWidgetInterface...OK
+ArrayElementGetOpaqueWidgetInterface...OK
+ArrayElementSetOpaqueWidgetInterface...OK
+ArrayElementCompareAndSetWidgetInterface...OK
+ArrayElementCompareAndExchangeWidgetInterface...OK
+ArrayElementCompareAndExchangeAcquireWidgetInterface...OK
+ArrayElementCompareAndExchangeReleaseWidgetInterface...OK
+ArrayElementWeakCompareAndSetPlainWidgetInterface...OK
+ArrayElementWeakCompareAndSetWidgetInterface...OK
+ArrayElementWeakCompareAndSetAcquireWidgetInterface...OK
+ArrayElementWeakCompareAndSetReleaseWidgetInterface...OK
+ArrayElementGetAndSetWidgetInterface...OK
+ArrayElementGetAndSetAcquireWidgetInterface...OK
+ArrayElementGetAndSetReleaseWidgetInterface...OK
+ArrayElementGetAndAddWidgetInterface...OK
+ArrayElementGetAndAddAcquireWidgetInterface...OK
+ArrayElementGetAndAddReleaseWidgetInterface...OK
+ArrayElementGetAndBitwiseOrWidgetInterface...OK
+ArrayElementGetAndBitwiseOrReleaseWidgetInterface...OK
+ArrayElementGetAndBitwiseOrAcquireWidgetInterface...OK
+ArrayElementGetAndBitwiseAndWidgetInterface...OK
+ArrayElementGetAndBitwiseAndReleaseWidgetInterface...OK
+ArrayElementGetAndBitwiseAndAcquireWidgetInterface...OK
+ArrayElementGetAndBitwiseXorWidgetInterface...OK
+ArrayElementGetAndBitwiseXorReleaseWidgetInterface...OK
+ArrayElementGetAndBitwiseXorAcquireWidgetInterface...OK
+BoxingReturnGetBoolean...OK
+BoxingSetBoolean...OK
+BoxingReturnGetVolatileBoolean...OK
+BoxingSetVolatileBoolean...OK
+BoxingReturnGetAcquireBoolean...OK
+BoxingSetReleaseBoolean...OK
+BoxingReturnGetOpaqueBoolean...OK
+BoxingSetOpaqueBoolean...OK
+BoxingCompareAndSetBoolean...OK
+BoxingCompareAndExchangeBoolean...OK
+BoxingCompareAndExchangeAcquireBoolean...OK
+BoxingCompareAndExchangeReleaseBoolean...OK
+BoxingWeakCompareAndSetPlainBoolean...OK
+BoxingWeakCompareAndSetBoolean...OK
+BoxingWeakCompareAndSetAcquireBoolean...OK
+BoxingWeakCompareAndSetReleaseBoolean...OK
+BoxingGetAndSetBoolean...OK
+BoxingGetAndSetAcquireBoolean...OK
+BoxingGetAndSetReleaseBoolean...OK
+BoxingGetAndAddBoolean...OK
+BoxingGetAndAddAcquireBoolean...OK
+BoxingGetAndAddReleaseBoolean...OK
+BoxingGetAndBitwiseOrBoolean...OK
+BoxingGetAndBitwiseOrReleaseBoolean...OK
+BoxingGetAndBitwiseOrAcquireBoolean...OK
+BoxingGetAndBitwiseAndBoolean...OK
+BoxingGetAndBitwiseAndReleaseBoolean...OK
+BoxingGetAndBitwiseAndAcquireBoolean...OK
+BoxingGetAndBitwiseXorBoolean...OK
+BoxingGetAndBitwiseXorReleaseBoolean...OK
+BoxingGetAndBitwiseXorAcquireBoolean...OK
+BoxingReturnGetByte...OK
+BoxingSetByte...OK
+BoxingReturnGetVolatileByte...OK
+BoxingSetVolatileByte...OK
+BoxingReturnGetAcquireByte...OK
+BoxingSetReleaseByte...OK
+BoxingReturnGetOpaqueByte...OK
+BoxingSetOpaqueByte...OK
+BoxingCompareAndSetByte...OK
+BoxingCompareAndExchangeByte...OK
+BoxingCompareAndExchangeAcquireByte...OK
+BoxingCompareAndExchangeReleaseByte...OK
+BoxingWeakCompareAndSetPlainByte...OK
+BoxingWeakCompareAndSetByte...OK
+BoxingWeakCompareAndSetAcquireByte...OK
+BoxingWeakCompareAndSetReleaseByte...OK
+BoxingGetAndSetByte...OK
+BoxingGetAndSetAcquireByte...OK
+BoxingGetAndSetReleaseByte...OK
+BoxingGetAndAddByte...OK
+BoxingGetAndAddAcquireByte...OK
+BoxingGetAndAddReleaseByte...OK
+BoxingGetAndBitwiseOrByte...OK
+BoxingGetAndBitwiseOrReleaseByte...OK
+BoxingGetAndBitwiseOrAcquireByte...OK
+BoxingGetAndBitwiseAndByte...OK
+BoxingGetAndBitwiseAndReleaseByte...OK
+BoxingGetAndBitwiseAndAcquireByte...OK
+BoxingGetAndBitwiseXorByte...OK
+BoxingGetAndBitwiseXorReleaseByte...OK
+BoxingGetAndBitwiseXorAcquireByte...OK
+BoxingReturnGetShort...OK
+BoxingSetShort...OK
+BoxingReturnGetVolatileShort...OK
+BoxingSetVolatileShort...OK
+BoxingReturnGetAcquireShort...OK
+BoxingSetReleaseShort...OK
+BoxingReturnGetOpaqueShort...OK
+BoxingSetOpaqueShort...OK
+BoxingCompareAndSetShort...OK
+BoxingCompareAndExchangeShort...OK
+BoxingCompareAndExchangeAcquireShort...OK
+BoxingCompareAndExchangeReleaseShort...OK
+BoxingWeakCompareAndSetPlainShort...OK
+BoxingWeakCompareAndSetShort...OK
+BoxingWeakCompareAndSetAcquireShort...OK
+BoxingWeakCompareAndSetReleaseShort...OK
+BoxingGetAndSetShort...OK
+BoxingGetAndSetAcquireShort...OK
+BoxingGetAndSetReleaseShort...OK
+BoxingGetAndAddShort...OK
+BoxingGetAndAddAcquireShort...OK
+BoxingGetAndAddReleaseShort...OK
+BoxingGetAndBitwiseOrShort...OK
+BoxingGetAndBitwiseOrReleaseShort...OK
+BoxingGetAndBitwiseOrAcquireShort...OK
+BoxingGetAndBitwiseAndShort...OK
+BoxingGetAndBitwiseAndReleaseShort...OK
+BoxingGetAndBitwiseAndAcquireShort...OK
+BoxingGetAndBitwiseXorShort...OK
+BoxingGetAndBitwiseXorReleaseShort...OK
+BoxingGetAndBitwiseXorAcquireShort...OK
+BoxingReturnGetChar...OK
+BoxingSetChar...OK
+BoxingReturnGetVolatileChar...OK
+BoxingSetVolatileChar...OK
+BoxingReturnGetAcquireChar...OK
+BoxingSetReleaseChar...OK
+BoxingReturnGetOpaqueChar...OK
+BoxingSetOpaqueChar...OK
+BoxingCompareAndSetChar...OK
+BoxingCompareAndExchangeChar...OK
+BoxingCompareAndExchangeAcquireChar...OK
+BoxingCompareAndExchangeReleaseChar...OK
+BoxingWeakCompareAndSetPlainChar...OK
+BoxingWeakCompareAndSetChar...OK
+BoxingWeakCompareAndSetAcquireChar...OK
+BoxingWeakCompareAndSetReleaseChar...OK
+BoxingGetAndSetChar...OK
+BoxingGetAndSetAcquireChar...OK
+BoxingGetAndSetReleaseChar...OK
+BoxingGetAndAddChar...OK
+BoxingGetAndAddAcquireChar...OK
+BoxingGetAndAddReleaseChar...OK
+BoxingGetAndBitwiseOrChar...OK
+BoxingGetAndBitwiseOrReleaseChar...OK
+BoxingGetAndBitwiseOrAcquireChar...OK
+BoxingGetAndBitwiseAndChar...OK
+BoxingGetAndBitwiseAndReleaseChar...OK
+BoxingGetAndBitwiseAndAcquireChar...OK
+BoxingGetAndBitwiseXorChar...OK
+BoxingGetAndBitwiseXorReleaseChar...OK
+BoxingGetAndBitwiseXorAcquireChar...OK
+BoxingReturnGetInt...OK
+BoxingSetInt...OK
+BoxingReturnGetVolatileInt...OK
+BoxingSetVolatileInt...OK
+BoxingReturnGetAcquireInt...OK
+BoxingSetReleaseInt...OK
+BoxingReturnGetOpaqueInt...OK
+BoxingSetOpaqueInt...OK
+BoxingCompareAndSetInt...OK
+BoxingCompareAndExchangeInt...OK
+BoxingCompareAndExchangeAcquireInt...OK
+BoxingCompareAndExchangeReleaseInt...OK
+BoxingWeakCompareAndSetPlainInt...OK
+BoxingWeakCompareAndSetInt...OK
+BoxingWeakCompareAndSetAcquireInt...OK
+BoxingWeakCompareAndSetReleaseInt...OK
+BoxingGetAndSetInt...OK
+BoxingGetAndSetAcquireInt...OK
+BoxingGetAndSetReleaseInt...OK
+BoxingGetAndAddInt...OK
+BoxingGetAndAddAcquireInt...OK
+BoxingGetAndAddReleaseInt...OK
+BoxingGetAndBitwiseOrInt...OK
+BoxingGetAndBitwiseOrReleaseInt...OK
+BoxingGetAndBitwiseOrAcquireInt...OK
+BoxingGetAndBitwiseAndInt...OK
+BoxingGetAndBitwiseAndReleaseInt...OK
+BoxingGetAndBitwiseAndAcquireInt...OK
+BoxingGetAndBitwiseXorInt...OK
+BoxingGetAndBitwiseXorReleaseInt...OK
+BoxingGetAndBitwiseXorAcquireInt...OK
+BoxingReturnGetLong...OK
+BoxingSetLong...OK
+BoxingReturnGetVolatileLong...OK
+BoxingSetVolatileLong...OK
+BoxingReturnGetAcquireLong...OK
+BoxingSetReleaseLong...OK
+BoxingReturnGetOpaqueLong...OK
+BoxingSetOpaqueLong...OK
+BoxingCompareAndSetLong...OK
+BoxingCompareAndExchangeLong...OK
+BoxingCompareAndExchangeAcquireLong...OK
+BoxingCompareAndExchangeReleaseLong...OK
+BoxingWeakCompareAndSetPlainLong...OK
+BoxingWeakCompareAndSetLong...OK
+BoxingWeakCompareAndSetAcquireLong...OK
+BoxingWeakCompareAndSetReleaseLong...OK
+BoxingGetAndSetLong...OK
+BoxingGetAndSetAcquireLong...OK
+BoxingGetAndSetReleaseLong...OK
+BoxingGetAndAddLong...OK
+BoxingGetAndAddAcquireLong...OK
+BoxingGetAndAddReleaseLong...OK
+BoxingGetAndBitwiseOrLong...OK
+BoxingGetAndBitwiseOrReleaseLong...OK
+BoxingGetAndBitwiseOrAcquireLong...OK
+BoxingGetAndBitwiseAndLong...OK
+BoxingGetAndBitwiseAndReleaseLong...OK
+BoxingGetAndBitwiseAndAcquireLong...OK
+BoxingGetAndBitwiseXorLong...OK
+BoxingGetAndBitwiseXorReleaseLong...OK
+BoxingGetAndBitwiseXorAcquireLong...OK
+BoxingReturnGetFloat...OK
+BoxingSetFloat...OK
+BoxingReturnGetVolatileFloat...OK
+BoxingSetVolatileFloat...OK
+BoxingReturnGetAcquireFloat...OK
+BoxingSetReleaseFloat...OK
+BoxingReturnGetOpaqueFloat...OK
+BoxingSetOpaqueFloat...OK
+BoxingCompareAndSetFloat...OK
+BoxingCompareAndExchangeFloat...OK
+BoxingCompareAndExchangeAcquireFloat...OK
+BoxingCompareAndExchangeReleaseFloat...OK
+BoxingWeakCompareAndSetPlainFloat...OK
+BoxingWeakCompareAndSetFloat...OK
+BoxingWeakCompareAndSetAcquireFloat...OK
+BoxingWeakCompareAndSetReleaseFloat...OK
+BoxingGetAndSetFloat...OK
+BoxingGetAndSetAcquireFloat...OK
+BoxingGetAndSetReleaseFloat...OK
+BoxingGetAndAddFloat...OK
+BoxingGetAndAddAcquireFloat...OK
+BoxingGetAndAddReleaseFloat...OK
+BoxingGetAndBitwiseOrFloat...OK
+BoxingGetAndBitwiseOrReleaseFloat...OK
+BoxingGetAndBitwiseOrAcquireFloat...OK
+BoxingGetAndBitwiseAndFloat...OK
+BoxingGetAndBitwiseAndReleaseFloat...OK
+BoxingGetAndBitwiseAndAcquireFloat...OK
+BoxingGetAndBitwiseXorFloat...OK
+BoxingGetAndBitwiseXorReleaseFloat...OK
+BoxingGetAndBitwiseXorAcquireFloat...OK
+BoxingReturnGetDouble...OK
+BoxingSetDouble...OK
+BoxingReturnGetVolatileDouble...OK
+BoxingSetVolatileDouble...OK
+BoxingReturnGetAcquireDouble...OK
+BoxingSetReleaseDouble...OK
+BoxingReturnGetOpaqueDouble...OK
+BoxingSetOpaqueDouble...OK
+BoxingCompareAndSetDouble...OK
+BoxingCompareAndExchangeDouble...OK
+BoxingCompareAndExchangeAcquireDouble...OK
+BoxingCompareAndExchangeReleaseDouble...OK
+BoxingWeakCompareAndSetPlainDouble...OK
+BoxingWeakCompareAndSetDouble...OK
+BoxingWeakCompareAndSetAcquireDouble...OK
+BoxingWeakCompareAndSetReleaseDouble...OK
+BoxingGetAndSetDouble...OK
+BoxingGetAndSetAcquireDouble...OK
+BoxingGetAndSetReleaseDouble...OK
+BoxingGetAndAddDouble...OK
+BoxingGetAndAddAcquireDouble...OK
+BoxingGetAndAddReleaseDouble...OK
+BoxingGetAndBitwiseOrDouble...OK
+BoxingGetAndBitwiseOrReleaseDouble...OK
+BoxingGetAndBitwiseOrAcquireDouble...OK
+BoxingGetAndBitwiseAndDouble...OK
+BoxingGetAndBitwiseAndReleaseDouble...OK
+BoxingGetAndBitwiseAndAcquireDouble...OK
+BoxingGetAndBitwiseXorDouble...OK
+BoxingGetAndBitwiseXorReleaseDouble...OK
+BoxingGetAndBitwiseXorAcquireDouble...OK
+NullReceiverTest...OK
+UnsupportedAccessModeTest...OK
+WrongArgumentTypeCausingWrongMethodTypeTest...OK
+TooManyArgumentsCausingWrongMethodTypeTest...OK
+TooFewArgumentsCausingWrongMethodTypeTest...OK
+ReturnTypeCausingWrongMethodTypeTest...OK
+UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest...OK
+FieldCoordinateTypeTest...OK
+ArrayElementOutOfBoundsIndexTest...OK
+ArrayElementBadIndexTypeTest...OK
+ArrayElementNullArrayTest...OK
+ArrayElementWrongArrayTypeTest...OK
+ArrayElementMissingIndexTest...OK
+ByteArrayViewOutOfBoundsIndexTest...OK
+ByteArrayViewUnalignedAccessesIndexTest...OK
+ByteArrayViewBadIndexTypeTest...OK
+ByteArrayViewMissingIndexTest...OK
+ByteArrayViewBadByteArrayTest...OK
+ByteBufferViewOutOfBoundsIndexTest...OK
+ByteBufferViewUnalignedAccessesIndexTest...OK
+ByteBufferViewBadIndexTypeTest...OK
+ByteBufferViewMissingIndexTest...OK
+ByteBufferViewBadByteBufferTest...OK
+FieldFloatTest...OK
+FieldDoubleTest...OK
+VoidReturnTypeTest...OK
+BoxedNullBooleanThrowsNPETest...OK
+BoxedNullByteThrowsNPETest...OK
+BoxedNullCharacterThrowsNPETest...OK
+BoxedNullShortThrowsNPETest...OK
+BoxedNullIntegerThrowsNPETest...OK
+BoxedNullLongThrowsNPETest...OK
+BoxedNullFloatThrowsNPETest...OK
+BoxedNullDoubleThrowsNPETest...OK
+WideningBooleanArgumentTest...OK
+WideningByteArgumentTest...OK
+WideningCharacterArgumentTest...OK
+WideningShortArgumentTest...OK
+WideningIntegerArgumentTest...OK
+WideningLongArgumentTest...OK
+WideningFloatArgumentTest...OK
+WideningDoubleArgumentTest...OK
+WideningBooleanReturnValueTest...OK
+WideningByteReturnValueTest...OK
+WideningCharacterReturnValueTest...OK
+WideningShortReturnValueTest...OK
+WideningIntegerReturnValueTest...OK
+WideningLongReturnValueTest...OK
+WideningFloatReturnValueTest...OK
+WideningDoubleReturnValueTest...OK
+SubtypeTest...OK
+SupertypeTest...OK
+InterfaceTest...OK
+ImplicitBoxingIntegerTest...OK
+3340 successes, 0 skips, 0 failures.
diff --git a/test/712-varhandle-invocations/expected.txt b/test/712-varhandle-invocations/expected.txt
deleted file mode 100644
index af92190..0000000
--- a/test/712-varhandle-invocations/expected.txt
+++ /dev/null
@@ -1,3183 +0,0 @@
-FieldGetBoolean...OK
-FieldGetByte...OK
-FieldGetShort...OK
-FieldGetChar...OK
-FieldGetInt...OK
-FieldGetLong...OK
-FieldGetFloat...OK
-FieldGetDouble...OK
-FieldSetBoolean...OK
-FieldSetByte...OK
-FieldSetShort...OK
-FieldSetChar...OK
-FieldSetInt...OK
-FieldSetLong...OK
-FieldSetFloat...OK
-FieldSetDouble...OK
-FieldGetVolatileBoolean...OK
-FieldGetVolatileByte...OK
-FieldGetVolatileShort...OK
-FieldGetVolatileChar...OK
-FieldGetVolatileInt...OK
-FieldGetVolatileLong...OK
-FieldGetVolatileFloat...OK
-FieldGetVolatileDouble...OK
-FieldSetVolatileBoolean...OK
-FieldSetVolatileByte...OK
-FieldSetVolatileShort...OK
-FieldSetVolatileChar...OK
-FieldSetVolatileInt...OK
-FieldSetVolatileLong...OK
-FieldSetVolatileFloat...OK
-FieldSetVolatileDouble...OK
-FieldGetAcquireBoolean...OK
-FieldGetAcquireByte...OK
-FieldGetAcquireShort...OK
-FieldGetAcquireChar...OK
-FieldGetAcquireInt...OK
-FieldGetAcquireLong...OK
-FieldGetAcquireFloat...OK
-FieldGetAcquireDouble...OK
-FieldSetReleaseBoolean...OK
-FieldSetReleaseByte...OK
-FieldSetReleaseShort...OK
-FieldSetReleaseChar...OK
-FieldSetReleaseInt...OK
-FieldSetReleaseLong...OK
-FieldSetReleaseFloat...OK
-FieldSetReleaseDouble...OK
-FieldGetOpaqueBoolean...OK
-FieldGetOpaqueByte...OK
-FieldGetOpaqueShort...OK
-FieldGetOpaqueChar...OK
-FieldGetOpaqueInt...OK
-FieldGetOpaqueLong...OK
-FieldGetOpaqueFloat...OK
-FieldGetOpaqueDouble...OK
-FieldSetOpaqueBoolean...OK
-FieldSetOpaqueByte...OK
-FieldSetOpaqueShort...OK
-FieldSetOpaqueChar...OK
-FieldSetOpaqueInt...OK
-FieldSetOpaqueLong...OK
-FieldSetOpaqueFloat...OK
-FieldSetOpaqueDouble...OK
-FieldCompareAndSetBoolean...OK
-FieldCompareAndSetByte...OK
-FieldCompareAndSetShort...OK
-FieldCompareAndSetChar...OK
-FieldCompareAndSetInt...OK
-FieldCompareAndSetLong...OK
-FieldCompareAndSetFloat...OK
-FieldCompareAndSetDouble...OK
-FieldCompareAndExchangeBoolean...OK
-FieldCompareAndExchangeByte...OK
-FieldCompareAndExchangeShort...OK
-FieldCompareAndExchangeChar...OK
-FieldCompareAndExchangeInt...OK
-FieldCompareAndExchangeLong...OK
-FieldCompareAndExchangeFloat...OK
-FieldCompareAndExchangeDouble...OK
-FieldCompareAndExchangeAcquireBoolean...OK
-FieldCompareAndExchangeAcquireByte...OK
-FieldCompareAndExchangeAcquireShort...OK
-FieldCompareAndExchangeAcquireChar...OK
-FieldCompareAndExchangeAcquireInt...OK
-FieldCompareAndExchangeAcquireLong...OK
-FieldCompareAndExchangeAcquireFloat...OK
-FieldCompareAndExchangeAcquireDouble...OK
-FieldCompareAndExchangeReleaseBoolean...OK
-FieldCompareAndExchangeReleaseByte...OK
-FieldCompareAndExchangeReleaseShort...OK
-FieldCompareAndExchangeReleaseChar...OK
-FieldCompareAndExchangeReleaseInt...OK
-FieldCompareAndExchangeReleaseLong...OK
-FieldCompareAndExchangeReleaseFloat...OK
-FieldCompareAndExchangeReleaseDouble...OK
-FieldWeakCompareAndSetPlainBoolean...OK
-FieldWeakCompareAndSetPlainByte...OK
-FieldWeakCompareAndSetPlainShort...OK
-FieldWeakCompareAndSetPlainChar...OK
-FieldWeakCompareAndSetPlainInt...OK
-FieldWeakCompareAndSetPlainLong...OK
-FieldWeakCompareAndSetPlainFloat...OK
-FieldWeakCompareAndSetPlainDouble...OK
-FieldWeakCompareAndSetBoolean...OK
-FieldWeakCompareAndSetByte...OK
-FieldWeakCompareAndSetShort...OK
-FieldWeakCompareAndSetChar...OK
-FieldWeakCompareAndSetInt...OK
-FieldWeakCompareAndSetLong...OK
-FieldWeakCompareAndSetFloat...OK
-FieldWeakCompareAndSetDouble...OK
-FieldWeakCompareAndSetAcquireBoolean...OK
-FieldWeakCompareAndSetAcquireByte...OK
-FieldWeakCompareAndSetAcquireShort...OK
-FieldWeakCompareAndSetAcquireChar...OK
-FieldWeakCompareAndSetAcquireInt...OK
-FieldWeakCompareAndSetAcquireLong...OK
-FieldWeakCompareAndSetAcquireFloat...OK
-FieldWeakCompareAndSetAcquireDouble...OK
-FieldWeakCompareAndSetReleaseBoolean...OK
-FieldWeakCompareAndSetReleaseByte...OK
-FieldWeakCompareAndSetReleaseShort...OK
-FieldWeakCompareAndSetReleaseChar...OK
-FieldWeakCompareAndSetReleaseInt...OK
-FieldWeakCompareAndSetReleaseLong...OK
-FieldWeakCompareAndSetReleaseFloat...OK
-FieldWeakCompareAndSetReleaseDouble...OK
-FieldGetAndSetBoolean...OK
-FieldGetAndSetByte...OK
-FieldGetAndSetShort...OK
-FieldGetAndSetChar...OK
-FieldGetAndSetInt...OK
-FieldGetAndSetLong...OK
-FieldGetAndSetFloat...OK
-FieldGetAndSetDouble...OK
-FieldGetAndSetAcquireBoolean...OK
-FieldGetAndSetAcquireByte...OK
-FieldGetAndSetAcquireShort...OK
-FieldGetAndSetAcquireChar...OK
-FieldGetAndSetAcquireInt...OK
-FieldGetAndSetAcquireLong...OK
-FieldGetAndSetAcquireFloat...OK
-FieldGetAndSetAcquireDouble...OK
-FieldGetAndSetReleaseBoolean...OK
-FieldGetAndSetReleaseByte...OK
-FieldGetAndSetReleaseShort...OK
-FieldGetAndSetReleaseChar...OK
-FieldGetAndSetReleaseInt...OK
-FieldGetAndSetReleaseLong...OK
-FieldGetAndSetReleaseFloat...OK
-FieldGetAndSetReleaseDouble...OK
-FieldGetAndAddBoolean...OK
-FieldGetAndAddByte...OK
-FieldGetAndAddShort...OK
-FieldGetAndAddChar...OK
-FieldGetAndAddInt...OK
-FieldGetAndAddLong...OK
-FieldGetAndAddFloat...OK
-FieldGetAndAddDouble...OK
-FieldGetAndAddAcquireBoolean...OK
-FieldGetAndAddAcquireByte...OK
-FieldGetAndAddAcquireShort...OK
-FieldGetAndAddAcquireChar...OK
-FieldGetAndAddAcquireInt...OK
-FieldGetAndAddAcquireLong...OK
-FieldGetAndAddAcquireFloat...OK
-FieldGetAndAddAcquireDouble...OK
-FieldGetAndAddReleaseBoolean...OK
-FieldGetAndAddReleaseByte...OK
-FieldGetAndAddReleaseShort...OK
-FieldGetAndAddReleaseChar...OK
-FieldGetAndAddReleaseInt...OK
-FieldGetAndAddReleaseLong...OK
-FieldGetAndAddReleaseFloat...OK
-FieldGetAndAddReleaseDouble...OK
-FieldGetAndBitwiseOrBoolean...OK
-FieldGetAndBitwiseOrByte...OK
-FieldGetAndBitwiseOrShort...OK
-FieldGetAndBitwiseOrChar...OK
-FieldGetAndBitwiseOrInt...OK
-FieldGetAndBitwiseOrLong...OK
-FieldGetAndBitwiseOrFloat...OK
-FieldGetAndBitwiseOrDouble...OK
-FieldGetAndBitwiseOrReleaseBoolean...OK
-FieldGetAndBitwiseOrReleaseByte...OK
-FieldGetAndBitwiseOrReleaseShort...OK
-FieldGetAndBitwiseOrReleaseChar...OK
-FieldGetAndBitwiseOrReleaseInt...OK
-FieldGetAndBitwiseOrReleaseLong...OK
-FieldGetAndBitwiseOrReleaseFloat...OK
-FieldGetAndBitwiseOrReleaseDouble...OK
-FieldGetAndBitwiseOrAcquireBoolean...OK
-FieldGetAndBitwiseOrAcquireByte...OK
-FieldGetAndBitwiseOrAcquireShort...OK
-FieldGetAndBitwiseOrAcquireChar...OK
-FieldGetAndBitwiseOrAcquireInt...OK
-FieldGetAndBitwiseOrAcquireLong...OK
-FieldGetAndBitwiseOrAcquireFloat...OK
-FieldGetAndBitwiseOrAcquireDouble...OK
-FieldGetAndBitwiseAndBoolean...OK
-FieldGetAndBitwiseAndByte...OK
-FieldGetAndBitwiseAndShort...OK
-FieldGetAndBitwiseAndChar...OK
-FieldGetAndBitwiseAndInt...OK
-FieldGetAndBitwiseAndLong...OK
-FieldGetAndBitwiseAndFloat...OK
-FieldGetAndBitwiseAndDouble...OK
-FieldGetAndBitwiseAndReleaseBoolean...OK
-FieldGetAndBitwiseAndReleaseByte...OK
-FieldGetAndBitwiseAndReleaseShort...OK
-FieldGetAndBitwiseAndReleaseChar...OK
-FieldGetAndBitwiseAndReleaseInt...OK
-FieldGetAndBitwiseAndReleaseLong...OK
-FieldGetAndBitwiseAndReleaseFloat...OK
-FieldGetAndBitwiseAndReleaseDouble...OK
-FieldGetAndBitwiseAndAcquireBoolean...OK
-FieldGetAndBitwiseAndAcquireByte...OK
-FieldGetAndBitwiseAndAcquireShort...OK
-FieldGetAndBitwiseAndAcquireChar...OK
-FieldGetAndBitwiseAndAcquireInt...OK
-FieldGetAndBitwiseAndAcquireLong...OK
-FieldGetAndBitwiseAndAcquireFloat...OK
-FieldGetAndBitwiseAndAcquireDouble...OK
-FieldGetAndBitwiseXorBoolean...OK
-FieldGetAndBitwiseXorByte...OK
-FieldGetAndBitwiseXorShort...OK
-FieldGetAndBitwiseXorChar...OK
-FieldGetAndBitwiseXorInt...OK
-FieldGetAndBitwiseXorLong...OK
-FieldGetAndBitwiseXorFloat...OK
-FieldGetAndBitwiseXorDouble...OK
-FieldGetAndBitwiseXorReleaseBoolean...OK
-FieldGetAndBitwiseXorReleaseByte...OK
-FieldGetAndBitwiseXorReleaseShort...OK
-FieldGetAndBitwiseXorReleaseChar...OK
-FieldGetAndBitwiseXorReleaseInt...OK
-FieldGetAndBitwiseXorReleaseLong...OK
-FieldGetAndBitwiseXorReleaseFloat...OK
-FieldGetAndBitwiseXorReleaseDouble...OK
-FieldGetAndBitwiseXorAcquireBoolean...OK
-FieldGetAndBitwiseXorAcquireByte...OK
-FieldGetAndBitwiseXorAcquireShort...OK
-FieldGetAndBitwiseXorAcquireChar...OK
-FieldGetAndBitwiseXorAcquireInt...OK
-FieldGetAndBitwiseXorAcquireLong...OK
-FieldGetAndBitwiseXorAcquireFloat...OK
-FieldGetAndBitwiseXorAcquireDouble...OK
-FinalFieldGetBoolean...OK
-FinalFieldGetByte...OK
-FinalFieldGetShort...OK
-FinalFieldGetChar...OK
-FinalFieldGetInt...OK
-FinalFieldGetLong...OK
-FinalFieldGetFloat...OK
-FinalFieldGetDouble...OK
-FinalFieldSetBoolean...OK
-FinalFieldSetByte...OK
-FinalFieldSetShort...OK
-FinalFieldSetChar...OK
-FinalFieldSetInt...OK
-FinalFieldSetLong...OK
-FinalFieldSetFloat...OK
-FinalFieldSetDouble...OK
-FinalFieldGetVolatileBoolean...OK
-FinalFieldGetVolatileByte...OK
-FinalFieldGetVolatileShort...OK
-FinalFieldGetVolatileChar...OK
-FinalFieldGetVolatileInt...OK
-FinalFieldGetVolatileLong...OK
-FinalFieldGetVolatileFloat...OK
-FinalFieldGetVolatileDouble...OK
-FinalFieldSetVolatileBoolean...OK
-FinalFieldSetVolatileByte...OK
-FinalFieldSetVolatileShort...OK
-FinalFieldSetVolatileChar...OK
-FinalFieldSetVolatileInt...OK
-FinalFieldSetVolatileLong...OK
-FinalFieldSetVolatileFloat...OK
-FinalFieldSetVolatileDouble...OK
-FinalFieldGetAcquireBoolean...OK
-FinalFieldGetAcquireByte...OK
-FinalFieldGetAcquireShort...OK
-FinalFieldGetAcquireChar...OK
-FinalFieldGetAcquireInt...OK
-FinalFieldGetAcquireLong...OK
-FinalFieldGetAcquireFloat...OK
-FinalFieldGetAcquireDouble...OK
-FinalFieldSetReleaseBoolean...OK
-FinalFieldSetReleaseByte...OK
-FinalFieldSetReleaseShort...OK
-FinalFieldSetReleaseChar...OK
-FinalFieldSetReleaseInt...OK
-FinalFieldSetReleaseLong...OK
-FinalFieldSetReleaseFloat...OK
-FinalFieldSetReleaseDouble...OK
-FinalFieldGetOpaqueBoolean...OK
-FinalFieldGetOpaqueByte...OK
-FinalFieldGetOpaqueShort...OK
-FinalFieldGetOpaqueChar...OK
-FinalFieldGetOpaqueInt...OK
-FinalFieldGetOpaqueLong...OK
-FinalFieldGetOpaqueFloat...OK
-FinalFieldGetOpaqueDouble...OK
-FinalFieldSetOpaqueBoolean...OK
-FinalFieldSetOpaqueByte...OK
-FinalFieldSetOpaqueShort...OK
-FinalFieldSetOpaqueChar...OK
-FinalFieldSetOpaqueInt...OK
-FinalFieldSetOpaqueLong...OK
-FinalFieldSetOpaqueFloat...OK
-FinalFieldSetOpaqueDouble...OK
-FinalFieldCompareAndSetBoolean...OK
-FinalFieldCompareAndSetByte...OK
-FinalFieldCompareAndSetShort...OK
-FinalFieldCompareAndSetChar...OK
-FinalFieldCompareAndSetInt...OK
-FinalFieldCompareAndSetLong...OK
-FinalFieldCompareAndSetFloat...OK
-FinalFieldCompareAndSetDouble...OK
-FinalFieldCompareAndExchangeBoolean...OK
-FinalFieldCompareAndExchangeByte...OK
-FinalFieldCompareAndExchangeShort...OK
-FinalFieldCompareAndExchangeChar...OK
-FinalFieldCompareAndExchangeInt...OK
-FinalFieldCompareAndExchangeLong...OK
-FinalFieldCompareAndExchangeFloat...OK
-FinalFieldCompareAndExchangeDouble...OK
-FinalFieldCompareAndExchangeAcquireBoolean...OK
-FinalFieldCompareAndExchangeAcquireByte...OK
-FinalFieldCompareAndExchangeAcquireShort...OK
-FinalFieldCompareAndExchangeAcquireChar...OK
-FinalFieldCompareAndExchangeAcquireInt...OK
-FinalFieldCompareAndExchangeAcquireLong...OK
-FinalFieldCompareAndExchangeAcquireFloat...OK
-FinalFieldCompareAndExchangeAcquireDouble...OK
-FinalFieldCompareAndExchangeReleaseBoolean...OK
-FinalFieldCompareAndExchangeReleaseByte...OK
-FinalFieldCompareAndExchangeReleaseShort...OK
-FinalFieldCompareAndExchangeReleaseChar...OK
-FinalFieldCompareAndExchangeReleaseInt...OK
-FinalFieldCompareAndExchangeReleaseLong...OK
-FinalFieldCompareAndExchangeReleaseFloat...OK
-FinalFieldCompareAndExchangeReleaseDouble...OK
-FinalFieldWeakCompareAndSetPlainBoolean...OK
-FinalFieldWeakCompareAndSetPlainByte...OK
-FinalFieldWeakCompareAndSetPlainShort...OK
-FinalFieldWeakCompareAndSetPlainChar...OK
-FinalFieldWeakCompareAndSetPlainInt...OK
-FinalFieldWeakCompareAndSetPlainLong...OK
-FinalFieldWeakCompareAndSetPlainFloat...OK
-FinalFieldWeakCompareAndSetPlainDouble...OK
-FinalFieldWeakCompareAndSetBoolean...OK
-FinalFieldWeakCompareAndSetByte...OK
-FinalFieldWeakCompareAndSetShort...OK
-FinalFieldWeakCompareAndSetChar...OK
-FinalFieldWeakCompareAndSetInt...OK
-FinalFieldWeakCompareAndSetLong...OK
-FinalFieldWeakCompareAndSetFloat...OK
-FinalFieldWeakCompareAndSetDouble...OK
-FinalFieldWeakCompareAndSetAcquireBoolean...OK
-FinalFieldWeakCompareAndSetAcquireByte...OK
-FinalFieldWeakCompareAndSetAcquireShort...OK
-FinalFieldWeakCompareAndSetAcquireChar...OK
-FinalFieldWeakCompareAndSetAcquireInt...OK
-FinalFieldWeakCompareAndSetAcquireLong...OK
-FinalFieldWeakCompareAndSetAcquireFloat...OK
-FinalFieldWeakCompareAndSetAcquireDouble...OK
-FinalFieldWeakCompareAndSetReleaseBoolean...OK
-FinalFieldWeakCompareAndSetReleaseByte...OK
-FinalFieldWeakCompareAndSetReleaseShort...OK
-FinalFieldWeakCompareAndSetReleaseChar...OK
-FinalFieldWeakCompareAndSetReleaseInt...OK
-FinalFieldWeakCompareAndSetReleaseLong...OK
-FinalFieldWeakCompareAndSetReleaseFloat...OK
-FinalFieldWeakCompareAndSetReleaseDouble...OK
-FinalFieldGetAndSetBoolean...OK
-FinalFieldGetAndSetByte...OK
-FinalFieldGetAndSetShort...OK
-FinalFieldGetAndSetChar...OK
-FinalFieldGetAndSetInt...OK
-FinalFieldGetAndSetLong...OK
-FinalFieldGetAndSetFloat...OK
-FinalFieldGetAndSetDouble...OK
-FinalFieldGetAndSetAcquireBoolean...OK
-FinalFieldGetAndSetAcquireByte...OK
-FinalFieldGetAndSetAcquireShort...OK
-FinalFieldGetAndSetAcquireChar...OK
-FinalFieldGetAndSetAcquireInt...OK
-FinalFieldGetAndSetAcquireLong...OK
-FinalFieldGetAndSetAcquireFloat...OK
-FinalFieldGetAndSetAcquireDouble...OK
-FinalFieldGetAndSetReleaseBoolean...OK
-FinalFieldGetAndSetReleaseByte...OK
-FinalFieldGetAndSetReleaseShort...OK
-FinalFieldGetAndSetReleaseChar...OK
-FinalFieldGetAndSetReleaseInt...OK
-FinalFieldGetAndSetReleaseLong...OK
-FinalFieldGetAndSetReleaseFloat...OK
-FinalFieldGetAndSetReleaseDouble...OK
-FinalFieldGetAndAddBoolean...OK
-FinalFieldGetAndAddByte...OK
-FinalFieldGetAndAddShort...OK
-FinalFieldGetAndAddChar...OK
-FinalFieldGetAndAddInt...OK
-FinalFieldGetAndAddLong...OK
-FinalFieldGetAndAddFloat...OK
-FinalFieldGetAndAddDouble...OK
-FinalFieldGetAndAddAcquireBoolean...OK
-FinalFieldGetAndAddAcquireByte...OK
-FinalFieldGetAndAddAcquireShort...OK
-FinalFieldGetAndAddAcquireChar...OK
-FinalFieldGetAndAddAcquireInt...OK
-FinalFieldGetAndAddAcquireLong...OK
-FinalFieldGetAndAddAcquireFloat...OK
-FinalFieldGetAndAddAcquireDouble...OK
-FinalFieldGetAndAddReleaseBoolean...OK
-FinalFieldGetAndAddReleaseByte...OK
-FinalFieldGetAndAddReleaseShort...OK
-FinalFieldGetAndAddReleaseChar...OK
-FinalFieldGetAndAddReleaseInt...OK
-FinalFieldGetAndAddReleaseLong...OK
-FinalFieldGetAndAddReleaseFloat...OK
-FinalFieldGetAndAddReleaseDouble...OK
-FinalFieldGetAndBitwiseOrBoolean...OK
-FinalFieldGetAndBitwiseOrByte...OK
-FinalFieldGetAndBitwiseOrShort...OK
-FinalFieldGetAndBitwiseOrChar...OK
-FinalFieldGetAndBitwiseOrInt...OK
-FinalFieldGetAndBitwiseOrLong...OK
-FinalFieldGetAndBitwiseOrFloat...OK
-FinalFieldGetAndBitwiseOrDouble...OK
-FinalFieldGetAndBitwiseOrReleaseBoolean...OK
-FinalFieldGetAndBitwiseOrReleaseByte...OK
-FinalFieldGetAndBitwiseOrReleaseShort...OK
-FinalFieldGetAndBitwiseOrReleaseChar...OK
-FinalFieldGetAndBitwiseOrReleaseInt...OK
-FinalFieldGetAndBitwiseOrReleaseLong...OK
-FinalFieldGetAndBitwiseOrReleaseFloat...OK
-FinalFieldGetAndBitwiseOrReleaseDouble...OK
-FinalFieldGetAndBitwiseOrAcquireBoolean...OK
-FinalFieldGetAndBitwiseOrAcquireByte...OK
-FinalFieldGetAndBitwiseOrAcquireShort...OK
-FinalFieldGetAndBitwiseOrAcquireChar...OK
-FinalFieldGetAndBitwiseOrAcquireInt...OK
-FinalFieldGetAndBitwiseOrAcquireLong...OK
-FinalFieldGetAndBitwiseOrAcquireFloat...OK
-FinalFieldGetAndBitwiseOrAcquireDouble...OK
-FinalFieldGetAndBitwiseAndBoolean...OK
-FinalFieldGetAndBitwiseAndByte...OK
-FinalFieldGetAndBitwiseAndShort...OK
-FinalFieldGetAndBitwiseAndChar...OK
-FinalFieldGetAndBitwiseAndInt...OK
-FinalFieldGetAndBitwiseAndLong...OK
-FinalFieldGetAndBitwiseAndFloat...OK
-FinalFieldGetAndBitwiseAndDouble...OK
-FinalFieldGetAndBitwiseAndReleaseBoolean...OK
-FinalFieldGetAndBitwiseAndReleaseByte...OK
-FinalFieldGetAndBitwiseAndReleaseShort...OK
-FinalFieldGetAndBitwiseAndReleaseChar...OK
-FinalFieldGetAndBitwiseAndReleaseInt...OK
-FinalFieldGetAndBitwiseAndReleaseLong...OK
-FinalFieldGetAndBitwiseAndReleaseFloat...OK
-FinalFieldGetAndBitwiseAndReleaseDouble...OK
-FinalFieldGetAndBitwiseAndAcquireBoolean...OK
-FinalFieldGetAndBitwiseAndAcquireByte...OK
-FinalFieldGetAndBitwiseAndAcquireShort...OK
-FinalFieldGetAndBitwiseAndAcquireChar...OK
-FinalFieldGetAndBitwiseAndAcquireInt...OK
-FinalFieldGetAndBitwiseAndAcquireLong...OK
-FinalFieldGetAndBitwiseAndAcquireFloat...OK
-FinalFieldGetAndBitwiseAndAcquireDouble...OK
-FinalFieldGetAndBitwiseXorBoolean...OK
-FinalFieldGetAndBitwiseXorByte...OK
-FinalFieldGetAndBitwiseXorShort...OK
-FinalFieldGetAndBitwiseXorChar...OK
-FinalFieldGetAndBitwiseXorInt...OK
-FinalFieldGetAndBitwiseXorLong...OK
-FinalFieldGetAndBitwiseXorFloat...OK
-FinalFieldGetAndBitwiseXorDouble...OK
-FinalFieldGetAndBitwiseXorReleaseBoolean...OK
-FinalFieldGetAndBitwiseXorReleaseByte...OK
-FinalFieldGetAndBitwiseXorReleaseShort...OK
-FinalFieldGetAndBitwiseXorReleaseChar...OK
-FinalFieldGetAndBitwiseXorReleaseInt...OK
-FinalFieldGetAndBitwiseXorReleaseLong...OK
-FinalFieldGetAndBitwiseXorReleaseFloat...OK
-FinalFieldGetAndBitwiseXorReleaseDouble...OK
-FinalFieldGetAndBitwiseXorAcquireBoolean...OK
-FinalFieldGetAndBitwiseXorAcquireByte...OK
-FinalFieldGetAndBitwiseXorAcquireShort...OK
-FinalFieldGetAndBitwiseXorAcquireChar...OK
-FinalFieldGetAndBitwiseXorAcquireInt...OK
-FinalFieldGetAndBitwiseXorAcquireLong...OK
-FinalFieldGetAndBitwiseXorAcquireFloat...OK
-FinalFieldGetAndBitwiseXorAcquireDouble...OK
-StaticFieldGetBoolean...OK
-StaticFieldGetByte...OK
-StaticFieldGetShort...OK
-StaticFieldGetChar...OK
-StaticFieldGetInt...OK
-StaticFieldGetLong...OK
-StaticFieldGetFloat...OK
-StaticFieldGetDouble...OK
-StaticFieldSetBoolean...OK
-StaticFieldSetByte...OK
-StaticFieldSetShort...OK
-StaticFieldSetChar...OK
-StaticFieldSetInt...OK
-StaticFieldSetLong...OK
-StaticFieldSetFloat...OK
-StaticFieldSetDouble...OK
-StaticFieldGetVolatileBoolean...OK
-StaticFieldGetVolatileByte...OK
-StaticFieldGetVolatileShort...OK
-StaticFieldGetVolatileChar...OK
-StaticFieldGetVolatileInt...OK
-StaticFieldGetVolatileLong...OK
-StaticFieldGetVolatileFloat...OK
-StaticFieldGetVolatileDouble...OK
-StaticFieldSetVolatileBoolean...OK
-StaticFieldSetVolatileByte...OK
-StaticFieldSetVolatileShort...OK
-StaticFieldSetVolatileChar...OK
-StaticFieldSetVolatileInt...OK
-StaticFieldSetVolatileLong...OK
-StaticFieldSetVolatileFloat...OK
-StaticFieldSetVolatileDouble...OK
-StaticFieldGetAcquireBoolean...OK
-StaticFieldGetAcquireByte...OK
-StaticFieldGetAcquireShort...OK
-StaticFieldGetAcquireChar...OK
-StaticFieldGetAcquireInt...OK
-StaticFieldGetAcquireLong...OK
-StaticFieldGetAcquireFloat...OK
-StaticFieldGetAcquireDouble...OK
-StaticFieldSetReleaseBoolean...OK
-StaticFieldSetReleaseByte...OK
-StaticFieldSetReleaseShort...OK
-StaticFieldSetReleaseChar...OK
-StaticFieldSetReleaseInt...OK
-StaticFieldSetReleaseLong...OK
-StaticFieldSetReleaseFloat...OK
-StaticFieldSetReleaseDouble...OK
-StaticFieldGetOpaqueBoolean...OK
-StaticFieldGetOpaqueByte...OK
-StaticFieldGetOpaqueShort...OK
-StaticFieldGetOpaqueChar...OK
-StaticFieldGetOpaqueInt...OK
-StaticFieldGetOpaqueLong...OK
-StaticFieldGetOpaqueFloat...OK
-StaticFieldGetOpaqueDouble...OK
-StaticFieldSetOpaqueBoolean...OK
-StaticFieldSetOpaqueByte...OK
-StaticFieldSetOpaqueShort...OK
-StaticFieldSetOpaqueChar...OK
-StaticFieldSetOpaqueInt...OK
-StaticFieldSetOpaqueLong...OK
-StaticFieldSetOpaqueFloat...OK
-StaticFieldSetOpaqueDouble...OK
-StaticFieldCompareAndSetBoolean...OK
-StaticFieldCompareAndSetByte...OK
-StaticFieldCompareAndSetShort...OK
-StaticFieldCompareAndSetChar...OK
-StaticFieldCompareAndSetInt...OK
-StaticFieldCompareAndSetLong...OK
-StaticFieldCompareAndSetFloat...OK
-StaticFieldCompareAndSetDouble...OK
-StaticFieldCompareAndExchangeBoolean...OK
-StaticFieldCompareAndExchangeByte...OK
-StaticFieldCompareAndExchangeShort...OK
-StaticFieldCompareAndExchangeChar...OK
-StaticFieldCompareAndExchangeInt...OK
-StaticFieldCompareAndExchangeLong...OK
-StaticFieldCompareAndExchangeFloat...OK
-StaticFieldCompareAndExchangeDouble...OK
-StaticFieldCompareAndExchangeAcquireBoolean...OK
-StaticFieldCompareAndExchangeAcquireByte...OK
-StaticFieldCompareAndExchangeAcquireShort...OK
-StaticFieldCompareAndExchangeAcquireChar...OK
-StaticFieldCompareAndExchangeAcquireInt...OK
-StaticFieldCompareAndExchangeAcquireLong...OK
-StaticFieldCompareAndExchangeAcquireFloat...OK
-StaticFieldCompareAndExchangeAcquireDouble...OK
-StaticFieldCompareAndExchangeReleaseBoolean...OK
-StaticFieldCompareAndExchangeReleaseByte...OK
-StaticFieldCompareAndExchangeReleaseShort...OK
-StaticFieldCompareAndExchangeReleaseChar...OK
-StaticFieldCompareAndExchangeReleaseInt...OK
-StaticFieldCompareAndExchangeReleaseLong...OK
-StaticFieldCompareAndExchangeReleaseFloat...OK
-StaticFieldCompareAndExchangeReleaseDouble...OK
-StaticFieldWeakCompareAndSetPlainBoolean...OK
-StaticFieldWeakCompareAndSetPlainByte...OK
-StaticFieldWeakCompareAndSetPlainShort...OK
-StaticFieldWeakCompareAndSetPlainChar...OK
-StaticFieldWeakCompareAndSetPlainInt...OK
-StaticFieldWeakCompareAndSetPlainLong...OK
-StaticFieldWeakCompareAndSetPlainFloat...OK
-StaticFieldWeakCompareAndSetPlainDouble...OK
-StaticFieldWeakCompareAndSetBoolean...OK
-StaticFieldWeakCompareAndSetByte...OK
-StaticFieldWeakCompareAndSetShort...OK
-StaticFieldWeakCompareAndSetChar...OK
-StaticFieldWeakCompareAndSetInt...OK
-StaticFieldWeakCompareAndSetLong...OK
-StaticFieldWeakCompareAndSetFloat...OK
-StaticFieldWeakCompareAndSetDouble...OK
-StaticFieldWeakCompareAndSetAcquireBoolean...OK
-StaticFieldWeakCompareAndSetAcquireByte...OK
-StaticFieldWeakCompareAndSetAcquireShort...OK
-StaticFieldWeakCompareAndSetAcquireChar...OK
-StaticFieldWeakCompareAndSetAcquireInt...OK
-StaticFieldWeakCompareAndSetAcquireLong...OK
-StaticFieldWeakCompareAndSetAcquireFloat...OK
-StaticFieldWeakCompareAndSetAcquireDouble...OK
-StaticFieldWeakCompareAndSetReleaseBoolean...OK
-StaticFieldWeakCompareAndSetReleaseByte...OK
-StaticFieldWeakCompareAndSetReleaseShort...OK
-StaticFieldWeakCompareAndSetReleaseChar...OK
-StaticFieldWeakCompareAndSetReleaseInt...OK
-StaticFieldWeakCompareAndSetReleaseLong...OK
-StaticFieldWeakCompareAndSetReleaseFloat...OK
-StaticFieldWeakCompareAndSetReleaseDouble...OK
-StaticFieldGetAndSetBoolean...OK
-StaticFieldGetAndSetByte...OK
-StaticFieldGetAndSetShort...OK
-StaticFieldGetAndSetChar...OK
-StaticFieldGetAndSetInt...OK
-StaticFieldGetAndSetLong...OK
-StaticFieldGetAndSetFloat...OK
-StaticFieldGetAndSetDouble...OK
-StaticFieldGetAndSetAcquireBoolean...OK
-StaticFieldGetAndSetAcquireByte...OK
-StaticFieldGetAndSetAcquireShort...OK
-StaticFieldGetAndSetAcquireChar...OK
-StaticFieldGetAndSetAcquireInt...OK
-StaticFieldGetAndSetAcquireLong...OK
-StaticFieldGetAndSetAcquireFloat...OK
-StaticFieldGetAndSetAcquireDouble...OK
-StaticFieldGetAndSetReleaseBoolean...OK
-StaticFieldGetAndSetReleaseByte...OK
-StaticFieldGetAndSetReleaseShort...OK
-StaticFieldGetAndSetReleaseChar...OK
-StaticFieldGetAndSetReleaseInt...OK
-StaticFieldGetAndSetReleaseLong...OK
-StaticFieldGetAndSetReleaseFloat...OK
-StaticFieldGetAndSetReleaseDouble...OK
-StaticFieldGetAndAddBoolean...OK
-StaticFieldGetAndAddByte...OK
-StaticFieldGetAndAddShort...OK
-StaticFieldGetAndAddChar...OK
-StaticFieldGetAndAddInt...OK
-StaticFieldGetAndAddLong...OK
-StaticFieldGetAndAddFloat...OK
-StaticFieldGetAndAddDouble...OK
-StaticFieldGetAndAddAcquireBoolean...OK
-StaticFieldGetAndAddAcquireByte...OK
-StaticFieldGetAndAddAcquireShort...OK
-StaticFieldGetAndAddAcquireChar...OK
-StaticFieldGetAndAddAcquireInt...OK
-StaticFieldGetAndAddAcquireLong...OK
-StaticFieldGetAndAddAcquireFloat...OK
-StaticFieldGetAndAddAcquireDouble...OK
-StaticFieldGetAndAddReleaseBoolean...OK
-StaticFieldGetAndAddReleaseByte...OK
-StaticFieldGetAndAddReleaseShort...OK
-StaticFieldGetAndAddReleaseChar...OK
-StaticFieldGetAndAddReleaseInt...OK
-StaticFieldGetAndAddReleaseLong...OK
-StaticFieldGetAndAddReleaseFloat...OK
-StaticFieldGetAndAddReleaseDouble...OK
-StaticFieldGetAndBitwiseOrBoolean...OK
-StaticFieldGetAndBitwiseOrByte...OK
-StaticFieldGetAndBitwiseOrShort...OK
-StaticFieldGetAndBitwiseOrChar...OK
-StaticFieldGetAndBitwiseOrInt...OK
-StaticFieldGetAndBitwiseOrLong...OK
-StaticFieldGetAndBitwiseOrFloat...OK
-StaticFieldGetAndBitwiseOrDouble...OK
-StaticFieldGetAndBitwiseOrReleaseBoolean...OK
-StaticFieldGetAndBitwiseOrReleaseByte...OK
-StaticFieldGetAndBitwiseOrReleaseShort...OK
-StaticFieldGetAndBitwiseOrReleaseChar...OK
-StaticFieldGetAndBitwiseOrReleaseInt...OK
-StaticFieldGetAndBitwiseOrReleaseLong...OK
-StaticFieldGetAndBitwiseOrReleaseFloat...OK
-StaticFieldGetAndBitwiseOrReleaseDouble...OK
-StaticFieldGetAndBitwiseOrAcquireBoolean...OK
-StaticFieldGetAndBitwiseOrAcquireByte...OK
-StaticFieldGetAndBitwiseOrAcquireShort...OK
-StaticFieldGetAndBitwiseOrAcquireChar...OK
-StaticFieldGetAndBitwiseOrAcquireInt...OK
-StaticFieldGetAndBitwiseOrAcquireLong...OK
-StaticFieldGetAndBitwiseOrAcquireFloat...OK
-StaticFieldGetAndBitwiseOrAcquireDouble...OK
-StaticFieldGetAndBitwiseAndBoolean...OK
-StaticFieldGetAndBitwiseAndByte...OK
-StaticFieldGetAndBitwiseAndShort...OK
-StaticFieldGetAndBitwiseAndChar...OK
-StaticFieldGetAndBitwiseAndInt...OK
-StaticFieldGetAndBitwiseAndLong...OK
-StaticFieldGetAndBitwiseAndFloat...OK
-StaticFieldGetAndBitwiseAndDouble...OK
-StaticFieldGetAndBitwiseAndReleaseBoolean...OK
-StaticFieldGetAndBitwiseAndReleaseByte...OK
-StaticFieldGetAndBitwiseAndReleaseShort...OK
-StaticFieldGetAndBitwiseAndReleaseChar...OK
-StaticFieldGetAndBitwiseAndReleaseInt...OK
-StaticFieldGetAndBitwiseAndReleaseLong...OK
-StaticFieldGetAndBitwiseAndReleaseFloat...OK
-StaticFieldGetAndBitwiseAndReleaseDouble...OK
-StaticFieldGetAndBitwiseAndAcquireBoolean...OK
-StaticFieldGetAndBitwiseAndAcquireByte...OK
-StaticFieldGetAndBitwiseAndAcquireShort...OK
-StaticFieldGetAndBitwiseAndAcquireChar...OK
-StaticFieldGetAndBitwiseAndAcquireInt...OK
-StaticFieldGetAndBitwiseAndAcquireLong...OK
-StaticFieldGetAndBitwiseAndAcquireFloat...OK
-StaticFieldGetAndBitwiseAndAcquireDouble...OK
-StaticFieldGetAndBitwiseXorBoolean...OK
-StaticFieldGetAndBitwiseXorByte...OK
-StaticFieldGetAndBitwiseXorShort...OK
-StaticFieldGetAndBitwiseXorChar...OK
-StaticFieldGetAndBitwiseXorInt...OK
-StaticFieldGetAndBitwiseXorLong...OK
-StaticFieldGetAndBitwiseXorFloat...OK
-StaticFieldGetAndBitwiseXorDouble...OK
-StaticFieldGetAndBitwiseXorReleaseBoolean...OK
-StaticFieldGetAndBitwiseXorReleaseByte...OK
-StaticFieldGetAndBitwiseXorReleaseShort...OK
-StaticFieldGetAndBitwiseXorReleaseChar...OK
-StaticFieldGetAndBitwiseXorReleaseInt...OK
-StaticFieldGetAndBitwiseXorReleaseLong...OK
-StaticFieldGetAndBitwiseXorReleaseFloat...OK
-StaticFieldGetAndBitwiseXorReleaseDouble...OK
-StaticFieldGetAndBitwiseXorAcquireBoolean...OK
-StaticFieldGetAndBitwiseXorAcquireByte...OK
-StaticFieldGetAndBitwiseXorAcquireShort...OK
-StaticFieldGetAndBitwiseXorAcquireChar...OK
-StaticFieldGetAndBitwiseXorAcquireInt...OK
-StaticFieldGetAndBitwiseXorAcquireLong...OK
-StaticFieldGetAndBitwiseXorAcquireFloat...OK
-StaticFieldGetAndBitwiseXorAcquireDouble...OK
-StaticFinalFieldGetBoolean...OK
-StaticFinalFieldGetByte...OK
-StaticFinalFieldGetShort...OK
-StaticFinalFieldGetChar...OK
-StaticFinalFieldGetInt...OK
-StaticFinalFieldGetLong...OK
-StaticFinalFieldGetFloat...OK
-StaticFinalFieldGetDouble...OK
-StaticFinalFieldSetBoolean...OK
-StaticFinalFieldSetByte...OK
-StaticFinalFieldSetShort...OK
-StaticFinalFieldSetChar...OK
-StaticFinalFieldSetInt...OK
-StaticFinalFieldSetLong...OK
-StaticFinalFieldSetFloat...OK
-StaticFinalFieldSetDouble...OK
-StaticFinalFieldGetVolatileBoolean...OK
-StaticFinalFieldGetVolatileByte...OK
-StaticFinalFieldGetVolatileShort...OK
-StaticFinalFieldGetVolatileChar...OK
-StaticFinalFieldGetVolatileInt...OK
-StaticFinalFieldGetVolatileLong...OK
-StaticFinalFieldGetVolatileFloat...OK
-StaticFinalFieldGetVolatileDouble...OK
-StaticFinalFieldSetVolatileBoolean...OK
-StaticFinalFieldSetVolatileByte...OK
-StaticFinalFieldSetVolatileShort...OK
-StaticFinalFieldSetVolatileChar...OK
-StaticFinalFieldSetVolatileInt...OK
-StaticFinalFieldSetVolatileLong...OK
-StaticFinalFieldSetVolatileFloat...OK
-StaticFinalFieldSetVolatileDouble...OK
-StaticFinalFieldGetAcquireBoolean...OK
-StaticFinalFieldGetAcquireByte...OK
-StaticFinalFieldGetAcquireShort...OK
-StaticFinalFieldGetAcquireChar...OK
-StaticFinalFieldGetAcquireInt...OK
-StaticFinalFieldGetAcquireLong...OK
-StaticFinalFieldGetAcquireFloat...OK
-StaticFinalFieldGetAcquireDouble...OK
-StaticFinalFieldSetReleaseBoolean...OK
-StaticFinalFieldSetReleaseByte...OK
-StaticFinalFieldSetReleaseShort...OK
-StaticFinalFieldSetReleaseChar...OK
-StaticFinalFieldSetReleaseInt...OK
-StaticFinalFieldSetReleaseLong...OK
-StaticFinalFieldSetReleaseFloat...OK
-StaticFinalFieldSetReleaseDouble...OK
-StaticFinalFieldGetOpaqueBoolean...OK
-StaticFinalFieldGetOpaqueByte...OK
-StaticFinalFieldGetOpaqueShort...OK
-StaticFinalFieldGetOpaqueChar...OK
-StaticFinalFieldGetOpaqueInt...OK
-StaticFinalFieldGetOpaqueLong...OK
-StaticFinalFieldGetOpaqueFloat...OK
-StaticFinalFieldGetOpaqueDouble...OK
-StaticFinalFieldSetOpaqueBoolean...OK
-StaticFinalFieldSetOpaqueByte...OK
-StaticFinalFieldSetOpaqueShort...OK
-StaticFinalFieldSetOpaqueChar...OK
-StaticFinalFieldSetOpaqueInt...OK
-StaticFinalFieldSetOpaqueLong...OK
-StaticFinalFieldSetOpaqueFloat...OK
-StaticFinalFieldSetOpaqueDouble...OK
-StaticFinalFieldCompareAndSetBoolean...OK
-StaticFinalFieldCompareAndSetByte...OK
-StaticFinalFieldCompareAndSetShort...OK
-StaticFinalFieldCompareAndSetChar...OK
-StaticFinalFieldCompareAndSetInt...OK
-StaticFinalFieldCompareAndSetLong...OK
-StaticFinalFieldCompareAndSetFloat...OK
-StaticFinalFieldCompareAndSetDouble...OK
-StaticFinalFieldCompareAndExchangeBoolean...OK
-StaticFinalFieldCompareAndExchangeByte...OK
-StaticFinalFieldCompareAndExchangeShort...OK
-StaticFinalFieldCompareAndExchangeChar...OK
-StaticFinalFieldCompareAndExchangeInt...OK
-StaticFinalFieldCompareAndExchangeLong...OK
-StaticFinalFieldCompareAndExchangeFloat...OK
-StaticFinalFieldCompareAndExchangeDouble...OK
-StaticFinalFieldCompareAndExchangeAcquireBoolean...OK
-StaticFinalFieldCompareAndExchangeAcquireByte...OK
-StaticFinalFieldCompareAndExchangeAcquireShort...OK
-StaticFinalFieldCompareAndExchangeAcquireChar...OK
-StaticFinalFieldCompareAndExchangeAcquireInt...OK
-StaticFinalFieldCompareAndExchangeAcquireLong...OK
-StaticFinalFieldCompareAndExchangeAcquireFloat...OK
-StaticFinalFieldCompareAndExchangeAcquireDouble...OK
-StaticFinalFieldCompareAndExchangeReleaseBoolean...OK
-StaticFinalFieldCompareAndExchangeReleaseByte...OK
-StaticFinalFieldCompareAndExchangeReleaseShort...OK
-StaticFinalFieldCompareAndExchangeReleaseChar...OK
-StaticFinalFieldCompareAndExchangeReleaseInt...OK
-StaticFinalFieldCompareAndExchangeReleaseLong...OK
-StaticFinalFieldCompareAndExchangeReleaseFloat...OK
-StaticFinalFieldCompareAndExchangeReleaseDouble...OK
-StaticFinalFieldWeakCompareAndSetPlainBoolean...OK
-StaticFinalFieldWeakCompareAndSetPlainByte...OK
-StaticFinalFieldWeakCompareAndSetPlainShort...OK
-StaticFinalFieldWeakCompareAndSetPlainChar...OK
-StaticFinalFieldWeakCompareAndSetPlainInt...OK
-StaticFinalFieldWeakCompareAndSetPlainLong...OK
-StaticFinalFieldWeakCompareAndSetPlainFloat...OK
-StaticFinalFieldWeakCompareAndSetPlainDouble...OK
-StaticFinalFieldWeakCompareAndSetBoolean...OK
-StaticFinalFieldWeakCompareAndSetByte...OK
-StaticFinalFieldWeakCompareAndSetShort...OK
-StaticFinalFieldWeakCompareAndSetChar...OK
-StaticFinalFieldWeakCompareAndSetInt...OK
-StaticFinalFieldWeakCompareAndSetLong...OK
-StaticFinalFieldWeakCompareAndSetFloat...OK
-StaticFinalFieldWeakCompareAndSetDouble...OK
-StaticFinalFieldWeakCompareAndSetAcquireBoolean...OK
-StaticFinalFieldWeakCompareAndSetAcquireByte...OK
-StaticFinalFieldWeakCompareAndSetAcquireShort...OK
-StaticFinalFieldWeakCompareAndSetAcquireChar...OK
-StaticFinalFieldWeakCompareAndSetAcquireInt...OK
-StaticFinalFieldWeakCompareAndSetAcquireLong...OK
-StaticFinalFieldWeakCompareAndSetAcquireFloat...OK
-StaticFinalFieldWeakCompareAndSetAcquireDouble...OK
-StaticFinalFieldWeakCompareAndSetReleaseBoolean...OK
-StaticFinalFieldWeakCompareAndSetReleaseByte...OK
-StaticFinalFieldWeakCompareAndSetReleaseShort...OK
-StaticFinalFieldWeakCompareAndSetReleaseChar...OK
-StaticFinalFieldWeakCompareAndSetReleaseInt...OK
-StaticFinalFieldWeakCompareAndSetReleaseLong...OK
-StaticFinalFieldWeakCompareAndSetReleaseFloat...OK
-StaticFinalFieldWeakCompareAndSetReleaseDouble...OK
-StaticFinalFieldGetAndSetBoolean...OK
-StaticFinalFieldGetAndSetByte...OK
-StaticFinalFieldGetAndSetShort...OK
-StaticFinalFieldGetAndSetChar...OK
-StaticFinalFieldGetAndSetInt...OK
-StaticFinalFieldGetAndSetLong...OK
-StaticFinalFieldGetAndSetFloat...OK
-StaticFinalFieldGetAndSetDouble...OK
-StaticFinalFieldGetAndSetAcquireBoolean...OK
-StaticFinalFieldGetAndSetAcquireByte...OK
-StaticFinalFieldGetAndSetAcquireShort...OK
-StaticFinalFieldGetAndSetAcquireChar...OK
-StaticFinalFieldGetAndSetAcquireInt...OK
-StaticFinalFieldGetAndSetAcquireLong...OK
-StaticFinalFieldGetAndSetAcquireFloat...OK
-StaticFinalFieldGetAndSetAcquireDouble...OK
-StaticFinalFieldGetAndSetReleaseBoolean...OK
-StaticFinalFieldGetAndSetReleaseByte...OK
-StaticFinalFieldGetAndSetReleaseShort...OK
-StaticFinalFieldGetAndSetReleaseChar...OK
-StaticFinalFieldGetAndSetReleaseInt...OK
-StaticFinalFieldGetAndSetReleaseLong...OK
-StaticFinalFieldGetAndSetReleaseFloat...OK
-StaticFinalFieldGetAndSetReleaseDouble...OK
-StaticFinalFieldGetAndAddBoolean...OK
-StaticFinalFieldGetAndAddByte...OK
-StaticFinalFieldGetAndAddShort...OK
-StaticFinalFieldGetAndAddChar...OK
-StaticFinalFieldGetAndAddInt...OK
-StaticFinalFieldGetAndAddLong...OK
-StaticFinalFieldGetAndAddFloat...OK
-StaticFinalFieldGetAndAddDouble...OK
-StaticFinalFieldGetAndAddAcquireBoolean...OK
-StaticFinalFieldGetAndAddAcquireByte...OK
-StaticFinalFieldGetAndAddAcquireShort...OK
-StaticFinalFieldGetAndAddAcquireChar...OK
-StaticFinalFieldGetAndAddAcquireInt...OK
-StaticFinalFieldGetAndAddAcquireLong...OK
-StaticFinalFieldGetAndAddAcquireFloat...OK
-StaticFinalFieldGetAndAddAcquireDouble...OK
-StaticFinalFieldGetAndAddReleaseBoolean...OK
-StaticFinalFieldGetAndAddReleaseByte...OK
-StaticFinalFieldGetAndAddReleaseShort...OK
-StaticFinalFieldGetAndAddReleaseChar...OK
-StaticFinalFieldGetAndAddReleaseInt...OK
-StaticFinalFieldGetAndAddReleaseLong...OK
-StaticFinalFieldGetAndAddReleaseFloat...OK
-StaticFinalFieldGetAndAddReleaseDouble...OK
-StaticFinalFieldGetAndBitwiseOrBoolean...OK
-StaticFinalFieldGetAndBitwiseOrByte...OK
-StaticFinalFieldGetAndBitwiseOrShort...OK
-StaticFinalFieldGetAndBitwiseOrChar...OK
-StaticFinalFieldGetAndBitwiseOrInt...OK
-StaticFinalFieldGetAndBitwiseOrLong...OK
-StaticFinalFieldGetAndBitwiseOrFloat...OK
-StaticFinalFieldGetAndBitwiseOrDouble...OK
-StaticFinalFieldGetAndBitwiseOrReleaseBoolean...OK
-StaticFinalFieldGetAndBitwiseOrReleaseByte...OK
-StaticFinalFieldGetAndBitwiseOrReleaseShort...OK
-StaticFinalFieldGetAndBitwiseOrReleaseChar...OK
-StaticFinalFieldGetAndBitwiseOrReleaseInt...OK
-StaticFinalFieldGetAndBitwiseOrReleaseLong...OK
-StaticFinalFieldGetAndBitwiseOrReleaseFloat...OK
-StaticFinalFieldGetAndBitwiseOrReleaseDouble...OK
-StaticFinalFieldGetAndBitwiseOrAcquireBoolean...OK
-StaticFinalFieldGetAndBitwiseOrAcquireByte...OK
-StaticFinalFieldGetAndBitwiseOrAcquireShort...OK
-StaticFinalFieldGetAndBitwiseOrAcquireChar...OK
-StaticFinalFieldGetAndBitwiseOrAcquireInt...OK
-StaticFinalFieldGetAndBitwiseOrAcquireLong...OK
-StaticFinalFieldGetAndBitwiseOrAcquireFloat...OK
-StaticFinalFieldGetAndBitwiseOrAcquireDouble...OK
-StaticFinalFieldGetAndBitwiseAndBoolean...OK
-StaticFinalFieldGetAndBitwiseAndByte...OK
-StaticFinalFieldGetAndBitwiseAndShort...OK
-StaticFinalFieldGetAndBitwiseAndChar...OK
-StaticFinalFieldGetAndBitwiseAndInt...OK
-StaticFinalFieldGetAndBitwiseAndLong...OK
-StaticFinalFieldGetAndBitwiseAndFloat...OK
-StaticFinalFieldGetAndBitwiseAndDouble...OK
-StaticFinalFieldGetAndBitwiseAndReleaseBoolean...OK
-StaticFinalFieldGetAndBitwiseAndReleaseByte...OK
-StaticFinalFieldGetAndBitwiseAndReleaseShort...OK
-StaticFinalFieldGetAndBitwiseAndReleaseChar...OK
-StaticFinalFieldGetAndBitwiseAndReleaseInt...OK
-StaticFinalFieldGetAndBitwiseAndReleaseLong...OK
-StaticFinalFieldGetAndBitwiseAndReleaseFloat...OK
-StaticFinalFieldGetAndBitwiseAndReleaseDouble...OK
-StaticFinalFieldGetAndBitwiseAndAcquireBoolean...OK
-StaticFinalFieldGetAndBitwiseAndAcquireByte...OK
-StaticFinalFieldGetAndBitwiseAndAcquireShort...OK
-StaticFinalFieldGetAndBitwiseAndAcquireChar...OK
-StaticFinalFieldGetAndBitwiseAndAcquireInt...OK
-StaticFinalFieldGetAndBitwiseAndAcquireLong...OK
-StaticFinalFieldGetAndBitwiseAndAcquireFloat...OK
-StaticFinalFieldGetAndBitwiseAndAcquireDouble...OK
-StaticFinalFieldGetAndBitwiseXorBoolean...OK
-StaticFinalFieldGetAndBitwiseXorByte...OK
-StaticFinalFieldGetAndBitwiseXorShort...OK
-StaticFinalFieldGetAndBitwiseXorChar...OK
-StaticFinalFieldGetAndBitwiseXorInt...OK
-StaticFinalFieldGetAndBitwiseXorLong...OK
-StaticFinalFieldGetAndBitwiseXorFloat...OK
-StaticFinalFieldGetAndBitwiseXorDouble...OK
-StaticFinalFieldGetAndBitwiseXorReleaseBoolean...OK
-StaticFinalFieldGetAndBitwiseXorReleaseByte...OK
-StaticFinalFieldGetAndBitwiseXorReleaseShort...OK
-StaticFinalFieldGetAndBitwiseXorReleaseChar...OK
-StaticFinalFieldGetAndBitwiseXorReleaseInt...OK
-StaticFinalFieldGetAndBitwiseXorReleaseLong...OK
-StaticFinalFieldGetAndBitwiseXorReleaseFloat...OK
-StaticFinalFieldGetAndBitwiseXorReleaseDouble...OK
-StaticFinalFieldGetAndBitwiseXorAcquireBoolean...OK
-StaticFinalFieldGetAndBitwiseXorAcquireByte...OK
-StaticFinalFieldGetAndBitwiseXorAcquireShort...OK
-StaticFinalFieldGetAndBitwiseXorAcquireChar...OK
-StaticFinalFieldGetAndBitwiseXorAcquireInt...OK
-StaticFinalFieldGetAndBitwiseXorAcquireLong...OK
-StaticFinalFieldGetAndBitwiseXorAcquireFloat...OK
-StaticFinalFieldGetAndBitwiseXorAcquireDouble...OK
-ArrayElementGetBoolean...OK
-ArrayElementGetByte...OK
-ArrayElementGetShort...OK
-ArrayElementGetChar...OK
-ArrayElementGetInt...OK
-ArrayElementGetLong...OK
-ArrayElementGetFloat...OK
-ArrayElementGetDouble...OK
-ArrayElementSetBoolean...OK
-ArrayElementSetByte...OK
-ArrayElementSetShort...OK
-ArrayElementSetChar...OK
-ArrayElementSetInt...OK
-ArrayElementSetLong...OK
-ArrayElementSetFloat...OK
-ArrayElementSetDouble...OK
-ArrayElementGetVolatileBoolean...OK
-ArrayElementGetVolatileByte...OK
-ArrayElementGetVolatileShort...OK
-ArrayElementGetVolatileChar...OK
-ArrayElementGetVolatileInt...OK
-ArrayElementGetVolatileLong...OK
-ArrayElementGetVolatileFloat...OK
-ArrayElementGetVolatileDouble...OK
-ArrayElementSetVolatileBoolean...OK
-ArrayElementSetVolatileByte...OK
-ArrayElementSetVolatileShort...OK
-ArrayElementSetVolatileChar...OK
-ArrayElementSetVolatileInt...OK
-ArrayElementSetVolatileLong...OK
-ArrayElementSetVolatileFloat...OK
-ArrayElementSetVolatileDouble...OK
-ArrayElementGetAcquireBoolean...OK
-ArrayElementGetAcquireByte...OK
-ArrayElementGetAcquireShort...OK
-ArrayElementGetAcquireChar...OK
-ArrayElementGetAcquireInt...OK
-ArrayElementGetAcquireLong...OK
-ArrayElementGetAcquireFloat...OK
-ArrayElementGetAcquireDouble...OK
-ArrayElementSetReleaseBoolean...OK
-ArrayElementSetReleaseByte...OK
-ArrayElementSetReleaseShort...OK
-ArrayElementSetReleaseChar...OK
-ArrayElementSetReleaseInt...OK
-ArrayElementSetReleaseLong...OK
-ArrayElementSetReleaseFloat...OK
-ArrayElementSetReleaseDouble...OK
-ArrayElementGetOpaqueBoolean...OK
-ArrayElementGetOpaqueByte...OK
-ArrayElementGetOpaqueShort...OK
-ArrayElementGetOpaqueChar...OK
-ArrayElementGetOpaqueInt...OK
-ArrayElementGetOpaqueLong...OK
-ArrayElementGetOpaqueFloat...OK
-ArrayElementGetOpaqueDouble...OK
-ArrayElementSetOpaqueBoolean...OK
-ArrayElementSetOpaqueByte...OK
-ArrayElementSetOpaqueShort...OK
-ArrayElementSetOpaqueChar...OK
-ArrayElementSetOpaqueInt...OK
-ArrayElementSetOpaqueLong...OK
-ArrayElementSetOpaqueFloat...OK
-ArrayElementSetOpaqueDouble...OK
-ArrayElementCompareAndSetBoolean...OK
-ArrayElementCompareAndSetByte...OK
-ArrayElementCompareAndSetShort...OK
-ArrayElementCompareAndSetChar...OK
-ArrayElementCompareAndSetInt...OK
-ArrayElementCompareAndSetLong...OK
-ArrayElementCompareAndSetFloat...OK
-ArrayElementCompareAndSetDouble...OK
-ArrayElementCompareAndExchangeBoolean...OK
-ArrayElementCompareAndExchangeByte...OK
-ArrayElementCompareAndExchangeShort...OK
-ArrayElementCompareAndExchangeChar...OK
-ArrayElementCompareAndExchangeInt...OK
-ArrayElementCompareAndExchangeLong...OK
-ArrayElementCompareAndExchangeFloat...OK
-ArrayElementCompareAndExchangeDouble...OK
-ArrayElementCompareAndExchangeAcquireBoolean...OK
-ArrayElementCompareAndExchangeAcquireByte...OK
-ArrayElementCompareAndExchangeAcquireShort...OK
-ArrayElementCompareAndExchangeAcquireChar...OK
-ArrayElementCompareAndExchangeAcquireInt...OK
-ArrayElementCompareAndExchangeAcquireLong...OK
-ArrayElementCompareAndExchangeAcquireFloat...OK
-ArrayElementCompareAndExchangeAcquireDouble...OK
-ArrayElementCompareAndExchangeReleaseBoolean...OK
-ArrayElementCompareAndExchangeReleaseByte...OK
-ArrayElementCompareAndExchangeReleaseShort...OK
-ArrayElementCompareAndExchangeReleaseChar...OK
-ArrayElementCompareAndExchangeReleaseInt...OK
-ArrayElementCompareAndExchangeReleaseLong...OK
-ArrayElementCompareAndExchangeReleaseFloat...OK
-ArrayElementCompareAndExchangeReleaseDouble...OK
-ArrayElementWeakCompareAndSetPlainBoolean...OK
-ArrayElementWeakCompareAndSetPlainByte...OK
-ArrayElementWeakCompareAndSetPlainShort...OK
-ArrayElementWeakCompareAndSetPlainChar...OK
-ArrayElementWeakCompareAndSetPlainInt...OK
-ArrayElementWeakCompareAndSetPlainLong...OK
-ArrayElementWeakCompareAndSetPlainFloat...OK
-ArrayElementWeakCompareAndSetPlainDouble...OK
-ArrayElementWeakCompareAndSetBoolean...OK
-ArrayElementWeakCompareAndSetByte...OK
-ArrayElementWeakCompareAndSetShort...OK
-ArrayElementWeakCompareAndSetChar...OK
-ArrayElementWeakCompareAndSetInt...OK
-ArrayElementWeakCompareAndSetLong...OK
-ArrayElementWeakCompareAndSetFloat...OK
-ArrayElementWeakCompareAndSetDouble...OK
-ArrayElementWeakCompareAndSetAcquireBoolean...OK
-ArrayElementWeakCompareAndSetAcquireByte...OK
-ArrayElementWeakCompareAndSetAcquireShort...OK
-ArrayElementWeakCompareAndSetAcquireChar...OK
-ArrayElementWeakCompareAndSetAcquireInt...OK
-ArrayElementWeakCompareAndSetAcquireLong...OK
-ArrayElementWeakCompareAndSetAcquireFloat...OK
-ArrayElementWeakCompareAndSetAcquireDouble...OK
-ArrayElementWeakCompareAndSetReleaseBoolean...OK
-ArrayElementWeakCompareAndSetReleaseByte...OK
-ArrayElementWeakCompareAndSetReleaseShort...OK
-ArrayElementWeakCompareAndSetReleaseChar...OK
-ArrayElementWeakCompareAndSetReleaseInt...OK
-ArrayElementWeakCompareAndSetReleaseLong...OK
-ArrayElementWeakCompareAndSetReleaseFloat...OK
-ArrayElementWeakCompareAndSetReleaseDouble...OK
-ArrayElementGetAndSetBoolean...OK
-ArrayElementGetAndSetByte...OK
-ArrayElementGetAndSetShort...OK
-ArrayElementGetAndSetChar...OK
-ArrayElementGetAndSetInt...OK
-ArrayElementGetAndSetLong...OK
-ArrayElementGetAndSetFloat...OK
-ArrayElementGetAndSetDouble...OK
-ArrayElementGetAndSetAcquireBoolean...OK
-ArrayElementGetAndSetAcquireByte...OK
-ArrayElementGetAndSetAcquireShort...OK
-ArrayElementGetAndSetAcquireChar...OK
-ArrayElementGetAndSetAcquireInt...OK
-ArrayElementGetAndSetAcquireLong...OK
-ArrayElementGetAndSetAcquireFloat...OK
-ArrayElementGetAndSetAcquireDouble...OK
-ArrayElementGetAndSetReleaseBoolean...OK
-ArrayElementGetAndSetReleaseByte...OK
-ArrayElementGetAndSetReleaseShort...OK
-ArrayElementGetAndSetReleaseChar...OK
-ArrayElementGetAndSetReleaseInt...OK
-ArrayElementGetAndSetReleaseLong...OK
-ArrayElementGetAndSetReleaseFloat...OK
-ArrayElementGetAndSetReleaseDouble...OK
-ArrayElementGetAndAddBoolean...OK
-ArrayElementGetAndAddByte...OK
-ArrayElementGetAndAddShort...OK
-ArrayElementGetAndAddChar...OK
-ArrayElementGetAndAddInt...OK
-ArrayElementGetAndAddLong...OK
-ArrayElementGetAndAddFloat...OK
-ArrayElementGetAndAddDouble...OK
-ArrayElementGetAndAddAcquireBoolean...OK
-ArrayElementGetAndAddAcquireByte...OK
-ArrayElementGetAndAddAcquireShort...OK
-ArrayElementGetAndAddAcquireChar...OK
-ArrayElementGetAndAddAcquireInt...OK
-ArrayElementGetAndAddAcquireLong...OK
-ArrayElementGetAndAddAcquireFloat...OK
-ArrayElementGetAndAddAcquireDouble...OK
-ArrayElementGetAndAddReleaseBoolean...OK
-ArrayElementGetAndAddReleaseByte...OK
-ArrayElementGetAndAddReleaseShort...OK
-ArrayElementGetAndAddReleaseChar...OK
-ArrayElementGetAndAddReleaseInt...OK
-ArrayElementGetAndAddReleaseLong...OK
-ArrayElementGetAndAddReleaseFloat...OK
-ArrayElementGetAndAddReleaseDouble...OK
-ArrayElementGetAndBitwiseOrBoolean...OK
-ArrayElementGetAndBitwiseOrByte...OK
-ArrayElementGetAndBitwiseOrShort...OK
-ArrayElementGetAndBitwiseOrChar...OK
-ArrayElementGetAndBitwiseOrInt...OK
-ArrayElementGetAndBitwiseOrLong...OK
-ArrayElementGetAndBitwiseOrFloat...OK
-ArrayElementGetAndBitwiseOrDouble...OK
-ArrayElementGetAndBitwiseOrReleaseBoolean...OK
-ArrayElementGetAndBitwiseOrReleaseByte...OK
-ArrayElementGetAndBitwiseOrReleaseShort...OK
-ArrayElementGetAndBitwiseOrReleaseChar...OK
-ArrayElementGetAndBitwiseOrReleaseInt...OK
-ArrayElementGetAndBitwiseOrReleaseLong...OK
-ArrayElementGetAndBitwiseOrReleaseFloat...OK
-ArrayElementGetAndBitwiseOrReleaseDouble...OK
-ArrayElementGetAndBitwiseOrAcquireBoolean...OK
-ArrayElementGetAndBitwiseOrAcquireByte...OK
-ArrayElementGetAndBitwiseOrAcquireShort...OK
-ArrayElementGetAndBitwiseOrAcquireChar...OK
-ArrayElementGetAndBitwiseOrAcquireInt...OK
-ArrayElementGetAndBitwiseOrAcquireLong...OK
-ArrayElementGetAndBitwiseOrAcquireFloat...OK
-ArrayElementGetAndBitwiseOrAcquireDouble...OK
-ArrayElementGetAndBitwiseAndBoolean...OK
-ArrayElementGetAndBitwiseAndByte...OK
-ArrayElementGetAndBitwiseAndShort...OK
-ArrayElementGetAndBitwiseAndChar...OK
-ArrayElementGetAndBitwiseAndInt...OK
-ArrayElementGetAndBitwiseAndLong...OK
-ArrayElementGetAndBitwiseAndFloat...OK
-ArrayElementGetAndBitwiseAndDouble...OK
-ArrayElementGetAndBitwiseAndReleaseBoolean...OK
-ArrayElementGetAndBitwiseAndReleaseByte...OK
-ArrayElementGetAndBitwiseAndReleaseShort...OK
-ArrayElementGetAndBitwiseAndReleaseChar...OK
-ArrayElementGetAndBitwiseAndReleaseInt...OK
-ArrayElementGetAndBitwiseAndReleaseLong...OK
-ArrayElementGetAndBitwiseAndReleaseFloat...OK
-ArrayElementGetAndBitwiseAndReleaseDouble...OK
-ArrayElementGetAndBitwiseAndAcquireBoolean...OK
-ArrayElementGetAndBitwiseAndAcquireByte...OK
-ArrayElementGetAndBitwiseAndAcquireShort...OK
-ArrayElementGetAndBitwiseAndAcquireChar...OK
-ArrayElementGetAndBitwiseAndAcquireInt...OK
-ArrayElementGetAndBitwiseAndAcquireLong...OK
-ArrayElementGetAndBitwiseAndAcquireFloat...OK
-ArrayElementGetAndBitwiseAndAcquireDouble...OK
-ArrayElementGetAndBitwiseXorBoolean...OK
-ArrayElementGetAndBitwiseXorByte...OK
-ArrayElementGetAndBitwiseXorShort...OK
-ArrayElementGetAndBitwiseXorChar...OK
-ArrayElementGetAndBitwiseXorInt...OK
-ArrayElementGetAndBitwiseXorLong...OK
-ArrayElementGetAndBitwiseXorFloat...OK
-ArrayElementGetAndBitwiseXorDouble...OK
-ArrayElementGetAndBitwiseXorReleaseBoolean...OK
-ArrayElementGetAndBitwiseXorReleaseByte...OK
-ArrayElementGetAndBitwiseXorReleaseShort...OK
-ArrayElementGetAndBitwiseXorReleaseChar...OK
-ArrayElementGetAndBitwiseXorReleaseInt...OK
-ArrayElementGetAndBitwiseXorReleaseLong...OK
-ArrayElementGetAndBitwiseXorReleaseFloat...OK
-ArrayElementGetAndBitwiseXorReleaseDouble...OK
-ArrayElementGetAndBitwiseXorAcquireBoolean...OK
-ArrayElementGetAndBitwiseXorAcquireByte...OK
-ArrayElementGetAndBitwiseXorAcquireShort...OK
-ArrayElementGetAndBitwiseXorAcquireChar...OK
-ArrayElementGetAndBitwiseXorAcquireInt...OK
-ArrayElementGetAndBitwiseXorAcquireLong...OK
-ArrayElementGetAndBitwiseXorAcquireFloat...OK
-ArrayElementGetAndBitwiseXorAcquireDouble...OK
-ByteArrayViewLEGetShort...OK
-ByteArrayViewLEGetChar...OK
-ByteArrayViewLEGetInt...OK
-ByteArrayViewLEGetLong...OK
-ByteArrayViewLEGetFloat...OK
-ByteArrayViewLEGetDouble...OK
-ByteArrayViewLESetShort...OK
-ByteArrayViewLESetChar...OK
-ByteArrayViewLESetInt...OK
-ByteArrayViewLESetLong...OK
-ByteArrayViewLESetFloat...OK
-ByteArrayViewLESetDouble...OK
-ByteArrayViewLEGetVolatileShort...OK
-ByteArrayViewLEGetVolatileChar...OK
-ByteArrayViewLEGetVolatileInt...OK
-ByteArrayViewLEGetVolatileLong...OK
-ByteArrayViewLEGetVolatileFloat...OK
-ByteArrayViewLEGetVolatileDouble...OK
-ByteArrayViewLESetVolatileShort...OK
-ByteArrayViewLESetVolatileChar...OK
-ByteArrayViewLESetVolatileInt...OK
-ByteArrayViewLESetVolatileLong...OK
-ByteArrayViewLESetVolatileFloat...OK
-ByteArrayViewLESetVolatileDouble...OK
-ByteArrayViewLEGetAcquireShort...OK
-ByteArrayViewLEGetAcquireChar...OK
-ByteArrayViewLEGetAcquireInt...OK
-ByteArrayViewLEGetAcquireLong...OK
-ByteArrayViewLEGetAcquireFloat...OK
-ByteArrayViewLEGetAcquireDouble...OK
-ByteArrayViewLESetReleaseShort...OK
-ByteArrayViewLESetReleaseChar...OK
-ByteArrayViewLESetReleaseInt...OK
-ByteArrayViewLESetReleaseLong...OK
-ByteArrayViewLESetReleaseFloat...OK
-ByteArrayViewLESetReleaseDouble...OK
-ByteArrayViewLEGetOpaqueShort...OK
-ByteArrayViewLEGetOpaqueChar...OK
-ByteArrayViewLEGetOpaqueInt...OK
-ByteArrayViewLEGetOpaqueLong...OK
-ByteArrayViewLEGetOpaqueFloat...OK
-ByteArrayViewLEGetOpaqueDouble...OK
-ByteArrayViewLESetOpaqueShort...OK
-ByteArrayViewLESetOpaqueChar...OK
-ByteArrayViewLESetOpaqueInt...OK
-ByteArrayViewLESetOpaqueLong...OK
-ByteArrayViewLESetOpaqueFloat...OK
-ByteArrayViewLESetOpaqueDouble...OK
-ByteArrayViewLECompareAndSetShort...OK
-ByteArrayViewLECompareAndSetChar...OK
-ByteArrayViewLECompareAndSetInt...OK
-ByteArrayViewLECompareAndSetLong...OK
-ByteArrayViewLECompareAndSetFloat...OK
-ByteArrayViewLECompareAndSetDouble...OK
-ByteArrayViewLECompareAndExchangeShort...OK
-ByteArrayViewLECompareAndExchangeChar...OK
-ByteArrayViewLECompareAndExchangeInt...OK
-ByteArrayViewLECompareAndExchangeLong...OK
-ByteArrayViewLECompareAndExchangeFloat...OK
-ByteArrayViewLECompareAndExchangeDouble...OK
-ByteArrayViewLECompareAndExchangeAcquireShort...OK
-ByteArrayViewLECompareAndExchangeAcquireChar...OK
-ByteArrayViewLECompareAndExchangeAcquireInt...OK
-ByteArrayViewLECompareAndExchangeAcquireLong...OK
-ByteArrayViewLECompareAndExchangeAcquireFloat...OK
-ByteArrayViewLECompareAndExchangeAcquireDouble...OK
-ByteArrayViewLECompareAndExchangeReleaseShort...OK
-ByteArrayViewLECompareAndExchangeReleaseChar...OK
-ByteArrayViewLECompareAndExchangeReleaseInt...OK
-ByteArrayViewLECompareAndExchangeReleaseLong...OK
-ByteArrayViewLECompareAndExchangeReleaseFloat...OK
-ByteArrayViewLECompareAndExchangeReleaseDouble...OK
-ByteArrayViewLEWeakCompareAndSetPlainShort...OK
-ByteArrayViewLEWeakCompareAndSetPlainChar...OK
-ByteArrayViewLEWeakCompareAndSetPlainInt...OK
-ByteArrayViewLEWeakCompareAndSetPlainLong...OK
-ByteArrayViewLEWeakCompareAndSetPlainFloat...OK
-ByteArrayViewLEWeakCompareAndSetPlainDouble...OK
-ByteArrayViewLEWeakCompareAndSetShort...OK
-ByteArrayViewLEWeakCompareAndSetChar...OK
-ByteArrayViewLEWeakCompareAndSetInt...OK
-ByteArrayViewLEWeakCompareAndSetLong...OK
-ByteArrayViewLEWeakCompareAndSetFloat...OK
-ByteArrayViewLEWeakCompareAndSetDouble...OK
-ByteArrayViewLEWeakCompareAndSetAcquireShort...OK
-ByteArrayViewLEWeakCompareAndSetAcquireChar...OK
-ByteArrayViewLEWeakCompareAndSetAcquireInt...OK
-ByteArrayViewLEWeakCompareAndSetAcquireLong...OK
-ByteArrayViewLEWeakCompareAndSetAcquireFloat...OK
-ByteArrayViewLEWeakCompareAndSetAcquireDouble...OK
-ByteArrayViewLEWeakCompareAndSetReleaseShort...OK
-ByteArrayViewLEWeakCompareAndSetReleaseChar...OK
-ByteArrayViewLEWeakCompareAndSetReleaseInt...OK
-ByteArrayViewLEWeakCompareAndSetReleaseLong...OK
-ByteArrayViewLEWeakCompareAndSetReleaseFloat...OK
-ByteArrayViewLEWeakCompareAndSetReleaseDouble...OK
-ByteArrayViewLEGetAndSetShort...OK
-ByteArrayViewLEGetAndSetChar...OK
-ByteArrayViewLEGetAndSetInt...OK
-ByteArrayViewLEGetAndSetLong...OK
-ByteArrayViewLEGetAndSetFloat...OK
-ByteArrayViewLEGetAndSetDouble...OK
-ByteArrayViewLEGetAndSetAcquireShort...OK
-ByteArrayViewLEGetAndSetAcquireChar...OK
-ByteArrayViewLEGetAndSetAcquireInt...OK
-ByteArrayViewLEGetAndSetAcquireLong...OK
-ByteArrayViewLEGetAndSetAcquireFloat...OK
-ByteArrayViewLEGetAndSetAcquireDouble...OK
-ByteArrayViewLEGetAndSetReleaseShort...OK
-ByteArrayViewLEGetAndSetReleaseChar...OK
-ByteArrayViewLEGetAndSetReleaseInt...OK
-ByteArrayViewLEGetAndSetReleaseLong...OK
-ByteArrayViewLEGetAndSetReleaseFloat...OK
-ByteArrayViewLEGetAndSetReleaseDouble...OK
-ByteArrayViewLEGetAndAddShort...OK
-ByteArrayViewLEGetAndAddChar...OK
-ByteArrayViewLEGetAndAddInt...OK
-ByteArrayViewLEGetAndAddLong...OK
-ByteArrayViewLEGetAndAddFloat...OK
-ByteArrayViewLEGetAndAddDouble...OK
-ByteArrayViewLEGetAndAddAcquireShort...OK
-ByteArrayViewLEGetAndAddAcquireChar...OK
-ByteArrayViewLEGetAndAddAcquireInt...OK
-ByteArrayViewLEGetAndAddAcquireLong...OK
-ByteArrayViewLEGetAndAddAcquireFloat...OK
-ByteArrayViewLEGetAndAddAcquireDouble...OK
-ByteArrayViewLEGetAndAddReleaseShort...OK
-ByteArrayViewLEGetAndAddReleaseChar...OK
-ByteArrayViewLEGetAndAddReleaseInt...OK
-ByteArrayViewLEGetAndAddReleaseLong...OK
-ByteArrayViewLEGetAndAddReleaseFloat...OK
-ByteArrayViewLEGetAndAddReleaseDouble...OK
-ByteArrayViewLEGetAndBitwiseOrShort...OK
-ByteArrayViewLEGetAndBitwiseOrChar...OK
-ByteArrayViewLEGetAndBitwiseOrInt...OK
-ByteArrayViewLEGetAndBitwiseOrLong...OK
-ByteArrayViewLEGetAndBitwiseOrFloat...OK
-ByteArrayViewLEGetAndBitwiseOrDouble...OK
-ByteArrayViewLEGetAndBitwiseOrReleaseShort...OK
-ByteArrayViewLEGetAndBitwiseOrReleaseChar...OK
-ByteArrayViewLEGetAndBitwiseOrReleaseInt...OK
-ByteArrayViewLEGetAndBitwiseOrReleaseLong...OK
-ByteArrayViewLEGetAndBitwiseOrReleaseFloat...OK
-ByteArrayViewLEGetAndBitwiseOrReleaseDouble...OK
-ByteArrayViewLEGetAndBitwiseOrAcquireShort...OK
-ByteArrayViewLEGetAndBitwiseOrAcquireChar...OK
-ByteArrayViewLEGetAndBitwiseOrAcquireInt...OK
-ByteArrayViewLEGetAndBitwiseOrAcquireLong...OK
-ByteArrayViewLEGetAndBitwiseOrAcquireFloat...OK
-ByteArrayViewLEGetAndBitwiseOrAcquireDouble...OK
-ByteArrayViewLEGetAndBitwiseAndShort...OK
-ByteArrayViewLEGetAndBitwiseAndChar...OK
-ByteArrayViewLEGetAndBitwiseAndInt...OK
-ByteArrayViewLEGetAndBitwiseAndLong...OK
-ByteArrayViewLEGetAndBitwiseAndFloat...OK
-ByteArrayViewLEGetAndBitwiseAndDouble...OK
-ByteArrayViewLEGetAndBitwiseAndReleaseShort...OK
-ByteArrayViewLEGetAndBitwiseAndReleaseChar...OK
-ByteArrayViewLEGetAndBitwiseAndReleaseInt...OK
-ByteArrayViewLEGetAndBitwiseAndReleaseLong...OK
-ByteArrayViewLEGetAndBitwiseAndReleaseFloat...OK
-ByteArrayViewLEGetAndBitwiseAndReleaseDouble...OK
-ByteArrayViewLEGetAndBitwiseAndAcquireShort...OK
-ByteArrayViewLEGetAndBitwiseAndAcquireChar...OK
-ByteArrayViewLEGetAndBitwiseAndAcquireInt...OK
-ByteArrayViewLEGetAndBitwiseAndAcquireLong...OK
-ByteArrayViewLEGetAndBitwiseAndAcquireFloat...OK
-ByteArrayViewLEGetAndBitwiseAndAcquireDouble...OK
-ByteArrayViewLEGetAndBitwiseXorShort...OK
-ByteArrayViewLEGetAndBitwiseXorChar...OK
-ByteArrayViewLEGetAndBitwiseXorInt...OK
-ByteArrayViewLEGetAndBitwiseXorLong...OK
-ByteArrayViewLEGetAndBitwiseXorFloat...OK
-ByteArrayViewLEGetAndBitwiseXorDouble...OK
-ByteArrayViewLEGetAndBitwiseXorReleaseShort...OK
-ByteArrayViewLEGetAndBitwiseXorReleaseChar...OK
-ByteArrayViewLEGetAndBitwiseXorReleaseInt...OK
-ByteArrayViewLEGetAndBitwiseXorReleaseLong...OK
-ByteArrayViewLEGetAndBitwiseXorReleaseFloat...OK
-ByteArrayViewLEGetAndBitwiseXorReleaseDouble...OK
-ByteArrayViewLEGetAndBitwiseXorAcquireShort...OK
-ByteArrayViewLEGetAndBitwiseXorAcquireChar...OK
-ByteArrayViewLEGetAndBitwiseXorAcquireInt...OK
-ByteArrayViewLEGetAndBitwiseXorAcquireLong...OK
-ByteArrayViewLEGetAndBitwiseXorAcquireFloat...OK
-ByteArrayViewLEGetAndBitwiseXorAcquireDouble...OK
-ByteArrayViewBEGetShort...OK
-ByteArrayViewBEGetChar...OK
-ByteArrayViewBEGetInt...OK
-ByteArrayViewBEGetLong...OK
-ByteArrayViewBEGetFloat...OK
-ByteArrayViewBEGetDouble...OK
-ByteArrayViewBESetShort...OK
-ByteArrayViewBESetChar...OK
-ByteArrayViewBESetInt...OK
-ByteArrayViewBESetLong...OK
-ByteArrayViewBESetFloat...OK
-ByteArrayViewBESetDouble...OK
-ByteArrayViewBEGetVolatileShort...OK
-ByteArrayViewBEGetVolatileChar...OK
-ByteArrayViewBEGetVolatileInt...OK
-ByteArrayViewBEGetVolatileLong...OK
-ByteArrayViewBEGetVolatileFloat...OK
-ByteArrayViewBEGetVolatileDouble...OK
-ByteArrayViewBESetVolatileShort...OK
-ByteArrayViewBESetVolatileChar...OK
-ByteArrayViewBESetVolatileInt...OK
-ByteArrayViewBESetVolatileLong...OK
-ByteArrayViewBESetVolatileFloat...OK
-ByteArrayViewBESetVolatileDouble...OK
-ByteArrayViewBEGetAcquireShort...OK
-ByteArrayViewBEGetAcquireChar...OK
-ByteArrayViewBEGetAcquireInt...OK
-ByteArrayViewBEGetAcquireLong...OK
-ByteArrayViewBEGetAcquireFloat...OK
-ByteArrayViewBEGetAcquireDouble...OK
-ByteArrayViewBESetReleaseShort...OK
-ByteArrayViewBESetReleaseChar...OK
-ByteArrayViewBESetReleaseInt...OK
-ByteArrayViewBESetReleaseLong...OK
-ByteArrayViewBESetReleaseFloat...OK
-ByteArrayViewBESetReleaseDouble...OK
-ByteArrayViewBEGetOpaqueShort...OK
-ByteArrayViewBEGetOpaqueChar...OK
-ByteArrayViewBEGetOpaqueInt...OK
-ByteArrayViewBEGetOpaqueLong...OK
-ByteArrayViewBEGetOpaqueFloat...OK
-ByteArrayViewBEGetOpaqueDouble...OK
-ByteArrayViewBESetOpaqueShort...OK
-ByteArrayViewBESetOpaqueChar...OK
-ByteArrayViewBESetOpaqueInt...OK
-ByteArrayViewBESetOpaqueLong...OK
-ByteArrayViewBESetOpaqueFloat...OK
-ByteArrayViewBESetOpaqueDouble...OK
-ByteArrayViewBECompareAndSetShort...OK
-ByteArrayViewBECompareAndSetChar...OK
-ByteArrayViewBECompareAndSetInt...OK
-ByteArrayViewBECompareAndSetLong...OK
-ByteArrayViewBECompareAndSetFloat...OK
-ByteArrayViewBECompareAndSetDouble...OK
-ByteArrayViewBECompareAndExchangeShort...OK
-ByteArrayViewBECompareAndExchangeChar...OK
-ByteArrayViewBECompareAndExchangeInt...OK
-ByteArrayViewBECompareAndExchangeLong...OK
-ByteArrayViewBECompareAndExchangeFloat...OK
-ByteArrayViewBECompareAndExchangeDouble...OK
-ByteArrayViewBECompareAndExchangeAcquireShort...OK
-ByteArrayViewBECompareAndExchangeAcquireChar...OK
-ByteArrayViewBECompareAndExchangeAcquireInt...OK
-ByteArrayViewBECompareAndExchangeAcquireLong...OK
-ByteArrayViewBECompareAndExchangeAcquireFloat...OK
-ByteArrayViewBECompareAndExchangeAcquireDouble...OK
-ByteArrayViewBECompareAndExchangeReleaseShort...OK
-ByteArrayViewBECompareAndExchangeReleaseChar...OK
-ByteArrayViewBECompareAndExchangeReleaseInt...OK
-ByteArrayViewBECompareAndExchangeReleaseLong...OK
-ByteArrayViewBECompareAndExchangeReleaseFloat...OK
-ByteArrayViewBECompareAndExchangeReleaseDouble...OK
-ByteArrayViewBEWeakCompareAndSetPlainShort...OK
-ByteArrayViewBEWeakCompareAndSetPlainChar...OK
-ByteArrayViewBEWeakCompareAndSetPlainInt...OK
-ByteArrayViewBEWeakCompareAndSetPlainLong...OK
-ByteArrayViewBEWeakCompareAndSetPlainFloat...OK
-ByteArrayViewBEWeakCompareAndSetPlainDouble...OK
-ByteArrayViewBEWeakCompareAndSetShort...OK
-ByteArrayViewBEWeakCompareAndSetChar...OK
-ByteArrayViewBEWeakCompareAndSetInt...OK
-ByteArrayViewBEWeakCompareAndSetLong...OK
-ByteArrayViewBEWeakCompareAndSetFloat...OK
-ByteArrayViewBEWeakCompareAndSetDouble...OK
-ByteArrayViewBEWeakCompareAndSetAcquireShort...OK
-ByteArrayViewBEWeakCompareAndSetAcquireChar...OK
-ByteArrayViewBEWeakCompareAndSetAcquireInt...OK
-ByteArrayViewBEWeakCompareAndSetAcquireLong...OK
-ByteArrayViewBEWeakCompareAndSetAcquireFloat...OK
-ByteArrayViewBEWeakCompareAndSetAcquireDouble...OK
-ByteArrayViewBEWeakCompareAndSetReleaseShort...OK
-ByteArrayViewBEWeakCompareAndSetReleaseChar...OK
-ByteArrayViewBEWeakCompareAndSetReleaseInt...OK
-ByteArrayViewBEWeakCompareAndSetReleaseLong...OK
-ByteArrayViewBEWeakCompareAndSetReleaseFloat...OK
-ByteArrayViewBEWeakCompareAndSetReleaseDouble...OK
-ByteArrayViewBEGetAndSetShort...OK
-ByteArrayViewBEGetAndSetChar...OK
-ByteArrayViewBEGetAndSetInt...OK
-ByteArrayViewBEGetAndSetLong...OK
-ByteArrayViewBEGetAndSetFloat...OK
-ByteArrayViewBEGetAndSetDouble...OK
-ByteArrayViewBEGetAndSetAcquireShort...OK
-ByteArrayViewBEGetAndSetAcquireChar...OK
-ByteArrayViewBEGetAndSetAcquireInt...OK
-ByteArrayViewBEGetAndSetAcquireLong...OK
-ByteArrayViewBEGetAndSetAcquireFloat...OK
-ByteArrayViewBEGetAndSetAcquireDouble...OK
-ByteArrayViewBEGetAndSetReleaseShort...OK
-ByteArrayViewBEGetAndSetReleaseChar...OK
-ByteArrayViewBEGetAndSetReleaseInt...OK
-ByteArrayViewBEGetAndSetReleaseLong...OK
-ByteArrayViewBEGetAndSetReleaseFloat...OK
-ByteArrayViewBEGetAndSetReleaseDouble...OK
-ByteArrayViewBEGetAndAddShort...OK
-ByteArrayViewBEGetAndAddChar...OK
-ByteArrayViewBEGetAndAddInt...OK
-ByteArrayViewBEGetAndAddLong...OK
-ByteArrayViewBEGetAndAddFloat...OK
-ByteArrayViewBEGetAndAddDouble...OK
-ByteArrayViewBEGetAndAddAcquireShort...OK
-ByteArrayViewBEGetAndAddAcquireChar...OK
-ByteArrayViewBEGetAndAddAcquireInt...OK
-ByteArrayViewBEGetAndAddAcquireLong...OK
-ByteArrayViewBEGetAndAddAcquireFloat...OK
-ByteArrayViewBEGetAndAddAcquireDouble...OK
-ByteArrayViewBEGetAndAddReleaseShort...OK
-ByteArrayViewBEGetAndAddReleaseChar...OK
-ByteArrayViewBEGetAndAddReleaseInt...OK
-ByteArrayViewBEGetAndAddReleaseLong...OK
-ByteArrayViewBEGetAndAddReleaseFloat...OK
-ByteArrayViewBEGetAndAddReleaseDouble...OK
-ByteArrayViewBEGetAndBitwiseOrShort...OK
-ByteArrayViewBEGetAndBitwiseOrChar...OK
-ByteArrayViewBEGetAndBitwiseOrInt...OK
-ByteArrayViewBEGetAndBitwiseOrLong...OK
-ByteArrayViewBEGetAndBitwiseOrFloat...OK
-ByteArrayViewBEGetAndBitwiseOrDouble...OK
-ByteArrayViewBEGetAndBitwiseOrReleaseShort...OK
-ByteArrayViewBEGetAndBitwiseOrReleaseChar...OK
-ByteArrayViewBEGetAndBitwiseOrReleaseInt...OK
-ByteArrayViewBEGetAndBitwiseOrReleaseLong...OK
-ByteArrayViewBEGetAndBitwiseOrReleaseFloat...OK
-ByteArrayViewBEGetAndBitwiseOrReleaseDouble...OK
-ByteArrayViewBEGetAndBitwiseOrAcquireShort...OK
-ByteArrayViewBEGetAndBitwiseOrAcquireChar...OK
-ByteArrayViewBEGetAndBitwiseOrAcquireInt...OK
-ByteArrayViewBEGetAndBitwiseOrAcquireLong...OK
-ByteArrayViewBEGetAndBitwiseOrAcquireFloat...OK
-ByteArrayViewBEGetAndBitwiseOrAcquireDouble...OK
-ByteArrayViewBEGetAndBitwiseAndShort...OK
-ByteArrayViewBEGetAndBitwiseAndChar...OK
-ByteArrayViewBEGetAndBitwiseAndInt...OK
-ByteArrayViewBEGetAndBitwiseAndLong...OK
-ByteArrayViewBEGetAndBitwiseAndFloat...OK
-ByteArrayViewBEGetAndBitwiseAndDouble...OK
-ByteArrayViewBEGetAndBitwiseAndReleaseShort...OK
-ByteArrayViewBEGetAndBitwiseAndReleaseChar...OK
-ByteArrayViewBEGetAndBitwiseAndReleaseInt...OK
-ByteArrayViewBEGetAndBitwiseAndReleaseLong...OK
-ByteArrayViewBEGetAndBitwiseAndReleaseFloat...OK
-ByteArrayViewBEGetAndBitwiseAndReleaseDouble...OK
-ByteArrayViewBEGetAndBitwiseAndAcquireShort...OK
-ByteArrayViewBEGetAndBitwiseAndAcquireChar...OK
-ByteArrayViewBEGetAndBitwiseAndAcquireInt...OK
-ByteArrayViewBEGetAndBitwiseAndAcquireLong...OK
-ByteArrayViewBEGetAndBitwiseAndAcquireFloat...OK
-ByteArrayViewBEGetAndBitwiseAndAcquireDouble...OK
-ByteArrayViewBEGetAndBitwiseXorShort...OK
-ByteArrayViewBEGetAndBitwiseXorChar...OK
-ByteArrayViewBEGetAndBitwiseXorInt...OK
-ByteArrayViewBEGetAndBitwiseXorLong...OK
-ByteArrayViewBEGetAndBitwiseXorFloat...OK
-ByteArrayViewBEGetAndBitwiseXorDouble...OK
-ByteArrayViewBEGetAndBitwiseXorReleaseShort...OK
-ByteArrayViewBEGetAndBitwiseXorReleaseChar...OK
-ByteArrayViewBEGetAndBitwiseXorReleaseInt...OK
-ByteArrayViewBEGetAndBitwiseXorReleaseLong...OK
-ByteArrayViewBEGetAndBitwiseXorReleaseFloat...OK
-ByteArrayViewBEGetAndBitwiseXorReleaseDouble...OK
-ByteArrayViewBEGetAndBitwiseXorAcquireShort...OK
-ByteArrayViewBEGetAndBitwiseXorAcquireChar...OK
-ByteArrayViewBEGetAndBitwiseXorAcquireInt...OK
-ByteArrayViewBEGetAndBitwiseXorAcquireLong...OK
-ByteArrayViewBEGetAndBitwiseXorAcquireFloat...OK
-ByteArrayViewBEGetAndBitwiseXorAcquireDouble...OK
-DirectByteBufferViewLEGetShort...OK
-DirectByteBufferViewLEGetChar...OK
-DirectByteBufferViewLEGetInt...OK
-DirectByteBufferViewLEGetLong...OK
-DirectByteBufferViewLEGetFloat...OK
-DirectByteBufferViewLEGetDouble...OK
-DirectByteBufferViewLESetShort...OK
-DirectByteBufferViewLESetChar...OK
-DirectByteBufferViewLESetInt...OK
-DirectByteBufferViewLESetLong...OK
-DirectByteBufferViewLESetFloat...OK
-DirectByteBufferViewLESetDouble...OK
-DirectByteBufferViewLEGetVolatileShort...OK
-DirectByteBufferViewLEGetVolatileChar...OK
-DirectByteBufferViewLEGetVolatileInt...OK
-DirectByteBufferViewLEGetVolatileLong...OK
-DirectByteBufferViewLEGetVolatileFloat...OK
-DirectByteBufferViewLEGetVolatileDouble...OK
-DirectByteBufferViewLESetVolatileShort...OK
-DirectByteBufferViewLESetVolatileChar...OK
-DirectByteBufferViewLESetVolatileInt...OK
-DirectByteBufferViewLESetVolatileLong...OK
-DirectByteBufferViewLESetVolatileFloat...OK
-DirectByteBufferViewLESetVolatileDouble...OK
-DirectByteBufferViewLEGetAcquireShort...OK
-DirectByteBufferViewLEGetAcquireChar...OK
-DirectByteBufferViewLEGetAcquireInt...OK
-DirectByteBufferViewLEGetAcquireLong...OK
-DirectByteBufferViewLEGetAcquireFloat...OK
-DirectByteBufferViewLEGetAcquireDouble...OK
-DirectByteBufferViewLESetReleaseShort...OK
-DirectByteBufferViewLESetReleaseChar...OK
-DirectByteBufferViewLESetReleaseInt...OK
-DirectByteBufferViewLESetReleaseLong...OK
-DirectByteBufferViewLESetReleaseFloat...OK
-DirectByteBufferViewLESetReleaseDouble...OK
-DirectByteBufferViewLEGetOpaqueShort...OK
-DirectByteBufferViewLEGetOpaqueChar...OK
-DirectByteBufferViewLEGetOpaqueInt...OK
-DirectByteBufferViewLEGetOpaqueLong...OK
-DirectByteBufferViewLEGetOpaqueFloat...OK
-DirectByteBufferViewLEGetOpaqueDouble...OK
-DirectByteBufferViewLESetOpaqueShort...OK
-DirectByteBufferViewLESetOpaqueChar...OK
-DirectByteBufferViewLESetOpaqueInt...OK
-DirectByteBufferViewLESetOpaqueLong...OK
-DirectByteBufferViewLESetOpaqueFloat...OK
-DirectByteBufferViewLESetOpaqueDouble...OK
-DirectByteBufferViewLECompareAndSetShort...OK
-DirectByteBufferViewLECompareAndSetChar...OK
-DirectByteBufferViewLECompareAndSetInt...OK
-DirectByteBufferViewLECompareAndSetLong...OK
-DirectByteBufferViewLECompareAndSetFloat...OK
-DirectByteBufferViewLECompareAndSetDouble...OK
-DirectByteBufferViewLECompareAndExchangeShort...OK
-DirectByteBufferViewLECompareAndExchangeChar...OK
-DirectByteBufferViewLECompareAndExchangeInt...OK
-DirectByteBufferViewLECompareAndExchangeLong...OK
-DirectByteBufferViewLECompareAndExchangeFloat...OK
-DirectByteBufferViewLECompareAndExchangeDouble...OK
-DirectByteBufferViewLECompareAndExchangeAcquireShort...OK
-DirectByteBufferViewLECompareAndExchangeAcquireChar...OK
-DirectByteBufferViewLECompareAndExchangeAcquireInt...OK
-DirectByteBufferViewLECompareAndExchangeAcquireLong...OK
-DirectByteBufferViewLECompareAndExchangeAcquireFloat...OK
-DirectByteBufferViewLECompareAndExchangeAcquireDouble...OK
-DirectByteBufferViewLECompareAndExchangeReleaseShort...OK
-DirectByteBufferViewLECompareAndExchangeReleaseChar...OK
-DirectByteBufferViewLECompareAndExchangeReleaseInt...OK
-DirectByteBufferViewLECompareAndExchangeReleaseLong...OK
-DirectByteBufferViewLECompareAndExchangeReleaseFloat...OK
-DirectByteBufferViewLECompareAndExchangeReleaseDouble...OK
-DirectByteBufferViewLEWeakCompareAndSetPlainShort...OK
-DirectByteBufferViewLEWeakCompareAndSetPlainChar...OK
-DirectByteBufferViewLEWeakCompareAndSetPlainInt...OK
-DirectByteBufferViewLEWeakCompareAndSetPlainLong...OK
-DirectByteBufferViewLEWeakCompareAndSetPlainFloat...OK
-DirectByteBufferViewLEWeakCompareAndSetPlainDouble...OK
-DirectByteBufferViewLEWeakCompareAndSetShort...OK
-DirectByteBufferViewLEWeakCompareAndSetChar...OK
-DirectByteBufferViewLEWeakCompareAndSetInt...OK
-DirectByteBufferViewLEWeakCompareAndSetLong...OK
-DirectByteBufferViewLEWeakCompareAndSetFloat...OK
-DirectByteBufferViewLEWeakCompareAndSetDouble...OK
-DirectByteBufferViewLEWeakCompareAndSetAcquireShort...OK
-DirectByteBufferViewLEWeakCompareAndSetAcquireChar...OK
-DirectByteBufferViewLEWeakCompareAndSetAcquireInt...OK
-DirectByteBufferViewLEWeakCompareAndSetAcquireLong...OK
-DirectByteBufferViewLEWeakCompareAndSetAcquireFloat...OK
-DirectByteBufferViewLEWeakCompareAndSetAcquireDouble...OK
-DirectByteBufferViewLEWeakCompareAndSetReleaseShort...OK
-DirectByteBufferViewLEWeakCompareAndSetReleaseChar...OK
-DirectByteBufferViewLEWeakCompareAndSetReleaseInt...OK
-DirectByteBufferViewLEWeakCompareAndSetReleaseLong...OK
-DirectByteBufferViewLEWeakCompareAndSetReleaseFloat...OK
-DirectByteBufferViewLEWeakCompareAndSetReleaseDouble...OK
-DirectByteBufferViewLEGetAndSetShort...OK
-DirectByteBufferViewLEGetAndSetChar...OK
-DirectByteBufferViewLEGetAndSetInt...OK
-DirectByteBufferViewLEGetAndSetLong...OK
-DirectByteBufferViewLEGetAndSetFloat...OK
-DirectByteBufferViewLEGetAndSetDouble...OK
-DirectByteBufferViewLEGetAndSetAcquireShort...OK
-DirectByteBufferViewLEGetAndSetAcquireChar...OK
-DirectByteBufferViewLEGetAndSetAcquireInt...OK
-DirectByteBufferViewLEGetAndSetAcquireLong...OK
-DirectByteBufferViewLEGetAndSetAcquireFloat...OK
-DirectByteBufferViewLEGetAndSetAcquireDouble...OK
-DirectByteBufferViewLEGetAndSetReleaseShort...OK
-DirectByteBufferViewLEGetAndSetReleaseChar...OK
-DirectByteBufferViewLEGetAndSetReleaseInt...OK
-DirectByteBufferViewLEGetAndSetReleaseLong...OK
-DirectByteBufferViewLEGetAndSetReleaseFloat...OK
-DirectByteBufferViewLEGetAndSetReleaseDouble...OK
-DirectByteBufferViewLEGetAndAddShort...OK
-DirectByteBufferViewLEGetAndAddChar...OK
-DirectByteBufferViewLEGetAndAddInt...OK
-DirectByteBufferViewLEGetAndAddLong...OK
-DirectByteBufferViewLEGetAndAddFloat...OK
-DirectByteBufferViewLEGetAndAddDouble...OK
-DirectByteBufferViewLEGetAndAddAcquireShort...OK
-DirectByteBufferViewLEGetAndAddAcquireChar...OK
-DirectByteBufferViewLEGetAndAddAcquireInt...OK
-DirectByteBufferViewLEGetAndAddAcquireLong...OK
-DirectByteBufferViewLEGetAndAddAcquireFloat...OK
-DirectByteBufferViewLEGetAndAddAcquireDouble...OK
-DirectByteBufferViewLEGetAndAddReleaseShort...OK
-DirectByteBufferViewLEGetAndAddReleaseChar...OK
-DirectByteBufferViewLEGetAndAddReleaseInt...OK
-DirectByteBufferViewLEGetAndAddReleaseLong...OK
-DirectByteBufferViewLEGetAndAddReleaseFloat...OK
-DirectByteBufferViewLEGetAndAddReleaseDouble...OK
-DirectByteBufferViewLEGetAndBitwiseOrShort...OK
-DirectByteBufferViewLEGetAndBitwiseOrChar...OK
-DirectByteBufferViewLEGetAndBitwiseOrInt...OK
-DirectByteBufferViewLEGetAndBitwiseOrLong...OK
-DirectByteBufferViewLEGetAndBitwiseOrFloat...OK
-DirectByteBufferViewLEGetAndBitwiseOrDouble...OK
-DirectByteBufferViewLEGetAndBitwiseOrReleaseShort...OK
-DirectByteBufferViewLEGetAndBitwiseOrReleaseChar...OK
-DirectByteBufferViewLEGetAndBitwiseOrReleaseInt...OK
-DirectByteBufferViewLEGetAndBitwiseOrReleaseLong...OK
-DirectByteBufferViewLEGetAndBitwiseOrReleaseFloat...OK
-DirectByteBufferViewLEGetAndBitwiseOrReleaseDouble...OK
-DirectByteBufferViewLEGetAndBitwiseOrAcquireShort...OK
-DirectByteBufferViewLEGetAndBitwiseOrAcquireChar...OK
-DirectByteBufferViewLEGetAndBitwiseOrAcquireInt...OK
-DirectByteBufferViewLEGetAndBitwiseOrAcquireLong...OK
-DirectByteBufferViewLEGetAndBitwiseOrAcquireFloat...OK
-DirectByteBufferViewLEGetAndBitwiseOrAcquireDouble...OK
-DirectByteBufferViewLEGetAndBitwiseAndShort...OK
-DirectByteBufferViewLEGetAndBitwiseAndChar...OK
-DirectByteBufferViewLEGetAndBitwiseAndInt...OK
-DirectByteBufferViewLEGetAndBitwiseAndLong...OK
-DirectByteBufferViewLEGetAndBitwiseAndFloat...OK
-DirectByteBufferViewLEGetAndBitwiseAndDouble...OK
-DirectByteBufferViewLEGetAndBitwiseAndReleaseShort...OK
-DirectByteBufferViewLEGetAndBitwiseAndReleaseChar...OK
-DirectByteBufferViewLEGetAndBitwiseAndReleaseInt...OK
-DirectByteBufferViewLEGetAndBitwiseAndReleaseLong...OK
-DirectByteBufferViewLEGetAndBitwiseAndReleaseFloat...OK
-DirectByteBufferViewLEGetAndBitwiseAndReleaseDouble...OK
-DirectByteBufferViewLEGetAndBitwiseAndAcquireShort...OK
-DirectByteBufferViewLEGetAndBitwiseAndAcquireChar...OK
-DirectByteBufferViewLEGetAndBitwiseAndAcquireInt...OK
-DirectByteBufferViewLEGetAndBitwiseAndAcquireLong...OK
-DirectByteBufferViewLEGetAndBitwiseAndAcquireFloat...OK
-DirectByteBufferViewLEGetAndBitwiseAndAcquireDouble...OK
-DirectByteBufferViewLEGetAndBitwiseXorShort...OK
-DirectByteBufferViewLEGetAndBitwiseXorChar...OK
-DirectByteBufferViewLEGetAndBitwiseXorInt...OK
-DirectByteBufferViewLEGetAndBitwiseXorLong...OK
-DirectByteBufferViewLEGetAndBitwiseXorFloat...OK
-DirectByteBufferViewLEGetAndBitwiseXorDouble...OK
-DirectByteBufferViewLEGetAndBitwiseXorReleaseShort...OK
-DirectByteBufferViewLEGetAndBitwiseXorReleaseChar...OK
-DirectByteBufferViewLEGetAndBitwiseXorReleaseInt...OK
-DirectByteBufferViewLEGetAndBitwiseXorReleaseLong...OK
-DirectByteBufferViewLEGetAndBitwiseXorReleaseFloat...OK
-DirectByteBufferViewLEGetAndBitwiseXorReleaseDouble...OK
-DirectByteBufferViewLEGetAndBitwiseXorAcquireShort...OK
-DirectByteBufferViewLEGetAndBitwiseXorAcquireChar...OK
-DirectByteBufferViewLEGetAndBitwiseXorAcquireInt...OK
-DirectByteBufferViewLEGetAndBitwiseXorAcquireLong...OK
-DirectByteBufferViewLEGetAndBitwiseXorAcquireFloat...OK
-DirectByteBufferViewLEGetAndBitwiseXorAcquireDouble...OK
-DirectByteBufferViewBEGetShort...OK
-DirectByteBufferViewBEGetChar...OK
-DirectByteBufferViewBEGetInt...OK
-DirectByteBufferViewBEGetLong...OK
-DirectByteBufferViewBEGetFloat...OK
-DirectByteBufferViewBEGetDouble...OK
-DirectByteBufferViewBESetShort...OK
-DirectByteBufferViewBESetChar...OK
-DirectByteBufferViewBESetInt...OK
-DirectByteBufferViewBESetLong...OK
-DirectByteBufferViewBESetFloat...OK
-DirectByteBufferViewBESetDouble...OK
-DirectByteBufferViewBEGetVolatileShort...OK
-DirectByteBufferViewBEGetVolatileChar...OK
-DirectByteBufferViewBEGetVolatileInt...OK
-DirectByteBufferViewBEGetVolatileLong...OK
-DirectByteBufferViewBEGetVolatileFloat...OK
-DirectByteBufferViewBEGetVolatileDouble...OK
-DirectByteBufferViewBESetVolatileShort...OK
-DirectByteBufferViewBESetVolatileChar...OK
-DirectByteBufferViewBESetVolatileInt...OK
-DirectByteBufferViewBESetVolatileLong...OK
-DirectByteBufferViewBESetVolatileFloat...OK
-DirectByteBufferViewBESetVolatileDouble...OK
-DirectByteBufferViewBEGetAcquireShort...OK
-DirectByteBufferViewBEGetAcquireChar...OK
-DirectByteBufferViewBEGetAcquireInt...OK
-DirectByteBufferViewBEGetAcquireLong...OK
-DirectByteBufferViewBEGetAcquireFloat...OK
-DirectByteBufferViewBEGetAcquireDouble...OK
-DirectByteBufferViewBESetReleaseShort...OK
-DirectByteBufferViewBESetReleaseChar...OK
-DirectByteBufferViewBESetReleaseInt...OK
-DirectByteBufferViewBESetReleaseLong...OK
-DirectByteBufferViewBESetReleaseFloat...OK
-DirectByteBufferViewBESetReleaseDouble...OK
-DirectByteBufferViewBEGetOpaqueShort...OK
-DirectByteBufferViewBEGetOpaqueChar...OK
-DirectByteBufferViewBEGetOpaqueInt...OK
-DirectByteBufferViewBEGetOpaqueLong...OK
-DirectByteBufferViewBEGetOpaqueFloat...OK
-DirectByteBufferViewBEGetOpaqueDouble...OK
-DirectByteBufferViewBESetOpaqueShort...OK
-DirectByteBufferViewBESetOpaqueChar...OK
-DirectByteBufferViewBESetOpaqueInt...OK
-DirectByteBufferViewBESetOpaqueLong...OK
-DirectByteBufferViewBESetOpaqueFloat...OK
-DirectByteBufferViewBESetOpaqueDouble...OK
-DirectByteBufferViewBECompareAndSetShort...OK
-DirectByteBufferViewBECompareAndSetChar...OK
-DirectByteBufferViewBECompareAndSetInt...OK
-DirectByteBufferViewBECompareAndSetLong...OK
-DirectByteBufferViewBECompareAndSetFloat...OK
-DirectByteBufferViewBECompareAndSetDouble...OK
-DirectByteBufferViewBECompareAndExchangeShort...OK
-DirectByteBufferViewBECompareAndExchangeChar...OK
-DirectByteBufferViewBECompareAndExchangeInt...OK
-DirectByteBufferViewBECompareAndExchangeLong...OK
-DirectByteBufferViewBECompareAndExchangeFloat...OK
-DirectByteBufferViewBECompareAndExchangeDouble...OK
-DirectByteBufferViewBECompareAndExchangeAcquireShort...OK
-DirectByteBufferViewBECompareAndExchangeAcquireChar...OK
-DirectByteBufferViewBECompareAndExchangeAcquireInt...OK
-DirectByteBufferViewBECompareAndExchangeAcquireLong...OK
-DirectByteBufferViewBECompareAndExchangeAcquireFloat...OK
-DirectByteBufferViewBECompareAndExchangeAcquireDouble...OK
-DirectByteBufferViewBECompareAndExchangeReleaseShort...OK
-DirectByteBufferViewBECompareAndExchangeReleaseChar...OK
-DirectByteBufferViewBECompareAndExchangeReleaseInt...OK
-DirectByteBufferViewBECompareAndExchangeReleaseLong...OK
-DirectByteBufferViewBECompareAndExchangeReleaseFloat...OK
-DirectByteBufferViewBECompareAndExchangeReleaseDouble...OK
-DirectByteBufferViewBEWeakCompareAndSetPlainShort...OK
-DirectByteBufferViewBEWeakCompareAndSetPlainChar...OK
-DirectByteBufferViewBEWeakCompareAndSetPlainInt...OK
-DirectByteBufferViewBEWeakCompareAndSetPlainLong...OK
-DirectByteBufferViewBEWeakCompareAndSetPlainFloat...OK
-DirectByteBufferViewBEWeakCompareAndSetPlainDouble...OK
-DirectByteBufferViewBEWeakCompareAndSetShort...OK
-DirectByteBufferViewBEWeakCompareAndSetChar...OK
-DirectByteBufferViewBEWeakCompareAndSetInt...OK
-DirectByteBufferViewBEWeakCompareAndSetLong...OK
-DirectByteBufferViewBEWeakCompareAndSetFloat...OK
-DirectByteBufferViewBEWeakCompareAndSetDouble...OK
-DirectByteBufferViewBEWeakCompareAndSetAcquireShort...OK
-DirectByteBufferViewBEWeakCompareAndSetAcquireChar...OK
-DirectByteBufferViewBEWeakCompareAndSetAcquireInt...OK
-DirectByteBufferViewBEWeakCompareAndSetAcquireLong...OK
-DirectByteBufferViewBEWeakCompareAndSetAcquireFloat...OK
-DirectByteBufferViewBEWeakCompareAndSetAcquireDouble...OK
-DirectByteBufferViewBEWeakCompareAndSetReleaseShort...OK
-DirectByteBufferViewBEWeakCompareAndSetReleaseChar...OK
-DirectByteBufferViewBEWeakCompareAndSetReleaseInt...OK
-DirectByteBufferViewBEWeakCompareAndSetReleaseLong...OK
-DirectByteBufferViewBEWeakCompareAndSetReleaseFloat...OK
-DirectByteBufferViewBEWeakCompareAndSetReleaseDouble...OK
-DirectByteBufferViewBEGetAndSetShort...OK
-DirectByteBufferViewBEGetAndSetChar...OK
-DirectByteBufferViewBEGetAndSetInt...OK
-DirectByteBufferViewBEGetAndSetLong...OK
-DirectByteBufferViewBEGetAndSetFloat...OK
-DirectByteBufferViewBEGetAndSetDouble...OK
-DirectByteBufferViewBEGetAndSetAcquireShort...OK
-DirectByteBufferViewBEGetAndSetAcquireChar...OK
-DirectByteBufferViewBEGetAndSetAcquireInt...OK
-DirectByteBufferViewBEGetAndSetAcquireLong...OK
-DirectByteBufferViewBEGetAndSetAcquireFloat...OK
-DirectByteBufferViewBEGetAndSetAcquireDouble...OK
-DirectByteBufferViewBEGetAndSetReleaseShort...OK
-DirectByteBufferViewBEGetAndSetReleaseChar...OK
-DirectByteBufferViewBEGetAndSetReleaseInt...OK
-DirectByteBufferViewBEGetAndSetReleaseLong...OK
-DirectByteBufferViewBEGetAndSetReleaseFloat...OK
-DirectByteBufferViewBEGetAndSetReleaseDouble...OK
-DirectByteBufferViewBEGetAndAddShort...OK
-DirectByteBufferViewBEGetAndAddChar...OK
-DirectByteBufferViewBEGetAndAddInt...OK
-DirectByteBufferViewBEGetAndAddLong...OK
-DirectByteBufferViewBEGetAndAddFloat...OK
-DirectByteBufferViewBEGetAndAddDouble...OK
-DirectByteBufferViewBEGetAndAddAcquireShort...OK
-DirectByteBufferViewBEGetAndAddAcquireChar...OK
-DirectByteBufferViewBEGetAndAddAcquireInt...OK
-DirectByteBufferViewBEGetAndAddAcquireLong...OK
-DirectByteBufferViewBEGetAndAddAcquireFloat...OK
-DirectByteBufferViewBEGetAndAddAcquireDouble...OK
-DirectByteBufferViewBEGetAndAddReleaseShort...OK
-DirectByteBufferViewBEGetAndAddReleaseChar...OK
-DirectByteBufferViewBEGetAndAddReleaseInt...OK
-DirectByteBufferViewBEGetAndAddReleaseLong...OK
-DirectByteBufferViewBEGetAndAddReleaseFloat...OK
-DirectByteBufferViewBEGetAndAddReleaseDouble...OK
-DirectByteBufferViewBEGetAndBitwiseOrShort...OK
-DirectByteBufferViewBEGetAndBitwiseOrChar...OK
-DirectByteBufferViewBEGetAndBitwiseOrInt...OK
-DirectByteBufferViewBEGetAndBitwiseOrLong...OK
-DirectByteBufferViewBEGetAndBitwiseOrFloat...OK
-DirectByteBufferViewBEGetAndBitwiseOrDouble...OK
-DirectByteBufferViewBEGetAndBitwiseOrReleaseShort...OK
-DirectByteBufferViewBEGetAndBitwiseOrReleaseChar...OK
-DirectByteBufferViewBEGetAndBitwiseOrReleaseInt...OK
-DirectByteBufferViewBEGetAndBitwiseOrReleaseLong...OK
-DirectByteBufferViewBEGetAndBitwiseOrReleaseFloat...OK
-DirectByteBufferViewBEGetAndBitwiseOrReleaseDouble...OK
-DirectByteBufferViewBEGetAndBitwiseOrAcquireShort...OK
-DirectByteBufferViewBEGetAndBitwiseOrAcquireChar...OK
-DirectByteBufferViewBEGetAndBitwiseOrAcquireInt...OK
-DirectByteBufferViewBEGetAndBitwiseOrAcquireLong...OK
-DirectByteBufferViewBEGetAndBitwiseOrAcquireFloat...OK
-DirectByteBufferViewBEGetAndBitwiseOrAcquireDouble...OK
-DirectByteBufferViewBEGetAndBitwiseAndShort...OK
-DirectByteBufferViewBEGetAndBitwiseAndChar...OK
-DirectByteBufferViewBEGetAndBitwiseAndInt...OK
-DirectByteBufferViewBEGetAndBitwiseAndLong...OK
-DirectByteBufferViewBEGetAndBitwiseAndFloat...OK
-DirectByteBufferViewBEGetAndBitwiseAndDouble...OK
-DirectByteBufferViewBEGetAndBitwiseAndReleaseShort...OK
-DirectByteBufferViewBEGetAndBitwiseAndReleaseChar...OK
-DirectByteBufferViewBEGetAndBitwiseAndReleaseInt...OK
-DirectByteBufferViewBEGetAndBitwiseAndReleaseLong...OK
-DirectByteBufferViewBEGetAndBitwiseAndReleaseFloat...OK
-DirectByteBufferViewBEGetAndBitwiseAndReleaseDouble...OK
-DirectByteBufferViewBEGetAndBitwiseAndAcquireShort...OK
-DirectByteBufferViewBEGetAndBitwiseAndAcquireChar...OK
-DirectByteBufferViewBEGetAndBitwiseAndAcquireInt...OK
-DirectByteBufferViewBEGetAndBitwiseAndAcquireLong...OK
-DirectByteBufferViewBEGetAndBitwiseAndAcquireFloat...OK
-DirectByteBufferViewBEGetAndBitwiseAndAcquireDouble...OK
-DirectByteBufferViewBEGetAndBitwiseXorShort...OK
-DirectByteBufferViewBEGetAndBitwiseXorChar...OK
-DirectByteBufferViewBEGetAndBitwiseXorInt...OK
-DirectByteBufferViewBEGetAndBitwiseXorLong...OK
-DirectByteBufferViewBEGetAndBitwiseXorFloat...OK
-DirectByteBufferViewBEGetAndBitwiseXorDouble...OK
-DirectByteBufferViewBEGetAndBitwiseXorReleaseShort...OK
-DirectByteBufferViewBEGetAndBitwiseXorReleaseChar...OK
-DirectByteBufferViewBEGetAndBitwiseXorReleaseInt...OK
-DirectByteBufferViewBEGetAndBitwiseXorReleaseLong...OK
-DirectByteBufferViewBEGetAndBitwiseXorReleaseFloat...OK
-DirectByteBufferViewBEGetAndBitwiseXorReleaseDouble...OK
-DirectByteBufferViewBEGetAndBitwiseXorAcquireShort...OK
-DirectByteBufferViewBEGetAndBitwiseXorAcquireChar...OK
-DirectByteBufferViewBEGetAndBitwiseXorAcquireInt...OK
-DirectByteBufferViewBEGetAndBitwiseXorAcquireLong...OK
-DirectByteBufferViewBEGetAndBitwiseXorAcquireFloat...OK
-DirectByteBufferViewBEGetAndBitwiseXorAcquireDouble...OK
-HeapByteBufferViewLEGetShort...OK
-HeapByteBufferViewLEGetChar...OK
-HeapByteBufferViewLEGetInt...OK
-HeapByteBufferViewLEGetLong...OK
-HeapByteBufferViewLEGetFloat...OK
-HeapByteBufferViewLEGetDouble...OK
-HeapByteBufferViewLESetShort...OK
-HeapByteBufferViewLESetChar...OK
-HeapByteBufferViewLESetInt...OK
-HeapByteBufferViewLESetLong...OK
-HeapByteBufferViewLESetFloat...OK
-HeapByteBufferViewLESetDouble...OK
-HeapByteBufferViewLEGetVolatileShort...OK
-HeapByteBufferViewLEGetVolatileChar...OK
-HeapByteBufferViewLEGetVolatileInt...OK
-HeapByteBufferViewLEGetVolatileLong...OK
-HeapByteBufferViewLEGetVolatileFloat...OK
-HeapByteBufferViewLEGetVolatileDouble...OK
-HeapByteBufferViewLESetVolatileShort...OK
-HeapByteBufferViewLESetVolatileChar...OK
-HeapByteBufferViewLESetVolatileInt...OK
-HeapByteBufferViewLESetVolatileLong...OK
-HeapByteBufferViewLESetVolatileFloat...OK
-HeapByteBufferViewLESetVolatileDouble...OK
-HeapByteBufferViewLEGetAcquireShort...OK
-HeapByteBufferViewLEGetAcquireChar...OK
-HeapByteBufferViewLEGetAcquireInt...OK
-HeapByteBufferViewLEGetAcquireLong...OK
-HeapByteBufferViewLEGetAcquireFloat...OK
-HeapByteBufferViewLEGetAcquireDouble...OK
-HeapByteBufferViewLESetReleaseShort...OK
-HeapByteBufferViewLESetReleaseChar...OK
-HeapByteBufferViewLESetReleaseInt...OK
-HeapByteBufferViewLESetReleaseLong...OK
-HeapByteBufferViewLESetReleaseFloat...OK
-HeapByteBufferViewLESetReleaseDouble...OK
-HeapByteBufferViewLEGetOpaqueShort...OK
-HeapByteBufferViewLEGetOpaqueChar...OK
-HeapByteBufferViewLEGetOpaqueInt...OK
-HeapByteBufferViewLEGetOpaqueLong...OK
-HeapByteBufferViewLEGetOpaqueFloat...OK
-HeapByteBufferViewLEGetOpaqueDouble...OK
-HeapByteBufferViewLESetOpaqueShort...OK
-HeapByteBufferViewLESetOpaqueChar...OK
-HeapByteBufferViewLESetOpaqueInt...OK
-HeapByteBufferViewLESetOpaqueLong...OK
-HeapByteBufferViewLESetOpaqueFloat...OK
-HeapByteBufferViewLESetOpaqueDouble...OK
-HeapByteBufferViewLECompareAndSetShort...OK
-HeapByteBufferViewLECompareAndSetChar...OK
-HeapByteBufferViewLECompareAndSetInt...OK
-HeapByteBufferViewLECompareAndSetLong...OK
-HeapByteBufferViewLECompareAndSetFloat...OK
-HeapByteBufferViewLECompareAndSetDouble...OK
-HeapByteBufferViewLECompareAndExchangeShort...OK
-HeapByteBufferViewLECompareAndExchangeChar...OK
-HeapByteBufferViewLECompareAndExchangeInt...OK
-HeapByteBufferViewLECompareAndExchangeLong...OK
-HeapByteBufferViewLECompareAndExchangeFloat...OK
-HeapByteBufferViewLECompareAndExchangeDouble...OK
-HeapByteBufferViewLECompareAndExchangeAcquireShort...OK
-HeapByteBufferViewLECompareAndExchangeAcquireChar...OK
-HeapByteBufferViewLECompareAndExchangeAcquireInt...OK
-HeapByteBufferViewLECompareAndExchangeAcquireLong...OK
-HeapByteBufferViewLECompareAndExchangeAcquireFloat...OK
-HeapByteBufferViewLECompareAndExchangeAcquireDouble...OK
-HeapByteBufferViewLECompareAndExchangeReleaseShort...OK
-HeapByteBufferViewLECompareAndExchangeReleaseChar...OK
-HeapByteBufferViewLECompareAndExchangeReleaseInt...OK
-HeapByteBufferViewLECompareAndExchangeReleaseLong...OK
-HeapByteBufferViewLECompareAndExchangeReleaseFloat...OK
-HeapByteBufferViewLECompareAndExchangeReleaseDouble...OK
-HeapByteBufferViewLEWeakCompareAndSetPlainShort...OK
-HeapByteBufferViewLEWeakCompareAndSetPlainChar...OK
-HeapByteBufferViewLEWeakCompareAndSetPlainInt...OK
-HeapByteBufferViewLEWeakCompareAndSetPlainLong...OK
-HeapByteBufferViewLEWeakCompareAndSetPlainFloat...OK
-HeapByteBufferViewLEWeakCompareAndSetPlainDouble...OK
-HeapByteBufferViewLEWeakCompareAndSetShort...OK
-HeapByteBufferViewLEWeakCompareAndSetChar...OK
-HeapByteBufferViewLEWeakCompareAndSetInt...OK
-HeapByteBufferViewLEWeakCompareAndSetLong...OK
-HeapByteBufferViewLEWeakCompareAndSetFloat...OK
-HeapByteBufferViewLEWeakCompareAndSetDouble...OK
-HeapByteBufferViewLEWeakCompareAndSetAcquireShort...OK
-HeapByteBufferViewLEWeakCompareAndSetAcquireChar...OK
-HeapByteBufferViewLEWeakCompareAndSetAcquireInt...OK
-HeapByteBufferViewLEWeakCompareAndSetAcquireLong...OK
-HeapByteBufferViewLEWeakCompareAndSetAcquireFloat...OK
-HeapByteBufferViewLEWeakCompareAndSetAcquireDouble...OK
-HeapByteBufferViewLEWeakCompareAndSetReleaseShort...OK
-HeapByteBufferViewLEWeakCompareAndSetReleaseChar...OK
-HeapByteBufferViewLEWeakCompareAndSetReleaseInt...OK
-HeapByteBufferViewLEWeakCompareAndSetReleaseLong...OK
-HeapByteBufferViewLEWeakCompareAndSetReleaseFloat...OK
-HeapByteBufferViewLEWeakCompareAndSetReleaseDouble...OK
-HeapByteBufferViewLEGetAndSetShort...OK
-HeapByteBufferViewLEGetAndSetChar...OK
-HeapByteBufferViewLEGetAndSetInt...OK
-HeapByteBufferViewLEGetAndSetLong...OK
-HeapByteBufferViewLEGetAndSetFloat...OK
-HeapByteBufferViewLEGetAndSetDouble...OK
-HeapByteBufferViewLEGetAndSetAcquireShort...OK
-HeapByteBufferViewLEGetAndSetAcquireChar...OK
-HeapByteBufferViewLEGetAndSetAcquireInt...OK
-HeapByteBufferViewLEGetAndSetAcquireLong...OK
-HeapByteBufferViewLEGetAndSetAcquireFloat...OK
-HeapByteBufferViewLEGetAndSetAcquireDouble...OK
-HeapByteBufferViewLEGetAndSetReleaseShort...OK
-HeapByteBufferViewLEGetAndSetReleaseChar...OK
-HeapByteBufferViewLEGetAndSetReleaseInt...OK
-HeapByteBufferViewLEGetAndSetReleaseLong...OK
-HeapByteBufferViewLEGetAndSetReleaseFloat...OK
-HeapByteBufferViewLEGetAndSetReleaseDouble...OK
-HeapByteBufferViewLEGetAndAddShort...OK
-HeapByteBufferViewLEGetAndAddChar...OK
-HeapByteBufferViewLEGetAndAddInt...OK
-HeapByteBufferViewLEGetAndAddLong...OK
-HeapByteBufferViewLEGetAndAddFloat...OK
-HeapByteBufferViewLEGetAndAddDouble...OK
-HeapByteBufferViewLEGetAndAddAcquireShort...OK
-HeapByteBufferViewLEGetAndAddAcquireChar...OK
-HeapByteBufferViewLEGetAndAddAcquireInt...OK
-HeapByteBufferViewLEGetAndAddAcquireLong...OK
-HeapByteBufferViewLEGetAndAddAcquireFloat...OK
-HeapByteBufferViewLEGetAndAddAcquireDouble...OK
-HeapByteBufferViewLEGetAndAddReleaseShort...OK
-HeapByteBufferViewLEGetAndAddReleaseChar...OK
-HeapByteBufferViewLEGetAndAddReleaseInt...OK
-HeapByteBufferViewLEGetAndAddReleaseLong...OK
-HeapByteBufferViewLEGetAndAddReleaseFloat...OK
-HeapByteBufferViewLEGetAndAddReleaseDouble...OK
-HeapByteBufferViewLEGetAndBitwiseOrShort...OK
-HeapByteBufferViewLEGetAndBitwiseOrChar...OK
-HeapByteBufferViewLEGetAndBitwiseOrInt...OK
-HeapByteBufferViewLEGetAndBitwiseOrLong...OK
-HeapByteBufferViewLEGetAndBitwiseOrFloat...OK
-HeapByteBufferViewLEGetAndBitwiseOrDouble...OK
-HeapByteBufferViewLEGetAndBitwiseOrReleaseShort...OK
-HeapByteBufferViewLEGetAndBitwiseOrReleaseChar...OK
-HeapByteBufferViewLEGetAndBitwiseOrReleaseInt...OK
-HeapByteBufferViewLEGetAndBitwiseOrReleaseLong...OK
-HeapByteBufferViewLEGetAndBitwiseOrReleaseFloat...OK
-HeapByteBufferViewLEGetAndBitwiseOrReleaseDouble...OK
-HeapByteBufferViewLEGetAndBitwiseOrAcquireShort...OK
-HeapByteBufferViewLEGetAndBitwiseOrAcquireChar...OK
-HeapByteBufferViewLEGetAndBitwiseOrAcquireInt...OK
-HeapByteBufferViewLEGetAndBitwiseOrAcquireLong...OK
-HeapByteBufferViewLEGetAndBitwiseOrAcquireFloat...OK
-HeapByteBufferViewLEGetAndBitwiseOrAcquireDouble...OK
-HeapByteBufferViewLEGetAndBitwiseAndShort...OK
-HeapByteBufferViewLEGetAndBitwiseAndChar...OK
-HeapByteBufferViewLEGetAndBitwiseAndInt...OK
-HeapByteBufferViewLEGetAndBitwiseAndLong...OK
-HeapByteBufferViewLEGetAndBitwiseAndFloat...OK
-HeapByteBufferViewLEGetAndBitwiseAndDouble...OK
-HeapByteBufferViewLEGetAndBitwiseAndReleaseShort...OK
-HeapByteBufferViewLEGetAndBitwiseAndReleaseChar...OK
-HeapByteBufferViewLEGetAndBitwiseAndReleaseInt...OK
-HeapByteBufferViewLEGetAndBitwiseAndReleaseLong...OK
-HeapByteBufferViewLEGetAndBitwiseAndReleaseFloat...OK
-HeapByteBufferViewLEGetAndBitwiseAndReleaseDouble...OK
-HeapByteBufferViewLEGetAndBitwiseAndAcquireShort...OK
-HeapByteBufferViewLEGetAndBitwiseAndAcquireChar...OK
-HeapByteBufferViewLEGetAndBitwiseAndAcquireInt...OK
-HeapByteBufferViewLEGetAndBitwiseAndAcquireLong...OK
-HeapByteBufferViewLEGetAndBitwiseAndAcquireFloat...OK
-HeapByteBufferViewLEGetAndBitwiseAndAcquireDouble...OK
-HeapByteBufferViewLEGetAndBitwiseXorShort...OK
-HeapByteBufferViewLEGetAndBitwiseXorChar...OK
-HeapByteBufferViewLEGetAndBitwiseXorInt...OK
-HeapByteBufferViewLEGetAndBitwiseXorLong...OK
-HeapByteBufferViewLEGetAndBitwiseXorFloat...OK
-HeapByteBufferViewLEGetAndBitwiseXorDouble...OK
-HeapByteBufferViewLEGetAndBitwiseXorReleaseShort...OK
-HeapByteBufferViewLEGetAndBitwiseXorReleaseChar...OK
-HeapByteBufferViewLEGetAndBitwiseXorReleaseInt...OK
-HeapByteBufferViewLEGetAndBitwiseXorReleaseLong...OK
-HeapByteBufferViewLEGetAndBitwiseXorReleaseFloat...OK
-HeapByteBufferViewLEGetAndBitwiseXorReleaseDouble...OK
-HeapByteBufferViewLEGetAndBitwiseXorAcquireShort...OK
-HeapByteBufferViewLEGetAndBitwiseXorAcquireChar...OK
-HeapByteBufferViewLEGetAndBitwiseXorAcquireInt...OK
-HeapByteBufferViewLEGetAndBitwiseXorAcquireLong...OK
-HeapByteBufferViewLEGetAndBitwiseXorAcquireFloat...OK
-HeapByteBufferViewLEGetAndBitwiseXorAcquireDouble...OK
-HeapByteBufferViewBEGetShort...OK
-HeapByteBufferViewBEGetChar...OK
-HeapByteBufferViewBEGetInt...OK
-HeapByteBufferViewBEGetLong...OK
-HeapByteBufferViewBEGetFloat...OK
-HeapByteBufferViewBEGetDouble...OK
-HeapByteBufferViewBESetShort...OK
-HeapByteBufferViewBESetChar...OK
-HeapByteBufferViewBESetInt...OK
-HeapByteBufferViewBESetLong...OK
-HeapByteBufferViewBESetFloat...OK
-HeapByteBufferViewBESetDouble...OK
-HeapByteBufferViewBEGetVolatileShort...OK
-HeapByteBufferViewBEGetVolatileChar...OK
-HeapByteBufferViewBEGetVolatileInt...OK
-HeapByteBufferViewBEGetVolatileLong...OK
-HeapByteBufferViewBEGetVolatileFloat...OK
-HeapByteBufferViewBEGetVolatileDouble...OK
-HeapByteBufferViewBESetVolatileShort...OK
-HeapByteBufferViewBESetVolatileChar...OK
-HeapByteBufferViewBESetVolatileInt...OK
-HeapByteBufferViewBESetVolatileLong...OK
-HeapByteBufferViewBESetVolatileFloat...OK
-HeapByteBufferViewBESetVolatileDouble...OK
-HeapByteBufferViewBEGetAcquireShort...OK
-HeapByteBufferViewBEGetAcquireChar...OK
-HeapByteBufferViewBEGetAcquireInt...OK
-HeapByteBufferViewBEGetAcquireLong...OK
-HeapByteBufferViewBEGetAcquireFloat...OK
-HeapByteBufferViewBEGetAcquireDouble...OK
-HeapByteBufferViewBESetReleaseShort...OK
-HeapByteBufferViewBESetReleaseChar...OK
-HeapByteBufferViewBESetReleaseInt...OK
-HeapByteBufferViewBESetReleaseLong...OK
-HeapByteBufferViewBESetReleaseFloat...OK
-HeapByteBufferViewBESetReleaseDouble...OK
-HeapByteBufferViewBEGetOpaqueShort...OK
-HeapByteBufferViewBEGetOpaqueChar...OK
-HeapByteBufferViewBEGetOpaqueInt...OK
-HeapByteBufferViewBEGetOpaqueLong...OK
-HeapByteBufferViewBEGetOpaqueFloat...OK
-HeapByteBufferViewBEGetOpaqueDouble...OK
-HeapByteBufferViewBESetOpaqueShort...OK
-HeapByteBufferViewBESetOpaqueChar...OK
-HeapByteBufferViewBESetOpaqueInt...OK
-HeapByteBufferViewBESetOpaqueLong...OK
-HeapByteBufferViewBESetOpaqueFloat...OK
-HeapByteBufferViewBESetOpaqueDouble...OK
-HeapByteBufferViewBECompareAndSetShort...OK
-HeapByteBufferViewBECompareAndSetChar...OK
-HeapByteBufferViewBECompareAndSetInt...OK
-HeapByteBufferViewBECompareAndSetLong...OK
-HeapByteBufferViewBECompareAndSetFloat...OK
-HeapByteBufferViewBECompareAndSetDouble...OK
-HeapByteBufferViewBECompareAndExchangeShort...OK
-HeapByteBufferViewBECompareAndExchangeChar...OK
-HeapByteBufferViewBECompareAndExchangeInt...OK
-HeapByteBufferViewBECompareAndExchangeLong...OK
-HeapByteBufferViewBECompareAndExchangeFloat...OK
-HeapByteBufferViewBECompareAndExchangeDouble...OK
-HeapByteBufferViewBECompareAndExchangeAcquireShort...OK
-HeapByteBufferViewBECompareAndExchangeAcquireChar...OK
-HeapByteBufferViewBECompareAndExchangeAcquireInt...OK
-HeapByteBufferViewBECompareAndExchangeAcquireLong...OK
-HeapByteBufferViewBECompareAndExchangeAcquireFloat...OK
-HeapByteBufferViewBECompareAndExchangeAcquireDouble...OK
-HeapByteBufferViewBECompareAndExchangeReleaseShort...OK
-HeapByteBufferViewBECompareAndExchangeReleaseChar...OK
-HeapByteBufferViewBECompareAndExchangeReleaseInt...OK
-HeapByteBufferViewBECompareAndExchangeReleaseLong...OK
-HeapByteBufferViewBECompareAndExchangeReleaseFloat...OK
-HeapByteBufferViewBECompareAndExchangeReleaseDouble...OK
-HeapByteBufferViewBEWeakCompareAndSetPlainShort...OK
-HeapByteBufferViewBEWeakCompareAndSetPlainChar...OK
-HeapByteBufferViewBEWeakCompareAndSetPlainInt...OK
-HeapByteBufferViewBEWeakCompareAndSetPlainLong...OK
-HeapByteBufferViewBEWeakCompareAndSetPlainFloat...OK
-HeapByteBufferViewBEWeakCompareAndSetPlainDouble...OK
-HeapByteBufferViewBEWeakCompareAndSetShort...OK
-HeapByteBufferViewBEWeakCompareAndSetChar...OK
-HeapByteBufferViewBEWeakCompareAndSetInt...OK
-HeapByteBufferViewBEWeakCompareAndSetLong...OK
-HeapByteBufferViewBEWeakCompareAndSetFloat...OK
-HeapByteBufferViewBEWeakCompareAndSetDouble...OK
-HeapByteBufferViewBEWeakCompareAndSetAcquireShort...OK
-HeapByteBufferViewBEWeakCompareAndSetAcquireChar...OK
-HeapByteBufferViewBEWeakCompareAndSetAcquireInt...OK
-HeapByteBufferViewBEWeakCompareAndSetAcquireLong...OK
-HeapByteBufferViewBEWeakCompareAndSetAcquireFloat...OK
-HeapByteBufferViewBEWeakCompareAndSetAcquireDouble...OK
-HeapByteBufferViewBEWeakCompareAndSetReleaseShort...OK
-HeapByteBufferViewBEWeakCompareAndSetReleaseChar...OK
-HeapByteBufferViewBEWeakCompareAndSetReleaseInt...OK
-HeapByteBufferViewBEWeakCompareAndSetReleaseLong...OK
-HeapByteBufferViewBEWeakCompareAndSetReleaseFloat...OK
-HeapByteBufferViewBEWeakCompareAndSetReleaseDouble...OK
-HeapByteBufferViewBEGetAndSetShort...OK
-HeapByteBufferViewBEGetAndSetChar...OK
-HeapByteBufferViewBEGetAndSetInt...OK
-HeapByteBufferViewBEGetAndSetLong...OK
-HeapByteBufferViewBEGetAndSetFloat...OK
-HeapByteBufferViewBEGetAndSetDouble...OK
-HeapByteBufferViewBEGetAndSetAcquireShort...OK
-HeapByteBufferViewBEGetAndSetAcquireChar...OK
-HeapByteBufferViewBEGetAndSetAcquireInt...OK
-HeapByteBufferViewBEGetAndSetAcquireLong...OK
-HeapByteBufferViewBEGetAndSetAcquireFloat...OK
-HeapByteBufferViewBEGetAndSetAcquireDouble...OK
-HeapByteBufferViewBEGetAndSetReleaseShort...OK
-HeapByteBufferViewBEGetAndSetReleaseChar...OK
-HeapByteBufferViewBEGetAndSetReleaseInt...OK
-HeapByteBufferViewBEGetAndSetReleaseLong...OK
-HeapByteBufferViewBEGetAndSetReleaseFloat...OK
-HeapByteBufferViewBEGetAndSetReleaseDouble...OK
-HeapByteBufferViewBEGetAndAddShort...OK
-HeapByteBufferViewBEGetAndAddChar...OK
-HeapByteBufferViewBEGetAndAddInt...OK
-HeapByteBufferViewBEGetAndAddLong...OK
-HeapByteBufferViewBEGetAndAddFloat...OK
-HeapByteBufferViewBEGetAndAddDouble...OK
-HeapByteBufferViewBEGetAndAddAcquireShort...OK
-HeapByteBufferViewBEGetAndAddAcquireChar...OK
-HeapByteBufferViewBEGetAndAddAcquireInt...OK
-HeapByteBufferViewBEGetAndAddAcquireLong...OK
-HeapByteBufferViewBEGetAndAddAcquireFloat...OK
-HeapByteBufferViewBEGetAndAddAcquireDouble...OK
-HeapByteBufferViewBEGetAndAddReleaseShort...OK
-HeapByteBufferViewBEGetAndAddReleaseChar...OK
-HeapByteBufferViewBEGetAndAddReleaseInt...OK
-HeapByteBufferViewBEGetAndAddReleaseLong...OK
-HeapByteBufferViewBEGetAndAddReleaseFloat...OK
-HeapByteBufferViewBEGetAndAddReleaseDouble...OK
-HeapByteBufferViewBEGetAndBitwiseOrShort...OK
-HeapByteBufferViewBEGetAndBitwiseOrChar...OK
-HeapByteBufferViewBEGetAndBitwiseOrInt...OK
-HeapByteBufferViewBEGetAndBitwiseOrLong...OK
-HeapByteBufferViewBEGetAndBitwiseOrFloat...OK
-HeapByteBufferViewBEGetAndBitwiseOrDouble...OK
-HeapByteBufferViewBEGetAndBitwiseOrReleaseShort...OK
-HeapByteBufferViewBEGetAndBitwiseOrReleaseChar...OK
-HeapByteBufferViewBEGetAndBitwiseOrReleaseInt...OK
-HeapByteBufferViewBEGetAndBitwiseOrReleaseLong...OK
-HeapByteBufferViewBEGetAndBitwiseOrReleaseFloat...OK
-HeapByteBufferViewBEGetAndBitwiseOrReleaseDouble...OK
-HeapByteBufferViewBEGetAndBitwiseOrAcquireShort...OK
-HeapByteBufferViewBEGetAndBitwiseOrAcquireChar...OK
-HeapByteBufferViewBEGetAndBitwiseOrAcquireInt...OK
-HeapByteBufferViewBEGetAndBitwiseOrAcquireLong...OK
-HeapByteBufferViewBEGetAndBitwiseOrAcquireFloat...OK
-HeapByteBufferViewBEGetAndBitwiseOrAcquireDouble...OK
-HeapByteBufferViewBEGetAndBitwiseAndShort...OK
-HeapByteBufferViewBEGetAndBitwiseAndChar...OK
-HeapByteBufferViewBEGetAndBitwiseAndInt...OK
-HeapByteBufferViewBEGetAndBitwiseAndLong...OK
-HeapByteBufferViewBEGetAndBitwiseAndFloat...OK
-HeapByteBufferViewBEGetAndBitwiseAndDouble...OK
-HeapByteBufferViewBEGetAndBitwiseAndReleaseShort...OK
-HeapByteBufferViewBEGetAndBitwiseAndReleaseChar...OK
-HeapByteBufferViewBEGetAndBitwiseAndReleaseInt...OK
-HeapByteBufferViewBEGetAndBitwiseAndReleaseLong...OK
-HeapByteBufferViewBEGetAndBitwiseAndReleaseFloat...OK
-HeapByteBufferViewBEGetAndBitwiseAndReleaseDouble...OK
-HeapByteBufferViewBEGetAndBitwiseAndAcquireShort...OK
-HeapByteBufferViewBEGetAndBitwiseAndAcquireChar...OK
-HeapByteBufferViewBEGetAndBitwiseAndAcquireInt...OK
-HeapByteBufferViewBEGetAndBitwiseAndAcquireLong...OK
-HeapByteBufferViewBEGetAndBitwiseAndAcquireFloat...OK
-HeapByteBufferViewBEGetAndBitwiseAndAcquireDouble...OK
-HeapByteBufferViewBEGetAndBitwiseXorShort...OK
-HeapByteBufferViewBEGetAndBitwiseXorChar...OK
-HeapByteBufferViewBEGetAndBitwiseXorInt...OK
-HeapByteBufferViewBEGetAndBitwiseXorLong...OK
-HeapByteBufferViewBEGetAndBitwiseXorFloat...OK
-HeapByteBufferViewBEGetAndBitwiseXorDouble...OK
-HeapByteBufferViewBEGetAndBitwiseXorReleaseShort...OK
-HeapByteBufferViewBEGetAndBitwiseXorReleaseChar...OK
-HeapByteBufferViewBEGetAndBitwiseXorReleaseInt...OK
-HeapByteBufferViewBEGetAndBitwiseXorReleaseLong...OK
-HeapByteBufferViewBEGetAndBitwiseXorReleaseFloat...OK
-HeapByteBufferViewBEGetAndBitwiseXorReleaseDouble...OK
-HeapByteBufferViewBEGetAndBitwiseXorAcquireShort...OK
-HeapByteBufferViewBEGetAndBitwiseXorAcquireChar...OK
-HeapByteBufferViewBEGetAndBitwiseXorAcquireInt...OK
-HeapByteBufferViewBEGetAndBitwiseXorAcquireLong...OK
-HeapByteBufferViewBEGetAndBitwiseXorAcquireFloat...OK
-HeapByteBufferViewBEGetAndBitwiseXorAcquireDouble...OK
-HeapByteBufferReadOnlyViewLEGetShort...OK
-HeapByteBufferReadOnlyViewLEGetChar...OK
-HeapByteBufferReadOnlyViewLEGetInt...OK
-HeapByteBufferReadOnlyViewLEGetLong...OK
-HeapByteBufferReadOnlyViewLEGetFloat...OK
-HeapByteBufferReadOnlyViewLEGetDouble...OK
-HeapByteBufferReadOnlyViewLESetShort...OK
-HeapByteBufferReadOnlyViewLESetChar...OK
-HeapByteBufferReadOnlyViewLESetInt...OK
-HeapByteBufferReadOnlyViewLESetLong...OK
-HeapByteBufferReadOnlyViewLESetFloat...OK
-HeapByteBufferReadOnlyViewLESetDouble...OK
-HeapByteBufferReadOnlyViewLEGetVolatileShort...OK
-HeapByteBufferReadOnlyViewLEGetVolatileChar...OK
-HeapByteBufferReadOnlyViewLEGetVolatileInt...OK
-HeapByteBufferReadOnlyViewLEGetVolatileLong...OK
-HeapByteBufferReadOnlyViewLEGetVolatileFloat...OK
-HeapByteBufferReadOnlyViewLEGetVolatileDouble...OK
-HeapByteBufferReadOnlyViewLESetVolatileShort...OK
-HeapByteBufferReadOnlyViewLESetVolatileChar...OK
-HeapByteBufferReadOnlyViewLESetVolatileInt...OK
-HeapByteBufferReadOnlyViewLESetVolatileLong...OK
-HeapByteBufferReadOnlyViewLESetVolatileFloat...OK
-HeapByteBufferReadOnlyViewLESetVolatileDouble...OK
-HeapByteBufferReadOnlyViewLEGetAcquireShort...OK
-HeapByteBufferReadOnlyViewLEGetAcquireChar...OK
-HeapByteBufferReadOnlyViewLEGetAcquireInt...OK
-HeapByteBufferReadOnlyViewLEGetAcquireLong...OK
-HeapByteBufferReadOnlyViewLEGetAcquireFloat...OK
-HeapByteBufferReadOnlyViewLEGetAcquireDouble...OK
-HeapByteBufferReadOnlyViewLESetReleaseShort...OK
-HeapByteBufferReadOnlyViewLESetReleaseChar...OK
-HeapByteBufferReadOnlyViewLESetReleaseInt...OK
-HeapByteBufferReadOnlyViewLESetReleaseLong...OK
-HeapByteBufferReadOnlyViewLESetReleaseFloat...OK
-HeapByteBufferReadOnlyViewLESetReleaseDouble...OK
-HeapByteBufferReadOnlyViewLEGetOpaqueShort...OK
-HeapByteBufferReadOnlyViewLEGetOpaqueChar...OK
-HeapByteBufferReadOnlyViewLEGetOpaqueInt...OK
-HeapByteBufferReadOnlyViewLEGetOpaqueLong...OK
-HeapByteBufferReadOnlyViewLEGetOpaqueFloat...OK
-HeapByteBufferReadOnlyViewLEGetOpaqueDouble...OK
-HeapByteBufferReadOnlyViewLESetOpaqueShort...OK
-HeapByteBufferReadOnlyViewLESetOpaqueChar...OK
-HeapByteBufferReadOnlyViewLESetOpaqueInt...OK
-HeapByteBufferReadOnlyViewLESetOpaqueLong...OK
-HeapByteBufferReadOnlyViewLESetOpaqueFloat...OK
-HeapByteBufferReadOnlyViewLESetOpaqueDouble...OK
-HeapByteBufferReadOnlyViewLECompareAndSetShort...OK
-HeapByteBufferReadOnlyViewLECompareAndSetChar...OK
-HeapByteBufferReadOnlyViewLECompareAndSetInt...OK
-HeapByteBufferReadOnlyViewLECompareAndSetLong...OK
-HeapByteBufferReadOnlyViewLECompareAndSetFloat...OK
-HeapByteBufferReadOnlyViewLECompareAndSetDouble...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeShort...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeChar...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeInt...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeLong...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeFloat...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeDouble...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireShort...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireChar...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireInt...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireLong...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireFloat...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireDouble...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseShort...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseChar...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseInt...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseLong...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseFloat...OK
-HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseDouble...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainShort...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainChar...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainInt...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainLong...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainFloat...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainDouble...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetShort...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetChar...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetInt...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetLong...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetFloat...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetDouble...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireShort...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireChar...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireInt...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireLong...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireFloat...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireDouble...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseShort...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseChar...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseInt...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseLong...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseFloat...OK
-HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndSetShort...OK
-HeapByteBufferReadOnlyViewLEGetAndSetChar...OK
-HeapByteBufferReadOnlyViewLEGetAndSetInt...OK
-HeapByteBufferReadOnlyViewLEGetAndSetLong...OK
-HeapByteBufferReadOnlyViewLEGetAndSetFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndSetDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndSetAcquireShort...OK
-HeapByteBufferReadOnlyViewLEGetAndSetAcquireChar...OK
-HeapByteBufferReadOnlyViewLEGetAndSetAcquireInt...OK
-HeapByteBufferReadOnlyViewLEGetAndSetAcquireLong...OK
-HeapByteBufferReadOnlyViewLEGetAndSetAcquireFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndSetAcquireDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndSetReleaseShort...OK
-HeapByteBufferReadOnlyViewLEGetAndSetReleaseChar...OK
-HeapByteBufferReadOnlyViewLEGetAndSetReleaseInt...OK
-HeapByteBufferReadOnlyViewLEGetAndSetReleaseLong...OK
-HeapByteBufferReadOnlyViewLEGetAndSetReleaseFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndSetReleaseDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndAddShort...OK
-HeapByteBufferReadOnlyViewLEGetAndAddChar...OK
-HeapByteBufferReadOnlyViewLEGetAndAddInt...OK
-HeapByteBufferReadOnlyViewLEGetAndAddLong...OK
-HeapByteBufferReadOnlyViewLEGetAndAddFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndAddDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndAddAcquireShort...OK
-HeapByteBufferReadOnlyViewLEGetAndAddAcquireChar...OK
-HeapByteBufferReadOnlyViewLEGetAndAddAcquireInt...OK
-HeapByteBufferReadOnlyViewLEGetAndAddAcquireLong...OK
-HeapByteBufferReadOnlyViewLEGetAndAddAcquireFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndAddAcquireDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndAddReleaseShort...OK
-HeapByteBufferReadOnlyViewLEGetAndAddReleaseChar...OK
-HeapByteBufferReadOnlyViewLEGetAndAddReleaseInt...OK
-HeapByteBufferReadOnlyViewLEGetAndAddReleaseLong...OK
-HeapByteBufferReadOnlyViewLEGetAndAddReleaseFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndAddReleaseDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrShort...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrChar...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrInt...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrLong...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseShort...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseChar...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseInt...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseLong...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireShort...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireChar...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireInt...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireLong...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndShort...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndChar...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndInt...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndLong...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseShort...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseChar...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseInt...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseLong...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireShort...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireChar...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireInt...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireLong...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorShort...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorChar...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorInt...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorLong...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseShort...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseChar...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseInt...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseLong...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseDouble...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireShort...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireChar...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireInt...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireLong...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireFloat...OK
-HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireDouble...OK
-HeapByteBufferReadOnlyViewBEGetShort...OK
-HeapByteBufferReadOnlyViewBEGetChar...OK
-HeapByteBufferReadOnlyViewBEGetInt...OK
-HeapByteBufferReadOnlyViewBEGetLong...OK
-HeapByteBufferReadOnlyViewBEGetFloat...OK
-HeapByteBufferReadOnlyViewBEGetDouble...OK
-HeapByteBufferReadOnlyViewBESetShort...OK
-HeapByteBufferReadOnlyViewBESetChar...OK
-HeapByteBufferReadOnlyViewBESetInt...OK
-HeapByteBufferReadOnlyViewBESetLong...OK
-HeapByteBufferReadOnlyViewBESetFloat...OK
-HeapByteBufferReadOnlyViewBESetDouble...OK
-HeapByteBufferReadOnlyViewBEGetVolatileShort...OK
-HeapByteBufferReadOnlyViewBEGetVolatileChar...OK
-HeapByteBufferReadOnlyViewBEGetVolatileInt...OK
-HeapByteBufferReadOnlyViewBEGetVolatileLong...OK
-HeapByteBufferReadOnlyViewBEGetVolatileFloat...OK
-HeapByteBufferReadOnlyViewBEGetVolatileDouble...OK
-HeapByteBufferReadOnlyViewBESetVolatileShort...OK
-HeapByteBufferReadOnlyViewBESetVolatileChar...OK
-HeapByteBufferReadOnlyViewBESetVolatileInt...OK
-HeapByteBufferReadOnlyViewBESetVolatileLong...OK
-HeapByteBufferReadOnlyViewBESetVolatileFloat...OK
-HeapByteBufferReadOnlyViewBESetVolatileDouble...OK
-HeapByteBufferReadOnlyViewBEGetAcquireShort...OK
-HeapByteBufferReadOnlyViewBEGetAcquireChar...OK
-HeapByteBufferReadOnlyViewBEGetAcquireInt...OK
-HeapByteBufferReadOnlyViewBEGetAcquireLong...OK
-HeapByteBufferReadOnlyViewBEGetAcquireFloat...OK
-HeapByteBufferReadOnlyViewBEGetAcquireDouble...OK
-HeapByteBufferReadOnlyViewBESetReleaseShort...OK
-HeapByteBufferReadOnlyViewBESetReleaseChar...OK
-HeapByteBufferReadOnlyViewBESetReleaseInt...OK
-HeapByteBufferReadOnlyViewBESetReleaseLong...OK
-HeapByteBufferReadOnlyViewBESetReleaseFloat...OK
-HeapByteBufferReadOnlyViewBESetReleaseDouble...OK
-HeapByteBufferReadOnlyViewBEGetOpaqueShort...OK
-HeapByteBufferReadOnlyViewBEGetOpaqueChar...OK
-HeapByteBufferReadOnlyViewBEGetOpaqueInt...OK
-HeapByteBufferReadOnlyViewBEGetOpaqueLong...OK
-HeapByteBufferReadOnlyViewBEGetOpaqueFloat...OK
-HeapByteBufferReadOnlyViewBEGetOpaqueDouble...OK
-HeapByteBufferReadOnlyViewBESetOpaqueShort...OK
-HeapByteBufferReadOnlyViewBESetOpaqueChar...OK
-HeapByteBufferReadOnlyViewBESetOpaqueInt...OK
-HeapByteBufferReadOnlyViewBESetOpaqueLong...OK
-HeapByteBufferReadOnlyViewBESetOpaqueFloat...OK
-HeapByteBufferReadOnlyViewBESetOpaqueDouble...OK
-HeapByteBufferReadOnlyViewBECompareAndSetShort...OK
-HeapByteBufferReadOnlyViewBECompareAndSetChar...OK
-HeapByteBufferReadOnlyViewBECompareAndSetInt...OK
-HeapByteBufferReadOnlyViewBECompareAndSetLong...OK
-HeapByteBufferReadOnlyViewBECompareAndSetFloat...OK
-HeapByteBufferReadOnlyViewBECompareAndSetDouble...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeShort...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeChar...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeInt...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeLong...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeFloat...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeDouble...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireShort...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireChar...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireInt...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireLong...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireFloat...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireDouble...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseShort...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseChar...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseInt...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseLong...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseFloat...OK
-HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseDouble...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainShort...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainChar...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainInt...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainLong...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainFloat...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainDouble...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetShort...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetChar...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetInt...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetLong...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetFloat...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetDouble...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireShort...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireChar...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireInt...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireLong...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireFloat...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireDouble...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseShort...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseChar...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseInt...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseLong...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseFloat...OK
-HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndSetShort...OK
-HeapByteBufferReadOnlyViewBEGetAndSetChar...OK
-HeapByteBufferReadOnlyViewBEGetAndSetInt...OK
-HeapByteBufferReadOnlyViewBEGetAndSetLong...OK
-HeapByteBufferReadOnlyViewBEGetAndSetFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndSetDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndSetAcquireShort...OK
-HeapByteBufferReadOnlyViewBEGetAndSetAcquireChar...OK
-HeapByteBufferReadOnlyViewBEGetAndSetAcquireInt...OK
-HeapByteBufferReadOnlyViewBEGetAndSetAcquireLong...OK
-HeapByteBufferReadOnlyViewBEGetAndSetAcquireFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndSetAcquireDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndSetReleaseShort...OK
-HeapByteBufferReadOnlyViewBEGetAndSetReleaseChar...OK
-HeapByteBufferReadOnlyViewBEGetAndSetReleaseInt...OK
-HeapByteBufferReadOnlyViewBEGetAndSetReleaseLong...OK
-HeapByteBufferReadOnlyViewBEGetAndSetReleaseFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndSetReleaseDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndAddShort...OK
-HeapByteBufferReadOnlyViewBEGetAndAddChar...OK
-HeapByteBufferReadOnlyViewBEGetAndAddInt...OK
-HeapByteBufferReadOnlyViewBEGetAndAddLong...OK
-HeapByteBufferReadOnlyViewBEGetAndAddFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndAddDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndAddAcquireShort...OK
-HeapByteBufferReadOnlyViewBEGetAndAddAcquireChar...OK
-HeapByteBufferReadOnlyViewBEGetAndAddAcquireInt...OK
-HeapByteBufferReadOnlyViewBEGetAndAddAcquireLong...OK
-HeapByteBufferReadOnlyViewBEGetAndAddAcquireFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndAddAcquireDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndAddReleaseShort...OK
-HeapByteBufferReadOnlyViewBEGetAndAddReleaseChar...OK
-HeapByteBufferReadOnlyViewBEGetAndAddReleaseInt...OK
-HeapByteBufferReadOnlyViewBEGetAndAddReleaseLong...OK
-HeapByteBufferReadOnlyViewBEGetAndAddReleaseFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndAddReleaseDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrShort...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrChar...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrInt...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrLong...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseShort...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseChar...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseInt...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseLong...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireShort...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireChar...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireInt...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireLong...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndShort...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndChar...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndInt...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndLong...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseShort...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseChar...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseInt...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseLong...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireShort...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireChar...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireInt...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireLong...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorShort...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorChar...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorInt...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorLong...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseShort...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseChar...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseInt...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseLong...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseDouble...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireShort...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireChar...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireInt...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireLong...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireFloat...OK
-HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireDouble...OK
-FieldGetWidget...OK
-FieldSetWidget...OK
-FieldGetVolatileWidget...OK
-FieldSetVolatileWidget...OK
-FieldGetAcquireWidget...OK
-FieldSetReleaseWidget...OK
-FieldGetOpaqueWidget...OK
-FieldSetOpaqueWidget...OK
-FieldCompareAndSetWidget...OK
-FieldCompareAndExchangeWidget...OK
-FieldCompareAndExchangeAcquireWidget...OK
-FieldCompareAndExchangeReleaseWidget...OK
-FieldWeakCompareAndSetPlainWidget...OK
-FieldWeakCompareAndSetWidget...OK
-FieldWeakCompareAndSetAcquireWidget...OK
-FieldWeakCompareAndSetReleaseWidget...OK
-FieldGetAndSetWidget...OK
-FieldGetAndSetAcquireWidget...OK
-FieldGetAndSetReleaseWidget...OK
-FieldGetAndAddWidget...OK
-FieldGetAndAddAcquireWidget...OK
-FieldGetAndAddReleaseWidget...OK
-FieldGetAndBitwiseOrWidget...OK
-FieldGetAndBitwiseOrReleaseWidget...OK
-FieldGetAndBitwiseOrAcquireWidget...OK
-FieldGetAndBitwiseAndWidget...OK
-FieldGetAndBitwiseAndReleaseWidget...OK
-FieldGetAndBitwiseAndAcquireWidget...OK
-FieldGetAndBitwiseXorWidget...OK
-FieldGetAndBitwiseXorReleaseWidget...OK
-FieldGetAndBitwiseXorAcquireWidget...OK
-FinalFieldGetWidget...OK
-FinalFieldSetWidget...OK
-FinalFieldGetVolatileWidget...OK
-FinalFieldSetVolatileWidget...OK
-FinalFieldGetAcquireWidget...OK
-FinalFieldSetReleaseWidget...OK
-FinalFieldGetOpaqueWidget...OK
-FinalFieldSetOpaqueWidget...OK
-FinalFieldCompareAndSetWidget...OK
-FinalFieldCompareAndExchangeWidget...OK
-FinalFieldCompareAndExchangeAcquireWidget...OK
-FinalFieldCompareAndExchangeReleaseWidget...OK
-FinalFieldWeakCompareAndSetPlainWidget...OK
-FinalFieldWeakCompareAndSetWidget...OK
-FinalFieldWeakCompareAndSetAcquireWidget...OK
-FinalFieldWeakCompareAndSetReleaseWidget...OK
-FinalFieldGetAndSetWidget...OK
-FinalFieldGetAndSetAcquireWidget...OK
-FinalFieldGetAndSetReleaseWidget...OK
-FinalFieldGetAndAddWidget...OK
-FinalFieldGetAndAddAcquireWidget...OK
-FinalFieldGetAndAddReleaseWidget...OK
-FinalFieldGetAndBitwiseOrWidget...OK
-FinalFieldGetAndBitwiseOrReleaseWidget...OK
-FinalFieldGetAndBitwiseOrAcquireWidget...OK
-FinalFieldGetAndBitwiseAndWidget...OK
-FinalFieldGetAndBitwiseAndReleaseWidget...OK
-FinalFieldGetAndBitwiseAndAcquireWidget...OK
-FinalFieldGetAndBitwiseXorWidget...OK
-FinalFieldGetAndBitwiseXorReleaseWidget...OK
-FinalFieldGetAndBitwiseXorAcquireWidget...OK
-StaticFieldGetWidget...OK
-StaticFieldSetWidget...OK
-StaticFieldGetVolatileWidget...OK
-StaticFieldSetVolatileWidget...OK
-StaticFieldGetAcquireWidget...OK
-StaticFieldSetReleaseWidget...OK
-StaticFieldGetOpaqueWidget...OK
-StaticFieldSetOpaqueWidget...OK
-StaticFieldCompareAndSetWidget...OK
-StaticFieldCompareAndExchangeWidget...OK
-StaticFieldCompareAndExchangeAcquireWidget...OK
-StaticFieldCompareAndExchangeReleaseWidget...OK
-StaticFieldWeakCompareAndSetPlainWidget...OK
-StaticFieldWeakCompareAndSetWidget...OK
-StaticFieldWeakCompareAndSetAcquireWidget...OK
-StaticFieldWeakCompareAndSetReleaseWidget...OK
-StaticFieldGetAndSetWidget...OK
-StaticFieldGetAndSetAcquireWidget...OK
-StaticFieldGetAndSetReleaseWidget...OK
-StaticFieldGetAndAddWidget...OK
-StaticFieldGetAndAddAcquireWidget...OK
-StaticFieldGetAndAddReleaseWidget...OK
-StaticFieldGetAndBitwiseOrWidget...OK
-StaticFieldGetAndBitwiseOrReleaseWidget...OK
-StaticFieldGetAndBitwiseOrAcquireWidget...OK
-StaticFieldGetAndBitwiseAndWidget...OK
-StaticFieldGetAndBitwiseAndReleaseWidget...OK
-StaticFieldGetAndBitwiseAndAcquireWidget...OK
-StaticFieldGetAndBitwiseXorWidget...OK
-StaticFieldGetAndBitwiseXorReleaseWidget...OK
-StaticFieldGetAndBitwiseXorAcquireWidget...OK
-StaticFinalFieldGetWidget...OK
-StaticFinalFieldSetWidget...OK
-StaticFinalFieldGetVolatileWidget...OK
-StaticFinalFieldSetVolatileWidget...OK
-StaticFinalFieldGetAcquireWidget...OK
-StaticFinalFieldSetReleaseWidget...OK
-StaticFinalFieldGetOpaqueWidget...OK
-StaticFinalFieldSetOpaqueWidget...OK
-StaticFinalFieldCompareAndSetWidget...OK
-StaticFinalFieldCompareAndExchangeWidget...OK
-StaticFinalFieldCompareAndExchangeAcquireWidget...OK
-StaticFinalFieldCompareAndExchangeReleaseWidget...OK
-StaticFinalFieldWeakCompareAndSetPlainWidget...OK
-StaticFinalFieldWeakCompareAndSetWidget...OK
-StaticFinalFieldWeakCompareAndSetAcquireWidget...OK
-StaticFinalFieldWeakCompareAndSetReleaseWidget...OK
-StaticFinalFieldGetAndSetWidget...OK
-StaticFinalFieldGetAndSetAcquireWidget...OK
-StaticFinalFieldGetAndSetReleaseWidget...OK
-StaticFinalFieldGetAndAddWidget...OK
-StaticFinalFieldGetAndAddAcquireWidget...OK
-StaticFinalFieldGetAndAddReleaseWidget...OK
-StaticFinalFieldGetAndBitwiseOrWidget...OK
-StaticFinalFieldGetAndBitwiseOrReleaseWidget...OK
-StaticFinalFieldGetAndBitwiseOrAcquireWidget...OK
-StaticFinalFieldGetAndBitwiseAndWidget...OK
-StaticFinalFieldGetAndBitwiseAndReleaseWidget...OK
-StaticFinalFieldGetAndBitwiseAndAcquireWidget...OK
-StaticFinalFieldGetAndBitwiseXorWidget...OK
-StaticFinalFieldGetAndBitwiseXorReleaseWidget...OK
-StaticFinalFieldGetAndBitwiseXorAcquireWidget...OK
-ArrayElementGetWidget...OK
-ArrayElementSetWidget...OK
-ArrayElementGetVolatileWidget...OK
-ArrayElementSetVolatileWidget...OK
-ArrayElementGetAcquireWidget...OK
-ArrayElementSetReleaseWidget...OK
-ArrayElementGetOpaqueWidget...OK
-ArrayElementSetOpaqueWidget...OK
-ArrayElementCompareAndSetWidget...OK
-ArrayElementCompareAndExchangeWidget...OK
-ArrayElementCompareAndExchangeAcquireWidget...OK
-ArrayElementCompareAndExchangeReleaseWidget...OK
-ArrayElementWeakCompareAndSetPlainWidget...OK
-ArrayElementWeakCompareAndSetWidget...OK
-ArrayElementWeakCompareAndSetAcquireWidget...OK
-ArrayElementWeakCompareAndSetReleaseWidget...OK
-ArrayElementGetAndSetWidget...OK
-ArrayElementGetAndSetAcquireWidget...OK
-ArrayElementGetAndSetReleaseWidget...OK
-ArrayElementGetAndAddWidget...OK
-ArrayElementGetAndAddAcquireWidget...OK
-ArrayElementGetAndAddReleaseWidget...OK
-ArrayElementGetAndBitwiseOrWidget...OK
-ArrayElementGetAndBitwiseOrReleaseWidget...OK
-ArrayElementGetAndBitwiseOrAcquireWidget...OK
-ArrayElementGetAndBitwiseAndWidget...OK
-ArrayElementGetAndBitwiseAndReleaseWidget...OK
-ArrayElementGetAndBitwiseAndAcquireWidget...OK
-ArrayElementGetAndBitwiseXorWidget...OK
-ArrayElementGetAndBitwiseXorReleaseWidget...OK
-ArrayElementGetAndBitwiseXorAcquireWidget...OK
-BoxingReturnGetBoolean...OK
-BoxingSetBoolean...OK
-BoxingReturnGetVolatileBoolean...OK
-BoxingSetVolatileBoolean...OK
-BoxingReturnGetAcquireBoolean...OK
-BoxingSetReleaseBoolean...OK
-BoxingReturnGetOpaqueBoolean...OK
-BoxingSetOpaqueBoolean...OK
-BoxingCompareAndSetBoolean...OK
-BoxingCompareAndExchangeBoolean...OK
-BoxingCompareAndExchangeAcquireBoolean...OK
-BoxingCompareAndExchangeReleaseBoolean...OK
-BoxingWeakCompareAndSetPlainBoolean...OK
-BoxingWeakCompareAndSetBoolean...OK
-BoxingWeakCompareAndSetAcquireBoolean...OK
-BoxingWeakCompareAndSetReleaseBoolean...OK
-BoxingGetAndSetBoolean...OK
-BoxingGetAndSetAcquireBoolean...OK
-BoxingGetAndSetReleaseBoolean...OK
-BoxingGetAndAddBoolean...OK
-BoxingGetAndAddAcquireBoolean...OK
-BoxingGetAndAddReleaseBoolean...OK
-BoxingGetAndBitwiseOrBoolean...OK
-BoxingGetAndBitwiseOrReleaseBoolean...OK
-BoxingGetAndBitwiseOrAcquireBoolean...OK
-BoxingGetAndBitwiseAndBoolean...OK
-BoxingGetAndBitwiseAndReleaseBoolean...OK
-BoxingGetAndBitwiseAndAcquireBoolean...OK
-BoxingGetAndBitwiseXorBoolean...OK
-BoxingGetAndBitwiseXorReleaseBoolean...OK
-BoxingGetAndBitwiseXorAcquireBoolean...OK
-BoxingReturnGetByte...OK
-BoxingSetByte...OK
-BoxingReturnGetVolatileByte...OK
-BoxingSetVolatileByte...OK
-BoxingReturnGetAcquireByte...OK
-BoxingSetReleaseByte...OK
-BoxingReturnGetOpaqueByte...OK
-BoxingSetOpaqueByte...OK
-BoxingCompareAndSetByte...OK
-BoxingCompareAndExchangeByte...OK
-BoxingCompareAndExchangeAcquireByte...OK
-BoxingCompareAndExchangeReleaseByte...OK
-BoxingWeakCompareAndSetPlainByte...OK
-BoxingWeakCompareAndSetByte...OK
-BoxingWeakCompareAndSetAcquireByte...OK
-BoxingWeakCompareAndSetReleaseByte...OK
-BoxingGetAndSetByte...OK
-BoxingGetAndSetAcquireByte...OK
-BoxingGetAndSetReleaseByte...OK
-BoxingGetAndAddByte...OK
-BoxingGetAndAddAcquireByte...OK
-BoxingGetAndAddReleaseByte...OK
-BoxingGetAndBitwiseOrByte...OK
-BoxingGetAndBitwiseOrReleaseByte...OK
-BoxingGetAndBitwiseOrAcquireByte...OK
-BoxingGetAndBitwiseAndByte...OK
-BoxingGetAndBitwiseAndReleaseByte...OK
-BoxingGetAndBitwiseAndAcquireByte...OK
-BoxingGetAndBitwiseXorByte...OK
-BoxingGetAndBitwiseXorReleaseByte...OK
-BoxingGetAndBitwiseXorAcquireByte...OK
-BoxingReturnGetShort...OK
-BoxingSetShort...OK
-BoxingReturnGetVolatileShort...OK
-BoxingSetVolatileShort...OK
-BoxingReturnGetAcquireShort...OK
-BoxingSetReleaseShort...OK
-BoxingReturnGetOpaqueShort...OK
-BoxingSetOpaqueShort...OK
-BoxingCompareAndSetShort...OK
-BoxingCompareAndExchangeShort...OK
-BoxingCompareAndExchangeAcquireShort...OK
-BoxingCompareAndExchangeReleaseShort...OK
-BoxingWeakCompareAndSetPlainShort...OK
-BoxingWeakCompareAndSetShort...OK
-BoxingWeakCompareAndSetAcquireShort...OK
-BoxingWeakCompareAndSetReleaseShort...OK
-BoxingGetAndSetShort...OK
-BoxingGetAndSetAcquireShort...OK
-BoxingGetAndSetReleaseShort...OK
-BoxingGetAndAddShort...OK
-BoxingGetAndAddAcquireShort...OK
-BoxingGetAndAddReleaseShort...OK
-BoxingGetAndBitwiseOrShort...OK
-BoxingGetAndBitwiseOrReleaseShort...OK
-BoxingGetAndBitwiseOrAcquireShort...OK
-BoxingGetAndBitwiseAndShort...OK
-BoxingGetAndBitwiseAndReleaseShort...OK
-BoxingGetAndBitwiseAndAcquireShort...OK
-BoxingGetAndBitwiseXorShort...OK
-BoxingGetAndBitwiseXorReleaseShort...OK
-BoxingGetAndBitwiseXorAcquireShort...OK
-BoxingReturnGetChar...OK
-BoxingSetChar...OK
-BoxingReturnGetVolatileChar...OK
-BoxingSetVolatileChar...OK
-BoxingReturnGetAcquireChar...OK
-BoxingSetReleaseChar...OK
-BoxingReturnGetOpaqueChar...OK
-BoxingSetOpaqueChar...OK
-BoxingCompareAndSetChar...OK
-BoxingCompareAndExchangeChar...OK
-BoxingCompareAndExchangeAcquireChar...OK
-BoxingCompareAndExchangeReleaseChar...OK
-BoxingWeakCompareAndSetPlainChar...OK
-BoxingWeakCompareAndSetChar...OK
-BoxingWeakCompareAndSetAcquireChar...OK
-BoxingWeakCompareAndSetReleaseChar...OK
-BoxingGetAndSetChar...OK
-BoxingGetAndSetAcquireChar...OK
-BoxingGetAndSetReleaseChar...OK
-BoxingGetAndAddChar...OK
-BoxingGetAndAddAcquireChar...OK
-BoxingGetAndAddReleaseChar...OK
-BoxingGetAndBitwiseOrChar...OK
-BoxingGetAndBitwiseOrReleaseChar...OK
-BoxingGetAndBitwiseOrAcquireChar...OK
-BoxingGetAndBitwiseAndChar...OK
-BoxingGetAndBitwiseAndReleaseChar...OK
-BoxingGetAndBitwiseAndAcquireChar...OK
-BoxingGetAndBitwiseXorChar...OK
-BoxingGetAndBitwiseXorReleaseChar...OK
-BoxingGetAndBitwiseXorAcquireChar...OK
-BoxingReturnGetInt...OK
-BoxingSetInt...OK
-BoxingReturnGetVolatileInt...OK
-BoxingSetVolatileInt...OK
-BoxingReturnGetAcquireInt...OK
-BoxingSetReleaseInt...OK
-BoxingReturnGetOpaqueInt...OK
-BoxingSetOpaqueInt...OK
-BoxingCompareAndSetInt...OK
-BoxingCompareAndExchangeInt...OK
-BoxingCompareAndExchangeAcquireInt...OK
-BoxingCompareAndExchangeReleaseInt...OK
-BoxingWeakCompareAndSetPlainInt...OK
-BoxingWeakCompareAndSetInt...OK
-BoxingWeakCompareAndSetAcquireInt...OK
-BoxingWeakCompareAndSetReleaseInt...OK
-BoxingGetAndSetInt...OK
-BoxingGetAndSetAcquireInt...OK
-BoxingGetAndSetReleaseInt...OK
-BoxingGetAndAddInt...OK
-BoxingGetAndAddAcquireInt...OK
-BoxingGetAndAddReleaseInt...OK
-BoxingGetAndBitwiseOrInt...OK
-BoxingGetAndBitwiseOrReleaseInt...OK
-BoxingGetAndBitwiseOrAcquireInt...OK
-BoxingGetAndBitwiseAndInt...OK
-BoxingGetAndBitwiseAndReleaseInt...OK
-BoxingGetAndBitwiseAndAcquireInt...OK
-BoxingGetAndBitwiseXorInt...OK
-BoxingGetAndBitwiseXorReleaseInt...OK
-BoxingGetAndBitwiseXorAcquireInt...OK
-BoxingReturnGetLong...OK
-BoxingSetLong...OK
-BoxingReturnGetVolatileLong...OK
-BoxingSetVolatileLong...OK
-BoxingReturnGetAcquireLong...OK
-BoxingSetReleaseLong...OK
-BoxingReturnGetOpaqueLong...OK
-BoxingSetOpaqueLong...OK
-BoxingCompareAndSetLong...OK
-BoxingCompareAndExchangeLong...OK
-BoxingCompareAndExchangeAcquireLong...OK
-BoxingCompareAndExchangeReleaseLong...OK
-BoxingWeakCompareAndSetPlainLong...OK
-BoxingWeakCompareAndSetLong...OK
-BoxingWeakCompareAndSetAcquireLong...OK
-BoxingWeakCompareAndSetReleaseLong...OK
-BoxingGetAndSetLong...OK
-BoxingGetAndSetAcquireLong...OK
-BoxingGetAndSetReleaseLong...OK
-BoxingGetAndAddLong...OK
-BoxingGetAndAddAcquireLong...OK
-BoxingGetAndAddReleaseLong...OK
-BoxingGetAndBitwiseOrLong...OK
-BoxingGetAndBitwiseOrReleaseLong...OK
-BoxingGetAndBitwiseOrAcquireLong...OK
-BoxingGetAndBitwiseAndLong...OK
-BoxingGetAndBitwiseAndReleaseLong...OK
-BoxingGetAndBitwiseAndAcquireLong...OK
-BoxingGetAndBitwiseXorLong...OK
-BoxingGetAndBitwiseXorReleaseLong...OK
-BoxingGetAndBitwiseXorAcquireLong...OK
-BoxingReturnGetFloat...OK
-BoxingSetFloat...OK
-BoxingReturnGetVolatileFloat...OK
-BoxingSetVolatileFloat...OK
-BoxingReturnGetAcquireFloat...OK
-BoxingSetReleaseFloat...OK
-BoxingReturnGetOpaqueFloat...OK
-BoxingSetOpaqueFloat...OK
-BoxingCompareAndSetFloat...OK
-BoxingCompareAndExchangeFloat...OK
-BoxingCompareAndExchangeAcquireFloat...OK
-BoxingCompareAndExchangeReleaseFloat...OK
-BoxingWeakCompareAndSetPlainFloat...OK
-BoxingWeakCompareAndSetFloat...OK
-BoxingWeakCompareAndSetAcquireFloat...OK
-BoxingWeakCompareAndSetReleaseFloat...OK
-BoxingGetAndSetFloat...OK
-BoxingGetAndSetAcquireFloat...OK
-BoxingGetAndSetReleaseFloat...OK
-BoxingGetAndAddFloat...OK
-BoxingGetAndAddAcquireFloat...OK
-BoxingGetAndAddReleaseFloat...OK
-BoxingGetAndBitwiseOrFloat...OK
-BoxingGetAndBitwiseOrReleaseFloat...OK
-BoxingGetAndBitwiseOrAcquireFloat...OK
-BoxingGetAndBitwiseAndFloat...OK
-BoxingGetAndBitwiseAndReleaseFloat...OK
-BoxingGetAndBitwiseAndAcquireFloat...OK
-BoxingGetAndBitwiseXorFloat...OK
-BoxingGetAndBitwiseXorReleaseFloat...OK
-BoxingGetAndBitwiseXorAcquireFloat...OK
-BoxingReturnGetDouble...OK
-BoxingSetDouble...OK
-BoxingReturnGetVolatileDouble...OK
-BoxingSetVolatileDouble...OK
-BoxingReturnGetAcquireDouble...OK
-BoxingSetReleaseDouble...OK
-BoxingReturnGetOpaqueDouble...OK
-BoxingSetOpaqueDouble...OK
-BoxingCompareAndSetDouble...OK
-BoxingCompareAndExchangeDouble...OK
-BoxingCompareAndExchangeAcquireDouble...OK
-BoxingCompareAndExchangeReleaseDouble...OK
-BoxingWeakCompareAndSetPlainDouble...OK
-BoxingWeakCompareAndSetDouble...OK
-BoxingWeakCompareAndSetAcquireDouble...OK
-BoxingWeakCompareAndSetReleaseDouble...OK
-BoxingGetAndSetDouble...OK
-BoxingGetAndSetAcquireDouble...OK
-BoxingGetAndSetReleaseDouble...OK
-BoxingGetAndAddDouble...OK
-BoxingGetAndAddAcquireDouble...OK
-BoxingGetAndAddReleaseDouble...OK
-BoxingGetAndBitwiseOrDouble...OK
-BoxingGetAndBitwiseOrReleaseDouble...OK
-BoxingGetAndBitwiseOrAcquireDouble...OK
-BoxingGetAndBitwiseAndDouble...OK
-BoxingGetAndBitwiseAndReleaseDouble...OK
-BoxingGetAndBitwiseAndAcquireDouble...OK
-BoxingGetAndBitwiseXorDouble...OK
-BoxingGetAndBitwiseXorReleaseDouble...OK
-BoxingGetAndBitwiseXorAcquireDouble...OK
-NullReceiverTest...OK
-UnsupportedAccessModeTest...OK
-WrongArgumentTypeCausingWrongMethodTypeTest...OK
-TooManyArgumentsCausingWrongMethodTypeTest...OK
-TooFewArgumentsCausingWrongMethodTypeTest...OK
-ReturnTypeCausingWrongMethodTypeTest...OK
-UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest...OK
-FieldCoordinateTypeTest...OK
-ArrayElementOutOfBoundsIndexTest...OK
-ArrayElementBadIndexTypeTest...OK
-ArrayElementNullArrayTest...OK
-ArrayElementWrongArrayTypeTest...OK
-ArrayElementMissingIndexTest...OK
-ByteArrayViewOutOfBoundsIndexTest...OK
-ByteArrayViewUnalignedAccessesIndexTest...OK
-ByteArrayViewBadIndexTypeTest...OK
-ByteArrayViewMissingIndexTest...OK
-ByteArrayViewBadByteArrayTest...OK
-ByteBufferViewOutOfBoundsIndexTest...OK
-ByteBufferViewUnalignedAccessesIndexTest...OK
-ByteBufferViewBadIndexTypeTest...OK
-ByteBufferViewMissingIndexTest...OK
-ByteBufferViewBadByteBufferTest...OK
-VoidReturnTypeTest...OK
-BoxedNullBooleanThrowsNPETest...OK
-BoxedNullByteThrowsNPETest...OK
-BoxedNullCharacterThrowsNPETest...OK
-BoxedNullShortThrowsNPETest...OK
-BoxedNullIntegerThrowsNPETest...OK
-BoxedNullLongThrowsNPETest...OK
-BoxedNullFloatThrowsNPETest...OK
-BoxedNullDoubleThrowsNPETest...OK
-WideningBooleanArgumentTest...OK
-WideningByteArgumentTest...OK
-WideningCharacterArgumentTest...OK
-WideningShortArgumentTest...OK
-WideningIntegerArgumentTest...OK
-WideningLongArgumentTest...OK
-WideningFloatArgumentTest...OK
-WideningDoubleArgumentTest...OK
-WideningBooleanReturnValueTest...OK
-WideningByteReturnValueTest...OK
-WideningCharacterReturnValueTest...OK
-WideningShortReturnValueTest...OK
-WideningIntegerReturnValueTest...OK
-WideningLongReturnValueTest...OK
-WideningFloatReturnValueTest...OK
-WideningDoubleReturnValueTest...OK
-SubtypeTest...OK
-SupertypeTest...OK
-ImplicitBoxingIntegerTest...OK
-3182 successes, 0 skips, 0 failures.
diff --git a/test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java b/test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java
index 8f81c94..31a004e 100644
--- a/test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java
+++ b/test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java
@@ -76,6 +76,11 @@
                 failUnreachable();
             } catch (NullPointerException ex) {
             }
+            try {
+                byte unused = (byte) vh.get();
+                failUnreachable();
+            } catch (WrongMethodTypeException ex) {
+            }
         }
 
         public static void main(String[] args) {
diff --git a/test/712-varhandle-invocations/src/VarHandleFpCasTests.java b/test/712-varhandle-invocations/src/VarHandleFpCasTests.java
new file mode 100644
index 0000000..9c199e4
--- /dev/null
+++ b/test/712-varhandle-invocations/src/VarHandleFpCasTests.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 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.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class VarHandleFpCasTests {
+    public static class FieldFloatTest extends VarHandleUnitTest {
+        private static final VarHandle vh;
+
+        public static class A {
+            public float field;
+        }
+
+        static {
+            try {
+                vh = MethodHandles.lookup().findVarHandle(A.class, "field", float.class);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        protected void doTest() {
+            A a = new A();
+            assertTrue(vh.compareAndSet(a, 0.0f, 1.0f));
+            assertTrue(vh.compareAndSet(a, 1.0f, 0.0f));
+            assertFalse(vh.compareAndSet(a, -0.0f, Float.NaN));
+            assertTrue(vh.compareAndSet(a, 0.0f, Float.NaN));
+            assertTrue(vh.compareAndSet(a, Float.NaN, 0.0f));
+        }
+
+        public static void main(String[] args) {
+            new FieldFloatTest().run();
+        }
+    }
+
+    public static class FieldDoubleTest extends VarHandleUnitTest {
+        private static final VarHandle vh;
+
+        public static class A {
+            public double field;
+        }
+
+        static {
+            try {
+                vh = MethodHandles.lookup().findVarHandle(A.class, "field", double.class);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        protected void doTest() {
+            A a = new A();
+            assertTrue(vh.compareAndSet(a, 0.0, 1.0));
+            assertTrue(vh.compareAndSet(a, 1.0, 0.0));
+            assertFalse(vh.compareAndSet(a, -0.0, Double.NaN));
+            assertTrue(vh.compareAndSet(a, 0.0, Double.NaN));
+            assertTrue(vh.compareAndSet(a, Double.NaN, 0.0));
+        }
+
+        public static void main(String[] args) {
+            new FieldDoubleTest().run();
+        }
+    }
+
+    public static void main(String[] args) {
+        FieldFloatTest.main(args);
+        FieldDoubleTest.main(args);
+    }
+}
diff --git a/test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java b/test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java
index c0fbd49..73e3044 100644
--- a/test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java
+++ b/test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java
@@ -39,12 +39,14 @@
             // Void is always okay for a return type.
             vh.setVolatile(this, 33);
             vh.get(this);
-            vh.compareAndSet(this, 33, 44);
-            vh.compareAndSet(this, 27, 16);
-            vh.weakCompareAndSet(this, 17, 19);
             vh.getAndSet(this, 200000);
             vh.getAndBitwiseXor(this, 0x5a5a5a5a);
             vh.getAndAdd(this, 99);
+
+            // Return type of these is boolean (JLS9 S15.12), but check anyway.
+            vh.compareAndSet(this, 33, 44);
+            vh.compareAndSet(this, 27, 16);
+            vh.weakCompareAndSet(this, 17, 19);
         }
 
         public static void main(String[] args) {
@@ -668,7 +670,7 @@
             vh.set((short) 1);
             vh.set((int) 1);
             vh.set((long) 1);
-            vh.set((double) 1.0f);
+            vh.set((float) 1.0f);
             vh.set((double) 1.0);
         }
 
@@ -1215,6 +1217,11 @@
                 failUnreachable();
             } catch (UnsupportedOperationException e) {
             }
+            try {
+                boolean result = vh.compareAndSet(this, new Object(), Widget.ONE);
+                failUnreachable();
+            } catch (ClassCastException e) {
+            }
         }
     }
 
@@ -1246,6 +1253,105 @@
         }
     }
 
+    public static class InterfaceTest extends VarHandleUnitTest {
+        public interface ParentInterface {
+            int getValue();
+        }
+
+        public interface ChildInterface extends ParentInterface {
+            void setValue(int newValue);
+        }
+
+        public class A implements ParentInterface {
+            protected int value = 0;
+            public int getValue() { return value; }
+        }
+
+        public class B extends A implements ChildInterface {
+            public void setValue(int newValue) { value = newValue; }
+        }
+
+        private ParentInterface pi;
+        private A obj;
+
+        private VarHandle vh_pi;
+        private VarHandle vh_obj;
+        {
+            try {
+                vh_pi = MethodHandles.lookup().findVarHandle(InterfaceTest.class, "pi",
+                                                             InterfaceTest.ParentInterface.class);
+                vh_obj = MethodHandles.lookup().findVarHandle(InterfaceTest.class, "obj",
+                                                              InterfaceTest.A.class);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public static void main(String[] args) {
+            new InterfaceTest().run();
+        }
+
+        @Override
+        public void doTest() {
+            // Tests using VarHandle to field of type ParentInterface.
+            {
+                pi = (ParentInterface) new A();
+                ParentInterface p = (ParentInterface) vh_pi.get(this);
+                Object o = (Object) vh_pi.get(this);
+                try {
+                    ChildInterface c = (ChildInterface) vh_pi.get(this);
+                    failUnreachable();
+                } catch (ClassCastException expected) {}
+            }
+            {
+                pi = new B();
+                ParentInterface p = (ParentInterface) vh_pi.get(this);
+                B b = (B) vh_pi.get(this);
+                Object o = (Object) vh_pi.get(this);
+                ChildInterface c = (ChildInterface) vh_pi.get(this);
+            }
+            {
+                pi = null;
+                ParentInterface p = (ParentInterface) vh_pi.get(this);
+                B b = (B) vh_pi.get(this);
+                Object o = (Object) vh_pi.get(this);
+                ChildInterface c = (ChildInterface) vh_pi.get(this);
+            }
+
+            // Tests using VarHandle to field of type A.
+            {
+                obj = new A();
+                ParentInterface p = (ParentInterface) vh_obj.get(this);
+                Object o = (Object) vh_obj.get(this);
+                A a = (A) vh_obj.get(this);
+                try {
+                    B b = (B) vh_obj.get(this);
+                    failUnreachable();
+                } catch (ClassCastException e) {}
+                try {
+                    ChildInterface c = (ChildInterface) vh_obj.get(this);
+                    failUnreachable();
+                } catch (ClassCastException e) {}
+            }
+            {
+                obj = new B();
+                ParentInterface p = (ParentInterface) vh_obj.get(this);
+                Object o = (Object) vh_obj.get(this);
+                A a = (A) vh_obj.get(this);
+                B b = (B) vh_obj.get(this);
+                ChildInterface c = (ChildInterface) vh_obj.get(this);
+            }
+            {
+                obj = null;
+                ParentInterface p = (ParentInterface) vh_obj.get(this);
+                Object o = (Object) vh_obj.get(this);
+                A a = (A) vh_obj.get(this);
+                B b = (B) vh_obj.get(this);
+                ChildInterface c = (ChildInterface) vh_obj.get(this);
+            }
+        }
+    }
+
     public static class ImplicitBoxingIntegerTest extends VarHandleUnitTest {
         private static Integer field;
         private static final VarHandle vh;
@@ -1278,26 +1384,29 @@
             } catch (WrongMethodTypeException e) {
             }
             try {
-                vh.set((short) 1);
+                vh.set('A');
                 failUnreachable();
             } catch (WrongMethodTypeException e) {
             }
             try {
-                vh.set('A');
+                vh.set((short) 1);
                 failUnreachable();
             } catch (WrongMethodTypeException e) {
             }
             vh.set(2);
             try {
                 vh.setRelease(Long.MAX_VALUE);
+                failUnreachable();
             } catch (WrongMethodTypeException e) {
             }
             try {
                 vh.setRelease(Float.MAX_VALUE);
+                failUnreachable();
             } catch (WrongMethodTypeException e) {
             }
             try {
                 vh.setRelease(Double.MAX_VALUE);
+                failUnreachable();
             } catch (WrongMethodTypeException e) {
             }
             vh.set(null);
@@ -1337,6 +1446,7 @@
 
         SubtypeTest.main(args);
         SupertypeTest.main(args);
+        InterfaceTest.main(args);
 
         ImplicitBoxingIntegerTest.main(args);
     }
diff --git a/test/712-varhandle-invocations/src/Widget.java b/test/712-varhandle-invocations/src/Widget.java
index 0282ff8..332b4ea 100644
--- a/test/712-varhandle-invocations/src/Widget.java
+++ b/test/712-varhandle-invocations/src/Widget.java
@@ -15,7 +15,7 @@
  */
 
 // Widget class for reference type accessor tests.
-public class Widget {
+public class Widget implements WidgetInterface {
     protected int requisitionNumber;
 
     public Widget(int requisitionNumber) {
@@ -34,6 +34,8 @@
         return requisitionNumber == wo.requisitionNumber;
     }
 
+    public int getRequisitionNumber() { return requisitionNumber; }
+
     public static final Widget ONE = new Widget(1);
     public static final Widget TWO = new Widget(2);
 }
diff --git a/test/712-varhandle-invocations/src/WidgetInterface.java b/test/712-varhandle-invocations/src/WidgetInterface.java
new file mode 100644
index 0000000..441abbe
--- /dev/null
+++ b/test/712-varhandle-invocations/src/WidgetInterface.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+// Widget interface for reference type accessor tests.
+public interface WidgetInterface {
+    int getRequisitionNumber();
+}
diff --git a/test/712-varhandle-invocations/util-src/generate_java.py b/test/712-varhandle-invocations/util-src/generate_java.py
index f535b40..5d4bced 100644
--- a/test/712-varhandle-invocations/util-src/generate_java.py
+++ b/test/712-varhandle-invocations/util-src/generate_java.py
@@ -77,7 +77,7 @@
 BOOLEAN_TYPE = ValueType("boolean", "Boolean", [ "true", "false" ], ordinal = 0, width = 1, supports_numeric=False)
 BYTE_TYPE=ValueType("byte", "Byte", [ "(byte) -128", "(byte) -61", "(byte) 7", "(byte) 127", "(byte) 33" ], ordinal=1, width=1)
 SHORT_TYPE=ValueType("short", "Short", [ "(short) -32768", "(short) -384", "(short) 32767", "(short) 0xaa55" ], ordinal=2, width=2)
-CHAR_TYPE=ValueType("char", "Character", [ r"'A'", r"'#'", r"'$'", r"'Z'", r"'t'", r"'c'" ], ordinal=3, width=2)
+CHAR_TYPE=ValueType("char", "Character", [ r"'A'", r"'#'", r"'$'", r"'Z'", r"'t'", r"'c'",  r"Character.MAX_VALUE", r"Character.MIN_LOW_SURROGATE"], ordinal=3, width=2)
 INT_TYPE=ValueType("int", "Integer", [ "-0x01234567", "0x7f6e5d4c", "0x12345678", "0x10215220", "42" ], ordinal=4, width=4)
 LONG_TYPE=ValueType("long", "Long", [ "-0x0123456789abcdefl", "0x789abcdef0123456l", "0xfedcba9876543210l" ], ordinal=5, width=8)
 FLOAT_TYPE=ValueType("float", "Float", [ "-7.77e23f", "1.234e-17f", "3.40e36f", "-8.888e3f", "4.442e11f" ], ordinal=6, width=4, supports_bitwise=False)
@@ -722,6 +722,16 @@
         for accessor in VAR_HANDLE_ACCESSORS:
             emit_accessor_test(var_handle_kind, accessor, ref_type, output_path)
 
+def emit_interface_accessor_tests(output_path):
+    ref_type = JavaType("WidgetInterface", [ "Widget.ONE", "Widget.TWO", "null" ])
+    for var_handle_kind in ALL_VAR_HANDLE_KINDS:
+        if var_handle_kind.is_view():
+            # Views as reference type arrays are not supported. They
+            # fail instantiation. This is tested in 710-varhandle-creation.
+            continue
+        for accessor in VAR_HANDLE_ACCESSORS:
+            emit_accessor_test(var_handle_kind, accessor, ref_type, output_path)
+
 def emit_boxing_value_type_accessor_test(accessor, var_type, output_path):
     test_class = "Boxing" + capitalize_first(accessor.method_name) + capitalize_first(var_type.name)
     GENERATED_TEST_CLASSES.append(test_class)
@@ -873,6 +883,7 @@
         sys.exit(1)
     emit_value_type_accessor_tests(final_java_dir)
     emit_reference_accessor_tests(final_java_dir)
+    emit_interface_accessor_tests(final_java_dir)
     emit_boxing_value_type_accessor_tests(final_java_dir)
     emit_main(final_java_dir, argv[2:])
 
diff --git a/test/121-modifiers/expected.txt b/test/713-varhandle-invokers/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/713-varhandle-invokers/expected-stderr.txt
diff --git a/test/713-varhandle-invokers/expected.txt b/test/713-varhandle-invokers/expected-stdout.txt
similarity index 100%
rename from test/713-varhandle-invokers/expected.txt
rename to test/713-varhandle-invokers/expected-stdout.txt
diff --git a/test/714-invoke-custom-lambda-metafactory/expected-stderr.txt b/test/714-invoke-custom-lambda-metafactory/expected-stderr.txt
new file mode 100644
index 0000000..f1d8b5f
--- /dev/null
+++ b/test/714-invoke-custom-lambda-metafactory/expected-stderr.txt
@@ -0,0 +1,4 @@
+Exception in thread "main" java.lang.BootstrapMethodError: Exception from call site #0 bootstrap method
+	at Main.main(Main.java:25)
+Caused by: java.lang.ClassCastException: Bootstrap method returned null
+	... 1 more
diff --git a/test/714-invoke-custom-lambda-metafactory/expected-stdout.txt b/test/714-invoke-custom-lambda-metafactory/expected-stdout.txt
new file mode 100644
index 0000000..a9bf5a0
--- /dev/null
+++ b/test/714-invoke-custom-lambda-metafactory/expected-stdout.txt
@@ -0,0 +1 @@
+exit status: 1
diff --git a/test/714-invoke-custom-lambda-metafactory/expected.txt b/test/714-invoke-custom-lambda-metafactory/expected.txt
deleted file mode 100644
index c98a4c2..0000000
--- a/test/714-invoke-custom-lambda-metafactory/expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Exception in thread "main" java.lang.BootstrapMethodError: Exception from call site #0 bootstrap method
-	at Main.main(Main.java:25)
-Caused by: java.lang.ClassCastException: Bootstrap method returned null
-	... 1 more
-exit status: 1
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/715-clinit-implicit-parameter-annotations/expected-stderr.txt
similarity index 100%
copy from test/148-multithread-gc-annotations/expected.txt
copy to test/715-clinit-implicit-parameter-annotations/expected-stderr.txt
diff --git a/test/715-clinit-implicit-parameter-annotations/expected.txt b/test/715-clinit-implicit-parameter-annotations/expected-stdout.txt
similarity index 100%
rename from test/715-clinit-implicit-parameter-annotations/expected.txt
rename to test/715-clinit-implicit-parameter-annotations/expected-stdout.txt
diff --git a/test/1901-get-bytecodes/expected.txt b/test/716-jli-jit-samples/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/716-jli-jit-samples/expected-stderr.txt
diff --git a/test/716-jli-jit-samples/expected.txt b/test/716-jli-jit-samples/expected-stdout.txt
similarity index 100%
rename from test/716-jli-jit-samples/expected.txt
rename to test/716-jli-jit-samples/expected-stdout.txt
diff --git a/test/717-integer-value-of/Android.bp b/test/717-integer-value-of/Android.bp
new file mode 100644
index 0000000..03d3ac3
--- /dev/null
+++ b/test/717-integer-value-of/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `717-integer-value-of`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-717-integer-value-of",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-717-integer-value-of-expected-stdout",
+        ":art-run-test-717-integer-value-of-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-717-integer-value-of-expected-stdout",
+    out: ["art-run-test-717-integer-value-of-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-717-integer-value-of-expected-stderr",
+    out: ["art-run-test-717-integer-value-of-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/422-instanceof/expected.txt b/test/717-integer-value-of/expected-stderr.txt
similarity index 100%
copy from test/422-instanceof/expected.txt
copy to test/717-integer-value-of/expected-stderr.txt
diff --git a/test/717-integer-value-of/expected.txt b/test/717-integer-value-of/expected-stdout.txt
similarity index 100%
rename from test/717-integer-value-of/expected.txt
rename to test/717-integer-value-of/expected-stdout.txt
diff --git a/test/718-zipfile-finalizer/Android.bp b/test/718-zipfile-finalizer/Android.bp
new file mode 100644
index 0000000..ed1dc66
--- /dev/null
+++ b/test/718-zipfile-finalizer/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `718-zipfile-finalizer`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-718-zipfile-finalizer",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-718-zipfile-finalizer-expected-stdout",
+        ":art-run-test-718-zipfile-finalizer-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-718-zipfile-finalizer-expected-stdout",
+    out: ["art-run-test-718-zipfile-finalizer-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-718-zipfile-finalizer-expected-stderr",
+    out: ["art-run-test-718-zipfile-finalizer-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/718-zipfile-finalizer/expected.txt b/test/718-zipfile-finalizer/expected-stderr.txt
similarity index 100%
rename from test/718-zipfile-finalizer/expected.txt
rename to test/718-zipfile-finalizer/expected-stderr.txt
diff --git a/test/718-zipfile-finalizer/expected.txt b/test/718-zipfile-finalizer/expected-stdout.txt
similarity index 100%
copy from test/718-zipfile-finalizer/expected.txt
copy to test/718-zipfile-finalizer/expected-stdout.txt
diff --git a/test/719-dm-verify-redefinition/check b/test/719-dm-verify-redefinition/check
deleted file mode 100644
index b10a0e2..0000000
--- a/test/719-dm-verify-redefinition/check
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/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.
-
-# Search for the redefinition line and remove unnecessary tags.
-sed -e 's/^dex2oat[d]\?\(\|32\|64\)\ W.*\] \(Fast verification failed: Class L[^;]*; redefines a class in the classpath\).*/\2/g' "$2" > "$2.tmp1"
-# Remove all other dex2oat/dalvikvm log lines.
-grep -v dex2oat "$2.tmp1" | grep -v dalvikvm >> "$2.tmp2"
-
-./default-check "$1" "$2.tmp2"
diff --git a/test/719-dm-verify-redefinition/expected.txt b/test/719-dm-verify-redefinition/expected.txt
deleted file mode 100644
index c210c0d..0000000
--- a/test/719-dm-verify-redefinition/expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Fast verification failed: Class LRedefined; redefines a class in the classpath
-Hello, world!
diff --git a/test/719-dm-verify-redefinition/info.txt b/test/719-dm-verify-redefinition/info.txt
deleted file mode 100644
index 1229bdb..0000000
--- a/test/719-dm-verify-redefinition/info.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Verifies that the vdex file from a DexMetadata archive is discarded
-if the app redefines boot classes.
diff --git a/test/719-dm-verify-redefinition/run b/test/719-dm-verify-redefinition/run
deleted file mode 100644
index f4e9d71..0000000
--- a/test/719-dm-verify-redefinition/run
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/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.
-
-# This will compile just the primary jar and then compile again with vdex
-# and the secondary jar in classpath. The Redefined class in the secondary
-# jar should take precedence and fast-verify should fail.
-export ANDROID_LOG_TAGS='*:w'
-exec ${RUN} \
-  --external-log-tags \
-  --dm \
-  --vdex-arg \
-  --class-loader-context=PCL[$DEX_LOCATION/719-dm-verify-redefinition-ex.jar] \
-  "${@}"
diff --git a/test/719-dm-verify-redefinition/src-ex/Redefined.java b/test/719-dm-verify-redefinition/src-ex/Redefined.java
deleted file mode 100644
index cab7974..0000000
--- a/test/719-dm-verify-redefinition/src-ex/Redefined.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * 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 Redefined {
-}
diff --git a/test/719-dm-verify-redefinition/src/Main.java b/test/719-dm-verify-redefinition/src/Main.java
deleted file mode 100644
index 241792f..0000000
--- a/test/719-dm-verify-redefinition/src/Main.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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) {
-    System.out.println("Hello, world!");
-  }
-}
diff --git a/test/719-dm-verify-redefinition/src/Redefined.java b/test/719-dm-verify-redefinition/src/Redefined.java
deleted file mode 100644
index cab7974..0000000
--- a/test/719-dm-verify-redefinition/src/Redefined.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * 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 Redefined {
-}
diff --git a/test/720-thread-priority/Android.bp b/test/720-thread-priority/Android.bp
new file mode 100644
index 0000000..3a53717
--- /dev/null
+++ b/test/720-thread-priority/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `720-thread-priority`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-720-thread-priority",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-720-thread-priority-expected-stdout",
+        ":art-run-test-720-thread-priority-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-720-thread-priority-expected-stdout",
+    out: ["art-run-test-720-thread-priority-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-720-thread-priority-expected-stderr",
+    out: ["art-run-test-720-thread-priority-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/721-osr/expected.txt b/test/720-thread-priority/expected-stderr.txt
similarity index 100%
copy from test/721-osr/expected.txt
copy to test/720-thread-priority/expected-stderr.txt
diff --git a/test/720-thread-priority/expected.txt b/test/720-thread-priority/expected-stdout.txt
similarity index 100%
rename from test/720-thread-priority/expected.txt
rename to test/720-thread-priority/expected-stdout.txt
diff --git a/test/721-osr/Android.bp b/test/721-osr/Android.bp
new file mode 100644
index 0000000..22aa0c3
--- /dev/null
+++ b/test/721-osr/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `721-osr`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-721-osr",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-721-osr-expected-stdout",
+        ":art-run-test-721-osr-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-721-osr-expected-stdout",
+    out: ["art-run-test-721-osr-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-721-osr-expected-stderr",
+    out: ["art-run-test-721-osr-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/721-osr/expected.txt b/test/721-osr/expected-stderr.txt
similarity index 100%
rename from test/721-osr/expected.txt
rename to test/721-osr/expected-stderr.txt
diff --git a/test/721-osr/expected.txt b/test/721-osr/expected-stdout.txt
similarity index 100%
copy from test/721-osr/expected.txt
copy to test/721-osr/expected-stdout.txt
diff --git a/test/721-osr/src/Main.java b/test/721-osr/src/Main.java
index 2f0892c..0d41d29 100644
--- a/test/721-osr/src/Main.java
+++ b/test/721-osr/src/Main.java
@@ -33,9 +33,9 @@
         }
 
         // Loop enough to potentially trigger OSR.
-        List<Integer> dummyObjects = new ArrayList<Integer>(200_000);
+        List<Integer> placeholderObjects = new ArrayList<Integer>(200_000);
         for (int i = 0; i < 200_000; i++) {
-            dummyObjects.add(1024);
+            placeholderObjects.add(1024);
         }
 
         if (testFloat != 1000.0f) {
diff --git a/test/723-string-init-range/expected.txt b/test/723-string-init-range/expected-stderr.txt
similarity index 100%
rename from test/723-string-init-range/expected.txt
rename to test/723-string-init-range/expected-stderr.txt
diff --git a/test/723-string-init-range/expected.txt b/test/723-string-init-range/expected-stdout.txt
similarity index 100%
copy from test/723-string-init-range/expected.txt
copy to test/723-string-init-range/expected-stdout.txt
diff --git a/test/723-string-init-range/smali/new-instance.smali b/test/723-string-init-range/smali/new-instance.smali
index 45d6329..29fa696 100644
--- a/test/723-string-init-range/smali/new-instance.smali
+++ b/test/723-string-init-range/smali/new-instance.smali
@@ -23,3 +23,25 @@
     invoke-direct/range {v0 .. v1}, Ljava/lang/String;-><init>(Ljava/lang/String;)V
     return-object v0
 .end method
+
+.method public static initRange([BIII)Ljava/lang/String;
+    .registers 9
+    new-instance v0, Ljava/lang/String;
+    move-object v1, p0
+    move v2, p1
+    move v3, p2
+    move v4, p3
+    invoke-direct/range {v0 .. v4}, Ljava/lang/String;-><init>([BIII)V
+    return-object v0
+.end method
+
+.method public static initRangeWithAlias(Ljava/lang/String;)Ljava/lang/String;
+    .registers 19
+    # Put the object in a register > 0xF, as the arm64 nterp implementation wrongly masked
+    # that register with 0xF when handling String.<init> in an invoke-range.
+    new-instance v16, Ljava/lang/String;
+    move-object/from16 v1, v16
+    move-object/16 v17, p0
+    invoke-direct/range {v16 .. v17}, Ljava/lang/String;-><init>(Ljava/lang/String;)V
+    return-object v1
+.end method
diff --git a/test/723-string-init-range/src/Main.java b/test/723-string-init-range/src/Main.java
index 97ba76d..ca2fb7a 100644
--- a/test/723-string-init-range/src/Main.java
+++ b/test/723-string-init-range/src/Main.java
@@ -26,5 +26,18 @@
     if (!expected.equals(result)) {
       throw new Error("Expected '" + expected + "', got " + result);
     }
+
+    m = c.getMethod("initRange", byte[].class, int.class, int.class, int.class);
+    byte[] byteArray = expected.getBytes();
+    result = (String)m.invoke(null, byteArray, 0, 0, 5);
+    if (!expected.equals(result)) {
+      throw new Error("Expected '" + expected + "', got " + result);
+    }
+
+    m = c.getMethod("initRangeWithAlias", String.class);
+    result = (String)m.invoke(null, expected);
+    if (!expected.equals(result)) {
+      throw new Error("Expected '" + expected + "', got " + result);
+    }
   }
 }
diff --git a/test/724-invoke-super-npe/expected.txt b/test/724-invoke-super-npe/expected-stderr.txt
similarity index 100%
rename from test/724-invoke-super-npe/expected.txt
rename to test/724-invoke-super-npe/expected-stderr.txt
diff --git a/test/724-invoke-super-npe/expected.txt b/test/724-invoke-super-npe/expected-stdout.txt
similarity index 100%
copy from test/724-invoke-super-npe/expected.txt
copy to test/724-invoke-super-npe/expected-stdout.txt
diff --git a/test/725-imt-conflict-object/expected.txt b/test/725-imt-conflict-object/expected-stderr.txt
similarity index 100%
rename from test/725-imt-conflict-object/expected.txt
rename to test/725-imt-conflict-object/expected-stderr.txt
diff --git a/test/725-imt-conflict-object/expected.txt b/test/725-imt-conflict-object/expected-stdout.txt
similarity index 100%
copy from test/725-imt-conflict-object/expected.txt
copy to test/725-imt-conflict-object/expected-stdout.txt
diff --git a/test/726-array-store/Android.bp b/test/726-array-store/Android.bp
new file mode 100644
index 0000000..dc6cc24
--- /dev/null
+++ b/test/726-array-store/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `726-array-store`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-726-array-store",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-726-array-store-expected-stdout",
+        ":art-run-test-726-array-store-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-726-array-store-expected-stdout",
+    out: ["art-run-test-726-array-store-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-726-array-store-expected-stderr",
+    out: ["art-run-test-726-array-store-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/721-osr/expected.txt b/test/726-array-store/expected-stderr.txt
similarity index 100%
copy from test/721-osr/expected.txt
copy to test/726-array-store/expected-stderr.txt
diff --git a/test/721-osr/expected.txt b/test/726-array-store/expected-stdout.txt
similarity index 100%
copy from test/721-osr/expected.txt
copy to test/726-array-store/expected-stdout.txt
diff --git a/test/726-array-store/info.txt b/test/726-array-store/info.txt
new file mode 100644
index 0000000..623d923
--- /dev/null
+++ b/test/726-array-store/info.txt
@@ -0,0 +1 @@
+Regression test on storing an invalid type into an array.
diff --git a/test/726-array-store/src/Main.java b/test/726-array-store/src/Main.java
new file mode 100644
index 0000000..349e272
--- /dev/null
+++ b/test/726-array-store/src/Main.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 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 {
+      $noinline$doTest(args);
+      throw new Error("Expected ArrayStoreException");
+    } catch (ArrayStoreException e) {
+      // expected
+      check(e, mainLine, methodLine, "$noinline$doTest");
+    }
+  }
+
+  public static void $noinline$doTest(String[] args) {
+    Object[] o = new String[2];
+    o[0] = args;
+  }
+
+  public static int mainLine = 21;
+  public static int methodLine = 31;
+
+  static void check(ArrayStoreException ase, int mainLine, int methodLine, String methodName) {
+    StackTraceElement[] trace = ase.getStackTrace();
+    checkElement(trace[0], "Main", methodName, "Main.java", methodLine);
+    checkElement(trace[1], "Main", "main", "Main.java", mainLine);
+  }
+
+  static void checkElement(StackTraceElement element,
+                           String declaringClass, String methodName,
+                           String fileName, int lineNumber) {
+    assertEquals(declaringClass, element.getClassName());
+    assertEquals(methodName, element.getMethodName());
+    assertEquals(fileName, element.getFileName());
+    assertEquals(lineNumber, element.getLineNumber());
+  }
+
+  static void assertEquals(Object expected, Object actual) {
+    if (!expected.equals(actual)) {
+      String msg = "Expected \"" + expected + "\" but got \"" + actual + "\"";
+      throw new AssertionError(msg);
+    }
+  }
+
+  static void assertEquals(int expected, int actual) {
+    if (expected != actual) {
+      throw new AssertionError("Expected " + expected + " got " + actual);
+    }
+  }
+}
diff --git a/test/519-bound-load-class/expected.txt b/test/727-checker-unresolved-class/expected-stderr.txt
similarity index 100%
copy from test/519-bound-load-class/expected.txt
copy to test/727-checker-unresolved-class/expected-stderr.txt
diff --git a/test/727-checker-unresolved-class/expected-stdout.txt b/test/727-checker-unresolved-class/expected-stdout.txt
new file mode 100644
index 0000000..b33a798
--- /dev/null
+++ b/test/727-checker-unresolved-class/expected-stdout.txt
@@ -0,0 +1,12 @@
+ResolvedPackagePrivateClass.$noinline$publicStaticMethod()
+UnresolvedPublicClass passed
+UnresolvedPackagePrivateClass passed
+ResolvedPackagePrivateClass.$noinline$publicStaticMethod()
+ResolvedPackagePrivateClass.$noinline$publicStaticMethod()
+ResolvedPackagePrivateClass.$noinline$staticMethod()
+ResolvedPackagePrivateClass.$noinline$staticMethod()
+PublicSubclassOfUnresolvedClass passed
+ResolvedPackagePrivateClass.$noinline$publicStaticMethod()
+PublicSubclassOfUnresolvedClass2 passed
+PackagePrivateSubclassOfUnresolvedClass passed
+PackagePrivateSubclassOfUnresolvedClass2 passed
diff --git a/test/727-checker-unresolved-class/info.txt b/test/727-checker-unresolved-class/info.txt
new file mode 100644
index 0000000..cc60c0f
--- /dev/null
+++ b/test/727-checker-unresolved-class/info.txt
@@ -0,0 +1,2 @@
+Tests for compiling with unresolved classes, including unresolved
+class of the method being compiled.
diff --git a/test/727-checker-unresolved-class/jasmin/GetPackagePrivateSubclassOfUnresolvedClass2FromSamePackage.j b/test/727-checker-unresolved-class/jasmin/GetPackagePrivateSubclassOfUnresolvedClass2FromSamePackage.j
new file mode 100644
index 0000000..0add87b
--- /dev/null
+++ b/test/727-checker-unresolved-class/jasmin/GetPackagePrivateSubclassOfUnresolvedClass2FromSamePackage.j
@@ -0,0 +1,27 @@
+; Copyright (C) 2020 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.
+
+.bytecode 49.0
+
+.class                   public resolved/GetPackagePrivateSubclassOfUnresolvedClass2FromSamePackage
+.super                   java/lang/Object
+
+; TODO: Make $inline$ when we relax the verifier. b/28313047
+.method                  public static get()Ljava/lang/Class;
+  .limit stack           1
+  .limit locals          0
+  ; Fail to resolve class in same literal package but defined in child ClassLoader.
+  ldc resolved/PackagePrivateSubclassOfUnresolvedClass2
+  areturn
+.end method
diff --git a/test/727-checker-unresolved-class/jasmin/GetPublicSubclassOfUnresolvedClass2FromSamePackage.j b/test/727-checker-unresolved-class/jasmin/GetPublicSubclassOfUnresolvedClass2FromSamePackage.j
new file mode 100644
index 0000000..0868365
--- /dev/null
+++ b/test/727-checker-unresolved-class/jasmin/GetPublicSubclassOfUnresolvedClass2FromSamePackage.j
@@ -0,0 +1,27 @@
+; Copyright (C) 2020 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.
+
+.bytecode 49.0
+
+.class                   public resolved/GetPublicSubclassOfUnresolvedClass2FromSamePackage
+.super                   java/lang/Object
+
+; TODO: Make $inline$ when we relax the verifier. b/28313047
+.method                  public static get()Ljava/lang/Class;
+  .limit stack           1
+  .limit locals          0
+  ; Fail to resolve class in same literal package but defined in child ClassLoader.
+  ldc resolved/PublicSubclassOfUnresolvedClass2
+  areturn
+.end method
diff --git a/test/727-checker-unresolved-class/res/updateable.txt b/test/727-checker-unresolved-class/res/updateable.txt
new file mode 100644
index 0000000..7938381
--- /dev/null
+++ b/test/727-checker-unresolved-class/res/updateable.txt
@@ -0,0 +1 @@
+unresolved
diff --git a/test/727-checker-unresolved-class/run b/test/727-checker-unresolved-class/run
new file mode 100644
index 0000000..d087a8f
--- /dev/null
+++ b/test/727-checker-unresolved-class/run
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Copyright (C) 2020 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.
+
+if [[ "$TEST_RUNTIME" == "jvm" ]]; then
+  exec ${RUN} $@
+else
+  # Compile the secondary dex file with the right class loader hierarchy with
+  #     --secondary-class-loader-context.
+  # Append graphs for checker tests (we run dex2oat twice) with
+  #     --dump-cfg-append.
+  # Make some classes unresolved for AOT compilation with
+  #     --updatable-bcp-packages-file.
+  exec ${RUN} $@ \
+      --secondary-class-loader-context "PCL[];PCL[$DEX_LOCATION/$TEST_NAME.jar]" \
+      -Xcompiler-option --dump-cfg-append \
+      -Xcompiler-option --updatable-bcp-packages-file="$DEX_LOCATION/res/updateable.txt"
+fi
diff --git a/test/727-checker-unresolved-class/src-ex/Test.java b/test/727-checker-unresolved-class/src-ex/Test.java
new file mode 100644
index 0000000..54d7b8d
--- /dev/null
+++ b/test/727-checker-unresolved-class/src-ex/Test.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 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 resolved.PackagePrivateSubclassOfUnresolvedClassProxy;
+import resolved.PackagePrivateSubclassOfUnresolvedClass2Proxy;
+import resolved.PublicSubclassOfUnresolvedClass;
+import resolved.PublicSubclassOfUnresolvedClass2;
+import unresolved.UnresolvedPackagePrivateClassProxy;
+import unresolved.UnresolvedPublicClass;
+
+public class Test {
+  public static void $noinline$main() {
+    UnresolvedPublicClass.$noinline$main();
+    UnresolvedPackagePrivateClassProxy.$noinline$main();
+    PublicSubclassOfUnresolvedClass.$noinline$main();
+    PublicSubclassOfUnresolvedClass2.$noinline$main();
+    PackagePrivateSubclassOfUnresolvedClassProxy.$noinline$main();
+    PackagePrivateSubclassOfUnresolvedClass2Proxy.$noinline$main();
+  }
+}
diff --git a/test/727-checker-unresolved-class/src-ex/getters/GetPackagePrivateSubclassOfUnresolvedClass2.java b/test/727-checker-unresolved-class/src-ex/getters/GetPackagePrivateSubclassOfUnresolvedClass2.java
new file mode 100644
index 0000000..41ba071
--- /dev/null
+++ b/test/727-checker-unresolved-class/src-ex/getters/GetPackagePrivateSubclassOfUnresolvedClass2.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package getters;
+
+import resolved.PackagePrivateSubclassOfUnresolvedClass2;
+
+public class GetPackagePrivateSubclassOfUnresolvedClass2 {
+  // TODO: Make $inline$ when we relax the verifier. b/28313047
+  public static Class<?> get() {
+    return PackagePrivateSubclassOfUnresolvedClass2.class;
+  }
+}
diff --git a/test/727-checker-unresolved-class/src-ex/getters/GetPublicSubclassOfUnresolvedClass2.java b/test/727-checker-unresolved-class/src-ex/getters/GetPublicSubclassOfUnresolvedClass2.java
new file mode 100644
index 0000000..9020f97
--- /dev/null
+++ b/test/727-checker-unresolved-class/src-ex/getters/GetPublicSubclassOfUnresolvedClass2.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package getters;
+
+import resolved.PublicSubclassOfUnresolvedClass2;
+
+public class GetPublicSubclassOfUnresolvedClass2 {
+  // TODO: Make $inline$ when we relax the verifier. b/28313047
+  public static Class<?> get() {
+    return PublicSubclassOfUnresolvedClass2.class;
+  }
+}
diff --git a/test/727-checker-unresolved-class/src-ex/resolved/PackagePrivateSubclassOfUnresolvedClass2.java b/test/727-checker-unresolved-class/src-ex/resolved/PackagePrivateSubclassOfUnresolvedClass2.java
new file mode 100644
index 0000000..3f0bc05
--- /dev/null
+++ b/test/727-checker-unresolved-class/src-ex/resolved/PackagePrivateSubclassOfUnresolvedClass2.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+import getters.GetPackagePrivateSubclassOfUnresolvedClass2;
+import unresolved.UnresolvedPublicClass;
+
+// This class is used for compiling code that accesses it but it is
+// replaced by a package-private class from src-ex2/ with reduced access
+// to run tests, including access check tests.
+public class PackagePrivateSubclassOfUnresolvedClass2 extends UnresolvedPublicClass {
+  public static void $noinline$main() {
+    throw new Error("Unreachable");
+  }
+}
diff --git a/test/727-checker-unresolved-class/src-ex/resolved/PackagePrivateSubclassOfUnresolvedClass2Proxy.java b/test/727-checker-unresolved-class/src-ex/resolved/PackagePrivateSubclassOfUnresolvedClass2Proxy.java
new file mode 100644
index 0000000..a6dc803
--- /dev/null
+++ b/test/727-checker-unresolved-class/src-ex/resolved/PackagePrivateSubclassOfUnresolvedClass2Proxy.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+public class PackagePrivateSubclassOfUnresolvedClass2Proxy
+    extends PackagePrivateSubclassOfUnresolvedClass2 {
+}
diff --git a/test/727-checker-unresolved-class/src-ex/resolved/PublicSubclassOfUnresolvedClass2.java b/test/727-checker-unresolved-class/src-ex/resolved/PublicSubclassOfUnresolvedClass2.java
new file mode 100644
index 0000000..887196a
--- /dev/null
+++ b/test/727-checker-unresolved-class/src-ex/resolved/PublicSubclassOfUnresolvedClass2.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+import getters.GetPublicSubclassOfUnresolvedClass2;
+import unresolved.UnresolvedPublicClass;
+
+// This class is defined by the child class loader, so access to
+// package-private classes and members defined in the parent class
+// loader is illegal even though the package name is the same.
+public class PublicSubclassOfUnresolvedClass2 extends UnresolvedPublicClass {
+  public static void $noinline$main() {
+    $noinline$testReferrersClass();
+    $noinline$testInlinedReferrersClass();
+    $noinline$testInlinedReferrersClassFromSamePackage();
+
+    $noinline$testResolvedPublicClass();
+    $noinline$testResolvedPackagePrivateClass();
+
+    $noinline$testPublicFieldInResolvedPackagePrivateClass();
+    $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPrivateFieldInResolvedPackagePrivateClass();
+    $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass();
+    $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass();
+
+    $noinline$testPublicMethodInResolvedPackagePrivateClass();
+    $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPrivateMethodInResolvedPackagePrivateClass();
+    $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass();
+    $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass();
+
+    System.out.println("PublicSubclassOfUnresolvedClass2 passed");
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testReferrersClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.PublicSubclassOfUnresolvedClass2 needs_access_check:false
+  static void $noinline$testReferrersClass() {
+    Class<?> c = PublicSubclassOfUnresolvedClass2.class;
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testInlinedReferrersClass() inliner (after)
+  // CHECK: LoadClass class_name:resolved.PublicSubclassOfUnresolvedClass2 needs_access_check:false
+  static void $noinline$testInlinedReferrersClass() {
+    // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+    Class<?> c = GetPublicSubclassOfUnresolvedClass2.get();
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testInlinedReferrersClassFromSamePackage() inliner (after)
+  // CHECK: LoadClass class_name:resolved.PublicSubclassOfUnresolvedClass2 needs_access_check:true
+  static void $noinline$testInlinedReferrersClassFromSamePackage() {
+    // Trying to resolve this class by name in parent class loader throws NoClassDefFoundError.
+    try{
+      // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+      Class<?> c = GetPublicSubclassOfUnresolvedClass2FromSamePackage.get();
+      throw new Error("Unreachable");
+    } catch (NoClassDefFoundError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testResolvedPublicClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.ResolvedPublicSubclassOfPackagePrivateClass needs_access_check:false
+  static void $noinline$testResolvedPublicClass() {
+    Class<?> c = ResolvedPublicSubclassOfPackagePrivateClass.class;
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testResolvedPackagePrivateClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.ResolvedPackagePrivateClass needs_access_check:true
+  static void $noinline$testResolvedPackagePrivateClass() {
+    try {
+      Class<?> c = ResolvedPackagePrivateClass.class;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPublicFieldInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.publicIntField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: StaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: UnresolvedStaticFieldSet
+  static void $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() {
+    ResolvedPublicSubclassOfPackagePrivateClass.publicIntField = 42;
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPrivateFieldInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.privateIntField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() {
+    try {
+      ResolvedPublicSubclassOfPackagePrivateClass.privateIntField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.intField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() {
+    try {
+      ResolvedPublicSubclassOfPackagePrivateClass.intField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod
+  static void $noinline$testPublicMethodInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.$noinline$publicStaticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod
+  static void $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() {
+    ResolvedPublicSubclassOfPackagePrivateClass.$noinline$publicStaticMethod();
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod
+  static void $noinline$testPrivateMethodInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.$noinline$privateStaticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod
+  static void $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() {
+    try {
+      ResolvedPublicSubclassOfPackagePrivateClass.$noinline$privateStaticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod
+  static void $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.$noinline$staticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass2.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod
+  static void $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() {
+    try {
+      ResolvedPublicSubclassOfPackagePrivateClass.$noinline$staticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+}
diff --git a/test/727-checker-unresolved-class/src-ex2/resolved/PackagePrivateSubclassOfUnresolvedClass2.java b/test/727-checker-unresolved-class/src-ex2/resolved/PackagePrivateSubclassOfUnresolvedClass2.java
new file mode 100644
index 0000000..a0c61ce
--- /dev/null
+++ b/test/727-checker-unresolved-class/src-ex2/resolved/PackagePrivateSubclassOfUnresolvedClass2.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+import getters.GetPackagePrivateSubclassOfUnresolvedClass2;
+import unresolved.UnresolvedPublicClass;
+
+// This class is defined by the child class loader, so access to
+// package-private classes and members defined in the parent class
+// loader is illegal even though the package name is the same.
+public class PackagePrivateSubclassOfUnresolvedClass2 extends UnresolvedPublicClass {
+  public static void $noinline$main() {
+    $noinline$testReferrersClass();
+    $noinline$testInlinedReferrersClass();
+    $noinline$testInlinedReferrersClassFromSamePackage();
+
+    System.out.println("PackagePrivateSubclassOfUnresolvedClass2 passed");
+  }
+
+  /// CHECK-START: void resolved.PackagePrivateSubclassOfUnresolvedClass2.$noinline$testReferrersClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.PackagePrivateSubclassOfUnresolvedClass2 needs_access_check:false
+  static void $noinline$testReferrersClass() {
+    Class<?> c = PackagePrivateSubclassOfUnresolvedClass2.class;
+  }
+
+  /// CHECK-START: void resolved.PackagePrivateSubclassOfUnresolvedClass2.$noinline$testInlinedReferrersClass() inliner (after)
+  // CHECK: LoadClass class_name:resolved.PackagePrivateSubclassOfUnresolvedClass2 needs_access_check:true
+  static void $noinline$testInlinedReferrersClass() {
+    // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+    Class<?> c = GetPackagePrivateSubclassOfUnresolvedClass2.get();
+  }
+
+  /// CHECK-START: void resolved.PackagePrivateSubclassOfUnresolvedClass2.$noinline$testInlinedReferrersClassFromSamePackage() inliner (after)
+  // CHECK: LoadClass class_name:resolved.PackagePrivateSubclassOfUnresolvedClass2 needs_access_check:true
+  static void $noinline$testInlinedReferrersClassFromSamePackage() {
+    // Trying to resolve this class by name in parent class loader throws NoClassDefFoundError.
+    try {
+      // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+      Class<?> c = GetPackagePrivateSubclassOfUnresolvedClass2FromSamePackage.get();
+      throw new Error("Unreachable");
+    } catch (NoClassDefFoundError expected) {}
+  }
+}
diff --git a/test/727-checker-unresolved-class/src-multidex/getters/GetUnresolvedPublicClassFromDifferentDexFile.java b/test/727-checker-unresolved-class/src-multidex/getters/GetUnresolvedPublicClassFromDifferentDexFile.java
new file mode 100644
index 0000000..fd63ced
--- /dev/null
+++ b/test/727-checker-unresolved-class/src-multidex/getters/GetUnresolvedPublicClassFromDifferentDexFile.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package getters;
+
+import resolved.PublicSubclassOfUnresolvedClass;
+import unresolved.UnresolvedPublicClass;
+import unresolved.UnresolvedPublicClazz;
+
+public class GetUnresolvedPublicClassFromDifferentDexFile {
+  // TODO: Make $inline$ when we relax the verifier. b/28313047
+  public static Class<?> get() {
+    return UnresolvedPublicClass.class;
+  }
+
+  // TODO: Make $inline$ when we relax the verifier. b/28313047
+  public static Class<?> getOtherClass() {
+    return PublicSubclassOfUnresolvedClass.class;
+  }
+
+  // TODO: Make $inline$ when we relax the verifier. b/28313047
+  public static Class<?> getOtherClassWithSameDescriptorLength() {
+    return UnresolvedPublicClazz.class;
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/Main.java b/test/727-checker-unresolved-class/src/Main.java
new file mode 100644
index 0000000..5b6a46a
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/Main.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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.Constructor;
+import java.lang.reflect.Method;
+
+public class Main {
+  public static String TEST_NAME = "727-checker-unresolved-class";
+
+  public static ClassLoader getClassLoaderFor(String location) throws Exception {
+    try {
+      Class<?> class_loader_class = Class.forName("dalvik.system.PathClassLoader");
+      Constructor<?> ctor =
+          class_loader_class.getConstructor(String.class, ClassLoader.class);
+      /* on Dalvik, this is a DexFile; otherwise, it's null */
+      return (ClassLoader) ctor.newInstance(location + "/" + TEST_NAME + "-ex.jar",
+                                            Main.class.getClassLoader());
+    } catch (ClassNotFoundException e) {
+      // Running on RI. Use URLClassLoader.
+      return new java.net.URLClassLoader(
+          new java.net.URL[] { new java.net.URL("file://" + location + "/classes-ex/") });
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    ClassLoader new_loader = getClassLoaderFor(System.getenv("DEX_LOCATION"));
+    Class<?> testClass = Class.forName("Test", true, new_loader);
+    Method testMain = testClass.getMethod("$noinline$main");
+    testMain.invoke(null);
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/getters/GetPackagePrivateSubclassOfUnresolvedClass.java b/test/727-checker-unresolved-class/src/getters/GetPackagePrivateSubclassOfUnresolvedClass.java
new file mode 100644
index 0000000..cf79d80
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/getters/GetPackagePrivateSubclassOfUnresolvedClass.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package getters;
+
+import resolved.PackagePrivateSubclassOfUnresolvedClass;
+
+public class GetPackagePrivateSubclassOfUnresolvedClass {
+  // TODO: Make $inline$ when we relax the verifier. b/28313047
+  public static Class<?> get() {
+    return PackagePrivateSubclassOfUnresolvedClass.class;
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/getters/GetPublicSubclassOfUnresolvedClass.java b/test/727-checker-unresolved-class/src/getters/GetPublicSubclassOfUnresolvedClass.java
new file mode 100644
index 0000000..099fd53
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/getters/GetPublicSubclassOfUnresolvedClass.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package getters;
+
+import resolved.PublicSubclassOfUnresolvedClass;
+
+public class GetPublicSubclassOfUnresolvedClass {
+  // TODO: Make $inline$ when we relax the verifier. b/28313047
+  public static Class<?> get() {
+    return PublicSubclassOfUnresolvedClass.class;
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/getters/GetUnresolvedPackagePrivateClass.java b/test/727-checker-unresolved-class/src/getters/GetUnresolvedPackagePrivateClass.java
new file mode 100644
index 0000000..356d0e0
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/getters/GetUnresolvedPackagePrivateClass.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package getters;
+
+import unresolved.UnresolvedPackagePrivateClass;
+
+public class GetUnresolvedPackagePrivateClass {
+  // TODO: When we relax verifier to ignore access check failures,
+  // change this method to `$inline$`.
+  public static Class<?> get() {
+    return UnresolvedPackagePrivateClass.class;
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/getters/GetUnresolvedPublicClass.java b/test/727-checker-unresolved-class/src/getters/GetUnresolvedPublicClass.java
new file mode 100644
index 0000000..2c0bb0b
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/getters/GetUnresolvedPublicClass.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package getters;
+
+import unresolved.UnresolvedPublicClass;
+
+public class GetUnresolvedPublicClass {
+  // TODO: Make $inline$ when we relax the verifier. b/28313047
+  public static Class<?> get() {
+    return UnresolvedPublicClass.class;
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/resolved/GetPackagePrivateSubclassOfUnresolvedClassFromSamePackage.java b/test/727-checker-unresolved-class/src/resolved/GetPackagePrivateSubclassOfUnresolvedClassFromSamePackage.java
new file mode 100644
index 0000000..2c221c5
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/resolved/GetPackagePrivateSubclassOfUnresolvedClassFromSamePackage.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+public class GetPackagePrivateSubclassOfUnresolvedClassFromSamePackage {
+  // TODO: Make $inline$ when we relax the verifier. b/28313047
+  public static Class<?> get() {
+    return PackagePrivateSubclassOfUnresolvedClass.class;
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/resolved/GetPublicSubclassOfUnresolvedClassFromSamePackage.java b/test/727-checker-unresolved-class/src/resolved/GetPublicSubclassOfUnresolvedClassFromSamePackage.java
new file mode 100644
index 0000000..6874906
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/resolved/GetPublicSubclassOfUnresolvedClassFromSamePackage.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+public class GetPublicSubclassOfUnresolvedClassFromSamePackage {
+  // TODO: Make $inline$ when we relax the verifier. b/28313047
+  public static Class<?> get() {
+    return PublicSubclassOfUnresolvedClass.class;
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/resolved/PackagePrivateSubclassOfUnresolvedClass.java b/test/727-checker-unresolved-class/src/resolved/PackagePrivateSubclassOfUnresolvedClass.java
new file mode 100644
index 0000000..7ba0c2c
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/resolved/PackagePrivateSubclassOfUnresolvedClass.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+// This class is used for compiling code that accesses it but it is
+// replaced by a package-private class from src2/ with reduced access
+// to run tests, including access check tests.
+public class PackagePrivateSubclassOfUnresolvedClass {
+  public static void $noinline$main() {
+    throw new Error("Unreachable");
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/resolved/PackagePrivateSubclassOfUnresolvedClassProxy.java b/test/727-checker-unresolved-class/src/resolved/PackagePrivateSubclassOfUnresolvedClassProxy.java
new file mode 100644
index 0000000..8d07de6
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/resolved/PackagePrivateSubclassOfUnresolvedClassProxy.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+public class PackagePrivateSubclassOfUnresolvedClassProxy
+    extends PackagePrivateSubclassOfUnresolvedClass {
+}
diff --git a/test/727-checker-unresolved-class/src/resolved/PublicSubclassOfUnresolvedClass.java b/test/727-checker-unresolved-class/src/resolved/PublicSubclassOfUnresolvedClass.java
new file mode 100644
index 0000000..2b8cbf8
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/resolved/PublicSubclassOfUnresolvedClass.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+import getters.GetPublicSubclassOfUnresolvedClass;
+import unresolved.UnresolvedPublicClass;
+
+public class PublicSubclassOfUnresolvedClass extends UnresolvedPublicClass {
+  public static void $noinline$main() {
+    $noinline$testReferrersClass();
+    $noinline$testInlinedReferrersClass();
+    $noinline$testInlinedReferrersClassFromSamePackage();
+
+    $noinline$testResolvedPublicClass();
+    $noinline$testResolvedPackagePrivateClass();
+
+    $noinline$testPublicFieldInResolvedPackagePrivateClass();
+    $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPrivateFieldInResolvedPackagePrivateClass();
+    $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass();
+    $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass();
+
+    $noinline$testPublicMethodInResolvedPackagePrivateClass();
+    $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPrivateMethodInResolvedPackagePrivateClass();
+    $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass();
+    $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass();
+
+    System.out.println("PublicSubclassOfUnresolvedClass passed");
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testReferrersClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.PublicSubclassOfUnresolvedClass needs_access_check:false
+  static void $noinline$testReferrersClass() {
+    Class<?> c = PublicSubclassOfUnresolvedClass.class;
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testInlinedReferrersClass() inliner (after)
+  // CHECK: LoadClass class_name:resolved.PublicSubclassOfUnresolvedClass needs_access_check:false
+  static void $noinline$testInlinedReferrersClass() {
+    // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+    Class<?> c = GetPublicSubclassOfUnresolvedClass.get();
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testInlinedReferrersClassFromSamePackage() inliner (after)
+  // CHECK: LoadClass class_name:resolved.PublicSubclassOfUnresolvedClass needs_access_check:false
+  static void $noinline$testInlinedReferrersClassFromSamePackage() {
+    // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+    Class<?> c = GetPublicSubclassOfUnresolvedClassFromSamePackage.get();
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testResolvedPublicClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.ResolvedPublicSubclassOfPackagePrivateClass needs_access_check:false
+  static void $noinline$testResolvedPublicClass() {
+    Class<?> c = ResolvedPublicSubclassOfPackagePrivateClass.class;
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testResolvedPackagePrivateClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.ResolvedPackagePrivateClass needs_access_check:false
+  static void $noinline$testResolvedPackagePrivateClass() {
+    Class<?> c = ResolvedPackagePrivateClass.class;
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: StaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: UnresolvedStaticFieldSet
+  static void $noinline$testPublicFieldInResolvedPackagePrivateClass() {
+    ResolvedPackagePrivateClass.publicIntField = 42;
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: StaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: UnresolvedStaticFieldSet
+  static void $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() {
+    ResolvedPublicSubclassOfPackagePrivateClass.publicIntField = 42;
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPrivateFieldInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.privateIntField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() {
+    try {
+      ResolvedPublicSubclassOfPackagePrivateClass.privateIntField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: StaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: UnresolvedStaticFieldSet
+  static void $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() {
+    ResolvedPackagePrivateClass.intField = 42;
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: StaticFieldSet
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: UnresolvedStaticFieldSet
+  static void $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() {
+    ResolvedPublicSubclassOfPackagePrivateClass.intField = 42;
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod
+  static void $noinline$testPublicMethodInResolvedPackagePrivateClass() {
+    ResolvedPackagePrivateClass.$noinline$publicStaticMethod();
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod
+  static void $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() {
+    ResolvedPublicSubclassOfPackagePrivateClass.$noinline$publicStaticMethod();
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod
+  static void $noinline$testPrivateMethodInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.$noinline$privateStaticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod
+  static void $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() {
+    try {
+      ResolvedPublicSubclassOfPackagePrivateClass.$noinline$privateStaticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod
+  static void $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() {
+    ResolvedPackagePrivateClass.$noinline$staticMethod();
+  }
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod
+
+  /// CHECK-START: void resolved.PublicSubclassOfUnresolvedClass.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod
+  static void $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() {
+    ResolvedPublicSubclassOfPackagePrivateClass.$noinline$staticMethod();
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/resolved/ResolvedPackagePrivateClass.java b/test/727-checker-unresolved-class/src/resolved/ResolvedPackagePrivateClass.java
new file mode 100644
index 0000000..0c7d055
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/resolved/ResolvedPackagePrivateClass.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+// This class is used for compiling code that accesses its fields but it is
+// replaced by a package-private class from src2/ with reduced access to
+// some members to test different access checks.
+public class ResolvedPackagePrivateClass {
+  public static int publicIntField;
+  public static int privateIntField;
+  public static int intField;
+
+  public static void $noinline$publicStaticMethod() {
+    System.out.println("ResolvedPackagePrivateClass.$noinline$publicStaticMethod()");
+  }
+
+  public static void $noinline$privateStaticMethod() {
+    System.out.println("ResolvedPackagePrivateClass.$noinline$privateStaticMethod()");
+  }
+
+  public static void $noinline$staticMethod() {
+    System.out.println("ResolvedPackagePrivateClass.$noinline$staticMethod()");
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/resolved/ResolvedPublicSubclassOfPackagePrivateClass.java b/test/727-checker-unresolved-class/src/resolved/ResolvedPublicSubclassOfPackagePrivateClass.java
new file mode 100644
index 0000000..1ca6060
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/resolved/ResolvedPublicSubclassOfPackagePrivateClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+public class ResolvedPublicSubclassOfPackagePrivateClass extends ResolvedPackagePrivateClass {
+}
diff --git a/test/727-checker-unresolved-class/src/unresolved/UnresolvedPackagePrivateClass.java b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPackagePrivateClass.java
new file mode 100644
index 0000000..b5ed7ff
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPackagePrivateClass.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package unresolved;
+
+// This class is used for compiling code that accesses it but it is
+// replaced by a package-private class from src2/ with reduced access
+// to run tests, including access check tests.
+public class UnresolvedPackagePrivateClass {
+  public static void $noinline$main() {
+    throw new Error("Unreachable");
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/unresolved/UnresolvedPackagePrivateClassProxy.java b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPackagePrivateClassProxy.java
new file mode 100644
index 0000000..b880a87
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPackagePrivateClassProxy.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package unresolved;
+
+public class UnresolvedPackagePrivateClassProxy extends UnresolvedPackagePrivateClass {
+}
diff --git a/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java
new file mode 100644
index 0000000..4864e64
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package unresolved;
+
+import getters.GetUnresolvedPublicClass;
+import getters.GetUnresolvedPublicClassFromDifferentDexFile;
+import resolved.PackagePrivateSubclassOfUnresolvedClass;
+import resolved.PublicSubclassOfUnresolvedClass;
+import resolved.ResolvedPackagePrivateClass;
+import resolved.ResolvedPublicSubclassOfPackagePrivateClass;
+
+public class UnresolvedPublicClass {
+  public static void $noinline$main() {
+    $noinline$testReferrersClass();
+    $noinline$testInlinedReferrersClass();
+    $noinline$testInlinedReferrersClassFromDifferentDexFile();
+    $noinline$testInlinedClassDescriptorCompare1();
+    $noinline$testInlinedClassDescriptorCompare2();
+
+    $noinline$testResolvedPublicClass();
+    $noinline$testResolvedPackagePrivateClass();
+    $noinline$testUnresolvedPublicClass();
+    $noinline$testUnresolvedPackagePrivateClass();
+    $noinline$testUnresolvedPublicClassInSamePackage();
+    $noinline$testUnresolvedPackagePrivateClassInSamePackage();
+
+    $noinline$testPublicFieldInResolvedPackagePrivateClass();
+    $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPrivateFieldInResolvedPackagePrivateClass();
+    $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass();
+    $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass();
+
+    $noinline$testPublicMethodInResolvedPackagePrivateClass();
+    $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPrivateMethodInResolvedPackagePrivateClass();
+    $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass();
+    $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass();
+    $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass();
+
+    System.out.println("UnresolvedPublicClass passed");
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testReferrersClass() builder (after)
+  /// CHECK: LoadClass class_name:unresolved.UnresolvedPublicClass needs_access_check:false
+  static void $noinline$testReferrersClass() {
+    Class<?> c = UnresolvedPublicClass.class;
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testInlinedReferrersClass() inliner (after)
+  // CHECK: LoadClass class_name:unresolved.UnresolvedPublicClass needs_access_check:false
+  static void $noinline$testInlinedReferrersClass() {
+    // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+    Class<?> c = GetUnresolvedPublicClass.get();
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testInlinedReferrersClassFromDifferentDexFile() inliner (after)
+  // CHECK: LoadClass class_name:unresolved.UnresolvedPublicClass needs_access_check:false
+  static void $noinline$testInlinedReferrersClassFromDifferentDexFile() {
+    // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+    Class<?> c = GetUnresolvedPublicClassFromDifferentDexFile.get();
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testInlinedClassDescriptorCompare1() inliner (after)
+  // CHECK: LoadClass class_name:resolved.PublicSubclassOfUnresolvedClass needs_access_check:true
+  static void $noinline$testInlinedClassDescriptorCompare1() {
+    // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+    Class<?> c =
+        GetUnresolvedPublicClassFromDifferentDexFile.getOtherClass();
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testInlinedClassDescriptorCompare2() inliner (after)
+  // CHECK: LoadClass class_name:unresolved.UnresolvedPublicClazz needs_access_check:true
+  static void $noinline$testInlinedClassDescriptorCompare2() {
+    // This is useful for code coverage of descriptor comparison
+    // implemented by first comparing the utf16 lengths and then
+    // checking strcmp(). Using these classes we cover the path
+    // where utf16 lengths match but string contents differ.
+    // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+    Class<?> c =
+        GetUnresolvedPublicClassFromDifferentDexFile.getOtherClassWithSameDescriptorLength();
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testResolvedPublicClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.ResolvedPublicSubclassOfPackagePrivateClass needs_access_check:false
+  static void $noinline$testResolvedPublicClass() {
+    Class<?> c = ResolvedPublicSubclassOfPackagePrivateClass.class;
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testResolvedPackagePrivateClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.ResolvedPackagePrivateClass needs_access_check:true
+  static void $noinline$testResolvedPackagePrivateClass() {
+    try {
+      Class<?> c = ResolvedPackagePrivateClass.class;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.PublicSubclassOfUnresolvedClass needs_access_check:true
+
+  /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClass() builder (after)
+  /// CHECK: LoadClass load_kind:BssEntryPublic class_name:resolved.PublicSubclassOfUnresolvedClass
+  static void $noinline$testUnresolvedPublicClass() {
+    Class<?> c = PublicSubclassOfUnresolvedClass.class;
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.PackagePrivateSubclassOfUnresolvedClass needs_access_check:true
+
+  /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClass() builder (after)
+  /// CHECK: LoadClass load_kind:BssEntryPublic class_name:resolved.PackagePrivateSubclassOfUnresolvedClass
+  static void $noinline$testUnresolvedPackagePrivateClass() {
+    try {
+      Class<?> c = PackagePrivateSubclassOfUnresolvedClass.class;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClassInSamePackage() builder (after)
+  /// CHECK: LoadClass class_name:unresolved.UnresolvedPublicClazz needs_access_check:true
+
+  /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClassInSamePackage() builder (after)
+  /// CHECK: LoadClass load_kind:BssEntryPackage class_name:unresolved.UnresolvedPublicClazz
+  static void $noinline$testUnresolvedPublicClassInSamePackage() {
+    Class<?> c = UnresolvedPublicClazz.class;
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClassInSamePackage() builder (after)
+  /// CHECK: LoadClass class_name:unresolved.UnresolvedPackagePrivateClass needs_access_check:true
+
+  /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClassInSamePackage() builder (after)
+  /// CHECK: LoadClass load_kind:BssEntryPackage class_name:unresolved.UnresolvedPackagePrivateClass
+  static void $noinline$testUnresolvedPackagePrivateClassInSamePackage() {
+    Class<?> c = UnresolvedPackagePrivateClass.class;
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPublicFieldInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.publicIntField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: StaticFieldSet
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: UnresolvedStaticFieldSet
+  static void $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass() {
+    ResolvedPublicSubclassOfPackagePrivateClass.publicIntField = 42;
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPrivateFieldInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.privateIntField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() {
+    try {
+      ResolvedPublicSubclassOfPackagePrivateClass.privateIntField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPackagePrivateFieldInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.intField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: UnresolvedStaticFieldSet
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: StaticFieldSet
+  static void $noinline$testPackagePrivateFieldInPackagePrivateClassViaResolvedPublicSubclass() {
+    try {
+      ResolvedPublicSubclassOfPackagePrivateClass.intField = 42;
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPublicMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod
+  static void $noinline$testPublicMethodInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.$noinline$publicStaticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$publicStaticMethod
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: InvokeUnresolved method_name:{{[^$]*}}$noinline$publicStaticMethod
+  static void $noinline$testPublicMethodInPackagePrivateClassViaResolvedPublicSubclass() {
+    ResolvedPublicSubclassOfPackagePrivateClass.$noinline$publicStaticMethod();
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod
+  static void $noinline$testPrivateMethodInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.$noinline$privateStaticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$privateStaticMethod
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$privateStaticMethod
+  static void $noinline$testPrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() {
+    try {
+      ResolvedPublicSubclassOfPackagePrivateClass.$noinline$privateStaticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod
+  static void $noinline$testPackagePrivateMethodInResolvedPackagePrivateClass() {
+    try {
+      ResolvedPackagePrivateClass.$noinline$staticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK: InvokeUnresolved method_name:{{[^$]*}}$noinline$staticMethod
+
+  /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() builder (after)
+  /// CHECK-NOT: InvokeStaticOrDirect method_name:{{[^$]*}}$noinline$staticMethod
+  static void $noinline$testPackagePrivateMethodInPackagePrivateClassViaResolvedPublicSubclass() {
+    try {
+      ResolvedPublicSubclassOfPackagePrivateClass.$noinline$staticMethod();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+}
diff --git a/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClazz.java b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClazz.java
new file mode 100644
index 0000000..8fc8dd6
--- /dev/null
+++ b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClazz.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package unresolved;
+
+// Class with the same descriptor length as UnresolvedPublicClass.
+public class UnresolvedPublicClazz {
+}
diff --git a/test/727-checker-unresolved-class/src2/resolved/PackagePrivateSubclassOfUnresolvedClass.java b/test/727-checker-unresolved-class/src2/resolved/PackagePrivateSubclassOfUnresolvedClass.java
new file mode 100644
index 0000000..2f8526d
--- /dev/null
+++ b/test/727-checker-unresolved-class/src2/resolved/PackagePrivateSubclassOfUnresolvedClass.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+import getters.GetPackagePrivateSubclassOfUnresolvedClass;
+import unresolved.UnresolvedPublicClass;
+
+class PackagePrivateSubclassOfUnresolvedClass extends UnresolvedPublicClass {
+  public static void $noinline$main() {
+    $noinline$testReferrersClass();
+    $noinline$testInlinedReferrersClass();
+    $noinline$testInlinedReferrersClassFromSamePackage();
+
+    System.out.println("PackagePrivateSubclassOfUnresolvedClass passed");
+  }
+
+  /// CHECK-START: void resolved.PackagePrivateSubclassOfUnresolvedClass.$noinline$testReferrersClass() builder (after)
+  /// CHECK: LoadClass class_name:resolved.PackagePrivateSubclassOfUnresolvedClass needs_access_check:false
+  static void $noinline$testReferrersClass() {
+    Class<?> c = PackagePrivateSubclassOfUnresolvedClass.class;
+  }
+
+  /// CHECK-START: void resolved.PackagePrivateSubclassOfUnresolvedClass.$noinline$testInlinedReferrersClass() inliner (after)
+  // CHECK: LoadClass class_name:resolved.PackagePrivateSubclassOfUnresolvedClass needs_access_check:true
+  static void $noinline$testInlinedReferrersClass() {
+    try {
+      // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+      Class<?> c = GetPackagePrivateSubclassOfUnresolvedClass.get();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+
+  /// CHECK-START: void resolved.PackagePrivateSubclassOfUnresolvedClass.$noinline$testInlinedReferrersClassFromSamePackage() inliner (after)
+  // CHECK: LoadClass class_name:resolved.PackagePrivateSubclassOfUnresolvedClass needs_access_check:false
+  static void $noinline$testInlinedReferrersClassFromSamePackage() {
+    // TODO: Make $inline$ and enable CHECK above when we relax the verifier. b/28313047
+    Class<?> c = GetPackagePrivateSubclassOfUnresolvedClassFromSamePackage.get();
+  }
+}
diff --git a/test/727-checker-unresolved-class/src2/resolved/ResolvedPackagePrivateClass.java b/test/727-checker-unresolved-class/src2/resolved/ResolvedPackagePrivateClass.java
new file mode 100644
index 0000000..4d866e1
--- /dev/null
+++ b/test/727-checker-unresolved-class/src2/resolved/ResolvedPackagePrivateClass.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package resolved;
+
+class ResolvedPackagePrivateClass {
+    public static int publicIntField;
+    private static int privateIntField;
+    static int intField;
+
+    public static void $noinline$publicStaticMethod() {
+      System.out.println("ResolvedPackagePrivateClass.$noinline$publicStaticMethod()");
+    }
+
+    private static void $noinline$privateStaticMethod() {
+      System.out.println("ResolvedPackagePrivateClass.$noinline$privateStaticMethod()");
+    }
+
+    static void $noinline$staticMethod() {
+      System.out.println("ResolvedPackagePrivateClass.$noinline$staticMethod()");
+    }
+}
diff --git a/test/727-checker-unresolved-class/src2/unresolved/UnresolvedPackagePrivateClass.java b/test/727-checker-unresolved-class/src2/unresolved/UnresolvedPackagePrivateClass.java
new file mode 100644
index 0000000..5c3df25
--- /dev/null
+++ b/test/727-checker-unresolved-class/src2/unresolved/UnresolvedPackagePrivateClass.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package unresolved;
+
+import getters.GetUnresolvedPackagePrivateClass;
+
+class UnresolvedPackagePrivateClass {
+  public static void $noinline$main() {
+    $noinline$testReferrersClass();
+    $noinline$testInlinedReferrersClass();
+
+    System.out.println("UnresolvedPackagePrivateClass passed");
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPackagePrivateClass.$noinline$testReferrersClass() builder (after)
+  /// CHECK: LoadClass class_name:unresolved.UnresolvedPackagePrivateClass needs_access_check:false
+  static void $noinline$testReferrersClass() {
+    Class<?> c = UnresolvedPackagePrivateClass.class;
+  }
+
+  /// CHECK-START: void unresolved.UnresolvedPackagePrivateClass.$noinline$testInlinedReferrersClass() inliner (after)
+  // CHECK: LoadClass class_name:unresolved.UnresolvedPackagePrivateClass needs_access_check:true
+  static void $noinline$testInlinedReferrersClass() {
+    try {
+      // TODO: When we relax verifier to ignore access check failures,
+      // change the called method to `$inline$` and enable the CHECK above.
+      Class<?> c = GetUnresolvedPackagePrivateClass.get();
+      throw new Error("Unreachable");
+    } catch (IllegalAccessError expected) {}
+  }
+}
diff --git a/test/728-imt-conflict-zygote/Android.bp b/test/728-imt-conflict-zygote/Android.bp
new file mode 100644
index 0000000..aaa145c
--- /dev/null
+++ b/test/728-imt-conflict-zygote/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `728-imt-conflict-zygote`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-728-imt-conflict-zygote",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-728-imt-conflict-zygote-expected-stdout",
+        ":art-run-test-728-imt-conflict-zygote-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-728-imt-conflict-zygote-expected-stdout",
+    out: ["art-run-test-728-imt-conflict-zygote-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-728-imt-conflict-zygote-expected-stderr",
+    out: ["art-run-test-728-imt-conflict-zygote-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/723-string-init-range/expected.txt b/test/728-imt-conflict-zygote/expected-stderr.txt
similarity index 100%
copy from test/723-string-init-range/expected.txt
copy to test/728-imt-conflict-zygote/expected-stderr.txt
diff --git a/test/720-thread-priority/expected.txt b/test/728-imt-conflict-zygote/expected-stdout.txt
similarity index 100%
copy from test/720-thread-priority/expected.txt
copy to test/728-imt-conflict-zygote/expected-stdout.txt
diff --git a/test/728-imt-conflict-zygote/info.txt b/test/728-imt-conflict-zygote/info.txt
new file mode 100644
index 0000000..85a67f3
--- /dev/null
+++ b/test/728-imt-conflict-zygote/info.txt
@@ -0,0 +1,2 @@
+Regression test for the compiler in the case we need to do a runtime call to
+lookup an ArtMethod for an invokeinterface.
diff --git a/test/728-imt-conflict-zygote/run b/test/728-imt-conflict-zygote/run
new file mode 100644
index 0000000..8fdff6d
--- /dev/null
+++ b/test/728-imt-conflict-zygote/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2020 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.
+
+./default-run "$@" --zygote
diff --git a/test/728-imt-conflict-zygote/src/Main.java b/test/728-imt-conflict-zygote/src/Main.java
new file mode 100644
index 0000000..5a88679
--- /dev/null
+++ b/test/728-imt-conflict-zygote/src/Main.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2020 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.Method;
+
+// An interface with enough methods to trigger a conflict.
+interface Itf {
+  public void method0a();
+  public void method0b();
+  public void method0c();
+  public void method0d();
+  public void method0e();
+  public void method0f();
+  public void method0g();
+  public void method0h();
+  public void method0i();
+  public void method0j();
+  public void method0k();
+  public void method0l();
+  public void method0m();
+  public void method0n();
+  public void method0o();
+  public void method0p();
+  public void method0q();
+  public void method0r();
+  public void method0s();
+  public void method0t();
+  public void method0u();
+  public void method0v();
+  public void method0w();
+  public void method0x();
+  public void method0y();
+  public void method0z();
+  public void method1a();
+  public void method1b();
+  public void method1c();
+  public void method1d();
+  public void method1e();
+  public void method1f();
+  public void method1g();
+  public void method1h();
+  public void method1i();
+  public void method1j();
+  public void method1k();
+  public void method1l();
+  public void method1m();
+  public void method1n();
+  public void method1o();
+  public void method1p();
+  public void method1q();
+  public void method1r();
+  public void method1s();
+  public void method1t();
+  public void method1u();
+  public void method1v();
+  public void method1w();
+  public void method1x();
+  public void method1y();
+  public void method1z();
+  public void method2a();
+  public void method2b();
+  public void method2c();
+  public void method2d();
+  public void method2e();
+  public void method2f();
+  public void method2g();
+  public void method2h();
+  public void method2i();
+  public void method2j();
+  public void method2k();
+  public void method2l();
+  public void method2m();
+  public void method2n();
+  public void method2o();
+  public void method2p();
+  public void method2q();
+  public void method2r();
+  public void method2s();
+  public void method2t();
+  public void method2u();
+  public void method2v();
+  public void method2w();
+  public void method2x();
+  public void method2y();
+  public void method2z();
+}
+
+public class Main implements Itf {
+  public static Itf main;
+  public static void main(String[] args) throws Exception {
+    System.loadLibrary(args[0]);
+    ensureJitCompiled(Main.class, "$noinline$callInterfaceMethods");
+    $noinline$callInterfaceMethods(new Main());
+  }
+
+  public static native void ensureJitCompiled(Class<?> cls, String name);
+
+  public static void $noinline$callInterfaceMethods(Itf itf) {
+    itf.method0a();
+    itf.method0b();
+    itf.method0c();
+    itf.method0d();
+    itf.method0e();
+    itf.method0f();
+    itf.method0g();
+    itf.method0h();
+    itf.method0i();
+    itf.method0j();
+    itf.method0k();
+    itf.method0l();
+    itf.method0m();
+    itf.method0n();
+    itf.method0o();
+    itf.method0p();
+    itf.method0q();
+    itf.method0r();
+    itf.method0s();
+    itf.method0t();
+    itf.method0u();
+    itf.method0v();
+    itf.method0w();
+    itf.method0x();
+    itf.method0y();
+    itf.method0z();
+
+    itf.method1a();
+    itf.method1b();
+    itf.method1c();
+    itf.method1d();
+    itf.method1e();
+    itf.method1f();
+    itf.method1g();
+    itf.method1h();
+    itf.method1i();
+    itf.method1j();
+    itf.method1k();
+    itf.method1l();
+    itf.method1m();
+    itf.method1n();
+    itf.method1o();
+    itf.method1p();
+    itf.method1q();
+    itf.method1r();
+    itf.method1s();
+    itf.method1t();
+    itf.method1u();
+    itf.method1v();
+    itf.method1w();
+    itf.method1x();
+    itf.method1y();
+    itf.method1z();
+  }
+
+  public void method0a() {}
+  public void method0b() {}
+  public void method0c() {}
+  public void method0d() {}
+  public void method0e() {}
+  public void method0f() {}
+  public void method0g() {}
+  public void method0h() {}
+  public void method0i() {}
+  public void method0j() {}
+  public void method0k() {}
+  public void method0l() {}
+  public void method0m() {}
+  public void method0n() {}
+  public void method0o() {}
+  public void method0p() {}
+  public void method0q() {}
+  public void method0r() {}
+  public void method0s() {}
+  public void method0t() {}
+  public void method0u() {}
+  public void method0v() {}
+  public void method0w() {}
+  public void method0x() {}
+  public void method0y() {}
+  public void method0z() {}
+  public void method1a() {}
+  public void method1b() {}
+  public void method1c() {}
+  public void method1d() {}
+  public void method1e() {}
+  public void method1f() {}
+  public void method1g() {}
+  public void method1h() {}
+  public void method1i() {}
+  public void method1j() {}
+  public void method1k() {}
+  public void method1l() {}
+  public void method1m() {}
+  public void method1n() {}
+  public void method1o() {}
+  public void method1p() {}
+  public void method1q() {}
+  public void method1r() {}
+  public void method1s() {}
+  public void method1t() {}
+  public void method1u() {}
+  public void method1v() {}
+  public void method1w() {}
+  public void method1x() {}
+  public void method1y() {}
+  public void method1z() {}
+  public void method2a() {}
+  public void method2b() {}
+  public void method2c() {}
+  public void method2d() {}
+  public void method2e() {}
+  public void method2f() {}
+  public void method2g() {}
+  public void method2h() {}
+  public void method2i() {}
+  public void method2j() {}
+  public void method2k() {}
+  public void method2l() {}
+  public void method2m() {}
+  public void method2n() {}
+  public void method2o() {}
+  public void method2p() {}
+  public void method2q() {}
+  public void method2r() {}
+  public void method2s() {}
+  public void method2t() {}
+  public void method2u() {}
+  public void method2v() {}
+  public void method2w() {}
+  public void method2x() {}
+  public void method2y() {}
+  public void method2z() {}
+}
diff --git a/test/729-checker-polymorphic-intrinsic/Android.bp b/test/729-checker-polymorphic-intrinsic/Android.bp
new file mode 100644
index 0000000..b39635c
--- /dev/null
+++ b/test/729-checker-polymorphic-intrinsic/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `729-checker-polymorphic-intrinsic`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-729-checker-polymorphic-intrinsic",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-729-checker-polymorphic-intrinsic-expected-stdout",
+        ":art-run-test-729-checker-polymorphic-intrinsic-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-729-checker-polymorphic-intrinsic-expected-stdout",
+    out: ["art-run-test-729-checker-polymorphic-intrinsic-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-729-checker-polymorphic-intrinsic-expected-stderr",
+    out: ["art-run-test-729-checker-polymorphic-intrinsic-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/643-checker-bogus-ic/expected.txt b/test/729-checker-polymorphic-intrinsic/expected-stderr.txt
similarity index 100%
copy from test/643-checker-bogus-ic/expected.txt
copy to test/729-checker-polymorphic-intrinsic/expected-stderr.txt
diff --git a/test/643-checker-bogus-ic/expected.txt b/test/729-checker-polymorphic-intrinsic/expected-stdout.txt
similarity index 100%
copy from test/643-checker-bogus-ic/expected.txt
copy to test/729-checker-polymorphic-intrinsic/expected-stdout.txt
diff --git a/test/729-checker-polymorphic-intrinsic/info.txt b/test/729-checker-polymorphic-intrinsic/info.txt
new file mode 100644
index 0000000..bfe0f2d
--- /dev/null
+++ b/test/729-checker-polymorphic-intrinsic/info.txt
@@ -0,0 +1 @@
+Test for a polymorphic inline cache containing an intrinsic call.
diff --git a/test/729-checker-polymorphic-intrinsic/profile b/test/729-checker-polymorphic-intrinsic/profile
new file mode 100644
index 0000000..41598c3
--- /dev/null
+++ b/test/729-checker-polymorphic-intrinsic/profile
@@ -0,0 +1 @@
+SHLMain;->inlinePolymorphic(Ljava/lang/Object;)Ljava/lang/String;+Ljava/lang/StringBuilder;,Ljava/lang/String;
diff --git a/test/729-checker-polymorphic-intrinsic/run b/test/729-checker-polymorphic-intrinsic/run
new file mode 100644
index 0000000..5fa72ed
--- /dev/null
+++ b/test/729-checker-polymorphic-intrinsic/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 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/729-checker-polymorphic-intrinsic/src/Main.java b/test/729-checker-polymorphic-intrinsic/src/Main.java
new file mode 100644
index 0000000..e1b72ac
--- /dev/null
+++ b/test/729-checker-polymorphic-intrinsic/src/Main.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 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 {
+
+  /// CHECK-START: java.lang.String Main.inlinePolymorphic(java.lang.Object) inliner (before)
+  /// CHECK:       InvokeVirtual method_name:java.lang.Object.toString
+
+  /// CHECK-START: java.lang.String Main.inlinePolymorphic(java.lang.Object) inliner (after)
+  /// CHECK-DAG:   InvokeVirtual method_name:java.lang.Object.toString
+  /// CHECK-DAG:   InvokeVirtual method_name:java.lang.StringBuilder.toString intrinsic:StringBuilderToString
+  public static String inlinePolymorphic(Object obj) {
+    return obj.toString();
+  }
+
+  public static void assertEquals(String actual, String expected) {
+    if (!expected.equals(actual)) {
+      throw new Error("Expected " + expected + ", got " + actual);
+    }
+  }
+
+  public static void main(String[] args) {
+    assertEquals(inlinePolymorphic(new StringBuilder("abc")), "abc");
+    assertEquals(inlinePolymorphic("def"), "def");
+  }
+}
diff --git a/test/730-cha-deopt/Android.bp b/test/730-cha-deopt/Android.bp
new file mode 100644
index 0000000..472564c
--- /dev/null
+++ b/test/730-cha-deopt/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `730-cha-deopt`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-730-cha-deopt",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-730-cha-deopt-expected-stdout",
+        ":art-run-test-730-cha-deopt-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-730-cha-deopt-expected-stdout",
+    out: ["art-run-test-730-cha-deopt-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-730-cha-deopt-expected-stderr",
+    out: ["art-run-test-730-cha-deopt-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/513-array-deopt/expected.txt b/test/730-cha-deopt/expected-stderr.txt
similarity index 100%
copy from test/513-array-deopt/expected.txt
copy to test/730-cha-deopt/expected-stderr.txt
diff --git a/test/687-deopt/expected.txt b/test/730-cha-deopt/expected-stdout.txt
similarity index 100%
copy from test/687-deopt/expected.txt
copy to test/730-cha-deopt/expected-stdout.txt
diff --git a/test/730-cha-deopt/info.txt b/test/730-cha-deopt/info.txt
new file mode 100644
index 0000000..3679a24
--- /dev/null
+++ b/test/730-cha-deopt/info.txt
@@ -0,0 +1,2 @@
+Test that dynamically loading a class which invalidates single implementation
+assumptions, make compiled code deoptimize.
diff --git a/test/730-cha-deopt/src/Main.java b/test/730-cha-deopt/src/Main.java
new file mode 100644
index 0000000..effbec2
--- /dev/null
+++ b/test/730-cha-deopt/src/Main.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+interface Itf {
+  public String interfaceMethod();
+}
+
+public class Main implements Itf {
+
+  public static void main(String[] args) throws Exception {
+    System.loadLibrary(args[0]);
+    ensureJitCompiled(Main.class, "$noinline$invoke");
+    String result = $noinline$invoke(new Main());
+    if (!"Main".equals(result)) {
+      throw new Error("Expected Main, got " + result);
+    }
+
+    // Load SubItf dynamically, to avoid prior verification of this method to load it.
+    Class<?> cls = Class.forName("SubItf");
+    Itf itf = (Itf) cls.newInstance();
+
+    result = $noinline$invoke(itf);
+    if (!"SubItf".equals(result)) {
+      throw new Error("Expected SubItf, got " + result);
+    }
+
+  }
+
+  public static String $noinline$invoke(Itf itf) {
+    return itf.interfaceMethod();
+  }
+
+  public String interfaceMethod() {
+    return "Main";
+  }
+
+  public static native void ensureJitCompiled(Class<?> cls, String methodName);
+}
+
+class SubItf implements Itf {
+  public String interfaceMethod() {
+    return "SubItf";
+  }
+}
diff --git a/test/730-checker-inlining-super/Android.bp b/test/730-checker-inlining-super/Android.bp
new file mode 100644
index 0000000..8247b65
--- /dev/null
+++ b/test/730-checker-inlining-super/Android.bp
@@ -0,0 +1,43 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `730-checker-inlining-super`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-730-checker-inlining-super",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-730-checker-inlining-super-expected-stdout",
+        ":art-run-test-730-checker-inlining-super-expected-stderr",
+    ],
+    // Include the Java source files in the test's artifacts, to make Checker assertions
+    // available to the TradeFed test runner.
+    include_srcs: true,
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-730-checker-inlining-super-expected-stdout",
+    out: ["art-run-test-730-checker-inlining-super-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-730-checker-inlining-super-expected-stderr",
+    out: ["art-run-test-730-checker-inlining-super-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/551-invoke-super/expected.txt b/test/730-checker-inlining-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/730-checker-inlining-super/expected-stderr.txt
diff --git a/test/551-invoke-super/expected.txt b/test/730-checker-inlining-super/expected-stdout.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/730-checker-inlining-super/expected-stdout.txt
diff --git a/test/730-checker-inlining-super/info.txt b/test/730-checker-inlining-super/info.txt
new file mode 100644
index 0000000..d34596a
--- /dev/null
+++ b/test/730-checker-inlining-super/info.txt
@@ -0,0 +1,2 @@
+Test that an invoke-virtual devirtualized by the compiler uses the right bss
+slot at runtime.
diff --git a/test/730-checker-inlining-super/src/Main.java b/test/730-checker-inlining-super/src/Main.java
new file mode 100644
index 0000000..5a1b574
--- /dev/null
+++ b/test/730-checker-inlining-super/src/Main.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class SuperClass {
+  public int doInvoke() {
+    synchronized (this) {
+      return 42;
+    }
+  }
+}
+
+public class Main extends SuperClass {
+
+  public static void main(String[] args) {
+    Main m = new Main();
+    int value = doInvokeTypedSuperClass(m);
+    if (value != 43) {
+      throw new Error("Expected 43, got " + value);
+    }
+  }
+
+  public static int doInvokeTypedSuperClass(SuperClass sc) {
+    return sc.doInvoke();
+  }
+
+  public int doInvoke() {
+    synchronized (this) {
+      return super.doInvoke() + 1;
+    }
+  }
+}
diff --git a/test/001-Main/expected.txt b/test/800-smali/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/800-smali/expected-stderr.txt
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected-stdout.txt
similarity index 100%
rename from test/800-smali/expected.txt
rename to test/800-smali/expected-stdout.txt
diff --git a/test/800-smali/jni.cc b/test/800-smali/jni.cc
index bf9e88a..15830a3 100644
--- a/test/800-smali/jni.cc
+++ b/test/800-smali/jni.cc
@@ -29,11 +29,12 @@
 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAotVerified(JNIEnv* env, jclass, jclass cls) {
   ScopedObjectAccess soa(env);
   Runtime* rt = Runtime::Current();
-
-  ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass = hs.NewHandle(soa.Decode<mirror::Class>(cls));
   const DexFile& dex_file = *klass->GetDexCache()->GetDexFile();
   ClassStatus oat_file_class_status(ClassStatus::kNotReady);
-  bool ret = rt->GetClassLinker()->VerifyClassUsingOatFile(dex_file, klass, oat_file_class_status);
+  bool ret = rt->GetClassLinker()->VerifyClassUsingOatFile(
+      soa.Self(), dex_file, klass, oat_file_class_status);
   return ret;
 }
 
diff --git a/test/800-smali/smali/b_20843113.smali b/test/800-smali/smali/b_20843113.smali
index ab3dc41..0105c20 100644
--- a/test/800-smali/smali/b_20843113.smali
+++ b/test/800-smali/smali/b_20843113.smali
@@ -27,7 +27,7 @@
 .catchall {:Label1 .. :Label2} :Handler
 .end method
 
-# Just a dummy.
+# Just a placeholder.
 .method public static run()V
 .registers 1
        return-void
diff --git a/test/800-smali/smali/b_22411633_2.smali b/test/800-smali/smali/b_22411633_2.smali
index 9f27c4c..6c4be40 100644
--- a/test/800-smali/smali/b_22411633_2.smali
+++ b/test/800-smali/smali/b_22411633_2.smali
@@ -28,7 +28,7 @@
 
 :LabelMergeObject
 
-       # Dummy work to separate blocks. At this point, v4 is of type Reference<Object>.
+       # Arbitrary work to separate blocks. At this point, v4 is of type Reference<Object>.
        add-int/lit16 v3, v3, 1
 
 :LabelMerge
diff --git a/test/801-VoidCheckCast/expected.txt b/test/801-VoidCheckCast/expected-stderr.txt
similarity index 100%
rename from test/801-VoidCheckCast/expected.txt
rename to test/801-VoidCheckCast/expected-stderr.txt
diff --git a/test/801-VoidCheckCast/expected.txt b/test/801-VoidCheckCast/expected-stdout.txt
similarity index 100%
copy from test/801-VoidCheckCast/expected.txt
copy to test/801-VoidCheckCast/expected-stdout.txt
diff --git a/test/536-checker-intrinsic-optimization/expected.txt b/test/802-deoptimization/expected-stderr.txt
similarity index 100%
copy from test/536-checker-intrinsic-optimization/expected.txt
copy to test/802-deoptimization/expected-stderr.txt
diff --git a/test/802-deoptimization/expected.txt b/test/802-deoptimization/expected-stdout.txt
similarity index 100%
rename from test/802-deoptimization/expected.txt
rename to test/802-deoptimization/expected-stdout.txt
diff --git a/test/551-invoke-super/expected.txt b/test/803-no-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/803-no-super/expected-stderr.txt
diff --git a/test/803-no-super/expected.txt b/test/803-no-super/expected-stdout.txt
similarity index 100%
rename from test/803-no-super/expected.txt
rename to test/803-no-super/expected-stdout.txt
diff --git a/test/1903-suspend-self/expected.txt b/test/804-class-extends-itself/expected-stderr.txt
similarity index 100%
copy from test/1903-suspend-self/expected.txt
copy to test/804-class-extends-itself/expected-stderr.txt
diff --git a/test/804-class-extends-itself/expected.txt b/test/804-class-extends-itself/expected-stdout.txt
similarity index 100%
rename from test/804-class-extends-itself/expected.txt
rename to test/804-class-extends-itself/expected-stdout.txt
diff --git a/test/805-TooDeepClassInstanceOf/Android.bp b/test/805-TooDeepClassInstanceOf/Android.bp
new file mode 100644
index 0000000..878f126
--- /dev/null
+++ b/test/805-TooDeepClassInstanceOf/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `805-TooDeepClassInstanceOf`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-805-TooDeepClassInstanceOf",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-805-TooDeepClassInstanceOf-expected-stdout",
+        ":art-run-test-805-TooDeepClassInstanceOf-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-805-TooDeepClassInstanceOf-expected-stdout",
+    out: ["art-run-test-805-TooDeepClassInstanceOf-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-805-TooDeepClassInstanceOf-expected-stderr",
+    out: ["art-run-test-805-TooDeepClassInstanceOf-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/801-VoidCheckCast/expected.txt b/test/805-TooDeepClassInstanceOf/expected-stderr.txt
similarity index 100%
copy from test/801-VoidCheckCast/expected.txt
copy to test/805-TooDeepClassInstanceOf/expected-stderr.txt
diff --git a/test/805-TooDeepClassInstanceOf/expected.txt b/test/805-TooDeepClassInstanceOf/expected-stdout.txt
similarity index 100%
rename from test/805-TooDeepClassInstanceOf/expected.txt
rename to test/805-TooDeepClassInstanceOf/expected-stdout.txt
diff --git a/test/806-TooWideClassInstanceOf/Android.bp b/test/806-TooWideClassInstanceOf/Android.bp
new file mode 100644
index 0000000..bdff812
--- /dev/null
+++ b/test/806-TooWideClassInstanceOf/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `806-TooWideClassInstanceOf`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-806-TooWideClassInstanceOf",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-806-TooWideClassInstanceOf-expected-stdout",
+        ":art-run-test-806-TooWideClassInstanceOf-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-806-TooWideClassInstanceOf-expected-stdout",
+    out: ["art-run-test-806-TooWideClassInstanceOf-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-806-TooWideClassInstanceOf-expected-stderr",
+    out: ["art-run-test-806-TooWideClassInstanceOf-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/801-VoidCheckCast/expected.txt b/test/806-TooWideClassInstanceOf/expected-stderr.txt
similarity index 100%
copy from test/801-VoidCheckCast/expected.txt
copy to test/806-TooWideClassInstanceOf/expected-stderr.txt
diff --git a/test/806-TooWideClassInstanceOf/expected.txt b/test/806-TooWideClassInstanceOf/expected-stdout.txt
similarity index 100%
rename from test/806-TooWideClassInstanceOf/expected.txt
rename to test/806-TooWideClassInstanceOf/expected-stdout.txt
diff --git a/test/801-VoidCheckCast/expected.txt b/test/807-method-handle-and-mr/expected-stderr.txt
similarity index 100%
copy from test/801-VoidCheckCast/expected.txt
copy to test/807-method-handle-and-mr/expected-stderr.txt
diff --git a/test/807-method-handle-and-mr/expected.txt b/test/807-method-handle-and-mr/expected-stdout.txt
similarity index 100%
rename from test/807-method-handle-and-mr/expected.txt
rename to test/807-method-handle-and-mr/expected-stdout.txt
diff --git a/test/563-checker-invoke-super/expected.txt b/test/808-checker-invoke-super/expected-stderr.txt
similarity index 100%
copy from test/563-checker-invoke-super/expected.txt
copy to test/808-checker-invoke-super/expected-stderr.txt
diff --git a/test/563-checker-invoke-super/expected.txt b/test/808-checker-invoke-super/expected-stdout.txt
similarity index 100%
copy from test/563-checker-invoke-super/expected.txt
copy to test/808-checker-invoke-super/expected-stdout.txt
diff --git a/test/808-checker-invoke-super/info.txt b/test/808-checker-invoke-super/info.txt
new file mode 100644
index 0000000..015ce5c
--- /dev/null
+++ b/test/808-checker-invoke-super/info.txt
@@ -0,0 +1,2 @@
+Test that even if a supercall cannot directly reference the resolved method
+within the dex file, we still generate a HInvokeStaticOrDirect.
diff --git a/test/808-checker-invoke-super/smali-multidex/Class.smali b/test/808-checker-invoke-super/smali-multidex/Class.smali
new file mode 100644
index 0000000..e312c45
--- /dev/null
+++ b/test/808-checker-invoke-super/smali-multidex/Class.smali
@@ -0,0 +1,24 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LClass;
+.super LSuperClass;
+
+## CHECK-START: void Class.$noinline$foo() register (after)
+## CHECK-DAG:     InvokeStaticOrDirect method_name:SuperClass.$noinline$foo
+.method public $noinline$foo()V
+.registers 1
+    invoke-super {p0}, LClass;->$noinline$foo()V
+    return-void
+.end method
diff --git a/test/808-checker-invoke-super/smali/Main.smali b/test/808-checker-invoke-super/smali/Main.smali
new file mode 100644
index 0000000..b9122b3
--- /dev/null
+++ b/test/808-checker-invoke-super/smali/Main.smali
@@ -0,0 +1,25 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LMain;
+.super Ljava/lang/Object;
+
+.method public static main([Ljava/lang/String;)V
+.registers 1
+    new-instance v0, LClass;
+    invoke-direct {v0}, LClass;-><init>()V
+    invoke-virtual {v0}, LClass;->$noinline$foo()V
+    invoke-virtual {v0}, LClass;->$noinline$foo()V
+    return-void
+.end method
diff --git a/test/808-checker-invoke-super/smali/SuperClass.smali b/test/808-checker-invoke-super/smali/SuperClass.smali
new file mode 100644
index 0000000..506cf56
--- /dev/null
+++ b/test/808-checker-invoke-super/smali/SuperClass.smali
@@ -0,0 +1,21 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LSuperClass;
+.super Ljava/lang/Object;
+
+.method public $noinline$foo()V
+.registers 1
+    return-void
+.end method
diff --git a/test/160-read-barrier-stress/expected.txt b/test/809-checker-invoke-super-bss/expected-stderr.txt
similarity index 100%
copy from test/160-read-barrier-stress/expected.txt
copy to test/809-checker-invoke-super-bss/expected-stderr.txt
diff --git a/test/160-read-barrier-stress/expected.txt b/test/809-checker-invoke-super-bss/expected-stdout.txt
similarity index 100%
copy from test/160-read-barrier-stress/expected.txt
copy to test/809-checker-invoke-super-bss/expected-stdout.txt
diff --git a/test/809-checker-invoke-super-bss/info.txt b/test/809-checker-invoke-super-bss/info.txt
new file mode 100644
index 0000000..4ec0867
--- /dev/null
+++ b/test/809-checker-invoke-super-bss/info.txt
@@ -0,0 +1,2 @@
+Test that the dex invoke index of an HInvokeStaticOrDirect coming for a super
+call is that of the resolved method. The BSS logic at runtime depends on it.
diff --git a/test/809-checker-invoke-super-bss/smali-multidex/OtherClass.smali b/test/809-checker-invoke-super-bss/smali-multidex/OtherClass.smali
new file mode 100644
index 0000000..2a87f4b
--- /dev/null
+++ b/test/809-checker-invoke-super-bss/smali-multidex/OtherClass.smali
@@ -0,0 +1,30 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LOtherClass;
+.super LSuperClass;
+
+## CHECK-START: void OtherClass.$noinline$foo() register (after)
+## CHECK-DAG:     InvokeStaticOrDirect dex_file_index:<<Index1:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-DAG:     InvokeStaticOrDirect dex_file_index:<<Index2:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-DAG:     InvokeStaticOrDirect dex_file_index:<<Index3:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-EVAL:    <<Index1>> == <<Index2>>
+## CHECK-EVAL:    <<Index1>> == <<Index3>>
+.method public $noinline$foo()V
+.registers 1
+    invoke-super {p0}, LOtherClass;->$noinline$foo()V
+    invoke-super {p0}, LSuperClass;->$noinline$foo()V
+    invoke-super {p0}, LSuperSuperClass;->$noinline$foo()V
+    return-void
+.end method
diff --git a/test/809-checker-invoke-super-bss/smali/Class.smali b/test/809-checker-invoke-super-bss/smali/Class.smali
new file mode 100644
index 0000000..5d416a7
--- /dev/null
+++ b/test/809-checker-invoke-super-bss/smali/Class.smali
@@ -0,0 +1,30 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LClass;
+.super LSuperClass;
+
+## CHECK-START: void Class.$noinline$foo() register (after)
+## CHECK-DAG:     InvokeStaticOrDirect dex_file_index:<<Index1:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-DAG:     InvokeStaticOrDirect dex_file_index:<<Index2:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-DAG:     InvokeStaticOrDirect dex_file_index:<<Index3:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-EVAL:    <<Index1>> == <<Index2>>
+## CHECK-EVAL:    <<Index1>> == <<Index3>>
+.method public $noinline$foo()V
+.registers 1
+    invoke-super {p0}, LClass;->$noinline$foo()V
+    invoke-super {p0}, LSuperClass;->$noinline$foo()V
+    invoke-super {p0}, LSuperSuperClass;->$noinline$foo()V
+    return-void
+.end method
diff --git a/test/809-checker-invoke-super-bss/smali/Main.smali b/test/809-checker-invoke-super-bss/smali/Main.smali
new file mode 100644
index 0000000..6d67f08
--- /dev/null
+++ b/test/809-checker-invoke-super-bss/smali/Main.smali
@@ -0,0 +1,29 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LMain;
+.super Ljava/lang/Object;
+
+.method public static main([Ljava/lang/String;)V
+.registers 1
+    new-instance v0, LClass;
+    invoke-direct {v0}, LClass;-><init>()V
+    invoke-virtual {v0}, LClass;->$noinline$foo()V
+    invoke-virtual {v0}, LClass;->$noinline$foo()V
+    new-instance v0, LOtherClass;
+    invoke-direct {v0}, LOtherClass;-><init>()V
+    invoke-virtual {v0}, LOtherClass;->$noinline$foo()V
+    invoke-virtual {v0}, LOtherClass;->$noinline$foo()V
+    return-void
+.end method
diff --git a/test/809-checker-invoke-super-bss/smali/SuperClass.smali b/test/809-checker-invoke-super-bss/smali/SuperClass.smali
new file mode 100644
index 0000000..7dfc7dc
--- /dev/null
+++ b/test/809-checker-invoke-super-bss/smali/SuperClass.smali
@@ -0,0 +1,16 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LSuperClass;
+.super LSuperSuperClass;
diff --git a/test/809-checker-invoke-super-bss/smali/SuperSuperClass.smali b/test/809-checker-invoke-super-bss/smali/SuperSuperClass.smali
new file mode 100644
index 0000000..05b687a
--- /dev/null
+++ b/test/809-checker-invoke-super-bss/smali/SuperSuperClass.smali
@@ -0,0 +1,21 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LSuperSuperClass;
+.super Ljava/lang/Object;
+
+.method public $noinline$foo()V
+.registers 1
+    return-void
+.end method
diff --git a/test/516-dead-move-result/expected.txt b/test/810-checker-invoke-super-default/expected-stderr.txt
similarity index 100%
copy from test/516-dead-move-result/expected.txt
copy to test/810-checker-invoke-super-default/expected-stderr.txt
diff --git a/test/516-dead-move-result/expected.txt b/test/810-checker-invoke-super-default/expected-stdout.txt
similarity index 100%
copy from test/516-dead-move-result/expected.txt
copy to test/810-checker-invoke-super-default/expected-stdout.txt
diff --git a/test/810-checker-invoke-super-default/info.txt b/test/810-checker-invoke-super-default/info.txt
new file mode 100644
index 0000000..f5c5dbf
--- /dev/null
+++ b/test/810-checker-invoke-super-default/info.txt
@@ -0,0 +1 @@
+Test that we don't store copied methods in BSS.
diff --git a/test/810-checker-invoke-super-default/smali/AbstractClass.smali b/test/810-checker-invoke-super-default/smali/AbstractClass.smali
new file mode 100644
index 0000000..c7be9c7
--- /dev/null
+++ b/test/810-checker-invoke-super-default/smali/AbstractClass.smali
@@ -0,0 +1,17 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class abstract LAbstractClass;
+.super Ljava/lang/Object;
+.implements LItf;
diff --git a/test/810-checker-invoke-super-default/smali/Class.smali b/test/810-checker-invoke-super-default/smali/Class.smali
new file mode 100644
index 0000000..807b839
--- /dev/null
+++ b/test/810-checker-invoke-super-default/smali/Class.smali
@@ -0,0 +1,30 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LClass;
+.super LAbstractClass;
+
+## CHECK-START: void Class.$noinline$foo() register (after)
+# We check that the method_index is 0, as that's the method index for the interface method.
+# The copied method would have a different method index.
+## CHECK-DAG:     InvokeStaticOrDirect method_name:Itf.$noinline$foo method_index:0
+## CHECK-DAG:     InvokeStaticOrDirect method_name:Itf.$noinline$foo method_index:0
+## CHECK-DAG:     InvokeStaticOrDirect method_name:Itf.$noinline$foo method_index:0
+.method public $noinline$foo()V
+.registers 1
+    invoke-super {p0}, LClass;->$noinline$foo()V
+    invoke-super {p0}, LAbstractClass;->$noinline$foo()V
+    invoke-super {p0}, LItf;->$noinline$foo()V
+    return-void
+.end method
diff --git a/test/810-checker-invoke-super-default/smali/Itf.smali b/test/810-checker-invoke-super-default/smali/Itf.smali
new file mode 100644
index 0000000..350c85d
--- /dev/null
+++ b/test/810-checker-invoke-super-default/smali/Itf.smali
@@ -0,0 +1,21 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public abstract interface LItf;
+.super Ljava/lang/Object;
+
+.method public $noinline$foo()V
+.registers 1
+   return-void
+.end method
diff --git a/test/810-checker-invoke-super-default/smali/Main.smali b/test/810-checker-invoke-super-default/smali/Main.smali
new file mode 100644
index 0000000..6d67f08
--- /dev/null
+++ b/test/810-checker-invoke-super-default/smali/Main.smali
@@ -0,0 +1,29 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LMain;
+.super Ljava/lang/Object;
+
+.method public static main([Ljava/lang/String;)V
+.registers 1
+    new-instance v0, LClass;
+    invoke-direct {v0}, LClass;-><init>()V
+    invoke-virtual {v0}, LClass;->$noinline$foo()V
+    invoke-virtual {v0}, LClass;->$noinline$foo()V
+    new-instance v0, LOtherClass;
+    invoke-direct {v0}, LOtherClass;-><init>()V
+    invoke-virtual {v0}, LOtherClass;->$noinline$foo()V
+    invoke-virtual {v0}, LOtherClass;->$noinline$foo()V
+    return-void
+.end method
diff --git a/test/810-checker-invoke-super-default/smali/OtherAbstractClass.smali b/test/810-checker-invoke-super-default/smali/OtherAbstractClass.smali
new file mode 100644
index 0000000..496484c
--- /dev/null
+++ b/test/810-checker-invoke-super-default/smali/OtherAbstractClass.smali
@@ -0,0 +1,17 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class abstract LOtherAbstractClass;
+.super Ljava/lang/Object;
+.implements LItf;
diff --git a/test/810-checker-invoke-super-default/smali/OtherClass.smali b/test/810-checker-invoke-super-default/smali/OtherClass.smali
new file mode 100644
index 0000000..e6e18fe
--- /dev/null
+++ b/test/810-checker-invoke-super-default/smali/OtherClass.smali
@@ -0,0 +1,30 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class LOtherClass;
+.super LOtherAbstractClass;
+
+## CHECK-START: void OtherClass.$noinline$foo() register (after)
+# We check that the method_index is 0, as that's the method index for the interface method.
+# The copied method would have a different method index.
+## CHECK-DAG:     InvokeStaticOrDirect method_name:Itf.$noinline$foo method_index:0
+## CHECK-DAG:     InvokeStaticOrDirect method_name:Itf.$noinline$foo method_index:0
+## CHECK-DAG:     InvokeStaticOrDirect method_name:Itf.$noinline$foo method_index:0
+.method public $noinline$foo()V
+.registers 1
+    invoke-super {p0}, LOtherClass;->$noinline$foo()V
+    invoke-super {p0}, LOtherAbstractClass;->$noinline$foo()V
+    invoke-super {p0}, LItf;->$noinline$foo()V
+    return-void
+.end method
diff --git a/test/688-shared-library/expected.txt b/test/811-checker-invoke-super-secondary/expected-stderr.txt
similarity index 100%
copy from test/688-shared-library/expected.txt
copy to test/811-checker-invoke-super-secondary/expected-stderr.txt
diff --git a/test/688-shared-library/expected.txt b/test/811-checker-invoke-super-secondary/expected-stdout.txt
similarity index 100%
copy from test/688-shared-library/expected.txt
copy to test/811-checker-invoke-super-secondary/expected-stdout.txt
diff --git a/test/811-checker-invoke-super-secondary/info.txt b/test/811-checker-invoke-super-secondary/info.txt
new file mode 100644
index 0000000..1de0057
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/info.txt
@@ -0,0 +1,2 @@
+Regression test when a super call resolves to a method from a different class
+loader.
diff --git a/test/811-checker-invoke-super-secondary/smali-ex/OtherClass.smali b/test/811-checker-invoke-super-secondary/smali-ex/OtherClass.smali
new file mode 100644
index 0000000..ba58b9c
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/smali-ex/OtherClass.smali
@@ -0,0 +1,34 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LOtherClass;
+.super LOtherSuperClass;
+
+## CHECK-START: void OtherClass.$noinline$foo() register (after)
+## CHECK-DAG:     InvokeStaticOrDirect dex_file_index:<<Index1:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-DAG:     InvokeStaticOrDirect dex_file_index:<<Index2:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-EVAL:    <<Index1>> == <<Index2>>
+.method public $noinline$foo()V
+.registers 1
+    invoke-super {p0}, LOtherSuperClass;->$noinline$foo()V
+    invoke-super {p0}, LSuperSuperClass;->$noinline$foo()V
+    return-void
+.end method
+
+.method public constructor <init>()V
+    .registers 1
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method
+
diff --git a/test/811-checker-invoke-super-secondary/smali-ex/OtherSuperClass.smali b/test/811-checker-invoke-super-secondary/smali-ex/OtherSuperClass.smali
new file mode 100644
index 0000000..4b444bb
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/smali-ex/OtherSuperClass.smali
@@ -0,0 +1,16 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LOtherSuperClass;
+.super LSuperClass;
diff --git a/test/811-checker-invoke-super-secondary/smali/SuperClass.smali b/test/811-checker-invoke-super-secondary/smali/SuperClass.smali
new file mode 100644
index 0000000..016da13
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/smali/SuperClass.smali
@@ -0,0 +1,16 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LSuperClass;
+.super LSuperSuperClass;
diff --git a/test/811-checker-invoke-super-secondary/smali/SuperSuperClass.smali b/test/811-checker-invoke-super-secondary/smali/SuperSuperClass.smali
new file mode 100644
index 0000000..4c4569e
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/smali/SuperSuperClass.smali
@@ -0,0 +1,21 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LSuperSuperClass;
+.super Ljava/lang/Object;
+
+.method public $noinline$foo()V
+.registers 1
+    return-void
+.end method
diff --git a/test/811-checker-invoke-super-secondary/src/Main.java b/test/811-checker-invoke-super-secondary/src/Main.java
new file mode 100644
index 0000000..6c9fcc1
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/src/Main.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 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 dalvik.system.PathClassLoader;
+
+class Main {
+  static final String TEST_NAME = "811-checker-invoke-super-secondary";
+
+  static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/" + TEST_NAME + ".jar";
+
+  static final String SECONDARY_NAME = TEST_NAME + "-ex";
+  static final String SECONDARY_DEX_FILE =
+    System.getenv("DEX_LOCATION") + "/" + SECONDARY_NAME + ".jar";
+
+  public static void main(String[] args) throws Exception {
+    PathClassLoader pcl = new PathClassLoader(SECONDARY_DEX_FILE, Main.class.getClassLoader());
+
+    Class<?> secondaryCls = pcl.loadClass("OtherClass");
+    secondaryCls.getDeclaredMethod("$noinline$foo").invoke(secondaryCls.newInstance());
+  }
+}
diff --git a/test/812-recursive-default/Android.bp b/test/812-recursive-default/Android.bp
new file mode 100644
index 0000000..9c2fe2c
--- /dev/null
+++ b/test/812-recursive-default/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `812-recursive-default`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-812-recursive-default",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-812-recursive-default-expected-stdout",
+        ":art-run-test-812-recursive-default-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-812-recursive-default-expected-stdout",
+    out: ["art-run-test-812-recursive-default-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-812-recursive-default-expected-stderr",
+    out: ["art-run-test-812-recursive-default-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/516-dead-move-result/expected.txt b/test/812-recursive-default/expected-stderr.txt
similarity index 100%
copy from test/516-dead-move-result/expected.txt
copy to test/812-recursive-default/expected-stderr.txt
diff --git a/test/516-dead-move-result/expected.txt b/test/812-recursive-default/expected-stdout.txt
similarity index 100%
copy from test/516-dead-move-result/expected.txt
copy to test/812-recursive-default/expected-stdout.txt
diff --git a/test/812-recursive-default/info.txt b/test/812-recursive-default/info.txt
new file mode 100644
index 0000000..0fe9de7
--- /dev/null
+++ b/test/812-recursive-default/info.txt
@@ -0,0 +1,2 @@
+Test that the compiler can handle recursive calls in a
+default interface method.
diff --git a/test/812-recursive-default/src/Main.java b/test/812-recursive-default/src/Main.java
new file mode 100644
index 0000000..4a6b886
--- /dev/null
+++ b/test/812-recursive-default/src/Main.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+interface Itf {
+  public default int fib(int a) {
+    if (a <= 1) return a;
+    return fib(a - 1) + fib(a - 2);
+  }
+}
+
+public class Main implements Itf {
+
+  public static void main(String[] args) {
+    int result = new Main().fib(2);
+    if (result != 1) {
+      throw new Error("Expected 1, got " + result);
+    }
+  }
+
+  public int fib(int a) {
+    return Itf.super.fib(a);
+  }
+}
diff --git a/test/813-fp-args/Android.bp b/test/813-fp-args/Android.bp
new file mode 100644
index 0000000..5df0f42
--- /dev/null
+++ b/test/813-fp-args/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `813-fp-args`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-813-fp-args",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-813-fp-args-expected-stdout",
+        ":art-run-test-813-fp-args-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-813-fp-args-expected-stdout",
+    out: ["art-run-test-813-fp-args-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-813-fp-args-expected-stderr",
+    out: ["art-run-test-813-fp-args-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/406-fields/expected.txt b/test/813-fp-args/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/813-fp-args/expected-stderr.txt
diff --git a/test/457-regs/expected.txt b/test/813-fp-args/expected-stdout.txt
similarity index 100%
copy from test/457-regs/expected.txt
copy to test/813-fp-args/expected-stdout.txt
diff --git a/test/813-fp-args/info.txt b/test/813-fp-args/info.txt
new file mode 100644
index 0000000..5c204cb
--- /dev/null
+++ b/test/813-fp-args/info.txt
@@ -0,0 +1 @@
+Regression test on floating point native ABI, targeted for ARM.
diff --git a/test/813-fp-args/src/Main.java b/test/813-fp-args/src/Main.java
new file mode 100644
index 0000000..fa8ac07
--- /dev/null
+++ b/test/813-fp-args/src/Main.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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]);
+    // Compile it to ensure we're calling compiled code.
+    ensureJitCompiled(Main.class, "myMethod");
+    myMethod(1, 2, 3, 4);
+  }
+
+  public static void assertEquals(float expected, float actual) {
+    if (expected != actual) {
+      throw new Error("Expected " + expected + " got " + actual);
+    }
+  }
+
+  public static void assertEquals(double expected, double actual) {
+    if (expected != actual) {
+      throw new Error("Expected " + expected + " got " + actual);
+    }
+  }
+
+  public static void myMethod(float a, double b, float c, float d) {
+    assertEquals(1, a);
+    assertEquals(2, b);
+    assertEquals(3, c);
+    assertEquals(4, d);
+  }
+
+  public static native void ensureJitCompiled(Class<?> cls, String name);
+}
diff --git a/test/814-large-field-offsets/Android.bp b/test/814-large-field-offsets/Android.bp
new file mode 100644
index 0000000..e3193a8
--- /dev/null
+++ b/test/814-large-field-offsets/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `814-large-field-offsets`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-814-large-field-offsets",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-814-large-field-offsets-expected-stdout",
+        ":art-run-test-814-large-field-offsets-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-814-large-field-offsets-expected-stdout",
+    out: ["art-run-test-814-large-field-offsets-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-814-large-field-offsets-expected-stderr",
+    out: ["art-run-test-814-large-field-offsets-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/410-floats/expected.txt b/test/814-large-field-offsets/expected-stderr.txt
similarity index 100%
copy from test/410-floats/expected.txt
copy to test/814-large-field-offsets/expected-stderr.txt
diff --git a/test/410-floats/expected.txt b/test/814-large-field-offsets/expected-stdout.txt
similarity index 100%
copy from test/410-floats/expected.txt
copy to test/814-large-field-offsets/expected-stdout.txt
diff --git a/test/814-large-field-offsets/info.txt b/test/814-large-field-offsets/info.txt
new file mode 100644
index 0000000..eb2351f
--- /dev/null
+++ b/test/814-large-field-offsets/info.txt
@@ -0,0 +1 @@
+Regression test checking that we throw NPE on large field offsets.
diff --git a/test/814-large-field-offsets/src/Main.java b/test/814-large-field-offsets/src/Main.java
new file mode 100644
index 0000000..36d4f5e
--- /dev/null
+++ b/test/814-large-field-offsets/src/Main.java
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2017 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 {
+
+  Object i0000, i0001, i0002, i0003, i0004, i0005, i0006, i0007, i0008, i0009;
+  Object i0010, i0011, i0012, i0013, i0014, i0015, i0016, i0017, i0018, i0019;
+  Object i0020, i0021, i0022, i0023, i0024, i0025, i0026, i0027, i0028, i0029;
+  Object i0030, i0031, i0032, i0033, i0034, i0035, i0036, i0037, i0038, i0039;
+  Object i0040, i0041, i0042, i0043, i0044, i0045, i0046, i0047, i0048, i0049;
+  Object i0050, i0051, i0052, i0053, i0054, i0055, i0056, i0057, i0058, i0059;
+  Object i0060, i0061, i0062, i0063, i0064, i0065, i0066, i0067, i0068, i0069;
+  Object i0070, i0071, i0072, i0073, i0074, i0075, i0076, i0077, i0078, i0079;
+  Object i0080, i0081, i0082, i0083, i0084, i0085, i0086, i0087, i0088, i0089;
+  Object i0090, i0091, i0092, i0093, i0094, i0095, i0096, i0097, i0098, i0099;
+
+  Object i0100, i0101, i0102, i0103, i0104, i0105, i0106, i0107, i0108, i0109;
+  Object i0110, i0111, i0112, i0113, i0114, i0115, i0116, i0117, i0118, i0119;
+  Object i0120, i0121, i0122, i0123, i0124, i0125, i0126, i0127, i0128, i0129;
+  Object i0130, i0131, i0132, i0133, i0134, i0135, i0136, i0137, i0138, i0139;
+  Object i0140, i0141, i0142, i0143, i0144, i0145, i0146, i0147, i0148, i0149;
+  Object i0150, i0151, i0152, i0153, i0154, i0155, i0156, i0157, i0158, i0159;
+  Object i0160, i0161, i0162, i0163, i0164, i0165, i0166, i0167, i0168, i0169;
+  Object i0170, i0171, i0172, i0173, i0174, i0175, i0176, i0177, i0178, i0179;
+  Object i0180, i0181, i0182, i0183, i0184, i0185, i0186, i0187, i0188, i0189;
+  Object i0190, i0191, i0192, i0193, i0194, i0195, i0196, i0197, i0198, i0199;
+
+  Object i0200, i0201, i0202, i0203, i0204, i0205, i0206, i0207, i0208, i0209;
+  Object i0210, i0211, i0212, i0213, i0214, i0215, i0216, i0217, i0218, i0219;
+  Object i0220, i0221, i0222, i0223, i0224, i0225, i0226, i0227, i0228, i0229;
+  Object i0230, i0231, i0232, i0233, i0234, i0235, i0236, i0237, i0238, i0239;
+  Object i0240, i0241, i0242, i0243, i0244, i0245, i0246, i0247, i0248, i0249;
+  Object i0250, i0251, i0252, i0253, i0254, i0255, i0256, i0257, i0258, i0259;
+  Object i0260, i0261, i0262, i0263, i0264, i0265, i0266, i0267, i0268, i0269;
+  Object i0270, i0271, i0272, i0273, i0274, i0275, i0276, i0277, i0278, i0279;
+  Object i0280, i0281, i0282, i0283, i0284, i0285, i0286, i0287, i0288, i0289;
+  Object i0290, i0291, i0292, i0293, i0294, i0295, i0296, i0297, i0298, i0299;
+
+  Object i0300, i0301, i0302, i0303, i0304, i0305, i0306, i0307, i0308, i0309;
+  Object i0310, i0311, i0312, i0313, i0314, i0315, i0316, i0317, i0318, i0319;
+  Object i0320, i0321, i0322, i0323, i0324, i0325, i0326, i0327, i0328, i0329;
+  Object i0330, i0331, i0332, i0333, i0334, i0335, i0336, i0337, i0338, i0339;
+  Object i0340, i0341, i0342, i0343, i0344, i0345, i0346, i0347, i0348, i0349;
+  Object i0350, i0351, i0352, i0353, i0354, i0355, i0356, i0357, i0358, i0359;
+  Object i0360, i0361, i0362, i0363, i0364, i0365, i0366, i0367, i0368, i0369;
+  Object i0370, i0371, i0372, i0373, i0374, i0375, i0376, i0377, i0378, i0379;
+  Object i0380, i0381, i0382, i0383, i0384, i0385, i0386, i0387, i0388, i0389;
+  Object i0390, i0391, i0392, i0393, i0394, i0395, i0396, i0397, i0398, i0399;
+
+  Object i0400, i0401, i0402, i0403, i0404, i0405, i0406, i0407, i0408, i0409;
+  Object i0410, i0411, i0412, i0413, i0414, i0415, i0416, i0417, i0418, i0419;
+  Object i0420, i0421, i0422, i0423, i0424, i0425, i0426, i0427, i0428, i0429;
+  Object i0430, i0431, i0432, i0433, i0434, i0435, i0436, i0437, i0438, i0439;
+  Object i0440, i0441, i0442, i0443, i0444, i0445, i0446, i0447, i0448, i0449;
+  Object i0450, i0451, i0452, i0453, i0454, i0455, i0456, i0457, i0458, i0459;
+  Object i0460, i0461, i0462, i0463, i0464, i0465, i0466, i0467, i0468, i0469;
+  Object i0470, i0471, i0472, i0473, i0474, i0475, i0476, i0477, i0478, i0479;
+  Object i0480, i0481, i0482, i0483, i0484, i0485, i0486, i0487, i0488, i0489;
+  Object i0490, i0491, i0492, i0493, i0494, i0495, i0496, i0497, i0498, i0499;
+
+  Object i0500, i0501, i0502, i0503, i0504, i0505, i0506, i0507, i0508, i0509;
+  Object i0510, i0511, i0512, i0513, i0514, i0515, i0516, i0517, i0518, i0519;
+  Object i0520, i0521, i0522, i0523, i0524, i0525, i0526, i0527, i0528, i0529;
+  Object i0530, i0531, i0532, i0533, i0534, i0535, i0536, i0537, i0538, i0539;
+  Object i0540, i0541, i0542, i0543, i0544, i0545, i0546, i0547, i0548, i0549;
+  Object i0550, i0551, i0552, i0553, i0554, i0555, i0556, i0557, i0558, i0559;
+  Object i0560, i0561, i0562, i0563, i0564, i0565, i0566, i0567, i0568, i0569;
+  Object i0570, i0571, i0572, i0573, i0574, i0575, i0576, i0577, i0578, i0579;
+  Object i0580, i0581, i0582, i0583, i0584, i0585, i0586, i0587, i0588, i0589;
+  Object i0590, i0591, i0592, i0593, i0594, i0595, i0596, i0597, i0598, i0599;
+
+  Object i0600, i0601, i0602, i0603, i0604, i0605, i0606, i0607, i0608, i0609;
+  Object i0610, i0611, i0612, i0613, i0614, i0615, i0616, i0617, i0618, i0619;
+  Object i0620, i0621, i0622, i0623, i0624, i0625, i0626, i0627, i0628, i0629;
+  Object i0630, i0631, i0632, i0633, i0634, i0635, i0636, i0637, i0638, i0639;
+  Object i0640, i0641, i0642, i0643, i0644, i0645, i0646, i0647, i0648, i0649;
+  Object i0650, i0651, i0652, i0653, i0654, i0655, i0656, i0657, i0658, i0659;
+  Object i0660, i0661, i0662, i0663, i0664, i0665, i0666, i0667, i0668, i0669;
+  Object i0670, i0671, i0672, i0673, i0674, i0675, i0676, i0677, i0678, i0679;
+  Object i0680, i0681, i0682, i0683, i0684, i0685, i0686, i0687, i0688, i0689;
+  Object i0690, i0691, i0692, i0693, i0694, i0695, i0696, i0697, i0698, i0699;
+
+  Object i0700, i0701, i0702, i0703, i0704, i0705, i0706, i0707, i0708, i0709;
+  Object i0710, i0711, i0712, i0713, i0714, i0715, i0716, i0717, i0718, i0719;
+  Object i0720, i0721, i0722, i0723, i0724, i0725, i0726, i0727, i0728, i0729;
+  Object i0730, i0731, i0732, i0733, i0734, i0735, i0736, i0737, i0738, i0739;
+  Object i0740, i0741, i0742, i0743, i0744, i0745, i0746, i0747, i0748, i0749;
+  Object i0750, i0751, i0752, i0753, i0754, i0755, i0756, i0757, i0758, i0759;
+  Object i0760, i0761, i0762, i0763, i0764, i0765, i0766, i0767, i0768, i0769;
+  Object i0770, i0771, i0772, i0773, i0774, i0775, i0776, i0777, i0778, i0779;
+  Object i0780, i0781, i0782, i0783, i0784, i0785, i0786, i0787, i0788, i0789;
+  Object i0790, i0791, i0792, i0793, i0794, i0795, i0796, i0797, i0798, i0799;
+
+  Object i0800, i0801, i0802, i0803, i0804, i0805, i0806, i0807, i0808, i0809;
+  Object i0810, i0811, i0812, i0813, i0814, i0815, i0816, i0817, i0818, i0819;
+  Object i0820, i0821, i0822, i0823, i0824, i0825, i0826, i0827, i0828, i0829;
+  Object i0830, i0831, i0832, i0833, i0834, i0835, i0836, i0837, i0838, i0839;
+  Object i0840, i0841, i0842, i0843, i0844, i0845, i0846, i0847, i0848, i0849;
+  Object i0850, i0851, i0852, i0853, i0854, i0855, i0856, i0857, i0858, i0859;
+  Object i0860, i0861, i0862, i0863, i0864, i0865, i0866, i0867, i0868, i0869;
+  Object i0870, i0871, i0872, i0873, i0874, i0875, i0876, i0877, i0878, i0879;
+  Object i0880, i0881, i0882, i0883, i0884, i0885, i0886, i0887, i0888, i0889;
+  Object i0890, i0891, i0892, i0893, i0894, i0895, i0896, i0897, i0898, i0899;
+
+  Object i0900, i0901, i0902, i0903, i0904, i0905, i0906, i0907, i0908, i0909;
+  Object i0910, i0911, i0912, i0913, i0914, i0915, i0916, i0917, i0918, i0919;
+  Object i0920, i0921, i0922, i0923, i0924, i0925, i0926, i0927, i0928, i0929;
+  Object i0930, i0931, i0932, i0933, i0934, i0935, i0936, i0937, i0938, i0939;
+  Object i0940, i0941, i0942, i0943, i0944, i0945, i0946, i0947, i0948, i0949;
+  Object i0950, i0951, i0952, i0953, i0954, i0955, i0956, i0957, i0958, i0959;
+  Object i0960, i0961, i0962, i0963, i0964, i0965, i0966, i0967, i0968, i0969;
+  Object i0970, i0971, i0972, i0973, i0974, i0975, i0976, i0977, i0978, i0979;
+  Object i0980, i0981, i0982, i0983, i0984, i0985, i0986, i0987, i0988, i0989;
+  Object i0990, i0991, i0992, i0993, i0994, i0995, i0996, i0997, i0998, i0999;
+
+  Object i1000, i1001, i1002, i1003, i1004, i1005, i1006, i1007, i1008, i1009;
+  Object i1010, i1011, i1012, i1013, i1014, i1015, i1016, i1017, i1018, i1019;
+  Object i1020, i1021, i1022, i1023, i1024, i1025, i1026, i1027, i1028, i1029;
+  Object i1030, i1031, i1032, i1033, i1034, i1035, i1036, i1037, i1038, i1039;
+  Object i1040, i1041, i1042, i1043, i1044, i1045, i1046, i1047, i1048, i1049;
+  Object i1050, i1051, i1052, i1053, i1054, i1055, i1056, i1057, i1058, i1059;
+  Object i1060, i1061, i1062, i1063, i1064, i1065, i1066, i1067, i1068, i1069;
+  Object i1070, i1071, i1072, i1073, i1074, i1075, i1076, i1077, i1078, i1079;
+  Object i1080, i1081, i1082, i1083, i1084, i1085, i1086, i1087, i1088, i1089;
+  Object i1090, i1091, i1092, i1093, i1094, i1095, i1096, i1097, i1098, i1099;
+
+  volatile Object volatileObjectField;
+  volatile int volatileIntField;
+  volatile long volatileWideField;
+
+  Object objectField;
+  int intField;
+  long wideField;
+
+  volatile Object putVolatileObjectField;
+  volatile int putVolatileIntField;
+  volatile long putVolatileWideField;
+
+  Object putObjectField;
+  int putIntField;
+  long putWideField;
+
+  static void check(NullPointerException npe, int firstLine) {
+    StackTraceElement[] trace = npe.getStackTrace();
+    checkElement(trace[0], "Main", "test", "Main.java", firstLine);
+    checkElement(trace[1], "Main", "main", "Main.java", 179);
+  }
+
+  static void checkElement(StackTraceElement element,
+                                  String declaringClass, String methodName,
+                                  String fileName, int lineNumber) {
+    assertEquals(declaringClass, element.getClassName());
+    assertEquals(methodName, element.getMethodName());
+    assertEquals(fileName, element.getFileName());
+    assertEquals(lineNumber, element.getLineNumber());
+  }
+
+  static void assertEquals(Object expected, Object actual) {
+    if (!expected.equals(actual)) {
+      String msg = "Expected \"" + expected + "\" but got \"" + actual + "\"";
+      throw new AssertionError(msg);
+    }
+  }
+
+  public static void main(String[] args) {
+    test();
+  }
+
+  public static void test() {
+    NullPointerException npe = null;
+    int thisLine = 184;
+
+    // We do each kind of test twice, to both test the fast path and the slow path
+    // of nterp.
+
+    try {
+      System.out.println($noinline$getNull().objectField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 6);
+
+    try {
+      System.out.println($noinline$getNull().objectField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      System.out.println($noinline$getNull().intField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      System.out.println($noinline$getNull().intField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      System.out.println($noinline$getNull().wideField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      System.out.println($noinline$getNull().wideField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      System.out.println($noinline$getNull().volatileObjectField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      System.out.println($noinline$getNull().volatileObjectField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      System.out.println($noinline$getNull().volatileIntField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      System.out.println($noinline$getNull().volatileIntField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      System.out.println($noinline$getNull().volatileWideField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      System.out.println($noinline$getNull().volatileWideField);
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putObjectField = null;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putObjectField = null;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putIntField = 42;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putIntField = 42;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putWideField = 42L;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putWideField = 42L;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putVolatileObjectField = null;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putVolatileObjectField = null;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putVolatileIntField = 42;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putVolatileIntField = 42;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putVolatileWideField = 42L;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+
+    try {
+      $noinline$getNull().putVolatileWideField = 42L;
+    } catch (NullPointerException e) {
+      npe = e;
+    }
+    check(npe, thisLine += 7);
+  }
+
+  public static Main $noinline$getNull() {
+    return null;
+  }
+}
diff --git a/test/815-invokeinterface-default/Android.bp b/test/815-invokeinterface-default/Android.bp
new file mode 100644
index 0000000..9981b02
--- /dev/null
+++ b/test/815-invokeinterface-default/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `815-invokeinterface-default`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-815-invokeinterface-default",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-815-invokeinterface-default-expected-stdout",
+        ":art-run-test-815-invokeinterface-default-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-815-invokeinterface-default-expected-stdout",
+    out: ["art-run-test-815-invokeinterface-default-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-815-invokeinterface-default-expected-stderr",
+    out: ["art-run-test-815-invokeinterface-default-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/516-dead-move-result/expected.txt b/test/815-invokeinterface-default/expected-stderr.txt
similarity index 100%
copy from test/516-dead-move-result/expected.txt
copy to test/815-invokeinterface-default/expected-stderr.txt
diff --git a/test/516-dead-move-result/expected.txt b/test/815-invokeinterface-default/expected-stdout.txt
similarity index 100%
copy from test/516-dead-move-result/expected.txt
copy to test/815-invokeinterface-default/expected-stdout.txt
diff --git a/test/815-invokeinterface-default/info.txt b/test/815-invokeinterface-default/info.txt
new file mode 100644
index 0000000..7d6c696
--- /dev/null
+++ b/test/815-invokeinterface-default/info.txt
@@ -0,0 +1,2 @@
+Regression test for the compiler where we used to pass a copied method as hidden
+argument for invokeinterface, which isn't supported.
diff --git a/test/815-invokeinterface-default/src/Main.java b/test/815-invokeinterface-default/src/Main.java
new file mode 100644
index 0000000..db3612b
--- /dev/null
+++ b/test/815-invokeinterface-default/src/Main.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2021 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.Method;
+
+// An interface with enough methods to trigger a conflict.
+interface Itf {
+  public void method0a();
+  public void method0b();
+  public void method0c();
+  public void method0d();
+  public void method0e();
+  public void method0f();
+  public void method0g();
+  public void method0h();
+  public void method0i();
+  public void method0j();
+  public void method0k();
+  public void method0l();
+  public void method0m();
+  public void method0n();
+  public void method0o();
+  public void method0p();
+  public void method0q();
+  public void method0r();
+  public void method0s();
+  public void method0t();
+  public void method0u();
+  public void method0v();
+  public void method0w();
+  public void method0x();
+  public void method0y();
+  public void method0z();
+  public void method1a();
+  public void method1b();
+  public void method1c();
+  public void method1d();
+  public void method1e();
+  public void method1f();
+  public void method1g();
+  public void method1h();
+  public void method1i();
+  public void method1j();
+  public void method1k();
+  public void method1l();
+  public void method1m();
+  public void method1n();
+  public void method1o();
+  public void method1p();
+  public void method1q();
+  public void method1r();
+  public void method1s();
+  public void method1t();
+  public void method1u();
+  public void method1v();
+  public void method1w();
+  public void method1x();
+  public void method1y();
+  public void method1z();
+  public void method2a();
+  public void method2b();
+  public void method2c();
+  public void method2d();
+  public void method2e();
+  public void method2f();
+  public void method2g();
+  public void method2h();
+  public void method2i();
+  public void method2j();
+  public void method2k();
+  public void method2l();
+  public void method2m();
+  public void method2n();
+  public void method2o();
+  public void method2p();
+  public void method2q();
+  public void method2r();
+  public void method2s();
+  public void method2t();
+  public void method2u();
+  public void method2v();
+  public void method2w();
+  public void method2x();
+  public void method2y();
+  public void method2z();
+
+  public default void $noinline$defaultRecursiveMethod(boolean callRecursive) {
+    if (callRecursive) {
+      $noinline$defaultRecursiveMethod(false);
+    }
+  }
+}
+
+public class Main implements Itf {
+  public static void main(String[] args) throws Exception {
+    Main main = new Main();
+    main.$noinline$defaultRecursiveMethod(true);
+  }
+
+  public void method0a() {}
+  public void method0b() {}
+  public void method0c() {}
+  public void method0d() {}
+  public void method0e() {}
+  public void method0f() {}
+  public void method0g() {}
+  public void method0h() {}
+  public void method0i() {}
+  public void method0j() {}
+  public void method0k() {}
+  public void method0l() {}
+  public void method0m() {}
+  public void method0n() {}
+  public void method0o() {}
+  public void method0p() {}
+  public void method0q() {}
+  public void method0r() {}
+  public void method0s() {}
+  public void method0t() {}
+  public void method0u() {}
+  public void method0v() {}
+  public void method0w() {}
+  public void method0x() {}
+  public void method0y() {}
+  public void method0z() {}
+  public void method1a() {}
+  public void method1b() {}
+  public void method1c() {}
+  public void method1d() {}
+  public void method1e() {}
+  public void method1f() {}
+  public void method1g() {}
+  public void method1h() {}
+  public void method1i() {}
+  public void method1j() {}
+  public void method1k() {}
+  public void method1l() {}
+  public void method1m() {}
+  public void method1n() {}
+  public void method1o() {}
+  public void method1p() {}
+  public void method1q() {}
+  public void method1r() {}
+  public void method1s() {}
+  public void method1t() {}
+  public void method1u() {}
+  public void method1v() {}
+  public void method1w() {}
+  public void method1x() {}
+  public void method1y() {}
+  public void method1z() {}
+  public void method2a() {}
+  public void method2b() {}
+  public void method2c() {}
+  public void method2d() {}
+  public void method2e() {}
+  public void method2f() {}
+  public void method2g() {}
+  public void method2h() {}
+  public void method2i() {}
+  public void method2j() {}
+  public void method2k() {}
+  public void method2l() {}
+  public void method2m() {}
+  public void method2n() {}
+  public void method2o() {}
+  public void method2p() {}
+  public void method2q() {}
+  public void method2r() {}
+  public void method2s() {}
+  public void method2t() {}
+  public void method2u() {}
+  public void method2v() {}
+  public void method2w() {}
+  public void method2x() {}
+  public void method2y() {}
+  public void method2z() {}
+}
diff --git a/test/412-new-array/expected.txt b/test/816-illegal-new-array/expected-stderr.txt
similarity index 100%
copy from test/412-new-array/expected.txt
copy to test/816-illegal-new-array/expected-stderr.txt
diff --git a/test/412-new-array/expected.txt b/test/816-illegal-new-array/expected-stdout.txt
similarity index 100%
copy from test/412-new-array/expected.txt
copy to test/816-illegal-new-array/expected-stdout.txt
diff --git a/test/816-illegal-new-array/info.txt b/test/816-illegal-new-array/info.txt
new file mode 100644
index 0000000..b5eaf3e
--- /dev/null
+++ b/test/816-illegal-new-array/info.txt
@@ -0,0 +1,2 @@
+Regression test for mterp which used to not do access checks on array
+allocation opcodes.
diff --git a/test/816-illegal-new-array/smali/TestCase.smali b/test/816-illegal-new-array/smali/TestCase.smali
new file mode 100644
index 0000000..e0dbbf3
--- /dev/null
+++ b/test/816-illegal-new-array/smali/TestCase.smali
@@ -0,0 +1,47 @@
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class  public LTestCase;
+.super  Ljava/lang/Object;
+
+
+.method public constructor <init>()V
+.registers 1
+    invoke-direct {v0}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method
+
+.method public static filledNewArray()[Ljava/lang/Object;
+.registers 1
+    const v0, 0
+    filled-new-array {v0}, [Lp/Foo;
+    move-result-object v0
+    return-object v0
+.end method
+
+.method public static filledNewArrayRange()[Ljava/lang/Object;
+.registers 2
+    const v0, 0
+    const v1, 0
+    filled-new-array/range {v0..v1}, [Lp/Foo;
+    move-result-object v0
+    return-object v0
+.end method
+
+.method public static newArray()V
+.registers 1
+    const v0, 0
+    new-array v0, v0, [Lp/Foo;
+    return-void
+.end method
diff --git a/test/816-illegal-new-array/src/Main.java b/test/816-illegal-new-array/src/Main.java
new file mode 100644
index 0000000..2d48c12
--- /dev/null
+++ b/test/816-illegal-new-array/src/Main.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 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.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class Main {
+
+  public static void main(String[] args) throws Exception {
+    Class<?> c = Class.forName("TestCase");
+    Method m = c.getMethod("filledNewArray");
+    try {
+      m.invoke(null);
+      throw new Error("Expected IllegalAccessError");
+    } catch (InvocationTargetException e) {
+      if (!(e.getCause() instanceof IllegalAccessError)) {
+        throw new Error("Expected IllegalAccessError, got " + e.getCause());
+      }
+    }
+
+    m = c.getMethod("filledNewArrayRange");
+    try {
+      m.invoke(null);
+      throw new Error("Expected IllegalAccessError");
+    } catch (InvocationTargetException e) {
+      if (!(e.getCause() instanceof IllegalAccessError)) {
+        throw new Error("Expected IllegalAccessError, got " + e.getCause());
+      }
+    }
+
+    m = c.getMethod("newArray");
+    try {
+      m.invoke(null);
+      throw new Error("Expected IllegalAccessError");
+    } catch (InvocationTargetException e) {
+      if (!(e.getCause() instanceof IllegalAccessError)) {
+        throw new Error("Expected IllegalAccessError, got " + e.getCause());
+      }
+    }
+  }
+}
+
diff --git a/test/816-illegal-new-array/src/p/Foo.java b/test/816-illegal-new-array/src/p/Foo.java
new file mode 100644
index 0000000..8d018e0
--- /dev/null
+++ b/test/816-illegal-new-array/src/p/Foo.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package p;
+
+class Foo {
+}
diff --git a/test/817-hiddenapi/build b/test/817-hiddenapi/build
new file mode 100644
index 0000000..330a6de
--- /dev/null
+++ b/test/817-hiddenapi/build
@@ -0,0 +1,38 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+set -e
+
+# Build the jars twice. First with applying hiddenapi, creating a boot jar, then
+# a second time without to create a normal jar. We need to do this because we
+# want to load the jar once as an app module and once as a member of the boot
+# class path. The DexFileVerifier would fail on the former as it does not allow
+# hidden API access flags in dex files. DexFileVerifier is not invoked on boot
+# class path dex files, so the boot jar loads fine in the latter case.
+
+export USE_HIDDENAPI=true
+./default-build "$@"
+
+# Move the jar file into the resource folder to be bundled with the test.
+mkdir res
+mv ${TEST_NAME}.jar res/boot.jar
+
+# Clear all intermediate files otherwise default-build would either skip
+# compilation or fail rebuilding.
+rm -rf classes*
+
+export USE_HIDDENAPI=false
+./default-build "$@"
diff --git a/test/817-hiddenapi/check b/test/817-hiddenapi/check
new file mode 100755
index 0000000..8c21ab4
--- /dev/null
+++ b/test/817-hiddenapi/check
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 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.
+
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
+# On gcstress configurations, an extra "JNI_OnUnload called" line may
+# be emitted. If so, remove it.
+sed -e '${/^JNI_OnUnload called$/d;}' "$2" > "$2.tmp"
+
+./default-check "$1" "$2.tmp" "$3" "$4"
diff --git a/test/674-hiddenapi/expected.txt b/test/817-hiddenapi/expected-stderr.txt
similarity index 100%
copy from test/674-hiddenapi/expected.txt
copy to test/817-hiddenapi/expected-stderr.txt
diff --git a/test/817-hiddenapi/expected-stdout.txt b/test/817-hiddenapi/expected-stdout.txt
new file mode 100644
index 0000000..8db7853
--- /dev/null
+++ b/test/817-hiddenapi/expected-stdout.txt
@@ -0,0 +1,2 @@
+JNI_OnLoad called
+JNI_OnLoad called
diff --git a/test/817-hiddenapi/hiddenapi-flags.csv b/test/817-hiddenapi/hiddenapi-flags.csv
new file mode 100644
index 0000000..ee0ede1
--- /dev/null
+++ b/test/817-hiddenapi/hiddenapi-flags.csv
@@ -0,0 +1,2 @@
+LNotInAbstractParent;->methodPublicSdkNotInAbstractParent()I,blocked
+LOtherInterface;->methodPublicSdkNotInAbstractParent()I,blocked
diff --git a/test/817-hiddenapi/info.txt b/test/817-hiddenapi/info.txt
new file mode 100644
index 0000000..01436aa
--- /dev/null
+++ b/test/817-hiddenapi/info.txt
@@ -0,0 +1,2 @@
+Test that even if hiddenapi bits are not propagated up the hierarchy, the
+runtime can handle a method being visible through different means.
diff --git a/test/817-hiddenapi/src-art/Main.java b/test/817-hiddenapi/src-art/Main.java
new file mode 100644
index 0000000..b83327e
--- /dev/null
+++ b/test/817-hiddenapi/src-art/Main.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 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 dalvik.system.PathClassLoader;
+import java.io.File;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.util.Arrays;
+
+public class Main {
+
+  public static void main(String[] args) throws Exception {
+    System.loadLibrary(args[0]);
+
+    // Enable hidden API checks in case they are disabled by default.
+    init();
+
+    // Put the classes with hiddenapi bits in the boot classpath.
+    appendToBootClassLoader(DEX_PARENT_BOOT, /* isCorePlatform */ false);
+
+    // Create a new class loader so the TestCase class sees the InheritAbstract classes in the boot
+    // classpath.
+    ClassLoader childLoader = new PathClassLoader(DEX_CHILD, Object.class.getClassLoader());
+    Class<?> cls = Class.forName("TestCase", true, childLoader);
+    Method m = cls.getDeclaredMethod("test");
+    m.invoke(null);
+
+    // Create a new native library which 'childLoader' can load.
+    String absoluteLibraryPath = getNativeLibFileName(args[0]);
+
+    // Do the test for JNI code.
+    m = cls.getDeclaredMethod("testNative", String.class);
+    m.invoke(null, createNativeLibCopy(absoluteLibraryPath));
+  }
+
+  // Tries to find the absolute path of the native library whose basename is 'arg'.
+  private static String getNativeLibFileName(String arg) throws Exception {
+    String libName = System.mapLibraryName(arg);
+    Method libPathsMethod = Runtime.class.getDeclaredMethod("getLibPaths");
+    libPathsMethod.setAccessible(true);
+    String[] libPaths = (String[]) libPathsMethod.invoke(Runtime.getRuntime());
+    String nativeLibFileName = null;
+    for (String p : libPaths) {
+      String candidate = p + libName;
+      if (new File(candidate).exists()) {
+        nativeLibFileName = candidate;
+        break;
+      }
+    }
+    if (nativeLibFileName == null) {
+      throw new IllegalStateException("Didn't find " + libName + " in " +
+          Arrays.toString(libPaths));
+    }
+    return nativeLibFileName;
+  }
+
+  // Copy native library to a new file with a unique name so it does not
+  // conflict with other loaded instance of the same binary file.
+  private static String createNativeLibCopy(String nativeLibFileName) throws Exception {
+    String tempFileName = System.mapLibraryName("hiddenapitest");
+    File tempFile = new File(System.getenv("DEX_LOCATION"), tempFileName);
+    Files.copy(new File(nativeLibFileName).toPath(), tempFile.toPath());
+    return tempFile.getAbsolutePath();
+  }
+
+  private static final String DEX_PARENT_BOOT =
+      new File(new File(System.getenv("DEX_LOCATION"), "res"), "boot.jar").getAbsolutePath();
+  private static final String DEX_CHILD =
+      new File(System.getenv("DEX_LOCATION"), "817-hiddenapi-ex.jar").getAbsolutePath();
+
+  private static native int appendToBootClassLoader(String dexPath, boolean isCorePlatform);
+  private static native void init();
+}
diff --git a/test/817-hiddenapi/src-ex/TestCase.java b/test/817-hiddenapi/src-ex/TestCase.java
new file mode 100644
index 0000000..ed3ecc8
--- /dev/null
+++ b/test/817-hiddenapi/src-ex/TestCase.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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 TestCase {
+
+  public static void test() {
+    // This call should be successful as the method is accessible through the interface.
+    int value = new InheritAbstract().methodPublicSdkNotInAbstractParent();
+    if (value != 42) {
+      throw new Error("Expected 42, got " + value);
+    }
+  }
+
+  public static void testNative(String library) {
+    System.load(library);
+    int value = testNativeInternal();
+    if (value != 42) {
+      throw new Error("Expected 42, got " + value);
+    }
+  }
+
+  public static native int testNativeInternal();
+}
diff --git a/test/817-hiddenapi/src/InheritAbstract.java b/test/817-hiddenapi/src/InheritAbstract.java
new file mode 100644
index 0000000..761e0bf
--- /dev/null
+++ b/test/817-hiddenapi/src/InheritAbstract.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2021 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 InheritAbstract extends NotInAbstractParent implements OtherInterface, NotInAbstractInterface {
+  // We don't define methodPublicSdkNotInAbstractParent in this class so the method resolution in
+  // ART first hits the blocked method in NotInAbstractParent.
+}
diff --git a/test/817-hiddenapi/src/NotInAbstractInterface.java b/test/817-hiddenapi/src/NotInAbstractInterface.java
new file mode 100644
index 0000000..1400e21
--- /dev/null
+++ b/test/817-hiddenapi/src/NotInAbstractInterface.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2021 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 interface NotInAbstractInterface {
+  // This method will be part of the public SDK.
+  int methodPublicSdkNotInAbstractParent();
+}
diff --git a/test/817-hiddenapi/src/NotInAbstractParent.java b/test/817-hiddenapi/src/NotInAbstractParent.java
new file mode 100644
index 0000000..464cffd
--- /dev/null
+++ b/test/817-hiddenapi/src/NotInAbstractParent.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 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 abstract class NotInAbstractParent {
+  // This method will be in the blocklist.
+  public int methodPublicSdkNotInAbstractParent() {
+    return 42;
+  }
+}
diff --git a/test/817-hiddenapi/src/OtherInterface.java b/test/817-hiddenapi/src/OtherInterface.java
new file mode 100644
index 0000000..fd9c87e
--- /dev/null
+++ b/test/817-hiddenapi/src/OtherInterface.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+interface OtherInterface {
+  // This method will not be part of the public SDK.
+  int methodPublicSdkNotInAbstractParent();
+}
diff --git a/test/817-hiddenapi/test_native.cc b/test/817-hiddenapi/test_native.cc
new file mode 100644
index 0000000..1c4dd8e
--- /dev/null
+++ b/test/817-hiddenapi/test_native.cc
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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 <android-base/logging.h>
+
+namespace art {
+
+extern "C" JNIEXPORT jint JNICALL Java_TestCase_testNativeInternal(JNIEnv* env,
+                                                                   jclass) {
+  jclass cls = env->FindClass("InheritAbstract");
+  CHECK(cls != nullptr);
+  jmethodID constructor = env->GetMethodID(cls, "<init>", "()V");
+  CHECK(constructor != nullptr);
+  jmethodID method_id = env->GetMethodID(cls, "methodPublicSdkNotInAbstractParent", "()I");
+  if (method_id == nullptr) {
+    return -1;
+  }
+  jobject obj = env->NewObject(cls, constructor);
+  return env->CallIntMethod(obj, method_id);
+}
+
+}  // namespace art
diff --git a/test/818-clinit-nterp/Android.bp b/test/818-clinit-nterp/Android.bp
new file mode 100644
index 0000000..f168de3
--- /dev/null
+++ b/test/818-clinit-nterp/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `818-clinit-nterp`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-818-clinit-nterp",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-818-clinit-nterp-expected-stdout",
+        ":art-run-test-818-clinit-nterp-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-818-clinit-nterp-expected-stdout",
+    out: ["art-run-test-818-clinit-nterp-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-818-clinit-nterp-expected-stderr",
+    out: ["art-run-test-818-clinit-nterp-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/581-rtp/expected.txt b/test/818-clinit-nterp/expected-stderr.txt
similarity index 100%
copy from test/581-rtp/expected.txt
copy to test/818-clinit-nterp/expected-stderr.txt
diff --git a/test/581-rtp/expected.txt b/test/818-clinit-nterp/expected-stdout.txt
similarity index 100%
copy from test/581-rtp/expected.txt
copy to test/818-clinit-nterp/expected-stdout.txt
diff --git a/test/818-clinit-nterp/info.txt b/test/818-clinit-nterp/info.txt
new file mode 100644
index 0000000..7313189
--- /dev/null
+++ b/test/818-clinit-nterp/info.txt
@@ -0,0 +1,2 @@
+Regression test for image creation, which used to install the nterp trampoline
+on methods that required a clinit check.
diff --git a/test/818-clinit-nterp/profile b/test/818-clinit-nterp/profile
new file mode 100644
index 0000000..df4346e
--- /dev/null
+++ b/test/818-clinit-nterp/profile
@@ -0,0 +1,2 @@
+LMain;
+LClinit;
diff --git a/test/818-clinit-nterp/run b/test/818-clinit-nterp/run
new file mode 100644
index 0000000..52d2b5f
--- /dev/null
+++ b/test/818-clinit-nterp/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
diff --git a/test/818-clinit-nterp/src/Main.java b/test/818-clinit-nterp/src/Main.java
new file mode 100644
index 0000000..5342cec
--- /dev/null
+++ b/test/818-clinit-nterp/src/Main.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 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) {
+    Clinit.run();
+    if (!clinitDidRun) {
+      throw new Error("Expected Clinit.<clinit> to have run");
+    }
+  }
+  static boolean clinitDidRun = false;
+}
+
+class Clinit {
+  public static void run() {
+  }
+
+  static {
+    Main.clinitDidRun = true;
+  }
+}
diff --git a/test/202-thread-oome/expected.txt b/test/819-verification-runtime/expected-stderr.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/819-verification-runtime/expected-stderr.txt
diff --git a/test/202-thread-oome/expected.txt b/test/819-verification-runtime/expected-stdout.txt
similarity index 100%
copy from test/202-thread-oome/expected.txt
copy to test/819-verification-runtime/expected-stdout.txt
diff --git a/test/819-verification-runtime/info.txt b/test/819-verification-runtime/info.txt
new file mode 100644
index 0000000..bb641bb
--- /dev/null
+++ b/test/819-verification-runtime/info.txt
@@ -0,0 +1,2 @@
+Regression test for the verifier, where we need to keep the behavior of
+a known throwing instruction means the code following it is unreachable.
diff --git a/test/819-verification-runtime/smali/Main.smali b/test/819-verification-runtime/smali/Main.smali
new file mode 100644
index 0000000..623cfa3
--- /dev/null
+++ b/test/819-verification-runtime/smali/Main.smali
@@ -0,0 +1,40 @@
+# Copyright 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LMain;
+
+.super Ljava/lang/Object;
+
+.method public static main([Ljava/lang/String;)V
+  .registers 1
+  invoke-static {}, LMain;->softFail()I
+  return-void
+.end method
+
+.method public static softFail()I
+  .registers 1
+  sget v0, LMain;->test:I
+  if-eqz v0, :Lzero
+  # BecausenonExistentMethod does not exist, the verifier will
+  # consider this instructions as always throwing, and will not
+  # look at the return-void below.
+  invoke-static {}, LMain;->nonExistentMethod()V
+  # Normally, this should hard-fail the verification, but it is
+  # skipped due to the throwing instruction above.
+  return-void
+:Lzero
+  return v0
+.end method
+
+.field public static test:I
diff --git a/test/801-VoidCheckCast/expected.txt b/test/820-vdex-multidex/expected-stderr.txt
similarity index 100%
copy from test/801-VoidCheckCast/expected.txt
copy to test/820-vdex-multidex/expected-stderr.txt
diff --git a/test/820-vdex-multidex/expected-stdout.txt b/test/820-vdex-multidex/expected-stdout.txt
new file mode 100644
index 0000000..e965047
--- /dev/null
+++ b/test/820-vdex-multidex/expected-stdout.txt
@@ -0,0 +1 @@
+Hello
diff --git a/test/820-vdex-multidex/info.txt b/test/820-vdex-multidex/info.txt
new file mode 100644
index 0000000..f6b87ea
--- /dev/null
+++ b/test/820-vdex-multidex/info.txt
@@ -0,0 +1 @@
+Test that vdex logic works with multidex.
diff --git a/test/820-vdex-multidex/run b/test/820-vdex-multidex/run
new file mode 100644
index 0000000..3f6dc3c
--- /dev/null
+++ b/test/820-vdex-multidex/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 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} -Xcompiler-option --compiler-filter=verify --vdex "${@}"
diff --git a/test/820-vdex-multidex/src-multidex/Foo.java b/test/820-vdex-multidex/src-multidex/Foo.java
new file mode 100644
index 0000000..6d18efb
--- /dev/null
+++ b/test/820-vdex-multidex/src-multidex/Foo.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2021 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 Foo {
+}
diff --git a/test/820-vdex-multidex/src/Main.java b/test/820-vdex-multidex/src/Main.java
new file mode 100644
index 0000000..164e784
--- /dev/null
+++ b/test/820-vdex-multidex/src/Main.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 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.out.println("Hello");
+  }
+}
+
diff --git a/test/821-madvise-willneed/Android.bp b/test/821-madvise-willneed/Android.bp
new file mode 100644
index 0000000..86e883c
--- /dev/null
+++ b/test/821-madvise-willneed/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `821-madvise-willneed`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-821-madvise-willneed",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-821-madvise-willneed-expected-stdout",
+        ":art-run-test-821-madvise-willneed-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-821-madvise-willneed-expected-stdout",
+    out: ["art-run-test-821-madvise-willneed-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-821-madvise-willneed-expected-stderr",
+    out: ["art-run-test-821-madvise-willneed-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/168-vmstack-annotated/expected.txt b/test/821-madvise-willneed/expected-stderr.txt
similarity index 100%
copy from test/168-vmstack-annotated/expected.txt
copy to test/821-madvise-willneed/expected-stderr.txt
diff --git a/test/001-HelloWorld/expected.txt b/test/821-madvise-willneed/expected-stdout.txt
similarity index 100%
copy from test/001-HelloWorld/expected.txt
copy to test/821-madvise-willneed/expected-stdout.txt
diff --git a/test/821-madvise-willneed/info.txt b/test/821-madvise-willneed/info.txt
new file mode 100644
index 0000000..cea36a0
--- /dev/null
+++ b/test/821-madvise-willneed/info.txt
@@ -0,0 +1 @@
+Verify that passing madvise size limits argument to ART does not cause a crash
diff --git a/test/821-madvise-willneed/run b/test/821-madvise-willneed/run
new file mode 100644
index 0000000..2c3917f
--- /dev/null
+++ b/test/821-madvise-willneed/run
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 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.i
+
+# Load and run HelloWorld after madvising odex, vdex, art files to 100MB size
+# limit
+exec ${RUN} "${@}" --runtime-option -XMadviseWillNeedVdexFileSize:104857600 \
+  --runtime-option -XMadviseWillNeedOdexFileSize:104857600 \
+  --runtime-option -XMadviseWillNeedArtFileSize:104857600
diff --git a/test/821-madvise-willneed/src/Main.java b/test/821-madvise-willneed/src/Main.java
new file mode 100644
index 0000000..cc8c521
--- /dev/null
+++ b/test/821-madvise-willneed/src/Main.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 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.out.println("Hello, world!");
+  }
+}
diff --git a/test/821-many-args/Android.bp b/test/821-many-args/Android.bp
new file mode 100644
index 0000000..75f9798
--- /dev/null
+++ b/test/821-many-args/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `821-many-args`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-821-many-args",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-821-many-args-expected-stdout",
+        ":art-run-test-821-many-args-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-821-many-args-expected-stdout",
+    out: ["art-run-test-821-many-args-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-821-many-args-expected-stderr",
+    out: ["art-run-test-821-many-args-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/821-many-args/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/821-many-args/expected-stderr.txt
diff --git a/test/457-regs/expected.txt b/test/821-many-args/expected-stdout.txt
similarity index 100%
copy from test/457-regs/expected.txt
copy to test/821-many-args/expected-stdout.txt
diff --git a/test/821-many-args/info.txt b/test/821-many-args/info.txt
new file mode 100644
index 0000000..8d150aa
--- /dev/null
+++ b/test/821-many-args/info.txt
@@ -0,0 +1 @@
+Test for doing nterp -> compiled code transitions in the fast path.
diff --git a/test/821-many-args/src/Main.java b/test/821-many-args/src/Main.java
new file mode 100644
index 0000000..8818b90
--- /dev/null
+++ b/test/821-many-args/src/Main.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2021 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]);
+    ensureJitCompiled(Main.class, "staticMethod");
+    int a = staticMethod(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    assertEquals(42, a);
+
+    ensureJitCompiled(Main.class, "staticMethodNonRange");
+    a = staticMethodNonRange(1, 2, 3, 4, 5);
+    assertEquals(42, a);
+
+    staticMain = new Main();
+    ensureJitCompiled(Main.class, "instanceMethod");
+    a = staticMain.instanceMethod(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    assertEquals(42, a);
+
+    ensureJitCompiled(Main.class, "instanceMethodNonRange");
+    a = staticMain.instanceMethodNonRange(1, 2, 3, 4);
+    assertEquals(42, a);
+  }
+
+  public static int staticMethod(
+      int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
+    assertEquals(10, j);
+    assertEquals(9, i);
+    assertEquals(8, h);
+    assertEquals(7, g);
+    assertEquals(6, f);
+    assertEquals(5, e);
+    assertEquals(4, d);
+    assertEquals(3, c);
+    assertEquals(2, b);
+    assertEquals(1, a);
+    return 42;
+  }
+
+  public int instanceMethod(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
+    assertEquals(10, j);
+    assertEquals(9, i);
+    assertEquals(8, h);
+    assertEquals(7, g);
+    assertEquals(6, f);
+    assertEquals(5, e);
+    assertEquals(4, d);
+    assertEquals(3, c);
+    assertEquals(2, b);
+    assertEquals(1, a);
+    assertEquals(staticMain, this);
+    return 42;
+  }
+
+  public static int staticMethodNonRange(int a, int b, int c, int d, int e) {
+    assertEquals(5, e);
+    assertEquals(4, d);
+    assertEquals(3, c);
+    assertEquals(2, b);
+    assertEquals(1, a);
+    return 42;
+  }
+
+  public int instanceMethodNonRange(int a, int b, int c, int d) {
+    assertEquals(4, d);
+    assertEquals(3, c);
+    assertEquals(2, b);
+    assertEquals(1, a);
+    assertEquals(staticMain, this);
+    return 42;
+  }
+
+  static Main staticMain;
+
+  public static void assertEquals(int expected, int actual) {
+    if (expected != actual) {
+      throw new Error("Expected " + expected + ", got " + actual);
+    }
+  }
+
+  public static void assertEquals(Object expected, Object actual) {
+    if (expected != actual) {
+      throw new Error("Expected " + expected + ", got " + actual);
+    }
+  }
+
+  public static native void ensureJitCompiled(Class<?> cls, String methodName);
+}
diff --git a/test/822-hiddenapi-future/build b/test/822-hiddenapi-future/build
new file mode 100644
index 0000000..02ce549
--- /dev/null
+++ b/test/822-hiddenapi-future/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2021 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.
+
+USE_HIDDENAPI=true ./default-build "$@"
diff --git a/test/082-inline-execute/expected.txt b/test/822-hiddenapi-future/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/822-hiddenapi-future/expected-stderr.txt
diff --git a/test/612-jit-dex-cache/expected.txt b/test/822-hiddenapi-future/expected-stdout.txt
similarity index 100%
copy from test/612-jit-dex-cache/expected.txt
copy to test/822-hiddenapi-future/expected-stdout.txt
diff --git a/test/822-hiddenapi-future/hiddenapi-flags.csv b/test/822-hiddenapi-future/hiddenapi-flags.csv
new file mode 100644
index 0000000..4f95ec0
--- /dev/null
+++ b/test/822-hiddenapi-future/hiddenapi-flags.csv
@@ -0,0 +1 @@
+LMyClass;->futureHidden()I,max-target-future
diff --git a/test/822-hiddenapi-future/info.txt b/test/822-hiddenapi-future/info.txt
new file mode 100644
index 0000000..6360d9b
--- /dev/null
+++ b/test/822-hiddenapi-future/info.txt
@@ -0,0 +1 @@
+Tests that future hiddenapi flags do not crash the runtime.
diff --git a/test/822-hiddenapi-future/src-ex/MyClass.java b/test/822-hiddenapi-future/src-ex/MyClass.java
new file mode 100644
index 0000000..4a9ec9c
--- /dev/null
+++ b/test/822-hiddenapi-future/src-ex/MyClass.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 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 MyClass {
+  public static int futureHidden() {
+    return 42;
+  }
+}
diff --git a/test/822-hiddenapi-future/src/Main.java b/test/822-hiddenapi-future/src/Main.java
new file mode 100644
index 0000000..f90a161
--- /dev/null
+++ b/test/822-hiddenapi-future/src/Main.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 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.io.File;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class Main {
+  public static void main(String[] args) throws Exception {
+    System.loadLibrary(args[0]);
+    init();
+    appendToBootClassLoader(DEX_EXTRA, /* isCorePlatform */ false);
+
+    Class<?> klass = Object.class.getClassLoader().loadClass("MyClass");
+    Method m = klass.getDeclaredMethod("futureHidden");
+    Integer result = (Integer) m.invoke(null);
+    if (result.intValue() != 42) {
+      throw new Error("Expected 42, got " + result.intValue());
+    }
+  }
+
+  private static final String DEX_EXTRA = new File(System.getenv("DEX_LOCATION"),
+      "822-hiddenapi-future-ex.jar").getAbsolutePath();
+
+  private static native void init();
+  private static native void appendToBootClassLoader(String dexPath, boolean isCorePlatform);
+}
diff --git a/test/535-deopt-and-inlining/expected.txt b/test/823-cha-inlining/expected-stderr.txt
similarity index 100%
copy from test/535-deopt-and-inlining/expected.txt
copy to test/823-cha-inlining/expected-stderr.txt
diff --git a/test/566-polymorphic-inlining/expected.txt b/test/823-cha-inlining/expected-stdout.txt
similarity index 100%
copy from test/566-polymorphic-inlining/expected.txt
copy to test/823-cha-inlining/expected-stdout.txt
diff --git a/test/823-cha-inlining/info.txt b/test/823-cha-inlining/info.txt
new file mode 100644
index 0000000..312a2ef
--- /dev/null
+++ b/test/823-cha-inlining/info.txt
@@ -0,0 +1 @@
+Tests for the combination of CHA and default methods.
diff --git a/test/823-cha-inlining/src/Main.java b/test/823-cha-inlining/src/Main.java
new file mode 100644
index 0000000..c683e6b
--- /dev/null
+++ b/test/823-cha-inlining/src/Main.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+interface Itf {
+  // We make the methods below directly throw instead of using the $noinline$
+  // directive to get the inliner actually try to inline but decide not to.
+  // This will then make the compiler try to generate an HInvokeVirtual instead
+  // of an HInvokeInterface.
+
+  public default void m() throws Exception {
+    throw new Exception("Don't inline me");
+  }
+  public default void mConflict() throws Exception {
+    throw new Exception("Don't inline me");
+  }
+}
+
+// This is redefined in src2 with a mConflict method.
+interface Itf2 {
+}
+
+interface Itf3 extends Itf, Itf2 {
+}
+
+class Itf3Impl implements Itf3 {
+}
+
+interface Itf4 extends Itf, Itf2 {
+  public default void m() throws Exception {
+    throw new Exception("Don't inline me");
+  }
+}
+
+class Itf4Impl implements Itf4 {
+}
+
+
+public class Main implements Itf, Itf2 {
+
+  public static void main(String[] args) {
+    System.loadLibrary(args[0]);
+
+    // Execute enough time to populate inline caches.
+    for (int i = 0; i < 100000; ++i) {
+      try {
+        $noinline$doCallDefault();
+      } catch (Exception e) {
+        // Expected.
+      }
+    }
+    ensureJitCompiled(Main.class, "$noinline$doCallDefault");
+    try {
+      $noinline$doCallDefault();
+      throw new Error("Expected exception");
+    } catch (Exception e) {
+      // Expected.
+    }
+
+    ensureJitCompiled(Main.class, "$noinline$doCallDefaultConflict");
+    try {
+      $noinline$doCallDefaultConflict();
+      throw new Error("Expected IncompatibleClassChangeError");
+    } catch (Exception e) {
+      throw new Error("Unexpected exception");
+    } catch (IncompatibleClassChangeError e) {
+      // Expected.
+    }
+
+    // Execute enough time to populate inline caches.
+    for (int i = 0; i < 100000; ++i) {
+      try {
+        $noinline$doCallDefaultConflictItf3();
+      } catch (Throwable t) {
+        // Expected.
+      }
+    }
+    ensureJitCompiled(Main.class, "$noinline$doCallDefaultConflictItf3");
+    try {
+      $noinline$doCallDefaultConflictItf3();
+      throw new Error("Expected IncompatibleClassChangeError");
+    } catch (Exception e) {
+      throw new Error("Unexpected exception " + e);
+    } catch (IncompatibleClassChangeError e) {
+      // Expected.
+    }
+
+    ensureJitCompiled(Main.class, "$noinline$doCallDefaultConflictItf4");
+    try {
+      $noinline$doCallDefaultConflictItf4();
+      throw new Error("Expected IncompatibleClassChangeError");
+    } catch (Exception e) {
+      throw new Error("Unexpected exception");
+    } catch (IncompatibleClassChangeError e) {
+      // Expected.
+    }
+  }
+
+  public static void $noinline$doCallDefault() throws Exception {
+    itf.m();
+  }
+
+  public static void $noinline$doCallDefaultConflict() throws Exception {
+    itf.mConflict();
+  }
+
+  public static void $noinline$doCallDefaultConflictItf3() throws Exception {
+    itf3.mConflict();
+  }
+
+  public static void $noinline$doCallDefaultConflictItf4() throws Exception {
+    itf4.mConflict();
+  }
+
+  static Itf itf = new Main();
+  static Itf3 itf3 = new Itf3Impl();
+  static Itf4 itf4 = new Itf4Impl();
+
+  private static native void ensureJitCompiled(Class<?> cls, String methodName);
+}
diff --git a/test/823-cha-inlining/src2/Itf2.java b/test/823-cha-inlining/src2/Itf2.java
new file mode 100644
index 0000000..6b019c4
--- /dev/null
+++ b/test/823-cha-inlining/src2/Itf2.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+interface Itf2 {
+  public default void mConflict() throws Exception {
+    throw new Exception("Don't inline me");
+  }
+}
diff --git a/test/900-hello-plugin/Android.bp b/test/900-hello-plugin/Android.bp
new file mode 100644
index 0000000..1bae532
--- /dev/null
+++ b/test/900-hello-plugin/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `900-hello-plugin`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-900-hello-plugin",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-900-hello-plugin-expected-stdout",
+        ":art-run-test-900-hello-plugin-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-900-hello-plugin-expected-stdout",
+    out: ["art-run-test-900-hello-plugin-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-900-hello-plugin-expected-stderr",
+    out: ["art-run-test-900-hello-plugin-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/900-hello-plugin/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/900-hello-plugin/expected-stderr.txt
diff --git a/test/900-hello-plugin/expected.txt b/test/900-hello-plugin/expected-stdout.txt
similarity index 100%
rename from test/900-hello-plugin/expected.txt
rename to test/900-hello-plugin/expected-stdout.txt
diff --git a/test/901-hello-ti-agent/Android.bp b/test/901-hello-ti-agent/Android.bp
new file mode 100644
index 0000000..65e4454
--- /dev/null
+++ b/test/901-hello-ti-agent/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `901-hello-ti-agent`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-901-hello-ti-agent",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-901-hello-ti-agent-expected-stdout",
+        ":art-run-test-901-hello-ti-agent-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-901-hello-ti-agent-expected-stdout",
+    out: ["art-run-test-901-hello-ti-agent-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-901-hello-ti-agent-expected-stderr",
+    out: ["art-run-test-901-hello-ti-agent-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/436-shift-constant/expected.txt b/test/901-hello-ti-agent/expected-stderr.txt
similarity index 100%
copy from test/436-shift-constant/expected.txt
copy to test/901-hello-ti-agent/expected-stderr.txt
diff --git a/test/901-hello-ti-agent/expected.txt b/test/901-hello-ti-agent/expected-stdout.txt
similarity index 100%
rename from test/901-hello-ti-agent/expected.txt
rename to test/901-hello-ti-agent/expected-stdout.txt
diff --git a/test/902-hello-transformation/Android.bp b/test/902-hello-transformation/Android.bp
new file mode 100644
index 0000000..042e09e
--- /dev/null
+++ b/test/902-hello-transformation/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `902-hello-transformation`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-902-hello-transformation",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-902-hello-transformation-expected-stdout",
+        ":art-run-test-902-hello-transformation-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-902-hello-transformation-expected-stdout",
+    out: ["art-run-test-902-hello-transformation-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-902-hello-transformation-expected-stderr",
+    out: ["art-run-test-902-hello-transformation-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-fragmentation/expected.txt b/test/902-hello-transformation/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/902-hello-transformation/expected-stderr.txt
diff --git a/test/902-hello-transformation/expected.txt b/test/902-hello-transformation/expected-stdout.txt
similarity index 100%
rename from test/902-hello-transformation/expected.txt
rename to test/902-hello-transformation/expected-stdout.txt
diff --git a/test/903-hello-tagging/Android.bp b/test/903-hello-tagging/Android.bp
new file mode 100644
index 0000000..fe395dc
--- /dev/null
+++ b/test/903-hello-tagging/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `903-hello-tagging`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-903-hello-tagging",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-903-hello-tagging-expected-stdout",
+        ":art-run-test-903-hello-tagging-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-903-hello-tagging-expected-stdout",
+    out: ["art-run-test-903-hello-tagging-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-903-hello-tagging-expected-stderr",
+    out: ["art-run-test-903-hello-tagging-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/304-method-tracing/expected.txt b/test/903-hello-tagging/expected-stderr.txt
similarity index 100%
copy from test/304-method-tracing/expected.txt
copy to test/903-hello-tagging/expected-stderr.txt
diff --git a/test/903-hello-tagging/expected.txt b/test/903-hello-tagging/expected-stdout.txt
similarity index 100%
rename from test/903-hello-tagging/expected.txt
rename to test/903-hello-tagging/expected-stdout.txt
diff --git a/test/904-object-allocation/Android.bp b/test/904-object-allocation/Android.bp
new file mode 100644
index 0000000..54d2e45
--- /dev/null
+++ b/test/904-object-allocation/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `904-object-allocation`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-904-object-allocation",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-904-object-allocation-expected-stdout",
+        ":art-run-test-904-object-allocation-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-904-object-allocation-expected-stdout",
+    out: ["art-run-test-904-object-allocation-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-904-object-allocation-expected-stderr",
+    out: ["art-run-test-904-object-allocation-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-fragmentation/expected.txt b/test/904-object-allocation/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/904-object-allocation/expected-stderr.txt
diff --git a/test/904-object-allocation/expected.txt b/test/904-object-allocation/expected-stdout.txt
similarity index 100%
rename from test/904-object-allocation/expected.txt
rename to test/904-object-allocation/expected-stdout.txt
diff --git a/test/905-object-free/Android.bp b/test/905-object-free/Android.bp
new file mode 100644
index 0000000..798274f
--- /dev/null
+++ b/test/905-object-free/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `905-object-free`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-905-object-free",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-905-object-free-expected-stdout",
+        ":art-run-test-905-object-free-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-905-object-free-expected-stdout",
+    out: ["art-run-test-905-object-free-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-905-object-free-expected-stderr",
+    out: ["art-run-test-905-object-free-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/998-redefine-use-after-free/expected.txt b/test/905-object-free/expected-stderr.txt
similarity index 100%
copy from test/998-redefine-use-after-free/expected.txt
copy to test/905-object-free/expected-stderr.txt
diff --git a/test/905-object-free/expected.txt b/test/905-object-free/expected-stdout.txt
similarity index 100%
rename from test/905-object-free/expected.txt
rename to test/905-object-free/expected-stdout.txt
diff --git a/test/906-iterate-heap/Android.bp b/test/906-iterate-heap/Android.bp
new file mode 100644
index 0000000..d61ed65
--- /dev/null
+++ b/test/906-iterate-heap/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `906-iterate-heap`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-906-iterate-heap",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-906-iterate-heap-expected-stdout",
+        ":art-run-test-906-iterate-heap-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-906-iterate-heap-expected-stdout",
+    out: ["art-run-test-906-iterate-heap-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-906-iterate-heap-expected-stderr",
+    out: ["art-run-test-906-iterate-heap-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/581-rtp/expected.txt b/test/906-iterate-heap/expected-stderr.txt
similarity index 100%
copy from test/581-rtp/expected.txt
copy to test/906-iterate-heap/expected-stderr.txt
diff --git a/test/906-iterate-heap/expected.txt b/test/906-iterate-heap/expected-stdout.txt
similarity index 100%
rename from test/906-iterate-heap/expected.txt
rename to test/906-iterate-heap/expected-stdout.txt
diff --git a/test/906-iterate-heap/src/art/Test906.java b/test/906-iterate-heap/src/art/Test906.java
index b782c9b..c65934d 100644
--- a/test/906-iterate-heap/src/art/Test906.java
+++ b/test/906-iterate-heap/src/art/Test906.java
@@ -29,9 +29,15 @@
   // the middle of a GC we could incorrectly fail. This is expected to be incredibly rare so 10
   // retries should be more than sufficient.
   private static final int ITERATE_RETRIES = 10;
+  private static final class Foobar {}
+
   private static void testHeapCount() throws Exception {
     IllegalStateException lastThrow = new IllegalStateException(
         "Failed to get consistent counts after " + ITERATE_RETRIES + " retries");
+    Foobar[] foobars = new Foobar[123];
+    for (int i = 0; i < foobars.length; i++) {
+      foobars[i] = new Foobar();
+    }
     for (int i = 0; i < ITERATE_RETRIES; i++) {
       try {
         int all = iterateThroughHeapCount(0, null, Integer.MAX_VALUE);
@@ -41,6 +47,7 @@
             Integer.MAX_VALUE);
         int untaggedClass = iterateThroughHeapCount(HEAP_FILTER_OUT_CLASS_TAGGED, null,
             Integer.MAX_VALUE);
+        int filteredClass = iterateThroughHeapCount(0, Foobar.class, Integer.MAX_VALUE);
 
         if (all != tagged + untagged) {
           throw new IllegalStateException("Instances: " + all + " != " + tagged + " + " + untagged);
@@ -49,6 +56,10 @@
           throw new IllegalStateException("By class: " + all + " != " + taggedClass + " + " +
               untaggedClass);
         }
+        if (filteredClass != foobars.length) {
+          throw new IllegalStateException(
+              "Missed objects of foobar type. " + filteredClass + " != " + foobars.length);
+        }
         if (tagged != 6) {
           throw new IllegalStateException(tagged + " tagged objects");
         }
diff --git a/test/907-get-loaded-classes/Android.bp b/test/907-get-loaded-classes/Android.bp
new file mode 100644
index 0000000..614a30f
--- /dev/null
+++ b/test/907-get-loaded-classes/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `907-get-loaded-classes`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-907-get-loaded-classes",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-907-get-loaded-classes-expected-stdout",
+        ":art-run-test-907-get-loaded-classes-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-907-get-loaded-classes-expected-stdout",
+    out: ["art-run-test-907-get-loaded-classes-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-907-get-loaded-classes-expected-stderr",
+    out: ["art-run-test-907-get-loaded-classes-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/907-get-loaded-classes/expected.txt b/test/907-get-loaded-classes/expected-stderr.txt
similarity index 100%
rename from test/907-get-loaded-classes/expected.txt
rename to test/907-get-loaded-classes/expected-stderr.txt
diff --git a/test/907-get-loaded-classes/expected.txt b/test/907-get-loaded-classes/expected-stdout.txt
similarity index 100%
copy from test/907-get-loaded-classes/expected.txt
copy to test/907-get-loaded-classes/expected-stdout.txt
diff --git a/test/908-gc-start-finish/Android.bp b/test/908-gc-start-finish/Android.bp
new file mode 100644
index 0000000..7aa75ff
--- /dev/null
+++ b/test/908-gc-start-finish/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `908-gc-start-finish`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-908-gc-start-finish",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-908-gc-start-finish-expected-stdout",
+        ":art-run-test-908-gc-start-finish-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-908-gc-start-finish-expected-stdout",
+    out: ["art-run-test-908-gc-start-finish-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-908-gc-start-finish-expected-stderr",
+    out: ["art-run-test-908-gc-start-finish-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/411-optimizing-arith/expected.txt b/test/908-gc-start-finish/expected-stderr.txt
similarity index 100%
copy from test/411-optimizing-arith/expected.txt
copy to test/908-gc-start-finish/expected-stderr.txt
diff --git a/test/908-gc-start-finish/expected.txt b/test/908-gc-start-finish/expected-stdout.txt
similarity index 100%
rename from test/908-gc-start-finish/expected.txt
rename to test/908-gc-start-finish/expected-stdout.txt
diff --git a/test/528-long-hint/expected.txt b/test/909-attach-agent/expected-stderr.txt
similarity index 100%
copy from test/528-long-hint/expected.txt
copy to test/909-attach-agent/expected-stderr.txt
diff --git a/test/909-attach-agent/expected.txt b/test/909-attach-agent/expected-stdout.txt
similarity index 100%
rename from test/909-attach-agent/expected.txt
rename to test/909-attach-agent/expected-stdout.txt
diff --git a/test/909-attach-agent/run b/test/909-attach-agent/run
index add558e..71b1e1c 100755
--- a/test/909-attach-agent/run
+++ b/test/909-attach-agent/run
@@ -25,7 +25,7 @@
   # On interpreter we are fully capable of providing the full jvmti api so we
   # have a slightly different expected output.
   # TODO We should really be changing this in the 'check' script.
-  patch -s expected.txt <interpreter-expected.patch
+  patch -s expected-stdout.txt <interpreter-expected.patch
 fi
 
 # Provide additional runtime options when running on device.
diff --git a/test/910-methods/Android.bp b/test/910-methods/Android.bp
new file mode 100644
index 0000000..5832d12
--- /dev/null
+++ b/test/910-methods/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `910-methods`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-910-methods",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-910-methods-expected-stdout",
+        ":art-run-test-910-methods-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-910-methods-expected-stdout",
+    out: ["art-run-test-910-methods-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-910-methods-expected-stderr",
+    out: ["art-run-test-910-methods-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/406-fields/expected.txt b/test/910-methods/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/910-methods/expected-stderr.txt
diff --git a/test/910-methods/expected.txt b/test/910-methods/expected-stdout.txt
similarity index 100%
rename from test/910-methods/expected.txt
rename to test/910-methods/expected-stdout.txt
diff --git a/test/910-methods/src/art/Test910.java b/test/910-methods/src/art/Test910.java
index e1da277..4338448 100644
--- a/test/910-methods/src/art/Test910.java
+++ b/test/910-methods/src/art/Test910.java
@@ -33,7 +33,7 @@
 
     testMethod(getProxyClass(), "run");
 
-    // Find a synthetic method in the dummy inner class. Do not print the name. Javac and Jack
+    // Find a synthetic method in the placeholder inner class. Do not print the name. Javac and Jack
     // disagree on the naming of synthetic accessors.
     testMethod(findSyntheticMethod(), NestedSynthetic.class, false);
   }
@@ -106,11 +106,11 @@
 
   private static class NestedSynthetic {
     // Accessing this private field will create a synthetic accessor method;
-    private static String dummy;
+    private static String placeholder;
   }
 
-  private static void dummyAccess() {
-    System.out.println(NestedSynthetic.dummy);
+  private static void placeholderAccess() {
+    System.out.println(NestedSynthetic.placeholder);
   }
 
   private static Method findSyntheticMethod() throws Exception {
diff --git a/test/911-get-stack-trace/Android.bp b/test/911-get-stack-trace/Android.bp
new file mode 100644
index 0000000..c798eea
--- /dev/null
+++ b/test/911-get-stack-trace/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `911-get-stack-trace`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-911-get-stack-trace",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-911-get-stack-trace-expected-stdout",
+        ":art-run-test-911-get-stack-trace-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-911-get-stack-trace-expected-stdout",
+    out: ["art-run-test-911-get-stack-trace-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-911-get-stack-trace-expected-stderr",
+    out: ["art-run-test-911-get-stack-trace-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/423-invoke-interface/expected.txt b/test/911-get-stack-trace/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/911-get-stack-trace/expected-stderr.txt
diff --git a/test/911-get-stack-trace/expected-stdout.txt b/test/911-get-stack-trace/expected-stdout.txt
new file mode 100644
index 0000000..86be681
--- /dev/null
+++ b/test/911-get-stack-trace/expected-stdout.txt
@@ -0,0 +1,919 @@
+###################
+### Same thread ###
+###################
+From top
+---------
+ getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2
+ print (Ljava/lang/Thread;II)V 0 38
+ printOrWait (IILart/ControlData;)V 6 41
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ doTest ()V 31 25
+ run ()V 0 31
+---------
+ print (Ljava/lang/Thread;II)V 0 38
+ printOrWait (IILart/ControlData;)V 6 41
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ doTest ()V 35 26
+ run ()V 0 31
+---------
+ getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2
+ print (Ljava/lang/Thread;II)V 0 38
+ printOrWait (IILart/ControlData;)V 6 41
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+---------
+ printOrWait (IILart/ControlData;)V 6 41
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+---------
+ printOrWait (IILart/ControlData;)V 6 41
+From bottom
+---------
+ run ()V 0 31
+---------
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ doTest ()V 61 33
+ run ()V 0 31
+---------
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+################################
+### Other thread (suspended) ###
+################################
+From top
+---------
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 28
+---------
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 28
+---------
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+---------
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+---------
+ wait ()V 2 568
+From bottom
+---------
+ run ()V 4 28
+---------
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 28
+---------
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+
+###########################
+### Other thread (live) ###
+###########################
+From top
+---------
+ printOrWait (IILart/ControlData;)V 45 54
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 62
+---------
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 62
+---------
+ printOrWait (IILart/ControlData;)V 45 54
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+---------
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+From bottom
+---------
+ run ()V 4 62
+---------
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 62
+---------
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+
+################################
+### Other threads (suspended) ###
+################################
+---------
+AllTraces Thread 0
+
+---------
+AllTraces Thread 1
+
+---------
+AllTraces Thread 2
+
+---------
+AllTraces Thread 3
+
+---------
+AllTraces Thread 4
+
+---------
+AllTraces Thread 5
+
+---------
+AllTraces Thread 6
+
+---------
+AllTraces Thread 7
+
+---------
+AllTraces Thread 8
+
+---------
+AllTraces Thread 9
+
+---------
+FinalizerDaemon
+<not printed>
+---------
+FinalizerWatchdogDaemon
+<not printed>
+---------
+HeapTaskDaemon
+<not printed>
+---------
+ReferenceQueueDaemon
+<not printed>
+---------
+Signal Catcher
+
+---------
+Test911
+
+---------
+main
+<not printed>
+---------
+AllTraces Thread 0
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+AllTraces Thread 1
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+AllTraces Thread 2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+AllTraces Thread 3
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+AllTraces Thread 4
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+AllTraces Thread 5
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+AllTraces Thread 6
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+AllTraces Thread 7
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+AllTraces Thread 8
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+AllTraces Thread 9
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+FinalizerDaemon
+<not printed>
+---------
+FinalizerWatchdogDaemon
+<not printed>
+---------
+HeapTaskDaemon
+<not printed>
+---------
+ReferenceQueueDaemon
+<not printed>
+---------
+Signal Catcher
+
+---------
+Test911
+ getAllStackTraces (I)[[Ljava/lang/Object; -1 -2
+ printAll (I)V 0 75
+ doTest ()V 118 59
+ run ()V 28 44
+
+---------
+main
+<not printed>
+---------
+AllTraces Thread 0
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 47
+
+---------
+AllTraces Thread 1
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 47
+
+---------
+AllTraces Thread 2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 47
+
+---------
+AllTraces Thread 3
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 47
+
+---------
+AllTraces Thread 4
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 47
+
+---------
+AllTraces Thread 5
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 47
+
+---------
+AllTraces Thread 6
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 47
+
+---------
+AllTraces Thread 7
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 47
+
+---------
+AllTraces Thread 8
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 47
+
+---------
+AllTraces Thread 9
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 47
+
+---------
+FinalizerDaemon
+<not printed>
+---------
+FinalizerWatchdogDaemon
+<not printed>
+---------
+HeapTaskDaemon
+<not printed>
+---------
+ReferenceQueueDaemon
+<not printed>
+---------
+Signal Catcher
+
+---------
+Test911
+ getAllStackTraces (I)[[Ljava/lang/Object; -1 -2
+ printAll (I)V 0 75
+ doTest ()V 123 61
+ run ()V 28 44
+
+---------
+main
+<not printed>
+
+########################################
+### Other select threads (suspended) ###
+########################################
+---------
+Test911
+
+---------
+ThreadListTraces Thread 0
+
+---------
+ThreadListTraces Thread 2
+
+---------
+ThreadListTraces Thread 4
+
+---------
+ThreadListTraces Thread 6
+
+---------
+ThreadListTraces Thread 8
+
+---------
+Test911
+ getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
+ printList ([Ljava/lang/Thread;I)V 0 68
+ doTest ()V 110 54
+ run ()V 36 49
+
+---------
+ThreadListTraces Thread 0
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+ThreadListTraces Thread 2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+ThreadListTraces Thread 4
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+ThreadListTraces Thread 6
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+ThreadListTraces Thread 8
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+
+---------
+Test911
+ getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
+ printList ([Ljava/lang/Thread;I)V 0 68
+ doTest ()V 115 56
+ run ()V 36 49
+
+---------
+ThreadListTraces Thread 0
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 37
+
+---------
+ThreadListTraces Thread 2
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 37
+
+---------
+ThreadListTraces Thread 4
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 37
+
+---------
+ThreadListTraces Thread 6
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 37
+
+---------
+ThreadListTraces Thread 8
+ wait (JI)V -1 -2
+ wait (J)V 1 442
+ wait ()V 2 568
+ printOrWait (IILart/ControlData;)V 24 47
+ baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
+ bar (IIILart/ControlData;)J 0 26
+ foo (IIILart/ControlData;)I 0 21
+ run ()V 4 37
+
+
+###################
+### Same thread ###
+###################
+4
+JVMTI_ERROR_ILLEGAL_ARGUMENT
+[public static native java.lang.Object[] art.Frames.getFrameLocation(java.lang.Thread,int), ffffffff]
+[public static void art.Frames.doTestSameThread(), 3e]
+[public static void art.Frames.doTest() throws java.lang.Exception, 0]
+[public void art.Test911$1.run(), 2c]
+JVMTI_ERROR_NO_MORE_FRAMES
+
+################################
+### Other thread (suspended) ###
+################################
+20
+JVMTI_ERROR_ILLEGAL_ARGUMENT
+[public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, ffffffff]
+[public final void java.lang.Object.wait(long) throws java.lang.InterruptedException, 1]
+[public final void java.lang.Object.wait() throws java.lang.InterruptedException, 2]
+[private static void art.Recurse.printOrWait(int,int,art.ControlData), 18]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 2]
+[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
+[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
+[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
+[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
+[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
+[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
+[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
+[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
+[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
+[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
+[public void art.Frames$1.run(), 4]
+JVMTI_ERROR_NO_MORE_FRAMES
+
+###########################
+### Other thread (live) ###
+###########################
+17
+JVMTI_ERROR_ILLEGAL_ARGUMENT
+[private static void art.Recurse.printOrWait(int,int,art.ControlData), 2d]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 2]
+[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
+[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
+[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
+[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
+[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
+[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
+[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
+[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
+[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
+[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
+[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
+[public void art.Frames$2.run(), 4]
+JVMTI_ERROR_NO_MORE_FRAMES
+Done
diff --git a/test/911-get-stack-trace/expected.txt b/test/911-get-stack-trace/expected.txt
deleted file mode 100644
index c1d0378..0000000
--- a/test/911-get-stack-trace/expected.txt
+++ /dev/null
@@ -1,919 +0,0 @@
-###################
-### Same thread ###
-###################
-From top
----------
- getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2
- print (Ljava/lang/Thread;II)V 0 38
- printOrWait (IILart/ControlData;)V 6 41
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- doTest ()V 31 25
- run ()V 0 31
----------
- print (Ljava/lang/Thread;II)V 0 38
- printOrWait (IILart/ControlData;)V 6 41
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- doTest ()V 35 26
- run ()V 0 31
----------
- getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2
- print (Ljava/lang/Thread;II)V 0 38
- printOrWait (IILart/ControlData;)V 6 41
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
----------
- printOrWait (IILart/ControlData;)V 6 41
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
----------
- printOrWait (IILart/ControlData;)V 6 41
-From bottom
----------
- run ()V 0 31
----------
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- doTest ()V 61 33
- run ()V 0 31
----------
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
-################################
-### Other thread (suspended) ###
-################################
-From top
----------
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 28
----------
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 28
----------
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
----------
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
----------
- wait ()V 2 568
-From bottom
----------
- run ()V 4 28
----------
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 28
----------
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
-
-###########################
-### Other thread (live) ###
-###########################
-From top
----------
- printOrWait (IILart/ControlData;)V 45 54
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 62
----------
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 62
----------
- printOrWait (IILart/ControlData;)V 45 54
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
----------
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-From bottom
----------
- run ()V 4 62
----------
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 62
----------
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
-
-################################
-### Other threads (suspended) ###
-################################
----------
-AllTraces Thread 0
-
----------
-AllTraces Thread 1
-
----------
-AllTraces Thread 2
-
----------
-AllTraces Thread 3
-
----------
-AllTraces Thread 4
-
----------
-AllTraces Thread 5
-
----------
-AllTraces Thread 6
-
----------
-AllTraces Thread 7
-
----------
-AllTraces Thread 8
-
----------
-AllTraces Thread 9
-
----------
-FinalizerDaemon
-<not printed>
----------
-FinalizerWatchdogDaemon
-<not printed>
----------
-HeapTaskDaemon
-<not printed>
----------
-ReferenceQueueDaemon
-<not printed>
----------
-Signal Catcher
-
----------
-Test911
-
----------
-main
-<not printed>
----------
-AllTraces Thread 0
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-AllTraces Thread 1
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-AllTraces Thread 2
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-AllTraces Thread 3
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-AllTraces Thread 4
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-AllTraces Thread 5
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-AllTraces Thread 6
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-AllTraces Thread 7
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-AllTraces Thread 8
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-AllTraces Thread 9
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-FinalizerDaemon
-<not printed>
----------
-FinalizerWatchdogDaemon
-<not printed>
----------
-HeapTaskDaemon
-<not printed>
----------
-ReferenceQueueDaemon
-<not printed>
----------
-Signal Catcher
-
----------
-Test911
- getAllStackTraces (I)[[Ljava/lang/Object; -1 -2
- printAll (I)V 0 75
- doTest ()V 120 59
- run ()V 28 44
-
----------
-main
-<not printed>
----------
-AllTraces Thread 0
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 47
-
----------
-AllTraces Thread 1
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 47
-
----------
-AllTraces Thread 2
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 47
-
----------
-AllTraces Thread 3
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 47
-
----------
-AllTraces Thread 4
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 47
-
----------
-AllTraces Thread 5
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 47
-
----------
-AllTraces Thread 6
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 47
-
----------
-AllTraces Thread 7
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 47
-
----------
-AllTraces Thread 8
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 47
-
----------
-AllTraces Thread 9
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 47
-
----------
-FinalizerDaemon
-<not printed>
----------
-FinalizerWatchdogDaemon
-<not printed>
----------
-HeapTaskDaemon
-<not printed>
----------
-ReferenceQueueDaemon
-<not printed>
----------
-Signal Catcher
-
----------
-Test911
- getAllStackTraces (I)[[Ljava/lang/Object; -1 -2
- printAll (I)V 0 75
- doTest ()V 125 61
- run ()V 28 44
-
----------
-main
-<not printed>
-
-########################################
-### Other select threads (suspended) ###
-########################################
----------
-Test911
-
----------
-ThreadListTraces Thread 0
-
----------
-ThreadListTraces Thread 2
-
----------
-ThreadListTraces Thread 4
-
----------
-ThreadListTraces Thread 6
-
----------
-ThreadListTraces Thread 8
-
----------
-Test911
- getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
- printList ([Ljava/lang/Thread;I)V 0 68
- doTest ()V 110 54
- run ()V 36 49
-
----------
-ThreadListTraces Thread 0
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-ThreadListTraces Thread 2
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-ThreadListTraces Thread 4
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-ThreadListTraces Thread 6
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-ThreadListTraces Thread 8
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
-
----------
-Test911
- getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2
- printList ([Ljava/lang/Thread;I)V 0 68
- doTest ()V 115 56
- run ()V 36 49
-
----------
-ThreadListTraces Thread 0
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 37
-
----------
-ThreadListTraces Thread 2
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 37
-
----------
-ThreadListTraces Thread 4
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 37
-
----------
-ThreadListTraces Thread 6
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 37
-
----------
-ThreadListTraces Thread 8
- wait (JI)V -1 -2
- wait (J)V 1 442
- wait ()V 2 568
- printOrWait (IILart/ControlData;)V 24 47
- baz (IIILart/ControlData;)Ljava/lang/Object; 2 32
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- baz (IIILart/ControlData;)Ljava/lang/Object; 8 34
- bar (IIILart/ControlData;)J 0 26
- foo (IIILart/ControlData;)I 0 21
- run ()V 4 37
-
-
-###################
-### Same thread ###
-###################
-4
-JVMTI_ERROR_ILLEGAL_ARGUMENT
-[public static native java.lang.Object[] art.Frames.getFrameLocation(java.lang.Thread,int), ffffffff]
-[public static void art.Frames.doTestSameThread(), 3e]
-[public static void art.Frames.doTest() throws java.lang.Exception, 0]
-[public void art.Test911$1.run(), 2c]
-JVMTI_ERROR_NO_MORE_FRAMES
-
-################################
-### Other thread (suspended) ###
-################################
-20
-JVMTI_ERROR_ILLEGAL_ARGUMENT
-[public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, ffffffff]
-[public final void java.lang.Object.wait(long) throws java.lang.InterruptedException, 1]
-[public final void java.lang.Object.wait() throws java.lang.InterruptedException, 2]
-[private static void art.Recurse.printOrWait(int,int,art.ControlData), 18]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 2]
-[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
-[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
-[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
-[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
-[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
-[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[public void art.Frames$1.run(), 4]
-JVMTI_ERROR_NO_MORE_FRAMES
-
-###########################
-### Other thread (live) ###
-###########################
-17
-JVMTI_ERROR_ILLEGAL_ARGUMENT
-[private static void art.Recurse.printOrWait(int,int,art.ControlData), 2d]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 2]
-[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
-[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
-[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
-[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
-[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[private static java.lang.Object art.Recurse.baz(int,int,int,art.ControlData), 8]
-[private static long art.Recurse.bar(int,int,int,art.ControlData), 0]
-[public static int art.Recurse.foo(int,int,int,art.ControlData), 0]
-[public void art.Frames$2.run(), 4]
-JVMTI_ERROR_NO_MORE_FRAMES
-Done
diff --git a/test/911-get-stack-trace/src/art/PrintThread.java b/test/911-get-stack-trace/src/art/PrintThread.java
index 94f3a33..f843cc3 100644
--- a/test/911-get-stack-trace/src/art/PrintThread.java
+++ b/test/911-get-stack-trace/src/art/PrintThread.java
@@ -42,7 +42,8 @@
   // may not exist depending on the environment.
   public final static String IGNORE_THREAD_NAME_REGEX =
       "Binder:|RenderThread|hwuiTask|Jit thread pool worker|Instr:|JDWP|Profile Saver|main|" +
-      "queued-work-looper|InstrumentationConnectionThread|intel_svc_streamer_thread|ForkJoinPool";
+      "queued-work-looper|InstrumentationConnectionThread|intel_svc_streamer_thread|" +
+      "ForkJoinPool|Metrics Background Reporting Thread";
   public final static Matcher IGNORE_THREADS =
       Pattern.compile(IGNORE_THREAD_NAME_REGEX).matcher("");
 
diff --git a/test/907-get-loaded-classes/expected.txt b/test/912-classes/expected-stderr.txt
similarity index 100%
copy from test/907-get-loaded-classes/expected.txt
copy to test/912-classes/expected-stderr.txt
diff --git a/test/912-classes/expected.txt b/test/912-classes/expected-stdout.txt
similarity index 100%
rename from test/912-classes/expected.txt
rename to test/912-classes/expected-stdout.txt
diff --git a/test/912-classes/src-art/art/Test912.java b/test/912-classes/src-art/art/Test912.java
index a2e8934..8e6b75f 100644
--- a/test/912-classes/src-art/art/Test912.java
+++ b/test/912-classes/src-art/art/Test912.java
@@ -64,7 +64,7 @@
     testClassStatus(Object.class);
     testClassStatus(TestForNonInit.class);
     try {
-      System.out.println(TestForInitFail.dummy);
+      System.out.println(TestForInitFail.intValue);
     } catch (ExceptionInInitializerError e) {
     }
     testClassStatus(TestForInitFail.class);
@@ -281,9 +281,9 @@
       }
     };
 
-    Thread dummyThread = new Thread();
-    dummyThread.start();
-    dummyThread.join();
+    Thread noopThread = new Thread();
+    noopThread.start();
+    noopThread.join();
 
     enableClassLoadPreparePrintEvents(true, Thread.currentThread());
 
@@ -424,12 +424,12 @@
   }
 
   private static class TestForNonInit {
-    public static double dummy = Math.random();  // So it can't be compile-time initialized.
+    public static double doubleValue = Math.random();  // So it can't be compile-time initialized.
   }
 
   @SuppressWarnings("RandomCast")
   private static class TestForInitFail {
-    public static int dummy = ((int)Math.random())/0;  // So it throws when initializing.
+    public static int intValue = ((int)Math.random())/0;  // So it throws when initializing.
   }
 
   public static interface InfA {
diff --git a/test/913-heaps/Android.bp b/test/913-heaps/Android.bp
new file mode 100644
index 0000000..9749b30
--- /dev/null
+++ b/test/913-heaps/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `913-heaps`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-913-heaps",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-913-heaps-expected-stdout",
+        ":art-run-test-913-heaps-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-913-heaps-expected-stdout",
+    out: ["art-run-test-913-heaps-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-913-heaps-expected-stderr",
+    out: ["art-run-test-913-heaps-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/406-fields/expected.txt b/test/913-heaps/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/913-heaps/expected-stderr.txt
diff --git a/test/913-heaps/expected-stdout.txt b/test/913-heaps/expected-stdout.txt
new file mode 100644
index 0000000..e9b82f3
--- /dev/null
+++ b/test/913-heaps/expected-stdout.txt
@@ -0,0 +1,392 @@
+---
+true true
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=124, length=-1]
+1001@0 --(superclass)--> 1000@0 [size=123456780000, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780004, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780001, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780003, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780001, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780002, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+6@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
+---
+1001@0 --(superclass)--> 1000@0 [size=123456780000, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780004, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780001, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780003, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780001, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780002, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+6@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
+---
+root@root --(jni-global)--> 1@1000 [size=16, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=124, length=-1]
+1001@0 --(superclass)--> 1000@0 [size=123456780005, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780009, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780006, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780008, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780006, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780007, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+6@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
+---
+1001@0 --(superclass)--> 1000@0 [size=123456780005, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780009, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780006, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780008, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780006, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780007, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+6@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
+---
+root@root --(thread)--> 3000@0 [size=124, length=-1]
+---
+3@1001 --(class)--> 1001@0 [size=123456780011, length=-1]
+---
+root@root --(thread)--> 3000@0 [size=124, length=-1]
+---
+3@1001 --(class)--> 1001@0 [size=123456780016, length=-1]
+---
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=124, length=-1]
+---
+1001@0 --(superclass)--> 1000@0 [size=123456780020, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780021, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+---
+root@root --(jni-global)--> 1@1000 [size=16, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=124, length=-1]
+---
+1001@0 --(superclass)--> 1000@0 [size=123456780025, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780026, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+---
+[1@0 (32, 'HelloWorld'), 2@0 (16, '')]
+2
+3
+2@0 (15, 3xB '010203')
+3@0 (16, 2xC '41005a00')
+8@0 (32, 2xD '0000000000000000000000000000f03f')
+6@0 (20, 2xF '000000000000803f')
+5@0 (24, 3xI '010000000200000003000000')
+7@0 (40, 3xJ '010000000000000002000000000000000300000000000000')
+4@0 (18, 3xS '010002000300')
+1@0 (14, 2xZ '0001')
+23456789
+10000@0 (static, int, index=3) 0000000000000000
+10001
+10000@0 (static, int, index=11) 0000000000000000
+10001
+10001
+10001
+10000@0 (instance, int, index=2) 0000000000000000
+10001@0 (instance, byte, index=4) 0000000000000001
+10002@0 (instance, char, index=5) 0000000000000061
+10003@0 (instance, int, index=6) 0000000000000003
+10004@0 (instance, long, index=7) 0000000000000004
+10005@0 (instance, short, index=9) 0000000000000002
+10006
+10000@0 (instance, int, index=3) 0000000000000000
+10001@0 (instance, byte, index=5) 0000000000000001
+10002@0 (instance, char, index=6) 0000000000000061
+10003@0 (instance, int, index=7) 0000000000000003
+10004@0 (instance, long, index=8) 0000000000000004
+10005@0 (instance, short, index=10) 0000000000000002
+10006@0 (instance, double, index=12) 3ff3ae147ae147ae
+10007@0 (instance, float, index=13) 000000003f9d70a4
+10008
+--- klass ---
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+---
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+---
+root@root --(jni-global)--> 1@1000 [size=16, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+---
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+---
+--- heap_filter ---
+---- tagged objects
+---
+---
+---
+---
+---- untagged objects
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 164])--> 1000@0 [size=123456780050, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=124, length=-1]
+1001@0 --(superclass)--> 1000@0 [size=123456780050, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780054, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780051, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780053, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780051, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780052, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+6@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
+---
+1001@0 --(superclass)--> 1000@0 [size=123456780050, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780054, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780051, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780053, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780051, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780052, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+6@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
+---
+root@root --(jni-global)--> 1@1000 [size=16, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 164])--> 1000@0 [size=123456780055, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=124, length=-1]
+1001@0 --(superclass)--> 1000@0 [size=123456780055, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780059, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780056, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780058, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780056, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780057, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+6@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
+---
+1001@0 --(superclass)--> 1000@0 [size=123456780055, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780059, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780056, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780058, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780056, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780057, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+6@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
+---
+---- tagged classes
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 181])--> 1000@0 [size=123456780060, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=124, length=-1]
+1001@0 --(superclass)--> 1000@0 [size=123456780060, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780064, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780061, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780063, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780061, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780062, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+6@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
+---
+1001@0 --(superclass)--> 1000@0 [size=123456780060, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780064, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780061, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780063, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780061, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780062, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+6@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
+---
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 181])--> 1000@0 [size=123456780065, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=124, length=-1]
+1001@0 --(superclass)--> 1000@0 [size=123456780065, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780069, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780066, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780068, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780066, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780067, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+6@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
+---
+1001@0 --(superclass)--> 1000@0 [size=123456780065, length=-1]
+1002@0 --(interface)--> 2001@0 [size=123456780069, length=-1]
+1002@0 --(superclass)--> 1001@0 [size=123456780066, length=-1]
+1@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
+2001@0 --(interface)--> 2000@0 [size=123456780068, length=-1]
+2@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
+3@1001 --(class)--> 1001@0 [size=123456780066, length=-1]
+4@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
+5@1002 --(class)--> 1002@0 [size=123456780067, length=-1]
+5@1002 --(field@8)--> 500@0 [size=20, length=2]
+6@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
+---
+---- untagged classes
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+---
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+---
+root@root --(jni-global)--> 1@1000 [size=16, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+---
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
+500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
+5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
+---
+
+default
+image
+zygote
+app
+
+3
diff --git a/test/913-heaps/expected.txt b/test/913-heaps/expected.txt
deleted file mode 100644
index 8fe2ba5..0000000
--- a/test/913-heaps/expected.txt
+++ /dev/null
@@ -1,397 +0,0 @@
----
-true true
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
-1001@0 --(superclass)--> 1000@0 [size=123456780000, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780004, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780001, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780003, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780001, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780002, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
-6@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
----
-1001@0 --(superclass)--> 1000@0 [size=123456780000, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780004, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780001, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780003, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780001, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780002, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
-6@1000 --(class)--> 1000@0 [size=123456780000, length=-1]
----
-root@root --(jni-global)--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 1@1000 [size=16, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
-1001@0 --(superclass)--> 1000@0 [size=123456780005, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780009, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780006, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780008, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780006, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780007, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
-6@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
----
-1001@0 --(superclass)--> 1000@0 [size=123456780005, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780009, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780006, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780008, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780006, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780007, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
-6@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
----
-root@root --(thread)--> 3000@0 [size=124, length=-1]
----
-3@1001 --(class)--> 1001@0 [size=123456780011, length=-1]
----
-root@root --(thread)--> 3000@0 [size=124, length=-1]
----
-3@1001 --(class)--> 1001@0 [size=123456780016, length=-1]
----
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
----
-1001@0 --(superclass)--> 1000@0 [size=123456780020, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780021, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
----
-root@root --(jni-global)--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 1@1000 [size=16, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
----
-1001@0 --(superclass)--> 1000@0 [size=123456780025, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780026, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
----
-[1@0 (32, 'HelloWorld'), 2@0 (16, '')]
-2
-3
-2@0 (15, 3xB '010203')
-3@0 (16, 2xC '41005a00')
-8@0 (32, 2xD '0000000000000000000000000000f03f')
-6@0 (20, 2xF '000000000000803f')
-5@0 (24, 3xI '010000000200000003000000')
-7@0 (40, 3xJ '010000000000000002000000000000000300000000000000')
-4@0 (18, 3xS '010002000300')
-1@0 (14, 2xZ '0001')
-23456789
-10000@0 (static, int, index=3) 0000000000000000
-10001
-10000@0 (static, int, index=11) 0000000000000000
-10001
-10001
-10001
-10000@0 (instance, int, index=2) 0000000000000000
-10001@0 (instance, byte, index=4) 0000000000000001
-10002@0 (instance, char, index=5) 0000000000000061
-10003@0 (instance, int, index=6) 0000000000000003
-10004@0 (instance, long, index=7) 0000000000000004
-10005@0 (instance, short, index=9) 0000000000000002
-10006
-10000@0 (instance, int, index=3) 0000000000000000
-10001@0 (instance, byte, index=5) 0000000000000001
-10002@0 (instance, char, index=6) 0000000000000061
-10003@0 (instance, int, index=7) 0000000000000003
-10004@0 (instance, long, index=8) 0000000000000004
-10005@0 (instance, short, index=10) 0000000000000002
-10006@0 (instance, double, index=12) 3ff3ae147ae147ae
-10007@0 (instance, float, index=13) 000000003f9d70a4
-10008
---- klass ---
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
----
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
----
-root@root --(jni-global)--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(thread)--> 1@1000 [size=16, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
----
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
----
---- heap_filter ---
----- tagged objects
----
----
----
----
----- untagged objects
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 164])--> 1000@0 [size=123456780050, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
-1001@0 --(superclass)--> 1000@0 [size=123456780050, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780054, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780051, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780053, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780051, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780052, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
-6@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
----
-1001@0 --(superclass)--> 1000@0 [size=123456780050, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780054, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780051, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780053, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780051, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780052, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
-6@1000 --(class)--> 1000@0 [size=123456780050, length=-1]
----
-root@root --(jni-global)--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 164])--> 1000@0 [size=123456780055, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 1@1000 [size=16, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
-1001@0 --(superclass)--> 1000@0 [size=123456780055, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780059, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780056, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780058, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780056, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780057, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
-6@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
----
-1001@0 --(superclass)--> 1000@0 [size=123456780055, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780059, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780056, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780058, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780056, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780057, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
-6@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
----
----- tagged classes
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 181])--> 1000@0 [size=123456780060, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
-1001@0 --(superclass)--> 1000@0 [size=123456780060, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780064, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780061, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780063, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780061, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780062, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-6@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
----
-1001@0 --(superclass)--> 1000@0 [size=123456780060, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780064, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780061, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780063, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780061, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780062, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-6@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
----
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 181])--> 1000@0 [size=123456780065, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
-1001@0 --(superclass)--> 1000@0 [size=123456780065, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780069, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780066, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780068, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780066, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780067, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-6@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
----
-1001@0 --(superclass)--> 1000@0 [size=123456780065, length=-1]
-1002@0 --(interface)--> 2001@0 [size=123456780069, length=-1]
-1002@0 --(superclass)--> 1001@0 [size=123456780066, length=-1]
-1@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
-2001@0 --(interface)--> 2000@0 [size=123456780068, length=-1]
-2@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
-3@1001 --(class)--> 1001@0 [size=123456780066, length=-1]
-4@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
-5@1002 --(class)--> 1002@0 [size=123456780067, length=-1]
-5@1002 --(field@8)--> 500@0 [size=20, length=2]
-6@1000 --(class)--> 1000@0 [size=123456780065, length=-1]
----
----- untagged classes
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
----
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
----
-root@root --(jni-global)--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(thread)--> 1@1000 [size=16, length=-1]
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
----
-1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
-1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
-3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
-3@1001 --(field@5)--> 5@1002 [size=36, length=-1]
-500@0 --(array-element@1)--> 2@1000 [size=16, length=-1]
-5@1002 --(field@10)--> 1@1000 [size=16, length=-1]
-5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
----
-
-default
-image
-zygote
-app
-
-3
diff --git a/test/914-hello-obsolescence/Android.bp b/test/914-hello-obsolescence/Android.bp
new file mode 100644
index 0000000..bb8ffb4
--- /dev/null
+++ b/test/914-hello-obsolescence/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `914-hello-obsolescence`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-914-hello-obsolescence",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-914-hello-obsolescence-expected-stdout",
+        ":art-run-test-914-hello-obsolescence-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-914-hello-obsolescence-expected-stdout",
+    out: ["art-run-test-914-hello-obsolescence-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-914-hello-obsolescence-expected-stderr",
+    out: ["art-run-test-914-hello-obsolescence-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/435-new-instance/expected.txt b/test/914-hello-obsolescence/expected-stderr.txt
similarity index 100%
copy from test/435-new-instance/expected.txt
copy to test/914-hello-obsolescence/expected-stderr.txt
diff --git a/test/914-hello-obsolescence/expected.txt b/test/914-hello-obsolescence/expected-stdout.txt
similarity index 100%
rename from test/914-hello-obsolescence/expected.txt
rename to test/914-hello-obsolescence/expected-stdout.txt
diff --git a/test/915-obsolete-2/Android.bp b/test/915-obsolete-2/Android.bp
new file mode 100644
index 0000000..b3216f0
--- /dev/null
+++ b/test/915-obsolete-2/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `915-obsolete-2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-915-obsolete-2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-915-obsolete-2-expected-stdout",
+        ":art-run-test-915-obsolete-2-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-915-obsolete-2-expected-stdout",
+    out: ["art-run-test-915-obsolete-2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-915-obsolete-2-expected-stderr",
+    out: ["art-run-test-915-obsolete-2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/580-crc32/expected.txt b/test/915-obsolete-2/expected-stderr.txt
similarity index 100%
copy from test/580-crc32/expected.txt
copy to test/915-obsolete-2/expected-stderr.txt
diff --git a/test/915-obsolete-2/expected.txt b/test/915-obsolete-2/expected-stdout.txt
similarity index 100%
rename from test/915-obsolete-2/expected.txt
rename to test/915-obsolete-2/expected-stdout.txt
diff --git a/test/916-obsolete-jit/Android.bp b/test/916-obsolete-jit/Android.bp
new file mode 100644
index 0000000..c5ed6e1
--- /dev/null
+++ b/test/916-obsolete-jit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `916-obsolete-jit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-916-obsolete-jit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-916-obsolete-jit-expected-stdout",
+        ":art-run-test-916-obsolete-jit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-916-obsolete-jit-expected-stdout",
+    out: ["art-run-test-916-obsolete-jit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-916-obsolete-jit-expected-stderr",
+    out: ["art-run-test-916-obsolete-jit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/545-tracing-and-jit/expected.txt b/test/916-obsolete-jit/expected-stderr.txt
similarity index 100%
copy from test/545-tracing-and-jit/expected.txt
copy to test/916-obsolete-jit/expected-stderr.txt
diff --git a/test/916-obsolete-jit/expected.txt b/test/916-obsolete-jit/expected-stdout.txt
similarity index 100%
rename from test/916-obsolete-jit/expected.txt
rename to test/916-obsolete-jit/expected-stdout.txt
diff --git a/test/917-fields-transformation/Android.bp b/test/917-fields-transformation/Android.bp
new file mode 100644
index 0000000..41b1b63
--- /dev/null
+++ b/test/917-fields-transformation/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `917-fields-transformation`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-917-fields-transformation",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-917-fields-transformation-expected-stdout",
+        ":art-run-test-917-fields-transformation-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-917-fields-transformation-expected-stdout",
+    out: ["art-run-test-917-fields-transformation-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-917-fields-transformation-expected-stderr",
+    out: ["art-run-test-917-fields-transformation-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/080-oom-fragmentation/expected.txt b/test/917-fields-transformation/expected-stderr.txt
similarity index 100%
copy from test/080-oom-fragmentation/expected.txt
copy to test/917-fields-transformation/expected-stderr.txt
diff --git a/test/917-fields-transformation/expected.txt b/test/917-fields-transformation/expected-stdout.txt
similarity index 100%
rename from test/917-fields-transformation/expected.txt
rename to test/917-fields-transformation/expected-stdout.txt
diff --git a/test/918-fields/Android.bp b/test/918-fields/Android.bp
new file mode 100644
index 0000000..98beeda
--- /dev/null
+++ b/test/918-fields/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `918-fields`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-918-fields",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-918-fields-expected-stdout",
+        ":art-run-test-918-fields-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-918-fields-expected-stdout",
+    out: ["art-run-test-918-fields-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-918-fields-expected-stderr",
+    out: ["art-run-test-918-fields-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/406-fields/expected.txt b/test/918-fields/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/918-fields/expected-stderr.txt
diff --git a/test/918-fields/expected.txt b/test/918-fields/expected-stdout.txt
similarity index 100%
rename from test/918-fields/expected.txt
rename to test/918-fields/expected-stdout.txt
diff --git a/test/919-obsolete-fields/Android.bp b/test/919-obsolete-fields/Android.bp
new file mode 100644
index 0000000..f0ecc8f
--- /dev/null
+++ b/test/919-obsolete-fields/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `919-obsolete-fields`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-919-obsolete-fields",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-919-obsolete-fields-expected-stdout",
+        ":art-run-test-919-obsolete-fields-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-919-obsolete-fields-expected-stdout",
+    out: ["art-run-test-919-obsolete-fields-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-919-obsolete-fields-expected-stderr",
+    out: ["art-run-test-919-obsolete-fields-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/406-fields/expected.txt b/test/919-obsolete-fields/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/919-obsolete-fields/expected-stderr.txt
diff --git a/test/919-obsolete-fields/expected.txt b/test/919-obsolete-fields/expected-stdout.txt
similarity index 100%
rename from test/919-obsolete-fields/expected.txt
rename to test/919-obsolete-fields/expected-stdout.txt
diff --git a/test/920-objects/Android.bp b/test/920-objects/Android.bp
new file mode 100644
index 0000000..570c753
--- /dev/null
+++ b/test/920-objects/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `920-objects`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-920-objects",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-920-objects-expected-stdout",
+        ":art-run-test-920-objects-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-920-objects-expected-stdout",
+    out: ["art-run-test-920-objects-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-920-objects-expected-stderr",
+    out: ["art-run-test-920-objects-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/698-selects/expected.txt b/test/920-objects/expected-stderr.txt
similarity index 100%
copy from test/698-selects/expected.txt
copy to test/920-objects/expected-stderr.txt
diff --git a/test/920-objects/expected.txt b/test/920-objects/expected-stdout.txt
similarity index 100%
rename from test/920-objects/expected.txt
rename to test/920-objects/expected-stdout.txt
diff --git a/test/921-hello-failure/Android.bp b/test/921-hello-failure/Android.bp
new file mode 100644
index 0000000..9776ac2
--- /dev/null
+++ b/test/921-hello-failure/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `921-hello-failure`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-921-hello-failure",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-921-hello-failure-expected-stdout",
+        ":art-run-test-921-hello-failure-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-921-hello-failure-expected-stdout",
+    out: ["art-run-test-921-hello-failure-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-921-hello-failure-expected-stderr",
+    out: ["art-run-test-921-hello-failure-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/082-inline-execute/expected.txt b/test/921-hello-failure/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/921-hello-failure/expected-stderr.txt
diff --git a/test/921-hello-failure/expected.txt b/test/921-hello-failure/expected-stdout.txt
similarity index 100%
rename from test/921-hello-failure/expected.txt
rename to test/921-hello-failure/expected-stdout.txt
diff --git a/test/922-properties/Android.bp b/test/922-properties/Android.bp
new file mode 100644
index 0000000..dc54fef
--- /dev/null
+++ b/test/922-properties/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `922-properties`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-922-properties",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-922-properties-expected-stdout",
+        ":art-run-test-922-properties-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-922-properties-expected-stdout",
+    out: ["art-run-test-922-properties-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-922-properties-expected-stderr",
+    out: ["art-run-test-922-properties-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/922-properties/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/922-properties/expected-stderr.txt
diff --git a/test/922-properties/expected.txt b/test/922-properties/expected-stdout.txt
similarity index 100%
rename from test/922-properties/expected.txt
rename to test/922-properties/expected-stdout.txt
diff --git a/test/923-monitors/Android.bp b/test/923-monitors/Android.bp
new file mode 100644
index 0000000..8d3e8ff
--- /dev/null
+++ b/test/923-monitors/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `923-monitors`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-923-monitors",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-923-monitors-expected-stdout",
+        ":art-run-test-923-monitors-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-923-monitors-expected-stdout",
+    out: ["art-run-test-923-monitors-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-923-monitors-expected-stderr",
+    out: ["art-run-test-923-monitors-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/923-monitors/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/923-monitors/expected-stderr.txt
diff --git a/test/923-monitors/expected.txt b/test/923-monitors/expected-stdout.txt
similarity index 100%
rename from test/923-monitors/expected.txt
rename to test/923-monitors/expected-stdout.txt
diff --git a/test/923-monitors/monitors.cc b/test/923-monitors/monitors.cc
index 9afe22d..e4f3860 100644
--- a/test/923-monitors/monitors.cc
+++ b/test/923-monitors/monitors.cc
@@ -40,7 +40,7 @@
 extern "C" JNIEXPORT jlong JNICALL Java_art_Test923_createRawMonitor(
     JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) {
   jrawMonitorID id;
-  jvmtiError result = jvmti_env->CreateRawMonitor("dummy", &id);
+  jvmtiError result = jvmti_env->CreateRawMonitor("placeholder", &id);
   if (JvmtiErrorToException(env, jvmti_env, result)) {
     return 0;
   }
diff --git a/test/924-threads/Android.bp b/test/924-threads/Android.bp
new file mode 100644
index 0000000..f46122d
--- /dev/null
+++ b/test/924-threads/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `924-threads`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-924-threads",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-924-threads-expected-stdout",
+        ":art-run-test-924-threads-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-924-threads-expected-stdout",
+    out: ["art-run-test-924-threads-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-924-threads-expected-stderr",
+    out: ["art-run-test-924-threads-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/406-fields/expected.txt b/test/924-threads/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/924-threads/expected-stderr.txt
diff --git a/test/924-threads/expected.txt b/test/924-threads/expected-stdout.txt
similarity index 100%
rename from test/924-threads/expected.txt
rename to test/924-threads/expected-stdout.txt
diff --git a/test/925-threadgroups/Android.bp b/test/925-threadgroups/Android.bp
new file mode 100644
index 0000000..71429bd
--- /dev/null
+++ b/test/925-threadgroups/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `925-threadgroups`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-925-threadgroups",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-925-threadgroups-expected-stdout",
+        ":art-run-test-925-threadgroups-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-925-threadgroups-expected-stdout",
+    out: ["art-run-test-925-threadgroups-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-925-threadgroups-expected-stderr",
+    out: ["art-run-test-925-threadgroups-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/925-threadgroups/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/925-threadgroups/expected-stderr.txt
diff --git a/test/925-threadgroups/expected-stdout.txt b/test/925-threadgroups/expected-stdout.txt
new file mode 100644
index 0000000..3cc36f2
--- /dev/null
+++ b/test/925-threadgroups/expected-stdout.txt
@@ -0,0 +1,21 @@
+java.lang.ThreadGroup[name=main,maxpri=10]
+  java.lang.ThreadGroup[name=system,maxpri=10]
+  main
+  10
+  false
+java.lang.ThreadGroup[name=system,maxpri=10]
+  null
+  system
+  10
+  false
+main:
+  [Thread[main,5,main]]
+  []
+system:
+  [Thread[FinalizerDaemon,5,system], Thread[FinalizerWatchdogDaemon,5,system], Thread[HeapTaskDaemon,5,system], Thread[Metrics Background Reporting Thread,5,system], Thread[ReferenceQueueDaemon,5,system], Thread[Signal Catcher,5,system]]
+  [java.lang.ThreadGroup[name=main,maxpri=10]]
+art.Test925$CustomThreadGroup[name=TEST GROUP,maxpri=10]
+  java.lang.ThreadGroup[name=main,maxpri=10]
+  TEST GROUP
+  10
+  false
diff --git a/test/925-threadgroups/expected.txt b/test/925-threadgroups/expected.txt
deleted file mode 100644
index 9dfa37d..0000000
--- a/test/925-threadgroups/expected.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-java.lang.ThreadGroup[name=main,maxpri=10]
-  java.lang.ThreadGroup[name=system,maxpri=10]
-  main
-  10
-  false
-java.lang.ThreadGroup[name=system,maxpri=10]
-  null
-  system
-  10
-  false
-main:
-  [Thread[main,5,main]]
-  []
-system:
-  [Thread[FinalizerDaemon,5,system], Thread[FinalizerWatchdogDaemon,5,system], Thread[HeapTaskDaemon,5,system], Thread[ReferenceQueueDaemon,5,system], Thread[Signal Catcher,5,system]]
-  [java.lang.ThreadGroup[name=main,maxpri=10]]
-art.Test925$CustomThreadGroup[name=TEST GROUP,maxpri=10]
-  java.lang.ThreadGroup[name=main,maxpri=10]
-  TEST GROUP
-  10
-  false
diff --git a/test/925-threadgroups/run b/test/925-threadgroups/run
index c6e62ae..8e44166 100755
--- a/test/925-threadgroups/run
+++ b/test/925-threadgroups/run
@@ -14,4 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-./default-run "$@" --jvmti
+./default-run "$@" --jvmti --runtime-option -Xmetrics-reporting-mods:100
diff --git a/test/925-threadgroups/src/art/Test925.java b/test/925-threadgroups/src/art/Test925.java
index a63f4ce..78068ae 100644
--- a/test/925-threadgroups/src/art/Test925.java
+++ b/test/925-threadgroups/src/art/Test925.java
@@ -47,7 +47,7 @@
     printThreadGroupInfo(curGroup);
     printThreadGroupInfo(rootGroup);
 
-    waitGroupChildren(rootGroup, 5 /* # daemons */, 30 /* timeout in seconds */);
+    waitGroupChildren(rootGroup, 6 /* # daemons */, 30 /* timeout in seconds */);
 
     checkChildren(curGroup);
 
diff --git a/test/926-multi-obsolescence/Android.bp b/test/926-multi-obsolescence/Android.bp
new file mode 100644
index 0000000..1040bf5
--- /dev/null
+++ b/test/926-multi-obsolescence/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `926-multi-obsolescence`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-926-multi-obsolescence",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-926-multi-obsolescence-expected-stdout",
+        ":art-run-test-926-multi-obsolescence-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-926-multi-obsolescence-expected-stdout",
+    out: ["art-run-test-926-multi-obsolescence-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-926-multi-obsolescence-expected-stderr",
+    out: ["art-run-test-926-multi-obsolescence-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/435-new-instance/expected.txt b/test/926-multi-obsolescence/expected-stderr.txt
similarity index 100%
copy from test/435-new-instance/expected.txt
copy to test/926-multi-obsolescence/expected-stderr.txt
diff --git a/test/926-multi-obsolescence/expected.txt b/test/926-multi-obsolescence/expected-stdout.txt
similarity index 100%
rename from test/926-multi-obsolescence/expected.txt
rename to test/926-multi-obsolescence/expected-stdout.txt
diff --git a/test/927-timers/Android.bp b/test/927-timers/Android.bp
new file mode 100644
index 0000000..7265bb8
--- /dev/null
+++ b/test/927-timers/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `927-timers`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-927-timers",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-927-timers-expected-stdout",
+        ":art-run-test-927-timers-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-927-timers-expected-stdout",
+    out: ["art-run-test-927-timers-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-927-timers-expected-stderr",
+    out: ["art-run-test-927-timers-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/927-timers/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/927-timers/expected-stderr.txt
diff --git a/test/927-timers/expected.txt b/test/927-timers/expected-stdout.txt
similarity index 100%
rename from test/927-timers/expected.txt
rename to test/927-timers/expected-stdout.txt
diff --git a/test/928-jni-table/Android.bp b/test/928-jni-table/Android.bp
new file mode 100644
index 0000000..272c5e9
--- /dev/null
+++ b/test/928-jni-table/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `928-jni-table`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-928-jni-table",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-928-jni-table-expected-stdout",
+        ":art-run-test-928-jni-table-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-928-jni-table-expected-stdout",
+    out: ["art-run-test-928-jni-table-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-928-jni-table-expected-stderr",
+    out: ["art-run-test-928-jni-table-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1911-get-local-var-table/expected.txt b/test/928-jni-table/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/928-jni-table/expected-stderr.txt
diff --git a/test/928-jni-table/expected.txt b/test/928-jni-table/expected-stdout.txt
similarity index 100%
rename from test/928-jni-table/expected.txt
rename to test/928-jni-table/expected-stdout.txt
diff --git a/test/558-switch/expected.txt b/test/929-search/expected-stderr.txt
similarity index 100%
copy from test/558-switch/expected.txt
copy to test/929-search/expected-stderr.txt
diff --git a/test/929-search/expected.txt b/test/929-search/expected-stdout.txt
similarity index 100%
rename from test/929-search/expected.txt
rename to test/929-search/expected-stdout.txt
diff --git a/test/930-hello-retransform/Android.bp b/test/930-hello-retransform/Android.bp
new file mode 100644
index 0000000..de0e25c
--- /dev/null
+++ b/test/930-hello-retransform/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `930-hello-retransform`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-930-hello-retransform",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-930-hello-retransform-expected-stdout",
+        ":art-run-test-930-hello-retransform-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-930-hello-retransform-expected-stdout",
+    out: ["art-run-test-930-hello-retransform-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-930-hello-retransform-expected-stderr",
+    out: ["art-run-test-930-hello-retransform-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/561-divrem/expected.txt b/test/930-hello-retransform/expected-stderr.txt
similarity index 100%
copy from test/561-divrem/expected.txt
copy to test/930-hello-retransform/expected-stderr.txt
diff --git a/test/930-hello-retransform/expected.txt b/test/930-hello-retransform/expected-stdout.txt
similarity index 100%
rename from test/930-hello-retransform/expected.txt
rename to test/930-hello-retransform/expected-stdout.txt
diff --git a/test/931-agent-thread/Android.bp b/test/931-agent-thread/Android.bp
new file mode 100644
index 0000000..31ef9ca
--- /dev/null
+++ b/test/931-agent-thread/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `931-agent-thread`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-931-agent-thread",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-931-agent-thread-expected-stdout",
+        ":art-run-test-931-agent-thread-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-931-agent-thread-expected-stdout",
+    out: ["art-run-test-931-agent-thread-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-931-agent-thread-expected-stderr",
+    out: ["art-run-test-931-agent-thread-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/931-agent-thread/agent_thread.cc b/test/931-agent-thread/agent_thread.cc
index 577a97e..391df4e 100644
--- a/test/931-agent-thread/agent_thread.cc
+++ b/test/931-agent-thread/agent_thread.cc
@@ -120,19 +120,13 @@
     env->DeleteLocalRef(cur_thread_info.context_class_loader);
   }
 
-  jmethodID initID = env->GetMethodID(thread_klass.get(),
-                                      "<init>",
-                                      "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
+  jmethodID initID = env->GetMethodID(
+      thread_klass.get(), "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;)V");
   if (initID == nullptr) {
     return;
   }
-  env->CallNonvirtualVoidMethod(thread.get(),
-                                thread_klass.get(),
-                                initID,
-                                thread_group.get(),
-                                thread_name.get(),
-                                0,
-                                JNI_FALSE);
+  env->CallNonvirtualVoidMethod(
+      thread.get(), thread_klass.get(), initID, thread_group.get(), thread_name.get());
   if (env->ExceptionCheck()) {
     return;
   }
diff --git a/test/1902-suspend/expected.txt b/test/931-agent-thread/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/931-agent-thread/expected-stderr.txt
diff --git a/test/931-agent-thread/expected.txt b/test/931-agent-thread/expected-stdout.txt
similarity index 100%
rename from test/931-agent-thread/expected.txt
rename to test/931-agent-thread/expected-stdout.txt
diff --git a/test/932-transform-saves/Android.bp b/test/932-transform-saves/Android.bp
new file mode 100644
index 0000000..5b3b215
--- /dev/null
+++ b/test/932-transform-saves/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `932-transform-saves`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-932-transform-saves",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-932-transform-saves-expected-stdout",
+        ":art-run-test-932-transform-saves-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-932-transform-saves-expected-stdout",
+    out: ["art-run-test-932-transform-saves-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-932-transform-saves-expected-stderr",
+    out: ["art-run-test-932-transform-saves-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1901-get-bytecodes/expected.txt b/test/932-transform-saves/expected-stderr.txt
similarity index 100%
copy from test/1901-get-bytecodes/expected.txt
copy to test/932-transform-saves/expected-stderr.txt
diff --git a/test/932-transform-saves/expected.txt b/test/932-transform-saves/expected-stdout.txt
similarity index 100%
rename from test/932-transform-saves/expected.txt
rename to test/932-transform-saves/expected-stdout.txt
diff --git a/test/933-misc-events/Android.bp b/test/933-misc-events/Android.bp
new file mode 100644
index 0000000..abc5fbf
--- /dev/null
+++ b/test/933-misc-events/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `933-misc-events`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-933-misc-events",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-933-misc-events-expected-stdout",
+        ":art-run-test-933-misc-events-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-933-misc-events-expected-stdout",
+    out: ["art-run-test-933-misc-events-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-933-misc-events-expected-stderr",
+    out: ["art-run-test-933-misc-events-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/410-floats/expected.txt b/test/933-misc-events/expected-stderr.txt
similarity index 100%
copy from test/410-floats/expected.txt
copy to test/933-misc-events/expected-stderr.txt
diff --git a/test/933-misc-events/expected.txt b/test/933-misc-events/expected-stdout.txt
similarity index 100%
rename from test/933-misc-events/expected.txt
rename to test/933-misc-events/expected-stdout.txt
diff --git a/test/561-divrem/expected.txt b/test/934-load-transform/expected-stderr.txt
similarity index 100%
copy from test/561-divrem/expected.txt
copy to test/934-load-transform/expected-stderr.txt
diff --git a/test/934-load-transform/expected.txt b/test/934-load-transform/expected-stdout.txt
similarity index 100%
rename from test/934-load-transform/expected.txt
rename to test/934-load-transform/expected-stdout.txt
diff --git a/test/537-checker-debuggable/expected.txt b/test/935-non-retransformable/expected-stderr.txt
similarity index 100%
copy from test/537-checker-debuggable/expected.txt
copy to test/935-non-retransformable/expected-stderr.txt
diff --git a/test/935-non-retransformable/expected.txt b/test/935-non-retransformable/expected-stdout.txt
similarity index 100%
rename from test/935-non-retransformable/expected.txt
rename to test/935-non-retransformable/expected-stdout.txt
diff --git a/test/1902-suspend/expected.txt b/test/936-search-onload/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/936-search-onload/expected-stderr.txt
diff --git a/test/936-search-onload/expected.txt b/test/936-search-onload/expected-stdout.txt
similarity index 100%
rename from test/936-search-onload/expected.txt
rename to test/936-search-onload/expected-stdout.txt
diff --git a/test/937-hello-retransform-package/Android.bp b/test/937-hello-retransform-package/Android.bp
new file mode 100644
index 0000000..10ebdf4
--- /dev/null
+++ b/test/937-hello-retransform-package/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `937-hello-retransform-package`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-937-hello-retransform-package",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-937-hello-retransform-package-expected-stdout",
+        ":art-run-test-937-hello-retransform-package-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-937-hello-retransform-package-expected-stdout",
+    out: ["art-run-test-937-hello-retransform-package-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-937-hello-retransform-package-expected-stderr",
+    out: ["art-run-test-937-hello-retransform-package-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1337-gc-coverage/expected.txt b/test/937-hello-retransform-package/expected-stderr.txt
similarity index 100%
copy from test/1337-gc-coverage/expected.txt
copy to test/937-hello-retransform-package/expected-stderr.txt
diff --git a/test/937-hello-retransform-package/expected.txt b/test/937-hello-retransform-package/expected-stdout.txt
similarity index 100%
rename from test/937-hello-retransform-package/expected.txt
rename to test/937-hello-retransform-package/expected-stdout.txt
diff --git a/test/432-optimizing-cmp/expected.txt b/test/938-load-transform-bcp/expected-stderr.txt
similarity index 100%
copy from test/432-optimizing-cmp/expected.txt
copy to test/938-load-transform-bcp/expected-stderr.txt
diff --git a/test/938-load-transform-bcp/expected.txt b/test/938-load-transform-bcp/expected-stdout.txt
similarity index 100%
rename from test/938-load-transform-bcp/expected.txt
rename to test/938-load-transform-bcp/expected-stdout.txt
diff --git a/test/939-hello-transformation-bcp/Android.bp b/test/939-hello-transformation-bcp/Android.bp
new file mode 100644
index 0000000..98fa0dc
--- /dev/null
+++ b/test/939-hello-transformation-bcp/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `939-hello-transformation-bcp`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-939-hello-transformation-bcp",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-939-hello-transformation-bcp-expected-stdout",
+        ":art-run-test-939-hello-transformation-bcp-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-939-hello-transformation-bcp-expected-stdout",
+    out: ["art-run-test-939-hello-transformation-bcp-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-939-hello-transformation-bcp-expected-stderr",
+    out: ["art-run-test-939-hello-transformation-bcp-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/2024-InvariantNegativeLoop/expected.txt b/test/939-hello-transformation-bcp/expected-stderr.txt
similarity index 100%
copy from test/2024-InvariantNegativeLoop/expected.txt
copy to test/939-hello-transformation-bcp/expected-stderr.txt
diff --git a/test/939-hello-transformation-bcp/expected.txt b/test/939-hello-transformation-bcp/expected-stdout.txt
similarity index 100%
rename from test/939-hello-transformation-bcp/expected.txt
rename to test/939-hello-transformation-bcp/expected-stdout.txt
diff --git a/test/940-recursive-obsolete/Android.bp b/test/940-recursive-obsolete/Android.bp
new file mode 100644
index 0000000..19a6732
--- /dev/null
+++ b/test/940-recursive-obsolete/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `940-recursive-obsolete`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-940-recursive-obsolete",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-940-recursive-obsolete-expected-stdout",
+        ":art-run-test-940-recursive-obsolete-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-940-recursive-obsolete-expected-stdout",
+    out: ["art-run-test-940-recursive-obsolete-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-940-recursive-obsolete-expected-stderr",
+    out: ["art-run-test-940-recursive-obsolete-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/082-inline-execute/expected.txt b/test/940-recursive-obsolete/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/940-recursive-obsolete/expected-stderr.txt
diff --git a/test/940-recursive-obsolete/expected.txt b/test/940-recursive-obsolete/expected-stdout.txt
similarity index 100%
rename from test/940-recursive-obsolete/expected.txt
rename to test/940-recursive-obsolete/expected-stdout.txt
diff --git a/test/941-recursive-obsolete-jit/Android.bp b/test/941-recursive-obsolete-jit/Android.bp
new file mode 100644
index 0000000..df6be48
--- /dev/null
+++ b/test/941-recursive-obsolete-jit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `941-recursive-obsolete-jit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-941-recursive-obsolete-jit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-941-recursive-obsolete-jit-expected-stdout",
+        ":art-run-test-941-recursive-obsolete-jit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-941-recursive-obsolete-jit-expected-stdout",
+    out: ["art-run-test-941-recursive-obsolete-jit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-941-recursive-obsolete-jit-expected-stderr",
+    out: ["art-run-test-941-recursive-obsolete-jit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/545-tracing-and-jit/expected.txt b/test/941-recursive-obsolete-jit/expected-stderr.txt
similarity index 100%
copy from test/545-tracing-and-jit/expected.txt
copy to test/941-recursive-obsolete-jit/expected-stderr.txt
diff --git a/test/941-recurive-obsolete-jit/expected.txt b/test/941-recursive-obsolete-jit/expected-stdout.txt
similarity index 100%
rename from test/941-recurive-obsolete-jit/expected.txt
rename to test/941-recursive-obsolete-jit/expected-stdout.txt
diff --git a/test/941-recurive-obsolete-jit/info.txt b/test/941-recursive-obsolete-jit/info.txt
similarity index 100%
rename from test/941-recurive-obsolete-jit/info.txt
rename to test/941-recursive-obsolete-jit/info.txt
diff --git a/test/941-recurive-obsolete-jit/run b/test/941-recursive-obsolete-jit/run
similarity index 100%
rename from test/941-recurive-obsolete-jit/run
rename to test/941-recursive-obsolete-jit/run
diff --git a/test/941-recurive-obsolete-jit/src/Main.java b/test/941-recursive-obsolete-jit/src/Main.java
similarity index 100%
rename from test/941-recurive-obsolete-jit/src/Main.java
rename to test/941-recursive-obsolete-jit/src/Main.java
diff --git a/test/941-recurive-obsolete-jit/src/Transform.java b/test/941-recursive-obsolete-jit/src/Transform.java
similarity index 100%
rename from test/941-recurive-obsolete-jit/src/Transform.java
rename to test/941-recursive-obsolete-jit/src/Transform.java
diff --git a/test/941-recurive-obsolete-jit/src/art/Redefinition.java b/test/941-recursive-obsolete-jit/src/art/Redefinition.java
similarity index 100%
rename from test/941-recurive-obsolete-jit/src/art/Redefinition.java
rename to test/941-recursive-obsolete-jit/src/art/Redefinition.java
diff --git a/test/942-private-recursive/Android.bp b/test/942-private-recursive/Android.bp
new file mode 100644
index 0000000..a83b776
--- /dev/null
+++ b/test/942-private-recursive/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `942-private-recursive`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-942-private-recursive",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-942-private-recursive-expected-stdout",
+        ":art-run-test-942-private-recursive-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-942-private-recursive-expected-stdout",
+    out: ["art-run-test-942-private-recursive-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-942-private-recursive-expected-stderr",
+    out: ["art-run-test-942-private-recursive-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/082-inline-execute/expected.txt b/test/942-private-recursive/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/942-private-recursive/expected-stderr.txt
diff --git a/test/942-private-recursive/expected.txt b/test/942-private-recursive/expected-stdout.txt
similarity index 100%
rename from test/942-private-recursive/expected.txt
rename to test/942-private-recursive/expected-stdout.txt
diff --git a/test/943-private-recursive-jit/Android.bp b/test/943-private-recursive-jit/Android.bp
new file mode 100644
index 0000000..96593f0
--- /dev/null
+++ b/test/943-private-recursive-jit/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `943-private-recursive-jit`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-943-private-recursive-jit",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-943-private-recursive-jit-expected-stdout",
+        ":art-run-test-943-private-recursive-jit-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-943-private-recursive-jit-expected-stdout",
+    out: ["art-run-test-943-private-recursive-jit-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-943-private-recursive-jit-expected-stderr",
+    out: ["art-run-test-943-private-recursive-jit-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/545-tracing-and-jit/expected.txt b/test/943-private-recursive-jit/expected-stderr.txt
similarity index 100%
copy from test/545-tracing-and-jit/expected.txt
copy to test/943-private-recursive-jit/expected-stderr.txt
diff --git a/test/943-private-recursive-jit/expected.txt b/test/943-private-recursive-jit/expected-stdout.txt
similarity index 100%
rename from test/943-private-recursive-jit/expected.txt
rename to test/943-private-recursive-jit/expected-stdout.txt
diff --git a/test/944-transform-classloaders/Android.bp b/test/944-transform-classloaders/Android.bp
new file mode 100644
index 0000000..d988484
--- /dev/null
+++ b/test/944-transform-classloaders/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `944-transform-classloaders`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-944-transform-classloaders",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-944-transform-classloaders-expected-stdout",
+        ":art-run-test-944-transform-classloaders-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-944-transform-classloaders-expected-stdout",
+    out: ["art-run-test-944-transform-classloaders-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-944-transform-classloaders-expected-stderr",
+    out: ["art-run-test-944-transform-classloaders-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/121-modifiers/expected.txt b/test/944-transform-classloaders/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/944-transform-classloaders/expected-stderr.txt
diff --git a/test/944-transform-classloaders/expected.txt b/test/944-transform-classloaders/expected-stdout.txt
similarity index 100%
rename from test/944-transform-classloaders/expected.txt
rename to test/944-transform-classloaders/expected-stdout.txt
diff --git a/test/945-obsolete-native/Android.bp b/test/945-obsolete-native/Android.bp
new file mode 100644
index 0000000..6014da6
--- /dev/null
+++ b/test/945-obsolete-native/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `945-obsolete-native`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-945-obsolete-native",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-945-obsolete-native-expected-stdout",
+        ":art-run-test-945-obsolete-native-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-945-obsolete-native-expected-stdout",
+    out: ["art-run-test-945-obsolete-native-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-945-obsolete-native-expected-stderr",
+    out: ["art-run-test-945-obsolete-native-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/082-inline-execute/expected.txt b/test/945-obsolete-native/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/945-obsolete-native/expected-stderr.txt
diff --git a/test/945-obsolete-native/expected.txt b/test/945-obsolete-native/expected-stdout.txt
similarity index 100%
rename from test/945-obsolete-native/expected.txt
rename to test/945-obsolete-native/expected-stdout.txt
diff --git a/test/946-obsolete-throw/Android.bp b/test/946-obsolete-throw/Android.bp
new file mode 100644
index 0000000..aedab56
--- /dev/null
+++ b/test/946-obsolete-throw/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `946-obsolete-throw`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-946-obsolete-throw",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-946-obsolete-throw-expected-stdout",
+        ":art-run-test-946-obsolete-throw-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-946-obsolete-throw-expected-stdout",
+    out: ["art-run-test-946-obsolete-throw-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-946-obsolete-throw-expected-stderr",
+    out: ["art-run-test-946-obsolete-throw-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/001-Main/expected.txt b/test/946-obsolete-throw/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/946-obsolete-throw/expected-stderr.txt
diff --git a/test/946-obsolete-throw/expected.txt b/test/946-obsolete-throw/expected-stdout.txt
similarity index 100%
rename from test/946-obsolete-throw/expected.txt
rename to test/946-obsolete-throw/expected-stdout.txt
diff --git a/test/947-reflect-method/Android.bp b/test/947-reflect-method/Android.bp
new file mode 100644
index 0000000..74abcc0
--- /dev/null
+++ b/test/947-reflect-method/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `947-reflect-method`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-947-reflect-method",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-947-reflect-method-expected-stdout",
+        ":art-run-test-947-reflect-method-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-947-reflect-method-expected-stdout",
+    out: ["art-run-test-947-reflect-method-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-947-reflect-method-expected-stderr",
+    out: ["art-run-test-947-reflect-method-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/491-current-method/expected.txt b/test/947-reflect-method/expected-stderr.txt
similarity index 100%
copy from test/491-current-method/expected.txt
copy to test/947-reflect-method/expected-stderr.txt
diff --git a/test/947-reflect-method/expected.txt b/test/947-reflect-method/expected-stdout.txt
similarity index 100%
rename from test/947-reflect-method/expected.txt
rename to test/947-reflect-method/expected-stdout.txt
diff --git a/test/148-multithread-gc-annotations/expected.txt b/test/948-change-annotations/expected-stderr.txt
similarity index 100%
copy from test/148-multithread-gc-annotations/expected.txt
copy to test/948-change-annotations/expected-stderr.txt
diff --git a/test/948-change-annotations/expected.txt b/test/948-change-annotations/expected-stdout.txt
similarity index 100%
rename from test/948-change-annotations/expected.txt
rename to test/948-change-annotations/expected-stdout.txt
diff --git a/test/949-in-memory-transform/Android.bp b/test/949-in-memory-transform/Android.bp
new file mode 100644
index 0000000..ed569e6
--- /dev/null
+++ b/test/949-in-memory-transform/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `949-in-memory-transform`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-949-in-memory-transform",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-949-in-memory-transform-expected-stdout",
+        ":art-run-test-949-in-memory-transform-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-949-in-memory-transform-expected-stdout",
+    out: ["art-run-test-949-in-memory-transform-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-949-in-memory-transform-expected-stderr",
+    out: ["art-run-test-949-in-memory-transform-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/561-divrem/expected.txt b/test/949-in-memory-transform/expected-stderr.txt
similarity index 100%
copy from test/561-divrem/expected.txt
copy to test/949-in-memory-transform/expected-stderr.txt
diff --git a/test/949-in-memory-transform/expected.txt b/test/949-in-memory-transform/expected-stdout.txt
similarity index 100%
rename from test/949-in-memory-transform/expected.txt
rename to test/949-in-memory-transform/expected-stdout.txt
diff --git a/test/950-redefine-intrinsic/Android.bp b/test/950-redefine-intrinsic/Android.bp
new file mode 100644
index 0000000..2dd669e
--- /dev/null
+++ b/test/950-redefine-intrinsic/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `950-redefine-intrinsic`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-950-redefine-intrinsic",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-950-redefine-intrinsic-expected-stdout",
+        ":art-run-test-950-redefine-intrinsic-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-950-redefine-intrinsic-expected-stdout",
+    out: ["art-run-test-950-redefine-intrinsic-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-950-redefine-intrinsic-expected-stderr",
+    out: ["art-run-test-950-redefine-intrinsic-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/643-checker-bogus-ic/expected.txt b/test/950-redefine-intrinsic/expected-stderr.txt
similarity index 100%
copy from test/643-checker-bogus-ic/expected.txt
copy to test/950-redefine-intrinsic/expected-stderr.txt
diff --git a/test/950-redefine-intrinsic/expected.txt b/test/950-redefine-intrinsic/expected-stdout.txt
similarity index 100%
rename from test/950-redefine-intrinsic/expected.txt
rename to test/950-redefine-intrinsic/expected-stdout.txt
diff --git a/test/951-threaded-obsolete/Android.bp b/test/951-threaded-obsolete/Android.bp
new file mode 100644
index 0000000..0870ee2
--- /dev/null
+++ b/test/951-threaded-obsolete/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `951-threaded-obsolete`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-951-threaded-obsolete",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-951-threaded-obsolete-expected-stdout",
+        ":art-run-test-951-threaded-obsolete-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-951-threaded-obsolete-expected-stdout",
+    out: ["art-run-test-951-threaded-obsolete-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-951-threaded-obsolete-expected-stderr",
+    out: ["art-run-test-951-threaded-obsolete-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/082-inline-execute/expected.txt b/test/951-threaded-obsolete/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/951-threaded-obsolete/expected-stderr.txt
diff --git a/test/951-threaded-obsolete/expected.txt b/test/951-threaded-obsolete/expected-stdout.txt
similarity index 100%
rename from test/951-threaded-obsolete/expected.txt
rename to test/951-threaded-obsolete/expected-stdout.txt
diff --git a/test/952-invoke-custom/build b/test/952-invoke-custom/build
index a70fc20..de7e91d 100755
--- a/test/952-invoke-custom/build
+++ b/test/952-invoke-custom/build
@@ -27,14 +27,13 @@
   set -e # Stop on error - the caller script may not have this set.
 
   # Update arguments to add transformer and ASM to the compiler classpath.
-  local args=()
   local classpath="./transformer.jar:$ASM_JAR"
+  local args=(-cp $classpath)
   while [ $# -ne 0 ] ; do
     case $1 in
       -cp|-classpath|--class-path)
         shift
         shift
-        args+=(-cp $classpath)
         ;;
       *)
         args+=("$1")
diff --git a/test/561-divrem/expected.txt b/test/952-invoke-custom/expected-stderr.txt
similarity index 100%
copy from test/561-divrem/expected.txt
copy to test/952-invoke-custom/expected-stderr.txt
diff --git a/test/952-invoke-custom/expected.txt b/test/952-invoke-custom/expected-stdout.txt
similarity index 100%
rename from test/952-invoke-custom/expected.txt
rename to test/952-invoke-custom/expected-stdout.txt
diff --git a/test/706-checker-scheduler/expected.txt b/test/953-invoke-polymorphic-compiler/expected-stderr.txt
similarity index 100%
copy from test/706-checker-scheduler/expected.txt
copy to test/953-invoke-polymorphic-compiler/expected-stderr.txt
diff --git a/test/953-invoke-polymorphic-compiler/expected.txt b/test/953-invoke-polymorphic-compiler/expected-stdout.txt
similarity index 100%
rename from test/953-invoke-polymorphic-compiler/expected.txt
rename to test/953-invoke-polymorphic-compiler/expected-stdout.txt
diff --git a/test/954-invoke-polymorphic-verifier/check b/test/954-invoke-polymorphic-verifier/check
index 85db5ae..3f9e6dc 100755
--- a/test/954-invoke-polymorphic-verifier/check
+++ b/test/954-invoke-polymorphic-verifier/check
@@ -14,6 +14,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # Strip out temporary file path information and indices from output.
 sed -e "s/ [(]declaration of.*//" -e "s/\[0x[0-9A-F]*\] //g" "$2" > "$2.tmp"
-diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null
+diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4" >/dev/null
diff --git a/test/463-checker-boolean-simplifier/expected.txt b/test/954-invoke-polymorphic-verifier/expected-stderr.txt
similarity index 100%
copy from test/463-checker-boolean-simplifier/expected.txt
copy to test/954-invoke-polymorphic-verifier/expected-stderr.txt
diff --git a/test/954-invoke-polymorphic-verifier/expected.txt b/test/954-invoke-polymorphic-verifier/expected-stdout.txt
similarity index 100%
rename from test/954-invoke-polymorphic-verifier/expected.txt
rename to test/954-invoke-polymorphic-verifier/expected-stdout.txt
diff --git a/test/520-equivalent-phi/expected.txt b/test/955-methodhandles-smali/expected-stderr.txt
similarity index 100%
copy from test/520-equivalent-phi/expected.txt
copy to test/955-methodhandles-smali/expected-stderr.txt
diff --git a/test/955-methodhandles-smali/expected.txt b/test/955-methodhandles-smali/expected-stdout.txt
similarity index 100%
rename from test/955-methodhandles-smali/expected.txt
rename to test/955-methodhandles-smali/expected-stdout.txt
diff --git a/test/450-checker-types/expected.txt b/test/956-methodhandles/expected-stderr.txt
similarity index 100%
copy from test/450-checker-types/expected.txt
copy to test/956-methodhandles/expected-stderr.txt
diff --git a/test/956-methodhandles/expected.txt b/test/956-methodhandles/expected-stdout.txt
similarity index 100%
rename from test/956-methodhandles/expected.txt
rename to test/956-methodhandles/expected-stdout.txt
diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java
index e70c83b..5dace08 100644
--- a/test/956-methodhandles/src/Main.java
+++ b/test/956-methodhandles/src/Main.java
@@ -1172,13 +1172,13 @@
 
     // boolean -> int
     try {
-        int dummy = (int) mh.invoke("True");
+        int unexpectedValue = (int) mh.invoke("True");
         fail();
     } catch (WrongMethodTypeException e) {}
 
     // boolean -> Integer
     try {
-        Integer dummy = (Integer) mh.invoke("True");
+        Integer unexpectedValue = (Integer) mh.invoke("True");
         fail();
     } catch (WrongMethodTypeException e) {}
 
@@ -1190,13 +1190,13 @@
 
     // Boolean -> int
     try {
-        int dummy = (int) mh.invoke(false);
+        int unexpectedValue = (int) mh.invoke(false);
         fail();
     } catch (WrongMethodTypeException e) {}
 
     // Boolean -> Integer
     try {
-        Integer dummy = (Integer) mh.invoke("True");
+        Integer unexpectedValue = (Integer) mh.invoke("True");
         fail();
     } catch (WrongMethodTypeException e) {}
 
diff --git a/test/907-get-loaded-classes/expected.txt b/test/957-methodhandle-transforms/expected-stderr.txt
similarity index 100%
copy from test/907-get-loaded-classes/expected.txt
copy to test/957-methodhandle-transforms/expected-stderr.txt
diff --git a/test/957-methodhandle-transforms/expected.txt b/test/957-methodhandle-transforms/expected-stdout.txt
similarity index 100%
rename from test/957-methodhandle-transforms/expected.txt
rename to test/957-methodhandle-transforms/expected-stdout.txt
diff --git a/test/957-methodhandle-transforms/src/Main.java b/test/957-methodhandle-transforms/src/Main.java
index b6bbe74..0bdc80a 100644
--- a/test/957-methodhandle-transforms/src/Main.java
+++ b/test/957-methodhandle-transforms/src/Main.java
@@ -1342,7 +1342,7 @@
     } catch (WrongMethodTypeException expected) {
     }
 
-    // Sanity checks on other array types.
+    // Checks on other array types.
 
     MethodHandle target = MethodHandles.lookup().findStatic(
         Main.class, "collectBoolean",
diff --git a/test/421-large-frame/expected.txt b/test/958-methodhandle-stackframe/expected-stderr.txt
similarity index 100%
copy from test/421-large-frame/expected.txt
copy to test/958-methodhandle-stackframe/expected-stderr.txt
diff --git a/test/958-methodhandle-stackframe/expected.txt b/test/958-methodhandle-stackframe/expected-stdout.txt
similarity index 100%
rename from test/958-methodhandle-stackframe/expected.txt
rename to test/958-methodhandle-stackframe/expected-stdout.txt
diff --git a/test/121-modifiers/expected.txt b/test/959-invoke-polymorphic-accessors/expected-stderr.txt
similarity index 100%
copy from test/121-modifiers/expected.txt
copy to test/959-invoke-polymorphic-accessors/expected-stderr.txt
diff --git a/test/959-invoke-polymorphic-accessors/expected.txt b/test/959-invoke-polymorphic-accessors/expected-stdout.txt
similarity index 100%
rename from test/959-invoke-polymorphic-accessors/expected.txt
rename to test/959-invoke-polymorphic-accessors/expected-stdout.txt
diff --git a/test/520-equivalent-phi/expected.txt b/test/960-default-smali/expected-stderr.txt
similarity index 100%
copy from test/520-equivalent-phi/expected.txt
copy to test/960-default-smali/expected-stderr.txt
diff --git a/test/960-default-smali/expected.txt b/test/960-default-smali/expected-stdout.txt
similarity index 100%
rename from test/960-default-smali/expected.txt
rename to test/960-default-smali/expected-stdout.txt
diff --git a/test/960-default-smali/info.txt b/test/960-default-smali/info.txt
index 9583abb..cb525a2 100644
--- a/test/960-default-smali/info.txt
+++ b/test/960-default-smali/info.txt
@@ -17,4 +17,4 @@
     <Add new classes/interfaces>
     <Add these classes/interfaces to ./smali/classes.xml>
     JAVA_HOME="/path/to/java-8-jdk" ../run-test --use-java-home --update --jvm --host 956-default-smali
-    git add ./smali/classes.xml ./expected.txt
+    git add ./smali/classes.xml ./expected-stdout.txt
diff --git a/test/961-default-iface-resolution-gen/build b/test/961-default-iface-resolution-gen/build
index 1d24589..b9b36d0 100755
--- a/test/961-default-iface-resolution-gen/build
+++ b/test/961-default-iface-resolution-gen/build
@@ -19,7 +19,7 @@
 
 mkdir -p ./src
 
-# Generate the smali files and expected.txt or fail
-./util-src/generate_java.py ./src ./expected.txt
+# Generate the smali files and expected-stdout.txt or fail
+./util-src/generate_java.py ./src ./expected-stdout.txt
 
 ./default-build "$@" --experimental default-methods
diff --git a/test/001-Main/expected.txt b/test/961-default-iface-resolution-gen/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/961-default-iface-resolution-gen/expected-stderr.txt
diff --git a/test/961-default-iface-resolution-gen/expected.txt b/test/961-default-iface-resolution-gen/expected-stdout.txt
similarity index 100%
rename from test/961-default-iface-resolution-gen/expected.txt
rename to test/961-default-iface-resolution-gen/expected-stdout.txt
diff --git a/test/961-default-iface-resolution-gen/info.txt b/test/961-default-iface-resolution-gen/info.txt
index 2cd2cc7..b5a04fd 100644
--- a/test/961-default-iface-resolution-gen/info.txt
+++ b/test/961-default-iface-resolution-gen/info.txt
@@ -13,5 +13,5 @@
 return equivalent output when run multiple times and the expected output should
 be valid.
 
-Do not modify the expected.txt file. It is generated on each run by
+Do not modify the expected-stdout.txt file. It is generated on each run by
 util-src/generate_smali.py.
diff --git a/test/1900-track-alloc/expected.txt b/test/962-iface-static/expected-stderr.txt
similarity index 100%
copy from test/1900-track-alloc/expected.txt
copy to test/962-iface-static/expected-stderr.txt
diff --git a/test/962-iface-static/expected.txt b/test/962-iface-static/expected-stdout.txt
similarity index 100%
rename from test/962-iface-static/expected.txt
rename to test/962-iface-static/expected-stdout.txt
diff --git a/test/963-default-range-smali/Android.bp b/test/963-default-range-smali/Android.bp
new file mode 100644
index 0000000..b4cb157
--- /dev/null
+++ b/test/963-default-range-smali/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `963-default-range-smali`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-963-default-range-smali",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-963-default-range-smali-expected-stdout",
+        ":art-run-test-963-default-range-smali-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-963-default-range-smali-expected-stdout",
+    out: ["art-run-test-963-default-range-smali-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-963-default-range-smali-expected-stderr",
+    out: ["art-run-test-963-default-range-smali-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/520-equivalent-phi/expected.txt b/test/963-default-range-smali/expected-stderr.txt
similarity index 100%
copy from test/520-equivalent-phi/expected.txt
copy to test/963-default-range-smali/expected-stderr.txt
diff --git a/test/963-default-range-smali/expected.txt b/test/963-default-range-smali/expected-stdout.txt
similarity index 100%
rename from test/963-default-range-smali/expected.txt
rename to test/963-default-range-smali/expected-stdout.txt
diff --git a/test/964-default-iface-init-gen/build b/test/964-default-iface-init-gen/build
index 1d24589..b9b36d0 100755
--- a/test/964-default-iface-init-gen/build
+++ b/test/964-default-iface-init-gen/build
@@ -19,7 +19,7 @@
 
 mkdir -p ./src
 
-# Generate the smali files and expected.txt or fail
-./util-src/generate_java.py ./src ./expected.txt
+# Generate the smali files and expected-stdout.txt or fail
+./util-src/generate_java.py ./src ./expected-stdout.txt
 
 ./default-build "$@" --experimental default-methods
diff --git a/test/972-default-imt-collision/expected.txt b/test/964-default-iface-init-gen/expected-stderr.txt
similarity index 100%
copy from test/972-default-imt-collision/expected.txt
copy to test/964-default-iface-init-gen/expected-stderr.txt
diff --git a/test/964-default-iface-init-gen/expected.txt b/test/964-default-iface-init-gen/expected-stdout.txt
similarity index 100%
rename from test/964-default-iface-init-gen/expected.txt
rename to test/964-default-iface-init-gen/expected-stdout.txt
diff --git a/test/964-default-iface-init-gen/info.txt b/test/964-default-iface-init-gen/info.txt
index 5805a86..641fd03 100644
--- a/test/964-default-iface-init-gen/info.txt
+++ b/test/964-default-iface-init-gen/info.txt
@@ -13,5 +13,5 @@
 return equivalent output when run multiple times and the expected output should
 be valid.
 
-Do not modify the expected.txt file. It is generated on each run by
+Do not modify the expected-stdout.txt file. It is generated on each run by
 util-src/generate_smali.py.
diff --git a/test/165-lock-owner-proxy/expected.txt b/test/965-default-verify/expected-stderr.txt
similarity index 100%
copy from test/165-lock-owner-proxy/expected.txt
copy to test/965-default-verify/expected-stderr.txt
diff --git a/test/965-default-verify/expected.txt b/test/965-default-verify/expected-stdout.txt
similarity index 100%
rename from test/965-default-verify/expected.txt
rename to test/965-default-verify/expected-stdout.txt
diff --git a/test/434-invoke-direct/expected.txt b/test/966-default-conflict/expected-stderr.txt
similarity index 100%
copy from test/434-invoke-direct/expected.txt
copy to test/966-default-conflict/expected-stderr.txt
diff --git a/test/966-default-conflict/expected.txt b/test/966-default-conflict/expected-stdout.txt
similarity index 100%
rename from test/966-default-conflict/expected.txt
rename to test/966-default-conflict/expected-stdout.txt
diff --git a/test/421-large-frame/expected.txt b/test/967-default-ame/expected-stderr.txt
similarity index 100%
copy from test/421-large-frame/expected.txt
copy to test/967-default-ame/expected-stderr.txt
diff --git a/test/967-default-ame/expected.txt b/test/967-default-ame/expected-stdout.txt
similarity index 100%
rename from test/967-default-ame/expected.txt
rename to test/967-default-ame/expected-stdout.txt
diff --git a/test/968-default-partial-compile-gen/build b/test/968-default-partial-compile-gen/build
index c8f0384..38e84a5 100755
--- a/test/968-default-partial-compile-gen/build
+++ b/test/968-default-partial-compile-gen/build
@@ -23,14 +23,14 @@
   mkdir -p src
   echo "${JAVAC} \$@" >> ./javac_exec.sh
   # This will use java_exec.sh to execute the javac compiler. It will place the
-  # compiled class files in ./classes and the expected values in expected.txt
+  # compiled class files in ./classes and the expected values in expected-stdout.txt
   #
   # After this the src directory will contain the final versions of all files.
-  ./util-src/generate_java.py ./javac_exec.sh ./src ./classes ./expected.txt ./build_log
+  ./util-src/generate_java.py ./javac_exec.sh ./src ./classes ./expected-stdout.txt ./build_log
 else
   mkdir -p ./smali
-  # Generate the smali files and expected.txt or fail
-  ./util-src/generate_smali.py ./smali ./expected.txt
+  # Generate the smali files and expected-stdout.txt or fail
+  ./util-src/generate_smali.py ./smali ./expected-stdout.txt
   # Use the default build script
   ./default-build "$@" "$EXTRA_ARGS" --experimental default-methods
 fi
diff --git a/test/001-Main/expected.txt b/test/968-default-partial-compile-gen/expected-stderr.txt
similarity index 100%
copy from test/001-Main/expected.txt
copy to test/968-default-partial-compile-gen/expected-stderr.txt
diff --git a/test/968-default-partial-compile-gen/expected.txt b/test/968-default-partial-compile-gen/expected-stdout.txt
similarity index 100%
rename from test/968-default-partial-compile-gen/expected.txt
rename to test/968-default-partial-compile-gen/expected-stdout.txt
diff --git a/test/968-default-partial-compile-gen/info.txt b/test/968-default-partial-compile-gen/info.txt
index bc1c428..e4bd5a7 100644
--- a/test/968-default-partial-compile-gen/info.txt
+++ b/test/968-default-partial-compile-gen/info.txt
@@ -13,5 +13,5 @@
 return equivalent output when run multiple times and the expected output should
 be valid.
 
-Do not modify the expected.txt file. It is generated on each run by
+Do not modify the expected-stdout.txt file. It is generated on each run by
 util-src/generate_smali.py.
diff --git a/test/551-invoke-super/expected.txt b/test/969-iface-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/969-iface-super/expected-stderr.txt
diff --git a/test/969-iface-super/expected.txt b/test/969-iface-super/expected-stdout.txt
similarity index 100%
rename from test/969-iface-super/expected.txt
rename to test/969-iface-super/expected-stdout.txt
diff --git a/test/970-iface-super-resolution-gen/build b/test/970-iface-super-resolution-gen/build
index 0594501..6eecd71 100755
--- a/test/970-iface-super-resolution-gen/build
+++ b/test/970-iface-super-resolution-gen/build
@@ -23,11 +23,11 @@
   # Build the Java files
   mkdir -p src
   mkdir -p src2
-  ./util-src/generate_java.py ./src2 ./src ./expected.txt
+  ./util-src/generate_java.py ./src2 ./src ./expected-stdout.txt
 else
-  # Generate the smali files and expected.txt or fail
+  # Generate the smali files and expected-stdout.txt or fail
   mkdir -p smali
-  ./util-src/generate_smali.py ./smali ./expected.txt
+  ./util-src/generate_smali.py ./smali ./expected-stdout.txt
 fi
 
 ./default-build "$@" --experimental default-methods
diff --git a/test/972-default-imt-collision/expected.txt b/test/970-iface-super-resolution-gen/expected-stderr.txt
similarity index 100%
copy from test/972-default-imt-collision/expected.txt
copy to test/970-iface-super-resolution-gen/expected-stderr.txt
diff --git a/test/970-iface-super-resolution-gen/expected.txt b/test/970-iface-super-resolution-gen/expected-stdout.txt
similarity index 100%
rename from test/970-iface-super-resolution-gen/expected.txt
rename to test/970-iface-super-resolution-gen/expected-stdout.txt
diff --git a/test/970-iface-super-resolution-gen/info.txt b/test/970-iface-super-resolution-gen/info.txt
index 2cd2cc7..b5a04fd 100644
--- a/test/970-iface-super-resolution-gen/info.txt
+++ b/test/970-iface-super-resolution-gen/info.txt
@@ -13,5 +13,5 @@
 return equivalent output when run multiple times and the expected output should
 be valid.
 
-Do not modify the expected.txt file. It is generated on each run by
+Do not modify the expected-stdout.txt file. It is generated on each run by
 util-src/generate_smali.py.
diff --git a/test/971-iface-super/build b/test/971-iface-super/build
index c8f0384..38e84a5 100755
--- a/test/971-iface-super/build
+++ b/test/971-iface-super/build
@@ -23,14 +23,14 @@
   mkdir -p src
   echo "${JAVAC} \$@" >> ./javac_exec.sh
   # This will use java_exec.sh to execute the javac compiler. It will place the
-  # compiled class files in ./classes and the expected values in expected.txt
+  # compiled class files in ./classes and the expected values in expected-stdout.txt
   #
   # After this the src directory will contain the final versions of all files.
-  ./util-src/generate_java.py ./javac_exec.sh ./src ./classes ./expected.txt ./build_log
+  ./util-src/generate_java.py ./javac_exec.sh ./src ./classes ./expected-stdout.txt ./build_log
 else
   mkdir -p ./smali
-  # Generate the smali files and expected.txt or fail
-  ./util-src/generate_smali.py ./smali ./expected.txt
+  # Generate the smali files and expected-stdout.txt or fail
+  ./util-src/generate_smali.py ./smali ./expected-stdout.txt
   # Use the default build script
   ./default-build "$@" "$EXTRA_ARGS" --experimental default-methods
 fi
diff --git a/test/551-invoke-super/expected.txt b/test/971-iface-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/971-iface-super/expected-stderr.txt
diff --git a/test/971-iface-super/expected.txt b/test/971-iface-super/expected-stdout.txt
similarity index 100%
rename from test/971-iface-super/expected.txt
rename to test/971-iface-super/expected-stdout.txt
diff --git a/test/971-iface-super/info.txt b/test/971-iface-super/info.txt
index bc1c428..e4bd5a7 100644
--- a/test/971-iface-super/info.txt
+++ b/test/971-iface-super/info.txt
@@ -13,5 +13,5 @@
 return equivalent output when run multiple times and the expected output should
 be valid.
 
-Do not modify the expected.txt file. It is generated on each run by
+Do not modify the expected-stdout.txt file. It is generated on each run by
 util-src/generate_smali.py.
diff --git a/test/972-default-imt-collision/expected.txt b/test/972-default-imt-collision/expected-stderr.txt
similarity index 100%
rename from test/972-default-imt-collision/expected.txt
rename to test/972-default-imt-collision/expected-stderr.txt
diff --git a/test/972-default-imt-collision/expected.txt b/test/972-default-imt-collision/expected-stdout.txt
similarity index 100%
copy from test/972-default-imt-collision/expected.txt
copy to test/972-default-imt-collision/expected-stdout.txt
diff --git a/test/972-default-imt-collision/expected.txt b/test/972-iface-super-multidex/expected-stderr.txt
similarity index 100%
copy from test/972-default-imt-collision/expected.txt
copy to test/972-iface-super-multidex/expected-stderr.txt
diff --git a/test/972-iface-super-multidex/expected.txt b/test/972-iface-super-multidex/expected-stdout.txt
similarity index 100%
rename from test/972-iface-super-multidex/expected.txt
rename to test/972-iface-super-multidex/expected-stdout.txt
diff --git a/test/981-dedup-original-dex/expected.txt b/test/973-default-multidex/expected-stderr.txt
similarity index 100%
copy from test/981-dedup-original-dex/expected.txt
copy to test/973-default-multidex/expected-stderr.txt
diff --git a/test/973-default-multidex/expected.txt b/test/973-default-multidex/expected-stdout.txt
similarity index 100%
rename from test/973-default-multidex/expected.txt
rename to test/973-default-multidex/expected-stdout.txt
diff --git a/test/551-invoke-super/expected.txt b/test/974-verify-interface-super/expected-stderr.txt
similarity index 100%
copy from test/551-invoke-super/expected.txt
copy to test/974-verify-interface-super/expected-stderr.txt
diff --git a/test/974-verify-interface-super/expected.txt b/test/974-verify-interface-super/expected-stdout.txt
similarity index 100%
rename from test/974-verify-interface-super/expected.txt
rename to test/974-verify-interface-super/expected-stdout.txt
diff --git a/test/453-not-byte/expected.txt b/test/975-iface-private/expected-stderr.txt
similarity index 100%
copy from test/453-not-byte/expected.txt
copy to test/975-iface-private/expected-stderr.txt
diff --git a/test/975-iface-private/expected.txt b/test/975-iface-private/expected-stdout.txt
similarity index 100%
rename from test/975-iface-private/expected.txt
rename to test/975-iface-private/expected-stdout.txt
diff --git a/test/406-fields/expected.txt b/test/976-conflict-no-methods/expected-stderr.txt
similarity index 100%
copy from test/406-fields/expected.txt
copy to test/976-conflict-no-methods/expected-stderr.txt
diff --git a/test/976-conflict-no-methods/expected.txt b/test/976-conflict-no-methods/expected-stdout.txt
similarity index 100%
rename from test/976-conflict-no-methods/expected.txt
rename to test/976-conflict-no-methods/expected-stdout.txt
diff --git a/test/423-invoke-interface/expected.txt b/test/978-virtual-interface/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/978-virtual-interface/expected-stderr.txt
diff --git a/test/978-virtual-interface/expected.txt b/test/978-virtual-interface/expected-stdout.txt
similarity index 100%
rename from test/978-virtual-interface/expected.txt
rename to test/978-virtual-interface/expected-stdout.txt
diff --git a/test/1911-get-local-var-table/expected.txt b/test/979-const-method-handle/expected-stderr.txt
similarity index 100%
copy from test/1911-get-local-var-table/expected.txt
copy to test/979-const-method-handle/expected-stderr.txt
diff --git a/test/979-const-method-handle/expected.txt b/test/979-const-method-handle/expected-stdout.txt
similarity index 100%
rename from test/979-const-method-handle/expected.txt
rename to test/979-const-method-handle/expected-stdout.txt
diff --git a/test/980-redefine-object/check b/test/980-redefine-object/check
index 6f1e709..80a3cd7 100755
--- a/test/980-redefine-object/check
+++ b/test/980-redefine-object/check
@@ -14,10 +14,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
 # The number of paused background threads (and therefore InterruptedExceptions)
 # can change so we will just delete their lines from the log.
 
 cat "$2" \
-  | sed "/Object allocated of type 'java\.lang\.InterruptedException'/d" \
-  | sed "/Object allocated of type 'java\.lang\.Long'/d" \
-  | diff --strip-trailing-cr -q "$1" - >/dev/null
+    | sed "/Object allocated of type 'java\.lang\.InterruptedException'/d" \
+    | sed "/Object allocated of type 'java\.lang\.Long'/d" \
+    | diff --strip-trailing-cr -q "$1" - >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4" >/dev/null
diff --git a/test/152-dead-large-object/expected.txt b/test/980-redefine-object/expected-stderr.txt
similarity index 100%
copy from test/152-dead-large-object/expected.txt
copy to test/980-redefine-object/expected-stderr.txt
diff --git a/test/980-redefine-object/expected.txt b/test/980-redefine-object/expected-stdout.txt
similarity index 100%
rename from test/980-redefine-object/expected.txt
rename to test/980-redefine-object/expected-stdout.txt
diff --git a/test/980-redefine-object/info.txt b/test/980-redefine-object/info.txt
index f3e01b5..187dc24 100644
--- a/test/980-redefine-object/info.txt
+++ b/test/980-redefine-object/info.txt
@@ -20,4 +20,4 @@
 
 It is also possible it could fail due to the pattern of allocations caused by
 doing string concatenation or printing changing. In this case you should simply
-update the expected.txt file.
+update the expected-stdout.txt file.
diff --git a/test/981-dedup-original-dex/expected.txt b/test/981-dedup-original-dex/expected-stderr.txt
similarity index 100%
rename from test/981-dedup-original-dex/expected.txt
rename to test/981-dedup-original-dex/expected-stderr.txt
diff --git a/test/981-dedup-original-dex/expected.txt b/test/981-dedup-original-dex/expected-stdout.txt
similarity index 100%
copy from test/981-dedup-original-dex/expected.txt
copy to test/981-dedup-original-dex/expected-stdout.txt
diff --git a/test/982-ok-no-retransform/Android.bp b/test/982-ok-no-retransform/Android.bp
new file mode 100644
index 0000000..842071c
--- /dev/null
+++ b/test/982-ok-no-retransform/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `982-ok-no-retransform`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-982-ok-no-retransform",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-982-ok-no-retransform-expected-stdout",
+        ":art-run-test-982-ok-no-retransform-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-982-ok-no-retransform-expected-stdout",
+    out: ["art-run-test-982-ok-no-retransform-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-982-ok-no-retransform-expected-stderr",
+    out: ["art-run-test-982-ok-no-retransform-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/981-dedup-original-dex/expected.txt b/test/982-ok-no-retransform/expected-stderr.txt
similarity index 100%
copy from test/981-dedup-original-dex/expected.txt
copy to test/982-ok-no-retransform/expected-stderr.txt
diff --git a/test/982-ok-no-retransform/expected.txt b/test/982-ok-no-retransform/expected-stdout.txt
similarity index 100%
rename from test/982-ok-no-retransform/expected.txt
rename to test/982-ok-no-retransform/expected-stdout.txt
diff --git a/test/983-source-transform-verify/Android.bp b/test/983-source-transform-verify/Android.bp
new file mode 100644
index 0000000..0260b91
--- /dev/null
+++ b/test/983-source-transform-verify/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `983-source-transform-verify`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-983-source-transform-verify",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-983-source-transform-verify-expected-stdout",
+        ":art-run-test-983-source-transform-verify-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-983-source-transform-verify-expected-stdout",
+    out: ["art-run-test-983-source-transform-verify-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-983-source-transform-verify-expected-stderr",
+    out: ["art-run-test-983-source-transform-verify-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/981-dedup-original-dex/expected.txt b/test/983-source-transform-verify/expected-stderr.txt
similarity index 100%
copy from test/981-dedup-original-dex/expected.txt
copy to test/983-source-transform-verify/expected-stderr.txt
diff --git a/test/983-source-transform-verify/expected.txt b/test/983-source-transform-verify/expected-stdout.txt
similarity index 100%
rename from test/983-source-transform-verify/expected.txt
rename to test/983-source-transform-verify/expected-stdout.txt
diff --git a/test/983-source-transform-verify/source_transform_art.cc b/test/983-source-transform-verify/source_transform_art.cc
index fbf25b8..a1916a0 100644
--- a/test/983-source-transform-verify/source_transform_art.cc
+++ b/test/983-source-transform-verify/source_transform_art.cc
@@ -58,8 +58,7 @@
       for (const DexInstructionPcPair& pair : method.GetInstructions()) {
         const Instruction& inst = pair.Inst();
         int forbidden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
-        if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
-            (inst.GetVerifyExtraFlags() & forbidden_flags) != 0) {
+        if ((inst.GetVerifyExtraFlags() & forbidden_flags) != 0) {
           LOG(FATAL) << "Unexpected instruction found in " << dex->PrettyMethod(method.GetIndex())
                      << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : "
                      << inst.DumpString(dex.get()) << std::endl;
diff --git a/test/984-obsolete-invoke/Android.bp b/test/984-obsolete-invoke/Android.bp
new file mode 100644
index 0000000..fcc2af1
--- /dev/null
+++ b/test/984-obsolete-invoke/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `984-obsolete-invoke`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-984-obsolete-invoke",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-984-obsolete-invoke-expected-stdout",
+        ":art-run-test-984-obsolete-invoke-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-984-obsolete-invoke-expected-stdout",
+    out: ["art-run-test-984-obsolete-invoke-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-984-obsolete-invoke-expected-stderr",
+    out: ["art-run-test-984-obsolete-invoke-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/683-clinit-inline-static-invoke/expected.txt b/test/984-obsolete-invoke/expected-stderr.txt
similarity index 100%
copy from test/683-clinit-inline-static-invoke/expected.txt
copy to test/984-obsolete-invoke/expected-stderr.txt
diff --git a/test/984-obsolete-invoke/expected.txt b/test/984-obsolete-invoke/expected-stdout.txt
similarity index 100%
rename from test/984-obsolete-invoke/expected.txt
rename to test/984-obsolete-invoke/expected-stdout.txt
diff --git a/test/985-re-obsolete/Android.bp b/test/985-re-obsolete/Android.bp
new file mode 100644
index 0000000..90ba51a
--- /dev/null
+++ b/test/985-re-obsolete/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `985-re-obsolete`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-985-re-obsolete",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-985-re-obsolete-expected-stdout",
+        ":art-run-test-985-re-obsolete-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-985-re-obsolete-expected-stdout",
+    out: ["art-run-test-985-re-obsolete-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-985-re-obsolete-expected-stderr",
+    out: ["art-run-test-985-re-obsolete-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/453-not-byte/expected.txt b/test/985-re-obsolete/expected-stderr.txt
similarity index 100%
copy from test/453-not-byte/expected.txt
copy to test/985-re-obsolete/expected-stderr.txt
diff --git a/test/985-re-obsolete/expected.txt b/test/985-re-obsolete/expected-stdout.txt
similarity index 100%
rename from test/985-re-obsolete/expected.txt
rename to test/985-re-obsolete/expected-stdout.txt
diff --git a/test/986-native-method-bind/Android.bp b/test/986-native-method-bind/Android.bp
new file mode 100644
index 0000000..673d786
--- /dev/null
+++ b/test/986-native-method-bind/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `986-native-method-bind`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-986-native-method-bind",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-986-native-method-bind-expected-stdout",
+        ":art-run-test-986-native-method-bind-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-986-native-method-bind-expected-stdout",
+    out: ["art-run-test-986-native-method-bind-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-986-native-method-bind-expected-stderr",
+    out: ["art-run-test-986-native-method-bind-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/986-native-method-bind/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/986-native-method-bind/expected-stderr.txt
diff --git a/test/986-native-method-bind/expected.txt b/test/986-native-method-bind/expected-stdout.txt
similarity index 100%
rename from test/986-native-method-bind/expected.txt
rename to test/986-native-method-bind/expected-stdout.txt
diff --git a/test/987-agent-bind/Android.bp b/test/987-agent-bind/Android.bp
new file mode 100644
index 0000000..99ed3d8
--- /dev/null
+++ b/test/987-agent-bind/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `987-agent-bind`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-987-agent-bind",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-987-agent-bind-expected-stdout",
+        ":art-run-test-987-agent-bind-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-987-agent-bind-expected-stdout",
+    out: ["art-run-test-987-agent-bind-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-987-agent-bind-expected-stderr",
+    out: ["art-run-test-987-agent-bind-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/1902-suspend/expected.txt b/test/987-agent-bind/expected-stderr.txt
similarity index 100%
copy from test/1902-suspend/expected.txt
copy to test/987-agent-bind/expected-stderr.txt
diff --git a/test/987-agent-bind/expected.txt b/test/987-agent-bind/expected-stdout.txt
similarity index 100%
rename from test/987-agent-bind/expected.txt
rename to test/987-agent-bind/expected-stdout.txt
diff --git a/test/988-method-trace/Android.bp b/test/988-method-trace/Android.bp
new file mode 100644
index 0000000..c5f607d
--- /dev/null
+++ b/test/988-method-trace/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `988-method-trace`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-988-method-trace",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-988-method-trace-expected-stdout",
+        ":art-run-test-988-method-trace-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-988-method-trace-expected-stdout",
+    out: ["art-run-test-988-method-trace-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-988-method-trace-expected-stderr",
+    out: ["art-run-test-988-method-trace-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/423-invoke-interface/expected.txt b/test/988-method-trace/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/988-method-trace/expected-stderr.txt
diff --git a/test/988-method-trace/expected-stdout.txt b/test/988-method-trace/expected-stdout.txt
new file mode 100644
index 0000000..f82b392
--- /dev/null
+++ b/test/988-method-trace/expected-stdout.txt
@@ -0,0 +1,533 @@
+.<= public static void art.Trace.enableTracing(java.lang.Class,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.Thread) -> <null: null>
+<= public static void art.Trace.enableMethodTracing(java.lang.Class,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.Thread) -> <null: null>
+=> art.Test988$IterOp()
+.=> public java.lang.Object()
+.<= public java.lang.Object() -> <null: null>
+<= art.Test988$IterOp() -> <null: null>
+=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
+.=> public int art.Test988$IterOp.applyAsInt(int)
+..=> static int art.Test988.iter_fibonacci(int)
+..<= static int art.Test988.iter_fibonacci(int) -> <class java.lang.Integer: 832040>
+.<= public int art.Test988$IterOp.applyAsInt(int) -> <class java.lang.Integer: 832040>
+.=> public art.Test988$FibResult(java.lang.String,int,int)
+..=> public java.lang.Object()
+..<= public java.lang.Object() -> <null: null>
+.<= public art.Test988$FibResult(java.lang.String,int,int) -> <null: null>
+.=> public boolean java.util.ArrayList.add(java.lang.Object)
+..=> private void java.util.ArrayList.ensureCapacityInternal(int)
+...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
+...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
+..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
+fibonacci(30)=832040
+.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
+<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
+=> art.Test988$RecurOp()
+.=> public java.lang.Object()
+.<= public java.lang.Object() -> <null: null>
+<= art.Test988$RecurOp() -> <null: null>
+=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
+.=> public int art.Test988$RecurOp.applyAsInt(int)
+..=> static int art.Test988.fibonacci(int)
+...=> static int art.Test988.fibonacci(int)
+....=> static int art.Test988.fibonacci(int)
+.....=> static int art.Test988.fibonacci(int)
+......=> static int art.Test988.fibonacci(int)
+......<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
+......=> static int art.Test988.fibonacci(int)
+......<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 0>
+.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
+.....=> static int art.Test988.fibonacci(int)
+.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
+....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 2>
+....=> static int art.Test988.fibonacci(int)
+.....=> static int art.Test988.fibonacci(int)
+.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
+.....=> static int art.Test988.fibonacci(int)
+.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 0>
+....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
+...<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 3>
+...=> static int art.Test988.fibonacci(int)
+....=> static int art.Test988.fibonacci(int)
+.....=> static int art.Test988.fibonacci(int)
+.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
+.....=> static int art.Test988.fibonacci(int)
+.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 0>
+....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
+....=> static int art.Test988.fibonacci(int)
+....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
+...<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 2>
+..<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 5>
+.<= public int art.Test988$RecurOp.applyAsInt(int) -> <class java.lang.Integer: 5>
+.=> public art.Test988$FibResult(java.lang.String,int,int)
+..=> public java.lang.Object()
+..<= public java.lang.Object() -> <null: null>
+.<= public art.Test988$FibResult(java.lang.String,int,int) -> <null: null>
+.=> public boolean java.util.ArrayList.add(java.lang.Object)
+..=> private void java.util.ArrayList.ensureCapacityInternal(int)
+...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
+...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
+..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
+fibonacci(5)=5
+.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
+<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
+=> art.Test988$NativeOp()
+.=> public java.lang.Object()
+.<= public java.lang.Object() -> <null: null>
+<= art.Test988$NativeOp() -> <null: null>
+=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
+.=> public int art.Test988$NativeOp.applyAsInt(int)
+..=> static int art.Test988.nativeFibonacci(int)
+..<= static int art.Test988.nativeFibonacci(int) -> <class java.lang.Integer: 5>
+.<= public int art.Test988$NativeOp.applyAsInt(int) -> <class java.lang.Integer: 5>
+.=> public art.Test988$FibResult(java.lang.String,int,int)
+..=> public java.lang.Object()
+..<= public java.lang.Object() -> <null: null>
+.<= public art.Test988$FibResult(java.lang.String,int,int) -> <null: null>
+.=> public boolean java.util.ArrayList.add(java.lang.Object)
+..=> private void java.util.ArrayList.ensureCapacityInternal(int)
+...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
+...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
+..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
+fibonacci(5)=5
+.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
+<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
+=> art.Test988$IterOp()
+.=> public java.lang.Object()
+.<= public java.lang.Object() -> <null: null>
+<= art.Test988$IterOp() -> <null: null>
+=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
+.=> public int art.Test988$IterOp.applyAsInt(int)
+..=> static int art.Test988.iter_fibonacci(int)
+...=> public java.lang.StringBuilder()
+....=> java.lang.AbstractStringBuilder(int)
+.....=> public java.lang.Object()
+.....<= public java.lang.Object() -> <null: null>
+....<= java.lang.AbstractStringBuilder(int) -> <null: null>
+...<= public java.lang.StringBuilder() -> <null: null>
+...=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
+....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String)
+.....=> public int java.lang.String.length()
+.....<= public int java.lang.String.length() -> <class java.lang.Integer: 14>
+.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
+.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
+.....=> public void java.lang.String.getChars(int,int,char[],int)
+......=> public int java.lang.String.length()
+......<= public int java.lang.String.length() -> <class java.lang.Integer: 14>
+......=> native void java.lang.String.getCharsNoCheck(int,int,char[],int)
+......<= native void java.lang.String.getCharsNoCheck(int,int,char[],int) -> <null: null>
+.....<= public void java.lang.String.getChars(int,int,char[],int) -> <null: null>
+....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...=> public java.lang.StringBuilder java.lang.StringBuilder.append(int)
+....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(int)
+.....=> static int java.lang.Integer.stringSize(int)
+.....<= static int java.lang.Integer.stringSize(int) -> <class java.lang.Integer: 2>
+.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
+......=> private int java.lang.AbstractStringBuilder.newCapacity(int)
+......<= private int java.lang.AbstractStringBuilder.newCapacity(int) -> <class java.lang.Integer: 34>
+......=> public static char[] java.util.Arrays.copyOf(char[],int)
+.......=> public static int java.lang.Math.min(int,int)
+.......<= public static int java.lang.Math.min(int,int) -> <class java.lang.Integer: 16>
+.......=> public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
+.......<= public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int) -> <null: null>
+......<= public static char[] java.util.Arrays.copyOf(char[],int) -> <class [C: [B, a, d,  , a, r, g, u, m, e, n, t, :,  , -, 1, 9,  , <,  , 0, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>]>
+.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
+.....=> static void java.lang.Integer.getChars(int,int,char[])
+.....<= static void java.lang.Integer.getChars(int,int,char[]) -> <null: null>
+....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(int) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...<= public java.lang.StringBuilder java.lang.StringBuilder.append(int) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
+....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String)
+.....=> public int java.lang.String.length()
+.....<= public int java.lang.String.length() -> <class java.lang.Integer: 4>
+.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
+.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
+.....=> public void java.lang.String.getChars(int,int,char[],int)
+......=> public int java.lang.String.length()
+......<= public int java.lang.String.length() -> <class java.lang.Integer: 4>
+......=> native void java.lang.String.getCharsNoCheck(int,int,char[],int)
+......<= native void java.lang.String.getCharsNoCheck(int,int,char[],int) -> <null: null>
+.....<= public void java.lang.String.getChars(int,int,char[],int) -> <null: null>
+....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...=> public java.lang.String java.lang.StringBuilder.toString()
+....=> public static java.lang.String java.lang.StringFactory.newStringFromChars(char[],int,int)
+.....=> static java.lang.String java.lang.StringFactory.newStringFromChars(int,int,char[])
+.....<= static java.lang.String java.lang.StringFactory.newStringFromChars(int,int,char[]) -> <class java.lang.String: Bad argument: -19 < 0>
+....<= public static java.lang.String java.lang.StringFactory.newStringFromChars(char[],int,int) -> <class java.lang.String: Bad argument: -19 < 0>
+...<= public java.lang.String java.lang.StringBuilder.toString() -> <class java.lang.String: Bad argument: -19 < 0>
+...=> public java.lang.Error(java.lang.String)
+....=> public java.lang.Throwable(java.lang.String)
+.....=> public java.lang.Object()
+.....<= public java.lang.Object() -> <null: null>
+.....=> public static final java.util.List java.util.Collections.emptyList()
+.....<= public static final java.util.List java.util.Collections.emptyList() -> <class java.util.Collections$EmptyList: []>
+.....=> public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace()
+......=> private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace()
+......<= private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace() -> <class [Ljava.lang.Object;: <non-deterministic>>
+.....<= public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace() -> <class java.lang.Error: java.lang.Error: Bad argument: -19 < 0
+	art.Test988.iter_fibonacci(Test988.java:269)
+	art.Test988$IterOp.applyAsInt(Test988.java:264)
+	art.Test988.doFibTest(Test988.java:402)
+	art.Test988.run(Test988.java:358)
+	<additional hidden frames>
+>
+....<= public java.lang.Throwable(java.lang.String) -> <null: null>
+...<= public java.lang.Error(java.lang.String) -> <null: null>
+..<= static int art.Test988.iter_fibonacci(int) EXCEPTION
+.<= public int art.Test988$IterOp.applyAsInt(int) EXCEPTION
+.=> public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable)
+..=> public java.lang.Object()
+..<= public java.lang.Object() -> <null: null>
+.<= public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable) -> <null: null>
+.=> public boolean java.util.ArrayList.add(java.lang.Object)
+..=> private void java.util.ArrayList.ensureCapacityInternal(int)
+...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
+...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
+..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
+fibonacci(-19) -> java.lang.Error: Bad argument: -19 < 0
+	art.Test988.iter_fibonacci(Test988.java:269)
+	art.Test988$IterOp.applyAsInt(Test988.java:264)
+	art.Test988.doFibTest(Test988.java:402)
+	art.Test988.run(Test988.java:358)
+	<additional hidden frames>
+
+.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
+<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
+=> art.Test988$RecurOp()
+.=> public java.lang.Object()
+.<= public java.lang.Object() -> <null: null>
+<= art.Test988$RecurOp() -> <null: null>
+=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
+.=> public int art.Test988$RecurOp.applyAsInt(int)
+..=> static int art.Test988.fibonacci(int)
+...=> public java.lang.StringBuilder()
+....=> java.lang.AbstractStringBuilder(int)
+.....=> public java.lang.Object()
+.....<= public java.lang.Object() -> <null: null>
+....<= java.lang.AbstractStringBuilder(int) -> <null: null>
+...<= public java.lang.StringBuilder() -> <null: null>
+...=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
+....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String)
+.....=> public int java.lang.String.length()
+.....<= public int java.lang.String.length() -> <class java.lang.Integer: 14>
+.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
+.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
+.....=> public void java.lang.String.getChars(int,int,char[],int)
+......=> public int java.lang.String.length()
+......<= public int java.lang.String.length() -> <class java.lang.Integer: 14>
+......=> native void java.lang.String.getCharsNoCheck(int,int,char[],int)
+......<= native void java.lang.String.getCharsNoCheck(int,int,char[],int) -> <null: null>
+.....<= public void java.lang.String.getChars(int,int,char[],int) -> <null: null>
+....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...=> public java.lang.StringBuilder java.lang.StringBuilder.append(int)
+....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(int)
+.....=> static int java.lang.Integer.stringSize(int)
+.....<= static int java.lang.Integer.stringSize(int) -> <class java.lang.Integer: 2>
+.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
+......=> private int java.lang.AbstractStringBuilder.newCapacity(int)
+......<= private int java.lang.AbstractStringBuilder.newCapacity(int) -> <class java.lang.Integer: 34>
+......=> public static char[] java.util.Arrays.copyOf(char[],int)
+.......=> public static int java.lang.Math.min(int,int)
+.......<= public static int java.lang.Math.min(int,int) -> <class java.lang.Integer: 16>
+.......=> public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
+.......<= public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int) -> <null: null>
+......<= public static char[] java.util.Arrays.copyOf(char[],int) -> <class [C: [B, a, d,  , a, r, g, u, m, e, n, t, :,  , -, 1, 9,  , <,  , 0, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>]>
+.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
+.....=> static void java.lang.Integer.getChars(int,int,char[])
+.....<= static void java.lang.Integer.getChars(int,int,char[]) -> <null: null>
+....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(int) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...<= public java.lang.StringBuilder java.lang.StringBuilder.append(int) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
+....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String)
+.....=> public int java.lang.String.length()
+.....<= public int java.lang.String.length() -> <class java.lang.Integer: 4>
+.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
+.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
+.....=> public void java.lang.String.getChars(int,int,char[],int)
+......=> public int java.lang.String.length()
+......<= public int java.lang.String.length() -> <class java.lang.Integer: 4>
+......=> native void java.lang.String.getCharsNoCheck(int,int,char[],int)
+......<= native void java.lang.String.getCharsNoCheck(int,int,char[],int) -> <null: null>
+.....<= public void java.lang.String.getChars(int,int,char[],int) -> <null: null>
+....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
+...=> public java.lang.String java.lang.StringBuilder.toString()
+....=> public static java.lang.String java.lang.StringFactory.newStringFromChars(char[],int,int)
+.....=> static java.lang.String java.lang.StringFactory.newStringFromChars(int,int,char[])
+.....<= static java.lang.String java.lang.StringFactory.newStringFromChars(int,int,char[]) -> <class java.lang.String: Bad argument: -19 < 0>
+....<= public static java.lang.String java.lang.StringFactory.newStringFromChars(char[],int,int) -> <class java.lang.String: Bad argument: -19 < 0>
+...<= public java.lang.String java.lang.StringBuilder.toString() -> <class java.lang.String: Bad argument: -19 < 0>
+...=> public java.lang.Error(java.lang.String)
+....=> public java.lang.Throwable(java.lang.String)
+.....=> public java.lang.Object()
+.....<= public java.lang.Object() -> <null: null>
+.....=> public static final java.util.List java.util.Collections.emptyList()
+.....<= public static final java.util.List java.util.Collections.emptyList() -> <class java.util.Collections$EmptyList: []>
+.....=> public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace()
+......=> private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace()
+......<= private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace() -> <class [Ljava.lang.Object;: <non-deterministic>>
+.....<= public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace() -> <class java.lang.Error: java.lang.Error: Bad argument: -19 < 0
+	art.Test988.fibonacci(Test988.java:291)
+	art.Test988$RecurOp.applyAsInt(Test988.java:286)
+	art.Test988.doFibTest(Test988.java:402)
+	art.Test988.run(Test988.java:359)
+	<additional hidden frames>
+>
+....<= public java.lang.Throwable(java.lang.String) -> <null: null>
+...<= public java.lang.Error(java.lang.String) -> <null: null>
+..<= static int art.Test988.fibonacci(int) EXCEPTION
+.<= public int art.Test988$RecurOp.applyAsInt(int) EXCEPTION
+.=> public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable)
+..=> public java.lang.Object()
+..<= public java.lang.Object() -> <null: null>
+.<= public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable) -> <null: null>
+.=> public boolean java.util.ArrayList.add(java.lang.Object)
+..=> private void java.util.ArrayList.ensureCapacityInternal(int)
+...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
+...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
+..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
+fibonacci(-19) -> java.lang.Error: Bad argument: -19 < 0
+	art.Test988.fibonacci(Test988.java:291)
+	art.Test988$RecurOp.applyAsInt(Test988.java:286)
+	art.Test988.doFibTest(Test988.java:402)
+	art.Test988.run(Test988.java:359)
+	<additional hidden frames>
+
+.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
+<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
+=> art.Test988$NativeOp()
+.=> public java.lang.Object()
+.<= public java.lang.Object() -> <null: null>
+<= art.Test988$NativeOp() -> <null: null>
+=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
+.=> public int art.Test988$NativeOp.applyAsInt(int)
+..=> static int art.Test988.nativeFibonacci(int)
+...=> public java.lang.Error(java.lang.String)
+....=> public java.lang.Throwable(java.lang.String)
+.....=> public java.lang.Object()
+.....<= public java.lang.Object() -> <null: null>
+.....=> public static final java.util.List java.util.Collections.emptyList()
+.....<= public static final java.util.List java.util.Collections.emptyList() -> <class java.util.Collections$EmptyList: []>
+.....=> public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace()
+......=> private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace()
+......<= private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace() -> <class [Ljava.lang.Object;: <non-deterministic>>
+.....<= public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace() -> <class java.lang.Error: java.lang.Error: bad argument
+	art.Test988.nativeFibonacci(Native Method)
+	art.Test988$NativeOp.applyAsInt(Test988.java:301)
+	art.Test988.doFibTest(Test988.java:402)
+	art.Test988.run(Test988.java:360)
+	<additional hidden frames>
+>
+....<= public java.lang.Throwable(java.lang.String) -> <null: null>
+...<= public java.lang.Error(java.lang.String) -> <null: null>
+..<= static int art.Test988.nativeFibonacci(int) EXCEPTION
+.<= public int art.Test988$NativeOp.applyAsInt(int) EXCEPTION
+.=> public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable)
+..=> public java.lang.Object()
+..<= public java.lang.Object() -> <null: null>
+.<= public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable) -> <null: null>
+.=> public boolean java.util.ArrayList.add(java.lang.Object)
+..=> private void java.util.ArrayList.ensureCapacityInternal(int)
+...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
+...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
+..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
+fibonacci(-19) -> java.lang.Error: bad argument
+	art.Test988.nativeFibonacci(Native Method)
+	art.Test988$NativeOp.applyAsInt(Test988.java:301)
+	art.Test988.doFibTest(Test988.java:402)
+	art.Test988.run(Test988.java:360)
+	<additional hidden frames>
+
+.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
+<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
+=> public final void <non-deterministic-type 0>.run()
+.=> private static java.lang.Object java.lang.reflect.Proxy.invoke(java.lang.reflect.Proxy,java.lang.reflect.Method,java.lang.Object[]) throws java.lang.Throwable
+..=> public java.lang.Object art.Test988$TestRunnableInvokeHandler.invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[]) throws java.lang.Throwable
+..<= public java.lang.Object art.Test988$TestRunnableInvokeHandler.invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[]) throws java.lang.Throwable -> <null: null>
+.<= private static java.lang.Object java.lang.reflect.Proxy.invoke(java.lang.reflect.Proxy,java.lang.reflect.Method,java.lang.Object[]) throws java.lang.Throwable -> <null: null>
+<= public final void <non-deterministic-type 0>.run() -> <null: null>
+=> static void art.Test988$IntrinsicsTest.doTest()
+.=> static void art.Test988Intrinsics.test()
+..=> public static long java.lang.Double.doubleToRawLongBits(double)
+..<= public static long java.lang.Double.doubleToRawLongBits(double) -> <class java.lang.Long: 0>
+..=> public static long java.lang.Double.doubleToLongBits(double)
+..<= public static long java.lang.Double.doubleToLongBits(double) -> <class java.lang.Long: 0>
+..=> public static boolean java.lang.Double.isInfinite(double)
+..<= public static boolean java.lang.Double.isInfinite(double) -> <class java.lang.Boolean: false>
+..=> public static boolean java.lang.Double.isNaN(double)
+..<= public static boolean java.lang.Double.isNaN(double) -> <class java.lang.Boolean: false>
+..=> public static double java.lang.Double.longBitsToDouble(long)
+..<= public static double java.lang.Double.longBitsToDouble(long) -> <class java.lang.Double: 0.0>
+..=> public static int java.lang.Float.floatToRawIntBits(float)
+..<= public static int java.lang.Float.floatToRawIntBits(float) -> <class java.lang.Integer: 0>
+..=> public static int java.lang.Float.floatToIntBits(float)
+..<= public static int java.lang.Float.floatToIntBits(float) -> <class java.lang.Integer: 0>
+..=> public static boolean java.lang.Float.isInfinite(float)
+..<= public static boolean java.lang.Float.isInfinite(float) -> <class java.lang.Boolean: false>
+..=> public static boolean java.lang.Float.isNaN(float)
+..<= public static boolean java.lang.Float.isNaN(float) -> <class java.lang.Boolean: false>
+..=> public static float java.lang.Float.intBitsToFloat(int)
+..<= public static float java.lang.Float.intBitsToFloat(int) -> <class java.lang.Float: 0.0>
+..=> public static int java.lang.Integer.reverse(int)
+..<= public static int java.lang.Integer.reverse(int) -> <class java.lang.Integer: 0>
+..=> public static int java.lang.Integer.reverseBytes(int)
+..<= public static int java.lang.Integer.reverseBytes(int) -> <class java.lang.Integer: 0>
+..=> public static int java.lang.Integer.bitCount(int)
+..<= public static int java.lang.Integer.bitCount(int) -> <class java.lang.Integer: 0>
+..=> public static int java.lang.Integer.compare(int,int)
+..<= public static int java.lang.Integer.compare(int,int) -> <class java.lang.Integer: 0>
+..=> public static int java.lang.Integer.highestOneBit(int)
+..<= public static int java.lang.Integer.highestOneBit(int) -> <class java.lang.Integer: 0>
+..=> public static int java.lang.Integer.lowestOneBit(int)
+..<= public static int java.lang.Integer.lowestOneBit(int) -> <class java.lang.Integer: 0>
+..=> public static int java.lang.Integer.numberOfLeadingZeros(int)
+..<= public static int java.lang.Integer.numberOfLeadingZeros(int) -> <class java.lang.Integer: 32>
+..=> public static int java.lang.Integer.numberOfTrailingZeros(int)
+..<= public static int java.lang.Integer.numberOfTrailingZeros(int) -> <class java.lang.Integer: 32>
+..=> public static int java.lang.Integer.rotateRight(int,int)
+..<= public static int java.lang.Integer.rotateRight(int,int) -> <class java.lang.Integer: 0>
+..=> public static int java.lang.Integer.rotateLeft(int,int)
+..<= public static int java.lang.Integer.rotateLeft(int,int) -> <class java.lang.Integer: 0>
+..=> public static int java.lang.Integer.signum(int)
+..<= public static int java.lang.Integer.signum(int) -> <class java.lang.Integer: 0>
+..=> public static long java.lang.Long.reverse(long)
+..<= public static long java.lang.Long.reverse(long) -> <class java.lang.Long: 0>
+..=> public static long java.lang.Long.reverseBytes(long)
+..<= public static long java.lang.Long.reverseBytes(long) -> <class java.lang.Long: 0>
+..=> public static int java.lang.Long.bitCount(long)
+..<= public static int java.lang.Long.bitCount(long) -> <class java.lang.Integer: 0>
+..=> public static int java.lang.Long.compare(long,long)
+..<= public static int java.lang.Long.compare(long,long) -> <class java.lang.Integer: 0>
+..=> public static long java.lang.Long.highestOneBit(long)
+..<= public static long java.lang.Long.highestOneBit(long) -> <class java.lang.Long: 0>
+..=> public static long java.lang.Long.lowestOneBit(long)
+..<= public static long java.lang.Long.lowestOneBit(long) -> <class java.lang.Long: 0>
+..=> public static int java.lang.Long.numberOfLeadingZeros(long)
+..<= public static int java.lang.Long.numberOfLeadingZeros(long) -> <class java.lang.Integer: 64>
+..=> public static int java.lang.Long.numberOfTrailingZeros(long)
+..<= public static int java.lang.Long.numberOfTrailingZeros(long) -> <class java.lang.Integer: 64>
+..=> public static long java.lang.Long.rotateRight(long,int)
+..<= public static long java.lang.Long.rotateRight(long,int) -> <class java.lang.Long: 0>
+..=> public static long java.lang.Long.rotateLeft(long,int)
+..<= public static long java.lang.Long.rotateLeft(long,int) -> <class java.lang.Long: 0>
+..=> public static int java.lang.Long.signum(long)
+..<= public static int java.lang.Long.signum(long) -> <class java.lang.Integer: 0>
+..=> public static short java.lang.Short.reverseBytes(short)
+..<= public static short java.lang.Short.reverseBytes(short) -> <class java.lang.Short: 0>
+..=> public static double java.lang.Math.abs(double)
+..<= public static double java.lang.Math.abs(double) -> <class java.lang.Double: 0.0>
+..=> public static float java.lang.Math.abs(float)
+..<= public static float java.lang.Math.abs(float) -> <class java.lang.Float: 0.0>
+..=> public static long java.lang.Math.abs(long)
+..<= public static long java.lang.Math.abs(long) -> <class java.lang.Long: 0>
+..=> public static int java.lang.Math.abs(int)
+..<= public static int java.lang.Math.abs(int) -> <class java.lang.Integer: 0>
+..=> public static double java.lang.Math.min(double,double)
+..<= public static double java.lang.Math.min(double,double) -> <class java.lang.Double: 0.0>
+..=> public static float java.lang.Math.min(float,float)
+..<= public static float java.lang.Math.min(float,float) -> <class java.lang.Float: 0.0>
+..=> public static long java.lang.Math.min(long,long)
+..<= public static long java.lang.Math.min(long,long) -> <class java.lang.Long: 0>
+..=> public static int java.lang.Math.min(int,int)
+..<= public static int java.lang.Math.min(int,int) -> <class java.lang.Integer: 0>
+..=> public static double java.lang.Math.max(double,double)
+..<= public static double java.lang.Math.max(double,double) -> <class java.lang.Double: 0.0>
+..=> public static float java.lang.Math.max(float,float)
+..<= public static float java.lang.Math.max(float,float) -> <class java.lang.Float: 0.0>
+..=> public static long java.lang.Math.max(long,long)
+..<= public static long java.lang.Math.max(long,long) -> <class java.lang.Long: 0>
+..=> public static int java.lang.Math.max(int,int)
+..<= public static int java.lang.Math.max(int,int) -> <class java.lang.Integer: 0>
+..=> public static double java.lang.Math.cos(double)
+..<= public static double java.lang.Math.cos(double) -> <class java.lang.Double: 1.0>
+..=> public static double java.lang.Math.sin(double)
+..<= public static double java.lang.Math.sin(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.acos(double)
+..<= public static double java.lang.Math.acos(double) -> <class java.lang.Double: 1.5707963267948966>
+..=> public static double java.lang.Math.asin(double)
+..<= public static double java.lang.Math.asin(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.atan(double)
+..<= public static double java.lang.Math.atan(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.atan2(double,double)
+..<= public static double java.lang.Math.atan2(double,double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.cbrt(double)
+..<= public static double java.lang.Math.cbrt(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.cosh(double)
+..<= public static double java.lang.Math.cosh(double) -> <class java.lang.Double: 1.0>
+..=> public static double java.lang.Math.exp(double)
+..<= public static double java.lang.Math.exp(double) -> <class java.lang.Double: 1.0>
+..=> public static double java.lang.Math.expm1(double)
+..<= public static double java.lang.Math.expm1(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.hypot(double,double)
+..<= public static double java.lang.Math.hypot(double,double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.log(double)
+..<= public static double java.lang.Math.log(double) -> <class java.lang.Double: -Infinity>
+..=> public static double java.lang.Math.log10(double)
+..<= public static double java.lang.Math.log10(double) -> <class java.lang.Double: -Infinity>
+..=> public static double java.lang.Math.nextAfter(double,double)
+..<= public static double java.lang.Math.nextAfter(double,double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.sinh(double)
+..<= public static double java.lang.Math.sinh(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.tan(double)
+..<= public static double java.lang.Math.tan(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.tanh(double)
+..<= public static double java.lang.Math.tanh(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.sqrt(double)
+..<= public static double java.lang.Math.sqrt(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.ceil(double)
+..<= public static double java.lang.Math.ceil(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.floor(double)
+..<= public static double java.lang.Math.floor(double) -> <class java.lang.Double: 0.0>
+..=> public static double java.lang.Math.rint(double)
+..<= public static double java.lang.Math.rint(double) -> <class java.lang.Double: 0.0>
+..=> public static long java.lang.Math.round(double)
+..<= public static long java.lang.Math.round(double) -> <class java.lang.Long: 0>
+..=> public static int java.lang.Math.round(float)
+..<= public static int java.lang.Math.round(float) -> <class java.lang.Integer: 0>
+..=> public static java.lang.Thread java.lang.Thread.currentThread()
+..<= public static java.lang.Thread java.lang.Thread.currentThread() -> <<non-deterministic>: <non-deterministic>>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: s>
+..=> public int java.lang.String.compareTo(java.lang.String)
+..<= public int java.lang.String.compareTo(java.lang.String) -> <class java.lang.Integer: 11>
+..=> public boolean java.lang.String.equals(java.lang.Object)
+..<= public boolean java.lang.String.equals(java.lang.Object) -> <class java.lang.Boolean: false>
+..=> public int java.lang.String.indexOf(int)
+..<= public int java.lang.String.indexOf(int) -> <class java.lang.Integer: -1>
+..=> public int java.lang.String.indexOf(int,int)
+..<= public int java.lang.String.indexOf(int,int) -> <class java.lang.Integer: -1>
+..=> public int java.lang.String.indexOf(java.lang.String)
+..<= public int java.lang.String.indexOf(java.lang.String) -> <class java.lang.Integer: -1>
+..=> public int java.lang.String.indexOf(java.lang.String,int)
+..<= public int java.lang.String.indexOf(java.lang.String,int) -> <class java.lang.Integer: -1>
+..=> public boolean java.lang.String.isEmpty()
+..<= public boolean java.lang.String.isEmpty() -> <class java.lang.Boolean: false>
+..=> public int java.lang.String.length()
+..<= public int java.lang.String.length() -> <class java.lang.Integer: 17>
+..=> public synchronized java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String)
+..<= public synchronized java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String) -> <class java.lang.StringBuffer: some large string bufferhello>
+..=> public synchronized int java.lang.StringBuffer.length()
+..<= public synchronized int java.lang.StringBuffer.length() -> <class java.lang.Integer: 29>
+..=> public synchronized java.lang.String java.lang.StringBuffer.toString()
+..<= public synchronized java.lang.String java.lang.StringBuffer.toString() -> <class java.lang.String: some large string bufferhello>
+..=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
+..<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: some large string builderhello>
+..=> public int java.lang.StringBuilder.length()
+..<= public int java.lang.StringBuilder.length() -> <class java.lang.Integer: 30>
+..=> public java.lang.String java.lang.StringBuilder.toString()
+..<= public java.lang.String java.lang.StringBuilder.toString() -> <class java.lang.String: some large string builderhello>
+..=> public static java.lang.Integer java.lang.Integer.valueOf(int)
+..<= public static java.lang.Integer java.lang.Integer.valueOf(int) -> <class java.lang.Integer: 0>
+..=> public static boolean java.lang.Thread.interrupted()
+..<= public static boolean java.lang.Thread.interrupted() -> <class java.lang.Boolean: false>
+.<= static void art.Test988Intrinsics.test() -> <null: null>
+.=> public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
+.<= public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int) -> <null: null>
+.=> public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
+.<= public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int) -> <null: null>
+<= static void art.Test988$IntrinsicsTest.doTest() -> <null: null>
+=> public static java.lang.Thread java.lang.Thread.currentThread()
+<= public static java.lang.Thread java.lang.Thread.currentThread() -> <<non-deterministic>: <non-deterministic>>
+=> public static void art.Trace.disableTracing(java.lang.Thread)
diff --git a/test/988-method-trace/expected.txt b/test/988-method-trace/expected.txt
deleted file mode 100644
index b263308..0000000
--- a/test/988-method-trace/expected.txt
+++ /dev/null
@@ -1,533 +0,0 @@
-.<= public static void art.Trace.enableTracing(java.lang.Class,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.Thread) -> <null: null>
-<= public static void art.Trace.enableMethodTracing(java.lang.Class,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.Thread) -> <null: null>
-=> art.Test988$IterOp()
-.=> public java.lang.Object()
-.<= public java.lang.Object() -> <null: null>
-<= art.Test988$IterOp() -> <null: null>
-=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
-.=> public int art.Test988$IterOp.applyAsInt(int)
-..=> static int art.Test988.iter_fibonacci(int)
-..<= static int art.Test988.iter_fibonacci(int) -> <class java.lang.Integer: 832040>
-.<= public int art.Test988$IterOp.applyAsInt(int) -> <class java.lang.Integer: 832040>
-.=> public art.Test988$FibResult(java.lang.String,int,int)
-..=> public java.lang.Object()
-..<= public java.lang.Object() -> <null: null>
-.<= public art.Test988$FibResult(java.lang.String,int,int) -> <null: null>
-.=> public boolean java.util.ArrayList.add(java.lang.Object)
-..=> private void java.util.ArrayList.ensureCapacityInternal(int)
-...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
-...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
-..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
-fibonacci(30)=832040
-.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
-<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
-=> art.Test988$RecurOp()
-.=> public java.lang.Object()
-.<= public java.lang.Object() -> <null: null>
-<= art.Test988$RecurOp() -> <null: null>
-=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
-.=> public int art.Test988$RecurOp.applyAsInt(int)
-..=> static int art.Test988.fibonacci(int)
-...=> static int art.Test988.fibonacci(int)
-....=> static int art.Test988.fibonacci(int)
-.....=> static int art.Test988.fibonacci(int)
-......=> static int art.Test988.fibonacci(int)
-......<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
-......=> static int art.Test988.fibonacci(int)
-......<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 0>
-.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
-.....=> static int art.Test988.fibonacci(int)
-.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
-....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 2>
-....=> static int art.Test988.fibonacci(int)
-.....=> static int art.Test988.fibonacci(int)
-.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
-.....=> static int art.Test988.fibonacci(int)
-.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 0>
-....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
-...<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 3>
-...=> static int art.Test988.fibonacci(int)
-....=> static int art.Test988.fibonacci(int)
-.....=> static int art.Test988.fibonacci(int)
-.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
-.....=> static int art.Test988.fibonacci(int)
-.....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 0>
-....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
-....=> static int art.Test988.fibonacci(int)
-....<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 1>
-...<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 2>
-..<= static int art.Test988.fibonacci(int) -> <class java.lang.Integer: 5>
-.<= public int art.Test988$RecurOp.applyAsInt(int) -> <class java.lang.Integer: 5>
-.=> public art.Test988$FibResult(java.lang.String,int,int)
-..=> public java.lang.Object()
-..<= public java.lang.Object() -> <null: null>
-.<= public art.Test988$FibResult(java.lang.String,int,int) -> <null: null>
-.=> public boolean java.util.ArrayList.add(java.lang.Object)
-..=> private void java.util.ArrayList.ensureCapacityInternal(int)
-...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
-...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
-..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
-fibonacci(5)=5
-.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
-<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
-=> art.Test988$NativeOp()
-.=> public java.lang.Object()
-.<= public java.lang.Object() -> <null: null>
-<= art.Test988$NativeOp() -> <null: null>
-=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
-.=> public int art.Test988$NativeOp.applyAsInt(int)
-..=> static int art.Test988.nativeFibonacci(int)
-..<= static int art.Test988.nativeFibonacci(int) -> <class java.lang.Integer: 5>
-.<= public int art.Test988$NativeOp.applyAsInt(int) -> <class java.lang.Integer: 5>
-.=> public art.Test988$FibResult(java.lang.String,int,int)
-..=> public java.lang.Object()
-..<= public java.lang.Object() -> <null: null>
-.<= public art.Test988$FibResult(java.lang.String,int,int) -> <null: null>
-.=> public boolean java.util.ArrayList.add(java.lang.Object)
-..=> private void java.util.ArrayList.ensureCapacityInternal(int)
-...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
-...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
-..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
-fibonacci(5)=5
-.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
-<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
-=> art.Test988$IterOp()
-.=> public java.lang.Object()
-.<= public java.lang.Object() -> <null: null>
-<= art.Test988$IterOp() -> <null: null>
-=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
-.=> public int art.Test988$IterOp.applyAsInt(int)
-..=> static int art.Test988.iter_fibonacci(int)
-...=> public java.lang.StringBuilder()
-....=> java.lang.AbstractStringBuilder(int)
-.....=> public java.lang.Object()
-.....<= public java.lang.Object() -> <null: null>
-....<= java.lang.AbstractStringBuilder(int) -> <null: null>
-...<= public java.lang.StringBuilder() -> <null: null>
-...=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
-....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String)
-.....=> public int java.lang.String.length()
-.....<= public int java.lang.String.length() -> <class java.lang.Integer: 14>
-.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
-.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
-.....=> public void java.lang.String.getChars(int,int,char[],int)
-......=> public int java.lang.String.length()
-......<= public int java.lang.String.length() -> <class java.lang.Integer: 14>
-......=> native void java.lang.String.getCharsNoCheck(int,int,char[],int)
-......<= native void java.lang.String.getCharsNoCheck(int,int,char[],int) -> <null: null>
-.....<= public void java.lang.String.getChars(int,int,char[],int) -> <null: null>
-....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...=> public java.lang.StringBuilder java.lang.StringBuilder.append(int)
-....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(int)
-.....=> static int java.lang.Integer.stringSize(int)
-.....<= static int java.lang.Integer.stringSize(int) -> <class java.lang.Integer: 2>
-.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
-......=> private int java.lang.AbstractStringBuilder.newCapacity(int)
-......<= private int java.lang.AbstractStringBuilder.newCapacity(int) -> <class java.lang.Integer: 34>
-......=> public static char[] java.util.Arrays.copyOf(char[],int)
-.......=> public static int java.lang.Math.min(int,int)
-.......<= public static int java.lang.Math.min(int,int) -> <class java.lang.Integer: 16>
-.......=> public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
-.......<= public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int) -> <null: null>
-......<= public static char[] java.util.Arrays.copyOf(char[],int) -> <class [C: [B, a, d,  , a, r, g, u, m, e, n, t, :,  , -, 1, 9,  , <,  , 0, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>]>
-.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
-.....=> static void java.lang.Integer.getChars(int,int,char[])
-.....<= static void java.lang.Integer.getChars(int,int,char[]) -> <null: null>
-....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(int) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...<= public java.lang.StringBuilder java.lang.StringBuilder.append(int) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
-....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String)
-.....=> public int java.lang.String.length()
-.....<= public int java.lang.String.length() -> <class java.lang.Integer: 4>
-.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
-.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
-.....=> public void java.lang.String.getChars(int,int,char[],int)
-......=> public int java.lang.String.length()
-......<= public int java.lang.String.length() -> <class java.lang.Integer: 4>
-......=> native void java.lang.String.getCharsNoCheck(int,int,char[],int)
-......<= native void java.lang.String.getCharsNoCheck(int,int,char[],int) -> <null: null>
-.....<= public void java.lang.String.getChars(int,int,char[],int) -> <null: null>
-....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...=> public java.lang.String java.lang.StringBuilder.toString()
-....=> public static java.lang.String java.lang.StringFactory.newStringFromChars(char[],int,int)
-.....=> static java.lang.String java.lang.StringFactory.newStringFromChars(int,int,char[])
-.....<= static java.lang.String java.lang.StringFactory.newStringFromChars(int,int,char[]) -> <class java.lang.String: Bad argument: -19 < 0>
-....<= public static java.lang.String java.lang.StringFactory.newStringFromChars(char[],int,int) -> <class java.lang.String: Bad argument: -19 < 0>
-...<= public java.lang.String java.lang.StringBuilder.toString() -> <class java.lang.String: Bad argument: -19 < 0>
-...=> public java.lang.Error(java.lang.String)
-....=> public java.lang.Throwable(java.lang.String)
-.....=> public java.lang.Object()
-.....<= public java.lang.Object() -> <null: null>
-.....=> public static final java.util.List java.util.Collections.emptyList()
-.....<= public static final java.util.List java.util.Collections.emptyList() -> <class java.util.Collections$EmptyList: []>
-.....=> public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace()
-......=> private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace()
-......<= private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace() -> <class [Ljava.lang.Object;: <non-deterministic>>
-.....<= public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace() -> <class java.lang.Error: java.lang.Error: Bad argument: -19 < 0
-	art.Test988.iter_fibonacci(Test988.java:255)
-	art.Test988$IterOp.applyAsInt(Test988.java:250)
-	art.Test988.doFibTest(Test988.java:388)
-	art.Test988.run(Test988.java:344)
-	<additional hidden frames>
->
-....<= public java.lang.Throwable(java.lang.String) -> <null: null>
-...<= public java.lang.Error(java.lang.String) -> <null: null>
-..<= static int art.Test988.iter_fibonacci(int) EXCEPTION
-.<= public int art.Test988$IterOp.applyAsInt(int) EXCEPTION
-.=> public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable)
-..=> public java.lang.Object()
-..<= public java.lang.Object() -> <null: null>
-.<= public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable) -> <null: null>
-.=> public boolean java.util.ArrayList.add(java.lang.Object)
-..=> private void java.util.ArrayList.ensureCapacityInternal(int)
-...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
-...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
-..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
-fibonacci(-19) -> java.lang.Error: Bad argument: -19 < 0
-	art.Test988.iter_fibonacci(Test988.java:255)
-	art.Test988$IterOp.applyAsInt(Test988.java:250)
-	art.Test988.doFibTest(Test988.java:388)
-	art.Test988.run(Test988.java:344)
-	<additional hidden frames>
-
-.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
-<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
-=> art.Test988$RecurOp()
-.=> public java.lang.Object()
-.<= public java.lang.Object() -> <null: null>
-<= art.Test988$RecurOp() -> <null: null>
-=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
-.=> public int art.Test988$RecurOp.applyAsInt(int)
-..=> static int art.Test988.fibonacci(int)
-...=> public java.lang.StringBuilder()
-....=> java.lang.AbstractStringBuilder(int)
-.....=> public java.lang.Object()
-.....<= public java.lang.Object() -> <null: null>
-....<= java.lang.AbstractStringBuilder(int) -> <null: null>
-...<= public java.lang.StringBuilder() -> <null: null>
-...=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
-....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String)
-.....=> public int java.lang.String.length()
-.....<= public int java.lang.String.length() -> <class java.lang.Integer: 14>
-.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
-.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
-.....=> public void java.lang.String.getChars(int,int,char[],int)
-......=> public int java.lang.String.length()
-......<= public int java.lang.String.length() -> <class java.lang.Integer: 14>
-......=> native void java.lang.String.getCharsNoCheck(int,int,char[],int)
-......<= native void java.lang.String.getCharsNoCheck(int,int,char[],int) -> <null: null>
-.....<= public void java.lang.String.getChars(int,int,char[],int) -> <null: null>
-....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...=> public java.lang.StringBuilder java.lang.StringBuilder.append(int)
-....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(int)
-.....=> static int java.lang.Integer.stringSize(int)
-.....<= static int java.lang.Integer.stringSize(int) -> <class java.lang.Integer: 2>
-.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
-......=> private int java.lang.AbstractStringBuilder.newCapacity(int)
-......<= private int java.lang.AbstractStringBuilder.newCapacity(int) -> <class java.lang.Integer: 34>
-......=> public static char[] java.util.Arrays.copyOf(char[],int)
-.......=> public static int java.lang.Math.min(int,int)
-.......<= public static int java.lang.Math.min(int,int) -> <class java.lang.Integer: 16>
-.......=> public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
-.......<= public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int) -> <null: null>
-......<= public static char[] java.util.Arrays.copyOf(char[],int) -> <class [C: [B, a, d,  , a, r, g, u, m, e, n, t, :,  , -, 1, 9,  , <,  , 0, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>, <control-0000>]>
-.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
-.....=> static void java.lang.Integer.getChars(int,int,char[])
-.....<= static void java.lang.Integer.getChars(int,int,char[]) -> <null: null>
-....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(int) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...<= public java.lang.StringBuilder java.lang.StringBuilder.append(int) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
-....=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String)
-.....=> public int java.lang.String.length()
-.....<= public int java.lang.String.length() -> <class java.lang.Integer: 4>
-.....=> private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int)
-.....<= private void java.lang.AbstractStringBuilder.ensureCapacityInternal(int) -> <null: null>
-.....=> public void java.lang.String.getChars(int,int,char[],int)
-......=> public int java.lang.String.length()
-......<= public int java.lang.String.length() -> <class java.lang.Integer: 4>
-......=> native void java.lang.String.getCharsNoCheck(int,int,char[],int)
-......<= native void java.lang.String.getCharsNoCheck(int,int,char[],int) -> <null: null>
-.....<= public void java.lang.String.getChars(int,int,char[],int) -> <null: null>
-....<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: Bad argument: -19 < 0>
-...=> public java.lang.String java.lang.StringBuilder.toString()
-....=> public static java.lang.String java.lang.StringFactory.newStringFromChars(char[],int,int)
-.....=> static java.lang.String java.lang.StringFactory.newStringFromChars(int,int,char[])
-.....<= static java.lang.String java.lang.StringFactory.newStringFromChars(int,int,char[]) -> <class java.lang.String: Bad argument: -19 < 0>
-....<= public static java.lang.String java.lang.StringFactory.newStringFromChars(char[],int,int) -> <class java.lang.String: Bad argument: -19 < 0>
-...<= public java.lang.String java.lang.StringBuilder.toString() -> <class java.lang.String: Bad argument: -19 < 0>
-...=> public java.lang.Error(java.lang.String)
-....=> public java.lang.Throwable(java.lang.String)
-.....=> public java.lang.Object()
-.....<= public java.lang.Object() -> <null: null>
-.....=> public static final java.util.List java.util.Collections.emptyList()
-.....<= public static final java.util.List java.util.Collections.emptyList() -> <class java.util.Collections$EmptyList: []>
-.....=> public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace()
-......=> private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace()
-......<= private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace() -> <class [Ljava.lang.Object;: <non-deterministic>>
-.....<= public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace() -> <class java.lang.Error: java.lang.Error: Bad argument: -19 < 0
-	art.Test988.fibonacci(Test988.java:277)
-	art.Test988$RecurOp.applyAsInt(Test988.java:272)
-	art.Test988.doFibTest(Test988.java:388)
-	art.Test988.run(Test988.java:345)
-	<additional hidden frames>
->
-....<= public java.lang.Throwable(java.lang.String) -> <null: null>
-...<= public java.lang.Error(java.lang.String) -> <null: null>
-..<= static int art.Test988.fibonacci(int) EXCEPTION
-.<= public int art.Test988$RecurOp.applyAsInt(int) EXCEPTION
-.=> public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable)
-..=> public java.lang.Object()
-..<= public java.lang.Object() -> <null: null>
-.<= public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable) -> <null: null>
-.=> public boolean java.util.ArrayList.add(java.lang.Object)
-..=> private void java.util.ArrayList.ensureCapacityInternal(int)
-...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
-...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
-..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
-fibonacci(-19) -> java.lang.Error: Bad argument: -19 < 0
-	art.Test988.fibonacci(Test988.java:277)
-	art.Test988$RecurOp.applyAsInt(Test988.java:272)
-	art.Test988.doFibTest(Test988.java:388)
-	art.Test988.run(Test988.java:345)
-	<additional hidden frames>
-
-.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
-<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
-=> art.Test988$NativeOp()
-.=> public java.lang.Object()
-.<= public java.lang.Object() -> <null: null>
-<= art.Test988$NativeOp() -> <null: null>
-=> public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator)
-.=> public int art.Test988$NativeOp.applyAsInt(int)
-..=> static int art.Test988.nativeFibonacci(int)
-...=> public java.lang.Error(java.lang.String)
-....=> public java.lang.Throwable(java.lang.String)
-.....=> public java.lang.Object()
-.....<= public java.lang.Object() -> <null: null>
-.....=> public static final java.util.List java.util.Collections.emptyList()
-.....<= public static final java.util.List java.util.Collections.emptyList() -> <class java.util.Collections$EmptyList: []>
-.....=> public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace()
-......=> private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace()
-......<= private static java.lang.Object java.lang.Throwable.nativeFillInStackTrace() -> <class [Ljava.lang.Object;: <non-deterministic>>
-.....<= public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace() -> <class java.lang.Error: java.lang.Error: bad argument
-	art.Test988.nativeFibonacci(Native Method)
-	art.Test988$NativeOp.applyAsInt(Test988.java:287)
-	art.Test988.doFibTest(Test988.java:388)
-	art.Test988.run(Test988.java:346)
-	<additional hidden frames>
->
-....<= public java.lang.Throwable(java.lang.String) -> <null: null>
-...<= public java.lang.Error(java.lang.String) -> <null: null>
-..<= static int art.Test988.nativeFibonacci(int) EXCEPTION
-.<= public int art.Test988$NativeOp.applyAsInt(int) EXCEPTION
-.=> public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable)
-..=> public java.lang.Object()
-..<= public java.lang.Object() -> <null: null>
-.<= public art.Test988$FibThrow(java.lang.String,int,java.lang.Throwable) -> <null: null>
-.=> public boolean java.util.ArrayList.add(java.lang.Object)
-..=> private void java.util.ArrayList.ensureCapacityInternal(int)
-...=> private void java.util.ArrayList.ensureExplicitCapacity(int)
-...<= private void java.util.ArrayList.ensureExplicitCapacity(int) -> <null: null>
-..<= private void java.util.ArrayList.ensureCapacityInternal(int) -> <null: null>
-fibonacci(-19) -> java.lang.Error: bad argument
-	art.Test988.nativeFibonacci(Native Method)
-	art.Test988$NativeOp.applyAsInt(Test988.java:287)
-	art.Test988.doFibTest(Test988.java:388)
-	art.Test988.run(Test988.java:346)
-	<additional hidden frames>
-
-.<= public boolean java.util.ArrayList.add(java.lang.Object) -> <class java.lang.Boolean: true>
-<= public static void art.Test988.doFibTest(int,java.util.function.IntUnaryOperator) -> <null: null>
-=> public final void <non-deterministic-type 0>.run()
-.=> private static java.lang.Object java.lang.reflect.Proxy.invoke(java.lang.reflect.Proxy,java.lang.reflect.Method,java.lang.Object[]) throws java.lang.Throwable
-..=> public java.lang.Object art.Test988$TestRunnableInvokeHandler.invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[]) throws java.lang.Throwable
-..<= public java.lang.Object art.Test988$TestRunnableInvokeHandler.invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[]) throws java.lang.Throwable -> <null: null>
-.<= private static java.lang.Object java.lang.reflect.Proxy.invoke(java.lang.reflect.Proxy,java.lang.reflect.Method,java.lang.Object[]) throws java.lang.Throwable -> <null: null>
-<= public final void <non-deterministic-type 0>.run() -> <null: null>
-=> static void art.Test988$IntrinsicsTest.doTest()
-.=> static void art.Test988Intrinsics.test()
-..=> public static long java.lang.Double.doubleToRawLongBits(double)
-..<= public static long java.lang.Double.doubleToRawLongBits(double) -> <class java.lang.Long: 0>
-..=> public static long java.lang.Double.doubleToLongBits(double)
-..<= public static long java.lang.Double.doubleToLongBits(double) -> <class java.lang.Long: 0>
-..=> public static boolean java.lang.Double.isInfinite(double)
-..<= public static boolean java.lang.Double.isInfinite(double) -> <class java.lang.Boolean: false>
-..=> public static boolean java.lang.Double.isNaN(double)
-..<= public static boolean java.lang.Double.isNaN(double) -> <class java.lang.Boolean: false>
-..=> public static double java.lang.Double.longBitsToDouble(long)
-..<= public static double java.lang.Double.longBitsToDouble(long) -> <class java.lang.Double: 0.0>
-..=> public static int java.lang.Float.floatToRawIntBits(float)
-..<= public static int java.lang.Float.floatToRawIntBits(float) -> <class java.lang.Integer: 0>
-..=> public static int java.lang.Float.floatToIntBits(float)
-..<= public static int java.lang.Float.floatToIntBits(float) -> <class java.lang.Integer: 0>
-..=> public static boolean java.lang.Float.isInfinite(float)
-..<= public static boolean java.lang.Float.isInfinite(float) -> <class java.lang.Boolean: false>
-..=> public static boolean java.lang.Float.isNaN(float)
-..<= public static boolean java.lang.Float.isNaN(float) -> <class java.lang.Boolean: false>
-..=> public static float java.lang.Float.intBitsToFloat(int)
-..<= public static float java.lang.Float.intBitsToFloat(int) -> <class java.lang.Float: 0.0>
-..=> public static int java.lang.Integer.reverse(int)
-..<= public static int java.lang.Integer.reverse(int) -> <class java.lang.Integer: 0>
-..=> public static int java.lang.Integer.reverseBytes(int)
-..<= public static int java.lang.Integer.reverseBytes(int) -> <class java.lang.Integer: 0>
-..=> public static int java.lang.Integer.bitCount(int)
-..<= public static int java.lang.Integer.bitCount(int) -> <class java.lang.Integer: 0>
-..=> public static int java.lang.Integer.compare(int,int)
-..<= public static int java.lang.Integer.compare(int,int) -> <class java.lang.Integer: 0>
-..=> public static int java.lang.Integer.highestOneBit(int)
-..<= public static int java.lang.Integer.highestOneBit(int) -> <class java.lang.Integer: 0>
-..=> public static int java.lang.Integer.lowestOneBit(int)
-..<= public static int java.lang.Integer.lowestOneBit(int) -> <class java.lang.Integer: 0>
-..=> public static int java.lang.Integer.numberOfLeadingZeros(int)
-..<= public static int java.lang.Integer.numberOfLeadingZeros(int) -> <class java.lang.Integer: 32>
-..=> public static int java.lang.Integer.numberOfTrailingZeros(int)
-..<= public static int java.lang.Integer.numberOfTrailingZeros(int) -> <class java.lang.Integer: 32>
-..=> public static int java.lang.Integer.rotateRight(int,int)
-..<= public static int java.lang.Integer.rotateRight(int,int) -> <class java.lang.Integer: 0>
-..=> public static int java.lang.Integer.rotateLeft(int,int)
-..<= public static int java.lang.Integer.rotateLeft(int,int) -> <class java.lang.Integer: 0>
-..=> public static int java.lang.Integer.signum(int)
-..<= public static int java.lang.Integer.signum(int) -> <class java.lang.Integer: 0>
-..=> public static long java.lang.Long.reverse(long)
-..<= public static long java.lang.Long.reverse(long) -> <class java.lang.Long: 0>
-..=> public static long java.lang.Long.reverseBytes(long)
-..<= public static long java.lang.Long.reverseBytes(long) -> <class java.lang.Long: 0>
-..=> public static int java.lang.Long.bitCount(long)
-..<= public static int java.lang.Long.bitCount(long) -> <class java.lang.Integer: 0>
-..=> public static int java.lang.Long.compare(long,long)
-..<= public static int java.lang.Long.compare(long,long) -> <class java.lang.Integer: 0>
-..=> public static long java.lang.Long.highestOneBit(long)
-..<= public static long java.lang.Long.highestOneBit(long) -> <class java.lang.Long: 0>
-..=> public static long java.lang.Long.lowestOneBit(long)
-..<= public static long java.lang.Long.lowestOneBit(long) -> <class java.lang.Long: 0>
-..=> public static int java.lang.Long.numberOfLeadingZeros(long)
-..<= public static int java.lang.Long.numberOfLeadingZeros(long) -> <class java.lang.Integer: 64>
-..=> public static int java.lang.Long.numberOfTrailingZeros(long)
-..<= public static int java.lang.Long.numberOfTrailingZeros(long) -> <class java.lang.Integer: 64>
-..=> public static long java.lang.Long.rotateRight(long,int)
-..<= public static long java.lang.Long.rotateRight(long,int) -> <class java.lang.Long: 0>
-..=> public static long java.lang.Long.rotateLeft(long,int)
-..<= public static long java.lang.Long.rotateLeft(long,int) -> <class java.lang.Long: 0>
-..=> public static int java.lang.Long.signum(long)
-..<= public static int java.lang.Long.signum(long) -> <class java.lang.Integer: 0>
-..=> public static short java.lang.Short.reverseBytes(short)
-..<= public static short java.lang.Short.reverseBytes(short) -> <class java.lang.Short: 0>
-..=> public static double java.lang.Math.abs(double)
-..<= public static double java.lang.Math.abs(double) -> <class java.lang.Double: 0.0>
-..=> public static float java.lang.Math.abs(float)
-..<= public static float java.lang.Math.abs(float) -> <class java.lang.Float: 0.0>
-..=> public static long java.lang.Math.abs(long)
-..<= public static long java.lang.Math.abs(long) -> <class java.lang.Long: 0>
-..=> public static int java.lang.Math.abs(int)
-..<= public static int java.lang.Math.abs(int) -> <class java.lang.Integer: 0>
-..=> public static double java.lang.Math.min(double,double)
-..<= public static double java.lang.Math.min(double,double) -> <class java.lang.Double: 0.0>
-..=> public static float java.lang.Math.min(float,float)
-..<= public static float java.lang.Math.min(float,float) -> <class java.lang.Float: 0.0>
-..=> public static long java.lang.Math.min(long,long)
-..<= public static long java.lang.Math.min(long,long) -> <class java.lang.Long: 0>
-..=> public static int java.lang.Math.min(int,int)
-..<= public static int java.lang.Math.min(int,int) -> <class java.lang.Integer: 0>
-..=> public static double java.lang.Math.max(double,double)
-..<= public static double java.lang.Math.max(double,double) -> <class java.lang.Double: 0.0>
-..=> public static float java.lang.Math.max(float,float)
-..<= public static float java.lang.Math.max(float,float) -> <class java.lang.Float: 0.0>
-..=> public static long java.lang.Math.max(long,long)
-..<= public static long java.lang.Math.max(long,long) -> <class java.lang.Long: 0>
-..=> public static int java.lang.Math.max(int,int)
-..<= public static int java.lang.Math.max(int,int) -> <class java.lang.Integer: 0>
-..=> public static double java.lang.Math.cos(double)
-..<= public static double java.lang.Math.cos(double) -> <class java.lang.Double: 1.0>
-..=> public static double java.lang.Math.sin(double)
-..<= public static double java.lang.Math.sin(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.acos(double)
-..<= public static double java.lang.Math.acos(double) -> <class java.lang.Double: 1.5707963267948966>
-..=> public static double java.lang.Math.asin(double)
-..<= public static double java.lang.Math.asin(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.atan(double)
-..<= public static double java.lang.Math.atan(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.atan2(double,double)
-..<= public static double java.lang.Math.atan2(double,double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.cbrt(double)
-..<= public static double java.lang.Math.cbrt(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.cosh(double)
-..<= public static double java.lang.Math.cosh(double) -> <class java.lang.Double: 1.0>
-..=> public static double java.lang.Math.exp(double)
-..<= public static double java.lang.Math.exp(double) -> <class java.lang.Double: 1.0>
-..=> public static double java.lang.Math.expm1(double)
-..<= public static double java.lang.Math.expm1(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.hypot(double,double)
-..<= public static double java.lang.Math.hypot(double,double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.log(double)
-..<= public static double java.lang.Math.log(double) -> <class java.lang.Double: -Infinity>
-..=> public static double java.lang.Math.log10(double)
-..<= public static double java.lang.Math.log10(double) -> <class java.lang.Double: -Infinity>
-..=> public static double java.lang.Math.nextAfter(double,double)
-..<= public static double java.lang.Math.nextAfter(double,double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.sinh(double)
-..<= public static double java.lang.Math.sinh(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.tan(double)
-..<= public static double java.lang.Math.tan(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.tanh(double)
-..<= public static double java.lang.Math.tanh(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.sqrt(double)
-..<= public static double java.lang.Math.sqrt(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.ceil(double)
-..<= public static double java.lang.Math.ceil(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.floor(double)
-..<= public static double java.lang.Math.floor(double) -> <class java.lang.Double: 0.0>
-..=> public static double java.lang.Math.rint(double)
-..<= public static double java.lang.Math.rint(double) -> <class java.lang.Double: 0.0>
-..=> public static long java.lang.Math.round(double)
-..<= public static long java.lang.Math.round(double) -> <class java.lang.Long: 0>
-..=> public static int java.lang.Math.round(float)
-..<= public static int java.lang.Math.round(float) -> <class java.lang.Integer: 0>
-..=> public static java.lang.Thread java.lang.Thread.currentThread()
-..<= public static java.lang.Thread java.lang.Thread.currentThread() -> <<non-deterministic>: <non-deterministic>>
-..=> public char java.lang.String.charAt(int)
-..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: s>
-..=> public int java.lang.String.compareTo(java.lang.String)
-..<= public int java.lang.String.compareTo(java.lang.String) -> <class java.lang.Integer: 11>
-..=> public boolean java.lang.String.equals(java.lang.Object)
-..<= public boolean java.lang.String.equals(java.lang.Object) -> <class java.lang.Boolean: false>
-..=> public int java.lang.String.indexOf(int)
-..<= public int java.lang.String.indexOf(int) -> <class java.lang.Integer: -1>
-..=> public int java.lang.String.indexOf(int,int)
-..<= public int java.lang.String.indexOf(int,int) -> <class java.lang.Integer: -1>
-..=> public int java.lang.String.indexOf(java.lang.String)
-..<= public int java.lang.String.indexOf(java.lang.String) -> <class java.lang.Integer: -1>
-..=> public int java.lang.String.indexOf(java.lang.String,int)
-..<= public int java.lang.String.indexOf(java.lang.String,int) -> <class java.lang.Integer: -1>
-..=> public boolean java.lang.String.isEmpty()
-..<= public boolean java.lang.String.isEmpty() -> <class java.lang.Boolean: false>
-..=> public int java.lang.String.length()
-..<= public int java.lang.String.length() -> <class java.lang.Integer: 17>
-..=> public synchronized java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String)
-..<= public synchronized java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String) -> <class java.lang.StringBuffer: some large string bufferhello>
-..=> public synchronized int java.lang.StringBuffer.length()
-..<= public synchronized int java.lang.StringBuffer.length() -> <class java.lang.Integer: 29>
-..=> public synchronized java.lang.String java.lang.StringBuffer.toString()
-..<= public synchronized java.lang.String java.lang.StringBuffer.toString() -> <class java.lang.String: some large string bufferhello>
-..=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
-..<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: some large string builderhello>
-..=> public int java.lang.StringBuilder.length()
-..<= public int java.lang.StringBuilder.length() -> <class java.lang.Integer: 30>
-..=> public java.lang.String java.lang.StringBuilder.toString()
-..<= public java.lang.String java.lang.StringBuilder.toString() -> <class java.lang.String: some large string builderhello>
-..=> public static java.lang.Integer java.lang.Integer.valueOf(int)
-..<= public static java.lang.Integer java.lang.Integer.valueOf(int) -> <class java.lang.Integer: 0>
-..=> public static boolean java.lang.Thread.interrupted()
-..<= public static boolean java.lang.Thread.interrupted() -> <class java.lang.Boolean: false>
-.<= static void art.Test988Intrinsics.test() -> <null: null>
-.=> public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
-.<= public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int) -> <null: null>
-.=> public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
-.<= public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int) -> <null: null>
-<= static void art.Test988$IntrinsicsTest.doTest() -> <null: null>
-=> public static java.lang.Thread java.lang.Thread.currentThread()
-<= public static java.lang.Thread java.lang.Thread.currentThread() -> <<non-deterministic>: <non-deterministic>>
-=> public static void art.Trace.disableTracing(java.lang.Thread)
diff --git a/test/988-method-trace/gen_srcs.py b/test/988-method-trace/gen_srcs.py
index 225f41b..697b17f 100755
--- a/test/988-method-trace/gen_srcs.py
+++ b/test/988-method-trace/gen_srcs.py
@@ -179,8 +179,8 @@
   def __str__(self):
     return "MethodInfo " + str(self.__dict__)
 
-  def dummy_parameters(self):
-    dummy_values = {
+  def placeholder_parameters(self):
+    placeholder_values = {
      'boolean' : 'false',
      'byte' : '(byte)0',
      'char' : "'x'",
@@ -191,14 +191,14 @@
      'double' : '0.0'
     }
 
-    def object_dummy(name):
+    def object_placeholder(name):
       if name == "java.lang.String":
         return '"hello"'
       else:
         return "(%s)null" %(name)
-    return [ dummy_values.get(param, object_dummy(param)) for param in self.parameters ]
+    return [ placeholder_values.get(param, object_placeholder(param)) for param in self.parameters ]
 
-  def dummy_instance_value(self):
+  def placeholder_instance_value(self):
     return KLASS_INSTANCE_INITIALIZERS.get(self.klass, 'new %s()' %(self.klass))
 
   def is_blacklisted(self):
@@ -257,19 +257,19 @@
     receiver = "instance_" + method_info.klass.replace(".", "_")
   return receiver
 
-# Format a dummy call with dummy method parameters to the requested method.
+# Format a placeholder call with placeholder method parameters to the requested method.
 def format_call_to(method_info):
-  dummy_args = ", ".join(method_info.dummy_parameters())
+  placeholder_args = ", ".join(method_info.placeholder_parameters())
   receiver = format_receiver_name(method_info)
 
-  return ("%s.%s(%s);" %(receiver, method_info.method_name, dummy_args))
+  return ("%s.%s(%s);" %(receiver, method_info.method_name, placeholder_args))
 
 # Format a static variable with an instance that could be used as the receiver
 # (or None for non-static methods).
 def format_instance_variable(method_info):
   if method_info.staticness == 'static':
     return None
-  return "static %s %s = %s;" %(method_info.klass, format_receiver_name(method_info), method_info.dummy_instance_value())
+  return "static %s %s = %s;" %(method_info.klass, format_receiver_name(method_info), method_info.placeholder_instance_value())
 
 def format_initialize_klass(method_info):
   return "%s.class.toString();" %(method_info.klass)
diff --git a/test/988-method-trace/src/art/Test988.java b/test/988-method-trace/src/art/Test988.java
index 075e075..9c8ce4a 100644
--- a/test/988-method-trace/src/art/Test988.java
+++ b/test/988-method-trace/src/art/Test988.java
@@ -23,29 +23,43 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.util.ArrayList;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.function.IntUnaryOperator;
+import java.util.function.Predicate;
 
 public class Test988 {
 
     // Methods with non-deterministic output that should not be printed.
-    static Set<Method> NON_DETERMINISTIC_OUTPUT_METHODS = new HashSet<>();
-    static Set<Method> NON_DETERMINISTIC_OUTPUT_TYPE_METHODS = new HashSet<>();
+    static List<Predicate<Executable>> NON_DETERMINISTIC_OUTPUT_METHODS = new ArrayList<>();
+    static List<Predicate<Executable>> NON_DETERMINISTIC_OUTPUT_TYPE_METHODS = new ArrayList<>();
     static List<Class<?>> NON_DETERMINISTIC_TYPE_NAMES = new ArrayList<>();
 
+    static Predicate<Executable> IS_NON_DETERMINISTIC_OUTPUT =
+        (x) -> NON_DETERMINISTIC_OUTPUT_METHODS.stream().anyMatch((pred) -> pred.test(x));
+    static Predicate<Executable> IS_NON_DETERMINISTIC_OUTPUT_TYPE =
+        (x) -> NON_DETERMINISTIC_OUTPUT_TYPE_METHODS.stream().anyMatch((pred) -> pred.test(x));
+
+    public static final Predicate<Executable> EqPred(Executable m) {
+      return (Executable n) -> n.equals(m);
+    }
+
     static {
+      // Throwable.nativeFillInStackTrace is only on android and hiddenapi so we
+      // should avoid trying to find it at all.
+      NON_DETERMINISTIC_OUTPUT_METHODS.add(
+        (Executable ex) -> {
+          return ex.getDeclaringClass().equals(Throwable.class)
+              && ex.getName().equals("nativeFillInStackTrace");
+        });
       try {
         NON_DETERMINISTIC_OUTPUT_METHODS.add(
-            Throwable.class.getDeclaredMethod("nativeFillInStackTrace"));
-      } catch (Exception e) {}
-      try {
-        NON_DETERMINISTIC_OUTPUT_METHODS.add(Thread.class.getDeclaredMethod("currentThread"));
-        NON_DETERMINISTIC_OUTPUT_TYPE_METHODS.add(Thread.class.getDeclaredMethod("currentThread"));
+            EqPred(Thread.class.getDeclaredMethod("currentThread")));
+        NON_DETERMINISTIC_OUTPUT_TYPE_METHODS.add(
+            EqPred(Thread.class.getDeclaredMethod("currentThread")));
       } catch (Exception e) {}
       try {
         NON_DETERMINISTIC_TYPE_NAMES.add(
@@ -160,7 +174,7 @@
         @Override
         public void Print() {
             String print;
-            if (NON_DETERMINISTIC_OUTPUT_METHODS.contains(m)) {
+            if (IS_NON_DETERMINISTIC_OUTPUT.test(m)) {
                 print = "<non-deterministic>";
             } else {
                 print = genericToString(val);
@@ -175,7 +189,7 @@
             } else if (NON_DETERMINISTIC_TYPE_NAMES.contains(klass)) {
               klass_print = "<non-deterministic-class " +
                   NON_DETERMINISTIC_TYPE_NAMES.indexOf(klass) + ">";
-            } else if (NON_DETERMINISTIC_OUTPUT_TYPE_METHODS.contains(m)) {
+            } else if (IS_NON_DETERMINISTIC_OUTPUT_TYPE.test(m)) {
               klass_print = "<non-deterministic>";
             } else {
               klass_print = klass.toString();
diff --git a/test/989-method-trace-throw/Android.bp b/test/989-method-trace-throw/Android.bp
new file mode 100644
index 0000000..71d14b6
--- /dev/null
+++ b/test/989-method-trace-throw/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `989-method-trace-throw`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-989-method-trace-throw",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-989-method-trace-throw-expected-stdout",
+        ":art-run-test-989-method-trace-throw-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-989-method-trace-throw-expected-stdout",
+    out: ["art-run-test-989-method-trace-throw-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-989-method-trace-throw-expected-stderr",
+    out: ["art-run-test-989-method-trace-throw-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/981-dedup-original-dex/expected.txt b/test/989-method-trace-throw/expected-stderr.txt
similarity index 100%
copy from test/981-dedup-original-dex/expected.txt
copy to test/989-method-trace-throw/expected-stderr.txt
diff --git a/test/989-method-trace-throw/expected.txt b/test/989-method-trace-throw/expected-stdout.txt
similarity index 100%
rename from test/989-method-trace-throw/expected.txt
rename to test/989-method-trace-throw/expected-stdout.txt
diff --git a/test/990-field-trace/Android.bp b/test/990-field-trace/Android.bp
new file mode 100644
index 0000000..30997c1
--- /dev/null
+++ b/test/990-field-trace/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `990-field-trace`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-990-field-trace",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-990-field-trace-expected-stdout",
+        ":art-run-test-990-field-trace-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-990-field-trace-expected-stdout",
+    out: ["art-run-test-990-field-trace-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-990-field-trace-expected-stderr",
+    out: ["art-run-test-990-field-trace-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/423-invoke-interface/expected.txt b/test/990-field-trace/expected-stderr.txt
similarity index 100%
copy from test/423-invoke-interface/expected.txt
copy to test/990-field-trace/expected-stderr.txt
diff --git a/test/990-field-trace/expected.txt b/test/990-field-trace/expected-stdout.txt
similarity index 100%
rename from test/990-field-trace/expected.txt
rename to test/990-field-trace/expected-stdout.txt
diff --git a/test/991-field-trace-2/Android.bp b/test/991-field-trace-2/Android.bp
new file mode 100644
index 0000000..956c44d
--- /dev/null
+++ b/test/991-field-trace-2/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `991-field-trace-2`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-991-field-trace-2",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-991-field-trace-2-expected-stdout",
+        ":art-run-test-991-field-trace-2-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-991-field-trace-2-expected-stdout",
+    out: ["art-run-test-991-field-trace-2-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-991-field-trace-2-expected-stderr",
+    out: ["art-run-test-991-field-trace-2-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/446-checker-inliner2/expected.txt b/test/991-field-trace-2/expected-stderr.txt
similarity index 100%
copy from test/446-checker-inliner2/expected.txt
copy to test/991-field-trace-2/expected-stderr.txt
diff --git a/test/991-field-trace-2/expected.txt b/test/991-field-trace-2/expected-stdout.txt
similarity index 100%
rename from test/991-field-trace-2/expected.txt
rename to test/991-field-trace-2/expected-stdout.txt
diff --git a/test/992-source-data/Android.bp b/test/992-source-data/Android.bp
new file mode 100644
index 0000000..e33abfd
--- /dev/null
+++ b/test/992-source-data/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `992-source-data`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-992-source-data",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-992-source-data-expected-stdout",
+        ":art-run-test-992-source-data-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-992-source-data-expected-stdout",
+    out: ["art-run-test-992-source-data-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-992-source-data-expected-stderr",
+    out: ["art-run-test-992-source-data-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/559-bce-ssa/expected.txt b/test/992-source-data/expected-stderr.txt
similarity index 100%
copy from test/559-bce-ssa/expected.txt
copy to test/992-source-data/expected-stderr.txt
diff --git a/test/992-source-data/expected.txt b/test/992-source-data/expected-stdout.txt
similarity index 100%
rename from test/992-source-data/expected.txt
rename to test/992-source-data/expected-stdout.txt
diff --git a/test/993-breakpoints/Android.bp b/test/993-breakpoints/Android.bp
new file mode 100644
index 0000000..72ce18f
--- /dev/null
+++ b/test/993-breakpoints/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `993-breakpoints`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-993-breakpoints",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-993-breakpoints-expected-stdout",
+        ":art-run-test-993-breakpoints-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-993-breakpoints-expected-stdout",
+    out: ["art-run-test-993-breakpoints-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-993-breakpoints-expected-stderr",
+    out: ["art-run-test-993-breakpoints-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/410-floats/expected.txt b/test/993-breakpoints/expected-stderr.txt
similarity index 100%
copy from test/410-floats/expected.txt
copy to test/993-breakpoints/expected-stderr.txt
diff --git a/test/993-breakpoints/expected-stdout.txt b/test/993-breakpoints/expected-stdout.txt
new file mode 100644
index 0000000..37c85a5
--- /dev/null
+++ b/test/993-breakpoints/expected-stdout.txt
@@ -0,0 +1,714 @@
+Running static invoke
+	Breaking on []
+		Native invoking: public static void art.Test993.breakpoint() args: [this: null]
+		Reflective invoking: public static void art.Test993.breakpoint() args: [this: null]
+		Invoking "Test993::breakpoint"
+	Breaking on [public static void art.Test993.breakpoint() @ 41]
+		Native invoking: public static void art.Test993.breakpoint() args: [this: null]
+			Breakpoint: public static void art.Test993.breakpoint() @ line=41
+		Reflective invoking: public static void art.Test993.breakpoint() args: [this: null]
+			Breakpoint: public static void art.Test993.breakpoint() @ line=41
+		Invoking "Test993::breakpoint"
+			Breakpoint: public static void art.Test993.breakpoint() @ line=41
+Running private static invoke
+	Breaking on []
+		Native invoking: private static void art.Test993.privateBreakpoint() args: [this: null]
+		Invoking "Test993::privateBreakpoint"
+	Breaking on [private static void art.Test993.privateBreakpoint() @ 45]
+		Native invoking: private static void art.Test993.privateBreakpoint() args: [this: null]
+			Breakpoint: private static void art.Test993.privateBreakpoint() @ line=45
+		Invoking "Test993::privateBreakpoint"
+			Breakpoint: private static void art.Test993.privateBreakpoint() @ line=45
+Running interface static invoke
+	Breaking on []
+		Native invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
+		Reflective invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
+		Invoking "Breakable::iBreakpoint"
+	Breaking on [public static void art.Test993$Breakable.iBreakpoint() @ 51]
+		Native invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
+			Breakpoint: public static void art.Test993$Breakable.iBreakpoint() @ line=51
+		Reflective invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
+			Breakpoint: public static void art.Test993$Breakable.iBreakpoint() @ line=51
+		Invoking "Breakable::iBreakpoint"
+			Breakpoint: public static void art.Test993$Breakable.iBreakpoint() @ line=51
+Running TestClass1 invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
+		Invoking "((Breakable)new TestClass1()).breakit()"
+		Invoking "new TestClass1().breakit()"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass1()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass1().breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+Running TestClass1ext invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+		Invoking "((Breakable)new TestClass1ext()).breakit()"
+		Invoking "((TestClass1)new TestClass1ext()).breakit()"
+		Invoking "new TestClass1ext().breakit()"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass1ext()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass1)new TestClass1ext()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass1ext().breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+	Breaking on [public void art.Test993$TestClass1ext.breakit() @ 74]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Invoking "((Breakable)new TestClass1ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Invoking "((TestClass1)new TestClass1ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Invoking "new TestClass1ext().breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass1ext.breakit() @ 74]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass1ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass1)new TestClass1ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass1ext().breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+Running TestClass2 invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+		Invoking "((Breakable)new TestClass2()).breakit()"
+		Invoking "new TestClass2().breakit()"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+		Invoking "((Breakable)new TestClass2()).breakit()"
+		Invoking "new TestClass2().breakit()"
+	Breaking on [public void art.Test993$TestClass2.breakit() @ 83]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2().breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2.breakit() @ 83]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2().breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+Running TestClass2ext invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+		Invoking "new TestClass2ext().breakit())"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+		Invoking "new TestClass2ext().breakit())"
+	Breaking on [public void art.Test993$TestClass2.breakit() @ 83]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+	Breaking on [public void art.Test993$TestClass2ext.breakit() @ 91]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2.breakit() @ 83]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2ext.breakit() @ 91]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+	Breaking on [public void art.Test993$TestClass2.breakit() @ 83, public void art.Test993$TestClass2ext.breakit() @ 91]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2.breakit() @ 83, public void art.Test993$TestClass2ext.breakit() @ 91]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+Running TestClass3 invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+		Invoking "((Breakable)new TestClass3()).breakit()"
+		Invoking "new TestClass3().breakit())"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3().breakit())"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+	Breaking on [public void art.Test993$TestClass3.breakit() @ 99]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "((Breakable)new TestClass3()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "new TestClass3().breakit())"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3.breakit() @ 99]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3().breakit())"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+Running TestClass3ext invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+		Invoking "new TestClass3ext().breakit())"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+	Breaking on [public void art.Test993$TestClass3.breakit() @ 99]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+	Breaking on [public void art.Test993$TestClass3ext.breakit() @ 108]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3.breakit() @ 99]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3ext.breakit() @ 108]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+	Breaking on [public void art.Test993$TestClass3.breakit() @ 99, public void art.Test993$TestClass3ext.breakit() @ 108]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3.breakit() @ 99, public void art.Test993$TestClass3ext.breakit() @ 108]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+Running private instance invoke
+	Breaking on []
+		Native invoking: private void art.Test993$TestClass4.privateMethod() args: [this: TestClass4]
+		Invoking "new TestClass4().callPrivateMethod()"
+	Breaking on [private void art.Test993$TestClass4.privateMethod() @ 118]
+		Native invoking: private void art.Test993$TestClass4.privateMethod() args: [this: TestClass4]
+			Breakpoint: private void art.Test993$TestClass4.privateMethod() @ line=118
+		Invoking "new TestClass4().callPrivateMethod()"
+			Breakpoint: private void art.Test993$TestClass4.privateMethod() @ line=118
+Running Vector constructor
+	Breaking on []
+		Native constructor: public java.util.Vector(), type: class java.util.Vector
+			Created: []
+		Reflective constructor: public java.util.Vector()
+			Created: []
+		Constructing: new Vector()
+			Created: []
+	Breaking on [public java.util.Vector() @ <NON-DETERMINISTIC>]
+		Native constructor: public java.util.Vector(), type: class java.util.Vector
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Reflective constructor: public java.util.Vector()
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Constructing: new Vector()
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+Running Stack constructor
+	Breaking on []
+		Native constructor: public java.util.Stack(), type: class java.util.Stack
+			Created: []
+		Reflective constructor: public java.util.Stack()
+			Created: []
+		Constructing: new Stack()
+			Created: []
+	Breaking on [public java.util.Stack() @ <NON-DETERMINISTIC>]
+		Native constructor: public java.util.Stack(), type: class java.util.Stack
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Reflective constructor: public java.util.Stack()
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Constructing: new Stack()
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Created: []
+	Breaking on [public java.util.Vector() @ <NON-DETERMINISTIC>]
+		Native constructor: public java.util.Stack(), type: class java.util.Stack
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Reflective constructor: public java.util.Stack()
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Constructing: new Stack()
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+	Breaking on [public java.util.Stack() @ <NON-DETERMINISTIC>, public java.util.Vector() @ <NON-DETERMINISTIC>]
+		Native constructor: public java.util.Stack(), type: class java.util.Stack
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Reflective constructor: public java.util.Stack()
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Constructing: new Stack()
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+Running bcp static invoke
+	Breaking on []
+		Native invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
+		Reflective invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
+		Invoking "Optional::empty"
+	Breaking on [public static java.util.Optional java.util.Optional.empty() @ <NON-DETERMINISTIC>]
+		Native invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
+			Breakpoint: public static java.util.Optional java.util.Optional.empty() @ line=<NON-DETERMINISTIC>
+		Reflective invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
+			Breakpoint: public static java.util.Optional java.util.Optional.empty() @ line=<NON-DETERMINISTIC>
+		Invoking "Optional::empty"
+			Breakpoint: public static java.util.Optional java.util.Optional.empty() @ line=<NON-DETERMINISTIC>
+Running bcp private static invoke
+	Breaking on []
+		Native invoking: private static long java.util.Random.seedUniquifier() args: [this: null]
+		Invoking "Random::seedUniquifier"
+	Breaking on [private static long java.util.Random.seedUniquifier() @ <NON-DETERMINISTIC>]
+		Native invoking: private static long java.util.Random.seedUniquifier() args: [this: null]
+			Breakpoint: private static long java.util.Random.seedUniquifier() @ line=<NON-DETERMINISTIC>
+		Invoking "Random::seedUniquifier"
+			Breakpoint: private static long java.util.Random.seedUniquifier() @ line=<NON-DETERMINISTIC>
+Running bcp private invoke
+	Breaking on []
+		Native invoking: private java.math.BigDecimal java.time.Duration.toBigDecimalSeconds() args: [this: PT336H]
+		Invoking "Duration::toBigDecimalSeconds"
+	Breaking on [private java.math.BigDecimal java.time.Duration.toBigDecimalSeconds() @ <NON-DETERMINISTIC>]
+		Native invoking: private java.math.BigDecimal java.time.Duration.toBigDecimalSeconds() args: [this: PT336H]
+			Breakpoint: private java.math.BigDecimal java.time.Duration.toBigDecimalSeconds() @ line=<NON-DETERMINISTIC>
+		Invoking "Duration::toBigDecimalSeconds"
+			Breakpoint: private java.math.BigDecimal java.time.Duration.toBigDecimalSeconds() @ line=<NON-DETERMINISTIC>
+Running bcp invoke
+	Breaking on []
+		Native invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test]]
+		Reflective invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test2]]
+		Invoking "Optional::isPresent"
+	Breaking on [public boolean java.util.Optional.isPresent() @ <NON-DETERMINISTIC>]
+		Native invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test]]
+			Breakpoint: public boolean java.util.Optional.isPresent() @ line=<NON-DETERMINISTIC>
+		Reflective invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test2]]
+			Breakpoint: public boolean java.util.Optional.isPresent() @ line=<NON-DETERMINISTIC>
+		Invoking "Optional::isPresent"
+			Breakpoint: public boolean java.util.Optional.isPresent() @ line=<NON-DETERMINISTIC>
+Running TestClass1 constructor
+	Breaking on []
+		Native constructor: public art.Test993$TestClass1(), type: class art.Test993$TestClass1
+			Created: TestClass1
+		Reflective constructor: public art.Test993$TestClass1()
+			Created: TestClass1
+		Constructing: new TestClass1()
+			Created: TestClass1
+	Breaking on [public art.Test993$TestClass1() @ 62]
+		Native constructor: public art.Test993$TestClass1(), type: class art.Test993$TestClass1
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1
+		Reflective constructor: public art.Test993$TestClass1()
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1
+		Constructing: new TestClass1()
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1
+Running TestClass1ext constructor
+	Breaking on []
+		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
+			Created: TestClass1Ext
+		Reflective constructor: public art.Test993$TestClass1ext()
+			Created: TestClass1Ext
+		Constructing: new TestClass1ext()
+			Created: TestClass1Ext
+	Breaking on [public art.Test993$TestClass1() @ 62]
+		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
+		Reflective constructor: public art.Test993$TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
+		Constructing: new TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
+	Breaking on [public art.Test993$TestClass1ext() @ 70]
+		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Created: TestClass1Ext
+		Reflective constructor: public art.Test993$TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Created: TestClass1Ext
+		Constructing: new TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Created: TestClass1Ext
+	Breaking on [public art.Test993$TestClass1() @ 62, public art.Test993$TestClass1ext() @ 70]
+		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
+		Reflective constructor: public art.Test993$TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
+		Constructing: new TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
diff --git a/test/993-breakpoints/expected.txt b/test/993-breakpoints/expected.txt
deleted file mode 100644
index 1749a77..0000000
--- a/test/993-breakpoints/expected.txt
+++ /dev/null
@@ -1,714 +0,0 @@
-Running static invoke
-	Breaking on []
-		Native invoking: public static void art.Test993.breakpoint() args: [this: null]
-		Reflective invoking: public static void art.Test993.breakpoint() args: [this: null]
-		Invoking "Test993::breakpoint"
-	Breaking on [public static void art.Test993.breakpoint() @ 41]
-		Native invoking: public static void art.Test993.breakpoint() args: [this: null]
-			Breakpoint: public static void art.Test993.breakpoint() @ line=41
-		Reflective invoking: public static void art.Test993.breakpoint() args: [this: null]
-			Breakpoint: public static void art.Test993.breakpoint() @ line=41
-		Invoking "Test993::breakpoint"
-			Breakpoint: public static void art.Test993.breakpoint() @ line=41
-Running private static invoke
-	Breaking on []
-		Native invoking: private static void art.Test993.privateBreakpoint() args: [this: null]
-		Invoking "Test993::privateBreakpoint"
-	Breaking on [private static void art.Test993.privateBreakpoint() @ 45]
-		Native invoking: private static void art.Test993.privateBreakpoint() args: [this: null]
-			Breakpoint: private static void art.Test993.privateBreakpoint() @ line=45
-		Invoking "Test993::privateBreakpoint"
-			Breakpoint: private static void art.Test993.privateBreakpoint() @ line=45
-Running interface static invoke
-	Breaking on []
-		Native invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
-		Reflective invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
-		Invoking "Breakable::iBreakpoint"
-	Breaking on [public static void art.Test993$Breakable.iBreakpoint() @ 51]
-		Native invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
-			Breakpoint: public static void art.Test993$Breakable.iBreakpoint() @ line=51
-		Reflective invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
-			Breakpoint: public static void art.Test993$Breakable.iBreakpoint() @ line=51
-		Invoking "Breakable::iBreakpoint"
-			Breakpoint: public static void art.Test993$Breakable.iBreakpoint() @ line=51
-Running TestClass1 invokes
-	Breaking on []
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
-		Invoking "((Breakable)new TestClass1()).breakit()"
-		Invoking "new TestClass1().breakit()"
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((Breakable)new TestClass1()).breakit()"
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "new TestClass1().breakit()"
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-Running TestClass1ext invokes
-	Breaking on []
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
-		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
-		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
-		Invoking "((Breakable)new TestClass1ext()).breakit()"
-		Invoking "((TestClass1)new TestClass1ext()).breakit()"
-		Invoking "new TestClass1ext().breakit()"
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((Breakable)new TestClass1ext()).breakit()"
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((TestClass1)new TestClass1ext()).breakit()"
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "new TestClass1ext().breakit()"
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-	Breaking on [public void art.Test993$TestClass1ext.breakit() @ 74]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-		Invoking "((Breakable)new TestClass1ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-		Invoking "((TestClass1)new TestClass1ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-		Invoking "new TestClass1ext().breakit()"
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass1ext.breakit() @ 74]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((Breakable)new TestClass1ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((TestClass1)new TestClass1ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "new TestClass1ext().breakit()"
-			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-Running TestClass2 invokes
-	Breaking on []
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
-		Invoking "((Breakable)new TestClass2()).breakit()"
-		Invoking "new TestClass2().breakit()"
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
-		Invoking "((Breakable)new TestClass2()).breakit()"
-		Invoking "new TestClass2().breakit()"
-	Breaking on [public void art.Test993$TestClass2.breakit() @ 83]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "((Breakable)new TestClass2()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "new TestClass2().breakit()"
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2.breakit() @ 83]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "((Breakable)new TestClass2()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "new TestClass2().breakit()"
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-Running TestClass2ext invokes
-	Breaking on []
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-		Invoking "((Breakable)new TestClass2ext()).breakit()"
-		Invoking "((TestClass2)new TestClass2ext()).breakit()"
-		Invoking "new TestClass2ext().breakit())"
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-		Invoking "((Breakable)new TestClass2ext()).breakit()"
-		Invoking "((TestClass2)new TestClass2ext()).breakit()"
-		Invoking "new TestClass2ext().breakit())"
-	Breaking on [public void art.Test993$TestClass2.breakit() @ 83]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "((Breakable)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "((TestClass2)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "new TestClass2ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-	Breaking on [public void art.Test993$TestClass2ext.breakit() @ 91]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Invoking "((Breakable)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Invoking "((TestClass2)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Invoking "new TestClass2ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2.breakit() @ 83]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "((Breakable)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "((TestClass2)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "new TestClass2ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2ext.breakit() @ 91]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Invoking "((Breakable)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Invoking "((TestClass2)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-		Invoking "new TestClass2ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-	Breaking on [public void art.Test993$TestClass2.breakit() @ 83, public void art.Test993$TestClass2ext.breakit() @ 91]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "((Breakable)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "((TestClass2)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "new TestClass2ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2.breakit() @ 83, public void art.Test993$TestClass2ext.breakit() @ 91]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "((Breakable)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "((TestClass2)new TestClass2ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-		Invoking "new TestClass2ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
-			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
-Running TestClass3 invokes
-	Breaking on []
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
-		Invoking "((Breakable)new TestClass3()).breakit()"
-		Invoking "new TestClass3().breakit())"
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((Breakable)new TestClass3()).breakit()"
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "new TestClass3().breakit())"
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-	Breaking on [public void art.Test993$TestClass3.breakit() @ 99]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Invoking "((Breakable)new TestClass3()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Invoking "new TestClass3().breakit())"
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3.breakit() @ 99]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((Breakable)new TestClass3()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "new TestClass3().breakit())"
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-Running TestClass3ext invokes
-	Breaking on []
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-		Invoking "((Breakable)new TestClass3ext()).breakit()"
-		Invoking "((TestClass3)new TestClass3ext()).breakit()"
-		Invoking "new TestClass3ext().breakit())"
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((Breakable)new TestClass3ext()).breakit()"
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((TestClass3)new TestClass3ext()).breakit()"
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "new TestClass3ext().breakit())"
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-	Breaking on [public void art.Test993$TestClass3.breakit() @ 99]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Invoking "((Breakable)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Invoking "((TestClass3)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Invoking "new TestClass3ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-	Breaking on [public void art.Test993$TestClass3ext.breakit() @ 108]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-		Invoking "((Breakable)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-		Invoking "((TestClass3)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-		Invoking "new TestClass3ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3.breakit() @ 99]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((Breakable)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((TestClass3)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "new TestClass3ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3ext.breakit() @ 108]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((Breakable)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((TestClass3)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "new TestClass3ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-	Breaking on [public void art.Test993$TestClass3.breakit() @ 99, public void art.Test993$TestClass3ext.breakit() @ 108]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Invoking "((Breakable)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Invoking "((TestClass3)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-		Invoking "new TestClass3ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3.breakit() @ 99, public void art.Test993$TestClass3ext.breakit() @ 108]
-		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((Breakable)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "((TestClass3)new TestClass3ext()).breakit()"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-		Invoking "new TestClass3ext().breakit())"
-			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
-			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
-			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
-Running private instance invoke
-	Breaking on []
-		Native invoking: private void art.Test993$TestClass4.privateMethod() args: [this: TestClass4]
-		Invoking "new TestClass4().callPrivateMethod()"
-	Breaking on [private void art.Test993$TestClass4.privateMethod() @ 118]
-		Native invoking: private void art.Test993$TestClass4.privateMethod() args: [this: TestClass4]
-			Breakpoint: private void art.Test993$TestClass4.privateMethod() @ line=118
-		Invoking "new TestClass4().callPrivateMethod()"
-			Breakpoint: private void art.Test993$TestClass4.privateMethod() @ line=118
-Running Vector constructor
-	Breaking on []
-		Native constructor: public java.util.Vector(), type: class java.util.Vector
-			Created: []
-		Reflective constructor: public java.util.Vector()
-			Created: []
-		Constructing: new Vector()
-			Created: []
-	Breaking on [public java.util.Vector() @ <NON-DETERMINISTIC>]
-		Native constructor: public java.util.Vector(), type: class java.util.Vector
-			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
-			Created: []
-		Reflective constructor: public java.util.Vector()
-			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
-			Created: []
-		Constructing: new Vector()
-			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
-			Created: []
-Running Stack constructor
-	Breaking on []
-		Native constructor: public java.util.Stack(), type: class java.util.Stack
-			Created: []
-		Reflective constructor: public java.util.Stack()
-			Created: []
-		Constructing: new Stack()
-			Created: []
-	Breaking on [public java.util.Stack() @ <NON-DETERMINISTIC>]
-		Native constructor: public java.util.Stack(), type: class java.util.Stack
-			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
-			Created: []
-		Reflective constructor: public java.util.Stack()
-			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
-			Created: []
-		Constructing: new Stack()
-			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
-			Created: []
-	Breaking on [public java.util.Vector() @ <NON-DETERMINISTIC>]
-		Native constructor: public java.util.Stack(), type: class java.util.Stack
-			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
-			Created: []
-		Reflective constructor: public java.util.Stack()
-			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
-			Created: []
-		Constructing: new Stack()
-			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
-			Created: []
-	Breaking on [public java.util.Stack() @ <NON-DETERMINISTIC>, public java.util.Vector() @ <NON-DETERMINISTIC>]
-		Native constructor: public java.util.Stack(), type: class java.util.Stack
-			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
-			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
-			Created: []
-		Reflective constructor: public java.util.Stack()
-			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
-			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
-			Created: []
-		Constructing: new Stack()
-			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
-			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
-			Created: []
-Running bcp static invoke
-	Breaking on []
-		Native invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
-		Reflective invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
-		Invoking "Optional::empty"
-	Breaking on [public static java.util.Optional java.util.Optional.empty() @ <NON-DETERMINISTIC>]
-		Native invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
-			Breakpoint: public static java.util.Optional java.util.Optional.empty() @ line=<NON-DETERMINISTIC>
-		Reflective invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
-			Breakpoint: public static java.util.Optional java.util.Optional.empty() @ line=<NON-DETERMINISTIC>
-		Invoking "Optional::empty"
-			Breakpoint: public static java.util.Optional java.util.Optional.empty() @ line=<NON-DETERMINISTIC>
-Running bcp private static invoke
-	Breaking on []
-		Native invoking: private static long java.util.Random.seedUniquifier() args: [this: null]
-		Invoking "Random::seedUniquifier"
-	Breaking on [private static long java.util.Random.seedUniquifier() @ <NON-DETERMINISTIC>]
-		Native invoking: private static long java.util.Random.seedUniquifier() args: [this: null]
-			Breakpoint: private static long java.util.Random.seedUniquifier() @ line=<NON-DETERMINISTIC>
-		Invoking "Random::seedUniquifier"
-			Breakpoint: private static long java.util.Random.seedUniquifier() @ line=<NON-DETERMINISTIC>
-Running bcp private invoke
-	Breaking on []
-		Native invoking: private java.math.BigDecimal java.time.Duration.toSeconds() args: [this: PT336H]
-		Invoking "Duration::toSeconds"
-	Breaking on [private java.math.BigDecimal java.time.Duration.toSeconds() @ <NON-DETERMINISTIC>]
-		Native invoking: private java.math.BigDecimal java.time.Duration.toSeconds() args: [this: PT336H]
-			Breakpoint: private java.math.BigDecimal java.time.Duration.toSeconds() @ line=<NON-DETERMINISTIC>
-		Invoking "Duration::toSeconds"
-			Breakpoint: private java.math.BigDecimal java.time.Duration.toSeconds() @ line=<NON-DETERMINISTIC>
-Running bcp invoke
-	Breaking on []
-		Native invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test]]
-		Reflective invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test2]]
-		Invoking "Optional::isPresent"
-	Breaking on [public boolean java.util.Optional.isPresent() @ <NON-DETERMINISTIC>]
-		Native invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test]]
-			Breakpoint: public boolean java.util.Optional.isPresent() @ line=<NON-DETERMINISTIC>
-		Reflective invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test2]]
-			Breakpoint: public boolean java.util.Optional.isPresent() @ line=<NON-DETERMINISTIC>
-		Invoking "Optional::isPresent"
-			Breakpoint: public boolean java.util.Optional.isPresent() @ line=<NON-DETERMINISTIC>
-Running TestClass1 constructor
-	Breaking on []
-		Native constructor: public art.Test993$TestClass1(), type: class art.Test993$TestClass1
-			Created: TestClass1
-		Reflective constructor: public art.Test993$TestClass1()
-			Created: TestClass1
-		Constructing: new TestClass1()
-			Created: TestClass1
-	Breaking on [public art.Test993$TestClass1() @ 62]
-		Native constructor: public art.Test993$TestClass1(), type: class art.Test993$TestClass1
-			Breakpoint: public art.Test993$TestClass1() @ line=62
-			Created: TestClass1
-		Reflective constructor: public art.Test993$TestClass1()
-			Breakpoint: public art.Test993$TestClass1() @ line=62
-			Created: TestClass1
-		Constructing: new TestClass1()
-			Breakpoint: public art.Test993$TestClass1() @ line=62
-			Created: TestClass1
-Running TestClass1ext constructor
-	Breaking on []
-		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
-			Created: TestClass1Ext
-		Reflective constructor: public art.Test993$TestClass1ext()
-			Created: TestClass1Ext
-		Constructing: new TestClass1ext()
-			Created: TestClass1Ext
-	Breaking on [public art.Test993$TestClass1() @ 62]
-		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
-			Breakpoint: public art.Test993$TestClass1() @ line=62
-			Created: TestClass1Ext
-		Reflective constructor: public art.Test993$TestClass1ext()
-			Breakpoint: public art.Test993$TestClass1() @ line=62
-			Created: TestClass1Ext
-		Constructing: new TestClass1ext()
-			Breakpoint: public art.Test993$TestClass1() @ line=62
-			Created: TestClass1Ext
-	Breaking on [public art.Test993$TestClass1ext() @ 70]
-		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
-			Breakpoint: public art.Test993$TestClass1ext() @ line=70
-			Created: TestClass1Ext
-		Reflective constructor: public art.Test993$TestClass1ext()
-			Breakpoint: public art.Test993$TestClass1ext() @ line=70
-			Created: TestClass1Ext
-		Constructing: new TestClass1ext()
-			Breakpoint: public art.Test993$TestClass1ext() @ line=70
-			Created: TestClass1Ext
-	Breaking on [public art.Test993$TestClass1() @ 62, public art.Test993$TestClass1ext() @ 70]
-		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
-			Breakpoint: public art.Test993$TestClass1ext() @ line=70
-			Breakpoint: public art.Test993$TestClass1() @ line=62
-			Created: TestClass1Ext
-		Reflective constructor: public art.Test993$TestClass1ext()
-			Breakpoint: public art.Test993$TestClass1ext() @ line=70
-			Breakpoint: public art.Test993$TestClass1() @ line=62
-			Created: TestClass1Ext
-		Constructing: new TestClass1ext()
-			Breakpoint: public art.Test993$TestClass1ext() @ line=70
-			Breakpoint: public art.Test993$TestClass1() @ line=62
-			Created: TestClass1Ext
diff --git a/test/993-breakpoints/expected_cts.txt b/test/993-breakpoints/expected_cts.txt
new file mode 100644
index 0000000..6c4e881
--- /dev/null
+++ b/test/993-breakpoints/expected_cts.txt
@@ -0,0 +1,696 @@
+Running static invoke
+	Breaking on []
+		Native invoking: public static void art.Test993.breakpoint() args: [this: null]
+		Reflective invoking: public static void art.Test993.breakpoint() args: [this: null]
+		Invoking "Test993::breakpoint"
+	Breaking on [public static void art.Test993.breakpoint() @ 41]
+		Native invoking: public static void art.Test993.breakpoint() args: [this: null]
+			Breakpoint: public static void art.Test993.breakpoint() @ line=41
+		Reflective invoking: public static void art.Test993.breakpoint() args: [this: null]
+			Breakpoint: public static void art.Test993.breakpoint() @ line=41
+		Invoking "Test993::breakpoint"
+			Breakpoint: public static void art.Test993.breakpoint() @ line=41
+Running private static invoke
+	Breaking on []
+		Native invoking: private static void art.Test993.privateBreakpoint() args: [this: null]
+		Invoking "Test993::privateBreakpoint"
+	Breaking on [private static void art.Test993.privateBreakpoint() @ 45]
+		Native invoking: private static void art.Test993.privateBreakpoint() args: [this: null]
+			Breakpoint: private static void art.Test993.privateBreakpoint() @ line=45
+		Invoking "Test993::privateBreakpoint"
+			Breakpoint: private static void art.Test993.privateBreakpoint() @ line=45
+Running interface static invoke
+	Breaking on []
+		Native invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
+		Reflective invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
+		Invoking "Breakable::iBreakpoint"
+	Breaking on [public static void art.Test993$Breakable.iBreakpoint() @ 51]
+		Native invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
+			Breakpoint: public static void art.Test993$Breakable.iBreakpoint() @ line=51
+		Reflective invoking: public static void art.Test993$Breakable.iBreakpoint() args: [this: null]
+			Breakpoint: public static void art.Test993$Breakable.iBreakpoint() @ line=51
+		Invoking "Breakable::iBreakpoint"
+			Breakpoint: public static void art.Test993$Breakable.iBreakpoint() @ line=51
+Running TestClass1 invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
+		Invoking "((Breakable)new TestClass1()).breakit()"
+		Invoking "new TestClass1().breakit()"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass1()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass1().breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+Running TestClass1ext invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+		Invoking "((Breakable)new TestClass1ext()).breakit()"
+		Invoking "((TestClass1)new TestClass1ext()).breakit()"
+		Invoking "new TestClass1ext().breakit()"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass1ext()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass1)new TestClass1ext()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass1ext().breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+	Breaking on [public void art.Test993$TestClass1ext.breakit() @ 74]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Invoking "((Breakable)new TestClass1ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Invoking "((TestClass1)new TestClass1ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+		Invoking "new TestClass1ext().breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass1ext.breakit() @ 74]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass1ext.breakit() args: [this: TestClass1Ext]
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass1ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass1)new TestClass1ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass1ext().breakit()"
+			Breakpoint: public void art.Test993$TestClass1ext.breakit() @ line=74
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+Running TestClass2 invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+		Invoking "((Breakable)new TestClass2()).breakit()"
+		Invoking "new TestClass2().breakit()"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+		Invoking "((Breakable)new TestClass2()).breakit()"
+		Invoking "new TestClass2().breakit()"
+	Breaking on [public void art.Test993$TestClass2.breakit() @ 83]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2().breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2.breakit() @ 83]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2().breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+Running TestClass2ext invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+		Invoking "new TestClass2ext().breakit())"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+		Invoking "new TestClass2ext().breakit())"
+	Breaking on [public void art.Test993$TestClass2.breakit() @ 83]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+	Breaking on [public void art.Test993$TestClass2ext.breakit() @ 91]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2.breakit() @ 83]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2ext.breakit() @ 91]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+	Breaking on [public void art.Test993$TestClass2.breakit() @ 83, public void art.Test993$TestClass2ext.breakit() @ 91]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass2.breakit() @ 83, public void art.Test993$TestClass2ext.breakit() @ 91]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Native invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Reflective invoking: public void art.Test993$TestClass2ext.breakit() args: [this: TestClass2ext]
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((Breakable)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "((TestClass2)new TestClass2ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+		Invoking "new TestClass2ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass2ext.breakit() @ line=91
+			Breakpoint: public void art.Test993$TestClass2.breakit() @ line=83
+Running TestClass3 invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+		Invoking "((Breakable)new TestClass3()).breakit()"
+		Invoking "new TestClass3().breakit())"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3().breakit())"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+	Breaking on [public void art.Test993$TestClass3.breakit() @ 99]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "((Breakable)new TestClass3()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "new TestClass3().breakit())"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3.breakit() @ 99]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3().breakit())"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+Running TestClass3ext invokes
+	Breaking on []
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+		Invoking "new TestClass3ext().breakit())"
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+	Breaking on [public void art.Test993$TestClass3.breakit() @ 99]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+	Breaking on [public void art.Test993$TestClass3ext.breakit() @ 108]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3.breakit() @ 99]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3ext.breakit() @ 108]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+	Breaking on [public void art.Test993$TestClass3.breakit() @ 99, public void art.Test993$TestClass3ext.breakit() @ 108]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+	Breaking on [public default void art.Test993$Breakable.breakit() @ 55, public void art.Test993$TestClass3.breakit() @ 99, public void art.Test993$TestClass3ext.breakit() @ 108]
+		Native invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Native invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public default void art.Test993$Breakable.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Reflective invoking: public void art.Test993$TestClass3ext.breakit() args: [this: TestClass3ext]
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((Breakable)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "((TestClass3)new TestClass3ext()).breakit()"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+		Invoking "new TestClass3ext().breakit())"
+			Breakpoint: public void art.Test993$TestClass3ext.breakit() @ line=108
+			Breakpoint: public void art.Test993$TestClass3.breakit() @ line=99
+			Breakpoint: public default void art.Test993$Breakable.breakit() @ line=55
+Running private instance invoke
+	Breaking on []
+		Native invoking: private void art.Test993$TestClass4.privateMethod() args: [this: TestClass4]
+		Invoking "new TestClass4().callPrivateMethod()"
+	Breaking on [private void art.Test993$TestClass4.privateMethod() @ 118]
+		Native invoking: private void art.Test993$TestClass4.privateMethod() args: [this: TestClass4]
+			Breakpoint: private void art.Test993$TestClass4.privateMethod() @ line=118
+		Invoking "new TestClass4().callPrivateMethod()"
+			Breakpoint: private void art.Test993$TestClass4.privateMethod() @ line=118
+Running Vector constructor
+	Breaking on []
+		Native constructor: public java.util.Vector(), type: class java.util.Vector
+			Created: []
+		Reflective constructor: public java.util.Vector()
+			Created: []
+		Constructing: new Vector()
+			Created: []
+	Breaking on [public java.util.Vector() @ <NON-DETERMINISTIC>]
+		Native constructor: public java.util.Vector(), type: class java.util.Vector
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Reflective constructor: public java.util.Vector()
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Constructing: new Vector()
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+Running Stack constructor
+	Breaking on []
+		Native constructor: public java.util.Stack(), type: class java.util.Stack
+			Created: []
+		Reflective constructor: public java.util.Stack()
+			Created: []
+		Constructing: new Stack()
+			Created: []
+	Breaking on [public java.util.Stack() @ <NON-DETERMINISTIC>]
+		Native constructor: public java.util.Stack(), type: class java.util.Stack
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Reflective constructor: public java.util.Stack()
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Constructing: new Stack()
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Created: []
+	Breaking on [public java.util.Vector() @ <NON-DETERMINISTIC>]
+		Native constructor: public java.util.Stack(), type: class java.util.Stack
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Reflective constructor: public java.util.Stack()
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Constructing: new Stack()
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+	Breaking on [public java.util.Stack() @ <NON-DETERMINISTIC>, public java.util.Vector() @ <NON-DETERMINISTIC>]
+		Native constructor: public java.util.Stack(), type: class java.util.Stack
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Reflective constructor: public java.util.Stack()
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+		Constructing: new Stack()
+			Breakpoint: public java.util.Stack() @ line=<NON-DETERMINISTIC>
+			Breakpoint: public java.util.Vector() @ line=<NON-DETERMINISTIC>
+			Created: []
+Running bcp static invoke
+	Breaking on []
+		Native invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
+		Reflective invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
+		Invoking "Optional::empty"
+	Breaking on [public static java.util.Optional java.util.Optional.empty() @ <NON-DETERMINISTIC>]
+		Native invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
+			Breakpoint: public static java.util.Optional java.util.Optional.empty() @ line=<NON-DETERMINISTIC>
+		Reflective invoking: public static java.util.Optional java.util.Optional.empty() args: [this: null]
+			Breakpoint: public static java.util.Optional java.util.Optional.empty() @ line=<NON-DETERMINISTIC>
+		Invoking "Optional::empty"
+			Breakpoint: public static java.util.Optional java.util.Optional.empty() @ line=<NON-DETERMINISTIC>
+Running bcp invoke
+	Breaking on []
+		Native invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test]]
+		Reflective invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test2]]
+		Invoking "Optional::isPresent"
+	Breaking on [public boolean java.util.Optional.isPresent() @ <NON-DETERMINISTIC>]
+		Native invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test]]
+			Breakpoint: public boolean java.util.Optional.isPresent() @ line=<NON-DETERMINISTIC>
+		Reflective invoking: public boolean java.util.Optional.isPresent() args: [this: Optional[test2]]
+			Breakpoint: public boolean java.util.Optional.isPresent() @ line=<NON-DETERMINISTIC>
+		Invoking "Optional::isPresent"
+			Breakpoint: public boolean java.util.Optional.isPresent() @ line=<NON-DETERMINISTIC>
+Running TestClass1 constructor
+	Breaking on []
+		Native constructor: public art.Test993$TestClass1(), type: class art.Test993$TestClass1
+			Created: TestClass1
+		Reflective constructor: public art.Test993$TestClass1()
+			Created: TestClass1
+		Constructing: new TestClass1()
+			Created: TestClass1
+	Breaking on [public art.Test993$TestClass1() @ 62]
+		Native constructor: public art.Test993$TestClass1(), type: class art.Test993$TestClass1
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1
+		Reflective constructor: public art.Test993$TestClass1()
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1
+		Constructing: new TestClass1()
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1
+Running TestClass1ext constructor
+	Breaking on []
+		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
+			Created: TestClass1Ext
+		Reflective constructor: public art.Test993$TestClass1ext()
+			Created: TestClass1Ext
+		Constructing: new TestClass1ext()
+			Created: TestClass1Ext
+	Breaking on [public art.Test993$TestClass1() @ 62]
+		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
+		Reflective constructor: public art.Test993$TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
+		Constructing: new TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
+	Breaking on [public art.Test993$TestClass1ext() @ 70]
+		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Created: TestClass1Ext
+		Reflective constructor: public art.Test993$TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Created: TestClass1Ext
+		Constructing: new TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Created: TestClass1Ext
+	Breaking on [public art.Test993$TestClass1() @ 62, public art.Test993$TestClass1ext() @ 70]
+		Native constructor: public art.Test993$TestClass1ext(), type: class art.Test993$TestClass1ext
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
+		Reflective constructor: public art.Test993$TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
+		Constructing: new TestClass1ext()
+			Breakpoint: public art.Test993$TestClass1ext() @ line=70
+			Breakpoint: public art.Test993$TestClass1() @ line=62
+			Created: TestClass1Ext
diff --git a/test/993-breakpoints/src/Main.java b/test/993-breakpoints/src/Main.java
index b11f6f8..b4e60b8 100644
--- a/test/993-breakpoints/src/Main.java
+++ b/test/993-breakpoints/src/Main.java
@@ -16,6 +16,6 @@
 
 public class Main {
   public static void main(String[] args) throws Exception {
-    art.Test993.run();
+    art.Test993.run(true);
   }
 }
diff --git a/test/993-breakpoints/src/art/Test993.java b/test/993-breakpoints/src/art/Test993.java
index d6a6a67..0c07298 100644
--- a/test/993-breakpoints/src/art/Test993.java
+++ b/test/993-breakpoints/src/art/Test993.java
@@ -327,6 +327,9 @@
   }
 
   public static void run() throws Exception {
+    run(false);
+  }
+  public static void run(boolean test_BCP_private) throws Exception {
     // Set up breakpoints
     Breakpoint.stopBreakpointWatch(Thread.currentThread());
     Breakpoint.startBreakpointWatch(
@@ -336,7 +339,7 @@
         Thread.currentThread());
 
     runMethodTests();
-    runBCPMethodTests();
+    runBCPMethodTests(test_BCP_private);
     runConstructorTests();
 
     Breakpoint.stopBreakpointWatch(Thread.currentThread());
@@ -371,12 +374,14 @@
   // These test to make sure we are able to break on functions that might have been quickened or
   // inlined from the boot-image. These were all chosen for being in the bootclasspath, not being
   // long enough to prevent inlining, and not being used for the testing framework.
-  public static void runBCPMethodTests() throws Exception {
+  public static void runBCPMethodTests(boolean test_BCP_private) throws Exception {
     // The methods we will be breaking on.
-    Method bcp_private_method = Duration.class.getDeclaredMethod("toSeconds");
+    Method bcp_private_method =
+        test_BCP_private ? Duration.class.getDeclaredMethod("toBigDecimalSeconds") : null;
     Method bcp_virtual_method = Optional.class.getDeclaredMethod("isPresent");
     Method bcp_static_method = Optional.class.getDeclaredMethod("empty");
-    Method bcp_private_static_method = Random.class.getDeclaredMethod("seedUniquifier");
+    Method bcp_private_static_method =
+        test_BCP_private ? Random.class.getDeclaredMethod("seedUniquifier") : null;
 
     // Some constructors we will break on.
     Constructor<?> bcp_stack_constructor = Stack.class.getConstructor();
@@ -420,27 +425,31 @@
     runTestGroups("bcp static invoke", static_invokes, static_breakpoints);
 
     // Static private class function
-    Runnable[] private_static_invokes = new Runnable[] {
-      new InvokeNativeLong(bcp_private_static_method, null),
+    if (test_BCP_private) {
+      Runnable[] private_static_invokes = new Runnable[] {
+        new InvokeNativeLong(bcp_private_static_method, null),
 
-      new InvokeDirect("Random::seedUniquifier", () -> { new Random(); }),
-    };
-    Breakpoint.Manager.BP[] private_static_breakpoints = new Breakpoint.Manager.BP[] {
-      BP(bcp_private_static_method)
-    };
-    runTestGroups("bcp private static invoke", private_static_invokes, private_static_breakpoints);
+        new InvokeDirect("Random::seedUniquifier", () -> { new Random(); }),
+      };
+      Breakpoint.Manager.BP[] private_static_breakpoints = new Breakpoint.Manager.BP[] {
+        BP(bcp_private_static_method)
+      };
+      runTestGroups("bcp private static invoke", private_static_invokes, private_static_breakpoints);
+    }
 
     // private class method
-    Duration test_duration = Duration.ofDays(14);
-    Runnable[] private_invokes = new Runnable[] {
-      new InvokeNativeObject(bcp_private_method, test_duration),
+    if (test_BCP_private) {
+      Duration test_duration = Duration.ofDays(14);
+      Runnable[] private_invokes = new Runnable[] {
+        new InvokeNativeObject(bcp_private_method, test_duration),
 
-      new InvokeDirect("Duration::toSeconds", () -> { test_duration.multipliedBy(2); }),
-    };
-    Breakpoint.Manager.BP[] private_breakpoints = new Breakpoint.Manager.BP[] {
-      BP(bcp_private_method)
-    };
-    runTestGroups("bcp private invoke", private_invokes, private_breakpoints);
+        new InvokeDirect("Duration::toBigDecimalSeconds", () -> { test_duration.multipliedBy(2); }),
+      };
+      Breakpoint.Manager.BP[] private_breakpoints = new Breakpoint.Manager.BP[] {
+        BP(bcp_private_method)
+      };
+      runTestGroups("bcp private invoke", private_invokes, private_breakpoints);
+    }
 
     // class method
     Runnable[] public_invokes = new Runnable[] {
diff --git a/test/994-breakpoint-line/Android.bp b/test/994-breakpoint-line/Android.bp
new file mode 100644
index 0000000..4c0cd20
--- /dev/null
+++ b/test/994-breakpoint-line/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `994-breakpoint-line`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-994-breakpoint-line",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-994-breakpoint-line-expected-stdout",
+        ":art-run-test-994-breakpoint-line-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-994-breakpoint-line-expected-stdout",
+    out: ["art-run-test-994-breakpoint-line-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-994-breakpoint-line-expected-stderr",
+    out: ["art-run-test-994-breakpoint-line-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/437-inline/expected.txt b/test/994-breakpoint-line/expected-stderr.txt
similarity index 100%
copy from test/437-inline/expected.txt
copy to test/994-breakpoint-line/expected-stderr.txt
diff --git a/test/994-breakpoint-line/expected.txt b/test/994-breakpoint-line/expected-stdout.txt
similarity index 100%
rename from test/994-breakpoint-line/expected.txt
rename to test/994-breakpoint-line/expected-stdout.txt
diff --git a/test/995-breakpoints-throw/Android.bp b/test/995-breakpoints-throw/Android.bp
new file mode 100644
index 0000000..00146b0
--- /dev/null
+++ b/test/995-breakpoints-throw/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `995-breakpoints-throw`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-995-breakpoints-throw",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-995-breakpoints-throw-expected-stdout",
+        ":art-run-test-995-breakpoints-throw-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-995-breakpoints-throw-expected-stdout",
+    out: ["art-run-test-995-breakpoints-throw-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-995-breakpoints-throw-expected-stderr",
+    out: ["art-run-test-995-breakpoints-throw-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/402-optimizing-control-flow/expected.txt b/test/995-breakpoints-throw/expected-stderr.txt
similarity index 100%
copy from test/402-optimizing-control-flow/expected.txt
copy to test/995-breakpoints-throw/expected-stderr.txt
diff --git a/test/995-breakpoints-throw/expected.txt b/test/995-breakpoints-throw/expected-stdout.txt
similarity index 100%
rename from test/995-breakpoints-throw/expected.txt
rename to test/995-breakpoints-throw/expected-stdout.txt
diff --git a/test/996-breakpoint-obsolete/Android.bp b/test/996-breakpoint-obsolete/Android.bp
new file mode 100644
index 0000000..d1ea56b
--- /dev/null
+++ b/test/996-breakpoint-obsolete/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `996-breakpoint-obsolete`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-996-breakpoint-obsolete",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-996-breakpoint-obsolete-expected-stdout",
+        ":art-run-test-996-breakpoint-obsolete-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-996-breakpoint-obsolete-expected-stdout",
+    out: ["art-run-test-996-breakpoint-obsolete-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-996-breakpoint-obsolete-expected-stderr",
+    out: ["art-run-test-996-breakpoint-obsolete-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/082-inline-execute/expected.txt b/test/996-breakpoint-obsolete/expected-stderr.txt
similarity index 100%
copy from test/082-inline-execute/expected.txt
copy to test/996-breakpoint-obsolete/expected-stderr.txt
diff --git a/test/996-breakpoint-obsolete/expected.txt b/test/996-breakpoint-obsolete/expected-stdout.txt
similarity index 100%
rename from test/996-breakpoint-obsolete/expected.txt
rename to test/996-breakpoint-obsolete/expected-stdout.txt
diff --git a/test/997-single-step/Android.bp b/test/997-single-step/Android.bp
new file mode 100644
index 0000000..45d29ab
--- /dev/null
+++ b/test/997-single-step/Android.bp
@@ -0,0 +1,40 @@
+// Generated by `regen-test-files`. Do not edit manually.
+
+// Build rules for ART run-test `997-single-step`.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+// Test's Dex code.
+java_test {
+    name: "art-run-test-997-single-step",
+    defaults: ["art-run-test-defaults"],
+    test_config_template: ":art-run-test-target-no-test-suite-tag-template",
+    srcs: ["src/**/*.java"],
+    data: [
+        ":art-run-test-997-single-step-expected-stdout",
+        ":art-run-test-997-single-step-expected-stderr",
+    ],
+}
+
+// Test's expected standard output.
+genrule {
+    name: "art-run-test-997-single-step-expected-stdout",
+    out: ["art-run-test-997-single-step-expected-stdout.txt"],
+    srcs: ["expected-stdout.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
+
+// Test's expected standard error.
+genrule {
+    name: "art-run-test-997-single-step-expected-stderr",
+    out: ["art-run-test-997-single-step-expected-stderr.txt"],
+    srcs: ["expected-stderr.txt"],
+    cmd: "cp -f $(in) $(out)",
+}
diff --git a/test/581-rtp/expected.txt b/test/997-single-step/expected-stderr.txt
similarity index 100%
copy from test/581-rtp/expected.txt
copy to test/997-single-step/expected-stderr.txt
diff --git a/test/997-single-step/expected.txt b/test/997-single-step/expected-stdout.txt
similarity index 100%
rename from test/997-single-step/expected.txt
rename to test/997-single-step/expected-stdout.txt
diff --git a/test/998-redefine-use-after-free/expected.txt b/test/998-redefine-use-after-free/expected-stderr.txt
similarity index 100%
rename from test/998-redefine-use-after-free/expected.txt
rename to test/998-redefine-use-after-free/expected-stderr.txt
diff --git a/test/998-redefine-use-after-free/expected.txt b/test/998-redefine-use-after-free/expected-stdout.txt
similarity index 100%
copy from test/998-redefine-use-after-free/expected.txt
copy to test/998-redefine-use-after-free/expected-stdout.txt
diff --git a/test/674-hiddenapi/expected.txt b/test/999-redefine-hiddenapi/expected-stderr.txt
similarity index 100%
copy from test/674-hiddenapi/expected.txt
copy to test/999-redefine-hiddenapi/expected-stderr.txt
diff --git a/test/999-redefine-hiddenapi/expected.txt b/test/999-redefine-hiddenapi/expected-stdout.txt
similarity index 100%
rename from test/999-redefine-hiddenapi/expected.txt
rename to test/999-redefine-hiddenapi/expected-stdout.txt
diff --git a/test/999-redefine-hiddenapi/hiddenapi-flags.csv b/test/999-redefine-hiddenapi/hiddenapi-flags.csv
index 7f632d3..b3bfe0a 100644
--- a/test/999-redefine-hiddenapi/hiddenapi-flags.csv
+++ b/test/999-redefine-hiddenapi/hiddenapi-flags.csv
@@ -1,2 +1,2 @@
-Lart/Test999;->foo()V,blacklist
-Lart/Test999;->bar:I,blacklist
+Lart/Test999;->foo()V,blocked
+Lart/Test999;->bar:I,blocked
diff --git a/test/Android.bp b/test/Android.bp
index 0f09fcc..fbef1ff 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -16,10 +16,56 @@
 
 // ART gtests.
 
-art_cc_defaults {
-    name: "art_test_defaults",
-    host_supported: true,
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+soong_config_module_type_import {
+    from: "art/build/SoongConfig.bp",
+    module_types: [
+        "art_module_cc_defaults",
+    ],
+}
+
+// Properties common to `art_test_defaults` and `art_standalone_test_defaults`.
+art_module_cc_defaults {
+    name: "art_test_common_defaults",
     target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    cflags: [
+        "-Wno-frame-larger-than=",
+    ],
+}
+
+art_module_cc_defaults {
+    name: "art_test_defaults",
+    defaults: [
+        "art_test_common_defaults",
+    ],
+    host_supported: true,
+    soong_config_variables: {
+        source_build: {
+            target: {
+                android: {
+                    test_for: [
+                        "com.android.art",
+                        "com.android.art.debug",
+                    ],
+                },
+            },
+        },
+    },
+    target: {
+        // The following set of relative_install_paths installs the library in a
+        // location that will be available as java.library.path in run tests.
         android_arm: {
             relative_install_path: "art/arm",
         },
@@ -32,47 +78,74 @@
         android_x86_64: {
             relative_install_path: "art/x86_64",
         },
-        darwin: {
-            enabled: false,
-        },
     },
-    cflags: [
-        "-Wno-frame-larger-than=",
-    ],
+    // Tests aren't generally included in any APEX, but this is necessary to
+    // avoid duplicate install rules for them by making them unavailable to platform.
     apex_available: [
         "com.android.art.debug",
     ],
 }
 
+// Variant of art_test_defaults that installs the library in a location which
+// will be added to the default namespace, and hence also the com_android_art
+// namespace. That allows the library to have shared_libs dependencies on all
+// ART internal libraries.
+//
+// Currently this only works for run tests where run-test-jar sets
+// LD_LIBRARY_PATH and NATIVELOADER_DEFAULT_NAMESPACE_LIBS.
 art_cc_defaults {
-    name: "art_gtest_defaults",
-    test_per_src: true,
-    // These really are gtests, but the gtest library comes from libart-gtest.so
-    gtest: false,
-    defaults: [
-        "art_test_defaults",
-        "art_debug_defaults",
-        "art_defaults",
+    name: "art_test_internal_library_defaults",
+    defaults: ["art_test_defaults"],
+    target: {
+        android_arm: {
+            relative_install_path: "com.android.art/lib",
+        },
+        android_arm64: {
+            relative_install_path: "com.android.art/lib64",
+        },
+        android_x86: {
+            relative_install_path: "com.android.art/lib",
+        },
+        android_x86_64: {
+            relative_install_path: "com.android.art/lib64",
+        },
+    },
+}
+
+// Test configuration template for standalone ART gtests on target (not bundled with the ART APEX).
+filegroup {
+    name: "art-gtests-target-standalone-template",
+    srcs: [
+        "art-gtests-target-standalone-template.xml",
     ],
+}
+
+art_cc_defaults {
+    name: "art_standalone_test_defaults",
+    defaults: [
+        "art_test_common_defaults",
+    ],
+    // Standalone ART gtests are only supported on device for now.
+    // TODO: Add support for host standalone ART gtests. Note that they should not differ much
+    // from the original ("non-standalone") host gtests, as the latter are not really bundled with
+    // the host ART APEX / artifacts (unlike their device counterparts); but as we plan to remove
+    // the ART gtests bundled with the ART APEX, we'll have to support the host case here
+    // eventually.
+    host_supported: false,
+    test_config_template: ":art-gtests-target-standalone-template",
+}
+
+// Properties common to `art_gtest_defaults` and `art_standalone_gtest_defaults`.
+art_cc_defaults {
+    name: "art_gtest_common_defaults",
+    // These really are gtests, but the gtest library comes from `libart(d)-gtest.so`.
+    gtest: false,
 
     shared_libs: [
-        "libartd",
-        "libartd-disassembler",
-        "libvixld",
-        "libart-gtest",
-        "libdexfiled",
-        "libprofiled",
-        "libartbased",
-
         "libbase",
-        "libicuuc",
-        "libicui18n",
-        "libnativehelper",
+        "liblog",
         "libz",
     ],
-    whole_static_libs: [
-        "libsigchain",
-    ],
 
     target: {
         linux: {
@@ -96,30 +169,124 @@
                 "libziparchive",
             ],
         },
-        android: {
-            shared_libs: [
-                "liblog",
-            ],
-        },
     },
 }
 
 art_cc_defaults {
-    name: "libart-gtest-defaults",
-    host_supported: true,
+    name: "art_gtest_defaults",
     defaults: [
+        "art_test_defaults",
+        "art_gtest_common_defaults",
         "art_debug_defaults",
         "art_defaults",
     ],
+
+    test_suites: ["art-host-tests"],
+    test_options: {
+        test_suite_tag: ["art-host-gtest"],
+    },
+
     shared_libs: [
         "libartd",
-        "libartd-compiler",
+        "libartd-disassembler",
+        "libartd-gtest",
         "libdexfiled",
         "libprofiled",
         "libartbased",
+
+        // Library `libnativehelper` needs to appear after `libartd` here,
+        // otherwise the following tests from module `libartd-runtime-gtest`
+        // will fail because `art/runtime/jni/java_vm_ext.cc` and
+        // `libnativehelper/JniInvocation.c` define symbols with the same name
+        // (e.g. `JNI_GetDefaultJavaVMInitArgs`) and the link order does matter
+        // for these tests:
+        // - JavaVmExtTest#JNI_GetDefaultJavaVMInitArgs
+        // - JavaVmExtTest#JNI_GetCreatedJavaVMs
+        // - JavaVmExtTest#AttachCurrentThread
+        // - JavaVmExtTest#AttachCurrentThreadAsDaemon
+        // - JavaVmExtTest#AttachCurrentThread_SmallStack
+        "libnativehelper",
+    ],
+}
+
+art_cc_defaults {
+    name: "art_standalone_gtest_defaults",
+    defaults: [
+        // Note: We don't include "art_debug_defaults" here, as standalone ART
+        // gtests link with the "non-d" versions of the libraries contained in
+        // the ART APEX, so that they can be used with all ART APEX flavors
+        // (including the Release ART APEX).
+        "art_standalone_test_defaults",
+        "art_gtest_common_defaults",
+        "art_defaults",
+    ],
+
+    test_suites: [
+        "general-tests",
+        "mts-art",
+    ],
+
+    // Support multilib variants (using different suffix per sub-architecture), which is needed on
+    // build targets with secondary architectures, as the MTS test suite packaging logic flattens
+    // all test artifacts into a single `testcases` directory.
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+
+    // We use the "non-d" variants of libraries, as the Release ART APEX does
+    // not contain the "d" (debug) variants.
+    shared_libs: [
+        "libart",
+        "libart-disassembler",
+        "libdexfile",
+        "libprofile",
+        "libartbase",
+
+        // Library `libnativehelper` needs to appear after `libart` here,
+        // otherwise the following tests from module `libart-runtime-gtest`
+        // will fail because `art/runtime/jni/java_vm_ext.cc` and
+        // `libnativehelper/JniInvocation.c` define symbols with the same name
+        // (e.g. `JNI_GetDefaultJavaVMInitArgs`) and the link order does matter
+        // for these tests:
+        // - JavaVmExtTest#JNI_GetDefaultJavaVMInitArgs
+        // - JavaVmExtTest#JNI_GetCreatedJavaVMs
+        // - JavaVmExtTest#AttachCurrentThread
+        // - JavaVmExtTest#AttachCurrentThreadAsDaemon
+        // - JavaVmExtTest#AttachCurrentThread_SmallStack
+        "libnativehelper",
     ],
     static_libs: [
-        "libgtest",
+        // For now, link `libart-gtest` statically for simplicity, to save the
+        // added complexity to package it in test suites (along with other test
+        // artifacts) and install it on device during tests.
+        // TODO(b/192070541): Consider linking `libart-gtest` dynamically.
+        "libart-gtest",
+    ],
+
+    test_for: [
+        "com.android.art",
+        "com.android.art.debug",
+    ],
+}
+
+// Properties common to `libart-gtest-defaults` and `libartd-gtest-defaults`.
+art_cc_defaults {
+    name: "libart-gtest-common-defaults",
+    defaults: [
+        "art_defaults",
+    ],
+    host_supported: true,
+    shared_libs: [
+        "liblog",
+    ],
+    static_libs: [
+        "libgtest_isolated",
     ],
     target: {
         android32: {
@@ -142,17 +309,32 @@
     },
     apex_available: [
         "com.android.art.debug",
+        // TODO(b/183882457): This lib doesn't go into com.android.art, but
+        // apex_available lists need to be the same for internal libs to avoid
+        // stubs, and this depends on libdexfiled and others.
+        "com.android.art",
     ],
 }
 
-art_cc_library {
-    name: "libart-gtest",
-    host_supported: true,
-    whole_static_libs: [
-        "libart-compiler-gtest",
-        "libart-runtime-gtest",
-        "libartbase-art-gtest",
-        "libgtest",
+art_cc_defaults {
+    name: "libart-gtest-defaults",
+    defaults: [
+        "libart-gtest-common-defaults",
+    ],
+    shared_libs: [
+        "libart",
+        "libart-compiler",
+        "libdexfile",
+        "libprofile",
+        "libartbase",
+    ],
+}
+
+art_cc_defaults {
+    name: "libartd-gtest-defaults",
+    defaults: [
+        "art_debug_defaults",
+        "libart-gtest-common-defaults",
     ],
     shared_libs: [
         "libartd",
@@ -160,8 +342,26 @@
         "libdexfiled",
         "libprofiled",
         "libartbased",
+    ],
+}
+
+// Properties common to `libart-gtest` and `libartd-gtest`.
+art_cc_defaults {
+    name: "libart-gtest-common",
+    defaults: [
+        "art_defaults",
+    ],
+    host_supported: true,
+    srcs: [
+        "common/gtest_main.cc",
+    ],
+    whole_static_libs: [
+        "libgtest_isolated",
+    ],
+    shared_libs: [
         "libbase",
         "libbacktrace",
+        "liblog",
     ],
     target: {
         darwin: {
@@ -170,11 +370,103 @@
     },
     apex_available: [
         "com.android.art.debug",
+        // TODO(b/183882457): This lib doesn't go into com.android.art, but
+        // apex_available lists need to be the same for internal libs to avoid
+        // stubs, and this depends on libdexfiled and others.
+        "com.android.art",
+    ],
+}
+
+art_cc_library {
+    name: "libart-gtest",
+    defaults: [
+        "libart-gtest-common",
+    ],
+    whole_static_libs: [
+        "libart-compiler-gtest",
+        "libart-runtime-gtest",
+        "libartbase-art-gtest",
+    ],
+    shared_libs: [
+        "libart",
+        "libart-compiler",
+        "libdexfile",
+        "libprofile",
+        "libartbase",
+    ],
+}
+
+art_cc_library {
+    name: "libartd-gtest",
+    defaults: [
+        "art_debug_defaults",
+        "libart-gtest-common",
+    ],
+    whole_static_libs: [
+        "libartd-compiler-gtest",
+        "libartd-runtime-gtest",
+        "libartbased-art-gtest",
+    ],
+    shared_libs: [
+        "libartd",
+        "libartd-compiler",
+        "libdexfiled",
+        "libprofiled",
+        "libartbased",
     ],
 }
 
 // ART run-tests.
 
+// Test configuration template for ART run-tests on target expected to run
+// successfully, and as such tagged as part of TradeFed's `art-target-run-test`
+// test suite via the `test-suite-tag`.
+filegroup {
+    name: "art-run-test-target-template",
+    srcs: [
+        "art-run-test-target-template.xml",
+    ],
+}
+
+// Test configuration template for ART run-tests on target expected to run
+// successfully, and as such *not* tagged as part of TradeFed's
+// `art-target-run-test` test suite via the `test-suite-tag`. This is as
+// temporary measure, while we add proper support for all ART (target) run-tests
+// to TradeFed (b/147818031).
+filegroup {
+    name: "art-run-test-target-no-test-suite-tag-template",
+    srcs: [
+        "art-run-test-target-no-test-suite-tag-template.xml",
+    ],
+}
+
+java_defaults {
+    name: "art-run-test-defaults",
+
+    // Compile against the "core" bootclasspath, not the "default" one (current
+    // platform) -- use the same settings as Libcore tests (see e.g. the
+    // definition of module `core-tests` in libcore/JavaLibrary.bp).
+    //
+    // Note: The legacy way to build ART run-tests uses the
+    // `javac_with_bootclasspath` function defined in `test/etc/default-build`.
+    // See also `tools/javac-helper.sh`.
+    sdk_version: "none",
+    system_modules: "core-all-system-modules",
+
+    // Some ART run-tests contain constructs which break ErrorProne checks;
+    // disable them on `errorprone` builds.
+    errorprone: {
+        javacflags: ["-XepDisableAllChecks"],
+    },
+    test_suites: [
+        "general-tests",
+        "mts-art",
+    ],
+    host_required: [
+        "art-run-test-checker",
+    ],
+}
+
 art_cc_test_library {
     name: "libarttest",
     defaults: ["libarttest-defaults"],
@@ -232,12 +524,13 @@
 cc_defaults {
     name: "libartagent-defaults",
     defaults: [
-        "art_test_defaults",
+        "art_test_internal_library_defaults",
         "art_defaults",
     ],
     shared_libs: [
         "libbacktrace",
         "libbase",
+        "liblog",
         "libnativehelper",
     ],
 }
@@ -272,7 +565,7 @@
 art_cc_defaults {
     name: "libtiagent-base-defaults",
     defaults: [
-        "art_test_defaults",
+        "art_test_internal_library_defaults",
         "art_defaults",
         // Not derived from libartagent-defaults for NDK.
     ],
@@ -402,6 +695,7 @@
         "1963-add-to-dex-classloader-in-memory/check_memfd_create.cc",
         "2012-structural-redefinition-failures-jni-id/set-jni-id-used.cc",
         "2031-zygote-compiled-frame-deopt/native-wait.cc",
+        "2038-hiddenapi-jvmti-ext/hiddenapi_ext.cc",
     ],
     static_libs: [
         "libz",
@@ -437,6 +731,14 @@
 cc_library_static {
     name: "libctstiagent",
     defaults: ["libtiagent-base-defaults"],
+
+    // TODO(b/187288515): Providing this as a prebuilt introduces an issue with
+    // sdk_version propagation. Temporarily use the source library instead,
+    // which means we need to override the logic inherited from art_defaults and
+    // art_test_internal_library_defaults that disables sources when not
+    // building ART from sources.
+    enabled: true,
+
     visibility: [
         "//cts/hostsidetests/jvmti:__subpackages__",
     ],
@@ -536,7 +838,7 @@
 cc_defaults {
     name: "libarttest-defaults",
     defaults: [
-        "art_test_defaults",
+        "art_test_internal_library_defaults",
         "art_defaults",
     ],
     srcs: [
@@ -561,6 +863,7 @@
         "172-app-image-twice/debug_print_class.cc",
         "177-visibly-initialized-deadlock/visibly_initialized.cc",
         "178-app-image-native-method/native_methods.cc",
+        "179-nonvirtual-jni/nonvirtual-call.cc",
         "1945-proxy-method-arguments/get_args.cc",
         "203-multi-checkpoint/multi_checkpoint.cc",
         "305-other-fault-handler/fault_handler.cc",
@@ -589,6 +892,7 @@
         "708-jit-cache-churn/jit.cc",
         "720-thread-priority/thread_priority.cc",
         "800-smali/jni.cc",
+        "817-hiddenapi/test_native.cc",
         "909-attach-agent/disallow_debugging.cc",
         "1001-app-image-regions/app_image_regions.cc",
         "1002-notify-startup/startup_interface.cc",
@@ -597,19 +901,24 @@
         "1985-structural-redefine-stack-scope/stack_scope.cc",
         "2011-stack-walk-concurrent-instrument/stack_walk_concurrent.cc",
         "2031-zygote-compiled-frame-deopt/native-wait.cc",
+        "2033-shutdown-mechanics/native_shutdown.cc",
+        "2036-jni-filechannel/jni_filechannel.cc",
+        "2037-thread-name-inherit/thread_name_inherit.cc",
         "common/runtime_state.cc",
         "common/stack_inspect.cc",
     ],
     shared_libs: [
         "libbacktrace",
         "libbase",
+        "liblog",
         "libnativehelper",
     ],
 }
 
-filegroup {
+java_library {
     name: "art_cts_jvmti_test_library",
     visibility: [
+        "//art:__subpackages__",
         "//cts/hostsidetests/jvmti:__subpackages__",
     ],
     srcs: [
@@ -770,145 +1079,144 @@
         "2006-virtual-structural-finalizing/src-art/art/Test2006.java",
         "2007-virtual-structural-finalizable/src-art/art/Test2007.java",
     ],
+    sdk_version: "core_platform",
 }
 
 // CTS test runner in cts/hostsidetests/jvmti looks for an expected test
 // result for the test NN in the file results.NN.expected.txt while in the
-// source tree each expected test result is in the NN-xxxx/expected.txt.
+// source tree each expected test result is in the NN-xxxx/expected-stdout.txt.
 // Copy+rename them them to a temporary directory and them zip them.
 java_genrule {
-    name: "expected_cts_outputs",
-    visibility: [
-        "//cts/hostsidetests/jvmti:__subpackages__",
-    ],
+    name: "expected_cts_outputs_gen",
     srcs: [
-        "901-hello-ti-agent/expected.txt",
-        "902-hello-transformation/expected.txt",
-        "903-hello-tagging/expected.txt",
-        "904-object-allocation/expected.txt",
-        "905-object-free/expected.txt",
-        "906-iterate-heap/expected.txt",
-        "907-get-loaded-classes/expected.txt",
-        "908-gc-start-finish/expected.txt",
-        "910-methods/expected.txt",
+        "901-hello-ti-agent/expected-stdout.txt",
+        "902-hello-transformation/expected-stdout.txt",
+        "903-hello-tagging/expected-stdout.txt",
+        "904-object-allocation/expected-stdout.txt",
+        "905-object-free/expected-stdout.txt",
+        "906-iterate-heap/expected-stdout.txt",
+        "907-get-loaded-classes/expected-stdout.txt",
+        "908-gc-start-finish/expected-stdout.txt",
+        "910-methods/expected-stdout.txt",
         "911-get-stack-trace/expected-cts-version.txt",
-        "912-classes/expected.txt",
-        "913-heaps/expected.txt",
-        "914-hello-obsolescence/expected.txt",
-        "915-obsolete-2/expected.txt",
-        "917-fields-transformation/expected.txt",
-        "918-fields/expected.txt",
-        "919-obsolete-fields/expected.txt",
-        "920-objects/expected.txt",
-        "922-properties/expected.txt",
-        "923-monitors/expected.txt",
-        "924-threads/expected.txt",
-        "925-threadgroups/expected.txt",
-        "926-multi-obsolescence/expected.txt",
-        "927-timers/expected.txt",
-        "928-jni-table/expected.txt",
-        "930-hello-retransform/expected.txt",
-        "931-agent-thread/expected.txt",
-        "932-transform-saves/expected.txt",
-        "933-misc-events/expected.txt",
-        "940-recursive-obsolete/expected.txt",
-        "942-private-recursive/expected.txt",
-        "944-transform-classloaders/expected.txt",
-        "945-obsolete-native/expected.txt",
-        "947-reflect-method/expected.txt",
-        "951-threaded-obsolete/expected.txt",
-        "982-ok-no-retransform/expected.txt",
-        "983-source-transform-verify/expected.txt",
-        "984-obsolete-invoke/expected.txt",
-        "985-re-obsolete/expected.txt",
-        "986-native-method-bind/expected.txt",
-        "988-method-trace/expected.txt",
-        "989-method-trace-throw/expected.txt",
-        "990-field-trace/expected.txt",
-        "991-field-trace-2/expected.txt",
-        "992-source-data/expected.txt",
-        "993-breakpoints/expected.txt",
-        "994-breakpoint-line/expected.txt",
-        "995-breakpoints-throw/expected.txt",
-        "996-breakpoint-obsolete/expected.txt",
-        "997-single-step/expected.txt",
-        "1900-track-alloc/expected.txt",
-        "1901-get-bytecodes/expected.txt",
-        "1902-suspend/expected.txt",
-        "1903-suspend-self/expected.txt",
-        "1904-double-suspend/expected.txt",
-        "1906-suspend-list-me-first/expected.txt",
-        "1907-suspend-list-self-twice/expected.txt",
-        "1908-suspend-native-resume-self/expected.txt",
-        "1909-per-agent-tls/expected.txt",
-        "1910-transform-with-default/expected.txt",
-        "1911-get-local-var-table/expected.txt",
-        "1912-get-set-local-primitive/expected.txt",
-        "1913-get-set-local-objects/expected.txt",
-        "1914-get-local-instance/expected.txt",
-        "1915-get-set-local-current-thread/expected.txt",
-        "1916-get-set-current-frame/expected.txt",
-        "1917-get-stack-frame/expected.txt",
-        "1920-suspend-native-monitor/expected.txt",
-        "1921-suspend-native-recursive-monitor/expected.txt",
-        "1922-owned-monitors-info/expected.txt",
-        "1923-frame-pop/expected.txt",
-        "1924-frame-pop-toggle/expected.txt",
-        "1925-self-frame-pop/expected.txt",
-        "1926-missed-frame-pop/expected.txt",
-        "1927-exception-event/expected.txt",
-        "1928-exception-event-exception/expected.txt",
-        "1930-monitor-info/expected.txt",
-        "1931-monitor-events/expected.txt",
-        "1932-monitor-events-misc/expected.txt",
-        "1933-monitor-current-contended/expected.txt",
-        "1934-jvmti-signal-thread/expected.txt",
-        "1936-thread-end-events/expected.txt",
-        "1937-transform-soft-fail/expected.txt",
-        "1939-proxy-frames/expected.txt",
-        "1941-dispose-stress/expected.txt",
-        "1942-suspend-raw-monitor-exit/expected.txt",
-        "1943-suspend-raw-monitor-wait/expected.txt",
-        "1953-pop-frame/expected.txt",
-        "1958-transform-try-jit/expected.txt",
-        "1962-multi-thread-events/expected.txt",
-        "1963-add-to-dex-classloader-in-memory/expected.txt",
-        "1967-get-set-local-bad-slot/expected.txt",
-        "1968-force-early-return/expected.txt",
-        "1969-force-early-return-void/expected.txt",
-        "1970-force-early-return-long/expected.txt",
-        "1971-multi-force-early-return/expected.txt",
-        "1974-resize-array/expected.txt",
-        "1975-hello-structural-transformation/expected.txt",
-        "1976-hello-structural-static-methods/expected.txt",
-        "1977-hello-structural-obsolescence/expected.txt",
-        "1978-regular-obsolete-then-structural-obsolescence/expected.txt",
-        "1979-threaded-structural-transformation/expected.txt",
+        "912-classes/expected-stdout.txt",
+        "913-heaps/expected-stdout.txt",
+        "914-hello-obsolescence/expected-stdout.txt",
+        "915-obsolete-2/expected-stdout.txt",
+        "917-fields-transformation/expected-stdout.txt",
+        "918-fields/expected-stdout.txt",
+        "919-obsolete-fields/expected-stdout.txt",
+        "920-objects/expected-stdout.txt",
+        "922-properties/expected-stdout.txt",
+        "923-monitors/expected-stdout.txt",
+        "924-threads/expected-stdout.txt",
+        "925-threadgroups/expected-stdout.txt",
+        "926-multi-obsolescence/expected-stdout.txt",
+        "927-timers/expected-stdout.txt",
+        "928-jni-table/expected-stdout.txt",
+        "930-hello-retransform/expected-stdout.txt",
+        "931-agent-thread/expected-stdout.txt",
+        "932-transform-saves/expected-stdout.txt",
+        "933-misc-events/expected-stdout.txt",
+        "940-recursive-obsolete/expected-stdout.txt",
+        "942-private-recursive/expected-stdout.txt",
+        "944-transform-classloaders/expected-stdout.txt",
+        "945-obsolete-native/expected-stdout.txt",
+        "947-reflect-method/expected-stdout.txt",
+        "951-threaded-obsolete/expected-stdout.txt",
+        "982-ok-no-retransform/expected-stdout.txt",
+        "983-source-transform-verify/expected-stdout.txt",
+        "984-obsolete-invoke/expected-stdout.txt",
+        "985-re-obsolete/expected-stdout.txt",
+        "986-native-method-bind/expected-stdout.txt",
+        "988-method-trace/expected-stdout.txt",
+        "989-method-trace-throw/expected-stdout.txt",
+        "990-field-trace/expected-stdout.txt",
+        "991-field-trace-2/expected-stdout.txt",
+        "992-source-data/expected-stdout.txt",
+        // Need to avoid using hidden-apis
+        "993-breakpoints/expected_cts.txt",
+        "994-breakpoint-line/expected-stdout.txt",
+        "995-breakpoints-throw/expected-stdout.txt",
+        "996-breakpoint-obsolete/expected-stdout.txt",
+        "997-single-step/expected-stdout.txt",
+        "1900-track-alloc/expected-stdout.txt",
+        "1901-get-bytecodes/expected-stdout.txt",
+        "1902-suspend/expected-stdout.txt",
+        "1903-suspend-self/expected-stdout.txt",
+        "1904-double-suspend/expected-stdout.txt",
+        "1906-suspend-list-me-first/expected-stdout.txt",
+        "1907-suspend-list-self-twice/expected-stdout.txt",
+        "1908-suspend-native-resume-self/expected-stdout.txt",
+        "1909-per-agent-tls/expected-stdout.txt",
+        "1910-transform-with-default/expected-stdout.txt",
+        "1911-get-local-var-table/expected-stdout.txt",
+        "1912-get-set-local-primitive/expected-stdout.txt",
+        "1913-get-set-local-objects/expected-stdout.txt",
+        "1914-get-local-instance/expected-stdout.txt",
+        "1915-get-set-local-current-thread/expected-stdout.txt",
+        "1916-get-set-current-frame/expected-stdout.txt",
+        "1917-get-stack-frame/expected-stdout.txt",
+        "1920-suspend-native-monitor/expected-stdout.txt",
+        "1921-suspend-native-recursive-monitor/expected-stdout.txt",
+        "1922-owned-monitors-info/expected-stdout.txt",
+        "1923-frame-pop/expected-stdout.txt",
+        "1924-frame-pop-toggle/expected-stdout.txt",
+        "1925-self-frame-pop/expected-stdout.txt",
+        "1926-missed-frame-pop/expected-stdout.txt",
+        "1927-exception-event/expected-stdout.txt",
+        "1928-exception-event-exception/expected-stdout.txt",
+        "1930-monitor-info/expected-stdout.txt",
+        "1931-monitor-events/expected-stdout.txt",
+        "1932-monitor-events-misc/expected-stdout.txt",
+        "1933-monitor-current-contended/expected-stdout.txt",
+        "1934-jvmti-signal-thread/expected-stdout.txt",
+        "1936-thread-end-events/expected-stdout.txt",
+        "1937-transform-soft-fail/expected-stdout.txt",
+        "1939-proxy-frames/expected-stdout.txt",
+        "1941-dispose-stress/expected-stdout.txt",
+        "1942-suspend-raw-monitor-exit/expected-stdout.txt",
+        "1943-suspend-raw-monitor-wait/expected-stdout.txt",
+        "1953-pop-frame/expected-stdout.txt",
+        "1958-transform-try-jit/expected-stdout.txt",
+        "1962-multi-thread-events/expected-stdout.txt",
+        "1963-add-to-dex-classloader-in-memory/expected-stdout.txt",
+        "1967-get-set-local-bad-slot/expected-stdout.txt",
+        "1968-force-early-return/expected-stdout.txt",
+        "1969-force-early-return-void/expected-stdout.txt",
+        "1970-force-early-return-long/expected-stdout.txt",
+        "1971-multi-force-early-return/expected-stdout.txt",
+        "1974-resize-array/expected-stdout.txt",
+        "1975-hello-structural-transformation/expected-stdout.txt",
+        "1976-hello-structural-static-methods/expected-stdout.txt",
+        "1977-hello-structural-obsolescence/expected-stdout.txt",
+        "1978-regular-obsolete-then-structural-obsolescence/expected-stdout.txt",
+        "1979-threaded-structural-transformation/expected-stdout.txt",
         // TODO Requires VarHandles to be un-@hide. See b/64382372
-        // "test/1981-structural-redef-private-method-handles/expected.txt",
+        // "test/1981-structural-redef-private-method-handles/expected-stdout.txt",
         "1981-structural-redef-private-method-handles/expected_no_mh.txt",
-        "1982-no-virtuals-structural-redefinition/expected.txt",
+        "1982-no-virtuals-structural-redefinition/expected-stdout.txt",
         // JNI-id use can change the outcome of this test on device.
         "1983-structural-redefinition-failures/expected-cts.txt",
-        "1984-structural-redefine-field-trace/expected.txt",
-        "1988-multi-structural-redefine/expected.txt",
-        "1989-transform-bad-monitor/expected.txt",
-        "1990-structural-bad-verify/expected.txt",
-        "1991-hello-structural-retransform/expected.txt",
-        "1992-retransform-no-such-field/expected.txt",
-        "1994-final-virtual-structural/expected.txt",
-        "1995-final-virtual-structural-multithread/expected.txt",
-        "1996-final-override-virtual-structural/expected.txt",
-        "1997-structural-shadow-method/expected.txt",
-        "1998-structural-shadow-field/expected.txt",
-        "1999-virtual-structural/expected.txt",
-        "2001-virtual-structural-multithread/expected.txt",
-        "2002-virtual-structural-initializing/expected.txt",
-        "2003-double-virtual-structural/expected.txt",
-        "2004-double-virtual-structural-abstract/expected.txt",
-        "2005-pause-all-redefine-multithreaded/expected.txt",
-        "2006-virtual-structural-finalizing/expected.txt",
-        "2007-virtual-structural-finalizable/expected.txt",
+        "1984-structural-redefine-field-trace/expected-stdout.txt",
+        "1988-multi-structural-redefine/expected-stdout.txt",
+        "1989-transform-bad-monitor/expected-stdout.txt",
+        "1990-structural-bad-verify/expected-stdout.txt",
+        "1991-hello-structural-retransform/expected-stdout.txt",
+        "1992-retransform-no-such-field/expected-stdout.txt",
+        "1994-final-virtual-structural/expected-stdout.txt",
+        "1995-final-virtual-structural-multithread/expected-stdout.txt",
+        "1996-final-override-virtual-structural/expected-stdout.txt",
+        "1997-structural-shadow-method/expected-stdout.txt",
+        "1998-structural-shadow-field/expected-stdout.txt",
+        "1999-virtual-structural/expected-stdout.txt",
+        "2001-virtual-structural-multithread/expected-stdout.txt",
+        "2002-virtual-structural-initializing/expected-stdout.txt",
+        "2003-double-virtual-structural/expected-stdout.txt",
+        "2004-double-virtual-structural-abstract/expected-stdout.txt",
+        "2005-pause-all-redefine-multithreaded/expected-stdout.txt",
+        "2006-virtual-structural-finalizing/expected-stdout.txt",
+        "2007-virtual-structural-finalizable/expected-stdout.txt",
     ],
     out: ["expected_cts_outputs.jar"],
     tools: ["soong_zip"],
@@ -918,6 +1226,77 @@
         "$(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res",
 }
 
+// Wrap the expected_cts_outputs_gen inside a java library to make it easy
+// to export as a member of a module_exports.
+java_library {
+    name: "expected_cts_outputs",
+    visibility: [
+        "//art/build/sdk",
+        "//cts/hostsidetests/jvmti:__subpackages__",
+    ],
+    static_libs: [
+        "expected_cts_outputs_gen",
+    ],
+    sdk_version: "core_current",
+}
+
+art_cc_test {
+    name: "ArtGtestsTargetInstallApex",
+    defaults: [
+        // Enable only in source builds, where com.android.art.testing is
+        // available.
+        "art_module_source_build_defaults",
+    ],
+    data: [
+        // We need the ART testing apex, which contains all gtest binaries.
+        // Note that due to build system and linker constraints the gtests must be in the apex.
+        ":com.android.art.testing",
+    ],
+    // It seems that only device-tests build can create a valid apex.
+    test_suites: [
+        "device-tests",
+        "mts-art",
+    ],
+    test_config: "art-gtests-target-install-apex.xml",
+
+    // Support multilib variants (using different suffix per sub-architecture), which is needed on
+    // build targets with secondary architectures, as the MTS test suite packaging logic flattens
+    // all test artifacts into a single `testcases` directory.
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+    test_for: [
+        "com.android.art",
+        "com.android.art.debug",
+    ],
+}
+
+art_cc_test {
+    name: "ArtGtestsTargetChroot",
+    defaults: [
+        // Enable only in source builds, where com.android.art.testing is
+        // available.
+        "art_module_source_build_defaults",
+    ],
+    data: [
+        // We need the ART testing apex, which contains all gtest binaries.
+        // Note that due to build system and linker constraints the gtests must be in the apex.
+        ":com.android.art.testing",
+    ],
+    test_suites: ["general-tests"],
+    test_config: "art-gtests-target-chroot.xml",
+    test_for: [
+        "com.android.art",
+        "com.android.art.debug",
+    ],
+}
+
 filegroup {
     name: "art-gtest-jars",
     srcs: [
@@ -983,6 +1362,7 @@
         enabled: false,
     },
     sdk_version: "core_platform",
+    uncompress_dex: false,
 }
 
 // The following modules are just trivial compilations (non-trivial cases are the end).
@@ -1233,6 +1613,12 @@
     defaults: ["art-gtest-jars-defaults"],
 }
 
+java_library {
+    name: "art-gtest-jars-Dex2oatVdexTestDex",
+    srcs: ["Dex2oatVdexTestDex/**/*.java"],
+    defaults: ["art-gtest-jars-defaults"],
+}
+
 // The following cases are non-trivial.
 
 // Uncompress classes.dex files in the jar file.
@@ -1347,23 +1733,42 @@
     ],
 }
 
+// Smali compiled files.
+// Since they are not compiled by javac, we use different extension for them.
+// The .jar extension for them would cause subtle failures in the test infra,
+// which finds and opens all jar files and expects them to be valid zip files.
+
 genrule {
     name: "art-gtest-jars-VerifierDeps",
     defaults: ["art-gtest-jars-smali-defaults"],
     srcs: ["VerifierDeps/**/*.smali"],
-    out: ["art-gtest-jars-VerifierDeps.jar"],
+    out: ["art-gtest-jars-VerifierDeps.dex"],
 }
 
 genrule {
     name: "art-gtest-jars-VerifierDepsMulti",
     defaults: ["art-gtest-jars-smali-defaults"],
     srcs: ["VerifierDepsMulti/**/*.smali"],
-    out: ["art-gtest-jars-VerifierDepsMulti.jar"],
+    out: ["art-gtest-jars-VerifierDepsMulti.dex"],
 }
 
 genrule {
     name: "art-gtest-jars-VerifySoftFailDuringClinit",
     defaults: ["art-gtest-jars-smali-defaults"],
     srcs: ["VerifySoftFailDuringClinit/**/*.smali"],
-    out: ["art-gtest-jars-VerifySoftFailDuringClinit.jar"],
+    out: ["art-gtest-jars-VerifySoftFailDuringClinit.dex"],
+}
+
+genrule {
+    name: "art-gtest-jars-LinkageTest",
+    defaults: ["art-gtest-jars-smali-defaults"],
+    srcs: ["LinkageTest/*.smali"],
+    out: ["art-gtest-jars-LinkageTest.dex"],
+}
+
+genrule {
+    name: "art-gtest-jars-Dex2oatVdexPublicSdkDex",
+    defaults: ["art-gtest-jars-smali-defaults"],
+    srcs: ["Dex2oatVdexPublicSdkDex/*.smali"],
+    out: ["art-gtest-jars-Dex2oatVdexPublicSdkDex.dex"],
 }
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index c4e07d3..8b5aae4 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -19,7 +19,6 @@
 
 # Dependencies for actually running a run-test.
 TEST_ART_RUN_TEST_DEPENDENCIES := \
-  $(HOST_OUT_EXECUTABLES)/dx \
   $(HOST_OUT_EXECUTABLES)/d8 \
   $(HOST_OUT_EXECUTABLES)/hiddenapi \
   $(HOST_OUT_EXECUTABLES)/jasmin \
@@ -49,9 +48,6 @@
 # Also need signal_dumper.
 ART_TEST_TARGET_RUN_TEST_DEPENDENCIES += signal_dumper-target
 
-ART_TEST_TARGET_RUN_TEST_DEPENDENCIES += \
-  $(foreach jar,$(TARGET_TEST_CORE_JARS),$(TARGET_OUT_JAVA_LIBRARIES)/$(jar).jar)
-
 # All tests require the host executables. The tests also depend on the core images, but on
 # specific version depending on the compiler.
 ART_TEST_HOST_RUN_TEST_DEPENDENCIES := \
@@ -74,7 +70,8 @@
   $(ART_HOST_OUT_SHARED_LIBRARIES)/libopenjdkd$(ART_HOST_SHLIB_EXTENSION) \
   $(ART_HOST_OUT_SHARED_LIBRARIES)/libopenjdkjvmti$(ART_HOST_SHLIB_EXTENSION) \
   $(ART_HOST_OUT_SHARED_LIBRARIES)/libopenjdkjvmtid$(ART_HOST_SHLIB_EXTENSION) \
-  $(HOST_CORE_DEX_LOCATIONS) \
+  $(ART_HOST_DEX_DEPENDENCIES) \
+  $(HOST_I18N_DATA)
 
 ifneq ($(HOST_PREFER_32_BIT),true)
 ART_TEST_HOST_RUN_TEST_DEPENDENCIES += \
@@ -97,52 +94,15 @@
 
 endif
 
-# Host executables.
-host_prereq_rules := $(ART_TEST_HOST_RUN_TEST_DEPENDENCIES)
-
-# Required for jasmin and smali.
-host_prereq_rules += $(TEST_ART_RUN_TEST_DEPENDENCIES)
-
-define core-image-dependencies
-  image_suffix := $(3)
-  ifeq ($(3),regalloc_gc)
-    image_suffix:=optimizing
-  else
-    ifeq ($(3),jit)
-      image_suffix:=interpreter
-    endif
-  endif
-  ifeq ($(2),no-image)
-    $(1)_prereq_rules += $$($(call to-upper,$(1))_CORE_IMAGE_$$(image_suffix)_$(4))
-  else
-    ifeq ($(2),picimage)
-      $(1)_prereq_rules += $$($(call to-upper,$(1))_CORE_IMAGE_$$(image_suffix)_$(4))
-    else
-      ifeq ($(2),multipicimage)
-        $(1)_prereq_rules += $$($(call to-upper,$(1))_CORE_IMAGE_$$(image_suffix)_multi_$(4))
-      endif
-    endif
-  endif
-endef
-
-TARGET_TYPES := host target
-COMPILER_TYPES := jit interpreter optimizing regalloc_gc jit interp-ac speed-profile
-IMAGE_TYPES := picimage no-image multipicimage
-ALL_ADDRESS_SIZES := 64 32
-
-# Add core image dependencies required for given target - HOST or TARGET,
-# IMAGE_TYPE, COMPILER_TYPE and ADDRESS_SIZE to the prereq_rules.
-$(foreach target, $(TARGET_TYPES), \
-  $(foreach image, $(IMAGE_TYPES), \
-    $(foreach compiler, $(COMPILER_TYPES), \
-      $(foreach address_size, $(ALL_ADDRESS_SIZES), $(eval \
-        $(call core-image-dependencies,$(target),$(image),$(compiler),$(address_size)))))))
-
-test-art-host-run-test-dependencies : $(host_prereq_rules)
+test-art-host-run-test-dependencies : \
+      $(ART_TEST_HOST_RUN_TEST_DEPENDENCIES) $(TEST_ART_RUN_TEST_DEPENDENCIES) \
+      $(HOST_BOOT_IMAGE_JARS) $(HOST_BOOT_IMAGE) $(2ND_HOST_BOOT_IMAGE)
 .PHONY: test-art-host-run-test-dependencies
+test-art-run-test-dependencies : test-art-host-run-test-dependencies
+
 test-art-target-run-test-dependencies :
 .PHONY: test-art-target-run-test-dependencies
-test-art-run-test-dependencies : test-art-host-run-test-dependencies test-art-target-run-test-dependencies
+test-art-run-test-dependencies : test-art-target-run-test-dependencies
 .PHONY: test-art-run-test-dependencies
 
 # Create a rule to build and run a test group of the following form:
@@ -156,18 +116,12 @@
 	./art/test/testrunner/testrunner.py $$(args)
   build_target :=
   args :=
+
+  test-art-run-test : $(build_target)
 endef  # define-test-art-host-or-target-run-test-group
 
-$(foreach target, $(TARGET_TYPES), $(eval \
-  $(call define-test-art-host-or-target-run-test-group,$(target))))
+$(eval $(call define-test-art-host-or-target-run-test-group,target))
+$(eval $(call define-test-art-host-or-target-run-test-group,host))
 
-test-art-run-test : test-art-host-run-test test-art-target-run-test
-
-host_prereq_rules :=
-core-image-dependencies :=
 define-test-art-host-or-target-run-test-group :=
-TARGET_TYPES :=
-COMPILER_TYPES :=
-IMAGE_TYPES :=
-ALL_ADDRESS_SIZES :=
 LOCAL_PATH :=
diff --git a/test/Dex2oatVdexPublicSdkDex/Class.smali b/test/Dex2oatVdexPublicSdkDex/Class.smali
new file mode 100644
index 0000000..212631f
--- /dev/null
+++ b/test/Dex2oatVdexPublicSdkDex/Class.smali
@@ -0,0 +1,22 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+.class public Ljava/lang/Class;
+.super Ljava/lang/Object;
+
+.method static constructor <clinit>()V
+    .registers 0
+    return-void
+.end method
diff --git a/test/Dex2oatVdexPublicSdkDex/Integer.smali b/test/Dex2oatVdexPublicSdkDex/Integer.smali
new file mode 100644
index 0000000..6a26224
--- /dev/null
+++ b/test/Dex2oatVdexPublicSdkDex/Integer.smali
@@ -0,0 +1,47 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+.class public Ljava/lang/Integer;
+.super Ljava/lang/Number;
+
+.field public static final BYTES:I
+
+.method static constructor <clinit>()V
+    .registers 0
+    return-void
+.end method
+
+.method public constructor <init>(I)V
+    .registers 2
+    invoke-static {v0}, Ljava/lang/Integer;->throw()V
+.end method
+
+.method public static getInteger(Ljava/lang/String;)Ljava/lang/Integer;
+    .registers 1
+    invoke-static {v0}, Ljava/lang/Integer;->throw()V
+.end method
+
+.method public doubleValue()D
+    .registers 1
+    invoke-static {v0}, Ljava/lang/Integer;->throw()V
+.end method
+
+.method public static throw()V
+.registers 2
+    new-instance v0, Ljava/lang/RuntimeException;
+    const-string v1, "This is an error message"
+    invoke-direct {v0, v1}, Ljava/lang/RuntimeException;-><init>(Ljava/lang/String;)V
+    throw v0
+.end method
diff --git a/test/Dex2oatVdexPublicSdkDex/Number.smali b/test/Dex2oatVdexPublicSdkDex/Number.smali
new file mode 100644
index 0000000..340469a
--- /dev/null
+++ b/test/Dex2oatVdexPublicSdkDex/Number.smali
@@ -0,0 +1,35 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+.class public Ljava/lang/Number;
+.super Ljava/lang/Object;
+
+.method static constructor <clinit>()V
+    .registers 0
+    return-void
+.end method
+
+.method public constructor <init>()V
+    .registers 2
+    invoke-static {v0}, Ljava/lang/Number;->throw()V
+.end method
+
+.method public static throw()V
+.registers 2
+    new-instance v0, Ljava/lang/RuntimeException;
+    const-string v1, "This is an error message"
+    invoke-direct {v0, v1}, Ljava/lang/RuntimeException;-><init>(Ljava/lang/String;)V
+    throw v0
+.end method
diff --git a/test/Dex2oatVdexPublicSdkDex/Object.smali b/test/Dex2oatVdexPublicSdkDex/Object.smali
new file mode 100644
index 0000000..295a9e3
--- /dev/null
+++ b/test/Dex2oatVdexPublicSdkDex/Object.smali
@@ -0,0 +1,37 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+.class public Ljava/lang/Object;
+
+.method static constructor <clinit>()V
+    .registers 0
+    return-void
+.end method
+
+.method public constructor <init>()V
+    .registers 2
+    invoke-static {v0}, Ljava/lang/Object;->throw()V
+.end method
+
+.method public native notify()V
+.end method
+
+.method public static throw()V
+.registers 2
+    new-instance v0, Ljava/lang/RuntimeException;
+    const-string v1, "This is an error message"
+    invoke-direct {v0, v1}, Ljava/lang/RuntimeException;-><init>(Ljava/lang/String;)V
+    throw v0
+.end method
diff --git a/test/Dex2oatVdexPublicSdkDex/Readme.md b/test/Dex2oatVdexPublicSdkDex/Readme.md
new file mode 100644
index 0000000..5b3567a
--- /dev/null
+++ b/test/Dex2oatVdexPublicSdkDex/Readme.md
@@ -0,0 +1,6 @@
+This dex file redefines some popular java.lang classes in order to assist
+with testing sdk-based verification.
+
+Each of these classes only defines the stubs for a limited number of methods
+and fields. They are compiled into a dex file and passed to dex2oat to simulate
+a proper SDK-stub jars. The methods not declared here should not be resolved.
diff --git a/test/Dex2oatVdexTestDex/Dex2oatVdexTestDex.java b/test/Dex2oatVdexTestDex/Dex2oatVdexTestDex.java
new file mode 100644
index 0000000..e4862bd
--- /dev/null
+++ b/test/Dex2oatVdexTestDex/Dex2oatVdexTestDex.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+/**
+ * Check that the classes using publicly listed APIS are verified.
+ */
+
+class AccessPublicCtor {
+  public Integer foo() {
+    return new Integer(1);
+  }
+}
+
+class AccessPublicMethod {
+  public double foo(Integer i) {
+    return i.doubleValue();
+  }
+}
+
+class AccessPublicMethodFromParent {
+  public void foo(Integer i) {
+    i.notify();
+  }
+}
+
+class AccessPublicStaticMethod {
+  public Integer foo() {
+    return Integer.getInteger("1");
+  }
+}
+
+class AccessPublicStaticField {
+  public int foo() {
+    return Integer.BYTES;
+  }
+}
+
+/**
+ * Check that the classes using non publicly listed APIS are not verified.
+ */
+
+class AccessNonPublicCtor {
+  public Integer foo() {
+    return new Integer("1");
+  }
+}
+
+class AccessNonPublicMethod {
+  public float foo(Integer i) {
+    return i.floatValue();
+  }
+}
+
+class AccessNonPublicMethodFromParent {
+  public void foo(Integer i) {
+    i.notifyAll();
+  }
+}
+
+class AccessNonPublicStaticMethod {
+  public Integer foo() {
+    return Integer.getInteger("1", 0);
+  }
+}
+
+class AccessNonPublicStaticField {
+  public Class foo() {
+    return Integer.TYPE;
+  }
+}
diff --git a/test/DexToDexDecompiler/Main.java b/test/DexToDexDecompiler/Main.java
index 8f5075a..60f3049 100644
--- a/test/DexToDexDecompiler/Main.java
+++ b/test/DexToDexDecompiler/Main.java
@@ -16,7 +16,6 @@
 
 public class Main {
   Main() {
-    // Will be quickened with RETURN_VOID_NO_BARRIER.
   }
 
   public static void main() {
diff --git a/test/LinkageTest/Main.smali b/test/LinkageTest/Main.smali
new file mode 100644
index 0000000..267dacf
--- /dev/null
+++ b/test/LinkageTest/Main.smali
@@ -0,0 +1,21 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LMain;
+.super Ljava/lang/Object;
+
+.method public static main([Ljava/lang/String;)V
+  .registers 1
+  return-void
+.end method
diff --git a/test/LinkageTest/MyClassLoader.smali b/test/LinkageTest/MyClassLoader.smali
new file mode 100644
index 0000000..e06e9a0
--- /dev/null
+++ b/test/LinkageTest/MyClassLoader.smali
@@ -0,0 +1,22 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LMyClassLoader;
+.super Ldalvik/system/PathClassLoader;
+
+.method public static getNull()Ljava/lang/Object;
+  .registers 1
+  const v0, 0x0
+  return-object v0
+.end method
diff --git a/test/LinkageTest/Object.smali b/test/LinkageTest/Object.smali
new file mode 100644
index 0000000..35c6c77
--- /dev/null
+++ b/test/LinkageTest/Object.smali
@@ -0,0 +1,21 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public Ljava/lang/Object;
+
+.method public static $noinline$bar()LUnresolved;
+  .registers 1
+  const v0, 0x0
+  return-object v0
+.end method
diff --git a/test/MyClassNatives/MyClassNatives.java b/test/MyClassNatives/MyClassNatives.java
index 3d939d6..463fe3f 100644
--- a/test/MyClassNatives/MyClassNatives.java
+++ b/test/MyClassNatives/MyClassNatives.java
@@ -20,8 +20,7 @@
 /*
  * AUTOMATICALLY GENERATED FROM art/tools/mako-source-generator/...../MyClassNatives.java.mako
  *
- * !!! DO NOT EDIT DIRECTLY !!!
- *
+ * The tool is however not available, so the changes now need to be done by hand.
  */
 class MyClassNatives {
 
@@ -176,8 +175,6 @@
     @FastNative
     native double fooDD_Fast(double x, double y);
     @FastNative
-    synchronized native long fooJJ_synchronized_Fast(long x, long y);
-    @FastNative
     native Object fooIOO_Fast(int x, Object y, Object z);
     @FastNative
     static native Object fooSIOO_Fast(int x, Object y, Object z);
@@ -186,15 +183,13 @@
     @FastNative
     static native double fooSDD_Fast(double x, double y);
     @FastNative
-    static synchronized native Object fooSSIOO_Fast(int x, Object y, Object z);
-    @FastNative
     static native void arraycopy_Fast(Object src, int src_pos, Object dst, int dst_pos, int length);
     @FastNative
     native boolean compareAndSwapInt_Fast(Object obj, long offset, int expected, int newval);
     @FastNative
     static native int getText_Fast(long val1, Object obj1, long val2, Object obj2);
     @FastNative
-    synchronized native Object[] getSinkPropertiesNative_Fast(String path);
+    native Object[] getSinkPropertiesNative_Fast(String path);
 
     @FastNative
     native Class<?> instanceMethodThatShouldReturnClass_Fast();
diff --git a/test/OWNERS b/test/OWNERS
new file mode 100644
index 0000000..28d5064
--- /dev/null
+++ b/test/OWNERS
@@ -0,0 +1,4 @@
+# See also ART owners in the parent directory.
+rpl@google.com
+dsrbecky@google.com
+*
diff --git a/test/ProfileTestMultiDex/Main.java b/test/ProfileTestMultiDex/Main.java
index 978cb2c..98d4d96 100644
--- a/test/ProfileTestMultiDex/Main.java
+++ b/test/ProfileTestMultiDex/Main.java
@@ -46,26 +46,64 @@
   public int noInlineCache(Super s) {
     return s.getValue();
   }
+
+  public int inlineMultiMonomorphic(Super s, Secret sec) {
+    return s.getValue() + sec.getIdentity();
+  }
+
+  public int inlineMultiPolymorphic(Super s, Secret sec) {
+    return s.getValue() + sec.getIdentity();
+  }
+
+  public int inlineTriplePolymorphic(Super s, Secret sec, Secret thr) {
+    return s.getValue() + sec.getIdentity() + thr.getIdentity();
+  }
+
+  public int inlineMultiMegamorphic(Super s, Secret sec) {
+    return s.getValue() + sec.getIdentity();
+  }
+
+  public int inlineMultiMissingTypes(Super s, Secret sec) {
+    return s.getValue() + sec.getIdentity();
+  }
+
+  public int noInlineCacheMulti(Super s, Secret sec) {
+    return s.getValue() + sec.getIdentity();
+  }
 }
 
-abstract class Super {
+class TestInlineSubtype extends TestInline {
+  public void foobar() {
+    this.inlineMonomorphic(new SubA());
+  }
+}
+
+abstract class Secret {
+  abstract int getIdentity();
+}
+
+abstract class Super extends Secret {
   abstract int getValue();
 }
 
 class SubA extends Super {
   int getValue() { return 42; }
+  int getIdentity() { return 24; }
 }
 
 class SubB extends Super {
   int getValue() { return 38; };
+  int getIdentity() { return 83; }
 }
 
 class SubD extends Super {
   int getValue() { return 20; };
+  int getIdentity() { return 2; };
 }
 
 class SubE extends Super {
   int getValue() { return 16; };
+  int getIdentity() { return 61; };
 }
 
 // Add a class with lots of methods so we can test profile guided compilation triggers.
diff --git a/test/ProfileTestMultiDex/Second.java b/test/ProfileTestMultiDex/Second.java
index a2bb8d4..c9b3c0b 100644
--- a/test/ProfileTestMultiDex/Second.java
+++ b/test/ProfileTestMultiDex/Second.java
@@ -28,6 +28,7 @@
 
 class SubC extends Super {
   int getValue() { return 24; }
+  int getIdentity() { return 42; }
 }
 
 class TestIntrinsicOatdump {
diff --git a/test/ProfileTestMultiDex/main.jpp b/test/ProfileTestMultiDex/main.jpp
index 0644072..33fede8 100644
--- a/test/ProfileTestMultiDex/main.jpp
+++ b/test/ProfileTestMultiDex/main.jpp
@@ -1,9 +1,12 @@
 Main:
   @@com.android.jack.annotations.ForceInMainDex
   class Main
-TestInqline:
+TestInline:
   @@com.android.jack.annotations.ForceInMainDex
   class TestInline
+Secret:
+  @@com.android.jack.annotations.ForceInMainDex
+  class Secret
 Super:
   @@com.android.jack.annotations.ForceInMainDex
   class Super
@@ -22,3 +25,6 @@
 ZLotsOfMethods:
 @@com.android.jack.annotations.ForceInMainDex
   class ZLotsOfMethods
+TestInlineSubtype:
+  @@com.android.jack.annotations.ForceInMainDex
+  class TestInlineSubtype
diff --git a/test/ProfileTestMultiDex/main.list b/test/ProfileTestMultiDex/main.list
index 6ca79d4..023f948 100644
--- a/test/ProfileTestMultiDex/main.list
+++ b/test/ProfileTestMultiDex/main.list
@@ -1,5 +1,7 @@
 Main.class
 TestInline.class
+TestInlineSubtype.class
+Secret.class
 Super.class
 SubA.class
 SubB.class
diff --git a/test/README.arm_fvp.md b/test/README.arm_fvp.md
new file mode 100644
index 0000000..47ef715
--- /dev/null
+++ b/test/README.arm_fvp.md
@@ -0,0 +1,165 @@
+# Build and Run ART tests on ARM FVP
+
+This document describes how to build and run an Android system image targeting
+the ARM Fixed Virtual Platform and to use it as a target platform for running
+ART tests via ADB.
+
+This instruction was checked to be working for the AOSP master tree on
+2021-01-13; the up-to-date instruction on how to build the kernel and firmware
+could be found here: device/generic/goldfish/fvpbase/README.md.
+
+## Configuring and Building AOSP
+
+First, an AOSP image should be configured and built, including the kernel and
+firmware.
+
+### Generating build system configs
+
+```
+cd $AOSP
+
+. build/envsetup.sh
+# fvp_mini target is used as we don't need a GUI for ART tests.
+lunch fvp_mini-eng
+
+# This is expected to fail; it generates all the build rules files.
+m
+```
+
+### Building the kernel
+
+```
+cd $SOME_DIRECTORY_OUTSIDE_AOSP
+
+mkdir android-kernel-mainline
+cd android-kernel-mainline
+repo init -u https://android.googlesource.com/kernel/manifest -b common-android-mainline
+repo sync
+BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
+BUILD_CONFIG=common-modules/virtual-device/build.config.fvp build/build.sh
+```
+
+The resulting kernel image and DTB (Device Tree Binary) must then be copied into
+the product output directory:
+
+```
+cp out/android-mainline/dist/Image $ANDROID_PRODUCT_OUT/kernel
+cp out/android-mainline/dist/fvp-base-revc.dtb out/android-mainline/dist/initramfs.img $ANDROID_PRODUCT_OUT/
+```
+
+### Building the firmware (ARM Trusted Firmware and U-Boot)
+
+First, install ``dtc``, the device tree compiler. On Debian, this is in the
+``device-tree-compiler`` package.
+
+```
+sudo apt-get install device-tree-compiler
+```
+
+Then run:
+
+```
+mkdir platform
+cd platform
+repo init -u https://git.linaro.org/landing-teams/working/arm/manifest.git -m pinned-uboot.xml -b 20.01
+repo sync
+
+# The included copy of U-Boot is incompatible with this version of AOSP, switch to a recent upstream checkout.
+cd u-boot
+git fetch https://gitlab.denx.de/u-boot/u-boot.git/ master
+git checkout 18b9c98024ec89e00a57707f07ff6ada06089d26
+cd ..
+
+mkdir -p tools/gcc
+cd tools/gcc
+wget https://releases.linaro.org/components/toolchain/binaries/6.2-2016.11/aarch64-linux-gnu/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu.tar.xz
+tar -xJf gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu.tar.xz
+cd ../..
+
+build-scripts/build-test-uboot.sh -p fvp all
+```
+
+These components must then be copied into the product output directory:
+
+```
+cp output/fvp/fvp-uboot/uboot/{bl1,fip}.bin $ANDROID_PRODUCT_OUT/
+```
+
+## Setting up the FVP model
+
+### Obtaining the model
+
+The public Arm FVP could be obtained from https://developer.arm.com/; one would
+need to create an account there and accept EULA to download and install it.
+A link for the latest version:
+
+https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models: "Armv8-A Base RevC AEM FVP"
+
+The AEMv8-A Base Platform FVP is a free of charge Fixed Virtual Platform of the
+latest Arm v8-A architecture features and has been validated with compatible
+Open Source software, which can be found on the reference open source software
+stacks page along with instructions for running the software
+
+### Running the model
+
+From a lunched environment:
+
+```
+export MODEL_PATH=/path/to/model/dir
+export MODEL_BIN=${MODEL_PATH}/models/Linux64_GCC-6.4/FVP_Base_RevC-2xAEMv8A
+./device/generic/goldfish/fvpbase/run_model
+```
+
+If any extra parameters are needed for the model (e.g. specifying plugins) they
+should be specified as cmdline options for 'run_model'. E.g. to run a model
+which support SVE:
+
+```
+export SVE_PLUGIN=${MODEL_PATH}/plugins/Linux64_GCC-6.4/ScalableVectorExtension.so
+$ ./device/generic/goldfish/fvpbase/run_model --plugin ${SVE_PLUGIN} -C SVE.ScalableVectorExtension.veclen=2
+```
+
+Note: SVE vector length is passed in units of 64-bit blocks. So "2" would stand
+for 128-bit vector length.
+
+The model will start and will have fully booted to shell in around 20 minutes
+(you will see "sys.boot_completed=1" in the log). It can be accessed as a
+regular device with adb:
+
+```
+adb connect localhost:5555
+```
+
+To terminate the model, press ``Ctrl-] Ctrl-D`` to terminate the telnet
+connection.
+
+## Running ART test on FVP
+
+The model behaves as a regular adb device so running ART tests could be done using
+the standard chroot method described in test/README.chroot.md; the steps are
+also described below. A separate AOSP tree (not the one used for the model
+itself), should be used - full or minimal.
+
+Then the regular ART testing routine could be performed; the regular "lunch"
+target ("armv8" and other targets, not "fvp-eng").
+
+
+```
+export ART_TEST_CHROOT=/data/local/art-test-chroot
+export OVERRIDE_TARGET_FLATTEN_APEX=true
+export SOONG_ALLOW_MISSING_DEPENDENCIES=true
+export TARGET_BUILD_UNBUNDLED=true
+export ART_TEST_RUN_ON_ARM_FVP=true
+
+. ./build/envsetup.sh
+lunch armv8-userdebug
+art/tools/buildbot-build.sh --target
+
+art/tools/buildbot-teardown-device.sh
+art/tools/buildbot-cleanup-device.sh
+art/tools/buildbot-setup-device.sh
+art/tools/buildbot-sync.sh
+
+art/test/testrunner/testrunner.py --target --64 --optimizing -j1
+
+```
diff --git a/test/README.atest.md b/test/README.atest.md
new file mode 100644
index 0000000..dc3878a
--- /dev/null
+++ b/test/README.atest.md
@@ -0,0 +1,152 @@
+# Running ART Tests with Atest / Trade Federation
+
+ART Testing has early support for execution in the [Trade
+Federation](https://source.android.com/devices/tech/test_infra/tradefed)
+("TradeFed") test harness, in particular via the
+[Atest](https://source.android.com/compatibility/tests/development/atest)
+command line tool.
+
+Atest conveniently takes care of building tests and their dependencies (using
+Soong, the Android build system) and executing them using Trade Federation.
+
+See also [README.md](README.md) for a general introduction to ART run-tests and
+gtests.
+
+## ART run-tests
+
+### Running ART run-tests on device
+
+ART run-tests are defined in sub-directories of `test/` starting with a number
+(e.g. `test/001-HelloWorld`). Each ART run-test is identified in the build
+system by a Soong module name following the `art-run-test-`*`<test-directory>`*
+format (e.g. `art-run-test-001-HelloWorld`).
+
+You can run a specific ART run-test on device by passing its Soong module name
+to Atest:
+```bash
+atest art-run-test-001-HelloWorld
+```
+
+To run all ART run-tests in a single command, the currently recommended way is
+to use [test mapping](#test-mapping) (see below).
+
+You can nonetheless run all supported ART run-tests with a single Atest command,
+using its support for wildcards:
+```bash
+atest art-run-test-\*
+```
+
+Note: Many ART run-tests are failing with the TradeFed harness as of March 2021,
+so the above Atest command will likely report many tests failures. The ART team
+is actively working on this issue.
+
+## ART gtests
+
+### Running ART gtests on device
+
+Because of current build- and link-related limitations, ART gtests can only run
+as part of the Testing ART APEX (`com.android.art.testing.apex`) on device,
+i.e. they have to be part of the ART APEX package itself to be able to build and
+run properly. This means that it is not possible to test the ART APEX presently
+residing on a device (either the original one, located in the "system"
+partition, or an updated package, present in the "data" partition).
+
+There are two ways to run ART gtests on device:
+* by installing the Testing ART APEX (i.e. manually "updating" the ART APEX on
+  device); or
+* by setting up a `chroot` environment on the device, and "activating" the
+  Testing ART APEX in that environment.
+
+### Running ART gtests on device by installing the Testing ART APEX
+
+You can run ART gtests on device with the ART APEX installation strategy by
+using the following `atest` command:
+
+```bash
+atest ArtGtestsTargetInstallApex
+```
+
+This command:
+1. builds the Testing ART APEX from the Android source tree (including the ART
+   gtests);
+2. installs the Testing ART APEX using `adb install`;
+3. reboots the device;
+4. runs the tests; and
+5. uninstalls the module.
+
+You can run the tests of a single ART gtest C++ class using the
+`ArtGtestsTargetInstallApex:`*`<art-gtest-c++-class>`* syntax, e.g.:
+```bash
+atest ArtGtestsTargetInstallApex:JniInternalTest
+```
+
+This syntax also supports the use of wildcards, e.g.:
+```bash
+atest ArtGtestsTargetInstallApex:*Test*
+```
+
+You can also use Trade Federation options to run a subset of ART gtests, e.g.:
+```bash
+atest ArtGtestsTargetInstallApex -- \
+  --module ArtGtestsTargetInstallApex --test '*JniInternalTest*'
+```
+
+You can also pass option `--gtest_filter` to the gtest binary to achieve a
+similar effect:
+```bash
+atest ArtGtestsTargetInstallApex -- \
+  --test-arg com.android.tradefed.testtype.GTest:native-test-flag:"--gtest_filter=*JniInternalTest*"
+```
+
+### Running ART gtests on device using a `chroot` environment
+
+You can run ART gtests on device with the chroot-based strategy by using the
+following `atest` command:
+
+```bash
+atest ArtGtestsTargetChroot
+```
+
+This command:
+1. builds the Testing ART APEX from the Android source tree (including the ART
+   gtests) and all the necessary dependencies for the `chroot` environment;
+2. sets up a `chroot` environment on the device;
+3. "activates" the Testing ART APEX (and other APEXes that it depends on) in the
+   `chroot` environment;
+4. runs the tests within the `chroot` environment; and
+5. cleans up the environment (deactivates the APEXes and removes the `chroot`
+   environment).
+
+## Test Mapping
+
+ART Testing supports the execution of tests via [Test
+Mapping](https://source.android.com/compatibility/tests/development/test-mapping).
+The tests declared in ART's [TEST_MAPPING](../TEST_MAPPING) file are executed
+during pre-submit testing (when an ART changelist in Gerrit is verified by
+Treehugger) and/or post-submit testing (when a given change is merged in the
+Android code base), depending on the "test group" where a test is declared.
+
+### Running tests via Test Mapping with Atest
+
+It is possible to run tests via test mapping locally using Atest.
+
+To run all the tests declared in ART's `TEST_MAPPING` file, use the following
+command from the Android source tree top-level directory:
+```bash
+atest --test-mapping art:all
+```
+In the previous command, `art` is the (relative) path to the directory
+containing the `TEST_MAPPING` file listing the tests to run, while `all` means
+that tests declared in all [test
+groups](https://source.android.com/compatibility/tests/development/test-mapping#defining_test_groups)
+shall be run.
+
+To only run tests executed during pre-submit testing, use:
+```bash
+atest --test-mapping art:presubmit
+```
+
+To only run tests executed during post-submit testing, use:
+```bash
+atest --test-mapping art:postsubmit
+```
diff --git a/test/README.chroot.md b/test/README.chroot.md
index 7c3fa8f..a4fee55 100644
--- a/test/README.chroot.md
+++ b/test/README.chroot.md
@@ -114,11 +114,11 @@
 10. Run JDWP tests:
     * On a 64-bit target:
         ```bash
-        art/tools/run-jdwp-tests.sh --mode=device --variant=X64
+        art/tools/run-libjdwp-tests.sh --mode=device --variant=X64
         ```
     * On a 32-bit target:
         ```bash
-        art/tools/run-jdwp-tests.sh --mode=device --variant=X32
+        art/tools/run-libjdwp-tests.sh --mode=device --variant=X32
         ```
 11. Tear down device setup:
     ```bash
diff --git a/test/README.md b/test/README.md
index d199bfe..74fbead 100644
--- a/test/README.md
+++ b/test/README.md
@@ -39,9 +39,10 @@
 by `test/etc/default-run`.
 
 After the execution of a run-test, the check step's default behavior
-(implemented in `test/etc/default-check`) is to compare its standard output with
-the contents of the `expected.txt` file contained in the test's directory; any
-mismatch triggers a test failure.
+(implemented in `test/etc/default-check`) is to respectively compare its
+standard output and standard error with the contents of the
+`expected-stdout.txt` and `expected-stderr.txt` files contained in the test's
+directory; any mismatch triggers a test failure.
 
 The `test/run-test` script handles the execution of a single run-test in a given
 configuration. The Python script `test/testrunner/testrunner.py` is a convenient
@@ -92,18 +93,44 @@
 $ art/test.py -h
 ```
 
+## Building tests
+
+In general all tests require some dependencies to be built before they can be run.
+In general you can pass the `--build-dependencies` flag (also available as short
+option -b) to `art/test.py` program to automatically build required dependencies.
+One can also directly use the various `test-art-...-dependencies` targets listed
+below.
+
 ## Running all tests on the build host
 
 ```sh
+$ # Build test files
+$ m test-art-host-run-test-dependencies
+$ # Run the tests
 $ art/test.py --host
 ```
 
+Or:
+
+```
+$ art/test.py -b --host
+```
+
 ## Running all tests on the target device
 
 ```sh
+$ # Build test files
+$ m test-art-target-run-test-dependencies
+$ # Run the tests
 $ art/test.py --target
 ```
 
+Or:
+
+```
+$ art/test.py -b --target
+```
+
 ## Running all gtests on the build host
 
 ```sh
@@ -119,9 +146,17 @@
 ## Running all run-tests on the build host
 
 ```sh
+$ # Build test files
+$ m test-art-host-run-test-dependencies
 $ art/test.py --host -r
 ```
 
+Or:
+
+```
+$ art/test.py -b --host -r
+```
+
 ## Running all run-tests on the target device
 
 ```sh
@@ -131,15 +166,34 @@
 ## Running one run-test on the build host
 
 ```sh
+$ # Build test files
+$ m test-art-host-run-test-dependencies
+$ # Run the tests
 $ art/test.py --host -r -t 001-HelloWorld
 ```
 
+Or:
+
+```
+$ art/test.py -b --host -r -t 001-HelloWorld
+```
+
 ## Running one run-test on the target device
 
 ```sh
 $ art/test.py --target -r -t 001-HelloWorld
 ```
 
+## Running one gtest on the build host
+
+```sh
+$ find out/host/ -type f -name art_runtime_tests  # Find the path of the test.
+$ out/host/linux-x86/nativetest/art_runtime_tests/art_runtime_tests
+```
+
+Add "--no_isolate" to run the tests one by one in single process (disable forking).
+Add "--gtest_filter=..." to select specific sub-test(s) to run.
+Prefix by "gdb --args " to run the test in gdb.
 
 # ART Continuous Integration
 
diff --git a/test/Transaction/Transaction.java b/test/Transaction/Transaction.java
index e7085c1..6a4f5ef 100644
--- a/test/Transaction/Transaction.java
+++ b/test/Transaction/Transaction.java
@@ -74,6 +74,31 @@
       }
     }
 
+    static class CatchClassForNameAbortClass {
+      static {
+        try {
+          Class.forName("non.existent.TestClass");
+        } catch (Throwable e) {
+          // ignore exception.
+        }
+      }
+    }
+
+    static class CatchClassForNameAbortClassTwice {
+      static {
+        try {
+          Class.forName("non.existent.TestClass");
+        } catch (Throwable e) {
+          // ignore exception.
+        }
+        try {
+          Class.forName("non.existent.TestClass");
+        } catch (Throwable e) {
+          // ignore exception.
+        }
+      }
+    }
+
     // Helper class to abort transaction: finalizable class with natve methods.
     static class AbortHelperClass {
       public void finalize() throws Throwable {
diff --git a/test/VerifierDepsMulti/MySoftVerificationFailure.smali b/test/VerifierDepsMulti/MySoftVerificationFailure.smali
index 6b56a3b..2bede45 100644
--- a/test/VerifierDepsMulti/MySoftVerificationFailure.smali
+++ b/test/VerifierDepsMulti/MySoftVerificationFailure.smali
@@ -17,8 +17,9 @@
 
 .method public final foo()V
   .registers 1
-  sget-object v0, LMySoftVerificationFailure;->error:LUnknownType;
+  sget-object v0, LMySoftVerificationFailure;->error:Ljava/lang/Object;
+  # Throwing a non-exception class is a soft failure.
   throw v0
 .end method
 
-.field public static error:LUnknownType;
+.field public static error:Ljava/lang/Object;
diff --git a/test/art-gtests-target-chroot.xml b/test/art-gtests-target-chroot.xml
new file mode 100644
index 0000000..f274ff1
--- /dev/null
+++ b/test/art-gtests-target-chroot.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="ART gtests for target (using chroot)">
+    <option name="test-suite-tag" value="art-target-gtest-chroot" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+    <target_preparer class="com.android.tradefed.targetprep.DisableSELinuxTargetPreparer" />
+    <target_preparer class="com.android.tradefed.targetprep.ArtChrootPreparer" />
+
+    <test class="com.android.tradefed.testtype.ArtGTest" >
+        <!-- TODO(b/147821328): These tests do not work since they need to write to /system -->
+        <option name="exclude-filter" value="HiddenApiTest.DexDomain_System*:OatFileAssistantTest.SystemFrameworkDir" />
+        <option name="native-test-timeout" value="600000" />
+        <option name="native-test-device-path" value="/data/local/tmp/art-test-chroot/apex/com.android.art/bin/art" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/test/art-gtests-target-install-apex.xml b/test/art-gtests-target-install-apex.xml
new file mode 100644
index 0000000..39c46fb
--- /dev/null
+++ b/test/art-gtests-target-install-apex.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="ART gtests for target (using apex installation)">
+    <option name="test-suite-tag" value="art" />
+    <option name="test-suite-tag" value="art-target-gtest-install-apex" />
+
+    <target_preparer class="com.android.tradefed.targetprep.InstallApexModuleTargetPreparer" >
+        <option name="test-file-name" value="com.android.art.testing.apex" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <!-- TODO(b/147821328): These tests do not work since they need to write to /system -->
+        <option name="exclude-filter" value="HiddenApiTest.DexDomain_System*:OatFileAssistantTest.SystemFrameworkDir" />
+        <option name="native-test-timeout" value="600000" /> <!-- 10 min -->
+        <option name="native-test-device-path" value="/apex/com.android.art/bin/art" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/test/art-gtests-target-standalone-template.xml b/test/art-gtests-target-standalone-template.xml
new file mode 100644
index 0000000..4b2bdc1
--- /dev/null
+++ b/test/art-gtests-target-standalone-template.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<!-- Note: This test config file for {MODULE} is generated from a template. -->
+<configuration description="Runs {MODULE}.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="{MODULE}->/data/local/tmp/nativetest/{MODULE}" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/nativetest" />
+        <option name="module-name" value="{MODULE}" />
+        <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+        <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/test/art-run-test-target-no-test-suite-tag-template.xml b/test/art-run-test-target-no-test-suite-tag-template.xml
new file mode 100644
index 0000000..7e7b592
--- /dev/null
+++ b/test/art-run-test-target-no-test-suite-tag-template.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<!-- Note: This test config for {MODULE} is generated from a template. -->
+<configuration description="Test module config for {MODULE}">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <!-- TODO: Use option `push-file` instead of deprecated option
+             `push`. -->
+        <option name="push" value="{MODULE}.jar->/data/local/tmp/{MODULE}/{MODULE}.jar" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.ArtRunTest">
+        <option name="run-test-name" value="{MODULE}" />
+        <option name="classpath" value="/data/local/tmp/{MODULE}/{MODULE}.jar" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/test/art-run-test-target-template.xml b/test/art-run-test-target-template.xml
new file mode 100644
index 0000000..4084afa
--- /dev/null
+++ b/test/art-run-test-target-template.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<!-- Note: This test config for {MODULE} is generated from a template. -->
+<configuration description="Test module config for {MODULE}">
+    <option name="test-suite-tag" value="art-target-run-test" />
+    <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.art.apex" />
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <!-- TODO: Use option `push-file` instead of deprecated option
+             `push`. -->
+        <option name="push" value="{MODULE}.jar->/data/local/tmp/{MODULE}/{MODULE}.jar" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.ArtRunTest">
+        <option name="run-test-name" value="{MODULE}" />
+        <option name="classpath" value="/data/local/tmp/{MODULE}/{MODULE}.jar" />
+    </test>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
+</configuration>
diff --git a/test/common/gtest_main.cc b/test/common/gtest_main.cc
new file mode 100644
index 0000000..95dadcf
--- /dev/null
+++ b/test/common/gtest_main.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 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 <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "base/logging.h"
+#include "base/mem_map.h"
+#include "base/mutex.h"
+#include "gtest_extras/IsolateMain.h"
+#include "runtime.h"
+
+extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
+  static const char* initial_args[] = {
+      "--deadline_threshold_ms=1200000",  // hwasan takes ~10min.
+      "--slow_threshold_ms=300000",
+  };
+  *args = initial_args;
+  *num_args = 2;
+  return true;
+}
+
+// Allow other test code to run global initialization/configuration before gtest infra takes over.
+extern "C" __attribute__((visibility("default"))) __attribute__((weak)) void ArtTestGlobalInit();
+
+int main(int argc, char** argv, char** envp) {
+  // Gtests can be very noisy. For example, an executable with multiple tests will trigger native
+  // bridge warnings. The following line reduces the minimum log severity to ERROR and suppresses
+  // everything else. In case you want to see all messages, comment out the line.
+  const char* log_tag_override = getenv("ART_GTEST_OVERRIDE_LOG_TAGS");
+  setenv("ANDROID_LOG_TAGS", log_tag_override == nullptr ? "*:e" : log_tag_override, 1);
+
+  art::Locks::Init();
+  art::InitLogging(argv, art::Runtime::Abort);
+  art::MemMap::Init();
+  LOG(INFO) << "Running main() from common_runtime_test.cc...";
+  if (ArtTestGlobalInit != nullptr) {
+    ArtTestGlobalInit();
+  }
+  return IsolateMain(argc, argv, envp);
+}
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index 6c76288..4c22bd1 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -126,7 +126,10 @@
   CHECK(oat_file != nullptr);
 
   const char* cmd_line = oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey);
-  CHECK(cmd_line != nullptr);  // Huh? This should not happen.
+  if (cmd_line == nullptr) {
+    // Vdex-only execution, conservatively say no.
+    return JNI_FALSE;
+  }
 
   // Check the backend.
   constexpr const char* kCompilerBackend = "--compiler-backend=";
@@ -143,23 +146,16 @@
   constexpr const char* kCompilerFilter = "--compiler-filter=";
   const char* filter = strstr(cmd_line, kCompilerFilter);
   if (filter != nullptr) {
-    // If it's set, make sure it's not interpret-only|verify-none|verify-at-runtime.
-    // Note: The space filter might have an impact on the test, but ignore that for now.
     filter += strlen(kCompilerFilter);
-    constexpr const char* kInterpretOnly = "interpret-only";
-    constexpr const char* kVerifyNone = "verify-none";
-    constexpr const char* kVerifyAtRuntime = "verify-at-runtime";
-    constexpr const char* kQuicken = "quicken";
-    constexpr const char* kExtract = "extract";
-    if (strncmp(filter, kInterpretOnly, strlen(kInterpretOnly)) == 0 ||
-        strncmp(filter, kVerifyNone, strlen(kVerifyNone)) == 0 ||
-        strncmp(filter, kVerifyAtRuntime, strlen(kVerifyAtRuntime)) == 0 ||
-        strncmp(filter, kExtract, strlen(kExtract)) == 0 ||
-        strncmp(filter, kQuicken, strlen(kQuicken)) == 0) {
-      return JNI_FALSE;
-    }
+    const char* end = strchr(filter, ' ');
+    std::string string_filter(filter, (end == nullptr) ? strlen(filter) : end - filter);
+    CompilerFilter::Filter compiler_filter;
+    bool success = CompilerFilter::ParseCompilerFilter(string_filter.c_str(), &compiler_filter);
+    CHECK(success);
+    return CompilerFilter::IsAotCompilationEnabled(compiler_filter) ? JNI_TRUE : JNI_FALSE;
   }
 
+  // No filter passed, assume default has AOT.
   return JNI_TRUE;
 }
 
@@ -229,13 +225,12 @@
   return jit->GetCodeCache()->ContainsMethod(method);
 }
 
-static void ForceJitCompiled(Thread* self, ArtMethod* method) REQUIRES(!Locks::mutator_lock_) {
-  bool native = false;
+static void ForceJitCompiled(Thread* self,
+                             ArtMethod* method,
+                             CompilationKind kind) REQUIRES(!Locks::mutator_lock_) {
   {
     ScopedObjectAccess soa(self);
-    if (method->IsNative()) {
-      native = true;
-    } else if (!Runtime::Current()->GetRuntimeCallbacks()->IsMethodSafeToJit(method)) {
+    if (!Runtime::Current()->GetRuntimeCallbacks()->IsMethodSafeToJit(method)) {
       std::string msg(method->PrettyMethod());
       msg += ": is not safe to jit!";
       ThrowIllegalStateException(msg.c_str());
@@ -269,27 +264,15 @@
   // Update the code cache to make sure the JIT code does not get deleted.
   // Note: this will apply to all JIT compilations.
   code_cache->SetGarbageCollectCode(false);
-  while (true) {
-    if (native && code_cache->ContainsMethod(method)) {
-      break;
-    } else {
-      // Sleep to yield to the compiler thread.
-      usleep(1000);
-      ScopedObjectAccess soa(self);
-      if (!native && jit->GetCodeCache()->CanAllocateProfilingInfo()) {
-        // Make sure there is a profiling info, required by the compiler.
-        ProfilingInfo::Create(self, method, /* retry_allocation */ true);
-      }
-      // Will either ensure it's compiled or do the compilation itself. We do
-      // this before checking if we will execute JIT code to make sure the
-      // method is compiled 'optimized' and not baseline (tests expect optimized
-      // compilation).
-      jit->CompileMethod(method, self, /*baseline=*/ false, /*osr=*/ false, /*prejit=*/ false);
-      if (code_cache->WillExecuteJitCode(method)) {
-        break;
-      }
-    }
-  }
+  do {
+    // Sleep to yield to the compiler thread.
+    usleep(1000);
+    ScopedObjectAccess soa(self);
+    // Will either ensure it's compiled or do the compilation itself. We do
+    // this before checking if we will execute JIT code in case the request
+    // is for an 'optimized' compilation.
+    jit->CompileMethod(method, self, kind, /*prejit=*/ false);
+  } while (!code_cache->ContainsPc(method->GetEntryPointFromQuickCompiledCode()));
 }
 
 extern "C" JNIEXPORT void JNICALL Java_Main_ensureMethodJitCompiled(JNIEnv*, jclass, jobject meth) {
@@ -304,7 +287,7 @@
     ScopedObjectAccess soa(self);
     method = ArtMethod::FromReflectedMethod(soa, meth);
   }
-  ForceJitCompiled(self, method);
+  ForceJitCompiled(self, method, CompilationKind::kOptimized);
 }
 
 extern "C" JNIEXPORT void JNICALL Java_Main_ensureJitCompiled(JNIEnv* env,
@@ -324,7 +307,27 @@
     ScopedUtfChars chars(env, method_name);
     method = GetMethod(soa, cls, chars);
   }
-  ForceJitCompiled(self, method);
+  ForceJitCompiled(self, method, CompilationKind::kOptimized);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_ensureJitBaselineCompiled(JNIEnv* env,
+                                                                      jclass,
+                                                                      jclass cls,
+                                                                      jstring method_name) {
+  jit::Jit* jit = GetJitIfEnabled();
+  if (jit == nullptr) {
+    return;
+  }
+
+  Thread* self = Thread::Current();
+  ArtMethod* method = nullptr;
+  {
+    ScopedObjectAccess soa(self);
+
+    ScopedUtfChars chars(env, method_name);
+    method = GetMethod(soa, cls, chars);
+  }
+  ForceJitCompiled(self, method, CompilationKind::kBaseline);
 }
 
 extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasSingleImplementation(JNIEnv* env,
diff --git a/test/dexdump/all-dex-files.jar b/test/dexdump/all-dex-files.jar
new file mode 100644
index 0000000..0a94a86
--- /dev/null
+++ b/test/dexdump/all-dex-files.jar
Binary files differ
diff --git a/test/dexdump/all-dex-files.lst b/test/dexdump/all-dex-files.lst
new file mode 100644
index 0000000..0307f89
--- /dev/null
+++ b/test/dexdump/all-dex-files.lst
@@ -0,0 +1,259 @@
+#all-dex-files.jar
+0x0000043c 8 A <init> ()V (none) -1
+0x00000454 58 A arrays ()V (none) -1
+0x000004a0 130 A binary_ops ()V (none) -1
+0x00000534 66 A binary_ops_2addr ()V (none) -1
+0x00000588 34 A binary_ops_lit16 ()V (none) -1
+0x000005bc 46 A binary_ops_lit8 ()V (none) -1
+0x000005fc 22 A compares ()V (none) -1
+0x00000624 50 A conditionals ()V (none) -1
+0x00000668 56 A constants ()V (none) -1
+0x000006b0 108 A misc ()V (none) -1
+0x0000072c 46 A moves ()V (none) -1
+0x0000076c 32 A packed_switch ()V (none) -1
+0x0000079c 2 A return32 ()I (none) -1
+0x000007b0 2 A return64 ()I (none) -1
+0x000007c4 2 A return_object ()Ljava/lang/Object; (none) -1
+0x000007d8 44 A sparse_switch ()V (none) -1
+0x00000814 58 A static_fields ()V (none) -1
+0x00000860 44 A unary_ops ()V (none) -1
+0x0000089c 58 A instance_fields ()V (none) -1
+0x000008e8 30 A invokes ()V (none) -1
+0x0000149c 8 com.google.android.checkers.Checkers <init> ()V (none) -1
+0x000014b4 66 com.google.android.checkers.Checkers a (Z)V (none) -1
+0x00001508 8 com.google.android.checkers.Checkers onConfigurationChanged (Landroid/content/res/Configuration;)V (none) -1
+0x00001520 118 com.google.android.checkers.Checkers onCreate (Landroid/os/Bundle;)V (none) -1
+0x000015a8 432 com.google.android.checkers.Checkers onCreateOptionsMenu (Landroid/view/Menu;)Z (none) -1
+0x00001768 116 com.google.android.checkers.Checkers onKeyDown (ILandroid/view/KeyEvent;)Z (none) -1
+0x000017ec 316 com.google.android.checkers.Checkers onOptionsItemSelected (Landroid/view/MenuItem;)Z (none) -1
+0x00001938 42 com.google.android.checkers.Checkers onPause ()V (none) -1
+0x00001974 16 com.google.android.checkers.Checkers onStop ()V (none) -1
+0x00001994 88 com.google.android.checkers.Checkers onTrackballEvent (Landroid/view/MotionEvent;)Z (none) -1
+0x000019fc 1324 com.google.android.checkers.CheckersView <init> (Landroid/content/Context;Landroid/content/SharedPreferences;)V (none) -1
+0x00001f48 62 com.google.android.checkers.CheckersView a (Landroid/content/SharedPreferences$Editor;Ljava/lang/String;[I)V (none) -1
+0x00001f98 66 com.google.android.checkers.CheckersView a (Landroid/content/SharedPreferences;Ljava/lang/String;[I)V (none) -1
+0x00001fec 126 com.google.android.checkers.CheckersView a (Landroid/graphics/Canvas;IIII)V (none) -1
+0x0000207c 162 com.google.android.checkers.CheckersView a (Landroid/graphics/Canvas;IIIILandroid/graphics/Paint;Landroid/graphics/Paint;Z)V (none) -1
+0x00002130 8 com.google.android.checkers.CheckersView a (Lcom/google/android/checkers/CheckersView;I)V (none) -1
+0x00002148 588 com.google.android.checkers.CheckersView a (Landroid/content/SharedPreferences;)Z (none) -1
+0x000023d0 22 com.google.android.checkers.CheckersView a (Lcom/google/android/checkers/CheckersView;)Z (none) -1
+0x000023f8 1290 com.google.android.checkers.CheckersView a (ZIIII)Z (none) -1
+0x00002930 204 com.google.android.checkers.CheckersView b (FF)I (none) -1
+0x00002a20 36 com.google.android.checkers.CheckersView b (I)V (none) -1
+0x00002a60 198 com.google.android.checkers.CheckersView b (Landroid/graphics/Canvas;IIII)V (none) -1
+0x00002b38 524 com.google.android.checkers.CheckersView c (I)V (none) -1
+0x00002d54 176 com.google.android.checkers.CheckersView d ()V (none) -1
+0x00002e14 20 com.google.android.checkers.CheckersView e ()Z (none) -1
+0x00002e38 128 com.google.android.checkers.CheckersView a ()V (none) -1
+0x00002ec8 226 com.google.android.checkers.CheckersView a (FF)V (none) -1
+0x00002fd8 32 com.google.android.checkers.CheckersView a (IIII)V (none) -1
+0x00003008 340 com.google.android.checkers.CheckersView a (Landroid/content/SharedPreferences$Editor;)V (none) -1
+0x00003178 34 com.google.android.checkers.CheckersView a (I)Z (none) -1
+0x000031ac 44 com.google.android.checkers.CheckersView a (Z)Z (none) -1
+0x000031f4 60 com.google.android.checkers.CheckersView b ()V (none) -1
+0x0000324c 138 com.google.android.checkers.CheckersView b (Z)Z (none) -1
+0x000032f4 16 com.google.android.checkers.CheckersView c ()I (none) -1
+0x00003320 68 com.google.android.checkers.CheckersView c (Z)Z (none) -1
+0x00003380 38 com.google.android.checkers.CheckersView d (Z)Z (none) -1
+0x000033c4 2528 com.google.android.checkers.CheckersView draw (Landroid/graphics/Canvas;)V (none) -1
+0x00003dd0 38 com.google.android.checkers.CheckersView e (Z)Z (none) -1
+0x00003e14 104 com.google.android.checkers.CheckersView onSizeChanged (IIII)V (none) -1
+0x00003e98 82 com.google.android.checkers.CheckersView onTouchEvent (Landroid/view/MotionEvent;)Z (none) -1
+0x00003efc 128 com.google.android.checkers.CheckersView setLevel (I)V (none) -1
+0x00003f98 2780 com.google.android.checkers.a <clinit> ()V (none) -1
+0x00004a84 188 com.google.android.checkers.a <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x00004b5c 28 com.google.android.checkers.a a (II)I (none) -1
+0x00004b88 2592 com.google.android.checkers.a a (IIIIIZ)I (none) -1
+0x000055b8 110 com.google.android.checkers.a a (IZ)I (none) -1
+0x00005638 196 com.google.android.checkers.a a (Z)I (none) -1
+0x0000570c 112 com.google.android.checkers.a a (ZII)I (none) -1
+0x0000578c 88 com.google.android.checkers.a a (ZIIIZ)I (none) -1
+0x000057f4 68 com.google.android.checkers.a a (ZIIZ)I (none) -1
+0x00005848 152 com.google.android.checkers.a a (IIII)V (none) -1
+0x000058f0 78 com.google.android.checkers.a a (IIIII)V (none) -1
+0x00005950 198 com.google.android.checkers.a a (IIIIIIII)V (none) -1
+0x00005a28 1750 com.google.android.checkers.a a (IZI)Z (none) -1
+0x00006110 92 com.google.android.checkers.a b (ZIIIZ)I (none) -1
+0x0000617c 112 com.google.android.checkers.a b (ZIIZ)I (none) -1
+0x000061fc 38 com.google.android.checkers.a b ()V (none) -1
+0x0000624c 736 com.google.android.checkers.a b (I)V (none) -1
+0x0000653c 198 com.google.android.checkers.a b (IIIIIIII)V (none) -1
+0x00006614 922 com.google.android.checkers.a b (IZI)Z (none) -1
+0x000069c0 108 com.google.android.checkers.a c (ZIIZ)I (none) -1
+0x00006a3c 16 com.google.android.checkers.a c ()V (none) -1
+0x00006a68 406 com.google.android.checkers.a c (IIIIIIII)V (none) -1
+0x00006c10 112 com.google.android.checkers.a d (ZIIZ)I (none) -1
+0x00006c90 16 com.google.android.checkers.a a (ZZ)I (none) -1
+0x00006cb0 90 com.google.android.checkers.a a ()V (none) -1
+0x00006d1c 8 com.google.android.checkers.a a (I)V (none) -1
+0x00006d34 74 com.google.android.checkers.a a (IIIIZ)V (none) -1
+0x00006d90 32 com.google.android.checkers.a b (ZZ)V (none) -1
+0x00006dcc 1052 com.google.android.checkers.a run ()V (none) -1
+0x000071f8 12 com.google.android.checkers.b <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x00007214 28 com.google.android.checkers.b onClick (Landroid/content/DialogInterface;I)V (none) -1
+0x00007240 12 com.google.android.checkers.c <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x0000725c 2 com.google.android.checkers.c onClick (Landroid/content/DialogInterface;I)V (none) -1
+0x00007270 12 com.google.android.checkers.d <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x0000728c 2 com.google.android.checkers.d onClick (Landroid/content/DialogInterface;I)V (none) -1
+0x000072a0 12 com.google.android.checkers.e <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x000072bc 14 com.google.android.checkers.e onClick (Landroid/content/DialogInterface;I)V (none) -1
+0x000072dc 12 com.google.android.checkers.f <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x000072f8 12 com.google.android.checkers.f onClick (Landroid/content/DialogInterface;I)V (none) -1
+0x00007314 58 com.google.android.checkers.g a ([B)Z (none) -1
+0x000003c0 8 Main <init> ()V Main.java 22
+0x000003d8 50 Main main ([Ljava/lang/String;)V Main.java 26
+0x0000041c 8 constmethodhandle.ConstTest <init> ()V ConstTest.java 22
+0x00000434 94 constmethodhandle.ConstTest displayMethodHandle (Ljava/lang/invoke/MethodHandle;)V ConstTest.java 24
+0x000004a4 50 constmethodhandle.ConstTest displayMethodType (Ljava/lang/invoke/MethodType;)V ConstTest.java 29
+0x000004e8 30 constmethodhandle.ConstTest main ([Ljava/lang/String;)V ConstTest.java -1
+0x00000518 6 constmethodhandle.ConstTest test1 ()Ljava/lang/invoke/MethodHandle; ConstTest.java -1
+0x00000530 6 constmethodhandle.ConstTest test2 ()Ljava/lang/invoke/MethodType; ConstTest.java -1
+0x00001b28 8 TestBadBootstrapArguments$TestersConstantCallSite <init> (Ljava/lang/invoke/MethodHandle;)V TestBadBootstrapArguments.java 449
+0x00002554 8 TestBase <init> ()V TestBase.java 19
+0x0000256c 68 TestBase assertEquals (BB)V TestBase.java 27
+0x000025c0 68 TestBase assertEquals (CC)V TestBase.java 34
+0x00002614 72 TestBase assertEquals (DD)V TestBase.java 69
+0x0000266c 72 TestBase assertEquals (FF)V TestBase.java 62
+0x000026c4 68 TestBase assertEquals (II)V TestBase.java 48
+0x00002774 72 TestBase assertEquals (JJ)V TestBase.java 55
+0x00002718 76 TestBase assertEquals (Ljava/lang/Object;Ljava/lang/Object;)V TestBase.java 76
+0x000027cc 68 TestBase assertEquals (SS)V TestBase.java 41
+0x00002820 76 TestBase assertNotEquals (Ljava/lang/Object;Ljava/lang/Object;)V TestBase.java 82
+0x0000287c 16 TestBase assertNotReached ()V TestBase.java 88
+0x0000289c 52 TestBase assertTrue (Z)V TestBase.java 21
+0x000028e0 22 TestBase fail ()V TestBase.java 92
+0x00002acc 8 TestInvocationKinds$Widget <init> (I)V TestInvocationKinds.java 177
+0x00002ef8 8 TestInvokeCustomWithConcurrentThreads$1 <init> ()V TestInvokeCustomWithConcurrentThreads.java 33
+0x00002eb0 26 TestInvokeCustomWithConcurrentThreads$1 initialValue ()Ljava/lang/Integer; TestInvokeCustomWithConcurrentThreads.java 36
+0x00002edc 10 TestInvokeCustomWithConcurrentThreads$1 initialValue ()Ljava/lang/Object; TestInvokeCustomWithConcurrentThreads.java 33
+0x00003fd8 8 UnrelatedBSM <init> ()V UnrelatedBSM.java 23
+0x00003fb4 20 UnrelatedBSM bsm (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite; UnrelatedBSM.java 27
+0x00001910 8 Main <init> ()V Main.java 21
+0x00001928 132 Main TestLinkerMethodMinimalArguments ()V Main.java 49
+0x000019e0 44 Main TestLinkerMethodMultipleArgumentTypes ()V Main.java 42
+0x00001a1c 156 Main TestUninitializedCallSite ()V Main.java 24
+0x00001ae0 56 Main main ([Ljava/lang/String;)V Main.java 78
+0x00001d74 8 TestBadBootstrapArguments <init> ()V TestBadBootstrapArguments.java 27
+0x00001d8c 16 TestBadBootstrapArguments boxingArguments ()V TestBadBootstrapArguments.java 348
+0x00001bc4 170 TestBadBootstrapArguments bsm (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite; TestBadBootstrapArguments.java 35
+0x00001c80 90 TestBadBootstrapArguments bsmDJ (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite; TestBadBootstrapArguments.java 270
+0x00001cec 90 TestBadBootstrapArguments bsmDoubleLong (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite; TestBadBootstrapArguments.java 314
+0x00001b6c 26 TestBadBootstrapArguments bsmReturningInteger (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer; TestBadBootstrapArguments.java 425
+0x00001b98 26 TestBadBootstrapArguments bsmReturningObject (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object; TestBadBootstrapArguments.java 402
+0x00001b40 28 TestBadBootstrapArguments bsmReturningTestersConstantCallsite (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite; TestBadBootstrapArguments.java 455
+0x00001dac 16 TestBadBootstrapArguments bsmReturningVoid (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V TestBadBootstrapArguments.java 380
+0x00001d58 10 TestBadBootstrapArguments bsmZBCS (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite; TestBadBootstrapArguments.java 227
+0x00001dcc 16 TestBadBootstrapArguments extraArguments ()V TestBadBootstrapArguments.java 158
+0x00001dec 16 TestBadBootstrapArguments happy ()V TestBadBootstrapArguments.java 74
+0x00001e0c 8 TestBadBootstrapArguments integerReturnType ()V TestBadBootstrapArguments.java 444
+0x00001e24 8 TestBadBootstrapArguments invokeBoxingArguments ()V TestBadBootstrapArguments.java 344
+0x00001e3c 8 TestBadBootstrapArguments invokeExtraArguments ()V TestBadBootstrapArguments.java 154
+0x00001e54 8 TestBadBootstrapArguments invokeHappy ()V TestBadBootstrapArguments.java 70
+0x00001e6c 8 TestBadBootstrapArguments invokeIntegerReturnType ()V TestBadBootstrapArguments.java 440
+0x00001e84 8 TestBadBootstrapArguments invokeMissingParameterTypes ()V TestBadBootstrapArguments.java 124
+0x00001e9c 8 TestBadBootstrapArguments invokeNarrowArguments ()V TestBadBootstrapArguments.java 256
+0x00001eb4 8 TestBadBootstrapArguments invokeObjectReturnType ()V TestBadBootstrapArguments.java 417
+0x00001ecc 8 TestBadBootstrapArguments invokeViaCustomCallSiteClass ()V TestBadBootstrapArguments.java 469
+0x00001ee4 8 TestBadBootstrapArguments invokeVoidReturnType ()V TestBadBootstrapArguments.java 394
+0x00001efc 8 TestBadBootstrapArguments invokeWideningArguments ()V TestBadBootstrapArguments.java 300
+0x00001f14 8 TestBadBootstrapArguments invokeWideningBoxingArguments ()V TestBadBootstrapArguments.java 372
+0x00001f2c 8 TestBadBootstrapArguments invokeWrongArguments ()V TestBadBootstrapArguments.java 182
+0x00001f44 8 TestBadBootstrapArguments invokeWrongArgumentsAgain ()V TestBadBootstrapArguments.java 210
+0x00001f5c 8 TestBadBootstrapArguments invokeWrongParameterTypes ()V TestBadBootstrapArguments.java 98
+0x00001f74 16 TestBadBootstrapArguments missingParameterTypes ()V TestBadBootstrapArguments.java 128
+0x00001f94 8 TestBadBootstrapArguments narrowArguments ()V TestBadBootstrapArguments.java 260
+0x00001fac 8 TestBadBootstrapArguments objectReturnType ()V TestBadBootstrapArguments.java 421
+0x00001fc4 16 TestBadBootstrapArguments sayHello ()V TestBadBootstrapArguments.java 473
+0x00001fe4 1058 TestBadBootstrapArguments test ()V TestBadBootstrapArguments.java 477
+0x0000249c 8 TestBadBootstrapArguments voidReturnType ()V TestBadBootstrapArguments.java 398
+0x000024b4 16 TestBadBootstrapArguments wideningArguments ()V TestBadBootstrapArguments.java 304
+0x000024d4 16 TestBadBootstrapArguments wideningBoxingArguments ()V TestBadBootstrapArguments.java 376
+0x000024f4 16 TestBadBootstrapArguments wrongArguments ()V TestBadBootstrapArguments.java 186
+0x00002514 16 TestBadBootstrapArguments wrongArgumentsAgain ()V TestBadBootstrapArguments.java 214
+0x00002534 16 TestBadBootstrapArguments wrongParameterTypes ()V TestBadBootstrapArguments.java 102
+0x000029d8 8 TestDynamicBootstrapArguments <clinit> ()V TestDynamicBootstrapArguments.java 27
+0x000029f0 8 TestDynamicBootstrapArguments <init> ()V TestDynamicBootstrapArguments.java 26
+0x00002970 86 TestDynamicBootstrapArguments bsm (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite; TestDynamicBootstrapArguments.java 36
+0x00002908 60 TestDynamicBootstrapArguments targetA100000000 (ILjava/lang/String;Ljava/lang/Double;)I TestDynamicBootstrapArguments.java 71
+0x00002a08 50 TestDynamicBootstrapArguments test ()V TestDynamicBootstrapArguments.java 86
+0x00002a4c 110 TestDynamicBootstrapArguments testCallSites ()V TestDynamicBootstrapArguments.java 80
+0x00002954 10 TestDynamicBootstrapArguments testDynamic (ILjava/lang/String;Ljava/lang/Double;)I TestDynamicBootstrapArguments.java 66
+0x00002cb4 8 TestInvocationKinds <init> ()V TestInvocationKinds.java 25
+0x00002b00 12 TestInvocationKinds getInstanceField (LTestInvocationKinds;)D TestInvocationKinds.java 117
+0x00002b38 10 TestInvocationKinds getStaticField ()I TestInvocationKinds.java 71
+0x00002b70 40 TestInvocationKinds lookupConstructor (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 183
+0x00002ba8 40 TestInvocationKinds lookupInstanceFieldGetter (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 101
+0x00002be0 42 TestInvocationKinds lookupInstanceFieldSetter (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 78
+0x00002c1c 32 TestInvocationKinds lookupStaticFieldGetter (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 32
+0x00002c4c 34 TestInvocationKinds lookupStaticFieldSetter (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 54
+0x00002c80 36 TestInvocationKinds lookupVirtual (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvocationKinds.java 146
+0x00002ae4 10 TestInvocationKinds makeWidget (I)LTestInvocationKinds$Widget; TestInvocationKinds.java 200
+0x00002b54 10 TestInvocationKinds maxIntegerValue (LTestInvocationKinds;II)I TestInvocationKinds.java 159
+0x00002ccc 16 TestInvocationKinds setInstanceField (LTestInvocationKinds;D)V TestInvocationKinds.java 94
+0x00002cec 8 TestInvocationKinds setStaticField (I)V TestInvocationKinds.java 48
+0x00002d04 48 TestInvocationKinds test ()V TestInvocationKinds.java 212
+0x00002d44 62 TestInvocationKinds testConstructor ()V TestInvocationKinds.java 205
+0x00002d94 88 TestInvocationKinds testInstanceFieldAccessors ()V TestInvocationKinds.java 133
+0x00002dfc 50 TestInvocationKinds testInvokeVirtual ()V TestInvocationKinds.java 168
+0x00002e40 94 TestInvocationKinds testStaticFieldAccessors ()V TestInvocationKinds.java 122
+0x00002b1c 12 TestInvocationKinds getMaxIntegerValue (II)I TestInvocationKinds.java 164
+0x00003074 74 TestInvokeCustomWithConcurrentThreads <clinit> ()V TestInvokeCustomWithConcurrentThreads.java 30
+0x000030d0 8 TestInvokeCustomWithConcurrentThreads <init> ()V TestInvokeCustomWithConcurrentThreads.java 52
+0x0000305c 6 TestInvokeCustomWithConcurrentThreads access$000 ()Ljava/util/concurrent/atomic/AtomicInteger; TestInvokeCustomWithConcurrentThreads.java 27
+0x00002f10 26 TestInvokeCustomWithConcurrentThreads getThreadIndex ()I TestInvokeCustomWithConcurrentThreads.java 55
+0x00002f88 194 TestInvokeCustomWithConcurrentThreads linkerMethod (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestInvokeCustomWithConcurrentThreads.java 87
+0x00002f3c 2 TestInvokeCustomWithConcurrentThreads notUsed (I)I TestInvokeCustomWithConcurrentThreads.java 59
+0x00002f50 40 TestInvokeCustomWithConcurrentThreads setCalled (I)I TestInvokeCustomWithConcurrentThreads.java 79
+0x0000310c 458 TestInvokeCustomWithConcurrentThreads test ()V TestInvokeCustomWithConcurrentThreads.java 107
+0x000030e8 18 TestInvokeCustomWithConcurrentThreads run ()V TestInvokeCustomWithConcurrentThreads.java 63
+0x00003414 8 TestLinkerMethodMinimalArguments <clinit> ()V TestLinkerMethodMinimalArguments.java 26
+0x0000342c 8 TestLinkerMethodMinimalArguments <init> ()V TestLinkerMethodMinimalArguments.java 25
+0x000032e8 46 TestLinkerMethodMinimalArguments _add (II)I TestLinkerMethodMinimalArguments.java 51
+0x00003328 10 TestLinkerMethodMinimalArguments add (II)I TestLinkerMethodMinimalArguments.java 45
+0x00003344 192 TestLinkerMethodMinimalArguments linkerMethod (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; TestLinkerMethodMinimalArguments.java 61
+0x00003444 136 TestLinkerMethodMinimalArguments test (III)V TestLinkerMethodMinimalArguments.java 78
+0x00003628 8 TestLinkerMethodMultipleArgumentTypes <clinit> ()V TestLinkerMethodMultipleArgumentTypes.java 28
+0x00003640 8 TestLinkerMethodMultipleArgumentTypes <init> ()V TestLinkerMethodMultipleArgumentTypes.java 26
+0x000034f4 6 TestLinkerMethodMultipleArgumentTypes _add (II)I TestLinkerMethodMultipleArgumentTypes.java 74
+0x0000350c 10 TestLinkerMethodMultipleArgumentTypes add (II)I TestLinkerMethodMultipleArgumentTypes.java 68
+0x00003528 238 TestLinkerMethodMultipleArgumentTypes linkerMethod (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite; TestLinkerMethodMultipleArgumentTypes.java 93
+0x00003658 34 TestLinkerMethodMultipleArgumentTypes test (II)V TestLinkerMethodMultipleArgumentTypes.java 114
+0x000034dc 6 TestLinkerMethodMultipleArgumentTypes GetBootstrapRunCount ()I TestLinkerMethodMultipleArgumentTypes.java 110
+0x000036f4 8 TestLinkerUnrelatedBSM <init> ()V TestLinkerUnrelatedBSM.java 23
+0x0000368c 6 TestLinkerUnrelatedBSM _addf (FF)F TestLinkerUnrelatedBSM.java 47
+0x000036a4 6 TestLinkerUnrelatedBSM _subf (FF)F TestLinkerUnrelatedBSM.java 73
+0x000036bc 10 TestLinkerUnrelatedBSM addf (FF)F TestLinkerUnrelatedBSM.java 42
+0x000036d8 10 TestLinkerUnrelatedBSM subf (FF)F TestLinkerUnrelatedBSM.java 68
+0x0000370c 68 TestLinkerUnrelatedBSM test ()V TestLinkerUnrelatedBSM.java 77
+0x00003a8c 8 TestVariableArityLinkerMethod <init> ()V TestVariableArityLinkerMethod.java 27
+0x00003760 68 TestVariableArityLinkerMethod bsmWithBoxedArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 477
+0x000037b4 74 TestVariableArityLinkerMethod bsmWithClassAndFloatArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 294
+0x00003810 68 TestVariableArityLinkerMethod bsmWithClassArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 367
+0x00003864 68 TestVariableArityLinkerMethod bsmWithDoubleArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 332
+0x000038b8 82 TestVariableArityLinkerMethod bsmWithFloatAndLongArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 257
+0x0000391c 82 TestVariableArityLinkerMethod bsmWithIntAndStringArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 133
+0x00003980 82 TestVariableArityLinkerMethod bsmWithLongAndIntArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 219
+0x000039e4 68 TestVariableArityLinkerMethod bsmWithStringArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 61
+0x00003a38 68 TestVariableArityLinkerMethod bsmWithWiderArray (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite; TestVariableArityLinkerMethod.java 447
+0x00003aa4 16 TestVariableArityLinkerMethod methodA ()V TestVariableArityLinkerMethod.java 86
+0x00003ac4 16 TestVariableArityLinkerMethod methodB ()V TestVariableArityLinkerMethod.java 105
+0x00003ae4 16 TestVariableArityLinkerMethod methodC ()V TestVariableArityLinkerMethod.java 123
+0x00003b04 16 TestVariableArityLinkerMethod methodD ()V TestVariableArityLinkerMethod.java 166
+0x00003b24 16 TestVariableArityLinkerMethod methodE ()V TestVariableArityLinkerMethod.java 189
+0x00003b44 16 TestVariableArityLinkerMethod methodF ()V TestVariableArityLinkerMethod.java 209
+0x00003b64 16 TestVariableArityLinkerMethod methodG ()V TestVariableArityLinkerMethod.java 247
+0x00003b84 16 TestVariableArityLinkerMethod methodH ()V TestVariableArityLinkerMethod.java 284
+0x00003ba4 16 TestVariableArityLinkerMethod methodI ()V TestVariableArityLinkerMethod.java 323
+0x00003bc4 16 TestVariableArityLinkerMethod methodJ ()V TestVariableArityLinkerMethod.java 358
+0x00003be4 16 TestVariableArityLinkerMethod methodK ()V TestVariableArityLinkerMethod.java 392
+0x00003c04 8 TestVariableArityLinkerMethod methodO ()V TestVariableArityLinkerMethod.java 413
+0x00003c1c 8 TestVariableArityLinkerMethod methodP ()V TestVariableArityLinkerMethod.java 441
+0x00003c34 8 TestVariableArityLinkerMethod methodQ ()V TestVariableArityLinkerMethod.java 468
+0x00003c4c 8 TestVariableArityLinkerMethod methodR ()V TestVariableArityLinkerMethod.java 501
+0x00003c64 318 TestVariableArityLinkerMethod printBsmArgs (Ljava/lang/String;[Ljava/lang/Object;)V TestVariableArityLinkerMethod.java 29
+0x00003db4 448 TestVariableArityLinkerMethod test ()V TestVariableArityLinkerMethod.java 506
+0x000001bc 8 Main <init> ()V Main.java 9
+0x000001d4 60 Main main ([Ljava/lang/String;)V Main.java 31
+0x000001bc 8 StaticFields <init> ()V StaticFields.java 24
+0x000003bc 8 Test <clinit> ()V Test.java 66
+0x000003d4 8 Test <init> ()V Test.java 1
diff --git a/test/dexdump/all-dex-files.txt b/test/dexdump/all-dex-files.txt
new file mode 100644
index 0000000..4504f49
--- /dev/null
+++ b/test/dexdump/all-dex-files.txt
@@ -0,0 +1,15285 @@
+Processing 'all-dex-files.jar'...
+Opened 'all-dex-files.jar:classes.dex', DEX version '035'
+DEX file header:
+magic               : 'dex\n035\0'
+checksum            : d5134208
+signature           : 7af6...100f
+file_size           : 2572
+header_size         : 112
+link_size           : 0
+link_off            : 0 (0x000000)
+string_ids_size     : 46
+string_ids_off      : 112 (0x000070)
+type_ids_size       : 10
+type_ids_off        : 296 (0x000128)
+proto_ids_size      : 3
+proto_ids_off       : 336 (0x000150)
+field_ids_size      : 14
+field_ids_off       : 372 (0x000174)
+method_ids_size     : 21
+method_ids_off      : 484 (0x0001e4)
+class_defs_size     : 1
+class_defs_off      : 652 (0x00028c)
+data_size           : 1888
+data_off            : 684 (0x0002ac)
+
+Class #0 header:
+class_idx           : 4
+access_flags        : 1 (0x0001)
+superclass_idx      : 5
+interfaces_off      : 0 (0x000000)
+source_file_idx     : -1
+annotations_off     : 0 (0x000000)
+class_data_off      : 2310 (0x000906)
+static_fields_size  : 7
+instance_fields_size: 7
+direct_methods_size : 18
+virtual_methods_size: 2
+
+Class #0            -
+  Class descriptor  : 'LA;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+  Static fields     -
+    #0              : (in LA;)
+      name          : 'sB'
+      type          : 'B'
+      access        : 0x000a (PRIVATE STATIC)
+    #1              : (in LA;)
+      name          : 'sC'
+      type          : 'C'
+      access        : 0x000a (PRIVATE STATIC)
+    #2              : (in LA;)
+      name          : 'sI'
+      type          : 'I'
+      access        : 0x000a (PRIVATE STATIC)
+    #3              : (in LA;)
+      name          : 'sJ'
+      type          : 'J'
+      access        : 0x000a (PRIVATE STATIC)
+    #4              : (in LA;)
+      name          : 'sO'
+      type          : 'LA;'
+      access        : 0x000a (PRIVATE STATIC)
+    #5              : (in LA;)
+      name          : 'sS'
+      type          : 'S'
+      access        : 0x000a (PRIVATE STATIC)
+    #6              : (in LA;)
+      name          : 'sZ'
+      type          : 'Z'
+      access        : 0x000a (PRIVATE STATIC)
+  Instance fields   -
+    #0              : (in LA;)
+      name          : 'mB'
+      type          : 'B'
+      access        : 0x0002 (PRIVATE)
+    #1              : (in LA;)
+      name          : 'mC'
+      type          : 'C'
+      access        : 0x0002 (PRIVATE)
+    #2              : (in LA;)
+      name          : 'mI'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #3              : (in LA;)
+      name          : 'mJ'
+      type          : 'J'
+      access        : 0x0002 (PRIVATE)
+    #4              : (in LA;)
+      name          : 'mO'
+      type          : 'LA;'
+      access        : 0x0002 (PRIVATE)
+    #5              : (in LA;)
+      name          : 'mS'
+      type          : 'S'
+      access        : 0x0002 (PRIVATE)
+    #6              : (in LA;)
+      name          : 'mZ'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+  Direct methods    -
+    #0              : (in LA;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 0
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+00042c:                                        |[00042c] A.<init>:()V
+00043c: 7010 1400 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0014
+000442: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #1              : (in LA;)
+      name          : 'arrays'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 1
+      code          -
+      registers     : 3
+      ins           : 0
+      outs          : 0
+      insns size    : 29 16-bit code units
+000444:                                        |[000444] A.arrays:()V
+000454: 4400 0102                              |0000: aget v0, v1, v2
+000458: 4500 0102                              |0002: aget-wide v0, v1, v2
+00045c: 4600 0102                              |0004: aget-object v0, v1, v2
+000460: 4700 0102                              |0006: aget-boolean v0, v1, v2
+000464: 4800 0102                              |0008: aget-byte v0, v1, v2
+000468: 4900 0102                              |000a: aget-char v0, v1, v2
+00046c: 4a00 0102                              |000c: aget-short v0, v1, v2
+000470: 4b00 0102                              |000e: aput v0, v1, v2
+000474: 4c00 0102                              |0010: aput-wide v0, v1, v2
+000478: 4d00 0102                              |0012: aput-object v0, v1, v2
+00047c: 4e00 0102                              |0014: aput-boolean v0, v1, v2
+000480: 4f00 0102                              |0016: aput-byte v0, v1, v2
+000484: 5000 0102                              |0018: aput-char v0, v1, v2
+000488: 5100 0102                              |001a: aput-short v0, v1, v2
+00048c: 0e00                                   |001c: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #2              : (in LA;)
+      name          : 'binary_ops'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 2
+      code          -
+      registers     : 3
+      ins           : 0
+      outs          : 0
+      insns size    : 65 16-bit code units
+000490:                                        |[000490] A.binary_ops:()V
+0004a0: 9000 0102                              |0000: add-int v0, v1, v2
+0004a4: 9100 0102                              |0002: sub-int v0, v1, v2
+0004a8: 9200 0102                              |0004: mul-int v0, v1, v2
+0004ac: 9300 0102                              |0006: div-int v0, v1, v2
+0004b0: 9400 0102                              |0008: rem-int v0, v1, v2
+0004b4: 9500 0102                              |000a: and-int v0, v1, v2
+0004b8: 9600 0102                              |000c: or-int v0, v1, v2
+0004bc: 9700 0102                              |000e: xor-int v0, v1, v2
+0004c0: 9800 0102                              |0010: shl-int v0, v1, v2
+0004c4: 9900 0102                              |0012: shr-int v0, v1, v2
+0004c8: 9a00 0102                              |0014: ushr-int v0, v1, v2
+0004cc: 9b00 0102                              |0016: add-long v0, v1, v2
+0004d0: 9c00 0102                              |0018: sub-long v0, v1, v2
+0004d4: 9d00 0102                              |001a: mul-long v0, v1, v2
+0004d8: 9e00 0102                              |001c: div-long v0, v1, v2
+0004dc: 9f00 0102                              |001e: rem-long v0, v1, v2
+0004e0: a000 0102                              |0020: and-long v0, v1, v2
+0004e4: a100 0102                              |0022: or-long v0, v1, v2
+0004e8: a200 0102                              |0024: xor-long v0, v1, v2
+0004ec: a300 0102                              |0026: shl-long v0, v1, v2
+0004f0: a400 0102                              |0028: shr-long v0, v1, v2
+0004f4: a500 0102                              |002a: ushr-long v0, v1, v2
+0004f8: a600 0102                              |002c: add-float v0, v1, v2
+0004fc: a700 0102                              |002e: sub-float v0, v1, v2
+000500: a800 0102                              |0030: mul-float v0, v1, v2
+000504: a900 0102                              |0032: div-float v0, v1, v2
+000508: aa00 0102                              |0034: rem-float v0, v1, v2
+00050c: ab00 0102                              |0036: add-double v0, v1, v2
+000510: ac00 0102                              |0038: sub-double v0, v1, v2
+000514: ad00 0102                              |003a: mul-double v0, v1, v2
+000518: ae00 0102                              |003c: div-double v0, v1, v2
+00051c: af00 0102                              |003e: rem-double v0, v1, v2
+000520: 0e00                                   |0040: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #3              : (in LA;)
+      name          : 'binary_ops_2addr'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 3
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 0
+      insns size    : 33 16-bit code units
+000524:                                        |[000524] A.binary_ops_2addr:()V
+000534: b010                                   |0000: add-int/2addr v0, v1
+000536: b110                                   |0001: sub-int/2addr v0, v1
+000538: b210                                   |0002: mul-int/2addr v0, v1
+00053a: b310                                   |0003: div-int/2addr v0, v1
+00053c: b410                                   |0004: rem-int/2addr v0, v1
+00053e: b510                                   |0005: and-int/2addr v0, v1
+000540: b610                                   |0006: or-int/2addr v0, v1
+000542: b710                                   |0007: xor-int/2addr v0, v1
+000544: b810                                   |0008: shl-int/2addr v0, v1
+000546: b910                                   |0009: shr-int/2addr v0, v1
+000548: ba10                                   |000a: ushr-int/2addr v0, v1
+00054a: bb10                                   |000b: add-long/2addr v0, v1
+00054c: bc10                                   |000c: sub-long/2addr v0, v1
+00054e: bd10                                   |000d: mul-long/2addr v0, v1
+000550: be10                                   |000e: div-long/2addr v0, v1
+000552: bf10                                   |000f: rem-long/2addr v0, v1
+000554: c010                                   |0010: and-long/2addr v0, v1
+000556: c110                                   |0011: or-long/2addr v0, v1
+000558: c210                                   |0012: xor-long/2addr v0, v1
+00055a: c310                                   |0013: shl-long/2addr v0, v1
+00055c: c410                                   |0014: shr-long/2addr v0, v1
+00055e: c510                                   |0015: ushr-long/2addr v0, v1
+000560: c610                                   |0016: add-float/2addr v0, v1
+000562: c710                                   |0017: sub-float/2addr v0, v1
+000564: c810                                   |0018: mul-float/2addr v0, v1
+000566: c910                                   |0019: div-float/2addr v0, v1
+000568: ca10                                   |001a: rem-float/2addr v0, v1
+00056a: cb10                                   |001b: add-double/2addr v0, v1
+00056c: cc10                                   |001c: sub-double/2addr v0, v1
+00056e: cd10                                   |001d: mul-double/2addr v0, v1
+000570: ce10                                   |001e: div-double/2addr v0, v1
+000572: cf10                                   |001f: rem-double/2addr v0, v1
+000574: 0e00                                   |0020: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #4              : (in LA;)
+      name          : 'binary_ops_lit16'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 4
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 0
+      insns size    : 17 16-bit code units
+000578:                                        |[000578] A.binary_ops_lit16:()V
+000588: d010 3412                              |0000: add-int/lit16 v0, v1, #int 4660 // #1234
+00058c: d110 3412                              |0002: rsub-int v0, v1, #int 4660 // #1234
+000590: d210 3412                              |0004: mul-int/lit16 v0, v1, #int 4660 // #1234
+000594: d310 3412                              |0006: div-int/lit16 v0, v1, #int 4660 // #1234
+000598: d410 3412                              |0008: rem-int/lit16 v0, v1, #int 4660 // #1234
+00059c: d510 3412                              |000a: and-int/lit16 v0, v1, #int 4660 // #1234
+0005a0: d610 3412                              |000c: or-int/lit16 v0, v1, #int 4660 // #1234
+0005a4: d710 3412                              |000e: xor-int/lit16 v0, v1, #int 4660 // #1234
+0005a8: 0e00                                   |0010: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #5              : (in LA;)
+      name          : 'binary_ops_lit8'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 5
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 0
+      insns size    : 23 16-bit code units
+0005ac:                                        |[0005ac] A.binary_ops_lit8:()V
+0005bc: d800 0112                              |0000: add-int/lit8 v0, v1, #int 18 // #12
+0005c0: d900 0112                              |0002: rsub-int/lit8 v0, v1, #int 18 // #12
+0005c4: da00 0112                              |0004: mul-int/lit8 v0, v1, #int 18 // #12
+0005c8: db00 0112                              |0006: div-int/lit8 v0, v1, #int 18 // #12
+0005cc: dc00 0112                              |0008: rem-int/lit8 v0, v1, #int 18 // #12
+0005d0: dd00 0112                              |000a: and-int/lit8 v0, v1, #int 18 // #12
+0005d4: de00 0112                              |000c: or-int/lit8 v0, v1, #int 18 // #12
+0005d8: df00 0112                              |000e: xor-int/lit8 v0, v1, #int 18 // #12
+0005dc: e000 0112                              |0010: shl-int/lit8 v0, v1, #int 18 // #12
+0005e0: e100 0112                              |0012: shr-int/lit8 v0, v1, #int 18 // #12
+0005e4: e200 0112                              |0014: ushr-int/lit8 v0, v1, #int 18 // #12
+0005e8: 0e00                                   |0016: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #6              : (in LA;)
+      name          : 'compares'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 6
+      code          -
+      registers     : 3
+      ins           : 0
+      outs          : 0
+      insns size    : 11 16-bit code units
+0005ec:                                        |[0005ec] A.compares:()V
+0005fc: 2d00 0102                              |0000: cmpl-float v0, v1, v2
+000600: 2e00 0102                              |0002: cmpg-float v0, v1, v2
+000604: 2f00 0102                              |0004: cmpl-double v0, v1, v2
+000608: 3000 0102                              |0006: cmpg-double v0, v1, v2
+00060c: 3100 0102                              |0008: cmp-long v0, v1, v2
+000610: 0e00                                   |000a: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #7              : (in LA;)
+      name          : 'conditionals'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 7
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 0
+      insns size    : 25 16-bit code units
+000614:                                        |[000614] A.conditionals:()V
+000624: 3210 1800                              |0000: if-eq v0, v1, 0018 // +0018
+000628: 3310 1600                              |0002: if-ne v0, v1, 0018 // +0016
+00062c: 3410 1400                              |0004: if-lt v0, v1, 0018 // +0014
+000630: 3510 1200                              |0006: if-ge v0, v1, 0018 // +0012
+000634: 3610 1000                              |0008: if-gt v0, v1, 0018 // +0010
+000638: 3710 0e00                              |000a: if-le v0, v1, 0018 // +000e
+00063c: 3800 0c00                              |000c: if-eqz v0, 0018 // +000c
+000640: 3900 0a00                              |000e: if-nez v0, 0018 // +000a
+000644: 3a00 0800                              |0010: if-ltz v0, 0018 // +0008
+000648: 3b00 0600                              |0012: if-gez v0, 0018 // +0006
+00064c: 3c00 0400                              |0014: if-gtz v0, 0018 // +0004
+000650: 3d00 0200                              |0016: if-lez v0, 0018 // +0002
+000654: 0e00                                   |0018: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #8              : (in LA;)
+      name          : 'constants'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 8
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 28 16-bit code units
+000658:                                        |[000658] A.constants:()V
+000668: 1210                                   |0000: const/4 v0, #int 1 // #1
+00066a: 1300 3412                              |0001: const/16 v0, #int 4660 // #1234
+00066e: 1400 7856 3412                         |0003: const v0, #float 5.69046e-28 // #12345678
+000674: 1500 3412                              |0006: const/high16 v0, #int 305397760 // #1234
+000678: 1600 3412                              |0008: const-wide/16 v0, #int 4660 // #1234
+00067c: 1700 7856 3412                         |000a: const-wide/32 v0, #float 5.69046e-28 // #12345678
+000682: 1800 efcd ab90 7856 3412               |000d: const-wide v0, #double 5.62635e-221 // #1234567890abcdef
+00068c: 1900 3412                              |0012: const-wide/high16 v0, #long 1311673391471656960 // #1234
+000690: 1a00 2c00                              |0014: const-string v0, "string" // string@002c
+000694: 1b00 2c00 0000                         |0016: const-string/jumbo v0, "string" // string@0000002c
+00069a: 1c00 0500                              |0019: const-class v0, Ljava/lang/Object; // type@0005
+00069e: 0e00                                   |001b: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #9              : (in LA;)
+      name          : 'misc'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 11
+      code          -
+      registers     : 5
+      ins           : 0
+      outs          : 0
+      insns size    : 54 16-bit code units
+0006a0:                                        |[0006a0] A.misc:()V
+0006b0: 0000                                   |0000: nop // spacer
+0006b2: 1d00                                   |0001: monitor-enter v0
+0006b4: 1e00                                   |0002: monitor-exit v0
+0006b6: 1f00 0500                              |0003: check-cast v0, Ljava/lang/Object; // type@0005
+0006ba: 2010 0500                              |0005: instance-of v0, v1, Ljava/lang/Object; // type@0005
+0006be: 2110                                   |0007: array-length v0, v1
+0006c0: 2200 0500                              |0008: new-instance v0, Ljava/lang/Object; // type@0005
+0006c4: 2310 0500                              |000a: new-array v0, v1, Ljava/lang/Object; // type@0005
+0006c8: 2454 0900 1032                         |000c: filled-new-array {v0, v1, v2, v3, v4}, [Ljava/lang/Object; // type@0009
+0006ce: 2505 0900 0000                         |000f: filled-new-array/range {v0, v1, v2, v3, v4}, [Ljava/lang/Object; // type@0009
+0006d4: 2600 0c00 0000                         |0012: fill-array-data v0, 0000001e // +0000000c
+0006da: 2700                                   |0015: throw v0
+0006dc: 2806                                   |0016: goto 001c // +0006
+0006de: 2900 0500                              |0017: goto/16 001c // +0005
+0006e2: 2a00 0300 0000                         |0019: goto/32 #00000003
+0006e8: 0e00                                   |001c: return-void
+0006ea: 0000                                   |001d: nop // spacer
+0006ec: 0003 0400 0a00 0000 0100 0000 0200 ... |001e: array-data (24 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #10              : (in LA;)
+      name          : 'moves'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 12
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 0
+      insns size    : 23 16-bit code units
+00071c:                                        |[00071c] A.moves:()V
+00072c: 0110                                   |0000: move v0, v1
+00072e: 0200 0100                              |0001: move/from16 v0, v1
+000732: 0300 0000 0100                         |0003: move/16 v0, v1
+000738: 0410                                   |0006: move-wide v0, v1
+00073a: 0500 0100                              |0007: move-wide/from16 v0, v1
+00073e: 0600 0000 0100                         |0009: move-wide/16 v0, v1
+000744: 0710                                   |000c: move-object v0, v1
+000746: 0800 0100                              |000d: move-object/from16 v0, v1
+00074a: 0900 0000 0100                         |000f: move-object/16 v0, v1
+000750: 0a00                                   |0012: move-result v0
+000752: 0b00                                   |0013: move-result-wide v0
+000754: 0c00                                   |0014: move-result-object v0
+000756: 0d00                                   |0015: move-exception v0
+000758: 0e00                                   |0016: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #11              : (in LA;)
+      name          : 'packed_switch'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 13
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 16 16-bit code units
+00075c:                                        |[00075c] A.packed_switch:()V
+00076c: 2b00 0800 0000                         |0000: packed-switch v0, 00000008 // +00000008
+000772: 0e00                                   |0003: return-void
+000774: 28ff                                   |0004: goto 0003 // -0001
+000776: 28fe                                   |0005: goto 0003 // -0002
+000778: 28fd                                   |0006: goto 0003 // -0003
+00077a: 0000                                   |0007: nop // spacer
+00077c: 0001 0200 feff ff7f 0500 0000 0600 ... |0008: packed-switch-data (8 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #12              : (in LA;)
+      name          : 'return32'
+      type          : '()I'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 14
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 1 16-bit code units
+00078c:                                        |[00078c] A.return32:()I
+00079c: 0f00                                   |0000: return v0
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #13              : (in LA;)
+      name          : 'return64'
+      type          : '()I'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 15
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 0
+      insns size    : 1 16-bit code units
+0007a0:                                        |[0007a0] A.return64:()I
+0007b0: 1000                                   |0000: return-wide v0
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #14              : (in LA;)
+      name          : 'return_object'
+      type          : '()Ljava/lang/Object;'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 16
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 1 16-bit code units
+0007b4:                                        |[0007b4] A.return_object:()Ljava/lang/Object;
+0007c4: 1100                                   |0000: return-object v0
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #15              : (in LA;)
+      name          : 'sparse_switch'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 17
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 0
+      insns size    : 22 16-bit code units
+0007c8:                                        |[0007c8] A.sparse_switch:()V
+0007d8: 2c00 0400 0000                         |0000: sparse-switch v0, 00000004 // +00000004
+0007de: 0e00                                   |0003: return-void
+0007e0: 0002 0400 1111 0000 2222 0000 3333 ... |0004: sparse-switch-data (18 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #16              : (in LA;)
+      name          : 'static_fields'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 18
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 29 16-bit code units
+000804:                                        |[000804] A.static_fields:()V
+000814: 6000 0900                              |0000: sget v0, LA;.sI:I // field@0009
+000818: 6100 0a00                              |0002: sget-wide v0, LA;.sJ:J // field@000a
+00081c: 6200 0b00                              |0004: sget-object v0, LA;.sO:LA; // field@000b
+000820: 6300 0d00                              |0006: sget-boolean v0, LA;.sZ:Z // field@000d
+000824: 6400 0700                              |0008: sget-byte v0, LA;.sB:B // field@0007
+000828: 6500 0800                              |000a: sget-char v0, LA;.sC:C // field@0008
+00082c: 6600 0c00                              |000c: sget-short v0, LA;.sS:S // field@000c
+000830: 6700 0900                              |000e: sput v0, LA;.sI:I // field@0009
+000834: 6800 0a00                              |0010: sput-wide v0, LA;.sJ:J // field@000a
+000838: 6900 0b00                              |0012: sput-object v0, LA;.sO:LA; // field@000b
+00083c: 6a00 0d00                              |0014: sput-boolean v0, LA;.sZ:Z // field@000d
+000840: 6b00 0700                              |0016: sput-byte v0, LA;.sB:B // field@0007
+000844: 6c00 0800                              |0018: sput-char v0, LA;.sC:C // field@0008
+000848: 6d00 0500                              |001a: sput-short v0, LA;.mS:S // field@0005
+00084c: 0e00                                   |001c: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #17              : (in LA;)
+      name          : 'unary_ops'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 19
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 0
+      insns size    : 22 16-bit code units
+000850:                                        |[000850] A.unary_ops:()V
+000860: 7b10                                   |0000: neg-int v0, v1
+000862: 7c10                                   |0001: not-int v0, v1
+000864: 7d10                                   |0002: neg-long v0, v1
+000866: 7e10                                   |0003: not-long v0, v1
+000868: 7f10                                   |0004: neg-float v0, v1
+00086a: 8010                                   |0005: neg-double v0, v1
+00086c: 8110                                   |0006: int-to-long v0, v1
+00086e: 8210                                   |0007: int-to-float v0, v1
+000870: 8310                                   |0008: int-to-double v0, v1
+000872: 8410                                   |0009: long-to-int v0, v1
+000874: 8510                                   |000a: long-to-float v0, v1
+000876: 8610                                   |000b: long-to-double v0, v1
+000878: 8710                                   |000c: float-to-int v0, v1
+00087a: 8810                                   |000d: float-to-long v0, v1
+00087c: 8910                                   |000e: float-to-double v0, v1
+00087e: 8a10                                   |000f: double-to-int v0, v1
+000880: 8b10                                   |0010: double-to-long v0, v1
+000882: 8c10                                   |0011: double-to-float v0, v1
+000884: 8d10                                   |0012: int-to-byte v0, v1
+000886: 8e10                                   |0013: int-to-char v0, v1
+000888: 8f10                                   |0014: int-to-short v0, v1
+00088a: 0e00                                   |0015: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+    #0              : (in LA;)
+      name          : 'instance_fields'
+      type          : '()V'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 9
+      code          -
+      registers     : 2
+      ins           : 1
+      outs          : 0
+      insns size    : 29 16-bit code units
+00088c:                                        |[00088c] A.instance_fields:()V
+00089c: 5210 0900                              |0000: iget v0, v1, LA;.sI:I // field@0009
+0008a0: 5310 0a00                              |0002: iget-wide v0, v1, LA;.sJ:J // field@000a
+0008a4: 5410 0b00                              |0004: iget-object v0, v1, LA;.sO:LA; // field@000b
+0008a8: 5510 0d00                              |0006: iget-boolean v0, v1, LA;.sZ:Z // field@000d
+0008ac: 5610 0700                              |0008: iget-byte v0, v1, LA;.sB:B // field@0007
+0008b0: 5710 0800                              |000a: iget-char v0, v1, LA;.sC:C // field@0008
+0008b4: 5810 0c00                              |000c: iget-short v0, v1, LA;.sS:S // field@000c
+0008b8: 5910 0900                              |000e: iput v0, v1, LA;.sI:I // field@0009
+0008bc: 5a10 0a00                              |0010: iput-wide v0, v1, LA;.sJ:J // field@000a
+0008c0: 5b10 0b00                              |0012: iput-object v0, v1, LA;.sO:LA; // field@000b
+0008c4: 5c10 0d00                              |0014: iput-boolean v0, v1, LA;.sZ:Z // field@000d
+0008c8: 5d10 0700                              |0016: iput-byte v0, v1, LA;.sB:B // field@0007
+0008cc: 5e10 0800                              |0018: iput-char v0, v1, LA;.sC:C // field@0008
+0008d0: 5f10 0c00                              |001a: iput-short v0, v1, LA;.sS:S // field@000c
+0008d4: 0e00                                   |001c: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #1              : (in LA;)
+      name          : 'invokes'
+      type          : '()V'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 10
+      code          -
+      registers     : 5
+      ins           : 1
+      outs          : 1
+      insns size    : 15 16-bit code units
+0008d8:                                        |[0008d8] A.invokes:()V
+0008e8: 6e54 0a00 1032                         |0000: invoke-virtual {v0, v1, v2, v3, v4}, LA;.invokes:()V // method@000a
+0008ee: 6f54 0a00 1032                         |0003: invoke-super {v0, v1, v2, v3, v4}, LA;.invokes:()V // method@000a
+0008f4: 7054 0a00 1032                         |0006: invoke-direct {v0, v1, v2, v3, v4}, LA;.invokes:()V // method@000a
+0008fa: 7154 0a00 1032                         |0009: invoke-static {v0, v1, v2, v3, v4}, LA;.invokes:()V // method@000a
+000900: 7254 0a00 1032                         |000c: invoke-interface {v0, v1, v2, v3, v4}, LA;.invokes:()V // method@000a
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  source_file_idx   : -1 (unknown)
+
+Opened 'all-dex-files.jar:classes2.dex', DEX version '035'
+DEX file header:
+magic               : 'dex\n035\0'
+checksum            : 3ce07f0d
+signature           : 6aca...3cae
+file_size           : 35384
+header_size         : 112
+link_size           : 0
+link_off            : 0 (0x000000)
+string_ids_size     : 323
+string_ids_off      : 112 (0x000070)
+type_ids_size       : 58
+type_ids_off        : 1404 (0x00057c)
+proto_ids_size      : 88
+proto_ids_off       : 1636 (0x000664)
+field_ids_size      : 108
+field_ids_off       : 2692 (0x000a84)
+method_ids_size     : 177
+method_ids_off      : 3556 (0x000de4)
+class_defs_size     : 9
+class_defs_off      : 4972 (0x00136c)
+data_size           : 30124
+data_off            : 5260 (0x00148c)
+
+Class #0 header:
+class_idx           : 30
+access_flags        : 1 (0x0001)
+superclass_idx      : 4
+interfaces_off      : 0 (0x000000)
+source_file_idx     : -1
+annotations_off     : 0 (0x000000)
+class_data_off      : 34554 (0x0086fa)
+static_fields_size  : 0
+instance_fields_size: 1
+direct_methods_size : 2
+virtual_methods_size: 8
+
+Class #0            -
+  Class descriptor  : 'Lcom/google/android/checkers/Checkers;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'Landroid/app/Activity;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+    #0              : (in Lcom/google/android/checkers/Checkers;)
+      name          : 'a'
+      type          : 'Lcom/google/android/checkers/CheckersView;'
+      access        : 0x0002 (PRIVATE)
+  Direct methods    -
+    #0              : (in Lcom/google/android/checkers/Checkers;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 62
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+00148c:                                        |[00148c] com.google.android.checkers.Checkers.<init>:()V
+00149c: 7010 0000 0000                         |0000: invoke-direct {v0}, Landroid/app/Activity;.<init>:()V // method@0000
+0014a2: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #1              : (in Lcom/google/android/checkers/Checkers;)
+      name          : 'a'
+      type          : '(Z)V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 63
+      code          -
+      registers     : 4
+      ins           : 2
+      outs          : 2
+      insns size    : 33 16-bit code units
+0014a4:                                        |[0014a4] com.google.android.checkers.Checkers.a:(Z)V
+0014b4: 6e10 4100 0200                         |0000: invoke-virtual {v2}, Lcom/google/android/checkers/Checkers;.getWindow:()Landroid/view/Window; // method@0041
+0014ba: 0c00                                   |0003: move-result-object v0
+0014bc: 3803 1200                              |0004: if-eqz v3, 0016 // +0012
+0014c0: 1301 8004                              |0006: const/16 v1, #int 1152 // #480
+0014c4: 6e20 3a00 1000                         |0008: invoke-virtual {v0, v1}, Landroid/view/Window;.addFlags:(I)V // method@003a
+0014ca: 1301 0008                              |000b: const/16 v1, #int 2048 // #800
+0014ce: 6e20 3b00 1000                         |000d: invoke-virtual {v0, v1}, Landroid/view/Window;.clearFlags:(I)V // method@003b
+0014d4: 5420 0100                              |0010: iget-object v0, v2, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0014d8: 6e10 6f00 0000                         |0012: invoke-virtual {v0}, Lcom/google/android/checkers/CheckersView;.requestLayout:()V // method@006f
+0014de: 0e00                                   |0015: return-void
+0014e0: 1301 8008                              |0016: const/16 v1, #int 2176 // #880
+0014e4: 6e20 3a00 1000                         |0018: invoke-virtual {v0, v1}, Landroid/view/Window;.addFlags:(I)V // method@003a
+0014ea: 1301 0004                              |001b: const/16 v1, #int 1024 // #400
+0014ee: 6e20 3b00 1000                         |001d: invoke-virtual {v0, v1}, Landroid/view/Window;.clearFlags:(I)V // method@003b
+0014f4: 28f0                                   |0020: goto 0010 // -0010
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+    #0              : (in Lcom/google/android/checkers/Checkers;)
+      name          : 'onConfigurationChanged'
+      type          : '(Landroid/content/res/Configuration;)V'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 66
+      code          -
+      registers     : 2
+      ins           : 2
+      outs          : 2
+      insns size    : 4 16-bit code units
+0014f8:                                        |[0014f8] com.google.android.checkers.Checkers.onConfigurationChanged:(Landroid/content/res/Configuration;)V
+001508: 6f20 0100 1000                         |0000: invoke-super {v0, v1}, Landroid/app/Activity;.onConfigurationChanged:(Landroid/content/res/Configuration;)V // method@0001
+00150e: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #1              : (in Lcom/google/android/checkers/Checkers;)
+      name          : 'onCreate'
+      type          : '(Landroid/os/Bundle;)V'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 67
+      code          -
+      registers     : 8
+      ins           : 2
+      outs          : 3
+      insns size    : 59 16-bit code units
+001510:                                        |[001510] com.google.android.checkers.Checkers.onCreate:(Landroid/os/Bundle;)V
+001520: 1215                                   |0000: const/4 v5, #int 1 // #1
+001522: 1201                                   |0001: const/4 v1, #int 0 // #0
+001524: 6f20 0200 7600                         |0002: invoke-super {v6, v7}, Landroid/app/Activity;.onCreate:(Landroid/os/Bundle;)V // method@0002
+00152a: 6e20 4a00 5600                         |0005: invoke-virtual {v6, v5}, Lcom/google/android/checkers/Checkers;.requestWindowFeature:(I)Z // method@004a
+001530: 2200 1f00                              |0008: new-instance v0, Lcom/google/android/checkers/CheckersView; // type@001f
+001534: 6e20 4000 1600                         |000a: invoke-virtual {v6, v1}, Lcom/google/android/checkers/Checkers;.getPreferences:(I)Landroid/content/SharedPreferences; // method@0040
+00153a: 0c02                                   |000d: move-result-object v2
+00153c: 7030 4d00 6002                         |000e: invoke-direct {v0, v6, v2}, Lcom/google/android/checkers/CheckersView;.<init>:(Landroid/content/Context;Landroid/content/SharedPreferences;)V // method@004d
+001542: 5b60 0100                              |0011: iput-object v0, v6, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001546: 1a03 b500                              |0013: const-string v3, "by Aart J.C. Bik" // string@00b5
+00154a: 0110                                   |0015: move v0, v1
+00154c: 0112                                   |0016: move v2, v1
+00154e: 6e10 a400 0300                         |0017: invoke-virtual {v3}, Ljava/lang/String;.length:()I // method@00a4
+001554: 0a04                                   |001a: move-result v4
+001556: 3440 1800                              |001b: if-lt v0, v4, 0033 // +0018
+00155a: 1300 c204                              |001d: const/16 v0, #int 1218 // #4c2
+00155e: 3202 0500                              |001f: if-eq v2, v0, 0024 // +0005
+001562: 7110 ac00 0500                         |0021: invoke-static {v5}, Ljava/lang/System;.exit:(I)V // method@00ac
+001568: 5460 0100                              |0024: iget-object v0, v6, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+00156c: 6e20 4b00 0600                         |0026: invoke-virtual {v6, v0}, Lcom/google/android/checkers/Checkers;.setContentView:(Landroid/view/View;)V // method@004b
+001572: 5460 0100                              |0029: iget-object v0, v6, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001576: 6e20 6500 1000                         |002b: invoke-virtual {v0, v1}, Lcom/google/android/checkers/CheckersView;.d:(Z)Z // method@0065
+00157c: 0a00                                   |002e: move-result v0
+00157e: 7020 3f00 0600                         |002f: invoke-direct {v6, v0}, Lcom/google/android/checkers/Checkers;.a:(Z)V // method@003f
+001584: 0e00                                   |0032: return-void
+001586: 6e20 a300 0300                         |0033: invoke-virtual {v3, v0}, Ljava/lang/String;.charAt:(I)C // method@00a3
+00158c: 0a04                                   |0036: move-result v4
+00158e: b042                                   |0037: add-int/2addr v2, v4
+001590: d800 0001                              |0038: add-int/lit8 v0, v0, #int 1 // #01
+001594: 28dd                                   |003a: goto 0017 // -0023
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #2              : (in Lcom/google/android/checkers/Checkers;)
+      name          : 'onCreateOptionsMenu'
+      type          : '(Landroid/view/Menu;)Z'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 68
+      code          -
+      registers     : 11
+      ins           : 2
+      outs          : 5
+      insns size    : 216 16-bit code units
+001598:                                        |[001598] com.google.android.checkers.Checkers.onCreateOptionsMenu:(Landroid/view/Menu;)Z
+0015a8: 1248                                   |0000: const/4 v8, #int 4 // #4
+0015aa: 1237                                   |0001: const/4 v7, #int 3 // #3
+0015ac: 1226                                   |0002: const/4 v6, #int 2 // #2
+0015ae: 1205                                   |0003: const/4 v5, #int 0 // #0
+0015b0: 1214                                   |0004: const/4 v4, #int 1 // #1
+0015b2: 6f20 0300 a900                         |0005: invoke-super {v9, v10}, Landroid/app/Activity;.onCreateOptionsMenu:(Landroid/view/Menu;)Z // method@0003
+0015b8: 1a00 7400                              |0008: const-string v0, "New Game" // string@0074
+0015bc: 7250 2b00 5a55                         |000a: invoke-interface {v10, v5, v5, v5, v0}, Landroid/view/Menu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@002b
+0015c2: 1a00 8200                              |000d: const-string v0, "Undo" // string@0082
+0015c6: 7250 2b00 5a44                         |000f: invoke-interface {v10, v5, v4, v4, v0}, Landroid/view/Menu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@002b
+0015cc: 1a00 8000                              |0012: const-string v0, "Switch Side" // string@0080
+0015d0: 7250 2b00 5a66                         |0014: invoke-interface {v10, v5, v6, v6, v0}, Landroid/view/Menu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@002b
+0015d6: 1a00 7800                              |0017: const-string v0, "Options" // string@0078
+0015da: 7250 2c00 5a77                         |0019: invoke-interface {v10, v5, v7, v7, v0}, Landroid/view/Menu;.addSubMenu:(IIILjava/lang/CharSequence;)Landroid/view/SubMenu; // method@002c
+0015e0: 0c00                                   |001c: move-result-object v0
+0015e2: 1a01 7100                              |001d: const-string v1, "Move Coach" // string@0071
+0015e6: 7251 3400 4055                         |001f: invoke-interface {v0, v4, v5, v5, v1}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+0015ec: 0c01                                   |0022: move-result-object v1
+0015ee: 7220 2f00 4100                         |0023: invoke-interface {v1, v4}, Landroid/view/MenuItem;.setCheckable:(Z)Landroid/view/MenuItem; // method@002f
+0015f4: 0c01                                   |0026: move-result-object v1
+0015f6: 5492 0100                              |0027: iget-object v2, v9, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0015fa: 6e20 5a00 5200                         |0029: invoke-virtual {v2, v5}, Lcom/google/android/checkers/CheckersView;.a:(Z)Z // method@005a
+001600: 0a02                                   |002c: move-result v2
+001602: 7220 3000 2100                         |002d: invoke-interface {v1, v2}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+001608: 1a01 7700                              |0030: const-string v1, "Optional Jumps" // string@0077
+00160c: 7251 3400 4044                         |0032: invoke-interface {v0, v4, v4, v4, v1}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+001612: 0c01                                   |0035: move-result-object v1
+001614: 7220 2f00 4100                         |0036: invoke-interface {v1, v4}, Landroid/view/MenuItem;.setCheckable:(Z)Landroid/view/MenuItem; // method@002f
+00161a: 0c01                                   |0039: move-result-object v1
+00161c: 5492 0100                              |003a: iget-object v2, v9, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001620: 6e20 6000 5200                         |003c: invoke-virtual {v2, v5}, Lcom/google/android/checkers/CheckersView;.b:(Z)Z // method@0060
+001626: 0a02                                   |003f: move-result v2
+001628: 7220 3000 2100                         |0040: invoke-interface {v1, v2}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+00162e: 1a01 9800                              |0043: const-string v1, "View from White" // string@0098
+001632: 7251 3400 4066                         |0045: invoke-interface {v0, v4, v6, v6, v1}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+001638: 0c01                                   |0048: move-result-object v1
+00163a: 7220 2f00 4100                         |0049: invoke-interface {v1, v4}, Landroid/view/MenuItem;.setCheckable:(Z)Landroid/view/MenuItem; // method@002f
+001640: 0c01                                   |004c: move-result-object v1
+001642: 5492 0100                              |004d: iget-object v2, v9, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001646: 6e20 6300 5200                         |004f: invoke-virtual {v2, v5}, Lcom/google/android/checkers/CheckersView;.c:(Z)Z // method@0063
+00164c: 0a02                                   |0052: move-result v2
+00164e: 7220 3000 2100                         |0053: invoke-interface {v1, v2}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+001654: 1a01 1800                              |0056: const-string v1, "Full Screen" // string@0018
+001658: 7251 3400 4077                         |0058: invoke-interface {v0, v4, v7, v7, v1}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+00165e: 0c01                                   |005b: move-result-object v1
+001660: 7220 2f00 4100                         |005c: invoke-interface {v1, v4}, Landroid/view/MenuItem;.setCheckable:(Z)Landroid/view/MenuItem; // method@002f
+001666: 0c01                                   |005f: move-result-object v1
+001668: 5492 0100                              |0060: iget-object v2, v9, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+00166c: 6e20 6500 5200                         |0062: invoke-virtual {v2, v5}, Lcom/google/android/checkers/CheckersView;.d:(Z)Z // method@0065
+001672: 0a02                                   |0065: move-result v2
+001674: 7220 3000 2100                         |0066: invoke-interface {v1, v2}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+00167a: 1a01 7e00                              |0069: const-string v1, "Start Screen" // string@007e
+00167e: 7251 3400 4088                         |006b: invoke-interface {v0, v4, v8, v8, v1}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+001684: 0c01                                   |006e: move-result-object v1
+001686: 7220 2f00 4100                         |006f: invoke-interface {v1, v4}, Landroid/view/MenuItem;.setCheckable:(Z)Landroid/view/MenuItem; // method@002f
+00168c: 0c01                                   |0072: move-result-object v1
+00168e: 5492 0100                              |0073: iget-object v2, v9, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001692: 6e20 6800 5200                         |0075: invoke-virtual {v2, v5}, Lcom/google/android/checkers/CheckersView;.e:(Z)Z // method@0068
+001698: 0a02                                   |0078: move-result v2
+00169a: 7220 3000 2100                         |0079: invoke-interface {v1, v2}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+0016a0: 1251                                   |007c: const/4 v1, #int 5 // #5
+0016a2: 1252                                   |007d: const/4 v2, #int 5 // #5
+0016a4: 1a03 0d00                              |007e: const-string v3, "Board Color" // string@000d
+0016a8: 7253 3400 4021                         |0080: invoke-interface {v0, v4, v1, v2, v3}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+0016ae: 1a00 5800                              |0083: const-string v0, "Level" // string@0058
+0016b2: 7250 2c00 5a88                         |0085: invoke-interface {v10, v5, v8, v8, v0}, Landroid/view/Menu;.addSubMenu:(IIILjava/lang/CharSequence;)Landroid/view/SubMenu; // method@002c
+0016b8: 0c00                                   |0088: move-result-object v0
+0016ba: 1a01 1700                              |0089: const-string v1, "Free Play" // string@0017
+0016be: 7251 3400 6055                         |008b: invoke-interface {v0, v6, v5, v5, v1}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+0016c4: 1a01 7b00                              |008e: const-string v1, "Random (0s)" // string@007b
+0016c8: 7251 3400 6044                         |0090: invoke-interface {v0, v6, v4, v4, v1}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+0016ce: 1a01 5900                              |0093: const-string v1, "Level 1 (fast)" // string@0059
+0016d2: 7251 3400 6066                         |0095: invoke-interface {v0, v6, v6, v6, v1}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+0016d8: 1a01 5a00                              |0098: const-string v1, "Level 2 (1s)" // string@005a
+0016dc: 7251 3400 6077                         |009a: invoke-interface {v0, v6, v7, v7, v1}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+0016e2: 1a01 5b00                              |009d: const-string v1, "Level 3 (5s)" // string@005b
+0016e6: 7251 3400 6088                         |009f: invoke-interface {v0, v6, v8, v8, v1}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+0016ec: 1251                                   |00a2: const/4 v1, #int 5 // #5
+0016ee: 1252                                   |00a3: const/4 v2, #int 5 // #5
+0016f0: 1a03 5c00                              |00a4: const-string v3, "Level 4 (10s)" // string@005c
+0016f4: 7253 3400 6021                         |00a6: invoke-interface {v0, v6, v1, v2, v3}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+0016fa: 1261                                   |00a9: const/4 v1, #int 6 // #6
+0016fc: 1262                                   |00aa: const/4 v2, #int 6 // #6
+0016fe: 1a03 5d00                              |00ab: const-string v3, "Level 5 (15s)" // string@005d
+001702: 7253 3400 6021                         |00ad: invoke-interface {v0, v6, v1, v2, v3}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+001708: 1271                                   |00b0: const/4 v1, #int 7 // #7
+00170a: 1272                                   |00b1: const/4 v2, #int 7 // #7
+00170c: 1a03 5e00                              |00b2: const-string v3, "Level 6 (30s)" // string@005e
+001710: 7253 3400 6021                         |00b4: invoke-interface {v0, v6, v1, v2, v3}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+001716: 1301 0800                              |00b7: const/16 v1, #int 8 // #8
+00171a: 1302 0800                              |00b9: const/16 v2, #int 8 // #8
+00171e: 1a03 5f00                              |00bb: const-string v3, "Level 7 (60s)" // string@005f
+001722: 7253 3400 6021                         |00bd: invoke-interface {v0, v6, v1, v2, v3}, Landroid/view/SubMenu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@0034
+001728: 7240 3600 6044                         |00c0: invoke-interface {v0, v6, v4, v4}, Landroid/view/SubMenu;.setGroupCheckable:(IZZ)V // method@0036
+00172e: 5491 0100                              |00c3: iget-object v1, v9, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001732: 6e10 6100 0100                         |00c5: invoke-virtual {v1}, Lcom/google/android/checkers/CheckersView;.c:()I // method@0061
+001738: 0a01                                   |00c8: move-result v1
+00173a: 7220 3500 1000                         |00c9: invoke-interface {v0, v1}, Landroid/view/SubMenu;.findItem:(I)Landroid/view/MenuItem; // method@0035
+001740: 0c00                                   |00cc: move-result-object v0
+001742: 7220 3000 4000                         |00cd: invoke-interface {v0, v4}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+001748: 1250                                   |00d0: const/4 v0, #int 5 // #5
+00174a: 1251                                   |00d1: const/4 v1, #int 5 // #5
+00174c: 1a02 9b00                              |00d2: const-string v2, "Website" // string@009b
+001750: 7252 2b00 5a10                         |00d4: invoke-interface {v10, v5, v0, v1, v2}, Landroid/view/Menu;.add:(IIILjava/lang/CharSequence;)Landroid/view/MenuItem; // method@002b
+001756: 0f04                                   |00d7: return v4
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #3              : (in Lcom/google/android/checkers/Checkers;)
+      name          : 'onKeyDown'
+      type          : '(ILandroid/view/KeyEvent;)Z'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 69
+      code          -
+      registers     : 8
+      ins           : 3
+      outs          : 3
+      insns size    : 58 16-bit code units
+001758:                                        |[001758] com.google.android.checkers.Checkers.onKeyDown:(ILandroid/view/KeyEvent;)Z
+001768: 1504 803f                              |0000: const/high16 v4, #int 1065353216 // #3f80
+00176c: 1503 80bf                              |0002: const/high16 v3, #int -1082130432 // #bf80
+001770: 1202                                   |0004: const/4 v2, #int 0 // #0
+001772: 1210                                   |0005: const/4 v0, #int 1 // #1
+001774: 2b06 2600 0000                         |0006: packed-switch v6, 0000002c // +00000026
+00177a: 6f30 0400 6507                         |0009: invoke-super {v5, v6, v7}, Landroid/app/Activity;.onKeyDown:(ILandroid/view/KeyEvent;)Z // method@0004
+001780: 0a00                                   |000c: move-result v0
+001782: 0f00                                   |000d: return v0
+001784: 5451 0100                              |000e: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001788: 6e10 5d00 0100                         |0010: invoke-virtual {v1}, Lcom/google/android/checkers/CheckersView;.b:()V // method@005d
+00178e: 28fa                                   |0013: goto 000d // -0006
+001790: 5451 0100                              |0014: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001794: 6e30 4f00 3102                         |0016: invoke-virtual {v1, v3, v2}, Lcom/google/android/checkers/CheckersView;.a:(FF)V // method@004f
+00179a: 28f4                                   |0019: goto 000d // -000c
+00179c: 5451 0100                              |001a: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0017a0: 6e30 4f00 4102                         |001c: invoke-virtual {v1, v4, v2}, Lcom/google/android/checkers/CheckersView;.a:(FF)V // method@004f
+0017a6: 28ee                                   |001f: goto 000d // -0012
+0017a8: 5451 0100                              |0020: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0017ac: 6e30 4f00 2103                         |0022: invoke-virtual {v1, v2, v3}, Lcom/google/android/checkers/CheckersView;.a:(FF)V // method@004f
+0017b2: 28e8                                   |0025: goto 000d // -0018
+0017b4: 5451 0100                              |0026: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0017b8: 6e30 4f00 2104                         |0028: invoke-virtual {v1, v2, v4}, Lcom/google/android/checkers/CheckersView;.a:(FF)V // method@004f
+0017be: 28e2                                   |002b: goto 000d // -001e
+0017c0: 0001 0500 1300 0000 1a00 0000 2000 ... |002c: packed-switch-data (14 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #4              : (in Lcom/google/android/checkers/Checkers;)
+      name          : 'onOptionsItemSelected'
+      type          : '(Landroid/view/MenuItem;)Z'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 70
+      code          -
+      registers     : 7
+      ins           : 2
+      outs          : 3
+      insns size    : 158 16-bit code units
+0017dc:                                        |[0017dc] com.google.android.checkers.Checkers.onOptionsItemSelected:(Landroid/view/MenuItem;)Z
+0017ec: 1254                                   |0000: const/4 v4, #int 5 // #5
+0017ee: 1223                                   |0001: const/4 v3, #int 2 // #2
+0017f0: 1210                                   |0002: const/4 v0, #int 1 // #1
+0017f2: 7210 2e00 0600                         |0003: invoke-interface {v6}, Landroid/view/MenuItem;.getItemId:()I // method@002e
+0017f8: 0a01                                   |0006: move-result v1
+0017fa: 7210 2d00 0600                         |0007: invoke-interface {v6}, Landroid/view/MenuItem;.getGroupId:()I // method@002d
+001800: 0a02                                   |000a: move-result v2
+001802: 2b02 8900 0000                         |000b: packed-switch v2, 00000094 // +00000089
+001808: 6f20 0500 6500                         |000e: invoke-super {v5, v6}, Landroid/app/Activity;.onOptionsItemSelected:(Landroid/view/MenuItem;)Z // method@0005
+00180e: 0a00                                   |0011: move-result v0
+001810: 0f00                                   |0012: return v0
+001812: 3901 0900                              |0013: if-nez v1, 001c // +0009
+001816: 5451 0100                              |0015: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+00181a: 12d2                                   |0017: const/4 v2, #int -3 // #fd
+00181c: 6e20 5700 2100                         |0018: invoke-virtual {v1, v2}, Lcom/google/android/checkers/CheckersView;.a:(I)Z // method@0057
+001822: 28f7                                   |001b: goto 0012 // -0009
+001824: 3301 0900                              |001c: if-ne v1, v0, 0025 // +0009
+001828: 5451 0100                              |001e: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+00182c: 12e2                                   |0020: const/4 v2, #int -2 // #fe
+00182e: 6e20 5700 2100                         |0021: invoke-virtual {v1, v2}, Lcom/google/android/checkers/CheckersView;.a:(I)Z // method@0057
+001834: 28ee                                   |0024: goto 0012 // -0012
+001836: 3331 0900                              |0025: if-ne v1, v3, 002e // +0009
+00183a: 5451 0100                              |0027: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+00183e: 12c2                                   |0029: const/4 v2, #int -4 // #fc
+001840: 6e20 5700 2100                         |002a: invoke-virtual {v1, v2}, Lcom/google/android/checkers/CheckersView;.a:(I)Z // method@0057
+001846: 28e5                                   |002d: goto 0012 // -001b
+001848: 3341 e0ff                              |002e: if-ne v1, v4, 000e // -0020
+00184c: 1a01 e300                              |0030: const-string v1, "http://www.aartbik.com/MISC/android.html" // string@00e3
+001850: 7110 2900 0100                         |0032: invoke-static {v1}, Landroid/net/Uri;.parse:(Ljava/lang/String;)Landroid/net/Uri; // method@0029
+001856: 0c01                                   |0035: move-result-object v1
+001858: 2202 0a00                              |0036: new-instance v2, Landroid/content/Intent; // type@000a
+00185c: 1a03 af00                              |0038: const-string v3, "android.intent.action.VIEW" // string@00af
+001860: 7030 1200 3201                         |003a: invoke-direct {v2, v3, v1}, Landroid/content/Intent;.<init>:(Ljava/lang/String;Landroid/net/Uri;)V // method@0012
+001866: 6e20 4c00 2500                         |003d: invoke-virtual {v5, v2}, Lcom/google/android/checkers/Checkers;.startActivity:(Landroid/content/Intent;)V // method@004c
+00186c: 28d2                                   |0040: goto 0012 // -002e
+00186e: 3901 0c00                              |0041: if-nez v1, 004d // +000c
+001872: 5451 0100                              |0043: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001876: 6e20 5a00 0100                         |0045: invoke-virtual {v1, v0}, Lcom/google/android/checkers/CheckersView;.a:(Z)Z // method@005a
+00187c: 0a01                                   |0048: move-result v1
+00187e: 7220 3000 1600                         |0049: invoke-interface {v6, v1}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+001884: 28c6                                   |004c: goto 0012 // -003a
+001886: 3301 0c00                              |004d: if-ne v1, v0, 0059 // +000c
+00188a: 5451 0100                              |004f: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+00188e: 6e20 6000 0100                         |0051: invoke-virtual {v1, v0}, Lcom/google/android/checkers/CheckersView;.b:(Z)Z // method@0060
+001894: 0a01                                   |0054: move-result v1
+001896: 7220 3000 1600                         |0055: invoke-interface {v6, v1}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+00189c: 28ba                                   |0058: goto 0012 // -0046
+00189e: 3331 0c00                              |0059: if-ne v1, v3, 0065 // +000c
+0018a2: 5451 0100                              |005b: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0018a6: 6e20 6300 0100                         |005d: invoke-virtual {v1, v0}, Lcom/google/android/checkers/CheckersView;.c:(Z)Z // method@0063
+0018ac: 0a01                                   |0060: move-result v1
+0018ae: 7220 3000 1600                         |0061: invoke-interface {v6, v1}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+0018b4: 28ae                                   |0064: goto 0012 // -0052
+0018b6: 1232                                   |0065: const/4 v2, #int 3 // #3
+0018b8: 3321 0f00                              |0066: if-ne v1, v2, 0075 // +000f
+0018bc: 5451 0100                              |0068: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0018c0: 6e20 6500 0100                         |006a: invoke-virtual {v1, v0}, Lcom/google/android/checkers/CheckersView;.d:(Z)Z // method@0065
+0018c6: 0a01                                   |006d: move-result v1
+0018c8: 7220 3000 1600                         |006e: invoke-interface {v6, v1}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+0018ce: 7020 3f00 1500                         |0071: invoke-direct {v5, v1}, Lcom/google/android/checkers/Checkers;.a:(Z)V // method@003f
+0018d4: 289e                                   |0074: goto 0012 // -0062
+0018d6: 1242                                   |0075: const/4 v2, #int 4 // #4
+0018d8: 3321 0c00                              |0076: if-ne v1, v2, 0082 // +000c
+0018dc: 5451 0100                              |0078: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0018e0: 6e20 6800 0100                         |007a: invoke-virtual {v1, v0}, Lcom/google/android/checkers/CheckersView;.e:(Z)Z // method@0068
+0018e6: 0a01                                   |007d: move-result v1
+0018e8: 7220 3000 1600                         |007e: invoke-interface {v6, v1}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+0018ee: 2891                                   |0081: goto 0012 // -006f
+0018f0: 3341 8cff                              |0082: if-ne v1, v4, 000e // -0074
+0018f4: 5451 0100                              |0084: iget-object v1, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0018f8: 6e10 4e00 0100                         |0086: invoke-virtual {v1}, Lcom/google/android/checkers/CheckersView;.a:()V // method@004e
+0018fe: 2889                                   |0089: goto 0012 // -0077
+001900: 5452 0100                              |008a: iget-object v2, v5, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001904: 6e20 7000 1200                         |008c: invoke-virtual {v2, v1}, Lcom/google/android/checkers/CheckersView;.setLevel:(I)V // method@0070
+00190a: 7220 3000 0600                         |008f: invoke-interface {v6, v0}, Landroid/view/MenuItem;.setChecked:(Z)Landroid/view/MenuItem; // method@0030
+001910: 2880                                   |0092: goto 0012 // -0080
+001912: 0000                                   |0093: nop // spacer
+001914: 0001 0300 0000 0000 0800 0000 3600 ... |0094: packed-switch-data (10 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #5              : (in Lcom/google/android/checkers/Checkers;)
+      name          : 'onPause'
+      type          : '()V'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 71
+      code          -
+      registers     : 3
+      ins           : 1
+      outs          : 2
+      insns size    : 21 16-bit code units
+001928:                                        |[001928] com.google.android.checkers.Checkers.onPause:()V
+001938: 6f10 0600 0200                         |0000: invoke-super {v2}, Landroid/app/Activity;.onPause:()V // method@0006
+00193e: 1200                                   |0003: const/4 v0, #int 0 // #0
+001940: 6e20 4000 0200                         |0004: invoke-virtual {v2, v0}, Lcom/google/android/checkers/Checkers;.getPreferences:(I)Landroid/content/SharedPreferences; // method@0040
+001946: 0c00                                   |0007: move-result-object v0
+001948: 7210 1700 0000                         |0008: invoke-interface {v0}, Landroid/content/SharedPreferences;.edit:()Landroid/content/SharedPreferences$Editor; // method@0017
+00194e: 0c00                                   |000b: move-result-object v0
+001950: 5421 0100                              |000c: iget-object v1, v2, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+001954: 6e20 5100 0100                         |000e: invoke-virtual {v1, v0}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/content/SharedPreferences$Editor;)V // method@0051
+00195a: 7210 1400 0000                         |0011: invoke-interface {v0}, Landroid/content/SharedPreferences$Editor;.commit:()Z // method@0014
+001960: 0e00                                   |0014: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #6              : (in Lcom/google/android/checkers/Checkers;)
+      name          : 'onStop'
+      type          : '()V'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 72
+      code          -
+      registers     : 2
+      ins           : 1
+      outs          : 1
+      insns size    : 8 16-bit code units
+001964:                                        |[001964] com.google.android.checkers.Checkers.onStop:()V
+001974: 6f10 0700 0100                         |0000: invoke-super {v1}, Landroid/app/Activity;.onStop:()V // method@0007
+00197a: 1200                                   |0003: const/4 v0, #int 0 // #0
+00197c: 7110 ac00 0000                         |0004: invoke-static {v0}, Ljava/lang/System;.exit:(I)V // method@00ac
+001982: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #7              : (in Lcom/google/android/checkers/Checkers;)
+      name          : 'onTrackballEvent'
+      type          : '(Landroid/view/MotionEvent;)Z'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 73
+      code          -
+      registers     : 6
+      ins           : 2
+      outs          : 3
+      insns size    : 44 16-bit code units
+001984:                                        |[001984] com.google.android.checkers.Checkers.onTrackballEvent:(Landroid/view/MotionEvent;)Z
+001994: 1210                                   |0000: const/4 v0, #int 1 // #1
+001996: 6e10 3100 0500                         |0001: invoke-virtual {v5}, Landroid/view/MotionEvent;.getAction:()I // method@0031
+00199c: 0a01                                   |0004: move-result v1
+00199e: 2b01 1d00 0000                         |0005: packed-switch v1, 00000022 // +0000001d
+0019a4: 6f20 0800 5400                         |0008: invoke-super {v4, v5}, Landroid/app/Activity;.onTrackballEvent:(Landroid/view/MotionEvent;)Z // method@0008
+0019aa: 0a00                                   |000b: move-result v0
+0019ac: 0f00                                   |000c: return v0
+0019ae: 5441 0100                              |000d: iget-object v1, v4, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0019b2: 6e10 5d00 0100                         |000f: invoke-virtual {v1}, Lcom/google/android/checkers/CheckersView;.b:()V // method@005d
+0019b8: 28fa                                   |0012: goto 000c // -0006
+0019ba: 5441 0100                              |0013: iget-object v1, v4, Lcom/google/android/checkers/Checkers;.a:Lcom/google/android/checkers/CheckersView; // field@0001
+0019be: 6e10 3200 0500                         |0015: invoke-virtual {v5}, Landroid/view/MotionEvent;.getX:()F // method@0032
+0019c4: 0a02                                   |0018: move-result v2
+0019c6: 6e10 3300 0500                         |0019: invoke-virtual {v5}, Landroid/view/MotionEvent;.getY:()F // method@0033
+0019cc: 0a03                                   |001c: move-result v3
+0019ce: 6e30 4f00 2103                         |001d: invoke-virtual {v1, v2, v3}, Lcom/google/android/checkers/CheckersView;.a:(FF)V // method@004f
+0019d4: 28ec                                   |0020: goto 000c // -0014
+0019d6: 0000                                   |0021: nop // spacer
+0019d8: 0001 0300 0000 0000 0800 0000 0300 ... |0022: packed-switch-data (10 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  source_file_idx   : -1 (unknown)
+
+Class #1 header:
+class_idx           : 31
+access_flags        : 1 (0x0001)
+superclass_idx      : 27
+interfaces_off      : 0 (0x000000)
+source_file_idx     : -1
+annotations_off     : 0 (0x000000)
+class_data_off      : 34602 (0x00872a)
+static_fields_size  : 0
+instance_fields_size: 43
+direct_methods_size : 15
+virtual_methods_size: 16
+
+Class #1            -
+  Class descriptor  : 'Lcom/google/android/checkers/CheckersView;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'Landroid/view/View;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+    #0              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'A'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #1              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'B'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #2              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'C'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #3              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'D'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #4              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'E'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #5              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'F'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #6              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'G'
+      type          : '[I'
+      access        : 0x0002 (PRIVATE)
+    #7              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'H'
+      type          : '[I'
+      access        : 0x0002 (PRIVATE)
+    #8              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'I'
+      type          : '[I'
+      access        : 0x0002 (PRIVATE)
+    #9              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'J'
+      type          : '[I'
+      access        : 0x0002 (PRIVATE)
+    #10              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'K'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #11              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'L'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #12              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'M'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #13              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'N'
+      type          : 'Ljava/lang/String;'
+      access        : 0x0002 (PRIVATE)
+    #14              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'O'
+      type          : 'F'
+      access        : 0x0002 (PRIVATE)
+    #15              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'P'
+      type          : 'F'
+      access        : 0x0002 (PRIVATE)
+    #16              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'Q'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #17              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : 'Landroid/content/Context;'
+      access        : 0x0002 (PRIVATE)
+    #18              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'b'
+      type          : 'Landroid/graphics/Paint;'
+      access        : 0x0002 (PRIVATE)
+    #19              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'c'
+      type          : 'Landroid/graphics/Paint;'
+      access        : 0x0002 (PRIVATE)
+    #20              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'd'
+      type          : 'Landroid/graphics/Paint;'
+      access        : 0x0002 (PRIVATE)
+    #21              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'e'
+      type          : 'Landroid/graphics/Paint;'
+      access        : 0x0002 (PRIVATE)
+    #22              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'f'
+      type          : 'Landroid/graphics/Paint;'
+      access        : 0x0002 (PRIVATE)
+    #23              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'g'
+      type          : 'Landroid/graphics/Paint;'
+      access        : 0x0002 (PRIVATE)
+    #24              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'h'
+      type          : 'Landroid/graphics/Paint;'
+      access        : 0x0002 (PRIVATE)
+    #25              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'i'
+      type          : 'Landroid/graphics/Paint;'
+      access        : 0x0002 (PRIVATE)
+    #26              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'j'
+      type          : 'Landroid/graphics/Paint;'
+      access        : 0x0002 (PRIVATE)
+    #27              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'k'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #28              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'l'
+      type          : 'F'
+      access        : 0x0002 (PRIVATE)
+    #29              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'm'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #30              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'n'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #31              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'o'
+      type          : 'Landroid/graphics/drawable/Drawable;'
+      access        : 0x0002 (PRIVATE)
+    #32              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'p'
+      type          : 'Lcom/google/android/checkers/a;'
+      access        : 0x0002 (PRIVATE)
+    #33              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'q'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #34              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'r'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #35              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 's'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #36              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 't'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #37              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'u'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #38              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'v'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #39              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'w'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #40              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'x'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #41              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'y'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #42              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'z'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+  Direct methods    -
+    #0              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : '<init>'
+      type          : '(Landroid/content/Context;Landroid/content/SharedPreferences;)V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 77
+      code          -
+      registers     : 12
+      ins           : 3
+      outs          : 5
+      insns size    : 662 16-bit code units
+0019ec:                                        |[0019ec] com.google.android.checkers.CheckersView.<init>:(Landroid/content/Context;Landroid/content/SharedPreferences;)V
+0019fc: 1308 0800                              |0000: const/16 v8, #int 8 // #8
+001a00: 1217                                   |0002: const/4 v7, #int 1 // #1
+001a02: 1306 ff00                              |0003: const/16 v6, #int 255 // #ff
+001a06: 1205                                   |0005: const/4 v5, #int 0 // #0
+001a08: 1204                                   |0006: const/4 v4, #int 0 // #0
+001a0a: 7020 3700 a900                         |0007: invoke-direct {v9, v10}, Landroid/view/View;.<init>:(Landroid/content/Context;)V // method@0037
+001a10: 5b9a 1300                              |000a: iput-object v10, v9, Lcom/google/android/checkers/CheckersView;.a:Landroid/content/Context; // field@0013
+001a14: 2200 1100                              |000c: new-instance v0, Landroid/graphics/Paint; // type@0011
+001a18: 7010 2100 0000                         |000e: invoke-direct {v0}, Landroid/graphics/Paint;.<init>:()V // method@0021
+001a1e: 5b90 1400                              |0011: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+001a22: 5490 1400                              |0013: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+001a26: 6e20 2300 7000                         |0015: invoke-virtual {v0, v7}, Landroid/graphics/Paint;.setAntiAlias:(Z)V // method@0023
+001a2c: 5490 1400                              |0018: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+001a30: 6e54 2200 6044                         |001a: invoke-virtual {v0, v6, v4, v4, v4}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+001a36: 2200 1100                              |001d: new-instance v0, Landroid/graphics/Paint; // type@0011
+001a3a: 7010 2100 0000                         |001f: invoke-direct {v0}, Landroid/graphics/Paint;.<init>:()V // method@0021
+001a40: 5b90 1500                              |0022: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+001a44: 5490 1500                              |0024: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+001a48: 6e20 2300 7000                         |0026: invoke-virtual {v0, v7}, Landroid/graphics/Paint;.setAntiAlias:(Z)V // method@0023
+001a4e: 5490 1500                              |0029: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+001a52: 6e56 2200 6066                         |002b: invoke-virtual {v0, v6, v6, v6, v6}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+001a58: 2200 1100                              |002e: new-instance v0, Landroid/graphics/Paint; // type@0011
+001a5c: 7010 2100 0000                         |0030: invoke-direct {v0}, Landroid/graphics/Paint;.<init>:()V // method@0021
+001a62: 5b90 1600                              |0033: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.d:Landroid/graphics/Paint; // field@0016
+001a66: 5490 1600                              |0035: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.d:Landroid/graphics/Paint; // field@0016
+001a6a: 6e20 2300 7000                         |0037: invoke-virtual {v0, v7}, Landroid/graphics/Paint;.setAntiAlias:(Z)V // method@0023
+001a70: 5490 1600                              |003a: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.d:Landroid/graphics/Paint; // field@0016
+001a74: 1301 fb00                              |003c: const/16 v1, #int 251 // #fb
+001a78: 1302 d700                              |003e: const/16 v2, #int 215 // #d7
+001a7c: 1303 ae00                              |0040: const/16 v3, #int 174 // #ae
+001a80: 6e53 2200 6021                         |0042: invoke-virtual {v0, v6, v1, v2, v3}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+001a86: 2200 1100                              |0045: new-instance v0, Landroid/graphics/Paint; // type@0011
+001a8a: 7010 2100 0000                         |0047: invoke-direct {v0}, Landroid/graphics/Paint;.<init>:()V // method@0021
+001a90: 5b90 1700                              |004a: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.e:Landroid/graphics/Paint; // field@0017
+001a94: 5490 1700                              |004c: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.e:Landroid/graphics/Paint; // field@0017
+001a98: 6e20 2300 7000                         |004e: invoke-virtual {v0, v7}, Landroid/graphics/Paint;.setAntiAlias:(Z)V // method@0023
+001a9e: 5490 1700                              |0051: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.e:Landroid/graphics/Paint; // field@0017
+001aa2: 6e54 2200 6044                         |0053: invoke-virtual {v0, v6, v4, v4, v4}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+001aa8: 2200 1100                              |0056: new-instance v0, Landroid/graphics/Paint; // type@0011
+001aac: 7010 2100 0000                         |0058: invoke-direct {v0}, Landroid/graphics/Paint;.<init>:()V // method@0021
+001ab2: 5b90 1800                              |005b: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.f:Landroid/graphics/Paint; // field@0018
+001ab6: 5490 1800                              |005d: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.f:Landroid/graphics/Paint; // field@0018
+001aba: 6e20 2300 7000                         |005f: invoke-virtual {v0, v7}, Landroid/graphics/Paint;.setAntiAlias:(Z)V // method@0023
+001ac0: 5490 1800                              |0062: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.f:Landroid/graphics/Paint; // field@0018
+001ac4: 6e54 2200 6046                         |0064: invoke-virtual {v0, v6, v6, v4, v4}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+001aca: 2200 1100                              |0067: new-instance v0, Landroid/graphics/Paint; // type@0011
+001ace: 7010 2100 0000                         |0069: invoke-direct {v0}, Landroid/graphics/Paint;.<init>:()V // method@0021
+001ad4: 5b90 1900                              |006c: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.g:Landroid/graphics/Paint; // field@0019
+001ad8: 5490 1900                              |006e: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.g:Landroid/graphics/Paint; // field@0019
+001adc: 6e20 2300 7000                         |0070: invoke-virtual {v0, v7}, Landroid/graphics/Paint;.setAntiAlias:(Z)V // method@0023
+001ae2: 5490 1900                              |0073: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.g:Landroid/graphics/Paint; // field@0019
+001ae6: 1301 a500                              |0075: const/16 v1, #int 165 // #a5
+001aea: 6e54 2200 6016                         |0077: invoke-virtual {v0, v6, v6, v1, v4}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+001af0: 2200 1100                              |007a: new-instance v0, Landroid/graphics/Paint; // type@0011
+001af4: 7010 2100 0000                         |007c: invoke-direct {v0}, Landroid/graphics/Paint;.<init>:()V // method@0021
+001afa: 5b90 1a00                              |007f: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.h:Landroid/graphics/Paint; // field@001a
+001afe: 5490 1a00                              |0081: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.h:Landroid/graphics/Paint; // field@001a
+001b02: 6e20 2300 7000                         |0083: invoke-virtual {v0, v7}, Landroid/graphics/Paint;.setAntiAlias:(Z)V // method@0023
+001b08: 5490 1a00                              |0086: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.h:Landroid/graphics/Paint; // field@001a
+001b0c: 1301 c800                              |0088: const/16 v1, #int 200 // #c8
+001b10: 6e54 2200 6016                         |008a: invoke-virtual {v0, v6, v6, v1, v4}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+001b16: 5490 1a00                              |008d: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.h:Landroid/graphics/Paint; // field@001a
+001b1a: 1501 0040                              |008f: const/high16 v1, #int 1073741824 // #4000
+001b1e: 6e20 2400 1000                         |0091: invoke-virtual {v0, v1}, Landroid/graphics/Paint;.setStrokeWidth:(F)V // method@0024
+001b24: 2200 1100                              |0094: new-instance v0, Landroid/graphics/Paint; // type@0011
+001b28: 7010 2100 0000                         |0096: invoke-direct {v0}, Landroid/graphics/Paint;.<init>:()V // method@0021
+001b2e: 5b90 1b00                              |0099: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.i:Landroid/graphics/Paint; // field@001b
+001b32: 5490 1b00                              |009b: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.i:Landroid/graphics/Paint; // field@001b
+001b36: 6e20 2300 7000                         |009d: invoke-virtual {v0, v7}, Landroid/graphics/Paint;.setAntiAlias:(Z)V // method@0023
+001b3c: 5490 1b00                              |00a0: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.i:Landroid/graphics/Paint; // field@001b
+001b40: 6e54 2200 6064                         |00a2: invoke-virtual {v0, v6, v4, v6, v4}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+001b46: 2200 1100                              |00a5: new-instance v0, Landroid/graphics/Paint; // type@0011
+001b4a: 7010 2100 0000                         |00a7: invoke-direct {v0}, Landroid/graphics/Paint;.<init>:()V // method@0021
+001b50: 5b90 1c00                              |00aa: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.j:Landroid/graphics/Paint; // field@001c
+001b54: 5490 1c00                              |00ac: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.j:Landroid/graphics/Paint; // field@001c
+001b58: 6e20 2300 7000                         |00ae: invoke-virtual {v0, v7}, Landroid/graphics/Paint;.setAntiAlias:(Z)V // method@0023
+001b5e: 5490 1c00                              |00b1: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.j:Landroid/graphics/Paint; // field@001c
+001b62: 6e54 2200 6044                         |00b3: invoke-virtual {v0, v6, v4, v4, v4}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+001b68: 5490 1c00                              |00b6: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.j:Landroid/graphics/Paint; // field@001c
+001b6c: 6201 0000                              |00b8: sget-object v1, Landroid/graphics/Paint$Style;.STROKE:Landroid/graphics/Paint$Style; // field@0000
+001b70: 6e20 2500 1000                         |00ba: invoke-virtual {v0, v1}, Landroid/graphics/Paint;.setStyle:(Landroid/graphics/Paint$Style;)V // method@0025
+001b76: 5490 1c00                              |00bd: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.j:Landroid/graphics/Paint; // field@001c
+001b7a: 1501 a040                              |00bf: const/high16 v1, #int 1084227584 // #40a0
+001b7e: 6e20 2400 1000                         |00c1: invoke-virtual {v0, v1}, Landroid/graphics/Paint;.setStrokeWidth:(F)V // method@0024
+001b84: 1300 0c00                              |00c4: const/16 v0, #int 12 // #c
+001b88: 5990 1d00                              |00c6: iput v0, v9, Lcom/google/android/checkers/CheckersView;.k:I // field@001d
+001b8c: 1200                                   |00c8: const/4 v0, #int 0 // #0
+001b8e: 5990 1e00                              |00c9: iput v0, v9, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+001b92: 5994 1f00                              |00cb: iput v4, v9, Lcom/google/android/checkers/CheckersView;.m:I // field@001f
+001b96: 5994 2000                              |00cd: iput v4, v9, Lcom/google/android/checkers/CheckersView;.n:I // field@0020
+001b9a: 5490 1300                              |00cf: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.a:Landroid/content/Context; // field@0013
+001b9e: 6e10 1100 0000                         |00d1: invoke-virtual {v0}, Landroid/content/Context;.getResources:()Landroid/content/res/Resources; // method@0011
+001ba4: 0c00                                   |00d4: move-result-object v0
+001ba6: 1501 027f                              |00d5: const/high16 v1, #int 2130837504 // #7f02
+001baa: 6e20 1a00 1000                         |00d7: invoke-virtual {v0, v1}, Landroid/content/res/Resources;.getDrawable:(I)Landroid/graphics/drawable/Drawable; // method@001a
+001bb0: 0c00                                   |00da: move-result-object v0
+001bb2: 5b90 2100                              |00db: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.o:Landroid/graphics/drawable/Drawable; // field@0021
+001bb6: 2380 3700                              |00dd: new-array v0, v8, [I // type@0037
+001bba: 5b90 0800                              |00df: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.G:[I // field@0008
+001bbe: 2380 3700                              |00e1: new-array v0, v8, [I // type@0037
+001bc2: 5b90 0900                              |00e3: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.H:[I // field@0009
+001bc6: 2380 3700                              |00e5: new-array v0, v8, [I // type@0037
+001bca: 5b90 0a00                              |00e7: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.I:[I // field@000a
+001bce: 2380 3700                              |00e9: new-array v0, v8, [I // type@0037
+001bd2: 5b90 0b00                              |00eb: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.J:[I // field@000b
+001bd6: 1300 0002                              |00ed: const/16 v0, #int 512 // #200
+001bda: 2300 3600                              |00ef: new-array v0, v0, [B // type@0036
+001bde: 6900 5900                              |00f1: sput-object v0, Lcom/google/android/checkers/g;.a:[B // field@0059
+001be2: 1300 8003                              |00f3: const/16 v0, #int 896 // #380
+001be6: 2300 3600                              |00f5: new-array v0, v0, [B // type@0036
+001bea: 6900 5a00                              |00f7: sput-object v0, Lcom/google/android/checkers/g;.b:[B // field@005a
+001bee: 1300 8003                              |00f9: const/16 v0, #int 896 // #380
+001bf2: 2300 3600                              |00fb: new-array v0, v0, [B // type@0036
+001bf6: 6900 5b00                              |00fd: sput-object v0, Lcom/google/android/checkers/g;.c:[B // field@005b
+001bfa: 1300 1003                              |00ff: const/16 v0, #int 784 // #310
+001bfe: 2300 3600                              |0101: new-array v0, v0, [B // type@0036
+001c02: 6900 5c00                              |0103: sput-object v0, Lcom/google/android/checkers/g;.d:[B // field@005c
+001c06: 1300 001f                              |0105: const/16 v0, #int 7936 // #1f00
+001c0a: 2300 3600                              |0107: new-array v0, v0, [B // type@0036
+001c0e: 6900 5d00                              |0109: sput-object v0, Lcom/google/android/checkers/g;.e:[B // field@005d
+001c12: 1300 001f                              |010b: const/16 v0, #int 7936 // #1f00
+001c16: 2300 3600                              |010d: new-array v0, v0, [B // type@0036
+001c1a: 6900 5e00                              |010f: sput-object v0, Lcom/google/android/checkers/g;.f:[B // field@005e
+001c1e: 1300 4036                              |0111: const/16 v0, #int 13888 // #3640
+001c22: 2300 3600                              |0113: new-array v0, v0, [B // type@0036
+001c26: 6900 5f00                              |0115: sput-object v0, Lcom/google/android/checkers/g;.g:[B // field@005f
+001c2a: 1300 4036                              |0117: const/16 v0, #int 13888 // #3640
+001c2e: 2300 3600                              |0119: new-array v0, v0, [B // type@0036
+001c32: 6900 6000                              |011b: sput-object v0, Lcom/google/android/checkers/g;.h:[B // field@0060
+001c36: 1300 0070                              |011d: const/16 v0, #int 28672 // #7000
+001c3a: 2300 3600                              |011f: new-array v0, v0, [B // type@0036
+001c3e: 6900 6100                              |0121: sput-object v0, Lcom/google/android/checkers/g;.i:[B // field@0061
+001c42: 1300 0070                              |0123: const/16 v0, #int 28672 // #7000
+001c46: 2300 3600                              |0125: new-array v0, v0, [B // type@0036
+001c4a: 6900 6200                              |0127: sput-object v0, Lcom/google/android/checkers/g;.j:[B // field@0062
+001c4e: 1300 0062                              |0129: const/16 v0, #int 25088 // #6200
+001c52: 2300 3600                              |012b: new-array v0, v0, [B // type@0036
+001c56: 6900 6300                              |012d: sput-object v0, Lcom/google/android/checkers/g;.k:[B // field@0063
+001c5a: 1300 0062                              |012f: const/16 v0, #int 25088 // #6200
+001c5e: 2300 3600                              |0131: new-array v0, v0, [B // type@0036
+001c62: 6900 6400                              |0133: sput-object v0, Lcom/google/android/checkers/g;.l:[B // field@0064
+001c66: 1300 402f                              |0135: const/16 v0, #int 12096 // #2f40
+001c6a: 2300 3600                              |0137: new-array v0, v0, [B // type@0036
+001c6e: 6900 6500                              |0139: sput-object v0, Lcom/google/android/checkers/g;.m:[B // field@0065
+001c72: 1300 402f                              |013b: const/16 v0, #int 12096 // #2f40
+001c76: 2300 3600                              |013d: new-array v0, v0, [B // type@0036
+001c7a: 6900 6600                              |013f: sput-object v0, Lcom/google/android/checkers/g;.n:[B // field@0066
+001c7e: 1300 5829                              |0141: const/16 v0, #int 10584 // #2958
+001c82: 2300 3600                              |0143: new-array v0, v0, [B // type@0036
+001c86: 6900 6700                              |0145: sput-object v0, Lcom/google/android/checkers/g;.o:[B // field@0067
+001c8a: 1300 5829                              |0147: const/16 v0, #int 10584 // #2958
+001c8e: 2300 3600                              |0149: new-array v0, v0, [B // type@0036
+001c92: 6900 6800                              |014b: sput-object v0, Lcom/google/android/checkers/g;.p:[B // field@0068
+001c96: 1400 00c1 0300                         |014d: const v0, #float 3.44742e-40 // #0003c100
+001c9c: 2300 3600                              |0150: new-array v0, v0, [B // type@0036
+001ca0: 6900 6900                              |0152: sput-object v0, Lcom/google/android/checkers/g;.q:[B // field@0069
+001ca4: 6e10 1100 0a00                         |0154: invoke-virtual {v10}, Landroid/content/Context;.getResources:()Landroid/content/res/Resources; // method@0011
+001caa: 0c00                                   |0157: move-result-object v0
+001cac: 1501 037f                              |0158: const/high16 v1, #int 2130903040 // #7f03
+001cb0: 6e20 1b00 1000                         |015a: invoke-virtual {v0, v1}, Landroid/content/res/Resources;.openRawResource:(I)Ljava/io/InputStream; // method@001b
+001cb6: 0c00                                   |015d: move-result-object v0
+001cb8: 2201 2700                              |015e: new-instance v1, Ljava/io/BufferedInputStream; // type@0027
+001cbc: 1302 0020                              |0160: const/16 v2, #int 8192 // #2000
+001cc0: 7030 9a00 0102                         |0162: invoke-direct {v1, v0, v2}, Ljava/io/BufferedInputStream;.<init>:(Ljava/io/InputStream;I)V // method@009a
+001cc6: 6901 6b00                              |0165: sput-object v1, Lcom/google/android/checkers/g;.s:Ljava/io/BufferedInputStream; // field@006b
+001cca: 6200 5900                              |0167: sget-object v0, Lcom/google/android/checkers/g;.a:[B // field@0059
+001cce: 7110 9900 0000                         |0169: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001cd4: 6200 5a00                              |016c: sget-object v0, Lcom/google/android/checkers/g;.b:[B // field@005a
+001cd8: 7110 9900 0000                         |016e: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001cde: 6200 5b00                              |0171: sget-object v0, Lcom/google/android/checkers/g;.c:[B // field@005b
+001ce2: 7110 9900 0000                         |0173: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001ce8: 6200 5c00                              |0176: sget-object v0, Lcom/google/android/checkers/g;.d:[B // field@005c
+001cec: 7110 9900 0000                         |0178: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001cf2: 6200 5d00                              |017b: sget-object v0, Lcom/google/android/checkers/g;.e:[B // field@005d
+001cf6: 7110 9900 0000                         |017d: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001cfc: 6200 5e00                              |0180: sget-object v0, Lcom/google/android/checkers/g;.f:[B // field@005e
+001d00: 7110 9900 0000                         |0182: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d06: 6200 5f00                              |0185: sget-object v0, Lcom/google/android/checkers/g;.g:[B // field@005f
+001d0a: 7110 9900 0000                         |0187: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d10: 6200 6000                              |018a: sget-object v0, Lcom/google/android/checkers/g;.h:[B // field@0060
+001d14: 7110 9900 0000                         |018c: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d1a: 6200 6100                              |018f: sget-object v0, Lcom/google/android/checkers/g;.i:[B // field@0061
+001d1e: 7110 9900 0000                         |0191: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d24: 6200 6200                              |0194: sget-object v0, Lcom/google/android/checkers/g;.j:[B // field@0062
+001d28: 7110 9900 0000                         |0196: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d2e: 6200 6300                              |0199: sget-object v0, Lcom/google/android/checkers/g;.k:[B // field@0063
+001d32: 7110 9900 0000                         |019b: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d38: 6200 6400                              |019e: sget-object v0, Lcom/google/android/checkers/g;.l:[B // field@0064
+001d3c: 7110 9900 0000                         |01a0: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d42: 6200 6500                              |01a3: sget-object v0, Lcom/google/android/checkers/g;.m:[B // field@0065
+001d46: 7110 9900 0000                         |01a5: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d4c: 6200 6600                              |01a8: sget-object v0, Lcom/google/android/checkers/g;.n:[B // field@0066
+001d50: 7110 9900 0000                         |01aa: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d56: 6200 6700                              |01ad: sget-object v0, Lcom/google/android/checkers/g;.o:[B // field@0067
+001d5a: 7110 9900 0000                         |01af: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d60: 6200 6800                              |01b2: sget-object v0, Lcom/google/android/checkers/g;.p:[B // field@0068
+001d64: 7110 9900 0000                         |01b4: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d6a: 6200 6900                              |01b7: sget-object v0, Lcom/google/android/checkers/g;.q:[B // field@0069
+001d6e: 7110 9900 0000                         |01b9: invoke-static {v0}, Lcom/google/android/checkers/g;.a:([B)Z // method@0099
+001d74: 6200 6b00                              |01bc: sget-object v0, Lcom/google/android/checkers/g;.s:Ljava/io/BufferedInputStream; // field@006b
+001d78: 6e10 9b00 0000                         |01be: invoke-virtual {v0}, Ljava/io/BufferedInputStream;.close:()V // method@009b
+001d7e: 1200                                   |01c1: const/4 v0, #int 0 // #0
+001d80: 6900 6b00                              |01c2: sput-object v0, Lcom/google/android/checkers/g;.s:Ljava/io/BufferedInputStream; // field@006b
+001d84: 1210                                   |01c4: const/4 v0, #int 1 // #1
+001d86: 6a00 6a00                              |01c5: sput-boolean v0, Lcom/google/android/checkers/g;.r:Z // field@006a
+001d8a: 2200 2000                              |01c7: new-instance v0, Lcom/google/android/checkers/a; // type@0020
+001d8e: 7020 7200 9000                         |01c9: invoke-direct {v0, v9}, Lcom/google/android/checkers/a;.<init>:(Lcom/google/android/checkers/CheckersView;)V // method@0072
+001d94: 5b90 2200                              |01cc: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+001d98: 5b95 0f00                              |01ce: iput-object v5, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+001d9c: 7020 5800 b900                         |01d0: invoke-direct {v9, v11}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/content/SharedPreferences;)Z // method@0058
+001da2: 0a00                                   |01d3: move-result v0
+001da4: 3800 8500                              |01d4: if-eqz v0, 0259 // +0085
+001da8: 7010 6700 0900                         |01d6: invoke-direct {v9}, Lcom/google/android/checkers/CheckersView;.e:()Z // method@0067
+001dae: 0a00                                   |01d9: move-result v0
+001db0: 3900 0600                              |01da: if-nez v0, 01e0 // +0006
+001db4: 1a00 1701                              |01dc: const-string v0, "restored game" // string@0117
+001db8: 5b90 0f00                              |01de: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+001dbc: 7010 6400 0900                         |01e0: invoke-direct {v9}, Lcom/google/android/checkers/CheckersView;.d:()V // method@0064
+001dc2: 1500 20c1                              |01e3: const/high16 v0, #int -1054867456 // #c120
+001dc6: 5990 1000                              |01e5: iput v0, v9, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+001dca: 1500 20c1                              |01e7: const/high16 v0, #int -1054867456 // #c120
+001dce: 5990 1100                              |01e9: iput v0, v9, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+001dd2: 5994 1200                              |01eb: iput v4, v9, Lcom/google/android/checkers/CheckersView;.Q:I // field@0012
+001dd6: 5590 0600                              |01ed: iget-boolean v0, v9, Lcom/google/android/checkers/CheckersView;.E:Z // field@0006
+001dda: 3800 2e00                              |01ef: if-eqz v0, 021d // +002e
+001dde: 7010 6700 0900                         |01f1: invoke-direct {v9}, Lcom/google/android/checkers/CheckersView;.e:()Z // method@0067
+001de4: 0a00                                   |01f4: move-result v0
+001de6: 3800 2800                              |01f5: if-eqz v0, 021d // +0028
+001dea: 2200 0500                              |01f7: new-instance v0, Landroid/app/AlertDialog$Builder; // type@0005
+001dee: 5491 1300                              |01f9: iget-object v1, v9, Lcom/google/android/checkers/CheckersView;.a:Landroid/content/Context; // field@0013
+001df2: 7020 0900 1000                         |01fb: invoke-direct {v0, v1}, Landroid/app/AlertDialog$Builder;.<init>:(Landroid/content/Context;)V // method@0009
+001df8: 1a01 1200                              |01fe: const-string v1, "Checkers for Android was written by Aart J.C. Bik.
+
+Use the touch screen or trackball to make a move. Press the MENU button for more options, such as making captures optional instead of mandatory.
+
+The application complies with the official American checkers rules, where black moves first, captures are mandatory, men only move and jump forward, and kings move and jump forward and backward (but not over a distance). Please note that many variants of checkers exist, and this game may not use the rules you are most familiar with.
+" // string@0012
+001dfc: 6e20 0c00 1000                         |0200: invoke-virtual {v0, v1}, Landroid/app/AlertDialog$Builder;.setMessage:(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder; // method@000c
+001e02: 0c00                                   |0203: move-result-object v0
+001e04: 1a01 2b00                              |0204: const-string v1, "KEEP SHOWING" // string@002b
+001e08: 2202 2300                              |0206: new-instance v2, Lcom/google/android/checkers/d; // type@0023
+001e0c: 7020 9300 9200                         |0208: invoke-direct {v2, v9}, Lcom/google/android/checkers/d;.<init>:(Lcom/google/android/checkers/CheckersView;)V // method@0093
+001e12: 6e30 0e00 1002                         |020b: invoke-virtual {v0, v1, v2}, Landroid/app/AlertDialog$Builder;.setPositiveButton:(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder; // method@000e
+001e18: 0c00                                   |020e: move-result-object v0
+001e1a: 1a01 7c00                              |020f: const-string v1, "STOP SHOWING" // string@007c
+001e1e: 2202 2400                              |0211: new-instance v2, Lcom/google/android/checkers/e; // type@0024
+001e22: 7020 9500 9200                         |0213: invoke-direct {v2, v9}, Lcom/google/android/checkers/e;.<init>:(Lcom/google/android/checkers/CheckersView;)V // method@0095
+001e28: 6e30 0d00 1002                         |0216: invoke-virtual {v0, v1, v2}, Landroid/app/AlertDialog$Builder;.setNegativeButton:(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder; // method@000d
+001e2e: 0c00                                   |0219: move-result-object v0
+001e30: 6e10 1000 0000                         |021a: invoke-virtual {v0}, Landroid/app/AlertDialog$Builder;.show:()Landroid/app/AlertDialog; // method@0010
+001e36: 0e00                                   |021d: return-void
+001e38: 0d00                                   |021e: move-exception v0
+001e3a: 1a01 0800                              |021f: const-string v1, "BIK" // string@0008
+001e3e: 2202 3000                              |0221: new-instance v2, Ljava/lang/StringBuilder; // type@0030
+001e42: 1a03 b700                              |0223: const-string v3, "cannot read tb: " // string@00b7
+001e46: 7020 a600 3200                         |0225: invoke-direct {v2, v3}, Ljava/lang/StringBuilder;.<init>:(Ljava/lang/String;)V // method@00a6
+001e4c: 6e20 a800 0200                         |0228: invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00a8
+001e52: 0c00                                   |022b: move-result-object v0
+001e54: 6e10 aa00 0000                         |022c: invoke-virtual {v0}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00aa
+001e5a: 0c00                                   |022f: move-result-object v0
+001e5c: 7120 2a00 0100                         |0230: invoke-static {v1, v0}, Landroid/util/Log;.d:(Ljava/lang/String;Ljava/lang/String;)I // method@002a
+001e62: 6905 5900                              |0233: sput-object v5, Lcom/google/android/checkers/g;.a:[B // field@0059
+001e66: 6905 5a00                              |0235: sput-object v5, Lcom/google/android/checkers/g;.b:[B // field@005a
+001e6a: 6905 5b00                              |0237: sput-object v5, Lcom/google/android/checkers/g;.c:[B // field@005b
+001e6e: 6905 5c00                              |0239: sput-object v5, Lcom/google/android/checkers/g;.d:[B // field@005c
+001e72: 6905 5d00                              |023b: sput-object v5, Lcom/google/android/checkers/g;.e:[B // field@005d
+001e76: 6905 5e00                              |023d: sput-object v5, Lcom/google/android/checkers/g;.f:[B // field@005e
+001e7a: 6905 5f00                              |023f: sput-object v5, Lcom/google/android/checkers/g;.g:[B // field@005f
+001e7e: 6905 6000                              |0241: sput-object v5, Lcom/google/android/checkers/g;.h:[B // field@0060
+001e82: 6905 6100                              |0243: sput-object v5, Lcom/google/android/checkers/g;.i:[B // field@0061
+001e86: 6905 6200                              |0245: sput-object v5, Lcom/google/android/checkers/g;.j:[B // field@0062
+001e8a: 6905 6300                              |0247: sput-object v5, Lcom/google/android/checkers/g;.k:[B // field@0063
+001e8e: 6905 6400                              |0249: sput-object v5, Lcom/google/android/checkers/g;.l:[B // field@0064
+001e92: 6905 6500                              |024b: sput-object v5, Lcom/google/android/checkers/g;.m:[B // field@0065
+001e96: 6905 6600                              |024d: sput-object v5, Lcom/google/android/checkers/g;.n:[B // field@0066
+001e9a: 6905 6700                              |024f: sput-object v5, Lcom/google/android/checkers/g;.o:[B // field@0067
+001e9e: 6905 6800                              |0251: sput-object v5, Lcom/google/android/checkers/g;.p:[B // field@0068
+001ea2: 6905 6900                              |0253: sput-object v5, Lcom/google/android/checkers/g;.q:[B // field@0069
+001ea6: 6a04 6a00                              |0255: sput-boolean v4, Lcom/google/android/checkers/g;.r:Z // field@006a
+001eaa: 2900 70ff                              |0257: goto/16 01c7 // -0090
+001eae: 5997 2300                              |0259: iput v7, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+001eb2: 5490 2200                              |025b: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+001eb6: 5200 3d00                              |025d: iget v0, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+001eba: 5990 2400                              |025f: iput v0, v9, Lcom/google/android/checkers/CheckersView;.r:I // field@0024
+001ebe: 5490 2200                              |0261: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+001ec2: 5200 3f00                              |0263: iget v0, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+001ec6: 5990 2500                              |0265: iput v0, v9, Lcom/google/android/checkers/CheckersView;.s:I // field@0025
+001eca: 5490 2200                              |0267: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+001ece: 5200 3e00                              |0269: iget v0, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+001ed2: 5990 2600                              |026b: iput v0, v9, Lcom/google/android/checkers/CheckersView;.t:I // field@0026
+001ed6: 5490 2200                              |026d: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+001eda: 5200 4000                              |026f: iget v0, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+001ede: 5990 2700                              |0271: iput v0, v9, Lcom/google/android/checkers/CheckersView;.u:I // field@0027
+001ee2: 5994 2800                              |0273: iput v4, v9, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+001ee6: 5994 2900                              |0275: iput v4, v9, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+001eea: 5994 2a00                              |0277: iput v4, v9, Lcom/google/android/checkers/CheckersView;.x:I // field@002a
+001eee: 5c94 2b00                              |0279: iput-boolean v4, v9, Lcom/google/android/checkers/CheckersView;.y:Z // field@002b
+001ef2: 1230                                   |027b: const/4 v0, #int 3 // #3
+001ef4: 5990 2c00                              |027c: iput v0, v9, Lcom/google/android/checkers/CheckersView;.z:I // field@002c
+001ef8: 5c97 0200                              |027e: iput-boolean v7, v9, Lcom/google/android/checkers/CheckersView;.A:Z // field@0002
+001efc: 5c94 0300                              |0280: iput-boolean v4, v9, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+001f00: 5c94 0400                              |0282: iput-boolean v4, v9, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+001f04: 5c94 0500                              |0284: iput-boolean v4, v9, Lcom/google/android/checkers/CheckersView;.D:Z // field@0005
+001f08: 5c97 0600                              |0286: iput-boolean v7, v9, Lcom/google/android/checkers/CheckersView;.E:Z // field@0006
+001f0c: 5994 0700                              |0288: iput v4, v9, Lcom/google/android/checkers/CheckersView;.F:I // field@0007
+001f10: 5994 0c00                              |028a: iput v4, v9, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+001f14: 5994 0d00                              |028c: iput v4, v9, Lcom/google/android/checkers/CheckersView;.L:I // field@000d
+001f18: 5490 2200                              |028e: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+001f1c: 5200 3c00                              |0290: iget v0, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+001f20: 5990 0e00                              |0292: iput v0, v9, Lcom/google/android/checkers/CheckersView;.M:I // field@000e
+001f24: 2900 4cff                              |0294: goto/16 01e0 // -00b4
+      catches       : 1
+        0x00ef - 0x01c7
+          Ljava/lang/Exception; -> 0x021e
+      positions     : 
+      locals        : 
+
+    #1              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(Landroid/content/SharedPreferences$Editor;Ljava/lang/String;[I)V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 82
+      code          -
+      registers     : 6
+      ins           : 3
+      outs          : 3
+      insns size    : 31 16-bit code units
+001f38:                                        |[001f38] com.google.android.checkers.CheckersView.a:(Landroid/content/SharedPreferences$Editor;Ljava/lang/String;[I)V
+001f48: 1200                                   |0000: const/4 v0, #int 0 // #0
+001f4a: 1301 0800                              |0001: const/16 v1, #int 8 // #8
+001f4e: 3410 0300                              |0003: if-lt v0, v1, 0006 // +0003
+001f52: 0e00                                   |0005: return-void
+001f54: 2201 3000                              |0006: new-instance v1, Ljava/lang/StringBuilder; // type@0030
+001f58: 7110 a500 0400                         |0008: invoke-static {v4}, Ljava/lang/String;.valueOf:(Ljava/lang/Object;)Ljava/lang/String; // method@00a5
+001f5e: 0c02                                   |000b: move-result-object v2
+001f60: 7020 a600 2100                         |000c: invoke-direct {v1, v2}, Ljava/lang/StringBuilder;.<init>:(Ljava/lang/String;)V // method@00a6
+001f66: 6e20 a700 0100                         |000f: invoke-virtual {v1, v0}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+001f6c: 0c01                                   |0012: move-result-object v1
+001f6e: 6e10 aa00 0100                         |0013: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00aa
+001f74: 0c01                                   |0016: move-result-object v1
+001f76: 4402 0500                              |0017: aget v2, v5, v0
+001f7a: 7230 1600 1302                         |0019: invoke-interface {v3, v1, v2}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+001f80: d800 0001                              |001c: add-int/lit8 v0, v0, #int 1 // #01
+001f84: 28e3                                   |001e: goto 0001 // -001d
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #2              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(Landroid/content/SharedPreferences;Ljava/lang/String;[I)V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 83
+      code          -
+      registers     : 7
+      ins           : 3
+      outs          : 3
+      insns size    : 33 16-bit code units
+001f88:                                        |[001f88] com.google.android.checkers.CheckersView.a:(Landroid/content/SharedPreferences;Ljava/lang/String;[I)V
+001f98: 1201                                   |0000: const/4 v1, #int 0 // #0
+001f9a: 0110                                   |0001: move v0, v1
+001f9c: 1302 0800                              |0002: const/16 v2, #int 8 // #8
+001fa0: 3420 0300                              |0004: if-lt v0, v2, 0007 // +0003
+001fa4: 0e00                                   |0006: return-void
+001fa6: 2202 3000                              |0007: new-instance v2, Ljava/lang/StringBuilder; // type@0030
+001faa: 7110 a500 0500                         |0009: invoke-static {v5}, Ljava/lang/String;.valueOf:(Ljava/lang/Object;)Ljava/lang/String; // method@00a5
+001fb0: 0c03                                   |000c: move-result-object v3
+001fb2: 7020 a600 3200                         |000d: invoke-direct {v2, v3}, Ljava/lang/StringBuilder;.<init>:(Ljava/lang/String;)V // method@00a6
+001fb8: 6e20 a700 0200                         |0010: invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+001fbe: 0c02                                   |0013: move-result-object v2
+001fc0: 6e10 aa00 0200                         |0014: invoke-virtual {v2}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00aa
+001fc6: 0c02                                   |0017: move-result-object v2
+001fc8: 7230 1900 2401                         |0018: invoke-interface {v4, v2, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+001fce: 0a02                                   |001b: move-result v2
+001fd0: 4b02 0600                              |001c: aput v2, v6, v0
+001fd4: d800 0001                              |001e: add-int/lit8 v0, v0, #int 1 // #01
+001fd8: 28e2                                   |0020: goto 0002 // -001e
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #3              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(Landroid/graphics/Canvas;IIII)V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 84
+      code          -
+      registers     : 13
+      ins           : 6
+      outs          : 6
+      insns size    : 63 16-bit code units
+001fdc:                                        |[001fdc] com.google.android.checkers.CheckersView.a:(Landroid/graphics/Canvas;IIII)V
+001fec: e201 0902                              |0000: ushr-int/lit8 v1, v9, #int 2 // #02
+001ff0: dd00 0903                              |0002: and-int/lit8 v0, v9, #int 3 // #03
+001ff4: da00 0002                              |0004: mul-int/lit8 v0, v0, #int 2 // #02
+001ff8: d800 0001                              |0006: add-int/lit8 v0, v0, #int 1 // #01
+001ffc: dd02 0101                              |0008: and-int/lit8 v2, v1, #int 1 // #01
+002000: 9103 0002                              |000a: sub-int v3, v0, v2
+002004: e200 0a02                              |000c: ushr-int/lit8 v0, v10, #int 2 // #02
+002008: dd02 0a03                              |000e: and-int/lit8 v2, v10, #int 3 // #03
+00200c: da02 0202                              |0010: mul-int/lit8 v2, v2, #int 2 // #02
+002010: d802 0201                              |0012: add-int/lit8 v2, v2, #int 1 // #01
+002014: dd04 0001                              |0014: and-int/lit8 v4, v0, #int 1 // #01
+002018: b142                                   |0016: sub-int/2addr v2, v4
+00201a: 5574 0400                              |0017: iget-boolean v4, v7, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+00201e: 3804 2100                              |0019: if-eqz v4, 003a // +0021
+002022: d901 0107                              |001b: rsub-int/lit8 v1, v1, #int 7 // #07
+002026: d903 0307                              |001d: rsub-int/lit8 v3, v3, #int 7 // #07
+00202a: d900 0007                              |001f: rsub-int/lit8 v0, v0, #int 7 // #07
+00202e: d902 0207                              |0021: rsub-int/lit8 v2, v2, #int 7 // #07
+002032: 0116                                   |0023: move v6, v1
+002034: 0131                                   |0024: move v1, v3
+002036: 0123                                   |0025: move v3, v2
+002038: 0162                                   |0026: move v2, v6
+00203a: b2b1                                   |0027: mul-int/2addr v1, v11
+00203c: b0c1                                   |0028: add-int/2addr v1, v12
+00203e: 8211                                   |0029: int-to-float v1, v1
+002040: b2b2                                   |002a: mul-int/2addr v2, v11
+002042: b0c2                                   |002b: add-int/2addr v2, v12
+002044: 8222                                   |002c: int-to-float v2, v2
+002046: b2b3                                   |002d: mul-int/2addr v3, v11
+002048: b0c3                                   |002e: add-int/2addr v3, v12
+00204a: 8233                                   |002f: int-to-float v3, v3
+00204c: b2b0                                   |0030: mul-int/2addr v0, v11
+00204e: b0c0                                   |0031: add-int/2addr v0, v12
+002050: 8204                                   |0032: int-to-float v4, v0
+002052: 5475 1a00                              |0033: iget-object v5, v7, Lcom/google/android/checkers/CheckersView;.h:Landroid/graphics/Paint; // field@001a
+002056: 0780                                   |0035: move-object v0, v8
+002058: 7406 1d00 0000                         |0036: invoke-virtual/range {v0, v1, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawLine:(FFFFLandroid/graphics/Paint;)V // method@001d
+00205e: 0e00                                   |0039: return-void
+002060: 0116                                   |003a: move v6, v1
+002062: 0131                                   |003b: move v1, v3
+002064: 0123                                   |003c: move v3, v2
+002066: 0162                                   |003d: move v2, v6
+002068: 28e9                                   |003e: goto 0027 // -0017
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #4              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(Landroid/graphics/Canvas;IIIILandroid/graphics/Paint;Landroid/graphics/Paint;Z)V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 85
+      code          -
+      registers     : 13
+      ins           : 8
+      outs          : 5
+      insns size    : 81 16-bit code units
+00206c:                                        |[00206c] com.google.android.checkers.CheckersView.a:(Landroid/graphics/Canvas;IIIILandroid/graphics/Paint;Landroid/graphics/Paint;Z)V
+00207c: 8260                                   |0000: int-to-float v0, v6
+00207e: 8271                                   |0001: int-to-float v1, v7
+002080: d802 08fe                              |0002: add-int/lit8 v2, v8, #int -2 // #fe
+002084: 8222                                   |0004: int-to-float v2, v2
+002086: 6e5a 1c00 0521                         |0005: invoke-virtual {v5, v0, v1, v2, v10}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+00208c: 8260                                   |0008: int-to-float v0, v6
+00208e: 8271                                   |0009: int-to-float v1, v7
+002090: d802 08fc                              |000a: add-int/lit8 v2, v8, #int -4 // #fc
+002094: 8222                                   |000c: int-to-float v2, v2
+002096: 6e5b 1c00 0521                         |000d: invoke-virtual {v5, v0, v1, v2, v11}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+00209c: 8260                                   |0010: int-to-float v0, v6
+00209e: 8271                                   |0011: int-to-float v1, v7
+0020a0: d802 08f9                              |0012: add-int/lit8 v2, v8, #int -7 // #f9
+0020a4: 8222                                   |0014: int-to-float v2, v2
+0020a6: 6e5a 1c00 0521                         |0015: invoke-virtual {v5, v0, v1, v2, v10}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+0020ac: 8260                                   |0018: int-to-float v0, v6
+0020ae: 8271                                   |0019: int-to-float v1, v7
+0020b0: d802 08f7                              |001a: add-int/lit8 v2, v8, #int -9 // #f7
+0020b4: 8222                                   |001c: int-to-float v2, v2
+0020b6: 6e5b 1c00 0521                         |001d: invoke-virtual {v5, v0, v1, v2, v11}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+0020bc: 380c 3000                              |0020: if-eqz v12, 0050 // +0030
+0020c0: e100 0802                              |0022: shr-int/lit8 v0, v8, #int 2 // #02
+0020c4: 9101 0600                              |0024: sub-int v1, v6, v0
+0020c8: 9100 0700                              |0026: sub-int v0, v7, v0
+0020cc: 8212                                   |0028: int-to-float v2, v1
+0020ce: 8203                                   |0029: int-to-float v3, v0
+0020d0: d804 08fe                              |002a: add-int/lit8 v4, v8, #int -2 // #fe
+0020d4: 8244                                   |002c: int-to-float v4, v4
+0020d6: 6e5a 1c00 2543                         |002d: invoke-virtual {v5, v2, v3, v4, v10}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+0020dc: 8212                                   |0030: int-to-float v2, v1
+0020de: 8203                                   |0031: int-to-float v3, v0
+0020e0: d804 08fc                              |0032: add-int/lit8 v4, v8, #int -4 // #fc
+0020e4: 8244                                   |0034: int-to-float v4, v4
+0020e6: 6e5b 1c00 2543                         |0035: invoke-virtual {v5, v2, v3, v4, v11}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+0020ec: 8212                                   |0038: int-to-float v2, v1
+0020ee: 8203                                   |0039: int-to-float v3, v0
+0020f0: d804 08f9                              |003a: add-int/lit8 v4, v8, #int -7 // #f9
+0020f4: 8244                                   |003c: int-to-float v4, v4
+0020f6: 6e5a 1c00 2543                         |003d: invoke-virtual {v5, v2, v3, v4, v10}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+0020fc: 8212                                   |0040: int-to-float v2, v1
+0020fe: 8203                                   |0041: int-to-float v3, v0
+002100: d804 08f7                              |0042: add-int/lit8 v4, v8, #int -9 // #f7
+002104: 8244                                   |0044: int-to-float v4, v4
+002106: 6e5b 1c00 2543                         |0045: invoke-virtual {v5, v2, v3, v4, v11}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+00210c: 1a02 2a00                              |0048: const-string v2, "K" // string@002a
+002110: b191                                   |004a: sub-int/2addr v1, v9
+002112: 8211                                   |004b: int-to-float v1, v1
+002114: 8200                                   |004c: int-to-float v0, v0
+002116: 6e5a 2000 2501                         |004d: invoke-virtual {v5, v2, v1, v0, v10}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+00211c: 0e00                                   |0050: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #5              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(Lcom/google/android/checkers/CheckersView;I)V'
+      access        : 0x1008 (STATIC SYNTHETIC)
+      method_idx    : 86
+      code          -
+      registers     : 2
+      ins           : 2
+      outs          : 2
+      insns size    : 4 16-bit code units
+002120:                                        |[002120] com.google.android.checkers.CheckersView.a:(Lcom/google/android/checkers/CheckersView;I)V
+002130: 7020 5e00 1000                         |0000: invoke-direct {v0, v1}, Lcom/google/android/checkers/CheckersView;.b:(I)V // method@005e
+002136: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #6              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(Landroid/content/SharedPreferences;)Z'
+      access        : 0x20012 (PRIVATE FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 88
+      code          -
+      registers     : 12
+      ins           : 2
+      outs          : 6
+      insns size    : 294 16-bit code units
+002138:                                        |[002138] com.google.android.checkers.CheckersView.a:(Landroid/content/SharedPreferences;)Z
+002148: 1249                                   |0000: const/4 v9, #int 4 // #4
+00214a: 1232                                   |0001: const/4 v2, #int 3 // #3
+00214c: 1217                                   |0002: const/4 v7, #int 1 // #1
+00214e: 1206                                   |0003: const/4 v6, #int 0 // #0
+002150: 1d0a                                   |0004: monitor-enter v10
+002152: 380b 1b01                              |0005: if-eqz v11, 0120 // +011b
+002156: 1a00 d000                              |0007: const-string v0, "format" // string@00d0
+00215a: 1201                                   |0009: const/4 v1, #int 0 // #0
+00215c: 7230 1900 0b01                         |000a: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+002162: 0a00                                   |000d: move-result v0
+002164: 1301 2200                              |000e: const/16 v1, #int 34 // #22
+002168: 3210 0500                              |0010: if-eq v0, v1, 0015 // +0005
+00216c: 0160                                   |0012: move v0, v6
+00216e: 1e0a                                   |0013: monitor-exit v10
+002170: 0f00                                   |0014: return v0
+002172: 1a00 3101                              |0015: const-string v0, "state" // string@0131
+002176: 1211                                   |0017: const/4 v1, #int 1 // #1
+002178: 7230 1900 0b01                         |0018: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+00217e: 0a00                                   |001b: move-result v0
+002180: 59a0 2300                              |001c: iput v0, v10, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002184: 1a00 3f01                              |001e: const-string v0, "wp" // string@013f
+002188: 1201                                   |0020: const/4 v1, #int 0 // #0
+00218a: 7230 1900 0b01                         |0021: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+002190: 0a00                                   |0024: move-result v0
+002192: 59a0 2400                              |0025: iput v0, v10, Lcom/google/android/checkers/CheckersView;.r:I // field@0024
+002196: 1a00 b400                              |0027: const-string v0, "bp" // string@00b4
+00219a: 1201                                   |0029: const/4 v1, #int 0 // #0
+00219c: 7230 1900 0b01                         |002a: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+0021a2: 0a00                                   |002d: move-result v0
+0021a4: 59a0 2500                              |002e: iput v0, v10, Lcom/google/android/checkers/CheckersView;.s:I // field@0025
+0021a8: 1a00 3e01                              |0030: const-string v0, "wk" // string@013e
+0021ac: 1201                                   |0032: const/4 v1, #int 0 // #0
+0021ae: 7230 1900 0b01                         |0033: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+0021b4: 0a00                                   |0036: move-result v0
+0021b6: 59a0 2600                              |0037: iput v0, v10, Lcom/google/android/checkers/CheckersView;.t:I // field@0026
+0021ba: 1a00 b300                              |0039: const-string v0, "bk" // string@00b3
+0021be: 1201                                   |003b: const/4 v1, #int 0 // #0
+0021c0: 7230 1900 0b01                         |003c: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+0021c6: 0a00                                   |003f: move-result v0
+0021c8: 59a0 2700                              |0040: iput v0, v10, Lcom/google/android/checkers/CheckersView;.u:I // field@0027
+0021cc: 1a00 e800                              |0042: const-string v0, "l1" // string@00e8
+0021d0: 1201                                   |0044: const/4 v1, #int 0 // #0
+0021d2: 7230 1900 0b01                         |0045: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+0021d8: 0a00                                   |0048: move-result v0
+0021da: 59a0 2800                              |0049: iput v0, v10, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+0021de: 1a00 e900                              |004b: const-string v0, "l2" // string@00e9
+0021e2: 1201                                   |004d: const/4 v1, #int 0 // #0
+0021e4: 7230 1900 0b01                         |004e: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+0021ea: 0a00                                   |0051: move-result v0
+0021ec: 59a0 2900                              |0052: iput v0, v10, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+0021f0: 1a00 ef00                              |0054: const-string v0, "lm" // string@00ef
+0021f4: 1201                                   |0056: const/4 v1, #int 0 // #0
+0021f6: 7230 1900 0b01                         |0057: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+0021fc: 0a00                                   |005a: move-result v0
+0021fe: 59a0 2a00                              |005b: iput v0, v10, Lcom/google/android/checkers/CheckersView;.x:I // field@002a
+002202: 1a00 b800                              |005d: const-string v0, "cap" // string@00b8
+002206: 1211                                   |005f: const/4 v1, #int 1 // #1
+002208: 7230 1800 0b01                         |0060: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getBoolean:(Ljava/lang/String;Z)Z // method@0018
+00220e: 0a00                                   |0063: move-result v0
+002210: 5ca0 2b00                              |0064: iput-boolean v0, v10, Lcom/google/android/checkers/CheckersView;.y:Z // field@002b
+002214: 1a00 ee00                              |0066: const-string v0, "level" // string@00ee
+002218: 1231                                   |0068: const/4 v1, #int 3 // #3
+00221a: 7230 1900 0b01                         |0069: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+002220: 0a00                                   |006c: move-result v0
+002222: 59a0 2c00                              |006d: iput v0, v10, Lcom/google/android/checkers/CheckersView;.z:I // field@002c
+002226: 1a00 2d01                              |006f: const-string v0, "show" // string@012d
+00222a: 1211                                   |0071: const/4 v1, #int 1 // #1
+00222c: 7230 1800 0b01                         |0072: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getBoolean:(Ljava/lang/String;Z)Z // method@0018
+002232: 0a00                                   |0075: move-result v0
+002234: 5ca0 0200                              |0076: iput-boolean v0, v10, Lcom/google/android/checkers/CheckersView;.A:Z // field@0002
+002238: 1a00 d100                              |0078: const-string v0, "free" // string@00d1
+00223c: 1201                                   |007a: const/4 v1, #int 0 // #0
+00223e: 7230 1800 0b01                         |007b: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getBoolean:(Ljava/lang/String;Z)Z // method@0018
+002244: 0a00                                   |007e: move-result v0
+002246: 5ca0 0300                              |007f: iput-boolean v0, v10, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+00224a: 1a00 1801                              |0081: const-string v0, "rot" // string@0118
+00224e: 1201                                   |0083: const/4 v1, #int 0 // #0
+002250: 7230 1800 0b01                         |0084: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getBoolean:(Ljava/lang/String;Z)Z // method@0018
+002256: 0a00                                   |0087: move-result v0
+002258: 5ca0 0400                              |0088: iput-boolean v0, v10, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+00225c: 1a00 d300                              |008a: const-string v0, "full" // string@00d3
+002260: 1201                                   |008c: const/4 v1, #int 0 // #0
+002262: 7230 1800 0b01                         |008d: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getBoolean:(Ljava/lang/String;Z)Z // method@0018
+002268: 0a00                                   |0090: move-result v0
+00226a: 5ca0 0500                              |0091: iput-boolean v0, v10, Lcom/google/android/checkers/CheckersView;.D:Z // field@0005
+00226e: 1a00 2f01                              |0093: const-string v0, "start" // string@012f
+002272: 1211                                   |0095: const/4 v1, #int 1 // #1
+002274: 7230 1800 0b01                         |0096: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getBoolean:(Ljava/lang/String;Z)Z // method@0018
+00227a: 0a00                                   |0099: move-result v0
+00227c: 5ca0 0600                              |009a: iput-boolean v0, v10, Lcom/google/android/checkers/CheckersView;.E:Z // field@0006
+002280: 1a00 bd00                              |009c: const-string v0, "color" // string@00bd
+002284: 1201                                   |009e: const/4 v1, #int 0 // #0
+002286: 7230 1900 0b01                         |009f: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+00228c: 0a00                                   |00a2: move-result v0
+00228e: 59a0 0700                              |00a3: iput v0, v10, Lcom/google/android/checkers/CheckersView;.F:I // field@0007
+002292: 1a00 f300                              |00a5: const-string v0, "lwp" // string@00f3
+002296: 54a1 0800                              |00a7: iget-object v1, v10, Lcom/google/android/checkers/CheckersView;.G:[I // field@0008
+00229a: 7130 5300 0b01                         |00a9: invoke-static {v11, v0, v1}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/content/SharedPreferences;Ljava/lang/String;[I)V // method@0053
+0022a0: 1a00 f200                              |00ac: const-string v0, "lwk" // string@00f2
+0022a4: 54a1 0900                              |00ae: iget-object v1, v10, Lcom/google/android/checkers/CheckersView;.H:[I // field@0009
+0022a8: 7130 5300 0b01                         |00b0: invoke-static {v11, v0, v1}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/content/SharedPreferences;Ljava/lang/String;[I)V // method@0053
+0022ae: 1a00 eb00                              |00b3: const-string v0, "lbp" // string@00eb
+0022b2: 54a1 0a00                              |00b5: iget-object v1, v10, Lcom/google/android/checkers/CheckersView;.I:[I // field@000a
+0022b6: 7130 5300 0b01                         |00b7: invoke-static {v11, v0, v1}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/content/SharedPreferences;Ljava/lang/String;[I)V // method@0053
+0022bc: 1a00 ea00                              |00ba: const-string v0, "lbk" // string@00ea
+0022c0: 54a1 0b00                              |00bc: iget-object v1, v10, Lcom/google/android/checkers/CheckersView;.J:[I // field@000b
+0022c4: 7130 5300 0b01                         |00be: invoke-static {v11, v0, v1}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/content/SharedPreferences;Ljava/lang/String;[I)V // method@0053
+0022ca: 1a00 f100                              |00c1: const-string v0, "lp" // string@00f1
+0022ce: 1201                                   |00c3: const/4 v1, #int 0 // #0
+0022d0: 7230 1900 0b01                         |00c4: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+0022d6: 0a00                                   |00c7: move-result v0
+0022d8: 59a0 0c00                              |00c8: iput v0, v10, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+0022dc: 1a00 ec00                              |00ca: const-string v0, "lc" // string@00ec
+0022e0: 1201                                   |00cc: const/4 v1, #int 0 // #0
+0022e2: 7230 1900 0b01                         |00cd: invoke-interface {v11, v0, v1}, Landroid/content/SharedPreferences;.getInt:(Ljava/lang/String;I)I // method@0019
+0022e8: 0a00                                   |00d0: move-result v0
+0022ea: 59a0 0d00                              |00d1: iput v0, v10, Lcom/google/android/checkers/CheckersView;.L:I // field@000d
+0022ee: 52a0 2c00                              |00d3: iget v0, v10, Lcom/google/android/checkers/CheckersView;.z:I // field@002c
+0022f2: 6e20 7000 0a00                         |00d5: invoke-virtual {v10, v0}, Lcom/google/android/checkers/CheckersView;.setLevel:(I)V // method@0070
+0022f8: 52a0 2300                              |00d8: iget v0, v10, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+0022fc: 3220 3d00                              |00da: if-eq v0, v2, 0117 // +003d
+002300: 52a0 2300                              |00dc: iget v0, v10, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002304: 3290 3900                              |00de: if-eq v0, v9, 0117 // +0039
+002308: 52a0 2300                              |00e0: iget v0, v10, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+00230c: 1261                                   |00e2: const/4 v1, #int 6 // #6
+00230e: 3210 3400                              |00e3: if-eq v0, v1, 0117 // +0034
+002312: 0165                                   |00e5: move v5, v6
+002314: 54a8 2200                              |00e6: iget-object v8, v10, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002318: 1d08                                   |00e8: monitor-enter v8
+00231a: 54a0 2200                              |00e9: iget-object v0, v10, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+00231e: 52a1 2400                              |00eb: iget v1, v10, Lcom/google/android/checkers/CheckersView;.r:I // field@0024
+002322: 52a2 2600                              |00ed: iget v2, v10, Lcom/google/android/checkers/CheckersView;.t:I // field@0026
+002326: 52a3 2500                              |00ef: iget v3, v10, Lcom/google/android/checkers/CheckersView;.s:I // field@0025
+00232a: 52a4 2700                              |00f1: iget v4, v10, Lcom/google/android/checkers/CheckersView;.u:I // field@0027
+00232e: 7406 8000 0000                         |00f3: invoke-virtual/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIIZ)V // method@0080
+002334: 54a0 2200                              |00f6: iget-object v0, v10, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002338: 55a1 0300                              |00f8: iget-boolean v1, v10, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+00233c: 6e30 7a00 5001                         |00fa: invoke-virtual {v0, v5, v1}, Lcom/google/android/checkers/a;.a:(ZZ)I // method@007a
+002342: 54a0 2200                              |00fd: iget-object v0, v10, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002346: 5200 3c00                              |00ff: iget v0, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+00234a: 59a0 0e00                              |0101: iput v0, v10, Lcom/google/android/checkers/CheckersView;.M:I // field@000e
+00234e: 1e08                                   |0103: monitor-exit v8
+002350: 52a0 2300                              |0104: iget v0, v10, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002354: 3290 0700                              |0106: if-eq v0, v9, 010d // +0007
+002358: 52a0 2300                              |0108: iget v0, v10, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+00235c: 1221                                   |010a: const/4 v1, #int 2 // #2
+00235e: 3310 0900                              |010b: if-ne v0, v1, 0114 // +0009
+002362: 54a0 2200                              |010d: iget-object v0, v10, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002366: 55a1 0300                              |010f: iget-boolean v1, v10, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+00236a: 6e30 8700 5001                         |0111: invoke-virtual {v0, v5, v1}, Lcom/google/android/checkers/a;.b:(ZZ)V // method@0087
+002370: 0170                                   |0114: move v0, v7
+002372: 2900 fefe                              |0115: goto/16 0013 // -0102
+002376: 0175                                   |0117: move v5, v7
+002378: 28ce                                   |0118: goto 00e6 // -0032
+00237a: 0d00                                   |0119: move-exception v0
+00237c: 1e08                                   |011a: monitor-exit v8
+00237e: 2700                                   |011b: throw v0
+002380: 0d00                                   |011c: move-exception v0
+002382: 0160                                   |011d: move v0, v6
+002384: 2900 f5fe                              |011e: goto/16 0013 // -010b
+002388: 0160                                   |0120: move v0, v6
+00238a: 2900 f2fe                              |0121: goto/16 0013 // -010e
+00238e: 0d00                                   |0123: move-exception v0
+002390: 1e0a                                   |0124: monitor-exit v10
+002392: 2700                                   |0125: throw v0
+      catches       : 4
+        0x0007 - 0x000d
+          Ljava/lang/ClassCastException; -> 0x011c
+          <any> -> 0x0123
+        0x0015 - 0x00e9
+          Ljava/lang/ClassCastException; -> 0x011c
+          <any> -> 0x0123
+        0x00e9 - 0x0104
+          <any> -> 0x0119
+        0x0104 - 0x011c
+          Ljava/lang/ClassCastException; -> 0x011c
+          <any> -> 0x0123
+      positions     : 
+      locals        : 
+
+    #7              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(Lcom/google/android/checkers/CheckersView;)Z'
+      access        : 0x1008 (STATIC SYNTHETIC)
+      method_idx    : 89
+      code          -
+      registers     : 7
+      ins           : 1
+      outs          : 6
+      insns size    : 11 16-bit code units
+0023c0:                                        |[0023c0] com.google.android.checkers.CheckersView.a:(Lcom/google/android/checkers/CheckersView;)Z
+0023d0: 1201                                   |0000: const/4 v1, #int 0 // #0
+0023d2: 12f2                                   |0001: const/4 v2, #int -1 // #ff
+0023d4: 0760                                   |0002: move-object v0, v6
+0023d6: 0113                                   |0003: move v3, v1
+0023d8: 0114                                   |0004: move v4, v1
+0023da: 0115                                   |0005: move v5, v1
+0023dc: 7606 5b00 0000                         |0006: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/CheckersView;.a:(ZIIII)Z // method@005b
+0023e2: 0a00                                   |0009: move-result v0
+0023e4: 0f00                                   |000a: return v0
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #8              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(ZIIII)Z'
+      access        : 0x20012 (PRIVATE FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 91
+      code          -
+      registers     : 15
+      ins           : 6
+      outs          : 6
+      insns size    : 645 16-bit code units
+0023e8:                                        |[0023e8] com.google.android.checkers.CheckersView.a:(ZIIII)Z
+0023f8: 1232                                   |0000: const/4 v2, #int 3 // #3
+0023fa: 12f1                                   |0001: const/4 v1, #int -1 // #ff
+0023fc: 1223                                   |0002: const/4 v3, #int 2 // #2
+0023fe: 1216                                   |0003: const/4 v6, #int 1 // #1
+002400: 1207                                   |0004: const/4 v7, #int 0 // #0
+002402: 1d09                                   |0005: monitor-enter v9
+002404: 380a 1b00                              |0006: if-eqz v10, 0021 // +001b
+002408: 5290 1200                              |0008: iget v0, v9, Lcom/google/android/checkers/CheckersView;.Q:I // field@0012
+00240c: 3d00 1700                              |000a: if-lez v0, 0021 // +0017
+002410: 5290 1200                              |000c: iget v0, v9, Lcom/google/android/checkers/CheckersView;.Q:I // field@0012
+002414: 3330 2b00                              |000e: if-ne v0, v3, 0039 // +002b
+002418: 12eb                                   |0010: const/4 v11, #int -2 // #fe
+00241a: 5290 2300                              |0011: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+00241e: 3330 2800                              |0013: if-ne v0, v3, 003b // +0028
+002422: 0160                                   |0015: move v0, v6
+002424: 5990 2300                              |0016: iput v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002428: 5290 2c00                              |0018: iget v0, v9, Lcom/google/android/checkers/CheckersView;.z:I // field@002c
+00242c: 6e20 7000 0900                         |001a: invoke-virtual {v9, v0}, Lcom/google/android/checkers/CheckersView;.setLevel:(I)V // method@0070
+002432: 1200                                   |001d: const/4 v0, #int 0 // #0
+002434: 5990 1200                              |001e: iput v0, v9, Lcom/google/android/checkers/CheckersView;.Q:I // field@0012
+002438: 017a                                   |0020: move v10, v7
+00243a: 380a 8800                              |0021: if-eqz v10, 00a9 // +0088
+00243e: 7020 6200 b900                         |0023: invoke-direct {v9, v11}, Lcom/google/android/checkers/CheckersView;.c:(I)V // method@0062
+002444: 5290 2300                              |0026: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002448: 1252                                   |0028: const/4 v2, #int 5 // #5
+00244a: 3220 0d00                              |0029: if-eq v0, v2, 0036 // +000d
+00244e: 5290 2300                              |002b: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002452: 1262                                   |002d: const/4 v2, #int 6 // #6
+002454: 3220 0800                              |002e: if-eq v0, v2, 0036 // +0008
+002458: 390d 0d00                              |0030: if-nez v13, 003d // +000d
+00245c: 1a00 1301                              |0032: const-string v0, "random play" // string@0113
+002460: 5b90 0f00                              |0034: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+002464: 0160                                   |0036: move v0, v6
+002466: 1e09                                   |0037: monitor-exit v9
+002468: 0f00                                   |0038: return v0
+00246a: 011b                                   |0039: move v11, v1
+00246c: 28d7                                   |003a: goto 0011 // -0029
+00246e: 0120                                   |003b: move v0, v2
+002470: 28da                                   |003c: goto 0016 // -0026
+002472: 331d 0a00                              |003d: if-ne v13, v1, 0047 // +000a
+002476: 1a00 0801                              |003f: const-string v0, "only reply" // string@0108
+00247a: 5b90 0f00                              |0041: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+00247e: 28f3                                   |0043: goto 0036 // -000d
+002480: 0d00                                   |0044: move-exception v0
+002482: 1e09                                   |0045: monitor-exit v9
+002484: 2700                                   |0046: throw v0
+002486: 12e0                                   |0047: const/4 v0, #int -2 // #fe
+002488: 330d 0700                              |0048: if-ne v13, v0, 004f // +0007
+00248c: 1a00 0a01                              |004a: const-string v0, "opening" // string@010a
+002490: 5b90 0f00                              |004c: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+002494: 28e8                                   |004e: goto 0036 // -0018
+002496: 1300 0083                              |004f: const/16 v0, #int -32000 // #8300
+00249a: 360c 1800                              |0051: if-gt v12, v0, 0069 // +0018
+00249e: 2200 3000                              |0053: new-instance v0, Ljava/lang/StringBuilder; // type@0030
+0024a2: 1a01 f000                              |0055: const-string v1, "loss in #" // string@00f0
+0024a6: 7020 a600 1000                         |0057: invoke-direct {v0, v1}, Ljava/lang/StringBuilder;.<init>:(Ljava/lang/String;)V // method@00a6
+0024ac: d0c1 f47e                              |005a: add-int/lit16 v1, v12, #int 32500 // #7ef4
+0024b0: db01 0102                              |005c: div-int/lit8 v1, v1, #int 2 // #02
+0024b4: 6e20 a700 1000                         |005e: invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+0024ba: 0c00                                   |0061: move-result-object v0
+0024bc: 6e10 aa00 0000                         |0062: invoke-virtual {v0}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00aa
+0024c2: 0c00                                   |0065: move-result-object v0
+0024c4: 5b90 0f00                              |0066: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+0024c8: 28ce                                   |0068: goto 0036 // -0032
+0024ca: 1300 007d                              |0069: const/16 v0, #int 32000 // #7d00
+0024ce: 340c 1800                              |006b: if-lt v12, v0, 0083 // +0018
+0024d2: 2200 3000                              |006d: new-instance v0, Ljava/lang/StringBuilder; // type@0030
+0024d6: 1a01 3d01                              |006f: const-string v1, "win in #" // string@013d
+0024da: 7020 a600 1000                         |0071: invoke-direct {v0, v1}, Ljava/lang/StringBuilder;.<init>:(Ljava/lang/String;)V // method@00a6
+0024e0: d1c1 f47e                              |0074: rsub-int v1, v12, #int 32500 // #7ef4
+0024e4: db01 0102                              |0076: div-int/lit8 v1, v1, #int 2 // #02
+0024e8: 6e20 a700 1000                         |0078: invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+0024ee: 0c00                                   |007b: move-result-object v0
+0024f0: 6e10 aa00 0000                         |007c: invoke-virtual {v0}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00aa
+0024f6: 0c00                                   |007f: move-result-object v0
+0024f8: 5b90 0f00                              |0080: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+0024fc: 28b4                                   |0082: goto 0036 // -004c
+0024fe: 2200 3000                              |0083: new-instance v0, Ljava/lang/StringBuilder; // type@0030
+002502: 1a01 3901                              |0085: const-string v1, "v=" // string@0139
+002506: 7020 a600 1000                         |0087: invoke-direct {v0, v1}, Ljava/lang/StringBuilder;.<init>:(Ljava/lang/String;)V // method@00a6
+00250c: 6e20 a700 c000                         |008a: invoke-virtual {v0, v12}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+002512: 0c00                                   |008d: move-result-object v0
+002514: 1a01 0000                              |008e: const-string v1, " d=" // string@0000
+002518: 6e20 a900 1000                         |0090: invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00a9
+00251e: 0c00                                   |0093: move-result-object v0
+002520: 6e20 a700 d000                         |0094: invoke-virtual {v0, v13}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+002526: 0c00                                   |0097: move-result-object v0
+002528: 1a01 0100                              |0098: const-string v1, " n=" // string@0001
+00252c: 6e20 a900 1000                         |009a: invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00a9
+002532: 0c00                                   |009d: move-result-object v0
+002534: 6e20 a700 e000                         |009e: invoke-virtual {v0, v14}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+00253a: 0c00                                   |00a1: move-result-object v0
+00253c: 6e10 aa00 0000                         |00a2: invoke-virtual {v0}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00aa
+002542: 0c00                                   |00a5: move-result-object v0
+002544: 5b90 0f00                              |00a6: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+002548: 288e                                   |00a8: goto 0036 // -0072
+00254a: 12d0                                   |00a9: const/4 v0, #int -3 // #fd
+00254c: 330b 3000                              |00aa: if-ne v11, v0, 00da // +0030
+002550: 2200 0500                              |00ac: new-instance v0, Landroid/app/AlertDialog$Builder; // type@0005
+002554: 5491 1300                              |00ae: iget-object v1, v9, Lcom/google/android/checkers/CheckersView;.a:Landroid/content/Context; // field@0013
+002558: 7020 0900 1000                         |00b0: invoke-direct {v0, v1}, Landroid/app/AlertDialog$Builder;.<init>:(Landroid/content/Context;)V // method@0009
+00255e: 1a01 7f00                              |00b3: const-string v1, "Start a new game?" // string@007f
+002562: 6e20 0c00 1000                         |00b5: invoke-virtual {v0, v1}, Landroid/app/AlertDialog$Builder;.setMessage:(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder; // method@000c
+002568: 0c00                                   |00b8: move-result-object v0
+00256a: 1201                                   |00b9: const/4 v1, #int 0 // #0
+00256c: 6e20 0a00 1000                         |00ba: invoke-virtual {v0, v1}, Landroid/app/AlertDialog$Builder;.setCancelable:(Z)Landroid/app/AlertDialog$Builder; // method@000a
+002572: 0c00                                   |00bd: move-result-object v0
+002574: 1a01 9e00                              |00be: const-string v1, "Yes" // string@009e
+002578: 2202 2100                              |00c0: new-instance v2, Lcom/google/android/checkers/b; // type@0021
+00257c: 7020 8f00 9200                         |00c2: invoke-direct {v2, v9}, Lcom/google/android/checkers/b;.<init>:(Lcom/google/android/checkers/CheckersView;)V // method@008f
+002582: 6e30 0e00 1002                         |00c5: invoke-virtual {v0, v1, v2}, Landroid/app/AlertDialog$Builder;.setPositiveButton:(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder; // method@000e
+002588: 0c00                                   |00c8: move-result-object v0
+00258a: 1a01 7500                              |00c9: const-string v1, "No" // string@0075
+00258e: 2202 2200                              |00cb: new-instance v2, Lcom/google/android/checkers/c; // type@0022
+002592: 7020 9100 9200                         |00cd: invoke-direct {v2, v9}, Lcom/google/android/checkers/c;.<init>:(Lcom/google/android/checkers/CheckersView;)V // method@0091
+002598: 6e30 0d00 1002                         |00d0: invoke-virtual {v0, v1, v2}, Landroid/app/AlertDialog$Builder;.setNegativeButton:(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder; // method@000d
+00259e: 0c00                                   |00d3: move-result-object v0
+0025a0: 6e10 1000 0000                         |00d4: invoke-virtual {v0}, Landroid/app/AlertDialog$Builder;.show:()Landroid/app/AlertDialog; // method@0010
+0025a6: 0160                                   |00d7: move v0, v6
+0025a8: 2900 5fff                              |00d8: goto/16 0037 // -00a1
+0025ac: 331b 5b00                              |00da: if-ne v11, v1, 0135 // +005b
+0025b0: 5290 2300                              |00dc: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+0025b4: 3230 0700                              |00de: if-eq v0, v3, 00e5 // +0007
+0025b8: 5290 2300                              |00e0: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+0025bc: 1241                                   |00e2: const/4 v1, #int 4 // #4
+0025be: 3310 1100                              |00e3: if-ne v0, v1, 00f4 // +0011
+0025c2: 1210                                   |00e5: const/4 v0, #int 1 // #1
+0025c4: 5990 1200                              |00e6: iput v0, v9, Lcom/google/android/checkers/CheckersView;.Q:I // field@0012
+0025c8: 5490 2200                              |00e8: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+0025cc: 1211                                   |00ea: const/4 v1, #int 1 // #1
+0025ce: 5901 4100                              |00eb: iput v1, v0, Lcom/google/android/checkers/a;.h:I // field@0041
+0025d2: 1a00 3201                              |00ed: const-string v0, "stopping...." // string@0132
+0025d6: 5b90 0f00                              |00ef: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+0025da: 0160                                   |00f1: move v0, v6
+0025dc: 2900 45ff                              |00f2: goto/16 0037 // -00bb
+0025e0: 1200                                   |00f4: const/4 v0, #int 0 // #0
+0025e2: 5990 1200                              |00f5: iput v0, v9, Lcom/google/android/checkers/CheckersView;.Q:I // field@0012
+0025e6: 5490 2200                              |00f7: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+0025ea: 6e10 7b00 0000                         |00f9: invoke-virtual {v0}, Lcom/google/android/checkers/a;.a:()V // method@007b
+0025f0: 1210                                   |00fc: const/4 v0, #int 1 // #1
+0025f2: 5990 2300                              |00fd: iput v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+0025f6: 5490 2200                              |00ff: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+0025fa: 5200 3d00                              |0101: iget v0, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+0025fe: 5990 2400                              |0103: iput v0, v9, Lcom/google/android/checkers/CheckersView;.r:I // field@0024
+002602: 5490 2200                              |0105: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002606: 5200 3f00                              |0107: iget v0, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+00260a: 5990 2500                              |0109: iput v0, v9, Lcom/google/android/checkers/CheckersView;.s:I // field@0025
+00260e: 5490 2200                              |010b: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002612: 5200 3e00                              |010d: iget v0, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+002616: 5990 2600                              |010f: iput v0, v9, Lcom/google/android/checkers/CheckersView;.t:I // field@0026
+00261a: 5490 2200                              |0111: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+00261e: 5200 4000                              |0113: iget v0, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+002622: 5990 2700                              |0115: iput v0, v9, Lcom/google/android/checkers/CheckersView;.u:I // field@0027
+002626: 1200                                   |0117: const/4 v0, #int 0 // #0
+002628: 5990 2800                              |0118: iput v0, v9, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+00262c: 1200                                   |011a: const/4 v0, #int 0 // #0
+00262e: 5990 2900                              |011b: iput v0, v9, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+002632: 1200                                   |011d: const/4 v0, #int 0 // #0
+002634: 5990 2a00                              |011e: iput v0, v9, Lcom/google/android/checkers/CheckersView;.x:I // field@002a
+002638: 1200                                   |0120: const/4 v0, #int 0 // #0
+00263a: 5c90 2b00                              |0121: iput-boolean v0, v9, Lcom/google/android/checkers/CheckersView;.y:Z // field@002b
+00263e: 1200                                   |0123: const/4 v0, #int 0 // #0
+002640: 5990 0c00                              |0124: iput v0, v9, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+002644: 1200                                   |0126: const/4 v0, #int 0 // #0
+002646: 5990 0d00                              |0127: iput v0, v9, Lcom/google/android/checkers/CheckersView;.L:I // field@000d
+00264a: 5490 2200                              |0129: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+00264e: 5200 3c00                              |012b: iget v0, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+002652: 5990 0e00                              |012d: iput v0, v9, Lcom/google/android/checkers/CheckersView;.M:I // field@000e
+002656: 1200                                   |012f: const/4 v0, #int 0 // #0
+002658: 5b90 0f00                              |0130: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+00265c: 0160                                   |0132: move v0, v6
+00265e: 2900 04ff                              |0133: goto/16 0037 // -00fc
+002662: 12e0                                   |0135: const/4 v0, #int -2 // #fe
+002664: 330b b100                              |0136: if-ne v11, v0, 01e7 // +00b1
+002668: 1200                                   |0138: const/4 v0, #int 0 // #0
+00266a: 5990 2800                              |0139: iput v0, v9, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+00266e: 1200                                   |013b: const/4 v0, #int 0 // #0
+002670: 5990 2900                              |013c: iput v0, v9, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+002674: 1200                                   |013e: const/4 v0, #int 0 // #0
+002676: 5990 2a00                              |013f: iput v0, v9, Lcom/google/android/checkers/CheckersView;.x:I // field@002a
+00267a: 5290 2300                              |0141: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+00267e: 3230 0700                              |0143: if-eq v0, v3, 014a // +0007
+002682: 5290 2300                              |0145: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002686: 1241                                   |0147: const/4 v1, #int 4 // #4
+002688: 3310 1100                              |0148: if-ne v0, v1, 0159 // +0011
+00268c: 1220                                   |014a: const/4 v0, #int 2 // #2
+00268e: 5990 1200                              |014b: iput v0, v9, Lcom/google/android/checkers/CheckersView;.Q:I // field@0012
+002692: 5490 2200                              |014d: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002696: 1211                                   |014f: const/4 v1, #int 1 // #1
+002698: 5901 4100                              |0150: iput v1, v0, Lcom/google/android/checkers/a;.h:I // field@0041
+00269c: 1a00 3201                              |0152: const-string v0, "stopping...." // string@0132
+0026a0: 5b90 0f00                              |0154: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+0026a4: 0160                                   |0156: move v0, v6
+0026a6: 2900 e0fe                              |0157: goto/16 0037 // -0120
+0026aa: 1200                                   |0159: const/4 v0, #int 0 // #0
+0026ac: 5990 1200                              |015a: iput v0, v9, Lcom/google/android/checkers/CheckersView;.Q:I // field@0012
+0026b0: 5290 2300                              |015c: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+0026b4: 3260 7600                              |015e: if-eq v0, v6, 01d4 // +0076
+0026b8: 5290 2300                              |0160: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+0026bc: 1251                                   |0162: const/4 v1, #int 5 // #5
+0026be: 3210 7100                              |0163: if-eq v0, v1, 01d4 // +0071
+0026c2: 0175                                   |0165: move v5, v7
+0026c4: 5290 0d00                              |0166: iget v0, v9, Lcom/google/android/checkers/CheckersView;.L:I // field@000d
+0026c8: 3d00 7200                              |0168: if-lez v0, 01da // +0072
+0026cc: 5290 0d00                              |016a: iget v0, v9, Lcom/google/android/checkers/CheckersView;.L:I // field@000d
+0026d0: d800 00ff                              |016c: add-int/lit8 v0, v0, #int -1 // #ff
+0026d4: 5990 0d00                              |016e: iput v0, v9, Lcom/google/android/checkers/CheckersView;.L:I // field@000d
+0026d8: 5290 0c00                              |0170: iget v0, v9, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+0026dc: 3d00 6400                              |0172: if-lez v0, 01d6 // +0064
+0026e0: 5290 0c00                              |0174: iget v0, v9, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+0026e4: d800 00ff                              |0176: add-int/lit8 v0, v0, #int -1 // #ff
+0026e8: 5990 0c00                              |0178: iput v0, v9, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+0026ec: 5294 0c00                              |017a: iget v4, v9, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+0026f0: 5490 2200                              |017c: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+0026f4: 5491 0800                              |017e: iget-object v1, v9, Lcom/google/android/checkers/CheckersView;.G:[I // field@0008
+0026f8: 4401 0104                              |0180: aget v1, v1, v4
+0026fc: 5492 0900                              |0182: iget-object v2, v9, Lcom/google/android/checkers/CheckersView;.H:[I // field@0009
+002700: 4402 0204                              |0184: aget v2, v2, v4
+002704: 5493 0a00                              |0186: iget-object v3, v9, Lcom/google/android/checkers/CheckersView;.I:[I // field@000a
+002708: 4403 0304                              |0188: aget v3, v3, v4
+00270c: 5498 0b00                              |018a: iget-object v8, v9, Lcom/google/android/checkers/CheckersView;.J:[I // field@000b
+002710: 4404 0804                              |018c: aget v4, v8, v4
+002714: 7406 8000 0000                         |018e: invoke-virtual/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIIZ)V // method@0080
+00271a: 0160                                   |0191: move v0, v6
+00271c: 3800 4e00                              |0192: if-eqz v0, 01e0 // +004e
+002720: 3805 4800                              |0194: if-eqz v5, 01dc // +0048
+002724: 1230                                   |0196: const/4 v0, #int 3 // #3
+002726: 5990 2300                              |0197: iput v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+00272a: 5490 2200                              |0199: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+00272e: 5200 3d00                              |019b: iget v0, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+002732: 5990 2400                              |019d: iput v0, v9, Lcom/google/android/checkers/CheckersView;.r:I // field@0024
+002736: 5490 2200                              |019f: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+00273a: 5200 3f00                              |01a1: iget v0, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+00273e: 5990 2500                              |01a3: iput v0, v9, Lcom/google/android/checkers/CheckersView;.s:I // field@0025
+002742: 5490 2200                              |01a5: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002746: 5200 3e00                              |01a7: iget v0, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+00274a: 5990 2600                              |01a9: iput v0, v9, Lcom/google/android/checkers/CheckersView;.t:I // field@0026
+00274e: 5490 2200                              |01ab: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002752: 5200 4000                              |01ad: iget v0, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+002756: 5990 2700                              |01af: iput v0, v9, Lcom/google/android/checkers/CheckersView;.u:I // field@0027
+00275a: 1200                                   |01b1: const/4 v0, #int 0 // #0
+00275c: 5990 2800                              |01b2: iput v0, v9, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+002760: 1200                                   |01b4: const/4 v0, #int 0 // #0
+002762: 5990 2900                              |01b5: iput v0, v9, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+002766: 1200                                   |01b7: const/4 v0, #int 0 // #0
+002768: 5990 2a00                              |01b8: iput v0, v9, Lcom/google/android/checkers/CheckersView;.x:I // field@002a
+00276c: 5490 2200                              |01ba: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002770: 5591 0300                              |01bc: iget-boolean v1, v9, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+002774: 6e30 7a00 5001                         |01be: invoke-virtual {v0, v5, v1}, Lcom/google/android/checkers/a;.a:(ZZ)I // method@007a
+00277a: 0a00                                   |01c1: move-result v0
+00277c: 3360 0300                              |01c2: if-ne v0, v6, 01c5 // +0003
+002780: 0167                                   |01c4: move v7, v6
+002782: 5c97 2b00                              |01c5: iput-boolean v7, v9, Lcom/google/android/checkers/CheckersView;.y:Z // field@002b
+002786: 5490 2200                              |01c7: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+00278a: 5200 3c00                              |01c9: iget v0, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+00278e: 5990 0e00                              |01cb: iput v0, v9, Lcom/google/android/checkers/CheckersView;.M:I // field@000e
+002792: 1a00 3701                              |01cd: const-string v0, "undid half-move" // string@0137
+002796: 5b90 0f00                              |01cf: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+00279a: 0160                                   |01d1: move v0, v6
+00279c: 2900 65fe                              |01d2: goto/16 0037 // -019b
+0027a0: 0165                                   |01d4: move v5, v6
+0027a2: 2891                                   |01d5: goto 0166 // -006f
+0027a4: 1270                                   |01d6: const/4 v0, #int 7 // #7
+0027a6: 5990 0c00                              |01d7: iput v0, v9, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+0027aa: 28a1                                   |01d9: goto 017a // -005f
+0027ac: 0170                                   |01da: move v0, v7
+0027ae: 28b7                                   |01db: goto 0192 // -0049
+0027b0: 1210                                   |01dc: const/4 v0, #int 1 // #1
+0027b2: 5990 2300                              |01dd: iput v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+0027b6: 28ba                                   |01df: goto 0199 // -0046
+0027b8: 1a00 f900                              |01e0: const-string v0, "no more undo" // string@00f9
+0027bc: 5b90 0f00                              |01e2: iput-object v0, v9, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+0027c0: 0160                                   |01e4: move v0, v6
+0027c2: 2900 52fe                              |01e5: goto/16 0037 // -01ae
+0027c6: 12c0                                   |01e7: const/4 v0, #int -4 // #fc
+0027c8: 330b 4c00                              |01e8: if-ne v11, v0, 0234 // +004c
+0027cc: 5290 2300                              |01ea: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+0027d0: 3360 2300                              |01ec: if-ne v0, v6, 020f // +0023
+0027d4: 1220                                   |01ee: const/4 v0, #int 2 // #2
+0027d6: 5990 2300                              |01ef: iput v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+0027da: 5490 2200                              |01f1: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+0027de: 1201                                   |01f3: const/4 v1, #int 0 // #0
+0027e0: 5592 0300                              |01f4: iget-boolean v2, v9, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+0027e4: 6e30 8700 1002                         |01f6: invoke-virtual {v0, v1, v2}, Lcom/google/android/checkers/a;.b:(ZZ)V // method@0087
+0027ea: 5491 1300                              |01f9: iget-object v1, v9, Lcom/google/android/checkers/CheckersView;.a:Landroid/content/Context; // field@0013
+0027ee: 5590 0400                              |01fb: iget-boolean v0, v9, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+0027f2: 3800 0f00                              |01fd: if-eqz v0, 020c // +000f
+0027f6: 1a00 bf00                              |01ff: const-string v0, "computer now plays black" // string@00bf
+0027fa: 1202                                   |0201: const/4 v2, #int 0 // #0
+0027fc: 7130 3c00 0102                         |0202: invoke-static {v1, v0, v2}, Landroid/widget/Toast;.makeText:(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; // method@003c
+002802: 0c00                                   |0205: move-result-object v0
+002804: 6e10 3d00 0000                         |0206: invoke-virtual {v0}, Landroid/widget/Toast;.show:()V // method@003d
+00280a: 0160                                   |0209: move v0, v6
+00280c: 2900 2dfe                              |020a: goto/16 0037 // -01d3
+002810: 1a00 c000                              |020c: const-string v0, "computer now plays black
+goto options to rotate board" // string@00c0
+002814: 28f3                                   |020e: goto 0201 // -000d
+002816: 5290 2300                              |020f: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+00281a: 3320 6f00                              |0211: if-ne v0, v2, 0280 // +006f
+00281e: 1240                                   |0213: const/4 v0, #int 4 // #4
+002820: 5990 2300                              |0214: iput v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002824: 5490 2200                              |0216: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002828: 1211                                   |0218: const/4 v1, #int 1 // #1
+00282a: 5592 0300                              |0219: iget-boolean v2, v9, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+00282e: 6e30 8700 1002                         |021b: invoke-virtual {v0, v1, v2}, Lcom/google/android/checkers/a;.b:(ZZ)V // method@0087
+002834: 5491 1300                              |021e: iget-object v1, v9, Lcom/google/android/checkers/CheckersView;.a:Landroid/content/Context; // field@0013
+002838: 5590 0400                              |0220: iget-boolean v0, v9, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+00283c: 3800 0f00                              |0222: if-eqz v0, 0231 // +000f
+002840: 1a00 c200                              |0224: const-string v0, "computer now plays white
+goto options to rotate board" // string@00c2
+002844: 1202                                   |0226: const/4 v2, #int 0 // #0
+002846: 7130 3c00 0102                         |0227: invoke-static {v1, v0, v2}, Landroid/widget/Toast;.makeText:(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; // method@003c
+00284c: 0c00                                   |022a: move-result-object v0
+00284e: 6e10 3d00 0000                         |022b: invoke-virtual {v0}, Landroid/widget/Toast;.show:()V // method@003d
+002854: 0160                                   |022e: move v0, v6
+002856: 2900 08fe                              |022f: goto/16 0037 // -01f8
+00285a: 1a00 c100                              |0231: const-string v0, "computer now plays white" // string@00c1
+00285e: 28f3                                   |0233: goto 0226 // -000d
+002860: 336b 4c00                              |0234: if-ne v11, v6, 0280 // +004c
+002864: 5290 2300                              |0236: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002868: 3260 0600                              |0238: if-eq v0, v6, 023e // +0006
+00286c: 5290 2300                              |023a: iget v0, v9, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002870: 3320 4400                              |023c: if-ne v0, v2, 0280 // +0044
+002874: 1200                                   |023e: const/4 v0, #int 0 // #0
+002876: 5990 2900                              |023f: iput v0, v9, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+00287a: 1200                                   |0241: const/4 v0, #int 0 // #0
+00287c: 5990 2a00                              |0242: iput v0, v9, Lcom/google/android/checkers/CheckersView;.x:I // field@002a
+002880: 5490 2200                              |0244: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002884: 5204 3c00                              |0246: iget v4, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+002888: 5490 2200                              |0248: iget-object v0, v9, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+00288c: 5405 3b00                              |024a: iget-object v5, v0, Lcom/google/android/checkers/a;.b:[I // field@003b
+002890: 0172                                   |024c: move v2, v7
+002892: 0170                                   |024d: move v0, v7
+002894: 0173                                   |024e: move v3, v7
+002896: 3442 0a00                              |024f: if-lt v2, v4, 0259 // +000a
+00289a: 3363 2500                              |0251: if-ne v3, v6, 0276 // +0025
+00289e: 7020 6200 1900                         |0253: invoke-direct {v9, v1}, Lcom/google/android/checkers/CheckersView;.c:(I)V // method@0062
+0028a4: 0160                                   |0256: move v0, v6
+0028a6: 2900 e0fd                              |0257: goto/16 0037 // -0220
+0028aa: 5297 2800                              |0259: iget v7, v9, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+0028ae: 4408 0502                              |025b: aget v8, v5, v2
+0028b2: b587                                   |025d: and-int/2addr v7, v8
+0028b4: 5298 2800                              |025e: iget v8, v9, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+0028b8: 3387 1300                              |0260: if-ne v7, v8, 0273 // +0013
+0028bc: 4401 0502                              |0262: aget v1, v5, v2
+0028c0: 3201 1f00                              |0264: if-eq v1, v0, 0283 // +001f
+0028c4: d801 0301                              |0266: add-int/lit8 v1, v3, #int 1 // #01
+0028c8: 4400 0502                              |0268: aget v0, v5, v2
+0028cc: 5293 2900                              |026a: iget v3, v9, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+0028d0: 4407 0502                              |026c: aget v7, v5, v2
+0028d4: b673                                   |026e: or-int/2addr v3, v7
+0028d6: 5993 2900                              |026f: iput v3, v9, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+0028da: 0113                                   |0271: move v3, v1
+0028dc: 0121                                   |0272: move v1, v2
+0028de: d802 0201                              |0273: add-int/lit8 v2, v2, #int 1 // #01
+0028e2: 28da                                   |0275: goto 024f // -0026
+0028e4: 5290 2900                              |0276: iget v0, v9, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+0028e8: 3900 0500                              |0278: if-nez v0, 027d // +0005
+0028ec: 1200                                   |027a: const/4 v0, #int 0 // #0
+0028ee: 5990 2800                              |027b: iput v0, v9, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+0028f2: 0160                                   |027d: move v0, v6
+0028f4: 2900 b9fd                              |027e: goto/16 0037 // -0247
+0028f8: 0170                                   |0280: move v0, v7
+0028fa: 2900 b6fd                              |0281: goto/16 0037 // -024a
+0028fe: 0131                                   |0283: move v1, v3
+002900: 28e4                                   |0284: goto 0268 // -001c
+      catches       : 3
+        0x0008 - 0x0036
+          <any> -> 0x0044
+        0x003f - 0x0043
+          <any> -> 0x0044
+        0x004a - 0x027d
+          <any> -> 0x0044
+      positions     : 
+      locals        : 
+
+    #9              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'b'
+      type          : '(FF)I'
+      access        : 0x20012 (PRIVATE FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 92
+      code          -
+      registers     : 13
+      ins           : 3
+      outs          : 1
+      insns size    : 102 16-bit code units
+002920:                                        |[002920] com.google.android.checkers.CheckersView.b:(FF)I
+002930: 1309 0800                              |0000: const/16 v9, #int 8 // #8
+002934: 1201                                   |0002: const/4 v1, #int 0 // #0
+002936: 1210                                   |0003: const/4 v0, #int 1 // #1
+002938: 1d0a                                   |0004: monitor-enter v10
+00293a: 6e10 6a00 0a00                         |0005: invoke-virtual {v10}, Lcom/google/android/checkers/CheckersView;.getWidth:()I // method@006a
+002940: 0a02                                   |0008: move-result v2
+002942: 6e10 6900 0a00                         |0009: invoke-virtual {v10}, Lcom/google/android/checkers/CheckersView;.getHeight:()I // method@0069
+002948: 0a03                                   |000c: move-result v3
+00294a: 3532 1400                              |000d: if-ge v2, v3, 0021 // +0014
+00294e: e207 0203                              |000f: ushr-int/lit8 v7, v2, #int 3 // #03
+002952: 52a2 2300                              |0011: iget v2, v10, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002956: 3202 0700                              |0013: if-eq v2, v0, 001a // +0007
+00295a: 52a2 2300                              |0015: iget v2, v10, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+00295e: 1233                                   |0017: const/4 v3, #int 3 // #3
+002960: 3332 0600                              |0018: if-ne v2, v3, 001e // +0006
+002964: 0116                                   |001a: move v6, v1
+002966: 0103                                   |001b: move v3, v0
+002968: 3496 0700                              |001c: if-lt v6, v9, 0023 // +0007
+00296c: 0110                                   |001e: move v0, v1
+00296e: 1e0a                                   |001f: monitor-exit v10
+002970: 0f00                                   |0020: return v0
+002972: 0132                                   |0021: move v2, v3
+002974: 28ed                                   |0022: goto 000f // -0013
+002976: d902 0601                              |0023: rsub-int/lit8 v2, v6, #int 1 // #01
+00297a: dd02 0201                              |0025: and-int/lit8 v2, v2, #int 1 // #01
+00297e: 0124                                   |0027: move v4, v2
+002980: 0135                                   |0028: move v5, v3
+002982: 3494 0700                              |0029: if-lt v4, v9, 0030 // +0007
+002986: d802 0601                              |002b: add-int/lit8 v2, v6, #int 1 // #01
+00298a: 0126                                   |002d: move v6, v2
+00298c: 0153                                   |002e: move v3, v5
+00298e: 28ed                                   |002f: goto 001c // -0013
+002990: 55a2 0400                              |0030: iget-boolean v2, v10, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+002994: 3802 2800                              |0032: if-eqz v2, 005a // +0028
+002998: d902 0407                              |0034: rsub-int/lit8 v2, v4, #int 7 // #07
+00299c: 9203 0702                              |0036: mul-int v3, v7, v2
+0029a0: d902 0607                              |0038: rsub-int/lit8 v2, v6, #int 7 // #07
+0029a4: b272                                   |003a: mul-int/2addr v2, v7
+0029a6: 8238                                   |003b: int-to-float v8, v3
+0029a8: 2e08 080b                              |003c: cmpg-float v8, v8, v11
+0029ac: 3c08 2100                              |003e: if-gtz v8, 005f // +0021
+0029b0: b073                                   |0040: add-int/2addr v3, v7
+0029b2: 8233                                   |0041: int-to-float v3, v3
+0029b4: 2e03 0b03                              |0042: cmpg-float v3, v11, v3
+0029b8: 3b03 1b00                              |0044: if-gez v3, 005f // +001b
+0029bc: 8223                                   |0046: int-to-float v3, v2
+0029be: 2e03 030c                              |0047: cmpg-float v3, v3, v12
+0029c2: 3c03 1600                              |0049: if-gtz v3, 005f // +0016
+0029c6: b072                                   |004b: add-int/2addr v2, v7
+0029c8: 8222                                   |004c: int-to-float v2, v2
+0029ca: 2e02 0c02                              |004d: cmpg-float v2, v12, v2
+0029ce: 3b02 1000                              |004f: if-gez v2, 005f // +0010
+0029d2: 52a1 2800                              |0051: iget v1, v10, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+0029d6: b651                                   |0053: or-int/2addr v1, v5
+0029d8: 59a1 2800                              |0054: iput v1, v10, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+0029dc: 28c9                                   |0056: goto 001f // -0037
+0029de: 0d00                                   |0057: move-exception v0
+0029e0: 1e0a                                   |0058: monitor-exit v10
+0029e2: 2700                                   |0059: throw v0
+0029e4: 9203 0704                              |005a: mul-int v3, v7, v4
+0029e8: 9202 0706                              |005c: mul-int v2, v7, v6
+0029ec: 28dd                                   |005e: goto 003b // -0023
+0029ee: e003 0501                              |005f: shl-int/lit8 v3, v5, #int 1 // #01
+0029f2: d802 0402                              |0061: add-int/lit8 v2, v4, #int 2 // #02
+0029f6: 0124                                   |0063: move v4, v2
+0029f8: 0135                                   |0064: move v5, v3
+0029fa: 28c4                                   |0065: goto 0029 // -003c
+      catches       : 2
+        0x0005 - 0x0017
+          <any> -> 0x0057
+        0x0030 - 0x0056
+          <any> -> 0x0057
+      positions     : 
+      locals        : 
+
+    #10              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'b'
+      type          : '(I)V'
+      access        : 0x20012 (PRIVATE FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 94
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 1
+      insns size    : 18 16-bit code units
+002a10:                                        |[002a10] com.google.android.checkers.CheckersView.b:(I)V
+002a20: 1d01                                   |0000: monitor-enter v1
+002a22: 5210 0700                              |0001: iget v0, v1, Lcom/google/android/checkers/CheckersView;.F:I // field@0007
+002a26: 3220 0a00                              |0003: if-eq v0, v2, 000d // +000a
+002a2a: 5912 0700                              |0005: iput v2, v1, Lcom/google/android/checkers/CheckersView;.F:I // field@0007
+002a2e: 7010 6400 0100                         |0007: invoke-direct {v1}, Lcom/google/android/checkers/CheckersView;.d:()V // method@0064
+002a34: 6e10 6d00 0100                         |000a: invoke-virtual {v1}, Lcom/google/android/checkers/CheckersView;.postInvalidate:()V // method@006d
+002a3a: 1e01                                   |000d: monitor-exit v1
+002a3c: 0e00                                   |000e: return-void
+002a3e: 0d00                                   |000f: move-exception v0
+002a40: 1e01                                   |0010: monitor-exit v1
+002a42: 2700                                   |0011: throw v0
+      catches       : 1
+        0x0001 - 0x000d
+          <any> -> 0x000f
+      positions     : 
+      locals        : 
+
+    #11              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'b'
+      type          : '(Landroid/graphics/Canvas;IIII)V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 95
+      code          -
+      registers     : 16
+      ins           : 6
+      outs          : 6
+      insns size    : 99 16-bit code units
+002a50:                                        |[002a50] com.google.android.checkers.CheckersView.b:(Landroid/graphics/Canvas;IIII)V
+002a60: df00 0cff                              |0000: xor-int/lit8 v0, v12, #int -1 // #ff
+002a64: b5d0                                   |0002: and-int/2addr v0, v13
+002a66: 3900 5e00                              |0003: if-nez v0, 0061 // +005e
+002a6a: 7110 9f00 0c00                         |0005: invoke-static {v12}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+002a70: 0a02                                   |0008: move-result v2
+002a72: d800 0cff                              |0009: add-int/lit8 v0, v12, #int -1 // #ff
+002a76: b5c0                                   |000b: and-int/2addr v0, v12
+002a78: 7110 9f00 0000                         |000c: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+002a7e: 0a03                                   |000f: move-result v3
+002a80: 07a0                                   |0010: move-object v0, v10
+002a82: 07b1                                   |0011: move-object v1, v11
+002a84: 01e4                                   |0012: move v4, v14
+002a86: 01f5                                   |0013: move v5, v15
+002a88: 7606 5400 0000                         |0014: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/graphics/Canvas;IIII)V // method@0054
+002a8e: 0e00                                   |0017: return-void
+002a90: 7110 9f00 0800                         |0018: invoke-static {v8}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+002a96: 0a03                                   |001b: move-result v3
+002a98: e200 0302                              |001c: ushr-int/lit8 v0, v3, #int 2 // #02
+002a9c: dd00 0001                              |001e: and-int/lit8 v0, v0, #int 1 // #01
+002aa0: 3800 3600                              |0020: if-eqz v0, 0056 // +0036
+002aa4: d802 03fb                              |0022: add-int/lit8 v2, v3, #int -5 // #fb
+002aa8: d801 03fc                              |0024: add-int/lit8 v1, v3, #int -4 // #fc
+002aac: d800 0303                              |0026: add-int/lit8 v0, v3, #int 3 // #03
+002ab0: d803 0304                              |0028: add-int/lit8 v3, v3, #int 4 // #04
+002ab4: 0106                                   |002a: move v6, v0
+002ab6: 0117                                   |002b: move v7, v1
+002ab8: 1210                                   |002c: const/4 v0, #int 1 // #1
+002aba: b820                                   |002d: shl-int/2addr v0, v2
+002abc: 1211                                   |002e: const/4 v1, #int 1 // #1
+002abe: b831                                   |002f: shl-int/2addr v1, v3
+002ac0: b610                                   |0030: or-int/2addr v0, v1
+002ac2: 1211                                   |0031: const/4 v1, #int 1 // #1
+002ac4: b871                                   |0032: shl-int/2addr v1, v7
+002ac6: 1214                                   |0033: const/4 v4, #int 1 // #1
+002ac8: b864                                   |0034: shl-int/2addr v4, v6
+002aca: 9609 0104                              |0035: or-int v9, v1, v4
+002ace: 9501 000c                              |0037: and-int v1, v0, v12
+002ad2: 3301 0900                              |0039: if-ne v1, v0, 0042 // +0009
+002ad6: 07a0                                   |003b: move-object v0, v10
+002ad8: 07b1                                   |003c: move-object v1, v11
+002ada: 01e4                                   |003d: move v4, v14
+002adc: 01f5                                   |003e: move v5, v15
+002ade: 7606 5400 0000                         |003f: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/graphics/Canvas;IIII)V // method@0054
+002ae4: 9500 090c                              |0042: and-int v0, v9, v12
+002ae8: 3390 0b00                              |0044: if-ne v0, v9, 004f // +000b
+002aec: 07a0                                   |0046: move-object v0, v10
+002aee: 07b1                                   |0047: move-object v1, v11
+002af0: 0172                                   |0048: move v2, v7
+002af2: 0163                                   |0049: move v3, v6
+002af4: 01e4                                   |004a: move v4, v14
+002af6: 01f5                                   |004b: move v5, v15
+002af8: 7606 5400 0000                         |004c: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/graphics/Canvas;IIII)V // method@0054
+002afe: d800 08ff                              |004f: add-int/lit8 v0, v8, #int -1 // #ff
+002b02: b580                                   |0051: and-int/2addr v0, v8
+002b04: 0108                                   |0052: move v8, v0
+002b06: 3908 c5ff                              |0053: if-nez v8, 0018 // -003b
+002b0a: 28c2                                   |0055: goto 0017 // -003e
+002b0c: d802 03fc                              |0056: add-int/lit8 v2, v3, #int -4 // #fc
+002b10: d801 03fd                              |0058: add-int/lit8 v1, v3, #int -3 // #fd
+002b14: d800 0304                              |005a: add-int/lit8 v0, v3, #int 4 // #04
+002b18: d803 0305                              |005c: add-int/lit8 v3, v3, #int 5 // #05
+002b1c: 0106                                   |005e: move v6, v0
+002b1e: 0117                                   |005f: move v7, v1
+002b20: 28cc                                   |0060: goto 002c // -0034
+002b22: 0108                                   |0061: move v8, v0
+002b24: 28f1                                   |0062: goto 0053 // -000f
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #12              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'c'
+      type          : '(I)V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 98
+      code          -
+      registers     : 10
+      ins           : 2
+      outs          : 3
+      insns size    : 262 16-bit code units
+002b28:                                        |[002b28] com.google.android.checkers.CheckersView.c:(I)V
+002b38: 1237                                   |0000: const/4 v7, #int 3 // #3
+002b3a: 1226                                   |0001: const/4 v6, #int 2 // #2
+002b3c: 1212                                   |0002: const/4 v2, #int 1 // #1
+002b3e: 1201                                   |0003: const/4 v1, #int 0 // #0
+002b40: 5280 0c00                              |0004: iget v0, v8, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+002b44: 5483 0800                              |0006: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.G:[I // field@0008
+002b48: 5484 2200                              |0008: iget-object v4, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002b4c: 5244 3d00                              |000a: iget v4, v4, Lcom/google/android/checkers/a;.d:I // field@003d
+002b50: 4b04 0300                              |000c: aput v4, v3, v0
+002b54: 5483 0900                              |000e: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.H:[I // field@0009
+002b58: 5484 2200                              |0010: iget-object v4, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002b5c: 5244 3e00                              |0012: iget v4, v4, Lcom/google/android/checkers/a;.e:I // field@003e
+002b60: 4b04 0300                              |0014: aput v4, v3, v0
+002b64: 5483 0a00                              |0016: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.I:[I // field@000a
+002b68: 5484 2200                              |0018: iget-object v4, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002b6c: 5244 3f00                              |001a: iget v4, v4, Lcom/google/android/checkers/a;.f:I // field@003f
+002b70: 4b04 0300                              |001c: aput v4, v3, v0
+002b74: 5483 0b00                              |001e: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.J:[I // field@000b
+002b78: 5484 2200                              |0020: iget-object v4, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002b7c: 5244 4000                              |0022: iget v4, v4, Lcom/google/android/checkers/a;.g:I // field@0040
+002b80: 4b04 0300                              |0024: aput v4, v3, v0
+002b84: 5280 0c00                              |0026: iget v0, v8, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+002b88: 1273                                   |0028: const/4 v3, #int 7 // #7
+002b8a: 3530 6e00                              |0029: if-ge v0, v3, 0097 // +006e
+002b8e: 5280 0c00                              |002b: iget v0, v8, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+002b92: d800 0001                              |002d: add-int/lit8 v0, v0, #int 1 // #01
+002b96: 5980 0c00                              |002f: iput v0, v8, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+002b9a: 5280 0d00                              |0031: iget v0, v8, Lcom/google/android/checkers/CheckersView;.L:I // field@000d
+002b9e: 1303 0800                              |0033: const/16 v3, #int 8 // #8
+002ba2: 3530 0800                              |0035: if-ge v0, v3, 003d // +0008
+002ba6: 5280 0d00                              |0037: iget v0, v8, Lcom/google/android/checkers/CheckersView;.L:I // field@000d
+002baa: d800 0001                              |0039: add-int/lit8 v0, v0, #int 1 // #01
+002bae: 5980 0d00                              |003b: iput v0, v8, Lcom/google/android/checkers/CheckersView;.L:I // field@000d
+002bb2: 5280 2300                              |003d: iget v0, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002bb6: 3220 5b00                              |003f: if-eq v0, v2, 009a // +005b
+002bba: 5280 2300                              |0041: iget v0, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002bbe: 3260 5700                              |0043: if-eq v0, v6, 009a // +0057
+002bc2: 0110                                   |0045: move v0, v1
+002bc4: 5981 2800                              |0046: iput v1, v8, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+002bc8: 5981 2900                              |0048: iput v1, v8, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+002bcc: 5483 2200                              |004a: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002bd0: 5433 3b00                              |004c: iget-object v3, v3, Lcom/google/android/checkers/a;.b:[I // field@003b
+002bd4: 4403 0309                              |004e: aget v3, v3, v9
+002bd8: 5983 2a00                              |0050: iput v3, v8, Lcom/google/android/checkers/CheckersView;.x:I // field@002a
+002bdc: 1403 6666 663f                         |0052: const v3, #float 0.9 // #3f666666
+002be2: 5983 1e00                              |0055: iput v3, v8, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+002be6: 3800 4500                              |0057: if-eqz v0, 009c // +0045
+002bea: 5483 2200                              |0059: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002bee: 5433 3a00                              |005b: iget-object v3, v3, Lcom/google/android/checkers/a;.a:[I // field@003a
+002bf2: 4403 0309                              |005d: aget v3, v3, v9
+002bf6: 5284 2400                              |005f: iget v4, v8, Lcom/google/android/checkers/CheckersView;.r:I // field@0024
+002bfa: 5285 2600                              |0061: iget v5, v8, Lcom/google/android/checkers/CheckersView;.t:I // field@0026
+002bfe: b654                                   |0063: or-int/2addr v4, v5
+002c00: b543                                   |0064: and-int/2addr v3, v4
+002c02: 5983 1f00                              |0065: iput v3, v8, Lcom/google/android/checkers/CheckersView;.m:I // field@001f
+002c06: 5981 2000                              |0067: iput v1, v8, Lcom/google/android/checkers/CheckersView;.n:I // field@0020
+002c0a: 5483 2200                              |0069: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002c0e: 6e20 7c00 9300                         |006b: invoke-virtual {v3, v9}, Lcom/google/android/checkers/a;.a:(I)V // method@007c
+002c14: 5483 2200                              |006e: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002c18: 5233 3d00                              |0070: iget v3, v3, Lcom/google/android/checkers/a;.d:I // field@003d
+002c1c: 5983 2400                              |0072: iput v3, v8, Lcom/google/android/checkers/CheckersView;.r:I // field@0024
+002c20: 5483 2200                              |0074: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002c24: 5233 3f00                              |0076: iget v3, v3, Lcom/google/android/checkers/a;.f:I // field@003f
+002c28: 5983 2500                              |0078: iput v3, v8, Lcom/google/android/checkers/CheckersView;.s:I // field@0025
+002c2c: 5483 2200                              |007a: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002c30: 5233 3e00                              |007c: iget v3, v3, Lcom/google/android/checkers/a;.e:I // field@003e
+002c34: 5983 2600                              |007e: iput v3, v8, Lcom/google/android/checkers/CheckersView;.t:I // field@0026
+002c38: 5483 2200                              |0080: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002c3c: 5233 4000                              |0082: iget v3, v3, Lcom/google/android/checkers/a;.g:I // field@0040
+002c40: 5983 2700                              |0084: iput v3, v8, Lcom/google/android/checkers/CheckersView;.u:I // field@0027
+002c44: 5c81 2b00                              |0086: iput-boolean v1, v8, Lcom/google/android/checkers/CheckersView;.y:Z // field@002b
+002c48: 1203                                   |0088: const/4 v3, #int 0 // #0
+002c4a: 5b83 0f00                              |0089: iput-object v3, v8, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+002c4e: 5483 2200                              |008b: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002c52: 5584 0300                              |008d: iget-boolean v4, v8, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+002c56: 6e30 7a00 0304                         |008f: invoke-virtual {v3, v0, v4}, Lcom/google/android/checkers/a;.a:(ZZ)I // method@007a
+002c5c: 0a03                                   |0092: move-result v3
+002c5e: 2b03 6900 0000                         |0093: packed-switch v3, 000000fc // +00000069
+002c64: 0e00                                   |0096: return-void
+002c66: 5981 0c00                              |0097: iput v1, v8, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+002c6a: 2898                                   |0099: goto 0031 // -0068
+002c6c: 0120                                   |009a: move v0, v2
+002c6e: 28ab                                   |009b: goto 0046 // -0055
+002c70: 5981 1f00                              |009c: iput v1, v8, Lcom/google/android/checkers/CheckersView;.m:I // field@001f
+002c74: 5483 2200                              |009e: iget-object v3, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002c78: 5433 3a00                              |00a0: iget-object v3, v3, Lcom/google/android/checkers/a;.a:[I // field@003a
+002c7c: 4403 0309                              |00a2: aget v3, v3, v9
+002c80: 5284 2500                              |00a4: iget v4, v8, Lcom/google/android/checkers/CheckersView;.s:I // field@0025
+002c84: 5285 2700                              |00a6: iget v5, v8, Lcom/google/android/checkers/CheckersView;.u:I // field@0027
+002c88: b654                                   |00a8: or-int/2addr v4, v5
+002c8a: b543                                   |00a9: and-int/2addr v3, v4
+002c8c: 5983 2000                              |00aa: iput v3, v8, Lcom/google/android/checkers/CheckersView;.n:I // field@0020
+002c90: 28bd                                   |00ac: goto 0069 // -0043
+002c92: 3800 0800                              |00ad: if-eqz v0, 00b5 // +0008
+002c96: 1260                                   |00af: const/4 v0, #int 6 // #6
+002c98: 5980 2300                              |00b0: iput v0, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002c9c: 5981 0e00                              |00b2: iput v1, v8, Lcom/google/android/checkers/CheckersView;.M:I // field@000e
+002ca0: 28e2                                   |00b4: goto 0096 // -001e
+002ca2: 1250                                   |00b5: const/4 v0, #int 5 // #5
+002ca4: 28fa                                   |00b6: goto 00b0 // -0006
+002ca6: 5c82 2b00                              |00b7: iput-boolean v2, v8, Lcom/google/android/checkers/CheckersView;.y:Z // field@002b
+002caa: 5481 2200                              |00b9: iget-object v1, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002cae: 5211 3c00                              |00bb: iget v1, v1, Lcom/google/android/checkers/a;.c:I // field@003c
+002cb2: 5981 0e00                              |00bd: iput v1, v8, Lcom/google/android/checkers/CheckersView;.M:I // field@000e
+002cb6: 5281 2300                              |00bf: iget v1, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002cba: 3321 1800                              |00c1: if-ne v1, v2, 00d9 // +0018
+002cbe: 5281 2c00                              |00c3: iget v1, v8, Lcom/google/android/checkers/CheckersView;.z:I // field@002c
+002cc2: 3901 0900                              |00c5: if-nez v1, 00ce // +0009
+002cc6: 5987 2300                              |00c7: iput v7, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002cca: 1a00 d200                              |00c9: const-string v0, "free play" // string@00d2
+002cce: 5b80 0f00                              |00cb: iput-object v0, v8, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+002cd2: 28c9                                   |00cd: goto 0096 // -0037
+002cd4: 1241                                   |00ce: const/4 v1, #int 4 // #4
+002cd6: 5981 2300                              |00cf: iput v1, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002cda: 5481 2200                              |00d1: iget-object v1, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002cde: 5582 0300                              |00d3: iget-boolean v2, v8, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+002ce2: 6e30 8700 0102                         |00d5: invoke-virtual {v1, v0, v2}, Lcom/google/android/checkers/a;.b:(ZZ)V // method@0087
+002ce8: 28be                                   |00d8: goto 0096 // -0042
+002cea: 5281 2300                              |00d9: iget v1, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002cee: 3371 1700                              |00db: if-ne v1, v7, 00f2 // +0017
+002cf2: 5281 2c00                              |00dd: iget v1, v8, Lcom/google/android/checkers/CheckersView;.z:I // field@002c
+002cf6: 3901 0900                              |00df: if-nez v1, 00e8 // +0009
+002cfa: 5982 2300                              |00e1: iput v2, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002cfe: 1a00 d200                              |00e3: const-string v0, "free play" // string@00d2
+002d02: 5b80 0f00                              |00e5: iput-object v0, v8, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+002d06: 28af                                   |00e7: goto 0096 // -0051
+002d08: 5986 2300                              |00e8: iput v6, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002d0c: 5481 2200                              |00ea: iget-object v1, v8, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+002d10: 5582 0300                              |00ec: iget-boolean v2, v8, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+002d14: 6e30 8700 0102                         |00ee: invoke-virtual {v1, v0, v2}, Lcom/google/android/checkers/a;.b:(ZZ)V // method@0087
+002d1a: 28a5                                   |00f1: goto 0096 // -005b
+002d1c: 5280 2300                              |00f2: iget v0, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002d20: 3360 0500                              |00f4: if-ne v0, v6, 00f9 // +0005
+002d24: 5987 2300                              |00f6: iput v7, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002d28: 289e                                   |00f8: goto 0096 // -0062
+002d2a: 5982 2300                              |00f9: iput v2, v8, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+002d2e: 289b                                   |00fb: goto 0096 // -0065
+002d30: 0001 0300 0000 0000 1a00 0000 2400 ... |00fc: packed-switch-data (10 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #13              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'd'
+      type          : '()V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 100
+      code          -
+      registers     : 6
+      ins           : 1
+      outs          : 5
+      insns size    : 88 16-bit code units
+002d44:                                        |[002d44] com.google.android.checkers.CheckersView.d:()V
+002d54: 1303 8b00                              |0000: const/16 v3, #int 139 // #8b
+002d58: 1301 cc00                              |0002: const/16 v1, #int 204 // #cc
+002d5c: 1304 ff00                              |0004: const/16 v4, #int 255 // #ff
+002d60: 5250 0700                              |0006: iget v0, v5, Lcom/google/android/checkers/CheckersView;.F:I // field@0007
+002d64: 2b00 4000 0000                         |0008: packed-switch v0, 00000048 // +00000040
+002d6a: 0e00                                   |000b: return-void
+002d6c: 5450 1700                              |000c: iget-object v0, v5, Lcom/google/android/checkers/CheckersView;.e:Landroid/graphics/Paint; // field@0017
+002d70: 1301 6600                              |000e: const/16 v1, #int 102 // #66
+002d74: 1302 cd00                              |0010: const/16 v2, #int 205 // #cd
+002d78: 1303 aa00                              |0012: const/16 v3, #int 170 // #aa
+002d7c: 6e53 2200 4021                         |0014: invoke-virtual {v0, v4, v1, v2, v3}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+002d82: 28f4                                   |0017: goto 000b // -000c
+002d84: 5450 1700                              |0018: iget-object v0, v5, Lcom/google/android/checkers/CheckersView;.e:Landroid/graphics/Paint; // field@0017
+002d88: 1301 4500                              |001a: const/16 v1, #int 69 // #45
+002d8c: 1302 7400                              |001c: const/16 v2, #int 116 // #74
+002d90: 6e52 2200 4031                         |001e: invoke-virtual {v0, v4, v1, v3, v2}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+002d96: 28ea                                   |0021: goto 000b // -0016
+002d98: 5450 1700                              |0022: iget-object v0, v5, Lcom/google/android/checkers/CheckersView;.e:Landroid/graphics/Paint; // field@0017
+002d9c: 1301 1e00                              |0024: const/16 v1, #int 30 // #1e
+002da0: 1302 9000                              |0026: const/16 v2, #int 144 // #90
+002da4: 6e54 2200 4021                         |0028: invoke-virtual {v0, v4, v1, v2, v4}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+002daa: 28e0                                   |002b: goto 000b // -0020
+002dac: 5450 1700                              |002c: iget-object v0, v5, Lcom/google/android/checkers/CheckersView;.e:Landroid/graphics/Paint; // field@0017
+002db0: 1301 8e00                              |002e: const/16 v1, #int 142 // #8e
+002db4: 1302 6b00                              |0030: const/16 v2, #int 107 // #6b
+002db8: 1303 2300                              |0032: const/16 v3, #int 35 // #23
+002dbc: 6e53 2200 4021                         |0034: invoke-virtual {v0, v4, v1, v2, v3}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+002dc2: 28d4                                   |0037: goto 000b // -002c
+002dc4: 5450 1700                              |0038: iget-object v0, v5, Lcom/google/android/checkers/CheckersView;.e:Landroid/graphics/Paint; // field@0017
+002dc8: 1301 6c00                              |003a: const/16 v1, #int 108 // #6c
+002dcc: 1302 7b00                              |003c: const/16 v2, #int 123 // #7b
+002dd0: 6e53 2200 4021                         |003e: invoke-virtual {v0, v4, v1, v2, v3}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+002dd6: 28ca                                   |0041: goto 000b // -0036
+002dd8: 5450 1700                              |0042: iget-object v0, v5, Lcom/google/android/checkers/CheckersView;.e:Landroid/graphics/Paint; // field@0017
+002ddc: 6e51 2200 4011                         |0044: invoke-virtual {v0, v4, v1, v1, v1}, Landroid/graphics/Paint;.setARGB:(IIII)V // method@0022
+002de2: 28c4                                   |0047: goto 000b // -003c
+002de4: 0001 0600 0100 0000 0400 0000 1000 ... |0048: packed-switch-data (16 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #14              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'e'
+      type          : '()Z'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 103
+      code          -
+      registers     : 3
+      ins           : 1
+      outs          : 0
+      insns size    : 10 16-bit code units
+002e04:                                        |[002e04] com.google.android.checkers.CheckersView.e:()Z
+002e14: 5220 2500                              |0000: iget v0, v2, Lcom/google/android/checkers/CheckersView;.s:I // field@0025
+002e18: 1501 f0ff                              |0002: const/high16 v1, #int -1048576 // #fff0
+002e1c: 3310 0400                              |0004: if-ne v0, v1, 0008 // +0004
+002e20: 1210                                   |0006: const/4 v0, #int 1 // #1
+002e22: 0f00                                   |0007: return v0
+002e24: 1200                                   |0008: const/4 v0, #int 0 // #0
+002e26: 28fe                                   |0009: goto 0007 // -0002
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+    #0              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '()V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 78
+      code          -
+      registers     : 4
+      ins           : 1
+      outs          : 3
+      insns size    : 64 16-bit code units
+002e28:                                        |[002e28] com.google.android.checkers.CheckersView.a:()V
+002e38: 1270                                   |0000: const/4 v0, #int 7 // #7
+002e3a: 2300 3800                              |0001: new-array v0, v0, [Ljava/lang/CharSequence; // type@0038
+002e3e: 1201                                   |0003: const/4 v1, #int 0 // #0
+002e40: 1a02 9d00                              |0004: const-string v2, "Wood" // string@009d
+002e44: 4d02 0001                              |0006: aput-object v2, v0, v1
+002e48: 1211                                   |0008: const/4 v1, #int 1 // #1
+002e4a: 1a02 6000                              |0009: const-string v2, "Light Aquamarine" // string@0060
+002e4e: 4d02 0001                              |000b: aput-object v2, v0, v1
+002e52: 1221                                   |000d: const/4 v1, #int 2 // #2
+002e54: 1a02 1400                              |000e: const-string v2, "Dark Aquamarine" // string@0014
+002e58: 4d02 0001                              |0010: aput-object v2, v0, v1
+002e5c: 1231                                   |0012: const/4 v1, #int 3 // #3
+002e5e: 1a02 0c00                              |0013: const-string v2, "Blue" // string@000c
+002e62: 4d02 0001                              |0015: aput-object v2, v0, v1
+002e66: 1241                                   |0017: const/4 v1, #int 4 // #4
+002e68: 1a02 0e00                              |0018: const-string v2, "Brown" // string@000e
+002e6c: 4d02 0001                              |001a: aput-object v2, v0, v1
+002e70: 1251                                   |001c: const/4 v1, #int 5 // #5
+002e72: 1a02 1a00                              |001d: const-string v2, "Grey" // string@001a
+002e76: 4d02 0001                              |001f: aput-object v2, v0, v1
+002e7a: 1261                                   |0021: const/4 v1, #int 6 // #6
+002e7c: 1a02 6100                              |0022: const-string v2, "Light Grey" // string@0061
+002e80: 4d02 0001                              |0024: aput-object v2, v0, v1
+002e84: 2201 0500                              |0026: new-instance v1, Landroid/app/AlertDialog$Builder; // type@0005
+002e88: 5432 1300                              |0028: iget-object v2, v3, Lcom/google/android/checkers/CheckersView;.a:Landroid/content/Context; // field@0013
+002e8c: 7020 0900 2100                         |002a: invoke-direct {v1, v2}, Landroid/app/AlertDialog$Builder;.<init>:(Landroid/content/Context;)V // method@0009
+002e92: 1a02 0d00                              |002d: const-string v2, "Board Color" // string@000d
+002e96: 6e20 0f00 2100                         |002f: invoke-virtual {v1, v2}, Landroid/app/AlertDialog$Builder;.setTitle:(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder; // method@000f
+002e9c: 0c01                                   |0032: move-result-object v1
+002e9e: 2202 2500                              |0033: new-instance v2, Lcom/google/android/checkers/f; // type@0025
+002ea2: 7020 9700 3200                         |0035: invoke-direct {v2, v3}, Lcom/google/android/checkers/f;.<init>:(Lcom/google/android/checkers/CheckersView;)V // method@0097
+002ea8: 6e30 0b00 0102                         |0038: invoke-virtual {v1, v0, v2}, Landroid/app/AlertDialog$Builder;.setItems:([Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder; // method@000b
+002eae: 0c00                                   |003b: move-result-object v0
+002eb0: 6e10 1000 0000                         |003c: invoke-virtual {v0}, Landroid/app/AlertDialog$Builder;.show:()Landroid/app/AlertDialog; // method@0010
+002eb6: 0e00                                   |003f: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #1              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(FF)V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 79
+      code          -
+      registers     : 10
+      ins           : 3
+      outs          : 1
+      insns size    : 113 16-bit code units
+002eb8:                                        |[002eb8] com.google.android.checkers.CheckersView.a:(FF)V
+002ec8: 1206                                   |0000: const/4 v6, #int 0 // #0
+002eca: 6e10 6a00 0700                         |0001: invoke-virtual {v7}, Lcom/google/android/checkers/CheckersView;.getWidth:()I // method@006a
+002ed0: 0a01                                   |0004: move-result v1
+002ed2: 6e10 6900 0700                         |0005: invoke-virtual {v7}, Lcom/google/android/checkers/CheckersView;.getHeight:()I // method@0069
+002ed8: 0a02                                   |0008: move-result v2
+002eda: 3521 4900                              |0009: if-ge v1, v2, 0052 // +0049
+002ede: 0110                                   |000b: move v0, v1
+002ee0: e200 0003                              |000c: ushr-int/lit8 v0, v0, #int 3 // #03
+002ee4: e003 0003                              |000e: shl-int/lit8 v3, v0, #int 3 // #03
+002ee8: 5274 1000                              |0010: iget v4, v7, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+002eec: 2e04 0604                              |0012: cmpg-float v4, v6, v4
+002ef0: 3c04 1600                              |0014: if-gtz v4, 002a // +0016
+002ef4: 5274 1000                              |0016: iget v4, v7, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+002ef8: 8235                                   |0018: int-to-float v5, v3
+002efa: 2e04 0405                              |0019: cmpg-float v4, v4, v5
+002efe: 3b04 0f00                              |001b: if-gez v4, 002a // +000f
+002f02: 5274 1100                              |001d: iget v4, v7, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+002f06: 2e04 0604                              |001f: cmpg-float v4, v6, v4
+002f0a: 3c04 0900                              |0021: if-gtz v4, 002a // +0009
+002f0e: 5274 1100                              |0023: iget v4, v7, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+002f12: 8233                                   |0025: int-to-float v3, v3
+002f14: 2e03 0403                              |0026: cmpg-float v3, v4, v3
+002f18: 3a03 0400                              |0028: if-ltz v3, 002c // +0004
+002f1c: 1300 1000                              |002a: const/16 v0, #int 16 // #10
+002f20: 1d07                                   |002c: monitor-enter v7
+002f22: 5273 1000                              |002d: iget v3, v7, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+002f26: 8204                                   |002f: int-to-float v4, v0
+002f28: c884                                   |0030: mul-float/2addr v4, v8
+002f2a: c643                                   |0031: add-float/2addr v3, v4
+002f2c: 5973 1000                              |0032: iput v3, v7, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+002f30: 5273 1100                              |0034: iget v3, v7, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+002f34: 8200                                   |0036: int-to-float v0, v0
+002f36: c890                                   |0037: mul-float/2addr v0, v9
+002f38: c630                                   |0038: add-float/2addr v0, v3
+002f3a: 5970 1100                              |0039: iput v0, v7, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+002f3e: 5270 1000                              |003b: iget v0, v7, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+002f42: 2e00 0006                              |003d: cmpg-float v0, v0, v6
+002f46: 3b00 1500                              |003f: if-gez v0, 0054 // +0015
+002f4a: 1200                                   |0041: const/4 v0, #int 0 // #0
+002f4c: 5970 1000                              |0042: iput v0, v7, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+002f50: 5270 1100                              |0044: iget v0, v7, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+002f54: 2e00 0006                              |0046: cmpg-float v0, v0, v6
+002f58: 3b00 1c00                              |0048: if-gez v0, 0064 // +001c
+002f5c: 1200                                   |004a: const/4 v0, #int 0 // #0
+002f5e: 5970 1100                              |004b: iput v0, v7, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+002f62: 1e07                                   |004d: monitor-exit v7
+002f64: 6e10 6d00 0700                         |004e: invoke-virtual {v7}, Lcom/google/android/checkers/CheckersView;.postInvalidate:()V // method@006d
+002f6a: 0e00                                   |0051: return-void
+002f6c: 0120                                   |0052: move v0, v2
+002f6e: 28b9                                   |0053: goto 000c // -0047
+002f70: 5270 1000                              |0054: iget v0, v7, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+002f74: 8213                                   |0056: int-to-float v3, v1
+002f76: 2d00 0003                              |0057: cmpl-float v0, v0, v3
+002f7a: 3a00 ebff                              |0059: if-ltz v0, 0044 // -0015
+002f7e: d800 01ff                              |005b: add-int/lit8 v0, v1, #int -1 // #ff
+002f82: 8200                                   |005d: int-to-float v0, v0
+002f84: 5970 1000                              |005e: iput v0, v7, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+002f88: 28e4                                   |0060: goto 0044 // -001c
+002f8a: 0d00                                   |0061: move-exception v0
+002f8c: 1e07                                   |0062: monitor-exit v7
+002f8e: 2700                                   |0063: throw v0
+002f90: 5270 1100                              |0064: iget v0, v7, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+002f94: 8221                                   |0066: int-to-float v1, v2
+002f96: 2d00 0001                              |0067: cmpl-float v0, v0, v1
+002f9a: 3a00 e4ff                              |0069: if-ltz v0, 004d // -001c
+002f9e: d800 02ff                              |006b: add-int/lit8 v0, v2, #int -1 // #ff
+002fa2: 8200                                   |006d: int-to-float v0, v0
+002fa4: 5970 1100                              |006e: iput v0, v7, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+002fa8: 28dd                                   |0070: goto 004d // -0023
+      catches       : 3
+        0x002d - 0x004e
+          <any> -> 0x0061
+        0x0054 - 0x0060
+          <any> -> 0x0061
+        0x0064 - 0x0070
+          <any> -> 0x0061
+      positions     : 
+      locals        : 
+
+    #2              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(IIII)V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 80
+      code          -
+      registers     : 11
+      ins           : 5
+      outs          : 6
+      insns size    : 16 16-bit code units
+002fc8:                                        |[002fc8] com.google.android.checkers.CheckersView.a:(IIII)V
+002fd8: 1211                                   |0000: const/4 v1, #int 1 // #1
+002fda: 0760                                   |0001: move-object v0, v6
+002fdc: 0172                                   |0002: move v2, v7
+002fde: 0183                                   |0003: move v3, v8
+002fe0: 0194                                   |0004: move v4, v9
+002fe2: 01a5                                   |0005: move v5, v10
+002fe4: 7606 5b00 0000                         |0006: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/CheckersView;.a:(ZIIII)Z // method@005b
+002fea: 0a00                                   |0009: move-result v0
+002fec: 3800 0500                              |000a: if-eqz v0, 000f // +0005
+002ff0: 6e10 6d00 0600                         |000c: invoke-virtual {v6}, Lcom/google/android/checkers/CheckersView;.postInvalidate:()V // method@006d
+002ff6: 0e00                                   |000f: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #3              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(Landroid/content/SharedPreferences$Editor;)V'
+      access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 81
+      code          -
+      registers     : 4
+      ins           : 2
+      outs          : 3
+      insns size    : 170 16-bit code units
+002ff8:                                        |[002ff8] com.google.android.checkers.CheckersView.a:(Landroid/content/SharedPreferences$Editor;)V
+003008: 1d02                                   |0000: monitor-enter v2
+00300a: 7210 1300 0300                         |0001: invoke-interface {v3}, Landroid/content/SharedPreferences$Editor;.clear:()Landroid/content/SharedPreferences$Editor; // method@0013
+003010: 1a00 d000                              |0004: const-string v0, "format" // string@00d0
+003014: 1301 2200                              |0006: const/16 v1, #int 34 // #22
+003018: 7230 1600 0301                         |0008: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+00301e: 1a00 3101                              |000b: const-string v0, "state" // string@0131
+003022: 5221 2300                              |000d: iget v1, v2, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+003026: 7230 1600 0301                         |000f: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+00302c: 1a00 3f01                              |0012: const-string v0, "wp" // string@013f
+003030: 5221 2400                              |0014: iget v1, v2, Lcom/google/android/checkers/CheckersView;.r:I // field@0024
+003034: 7230 1600 0301                         |0016: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+00303a: 1a00 b400                              |0019: const-string v0, "bp" // string@00b4
+00303e: 5221 2500                              |001b: iget v1, v2, Lcom/google/android/checkers/CheckersView;.s:I // field@0025
+003042: 7230 1600 0301                         |001d: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+003048: 1a00 3e01                              |0020: const-string v0, "wk" // string@013e
+00304c: 5221 2600                              |0022: iget v1, v2, Lcom/google/android/checkers/CheckersView;.t:I // field@0026
+003050: 7230 1600 0301                         |0024: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+003056: 1a00 b300                              |0027: const-string v0, "bk" // string@00b3
+00305a: 5221 2700                              |0029: iget v1, v2, Lcom/google/android/checkers/CheckersView;.u:I // field@0027
+00305e: 7230 1600 0301                         |002b: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+003064: 1a00 e800                              |002e: const-string v0, "l1" // string@00e8
+003068: 5221 2800                              |0030: iget v1, v2, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+00306c: 7230 1600 0301                         |0032: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+003072: 1a00 e900                              |0035: const-string v0, "l2" // string@00e9
+003076: 5221 2900                              |0037: iget v1, v2, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+00307a: 7230 1600 0301                         |0039: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+003080: 1a00 ef00                              |003c: const-string v0, "lm" // string@00ef
+003084: 5221 2a00                              |003e: iget v1, v2, Lcom/google/android/checkers/CheckersView;.x:I // field@002a
+003088: 7230 1600 0301                         |0040: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+00308e: 1a00 b800                              |0043: const-string v0, "cap" // string@00b8
+003092: 5521 2b00                              |0045: iget-boolean v1, v2, Lcom/google/android/checkers/CheckersView;.y:Z // field@002b
+003096: 7230 1500 0301                         |0047: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putBoolean:(Ljava/lang/String;Z)Landroid/content/SharedPreferences$Editor; // method@0015
+00309c: 1a00 ee00                              |004a: const-string v0, "level" // string@00ee
+0030a0: 5221 2c00                              |004c: iget v1, v2, Lcom/google/android/checkers/CheckersView;.z:I // field@002c
+0030a4: 7230 1600 0301                         |004e: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+0030aa: 1a00 2d01                              |0051: const-string v0, "show" // string@012d
+0030ae: 5521 0200                              |0053: iget-boolean v1, v2, Lcom/google/android/checkers/CheckersView;.A:Z // field@0002
+0030b2: 7230 1500 0301                         |0055: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putBoolean:(Ljava/lang/String;Z)Landroid/content/SharedPreferences$Editor; // method@0015
+0030b8: 1a00 d100                              |0058: const-string v0, "free" // string@00d1
+0030bc: 5521 0300                              |005a: iget-boolean v1, v2, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+0030c0: 7230 1500 0301                         |005c: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putBoolean:(Ljava/lang/String;Z)Landroid/content/SharedPreferences$Editor; // method@0015
+0030c6: 1a00 1801                              |005f: const-string v0, "rot" // string@0118
+0030ca: 5521 0400                              |0061: iget-boolean v1, v2, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+0030ce: 7230 1500 0301                         |0063: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putBoolean:(Ljava/lang/String;Z)Landroid/content/SharedPreferences$Editor; // method@0015
+0030d4: 1a00 d300                              |0066: const-string v0, "full" // string@00d3
+0030d8: 5521 0500                              |0068: iget-boolean v1, v2, Lcom/google/android/checkers/CheckersView;.D:Z // field@0005
+0030dc: 7230 1500 0301                         |006a: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putBoolean:(Ljava/lang/String;Z)Landroid/content/SharedPreferences$Editor; // method@0015
+0030e2: 1a00 2f01                              |006d: const-string v0, "start" // string@012f
+0030e6: 5521 0600                              |006f: iget-boolean v1, v2, Lcom/google/android/checkers/CheckersView;.E:Z // field@0006
+0030ea: 7230 1500 0301                         |0071: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putBoolean:(Ljava/lang/String;Z)Landroid/content/SharedPreferences$Editor; // method@0015
+0030f0: 1a00 bd00                              |0074: const-string v0, "color" // string@00bd
+0030f4: 5221 0700                              |0076: iget v1, v2, Lcom/google/android/checkers/CheckersView;.F:I // field@0007
+0030f8: 7230 1600 0301                         |0078: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+0030fe: 1a00 f300                              |007b: const-string v0, "lwp" // string@00f3
+003102: 5421 0800                              |007d: iget-object v1, v2, Lcom/google/android/checkers/CheckersView;.G:[I // field@0008
+003106: 7130 5200 0301                         |007f: invoke-static {v3, v0, v1}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/content/SharedPreferences$Editor;Ljava/lang/String;[I)V // method@0052
+00310c: 1a00 f200                              |0082: const-string v0, "lwk" // string@00f2
+003110: 5421 0900                              |0084: iget-object v1, v2, Lcom/google/android/checkers/CheckersView;.H:[I // field@0009
+003114: 7130 5200 0301                         |0086: invoke-static {v3, v0, v1}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/content/SharedPreferences$Editor;Ljava/lang/String;[I)V // method@0052
+00311a: 1a00 eb00                              |0089: const-string v0, "lbp" // string@00eb
+00311e: 5421 0a00                              |008b: iget-object v1, v2, Lcom/google/android/checkers/CheckersView;.I:[I // field@000a
+003122: 7130 5200 0301                         |008d: invoke-static {v3, v0, v1}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/content/SharedPreferences$Editor;Ljava/lang/String;[I)V // method@0052
+003128: 1a00 ea00                              |0090: const-string v0, "lbk" // string@00ea
+00312c: 5421 0b00                              |0092: iget-object v1, v2, Lcom/google/android/checkers/CheckersView;.J:[I // field@000b
+003130: 7130 5200 0301                         |0094: invoke-static {v3, v0, v1}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/content/SharedPreferences$Editor;Ljava/lang/String;[I)V // method@0052
+003136: 1a00 f100                              |0097: const-string v0, "lp" // string@00f1
+00313a: 5221 0c00                              |0099: iget v1, v2, Lcom/google/android/checkers/CheckersView;.K:I // field@000c
+00313e: 7230 1600 0301                         |009b: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+003144: 1a00 ec00                              |009e: const-string v0, "lc" // string@00ec
+003148: 5221 0d00                              |00a0: iget v1, v2, Lcom/google/android/checkers/CheckersView;.L:I // field@000d
+00314c: 7230 1600 0301                         |00a2: invoke-interface {v3, v0, v1}, Landroid/content/SharedPreferences$Editor;.putInt:(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor; // method@0016
+003152: 1e02                                   |00a5: monitor-exit v2
+003154: 0e00                                   |00a6: return-void
+003156: 0d00                                   |00a7: move-exception v0
+003158: 1e02                                   |00a8: monitor-exit v2
+00315a: 2700                                   |00a9: throw v0
+      catches       : 1
+        0x0001 - 0x00a5
+          <any> -> 0x00a7
+      positions     : 
+      locals        : 
+
+    #4              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(I)Z'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 87
+      code          -
+      registers     : 8
+      ins           : 2
+      outs          : 6
+      insns size    : 17 16-bit code units
+003168:                                        |[003168] com.google.android.checkers.CheckersView.a:(I)Z
+003178: 1201                                   |0000: const/4 v1, #int 0 // #0
+00317a: 0760                                   |0001: move-object v0, v6
+00317c: 0172                                   |0002: move v2, v7
+00317e: 0113                                   |0003: move v3, v1
+003180: 0114                                   |0004: move v4, v1
+003182: 0115                                   |0005: move v5, v1
+003184: 7606 5b00 0000                         |0006: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/CheckersView;.a:(ZIIII)Z // method@005b
+00318a: 0a00                                   |0009: move-result v0
+00318c: 3800 0600                              |000a: if-eqz v0, 0010 // +0006
+003190: 6e10 6d00 0600                         |000c: invoke-virtual {v6}, Lcom/google/android/checkers/CheckersView;.postInvalidate:()V // method@006d
+003196: 1211                                   |000f: const/4 v1, #int 1 // #1
+003198: 0f01                                   |0010: return v1
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #5              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'a'
+      type          : '(Z)Z'
+      access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 90
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 1
+      insns size    : 22 16-bit code units
+00319c:                                        |[00319c] com.google.android.checkers.CheckersView.a:(Z)Z
+0031ac: 1d01                                   |0000: monitor-enter v1
+0031ae: 3802 0c00                              |0001: if-eqz v2, 000d // +000c
+0031b2: 5510 0200                              |0003: iget-boolean v0, v1, Lcom/google/android/checkers/CheckersView;.A:Z // field@0002
+0031b6: 3800 0c00                              |0005: if-eqz v0, 0011 // +000c
+0031ba: 1200                                   |0007: const/4 v0, #int 0 // #0
+0031bc: 5c10 0200                              |0008: iput-boolean v0, v1, Lcom/google/android/checkers/CheckersView;.A:Z // field@0002
+0031c0: 6e10 6d00 0100                         |000a: invoke-virtual {v1}, Lcom/google/android/checkers/CheckersView;.postInvalidate:()V // method@006d
+0031c6: 5510 0200                              |000d: iget-boolean v0, v1, Lcom/google/android/checkers/CheckersView;.A:Z // field@0002
+0031ca: 1e01                                   |000f: monitor-exit v1
+0031cc: 0f00                                   |0010: return v0
+0031ce: 1210                                   |0011: const/4 v0, #int 1 // #1
+0031d0: 28f6                                   |0012: goto 0008 // -000a
+0031d2: 0d00                                   |0013: move-exception v0
+0031d4: 1e01                                   |0014: monitor-exit v1
+0031d6: 2700                                   |0015: throw v0
+      catches       : 1
+        0x0003 - 0x000f
+          <any> -> 0x0013
+      positions     : 
+      locals        : 
+
+    #6              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'b'
+      type          : '()V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 93
+      code          -
+      registers     : 7
+      ins           : 1
+      outs          : 6
+      insns size    : 30 16-bit code units
+0031e4:                                        |[0031e4] com.google.android.checkers.CheckersView.b:()V
+0031f4: 1201                                   |0000: const/4 v1, #int 0 // #0
+0031f6: 1d06                                   |0001: monitor-enter v6
+0031f8: 5260 1000                              |0002: iget v0, v6, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+0031fc: 5262 1100                              |0004: iget v2, v6, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+003200: 7030 5c00 0602                         |0006: invoke-direct {v6, v0, v2}, Lcom/google/android/checkers/CheckersView;.b:(FF)I // method@005c
+003206: 0a02                                   |0009: move-result v2
+003208: 1e06                                   |000a: monitor-exit v6
+00320a: 3802 0f00                              |000b: if-eqz v2, 001a // +000f
+00320e: 0760                                   |000d: move-object v0, v6
+003210: 0113                                   |000e: move v3, v1
+003212: 0114                                   |000f: move v4, v1
+003214: 0115                                   |0010: move v5, v1
+003216: 7606 5b00 0000                         |0011: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/CheckersView;.a:(ZIIII)Z // method@005b
+00321c: 0a00                                   |0014: move-result v0
+00321e: 3800 0500                              |0015: if-eqz v0, 001a // +0005
+003222: 6e10 6d00 0600                         |0017: invoke-virtual {v6}, Lcom/google/android/checkers/CheckersView;.postInvalidate:()V // method@006d
+003228: 0e00                                   |001a: return-void
+00322a: 0d00                                   |001b: move-exception v0
+00322c: 1e06                                   |001c: monitor-exit v6
+00322e: 2700                                   |001d: throw v0
+      catches       : 1
+        0x0002 - 0x000b
+          <any> -> 0x001b
+      positions     : 
+      locals        : 
+
+    #7              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'b'
+      type          : '(Z)Z'
+      access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 96
+      code          -
+      registers     : 7
+      ins           : 2
+      outs          : 3
+      insns size    : 69 16-bit code units
+00323c:                                        |[00323c] com.google.android.checkers.CheckersView.b:(Z)Z
+00324c: 1233                                   |0000: const/4 v3, #int 3 // #3
+00324e: 1210                                   |0001: const/4 v0, #int 1 // #1
+003250: 1201                                   |0002: const/4 v1, #int 0 // #0
+003252: 1d05                                   |0003: monitor-enter v5
+003254: 3806 3400                              |0004: if-eqz v6, 0038 // +0034
+003258: 5552 0300                              |0006: iget-boolean v2, v5, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+00325c: 3802 3400                              |0008: if-eqz v2, 003c // +0034
+003260: 0112                                   |000a: move v2, v1
+003262: 5c52 0300                              |000b: iput-boolean v2, v5, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+003266: 5252 2300                              |000d: iget v2, v5, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+00326a: 3232 0600                              |000f: if-eq v2, v3, 0015 // +0006
+00326e: 5252 2300                              |0011: iget v2, v5, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+003272: 3302 2500                              |0013: if-ne v2, v0, 0038 // +0025
+003276: 5252 2300                              |0015: iget v2, v5, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+00327a: 3332 2700                              |0017: if-ne v2, v3, 003e // +0027
+00327e: 0102                                   |0019: move v2, v0
+003280: 1203                                   |001a: const/4 v3, #int 0 // #0
+003282: 5953 2800                              |001b: iput v3, v5, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+003286: 1203                                   |001d: const/4 v3, #int 0 // #0
+003288: 5953 2900                              |001e: iput v3, v5, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+00328c: 1203                                   |0020: const/4 v3, #int 0 // #0
+00328e: 5953 2a00                              |0021: iput v3, v5, Lcom/google/android/checkers/CheckersView;.x:I // field@002a
+003292: 5453 2200                              |0023: iget-object v3, v5, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+003296: 5554 0300                              |0025: iget-boolean v4, v5, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+00329a: 6e30 7a00 2304                         |0027: invoke-virtual {v3, v2, v4}, Lcom/google/android/checkers/a;.a:(ZZ)I // method@007a
+0032a0: 0a02                                   |002a: move-result v2
+0032a2: 3302 1500                              |002b: if-ne v2, v0, 0040 // +0015
+0032a6: 5c50 2b00                              |002d: iput-boolean v0, v5, Lcom/google/android/checkers/CheckersView;.y:Z // field@002b
+0032aa: 5450 2200                              |002f: iget-object v0, v5, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+0032ae: 5200 3c00                              |0031: iget v0, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+0032b2: 5950 0e00                              |0033: iput v0, v5, Lcom/google/android/checkers/CheckersView;.M:I // field@000e
+0032b6: 6e10 6d00 0500                         |0035: invoke-virtual {v5}, Lcom/google/android/checkers/CheckersView;.postInvalidate:()V // method@006d
+0032bc: 5550 0300                              |0038: iget-boolean v0, v5, Lcom/google/android/checkers/CheckersView;.B:Z // field@0003
+0032c0: 1e05                                   |003a: monitor-exit v5
+0032c2: 0f00                                   |003b: return v0
+0032c4: 0102                                   |003c: move v2, v0
+0032c6: 28ce                                   |003d: goto 000b // -0032
+0032c8: 0112                                   |003e: move v2, v1
+0032ca: 28db                                   |003f: goto 001a // -0025
+0032cc: 0110                                   |0040: move v0, v1
+0032ce: 28ec                                   |0041: goto 002d // -0014
+0032d0: 0d00                                   |0042: move-exception v0
+0032d2: 1e05                                   |0043: monitor-exit v5
+0032d4: 2700                                   |0044: throw v0
+      catches       : 1
+        0x0006 - 0x003a
+          <any> -> 0x0042
+      positions     : 
+      locals        : 
+
+    #8              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'c'
+      type          : '()I'
+      access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 97
+      code          -
+      registers     : 2
+      ins           : 1
+      outs          : 0
+      insns size    : 8 16-bit code units
+0032e4:                                        |[0032e4] com.google.android.checkers.CheckersView.c:()I
+0032f4: 1d01                                   |0000: monitor-enter v1
+0032f6: 5210 2c00                              |0001: iget v0, v1, Lcom/google/android/checkers/CheckersView;.z:I // field@002c
+0032fa: 1e01                                   |0003: monitor-exit v1
+0032fc: 0f00                                   |0004: return v0
+0032fe: 0d00                                   |0005: move-exception v0
+003300: 1e01                                   |0006: monitor-exit v1
+003302: 2700                                   |0007: throw v0
+      catches       : 1
+        0x0001 - 0x0003
+          <any> -> 0x0005
+      positions     : 
+      locals        : 
+
+    #9              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'c'
+      type          : '(Z)Z'
+      access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 99
+      code          -
+      registers     : 5
+      ins           : 2
+      outs          : 3
+      insns size    : 34 16-bit code units
+003310:                                        |[003310] com.google.android.checkers.CheckersView.c:(Z)Z
+003320: 1200                                   |0000: const/4 v0, #int 0 // #0
+003322: 1d03                                   |0001: monitor-enter v3
+003324: 3804 1700                              |0002: if-eqz v4, 0019 // +0017
+003328: 5531 0400                              |0004: iget-boolean v1, v3, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+00332c: 3801 1700                              |0006: if-eqz v1, 001d // +0017
+003330: 5c30 0400                              |0008: iput-boolean v0, v3, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+003334: 5430 1300                              |000a: iget-object v0, v3, Lcom/google/android/checkers/CheckersView;.a:Landroid/content/Context; // field@0013
+003338: 1a01 1901                              |000c: const-string v1, "rotated board" // string@0119
+00333c: 1202                                   |000e: const/4 v2, #int 0 // #0
+00333e: 7130 3c00 1002                         |000f: invoke-static {v0, v1, v2}, Landroid/widget/Toast;.makeText:(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; // method@003c
+003344: 0c00                                   |0012: move-result-object v0
+003346: 6e10 3d00 0000                         |0013: invoke-virtual {v0}, Landroid/widget/Toast;.show:()V // method@003d
+00334c: 6e10 6d00 0300                         |0016: invoke-virtual {v3}, Lcom/google/android/checkers/CheckersView;.postInvalidate:()V // method@006d
+003352: 5530 0400                              |0019: iget-boolean v0, v3, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+003356: 1e03                                   |001b: monitor-exit v3
+003358: 0f00                                   |001c: return v0
+00335a: 1210                                   |001d: const/4 v0, #int 1 // #1
+00335c: 28ea                                   |001e: goto 0008 // -0016
+00335e: 0d00                                   |001f: move-exception v0
+003360: 1e03                                   |0020: monitor-exit v3
+003362: 2700                                   |0021: throw v0
+      catches       : 1
+        0x0004 - 0x001b
+          <any> -> 0x001f
+      positions     : 
+      locals        : 
+
+    #10              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'd'
+      type          : '(Z)Z'
+      access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 101
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 0
+      insns size    : 19 16-bit code units
+003370:                                        |[003370] com.google.android.checkers.CheckersView.d:(Z)Z
+003380: 1d01                                   |0000: monitor-enter v1
+003382: 3802 0900                              |0001: if-eqz v2, 000a // +0009
+003386: 5510 0500                              |0003: iget-boolean v0, v1, Lcom/google/android/checkers/CheckersView;.D:Z // field@0005
+00338a: 3800 0900                              |0005: if-eqz v0, 000e // +0009
+00338e: 1200                                   |0007: const/4 v0, #int 0 // #0
+003390: 5c10 0500                              |0008: iput-boolean v0, v1, Lcom/google/android/checkers/CheckersView;.D:Z // field@0005
+003394: 5510 0500                              |000a: iget-boolean v0, v1, Lcom/google/android/checkers/CheckersView;.D:Z // field@0005
+003398: 1e01                                   |000c: monitor-exit v1
+00339a: 0f00                                   |000d: return v0
+00339c: 1210                                   |000e: const/4 v0, #int 1 // #1
+00339e: 28f9                                   |000f: goto 0008 // -0007
+0033a0: 0d00                                   |0010: move-exception v0
+0033a2: 1e01                                   |0011: monitor-exit v1
+0033a4: 2700                                   |0012: throw v0
+      catches       : 1
+        0x0003 - 0x000c
+          <any> -> 0x0010
+      positions     : 
+      locals        : 
+
+    #11              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'draw'
+      type          : '(Landroid/graphics/Canvas;)V'
+      access        : 0x20001 (PUBLIC DECLARED_SYNCHRONIZED)
+      method_idx    : 102
+      code          -
+      registers     : 30
+      ins           : 2
+      outs          : 8
+      insns size    : 1264 16-bit code units
+0033b4:                                        |[0033b4] com.google.android.checkers.CheckersView.draw:(Landroid/graphics/Canvas;)V
+0033c4: 1d1c                                   |0000: monitor-enter v28
+0033c6: 7502 3800 1c00                         |0001: invoke-super/range {v28, v29}, Landroid/view/View;.draw:(Landroid/graphics/Canvas;)V // method@0038
+0033cc: 7401 6a00 1c00                         |0004: invoke-virtual/range {v28}, Lcom/google/android/checkers/CheckersView;.getWidth:()I // method@006a
+0033d2: 0a03                                   |0007: move-result v3
+0033d4: 7401 6900 1c00                         |0008: invoke-virtual/range {v28}, Lcom/google/android/checkers/CheckersView;.getHeight:()I // method@0069
+0033da: 0a04                                   |000b: move-result v4
+0033dc: 3543 bc01                              |000c: if-ge v3, v4, 01c8 // +01bc
+0033e0: 0132                                   |000e: move v2, v3
+0033e2: e216 0203                              |000f: ushr-int/lit8 v22, v2, #int 3 // #03
+0033e6: e017 1603                              |0011: shl-int/lit8 v23, v22, #int 3 // #03
+0033ea: e218 1601                              |0013: ushr-int/lit8 v24, v22, #int 1 // #01
+0033ee: 0800 1c00                              |0015: move-object/from16 v0, v28
+0033f2: 5200 1d00                              |0017: iget v0, v0, Lcom/google/android/checkers/CheckersView;.k:I // field@001d
+0033f6: 0214 0000                              |0019: move/from16 v20, v0
+0033fa: db19 1403                              |001b: div-int/lit8 v25, v20, #int 3 // #03
+0033fe: 3543 ae01                              |001d: if-ge v3, v4, 01cb // +01ae
+003402: 1224                                   |001f: const/4 v4, #int 2 // #2
+003404: da02 140b                              |0020: mul-int/lit8 v2, v20, #int 11 // #0b
+003408: 9103 1702                              |0022: sub-int v3, v23, v2
+00340c: 9002 1714                              |0024: add-int v2, v23, v20
+003410: 0211 0200                              |0026: move/from16 v17, v2
+003414: 0212 0300                              |0028: move/from16 v18, v3
+003418: 0213 0200                              |002a: move/from16 v19, v2
+00341c: 0215 0400                              |002c: move/from16 v21, v4
+003420: 0800 1c00                              |002e: move-object/from16 v0, v28
+003424: 5402 1400                              |0030: iget-object v2, v0, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+003428: 0800 1d00                              |0032: move-object/from16 v0, v29
+00342c: 6e20 1e00 2000                         |0034: invoke-virtual {v0, v2}, Landroid/graphics/Canvas;.drawPaint:(Landroid/graphics/Paint;)V // method@001e
+003432: 0800 1c00                              |0037: move-object/from16 v0, v28
+003436: 5202 0700                              |0039: iget v2, v0, Lcom/google/android/checkers/CheckersView;.F:I // field@0007
+00343a: 3902 a201                              |003b: if-nez v2, 01dd // +01a2
+00343e: 0800 1c00                              |003d: move-object/from16 v0, v28
+003442: 5407 1600                              |003f: iget-object v7, v0, Lcom/google/android/checkers/CheckersView;.d:Landroid/graphics/Paint; // field@0016
+003446: 0800 1c00                              |0041: move-object/from16 v0, v28
+00344a: 5402 2100                              |0043: iget-object v2, v0, Lcom/google/android/checkers/CheckersView;.o:Landroid/graphics/drawable/Drawable; // field@0021
+00344e: 1203                                   |0045: const/4 v3, #int 0 // #0
+003450: 1204                                   |0046: const/4 v4, #int 0 // #0
+003452: 0200 1700                              |0047: move/from16 v0, v23
+003456: 0201 1700                              |0049: move/from16 v1, v23
+00345a: 6e51 2800 3204                         |004b: invoke-virtual {v2, v3, v4, v0, v1}, Landroid/graphics/drawable/Drawable;.setBounds:(IIII)V // method@0028
+003460: 0800 1c00                              |004e: move-object/from16 v0, v28
+003464: 5402 2100                              |0050: iget-object v2, v0, Lcom/google/android/checkers/CheckersView;.o:Landroid/graphics/drawable/Drawable; // field@0021
+003468: 0800 1d00                              |0052: move-object/from16 v0, v29
+00346c: 6e20 2700 0200                         |0054: invoke-virtual {v2, v0}, Landroid/graphics/drawable/Drawable;.draw:(Landroid/graphics/Canvas;)V // method@0027
+003472: 1202                                   |0057: const/4 v2, #int 0 // #0
+003474: 0129                                   |0058: move v9, v2
+003476: 1302 0800                              |0059: const/16 v2, #int 8 // #8
+00347a: 3429 9a01                              |005b: if-lt v9, v2, 01f5 // +019a
+00347e: 120d                                   |005d: const/4 v13, #int 0 // #0
+003480: 120c                                   |005e: const/4 v12, #int 0 // #0
+003482: 120b                                   |005f: const/4 v11, #int 0 // #0
+003484: 120a                                   |0060: const/4 v10, #int 0 // #0
+003486: 1213                                   |0061: const/4 v3, #int 1 // #1
+003488: 1202                                   |0062: const/4 v2, #int 0 // #0
+00348a: 0210 0200                              |0063: move/from16 v16, v2
+00348e: 1302 0800                              |0065: const/16 v2, #int 8 // #8
+003492: 0200 1000                              |0067: move/from16 v0, v16
+003496: 3420 ad01                              |0069: if-lt v0, v2, 0216 // +01ad
+00349a: 7601 6700 1c00                         |006b: invoke-direct/range {v28}, Lcom/google/android/checkers/CheckersView;.e:()Z // method@0067
+0034a0: 0a02                                   |006e: move-result v2
+0034a2: 3802 4d03                              |006f: if-eqz v2, 03bc // +034d
+0034a6: 1a02 1100                              |0071: const-string v2, "Checkers for Android" // string@0011
+0034aa: 0200 1500                              |0073: move/from16 v0, v21
+0034ae: 8203                                   |0075: int-to-float v3, v0
+0034b0: 0200 1300                              |0076: move/from16 v0, v19
+0034b4: 8204                                   |0078: int-to-float v4, v0
+0034b6: 0800 1c00                              |0079: move-object/from16 v0, v28
+0034ba: 5405 1500                              |007b: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+0034be: 0800 1d00                              |007d: move-object/from16 v0, v29
+0034c2: 6e55 2000 2043                         |007f: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+0034c8: 1a02 b500                              |0082: const-string v2, "by Aart J.C. Bik" // string@00b5
+0034cc: 0200 1500                              |0084: move/from16 v0, v21
+0034d0: 8203                                   |0086: int-to-float v3, v0
+0034d2: 9004 1314                              |0087: add-int v4, v19, v20
+0034d6: 8244                                   |0089: int-to-float v4, v4
+0034d8: 0800 1c00                              |008a: move-object/from16 v0, v28
+0034dc: 5405 1500                              |008c: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+0034e0: 0800 1d00                              |008e: move-object/from16 v0, v29
+0034e4: 6e55 2000 2043                         |0090: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+0034ea: 6302 6a00                              |0093: sget-boolean v2, Lcom/google/android/checkers/g;.r:Z // field@006a
+0034ee: 3902 1500                              |0095: if-nez v2, 00aa // +0015
+0034f2: 1a02 f800                              |0097: const-string v2, "no endgame TBs" // string@00f8
+0034f6: 0200 1500                              |0099: move/from16 v0, v21
+0034fa: 8203                                   |009b: int-to-float v3, v0
+0034fc: da04 1402                              |009c: mul-int/lit8 v4, v20, #int 2 // #02
+003500: 9004 0413                              |009e: add-int v4, v4, v19
+003504: 8244                                   |00a0: int-to-float v4, v4
+003506: 0800 1c00                              |00a1: move-object/from16 v0, v28
+00350a: 5405 1500                              |00a3: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+00350e: 0800 1d00                              |00a5: move-object/from16 v0, v29
+003512: 6e55 2000 2043                         |00a7: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003518: 0800 1c00                              |00aa: move-object/from16 v0, v28
+00351c: 5502 2b00                              |00ac: iget-boolean v2, v0, Lcom/google/android/checkers/CheckersView;.y:Z // field@002b
+003520: 3802 1300                              |00ae: if-eqz v2, 00c1 // +0013
+003524: 1a02 7000                              |00b0: const-string v2, "MUST CAPTURE" // string@0070
+003528: 0200 1200                              |00b2: move/from16 v0, v18
+00352c: 8203                                   |00b4: int-to-float v3, v0
+00352e: 0200 1100                              |00b5: move/from16 v0, v17
+003532: 8204                                   |00b7: int-to-float v4, v0
+003534: 0800 1c00                              |00b8: move-object/from16 v0, v28
+003538: 5405 1800                              |00ba: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.f:Landroid/graphics/Paint; // field@0018
+00353c: 0800 1d00                              |00bc: move-object/from16 v0, v29
+003540: 6e55 2000 2043                         |00be: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003546: 0800 1c00                              |00c1: move-object/from16 v0, v28
+00354a: 5202 2300                              |00c3: iget v2, v0, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+00354e: 2b02 1b04 0000                         |00c5: packed-switch v2, 000004e0 // +0000041b
+003554: 0800 1c00                              |00c8: move-object/from16 v0, v28
+003558: 5502 0200                              |00ca: iget-boolean v2, v0, Lcom/google/android/checkers/CheckersView;.A:Z // field@0002
+00355c: 3802 2600                              |00cc: if-eqz v2, 00f2 // +0026
+003560: 0800 1c00                              |00ce: move-object/from16 v0, v28
+003564: 5202 2300                              |00d0: iget v2, v0, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+003568: 1213                                   |00d2: const/4 v3, #int 1 // #1
+00356a: 3232 0900                              |00d3: if-eq v2, v3, 00dc // +0009
+00356e: 0800 1c00                              |00d5: move-object/from16 v0, v28
+003572: 5202 2300                              |00d7: iget v2, v0, Lcom/google/android/checkers/CheckersView;.q:I // field@0023
+003576: 1233                                   |00d9: const/4 v3, #int 3 // #3
+003578: 3332 1800                              |00da: if-ne v2, v3, 00f2 // +0018
+00357c: 0800 1c00                              |00dc: move-object/from16 v0, v28
+003580: 5402 2200                              |00de: iget-object v2, v0, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+003584: 5229 3c00                              |00e0: iget v9, v2, Lcom/google/android/checkers/a;.c:I // field@003c
+003588: 0800 1c00                              |00e2: move-object/from16 v0, v28
+00358c: 5402 2200                              |00e4: iget-object v2, v0, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+003590: 542a 3b00                              |00e6: iget-object v10, v2, Lcom/google/android/checkers/a;.b:[I // field@003b
+003594: 0800 1c00                              |00e8: move-object/from16 v0, v28
+003598: 5402 2200                              |00ea: iget-object v2, v0, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+00359c: 542b 3a00                              |00ec: iget-object v11, v2, Lcom/google/android/checkers/a;.a:[I // field@003a
+0035a0: 1202                                   |00ee: const/4 v2, #int 0 // #0
+0035a2: 0128                                   |00ef: move v8, v2
+0035a4: 3498 dc03                              |00f0: if-lt v8, v9, 04cc // +03dc
+0035a8: 0800 1c00                              |00f2: move-object/from16 v0, v28
+0035ac: 5402 0f00                              |00f4: iget-object v2, v0, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+0035b0: 3802 1700                              |00f6: if-eqz v2, 010d // +0017
+0035b4: 0800 1c00                              |00f8: move-object/from16 v0, v28
+0035b8: 5402 0f00                              |00fa: iget-object v2, v0, Lcom/google/android/checkers/CheckersView;.N:Ljava/lang/String; // field@000f
+0035bc: 0200 1200                              |00fc: move/from16 v0, v18
+0035c0: 8203                                   |00fe: int-to-float v3, v0
+0035c2: da04 1402                              |00ff: mul-int/lit8 v4, v20, #int 2 // #02
+0035c6: 9004 0411                              |0101: add-int v4, v4, v17
+0035ca: 8244                                   |0103: int-to-float v4, v4
+0035cc: 0800 1c00                              |0104: move-object/from16 v0, v28
+0035d0: 5405 1b00                              |0106: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.i:Landroid/graphics/Paint; // field@001b
+0035d4: 0800 1d00                              |0108: move-object/from16 v0, v29
+0035d8: 6e55 2000 2043                         |010a: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+0035de: 1202                                   |010d: const/4 v2, #int 0 // #0
+0035e0: 1203                                   |010e: const/4 v3, #int 0 // #0
+0035e2: 0800 1c00                              |010f: move-object/from16 v0, v28
+0035e6: 5204 1000                              |0111: iget v4, v0, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+0035ea: 2e03 0304                              |0113: cmpg-float v3, v3, v4
+0035ee: 3c03 5100                              |0115: if-gtz v3, 0166 // +0051
+0035f2: 0800 1c00                              |0117: move-object/from16 v0, v28
+0035f6: 5203 1000                              |0119: iget v3, v0, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+0035fa: 0200 1700                              |011b: move/from16 v0, v23
+0035fe: 8204                                   |011d: int-to-float v4, v0
+003600: 2e03 0304                              |011e: cmpg-float v3, v3, v4
+003604: 3b03 4600                              |0120: if-gez v3, 0166 // +0046
+003608: 1203                                   |0122: const/4 v3, #int 0 // #0
+00360a: 0800 1c00                              |0123: move-object/from16 v0, v28
+00360e: 5204 1100                              |0125: iget v4, v0, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+003612: 2e03 0304                              |0127: cmpg-float v3, v3, v4
+003616: 3c03 3d00                              |0129: if-gtz v3, 0166 // +003d
+00361a: 0800 1c00                              |012b: move-object/from16 v0, v28
+00361e: 5203 1100                              |012d: iget v3, v0, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+003622: 0200 1700                              |012f: move/from16 v0, v23
+003626: 8204                                   |0131: int-to-float v4, v0
+003628: 2e03 0304                              |0132: cmpg-float v3, v3, v4
+00362c: 3b03 3200                              |0134: if-gez v3, 0166 // +0032
+003630: 0800 1c00                              |0136: move-object/from16 v0, v28
+003634: 5203 1000                              |0138: iget v3, v0, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+003638: 8733                                   |013a: float-to-int v3, v3
+00363a: 9303 0316                              |013b: div-int v3, v3, v22
+00363e: 0800 1c00                              |013d: move-object/from16 v0, v28
+003642: 5204 1100                              |013f: iget v4, v0, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+003646: 8744                                   |0141: float-to-int v4, v4
+003648: 9304 0416                              |0142: div-int v4, v4, v22
+00364c: 3a03 2200                              |0144: if-ltz v3, 0166 // +0022
+003650: 1305 0800                              |0146: const/16 v5, #int 8 // #8
+003654: 3553 1e00                              |0148: if-ge v3, v5, 0166 // +001e
+003658: 3a04 1c00                              |014a: if-ltz v4, 0166 // +001c
+00365c: 1305 0800                              |014c: const/16 v5, #int 8 // #8
+003660: 3554 1800                              |014e: if-ge v4, v5, 0166 // +0018
+003664: 9202 1603                              |0150: mul-int v2, v22, v3
+003668: 9206 1604                              |0152: mul-int v6, v22, v4
+00366c: 8223                                   |0154: int-to-float v3, v2
+00366e: 8264                                   |0155: int-to-float v4, v6
+003670: 9002 0216                              |0156: add-int v2, v2, v22
+003674: 8225                                   |0158: int-to-float v5, v2
+003676: 9002 0616                              |0159: add-int v2, v6, v22
+00367a: 8226                                   |015b: int-to-float v6, v2
+00367c: 0800 1c00                              |015c: move-object/from16 v0, v28
+003680: 5407 1c00                              |015e: iget-object v7, v0, Lcom/google/android/checkers/CheckersView;.j:Landroid/graphics/Paint; // field@001c
+003684: 0802 1d00                              |0160: move-object/from16 v2, v29
+003688: 7406 1f00 0200                         |0162: invoke-virtual/range {v2, v3, v4, v5, v6, v7}, Landroid/graphics/Canvas;.drawRect:(FFFFLandroid/graphics/Paint;)V // method@001f
+00368e: 1212                                   |0165: const/4 v2, #int 1 // #1
+003690: 3902 2800                              |0166: if-nez v2, 018e // +0028
+003694: 0800 1c00                              |0168: move-object/from16 v0, v28
+003698: 5202 1000                              |016a: iget v2, v0, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+00369c: 0800 1c00                              |016c: move-object/from16 v0, v28
+0036a0: 5203 1100                              |016e: iget v3, v0, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+0036a4: 1504 a040                              |0170: const/high16 v4, #int 1084227584 // #40a0
+0036a8: 0800 1c00                              |0172: move-object/from16 v0, v28
+0036ac: 5405 1500                              |0174: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+0036b0: 0800 1d00                              |0176: move-object/from16 v0, v29
+0036b4: 6e55 1c00 2043                         |0178: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+0036ba: 0800 1c00                              |017b: move-object/from16 v0, v28
+0036be: 5202 1000                              |017d: iget v2, v0, Lcom/google/android/checkers/CheckersView;.O:F // field@0010
+0036c2: 0800 1c00                              |017f: move-object/from16 v0, v28
+0036c6: 5203 1100                              |0181: iget v3, v0, Lcom/google/android/checkers/CheckersView;.P:F // field@0011
+0036ca: 1504 4040                              |0183: const/high16 v4, #int 1077936128 // #4040
+0036ce: 0800 1c00                              |0185: move-object/from16 v0, v28
+0036d2: 5405 1400                              |0187: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+0036d6: 0800 1d00                              |0189: move-object/from16 v0, v29
+0036da: 6e55 1c00 2043                         |018b: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+0036e0: 0800 1c00                              |018e: move-object/from16 v0, v28
+0036e4: 5202 1e00                              |0190: iget v2, v0, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+0036e8: 1203                                   |0192: const/4 v3, #int 0 // #0
+0036ea: 2d02 0203                              |0193: cmpl-float v2, v2, v3
+0036ee: 3d02 3100                              |0195: if-lez v2, 01c6 // +0031
+0036f2: 0800 1c00                              |0197: move-object/from16 v0, v28
+0036f6: 5202 1e00                              |0199: iget v2, v0, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+0036fa: 8922                                   |019b: float-to-double v2, v2
+0036fc: 1804 9a99 9999 9999 a93f               |019c: const-wide v4, #double 0.05 // #3fa999999999999a
+003706: cc42                                   |01a1: sub-double/2addr v2, v4
+003708: 8c22                                   |01a2: double-to-float v2, v2
+00370a: 0800 1c00                              |01a3: move-object/from16 v0, v28
+00370e: 5902 1e00                              |01a5: iput v2, v0, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+003712: 0800 1c00                              |01a7: move-object/from16 v0, v28
+003716: 5202 1e00                              |01a9: iget v2, v0, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+00371a: 1203                                   |01ab: const/4 v3, #int 0 // #0
+00371c: 2e02 0203                              |01ac: cmpg-float v2, v2, v3
+003720: 3c02 1100                              |01ae: if-gtz v2, 01bf // +0011
+003724: 1202                                   |01b0: const/4 v2, #int 0 // #0
+003726: 0800 1c00                              |01b1: move-object/from16 v0, v28
+00372a: 5902 1e00                              |01b3: iput v2, v0, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+00372e: 1202                                   |01b5: const/4 v2, #int 0 // #0
+003730: 0800 1c00                              |01b6: move-object/from16 v0, v28
+003734: 5902 1f00                              |01b8: iput v2, v0, Lcom/google/android/checkers/CheckersView;.m:I // field@001f
+003738: 1202                                   |01ba: const/4 v2, #int 0 // #0
+00373a: 0800 1c00                              |01bb: move-object/from16 v0, v28
+00373e: 5902 2000                              |01bd: iput v2, v0, Lcom/google/android/checkers/CheckersView;.n:I // field@0020
+003742: 1602 3200                              |01bf: const-wide/16 v2, #int 50 // #32
+003746: 0800 1c00                              |01c1: move-object/from16 v0, v28
+00374a: 6e30 6e00 2003                         |01c3: invoke-virtual {v0, v2, v3}, Lcom/google/android/checkers/CheckersView;.postInvalidateDelayed:(J)V // method@006e
+003750: 1e1c                                   |01c6: monitor-exit v28
+003752: 0e00                                   |01c7: return-void
+003754: 0142                                   |01c8: move v2, v4
+003756: 2900 46fe                              |01c9: goto/16 000f // -01ba
+00375a: d803 1702                              |01cb: add-int/lit8 v3, v23, #int 2 // #02
+00375e: da02 1402                              |01cd: mul-int/lit8 v2, v20, #int 2 // #02
+003762: 9102 1702                              |01cf: sub-int v2, v23, v2
+003766: 9102 0219                              |01d1: sub-int v2, v2, v25
+00376a: 0211 0200                              |01d3: move/from16 v17, v2
+00376e: 0212 0300                              |01d5: move/from16 v18, v3
+003772: 0213 1400                              |01d7: move/from16 v19, v20
+003776: 0215 0300                              |01d9: move/from16 v21, v3
+00377a: 2900 53fe                              |01db: goto/16 002e // -01ad
+00377e: 0800 1c00                              |01dd: move-object/from16 v0, v28
+003782: 5408 1500                              |01df: iget-object v8, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003786: 1203                                   |01e1: const/4 v3, #int 0 // #0
+003788: 1204                                   |01e2: const/4 v4, #int 0 // #0
+00378a: 0200 1700                              |01e3: move/from16 v0, v23
+00378e: 8205                                   |01e5: int-to-float v5, v0
+003790: 0200 1700                              |01e6: move/from16 v0, v23
+003794: 8206                                   |01e8: int-to-float v6, v0
+003796: 0800 1c00                              |01e9: move-object/from16 v0, v28
+00379a: 5407 1700                              |01eb: iget-object v7, v0, Lcom/google/android/checkers/CheckersView;.e:Landroid/graphics/Paint; // field@0017
+00379e: 0802 1d00                              |01ed: move-object/from16 v2, v29
+0037a2: 7406 1f00 0200                         |01ef: invoke-virtual/range {v2, v3, v4, v5, v6, v7}, Landroid/graphics/Canvas;.drawRect:(FFFFLandroid/graphics/Paint;)V // method@001f
+0037a8: 0787                                   |01f2: move-object v7, v8
+0037aa: 2900 64fe                              |01f3: goto/16 0057 // -019c
+0037ae: 920a 1609                              |01f5: mul-int v10, v22, v9
+0037b2: dd02 0901                              |01f7: and-int/lit8 v2, v9, #int 1 // #01
+0037b6: 0128                                   |01f9: move v8, v2
+0037b8: 1302 0800                              |01fa: const/16 v2, #int 8 // #8
+0037bc: 3428 0700                              |01fc: if-lt v8, v2, 0203 // +0007
+0037c0: d802 0901                              |01fe: add-int/lit8 v2, v9, #int 1 // #01
+0037c4: 0129                                   |0200: move v9, v2
+0037c6: 2900 58fe                              |0201: goto/16 0059 // -01a8
+0037ca: 9202 1608                              |0203: mul-int v2, v22, v8
+0037ce: 82a3                                   |0205: int-to-float v3, v10
+0037d0: 8224                                   |0206: int-to-float v4, v2
+0037d2: 9005 0a16                              |0207: add-int v5, v10, v22
+0037d6: 8255                                   |0209: int-to-float v5, v5
+0037d8: 9002 0216                              |020a: add-int v2, v2, v22
+0037dc: 8226                                   |020c: int-to-float v6, v2
+0037de: 0802 1d00                              |020d: move-object/from16 v2, v29
+0037e2: 7406 1f00 0200                         |020f: invoke-virtual/range {v2, v3, v4, v5, v6, v7}, Landroid/graphics/Canvas;.drawRect:(FFFFLandroid/graphics/Paint;)V // method@001f
+0037e8: d802 0802                              |0212: add-int/lit8 v2, v8, #int 2 // #02
+0037ec: 0128                                   |0214: move v8, v2
+0037ee: 28e5                                   |0215: goto 01fa // -001b
+0037f0: d902 1001                              |0216: rsub-int/lit8 v2, v16, #int 1 // #01
+0037f4: dd02 0201                              |0218: and-int/lit8 v2, v2, #int 1 // #01
+0037f8: 012e                                   |021a: move v14, v2
+0037fa: 013f                                   |021b: move v15, v3
+0037fc: 1302 0800                              |021c: const/16 v2, #int 8 // #8
+003800: 342e 0900                              |021e: if-lt v14, v2, 0227 // +0009
+003804: d802 1001                              |0220: add-int/lit8 v2, v16, #int 1 // #01
+003808: 0210 0200                              |0222: move/from16 v16, v2
+00380c: 01f3                                   |0224: move v3, v15
+00380e: 2900 40fe                              |0225: goto/16 0065 // -01c0
+003812: 0800 1c00                              |0227: move-object/from16 v0, v28
+003816: 5502 0400                              |0229: iget-boolean v2, v0, Lcom/google/android/checkers/CheckersView;.C:Z // field@0004
+00381a: 3802 5d00                              |022b: if-eqz v2, 0288 // +005d
+00381e: d902 0e07                              |022d: rsub-int/lit8 v2, v14, #int 7 // #07
+003822: 9203 1602                              |022f: mul-int v3, v22, v2
+003826: d902 1007                              |0231: rsub-int/lit8 v2, v16, #int 7 // #07
+00382a: 9202 0216                              |0233: mul-int v2, v2, v22
+00382e: 0135                                   |0235: move v5, v3
+003830: 901a 1805                              |0236: add-int v26, v24, v5
+003834: 901b 1802                              |0238: add-int v27, v24, v2
+003838: 0800 1c00                              |023a: move-object/from16 v0, v28
+00383c: 5203 2800                              |023c: iget v3, v0, Lcom/google/android/checkers/CheckersView;.v:I // field@0028
+003840: b5f3                                   |023e: and-int/2addr v3, v15
+003842: 3803 4f00                              |023f: if-eqz v3, 028e // +004f
+003846: d803 0501                              |0241: add-int/lit8 v3, v5, #int 1 // #01
+00384a: 8233                                   |0243: int-to-float v3, v3
+00384c: d804 0201                              |0244: add-int/lit8 v4, v2, #int 1 // #01
+003850: 8244                                   |0246: int-to-float v4, v4
+003852: 9005 0516                              |0247: add-int v5, v5, v22
+003856: d805 05ff                              |0249: add-int/lit8 v5, v5, #int -1 // #ff
+00385a: 8255                                   |024b: int-to-float v5, v5
+00385c: 9002 0216                              |024c: add-int v2, v2, v22
+003860: d802 02ff                              |024e: add-int/lit8 v2, v2, #int -1 // #ff
+003864: 8226                                   |0250: int-to-float v6, v2
+003866: 0800 1c00                              |0251: move-object/from16 v0, v28
+00386a: 5407 1800                              |0253: iget-object v7, v0, Lcom/google/android/checkers/CheckersView;.f:Landroid/graphics/Paint; // field@0018
+00386e: 0802 1d00                              |0255: move-object/from16 v2, v29
+003872: 7406 1f00 0200                         |0257: invoke-virtual/range {v2, v3, v4, v5, v6, v7}, Landroid/graphics/Canvas;.drawRect:(FFFFLandroid/graphics/Paint;)V // method@001f
+003878: 0800 1c00                              |025a: move-object/from16 v0, v28
+00387c: 5202 2400                              |025c: iget v2, v0, Lcom/google/android/checkers/CheckersView;.r:I // field@0024
+003880: b5f2                                   |025e: and-int/2addr v2, v15
+003882: 3802 7a00                              |025f: if-eqz v2, 02d9 // +007a
+003886: 0800 1c00                              |0261: move-object/from16 v0, v28
+00388a: 5407 1400                              |0263: iget-object v7, v0, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+00388e: 0800 1c00                              |0265: move-object/from16 v0, v28
+003892: 5408 1500                              |0267: iget-object v8, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003896: 1209                                   |0269: const/4 v9, #int 0 // #0
+003898: 0802 1d00                              |026a: move-object/from16 v2, v29
+00389c: 0203 1a00                              |026c: move/from16 v3, v26
+0038a0: 0204 1b00                              |026e: move/from16 v4, v27
+0038a4: 0205 1800                              |0270: move/from16 v5, v24
+0038a8: 0206 1900                              |0272: move/from16 v6, v25
+0038ac: 7708 5500 0200                         |0274: invoke-static/range {v2, v3, v4, v5, v6, v7, v8, v9}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/graphics/Canvas;IIIILandroid/graphics/Paint;Landroid/graphics/Paint;Z)V // method@0055
+0038b2: d802 0d01                              |0277: add-int/lit8 v2, v13, #int 1 // #01
+0038b6: 01b3                                   |0279: move v3, v11
+0038b8: 01c4                                   |027a: move v4, v12
+0038ba: 0125                                   |027b: move v5, v2
+0038bc: 01a2                                   |027c: move v2, v10
+0038be: e007 0f01                              |027d: shl-int/lit8 v7, v15, #int 1 // #01
+0038c2: d806 0e02                              |027f: add-int/lit8 v6, v14, #int 2 // #02
+0038c6: 016e                                   |0281: move v14, v6
+0038c8: 012a                                   |0282: move v10, v2
+0038ca: 013b                                   |0283: move v11, v3
+0038cc: 014c                                   |0284: move v12, v4
+0038ce: 015d                                   |0285: move v13, v5
+0038d0: 017f                                   |0286: move v15, v7
+0038d2: 2895                                   |0287: goto 021c // -006b
+0038d4: 9203 160e                              |0288: mul-int v3, v22, v14
+0038d8: 9202 1610                              |028a: mul-int v2, v22, v16
+0038dc: 0135                                   |028c: move v5, v3
+0038de: 28a9                                   |028d: goto 0236 // -0057
+0038e0: 0800 1c00                              |028e: move-object/from16 v0, v28
+0038e4: 5203 2900                              |0290: iget v3, v0, Lcom/google/android/checkers/CheckersView;.w:I // field@0029
+0038e8: b5f3                                   |0292: and-int/2addr v3, v15
+0038ea: 3803 1f00                              |0293: if-eqz v3, 02b2 // +001f
+0038ee: d803 0501                              |0295: add-int/lit8 v3, v5, #int 1 // #01
+0038f2: 8233                                   |0297: int-to-float v3, v3
+0038f4: d804 0201                              |0298: add-int/lit8 v4, v2, #int 1 // #01
+0038f8: 8244                                   |029a: int-to-float v4, v4
+0038fa: 9005 0516                              |029b: add-int v5, v5, v22
+0038fe: d805 05ff                              |029d: add-int/lit8 v5, v5, #int -1 // #ff
+003902: 8255                                   |029f: int-to-float v5, v5
+003904: 9002 0216                              |02a0: add-int v2, v2, v22
+003908: d802 02ff                              |02a2: add-int/lit8 v2, v2, #int -1 // #ff
+00390c: 8226                                   |02a4: int-to-float v6, v2
+00390e: 0800 1c00                              |02a5: move-object/from16 v0, v28
+003912: 5407 1900                              |02a7: iget-object v7, v0, Lcom/google/android/checkers/CheckersView;.g:Landroid/graphics/Paint; // field@0019
+003916: 0802 1d00                              |02a9: move-object/from16 v2, v29
+00391a: 7406 1f00 0200                         |02ab: invoke-virtual/range {v2, v3, v4, v5, v6, v7}, Landroid/graphics/Canvas;.drawRect:(FFFFLandroid/graphics/Paint;)V // method@001f
+003920: 28ac                                   |02ae: goto 025a // -0054
+003922: 0d02                                   |02af: move-exception v2
+003924: 1e1c                                   |02b0: monitor-exit v28
+003926: 2702                                   |02b1: throw v2
+003928: 0800 1c00                              |02b2: move-object/from16 v0, v28
+00392c: 5503 0200                              |02b4: iget-boolean v3, v0, Lcom/google/android/checkers/CheckersView;.A:Z // field@0002
+003930: 3803 a4ff                              |02b6: if-eqz v3, 025a // -005c
+003934: 0800 1c00                              |02b8: move-object/from16 v0, v28
+003938: 5203 2a00                              |02ba: iget v3, v0, Lcom/google/android/checkers/CheckersView;.x:I // field@002a
+00393c: b5f3                                   |02bc: and-int/2addr v3, v15
+00393e: 3803 9dff                              |02bd: if-eqz v3, 025a // -0063
+003942: d803 0501                              |02bf: add-int/lit8 v3, v5, #int 1 // #01
+003946: 8233                                   |02c1: int-to-float v3, v3
+003948: d804 0201                              |02c2: add-int/lit8 v4, v2, #int 1 // #01
+00394c: 8244                                   |02c4: int-to-float v4, v4
+00394e: 9005 0516                              |02c5: add-int v5, v5, v22
+003952: d805 05ff                              |02c7: add-int/lit8 v5, v5, #int -1 // #ff
+003956: 8255                                   |02c9: int-to-float v5, v5
+003958: 9002 0216                              |02ca: add-int v2, v2, v22
+00395c: d802 02ff                              |02cc: add-int/lit8 v2, v2, #int -1 // #ff
+003960: 8226                                   |02ce: int-to-float v6, v2
+003962: 0800 1c00                              |02cf: move-object/from16 v0, v28
+003966: 5407 1b00                              |02d1: iget-object v7, v0, Lcom/google/android/checkers/CheckersView;.i:Landroid/graphics/Paint; // field@001b
+00396a: 0802 1d00                              |02d3: move-object/from16 v2, v29
+00396e: 7406 1f00 0200                         |02d5: invoke-virtual/range {v2, v3, v4, v5, v6, v7}, Landroid/graphics/Canvas;.drawRect:(FFFFLandroid/graphics/Paint;)V // method@001f
+003974: 2882                                   |02d8: goto 025a // -007e
+003976: 0800 1c00                              |02d9: move-object/from16 v0, v28
+00397a: 5202 2500                              |02db: iget v2, v0, Lcom/google/android/checkers/CheckersView;.s:I // field@0025
+00397e: b5f2                                   |02dd: and-int/2addr v2, v15
+003980: 3802 1f00                              |02de: if-eqz v2, 02fd // +001f
+003984: 0800 1c00                              |02e0: move-object/from16 v0, v28
+003988: 5407 1500                              |02e2: iget-object v7, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+00398c: 0800 1c00                              |02e4: move-object/from16 v0, v28
+003990: 5408 1400                              |02e6: iget-object v8, v0, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+003994: 1209                                   |02e8: const/4 v9, #int 0 // #0
+003996: 0802 1d00                              |02e9: move-object/from16 v2, v29
+00399a: 0203 1a00                              |02eb: move/from16 v3, v26
+00399e: 0204 1b00                              |02ed: move/from16 v4, v27
+0039a2: 0205 1800                              |02ef: move/from16 v5, v24
+0039a6: 0206 1900                              |02f1: move/from16 v6, v25
+0039aa: 7708 5500 0200                         |02f3: invoke-static/range {v2, v3, v4, v5, v6, v7, v8, v9}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/graphics/Canvas;IIIILandroid/graphics/Paint;Landroid/graphics/Paint;Z)V // method@0055
+0039b0: d802 0b01                              |02f6: add-int/lit8 v2, v11, #int 1 // #01
+0039b4: 0123                                   |02f8: move v3, v2
+0039b6: 01c4                                   |02f9: move v4, v12
+0039b8: 01d5                                   |02fa: move v5, v13
+0039ba: 01a2                                   |02fb: move v2, v10
+0039bc: 2881                                   |02fc: goto 027d // -007f
+0039be: 0800 1c00                              |02fd: move-object/from16 v0, v28
+0039c2: 5202 2600                              |02ff: iget v2, v0, Lcom/google/android/checkers/CheckersView;.t:I // field@0026
+0039c6: b5f2                                   |0301: and-int/2addr v2, v15
+0039c8: 3802 2000                              |0302: if-eqz v2, 0322 // +0020
+0039cc: 0800 1c00                              |0304: move-object/from16 v0, v28
+0039d0: 5407 1400                              |0306: iget-object v7, v0, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+0039d4: 0800 1c00                              |0308: move-object/from16 v0, v28
+0039d8: 5408 1500                              |030a: iget-object v8, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+0039dc: 1219                                   |030c: const/4 v9, #int 1 // #1
+0039de: 0802 1d00                              |030d: move-object/from16 v2, v29
+0039e2: 0203 1a00                              |030f: move/from16 v3, v26
+0039e6: 0204 1b00                              |0311: move/from16 v4, v27
+0039ea: 0205 1800                              |0313: move/from16 v5, v24
+0039ee: 0206 1900                              |0315: move/from16 v6, v25
+0039f2: 7708 5500 0200                         |0317: invoke-static/range {v2, v3, v4, v5, v6, v7, v8, v9}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/graphics/Canvas;IIIILandroid/graphics/Paint;Landroid/graphics/Paint;Z)V // method@0055
+0039f8: d802 0c01                              |031a: add-int/lit8 v2, v12, #int 1 // #01
+0039fc: 01b3                                   |031c: move v3, v11
+0039fe: 0124                                   |031d: move v4, v2
+003a00: 01d5                                   |031e: move v5, v13
+003a02: 01a2                                   |031f: move v2, v10
+003a04: 2900 5dff                              |0320: goto/16 027d // -00a3
+003a08: 0800 1c00                              |0322: move-object/from16 v0, v28
+003a0c: 5202 2700                              |0324: iget v2, v0, Lcom/google/android/checkers/CheckersView;.u:I // field@0027
+003a10: b5f2                                   |0326: and-int/2addr v2, v15
+003a12: 3802 1f00                              |0327: if-eqz v2, 0346 // +001f
+003a16: 0800 1c00                              |0329: move-object/from16 v0, v28
+003a1a: 5407 1500                              |032b: iget-object v7, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003a1e: 0800 1c00                              |032d: move-object/from16 v0, v28
+003a22: 5408 1400                              |032f: iget-object v8, v0, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+003a26: 1219                                   |0331: const/4 v9, #int 1 // #1
+003a28: 0802 1d00                              |0332: move-object/from16 v2, v29
+003a2c: 0203 1a00                              |0334: move/from16 v3, v26
+003a30: 0204 1b00                              |0336: move/from16 v4, v27
+003a34: 0205 1800                              |0338: move/from16 v5, v24
+003a38: 0206 1900                              |033a: move/from16 v6, v25
+003a3c: 7708 5500 0200                         |033c: invoke-static/range {v2, v3, v4, v5, v6, v7, v8, v9}, Lcom/google/android/checkers/CheckersView;.a:(Landroid/graphics/Canvas;IIIILandroid/graphics/Paint;Landroid/graphics/Paint;Z)V // method@0055
+003a42: d802 0a01                              |033f: add-int/lit8 v2, v10, #int 1 // #01
+003a46: 01b3                                   |0341: move v3, v11
+003a48: 01c4                                   |0342: move v4, v12
+003a4a: 01d5                                   |0343: move v5, v13
+003a4c: 2900 39ff                              |0344: goto/16 027d // -00c7
+003a50: 0800 1c00                              |0346: move-object/from16 v0, v28
+003a54: 5202 2000                              |0348: iget v2, v0, Lcom/google/android/checkers/CheckersView;.n:I // field@0020
+003a58: b5f2                                   |034a: and-int/2addr v2, v15
+003a5a: 3802 3600                              |034b: if-eqz v2, 0381 // +0036
+003a5e: 0200 1a00                              |034d: move/from16 v0, v26
+003a62: 8202                                   |034f: int-to-float v2, v0
+003a64: 0200 1b00                              |0350: move/from16 v0, v27
+003a68: 8203                                   |0352: int-to-float v3, v0
+003a6a: d804 18fe                              |0353: add-int/lit8 v4, v24, #int -2 // #fe
+003a6e: 8244                                   |0355: int-to-float v4, v4
+003a70: 0800 1c00                              |0356: move-object/from16 v0, v28
+003a74: 5205 1e00                              |0358: iget v5, v0, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+003a78: c854                                   |035a: mul-float/2addr v4, v5
+003a7a: 0800 1c00                              |035b: move-object/from16 v0, v28
+003a7e: 5405 1500                              |035d: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003a82: 0800 1d00                              |035f: move-object/from16 v0, v29
+003a86: 6e55 1c00 2043                         |0361: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+003a8c: 0200 1a00                              |0364: move/from16 v0, v26
+003a90: 8202                                   |0366: int-to-float v2, v0
+003a92: 0200 1b00                              |0367: move/from16 v0, v27
+003a96: 8203                                   |0369: int-to-float v3, v0
+003a98: d804 18fc                              |036a: add-int/lit8 v4, v24, #int -4 // #fc
+003a9c: 8244                                   |036c: int-to-float v4, v4
+003a9e: 0800 1c00                              |036d: move-object/from16 v0, v28
+003aa2: 5205 1e00                              |036f: iget v5, v0, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+003aa6: c854                                   |0371: mul-float/2addr v4, v5
+003aa8: 0800 1c00                              |0372: move-object/from16 v0, v28
+003aac: 5405 1400                              |0374: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+003ab0: 0800 1d00                              |0376: move-object/from16 v0, v29
+003ab4: 6e55 1c00 2043                         |0378: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+003aba: 01a2                                   |037b: move v2, v10
+003abc: 01b3                                   |037c: move v3, v11
+003abe: 01c4                                   |037d: move v4, v12
+003ac0: 01d5                                   |037e: move v5, v13
+003ac2: 2900 fefe                              |037f: goto/16 027d // -0102
+003ac6: 0800 1c00                              |0381: move-object/from16 v0, v28
+003aca: 5202 1f00                              |0383: iget v2, v0, Lcom/google/android/checkers/CheckersView;.m:I // field@001f
+003ace: b5f2                                   |0385: and-int/2addr v2, v15
+003ad0: 3802 3000                              |0386: if-eqz v2, 03b6 // +0030
+003ad4: 0200 1a00                              |0388: move/from16 v0, v26
+003ad8: 8202                                   |038a: int-to-float v2, v0
+003ada: 0200 1b00                              |038b: move/from16 v0, v27
+003ade: 8203                                   |038d: int-to-float v3, v0
+003ae0: d804 18fe                              |038e: add-int/lit8 v4, v24, #int -2 // #fe
+003ae4: 8244                                   |0390: int-to-float v4, v4
+003ae6: 0800 1c00                              |0391: move-object/from16 v0, v28
+003aea: 5205 1e00                              |0393: iget v5, v0, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+003aee: c854                                   |0395: mul-float/2addr v4, v5
+003af0: 0800 1c00                              |0396: move-object/from16 v0, v28
+003af4: 5405 1400                              |0398: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+003af8: 0800 1d00                              |039a: move-object/from16 v0, v29
+003afc: 6e55 1c00 2043                         |039c: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+003b02: 0200 1a00                              |039f: move/from16 v0, v26
+003b06: 8202                                   |03a1: int-to-float v2, v0
+003b08: 0200 1b00                              |03a2: move/from16 v0, v27
+003b0c: 8203                                   |03a4: int-to-float v3, v0
+003b0e: d804 18fc                              |03a5: add-int/lit8 v4, v24, #int -4 // #fc
+003b12: 8244                                   |03a7: int-to-float v4, v4
+003b14: 0800 1c00                              |03a8: move-object/from16 v0, v28
+003b18: 5205 1e00                              |03aa: iget v5, v0, Lcom/google/android/checkers/CheckersView;.l:F // field@001e
+003b1c: c854                                   |03ac: mul-float/2addr v4, v5
+003b1e: 0800 1c00                              |03ad: move-object/from16 v0, v28
+003b22: 5405 1500                              |03af: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003b26: 0800 1d00                              |03b1: move-object/from16 v0, v29
+003b2a: 6e55 1c00 2043                         |03b3: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawCircle:(FFFLandroid/graphics/Paint;)V // method@001c
+003b30: 01a2                                   |03b6: move v2, v10
+003b32: 01b3                                   |03b7: move v3, v11
+003b34: 01c4                                   |03b8: move v4, v12
+003b36: 01d5                                   |03b9: move v5, v13
+003b38: 2900 c3fe                              |03ba: goto/16 027d // -013d
+003b3c: 1a02 9c00                              |03bc: const-string v2, "White" // string@009c
+003b40: 0200 1500                              |03be: move/from16 v0, v21
+003b44: 8203                                   |03c0: int-to-float v3, v0
+003b46: 0200 1300                              |03c1: move/from16 v0, v19
+003b4a: 8204                                   |03c3: int-to-float v4, v0
+003b4c: 0800 1c00                              |03c4: move-object/from16 v0, v28
+003b50: 5405 1500                              |03c6: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003b54: 0800 1d00                              |03c8: move-object/from16 v0, v29
+003b58: 6e55 2000 2043                         |03ca: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003b5e: 1a02 0b00                              |03cd: const-string v2, "Black" // string@000b
+003b62: 0200 1500                              |03cf: move/from16 v0, v21
+003b66: 8203                                   |03d1: int-to-float v3, v0
+003b68: 9004 1314                              |03d2: add-int v4, v19, v20
+003b6c: 8244                                   |03d4: int-to-float v4, v4
+003b6e: 0800 1c00                              |03d5: move-object/from16 v0, v28
+003b72: 5405 1500                              |03d7: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003b76: 0800 1d00                              |03d9: move-object/from16 v0, v29
+003b7a: 6e55 2000 2043                         |03db: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003b80: 1a02 7200                              |03de: const-string v2, "Moves" // string@0072
+003b84: 0200 1500                              |03e0: move/from16 v0, v21
+003b88: 8203                                   |03e2: int-to-float v3, v0
+003b8a: da04 1402                              |03e3: mul-int/lit8 v4, v20, #int 2 // #02
+003b8e: 9004 0413                              |03e5: add-int v4, v4, v19
+003b92: 8244                                   |03e7: int-to-float v4, v4
+003b94: 0800 1c00                              |03e8: move-object/from16 v0, v28
+003b98: 5405 1500                              |03ea: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003b9c: 0800 1d00                              |03ec: move-object/from16 v0, v29
+003ba0: 6e55 2000 2043                         |03ee: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003ba6: 2202 3000                              |03f1: new-instance v2, Ljava/lang/StringBuilder; // type@0030
+003baa: 1a03 0300                              |03f3: const-string v3, ":  " // string@0003
+003bae: 7020 a600 3200                         |03f5: invoke-direct {v2, v3}, Ljava/lang/StringBuilder;.<init>:(Ljava/lang/String;)V // method@00a6
+003bb4: 6e20 a700 d200                         |03f8: invoke-virtual {v2, v13}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+003bba: 0c02                                   |03fb: move-result-object v2
+003bbc: 1a03 0200                              |03fc: const-string v3, "+" // string@0002
+003bc0: 6e20 a900 3200                         |03fe: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00a9
+003bc6: 0c02                                   |0401: move-result-object v2
+003bc8: 6e20 a700 c200                         |0402: invoke-virtual {v2, v12}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+003bce: 0c02                                   |0405: move-result-object v2
+003bd0: 6e10 aa00 0200                         |0406: invoke-virtual {v2}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00aa
+003bd6: 0c02                                   |0409: move-result-object v2
+003bd8: da03 1403                              |040a: mul-int/lit8 v3, v20, #int 3 // #03
+003bdc: 9003 0315                              |040c: add-int v3, v3, v21
+003be0: 8233                                   |040e: int-to-float v3, v3
+003be2: 0200 1300                              |040f: move/from16 v0, v19
+003be6: 8204                                   |0411: int-to-float v4, v0
+003be8: 0800 1c00                              |0412: move-object/from16 v0, v28
+003bec: 5405 1500                              |0414: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003bf0: 0800 1d00                              |0416: move-object/from16 v0, v29
+003bf4: 6e55 2000 2043                         |0418: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003bfa: 2202 3000                              |041b: new-instance v2, Ljava/lang/StringBuilder; // type@0030
+003bfe: 1a03 0300                              |041d: const-string v3, ":  " // string@0003
+003c02: 7020 a600 3200                         |041f: invoke-direct {v2, v3}, Ljava/lang/StringBuilder;.<init>:(Ljava/lang/String;)V // method@00a6
+003c08: 6e20 a700 b200                         |0422: invoke-virtual {v2, v11}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+003c0e: 0c02                                   |0425: move-result-object v2
+003c10: 1a03 0200                              |0426: const-string v3, "+" // string@0002
+003c14: 6e20 a900 3200                         |0428: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00a9
+003c1a: 0c02                                   |042b: move-result-object v2
+003c1c: 6e20 a700 a200                         |042c: invoke-virtual {v2, v10}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+003c22: 0c02                                   |042f: move-result-object v2
+003c24: 6e10 aa00 0200                         |0430: invoke-virtual {v2}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00aa
+003c2a: 0c02                                   |0433: move-result-object v2
+003c2c: da03 1403                              |0434: mul-int/lit8 v3, v20, #int 3 // #03
+003c30: 9003 0315                              |0436: add-int v3, v3, v21
+003c34: 8233                                   |0438: int-to-float v3, v3
+003c36: 9004 1314                              |0439: add-int v4, v19, v20
+003c3a: 8244                                   |043b: int-to-float v4, v4
+003c3c: 0800 1c00                              |043c: move-object/from16 v0, v28
+003c40: 5405 1500                              |043e: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003c44: 0800 1d00                              |0440: move-object/from16 v0, v29
+003c48: 6e55 2000 2043                         |0442: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003c4e: 2202 3000                              |0445: new-instance v2, Ljava/lang/StringBuilder; // type@0030
+003c52: 1a03 0300                              |0447: const-string v3, ":  " // string@0003
+003c56: 7020 a600 3200                         |0449: invoke-direct {v2, v3}, Ljava/lang/StringBuilder;.<init>:(Ljava/lang/String;)V // method@00a6
+003c5c: 0800 1c00                              |044c: move-object/from16 v0, v28
+003c60: 5203 0e00                              |044e: iget v3, v0, Lcom/google/android/checkers/CheckersView;.M:I // field@000e
+003c64: 6e20 a700 3200                         |0450: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00a7
+003c6a: 0c02                                   |0453: move-result-object v2
+003c6c: 6e10 aa00 0200                         |0454: invoke-virtual {v2}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00aa
+003c72: 0c02                                   |0457: move-result-object v2
+003c74: da03 1403                              |0458: mul-int/lit8 v3, v20, #int 3 // #03
+003c78: 9003 0315                              |045a: add-int v3, v3, v21
+003c7c: 8233                                   |045c: int-to-float v3, v3
+003c7e: da04 1402                              |045d: mul-int/lit8 v4, v20, #int 2 // #02
+003c82: 9004 0413                              |045f: add-int v4, v4, v19
+003c86: 8244                                   |0461: int-to-float v4, v4
+003c88: 0800 1c00                              |0462: move-object/from16 v0, v28
+003c8c: 5405 1500                              |0464: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003c90: 0800 1d00                              |0466: move-object/from16 v0, v29
+003c94: 6e55 2000 2043                         |0468: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003c9a: 2900 3ffc                              |046b: goto/16 00aa // -03c1
+003c9e: 1a02 0a00                              |046d: const-string v2, "BLACK'S MOVE?" // string@000a
+003ca2: 0200 1200                              |046f: move/from16 v0, v18
+003ca6: 8203                                   |0471: int-to-float v3, v0
+003ca8: 9004 1114                              |0472: add-int v4, v17, v20
+003cac: 8244                                   |0474: int-to-float v4, v4
+003cae: 0800 1c00                              |0475: move-object/from16 v0, v28
+003cb2: 5405 1500                              |0477: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003cb6: 0800 1d00                              |0479: move-object/from16 v0, v29
+003cba: 6e55 2000 2043                         |047b: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003cc0: 2900 4afc                              |047e: goto/16 00c8 // -03b6
+003cc4: 1a02 9a00                              |0480: const-string v2, "WHITE'S MOVE?" // string@009a
+003cc8: 0200 1200                              |0482: move/from16 v0, v18
+003ccc: 8203                                   |0484: int-to-float v3, v0
+003cce: 9004 1114                              |0485: add-int v4, v17, v20
+003cd2: 8244                                   |0487: int-to-float v4, v4
+003cd4: 0800 1c00                              |0488: move-object/from16 v0, v28
+003cd8: 5405 1500                              |048a: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003cdc: 0800 1d00                              |048c: move-object/from16 v0, v29
+003ce0: 6e55 2000 2043                         |048e: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003ce6: 2900 37fc                              |0491: goto/16 00c8 // -03c9
+003cea: 1a02 8100                              |0493: const-string v2, "THINKING...." // string@0081
+003cee: 0200 1200                              |0495: move/from16 v0, v18
+003cf2: 8203                                   |0497: int-to-float v3, v0
+003cf4: 9004 1114                              |0498: add-int v4, v17, v20
+003cf8: 8244                                   |049a: int-to-float v4, v4
+003cfa: 0800 1c00                              |049b: move-object/from16 v0, v28
+003cfe: 5405 1500                              |049d: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003d02: 0800 1d00                              |049f: move-object/from16 v0, v29
+003d06: 6e55 2000 2043                         |04a1: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003d0c: 2900 24fc                              |04a4: goto/16 00c8 // -03dc
+003d10: 1a02 9900                              |04a6: const-string v2, "WHITE WINS" // string@0099
+003d14: 0200 1200                              |04a8: move/from16 v0, v18
+003d18: 8203                                   |04aa: int-to-float v3, v0
+003d1a: 9004 1114                              |04ab: add-int v4, v17, v20
+003d1e: 8244                                   |04ad: int-to-float v4, v4
+003d20: 0800 1c00                              |04ae: move-object/from16 v0, v28
+003d24: 5405 1500                              |04b0: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003d28: 0800 1d00                              |04b2: move-object/from16 v0, v29
+003d2c: 6e55 2000 2043                         |04b4: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003d32: 2900 11fc                              |04b7: goto/16 00c8 // -03ef
+003d36: 1a02 0900                              |04b9: const-string v2, "BLACK WINS" // string@0009
+003d3a: 0200 1200                              |04bb: move/from16 v0, v18
+003d3e: 8203                                   |04bd: int-to-float v3, v0
+003d40: 9004 1114                              |04be: add-int v4, v17, v20
+003d44: 8244                                   |04c0: int-to-float v4, v4
+003d46: 0800 1c00                              |04c1: move-object/from16 v0, v28
+003d4a: 5405 1500                              |04c3: iget-object v5, v0, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003d4e: 0800 1d00                              |04c5: move-object/from16 v0, v29
+003d52: 6e55 2000 2043                         |04c7: invoke-virtual {v0, v2, v3, v4, v5}, Landroid/graphics/Canvas;.drawText:(Ljava/lang/String;FFLandroid/graphics/Paint;)V // method@0020
+003d58: 2900 fefb                              |04ca: goto/16 00c8 // -0402
+003d5c: 4404 0a08                              |04cc: aget v4, v10, v8
+003d60: 4405 0b08                              |04ce: aget v5, v11, v8
+003d64: 0802 1c00                              |04d0: move-object/from16 v2, v28
+003d68: 0803 1d00                              |04d2: move-object/from16 v3, v29
+003d6c: 0206 1600                              |04d4: move/from16 v6, v22
+003d70: 0207 1800                              |04d6: move/from16 v7, v24
+003d74: 7606 5f00 0200                         |04d8: invoke-direct/range {v2, v3, v4, v5, v6, v7}, Lcom/google/android/checkers/CheckersView;.b:(Landroid/graphics/Canvas;IIII)V // method@005f
+003d7a: d802 0801                              |04db: add-int/lit8 v2, v8, #int 1 // #01
+003d7e: 0128                                   |04dd: move v8, v2
+003d80: 2900 12fc                              |04de: goto/16 00f0 // -03ee
+003d84: 0001 0600 0100 0000 a803 0000 ce03 ... |04e0: packed-switch-data (16 units)
+      catches       : 3
+        0x0001 - 0x01c6
+          <any> -> 0x02af
+        0x01dd - 0x02ae
+          <any> -> 0x02af
+        0x02b2 - 0x04db
+          <any> -> 0x02af
+      positions     : 
+      locals        : 
+
+    #12              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'e'
+      type          : '(Z)Z'
+      access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 104
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 0
+      insns size    : 19 16-bit code units
+003dc0:                                        |[003dc0] com.google.android.checkers.CheckersView.e:(Z)Z
+003dd0: 1d01                                   |0000: monitor-enter v1
+003dd2: 3802 0900                              |0001: if-eqz v2, 000a // +0009
+003dd6: 5510 0600                              |0003: iget-boolean v0, v1, Lcom/google/android/checkers/CheckersView;.E:Z // field@0006
+003dda: 3800 0900                              |0005: if-eqz v0, 000e // +0009
+003dde: 1200                                   |0007: const/4 v0, #int 0 // #0
+003de0: 5c10 0600                              |0008: iput-boolean v0, v1, Lcom/google/android/checkers/CheckersView;.E:Z // field@0006
+003de4: 5510 0600                              |000a: iget-boolean v0, v1, Lcom/google/android/checkers/CheckersView;.E:Z // field@0006
+003de8: 1e01                                   |000c: monitor-exit v1
+003dea: 0f00                                   |000d: return v0
+003dec: 1210                                   |000e: const/4 v0, #int 1 // #1
+003dee: 28f9                                   |000f: goto 0008 // -0007
+003df0: 0d00                                   |0010: move-exception v0
+003df2: 1e01                                   |0011: monitor-exit v1
+003df4: 2700                                   |0012: throw v0
+      catches       : 1
+        0x0003 - 0x000c
+          <any> -> 0x0010
+      positions     : 
+      locals        : 
+
+    #13              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'onSizeChanged'
+      type          : '(IIII)V'
+      access        : 0x20004 (PROTECTED DECLARED_SYNCHRONIZED)
+      method_idx    : 107
+      code          -
+      registers     : 8
+      ins           : 5
+      outs          : 2
+      insns size    : 52 16-bit code units
+003e04:                                        |[003e04] com.google.android.checkers.CheckersView.onSizeChanged:(IIII)V
+003e14: 1d03                                   |0000: monitor-enter v3
+003e16: 3554 2c00                              |0001: if-ge v4, v5, 002d // +002c
+003e1a: 0140                                   |0003: move v0, v4
+003e1c: db01 0018                              |0004: div-int/lit8 v1, v0, #int 24 // #18
+003e20: 8211                                   |0006: int-to-float v1, v1
+003e22: 3754 2b00                              |0007: if-le v4, v5, 0032 // +002b
+003e26: 9100 0400                              |0009: sub-int v0, v4, v0
+003e2a: db00 000a                              |000b: div-int/lit8 v0, v0, #int 10 // #0a
+003e2e: 8200                                   |000d: int-to-float v0, v0
+003e30: 2e02 0001                              |000e: cmpg-float v2, v0, v1
+003e34: 3b02 2200                              |0010: if-gez v2, 0032 // +0022
+003e38: 5431 1400                              |0012: iget-object v1, v3, Lcom/google/android/checkers/CheckersView;.b:Landroid/graphics/Paint; // field@0014
+003e3c: 6e20 2600 0100                         |0014: invoke-virtual {v1, v0}, Landroid/graphics/Paint;.setTextSize:(F)V // method@0026
+003e42: 5431 1500                              |0017: iget-object v1, v3, Lcom/google/android/checkers/CheckersView;.c:Landroid/graphics/Paint; // field@0015
+003e46: 6e20 2600 0100                         |0019: invoke-virtual {v1, v0}, Landroid/graphics/Paint;.setTextSize:(F)V // method@0026
+003e4c: 5431 1b00                              |001c: iget-object v1, v3, Lcom/google/android/checkers/CheckersView;.i:Landroid/graphics/Paint; // field@001b
+003e50: 6e20 2600 0100                         |001e: invoke-virtual {v1, v0}, Landroid/graphics/Paint;.setTextSize:(F)V // method@0026
+003e56: 5431 1800                              |0021: iget-object v1, v3, Lcom/google/android/checkers/CheckersView;.f:Landroid/graphics/Paint; // field@0018
+003e5a: 6e20 2600 0100                         |0023: invoke-virtual {v1, v0}, Landroid/graphics/Paint;.setTextSize:(F)V // method@0026
+003e60: 8700                                   |0026: float-to-int v0, v0
+003e62: d800 0001                              |0027: add-int/lit8 v0, v0, #int 1 // #01
+003e66: 5930 1d00                              |0029: iput v0, v3, Lcom/google/android/checkers/CheckersView;.k:I // field@001d
+003e6a: 1e03                                   |002b: monitor-exit v3
+003e6c: 0e00                                   |002c: return-void
+003e6e: 0150                                   |002d: move v0, v5
+003e70: 28d6                                   |002e: goto 0004 // -002a
+003e72: 0d00                                   |002f: move-exception v0
+003e74: 1e03                                   |0030: monitor-exit v3
+003e76: 2700                                   |0031: throw v0
+003e78: 0110                                   |0032: move v0, v1
+003e7a: 28df                                   |0033: goto 0012 // -0021
+      catches       : 1
+        0x0004 - 0x002b
+          <any> -> 0x002f
+      positions     : 
+      locals        : 
+
+    #14              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'onTouchEvent'
+      type          : '(Landroid/view/MotionEvent;)Z'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 108
+      code          -
+      registers     : 8
+      ins           : 2
+      outs          : 6
+      insns size    : 41 16-bit code units
+003e88:                                        |[003e88] com.google.android.checkers.CheckersView.onTouchEvent:(Landroid/view/MotionEvent;)Z
+003e98: 1201                                   |0000: const/4 v1, #int 0 // #0
+003e9a: 6e10 3100 0700                         |0001: invoke-virtual {v7}, Landroid/view/MotionEvent;.getAction:()I // method@0031
+003ea0: 0a00                                   |0004: move-result v0
+003ea2: 3900 1f00                              |0005: if-nez v0, 0024 // +001f
+003ea6: 6e10 3200 0700                         |0007: invoke-virtual {v7}, Landroid/view/MotionEvent;.getX:()F // method@0032
+003eac: 0a00                                   |000a: move-result v0
+003eae: 6e10 3300 0700                         |000b: invoke-virtual {v7}, Landroid/view/MotionEvent;.getY:()F // method@0033
+003eb4: 0a02                                   |000e: move-result v2
+003eb6: 7030 5c00 0602                         |000f: invoke-direct {v6, v0, v2}, Lcom/google/android/checkers/CheckersView;.b:(FF)I // method@005c
+003ebc: 0a02                                   |0012: move-result v2
+003ebe: 3802 1100                              |0013: if-eqz v2, 0024 // +0011
+003ec2: 0760                                   |0015: move-object v0, v6
+003ec4: 0113                                   |0016: move v3, v1
+003ec6: 0114                                   |0017: move v4, v1
+003ec8: 0115                                   |0018: move v5, v1
+003eca: 7606 5b00 0000                         |0019: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/CheckersView;.a:(ZIIII)Z // method@005b
+003ed0: 0a00                                   |001c: move-result v0
+003ed2: 3800 0500                              |001d: if-eqz v0, 0022 // +0005
+003ed6: 6e10 6d00 0600                         |001f: invoke-virtual {v6}, Lcom/google/android/checkers/CheckersView;.postInvalidate:()V // method@006d
+003edc: 1210                                   |0022: const/4 v0, #int 1 // #1
+003ede: 0f00                                   |0023: return v0
+003ee0: 6f20 3900 7600                         |0024: invoke-super {v6, v7}, Landroid/view/View;.onTouchEvent:(Landroid/view/MotionEvent;)Z // method@0039
+003ee6: 0a00                                   |0027: move-result v0
+003ee8: 28fb                                   |0028: goto 0023 // -0005
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #15              : (in Lcom/google/android/checkers/CheckersView;)
+      name          : 'setLevel'
+      type          : '(I)V'
+      access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 112
+      code          -
+      registers     : 4
+      ins           : 2
+      outs          : 0
+      insns size    : 64 16-bit code units
+003eec:                                        |[003eec] com.google.android.checkers.CheckersView.setLevel:(I)V
+003efc: 1300 e803                              |0000: const/16 v0, #int 1000 // #3e8
+003f00: 1d02                                   |0002: monitor-enter v2
+003f02: 2b03 2700 0000                         |0003: packed-switch v3, 0000002a // +00000027
+003f08: 1233                                   |0006: const/4 v3, #int 3 // #3
+003f0a: 5421 2200                              |0007: iget-object v1, v2, Lcom/google/android/checkers/CheckersView;.p:Lcom/google/android/checkers/a; // field@0022
+003f0e: 5910 4100                              |0009: iput v0, v1, Lcom/google/android/checkers/a;.h:I // field@0041
+003f12: 5923 2c00                              |000b: iput v3, v2, Lcom/google/android/checkers/CheckersView;.z:I // field@002c
+003f16: 1e02                                   |000d: monitor-exit v2
+003f18: 0e00                                   |000e: return-void
+003f1a: 12f0                                   |000f: const/4 v0, #int -1 // #ff
+003f1c: 28f7                                   |0010: goto 0007 // -0009
+003f1e: 1200                                   |0011: const/4 v0, #int 0 // #0
+003f20: 28f5                                   |0012: goto 0007 // -000b
+003f22: 1300 6400                              |0013: const/16 v0, #int 100 // #64
+003f26: 28f2                                   |0015: goto 0007 // -000e
+003f28: 1300 8813                              |0016: const/16 v0, #int 5000 // #1388
+003f2c: 28ef                                   |0018: goto 0007 // -0011
+003f2e: 1300 1027                              |0019: const/16 v0, #int 10000 // #2710
+003f32: 28ec                                   |001b: goto 0007 // -0014
+003f34: 1300 983a                              |001c: const/16 v0, #int 15000 // #3a98
+003f38: 28e9                                   |001e: goto 0007 // -0017
+003f3a: 1300 3075                              |001f: const/16 v0, #int 30000 // #7530
+003f3e: 28e6                                   |0021: goto 0007 // -001a
+003f40: 1400 60ea 0000                         |0022: const v0, #float 8.40779e-41 // #0000ea60
+003f46: 28e2                                   |0025: goto 0007 // -001e
+003f48: 0d00                                   |0026: move-exception v0
+003f4a: 1e02                                   |0027: monitor-exit v2
+003f4c: 2700                                   |0028: throw v0
+003f4e: 0000                                   |0029: nop // spacer
+003f50: 0001 0900 0000 0000 0c00 0000 0e00 ... |002a: packed-switch-data (22 units)
+      catches       : 1
+        0x0007 - 0x000d
+          <any> -> 0x0026
+      positions     : 
+      locals        : 
+
+  source_file_idx   : -1 (unknown)
+
+Class #2 header:
+class_idx           : 32
+access_flags        : 17 (0x0011)
+superclass_idx      : 50
+interfaces_off      : 0 (0x000000)
+source_file_idx     : -1
+annotations_off     : 0 (0x000000)
+class_data_off      : 34848 (0x008820)
+static_fields_size  : 10
+instance_fields_size: 29
+direct_methods_size : 23
+virtual_methods_size: 6
+
+Class #2            -
+  Class descriptor  : 'Lcom/google/android/checkers/a;'
+  Access flags      : 0x0011 (PUBLIC FINAL)
+  Superclass        : 'Ljava/lang/Thread;'
+  Interfaces        -
+  Static fields     -
+    #0              : (in Lcom/google/android/checkers/a;)
+      name          : 'D'
+      type          : '[I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #1              : (in Lcom/google/android/checkers/a;)
+      name          : 'E'
+      type          : '[I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #2              : (in Lcom/google/android/checkers/a;)
+      name          : 'F'
+      type          : '[I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #3              : (in Lcom/google/android/checkers/a;)
+      name          : 'G'
+      type          : '[I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #4              : (in Lcom/google/android/checkers/a;)
+      name          : 'H'
+      type          : '[I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #5              : (in Lcom/google/android/checkers/a;)
+      name          : 'I'
+      type          : '[I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #6              : (in Lcom/google/android/checkers/a;)
+      name          : 'J'
+      type          : '[I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #7              : (in Lcom/google/android/checkers/a;)
+      name          : 'K'
+      type          : '[I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #8              : (in Lcom/google/android/checkers/a;)
+      name          : 'L'
+      type          : '[I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #9              : (in Lcom/google/android/checkers/a;)
+      name          : 'M'
+      type          : '[I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+  Instance fields   -
+    #0              : (in Lcom/google/android/checkers/a;)
+      name          : 'A'
+      type          : '[B'
+      access        : 0x0002 (PRIVATE)
+    #1              : (in Lcom/google/android/checkers/a;)
+      name          : 'B'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #2              : (in Lcom/google/android/checkers/a;)
+      name          : 'C'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #3              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '[I'
+      access        : 0x0001 (PUBLIC)
+    #4              : (in Lcom/google/android/checkers/a;)
+      name          : 'b'
+      type          : '[I'
+      access        : 0x0001 (PUBLIC)
+    #5              : (in Lcom/google/android/checkers/a;)
+      name          : 'c'
+      type          : 'I'
+      access        : 0x0001 (PUBLIC)
+    #6              : (in Lcom/google/android/checkers/a;)
+      name          : 'd'
+      type          : 'I'
+      access        : 0x0001 (PUBLIC)
+    #7              : (in Lcom/google/android/checkers/a;)
+      name          : 'e'
+      type          : 'I'
+      access        : 0x0001 (PUBLIC)
+    #8              : (in Lcom/google/android/checkers/a;)
+      name          : 'f'
+      type          : 'I'
+      access        : 0x0001 (PUBLIC)
+    #9              : (in Lcom/google/android/checkers/a;)
+      name          : 'g'
+      type          : 'I'
+      access        : 0x0001 (PUBLIC)
+    #10              : (in Lcom/google/android/checkers/a;)
+      name          : 'h'
+      type          : 'I'
+      access        : 0x0041 (PUBLIC VOLATILE)
+    #11              : (in Lcom/google/android/checkers/a;)
+      name          : 'i'
+      type          : 'Ljava/util/Random;'
+      access        : 0x0002 (PRIVATE)
+    #12              : (in Lcom/google/android/checkers/a;)
+      name          : 'j'
+      type          : 'Lcom/google/android/checkers/CheckersView;'
+      access        : 0x0002 (PRIVATE)
+    #13              : (in Lcom/google/android/checkers/a;)
+      name          : 'k'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #14              : (in Lcom/google/android/checkers/a;)
+      name          : 'l'
+      type          : 'J'
+      access        : 0x0002 (PRIVATE)
+    #15              : (in Lcom/google/android/checkers/a;)
+      name          : 'm'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #16              : (in Lcom/google/android/checkers/a;)
+      name          : 'n'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #17              : (in Lcom/google/android/checkers/a;)
+      name          : 'o'
+      type          : '[I'
+      access        : 0x0002 (PRIVATE)
+    #18              : (in Lcom/google/android/checkers/a;)
+      name          : 'p'
+      type          : '[I'
+      access        : 0x0002 (PRIVATE)
+    #19              : (in Lcom/google/android/checkers/a;)
+      name          : 'q'
+      type          : '[I'
+      access        : 0x0002 (PRIVATE)
+    #20              : (in Lcom/google/android/checkers/a;)
+      name          : 'r'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #21              : (in Lcom/google/android/checkers/a;)
+      name          : 's'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #22              : (in Lcom/google/android/checkers/a;)
+      name          : 't'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #23              : (in Lcom/google/android/checkers/a;)
+      name          : 'u'
+      type          : 'Z'
+      access        : 0x0002 (PRIVATE)
+    #24              : (in Lcom/google/android/checkers/a;)
+      name          : 'v'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #25              : (in Lcom/google/android/checkers/a;)
+      name          : 'w'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #26              : (in Lcom/google/android/checkers/a;)
+      name          : 'x'
+      type          : 'I'
+      access        : 0x0002 (PRIVATE)
+    #27              : (in Lcom/google/android/checkers/a;)
+      name          : 'y'
+      type          : '[I'
+      access        : 0x0002 (PRIVATE)
+    #28              : (in Lcom/google/android/checkers/a;)
+      name          : 'z'
+      type          : '[S'
+      access        : 0x0002 (PRIVATE)
+  Direct methods    -
+    #0              : (in Lcom/google/android/checkers/a;)
+      name          : '<clinit>'
+      type          : '()V'
+      access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 113
+      code          -
+      registers     : 8
+      ins           : 0
+      outs          : 0
+      insns size    : 1390 16-bit code units
+003f88:                                        |[003f88] com.google.android.checkers.a.<clinit>:()V
+003f98: 1227                                   |0000: const/4 v7, #int 2 // #2
+003f9a: 1306 1500                              |0001: const/16 v6, #int 21 // #15
+003f9e: 1305 1000                              |0003: const/16 v5, #int 16 // #10
+003fa2: 1304 0a00                              |0005: const/16 v4, #int 10 // #a
+003fa6: 1303 2000                              |0007: const/16 v3, #int 32 // #20
+003faa: 2330 3700                              |0009: new-array v0, v3, [I // type@0037
+003fae: 1251                                   |000b: const/4 v1, #int 5 // #5
+003fb0: 1212                                   |000c: const/4 v2, #int 1 // #1
+003fb2: 4b02 0001                              |000d: aput v2, v0, v1
+003fb6: 1261                                   |000f: const/4 v1, #int 6 // #6
+003fb8: 4b07 0001                              |0010: aput v7, v0, v1
+003fbc: 1271                                   |0012: const/4 v1, #int 7 // #7
+003fbe: 1242                                   |0013: const/4 v2, #int 4 // #4
+003fc0: 4b02 0001                              |0014: aput v2, v0, v1
+003fc4: 1301 0800                              |0016: const/16 v1, #int 8 // #8
+003fc8: 4b05 0001                              |0018: aput v5, v0, v1
+003fcc: 1301 0900                              |001a: const/16 v1, #int 9 // #9
+003fd0: 4b03 0001                              |001c: aput v3, v0, v1
+003fd4: 1301 4000                              |001e: const/16 v1, #int 64 // #40
+003fd8: 4b01 0004                              |0020: aput v1, v0, v4
+003fdc: 1301 0b00                              |0022: const/16 v1, #int 11 // #b
+003fe0: 1302 8000                              |0024: const/16 v2, #int 128 // #80
+003fe4: 4b02 0001                              |0026: aput v2, v0, v1
+003fe8: 1301 0d00                              |0028: const/16 v1, #int 13 // #d
+003fec: 1302 0001                              |002a: const/16 v2, #int 256 // #100
+003ff0: 4b02 0001                              |002c: aput v2, v0, v1
+003ff4: 1301 0e00                              |002e: const/16 v1, #int 14 // #e
+003ff8: 1302 0002                              |0030: const/16 v2, #int 512 // #200
+003ffc: 4b02 0001                              |0032: aput v2, v0, v1
+004000: 1301 0f00                              |0034: const/16 v1, #int 15 // #f
+004004: 1302 0004                              |0036: const/16 v2, #int 1024 // #400
+004008: 4b02 0001                              |0038: aput v2, v0, v1
+00400c: 1301 0010                              |003a: const/16 v1, #int 4096 // #1000
+004010: 4b01 0005                              |003c: aput v1, v0, v5
+004014: 1301 1100                              |003e: const/16 v1, #int 17 // #11
+004018: 1302 0020                              |0040: const/16 v2, #int 8192 // #2000
+00401c: 4b02 0001                              |0042: aput v2, v0, v1
+004020: 1301 1200                              |0044: const/16 v1, #int 18 // #12
+004024: 1302 0040                              |0046: const/16 v2, #int 16384 // #4000
+004028: 4b02 0001                              |0048: aput v2, v0, v1
+00402c: 1301 1300                              |004a: const/16 v1, #int 19 // #13
+004030: 1402 0080 0000                         |004c: const v2, #float 4.59177e-41 // #00008000
+004036: 4b02 0001                              |004f: aput v2, v0, v1
+00403a: 1501 0100                              |0051: const/high16 v1, #int 65536 // #1
+00403e: 4b01 0006                              |0053: aput v1, v0, v6
+004042: 1301 1600                              |0055: const/16 v1, #int 22 // #16
+004046: 1502 0200                              |0057: const/high16 v2, #int 131072 // #2
+00404a: 4b02 0001                              |0059: aput v2, v0, v1
+00404e: 1301 1700                              |005b: const/16 v1, #int 23 // #17
+004052: 1502 0400                              |005d: const/high16 v2, #int 262144 // #4
+004056: 4b02 0001                              |005f: aput v2, v0, v1
+00405a: 1301 1800                              |0061: const/16 v1, #int 24 // #18
+00405e: 1502 1000                              |0063: const/high16 v2, #int 1048576 // #10
+004062: 4b02 0001                              |0065: aput v2, v0, v1
+004066: 1301 1900                              |0067: const/16 v1, #int 25 // #19
+00406a: 1502 2000                              |0069: const/high16 v2, #int 2097152 // #20
+00406e: 4b02 0001                              |006b: aput v2, v0, v1
+004072: 1301 1a00                              |006d: const/16 v1, #int 26 // #1a
+004076: 1502 4000                              |006f: const/high16 v2, #int 4194304 // #40
+00407a: 4b02 0001                              |0071: aput v2, v0, v1
+00407e: 1301 1b00                              |0073: const/16 v1, #int 27 // #1b
+004082: 1502 8000                              |0075: const/high16 v2, #int 8388608 // #80
+004086: 4b02 0001                              |0077: aput v2, v0, v1
+00408a: 1301 1d00                              |0079: const/16 v1, #int 29 // #1d
+00408e: 1502 0001                              |007b: const/high16 v2, #int 16777216 // #100
+004092: 4b02 0001                              |007d: aput v2, v0, v1
+004096: 1301 1e00                              |007f: const/16 v1, #int 30 // #1e
+00409a: 1502 0002                              |0081: const/high16 v2, #int 33554432 // #200
+00409e: 4b02 0001                              |0083: aput v2, v0, v1
+0040a2: 1301 1f00                              |0085: const/16 v1, #int 31 // #1f
+0040a6: 1502 0004                              |0087: const/high16 v2, #int 67108864 // #400
+0040aa: 4b02 0001                              |0089: aput v2, v0, v1
+0040ae: 6900 3000                              |008b: sput-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+0040b2: 2330 3700                              |008d: new-array v0, v3, [I // type@0037
+0040b6: 1301 0900                              |008f: const/16 v1, #int 9 // #9
+0040ba: 1212                                   |0091: const/4 v2, #int 1 // #1
+0040bc: 4b02 0001                              |0092: aput v2, v0, v1
+0040c0: 4b07 0004                              |0094: aput v7, v0, v4
+0040c4: 1301 0b00                              |0096: const/16 v1, #int 11 // #b
+0040c8: 1242                                   |0098: const/4 v2, #int 4 // #4
+0040ca: 4b02 0001                              |0099: aput v2, v0, v1
+0040ce: 1301 0d00                              |009b: const/16 v1, #int 13 // #d
+0040d2: 4b05 0001                              |009d: aput v5, v0, v1
+0040d6: 1301 0e00                              |009f: const/16 v1, #int 14 // #e
+0040da: 4b03 0001                              |00a1: aput v3, v0, v1
+0040de: 1301 0f00                              |00a3: const/16 v1, #int 15 // #f
+0040e2: 1302 4000                              |00a5: const/16 v2, #int 64 // #40
+0040e6: 4b02 0001                              |00a7: aput v2, v0, v1
+0040ea: 1301 1100                              |00a9: const/16 v1, #int 17 // #11
+0040ee: 1302 0001                              |00ab: const/16 v2, #int 256 // #100
+0040f2: 4b02 0001                              |00ad: aput v2, v0, v1
+0040f6: 1301 1200                              |00af: const/16 v1, #int 18 // #12
+0040fa: 1302 0002                              |00b1: const/16 v2, #int 512 // #200
+0040fe: 4b02 0001                              |00b3: aput v2, v0, v1
+004102: 1301 1300                              |00b5: const/16 v1, #int 19 // #13
+004106: 1302 0004                              |00b7: const/16 v2, #int 1024 // #400
+00410a: 4b02 0001                              |00b9: aput v2, v0, v1
+00410e: 1301 0010                              |00bb: const/16 v1, #int 4096 // #1000
+004112: 4b01 0006                              |00bd: aput v1, v0, v6
+004116: 1301 1600                              |00bf: const/16 v1, #int 22 // #16
+00411a: 1302 0020                              |00c1: const/16 v2, #int 8192 // #2000
+00411e: 4b02 0001                              |00c3: aput v2, v0, v1
+004122: 1301 1700                              |00c5: const/16 v1, #int 23 // #17
+004126: 1302 0040                              |00c7: const/16 v2, #int 16384 // #4000
+00412a: 4b02 0001                              |00c9: aput v2, v0, v1
+00412e: 1301 1900                              |00cb: const/16 v1, #int 25 // #19
+004132: 1502 0100                              |00cd: const/high16 v2, #int 65536 // #1
+004136: 4b02 0001                              |00cf: aput v2, v0, v1
+00413a: 1301 1a00                              |00d1: const/16 v1, #int 26 // #1a
+00413e: 1502 0200                              |00d3: const/high16 v2, #int 131072 // #2
+004142: 4b02 0001                              |00d5: aput v2, v0, v1
+004146: 1301 1b00                              |00d7: const/16 v1, #int 27 // #1b
+00414a: 1502 0400                              |00d9: const/high16 v2, #int 262144 // #4
+00414e: 4b02 0001                              |00db: aput v2, v0, v1
+004152: 1301 1d00                              |00dd: const/16 v1, #int 29 // #1d
+004156: 1502 1000                              |00df: const/high16 v2, #int 1048576 // #10
+00415a: 4b02 0001                              |00e1: aput v2, v0, v1
+00415e: 1301 1e00                              |00e3: const/16 v1, #int 30 // #1e
+004162: 1502 2000                              |00e5: const/high16 v2, #int 2097152 // #20
+004166: 4b02 0001                              |00e7: aput v2, v0, v1
+00416a: 1301 1f00                              |00e9: const/16 v1, #int 31 // #1f
+00416e: 1502 4000                              |00eb: const/high16 v2, #int 4194304 // #40
+004172: 4b02 0001                              |00ed: aput v2, v0, v1
+004176: 6900 3100                              |00ef: sput-object v0, Lcom/google/android/checkers/a;.E:[I // field@0031
+00417a: 2330 3700                              |00f1: new-array v0, v3, [I // type@0037
+00417e: 1241                                   |00f3: const/4 v1, #int 4 // #4
+004180: 1212                                   |00f4: const/4 v2, #int 1 // #1
+004182: 4b02 0001                              |00f5: aput v2, v0, v1
+004186: 1251                                   |00f7: const/4 v1, #int 5 // #5
+004188: 4b07 0001                              |00f8: aput v7, v0, v1
+00418c: 1261                                   |00fa: const/4 v1, #int 6 // #6
+00418e: 1242                                   |00fb: const/4 v2, #int 4 // #4
+004190: 4b02 0001                              |00fc: aput v2, v0, v1
+004194: 1271                                   |00fe: const/4 v1, #int 7 // #7
+004196: 1302 0800                              |00ff: const/16 v2, #int 8 // #8
+00419a: 4b02 0001                              |0101: aput v2, v0, v1
+00419e: 1301 0800                              |0103: const/16 v1, #int 8 // #8
+0041a2: 4b03 0001                              |0105: aput v3, v0, v1
+0041a6: 1301 0900                              |0107: const/16 v1, #int 9 // #9
+0041aa: 1302 4000                              |0109: const/16 v2, #int 64 // #40
+0041ae: 4b02 0001                              |010b: aput v2, v0, v1
+0041b2: 1301 8000                              |010d: const/16 v1, #int 128 // #80
+0041b6: 4b01 0004                              |010f: aput v1, v0, v4
+0041ba: 1301 0c00                              |0111: const/16 v1, #int 12 // #c
+0041be: 1302 0001                              |0113: const/16 v2, #int 256 // #100
+0041c2: 4b02 0001                              |0115: aput v2, v0, v1
+0041c6: 1301 0d00                              |0117: const/16 v1, #int 13 // #d
+0041ca: 1302 0002                              |0119: const/16 v2, #int 512 // #200
+0041ce: 4b02 0001                              |011b: aput v2, v0, v1
+0041d2: 1301 0e00                              |011d: const/16 v1, #int 14 // #e
+0041d6: 1302 0004                              |011f: const/16 v2, #int 1024 // #400
+0041da: 4b02 0001                              |0121: aput v2, v0, v1
+0041de: 1301 0f00                              |0123: const/16 v1, #int 15 // #f
+0041e2: 1302 0008                              |0125: const/16 v2, #int 2048 // #800
+0041e6: 4b02 0001                              |0127: aput v2, v0, v1
+0041ea: 1301 0020                              |0129: const/16 v1, #int 8192 // #2000
+0041ee: 4b01 0005                              |012b: aput v1, v0, v5
+0041f2: 1301 1100                              |012d: const/16 v1, #int 17 // #11
+0041f6: 1302 0040                              |012f: const/16 v2, #int 16384 // #4000
+0041fa: 4b02 0001                              |0131: aput v2, v0, v1
+0041fe: 1301 1200                              |0133: const/16 v1, #int 18 // #12
+004202: 1402 0080 0000                         |0135: const v2, #float 4.59177e-41 // #00008000
+004208: 4b02 0001                              |0138: aput v2, v0, v1
+00420c: 1301 1400                              |013a: const/16 v1, #int 20 // #14
+004210: 1502 0100                              |013c: const/high16 v2, #int 65536 // #1
+004214: 4b02 0001                              |013e: aput v2, v0, v1
+004218: 1501 0200                              |0140: const/high16 v1, #int 131072 // #2
+00421c: 4b01 0006                              |0142: aput v1, v0, v6
+004220: 1301 1600                              |0144: const/16 v1, #int 22 // #16
+004224: 1502 0400                              |0146: const/high16 v2, #int 262144 // #4
+004228: 4b02 0001                              |0148: aput v2, v0, v1
+00422c: 1301 1700                              |014a: const/16 v1, #int 23 // #17
+004230: 1502 0800                              |014c: const/high16 v2, #int 524288 // #8
+004234: 4b02 0001                              |014e: aput v2, v0, v1
+004238: 1301 1800                              |0150: const/16 v1, #int 24 // #18
+00423c: 1502 2000                              |0152: const/high16 v2, #int 2097152 // #20
+004240: 4b02 0001                              |0154: aput v2, v0, v1
+004244: 1301 1900                              |0156: const/16 v1, #int 25 // #19
+004248: 1502 4000                              |0158: const/high16 v2, #int 4194304 // #40
+00424c: 4b02 0001                              |015a: aput v2, v0, v1
+004250: 1301 1a00                              |015c: const/16 v1, #int 26 // #1a
+004254: 1502 8000                              |015e: const/high16 v2, #int 8388608 // #80
+004258: 4b02 0001                              |0160: aput v2, v0, v1
+00425c: 1301 1c00                              |0162: const/16 v1, #int 28 // #1c
+004260: 1502 0001                              |0164: const/high16 v2, #int 16777216 // #100
+004264: 4b02 0001                              |0166: aput v2, v0, v1
+004268: 1301 1d00                              |0168: const/16 v1, #int 29 // #1d
+00426c: 1502 0002                              |016a: const/high16 v2, #int 33554432 // #200
+004270: 4b02 0001                              |016c: aput v2, v0, v1
+004274: 1301 1e00                              |016e: const/16 v1, #int 30 // #1e
+004278: 1502 0004                              |0170: const/high16 v2, #int 67108864 // #400
+00427c: 4b02 0001                              |0172: aput v2, v0, v1
+004280: 1301 1f00                              |0174: const/16 v1, #int 31 // #1f
+004284: 1502 0008                              |0176: const/high16 v2, #int 134217728 // #800
+004288: 4b02 0001                              |0178: aput v2, v0, v1
+00428c: 6900 3200                              |017a: sput-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+004290: 2330 3700                              |017c: new-array v0, v3, [I // type@0037
+004294: 1301 0800                              |017e: const/16 v1, #int 8 // #8
+004298: 4b07 0001                              |0180: aput v7, v0, v1
+00429c: 1301 0900                              |0182: const/16 v1, #int 9 // #9
+0042a0: 1242                                   |0184: const/4 v2, #int 4 // #4
+0042a2: 4b02 0001                              |0185: aput v2, v0, v1
+0042a6: 1301 0800                              |0187: const/16 v1, #int 8 // #8
+0042aa: 4b01 0004                              |0189: aput v1, v0, v4
+0042ae: 1301 0c00                              |018b: const/16 v1, #int 12 // #c
+0042b2: 4b03 0001                              |018d: aput v3, v0, v1
+0042b6: 1301 0d00                              |018f: const/16 v1, #int 13 // #d
+0042ba: 1302 4000                              |0191: const/16 v2, #int 64 // #40
+0042be: 4b02 0001                              |0193: aput v2, v0, v1
+0042c2: 1301 0e00                              |0195: const/16 v1, #int 14 // #e
+0042c6: 1302 8000                              |0197: const/16 v2, #int 128 // #80
+0042ca: 4b02 0001                              |0199: aput v2, v0, v1
+0042ce: 1301 0002                              |019b: const/16 v1, #int 512 // #200
+0042d2: 4b01 0005                              |019d: aput v1, v0, v5
+0042d6: 1301 1100                              |019f: const/16 v1, #int 17 // #11
+0042da: 1302 0004                              |01a1: const/16 v2, #int 1024 // #400
+0042de: 4b02 0001                              |01a3: aput v2, v0, v1
+0042e2: 1301 1200                              |01a5: const/16 v1, #int 18 // #12
+0042e6: 1302 0008                              |01a7: const/16 v2, #int 2048 // #800
+0042ea: 4b02 0001                              |01a9: aput v2, v0, v1
+0042ee: 1301 1400                              |01ab: const/16 v1, #int 20 // #14
+0042f2: 1302 0020                              |01ad: const/16 v2, #int 8192 // #2000
+0042f6: 4b02 0001                              |01af: aput v2, v0, v1
+0042fa: 1301 0040                              |01b1: const/16 v1, #int 16384 // #4000
+0042fe: 4b01 0006                              |01b3: aput v1, v0, v6
+004302: 1301 1600                              |01b5: const/16 v1, #int 22 // #16
+004306: 1402 0080 0000                         |01b7: const v2, #float 4.59177e-41 // #00008000
+00430c: 4b02 0001                              |01ba: aput v2, v0, v1
+004310: 1301 1800                              |01bc: const/16 v1, #int 24 // #18
+004314: 1502 0200                              |01be: const/high16 v2, #int 131072 // #2
+004318: 4b02 0001                              |01c0: aput v2, v0, v1
+00431c: 1301 1900                              |01c2: const/16 v1, #int 25 // #19
+004320: 1502 0400                              |01c4: const/high16 v2, #int 262144 // #4
+004324: 4b02 0001                              |01c6: aput v2, v0, v1
+004328: 1301 1a00                              |01c8: const/16 v1, #int 26 // #1a
+00432c: 1502 0800                              |01ca: const/high16 v2, #int 524288 // #8
+004330: 4b02 0001                              |01cc: aput v2, v0, v1
+004334: 1301 1c00                              |01ce: const/16 v1, #int 28 // #1c
+004338: 1502 2000                              |01d0: const/high16 v2, #int 2097152 // #20
+00433c: 4b02 0001                              |01d2: aput v2, v0, v1
+004340: 1301 1d00                              |01d4: const/16 v1, #int 29 // #1d
+004344: 1502 4000                              |01d6: const/high16 v2, #int 4194304 // #40
+004348: 4b02 0001                              |01d8: aput v2, v0, v1
+00434c: 1301 1e00                              |01da: const/16 v1, #int 30 // #1e
+004350: 1502 8000                              |01dc: const/high16 v2, #int 8388608 // #80
+004354: 4b02 0001                              |01de: aput v2, v0, v1
+004358: 6900 3300                              |01e0: sput-object v0, Lcom/google/android/checkers/a;.G:[I // field@0033
+00435c: 2330 3700                              |01e2: new-array v0, v3, [I // type@0037
+004360: 1201                                   |01e4: const/4 v1, #int 0 // #0
+004362: 4b05 0001                              |01e5: aput v5, v0, v1
+004366: 1211                                   |01e7: const/4 v1, #int 1 // #1
+004368: 4b03 0001                              |01e8: aput v3, v0, v1
+00436c: 1301 4000                              |01ea: const/16 v1, #int 64 // #40
+004370: 4b01 0007                              |01ec: aput v1, v0, v7
+004374: 1231                                   |01ee: const/4 v1, #int 3 // #3
+004376: 1302 8000                              |01ef: const/16 v2, #int 128 // #80
+00437a: 4b02 0001                              |01f1: aput v2, v0, v1
+00437e: 1251                                   |01f3: const/4 v1, #int 5 // #5
+004380: 1302 0001                              |01f4: const/16 v2, #int 256 // #100
+004384: 4b02 0001                              |01f6: aput v2, v0, v1
+004388: 1261                                   |01f8: const/4 v1, #int 6 // #6
+00438a: 1302 0002                              |01f9: const/16 v2, #int 512 // #200
+00438e: 4b02 0001                              |01fb: aput v2, v0, v1
+004392: 1271                                   |01fd: const/4 v1, #int 7 // #7
+004394: 1302 0004                              |01fe: const/16 v2, #int 1024 // #400
+004398: 4b02 0001                              |0200: aput v2, v0, v1
+00439c: 1301 0800                              |0202: const/16 v1, #int 8 // #8
+0043a0: 1302 0010                              |0204: const/16 v2, #int 4096 // #1000
+0043a4: 4b02 0001                              |0206: aput v2, v0, v1
+0043a8: 1301 0900                              |0208: const/16 v1, #int 9 // #9
+0043ac: 1302 0020                              |020a: const/16 v2, #int 8192 // #2000
+0043b0: 4b02 0001                              |020c: aput v2, v0, v1
+0043b4: 1301 0040                              |020e: const/16 v1, #int 16384 // #4000
+0043b8: 4b01 0004                              |0210: aput v1, v0, v4
+0043bc: 1301 0b00                              |0212: const/16 v1, #int 11 // #b
+0043c0: 1402 0080 0000                         |0214: const v2, #float 4.59177e-41 // #00008000
+0043c6: 4b02 0001                              |0217: aput v2, v0, v1
+0043ca: 1301 0d00                              |0219: const/16 v1, #int 13 // #d
+0043ce: 1502 0100                              |021b: const/high16 v2, #int 65536 // #1
+0043d2: 4b02 0001                              |021d: aput v2, v0, v1
+0043d6: 1301 0e00                              |021f: const/16 v1, #int 14 // #e
+0043da: 1502 0200                              |0221: const/high16 v2, #int 131072 // #2
+0043de: 4b02 0001                              |0223: aput v2, v0, v1
+0043e2: 1301 0f00                              |0225: const/16 v1, #int 15 // #f
+0043e6: 1502 0400                              |0227: const/high16 v2, #int 262144 // #4
+0043ea: 4b02 0001                              |0229: aput v2, v0, v1
+0043ee: 1501 1000                              |022b: const/high16 v1, #int 1048576 // #10
+0043f2: 4b01 0005                              |022d: aput v1, v0, v5
+0043f6: 1301 1100                              |022f: const/16 v1, #int 17 // #11
+0043fa: 1502 2000                              |0231: const/high16 v2, #int 2097152 // #20
+0043fe: 4b02 0001                              |0233: aput v2, v0, v1
+004402: 1301 1200                              |0235: const/16 v1, #int 18 // #12
+004406: 1502 4000                              |0237: const/high16 v2, #int 4194304 // #40
+00440a: 4b02 0001                              |0239: aput v2, v0, v1
+00440e: 1301 1300                              |023b: const/16 v1, #int 19 // #13
+004412: 1502 8000                              |023d: const/high16 v2, #int 8388608 // #80
+004416: 4b02 0001                              |023f: aput v2, v0, v1
+00441a: 1501 0001                              |0241: const/high16 v1, #int 16777216 // #100
+00441e: 4b01 0006                              |0243: aput v1, v0, v6
+004422: 1301 1600                              |0245: const/16 v1, #int 22 // #16
+004426: 1502 0002                              |0247: const/high16 v2, #int 33554432 // #200
+00442a: 4b02 0001                              |0249: aput v2, v0, v1
+00442e: 1301 1700                              |024b: const/16 v1, #int 23 // #17
+004432: 1502 0004                              |024d: const/high16 v2, #int 67108864 // #400
+004436: 4b02 0001                              |024f: aput v2, v0, v1
+00443a: 1301 1800                              |0251: const/16 v1, #int 24 // #18
+00443e: 1502 0010                              |0253: const/high16 v2, #int 268435456 // #1000
+004442: 4b02 0001                              |0255: aput v2, v0, v1
+004446: 1301 1900                              |0257: const/16 v1, #int 25 // #19
+00444a: 1502 0020                              |0259: const/high16 v2, #int 536870912 // #2000
+00444e: 4b02 0001                              |025b: aput v2, v0, v1
+004452: 1301 1a00                              |025d: const/16 v1, #int 26 // #1a
+004456: 1502 0040                              |025f: const/high16 v2, #int 1073741824 // #4000
+00445a: 4b02 0001                              |0261: aput v2, v0, v1
+00445e: 1301 1b00                              |0263: const/16 v1, #int 27 // #1b
+004462: 1502 0080                              |0265: const/high16 v2, #int -2147483648 // #8000
+004466: 4b02 0001                              |0267: aput v2, v0, v1
+00446a: 6900 3400                              |0269: sput-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+00446e: 2330 3700                              |026b: new-array v0, v3, [I // type@0037
+004472: 1211                                   |026d: const/4 v1, #int 1 // #1
+004474: 1302 0001                              |026e: const/16 v2, #int 256 // #100
+004478: 4b02 0001                              |0270: aput v2, v0, v1
+00447c: 1301 0002                              |0272: const/16 v1, #int 512 // #200
+004480: 4b01 0007                              |0274: aput v1, v0, v7
+004484: 1231                                   |0276: const/4 v1, #int 3 // #3
+004486: 1302 0004                              |0277: const/16 v2, #int 1024 // #400
+00448a: 4b02 0001                              |0279: aput v2, v0, v1
+00448e: 1251                                   |027b: const/4 v1, #int 5 // #5
+004490: 1302 0010                              |027c: const/16 v2, #int 4096 // #1000
+004494: 4b02 0001                              |027e: aput v2, v0, v1
+004498: 1261                                   |0280: const/4 v1, #int 6 // #6
+00449a: 1302 0020                              |0281: const/16 v2, #int 8192 // #2000
+00449e: 4b02 0001                              |0283: aput v2, v0, v1
+0044a2: 1271                                   |0285: const/4 v1, #int 7 // #7
+0044a4: 1302 0040                              |0286: const/16 v2, #int 16384 // #4000
+0044a8: 4b02 0001                              |0288: aput v2, v0, v1
+0044ac: 1301 0900                              |028a: const/16 v1, #int 9 // #9
+0044b0: 1502 0100                              |028c: const/high16 v2, #int 65536 // #1
+0044b4: 4b02 0001                              |028e: aput v2, v0, v1
+0044b8: 1501 0200                              |0290: const/high16 v1, #int 131072 // #2
+0044bc: 4b01 0004                              |0292: aput v1, v0, v4
+0044c0: 1301 0b00                              |0294: const/16 v1, #int 11 // #b
+0044c4: 1502 0400                              |0296: const/high16 v2, #int 262144 // #4
+0044c8: 4b02 0001                              |0298: aput v2, v0, v1
+0044cc: 1301 0d00                              |029a: const/16 v1, #int 13 // #d
+0044d0: 1502 1000                              |029c: const/high16 v2, #int 1048576 // #10
+0044d4: 4b02 0001                              |029e: aput v2, v0, v1
+0044d8: 1301 0e00                              |02a0: const/16 v1, #int 14 // #e
+0044dc: 1502 2000                              |02a2: const/high16 v2, #int 2097152 // #20
+0044e0: 4b02 0001                              |02a4: aput v2, v0, v1
+0044e4: 1301 0f00                              |02a6: const/16 v1, #int 15 // #f
+0044e8: 1502 4000                              |02a8: const/high16 v2, #int 4194304 // #40
+0044ec: 4b02 0001                              |02aa: aput v2, v0, v1
+0044f0: 1301 1100                              |02ac: const/16 v1, #int 17 // #11
+0044f4: 1502 0001                              |02ae: const/high16 v2, #int 16777216 // #100
+0044f8: 4b02 0001                              |02b0: aput v2, v0, v1
+0044fc: 1301 1200                              |02b2: const/16 v1, #int 18 // #12
+004500: 1502 0002                              |02b4: const/high16 v2, #int 33554432 // #200
+004504: 4b02 0001                              |02b6: aput v2, v0, v1
+004508: 1301 1300                              |02b8: const/16 v1, #int 19 // #13
+00450c: 1502 0004                              |02ba: const/high16 v2, #int 67108864 // #400
+004510: 4b02 0001                              |02bc: aput v2, v0, v1
+004514: 1501 0010                              |02be: const/high16 v1, #int 268435456 // #1000
+004518: 4b01 0006                              |02c0: aput v1, v0, v6
+00451c: 1301 1600                              |02c2: const/16 v1, #int 22 // #16
+004520: 1502 0020                              |02c4: const/high16 v2, #int 536870912 // #2000
+004524: 4b02 0001                              |02c6: aput v2, v0, v1
+004528: 1301 1700                              |02c8: const/16 v1, #int 23 // #17
+00452c: 1502 0040                              |02ca: const/high16 v2, #int 1073741824 // #4000
+004530: 4b02 0001                              |02cc: aput v2, v0, v1
+004534: 6900 3500                              |02ce: sput-object v0, Lcom/google/android/checkers/a;.I:[I // field@0035
+004538: 2330 3700                              |02d0: new-array v0, v3, [I // type@0037
+00453c: 1201                                   |02d2: const/4 v1, #int 0 // #0
+00453e: 4b03 0001                              |02d3: aput v3, v0, v1
+004542: 1211                                   |02d5: const/4 v1, #int 1 // #1
+004544: 1302 4000                              |02d6: const/16 v2, #int 64 // #40
+004548: 4b02 0001                              |02d8: aput v2, v0, v1
+00454c: 1301 8000                              |02da: const/16 v1, #int 128 // #80
+004550: 4b01 0007                              |02dc: aput v1, v0, v7
+004554: 1241                                   |02de: const/4 v1, #int 4 // #4
+004556: 1302 0001                              |02df: const/16 v2, #int 256 // #100
+00455a: 4b02 0001                              |02e1: aput v2, v0, v1
+00455e: 1251                                   |02e3: const/4 v1, #int 5 // #5
+004560: 1302 0002                              |02e4: const/16 v2, #int 512 // #200
+004564: 4b02 0001                              |02e6: aput v2, v0, v1
+004568: 1261                                   |02e8: const/4 v1, #int 6 // #6
+00456a: 1302 0004                              |02e9: const/16 v2, #int 1024 // #400
+00456e: 4b02 0001                              |02eb: aput v2, v0, v1
+004572: 1271                                   |02ed: const/4 v1, #int 7 // #7
+004574: 1302 0008                              |02ee: const/16 v2, #int 2048 // #800
+004578: 4b02 0001                              |02f0: aput v2, v0, v1
+00457c: 1301 0800                              |02f2: const/16 v1, #int 8 // #8
+004580: 1302 0020                              |02f4: const/16 v2, #int 8192 // #2000
+004584: 4b02 0001                              |02f6: aput v2, v0, v1
+004588: 1301 0900                              |02f8: const/16 v1, #int 9 // #9
+00458c: 1302 0040                              |02fa: const/16 v2, #int 16384 // #4000
+004590: 4b02 0001                              |02fc: aput v2, v0, v1
+004594: 1401 0080 0000                         |02fe: const v1, #float 4.59177e-41 // #00008000
+00459a: 4b01 0004                              |0301: aput v1, v0, v4
+00459e: 1301 0c00                              |0303: const/16 v1, #int 12 // #c
+0045a2: 1502 0100                              |0305: const/high16 v2, #int 65536 // #1
+0045a6: 4b02 0001                              |0307: aput v2, v0, v1
+0045aa: 1301 0d00                              |0309: const/16 v1, #int 13 // #d
+0045ae: 1502 0200                              |030b: const/high16 v2, #int 131072 // #2
+0045b2: 4b02 0001                              |030d: aput v2, v0, v1
+0045b6: 1301 0e00                              |030f: const/16 v1, #int 14 // #e
+0045ba: 1502 0400                              |0311: const/high16 v2, #int 262144 // #4
+0045be: 4b02 0001                              |0313: aput v2, v0, v1
+0045c2: 1301 0f00                              |0315: const/16 v1, #int 15 // #f
+0045c6: 1502 0800                              |0317: const/high16 v2, #int 524288 // #8
+0045ca: 4b02 0001                              |0319: aput v2, v0, v1
+0045ce: 1501 2000                              |031b: const/high16 v1, #int 2097152 // #20
+0045d2: 4b01 0005                              |031d: aput v1, v0, v5
+0045d6: 1301 1100                              |031f: const/16 v1, #int 17 // #11
+0045da: 1502 4000                              |0321: const/high16 v2, #int 4194304 // #40
+0045de: 4b02 0001                              |0323: aput v2, v0, v1
+0045e2: 1301 1200                              |0325: const/16 v1, #int 18 // #12
+0045e6: 1502 8000                              |0327: const/high16 v2, #int 8388608 // #80
+0045ea: 4b02 0001                              |0329: aput v2, v0, v1
+0045ee: 1301 1400                              |032b: const/16 v1, #int 20 // #14
+0045f2: 1502 0001                              |032d: const/high16 v2, #int 16777216 // #100
+0045f6: 4b02 0001                              |032f: aput v2, v0, v1
+0045fa: 1501 0002                              |0331: const/high16 v1, #int 33554432 // #200
+0045fe: 4b01 0006                              |0333: aput v1, v0, v6
+004602: 1301 1600                              |0335: const/16 v1, #int 22 // #16
+004606: 1502 0004                              |0337: const/high16 v2, #int 67108864 // #400
+00460a: 4b02 0001                              |0339: aput v2, v0, v1
+00460e: 1301 1700                              |033b: const/16 v1, #int 23 // #17
+004612: 1502 0008                              |033d: const/high16 v2, #int 134217728 // #800
+004616: 4b02 0001                              |033f: aput v2, v0, v1
+00461a: 1301 1800                              |0341: const/16 v1, #int 24 // #18
+00461e: 1502 0020                              |0343: const/high16 v2, #int 536870912 // #2000
+004622: 4b02 0001                              |0345: aput v2, v0, v1
+004626: 1301 1900                              |0347: const/16 v1, #int 25 // #19
+00462a: 1502 0040                              |0349: const/high16 v2, #int 1073741824 // #4000
+00462e: 4b02 0001                              |034b: aput v2, v0, v1
+004632: 1301 1a00                              |034d: const/16 v1, #int 26 // #1a
+004636: 1502 0080                              |034f: const/high16 v2, #int -2147483648 // #8000
+00463a: 4b02 0001                              |0351: aput v2, v0, v1
+00463e: 6900 3600                              |0353: sput-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+004642: 2330 3700                              |0355: new-array v0, v3, [I // type@0037
+004646: 1201                                   |0357: const/4 v1, #int 0 // #0
+004648: 1302 0002                              |0358: const/16 v2, #int 512 // #200
+00464c: 4b02 0001                              |035a: aput v2, v0, v1
+004650: 1211                                   |035c: const/4 v1, #int 1 // #1
+004652: 1302 0004                              |035d: const/16 v2, #int 1024 // #400
+004656: 4b02 0001                              |035f: aput v2, v0, v1
+00465a: 1301 0008                              |0361: const/16 v1, #int 2048 // #800
+00465e: 4b01 0007                              |0363: aput v1, v0, v7
+004662: 1241                                   |0365: const/4 v1, #int 4 // #4
+004664: 1302 0020                              |0366: const/16 v2, #int 8192 // #2000
+004668: 4b02 0001                              |0368: aput v2, v0, v1
+00466c: 1251                                   |036a: const/4 v1, #int 5 // #5
+00466e: 1302 0040                              |036b: const/16 v2, #int 16384 // #4000
+004672: 4b02 0001                              |036d: aput v2, v0, v1
+004676: 1261                                   |036f: const/4 v1, #int 6 // #6
+004678: 1402 0080 0000                         |0370: const v2, #float 4.59177e-41 // #00008000
+00467e: 4b02 0001                              |0373: aput v2, v0, v1
+004682: 1301 0800                              |0375: const/16 v1, #int 8 // #8
+004686: 1502 0200                              |0377: const/high16 v2, #int 131072 // #2
+00468a: 4b02 0001                              |0379: aput v2, v0, v1
+00468e: 1301 0900                              |037b: const/16 v1, #int 9 // #9
+004692: 1502 0400                              |037d: const/high16 v2, #int 262144 // #4
+004696: 4b02 0001                              |037f: aput v2, v0, v1
+00469a: 1501 0800                              |0381: const/high16 v1, #int 524288 // #8
+00469e: 4b01 0004                              |0383: aput v1, v0, v4
+0046a2: 1301 0c00                              |0385: const/16 v1, #int 12 // #c
+0046a6: 1502 2000                              |0387: const/high16 v2, #int 2097152 // #20
+0046aa: 4b02 0001                              |0389: aput v2, v0, v1
+0046ae: 1301 0d00                              |038b: const/16 v1, #int 13 // #d
+0046b2: 1502 4000                              |038d: const/high16 v2, #int 4194304 // #40
+0046b6: 4b02 0001                              |038f: aput v2, v0, v1
+0046ba: 1301 0e00                              |0391: const/16 v1, #int 14 // #e
+0046be: 1502 8000                              |0393: const/high16 v2, #int 8388608 // #80
+0046c2: 4b02 0001                              |0395: aput v2, v0, v1
+0046c6: 1501 0002                              |0397: const/high16 v1, #int 33554432 // #200
+0046ca: 4b01 0005                              |0399: aput v1, v0, v5
+0046ce: 1301 1100                              |039b: const/16 v1, #int 17 // #11
+0046d2: 1502 0004                              |039d: const/high16 v2, #int 67108864 // #400
+0046d6: 4b02 0001                              |039f: aput v2, v0, v1
+0046da: 1301 1200                              |03a1: const/16 v1, #int 18 // #12
+0046de: 1502 0008                              |03a3: const/high16 v2, #int 134217728 // #800
+0046e2: 4b02 0001                              |03a5: aput v2, v0, v1
+0046e6: 1301 1400                              |03a7: const/16 v1, #int 20 // #14
+0046ea: 1502 0020                              |03a9: const/high16 v2, #int 536870912 // #2000
+0046ee: 4b02 0001                              |03ab: aput v2, v0, v1
+0046f2: 1501 0040                              |03ad: const/high16 v1, #int 1073741824 // #4000
+0046f6: 4b01 0006                              |03af: aput v1, v0, v6
+0046fa: 1301 1600                              |03b1: const/16 v1, #int 22 // #16
+0046fe: 1502 0080                              |03b3: const/high16 v2, #int -2147483648 // #8000
+004702: 4b02 0001                              |03b5: aput v2, v0, v1
+004706: 6900 3700                              |03b7: sput-object v0, Lcom/google/android/checkers/a;.K:[I // field@0037
+00470a: 2330 3700                              |03b9: new-array v0, v3, [I // type@0037
+00470e: 1211                                   |03bb: const/4 v1, #int 1 // #1
+004710: 4b01 0007                              |03bc: aput v1, v0, v7
+004714: 1231                                   |03be: const/4 v1, #int 3 // #3
+004716: 1232                                   |03bf: const/4 v2, #int 3 // #3
+004718: 4b02 0001                              |03c0: aput v2, v0, v1
+00471c: 1241                                   |03c2: const/4 v1, #int 4 // #4
+00471e: 1262                                   |03c3: const/4 v2, #int 6 // #6
+004720: 4b02 0001                              |03c4: aput v2, v0, v1
+004724: 1251                                   |03c6: const/4 v1, #int 5 // #5
+004726: 4b04 0001                              |03c7: aput v4, v0, v1
+00472a: 1261                                   |03c9: const/4 v1, #int 6 // #6
+00472c: 1302 0f00                              |03ca: const/16 v2, #int 15 // #f
+004730: 4b02 0001                              |03cc: aput v2, v0, v1
+004734: 1271                                   |03ce: const/4 v1, #int 7 // #7
+004736: 4b06 0001                              |03cf: aput v6, v0, v1
+00473a: 1301 0800                              |03d1: const/16 v1, #int 8 // #8
+00473e: 1302 1c00                              |03d3: const/16 v2, #int 28 // #1c
+004742: 4b02 0001                              |03d5: aput v2, v0, v1
+004746: 1301 0900                              |03d7: const/16 v1, #int 9 // #9
+00474a: 1302 2400                              |03d9: const/16 v2, #int 36 // #24
+00474e: 4b02 0001                              |03db: aput v2, v0, v1
+004752: 1301 2d00                              |03dd: const/16 v1, #int 45 // #2d
+004756: 4b01 0004                              |03df: aput v1, v0, v4
+00475a: 1301 0b00                              |03e1: const/16 v1, #int 11 // #b
+00475e: 1302 3700                              |03e3: const/16 v2, #int 55 // #37
+004762: 4b02 0001                              |03e5: aput v2, v0, v1
+004766: 1301 0c00                              |03e7: const/16 v1, #int 12 // #c
+00476a: 1302 4200                              |03e9: const/16 v2, #int 66 // #42
+00476e: 4b02 0001                              |03eb: aput v2, v0, v1
+004772: 1301 0d00                              |03ed: const/16 v1, #int 13 // #d
+004776: 1302 4e00                              |03ef: const/16 v2, #int 78 // #4e
+00477a: 4b02 0001                              |03f1: aput v2, v0, v1
+00477e: 1301 0e00                              |03f3: const/16 v1, #int 14 // #e
+004782: 1302 5b00                              |03f5: const/16 v2, #int 91 // #5b
+004786: 4b02 0001                              |03f7: aput v2, v0, v1
+00478a: 1301 0f00                              |03f9: const/16 v1, #int 15 // #f
+00478e: 1302 6900                              |03fb: const/16 v2, #int 105 // #69
+004792: 4b02 0001                              |03fd: aput v2, v0, v1
+004796: 1301 7800                              |03ff: const/16 v1, #int 120 // #78
+00479a: 4b01 0005                              |0401: aput v1, v0, v5
+00479e: 1301 1100                              |0403: const/16 v1, #int 17 // #11
+0047a2: 1302 8800                              |0405: const/16 v2, #int 136 // #88
+0047a6: 4b02 0001                              |0407: aput v2, v0, v1
+0047aa: 1301 1200                              |0409: const/16 v1, #int 18 // #12
+0047ae: 1302 9900                              |040b: const/16 v2, #int 153 // #99
+0047b2: 4b02 0001                              |040d: aput v2, v0, v1
+0047b6: 1301 1300                              |040f: const/16 v1, #int 19 // #13
+0047ba: 1302 ab00                              |0411: const/16 v2, #int 171 // #ab
+0047be: 4b02 0001                              |0413: aput v2, v0, v1
+0047c2: 1301 1400                              |0415: const/16 v1, #int 20 // #14
+0047c6: 1302 be00                              |0417: const/16 v2, #int 190 // #be
+0047ca: 4b02 0001                              |0419: aput v2, v0, v1
+0047ce: 1301 d200                              |041b: const/16 v1, #int 210 // #d2
+0047d2: 4b01 0006                              |041d: aput v1, v0, v6
+0047d6: 1301 1600                              |041f: const/16 v1, #int 22 // #16
+0047da: 1302 e700                              |0421: const/16 v2, #int 231 // #e7
+0047de: 4b02 0001                              |0423: aput v2, v0, v1
+0047e2: 1301 1700                              |0425: const/16 v1, #int 23 // #17
+0047e6: 1302 fd00                              |0427: const/16 v2, #int 253 // #fd
+0047ea: 4b02 0001                              |0429: aput v2, v0, v1
+0047ee: 1301 1800                              |042b: const/16 v1, #int 24 // #18
+0047f2: 1302 1401                              |042d: const/16 v2, #int 276 // #114
+0047f6: 4b02 0001                              |042f: aput v2, v0, v1
+0047fa: 1301 1900                              |0431: const/16 v1, #int 25 // #19
+0047fe: 1302 2c01                              |0433: const/16 v2, #int 300 // #12c
+004802: 4b02 0001                              |0435: aput v2, v0, v1
+004806: 1301 1a00                              |0437: const/16 v1, #int 26 // #1a
+00480a: 1302 4501                              |0439: const/16 v2, #int 325 // #145
+00480e: 4b02 0001                              |043b: aput v2, v0, v1
+004812: 1301 1b00                              |043d: const/16 v1, #int 27 // #1b
+004816: 1302 5f01                              |043f: const/16 v2, #int 351 // #15f
+00481a: 4b02 0001                              |0441: aput v2, v0, v1
+00481e: 1301 1c00                              |0443: const/16 v1, #int 28 // #1c
+004822: 1302 7a01                              |0445: const/16 v2, #int 378 // #17a
+004826: 4b02 0001                              |0447: aput v2, v0, v1
+00482a: 1301 1d00                              |0449: const/16 v1, #int 29 // #1d
+00482e: 1302 9601                              |044b: const/16 v2, #int 406 // #196
+004832: 4b02 0001                              |044d: aput v2, v0, v1
+004836: 1301 1e00                              |044f: const/16 v1, #int 30 // #1e
+00483a: 1302 b301                              |0451: const/16 v2, #int 435 // #1b3
+00483e: 4b02 0001                              |0453: aput v2, v0, v1
+004842: 1301 1f00                              |0455: const/16 v1, #int 31 // #1f
+004846: 1302 d101                              |0457: const/16 v2, #int 465 // #1d1
+00484a: 4b02 0001                              |0459: aput v2, v0, v1
+00484e: 6900 3800                              |045b: sput-object v0, Lcom/google/android/checkers/a;.L:[I // field@0038
+004852: 1300 8100                              |045d: const/16 v0, #int 129 // #81
+004856: 2300 3700                              |045f: new-array v0, v0, [I // type@0037
+00485a: 2600 0700 0000                         |0461: fill-array-data v0, 00000468 // +00000007
+004860: 6900 3900                              |0464: sput-object v0, Lcom/google/android/checkers/a;.M:[I // field@0039
+004864: 0e00                                   |0466: return-void
+004866: 0000                                   |0467: nop // spacer
+004868: 0003 0400 8100 0000 6745 68ba ff5c ... |0468: array-data (262 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #1              : (in Lcom/google/android/checkers/a;)
+      name          : '<init>'
+      type          : '(Lcom/google/android/checkers/CheckersView;)V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 114
+      code          -
+      registers     : 7
+      ins           : 2
+      outs          : 1
+      insns size    : 94 16-bit code units
+004a74:                                        |[004a74] com.google.android.checkers.a.<init>:(Lcom/google/android/checkers/CheckersView;)V
+004a84: 1304 4000                              |0000: const/16 v4, #int 64 // #40
+004a88: 1203                                   |0002: const/4 v3, #int 0 // #0
+004a8a: 1302 0010                              |0003: const/16 v2, #int 4096 // #1000
+004a8e: 1200                                   |0005: const/4 v0, #int 0 // #0
+004a90: 7010 ad00 0500                         |0006: invoke-direct {v5}, Ljava/lang/Thread;.<init>:()V // method@00ad
+004a96: 1301 e803                              |0009: const/16 v1, #int 1000 // #3e8
+004a9a: 5951 4100                              |000b: iput v1, v5, Lcom/google/android/checkers/a;.h:I // field@0041
+004a9e: 2201 3300                              |000d: new-instance v1, Ljava/util/Random; // type@0033
+004aa2: 7010 af00 0100                         |000f: invoke-direct {v1}, Ljava/util/Random;.<init>:()V // method@00af
+004aa8: 5b51 4200                              |0012: iput-object v1, v5, Lcom/google/android/checkers/a;.i:Ljava/util/Random; // field@0042
+004aac: 5b56 4300                              |0014: iput-object v6, v5, Lcom/google/android/checkers/a;.j:Lcom/google/android/checkers/CheckersView; // field@0043
+004ab0: 5c50 4400                              |0016: iput-boolean v0, v5, Lcom/google/android/checkers/a;.k:Z // field@0044
+004ab4: 2321 3700                              |0018: new-array v1, v2, [I // type@0037
+004ab8: 5b51 4800                              |001a: iput-object v1, v5, Lcom/google/android/checkers/a;.o:[I // field@0048
+004abc: 2321 3700                              |001c: new-array v1, v2, [I // type@0037
+004ac0: 5b51 3a00                              |001e: iput-object v1, v5, Lcom/google/android/checkers/a;.a:[I // field@003a
+004ac4: 2321 3700                              |0020: new-array v1, v2, [I // type@0037
+004ac8: 5b51 4900                              |0022: iput-object v1, v5, Lcom/google/android/checkers/a;.p:[I // field@0049
+004acc: 2341 3700                              |0024: new-array v1, v4, [I // type@0037
+004ad0: 5b51 3b00                              |0026: iput-object v1, v5, Lcom/google/android/checkers/a;.b:[I // field@003b
+004ad4: 2341 3700                              |0028: new-array v1, v4, [I // type@0037
+004ad8: 5b51 4a00                              |002a: iput-object v1, v5, Lcom/google/android/checkers/a;.q:[I // field@004a
+004adc: 5c50 4c00                              |002c: iput-boolean v0, v5, Lcom/google/android/checkers/a;.s:Z // field@004c
+004ae0: 1501 1000                              |002e: const/high16 v1, #int 1048576 // #10
+004ae4: 2311 3700                              |0030: new-array v1, v1, [I // type@0037
+004ae8: 5b51 5200                              |0032: iput-object v1, v5, Lcom/google/android/checkers/a;.y:[I // field@0052
+004aec: 1501 1000                              |0034: const/high16 v1, #int 1048576 // #10
+004af0: 2311 3900                              |0036: new-array v1, v1, [S // type@0039
+004af4: 5b51 5300                              |0038: iput-object v1, v5, Lcom/google/android/checkers/a;.z:[S // field@0053
+004af8: 1501 1000                              |003a: const/high16 v1, #int 1048576 // #10
+004afc: 2311 3600                              |003c: new-array v1, v1, [B // type@0036
+004b00: 5b51 2d00                              |003e: iput-object v1, v5, Lcom/google/android/checkers/a;.A:[B // field@002d
+004b04: 5451 5200                              |0040: iget-object v1, v5, Lcom/google/android/checkers/a;.y:[I // field@0052
+004b08: 3801 0b00                              |0042: if-eqz v1, 004d // +000b
+004b0c: 5451 5300                              |0044: iget-object v1, v5, Lcom/google/android/checkers/a;.z:[S // field@0053
+004b10: 3801 0700                              |0046: if-eqz v1, 004d // +0007
+004b14: 5451 2d00                              |0048: iget-object v1, v5, Lcom/google/android/checkers/a;.A:[B // field@002d
+004b18: 3801 0300                              |004a: if-eqz v1, 004d // +0003
+004b1c: 1210                                   |004c: const/4 v0, #int 1 // #1
+004b1e: 5c50 2e00                              |004d: iput-boolean v0, v5, Lcom/google/android/checkers/a;.B:Z // field@002e
+004b22: 6e10 7b00 0500                         |004f: invoke-virtual {v5}, Lcom/google/android/checkers/a;.a:()V // method@007b
+004b28: 6e10 8e00 0500                         |0052: invoke-virtual {v5}, Lcom/google/android/checkers/a;.start:()V // method@008e
+004b2e: 0e00                                   |0055: return-void
+004b30: 0d01                                   |0056: move-exception v1
+004b32: 5b53 5200                              |0057: iput-object v3, v5, Lcom/google/android/checkers/a;.y:[I // field@0052
+004b36: 5b53 5300                              |0059: iput-object v3, v5, Lcom/google/android/checkers/a;.z:[S // field@0053
+004b3a: 5b53 2d00                              |005b: iput-object v3, v5, Lcom/google/android/checkers/a;.A:[B // field@002d
+004b3e: 28e3                                   |005d: goto 0040 // -001d
+      catches       : 1
+        0x0030 - 0x0040
+          Ljava/lang/Exception; -> 0x0056
+      positions     : 
+      locals        : 
+
+    #2              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(II)I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+      method_idx    : 115
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 0
+      insns size    : 14 16-bit code units
+004b4c:                                        |[004b4c] com.google.android.checkers.a.a:(II)I
+004b5c: 3d01 0600                              |0000: if-lez v1, 0006 // +0006
+004b60: d010 757e                              |0002: add-int/lit16 v0, v1, #int 32373 // #7e75
+004b64: b120                                   |0004: sub-int/2addr v0, v2
+004b66: 0f00                                   |0005: return v0
+004b68: 3b01 0600                              |0006: if-gez v1, 000c // +0006
+004b6c: d010 8b81                              |0008: add-int/lit16 v0, v1, #int -32373 // #818b
+004b70: b020                                   |000a: add-int/2addr v0, v2
+004b72: 28fa                                   |000b: goto 0005 // -0006
+004b74: 1200                                   |000c: const/4 v0, #int 0 // #0
+004b76: 28f8                                   |000d: goto 0005 // -0008
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #3              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(IIIIIZ)I'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 116
+      code          -
+      registers     : 31
+      ins           : 7
+      outs          : 7
+      insns size    : 1296 16-bit code units
+004b78:                                        |[004b78] com.google.android.checkers.a.a:(IIIIIZ)I
+004b88: 0800 1800                              |0000: move-object/from16 v0, v24
+004b8c: 5203 2f00                              |0002: iget v3, v0, Lcom/google/android/checkers/a;.C:I // field@002f
+004b90: d803 0301                              |0004: add-int/lit8 v3, v3, #int 1 // #01
+004b94: 0800 1800                              |0006: move-object/from16 v0, v24
+004b98: 5903 2f00                              |0008: iput v3, v0, Lcom/google/android/checkers/a;.C:I // field@002f
+004b9c: 0800 1800                              |000a: move-object/from16 v0, v24
+004ba0: 5203 4f00                              |000c: iget v3, v0, Lcom/google/android/checkers/a;.v:I // field@004f
+004ba4: 3803 0800                              |000e: if-eqz v3, 0016 // +0008
+004ba8: 0800 1800                              |0010: move-object/from16 v0, v24
+004bac: 5203 5000                              |0012: iget v3, v0, Lcom/google/android/checkers/a;.w:I // field@0050
+004bb0: 3903 0700                              |0014: if-nez v3, 001b // +0007
+004bb4: 0200 1b00                              |0016: move/from16 v0, v27
+004bb8: d004 0c81                              |0018: add-int/lit16 v4, v0, #int -32500 // #810c
+004bbc: 0f04                                   |001a: return v4
+004bbe: 0800 1800                              |001b: move-object/from16 v0, v24
+004bc2: 5503 4e00                              |001d: iget-boolean v3, v0, Lcom/google/android/checkers/a;.u:Z // field@004e
+004bc6: 3803 0e00                              |001f: if-eqz v3, 002d // +000e
+004bca: 0800 1800                              |0021: move-object/from16 v0, v24
+004bce: 5203 4f00                              |0023: iget v3, v0, Lcom/google/android/checkers/a;.v:I // field@004f
+004bd2: 0800 1800                              |0025: move-object/from16 v0, v24
+004bd6: 5204 5000                              |0027: iget v4, v0, Lcom/google/android/checkers/a;.w:I // field@0050
+004bda: b043                                   |0029: add-int/2addr v3, v4
+004bdc: 2b03 c004 0000                         |002a: packed-switch v3, 000004ea // +000004c0
+004be2: 1303 4000                              |002d: const/16 v3, #int 64 // #40
+004be6: 0200 1c00                              |002f: move/from16 v0, v28
+004bea: 3530 b404                              |0031: if-ge v0, v3, 04e5 // +04b4
+004bee: 1303 6400                              |0033: const/16 v3, #int 100 // #64
+004bf2: 0200 1d00                              |0035: move/from16 v0, v29
+004bf6: 3430 ae04                              |0037: if-lt v0, v3, 04e5 // +04ae
+004bfa: d81d 1d9c                              |0039: add-int/lit8 v29, v29, #int -100 // #9c
+004bfe: d81c 1c01                              |003b: add-int/lit8 v28, v28, #int 1 // #01
+004c02: 0207 1c00                              |003d: move/from16 v7, v28
+004c06: 0200 1b00                              |003f: move/from16 v0, v27
+004c0a: 3570 8103                              |0041: if-ge v0, v7, 03c2 // +0381
+004c0e: 0800 1800                              |0043: move-object/from16 v0, v24
+004c12: 5503 2e00                              |0045: iget-boolean v3, v0, Lcom/google/android/checkers/a;.B:Z // field@002e
+004c16: 3803 3400                              |0047: if-eqz v3, 007b // +0034
+004c1a: 0800 1800                              |0049: move-object/from16 v0, v24
+004c1e: 5203 5100                              |004b: iget v3, v0, Lcom/google/android/checkers/a;.x:I // field@0051
+004c22: 1404 ffff 0f00                         |004d: const v4, #float 1.46937e-39 // #000fffff
+004c28: b534                                   |0050: and-int/2addr v4, v3
+004c2a: 0800 1800                              |0051: move-object/from16 v0, v24
+004c2e: 5405 5200                              |0053: iget-object v5, v0, Lcom/google/android/checkers/a;.y:[I // field@0052
+004c32: 4405 0504                              |0055: aget v5, v5, v4
+004c36: 3335 d702                              |0057: if-ne v5, v3, 032e // +02d7
+004c3a: 0800 1800                              |0059: move-object/from16 v0, v24
+004c3e: 5403 2d00                              |005b: iget-object v3, v0, Lcom/google/android/checkers/a;.A:[B // field@002d
+004c42: 4803 0304                              |005d: aget-byte v3, v3, v4
+004c46: dd03 033f                              |005f: and-int/lit8 v3, v3, #int 63 // #3f
+004c4a: 9105 071b                              |0061: sub-int v5, v7, v27
+004c4e: 3453 cb02                              |0063: if-lt v3, v5, 032e // +02cb
+004c52: 0800 1800                              |0065: move-object/from16 v0, v24
+004c56: 5403 2d00                              |0067: iget-object v3, v0, Lcom/google/android/checkers/a;.A:[B // field@002d
+004c5a: 4803 0304                              |0069: aget-byte v3, v3, v4
+004c5e: d533 c000                              |006b: and-int/lit16 v3, v3, #int 192 // #00c0
+004c62: 0800 1800                              |006d: move-object/from16 v0, v24
+004c66: 5405 5300                              |006f: iget-object v5, v0, Lcom/google/android/checkers/a;.z:[S // field@0053
+004c6a: 4a04 0504                              |0071: aget-short v4, v5, v4
+004c6e: 2c03 8104 0000                         |0073: sparse-switch v3, 000004f4 // +00000481
+004c74: 1403 3f42 0f00                         |0076: const v3, #float 1.4013e-39 // #000f423f
+004c7a: 3334 a1ff                              |0079: if-ne v4, v3, 001a // -005f
+004c7e: 0800 1800                              |007b: move-object/from16 v0, v24
+004c82: 0201 1b00                              |007d: move/from16 v1, v27
+004c86: 0202 1e00                              |007f: move/from16 v2, v30
+004c8a: 7030 7500 1002                         |0081: invoke-direct {v0, v1, v2}, Lcom/google/android/checkers/a;.a:(IZ)I // method@0075
+004c90: 0a03                                   |0084: move-result v3
+004c92: 2b03 7904 0000                         |0085: packed-switch v3, 000004fe // +00000479
+004c98: 0800 1800                              |0088: move-object/from16 v0, v24
+004c9c: 520d 3c00                              |008a: iget v13, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+004ca0: 0800 1800                              |008c: move-object/from16 v0, v24
+004ca4: 520e 4b00                              |008e: iget v14, v0, Lcom/google/android/checkers/a;.r:I // field@004b
+004ca8: 0800 1800                              |0090: move-object/from16 v0, v24
+004cac: 520f 3d00                              |0092: iget v15, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004cb0: 0800 1800                              |0094: move-object/from16 v0, v24
+004cb4: 5200 3e00                              |0096: iget v0, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+004cb8: 0210 0000                              |0098: move/from16 v16, v0
+004cbc: 0800 1800                              |009a: move-object/from16 v0, v24
+004cc0: 5200 3f00                              |009c: iget v0, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004cc4: 0211 0000                              |009e: move/from16 v17, v0
+004cc8: 0800 1800                              |00a0: move-object/from16 v0, v24
+004ccc: 5200 4000                              |00a2: iget v0, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+004cd0: 0212 0000                              |00a4: move/from16 v18, v0
+004cd4: 0800 1800                              |00a6: move-object/from16 v0, v24
+004cd8: 5200 4f00                              |00a8: iget v0, v0, Lcom/google/android/checkers/a;.v:I // field@004f
+004cdc: 0213 0000                              |00aa: move/from16 v19, v0
+004ce0: 0800 1800                              |00ac: move-object/from16 v0, v24
+004ce4: 5200 5000                              |00ae: iget v0, v0, Lcom/google/android/checkers/a;.w:I // field@0050
+004ce8: 0214 0000                              |00b0: move/from16 v20, v0
+004cec: 0800 1800                              |00b2: move-object/from16 v0, v24
+004cf0: 5200 5100                              |00b4: iget v0, v0, Lcom/google/android/checkers/a;.x:I // field@0051
+004cf4: 0215 0000                              |00b6: move/from16 v21, v0
+004cf8: 2b0d 4e04 0000                         |00b8: packed-switch v13, 00000506 // +0000044e
+004cfe: 1208                                   |00bb: const/4 v8, #int 0 // #0
+004d00: 130a 4000                              |00bc: const/16 v10, #int 64 // #40
+004d04: 1203                                   |00be: const/4 v3, #int 0 // #0
+004d06: 013c                                   |00bf: move v12, v3
+004d08: 020b 1900                              |00c0: move/from16 v11, v25
+004d0c: 34dc 9602                              |00c2: if-lt v12, v13, 0358 // +0296
+004d10: 0800 1800                              |00c4: move-object/from16 v0, v24
+004d14: 5503 2e00                              |00c6: iget-boolean v3, v0, Lcom/google/android/checkers/a;.B:Z // field@002e
+004d18: 3803 0900                              |00c8: if-eqz v3, 00d1 // +0009
+004d1c: 0800 1800                              |00ca: move-object/from16 v0, v24
+004d20: 0201 1b00                              |00cc: move/from16 v1, v27
+004d24: 705b 7d00 10a7                         |00ce: invoke-direct {v0, v1, v7, v10, v11}, Lcom/google/android/checkers/a;.a:(IIII)V // method@007d
+004d2a: 01b4                                   |00d1: move v4, v11
+004d2c: 2900 48ff                              |00d2: goto/16 001a // -00b8
+004d30: 0800 1800                              |00d4: move-object/from16 v0, v24
+004d34: 5203 3d00                              |00d6: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004d38: 3803 3800                              |00d8: if-eqz v3, 0110 // +0038
+004d3c: 0800 1800                              |00da: move-object/from16 v0, v24
+004d40: 5203 3f00                              |00dc: iget v3, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004d44: 3803 3200                              |00de: if-eqz v3, 0110 // +0032
+004d48: 0800 1800                              |00e0: move-object/from16 v0, v24
+004d4c: 5203 3d00                              |00e2: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004d50: 0800 1800                              |00e4: move-object/from16 v0, v24
+004d54: 5205 3f00                              |00e6: iget v5, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004d58: 381e 1b00                              |00e8: if-eqz v30, 0103 // +001b
+004d5c: 7110 9f00 0300                         |00ea: invoke-static {v3}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+004d62: 0a04                                   |00ed: move-result v4
+004d64: 7110 9f00 0500                         |00ee: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+004d6a: 0a03                                   |00f1: move-result v3
+004d6c: d803 03fc                              |00f2: add-int/lit8 v3, v3, #int -4 // #fc
+004d70: 6205 5c00                              |00f4: sget-object v5, Lcom/google/android/checkers/g;.d:[B // field@005c
+004d74: da03 031c                              |00f6: mul-int/lit8 v3, v3, #int 28 // #1c
+004d78: b043                                   |00f8: add-int/2addr v3, v4
+004d7a: 4803 0503                              |00f9: aget-byte v3, v5, v3
+004d7e: 0200 1b00                              |00fb: move/from16 v0, v27
+004d82: 7120 7300 0300                         |00fd: invoke-static {v3, v0}, Lcom/google/android/checkers/a;.a:(II)I // method@0073
+004d88: 0a04                                   |0100: move-result v4
+004d8a: 2900 19ff                              |0101: goto/16 001a // -00e7
+004d8e: 7110 9f00 0500                         |0103: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+004d94: 0a04                                   |0106: move-result v4
+004d96: d904 041f                              |0107: rsub-int/lit8 v4, v4, #int 31 // #1f
+004d9a: 7110 9f00 0300                         |0109: invoke-static {v3}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+004da0: 0a03                                   |010c: move-result v3
+004da2: d903 031f                              |010d: rsub-int/lit8 v3, v3, #int 31 // #1f
+004da6: 28e3                                   |010f: goto 00f2 // -001d
+004da8: 0800 1800                              |0110: move-object/from16 v0, v24
+004dac: 5203 3f00                              |0112: iget v3, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004db0: 3803 1200                              |0114: if-eqz v3, 0126 // +0012
+004db4: 0800 1800                              |0116: move-object/from16 v0, v24
+004db8: 5203 3e00                              |0118: iget v3, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+004dbc: 0800 1800                              |011a: move-object/from16 v0, v24
+004dc0: 5204 3f00                              |011c: iget v4, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004dc4: 1205                                   |011e: const/4 v5, #int 0 // #0
+004dc6: 0200 1e00                              |011f: move/from16 v0, v30
+004dca: 7140 7900 3054                         |0121: invoke-static {v0, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(ZIIZ)I // method@0079
+004dd0: 0a03                                   |0124: move-result v3
+004dd2: 28d6                                   |0125: goto 00fb // -002a
+004dd4: 0800 1800                              |0126: move-object/from16 v0, v24
+004dd8: 5203 3d00                              |0128: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004ddc: 3803 1500                              |012a: if-eqz v3, 013f // +0015
+004de0: 381e 1100                              |012c: if-eqz v30, 013d // +0011
+004de4: 1203                                   |012e: const/4 v3, #int 0 // #0
+004de6: 0800 1800                              |012f: move-object/from16 v0, v24
+004dea: 5204 4000                              |0131: iget v4, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+004dee: 0800 1800                              |0133: move-object/from16 v0, v24
+004df2: 5205 3d00                              |0135: iget v5, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004df6: 1216                                   |0137: const/4 v6, #int 1 // #1
+004df8: 7140 7900 4365                         |0138: invoke-static {v3, v4, v5, v6}, Lcom/google/android/checkers/a;.a:(ZIIZ)I // method@0079
+004dfe: 0a03                                   |013b: move-result v3
+004e00: 28bf                                   |013c: goto 00fb // -0041
+004e02: 1213                                   |013d: const/4 v3, #int 1 // #1
+004e04: 28f1                                   |013e: goto 012f // -000f
+004e06: 0800 1800                              |013f: move-object/from16 v0, v24
+004e0a: 5203 3e00                              |0141: iget v3, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+004e0e: 0800 1800                              |0143: move-object/from16 v0, v24
+004e12: 5205 4000                              |0145: iget v5, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+004e16: 381e 1a00                              |0147: if-eqz v30, 0161 // +001a
+004e1a: 7110 9f00 0300                         |0149: invoke-static {v3}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+004e20: 0a04                                   |014c: move-result v4
+004e22: 7110 9f00 0500                         |014d: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+004e28: 0a03                                   |0150: move-result v3
+004e2a: 1305 1000                              |0151: const/16 v5, #int 16 // #10
+004e2e: 3454 0600                              |0153: if-lt v4, v5, 0159 // +0006
+004e32: d904 041f                              |0155: rsub-int/lit8 v4, v4, #int 31 // #1f
+004e36: d903 031f                              |0157: rsub-int/lit8 v3, v3, #int 31 // #1f
+004e3a: 6205 5900                              |0159: sget-object v5, Lcom/google/android/checkers/g;.a:[B // field@0059
+004e3e: da03 0310                              |015b: mul-int/lit8 v3, v3, #int 16 // #10
+004e42: b043                                   |015d: add-int/2addr v3, v4
+004e44: 4803 0503                              |015e: aget-byte v3, v5, v3
+004e48: 289b                                   |0160: goto 00fb // -0065
+004e4a: 7110 9f00 0500                         |0161: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+004e50: 0a04                                   |0164: move-result v4
+004e52: 7110 9f00 0300                         |0165: invoke-static {v3}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+004e58: 0a03                                   |0168: move-result v3
+004e5a: 28e8                                   |0169: goto 0151 // -0018
+004e5c: 0800 1800                              |016a: move-object/from16 v0, v24
+004e60: 5203 4f00                              |016c: iget v3, v0, Lcom/google/android/checkers/a;.v:I // field@004f
+004e64: 1214                                   |016e: const/4 v4, #int 1 // #1
+004e66: 3343 a000                              |016f: if-ne v3, v4, 020f // +00a0
+004e6a: 0800 1800                              |0171: move-object/from16 v0, v24
+004e6e: 5203 3d00                              |0173: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004e72: 3803 5200                              |0175: if-eqz v3, 01c7 // +0052
+004e76: 0800 1800                              |0177: move-object/from16 v0, v24
+004e7a: 5203 4000                              |0179: iget v3, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+004e7e: 3903 1c00                              |017b: if-nez v3, 0197 // +001c
+004e82: 381e 1800                              |017d: if-eqz v30, 0195 // +0018
+004e86: 1203                                   |017f: const/4 v3, #int 0 // #0
+004e88: 0800 1800                              |0180: move-object/from16 v0, v24
+004e8c: 5204 3f00                              |0182: iget v4, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004e90: 0800 1800                              |0184: move-object/from16 v0, v24
+004e94: 5205 3d00                              |0186: iget v5, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004e98: 1216                                   |0188: const/4 v6, #int 1 // #1
+004e9a: 7140 8c00 4365                         |0189: invoke-static {v3, v4, v5, v6}, Lcom/google/android/checkers/a;.d:(ZIIZ)I // method@008c
+004ea0: 0a03                                   |018c: move-result v3
+004ea2: 0200 1b00                              |018d: move/from16 v0, v27
+004ea6: 7120 7300 0300                         |018f: invoke-static {v3, v0}, Lcom/google/android/checkers/a;.a:(II)I // method@0073
+004eac: 0a04                                   |0192: move-result v4
+004eae: 2900 87fe                              |0193: goto/16 001a // -0179
+004eb2: 1213                                   |0195: const/4 v3, #int 1 // #1
+004eb4: 28ea                                   |0196: goto 0180 // -0016
+004eb6: 0800 1800                              |0197: move-object/from16 v0, v24
+004eba: 5203 3f00                              |0199: iget v3, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004ebe: 3803 1900                              |019b: if-eqz v3, 01b4 // +0019
+004ec2: 381e 1500                              |019d: if-eqz v30, 01b2 // +0015
+004ec6: 1203                                   |019f: const/4 v3, #int 0 // #0
+004ec8: 0800 1800                              |01a0: move-object/from16 v0, v24
+004ecc: 5204 3f00                              |01a2: iget v4, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004ed0: 0800 1800                              |01a4: move-object/from16 v0, v24
+004ed4: 5205 4000                              |01a6: iget v5, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+004ed8: 0800 1800                              |01a8: move-object/from16 v0, v24
+004edc: 5206 3d00                              |01aa: iget v6, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004ee0: 1217                                   |01ac: const/4 v7, #int 1 // #1
+004ee2: 7157 8200 4365                         |01ad: invoke-static {v3, v4, v5, v6, v7}, Lcom/google/android/checkers/a;.b:(ZIIIZ)I // method@0082
+004ee8: 0a03                                   |01b0: move-result v3
+004eea: 28dc                                   |01b1: goto 018d // -0024
+004eec: 1213                                   |01b2: const/4 v3, #int 1 // #1
+004eee: 28ed                                   |01b3: goto 01a0 // -0013
+004ef0: 381e 1100                              |01b4: if-eqz v30, 01c5 // +0011
+004ef4: 1203                                   |01b6: const/4 v3, #int 0 // #0
+004ef6: 0800 1800                              |01b7: move-object/from16 v0, v24
+004efa: 5204 4000                              |01b9: iget v4, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+004efe: 0800 1800                              |01bb: move-object/from16 v0, v24
+004f02: 5205 3d00                              |01bd: iget v5, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004f06: 1216                                   |01bf: const/4 v6, #int 1 // #1
+004f08: 7140 8300 4365                         |01c0: invoke-static {v3, v4, v5, v6}, Lcom/google/android/checkers/a;.b:(ZIIZ)I // method@0083
+004f0e: 0a03                                   |01c3: move-result v3
+004f10: 28c9                                   |01c4: goto 018d // -0037
+004f12: 1213                                   |01c5: const/4 v3, #int 1 // #1
+004f14: 28f1                                   |01c6: goto 01b7 // -000f
+004f16: 0800 1800                              |01c7: move-object/from16 v0, v24
+004f1a: 5203 4000                              |01c9: iget v3, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+004f1e: 3903 1500                              |01cb: if-nez v3, 01e0 // +0015
+004f22: 381e 1100                              |01cd: if-eqz v30, 01de // +0011
+004f26: 1203                                   |01cf: const/4 v3, #int 0 // #0
+004f28: 0800 1800                              |01d0: move-object/from16 v0, v24
+004f2c: 5204 3f00                              |01d2: iget v4, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004f30: 0800 1800                              |01d4: move-object/from16 v0, v24
+004f34: 5205 3e00                              |01d6: iget v5, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+004f38: 1216                                   |01d8: const/4 v6, #int 1 // #1
+004f3a: 7140 8900 4365                         |01d9: invoke-static {v3, v4, v5, v6}, Lcom/google/android/checkers/a;.c:(ZIIZ)I // method@0089
+004f40: 0a03                                   |01dc: move-result v3
+004f42: 28b0                                   |01dd: goto 018d // -0050
+004f44: 1213                                   |01de: const/4 v3, #int 1 // #1
+004f46: 28f1                                   |01df: goto 01d0 // -000f
+004f48: 0800 1800                              |01e0: move-object/from16 v0, v24
+004f4c: 5203 3f00                              |01e2: iget v3, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004f50: 3803 1900                              |01e4: if-eqz v3, 01fd // +0019
+004f54: 381e 1500                              |01e6: if-eqz v30, 01fb // +0015
+004f58: 1203                                   |01e8: const/4 v3, #int 0 // #0
+004f5a: 0800 1800                              |01e9: move-object/from16 v0, v24
+004f5e: 5204 3f00                              |01eb: iget v4, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004f62: 0800 1800                              |01ed: move-object/from16 v0, v24
+004f66: 5205 4000                              |01ef: iget v5, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+004f6a: 0800 1800                              |01f1: move-object/from16 v0, v24
+004f6e: 5206 3e00                              |01f3: iget v6, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+004f72: 1217                                   |01f5: const/4 v7, #int 1 // #1
+004f74: 7157 7800 4365                         |01f6: invoke-static {v3, v4, v5, v6, v7}, Lcom/google/android/checkers/a;.a:(ZIIIZ)I // method@0078
+004f7a: 0a03                                   |01f9: move-result v3
+004f7c: 2893                                   |01fa: goto 018d // -006d
+004f7e: 1213                                   |01fb: const/4 v3, #int 1 // #1
+004f80: 28ed                                   |01fc: goto 01e9 // -0013
+004f82: 381e 1000                              |01fd: if-eqz v30, 020d // +0010
+004f86: 1203                                   |01ff: const/4 v3, #int 0 // #0
+004f88: 0800 1800                              |0200: move-object/from16 v0, v24
+004f8c: 5204 4000                              |0202: iget v4, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+004f90: 0800 1800                              |0204: move-object/from16 v0, v24
+004f94: 5205 3e00                              |0206: iget v5, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+004f98: 7130 7700 4305                         |0208: invoke-static {v3, v4, v5}, Lcom/google/android/checkers/a;.a:(ZII)I // method@0077
+004f9e: 0a03                                   |020b: move-result v3
+004fa0: 2881                                   |020c: goto 018d // -007f
+004fa2: 1213                                   |020d: const/4 v3, #int 1 // #1
+004fa4: 28f2                                   |020e: goto 0200 // -000e
+004fa6: 0800 1800                              |020f: move-object/from16 v0, v24
+004faa: 5203 3f00                              |0211: iget v3, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004fae: 3803 4500                              |0213: if-eqz v3, 0258 // +0045
+004fb2: 0800 1800                              |0215: move-object/from16 v0, v24
+004fb6: 5203 3e00                              |0217: iget v3, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+004fba: 3903 1300                              |0219: if-nez v3, 022c // +0013
+004fbe: 0800 1800                              |021b: move-object/from16 v0, v24
+004fc2: 5203 3d00                              |021d: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004fc6: 0800 1800                              |021f: move-object/from16 v0, v24
+004fca: 5204 3f00                              |0221: iget v4, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+004fce: 1205                                   |0223: const/4 v5, #int 0 // #0
+004fd0: 0200 1e00                              |0224: move/from16 v0, v30
+004fd4: 7140 8c00 3054                         |0226: invoke-static {v0, v3, v4, v5}, Lcom/google/android/checkers/a;.d:(ZIIZ)I // method@008c
+004fda: 0a03                                   |0229: move-result v3
+004fdc: 2900 63ff                              |022a: goto/16 018d // -009d
+004fe0: 0800 1800                              |022c: move-object/from16 v0, v24
+004fe4: 5203 3d00                              |022e: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004fe8: 3803 1700                              |0230: if-eqz v3, 0247 // +0017
+004fec: 0800 1800                              |0232: move-object/from16 v0, v24
+004ff0: 5203 3d00                              |0234: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+004ff4: 0800 1800                              |0236: move-object/from16 v0, v24
+004ff8: 5204 3e00                              |0238: iget v4, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+004ffc: 0800 1800                              |023a: move-object/from16 v0, v24
+005000: 5205 3f00                              |023c: iget v5, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+005004: 1206                                   |023e: const/4 v6, #int 0 // #0
+005006: 0200 1e00                              |023f: move/from16 v0, v30
+00500a: 7156 8200 3054                         |0241: invoke-static {v0, v3, v4, v5, v6}, Lcom/google/android/checkers/a;.b:(ZIIIZ)I // method@0082
+005010: 0a03                                   |0244: move-result v3
+005012: 2900 48ff                              |0245: goto/16 018d // -00b8
+005016: 0800 1800                              |0247: move-object/from16 v0, v24
+00501a: 5203 3e00                              |0249: iget v3, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+00501e: 0800 1800                              |024b: move-object/from16 v0, v24
+005022: 5204 3f00                              |024d: iget v4, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+005026: 1205                                   |024f: const/4 v5, #int 0 // #0
+005028: 0200 1e00                              |0250: move/from16 v0, v30
+00502c: 7140 8300 3054                         |0252: invoke-static {v0, v3, v4, v5}, Lcom/google/android/checkers/a;.b:(ZIIZ)I // method@0083
+005032: 0a03                                   |0255: move-result v3
+005034: 2900 37ff                              |0256: goto/16 018d // -00c9
+005038: 0800 1800                              |0258: move-object/from16 v0, v24
+00503c: 5203 3e00                              |025a: iget v3, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+005040: 3903 1300                              |025c: if-nez v3, 026f // +0013
+005044: 0800 1800                              |025e: move-object/from16 v0, v24
+005048: 5203 3d00                              |0260: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+00504c: 0800 1800                              |0262: move-object/from16 v0, v24
+005050: 5204 4000                              |0264: iget v4, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+005054: 1205                                   |0266: const/4 v5, #int 0 // #0
+005056: 0200 1e00                              |0267: move/from16 v0, v30
+00505a: 7140 8900 3054                         |0269: invoke-static {v0, v3, v4, v5}, Lcom/google/android/checkers/a;.c:(ZIIZ)I // method@0089
+005060: 0a03                                   |026c: move-result v3
+005062: 2900 20ff                              |026d: goto/16 018d // -00e0
+005066: 0800 1800                              |026f: move-object/from16 v0, v24
+00506a: 5203 3d00                              |0271: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+00506e: 3803 1700                              |0273: if-eqz v3, 028a // +0017
+005072: 0800 1800                              |0275: move-object/from16 v0, v24
+005076: 5203 3d00                              |0277: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+00507a: 0800 1800                              |0279: move-object/from16 v0, v24
+00507e: 5204 3e00                              |027b: iget v4, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+005082: 0800 1800                              |027d: move-object/from16 v0, v24
+005086: 5205 4000                              |027f: iget v5, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+00508a: 1206                                   |0281: const/4 v6, #int 0 // #0
+00508c: 0200 1e00                              |0282: move/from16 v0, v30
+005090: 7156 7800 3054                         |0284: invoke-static {v0, v3, v4, v5, v6}, Lcom/google/android/checkers/a;.a:(ZIIIZ)I // method@0078
+005096: 0a03                                   |0287: move-result v3
+005098: 2900 05ff                              |0288: goto/16 018d // -00fb
+00509c: 0800 1800                              |028a: move-object/from16 v0, v24
+0050a0: 5203 3e00                              |028c: iget v3, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+0050a4: 0800 1800                              |028e: move-object/from16 v0, v24
+0050a8: 5204 4000                              |0290: iget v4, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+0050ac: 0200 1e00                              |0292: move/from16 v0, v30
+0050b0: 7130 7700 3004                         |0294: invoke-static {v0, v3, v4}, Lcom/google/android/checkers/a;.a:(ZII)I // method@0077
+0050b6: 0a03                                   |0297: move-result v3
+0050b8: 2900 f5fe                              |0298: goto/16 018d // -010b
+0050bc: 0800 1800                              |029a: move-object/from16 v0, v24
+0050c0: 5203 4f00                              |029c: iget v3, v0, Lcom/google/android/checkers/a;.v:I // field@004f
+0050c4: 1224                                   |029e: const/4 v4, #int 2 // #2
+0050c6: 3343 8efd                              |029f: if-ne v3, v4, 002d // -0272
+0050ca: 0800 1800                              |02a1: move-object/from16 v0, v24
+0050ce: 5203 5000                              |02a3: iget v3, v0, Lcom/google/android/checkers/a;.w:I // field@0050
+0050d2: 1224                                   |02a5: const/4 v4, #int 2 // #2
+0050d4: 3343 87fd                              |02a6: if-ne v3, v4, 002d // -0279
+0050d8: 0800 1800                              |02a8: move-object/from16 v0, v24
+0050dc: 5203 3d00                              |02aa: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+0050e0: 3903 81fd                              |02ac: if-nez v3, 002d // -027f
+0050e4: 0800 1800                              |02ae: move-object/from16 v0, v24
+0050e8: 5203 3f00                              |02b0: iget v3, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+0050ec: 3903 7bfd                              |02b2: if-nez v3, 002d // -0285
+0050f0: 0800 1800                              |02b4: move-object/from16 v0, v24
+0050f4: 5203 3e00                              |02b6: iget v3, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+0050f8: 0800 1800                              |02b8: move-object/from16 v0, v24
+0050fc: 5207 4000                              |02ba: iget v7, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+005100: 381e 4000                              |02bc: if-eqz v30, 02fc // +0040
+005104: 7110 9f00 0300                         |02be: invoke-static {v3}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+00510a: 0a06                                   |02c1: move-result v6
+00510c: d804 03ff                              |02c2: add-int/lit8 v4, v3, #int -1 // #ff
+005110: b543                                   |02c4: and-int/2addr v3, v4
+005112: 7110 9f00 0300                         |02c5: invoke-static {v3}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005118: 0a05                                   |02c8: move-result v5
+00511a: 7110 9f00 0700                         |02c9: invoke-static {v7}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005120: 0a04                                   |02cc: move-result v4
+005122: d803 07ff                              |02cd: add-int/lit8 v3, v7, #int -1 // #ff
+005126: b573                                   |02cf: and-int/2addr v3, v7
+005128: 7110 9f00 0300                         |02d0: invoke-static {v3}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+00512e: 0a03                                   |02d3: move-result v3
+005130: 0216 0300                              |02d4: move/from16 v22, v3
+005134: 0153                                   |02d6: move v3, v5
+005136: 0205 1600                              |02d7: move/from16 v5, v22
+00513a: 0217 0400                              |02d9: move/from16 v23, v4
+00513e: 0164                                   |02db: move v4, v6
+005140: 0206 1700                              |02dc: move/from16 v6, v23
+005144: 3534 3f00                              |02de: if-ge v4, v3, 031d // +003f
+005148: 6207 3800                              |02e0: sget-object v7, Lcom/google/android/checkers/a;.L:[I // field@0038
+00514c: 4403 0703                              |02e2: aget v3, v7, v3
+005150: b043                                   |02e4: add-int/2addr v3, v4
+005152: 0134                                   |02e5: move v4, v3
+005154: 3556 3e00                              |02e6: if-ge v6, v5, 0324 // +003e
+005158: 6203 3800                              |02e8: sget-object v3, Lcom/google/android/checkers/a;.L:[I // field@0038
+00515c: 4403 0305                              |02ea: aget v3, v3, v5
+005160: b063                                   |02ec: add-int/2addr v3, v6
+005162: 6205 6900                              |02ed: sget-object v5, Lcom/google/android/checkers/g;.q:[B // field@0069
+005166: d244 f001                              |02ef: mul-int/lit16 v4, v4, #int 496 // #01f0
+00516a: b043                                   |02f1: add-int/2addr v3, v4
+00516c: 4803 0503                              |02f2: aget-byte v3, v5, v3
+005170: 0200 1b00                              |02f4: move/from16 v0, v27
+005174: 7120 7300 0300                         |02f6: invoke-static {v3, v0}, Lcom/google/android/checkers/a;.a:(II)I // method@0073
+00517a: 0a04                                   |02f9: move-result v4
+00517c: 2900 20fd                              |02fa: goto/16 001a // -02e0
+005180: 7110 9f00 0700                         |02fc: invoke-static {v7}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005186: 0a06                                   |02ff: move-result v6
+005188: d804 07ff                              |0300: add-int/lit8 v4, v7, #int -1 // #ff
+00518c: b574                                   |0302: and-int/2addr v4, v7
+00518e: 7110 9f00 0400                         |0303: invoke-static {v4}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005194: 0a05                                   |0306: move-result v5
+005196: 7110 9f00 0300                         |0307: invoke-static {v3}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+00519c: 0a04                                   |030a: move-result v4
+00519e: d807 03ff                              |030b: add-int/lit8 v7, v3, #int -1 // #ff
+0051a2: b573                                   |030d: and-int/2addr v3, v7
+0051a4: 7110 9f00 0300                         |030e: invoke-static {v3}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0051aa: 0a03                                   |0311: move-result v3
+0051ac: 0216 0300                              |0312: move/from16 v22, v3
+0051b0: 0153                                   |0314: move v3, v5
+0051b2: 0205 1600                              |0315: move/from16 v5, v22
+0051b6: 0217 0400                              |0317: move/from16 v23, v4
+0051ba: 0164                                   |0319: move v4, v6
+0051bc: 0206 1700                              |031a: move/from16 v6, v23
+0051c0: 28c2                                   |031c: goto 02de // -003e
+0051c2: 6207 3800                              |031d: sget-object v7, Lcom/google/android/checkers/a;.L:[I // field@0038
+0051c6: 4404 0704                              |031f: aget v4, v7, v4
+0051ca: b043                                   |0321: add-int/2addr v3, v4
+0051cc: 0134                                   |0322: move v4, v3
+0051ce: 28c3                                   |0323: goto 02e6 // -003d
+0051d0: 6203 3800                              |0324: sget-object v3, Lcom/google/android/checkers/a;.L:[I // field@0038
+0051d4: 4403 0306                              |0326: aget v3, v3, v6
+0051d8: b053                                   |0328: add-int/2addr v3, v5
+0051da: 28c4                                   |0329: goto 02ed // -003c
+0051dc: 0200 1900                              |032a: move/from16 v0, v25
+0051e0: 3704 4afd                              |032c: if-le v4, v0, 0076 // -02b6
+0051e4: 1404 3f42 0f00                         |032e: const v4, #float 1.4013e-39 // #000f423f
+0051ea: 2900 45fd                              |0331: goto/16 0076 // -02bb
+0051ee: 0200 1a00                              |0333: move/from16 v0, v26
+0051f2: 3404 f9ff                              |0335: if-lt v4, v0, 032e // -0007
+0051f6: 2900 3ffd                              |0337: goto/16 0076 // -02c1
+0051fa: 0200 1b00                              |0339: move/from16 v0, v27
+0051fe: d004 0c81                              |033b: add-int/lit16 v4, v0, #int -32500 // #810c
+005202: 2900 ddfc                              |033d: goto/16 001a // -0323
+005206: 9103 071b                              |033f: sub-int v3, v7, v27
+00520a: 1214                                   |0341: const/4 v4, #int 1 // #1
+00520c: 3643 46fd                              |0342: if-gt v3, v4, 0088 // -02ba
+005210: 1303 4000                              |0344: const/16 v3, #int 64 // #40
+005214: 3537 42fd                              |0346: if-ge v7, v3, 0088 // -02be
+005218: d807 0701                              |0348: add-int/lit8 v7, v7, #int 1 // #01
+00521c: 2900 3efd                              |034a: goto/16 0088 // -02c2
+005220: d808 1d1e                              |034c: add-int/lit8 v8, v29, #int 30 // #1e
+005224: 2900 6efd                              |034e: goto/16 00bc // -0292
+005228: d808 1d0a                              |0350: add-int/lit8 v8, v29, #int 10 // #0a
+00522c: 2900 6afd                              |0352: goto/16 00bc // -0296
+005230: d808 1d05                              |0354: add-int/lit8 v8, v29, #int 5 // #05
+005234: 2900 66fd                              |0356: goto/16 00bc // -029a
+005238: 9003 0e0c                              |0358: add-int v3, v14, v12
+00523c: 0800 1800                              |035a: move-object/from16 v0, v24
+005240: 7020 8500 3000                         |035c: invoke-direct {v0, v3}, Lcom/google/android/checkers/a;.b:(I)V // method@0085
+005246: 0200 1a00                              |035f: move/from16 v0, v26
+00524a: 7b04                                   |0361: neg-int v4, v0
+00524c: 7bb5                                   |0362: neg-int v5, v11
+00524e: d806 1b01                              |0363: add-int/lit8 v6, v27, #int 1 // #01
+005252: 381e 3b00                              |0365: if-eqz v30, 03a0 // +003b
+005256: 1209                                   |0367: const/4 v9, #int 0 // #0
+005258: 0803 1800                              |0368: move-object/from16 v3, v24
+00525c: 7607 7400 0300                         |036a: invoke-direct/range {v3, v4, v5, v6, v7, v8, v9}, Lcom/google/android/checkers/a;.a:(IIIIIZ)I // method@0074
+005262: 0a03                                   |036d: move-result v3
+005264: 7b34                                   |036e: neg-int v4, v3
+005266: 0800 1800                              |036f: move-object/from16 v0, v24
+00526a: 590f 3d00                              |0371: iput v15, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+00526e: 0200 1000                              |0373: move/from16 v0, v16
+005272: 0801 1800                              |0375: move-object/from16 v1, v24
+005276: 5910 3e00                              |0377: iput v0, v1, Lcom/google/android/checkers/a;.e:I // field@003e
+00527a: 0200 1100                              |0379: move/from16 v0, v17
+00527e: 0801 1800                              |037b: move-object/from16 v1, v24
+005282: 5910 3f00                              |037d: iput v0, v1, Lcom/google/android/checkers/a;.f:I // field@003f
+005286: 0200 1200                              |037f: move/from16 v0, v18
+00528a: 0801 1800                              |0381: move-object/from16 v1, v24
+00528e: 5910 4000                              |0383: iput v0, v1, Lcom/google/android/checkers/a;.g:I // field@0040
+005292: 0200 1300                              |0385: move/from16 v0, v19
+005296: 0801 1800                              |0387: move-object/from16 v1, v24
+00529a: 5910 4f00                              |0389: iput v0, v1, Lcom/google/android/checkers/a;.v:I // field@004f
+00529e: 0200 1400                              |038b: move/from16 v0, v20
+0052a2: 0801 1800                              |038d: move-object/from16 v1, v24
+0052a6: 5910 5000                              |038f: iput v0, v1, Lcom/google/android/checkers/a;.w:I // field@0050
+0052aa: 0200 1500                              |0391: move/from16 v0, v21
+0052ae: 0801 1800                              |0393: move-object/from16 v1, v24
+0052b2: 5910 5100                              |0395: iput v0, v1, Lcom/google/android/checkers/a;.x:I // field@0051
+0052b6: 0800 1800                              |0397: move-object/from16 v0, v24
+0052ba: 5503 4600                              |0399: iget-boolean v3, v0, Lcom/google/android/checkers/a;.m:Z // field@0046
+0052be: 3803 0700                              |039b: if-eqz v3, 03a2 // +0007
+0052c2: 1204                                   |039d: const/4 v4, #int 0 // #0
+0052c4: 2900 7cfc                              |039e: goto/16 001a // -0384
+0052c8: 1219                                   |03a0: const/4 v9, #int 1 // #1
+0052ca: 28c7                                   |03a1: goto 0368 // -0039
+0052cc: 37b4 3f01                              |03a2: if-le v4, v11, 04e1 // +013f
+0052d0: 0200 1a00                              |03a4: move/from16 v0, v26
+0052d4: 3404 1300                              |03a6: if-lt v4, v0, 03b9 // +0013
+0052d8: 0800 1800                              |03a8: move-object/from16 v0, v24
+0052dc: 5503 2e00                              |03aa: iget-boolean v3, v0, Lcom/google/android/checkers/a;.B:Z // field@002e
+0052e0: 3803 6efc                              |03ac: if-eqz v3, 001a // -0392
+0052e4: 1303 8000                              |03ae: const/16 v3, #int 128 // #80
+0052e8: 0800 1800                              |03b0: move-object/from16 v0, v24
+0052ec: 0201 1b00                              |03b2: move/from16 v1, v27
+0052f0: 7054 7d00 1037                         |03b4: invoke-direct {v0, v1, v7, v3, v4}, Lcom/google/android/checkers/a;.a:(IIII)V // method@007d
+0052f6: 2900 63fc                              |03b7: goto/16 001a // -039d
+0052fa: 1303 c000                              |03b9: const/16 v3, #int 192 // #c0
+0052fe: d805 0c01                              |03bb: add-int/lit8 v5, v12, #int 1 // #01
+005302: 015c                                   |03bd: move v12, v5
+005304: 013a                                   |03be: move v10, v3
+005306: 014b                                   |03bf: move v11, v4
+005308: 2900 02fd                              |03c0: goto/16 00c2 // -02fe
+00530c: 0800 1800                              |03c2: move-object/from16 v0, v24
+005310: 5203 4700                              |03c4: iget v3, v0, Lcom/google/android/checkers/a;.n:I // field@0047
+005314: d804 0301                              |03c6: add-int/lit8 v4, v3, #int 1 // #01
+005318: 0800 1800                              |03c8: move-object/from16 v0, v24
+00531c: 5904 4700                              |03ca: iput v4, v0, Lcom/google/android/checkers/a;.n:I // field@0047
+005320: 1304 8813                              |03cc: const/16 v4, #int 5000 // #1388
+005324: 3743 2100                              |03ce: if-le v3, v4, 03ef // +0021
+005328: 1203                                   |03d0: const/4 v3, #int 0 // #0
+00532a: 0800 1800                              |03d1: move-object/from16 v0, v24
+00532e: 5903 4700                              |03d3: iput v3, v0, Lcom/google/android/checkers/a;.n:I // field@0047
+005332: 7100 ab00 0000                         |03d5: invoke-static {}, Ljava/lang/System;.currentTimeMillis:()J // method@00ab
+005338: 0b03                                   |03d8: move-result-wide v3
+00533a: 0800 1800                              |03d9: move-object/from16 v0, v24
+00533e: 5305 4500                              |03db: iget-wide v5, v0, Lcom/google/android/checkers/a;.l:J // field@0045
+005342: 0800 1800                              |03dd: move-object/from16 v0, v24
+005346: 5207 4100                              |03df: iget v7, v0, Lcom/google/android/checkers/a;.h:I // field@0041
+00534a: 8177                                   |03e1: int-to-long v7, v7
+00534c: bb75                                   |03e2: add-long/2addr v5, v7
+00534e: 3103 0305                              |03e3: cmp-long v3, v3, v5
+005352: 3d03 0a00                              |03e5: if-lez v3, 03ef // +000a
+005356: 1213                                   |03e7: const/4 v3, #int 1 // #1
+005358: 0800 1800                              |03e8: move-object/from16 v0, v24
+00535c: 5c03 4600                              |03ea: iput-boolean v3, v0, Lcom/google/android/checkers/a;.m:Z // field@0046
+005360: 1204                                   |03ec: const/4 v4, #int 0 // #0
+005362: 2900 2dfc                              |03ed: goto/16 001a // -03d3
+005366: 1204                                   |03ef: const/4 v4, #int 0 // #0
+005368: 0800 1800                              |03f0: move-object/from16 v0, v24
+00536c: 5203 3d00                              |03f2: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+005370: 3903 ad00                              |03f4: if-nez v3, 04a1 // +00ad
+005374: 0800 1800                              |03f6: move-object/from16 v0, v24
+005378: 5203 3e00                              |03f8: iget v3, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+00537c: 0145                                   |03fa: move v5, v4
+00537e: 3903 ad00                              |03fb: if-nez v3, 04a8 // +00ad
+005382: 1204                                   |03fd: const/4 v4, #int 0 // #0
+005384: 0800 1800                              |03fe: move-object/from16 v0, v24
+005388: 5203 3f00                              |0400: iget v3, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+00538c: 3903 ae00                              |0402: if-nez v3, 04b0 // +00ae
+005390: 0800 1800                              |0404: move-object/from16 v0, v24
+005394: 5203 4000                              |0406: iget v3, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+005398: 3903 af00                              |0408: if-nez v3, 04b7 // +00af
+00539c: 3345 b400                              |040a: if-ne v5, v4, 04be // +00b4
+0053a0: 1203                                   |040c: const/4 v3, #int 0 // #0
+0053a2: 3545 bd00                              |040d: if-ge v5, v4, 04ca // +00bd
+0053a6: 0800 1800                              |040f: move-object/from16 v0, v24
+0053aa: 5204 3e00                              |0411: iget v4, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+0053ae: 1405 1100 0088                         |0413: const v5, #float -3.85187e-34 // #88000011
+0053b4: b554                                   |0416: and-int/2addr v4, v5
+0053b6: 3804 0900                              |0417: if-eqz v4, 0420 // +0009
+0053ba: 7110 9e00 0400                         |0419: invoke-static {v4}, Ljava/lang/Integer;.bitCount:(I)I // method@009e
+0053c0: 0a04                                   |041c: move-result v4
+0053c2: e004 0403                              |041d: shl-int/lit8 v4, v4, #int 3 // #03
+0053c6: b043                                   |041f: add-int/2addr v3, v4
+0053c8: 0800 1800                              |0420: move-object/from16 v0, v24
+0053cc: 5204 3d00                              |0422: iget v4, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+0053d0: 0800 1800                              |0424: move-object/from16 v0, v24
+0053d4: 5205 3e00                              |0426: iget v5, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+0053d8: b654                                   |0428: or-int/2addr v4, v5
+0053da: 0800 1800                              |0429: move-object/from16 v0, v24
+0053de: 5205 3f00                              |042b: iget v5, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+0053e2: 0800 1800                              |042d: move-object/from16 v0, v24
+0053e6: 5206 4000                              |042f: iget v6, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+0053ea: b665                                   |0431: or-int/2addr v5, v6
+0053ec: 0800 1800                              |0432: move-object/from16 v0, v24
+0053f0: 5206 3f00                              |0434: iget v6, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+0053f4: 3806 0900                              |0436: if-eqz v6, 043f // +0009
+0053f8: dd06 0405                              |0438: and-int/lit8 v6, v4, #int 5 // #05
+0053fc: 1257                                   |043a: const/4 v7, #int 5 // #5
+0053fe: 3376 0400                              |043b: if-ne v6, v7, 043f // +0004
+005402: d803 030c                              |043d: add-int/lit8 v3, v3, #int 12 // #0c
+005406: 0800 1800                              |043f: move-object/from16 v0, v24
+00540a: 5206 3d00                              |0441: iget v6, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+00540e: 3806 0b00                              |0443: if-eqz v6, 044e // +000b
+005412: 1506 00a0                              |0445: const/high16 v6, #int -1610612736 // #a000
+005416: b556                                   |0447: and-int/2addr v6, v5
+005418: 1507 00a0                              |0448: const/high16 v7, #int -1610612736 // #a000
+00541c: 3376 0400                              |044a: if-ne v6, v7, 044e // +0004
+005420: d803 03f4                              |044c: add-int/lit8 v3, v3, #int -12 // #f4
+005424: 1406 0066 6600                         |044e: const v6, #float 9.40381e-39 // #00666600
+00542a: b564                                   |0451: and-int/2addr v4, v6
+00542c: 7110 9e00 0400                         |0452: invoke-static {v4}, Ljava/lang/Integer;.bitCount:(I)I // method@009e
+005432: 0a04                                   |0455: move-result v4
+005434: 1406 0066 6600                         |0456: const v6, #float 9.40381e-39 // #00666600
+00543a: b565                                   |0459: and-int/2addr v5, v6
+00543c: 7110 9e00 0500                         |045a: invoke-static {v5}, Ljava/lang/Integer;.bitCount:(I)I // method@009e
+005442: 0a05                                   |045d: move-result v5
+005444: b154                                   |045e: sub-int/2addr v4, v5
+005446: b043                                   |045f: add-int/2addr v3, v4
+005448: 0800 1800                              |0460: move-object/from16 v0, v24
+00544c: 5204 3d00                              |0462: iget v4, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+005450: 1405 1818 1818                         |0464: const v5, #float 1.96577e-24 // #18181818
+005456: b554                                   |0467: and-int/2addr v4, v5
+005458: 7110 9e00 0400                         |0468: invoke-static {v4}, Ljava/lang/Integer;.bitCount:(I)I // method@009e
+00545e: 0a04                                   |046b: move-result v4
+005460: 0800 1800                              |046c: move-object/from16 v0, v24
+005464: 5205 3f00                              |046e: iget v5, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+005468: 1406 1818 1818                         |0470: const v6, #float 1.96577e-24 // #18181818
+00546e: b565                                   |0473: and-int/2addr v5, v6
+005470: 7110 9e00 0500                         |0474: invoke-static {v5}, Ljava/lang/Integer;.bitCount:(I)I // method@009e
+005476: 0a05                                   |0477: move-result v5
+005478: b154                                   |0478: sub-int/2addr v4, v5
+00547a: b143                                   |0479: sub-int/2addr v3, v4
+00547c: 0800 1800                              |047a: move-object/from16 v0, v24
+005480: 5204 3e00                              |047c: iget v4, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+005484: 1405 0800 0010                         |047e: const v5, #float 2.52436e-29 // #10000008
+00548a: b554                                   |0481: and-int/2addr v4, v5
+00548c: 3804 0900                              |0482: if-eqz v4, 048b // +0009
+005490: 7110 9e00 0400                         |0484: invoke-static {v4}, Ljava/lang/Integer;.bitCount:(I)I // method@009e
+005496: 0a04                                   |0487: move-result v4
+005498: e004 0405                              |0488: shl-int/lit8 v4, v4, #int 5 // #05
+00549c: b143                                   |048a: sub-int/2addr v3, v4
+00549e: 0800 1800                              |048b: move-object/from16 v0, v24
+0054a2: 5204 4000                              |048d: iget v4, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+0054a6: 1405 0800 0010                         |048f: const v5, #float 2.52436e-29 // #10000008
+0054ac: b554                                   |0492: and-int/2addr v4, v5
+0054ae: 3804 4c00                              |0493: if-eqz v4, 04df // +004c
+0054b2: 7110 9e00 0400                         |0495: invoke-static {v4}, Ljava/lang/Integer;.bitCount:(I)I // method@009e
+0054b8: 0a04                                   |0498: move-result v4
+0054ba: e004 0405                              |0499: shl-int/lit8 v4, v4, #int 5 // #05
+0054be: b034                                   |049b: add-int/2addr v4, v3
+0054c0: 391e 7efb                              |049c: if-nez v30, 001a // -0482
+0054c4: 7b44                                   |049e: neg-int v4, v4
+0054c6: 2900 7bfb                              |049f: goto/16 001a // -0485
+0054ca: d804 0464                              |04a1: add-int/lit8 v4, v4, #int 100 // #64
+0054ce: d805 03ff                              |04a3: add-int/lit8 v5, v3, #int -1 // #ff
+0054d2: b553                                   |04a5: and-int/2addr v3, v5
+0054d4: 2900 4eff                              |04a6: goto/16 03f4 // -00b2
+0054d8: d054 8600                              |04a8: add-int/lit16 v4, v5, #int 134 // #0086
+0054dc: d805 03ff                              |04aa: add-int/lit8 v5, v3, #int -1 // #ff
+0054e0: b553                                   |04ac: and-int/2addr v3, v5
+0054e2: 0145                                   |04ad: move v5, v4
+0054e4: 2900 4dff                              |04ae: goto/16 03fb // -00b3
+0054e8: d804 0464                              |04b0: add-int/lit8 v4, v4, #int 100 // #64
+0054ec: d806 03ff                              |04b2: add-int/lit8 v6, v3, #int -1 // #ff
+0054f0: b563                                   |04b4: and-int/2addr v3, v6
+0054f2: 2900 4dff                              |04b5: goto/16 0402 // -00b3
+0054f6: d044 8600                              |04b7: add-int/lit16 v4, v4, #int 134 // #0086
+0054fa: d806 03ff                              |04b9: add-int/lit8 v6, v3, #int -1 // #ff
+0054fe: b563                                   |04bb: and-int/2addr v3, v6
+005500: 2900 4cff                              |04bc: goto/16 0408 // -00b4
+005504: 9103 0504                              |04be: sub-int v3, v5, v4
+005508: 9106 0504                              |04c0: sub-int v6, v5, v4
+00550c: e006 0608                              |04c2: shl-int/lit8 v6, v6, #int 8 // #08
+005510: 9007 0504                              |04c4: add-int v7, v5, v4
+005514: b376                                   |04c6: div-int/2addr v6, v7
+005516: b063                                   |04c7: add-int/2addr v3, v6
+005518: 2900 45ff                              |04c8: goto/16 040d // -00bb
+00551c: 3745 56ff                              |04ca: if-le v5, v4, 0420 // -00aa
+005520: 0800 1800                              |04cc: move-object/from16 v0, v24
+005524: 5204 4000                              |04ce: iget v4, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+005528: 1405 1100 0088                         |04d0: const v5, #float -3.85187e-34 // #88000011
+00552e: b554                                   |04d3: and-int/2addr v4, v5
+005530: 3804 4cff                              |04d4: if-eqz v4, 0420 // -00b4
+005534: 7110 9e00 0400                         |04d6: invoke-static {v4}, Ljava/lang/Integer;.bitCount:(I)I // method@009e
+00553a: 0a04                                   |04d9: move-result v4
+00553c: e004 0403                              |04da: shl-int/lit8 v4, v4, #int 3 // #03
+005540: b143                                   |04dc: sub-int/2addr v3, v4
+005542: 2900 43ff                              |04dd: goto/16 0420 // -00bd
+005546: 0134                                   |04df: move v4, v3
+005548: 28bc                                   |04e0: goto 049c // -0044
+00554a: 01a3                                   |04e1: move v3, v10
+00554c: 01b4                                   |04e2: move v4, v11
+00554e: 2900 d8fe                              |04e3: goto/16 03bb // -0128
+005552: 0207 1c00                              |04e5: move/from16 v7, v28
+005556: 2900 58fb                              |04e7: goto/16 003f // -04a8
+00555a: 0000                                   |04e9: nop // spacer
+00555c: 0001 0300 0200 0000 aa00 0000 4001 ... |04ea: packed-switch-data (10 units)
+005570: 0002 0200 4000 0000 8000 0000 b702 ... |04f4: sparse-switch-data (10 units)
+005584: 0001 0200 0000 0000 b402 0000 ba02 ... |04fe: packed-switch-data (8 units)
+005594: 0001 0300 0100 0000 9402 0000 9802 ... |0506: packed-switch-data (10 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #4              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(IZ)I'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 117
+      code          -
+      registers     : 7
+      ins           : 3
+      outs          : 4
+      insns size    : 55 16-bit code units
+0055a8:                                        |[0055a8] com.google.android.checkers.a.a:(IZ)I
+0055b8: 1221                                   |0000: const/4 v1, #int 2 // #2
+0055ba: 1200                                   |0001: const/4 v0, #int 0 // #0
+0055bc: 5940 3c00                              |0002: iput v0, v4, Lcom/google/android/checkers/a;.c:I // field@003c
+0055c0: da02 0540                              |0004: mul-int/lit8 v2, v5, #int 64 // #40
+0055c4: 5942 4b00                              |0006: iput v2, v4, Lcom/google/android/checkers/a;.r:I // field@004b
+0055c8: 5242 3d00                              |0008: iget v2, v4, Lcom/google/android/checkers/a;.d:I // field@003d
+0055cc: 5243 3e00                              |000a: iget v3, v4, Lcom/google/android/checkers/a;.e:I // field@003e
+0055d0: b632                                   |000c: or-int/2addr v2, v3
+0055d2: 5243 3f00                              |000d: iget v3, v4, Lcom/google/android/checkers/a;.f:I // field@003f
+0055d6: b632                                   |000f: or-int/2addr v2, v3
+0055d8: 5243 4000                              |0010: iget v3, v4, Lcom/google/android/checkers/a;.g:I // field@0040
+0055dc: b632                                   |0012: or-int/2addr v2, v3
+0055de: df02 02ff                              |0013: xor-int/lit8 v2, v2, #int -1 // #ff
+0055e2: 5543 4c00                              |0015: iget-boolean v3, v4, Lcom/google/android/checkers/a;.s:Z // field@004c
+0055e6: 3803 1000                              |0017: if-eqz v3, 0027 // +0010
+0055ea: 7040 8100 5426                         |0019: invoke-direct {v4, v5, v6, v2}, Lcom/google/android/checkers/a;.a:(IZI)Z // method@0081
+0055f0: 0a03                                   |001c: move-result v3
+0055f2: 7040 8800 5426                         |001d: invoke-direct {v4, v5, v6, v2}, Lcom/google/android/checkers/a;.b:(IZI)Z // method@0088
+0055f8: 0a02                                   |0020: move-result v2
+0055fa: 3903 0400                              |0021: if-nez v3, 0025 // +0004
+0055fe: 3802 0300                              |0023: if-eqz v2, 0026 // +0003
+005602: 0110                                   |0025: move v0, v1
+005604: 0f00                                   |0026: return v0
+005606: 7040 8100 5426                         |0027: invoke-direct {v4, v5, v6, v2}, Lcom/google/android/checkers/a;.a:(IZI)Z // method@0081
+00560c: 0a03                                   |002a: move-result v3
+00560e: 3803 0400                              |002b: if-eqz v3, 002f // +0004
+005612: 1210                                   |002d: const/4 v0, #int 1 // #1
+005614: 28f8                                   |002e: goto 0026 // -0008
+005616: 7040 8800 5426                         |002f: invoke-direct {v4, v5, v6, v2}, Lcom/google/android/checkers/a;.b:(IZI)Z // method@0088
+00561c: 0a02                                   |0032: move-result v2
+00561e: 3802 f3ff                              |0033: if-eqz v2, 0026 // -000d
+005622: 0110                                   |0035: move v0, v1
+005624: 28f0                                   |0036: goto 0026 // -0010
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #5              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(Z)I'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 118
+      code          -
+      registers     : 7
+      ins           : 2
+      outs          : 1
+      insns size    : 98 16-bit code units
+005628:                                        |[005628] com.google.android.checkers.a.a:(Z)I
+005638: 3806 1700                              |0000: if-eqz v6, 0017 // +0017
+00563c: 1200                                   |0002: const/4 v0, #int 0 // #0
+00563e: 5251 3d00                              |0003: iget v1, v5, Lcom/google/android/checkers/a;.d:I // field@003d
+005642: 0114                                   |0005: move v4, v1
+005644: 0101                                   |0006: move v1, v0
+005646: 0140                                   |0007: move v0, v4
+005648: 3900 1600                              |0008: if-nez v0, 001e // +0016
+00564c: 5250 3e00                              |000a: iget v0, v5, Lcom/google/android/checkers/a;.e:I // field@003e
+005650: 3900 2300                              |000c: if-nez v0, 002f // +0023
+005654: 5250 3f00                              |000e: iget v0, v5, Lcom/google/android/checkers/a;.f:I // field@003f
+005658: 3900 3000                              |0010: if-nez v0, 0040 // +0030
+00565c: 5250 4000                              |0012: iget v0, v5, Lcom/google/android/checkers/a;.g:I // field@0040
+005660: 3900 3d00                              |0014: if-nez v0, 0051 // +003d
+005664: 0f01                                   |0016: return v1
+005666: 6200 3900                              |0017: sget-object v0, Lcom/google/android/checkers/a;.M:[I // field@0039
+00566a: 1301 8000                              |0019: const/16 v1, #int 128 // #80
+00566e: 4400 0001                              |001b: aget v0, v0, v1
+005672: 28e6                                   |001d: goto 0003 // -001a
+005674: 6202 3900                              |001e: sget-object v2, Lcom/google/android/checkers/a;.M:[I // field@0039
+005678: 7110 9f00 0000                         |0020: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+00567e: 0a03                                   |0023: move-result v3
+005680: da03 0304                              |0024: mul-int/lit8 v3, v3, #int 4 // #04
+005684: d803 0300                              |0026: add-int/lit8 v3, v3, #int 0 // #00
+005688: 4402 0203                              |0028: aget v2, v2, v3
+00568c: b721                                   |002a: xor-int/2addr v1, v2
+00568e: d802 00ff                              |002b: add-int/lit8 v2, v0, #int -1 // #ff
+005692: b520                                   |002d: and-int/2addr v0, v2
+005694: 28da                                   |002e: goto 0008 // -0026
+005696: 6202 3900                              |002f: sget-object v2, Lcom/google/android/checkers/a;.M:[I // field@0039
+00569a: 7110 9f00 0000                         |0031: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0056a0: 0a03                                   |0034: move-result v3
+0056a2: da03 0304                              |0035: mul-int/lit8 v3, v3, #int 4 // #04
+0056a6: d803 0301                              |0037: add-int/lit8 v3, v3, #int 1 // #01
+0056aa: 4402 0203                              |0039: aget v2, v2, v3
+0056ae: b721                                   |003b: xor-int/2addr v1, v2
+0056b0: d802 00ff                              |003c: add-int/lit8 v2, v0, #int -1 // #ff
+0056b4: b520                                   |003e: and-int/2addr v0, v2
+0056b6: 28cd                                   |003f: goto 000c // -0033
+0056b8: 6202 3900                              |0040: sget-object v2, Lcom/google/android/checkers/a;.M:[I // field@0039
+0056bc: 7110 9f00 0000                         |0042: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0056c2: 0a03                                   |0045: move-result v3
+0056c4: da03 0304                              |0046: mul-int/lit8 v3, v3, #int 4 // #04
+0056c8: d803 0302                              |0048: add-int/lit8 v3, v3, #int 2 // #02
+0056cc: 4402 0203                              |004a: aget v2, v2, v3
+0056d0: b721                                   |004c: xor-int/2addr v1, v2
+0056d2: d802 00ff                              |004d: add-int/lit8 v2, v0, #int -1 // #ff
+0056d6: b520                                   |004f: and-int/2addr v0, v2
+0056d8: 28c0                                   |0050: goto 0010 // -0040
+0056da: 6202 3900                              |0051: sget-object v2, Lcom/google/android/checkers/a;.M:[I // field@0039
+0056de: 7110 9f00 0000                         |0053: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0056e4: 0a03                                   |0056: move-result v3
+0056e6: da03 0304                              |0057: mul-int/lit8 v3, v3, #int 4 // #04
+0056ea: d803 0303                              |0059: add-int/lit8 v3, v3, #int 3 // #03
+0056ee: 4402 0203                              |005b: aget v2, v2, v3
+0056f2: b721                                   |005d: xor-int/2addr v1, v2
+0056f4: d802 00ff                              |005e: add-int/lit8 v2, v0, #int -1 // #ff
+0056f8: b520                                   |0060: and-int/2addr v0, v2
+0056fa: 28b3                                   |0061: goto 0014 // -004d
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #6              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(ZII)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 119
+      code          -
+      registers     : 7
+      ins           : 3
+      outs          : 1
+      insns size    : 56 16-bit code units
+0056fc:                                        |[0056fc] com.google.android.checkers.a.a:(ZII)I
+00570c: 7110 9f00 0500                         |0000: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005712: 0a00                                   |0003: move-result v0
+005714: d801 05ff                              |0004: add-int/lit8 v1, v5, #int -1 // #ff
+005718: b551                                   |0006: and-int/2addr v1, v5
+00571a: 7110 9f00 0100                         |0007: invoke-static {v1}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005720: 0a02                                   |000a: move-result v2
+005722: 7110 9f00 0600                         |000b: invoke-static {v6}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005728: 0a01                                   |000e: move-result v1
+00572a: 1303 1000                              |000f: const/16 v3, #int 16 // #10
+00572e: 3431 0800                              |0011: if-lt v1, v3, 0019 // +0008
+005732: d900 001f                              |0013: rsub-int/lit8 v0, v0, #int 31 // #1f
+005736: d902 021f                              |0015: rsub-int/lit8 v2, v2, #int 31 // #1f
+00573a: d901 011f                              |0017: rsub-int/lit8 v1, v1, #int 31 // #1f
+00573e: 3520 1100                              |0019: if-ge v0, v2, 002a // +0011
+005742: 6203 3800                              |001b: sget-object v3, Lcom/google/android/checkers/a;.L:[I // field@0038
+005746: 4402 0302                              |001d: aget v2, v3, v2
+00574a: b020                                   |001f: add-int/2addr v0, v2
+00574c: 3804 1000                              |0020: if-eqz v4, 0030 // +0010
+005750: 6202 5d00                              |0022: sget-object v2, Lcom/google/android/checkers/g;.e:[B // field@005d
+005754: da00 0010                              |0024: mul-int/lit8 v0, v0, #int 16 // #10
+005758: b010                                   |0026: add-int/2addr v0, v1
+00575a: 4800 0200                              |0027: aget-byte v0, v2, v0
+00575e: 0f00                                   |0029: return v0
+005760: 6203 3800                              |002a: sget-object v3, Lcom/google/android/checkers/a;.L:[I // field@0038
+005764: 4400 0300                              |002c: aget v0, v3, v0
+005768: b020                                   |002e: add-int/2addr v0, v2
+00576a: 28f1                                   |002f: goto 0020 // -000f
+00576c: 6202 5e00                              |0030: sget-object v2, Lcom/google/android/checkers/g;.f:[B // field@005e
+005770: da00 0010                              |0032: mul-int/lit8 v0, v0, #int 16 // #10
+005774: b010                                   |0034: add-int/2addr v0, v1
+005776: 4800 0200                              |0035: aget-byte v0, v2, v0
+00577a: 28f2                                   |0037: goto 0029 // -000e
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #7              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(ZIIIZ)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 120
+      code          -
+      registers     : 9
+      ins           : 5
+      outs          : 1
+      insns size    : 44 16-bit code units
+00577c:                                        |[00577c] com.google.android.checkers.a.a:(ZIIIZ)I
+00578c: 7110 9f00 0500                         |0000: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005792: 0a02                                   |0003: move-result v2
+005794: 7110 9f00 0600                         |0004: invoke-static {v6}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+00579a: 0a01                                   |0007: move-result v1
+00579c: 7110 9f00 0700                         |0008: invoke-static {v7}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0057a2: 0a00                                   |000b: move-result v0
+0057a4: 3808 0800                              |000c: if-eqz v8, 0014 // +0008
+0057a8: d902 021f                              |000e: rsub-int/lit8 v2, v2, #int 31 // #1f
+0057ac: d901 011f                              |0010: rsub-int/lit8 v1, v1, #int 31 // #1f
+0057b0: d900 001f                              |0012: rsub-int/lit8 v0, v0, #int 31 // #1f
+0057b4: 3804 0d00                              |0014: if-eqz v4, 0021 // +000d
+0057b8: 6203 6100                              |0016: sget-object v3, Lcom/google/android/checkers/g;.i:[B // field@0061
+0057bc: d222 0004                              |0018: mul-int/lit16 v2, v2, #int 1024 // #0400
+0057c0: da01 0120                              |001a: mul-int/lit8 v1, v1, #int 32 // #20
+0057c4: b021                                   |001c: add-int/2addr v1, v2
+0057c6: b010                                   |001d: add-int/2addr v0, v1
+0057c8: 4800 0300                              |001e: aget-byte v0, v3, v0
+0057cc: 0f00                                   |0020: return v0
+0057ce: 6203 6200                              |0021: sget-object v3, Lcom/google/android/checkers/g;.j:[B // field@0062
+0057d2: d222 0004                              |0023: mul-int/lit16 v2, v2, #int 1024 // #0400
+0057d6: da01 0120                              |0025: mul-int/lit8 v1, v1, #int 32 // #20
+0057da: b021                                   |0027: add-int/2addr v1, v2
+0057dc: b010                                   |0028: add-int/2addr v0, v1
+0057de: 4800 0300                              |0029: aget-byte v0, v3, v0
+0057e2: 28f5                                   |002b: goto 0020 // -000b
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #8              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(ZIIZ)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 121
+      code          -
+      registers     : 7
+      ins           : 4
+      outs          : 1
+      insns size    : 34 16-bit code units
+0057e4:                                        |[0057e4] com.google.android.checkers.a.a:(ZIIZ)I
+0057f4: 7110 9f00 0400                         |0000: invoke-static {v4}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0057fa: 0a01                                   |0003: move-result v1
+0057fc: 7110 9f00 0500                         |0004: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005802: 0a00                                   |0007: move-result v0
+005804: 3806 0600                              |0008: if-eqz v6, 000e // +0006
+005808: d901 011f                              |000a: rsub-int/lit8 v1, v1, #int 31 // #1f
+00580c: d900 001f                              |000c: rsub-int/lit8 v0, v0, #int 31 // #1f
+005810: d800 00fc                              |000e: add-int/lit8 v0, v0, #int -4 // #fc
+005814: 3803 0a00                              |0010: if-eqz v3, 001a // +000a
+005818: 6202 5a00                              |0012: sget-object v2, Lcom/google/android/checkers/g;.b:[B // field@005a
+00581c: da00 0020                              |0014: mul-int/lit8 v0, v0, #int 32 // #20
+005820: b010                                   |0016: add-int/2addr v0, v1
+005822: 4800 0200                              |0017: aget-byte v0, v2, v0
+005826: 0f00                                   |0019: return v0
+005828: 6202 5b00                              |001a: sget-object v2, Lcom/google/android/checkers/g;.c:[B // field@005b
+00582c: da00 0020                              |001c: mul-int/lit8 v0, v0, #int 32 // #20
+005830: b010                                   |001e: add-int/2addr v0, v1
+005832: 4800 0200                              |001f: aget-byte v0, v2, v0
+005836: 28f8                                   |0021: goto 0019 // -0008
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #9              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(IIII)V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 125
+      code          -
+      registers     : 9
+      ins           : 5
+      outs          : 0
+      insns size    : 76 16-bit code units
+005838:                                        |[005838] com.google.android.checkers.a.a:(IIII)V
+005848: 1301 007d                              |0000: const/16 v1, #int 32000 // #7d00
+00584c: 1302 3f00                              |0002: const/16 v2, #int 63 // #3f
+005850: 1203                                   |0004: const/4 v3, #int 0 // #0
+005852: 1300 0083                              |0005: const/16 v0, #int -32000 // #8300
+005856: 3608 2300                              |0007: if-gt v8, v0, 002a // +0023
+00585a: 2c07 2f00 0000                         |0009: sparse-switch v7, 00000038 // +0000002f
+005860: 0e00                                   |000c: return-void
+005862: 1307 4000                              |000d: const/16 v7, #int 64 // #40
+005866: 0108                                   |000f: move v8, v0
+005868: 0126                                   |0010: move v6, v2
+00586a: 0135                                   |0011: move v5, v3
+00586c: 5240 5100                              |0012: iget v0, v4, Lcom/google/android/checkers/a;.x:I // field@0051
+005870: 1401 ffff 0f00                         |0014: const v1, #float 1.46937e-39 // #000fffff
+005876: b501                                   |0017: and-int/2addr v1, v0
+005878: 5442 5200                              |0018: iget-object v2, v4, Lcom/google/android/checkers/a;.y:[I // field@0052
+00587c: 4b00 0201                              |001a: aput v0, v2, v1
+005880: 5440 5300                              |001c: iget-object v0, v4, Lcom/google/android/checkers/a;.z:[S // field@0053
+005884: 8f82                                   |001e: int-to-short v2, v8
+005886: 5102 0001                              |001f: aput-short v2, v0, v1
+00588a: 5440 2d00                              |0021: iget-object v0, v4, Lcom/google/android/checkers/a;.A:[B // field@002d
+00588e: 9102 0605                              |0023: sub-int v2, v6, v5
+005892: b672                                   |0025: or-int/2addr v2, v7
+005894: 8d22                                   |0026: int-to-byte v2, v2
+005896: 4f02 0001                              |0027: aput-byte v2, v0, v1
+00589a: 28e3                                   |0029: goto 000c // -001d
+00589c: 3418 e8ff                              |002a: if-lt v8, v1, 0012 // -0018
+0058a0: 2c07 1600 0000                         |002c: sparse-switch v7, 00000042 // +00000016
+0058a6: 28dd                                   |002f: goto 000c // -0023
+0058a8: 0118                                   |0030: move v8, v1
+0058aa: 0126                                   |0031: move v6, v2
+0058ac: 0135                                   |0032: move v5, v3
+0058ae: 28df                                   |0033: goto 0012 // -0021
+0058b0: 1307 8000                              |0034: const/16 v7, #int 128 // #80
+0058b4: 28fa                                   |0036: goto 0030 // -0006
+0058b6: 0000                                   |0037: nop // spacer
+0058b8: 0002 0200 4000 0000 c000 0000 0600 ... |0038: sparse-switch-data (10 units)
+0058cc: 0002 0200 8000 0000 c000 0000 0400 ... |0042: sparse-switch-data (10 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #10              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(IIIII)V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 126
+      code          -
+      registers     : 10
+      ins           : 6
+      outs          : 0
+      insns size    : 39 16-bit code units
+0058e0:                                        |[0058e0] com.google.android.checkers.a.a:(IIIII)V
+0058f0: 5240 3c00                              |0000: iget v0, v4, Lcom/google/android/checkers/a;.c:I // field@003c
+0058f4: 1301 4000                              |0002: const/16 v1, #int 64 // #40
+0058f8: 3410 0300                              |0004: if-lt v0, v1, 0007 // +0003
+0058fc: 0e00                                   |0006: return-void
+0058fe: 5240 3c00                              |0007: iget v0, v4, Lcom/google/android/checkers/a;.c:I // field@003c
+005902: d801 0001                              |0009: add-int/lit8 v1, v0, #int 1 // #01
+005906: 5941 3c00                              |000b: iput v1, v4, Lcom/google/android/checkers/a;.c:I // field@003c
+00590a: 5241 4b00                              |000d: iget v1, v4, Lcom/google/android/checkers/a;.r:I // field@004b
+00590e: 5442 4800                              |000f: iget-object v2, v4, Lcom/google/android/checkers/a;.o:[I // field@0048
+005912: 9003 0100                              |0011: add-int v3, v1, v0
+005916: 4b06 0203                              |0013: aput v6, v2, v3
+00591a: 5442 3a00                              |0015: iget-object v2, v4, Lcom/google/android/checkers/a;.a:[I // field@003a
+00591e: 9003 0100                              |0017: add-int v3, v1, v0
+005922: 4b07 0203                              |0019: aput v7, v2, v3
+005926: 5442 4900                              |001b: iget-object v2, v4, Lcom/google/android/checkers/a;.p:[I // field@0049
+00592a: b001                                   |001d: add-int/2addr v1, v0
+00592c: 4b08 0201                              |001e: aput v8, v2, v1
+005930: 3905 e6ff                              |0020: if-nez v5, 0006 // -001a
+005934: 5441 3b00                              |0022: iget-object v1, v4, Lcom/google/android/checkers/a;.b:[I // field@003b
+005938: 4b09 0100                              |0024: aput v9, v1, v0
+00593c: 28e0                                   |0026: goto 0006 // -0020
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #11              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(IIIIIIII)V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 127
+      code          -
+      registers     : 18
+      ins           : 9
+      outs          : 9
+      insns size    : 99 16-bit code units
+005940:                                        |[005940] com.google.android.checkers.a.a:(IIIIIIII)V
+005950: 1210                                   |0000: const/4 v0, #int 1 // #1
+005952: 6201 3000                              |0001: sget-object v1, Lcom/google/android/checkers/a;.D:[I // field@0030
+005956: 4401 010d                              |0003: aget v1, v1, v13
+00595a: b5c1                                   |0005: and-int/2addr v1, v12
+00595c: 3801 2500                              |0006: if-eqz v1, 002b // +0025
+005960: 6201 3100                              |0008: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+005964: 4401 010d                              |000a: aget v1, v1, v13
+005968: b5b1                                   |000c: and-int/2addr v1, v11
+00596a: 3801 1e00                              |000d: if-eqz v1, 002b // +001e
+00596e: d804 0df7                              |000f: add-int/lit8 v4, v13, #int -9 // #f7
+005972: 6200 3100                              |0011: sget-object v0, Lcom/google/android/checkers/a;.E:[I // field@0031
+005976: 4405 000d                              |0013: aget v5, v0, v13
+00597a: 6200 3000                              |0015: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+00597e: 4400 000d                              |0017: aget v0, v0, v13
+005982: 9606 0f00                              |0019: or-int v6, v15, v0
+005986: d807 1001                              |001b: add-int/lit8 v7, v16, #int 1 // #01
+00598a: 6200 3100                              |001d: sget-object v0, Lcom/google/android/checkers/a;.E:[I // field@0031
+00598e: 4400 000d                              |001f: aget v0, v0, v13
+005992: 9608 1100                              |0021: or-int v8, v17, v0
+005996: 0790                                   |0023: move-object v0, v9
+005998: 01a1                                   |0024: move v1, v10
+00599a: 01b2                                   |0025: move v2, v11
+00599c: 01c3                                   |0026: move v3, v12
+00599e: 7609 7f00 0000                         |0027: invoke-direct/range {v0, v1, v2, v3, v4, v5, v6, v7, v8}, Lcom/google/android/checkers/a;.a:(IIIIIIII)V // method@007f
+0059a4: 1200                                   |002a: const/4 v0, #int 0 // #0
+0059a6: 6201 3200                              |002b: sget-object v1, Lcom/google/android/checkers/a;.F:[I // field@0032
+0059aa: 4401 010d                              |002d: aget v1, v1, v13
+0059ae: b5c1                                   |002f: and-int/2addr v1, v12
+0059b0: 3801 2500                              |0030: if-eqz v1, 0055 // +0025
+0059b4: 6201 3300                              |0032: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+0059b8: 4401 010d                              |0034: aget v1, v1, v13
+0059bc: b5b1                                   |0036: and-int/2addr v1, v11
+0059be: 3801 1e00                              |0037: if-eqz v1, 0055 // +001e
+0059c2: d804 0df9                              |0039: add-int/lit8 v4, v13, #int -7 // #f9
+0059c6: 6200 3300                              |003b: sget-object v0, Lcom/google/android/checkers/a;.G:[I // field@0033
+0059ca: 4405 000d                              |003d: aget v5, v0, v13
+0059ce: 6200 3200                              |003f: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+0059d2: 4400 000d                              |0041: aget v0, v0, v13
+0059d6: 9606 0f00                              |0043: or-int v6, v15, v0
+0059da: d807 1001                              |0045: add-int/lit8 v7, v16, #int 1 // #01
+0059de: 6200 3300                              |0047: sget-object v0, Lcom/google/android/checkers/a;.G:[I // field@0033
+0059e2: 4400 000d                              |0049: aget v0, v0, v13
+0059e6: 9608 1100                              |004b: or-int v8, v17, v0
+0059ea: 0790                                   |004d: move-object v0, v9
+0059ec: 01a1                                   |004e: move v1, v10
+0059ee: 01b2                                   |004f: move v2, v11
+0059f0: 01c3                                   |0050: move v3, v12
+0059f2: 7609 7f00 0000                         |0051: invoke-direct/range {v0, v1, v2, v3, v4, v5, v6, v7, v8}, Lcom/google/android/checkers/a;.a:(IIIIIIII)V // method@007f
+0059f8: 1200                                   |0054: const/4 v0, #int 0 // #0
+0059fa: 3800 0d00                              |0055: if-eqz v0, 0062 // +000d
+0059fe: 0790                                   |0057: move-object v0, v9
+005a00: 01a1                                   |0058: move v1, v10
+005a02: 01e2                                   |0059: move v2, v14
+005a04: 01f3                                   |005a: move v3, v15
+005a06: 0204 1000                              |005b: move/from16 v4, v16
+005a0a: 0205 1100                              |005d: move/from16 v5, v17
+005a0e: 7606 7e00 0000                         |005f: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+005a14: 0e00                                   |0062: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #12              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(IZI)Z'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 129
+      code          -
+      registers     : 21
+      ins           : 4
+      outs          : 9
+      insns size    : 875 16-bit code units
+005a18:                                        |[005a18] com.google.android.checkers.a.a:(IZI)Z
+005a28: 3813 b901                              |0000: if-eqz v19, 01b9 // +01b9
+005a2c: 0800 1100                              |0002: move-object/from16 v0, v17
+005a30: 5201 3e00                              |0004: iget v1, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+005a34: 0800 1100                              |0006: move-object/from16 v0, v17
+005a38: 5202 3d00                              |0008: iget v2, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+005a3c: b612                                   |000a: or-int/2addr v2, v1
+005a3e: 0800 1100                              |000b: move-object/from16 v0, v17
+005a42: 5201 4000                              |000d: iget v1, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+005a46: 0800 1100                              |000f: move-object/from16 v0, v17
+005a4a: 5203 3f00                              |0011: iget v3, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+005a4e: 9604 0103                              |0013: or-int v4, v1, v3
+005a52: 1201                                   |0015: const/4 v1, #int 0 // #0
+005a54: e203 1404                              |0016: ushr-int/lit8 v3, v20, #int 4 // #04
+005a58: b543                                   |0018: and-int/2addr v3, v4
+005a5a: 3803 1200                              |0019: if-eqz v3, 002b // +0012
+005a5e: 1401 e0e0 e0e0                         |001b: const v1, #float -1.29634e+20 // #e0e0e0e0
+005a64: b531                                   |001e: and-int/2addr v1, v3
+005a66: e201 0105                              |001f: ushr-int/lit8 v1, v1, #int 5 // #05
+005a6a: 1405 0007 0707                         |0021: const v5, #float 1.01583e-34 // #07070700
+005a70: b553                                   |0024: and-int/2addr v3, v5
+005a72: e203 0303                              |0025: ushr-int/lit8 v3, v3, #int 3 // #03
+005a76: b631                                   |0027: or-int/2addr v1, v3
+005a78: b521                                   |0028: and-int/2addr v1, v2
+005a7a: de01 0100                              |0029: or-int/lit8 v1, v1, #int 0 // #00
+005a7e: 1403 e0e0 e0e0                         |002b: const v3, #float -1.29634e+20 // #e0e0e0e0
+005a84: 9503 0314                              |002e: and-int v3, v3, v20
+005a88: e203 0305                              |0030: ushr-int/lit8 v3, v3, #int 5 // #05
+005a8c: 1405 0007 0707                         |0032: const v5, #float 1.01583e-34 // #07070700
+005a92: 9505 0514                              |0035: and-int v5, v5, v20
+005a96: e205 0503                              |0037: ushr-int/lit8 v5, v5, #int 3 // #03
+005a9a: b653                                   |0039: or-int/2addr v3, v5
+005a9c: b543                                   |003a: and-int/2addr v3, v4
+005a9e: 3803 0600                              |003b: if-eqz v3, 0041 // +0006
+005aa2: e203 0304                              |003d: ushr-int/lit8 v3, v3, #int 4 // #04
+005aa6: b532                                   |003f: and-int/2addr v2, v3
+005aa8: b621                                   |0040: or-int/2addr v1, v2
+005aaa: 0800 1100                              |0041: move-object/from16 v0, v17
+005aae: 5202 3e00                              |0043: iget v2, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+005ab2: 3802 3400                              |0045: if-eqz v2, 0079 // +0034
+005ab6: e002 1404                              |0047: shl-int/lit8 v2, v20, #int 4 // #04
+005aba: b542                                   |0049: and-int/2addr v2, v4
+005abc: 3802 1500                              |004a: if-eqz v2, 005f // +0015
+005ac0: 0800 1100                              |004c: move-object/from16 v0, v17
+005ac4: 5203 3e00                              |004e: iget v3, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+005ac8: 1405 0707 0707                         |0050: const v5, #float 1.01583e-34 // #07070707
+005ace: b525                                   |0053: and-int/2addr v5, v2
+005ad0: e005 0505                              |0054: shl-int/lit8 v5, v5, #int 5 // #05
+005ad4: 1406 e0e0 e000                         |0056: const v6, #float 2.06518e-38 // #00e0e0e0
+005ada: b562                                   |0059: and-int/2addr v2, v6
+005adc: e002 0203                              |005a: shl-int/lit8 v2, v2, #int 3 // #03
+005ae0: b652                                   |005c: or-int/2addr v2, v5
+005ae2: b532                                   |005d: and-int/2addr v2, v3
+005ae4: b621                                   |005e: or-int/2addr v1, v2
+005ae6: 1402 0707 0707                         |005f: const v2, #float 1.01583e-34 // #07070707
+005aec: 9502 0214                              |0062: and-int v2, v2, v20
+005af0: e002 0205                              |0064: shl-int/lit8 v2, v2, #int 5 // #05
+005af4: 1403 e0e0 e000                         |0066: const v3, #float 2.06518e-38 // #00e0e0e0
+005afa: 9503 0314                              |0069: and-int v3, v3, v20
+005afe: e003 0303                              |006b: shl-int/lit8 v3, v3, #int 3 // #03
+005b02: b632                                   |006d: or-int/2addr v2, v3
+005b04: b542                                   |006e: and-int/2addr v2, v4
+005b06: 3802 0a00                              |006f: if-eqz v2, 0079 // +000a
+005b0a: 0800 1100                              |0071: move-object/from16 v0, v17
+005b0e: 5203 3e00                              |0073: iget v3, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+005b12: e002 0204                              |0075: shl-int/lit8 v2, v2, #int 4 // #04
+005b16: b532                                   |0077: and-int/2addr v2, v3
+005b18: b621                                   |0078: or-int/2addr v1, v2
+005b1a: 3901 0a00                              |0079: if-nez v1, 0083 // +000a
+005b1e: 0800 1100                              |007b: move-object/from16 v0, v17
+005b22: 5201 3c00                              |007d: iget v1, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+005b26: 3801 e902                              |007f: if-eqz v1, 0368 // +02e9
+005b2a: 1211                                   |0081: const/4 v1, #int 1 // #1
+005b2c: 0f01                                   |0082: return v1
+005b2e: 7110 9f00 0100                         |0083: invoke-static {v1}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005b34: 0a0f                                   |0086: move-result v15
+005b36: 1212                                   |0087: const/4 v2, #int 1 // #1
+005b38: 9810 020f                              |0088: shl-int v16, v2, v15
+005b3c: 970e 0110                              |008a: xor-int v14, v1, v16
+005b40: 0800 1100                              |008c: move-object/from16 v0, v17
+005b44: 5201 3e00                              |008e: iget v1, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+005b48: 9501 0110                              |0090: and-int v1, v1, v16
+005b4c: 3901 5c00                              |0092: if-nez v1, 00ee // +005c
+005b50: 6201 3400                              |0094: sget-object v1, Lcom/google/android/checkers/a;.H:[I // field@0034
+005b54: 4401 010f                              |0096: aget v1, v1, v15
+005b58: b541                                   |0098: and-int/2addr v1, v4
+005b5a: 3801 2700                              |0099: if-eqz v1, 00c0 // +0027
+005b5e: 6201 3500                              |009b: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+005b62: 4401 010f                              |009d: aget v1, v1, v15
+005b66: 9501 0114                              |009f: and-int v1, v1, v20
+005b6a: 3801 1f00                              |00a1: if-eqz v1, 00c0 // +001f
+005b6e: d805 0f07                              |00a3: add-int/lit8 v5, v15, #int 7 // #07
+005b72: 6201 3500                              |00a5: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+005b76: 4406 010f                              |00a7: aget v6, v1, v15
+005b7a: 6201 3400                              |00a9: sget-object v1, Lcom/google/android/checkers/a;.H:[I // field@0034
+005b7e: 4401 010f                              |00ab: aget v1, v1, v15
+005b82: 9607 1001                              |00ad: or-int v7, v16, v1
+005b86: 1308 0101                              |00af: const/16 v8, #int 257 // #101
+005b8a: 6201 3500                              |00b1: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+005b8e: 4401 010f                              |00b3: aget v1, v1, v15
+005b92: 9609 1001                              |00b5: or-int v9, v16, v1
+005b96: 0801 1100                              |00b7: move-object/from16 v1, v17
+005b9a: 0202 1200                              |00b9: move/from16 v2, v18
+005b9e: 0203 1400                              |00bb: move/from16 v3, v20
+005ba2: 7609 8600 0100                         |00bd: invoke-direct/range {v1, v2, v3, v4, v5, v6, v7, v8, v9}, Lcom/google/android/checkers/a;.b:(IIIIIIII)V // method@0086
+005ba8: 6201 3600                              |00c0: sget-object v1, Lcom/google/android/checkers/a;.J:[I // field@0036
+005bac: 4401 010f                              |00c2: aget v1, v1, v15
+005bb0: b541                                   |00c4: and-int/2addr v1, v4
+005bb2: 3801 f100                              |00c5: if-eqz v1, 01b6 // +00f1
+005bb6: 6201 3700                              |00c7: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+005bba: 4401 010f                              |00c9: aget v1, v1, v15
+005bbe: 9501 0114                              |00cb: and-int v1, v1, v20
+005bc2: 3801 e900                              |00cd: if-eqz v1, 01b6 // +00e9
+005bc6: d805 0f09                              |00cf: add-int/lit8 v5, v15, #int 9 // #09
+005bca: 6201 3700                              |00d1: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+005bce: 4406 010f                              |00d3: aget v6, v1, v15
+005bd2: 6201 3600                              |00d5: sget-object v1, Lcom/google/android/checkers/a;.J:[I // field@0036
+005bd6: 4401 010f                              |00d7: aget v1, v1, v15
+005bda: 9607 1001                              |00d9: or-int v7, v16, v1
+005bde: 1308 0101                              |00db: const/16 v8, #int 257 // #101
+005be2: 6201 3700                              |00dd: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+005be6: 4401 010f                              |00df: aget v1, v1, v15
+005bea: 9609 1001                              |00e1: or-int v9, v16, v1
+005bee: 0801 1100                              |00e3: move-object/from16 v1, v17
+005bf2: 0202 1200                              |00e5: move/from16 v2, v18
+005bf6: 0203 1400                              |00e7: move/from16 v3, v20
+005bfa: 7609 8600 0100                         |00e9: invoke-direct/range {v1, v2, v3, v4, v5, v6, v7, v8, v9}, Lcom/google/android/checkers/a;.b:(IIIIIIII)V // method@0086
+005c00: 01e1                                   |00ec: move v1, v14
+005c02: 288c                                   |00ed: goto 0079 // -0074
+005c04: 6201 3000                              |00ee: sget-object v1, Lcom/google/android/checkers/a;.D:[I // field@0030
+005c08: 4401 010f                              |00f0: aget v1, v1, v15
+005c0c: b541                                   |00f2: and-int/2addr v1, v4
+005c0e: 3801 2d00                              |00f3: if-eqz v1, 0120 // +002d
+005c12: 6201 3100                              |00f5: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+005c16: 4401 010f                              |00f7: aget v1, v1, v15
+005c1a: 9501 0114                              |00f9: and-int v1, v1, v20
+005c1e: 3801 2500                              |00fb: if-eqz v1, 0120 // +0025
+005c22: 9607 1410                              |00fd: or-int v7, v20, v16
+005c26: 6201 3000                              |00ff: sget-object v1, Lcom/google/android/checkers/a;.D:[I // field@0030
+005c2a: 4401 010f                              |0101: aget v1, v1, v15
+005c2e: 9708 0401                              |0103: xor-int v8, v4, v1
+005c32: d809 0ff7                              |0105: add-int/lit8 v9, v15, #int -9 // #f7
+005c36: 6201 3100                              |0107: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+005c3a: 440a 010f                              |0109: aget v10, v1, v15
+005c3e: 6201 3000                              |010b: sget-object v1, Lcom/google/android/checkers/a;.D:[I // field@0030
+005c42: 4401 010f                              |010d: aget v1, v1, v15
+005c46: 960b 1001                              |010f: or-int v11, v16, v1
+005c4a: 130c 0102                              |0111: const/16 v12, #int 513 // #201
+005c4e: 6201 3100                              |0113: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+005c52: 4401 010f                              |0115: aget v1, v1, v15
+005c56: 960d 1001                              |0117: or-int v13, v16, v1
+005c5a: 0805 1100                              |0119: move-object/from16 v5, v17
+005c5e: 0206 1200                              |011b: move/from16 v6, v18
+005c62: 7609 8b00 0500                         |011d: invoke-direct/range {v5, v6, v7, v8, v9, v10, v11, v12, v13}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+005c68: 6201 3200                              |0120: sget-object v1, Lcom/google/android/checkers/a;.F:[I // field@0032
+005c6c: 4401 010f                              |0122: aget v1, v1, v15
+005c70: b541                                   |0124: and-int/2addr v1, v4
+005c72: 3801 2d00                              |0125: if-eqz v1, 0152 // +002d
+005c76: 6201 3300                              |0127: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+005c7a: 4401 010f                              |0129: aget v1, v1, v15
+005c7e: 9501 0114                              |012b: and-int v1, v1, v20
+005c82: 3801 2500                              |012d: if-eqz v1, 0152 // +0025
+005c86: 9607 1410                              |012f: or-int v7, v20, v16
+005c8a: 6201 3200                              |0131: sget-object v1, Lcom/google/android/checkers/a;.F:[I // field@0032
+005c8e: 4401 010f                              |0133: aget v1, v1, v15
+005c92: 9708 0401                              |0135: xor-int v8, v4, v1
+005c96: d809 0ff9                              |0137: add-int/lit8 v9, v15, #int -7 // #f9
+005c9a: 6201 3300                              |0139: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+005c9e: 440a 010f                              |013b: aget v10, v1, v15
+005ca2: 6201 3200                              |013d: sget-object v1, Lcom/google/android/checkers/a;.F:[I // field@0032
+005ca6: 4401 010f                              |013f: aget v1, v1, v15
+005caa: 960b 1001                              |0141: or-int v11, v16, v1
+005cae: 130c 0102                              |0143: const/16 v12, #int 513 // #201
+005cb2: 6201 3300                              |0145: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+005cb6: 4401 010f                              |0147: aget v1, v1, v15
+005cba: 960d 1001                              |0149: or-int v13, v16, v1
+005cbe: 0805 1100                              |014b: move-object/from16 v5, v17
+005cc2: 0206 1200                              |014d: move/from16 v6, v18
+005cc6: 7609 8b00 0500                         |014f: invoke-direct/range {v5, v6, v7, v8, v9, v10, v11, v12, v13}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+005ccc: 6201 3400                              |0152: sget-object v1, Lcom/google/android/checkers/a;.H:[I // field@0034
+005cd0: 4401 010f                              |0154: aget v1, v1, v15
+005cd4: b541                                   |0156: and-int/2addr v1, v4
+005cd6: 3801 2d00                              |0157: if-eqz v1, 0184 // +002d
+005cda: 6201 3500                              |0159: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+005cde: 4401 010f                              |015b: aget v1, v1, v15
+005ce2: 9501 0114                              |015d: and-int v1, v1, v20
+005ce6: 3801 2500                              |015f: if-eqz v1, 0184 // +0025
+005cea: 9607 1410                              |0161: or-int v7, v20, v16
+005cee: 6201 3400                              |0163: sget-object v1, Lcom/google/android/checkers/a;.H:[I // field@0034
+005cf2: 4401 010f                              |0165: aget v1, v1, v15
+005cf6: 9708 0401                              |0167: xor-int v8, v4, v1
+005cfa: d809 0f07                              |0169: add-int/lit8 v9, v15, #int 7 // #07
+005cfe: 6201 3500                              |016b: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+005d02: 440a 010f                              |016d: aget v10, v1, v15
+005d06: 6201 3400                              |016f: sget-object v1, Lcom/google/android/checkers/a;.H:[I // field@0034
+005d0a: 4401 010f                              |0171: aget v1, v1, v15
+005d0e: 960b 1001                              |0173: or-int v11, v16, v1
+005d12: 130c 0102                              |0175: const/16 v12, #int 513 // #201
+005d16: 6201 3500                              |0177: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+005d1a: 4401 010f                              |0179: aget v1, v1, v15
+005d1e: 960d 1001                              |017b: or-int v13, v16, v1
+005d22: 0805 1100                              |017d: move-object/from16 v5, v17
+005d26: 0206 1200                              |017f: move/from16 v6, v18
+005d2a: 7609 8b00 0500                         |0181: invoke-direct/range {v5, v6, v7, v8, v9, v10, v11, v12, v13}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+005d30: 6201 3600                              |0184: sget-object v1, Lcom/google/android/checkers/a;.J:[I // field@0036
+005d34: 4401 010f                              |0186: aget v1, v1, v15
+005d38: b541                                   |0188: and-int/2addr v1, v4
+005d3a: 3801 2d00                              |0189: if-eqz v1, 01b6 // +002d
+005d3e: 6201 3700                              |018b: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+005d42: 4401 010f                              |018d: aget v1, v1, v15
+005d46: 9501 0114                              |018f: and-int v1, v1, v20
+005d4a: 3801 2500                              |0191: if-eqz v1, 01b6 // +0025
+005d4e: 9607 1410                              |0193: or-int v7, v20, v16
+005d52: 6201 3600                              |0195: sget-object v1, Lcom/google/android/checkers/a;.J:[I // field@0036
+005d56: 4401 010f                              |0197: aget v1, v1, v15
+005d5a: 9708 0401                              |0199: xor-int v8, v4, v1
+005d5e: d809 0f09                              |019b: add-int/lit8 v9, v15, #int 9 // #09
+005d62: 6201 3700                              |019d: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+005d66: 440a 010f                              |019f: aget v10, v1, v15
+005d6a: 6201 3600                              |01a1: sget-object v1, Lcom/google/android/checkers/a;.J:[I // field@0036
+005d6e: 4401 010f                              |01a3: aget v1, v1, v15
+005d72: 960b 1001                              |01a5: or-int v11, v16, v1
+005d76: 130c 0102                              |01a7: const/16 v12, #int 513 // #201
+005d7a: 6201 3700                              |01a9: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+005d7e: 4401 010f                              |01ab: aget v1, v1, v15
+005d82: 960d 1001                              |01ad: or-int v13, v16, v1
+005d86: 0805 1100                              |01af: move-object/from16 v5, v17
+005d8a: 0206 1200                              |01b1: move/from16 v6, v18
+005d8e: 7609 8b00 0500                         |01b3: invoke-direct/range {v5, v6, v7, v8, v9, v10, v11, v12, v13}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+005d94: 01e1                                   |01b6: move v1, v14
+005d96: 2900 c2fe                              |01b7: goto/16 0079 // -013e
+005d9a: 0800 1100                              |01b9: move-object/from16 v0, v17
+005d9e: 5201 4000                              |01bb: iget v1, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+005da2: 0800 1100                              |01bd: move-object/from16 v0, v17
+005da6: 5202 3f00                              |01bf: iget v2, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+005daa: b612                                   |01c1: or-int/2addr v2, v1
+005dac: 0800 1100                              |01c2: move-object/from16 v0, v17
+005db0: 5201 3e00                              |01c4: iget v1, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+005db4: 0800 1100                              |01c6: move-object/from16 v0, v17
+005db8: 5203 3d00                              |01c8: iget v3, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+005dbc: 9604 0103                              |01ca: or-int v4, v1, v3
+005dc0: 1201                                   |01cc: const/4 v1, #int 0 // #0
+005dc2: 0800 1100                              |01cd: move-object/from16 v0, v17
+005dc6: 5203 4000                              |01cf: iget v3, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+005dca: 3803 3500                              |01d1: if-eqz v3, 0206 // +0035
+005dce: e203 1404                              |01d3: ushr-int/lit8 v3, v20, #int 4 // #04
+005dd2: b543                                   |01d5: and-int/2addr v3, v4
+005dd4: 3803 1600                              |01d6: if-eqz v3, 01ec // +0016
+005dd8: 0800 1100                              |01d8: move-object/from16 v0, v17
+005ddc: 5201 4000                              |01da: iget v1, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+005de0: 1405 e0e0 e0e0                         |01dc: const v5, #float -1.29634e+20 // #e0e0e0e0
+005de6: b535                                   |01df: and-int/2addr v5, v3
+005de8: e205 0505                              |01e0: ushr-int/lit8 v5, v5, #int 5 // #05
+005dec: 1406 0007 0707                         |01e2: const v6, #float 1.01583e-34 // #07070700
+005df2: b563                                   |01e5: and-int/2addr v3, v6
+005df4: e203 0303                              |01e6: ushr-int/lit8 v3, v3, #int 3 // #03
+005df8: b653                                   |01e8: or-int/2addr v3, v5
+005dfa: b531                                   |01e9: and-int/2addr v1, v3
+005dfc: de01 0100                              |01ea: or-int/lit8 v1, v1, #int 0 // #00
+005e00: 1403 e0e0 e0e0                         |01ec: const v3, #float -1.29634e+20 // #e0e0e0e0
+005e06: 9503 0314                              |01ef: and-int v3, v3, v20
+005e0a: e203 0305                              |01f1: ushr-int/lit8 v3, v3, #int 5 // #05
+005e0e: 1405 0007 0707                         |01f3: const v5, #float 1.01583e-34 // #07070700
+005e14: 9505 0514                              |01f6: and-int v5, v5, v20
+005e18: e205 0503                              |01f8: ushr-int/lit8 v5, v5, #int 3 // #03
+005e1c: b653                                   |01fa: or-int/2addr v3, v5
+005e1e: b543                                   |01fb: and-int/2addr v3, v4
+005e20: 3803 0a00                              |01fc: if-eqz v3, 0206 // +000a
+005e24: 0800 1100                              |01fe: move-object/from16 v0, v17
+005e28: 5205 4000                              |0200: iget v5, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+005e2c: e203 0304                              |0202: ushr-int/lit8 v3, v3, #int 4 // #04
+005e30: b553                                   |0204: and-int/2addr v3, v5
+005e32: b631                                   |0205: or-int/2addr v1, v3
+005e34: e003 1404                              |0206: shl-int/lit8 v3, v20, #int 4 // #04
+005e38: b543                                   |0208: and-int/2addr v3, v4
+005e3a: 3803 1100                              |0209: if-eqz v3, 021a // +0011
+005e3e: 1405 0707 0707                         |020b: const v5, #float 1.01583e-34 // #07070707
+005e44: b535                                   |020e: and-int/2addr v5, v3
+005e46: e005 0505                              |020f: shl-int/lit8 v5, v5, #int 5 // #05
+005e4a: 1406 e0e0 e000                         |0211: const v6, #float 2.06518e-38 // #00e0e0e0
+005e50: b563                                   |0214: and-int/2addr v3, v6
+005e52: e003 0303                              |0215: shl-int/lit8 v3, v3, #int 3 // #03
+005e56: b653                                   |0217: or-int/2addr v3, v5
+005e58: b523                                   |0218: and-int/2addr v3, v2
+005e5a: b631                                   |0219: or-int/2addr v1, v3
+005e5c: 1403 0707 0707                         |021a: const v3, #float 1.01583e-34 // #07070707
+005e62: 9503 0314                              |021d: and-int v3, v3, v20
+005e66: e003 0305                              |021f: shl-int/lit8 v3, v3, #int 5 // #05
+005e6a: 1405 e0e0 e000                         |0221: const v5, #float 2.06518e-38 // #00e0e0e0
+005e70: 9505 0514                              |0224: and-int v5, v5, v20
+005e74: e005 0503                              |0226: shl-int/lit8 v5, v5, #int 3 // #03
+005e78: b653                                   |0228: or-int/2addr v3, v5
+005e7a: b543                                   |0229: and-int/2addr v3, v4
+005e7c: 3803 0600                              |022a: if-eqz v3, 0230 // +0006
+005e80: e003 0304                              |022c: shl-int/lit8 v3, v3, #int 4 // #04
+005e84: b532                                   |022e: and-int/2addr v2, v3
+005e86: b621                                   |022f: or-int/2addr v1, v2
+005e88: 3801 4bfe                              |0230: if-eqz v1, 007b // -01b5
+005e8c: 7110 9f00 0100                         |0232: invoke-static {v1}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+005e92: 0a0f                                   |0235: move-result v15
+005e94: 1212                                   |0236: const/4 v2, #int 1 // #1
+005e96: 9810 020f                              |0237: shl-int v16, v2, v15
+005e9a: 970e 0110                              |0239: xor-int v14, v1, v16
+005e9e: 0800 1100                              |023b: move-object/from16 v0, v17
+005ea2: 5201 4000                              |023d: iget v1, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+005ea6: 9501 0110                              |023f: and-int v1, v1, v16
+005eaa: 3901 5c00                              |0241: if-nez v1, 029d // +005c
+005eae: 6201 3000                              |0243: sget-object v1, Lcom/google/android/checkers/a;.D:[I // field@0030
+005eb2: 4401 010f                              |0245: aget v1, v1, v15
+005eb6: b541                                   |0247: and-int/2addr v1, v4
+005eb8: 3801 2700                              |0248: if-eqz v1, 026f // +0027
+005ebc: 6201 3100                              |024a: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+005ec0: 4401 010f                              |024c: aget v1, v1, v15
+005ec4: 9501 0114                              |024e: and-int v1, v1, v20
+005ec8: 3801 1f00                              |0250: if-eqz v1, 026f // +001f
+005ecc: d805 0ff7                              |0252: add-int/lit8 v5, v15, #int -9 // #f7
+005ed0: 6201 3100                              |0254: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+005ed4: 4406 010f                              |0256: aget v6, v1, v15
+005ed8: 6201 3000                              |0258: sget-object v1, Lcom/google/android/checkers/a;.D:[I // field@0030
+005edc: 4401 010f                              |025a: aget v1, v1, v15
+005ee0: 9607 1001                              |025c: or-int v7, v16, v1
+005ee4: 1308 0104                              |025e: const/16 v8, #int 1025 // #401
+005ee8: 6201 3100                              |0260: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+005eec: 4401 010f                              |0262: aget v1, v1, v15
+005ef0: 9609 1001                              |0264: or-int v9, v16, v1
+005ef4: 0801 1100                              |0266: move-object/from16 v1, v17
+005ef8: 0202 1200                              |0268: move/from16 v2, v18
+005efc: 0203 1400                              |026a: move/from16 v3, v20
+005f00: 7609 7f00 0100                         |026c: invoke-direct/range {v1, v2, v3, v4, v5, v6, v7, v8, v9}, Lcom/google/android/checkers/a;.a:(IIIIIIII)V // method@007f
+005f06: 6201 3200                              |026f: sget-object v1, Lcom/google/android/checkers/a;.F:[I // field@0032
+005f0a: 4401 010f                              |0271: aget v1, v1, v15
+005f0e: b541                                   |0273: and-int/2addr v1, v4
+005f10: 3801 f100                              |0274: if-eqz v1, 0365 // +00f1
+005f14: 6201 3300                              |0276: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+005f18: 4401 010f                              |0278: aget v1, v1, v15
+005f1c: 9501 0114                              |027a: and-int v1, v1, v20
+005f20: 3801 e900                              |027c: if-eqz v1, 0365 // +00e9
+005f24: d805 0ff9                              |027e: add-int/lit8 v5, v15, #int -7 // #f9
+005f28: 6201 3300                              |0280: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+005f2c: 4406 010f                              |0282: aget v6, v1, v15
+005f30: 6201 3200                              |0284: sget-object v1, Lcom/google/android/checkers/a;.F:[I // field@0032
+005f34: 4401 010f                              |0286: aget v1, v1, v15
+005f38: 9607 1001                              |0288: or-int v7, v16, v1
+005f3c: 1308 0104                              |028a: const/16 v8, #int 1025 // #401
+005f40: 6201 3300                              |028c: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+005f44: 4401 010f                              |028e: aget v1, v1, v15
+005f48: 9609 1001                              |0290: or-int v9, v16, v1
+005f4c: 0801 1100                              |0292: move-object/from16 v1, v17
+005f50: 0202 1200                              |0294: move/from16 v2, v18
+005f54: 0203 1400                              |0296: move/from16 v3, v20
+005f58: 7609 7f00 0100                         |0298: invoke-direct/range {v1, v2, v3, v4, v5, v6, v7, v8, v9}, Lcom/google/android/checkers/a;.a:(IIIIIIII)V // method@007f
+005f5e: 01e1                                   |029b: move v1, v14
+005f60: 2894                                   |029c: goto 0230 // -006c
+005f62: 6201 3000                              |029d: sget-object v1, Lcom/google/android/checkers/a;.D:[I // field@0030
+005f66: 4401 010f                              |029f: aget v1, v1, v15
+005f6a: b541                                   |02a1: and-int/2addr v1, v4
+005f6c: 3801 2d00                              |02a2: if-eqz v1, 02cf // +002d
+005f70: 6201 3100                              |02a4: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+005f74: 4401 010f                              |02a6: aget v1, v1, v15
+005f78: 9501 0114                              |02a8: and-int v1, v1, v20
+005f7c: 3801 2500                              |02aa: if-eqz v1, 02cf // +0025
+005f80: 9607 1410                              |02ac: or-int v7, v20, v16
+005f84: 6201 3000                              |02ae: sget-object v1, Lcom/google/android/checkers/a;.D:[I // field@0030
+005f88: 4401 010f                              |02b0: aget v1, v1, v15
+005f8c: 9708 0401                              |02b2: xor-int v8, v4, v1
+005f90: d809 0ff7                              |02b4: add-int/lit8 v9, v15, #int -9 // #f7
+005f94: 6201 3100                              |02b6: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+005f98: 440a 010f                              |02b8: aget v10, v1, v15
+005f9c: 6201 3000                              |02ba: sget-object v1, Lcom/google/android/checkers/a;.D:[I // field@0030
+005fa0: 4401 010f                              |02bc: aget v1, v1, v15
+005fa4: 960b 1001                              |02be: or-int v11, v16, v1
+005fa8: 130c 0108                              |02c0: const/16 v12, #int 2049 // #801
+005fac: 6201 3100                              |02c2: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+005fb0: 4401 010f                              |02c4: aget v1, v1, v15
+005fb4: 960d 1001                              |02c6: or-int v13, v16, v1
+005fb8: 0805 1100                              |02c8: move-object/from16 v5, v17
+005fbc: 0206 1200                              |02ca: move/from16 v6, v18
+005fc0: 7609 8b00 0500                         |02cc: invoke-direct/range {v5, v6, v7, v8, v9, v10, v11, v12, v13}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+005fc6: 6201 3200                              |02cf: sget-object v1, Lcom/google/android/checkers/a;.F:[I // field@0032
+005fca: 4401 010f                              |02d1: aget v1, v1, v15
+005fce: b541                                   |02d3: and-int/2addr v1, v4
+005fd0: 3801 2d00                              |02d4: if-eqz v1, 0301 // +002d
+005fd4: 6201 3300                              |02d6: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+005fd8: 4401 010f                              |02d8: aget v1, v1, v15
+005fdc: 9501 0114                              |02da: and-int v1, v1, v20
+005fe0: 3801 2500                              |02dc: if-eqz v1, 0301 // +0025
+005fe4: 9607 1410                              |02de: or-int v7, v20, v16
+005fe8: 6201 3200                              |02e0: sget-object v1, Lcom/google/android/checkers/a;.F:[I // field@0032
+005fec: 4401 010f                              |02e2: aget v1, v1, v15
+005ff0: 9708 0401                              |02e4: xor-int v8, v4, v1
+005ff4: d809 0ff9                              |02e6: add-int/lit8 v9, v15, #int -7 // #f9
+005ff8: 6201 3300                              |02e8: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+005ffc: 440a 010f                              |02ea: aget v10, v1, v15
+006000: 6201 3200                              |02ec: sget-object v1, Lcom/google/android/checkers/a;.F:[I // field@0032
+006004: 4401 010f                              |02ee: aget v1, v1, v15
+006008: 960b 1001                              |02f0: or-int v11, v16, v1
+00600c: 130c 0108                              |02f2: const/16 v12, #int 2049 // #801
+006010: 6201 3300                              |02f4: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+006014: 4401 010f                              |02f6: aget v1, v1, v15
+006018: 960d 1001                              |02f8: or-int v13, v16, v1
+00601c: 0805 1100                              |02fa: move-object/from16 v5, v17
+006020: 0206 1200                              |02fc: move/from16 v6, v18
+006024: 7609 8b00 0500                         |02fe: invoke-direct/range {v5, v6, v7, v8, v9, v10, v11, v12, v13}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+00602a: 6201 3400                              |0301: sget-object v1, Lcom/google/android/checkers/a;.H:[I // field@0034
+00602e: 4401 010f                              |0303: aget v1, v1, v15
+006032: b541                                   |0305: and-int/2addr v1, v4
+006034: 3801 2d00                              |0306: if-eqz v1, 0333 // +002d
+006038: 6201 3500                              |0308: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+00603c: 4401 010f                              |030a: aget v1, v1, v15
+006040: 9501 0114                              |030c: and-int v1, v1, v20
+006044: 3801 2500                              |030e: if-eqz v1, 0333 // +0025
+006048: 9607 1410                              |0310: or-int v7, v20, v16
+00604c: 6201 3400                              |0312: sget-object v1, Lcom/google/android/checkers/a;.H:[I // field@0034
+006050: 4401 010f                              |0314: aget v1, v1, v15
+006054: 9708 0401                              |0316: xor-int v8, v4, v1
+006058: d809 0f07                              |0318: add-int/lit8 v9, v15, #int 7 // #07
+00605c: 6201 3500                              |031a: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+006060: 440a 010f                              |031c: aget v10, v1, v15
+006064: 6201 3400                              |031e: sget-object v1, Lcom/google/android/checkers/a;.H:[I // field@0034
+006068: 4401 010f                              |0320: aget v1, v1, v15
+00606c: 960b 1001                              |0322: or-int v11, v16, v1
+006070: 130c 0108                              |0324: const/16 v12, #int 2049 // #801
+006074: 6201 3500                              |0326: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+006078: 4401 010f                              |0328: aget v1, v1, v15
+00607c: 960d 1001                              |032a: or-int v13, v16, v1
+006080: 0805 1100                              |032c: move-object/from16 v5, v17
+006084: 0206 1200                              |032e: move/from16 v6, v18
+006088: 7609 8b00 0500                         |0330: invoke-direct/range {v5, v6, v7, v8, v9, v10, v11, v12, v13}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+00608e: 6201 3600                              |0333: sget-object v1, Lcom/google/android/checkers/a;.J:[I // field@0036
+006092: 4401 010f                              |0335: aget v1, v1, v15
+006096: b541                                   |0337: and-int/2addr v1, v4
+006098: 3801 2d00                              |0338: if-eqz v1, 0365 // +002d
+00609c: 6201 3700                              |033a: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+0060a0: 4401 010f                              |033c: aget v1, v1, v15
+0060a4: 9501 0114                              |033e: and-int v1, v1, v20
+0060a8: 3801 2500                              |0340: if-eqz v1, 0365 // +0025
+0060ac: 9607 1410                              |0342: or-int v7, v20, v16
+0060b0: 6201 3600                              |0344: sget-object v1, Lcom/google/android/checkers/a;.J:[I // field@0036
+0060b4: 4401 010f                              |0346: aget v1, v1, v15
+0060b8: 9708 0401                              |0348: xor-int v8, v4, v1
+0060bc: d809 0f09                              |034a: add-int/lit8 v9, v15, #int 9 // #09
+0060c0: 6201 3700                              |034c: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+0060c4: 440a 010f                              |034e: aget v10, v1, v15
+0060c8: 6201 3600                              |0350: sget-object v1, Lcom/google/android/checkers/a;.J:[I // field@0036
+0060cc: 4401 010f                              |0352: aget v1, v1, v15
+0060d0: 960b 1001                              |0354: or-int v11, v16, v1
+0060d4: 130c 0108                              |0356: const/16 v12, #int 2049 // #801
+0060d8: 6201 3700                              |0358: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+0060dc: 4401 010f                              |035a: aget v1, v1, v15
+0060e0: 960d 1001                              |035c: or-int v13, v16, v1
+0060e4: 0805 1100                              |035e: move-object/from16 v5, v17
+0060e8: 0206 1200                              |0360: move/from16 v6, v18
+0060ec: 7609 8b00 0500                         |0362: invoke-direct/range {v5, v6, v7, v8, v9, v10, v11, v12, v13}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+0060f2: 01e1                                   |0365: move v1, v14
+0060f4: 2900 cafe                              |0366: goto/16 0230 // -0136
+0060f8: 1201                                   |0368: const/4 v1, #int 0 // #0
+0060fa: 2900 19fd                              |0369: goto/16 0082 // -02e7
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #13              : (in Lcom/google/android/checkers/a;)
+      name          : 'b'
+      type          : '(ZIIIZ)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 130
+      code          -
+      registers     : 9
+      ins           : 5
+      outs          : 1
+      insns size    : 46 16-bit code units
+006100:                                        |[006100] com.google.android.checkers.a.b:(ZIIIZ)I
+006110: 7110 9f00 0500                         |0000: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+006116: 0a02                                   |0003: move-result v2
+006118: 7110 9f00 0600                         |0004: invoke-static {v6}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+00611e: 0a01                                   |0007: move-result v1
+006120: 7110 9f00 0700                         |0008: invoke-static {v7}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+006126: 0a00                                   |000b: move-result v0
+006128: 3808 0800                              |000c: if-eqz v8, 0014 // +0008
+00612c: d902 021f                              |000e: rsub-int/lit8 v2, v2, #int 31 // #1f
+006130: d901 011f                              |0010: rsub-int/lit8 v1, v1, #int 31 // #1f
+006134: d900 001f                              |0012: rsub-int/lit8 v0, v0, #int 31 // #1f
+006138: d800 00fc                              |0014: add-int/lit8 v0, v0, #int -4 // #fc
+00613c: 3804 0d00                              |0016: if-eqz v4, 0023 // +000d
+006140: 6203 6300                              |0018: sget-object v3, Lcom/google/android/checkers/g;.k:[B // field@0063
+006144: d200 8003                              |001a: mul-int/lit16 v0, v0, #int 896 // #0380
+006148: da02 0220                              |001c: mul-int/lit8 v2, v2, #int 32 // #20
+00614c: b020                                   |001e: add-int/2addr v0, v2
+00614e: b010                                   |001f: add-int/2addr v0, v1
+006150: 4800 0300                              |0020: aget-byte v0, v3, v0
+006154: 0f00                                   |0022: return v0
+006156: 6203 6400                              |0023: sget-object v3, Lcom/google/android/checkers/g;.l:[B // field@0064
+00615a: d200 8003                              |0025: mul-int/lit16 v0, v0, #int 896 // #0380
+00615e: da02 0220                              |0027: mul-int/lit8 v2, v2, #int 32 // #20
+006162: b020                                   |0029: add-int/2addr v0, v2
+006164: b010                                   |002a: add-int/2addr v0, v1
+006166: 4800 0300                              |002b: aget-byte v0, v3, v0
+00616a: 28f5                                   |002d: goto 0022 // -000b
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #14              : (in Lcom/google/android/checkers/a;)
+      name          : 'b'
+      type          : '(ZIIZ)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 131
+      code          -
+      registers     : 8
+      ins           : 4
+      outs          : 1
+      insns size    : 56 16-bit code units
+00616c:                                        |[00616c] com.google.android.checkers.a.b:(ZIIZ)I
+00617c: 7110 9f00 0500                         |0000: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+006182: 0a00                                   |0003: move-result v0
+006184: d801 05ff                              |0004: add-int/lit8 v1, v5, #int -1 // #ff
+006188: b551                                   |0006: and-int/2addr v1, v5
+00618a: 7110 9f00 0100                         |0007: invoke-static {v1}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+006190: 0a02                                   |000a: move-result v2
+006192: 7110 9f00 0600                         |000b: invoke-static {v6}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+006198: 0a01                                   |000e: move-result v1
+00619a: 3807 0800                              |000f: if-eqz v7, 0017 // +0008
+00619e: d900 001f                              |0011: rsub-int/lit8 v0, v0, #int 31 // #1f
+0061a2: d902 021f                              |0013: rsub-int/lit8 v2, v2, #int 31 // #1f
+0061a6: d901 011f                              |0015: rsub-int/lit8 v1, v1, #int 31 // #1f
+0061aa: d801 01fc                              |0017: add-int/lit8 v1, v1, #int -4 // #fc
+0061ae: 3520 1100                              |0019: if-ge v0, v2, 002a // +0011
+0061b2: 6203 3800                              |001b: sget-object v3, Lcom/google/android/checkers/a;.L:[I // field@0038
+0061b6: 4402 0302                              |001d: aget v2, v3, v2
+0061ba: b020                                   |001f: add-int/2addr v0, v2
+0061bc: 3804 1000                              |0020: if-eqz v4, 0030 // +0010
+0061c0: 6202 5f00                              |0022: sget-object v2, Lcom/google/android/checkers/g;.g:[B // field@005f
+0061c4: d211 f001                              |0024: mul-int/lit16 v1, v1, #int 496 // #01f0
+0061c8: b010                                   |0026: add-int/2addr v0, v1
+0061ca: 4800 0200                              |0027: aget-byte v0, v2, v0
+0061ce: 0f00                                   |0029: return v0
+0061d0: 6203 3800                              |002a: sget-object v3, Lcom/google/android/checkers/a;.L:[I // field@0038
+0061d4: 4400 0300                              |002c: aget v0, v3, v0
+0061d8: b020                                   |002e: add-int/2addr v0, v2
+0061da: 28f1                                   |002f: goto 0020 // -000f
+0061dc: 6202 6000                              |0030: sget-object v2, Lcom/google/android/checkers/g;.h:[B // field@0060
+0061e0: d211 f001                              |0032: mul-int/lit16 v1, v1, #int 496 // #01f0
+0061e4: b010                                   |0034: add-int/2addr v0, v1
+0061e6: 4800 0200                              |0035: aget-byte v0, v2, v0
+0061ea: 28f2                                   |0037: goto 0029 // -000e
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #15              : (in Lcom/google/android/checkers/a;)
+      name          : 'b'
+      type          : '()V'
+      access        : 0x20012 (PRIVATE FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 132
+      code          -
+      registers     : 2
+      ins           : 1
+      outs          : 1
+      insns size    : 19 16-bit code units
+0061ec:                                        |[0061ec] com.google.android.checkers.a.b:()V
+0061fc: 1d01                                   |0000: monitor-enter v1
+0061fe: 5510 4400                              |0001: iget-boolean v0, v1, Lcom/google/android/checkers/a;.k:Z // field@0044
+006202: 3800 0700                              |0003: if-eqz v0, 000a // +0007
+006206: 1200                                   |0005: const/4 v0, #int 0 // #0
+006208: 5c10 4400                              |0006: iput-boolean v0, v1, Lcom/google/android/checkers/a;.k:Z // field@0044
+00620c: 1e01                                   |0008: monitor-exit v1
+00620e: 0e00                                   |0009: return-void
+006210: 6e10 a200 0100                         |000a: invoke-virtual {v1}, Ljava/lang/Object;.wait:()V // method@00a2
+006216: 28f4                                   |000d: goto 0001 // -000c
+006218: 0d00                                   |000e: move-exception v0
+00621a: 28f2                                   |000f: goto 0001 // -000e
+00621c: 0d00                                   |0010: move-exception v0
+00621e: 1e01                                   |0011: monitor-exit v1
+006220: 2700                                   |0012: throw v0
+      catches       : 2
+        0x0001 - 0x0008
+          <any> -> 0x0010
+        0x000a - 0x000d
+          Ljava/lang/InterruptedException; -> 0x000e
+          <any> -> 0x0010
+      positions     : 
+      locals        : 
+
+    #16              : (in Lcom/google/android/checkers/a;)
+      name          : 'b'
+      type          : '(I)V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 133
+      code          -
+      registers     : 10
+      ins           : 2
+      outs          : 1
+      insns size    : 368 16-bit code units
+00623c:                                        |[00623c] com.google.android.checkers.a.b:(I)V
+00624c: 5280 3d00                              |0000: iget v0, v8, Lcom/google/android/checkers/a;.d:I // field@003d
+006250: 5282 3e00                              |0002: iget v2, v8, Lcom/google/android/checkers/a;.e:I // field@003e
+006254: 5283 3f00                              |0004: iget v3, v8, Lcom/google/android/checkers/a;.f:I // field@003f
+006258: 5284 4000                              |0006: iget v4, v8, Lcom/google/android/checkers/a;.g:I // field@0040
+00625c: 5481 4900                              |0008: iget-object v1, v8, Lcom/google/android/checkers/a;.p:[I // field@0049
+006260: 4401 0109                              |000a: aget v1, v1, v9
+006264: d511 ff00                              |000c: and-int/lit16 v1, v1, #int 255 // #00ff
+006268: 5485 4900                              |000e: iget-object v5, v8, Lcom/google/android/checkers/a;.p:[I // field@0049
+00626c: 4405 0509                              |0010: aget v5, v5, v9
+006270: d555 000f                              |0012: and-int/lit16 v5, v5, #int 3840 // #0f00
+006274: 5486 4800                              |0014: iget-object v6, v8, Lcom/google/android/checkers/a;.o:[I // field@0048
+006278: 4406 0609                              |0016: aget v6, v6, v9
+00627c: 2c05 4601 0000                         |0018: sparse-switch v5, 0000015e // +00000146
+006282: 5281 5100                              |001b: iget v1, v8, Lcom/google/android/checkers/a;.x:I // field@0051
+006286: 6205 3900                              |001d: sget-object v5, Lcom/google/android/checkers/a;.M:[I // field@0039
+00628a: 1306 8000                              |001f: const/16 v6, #int 128 // #80
+00628e: 4405 0506                              |0021: aget v5, v5, v6
+006292: b751                                   |0023: xor-int/2addr v1, v5
+006294: 5285 3d00                              |0024: iget v5, v8, Lcom/google/android/checkers/a;.d:I // field@003d
+006298: b750                                   |0026: xor-int/2addr v0, v5
+00629a: 3900 ee00                              |0027: if-nez v0, 0115 // +00ee
+00629e: 5280 3e00                              |0029: iget v0, v8, Lcom/google/android/checkers/a;.e:I // field@003e
+0062a2: b720                                   |002b: xor-int/2addr v0, v2
+0062a4: 3900 fb00                              |002c: if-nez v0, 0127 // +00fb
+0062a8: 5280 3f00                              |002e: iget v0, v8, Lcom/google/android/checkers/a;.f:I // field@003f
+0062ac: b730                                   |0030: xor-int/2addr v0, v3
+0062ae: 3900 0801                              |0031: if-nez v0, 0139 // +0108
+0062b2: 5280 4000                              |0033: iget v0, v8, Lcom/google/android/checkers/a;.g:I // field@0040
+0062b6: b740                                   |0035: xor-int/2addr v0, v4
+0062b8: 3900 1501                              |0036: if-nez v0, 014b // +0115
+0062bc: 5981 5100                              |0038: iput v1, v8, Lcom/google/android/checkers/a;.x:I // field@0051
+0062c0: 0e00                                   |003a: return-void
+0062c2: 1505 00f0                              |003b: const/high16 v5, #int -268435456 // #f000
+0062c6: b565                                   |003d: and-int/2addr v5, v6
+0062c8: 3805 3100                              |003e: if-eqz v5, 006f // +0031
+0062cc: 5285 3d00                              |0040: iget v5, v8, Lcom/google/android/checkers/a;.d:I // field@003d
+0062d0: 5487 3a00                              |0042: iget-object v7, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+0062d4: 4407 0709                              |0044: aget v7, v7, v9
+0062d8: df07 07ff                              |0046: xor-int/lit8 v7, v7, #int -1 // #ff
+0062dc: b575                                   |0048: and-int/2addr v5, v7
+0062de: 5985 3d00                              |0049: iput v5, v8, Lcom/google/android/checkers/a;.d:I // field@003d
+0062e2: 5285 3e00                              |004b: iget v5, v8, Lcom/google/android/checkers/a;.e:I // field@003e
+0062e6: b665                                   |004d: or-int/2addr v5, v6
+0062e8: 5985 3e00                              |004e: iput v5, v8, Lcom/google/android/checkers/a;.e:I // field@003e
+0062ec: 3801 cbff                              |0050: if-eqz v1, 001b // -0035
+0062f0: 5285 3f00                              |0052: iget v5, v8, Lcom/google/android/checkers/a;.f:I // field@003f
+0062f4: 5486 3a00                              |0054: iget-object v6, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+0062f8: 4406 0609                              |0056: aget v6, v6, v9
+0062fc: df06 06ff                              |0058: xor-int/lit8 v6, v6, #int -1 // #ff
+006300: b565                                   |005a: and-int/2addr v5, v6
+006302: 5985 3f00                              |005b: iput v5, v8, Lcom/google/android/checkers/a;.f:I // field@003f
+006306: 5285 4000                              |005d: iget v5, v8, Lcom/google/android/checkers/a;.g:I // field@0040
+00630a: 5486 3a00                              |005f: iget-object v6, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+00630e: 4406 0609                              |0061: aget v6, v6, v9
+006312: df06 06ff                              |0063: xor-int/lit8 v6, v6, #int -1 // #ff
+006316: b565                                   |0065: and-int/2addr v5, v6
+006318: 5985 4000                              |0066: iput v5, v8, Lcom/google/android/checkers/a;.g:I // field@0040
+00631c: 5285 5000                              |0068: iget v5, v8, Lcom/google/android/checkers/a;.w:I // field@0050
+006320: 9101 0501                              |006a: sub-int v1, v5, v1
+006324: 5981 5000                              |006c: iput v1, v8, Lcom/google/android/checkers/a;.w:I // field@0050
+006328: 28ad                                   |006e: goto 001b // -0053
+00632a: 5285 3d00                              |006f: iget v5, v8, Lcom/google/android/checkers/a;.d:I // field@003d
+00632e: 5487 3a00                              |0071: iget-object v7, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+006332: 4407 0709                              |0073: aget v7, v7, v9
+006336: df07 07ff                              |0075: xor-int/lit8 v7, v7, #int -1 // #ff
+00633a: b575                                   |0077: and-int/2addr v5, v7
+00633c: b665                                   |0078: or-int/2addr v5, v6
+00633e: 5985 3d00                              |0079: iput v5, v8, Lcom/google/android/checkers/a;.d:I // field@003d
+006342: 28d5                                   |007b: goto 0050 // -002b
+006344: 5285 3e00                              |007c: iget v5, v8, Lcom/google/android/checkers/a;.e:I // field@003e
+006348: 5487 3a00                              |007e: iget-object v7, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+00634c: 4407 0709                              |0080: aget v7, v7, v9
+006350: df07 07ff                              |0082: xor-int/lit8 v7, v7, #int -1 // #ff
+006354: b575                                   |0084: and-int/2addr v5, v7
+006356: b665                                   |0085: or-int/2addr v5, v6
+006358: 5985 3e00                              |0086: iput v5, v8, Lcom/google/android/checkers/a;.e:I // field@003e
+00635c: 3801 93ff                              |0088: if-eqz v1, 001b // -006d
+006360: 5285 3f00                              |008a: iget v5, v8, Lcom/google/android/checkers/a;.f:I // field@003f
+006364: 5486 3a00                              |008c: iget-object v6, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+006368: 4406 0609                              |008e: aget v6, v6, v9
+00636c: df06 06ff                              |0090: xor-int/lit8 v6, v6, #int -1 // #ff
+006370: b565                                   |0092: and-int/2addr v5, v6
+006372: 5985 3f00                              |0093: iput v5, v8, Lcom/google/android/checkers/a;.f:I // field@003f
+006376: 5285 4000                              |0095: iget v5, v8, Lcom/google/android/checkers/a;.g:I // field@0040
+00637a: 5486 3a00                              |0097: iget-object v6, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+00637e: 4406 0609                              |0099: aget v6, v6, v9
+006382: df06 06ff                              |009b: xor-int/lit8 v6, v6, #int -1 // #ff
+006386: b565                                   |009d: and-int/2addr v5, v6
+006388: 5985 4000                              |009e: iput v5, v8, Lcom/google/android/checkers/a;.g:I // field@0040
+00638c: 5285 5000                              |00a0: iget v5, v8, Lcom/google/android/checkers/a;.w:I // field@0050
+006390: 9101 0501                              |00a2: sub-int v1, v5, v1
+006394: 5981 5000                              |00a4: iput v1, v8, Lcom/google/android/checkers/a;.w:I // field@0050
+006398: 2900 75ff                              |00a6: goto/16 001b // -008b
+00639c: dd05 060f                              |00a8: and-int/lit8 v5, v6, #int 15 // #0f
+0063a0: 3805 3200                              |00aa: if-eqz v5, 00dc // +0032
+0063a4: 5285 3f00                              |00ac: iget v5, v8, Lcom/google/android/checkers/a;.f:I // field@003f
+0063a8: 5487 3a00                              |00ae: iget-object v7, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+0063ac: 4407 0709                              |00b0: aget v7, v7, v9
+0063b0: df07 07ff                              |00b2: xor-int/lit8 v7, v7, #int -1 // #ff
+0063b4: b575                                   |00b4: and-int/2addr v5, v7
+0063b6: 5985 3f00                              |00b5: iput v5, v8, Lcom/google/android/checkers/a;.f:I // field@003f
+0063ba: 5285 4000                              |00b7: iget v5, v8, Lcom/google/android/checkers/a;.g:I // field@0040
+0063be: b665                                   |00b9: or-int/2addr v5, v6
+0063c0: 5985 4000                              |00ba: iput v5, v8, Lcom/google/android/checkers/a;.g:I // field@0040
+0063c4: 3801 5fff                              |00bc: if-eqz v1, 001b // -00a1
+0063c8: 5285 3d00                              |00be: iget v5, v8, Lcom/google/android/checkers/a;.d:I // field@003d
+0063cc: 5486 3a00                              |00c0: iget-object v6, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+0063d0: 4406 0609                              |00c2: aget v6, v6, v9
+0063d4: df06 06ff                              |00c4: xor-int/lit8 v6, v6, #int -1 // #ff
+0063d8: b565                                   |00c6: and-int/2addr v5, v6
+0063da: 5985 3d00                              |00c7: iput v5, v8, Lcom/google/android/checkers/a;.d:I // field@003d
+0063de: 5285 3e00                              |00c9: iget v5, v8, Lcom/google/android/checkers/a;.e:I // field@003e
+0063e2: 5486 3a00                              |00cb: iget-object v6, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+0063e6: 4406 0609                              |00cd: aget v6, v6, v9
+0063ea: df06 06ff                              |00cf: xor-int/lit8 v6, v6, #int -1 // #ff
+0063ee: b565                                   |00d1: and-int/2addr v5, v6
+0063f0: 5985 3e00                              |00d2: iput v5, v8, Lcom/google/android/checkers/a;.e:I // field@003e
+0063f4: 5285 4f00                              |00d4: iget v5, v8, Lcom/google/android/checkers/a;.v:I // field@004f
+0063f8: 9101 0501                              |00d6: sub-int v1, v5, v1
+0063fc: 5981 4f00                              |00d8: iput v1, v8, Lcom/google/android/checkers/a;.v:I // field@004f
+006400: 2900 41ff                              |00da: goto/16 001b // -00bf
+006404: 5285 3f00                              |00dc: iget v5, v8, Lcom/google/android/checkers/a;.f:I // field@003f
+006408: 5487 3a00                              |00de: iget-object v7, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+00640c: 4407 0709                              |00e0: aget v7, v7, v9
+006410: df07 07ff                              |00e2: xor-int/lit8 v7, v7, #int -1 // #ff
+006414: b575                                   |00e4: and-int/2addr v5, v7
+006416: b665                                   |00e5: or-int/2addr v5, v6
+006418: 5985 3f00                              |00e6: iput v5, v8, Lcom/google/android/checkers/a;.f:I // field@003f
+00641c: 28d4                                   |00e8: goto 00bc // -002c
+00641e: 5285 4000                              |00e9: iget v5, v8, Lcom/google/android/checkers/a;.g:I // field@0040
+006422: 5487 3a00                              |00eb: iget-object v7, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+006426: 4407 0709                              |00ed: aget v7, v7, v9
+00642a: df07 07ff                              |00ef: xor-int/lit8 v7, v7, #int -1 // #ff
+00642e: b575                                   |00f1: and-int/2addr v5, v7
+006430: b665                                   |00f2: or-int/2addr v5, v6
+006432: 5985 4000                              |00f3: iput v5, v8, Lcom/google/android/checkers/a;.g:I // field@0040
+006436: 3801 26ff                              |00f5: if-eqz v1, 001b // -00da
+00643a: 5285 3d00                              |00f7: iget v5, v8, Lcom/google/android/checkers/a;.d:I // field@003d
+00643e: 5486 3a00                              |00f9: iget-object v6, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+006442: 4406 0609                              |00fb: aget v6, v6, v9
+006446: df06 06ff                              |00fd: xor-int/lit8 v6, v6, #int -1 // #ff
+00644a: b565                                   |00ff: and-int/2addr v5, v6
+00644c: 5985 3d00                              |0100: iput v5, v8, Lcom/google/android/checkers/a;.d:I // field@003d
+006450: 5285 3e00                              |0102: iget v5, v8, Lcom/google/android/checkers/a;.e:I // field@003e
+006454: 5486 3a00                              |0104: iget-object v6, v8, Lcom/google/android/checkers/a;.a:[I // field@003a
+006458: 4406 0609                              |0106: aget v6, v6, v9
+00645c: df06 06ff                              |0108: xor-int/lit8 v6, v6, #int -1 // #ff
+006460: b565                                   |010a: and-int/2addr v5, v6
+006462: 5985 3e00                              |010b: iput v5, v8, Lcom/google/android/checkers/a;.e:I // field@003e
+006466: 5285 4f00                              |010d: iget v5, v8, Lcom/google/android/checkers/a;.v:I // field@004f
+00646a: 9101 0501                              |010f: sub-int v1, v5, v1
+00646e: 5981 4f00                              |0111: iput v1, v8, Lcom/google/android/checkers/a;.v:I // field@004f
+006472: 2900 08ff                              |0113: goto/16 001b // -00f8
+006476: 6205 3900                              |0115: sget-object v5, Lcom/google/android/checkers/a;.M:[I // field@0039
+00647a: 7110 9f00 0000                         |0117: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+006480: 0a06                                   |011a: move-result v6
+006482: da06 0604                              |011b: mul-int/lit8 v6, v6, #int 4 // #04
+006486: d806 0600                              |011d: add-int/lit8 v6, v6, #int 0 // #00
+00648a: 4405 0506                              |011f: aget v5, v5, v6
+00648e: b751                                   |0121: xor-int/2addr v1, v5
+006490: d805 00ff                              |0122: add-int/lit8 v5, v0, #int -1 // #ff
+006494: b550                                   |0124: and-int/2addr v0, v5
+006496: 2900 02ff                              |0125: goto/16 0027 // -00fe
+00649a: 6202 3900                              |0127: sget-object v2, Lcom/google/android/checkers/a;.M:[I // field@0039
+00649e: 7110 9f00 0000                         |0129: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0064a4: 0a05                                   |012c: move-result v5
+0064a6: da05 0504                              |012d: mul-int/lit8 v5, v5, #int 4 // #04
+0064aa: d805 0501                              |012f: add-int/lit8 v5, v5, #int 1 // #01
+0064ae: 4402 0205                              |0131: aget v2, v2, v5
+0064b2: b721                                   |0133: xor-int/2addr v1, v2
+0064b4: d802 00ff                              |0134: add-int/lit8 v2, v0, #int -1 // #ff
+0064b8: b520                                   |0136: and-int/2addr v0, v2
+0064ba: 2900 f5fe                              |0137: goto/16 002c // -010b
+0064be: 6202 3900                              |0139: sget-object v2, Lcom/google/android/checkers/a;.M:[I // field@0039
+0064c2: 7110 9f00 0000                         |013b: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0064c8: 0a03                                   |013e: move-result v3
+0064ca: da03 0304                              |013f: mul-int/lit8 v3, v3, #int 4 // #04
+0064ce: d803 0302                              |0141: add-int/lit8 v3, v3, #int 2 // #02
+0064d2: 4402 0203                              |0143: aget v2, v2, v3
+0064d6: b721                                   |0145: xor-int/2addr v1, v2
+0064d8: d802 00ff                              |0146: add-int/lit8 v2, v0, #int -1 // #ff
+0064dc: b520                                   |0148: and-int/2addr v0, v2
+0064de: 2900 e8fe                              |0149: goto/16 0031 // -0118
+0064e2: 6202 3900                              |014b: sget-object v2, Lcom/google/android/checkers/a;.M:[I // field@0039
+0064e6: 7110 9f00 0000                         |014d: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0064ec: 0a03                                   |0150: move-result v3
+0064ee: da03 0304                              |0151: mul-int/lit8 v3, v3, #int 4 // #04
+0064f2: d803 0303                              |0153: add-int/lit8 v3, v3, #int 3 // #03
+0064f6: 4402 0203                              |0155: aget v2, v2, v3
+0064fa: b721                                   |0157: xor-int/2addr v1, v2
+0064fc: d802 00ff                              |0158: add-int/lit8 v2, v0, #int -1 // #ff
+006500: b520                                   |015a: and-int/2addr v0, v2
+006502: 2900 dbfe                              |015b: goto/16 0036 // -0125
+006506: 0000                                   |015d: nop // spacer
+006508: 0002 0400 0001 0000 0002 0000 0004 ... |015e: sparse-switch-data (18 units)
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #17              : (in Lcom/google/android/checkers/a;)
+      name          : 'b'
+      type          : '(IIIIIIII)V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 134
+      code          -
+      registers     : 18
+      ins           : 9
+      outs          : 9
+      insns size    : 99 16-bit code units
+00652c:                                        |[00652c] com.google.android.checkers.a.b:(IIIIIIII)V
+00653c: 1210                                   |0000: const/4 v0, #int 1 // #1
+00653e: 6201 3400                              |0001: sget-object v1, Lcom/google/android/checkers/a;.H:[I // field@0034
+006542: 4401 010d                              |0003: aget v1, v1, v13
+006546: b5c1                                   |0005: and-int/2addr v1, v12
+006548: 3801 2500                              |0006: if-eqz v1, 002b // +0025
+00654c: 6201 3500                              |0008: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+006550: 4401 010d                              |000a: aget v1, v1, v13
+006554: b5b1                                   |000c: and-int/2addr v1, v11
+006556: 3801 1e00                              |000d: if-eqz v1, 002b // +001e
+00655a: d804 0d07                              |000f: add-int/lit8 v4, v13, #int 7 // #07
+00655e: 6200 3500                              |0011: sget-object v0, Lcom/google/android/checkers/a;.I:[I // field@0035
+006562: 4405 000d                              |0013: aget v5, v0, v13
+006566: 6200 3400                              |0015: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+00656a: 4400 000d                              |0017: aget v0, v0, v13
+00656e: 9606 0f00                              |0019: or-int v6, v15, v0
+006572: d807 1001                              |001b: add-int/lit8 v7, v16, #int 1 // #01
+006576: 6200 3500                              |001d: sget-object v0, Lcom/google/android/checkers/a;.I:[I // field@0035
+00657a: 4400 000d                              |001f: aget v0, v0, v13
+00657e: 9608 1100                              |0021: or-int v8, v17, v0
+006582: 0790                                   |0023: move-object v0, v9
+006584: 01a1                                   |0024: move v1, v10
+006586: 01b2                                   |0025: move v2, v11
+006588: 01c3                                   |0026: move v3, v12
+00658a: 7609 8600 0000                         |0027: invoke-direct/range {v0, v1, v2, v3, v4, v5, v6, v7, v8}, Lcom/google/android/checkers/a;.b:(IIIIIIII)V // method@0086
+006590: 1200                                   |002a: const/4 v0, #int 0 // #0
+006592: 6201 3600                              |002b: sget-object v1, Lcom/google/android/checkers/a;.J:[I // field@0036
+006596: 4401 010d                              |002d: aget v1, v1, v13
+00659a: b5c1                                   |002f: and-int/2addr v1, v12
+00659c: 3801 2500                              |0030: if-eqz v1, 0055 // +0025
+0065a0: 6201 3700                              |0032: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+0065a4: 4401 010d                              |0034: aget v1, v1, v13
+0065a8: b5b1                                   |0036: and-int/2addr v1, v11
+0065aa: 3801 1e00                              |0037: if-eqz v1, 0055 // +001e
+0065ae: d804 0d09                              |0039: add-int/lit8 v4, v13, #int 9 // #09
+0065b2: 6200 3700                              |003b: sget-object v0, Lcom/google/android/checkers/a;.K:[I // field@0037
+0065b6: 4405 000d                              |003d: aget v5, v0, v13
+0065ba: 6200 3600                              |003f: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+0065be: 4400 000d                              |0041: aget v0, v0, v13
+0065c2: 9606 0f00                              |0043: or-int v6, v15, v0
+0065c6: d807 1001                              |0045: add-int/lit8 v7, v16, #int 1 // #01
+0065ca: 6200 3700                              |0047: sget-object v0, Lcom/google/android/checkers/a;.K:[I // field@0037
+0065ce: 4400 000d                              |0049: aget v0, v0, v13
+0065d2: 9608 1100                              |004b: or-int v8, v17, v0
+0065d6: 0790                                   |004d: move-object v0, v9
+0065d8: 01a1                                   |004e: move v1, v10
+0065da: 01b2                                   |004f: move v2, v11
+0065dc: 01c3                                   |0050: move v3, v12
+0065de: 7609 8600 0000                         |0051: invoke-direct/range {v0, v1, v2, v3, v4, v5, v6, v7, v8}, Lcom/google/android/checkers/a;.b:(IIIIIIII)V // method@0086
+0065e4: 1200                                   |0054: const/4 v0, #int 0 // #0
+0065e6: 3800 0d00                              |0055: if-eqz v0, 0062 // +000d
+0065ea: 0790                                   |0057: move-object v0, v9
+0065ec: 01a1                                   |0058: move v1, v10
+0065ee: 01e2                                   |0059: move v2, v14
+0065f0: 01f3                                   |005a: move v3, v15
+0065f2: 0204 1000                              |005b: move/from16 v4, v16
+0065f6: 0205 1100                              |005d: move/from16 v5, v17
+0065fa: 7606 7e00 0000                         |005f: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+006600: 0e00                                   |0062: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #18              : (in Lcom/google/android/checkers/a;)
+      name          : 'b'
+      type          : '(IZI)Z'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 136
+      code          -
+      registers     : 15
+      ins           : 4
+      outs          : 6
+      insns size    : 461 16-bit code units
+006604:                                        |[006604] com.google.android.checkers.a.b:(IZI)Z
+006614: 1404 e0e0 e000                         |0000: const v4, #float 2.06518e-38 // #00e0e0e0
+00661a: 1216                                   |0003: const/4 v6, #int 1 // #1
+00661c: 1403 e0e0 e0e0                         |0004: const v3, #float -1.29634e+20 // #e0e0e0e0
+006622: 130a 0008                              |0007: const/16 v10, #int 2048 // #800
+006626: 1309 0002                              |0009: const/16 v9, #int 512 // #200
+00662a: 380d e400                              |000b: if-eqz v13, 00ef // +00e4
+00662e: 52b0 3e00                              |000d: iget v0, v11, Lcom/google/android/checkers/a;.e:I // field@003e
+006632: 3900 1b00                              |000f: if-nez v0, 002a // +001b
+006636: 52b0 3d00                              |0011: iget v0, v11, Lcom/google/android/checkers/a;.d:I // field@003d
+00663a: e201 0e04                              |0013: ushr-int/lit8 v1, v14, #int 4 // #04
+00663e: 9502 0e03                              |0015: and-int v2, v14, v3
+006642: e202 0205                              |0017: ushr-int/lit8 v2, v2, #int 5 // #05
+006646: b621                                   |0019: or-int/2addr v1, v2
+006648: 1402 0007 0707                         |001a: const v2, #float 1.01583e-34 // #07070700
+00664e: b5e2                                   |001d: and-int/2addr v2, v14
+006650: e202 0203                              |001e: ushr-int/lit8 v2, v2, #int 3 // #03
+006654: b621                                   |0020: or-int/2addr v1, v2
+006656: b510                                   |0021: and-int/2addr v0, v1
+006658: 3900 2f00                              |0022: if-nez v0, 0051 // +002f
+00665c: 52b0 3c00                              |0024: iget v0, v11, Lcom/google/android/checkers/a;.c:I // field@003c
+006660: 3800 a401                              |0026: if-eqz v0, 01ca // +01a4
+006664: 0160                                   |0028: move v0, v6
+006666: 0f00                                   |0029: return v0
+006668: 52b0 3e00                              |002a: iget v0, v11, Lcom/google/android/checkers/a;.e:I // field@003e
+00666c: 52b1 3d00                              |002c: iget v1, v11, Lcom/google/android/checkers/a;.d:I // field@003d
+006670: b610                                   |002e: or-int/2addr v0, v1
+006672: e201 0e04                              |002f: ushr-int/lit8 v1, v14, #int 4 // #04
+006676: 9502 0e03                              |0031: and-int v2, v14, v3
+00667a: e202 0205                              |0033: ushr-int/lit8 v2, v2, #int 5 // #05
+00667e: b621                                   |0035: or-int/2addr v1, v2
+006680: 1402 0007 0707                         |0036: const v2, #float 1.01583e-34 // #07070700
+006686: b5e2                                   |0039: and-int/2addr v2, v14
+006688: e202 0203                              |003a: ushr-int/lit8 v2, v2, #int 3 // #03
+00668c: b621                                   |003c: or-int/2addr v1, v2
+00668e: b510                                   |003d: and-int/2addr v0, v1
+006690: 52b1 3e00                              |003e: iget v1, v11, Lcom/google/android/checkers/a;.e:I // field@003e
+006694: e002 0e04                              |0040: shl-int/lit8 v2, v14, #int 4 // #04
+006698: 1403 0707 0707                         |0042: const v3, #float 1.01583e-34 // #07070707
+00669e: b5e3                                   |0045: and-int/2addr v3, v14
+0066a0: e003 0305                              |0046: shl-int/lit8 v3, v3, #int 5 // #05
+0066a4: b632                                   |0048: or-int/2addr v2, v3
+0066a6: 9503 0e04                              |0049: and-int v3, v14, v4
+0066aa: e003 0303                              |004b: shl-int/lit8 v3, v3, #int 3 // #03
+0066ae: b632                                   |004d: or-int/2addr v2, v3
+0066b0: b521                                   |004e: and-int/2addr v1, v2
+0066b2: b610                                   |004f: or-int/2addr v0, v1
+0066b4: 28d2                                   |0050: goto 0022 // -002e
+0066b6: 7110 9f00 0000                         |0051: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0066bc: 0a08                                   |0054: move-result v8
+0066be: 9803 0608                              |0055: shl-int v3, v6, v8
+0066c2: 9707 0003                              |0057: xor-int v7, v0, v3
+0066c6: 52b0 3e00                              |0059: iget v0, v11, Lcom/google/android/checkers/a;.e:I // field@003e
+0066ca: b530                                   |005b: and-int/2addr v0, v3
+0066cc: 3900 3400                              |005c: if-nez v0, 0090 // +0034
+0066d0: 6200 3400                              |005e: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+0066d4: 4400 0008                              |0060: aget v0, v0, v8
+0066d8: b5e0                                   |0062: and-int/2addr v0, v14
+0066da: 3800 1300                              |0063: if-eqz v0, 0076 // +0013
+0066de: 6200 3400                              |0065: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+0066e2: 4402 0008                              |0067: aget v2, v0, v8
+0066e6: 1304 0001                              |0069: const/16 v4, #int 256 // #100
+0066ea: 6200 3400                              |006b: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+0066ee: 4400 0008                              |006d: aget v0, v0, v8
+0066f2: 9605 0300                              |006f: or-int v5, v3, v0
+0066f6: 07b0                                   |0071: move-object v0, v11
+0066f8: 01c1                                   |0072: move v1, v12
+0066fa: 7606 7e00 0000                         |0073: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+006700: 6200 3600                              |0076: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+006704: 4400 0008                              |0078: aget v0, v0, v8
+006708: b5e0                                   |007a: and-int/2addr v0, v14
+00670a: 3800 7100                              |007b: if-eqz v0, 00ec // +0071
+00670e: 6200 3600                              |007d: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+006712: 4402 0008                              |007f: aget v2, v0, v8
+006716: 1304 0001                              |0081: const/16 v4, #int 256 // #100
+00671a: 6200 3600                              |0083: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+00671e: 4400 0008                              |0085: aget v0, v0, v8
+006722: 9605 0300                              |0087: or-int v5, v3, v0
+006726: 07b0                                   |0089: move-object v0, v11
+006728: 01c1                                   |008a: move v1, v12
+00672a: 7606 7e00 0000                         |008b: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+006730: 0170                                   |008e: move v0, v7
+006732: 2893                                   |008f: goto 0022 // -006d
+006734: 6200 3000                              |0090: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+006738: 4400 0008                              |0092: aget v0, v0, v8
+00673c: b5e0                                   |0094: and-int/2addr v0, v14
+00673e: 3800 1200                              |0095: if-eqz v0, 00a7 // +0012
+006742: 6200 3000                              |0097: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+006746: 4402 0008                              |0099: aget v2, v0, v8
+00674a: 6200 3000                              |009b: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+00674e: 4400 0008                              |009d: aget v0, v0, v8
+006752: 9605 0300                              |009f: or-int v5, v3, v0
+006756: 07b0                                   |00a1: move-object v0, v11
+006758: 01c1                                   |00a2: move v1, v12
+00675a: 0194                                   |00a3: move v4, v9
+00675c: 7606 7e00 0000                         |00a4: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+006762: 6200 3200                              |00a7: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+006766: 4400 0008                              |00a9: aget v0, v0, v8
+00676a: b5e0                                   |00ab: and-int/2addr v0, v14
+00676c: 3800 1200                              |00ac: if-eqz v0, 00be // +0012
+006770: 6200 3200                              |00ae: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+006774: 4402 0008                              |00b0: aget v2, v0, v8
+006778: 6200 3200                              |00b2: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+00677c: 4400 0008                              |00b4: aget v0, v0, v8
+006780: 9605 0300                              |00b6: or-int v5, v3, v0
+006784: 07b0                                   |00b8: move-object v0, v11
+006786: 01c1                                   |00b9: move v1, v12
+006788: 0194                                   |00ba: move v4, v9
+00678a: 7606 7e00 0000                         |00bb: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+006790: 6200 3400                              |00be: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+006794: 4400 0008                              |00c0: aget v0, v0, v8
+006798: b5e0                                   |00c2: and-int/2addr v0, v14
+00679a: 3800 1200                              |00c3: if-eqz v0, 00d5 // +0012
+00679e: 6200 3400                              |00c5: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+0067a2: 4402 0008                              |00c7: aget v2, v0, v8
+0067a6: 6200 3400                              |00c9: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+0067aa: 4400 0008                              |00cb: aget v0, v0, v8
+0067ae: 9605 0300                              |00cd: or-int v5, v3, v0
+0067b2: 07b0                                   |00cf: move-object v0, v11
+0067b4: 01c1                                   |00d0: move v1, v12
+0067b6: 0194                                   |00d1: move v4, v9
+0067b8: 7606 7e00 0000                         |00d2: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+0067be: 6200 3600                              |00d5: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+0067c2: 4400 0008                              |00d7: aget v0, v0, v8
+0067c6: b5e0                                   |00d9: and-int/2addr v0, v14
+0067c8: 3800 1200                              |00da: if-eqz v0, 00ec // +0012
+0067cc: 6200 3600                              |00dc: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+0067d0: 4402 0008                              |00de: aget v2, v0, v8
+0067d4: 6200 3600                              |00e0: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+0067d8: 4400 0008                              |00e2: aget v0, v0, v8
+0067dc: 9605 0300                              |00e4: or-int v5, v3, v0
+0067e0: 07b0                                   |00e6: move-object v0, v11
+0067e2: 01c1                                   |00e7: move v1, v12
+0067e4: 0194                                   |00e8: move v4, v9
+0067e6: 7606 7e00 0000                         |00e9: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+0067ec: 0170                                   |00ec: move v0, v7
+0067ee: 2900 35ff                              |00ed: goto/16 0022 // -00cb
+0067f2: 52b0 4000                              |00ef: iget v0, v11, Lcom/google/android/checkers/a;.g:I // field@0040
+0067f6: 3900 5400                              |00f1: if-nez v0, 0145 // +0054
+0067fa: 52b0 3f00                              |00f3: iget v0, v11, Lcom/google/android/checkers/a;.f:I // field@003f
+0067fe: e001 0e04                              |00f5: shl-int/lit8 v1, v14, #int 4 // #04
+006802: 1402 0707 0707                         |00f7: const v2, #float 1.01583e-34 // #07070707
+006808: b5e2                                   |00fa: and-int/2addr v2, v14
+00680a: e002 0205                              |00fb: shl-int/lit8 v2, v2, #int 5 // #05
+00680e: b621                                   |00fd: or-int/2addr v1, v2
+006810: 9502 0e04                              |00fe: and-int v2, v14, v4
+006814: e002 0203                              |0100: shl-int/lit8 v2, v2, #int 3 // #03
+006818: b621                                   |0102: or-int/2addr v1, v2
+00681a: b510                                   |0103: and-int/2addr v0, v1
+00681c: 3800 20ff                              |0104: if-eqz v0, 0024 // -00e0
+006820: 7110 9f00 0000                         |0106: invoke-static {v0}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+006826: 0a08                                   |0109: move-result v8
+006828: 9803 0608                              |010a: shl-int v3, v6, v8
+00682c: 9707 0003                              |010c: xor-int v7, v0, v3
+006830: 52b0 4000                              |010e: iget v0, v11, Lcom/google/android/checkers/a;.g:I // field@0040
+006834: b530                                   |0110: and-int/2addr v0, v3
+006836: 3900 5a00                              |0111: if-nez v0, 016b // +005a
+00683a: 6200 3000                              |0113: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+00683e: 4400 0008                              |0115: aget v0, v0, v8
+006842: b5e0                                   |0117: and-int/2addr v0, v14
+006844: 3800 1300                              |0118: if-eqz v0, 012b // +0013
+006848: 6200 3000                              |011a: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+00684c: 4402 0008                              |011c: aget v2, v0, v8
+006850: 1304 0004                              |011e: const/16 v4, #int 1024 // #400
+006854: 6200 3000                              |0120: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+006858: 4400 0008                              |0122: aget v0, v0, v8
+00685c: 9605 0300                              |0124: or-int v5, v3, v0
+006860: 07b0                                   |0126: move-object v0, v11
+006862: 01c1                                   |0127: move v1, v12
+006864: 7606 7e00 0000                         |0128: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+00686a: 6200 3200                              |012b: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+00686e: 4400 0008                              |012d: aget v0, v0, v8
+006872: b5e0                                   |012f: and-int/2addr v0, v14
+006874: 3800 9700                              |0130: if-eqz v0, 01c7 // +0097
+006878: 6200 3200                              |0132: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+00687c: 4402 0008                              |0134: aget v2, v0, v8
+006880: 1304 0004                              |0136: const/16 v4, #int 1024 // #400
+006884: 6200 3200                              |0138: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+006888: 4400 0008                              |013a: aget v0, v0, v8
+00688c: 9605 0300                              |013c: or-int v5, v3, v0
+006890: 07b0                                   |013e: move-object v0, v11
+006892: 01c1                                   |013f: move v1, v12
+006894: 7606 7e00 0000                         |0140: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+00689a: 0170                                   |0143: move v0, v7
+00689c: 28c0                                   |0144: goto 0104 // -0040
+00689e: 52b0 4000                              |0145: iget v0, v11, Lcom/google/android/checkers/a;.g:I // field@0040
+0068a2: 52b1 3f00                              |0147: iget v1, v11, Lcom/google/android/checkers/a;.f:I // field@003f
+0068a6: b610                                   |0149: or-int/2addr v0, v1
+0068a8: e001 0e04                              |014a: shl-int/lit8 v1, v14, #int 4 // #04
+0068ac: 1402 0707 0707                         |014c: const v2, #float 1.01583e-34 // #07070707
+0068b2: b5e2                                   |014f: and-int/2addr v2, v14
+0068b4: e002 0205                              |0150: shl-int/lit8 v2, v2, #int 5 // #05
+0068b8: b621                                   |0152: or-int/2addr v1, v2
+0068ba: 9502 0e04                              |0153: and-int v2, v14, v4
+0068be: e002 0203                              |0155: shl-int/lit8 v2, v2, #int 3 // #03
+0068c2: b621                                   |0157: or-int/2addr v1, v2
+0068c4: b510                                   |0158: and-int/2addr v0, v1
+0068c6: 52b1 4000                              |0159: iget v1, v11, Lcom/google/android/checkers/a;.g:I // field@0040
+0068ca: e202 0e04                              |015b: ushr-int/lit8 v2, v14, #int 4 // #04
+0068ce: b5e3                                   |015d: and-int/2addr v3, v14
+0068d0: e203 0305                              |015e: ushr-int/lit8 v3, v3, #int 5 // #05
+0068d4: b632                                   |0160: or-int/2addr v2, v3
+0068d6: 1403 0007 0707                         |0161: const v3, #float 1.01583e-34 // #07070700
+0068dc: b5e3                                   |0164: and-int/2addr v3, v14
+0068de: e203 0303                              |0165: ushr-int/lit8 v3, v3, #int 3 // #03
+0068e2: b632                                   |0167: or-int/2addr v2, v3
+0068e4: b521                                   |0168: and-int/2addr v1, v2
+0068e6: b610                                   |0169: or-int/2addr v0, v1
+0068e8: 289a                                   |016a: goto 0104 // -0066
+0068ea: 6200 3000                              |016b: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+0068ee: 4400 0008                              |016d: aget v0, v0, v8
+0068f2: b5e0                                   |016f: and-int/2addr v0, v14
+0068f4: 3800 1200                              |0170: if-eqz v0, 0182 // +0012
+0068f8: 6200 3000                              |0172: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+0068fc: 4402 0008                              |0174: aget v2, v0, v8
+006900: 6200 3000                              |0176: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+006904: 4400 0008                              |0178: aget v0, v0, v8
+006908: 9605 0300                              |017a: or-int v5, v3, v0
+00690c: 07b0                                   |017c: move-object v0, v11
+00690e: 01c1                                   |017d: move v1, v12
+006910: 01a4                                   |017e: move v4, v10
+006912: 7606 7e00 0000                         |017f: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+006918: 6200 3200                              |0182: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+00691c: 4400 0008                              |0184: aget v0, v0, v8
+006920: b5e0                                   |0186: and-int/2addr v0, v14
+006922: 3800 1200                              |0187: if-eqz v0, 0199 // +0012
+006926: 6200 3200                              |0189: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+00692a: 4402 0008                              |018b: aget v2, v0, v8
+00692e: 6200 3200                              |018d: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+006932: 4400 0008                              |018f: aget v0, v0, v8
+006936: 9605 0300                              |0191: or-int v5, v3, v0
+00693a: 07b0                                   |0193: move-object v0, v11
+00693c: 01c1                                   |0194: move v1, v12
+00693e: 01a4                                   |0195: move v4, v10
+006940: 7606 7e00 0000                         |0196: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+006946: 6200 3400                              |0199: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+00694a: 4400 0008                              |019b: aget v0, v0, v8
+00694e: b5e0                                   |019d: and-int/2addr v0, v14
+006950: 3800 1200                              |019e: if-eqz v0, 01b0 // +0012
+006954: 6200 3400                              |01a0: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+006958: 4402 0008                              |01a2: aget v2, v0, v8
+00695c: 6200 3400                              |01a4: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+006960: 4400 0008                              |01a6: aget v0, v0, v8
+006964: 9605 0300                              |01a8: or-int v5, v3, v0
+006968: 07b0                                   |01aa: move-object v0, v11
+00696a: 01c1                                   |01ab: move v1, v12
+00696c: 01a4                                   |01ac: move v4, v10
+00696e: 7606 7e00 0000                         |01ad: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+006974: 6200 3600                              |01b0: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+006978: 4400 0008                              |01b2: aget v0, v0, v8
+00697c: b5e0                                   |01b4: and-int/2addr v0, v14
+00697e: 3800 1200                              |01b5: if-eqz v0, 01c7 // +0012
+006982: 6200 3600                              |01b7: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+006986: 4402 0008                              |01b9: aget v2, v0, v8
+00698a: 6200 3600                              |01bb: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+00698e: 4400 0008                              |01bd: aget v0, v0, v8
+006992: 9605 0300                              |01bf: or-int v5, v3, v0
+006996: 07b0                                   |01c1: move-object v0, v11
+006998: 01c1                                   |01c2: move v1, v12
+00699a: 01a4                                   |01c3: move v4, v10
+00699c: 7606 7e00 0000                         |01c4: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+0069a2: 0170                                   |01c7: move v0, v7
+0069a4: 2900 3cff                              |01c8: goto/16 0104 // -00c4
+0069a8: 1200                                   |01ca: const/4 v0, #int 0 // #0
+0069aa: 2900 5efe                              |01cb: goto/16 0029 // -01a2
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #19              : (in Lcom/google/android/checkers/a;)
+      name          : 'c'
+      type          : '(ZIIZ)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 137
+      code          -
+      registers     : 8
+      ins           : 4
+      outs          : 1
+      insns size    : 54 16-bit code units
+0069b0:                                        |[0069b0] com.google.android.checkers.a.c:(ZIIZ)I
+0069c0: 7110 9f00 0500                         |0000: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0069c6: 0a00                                   |0003: move-result v0
+0069c8: d801 05ff                              |0004: add-int/lit8 v1, v5, #int -1 // #ff
+0069cc: b551                                   |0006: and-int/2addr v1, v5
+0069ce: 7110 9f00 0100                         |0007: invoke-static {v1}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0069d4: 0a02                                   |000a: move-result v2
+0069d6: 7110 9f00 0600                         |000b: invoke-static {v6}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+0069dc: 0a01                                   |000e: move-result v1
+0069de: 3807 0800                              |000f: if-eqz v7, 0017 // +0008
+0069e2: d900 001f                              |0011: rsub-int/lit8 v0, v0, #int 31 // #1f
+0069e6: d902 021f                              |0013: rsub-int/lit8 v2, v2, #int 31 // #1f
+0069ea: d901 011f                              |0015: rsub-int/lit8 v1, v1, #int 31 // #1f
+0069ee: 3520 1100                              |0017: if-ge v0, v2, 0028 // +0011
+0069f2: 6203 3800                              |0019: sget-object v3, Lcom/google/android/checkers/a;.L:[I // field@0038
+0069f6: 4402 0302                              |001b: aget v2, v3, v2
+0069fa: b020                                   |001d: add-int/2addr v0, v2
+0069fc: 3804 1000                              |001e: if-eqz v4, 002e // +0010
+006a00: 6202 6500                              |0020: sget-object v2, Lcom/google/android/checkers/g;.m:[B // field@0065
+006a04: da00 0020                              |0022: mul-int/lit8 v0, v0, #int 32 // #20
+006a08: b010                                   |0024: add-int/2addr v0, v1
+006a0a: 4800 0200                              |0025: aget-byte v0, v2, v0
+006a0e: 0f00                                   |0027: return v0
+006a10: 6203 3800                              |0028: sget-object v3, Lcom/google/android/checkers/a;.L:[I // field@0038
+006a14: 4400 0300                              |002a: aget v0, v3, v0
+006a18: b020                                   |002c: add-int/2addr v0, v2
+006a1a: 28f1                                   |002d: goto 001e // -000f
+006a1c: 6202 6600                              |002e: sget-object v2, Lcom/google/android/checkers/g;.n:[B // field@0066
+006a20: da00 0020                              |0030: mul-int/lit8 v0, v0, #int 32 // #20
+006a24: b010                                   |0032: add-int/2addr v0, v1
+006a26: 4800 0200                              |0033: aget-byte v0, v2, v0
+006a2a: 28f2                                   |0035: goto 0027 // -000e
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #20              : (in Lcom/google/android/checkers/a;)
+      name          : 'c'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 138
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+006a2c:                                        |[006a2c] com.google.android.checkers.a.c:()V
+006a3c: 1600 f401                              |0000: const-wide/16 v0, #int 500 // #1f4
+006a40: 7120 ae00 1000                         |0002: invoke-static {v0, v1}, Ljava/lang/Thread;.sleep:(J)V // method@00ae
+006a46: 0e00                                   |0005: return-void
+006a48: 0d00                                   |0006: move-exception v0
+006a4a: 28fe                                   |0007: goto 0005 // -0002
+      catches       : 1
+        0x0002 - 0x0005
+          Ljava/lang/InterruptedException; -> 0x0006
+      positions     : 
+      locals        : 
+
+    #21              : (in Lcom/google/android/checkers/a;)
+      name          : 'c'
+      type          : '(IIIIIIII)V'
+      access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 139
+      code          -
+      registers     : 18
+      ins           : 9
+      outs          : 9
+      insns size    : 203 16-bit code units
+006a58:                                        |[006a58] com.google.android.checkers.a.c:(IIIIIIII)V
+006a68: 1210                                   |0000: const/4 v0, #int 1 // #1
+006a6a: 6201 3000                              |0001: sget-object v1, Lcom/google/android/checkers/a;.D:[I // field@0030
+006a6e: 4401 010d                              |0003: aget v1, v1, v13
+006a72: b5c1                                   |0005: and-int/2addr v1, v12
+006a74: 3801 2a00                              |0006: if-eqz v1, 0030 // +002a
+006a78: 6201 3100                              |0008: sget-object v1, Lcom/google/android/checkers/a;.E:[I // field@0031
+006a7c: 4401 010d                              |000a: aget v1, v1, v13
+006a80: b5b1                                   |000c: and-int/2addr v1, v11
+006a82: 3801 2300                              |000d: if-eqz v1, 0030 // +0023
+006a86: 6200 3000                              |000f: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+006a8a: 4400 000d                              |0011: aget v0, v0, v13
+006a8e: 9703 0c00                              |0013: xor-int v3, v12, v0
+006a92: d804 0df7                              |0015: add-int/lit8 v4, v13, #int -9 // #f7
+006a96: 6200 3100                              |0017: sget-object v0, Lcom/google/android/checkers/a;.E:[I // field@0031
+006a9a: 4405 000d                              |0019: aget v5, v0, v13
+006a9e: 6200 3000                              |001b: sget-object v0, Lcom/google/android/checkers/a;.D:[I // field@0030
+006aa2: 4400 000d                              |001d: aget v0, v0, v13
+006aa6: 9606 0f00                              |001f: or-int v6, v15, v0
+006aaa: d807 1001                              |0021: add-int/lit8 v7, v16, #int 1 // #01
+006aae: 6200 3100                              |0023: sget-object v0, Lcom/google/android/checkers/a;.E:[I // field@0031
+006ab2: 4400 000d                              |0025: aget v0, v0, v13
+006ab6: 9608 1100                              |0027: or-int v8, v17, v0
+006aba: 0790                                   |0029: move-object v0, v9
+006abc: 01a1                                   |002a: move v1, v10
+006abe: 01b2                                   |002b: move v2, v11
+006ac0: 7609 8b00 0000                         |002c: invoke-direct/range {v0, v1, v2, v3, v4, v5, v6, v7, v8}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+006ac6: 1200                                   |002f: const/4 v0, #int 0 // #0
+006ac8: 6201 3200                              |0030: sget-object v1, Lcom/google/android/checkers/a;.F:[I // field@0032
+006acc: 4401 010d                              |0032: aget v1, v1, v13
+006ad0: b5c1                                   |0034: and-int/2addr v1, v12
+006ad2: 3801 2a00                              |0035: if-eqz v1, 005f // +002a
+006ad6: 6201 3300                              |0037: sget-object v1, Lcom/google/android/checkers/a;.G:[I // field@0033
+006ada: 4401 010d                              |0039: aget v1, v1, v13
+006ade: b5b1                                   |003b: and-int/2addr v1, v11
+006ae0: 3801 2300                              |003c: if-eqz v1, 005f // +0023
+006ae4: 6200 3200                              |003e: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+006ae8: 4400 000d                              |0040: aget v0, v0, v13
+006aec: 9703 0c00                              |0042: xor-int v3, v12, v0
+006af0: d804 0df9                              |0044: add-int/lit8 v4, v13, #int -7 // #f9
+006af4: 6200 3300                              |0046: sget-object v0, Lcom/google/android/checkers/a;.G:[I // field@0033
+006af8: 4405 000d                              |0048: aget v5, v0, v13
+006afc: 6200 3200                              |004a: sget-object v0, Lcom/google/android/checkers/a;.F:[I // field@0032
+006b00: 4400 000d                              |004c: aget v0, v0, v13
+006b04: 9606 0f00                              |004e: or-int v6, v15, v0
+006b08: d807 1001                              |0050: add-int/lit8 v7, v16, #int 1 // #01
+006b0c: 6200 3300                              |0052: sget-object v0, Lcom/google/android/checkers/a;.G:[I // field@0033
+006b10: 4400 000d                              |0054: aget v0, v0, v13
+006b14: 9608 1100                              |0056: or-int v8, v17, v0
+006b18: 0790                                   |0058: move-object v0, v9
+006b1a: 01a1                                   |0059: move v1, v10
+006b1c: 01b2                                   |005a: move v2, v11
+006b1e: 7609 8b00 0000                         |005b: invoke-direct/range {v0, v1, v2, v3, v4, v5, v6, v7, v8}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+006b24: 1200                                   |005e: const/4 v0, #int 0 // #0
+006b26: 6201 3400                              |005f: sget-object v1, Lcom/google/android/checkers/a;.H:[I // field@0034
+006b2a: 4401 010d                              |0061: aget v1, v1, v13
+006b2e: b5c1                                   |0063: and-int/2addr v1, v12
+006b30: 3801 2a00                              |0064: if-eqz v1, 008e // +002a
+006b34: 6201 3500                              |0066: sget-object v1, Lcom/google/android/checkers/a;.I:[I // field@0035
+006b38: 4401 010d                              |0068: aget v1, v1, v13
+006b3c: b5b1                                   |006a: and-int/2addr v1, v11
+006b3e: 3801 2300                              |006b: if-eqz v1, 008e // +0023
+006b42: 6200 3400                              |006d: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+006b46: 4400 000d                              |006f: aget v0, v0, v13
+006b4a: 9703 0c00                              |0071: xor-int v3, v12, v0
+006b4e: d804 0d07                              |0073: add-int/lit8 v4, v13, #int 7 // #07
+006b52: 6200 3500                              |0075: sget-object v0, Lcom/google/android/checkers/a;.I:[I // field@0035
+006b56: 4405 000d                              |0077: aget v5, v0, v13
+006b5a: 6200 3400                              |0079: sget-object v0, Lcom/google/android/checkers/a;.H:[I // field@0034
+006b5e: 4400 000d                              |007b: aget v0, v0, v13
+006b62: 9606 0f00                              |007d: or-int v6, v15, v0
+006b66: d807 1001                              |007f: add-int/lit8 v7, v16, #int 1 // #01
+006b6a: 6200 3500                              |0081: sget-object v0, Lcom/google/android/checkers/a;.I:[I // field@0035
+006b6e: 4400 000d                              |0083: aget v0, v0, v13
+006b72: 9608 1100                              |0085: or-int v8, v17, v0
+006b76: 0790                                   |0087: move-object v0, v9
+006b78: 01a1                                   |0088: move v1, v10
+006b7a: 01b2                                   |0089: move v2, v11
+006b7c: 7609 8b00 0000                         |008a: invoke-direct/range {v0, v1, v2, v3, v4, v5, v6, v7, v8}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+006b82: 1200                                   |008d: const/4 v0, #int 0 // #0
+006b84: 6201 3600                              |008e: sget-object v1, Lcom/google/android/checkers/a;.J:[I // field@0036
+006b88: 4401 010d                              |0090: aget v1, v1, v13
+006b8c: b5c1                                   |0092: and-int/2addr v1, v12
+006b8e: 3801 2a00                              |0093: if-eqz v1, 00bd // +002a
+006b92: 6201 3700                              |0095: sget-object v1, Lcom/google/android/checkers/a;.K:[I // field@0037
+006b96: 4401 010d                              |0097: aget v1, v1, v13
+006b9a: b5b1                                   |0099: and-int/2addr v1, v11
+006b9c: 3801 2300                              |009a: if-eqz v1, 00bd // +0023
+006ba0: 6200 3600                              |009c: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+006ba4: 4400 000d                              |009e: aget v0, v0, v13
+006ba8: 9703 0c00                              |00a0: xor-int v3, v12, v0
+006bac: d804 0d09                              |00a2: add-int/lit8 v4, v13, #int 9 // #09
+006bb0: 6200 3700                              |00a4: sget-object v0, Lcom/google/android/checkers/a;.K:[I // field@0037
+006bb4: 4405 000d                              |00a6: aget v5, v0, v13
+006bb8: 6200 3600                              |00a8: sget-object v0, Lcom/google/android/checkers/a;.J:[I // field@0036
+006bbc: 4400 000d                              |00aa: aget v0, v0, v13
+006bc0: 9606 0f00                              |00ac: or-int v6, v15, v0
+006bc4: d807 1001                              |00ae: add-int/lit8 v7, v16, #int 1 // #01
+006bc8: 6200 3700                              |00b0: sget-object v0, Lcom/google/android/checkers/a;.K:[I // field@0037
+006bcc: 4400 000d                              |00b2: aget v0, v0, v13
+006bd0: 9608 1100                              |00b4: or-int v8, v17, v0
+006bd4: 0790                                   |00b6: move-object v0, v9
+006bd6: 01a1                                   |00b7: move v1, v10
+006bd8: 01b2                                   |00b8: move v2, v11
+006bda: 7609 8b00 0000                         |00b9: invoke-direct/range {v0, v1, v2, v3, v4, v5, v6, v7, v8}, Lcom/google/android/checkers/a;.c:(IIIIIIII)V // method@008b
+006be0: 1200                                   |00bc: const/4 v0, #int 0 // #0
+006be2: 3800 0d00                              |00bd: if-eqz v0, 00ca // +000d
+006be6: 0790                                   |00bf: move-object v0, v9
+006be8: 01a1                                   |00c0: move v1, v10
+006bea: 01e2                                   |00c1: move v2, v14
+006bec: 01f3                                   |00c2: move v3, v15
+006bee: 0204 1000                              |00c3: move/from16 v4, v16
+006bf2: 0205 1100                              |00c5: move/from16 v5, v17
+006bf6: 7606 7e00 0000                         |00c7: invoke-direct/range {v0, v1, v2, v3, v4, v5}, Lcom/google/android/checkers/a;.a:(IIIII)V // method@007e
+006bfc: 0e00                                   |00ca: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #22              : (in Lcom/google/android/checkers/a;)
+      name          : 'd'
+      type          : '(ZIIZ)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 140
+      code          -
+      registers     : 8
+      ins           : 4
+      outs          : 1
+      insns size    : 56 16-bit code units
+006c00:                                        |[006c00] com.google.android.checkers.a.d:(ZIIZ)I
+006c10: 7110 9f00 0500                         |0000: invoke-static {v5}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+006c16: 0a00                                   |0003: move-result v0
+006c18: d801 05ff                              |0004: add-int/lit8 v1, v5, #int -1 // #ff
+006c1c: b551                                   |0006: and-int/2addr v1, v5
+006c1e: 7110 9f00 0100                         |0007: invoke-static {v1}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+006c24: 0a02                                   |000a: move-result v2
+006c26: 7110 9f00 0600                         |000b: invoke-static {v6}, Ljava/lang/Integer;.numberOfTrailingZeros:(I)I // method@009f
+006c2c: 0a01                                   |000e: move-result v1
+006c2e: 3807 0800                              |000f: if-eqz v7, 0017 // +0008
+006c32: d900 001f                              |0011: rsub-int/lit8 v0, v0, #int 31 // #1f
+006c36: d902 021f                              |0013: rsub-int/lit8 v2, v2, #int 31 // #1f
+006c3a: d901 011f                              |0015: rsub-int/lit8 v1, v1, #int 31 // #1f
+006c3e: d801 01fc                              |0017: add-int/lit8 v1, v1, #int -4 // #fc
+006c42: 3520 1100                              |0019: if-ge v0, v2, 002a // +0011
+006c46: 6203 3800                              |001b: sget-object v3, Lcom/google/android/checkers/a;.L:[I // field@0038
+006c4a: 4402 0302                              |001d: aget v2, v3, v2
+006c4e: b020                                   |001f: add-int/2addr v0, v2
+006c50: 3804 1000                              |0020: if-eqz v4, 0030 // +0010
+006c54: 6202 6700                              |0022: sget-object v2, Lcom/google/android/checkers/g;.o:[B // field@0067
+006c58: da00 001c                              |0024: mul-int/lit8 v0, v0, #int 28 // #1c
+006c5c: b010                                   |0026: add-int/2addr v0, v1
+006c5e: 4800 0200                              |0027: aget-byte v0, v2, v0
+006c62: 0f00                                   |0029: return v0
+006c64: 6203 3800                              |002a: sget-object v3, Lcom/google/android/checkers/a;.L:[I // field@0038
+006c68: 4400 0300                              |002c: aget v0, v3, v0
+006c6c: b020                                   |002e: add-int/2addr v0, v2
+006c6e: 28f1                                   |002f: goto 0020 // -000f
+006c70: 6202 6800                              |0030: sget-object v2, Lcom/google/android/checkers/g;.p:[B // field@0068
+006c74: da00 001c                              |0032: mul-int/lit8 v0, v0, #int 28 // #1c
+006c78: b010                                   |0034: add-int/2addr v0, v1
+006c7a: 4800 0200                              |0035: aget-byte v0, v2, v0
+006c7e: 28f2                                   |0037: goto 0029 // -000e
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+    #0              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(ZZ)I'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 122
+      code          -
+      registers     : 4
+      ins           : 3
+      outs          : 3
+      insns size    : 8 16-bit code units
+006c80:                                        |[006c80] com.google.android.checkers.a.a:(ZZ)I
+006c90: 5c13 4c00                              |0000: iput-boolean v3, v1, Lcom/google/android/checkers/a;.s:Z // field@004c
+006c94: 1200                                   |0002: const/4 v0, #int 0 // #0
+006c96: 7030 7500 0102                         |0003: invoke-direct {v1, v0, v2}, Lcom/google/android/checkers/a;.a:(IZ)I // method@0075
+006c9c: 0a00                                   |0006: move-result v0
+006c9e: 0f00                                   |0007: return v0
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #1              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '()V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 123
+      code          -
+      registers     : 4
+      ins           : 1
+      outs          : 3
+      insns size    : 45 16-bit code units
+006ca0:                                        |[006ca0] com.google.android.checkers.a.a:()V
+006cb0: 1302 0c00                              |0000: const/16 v2, #int 12 // #c
+006cb4: 1201                                   |0002: const/4 v1, #int 0 // #0
+006cb6: 1300 ff0f                              |0003: const/16 v0, #int 4095 // #fff
+006cba: 5930 3d00                              |0005: iput v0, v3, Lcom/google/android/checkers/a;.d:I // field@003d
+006cbe: 5931 3e00                              |0007: iput v1, v3, Lcom/google/android/checkers/a;.e:I // field@003e
+006cc2: 1500 f0ff                              |0009: const/high16 v0, #int -1048576 // #fff0
+006cc6: 5930 3f00                              |000b: iput v0, v3, Lcom/google/android/checkers/a;.f:I // field@003f
+006cca: 5931 4000                              |000d: iput v1, v3, Lcom/google/android/checkers/a;.g:I // field@0040
+006cce: 5932 4f00                              |000f: iput v2, v3, Lcom/google/android/checkers/a;.v:I // field@004f
+006cd2: 5932 5000                              |0011: iput v2, v3, Lcom/google/android/checkers/a;.w:I // field@0050
+006cd6: 7020 7600 1300                         |0013: invoke-direct {v3, v1}, Lcom/google/android/checkers/a;.a:(Z)I // method@0076
+006cdc: 0a00                                   |0016: move-result v0
+006cde: 5930 5100                              |0017: iput v0, v3, Lcom/google/android/checkers/a;.x:I // field@0051
+006ce2: 7030 7500 1301                         |0019: invoke-direct {v3, v1, v1}, Lcom/google/android/checkers/a;.a:(IZ)I // method@0075
+006ce8: 5530 2e00                              |001c: iget-boolean v0, v3, Lcom/google/android/checkers/a;.B:Z // field@002e
+006cec: 3800 0700                              |001e: if-eqz v0, 0025 // +0007
+006cf0: 0110                                   |0020: move v0, v1
+006cf2: 1502 1000                              |0021: const/high16 v2, #int 1048576 // #10
+006cf6: 3420 0300                              |0023: if-lt v0, v2, 0026 // +0003
+006cfa: 0e00                                   |0025: return-void
+006cfc: 5432 5200                              |0026: iget-object v2, v3, Lcom/google/android/checkers/a;.y:[I // field@0052
+006d00: 4b01 0200                              |0028: aput v1, v2, v0
+006d04: d800 0001                              |002a: add-int/lit8 v0, v0, #int 1 // #01
+006d08: 28f5                                   |002c: goto 0021 // -000b
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #2              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(I)V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 124
+      code          -
+      registers     : 2
+      ins           : 2
+      outs          : 2
+      insns size    : 4 16-bit code units
+006d0c:                                        |[006d0c] com.google.android.checkers.a.a:(I)V
+006d1c: 7020 8500 1000                         |0000: invoke-direct {v0, v1}, Lcom/google/android/checkers/a;.b:(I)V // method@0085
+006d22: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #3              : (in Lcom/google/android/checkers/a;)
+      name          : 'a'
+      type          : '(IIIIZ)V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 128
+      code          -
+      registers     : 8
+      ins           : 6
+      outs          : 2
+      insns size    : 37 16-bit code units
+006d24:                                        |[006d24] com.google.android.checkers.a.a:(IIIIZ)V
+006d34: 5923 3d00                              |0000: iput v3, v2, Lcom/google/android/checkers/a;.d:I // field@003d
+006d38: 5924 3e00                              |0002: iput v4, v2, Lcom/google/android/checkers/a;.e:I // field@003e
+006d3c: 5925 3f00                              |0004: iput v5, v2, Lcom/google/android/checkers/a;.f:I // field@003f
+006d40: 5926 4000                              |0006: iput v6, v2, Lcom/google/android/checkers/a;.g:I // field@0040
+006d44: 5220 3d00                              |0008: iget v0, v2, Lcom/google/android/checkers/a;.d:I // field@003d
+006d48: 5221 3e00                              |000a: iget v1, v2, Lcom/google/android/checkers/a;.e:I // field@003e
+006d4c: b610                                   |000c: or-int/2addr v0, v1
+006d4e: 7110 9e00 0000                         |000d: invoke-static {v0}, Ljava/lang/Integer;.bitCount:(I)I // method@009e
+006d54: 0a00                                   |0010: move-result v0
+006d56: 5920 4f00                              |0011: iput v0, v2, Lcom/google/android/checkers/a;.v:I // field@004f
+006d5a: 5220 3f00                              |0013: iget v0, v2, Lcom/google/android/checkers/a;.f:I // field@003f
+006d5e: 5221 4000                              |0015: iget v1, v2, Lcom/google/android/checkers/a;.g:I // field@0040
+006d62: b610                                   |0017: or-int/2addr v0, v1
+006d64: 7110 9e00 0000                         |0018: invoke-static {v0}, Ljava/lang/Integer;.bitCount:(I)I // method@009e
+006d6a: 0a00                                   |001b: move-result v0
+006d6c: 5920 5000                              |001c: iput v0, v2, Lcom/google/android/checkers/a;.w:I // field@0050
+006d70: 7020 7600 7200                         |001e: invoke-direct {v2, v7}, Lcom/google/android/checkers/a;.a:(Z)I // method@0076
+006d76: 0a00                                   |0021: move-result v0
+006d78: 5920 5100                              |0022: iput v0, v2, Lcom/google/android/checkers/a;.x:I // field@0051
+006d7c: 0e00                                   |0024: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #4              : (in Lcom/google/android/checkers/a;)
+      name          : 'b'
+      type          : '(ZZ)V'
+      access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 135
+      code          -
+      registers     : 4
+      ins           : 3
+      outs          : 1
+      insns size    : 16 16-bit code units
+006d80:                                        |[006d80] com.google.android.checkers.a.b:(ZZ)V
+006d90: 1d01                                   |0000: monitor-enter v1
+006d92: 5c12 4d00                              |0001: iput-boolean v2, v1, Lcom/google/android/checkers/a;.t:Z // field@004d
+006d96: 5c13 4c00                              |0003: iput-boolean v3, v1, Lcom/google/android/checkers/a;.s:Z // field@004c
+006d9a: 1210                                   |0005: const/4 v0, #int 1 // #1
+006d9c: 5c10 4400                              |0006: iput-boolean v0, v1, Lcom/google/android/checkers/a;.k:Z // field@0044
+006da0: 6e10 a100 0100                         |0008: invoke-virtual {v1}, Ljava/lang/Object;.notify:()V // method@00a1
+006da6: 1e01                                   |000b: monitor-exit v1
+006da8: 0e00                                   |000c: return-void
+006daa: 0d00                                   |000d: move-exception v0
+006dac: 1e01                                   |000e: monitor-exit v1
+006dae: 2700                                   |000f: throw v0
+      catches       : 1
+        0x0001 - 0x000b
+          <any> -> 0x000d
+      positions     : 
+      locals        : 
+
+    #5              : (in Lcom/google/android/checkers/a;)
+      name          : 'run'
+      type          : '()V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 141
+      code          -
+      registers     : 24
+      ins           : 1
+      outs          : 7
+      insns size    : 526 16-bit code units
+006dbc:                                        |[006dbc] com.google.android.checkers.a.run:()V
+006dcc: 7601 8400 1700                         |0000: invoke-direct/range {v23}, Lcom/google/android/checkers/a;.b:()V // method@0084
+006dd2: 0800 1700                              |0003: move-object/from16 v0, v23
+006dd6: 5202 3c00                              |0005: iget v2, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+006dda: 1213                                   |0007: const/4 v3, #int 1 // #1
+006ddc: 3332 1100                              |0008: if-ne v2, v3, 0019 // +0011
+006de0: 7100 8a00 0000                         |000a: invoke-static {}, Lcom/google/android/checkers/a;.c:()V // method@008a
+006de6: 0800 1700                              |000d: move-object/from16 v0, v23
+006dea: 5402 4300                              |000f: iget-object v2, v0, Lcom/google/android/checkers/a;.j:Lcom/google/android/checkers/CheckersView; // field@0043
+006dee: 1203                                   |0011: const/4 v3, #int 0 // #0
+006df0: 1204                                   |0012: const/4 v4, #int 0 // #0
+006df2: 12f5                                   |0013: const/4 v5, #int -1 // #ff
+006df4: 1216                                   |0014: const/4 v6, #int 1 // #1
+006df6: 6e56 5000 3254                         |0015: invoke-virtual {v2, v3, v4, v5, v6}, Lcom/google/android/checkers/CheckersView;.a:(IIII)V // method@0050
+006dfc: 28e8                                   |0018: goto 0000 // -0018
+006dfe: 0800 1700                              |0019: move-object/from16 v0, v23
+006e02: 5202 4100                              |001b: iget v2, v0, Lcom/google/android/checkers/a;.h:I // field@0041
+006e06: 3902 1c00                              |001d: if-nez v2, 0039 // +001c
+006e0a: 7100 8a00 0000                         |001f: invoke-static {}, Lcom/google/android/checkers/a;.c:()V // method@008a
+006e10: 0800 1700                              |0022: move-object/from16 v0, v23
+006e14: 5402 4200                              |0024: iget-object v2, v0, Lcom/google/android/checkers/a;.i:Ljava/util/Random; // field@0042
+006e18: 0800 1700                              |0026: move-object/from16 v0, v23
+006e1c: 5203 3c00                              |0028: iget v3, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+006e20: 6e20 b000 3200                         |002a: invoke-virtual {v2, v3}, Ljava/util/Random;.nextInt:(I)I // method@00b0
+006e26: 0a02                                   |002d: move-result v2
+006e28: 0800 1700                              |002e: move-object/from16 v0, v23
+006e2c: 5403 4300                              |0030: iget-object v3, v0, Lcom/google/android/checkers/a;.j:Lcom/google/android/checkers/CheckersView; // field@0043
+006e30: 1204                                   |0032: const/4 v4, #int 0 // #0
+006e32: 1205                                   |0033: const/4 v5, #int 0 // #0
+006e34: 1216                                   |0034: const/4 v6, #int 1 // #1
+006e36: 6e56 5000 2354                         |0035: invoke-virtual {v3, v2, v4, v5, v6}, Lcom/google/android/checkers/CheckersView;.a:(IIII)V // method@0050
+006e3c: 28c8                                   |0038: goto 0000 // -0038
+006e3e: 0800 1700                              |0039: move-object/from16 v0, v23
+006e42: 5202 3d00                              |003b: iget v2, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+006e46: 1303 ff0f                              |003d: const/16 v3, #int 4095 // #fff
+006e4a: 3332 2700                              |003f: if-ne v2, v3, 0066 // +0027
+006e4e: 7100 8a00 0000                         |0041: invoke-static {}, Lcom/google/android/checkers/a;.c:()V // method@008a
+006e54: 0800 1700                              |0044: move-object/from16 v0, v23
+006e58: 5403 4200                              |0046: iget-object v3, v0, Lcom/google/android/checkers/a;.i:Ljava/util/Random; // field@0042
+006e5c: 0800 1700                              |0048: move-object/from16 v0, v23
+006e60: 5204 3c00                              |004a: iget v4, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+006e64: 0800 1700                              |004c: move-object/from16 v0, v23
+006e68: 5502 4d00                              |004e: iget-boolean v2, v0, Lcom/google/android/checkers/a;.t:Z // field@004d
+006e6c: 3802 1400                              |0050: if-eqz v2, 0064 // +0014
+006e70: 1212                                   |0052: const/4 v2, #int 1 // #1
+006e72: 9102 0402                              |0053: sub-int v2, v4, v2
+006e76: 6e20 b000 2300                         |0055: invoke-virtual {v3, v2}, Ljava/util/Random;.nextInt:(I)I // method@00b0
+006e7c: 0a02                                   |0058: move-result v2
+006e7e: 0800 1700                              |0059: move-object/from16 v0, v23
+006e82: 5403 4300                              |005b: iget-object v3, v0, Lcom/google/android/checkers/a;.j:Lcom/google/android/checkers/CheckersView; // field@0043
+006e86: 1204                                   |005d: const/4 v4, #int 0 // #0
+006e88: 12e5                                   |005e: const/4 v5, #int -2 // #fe
+006e8a: 1216                                   |005f: const/4 v6, #int 1 // #1
+006e8c: 6e56 5000 2354                         |0060: invoke-virtual {v3, v2, v4, v5, v6}, Lcom/google/android/checkers/CheckersView;.a:(IIII)V // method@0050
+006e92: 289d                                   |0063: goto 0000 // -0063
+006e94: 1202                                   |0064: const/4 v2, #int 0 // #0
+006e96: 28ee                                   |0065: goto 0053 // -0012
+006e98: 7100 ab00 0000                         |0066: invoke-static {}, Ljava/lang/System;.currentTimeMillis:()J // method@00ab
+006e9e: 0b02                                   |0069: move-result-wide v2
+006ea0: 0800 1700                              |006a: move-object/from16 v0, v23
+006ea4: 5a02 4500                              |006c: iput-wide v2, v0, Lcom/google/android/checkers/a;.l:J // field@0045
+006ea8: 1202                                   |006e: const/4 v2, #int 0 // #0
+006eaa: 0800 1700                              |006f: move-object/from16 v0, v23
+006eae: 5902 4700                              |0071: iput v2, v0, Lcom/google/android/checkers/a;.n:I // field@0047
+006eb2: 1202                                   |0073: const/4 v2, #int 0 // #0
+006eb4: 0800 1700                              |0074: move-object/from16 v0, v23
+006eb8: 5c02 4600                              |0076: iput-boolean v2, v0, Lcom/google/android/checkers/a;.m:Z // field@0046
+006ebc: 0800 1700                              |0078: move-object/from16 v0, v23
+006ec0: 5502 4c00                              |007a: iget-boolean v2, v0, Lcom/google/android/checkers/a;.s:Z // field@004c
+006ec4: 3902 5100                              |007c: if-nez v2, 00cd // +0051
+006ec8: 6302 6a00                              |007e: sget-boolean v2, Lcom/google/android/checkers/g;.r:Z // field@006a
+006ecc: 3802 4d00                              |0080: if-eqz v2, 00cd // +004d
+006ed0: 1212                                   |0082: const/4 v2, #int 1 // #1
+006ed2: 0800 1700                              |0083: move-object/from16 v0, v23
+006ed6: 5c02 4e00                              |0085: iput-boolean v2, v0, Lcom/google/android/checkers/a;.u:Z // field@004e
+006eda: 0800 1700                              |0087: move-object/from16 v0, v23
+006ede: 520e 3c00                              |0089: iget v14, v0, Lcom/google/android/checkers/a;.c:I // field@003c
+006ee2: 120d                                   |008b: const/4 v13, #int 0 // #0
+006ee4: 120b                                   |008c: const/4 v11, #int 0 // #0
+006ee6: 120a                                   |008d: const/4 v10, #int 0 // #0
+006ee8: 1212                                   |008e: const/4 v2, #int 1 // #1
+006eea: 0800 1700                              |008f: move-object/from16 v0, v23
+006eee: 5902 2f00                              |0091: iput v2, v0, Lcom/google/android/checkers/a;.C:I // field@002f
+006ef2: 0800 1700                              |0093: move-object/from16 v0, v23
+006ef6: 520f 3d00                              |0095: iget v15, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+006efa: 0800 1700                              |0097: move-object/from16 v0, v23
+006efe: 5200 3e00                              |0099: iget v0, v0, Lcom/google/android/checkers/a;.e:I // field@003e
+006f02: 0210 0000                              |009b: move/from16 v16, v0
+006f06: 0800 1700                              |009d: move-object/from16 v0, v23
+006f0a: 5200 3f00                              |009f: iget v0, v0, Lcom/google/android/checkers/a;.f:I // field@003f
+006f0e: 0211 0000                              |00a1: move/from16 v17, v0
+006f12: 0800 1700                              |00a3: move-object/from16 v0, v23
+006f16: 5200 4000                              |00a5: iget v0, v0, Lcom/google/android/checkers/a;.g:I // field@0040
+006f1a: 0212 0000                              |00a7: move/from16 v18, v0
+006f1e: 0800 1700                              |00a9: move-object/from16 v0, v23
+006f22: 5200 4f00                              |00ab: iget v0, v0, Lcom/google/android/checkers/a;.v:I // field@004f
+006f26: 0213 0000                              |00ad: move/from16 v19, v0
+006f2a: 0800 1700                              |00af: move-object/from16 v0, v23
+006f2e: 5200 5000                              |00b1: iget v0, v0, Lcom/google/android/checkers/a;.w:I // field@0050
+006f32: 0214 0000                              |00b3: move/from16 v20, v0
+006f36: 0800 1700                              |00b5: move-object/from16 v0, v23
+006f3a: 5200 5100                              |00b7: iget v0, v0, Lcom/google/android/checkers/a;.x:I // field@0051
+006f3e: 0215 0000                              |00b9: move/from16 v21, v0
+006f42: 1216                                   |00bb: const/4 v6, #int 1 // #1
+006f44: 1302 4000                              |00bc: const/16 v2, #int 64 // #40
+006f48: 3726 1100                              |00be: if-le v6, v2, 00cf // +0011
+006f4c: 0800 1700                              |00c0: move-object/from16 v0, v23
+006f50: 5402 4300                              |00c2: iget-object v2, v0, Lcom/google/android/checkers/a;.j:Lcom/google/android/checkers/CheckersView; // field@0043
+006f54: 0800 1700                              |00c4: move-object/from16 v0, v23
+006f58: 5203 2f00                              |00c6: iget v3, v0, Lcom/google/android/checkers/a;.C:I // field@002f
+006f5c: 6e53 5000 d2ab                         |00c8: invoke-virtual {v2, v13, v11, v10, v3}, Lcom/google/android/checkers/CheckersView;.a:(IIII)V // method@0050
+006f62: 2900 35ff                              |00cb: goto/16 0000 // -00cb
+006f66: 1202                                   |00cd: const/4 v2, #int 0 // #0
+006f68: 28b5                                   |00ce: goto 0083 // -004b
+006f6a: 1309 0180                              |00cf: const/16 v9, #int -32767 // #8001
+006f6e: 120c                                   |00d1: const/4 v12, #int 0 // #0
+006f70: 34ec 1500                              |00d2: if-lt v12, v14, 00e7 // +0015
+006f74: 1302 0083                              |00d4: const/16 v2, #int -32000 // #8300
+006f78: 3729 eaff                              |00d6: if-le v9, v2, 00c0 // -0016
+006f7c: 1302 007d                              |00d8: const/16 v2, #int 32000 // #7d00
+006f80: 3529 e6ff                              |00da: if-ge v9, v2, 00c0 // -001a
+006f84: 1202                                   |00dc: const/4 v2, #int 0 // #0
+006f86: 0125                                   |00dd: move v5, v2
+006f88: 01d2                                   |00de: move v2, v13
+006f8a: d803 0eff                              |00df: add-int/lit8 v3, v14, #int -1 // #ff
+006f8e: 3435 6000                              |00e1: if-lt v5, v3, 0141 // +0060
+006f92: d806 0601                              |00e3: add-int/lit8 v6, v6, #int 1 // #01
+006f96: 012d                                   |00e5: move v13, v2
+006f98: 28d6                                   |00e6: goto 00bc // -002a
+006f9a: 0800 1700                              |00e7: move-object/from16 v0, v23
+006f9e: 7020 8500 c000                         |00e9: invoke-direct {v0, v12}, Lcom/google/android/checkers/a;.b:(I)V // method@0085
+006fa4: 1303 0180                              |00ec: const/16 v3, #int -32767 // #8001
+006fa8: 7b94                                   |00ee: neg-int v4, v9
+006faa: 1215                                   |00ef: const/4 v5, #int 1 // #1
+006fac: 1207                                   |00f0: const/4 v7, #int 0 // #0
+006fae: 0800 1700                              |00f1: move-object/from16 v0, v23
+006fb2: 5502 4d00                              |00f3: iget-boolean v2, v0, Lcom/google/android/checkers/a;.t:Z // field@004d
+006fb6: 3802 4a00                              |00f5: if-eqz v2, 013f // +004a
+006fba: 1208                                   |00f7: const/4 v8, #int 0 // #0
+006fbc: 0802 1700                              |00f8: move-object/from16 v2, v23
+006fc0: 7607 7400 0200                         |00fa: invoke-direct/range {v2, v3, v4, v5, v6, v7, v8}, Lcom/google/android/checkers/a;.a:(IIIIIZ)I // method@0074
+006fc6: 0a02                                   |00fd: move-result v2
+006fc8: 7b22                                   |00fe: neg-int v2, v2
+006fca: 0800 1700                              |00ff: move-object/from16 v0, v23
+006fce: 5403 4a00                              |0101: iget-object v3, v0, Lcom/google/android/checkers/a;.q:[I // field@004a
+006fd2: 4b02 030c                              |0103: aput v2, v3, v12
+006fd6: 0800 1700                              |0105: move-object/from16 v0, v23
+006fda: 590f 3d00                              |0107: iput v15, v0, Lcom/google/android/checkers/a;.d:I // field@003d
+006fde: 0200 1000                              |0109: move/from16 v0, v16
+006fe2: 0801 1700                              |010b: move-object/from16 v1, v23
+006fe6: 5910 3e00                              |010d: iput v0, v1, Lcom/google/android/checkers/a;.e:I // field@003e
+006fea: 0200 1100                              |010f: move/from16 v0, v17
+006fee: 0801 1700                              |0111: move-object/from16 v1, v23
+006ff2: 5910 3f00                              |0113: iput v0, v1, Lcom/google/android/checkers/a;.f:I // field@003f
+006ff6: 0200 1200                              |0115: move/from16 v0, v18
+006ffa: 0801 1700                              |0117: move-object/from16 v1, v23
+006ffe: 5910 4000                              |0119: iput v0, v1, Lcom/google/android/checkers/a;.g:I // field@0040
+007002: 0200 1300                              |011b: move/from16 v0, v19
+007006: 0801 1700                              |011d: move-object/from16 v1, v23
+00700a: 5910 4f00                              |011f: iput v0, v1, Lcom/google/android/checkers/a;.v:I // field@004f
+00700e: 0200 1400                              |0121: move/from16 v0, v20
+007012: 0801 1700                              |0123: move-object/from16 v1, v23
+007016: 5910 5000                              |0125: iput v0, v1, Lcom/google/android/checkers/a;.w:I // field@0050
+00701a: 0200 1500                              |0127: move/from16 v0, v21
+00701e: 0801 1700                              |0129: move-object/from16 v1, v23
+007022: 5910 5100                              |012b: iput v0, v1, Lcom/google/android/checkers/a;.x:I // field@0051
+007026: 0800 1700                              |012d: move-object/from16 v0, v23
+00702a: 5503 4600                              |012f: iget-boolean v3, v0, Lcom/google/android/checkers/a;.m:Z // field@0046
+00702e: 3903 8fff                              |0131: if-nez v3, 00c0 // -0071
+007032: 3792 d500                              |0133: if-le v2, v9, 0208 // +00d5
+007036: 0163                                   |0135: move v3, v6
+007038: 0124                                   |0136: move v4, v2
+00703a: 01c5                                   |0137: move v5, v12
+00703c: d80c 0c01                              |0138: add-int/lit8 v12, v12, #int 1 // #01
+007040: 0129                                   |013a: move v9, v2
+007042: 013a                                   |013b: move v10, v3
+007044: 014b                                   |013c: move v11, v4
+007046: 015d                                   |013d: move v13, v5
+007048: 2894                                   |013e: goto 00d2 // -006c
+00704a: 1218                                   |013f: const/4 v8, #int 1 // #1
+00704c: 28b8                                   |0140: goto 00f8 // -0048
+00704e: 1213                                   |0141: const/4 v3, #int 1 // #1
+007050: d804 0eff                              |0142: add-int/lit8 v4, v14, #int -1 // #ff
+007054: 3445 0800                              |0144: if-lt v5, v4, 014c // +0008
+007058: 3903 9dff                              |0146: if-nez v3, 00e3 // -0063
+00705c: d803 0501                              |0148: add-int/lit8 v3, v5, #int 1 // #01
+007060: 0135                                   |014a: move v5, v3
+007062: 2894                                   |014b: goto 00df // -006c
+007064: 0800 1700                              |014c: move-object/from16 v0, v23
+007068: 5407 4a00                              |014e: iget-object v7, v0, Lcom/google/android/checkers/a;.q:[I // field@004a
+00706c: 4407 0704                              |0150: aget v7, v7, v4
+007070: 0800 1700                              |0152: move-object/from16 v0, v23
+007074: 5408 4a00                              |0154: iget-object v8, v0, Lcom/google/android/checkers/a;.q:[I // field@004a
+007078: d809 04ff                              |0156: add-int/lit8 v9, v4, #int -1 // #ff
+00707c: 4408 0809                              |0158: aget v8, v8, v9
+007080: 3787 a800                              |015a: if-le v7, v8, 0202 // +00a8
+007084: 0800 1700                              |015c: move-object/from16 v0, v23
+007088: 5403 4a00                              |015e: iget-object v3, v0, Lcom/google/android/checkers/a;.q:[I // field@004a
+00708c: 4403 0304                              |0160: aget v3, v3, v4
+007090: 0800 1700                              |0162: move-object/from16 v0, v23
+007094: 5407 4a00                              |0164: iget-object v7, v0, Lcom/google/android/checkers/a;.q:[I // field@004a
+007098: 0800 1700                              |0166: move-object/from16 v0, v23
+00709c: 5408 4a00                              |0168: iget-object v8, v0, Lcom/google/android/checkers/a;.q:[I // field@004a
+0070a0: d809 04ff                              |016a: add-int/lit8 v9, v4, #int -1 // #ff
+0070a4: 4408 0809                              |016c: aget v8, v8, v9
+0070a8: 4b08 0704                              |016e: aput v8, v7, v4
+0070ac: 0800 1700                              |0170: move-object/from16 v0, v23
+0070b0: 5407 4a00                              |0172: iget-object v7, v0, Lcom/google/android/checkers/a;.q:[I // field@004a
+0070b4: d808 04ff                              |0174: add-int/lit8 v8, v4, #int -1 // #ff
+0070b8: 4b03 0708                              |0176: aput v3, v7, v8
+0070bc: 0800 1700                              |0178: move-object/from16 v0, v23
+0070c0: 5403 4800                              |017a: iget-object v3, v0, Lcom/google/android/checkers/a;.o:[I // field@0048
+0070c4: 4403 0304                              |017c: aget v3, v3, v4
+0070c8: 0800 1700                              |017e: move-object/from16 v0, v23
+0070cc: 5407 4800                              |0180: iget-object v7, v0, Lcom/google/android/checkers/a;.o:[I // field@0048
+0070d0: 0800 1700                              |0182: move-object/from16 v0, v23
+0070d4: 5408 4800                              |0184: iget-object v8, v0, Lcom/google/android/checkers/a;.o:[I // field@0048
+0070d8: d809 04ff                              |0186: add-int/lit8 v9, v4, #int -1 // #ff
+0070dc: 4408 0809                              |0188: aget v8, v8, v9
+0070e0: 4b08 0704                              |018a: aput v8, v7, v4
+0070e4: 0800 1700                              |018c: move-object/from16 v0, v23
+0070e8: 5407 4800                              |018e: iget-object v7, v0, Lcom/google/android/checkers/a;.o:[I // field@0048
+0070ec: d808 04ff                              |0190: add-int/lit8 v8, v4, #int -1 // #ff
+0070f0: 4b03 0708                              |0192: aput v3, v7, v8
+0070f4: 0800 1700                              |0194: move-object/from16 v0, v23
+0070f8: 5403 3a00                              |0196: iget-object v3, v0, Lcom/google/android/checkers/a;.a:[I // field@003a
+0070fc: 4403 0304                              |0198: aget v3, v3, v4
+007100: 0800 1700                              |019a: move-object/from16 v0, v23
+007104: 5407 3a00                              |019c: iget-object v7, v0, Lcom/google/android/checkers/a;.a:[I // field@003a
+007108: 0800 1700                              |019e: move-object/from16 v0, v23
+00710c: 5408 3a00                              |01a0: iget-object v8, v0, Lcom/google/android/checkers/a;.a:[I // field@003a
+007110: d809 04ff                              |01a2: add-int/lit8 v9, v4, #int -1 // #ff
+007114: 4408 0809                              |01a4: aget v8, v8, v9
+007118: 4b08 0704                              |01a6: aput v8, v7, v4
+00711c: 0800 1700                              |01a8: move-object/from16 v0, v23
+007120: 5407 3a00                              |01aa: iget-object v7, v0, Lcom/google/android/checkers/a;.a:[I // field@003a
+007124: d808 04ff                              |01ac: add-int/lit8 v8, v4, #int -1 // #ff
+007128: 4b03 0708                              |01ae: aput v3, v7, v8
+00712c: 0800 1700                              |01b0: move-object/from16 v0, v23
+007130: 5403 4900                              |01b2: iget-object v3, v0, Lcom/google/android/checkers/a;.p:[I // field@0049
+007134: 4403 0304                              |01b4: aget v3, v3, v4
+007138: 0800 1700                              |01b6: move-object/from16 v0, v23
+00713c: 5407 4900                              |01b8: iget-object v7, v0, Lcom/google/android/checkers/a;.p:[I // field@0049
+007140: 0800 1700                              |01ba: move-object/from16 v0, v23
+007144: 5408 4900                              |01bc: iget-object v8, v0, Lcom/google/android/checkers/a;.p:[I // field@0049
+007148: d809 04ff                              |01be: add-int/lit8 v9, v4, #int -1 // #ff
+00714c: 4408 0809                              |01c0: aget v8, v8, v9
+007150: 4b08 0704                              |01c2: aput v8, v7, v4
+007154: 0800 1700                              |01c4: move-object/from16 v0, v23
+007158: 5407 4900                              |01c6: iget-object v7, v0, Lcom/google/android/checkers/a;.p:[I // field@0049
+00715c: d808 04ff                              |01c8: add-int/lit8 v8, v4, #int -1 // #ff
+007160: 4b03 0708                              |01ca: aput v3, v7, v8
+007164: 0800 1700                              |01cc: move-object/from16 v0, v23
+007168: 5403 3b00                              |01ce: iget-object v3, v0, Lcom/google/android/checkers/a;.b:[I // field@003b
+00716c: 4403 0304                              |01d0: aget v3, v3, v4
+007170: 0800 1700                              |01d2: move-object/from16 v0, v23
+007174: 5407 3b00                              |01d4: iget-object v7, v0, Lcom/google/android/checkers/a;.b:[I // field@003b
+007178: 0800 1700                              |01d6: move-object/from16 v0, v23
+00717c: 5408 3b00                              |01d8: iget-object v8, v0, Lcom/google/android/checkers/a;.b:[I // field@003b
+007180: d809 04ff                              |01da: add-int/lit8 v9, v4, #int -1 // #ff
+007184: 4408 0809                              |01dc: aget v8, v8, v9
+007188: 4b08 0704                              |01de: aput v8, v7, v4
+00718c: 0800 1700                              |01e0: move-object/from16 v0, v23
+007190: 5407 3b00                              |01e2: iget-object v7, v0, Lcom/google/android/checkers/a;.b:[I // field@003b
+007194: d808 04ff                              |01e4: add-int/lit8 v8, v4, #int -1 // #ff
+007198: 4b03 0708                              |01e6: aput v3, v7, v8
+00719c: 3342 1300                              |01e8: if-ne v2, v4, 01fb // +0013
+0071a0: d802 02ff                              |01ea: add-int/lit8 v2, v2, #int -1 // #ff
+0071a4: 1203                                   |01ec: const/4 v3, #int 0 // #0
+0071a6: 0216 0300                              |01ed: move/from16 v22, v3
+0071aa: 0123                                   |01ef: move v3, v2
+0071ac: 0202 1600                              |01f0: move/from16 v2, v22
+0071b0: d804 04ff                              |01f2: add-int/lit8 v4, v4, #int -1 // #ff
+0071b4: 0216 0200                              |01f4: move/from16 v22, v2
+0071b8: 0132                                   |01f6: move v2, v3
+0071ba: 0203 1600                              |01f7: move/from16 v3, v22
+0071be: 2900 4bff                              |01f9: goto/16 0144 // -00b5
+0071c2: d803 04ff                              |01fb: add-int/lit8 v3, v4, #int -1 // #ff
+0071c6: 3332 efff                              |01fd: if-ne v2, v3, 01ec // -0011
+0071ca: d802 0201                              |01ff: add-int/lit8 v2, v2, #int 1 // #01
+0071ce: 28eb                                   |0201: goto 01ec // -0015
+0071d0: 0216 0300                              |0202: move/from16 v22, v3
+0071d4: 0123                                   |0204: move v3, v2
+0071d6: 0202 1600                              |0205: move/from16 v2, v22
+0071da: 28eb                                   |0207: goto 01f2 // -0015
+0071dc: 0192                                   |0208: move v2, v9
+0071de: 01a3                                   |0209: move v3, v10
+0071e0: 01b4                                   |020a: move v4, v11
+0071e2: 01d5                                   |020b: move v5, v13
+0071e4: 2900 2cff                              |020c: goto/16 0138 // -00d4
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  source_file_idx   : -1 (unknown)
+
+Class #3 header:
+class_idx           : 33
+access_flags        : 16 (0x0010)
+superclass_idx      : 46
+interfaces_off      : 29520 (0x007350)
+source_file_idx     : -1
+annotations_off     : 0 (0x000000)
+class_data_off      : 35082 (0x00890a)
+static_fields_size  : 0
+instance_fields_size: 1
+direct_methods_size : 1
+virtual_methods_size: 1
+
+Class #3            -
+  Class descriptor  : 'Lcom/google/android/checkers/b;'
+  Access flags      : 0x0010 (FINAL)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+    #0              : 'Landroid/content/DialogInterface$OnClickListener;'
+  Static fields     -
+  Instance fields   -
+    #0              : (in Lcom/google/android/checkers/b;)
+      name          : 'a'
+      type          : 'Lcom/google/android/checkers/CheckersView;'
+      access        : 0x1010 (FINAL SYNTHETIC)
+  Direct methods    -
+    #0              : (in Lcom/google/android/checkers/b;)
+      name          : '<init>'
+      type          : '(Lcom/google/android/checkers/CheckersView;)V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 143
+      code          -
+      registers     : 2
+      ins           : 2
+      outs          : 1
+      insns size    : 6 16-bit code units
+0071e8:                                        |[0071e8] com.google.android.checkers.b.<init>:(Lcom/google/android/checkers/CheckersView;)V
+0071f8: 5b01 5400                              |0000: iput-object v1, v0, Lcom/google/android/checkers/b;.a:Lcom/google/android/checkers/CheckersView; // field@0054
+0071fc: 7010 a000 0000                         |0002: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00a0
+007202: 0e00                                   |0005: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+    #0              : (in Lcom/google/android/checkers/b;)
+      name          : 'onClick'
+      type          : '(Landroid/content/DialogInterface;I)V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 144
+      code          -
+      registers     : 4
+      ins           : 3
+      outs          : 1
+      insns size    : 14 16-bit code units
+007204:                                        |[007204] com.google.android.checkers.b.onClick:(Landroid/content/DialogInterface;I)V
+007214: 5410 5400                              |0000: iget-object v0, v1, Lcom/google/android/checkers/b;.a:Lcom/google/android/checkers/CheckersView; // field@0054
+007218: 7110 5900 0000                         |0002: invoke-static {v0}, Lcom/google/android/checkers/CheckersView;.a:(Lcom/google/android/checkers/CheckersView;)Z // method@0059
+00721e: 0a00                                   |0005: move-result v0
+007220: 3800 0700                              |0006: if-eqz v0, 000d // +0007
+007224: 5410 5400                              |0008: iget-object v0, v1, Lcom/google/android/checkers/b;.a:Lcom/google/android/checkers/CheckersView; // field@0054
+007228: 6e10 6d00 0000                         |000a: invoke-virtual {v0}, Lcom/google/android/checkers/CheckersView;.postInvalidate:()V // method@006d
+00722e: 0e00                                   |000d: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  source_file_idx   : -1 (unknown)
+
+Class #4 header:
+class_idx           : 34
+access_flags        : 16 (0x0010)
+superclass_idx      : 46
+interfaces_off      : 29520 (0x007350)
+source_file_idx     : -1
+annotations_off     : 0 (0x000000)
+class_data_off      : 35103 (0x00891f)
+static_fields_size  : 0
+instance_fields_size: 1
+direct_methods_size : 1
+virtual_methods_size: 1
+
+Class #4            -
+  Class descriptor  : 'Lcom/google/android/checkers/c;'
+  Access flags      : 0x0010 (FINAL)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+    #0              : 'Landroid/content/DialogInterface$OnClickListener;'
+  Static fields     -
+  Instance fields   -
+    #0              : (in Lcom/google/android/checkers/c;)
+      name          : 'a'
+      type          : 'Lcom/google/android/checkers/CheckersView;'
+      access        : 0x1010 (FINAL SYNTHETIC)
+  Direct methods    -
+    #0              : (in Lcom/google/android/checkers/c;)
+      name          : '<init>'
+      type          : '(Lcom/google/android/checkers/CheckersView;)V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 145
+      code          -
+      registers     : 2
+      ins           : 2
+      outs          : 1
+      insns size    : 6 16-bit code units
+007230:                                        |[007230] com.google.android.checkers.c.<init>:(Lcom/google/android/checkers/CheckersView;)V
+007240: 5b01 5500                              |0000: iput-object v1, v0, Lcom/google/android/checkers/c;.a:Lcom/google/android/checkers/CheckersView; // field@0055
+007244: 7010 a000 0000                         |0002: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00a0
+00724a: 0e00                                   |0005: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+    #0              : (in Lcom/google/android/checkers/c;)
+      name          : 'onClick'
+      type          : '(Landroid/content/DialogInterface;I)V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 146
+      code          -
+      registers     : 3
+      ins           : 3
+      outs          : 0
+      insns size    : 1 16-bit code units
+00724c:                                        |[00724c] com.google.android.checkers.c.onClick:(Landroid/content/DialogInterface;I)V
+00725c: 0e00                                   |0000: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  source_file_idx   : -1 (unknown)
+
+Class #5 header:
+class_idx           : 35
+access_flags        : 16 (0x0010)
+superclass_idx      : 46
+interfaces_off      : 29520 (0x007350)
+source_file_idx     : -1
+annotations_off     : 0 (0x000000)
+class_data_off      : 35124 (0x008934)
+static_fields_size  : 0
+instance_fields_size: 1
+direct_methods_size : 1
+virtual_methods_size: 1
+
+Class #5            -
+  Class descriptor  : 'Lcom/google/android/checkers/d;'
+  Access flags      : 0x0010 (FINAL)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+    #0              : 'Landroid/content/DialogInterface$OnClickListener;'
+  Static fields     -
+  Instance fields   -
+    #0              : (in Lcom/google/android/checkers/d;)
+      name          : 'a'
+      type          : 'Lcom/google/android/checkers/CheckersView;'
+      access        : 0x1010 (FINAL SYNTHETIC)
+  Direct methods    -
+    #0              : (in Lcom/google/android/checkers/d;)
+      name          : '<init>'
+      type          : '(Lcom/google/android/checkers/CheckersView;)V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 147
+      code          -
+      registers     : 2
+      ins           : 2
+      outs          : 1
+      insns size    : 6 16-bit code units
+007260:                                        |[007260] com.google.android.checkers.d.<init>:(Lcom/google/android/checkers/CheckersView;)V
+007270: 5b01 5600                              |0000: iput-object v1, v0, Lcom/google/android/checkers/d;.a:Lcom/google/android/checkers/CheckersView; // field@0056
+007274: 7010 a000 0000                         |0002: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00a0
+00727a: 0e00                                   |0005: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+    #0              : (in Lcom/google/android/checkers/d;)
+      name          : 'onClick'
+      type          : '(Landroid/content/DialogInterface;I)V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 148
+      code          -
+      registers     : 3
+      ins           : 3
+      outs          : 0
+      insns size    : 1 16-bit code units
+00727c:                                        |[00727c] com.google.android.checkers.d.onClick:(Landroid/content/DialogInterface;I)V
+00728c: 0e00                                   |0000: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  source_file_idx   : -1 (unknown)
+
+Class #6 header:
+class_idx           : 36
+access_flags        : 16 (0x0010)
+superclass_idx      : 46
+interfaces_off      : 29520 (0x007350)
+source_file_idx     : -1
+annotations_off     : 0 (0x000000)
+class_data_off      : 35145 (0x008949)
+static_fields_size  : 0
+instance_fields_size: 1
+direct_methods_size : 1
+virtual_methods_size: 1
+
+Class #6            -
+  Class descriptor  : 'Lcom/google/android/checkers/e;'
+  Access flags      : 0x0010 (FINAL)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+    #0              : 'Landroid/content/DialogInterface$OnClickListener;'
+  Static fields     -
+  Instance fields   -
+    #0              : (in Lcom/google/android/checkers/e;)
+      name          : 'a'
+      type          : 'Lcom/google/android/checkers/CheckersView;'
+      access        : 0x1010 (FINAL SYNTHETIC)
+  Direct methods    -
+    #0              : (in Lcom/google/android/checkers/e;)
+      name          : '<init>'
+      type          : '(Lcom/google/android/checkers/CheckersView;)V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 149
+      code          -
+      registers     : 2
+      ins           : 2
+      outs          : 1
+      insns size    : 6 16-bit code units
+007290:                                        |[007290] com.google.android.checkers.e.<init>:(Lcom/google/android/checkers/CheckersView;)V
+0072a0: 5b01 5700                              |0000: iput-object v1, v0, Lcom/google/android/checkers/e;.a:Lcom/google/android/checkers/CheckersView; // field@0057
+0072a4: 7010 a000 0000                         |0002: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00a0
+0072aa: 0e00                                   |0005: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+    #0              : (in Lcom/google/android/checkers/e;)
+      name          : 'onClick'
+      type          : '(Landroid/content/DialogInterface;I)V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 150
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 2
+      insns size    : 7 16-bit code units
+0072ac:                                        |[0072ac] com.google.android.checkers.e.onClick:(Landroid/content/DialogInterface;I)V
+0072bc: 5420 5700                              |0000: iget-object v0, v2, Lcom/google/android/checkers/e;.a:Lcom/google/android/checkers/CheckersView; // field@0057
+0072c0: 1211                                   |0002: const/4 v1, #int 1 // #1
+0072c2: 6e20 6800 1000                         |0003: invoke-virtual {v0, v1}, Lcom/google/android/checkers/CheckersView;.e:(Z)Z // method@0068
+0072c8: 0e00                                   |0006: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  source_file_idx   : -1 (unknown)
+
+Class #7 header:
+class_idx           : 37
+access_flags        : 16 (0x0010)
+superclass_idx      : 46
+interfaces_off      : 29520 (0x007350)
+source_file_idx     : -1
+annotations_off     : 0 (0x000000)
+class_data_off      : 35166 (0x00895e)
+static_fields_size  : 0
+instance_fields_size: 1
+direct_methods_size : 1
+virtual_methods_size: 1
+
+Class #7            -
+  Class descriptor  : 'Lcom/google/android/checkers/f;'
+  Access flags      : 0x0010 (FINAL)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+    #0              : 'Landroid/content/DialogInterface$OnClickListener;'
+  Static fields     -
+  Instance fields   -
+    #0              : (in Lcom/google/android/checkers/f;)
+      name          : 'a'
+      type          : 'Lcom/google/android/checkers/CheckersView;'
+      access        : 0x1010 (FINAL SYNTHETIC)
+  Direct methods    -
+    #0              : (in Lcom/google/android/checkers/f;)
+      name          : '<init>'
+      type          : '(Lcom/google/android/checkers/CheckersView;)V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 151
+      code          -
+      registers     : 2
+      ins           : 2
+      outs          : 1
+      insns size    : 6 16-bit code units
+0072cc:                                        |[0072cc] com.google.android.checkers.f.<init>:(Lcom/google/android/checkers/CheckersView;)V
+0072dc: 5b01 5800                              |0000: iput-object v1, v0, Lcom/google/android/checkers/f;.a:Lcom/google/android/checkers/CheckersView; // field@0058
+0072e0: 7010 a000 0000                         |0002: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00a0
+0072e6: 0e00                                   |0005: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+    #0              : (in Lcom/google/android/checkers/f;)
+      name          : 'onClick'
+      type          : '(Landroid/content/DialogInterface;I)V'
+      access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 152
+      code          -
+      registers     : 4
+      ins           : 3
+      outs          : 2
+      insns size    : 6 16-bit code units
+0072e8:                                        |[0072e8] com.google.android.checkers.f.onClick:(Landroid/content/DialogInterface;I)V
+0072f8: 5410 5800                              |0000: iget-object v0, v1, Lcom/google/android/checkers/f;.a:Lcom/google/android/checkers/CheckersView; // field@0058
+0072fc: 7120 5600 3000                         |0002: invoke-static {v0, v3}, Lcom/google/android/checkers/CheckersView;.a:(Lcom/google/android/checkers/CheckersView;I)V // method@0056
+007302: 0e00                                   |0005: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  source_file_idx   : -1 (unknown)
+
+Class #8 header:
+class_idx           : 38
+access_flags        : 17 (0x0011)
+superclass_idx      : 46
+interfaces_off      : 0 (0x000000)
+source_file_idx     : -1
+annotations_off     : 0 (0x000000)
+class_data_off      : 35187 (0x008973)
+static_fields_size  : 19
+instance_fields_size: 0
+direct_methods_size : 1
+virtual_methods_size: 0
+
+Class #8            -
+  Class descriptor  : 'Lcom/google/android/checkers/g;'
+  Access flags      : 0x0011 (PUBLIC FINAL)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+  Static fields     -
+    #0              : (in Lcom/google/android/checkers/g;)
+      name          : 'a'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #1              : (in Lcom/google/android/checkers/g;)
+      name          : 'b'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #2              : (in Lcom/google/android/checkers/g;)
+      name          : 'c'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #3              : (in Lcom/google/android/checkers/g;)
+      name          : 'd'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #4              : (in Lcom/google/android/checkers/g;)
+      name          : 'e'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #5              : (in Lcom/google/android/checkers/g;)
+      name          : 'f'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #6              : (in Lcom/google/android/checkers/g;)
+      name          : 'g'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #7              : (in Lcom/google/android/checkers/g;)
+      name          : 'h'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #8              : (in Lcom/google/android/checkers/g;)
+      name          : 'i'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #9              : (in Lcom/google/android/checkers/g;)
+      name          : 'j'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #10              : (in Lcom/google/android/checkers/g;)
+      name          : 'k'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #11              : (in Lcom/google/android/checkers/g;)
+      name          : 'l'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #12              : (in Lcom/google/android/checkers/g;)
+      name          : 'm'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #13              : (in Lcom/google/android/checkers/g;)
+      name          : 'n'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #14              : (in Lcom/google/android/checkers/g;)
+      name          : 'o'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #15              : (in Lcom/google/android/checkers/g;)
+      name          : 'p'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #16              : (in Lcom/google/android/checkers/g;)
+      name          : 'q'
+      type          : '[B'
+      access        : 0x0009 (PUBLIC STATIC)
+    #17              : (in Lcom/google/android/checkers/g;)
+      name          : 'r'
+      type          : 'Z'
+      access        : 0x0009 (PUBLIC STATIC)
+    #18              : (in Lcom/google/android/checkers/g;)
+      name          : 's'
+      type          : 'Ljava/io/BufferedInputStream;'
+      access        : 0x0008 (STATIC)
+  Instance fields   -
+  Direct methods    -
+    #0              : (in Lcom/google/android/checkers/g;)
+      name          : 'a'
+      type          : '([B)Z'
+      access        : 0x0008 (STATIC)
+      method_idx    : 153
+      code          -
+      registers     : 5
+      ins           : 1
+      outs          : 2
+      insns size    : 29 16-bit code units
+007304:                                        |[007304] com.google.android.checkers.g.a:([B)Z
+007314: 2141                                   |0000: array-length v1, v4
+007316: 1200                                   |0001: const/4 v0, #int 0 // #0
+007318: 3410 0400                              |0002: if-lt v0, v1, 0006 // +0004
+00731c: 1210                                   |0004: const/4 v0, #int 1 // #1
+00731e: 0f00                                   |0005: return v0
+007320: 6202 6b00                              |0006: sget-object v2, Lcom/google/android/checkers/g;.s:Ljava/io/BufferedInputStream; // field@006b
+007324: 6e10 9c00 0200                         |0008: invoke-virtual {v2}, Ljava/io/BufferedInputStream;.read:()I // method@009c
+00732a: 0a02                                   |000b: move-result v2
+00732c: 12f3                                   |000c: const/4 v3, #int -1 // #ff
+00732e: 3332 0a00                              |000d: if-ne v2, v3, 0017 // +000a
+007332: 2200 2b00                              |000f: new-instance v0, Ljava/lang/Exception; // type@002b
+007336: 1a01 3401                              |0011: const-string v1, "tb eof" // string@0134
+00733a: 7020 9d00 1000                         |0013: invoke-direct {v0, v1}, Ljava/lang/Exception;.<init>:(Ljava/lang/String;)V // method@009d
+007340: 2700                                   |0016: throw v0
+007342: 8d22                                   |0017: int-to-byte v2, v2
+007344: 4f02 0400                              |0018: aput-byte v2, v4, v0
+007348: d800 0001                              |001a: add-int/lit8 v0, v0, #int 1 // #01
+00734c: 28e6                                   |001c: goto 0002 // -001a
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+  source_file_idx   : -1 (unknown)
+
+Opened 'all-dex-files.jar:classes3.dex', DEX version '039'
+DEX file header:
+magic               : 'dex\n039\0'
+checksum            : 16656a27
+signature           : 1953...5aa5
+file_size           : 2524
+header_size         : 112
+link_size           : 0
+link_off            : 0 (0x000000)
+string_ids_size     : 57
+string_ids_off      : 112 (0x000070)
+type_ids_size       : 26
+type_ids_off        : 340 (0x000154)
+proto_ids_size      : 18
+proto_ids_off       : 444 (0x0001bc)
+field_ids_size      : 2
+field_ids_off       : 660 (0x000294)
+method_ids_size     : 23
+method_ids_off      : 676 (0x0002a4)
+class_defs_size     : 2
+class_defs_off      : 860 (0x00035c)
+data_size           : 1588
+data_off            : 936 (0x0003a8)
+
+Class #0 header:
+class_idx           : 5
+access_flags        : 1 (0x0001)
+superclass_idx      : 11
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 29
+annotations_off     : 1336 (0x000538)
+class_data_off      : 2270 (0x0008de)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 2
+virtual_methods_size: 0
+
+Class #0 annotations:
+Annotations on method #1 'main'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #0            -
+  Class descriptor  : 'LMain;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LMain;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 0
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+0003b0:                                        |[0003b0] Main.<init>:()V
+0003c0: 7010 0a00 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@000a
+0003c6: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=22
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LMain; 
+
+    #1              : (in LMain;)
+      name          : 'main'
+      type          : '([Ljava/lang/String;)V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 1
+      code          -
+      registers     : 6
+      ins           : 1
+      outs          : 4
+      insns size    : 25 16-bit code units
+0003c8:                                        |[0003c8] Main.main:([Ljava/lang/String;)V
+0003d8: 7100 1500 0000                         |0000: invoke-static {}, Ljava/lang/invoke/MethodHandles;.lookup:()Ljava/lang/invoke/MethodHandles$Lookup; // method@0015
+0003de: 0c00                                   |0003: move-result-object v0
+0003e0: 1c01 0600                              |0004: const-class v1, Lconstmethodhandle/ConstTest; // type@0006
+0003e4: 1a02 3000                              |0006: const-string v2, "main" // string@0030
+0003e8: 6203 0100                              |0008: sget-object v3, Ljava/lang/Void;.TYPE:Ljava/lang/Class; // field@0001
+0003ec: 1c04 1900                              |000a: const-class v4, [Ljava/lang/String; // type@0019
+0003f0: 7120 1600 4300                         |000c: invoke-static {v3, v4}, Ljava/lang/invoke/MethodType;.methodType:(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodType; // method@0016
+0003f6: 0c03                                   |000f: move-result-object v3
+0003f8: 6e40 1400 1032                         |0010: invoke-virtual {v0, v1, v2, v3}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@0014
+0003fe: 0c00                                   |0013: move-result-object v0
+000400: fa20 1200 5000 1000                    |0014: invoke-polymorphic {v0, v5}, Ljava/lang/invoke/MethodHandle;.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, ([Ljava/lang/String;)V // method@0012, proto@0010
+000408: 0e00                                   |0018: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=26
+        0x000c line=27
+        0x0014 line=28
+        0x0018 line=29
+      locals        : 
+        0x0000 - 0x0019 reg=5 (null) [Ljava/lang/String; 
+
+  Virtual methods   -
+  source_file_idx   : 29 (Main.java)
+
+Class #1 header:
+class_idx           : 6
+access_flags        : 1 (0x0001)
+superclass_idx      : 11
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 3
+annotations_off     : 1360 (0x000550)
+class_data_off      : 2284 (0x0008ec)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 6
+virtual_methods_size: 0
+
+Class #1 annotations:
+Annotations on method #3 'displayMethodHandle'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #1            -
+  Class descriptor  : 'Lconstmethodhandle/ConstTest;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in Lconstmethodhandle/ConstTest;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 2
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+00040c:                                        |[00040c] constmethodhandle.ConstTest.<init>:()V
+00041c: 7010 0a00 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@000a
+000422: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=22
+      locals        : 
+        0x0000 - 0x0004 reg=0 this Lconstmethodhandle/ConstTest; 
+
+    #1              : (in Lconstmethodhandle/ConstTest;)
+      name          : 'displayMethodHandle'
+      type          : '(Ljava/lang/invoke/MethodHandle;)V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 3
+      code          -
+      registers     : 4
+      ins           : 1
+      outs          : 2
+      insns size    : 47 16-bit code units
+000424:                                        |[000424] constmethodhandle.ConstTest.displayMethodHandle:(Ljava/lang/invoke/MethodHandle;)V
+000434: 6200 0000                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000
+000438: 2201 0d00                              |0002: new-instance v1, Ljava/lang/StringBuilder; // type@000d
+00043c: 7010 0c00 0100                         |0004: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@000c
+000442: 1a02 1e00                              |0007: const-string v2, "MethodHandle " // string@001e
+000446: 6e20 0e00 2100                         |0009: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@000e
+00044c: 0c01                                   |000c: move-result-object v1
+00044e: 6e20 0d00 3100                         |000d: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@000d
+000454: 0c01                                   |0010: move-result-object v1
+000456: 1a02 0000                              |0011: const-string v2, " => " // string@0000
+00045a: 6e20 0e00 2100                         |0013: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@000e
+000460: 0c01                                   |0016: move-result-object v1
+000462: 1402 0030 4046                         |0017: const v2, #float 12300 // #46403000
+000468: 7110 0900 0200                         |001a: invoke-static {v2}, Ljava/lang/Float;.valueOf:(F)Ljava/lang/Float; // method@0009
+00046e: 0c02                                   |001d: move-result-object v2
+000470: fa20 1100 2300 0100                    |001e: invoke-polymorphic {v3, v2}, Ljava/lang/invoke/MethodHandle;.invoke:([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/Object;)Ljava/lang/Class; // method@0011, proto@0001
+000478: 0c02                                   |0022: move-result-object v2
+00047a: 6e20 0d00 2100                         |0023: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@000d
+000480: 0c01                                   |0026: move-result-object v1
+000482: 6e10 0f00 0100                         |0027: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@000f
+000488: 0c01                                   |002a: move-result-object v1
+00048a: 6e20 0800 1000                         |002b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0008
+000490: 0e00                                   |002e: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=24
+        0x001a line=25
+        0x002b line=24
+        0x002e line=26
+      locals        : 
+        0x0000 - 0x002f reg=3 (null) Ljava/lang/invoke/MethodHandle; 
+
+    #2              : (in Lconstmethodhandle/ConstTest;)
+      name          : 'displayMethodType'
+      type          : '(Ljava/lang/invoke/MethodType;)V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 4
+      code          -
+      registers     : 4
+      ins           : 1
+      outs          : 2
+      insns size    : 25 16-bit code units
+000494:                                        |[000494] constmethodhandle.ConstTest.displayMethodType:(Ljava/lang/invoke/MethodType;)V
+0004a4: 6200 0000                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000
+0004a8: 2201 0d00                              |0002: new-instance v1, Ljava/lang/StringBuilder; // type@000d
+0004ac: 7010 0c00 0100                         |0004: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@000c
+0004b2: 1a02 1f00                              |0007: const-string v2, "MethodType " // string@001f
+0004b6: 6e20 0e00 2100                         |0009: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@000e
+0004bc: 0c01                                   |000c: move-result-object v1
+0004be: 6e20 0d00 3100                         |000d: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@000d
+0004c4: 0c01                                   |0010: move-result-object v1
+0004c6: 6e10 0f00 0100                         |0011: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@000f
+0004cc: 0c01                                   |0014: move-result-object v1
+0004ce: 6e20 0800 1000                         |0015: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0008
+0004d4: 0e00                                   |0018: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=29
+        0x0018 line=30
+      locals        : 
+        0x0000 - 0x0019 reg=3 (null) Ljava/lang/invoke/MethodType; 
+
+    #3              : (in Lconstmethodhandle/ConstTest;)
+      name          : 'main'
+      type          : '([Ljava/lang/String;)V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 5
+      code          -
+      registers     : 2
+      ins           : 1
+      outs          : 1
+      insns size    : 15 16-bit code units
+0004d8:                                        |[0004d8] constmethodhandle.ConstTest.main:([Ljava/lang/String;)V
+0004e8: 7100 0600 0000                         |0000: invoke-static {}, Lconstmethodhandle/ConstTest;.test1:()Ljava/lang/invoke/MethodHandle; // method@0006
+0004ee: 0c00                                   |0003: move-result-object v0
+0004f0: 7110 0300 0000                         |0004: invoke-static {v0}, Lconstmethodhandle/ConstTest;.displayMethodHandle:(Ljava/lang/invoke/MethodHandle;)V // method@0003
+0004f6: 7100 0700 0000                         |0007: invoke-static {}, Lconstmethodhandle/ConstTest;.test2:()Ljava/lang/invoke/MethodType; // method@0007
+0004fc: 0c00                                   |000a: move-result-object v0
+0004fe: 7110 0400 0000                         |000b: invoke-static {v0}, Lconstmethodhandle/ConstTest;.displayMethodType:(Ljava/lang/invoke/MethodType;)V // method@0004
+000504: 0e00                                   |000e: return-void
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #4              : (in Lconstmethodhandle/ConstTest;)
+      name          : 'test1'
+      type          : '()Ljava/lang/invoke/MethodHandle;'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 6
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 3 16-bit code units
+000508:                                        |[000508] constmethodhandle.ConstTest.test1:()Ljava/lang/invoke/MethodHandle;
+000518: fe00 0000                              |0000: const-method-handle v0, method_handle@0000
+00051c: 1100                                   |0002: return-object v0
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+    #5              : (in Lconstmethodhandle/ConstTest;)
+      name          : 'test2'
+      type          : '()Ljava/lang/invoke/MethodType;'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 7
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 3 16-bit code units
+000520:                                        |[000520] constmethodhandle.ConstTest.test2:()Ljava/lang/invoke/MethodType;
+000530: ff00 1100                              |0000: const-method-type v0, (CSIJFDLjava/lang/Object;)Z // proto@0011
+000534: 1100                                   |0002: return-object v0
+      catches       : (none)
+      positions     : 
+      locals        : 
+
+  Virtual methods   -
+  source_file_idx   : 3 (ConstTest.java)
+
+Method handle #0:
+  type        : invoke-instance
+  target      : Ljava/lang/Object; getClass
+  target_type : (Ljava/lang/Object;)Ljava/lang/Class;
+Opened 'all-dex-files.jar:classes4.dex', DEX version '038'
+DEX file header:
+magic               : 'dex\n038\0'
+checksum            : dc722174
+signature           : b59a...f803
+file_size           : 31732
+header_size         : 112
+link_size           : 0
+link_off            : 0 (0x000000)
+string_ids_size     : 478
+string_ids_off      : 112 (0x000070)
+type_ids_size       : 77
+type_ids_off        : 2024 (0x0007e8)
+proto_ids_size      : 91
+proto_ids_off       : 2332 (0x00091c)
+field_ids_size      : 21
+field_ids_off       : 3424 (0x000d60)
+method_ids_size     : 243
+method_ids_off      : 3592 (0x000e08)
+class_defs_size     : 14
+class_defs_off      : 5536 (0x0015a0)
+data_size           : 25332
+data_off            : 6400 (0x001900)
+
+Class #0 header:
+class_idx           : 7
+access_flags        : 0 (0x0000)
+superclass_idx      : 52
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 144
+annotations_off     : 30700 (0x0077ec)
+class_data_off      : 28922 (0x0070fa)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 1
+virtual_methods_size: 0
+
+Class #0 annotations:
+Annotations on class
+  VISIBILITY_SYSTEM Ldalvik/annotation/EnclosingClass; value=LTestBadBootstrapArguments;
+  VISIBILITY_SYSTEM Ldalvik/annotation/InnerClass; accessFlags=8 name="TestersConstantCallSite"
+
+Class #0            -
+  Class descriptor  : 'LTestBadBootstrapArguments$TestersConstantCallSite;'
+  Access flags      : 0x0000 ()
+  Superclass        : 'Ljava/lang/invoke/ConstantCallSite;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTestBadBootstrapArguments$TestersConstantCallSite;)
+      name          : '<init>'
+      type          : '(Ljava/lang/invoke/MethodHandle;)V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 8
+      code          -
+      registers     : 2
+      ins           : 2
+      outs          : 2
+      insns size    : 4 16-bit code units
+001b18:                                        |[001b18] TestBadBootstrapArguments$TestersConstantCallSite.<init>:(Ljava/lang/invoke/MethodHandle;)V
+001b28: 7020 d200 1000                         |0000: invoke-direct {v0, v1}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+001b2e: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=449
+        0x0003 line=450
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestBadBootstrapArguments$TestersConstantCallSite; 
+        0x0000 - 0x0004 reg=1 mh Ljava/lang/invoke/MethodHandle; 
+
+  Virtual methods   -
+  source_file_idx   : 144 (TestBadBootstrapArguments.java)
+
+Class #1 header:
+class_idx           : 9
+access_flags        : 1024 (0x0400)
+superclass_idx      : 42
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 145
+annotations_off     : 0 (0x000000)
+class_data_off      : 28932 (0x007104)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 13
+virtual_methods_size: 0
+
+Class #1            -
+  Class descriptor  : 'LTestBase;'
+  Access flags      : 0x0400 (ABSTRACT)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTestBase;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 50
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+002544:                                        |[002544] TestBase.<init>:()V
+002554: 7010 bf00 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00bf
+00255a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=19
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestBase; 
+
+    #1              : (in LTestBase;)
+      name          : 'assertEquals'
+      type          : '(BB)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 51
+      code          -
+      registers     : 5
+      ins           : 2
+      outs          : 2
+      insns size    : 34 16-bit code units
+00255c:                                        |[00255c] TestBase.assertEquals:(BB)V
+00256c: 3343 0300                              |0000: if-ne v3, v4, 0003 // +0003
+002570: 0e00                                   |0002: return-void
+002572: 2200 1e00                              |0003: new-instance v0, Ljava/lang/AssertionError; // type@001e
+002576: 2201 2d00                              |0005: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+00257a: 7010 c100 0100                         |0007: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+002580: 1a02 d300                              |000a: const-string v2, "assertEquals b1: " // string@00d3
+002584: 6e20 c800 2100                         |000c: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00258a: 6e20 c500 3100                         |000f: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+002590: 1a02 0d00                              |0012: const-string v2, ", b2: " // string@000d
+002594: 6e20 c800 2100                         |0014: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00259a: 6e20 c500 4100                         |0017: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0025a0: 6e10 ca00 0100                         |001a: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0025a6: 0c01                                   |001d: move-result-object v1
+0025a8: 7020 b500 1000                         |001e: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+0025ae: 2700                                   |0021: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=27
+        0x0002 line=28
+        0x0003 line=30
+      locals        : 
+        0x0000 - 0x0022 reg=3 b1 B 
+        0x0000 - 0x0022 reg=4 b2 B 
+
+    #2              : (in LTestBase;)
+      name          : 'assertEquals'
+      type          : '(CC)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 52
+      code          -
+      registers     : 5
+      ins           : 2
+      outs          : 2
+      insns size    : 34 16-bit code units
+0025b0:                                        |[0025b0] TestBase.assertEquals:(CC)V
+0025c0: 3343 0300                              |0000: if-ne v3, v4, 0003 // +0003
+0025c4: 0e00                                   |0002: return-void
+0025c6: 2200 1e00                              |0003: new-instance v0, Ljava/lang/AssertionError; // type@001e
+0025ca: 2201 2d00                              |0005: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+0025ce: 7010 c100 0100                         |0007: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0025d4: 1a02 d400                              |000a: const-string v2, "assertEquals c1: " // string@00d4
+0025d8: 6e20 c800 2100                         |000c: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0025de: 6e20 c200 3100                         |000f: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(C)Ljava/lang/StringBuilder; // method@00c2
+0025e4: 1a02 0e00                              |0012: const-string v2, ", c2: " // string@000e
+0025e8: 6e20 c800 2100                         |0014: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0025ee: 6e20 c200 4100                         |0017: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(C)Ljava/lang/StringBuilder; // method@00c2
+0025f4: 6e10 ca00 0100                         |001a: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0025fa: 0c01                                   |001d: move-result-object v1
+0025fc: 7020 b500 1000                         |001e: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+002602: 2700                                   |0021: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=34
+        0x0002 line=35
+        0x0003 line=37
+      locals        : 
+        0x0000 - 0x0022 reg=3 c1 C 
+        0x0000 - 0x0022 reg=4 c2 C 
+
+    #3              : (in LTestBase;)
+      name          : 'assertEquals'
+      type          : '(DD)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 53
+      code          -
+      registers     : 7
+      ins           : 4
+      outs          : 3
+      insns size    : 36 16-bit code units
+002604:                                        |[002604] TestBase.assertEquals:(DD)V
+002614: 2f00 0305                              |0000: cmpl-double v0, v3, v5
+002618: 3900 0300                              |0002: if-nez v0, 0005 // +0003
+00261c: 0e00                                   |0004: return-void
+00261e: 2200 1e00                              |0005: new-instance v0, Ljava/lang/AssertionError; // type@001e
+002622: 2201 2d00                              |0007: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+002626: 7010 c100 0100                         |0009: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00262c: 1a02 d500                              |000c: const-string v2, "assertEquals d1: " // string@00d5
+002630: 6e20 c800 2100                         |000e: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002636: 6e30 c300 3104                         |0011: invoke-virtual {v1, v3, v4}, Ljava/lang/StringBuilder;.append:(D)Ljava/lang/StringBuilder; // method@00c3
+00263c: 1a02 0f00                              |0014: const-string v2, ", d2: " // string@000f
+002640: 6e20 c800 2100                         |0016: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002646: 6e30 c300 5106                         |0019: invoke-virtual {v1, v5, v6}, Ljava/lang/StringBuilder;.append:(D)Ljava/lang/StringBuilder; // method@00c3
+00264c: 6e10 ca00 0100                         |001c: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+002652: 0c01                                   |001f: move-result-object v1
+002654: 7020 b500 1000                         |0020: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+00265a: 2700                                   |0023: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=69
+        0x0004 line=70
+        0x0005 line=72
+      locals        : 
+        0x0000 - 0x0024 reg=3 d1 D 
+        0x0000 - 0x0024 reg=5 d2 D 
+
+    #4              : (in LTestBase;)
+      name          : 'assertEquals'
+      type          : '(FF)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 54
+      code          -
+      registers     : 5
+      ins           : 2
+      outs          : 2
+      insns size    : 36 16-bit code units
+00265c:                                        |[00265c] TestBase.assertEquals:(FF)V
+00266c: 2d00 0304                              |0000: cmpl-float v0, v3, v4
+002670: 3900 0300                              |0002: if-nez v0, 0005 // +0003
+002674: 0e00                                   |0004: return-void
+002676: 2200 1e00                              |0005: new-instance v0, Ljava/lang/AssertionError; // type@001e
+00267a: 2201 2d00                              |0007: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+00267e: 7010 c100 0100                         |0009: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+002684: 1a02 d600                              |000c: const-string v2, "assertEquals f1: " // string@00d6
+002688: 6e20 c800 2100                         |000e: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00268e: 6e20 c400 3100                         |0011: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(F)Ljava/lang/StringBuilder; // method@00c4
+002694: 1a02 1000                              |0014: const-string v2, ", f2: " // string@0010
+002698: 6e20 c800 2100                         |0016: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00269e: 6e20 c400 4100                         |0019: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(F)Ljava/lang/StringBuilder; // method@00c4
+0026a4: 6e10 ca00 0100                         |001c: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0026aa: 0c01                                   |001f: move-result-object v1
+0026ac: 7020 b500 1000                         |0020: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+0026b2: 2700                                   |0023: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=62
+        0x0004 line=63
+        0x0005 line=65
+      locals        : 
+        0x0000 - 0x0024 reg=3 f1 F 
+        0x0000 - 0x0024 reg=4 f2 F 
+
+    #5              : (in LTestBase;)
+      name          : 'assertEquals'
+      type          : '(II)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 55
+      code          -
+      registers     : 5
+      ins           : 2
+      outs          : 2
+      insns size    : 34 16-bit code units
+0026b4:                                        |[0026b4] TestBase.assertEquals:(II)V
+0026c4: 3343 0300                              |0000: if-ne v3, v4, 0003 // +0003
+0026c8: 0e00                                   |0002: return-void
+0026ca: 2200 1e00                              |0003: new-instance v0, Ljava/lang/AssertionError; // type@001e
+0026ce: 2201 2d00                              |0005: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+0026d2: 7010 c100 0100                         |0007: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0026d8: 1a02 d700                              |000a: const-string v2, "assertEquals i1: " // string@00d7
+0026dc: 6e20 c800 2100                         |000c: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0026e2: 6e20 c500 3100                         |000f: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0026e8: 1a02 1100                              |0012: const-string v2, ", i2: " // string@0011
+0026ec: 6e20 c800 2100                         |0014: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0026f2: 6e20 c500 4100                         |0017: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0026f8: 6e10 ca00 0100                         |001a: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0026fe: 0c01                                   |001d: move-result-object v1
+002700: 7020 b500 1000                         |001e: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+002706: 2700                                   |0021: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=48
+        0x0002 line=49
+        0x0003 line=51
+      locals        : 
+        0x0000 - 0x0022 reg=3 i1 I 
+        0x0000 - 0x0022 reg=4 i2 I 
+
+    #6              : (in LTestBase;)
+      name          : 'assertEquals'
+      type          : '(JJ)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 56
+      code          -
+      registers     : 7
+      ins           : 4
+      outs          : 3
+      insns size    : 36 16-bit code units
+002764:                                        |[002764] TestBase.assertEquals:(JJ)V
+002774: 3100 0305                              |0000: cmp-long v0, v3, v5
+002778: 3900 0300                              |0002: if-nez v0, 0005 // +0003
+00277c: 0e00                                   |0004: return-void
+00277e: 2200 1e00                              |0005: new-instance v0, Ljava/lang/AssertionError; // type@001e
+002782: 2201 2d00                              |0007: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+002786: 7010 c100 0100                         |0009: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00278c: 1a02 d800                              |000c: const-string v2, "assertEquals l1: " // string@00d8
+002790: 6e20 c800 2100                         |000e: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002796: 6e30 c600 3104                         |0011: invoke-virtual {v1, v3, v4}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@00c6
+00279c: 1a02 1200                              |0014: const-string v2, ", l2: " // string@0012
+0027a0: 6e20 c800 2100                         |0016: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0027a6: 6e30 c600 5106                         |0019: invoke-virtual {v1, v5, v6}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@00c6
+0027ac: 6e10 ca00 0100                         |001c: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0027b2: 0c01                                   |001f: move-result-object v1
+0027b4: 7020 b500 1000                         |0020: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+0027ba: 2700                                   |0023: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=55
+        0x0004 line=56
+        0x0005 line=58
+      locals        : 
+        0x0000 - 0x0024 reg=3 l1 J 
+        0x0000 - 0x0024 reg=5 l2 J 
+
+    #7              : (in LTestBase;)
+      name          : 'assertEquals'
+      type          : '(Ljava/lang/Object;Ljava/lang/Object;)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 57
+      code          -
+      registers     : 5
+      ins           : 2
+      outs          : 2
+      insns size    : 38 16-bit code units
+002708:                                        |[002708] TestBase.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V
+002718: 7120 ec00 4300                         |0000: invoke-static {v3, v4}, Ljava/util/Objects;.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z // method@00ec
+00271e: 0a00                                   |0003: move-result v0
+002720: 3800 0300                              |0004: if-eqz v0, 0007 // +0003
+002724: 0e00                                   |0006: return-void
+002726: 2200 1e00                              |0007: new-instance v0, Ljava/lang/AssertionError; // type@001e
+00272a: 2201 2d00                              |0009: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+00272e: 7010 c100 0100                         |000b: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+002734: 1a02 da00                              |000e: const-string v2, "assertEquals: o1: " // string@00da
+002738: 6e20 c800 2100                         |0010: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00273e: 6e20 c700 3100                         |0013: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+002744: 1a02 1300                              |0016: const-string v2, ", o2: " // string@0013
+002748: 6e20 c800 2100                         |0018: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00274e: 6e20 c700 4100                         |001b: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+002754: 6e10 ca00 0100                         |001e: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+00275a: 0c01                                   |0021: move-result-object v1
+00275c: 7020 b500 1000                         |0022: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+002762: 2700                                   |0025: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=76
+        0x0006 line=79
+        0x0007 line=77
+      locals        : 
+        0x0000 - 0x0026 reg=3 o Ljava/lang/Object; 
+        0x0000 - 0x0026 reg=4 p Ljava/lang/Object; 
+
+    #8              : (in LTestBase;)
+      name          : 'assertEquals'
+      type          : '(SS)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 58
+      code          -
+      registers     : 5
+      ins           : 2
+      outs          : 2
+      insns size    : 34 16-bit code units
+0027bc:                                        |[0027bc] TestBase.assertEquals:(SS)V
+0027cc: 3343 0300                              |0000: if-ne v3, v4, 0003 // +0003
+0027d0: 0e00                                   |0002: return-void
+0027d2: 2200 1e00                              |0003: new-instance v0, Ljava/lang/AssertionError; // type@001e
+0027d6: 2201 2d00                              |0005: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+0027da: 7010 c100 0100                         |0007: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0027e0: 1a02 d900                              |000a: const-string v2, "assertEquals s1: " // string@00d9
+0027e4: 6e20 c800 2100                         |000c: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0027ea: 6e20 c500 3100                         |000f: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0027f0: 1a02 1400                              |0012: const-string v2, ", s2: " // string@0014
+0027f4: 6e20 c800 2100                         |0014: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0027fa: 6e20 c500 4100                         |0017: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+002800: 6e10 ca00 0100                         |001a: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+002806: 0c01                                   |001d: move-result-object v1
+002808: 7020 b500 1000                         |001e: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+00280e: 2700                                   |0021: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=41
+        0x0002 line=42
+        0x0003 line=44
+      locals        : 
+        0x0000 - 0x0022 reg=3 s1 S 
+        0x0000 - 0x0022 reg=4 s2 S 
+
+    #9              : (in LTestBase;)
+      name          : 'assertNotEquals'
+      type          : '(Ljava/lang/Object;Ljava/lang/Object;)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 59
+      code          -
+      registers     : 5
+      ins           : 2
+      outs          : 2
+      insns size    : 38 16-bit code units
+002810:                                        |[002810] TestBase.assertNotEquals:(Ljava/lang/Object;Ljava/lang/Object;)V
+002820: 7120 ec00 4300                         |0000: invoke-static {v3, v4}, Ljava/util/Objects;.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z // method@00ec
+002826: 0a00                                   |0003: move-result v0
+002828: 3900 0300                              |0004: if-nez v0, 0007 // +0003
+00282c: 0e00                                   |0006: return-void
+00282e: 2200 1e00                              |0007: new-instance v0, Ljava/lang/AssertionError; // type@001e
+002832: 2201 2d00                              |0009: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+002836: 7010 c100 0100                         |000b: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00283c: 1a02 dc00                              |000e: const-string v2, "assertNotEquals: o1: " // string@00dc
+002840: 6e20 c800 2100                         |0010: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002846: 6e20 c700 3100                         |0013: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+00284c: 1a02 1300                              |0016: const-string v2, ", o2: " // string@0013
+002850: 6e20 c800 2100                         |0018: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002856: 6e20 c700 4100                         |001b: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+00285c: 6e10 ca00 0100                         |001e: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+002862: 0c01                                   |0021: move-result-object v1
+002864: 7020 b500 1000                         |0022: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+00286a: 2700                                   |0025: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=82
+        0x0006 line=85
+        0x0007 line=83
+      locals        : 
+        0x0000 - 0x0026 reg=3 o Ljava/lang/Object; 
+        0x0000 - 0x0026 reg=4 p Ljava/lang/Object; 
+
+    #10              : (in LTestBase;)
+      name          : 'assertNotReached'
+      type          : '()V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 60
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+00286c:                                        |[00286c] TestBase.assertNotReached:()V
+00287c: 2200 1e00                              |0000: new-instance v0, Ljava/lang/AssertionError; // type@001e
+002880: 1a01 a300                              |0002: const-string v1, "Unreachable" // string@00a3
+002884: 7020 b500 1000                         |0004: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+00288a: 2700                                   |0007: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=88
+      locals        : 
+
+    #11              : (in LTestBase;)
+      name          : 'assertTrue'
+      type          : '(Z)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 61
+      code          -
+      registers     : 4
+      ins           : 1
+      outs          : 2
+      insns size    : 26 16-bit code units
+00288c:                                        |[00288c] TestBase.assertTrue:(Z)V
+00289c: 3803 0300                              |0000: if-eqz v3, 0003 // +0003
+0028a0: 0e00                                   |0002: return-void
+0028a2: 2200 1e00                              |0003: new-instance v0, Ljava/lang/AssertionError; // type@001e
+0028a6: 2201 2d00                              |0005: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+0028aa: 7010 c100 0100                         |0007: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0028b0: 1a02 df00                              |000a: const-string v2, "assertTrue value: " // string@00df
+0028b4: 6e20 c800 2100                         |000c: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0028ba: 6e20 c900 3100                         |000f: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(Z)Ljava/lang/StringBuilder; // method@00c9
+0028c0: 6e10 ca00 0100                         |0012: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0028c6: 0c01                                   |0015: move-result-object v1
+0028c8: 7020 b500 1000                         |0016: invoke-direct {v0, v1}, Ljava/lang/AssertionError;.<init>:(Ljava/lang/Object;)V // method@00b5
+0028ce: 2700                                   |0019: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=21
+        0x0002 line=24
+        0x0003 line=22
+      locals        : 
+        0x0000 - 0x001a reg=3 value Z 
+
+    #12              : (in LTestBase;)
+      name          : 'fail'
+      type          : '()V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 62
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 11 16-bit code units
+0028d0:                                        |[0028d0] TestBase.fail:()V
+0028e0: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0028e4: 1a01 2601                              |0002: const-string v1, "fail" // string@0126
+0028e8: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0028ee: 7100 cc00 0000                         |0007: invoke-static {}, Ljava/lang/Thread;.dumpStack:()V // method@00cc
+0028f4: 0e00                                   |000a: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=92
+        0x0007 line=93
+        0x000a line=94
+      locals        : 
+
+  Virtual methods   -
+  source_file_idx   : 145 (TestBase.java)
+
+Class #2 header:
+class_idx           : 11
+access_flags        : 0 (0x0000)
+superclass_idx      : 42
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 148
+annotations_off     : 30716 (0x0077fc)
+class_data_off      : 28990 (0x00713e)
+static_fields_size  : 0
+instance_fields_size: 1
+direct_methods_size : 1
+virtual_methods_size: 0
+
+Class #2 annotations:
+Annotations on class
+  VISIBILITY_SYSTEM Ldalvik/annotation/EnclosingClass; value=LTestInvocationKinds;
+  VISIBILITY_SYSTEM Ldalvik/annotation/InnerClass; accessFlags=8 name="Widget"
+
+Class #2            -
+  Class descriptor  : 'LTestInvocationKinds$Widget;'
+  Access flags      : 0x0000 ()
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+    #0              : (in LTestInvocationKinds$Widget;)
+      name          : 'value'
+      type          : 'I'
+      access        : 0x0000 ()
+  Direct methods    -
+    #0              : (in LTestInvocationKinds$Widget;)
+      name          : '<init>'
+      type          : '(I)V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 72
+      code          -
+      registers     : 2
+      ins           : 2
+      outs          : 1
+      insns size    : 4 16-bit code units
+002abc:                                        |[002abc] TestInvocationKinds$Widget.<init>:(I)V
+002acc: 7010 bf00 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00bf
+002ad2: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=177
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestInvocationKinds$Widget; 
+        0x0000 - 0x0004 reg=1 value I 
+
+  Virtual methods   -
+  source_file_idx   : 148 (TestInvocationKinds.java)
+
+Class #3 header:
+class_idx           : 13
+access_flags        : 0 (0x0000)
+superclass_idx      : 48
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 149
+annotations_off     : 30732 (0x00780c)
+class_data_off      : 29002 (0x00714a)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 1
+virtual_methods_size: 2
+
+Class #3 annotations:
+Annotations on class
+  VISIBILITY_SYSTEM Ldalvik/annotation/EnclosingClass; value=LTestInvokeCustomWithConcurrentThreads;
+  VISIBILITY_SYSTEM Ldalvik/annotation/InnerClass; accessFlags=0 name=null
+  VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value={ "Ljava/lang/ThreadLocal<" "Ljava/lang/Integer;" ">;" }
+
+Class #3            -
+  Class descriptor  : 'LTestInvokeCustomWithConcurrentThreads$1;'
+  Access flags      : 0x0000 ()
+  Superclass        : 'Ljava/lang/ThreadLocal;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTestInvokeCustomWithConcurrentThreads$1;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 96
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+002ee8:                                        |[002ee8] TestInvokeCustomWithConcurrentThreads$1.<init>:()V
+002ef8: 7010 cf00 0000                         |0000: invoke-direct {v0}, Ljava/lang/ThreadLocal;.<init>:()V // method@00cf
+002efe: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=33
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestInvokeCustomWithConcurrentThreads$1; 
+
+  Virtual methods   -
+    #0              : (in LTestInvokeCustomWithConcurrentThreads$1;)
+      name          : 'initialValue'
+      type          : '()Ljava/lang/Integer;'
+      access        : 0x0004 (PROTECTED)
+      method_idx    : 97
+      code          -
+      registers     : 2
+      ins           : 1
+      outs          : 1
+      insns size    : 13 16-bit code units
+002ea0:                                        |[002ea0] TestInvokeCustomWithConcurrentThreads$1.initialValue:()Ljava/lang/Integer;
+002eb0: 7100 6500 0000                         |0000: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.access$000:()Ljava/util/concurrent/atomic/AtomicInteger; // method@0065
+002eb6: 0c00                                   |0003: move-result-object v0
+002eb8: 6e10 f100 0000                         |0004: invoke-virtual {v0}, Ljava/util/concurrent/atomic/AtomicInteger;.getAndIncrement:()I // method@00f1
+002ebe: 0a00                                   |0007: move-result v0
+002ec0: 7110 bd00 0000                         |0008: invoke-static {v0}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+002ec6: 0c00                                   |000b: move-result-object v0
+002ec8: 1100                                   |000c: return-object v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=36
+      locals        : 
+        0x0000 - 0x000d reg=1 this LTestInvokeCustomWithConcurrentThreads$1; 
+
+    #1              : (in LTestInvokeCustomWithConcurrentThreads$1;)
+      name          : 'initialValue'
+      type          : '()Ljava/lang/Object;'
+      access        : 0x1044 (PROTECTED BRIDGE SYNTHETIC)
+      method_idx    : 98
+      code          -
+      registers     : 2
+      ins           : 1
+      outs          : 1
+      insns size    : 5 16-bit code units
+002ecc:                                        |[002ecc] TestInvokeCustomWithConcurrentThreads$1.initialValue:()Ljava/lang/Object;
+002edc: 6e10 6100 0100                         |0000: invoke-virtual {v1}, LTestInvokeCustomWithConcurrentThreads$1;.initialValue:()Ljava/lang/Integer; // method@0061
+002ee2: 0c00                                   |0003: move-result-object v0
+002ee4: 1100                                   |0004: return-object v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=33
+      locals        : 
+        0x0000 - 0x0005 reg=1 this LTestInvokeCustomWithConcurrentThreads$1; 
+
+  source_file_idx   : 149 (TestInvokeCustomWithConcurrentThreads.java)
+
+Class #4 header:
+class_idx           : 19
+access_flags        : 0 (0x0000)
+superclass_idx      : 42
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 164
+annotations_off     : 30748 (0x00781c)
+class_data_off      : 29021 (0x00715d)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 2
+virtual_methods_size: 0
+
+Class #4 annotations:
+Annotations on method #170 'bsm'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value={ "(" "Ljava/lang/invoke/MethodHandles$Lookup;" "Ljava/lang/String;" "Ljava/lang/invoke/MethodType;" "Ljava/lang/Class<" "*>;)" "Ljava/lang/invoke/CallSite;" }
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #4            -
+  Class descriptor  : 'LUnrelatedBSM;'
+  Access flags      : 0x0000 ()
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LUnrelatedBSM;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 169
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+003fc8:                                        |[003fc8] UnrelatedBSM.<init>:()V
+003fd8: 7010 bf00 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00bf
+003fde: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=23
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LUnrelatedBSM; 
+
+    #1              : (in LUnrelatedBSM;)
+      name          : 'bsm'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite;'
+      access        : 0x0008 (STATIC)
+      method_idx    : 170
+      code          -
+      registers     : 6
+      ins           : 4
+      outs          : 4
+      insns size    : 10 16-bit code units
+003fa4:                                        |[003fa4] UnrelatedBSM.bsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite;
+003fb4: 6e40 d800 5243                         |0000: invoke-virtual {v2, v5, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003fba: 0c00                                   |0003: move-result-object v0
+003fbc: 2201 3400                              |0004: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+003fc0: 7020 d200 0100                         |0006: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003fc6: 1101                                   |0009: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=27
+        0x0004 line=28
+      locals        : 
+        0x0000 - 0x0000 reg=5 (null) Ljava/lang/Class; 
+        0x0004 - 0x000a reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x000a reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x000a reg=3 name Ljava/lang/String; 
+        0x0000 - 0x000a reg=4 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x000a reg=5 target Ljava/lang/Class; Ljava/lang/Class<*>;
+
+  Virtual methods   -
+  source_file_idx   : 164 (UnrelatedBSM.java)
+
+Class #5 header:
+class_idx           : 6
+access_flags        : 1 (0x0001)
+superclass_idx      : 9
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 136
+annotations_off     : 30772 (0x007834)
+class_data_off      : 29036 (0x00716c)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 5
+virtual_methods_size: 0
+
+Class #5 annotations:
+Annotations on method #1 'TestLinkerMethodMinimalArguments'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #2 'TestLinkerMethodMultipleArgumentTypes'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #3 'TestUninitializedCallSite'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #7 'main'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #5            -
+  Class descriptor  : 'LMain;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'LTestBase;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LMain;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 0
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+001900:                                        |[001900] Main.<init>:()V
+001910: 7010 3200 0000                         |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+001916: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=21
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LMain; 
+
+    #1              : (in LMain;)
+      name          : 'TestLinkerMethodMinimalArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 1
+      code          -
+      registers     : 4
+      ins           : 0
+      outs          : 3
+      insns size    : 66 16-bit code units
+001918:                                        |[001918] Main.TestLinkerMethodMinimalArguments:()V
+001928: 1210                                   |0000: const/4 v0, #int 1 // #1
+00192a: 1301 0a00                              |0001: const/16 v1, #int 10 // #a
+00192e: 7130 7700 1001                         |0003: invoke-static {v0, v1, v1}, LTestLinkerMethodMinimalArguments;.test:(III)V // method@0077
+001934: 7100 0500 0000                         |0006: invoke-static {}, LMain;.assertNotReached:()V // method@0005
+00193a: 280f                                   |0009: goto 0018 // +000f
+00193c: 0d00                                   |000a: move-exception v0
+00193e: 6e10 b600 0000                         |000b: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+001944: 0c02                                   |000e: move-result-object v2
+001946: 6e10 c000 0200                         |000f: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00194c: 0c02                                   |0012: move-result-object v2
+00194e: 1c03 2200                              |0013: const-class v3, Ljava/lang/ClassCastException; // type@0022
+001952: 7120 0400 3200                         |0015: invoke-static {v2, v3}, LMain;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0004
+001958: 1220                                   |0018: const/4 v0, #int 2 // #2
+00195a: 1302 0b00                              |0019: const/16 v2, #int 11 // #b
+00195e: 7130 7700 1002                         |001b: invoke-static {v0, v1, v2}, LTestLinkerMethodMinimalArguments;.test:(III)V // method@0077
+001964: 7100 0500 0000                         |001e: invoke-static {}, LMain;.assertNotReached:()V // method@0005
+00196a: 280f                                   |0021: goto 0030 // +000f
+00196c: 0d00                                   |0022: move-exception v0
+00196e: 6e10 b600 0000                         |0023: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+001974: 0c02                                   |0026: move-result-object v2
+001976: 6e10 c000 0200                         |0027: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00197c: 0c02                                   |002a: move-result-object v2
+00197e: 1c03 2600                              |002b: const-class v3, Ljava/lang/InstantiationException; // type@0026
+001982: 7120 0400 3200                         |002d: invoke-static {v2, v3}, LMain;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0004
+001988: 1230                                   |0030: const/4 v0, #int 3 // #3
+00198a: 1302 0c00                              |0031: const/16 v2, #int 12 // #c
+00198e: 7130 7700 1002                         |0033: invoke-static {v0, v1, v2}, LTestLinkerMethodMinimalArguments;.test:(III)V // method@0077
+001994: 7100 0500 0000                         |0036: invoke-static {}, LMain;.assertNotReached:()V // method@0005
+00199a: 2802                                   |0039: goto 003b // +0002
+00199c: 0d00                                   |003a: move-exception v0
+00199e: 1200                                   |003b: const/4 v0, #int 0 // #0
+0019a0: 1302 0d00                              |003c: const/16 v2, #int 13 // #d
+0019a4: 7130 7700 1002                         |003e: invoke-static {v0, v1, v2}, LTestLinkerMethodMinimalArguments;.test:(III)V // method@0077
+0019aa: 0e00                                   |0041: return-void
+      catches       : 3
+        0x0003 - 0x0009
+          Ljava/lang/BootstrapMethodError; -> 0x000a
+        0x001b - 0x0021
+          Ljava/lang/BootstrapMethodError; -> 0x0022
+        0x0033 - 0x0039
+          Ljava/lang/ArithmeticException; -> 0x003a
+      positions     : 
+        0x0000 line=49
+        0x0006 line=53
+        0x0009 line=56
+        0x000a line=54
+        0x000b line=55
+        0x0018 line=59
+        0x001e line=61
+        0x0021 line=64
+        0x0022 line=62
+        0x0023 line=63
+        0x0030 line=67
+        0x0036 line=69
+        0x0039 line=71
+        0x003a line=70
+        0x003b line=73
+        0x0041 line=75
+      locals        : 
+        0x000b - 0x0018 reg=0 e Ljava/lang/BootstrapMethodError; 
+        0x0023 - 0x0030 reg=0 e Ljava/lang/BootstrapMethodError; 
+
+    #2              : (in LMain;)
+      name          : 'TestLinkerMethodMultipleArgumentTypes'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 2
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 22 16-bit code units
+0019d0:                                        |[0019d0] Main.TestLinkerMethodMultipleArgumentTypes:()V
+0019e0: 1300 2100                              |0000: const/16 v0, #int 33 // #21
+0019e4: 1301 4300                              |0002: const/16 v1, #int 67 // #43
+0019e8: 7120 8400 1000                         |0004: invoke-static {v0, v1}, LTestLinkerMethodMultipleArgumentTypes;.test:(II)V // method@0084
+0019ee: 1300 f0d8                              |0007: const/16 v0, #int -10000 // #d8f0
+0019f2: 1301 e803                              |0009: const/16 v1, #int 1000 // #3e8
+0019f6: 7120 8400 1000                         |000b: invoke-static {v0, v1}, LTestLinkerMethodMultipleArgumentTypes;.test:(II)V // method@0084
+0019fc: 1300 18fc                              |000e: const/16 v0, #int -1000 // #fc18
+001a00: 1301 1027                              |0010: const/16 v1, #int 10000 // #2710
+001a04: 7120 8400 1000                         |0012: invoke-static {v0, v1}, LTestLinkerMethodMultipleArgumentTypes;.test:(II)V // method@0084
+001a0a: 0e00                                   |0015: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=42
+        0x0007 line=43
+        0x000e line=44
+        0x0015 line=45
+      locals        : 
+
+    #3              : (in LMain;)
+      name          : 'TestUninitializedCallSite'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 3
+      code          -
+      registers     : 7
+      ins           : 0
+      outs          : 3
+      insns size    : 78 16-bit code units
+001a0c:                                        |[001a0c] Main.TestUninitializedCallSite:()V
+001a1c: 2200 3900                              |0000: new-instance v0, Ljava/lang/invoke/MutableCallSite; // type@0039
+001a20: 6201 1200                              |0002: sget-object v1, Ljava/lang/Integer;.TYPE:Ljava/lang/Class; // field@0012
+001a24: 7110 e100 0100                         |0004: invoke-static {v1}, Ljava/lang/invoke/MethodType;.methodType:(Ljava/lang/Class;)Ljava/lang/invoke/MethodType; // method@00e1
+001a2a: 0c01                                   |0007: move-result-object v1
+001a2c: 7020 e600 1000                         |0008: invoke-direct {v0, v1}, Ljava/lang/invoke/MutableCallSite;.<init>:(Ljava/lang/invoke/MethodType;)V // method@00e6
+001a32: 6e10 d100 0000                         |000b: invoke-virtual {v0}, Ljava/lang/invoke/CallSite;.getTarget:()Ljava/lang/invoke/MethodHandle; // method@00d1
+001a38: 0c01                                   |000e: move-result-object v1
+001a3a: fa10 d300 0100 4100                    |000f: invoke-polymorphic {v1}, Ljava/lang/invoke/MethodHandle;.invoke:([Ljava/lang/Object;)Ljava/lang/Object;, ()V // method@00d3, proto@0041
+001a42: 7100 0600 0000                         |0013: invoke-static {}, LMain;.fail:()V // method@0006
+001a48: 2809                                   |0016: goto 001f // +0009
+001a4a: 0d01                                   |0017: move-exception v1
+001a4c: 6202 1300                              |0018: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001a50: 1a03 2100                              |001a: const-string v3, "Caught exception from uninitialized call site" // string@0021
+001a54: 6e20 b300 3200                         |001c: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001a5a: 2201 3900                              |001f: new-instance v1, Ljava/lang/invoke/MutableCallSite; // type@0039
+001a5e: 1c02 2c00                              |0021: const-class v2, Ljava/lang/String; // type@002c
+001a62: 6203 1200                              |0023: sget-object v3, Ljava/lang/Integer;.TYPE:Ljava/lang/Class; // field@0012
+001a66: 1214                                   |0025: const/4 v4, #int 1 // #1
+001a68: 2344 4600                              |0026: new-array v4, v4, [Ljava/lang/Class; // type@0046
+001a6c: 1205                                   |0028: const/4 v5, #int 0 // #0
+001a6e: 6206 1100                              |0029: sget-object v6, Ljava/lang/Character;.TYPE:Ljava/lang/Class; // field@0011
+001a72: 4d06 0405                              |002b: aput-object v6, v4, v5
+001a76: 7130 e200 3204                         |002d: invoke-static {v2, v3, v4}, Ljava/lang/invoke/MethodType;.methodType:(Ljava/lang/Class;Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType; // method@00e2
+001a7c: 0c02                                   |0030: move-result-object v2
+001a7e: 7020 e600 2100                         |0031: invoke-direct {v1, v2}, Ljava/lang/invoke/MutableCallSite;.<init>:(Ljava/lang/invoke/MethodType;)V // method@00e6
+001a84: 0710                                   |0034: move-object v0, v1
+001a86: 6e10 d100 0000                         |0035: invoke-virtual {v0}, Ljava/lang/invoke/CallSite;.getTarget:()Ljava/lang/invoke/MethodHandle; // method@00d1
+001a8c: 0c01                                   |0038: move-result-object v1
+001a8e: 1302 ff05                              |0039: const/16 v2, #int 1535 // #5ff
+001a92: 1303 6400                              |003b: const/16 v3, #int 100 // #64
+001a96: fa30 d300 2103 4800                    |003d: invoke-polymorphic {v1, v2, v3}, Ljava/lang/invoke/MethodHandle;.invoke:([Ljava/lang/Object;)Ljava/lang/Object;, (IC)V // method@00d3, proto@0048
+001a9e: 7100 0600 0000                         |0041: invoke-static {}, LMain;.fail:()V // method@0006
+001aa4: 2809                                   |0044: goto 004d // +0009
+001aa6: 0d01                                   |0045: move-exception v1
+001aa8: 6202 1300                              |0046: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001aac: 1a03 2100                              |0048: const-string v3, "Caught exception from uninitialized call site" // string@0021
+001ab0: 6e20 b300 3200                         |004a: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001ab6: 0e00                                   |004d: return-void
+      catches       : 2
+        0x000b - 0x0016
+          Ljava/lang/IllegalStateException; -> 0x0017
+        0x0035 - 0x0044
+          Ljava/lang/IllegalStateException; -> 0x0045
+      positions     : 
+        0x0000 line=24
+        0x000b line=26
+        0x0013 line=27
+        0x0016 line=30
+        0x0017 line=28
+        0x0018 line=29
+        0x001f line=32
+        0x0035 line=34
+        0x0041 line=35
+        0x0044 line=38
+        0x0045 line=36
+        0x0046 line=37
+        0x004d line=39
+      locals        : 
+        0x0018 - 0x001f reg=1 e Ljava/lang/IllegalStateException; 
+        0x0046 - 0x004d reg=1 e Ljava/lang/IllegalStateException; 
+        0x000b - 0x004e reg=0 callSite Ljava/lang/invoke/CallSite; 
+
+    #4              : (in LMain;)
+      name          : 'main'
+      type          : '([Ljava/lang/String;)V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 7
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 0
+      insns size    : 28 16-bit code units
+001ad0:                                        |[001ad0] Main.main:([Ljava/lang/String;)V
+001ae0: 7100 0300 0000                         |0000: invoke-static {}, LMain;.TestUninitializedCallSite:()V // method@0003
+001ae6: 7100 0100 0000                         |0003: invoke-static {}, LMain;.TestLinkerMethodMinimalArguments:()V // method@0001
+001aec: 7100 0200 0000                         |0006: invoke-static {}, LMain;.TestLinkerMethodMultipleArgumentTypes:()V // method@0002
+001af2: 7100 8c00 0000                         |0009: invoke-static {}, LTestLinkerUnrelatedBSM;.test:()V // method@008c
+001af8: 7100 6e00 0000                         |000c: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.test:()V // method@006e
+001afe: 7100 5b00 0000                         |000f: invoke-static {}, LTestInvocationKinds;.test:()V // method@005b
+001b04: 7100 4500 0000                         |0012: invoke-static {}, LTestDynamicBootstrapArguments;.test:()V // method@0045
+001b0a: 7100 2b00 0000                         |0015: invoke-static {}, LTestBadBootstrapArguments;.test:()V // method@002b
+001b10: 7100 a800 0000                         |0018: invoke-static {}, LTestVariableArityLinkerMethod;.test:()V // method@00a8
+001b16: 0e00                                   |001b: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=78
+        0x0003 line=79
+        0x0006 line=80
+        0x0009 line=81
+        0x000c line=82
+        0x000f line=83
+        0x0012 line=84
+        0x0015 line=85
+        0x0018 line=86
+        0x001b line=87
+      locals        : 
+        0x0000 - 0x001c reg=0 args [Ljava/lang/String; 
+
+  Virtual methods   -
+  source_file_idx   : 136 (Main.java)
+
+Class #6 header:
+class_idx           : 8
+access_flags        : 1 (0x0001)
+superclass_idx      : 9
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 144
+annotations_off     : 30820 (0x007864)
+class_data_off      : 29062 (0x007186)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 38
+virtual_methods_size: 0
+
+Class #6 annotations:
+Annotations on class
+  VISIBILITY_SYSTEM Ldalvik/annotation/MemberClasses; value={ LTestBadBootstrapArguments$TestersConstantCallSite; }
+Annotations on method #14 'bsm'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #15 'bsmDJ'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #16 'bsmDoubleLong'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #19 'bsmReturningTestersConstantCallsite'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #21 'bsmZBCS'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #25 'invokeBoxingArguments'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmDoubleLong" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/Double; Ljava/lang/Long; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; doubleValue={ 1.79769e+308 } Lannotations/Constant; longValue={ 9223372036854775807 } } fieldOrMethodName="boxingArguments"
+Annotations on method #26 'invokeExtraArguments'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 1 } Lannotations/Constant; stringValue={ "2" } Lannotations/Constant; intValue={ 3 } } fieldOrMethodName="extraArguments"
+Annotations on method #27 'invokeHappy'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ -1 } Lannotations/Constant; stringValue={ "very" } } fieldOrMethodName="happy"
+Annotations on method #28 'invokeIntegerReturnType'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmReturningInteger" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } returnType=Ljava/lang/Integer; } fieldOrMethodName="integerReturnType"
+Annotations on method #29 'invokeMissingParameterTypes'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I D } } constantArgumentsForBootstrapMethod={ } fieldOrMethodName="missingParameterTypes"
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/NoSuchMethodError; }
+Annotations on method #30 'invokeNarrowArguments'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmZBCS" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Z B C S } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; booleanValue={ true } Lannotations/Constant; byteValue={ 127 } Lannotations/Constant; charValue={ 65 } Lannotations/Constant; shortValue={ -32768 } } fieldOrMethodName="narrowArguments"
+Annotations on method #31 'invokeObjectReturnType'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmReturningObject" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } returnType=Ljava/lang/Object; } fieldOrMethodName="ObjectReturnType"
+Annotations on method #32 'invokeViaCustomCallSiteClass'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmReturningTestersConstantCallsite" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } returnType=LTestBadBootstrapArguments$TestersConstantCallSite; } fieldOrMethodName="sayHello"
+Annotations on method #33 'invokeVoidReturnType'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmReturningVoid" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } returnType=V } fieldOrMethodName="voidReturnType"
+Annotations on method #34 'invokeWideningArguments'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmDJ" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; D J } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; doubleValue={ 1.79769e+308 } Lannotations/Constant; intValue={ 2147483647 } } fieldOrMethodName="wideningArguments"
+Annotations on method #35 'invokeWideningBoxingArguments'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsmDoubleLong" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/Double; Ljava/lang/Long; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; floatValue={ 3.40282e+38 } Lannotations/Constant; longValue={ 2147483647 } } fieldOrMethodName="wideningBoxingArguments"
+Annotations on method #36 'invokeWrongArguments'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; stringValue={ "1" } Lannotations/Constant; doubleValue={ 3.14159 } } fieldOrMethodName="wrongArguments"
+Annotations on method #37 'invokeWrongArgumentsAgain'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; doubleValue={ 3.14159 } Lannotations/Constant; stringValue={ "pie" } } fieldOrMethodName="wrongArgumentsAgain"
+Annotations on method #38 'invokeWrongParameterTypes'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestBadBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I D } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ -1 } Lannotations/Constant; stringValue={ "very" } } fieldOrMethodName="wrongParameterTypes"
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/NoSuchMethodError; }
+
+Class #6            -
+  Class descriptor  : 'LTestBadBootstrapArguments;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'LTestBase;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTestBadBootstrapArguments;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 9
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+001d64:                                        |[001d64] TestBadBootstrapArguments.<init>:()V
+001d74: 7010 3200 0000                         |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+001d7a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=27
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestBadBootstrapArguments; 
+
+    #1              : (in LTestBadBootstrapArguments;)
+      name          : 'boxingArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 12
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+001d7c:                                        |[001d7c] TestBadBootstrapArguments.boxingArguments:()V
+001d8c: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001d90: 1a01 e900                              |0002: const-string v1, "boxingArguments" // string@00e9
+001d94: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001d9a: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=348
+        0x0007 line=349
+      locals        : 
+
+    #2              : (in LTestBadBootstrapArguments;)
+      name          : 'bsm'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 14
+      code          -
+      registers     : 7
+      ins           : 5
+      outs          : 4
+      insns size    : 85 16-bit code units
+001bb4:                                        |[001bb4] TestBadBootstrapArguments.bsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite;
+001bc4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001bc8: 1a01 ee00                              |0002: const-string v1, "bsm(" // string@00ee
+001bcc: 6e20 b000 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001bd2: 6200 1300                              |0007: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001bd6: 6e10 dc00 0200                         |0009: invoke-virtual {v2}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+001bdc: 0c01                                   |000c: move-result-object v1
+001bde: 6e20 af00 1000                         |000d: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+001be4: 6200 1300                              |0010: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001be8: 1a01 0c00                              |0012: const-string v1, ", " // string@000c
+001bec: 6e20 b000 1000                         |0014: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001bf2: 6200 1300                              |0017: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001bf6: 6e20 b000 3000                         |0019: invoke-virtual {v0, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001bfc: 6200 1300                              |001c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c00: 1a01 0c00                              |001e: const-string v1, ", " // string@000c
+001c04: 6e20 b000 1000                         |0020: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001c0a: 6200 1300                              |0023: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c0e: 6e20 af00 4000                         |0025: invoke-virtual {v0, v4}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+001c14: 6200 1300                              |0028: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c18: 1a01 0c00                              |002a: const-string v1, ", " // string@000c
+001c1c: 6e20 b000 1000                         |002c: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001c22: 6200 1300                              |002f: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c26: 6e20 ad00 5000                         |0031: invoke-virtual {v0, v5}, Ljava/io/PrintStream;.print:(I)V // method@00ad
+001c2c: 6200 1300                              |0034: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c30: 1a01 0c00                              |0036: const-string v1, ", " // string@000c
+001c34: 6e20 b000 1000                         |0038: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001c3a: 6200 1300                              |003b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c3e: 6e20 b000 6000                         |003d: invoke-virtual {v0, v6}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001c44: 6200 1300                              |0040: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c48: 1a01 0700                              |0042: const-string v1, ")" // string@0007
+001c4c: 6e20 b300 1000                         |0044: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001c52: 6e10 dc00 0200                         |0047: invoke-virtual {v2}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+001c58: 0c00                                   |004a: move-result-object v0
+001c5a: 6e40 d800 0243                         |004b: invoke-virtual {v2, v0, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+001c60: 0c00                                   |004e: move-result-object v0
+001c62: 2201 3400                              |004f: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+001c66: 7020 d200 0100                         |0051: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+001c6c: 1101                                   |0054: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=35
+        0x0007 line=36
+        0x0010 line=37
+        0x0017 line=38
+        0x001c line=39
+        0x0023 line=40
+        0x0028 line=41
+        0x002f line=42
+        0x0034 line=43
+        0x003b line=44
+        0x0040 line=45
+        0x0047 line=46
+        0x004f line=47
+      locals        : 
+        0x004f - 0x0055 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0055 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0055 reg=3 methodName Ljava/lang/String; 
+        0x0000 - 0x0055 reg=4 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0055 reg=5 extraInt I 
+        0x0000 - 0x0055 reg=6 extraString Ljava/lang/String; 
+
+    #3              : (in LTestBadBootstrapArguments;)
+      name          : 'bsmDJ'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 15
+      code          -
+      registers     : 9
+      ins           : 7
+      outs          : 4
+      insns size    : 45 16-bit code units
+001c70:                                        |[001c70] TestBadBootstrapArguments.bsmDJ:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite;
+001c80: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c84: 1a01 f100                              |0002: const-string v1, "bsmDJ(..., " // string@00f1
+001c88: 6e20 b000 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001c8e: 6200 1300                              |0007: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c92: 6e30 ac00 5006                         |0009: invoke-virtual {v0, v5, v6}, Ljava/io/PrintStream;.print:(D)V // method@00ac
+001c98: 6200 1300                              |000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001c9c: 1a01 0c00                              |000e: const-string v1, ", " // string@000c
+001ca0: 6e20 b000 1000                         |0010: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001ca6: 6200 1300                              |0013: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001caa: 6e30 ae00 7008                         |0015: invoke-virtual {v0, v7, v8}, Ljava/io/PrintStream;.print:(J)V // method@00ae
+001cb0: 6200 1300                              |0018: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001cb4: 1a01 0700                              |001a: const-string v1, ")" // string@0007
+001cb8: 6e20 b300 1000                         |001c: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001cbe: 6e10 dc00 0200                         |001f: invoke-virtual {v2}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+001cc4: 0c00                                   |0022: move-result-object v0
+001cc6: 6e40 d800 0243                         |0023: invoke-virtual {v2, v0, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+001ccc: 0c00                                   |0026: move-result-object v0
+001cce: 2201 3400                              |0027: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+001cd2: 7020 d200 0100                         |0029: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+001cd8: 1101                                   |002c: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=270
+        0x0007 line=271
+        0x000c line=272
+        0x0013 line=273
+        0x0018 line=274
+        0x001f line=275
+        0x0027 line=276
+      locals        : 
+        0x0027 - 0x002d reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x002d reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x002d reg=3 methodName Ljava/lang/String; 
+        0x0000 - 0x002d reg=4 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x002d reg=5 extraArg0 D 
+        0x0000 - 0x002d reg=7 extraArg1 J 
+
+    #4              : (in LTestBadBootstrapArguments;)
+      name          : 'bsmDoubleLong'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 16
+      code          -
+      registers     : 7
+      ins           : 5
+      outs          : 4
+      insns size    : 45 16-bit code units
+001cdc:                                        |[001cdc] TestBadBootstrapArguments.bsmDoubleLong:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite;
+001cec: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001cf0: 1a01 f300                              |0002: const-string v1, "bsmDoubleLong(..., " // string@00f3
+001cf4: 6e20 b000 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001cfa: 6200 1300                              |0007: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001cfe: 6e20 af00 5000                         |0009: invoke-virtual {v0, v5}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+001d04: 6200 1300                              |000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001d08: 1a01 0c00                              |000e: const-string v1, ", " // string@000c
+001d0c: 6e20 b000 1000                         |0010: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+001d12: 6200 1300                              |0013: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001d16: 6e20 af00 6000                         |0015: invoke-virtual {v0, v6}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+001d1c: 6200 1300                              |0018: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001d20: 1a01 0700                              |001a: const-string v1, ")" // string@0007
+001d24: 6e20 b300 1000                         |001c: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001d2a: 6e10 dc00 0200                         |001f: invoke-virtual {v2}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+001d30: 0c00                                   |0022: move-result-object v0
+001d32: 6e40 d800 0243                         |0023: invoke-virtual {v2, v0, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+001d38: 0c00                                   |0026: move-result-object v0
+001d3a: 2201 3400                              |0027: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+001d3e: 7020 d200 0100                         |0029: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+001d44: 1101                                   |002c: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=314
+        0x0007 line=315
+        0x000c line=316
+        0x0013 line=317
+        0x0018 line=318
+        0x001f line=319
+        0x0027 line=320
+      locals        : 
+        0x0027 - 0x002d reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x002d reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x002d reg=3 methodName Ljava/lang/String; 
+        0x0000 - 0x002d reg=4 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x002d reg=5 extraArg0 Ljava/lang/Double; 
+        0x0000 - 0x002d reg=6 extraArg1 Ljava/lang/Long; 
+
+    #5              : (in LTestBadBootstrapArguments;)
+      name          : 'bsmReturningInteger'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer;'
+      access        : 0x0008 (STATIC)
+      method_idx    : 17
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 2
+      insns size    : 13 16-bit code units
+001b5c:                                        |[001b5c] TestBadBootstrapArguments.bsmReturningInteger:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer;
+001b6c: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001b70: 1a01 eb00                              |0002: const-string v1, "bsm returning Integer value." // string@00eb
+001b74: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001b7a: 1230                                   |0007: const/4 v0, #int 3 // #3
+001b7c: 7110 bd00 0000                         |0008: invoke-static {v0}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+001b82: 0c00                                   |000b: move-result-object v0
+001b84: 1100                                   |000c: return-object v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=425
+        0x0007 line=426
+      locals        : 
+        0x0000 - 0x000d reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x000d reg=3 name Ljava/lang/String; 
+        0x0000 - 0x000d reg=4 type Ljava/lang/invoke/MethodType; 
+
+    #6              : (in LTestBadBootstrapArguments;)
+      name          : 'bsmReturningObject'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object;'
+      access        : 0x0008 (STATIC)
+      method_idx    : 18
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 2
+      insns size    : 13 16-bit code units
+001b88:                                        |[001b88] TestBadBootstrapArguments.bsmReturningObject:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object;
+001b98: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001b9c: 1a01 ec00                              |0002: const-string v1, "bsm returning Object value." // string@00ec
+001ba0: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001ba6: 2200 2a00                              |0007: new-instance v0, Ljava/lang/Object; // type@002a
+001baa: 7010 bf00 0000                         |0009: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00bf
+001bb0: 1100                                   |000c: return-object v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=402
+        0x0007 line=403
+      locals        : 
+        0x0000 - 0x000d reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x000d reg=3 name Ljava/lang/String; 
+        0x0000 - 0x000d reg=4 type Ljava/lang/invoke/MethodType; 
+
+    #7              : (in LTestBadBootstrapArguments;)
+      name          : 'bsmReturningTestersConstantCallsite'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite;'
+      access        : 0x0008 (STATIC)
+      method_idx    : 19
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 4
+      insns size    : 14 16-bit code units
+001b30:                                        |[001b30] TestBadBootstrapArguments.bsmReturningTestersConstantCallsite:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite;
+001b40: 2200 0700                              |0000: new-instance v0, LTestBadBootstrapArguments$TestersConstantCallSite; // type@0007
+001b44: 6e10 dc00 0200                         |0002: invoke-virtual {v2}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+001b4a: 0c01                                   |0005: move-result-object v1
+001b4c: 6e40 d800 1243                         |0006: invoke-virtual {v2, v1, v3, v4}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+001b52: 0c01                                   |0009: move-result-object v1
+001b54: 7020 0800 1000                         |000a: invoke-direct {v0, v1}, LTestBadBootstrapArguments$TestersConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@0008
+001b5a: 1100                                   |000d: return-object v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=455
+      locals        : 
+        0x0000 - 0x000e reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x000e reg=3 name Ljava/lang/String; 
+        0x0000 - 0x000e reg=4 type Ljava/lang/invoke/MethodType; 
+
+    #8              : (in LTestBadBootstrapArguments;)
+      name          : 'bsmReturningVoid'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 20
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 2
+      insns size    : 8 16-bit code units
+001d9c:                                        |[001d9c] TestBadBootstrapArguments.bsmReturningVoid:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V
+001dac: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001db0: 1a01 ed00                              |0002: const-string v1, "bsm returning void value." // string@00ed
+001db4: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001dba: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=380
+        0x0007 line=381
+      locals        : 
+        0x0000 - 0x0008 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0008 reg=3 name Ljava/lang/String; 
+        0x0000 - 0x0008 reg=4 type Ljava/lang/invoke/MethodType; 
+
+    #9              : (in LTestBadBootstrapArguments;)
+      name          : 'bsmZBCS'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 21
+      code          -
+      registers     : 8
+      ins           : 7
+      outs          : 0
+      insns size    : 5 16-bit code units
+001d48:                                        |[001d48] TestBadBootstrapArguments.bsmZBCS:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite;
+001d58: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001d5e: 1200                                   |0003: const/4 v0, #int 0 // #0
+001d60: 1100                                   |0004: return-object v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=227
+        0x0003 line=228
+      locals        : 
+        0x0000 - 0x0005 reg=1 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0005 reg=2 methodName Ljava/lang/String; 
+        0x0000 - 0x0005 reg=3 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0005 reg=4 extraArg0 Z 
+        0x0000 - 0x0005 reg=5 extraArg1 B 
+        0x0000 - 0x0005 reg=6 extraArg2 C 
+        0x0000 - 0x0005 reg=7 extraArg3 S 
+
+    #10              : (in LTestBadBootstrapArguments;)
+      name          : 'extraArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 22
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+001dbc:                                        |[001dbc] TestBadBootstrapArguments.extraArguments:()V
+001dcc: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001dd0: 1a01 2001                              |0002: const-string v1, "extraArguments" // string@0120
+001dd4: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001dda: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=158
+        0x0007 line=159
+      locals        : 
+
+    #11              : (in LTestBadBootstrapArguments;)
+      name          : 'happy'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 23
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+001ddc:                                        |[001ddc] TestBadBootstrapArguments.happy:()V
+001dec: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001df0: 1a01 3d01                              |0002: const-string v1, "happy" // string@013d
+001df4: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001dfa: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=74
+        0x0007 line=75
+      locals        : 
+
+    #12              : (in LTestBadBootstrapArguments;)
+      name          : 'integerReturnType'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 24
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001dfc:                                        |[001dfc] TestBadBootstrapArguments.integerReturnType:()V
+001e0c: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e12: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=444
+        0x0003 line=445
+      locals        : 
+
+    #13              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeBoxingArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 25
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001e14:                                        |[001e14] TestBadBootstrapArguments.invokeBoxingArguments:()V
+001e24: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e2a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=344
+        0x0003 line=345
+      locals        : 
+
+    #14              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeExtraArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 26
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001e2c:                                        |[001e2c] TestBadBootstrapArguments.invokeExtraArguments:()V
+001e3c: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e42: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=154
+        0x0003 line=155
+      locals        : 
+
+    #15              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeHappy'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 27
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001e44:                                        |[001e44] TestBadBootstrapArguments.invokeHappy:()V
+001e54: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e5a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=70
+        0x0003 line=71
+      locals        : 
+
+    #16              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeIntegerReturnType'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 28
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001e5c:                                        |[001e5c] TestBadBootstrapArguments.invokeIntegerReturnType:()V
+001e6c: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e72: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=440
+        0x0003 line=441
+      locals        : 
+
+    #17              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeMissingParameterTypes'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 29
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001e74:                                        |[001e74] TestBadBootstrapArguments.invokeMissingParameterTypes:()V
+001e84: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001e8a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=124
+        0x0003 line=125
+      locals        : 
+
+    #18              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeNarrowArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 30
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001e8c:                                        |[001e8c] TestBadBootstrapArguments.invokeNarrowArguments:()V
+001e9c: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001ea2: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=256
+        0x0003 line=257
+      locals        : 
+
+    #19              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeObjectReturnType'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 31
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001ea4:                                        |[001ea4] TestBadBootstrapArguments.invokeObjectReturnType:()V
+001eb4: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001eba: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=417
+        0x0003 line=418
+      locals        : 
+
+    #20              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeViaCustomCallSiteClass'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 32
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001ebc:                                        |[001ebc] TestBadBootstrapArguments.invokeViaCustomCallSiteClass:()V
+001ecc: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001ed2: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=469
+        0x0003 line=470
+      locals        : 
+
+    #21              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeVoidReturnType'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 33
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001ed4:                                        |[001ed4] TestBadBootstrapArguments.invokeVoidReturnType:()V
+001ee4: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001eea: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=394
+        0x0003 line=395
+      locals        : 
+
+    #22              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeWideningArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 34
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001eec:                                        |[001eec] TestBadBootstrapArguments.invokeWideningArguments:()V
+001efc: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f02: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=300
+        0x0003 line=301
+      locals        : 
+
+    #23              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeWideningBoxingArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 35
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001f04:                                        |[001f04] TestBadBootstrapArguments.invokeWideningBoxingArguments:()V
+001f14: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f1a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=372
+        0x0003 line=373
+      locals        : 
+
+    #24              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeWrongArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 36
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001f1c:                                        |[001f1c] TestBadBootstrapArguments.invokeWrongArguments:()V
+001f2c: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f32: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=182
+        0x0003 line=183
+      locals        : 
+
+    #25              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeWrongArgumentsAgain'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 37
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001f34:                                        |[001f34] TestBadBootstrapArguments.invokeWrongArgumentsAgain:()V
+001f44: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f4a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=210
+        0x0003 line=211
+      locals        : 
+
+    #26              : (in LTestBadBootstrapArguments;)
+      name          : 'invokeWrongParameterTypes'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 38
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001f4c:                                        |[001f4c] TestBadBootstrapArguments.invokeWrongParameterTypes:()V
+001f5c: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f62: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=98
+        0x0003 line=99
+      locals        : 
+
+    #27              : (in LTestBadBootstrapArguments;)
+      name          : 'missingParameterTypes'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 39
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+001f64:                                        |[001f64] TestBadBootstrapArguments.missingParameterTypes:()V
+001f74: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001f78: 1a01 8c01                              |0002: const-string v1, "missingParameterTypes" // string@018c
+001f7c: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001f82: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=128
+        0x0007 line=129
+      locals        : 
+
+    #28              : (in LTestBadBootstrapArguments;)
+      name          : 'narrowArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 40
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001f84:                                        |[001f84] TestBadBootstrapArguments.narrowArguments:()V
+001f94: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001f9a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=260
+        0x0003 line=261
+      locals        : 
+
+    #29              : (in LTestBadBootstrapArguments;)
+      name          : 'objectReturnType'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 41
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+001f9c:                                        |[001f9c] TestBadBootstrapArguments.objectReturnType:()V
+001fac: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+001fb2: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=421
+        0x0003 line=422
+      locals        : 
+
+    #30              : (in LTestBadBootstrapArguments;)
+      name          : 'sayHello'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 42
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+001fb4:                                        |[001fb4] TestBadBootstrapArguments.sayHello:()V
+001fc4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001fc8: 1a01 2d00                              |0002: const-string v1, "Hello!" // string@002d
+001fcc: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001fd2: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=473
+        0x0007 line=474
+      locals        : 
+
+    #31              : (in LTestBadBootstrapArguments;)
+      name          : 'test'
+      type          : '()V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 43
+      code          -
+      registers     : 3
+      ins           : 0
+      outs          : 2
+      insns size    : 529 16-bit code units
+001fd4:                                        |[001fd4] TestBadBootstrapArguments.test:()V
+001fe4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+001fe8: 1a01 8f00                              |0002: const-string v1, "TestBadBootstrapArguments" // string@008f
+001fec: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+001ff2: fc00 0000 0000                         |0007: invoke-custom {}, call_site@0000
+001ff8: fc00 0100 0000                         |000a: invoke-custom {}, call_site@0001
+001ffe: 7100 0b00 0000                         |000d: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+002004: 2812                                   |0010: goto 0022 // +0012
+002006: 0d00                                   |0011: move-exception v0
+002008: 6201 1300                              |0012: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00200c: 1a02 6101                              |0014: const-string v2, "invokeWrongParameterTypes => " // string@0161
+002010: 6e20 b000 2100                         |0016: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002016: 6201 1300                              |0019: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00201a: 6e10 c000 0000                         |001b: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002020: 0c02                                   |001e: move-result-object v2
+002022: 6e20 b200 2100                         |001f: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002028: fc00 0200 0000                         |0022: invoke-custom {}, call_site@0002
+00202e: 7100 0b00 0000                         |0025: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+002034: 2812                                   |0028: goto 003a // +0012
+002036: 0d00                                   |0029: move-exception v0
+002038: 6201 1300                              |002a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00203c: 1a02 5101                              |002c: const-string v2, "invokeMissingParameterTypes => " // string@0151
+002040: 6e20 b000 2100                         |002e: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002046: 6201 1300                              |0031: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00204a: 6e10 c000 0000                         |0033: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002050: 0c02                                   |0036: move-result-object v2
+002052: 6e20 b200 2100                         |0037: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002058: fc00 0300 0000                         |003a: invoke-custom {}, call_site@0003
+00205e: 7100 0b00 0000                         |003d: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+002064: 2833                                   |0040: goto 0073 // +0033
+002066: 0d00                                   |0041: move-exception v0
+002068: 1c01 3a00                              |0042: const-class v1, Ljava/lang/invoke/WrongMethodTypeException; // type@003a
+00206c: 6e10 b600 0000                         |0044: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+002072: 0c02                                   |0047: move-result-object v2
+002074: 6e10 c000 0200                         |0048: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00207a: 0c02                                   |004b: move-result-object v2
+00207c: 7120 0a00 2100                         |004c: invoke-static {v1, v2}, LTestBadBootstrapArguments;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@000a
+002082: 6201 1300                              |004f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002086: 1a02 4c01                              |0051: const-string v2, "invokeExtraArguments => " // string@014c
+00208a: 6e20 b000 2100                         |0053: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002090: 6201 1300                              |0056: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002094: 6e10 c000 0000                         |0058: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00209a: 0c02                                   |005b: move-result-object v2
+00209c: 6e20 af00 2100                         |005c: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+0020a2: 6201 1300                              |005f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0020a6: 1a02 0200                              |0061: const-string v2, " => " // string@0002
+0020aa: 6e20 b000 2100                         |0063: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0020b0: 6201 1300                              |0066: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0020b4: 6e10 b600 0000                         |0068: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+0020ba: 0c02                                   |006b: move-result-object v2
+0020bc: 6e10 c000 0200                         |006c: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0020c2: 0c02                                   |006f: move-result-object v2
+0020c4: 6e20 b200 2100                         |0070: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+0020ca: fc00 0400 0000                         |0073: invoke-custom {}, call_site@0004
+0020d0: 7100 0b00 0000                         |0076: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+0020d6: 2833                                   |0079: goto 00ac // +0033
+0020d8: 0d00                                   |007a: move-exception v0
+0020da: 1c01 2200                              |007b: const-class v1, Ljava/lang/ClassCastException; // type@0022
+0020de: 6e10 b600 0000                         |007d: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+0020e4: 0c02                                   |0080: move-result-object v2
+0020e6: 6e10 c000 0200                         |0081: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0020ec: 0c02                                   |0084: move-result-object v2
+0020ee: 7120 0a00 2100                         |0085: invoke-static {v1, v2}, LTestBadBootstrapArguments;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@000a
+0020f4: 6201 1300                              |0088: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0020f8: 1a02 5d01                              |008a: const-string v2, "invokeWrongArguments => " // string@015d
+0020fc: 6e20 b000 2100                         |008c: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002102: 6201 1300                              |008f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002106: 6e10 c000 0000                         |0091: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00210c: 0c02                                   |0094: move-result-object v2
+00210e: 6e20 af00 2100                         |0095: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+002114: 6201 1300                              |0098: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002118: 1a02 0200                              |009a: const-string v2, " => " // string@0002
+00211c: 6e20 b000 2100                         |009c: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002122: 6201 1300                              |009f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002126: 6e10 b600 0000                         |00a1: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+00212c: 0c02                                   |00a4: move-result-object v2
+00212e: 6e10 c000 0200                         |00a5: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002134: 0c02                                   |00a8: move-result-object v2
+002136: 6e20 b200 2100                         |00a9: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+00213c: fc00 0500 0000                         |00ac: invoke-custom {}, call_site@0005
+002142: 7100 0b00 0000                         |00af: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+002148: 2833                                   |00b2: goto 00e5 // +0033
+00214a: 0d00                                   |00b3: move-exception v0
+00214c: 1c01 2200                              |00b4: const-class v1, Ljava/lang/ClassCastException; // type@0022
+002150: 6e10 b600 0000                         |00b6: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+002156: 0c02                                   |00b9: move-result-object v2
+002158: 6e10 c000 0200                         |00ba: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00215e: 0c02                                   |00bd: move-result-object v2
+002160: 7120 0a00 2100                         |00be: invoke-static {v1, v2}, LTestBadBootstrapArguments;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@000a
+002166: 6201 1300                              |00c1: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00216a: 1a02 5d01                              |00c3: const-string v2, "invokeWrongArguments => " // string@015d
+00216e: 6e20 b000 2100                         |00c5: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002174: 6201 1300                              |00c8: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002178: 6e10 c000 0000                         |00ca: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00217e: 0c02                                   |00cd: move-result-object v2
+002180: 6e20 af00 2100                         |00ce: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+002186: 6201 1300                              |00d1: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00218a: 1a02 0200                              |00d3: const-string v2, " => " // string@0002
+00218e: 6e20 b000 2100                         |00d5: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002194: 6201 1300                              |00d8: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002198: 6e10 b600 0000                         |00da: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+00219e: 0c02                                   |00dd: move-result-object v2
+0021a0: 6e10 c000 0200                         |00de: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0021a6: 0c02                                   |00e1: move-result-object v2
+0021a8: 6e20 b200 2100                         |00e2: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+0021ae: fc00 0600 0000                         |00e5: invoke-custom {}, call_site@0006
+0021b4: 7100 0b00 0000                         |00e8: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+0021ba: 2833                                   |00eb: goto 011e // +0033
+0021bc: 0d00                                   |00ec: move-exception v0
+0021be: 1c01 2200                              |00ed: const-class v1, Ljava/lang/ClassCastException; // type@0022
+0021c2: 6e10 b600 0000                         |00ef: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+0021c8: 0c02                                   |00f2: move-result-object v2
+0021ca: 6e10 c000 0200                         |00f3: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0021d0: 0c02                                   |00f6: move-result-object v2
+0021d2: 7120 0a00 2100                         |00f7: invoke-static {v1, v2}, LTestBadBootstrapArguments;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@000a
+0021d8: 6201 1300                              |00fa: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0021dc: 1a02 5f01                              |00fc: const-string v2, "invokeWrongArgumentsAgain => " // string@015f
+0021e0: 6e20 b000 2100                         |00fe: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0021e6: 6201 1300                              |0101: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0021ea: 6e10 c000 0000                         |0103: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0021f0: 0c02                                   |0106: move-result-object v2
+0021f2: 6e20 af00 2100                         |0107: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+0021f8: 6201 1300                              |010a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0021fc: 1a02 0200                              |010c: const-string v2, " => " // string@0002
+002200: 6e20 b000 2100                         |010e: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002206: 6201 1300                              |0111: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00220a: 6e10 b600 0000                         |0113: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+002210: 0c02                                   |0116: move-result-object v2
+002212: 6e10 c000 0200                         |0117: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002218: 0c02                                   |011a: move-result-object v2
+00221a: 6e20 b200 2100                         |011b: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002220: fc00 0700 0000                         |011e: invoke-custom {}, call_site@0007
+002226: 7100 0b00 0000                         |0121: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+00222c: 2833                                   |0124: goto 0157 // +0033
+00222e: 0d00                                   |0125: move-exception v0
+002230: 1c01 2200                              |0126: const-class v1, Ljava/lang/ClassCastException; // type@0022
+002234: 6e10 b600 0000                         |0128: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+00223a: 0c02                                   |012b: move-result-object v2
+00223c: 6e10 c000 0200                         |012c: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002242: 0c02                                   |012f: move-result-object v2
+002244: 7120 0a00 2100                         |0130: invoke-static {v1, v2}, LTestBadBootstrapArguments;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@000a
+00224a: 6201 1300                              |0133: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00224e: 1a02 5301                              |0135: const-string v2, "invokeNarrowArguments => " // string@0153
+002252: 6e20 b000 2100                         |0137: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002258: 6201 1300                              |013a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00225c: 6e10 c000 0000                         |013c: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002262: 0c02                                   |013f: move-result-object v2
+002264: 6e20 af00 2100                         |0140: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+00226a: 6201 1300                              |0143: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00226e: 1a02 0200                              |0145: const-string v2, " => " // string@0002
+002272: 6e20 b000 2100                         |0147: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002278: 6201 1300                              |014a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00227c: 6e10 b600 0000                         |014c: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+002282: 0c02                                   |014f: move-result-object v2
+002284: 6e10 c000 0200                         |0150: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00228a: 0c02                                   |0153: move-result-object v2
+00228c: 6e20 b200 2100                         |0154: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002292: fc00 0800 0000                         |0157: invoke-custom {}, call_site@0008
+002298: fc00 0900 0000                         |015a: invoke-custom {}, call_site@0009
+00229e: fc00 0a00 0000                         |015d: invoke-custom {}, call_site@000a
+0022a4: 7100 0b00 0000                         |0160: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+0022aa: 2826                                   |0163: goto 0189 // +0026
+0022ac: 0d00                                   |0164: move-exception v0
+0022ae: 6201 1300                              |0165: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0022b2: 1a02 5b01                              |0167: const-string v2, "invokeWideningBoxingArguments => " // string@015b
+0022b6: 6e20 b000 2100                         |0169: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0022bc: 6201 1300                              |016c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0022c0: 6e10 c000 0000                         |016e: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0022c6: 0c02                                   |0171: move-result-object v2
+0022c8: 6e20 af00 2100                         |0172: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+0022ce: 6201 1300                              |0175: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0022d2: 1a02 0200                              |0177: const-string v2, " => " // string@0002
+0022d6: 6e20 b000 2100                         |0179: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0022dc: 6201 1300                              |017c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0022e0: 6e10 b600 0000                         |017e: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+0022e6: 0c02                                   |0181: move-result-object v2
+0022e8: 6e10 c000 0200                         |0182: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0022ee: 0c02                                   |0185: move-result-object v2
+0022f0: 6e20 b200 2100                         |0186: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+0022f6: fc00 0b00 0000                         |0189: invoke-custom {}, call_site@000b
+0022fc: 7100 0b00 0000                         |018c: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+002302: 2826                                   |018f: goto 01b5 // +0026
+002304: 0d00                                   |0190: move-exception v0
+002306: 6201 1300                              |0191: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00230a: 1a02 5801                              |0193: const-string v2, "invokeVoidReturnType() => " // string@0158
+00230e: 6e20 b000 2100                         |0195: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002314: 6201 1300                              |0198: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002318: 6e10 c000 0000                         |019a: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00231e: 0c02                                   |019d: move-result-object v2
+002320: 6e20 af00 2100                         |019e: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+002326: 6201 1300                              |01a1: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00232a: 1a02 0200                              |01a3: const-string v2, " => " // string@0002
+00232e: 6e20 b000 2100                         |01a5: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002334: 6201 1300                              |01a8: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002338: 6e10 b600 0000                         |01aa: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+00233e: 0c02                                   |01ad: move-result-object v2
+002340: 6e10 c000 0200                         |01ae: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002346: 0c02                                   |01b1: move-result-object v2
+002348: 6e20 b200 2100                         |01b2: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+00234e: fc00 0c00 0000                         |01b5: invoke-custom {}, call_site@000c
+002354: 7100 0b00 0000                         |01b8: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+00235a: 2826                                   |01bb: goto 01e1 // +0026
+00235c: 0d00                                   |01bc: move-exception v0
+00235e: 6201 1300                              |01bd: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002362: 1a02 5501                              |01bf: const-string v2, "invokeObjectReturnType() => " // string@0155
+002366: 6e20 b000 2100                         |01c1: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+00236c: 6201 1300                              |01c4: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002370: 6e10 c000 0000                         |01c6: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002376: 0c02                                   |01c9: move-result-object v2
+002378: 6e20 af00 2100                         |01ca: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+00237e: 6201 1300                              |01cd: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002382: 1a02 0200                              |01cf: const-string v2, " => " // string@0002
+002386: 6e20 b000 2100                         |01d1: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+00238c: 6201 1300                              |01d4: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002390: 6e10 b600 0000                         |01d6: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+002396: 0c02                                   |01d9: move-result-object v2
+002398: 6e10 c000 0200                         |01da: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+00239e: 0c02                                   |01dd: move-result-object v2
+0023a0: 6e20 b200 2100                         |01de: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+0023a6: fc00 0d00 0000                         |01e1: invoke-custom {}, call_site@000d
+0023ac: 7100 0b00 0000                         |01e4: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+0023b2: 2826                                   |01e7: goto 020d // +0026
+0023b4: 0d00                                   |01e8: move-exception v0
+0023b6: 6201 1300                              |01e9: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0023ba: 1a02 4f01                              |01eb: const-string v2, "invokeIntegerReturnType() => " // string@014f
+0023be: 6e20 b000 2100                         |01ed: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0023c4: 6201 1300                              |01f0: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0023c8: 6e10 c000 0000                         |01f2: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0023ce: 0c02                                   |01f5: move-result-object v2
+0023d0: 6e20 af00 2100                         |01f6: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+0023d6: 6201 1300                              |01f9: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0023da: 1a02 0200                              |01fb: const-string v2, " => " // string@0002
+0023de: 6e20 b000 2100                         |01fd: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+0023e4: 6201 1300                              |0200: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0023e8: 6e10 b600 0000                         |0202: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+0023ee: 0c02                                   |0205: move-result-object v2
+0023f0: 6e10 c000 0200                         |0206: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+0023f6: 0c02                                   |0209: move-result-object v2
+0023f8: 6e20 b200 2100                         |020a: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+0023fe: fc00 0e00 0000                         |020d: invoke-custom {}, call_site@000e
+002404: 0e00                                   |0210: return-void
+      catches       : 11
+        0x000a - 0x0010
+          Ljava/lang/NoSuchMethodError; -> 0x0011
+        0x0022 - 0x0028
+          Ljava/lang/NoSuchMethodError; -> 0x0029
+        0x003a - 0x0040
+          Ljava/lang/BootstrapMethodError; -> 0x0041
+        0x0073 - 0x0079
+          Ljava/lang/BootstrapMethodError; -> 0x007a
+        0x00ac - 0x00b2
+          Ljava/lang/BootstrapMethodError; -> 0x00b3
+        0x00e5 - 0x00eb
+          Ljava/lang/BootstrapMethodError; -> 0x00ec
+        0x011e - 0x0124
+          Ljava/lang/BootstrapMethodError; -> 0x0125
+        0x015d - 0x0163
+          Ljava/lang/BootstrapMethodError; -> 0x0164
+        0x0189 - 0x018f
+          Ljava/lang/BootstrapMethodError; -> 0x0190
+        0x01b5 - 0x01bb
+          Ljava/lang/BootstrapMethodError; -> 0x01bc
+        0x01e1 - 0x01e7
+          Ljava/lang/BootstrapMethodError; -> 0x01e8
+      positions     : 
+        0x0000 line=477
+        0x0007 line=478
+        0x000a line=480
+        0x000d line=481
+        0x0010 line=485
+        0x0011 line=482
+        0x0012 line=483
+        0x0019 line=484
+        0x0022 line=487
+        0x0025 line=488
+        0x0028 line=492
+        0x0029 line=489
+        0x002a line=490
+        0x0031 line=491
+        0x003a line=494
+        0x003d line=495
+        0x0040 line=502
+        0x0041 line=496
+        0x0042 line=497
+        0x004f line=498
+        0x0056 line=499
+        0x005f line=500
+        0x0066 line=501
+        0x0073 line=504
+        0x0076 line=505
+        0x0079 line=512
+        0x007a line=506
+        0x007b line=507
+        0x0088 line=508
+        0x008f line=509
+        0x0098 line=510
+        0x009f line=511
+        0x00ac line=514
+        0x00af line=515
+        0x00b2 line=522
+        0x00b3 line=516
+        0x00b4 line=517
+        0x00c1 line=518
+        0x00c8 line=519
+        0x00d1 line=520
+        0x00d8 line=521
+        0x00e5 line=524
+        0x00e8 line=525
+        0x00eb line=532
+        0x00ec line=526
+        0x00ed line=527
+        0x00fa line=528
+        0x0101 line=529
+        0x010a line=530
+        0x0111 line=531
+        0x011e line=534
+        0x0121 line=535
+        0x0124 line=542
+        0x0125 line=536
+        0x0126 line=537
+        0x0133 line=538
+        0x013a line=539
+        0x0143 line=540
+        0x014a line=541
+        0x0157 line=543
+        0x015a line=544
+        0x015d line=546
+        0x0160 line=547
+        0x0163 line=553
+        0x0164 line=548
+        0x0165 line=549
+        0x016c line=550
+        0x0175 line=551
+        0x017c line=552
+        0x0189 line=555
+        0x018c line=556
+        0x018f line=562
+        0x0190 line=557
+        0x0191 line=558
+        0x0198 line=559
+        0x01a1 line=560
+        0x01a8 line=561
+        0x01b5 line=564
+        0x01b8 line=565
+        0x01bb line=571
+        0x01bc line=566
+        0x01bd line=567
+        0x01c4 line=568
+        0x01cd line=569
+        0x01d4 line=570
+        0x01e1 line=573
+        0x01e4 line=574
+        0x01e7 line=580
+        0x01e8 line=575
+        0x01e9 line=576
+        0x01f0 line=577
+        0x01f9 line=578
+        0x0200 line=579
+        0x020d line=581
+        0x0210 line=582
+      locals        : 
+        0x0012 - 0x0022 reg=0 expected Ljava/lang/NoSuchMethodError; 
+        0x002a - 0x003a reg=0 expected Ljava/lang/NoSuchMethodError; 
+        0x0042 - 0x0073 reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x007b - 0x00ac reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x00b4 - 0x00e5 reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x00ed - 0x011e reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x0126 - 0x0157 reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x0165 - 0x0189 reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x0191 - 0x01b5 reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x01bd - 0x01e1 reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x01e9 - 0x020d reg=0 expected Ljava/lang/BootstrapMethodError; 
+
+    #32              : (in LTestBadBootstrapArguments;)
+      name          : 'voidReturnType'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 44
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+00248c:                                        |[00248c] TestBadBootstrapArguments.voidReturnType:()V
+00249c: 7100 0b00 0000                         |0000: invoke-static {}, LTestBadBootstrapArguments;.assertNotReached:()V // method@000b
+0024a2: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=398
+        0x0003 line=399
+      locals        : 
+
+    #33              : (in LTestBadBootstrapArguments;)
+      name          : 'wideningArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 45
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+0024a4:                                        |[0024a4] TestBadBootstrapArguments.wideningArguments:()V
+0024b4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0024b8: 1a01 d101                              |0002: const-string v1, "wideningArguments" // string@01d1
+0024bc: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0024c2: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=304
+        0x0007 line=305
+      locals        : 
+
+    #34              : (in LTestBadBootstrapArguments;)
+      name          : 'wideningBoxingArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 46
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+0024c4:                                        |[0024c4] TestBadBootstrapArguments.wideningBoxingArguments:()V
+0024d4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0024d8: 1a01 d201                              |0002: const-string v1, "wideningBoxingArguments" // string@01d2
+0024dc: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0024e2: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=376
+        0x0007 line=377
+      locals        : 
+
+    #35              : (in LTestBadBootstrapArguments;)
+      name          : 'wrongArguments'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 47
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+0024e4:                                        |[0024e4] TestBadBootstrapArguments.wrongArguments:()V
+0024f4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0024f8: 1a01 d401                              |0002: const-string v1, "wrongArguments" // string@01d4
+0024fc: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002502: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=186
+        0x0007 line=187
+      locals        : 
+
+    #36              : (in LTestBadBootstrapArguments;)
+      name          : 'wrongArgumentsAgain'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 48
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+002504:                                        |[002504] TestBadBootstrapArguments.wrongArgumentsAgain:()V
+002514: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002518: 1a01 d501                              |0002: const-string v1, "wrongArgumentsAgain" // string@01d5
+00251c: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002522: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=214
+        0x0007 line=215
+      locals        : 
+
+    #37              : (in LTestBadBootstrapArguments;)
+      name          : 'wrongParameterTypes'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 49
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+002524:                                        |[002524] TestBadBootstrapArguments.wrongParameterTypes:()V
+002534: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002538: 1a01 d601                              |0002: const-string v1, "wrongParameterTypes" // string@01d6
+00253c: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002542: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=102
+        0x0007 line=103
+      locals        : 
+
+  Virtual methods   -
+  source_file_idx   : 144 (TestBadBootstrapArguments.java)
+
+Class #7 header:
+class_idx           : 10
+access_flags        : 0 (0x0000)
+superclass_idx      : 9
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 147
+annotations_off     : 30988 (0x00790c)
+class_data_off      : 29220 (0x007224)
+static_fields_size  : 1
+instance_fields_size: 0
+direct_methods_size : 7
+virtual_methods_size: 0
+
+Class #7 annotations:
+Annotations on method #67 'bsm'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #71 'testDynamic'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestDynamicBootstrapArguments; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/String; J } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; stringValue={ "A" } Lannotations/Constant; longValue={ 100000000 } } fieldOrMethodName="target" parameterTypes={ I Ljava/lang/String; D } returnType=I
+
+Class #7            -
+  Class descriptor  : 'LTestDynamicBootstrapArguments;'
+  Access flags      : 0x0000 ()
+  Superclass        : 'LTestBase;'
+  Interfaces        -
+  Static fields     -
+    #0              : (in LTestDynamicBootstrapArguments;)
+      name          : 'bsmCalls'
+      type          : 'I'
+      access        : 0x000a (PRIVATE STATIC)
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTestDynamicBootstrapArguments;)
+      name          : '<clinit>'
+      type          : '()V'
+      access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 63
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+0029c8:                                        |[0029c8] TestDynamicBootstrapArguments.<clinit>:()V
+0029d8: 1200                                   |0000: const/4 v0, #int 0 // #0
+0029da: 6700 0000                              |0001: sput v0, LTestDynamicBootstrapArguments;.bsmCalls:I // field@0000
+0029de: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=27
+      locals        : 
+
+    #1              : (in LTestDynamicBootstrapArguments;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 64
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+0029e0:                                        |[0029e0] TestDynamicBootstrapArguments.<init>:()V
+0029f0: 7010 3200 0000                         |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+0029f6: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=26
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestDynamicBootstrapArguments; 
+
+    #2              : (in LTestDynamicBootstrapArguments;)
+      name          : 'bsm'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite;'
+      access        : 0x0008 (STATIC)
+      method_idx    : 67
+      code          -
+      registers     : 11
+      ins           : 6
+      outs          : 4
+      insns size    : 43 16-bit code units
+002960:                                        |[002960] TestDynamicBootstrapArguments.bsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite;
+002970: 6000 0000                              |0000: sget v0, LTestDynamicBootstrapArguments;.bsmCalls:I // field@0000
+002974: d800 0001                              |0002: add-int/lit8 v0, v0, #int 1 // #01
+002978: 6700 0000                              |0004: sput v0, LTestDynamicBootstrapArguments;.bsmCalls:I // field@0000
+00297c: 1c00 0a00                              |0006: const-class v0, LTestDynamicBootstrapArguments; // type@000a
+002980: 2201 2d00                              |0008: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+002984: 7010 c100 0100                         |000a: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00298a: 6e20 c800 6100                         |000d: invoke-virtual {v1, v6}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002990: 6e20 c800 8100                         |0010: invoke-virtual {v1, v8}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+002996: 6e30 c600 910a                         |0013: invoke-virtual {v1, v9, v10}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@00c6
+00299c: 6e10 ca00 0100                         |0016: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0029a2: 0c01                                   |0019: move-result-object v1
+0029a4: 6e40 d800 0571                         |001a: invoke-virtual {v5, v0, v1, v7}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+0029aa: 0c02                                   |001d: move-result-object v2
+0029ac: 6203 1300                              |001e: sget-object v3, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0029b0: 1a04 ea00                              |0020: const-string v4, "bsm" // string@00ea
+0029b4: 6e20 b300 4300                         |0022: invoke-virtual {v3, v4}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0029ba: 2203 3400                              |0025: new-instance v3, Ljava/lang/invoke/ConstantCallSite; // type@0034
+0029be: 7020 d200 2300                         |0027: invoke-direct {v3, v2}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+0029c4: 1103                                   |002a: return-object v3
+      catches       : (none)
+      positions     : 
+        0x0000 line=36
+        0x0006 line=37
+        0x0008 line=38
+        0x001a line=39
+        0x001e line=40
+        0x0025 line=41
+      locals        : 
+        0x0008 - 0x002b reg=0 definingClass Ljava/lang/Class; Ljava/lang/Class<*>;
+        0x001a - 0x002b reg=1 methodName Ljava/lang/String; 
+        0x001e - 0x002b reg=2 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x002b reg=5 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x002b reg=6 name Ljava/lang/String; 
+        0x0000 - 0x002b reg=7 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x002b reg=8 otherNameComponent Ljava/lang/String; 
+        0x0000 - 0x002b reg=9 nameSuffix J 
+
+    #3              : (in LTestDynamicBootstrapArguments;)
+      name          : 'targetA100000000'
+      type          : '(ILjava/lang/String;Ljava/lang/Double;)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 68
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 2
+      insns size    : 30 16-bit code units
+0028f8:                                        |[0028f8] TestDynamicBootstrapArguments.targetA100000000:(ILjava/lang/String;Ljava/lang/Double;)I
+002908: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00290c: 6e20 ad00 2000                         |0002: invoke-virtual {v0, v2}, Ljava/io/PrintStream;.print:(I)V // method@00ad
+002912: 6200 1300                              |0005: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002916: 1a01 0c00                              |0007: const-string v1, ", " // string@000c
+00291a: 6e20 b000 1000                         |0009: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002920: 6200 1300                              |000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002924: 6e20 b000 3000                         |000e: invoke-virtual {v0, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+00292a: 6200 1300                              |0011: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00292e: 1a01 0c00                              |0013: const-string v1, ", " // string@000c
+002932: 6e20 b000 1000                         |0015: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002938: 6200 1300                              |0018: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00293c: 6e20 b200 4000                         |001a: invoke-virtual {v0, v4}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002942: 0f02                                   |001d: return v2
+      catches       : (none)
+      positions     : 
+        0x0000 line=71
+        0x0005 line=72
+        0x000c line=73
+        0x0011 line=74
+        0x0018 line=75
+        0x001d line=76
+      locals        : 
+        0x0000 - 0x001e reg=2 i I 
+        0x0000 - 0x001e reg=3 s Ljava/lang/String; 
+        0x0000 - 0x001e reg=4 d Ljava/lang/Double; 
+
+    #4              : (in LTestDynamicBootstrapArguments;)
+      name          : 'test'
+      type          : '()V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 69
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 25 16-bit code units
+0029f8:                                        |[0029f8] TestDynamicBootstrapArguments.test:()V
+002a08: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002a0c: 1a01 9200                              |0002: const-string v1, "TestDynamicArguments" // string@0092
+002a10: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002a16: 7100 4600 0000                         |0007: invoke-static {}, LTestDynamicBootstrapArguments;.testCallSites:()V // method@0046
+002a1c: 6000 0000                              |000a: sget v0, LTestDynamicBootstrapArguments;.bsmCalls:I // field@0000
+002a20: 1231                                   |000c: const/4 v1, #int 3 // #3
+002a22: 7120 4100 0100                         |000d: invoke-static {v1, v0}, LTestDynamicBootstrapArguments;.assertEquals:(II)V // method@0041
+002a28: 7100 4600 0000                         |0010: invoke-static {}, LTestDynamicBootstrapArguments;.testCallSites:()V // method@0046
+002a2e: 6000 0000                              |0013: sget v0, LTestDynamicBootstrapArguments;.bsmCalls:I // field@0000
+002a32: 7120 4100 0100                         |0015: invoke-static {v1, v0}, LTestDynamicBootstrapArguments;.assertEquals:(II)V // method@0041
+002a38: 0e00                                   |0018: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=86
+        0x0007 line=87
+        0x000a line=88
+        0x0010 line=89
+        0x0013 line=90
+        0x0018 line=91
+      locals        : 
+
+    #5              : (in LTestDynamicBootstrapArguments;)
+      name          : 'testCallSites'
+      type          : '()V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 70
+      code          -
+      registers     : 3
+      ins           : 0
+      outs          : 3
+      insns size    : 55 16-bit code units
+002a3c:                                        |[002a3c] TestDynamicBootstrapArguments.testCallSites:()V
+002a4c: 1a00 8b00                              |0000: const-string v0, "One" // string@008b
+002a50: 1801 182d 4454 fb21 0940               |0002: const-wide v1, #double 3.14159 // #400921fb54442d18
+002a5a: 7120 b900 2100                         |0007: invoke-static {v1, v2}, Ljava/lang/Double;.valueOf:(D)Ljava/lang/Double; // method@00b9
+002a60: 0c01                                   |000a: move-result-object v1
+002a62: 1202                                   |000b: const/4 v2, #int 0 // #0
+002a64: fc30 0f00 0201                         |000c: invoke-custom {v2, v0, v1}, call_site@000f
+002a6a: 0a00                                   |000f: move-result v0
+002a6c: 7120 4100 0200                         |0010: invoke-static {v2, v0}, LTestDynamicBootstrapArguments;.assertEquals:(II)V // method@0041
+002a72: 1a00 a200                              |0013: const-string v0, "Two" // string@00a2
+002a76: 1801 6957 148b 0abf 0540               |0015: const-wide v1, #double 2.71828 // #4005bf0a8b145769
+002a80: 7120 b900 2100                         |001a: invoke-static {v1, v2}, Ljava/lang/Double;.valueOf:(D)Ljava/lang/Double; // method@00b9
+002a86: 0c01                                   |001d: move-result-object v1
+002a88: 1212                                   |001e: const/4 v2, #int 1 // #1
+002a8a: fc30 1000 0201                         |001f: invoke-custom {v2, v0, v1}, call_site@0010
+002a90: 0a00                                   |0022: move-result v0
+002a92: 7120 4100 0200                         |0023: invoke-static {v2, v0}, LTestDynamicBootstrapArguments;.assertEquals:(II)V // method@0041
+002a98: 1a00 9f00                              |0026: const-string v0, "Three" // string@009f
+002a9c: 1601 0000                              |0028: const-wide/16 v1, #int 0 // #0
+002aa0: 7120 b900 2100                         |002a: invoke-static {v1, v2}, Ljava/lang/Double;.valueOf:(D)Ljava/lang/Double; // method@00b9
+002aa6: 0c01                                   |002d: move-result-object v1
+002aa8: 1222                                   |002e: const/4 v2, #int 2 // #2
+002aaa: fc30 1100 0201                         |002f: invoke-custom {v2, v0, v1}, call_site@0011
+002ab0: 0a00                                   |0032: move-result v0
+002ab2: 7120 4100 0200                         |0033: invoke-static {v2, v0}, LTestDynamicBootstrapArguments;.assertEquals:(II)V // method@0041
+002ab8: 0e00                                   |0036: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=80
+        0x0013 line=81
+        0x0026 line=82
+        0x0036 line=83
+      locals        : 
+
+    #6              : (in LTestDynamicBootstrapArguments;)
+      name          : 'testDynamic'
+      type          : '(ILjava/lang/String;Ljava/lang/Double;)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 71
+      code          -
+      registers     : 4
+      ins           : 3
+      outs          : 0
+      insns size    : 5 16-bit code units
+002944:                                        |[002944] TestDynamicBootstrapArguments.testDynamic:(ILjava/lang/String;Ljava/lang/Double;)I
+002954: 7100 4200 0000                         |0000: invoke-static {}, LTestDynamicBootstrapArguments;.assertNotReached:()V // method@0042
+00295a: 1200                                   |0003: const/4 v0, #int 0 // #0
+00295c: 0f00                                   |0004: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=66
+        0x0003 line=67
+      locals        : 
+        0x0000 - 0x0005 reg=1 i I 
+        0x0000 - 0x0005 reg=2 s Ljava/lang/String; 
+        0x0000 - 0x0005 reg=3 d Ljava/lang/Double; 
+
+  Virtual methods   -
+  source_file_idx   : 147 (TestDynamicBootstrapArguments.java)
+
+Class #8 header:
+class_idx           : 12
+access_flags        : 0 (0x0000)
+superclass_idx      : 9
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 148
+annotations_off     : 31020 (0x00792c)
+class_data_off      : 29258 (0x00724a)
+static_fields_size  : 1
+instance_fields_size: 1
+direct_methods_size : 18
+virtual_methods_size: 1
+
+Class #8 annotations:
+Annotations on class
+  VISIBILITY_SYSTEM Ldalvik/annotation/MemberClasses; value={ LTestInvocationKinds$Widget; }
+Annotations on method #78 'getInstanceField'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupInstanceFieldGetter" } fieldOrMethodName="instance_field" parameterTypes={ LTestInvocationKinds; } returnType=D
+Annotations on method #80 'getStaticField'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupStaticFieldGetter" } fieldOrMethodName="static_field" parameterTypes={ } returnType=I
+Annotations on method #81 'lookupConstructor'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #82 'lookupInstanceFieldGetter'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #83 'lookupInstanceFieldSetter'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #84 'lookupStaticFieldGetter'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #85 'lookupStaticFieldSetter'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #86 'lookupVirtual'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #87 'makeWidget'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupConstructor" } fieldOrMethodName="unused" parameterTypes={ I } returnType=LTestInvocationKinds$Widget;
+Annotations on method #88 'maxIntegerValue'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupVirtual" } fieldOrMethodName="getMaxIntegerValue" parameterTypes={ LTestInvocationKinds; I I } returnType=I
+Annotations on method #89 'setInstanceField'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupInstanceFieldSetter" } fieldOrMethodName="instance_field" parameterTypes={ LTestInvocationKinds; D } returnType=V
+Annotations on method #90 'setStaticField'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvocationKinds; name="lookupStaticFieldSetter" } fieldOrMethodName="static_field" parameterTypes={ I } returnType=V
+
+Class #8            -
+  Class descriptor  : 'LTestInvocationKinds;'
+  Access flags      : 0x0000 ()
+  Superclass        : 'LTestBase;'
+  Interfaces        -
+  Static fields     -
+    #0              : (in LTestInvocationKinds;)
+      name          : 'static_field'
+      type          : 'I'
+      access        : 0x000a (PRIVATE STATIC)
+  Instance fields   -
+    #0              : (in LTestInvocationKinds;)
+      name          : 'instance_field'
+      type          : 'D'
+      access        : 0x0002 (PRIVATE)
+  Direct methods    -
+    #0              : (in LTestInvocationKinds;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 73
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+002ca4:                                        |[002ca4] TestInvocationKinds.<init>:()V
+002cb4: 7010 3200 0000                         |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+002cba: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=25
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestInvocationKinds; 
+
+    #1              : (in LTestInvocationKinds;)
+      name          : 'getInstanceField'
+      type          : '(LTestInvocationKinds;)D'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 78
+      code          -
+      registers     : 3
+      ins           : 1
+      outs          : 0
+      insns size    : 6 16-bit code units
+002af0:                                        |[002af0] TestInvocationKinds.getInstanceField:(LTestInvocationKinds;)D
+002b00: 7100 4d00 0000                         |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002b06: 1900 f87f                              |0003: const-wide/high16 v0, #long 9221120237041090560 // #7ff8
+002b0a: 1000                                   |0005: return-wide v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=117
+        0x0003 line=118
+      locals        : 
+        0x0000 - 0x0006 reg=2 instance LTestInvocationKinds; 
+
+    #2              : (in LTestInvocationKinds;)
+      name          : 'getStaticField'
+      type          : '()I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 80
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 5 16-bit code units
+002b28:                                        |[002b28] TestInvocationKinds.getStaticField:()I
+002b38: 7100 4d00 0000                         |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002b3e: 1200                                   |0003: const/4 v0, #int 0 // #0
+002b40: 0f00                                   |0004: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=71
+        0x0003 line=72
+      locals        : 
+
+    #3              : (in LTestInvocationKinds;)
+      name          : 'lookupConstructor'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 81
+      code          -
+      registers     : 7
+      ins           : 3
+      outs          : 3
+      insns size    : 20 16-bit code units
+002b60:                                        |[002b60] TestInvocationKinds.lookupConstructor:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002b70: 6e10 e500 0600                         |0000: invoke-virtual {v6}, Ljava/lang/invoke/MethodType;.returnType:()Ljava/lang/Class; // method@00e5
+002b76: 0c00                                   |0003: move-result-object v0
+002b78: 6201 1400                              |0004: sget-object v1, Ljava/lang/Void;.TYPE:Ljava/lang/Class; // field@0014
+002b7c: 6e20 df00 1600                         |0006: invoke-virtual {v6, v1}, Ljava/lang/invoke/MethodType;.changeReturnType:(Ljava/lang/Class;)Ljava/lang/invoke/MethodType; // method@00df
+002b82: 0c01                                   |0009: move-result-object v1
+002b84: 6e30 d500 0401                         |000a: invoke-virtual {v4, v0, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findConstructor:(Ljava/lang/Class;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d5
+002b8a: 0c02                                   |000d: move-result-object v2
+002b8c: 2203 3400                              |000e: new-instance v3, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002b90: 7020 d200 2300                         |0010: invoke-direct {v3, v2}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002b96: 1103                                   |0013: return-object v3
+      catches       : (none)
+      positions     : 
+        0x0000 line=183
+        0x0004 line=184
+        0x000a line=185
+        0x000e line=186
+      locals        : 
+        0x0004 - 0x0014 reg=0 cls Ljava/lang/Class; Ljava/lang/Class<*>;
+        0x000a - 0x0014 reg=1 constructorMethodType Ljava/lang/invoke/MethodType; 
+        0x000e - 0x0014 reg=2 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0014 reg=4 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0014 reg=5 name Ljava/lang/String; 
+        0x0000 - 0x0014 reg=6 methodType Ljava/lang/invoke/MethodType; 
+
+    #4              : (in LTestInvocationKinds;)
+      name          : 'lookupInstanceFieldGetter'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+      access        : 0x0008 (STATIC)
+      method_idx    : 82
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 4
+      insns size    : 20 16-bit code units
+002b98:                                        |[002b98] TestInvocationKinds.lookupInstanceFieldGetter:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002ba8: 0000                                   |0000: nop // spacer
+002baa: 1200                                   |0001: const/4 v0, #int 0 // #0
+002bac: 6e20 e400 0400                         |0002: invoke-virtual {v4, v0}, Ljava/lang/invoke/MethodType;.parameterType:(I)Ljava/lang/Class; // method@00e4
+002bb2: 0c00                                   |0005: move-result-object v0
+002bb4: 6e10 e500 0400                         |0006: invoke-virtual {v4}, Ljava/lang/invoke/MethodType;.returnType:()Ljava/lang/Class; // method@00e5
+002bba: 0c01                                   |0009: move-result-object v1
+002bbc: 6e40 d600 0213                         |000a: invoke-virtual {v2, v0, v3, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findGetter:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; // method@00d6
+002bc2: 0c00                                   |000d: move-result-object v0
+002bc4: 2201 3400                              |000e: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002bc8: 7020 d200 0100                         |0010: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002bce: 1101                                   |0013: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=101
+        0x0001 line=102
+        0x000e line=103
+      locals        : 
+        0x000e - 0x0014 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0014 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0014 reg=3 name Ljava/lang/String; 
+        0x0000 - 0x0014 reg=4 methodType Ljava/lang/invoke/MethodType; 
+
+    #5              : (in LTestInvocationKinds;)
+      name          : 'lookupInstanceFieldSetter'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+      access        : 0x0008 (STATIC)
+      method_idx    : 83
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 4
+      insns size    : 21 16-bit code units
+002bd0:                                        |[002bd0] TestInvocationKinds.lookupInstanceFieldSetter:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002be0: 0000                                   |0000: nop // spacer
+002be2: 1200                                   |0001: const/4 v0, #int 0 // #0
+002be4: 6e20 e400 0400                         |0002: invoke-virtual {v4, v0}, Ljava/lang/invoke/MethodType;.parameterType:(I)Ljava/lang/Class; // method@00e4
+002bea: 0c00                                   |0005: move-result-object v0
+002bec: 1211                                   |0006: const/4 v1, #int 1 // #1
+002bee: 6e20 e400 1400                         |0007: invoke-virtual {v4, v1}, Ljava/lang/invoke/MethodType;.parameterType:(I)Ljava/lang/Class; // method@00e4
+002bf4: 0c01                                   |000a: move-result-object v1
+002bf6: 6e40 d700 0213                         |000b: invoke-virtual {v2, v0, v3, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findSetter:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; // method@00d7
+002bfc: 0c00                                   |000e: move-result-object v0
+002bfe: 2201 3400                              |000f: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002c02: 7020 d200 0100                         |0011: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002c08: 1101                                   |0014: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=78
+        0x0001 line=79
+        0x000f line=80
+      locals        : 
+        0x000f - 0x0015 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0015 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0015 reg=3 name Ljava/lang/String; 
+        0x0000 - 0x0015 reg=4 methodType Ljava/lang/invoke/MethodType; 
+
+    #6              : (in LTestInvocationKinds;)
+      name          : 'lookupStaticFieldGetter'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+      access        : 0x0008 (STATIC)
+      method_idx    : 84
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 4
+      insns size    : 16 16-bit code units
+002c0c:                                        |[002c0c] TestInvocationKinds.lookupStaticFieldGetter:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002c1c: 1c00 0c00                              |0000: const-class v0, LTestInvocationKinds; // type@000c
+002c20: 6e10 e500 0400                         |0002: invoke-virtual {v4}, Ljava/lang/invoke/MethodType;.returnType:()Ljava/lang/Class; // method@00e5
+002c26: 0c01                                   |0005: move-result-object v1
+002c28: 6e40 d900 0213                         |0006: invoke-virtual {v2, v0, v3, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findStaticGetter:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; // method@00d9
+002c2e: 0c00                                   |0009: move-result-object v0
+002c30: 2201 3400                              |000a: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002c34: 7020 d200 0100                         |000c: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002c3a: 1101                                   |000f: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=32
+        0x0002 line=33
+        0x000a line=34
+      locals        : 
+        0x000a - 0x0010 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0010 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0010 reg=3 name Ljava/lang/String; 
+        0x0000 - 0x0010 reg=4 methodType Ljava/lang/invoke/MethodType; 
+
+    #7              : (in LTestInvocationKinds;)
+      name          : 'lookupStaticFieldSetter'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+      access        : 0x0008 (STATIC)
+      method_idx    : 85
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 4
+      insns size    : 17 16-bit code units
+002c3c:                                        |[002c3c] TestInvocationKinds.lookupStaticFieldSetter:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002c4c: 1c00 0c00                              |0000: const-class v0, LTestInvocationKinds; // type@000c
+002c50: 1201                                   |0002: const/4 v1, #int 0 // #0
+002c52: 6e20 e400 1400                         |0003: invoke-virtual {v4, v1}, Ljava/lang/invoke/MethodType;.parameterType:(I)Ljava/lang/Class; // method@00e4
+002c58: 0c01                                   |0006: move-result-object v1
+002c5a: 6e40 da00 0213                         |0007: invoke-virtual {v2, v0, v3, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findStaticSetter:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; // method@00da
+002c60: 0c00                                   |000a: move-result-object v0
+002c62: 2201 3400                              |000b: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002c66: 7020 d200 0100                         |000d: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002c6c: 1101                                   |0010: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=54
+        0x0002 line=56
+        0x0007 line=55
+        0x000b line=57
+      locals        : 
+        0x000b - 0x0011 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0011 reg=2 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0011 reg=3 name Ljava/lang/String; 
+        0x0000 - 0x0011 reg=4 methodType Ljava/lang/invoke/MethodType; 
+
+    #8              : (in LTestInvocationKinds;)
+      name          : 'lookupVirtual'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 86
+      code          -
+      registers     : 6
+      ins           : 3
+      outs          : 4
+      insns size    : 18 16-bit code units
+002c70:                                        |[002c70] TestInvocationKinds.lookupVirtual:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002c80: 1200                                   |0000: const/4 v0, #int 0 // #0
+002c82: 1211                                   |0001: const/4 v1, #int 1 // #1
+002c84: 6e30 e000 0501                         |0002: invoke-virtual {v5, v0, v1}, Ljava/lang/invoke/MethodType;.dropParameterTypes:(II)Ljava/lang/invoke/MethodType; // method@00e0
+002c8a: 0c00                                   |0005: move-result-object v0
+002c8c: 1c01 0c00                              |0006: const-class v1, LTestInvocationKinds; // type@000c
+002c90: 6e40 db00 1304                         |0008: invoke-virtual {v3, v1, v4, v0}, Ljava/lang/invoke/MethodHandles$Lookup;.findVirtual:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00db
+002c96: 0c01                                   |000b: move-result-object v1
+002c98: 2202 3400                              |000c: new-instance v2, Ljava/lang/invoke/ConstantCallSite; // type@0034
+002c9c: 7020 d200 1200                         |000e: invoke-direct {v2, v1}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+002ca2: 1102                                   |0011: return-object v2
+      catches       : (none)
+      positions     : 
+        0x0000 line=146
+        0x0006 line=147
+        0x000c line=148
+      locals        : 
+        0x0006 - 0x0012 reg=0 mt Ljava/lang/invoke/MethodType; 
+        0x000c - 0x0012 reg=1 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0012 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0012 reg=4 name Ljava/lang/String; 
+        0x0000 - 0x0012 reg=5 methodType Ljava/lang/invoke/MethodType; 
+
+    #9              : (in LTestInvocationKinds;)
+      name          : 'makeWidget'
+      type          : '(I)LTestInvocationKinds$Widget;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 87
+      code          -
+      registers     : 2
+      ins           : 1
+      outs          : 0
+      insns size    : 5 16-bit code units
+002ad4:                                        |[002ad4] TestInvocationKinds.makeWidget:(I)LTestInvocationKinds$Widget;
+002ae4: 7100 4d00 0000                         |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002aea: 1200                                   |0003: const/4 v0, #int 0 // #0
+002aec: 1100                                   |0004: return-object v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=200
+        0x0003 line=201
+      locals        : 
+        0x0000 - 0x0005 reg=1 v I 
+
+    #10              : (in LTestInvocationKinds;)
+      name          : 'maxIntegerValue'
+      type          : '(LTestInvocationKinds;II)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 88
+      code          -
+      registers     : 4
+      ins           : 3
+      outs          : 0
+      insns size    : 5 16-bit code units
+002b44:                                        |[002b44] TestInvocationKinds.maxIntegerValue:(LTestInvocationKinds;II)I
+002b54: 7100 4d00 0000                         |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002b5a: 1200                                   |0003: const/4 v0, #int 0 // #0
+002b5c: 0f00                                   |0004: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=159
+        0x0003 line=160
+      locals        : 
+        0x0000 - 0x0005 reg=1 receiver LTestInvocationKinds; 
+        0x0000 - 0x0005 reg=2 x I 
+        0x0000 - 0x0005 reg=3 y I 
+
+    #11              : (in LTestInvocationKinds;)
+      name          : 'setInstanceField'
+      type          : '(LTestInvocationKinds;D)V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 89
+      code          -
+      registers     : 5
+      ins           : 3
+      outs          : 0
+      insns size    : 8 16-bit code units
+002cbc:                                        |[002cbc] TestInvocationKinds.setInstanceField:(LTestInvocationKinds;D)V
+002ccc: 7100 4d00 0000                         |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002cd2: 1900 f87f                              |0003: const-wide/high16 v0, #long 9221120237041090560 // #7ff8
+002cd6: 5a20 0200                              |0005: iput-wide v0, v2, LTestInvocationKinds;.instance_field:D // field@0002
+002cda: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=94
+        0x0003 line=95
+        0x0007 line=96
+      locals        : 
+        0x0000 - 0x0008 reg=2 instance LTestInvocationKinds; 
+        0x0000 - 0x0008 reg=3 value D 
+
+    #12              : (in LTestInvocationKinds;)
+      name          : 'setStaticField'
+      type          : '(I)V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 90
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 0
+      insns size    : 4 16-bit code units
+002cdc:                                        |[002cdc] TestInvocationKinds.setStaticField:(I)V
+002cec: 7100 4d00 0000                         |0000: invoke-static {}, LTestInvocationKinds;.assertNotReached:()V // method@004d
+002cf2: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=48
+        0x0003 line=49
+      locals        : 
+        0x0000 - 0x0004 reg=0 value I 
+
+    #13              : (in LTestInvocationKinds;)
+      name          : 'test'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 91
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 24 16-bit code units
+002cf4:                                        |[002cf4] TestInvocationKinds.test:()V
+002d04: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002d08: 1c01 0c00                              |0002: const-class v1, LTestInvocationKinds; // type@000c
+002d0c: 6e10 b700 0100                         |0004: invoke-virtual {v1}, Ljava/lang/Class;.getName:()Ljava/lang/String; // method@00b7
+002d12: 0c01                                   |0007: move-result-object v1
+002d14: 6e20 b300 1000                         |0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002d1a: 7100 5f00 0000                         |000b: invoke-static {}, LTestInvocationKinds;.testStaticFieldAccessors:()V // method@005f
+002d20: 7100 5d00 0000                         |000e: invoke-static {}, LTestInvocationKinds;.testInstanceFieldAccessors:()V // method@005d
+002d26: 7100 5e00 0000                         |0011: invoke-static {}, LTestInvocationKinds;.testInvokeVirtual:()V // method@005e
+002d2c: 7100 5c00 0000                         |0014: invoke-static {}, LTestInvocationKinds;.testConstructor:()V // method@005c
+002d32: 0e00                                   |0017: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=212
+        0x000b line=213
+        0x000e line=214
+        0x0011 line=215
+        0x0014 line=216
+        0x0017 line=217
+      locals        : 
+
+    #14              : (in LTestInvocationKinds;)
+      name          : 'testConstructor'
+      type          : '()V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 92
+      code          -
+      registers     : 3
+      ins           : 0
+      outs          : 2
+      insns size    : 31 16-bit code units
+002d34:                                        |[002d34] TestInvocationKinds.testConstructor:()V
+002d44: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002d48: 1a01 b601                              |0002: const-string v1, "testConstructor => " // string@01b6
+002d4c: 6e20 b000 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002d52: 1230                                   |0007: const/4 v0, #int 3 // #3
+002d54: fc10 1200 0000                         |0008: invoke-custom {v0}, call_site@0012
+002d5a: 0c00                                   |000b: move-result-object v0
+002d5c: 1c01 0b00                              |000c: const-class v1, LTestInvocationKinds$Widget; // type@000b
+002d60: 6e10 c000 0000                         |000e: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002d66: 0c02                                   |0011: move-result-object v2
+002d68: 7120 4c00 2100                         |0012: invoke-static {v1, v2}, LTestInvocationKinds;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@004c
+002d6e: 6201 1300                              |0015: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002d72: 6e10 c000 0000                         |0017: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+002d78: 0c02                                   |001a: move-result-object v2
+002d7a: 6e20 b200 2100                         |001b: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+002d80: 0e00                                   |001e: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=205
+        0x0007 line=206
+        0x000c line=207
+        0x0015 line=208
+        0x001e line=209
+      locals        : 
+        0x000c - 0x001f reg=0 receiver LTestInvocationKinds$Widget; 
+
+    #15              : (in LTestInvocationKinds;)
+      name          : 'testInstanceFieldAccessors'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 93
+      code          -
+      registers     : 5
+      ins           : 0
+      outs          : 4
+      insns size    : 44 16-bit code units
+002d84:                                        |[002d84] TestInvocationKinds.testInstanceFieldAccessors:()V
+002d94: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002d98: 1a01 b801                              |0002: const-string v1, "testInstanceFieldAccessors" // string@01b8
+002d9c: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002da2: 2200 0c00                              |0007: new-instance v0, LTestInvocationKinds; // type@000c
+002da6: 7010 4900 0000                         |0009: invoke-direct {v0}, LTestInvocationKinds;.<init>:()V // method@0049
+002dac: 1601 0100                              |000c: const-wide/16 v1, #int 1 // #1
+002db0: 5a01 0200                              |000e: iput-wide v1, v0, LTestInvocationKinds;.instance_field:D // field@0002
+002db4: 1801 182d 4454 fb21 0940               |0010: const-wide v1, #double 3.14159 // #400921fb54442d18
+002dbe: fc30 1300 1002                         |0015: invoke-custom {v0, v1, v2}, call_site@0013
+002dc4: 5303 0200                              |0018: iget-wide v3, v0, LTestInvocationKinds;.instance_field:D // field@0002
+002dc8: 7140 4a00 2143                         |001a: invoke-static {v1, v2, v3, v4}, LTestInvocationKinds;.assertEquals:(DD)V // method@004a
+002dce: 1801 6957 148b 0abf 0540               |001d: const-wide v1, #double 2.71828 // #4005bf0a8b145769
+002dd8: 5a01 0200                              |0022: iput-wide v1, v0, LTestInvocationKinds;.instance_field:D // field@0002
+002ddc: fc10 1400 0000                         |0024: invoke-custom {v0}, call_site@0014
+002de2: 0b03                                   |0027: move-result-wide v3
+002de4: 7140 4a00 2143                         |0028: invoke-static {v1, v2, v3, v4}, LTestInvocationKinds;.assertEquals:(DD)V // method@004a
+002dea: 0e00                                   |002b: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=133
+        0x0007 line=134
+        0x000c line=135
+        0x0010 line=136
+        0x0018 line=137
+        0x001d line=138
+        0x0024 line=139
+        0x002b line=140
+      locals        : 
+        0x000c - 0x002c reg=0 instance LTestInvocationKinds; 
+
+    #16              : (in LTestInvocationKinds;)
+      name          : 'testInvokeVirtual'
+      type          : '()V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 94
+      code          -
+      registers     : 3
+      ins           : 0
+      outs          : 3
+      insns size    : 25 16-bit code units
+002dec:                                        |[002dec] TestInvocationKinds.testInvokeVirtual:()V
+002dfc: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002e00: 1a01 ba01                              |0002: const-string v1, "testInvokeVirtual => max(77, -3) = " // string@01ba
+002e04: 6e20 b000 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+002e0a: 2200 0c00                              |0007: new-instance v0, LTestInvocationKinds; // type@000c
+002e0e: 7010 4900 0000                         |0009: invoke-direct {v0}, LTestInvocationKinds;.<init>:()V // method@0049
+002e14: 1301 4d00                              |000c: const/16 v1, #int 77 // #4d
+002e18: 12d2                                   |000e: const/4 v2, #int -3 // #fd
+002e1a: fc30 1500 1002                         |000f: invoke-custom {v0, v1, v2}, call_site@0015
+002e20: 0a01                                   |0012: move-result v1
+002e22: 6202 1300                              |0013: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002e26: 6e20 b100 1200                         |0015: invoke-virtual {v2, v1}, Ljava/io/PrintStream;.println:(I)V // method@00b1
+002e2c: 0e00                                   |0018: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=168
+        0x0007 line=169
+        0x000c line=170
+        0x0013 line=171
+        0x0018 line=172
+      locals        : 
+        0x000c - 0x0019 reg=0 receiver LTestInvocationKinds; 
+        0x0013 - 0x0019 reg=1 result I 
+
+    #17              : (in LTestInvocationKinds;)
+      name          : 'testStaticFieldAccessors'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 95
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 47 16-bit code units
+002e30:                                        |[002e30] TestInvocationKinds.testStaticFieldAccessors:()V
+002e40: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+002e44: 1a01 bb01                              |0002: const-string v1, "testStaticFieldAccessors" // string@01bb
+002e48: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+002e4e: 1230                                   |0007: const/4 v0, #int 3 // #3
+002e50: fc10 1600 0000                         |0008: invoke-custom {v0}, call_site@0016
+002e56: 6001 0300                              |000b: sget v1, LTestInvocationKinds;.static_field:I // field@0003
+002e5a: 7120 4b00 0100                         |000d: invoke-static {v1, v0}, LTestInvocationKinds;.assertEquals:(II)V // method@004b
+002e60: 1240                                   |0010: const/4 v0, #int 4 // #4
+002e62: fc10 1700 0000                         |0011: invoke-custom {v0}, call_site@0017
+002e68: 6001 0300                              |0014: sget v1, LTestInvocationKinds;.static_field:I // field@0003
+002e6c: 7120 4b00 0100                         |0016: invoke-static {v1, v0}, LTestInvocationKinds;.assertEquals:(II)V // method@004b
+002e72: 6000 0300                              |0019: sget v0, LTestInvocationKinds;.static_field:I // field@0003
+002e76: fc00 1800 0000                         |001b: invoke-custom {}, call_site@0018
+002e7c: 0a01                                   |001e: move-result v1
+002e7e: 7120 4b00 1000                         |001f: invoke-static {v0, v1}, LTestInvocationKinds;.assertEquals:(II)V // method@004b
+002e84: 1400 ffff ff7f                         |0022: const v0, #float nan // #7fffffff
+002e8a: 6700 0300                              |0025: sput v0, LTestInvocationKinds;.static_field:I // field@0003
+002e8e: fc00 1900 0000                         |0027: invoke-custom {}, call_site@0019
+002e94: 0a01                                   |002a: move-result v1
+002e96: 7120 4b00 1000                         |002b: invoke-static {v0, v1}, LTestInvocationKinds;.assertEquals:(II)V // method@004b
+002e9c: 0e00                                   |002e: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=122
+        0x0007 line=123
+        0x000b line=124
+        0x0010 line=125
+        0x0014 line=126
+        0x0019 line=127
+        0x0022 line=128
+        0x0027 line=129
+        0x002e line=130
+      locals        : 
+
+  Virtual methods   -
+    #0              : (in LTestInvocationKinds;)
+      name          : 'getMaxIntegerValue'
+      type          : '(II)I'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 79
+      code          -
+      registers     : 4
+      ins           : 3
+      outs          : 0
+      insns size    : 6 16-bit code units
+002b0c:                                        |[002b0c] TestInvocationKinds.getMaxIntegerValue:(II)I
+002b1c: 3732 0400                              |0000: if-le v2, v3, 0004 // +0004
+002b20: 0120                                   |0002: move v0, v2
+002b22: 2802                                   |0003: goto 0005 // +0002
+002b24: 0130                                   |0004: move v0, v3
+002b26: 0f00                                   |0005: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=164
+      locals        : 
+        0x0000 - 0x0006 reg=1 this LTestInvocationKinds; 
+        0x0000 - 0x0006 reg=2 x I 
+        0x0000 - 0x0006 reg=3 y I 
+
+  source_file_idx   : 148 (TestInvocationKinds.java)
+
+Class #9 header:
+class_idx           : 14
+access_flags        : 1 (0x0001)
+superclass_idx      : 9
+interfaces_off      : 18256 (0x004750)
+source_file_idx     : 149
+annotations_off     : 31132 (0x00799c)
+class_data_off      : 29344 (0x0072a0)
+static_fields_size  : 7
+instance_fields_size: 0
+direct_methods_size : 8
+virtual_methods_size: 1
+
+Class #9 annotations:
+Annotations on field #10 'threadIndex'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value={ "Ljava/lang/ThreadLocal<" "Ljava/lang/Integer;" ">;" }
+Annotations on method #106 'linkerMethod'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #109 'setCalled'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestInvokeCustomWithConcurrentThreads; name="linkerMethod" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } } fieldOrMethodName="setCalled" parameterTypes={ I } returnType=I
+Annotations on method #110 'test'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #9            -
+  Class descriptor  : 'LTestInvokeCustomWithConcurrentThreads;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'LTestBase;'
+  Interfaces        -
+    #0              : 'Ljava/lang/Runnable;'
+  Static fields     -
+    #0              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'NUMBER_OF_THREADS'
+      type          : 'I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+      value         : 16
+    #1              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'barrier'
+      type          : 'Ljava/util/concurrent/CyclicBarrier;'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #2              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'called'
+      type          : '[Ljava/util/concurrent/atomic/AtomicInteger;'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #3              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'instantiated'
+      type          : '[Ljava/lang/invoke/CallSite;'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #4              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'nextIndex'
+      type          : 'Ljava/util/concurrent/atomic/AtomicInteger;'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #5              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'targetted'
+      type          : '[Ljava/util/concurrent/atomic/AtomicInteger;'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+    #6              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'threadIndex'
+      type          : 'Ljava/lang/ThreadLocal;'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : '<clinit>'
+      type          : '()V'
+      access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 99
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 37 16-bit code units
+003064:                                        |[003064] TestInvokeCustomWithConcurrentThreads.<clinit>:()V
+003074: 2200 3e00                              |0000: new-instance v0, Ljava/util/concurrent/atomic/AtomicInteger; // type@003e
+003078: 1201                                   |0002: const/4 v1, #int 0 // #0
+00307a: 7020 ef00 1000                         |0003: invoke-direct {v0, v1}, Ljava/util/concurrent/atomic/AtomicInteger;.<init>:(I)V // method@00ef
+003080: 6900 0800                              |0006: sput-object v0, LTestInvokeCustomWithConcurrentThreads;.nextIndex:Ljava/util/concurrent/atomic/AtomicInteger; // field@0008
+003084: 2200 0d00                              |0008: new-instance v0, LTestInvokeCustomWithConcurrentThreads$1; // type@000d
+003088: 7010 6000 0000                         |000a: invoke-direct {v0}, LTestInvokeCustomWithConcurrentThreads$1;.<init>:()V // method@0060
+00308e: 6900 0a00                              |000d: sput-object v0, LTestInvokeCustomWithConcurrentThreads;.threadIndex:Ljava/lang/ThreadLocal; // field@000a
+003092: 1300 1000                              |000f: const/16 v0, #int 16 // #10
+003096: 2301 4b00                              |0011: new-array v1, v0, [Ljava/lang/invoke/CallSite; // type@004b
+00309a: 6901 0700                              |0013: sput-object v1, LTestInvokeCustomWithConcurrentThreads;.instantiated:[Ljava/lang/invoke/CallSite; // field@0007
+00309e: 2301 4c00                              |0015: new-array v1, v0, [Ljava/util/concurrent/atomic/AtomicInteger; // type@004c
+0030a2: 6901 0600                              |0017: sput-object v1, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+0030a6: 2301 4c00                              |0019: new-array v1, v0, [Ljava/util/concurrent/atomic/AtomicInteger; // type@004c
+0030aa: 6901 0900                              |001b: sput-object v1, LTestInvokeCustomWithConcurrentThreads;.targetted:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0009
+0030ae: 2201 3d00                              |001d: new-instance v1, Ljava/util/concurrent/CyclicBarrier; // type@003d
+0030b2: 7020 ed00 0100                         |001f: invoke-direct {v1, v0}, Ljava/util/concurrent/CyclicBarrier;.<init>:(I)V // method@00ed
+0030b8: 6901 0500                              |0022: sput-object v1, LTestInvokeCustomWithConcurrentThreads;.barrier:Ljava/util/concurrent/CyclicBarrier; // field@0005
+0030bc: 0e00                                   |0024: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=30
+        0x0008 line=32
+        0x000f line=41
+        0x0015 line=44
+        0x0019 line=47
+        0x001d line=50
+      locals        : 
+
+    #1              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10002 (PRIVATE CONSTRUCTOR)
+      method_idx    : 100
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+0030c0:                                        |[0030c0] TestInvokeCustomWithConcurrentThreads.<init>:()V
+0030d0: 7010 3200 0000                         |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+0030d6: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=52
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestInvokeCustomWithConcurrentThreads; 
+
+    #2              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'access$000'
+      type          : '()Ljava/util/concurrent/atomic/AtomicInteger;'
+      access        : 0x1008 (STATIC SYNTHETIC)
+      method_idx    : 101
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 3 16-bit code units
+00304c:                                        |[00304c] TestInvokeCustomWithConcurrentThreads.access$000:()Ljava/util/concurrent/atomic/AtomicInteger;
+00305c: 6200 0800                              |0000: sget-object v0, LTestInvokeCustomWithConcurrentThreads;.nextIndex:Ljava/util/concurrent/atomic/AtomicInteger; // field@0008
+003060: 1100                                   |0002: return-object v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=27
+      locals        : 
+
+    #3              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'getThreadIndex'
+      type          : '()I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 105
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 1
+      insns size    : 13 16-bit code units
+002f00:                                        |[002f00] TestInvokeCustomWithConcurrentThreads.getThreadIndex:()I
+002f10: 6200 0a00                              |0000: sget-object v0, LTestInvokeCustomWithConcurrentThreads;.threadIndex:Ljava/lang/ThreadLocal; // field@000a
+002f14: 6e10 d000 0000                         |0002: invoke-virtual {v0}, Ljava/lang/ThreadLocal;.get:()Ljava/lang/Object; // method@00d0
+002f1a: 0c00                                   |0005: move-result-object v0
+002f1c: 1f00 2700                              |0006: check-cast v0, Ljava/lang/Integer; // type@0027
+002f20: 6e10 bc00 0000                         |0008: invoke-virtual {v0}, Ljava/lang/Integer;.intValue:()I // method@00bc
+002f26: 0a00                                   |000b: move-result v0
+002f28: 0f00                                   |000c: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=55
+      locals        : 
+
+    #4              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'linkerMethod'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 106
+      code          -
+      registers     : 8
+      ins           : 3
+      outs          : 4
+      insns size    : 97 16-bit code units
+002f78:                                        |[002f78] TestInvokeCustomWithConcurrentThreads.linkerMethod:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+002f88: 1c00 0e00                              |0000: const-class v0, LTestInvokeCustomWithConcurrentThreads; // type@000e
+002f8c: 6e40 d800 0576                         |0002: invoke-virtual {v5, v0, v6, v7}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+002f92: 0c00                                   |0005: move-result-object v0
+002f94: 6e10 d400 0000                         |0006: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandle;.type:()Ljava/lang/invoke/MethodType; // method@00d4
+002f9a: 0c01                                   |0009: move-result-object v1
+002f9c: 7120 6700 1700                         |000a: invoke-static {v7, v1}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0067
+002fa2: 6e10 d400 0000                         |000d: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandle;.type:()Ljava/lang/invoke/MethodType; // method@00d4
+002fa8: 0c01                                   |0010: move-result-object v1
+002faa: 6e10 e300 0100                         |0011: invoke-virtual {v1}, Ljava/lang/invoke/MethodType;.parameterCount:()I // method@00e3
+002fb0: 0a01                                   |0014: move-result v1
+002fb2: 1212                                   |0015: const/4 v2, #int 1 // #1
+002fb4: 7120 6600 2100                         |0016: invoke-static {v1, v2}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(II)V // method@0066
+002fba: 2321 4800                              |0019: new-array v1, v2, [Ljava/lang/Object; // type@0048
+002fbe: 7100 6900 0000                         |001b: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.getThreadIndex:()I // method@0069
+002fc4: 0a03                                   |001e: move-result v3
+002fc6: 7110 bd00 0300                         |001f: invoke-static {v3}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+002fcc: 0c03                                   |0022: move-result-object v3
+002fce: 1204                                   |0023: const/4 v4, #int 0 // #0
+002fd0: 4d03 0104                              |0024: aput-object v3, v1, v4
+002fd4: 7130 de00 4001                         |0026: invoke-static {v0, v4, v1}, Ljava/lang/invoke/MethodHandles;.insertArguments:(Ljava/lang/invoke/MethodHandle;I[Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle; // method@00de
+002fda: 0c00                                   |0029: move-result-object v0
+002fdc: 2321 4600                              |002a: new-array v1, v2, [Ljava/lang/Class; // type@0046
+002fe0: 6203 1200                              |002c: sget-object v3, Ljava/lang/Integer;.TYPE:Ljava/lang/Class; // field@0012
+002fe4: 4d03 0104                              |002e: aput-object v3, v1, v4
+002fe8: 7130 dd00 4001                         |0030: invoke-static {v0, v4, v1}, Ljava/lang/invoke/MethodHandles;.dropArguments:(Ljava/lang/invoke/MethodHandle;I[Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle; // method@00dd
+002fee: 0c00                                   |0033: move-result-object v0
+002ff0: 6e10 d400 0000                         |0034: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandle;.type:()Ljava/lang/invoke/MethodType; // method@00d4
+002ff6: 0c01                                   |0037: move-result-object v1
+002ff8: 6e10 e300 0100                         |0038: invoke-virtual {v1}, Ljava/lang/invoke/MethodType;.parameterCount:()I // method@00e3
+002ffe: 0a01                                   |003b: move-result v1
+003000: 7120 6600 2100                         |003c: invoke-static {v1, v2}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(II)V // method@0066
+003006: 6e10 d400 0000                         |003f: invoke-virtual {v0}, Ljava/lang/invoke/MethodHandle;.type:()Ljava/lang/invoke/MethodType; // method@00d4
+00300c: 0c01                                   |0042: move-result-object v1
+00300e: 7120 6700 1700                         |0043: invoke-static {v7, v1}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0067
+003014: 6201 0500                              |0046: sget-object v1, LTestInvokeCustomWithConcurrentThreads;.barrier:Ljava/util/concurrent/CyclicBarrier; // field@0005
+003018: 6e10 ee00 0100                         |0048: invoke-virtual {v1}, Ljava/util/concurrent/CyclicBarrier;.await:()I // method@00ee
+00301e: 6201 0700                              |004b: sget-object v1, LTestInvokeCustomWithConcurrentThreads;.instantiated:[Ljava/lang/invoke/CallSite; // field@0007
+003022: 7100 6900 0000                         |004d: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.getThreadIndex:()I // method@0069
+003028: 0a02                                   |0050: move-result v2
+00302a: 2203 3400                              |0051: new-instance v3, Ljava/lang/invoke/ConstantCallSite; // type@0034
+00302e: 7020 d200 0300                         |0053: invoke-direct {v3, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003034: 4d03 0102                              |0056: aput-object v3, v1, v2
+003038: 6201 0700                              |0058: sget-object v1, LTestInvokeCustomWithConcurrentThreads;.instantiated:[Ljava/lang/invoke/CallSite; // field@0007
+00303c: 7100 6900 0000                         |005a: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.getThreadIndex:()I // method@0069
+003042: 0a02                                   |005d: move-result v2
+003044: 4601 0102                              |005e: aget-object v1, v1, v2
+003048: 1101                                   |0060: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=87
+        0x0002 line=88
+        0x0006 line=89
+        0x000d line=90
+        0x0019 line=91
+        0x002a line=92
+        0x0034 line=93
+        0x003f line=94
+        0x0046 line=99
+        0x004b line=101
+        0x0058 line=102
+      locals        : 
+        0x0006 - 0x0061 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0061 reg=5 caller Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0061 reg=6 name Ljava/lang/String; 
+        0x0000 - 0x0061 reg=7 methodType Ljava/lang/invoke/MethodType; 
+
+    #5              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'notUsed'
+      type          : '(I)I'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 107
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 0
+      insns size    : 1 16-bit code units
+002f2c:                                        |[002f2c] TestInvokeCustomWithConcurrentThreads.notUsed:(I)I
+002f3c: 0f00                                   |0000: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=59
+      locals        : 
+        0x0000 - 0x0001 reg=0 x I 
+
+    #6              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'setCalled'
+      type          : '(I)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 109
+      code          -
+      registers     : 3
+      ins           : 1
+      outs          : 2
+      insns size    : 20 16-bit code units
+002f40:                                        |[002f40] TestInvokeCustomWithConcurrentThreads.setCalled:(I)I
+002f50: 6200 0600                              |0000: sget-object v0, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+002f54: 4600 0002                              |0002: aget-object v0, v0, v2
+002f58: 6e10 f100 0000                         |0004: invoke-virtual {v0}, Ljava/util/concurrent/atomic/AtomicInteger;.getAndIncrement:()I // method@00f1
+002f5e: 6200 0900                              |0007: sget-object v0, LTestInvokeCustomWithConcurrentThreads;.targetted:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0009
+002f62: 7100 6900 0000                         |0009: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.getThreadIndex:()I // method@0069
+002f68: 0a01                                   |000c: move-result v1
+002f6a: 4600 0001                              |000d: aget-object v0, v0, v1
+002f6e: 6e20 f200 2000                         |000f: invoke-virtual {v0, v2}, Ljava/util/concurrent/atomic/AtomicInteger;.set:(I)V // method@00f2
+002f74: 1200                                   |0012: const/4 v0, #int 0 // #0
+002f76: 0f00                                   |0013: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=79
+        0x0007 line=80
+        0x0012 line=81
+      locals        : 
+        0x0000 - 0x0014 reg=2 index I 
+
+    #7              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'test'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 110
+      code          -
+      registers     : 12
+      ins           : 0
+      outs          : 3
+      insns size    : 229 16-bit code units
+0030fc:                                        |[0030fc] TestInvokeCustomWithConcurrentThreads.test:()V
+00310c: 1200                                   |0000: const/4 v0, #int 0 // #0
+00310e: 0101                                   |0001: move v1, v0
+003110: 1302 1000                              |0002: const/16 v2, #int 16 // #10
+003114: 3521 1700                              |0004: if-ge v1, v2, 001b // +0017
+003118: 6202 0600                              |0006: sget-object v2, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+00311c: 2203 3e00                              |0008: new-instance v3, Ljava/util/concurrent/atomic/AtomicInteger; // type@003e
+003120: 7020 ef00 0300                         |000a: invoke-direct {v3, v0}, Ljava/util/concurrent/atomic/AtomicInteger;.<init>:(I)V // method@00ef
+003126: 4d03 0201                              |000d: aput-object v3, v2, v1
+00312a: 6202 0900                              |000f: sget-object v2, LTestInvokeCustomWithConcurrentThreads;.targetted:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0009
+00312e: 2203 3e00                              |0011: new-instance v3, Ljava/util/concurrent/atomic/AtomicInteger; // type@003e
+003132: 7020 ef00 0300                         |0013: invoke-direct {v3, v0}, Ljava/util/concurrent/atomic/AtomicInteger;.<init>:(I)V // method@00ef
+003138: 4d03 0201                              |0016: aput-object v3, v2, v1
+00313c: d801 0101                              |0018: add-int/lit8 v1, v1, #int 1 // #01
+003140: 28e8                                   |001a: goto 0002 // -0018
+003142: 2321 4a00                              |001b: new-array v1, v2, [Ljava/lang/Thread; // type@004a
+003146: 0103                                   |001d: move v3, v0
+003148: 3523 1600                              |001e: if-ge v3, v2, 0034 // +0016
+00314c: 2204 2f00                              |0020: new-instance v4, Ljava/lang/Thread; // type@002f
+003150: 2205 0e00                              |0022: new-instance v5, LTestInvokeCustomWithConcurrentThreads; // type@000e
+003154: 7010 6400 0500                         |0024: invoke-direct {v5}, LTestInvokeCustomWithConcurrentThreads;.<init>:()V // method@0064
+00315a: 7020 cb00 5400                         |0027: invoke-direct {v4, v5}, Ljava/lang/Thread;.<init>:(Ljava/lang/Runnable;)V // method@00cb
+003160: 4d04 0103                              |002a: aput-object v4, v1, v3
+003164: 4604 0103                              |002c: aget-object v4, v1, v3
+003168: 6e10 ce00 0400                         |002e: invoke-virtual {v4}, Ljava/lang/Thread;.start:()V // method@00ce
+00316e: d803 0301                              |0031: add-int/lit8 v3, v3, #int 1 // #01
+003172: 28eb                                   |0033: goto 001e // -0015
+003174: 0103                                   |0034: move v3, v0
+003176: 3523 0a00                              |0035: if-ge v3, v2, 003f // +000a
+00317a: 4604 0103                              |0037: aget-object v4, v1, v3
+00317e: 6e10 cd00 0400                         |0039: invoke-virtual {v4}, Ljava/lang/Thread;.join:()V // method@00cd
+003184: d803 0301                              |003c: add-int/lit8 v3, v3, #int 1 // #01
+003188: 28f7                                   |003e: goto 0035 // -0009
+00318a: 1203                                   |003f: const/4 v3, #int 0 // #0
+00318c: 1204                                   |0040: const/4 v4, #int 0 // #0
+00318e: 0145                                   |0041: move v5, v4
+003190: 0134                                   |0042: move v4, v3
+003192: 0103                                   |0043: move v3, v0
+003194: 3523 2200                              |0044: if-ge v3, v2, 0066 // +0022
+003198: 6206 0700                              |0046: sget-object v6, LTestInvokeCustomWithConcurrentThreads;.instantiated:[Ljava/lang/invoke/CallSite; // field@0007
+00319c: 4606 0603                              |0048: aget-object v6, v6, v3
+0031a0: 1207                                   |004a: const/4 v7, #int 0 // #0
+0031a2: 7120 6800 7600                         |004b: invoke-static {v6, v7}, LTestInvokeCustomWithConcurrentThreads;.assertNotEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0068
+0031a8: 6206 0600                              |004e: sget-object v6, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+0031ac: 4606 0603                              |0050: aget-object v6, v6, v3
+0031b0: 6e10 f000 0600                         |0052: invoke-virtual {v6}, Ljava/util/concurrent/atomic/AtomicInteger;.get:()I // method@00f0
+0031b6: 0a06                                   |0055: move-result v6
+0031b8: 3806 0d00                              |0056: if-eqz v6, 0063 // +000d
+0031bc: d804 0401                              |0058: add-int/lit8 v4, v4, #int 1 // #01
+0031c0: 6206 0600                              |005a: sget-object v6, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+0031c4: 4606 0603                              |005c: aget-object v6, v6, v3
+0031c8: 6e10 f000 0600                         |005e: invoke-virtual {v6}, Ljava/util/concurrent/atomic/AtomicInteger;.get:()I // method@00f0
+0031ce: 0a06                                   |0061: move-result v6
+0031d0: b065                                   |0062: add-int/2addr v5, v6
+0031d2: d803 0301                              |0063: add-int/lit8 v3, v3, #int 1 // #01
+0031d6: 28df                                   |0065: goto 0044 // -0021
+0031d8: 6203 1300                              |0066: sget-object v3, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0031dc: 2206 2d00                              |0068: new-instance v6, Ljava/lang/StringBuilder; // type@002d
+0031e0: 7010 c100 0600                         |006a: invoke-direct {v6}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0031e6: 1a07 b800                              |006d: const-string v7, "Winners " // string@00b8
+0031ea: 6e20 c800 7600                         |006f: invoke-virtual {v6, v7}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0031f0: 6e20 c500 4600                         |0072: invoke-virtual {v6, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0031f6: 1a07 0500                              |0075: const-string v7, " Votes " // string@0005
+0031fa: 6e20 c800 7600                         |0077: invoke-virtual {v6, v7}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+003200: 6e20 c500 5600                         |007a: invoke-virtual {v6, v5}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+003206: 6e10 ca00 0600                         |007d: invoke-virtual {v6}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+00320c: 0c06                                   |0080: move-result-object v6
+00320e: 6e20 b300 6300                         |0081: invoke-virtual {v3, v6}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003214: 1223                                   |0084: const/4 v3, #int 2 // #2
+003216: 1216                                   |0085: const/4 v6, #int 1 // #1
+003218: 3264 2c00                              |0086: if-eq v4, v6, 00b2 // +002c
+00321c: 6207 1300                              |0088: sget-object v7, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003220: 1a08 9e00                              |008a: const-string v8, "Threads did not the same call-sites:" // string@009e
+003224: 6e20 b300 8700                         |008c: invoke-virtual {v7, v8}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+00322a: 0107                                   |008f: move v7, v0
+00322c: 3527 2200                              |0090: if-ge v7, v2, 00b2 // +0022
+003230: 6208 1300                              |0092: sget-object v8, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003234: 1a09 0400                              |0094: const-string v9, " Thread % 2d invoked call site instance #%02d
+" // string@0004
+003238: 233a 4800                              |0096: new-array v10, v3, [Ljava/lang/Object; // type@0048
+00323c: 7110 bd00 0700                         |0098: invoke-static {v7}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+003242: 0c0b                                   |009b: move-result-object v11
+003244: 4d0b 0a00                              |009c: aput-object v11, v10, v0
+003248: 620b 0900                              |009e: sget-object v11, LTestInvokeCustomWithConcurrentThreads;.targetted:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0009
+00324c: 460b 0b07                              |00a0: aget-object v11, v11, v7
+003250: 6e10 f000 0b00                         |00a2: invoke-virtual {v11}, Ljava/util/concurrent/atomic/AtomicInteger;.get:()I // method@00f0
+003256: 0a0b                                   |00a5: move-result v11
+003258: 7110 bd00 0b00                         |00a6: invoke-static {v11}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+00325e: 0c0b                                   |00a9: move-result-object v11
+003260: 4d0b 0a06                              |00aa: aput-object v11, v10, v6
+003264: 6e30 ab00 980a                         |00ac: invoke-virtual {v8, v9, v10}, Ljava/io/PrintStream;.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; // method@00ab
+00326a: d807 0701                              |00af: add-int/lit8 v7, v7, #int 1 // #01
+00326e: 28df                                   |00b1: goto 0090 // -0021
+003270: 3225 2c00                              |00b2: if-eq v5, v2, 00de // +002c
+003274: 6207 1300                              |00b4: sget-object v7, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003278: 1a08 2000                              |00b6: const-string v8, "Call-sites invocations :" // string@0020
+00327c: 6e20 b300 8700                         |00b8: invoke-virtual {v7, v8}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003282: 0107                                   |00bb: move v7, v0
+003284: 3527 2200                              |00bc: if-ge v7, v2, 00de // +0022
+003288: 6208 1300                              |00be: sget-object v8, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00328c: 1a09 0300                              |00c0: const-string v9, " Call site instance #%02d was invoked % 2d times
+" // string@0003
+003290: 233a 4800                              |00c2: new-array v10, v3, [Ljava/lang/Object; // type@0048
+003294: 7110 bd00 0700                         |00c4: invoke-static {v7}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+00329a: 0c0b                                   |00c7: move-result-object v11
+00329c: 4d0b 0a00                              |00c8: aput-object v11, v10, v0
+0032a0: 620b 0600                              |00ca: sget-object v11, LTestInvokeCustomWithConcurrentThreads;.called:[Ljava/util/concurrent/atomic/AtomicInteger; // field@0006
+0032a4: 460b 0b07                              |00cc: aget-object v11, v11, v7
+0032a8: 6e10 f000 0b00                         |00ce: invoke-virtual {v11}, Ljava/util/concurrent/atomic/AtomicInteger;.get:()I // method@00f0
+0032ae: 0a0b                                   |00d1: move-result v11
+0032b0: 7110 bd00 0b00                         |00d2: invoke-static {v11}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+0032b6: 0c0b                                   |00d5: move-result-object v11
+0032b8: 4d0b 0a06                              |00d6: aput-object v11, v10, v6
+0032bc: 6e30 ab00 980a                         |00d8: invoke-virtual {v8, v9, v10}, Ljava/io/PrintStream;.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; // method@00ab
+0032c2: d807 0701                              |00db: add-int/lit8 v7, v7, #int 1 // #01
+0032c6: 28df                                   |00dd: goto 00bc // -0021
+0032c8: 7120 6600 6400                         |00de: invoke-static {v4, v6}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(II)V // method@0066
+0032ce: 7120 6600 2500                         |00e1: invoke-static {v5, v2}, LTestInvokeCustomWithConcurrentThreads;.assertEquals:(II)V // method@0066
+0032d4: 0e00                                   |00e4: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=107
+        0x0006 line=108
+        0x000f line=109
+        0x0018 line=107
+        0x001b line=113
+        0x001d line=114
+        0x0020 line=115
+        0x002c line=116
+        0x0031 line=114
+        0x0034 line=120
+        0x0037 line=121
+        0x003c line=120
+        0x003f line=125
+        0x0040 line=126
+        0x0041 line=127
+        0x0046 line=128
+        0x004e line=129
+        0x0058 line=130
+        0x005a line=131
+        0x0063 line=127
+        0x0066 line=135
+        0x0084 line=139
+        0x0088 line=140
+        0x008f line=141
+        0x0092 line=142
+        0x0098 line=143
+        0x00ac line=142
+        0x00af line=141
+        0x00b2 line=149
+        0x00b4 line=150
+        0x00bb line=151
+        0x00be line=152
+        0x00c4 line=153
+        0x00d8 line=152
+        0x00db line=151
+        0x00de line=157
+        0x00e1 line=158
+        0x00e4 line=159
+      locals        : 
+        0x0002 - 0x001b reg=1 i I 
+        0x001e - 0x0034 reg=3 i I 
+        0x0035 - 0x003f reg=3 i I 
+        0x0040 - 0x0044 reg=3 winners I 
+        0x0041 - 0x0044 reg=4 votes I 
+        0x0044 - 0x0066 reg=3 i I 
+        0x0090 - 0x00b2 reg=7 i I 
+        0x00bc - 0x00de reg=7 i I 
+        0x001d - 0x00e5 reg=1 threads [Ljava/lang/Thread; 
+        0x0044 - 0x00e5 reg=4 winners I 
+        0x0044 - 0x00e5 reg=5 votes I 
+
+  Virtual methods   -
+    #0              : (in LTestInvokeCustomWithConcurrentThreads;)
+      name          : 'run'
+      type          : '()V'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 108
+      code          -
+      registers     : 2
+      ins           : 1
+      outs          : 1
+      insns size    : 9 16-bit code units
+0030d8:                                        |[0030d8] TestInvokeCustomWithConcurrentThreads.run:()V
+0030e8: 12f0                                   |0000: const/4 v0, #int -1 // #ff
+0030ea: fc10 1a00 0000                         |0001: invoke-custom {v0}, call_site@001a
+0030f0: 0a00                                   |0004: move-result v0
+0030f2: 7110 6b00 0000                         |0005: invoke-static {v0}, LTestInvokeCustomWithConcurrentThreads;.notUsed:(I)I // method@006b
+0030f8: 0e00                                   |0008: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=63
+        0x0005 line=64
+        0x0008 line=65
+      locals        : 
+        0x0005 - 0x0009 reg=0 x I 
+        0x0000 - 0x0009 reg=1 this LTestInvokeCustomWithConcurrentThreads; 
+
+  source_file_idx   : 149 (TestInvokeCustomWithConcurrentThreads.java)
+
+Class #10 header:
+class_idx           : 15
+access_flags        : 1 (0x0001)
+superclass_idx      : 9
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 151
+annotations_off     : 31180 (0x0079cc)
+class_data_off      : 29403 (0x0072db)
+static_fields_size  : 5
+instance_fields_size: 0
+direct_methods_size : 6
+virtual_methods_size: 0
+
+Class #10 annotations:
+Annotations on method #114 'add'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestLinkerMethodMinimalArguments; name="linkerMethod" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; } } fieldOrMethodName="_add" parameterTypes={ I I } returnType=I
+Annotations on method #118 'linkerMethod'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #119 'test'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #10            -
+  Class descriptor  : 'LTestLinkerMethodMinimalArguments;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'LTestBase;'
+  Interfaces        -
+  Static fields     -
+    #0              : (in LTestLinkerMethodMinimalArguments;)
+      name          : 'FAILURE_TYPE_LINKER_METHOD_RETURNS_NULL'
+      type          : 'I'
+      access        : 0x0018 (STATIC FINAL)
+      value         : 1
+    #1              : (in LTestLinkerMethodMinimalArguments;)
+      name          : 'FAILURE_TYPE_LINKER_METHOD_THROWS'
+      type          : 'I'
+      access        : 0x0018 (STATIC FINAL)
+      value         : 2
+    #2              : (in LTestLinkerMethodMinimalArguments;)
+      name          : 'FAILURE_TYPE_NONE'
+      type          : 'I'
+      access        : 0x0018 (STATIC FINAL)
+      value         : 0
+    #3              : (in LTestLinkerMethodMinimalArguments;)
+      name          : 'FAILURE_TYPE_TARGET_METHOD_THROWS'
+      type          : 'I'
+      access        : 0x0018 (STATIC FINAL)
+      value         : 3
+    #4              : (in LTestLinkerMethodMinimalArguments;)
+      name          : 'forceFailureType'
+      type          : 'I'
+      access        : 0x000a (PRIVATE STATIC)
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTestLinkerMethodMinimalArguments;)
+      name          : '<clinit>'
+      type          : '()V'
+      access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 111
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+003404:                                        |[003404] TestLinkerMethodMinimalArguments.<clinit>:()V
+003414: 1200                                   |0000: const/4 v0, #int 0 // #0
+003416: 6700 0f00                              |0001: sput v0, LTestLinkerMethodMinimalArguments;.forceFailureType:I // field@000f
+00341a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=26
+      locals        : 
+
+    #1              : (in LTestLinkerMethodMinimalArguments;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 112
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+00341c:                                        |[00341c] TestLinkerMethodMinimalArguments.<init>:()V
+00342c: 7010 3200 0000                         |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+003432: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=25
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestLinkerMethodMinimalArguments; 
+
+    #2              : (in LTestLinkerMethodMinimalArguments;)
+      name          : '_add'
+      type          : '(II)I'
+      access        : 0x0008 (STATIC)
+      method_idx    : 113
+      code          -
+      registers     : 4
+      ins           : 2
+      outs          : 2
+      insns size    : 23 16-bit code units
+0032d8:                                        |[0032d8] TestLinkerMethodMinimalArguments._add:(II)I
+0032e8: 6000 0f00                              |0000: sget v0, LTestLinkerMethodMinimalArguments;.forceFailureType:I // field@000f
+0032ec: 1231                                   |0002: const/4 v1, #int 3 // #3
+0032ee: 3210 0500                              |0003: if-eq v0, v1, 0008 // +0005
+0032f2: 9000 0203                              |0005: add-int v0, v2, v3
+0032f6: 0f00                                   |0007: return v0
+0032f8: 6200 1300                              |0008: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0032fc: 1a01 a000                              |000a: const-string v1, "Throwing ArithmeticException in add()" // string@00a0
+003300: 6e20 b300 1000                         |000c: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003306: 2200 1d00                              |000f: new-instance v0, Ljava/lang/ArithmeticException; // type@001d
+00330a: 1a01 cc00                              |0011: const-string v1, "add" // string@00cc
+00330e: 7020 b400 1000                         |0013: invoke-direct {v0, v1}, Ljava/lang/ArithmeticException;.<init>:(Ljava/lang/String;)V // method@00b4
+003314: 2700                                   |0016: throw v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=51
+        0x0005 line=55
+        0x0008 line=52
+        0x000f line=53
+      locals        : 
+        0x0000 - 0x0017 reg=2 a I 
+        0x0000 - 0x0017 reg=3 b I 
+
+    #3              : (in LTestLinkerMethodMinimalArguments;)
+      name          : 'add'
+      type          : '(II)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 114
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 0
+      insns size    : 5 16-bit code units
+003318:                                        |[003318] TestLinkerMethodMinimalArguments.add:(II)I
+003328: 7100 7400 0000                         |0000: invoke-static {}, LTestLinkerMethodMinimalArguments;.assertNotReached:()V // method@0074
+00332e: 12f0                                   |0003: const/4 v0, #int -1 // #ff
+003330: 0f00                                   |0004: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=45
+        0x0003 line=46
+      locals        : 
+        0x0000 - 0x0005 reg=1 a I 
+        0x0000 - 0x0005 reg=2 b I 
+
+    #4              : (in LTestLinkerMethodMinimalArguments;)
+      name          : 'linkerMethod'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 118
+      code          -
+      registers     : 7
+      ins           : 3
+      outs          : 4
+      insns size    : 96 16-bit code units
+003334:                                        |[003334] TestLinkerMethodMinimalArguments.linkerMethod:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+003344: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003348: 2201 2d00                              |0002: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+00334c: 7010 c100 0100                         |0004: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+003352: 1a02 6701                              |0007: const-string v2, "linkerMethod failure type " // string@0167
+003356: 6e20 c800 2100                         |0009: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00335c: 6002 0f00                              |000c: sget v2, LTestLinkerMethodMinimalArguments;.forceFailureType:I // field@000f
+003360: 6e20 c500 2100                         |000e: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+003366: 6e10 ca00 0100                         |0011: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+00336c: 0c01                                   |0014: move-result-object v1
+00336e: 6e20 b300 1000                         |0015: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003374: 1c00 0f00                              |0018: const-class v0, LTestLinkerMethodMinimalArguments; // type@000f
+003378: 6e40 d800 0465                         |001a: invoke-virtual {v4, v0, v5, v6}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+00337e: 0c00                                   |001d: move-result-object v0
+003380: 6001 0f00                              |001e: sget v1, LTestLinkerMethodMinimalArguments;.forceFailureType:I // field@000f
+003384: 2b01 3800 0000                         |0020: packed-switch v1, 00000058 // +00000038
+00338a: 2201 3400                              |0023: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+00338e: 7020 d200 0100                         |0025: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003394: 1101                                   |0028: return-object v1
+003396: 6201 1300                              |0029: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00339a: 1a02 a100                              |002b: const-string v2, "Throwing InstantiationException in linkerMethod()" // string@00a1
+00339e: 6e20 b300 2100                         |002d: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0033a4: 2201 2600                              |0030: new-instance v1, Ljava/lang/InstantiationException; // type@0026
+0033a8: 1a02 6601                              |0032: const-string v2, "linkerMethod" // string@0166
+0033ac: 7020 bb00 2100                         |0034: invoke-direct {v1, v2}, Ljava/lang/InstantiationException;.<init>:(Ljava/lang/String;)V // method@00bb
+0033b2: 2701                                   |0037: throw v1
+0033b4: 6201 1300                              |0038: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+0033b8: 2202 2d00                              |003a: new-instance v2, Ljava/lang/StringBuilder; // type@002d
+0033bc: 7010 c100 0200                         |003c: invoke-direct {v2}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+0033c2: 1a03 8c00                              |003f: const-string v3, "Returning null instead of CallSite for " // string@008c
+0033c6: 6e20 c800 3200                         |0041: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0033cc: 6e20 c800 5200                         |0044: invoke-virtual {v2, v5}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0033d2: 1a03 0000                              |0047: const-string v3, " " // string@0000
+0033d6: 6e20 c800 3200                         |0049: invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0033dc: 6e20 c700 6200                         |004c: invoke-virtual {v2, v6}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+0033e2: 6e10 ca00 0200                         |004f: invoke-virtual {v2}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0033e8: 0c02                                   |0052: move-result-object v2
+0033ea: 6e20 b300 2100                         |0053: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0033f0: 1201                                   |0056: const/4 v1, #int 0 // #0
+0033f2: 1101                                   |0057: return-object v1
+0033f4: 0001 0200 0100 0000 1800 0000 0900 ... |0058: packed-switch-data (8 units)
+      catches       : (none)
+      positions     : 
+        0x0000 line=61
+        0x0018 line=62
+        0x001a line=63
+        0x001e line=64
+        0x0023 line=73
+        0x0029 line=70
+        0x0030 line=71
+        0x0038 line=66
+        0x0056 line=68
+      locals        : 
+        0x001e - 0x0060 reg=0 mh_add Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0060 reg=4 caller Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0060 reg=5 name Ljava/lang/String; 
+        0x0000 - 0x0060 reg=6 methodType Ljava/lang/invoke/MethodType; 
+
+    #5              : (in LTestLinkerMethodMinimalArguments;)
+      name          : 'test'
+      type          : '(III)V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 119
+      code          -
+      registers     : 6
+      ins           : 3
+      outs          : 2
+      insns size    : 68 16-bit code units
+003434:                                        |[003434] TestLinkerMethodMinimalArguments.test:(III)V
+003444: 1200                                   |0000: const/4 v0, #int 0 // #0
+003446: 1211                                   |0001: const/4 v1, #int 1 // #1
+003448: 3a03 0400                              |0002: if-ltz v3, 0006 // +0004
+00344c: 0112                                   |0004: move v2, v1
+00344e: 2802                                   |0005: goto 0007 // +0002
+003450: 0102                                   |0006: move v2, v0
+003452: 7110 7500 0200                         |0007: invoke-static {v2}, LTestLinkerMethodMinimalArguments;.assertTrue:(Z)V // method@0075
+003458: 1232                                   |000a: const/4 v2, #int 3 // #3
+00345a: 3623 0400                              |000b: if-gt v3, v2, 000f // +0004
+00345e: 0110                                   |000d: move v0, v1
+003460: 0000                                   |000e: nop // spacer
+003462: 7110 7500 0000                         |000f: invoke-static {v0}, LTestLinkerMethodMinimalArguments;.assertTrue:(Z)V // method@0075
+003468: 6703 0f00                              |0012: sput v3, LTestLinkerMethodMinimalArguments;.forceFailureType:I // field@000f
+00346c: 9000 0405                              |0014: add-int v0, v4, v5
+003470: fc20 1b00 5400                         |0016: invoke-custom {v4, v5}, call_site@001b
+003476: 0a01                                   |0019: move-result v1
+003478: 7120 7300 1000                         |001a: invoke-static {v0, v1}, LTestLinkerMethodMinimalArguments;.assertEquals:(II)V // method@0073
+00347e: 6200 1300                              |001d: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003482: 2201 2d00                              |001f: new-instance v1, Ljava/lang/StringBuilder; // type@002d
+003486: 7010 c100 0100                         |0021: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00348c: 1a02 2a00                              |0024: const-string v2, "Failure Type + " // string@002a
+003490: 6e20 c800 2100                         |0026: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+003496: 6e20 c500 3100                         |0029: invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+00349c: 1a02 0100                              |002c: const-string v2, " (" // string@0001
+0034a0: 6e20 c800 2100                         |002e: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0034a6: 6e20 c500 4100                         |0031: invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0034ac: 6e20 c500 5100                         |0034: invoke-virtual {v1, v5}, Ljava/lang/StringBuilder;.append:(I)Ljava/lang/StringBuilder; // method@00c5
+0034b2: 1a02 0700                              |0037: const-string v2, ")" // string@0007
+0034b6: 6e20 c800 2100                         |0039: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+0034bc: 6e10 ca00 0100                         |003c: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+0034c2: 0c01                                   |003f: move-result-object v1
+0034c4: 6e20 b300 1000                         |0040: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+0034ca: 0e00                                   |0043: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=78
+        0x000a line=79
+        0x0012 line=80
+        0x0014 line=81
+        0x001d line=82
+        0x0043 line=83
+      locals        : 
+        0x0000 - 0x0044 reg=3 failureType I 
+        0x0000 - 0x0044 reg=4 x I 
+        0x0000 - 0x0044 reg=5 y I 
+
+  Virtual methods   -
+  source_file_idx   : 151 (TestLinkerMethodMinimalArguments.java)
+
+Class #11 header:
+class_idx           : 16
+access_flags        : 1 (0x0001)
+superclass_idx      : 9
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 153
+annotations_off     : 31220 (0x0079f4)
+class_data_off      : 29445 (0x007305)
+static_fields_size  : 1
+instance_fields_size: 0
+direct_methods_size : 6
+virtual_methods_size: 1
+
+Class #11 annotations:
+Annotations on method #124 'add'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestLinkerMethodMultipleArgumentTypes; name="linkerMethod" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I I I I I F D Ljava/lang/String; Ljava/lang/Class; J } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ -1 } Lannotations/Constant; intValue={ 1 } Lannotations/Constant; intValue={ 97 } Lannotations/Constant; intValue={ 1024 } Lannotations/Constant; intValue={ 1 } Lannotations/Constant; floatValue={ 11.1 } Lannotations/Constant; doubleValue={ 2.2 } Lannotations/Constant; stringValue={ "Hello" } Lannotations/Constant; classValue={ LTestLinkerMethodMultipleArgumentTypes; } Lannotations/Constant; longValue={ 123456789 } } fieldOrMethodName="_add" parameterTypes={ I I } returnType=I
+Annotations on method #131 'linkerMethod'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value={ "(" "Ljava/lang/invoke/MethodHandles$Lookup;" "Ljava/lang/String;" "Ljava/lang/invoke/MethodType;" "IIIIIFD" "Ljava/lang/String;" "Ljava/lang/Class<" "*>;J)" "Ljava/lang/invoke/CallSite;" }
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #132 'test'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #11            -
+  Class descriptor  : 'LTestLinkerMethodMultipleArgumentTypes;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'LTestBase;'
+  Interfaces        -
+  Static fields     -
+    #0              : (in LTestLinkerMethodMultipleArgumentTypes;)
+      name          : 'bootstrapRunCount'
+      type          : 'I'
+      access        : 0x000a (PRIVATE STATIC)
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTestLinkerMethodMultipleArgumentTypes;)
+      name          : '<clinit>'
+      type          : '()V'
+      access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 120
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+003618:                                        |[003618] TestLinkerMethodMultipleArgumentTypes.<clinit>:()V
+003628: 1200                                   |0000: const/4 v0, #int 0 // #0
+00362a: 6700 1000                              |0001: sput v0, LTestLinkerMethodMultipleArgumentTypes;.bootstrapRunCount:I // field@0010
+00362e: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=28
+      locals        : 
+
+    #1              : (in LTestLinkerMethodMultipleArgumentTypes;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 121
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+003630:                                        |[003630] TestLinkerMethodMultipleArgumentTypes.<init>:()V
+003640: 7010 3200 0000                         |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+003646: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=26
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestLinkerMethodMultipleArgumentTypes; 
+
+    #2              : (in LTestLinkerMethodMultipleArgumentTypes;)
+      name          : '_add'
+      type          : '(II)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 123
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 0
+      insns size    : 3 16-bit code units
+0034e4:                                        |[0034e4] TestLinkerMethodMultipleArgumentTypes._add:(II)I
+0034f4: 9000 0102                              |0000: add-int v0, v1, v2
+0034f8: 0f00                                   |0002: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=74
+      locals        : 
+        0x0000 - 0x0003 reg=1 a I 
+        0x0000 - 0x0003 reg=2 b I 
+
+    #3              : (in LTestLinkerMethodMultipleArgumentTypes;)
+      name          : 'add'
+      type          : '(II)I'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 124
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 0
+      insns size    : 5 16-bit code units
+0034fc:                                        |[0034fc] TestLinkerMethodMultipleArgumentTypes.add:(II)I
+00350c: 7100 8200 0000                         |0000: invoke-static {}, LTestLinkerMethodMultipleArgumentTypes;.assertNotReached:()V // method@0082
+003512: 12f0                                   |0003: const/4 v0, #int -1 // #ff
+003514: 0f00                                   |0004: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=68
+        0x0003 line=69
+      locals        : 
+        0x0000 - 0x0005 reg=1 a I 
+        0x0000 - 0x0005 reg=2 b I 
+
+    #4              : (in LTestLinkerMethodMultipleArgumentTypes;)
+      name          : 'linkerMethod'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 131
+      code          -
+      registers     : 31
+      ins           : 15
+      outs          : 4
+      insns size    : 119 16-bit code units
+003518:                                        |[003518] TestLinkerMethodMultipleArgumentTypes.linkerMethod:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite;
+003528: 0800 1100                              |0000: move-object/from16 v0, v17
+00352c: 0801 1200                              |0002: move-object/from16 v1, v18
+003530: 6202 1300                              |0004: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003534: 2203 2d00                              |0006: new-instance v3, Ljava/lang/StringBuilder; // type@002d
+003538: 7010 c100 0300                         |0008: invoke-direct {v3}, Ljava/lang/StringBuilder;.<init>:()V // method@00c1
+00353e: 1a04 6100                              |000b: const-string v4, "Linking " // string@0061
+003542: 6e20 c800 4300                         |000d: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+003548: 6e20 c800 0300                         |0010: invoke-virtual {v3, v0}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+00354e: 1a04 0000                              |0013: const-string v4, " " // string@0000
+003552: 6e20 c800 4300                         |0015: invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@00c8
+003558: 6e20 c700 1300                         |0018: invoke-virtual {v3, v1}, Ljava/lang/StringBuilder;.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; // method@00c7
+00355e: 6e10 ca00 0300                         |001b: invoke-virtual {v3}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@00ca
+003564: 0c03                                   |001e: move-result-object v3
+003566: 6e20 b300 3200                         |001f: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+00356c: 12f2                                   |0022: const/4 v2, #int -1 // #ff
+00356e: 0203 1300                              |0023: move/from16 v3, v19
+003572: 7120 7f00 3200                         |0025: invoke-static {v2, v3}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+003578: 1212                                   |0028: const/4 v2, #int 1 // #1
+00357a: 0204 1400                              |0029: move/from16 v4, v20
+00357e: 7120 7f00 4200                         |002b: invoke-static {v2, v4}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+003584: 1305 6100                              |002e: const/16 v5, #int 97 // #61
+003588: 0206 1500                              |0030: move/from16 v6, v21
+00358c: 7120 7f00 6500                         |0032: invoke-static {v5, v6}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+003592: 1305 0004                              |0035: const/16 v5, #int 1024 // #400
+003596: 0207 1600                              |0037: move/from16 v7, v22
+00359a: 7120 7f00 7500                         |0039: invoke-static {v5, v7}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+0035a0: 0205 1700                              |003c: move/from16 v5, v23
+0035a4: 7120 7f00 5200                         |003e: invoke-static {v2, v5}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+0035aa: 1402 9a99 3141                         |0041: const v2, #float 11.1 // #4131999a
+0035b0: 0208 1800                              |0044: move/from16 v8, v24
+0035b4: 7120 7e00 8200                         |0046: invoke-static {v2, v8}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(FF)V // method@007e
+0035ba: 1809 9a99 9999 9999 0140               |0049: const-wide v9, #double 2.2 // #400199999999999a
+0035c4: 050b 1900                              |004e: move-wide/from16 v11, v25
+0035c8: 7140 7d00 a9cb                         |0050: invoke-static {v9, v10, v11, v12}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(DD)V // method@007d
+0035ce: 1a02 2c00                              |0053: const-string v2, "Hello" // string@002c
+0035d2: 0809 1b00                              |0055: move-object/from16 v9, v27
+0035d6: 7120 8100 9200                         |0057: invoke-static {v2, v9}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0081
+0035dc: 1c02 1000                              |005a: const-class v2, LTestLinkerMethodMultipleArgumentTypes; // type@0010
+0035e0: 080a 1c00                              |005c: move-object/from16 v10, v28
+0035e4: 7120 8100 a200                         |005e: invoke-static {v2, v10}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(Ljava/lang/Object;Ljava/lang/Object;)V // method@0081
+0035ea: 170d 15cd 5b07                         |0061: const-wide/32 v13, #float 1.6536e-34 // #075bcd15
+0035f0: 0502 1d00                              |0064: move-wide/from16 v2, v29
+0035f4: 7140 8000 ed32                         |0066: invoke-static {v13, v14, v2, v3}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(JJ)V // method@0080
+0035fa: 1c0d 1000                              |0069: const-class v13, LTestLinkerMethodMultipleArgumentTypes; // type@0010
+0035fe: 080e 1000                              |006b: move-object/from16 v14, v16
+003602: 6e40 d800 de10                         |006d: invoke-virtual {v14, v13, v0, v1}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003608: 0c0d                                   |0070: move-result-object v13
+00360a: 220f 3400                              |0071: new-instance v15, Ljava/lang/invoke/ConstantCallSite; // type@0034
+00360e: 7020 d200 df00                         |0073: invoke-direct {v15, v13}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003614: 110f                                   |0076: return-object v15
+      catches       : (none)
+      positions     : 
+        0x0000 line=93
+        0x0022 line=94
+        0x0028 line=95
+        0x002e line=96
+        0x0035 line=97
+        0x003c line=98
+        0x0041 line=99
+        0x0049 line=100
+        0x0053 line=101
+        0x005a line=102
+        0x0061 line=103
+        0x0069 line=104
+        0x006b line=105
+        0x0071 line=106
+      locals        : 
+        0x0000 - 0x0000 reg=28 (null) Ljava/lang/Class; 
+        0x0071 - 0x0077 reg=13 mh_add Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0077 reg=16 caller Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0077 reg=17 name Ljava/lang/String; 
+        0x0000 - 0x0077 reg=18 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0077 reg=19 v1 I 
+        0x0000 - 0x0077 reg=20 v2 I 
+        0x0000 - 0x0077 reg=21 v3 I 
+        0x0000 - 0x0077 reg=22 v4 I 
+        0x0000 - 0x0077 reg=23 v5 I 
+        0x0000 - 0x0077 reg=24 v6 F 
+        0x0000 - 0x0077 reg=25 v7 D 
+        0x0000 - 0x0077 reg=27 v8 Ljava/lang/String; 
+        0x0000 - 0x0077 reg=28 v9 Ljava/lang/Class; Ljava/lang/Class<*>;
+        0x0000 - 0x0077 reg=29 v10 J 
+
+    #5              : (in LTestLinkerMethodMultipleArgumentTypes;)
+      name          : 'test'
+      type          : '(II)V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 132
+      code          -
+      registers     : 4
+      ins           : 2
+      outs          : 2
+      insns size    : 17 16-bit code units
+003648:                                        |[003648] TestLinkerMethodMultipleArgumentTypes.test:(II)V
+003658: 9000 0203                              |0000: add-int v0, v2, v3
+00365c: fc20 1c00 3200                         |0002: invoke-custom {v2, v3}, call_site@001c
+003662: 0a01                                   |0005: move-result v1
+003664: 7120 7f00 1000                         |0006: invoke-static {v0, v1}, LTestLinkerMethodMultipleArgumentTypes;.assertEquals:(II)V // method@007f
+00366a: 6200 1300                              |0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+00366e: 9001 0203                              |000b: add-int v1, v2, v3
+003672: 6e20 b100 1000                         |000d: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V // method@00b1
+003678: 0e00                                   |0010: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=114
+        0x0009 line=115
+        0x0010 line=116
+      locals        : 
+        0x0000 - 0x0011 reg=2 x I 
+        0x0000 - 0x0011 reg=3 y I 
+
+  Virtual methods   -
+    #0              : (in LTestLinkerMethodMultipleArgumentTypes;)
+      name          : 'GetBootstrapRunCount'
+      type          : '()I'
+      access        : 0x0001 (PUBLIC)
+      method_idx    : 122
+      code          -
+      registers     : 2
+      ins           : 1
+      outs          : 0
+      insns size    : 3 16-bit code units
+0034cc:                                        |[0034cc] TestLinkerMethodMultipleArgumentTypes.GetBootstrapRunCount:()I
+0034dc: 6000 1000                              |0000: sget v0, LTestLinkerMethodMultipleArgumentTypes;.bootstrapRunCount:I // field@0010
+0034e0: 0f00                                   |0002: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=110
+      locals        : 
+        0x0000 - 0x0003 reg=1 this LTestLinkerMethodMultipleArgumentTypes; 
+
+  source_file_idx   : 153 (TestLinkerMethodMultipleArgumentTypes.java)
+
+Class #12 header:
+class_idx           : 17
+access_flags        : 0 (0x0000)
+superclass_idx      : 9
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 154
+annotations_off     : 31260 (0x007a1c)
+class_data_off      : 29483 (0x00732b)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 6
+virtual_methods_size: 0
+
+Class #12 annotations:
+Annotations on method #136 'addf'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LUnrelatedBSM; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/Class; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; classValue={ LTestLinkerUnrelatedBSM; } } fieldOrMethodName="_addf" parameterTypes={ F F } returnType=F
+Annotations on method #139 'subf'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LUnrelatedBSM; name="bsm" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/Class; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; classValue={ LTestLinkerUnrelatedBSM; } } fieldOrMethodName="_subf" parameterTypes={ F F } returnType=F
+
+Class #12            -
+  Class descriptor  : 'LTestLinkerUnrelatedBSM;'
+  Access flags      : 0x0000 ()
+  Superclass        : 'LTestBase;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTestLinkerUnrelatedBSM;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 133
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+0036e4:                                        |[0036e4] TestLinkerUnrelatedBSM.<init>:()V
+0036f4: 7010 3200 0000                         |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+0036fa: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=23
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestLinkerUnrelatedBSM; 
+
+    #1              : (in LTestLinkerUnrelatedBSM;)
+      name          : '_addf'
+      type          : '(FF)F'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 134
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 0
+      insns size    : 3 16-bit code units
+00367c:                                        |[00367c] TestLinkerUnrelatedBSM._addf:(FF)F
+00368c: a600 0102                              |0000: add-float v0, v1, v2
+003690: 0f00                                   |0002: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=47
+      locals        : 
+        0x0000 - 0x0003 reg=1 a F 
+        0x0000 - 0x0003 reg=2 b F 
+
+    #2              : (in LTestLinkerUnrelatedBSM;)
+      name          : '_subf'
+      type          : '(FF)F'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 135
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 0
+      insns size    : 3 16-bit code units
+003694:                                        |[003694] TestLinkerUnrelatedBSM._subf:(FF)F
+0036a4: a700 0102                              |0000: sub-float v0, v1, v2
+0036a8: 0f00                                   |0002: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=73
+      locals        : 
+        0x0000 - 0x0003 reg=1 a F 
+        0x0000 - 0x0003 reg=2 b F 
+
+    #3              : (in LTestLinkerUnrelatedBSM;)
+      name          : 'addf'
+      type          : '(FF)F'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 136
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 0
+      insns size    : 5 16-bit code units
+0036ac:                                        |[0036ac] TestLinkerUnrelatedBSM.addf:(FF)F
+0036bc: 7100 8a00 0000                         |0000: invoke-static {}, LTestLinkerUnrelatedBSM;.assertNotReached:()V // method@008a
+0036c2: 1210                                   |0003: const/4 v0, #int 1 // #1
+0036c4: 0f00                                   |0004: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=42
+        0x0003 line=43
+      locals        : 
+        0x0000 - 0x0005 reg=1 a F 
+        0x0000 - 0x0005 reg=2 b F 
+
+    #4              : (in LTestLinkerUnrelatedBSM;)
+      name          : 'subf'
+      type          : '(FF)F'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 139
+      code          -
+      registers     : 3
+      ins           : 2
+      outs          : 0
+      insns size    : 5 16-bit code units
+0036c8:                                        |[0036c8] TestLinkerUnrelatedBSM.subf:(FF)F
+0036d8: 7100 8a00 0000                         |0000: invoke-static {}, LTestLinkerUnrelatedBSM;.assertNotReached:()V // method@008a
+0036de: 1210                                   |0003: const/4 v0, #int 1 // #1
+0036e0: 0f00                                   |0004: return v0
+      catches       : (none)
+      positions     : 
+        0x0000 line=68
+        0x0003 line=69
+      locals        : 
+        0x0000 - 0x0005 reg=1 a F 
+        0x0000 - 0x0005 reg=2 b F 
+
+    #5              : (in LTestLinkerUnrelatedBSM;)
+      name          : 'test'
+      type          : '()V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 140
+      code          -
+      registers     : 4
+      ins           : 0
+      outs          : 2
+      insns size    : 34 16-bit code units
+0036fc:                                        |[0036fc] TestLinkerUnrelatedBSM.test:()V
+00370c: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003710: 1c01 1100                              |0002: const-class v1, LTestLinkerUnrelatedBSM; // type@0011
+003714: 6e10 b700 0100                         |0004: invoke-virtual {v1}, Ljava/lang/Class;.getName:()Ljava/lang/String; // method@00b7
+00371a: 0c01                                   |0007: move-result-object v1
+00371c: 6e20 b300 1000                         |0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003722: 1500 003f                              |000b: const/high16 v0, #int 1056964608 // #3f00
+003726: 1501 0040                              |000d: const/high16 v1, #int 1073741824 // #4000
+00372a: fc20 1d00 0100                         |000f: invoke-custom {v1, v0}, call_site@001d
+003730: 0a02                                   |0012: move-result v2
+003732: 1503 2040                              |0013: const/high16 v3, #int 1075838976 // #4020
+003736: 7120 8900 2300                         |0015: invoke-static {v3, v2}, LTestLinkerUnrelatedBSM;.assertEquals:(FF)V // method@0089
+00373c: fc20 1e00 0100                         |0018: invoke-custom {v1, v0}, call_site@001e
+003742: 0a00                                   |001b: move-result v0
+003744: 1501 c03f                              |001c: const/high16 v1, #int 1069547520 // #3fc0
+003748: 7120 8900 0100                         |001e: invoke-static {v1, v0}, LTestLinkerUnrelatedBSM;.assertEquals:(FF)V // method@0089
+00374e: 0e00                                   |0021: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=77
+        0x000b line=78
+        0x0018 line=79
+        0x0021 line=80
+      locals        : 
+
+  Virtual methods   -
+  source_file_idx   : 154 (TestLinkerUnrelatedBSM.java)
+
+Class #13 header:
+class_idx           : 18
+access_flags        : 1 (0x0001)
+superclass_idx      : 9
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 156
+annotations_off     : 31292 (0x007a3c)
+class_data_off      : 29514 (0x00734a)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 27
+virtual_methods_size: 0
+
+Class #13 annotations:
+Annotations on method #143 'bsmWithBoxedArray'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #144 'bsmWithClassAndFloatArray'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value={ "(" "Ljava/lang/invoke/MethodHandles$Lookup;" "Ljava/lang/String;" "Ljava/lang/invoke/MethodType;" "Ljava/lang/Class<" "*>;[F)" "Ljava/lang/invoke/CallSite;" }
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #145 'bsmWithClassArray'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #146 'bsmWithDoubleArray'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #147 'bsmWithFloatAndLongArray'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #148 'bsmWithIntAndStringArray'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #149 'bsmWithLongAndIntArray'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #150 'bsmWithStringArray'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #151 'bsmWithWiderArray'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+Annotations on method #152 'methodA'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; stringValue={ "Aachen" } Lannotations/Constant; stringValue={ "Aalborg" } Lannotations/Constant; stringValue={ "Aalto" } } fieldOrMethodName="methodA"
+Annotations on method #153 'methodB'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; stringValue={ "barium" } } fieldOrMethodName="methodB"
+Annotations on method #154 'methodC'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [Ljava/lang/String; } } fieldOrMethodName="methodC"
+Annotations on method #155 'methodD'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithIntAndStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 101 } Lannotations/Constant; stringValue={ "zoo" } Lannotations/Constant; stringValue={ "zoogene" } Lannotations/Constant; stringValue={ "zoogenic" } } fieldOrMethodName="methodD"
+Annotations on method #156 'methodE'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithIntAndStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 102 } Lannotations/Constant; stringValue={ "zonic" } } fieldOrMethodName="methodE"
+Annotations on method #157 'methodF'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithIntAndStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 103 } } fieldOrMethodName="methodF"
+Annotations on method #158 'methodG'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithLongAndIntArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; J [I } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; longValue={ 81985529216486895 } Lannotations/Constant; intValue={ 1 } Lannotations/Constant; intValue={ -1 } Lannotations/Constant; intValue={ 2 } Lannotations/Constant; intValue={ -2 } } fieldOrMethodName="methodG"
+Annotations on method #159 'methodH'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithFloatAndLongArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; F [J } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; floatValue={ -2.71828 } Lannotations/Constant; longValue={ 999999999999 } Lannotations/Constant; longValue={ -8888888888888 } } fieldOrMethodName="methodH"
+Annotations on method #160 'methodI'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithClassAndFloatArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; Ljava/lang/Class; [F } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; classValue={ Ljava/lang/Throwable; } Lannotations/Constant; floatValue={ 3.40282e+38 } Lannotations/Constant; floatValue={ 1.4013e-45 } Lannotations/Constant; floatValue={ 3.14159 } Lannotations/Constant; floatValue={ -3.14159 } } fieldOrMethodName="methodI"
+Annotations on method #161 'methodJ'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithDoubleArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [D } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; doubleValue={ 1.79769e+308 } Lannotations/Constant; doubleValue={ 4.94066e-324 } Lannotations/Constant; doubleValue={ 2.71828 } Lannotations/Constant; doubleValue={ -3.14159 } } fieldOrMethodName="methodJ"
+Annotations on method #162 'methodK'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithClassArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [Ljava/lang/Class; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; classValue={ Ljava/lang/Integer; } Lannotations/Constant; classValue={ Ljava/lang/invoke/MethodHandles; } Lannotations/Constant; classValue={ Ljava/util/Arrays; } } fieldOrMethodName="methodK"
+Annotations on method #163 'methodO'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithIntAndStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 103 } Lannotations/Constant; intValue={ 104 } } fieldOrMethodName="methodO"
+Annotations on method #164 'methodP'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithIntAndStringArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; I [Ljava/lang/String; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 103 } Lannotations/Constant; stringValue={ "A" } Lannotations/Constant; stringValue={ "B" } Lannotations/Constant; intValue={ 42 } } fieldOrMethodName="methodP"
+Annotations on method #165 'methodQ'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithWiderArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [J } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 103 } Lannotations/Constant; intValue={ 42 } } fieldOrMethodName="methodQ"
+Annotations on method #166 'methodR'
+  VISIBILITY_RUNTIME Lannotations/CalledByIndy; bootstrapMethod={ Lannotations/BootstrapMethod; enclosingType=LTestVariableArityLinkerMethod; name="bsmWithBoxedArray" parameterTypes={ Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; [Ljava/lang/Integer; } } constantArgumentsForBootstrapMethod={ Lannotations/Constant; intValue={ 1030 } Lannotations/Constant; intValue={ 420 } } fieldOrMethodName="methodR"
+
+Class #13            -
+  Class descriptor  : 'LTestVariableArityLinkerMethod;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'LTestBase;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTestVariableArityLinkerMethod;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 141
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+003a7c:                                        |[003a7c] TestVariableArityLinkerMethod.<init>:()V
+003a8c: 7010 3200 0000                         |0000: invoke-direct {v0}, LTestBase;.<init>:()V // method@0032
+003a92: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=27
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTestVariableArityLinkerMethod; 
+
+    #1              : (in LTestVariableArityLinkerMethod;)
+      name          : 'bsmWithBoxedArray'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 143
+      code          -
+      registers     : 7
+      ins           : 4
+      outs          : 4
+      insns size    : 34 16-bit code units
+003750:                                        |[003750] TestVariableArityLinkerMethod.bsmWithBoxedArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite;
+003760: 1a00 f800                              |0000: const-string v0, "bsmWithBoxedArray" // string@00f8
+003764: 1241                                   |0002: const/4 v1, #int 4 // #4
+003766: 2311 4800                              |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+00376a: 1202                                   |0005: const/4 v2, #int 0 // #0
+00376c: 4d03 0102                              |0006: aput-object v3, v1, v2
+003770: 1212                                   |0008: const/4 v2, #int 1 // #1
+003772: 4d04 0102                              |0009: aput-object v4, v1, v2
+003776: 1222                                   |000b: const/4 v2, #int 2 // #2
+003778: 4d05 0102                              |000c: aput-object v5, v1, v2
+00377c: 1232                                   |000e: const/4 v2, #int 3 // #3
+00377e: 4d06 0102                              |000f: aput-object v6, v1, v2
+003782: 7120 a700 1000                         |0011: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+003788: 6e10 dc00 0300                         |0014: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+00378e: 0c00                                   |0017: move-result-object v0
+003790: 6e40 d800 0354                         |0018: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003796: 0c00                                   |001b: move-result-object v0
+003798: 2201 3400                              |001c: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+00379c: 7020 d200 0100                         |001e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+0037a2: 1101                                   |0021: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=477
+        0x0014 line=478
+        0x001c line=479
+      locals        : 
+        0x001c - 0x0022 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0022 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0022 reg=4 methodName Ljava/lang/String; 
+        0x0000 - 0x0022 reg=5 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0022 reg=6 extraArgs [Ljava/lang/Integer; 
+
+    #2              : (in LTestVariableArityLinkerMethod;)
+      name          : 'bsmWithClassAndFloatArray'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite;'
+      access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 144
+      code          -
+      registers     : 8
+      ins           : 5
+      outs          : 4
+      insns size    : 37 16-bit code units
+0037a4:                                        |[0037a4] TestVariableArityLinkerMethod.bsmWithClassAndFloatArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite;
+0037b4: 1a00 f900                              |0000: const-string v0, "bsmWithClassAndFloatArray" // string@00f9
+0037b8: 1251                                   |0002: const/4 v1, #int 5 // #5
+0037ba: 2311 4800                              |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+0037be: 1202                                   |0005: const/4 v2, #int 0 // #0
+0037c0: 4d03 0102                              |0006: aput-object v3, v1, v2
+0037c4: 1212                                   |0008: const/4 v2, #int 1 // #1
+0037c6: 4d04 0102                              |0009: aput-object v4, v1, v2
+0037ca: 1222                                   |000b: const/4 v2, #int 2 // #2
+0037cc: 4d05 0102                              |000c: aput-object v5, v1, v2
+0037d0: 1232                                   |000e: const/4 v2, #int 3 // #3
+0037d2: 4d06 0102                              |000f: aput-object v6, v1, v2
+0037d6: 1242                                   |0011: const/4 v2, #int 4 // #4
+0037d8: 4d07 0102                              |0012: aput-object v7, v1, v2
+0037dc: 7120 a700 1000                         |0014: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+0037e2: 6e10 dc00 0300                         |0017: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+0037e8: 0c00                                   |001a: move-result-object v0
+0037ea: 6e40 d800 0354                         |001b: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+0037f0: 0c00                                   |001e: move-result-object v0
+0037f2: 2201 3400                              |001f: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+0037f6: 7020 d200 0100                         |0021: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+0037fc: 1101                                   |0024: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=294
+        0x0017 line=296
+        0x001f line=297
+      locals        : 
+        0x0000 - 0x0000 reg=6 (null) Ljava/lang/Class; 
+        0x001f - 0x0025 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0025 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0025 reg=4 methodName Ljava/lang/String; 
+        0x0000 - 0x0025 reg=5 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0025 reg=6 extraArg Ljava/lang/Class; Ljava/lang/Class<*>;
+        0x0000 - 0x0025 reg=7 arityArgs [F 
+
+    #3              : (in LTestVariableArityLinkerMethod;)
+      name          : 'bsmWithClassArray'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite;'
+      access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 145
+      code          -
+      registers     : 7
+      ins           : 4
+      outs          : 4
+      insns size    : 34 16-bit code units
+003800:                                        |[003800] TestVariableArityLinkerMethod.bsmWithClassArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite;
+003810: 1a00 fa00                              |0000: const-string v0, "bsmWithClassArray" // string@00fa
+003814: 1241                                   |0002: const/4 v1, #int 4 // #4
+003816: 2311 4800                              |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+00381a: 1202                                   |0005: const/4 v2, #int 0 // #0
+00381c: 4d03 0102                              |0006: aput-object v3, v1, v2
+003820: 1212                                   |0008: const/4 v2, #int 1 // #1
+003822: 4d04 0102                              |0009: aput-object v4, v1, v2
+003826: 1222                                   |000b: const/4 v2, #int 2 // #2
+003828: 4d05 0102                              |000c: aput-object v5, v1, v2
+00382c: 1232                                   |000e: const/4 v2, #int 3 // #3
+00382e: 4d06 0102                              |000f: aput-object v6, v1, v2
+003832: 7120 a700 1000                         |0011: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+003838: 6e10 dc00 0300                         |0014: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+00383e: 0c00                                   |0017: move-result-object v0
+003840: 6e40 d800 0354                         |0018: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003846: 0c00                                   |001b: move-result-object v0
+003848: 2201 3400                              |001c: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+00384c: 7020 d200 0100                         |001e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003852: 1101                                   |0021: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=367
+        0x0014 line=368
+        0x001c line=369
+      locals        : 
+        0x001c - 0x0022 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0022 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0022 reg=4 methodName Ljava/lang/String; 
+        0x0000 - 0x0022 reg=5 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0022 reg=6 arityArgs [Ljava/lang/Class; 
+
+    #4              : (in LTestVariableArityLinkerMethod;)
+      name          : 'bsmWithDoubleArray'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite;'
+      access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 146
+      code          -
+      registers     : 7
+      ins           : 4
+      outs          : 4
+      insns size    : 34 16-bit code units
+003854:                                        |[003854] TestVariableArityLinkerMethod.bsmWithDoubleArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite;
+003864: 1a00 fb00                              |0000: const-string v0, "bsmWithDoubleArray" // string@00fb
+003868: 1241                                   |0002: const/4 v1, #int 4 // #4
+00386a: 2311 4800                              |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+00386e: 1202                                   |0005: const/4 v2, #int 0 // #0
+003870: 4d03 0102                              |0006: aput-object v3, v1, v2
+003874: 1212                                   |0008: const/4 v2, #int 1 // #1
+003876: 4d04 0102                              |0009: aput-object v4, v1, v2
+00387a: 1222                                   |000b: const/4 v2, #int 2 // #2
+00387c: 4d05 0102                              |000c: aput-object v5, v1, v2
+003880: 1232                                   |000e: const/4 v2, #int 3 // #3
+003882: 4d06 0102                              |000f: aput-object v6, v1, v2
+003886: 7120 a700 1000                         |0011: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+00388c: 6e10 dc00 0300                         |0014: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+003892: 0c00                                   |0017: move-result-object v0
+003894: 6e40 d800 0354                         |0018: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+00389a: 0c00                                   |001b: move-result-object v0
+00389c: 2201 3400                              |001c: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+0038a0: 7020 d200 0100                         |001e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+0038a6: 1101                                   |0021: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=332
+        0x0014 line=333
+        0x001c line=334
+      locals        : 
+        0x001c - 0x0022 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0022 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0022 reg=4 methodName Ljava/lang/String; 
+        0x0000 - 0x0022 reg=5 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0022 reg=6 arityArgs [D 
+
+    #5              : (in LTestVariableArityLinkerMethod;)
+      name          : 'bsmWithFloatAndLongArray'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite;'
+      access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 147
+      code          -
+      registers     : 9
+      ins           : 5
+      outs          : 4
+      insns size    : 41 16-bit code units
+0038a8:                                        |[0038a8] TestVariableArityLinkerMethod.bsmWithFloatAndLongArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite;
+0038b8: 1a00 fc00                              |0000: const-string v0, "bsmWithFloatAndLongArray" // string@00fc
+0038bc: 1251                                   |0002: const/4 v1, #int 5 // #5
+0038be: 2311 4800                              |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+0038c2: 1202                                   |0005: const/4 v2, #int 0 // #0
+0038c4: 4d04 0102                              |0006: aput-object v4, v1, v2
+0038c8: 1212                                   |0008: const/4 v2, #int 1 // #1
+0038ca: 4d05 0102                              |0009: aput-object v5, v1, v2
+0038ce: 1222                                   |000b: const/4 v2, #int 2 // #2
+0038d0: 4d06 0102                              |000c: aput-object v6, v1, v2
+0038d4: 7110 ba00 0700                         |000e: invoke-static {v7}, Ljava/lang/Float;.valueOf:(F)Ljava/lang/Float; // method@00ba
+0038da: 0c02                                   |0011: move-result-object v2
+0038dc: 1233                                   |0012: const/4 v3, #int 3 // #3
+0038de: 4d02 0103                              |0013: aput-object v2, v1, v3
+0038e2: 1242                                   |0015: const/4 v2, #int 4 // #4
+0038e4: 4d08 0102                              |0016: aput-object v8, v1, v2
+0038e8: 7120 a700 1000                         |0018: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+0038ee: 6e10 dc00 0400                         |001b: invoke-virtual {v4}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+0038f4: 0c00                                   |001e: move-result-object v0
+0038f6: 6e40 d800 0465                         |001f: invoke-virtual {v4, v0, v5, v6}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+0038fc: 0c00                                   |0022: move-result-object v0
+0038fe: 2201 3400                              |0023: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+003902: 7020 d200 0100                         |0025: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003908: 1101                                   |0028: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=257
+        0x000e line=258
+        0x0018 line=257
+        0x001b line=259
+        0x0023 line=260
+      locals        : 
+        0x0023 - 0x0029 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0029 reg=4 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0029 reg=5 methodName Ljava/lang/String; 
+        0x0000 - 0x0029 reg=6 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0029 reg=7 extraArg F 
+        0x0000 - 0x0029 reg=8 arityArgs [J 
+
+    #6              : (in LTestVariableArityLinkerMethod;)
+      name          : 'bsmWithIntAndStringArray'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite;'
+      access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 148
+      code          -
+      registers     : 9
+      ins           : 5
+      outs          : 4
+      insns size    : 41 16-bit code units
+00390c:                                        |[00390c] TestVariableArityLinkerMethod.bsmWithIntAndStringArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite;
+00391c: 1a00 fd00                              |0000: const-string v0, "bsmWithIntAndStringArray" // string@00fd
+003920: 1251                                   |0002: const/4 v1, #int 5 // #5
+003922: 2311 4800                              |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+003926: 1202                                   |0005: const/4 v2, #int 0 // #0
+003928: 4d04 0102                              |0006: aput-object v4, v1, v2
+00392c: 1212                                   |0008: const/4 v2, #int 1 // #1
+00392e: 4d05 0102                              |0009: aput-object v5, v1, v2
+003932: 1222                                   |000b: const/4 v2, #int 2 // #2
+003934: 4d06 0102                              |000c: aput-object v6, v1, v2
+003938: 7110 bd00 0700                         |000e: invoke-static {v7}, Ljava/lang/Integer;.valueOf:(I)Ljava/lang/Integer; // method@00bd
+00393e: 0c02                                   |0011: move-result-object v2
+003940: 1233                                   |0012: const/4 v3, #int 3 // #3
+003942: 4d02 0103                              |0013: aput-object v2, v1, v3
+003946: 1242                                   |0015: const/4 v2, #int 4 // #4
+003948: 4d08 0102                              |0016: aput-object v8, v1, v2
+00394c: 7120 a700 1000                         |0018: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+003952: 6e10 dc00 0400                         |001b: invoke-virtual {v4}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+003958: 0c00                                   |001e: move-result-object v0
+00395a: 6e40 d800 0465                         |001f: invoke-virtual {v4, v0, v5, v6}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003960: 0c00                                   |0022: move-result-object v0
+003962: 2201 3400                              |0023: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+003966: 7020 d200 0100                         |0025: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+00396c: 1101                                   |0028: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=133
+        0x000e line=138
+        0x0018 line=133
+        0x001b line=140
+        0x0023 line=141
+      locals        : 
+        0x0023 - 0x0029 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0029 reg=4 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0029 reg=5 methodName Ljava/lang/String; 
+        0x0000 - 0x0029 reg=6 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0029 reg=7 extraInt I 
+        0x0000 - 0x0029 reg=8 extraArityArgs [Ljava/lang/String; 
+
+    #7              : (in LTestVariableArityLinkerMethod;)
+      name          : 'bsmWithLongAndIntArray'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite;'
+      access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 149
+      code          -
+      registers     : 10
+      ins           : 6
+      outs          : 4
+      insns size    : 41 16-bit code units
+003970:                                        |[003970] TestVariableArityLinkerMethod.bsmWithLongAndIntArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite;
+003980: 1a00 fe00                              |0000: const-string v0, "bsmWithLongAndIntArray" // string@00fe
+003984: 1251                                   |0002: const/4 v1, #int 5 // #5
+003986: 2311 4800                              |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+00398a: 1202                                   |0005: const/4 v2, #int 0 // #0
+00398c: 4d04 0102                              |0006: aput-object v4, v1, v2
+003990: 1212                                   |0008: const/4 v2, #int 1 // #1
+003992: 4d05 0102                              |0009: aput-object v5, v1, v2
+003996: 1222                                   |000b: const/4 v2, #int 2 // #2
+003998: 4d06 0102                              |000c: aput-object v6, v1, v2
+00399c: 7120 be00 8700                         |000e: invoke-static {v7, v8}, Ljava/lang/Long;.valueOf:(J)Ljava/lang/Long; // method@00be
+0039a2: 0c02                                   |0011: move-result-object v2
+0039a4: 1233                                   |0012: const/4 v3, #int 3 // #3
+0039a6: 4d02 0103                              |0013: aput-object v2, v1, v3
+0039aa: 1242                                   |0015: const/4 v2, #int 4 // #4
+0039ac: 4d09 0102                              |0016: aput-object v9, v1, v2
+0039b0: 7120 a700 1000                         |0018: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+0039b6: 6e10 dc00 0400                         |001b: invoke-virtual {v4}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+0039bc: 0c00                                   |001e: move-result-object v0
+0039be: 6e40 d800 0465                         |001f: invoke-virtual {v4, v0, v5, v6}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+0039c4: 0c00                                   |0022: move-result-object v0
+0039c6: 2201 3400                              |0023: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+0039ca: 7020 d200 0100                         |0025: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+0039d0: 1101                                   |0028: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=219
+        0x001b line=220
+        0x0023 line=221
+      locals        : 
+        0x0023 - 0x0029 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0029 reg=4 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0029 reg=5 methodName Ljava/lang/String; 
+        0x0000 - 0x0029 reg=6 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0029 reg=7 extraArg J 
+        0x0000 - 0x0029 reg=9 arityArgs [I 
+
+    #8              : (in LTestVariableArityLinkerMethod;)
+      name          : 'bsmWithStringArray'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite;'
+      access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 150
+      code          -
+      registers     : 7
+      ins           : 4
+      outs          : 4
+      insns size    : 34 16-bit code units
+0039d4:                                        |[0039d4] TestVariableArityLinkerMethod.bsmWithStringArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite;
+0039e4: 1a00 ff00                              |0000: const-string v0, "bsmWithStringArray" // string@00ff
+0039e8: 1241                                   |0002: const/4 v1, #int 4 // #4
+0039ea: 2311 4800                              |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+0039ee: 1202                                   |0005: const/4 v2, #int 0 // #0
+0039f0: 4d03 0102                              |0006: aput-object v3, v1, v2
+0039f4: 1212                                   |0008: const/4 v2, #int 1 // #1
+0039f6: 4d04 0102                              |0009: aput-object v4, v1, v2
+0039fa: 1222                                   |000b: const/4 v2, #int 2 // #2
+0039fc: 4d05 0102                              |000c: aput-object v5, v1, v2
+003a00: 1232                                   |000e: const/4 v2, #int 3 // #3
+003a02: 4d06 0102                              |000f: aput-object v6, v1, v2
+003a06: 7120 a700 1000                         |0011: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+003a0c: 6e10 dc00 0300                         |0014: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+003a12: 0c00                                   |0017: move-result-object v0
+003a14: 6e40 d800 0354                         |0018: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003a1a: 0c00                                   |001b: move-result-object v0
+003a1c: 2201 3400                              |001c: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+003a20: 7020 d200 0100                         |001e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003a26: 1101                                   |0021: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=61
+        0x0014 line=62
+        0x001c line=63
+      locals        : 
+        0x001c - 0x0022 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0022 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0022 reg=4 methodName Ljava/lang/String; 
+        0x0000 - 0x0022 reg=5 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0022 reg=6 arityArgs [Ljava/lang/String; 
+
+    #9              : (in LTestVariableArityLinkerMethod;)
+      name          : 'bsmWithWiderArray'
+      type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite;'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 151
+      code          -
+      registers     : 7
+      ins           : 4
+      outs          : 4
+      insns size    : 34 16-bit code units
+003a28:                                        |[003a28] TestVariableArityLinkerMethod.bsmWithWiderArray:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite;
+003a38: 1a00 0001                              |0000: const-string v0, "bsmWithWiderArray" // string@0100
+003a3c: 1241                                   |0002: const/4 v1, #int 4 // #4
+003a3e: 2311 4800                              |0003: new-array v1, v1, [Ljava/lang/Object; // type@0048
+003a42: 1202                                   |0005: const/4 v2, #int 0 // #0
+003a44: 4d03 0102                              |0006: aput-object v3, v1, v2
+003a48: 1212                                   |0008: const/4 v2, #int 1 // #1
+003a4a: 4d04 0102                              |0009: aput-object v4, v1, v2
+003a4e: 1222                                   |000b: const/4 v2, #int 2 // #2
+003a50: 4d05 0102                              |000c: aput-object v5, v1, v2
+003a54: 1232                                   |000e: const/4 v2, #int 3 // #3
+003a56: 4d06 0102                              |000f: aput-object v6, v1, v2
+003a5a: 7120 a700 1000                         |0011: invoke-static {v0, v1}, LTestVariableArityLinkerMethod;.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V // method@00a7
+003a60: 6e10 dc00 0300                         |0014: invoke-virtual {v3}, Ljava/lang/invoke/MethodHandles$Lookup;.lookupClass:()Ljava/lang/Class; // method@00dc
+003a66: 0c00                                   |0017: move-result-object v0
+003a68: 6e40 d800 0354                         |0018: invoke-virtual {v3, v0, v4, v5}, Ljava/lang/invoke/MethodHandles$Lookup;.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; // method@00d8
+003a6e: 0c00                                   |001b: move-result-object v0
+003a70: 2201 3400                              |001c: new-instance v1, Ljava/lang/invoke/ConstantCallSite; // type@0034
+003a74: 7020 d200 0100                         |001e: invoke-direct {v1, v0}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
+003a7a: 1101                                   |0021: return-object v1
+      catches       : (none)
+      positions     : 
+        0x0000 line=447
+        0x0014 line=448
+        0x001c line=449
+      locals        : 
+        0x001c - 0x0022 reg=0 mh Ljava/lang/invoke/MethodHandle; 
+        0x0000 - 0x0022 reg=3 lookup Ljava/lang/invoke/MethodHandles$Lookup; 
+        0x0000 - 0x0022 reg=4 methodName Ljava/lang/String; 
+        0x0000 - 0x0022 reg=5 methodType Ljava/lang/invoke/MethodType; 
+        0x0000 - 0x0022 reg=6 extraArgs [J 
+
+    #10              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodA'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 152
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003a94:                                        |[003a94] TestVariableArityLinkerMethod.methodA:()V
+003aa4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003aa8: 1a01 7501                              |0002: const-string v1, "methodA" // string@0175
+003aac: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003ab2: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=86
+        0x0007 line=87
+      locals        : 
+
+    #11              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodB'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 153
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003ab4:                                        |[003ab4] TestVariableArityLinkerMethod.methodB:()V
+003ac4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ac8: 1a01 7601                              |0002: const-string v1, "methodB" // string@0176
+003acc: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003ad2: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=105
+        0x0007 line=106
+      locals        : 
+
+    #12              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodC'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 154
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003ad4:                                        |[003ad4] TestVariableArityLinkerMethod.methodC:()V
+003ae4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ae8: 1a01 7701                              |0002: const-string v1, "methodC" // string@0177
+003aec: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003af2: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=123
+        0x0007 line=124
+      locals        : 
+
+    #13              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodD'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 155
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003af4:                                        |[003af4] TestVariableArityLinkerMethod.methodD:()V
+003b04: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003b08: 1a01 7801                              |0002: const-string v1, "methodD" // string@0178
+003b0c: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003b12: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=166
+        0x0007 line=167
+      locals        : 
+
+    #14              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodE'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 156
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003b14:                                        |[003b14] TestVariableArityLinkerMethod.methodE:()V
+003b24: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003b28: 1a01 7901                              |0002: const-string v1, "methodE" // string@0179
+003b2c: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003b32: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=189
+        0x0007 line=190
+      locals        : 
+
+    #15              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodF'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 157
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003b34:                                        |[003b34] TestVariableArityLinkerMethod.methodF:()V
+003b44: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003b48: 1a01 7a01                              |0002: const-string v1, "methodF" // string@017a
+003b4c: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003b52: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=209
+        0x0007 line=210
+      locals        : 
+
+    #16              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodG'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 158
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003b54:                                        |[003b54] TestVariableArityLinkerMethod.methodG:()V
+003b64: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003b68: 1a01 7b01                              |0002: const-string v1, "methodG" // string@017b
+003b6c: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003b72: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=247
+        0x0007 line=248
+      locals        : 
+
+    #17              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodH'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 159
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003b74:                                        |[003b74] TestVariableArityLinkerMethod.methodH:()V
+003b84: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003b88: 1a01 7c01                              |0002: const-string v1, "methodH" // string@017c
+003b8c: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003b92: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=284
+        0x0007 line=285
+      locals        : 
+
+    #18              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodI'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 160
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003b94:                                        |[003b94] TestVariableArityLinkerMethod.methodI:()V
+003ba4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ba8: 1a01 7d01                              |0002: const-string v1, "methodI" // string@017d
+003bac: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003bb2: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=323
+        0x0007 line=324
+      locals        : 
+
+    #19              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodJ'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 161
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003bb4:                                        |[003bb4] TestVariableArityLinkerMethod.methodJ:()V
+003bc4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003bc8: 1a01 7e01                              |0002: const-string v1, "methodJ" // string@017e
+003bcc: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003bd2: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=358
+        0x0007 line=359
+      locals        : 
+
+    #20              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodK'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 162
+      code          -
+      registers     : 2
+      ins           : 0
+      outs          : 2
+      insns size    : 8 16-bit code units
+003bd4:                                        |[003bd4] TestVariableArityLinkerMethod.methodK:()V
+003be4: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003be8: 1a01 7f01                              |0002: const-string v1, "methodK" // string@017f
+003bec: 6e20 b300 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003bf2: 0e00                                   |0007: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=392
+        0x0007 line=393
+      locals        : 
+
+    #21              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodO'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 163
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+003bf4:                                        |[003bf4] TestVariableArityLinkerMethod.methodO:()V
+003c04: 7100 8e00 0000                         |0000: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003c0a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=413
+        0x0003 line=414
+      locals        : 
+
+    #22              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodP'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 164
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+003c0c:                                        |[003c0c] TestVariableArityLinkerMethod.methodP:()V
+003c1c: 7100 8e00 0000                         |0000: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003c22: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=441
+        0x0003 line=442
+      locals        : 
+
+    #23              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodQ'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 165
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+003c24:                                        |[003c24] TestVariableArityLinkerMethod.methodQ:()V
+003c34: 7100 8e00 0000                         |0000: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003c3a: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=468
+        0x0003 line=469
+      locals        : 
+
+    #24              : (in LTestVariableArityLinkerMethod;)
+      name          : 'methodR'
+      type          : '()V'
+      access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 166
+      code          -
+      registers     : 0
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+003c3c:                                        |[003c3c] TestVariableArityLinkerMethod.methodR:()V
+003c4c: 7100 8e00 0000                         |0000: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003c52: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=501
+        0x0003 line=502
+      locals        : 
+
+    #25              : (in LTestVariableArityLinkerMethod;)
+      name          : 'printBsmArgs'
+      type          : '(Ljava/lang/String;[Ljava/lang/Object;)V'
+      access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 167
+      code          -
+      registers     : 6
+      ins           : 2
+      outs          : 2
+      insns size    : 159 16-bit code units
+003c54:                                        |[003c54] TestVariableArityLinkerMethod.printBsmArgs:(Ljava/lang/String;[Ljava/lang/Object;)V
+003c64: 6200 1300                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003c68: 6e20 b000 4000                         |0002: invoke-virtual {v0, v4}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003c6e: 6200 1300                              |0005: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003c72: 1a01 0600                              |0007: const-string v1, "(" // string@0006
+003c76: 6e20 b000 1000                         |0009: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003c7c: 1200                                   |000c: const/4 v0, #int 0 // #0
+003c7e: 2151                                   |000d: array-length v1, v5
+003c80: 3510 8900                              |000e: if-ge v0, v1, 0097 // +0089
+003c84: 3800 0900                              |0010: if-eqz v0, 0019 // +0009
+003c88: 6201 1300                              |0012: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003c8c: 1a02 0c00                              |0014: const-string v2, ", " // string@000c
+003c90: 6e20 b000 2100                         |0016: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003c96: 4601 0500                              |0019: aget-object v1, v5, v0
+003c9a: 3801 7100                              |001b: if-eqz v1, 008c // +0071
+003c9e: 4601 0500                              |001d: aget-object v1, v5, v0
+003ca2: 6e10 c000 0100                         |001f: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003ca8: 0c01                                   |0022: move-result-object v1
+003caa: 6e10 b800 0100                         |0023: invoke-virtual {v1}, Ljava/lang/Class;.isArray:()Z // method@00b8
+003cb0: 0a01                                   |0026: move-result v1
+003cb2: 3801 6500                              |0027: if-eqz v1, 008c // +0065
+003cb6: 4601 0500                              |0029: aget-object v1, v5, v0
+003cba: 6e10 c000 0100                         |002b: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003cc0: 0c02                                   |002e: move-result-object v2
+003cc2: 1c03 4400                              |002f: const-class v3, [I // type@0044
+003cc6: 3332 0f00                              |0031: if-ne v2, v3, 0040 // +000f
+003cca: 6202 1300                              |0033: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003cce: 0713                                   |0035: move-object v3, v1
+003cd0: 1f03 4400                              |0036: check-cast v3, [I // type@0044
+003cd4: 7110 e900 0300                         |0038: invoke-static {v3}, Ljava/util/Arrays;.toString:([I)Ljava/lang/String; // method@00e9
+003cda: 0c03                                   |003b: move-result-object v3
+003cdc: 6e20 b000 3200                         |003c: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003ce2: 284c                                   |003f: goto 008b // +004c
+003ce4: 6e10 c000 0100                         |0040: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003cea: 0c02                                   |0043: move-result-object v2
+003cec: 1c03 4500                              |0044: const-class v3, [J // type@0045
+003cf0: 3332 0f00                              |0046: if-ne v2, v3, 0055 // +000f
+003cf4: 6202 1300                              |0048: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003cf8: 0713                                   |004a: move-object v3, v1
+003cfa: 1f03 4500                              |004b: check-cast v3, [J // type@0045
+003cfe: 7110 ea00 0300                         |004d: invoke-static {v3}, Ljava/util/Arrays;.toString:([J)Ljava/lang/String; // method@00ea
+003d04: 0c03                                   |0050: move-result-object v3
+003d06: 6e20 b000 3200                         |0051: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003d0c: 2837                                   |0054: goto 008b // +0037
+003d0e: 6e10 c000 0100                         |0055: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003d14: 0c02                                   |0058: move-result-object v2
+003d16: 1c03 4300                              |0059: const-class v3, [F // type@0043
+003d1a: 3332 0f00                              |005b: if-ne v2, v3, 006a // +000f
+003d1e: 6202 1300                              |005d: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003d22: 0713                                   |005f: move-object v3, v1
+003d24: 1f03 4300                              |0060: check-cast v3, [F // type@0043
+003d28: 7110 e800 0300                         |0062: invoke-static {v3}, Ljava/util/Arrays;.toString:([F)Ljava/lang/String; // method@00e8
+003d2e: 0c03                                   |0065: move-result-object v3
+003d30: 6e20 b000 3200                         |0066: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003d36: 2822                                   |0069: goto 008b // +0022
+003d38: 6e10 c000 0100                         |006a: invoke-virtual {v1}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003d3e: 0c02                                   |006d: move-result-object v2
+003d40: 1c03 4200                              |006e: const-class v3, [D // type@0042
+003d44: 3332 0f00                              |0070: if-ne v2, v3, 007f // +000f
+003d48: 6202 1300                              |0072: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003d4c: 0713                                   |0074: move-object v3, v1
+003d4e: 1f03 4200                              |0075: check-cast v3, [D // type@0042
+003d52: 7110 e700 0300                         |0077: invoke-static {v3}, Ljava/util/Arrays;.toString:([D)Ljava/lang/String; // method@00e7
+003d58: 0c03                                   |007a: move-result-object v3
+003d5a: 6e20 b000 3200                         |007b: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003d60: 280d                                   |007e: goto 008b // +000d
+003d62: 6202 1300                              |007f: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003d66: 0713                                   |0081: move-object v3, v1
+003d68: 1f03 4800                              |0082: check-cast v3, [Ljava/lang/Object; // type@0048
+003d6c: 7110 eb00 0300                         |0084: invoke-static {v3}, Ljava/util/Arrays;.toString:([Ljava/lang/Object;)Ljava/lang/String; // method@00eb
+003d72: 0c03                                   |0087: move-result-object v3
+003d74: 6e20 b000 3200                         |0088: invoke-virtual {v2, v3}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003d7a: 2808                                   |008b: goto 0093 // +0008
+003d7c: 6201 1300                              |008c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003d80: 4602 0500                              |008e: aget-object v2, v5, v0
+003d84: 6e20 af00 2100                         |0090: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+003d8a: d800 0001                              |0093: add-int/lit8 v0, v0, #int 1 // #01
+003d8e: 2900 78ff                              |0095: goto/16 000d // -0088
+003d92: 6200 1300                              |0097: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003d96: 1a01 0800                              |0099: const-string v1, ");" // string@0008
+003d9a: 6e20 b300 1000                         |009b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@00b3
+003da0: 0e00                                   |009e: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=29
+        0x0005 line=30
+        0x000c line=31
+        0x0010 line=32
+        0x0012 line=33
+        0x0019 line=35
+        0x0029 line=36
+        0x002b line=37
+        0x0033 line=38
+        0x0040 line=39
+        0x0048 line=40
+        0x0055 line=41
+        0x005d line=42
+        0x006a line=43
+        0x0072 line=44
+        0x007f line=46
+        0x008b line=48
+        0x008c line=49
+        0x0093 line=31
+        0x0097 line=52
+        0x009e line=53
+      locals        : 
+        0x002b - 0x008b reg=1 array Ljava/lang/Object; 
+        0x000d - 0x0097 reg=0 i I 
+        0x0000 - 0x009f reg=4 method Ljava/lang/String; 
+        0x0000 - 0x009f reg=5 args [Ljava/lang/Object; 
+
+    #26              : (in LTestVariableArityLinkerMethod;)
+      name          : 'test'
+      type          : '()V'
+      access        : 0x0008 (STATIC)
+      method_idx    : 168
+      code          -
+      registers     : 3
+      ins           : 0
+      outs          : 2
+      insns size    : 224 16-bit code units
+003da4:                                        |[003da4] TestVariableArityLinkerMethod.test:()V
+003db4: 1200                                   |0000: const/4 v0, #int 0 // #0
+003db6: 0101                                   |0001: move v1, v0
+003db8: 1222                                   |0002: const/4 v2, #int 2 // #2
+003dba: 3521 0e00                              |0003: if-ge v1, v2, 0011 // +000e
+003dbe: fc00 1f00 0000                         |0005: invoke-custom {}, call_site@001f
+003dc4: fc00 2000 0000                         |0008: invoke-custom {}, call_site@0020
+003dca: fc00 2100 0000                         |000b: invoke-custom {}, call_site@0021
+003dd0: d801 0101                              |000e: add-int/lit8 v1, v1, #int 1 // #01
+003dd4: 28f2                                   |0010: goto 0002 // -000e
+003dd6: 0000                                   |0011: nop // spacer
+003dd8: 3520 0e00                              |0012: if-ge v0, v2, 0020 // +000e
+003ddc: fc00 2200 0000                         |0014: invoke-custom {}, call_site@0022
+003de2: fc00 2300 0000                         |0017: invoke-custom {}, call_site@0023
+003de8: fc00 2400 0000                         |001a: invoke-custom {}, call_site@0024
+003dee: d800 0001                              |001d: add-int/lit8 v0, v0, #int 1 // #01
+003df2: 28f3                                   |001f: goto 0012 // -000d
+003df4: fc00 2500 0000                         |0020: invoke-custom {}, call_site@0025
+003dfa: fc00 2600 0000                         |0023: invoke-custom {}, call_site@0026
+003e00: fc00 2700 0000                         |0026: invoke-custom {}, call_site@0027
+003e06: fc00 2800 0000                         |0029: invoke-custom {}, call_site@0028
+003e0c: fc00 2900 0000                         |002c: invoke-custom {}, call_site@0029
+003e12: fc00 2a00 0000                         |002f: invoke-custom {}, call_site@002a
+003e18: 7100 8e00 0000                         |0032: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003e1e: 2826                                   |0035: goto 005b // +0026
+003e20: 0d00                                   |0036: move-exception v0
+003e22: 6201 1300                              |0037: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e26: 1a02 8201                              |0039: const-string v2, "methodO => " // string@0182
+003e2a: 6e20 b000 2100                         |003b: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003e30: 6201 1300                              |003e: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e34: 6e10 c000 0000                         |0040: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003e3a: 0c02                                   |0043: move-result-object v2
+003e3c: 6e20 af00 2100                         |0044: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+003e42: 6201 1300                              |0047: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e46: 1a02 0200                              |0049: const-string v2, " => " // string@0002
+003e4a: 6e20 b000 2100                         |004b: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003e50: 6201 1300                              |004e: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e54: 6e10 b600 0000                         |0050: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+003e5a: 0c02                                   |0053: move-result-object v2
+003e5c: 6e10 c000 0200                         |0054: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003e62: 0c02                                   |0057: move-result-object v2
+003e64: 6e20 b200 2100                         |0058: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+003e6a: fc00 2b00 0000                         |005b: invoke-custom {}, call_site@002b
+003e70: 7100 8e00 0000                         |005e: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003e76: 2826                                   |0061: goto 0087 // +0026
+003e78: 0d00                                   |0062: move-exception v0
+003e7a: 6201 1300                              |0063: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e7e: 1a02 8401                              |0065: const-string v2, "methodP => " // string@0184
+003e82: 6e20 b000 2100                         |0067: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003e88: 6201 1300                              |006a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e8c: 6e10 c000 0000                         |006c: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003e92: 0c02                                   |006f: move-result-object v2
+003e94: 6e20 af00 2100                         |0070: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+003e9a: 6201 1300                              |0073: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003e9e: 1a02 0200                              |0075: const-string v2, " => " // string@0002
+003ea2: 6e20 b000 2100                         |0077: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003ea8: 6201 1300                              |007a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003eac: 6e10 b600 0000                         |007c: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+003eb2: 0c02                                   |007f: move-result-object v2
+003eb4: 6e10 c000 0200                         |0080: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003eba: 0c02                                   |0083: move-result-object v2
+003ebc: 6e20 b200 2100                         |0084: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+003ec2: fc00 2c00 0000                         |0087: invoke-custom {}, call_site@002c
+003ec8: 7100 8e00 0000                         |008a: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003ece: 2826                                   |008d: goto 00b3 // +0026
+003ed0: 0d00                                   |008e: move-exception v0
+003ed2: 6201 1300                              |008f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ed6: 1a02 8601                              |0091: const-string v2, "methodQ => " // string@0186
+003eda: 6e20 b000 2100                         |0093: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003ee0: 6201 1300                              |0096: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ee4: 6e10 c000 0000                         |0098: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003eea: 0c02                                   |009b: move-result-object v2
+003eec: 6e20 af00 2100                         |009c: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+003ef2: 6201 1300                              |009f: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003ef6: 1a02 0200                              |00a1: const-string v2, " => " // string@0002
+003efa: 6e20 b000 2100                         |00a3: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003f00: 6201 1300                              |00a6: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003f04: 6e10 b600 0000                         |00a8: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+003f0a: 0c02                                   |00ab: move-result-object v2
+003f0c: 6e10 c000 0200                         |00ac: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003f12: 0c02                                   |00af: move-result-object v2
+003f14: 6e20 b200 2100                         |00b0: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+003f1a: fc00 2d00 0000                         |00b3: invoke-custom {}, call_site@002d
+003f20: 7100 8e00 0000                         |00b6: invoke-static {}, LTestVariableArityLinkerMethod;.assertNotReached:()V // method@008e
+003f26: 2826                                   |00b9: goto 00df // +0026
+003f28: 0d00                                   |00ba: move-exception v0
+003f2a: 6201 1300                              |00bb: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003f2e: 1a02 8801                              |00bd: const-string v2, "methodR => " // string@0188
+003f32: 6e20 b000 2100                         |00bf: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003f38: 6201 1300                              |00c2: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003f3c: 6e10 c000 0000                         |00c4: invoke-virtual {v0}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003f42: 0c02                                   |00c7: move-result-object v2
+003f44: 6e20 af00 2100                         |00c8: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/Object;)V // method@00af
+003f4a: 6201 1300                              |00cb: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003f4e: 1a02 0200                              |00cd: const-string v2, " => " // string@0002
+003f52: 6e20 b000 2100                         |00cf: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.print:(Ljava/lang/String;)V // method@00b0
+003f58: 6201 1300                              |00d2: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0013
+003f5c: 6e10 b600 0000                         |00d4: invoke-virtual {v0}, Ljava/lang/BootstrapMethodError;.getCause:()Ljava/lang/Throwable; // method@00b6
+003f62: 0c02                                   |00d7: move-result-object v2
+003f64: 6e10 c000 0200                         |00d8: invoke-virtual {v2}, Ljava/lang/Object;.getClass:()Ljava/lang/Class; // method@00c0
+003f6a: 0c02                                   |00db: move-result-object v2
+003f6c: 6e20 b200 2100                         |00dc: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V // method@00b2
+003f72: 0e00                                   |00df: return-void
+      catches       : 4
+        0x002f - 0x0035
+          Ljava/lang/BootstrapMethodError; -> 0x0036
+        0x005b - 0x0061
+          Ljava/lang/BootstrapMethodError; -> 0x0062
+        0x0087 - 0x008d
+          Ljava/lang/BootstrapMethodError; -> 0x008e
+        0x00b3 - 0x00b9
+          Ljava/lang/BootstrapMethodError; -> 0x00ba
+      positions     : 
+        0x0000 line=506
+        0x0005 line=507
+        0x0008 line=508
+        0x000b line=509
+        0x000e line=506
+        0x0011 line=511
+        0x0014 line=512
+        0x0017 line=513
+        0x001a line=514
+        0x001d line=511
+        0x0020 line=516
+        0x0023 line=517
+        0x0026 line=518
+        0x0029 line=519
+        0x002c line=520
+        0x002f line=527
+        0x0032 line=528
+        0x0035 line=534
+        0x0036 line=529
+        0x0037 line=530
+        0x003e line=531
+        0x0047 line=532
+        0x004e line=533
+        0x005b line=538
+        0x005e line=539
+        0x0061 line=545
+        0x0062 line=540
+        0x0063 line=541
+        0x006a line=542
+        0x0073 line=543
+        0x007a line=544
+        0x0087 line=549
+        0x008a line=550
+        0x008d line=556
+        0x008e line=551
+        0x008f line=552
+        0x0096 line=553
+        0x009f line=554
+        0x00a6 line=555
+        0x00b3 line=560
+        0x00b6 line=561
+        0x00b9 line=567
+        0x00ba line=562
+        0x00bb line=563
+        0x00c2 line=564
+        0x00cb line=565
+        0x00d2 line=566
+        0x00df line=568
+      locals        : 
+        0x0002 - 0x0011 reg=1 i I 
+        0x0012 - 0x0020 reg=0 i I 
+        0x0037 - 0x005b reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x0063 - 0x0087 reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x008f - 0x00b3 reg=0 expected Ljava/lang/BootstrapMethodError; 
+        0x00bb - 0x00df reg=0 expected Ljava/lang/BootstrapMethodError; 
+
+  Virtual methods   -
+  source_file_idx   : 156 (TestVariableArityLinkerMethod.java)
+
+Method handle #0:
+  type        : invoke-static
+  target      : LTestBadBootstrapArguments; bsm
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ID)Ljava/lang/invoke/CallSite;
+Method handle #1:
+  type        : invoke-static
+  target      : LTestBadBootstrapArguments; bsm
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite;
+Method handle #2:
+  type        : invoke-static
+  target      : LTestBadBootstrapArguments; bsmDJ
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite;
+Method handle #3:
+  type        : invoke-static
+  target      : LTestBadBootstrapArguments; bsmDoubleLong
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite;
+Method handle #4:
+  type        : invoke-static
+  target      : LTestBadBootstrapArguments; bsmReturningInteger
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer;
+Method handle #5:
+  type        : invoke-static
+  target      : LTestBadBootstrapArguments; bsmReturningObject
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object;
+Method handle #6:
+  type        : invoke-static
+  target      : LTestBadBootstrapArguments; bsmReturningTestersConstantCallsite
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite;
+Method handle #7:
+  type        : invoke-static
+  target      : LTestBadBootstrapArguments; bsmReturningVoid
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V
+Method handle #8:
+  type        : invoke-static
+  target      : LTestBadBootstrapArguments; bsmZBCS
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite;
+Method handle #9:
+  type        : invoke-static
+  target      : LTestDynamicBootstrapArguments; bsm
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite;
+Method handle #10:
+  type        : invoke-static
+  target      : LTestInvocationKinds; lookupConstructor
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #11:
+  type        : invoke-static
+  target      : LTestInvocationKinds; lookupInstanceFieldGetter
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #12:
+  type        : invoke-static
+  target      : LTestInvocationKinds; lookupInstanceFieldSetter
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #13:
+  type        : invoke-static
+  target      : LTestInvocationKinds; lookupStaticFieldGetter
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #14:
+  type        : invoke-static
+  target      : LTestInvocationKinds; lookupStaticFieldSetter
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #15:
+  type        : invoke-static
+  target      : LTestInvocationKinds; lookupVirtual
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #16:
+  type        : invoke-static
+  target      : LTestInvokeCustomWithConcurrentThreads; linkerMethod
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #17:
+  type        : invoke-static
+  target      : LTestLinkerMethodMinimalArguments; linkerMethod
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+Method handle #18:
+  type        : invoke-static
+  target      : LTestLinkerMethodMultipleArgumentTypes; linkerMethod
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite;
+Method handle #19:
+  type        : invoke-static
+  target      : LTestVariableArityLinkerMethod; bsmWithBoxedArray
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite;
+Method handle #20:
+  type        : invoke-static
+  target      : LTestVariableArityLinkerMethod; bsmWithClassAndFloatArray
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite;
+Method handle #21:
+  type        : invoke-static
+  target      : LTestVariableArityLinkerMethod; bsmWithClassArray
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite;
+Method handle #22:
+  type        : invoke-static
+  target      : LTestVariableArityLinkerMethod; bsmWithDoubleArray
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite;
+Method handle #23:
+  type        : invoke-static
+  target      : LTestVariableArityLinkerMethod; bsmWithFloatAndLongArray
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite;
+Method handle #24:
+  type        : invoke-static
+  target      : LTestVariableArityLinkerMethod; bsmWithIntAndStringArray
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite;
+Method handle #25:
+  type        : invoke-static
+  target      : LTestVariableArityLinkerMethod; bsmWithLongAndIntArray
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite;
+Method handle #26:
+  type        : invoke-static
+  target      : LTestVariableArityLinkerMethod; bsmWithStringArray
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite;
+Method handle #27:
+  type        : invoke-static
+  target      : LTestVariableArityLinkerMethod; bsmWithWiderArray
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite;
+Method handle #28:
+  type        : invoke-static
+  target      : LUnrelatedBSM; bsm
+  target_type : (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite;
+Call site #0: // offset 29649
+  link_argument[0] : 1 (MethodHandle)
+  link_argument[1] : happy (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : -1 (int)
+  link_argument[4] : very (String)
+Call site #1: // offset 29662
+  link_argument[0] : 0 (MethodHandle)
+  link_argument[1] : wrongParameterTypes (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : -1 (int)
+  link_argument[4] : very (String)
+Call site #2: // offset 29675
+  link_argument[0] : 0 (MethodHandle)
+  link_argument[1] : missingParameterTypes (String)
+  link_argument[2] : ()V (MethodType)
+Call site #3: // offset 29683
+  link_argument[0] : 1 (MethodHandle)
+  link_argument[1] : extraArguments (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 1 (int)
+  link_argument[4] : 2 (String)
+  link_argument[5] : 3 (int)
+Call site #4: // offset 29697
+  link_argument[0] : 1 (MethodHandle)
+  link_argument[1] : wrongArguments (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 1 (String)
+  link_argument[4] : 3.14159 (double)
+Call site #5: // offset 29697
+  link_argument[0] : 1 (MethodHandle)
+  link_argument[1] : wrongArguments (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 1 (String)
+  link_argument[4] : 3.14159 (double)
+Call site #6: // offset 29716
+  link_argument[0] : 1 (MethodHandle)
+  link_argument[1] : wrongArgumentsAgain (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 3.14159 (double)
+  link_argument[4] : pie (String)
+Call site #7: // offset 29736
+  link_argument[0] : 8 (MethodHandle)
+  link_argument[1] : narrowArguments (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 1 (int)
+  link_argument[4] : 127 (int)
+  link_argument[5] : 65 (int)
+  link_argument[6] : -32768 (int)
+Call site #8: // offset 29753
+  link_argument[0] : 2 (MethodHandle)
+  link_argument[1] : wideningArguments (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 1.79769e+308 (double)
+  link_argument[4] : 2147483647 (int)
+Call site #9: // offset 29775
+  link_argument[0] : 3 (MethodHandle)
+  link_argument[1] : boxingArguments (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 1.79769e+308 (double)
+  link_argument[4] : 9223372036854775807 (long)
+Call site #10: // offset 29800
+  link_argument[0] : 3 (MethodHandle)
+  link_argument[1] : wideningBoxingArguments (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 3.40282e+38 (float)
+  link_argument[4] : 2147483647 (long)
+Call site #11: // offset 29818
+  link_argument[0] : 7 (MethodHandle)
+  link_argument[1] : voidReturnType (String)
+  link_argument[2] : ()V (MethodType)
+Call site #12: // offset 29826
+  link_argument[0] : 5 (MethodHandle)
+  link_argument[1] : ObjectReturnType (String)
+  link_argument[2] : ()V (MethodType)
+Call site #13: // offset 29833
+  link_argument[0] : 4 (MethodHandle)
+  link_argument[1] : integerReturnType (String)
+  link_argument[2] : ()V (MethodType)
+Call site #14: // offset 29841
+  link_argument[0] : 6 (MethodHandle)
+  link_argument[1] : sayHello (String)
+  link_argument[2] : ()V (MethodType)
+Call site #15: // offset 29849
+  link_argument[0] : 9 (MethodHandle)
+  link_argument[1] : target (String)
+  link_argument[2] : (ILjava/lang/String;Ljava/lang/Double;)I (MethodType)
+  link_argument[3] : A (String)
+  link_argument[4] : 100000000 (long)
+Call site #16: // offset 29849
+  link_argument[0] : 9 (MethodHandle)
+  link_argument[1] : target (String)
+  link_argument[2] : (ILjava/lang/String;Ljava/lang/Double;)I (MethodType)
+  link_argument[3] : A (String)
+  link_argument[4] : 100000000 (long)
+Call site #17: // offset 29849
+  link_argument[0] : 9 (MethodHandle)
+  link_argument[1] : target (String)
+  link_argument[2] : (ILjava/lang/String;Ljava/lang/Double;)I (MethodType)
+  link_argument[3] : A (String)
+  link_argument[4] : 100000000 (long)
+Call site #18: // offset 29864
+  link_argument[0] : 10 (MethodHandle)
+  link_argument[1] : unused (String)
+  link_argument[2] : (I)LTestInvocationKinds$Widget; (MethodType)
+Call site #19: // offset 29872
+  link_argument[0] : 12 (MethodHandle)
+  link_argument[1] : instance_field (String)
+  link_argument[2] : (LTestInvocationKinds;D)V (MethodType)
+Call site #20: // offset 29880
+  link_argument[0] : 11 (MethodHandle)
+  link_argument[1] : instance_field (String)
+  link_argument[2] : (LTestInvocationKinds;)D (MethodType)
+Call site #21: // offset 29888
+  link_argument[0] : 15 (MethodHandle)
+  link_argument[1] : getMaxIntegerValue (String)
+  link_argument[2] : (LTestInvocationKinds;II)I (MethodType)
+Call site #22: // offset 29896
+  link_argument[0] : 14 (MethodHandle)
+  link_argument[1] : static_field (String)
+  link_argument[2] : (I)V (MethodType)
+Call site #23: // offset 29896
+  link_argument[0] : 14 (MethodHandle)
+  link_argument[1] : static_field (String)
+  link_argument[2] : (I)V (MethodType)
+Call site #24: // offset 29904
+  link_argument[0] : 13 (MethodHandle)
+  link_argument[1] : static_field (String)
+  link_argument[2] : ()I (MethodType)
+Call site #25: // offset 29904
+  link_argument[0] : 13 (MethodHandle)
+  link_argument[1] : static_field (String)
+  link_argument[2] : ()I (MethodType)
+Call site #26: // offset 29912
+  link_argument[0] : 16 (MethodHandle)
+  link_argument[1] : setCalled (String)
+  link_argument[2] : (I)I (MethodType)
+Call site #27: // offset 29920
+  link_argument[0] : 17 (MethodHandle)
+  link_argument[1] : _add (String)
+  link_argument[2] : (II)I (MethodType)
+Call site #28: // offset 29927
+  link_argument[0] : 18 (MethodHandle)
+  link_argument[1] : _add (String)
+  link_argument[2] : (II)I (MethodType)
+  link_argument[3] : -1 (int)
+  link_argument[4] : 1 (int)
+  link_argument[5] : 97 (int)
+  link_argument[6] : 1024 (int)
+  link_argument[7] : 1 (int)
+  link_argument[8] : 11.1 (float)
+  link_argument[9] : 2.2 (double)
+  link_argument[10] : Hello (String)
+  link_argument[11] : LTestLinkerMethodMultipleArgumentTypes; (Class)
+  link_argument[12] : 123456789 (long)
+Call site #29: // offset 29968
+  link_argument[0] : 28 (MethodHandle)
+  link_argument[1] : _addf (String)
+  link_argument[2] : (FF)F (MethodType)
+  link_argument[3] : LTestLinkerUnrelatedBSM; (Class)
+Call site #30: // offset 29977
+  link_argument[0] : 28 (MethodHandle)
+  link_argument[1] : _subf (String)
+  link_argument[2] : (FF)F (MethodType)
+  link_argument[3] : LTestLinkerUnrelatedBSM; (Class)
+Call site #31: // offset 29986
+  link_argument[0] : 26 (MethodHandle)
+  link_argument[1] : methodA (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : Aachen (String)
+  link_argument[4] : Aalborg (String)
+  link_argument[5] : Aalto (String)
+Call site #32: // offset 30000
+  link_argument[0] : 26 (MethodHandle)
+  link_argument[1] : methodB (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : barium (String)
+Call site #33: // offset 30010
+  link_argument[0] : 26 (MethodHandle)
+  link_argument[1] : methodC (String)
+  link_argument[2] : ()V (MethodType)
+Call site #34: // offset 30018
+  link_argument[0] : 24 (MethodHandle)
+  link_argument[1] : methodD (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 101 (int)
+  link_argument[4] : zoo (String)
+  link_argument[5] : zoogene (String)
+  link_argument[6] : zoogenic (String)
+Call site #35: // offset 30037
+  link_argument[0] : 24 (MethodHandle)
+  link_argument[1] : methodE (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 102 (int)
+  link_argument[4] : zonic (String)
+Call site #36: // offset 30050
+  link_argument[0] : 24 (MethodHandle)
+  link_argument[1] : methodF (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 103 (int)
+Call site #37: // offset 30060
+  link_argument[0] : 25 (MethodHandle)
+  link_argument[1] : methodG (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 81985529216486895 (long)
+  link_argument[4] : 1 (int)
+  link_argument[5] : -1 (int)
+  link_argument[6] : 2 (int)
+  link_argument[7] : -2 (int)
+Call site #38: // offset 30085
+  link_argument[0] : 23 (MethodHandle)
+  link_argument[1] : methodH (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : -2.71828 (float)
+  link_argument[4] : 999999999999 (long)
+  link_argument[5] : -8888888888888 (long)
+Call site #39: // offset 30112
+  link_argument[0] : 20 (MethodHandle)
+  link_argument[1] : methodI (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : Ljava/lang/Throwable; (Class)
+  link_argument[4] : 3.40282e+38 (float)
+  link_argument[5] : 1.4013e-45 (float)
+  link_argument[6] : 3.14159 (float)
+  link_argument[7] : -3.14159 (float)
+Call site #40: // offset 30142
+  link_argument[0] : 22 (MethodHandle)
+  link_argument[1] : methodJ (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 1.79769e+308 (double)
+  link_argument[4] : 4.94066e-324 (double)
+  link_argument[5] : 2.71828 (double)
+  link_argument[6] : -3.14159 (double)
+Call site #41: // offset 30186
+  link_argument[0] : 21 (MethodHandle)
+  link_argument[1] : methodK (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : Ljava/lang/Integer; (Class)
+  link_argument[4] : Ljava/lang/invoke/MethodHandles; (Class)
+  link_argument[5] : Ljava/util/Arrays; (Class)
+Call site #42: // offset 30200
+  link_argument[0] : 24 (MethodHandle)
+  link_argument[1] : methodO (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 103 (int)
+  link_argument[4] : 104 (int)
+Call site #43: // offset 30212
+  link_argument[0] : 24 (MethodHandle)
+  link_argument[1] : methodP (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 103 (int)
+  link_argument[4] : A (String)
+  link_argument[5] : B (String)
+  link_argument[6] : 42 (int)
+Call site #44: // offset 30228
+  link_argument[0] : 27 (MethodHandle)
+  link_argument[1] : methodQ (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 103 (int)
+  link_argument[4] : 42 (int)
+Call site #45: // offset 30240
+  link_argument[0] : 19 (MethodHandle)
+  link_argument[1] : methodR (String)
+  link_argument[2] : ()V (MethodType)
+  link_argument[3] : 1030 (int)
+  link_argument[4] : 420 (int)
+Opened 'all-dex-files.jar:classes5.dex', DEX version '037'
+DEX file header:
+magic               : 'dex\n037\0'
+checksum            : 0b5f9fd7
+signature           : fcf4...f0e5
+file_size           : 1160
+header_size         : 112
+link_size           : 0
+link_off            : 0 (0x000000)
+string_ids_size     : 30
+string_ids_off      : 112 (0x000070)
+type_ids_size       : 11
+type_ids_off        : 232 (0x0000e8)
+proto_ids_size      : 6
+proto_ids_off       : 276 (0x000114)
+field_ids_size      : 0
+field_ids_off       : 0 (0x000000)
+method_ids_size     : 5
+method_ids_off      : 348 (0x00015c)
+class_defs_size     : 1
+class_defs_off      : 388 (0x000184)
+data_size           : 740
+data_off            : 420 (0x0001a4)
+
+Class #0 header:
+class_idx           : 2
+access_flags        : 1 (0x0001)
+superclass_idx      : 4
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 12
+annotations_off     : 528 (0x000210)
+class_data_off      : 959 (0x0003bf)
+static_fields_size  : 0
+instance_fields_size: 0
+direct_methods_size : 2
+virtual_methods_size: 0
+
+Class #0 annotations:
+Annotations on method #1 'main'
+  VISIBILITY_SYSTEM Ldalvik/annotation/Throws; value={ Ljava/lang/Throwable; }
+
+Class #0            -
+  Class descriptor  : 'LMain;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+  Static fields     -
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LMain;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 0
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+0001ac:                                        |[0001ac] Main.<init>:()V
+0001bc: 7010 0200 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0002
+0001c2: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=9
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LMain; 
+
+    #1              : (in LMain;)
+      name          : 'main'
+      type          : '([Ljava/lang/String;)V'
+      access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 1
+      code          -
+      registers     : 10
+      ins           : 1
+      outs          : 0
+      insns size    : 30 16-bit code units
+0001c4:                                        |[0001c4] Main.main:([Ljava/lang/String;)V
+0001d4: 1802 9a99 9999 9999 0140               |0000: const-wide v2, #double 2.2 // #400199999999999a
+0001de: 1214                                   |0005: const/4 v4, #int 1 // #1
+0001e0: 1200                                   |0006: const/4 v0, #int 0 // #0
+0001e2: 1205                                   |0007: const/4 v5, #int 0 // #0
+0001e4: 1b01 1200 0000                         |0008: const-string/jumbo v1, "a" // string@00000012
+0001ea: 0146                                   |000b: move v6, v4
+0001ec: fb07 0300 0000 0200                    |000c: invoke-polymorphic/range {v0, v1, v2, v3, v4, v5, v6}, Ljava/lang/invoke/MethodHandle;.invoke:([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/String;DILjava/lang/Object;I)Ljava/lang/String; // method@0003, proto@0002
+0001f4: 0c07                                   |0010: move-result-object v7
+0001f6: fa40 0400 2043 0000                    |0011: invoke-polymorphic {v0, v2, v3, v4}, Ljava/lang/invoke/MethodHandle;.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, (DI)I // method@0004, proto@0000
+0001fe: 0a08                                   |0015: move-result v8
+000200: 1b01 1200 0000                         |0016: const-string/jumbo v1, "a" // string@00000012
+000206: fa54 0300 1032 0400                    |0019: invoke-polymorphic {v0, v1, v2, v3, v4}, Ljava/lang/invoke/MethodHandle;.invoke:([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/String;DI)V // method@0003, proto@0004
+00020e: 0e00                                   |001d: return-void
+      catches       : (none)
+      positions     : 
+        0x0006 line=31
+        0x0007 line=32
+        0x0008 line=33
+        0x0011 line=34
+        0x0016 line=35
+        0x001d line=56
+      locals        : 
+        0x0007 - 0x001e reg=0 handle Ljava/lang/invoke/MethodHandle; 
+        0x0008 - 0x001e reg=5 o Ljava/lang/Object; 
+        0x0011 - 0x001e reg=7 s Ljava/lang/String; 
+        0x0016 - 0x001e reg=8 x I 
+        0x0000 - 0x001e reg=9 args [Ljava/lang/String; 
+
+  Virtual methods   -
+  source_file_idx   : 12 (Main.java)
+
+Opened 'all-dex-files.jar:classes6.dex', DEX version '035'
+DEX file header:
+magic               : 'dex\n035\0'
+checksum            : 52d4fc6d
+signature           : 6e82...2f27
+file_size           : 1264
+header_size         : 112
+link_size           : 0
+link_off            : 0 (0x000000)
+string_ids_size     : 28
+string_ids_off      : 112 (0x000070)
+type_ids_size       : 12
+type_ids_off        : 224 (0x0000e0)
+proto_ids_size      : 1
+proto_ids_off       : 272 (0x000110)
+field_ids_size      : 12
+field_ids_off       : 284 (0x00011c)
+method_ids_size     : 2
+method_ids_off      : 380 (0x00017c)
+class_defs_size     : 1
+class_defs_off      : 396 (0x00018c)
+data_size           : 836
+data_off            : 428 (0x0001ac)
+
+Class #0 header:
+class_idx           : 6
+access_flags        : 1 (0x0001)
+superclass_idx      : 7
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 11
+annotations_off     : 0 (0x000000)
+class_data_off      : 1067 (0x00042b)
+static_fields_size  : 12
+instance_fields_size: 0
+direct_methods_size : 1
+virtual_methods_size: 0
+
+Class #0            -
+  Class descriptor  : 'LStaticFields;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+  Static fields     -
+    #0              : (in LStaticFields;)
+      name          : 'test00_public_static_final_byte_42'
+      type          : 'B'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 42
+    #1              : (in LStaticFields;)
+      name          : 'test01_public_static_final_short_43'
+      type          : 'S'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 43
+    #2              : (in LStaticFields;)
+      name          : 'test02_public_static_final_char_X'
+      type          : 'C'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 88
+    #3              : (in LStaticFields;)
+      name          : 'test03_public_static_final_int_44'
+      type          : 'I'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 44
+    #4              : (in LStaticFields;)
+      name          : 'test04_public_static_final_long_45'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 45
+    #5              : (in LStaticFields;)
+      name          : 'test05_public_static_final_float_46_47'
+      type          : 'F'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 46.47
+    #6              : (in LStaticFields;)
+      name          : 'test06_public_static_final_double_48_49'
+      type          : 'D'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 48.49
+    #7              : (in LStaticFields;)
+      name          : 'test07_public_static_final_string'
+      type          : 'Ljava/lang/String;'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : "abc \\><\"'&\t\r\n"
+    #8              : (in LStaticFields;)
+      name          : 'test08_public_static_final_object_null'
+      type          : 'Ljava/lang/Object;'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : null
+    #9              : (in LStaticFields;)
+      name          : 'test09_public_static_final_boolean_true'
+      type          : 'Z'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : true
+    #10              : (in LStaticFields;)
+      name          : 'test10_private_static_final_int_50'
+      type          : 'I'
+      access        : 0x001a (PRIVATE STATIC FINAL)
+      value         : 50
+    #11              : (in LStaticFields;)
+      name          : 'test99_empty_value'
+      type          : 'I'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LStaticFields;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 0
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+0001ac:                                        |[0001ac] StaticFields.<init>:()V
+0001bc: 7010 0100 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0001
+0001c2: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=24
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LStaticFields; 
+
+  Virtual methods   -
+  source_file_idx   : 11 (StaticFields.java)
+
+Opened 'all-dex-files.jar:classes7.dex', DEX version '035'
+DEX file header:
+magic               : 'dex\n035\0'
+checksum            : 7605eec0
+signature           : c197...a065
+file_size           : 1864
+header_size         : 112
+link_size           : 0
+link_off            : 0 (0x000000)
+string_ids_size     : 70
+string_ids_off      : 112 (0x000070)
+type_ids_size       : 12
+type_ids_off        : 392 (0x000188)
+proto_ids_size      : 1
+proto_ids_off       : 440 (0x0001b8)
+field_ids_size      : 54
+field_ids_off       : 452 (0x0001c4)
+method_ids_size     : 3
+method_ids_off      : 884 (0x000374)
+class_defs_size     : 1
+class_defs_off      : 908 (0x00038c)
+data_size           : 924
+data_off            : 940 (0x0003ac)
+
+Class #0 header:
+class_idx           : 6
+access_flags        : 1 (0x0001)
+superclass_idx      : 7
+interfaces_off      : 0 (0x000000)
+source_file_idx     : 13
+annotations_off     : 0 (0x000000)
+class_data_off      : 1578 (0x00062a)
+static_fields_size  : 54
+instance_fields_size: 0
+direct_methods_size : 2
+virtual_methods_size: 0
+
+Class #0            -
+  Class descriptor  : 'LTest;'
+  Access flags      : 0x0001 (PUBLIC)
+  Superclass        : 'Ljava/lang/Object;'
+  Interfaces        -
+  Static fields     -
+    #0              : (in LTest;)
+      name          : 'mB0'
+      type          : 'B'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 0
+    #1              : (in LTest;)
+      name          : 'mB1'
+      type          : 'B'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 127
+    #2              : (in LTest;)
+      name          : 'mB2'
+      type          : 'B'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -128
+    #3              : (in LTest;)
+      name          : 'mB3'
+      type          : 'B'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -1
+    #4              : (in LTest;)
+      name          : 'mC0'
+      type          : 'C'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 0
+    #5              : (in LTest;)
+      name          : 'mC1'
+      type          : 'C'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 32767
+    #6              : (in LTest;)
+      name          : 'mC2'
+      type          : 'C'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 32768
+    #7              : (in LTest;)
+      name          : 'mC3'
+      type          : 'C'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 255
+    #8              : (in LTest;)
+      name          : 'mC4'
+      type          : 'C'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 65520
+    #9              : (in LTest;)
+      name          : 'mC5'
+      type          : 'C'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 65535
+    #10              : (in LTest;)
+      name          : 'mD0'
+      type          : 'D'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -inf
+    #11              : (in LTest;)
+      name          : 'mD1'
+      type          : 'D'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 4.94066e-324
+    #12              : (in LTest;)
+      name          : 'mD2'
+      type          : 'D'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -0
+    #13              : (in LTest;)
+      name          : 'mD3'
+      type          : 'D'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 0
+    #14              : (in LTest;)
+      name          : 'mD4'
+      type          : 'D'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 1.79769e+308
+    #15              : (in LTest;)
+      name          : 'mD5'
+      type          : 'D'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : inf
+    #16              : (in LTest;)
+      name          : 'mD6'
+      type          : 'D'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : nan
+    #17              : (in LTest;)
+      name          : 'mF0'
+      type          : 'F'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -inf
+    #18              : (in LTest;)
+      name          : 'mF1'
+      type          : 'F'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 1.4013e-45
+    #19              : (in LTest;)
+      name          : 'mF2'
+      type          : 'F'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -0
+    #20              : (in LTest;)
+      name          : 'mF3'
+      type          : 'F'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 0
+    #21              : (in LTest;)
+      name          : 'mF4'
+      type          : 'F'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 3.40282e+38
+    #22              : (in LTest;)
+      name          : 'mF5'
+      type          : 'F'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : inf
+    #23              : (in LTest;)
+      name          : 'mF6'
+      type          : 'F'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : nan
+    #24              : (in LTest;)
+      name          : 'mI0'
+      type          : 'I'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 0
+    #25              : (in LTest;)
+      name          : 'mI1'
+      type          : 'I'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 2147483647
+    #26              : (in LTest;)
+      name          : 'mI2'
+      type          : 'I'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -2147483648
+    #27              : (in LTest;)
+      name          : 'mI3'
+      type          : 'I'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 255
+    #28              : (in LTest;)
+      name          : 'mI4'
+      type          : 'I'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -16
+    #29              : (in LTest;)
+      name          : 'mI5'
+      type          : 'I'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -4096
+    #30              : (in LTest;)
+      name          : 'mI6'
+      type          : 'I'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -1048576
+    #31              : (in LTest;)
+      name          : 'mI7'
+      type          : 'I'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -1
+    #32              : (in LTest;)
+      name          : 'mJ0'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 0
+    #33              : (in LTest;)
+      name          : 'mJ1'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 9223372036854775807
+    #34              : (in LTest;)
+      name          : 'mJ2'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -9223372036854775808
+    #35              : (in LTest;)
+      name          : 'mJ3'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 255
+    #36              : (in LTest;)
+      name          : 'mJ4'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -16
+    #37              : (in LTest;)
+      name          : 'mJ5'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -4096
+    #38              : (in LTest;)
+      name          : 'mJ6'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -1048576
+    #39              : (in LTest;)
+      name          : 'mJ7'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -268435456
+    #40              : (in LTest;)
+      name          : 'mJ8'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -68719476736
+    #41              : (in LTest;)
+      name          : 'mJ9'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -17592186044416
+    #42              : (in LTest;)
+      name          : 'mJa'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -4503599627370496
+    #43              : (in LTest;)
+      name          : 'mJb'
+      type          : 'J'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -1
+    #44              : (in LTest;)
+      name          : 'mObject'
+      type          : 'Ljava/lang/Object;'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : null
+    #45              : (in LTest;)
+      name          : 'mS0'
+      type          : 'S'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 0
+    #46              : (in LTest;)
+      name          : 'mS1'
+      type          : 'S'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 32767
+    #47              : (in LTest;)
+      name          : 'mS2'
+      type          : 'S'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -32768
+    #48              : (in LTest;)
+      name          : 'mS3'
+      type          : 'S'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : 255
+    #49              : (in LTest;)
+      name          : 'mS4'
+      type          : 'S'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -16
+    #50              : (in LTest;)
+      name          : 'mS5'
+      type          : 'S'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : -1
+    #51              : (in LTest;)
+      name          : 'mString'
+      type          : 'Ljava/lang/String;'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : "<&\"JOHO\"&>\n"
+    #52              : (in LTest;)
+      name          : 'mZ0'
+      type          : 'Z'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : false
+    #53              : (in LTest;)
+      name          : 'mZ1'
+      type          : 'Z'
+      access        : 0x0019 (PUBLIC STATIC FINAL)
+      value         : true
+  Instance fields   -
+  Direct methods    -
+    #0              : (in LTest;)
+      name          : '<clinit>'
+      type          : '()V'
+      access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 0
+      code          -
+      registers     : 1
+      ins           : 0
+      outs          : 0
+      insns size    : 4 16-bit code units
+0003ac:                                        |[0003ac] Test.<clinit>:()V
+0003bc: 1200                                   |0000: const/4 v0, #int 0 // #0
+0003be: 6900 2c00                              |0001: sput-object v0, LTest;.mObject:Ljava/lang/Object; // field@002c
+0003c2: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=66
+      locals        : 
+
+    #1              : (in LTest;)
+      name          : '<init>'
+      type          : '()V'
+      access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 1
+      code          -
+      registers     : 1
+      ins           : 1
+      outs          : 1
+      insns size    : 4 16-bit code units
+0003c4:                                        |[0003c4] Test.<init>:()V
+0003d4: 7010 0200 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0002
+0003da: 0e00                                   |0003: return-void
+      catches       : (none)
+      positions     : 
+        0x0000 line=1
+      locals        : 
+        0x0000 - 0x0004 reg=0 this LTest; 
+
+  Virtual methods   -
+  source_file_idx   : 13 (Test.java)
+
diff --git a/test/dexdump/all-dex-files.xml b/test/dexdump/all-dex-files.xml
new file mode 100644
index 0000000..d5520c9
--- /dev/null
+++ b/test/dexdump/all-dex-files.xml
@@ -0,0 +1,1863 @@
+<api>
+<package name=""
+>
+<class name="A"
+ extends="java.lang.Object"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="A"
+ type="A"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+<method name="arrays"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="binary_ops"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="binary_ops_2addr"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="binary_ops_lit16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="binary_ops_lit8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="compares"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="conditionals"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="constants"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="misc"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="moves"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="packed_switch"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="return32"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="return64"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="return_object"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="sparse_switch"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="static_fields"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="unary_ops"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="instance_fields"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="invokes"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</method>
+</class>
+</package>
+<package name="com.google.android.checkers"
+>
+<class name="Checkers"
+ extends="android.app.Activity"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="Checkers"
+ type="com.google.android.checkers.Checkers"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+<method name="onConfigurationChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="android.content.res.Configuration">
+</parameter>
+</method>
+<method name="onCreate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="onCreateOptionsMenu"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="android.view.Menu">
+</parameter>
+</method>
+<method name="onKeyDown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="int">
+</parameter>
+<parameter name="arg1" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="onOptionsItemSelected"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="android.view.MenuItem">
+</parameter>
+</method>
+<method name="onPause"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="onStop"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="onTrackballEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="android.view.MotionEvent">
+</parameter>
+</method>
+</class>
+<class name="CheckersView"
+ extends="android.view.View"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="CheckersView"
+ type="com.google.android.checkers.CheckersView"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="android.content.Context">
+</parameter>
+<parameter name="arg1" type="android.content.SharedPreferences">
+</parameter>
+</constructor>
+<method name="a"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+</method>
+<method name="a"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="float">
+</parameter>
+<parameter name="arg1" type="float">
+</parameter>
+</method>
+<method name="a"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="int">
+</parameter>
+<parameter name="arg1" type="int">
+</parameter>
+<parameter name="arg2" type="int">
+</parameter>
+<parameter name="arg3" type="int">
+</parameter>
+</method>
+<method name="a"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="android.content.SharedPreferences$Editor">
+</parameter>
+</method>
+<method name="a"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="int">
+</parameter>
+</method>
+<method name="a"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="boolean">
+</parameter>
+</method>
+<method name="b"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+</method>
+<method name="b"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="boolean">
+</parameter>
+</method>
+<method name="c"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ visibility="public"
+>
+</method>
+<method name="c"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="boolean">
+</parameter>
+</method>
+<method name="d"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="boolean">
+</parameter>
+</method>
+<method name="draw"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="android.graphics.Canvas">
+</parameter>
+</method>
+<method name="e"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="boolean">
+</parameter>
+</method>
+<method name="onSizeChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ visibility="protected"
+>
+<parameter name="arg0" type="int">
+</parameter>
+<parameter name="arg1" type="int">
+</parameter>
+<parameter name="arg2" type="int">
+</parameter>
+<parameter name="arg3" type="int">
+</parameter>
+</method>
+<method name="onTouchEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="setLevel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="int">
+</parameter>
+</method>
+</class>
+<class name="a"
+ extends="java.lang.Thread"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<field name="a"
+ type="int[]"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="b"
+ type="int[]"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="c"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="d"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="e"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="f"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="g"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="h"
+ type="int"
+ transient="false"
+ volatile="true"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</field>
+<constructor name="a"
+ type="com.google.android.checkers.a"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="com.google.android.checkers.CheckersView">
+</parameter>
+</constructor>
+<method name="a"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="boolean">
+</parameter>
+<parameter name="arg1" type="boolean">
+</parameter>
+</method>
+<method name="a"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+</method>
+<method name="a"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="int">
+</parameter>
+</method>
+<method name="a"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="int">
+</parameter>
+<parameter name="arg1" type="int">
+</parameter>
+<parameter name="arg2" type="int">
+</parameter>
+<parameter name="arg3" type="int">
+</parameter>
+<parameter name="arg4" type="boolean">
+</parameter>
+</method>
+<method name="b"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<parameter name="arg0" type="boolean">
+</parameter>
+<parameter name="arg1" type="boolean">
+</parameter>
+</method>
+<method name="run"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+</method>
+</class>
+<class name="g"
+ extends="java.lang.Object"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="true"
+ visibility="public"
+>
+<field name="a"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="b"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="c"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="d"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="e"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="f"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="g"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="h"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="i"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="j"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="k"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="l"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="m"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="n"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="o"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="p"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="q"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+<field name="r"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</field>
+</class>
+</package>
+<package name=""
+>
+<class name="Main"
+ extends="java.lang.Object"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="Main"
+ type="Main"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+<method name="main"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="java.lang.String[]">
+</parameter>
+</method>
+</class>
+</package>
+<package name="constmethodhandle"
+>
+<class name="ConstTest"
+ extends="java.lang.Object"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="ConstTest"
+ type="constmethodhandle.ConstTest"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+<method name="main"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="test1"
+ return="java.lang.invoke.MethodHandle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="test2"
+ return="java.lang.invoke.MethodType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+</class>
+</package>
+<package name=""
+>
+<class name="Main"
+ extends="TestBase"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="Main"
+ type="Main"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+<method name="main"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="java.lang.String[]">
+</parameter>
+</method>
+</class>
+<class name="TestBadBootstrapArguments"
+ extends="TestBase"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="TestBadBootstrapArguments"
+ type="TestBadBootstrapArguments"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+</class>
+<class name="TestInvokeCustomWithConcurrentThreads"
+ extends="TestBase"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<implements name="java.lang.Runnable">
+</implements>
+<method name="notUsed"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="int">
+</parameter>
+</method>
+<method name="test"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+</method>
+<method name="run"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</method>
+</class>
+<class name="TestLinkerMethodMinimalArguments"
+ extends="TestBase"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="TestLinkerMethodMinimalArguments"
+ type="TestLinkerMethodMinimalArguments"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+<method name="test"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="int">
+</parameter>
+<parameter name="arg1" type="int">
+</parameter>
+<parameter name="arg2" type="int">
+</parameter>
+</method>
+</class>
+<class name="TestLinkerMethodMultipleArgumentTypes"
+ extends="TestBase"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="TestLinkerMethodMultipleArgumentTypes"
+ type="TestLinkerMethodMultipleArgumentTypes"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+<method name="test"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="int">
+</parameter>
+<parameter name="arg1" type="int">
+</parameter>
+</method>
+<method name="GetBootstrapRunCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</method>
+</class>
+<class name="TestVariableArityLinkerMethod"
+ extends="TestBase"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="TestVariableArityLinkerMethod"
+ type="TestVariableArityLinkerMethod"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+</class>
+</package>
+<package name=""
+>
+<class name="Main"
+ extends="java.lang.Object"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<constructor name="Main"
+ type="Main"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+<method name="main"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ visibility="public"
+>
+<parameter name="arg0" type="java.lang.String[]">
+</parameter>
+</method>
+</class>
+</package>
+<package name=""
+>
+<class name="StaticFields"
+ extends="java.lang.Object"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<field name="test00_public_static_final_byte_42"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="42"
+>
+</field>
+<field name="test01_public_static_final_short_43"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="43"
+>
+</field>
+<field name="test02_public_static_final_char_X"
+ type="char"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="88"
+>
+</field>
+<field name="test03_public_static_final_int_44"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="44"
+>
+</field>
+<field name="test04_public_static_final_long_45"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="45"
+>
+</field>
+<field name="test05_public_static_final_float_46_47"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="46.47"
+>
+</field>
+<field name="test06_public_static_final_double_48_49"
+ type="double"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="48.49"
+>
+</field>
+<field name="test07_public_static_final_string"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="abc \\&gt;&lt;&quot;'&amp;\u0009\u000d\u000a"
+>
+</field>
+<field name="test08_public_static_final_object_null"
+ type="java.lang.Object"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="null"
+>
+</field>
+<field name="test09_public_static_final_boolean_true"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="true"
+>
+</field>
+<field name="test99_empty_value"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+>
+</field>
+<constructor name="StaticFields"
+ type="StaticFields"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+</class>
+</package>
+<package name=""
+>
+<class name="Test"
+ extends="java.lang.Object"
+ interface="false"
+ abstract="false"
+ static="false"
+ final="false"
+ visibility="public"
+>
+<field name="mB0"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="0"
+>
+</field>
+<field name="mB1"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="127"
+>
+</field>
+<field name="mB2"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-128"
+>
+</field>
+<field name="mB3"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-1"
+>
+</field>
+<field name="mC0"
+ type="char"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="0"
+>
+</field>
+<field name="mC1"
+ type="char"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="32767"
+>
+</field>
+<field name="mC2"
+ type="char"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="32768"
+>
+</field>
+<field name="mC3"
+ type="char"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="255"
+>
+</field>
+<field name="mC4"
+ type="char"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="65520"
+>
+</field>
+<field name="mC5"
+ type="char"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="65535"
+>
+</field>
+<field name="mD0"
+ type="double"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-inf"
+>
+</field>
+<field name="mD1"
+ type="double"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="4.94066e-324"
+>
+</field>
+<field name="mD2"
+ type="double"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-0"
+>
+</field>
+<field name="mD3"
+ type="double"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="0"
+>
+</field>
+<field name="mD4"
+ type="double"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="1.79769e+308"
+>
+</field>
+<field name="mD5"
+ type="double"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="inf"
+>
+</field>
+<field name="mD6"
+ type="double"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="nan"
+>
+</field>
+<field name="mF0"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-inf"
+>
+</field>
+<field name="mF1"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="1.4013e-45"
+>
+</field>
+<field name="mF2"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-0"
+>
+</field>
+<field name="mF3"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="0"
+>
+</field>
+<field name="mF4"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="3.40282e+38"
+>
+</field>
+<field name="mF5"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="inf"
+>
+</field>
+<field name="mF6"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="nan"
+>
+</field>
+<field name="mI0"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="0"
+>
+</field>
+<field name="mI1"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="2147483647"
+>
+</field>
+<field name="mI2"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-2147483648"
+>
+</field>
+<field name="mI3"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="255"
+>
+</field>
+<field name="mI4"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-16"
+>
+</field>
+<field name="mI5"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-4096"
+>
+</field>
+<field name="mI6"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-1048576"
+>
+</field>
+<field name="mI7"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-1"
+>
+</field>
+<field name="mJ0"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="0"
+>
+</field>
+<field name="mJ1"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="9223372036854775807"
+>
+</field>
+<field name="mJ2"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-9223372036854775808"
+>
+</field>
+<field name="mJ3"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="255"
+>
+</field>
+<field name="mJ4"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-16"
+>
+</field>
+<field name="mJ5"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-4096"
+>
+</field>
+<field name="mJ6"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-1048576"
+>
+</field>
+<field name="mJ7"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-268435456"
+>
+</field>
+<field name="mJ8"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-68719476736"
+>
+</field>
+<field name="mJ9"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-17592186044416"
+>
+</field>
+<field name="mJa"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-4503599627370496"
+>
+</field>
+<field name="mJb"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-1"
+>
+</field>
+<field name="mObject"
+ type="java.lang.Object"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="null"
+>
+</field>
+<field name="mS0"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="0"
+>
+</field>
+<field name="mS1"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="32767"
+>
+</field>
+<field name="mS2"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-32768"
+>
+</field>
+<field name="mS3"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="255"
+>
+</field>
+<field name="mS4"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-16"
+>
+</field>
+<field name="mS5"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="-1"
+>
+</field>
+<field name="mString"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="&lt;&amp;&quot;JOHO&quot;&amp;&gt;\u000a"
+>
+</field>
+<field name="mZ0"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="false"
+>
+</field>
+<field name="mZ1"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ visibility="public"
+ value="true"
+>
+</field>
+<constructor name="Test"
+ type="Test"
+ static="false"
+ final="false"
+ visibility="public"
+>
+</constructor>
+</class>
+</package>
+</api>
diff --git a/test/dexdump/all.txt b/test/dexdump/all.txt
index af4fb4c..894bac5 100644
--- a/test/dexdump/all.txt
+++ b/test/dexdump/all.txt
@@ -104,6 +104,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 0
       code          -
       registers     : 1
       ins           : 1
@@ -120,6 +121,7 @@
       name          : 'arrays'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 1
       code          -
       registers     : 3
       ins           : 0
@@ -149,6 +151,7 @@
       name          : 'binary_ops'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 2
       code          -
       registers     : 3
       ins           : 0
@@ -196,6 +199,7 @@
       name          : 'binary_ops_2addr'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 3
       code          -
       registers     : 2
       ins           : 0
@@ -243,6 +247,7 @@
       name          : 'binary_ops_lit16'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 4
       code          -
       registers     : 2
       ins           : 0
@@ -266,6 +271,7 @@
       name          : 'binary_ops_lit8'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 5
       code          -
       registers     : 2
       ins           : 0
@@ -292,6 +298,7 @@
       name          : 'compares'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 6
       code          -
       registers     : 3
       ins           : 0
@@ -312,6 +319,7 @@
       name          : 'conditionals'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 7
       code          -
       registers     : 2
       ins           : 0
@@ -339,6 +347,7 @@
       name          : 'constants'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 8
       code          -
       registers     : 1
       ins           : 0
@@ -365,6 +374,7 @@
       name          : 'misc'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 11
       code          -
       registers     : 5
       ins           : 0
@@ -397,6 +407,7 @@
       name          : 'moves'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 12
       code          -
       registers     : 2
       ins           : 0
@@ -425,6 +436,7 @@
       name          : 'packed_switch'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 13
       code          -
       registers     : 1
       ins           : 0
@@ -446,6 +458,7 @@
       name          : 'return32'
       type          : '()I'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 14
       code          -
       registers     : 1
       ins           : 0
@@ -461,6 +474,7 @@
       name          : 'return64'
       type          : '()I'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 15
       code          -
       registers     : 2
       ins           : 0
@@ -476,6 +490,7 @@
       name          : 'return_object'
       type          : '()Ljava/lang/Object;'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 16
       code          -
       registers     : 1
       ins           : 0
@@ -491,6 +506,7 @@
       name          : 'sparse_switch'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 17
       code          -
       registers     : 2
       ins           : 0
@@ -508,6 +524,7 @@
       name          : 'static_fields'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 18
       code          -
       registers     : 1
       ins           : 0
@@ -537,6 +554,7 @@
       name          : 'unary_ops'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 19
       code          -
       registers     : 2
       ins           : 0
@@ -574,6 +592,7 @@
       name          : 'instance_fields'
       type          : '()V'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 9
       code          -
       registers     : 2
       ins           : 1
@@ -603,6 +622,7 @@
       name          : 'invokes'
       type          : '()V'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 10
       code          -
       registers     : 5
       ins           : 1
diff --git a/test/dexdump/bytecodes.txt b/test/dexdump/bytecodes.txt
index 1ed66e8..018e68f 100644
--- a/test/dexdump/bytecodes.txt
+++ b/test/dexdump/bytecodes.txt
@@ -55,6 +55,7 @@
       name          : 'value'
       type          : '()[Ljava/lang/String;'
       access        : 0x0401 (PUBLIC ABSTRACT)
+      method_idx    : 0
       code          : (none)
 
   source_file_idx   : 46 (SuppressLint.java)
@@ -91,6 +92,7 @@
       name          : 'value'
       type          : '()I'
       access        : 0x0401 (PUBLIC ABSTRACT)
+      method_idx    : 1
       code          : (none)
 
   source_file_idx   : 48 (TargetApi.java)
@@ -124,6 +126,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 4
       code          -
       registers     : 1
       ins           : 1
@@ -171,6 +174,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 5
       code          -
       registers     : 1
       ins           : 1
@@ -223,6 +227,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 6
       code          -
       registers     : 1
       ins           : 1
@@ -269,6 +274,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 7
       code          -
       registers     : 1
       ins           : 1
@@ -436,6 +442,7 @@
       name          : '<clinit>'
       type          : '()V'
       access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 8
       code          -
       registers     : 2
       ins           : 0
@@ -485,6 +492,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 9
       code          -
       registers     : 9
       ins           : 1
@@ -636,6 +644,7 @@
       name          : 'add'
       type          : '(Ljava/lang/Object;)Ljava/lang/Object;'
       access        : 0x20002 (PRIVATE DECLARED_SYNCHRONIZED)
+      method_idx    : 10
       code          -
       registers     : 13
       ins           : 2
@@ -803,6 +812,7 @@
       name          : 'adds'
       type          : '(Ljava/lang/Object;)Ljava/lang/Object;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 11
       code          -
       registers     : 9
       ins           : 1
@@ -896,6 +906,7 @@
       name          : 'copies'
       type          : '()V'
       access        : 0x0002 (PRIVATE)
+      method_idx    : 12
       code          -
       registers     : 19
       ins           : 1
@@ -1020,6 +1031,7 @@
       name          : 'doit'
       type          : '(I)V'
       access        : 0x0002 (PRIVATE)
+      method_idx    : 13
       code          -
       registers     : 3
       ins           : 2
@@ -1084,6 +1096,7 @@
       name          : 'geta'
       type          : '()Z'
       access        : 0x0002 (PRIVATE)
+      method_idx    : 14
       code          -
       registers     : 8
       ins           : 1
@@ -1149,6 +1162,7 @@
       name          : 'p'
       type          : '(I)V'
       access        : 0x0002 (PRIVATE)
+      method_idx    : 16
       code          -
       registers     : 6
       ins           : 2
@@ -1184,6 +1198,7 @@
       name          : 'params'
       type          : '(BCSIJFDLjava/lang/Object;[I)J'
       access        : 0x0002 (PRIVATE)
+      method_idx    : 17
       code          -
       registers     : 38
       ins           : 12
@@ -1406,6 +1421,7 @@
       name          : 'q'
       type          : '(II)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 18
       code          -
       registers     : 10
       ins           : 3
@@ -1483,6 +1499,7 @@
       name          : 'r'
       type          : '(II)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 19
       code          -
       registers     : 15
       ins           : 2
@@ -1597,6 +1614,7 @@
       name          : 's'
       type          : '(JJ)J'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 21
       code          -
       registers     : 32
       ins           : 4
@@ -1753,6 +1771,7 @@
       name          : 'seta'
       type          : '()V'
       access        : 0x0002 (PRIVATE)
+      method_idx    : 22
       code          -
       registers     : 6
       ins           : 1
@@ -1805,6 +1824,7 @@
       name          : 'onStart'
       type          : '()V'
       access        : 0x0004 (PROTECTED)
+      method_idx    : 15
       code          -
       registers     : 2
       ins           : 1
@@ -1827,6 +1847,7 @@
       name          : 'run'
       type          : '()V'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 20
       code          -
       registers     : 3
       ins           : 1
diff --git a/test/dexdump/checkers.txt b/test/dexdump/checkers.txt
index aee6e64..40ea881 100644
--- a/test/dexdump/checkers.txt
+++ b/test/dexdump/checkers.txt
@@ -52,6 +52,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 62
       code          -
       registers     : 1
       ins           : 1
@@ -68,6 +69,7 @@
       name          : 'a'
       type          : '(Z)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 63
       code          -
       registers     : 4
       ins           : 2
@@ -98,6 +100,7 @@
       name          : 'onConfigurationChanged'
       type          : '(Landroid/content/res/Configuration;)V'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 66
       code          -
       registers     : 2
       ins           : 2
@@ -114,6 +117,7 @@
       name          : 'onCreate'
       type          : '(Landroid/os/Bundle;)V'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 67
       code          -
       registers     : 8
       ins           : 2
@@ -158,6 +162,7 @@
       name          : 'onCreateOptionsMenu'
       type          : '(Landroid/view/Menu;)Z'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 68
       code          -
       registers     : 11
       ins           : 2
@@ -277,6 +282,7 @@
       name          : 'onKeyDown'
       type          : '(ILandroid/view/KeyEvent;)Z'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 69
       code          -
       registers     : 8
       ins           : 3
@@ -315,6 +321,7 @@
       name          : 'onOptionsItemSelected'
       type          : '(Landroid/view/MenuItem;)Z'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 70
       code          -
       registers     : 7
       ins           : 2
@@ -407,6 +414,7 @@
       name          : 'onPause'
       type          : '()V'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 71
       code          -
       registers     : 3
       ins           : 1
@@ -431,6 +439,7 @@
       name          : 'onStop'
       type          : '()V'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 72
       code          -
       registers     : 2
       ins           : 1
@@ -449,6 +458,7 @@
       name          : 'onTrackballEvent'
       type          : '(Landroid/view/MotionEvent;)Z'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 73
       code          -
       registers     : 6
       ins           : 2
@@ -677,6 +687,7 @@
       name          : '<init>'
       type          : '(Landroid/content/Context;Landroid/content/SharedPreferences;)V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 77
       code          -
       registers     : 12
       ins           : 3
@@ -1004,6 +1015,7 @@
       name          : 'a'
       type          : '(Landroid/content/SharedPreferences$Editor;Ljava/lang/String;[I)V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 82
       code          -
       registers     : 6
       ins           : 3
@@ -1034,6 +1046,7 @@
       name          : 'a'
       type          : '(Landroid/content/SharedPreferences;Ljava/lang/String;[I)V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 83
       code          -
       registers     : 7
       ins           : 3
@@ -1066,6 +1079,7 @@
       name          : 'a'
       type          : '(Landroid/graphics/Canvas;IIII)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 84
       code          -
       registers     : 13
       ins           : 6
@@ -1123,6 +1137,7 @@
       name          : 'a'
       type          : '(Landroid/graphics/Canvas;IIIILandroid/graphics/Paint;Landroid/graphics/Paint;Z)V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 85
       code          -
       registers     : 13
       ins           : 8
@@ -1187,6 +1202,7 @@
       name          : 'a'
       type          : '(Lcom/google/android/checkers/CheckersView;I)V'
       access        : 0x1008 (STATIC SYNTHETIC)
+      method_idx    : 86
       code          -
       registers     : 2
       ins           : 2
@@ -1203,6 +1219,7 @@
       name          : 'a'
       type          : '(Landroid/content/SharedPreferences;)Z'
       access        : 0x20012 (PRIVATE FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 88
       code          -
       registers     : 12
       ins           : 2
@@ -1393,6 +1410,7 @@
       name          : 'a'
       type          : '(Lcom/google/android/checkers/CheckersView;)Z'
       access        : 0x1008 (STATIC SYNTHETIC)
+      method_idx    : 89
       code          -
       registers     : 7
       ins           : 1
@@ -1416,6 +1434,7 @@
       name          : 'a'
       type          : '(ZIIII)Z'
       access        : 0x20012 (PRIVATE FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 91
       code          -
       registers     : 15
       ins           : 6
@@ -1802,6 +1821,7 @@
       name          : 'b'
       type          : '(FF)I'
       access        : 0x20012 (PRIVATE FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 92
       code          -
       registers     : 13
       ins           : 3
@@ -1887,6 +1907,7 @@
       name          : 'b'
       type          : '(I)V'
       access        : 0x20012 (PRIVATE FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 94
       code          -
       registers     : 3
       ins           : 2
@@ -1914,6 +1935,7 @@
       name          : 'b'
       type          : '(Landroid/graphics/Canvas;IIII)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 95
       code          -
       registers     : 16
       ins           : 6
@@ -1994,6 +2016,7 @@
       name          : 'c'
       type          : '(I)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 98
       code          -
       registers     : 10
       ins           : 2
@@ -2146,6 +2169,7 @@
       name          : 'd'
       type          : '()V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 100
       code          -
       registers     : 6
       ins           : 1
@@ -2197,6 +2221,7 @@
       name          : 'e'
       type          : '()Z'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 103
       code          -
       registers     : 3
       ins           : 1
@@ -2219,6 +2244,7 @@
       name          : 'a'
       type          : '()V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 78
       code          -
       registers     : 4
       ins           : 1
@@ -2268,6 +2294,7 @@
       name          : 'a'
       type          : '(FF)V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 79
       code          -
       registers     : 10
       ins           : 3
@@ -2357,6 +2384,7 @@
       name          : 'a'
       type          : '(IIII)V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 80
       code          -
       registers     : 11
       ins           : 5
@@ -2382,6 +2410,7 @@
       name          : 'a'
       type          : '(Landroid/content/SharedPreferences$Editor;)V'
       access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 81
       code          -
       registers     : 4
       ins           : 2
@@ -2474,6 +2503,7 @@
       name          : 'a'
       type          : '(I)Z'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 87
       code          -
       registers     : 8
       ins           : 2
@@ -2500,6 +2530,7 @@
       name          : 'a'
       type          : '(Z)Z'
       access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 90
       code          -
       registers     : 3
       ins           : 2
@@ -2531,6 +2562,7 @@
       name          : 'b'
       type          : '()V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 93
       code          -
       registers     : 7
       ins           : 1
@@ -2567,6 +2599,7 @@
       name          : 'b'
       type          : '(Z)Z'
       access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 96
       code          -
       registers     : 7
       ins           : 2
@@ -2627,6 +2660,7 @@
       name          : 'c'
       type          : '()I'
       access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 97
       code          -
       registers     : 2
       ins           : 1
@@ -2650,6 +2684,7 @@
       name          : 'c'
       type          : '(Z)Z'
       access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 99
       code          -
       registers     : 5
       ins           : 2
@@ -2687,6 +2722,7 @@
       name          : 'd'
       type          : '(Z)Z'
       access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 101
       code          -
       registers     : 3
       ins           : 2
@@ -2717,6 +2753,7 @@
       name          : 'draw'
       type          : '(Landroid/graphics/Canvas;)V'
       access        : 0x20001 (PUBLIC DECLARED_SYNCHRONIZED)
+      method_idx    : 102
       code          -
       registers     : 30
       ins           : 2
@@ -3424,6 +3461,7 @@
       name          : 'e'
       type          : '(Z)Z'
       access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 104
       code          -
       registers     : 3
       ins           : 2
@@ -3454,6 +3492,7 @@
       name          : 'onSizeChanged'
       type          : '(IIII)V'
       access        : 0x20004 (PROTECTED DECLARED_SYNCHRONIZED)
+      method_idx    : 107
       code          -
       registers     : 8
       ins           : 5
@@ -3501,6 +3540,7 @@
       name          : 'onTouchEvent'
       type          : '(Landroid/view/MotionEvent;)Z'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 108
       code          -
       registers     : 8
       ins           : 2
@@ -3539,6 +3579,7 @@
       name          : 'setLevel'
       type          : '(I)V'
       access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 112
       code          -
       registers     : 4
       ins           : 2
@@ -3764,6 +3805,7 @@
       name          : '<clinit>'
       type          : '()V'
       access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 113
       code          -
       registers     : 8
       ins           : 0
@@ -4363,6 +4405,7 @@
       name          : '<init>'
       type          : '(Lcom/google/android/checkers/CheckersView;)V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 114
       code          -
       registers     : 7
       ins           : 2
@@ -4427,6 +4470,7 @@
       name          : 'a'
       type          : '(II)I'
       access        : 0x001a (PRIVATE STATIC FINAL)
+      method_idx    : 115
       code          -
       registers     : 3
       ins           : 2
@@ -4451,6 +4495,7 @@
       name          : 'a'
       type          : '(IIIIIZ)I'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 116
       code          -
       registers     : 31
       ins           : 7
@@ -5152,6 +5197,7 @@
       name          : 'a'
       type          : '(IZ)I'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 117
       code          -
       registers     : 7
       ins           : 3
@@ -5199,6 +5245,7 @@
       name          : 'a'
       type          : '(Z)I'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 118
       code          -
       registers     : 7
       ins           : 2
@@ -5271,6 +5318,7 @@
       name          : 'a'
       type          : '(ZII)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 119
       code          -
       registers     : 7
       ins           : 3
@@ -5317,6 +5365,7 @@
       name          : 'a'
       type          : '(ZIIIZ)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 120
       code          -
       registers     : 9
       ins           : 5
@@ -5356,6 +5405,7 @@
       name          : 'a'
       type          : '(ZIIZ)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 121
       code          -
       registers     : 7
       ins           : 4
@@ -5389,6 +5439,7 @@
       name          : 'a'
       type          : '(IIII)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 125
       code          -
       registers     : 9
       ins           : 5
@@ -5440,6 +5491,7 @@
       name          : 'a'
       type          : '(IIIII)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 126
       code          -
       registers     : 10
       ins           : 6
@@ -5475,6 +5527,7 @@
       name          : 'a'
       type          : '(IIIIIIII)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 127
       code          -
       registers     : 18
       ins           : 9
@@ -5547,6 +5600,7 @@
       name          : 'a'
       type          : '(IZI)Z'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 129
       code          -
       registers     : 21
       ins           : 4
@@ -6017,6 +6071,7 @@
       name          : 'b'
       type          : '(ZIIIZ)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 130
       code          -
       registers     : 9
       ins           : 5
@@ -6057,6 +6112,7 @@
       name          : 'b'
       type          : '(ZIIZ)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 131
       code          -
       registers     : 8
       ins           : 4
@@ -6103,6 +6159,7 @@
       name          : 'b'
       type          : '()V'
       access        : 0x20012 (PRIVATE FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 132
       code          -
       registers     : 2
       ins           : 1
@@ -6136,6 +6193,7 @@
       name          : 'b'
       type          : '(I)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 133
       code          -
       registers     : 10
       ins           : 2
@@ -6345,6 +6403,7 @@
       name          : 'b'
       type          : '(IIIIIIII)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 134
       code          -
       registers     : 18
       ins           : 9
@@ -6417,6 +6476,7 @@
       name          : 'b'
       type          : '(IZI)Z'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 136
       code          -
       registers     : 15
       ins           : 4
@@ -6695,6 +6755,7 @@
       name          : 'c'
       type          : '(ZIIZ)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 137
       code          -
       registers     : 8
       ins           : 4
@@ -6740,6 +6801,7 @@
       name          : 'c'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 138
       code          -
       registers     : 2
       ins           : 0
@@ -6761,6 +6823,7 @@
       name          : 'c'
       type          : '(IIIIIIII)V'
       access        : 0x0012 (PRIVATE FINAL)
+      method_idx    : 139
       code          -
       registers     : 18
       ins           : 9
@@ -6889,6 +6952,7 @@
       name          : 'd'
       type          : '(ZIIZ)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 140
       code          -
       registers     : 8
       ins           : 4
@@ -6936,6 +7000,7 @@
       name          : 'a'
       type          : '(ZZ)I'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 122
       code          -
       registers     : 4
       ins           : 3
@@ -6955,6 +7020,7 @@
       name          : 'a'
       type          : '()V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 123
       code          -
       registers     : 4
       ins           : 1
@@ -6993,6 +7059,7 @@
       name          : 'a'
       type          : '(I)V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 124
       code          -
       registers     : 2
       ins           : 2
@@ -7009,6 +7076,7 @@
       name          : 'a'
       type          : '(IIIIZ)V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 128
       code          -
       registers     : 8
       ins           : 6
@@ -7043,6 +7111,7 @@
       name          : 'b'
       type          : '(ZZ)V'
       access        : 0x20011 (PUBLIC FINAL DECLARED_SYNCHRONIZED)
+      method_idx    : 135
       code          -
       registers     : 4
       ins           : 3
@@ -7070,6 +7139,7 @@
       name          : 'run'
       type          : '()V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 141
       code          -
       registers     : 24
       ins           : 1
@@ -7401,6 +7471,7 @@
       name          : '<init>'
       type          : '(Lcom/google/android/checkers/CheckersView;)V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 143
       code          -
       registers     : 2
       ins           : 2
@@ -7419,6 +7490,7 @@
       name          : 'onClick'
       type          : '(Landroid/content/DialogInterface;I)V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 144
       code          -
       registers     : 4
       ins           : 3
@@ -7468,6 +7540,7 @@
       name          : '<init>'
       type          : '(Lcom/google/android/checkers/CheckersView;)V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 145
       code          -
       registers     : 2
       ins           : 2
@@ -7486,6 +7559,7 @@
       name          : 'onClick'
       type          : '(Landroid/content/DialogInterface;I)V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 146
       code          -
       registers     : 3
       ins           : 3
@@ -7529,6 +7603,7 @@
       name          : '<init>'
       type          : '(Lcom/google/android/checkers/CheckersView;)V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 147
       code          -
       registers     : 2
       ins           : 2
@@ -7547,6 +7622,7 @@
       name          : 'onClick'
       type          : '(Landroid/content/DialogInterface;I)V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 148
       code          -
       registers     : 3
       ins           : 3
@@ -7590,6 +7666,7 @@
       name          : '<init>'
       type          : '(Lcom/google/android/checkers/CheckersView;)V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 149
       code          -
       registers     : 2
       ins           : 2
@@ -7608,6 +7685,7 @@
       name          : 'onClick'
       type          : '(Landroid/content/DialogInterface;I)V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 150
       code          -
       registers     : 5
       ins           : 3
@@ -7654,6 +7732,7 @@
       name          : '<init>'
       type          : '(Lcom/google/android/checkers/CheckersView;)V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 151
       code          -
       registers     : 2
       ins           : 2
@@ -7672,6 +7751,7 @@
       name          : 'onClick'
       type          : '(Landroid/content/DialogInterface;I)V'
       access        : 0x0011 (PUBLIC FINAL)
+      method_idx    : 152
       code          -
       registers     : 4
       ins           : 3
@@ -7788,6 +7868,7 @@
       name          : 'a'
       type          : '([B)Z'
       access        : 0x0008 (STATIC)
+      method_idx    : 153
       code          -
       registers     : 5
       ins           : 1
diff --git a/test/dexdump/const-method-handle.txt b/test/dexdump/const-method-handle.txt
index 6b33502..12020e1 100644
--- a/test/dexdump/const-method-handle.txt
+++ b/test/dexdump/const-method-handle.txt
@@ -52,6 +52,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 0
       code          -
       registers     : 1
       ins           : 1
@@ -70,6 +71,7 @@
       name          : 'main'
       type          : '([Ljava/lang/String;)V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 1
       code          -
       registers     : 6
       ins           : 1
@@ -129,6 +131,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 2
       code          -
       registers     : 1
       ins           : 1
@@ -147,6 +150,7 @@
       name          : 'displayMethodHandle'
       type          : '(Ljava/lang/invoke/MethodHandle;)V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 3
       code          -
       registers     : 4
       ins           : 1
@@ -188,6 +192,7 @@
       name          : 'displayMethodType'
       type          : '(Ljava/lang/invoke/MethodType;)V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 4
       code          -
       registers     : 4
       ins           : 1
@@ -217,6 +222,7 @@
       name          : 'main'
       type          : '([Ljava/lang/String;)V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 5
       code          -
       registers     : 2
       ins           : 1
@@ -238,6 +244,7 @@
       name          : 'test1'
       type          : '()Ljava/lang/invoke/MethodHandle;'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 6
       code          -
       registers     : 1
       ins           : 0
@@ -254,6 +261,7 @@
       name          : 'test2'
       type          : '()Ljava/lang/invoke/MethodType;'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 7
       code          -
       registers     : 1
       ins           : 0
diff --git a/test/dexdump/const-method-handle.xml b/test/dexdump/const-method-handle.xml
index f1cf9f8..ec64b1f 100644
--- a/test/dexdump/const-method-handle.xml
+++ b/test/dexdump/const-method-handle.xml
@@ -80,12 +80,5 @@
 >
 </method>
 </class>
-<method_handle index="0"
- type="invoke-instance"
- target_class="Ljava/lang/Object;"
- target_member="getClass"
- target_member_type="(Ljava/lang/Object;)Ljava/lang/Class;"
->
-</method_handle>
 </package>
 </api>
diff --git a/test/dexdump/invoke-custom.txt b/test/dexdump/invoke-custom.txt
index 1bfa053..598b2fa 100644
--- a/test/dexdump/invoke-custom.txt
+++ b/test/dexdump/invoke-custom.txt
@@ -53,6 +53,7 @@
       name          : '<init>'
       type          : '(Ljava/lang/invoke/MethodHandle;)V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 8
       code          -
       registers     : 2
       ins           : 2
@@ -97,6 +98,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 50
       code          -
       registers     : 1
       ins           : 1
@@ -115,6 +117,7 @@
       name          : 'assertEquals'
       type          : '(BB)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 51
       code          -
       registers     : 5
       ins           : 2
@@ -149,6 +152,7 @@
       name          : 'assertEquals'
       type          : '(CC)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 52
       code          -
       registers     : 5
       ins           : 2
@@ -183,6 +187,7 @@
       name          : 'assertEquals'
       type          : '(DD)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 53
       code          -
       registers     : 7
       ins           : 4
@@ -218,6 +223,7 @@
       name          : 'assertEquals'
       type          : '(FF)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 54
       code          -
       registers     : 5
       ins           : 2
@@ -253,6 +259,7 @@
       name          : 'assertEquals'
       type          : '(II)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 55
       code          -
       registers     : 5
       ins           : 2
@@ -287,6 +294,7 @@
       name          : 'assertEquals'
       type          : '(JJ)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 56
       code          -
       registers     : 7
       ins           : 4
@@ -322,6 +330,7 @@
       name          : 'assertEquals'
       type          : '(Ljava/lang/Object;Ljava/lang/Object;)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 57
       code          -
       registers     : 5
       ins           : 2
@@ -358,6 +367,7 @@
       name          : 'assertEquals'
       type          : '(SS)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 58
       code          -
       registers     : 5
       ins           : 2
@@ -392,6 +402,7 @@
       name          : 'assertNotEquals'
       type          : '(Ljava/lang/Object;Ljava/lang/Object;)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 59
       code          -
       registers     : 5
       ins           : 2
@@ -428,6 +439,7 @@
       name          : 'assertNotReached'
       type          : '()V'
       access        : 0x0008 (STATIC)
+      method_idx    : 60
       code          -
       registers     : 2
       ins           : 0
@@ -447,6 +459,7 @@
       name          : 'assertTrue'
       type          : '(Z)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 61
       code          -
       registers     : 4
       ins           : 1
@@ -477,6 +490,7 @@
       name          : 'fail'
       type          : '()V'
       access        : 0x0008 (STATIC)
+      method_idx    : 62
       code          -
       registers     : 2
       ins           : 0
@@ -532,6 +546,7 @@
       name          : '<init>'
       type          : '(I)V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 72
       code          -
       registers     : 2
       ins           : 2
@@ -581,6 +596,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 96
       code          -
       registers     : 1
       ins           : 1
@@ -600,6 +616,7 @@
       name          : 'initialValue'
       type          : '()Ljava/lang/Integer;'
       access        : 0x0004 (PROTECTED)
+      method_idx    : 97
       code          -
       registers     : 2
       ins           : 1
@@ -623,6 +640,7 @@
       name          : 'initialValue'
       type          : '()Ljava/lang/Object;'
       access        : 0x1044 (PROTECTED BRIDGE SYNTHETIC)
+      method_idx    : 98
       code          -
       registers     : 2
       ins           : 1
@@ -670,6 +688,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 169
       code          -
       registers     : 1
       ins           : 1
@@ -688,6 +707,7 @@
       name          : 'bsm'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite;'
       access        : 0x0008 (STATIC)
+      method_idx    : 170
       code          -
       registers     : 6
       ins           : 4
@@ -749,6 +769,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 0
       code          -
       registers     : 1
       ins           : 1
@@ -767,6 +788,7 @@
       name          : 'TestLinkerMethodMinimalArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 1
       code          -
       registers     : 4
       ins           : 0
@@ -839,6 +861,7 @@
       name          : 'TestLinkerMethodMultipleArgumentTypes'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 2
       code          -
       registers     : 2
       ins           : 0
@@ -867,6 +890,7 @@
       name          : 'TestUninitializedCallSite'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 3
       code          -
       registers     : 7
       ins           : 0
@@ -939,6 +963,7 @@
       name          : 'main'
       type          : '([Ljava/lang/String;)V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 7
       code          -
       registers     : 1
       ins           : 1
@@ -1042,6 +1067,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 9
       code          -
       registers     : 1
       ins           : 1
@@ -1060,6 +1086,7 @@
       name          : 'boxingArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 12
       code          -
       registers     : 2
       ins           : 0
@@ -1080,6 +1107,7 @@
       name          : 'bsm'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 14
       code          -
       registers     : 7
       ins           : 5
@@ -1150,6 +1178,7 @@
       name          : 'bsmDJ'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 15
       code          -
       registers     : 9
       ins           : 7
@@ -1197,6 +1226,7 @@
       name          : 'bsmDoubleLong'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 16
       code          -
       registers     : 7
       ins           : 5
@@ -1244,6 +1274,7 @@
       name          : 'bsmReturningInteger'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer;'
       access        : 0x0008 (STATIC)
+      method_idx    : 17
       code          -
       registers     : 5
       ins           : 3
@@ -1270,6 +1301,7 @@
       name          : 'bsmReturningObject'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object;'
       access        : 0x0008 (STATIC)
+      method_idx    : 18
       code          -
       registers     : 5
       ins           : 3
@@ -1295,6 +1327,7 @@
       name          : 'bsmReturningTestersConstantCallsite'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite;'
       access        : 0x0008 (STATIC)
+      method_idx    : 19
       code          -
       registers     : 5
       ins           : 3
@@ -1320,6 +1353,7 @@
       name          : 'bsmReturningVoid'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V'
       access        : 0x0008 (STATIC)
+      method_idx    : 20
       code          -
       registers     : 5
       ins           : 3
@@ -1343,6 +1377,7 @@
       name          : 'bsmZBCS'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 21
       code          -
       registers     : 8
       ins           : 7
@@ -1369,6 +1404,7 @@
       name          : 'extraArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 22
       code          -
       registers     : 2
       ins           : 0
@@ -1389,6 +1425,7 @@
       name          : 'happy'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 23
       code          -
       registers     : 2
       ins           : 0
@@ -1409,6 +1446,7 @@
       name          : 'integerReturnType'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 24
       code          -
       registers     : 0
       ins           : 0
@@ -1427,6 +1465,7 @@
       name          : 'invokeBoxingArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 25
       code          -
       registers     : 0
       ins           : 0
@@ -1445,6 +1484,7 @@
       name          : 'invokeExtraArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 26
       code          -
       registers     : 0
       ins           : 0
@@ -1463,6 +1503,7 @@
       name          : 'invokeHappy'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 27
       code          -
       registers     : 0
       ins           : 0
@@ -1481,6 +1522,7 @@
       name          : 'invokeIntegerReturnType'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 28
       code          -
       registers     : 0
       ins           : 0
@@ -1499,6 +1541,7 @@
       name          : 'invokeMissingParameterTypes'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 29
       code          -
       registers     : 0
       ins           : 0
@@ -1517,6 +1560,7 @@
       name          : 'invokeNarrowArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 30
       code          -
       registers     : 0
       ins           : 0
@@ -1535,6 +1579,7 @@
       name          : 'invokeObjectReturnType'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 31
       code          -
       registers     : 0
       ins           : 0
@@ -1553,6 +1598,7 @@
       name          : 'invokeViaCustomCallSiteClass'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 32
       code          -
       registers     : 0
       ins           : 0
@@ -1571,6 +1617,7 @@
       name          : 'invokeVoidReturnType'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 33
       code          -
       registers     : 0
       ins           : 0
@@ -1589,6 +1636,7 @@
       name          : 'invokeWideningArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 34
       code          -
       registers     : 0
       ins           : 0
@@ -1607,6 +1655,7 @@
       name          : 'invokeWideningBoxingArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 35
       code          -
       registers     : 0
       ins           : 0
@@ -1625,6 +1674,7 @@
       name          : 'invokeWrongArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 36
       code          -
       registers     : 0
       ins           : 0
@@ -1643,6 +1693,7 @@
       name          : 'invokeWrongArgumentsAgain'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 37
       code          -
       registers     : 0
       ins           : 0
@@ -1661,6 +1712,7 @@
       name          : 'invokeWrongParameterTypes'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 38
       code          -
       registers     : 0
       ins           : 0
@@ -1679,6 +1731,7 @@
       name          : 'missingParameterTypes'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 39
       code          -
       registers     : 2
       ins           : 0
@@ -1699,6 +1752,7 @@
       name          : 'narrowArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 40
       code          -
       registers     : 0
       ins           : 0
@@ -1717,6 +1771,7 @@
       name          : 'objectReturnType'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 41
       code          -
       registers     : 0
       ins           : 0
@@ -1735,6 +1790,7 @@
       name          : 'sayHello'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 42
       code          -
       registers     : 2
       ins           : 0
@@ -1755,6 +1811,7 @@
       name          : 'test'
       type          : '()V'
       access        : 0x0008 (STATIC)
+      method_idx    : 43
       code          -
       registers     : 3
       ins           : 0
@@ -2137,6 +2194,7 @@
       name          : 'voidReturnType'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 44
       code          -
       registers     : 0
       ins           : 0
@@ -2155,6 +2213,7 @@
       name          : 'wideningArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 45
       code          -
       registers     : 2
       ins           : 0
@@ -2175,6 +2234,7 @@
       name          : 'wideningBoxingArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 46
       code          -
       registers     : 2
       ins           : 0
@@ -2195,6 +2255,7 @@
       name          : 'wrongArguments'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 47
       code          -
       registers     : 2
       ins           : 0
@@ -2215,6 +2276,7 @@
       name          : 'wrongArgumentsAgain'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 48
       code          -
       registers     : 2
       ins           : 0
@@ -2235,6 +2297,7 @@
       name          : 'wrongParameterTypes'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 49
       code          -
       registers     : 2
       ins           : 0
@@ -2289,6 +2352,7 @@
       name          : '<clinit>'
       type          : '()V'
       access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 63
       code          -
       registers     : 1
       ins           : 0
@@ -2307,6 +2371,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 64
       code          -
       registers     : 1
       ins           : 1
@@ -2325,6 +2390,7 @@
       name          : 'bsm'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite;'
       access        : 0x0008 (STATIC)
+      method_idx    : 67
       code          -
       registers     : 11
       ins           : 6
@@ -2372,6 +2438,7 @@
       name          : 'targetA100000000'
       type          : '(ILjava/lang/String;Ljava/lang/Double;)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 68
       code          -
       registers     : 5
       ins           : 3
@@ -2408,6 +2475,7 @@
       name          : 'test'
       type          : '()V'
       access        : 0x0008 (STATIC)
+      method_idx    : 69
       code          -
       registers     : 2
       ins           : 0
@@ -2439,6 +2507,7 @@
       name          : 'testCallSites'
       type          : '()V'
       access        : 0x0008 (STATIC)
+      method_idx    : 70
       code          -
       registers     : 3
       ins           : 0
@@ -2482,6 +2551,7 @@
       name          : 'testDynamic'
       type          : '(ILjava/lang/String;Ljava/lang/Double;)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 71
       code          -
       registers     : 4
       ins           : 3
@@ -2564,6 +2634,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 73
       code          -
       registers     : 1
       ins           : 1
@@ -2582,6 +2653,7 @@
       name          : 'getInstanceField'
       type          : '(LTestInvocationKinds;)D'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 78
       code          -
       registers     : 3
       ins           : 1
@@ -2602,6 +2674,7 @@
       name          : 'getStaticField'
       type          : '()I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 80
       code          -
       registers     : 1
       ins           : 0
@@ -2621,6 +2694,7 @@
       name          : 'lookupConstructor'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 81
       code          -
       registers     : 7
       ins           : 3
@@ -2655,6 +2729,7 @@
       name          : 'lookupInstanceFieldGetter'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
       access        : 0x0008 (STATIC)
+      method_idx    : 82
       code          -
       registers     : 5
       ins           : 3
@@ -2687,6 +2762,7 @@
       name          : 'lookupInstanceFieldSetter'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
       access        : 0x0008 (STATIC)
+      method_idx    : 83
       code          -
       registers     : 5
       ins           : 3
@@ -2720,6 +2796,7 @@
       name          : 'lookupStaticFieldGetter'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
       access        : 0x0008 (STATIC)
+      method_idx    : 84
       code          -
       registers     : 5
       ins           : 3
@@ -2749,6 +2826,7 @@
       name          : 'lookupStaticFieldSetter'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
       access        : 0x0008 (STATIC)
+      method_idx    : 85
       code          -
       registers     : 5
       ins           : 3
@@ -2780,6 +2858,7 @@
       name          : 'lookupVirtual'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 86
       code          -
       registers     : 6
       ins           : 3
@@ -2812,6 +2891,7 @@
       name          : 'makeWidget'
       type          : '(I)LTestInvocationKinds$Widget;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 87
       code          -
       registers     : 2
       ins           : 1
@@ -2832,6 +2912,7 @@
       name          : 'maxIntegerValue'
       type          : '(LTestInvocationKinds;II)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 88
       code          -
       registers     : 4
       ins           : 3
@@ -2854,6 +2935,7 @@
       name          : 'setInstanceField'
       type          : '(LTestInvocationKinds;D)V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 89
       code          -
       registers     : 5
       ins           : 3
@@ -2877,6 +2959,7 @@
       name          : 'setStaticField'
       type          : '(I)V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 90
       code          -
       registers     : 1
       ins           : 1
@@ -2896,6 +2979,7 @@
       name          : 'test'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 91
       code          -
       registers     : 2
       ins           : 0
@@ -2926,6 +3010,7 @@
       name          : 'testConstructor'
       type          : '()V'
       access        : 0x0008 (STATIC)
+      method_idx    : 92
       code          -
       registers     : 3
       ins           : 0
@@ -2961,6 +3046,7 @@
       name          : 'testInstanceFieldAccessors'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 93
       code          -
       registers     : 5
       ins           : 0
@@ -3001,6 +3087,7 @@
       name          : 'testInvokeVirtual'
       type          : '()V'
       access        : 0x0008 (STATIC)
+      method_idx    : 94
       code          -
       registers     : 3
       ins           : 0
@@ -3034,6 +3121,7 @@
       name          : 'testStaticFieldAccessors'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 95
       code          -
       registers     : 2
       ins           : 0
@@ -3079,6 +3167,7 @@
       name          : 'getMaxIntegerValue'
       type          : '(II)I'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 79
       code          -
       registers     : 4
       ins           : 3
@@ -3165,6 +3254,7 @@
       name          : '<clinit>'
       type          : '()V'
       access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 99
       code          -
       registers     : 2
       ins           : 0
@@ -3203,6 +3293,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10002 (PRIVATE CONSTRUCTOR)
+      method_idx    : 100
       code          -
       registers     : 1
       ins           : 1
@@ -3221,6 +3312,7 @@
       name          : 'access$000'
       type          : '()Ljava/util/concurrent/atomic/AtomicInteger;'
       access        : 0x1008 (STATIC SYNTHETIC)
+      method_idx    : 101
       code          -
       registers     : 1
       ins           : 0
@@ -3238,6 +3330,7 @@
       name          : 'getThreadIndex'
       type          : '()I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 105
       code          -
       registers     : 1
       ins           : 0
@@ -3260,6 +3353,7 @@
       name          : 'linkerMethod'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 106
       code          -
       registers     : 8
       ins           : 3
@@ -3336,6 +3430,7 @@
       name          : 'notUsed'
       type          : '(I)I'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 107
       code          -
       registers     : 1
       ins           : 1
@@ -3353,6 +3448,7 @@
       name          : 'setCalled'
       type          : '(I)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 109
       code          -
       registers     : 3
       ins           : 1
@@ -3381,6 +3477,7 @@
       name          : 'test'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 110
       code          -
       registers     : 12
       ins           : 0
@@ -3563,6 +3660,7 @@
       name          : 'run'
       type          : '()V'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 108
       code          -
       registers     : 2
       ins           : 1
@@ -3642,6 +3740,7 @@
       name          : '<clinit>'
       type          : '()V'
       access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 111
       code          -
       registers     : 1
       ins           : 0
@@ -3660,6 +3759,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 112
       code          -
       registers     : 1
       ins           : 1
@@ -3678,6 +3778,7 @@
       name          : '_add'
       type          : '(II)I'
       access        : 0x0008 (STATIC)
+      method_idx    : 113
       code          -
       registers     : 4
       ins           : 2
@@ -3710,6 +3811,7 @@
       name          : 'add'
       type          : '(II)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 114
       code          -
       registers     : 3
       ins           : 2
@@ -3731,6 +3833,7 @@
       name          : 'linkerMethod'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 118
       code          -
       registers     : 7
       ins           : 3
@@ -3798,6 +3901,7 @@
       name          : 'test'
       type          : '(III)V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 119
       code          -
       registers     : 6
       ins           : 3
@@ -3891,6 +3995,7 @@
       name          : '<clinit>'
       type          : '()V'
       access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 120
       code          -
       registers     : 1
       ins           : 0
@@ -3909,6 +4014,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 121
       code          -
       registers     : 1
       ins           : 1
@@ -3927,6 +4033,7 @@
       name          : '_add'
       type          : '(II)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 123
       code          -
       registers     : 3
       ins           : 2
@@ -3946,6 +4053,7 @@
       name          : 'add'
       type          : '(II)I'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 124
       code          -
       registers     : 3
       ins           : 2
@@ -3967,6 +4075,7 @@
       name          : 'linkerMethod'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 131
       code          -
       registers     : 31
       ins           : 15
@@ -4060,6 +4169,7 @@
       name          : 'test'
       type          : '(II)V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 132
       code          -
       registers     : 4
       ins           : 2
@@ -4088,6 +4198,7 @@
       name          : 'GetBootstrapRunCount'
       type          : '()I'
       access        : 0x0001 (PUBLIC)
+      method_idx    : 122
       code          -
       registers     : 2
       ins           : 1
@@ -4135,6 +4246,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10000 (CONSTRUCTOR)
+      method_idx    : 133
       code          -
       registers     : 1
       ins           : 1
@@ -4153,6 +4265,7 @@
       name          : '_addf'
       type          : '(FF)F'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 134
       code          -
       registers     : 3
       ins           : 2
@@ -4172,6 +4285,7 @@
       name          : '_subf'
       type          : '(FF)F'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 135
       code          -
       registers     : 3
       ins           : 2
@@ -4191,6 +4305,7 @@
       name          : 'addf'
       type          : '(FF)F'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 136
       code          -
       registers     : 3
       ins           : 2
@@ -4212,6 +4327,7 @@
       name          : 'subf'
       type          : '(FF)F'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 139
       code          -
       registers     : 3
       ins           : 2
@@ -4233,6 +4349,7 @@
       name          : 'test'
       type          : '()V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 140
       code          -
       registers     : 4
       ins           : 0
@@ -4342,6 +4459,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 141
       code          -
       registers     : 1
       ins           : 1
@@ -4360,6 +4478,7 @@
       name          : 'bsmWithBoxedArray'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 143
       code          -
       registers     : 7
       ins           : 4
@@ -4401,6 +4520,7 @@
       name          : 'bsmWithClassAndFloatArray'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite;'
       access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 144
       code          -
       registers     : 8
       ins           : 5
@@ -4446,6 +4566,7 @@
       name          : 'bsmWithClassArray'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite;'
       access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 145
       code          -
       registers     : 7
       ins           : 4
@@ -4487,6 +4608,7 @@
       name          : 'bsmWithDoubleArray'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite;'
       access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 146
       code          -
       registers     : 7
       ins           : 4
@@ -4528,6 +4650,7 @@
       name          : 'bsmWithFloatAndLongArray'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite;'
       access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 147
       code          -
       registers     : 9
       ins           : 5
@@ -4576,6 +4699,7 @@
       name          : 'bsmWithIntAndStringArray'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite;'
       access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 148
       code          -
       registers     : 9
       ins           : 5
@@ -4624,6 +4748,7 @@
       name          : 'bsmWithLongAndIntArray'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite;'
       access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 149
       code          -
       registers     : 10
       ins           : 6
@@ -4670,6 +4795,7 @@
       name          : 'bsmWithStringArray'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite;'
       access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 150
       code          -
       registers     : 7
       ins           : 4
@@ -4711,6 +4837,7 @@
       name          : 'bsmWithWiderArray'
       type          : '(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite;'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 151
       code          -
       registers     : 7
       ins           : 4
@@ -4752,6 +4879,7 @@
       name          : 'methodA'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 152
       code          -
       registers     : 2
       ins           : 0
@@ -4772,6 +4900,7 @@
       name          : 'methodB'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 153
       code          -
       registers     : 2
       ins           : 0
@@ -4792,6 +4921,7 @@
       name          : 'methodC'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 154
       code          -
       registers     : 2
       ins           : 0
@@ -4812,6 +4942,7 @@
       name          : 'methodD'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 155
       code          -
       registers     : 2
       ins           : 0
@@ -4832,6 +4963,7 @@
       name          : 'methodE'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 156
       code          -
       registers     : 2
       ins           : 0
@@ -4852,6 +4984,7 @@
       name          : 'methodF'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 157
       code          -
       registers     : 2
       ins           : 0
@@ -4872,6 +5005,7 @@
       name          : 'methodG'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 158
       code          -
       registers     : 2
       ins           : 0
@@ -4892,6 +5026,7 @@
       name          : 'methodH'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 159
       code          -
       registers     : 2
       ins           : 0
@@ -4912,6 +5047,7 @@
       name          : 'methodI'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 160
       code          -
       registers     : 2
       ins           : 0
@@ -4932,6 +5068,7 @@
       name          : 'methodJ'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 161
       code          -
       registers     : 2
       ins           : 0
@@ -4952,6 +5089,7 @@
       name          : 'methodK'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 162
       code          -
       registers     : 2
       ins           : 0
@@ -4972,6 +5110,7 @@
       name          : 'methodO'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 163
       code          -
       registers     : 0
       ins           : 0
@@ -4990,6 +5129,7 @@
       name          : 'methodP'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 164
       code          -
       registers     : 0
       ins           : 0
@@ -5008,6 +5148,7 @@
       name          : 'methodQ'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 165
       code          -
       registers     : 0
       ins           : 0
@@ -5026,6 +5167,7 @@
       name          : 'methodR'
       type          : '()V'
       access        : 0x000a (PRIVATE STATIC)
+      method_idx    : 166
       code          -
       registers     : 0
       ins           : 0
@@ -5044,6 +5186,7 @@
       name          : 'printBsmArgs'
       type          : '(Ljava/lang/String;[Ljava/lang/Object;)V'
       access        : 0x008a (PRIVATE STATIC VARARGS)
+      method_idx    : 167
       code          -
       registers     : 6
       ins           : 2
@@ -5164,6 +5307,7 @@
       name          : 'test'
       type          : '()V'
       access        : 0x0008 (STATIC)
+      method_idx    : 168
       code          -
       registers     : 3
       ins           : 0
diff --git a/test/dexdump/invoke-custom.xml b/test/dexdump/invoke-custom.xml
index 6d49ce1..963d623 100644
--- a/test/dexdump/invoke-custom.xml
+++ b/test/dexdump/invoke-custom.xml
@@ -176,520 +176,5 @@
 >
 </constructor>
 </class>
-<method_handle index="0"
- type="invoke-static"
- target_class="LTestBadBootstrapArguments;"
- target_member="bsm"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ID)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="1"
- type="invoke-static"
- target_class="LTestBadBootstrapArguments;"
- target_member="bsm"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ILjava/lang/String;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="2"
- type="invoke-static"
- target_class="LTestBadBootstrapArguments;"
- target_member="bsmDJ"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;DJ)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="3"
- type="invoke-static"
- target_class="LTestBadBootstrapArguments;"
- target_member="bsmDoubleLong"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Double;Ljava/lang/Long;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="4"
- type="invoke-static"
- target_class="LTestBadBootstrapArguments;"
- target_member="bsmReturningInteger"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Integer;"
->
-</method_handle>
-<method_handle index="5"
- type="invoke-static"
- target_class="LTestBadBootstrapArguments;"
- target_member="bsmReturningObject"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object;"
->
-</method_handle>
-<method_handle index="6"
- type="invoke-static"
- target_class="LTestBadBootstrapArguments;"
- target_member="bsmReturningTestersConstantCallsite"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)LTestBadBootstrapArguments$TestersConstantCallSite;"
->
-</method_handle>
-<method_handle index="7"
- type="invoke-static"
- target_class="LTestBadBootstrapArguments;"
- target_member="bsmReturningVoid"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)V"
->
-</method_handle>
-<method_handle index="8"
- type="invoke-static"
- target_class="LTestBadBootstrapArguments;"
- target_member="bsmZBCS"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;ZBCS)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="9"
- type="invoke-static"
- target_class="LTestDynamicBootstrapArguments;"
- target_member="bsm"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;J)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="10"
- type="invoke-static"
- target_class="LTestInvocationKinds;"
- target_member="lookupConstructor"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="11"
- type="invoke-static"
- target_class="LTestInvocationKinds;"
- target_member="lookupInstanceFieldGetter"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="12"
- type="invoke-static"
- target_class="LTestInvocationKinds;"
- target_member="lookupInstanceFieldSetter"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="13"
- type="invoke-static"
- target_class="LTestInvocationKinds;"
- target_member="lookupStaticFieldGetter"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="14"
- type="invoke-static"
- target_class="LTestInvocationKinds;"
- target_member="lookupStaticFieldSetter"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="15"
- type="invoke-static"
- target_class="LTestInvocationKinds;"
- target_member="lookupVirtual"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="16"
- type="invoke-static"
- target_class="LTestInvokeCustomWithConcurrentThreads;"
- target_member="linkerMethod"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="17"
- type="invoke-static"
- target_class="LTestLinkerMethodMinimalArguments;"
- target_member="linkerMethod"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="18"
- type="invoke-static"
- target_class="LTestLinkerMethodMultipleArgumentTypes;"
- target_member="linkerMethod"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;IIIIIFDLjava/lang/String;Ljava/lang/Class;J)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="19"
- type="invoke-static"
- target_class="LTestVariableArityLinkerMethod;"
- target_member="bsmWithBoxedArray"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Integer;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="20"
- type="invoke-static"
- target_class="LTestVariableArityLinkerMethod;"
- target_member="bsmWithClassAndFloatArray"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;[F)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="21"
- type="invoke-static"
- target_class="LTestVariableArityLinkerMethod;"
- target_member="bsmWithClassArray"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Class;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="22"
- type="invoke-static"
- target_class="LTestVariableArityLinkerMethod;"
- target_member="bsmWithDoubleArray"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[D)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="23"
- type="invoke-static"
- target_class="LTestVariableArityLinkerMethod;"
- target_member="bsmWithFloatAndLongArray"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;F[J)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="24"
- type="invoke-static"
- target_class="LTestVariableArityLinkerMethod;"
- target_member="bsmWithIntAndStringArray"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I[Ljava/lang/String;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="25"
- type="invoke-static"
- target_class="LTestVariableArityLinkerMethod;"
- target_member="bsmWithLongAndIntArray"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J[I)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="26"
- type="invoke-static"
- target_class="LTestVariableArityLinkerMethod;"
- target_member="bsmWithStringArray"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/String;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="27"
- type="invoke-static"
- target_class="LTestVariableArityLinkerMethod;"
- target_member="bsmWithWiderArray"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[J)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<method_handle index="28"
- type="invoke-static"
- target_class="LUnrelatedBSM;"
- target_member="bsm"
- target_member_type="(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/CallSite;"
->
-</method_handle>
-<call_site index="0" offset="29649">
-<link_argument index="0" type="MethodHandle" value="1"/>
-<link_argument index="1" type="String" values="happy"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="-1"/>
-<link_argument index="4" type="String" value="very"/>
-</call_site>
-<call_site index="1" offset="29662">
-<link_argument index="0" type="MethodHandle" value="0"/>
-<link_argument index="1" type="String" values="wrongParameterTypes"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="-1"/>
-<link_argument index="4" type="String" value="very"/>
-</call_site>
-<call_site index="2" offset="29675">
-<link_argument index="0" type="MethodHandle" value="0"/>
-<link_argument index="1" type="String" values="missingParameterTypes"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-</call_site>
-<call_site index="3" offset="29683">
-<link_argument index="0" type="MethodHandle" value="1"/>
-<link_argument index="1" type="String" values="extraArguments"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="1"/>
-<link_argument index="4" type="String" value="2"/>
-<link_argument index="5" type="int" value="3"/>
-</call_site>
-<call_site index="4" offset="29697">
-<link_argument index="0" type="MethodHandle" value="1"/>
-<link_argument index="1" type="String" values="wrongArguments"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="String" value="1"/>
-<link_argument index="4" type="double" value="3.14159"/>
-</call_site>
-<call_site index="5" offset="29697">
-<link_argument index="0" type="MethodHandle" value="1"/>
-<link_argument index="1" type="String" values="wrongArguments"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="String" value="1"/>
-<link_argument index="4" type="double" value="3.14159"/>
-</call_site>
-<call_site index="6" offset="29716">
-<link_argument index="0" type="MethodHandle" value="1"/>
-<link_argument index="1" type="String" values="wrongArgumentsAgain"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="double" value="3.14159"/>
-<link_argument index="4" type="String" value="pie"/>
-</call_site>
-<call_site index="7" offset="29736">
-<link_argument index="0" type="MethodHandle" value="8"/>
-<link_argument index="1" type="String" values="narrowArguments"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="1"/>
-<link_argument index="4" type="int" value="127"/>
-<link_argument index="5" type="int" value="65"/>
-<link_argument index="6" type="int" value="-32768"/>
-</call_site>
-<call_site index="8" offset="29753">
-<link_argument index="0" type="MethodHandle" value="2"/>
-<link_argument index="1" type="String" values="wideningArguments"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="double" value="1.79769e+308"/>
-<link_argument index="4" type="int" value="2147483647"/>
-</call_site>
-<call_site index="9" offset="29775">
-<link_argument index="0" type="MethodHandle" value="3"/>
-<link_argument index="1" type="String" values="boxingArguments"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="double" value="1.79769e+308"/>
-<link_argument index="4" type="long" value="9223372036854775807"/>
-</call_site>
-<call_site index="10" offset="29800">
-<link_argument index="0" type="MethodHandle" value="3"/>
-<link_argument index="1" type="String" values="wideningBoxingArguments"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="float" value="3.40282e+38"/>
-<link_argument index="4" type="long" value="2147483647"/>
-</call_site>
-<call_site index="11" offset="29818">
-<link_argument index="0" type="MethodHandle" value="7"/>
-<link_argument index="1" type="String" values="voidReturnType"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-</call_site>
-<call_site index="12" offset="29826">
-<link_argument index="0" type="MethodHandle" value="5"/>
-<link_argument index="1" type="String" values="ObjectReturnType"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-</call_site>
-<call_site index="13" offset="29833">
-<link_argument index="0" type="MethodHandle" value="4"/>
-<link_argument index="1" type="String" values="integerReturnType"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-</call_site>
-<call_site index="14" offset="29841">
-<link_argument index="0" type="MethodHandle" value="6"/>
-<link_argument index="1" type="String" values="sayHello"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-</call_site>
-<call_site index="15" offset="29849">
-<link_argument index="0" type="MethodHandle" value="9"/>
-<link_argument index="1" type="String" values="target"/>
-<link_argument index="2" type="MethodType" value="(ILjava/lang/String;Ljava/lang/Double;)I"/>
-<link_argument index="3" type="String" value="A"/>
-<link_argument index="4" type="long" value="100000000"/>
-</call_site>
-<call_site index="16" offset="29849">
-<link_argument index="0" type="MethodHandle" value="9"/>
-<link_argument index="1" type="String" values="target"/>
-<link_argument index="2" type="MethodType" value="(ILjava/lang/String;Ljava/lang/Double;)I"/>
-<link_argument index="3" type="String" value="A"/>
-<link_argument index="4" type="long" value="100000000"/>
-</call_site>
-<call_site index="17" offset="29849">
-<link_argument index="0" type="MethodHandle" value="9"/>
-<link_argument index="1" type="String" values="target"/>
-<link_argument index="2" type="MethodType" value="(ILjava/lang/String;Ljava/lang/Double;)I"/>
-<link_argument index="3" type="String" value="A"/>
-<link_argument index="4" type="long" value="100000000"/>
-</call_site>
-<call_site index="18" offset="29864">
-<link_argument index="0" type="MethodHandle" value="10"/>
-<link_argument index="1" type="String" values="unused"/>
-<link_argument index="2" type="MethodType" value="(I)LTestInvocationKinds$Widget;"/>
-</call_site>
-<call_site index="19" offset="29872">
-<link_argument index="0" type="MethodHandle" value="12"/>
-<link_argument index="1" type="String" values="instance_field"/>
-<link_argument index="2" type="MethodType" value="(LTestInvocationKinds;D)V"/>
-</call_site>
-<call_site index="20" offset="29880">
-<link_argument index="0" type="MethodHandle" value="11"/>
-<link_argument index="1" type="String" values="instance_field"/>
-<link_argument index="2" type="MethodType" value="(LTestInvocationKinds;)D"/>
-</call_site>
-<call_site index="21" offset="29888">
-<link_argument index="0" type="MethodHandle" value="15"/>
-<link_argument index="1" type="String" values="getMaxIntegerValue"/>
-<link_argument index="2" type="MethodType" value="(LTestInvocationKinds;II)I"/>
-</call_site>
-<call_site index="22" offset="29896">
-<link_argument index="0" type="MethodHandle" value="14"/>
-<link_argument index="1" type="String" values="static_field"/>
-<link_argument index="2" type="MethodType" value="(I)V"/>
-</call_site>
-<call_site index="23" offset="29896">
-<link_argument index="0" type="MethodHandle" value="14"/>
-<link_argument index="1" type="String" values="static_field"/>
-<link_argument index="2" type="MethodType" value="(I)V"/>
-</call_site>
-<call_site index="24" offset="29904">
-<link_argument index="0" type="MethodHandle" value="13"/>
-<link_argument index="1" type="String" values="static_field"/>
-<link_argument index="2" type="MethodType" value="()I"/>
-</call_site>
-<call_site index="25" offset="29904">
-<link_argument index="0" type="MethodHandle" value="13"/>
-<link_argument index="1" type="String" values="static_field"/>
-<link_argument index="2" type="MethodType" value="()I"/>
-</call_site>
-<call_site index="26" offset="29912">
-<link_argument index="0" type="MethodHandle" value="16"/>
-<link_argument index="1" type="String" values="setCalled"/>
-<link_argument index="2" type="MethodType" value="(I)I"/>
-</call_site>
-<call_site index="27" offset="29920">
-<link_argument index="0" type="MethodHandle" value="17"/>
-<link_argument index="1" type="String" values="_add"/>
-<link_argument index="2" type="MethodType" value="(II)I"/>
-</call_site>
-<call_site index="28" offset="29927">
-<link_argument index="0" type="MethodHandle" value="18"/>
-<link_argument index="1" type="String" values="_add"/>
-<link_argument index="2" type="MethodType" value="(II)I"/>
-<link_argument index="3" type="int" value="-1"/>
-<link_argument index="4" type="int" value="1"/>
-<link_argument index="5" type="int" value="97"/>
-<link_argument index="6" type="int" value="1024"/>
-<link_argument index="7" type="int" value="1"/>
-<link_argument index="8" type="float" value="11.1"/>
-<link_argument index="9" type="double" value="2.2"/>
-<link_argument index="10" type="String" value="Hello"/>
-<link_argument index="11" type="Class" value="LTestLinkerMethodMultipleArgumentTypes;"/>
-<link_argument index="12" type="long" value="123456789"/>
-</call_site>
-<call_site index="29" offset="29968">
-<link_argument index="0" type="MethodHandle" value="28"/>
-<link_argument index="1" type="String" values="_addf"/>
-<link_argument index="2" type="MethodType" value="(FF)F"/>
-<link_argument index="3" type="Class" value="LTestLinkerUnrelatedBSM;"/>
-</call_site>
-<call_site index="30" offset="29977">
-<link_argument index="0" type="MethodHandle" value="28"/>
-<link_argument index="1" type="String" values="_subf"/>
-<link_argument index="2" type="MethodType" value="(FF)F"/>
-<link_argument index="3" type="Class" value="LTestLinkerUnrelatedBSM;"/>
-</call_site>
-<call_site index="31" offset="29986">
-<link_argument index="0" type="MethodHandle" value="26"/>
-<link_argument index="1" type="String" values="methodA"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="String" value="Aachen"/>
-<link_argument index="4" type="String" value="Aalborg"/>
-<link_argument index="5" type="String" value="Aalto"/>
-</call_site>
-<call_site index="32" offset="30000">
-<link_argument index="0" type="MethodHandle" value="26"/>
-<link_argument index="1" type="String" values="methodB"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="String" value="barium"/>
-</call_site>
-<call_site index="33" offset="30010">
-<link_argument index="0" type="MethodHandle" value="26"/>
-<link_argument index="1" type="String" values="methodC"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-</call_site>
-<call_site index="34" offset="30018">
-<link_argument index="0" type="MethodHandle" value="24"/>
-<link_argument index="1" type="String" values="methodD"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="101"/>
-<link_argument index="4" type="String" value="zoo"/>
-<link_argument index="5" type="String" value="zoogene"/>
-<link_argument index="6" type="String" value="zoogenic"/>
-</call_site>
-<call_site index="35" offset="30037">
-<link_argument index="0" type="MethodHandle" value="24"/>
-<link_argument index="1" type="String" values="methodE"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="102"/>
-<link_argument index="4" type="String" value="zonic"/>
-</call_site>
-<call_site index="36" offset="30050">
-<link_argument index="0" type="MethodHandle" value="24"/>
-<link_argument index="1" type="String" values="methodF"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="103"/>
-</call_site>
-<call_site index="37" offset="30060">
-<link_argument index="0" type="MethodHandle" value="25"/>
-<link_argument index="1" type="String" values="methodG"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="long" value="81985529216486895"/>
-<link_argument index="4" type="int" value="1"/>
-<link_argument index="5" type="int" value="-1"/>
-<link_argument index="6" type="int" value="2"/>
-<link_argument index="7" type="int" value="-2"/>
-</call_site>
-<call_site index="38" offset="30085">
-<link_argument index="0" type="MethodHandle" value="23"/>
-<link_argument index="1" type="String" values="methodH"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="float" value="-2.71828"/>
-<link_argument index="4" type="long" value="999999999999"/>
-<link_argument index="5" type="long" value="-8888888888888"/>
-</call_site>
-<call_site index="39" offset="30112">
-<link_argument index="0" type="MethodHandle" value="20"/>
-<link_argument index="1" type="String" values="methodI"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="Class" value="Ljava/lang/Throwable;"/>
-<link_argument index="4" type="float" value="3.40282e+38"/>
-<link_argument index="5" type="float" value="1.4013e-45"/>
-<link_argument index="6" type="float" value="3.14159"/>
-<link_argument index="7" type="float" value="-3.14159"/>
-</call_site>
-<call_site index="40" offset="30142">
-<link_argument index="0" type="MethodHandle" value="22"/>
-<link_argument index="1" type="String" values="methodJ"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="double" value="1.79769e+308"/>
-<link_argument index="4" type="double" value="4.94066e-324"/>
-<link_argument index="5" type="double" value="2.71828"/>
-<link_argument index="6" type="double" value="-3.14159"/>
-</call_site>
-<call_site index="41" offset="30186">
-<link_argument index="0" type="MethodHandle" value="21"/>
-<link_argument index="1" type="String" values="methodK"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="Class" value="Ljava/lang/Integer;"/>
-<link_argument index="4" type="Class" value="Ljava/lang/invoke/MethodHandles;"/>
-<link_argument index="5" type="Class" value="Ljava/util/Arrays;"/>
-</call_site>
-<call_site index="42" offset="30200">
-<link_argument index="0" type="MethodHandle" value="24"/>
-<link_argument index="1" type="String" values="methodO"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="103"/>
-<link_argument index="4" type="int" value="104"/>
-</call_site>
-<call_site index="43" offset="30212">
-<link_argument index="0" type="MethodHandle" value="24"/>
-<link_argument index="1" type="String" values="methodP"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="103"/>
-<link_argument index="4" type="String" value="A"/>
-<link_argument index="5" type="String" value="B"/>
-<link_argument index="6" type="int" value="42"/>
-</call_site>
-<call_site index="44" offset="30228">
-<link_argument index="0" type="MethodHandle" value="27"/>
-<link_argument index="1" type="String" values="methodQ"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="103"/>
-<link_argument index="4" type="int" value="42"/>
-</call_site>
-<call_site index="45" offset="30240">
-<link_argument index="0" type="MethodHandle" value="19"/>
-<link_argument index="1" type="String" values="methodR"/>
-<link_argument index="2" type="MethodType" value="()V"/>
-<link_argument index="3" type="int" value="1030"/>
-<link_argument index="4" type="int" value="420"/>
-</call_site>
 </package>
 </api>
diff --git a/test/dexdump/invoke-polymorphic.txt b/test/dexdump/invoke-polymorphic.txt
index 16e708c..e279d01 100644
--- a/test/dexdump/invoke-polymorphic.txt
+++ b/test/dexdump/invoke-polymorphic.txt
@@ -52,6 +52,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 0
       code          -
       registers     : 1
       ins           : 1
@@ -70,6 +71,7 @@
       name          : 'main'
       type          : '([Ljava/lang/String;)V'
       access        : 0x0009 (PUBLIC STATIC)
+      method_idx    : 1
       code          -
       registers     : 10
       ins           : 1
diff --git a/test/dexdump/run-all-tests b/test/dexdump/run-all-tests
index 2fe4a02..a268c8b 100755
--- a/test/dexdump/run-all-tests
+++ b/test/dexdump/run-all-tests
@@ -46,6 +46,8 @@
 SUFFIX_COMMAND_MAP[xml]="${DEXDUMP} -e -l xml"
 SUFFIX_COMMAND_MAP[lst]="${DEXLIST}"
 
+ALL_DEX_FILES_JAR=all-dex-files.jar
+
 # Parse command-line options
 UPDATE="no"
 USAGE="no"
@@ -83,25 +85,48 @@
       fi
     done
   done
+
+  # Create a .jar file containing all dex files, renamed as expected by the runtime.
+  count=0
+  for i in *.dex; do
+    if [ ${count} = 0 ] ; then
+      dex_file=classes.dex
+      flags="-cf"
+    else
+      dex_file=classes${count}.dex
+      flags="-uf"
+    fi
+    cp $i ${tmpdir}/${dex_file}
+    jar ${flags} ${ALL_DEX_FILES_JAR} -C ${tmpdir} ${dex_file}
+    ((count += 1))
+    rm ${tmpdir}/${dex_file}
+  done
+
+  prefix=$(basename ${ALL_DEX_FILES_JAR} .jar)
+  for suffix in ${!SUFFIX_COMMAND_MAP[@]}; do
+    new_output=${prefix}.${suffix}
+    ${SUFFIX_COMMAND_MAP[${suffix}]} ${ALL_DEX_FILES_JAR} > ${new_output}
+  done
+
   exit 0
 fi
 
 # Run the tests.
 passed=0
 failed=0
-for dex in *.dex; do
-  echo ${dex}
+for input in *.dex *.jar; do
+  echo ${input}
   for suffix in ${!SUFFIX_COMMAND_MAP[@]}; do
-    expected_output=${dex%%.*}.${suffix}
+    expected_output=${input%%.*}.${suffix}
     actual_output=${tmpdir}/${expected_output}
-    cmd="${SUFFIX_COMMAND_MAP[${suffix}]} ${dex}"
+    cmd="${SUFFIX_COMMAND_MAP[${suffix}]} ${input}"
     ${cmd} > ${actual_output}
     cmp ${expected_output} ${actual_output}
     if [ "$?" = "0" ]; then
-        ((passed += 1))
+      ((passed += 1))
     else
-        ((failed += 1))
-        echo failed: ${cmd}
+      ((failed += 1))
+      echo failed: ${cmd}
     fi
   done
 done
diff --git a/test/dexdump/staticfields.txt b/test/dexdump/staticfields.txt
index f6d8f19..9afed2f 100644
--- a/test/dexdump/staticfields.txt
+++ b/test/dexdump/staticfields.txt
@@ -107,6 +107,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 0
       code          -
       registers     : 1
       ins           : 1
diff --git a/test/dexdump/staticfields.xml b/test/dexdump/staticfields.xml
index 9082f0e..7a1d475 100644
--- a/test/dexdump/staticfields.xml
+++ b/test/dexdump/staticfields.xml
@@ -86,7 +86,7 @@
  static="true"
  final="true"
  visibility="public"
- value="abc \&gt;&lt;&quot;'&amp;&#x9;&#xD;&#xA;"
+ value="abc \\&gt;&lt;&quot;'&amp;\u0009\u000d\u000a"
 >
 </field>
 <field name="test08_public_static_final_object_null"
diff --git a/test/dexdump/values.txt b/test/dexdump/values.txt
index 7f831b1..c40fa64 100644
--- a/test/dexdump/values.txt
+++ b/test/dexdump/values.txt
@@ -318,6 +318,7 @@
       name          : '<clinit>'
       type          : '()V'
       access        : 0x10008 (STATIC CONSTRUCTOR)
+      method_idx    : 0
       code          -
       registers     : 1
       ins           : 0
@@ -336,6 +337,7 @@
       name          : '<init>'
       type          : '()V'
       access        : 0x10001 (PUBLIC CONSTRUCTOR)
+      method_idx    : 1
       code          -
       registers     : 1
       ins           : 1
diff --git a/test/dexdump/values.xml b/test/dexdump/values.xml
index d6ba48d..a0140e3 100644
--- a/test/dexdump/values.xml
+++ b/test/dexdump/values.xml
@@ -526,7 +526,7 @@
  static="true"
  final="true"
  visibility="public"
- value="&lt;&amp;&quot;JOHO&quot;&amp;&gt;&#xA;"
+ value="&lt;&amp;&quot;JOHO&quot;&amp;&gt;\u000a"
 >
 </field>
 <field name="mZ0"
diff --git a/test/etc/default-build b/test/etc/default-build
index 1122c01..7f9c818 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -92,6 +92,12 @@
   HAS_SRC_EX=false
 fi
 
+if [ -d src-ex2 ]; then
+  HAS_SRC_EX2=true
+else
+  HAS_SRC_EX2=false
+fi
+
 if [ -d src-dex2oat-unresolved ]; then
   HAS_SRC_DEX2OAT_UNRESOLVED=true
 else
@@ -153,6 +159,9 @@
   elif [ "x$1" = "x--no-src-ex" ]; then
     HAS_SRC_EX=false
     shift
+  elif [ "x$1" = "x--no-src-ex2" ]; then
+    HAS_SRC_EX2=false
+    shift
   elif [ "x$1" = "x--no-smali" ]; then
     HAS_SMALI=false
     shift
@@ -370,19 +379,31 @@
     make_dex classes
   fi
 else
+  if [ "${HAS_SRC}" = "true" -a "${HAS_SRC_MULTIDEX}" = "true" ]; then
+    # To allow circular references, compile src/ and src-multidex/ together
+    # and pass the output as class path argument. Replacement sources
+    # in src-art/ can replace symbols used by src-multidex but everything
+    # needed to compile src-multidex should be present in src/.
+    mkdir classes-tmp-all
+    javac_with_bootclasspath -implicit:none -d classes-tmp-all \
+        `find src -name '*.java'` \
+        `find src-multidex -name '*.java'`
+    src_tmp_all="-cp classes-tmp-all"
+  fi
+
   if [ "${HAS_SRC}" = "true" ]; then
     mkdir -p classes
-    javac_with_bootclasspath -implicit:none -classpath src-multidex -d classes `find src -name '*.java'`
+    javac_with_bootclasspath -implicit:none $src_tmp_all -d classes `find src -name '*.java'`
   fi
 
   if [ "${HAS_SRC_ART}" = "true" ]; then
     mkdir -p classes
-    javac_with_bootclasspath -implicit:none -classpath src-multidex -d classes `find src-art -name '*.java'`
+    javac_with_bootclasspath -implicit:none $src_tmp_all -d classes `find src-art -name '*.java'`
   fi
 
   if [ "${HAS_SRC_MULTIDEX}" = "true" ]; then
     mkdir classes2
-    javac_with_bootclasspath -implicit:none -classpath src -d classes2 `find src-multidex -name '*.java'`
+    javac_with_bootclasspath -implicit:none $src_tmp_all -d classes2 `find src-multidex -name '*.java'`
     if [ ${NEED_DEX} = "true" ]; then
       make_dex classes2
     fi
@@ -411,7 +432,7 @@
   else
     # Move jasmin classes into classes directory so that they are picked up with -cp classes.
     mkdir -p classes
-    mv jasmin_classes/* classes
+    cp -r jasmin_classes/* classes/
   fi
 fi
 
@@ -447,21 +468,41 @@
   make_dexmerge classes2.dex smali_classes2.dex
 fi
 
-if [ ${HAS_SRC_EX} = "true" ]; then
+if [ ${HAS_SRC_EX} = "true" -o ${HAS_SRC_EX2} = "true" ]; then
   # Build src-ex into classes-ex.
-  # Includes 'src', 'src-art' source when compiling classes-ex, but exclude their .class files.
-  if [[ "${HAS_SRC}" == "true" ]]; then
+  # Includes 'src', 'src-art' and 'jasmin' source when compiling classes-ex,
+  # but exclude their .class files.
+  if [ "${HAS_SRC}" = "true" -o "${HAS_SRC_ART}" = "true" -o "${HAS_JASMIN}" = "true" ]; then
     mkdir -p classes-tmp-for-ex
-    javac_with_bootclasspath -d classes-tmp-for-ex `find src -name '*.java'`
     src_tmp_for_ex="-cp classes-tmp-for-ex"
   fi
+  if [ "${HAS_SRC}" = "true" -a "${HAS_SRC_MULTIDEX}" = "true" ]; then
+    javac_with_bootclasspath -d classes-tmp-for-ex \
+        `find src -name '*.java'` \
+        `find src-multidex -name '*.java'`
+  elif [[ "${HAS_SRC}" == "true" ]]; then
+    javac_with_bootclasspath -d classes-tmp-for-ex `find src -name '*.java'`
+  elif [[ "${HAS_SRC_MULTIDEX}" == "true" ]]; then
+    javac_with_bootclasspath -d classes-tmp-for-ex `find src-multidex -name '*.java'`
+  fi
   if [[ "${HAS_SRC_ART}" == "true" ]]; then
-    mkdir -p classes-tmp-for-ex
     javac_with_bootclasspath -d classes-tmp-for-ex `find src-art -name '*.java'`
-    src_tmp_for_ex="-cp classes-tmp-for-ex"
+  fi
+  if [[ "${HAS_JASMIN}" == "true" ]]; then
+    make_jasmin classes-tmp-for-ex $(find 'jasmin' -name '*.j')
   fi
   mkdir -p classes-ex
-  javac_with_bootclasspath -d classes-ex $src_tmp_for_ex `find src-ex -name '*.java'`
+  if [ ${HAS_SRC_EX} = "true" ]; then
+    javac_with_bootclasspath -d classes-ex $src_tmp_for_ex `find src-ex -name '*.java'`
+    if [[ "x$src_tmp_for_ex" = "x" ]]; then
+      src_tmp_for_ex="-cp classes-ex"
+    else
+      src_tmp_for_ex="$src_tmp_for_ex:classes-ex"
+    fi
+  fi
+  if [ ${HAS_SRC_EX2} = "true" ]; then
+    javac_with_bootclasspath -d classes-ex $src_tmp_for_ex `find src-ex2 -name '*.java'`
+  fi
 fi
 
 if [[ -d classes-ex ]] && [ ${NEED_DEX} = "true" ]; then
diff --git a/test/etc/default-check b/test/etc/default-check
index 46a095c..f6f7bf4 100755
--- a/test/etc/default-check
+++ b/test/etc/default-check
@@ -14,4 +14,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-diff --strip-trailing-cr -q "$1" "$2" >/dev/null
\ No newline at end of file
+# Inputs:
+# $1: Test's expected standard output
+# $2: Test's actual standard output
+# $3: Test's expected standard error
+# $4: Test's actual standard error
+
+diff --strip-trailing-cr -q "$1" "$2" >/dev/null \
+  && diff --strip-trailing-cr -q "$3" "$4" >/dev/null
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 101fa52..105af41 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -53,6 +53,7 @@
 INVOKE_WITH=""
 IS_JVMTI_TEST="n"
 ADD_LIBDIR_ARGUMENTS="n"
+SUFFIX64=""
 ISA=x86
 LIBRARY_DIRECTORY="lib"
 TEST_DIRECTORY="nativetest"
@@ -61,7 +62,6 @@
 PREBUILD="y"
 QUIET="n"
 RELOCATE="n"
-STRIP_DEX="n"
 SECONDARY_DEX=""
 TIME_OUT="n"  # "n" (disabled), "timeout" (use timeout), "gdb" (use gdb)
 TIMEOUT_DUMPER=signal_dumper
@@ -85,6 +85,9 @@
 TEST_DM="n"
 TEST_IS_NDEBUG="n"
 APP_IMAGE="y"
+SECONDARY_APP_IMAGE="y"
+SECONDARY_CLASS_LOADER_CONTEXT=""
+SECONDARY_COMPILATION="y"
 JVMTI_STRESS="n"
 JVMTI_STEP_STRESS="n"
 JVMTI_FIELD_STRESS="n"
@@ -108,6 +111,10 @@
 ANDROID_FLAGS="${ANDROID_FLAGS} -Xcompiler-option --runtime-arg -Xcompiler-option -XX:SlowDebug=true"
 COMPILER_FLAGS="${COMPILER_FLAGS} --runtime-arg -XX:SlowDebug=true"
 
+# Let the compiler and runtime know that we are running tests.
+COMPILE_FLAGS="${COMPILE_FLAGS} --compile-art-test"
+ANDROID_FLAGS="${ANDROID_FLAGS} -Xcompiler-option --compile-art-test"
+
 while true; do
     if [ "x$1" = "x--quiet" ]; then
         QUIET="y"
@@ -131,6 +138,8 @@
     elif [ "x$1" = "x--jvmti" ]; then
         USE_JVMTI="y"
         IS_JVMTI_TEST="y"
+        # Secondary images block some tested behavior.
+        SECONDARY_APP_IMAGE="n"
         shift
     elif [ "x$1" = "x--add-libdir-argument" ]; then
         ADD_LIBDIR_ARGUMENTS="y"
@@ -216,6 +225,7 @@
         # APP_IMAGE doesn't really work with jvmti redefine stress
         USE_JVMTI="y"
         APP_IMAGE="n"
+        SECONDARY_APP_IMAGE="n"
         JVMTI_STRESS="y"
         JVMTI_REDEFINE_STRESS="y"
         shift
@@ -237,8 +247,15 @@
     elif [ "x$1" = "x--no-app-image" ]; then
         APP_IMAGE="n"
         shift
-    elif [ "x$1" = "x--strip-dex" ]; then
-        STRIP_DEX="y"
+    elif [ "x$1" = "x--no-secondary-app-image" ]; then
+        SECONDARY_APP_IMAGE="n"
+        shift
+    elif [ "x$1" = "x--secondary-class-loader-context" ]; then
+        shift
+        SECONDARY_CLASS_LOADER_CONTEXT="$1"
+        shift
+    elif [ "x$1" = "x--no-secondary-compilation" ]; then
+        SECONDARY_COMPILATION="n"
         shift
     elif [ "x$1" = "x--host" ]; then
         HOST="y"
@@ -405,6 +422,7 @@
         shift
         break
     elif [ "x$1" = "x--64" ]; then
+        SUFFIX64="64"
         ISA="x86_64"
         GDBSERVER_DEVICE="gdbserver64"
         DALVIKVM="dalvikvm64"
@@ -488,7 +506,7 @@
 CHROOT_DEX_LOCATION="$CHROOT$DEX_LOCATION"
 
 # If running on device, determine the ISA of the device.
-if [ "$HOST" = "n" ]; then
+if [ "$HOST" = "n" -a "$USE_JVM" = "n" ]; then
   ISA=$("$ANDROID_BUILD_TOP/art/test/utils/get-device-isa" "$GET_DEVICE_ISA_BITNESS_FLAG")
 fi
 
@@ -615,14 +633,7 @@
   if [[ "$USE_JVM" = "y" ]]; then
     FLAGS="${FLAGS} -agentpath:${ANDROID_HOST_OUT}/nativetest64/${agent}=${TEST_NAME},jvm"
   else
-    if [[ "$HOST" = "y" ]]; then
-      FLAGS="${FLAGS} -agentpath:${agent}=${TEST_NAME},art"
-    else
-      # The linker configuration used for dalvikvm(64) in the ART APEX
-      # requires us to pass the full path to the agent to the runtime when
-      # running on device.
-      FLAGS="${FLAGS} -agentpath:/data/${TEST_DIRECTORY}/art/${ISA}/${agent}=${TEST_NAME},art"
-    fi
+    FLAGS="${FLAGS} -agentpath:${agent}=${TEST_NAME},art"
   fi
 fi
 
@@ -653,14 +664,7 @@
   if [[ "$USE_JVM" = "y" ]]; then
     FLAGS="${FLAGS} -agentpath:${ANDROID_HOST_OUT}/nativetest64/${agent}=${agent_args}"
   else
-    if [[ "$HOST" = "y" ]]; then
-      FLAGS="${FLAGS} -agentpath:${agent}=${agent_args}"
-    else
-      # The linker configuration used for dalvikvm(64) in the ART APEX
-      # requires us to pass the full path to the agent to the runtime when
-      # running on device.
-      FLAGS="${FLAGS} -agentpath:/data/${TEST_DIRECTORY}/art/${ISA}/${agent}=${agent_args}"
-    fi
+    FLAGS="${FLAGS} -agentpath:${agent}=${agent_args}"
   fi
 fi
 
@@ -679,7 +683,7 @@
   if [ "$CREATE_RUNNER" = "y" ]; then
     echo "#!/bin/bash" > runit.sh
     echo "export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH\""
-    echo $cmdline "2>&1" >> runit.sh
+    echo $cmdline >> runit.sh
     chmod u+x runit.sh
     echo "Runnable test script written to $PWD/runit.sh"
   else
@@ -689,31 +693,35 @@
 fi
 
 # 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.
+# because that's what we use for compiling the boot.art image.
 # It may contain additional modules from TEST_CORE_JARS.
-bpath_modules="core-oj core-libart core-icu4j okhttp bouncycastle apache-xml conscrypt"
-if [ "${HOST}" = "y" ]; then
-    framework="${ANDROID_HOST_OUT}/framework"
-    if [ "${ANDROID_HOST_OUT:0:${#ANDROID_BUILD_TOP}+1}" = "${ANDROID_BUILD_TOP}/" ]; then
-      framework_location="${ANDROID_HOST_OUT:${#ANDROID_BUILD_TOP}+1}/framework"
-    else
-      echo "error: ANDROID_BUILD_TOP/ is not a prefix of ANDROID_HOST_OUT"
-      echo "ANDROID_BUILD_TOP=${ANDROID_BUILD_TOP}"
-      echo "ANDROID_HOST_OUT=${ANDROID_HOST_OUT}"
-      exit
-    fi
-    bpath_suffix="-hostdex"
-else
-    framework="${ANDROID_ROOT}/framework"
-    framework_location="${ANDROID_ROOT}/framework"
-    bpath_suffix="-testdex"
-fi
+bpath_modules="core-oj core-libart okhttp bouncycastle apache-xml core-icu4j conscrypt"
 bpath=""
 bpath_locations=""
 bpath_separator=""
+bpath_prefix=""
+bpath_location_prefix=""
+if [ "${HOST}" = "y" ]; then
+  bpath_prefix="${ANDROID_HOST_OUT}"
+  if [ "${ANDROID_HOST_OUT:0:${#ANDROID_BUILD_TOP}+1}" = "${ANDROID_BUILD_TOP}/" ]; then
+    bpath_location_prefix="${ANDROID_HOST_OUT:${#ANDROID_BUILD_TOP}+1}"
+  else
+    echo "error: ANDROID_BUILD_TOP/ is not a prefix of ANDROID_HOST_OUT"
+    echo "ANDROID_BUILD_TOP=${ANDROID_BUILD_TOP}"
+    echo "ANDROID_HOST_OUT=${ANDROID_HOST_OUT}"
+    exit
+  fi
+fi
 for bpath_module in ${bpath_modules}; do
-  bpath+="${bpath_separator}${framework}/${bpath_module}${bpath_suffix}.jar"
-  bpath_locations+="${bpath_separator}${framework_location}/${bpath_module}${bpath_suffix}.jar"
+  apex_module="com.android.art"
+  case "$bpath_module" in
+    (conscrypt)  apex_module="com.android.conscrypt";;
+    (core-icu4j) apex_module="com.android.i18n";;
+    (*)          apex_module="com.android.art";;
+  esac
+  bpath_jar="/apex/${apex_module}/javalib/${bpath_module}.jar"
+  bpath+="${bpath_separator}${bpath_prefix}${bpath_jar}"
+  bpath_locations+="${bpath_separator}${bpath_location_prefix}${bpath_jar}"
   bpath_separator=":"
 done
 # Pass down the bootclasspath
@@ -732,7 +740,7 @@
     if [ "${RELOCATE}" = "y" ] ; then
       DALVIKVM_BOOT_OPT="-Ximage:${BOOT_IMAGE}"
     else
-      DALVIKVM_BOOT_OPT="-Ximage:/system/non-existent/core.art"
+      DALVIKVM_BOOT_OPT="-Ximage:/system/non-existent/boot.art"
     fi
 else
     DALVIKVM_BOOT_OPT="-Ximage:${BOOT_IMAGE}"
@@ -769,34 +777,29 @@
 
 if [ "$INTERPRETER" = "y" ]; then
     INT_OPTS="${INT_OPTS} -Xint"
-    if [ "$VERIFY" = "y" ] ; then
-      INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=quicken"
-      COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=quicken"
-    elif [ "$VERIFY" = "s" ]; then
-      INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=extract"
-      COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=extract"
-      DEX_VERIFY="${DEX_VERIFY} -Xverify:softfail"
-    else # VERIFY = "n"
-      INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=assume-verified"
-      COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=assume-verified"
-      DEX_VERIFY="${DEX_VERIFY} -Xverify:none"
-    fi
 fi
 
 if [ "$JIT" = "y" ]; then
     INT_OPTS="${INT_OPTS} -Xusejit:true"
-    if [ "$VERIFY" = "y" ] ; then
-      INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=quicken"
-      COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=quicken"
-    else
-      INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=assume-verified"
-      COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=assume-verified"
-      DEX_VERIFY="${DEX_VERIFY} -Xverify:none"
-    fi
 else
     INT_OPTS="${INT_OPTS} -Xusejit:false"
 fi
 
+if [ "$INTERPRETER" = "y" ] || [ "$JIT" = "y" ]; then
+  if [ "$VERIFY" = "y" ] ; then
+    INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=verify"
+    COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify"
+  elif [ "$VERIFY" = "s" ]; then
+    INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=extract"
+    COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=extract"
+    DEX_VERIFY="${DEX_VERIFY} -Xverify:softfail"
+  else # VERIFY = "n"
+    INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=assume-verified"
+    COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=assume-verified"
+    DEX_VERIFY="${DEX_VERIFY} -Xverify:none"
+  fi
+fi
+
 JNI_OPTS="-Xjnigreflimit:512 -Xcheck:jni"
 
 COMPILE_FLAGS="${COMPILE_FLAGS} --runtime-arg -Xnorelocate"
@@ -863,6 +866,7 @@
 linkroot_overlay_cmdline="true"
 setupapex_cmdline="true"
 installapex_cmdline="true"
+installapex_test_cmdline="true"
 
 linkdirs() {
   find "$1" -maxdepth 1 -mindepth 1 -type d | xargs -i ln -sf '{}' "$2"
@@ -896,6 +900,8 @@
   if [ "$DEV_MODE" = "y" ]; then
     ln_options="--verbose"
   fi
+  # If the ${RUN} is executed multiple times we don't need to recreate the link
+  installapex_test_cmdline="test -L ${DEX_LOCATION}/zipapex"
   installapex_cmdline="ln -s -f ${ln_options} ${EXTRACTED_ZIPAPEX_LOC} ${DEX_LOCATION}/zipapex"
 fi
 
@@ -905,7 +911,7 @@
   profman_cmdline="$ANDROID_ART_BIN_DIR/profman  \
     --apk=$DEX_LOCATION/$TEST_NAME.jar \
     --dex-location=$DEX_LOCATION/$TEST_NAME.jar"
-  if [ -f $DEX_LOCATION/$TEST_NAME-ex.jar ]; then
+  if [ -f "$TEST_NAME-ex.jar" ] && [ "$SECONDARY_COMPILATION" = "y" ] ; then
     profman_cmdline="${profman_cmdline} \
       --apk=$DEX_LOCATION/$TEST_NAME-ex.jar \
       --dex-location=$DEX_LOCATION/$TEST_NAME-ex.jar"
@@ -921,16 +927,27 @@
   fi
 fi
 
-# Enable mini-debug-info for JIT (if JIT is used).
-FLAGS="$FLAGS -Xcompiler-option --generate-mini-debug-info"
+function write_dex2oat_cmdlines {
+  local name="$1"
 
-if [ "$PREBUILD" = "y" ]; then
-  mkdir_locations="${mkdir_locations} ${DEX_LOCATION}/oat/$ISA"
+  local class_loader_context=""
+  local enable_app_image=false
   if [ "$APP_IMAGE" = "y" ]; then
-    # Pick a base that will force the app image to get relocated.
-    app_image="--app-image-file=$DEX_LOCATION/oat/$ISA/$TEST_NAME.art --resolve-startup-const-strings=true"
+    enable_app_image=true
   fi
 
+  # If the name ends in -ex then this is a secondary dex file
+  if [ "${name:${#name}-3}" = "-ex" ]; then
+    # Lazily realize the default value in case DEX_LOCATION/TEST_NAME change
+    [ -z "$SECONDARY_CLASS_LOADER_CONTEXT" ] && SECONDARY_CLASS_LOADER_CONTEXT="PCL[];PCL[$DEX_LOCATION/$TEST_NAME.jar]"
+    class_loader_context="'--class-loader-context=$SECONDARY_CLASS_LOADER_CONTEXT'"
+    $enable_app_image && [ "$SECONDARY_APP_IMAGE" = "y" ] || enable_app_image=false
+  fi
+
+  local app_image=""
+  $enable_app_image && app_image="--app-image-file=$DEX_LOCATION/oat/$ISA/$name.art --resolve-startup-const-strings=true"
+
+  local dex2oat_binary
   dex2oat_binary=${DEX2OAT_DEBUG_BINARY}
   if  [[ "$TEST_IS_NDEBUG" = "y" ]]; then
     dex2oat_binary=${DEX2OAT_NDEBUG_BINARY}
@@ -938,11 +955,12 @@
   dex2oat_cmdline="$INVOKE_WITH $ANDROID_ART_BIN_DIR/$dex2oat_binary \
                       $COMPILE_FLAGS \
                       --boot-image=${BOOT_IMAGE} \
-                      --dex-file=$DEX_LOCATION/$TEST_NAME.jar \
-                      --oat-file=$DEX_LOCATION/oat/$ISA/$TEST_NAME.odex \
-                      ${app_image} \
+                      --dex-file=$DEX_LOCATION/$name.jar \
+                      --oat-file=$DEX_LOCATION/oat/$ISA/$name.odex \
+                      "$app_image" \
                       --generate-mini-debug-info \
-                      --instruction-set=$ISA"
+                      --instruction-set=$ISA \
+                      $class_loader_context"
   if [ "x$INSTRUCTION_SET_FEATURES" != "x" ] ; then
     dex2oat_cmdline="${dex2oat_cmdline} --instruction-set-features=${INSTRUCTION_SET_FEATURES}"
   fi
@@ -959,20 +977,54 @@
     dex2oat_cmdline="timeout -k ${DEX2OAT_TIMEOUT}s -s SIGRTMIN+2 ${DEX2OAT_RT_TIMEOUT}s ${dex2oat_cmdline} --watchdog-timeout=${DEX2OAT_TIMEOUT}000"
   fi
   if [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then
-    vdex_cmdline="${dex2oat_cmdline} ${VDEX_ARGS} --input-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex --output-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex"
+    vdex_cmdline="${dex2oat_cmdline} ${VDEX_ARGS} --input-vdex=$DEX_LOCATION/oat/$ISA/$name.vdex --output-vdex=$DEX_LOCATION/oat/$ISA/$name.vdex"
   elif [ "$TEST_VDEX" = "y" ]; then
-    vdex_cmdline="${dex2oat_cmdline} ${VDEX_ARGS} --input-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex"
+    if [ "$VDEX_ARGS" = "" ]; then
+      # If no arguments need to be passed, just delete the odex file so that the runtime only picks up the vdex file.
+      vdex_cmdline="rm $DEX_LOCATION/oat/$ISA/$name.odex"
+    else
+      vdex_cmdline="${dex2oat_cmdline} ${VDEX_ARGS} --input-vdex=$DEX_LOCATION/oat/$ISA/$name.vdex"
+    fi
   elif [ "$TEST_DM" = "y" ]; then
-    dex2oat_cmdline="${dex2oat_cmdline} --output-vdex=$DEX_LOCATION/oat/$ISA/primary.vdex"
-    dm_cmdline="zip -qj $DEX_LOCATION/oat/$ISA/$TEST_NAME.dm $DEX_LOCATION/oat/$ISA/primary.vdex"
-    vdex_cmdline="${dex2oat_cmdline} ${VDEX_ARGS} --dump-timings --dm-file=$DEX_LOCATION/oat/$ISA/$TEST_NAME.dm"
-  elif [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then
-    vdex_cmdline="${dex2oat_cmdline} --input-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex --output-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex"
+    dex2oat_cmdline="${dex2oat_cmdline} --copy-dex-files=false --output-vdex=$DEX_LOCATION/oat/$ISA/primary.vdex"
+    dm_cmdline="zip -qj $DEX_LOCATION/oat/$ISA/$name.dm $DEX_LOCATION/oat/$ISA/primary.vdex"
+    vdex_cmdline="${dex2oat_cmdline} ${VDEX_ARGS} --dump-timings --dm-file=$DEX_LOCATION/oat/$ISA/$name.dm"
   fi
-fi
+}
 
-if [ "$STRIP_DEX" = "y" ]; then
-  strip_cmdline="zip --quiet --delete $DEX_LOCATION/$TEST_NAME.jar classes.dex"
+# Enable mini-debug-info for JIT (if JIT is used).
+FLAGS="$FLAGS -Xcompiler-option --generate-mini-debug-info"
+
+if [ "$PREBUILD" = "y" ]; then
+  mkdir_locations="${mkdir_locations} ${DEX_LOCATION}/oat/$ISA"
+
+  # "Primary".
+  write_dex2oat_cmdlines "$TEST_NAME"
+  dex2oat_cmdline=$(echo $dex2oat_cmdline)
+  dm_cmdline=$(echo $dm_cmdline)
+  vdex_cmdline=$(echo $vdex_cmdline)
+
+  # Enable mini-debug-info for JIT (if JIT is used).
+  FLAGS="$FLAGS -Xcompiler-option --generate-mini-debug-info"
+
+  if [ -f "$TEST_NAME-ex.jar" ] && [ "$SECONDARY_COMPILATION" = "y" ] ; then
+    # "Secondary" for test coverage.
+
+    # Store primary values.
+    base_dex2oat_cmdline="$dex2oat_cmdline"
+    base_dm_cmdline="$dm_cmdline"
+    base_vdex_cmdline="$vdex_cmdline"
+
+    write_dex2oat_cmdlines "$TEST_NAME-ex"
+    dex2oat_cmdline=$(echo $dex2oat_cmdline)
+    dm_cmdline=$(echo $dm_cmdline)
+    vdex_cmdline=$(echo $vdex_cmdline)
+
+    # Concatenate.
+    dex2oat_cmdline="$base_dex2oat_cmdline && $dex2oat_cmdline"
+    dm_cmdline="$base_dm_cmdline" # Only use primary dm.
+    vdex_cmdline="$base_vdex_cmdline && $vdex_cmdline"
+  fi
 fi
 
 if [ "$SYNC_BEFORE_RUN" = "y" ]; then
@@ -1016,11 +1068,22 @@
                   -XX:DumpNativeStackOnSigQuit:false \
                   -cp $DEX_LOCATION/$TEST_NAME.jar$SECONDARY_DEX $MAIN $ARGS"
 
+sanitize_dex2oat_cmdline() {
+  local args=()
+  for arg in "$@"; do
+    if [ "$arg" = "--class-loader-context=&" ]; then
+      arg="--class-loader-context=\&"
+    fi
+    args+=("$arg")
+  done
+  echo -n "${args[@]}"
+}
+
 # Remove whitespace.
-dex2oat_cmdline=$(echo $dex2oat_cmdline)
+dex2oat_cmdline=$(sanitize_dex2oat_cmdline $(echo $dex2oat_cmdline))
 dalvikvm_cmdline=$(echo $dalvikvm_cmdline)
 dm_cmdline=$(echo $dm_cmdline)
-vdex_cmdline=$(echo $vdex_cmdline)
+vdex_cmdline=$(sanitize_dex2oat_cmdline $(echo $vdex_cmdline))
 profman_cmdline=$(echo $profman_cmdline)
 
 # Use an empty ASAN_OPTIONS to enable defaults.
@@ -1085,24 +1148,30 @@
       # installation.
       LD_LIBRARY_PATH="$ANDROID_ROOT/$LIBRARY_DIRECTORY"
     fi
-    # Needed to access libarttest(d).so and JVMTI agent libraries.
-    LD_LIBRARY_PATH="/data/$TEST_DIRECTORY/art/$ISA:$LD_LIBRARY_PATH"
-    # Needed to access the boot (core) image files.
-    LD_LIBRARY_PATH="/data/art-test/$ISA:$LD_LIBRARY_PATH"
+
+    # This adds libarttest(d).so to the default linker namespace when dalvikvm
+    # is run from /apex/com.android.art/bin. Since that namespace is essentially
+    # an alias for the com_android_art namespace, that gives libarttest(d).so
+    # full access to the internal ART libraries.
+    LD_LIBRARY_PATH="/data/$TEST_DIRECTORY/com.android.art/lib${SUFFIX64}:$LD_LIBRARY_PATH"
+    if [ "$TEST_IS_NDEBUG" = "y" ]; then dlib=""; else dlib="d"; fi
+    art_test_internal_libraries=(
+      libartagent${dlib}.so
+      libarttest${dlib}.so
+      libtiagent${dlib}.so
+      libtistress${dlib}.so
+    )
+    art_test_internal_libraries="${art_test_internal_libraries[*]}"
+    NATIVELOADER_DEFAULT_NAMESPACE_LIBS="${art_test_internal_libraries// /:}"
+    dlib=
+    art_test_internal_libraries=
+
     # Needed to access the test's Odex files.
     LD_LIBRARY_PATH="$DEX_LOCATION/oat/$ISA:$LD_LIBRARY_PATH"
     # Needed to access the test's native libraries (see e.g. 674-hiddenapi,
     # which generates `libhiddenapitest_*.so` libraries in `$DEX_LOCATION`).
     LD_LIBRARY_PATH="$DEX_LOCATION:$LD_LIBRARY_PATH"
 
-    # System libraries needed by libarttestd.so
-    PUBLIC_LIBS=libc++.so:libbacktrace.so:libbase.so:libnativehelper.so
-    if [ "$TEST_IS_NDEBUG" = "y" ]; then
-      PUBLIC_LIBS=$PUBLIC_LIBS:libart.so:libdexfile.so:libprofile.so:libartbase.so
-    else
-      PUBLIC_LIBS=$PUBLIC_LIBS:libartd.so:libdexfiled.so:libprofiled.so:libartbased.so
-    fi
-
     # Prepend directories to the path on device.
     PREPEND_TARGET_PATH=$ANDROID_ART_BIN_DIR
     if [ "$ANDROID_ROOT" != "/system" ]; then
@@ -1157,7 +1226,6 @@
     cmdline="cd $DEX_LOCATION && \
              export ASAN_OPTIONS=$RUN_TEST_ASAN_OPTIONS && \
              export ANDROID_DATA=$DEX_LOCATION && \
-             export ANDROID_ADDITIONAL_PUBLIC_LIBRARIES=$PUBLIC_LIBS && \
              export DEX_LOCATION=$DEX_LOCATION && \
              export ANDROID_ROOT=$ANDROID_ROOT && \
              export ANDROID_I18N_ROOT=$ANDROID_I18N_ROOT && \
@@ -1167,6 +1235,7 @@
              rm -rf ${DEX_LOCATION}/dalvik-cache/ && \
              mkdir -p ${mkdir_locations} && \
              export LD_LIBRARY_PATH=$LD_LIBRARY_PATH && \
+             export NATIVELOADER_DEFAULT_NAMESPACE_LIBS=$NATIVELOADER_DEFAULT_NAMESPACE_LIBS && \
              export PATH=$PREPEND_TARGET_PATH:\$PATH && \
              $profman_cmdline && \
              $dex2oat_cmdline && \
@@ -1176,8 +1245,8 @@
              $sync_cmdline && \
              $timeout_prefix $dalvikvm_cmdline"
 
-    cmdfile=$(tempfile -p "cmd-" -s "-$TEST_NAME")
-    echo "$cmdline" > $cmdfile
+    cmdfile=$(mktemp cmd-XXXX --suffix "-$TEST_NAME")
+    echo "$cmdline" >> $cmdfile
 
     if [ "$DEV_MODE" = "y" ]; then
       echo $cmdline
@@ -1262,7 +1331,7 @@
         echo EXPORT $var=${!var}
       done
       echo "$(declare -f linkdirs)"
-      echo "mkdir -p ${mkdir_locations} && $setupapex_cmdline && $installapex_cmdline && $linkroot_cmdline && $linkroot_overlay_cmdline && $profman_cmdline && $dex2oat_cmdline && $dm_cmdline && $vdex_cmdline && $strip_cmdline && $sync_cmdline && $cmdline"
+      echo "mkdir -p ${mkdir_locations} && $setupapex_cmdline && ( $installapex_test_cmdline || $installapex_cmdline ) && $linkroot_cmdline && $linkroot_overlay_cmdline && $profman_cmdline && $dex2oat_cmdline && $dm_cmdline && $vdex_cmdline && $strip_cmdline && $sync_cmdline && $cmdline"
     fi
 
     cd $ANDROID_BUILD_TOP
@@ -1277,13 +1346,13 @@
 
     mkdir -p ${mkdir_locations} || exit 1
     $setupapex_cmdline || { echo "zipapex extraction failed." >&2 ; exit 2; }
-    $installapex_cmdline || { echo "zipapex install failed. cmd was: ${installapex_cmdline}." >&2; find ${mkdir_locations} -type f >&2; exit 2; }
+    $installapex_test_cmdline || $installapex_cmdline || { echo "zipapex install failed. cmd was: ${installapex_test_cmdline} || ${installapex_cmdline}." >&2; find ${mkdir_locations} -type f >&2; exit 2; }
     $linkroot_cmdline || { echo "create symlink android-root failed." >&2 ; exit 2; }
     $linkroot_overlay_cmdline || { echo "overlay android-root failed." >&2 ; exit 2; }
     $profman_cmdline || { echo "Profman failed." >&2 ; exit 2; }
-    $dex2oat_cmdline || { echo "Dex2oat failed." >&2 ; exit 2; }
-    $dm_cmdline || { echo "Dex2oat failed." >&2 ; exit 2; }
-    $vdex_cmdline || { echo "Dex2oat failed." >&2 ; exit 2; }
+    eval "$dex2oat_cmdline" || { echo "Dex2oat failed." >&2 ; exit 2; }
+    eval "$dm_cmdline" || { echo "Dex2oat failed." >&2 ; exit 2; }
+    eval "$vdex_cmdline" || { echo "Dex2oat failed." >&2 ; exit 2; }
     $strip_cmdline || { echo "Strip failed." >&2 ; exit 3; }
     $sync_cmdline || { echo "Sync failed." >&2 ; exit 4; }
 
@@ -1293,12 +1362,17 @@
         echo export $var="${!var}" >> ${DEX_LOCATION}/runit.sh
       done
       if [ "$DEV_MODE" = "y" ]; then
-        echo $cmdline "2>&1" >> ${DEX_LOCATION}/runit.sh
+        echo $cmdline >> ${DEX_LOCATION}/runit.sh
       else
         echo 'STDERR=$(mktemp)' >> ${DEX_LOCATION}/runit.sh
         echo 'STDOUT=$(mktemp)' >> ${DEX_LOCATION}/runit.sh
-        echo $cmdline '2>${STDERR} >${STDOUT}' >> ${DEX_LOCATION}/runit.sh
-        echo 'if diff ${STDOUT} $ANDROID_DATA/expected.txt; then' >> ${DEX_LOCATION}/runit.sh
+        echo $cmdline '>${STDOUT} 2>${STDERR}' >> ${DEX_LOCATION}/runit.sh
+        echo 'if diff ${STDOUT} $ANDROID_DATA/expected-stdout.txt; then' \
+          >> ${DEX_LOCATION}/runit.sh
+        echo '  rm -f ${STDOUT} ${STDERR}' >> ${DEX_LOCATION}/runit.sh
+        echo '  exit 0' >> ${DEX_LOCATION}/runit.sh
+        echo 'elif diff ${STDERR} $ANDROID_DATA/expected-stderr.txt; then' \
+          >> ${DEX_LOCATION}/runit.sh
         echo '  rm -f ${STDOUT} ${STDERR}' >> ${DEX_LOCATION}/runit.sh
         echo '  exit 0' >> ${DEX_LOCATION}/runit.sh
         echo 'else' >> ${DEX_LOCATION}/runit.sh
@@ -1327,7 +1401,7 @@
     else
       if [ "$TIME_OUT" != "gdb" ]; then
         trap 'kill -INT -$pid' INT
-        $cmdline "$@" 2>&1 & pid=$!
+        $cmdline "$@" & pid=$!
         wait $pid
         exit_value=$?
         # Add extra detail if time out is enabled.
@@ -1338,7 +1412,7 @@
       else
         # With a thread dump that uses gdb if a timeout.
         trap 'kill -INT -$pid' INT
-        $cmdline "$@" 2>&1 & pid=$!
+        $cmdline "$@" & pid=$!
         # Spawn a watcher process.
         ( sleep $TIME_OUT_VALUE && \
           echo "##### Thread dump using gdb on test timeout" && \
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 398f123..d9b089d 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -42,19 +42,12 @@
     },
     {
         "tests": ["002-sleep",
-                  "053-wait-some",
                   "055-enum-performance",
                   "133-static-invoke-super"],
         "description": ["Tests that are timing sensitive and flaky on heavily",
                         "loaded systems."]
     },
     {
-        "tests": "147-stripped-dex-fallback",
-        "variant": "target",
-        "description": ["147-stripped-dex-fallback isn't supported on device",
-                        "because --strip-dex  requires the zip command."]
-    },
-    {
         "tests": "569-checker-pattern-replacement",
         "variant": "target",
         "description": ["569-checker-pattern-replacement tests behaviour",
@@ -62,15 +55,13 @@
     },
     {
         "tests": ["116-nodex2oat",
-                  "118-noimage-dex2oat",
-                  "134-nodex2oat-nofallback"],
+                  "118-noimage-dex2oat"],
         "variant": "prebuild",
         "description": ["Note 116-nodex2oat is not broken per-se it just",
                         "doesn't (and isn't meant to) work with --prebuild."]
     },
     {
-        "tests": ["147-stripped-dex-fallback",
-                  "608-checker-unresolved-lse"],
+        "tests": ["608-checker-unresolved-lse"],
         "variant": "no-prebuild"
     },
     {
@@ -170,18 +161,12 @@
         "bug": "http://b/2133391"
     },
     {
-        "tests": "147-stripped-dex-fallback",
-        "variant": "no-image",
-        "description": ["147-stripped-dex-fallback is disabled because it",
-                        "requires --prebuild."]
-    },
-    {
         "tests": ["116-nodex2oat",
                   "118-noimage-dex2oat",
                   "137-cfi",
                   "138-duplicate-classes-check2"],
         "variant": "no-image",
-        "description": ["All these tests check that we have sane behavior if we",
+        "description": ["All these tests check that we have appropriate behavior if we",
                         "don't have a dex2oat. Therefore we",
                         "shouldn't run them in situations where we actually",
                         "don't have these since they explicitly test for them.",
@@ -251,7 +236,8 @@
         "variant": "trace | stream"
     },
     {
-        "tests": ["604-hot-static-interface",
+        "tests": ["566-polymorphic-inlining",
+                  "604-hot-static-interface",
                   "612-jit-dex-cache",
                   "613-inlining-dex-cache",
                   "626-set-resolved-string",
@@ -303,9 +289,24 @@
         "variant": "optimizing & ndebuggable | regalloc_gc & ndebuggable | speed-profile & ndebuggable | jit & ndebuggable | jit-on-first-use & ndebuggable"
     },
     {
+        "tests": ["596-app-images", "597-app-images-same-classloader"],
+        "description": "no image generated in configuration",
+        "variant": "no-image | no-prebuild"
+    },
+    {
+        "tests": ["596-app-images", "597-app-images-same-classloader"],
+        "description": "not generated when using the access check configuration",
+        "variant": "interp-ac"
+    },
+    {
+        "tests": ["596-app-images", "597-app-images-same-classloader"],
+        "description": "jvmti does not interact well with images",
+        "variant": "field-stress | jvmti-stress | redefine-stress | step-stress | trace-stress"
+    },
+    {
         "tests": "596-app-images",
-        "description": "Code being tested has been disabled",
-        "bug": "b/70734839"
+        "description": "app images do not initialize classes when debuggable",
+        "variant": "debuggable"
     },
     {
         "tests": "055-enum-performance",
@@ -326,8 +327,6 @@
     },
     {
         "tests": ["000-nop",
-                  "134-nodex2oat-nofallback",
-                  "147-stripped-dex-fallback",
                   "595-profile-saving"],
         "description": "The doesn't compile anything",
         "env_vars": {"ART_TEST_BISECTION": "true"},
@@ -442,6 +441,7 @@
             ".*method-handle.*",
             ".*varhandle.*",
             ".*var-handle.*",
+            "160-read-barrier-stress",
             "716-jli-jit-samples",
             "1975-hello-structural-transformation",
             "1976-hello-structural-static-methods",
@@ -481,7 +481,6 @@
             "004-StackWalk",
             "064-field-access",
             "083-compiler-regressions",
-            "098-ddmc",
             "107-int-math2",
             "129-ThreadGetId",
             "135-MirandaDispatch",
@@ -566,11 +565,12 @@
             "692-vdex-inmem-loader",
             "693-vdex-inmem-loader-evict",
             "944-transform-classloaders",
-            "999-redefine-hiddenapi"
+            "999-redefine-hiddenapi",
+            "2038-hiddenapi-jvmti-ext"
         ],
         "description": [
             "Tests that use custom class loaders or other features not supported ",
-            "by our JVMTI implementation"
+            "by our JVMTI implementation (such as hiddenapi, vdex or bad dex-files)"
         ],
         "variant": "jvmti-stress | redefine-stress"
     },
@@ -679,47 +679,6 @@
         "bug": "b/31098551"
     },
     {
-        "tests": [
-            "059-finalizer-throw",
-            "074-gc-thrash",
-            "911-get-stack-trace",
-            "913-heaps",
-            "980-redefine-object"
-        ],
-        "description": [
-            "Interpreter with access checks stack frames are too large and result in",
-            "StackOverFlow errors being thrown."
-        ],
-        "variant": "interp-ac & host",
-        "env_vars": {"SANITIZE_HOST": "address"}
-    },
-    {
-        "tests": [
-            "059-finalizer-throw",
-            "074-gc-thrash",
-            "911-get-stack-trace",
-            "913-heaps",
-            "980-redefine-object"
-        ],
-        "description": [
-            "Interpreter with access checks stack frames are too large and result in",
-            "StackOverFlow errors being thrown."
-        ],
-        "variant": "interp-ac & target",
-        "env_vars": {"SANITIZE_TARGET": "address"}
-    },
-    {
-        "tests": [
-            "074-gc-thrash"
-        ],
-        "description": [
-            "Interpreter with access checks stack frames are too large and result in",
-            "StackOverFlow errors being thrown."
-        ],
-        "variant": "interp-ac & target",
-        "env_vars": {"SANITIZE_TARGET": "hwaddress"}
-    },
-    {
         "tests": "071-dexfile-map-clean",
         "description": [ "We use prebuilt zipalign on master-art-host to avoid pulling in a lot",
                          "of the framework. But a non-sanitized zipalign binary does not work with",
@@ -856,7 +815,6 @@
           "088-monitor-verification",
           "091-override-package-private-method",
           "097-duplicate-method",
-          "098-ddmc",
           "099-vmdebug",
           "100-reflect2",
           "104-growth-limit",
@@ -869,7 +827,6 @@
           "130-hprof",
           "1337-gc-coverage",
           "1338-gc-no-los",
-          "134-nodex2oat-nofallback",
           "134-reg-promotion",
           "135-MirandaDispatch",
           "136-daemon-jni-shutdown",
@@ -883,7 +840,6 @@
           "144-static-field-sigquit",
           "145-alloc-tracking-stress",
           "146-bad-interface",
-          "147-stripped-dex-fallback",
           "148-multithread-gc-annotations",
           "150-loadlibrary",
           "154-gc-loop",
@@ -892,7 +848,6 @@
           "158-app-image-class-table",
           "159-app-image-fields",
           "161-final-abstract-class",
-          "162-method-resolution",
           "163-app-image-methods",
           "164-resolution-trampoline-dex-cache",
           "167-visit-locks",
@@ -910,14 +865,12 @@
           "432-optimizing-cmp",
           "434-invoke-direct",
           "435-new-instance",
-          "441-checker-inliner",
           "442-checker-constant-folding",
           "448-multiple-returns",
           "449-checker-bce",
           "452-multiple-returns2",
           "453-not-byte",
           "454-get-vreg",
-          "455-checker-gvn",
           "457-regs",
           "458-checker-instruct-simplification",
           "459-dead-phi",
@@ -929,7 +882,6 @@
           "471-uninitialized-locals",
           "472-unreachable-if-regression",
           "475-regression-inliner-ids",
-          "480-checker-dead-blocks",
           "496-checker-inlining-class-loader",
           "498-type-propagation",
           "501-null-constant-dce",
@@ -946,8 +898,6 @@
           "518-null-array-get",
           "520-equivalent-phi",
           "529-checker-unresolved",
-          "530-checker-lse",
-          "530-checker-lse-ctor-fences",
           "530-checker-lse3",
           "530-checker-regression-reftyp-final",
           "536-checker-intrinsic-optimization",
@@ -967,7 +917,6 @@
           "565-checker-doublenegbitwise",
           "565-checker-irreducible-loop",
           "566-polymorphic-inlining",
-          "567-checker-compare",
           "569-checker-pattern-replacement",
           "570-checker-osr",
           "571-irreducible-loop",
@@ -1011,7 +960,6 @@
           "628-vdex",
           "629-vdex-speed",
           "630-safecast-array",
-          "631-checker-fp-abs",
           "633-checker-rtp-getclass",
           "634-vdex-duplicate",
           "636-wrong-static-access",
@@ -1027,7 +975,6 @@
           "649-vdex-duplicate-method",
           "652-deopt-intrinsic",
           "656-annotation-lookup-generic-jni",
-          "656-checker-simd-opt",
           "659-unpadded-array",
           "660-clinit",
           "660-store-8-16",
@@ -1055,10 +1002,14 @@
           "707-checker-invalid-profile",
           "714-invoke-custom-lambda-metafactory",
           "716-jli-jit-samples",
+          "729-checker-polymorphic-intrinsic",
           "800-smali",
           "801-VoidCheckCast",
           "802-deoptimization",
           "804-class-extends-itself",
+          "816-illegal-new-array",
+          "819-verification-runtime",
+          "823-cha-inlining",
           "900-hello-plugin",
           "901-hello-ti-agent",
           "903-hello-tagging",
@@ -1168,18 +1119,29 @@
         "bug": "b/147207934"
     },
     {
-        "tests": ["530-checker-peel-unroll",
+        "tests": ["178-app-image-native-method",
+                  "530-checker-peel-unroll",
                   "616-cha-unloading",
                   "674-hiddenapi",
                   "677-fsi2",
                   "678-quickening",
                   "679-locks",
                   "688-shared-library",
+                  "689-zygote-jit-deopt",
                   "690-hiddenapi-same-name-methods",
                   "691-hiddenapi-proxy",
+                  "692-vdex-secondary-loader",
                   "692-vdex-inmem-loader",
                   "693-vdex-inmem-loader-evict",
                   "723-string-init-range",
+                  "808-checker-invoke-super",
+                  "809-checker-invoke-super-bss",
+                  "810-checker-invoke-super-default",
+                  "811-checker-invoke-super-secondary",
+                  "817-hiddenapi",
+                  "820-vdex-multidex",
+                  "821-many-args",
+                  "822-hiddenapi-future",
                   "999-redefine-hiddenapi",
                   "1000-non-moving-space-stress",
                   "1001-app-image-regions",
@@ -1222,7 +1184,13 @@
                   "2005-pause-all-redefine-multithreaded",
                   "2006-virtual-structural-finalizing",
                   "2007-virtual-structural-finalizable",
-                  "2035-structural-native-method"],
+                  "2009-structural-local-ref",
+                  "2011-stack-walk-concurrent-instrument",
+                  "2012-structural-redefinition-failures-jni-id",
+                  "2033-shutdown-mechanics",
+                  "2035-structural-native-method",
+                  "2036-structural-subclass-shadow",
+                  "2038-hiddenapi-jvmti-ext"],
         "variant": "jvm",
         "description": ["Doesn't run on RI."]
     },
@@ -1315,14 +1283,6 @@
         "description": [ "Fails to eliminate dead reference when debuggable." ]
     },
     {
-        "tests": ["719-dm-verify-redefinition"],
-        "variant": "jvm | speed-profile | interp-ac | target | no-prebuild",
-        "description": ["Doesn't run on RI because of boot class redefintion.",
-                        "Doesn't work with profiles because the run-test is not setup to",
-                        "support both. It also needs full verification, so no interp-ac.",
-                        "Requires zip, which isn't available on device"]
-    },
-    {
         "tests": ["004-ReferenceMap",
                   "449-checker-bce",
                   "466-get-live-vreg",
@@ -1364,6 +1324,12 @@
                         "zipapex runner."]
     },
     {
+        "tests": ["175-alloc-big-bignums"],
+        "variant": "interpreter | interp-ac | trace | no-image | debuggable | prebuild",
+        "bug": "b/174470490",
+        "description": "Interpreting BigInteger.add() is too slow (timeouts)"
+    },
+    {
         "tests": ["2029-contended-monitors"],
         "variant": "interpreter | interp-ac | gcstress | trace",
         "description": ["Slow test. Prone to timeouts."]
@@ -1373,5 +1339,83 @@
         "variant": "gcstress & debuggable & debug & host",
         "bug": "b/149708943",
         "description": ["Timeouts."]
+    },
+    {
+        "tests": ["003-omnibus-opcodes",
+                  "051-thread",
+                  "427-bounds",
+                  "570-checker-osr-locals",
+                  "597-app-images-same-classloader",
+                  "724-invoke-super-npe",
+                  "725-imt-conflict-object",
+                  "952-invoke-custom",
+                  "960-default-smali",
+                  "966-default-conflict",
+                  "990-field-trace",
+                  "2034-spaces-in-SimpleName"],
+        "variant": "jvm",
+        "bug": "b/154802847",
+        "description": ["Failing on RI. Needs further investigating."]
+    },
+    {
+        "tests": ["122-npe", "160-read-barrier-stress"],
+        "variant": "jvm",
+        "description": ["Reference.refersTo() not supported on old version of RI."]
+    },
+    {
+        "tests": ["2232-write-metrics-to-log"],
+        "variant": "jvm",
+        "description": ["RI does not support ART metrics."]
+    },
+    {
+        "tests": ["2232-write-metrics-to-log"],
+        "variant": "target",
+        "description": ["Checks LOG_STREAM output, which cannot be captured on target."]
+    },
+    {
+        "tests": ["053-wait-some"],
+        "env_vars": {"ART_TEST_DEBUG_GC": "true"},
+        "bug": "b/175435088",
+        "description": ["Test is time-sensitive and fails on debug-gc configuration."]
+    },
+    {
+        "tests": ["053-wait-some"],
+        "variant": "gcstress | interp-ac",
+        "bug": "b/175435088",
+        "description": ["Test is time-sensitive and fails on gcstress and",
+                        "interpreter-access-checks configurations."]
+    },
+    {
+        "tests": ["821-madvise-willneed"],
+        "variant": "jvm",
+        "description": ["Adding custom madvise flags. Not to be tested on default jvm"]
+    },
+    {
+        "tests": ["692-vdex-secondary-loader"],
+        "env_vars": {"ART_USE_READ_BARRIER": "false"},
+        "description": ["Uses the low-ram flag which does not work with CMS"]
+    },
+    {
+        "tests": ["150-loadlibrary",
+                  "656-annotation-lookup-generic-jni",
+                  "674-hiddenapi",
+                  "817-hiddenapi",
+                  "900-hello-plugin"],
+        "variant": "target",
+        "bug": "b/186654484",
+        "description": ["Disabled after the switch to avoid allow_all_shared_libs from the ART namespace to system."]
+    },
+    {
+        "tests": ["2001-virtual-structural-multithread"],
+        "env_vars": {"SANITIZE_HOST": "address"},
+        "bug": "b/176786675",
+        "description": ["Out of memory"]
+    },
+    {
+        "tests": ["2001-virtual-structural-multithread"],
+        "env_vars": {"ART_HEAP_POISONING": "true"},
+        "variant": "host",
+        "bug": "b/176786675",
+        "description": ["Out of memory"]
     }
 ]
diff --git a/test/odsign/Android.bp b/test/odsign/Android.bp
new file mode 100644
index 0000000..3677a99
--- /dev/null
+++ b/test/odsign/Android.bp
@@ -0,0 +1,71 @@
+// Copyright (C) 2021 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.
+
+package {
+    default_applicable_licenses: ["art_license"],
+}
+
+java_test_host {
+    name: "odsign_e2e_tests",
+    defaults: ["art_module_source_build_java_defaults"],
+    srcs: ["test-src/**/*.java"],
+    libs: ["tradefed"],
+    static_libs: [
+        "cts-install-lib-host",
+        "frameworks-base-hostutils",
+    ],
+    data: [
+        ":test_com.android.art",
+        ":odsign_e2e_test_app",
+    ],
+    test_config: "odsign-e2e-tests.xml",
+    test_suites: ["device-tests"],
+}
+
+cc_library_shared {
+    name: "libOdsignTestAppJni",
+    srcs: ["jni/**/*.cc"],
+    shared_libs: [
+        "libnativehelper_compat_libc++",
+        "liblog",
+    ],
+    static_libs: [
+        "libbase_ndk",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    stl: "c++_static",
+    sdk_version: "current",
+}
+
+android_test_helper_app {
+    name: "odsign_e2e_test_app",
+    manifest: "AndroidManifest.xml",
+    srcs: ["src/**/*.java"],
+    jni_libs: [
+        "libOdsignTestAppJni",
+    ],
+    compile_multilib: "both",
+    libs: [
+        "junit",
+    ],
+    static_libs: [
+        "androidx.test.runner",
+        "ctstestrunner-axt",
+    ],
+    sdk_version: "system_current",
+    min_sdk_version: "30",
+}
diff --git a/test/odsign/AndroidManifest.xml b/test/odsign/AndroidManifest.xml
new file mode 100644
index 0000000..b9936fc
--- /dev/null
+++ b/test/odsign/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.tests.odsign">
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.tests.odsign"
+                     android:label="test app for on-device signing">
+        <meta-data android:name="listener"
+                   android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>/>
+</manifest>
diff --git a/test/odsign/jni/android_tests_odsign_ArtifactsSignedTest.cc b/test/odsign/jni/android_tests_odsign_ArtifactsSignedTest.cc
new file mode 100644
index 0000000..a22b967
--- /dev/null
+++ b/test/odsign/jni/android_tests_odsign_ArtifactsSignedTest.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 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 "ArtifactsSignedTest"
+
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+#include <android/log.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_android_tests_odsign_ArtifactsSignedTest_hasFsverityNative(
+    JNIEnv *env, jobject /*thiz*/, jstring filePath) {
+  ScopedUtfChars path(env, filePath);
+
+  struct statx out = {};
+  if (statx(AT_FDCWD, path.c_str(), /*flags=*/ 0, STATX_ALL, &out) != 0) {
+    ALOGE("statx failed at %s", path.c_str());
+    return JNI_FALSE;
+  }
+
+  // Make sure we actually support ATTR_VERITY
+  if ((out.stx_attributes_mask & STATX_ATTR_VERITY) == 0) {
+    ALOGE("STATX_ATTR_VERITY not supported by kernel");
+    return JNI_FALSE;
+  }
+
+  return (out.stx_attributes & STATX_ATTR_VERITY) != 0 ? JNI_TRUE : JNI_FALSE;
+}
diff --git a/test/odsign/odsign-e2e-tests.xml b/test/odsign/odsign-e2e-tests.xml
new file mode 100644
index 0000000..2ed7b09
--- /dev/null
+++ b/test/odsign/odsign-e2e-tests.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Config for on-device signing ART e2e test cases">
+    <option name="test-suite-tag" value="odsign_e2e_tests" />
+    <option name="test-suite-tag" value="apct" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+    <test class="com.android.tradefed.testtype.HostTest" >
+        <option name="jar" value="odsign_e2e_tests.jar" />
+    </test>
+</configuration>
diff --git a/test/odsign/src/com/android/tests/odsign/ArtifactsSignedTest.java b/test/odsign/src/com/android/tests/odsign/ArtifactsSignedTest.java
new file mode 100644
index 0000000..25a46e3
--- /dev/null
+++ b/test/odsign/src/com/android/tests/odsign/ArtifactsSignedTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package com.android.tests.odsign;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ArtifactsSignedTest {
+    private static final String TAG = "VerifyArtArtifactsSignedTest";
+    private static final String ARTIFACTS_DIR = "/data/misc/apexdata/com.android.art/dalvik-cache";
+    private static final String FS_VERITY_PROC_PATH = "/proc/sys/fs/verity";
+
+    // Note that some of these files may exist multiple times - for different architectures
+    // Verifying that they are generated for the correct architectures is currently out of
+    // scope for this test.
+    private static final String[] REQUIRED_ARTIFACT_NAMES = {
+        "boot-framework.art",
+        "boot-framework.oat",
+        "boot-framework.vdex",
+        "system@framework@services.jar@classes.vdex",
+        "system@framework@services.jar@classes.odex",
+        "system@framework@services.jar@classes.art",
+    };
+
+    private static final ArrayList<String> mFoundArtifactNames = new ArrayList<>();
+
+    static {
+        System.loadLibrary("OdsignTestAppJni");
+    }
+
+    private static native boolean hasFsverityNative(@NonNull String path);
+
+    public boolean isFsVeritySupported() {
+        return new File(FS_VERITY_PROC_PATH).exists();
+    }
+
+    @Test
+    public void testArtArtifactsHaveFsverity() throws Exception {
+        assumeTrue("fs-verity is not supported on this device.", isFsVeritySupported());
+        List<File> files = Files.walk(Paths.get(ARTIFACTS_DIR), Integer.MAX_VALUE).
+            map(Path::toFile)
+            .collect(Collectors.toList());
+
+        for (File file : files) {
+            if (file.isFile()) {
+                assertTrue(file.getPath() + " is not in fs-verity",
+                        hasFsverityNative(file.getPath()));
+                Log.i(TAG, file.getPath() + " is in fs-verity");
+                mFoundArtifactNames.add(file.getName());
+            }
+        }
+        for (String artifact : REQUIRED_ARTIFACT_NAMES) {
+            assertTrue("Missing artifact " + artifact, mFoundArtifactNames.contains(artifact));
+        }
+    }
+
+    @Test
+    public void testGeneratesRequiredArtArtifacts() throws Exception {
+        List<File> files = Files.walk(Paths.get(ARTIFACTS_DIR), Integer.MAX_VALUE).
+            map(Path::toFile)
+            .collect(Collectors.toList());
+
+        for (File file : files) {
+            if (file.isFile()) {
+                mFoundArtifactNames.add(file.getName());
+            }
+        }
+        for (String artifact : REQUIRED_ARTIFACT_NAMES) {
+            assertTrue("Missing artifact " + artifact, mFoundArtifactNames.contains(artifact));
+        }
+    }
+}
diff --git a/test/odsign/test-src/com/android/tests/odsign/OnDeviceSigningHostTest.java b/test/odsign/test-src/com/android/tests/odsign/OnDeviceSigningHostTest.java
new file mode 100644
index 0000000..add3199
--- /dev/null
+++ b/test/odsign/test-src/com/android/tests/odsign/OnDeviceSigningHostTest.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package com.android.tests.odsign;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.cts.install.lib.host.InstallUtilsHost;
+
+import com.android.tradefed.device.ITestDevice.ApexInfo;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
+import com.android.tradefed.util.CommandResult;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class OnDeviceSigningHostTest extends BaseHostJUnit4Test {
+
+    private static final String APEX_FILENAME = "test_com.android.art.apex";
+
+    private static final String ART_APEX_DALVIK_CACHE_DIRNAME =
+            "/data/misc/apexdata/com.android.art/dalvik-cache";
+
+    private static final String ODREFRESH_COMPILATION_LOG =
+            "/data/misc/odrefresh/compilation-log.txt";
+
+    private final String[] APP_ARTIFACT_EXTENSIONS = new String[] {".art", ".odex", ".vdex"};
+
+    private final String[] BCP_ARTIFACT_EXTENSIONS = new String[] {".art", ".oat", ".vdex"};
+
+    private static final String TEST_APP_PACKAGE_NAME = "com.android.tests.odsign";
+    private static final String TEST_APP_APK = "odsign_e2e_test_app.apk";
+
+    private final InstallUtilsHost mInstallUtils = new InstallUtilsHost(this);
+
+    private static final Duration BOOT_COMPLETE_TIMEOUT = Duration.ofMinutes(2);
+
+    @Before
+    public void setUp() throws Exception {
+        assumeTrue("Updating APEX is not supported", mInstallUtils.isApexUpdateSupported());
+        installPackage(TEST_APP_APK);
+        mInstallUtils.installApexes(APEX_FILENAME);
+        removeCompilationLogToAvoidBackoff();
+        reboot();
+    }
+
+    @After
+    public void cleanup() throws Exception {
+        ApexInfo apex = mInstallUtils.getApexInfo(mInstallUtils.getTestFile(APEX_FILENAME));
+        getDevice().uninstallPackage(apex.name);
+        removeCompilationLogToAvoidBackoff();
+        reboot();
+    }
+
+    @Test
+    public void verifyArtUpgradeSignsFiles() throws Exception {
+        DeviceTestRunOptions options = new DeviceTestRunOptions(TEST_APP_PACKAGE_NAME);
+        options.setTestClassName(TEST_APP_PACKAGE_NAME + ".ArtifactsSignedTest");
+        options.setTestMethodName("testArtArtifactsHaveFsverity");
+        runDeviceTests(options);
+    }
+
+    @Test
+    public void verifyArtUpgradeGeneratesRequiredArtifacts() throws Exception {
+        DeviceTestRunOptions options = new DeviceTestRunOptions(TEST_APP_PACKAGE_NAME);
+        options.setTestClassName(TEST_APP_PACKAGE_NAME + ".ArtifactsSignedTest");
+        options.setTestMethodName("testGeneratesRequiredArtArtifacts");
+        runDeviceTests(options);
+    }
+
+    private Set<String> getMappedArtifacts(String pid, String grepPattern) throws Exception {
+        final String grepCommand = String.format("grep \"%s\" /proc/%s/maps", grepPattern, pid);
+        CommandResult result = getDevice().executeShellV2Command(grepCommand);
+        assertTrue(result.toString(), result.getExitCode() == 0);
+        Set<String> mappedFiles = new HashSet<>();
+        for (String line : result.getStdout().split("\\R")) {
+            int start = line.indexOf(ART_APEX_DALVIK_CACHE_DIRNAME);
+            if (line.contains("[")) {
+                continue; // ignore anonymously mapped sections which are quoted in square braces.
+            }
+            mappedFiles.add(line.substring(start));
+        }
+        return mappedFiles;
+    }
+
+    private String[] getSystemServerClasspath() throws Exception {
+        String systemServerClasspath =
+                getDevice().executeShellCommand("echo $SYSTEMSERVERCLASSPATH");
+        return systemServerClasspath.split(":");
+    }
+
+    private String getSystemServerIsa(String mappedArtifact) {
+        // Artifact path for system server artifacts has the form:
+        //    ART_APEX_DALVIK_CACHE_DIRNAME + "/<arch>/system@framework@some.jar@classes.odex"
+        // `mappedArtifacts` may include other artifacts, such as boot-framework.oat that are not
+        // prefixed by the architecture.
+        String[] pathComponents = mappedArtifact.split("/");
+        return pathComponents[pathComponents.length - 2];
+    }
+
+    private void verifySystemServerLoadedArtifacts() throws Exception {
+        String[] classpathElements = getSystemServerClasspath();
+        assertTrue("SYSTEMSERVERCLASSPATH is empty", classpathElements.length > 0);
+
+        String systemServerPid = getDevice().executeShellCommand("pgrep system_server");
+        assertTrue(systemServerPid != null);
+
+        // system_server artifacts are in the APEX data dalvik cache and names all contain
+        // the word "@classes". Look for mapped files that match this pattern in the proc map for
+        // system_server.
+        final String grepPattern = ART_APEX_DALVIK_CACHE_DIRNAME + ".*@classes";
+        final Set<String> mappedArtifacts = getMappedArtifacts(systemServerPid, grepPattern);
+        assertTrue(
+                "No mapped artifacts under " + ART_APEX_DALVIK_CACHE_DIRNAME,
+                mappedArtifacts.size() > 0);
+        final String isa = getSystemServerIsa(mappedArtifacts.iterator().next());
+        final String isaCacheDirectory = String.format("%s/%s", ART_APEX_DALVIK_CACHE_DIRNAME, isa);
+
+        // Check the non-APEX components in the system_server classpath have mapped artifacts.
+        for (String element : classpathElements) {
+            // Skip system_server classpath elements from APEXes as these are not currently
+            // compiled.
+            if (element.startsWith("/apex")) {
+                continue;
+            }
+            String escapedPath = element.substring(1).replace('/', '@');
+            for (String extension : APP_ARTIFACT_EXTENSIONS) {
+                final String fullArtifactPath =
+                        String.format("%s/%s@classes%s", isaCacheDirectory, escapedPath, extension);
+                assertTrue(
+                        "Missing " + fullArtifactPath, mappedArtifacts.contains(fullArtifactPath));
+            }
+        }
+
+        for (String mappedArtifact : mappedArtifacts) {
+            // Check no APEX JAR artifacts are mapped for system_server since if there
+            // are, then the policy around not compiling APEX jars for system_server has
+            // changed and this test needs updating here and in the system_server classpath
+            // check above.
+            assertTrue(
+                    "Unexpected mapped artifact: " + mappedArtifact,
+                    mappedArtifact.contains("/apex"));
+
+            // Check the mapped artifact has a .art, .odex or .vdex extension.
+            final boolean knownArtifactKind =
+                    Arrays.stream(APP_ARTIFACT_EXTENSIONS)
+                            .anyMatch(e -> mappedArtifact.endsWith(e));
+            assertTrue("Unknown artifact kind: " + mappedArtifact, knownArtifactKind);
+        }
+    }
+
+    private void verifyZygoteLoadedArtifacts(String zygoteName, String zygotePid) throws Exception {
+        final String bootExtensionName = "boot-framework";
+        final Set<String> mappedArtifacts = getMappedArtifacts(zygotePid, bootExtensionName);
+
+        assertTrue("Expect 3 boot-framework artifacts", mappedArtifacts.size() == 3);
+
+        String allArtifacts = mappedArtifacts.stream().collect(Collectors.joining(","));
+        for (String extension : BCP_ARTIFACT_EXTENSIONS) {
+            final String artifact = bootExtensionName + extension;
+            final boolean found = mappedArtifacts.stream().anyMatch(a -> a.endsWith(artifact));
+            assertTrue(zygoteName + " " + artifact + " not found: '" + allArtifacts + "'", found);
+        }
+    }
+
+    private void verifyZygotesLoadedArtifacts() throws Exception {
+        // There are potentially two zygote processes "zygote" and "zygote64". These are
+        // instances 32-bit and 64-bit unspecialized app_process processes.
+        // (frameworks/base/cmds/app_process).
+        int zygoteCount = 0;
+        for (String zygoteName : new String[] {"zygote", "zygote64"}) {
+            final CommandResult pgrepResult =
+                    getDevice().executeShellV2Command("pgrep " + zygoteName);
+            if (pgrepResult.getExitCode() != 0) {
+                continue;
+            }
+            final String zygotePid = pgrepResult.getStdout();
+            verifyZygoteLoadedArtifacts(zygoteName, zygotePid);
+            zygoteCount += 1;
+        }
+        assertTrue("No zygote processes found", zygoteCount > 0);
+    }
+
+    @Test
+    public void verifyGeneratedArtifactsLoaded() throws Exception {
+        // Checking zygote and system_server need the device have adb root to walk process maps.
+        final boolean adbEnabled = getDevice().enableAdbRoot();
+        assertTrue("ADB root failed and required to get process maps", adbEnabled);
+
+        // Check there is a compilation log, we expect compilation to have occurred.
+        assertTrue("Compilation log not found", haveCompilationLog());
+
+        // Check both zygote and system_server processes to see that they have loaded the
+        // artifacts compiled and signed by odrefresh and odsign. We check both here rather than
+        // having a separate test because the device reboots between each @Test method and
+        // that is an expensive use of time.
+        verifyZygotesLoadedArtifacts();
+        verifySystemServerLoadedArtifacts();
+    }
+
+    @Test
+    public void verifyGeneratedArtifactsLoadedForSamegradeUpdate() throws Exception {
+        // Install the same APEX effecting a samegrade update. The setUp method has installed it
+        // before us.
+        mInstallUtils.installApexes(APEX_FILENAME);
+        reboot();
+
+        final boolean adbEnabled = getDevice().enableAdbRoot();
+        assertTrue("ADB root failed and required to get odrefresh compilation log", adbEnabled);
+
+        // Check that odrefresh logged a compilation attempt due to samegrade ART APEX install.
+        String[] logLines = getDevice().pullFileContents(ODREFRESH_COMPILATION_LOG).split("\n");
+        assertTrue(
+                "Expected 3 lines in " + ODREFRESH_COMPILATION_LOG + ", found " + logLines.length,
+                logLines.length == 3);
+
+        // Check that the compilation log entries are reasonable, ie times move forward.
+        // The first line of the log is the log format version number.
+        String[] firstUpdateEntry = logLines[1].split(" ");
+        String[] secondUpdateEntry = logLines[2].split(" ");
+        final int LOG_ENTRY_FIELDS = 5;
+        assertTrue(
+                "Unexpected number of fields: " + firstUpdateEntry.length + " != " +
+                LOG_ENTRY_FIELDS,
+                firstUpdateEntry.length == LOG_ENTRY_FIELDS);
+        assertTrue(firstUpdateEntry.length == secondUpdateEntry.length);
+
+        final int LAST_UPDATE_MILLIS_INDEX = 1;
+        final int COMPILATION_TIME_INDEX = 3;
+        for (int i = 0; i < firstUpdateEntry.length; ++i) {
+            final long firstField = Long.parseLong(firstUpdateEntry[i]);
+            final long secondField = Long.parseLong(secondUpdateEntry[i]);
+            if (i == LAST_UPDATE_MILLIS_INDEX) {
+                // The second APEX lastUpdateMillis should be after the first, but a clock
+                // adjustment might reverse the order so we can't assert this (b/194365586).
+                assertTrue(
+                        "Last update times are expected to differ, but they are equal " +
+                        firstField + " == " + secondField,
+                        firstField != secondField);
+            } else if (i == COMPILATION_TIME_INDEX) {
+                // The second compilation time should be after the first compilation time, but
+                // a clock adjustment might reverse the order so we can't assert this
+                // (b/194365586).
+                assertTrue(
+                        "Compilation times are expected to differ, but they are equal " +
+                        firstField + " == " + secondField,
+                        firstField != secondField);
+            } else {
+                // The remaining fields should be the same, ie trigger for compilation.
+                assertTrue(
+                        "Compilation entries differ for position " + i + ": " +
+                        firstField + " != " + secondField,
+                        firstField == secondField);
+            }
+        }
+
+        verifyGeneratedArtifactsLoaded();
+    }
+
+    private boolean haveCompilationLog() throws Exception {
+        CommandResult result =
+                getDevice().executeShellV2Command("stat " + ODREFRESH_COMPILATION_LOG);
+        return result.getExitCode() == 0;
+    }
+
+    private void removeCompilationLogToAvoidBackoff() throws Exception {
+        getDevice().executeShellCommand("rm -f " + ODREFRESH_COMPILATION_LOG);
+    }
+
+    private void reboot() throws Exception {
+        getDevice().reboot();
+        boolean success = getDevice().waitForBootComplete(BOOT_COMPLETE_TIMEOUT.toMillis());
+        assertWithMessage("Device didn't boot in %s", BOOT_COMPLETE_TIMEOUT).that(success).isTrue();
+    }
+}
diff --git a/test/run-test b/test/run-test
index 66039b7..9352314 100755
--- a/test/run-test
+++ b/test/run-test
@@ -122,10 +122,13 @@
 info="info.txt"
 build="build"
 run="run"
-expected="expected.txt"
+expected_stdout="expected-stdout.txt"
+expected_stderr="expected-stderr.txt"
 check_cmd="check"
-output="output.txt"
-build_output="build-output.txt"
+test_stdout="test-stdout.txt"
+test_stderr="test-stderr.txt"
+build_stdout="build-stdout.txt"
+build_stderr="build-stderr.txt"
 cfg_output="graph.cfg"
 strace_output="strace-output.txt"
 lib="libartd.so"
@@ -352,6 +355,9 @@
     elif [ "x$1" = "x--no-precise" ]; then
         run_args+=(--no-precise)
         shift
+    elif [ "x$1" = "x--external-log-tags" ]; then
+        run_args+=(--external-log-tags)
+        shift
     elif [ "x$1" = "x--invoke-with" ]; then
         shift
         what="$1"
@@ -557,7 +563,7 @@
 # Cannot use readlink -m, as it does not exist on Mac.
 # Fallback to nuclear option:
 noncanonical_tmp_dir=$tmp_dir
-tmp_dir="`cd $oldwd ; python -c "import os; import sys; sys.stdout.write(os.path.realpath('$tmp_dir'))"`"
+tmp_dir="`cd $oldwd ; python3 -c "import os; import sys; sys.stdout.write(os.path.realpath('$tmp_dir'))"`"
 if [ -z $tmp_dir ] ; then
   err_echo "Failed to resolve $tmp_dir"
   exit 1
@@ -615,7 +621,8 @@
 function guess_target_arch_name() {
     # Check whether this is a device with native bridge. Currently this is hardcoded
     # to x86 + arm.
-    x86_arm=`ls ${ANDROID_PRODUCT_OUT}/data/art-test | sort | grep -E '^(arm|x86)$'`
+    local guess_path=${ANDROID_PRODUCT_OUT}/system/apex/com.android.art.testing/javalib
+    local x86_arm=`ls ${guess_path} | sort | grep -E '^(arm|x86)$'`
     # Collapse line-breaks into spaces
     x86_arm=$(echo $x86_arm)
     if [ "x$x86_arm" = "xarm x86" ] ; then
@@ -627,8 +634,8 @@
             target_arch_name=x86
         fi
     else
-        grep32bit=`ls ${ANDROID_PRODUCT_OUT}/data/art-test | grep -E '^(arm|x86)$'`
-        grep64bit=`ls ${ANDROID_PRODUCT_OUT}/data/art-test | grep -E '^(arm64|x86_64)$'`
+        local grep32bit=`ls ${guess_path} | grep -E '^(arm|x86)$'`
+        local grep64bit=`ls ${guess_path} | grep -E '^(arm64|x86_64)$'`
         if [ "x${suffix64}" = "x64" ]; then
             target_arch_name=${grep64bit}
         else
@@ -675,12 +682,16 @@
 elif [ "$runtime" = "art" ]; then
     if [ "$target_mode" = "no" ]; then
         guess_host_arch_name
-        run_args+=(--boot "${ANDROID_HOST_OUT}/framework/core.art:*")
+        run_args+=(--boot "${ANDROID_HOST_OUT}/apex/art_boot_images/javalib/boot.art")
         run_args+=(--runtime-option "-Djava.library.path=${host_lib_root}/lib${suffix64}:${host_lib_root}/nativetest${suffix64}")
     else
         guess_target_arch_name
+        # Note that libarttest(d).so and other test libraries that depend on ART
+        # internal libraries must not be in this path for JNI libraries - they
+        # need to be loaded through LD_LIBRARY_PATH and
+        # NATIVELOADER_DEFAULT_NAMESPACE_LIBS instead.
         run_args+=(--runtime-option "-Djava.library.path=/data/nativetest${suffix64}/art/${target_arch_name}")
-        run_args+=(--boot "/data/art-test/core.art:/data/art-test/*")
+        run_args+=(--boot "/apex/com.android.art/javalib/boot.art")
     fi
     if [ "$relocate" = "yes" ]; then
       run_args+=(--relocate)
@@ -760,7 +771,7 @@
         echo "              The script will only run the test portion, and " \
              "share oat and dex files."
         echo "  $prog --update [options] [test-name]  Update mode" \
-             "(replaces expected.txt)."
+             "(replaces expected-stdout.txt and expected-stderr.txt)."
         echo '  Omitting the test name or specifying "-" will use the' \
              "current directory."
         echo "  Runtime Options:"
@@ -797,7 +808,6 @@
         echo "    --zygote              Spawn the process from the Zygote." \
              "If used, then the"
         echo "                          other runtime options are ignored."
-        echo "    --no-dex2oat          Run as though dex2oat was failing."
         echo "    --prebuild            Run dex2oat on the files before starting test. (default)"
         echo "    --no-prebuild         Do not run dex2oat on the files before starting"
         echo "                          the test."
@@ -851,6 +861,8 @@
         echo "    --instruction-set-features [string]"
         echo "                          Set instruction-set-features for compilation."
         echo "    --quiet               Don't print anything except failure messages"
+        echo "    --external-log-tags   Use ANDROID_LOG_TAGS to set a custom logging level for"
+        echo "                          a test run."
         echo "    --bisection-search    Perform bisection bug search."
         echo "    --vdex                Test using vdex as in input to dex2oat. Only works with --prebuild."
         echo "    --suspend-timeout     Change thread suspend timeout ms (default 500000)."
@@ -863,17 +875,15 @@
 test_dir=`pwd`
 
 td_info="${test_dir}/${info}"
-td_expected="${test_dir}/${expected}"
+td_expected_stdout="${test_dir}/${expected_stdout}"
+td_expected_stderr="${test_dir}/${expected_stderr}"
 
-if [ ! -r $td_info ]; then
-    err_echo "${test_dir}: missing file $td_info"
-    exit 1
-fi
-
-if [ ! -r $td_expected ]; then
-    err_echo "${test_dir}: missing file $td_expected"
-    exit 1
-fi
+for td_file in "$td_info" "$td_expected_stdout" "$td_expected_stderr"; do
+    if [ ! -r "$td_file" ]; then
+        err_echo "${test_dir}: missing file $td_file"
+        exit 1
+    fi
+done
 
 # copy the test to a temp dir and run it
 
@@ -928,6 +938,7 @@
       fi
 
       run_args+=(-Xcompiler-option "--dump-cfg=$cfg_output_dir/$cfg_output" -Xcompiler-option -j1)
+      checker_args="$checker_args --print-cfg"
     fi
   fi
 fi
@@ -959,12 +970,12 @@
 good_run="yes"
 export TEST_RUNTIME="${runtime}"
 if [ "$dev_mode" = "yes" ]; then
-    "./${build}" $build_args 2>&1
+    "./${build}" $build_args
     build_exit="$?"
     echo "build exit status: $build_exit" 1>&2
     if [ "$build_exit" = '0' ]; then
         echo "${test_dir}: running..." 1>&2
-        "./${run}" "${run_args[@]}" "$@" 2>&1
+        "./${run}" "${run_args[@]}" "$@"
         run_exit="$?"
 
         if [ "$run_exit" = "0" ]; then
@@ -985,45 +996,61 @@
         echo "run exit status: $run_exit" 1>&2
     fi
 elif [ "$update_mode" = "yes" ]; then
-    "./${build}" $build_args >"$build_output" 2>&1
+    "./${build}" $build_args >"$build_stdout" 2>"$build_stderr"
     build_exit="$?"
     if [ "$build_exit" = '0' ]; then
         echo "${test_dir}: running..." 1>&2
-        "./${run}" "${run_args[@]}" "$@" >"$output" 2>&1
+        "./${run}" "${run_args[@]}" "$@" >"$test_stdout" 2>"$test_stderr"
         if [ "$run_checker" = "yes" ]; then
           if [ "$target_mode" = "yes" ]; then
             adb pull "$chroot/$cfg_output_dir/$cfg_output" &> /dev/null
           fi
-          "$checker" -q $checker_args "$cfg_output" "$tmp_dir" >> "$output" 2>&1
+          "$checker" -q $checker_args "$cfg_output" "$tmp_dir" >>"$test_stdout" 2>>"$test_stderr"
         fi
-        sed -e 's/[[:cntrl:]]$//g' < "$output" >"${td_expected}"
+        sed -e 's/[[:cntrl:]]$//g' <"$test_stdout" >"${td_expected_stdout}"
+        sed -e 's/[[:cntrl:]]$//g' <"$test_stderr" >"${td_expected_stderr}"
         good="yes"
     else
-        cat "$build_output" 1>&${real_stderr} 1>&2
+        err_echo "#################### build standard output"
+        cat "$build_stdout" 1>&${real_stderr}
+        err_echo "####################"
+        err_echo "#################### build standard error"
+        cat "$build_stderr" 1>&${real_stderr}
+        err_echo "####################"
         err_echo "build exit status: $build_exit"
     fi
 elif [ "$build_only" = "yes" ]; then
     good="yes"
-    "./${build}" $build_args >"$build_output" 2>&1
+    "./${build}" $build_args >"$build_stdout" 2>"$build_stderr"
     build_exit="$?"
     if [ "$build_exit" '!=' '0' ]; then
-        cp "$build_output" "$output"
-        echo "build exit status: $build_exit" >>"$output"
-        diff --strip-trailing-cr -q "$expected" "$output" >/dev/null
+        cp "$build_stdout" "$test_stdout"
+        diff --strip-trailing-cr -q "$expected_stdout" "$test_stdout" >/dev/null
         if [ "$?" '!=' "0" ]; then
             good="no"
-            err_echo "BUILD FAILED For ${TEST_NAME}"
+            err_echo "BUILD FAILED For ${TEST_NAME}" \
+              "(the build's standard output does not match the expected standard output)"
         fi
+        cp "$build_stderr" "$test_stderr"
+        diff --strip-trailing-cr -q "$expected_stderr" "$test_stderr" >/dev/null
+        if [ "$?" '!=' "0" ]; then
+            good="no"
+            err_echo "BUILD FAILED For ${TEST_NAME}" \
+              "(the build's standard error does not match the expected standard error)"
+        fi
+        echo "build exit status: $build_exit" >>"$test_stderr"
     fi
     # Clean up extraneous files that are not used by tests.
-    find $tmp_dir -mindepth 1  ! -regex ".*/\(.*jar\|$output\|$expected\)" | xargs rm -rf
+    find $tmp_dir -mindepth 1  \
+        ! -regex ".*/\(.*jar\|$test_stdout\|$expected_stdout|$test_stderr\|$expected_stderr\)" \
+      | xargs rm -rf
     exit 0
 else
-    "./${build}" $build_args >"$build_output" 2>&1
+    "./${build}" $build_args >"$build_stdout" 2>"$build_stderr"
     build_exit="$?"
     if [ "$build_exit" = '0' ]; then
         echo "${test_dir}: running..." 1>&2
-        "./${run}" "${run_args[@]}" "$@" >"$output" 2>&1
+        "./${run}" "${run_args[@]}" "$@" >"$test_stdout" 2>"$test_stderr"
         run_exit="$?"
         if [ "$run_exit" != "0" ]; then
             err_echo "run exit status: $run_exit"
@@ -1032,7 +1059,7 @@
             if [ "$target_mode" = "yes" ]; then
               adb pull "$chroot/$cfg_output_dir/$cfg_output" &> /dev/null
             fi
-            "$checker" -q $checker_args "$cfg_output" "$tmp_dir" >> "$output" 2>&1
+            "$checker" -q $checker_args "$cfg_output" "$tmp_dir" >>"$test_stdout" 2>>"$test_stderr"
             checker_exit="$?"
             if [ "$checker_exit" != "0" ]; then
                 err_echo "checker exit status: $checker_exit"
@@ -1045,20 +1072,22 @@
         fi
     else
         good_build="no"
-        cp "$build_output" "$output"
-        echo "Failed to build in tmpdir=${tmp_dir} from oldwd=${oldwd} and cwd=`pwd`" >> "$output"
-        echo "Non-canonical tmpdir was ${noncanonical_tmp_dir}" >> "$output"
-        echo "Args: ${args}" >> "$output"
-        echo "build exit status: $build_exit" >> "$output"
+        cp "$build_stdout" "$test_stdout"
+        cp "$build_stderr" "$test_stderr"
+        echo "Failed to build in tmpdir=${tmp_dir} from oldwd=${oldwd} and cwd=`pwd`" \
+          >> "$test_stderr"
+        echo "Non-canonical tmpdir was ${noncanonical_tmp_dir}" >> "$test_stderr"
+        echo "Args: ${args}" >> "$test_stderr"
+        echo "build exit status: $build_exit" >> "$test_stderr"
         max_name_length=$(getconf NAME_MAX ${tmp_dir})
-        echo "Max filename (NAME_MAX): ${max_name_length}" >> "$output"
+        echo "Max filename (NAME_MAX): ${max_name_length}" >> "$test_stderr"
         max_path_length=$(getconf PATH_MAX ${tmp_dir})
-        echo "Max pathlength (PATH_MAX): ${max_path_length}" >> "$output"
+        echo "Max pathlength (PATH_MAX): ${max_path_length}" >> "$test_stderr"
     fi
-    ./$check_cmd "$expected" "$output"
+    ./$check_cmd "$expected_stdout" "$test_stdout" "$expected_stderr" "$test_stderr"
     if [ "$?" = "0" ]; then
         if [ "$good_build" = "no" -o "$good_run" = "yes" ]; then
-          # output == expected
+          # test_stdout == expected_stdout && test_stderr == expected_stderr
           good="yes"
           echo "${test_dir}: succeeded!" 1>&2
         fi
@@ -1071,14 +1100,17 @@
         echo ' '
         echo '#################### info'
         cat "${td_info}" | sed 's/^/# /g'
-        echo '#################### diffs'
+        echo '#################### stdout diffs'
         if [ "$run_checker" == "yes" ]; then
           # Checker failures dump the whole CFG, so we output the whole diff.
-          diff --strip-trailing-cr -u "$expected" "$output"
+          diff --strip-trailing-cr -u "$expected_stdout" "$test_stdout"
         else
-          diff --strip-trailing-cr -u "$expected" "$output" | tail -n 3000
+          diff --strip-trailing-cr -u "$expected_stdout" "$test_stdout" | tail -n 10000
         fi
         echo '####################'
+        echo '#################### stderr diffs'
+        diff --strip-trailing-cr -u "$expected_stderr" "$test_stderr" | tail -n 10000
+        echo '####################'
         if [ "$strace" = "yes" ]; then
             echo '#################### strace output'
             tail -n 3000 "$tmp_dir/$strace_output"
@@ -1087,7 +1119,8 @@
         if [ "x$target_mode" = "xno" -a "x$SANITIZE_HOST" = "xaddress" ]; then
             # Run the stack script to symbolize any ASAN aborts on the host for SANITIZE_HOST. The
             # tools used by the given ABI work for both x86 and x86-64.
-            echo "ABI: 'x86_64'" | cat - "$output" | $ANDROID_BUILD_TOP/development/scripts/stack | tail -n 3000
+            echo "ABI: 'x86_64'" | cat - "$test_stdout" "$test_stderr" \
+              | $ANDROID_BUILD_TOP/development/scripts/stack | tail -n 3000
         fi
         echo ' '
     fi
@@ -1123,7 +1156,7 @@
         $maybe_device_mode \
         --raw-cmd="$raw_cmd" \
         --check-script="$cwd/check" \
-        --expected-output="$cwd/expected.txt" \
+        --expected-output="$cwd/expected-stdout.txt" \
         --logfile="$cwd/bisection_log.txt" \
         --timeout=${timeout:-300}
     fi
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index 6c9447d..40f750b 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -79,14 +79,10 @@
 
 ART_TEST_BISECTION = _getEnvBoolean('ART_TEST_BISECTION', False)
 
-DEX2OAT_HOST_INSTRUCTION_SET_FEATURES = _env.get('DEX2OAT_HOST_INSTRUCTION_SET_FEATURES')
-
 # Do you want run-tests with the host/target's second arch?
 ART_TEST_RUN_TEST_2ND_ARCH = _getEnvBoolean('ART_TEST_RUN_TEST_2ND_ARCH', True)
 
 HOST_2ND_ARCH_PREFIX = _get_build_var('HOST_2ND_ARCH_PREFIX')
-HOST_2ND_ARCH_PREFIX_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES = _env.get(
-  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')
@@ -145,3 +141,5 @@
 
 DIST_DIR = _get_build_var('DIST_DIR')
 SOONG_OUT_DIR = _get_build_var('SOONG_OUT_DIR')
+
+ART_TEST_RUN_ON_ARM_FVP = _getEnvBoolean('ART_TEST_RUN_ON_ARM_FVP', False)
diff --git a/test/testrunner/run_build_test_target.py b/test/testrunner/run_build_test_target.py
index 19f03c3..4191771 100755
--- a/test/testrunner/run_build_test_target.py
+++ b/test/testrunner/run_build_test_target.py
@@ -60,9 +60,22 @@
 n_threads = options.n_threads
 custom_env = target.get('env', {})
 custom_env['SOONG_ALLOW_MISSING_DEPENDENCIES'] = 'true'
+# Switch the build system to unbundled mode in the reduced manifest branch.
+if not os.path.isdir(env.ANDROID_BUILD_TOP + '/frameworks/base'):
+  custom_env['TARGET_BUILD_UNBUNDLED'] = 'true'
 print(custom_env)
 os.environ.update(custom_env)
 
+# always run installclean first remove any old installed files from previous builds.
+# this does not remove intermediate files, so it still avoids recompilation.
+clean_command = 'build/soong/soong_ui.bash --make-mode installclean'
+if env.DIST_DIR:
+  clean_command += ' dist'
+sys.stdout.write(str(clean_command) + '\n')
+sys.stdout.flush()
+if subprocess.call(clean_command.split()):
+  sys.exit(1)
+
 # build is just a binary/script that is directly executed to build any artifacts needed for the
 # test.
 if 'build' in target:
@@ -125,6 +138,8 @@
     run_test_command += ['4']
   if '--no-build-dependencies' not in test_flags:
     run_test_command += ['-b']
+    if env.DIST_DIR:
+      run_test_command += ['--dist']
   run_test_command += ['--verbose']
 
   sys.stdout.write(str(run_test_command) + '\n')
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 831622c..c531d2e 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -61,6 +61,7 @@
   raise
 
 import contextlib
+import csv
 import datetime
 import fnmatch
 import itertools
@@ -74,13 +75,13 @@
 import subprocess
 import sys
 import tempfile
+import threading
 import time
 
 import env
 from target_config import target_config
 from device_config import device_config
 
-# timeout for individual tests.
 # TODO: make it adjustable per tests and for buildbots
 #
 # Note: this needs to be larger than run-test timeouts, as long as this script
@@ -92,6 +93,10 @@
 #                            47m
 timeout = 3600 # 60 minutes
 
+if env.ART_TEST_RUN_ON_ARM_FVP:
+  # Increase timeout to 600 minutes due to the emulation overhead on FVP.
+  timeout = 36000
+
 # DISABLED_TEST_CONTAINER holds information about the disabled tests. It is a map
 # that has key as the test name (like 001-HelloWorld), and value as set of
 # variants that the test is disabled for.
@@ -123,14 +128,17 @@
 skipped_tests = []
 
 # Flags
-n_thread = -1
+n_thread = 0
 total_test_count = 0
 verbose = False
 dry_run = False
 ignore_skips = False
 build = False
+dist = False
 gdb = False
 gdb_arg = ''
+csv_result = None
+csv_writer = None
 runtime_option = ''
 with_agent = []
 zipapex_loc = None
@@ -146,6 +154,72 @@
 # value: set of variants user wants to run of type <key>.
 _user_input_variants = collections.defaultdict(set)
 
+
+class ChildProcessTracker(object):
+  """Keeps track of forked child processes to be able to kill them."""
+
+  def __init__(self):
+    self.procs = {}             # dict from pid to subprocess.Popen object
+    self.mutex = threading.Lock()
+
+  def wait(self, proc, timeout):
+    """Waits on the given subprocess and makes it available to kill_all meanwhile.
+
+    Args:
+      proc: The subprocess.Popen object to wait on.
+      timeout: Timeout passed on to proc.communicate.
+
+    Returns: A tuple of the process stdout output and its return value.
+    """
+    with self.mutex:
+      if self.procs is not None:
+        self.procs[proc.pid] = proc
+      else:
+        os.killpg(proc.pid, signal.SIGKILL) # kill_all has already been called.
+    try:
+      output = proc.communicate(timeout=timeout)[0]
+      return_value = proc.wait()
+      return output, return_value
+    finally:
+      with self.mutex:
+        if self.procs is not None:
+          del self.procs[proc.pid]
+
+  def kill_all(self):
+    """Kills all currently running processes and any future ones."""
+    with self.mutex:
+      for pid in self.procs:
+        os.killpg(pid, signal.SIGKILL)
+      self.procs = None # Make future wait() calls kill their processes immediately.
+
+child_process_tracker = ChildProcessTracker()
+
+
+def setup_csv_result():
+  """Set up the CSV output if required."""
+  global csv_writer
+  csv_writer = csv.writer(csv_result)
+  # Write the header.
+  csv_writer.writerow(['target', 'run', 'prebuild', 'compiler', 'relocate', 'trace', 'gc',
+                       'jni', 'image', 'debuggable', 'jvmti', 'cdex_level', 'test', 'address_size', 'result'])
+
+
+def send_csv_result(test, result):
+  """
+  Write a line into the CSV results file if one is available.
+  """
+  if csv_writer is not None:
+    csv_writer.writerow(extract_test_name(test) + [result])
+
+def close_csv_file():
+  global csv_result
+  global csv_writer
+  if csv_result is not None:
+    csv_writer = None
+    csv_result.flush()
+    csv_result.close()
+    csv_result = None
+
 def gather_test_info():
   """The method gathers test information about the test to be run which includes
   generating the list of total tests from the art/test directory and the list
@@ -240,12 +314,18 @@
     _user_input_variants['address_sizes_target']['target'] = _user_input_variants['address_sizes']
 
   global n_thread
-  if n_thread == -1:
-    if 'target' in _user_input_variants['target']:
-      n_thread = get_default_threads('target')
-    else:
-      n_thread = get_default_threads('host')
-    print_text("Concurrency: " + str(n_thread) + "\n")
+  if 'target' in _user_input_variants['target']:
+    device_name = get_device_name()
+    if n_thread == 0:
+      # Use only half of the cores since fully loading the device tends to lead to timeouts.
+      n_thread = get_target_cpu_count() // 2
+      if device_name == 'fugu':
+        n_thread = 1
+  else:
+    device_name = "host"
+    if n_thread == 0:
+      n_thread = get_host_cpu_count()
+  print_text("Concurrency: {} ({})\n".format(n_thread, device_name))
 
   global extra_arguments
   for target in _user_input_variants['target']:
@@ -279,7 +359,13 @@
                           stdout = subprocess.PIPE,
                           universal_newlines=True)
   # only wait 2 seconds.
-  output = proc.communicate(timeout = 2)[0]
+  timeout_val = 2
+
+  if env.ART_TEST_RUN_ON_ARM_FVP:
+    # Increase timeout to 200 seconds due to the emulation overhead on FVP.
+    timeout_val = 200
+
+  output = proc.communicate(timeout = timeout_val)[0]
   success = not proc.wait()
   if success:
     return output.strip()
@@ -482,14 +568,6 @@
       if address_size == '64':
         options_test += ' --64'
 
-        if env.DEX2OAT_HOST_INSTRUCTION_SET_FEATURES:
-          options_test += ' --instruction-set-features' + env.DEX2OAT_HOST_INSTRUCTION_SET_FEATURES
-
-      elif address_size == '32':
-        if env.HOST_2ND_ARCH_PREFIX_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES:
-          options_test += ' --instruction-set-features ' + \
-                          env.HOST_2ND_ARCH_PREFIX_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES
-
       # TODO(http://36039166): This is a temporary solution to
       # fix build breakages.
       options_test = (' --output-path %s') % (
@@ -510,18 +588,24 @@
         for address_size in _user_input_variants['address_sizes_target'][target]:
           test_futures.append(start_combination(executor, config_tuple, options_all, address_size))
 
-        for config_tuple in uncombinated_config:
-          test_futures.append(start_combination(executor, config_tuple, options_all, ""))  # no address size
+      for config_tuple in uncombinated_config:
+        test_futures.append(
+            start_combination(executor, config_tuple, options_all, ""))  # no address size
 
-      tests_done = 0
-      for test_future in concurrent.futures.as_completed(test_futures):
-        (test, status, failure_info, test_time) = test_future.result()
-        tests_done += 1
-        print_test_info(tests_done, test, status, failure_info, test_time)
-        if failure_info and not env.ART_TEST_KEEP_GOING:
-          for f in test_futures:
-            f.cancel()
-          break
+      try:
+        tests_done = 0
+        for test_future in concurrent.futures.as_completed(test_futures):
+          (test, status, failure_info, test_time) = test_future.result()
+          tests_done += 1
+          print_test_info(tests_done, test, status, failure_info, test_time)
+          if failure_info and not env.ART_TEST_KEEP_GOING:
+            for f in test_futures:
+              f.cancel()
+            break
+      except KeyboardInterrupt:
+        for f in test_futures:
+          f.cancel()
+        child_process_tracker.kill_all()
       executor.shutdown(True)
 
 @contextlib.contextmanager
@@ -541,6 +625,11 @@
   else:
     yield ""
 
+def _popen(**kwargs):
+  if sys.version_info.major == 3 and sys.version_info.minor >= 6:
+    return subprocess.Popen(encoding=sys.stdout.encoding, **kwargs)
+  return subprocess.Popen(**kwargs)
+
 def run_test(command, test, test_variant, test_name):
   """Runs the test.
 
@@ -569,13 +658,22 @@
       if verbose:
         print_text("Starting %s at %s\n" % (test_name, test_start_time))
       if gdb:
-        proc = subprocess.Popen(command.split(), stderr=subprocess.STDOUT,
-                                universal_newlines=True, start_new_session=True)
+        proc = _popen(
+          args=command.split(),
+          stderr=subprocess.STDOUT,
+          universal_newlines=True,
+          start_new_session=True
+        )
       else:
-        proc = subprocess.Popen(command.split(), stderr=subprocess.STDOUT, stdout = subprocess.PIPE,
-                                universal_newlines=True, start_new_session=True)
-      script_output = proc.communicate(timeout=timeout)[0]
-      test_passed = not proc.wait()
+        proc = _popen(
+          args=command.split(),
+          stderr=subprocess.STDOUT,
+          stdout = subprocess.PIPE,
+          universal_newlines=True,
+          start_new_session=True,
+        )
+      script_output, return_value = child_process_tracker.wait(proc, timeout)
+      test_passed = not return_value
       test_time_seconds = time.monotonic() - test_start_time
       test_time = datetime.timedelta(seconds=test_time_seconds)
 
@@ -695,6 +793,7 @@
           progress_info,
           test_name,
           result_text)
+    send_csv_result(test_name, result)
     print_text(info)
   except Exception as e:
     print_text(('%s\n%s\n') % (test_name, str(e)))
@@ -894,6 +993,32 @@
     for failed_test in sorted([test_info[0] for test_info in failed_tests]):
       print_text(('%s\n' % (failed_test)))
 
+test_name_matcher = None
+def extract_test_name(test_name):
+  """Parses the test name and returns all the parts"""
+  global test_name_matcher
+  if test_name_matcher is None:
+    regex = '^test-art-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['target']) + ')-'
+    regex += 'run-test-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['run']) + ')-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['prebuild']) + ')-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['compiler']) + ')-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['relocate']) + ')-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['trace']) + ')-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['gc']) + ')-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['jni']) + ')-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['image']) + ')-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['debuggable']) + ')-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['jvmti']) + ')-'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['cdex_level']) + ')-'
+    regex += '(' + '|'.join(RUN_TEST_SET) + ')'
+    regex += '(' + '|'.join(VARIANT_TYPE_DICT['address_sizes']) + ')$'
+    test_name_matcher = re.compile(regex)
+  match = test_name_matcher.match(test_name)
+  if match:
+    return list(match.group(i) for i in range(1,15))
+  raise ValueError(test_name + " is not a valid test")
 
 def parse_test_name(test_name):
   """Parses the testname provided by the user.
@@ -913,75 +1038,41 @@
   if test_set:
     return test_set
 
-  regex = '^test-art-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['target']) + ')-'
-  regex += 'run-test-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['run']) + ')-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['prebuild']) + ')-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['compiler']) + ')-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['relocate']) + ')-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['trace']) + ')-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['gc']) + ')-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['jni']) + ')-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['image']) + ')-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['debuggable']) + ')-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['jvmti']) + ')-'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['cdex_level']) + ')-'
-  regex += '(' + '|'.join(RUN_TEST_SET) + ')'
-  regex += '(' + '|'.join(VARIANT_TYPE_DICT['address_sizes']) + ')$'
-  match = re.match(regex, test_name)
+  parsed = extract_test_name(test_name)
+  _user_input_variants['target'].add(parsed[0])
+  _user_input_variants['run'].add(parsed[1])
+  _user_input_variants['prebuild'].add(parsed[2])
+  _user_input_variants['compiler'].add(parsed[3])
+  _user_input_variants['relocate'].add(parsed[4])
+  _user_input_variants['trace'].add(parsed[5])
+  _user_input_variants['gc'].add(parsed[6])
+  _user_input_variants['jni'].add(parsed[7])
+  _user_input_variants['image'].add(parsed[8])
+  _user_input_variants['debuggable'].add(parsed[9])
+  _user_input_variants['jvmti'].add(parsed[10])
+  _user_input_variants['cdex_level'].add(parsed[11])
+  _user_input_variants['address_sizes'].add(parsed[13])
+  return {parsed[12]}
+
+
+def get_target_cpu_count():
+  adb_command = 'adb shell cat /sys/devices/system/cpu/present'
+  cpu_info_proc = subprocess.Popen(adb_command.split(), stdout=subprocess.PIPE)
+  cpu_info = cpu_info_proc.stdout.read()
+  if type(cpu_info) is bytes:
+    cpu_info = cpu_info.decode('utf-8')
+  cpu_info_regex = r'\d*-(\d*)'
+  match = re.match(cpu_info_regex, cpu_info)
   if match:
-    _user_input_variants['target'].add(match.group(1))
-    _user_input_variants['run'].add(match.group(2))
-    _user_input_variants['prebuild'].add(match.group(3))
-    _user_input_variants['compiler'].add(match.group(4))
-    _user_input_variants['relocate'].add(match.group(5))
-    _user_input_variants['trace'].add(match.group(6))
-    _user_input_variants['gc'].add(match.group(7))
-    _user_input_variants['jni'].add(match.group(8))
-    _user_input_variants['image'].add(match.group(9))
-    _user_input_variants['debuggable'].add(match.group(10))
-    _user_input_variants['jvmti'].add(match.group(11))
-    _user_input_variants['cdex_level'].add(match.group(12))
-    _user_input_variants['address_sizes'].add(match.group(14))
-    return {match.group(13)}
-  raise ValueError(test_name + " is not a valid test")
-
-
-def setup_env_for_build_target(build_target, parser, options):
-  """Setup environment for the build target
-
-  The method setup environment for the master-art-host targets.
-  """
-  os.environ.update(build_target['env'])
-  os.environ['SOONG_ALLOW_MISSING_DEPENDENCIES'] = 'true'
-  print_text('%s\n' % (str(os.environ)))
-
-  target_options = vars(parser.parse_args(build_target['flags']))
-  target_options['host'] = True
-  target_options['verbose'] = True
-  target_options['build'] = True
-  target_options['n_thread'] = options['n_thread']
-  target_options['dry_run'] = options['dry_run']
-
-  return target_options
-
-def get_default_threads(target):
-  if target == 'target':
-    adb_command = 'adb shell cat /sys/devices/system/cpu/present'
-    cpu_info_proc = subprocess.Popen(adb_command.split(), stdout=subprocess.PIPE)
-    cpu_info = cpu_info_proc.stdout.read()
-    if type(cpu_info) is bytes:
-      cpu_info = cpu_info.decode('utf-8')
-    cpu_info_regex = r'\d*-(\d*)'
-    match = re.match(cpu_info_regex, cpu_info)
-    if match:
-      return int(match.group(1))
-    else:
-      raise ValueError('Unable to predict the concurrency for the target. '
-                       'Is device connected?')
+    return int(match.group(1)) + 1  # Add one to convert from "last-index" to "count"
   else:
-    return multiprocessing.cpu_count()
+    raise ValueError('Unable to predict the concurrency for the target. '
+                     'Is device connected?')
+
+
+def get_host_cpu_count():
+  return multiprocessing.cpu_count()
+
 
 def parse_option():
   global verbose
@@ -989,6 +1080,7 @@
   global ignore_skips
   global n_thread
   global build
+  global dist
   global gdb
   global gdb_arg
   global runtime_option
@@ -998,12 +1090,14 @@
   global run_all_configs
   global with_agent
   global zipapex_loc
+  global csv_result
 
   parser = argparse.ArgumentParser(description="Runs all or a subset of the ART test suite.")
   parser.add_argument('-t', '--test', action='append', dest='tests', help='name(s) of the test(s)')
   global_group = parser.add_argument_group('Global options',
                                            'Options that affect all tests being run')
-  global_group.add_argument('-j', type=int, dest='n_thread')
+  global_group.add_argument('-j', type=int, dest='n_thread', help="""Number of CPUs to use.
+                            Defaults to half of CPUs on target and all CPUs on host.""")
   global_group.add_argument('--timeout', default=timeout, type=int, dest='timeout')
   global_group.add_argument('--verbose', '-v', action='store_true', dest='verbose')
   global_group.add_argument('--dry-run', action='store_true', dest='dry_run')
@@ -1020,7 +1114,11 @@
                             action='store_true', dest='build',
                             help="""Build dependencies under all circumstances. By default we will
                             not build dependencies unless ART_TEST_RUN_TEST_BUILD=true.""")
-  global_group.add_argument('--build-target', dest='build_target', help='master-art-host targets')
+  global_group.add_argument('--dist',
+                            action='store_true', dest='dist',
+                            help="""If dependencies are to be built, pass `dist` to the build
+                            command line. You may want to also set the DIST_DIR environment
+                            variable when using this flag.""")
   global_group.set_defaults(build = env.ART_TEST_RUN_TEST_BUILD)
   global_group.add_argument('--gdb', action='store_true', dest='gdb')
   global_group.add_argument('--gdb-arg', dest='gdb_arg')
@@ -1042,6 +1140,8 @@
                             help='Location for runtime zipapex.')
   global_group.add_argument('-a', '--all', action='store_true', dest='run_all',
                             help="Run all the possible configurations for the input test set")
+  global_group.add_argument('--csv-results', action='store', dest='csv_result', default=None,
+                            type=argparse.FileType('w'), help='Store a CSV record of all results.')
   for variant_type, variant_set in VARIANT_TYPE_DICT.items():
     var_group = parser.add_argument_group(
         '{}-type Options'.format(variant_type),
@@ -1055,16 +1155,15 @@
       var_group.add_argument(flag, action='store_true', dest=variant)
 
   options = vars(parser.parse_args())
+  if options['csv_result'] is not None:
+    csv_result = options['csv_result']
+    setup_csv_result()
   # Handle the --all-<type> meta-options
   for variant_type, variant_set in VARIANT_TYPE_DICT.items():
     if options['all_' + variant_type]:
       for variant in variant_set:
         options[variant] = True
 
-  if options['build_target']:
-    options = setup_env_for_build_target(target_config[options['build_target']],
-                                         parser, options)
-
   tests = None
   env.EXTRA_DISABLED_TESTS.update(set(options['skips']))
   if options['tests']:
@@ -1086,6 +1185,7 @@
     dry_run = True
     verbose = True
   build = options['build']
+  dist = options['dist']
   if options['gdb']:
     n_thread = 1
     gdb = True
@@ -1119,7 +1219,10 @@
       build_targets += 'test-art-host-run-test-dependencies '
     build_command = env.ANDROID_BUILD_TOP + '/build/soong/soong_ui.bash --make-mode'
     build_command += ' DX='
+    if dist:
+      build_command += ' dist'
     build_command += ' ' + build_targets
+    print_text('Build command: %s\n' % build_command)
     if subprocess.call(build_command.split()):
       # Debugging for b/62653020
       if env.DIST_DIR:
@@ -1132,6 +1235,7 @@
     run_tests(RUN_TEST_SET)
 
   print_analysis()
+  close_csv_file()
 
   exit_code = 0 if len(failed_tests) == 0 else 1
   sys.exit(exit_code)
diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc
index 28265fc..cc83ad3 100644
--- a/test/ti-agent/common_load.cc
+++ b/test/ti-agent/common_load.cc
@@ -84,6 +84,7 @@
   { "943-private-recursive-jit", common_redefine::OnLoad, nullptr },
   { "1919-vminit-thread-start-timing", Test1919VMInitThreadStart::OnLoad, nullptr },
   { "2031-zygote-compiled-frame-deopt", nullptr, MinimalOnLoad },
+  { "2039-load-transform-larger", common_retransform::OnLoad, nullptr },
 };
 
 static AgentLib* FindAgent(char* name) {
diff --git a/test/utils/regen-test-files b/test/utils/regen-test-files
new file mode 100755
index 0000000..3fe9bac
--- /dev/null
+++ b/test/utils/regen-test-files
@@ -0,0 +1,987 @@
+#! /usr/bin/env python3
+#
+# Copyright 2020 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.
+
+# Regenerate some ART test related files.
+
+# This script handles only a subset of ART run-tests at the moment; additional
+# cases will be added later.
+
+import argparse
+import collections
+import json
+import logging
+import os
+import re
+import sys
+import textwrap
+import xml.dom.minidom
+
+logging.basicConfig(format='%(levelname)s: %(message)s')
+
+ME = os.path.basename(sys.argv[0])
+
+# Common advisory placed at the top of all generated files.
+ADVISORY = f"Generated by `{ME}`. Do not edit manually."
+
+# Default indentation unit.
+INDENT = "  "
+
+# Indentation unit for XML files.
+XML_INDENT = "    "
+
+def reindent(str, indent = ""):
+  """Reindent literal string while removing common leading spaces."""
+  return textwrap.indent(textwrap.dedent(str), indent)
+
+def copyright_header_text(year):
+  """Return the copyright header text used in XML files."""
+  return reindent(f"""\
+    Copyright (C) {year} 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.
+    """, " ")
+
+def split_list(l, n):
+  """Return a list of `n` sublists of (contiguous) elements of list `l`."""
+  assert n > 0
+  (d, m) = divmod(len(l), n)
+  # If the length of `l` is divisible by `n`, use that that divisor (`d`) as size of each sublist;
+  # otherwise, the next integer value (`d + 1`).
+  s = d if m == 0 else d + 1
+  result = [l[i:i + s] for i in range(0, len(l), s)]
+  assert len(result) == n
+  return result
+
+# The prefix used in the Soong module name of all ART run-tests.
+ART_RUN_TEST_MODULE_NAME_PREFIX = "art-run-test-"
+
+# Number of shards used to declare ART run-tests in the sharded ART MTS test plan.
+NUM_MTS_ART_RUN_TEST_SHARDS = 1
+
+# Known failing ART run-tests.
+# TODO(rpl): Investigate and address the causes of failures.
+known_failing_tests = [
+  "004-SignalTest",
+  "004-UnsafeTest",
+  "030-bad-finalizer",
+  "034-call-null",
+  "038-inner-null",
+  "044-proxy",
+  "051-thread",
+  "054-uncaught",
+  "086-null-super",
+  "087-gc-after-link",
+  "096-array-copy-concurrent-gc",
+  "1004-checker-volatile-ref-load",
+  "115-native-bridge",
+  "116-nodex2oat",
+  "1336-short-finalizer-timeout",
+  "1337-gc-coverage",
+  "1339-dead-reference-safe",
+  "134-nodex2oat-nofallback",
+  "136-daemon-jni-shutdown",
+  "139-register-natives",
+  "148-multithread-gc-annotations",
+  "149-suspend-all-stress",
+  "150-loadlibrary",
+  "154-gc-loop",
+  "158-app-image-class-table",
+  "169-threadgroup-jni",
+  "172-app-image-twice",
+  "177-visibly-initialized-deadlock",
+  "178-app-image-native-method",
+  "179-nonvirtual-jni",
+  "450-checker-types",
+  "1900-track-alloc",
+  "1901-get-bytecodes",
+  "1902-suspend",
+  "1903-suspend-self",
+  "1904-double-suspend",
+  "1905-suspend-native",
+  "1906-suspend-list-me-first",
+  "1907-suspend-list-self-twice",
+  "1908-suspend-native-resume-self",
+  "1909-per-agent-tls",
+  "1910-transform-with-default",
+  "1911-get-local-var-table",
+  "1912-get-set-local-primitive",
+  "1913-get-set-local-objects",
+  "1914-get-local-instance",
+  "1915-get-set-local-current-thread",
+  "1916-get-set-current-frame",
+  "1917-get-stack-frame",
+  "1919-vminit-thread-start-timing",
+  "1920-suspend-native-monitor",
+  "1921-suspend-native-recursive-monitor",
+  "1922-owned-monitors-info",
+  "1923-frame-pop",
+  "1924-frame-pop-toggle",
+  "1925-self-frame-pop",
+  "1926-missed-frame-pop",
+  "1927-exception-event",
+  "1928-exception-event-exception",
+  "1930-monitor-info",
+  "1931-monitor-events",
+  "1932-monitor-events-misc",
+  "1933-monitor-current-contended",
+  "1934-jvmti-signal-thread",
+  "1935-get-set-current-frame-jit",
+  "1936-thread-end-events",
+  "1937-transform-soft-fail",
+  "1938-transform-abstract-single-impl",
+  "1939-proxy-frames",
+  "1941-dispose-stress",
+  "1942-suspend-raw-monitor-exit",
+  "1943-suspend-raw-monitor-wait",
+  "1945-proxy-method-arguments",
+  "1947-breakpoint-redefine-deopt",
+  "1949-short-dex-file",
+  "1951-monitor-enter-no-suspend",
+  "1953-pop-frame",
+  "1954-pop-frame-jit",
+  "1955-pop-frame-jit-called",
+  "1956-pop-frame-jit-calling",
+  "1957-error-ext",
+  "1958-transform-try-jit",
+  "1959-redefine-object-instrument",
+  "1960-obsolete-jit-multithread-native",
+  "1961-obsolete-jit-multithread",
+  "1962-multi-thread-events",
+  "1963-add-to-dex-classloader-in-memory",
+  "1967-get-set-local-bad-slot",
+  "1968-force-early-return",
+  "1969-force-early-return-void",
+  "1970-force-early-return-long",
+  "1971-multi-force-early-return",
+  "1972-jni-id-swap-indices",
+  "1973-jni-id-swap-pointer",
+  "1974-resize-array",
+  "1975-hello-structural-transformation",
+  "1976-hello-structural-static-methods",
+  "1977-hello-structural-obsolescence",
+  "1978-regular-obsolete-then-structural-obsolescence",
+  "1979-threaded-structural-transformation",
+  "1980-obsolete-object-cleared",
+  "1982-no-virtuals-structural-redefinition",
+  "1984-structural-redefine-field-trace",
+  "1985-structural-redefine-stack-scope",
+  "1986-structural-redefine-multi-thread-stack-scope",
+  "1987-structural-redefine-recursive-stack-scope",
+  "1988-multi-structural-redefine",
+  "1989-transform-bad-monitor",
+  "1990-structural-bad-verify",
+  "1991-hello-structural-retransform",
+  "1992-retransform-no-such-field",
+  "1993-fallback-non-structural",
+  "1994-final-virtual-structural",
+  "1995-final-virtual-structural-multithread",
+  "1996-final-override-virtual-structural",
+  "1997-structural-shadow-method",
+  "1998-structural-shadow-field",
+  "1999-virtual-structural",
+  "2003-double-virtual-structural",
+  "2004-double-virtual-structural-abstract",
+  "2005-pause-all-redefine-multithreaded",
+  "2008-redefine-then-old-reflect-field",
+  "2011-stack-walk-concurrent-instrument",
+  "203-multi-checkpoint",
+  "2031-zygote-compiled-frame-deopt",
+  "2033-shutdown-mechanics",
+  "2036-jni-filechannel",
+  "2037-thread-name-inherit",
+  "305-other-fault-handler",
+  "449-checker-bce",
+  "454-get-vreg",
+  "461-get-reference-vreg",
+  "466-get-live-vreg",
+  "497-inlining-and-class-loader",
+  "530-regression-lse",
+  "555-UnsafeGetLong-regression",
+  "566-polymorphic-inlining",
+  "595-profile-saving",
+  "597-deopt-busy-loop",
+  "597-deopt-invoke-stub",
+  "597-deopt-new-string",
+  "602-deoptimizeable",
+  "604-hot-static-interface",
+  "616-cha-abstract",
+  "616-cha-interface",
+  "616-cha-miranda",
+  "616-cha-native",
+  "616-cha-regression-proxy-method",
+  "616-cha",
+  "623-checker-loop-regressions",
+  "626-set-resolved-string",
+  "629-vdex-speed",
+  "638-checker-inline-cache-intrinsic",
+  "642-fp-callees",
+  "647-jni-get-field-id",
+  "652-deopt-intrinsic",
+  "655-jit-clinit",
+  "656-loop-deopt",
+  "660-clinit",
+  "661-oat-writer-layout",
+  "664-aget-verifier",
+  "667-jit-jni-stub",
+  "674-hotness-compiled",
+  "679-locks",
+  "680-checker-deopt-dex-pc-0",
+  "685-deoptimizeable",
+  "687-deopt",
+  "689-zygote-jit-deopt",
+  "693-vdex-inmem-loader-evict",
+  "707-checker-invalid-profile",
+  "708-jit-cache-churn",
+  "717-integer-value-of",
+  "720-thread-priority",
+  # 728-imt-conflict-zygote: Custom `run` script + dependency on `libarttest`.
+  "728-imt-conflict-zygote",
+  # 730-cha-deopt: Fails with:
+  #
+  #   Test command execution failed with status FAILED: CommandResult: exit code=1, out=, err=Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
+  #           at Main.main(Main.java:24)
+  #
+  "730-cha-deopt",
+  # 813-fp-args: Dependency on `libarttest`.
+  "813-fp-args",
+  # 821-many-args: Fails with:
+  #
+  #   Test command execution failed with status FAILED: CommandResult: exit code=1, out=, err=Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
+  #           at Main.main(Main.java:20)
+  #
+  "821-many-args",
+  "900-hello-plugin",
+  "901-hello-ti-agent",
+  "902-hello-transformation",
+  "903-hello-tagging",
+  "904-object-allocation",
+  "905-object-free",
+  "906-iterate-heap",
+  "907-get-loaded-classes",
+  "908-gc-start-finish",
+  "910-methods",
+  "911-get-stack-trace",
+  "913-heaps",
+  "914-hello-obsolescence",
+  "915-obsolete-2",
+  "916-obsolete-jit",
+  "917-fields-transformation",
+  "918-fields",
+  "919-obsolete-fields",
+  "920-objects",
+  "921-hello-failure",
+  "922-properties",
+  "923-monitors",
+  "924-threads",
+  "925-threadgroups",
+  "926-multi-obsolescence",
+  "927-timers",
+  "928-jni-table",
+  "930-hello-retransform",
+  "931-agent-thread",
+  "932-transform-saves",
+  "933-misc-events",
+  "937-hello-retransform-package",
+  "939-hello-transformation-bcp",
+  "940-recursive-obsolete",
+  "941-recursive-obsolete-jit",
+  "942-private-recursive",
+  "943-private-recursive-jit",
+  "944-transform-classloaders",
+  "945-obsolete-native",
+  "946-obsolete-throw",
+  "947-reflect-method",
+  "949-in-memory-transform",
+  "950-redefine-intrinsic",
+  "951-threaded-obsolete",
+  "982-ok-no-retransform",
+  "983-source-transform-verify",
+  "984-obsolete-invoke",
+  "985-re-obsolete",
+  "986-native-method-bind",
+  "987-agent-bind",
+  "988-method-trace",
+  "989-method-trace-throw",
+  "990-field-trace",
+  "991-field-trace-2",
+  "992-source-data",
+  "993-breakpoints",
+  "994-breakpoint-line",
+  "995-breakpoints-throw",
+  "996-breakpoint-obsolete",
+  "997-single-step",
+]
+
+# More known failing tests, related to Checker.
+# TODO(rpl): Investigate and address the causes of failures.
+known_failing_tests.extend([
+  # Fails (on flame-userdebug) with:
+  #
+  #   java.lang.RuntimeException: Error running Checker
+  #   error: Statement could not be matched starting from line 564575
+  #   RemTest.java:289: lsr x{{\d+}}, x{{\d+}}, #32
+  #   ISA_FEATURES = {'a53': True, 'crc': True, 'lse': False, 'fp16': False, 'dotprod': False, 'sve': False}
+  #
+  "411-checker-hdiv-hrem-const",
+  # Fails (on aosp_cf_x86_phone-userdebug) with:
+  #
+  #   Error while running Checker: java.lang.RuntimeException: Error running Checker command:
+  #   error: Statement could not be matched starting from line 317325
+  #   Main.java:296: InvokeStaticOrDirect
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #   NewInstance  = l6
+  #
+  "476-checker-ctor-fence-redun-elim",
+  # Fails (on aosp_cf_x86_phone-userdebug) with:
+  #
+  #   Error while running Checker: java.lang.RuntimeException: Error running Checker command:
+  #   error: Statement could not be matched starting from line 264874
+  #   Main.java:77: InvokeStaticOrDirect [{{([ij]\d+,)?}}<<ClinitCheck>>]
+  #   ClinitCheck  = l4
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #   LoadClass    = l3
+  #
+  "478-checker-clinit-check-pruning",
+  # Fails (on aosp_cf_x86_phone-userdebug) with:
+  #
+  #   Error while running Checker: java.lang.RuntimeException: Error running Checker command:
+  #   error: Statement could not be matched starting from line 124181
+  #   Main.java:178: <<Arg:z\d+>>  StaticFieldGet  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>]
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #
+  "482-checker-loop-back-edge-use",
+  # Fails (on aosp_cf_x86_phone-userdebug) with:
+  #
+  #   Error while running Checker: java.lang.RuntimeException: Error running Checker command:
+  #   error: Statement could not be matched starting from line 7333
+  #   Main.java:66: <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->e(bp|si|di)}}
+  #   Arg          = i0
+  #   Const1       = i3
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #
+  "526-checker-caller-callee-regs",
+  # Fails (on aosp_cf_x86_phone-userdebug) with:
+  #
+  #   Error while running Checker: java.lang.RuntimeException: Error running Checker command:
+  #   error: NOT statement matched line 379347
+  #   Main.java:538: NewInstance
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #
+  "530-checker-lse",
+  # Fails (on cf_x86_phone-userdebug_coverage) with:
+  #
+  #   error: NOT statement matched line 117078
+  #   Main.java:108: NewInstance
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #
+  "530-checker-lse2",
+  # Fails (on aosp_cf_x86_phone-userdebug) with:
+  #
+  #   Error while running Checker: java.lang.RuntimeException: Error running Checker command:
+  #   error: NOT statement matched line 238857
+  #   Main.java:650: Shl
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #
+  "551-checker-shifter-operand",
+  # Fails (on aosp_cf_x86_phone-userdebug) with:
+  #
+  #   Error while running Checker: java.lang.RuntimeException: Error running Checker command:
+  #   error: Statement could not be matched starting from line 158575
+  #   Main.java:97: X86ComputeBaseMethodAddress
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #
+  "552-checker-sharpening",
+  # Fails (on flame-userdebug) with:
+  #
+  #   java.lang.RuntimeException: Error running Checker
+  #   error: Statement could not be matched starting from line 11964
+  #   Main.java:59: <<ConstM42:i\d+>>      IntConstant -42
+  #   ISA_FEATURES = {'a53': True, 'crc': True, 'lse': False, 'fp16': False, 'dotprod': False, 'sve': False}
+  #
+  #
+  "562-checker-no-intermediate",
+  # Fails (on cf_x86_phone-userdebug_coverage) with:
+  #
+  #   error: Statement could not be matched starting from line 5260
+  #   Main.java:24: InstanceFieldSet
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #
+  "583-checker-zero",
+  # Fails (on aosp_cf_x86_phone-userdebug) with:
+  #
+  #   Error while running Checker: java.lang.RuntimeException: Error running Checker command:
+  #   error: Statement could not be matched starting from line 149082
+  #   Main.java:312: <<LoadClass:l\d+>>   LoadClass class_name:Main
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #   Int42        = i8
+  #   Int43        = i10
+  #
+  "639-checker-code-sinking",
+  # Fails (on aosp_cf_x86_phone-userdebug) with:
+  #
+  #   error: Statement could not be matched starting from line 12527
+  #   Main.java:24: InvokeVirtual method_name:java.lang.StringBuilder.toString intrinsic:StringBuilderToString
+  #   ISA_FEATURES = {'ssse3': True, 'sse4': False}
+  #
+  "729-checker-polymorphic-intrinsic",
+])
+
+known_failing_tests = frozenset(known_failing_tests)
+
+# Percentage of ART run-tests (among the ones expected to succeed) to include in
+# the `presubmit` test group in `TEST_MAPPING` file -- the rest will be included
+# in `postsubmit` test group.
+# This value has to be a number between 0 and 100.
+presubmit_tests_percentage = 100
+
+# Percentage of ART run-tests (among the ones expected to succeed) to include in
+# the `mainline-presubmit` test group in `TEST_MAPPING` file.
+# This value has to be a number between 0 and 100.
+mainline_presubmit_tests_percentage = 100
+
+# ART gtests that do not need root access to the device.
+art_gtest_user_module_names = [
+    "art_standalone_cmdline_tests",
+    "art_standalone_compiler_tests",
+    "art_standalone_dex2oat_tests",
+    "art_standalone_dexdump_tests",
+    "art_standalone_dexlist_tests",
+    "art_standalone_libartbase_tests",
+    "art_standalone_libartpalette_tests",
+    "art_standalone_libdexfile_support_tests",
+    "art_standalone_libdexfile_tests",
+    "art_standalone_libprofile_tests",
+    "art_standalone_oatdump_tests",
+    "art_standalone_odrefresh_tests",
+    "art_standalone_runtime_compiler_tests",
+    "art_standalone_runtime_tests",
+    "art_standalone_sigchain_tests",
+]
+
+# ART gtests that need root access to the device.
+art_gtest_eng_only_module_names = [
+    "art_standalone_dexoptanalyzer_tests",
+    "art_standalone_profman_tests",
+]
+
+# All supported ART gtests.
+art_gtest_module_names = sorted(art_gtest_user_module_names + art_gtest_eng_only_module_names)
+
+
+# Is `run_test` a Checker test (i.e. a test containing Checker
+# assertions)?
+def is_checker_test(run_test):
+  return re.match("^[0-9]+-checker-", run_test)
+
+# Is `run_test` expected to succeed?
+def is_expected_succeeding(run_test):
+  return run_test not in known_failing_tests
+
+
+class Generator:
+  def __init__(self, top_dir):
+    """Generator of ART test files for an Android source tree anchored at `top_dir`."""
+    # Path to the Android top source tree.
+    self.top_dir = top_dir
+    # Path to the ART directory
+    self.art_dir = os.path.join(top_dir, "art")
+    # Path to the ART tests directory.
+    self.art_test_dir = os.path.join(self.art_dir, "test")
+    # Path to the MTS configuration directory.
+    self.mts_config_dir = os.path.join(
+        top_dir, "test", "mts", "tools", "mts-tradefed", "res", "config")
+
+  def enumerate_run_tests(self):
+    return sorted([run_test
+                   for run_test in os.listdir(self.art_test_dir)
+                   if re.match("^[0-9]{3,}-", run_test)])
+
+  # Is building `run_test` supported?
+  # TODO(b/147814778): Add build support for more tests.
+  def is_buildable(self, run_test):
+    run_test_path = os.path.join(self.art_test_dir, run_test)
+
+    # Ignore tests with non-default build rules.
+    if os.path.isfile(os.path.join(run_test_path, "build")):
+      return False
+    # Ignore tests with no `src` directory.
+    if not os.path.isdir(os.path.join(run_test_path, "src")):
+      return False
+    # Ignore tests with sources outside the `src` directory.
+    for subdir in ["jasmin",
+                   "jasmin-multidex",
+                   "smali",
+                   "smali-ex",
+                   "smali-multidex",
+                   "src-art",
+                   "src-dex2oat-unresolved",
+                   "src-ex",
+                   "src-ex2",
+                   "src-multidex",
+                   "src2"]:
+      if os.path.isdir(os.path.join(run_test_path, subdir)):
+        return False
+    # Ignore test with a copy of `sun.misc.Unsafe`.
+    if os.path.isfile(os.path.join(run_test_path, "src", "sun", "misc", "Unsafe.java")):
+      return False
+    # Ignore tests with Hidden API specs.
+    if os.path.isfile(os.path.join(run_test_path, "hiddenapi-flags.csv")):
+      return False
+    # All other tests are considered buildable.
+    return True
+
+  def regen_bp_files(self, run_tests, buildable_tests):
+    for run_test in run_tests:
+      # Remove any previously generated file.
+      bp_file = os.path.join(self.art_test_dir, run_test, "Android.bp")
+      if os.path.exists(bp_file):
+        logging.debug(f"Removing `{bp_file}`.")
+        os.remove(bp_file)
+
+    for run_test in buildable_tests:
+      self.regen_bp_file(run_test)
+
+  def regen_bp_file(self, run_test):
+    """Regenerate Blueprint file for an ART run-test."""
+
+    bp_file = os.path.join(self.art_test_dir, run_test, "Android.bp")
+
+    run_test_module_name = ART_RUN_TEST_MODULE_NAME_PREFIX + run_test
+
+    if is_expected_succeeding(run_test):
+      test_config_template = "art-run-test-target-template"
+    else:
+      test_config_template = "art-run-test-target-no-test-suite-tag-template"
+
+    if is_checker_test(run_test):
+      include_src = """\
+
+          // Include the Java source files in the test's artifacts, to make Checker assertions
+          // available to the TradeFed test runner.
+          include_srcs: true,"""
+    else:
+      include_src = ""
+    with open(bp_file, "w") as f:
+      logging.debug(f"Writing `{bp_file}`.")
+      f.write(textwrap.dedent(f"""\
+      // {ADVISORY}
+
+      // Build rules for ART run-test `{run_test}`.
+
+      package {{
+          // See: http://go/android-license-faq
+          // A large-scale-change added 'default_applicable_licenses' to import
+          // all of the 'license_kinds' from "art_license"
+          // to get the below license kinds:
+          //   SPDX-license-identifier-Apache-2.0
+          default_applicable_licenses: ["art_license"],
+      }}
+
+      // Test's Dex code.
+      java_test {{
+          name: "{run_test_module_name}",
+          defaults: ["art-run-test-defaults"],
+          test_config_template: ":{test_config_template}",
+          srcs: ["src/**/*.java"],
+          data: [
+              ":{run_test_module_name}-expected-stdout",
+              ":{run_test_module_name}-expected-stderr",
+          ],{include_src}
+      }}
+
+      // Test's expected standard output.
+      genrule {{
+          name: "{run_test_module_name}-expected-stdout",
+          out: ["{run_test_module_name}-expected-stdout.txt"],
+          srcs: ["expected-stdout.txt"],
+          cmd: "cp -f $(in) $(out)",
+      }}
+
+      // Test's expected standard error.
+      genrule {{
+          name: "{run_test_module_name}-expected-stderr",
+          out: ["{run_test_module_name}-expected-stderr.txt"],
+          srcs: ["expected-stderr.txt"],
+          cmd: "cp -f $(in) $(out)",
+      }}
+      """))
+
+  def regen_test_mapping_file(self, art_run_tests, num_presubmit_run_tests,
+                              num_mainline_presubmit_run_tests):
+    """Regenerate ART's `TEST_MAPPING`."""
+
+    run_test_module_names = [ART_RUN_TEST_MODULE_NAME_PREFIX + t for t in art_run_tests]
+
+    # Mainline presubmits.
+    mainline_presubmit_run_tests = run_test_module_names[0:num_mainline_presubmit_run_tests]
+    mainline_presubmit_tests = mainline_presubmit_run_tests + art_gtest_module_names
+    mainline_presubmit_tests_with_apex = [t + "[com.google.android.art.apex]"
+                                          for t
+                                          in mainline_presubmit_tests]
+    mainline_presubmit_tests_dict = [{"name": t} for t in mainline_presubmit_tests_with_apex]
+
+    # Presubmits.
+    other_presubmit_tests = [
+        "CtsJdwpTestCases",
+        "BootImageProfileTest",
+    ]
+    presubmit_run_tests = run_test_module_names[0:num_presubmit_run_tests]
+    presubmit_tests = other_presubmit_tests + presubmit_run_tests + art_gtest_module_names
+    presubmit_tests_dict = [{"name": t} for t in presubmit_tests]
+
+    # Postsubmits.
+    postsubmit_run_tests = run_test_module_names[num_presubmit_run_tests:]
+    postsubmit_tests_dict = [{"name": t} for t in postsubmit_run_tests]
+
+    # Use an `OrderedDict` container to preserve the order in which items are inserted.
+    # Do not produce an entry for a test group if it is empty.
+    test_mapping_dict = collections.OrderedDict([
+        (test_group_name, test_group_dict)
+        for (test_group_name, test_group_dict)
+        in [
+            ("mainline-presubmit", mainline_presubmit_tests_dict),
+            ("presubmit", presubmit_tests_dict),
+            ("postsubmit", postsubmit_tests_dict),
+        ]
+        if test_group_dict
+    ])
+    test_mapping_contents = json.dumps(test_mapping_dict, indent = INDENT)
+
+    test_mapping_file = os.path.join(self.art_dir, "TEST_MAPPING")
+    with open(test_mapping_file, "w") as f:
+      logging.debug(f"Writing `{test_mapping_file}`.")
+      f.write(f"// {ADVISORY}\n")
+      f.write(test_mapping_contents)
+      f.write("\n")
+
+  def create_mts_test_shard(self, description, tests, shard_num, copyright_year, comments = []):
+    """Factory method instantiating an `MtsTestShard`."""
+    return self.MtsTestShard(self.mts_config_dir,
+                             description, tests, shard_num, copyright_year, comments)
+
+  class MtsTestShard:
+    """Class encapsulating data and generation logic for an ART MTS test shard."""
+
+    def __init__(self, mts_config_dir, description, tests, shard_num, copyright_year, comments):
+      self.mts_config_dir = mts_config_dir
+      self.description = description
+      self.tests = tests
+      self.shard_num = shard_num
+      self.copyright_year = copyright_year
+      self.comments = comments
+
+    def shard_id(self):
+      return f"{self.shard_num:02}"
+
+    def test_plan_name(self):
+      return "mts-art-shard-" + self.shard_id()
+
+    def test_list_name(self):
+      return "mts-art-tests-list-user-shard-" + self.shard_id()
+
+    def regen_test_plan_file(self):
+      """Regenerate ART MTS test plan file shard (`mts-art-shard-<shard_num>.xml`)."""
+      root = xml.dom.minidom.Document()
+
+      advisory_header = root.createComment(f" {ADVISORY} ")
+      root.appendChild(advisory_header)
+      copyright_header = root.createComment(copyright_header_text(self.copyright_year))
+      root.appendChild(copyright_header)
+
+      configuration = root.createElement("configuration")
+      root.appendChild(configuration)
+      configuration.setAttribute(
+          "description",
+          f"Run mts-art-shard-{self.shard_id()} from a preexisting MTS installation.")
+
+      # Included XML files.
+      included_xml_files = ["mts", self.test_list_name()]
+      for xml_file in included_xml_files:
+        include = root.createElement("include")
+        include.setAttribute("name", xml_file)
+        configuration.appendChild(include)
+
+      # Test plan name.
+      option = root.createElement("option")
+      option.setAttribute("name", "plan")
+      option.setAttribute("value", self.test_plan_name())
+      configuration.appendChild(option)
+
+      xml_str = root.toprettyxml(indent = XML_INDENT, encoding = "utf-8")
+
+      test_plan_file = os.path.join(self.mts_config_dir, self.test_plan_name() + ".xml")
+      with open(test_plan_file, "wb") as f:
+        logging.debug(f"Writing `{test_plan_file}`.")
+        f.write(xml_str)
+
+    def regen_test_list_file(self):
+      """Regenerate ART MTS test list file (`mts-art-tests-list-user-shard-<shard_num>.xml`)."""
+      root = xml.dom.minidom.Document()
+
+      advisory_header = root.createComment(f" {ADVISORY} ")
+      root.appendChild(advisory_header)
+      copyright_header = root.createComment(copyright_header_text(self.copyright_year))
+      root.appendChild(copyright_header)
+
+      configuration = root.createElement("configuration")
+      root.appendChild(configuration)
+      configuration.setAttribute(
+          "description",
+          f"List of ART MTS tests that do not need root access (shard {self.shard_id()})"
+      )
+
+      # Test declarations.
+      # ------------------
+
+      def append_test_declaration(test):
+        option = root.createElement("option")
+        option.setAttribute("name", "compatibility:include-filter")
+        option.setAttribute("value", test)
+        configuration.appendChild(option)
+
+      test_declarations_comments = [self.description + "."]
+      test_declarations_comments.extend(self.comments)
+      for c in test_declarations_comments:
+        xml_comment = root.createComment(f" {c} ")
+        configuration.appendChild(xml_comment)
+      for t in self.tests:
+        append_test_declaration(t)
+
+      # `MainlineTestModuleController` configurations.
+      # ----------------------------------------------
+
+      def append_module_controller_configuration(test):
+        option = root.createElement("option")
+        option.setAttribute("name", "compatibility:module-arg")
+        option.setAttribute("value", f"{test}:enable:true")
+        configuration.appendChild(option)
+
+      module_controller_configuration_comments = [
+          f"Enable MainlineTestModuleController for {self.description}."]
+      module_controller_configuration_comments.extend(self.comments)
+      for c in module_controller_configuration_comments:
+        xml_comment = root.createComment(f" {c} ")
+        configuration.appendChild(xml_comment)
+      for t in self.tests:
+        append_module_controller_configuration(t)
+
+      xml_str = root.toprettyxml(indent = XML_INDENT, encoding = "utf-8")
+
+      test_list_file = os.path.join(self.mts_config_dir, self.test_list_name() + ".xml")
+      with open(test_list_file, "wb") as f:
+        logging.debug(f"Writing `{test_list_file}`.")
+        f.write(xml_str)
+
+  def regen_mts_art_tests_list_user_file(self, num_mts_art_run_test_shards):
+    """Regenerate ART MTS test list file (`mts-art-tests-list-user.xml`)."""
+    root = xml.dom.minidom.Document()
+
+    advisory_header = root.createComment(f" {ADVISORY} ")
+    root.appendChild(advisory_header)
+    copyright_header = root.createComment(copyright_header_text(2020))
+    root.appendChild(copyright_header)
+
+    configuration = root.createElement("configuration")
+    root.appendChild(configuration)
+    configuration.setAttribute("description", "List of ART MTS tests that do not need root access.")
+
+    # Included XML files.
+    for s in range(num_mts_art_run_test_shards):
+      include = root.createElement("include")
+      include.setAttribute("name", f"mts-art-tests-list-user-shard-{s:02}")
+      configuration.appendChild(include)
+
+    xml_str = root.toprettyxml(indent = XML_INDENT, encoding = "utf-8")
+
+    mts_art_tests_list_user_file = os.path.join(self.mts_config_dir, "mts-art-tests-list-user.xml")
+    with open(mts_art_tests_list_user_file, "wb") as f:
+      logging.debug(f"Writing `{mts_art_tests_list_user_file}`.")
+      f.write(xml_str)
+
+  def regen_art_mts_files(self, art_run_tests):
+    """Regenerate ART MTS definition files."""
+
+    # Remove any previously MTS ART test plan shard (`mts-art-shard-[0-9]+.xml`)
+    # and any test list shard (`mts-art-tests-list-user-shard-[0-9]+.xml`).
+    old_test_plan_shards = sorted([
+        test_plan_shard
+        for test_plan_shard in os.listdir(self.mts_config_dir)
+        if re.match("^mts-art-(tests-list-user-)?shard-[0-9]+.xml$", test_plan_shard)])
+    for shard in old_test_plan_shards:
+      shard_path = os.path.join(self.mts_config_dir, shard)
+      if os.path.exists(shard_path):
+        logging.debug(f"Removing `{shard_path}`.")
+        os.remove(shard_path)
+
+    mts_test_shards = []
+
+    # ART test (gtest & run-test) shard(s).
+    # TODO: Also handle the case of gtests requiring root access to the device
+    # (`art_gtest_eng_only_module_names`).
+    art_run_test_module_names = [ART_RUN_TEST_MODULE_NAME_PREFIX + t for t in art_run_tests]
+    art_run_test_shards = split_list(art_run_test_module_names, NUM_MTS_ART_RUN_TEST_SHARDS)
+    for i in range(len(art_run_test_shards)):
+      art_tests_shard_i_tests = art_run_test_shards[i]
+      # Append ART gtests to the last ART run-test shard for now.
+      # If needed, consider moving them to their own shard to increase
+      # the parallelization of code coverage runs.
+      if i + 1 == len(art_run_test_shards):
+        art_tests_shard_i_tests.extend(art_gtest_user_module_names)
+      art_tests_shard_i = self.create_mts_test_shard(
+          "ART run-tests", art_tests_shard_i_tests, i, 2020,
+          ["TODO(rpl): Find a way to express this list in a more concise fashion."])
+      mts_test_shards.append(art_tests_shard_i)
+
+    # CTS Libcore non-OJ tests (`CtsLibcoreTestCases`) shard.
+    cts_libcore_tests_shard_num = len(mts_test_shards)
+    cts_libcore_tests_shard = self.create_mts_test_shard(
+        "CTS Libcore non-OJ tests", ["CtsLibcoreTestCases"], cts_libcore_tests_shard_num, 2020)
+    mts_test_shards.append(cts_libcore_tests_shard)
+
+    # Other CTS Libcore tests shard.
+    other_cts_libcore_tests_shard_num = len(mts_test_shards)
+    other_cts_libcore_tests_shard_tests = [
+        "CtsLibcoreApiEvolutionTestCases",
+        "CtsLibcoreFileIOTestCases",
+        "CtsLibcoreJsr166TestCases",
+        "CtsLibcoreLegacy22TestCases",
+        "CtsLibcoreOjTestCases",
+        "CtsLibcoreWycheproofBCTestCases",
+        "MtsLibcoreOkHttpTestCases",
+    ]
+    other_cts_libcore_tests_shard = self.create_mts_test_shard(
+        "CTS Libcore OJ tests", other_cts_libcore_tests_shard_tests,
+        other_cts_libcore_tests_shard_num, 2021)
+    mts_test_shards.append(other_cts_libcore_tests_shard)
+
+    for s in mts_test_shards:
+      s.regen_test_plan_file()
+      s.regen_test_list_file()
+
+    self.regen_mts_art_tests_list_user_file(len(mts_test_shards))
+
+  def regen_test_files(self, regen_art_mts):
+    """Regenerate ART test files.
+
+    Args:
+      regen_art_mts: If true, also regenerate the ART MTS definition.
+    """
+    run_tests = self.enumerate_run_tests()
+
+    # Create a list of the tests that can currently be built, and for
+    # which a Blueprint file is to be generated.
+    buildable_tests = list(filter(self.is_buildable, run_tests))
+
+    # Create a list of the tests that can be built and are expected to
+    # succeed. These tests are to be added to ART's `TEST_MAPPING`
+    # file and also tagged as part of TradeFed's `art-target-run-test`
+    # test suite via the `test-suite-tag` option in their
+    # configuration file.
+    expected_succeeding_tests = list(filter(is_expected_succeeding, buildable_tests))
+
+    # Regenerate Blueprint files.
+    # ---------------------------
+
+    self.regen_bp_files(run_tests, buildable_tests)
+
+    buildable_tests_percentage = int(len(buildable_tests) * 100 / len(run_tests))
+
+    print(f"Generated Blueprint files for {len(buildable_tests)} ART run-tests out of"
+          f" {len(run_tests)} ({buildable_tests_percentage}%).")
+
+    # Regenerate `TEST_MAPPING` file.
+    # -------------------------------
+
+    # Note: We only include ART run-tests expected to succeed for now.
+
+    # Note: We only include a (growing) fraction of the supported ART
+    # run-tests (see `presubmit_tests_percentage`) into the
+    # `presubmit` test group (the other ART run-tests are added to the
+    # `postsubmit` test group), as we initially had issues with
+    # Android presubmits when the whole set of supported ART run-tests
+    # was included in one go (b/169310621). This progressive rollout
+    # allows us to better monitor future potential presubmit failures.
+    #
+    # Likewise for tests in the `mainline-presubmit` group.
+    num_presubmit_run_tests = int(len(expected_succeeding_tests) * presubmit_tests_percentage / 100)
+    num_mainline_presubmit_run_tests = int(
+        len(expected_succeeding_tests) * mainline_presubmit_tests_percentage / 100)
+    self.regen_test_mapping_file(
+        expected_succeeding_tests, num_presubmit_run_tests, num_mainline_presubmit_run_tests)
+
+    expected_succeeding_tests_percentage = int(
+        len(expected_succeeding_tests) * 100 / len(run_tests))
+
+    num_postsubmit_tests = len(expected_succeeding_tests) - num_presubmit_run_tests
+    postsubmit_tests_percentage = 100 - presubmit_tests_percentage
+
+    print(f"Generated TEST_MAPPING entries for {len(expected_succeeding_tests)} ART run-tests out"
+          f" of {len(run_tests)} ({expected_succeeding_tests_percentage}%):")
+    for (num_tests, test_kind, tests_percentage, test_group_name) in [
+        (num_mainline_presubmit_run_tests, "ART run-tests", mainline_presubmit_tests_percentage,
+         "mainline-presubmit"),
+        (len(art_gtest_module_names), "ART gtests", 100, "mainline-presubmit"),
+        (num_presubmit_run_tests, "ART run-tests", presubmit_tests_percentage, "presubmit"),
+        (len(art_gtest_module_names), "ART gtests", 100, "presubmit"),
+        (num_postsubmit_tests, "ART run-tests", postsubmit_tests_percentage, "postsubmit"),
+    ]:
+      print(
+          f"  {num_tests:3d} {test_kind} ({tests_percentage}%) in `{test_group_name}` test group.")
+
+    # Regenerate ART MTS definition (optional).
+    # -----------------------------------------
+
+    if regen_art_mts:
+      self.regen_art_mts_files(expected_succeeding_tests)
+      print(f"Generated ART MTS entries for {len(expected_succeeding_tests)} ART run-tests out"
+            f" of {len(run_tests)} ({expected_succeeding_tests_percentage}%).")
+
+def main():
+  if "ANDROID_BUILD_TOP" not in os.environ:
+    logging.error("ANDROID_BUILD_TOP environment variable is empty; did you forget to run `lunch`?")
+    sys.exit(1)
+
+  parser = argparse.ArgumentParser(
+      formatter_class=argparse.RawDescriptionHelpFormatter,
+      description=textwrap.dedent("Regenerate some ART test related files."),
+      epilog=textwrap.dedent("""\
+        Regenerate ART run-tests Blueprint files, ART's `TEST_MAPPING` file, and
+        optionally the ART MTS (Mainline Test Suite) definition.
+        """))
+  parser.add_argument("-m", "--regen-art-mts", help="regenerate the ART MTS definition as well",
+                      action="store_true")
+  parser.add_argument("-v", "--verbose", help="enable verbose output", action="store_true")
+  args = parser.parse_args()
+
+  if args.verbose:
+    logging.getLogger().setLevel(logging.DEBUG)
+
+  generator = Generator(os.path.join(os.environ["ANDROID_BUILD_TOP"]))
+  generator.regen_test_files(args.regen_art_mts)
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/Android.bp b/tools/Android.bp
index 2a8ff0a..9b9d3a7 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 python_binary_host {
     name: "generate_operator_out",
     srcs: [
@@ -29,10 +38,90 @@
     },
 }
 
+soong_config_module_type_import {
+    from: "art/build/SoongConfig.bp",
+    module_types: [
+        "art_module_sh_binary",
+    ],
+}
+
 // Copy the art shell script to the host and target's bin directory
-sh_binary {
+art_module_sh_binary {
     name: "art-script",
+
+    // Disable this script in prebuilt mode since it depends on dalvikvm which
+    // isn't a prebuilt.
+    // TODO(b/172480617): Clean up when sources are gone from the platform tree
+    // and we no longer need to support sources present when prebuilts are used.
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+
     host_supported: true,
     src: "art",
     filename_from_src: true,
+    target: {
+        host: {
+            // On device we require the ART APEX, but its Soong module name may
+            // be different depending on branch, and it's always present anyway,
+            // so we leave it out.
+            required: [
+                "dalvikvm",
+                "dex2oat",
+            ],
+        },
+        darwin: {
+            enabled: false,
+        },
+        windows: {
+            // When the module is enabled globally in the soong_config_variables
+            // stanza above, it gets enabled on windows too. Hence we need to
+            // disable it explicitly.
+            // TODO(b/172480617): Clean up with that.
+            enabled: false,
+        },
+    },
+}
+
+sh_binary {
+    name: "dex2oat-script",
+    host_supported: true,
+    src: "dex2oat_wrapper",
+    filename_from_src: true,
+    target: {
+        host: {
+            // On device we require the ART APEX, but its Soong module name may
+            // be different depending on branch, and it's always present anyway,
+            // so we leave it out.
+            required: [
+                "dex2oat",
+            ],
+        },
+        darwin: {
+            enabled: false,
+        },
+    },
+}
+
+python_binary_host {
+    name: "art-run-test-checker",
+    srcs: [
+        "checker/**/*.py",
+    ],
+    main: "checker/checker.py",
+    version: {
+        py2: {
+            enabled: false,
+        },
+        py3: {
+            enabled: true,
+        },
+    },
+    test_suites: [
+        "general-tests",
+        "mts",
+    ],
 }
diff --git a/tools/ahat/Android.bp b/tools/ahat/Android.bp
index 85aca4c..1a933bb 100644
--- a/tools/ahat/Android.bp
+++ b/tools/ahat/Android.bp
@@ -12,19 +12,36 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-droiddoc_host {
-    name: "ahat-docs",
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+droidstubs_host {
+    name: "ahat-docs-stubs",
     srcs: [
         "src/main/**/*.java",
     ],
-    custom_template: "droiddoc-templates-sdk",
-    args: "-stubpackages com.android.ahat:com.android.ahat.*",
     check_api: {
         current: {
             api_file: "etc/ahat_api.txt",
             removed_api_file: "etc/ahat_removed_api.txt",
         },
     },
+    flags: ["-stubpackages com.android.ahat:com.android.ahat.*"],
+    create_doc_stubs: true,
+}
+
+droiddoc_host {
+    name: "ahat-docs",
+    srcs: [
+        ":ahat-docs-stubs",
+    ],
+    custom_template: "droiddoc-templates-sdk",
 }
 
 // --- ahat.jar ----------------
diff --git a/tools/ahat/Android.mk b/tools/ahat/Android.mk
index 160bb28..16f1712 100644
--- a/tools/ahat/Android.mk
+++ b/tools/ahat/Android.mk
@@ -58,8 +58,9 @@
   $(AHAT_TEST_DALVIKVM_DEP) \
   $(ART_HOST_SHARED_LIBRARY_DEPENDENCIES) \
   $(ART_HOST_SHARED_LIBRARY_DEBUG_DEPENDENCIES) \
+  $(ART_HOST_DEX_DEPENDENCIES) \
   $(HOST_OUT_EXECUTABLES)/art \
-  $(HOST_CORE_IMG_OUT_BASE)$(CORE_IMG_SUFFIX)
+  $(HOST_CORE_IMG_OUTS)
 
 $(AHAT_TEST_DUMP_HPROF): PRIVATE_AHAT_TEST_ART := $(HOST_OUT_EXECUTABLES)/art
 $(AHAT_TEST_DUMP_HPROF): PRIVATE_AHAT_TEST_DUMP_JAR := $(AHAT_TEST_DUMP_JAR)
@@ -112,6 +113,9 @@
 LOCAL_IS_HOST_MODULE := true
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE := ahat-tests
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 LOCAL_TEST_CONFIG := ahat-tests.xml
 LOCAL_COMPATIBILITY_SUITE := general-tests
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/ahat/README.txt b/tools/ahat/README.txt
index 0474b13..1010e9d 100644
--- a/tools/ahat/README.txt
+++ b/tools/ahat/README.txt
@@ -52,6 +52,9 @@
  * Request to be able to sort tables by size.
 
 Release History:
+ 1.7.1 September 30, 2020
+   Fix issue parsing proguard maps with comments.
+
  1.7 August 8, 2019
    Annotate binder services, tokens, and proxies.
    Add option for viewing subclass instances of a class.
diff --git a/tools/ahat/etc/ahat.mf b/tools/ahat/etc/ahat.mf
index f96aa64..eedf4f0 100644
--- a/tools/ahat/etc/ahat.mf
+++ b/tools/ahat/etc/ahat.mf
@@ -1,4 +1,4 @@
 Name: ahat/
 Implementation-Title: ahat
-Implementation-Version: 1.7
+Implementation-Version: 1.7.1
 Main-Class: com.android.ahat.Main
diff --git a/tools/ahat/etc/ahat_api.txt b/tools/ahat/etc/ahat_api.txt
index 962f12b..9898af4 100644
--- a/tools/ahat/etc/ahat_api.txt
+++ b/tools/ahat/etc/ahat_api.txt
@@ -1,7 +1,8 @@
+// Signature format: 2.0
 package com.android.ahat {
 
   public class Main {
-    method public static void main(java.lang.String[]);
+    method public static void main(String[]);
   }
 
 }
@@ -14,23 +15,23 @@
     method public com.android.ahat.dominators.Dominators progress(com.android.ahat.progress.Progress, long);
   }
 
-  public static abstract interface Dominators.Graph<Node> {
-    method public abstract java.lang.Object getDominatorsComputationState(Node);
-    method public abstract java.lang.Iterable<? extends Node> getReferencesForDominators(Node);
-    method public abstract void setDominator(Node, Node);
-    method public abstract void setDominatorsComputationState(Node, java.lang.Object);
+  public static interface Dominators.Graph<Node> {
+    method public Object getDominatorsComputationState(Node);
+    method public Iterable<? extends Node> getReferencesForDominators(Node);
+    method public void setDominator(Node, Node);
+    method public void setDominatorsComputationState(Node, Object);
   }
 
-  public deprecated class DominatorsComputation {
-    method public static void computeDominators(com.android.ahat.dominators.DominatorsComputation.Node);
-    method public static void computeDominators(com.android.ahat.dominators.DominatorsComputation.Node, com.android.ahat.progress.Progress, long);
+  @Deprecated public class DominatorsComputation {
+    method @Deprecated public static void computeDominators(com.android.ahat.dominators.DominatorsComputation.Node);
+    method @Deprecated public static void computeDominators(com.android.ahat.dominators.DominatorsComputation.Node, com.android.ahat.progress.Progress, long);
   }
 
-  public static abstract interface DominatorsComputation.Node {
-    method public abstract java.lang.Object getDominatorsComputationState();
-    method public abstract java.lang.Iterable<? extends com.android.ahat.dominators.DominatorsComputation.Node> getReferencesForDominators();
-    method public abstract void setDominator(com.android.ahat.dominators.DominatorsComputation.Node);
-    method public abstract void setDominatorsComputationState(java.lang.Object);
+  @Deprecated public static interface DominatorsComputation.Node {
+    method @Deprecated public Object getDominatorsComputationState();
+    method @Deprecated public Iterable<? extends Node> getReferencesForDominators();
+    method @Deprecated public void setDominator(com.android.ahat.dominators.DominatorsComputation.Node);
+    method @Deprecated public void setDominatorsComputationState(Object);
   }
 
 }
@@ -40,82 +41,85 @@
   public class AhatArrayInstance extends com.android.ahat.heapdump.AhatInstance {
     method public int getLength();
     method public com.android.ahat.heapdump.Value getValue(int);
-    method public java.util.List<com.android.ahat.heapdump.Value> getValues();
+    method public List<Value> getValues();
+    method public String toString();
   }
 
   public class AhatClassInstance extends com.android.ahat.heapdump.AhatInstance {
-    method public java.lang.Iterable<com.android.ahat.heapdump.FieldValue> getInstanceFields();
+    method public Iterable<FieldValue> getInstanceFields();
+    method public String toString();
   }
 
   public class AhatClassObj extends com.android.ahat.heapdump.AhatInstance {
     method public com.android.ahat.heapdump.AhatInstance getClassLoader();
     method public com.android.ahat.heapdump.Field[] getInstanceFields();
     method public long getInstanceSize();
-    method public java.lang.String getName();
-    method public java.util.List<com.android.ahat.heapdump.FieldValue> getStaticFieldValues();
+    method public String getName();
+    method public List<FieldValue> getStaticFieldValues();
     method public com.android.ahat.heapdump.AhatClassObj getSuperClassObj();
+    method public String toString();
   }
 
-  public class AhatHeap implements com.android.ahat.heapdump.Diffable {
+  public class AhatHeap implements com.android.ahat.heapdump.Diffable<com.android.ahat.heapdump.AhatHeap> {
     method public com.android.ahat.heapdump.AhatHeap getBaseline();
-    method public java.lang.String getName();
+    method public String getName();
     method public com.android.ahat.heapdump.Size getSize();
     method public boolean isPlaceHolder();
   }
 
-  public abstract class AhatInstance implements com.android.ahat.heapdump.Diffable {
+  public abstract class AhatInstance implements com.android.ahat.heapdump.Diffable<com.android.ahat.heapdump.AhatInstance> {
     method public com.android.ahat.heapdump.AhatArrayInstance asArrayInstance();
-    method public java.awt.image.BufferedImage asBitmap();
+    method public BufferedImage asBitmap();
     method public com.android.ahat.heapdump.AhatClassInstance asClassInstance();
     method public com.android.ahat.heapdump.AhatClassObj asClassObj();
-    method public java.lang.String asString(int);
-    method public java.lang.String asString();
+    method public String asString(int);
+    method public String asString();
     method public com.android.ahat.heapdump.AhatInstance getAssociatedBitmapInstance();
     method public com.android.ahat.heapdump.AhatClassObj getAssociatedClassForOverhead();
     method public com.android.ahat.heapdump.AhatInstance getBaseline();
-    method public java.lang.String getBinderProxyInterfaceName();
-    method public java.lang.String getBinderStubInterfaceName();
-    method public java.lang.String getBinderTokenDescriptor();
-    method public java.lang.String getClassName();
+    method public String getBinderProxyInterfaceName();
+    method public String getBinderStubInterfaceName();
+    method public String getBinderTokenDescriptor();
+    method public String getClassName();
     method public com.android.ahat.heapdump.AhatClassObj getClassObj();
-    method public java.lang.String getDexCacheLocation(int);
-    method public java.util.List<com.android.ahat.heapdump.AhatInstance> getDominated();
-    method public com.android.ahat.heapdump.Value getField(java.lang.String);
-    method public deprecated java.util.List<com.android.ahat.heapdump.AhatInstance> getHardReverseReferences();
+    method public String getDexCacheLocation(int);
+    method public List<AhatInstance> getDominated();
+    method public com.android.ahat.heapdump.Value getField(String);
+    method @Deprecated public List<AhatInstance> getHardReverseReferences();
     method public com.android.ahat.heapdump.AhatHeap getHeap();
     method public long getId();
     method public com.android.ahat.heapdump.AhatInstance getImmediateDominator();
-    method public java.util.List<com.android.ahat.heapdump.PathElement> getPathFromGcRoot();
+    method public List<PathElement> getPathFromGcRoot();
     method public com.android.ahat.heapdump.Reachability getReachability();
-    method public com.android.ahat.heapdump.AhatInstance getRefField(java.lang.String);
+    method public com.android.ahat.heapdump.AhatInstance getRefField(String);
     method public com.android.ahat.heapdump.AhatInstance getReferent();
     method public com.android.ahat.heapdump.Size getRetainedSize(com.android.ahat.heapdump.AhatHeap);
-    method public java.util.List<com.android.ahat.heapdump.AhatInstance> getReverseReferences();
-    method public java.util.Collection<com.android.ahat.heapdump.RootType> getRootTypes();
+    method public List<AhatInstance> getReverseReferences();
+    method public Collection<RootType> getRootTypes();
     method public com.android.ahat.heapdump.Site getSite();
     method public com.android.ahat.heapdump.Size getSize();
-    method public deprecated java.util.List<com.android.ahat.heapdump.AhatInstance> getSoftReverseReferences();
+    method @Deprecated public List<AhatInstance> getSoftReverseReferences();
     method public com.android.ahat.heapdump.Size getTotalRetainedSize();
     method public boolean isArrayInstance();
     method public boolean isClassInstance();
     method public boolean isClassObj();
-    method public boolean isInstanceOfClass(java.lang.String);
+    method public boolean isInstanceOfClass(String);
     method public boolean isPlaceHolder();
     method public boolean isRoot();
     method public boolean isStronglyReachable();
     method public boolean isUnreachable();
-    method public deprecated boolean isWeaklyReachable();
-    method public abstract java.lang.String toString();
+    method @Deprecated public boolean isWeaklyReachable();
+    method public abstract String toString();
   }
 
-  public class AhatSnapshot implements com.android.ahat.heapdump.Diffable {
+  public class AhatSnapshot implements com.android.ahat.heapdump.Diffable<com.android.ahat.heapdump.AhatSnapshot> {
     method public com.android.ahat.heapdump.AhatClassObj findClassObj(long);
     method public com.android.ahat.heapdump.AhatInstance findInstance(long);
     method public com.android.ahat.heapdump.AhatSnapshot getBaseline();
-    method public com.android.ahat.heapdump.AhatHeap getHeap(java.lang.String);
-    method public java.util.List<com.android.ahat.heapdump.AhatHeap> getHeaps();
+    method public com.android.ahat.heapdump.AhatHeap getHeap(String);
+    method public List<AhatHeap> getHeaps();
     method public com.android.ahat.heapdump.Site getRootSite();
-    method public java.util.List<com.android.ahat.heapdump.AhatInstance> getRooted();
+    method public List<AhatInstance> getRooted();
     method public com.android.ahat.heapdump.Site getSite(long);
     method public boolean isDiffed();
     method public boolean isPlaceHolder();
@@ -127,73 +131,73 @@
 
   public class DiffFields {
     ctor public DiffFields();
-    method public static java.util.List<com.android.ahat.heapdump.DiffedFieldValue> diff(java.lang.Iterable<com.android.ahat.heapdump.FieldValue>, java.lang.Iterable<com.android.ahat.heapdump.FieldValue>);
+    method public static List<DiffedFieldValue> diff(Iterable<FieldValue>, Iterable<FieldValue>);
   }
 
-  public abstract interface Diffable<T> {
-    method public abstract T getBaseline();
-    method public abstract boolean isPlaceHolder();
+  public interface Diffable<T> {
+    method public T getBaseline();
+    method public boolean isPlaceHolder();
   }
 
   public class DiffedFieldValue {
     method public static com.android.ahat.heapdump.DiffedFieldValue added(com.android.ahat.heapdump.FieldValue);
     method public static com.android.ahat.heapdump.DiffedFieldValue deleted(com.android.ahat.heapdump.FieldValue);
+    method public boolean equals(Object);
+    method public int hashCode();
     method public static com.android.ahat.heapdump.DiffedFieldValue matched(com.android.ahat.heapdump.FieldValue, com.android.ahat.heapdump.FieldValue);
+    method public String toString();
     field public final com.android.ahat.heapdump.Value baseline;
     field public final com.android.ahat.heapdump.Value current;
-    field public final java.lang.String name;
+    field public final String name;
     field public final com.android.ahat.heapdump.DiffedFieldValue.Status status;
     field public final com.android.ahat.heapdump.Type type;
   }
 
-  public static final class DiffedFieldValue.Status extends java.lang.Enum {
-    method public static com.android.ahat.heapdump.DiffedFieldValue.Status valueOf(java.lang.String);
-    method public static final com.android.ahat.heapdump.DiffedFieldValue.Status[] values();
+  public enum DiffedFieldValue.Status {
     enum_constant public static final com.android.ahat.heapdump.DiffedFieldValue.Status ADDED;
     enum_constant public static final com.android.ahat.heapdump.DiffedFieldValue.Status DELETED;
     enum_constant public static final com.android.ahat.heapdump.DiffedFieldValue.Status MATCHED;
   }
 
   public class Field {
-    ctor public Field(java.lang.String, com.android.ahat.heapdump.Type);
-    field public final java.lang.String name;
+    ctor public Field(String, com.android.ahat.heapdump.Type);
+    field public final String name;
     field public final com.android.ahat.heapdump.Type type;
   }
 
   public class FieldValue {
-    ctor public FieldValue(java.lang.String, com.android.ahat.heapdump.Type, com.android.ahat.heapdump.Value);
-    field public final java.lang.String name;
+    ctor public FieldValue(String, com.android.ahat.heapdump.Type, com.android.ahat.heapdump.Value);
+    field public final String name;
     field public final com.android.ahat.heapdump.Type type;
     field public final com.android.ahat.heapdump.Value value;
   }
 
-  public class HprofFormatException extends java.lang.Exception {
+  public class HprofFormatException {
   }
 
   public class Parser {
-    ctor public Parser(java.nio.ByteBuffer);
-    ctor public Parser(java.io.File) throws java.io.IOException;
+    ctor public Parser(ByteBuffer);
+    ctor public Parser(File);
     method public com.android.ahat.heapdump.Parser map(com.android.ahat.proguard.ProguardMap);
-    method public com.android.ahat.heapdump.AhatSnapshot parse() throws com.android.ahat.heapdump.HprofFormatException, java.io.IOException;
-    method public static com.android.ahat.heapdump.AhatSnapshot parseHeapDump(java.io.File, com.android.ahat.proguard.ProguardMap) throws com.android.ahat.heapdump.HprofFormatException, java.io.IOException;
-    method public static com.android.ahat.heapdump.AhatSnapshot parseHeapDump(java.nio.ByteBuffer, com.android.ahat.proguard.ProguardMap) throws com.android.ahat.heapdump.HprofFormatException, java.io.IOException;
+    method public com.android.ahat.heapdump.AhatSnapshot parse() throws com.android.ahat.heapdump.HprofFormatException;
+    method public static com.android.ahat.heapdump.AhatSnapshot parseHeapDump(File, com.android.ahat.proguard.ProguardMap) throws com.android.ahat.heapdump.HprofFormatException;
+    method public static com.android.ahat.heapdump.AhatSnapshot parseHeapDump(ByteBuffer, com.android.ahat.proguard.ProguardMap) throws com.android.ahat.heapdump.HprofFormatException;
     method public com.android.ahat.heapdump.Parser progress(com.android.ahat.progress.Progress);
     method public com.android.ahat.heapdump.Parser retained(com.android.ahat.heapdump.Reachability);
   }
 
-  public class PathElement implements com.android.ahat.heapdump.Diffable {
-    ctor public PathElement(com.android.ahat.heapdump.AhatInstance, java.lang.String);
+  public class PathElement implements com.android.ahat.heapdump.Diffable<com.android.ahat.heapdump.PathElement> {
+    ctor public PathElement(com.android.ahat.heapdump.AhatInstance, String);
     method public com.android.ahat.heapdump.PathElement getBaseline();
     method public boolean isPlaceHolder();
-    field public final java.lang.String field;
+    field public final String field;
     field public final com.android.ahat.heapdump.AhatInstance instance;
     field public boolean isDominator;
   }
 
-  public final class Reachability extends java.lang.Enum {
+  public enum Reachability {
     method public boolean notWeakerThan(com.android.ahat.heapdump.Reachability);
-    method public static com.android.ahat.heapdump.Reachability valueOf(java.lang.String);
-    method public static final com.android.ahat.heapdump.Reachability[] values();
+    method public String toString();
     enum_constant public static final com.android.ahat.heapdump.Reachability FINALIZER;
     enum_constant public static final com.android.ahat.heapdump.Reachability PHANTOM;
     enum_constant public static final com.android.ahat.heapdump.Reachability SOFT;
@@ -202,9 +206,7 @@
     enum_constant public static final com.android.ahat.heapdump.Reachability WEAK;
   }
 
-  public final class RootType extends java.lang.Enum {
-    method public static com.android.ahat.heapdump.RootType valueOf(java.lang.String);
-    method public static final com.android.ahat.heapdump.RootType[] values();
+  public enum RootType {
     enum_constant public static final com.android.ahat.heapdump.RootType DEBUGGER;
     enum_constant public static final com.android.ahat.heapdump.RootType FINALIZING;
     enum_constant public static final com.android.ahat.heapdump.RootType INTERNED_STRING;
@@ -221,27 +223,27 @@
     enum_constant public static final com.android.ahat.heapdump.RootType VM_INTERNAL;
   }
 
-  public class Site implements com.android.ahat.heapdump.Diffable {
+  public class Site implements com.android.ahat.heapdump.Diffable<com.android.ahat.heapdump.Site> {
     method public com.android.ahat.heapdump.Site findSite(long);
     method public com.android.ahat.heapdump.Site getBaseline();
-    method public java.util.List<com.android.ahat.heapdump.Site> getChildren();
-    method public java.lang.String getFilename();
+    method public List<Site> getChildren();
+    method public String getFilename();
     method public long getId();
     method public int getLineNumber();
-    method public java.lang.String getMethodName();
-    method public void getObjects(java.lang.String, java.lang.String, java.util.Collection<com.android.ahat.heapdump.AhatInstance>);
-    method public void getObjects(java.util.function.Predicate<com.android.ahat.heapdump.AhatInstance>, java.util.function.Consumer<com.android.ahat.heapdump.AhatInstance>);
-    method public java.util.List<com.android.ahat.heapdump.Site.ObjectsInfo> getObjectsInfos();
+    method public String getMethodName();
+    method public void getObjects(String, String, Collection<AhatInstance>);
+    method public void getObjects(Predicate<AhatInstance>, Consumer<AhatInstance>);
+    method public List<ObjectsInfo> getObjectsInfos();
     method public com.android.ahat.heapdump.Site getParent();
-    method public java.lang.String getSignature();
+    method public String getSignature();
     method public com.android.ahat.heapdump.Size getSize(com.android.ahat.heapdump.AhatHeap);
     method public com.android.ahat.heapdump.Size getTotalSize();
     method public boolean isPlaceHolder();
   }
 
-  public static class Site.ObjectsInfo implements com.android.ahat.heapdump.Diffable {
+  public static class Site.ObjectsInfo implements com.android.ahat.heapdump.Diffable<com.android.ahat.heapdump.Site.ObjectsInfo> {
     method public com.android.ahat.heapdump.Site.ObjectsInfo getBaseline();
-    method public java.lang.String getClassName();
+    method public String getClassName();
     method public boolean isPlaceHolder();
     field public com.android.ahat.heapdump.AhatClassObj classObj;
     field public com.android.ahat.heapdump.AhatHeap heap;
@@ -251,9 +253,11 @@
 
   public class Size {
     ctor public Size(long, long);
+    method public boolean equals(Object);
     method public long getJavaSize();
     method public long getRegisteredNativeSize();
     method public long getSize();
+    method public int hashCode();
     method public boolean isZero();
     method public com.android.ahat.heapdump.Size plus(com.android.ahat.heapdump.Size);
     method public com.android.ahat.heapdump.Size plusRegisteredNativeSize(long);
@@ -262,22 +266,21 @@
 
   public class Sort {
     ctor public Sort();
-    method public static java.util.Comparator<com.android.ahat.heapdump.AhatInstance> defaultInstanceCompare(com.android.ahat.heapdump.AhatSnapshot);
-    method public static java.util.Comparator<com.android.ahat.heapdump.Site> defaultSiteCompare(com.android.ahat.heapdump.AhatSnapshot);
-    method public static <T> java.util.Comparator<T> withPriority(java.util.Comparator<T>...);
-    field public static final java.util.Comparator<com.android.ahat.heapdump.FieldValue> FIELD_VALUE_BY_NAME;
-    field public static final java.util.Comparator<com.android.ahat.heapdump.FieldValue> FIELD_VALUE_BY_TYPE;
-    field public static final java.util.Comparator<com.android.ahat.heapdump.AhatInstance> INSTANCE_BY_TOTAL_RETAINED_SIZE;
-    field public static final java.util.Comparator<com.android.ahat.heapdump.Site.ObjectsInfo> OBJECTS_INFO_BY_CLASS_NAME;
-    field public static final java.util.Comparator<com.android.ahat.heapdump.Site.ObjectsInfo> OBJECTS_INFO_BY_HEAP_NAME;
-    field public static final java.util.Comparator<com.android.ahat.heapdump.Site.ObjectsInfo> OBJECTS_INFO_BY_SIZE;
-    field public static final java.util.Comparator<com.android.ahat.heapdump.Site> SITE_BY_TOTAL_SIZE;
-    field public static final java.util.Comparator<com.android.ahat.heapdump.Size> SIZE_BY_SIZE;
+    method public static Comparator<AhatInstance> defaultInstanceCompare(com.android.ahat.heapdump.AhatSnapshot);
+    method public static Comparator<Site> defaultSiteCompare(com.android.ahat.heapdump.AhatSnapshot);
+    method public static <T> Comparator<T> withPriority(Comparator<T>...);
+    field public static final Comparator<FieldValue> FIELD_VALUE_BY_NAME;
+    field public static final Comparator<FieldValue> FIELD_VALUE_BY_TYPE;
+    field public static final Comparator<AhatInstance> INSTANCE_BY_TOTAL_RETAINED_SIZE;
+    field public static final Comparator<Site.ObjectsInfo> OBJECTS_INFO_BY_CLASS_NAME;
+    field public static final Comparator<Site.ObjectsInfo> OBJECTS_INFO_BY_HEAP_NAME;
+    field public static final Comparator<Site.ObjectsInfo> OBJECTS_INFO_BY_SIZE;
+    field public static final Comparator<Site> SITE_BY_TOTAL_SIZE;
+    field public static final Comparator<Size> SIZE_BY_SIZE;
   }
 
-  public final class Type extends java.lang.Enum {
-    method public static com.android.ahat.heapdump.Type valueOf(java.lang.String);
-    method public static final com.android.ahat.heapdump.Type[] values();
+  public enum Type {
+    method public String toString();
     enum_constant public static final com.android.ahat.heapdump.Type BOOLEAN;
     enum_constant public static final com.android.ahat.heapdump.Type BYTE;
     enum_constant public static final com.android.ahat.heapdump.Type CHAR;
@@ -287,17 +290,16 @@
     enum_constant public static final com.android.ahat.heapdump.Type LONG;
     enum_constant public static final com.android.ahat.heapdump.Type OBJECT;
     enum_constant public static final com.android.ahat.heapdump.Type SHORT;
-    field public final java.lang.String name;
+    field public final String name;
   }
 
   public abstract class Value {
-    ctor public Value();
     method public com.android.ahat.heapdump.AhatInstance asAhatInstance();
-    method public java.lang.Byte asByte();
-    method public java.lang.Character asChar();
-    method public java.lang.Integer asInteger();
-    method public java.lang.Long asLong();
-    method public abstract boolean equals(java.lang.Object);
+    method public Byte asByte();
+    method public Character asChar();
+    method public Integer asInteger();
+    method public Long asLong();
+    method public abstract boolean equals(Object);
     method public static com.android.ahat.heapdump.Value getBaseline(com.android.ahat.heapdump.Value);
     method public static com.android.ahat.heapdump.Type getType(com.android.ahat.heapdump.Value);
     method public abstract int hashCode();
@@ -313,7 +315,7 @@
     method public static com.android.ahat.heapdump.Value pack(short);
     method public static com.android.ahat.heapdump.Value pack(int);
     method public static com.android.ahat.heapdump.Value pack(long);
-    method public abstract java.lang.String toString();
+    method public abstract String toString();
   }
 
 }
@@ -324,16 +326,16 @@
     ctor public NullProgress();
     method public void advance(long);
     method public void done();
-    method public void start(java.lang.String, long);
+    method public void start(String, long);
     method public void update(long);
   }
 
-  public abstract interface Progress {
+  public interface Progress {
     method public default void advance();
-    method public abstract void advance(long);
-    method public abstract void done();
-    method public abstract void start(java.lang.String, long);
-    method public abstract void update(long);
+    method public void advance(long);
+    method public void done();
+    method public void start(String, long);
+    method public void update(long);
   }
 
 }
@@ -342,18 +344,18 @@
 
   public class ProguardMap {
     ctor public ProguardMap();
-    method public java.lang.String getClassName(java.lang.String);
-    method public java.lang.String getFieldName(java.lang.String, java.lang.String);
-    method public com.android.ahat.proguard.ProguardMap.Frame getFrame(java.lang.String, java.lang.String, java.lang.String, java.lang.String, int);
-    method public void readFromFile(java.io.File) throws java.io.FileNotFoundException, java.io.IOException, java.text.ParseException;
-    method public void readFromReader(java.io.Reader) throws java.io.IOException, java.text.ParseException;
+    method public String getClassName(String);
+    method public String getFieldName(String, String);
+    method public com.android.ahat.proguard.ProguardMap.Frame getFrame(String, String, String, String, int);
+    method public void readFromFile(File);
+    method public void readFromReader(Reader);
   }
 
   public static class ProguardMap.Frame {
-    field public final java.lang.String filename;
+    field public final String filename;
     field public final int line;
-    field public final java.lang.String method;
-    field public final java.lang.String signature;
+    field public final String method;
+    field public final String signature;
   }
 
 }
diff --git a/tools/ahat/etc/ahat_removed_api.txt b/tools/ahat/etc/ahat_removed_api.txt
index e69de29..d802177 100644
--- a/tools/ahat/etc/ahat_removed_api.txt
+++ b/tools/ahat/etc/ahat_removed_api.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/tools/ahat/src/main/com/android/ahat/DocString.java b/tools/ahat/src/main/com/android/ahat/DocString.java
index 76e9e80..eda9b38 100644
--- a/tools/ahat/src/main/com/android/ahat/DocString.java
+++ b/tools/ahat/src/main/com/android/ahat/DocString.java
@@ -129,7 +129,7 @@
    *
    * Nothing is printed for a size of zero.
    * Set isPlaceHolder to true to indicate that the size field corresponds to
-   * for a place holder object that should be annotated specially.
+   * for a placeholder object that should be annotated specially.
    */
   public static DocString size(long size, boolean isPlaceHolder) {
     DocString string = new DocString();
diff --git a/tools/ahat/src/main/com/android/ahat/ObjectHandler.java b/tools/ahat/src/main/com/android/ahat/ObjectHandler.java
index c099da8..4d85cc0 100644
--- a/tools/ahat/src/main/com/android/ahat/ObjectHandler.java
+++ b/tools/ahat/src/main/com/android/ahat/ObjectHandler.java
@@ -256,7 +256,7 @@
     doc.section("Sample Path from GC Root");
     List<PathElement> path = inst.getPathFromGcRoot();
 
-    // Add a dummy PathElement as a marker for the root.
+    // Add a fake PathElement as a marker for the root.
     final PathElement root = new PathElement(null, null);
     path.add(0, root);
 
@@ -308,4 +308,3 @@
     }
   }
 }
-
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatHeap.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatHeap.java
index 60c9a0d..a189945 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatHeap.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatHeap.java
@@ -37,7 +37,7 @@
   }
 
   /**
-   * Construct a place holder heap.
+   * Construct a placeholder heap.
    */
   private AhatHeap(String name, AhatHeap baseline) {
     mName = name;
@@ -48,7 +48,7 @@
   }
 
   /**
-   * Construct a new place holder heap that has the given baseline heap.
+   * Construct a new placeholder heap that has the given baseline heap.
    */
   static AhatHeap newPlaceHolderHeap(String name, AhatHeap baseline) {
     return new AhatHeap(name, baseline);
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java
index e62fb40..ebd96e9 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java
@@ -686,7 +686,7 @@
   }
 
   /**
-   * Returns a new place holder instance corresponding to this instance.
+   * Returns a new placeholder instance corresponding to this instance.
    */
   AhatInstance newPlaceHolderInstance() {
     return new AhatPlaceHolderInstance(this);
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatSnapshot.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatSnapshot.java
index 3634a1a..14dfe03 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatSnapshot.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatSnapshot.java
@@ -145,7 +145,7 @@
    * Returns a list of heaps in the snapshot in canonical order.
    * <p>
    * Note: modifications to the returned list are visible to this
-   * AhatSnapshot, which is used by diff to insert place holder heaps.
+   * AhatSnapshot, which is used by diff to insert placeholder heaps.
    *
    * @return list of heaps
    */
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Diff.java b/tools/ahat/src/main/com/android/ahat/heapdump/Diff.java
index b35b424..ca00f17 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Diff.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Diff.java
@@ -154,9 +154,9 @@
   }
 
   /**
-   * Recursively create place holder instances for the given instance and
+   * Recursively create placeholder instances for the given instance and
    * every instance dominated by that instance.
-   * Returns the place holder instance created for the given instance.
+   * Returns the placeholder instance created for the given instance.
    * Adds all allocated placeholders to the given placeholders list.
    */
   private static AhatInstance createPlaceHolders(AhatInstance inst,
@@ -260,7 +260,7 @@
    *
    * This requires that instances have already been diffed. In particular, we
    * require all AhatClassObjs in one snapshot have corresponding (possibly
-   * place-holder) AhatClassObjs in the other snapshot.
+   * placeholder) AhatClassObjs in the other snapshot.
    */
   private static void sites(Site a, Site b) {
     // Set the sites as baselines of each other.
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Diffable.java b/tools/ahat/src/main/com/android/ahat/heapdump/Diffable.java
index 09c8ee6..90852e9 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Diffable.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Diffable.java
@@ -37,11 +37,10 @@
    * Returns true if this is a placeholder object.
    * A placeholder object is used to indicate there is some object in the
    * baseline heap dump that is not in this heap dump. In that case, we create
-   * a dummy place holder object in this heap dump as an indicator of the
+   * a placeholder object in this heap dump as an indicator of the
    * object removed from the baseline heap dump.
    *
    * @return true if the object is a placeholder
    */
   boolean isPlaceHolder();
 }
-
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Parser.java b/tools/ahat/src/main/com/android/ahat/heapdump/Parser.java
index c7f7b4b..7fe444e 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Parser.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Parser.java
@@ -710,11 +710,11 @@
   }
 
   /**
-   * Dummy value representing a reference to an instance that has not yet been
+   * Placeholder value representing a reference to an instance that has not yet been
    * resolved.
    * When first initializing class static fields, we don't yet know what kinds
    * of objects Object references refer to. We use DeferredInstanceValue as
-   * a dummy kind of value to store the id of an object. In the fixup pass we
+   * a placeholder kind of value to store the id of an object. In the fixup pass we
    * resolve all the DeferredInstanceValues into their proper InstanceValues.
    */
   private static class DeferredInstanceValue extends Value {
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Value.java b/tools/ahat/src/main/com/android/ahat/heapdump/Value.java
index 5e48dca..1f9bb96 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Value.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Value.java
@@ -24,6 +24,7 @@
  * instance from the heap dump.
  */
 public abstract class Value {
+  Value() { }
   /**
    * Constructs a Value for an AhatInstance.
    * Note: returns null for null <code>value</code>.
diff --git a/tools/ahat/src/main/com/android/ahat/proguard/ProguardMap.java b/tools/ahat/src/main/com/android/ahat/proguard/ProguardMap.java
index 88231dd..f2f2383 100644
--- a/tools/ahat/src/main/com/android/ahat/proguard/ProguardMap.java
+++ b/tools/ahat/src/main/com/android/ahat/proguard/ProguardMap.java
@@ -232,8 +232,15 @@
 
       // After the class line comes zero or more field/method lines of the form:
       //   '    type clearName -> obfuscatedName'
+      //   '# comment line'
       line = reader.readLine();
-      while (line != null && line.startsWith("    ")) {
+      while (line != null && (line.startsWith("    ") || line.startsWith("#"))) {
+        // Comment lines start with '#' and may occur anywhere in the file.
+        // Skip over them.
+        if (line.startsWith("#")) {
+          line = reader.readLine();
+          continue;
+        }
         String trimmed = line.trim();
         int ws = trimmed.indexOf(' ');
         sep = trimmed.indexOf(" -> ");
diff --git a/tools/ahat/src/test-dump/Main.java b/tools/ahat/src/test-dump/Main.java
index ca18fd8..2e29076 100644
--- a/tools/ahat/src/test-dump/Main.java
+++ b/tools/ahat/src/test-dump/Main.java
@@ -38,7 +38,7 @@
     boolean baseline = args.length > 1 && args[1].equals("--base");
 
     // Enable allocation tracking so we get stack traces in the heap dump.
-    DdmVmInternal.enableRecentAllocations(true);
+    DdmVmInternal.setRecentAllocationsTrackingEnabled(true);
 
     // Allocate the instance of DumpedStuff.
     stuff = new DumpedStuff(baseline);
diff --git a/tools/art b/tools/art
old mode 100644
new mode 100755
index d44737c..e524b17
--- a/tools/art
+++ b/tools/art
@@ -1,3 +1,4 @@
+#! /bin/sh
 # Copyright (C) 2011 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +15,11 @@
 
 # This script is used on host and device. It uses a common subset
 # shell dialect that should work on the host (e.g. bash), and
-# Android (e.g. mksh).
+# Android (e.g. mksh). Try to switch to bash if the shebang above
+# has launched a pessimal shell on host.
+if [ -z "$KSH_VERSION" -a -z "$BASH_VERSION" -a -n "$(which bash)" ]; then
+  exec bash -c ". $0" -- "$@"
+fi
 
 ######################################
 # Functions
@@ -195,6 +200,12 @@
     verbose_run mkdir -p $(dirname "$dex_file")/oat/$ISA
     local oat_file=$(basename "$dex_file")
     local oat_file=$(dirname "$dex_file")/oat/$ISA/${oat_file%.*}.odex
+    if [ "$GENERATE_APP_IMAGE" = "yes" ]; then
+      local art_file=$(basename "$dex_file")
+      local art_file=$(dirname "$dex_file")/oat/$ISA/${art_file%.*}.art
+      DEX2OAT_FLAGS+=("--app-image-file=$art_file")
+    fi
+
     # When running dex2oat use the exact same context as when running dalvikvm.
     # (see run_art function)
     verbose_run ANDROID_DATA=$ANDROID_DATA                    \
@@ -232,6 +243,17 @@
     case $1 in
       -Xcompiler-option)
         DEX2OAT_FLAGS+=("$2")
+
+        # Enable app images for profile filters
+        case $2 in
+          --compiler-filter=speed-profile)
+            GENERATE_APP_IMAGE="yes"
+            ;;
+          --compiler-filter=everything-profile)
+            GENERATE_APP_IMAGE="yes"
+            ;;
+        esac
+
         shift
         ;;
       -Ximage:*)
@@ -314,6 +336,7 @@
 EXTRA_OPTIONS=()
 DEX2OAT_FLAGS=()
 DEX2OAT_CLASSPATH=()
+GENERATE_APP_IMAGE="no"
 
 # Parse arguments
 while [[ "$1" = "-"* ]]; do
@@ -527,37 +550,44 @@
   exit 1
 fi
 
-if [[ "$DEX2OAT_BOOT_IMAGE" = *core*.art && "$DEX2OAT_BCP" = "" ]]; then
+# Create boot class path filename or location list.
+# It takes one optional argument which is the prefix to be inserted before each entry.
+function get_boot_class_path() {
   # 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-icu4j 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
+  local modules="core-oj core-libart okhttp bouncycastle apache-xml core-icu4j conscrypt"
+  local prefix="$1"
+  local result=""
+  local separator=""
+  for module in ${modules}; do
+    case "$module" in
+      (conscrypt)  local apex="com.android.conscrypt";;
+      (core-icu4j) local apex="com.android.i18n";;
+      (*)          local apex="com.android.art";;
+    esac
+    result+="${separator}${prefix}/apex/${apex}/javalib/${module}.jar"
+    separator=":"
+  done
+  echo "$result"
+}
+
+# Create default boot class path if none was provided.
+if [[ "$DEX2OAT_BCP" = "" ]]; then
+  ANDROID_ROOT_MINUS_PWD="${ANDROID_ROOT#$PWD/}"  # For example: out/host/linux-x86
+  if [[ "$ANDROID_ROOT_MINUS_PWD" == */host/* ]]; then
+    DEX2OAT_BCP="$(get_boot_class_path $ANDROID_ROOT)"
+    DEX2OAT_BCP_LOCS="$(get_boot_class_path $ANDROID_ROOT_MINUS_PWD)"
+  elif [[ "$ANDROID_ROOT_MINUS_PWD" == */target/* ]]; then
+    DEX2OAT_BCP="$(get_boot_class_path $ANDROID_ROOT)"
+    DEX2OAT_BCP_LOCS="$(get_boot_class_path)"
+  else
+    echo "Can not determine whether are running on host or target"
+    exit 1
   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
+  if [ "$VERBOSE" = "yes" ]; then
+    echo ANDROID_ROOT=$ANDROID_ROOT
+    echo DEX2OAT_BOOT_IMAGE=$DEX2OAT_BOOT_IMAGE
+    echo DEX2OAT_BCP=$DEX2OAT_BCP
+    echo DEX2OAT_BCP_LOCS=$DEX2OAT_BCP_LOCS
   fi
 fi
 
diff --git a/tools/art_verifier/Android.bp b/tools/art_verifier/Android.bp
index 72327d5..5d19215 100644
--- a/tools/art_verifier/Android.bp
+++ b/tools/art_verifier/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 art_cc_defaults {
     name: "art_verifier-defaults",
     defaults: [
@@ -28,7 +37,7 @@
         "art_cmdlineparser_headers",
     ],
     static_libs: [
-        "libsigchain_dummy",
+        "libsigchain_fake",
     ],
     target: {
         android: {
diff --git a/tools/art_verifier/art_verifier.cc b/tools/art_verifier/art_verifier.cc
index 6fe27d6..313c470 100644
--- a/tools/art_verifier/art_verifier.cc
+++ b/tools/art_verifier/art_verifier.cc
@@ -247,6 +247,7 @@
           std::string error_msg;
           verifier::FailureKind res =
             verifier::ClassVerifier::VerifyClass(soa.Self(),
+                                                 /* verifier_deps= */ nullptr,
                                                  h_klass.Get(),
                                                  runtime->GetCompilerCallbacks(),
                                                  true,
diff --git a/tools/bisect_profile.py b/tools/bisect_profile.py
new file mode 100755
index 0000000..21018e0
--- /dev/null
+++ b/tools/bisect_profile.py
@@ -0,0 +1,204 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2021 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.
+
+#
+# Generates profiles from the set of all methods in a given set of dex/jars and
+# bisects to find minimal repro sets.
+#
+
+import shlex
+import argparse
+import pylibdexfile
+import math
+import subprocess
+from collections import namedtuple
+import sys
+import random
+import os
+
+ApkEntry = namedtuple("ApkEntry", ["file", "location"])
+
+
+def get_parser():
+  parser = argparse.ArgumentParser(
+      description="Bisect profile contents. We will wait while the user runs test"
+  )
+
+  class ApkAction(argparse.Action):
+
+    def __init__(self, option_strings, dest, **kwargs):
+      super(ApkAction, self).__init__(option_strings, dest, **kwargs)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+      lst = getattr(namespace, self.dest)
+      if lst is None:
+        setattr(namespace, self.dest, [])
+        lst = getattr(namespace, self.dest)
+      if len(values) == 1:
+        values = (values[0], values[0])
+      assert len(values) == 2, values
+      lst.append(ApkEntry(*values))
+
+  apks = parser.add_argument_group(title="APK selection")
+  apks.add_argument(
+      "--apk",
+      action=ApkAction,
+      dest="apks",
+      nargs=1,
+      default=[],
+      help="an apk/dex/jar to get methods from. Uses same path as location. " +
+           "Use --apk-and-location if this isn't desired."
+  )
+  apks.add_argument(
+      "--apk-and-location",
+      action=ApkAction,
+      nargs=2,
+      dest="apks",
+      help="an apk/dex/jar + location to get methods from."
+  )
+  profiles = parser.add_argument_group(
+      title="Profile selection").add_mutually_exclusive_group()
+  profiles.add_argument(
+      "--input-text-profile", help="a text profile to use for bisect")
+  profiles.add_argument("--input-profile", help="a profile to use for bisect")
+  parser.add_argument(
+      "--output-source", help="human readable file create the profile from")
+  parser.add_argument("--test-exec", help="file to exec (without arguments) to test a" +
+                                           " candidate. Test should exit 0 if the issue" +
+                                           " is not present and non-zero if the issue is" +
+                                           " present.")
+  parser.add_argument("output_file", help="file we will write the profiles to")
+  return parser
+
+
+def dump_files(meths, args, output):
+  for m in meths:
+    print("HS{}".format(m), file=output)
+  output.flush()
+  profman_args = [
+      "profmand", "--reference-profile-file={}".format(args.output_file),
+      "--create-profile-from={}".format(args.output_source)
+  ]
+  print(" ".join(map(shlex.quote, profman_args)))
+  for apk in args.apks:
+    profman_args += [
+        "--apk={}".format(apk.file), "--dex-location={}".format(apk.location)
+    ]
+  profman = subprocess.run(profman_args)
+  profman.check_returncode()
+
+
+def get_answer(args):
+  if args.test_exec is None:
+    while True:
+      answer = input("Does the file at {} cause the issue (y/n):".format(
+          args.output_file))
+      if len(answer) >= 1 and answer[0].lower() == "y":
+        return "y"
+      elif len(answer) >= 1 and answer[0].lower() == "n":
+        return "n"
+      else:
+        print("Please enter 'y' or 'n' only!")
+  else:
+    test_args = shlex.split(args.test_exec)
+    print(" ".join(map(shlex.quote, test_args)))
+    answer = subprocess.run(test_args)
+    if answer.returncode == 0:
+      return "n"
+    else:
+      return "y"
+
+def run_test(meths, args):
+  with open(args.output_source, "wt") as output:
+    dump_files(meths, args, output)
+    print("Currently testing {} methods. ~{} rounds to go.".format(
+        len(meths), 1 + math.floor(math.log2(len(meths)))))
+  return get_answer(args)
+
+def main():
+  parser = get_parser()
+  args = parser.parse_args()
+  if args.output_source is None:
+    fdnum = os.memfd_create("tempfile_profile")
+    args.output_source = "/proc/{}/fd/{}".format(os.getpid(), fdnum)
+  all_dexs = list()
+  for f in args.apks:
+    try:
+      all_dexs.append(pylibdexfile.FileDexFile(f.file, f.location))
+    except Exception as e1:
+      try:
+        all_dexs += pylibdexfile.OpenJar(f.file)
+      except Exception as e2:
+        parser.error("Failed to open file: {}. errors were {} and {}".format(
+            f.file, e1, e2))
+  if args.input_profile is not None:
+    profman_args = [
+        "profmand", "--dump-classes-and-methods",
+        "--profile-file={}".format(args.input_profile)
+    ]
+    for apk in args.apks:
+      profman_args.append("--apk={}".format(apk.file))
+    print(" ".join(map(shlex.quote, profman_args)))
+    res = subprocess.run(
+        profman_args, capture_output=True, universal_newlines=True)
+    res.check_returncode()
+    meth_list = list(filter(lambda a: a != "", res.stdout.split()))
+  elif args.input_text_profile is not None:
+    with open(args.input_text_profile, "rt") as inp:
+      meth_list = list(filter(lambda a: a != "", inp.readlines()))
+  else:
+    all_methods = set()
+    for d in all_dexs:
+      for m in d.methods:
+        all_methods.add(m.descriptor)
+    meth_list = list(all_methods)
+  print("Found {} methods. Will take ~{} iterations".format(
+      len(meth_list), 1 + math.floor(math.log2(len(meth_list)))))
+  print(
+      "type 'yes' if the behavior you are looking for is present (i.e. the compiled code crashes " +
+      "or something)"
+  )
+  print("Performing single check with all methods")
+  result = run_test(meth_list, args)
+  if result[0].lower() != "y":
+    cont = input(
+        "The behavior you were looking for did not occur when run against all methods. Continue " +
+        "(yes/no)? "
+    )
+    if cont[0].lower() != "y":
+      print("Aborting!")
+      sys.exit(1)
+  needs_dump = False
+  while len(meth_list) > 1:
+    test_methods = list(meth_list[0:len(meth_list) // 2])
+    result = run_test(test_methods, args)
+    if result[0].lower() == "y":
+      meth_list = test_methods
+      needs_dump = False
+    else:
+      meth_list = meth_list[len(meth_list) // 2:]
+      needs_dump = True
+  if needs_dump:
+    with open(args.output_source, "wt") as output:
+      dump_files(meth_list, args, output)
+  print("Found result!")
+  print("{}".format(meth_list[0]))
+  print("Leaving profile at {} and text profile at {}".format(
+      args.output_file, args.output_source))
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/bisection_search/bisection_search.py b/tools/bisection_search/bisection_search.py
index 102bbad..7f62b85 100755
--- a/tools/bisection_search/bisection_search.py
+++ b/tools/bisection_search/bisection_search.py
@@ -61,8 +61,8 @@
 # position in the command.
 RAW_CMD_RUNTIME_ARGS_TAG = '{ARGS}'
 
-# Default core image path relative to ANDROID_HOST_OUT.
-DEFAULT_IMAGE_RELATIVE_PATH = '/framework/core.art'
+# Default boot image path relative to ANDROID_HOST_OUT.
+DEFAULT_IMAGE_RELATIVE_PATH = 'apex/com.android.art/javalib/boot.art'
 
 class Dex2OatWrapperTestable(object):
   """Class representing a testable compilation.
diff --git a/tools/boot-image-profile-generate.sh b/tools/boot-image-profile-generate.sh
index de4dd42..20d0421 100755
--- a/tools/boot-image-profile-generate.sh
+++ b/tools/boot-image-profile-generate.sh
@@ -20,8 +20,8 @@
 #   1) the boot.zip file which contains the boot classpath and system server jars.
 #      This file can be obtained from running `m dist` or by configuring the device with
 #      the `art/tools/boot-image-profile-configure-device.sh` script.
-#   2) the preloaded classes blacklist which specify what clases should not be preloaded
-#      in Zygote. Usually located in usually in frameworks/base/config/preloaded-classes-blacklist
+#   2) the preloaded classes denylist which specify what clases should not be preloaded
+#      in Zygote. Usually located in usually in frameworks/base/config/preloaded-classes-denylist
 #   3) a list of raw boot image profiles extracted from devices. An example how to do that is
 #      by running `art/tools/boot-image-profile-extract-profile.sh` script.
 #
@@ -39,11 +39,11 @@
 fi
 
 if [[ "$#" -lt 4 ]]; then
-  echo "Usage $0 <output-dir> <boot.zip-location> <preloaded-blacklist-location> <profile-input1> <profile-input2> ... <profman args>"
+  echo "Usage $0 <output-dir> <boot.zip-location> <preloaded-denylist-location> <profile-input1> <profile-input2> ... <profman args>"
   echo "Without any profman args the script will use defaults."
-  echo "Example: $0 output-dir boot.zip frameworks/base/config/preloaded-classes-blacklist android1.prof android2.prof"
-  echo "         $0 output-dir boot.zip frameworks/base/config/preloaded-classes-blacklist android.prof --profman-arg --upgrade-startup-to-hot=true"
-  echo "preloaded.black-list is usually in frameworks/base/config/preloaded-classes-blacklist"
+  echo "Example: $0 output-dir boot.zip frameworks/base/config/preloaded-classes-denylist android1.prof android2.prof"
+  echo "         $0 output-dir boot.zip frameworks/base/config/preloaded-classes-denylist android.prof --profman-arg --upgrade-startup-to-hot=true"
+  echo "preloaded-deny-list-location is usually frameworks/base/config/preloaded-classes-denylist"
   exit 1
 fi
 
@@ -53,7 +53,7 @@
 
 OUT_DIR="$1"
 BOOT_ZIP="$2"
-PRELOADED_BLACKLIST="$3"
+PRELOADED_DENYLIST="$3"
 shift 3
 
 # Read the profile input args.
@@ -119,7 +119,7 @@
   "${profman_profile_input_args[@]}" \
   --out-profile-path="$OUT_BOOT_PROFILE" \
   --out-preloaded-classes-path="$OUT_PRELOADED_CLASSES" \
-  --preloaded-classes-blacklist="$PRELOADED_BLACKLIST" \
+  --preloaded-classes-denylist="$PRELOADED_DENYLIST" \
   --special-package=android:1 \
   --special-package=com.android.systemui:1 \
   "${profman_args[@]}"
@@ -147,4 +147,4 @@
 CLEAN_UP="${CLEAN_UP:-true}"
 if [[ "$CLEAN_UP" = "true" ]]; then
   rm -rf "$WORK_DIR"
-fi
\ No newline at end of file
+fi
diff --git a/tools/bootjars.sh b/tools/bootjars.sh
index f7abf27..6c39d31 100755
--- a/tools/bootjars.sh
+++ b/tools/bootjars.sh
@@ -73,19 +73,21 @@
   # defined in Android.common_path.mk, otherwise we would just use HOST-/TARGET_TEST_CORE_JARS.
 
   # 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.
+  # because that's what we use for compiling the boot.art image.
   # It may contain additional modules from TEST_CORE_JARS.
-  core_jars_list="core-oj core-libart core-icu4j okhttp bouncycastle apache-xml conscrypt"
-  core_jars_suffix=
-  if [[ $mode == target ]]; then
-    core_jars_suffix=-testdex
-  elif [[ $mode == host ]]; then
-    core_jars_suffix=-hostdex
-  fi
+  core_jars_list="core-oj core-libart okhttp bouncycastle apache-xml core-icu4j"
   boot_jars_list=""
   boot_separator=""
   for boot_module in ${core_jars_list}; do
-    boot_jars_list+="${boot_separator}${boot_module}${core_jars_suffix}"
+    jar_suffix=
+    if [[ $mode == host ]]; then
+      if [[ $boot_module == core-icu4j ]]; then
+        jar_suffix="-host-hostdex"
+      else
+        jar_suffix="-hostdex"
+      fi
+    fi
+    boot_jars_list+="${boot_separator}${boot_module}${jar_suffix}"
     boot_separator=" "
   done
 else
@@ -106,6 +108,23 @@
 intermediates_dir=$(readlink -m "$intermediates_dir")
 popd >/dev/null
 
-for jar in $boot_jars_list; do
-  echo "$intermediates_dir/JAVA_LIBRARIES/${jar}_intermediates/classes.jar"
-done
+if [[ $mode == target ]]; then
+  for jar in $boot_jars_list; do
+    if [[ $jar == "conscrypt" ]]; then
+      echo "$intermediates_dir/JAVA_LIBRARIES/${jar}.com.android.conscrypt_intermediates/classes.jar"
+    elif [[ $jar == "core-icu4j" ]]; then
+      # The location of ICU is different on an unbundled build.
+      if [[ -f "$intermediates_dir/JAVA_LIBRARIES/${jar}.com.android.i18n_intermediates/classes.jar" ]]; then
+        echo "$intermediates_dir/JAVA_LIBRARIES/${jar}.com.android.i18n_intermediates/classes.jar"
+      else
+        echo "$intermediates_dir/JAVA_LIBRARIES/${jar}_intermediates/classes.jar"
+      fi
+    else
+      echo "$intermediates_dir/JAVA_LIBRARIES/${jar}.com.android.art.testing_intermediates/classes.jar"
+    fi
+  done
+else
+  for jar in $boot_jars_list; do
+    echo "$intermediates_dir/JAVA_LIBRARIES/${jar}_intermediates/classes.jar"
+  done
+fi
diff --git a/tools/build_linux_bionic.sh b/tools/build_linux_bionic.sh
index 89e72b2..3c5a68f 100755
--- a/tools/build_linux_bionic.sh
+++ b/tools/build_linux_bionic.sh
@@ -31,13 +31,23 @@
   exit 1
 fi
 
+# TODO(b/194433871): Set MODULE_BUILD_FROM_SOURCE to disable prebuilt modules,
+# which Soong otherwise can create duplicate install rules for in --skip-make
+# mode.
+soong_args="MODULE_BUILD_FROM_SOURCE=true"
+
+# Switch the build system to unbundled mode in the reduced manifest branch.
+if [ ! -d frameworks/base ]; then
+  soong_args="$soong_args TARGET_BUILD_UNBUNDLED=true"
+fi
+
 source build/envsetup.sh >&/dev/null # for get_build_var
 # Soong needs a bunch of variables set and will not run if they are missing.
 # The default values of these variables is only contained in make, so use
 # nothing to create the variables then remove all the other artifacts.
 # Lunch since it seems we cannot find the build-number otherwise.
 lunch aosp_x86-eng
-build/soong/soong_ui.bash --make-mode nothing
+build/soong/soong_ui.bash --make-mode $soong_args nothing
 
 if [ $? != 0 ]; then
   exit 1
@@ -56,7 +66,7 @@
 cat $out_dir/soong/soong.variables > ${tmp_soong_var}
 
 # See comment above about b/123645297 for why we cannot just do m clean. Clear
-# out all files except for intermediates and installed files.
+# out all files except for intermediates and installed files and dexpreopt.config.
 find $out_dir/ -maxdepth 1 -mindepth 1 \
                -not -name soong        \
                -not -name host         \
@@ -64,6 +74,7 @@
 find $out_dir/soong/ -maxdepth 1 -mindepth 1   \
                      -not -name .intermediates \
                      -not -name host           \
+                     -not -name dexpreopt.config \
                      -not -name target | xargs -I '{}' rm -rf '{}'
 
 python3 <<END - ${tmp_soong_var} ${out_dir}/soong/soong.variables
@@ -76,8 +87,6 @@
 x['CrossHostArch'] = 'x86_64'
 if 'CrossHostSecondaryArch' in x:
   del x['CrossHostSecondaryArch']
-if 'DexpreoptGlobalConfig' in x:
-  del x['DexpreoptGlobalConfig']
 json.dump(x, open(sys.argv[2], mode='w'))
 END
 
@@ -86,4 +95,4 @@
 # Write a new build-number
 echo ${tmp_build_number}_SOONG_ONLY_BUILD > ${out_dir}/soong/build_number.txt
 
-build/soong/soong_ui.bash --make-mode --skip-make $@
+build/soong/soong_ui.bash --make-mode --skip-make $soong_args $@
diff --git a/tools/build_linux_bionic_tests.sh b/tools/build_linux_bionic_tests.sh
index 76dabd4..73596ad 100755
--- a/tools/build_linux_bionic_tests.sh
+++ b/tools/build_linux_bionic_tests.sh
@@ -26,6 +26,13 @@
   exit 1
 fi
 
+soong_args=""
+
+# Switch the build system to unbundled mode in the reduced manifest branch.
+if [ ! -d frameworks/base ]; then
+  soong_args="$soong_args TARGET_BUILD_UNBUNDLED=true"
+fi
+
 source build/envsetup.sh >&/dev/null # for get_build_var
 
 out_dir=$(get_build_var OUT_DIR)
@@ -38,7 +45,7 @@
 
 # First build all the targets still in .mk files (also build normal glibc host
 # targets so we know what's needed to run the tests).
-build/soong/soong_ui.bash --make-mode "$@" test-art-host-run-test-dependencies build-art-host-tests
+build/soong/soong_ui.bash --make-mode $soong_args "$@" test-art-host-run-test-dependencies build-art-host-tests
 if [ $? != 0 ]; then
   exit 1
 fi
@@ -82,13 +89,13 @@
   $soong_out/bin/hprof-conv
   $soong_out/bin/signal_dumper
   $soong_out/lib64/libclang_rt.ubsan_standalone-x86_64-android.so
-  $(find $host_out/apex -type f | sed "s:$host_out:$soong_out:g")
+  $(find $host_out/apex/com.android.art.host.zipapex -type f | sed "s:$host_out:$soong_out:g")
   $(find $host_out/lib64 -type f | sed "s:$host_out:$soong_out:g")
   $(find $host_out/nativetest64 -type f | sed "s:$host_out:$soong_out:g"))
 
 echo building ${bionic_targets[*]}
 
-build/soong/soong_ui.bash --make-mode --skip-make "$@" ${bionic_targets[*]}
+build/soong/soong_ui.bash --make-mode --skip-make $soong_args "$@" ${bionic_targets[*]}
 ret=$?
 
 mv $tmp_soong_var $out_dir/soong/soong.variables
diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh
index 17c68f6..9779b5d 100755
--- a/tools/buildbot-build.sh
+++ b/tools/buildbot-build.sh
@@ -16,12 +16,14 @@
 
 set -e
 
+shopt -s failglob
+
 if [ ! -d art ]; then
   echo "Script needs to be run at the root of the android tree"
   exit 1
 fi
 
-source build/envsetup.sh >&/dev/null # for get_build_var
+TARGET_ARCH=$(source build/envsetup.sh > /dev/null; get_build_var TARGET_ARCH)
 
 # Logic for setting out_dir from build/make/core/envsetup.mk:
 if [[ -z $OUT_DIR ]]; then
@@ -36,17 +38,24 @@
 
 java_libraries_dir=${out_dir}/target/common/obj/JAVA_LIBRARIES
 common_targets="vogar core-tests apache-harmony-jdwp-tests-hostdex jsr166-tests libartpalette-system mockito-target"
-mode="target"
+# These build targets have different names on device and host.
+specific_targets="libjavacoretests libjdwp libwrapagentproperties libwrapagentpropertiesd"
+build_host="no"
+build_target="no"
+installclean="no"
 j_arg="-j$(nproc)"
 showcommands=
 make_command=
 
 while true; do
   if [[ "$1" == "--host" ]]; then
-    mode="host"
+    build_host="yes"
     shift
   elif [[ "$1" == "--target" ]]; then
-    mode="target"
+    build_target="yes"
+    shift
+  elif [[ "$1" == "--installclean" ]]; then
+    installclean="yes"
     shift
   elif [[ "$1" == -j* ]]; then
     j_arg=$1
@@ -62,58 +71,124 @@
   fi
 done
 
-# Allow to build successfully in master-art.
-extra_args="SOONG_ALLOW_MISSING_DEPENDENCIES=true TEMPORARY_DISABLE_PATH_RESTRICTIONS=true"
+# If neither was selected, build both by default.
+if [[ $build_host == "no" ]] && [[ $build_target == "no" ]]; then
+  build_host="yes"
+  build_target="yes"
+fi
 
-if [[ $mode == "host" ]]; then
-  make_command="build/soong/soong_ui.bash --make-mode $j_arg $extra_args $showcommands build-art-host-tests $common_targets"
+# Allow to build successfully in master-art.
+extra_args="SOONG_ALLOW_MISSING_DEPENDENCIES=true"
+
+# Switch the build system to unbundled mode in the reduced manifest branch.
+if [ ! -d frameworks/base ]; then
+  extra_args="$extra_args TARGET_BUILD_UNBUNDLED=true"
+fi
+
+apexes=(
+  "com.android.art.testing"
+  "com.android.conscrypt"
+  "com.android.i18n"
+  "com.android.runtime"
+  "com.android.tzdata"
+  "com.android.os.statsd"
+)
+
+make_command="build/soong/soong_ui.bash --make-mode $j_arg $extra_args $showcommands $common_targets"
+if [[ $build_host == "yes" ]]; then
+  make_command+=" build-art-host-tests"
   make_command+=" dx-tests junit-host"
-  mode_suffix="-host"
-elif [[ $mode == "target" ]]; then
+  for LIB in ${specific_targets} ; do
+    make_command+=" $LIB-host"
+  done
+fi
+if [[ $build_target == "yes" ]]; then
   if [[ -z "${ANDROID_PRODUCT_OUT}" ]]; then
     echo 'ANDROID_PRODUCT_OUT environment variable is empty; did you forget to run `lunch`?'
     exit 1
   fi
-  make_command="build/soong/soong_ui.bash --make-mode $j_arg $extra_args $showcommands build-art-target-tests $common_targets"
-  make_command+=" libnetd_client-target toybox toolbox sh"
+  make_command+=" build-art-target-tests"
+  make_command+=" libnetd_client-target toybox sh libtombstoned_client"
   make_command+=" debuggerd su gdbserver"
-  make_command+=" libstdc++ "
+  # vogar requires the class files for conscrypt and ICU.
+  make_command+=" conscrypt core-icu4j"
   make_command+=" ${ANDROID_PRODUCT_OUT#"${ANDROID_BUILD_TOP}/"}/system/etc/public.libraries.txt"
-  if [[ -n "$ART_TEST_CHROOT" ]]; then
-    # Targets required to generate a linker configuration on device within the
-    # chroot environment.
-    make_command+=" linkerconfig"
-    # Additional targets needed for the chroot environment.
-    make_command+=" crash_dump event-log-tags"
-  fi
-  # Build the Runtime (Bionic) APEX.
-  make_command+=" com.android.runtime"
-  # Build the Testing ART APEX (which is a superset of the Release and Debug ART APEXes).
-  make_command+=" com.android.art.testing"
-  # Build the bootstrap Bionic artifacts links (linker, libc, libdl, libm).
-  # These targets create these symlinks:
-  # - from /system/bin/linker(64) to /apex/com.android.runtime/bin/linker(64); and
-  # - from /system/lib(64)/$lib to /apex/com.android.runtime/lib(64)/$lib.
-  make_command+=" linker libc.bootstrap libdl.bootstrap libdl_android.bootstrap libm.bootstrap"
-  # Build the Conscrypt APEX.
-  make_command+=" com.android.conscrypt"
-  # Build the i18n APEX.
-  make_command+=" com.android.i18n"
-  # Build the Time Zone Data APEX.
-  make_command+=" com.android.tzdata"
+  # Targets required to generate a linker configuration for device within the
+  # chroot environment. The *.libraries.txt targets are required by
+  # the source linkerconfig but not included in the prebuilt one.
+  make_command+=" linkerconfig conv_linker_config sanitizer.libraries.txt vndkcorevariant.libraries.txt"
+  # Additional targets needed for the chroot environment.
+  make_command+=" event-log-tags"
+  # Needed to extract prebuilt APEXes.
+  make_command+=" deapexer"
+  # Build/install the required APEXes.
+  make_command+=" ${apexes[*]}"
+  make_command+=" ${specific_targets}"
 fi
 
-mode_specific_libraries="libjavacoretests libjdwp libwrapagentproperties libwrapagentpropertiesd"
-for LIB in ${mode_specific_libraries} ; do
-  make_command+=" $LIB${mode_suffix}"
-done
-
+if [[ $installclean == "yes" ]]; then
+  echo "Perform installclean"
+  ANDROID_QUIET_BUILD=true build/soong/soong_ui.bash --make-mode $extra_args installclean
+else
+  echo "WARNING: Missing --installclean argument to buildbot-build.sh"
+  echo "WARNING: This is usually ok, but may cause rare odd failures."
+  echo ""
+fi
 
 echo "Executing $make_command"
 # Disable path restrictions to enable luci builds using vpython.
 eval "$make_command"
 
-if [[ $mode == "target" ]]; then
+if [[ $build_target == "yes" ]]; then
+  if [[ -z "${ANDROID_HOST_OUT}" ]]; then
+    echo "ANDROID_HOST_OUT environment variable is empty; using $out_dir/host/linux-x86"
+    ANDROID_HOST_OUT=$out_dir/host/linux-x86
+  fi
+
+  # Extract prebuilt APEXes.
+  debugfs=$ANDROID_HOST_OUT/bin/debugfs_static
+  for apex in ${apexes[@]}; do
+    dir="$ANDROID_PRODUCT_OUT/system/apex/${apex}"
+    file="$ANDROID_PRODUCT_OUT/system/apex/${apex}.apex"
+    if [ -f "${file}" ]; then
+      echo "Extracting APEX file: ${apex}"
+      rm -rf $dir
+      mkdir -p $dir
+      $ANDROID_HOST_OUT/bin/deapexer --debugfs_path $debugfs extract $file $dir
+    fi
+  done
+
+  # Replace stub libraries with implemenation libraries: because we do chroot
+  # testing, we need to install an implementation of the libraries (and cannot
+  # rely on the one already installed on the device, if the device is post R and
+  # has it).
+  implementation_libs=(
+    "heapprofd_client_api.so"
+    "libartpalette-system.so"
+    "liblog.so"
+  )
+  if [ -d prebuilts/runtime/mainline/platform/impl ]; then
+    if [[ $TARGET_ARCH = arm* ]]; then
+      arch32=arm
+      arch64=arm64
+    else
+      arch32=x86
+      arch64=x86_64
+    fi
+    for so in ${implementation_libs[@]}; do
+      if [ -d "$ANDROID_PRODUCT_OUT/system/lib" ]; then
+        cmd="cp -p prebuilts/runtime/mainline/platform/impl/$arch32/$so $ANDROID_PRODUCT_OUT/system/lib/$so"
+        echo "Executing $cmd"
+        eval "$cmd"
+      fi
+      if [ -d "$ANDROID_PRODUCT_OUT/system/lib64" ]; then
+        cmd="cp -p prebuilts/runtime/mainline/platform/impl/$arch64/$so $ANDROID_PRODUCT_OUT/system/lib64/$so"
+        echo "Executing $cmd"
+        eval "$cmd"
+      fi
+   done
+  fi
+
   # Create canonical name -> file name symlink in the symbol directory for the
   # Testing ART APEX.
   #
@@ -131,27 +206,24 @@
   link_command="mkdir -p $(dirname "$link_name") && ln -sf com.android.art.testing \"$link_name\""
   echo "Executing $link_command"
   eval "$link_command"
-  # Also provide access to symbols of binaries from the Runtime (Bionic) APEX,
-  # e.g. to support debugging in GDB.
-  find "$target_out_unstripped/apex/com.android.runtime/bin" -type f | while read target; do
-    cmd="ln -sf $target $target_out_unstripped/system/bin/$(basename $target)"
-    echo "Executing $cmd"
-    eval "$cmd"
-  done
 
   # Temporary fix for libjavacrypto.so dependencies in libcore and jvmti tests (b/147124225).
-  conscrypt_apex="$ANDROID_PRODUCT_OUT/system/apex/com.android.conscrypt"
+  conscrypt_dir="$ANDROID_PRODUCT_OUT/system/apex/com.android.conscrypt"
   conscrypt_libs="libjavacrypto.so libcrypto.so libssl.so"
-  if [ ! -d "${conscrypt_apex}" ]; then
-    echo -e "Missing conscrypt APEX in build output: ${conscrypt_apex}"
+  if [ ! -d "${conscrypt_dir}" ]; then
+    echo -e "Missing conscrypt APEX in build output: ${conscrypt_dir}"
+    exit 1
+  fi
+  if [ ! -f "${conscrypt_dir}/javalib/conscrypt.jar" ]; then
+    echo -e "Missing conscrypt jar in build output: ${conscrypt_dir}"
     exit 1
   fi
   for l in lib lib64; do
-    if [ ! -d "${conscrypt_apex}/$l" ]; then
+    if [ ! -d "$ANDROID_PRODUCT_OUT/system/$l" ]; then
       continue
     fi
     for so in $conscrypt_libs; do
-      src="${conscrypt_apex}/${l}/${so}"
+      src="${conscrypt_dir}/${l}/${so}"
       dst="$ANDROID_PRODUCT_OUT/system/${l}/${so}"
       if [ "${src}" -nt "${dst}" ]; then
         cmd="cp -p \"${src}\" \"${dst}\""
@@ -160,4 +232,138 @@
       fi
     done
   done
+
+  # TODO(b/159355595): Ensure there is a tzdata in system to avoid warnings on
+  # stderr from Bionic.
+  if [ ! -f $ANDROID_PRODUCT_OUT/system/usr/share/zoneinfo/tzdata ]; then
+    mkdir -p $ANDROID_PRODUCT_OUT/system/usr/share/zoneinfo
+    cp $ANDROID_PRODUCT_OUT/system/apex/com.android.tzdata/etc/tz/tzdata \
+      $ANDROID_PRODUCT_OUT/system/usr/share/zoneinfo/tzdata
+  fi
+
+  # Create system symlinks for the Runtime APEX. Normally handled by
+  # installSymlinkToRuntimeApex in soong/cc/binary.go, but we have to replicate
+  # it here since we don't run the install rules for the Runtime APEX.
+  for b in linker{,_asan}{,64}; do
+    echo "Symlinking /apex/com.android.runtime/bin/$b to /system/bin"
+    ln -sf /apex/com.android.runtime/bin/$b $ANDROID_PRODUCT_OUT/system/bin/$b
+  done
+  for d in $ANDROID_PRODUCT_OUT/system/apex/com.android.runtime/lib{,64}/bionic; do
+    if [ -d $d ]; then
+      for p in $d/*; do
+        lib_dir=$(expr $p : '.*/\(lib[0-9]*\)/.*')
+        lib_file=$(basename $p)
+        src=/apex/com.android.runtime/${lib_dir}/bionic/${lib_file}
+        dst=$ANDROID_PRODUCT_OUT/system/${lib_dir}/${lib_file}
+        echo "Symlinking $src into /system/${lib_dir}"
+        mkdir -p $(dirname $dst)
+        ln -sf $src $dst
+      done
+    fi
+  done
+
+  # Create linker config files. We run linkerconfig on host to avoid problems
+  # building it statically for device in an unbundled tree.
+
+  # temporary root for linkerconfig
+  linkerconfig_root=$ANDROID_PRODUCT_OUT/art_linkerconfig_root
+
+  rm -rf $linkerconfig_root
+
+  # Linkerconfig reads files from /system/etc
+  mkdir -p $linkerconfig_root/system
+  cp -r $ANDROID_PRODUCT_OUT/system/etc $linkerconfig_root/system
+
+  # For linkerconfig to pick up the APEXes correctly we need to make them
+  # available in $linkerconfig_root/apex.
+  mkdir -p $linkerconfig_root/apex
+  for apex in ${apexes[@]}; do
+    src="$ANDROID_PRODUCT_OUT/system/apex/${apex}"
+    if [[ $apex == com.android.art.* ]]; then
+      dst="$linkerconfig_root/apex/com.android.art"
+    else
+      dst="$linkerconfig_root/apex/${apex}"
+    fi
+    echo "Copying APEX directory from $src to $dst"
+    rm -rf $dst
+    cp -r $src $dst
+  done
+
+  # Linkerconfig also looks at /apex/apex-info-list.xml to check for system APEXes.
+  apex_xml_file=$linkerconfig_root/apex/apex-info-list.xml
+  echo "Creating $apex_xml_file"
+  cat <<EOF > $apex_xml_file
+<?xml version="1.0" encoding="utf-8"?>
+<apex-info-list>
+EOF
+  for apex in ${apexes[@]}; do
+    [[ $apex == com.android.art.* ]] && apex=com.android.art
+    cat <<EOF >> $apex_xml_file
+    <apex-info moduleName="${apex}" modulePath="/system/apex/${apex}.apex" preinstalledModulePath="/system/apex/${apex}.apex" versionCode="1" versionName="" isFactory="true" isActive="true">
+    </apex-info>
+EOF
+  done
+  cat <<EOF >> $apex_xml_file
+</apex-info-list>
+EOF
+
+  system_linker_config_pb=$linkerconfig_root/system/etc/linker.config.pb
+  # This list needs to be synced with provideLibs in system/etc/linker.config.pb
+  # in the targeted platform image.
+  # TODO(b/186649223): Create a prebuilt for it in platform-mainline-sdk.
+  system_provide_libs=(
+    heapprofd_client_api.so
+    libEGL.so
+    libGLESv1_CM.so
+    libGLESv2.so
+    libGLESv3.so
+    libOpenMAXAL.so
+    libOpenSLES.so
+    libRS.so
+    libaaudio.so
+    libadbd_auth.so
+    libadbd_fs.so
+    libamidi.so
+    libandroid.so
+    libandroid_net.so
+    libartpalette-system.so
+    libbinder_ndk.so
+    libc.so
+    libcamera2ndk.so
+    libcgrouprc.so
+    libclang_rt.asan-i686-android.so
+    libclang_rt.asan-x86_64-android.so
+    libdl.so
+    libdl_android.so
+    libft2.so
+    libincident.so
+    libjnigraphics.so
+    liblog.so
+    libm.so
+    libmediametrics.so
+    libmediandk.so
+    libnativewindow.so
+    libneuralnetworks_packageinfo.so
+    libselinux.so
+    libstdc++.so
+    libsync.so
+    libvndksupport.so
+    libvulkan.so
+    libz.so
+  )
+
+  echo "Encoding linker.config.json to $system_linker_config_pb"
+  $ANDROID_HOST_OUT/bin/conv_linker_config proto -s $ANDROID_BUILD_TOP/system/core/rootdir/etc/linker.config.json -o $system_linker_config_pb
+  $ANDROID_HOST_OUT/bin/conv_linker_config append -s $system_linker_config_pb -o $system_linker_config_pb --key "provideLibs" --value "${system_provide_libs[*]}"
+
+  # To avoid warnings from linkerconfig when it checks following two partitions
+  mkdir -p $linkerconfig_root/product
+  mkdir -p $linkerconfig_root/system_ext
+
+  platform_version=$(build/soong/soong_ui.bash --dumpvar-mode PLATFORM_VERSION)
+  linkerconfig_out=$ANDROID_PRODUCT_OUT/linkerconfig
+  echo "Generating linkerconfig in $linkerconfig_out"
+  rm -rf $linkerconfig_out
+  mkdir -p $linkerconfig_out
+  $ANDROID_HOST_OUT/bin/linkerconfig --target $linkerconfig_out --root $linkerconfig_root --vndk $platform_version
 fi
diff --git a/tools/buildbot-setup-device.sh b/tools/buildbot-setup-device.sh
index 54c928a..5c6ddcd 100755
--- a/tools/buildbot-setup-device.sh
+++ b/tools/buildbot-setup-device.sh
@@ -51,6 +51,13 @@
 
 seconds_per_hour=3600
 
+# b/187295147 : Disable live-lock kill daemon.
+# It can confuse long running processes for issues and kill them.
+# This usually manifests as temporarily lost adb connection.
+echo -e "${green}Killing llkd, seen killing adb${nc}"
+adb shell setprop ctl.stop llkd-0
+adb shell setprop ctl.stop llkd-1
+
 # Kill logd first, so that when we set the adb buffer size later in this file,
 # it is brought up again.
 echo -e "${green}Killing logd, seen leaking on fugu/N${nc}"
@@ -101,7 +108,7 @@
 echo -e "${green}Kill stalled dalvikvm processes${nc}"
 # 'ps' on M can sometimes hang.
 timeout 2s adb shell "ps" >/dev/null
-if [ $? = 124 ]; then
+if [[ $? == 124 ]] && [[ "$ART_TEST_RUN_ON_ARM_FVP" != true ]]; then
   echo -e "${green}Rebooting device to fix 'ps'${nc}"
   adb reboot
   adb wait-for-device root
@@ -148,7 +155,8 @@
 
   # Populate /etc in chroot with required files.
   adb shell mkdir -p "$ART_TEST_CHROOT/system/etc"
-  adb shell "cd $ART_TEST_CHROOT && ln -sf system/etc etc"
+  adb shell test -L "$ART_TEST_CHROOT/etc" \
+    || adb shell ln -s system/etc "$ART_TEST_CHROOT/etc"
 
   # Provide /proc in chroot.
   adb shell mkdir -p "$ART_TEST_CHROOT/proc"
@@ -173,4 +181,8 @@
 
   # Create /linkerconfig directory in chroot.
   adb shell mkdir -p "$ART_TEST_CHROOT/linkerconfig"
+
+  # Create /bin symlink for shebang compatibility.
+  adb shell test -L "$ART_TEST_CHROOT/bin" \
+    || adb shell ln -s system/bin "$ART_TEST_CHROOT/bin"
 fi
diff --git a/tools/buildbot-sync.sh b/tools/buildbot-sync.sh
index de83c50..00b745c 100755
--- a/tools/buildbot-sync.sh
+++ b/tools/buildbot-sync.sh
@@ -16,6 +16,8 @@
 
 # Push ART artifacts and its dependencies to a chroot directory for on-device testing.
 
+set -e
+
 if [ -t 1 ]; then
   # Color sequences if terminal is a tty.
   red='\033[0;31m'
@@ -44,52 +46,57 @@
   exit 1
 fi
 
-if [[ "$(build/soong/soong_ui.bash --dumpvar-mode TARGET_FLATTEN_APEX)" != "true" ]]; then
-  echo -e "${red}This script only works when  APEX packages are flattened, but the build" \
-    "configuration is set up to use non-flattened APEX packages.${nc}"
-  echo -e "${magenta}You can force APEX flattening by setting the environment variable" \
-    "\`OVERRIDE_TARGET_FLATTEN_APEX\` to \"true\" before starting the build and running this" \
-    "script.${nc}"
-  exit 1
-fi
 
+# Sync relevant product directories
+# ---------------------------------
 
-# `/system` "partition" synchronization.
-# --------------------------------------
+(
+  cd $ANDROID_PRODUCT_OUT
+  for dir in system/* linkerconfig data; do
+    [ -d $dir ] || continue
+    if [ $dir == system/apex ]; then
+      # We sync the APEXes later.
+      continue
+    fi
+    echo -e "${green}Syncing $dir directory...${nc}"
+    adb shell mkdir -p "$ART_TEST_CHROOT/$dir"
+    adb push $dir "$ART_TEST_CHROOT/$(dirname $dir)"
+  done
+)
 
-# Sync the system directory to the chroot.
-echo -e "${green}Syncing system directory...${nc}"
-adb shell mkdir -p "$ART_TEST_CHROOT/system"
-adb push "$ANDROID_PRODUCT_OUT/system" "$ART_TEST_CHROOT/"
 # Overwrite the default public.libraries.txt file with a smaller one that
 # contains only the public libraries pushed to the chroot directory.
 adb push "$ANDROID_BUILD_TOP/art/tools/public.libraries.buildbot.txt" \
   "$ART_TEST_CHROOT/system/etc/public.libraries.txt"
 
+# Create the framework directory if it doesn't exist. Some gtests need it.
+adb shell mkdir -p "$ART_TEST_CHROOT/system/framework"
 
 # APEX packages activation.
 # -------------------------
 
+adb shell mkdir -p "$ART_TEST_CHROOT/apex"
+
 # Manually "activate" the flattened APEX $1 by syncing it to /apex/$2 in the
 # chroot. $2 defaults to $1.
-#
-# TODO: Handle the case of build targets using non-flatted APEX packages.
-# As a workaround, one can run `export OVERRIDE_TARGET_FLATTEN_APEX=true` before building
-# a target to have its APEX packages flattened.
 activate_apex() {
   local src_apex=${1}
   local dst_apex=${2:-${src_apex}}
+
+  # Unpack the .apex file in the product directory, but if we already see a
+  # directory we assume buildbot-build.sh has already done it for us and just
+  # use it.
+  src_apex_path=$ANDROID_PRODUCT_OUT/system/apex/${src_apex}
+  if [ ! -d $src_apex_path ]; then
+    echo -e "${green}Extracting APEX ${src_apex}.apex...${nc}"
+    mkdir -p $src_apex_path
+    $ANDROID_HOST_OUT/bin/deapexer --debugfs_path $ANDROID_HOST_OUT/bin/debugfs_static \
+      extract ${src_apex_path}.apex $src_apex_path
+  fi
+
   echo -e "${green}Activating APEX ${src_apex} as ${dst_apex}...${nc}"
-  # We move the files from `/system/apex/${src_apex}` to `/apex/${dst_apex}` in
-  # the chroot directory, instead of simply using a symlink, as Bionic's linker
-  # relies on the real path name of a binary (e.g.
-  # `/apex/com.android.art/bin/dex2oat`) to select the linker configuration.
-  adb shell mkdir -p "$ART_TEST_CHROOT/apex"
   adb shell rm -rf "$ART_TEST_CHROOT/apex/${dst_apex}"
-  # Use use mv instead of cp, as cp has a bug on fugu NRD90R where symbolic
-  # links get copied with odd names, eg: libcrypto.so -> /system/lib/libcrypto.soe.sort.so
-  adb shell mv "$ART_TEST_CHROOT/system/apex/${src_apex}" "$ART_TEST_CHROOT/apex/${dst_apex}" \
-    || exit 1
+  adb push $src_apex_path "$ART_TEST_CHROOT/apex/${dst_apex}"
 }
 
 # "Activate" the required APEX modules.
@@ -98,32 +105,4 @@
 activate_apex com.android.runtime
 activate_apex com.android.tzdata
 activate_apex com.android.conscrypt
-
-
-# Linker configuration.
-# ---------------------
-
-# Statically linked `linkerconfig` binary.
-linkerconfig_binary="/system/bin/linkerconfig"
-# Generated linker configuration file path (since Android R).
-ld_generated_config_file_path="/linkerconfig/ld.config.txt"
-# Location of the generated linker configuration file.
-ld_generated_config_file_location=$(dirname "$ld_generated_config_file_path")
-
-# Generate linker configuration files on device.
-echo -e "${green}Generating linker configuration files on device in" \
-  "\`$ld_generated_config_file_path\`${nc}..."
-adb shell chroot "$ART_TEST_CHROOT" \
-  "$linkerconfig_binary" --target "$ld_generated_config_file_location" || exit 1
-ld_generated_config_files=$(adb shell find $ART_TEST_CHROOT/linkerconfig ! -type d | sed 's/^/  /')
-echo -e "${green}Generated linker configuration files on device:${nc}"
-echo -e "${green}$ld_generated_config_files${nc}"
-
-
-# `/data` "partition" synchronization.
-# ------------------------------------
-
-# Sync the data directory to the chroot.
-echo -e "${green}Syncing data directory...${nc}"
-adb shell mkdir -p "$ART_TEST_CHROOT/data"
-adb push "$ANDROID_PRODUCT_OUT/data" "$ART_TEST_CHROOT/"
+activate_apex com.android.os.statsd
diff --git a/tools/buildbot-teardown-device.sh b/tools/buildbot-teardown-device.sh
index e067a70..3a75bbd 100755
--- a/tools/buildbot-teardown-device.sh
+++ b/tools/buildbot-teardown-device.sh
@@ -92,6 +92,9 @@
            fi
     }
 
+    # Remove /bin symlink from chroot.
+    adb shell rm -f "$ART_TEST_CHROOT/bin"
+
     # Remove /apex from chroot.
     adb shell rm -rf "$ART_TEST_CHROOT/apex"
 
diff --git a/tools/checker/README b/tools/checker/README
index 8a6b128..b04b0d8 100644
--- a/tools/checker/README
+++ b/tools/checker/README
@@ -1,20 +1,21 @@
 Checker is a testing tool which compiles a given test file and compares the
 state of the control-flow graph before and after each optimization pass
-against a set of assertions specified alongside the tests.
+against a set of statements specified alongside the tests.
 
 Tests are written in Java or Smali, turned into DEX and compiled with the
-Optimizing compiler. "Check lines" are assertions formatted as comments of the
+Optimizing compiler. "Check lines" are statements formatted as comments of the
 source file. They begin with prefix "/// CHECK" or "## CHECK", respectively,
 followed by a pattern that the engine attempts to match in the compiler output.
 
-Assertions are tested in groups which correspond to the individual compiler
+Statements are tested in groups which correspond to the individual compiler
 passes. Each group of check lines therefore must start with a 'CHECK-START'
 header which specifies the output group it should be tested against. The group
 name must exactly match one of the groups recognized in the output (they can
 be listed with the '--list-passes' command-line flag).
 
 Matching of check lines is carried out in the order of appearance in the
-source file. There are three types of check lines:
+source file. There are five types of check lines. Branching instructions are
+also supported and documented later in this file.
  - CHECK:      Must match an output line which appears in the output group
                later than lines matched against any preceeding checks. Output
                lines must therefore match the check lines in the same order.
@@ -27,10 +28,10 @@
                later than lines matched against any preceeding checks and
                earlier than lines matched against any subsequent checks.
                Surrounding non-negative checks (or boundaries of the group)
-               therefore create a scope within which the assertion is verified.
+               therefore create a scope within which the statement is verified.
  - CHECK-NEXT: Must match the output line which comes right after the line which
-               matched the previous check. Cannot be used after any but the
-               in-order CHECK.
+               matched the previous check. Can only be used after a CHECK or
+               another CHECK-NEXT.
  - CHECK-EVAL: Specifies a Python expression which must evaluate to 'True'.
 
 Check-line patterns are treated as plain text rather than regular expressions
@@ -47,7 +48,7 @@
 be redefined or used undefined.
 
 Example:
-  The following assertions can be placed in a Java source file:
+  The following statements can be placed in a Java source file:
 
   /// CHECK-START: int MyClass.MyMethod() constant_folding (after)
   /// CHECK:         <<ID:i\d+>>  IntConstant {{11|22}}
@@ -83,3 +84,67 @@
 match. An example line looks like:
 
   /// CHECK-START-{X86_64,ARM,ARM64}: int MyClass.MyMethod() constant_folding (after)
+
+
+Branching is possible thanks to the following statements:
+ - CHECK-IF:
+ - CHECK-ELIF:
+ - CHECK-ELSE:
+ - CHECK-FI:
+
+CHECK-IF and CHECK-ELIF take a Python expression as input that will be evaluated by `eval`.
+
+A possible use case of branching is to check whether the generated code exploits the instruction
+architecture features enabled at compile time. For that purpose, you can call the custom made
+function isaHasFeature("feature_name").
+
+Example:
+  /// CHECK-START-ARM64: int other.TestByte.testDotProdComplex(byte[], byte[]) disassembly (after)
+  /// CHECK:        VecDotProd
+  /// CHECK-IF:     isaHasFeature("dotprod")
+  ///               CHECK:        sdot
+  /// CHECK-ELSE:
+  ///               CHECK-NOT:    sdot
+  /// CHECK-FI:
+
+Like CHECK-EVAL, CHECK-IF and CHECK-ELIF support only referencing of variables, defining new
+variables as part of the statement input is not allowed. Any other surrounding text will be passed
+to Python's `eval` as is. CHECK-ELSE and CHECK-FI must not have any input.
+
+Example:
+  /// CHECK-START: int MyClass.MyMethod() constant_folding (after)
+  /// CHECK:        {{i\d+}} IntConstant <<MyConst:(0|1|2)>>
+  /// CHECK-IF:     <<MyConst>> == 0
+  ///               CHECK-NEXT:            FooBar01
+  /// CHECK-ELIF:   <<MyConst>> == 1
+  ///               CHECK-NOT:             FooBar01
+  /// CHECK-FI:
+
+Branch blocks can contain any statement, including CHECK-NEXT and CHECK-DAG.
+Notice the CHECK-NEXT statement within the IF branch. When a CHECK-NEXT is encountered,
+Checker expects that the previously executed statement was either a CHECK or a CHECK-NEXT.
+This condition is enforced at runtime, and an error is thrown if it's not respected.
+
+Statements inside branches can define new variables. If a new variable gets defined inside a branch
+(of any depth, since nested branching is allowed), that variable will become global within the scope
+of the defining group. In other words, it will be valid everywhere after its definition within the
+block defined by the CHECK-START statement. The absence of lexical scoping for Checker variables
+seems a bit inelegant at first, but is probably more practical.
+
+Example:
+  /// CHECK-START: void MyClass.FooBar() liveness (after)
+  /// CHECK-IF:     os.environ.get('ART_READ_BARRIER_TYPE') != 'TABLELOOKUP'
+  ///               CHECK:                 <<MyID:i\d+>> IntConstant 3
+  /// CHECK-ELSE:
+  ///               CHECK:                 <<MyID:i\d+>> IntConstant 5
+  /// CHECK-FI:
+  /// CHECK-NEXT:   Return [<<MyID>>]
+
+Notice that the variable MyID remained valid outside the branch where it was defined.
+Furthermore, in this example, the definition of MyID depends on which branch gets selected at
+runtime. Attempting to re-define a variable or referencing an undefined variable is not allowed,
+Checker will throw a runtime error.
+The example above also shows how we can use environment variables to perform custom checks.
+
+It is possible to combine IF, (multiple) ELIF and ELSE statements together. Nested branching is
+also supported.
diff --git a/tools/checker/checker.py b/tools/checker/checker.py
index 65b01a7..ec933f6 100755
--- a/tools/checker/checker.py
+++ b/tools/checker/checker.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 #
 # Copyright (C) 2014 The Android Open Source Project
 #
@@ -17,13 +17,14 @@
 import argparse
 import os
 
-from common.archs                     import archs_list
-from common.logger                    import Logger
-from file_format.c1visualizer.parser  import ParseC1visualizerStream
-from file_format.checker.parser       import ParseCheckerStream
-from match.file                       import MatchFiles
+from common.archs import archs_list
+from common.logger import Logger
+from file_format.c1visualizer.parser import parse_c1_visualizer_stream
+from file_format.checker.parser import parse_checker_stream
+from match.file import match_files
 
-def ParseArguments():
+
+def parse_arguments():
   parser = argparse.ArgumentParser()
   parser.add_argument("tested_file",
                       help="text file the checks should be verified against")
@@ -39,71 +40,76 @@
                       help="Run tests for the specified target architecture.")
   parser.add_argument("--debuggable", action="store_true",
                       help="Run tests for debuggable code.")
+  parser.add_argument("--print-cfg", action="store_true", default="True", dest="print_cfg",
+                      help="Print the whole cfg file in case of test failure (default)")
+  parser.add_argument("--no-print-cfg", action="store_false", default="True", dest="print_cfg",
+                      help="Don't print the whole cfg file in case of test failure")
   parser.add_argument("-q", "--quiet", action="store_true",
                       help="print only errors")
   return parser.parse_args()
 
 
-def ListPasses(outputFilename):
-  c1File = ParseC1visualizerStream(os.path.basename(outputFilename), open(outputFilename, "r"))
-  for compiler_pass in c1File.passes:
+def list_passes(output_filename):
+  c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r"))
+  for compiler_pass in c1_file.passes:
     Logger.log(compiler_pass.name)
 
 
-def DumpPass(outputFilename, passName):
-  c1File = ParseC1visualizerStream(os.path.basename(outputFilename), open(outputFilename, "r"))
-  compiler_pass = c1File.findPass(passName)
+def dump_pass(output_filename, pass_name):
+  c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r"))
+  compiler_pass = c1_file.find_pass(pass_name)
   if compiler_pass:
-    maxLineNo = compiler_pass.startLineNo + len(compiler_pass.body)
-    lenLineNo = len(str(maxLineNo)) + 2
-    curLineNo = compiler_pass.startLineNo
+    max_line_no = compiler_pass.start_line_no + len(compiler_pass.body)
+    len_line_no = len(str(max_line_no)) + 2
+    cur_line_no = compiler_pass.start_line_no
     for line in compiler_pass.body:
-      Logger.log((str(curLineNo) + ":").ljust(lenLineNo) + line)
-      curLineNo += 1
+      Logger.log((str(cur_line_no) + ":").ljust(len_line_no) + line)
+      cur_line_no += 1
   else:
-    Logger.fail("Pass \"" + passName + "\" not found in the output")
+    Logger.fail('Pass "{}" not found in the output'.format(pass_name))
 
 
-def FindCheckerFiles(path):
+def find_checker_files(path):
   """ Returns a list of files to scan for check annotations in the given path.
       Path to a file is returned as a single-element list, directories are
-      recursively traversed and all '.java' and '.smali' files returned.
+      recursively traversed and all '.java', '.j', and '.smali' files returned.
   """
   if not path:
     Logger.fail("No source path provided")
   elif os.path.isfile(path):
-    return [ path ]
+    return [path]
   elif os.path.isdir(path):
-    foundFiles = []
+    found_files = []
     for root, dirs, files in os.walk(path):
       for file in files:
         extension = os.path.splitext(file)[1]
-        if extension in [".java", ".smali"]:
-          foundFiles.append(os.path.join(root, file))
-    return foundFiles
+        if extension in [".java", ".smali", ".j"]:
+          found_files.append(os.path.join(root, file))
+    return found_files
   else:
-    Logger.fail("Source path \"" + path + "\" not found")
+    Logger.fail('Source path "{}" not found'.format(path))
 
 
-def RunTests(checkPrefix, checkPath, outputFilename, targetArch, debuggableMode):
-  c1File = ParseC1visualizerStream(os.path.basename(outputFilename), open(outputFilename, "r"))
-  for checkFilename in FindCheckerFiles(checkPath):
-    checkerFile = ParseCheckerStream(os.path.basename(checkFilename),
-                                     checkPrefix,
-                                     open(checkFilename, "r"),
-                                     targetArch)
-    MatchFiles(checkerFile, c1File, targetArch, debuggableMode)
+def run_tests(check_prefix, check_path, output_filename, target_arch, debuggable_mode, print_cfg):
+  c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r"))
+  for check_filename in find_checker_files(check_path):
+    checker_file = parse_checker_stream(os.path.basename(check_filename),
+                                        check_prefix,
+                                        open(check_filename, "r"),
+                                        target_arch)
+    match_files(checker_file, c1_file, target_arch, debuggable_mode, print_cfg)
 
 
 if __name__ == "__main__":
-  args = ParseArguments()
+  args = parse_arguments()
 
   if args.quiet:
-    Logger.Verbosity = Logger.Level.Error
+    Logger.Verbosity = Logger.Level.ERROR
 
   if args.list_passes:
-    ListPasses(args.tested_file)
+    list_passes(args.tested_file)
   elif args.dump_pass:
-    DumpPass(args.tested_file, args.dump_pass)
+    dump_pass(args.tested_file, args.dump_pass)
   else:
-    RunTests(args.check_prefix, args.source_path, args.tested_file, args.arch, args.debuggable)
+    run_tests(args.check_prefix, args.source_path, args.tested_file, args.arch, args.debuggable,
+              args.print_cfg)
diff --git a/tools/checker/common/archs.py b/tools/checker/common/archs.py
index 9628c88..6781fbf 100644
--- a/tools/checker/common/archs.py
+++ b/tools/checker/common/archs.py
@@ -12,4 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-archs_list = ['ARM', 'ARM64', 'X86', 'X86_64']
+archs_list = ["ARM", "ARM64", "X86", "X86_64"]
diff --git a/tools/checker/common/immutables.py b/tools/checker/common/immutables.py
index e016867..3a29ce3 100644
--- a/tools/checker/common/immutables.py
+++ b/tools/checker/common/immutables.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+
 class ImmutableDict(dict):
   def __setitem__(self, key, value):
     raise RuntimeError("Cannot modify ImmutableDict")
@@ -19,7 +20,7 @@
   def __delitem__(self, key):
     raise RuntimeError("Cannot modify ImmutableDict")
 
-  def copyWith(self, key, value):
-    newDict = ImmutableDict(self)
-    dict.__setitem__(newDict, key, value)
-    return newDict
+  def copy_with(self, key, value):
+    new_dict = ImmutableDict(self)
+    dict.__setitem__(new_dict, key, value)
+    return new_dict
diff --git a/tools/checker/common/logger.py b/tools/checker/common/logger.py
index f13eaf6..1a65c73 100644
--- a/tools/checker/common/logger.py
+++ b/tools/checker/common/logger.py
@@ -12,54 +12,55 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
 import collections
+import enum
 import sys
 
-class Logger(object):
 
-  class Level(object):
-    NoOutput, Error, Info = range(3)
+class Logger:
+  class Level(enum.IntEnum):
+    NO_OUTPUT, ERROR, INFO = range(3)
 
-  class Color(object):
-    Default, Blue, Gray, Purple, Red, Green = range(6)
+  class Color(enum.Enum):
+    DEFAULT, BLUE, GRAY, PURPLE, RED, GREEN = range(6)
 
     @staticmethod
-    def terminalCode(color, out=sys.stdout):
+    def terminal_code(color, out=sys.stdout):
       if not out.isatty():
-        return ''
-      elif color == Logger.Color.Blue:
-        return '\033[94m'
-      elif color == Logger.Color.Gray:
-        return '\033[37m'
-      elif color == Logger.Color.Purple:
-        return '\033[95m'
-      elif color == Logger.Color.Red:
-        return '\033[91m'
-      elif color == Logger.Color.Green:
-        return '\033[32m'
+        return ""
+      elif color == Logger.Color.BLUE:
+        return "\033[94m"
+      elif color == Logger.Color.GRAY:
+        return "\033[37m"
+      elif color == Logger.Color.PURPLE:
+        return "\033[95m"
+      elif color == Logger.Color.RED:
+        return "\033[91m"
+      elif color == Logger.Color.GREEN:
+        return "\033[32m"
       else:
-        return '\033[0m'
+        return "\033[0m"
 
-  Verbosity = Level.Info
+  Verbosity = Level.INFO
 
   @staticmethod
-  def log(text, level=Level.Info, color=Color.Default, newLine=True, out=sys.stdout):
+  def log(content, level=Level.INFO, color=Color.DEFAULT, new_line=True, out=sys.stdout):
     if level <= Logger.Verbosity:
-      text = Logger.Color.terminalCode(color, out) + text + \
-             Logger.Color.terminalCode(Logger.Color.Default, out)
-      if newLine:
-        print(text, file=out)
+      content = "{}{}{}".format(Logger.Color.terminal_code(color, out), content,
+                                Logger.Color.terminal_code(Logger.Color.DEFAULT, out))
+      if new_line:
+        print(content, file=out)
       else:
-        print(text, end="", file=out)
+        print(content, end="", file=out)
       out.flush()
 
   @staticmethod
-  def fail(msg, file=None, line=-1, lineText=None, variables=None):
-    Logger.log("error: ", Logger.Level.Error, color=Logger.Color.Red, newLine=False, out=sys.stderr)
-    Logger.log(msg, Logger.Level.Error, out=sys.stderr)
+  def fail(msg, file=None, line=-1, line_text=None, variables=None):
+    Logger.log("error: ", Logger.Level.ERROR, color=Logger.Color.RED, new_line=False,
+               out=sys.stderr)
+    Logger.log(msg, Logger.Level.ERROR, out=sys.stderr)
 
-    if lineText:
+    if line_text:
       loc = ""
       if file:
         loc += file + ":"
@@ -67,33 +68,33 @@
         loc += str(line) + ":"
       if loc:
         loc += " "
-      Logger.log(loc, Logger.Level.Error, color=Logger.Color.Gray, newLine=False, out=sys.stderr)
-      Logger.log(lineText, Logger.Level.Error, out=sys.stderr)
+      Logger.log(loc, Logger.Level.ERROR, color=Logger.Color.GRAY, new_line=False,
+                 out=sys.stderr)
+      Logger.log(line_text, Logger.Level.ERROR, out=sys.stderr)
 
     if variables:
-      longestName = 0
-      for var in variables:
-        longestName = max(longestName, len(var))
+      longest_name = max(len(var) for var in variables)
 
       for var in collections.OrderedDict(sorted(variables.items())):
-        padding = ' ' * (longestName - len(var))
-        Logger.log(var, Logger.Level.Error, color=Logger.Color.Green, newLine=False, out=sys.stderr)
-        Logger.log(padding, Logger.Level.Error, newLine=False, out=sys.stderr)
-        Logger.log(" = ", Logger.Level.Error, newLine=False, out=sys.stderr)
-        Logger.log(variables[var], Logger.Level.Error, out=sys.stderr)
+        padding = " " * (longest_name - len(var))
+        Logger.log(var, Logger.Level.ERROR, color=Logger.Color.GREEN, new_line=False,
+                   out=sys.stderr)
+        Logger.log(padding, Logger.Level.ERROR, new_line=False, out=sys.stderr)
+        Logger.log(" = ", Logger.Level.ERROR, new_line=False, out=sys.stderr)
+        Logger.log(variables[var], Logger.Level.ERROR, out=sys.stderr)
 
     sys.exit(1)
 
   @staticmethod
-  def startTest(name):
-    Logger.log("TEST ", color=Logger.Color.Purple, newLine=False)
-    Logger.log(name + "... ", newLine=False)
+  def start_test(name):
+    Logger.log("TEST ", color=Logger.Color.PURPLE, new_line=False)
+    Logger.log(name + "... ", new_line=False)
 
   @staticmethod
-  def testPassed():
-    Logger.log("PASS", color=Logger.Color.Blue)
+  def test_passed():
+    Logger.log("PASS", color=Logger.Color.BLUE)
 
   @staticmethod
-  def testFailed(msg, assertion, variables):
-    Logger.log("FAIL", color=Logger.Color.Red)
-    Logger.fail(msg, assertion.fileName, assertion.lineNo, assertion.originalText, variables)
+  def test_failed(msg, statement, variables):
+    Logger.log("FAIL", color=Logger.Color.RED)
+    Logger.fail(msg, statement.filename, statement.line_no, statement.original_text, variables)
diff --git a/tools/checker/common/mixins.py b/tools/checker/common/mixins.py
index 819de24..81bd2a8 100644
--- a/tools/checker/common/mixins.py
+++ b/tools/checker/common/mixins.py
@@ -16,11 +16,11 @@
   """ Object equality via equality of dictionaries. """
 
   def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.__dict__ == other.__dict__
+    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
 
 class PrintableMixin:
   """ Prints object as name-dictionary pair. """
 
   def __repr__(self):
-    return "<%s: %s>" % (type(self).__name__, str(self.__dict__))
+    return "<{}: {}>".format(type(self).__name__, str(self.__dict__))
diff --git a/tools/checker/common/testing.py b/tools/checker/common/testing.py
deleted file mode 100644
index 1299c07..0000000
--- a/tools/checker/common/testing.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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.
-
-def ToUnicode(string):
-  """ Converts a string into Unicode.
-
-  This is a delegate function for the built-in `unicode`. It checks if the input
-  is not `None`, because `unicode` turns it into an actual "None" string.
-  """
-  assert string is not None
-  return unicode(string)
diff --git a/tools/checker/file_format/c1visualizer/parser.py b/tools/checker/file_format/c1visualizer/parser.py
index bdcde9d..55efbd7 100644
--- a/tools/checker/file_format/c1visualizer/parser.py
+++ b/tools/checker/file_format/c1visualizer/parser.py
@@ -12,20 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from common.logger                   import Logger
-from file_format.common              import SplitStream
+from common.logger import Logger
+from file_format.common import split_stream
 from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
 
 import re
 
+
 class C1ParserState:
-  OutsideBlock, InsideCompilationBlock, StartingCfgBlock, InsideCfgBlock = range(4)
+  OUTSIDE_BLOCK, INSIDE_COMPILATION_BLOCK, STARTING_CFG_BLOCK, INSIDE_CFG_BLOCK = range(4)
 
   def __init__(self):
-    self.currentState = C1ParserState.OutsideBlock
-    self.lastMethodName = None
+    self.current_state = C1ParserState.OUTSIDE_BLOCK
+    self.last_method_name = None
 
-def __parseC1Line(line, lineNo, state, fileName):
+
+def _parse_c1_line(c1_file, line, line_no, state, filename):
   """ This function is invoked on each line of the output file and returns
       a triplet which instructs the parser how the line should be handled. If the
       line is to be included in the current group, it is returned in the first
@@ -34,57 +36,80 @@
       function prototype compatible with `SplitStream` and is always set to
       `None` here.
   """
-  if state.currentState == C1ParserState.StartingCfgBlock:
+  if state.current_state == C1ParserState.STARTING_CFG_BLOCK:
     # Previous line started a new 'cfg' block which means that this one must
     # contain the name of the pass (this is enforced by C1visualizer).
-    if re.match("name\s+\"[^\"]+\"", line):
+    if re.match(r'name\s+"[^"]+"', line):
       # Extract the pass name, prepend it with the name of the method and
       # return as the beginning of a new group.
-      state.currentState = C1ParserState.InsideCfgBlock
-      return (None, state.lastMethodName + " " + line.split("\"")[1], None)
+      state.current_state = C1ParserState.INSIDE_CFG_BLOCK
+      return None, state.last_method_name + " " + line.split('"')[1], None
     else:
-      Logger.fail("Expected output group name", fileName, lineNo)
+      Logger.fail("Expected output group name", filename, line_no)
 
-  elif state.currentState == C1ParserState.InsideCfgBlock:
+  elif state.current_state == C1ParserState.INSIDE_CFG_BLOCK:
     if line == "end_cfg":
-      state.currentState = C1ParserState.OutsideBlock
-      return (None, None, None)
+      state.current_state = C1ParserState.OUTSIDE_BLOCK
+      return None, None, None
     else:
-      return (line, None, None)
+      return line, None, None
 
-  elif state.currentState == C1ParserState.InsideCompilationBlock:
+  elif state.current_state == C1ParserState.INSIDE_COMPILATION_BLOCK:
     # Search for the method's name. Format: method "<name>"
-    if re.match("method\s+\"[^\"]*\"", line):
-      methodName = line.split("\"")[1].strip()
-      if not methodName:
-        Logger.fail("Empty method name in output", fileName, lineNo)
-      state.lastMethodName = methodName
+    if re.match(r'method\s+"[^"]*"', line):
+      method_name = line.split('"')[1].strip()
+      if not method_name:
+        Logger.fail("Empty method name in output", filename, line_no)
+
+      match = re.search(r"isa_features:([\w,-]+)", method_name)
+      if match:
+        raw_features = match.group(1).split(",")
+        # Create a map of features in the form {feature_name: is_enabled}.
+        features = {}
+        for rf in raw_features:
+          feature_name = rf
+          is_enabled = True
+          # A '-' in front of the feature name indicates that the feature wasn't enabled at compile
+          # time.
+          if rf[0] == "-":
+            feature_name = rf[1:]
+            is_enabled = False
+          features[feature_name] = is_enabled
+
+        c1_file.set_isa_features(features)
+      else:
+        state.last_method_name = method_name
     elif line == "end_compilation":
-      state.currentState = C1ParserState.OutsideBlock
-    return (None, None, None)
+      state.current_state = C1ParserState.OUTSIDE_BLOCK
+    return None, None, None
 
   else:
-    assert state.currentState == C1ParserState.OutsideBlock
+    assert state.current_state == C1ParserState.OUTSIDE_BLOCK
     if line == "begin_cfg":
       # The line starts a new group but we'll wait until the next line from
       # which we can extract the name of the pass.
-      if state.lastMethodName is None:
-        Logger.fail("Expected method header", fileName, lineNo)
-      state.currentState = C1ParserState.StartingCfgBlock
-      return (None, None, None)
+      if state.last_method_name is None:
+        Logger.fail("Expected method header", filename, line_no)
+      state.current_state = C1ParserState.STARTING_CFG_BLOCK
+      return None, None, None
     elif line == "begin_compilation":
-      state.currentState = C1ParserState.InsideCompilationBlock
-      return (None, None, None)
+      state.current_state = C1ParserState.INSIDE_COMPILATION_BLOCK
+      return None, None, None
     else:
-      Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
+      Logger.fail("C1visualizer line not inside a group", filename, line_no)
 
-def ParseC1visualizerStream(fileName, stream):
-  c1File = C1visualizerFile(fileName)
+
+def parse_c1_visualizer_stream(filename, stream):
+  c1_file = C1visualizerFile(filename)
   state = C1ParserState()
-  fnProcessLine = lambda line, lineNo: __parseC1Line(line, lineNo, state, fileName)
-  fnLineOutsideChunk = lambda line, lineNo: \
-      Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
-  for passName, passLines, startLineNo, testArch in \
-      SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
-    C1visualizerPass(c1File, passName, passLines, startLineNo + 1)
-  return c1File
+
+  def fn_process_line(line, line_no):
+    return _parse_c1_line(c1_file, line, line_no, state, c1_file.base_file_name)
+
+  def fn_line_outside_chunk(line, line_no):
+    Logger.fail("C1visualizer line not inside a group", c1_file.base_file_name, line_no)
+
+  for pass_name, pass_lines, start_line_no, test_arch in split_stream(stream, fn_process_line,
+                                                                      fn_line_outside_chunk):
+    C1visualizerPass(c1_file, pass_name, pass_lines, start_line_no + 1)
+  return c1_file
diff --git a/tools/checker/file_format/c1visualizer/struct.py b/tools/checker/file_format/c1visualizer/struct.py
index 991564e..9428a0e 100644
--- a/tools/checker/file_format/c1visualizer/struct.py
+++ b/tools/checker/file_format/c1visualizer/struct.py
@@ -12,49 +12,57 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import os
+
+from common.immutables import ImmutableDict
 from common.logger import Logger
 from common.mixins import PrintableMixin
 
+
 class C1visualizerFile(PrintableMixin):
-
-  def __init__(self, fileName):
-    self.fileName = fileName
+  def __init__(self, filename):
+    self.base_file_name = os.path.basename(filename)
+    self.full_file_name = filename
     self.passes = []
+    self.instruction_set_features = ImmutableDict()
 
-  def addPass(self, new_pass):
+  def set_isa_features(self, features):
+    self.instruction_set_features = ImmutableDict(features)
+
+  def add_pass(self, new_pass):
     self.passes.append(new_pass)
 
-  def findPass(self, name):
+  def find_pass(self, name):
     for entry in self.passes:
       if entry.name == name:
         return entry
     return None
 
   def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.passes == other.passes
+    return (isinstance(other, self.__class__)
+            and self.passes == other.passes
+            and self.instruction_set_features == other.instruction_set_features)
 
 
 class C1visualizerPass(PrintableMixin):
-
-  def __init__(self, parent, name, body, startLineNo):
+  def __init__(self, parent, name, body, start_line_no):
     self.parent = parent
     self.name = name
     self.body = body
-    self.startLineNo = startLineNo
+    self.start_line_no = start_line_no
 
     if not self.name:
-      Logger.fail("C1visualizer pass does not have a name", self.fileName, self.startLineNo)
+      Logger.fail("C1visualizer pass does not have a name", self.filename, self.start_line_no)
     if not self.body:
-      Logger.fail("C1visualizer pass does not have a body", self.fileName, self.startLineNo)
+      Logger.fail("C1visualizer pass does not have a body", self.filename, self.start_line_no)
 
-    self.parent.addPass(self)
+    self.parent.add_pass(self)
 
   @property
-  def fileName(self):
-    return self.parent.fileName
+  def filename(self):
+    return self.parent.base_file_name
 
   def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.name == other.name \
-       and self.body == other.body
+    return (isinstance(other, self.__class__)
+            and self.name == other.name
+            and self.body == other.body)
diff --git a/tools/checker/file_format/c1visualizer/test.py b/tools/checker/file_format/c1visualizer/test.py
index 812a4cf..8c3cce4 100644
--- a/tools/checker/file_format/c1visualizer/test.py
+++ b/tools/checker/file_format/c1visualizer/test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 #
 # Copyright (C) 2014 The Android Open Source Project
 #
@@ -14,34 +14,38 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from common.testing                  import ToUnicode
-from file_format.c1visualizer.parser import ParseC1visualizerStream
+from common.immutables import ImmutableDict
+from file_format.c1visualizer.parser import parse_c1_visualizer_stream
 from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
 
 import io
 import unittest
 
+
 class C1visualizerParser_Test(unittest.TestCase):
 
-  def createFile(self, passList):
+  def create_file(self, data):
     """ Creates an instance of CheckerFile from provided info.
 
-    Data format: [ ( <case-name>, [ ( <text>, <assert-variant> ), ... ] ), ... ]
+    Data format: ( [ <isa-feature>, ... ],
+                   [ ( <case-name>, [ ( <text>, <assert-variant> ), ... ] ), ... ]
+                 )
     """
-    c1File = C1visualizerFile("<c1_file>")
-    for passEntry in passList:
-      passName = passEntry[0]
-      passBody = passEntry[1]
-      c1Pass = C1visualizerPass(c1File, passName, passBody, 0)
-    return c1File
+    c1_file = C1visualizerFile("<c1_file>")
+    c1_file.instruction_set_features = data[0]
+    for pass_entry in data[1]:
+      pass_name = pass_entry[0]
+      pass_body = pass_entry[1]
+      c1_pass = C1visualizerPass(c1_file, pass_name, pass_body, 0)
+    return c1_file
 
-  def assertParsesTo(self, c1Text, expectedData):
-    expectedFile = self.createFile(expectedData)
-    actualFile = ParseC1visualizerStream("<c1_file>", io.StringIO(ToUnicode(c1Text)))
-    return self.assertEqual(expectedFile, actualFile)
+  def assertParsesTo(self, c1_text, expected_data):
+    expected_file = self.create_file(expected_data)
+    actual_file = parse_c1_visualizer_stream("<c1_file>", io.StringIO(c1_text))
+    return self.assertEqual(expected_file, actual_file)
 
   def test_EmptyFile(self):
-    self.assertParsesTo("", [])
+    self.assertParsesTo("", (ImmutableDict(), []))
 
   def test_SingleGroup(self):
     self.assertParsesTo(
@@ -55,7 +59,9 @@
           bar
         end_cfg
       """,
-      [ ( "MyMethod pass1", [ "foo", "bar" ] ) ])
+      (ImmutableDict(), [
+        ("MyMethod pass1", ["foo", "bar"])
+      ]))
 
   def test_MultipleGroups(self):
     self.assertParsesTo(
@@ -76,8 +82,10 @@
           def
         end_cfg
       """,
-      [ ( "MyMethod1 pass1", [ "foo", "bar" ] ),
-        ( "MyMethod1 pass2", [ "abc", "def" ] ) ])
+      (ImmutableDict(), [
+        ("MyMethod1 pass1", ["foo", "bar"]),
+        ("MyMethod1 pass2", ["abc", "def"])
+      ]))
     self.assertParsesTo(
       """
         begin_compilation
@@ -101,5 +109,69 @@
           def
         end_cfg
       """,
-      [ ( "MyMethod1 pass1", [ "foo", "bar" ] ),
-        ( "MyMethod2 pass2", [ "abc", "def" ] ) ])
+      (ImmutableDict(), [
+        ("MyMethod1 pass1", ["foo", "bar"]),
+        ("MyMethod2 pass2", ["abc", "def"])
+      ]))
+
+  def test_InstructionSetFeatures(self):
+    self.assertParsesTo(
+      """
+        begin_compilation
+          name "isa_features:feature1,-feature2"
+          method "isa_features:feature1,-feature2"
+          date 1234
+        end_compilation
+      """,
+      (ImmutableDict({"feature1": True, "feature2": False}), []))
+    self.assertParsesTo(
+      """
+        begin_compilation
+          name "isa_features:feature1,-feature2"
+          method "isa_features:feature1,-feature2"
+          date 1234
+        end_compilation
+        begin_compilation
+          name "xyz1"
+          method "MyMethod1"
+          date 1234
+        end_compilation
+        begin_cfg
+          name "pass1"
+          foo
+          bar
+        end_cfg
+      """,
+      (ImmutableDict({"feature1": True, "feature2": False}), [
+        ("MyMethod1 pass1", ["foo", "bar"])
+      ]))
+    self.assertParsesTo(
+      """
+        begin_compilation
+          name "isa:some_isa isa_features:feature1,-feature2"
+          method "isa:some_isa isa_features:feature1,-feature2"
+          date 1234
+        end_compilation
+      """,
+      (ImmutableDict({"feature1": True, "feature2": False}), []))
+    self.assertParsesTo(
+      """
+        begin_compilation
+          name "isa:some_isa isa_features:feature1,-feature2"
+          method "isa:some_isa isa_features:feature1,-feature2"
+          date 1234
+        end_compilation
+        begin_compilation
+          name "xyz1"
+          method "MyMethod1"
+          date 1234
+        end_compilation
+        begin_cfg
+          name "pass1"
+          foo
+          bar
+        end_cfg
+      """,
+      (ImmutableDict({"feature1": True, "feature2": False}), [
+        ("MyMethod1 pass1", ["foo", "bar"])
+      ]))
diff --git a/tools/checker/file_format/checker/parser.py b/tools/checker/file_format/checker/parser.py
index 7a5a4c8..92e9b02 100644
--- a/tools/checker/file_format/checker/parser.py
+++ b/tools/checker/file_format/checker/parser.py
@@ -12,65 +12,68 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from common.archs               import archs_list
-from common.logger              import Logger
-from file_format.common         import SplitStream
-from file_format.checker.struct import CheckerFile, TestCase, TestAssertion, TestExpression
+from common.archs import archs_list
+from common.logger import Logger
+from file_format.common import split_stream
+from file_format.checker.struct import CheckerFile, TestCase, TestStatement, TestExpression
 
 import re
 
-def __isCheckerLine(line):
-  return line.startswith("///") or line.startswith("##")
 
-def __extractLine(prefix, line, arch = None, debuggable = False):
+def _is_checker_line(line):
+  return line.startswith("///") or line.startswith("##") or line.startswith(";;")
+
+
+def _extract_line(prefix, line, arch=None, debuggable=False):
   """ Attempts to parse a check line. The regex searches for a comment symbol
       followed by the CHECK keyword, given attribute and a colon at the very
       beginning of the line. Whitespaces are ignored.
   """
-  rIgnoreWhitespace = r"\s*"
-  rCommentSymbols = [r"///", r"##"]
-  arch_specifier = r"-%s" % arch if arch is not None else r""
-  dbg_specifier = r"-DEBUGGABLE" if debuggable else r""
-  regexPrefix = rIgnoreWhitespace + \
-                r"(" + r"|".join(rCommentSymbols) + r")" + \
-                rIgnoreWhitespace + \
-                prefix + arch_specifier + dbg_specifier + r":"
+  r_ignore_whitespace = r"\s*"
+  r_comment_symbols = ["///", "##", ";;"]
+  arch_specifier = "-{}".format(arch) if arch is not None else ""
+  dbg_specifier = "-DEBUGGABLE" if debuggable else ""
+  regex_prefix = (r_ignore_whitespace +
+                  "(" + "|".join(r_comment_symbols) + ")"
+                  + r_ignore_whitespace + prefix + arch_specifier + dbg_specifier + ":")
 
   # The 'match' function succeeds only if the pattern is matched at the
   # beginning of the line.
-  match = re.match(regexPrefix, line)
+  match = re.match(regex_prefix, line)
   if match is not None:
     return line[match.end():].strip()
   else:
     return None
 
-def __preprocessLineForStart(prefix, line, targetArch):
+
+def _preprocess_line_for_start(prefix, line, target_arch):
   """ This function modifies a CHECK-START-{x,y,z} into a matching
       CHECK-START-y line for matching targetArch y. If no matching
       architecture is found, CHECK-START-x is returned arbitrarily
       to ensure all following check lines are put into a test that
       is skipped. Any other line is left unmodified.
   """
-  if targetArch is not None:
+  if target_arch is not None:
     if prefix in line:
       # Find { } on the line and assume that defines the set.
-      s = line.find('{')
-      e = line.find('}')
-      if 0 < s and s < e:
-        archs = line[s+1:e].split(',')
+      s = line.find("{")
+      e = line.find("}")
+      if 0 < s < e:
+        archs = line[s + 1:e].split(",")
         # First verify that every archs is valid. Return the
         # full line on failure to prompt error back to user.
         for arch in archs:
-          if not arch in archs_list:
+          if arch not in archs_list:
             return line
         # Now accept matching arch or arbitrarily return first.
-        if targetArch in archs:
-          return line[:s] + targetArch + line[e + 1:]
+        if target_arch in archs:
+          return line[:s] + target_arch + line[e + 1:]
         else:
           return line[:s] + archs[0] + line[e + 1:]
   return line
 
-def __processLine(line, lineNo, prefix, fileName, targetArch):
+
+def _process_line(line, line_no, prefix, filename, target_arch):
   """ This function is invoked on each line of the check file and returns a triplet
       which instructs the parser how the line should be handled. If the line is
       to be included in the current check group, it is returned in the first
@@ -78,129 +81,160 @@
       returned in the second value. The third value indicates whether the line
       contained an architecture-specific suffix.
   """
-  if not __isCheckerLine(line):
+  if not _is_checker_line(line):
     return None, None, None
 
   # Lines beginning with 'CHECK-START' start a new test case.
   # We currently only consider the architecture suffix(es) in "CHECK-START" lines.
   for debuggable in [True, False]:
-    sline = __preprocessLineForStart(prefix + "-START", line, targetArch)
+    sline = _preprocess_line_for_start(prefix + "-START", line, target_arch)
     for arch in [None] + archs_list:
-      startLine = __extractLine(prefix + "-START", sline, arch, debuggable)
-      if startLine is not None:
-        return None, startLine, (arch, debuggable)
+      start_line = _extract_line(prefix + "-START", sline, arch, debuggable)
+      if start_line is not None:
+        return None, start_line, (arch, debuggable)
 
   # Lines starting only with 'CHECK' are matched in order.
-  plainLine = __extractLine(prefix, line)
-  if plainLine is not None:
-    return (plainLine, TestAssertion.Variant.InOrder, lineNo), None, None
+  plain_line = _extract_line(prefix, line)
+  if plain_line is not None:
+    return (plain_line, TestStatement.Variant.IN_ORDER, line_no), None, None
 
   # 'CHECK-NEXT' lines are in-order but must match the very next line.
-  nextLine = __extractLine(prefix + "-NEXT", line)
-  if nextLine is not None:
-    return (nextLine, TestAssertion.Variant.NextLine, lineNo), None, None
+  next_line = _extract_line(prefix + "-NEXT", line)
+  if next_line is not None:
+    return (next_line, TestStatement.Variant.NEXT_LINE, line_no), None, None
 
-  # 'CHECK-DAG' lines are no-order assertions.
-  dagLine = __extractLine(prefix + "-DAG", line)
-  if dagLine is not None:
-    return (dagLine, TestAssertion.Variant.DAG, lineNo), None, None
+  # 'CHECK-DAG' lines are no-order statements.
+  dag_line = _extract_line(prefix + "-DAG", line)
+  if dag_line is not None:
+    return (dag_line, TestStatement.Variant.DAG, line_no), None, None
 
-  # 'CHECK-NOT' lines are no-order negative assertions.
-  notLine = __extractLine(prefix + "-NOT", line)
-  if notLine is not None:
-    return (notLine, TestAssertion.Variant.Not, lineNo), None, None
+  # 'CHECK-NOT' lines are no-order negative statements.
+  not_line = _extract_line(prefix + "-NOT", line)
+  if not_line is not None:
+    return (not_line, TestStatement.Variant.NOT, line_no), None, None
 
   # 'CHECK-EVAL' lines evaluate a Python expression.
-  evalLine = __extractLine(prefix + "-EVAL", line)
-  if evalLine is not None:
-    return (evalLine, TestAssertion.Variant.Eval, lineNo), None, None
+  eval_line = _extract_line(prefix + "-EVAL", line)
+  if eval_line is not None:
+    return (eval_line, TestStatement.Variant.EVAL, line_no), None, None
 
-  Logger.fail("Checker assertion could not be parsed: '" + line + "'", fileName, lineNo)
+  # 'CHECK-IF' lines mark the beginning of a block that will be executed
+  # only if the Python expression that follows evaluates to true.
+  if_line = _extract_line(prefix + "-IF", line)
+  if if_line is not None:
+    return (if_line, TestStatement.Variant.IF, line_no), None, None
 
-def __isMatchAtStart(match):
+  # 'CHECK-ELIF' lines mark the beginning of an `else if` branch of a CHECK-IF block.
+  elif_line = _extract_line(prefix + "-ELIF", line)
+  if elif_line is not None:
+    return (elif_line, TestStatement.Variant.ELIF, line_no), None, None
+
+  # 'CHECK-ELSE' lines mark the beginning of the `else` branch of a CHECK-IF block.
+  else_line = _extract_line(prefix + "-ELSE", line)
+  if else_line is not None:
+    return (else_line, TestStatement.Variant.ELSE, line_no), None, None
+
+  # 'CHECK-FI' lines mark the end of a CHECK-IF block.
+  fi_line = _extract_line(prefix + "-FI", line)
+  if fi_line is not None:
+    return (fi_line, TestStatement.Variant.FI, line_no), None, None
+
+  Logger.fail("Checker statement could not be parsed: '" + line + "'", filename, line_no)
+
+
+def _is_match_at_start(match):
   """ Tests if the given Match occurred at the beginning of the line. """
   return (match is not None) and (match.start() == 0)
 
-def __firstMatch(matches, string):
+
+def _first_match(matches, string):
   """ Takes in a list of Match objects and returns the minimal start point among
       them. If there aren't any successful matches it returns the length of
       the searched string.
   """
-  starts = map(lambda m: len(string) if m is None else m.start(), matches)
-  return min(starts)
+  return min(len(string) if m is None else m.start() for m in matches)
 
-def ParseCheckerAssertion(parent, line, variant, lineNo):
+
+def parse_checker_statement(parent, line, variant, line_no):
   """ This method parses the content of a check line stripped of the initial
       comment symbol and the CHECK-* keyword.
   """
-  assertion = TestAssertion(parent, variant, line, lineNo)
-  isEvalLine = (variant == TestAssertion.Variant.Eval)
+  statement = TestStatement(parent, variant, line, line_no)
+
+  if statement.is_no_content_statement() and line:
+    Logger.fail("Expected empty statement: '{}'".format(line), statement.filename,
+                statement.line_no)
 
   # Loop as long as there is something to parse.
   while line:
     # Search for the nearest occurrence of the special markers.
-    if isEvalLine:
-      # The following constructs are not supported in CHECK-EVAL lines
-      matchWhitespace = None
-      matchPattern = None
-      matchVariableDefinition = None
+    if statement.is_eval_content_statement():
+      # The following constructs are not supported in CHECK-EVAL, -IF and -ELIF lines
+      match_whitespace = None
+      match_pattern = None
+      match_variable_definition = None
     else:
-      matchWhitespace = re.search(r"\s+", line)
-      matchPattern = re.search(TestExpression.Regex.regexPattern, line)
-      matchVariableDefinition = re.search(TestExpression.Regex.regexVariableDefinition, line)
-    matchVariableReference = re.search(TestExpression.Regex.regexVariableReference, line)
+      match_whitespace = re.search(r"\s+", line)
+      match_pattern = re.search(TestExpression.Regex.REGEX_PATTERN, line)
+      match_variable_definition = re.search(TestExpression.Regex.REGEX_VARIABLE_DEFINITION, line)
+    match_variable_reference = re.search(TestExpression.Regex.REGEX_VARIABLE_REFERENCE, line)
 
     # If one of the above was identified at the current position, extract them
     # from the line, parse them and add to the list of line parts.
-    if __isMatchAtStart(matchWhitespace):
+    if _is_match_at_start(match_whitespace):
       # A whitespace in the check line creates a new separator of line parts.
       # This allows for ignored output between the previous and next parts.
-      line = line[matchWhitespace.end():]
-      assertion.addExpression(TestExpression.createSeparator())
-    elif __isMatchAtStart(matchPattern):
-      pattern = line[0:matchPattern.end()]
+      line = line[match_whitespace.end():]
+      statement.add_expression(TestExpression.create_separator())
+    elif _is_match_at_start(match_pattern):
+      pattern = line[0:match_pattern.end()]
       pattern = pattern[2:-2]
-      line = line[matchPattern.end():]
-      assertion.addExpression(TestExpression.createPattern(pattern))
-    elif __isMatchAtStart(matchVariableReference):
-      var = line[0:matchVariableReference.end()]
-      line = line[matchVariableReference.end():]
+      line = line[match_pattern.end():]
+      statement.add_expression(TestExpression.create_pattern(pattern))
+    elif _is_match_at_start(match_variable_reference):
+      var = line[0:match_variable_reference.end()]
+      line = line[match_variable_reference.end():]
       name = var[2:-2]
-      assertion.addExpression(TestExpression.createVariableReference(name))
-    elif __isMatchAtStart(matchVariableDefinition):
-      var = line[0:matchVariableDefinition.end()]
-      line = line[matchVariableDefinition.end():]
-      colonPos = var.find(":")
-      name = var[2:colonPos]
-      body = var[colonPos+1:-2]
-      assertion.addExpression(TestExpression.createVariableDefinition(name, body))
+      statement.add_expression(TestExpression.create_variable_reference(name))
+    elif _is_match_at_start(match_variable_definition):
+      var = line[0:match_variable_definition.end()]
+      line = line[match_variable_definition.end():]
+      colon_pos = var.find(":")
+      name = var[2:colon_pos]
+      body = var[colon_pos + 1:-2]
+      statement.add_expression(TestExpression.create_variable_definition(name, body))
     else:
       # If we're not currently looking at a special marker, this is a plain
       # text match all the way until the first special marker (or the end
       # of the line).
-      firstMatch = __firstMatch([ matchWhitespace,
-                                  matchPattern,
-                                  matchVariableReference,
-                                  matchVariableDefinition ],
-                                line)
-      text = line[0:firstMatch]
-      line = line[firstMatch:]
-      if isEvalLine:
-        assertion.addExpression(TestExpression.createPlainText(text))
+      first_match = _first_match([match_whitespace,
+                                  match_pattern,
+                                  match_variable_reference,
+                                  match_variable_definition],
+                                 line)
+      text = line[0:first_match]
+      line = line[first_match:]
+      if statement.is_eval_content_statement():
+        statement.add_expression(TestExpression.create_plain_text(text))
       else:
-        assertion.addExpression(TestExpression.createPatternFromPlainText(text))
-  return assertion
+        statement.add_expression(TestExpression.create_pattern_from_plain_text(text))
+  return statement
 
-def ParseCheckerStream(fileName, prefix, stream, targetArch = None):
-  checkerFile = CheckerFile(fileName)
-  fnProcessLine = lambda line, lineNo: __processLine(line, lineNo, prefix, fileName, targetArch)
-  fnLineOutsideChunk = lambda line, lineNo: \
-      Logger.fail("Checker line not inside a group", fileName, lineNo)
-  for caseName, caseLines, startLineNo, testData in \
-      SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
-    testArch = testData[0]
-    forDebuggable = testData[1]
-    testCase = TestCase(checkerFile, caseName, startLineNo, testArch, forDebuggable)
-    for caseLine in caseLines:
-      ParseCheckerAssertion(testCase, caseLine[0], caseLine[1], caseLine[2])
-  return checkerFile
+
+def parse_checker_stream(file_name, prefix, stream, target_arch=None):
+  checker_file = CheckerFile(file_name)
+
+  def fn_process_line(line, line_no):
+    return _process_line(line, line_no, prefix, file_name, target_arch)
+
+  def fn_line_outside_chunk(line, line_no):
+    Logger.fail("Checker line not inside a group", file_name, line_no)
+
+  for case_name, case_lines, start_line_no, test_data in split_stream(stream, fn_process_line,
+                                                                      fn_line_outside_chunk):
+    test_arch = test_data[0]
+    for_debuggable = test_data[1]
+    test_case = TestCase(checker_file, case_name, start_line_no, test_arch, for_debuggable)
+    for case_line in case_lines:
+      parse_checker_statement(test_case, case_line[0], case_line[1], case_line[2])
+  return checker_file
diff --git a/tools/checker/file_format/checker/struct.py b/tools/checker/file_format/checker/struct.py
index a31aa54..f9242c4 100644
--- a/tools/checker/file_format/checker/struct.py
+++ b/tools/checker/file_format/checker/struct.py
@@ -12,128 +12,137 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import enum
+
 from common.logger import Logger
 from common.mixins import EqualityMixin, PrintableMixin
 
 import re
 
+
 class CheckerFile(PrintableMixin):
 
-  def __init__(self, fileName):
-    self.fileName = fileName
-    self.testCases = []
+  def __init__(self, filename):
+    self.file_name = filename
+    self.test_cases = []
 
-  def addTestCase(self, new_test_case):
-    self.testCases.append(new_test_case)
+  def add_test_case(self, new_test_case):
+    self.test_cases.append(new_test_case)
 
-  def testCasesForArch(self, targetArch):
-    return [t for t in self.testCases if t.testArch == targetArch]
+  def test_cases_for_arch(self, target_arch):
+    return [t for t in self.test_cases if t.test_arch == target_arch]
 
   def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.testCases == other.testCases
+    return isinstance(other, self.__class__) and self.test_cases == other.test_cases
 
 
 class TestCase(PrintableMixin):
 
-  def __init__(self, parent, name, startLineNo, testArch = None, forDebuggable = False):
+  def __init__(self, parent, name, start_line_no, test_arch=None, for_debuggable=False):
     assert isinstance(parent, CheckerFile)
 
     self.parent = parent
     self.name = name
-    self.assertions = []
-    self.startLineNo = startLineNo
-    self.testArch = testArch
-    self.forDebuggable = forDebuggable
+    self.statements = []
+    self.start_line_no = start_line_no
+    self.test_arch = test_arch
+    self.for_debuggable = for_debuggable
 
     if not self.name:
-      Logger.fail("Test case does not have a name", self.fileName, self.startLineNo)
+      Logger.fail("Test case does not have a name", self.filename, self.start_line_no)
 
-    self.parent.addTestCase(self)
+    self.parent.add_test_case(self)
 
   @property
-  def fileName(self):
-    return self.parent.fileName
+  def filename(self):
+    return self.parent.file_name
 
-  def addAssertion(self, new_assertion):
-    if new_assertion.variant == TestAssertion.Variant.NextLine:
-      if not self.assertions or \
-         (self.assertions[-1].variant != TestAssertion.Variant.InOrder and \
-          self.assertions[-1].variant != TestAssertion.Variant.NextLine):
-        Logger.fail("A next-line assertion can only be placed after an "
-                    "in-order assertion or another next-line assertion.",
-                    new_assertion.fileName, new_assertion.lineNo)
-    self.assertions.append(new_assertion)
+  def add_statement(self, new_statement):
+    self.statements.append(new_statement)
 
   def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.name == other.name \
-       and self.assertions == other.assertions
+    return (isinstance(other, self.__class__)
+            and self.name == other.name
+            and self.statements == other.statements)
 
 
-class TestAssertion(PrintableMixin):
+class TestStatement(PrintableMixin):
+  class Variant(enum.IntEnum):
+    """Supported types of statements."""
+    IN_ORDER, NEXT_LINE, DAG, NOT, EVAL, IF, ELIF, ELSE, FI = range(9)
 
-  class Variant(object):
-    """Supported types of assertions."""
-    InOrder, NextLine, DAG, Not, Eval = range(5)
-
-  def __init__(self, parent, variant, originalText, lineNo):
+  def __init__(self, parent, variant, original_text, line_no):
     assert isinstance(parent, TestCase)
 
     self.parent = parent
     self.variant = variant
     self.expressions = []
-    self.lineNo = lineNo
-    self.originalText = originalText
+    self.line_no = line_no
+    self.original_text = original_text
 
-    self.parent.addAssertion(self)
+    self.parent.add_statement(self)
 
   @property
-  def fileName(self):
-    return self.parent.fileName
+  def filename(self):
+    return self.parent.filename
 
-  def addExpression(self, new_expression):
+  def is_pattern_match_content_statement(self):
+    return self.variant in [TestStatement.Variant.IN_ORDER,
+                            TestStatement.Variant.NEXT_LINE,
+                            TestStatement.Variant.DAG,
+                            TestStatement.Variant.NOT]
+
+  def is_eval_content_statement(self):
+    return self.variant in [TestStatement.Variant.EVAL,
+                            TestStatement.Variant.IF,
+                            TestStatement.Variant.ELIF]
+
+  def is_no_content_statement(self):
+    return self.variant in [TestStatement.Variant.ELSE,
+                            TestStatement.Variant.FI]
+
+  def add_expression(self, new_expression):
     assert isinstance(new_expression, TestExpression)
-    if self.variant == TestAssertion.Variant.Not:
-      if new_expression.variant == TestExpression.Variant.VarDef:
-        Logger.fail("CHECK-NOT lines cannot define variables", self.fileName, self.lineNo)
+    if self.variant == TestStatement.Variant.NOT:
+      if new_expression.variant == TestExpression.Variant.VAR_DEF:
+        Logger.fail("CHECK-NOT lines cannot define variables", self.filename, self.line_no)
     self.expressions.append(new_expression)
 
-  def toRegex(self):
-    """ Returns a regex pattern for this entire assertion. Only used in tests. """
+  def to_regex(self):
+    """ Returns a regex pattern for this entire statement. Only used in tests. """
     regex = ""
     for expression in self.expressions:
-      if expression.variant == TestExpression.Variant.Separator:
+      if expression.variant == TestExpression.Variant.SEPARATOR:
         regex = regex + ", "
       else:
         regex = regex + "(" + expression.text + ")"
     return regex
 
   def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.variant == other.variant \
-       and self.expressions == other.expressions
+    return (isinstance(other, self.__class__)
+            and self.variant == other.variant
+            and self.expressions == other.expressions)
 
 
 class TestExpression(EqualityMixin, PrintableMixin):
-
-  class Variant(object):
+  class Variant:
     """Supported language constructs."""
-    PlainText, Pattern, VarRef, VarDef, Separator = range(5)
+    PLAIN_TEXT, PATTERN, VAR_REF, VAR_DEF, SEPARATOR = range(5)
 
-  class Regex(object):
-    rName = r"([a-zA-Z][a-zA-Z0-9]*)"
-    rRegex = r"(.+?)"
-    rPatternStartSym = r"(\{\{)"
-    rPatternEndSym = r"(\}\})"
-    rVariableStartSym = r"(<<)"
-    rVariableEndSym = r"(>>)"
-    rVariableSeparator = r"(:)"
-    rVariableDefinitionBody = rName + rVariableSeparator + rRegex
+  class Regex:
+    R_NAME = r"([a-zA-Z][a-zA-Z0-9]*)"
+    R_REGEX = r"(.+?)"
+    R_PATTERN_START_SYM = r"(\{\{)"
+    R_PATTERN_END_SYM = r"(\}\})"
+    R_VARIABLE_START_SYM = r"(<<)"
+    R_VARIABLE_END_SYM = r"(>>)"
+    R_VARIABLE_SEPARATOR = r"(:)"
+    R_VARIABLE_DEFINITION_BODY = R_NAME + R_VARIABLE_SEPARATOR + R_REGEX
 
-    regexPattern = rPatternStartSym + rRegex + rPatternEndSym
-    regexVariableReference = rVariableStartSym + rName + rVariableEndSym
-    regexVariableDefinition = rVariableStartSym + rVariableDefinitionBody + rVariableEndSym
+    REGEX_PATTERN = R_PATTERN_START_SYM + R_REGEX + R_PATTERN_END_SYM
+    REGEX_VARIABLE_REFERENCE = R_VARIABLE_START_SYM + R_NAME + R_VARIABLE_END_SYM
+    REGEX_VARIABLE_DEFINITION = (R_VARIABLE_START_SYM + R_VARIABLE_DEFINITION_BODY
+                                 + R_VARIABLE_END_SYM)
 
   def __init__(self, variant, name, text):
     self.variant = variant
@@ -141,33 +150,33 @@
     self.text = text
 
   def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.variant == other.variant \
-       and self.name == other.name \
-       and self.text == other.text
+    return (isinstance(other, self.__class__)
+            and self.variant == other.variant
+            and self.name == other.name
+            and self.text == other.text)
 
   @staticmethod
-  def createSeparator():
-    return TestExpression(TestExpression.Variant.Separator, None, None)
+  def create_separator():
+    return TestExpression(TestExpression.Variant.SEPARATOR, None, None)
 
   @staticmethod
-  def createPlainText(text):
-    return TestExpression(TestExpression.Variant.PlainText, None, text)
+  def create_plain_text(text):
+    return TestExpression(TestExpression.Variant.PLAIN_TEXT, None, text)
 
   @staticmethod
-  def createPatternFromPlainText(text):
-    return TestExpression(TestExpression.Variant.Pattern, None, re.escape(text))
+  def create_pattern_from_plain_text(text):
+    return TestExpression(TestExpression.Variant.PATTERN, None, re.escape(text))
 
   @staticmethod
-  def createPattern(pattern):
-    return TestExpression(TestExpression.Variant.Pattern, None, pattern)
+  def create_pattern(pattern):
+    return TestExpression(TestExpression.Variant.PATTERN, None, pattern)
 
   @staticmethod
-  def createVariableReference(name):
-    assert re.match(TestExpression.Regex.rName, name)
-    return TestExpression(TestExpression.Variant.VarRef, name, None)
+  def create_variable_reference(name):
+    assert re.match(TestExpression.Regex.R_NAME, name)
+    return TestExpression(TestExpression.Variant.VAR_REF, name, None)
 
   @staticmethod
-  def createVariableDefinition(name, pattern):
-    assert re.match(TestExpression.Regex.rName, name)
-    return TestExpression(TestExpression.Variant.VarDef, name, pattern)
+  def create_variable_definition(name, pattern):
+    assert re.match(TestExpression.Regex.R_NAME, name)
+    return TestExpression(TestExpression.Variant.VAR_DEF, name, pattern)
diff --git a/tools/checker/file_format/checker/test.py b/tools/checker/file_format/checker/test.py
index 579c190..dd440d6 100644
--- a/tools/checker/file_format/checker/test.py
+++ b/tools/checker/file_format/checker/test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 #
 # Copyright (C) 2014 The Android Open Source Project
 #
@@ -14,35 +14,35 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from common.archs               import archs_list
-from common.testing             import ToUnicode
-from file_format.checker.parser import ParseCheckerStream
-from file_format.checker.struct import CheckerFile, TestCase, TestAssertion, TestExpression
+from common.archs import archs_list
+from file_format.checker.parser import parse_checker_stream
+from file_format.checker.struct import CheckerFile, TestCase, TestStatement, TestExpression
 
 import io
 import unittest
 
 CheckerException = SystemExit
 
+
 class CheckerParser_PrefixTest(unittest.TestCase):
 
-  def tryParse(self, string):
-    checkerText = u"/// CHECK-START: pass\n" + ToUnicode(string)
-    return ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText))
+  def try_parse(self, string):
+    checker_text = "/// CHECK-START: pass\n" + string
+    return parse_checker_stream("<test-file>", "CHECK", io.StringIO(checker_text))
 
   def assertParses(self, string):
-    checkFile = self.tryParse(string)
-    self.assertEqual(len(checkFile.testCases), 1)
-    self.assertNotEqual(len(checkFile.testCases[0].assertions), 0)
+    check_file = self.try_parse(string)
+    self.assertEqual(len(check_file.test_cases), 1)
+    self.assertNotEqual(len(check_file.test_cases[0].statements), 0)
 
   def assertIgnored(self, string):
-    checkFile = self.tryParse(string)
-    self.assertEqual(len(checkFile.testCases), 1)
-    self.assertEqual(len(checkFile.testCases[0].assertions), 0)
+    check_file = self.try_parse(string)
+    self.assertEqual(len(check_file.test_cases), 1)
+    self.assertEqual(len(check_file.test_cases[0].statements), 0)
 
   def assertInvalid(self, string):
     with self.assertRaises(CheckerException):
-      self.tryParse(string)
+      self.try_parse(string)
 
   def test_ValidFormat(self):
     self.assertParses("///CHECK:foo")
@@ -73,47 +73,48 @@
     self.assertParses("    ///CHECK: foo")
     self.assertParses("///    CHECK: foo")
 
+
 class CheckerParser_TestExpressionTest(unittest.TestCase):
+  def parse_statement(self, string, variant=""):
+    checker_text = ("/// CHECK-START: pass\n" +
+                    "/// CHECK" + variant + ": " + string)
+    checker_file = parse_checker_stream("<test-file>", "CHECK", io.StringIO(checker_text))
+    self.assertEqual(len(checker_file.test_cases), 1)
+    test_case = checker_file.test_cases[0]
+    self.assertEqual(len(test_case.statements), 1)
+    return test_case.statements[0]
 
-  def parseAssertion(self, string, variant=""):
-    checkerText = (u"/// CHECK-START: pass\n" +
-                   u"/// CHECK" + ToUnicode(variant) + u": " + ToUnicode(string))
-    checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText))
-    self.assertEqual(len(checkerFile.testCases), 1)
-    testCase = checkerFile.testCases[0]
-    self.assertEqual(len(testCase.assertions), 1)
-    return testCase.assertions[0]
-
-  def parseExpression(self, string):
-    line = self.parseAssertion(string)
+  def parse_expression(self, string):
+    line = self.parse_statement(string)
     self.assertEqual(1, len(line.expressions))
     return line.expressions[0]
 
   def assertEqualsRegex(self, string, expected):
-    self.assertEqual(expected, self.parseAssertion(string).toRegex())
+    self.assertEqual(expected, self.parse_statement(string).to_regex())
 
   def assertEqualsText(self, string, text):
-    self.assertEqual(self.parseExpression(string), TestExpression.createPatternFromPlainText(text))
+    self.assertEqual(self.parse_expression(string),
+                     TestExpression.create_pattern_from_plain_text(text))
 
   def assertEqualsPattern(self, string, pattern):
-    self.assertEqual(self.parseExpression(string), TestExpression.createPattern(pattern))
+    self.assertEqual(self.parse_expression(string), TestExpression.create_pattern(pattern))
 
   def assertEqualsVarRef(self, string, name):
-    self.assertEqual(self.parseExpression(string), TestExpression.createVariableReference(name))
+    self.assertEqual(self.parse_expression(string), TestExpression.create_variable_reference(name))
 
   def assertEqualsVarDef(self, string, name, pattern):
-    self.assertEqual(self.parseExpression(string),
-                     TestExpression.createVariableDefinition(name, pattern))
+    self.assertEqual(self.parse_expression(string),
+                     TestExpression.create_variable_definition(name, pattern))
 
   def assertVariantNotEqual(self, string, variant):
-    self.assertNotEqual(variant, self.parseExpression(string).variant)
+    self.assertNotEqual(variant, self.parse_expression(string).variant)
 
   # Test that individual parts of the line are recognized
 
   def test_TextOnly(self):
     self.assertEqualsText("foo", "foo")
     self.assertEqualsText("  foo  ", "foo")
-    self.assertEqualsRegex("f$o^o", "(f\$o\^o)")
+    self.assertEqualsRegex("f$o^o", "(f\\$o\\^o)")
 
   def test_PatternOnly(self):
     self.assertEqualsPattern("{{a?b.c}}", "a?b.c")
@@ -168,16 +169,16 @@
 
   def test_Empty(self):
     self.assertEqualsText("{{}}", "{{}}")
-    self.assertVariantNotEqual("<<>>", TestExpression.Variant.VarRef)
-    self.assertVariantNotEqual("<<:>>", TestExpression.Variant.VarDef)
+    self.assertVariantNotEqual("<<>>", TestExpression.Variant.VAR_REF)
+    self.assertVariantNotEqual("<<:>>", TestExpression.Variant.VAR_DEF)
 
   def test_InvalidVarName(self):
-    self.assertVariantNotEqual("<<0ABC>>", TestExpression.Variant.VarRef)
-    self.assertVariantNotEqual("<<AB=C>>", TestExpression.Variant.VarRef)
-    self.assertVariantNotEqual("<<ABC=>>", TestExpression.Variant.VarRef)
-    self.assertVariantNotEqual("<<0ABC:abc>>", TestExpression.Variant.VarDef)
-    self.assertVariantNotEqual("<<AB=C:abc>>", TestExpression.Variant.VarDef)
-    self.assertVariantNotEqual("<<ABC=:abc>>", TestExpression.Variant.VarDef)
+    self.assertVariantNotEqual("<<0ABC>>", TestExpression.Variant.VAR_REF)
+    self.assertVariantNotEqual("<<AB=C>>", TestExpression.Variant.VAR_REF)
+    self.assertVariantNotEqual("<<ABC=>>", TestExpression.Variant.VAR_REF)
+    self.assertVariantNotEqual("<<0ABC:abc>>", TestExpression.Variant.VAR_DEF)
+    self.assertVariantNotEqual("<<AB=C:abc>>", TestExpression.Variant.VAR_DEF)
+    self.assertVariantNotEqual("<<ABC=:abc>>", TestExpression.Variant.VAR_DEF)
 
   def test_BodyMatchNotGreedy(self):
     self.assertEqualsRegex("{{abc}}{{def}}", "(abc)(def)")
@@ -185,33 +186,36 @@
 
   def test_NoVarDefsInNotChecks(self):
     with self.assertRaises(CheckerException):
-      self.parseAssertion("<<ABC:abc>>", "-NOT")
+      self.parse_statement("<<ABC:abc>>", "-NOT")
 
 
 class CheckerParser_FileLayoutTest(unittest.TestCase):
 
   # Creates an instance of CheckerFile from provided info.
   # Data format: [ ( <case-name>, [ ( <text>, <assert-variant> ), ... ] ), ... ]
-  def createFile(self, caseList):
-    testFile = CheckerFile("<test_file>")
-    for caseEntry in caseList:
-      caseName = caseEntry[0]
-      testCase = TestCase(testFile, caseName, 0)
-      assertionList = caseEntry[1]
-      for assertionEntry in assertionList:
-        content = assertionEntry[0]
-        variant = assertionEntry[1]
-        assertion = TestAssertion(testCase, variant, content, 0)
-        assertion.addExpression(TestExpression.createPatternFromPlainText(content))
-    return testFile
+  def create_file(self, case_list):
+    test_file = CheckerFile("<test_file>")
+    for caseEntry in case_list:
+      case_name = caseEntry[0]
+      test_case = TestCase(test_file, case_name, 0)
+      statement_list = caseEntry[1]
+      for statementEntry in statement_list:
+        content = statementEntry[0]
+        variant = statementEntry[1]
+        statement = TestStatement(test_case, variant, content, 0)
+        if statement.is_eval_content_statement():
+          statement.add_expression(TestExpression.create_plain_text(content))
+        elif statement.is_pattern_match_content_statement():
+          statement.add_expression(TestExpression.create_pattern_from_plain_text(content))
+    return test_file
 
-  def assertParsesTo(self, checkerText, expectedData):
-    expectedFile = self.createFile(expectedData)
-    actualFile = self.parse(checkerText)
-    return self.assertEqual(expectedFile, actualFile)
+  def assertParsesTo(self, checker_text, expected_data):
+    expected_file = self.create_file(expected_data)
+    actual_file = self.parse(checker_text)
+    return self.assertEqual(expected_file, actual_file)
 
-  def parse(self, checkerText):
-    return ParseCheckerStream("<test_file>", "CHECK", io.StringIO(ToUnicode(checkerText)))
+  def parse(self, checker_text):
+    return parse_checker_stream("<test_file>", "CHECK", io.StringIO(checker_text))
 
   def test_EmptyFile(self):
     self.assertParsesTo("", [])
@@ -223,8 +227,8 @@
         /// CHECK:  foo
         /// CHECK:    bar
       """,
-      [ ( "Example Group", [ ("foo", TestAssertion.Variant.InOrder),
-                             ("bar", TestAssertion.Variant.InOrder) ] ) ])
+      [("Example Group", [("foo", TestStatement.Variant.IN_ORDER),
+                          ("bar", TestStatement.Variant.IN_ORDER)])])
 
   def test_MultipleGroups(self):
     self.assertParsesTo(
@@ -236,12 +240,12 @@
         /// CHECK: abc
         /// CHECK: def
       """,
-      [ ( "Example Group1", [ ("foo", TestAssertion.Variant.InOrder),
-                              ("bar", TestAssertion.Variant.InOrder) ] ),
-        ( "Example Group2", [ ("abc", TestAssertion.Variant.InOrder),
-                              ("def", TestAssertion.Variant.InOrder) ] ) ])
+      [("Example Group1", [("foo", TestStatement.Variant.IN_ORDER),
+                           ("bar", TestStatement.Variant.IN_ORDER)]),
+       ("Example Group2", [("abc", TestStatement.Variant.IN_ORDER),
+                           ("def", TestStatement.Variant.IN_ORDER)])])
 
-  def test_AssertionVariants(self):
+  def test_StatementVariants(self):
     self.assertParsesTo(
       """
         /// CHECK-START: Example Group
@@ -252,144 +256,150 @@
         /// CHECK-NOT:  bar
         /// CHECK-DAG:  abc
         /// CHECK-DAG:  def
+        /// CHECK-EVAL: x > y
+        /// CHECK-IF:   x < y
+        /// CHECK-ELIF: x == y
+        /// CHECK-ELSE:
+        /// CHECK-FI:
       """,
-      [ ( "Example Group", [ ("foo1", TestAssertion.Variant.InOrder),
-                             ("foo2", TestAssertion.Variant.InOrder),
-                             ("foo3", TestAssertion.Variant.NextLine),
-                             ("foo4", TestAssertion.Variant.NextLine),
-                             ("bar", TestAssertion.Variant.Not),
-                             ("abc", TestAssertion.Variant.DAG),
-                             ("def", TestAssertion.Variant.DAG) ] ) ])
+      [("Example Group", [("foo1", TestStatement.Variant.IN_ORDER),
+                          ("foo2", TestStatement.Variant.IN_ORDER),
+                          ("foo3", TestStatement.Variant.NEXT_LINE),
+                          ("foo4", TestStatement.Variant.NEXT_LINE),
+                          ("bar", TestStatement.Variant.NOT),
+                          ("abc", TestStatement.Variant.DAG),
+                          ("def", TestStatement.Variant.DAG),
+                          ("x > y", TestStatement.Variant.EVAL),
+                          ("x < y", TestStatement.Variant.IF),
+                          ("x == y", TestStatement.Variant.ELIF),
+                          (None, TestStatement.Variant.ELSE),
+                          (None, TestStatement.Variant.FI)])])
 
-  def test_MisplacedNext(self):
+  def test_NoContentStatements(self):
     with self.assertRaises(CheckerException):
       self.parse(
         """
           /// CHECK-START: Example Group
-          /// CHECK-DAG:  foo
-          /// CHECK-NEXT: bar
+          /// CHECK-ELSE:    foo
         """)
     with self.assertRaises(CheckerException):
       self.parse(
         """
           /// CHECK-START: Example Group
-          /// CHECK-NOT:  foo
-          /// CHECK-NEXT: bar
+          /// CHECK-FI:      foo
         """)
-    with self.assertRaises(CheckerException):
-      self.parse(
-        """
-          /// CHECK-START: Example Group
-          /// CHECK-EVAL: foo
-          /// CHECK-NEXT: bar
-        """)
-    with self.assertRaises(CheckerException):
-      self.parse(
-        """
-          /// CHECK-START: Example Group
-          /// CHECK-NEXT: bar
-        """)
+
 
 class CheckerParser_SuffixTests(unittest.TestCase):
-
-  noarch_block = """
+  NOARCH_BLOCK = """
                   /// CHECK-START: Group
                   /// CHECK:       foo
                   /// CHECK-NEXT:  bar
                   /// CHECK-NOT:   baz
                   /// CHECK-DAG:   yoyo
+                  /// CHECK-EVAL: x > y
+                  /// CHECK-IF:   x < y
+                  /// CHECK-ELIF: x == y
+                  /// CHECK-ELSE:
+                  /// CHECK-FI:
                 """
 
-  arch_block = """
+  ARCH_BLOCK = """
                   /// CHECK-START-{test_arch}: Group
                   /// CHECK:       foo
                   /// CHECK-NEXT:  bar
                   /// CHECK-NOT:   baz
                   /// CHECK-DAG:   yoyo
+                  /// CHECK-EVAL: x > y
+                  /// CHECK-IF:   x < y
+                  /// CHECK-ELIF: x == y
+                  /// CHECK-ELSE:
+                  /// CHECK-FI:
                 """
 
-  def parse(self, checkerText):
-    return ParseCheckerStream("<test_file>", "CHECK", io.StringIO(ToUnicode(checkerText)))
+  def parse(self, checker_text):
+    return parse_checker_stream("<test_file>", "CHECK", io.StringIO(checker_text))
 
   def test_NonArchTests(self):
     for arch in [None] + archs_list:
-      checkerFile = self.parse(self.noarch_block)
-      self.assertEqual(len(checkerFile.testCases), 1)
-      self.assertEqual(len(checkerFile.testCases[0].assertions), 4)
+      checker_file = self.parse(self.NOARCH_BLOCK)
+      self.assertEqual(len(checker_file.test_cases), 1)
+      self.assertEqual(len(checker_file.test_cases[0].statements), 9)
 
   def test_IgnoreNonTargetArch(self):
-    for targetArch in archs_list:
-      for testArch in [a for a in archs_list if a != targetArch]:
-        checkerText = self.arch_block.format(test_arch = testArch)
-        checkerFile = self.parse(checkerText)
-        self.assertEqual(len(checkerFile.testCases), 1)
-        self.assertEqual(len(checkerFile.testCasesForArch(testArch)), 1)
-        self.assertEqual(len(checkerFile.testCasesForArch(targetArch)), 0)
+    for target_arch in archs_list:
+      for test_arch in [a for a in archs_list if a != target_arch]:
+        checker_text = self.ARCH_BLOCK.format(test_arch=test_arch)
+        checker_file = self.parse(checker_text)
+        self.assertEqual(len(checker_file.test_cases), 1)
+        self.assertEqual(len(checker_file.test_cases_for_arch(test_arch)), 1)
+        self.assertEqual(len(checker_file.test_cases_for_arch(target_arch)), 0)
 
   def test_Arch(self):
     for arch in archs_list:
-      checkerText = self.arch_block.format(test_arch = arch)
-      checkerFile = self.parse(checkerText)
-      self.assertEqual(len(checkerFile.testCases), 1)
-      self.assertEqual(len(checkerFile.testCasesForArch(arch)), 1)
-      self.assertEqual(len(checkerFile.testCases[0].assertions), 4)
+      checker_text = self.ARCH_BLOCK.format(test_arch=arch)
+      checker_file = self.parse(checker_text)
+      self.assertEqual(len(checker_file.test_cases), 1)
+      self.assertEqual(len(checker_file.test_cases_for_arch(arch)), 1)
+      self.assertEqual(len(checker_file.test_cases[0].statements), 9)
 
   def test_NoDebugAndArch(self):
-    testCase = self.parse("""
+    test_case = self.parse("""
         /// CHECK-START: Group
         /// CHECK: foo
-        """).testCases[0]
-    self.assertFalse(testCase.forDebuggable)
-    self.assertEqual(testCase.testArch, None)
+        """).test_cases[0]
+    self.assertFalse(test_case.for_debuggable)
+    self.assertEqual(test_case.test_arch, None)
 
   def test_SetDebugNoArch(self):
-    testCase = self.parse("""
+    test_case = self.parse("""
         /// CHECK-START-DEBUGGABLE: Group
         /// CHECK: foo
-        """).testCases[0]
-    self.assertTrue(testCase.forDebuggable)
-    self.assertEqual(testCase.testArch, None)
+        """).test_cases[0]
+    self.assertTrue(test_case.for_debuggable)
+    self.assertEqual(test_case.test_arch, None)
 
   def test_NoDebugSetArch(self):
-    testCase = self.parse("""
+    test_case = self.parse("""
         /// CHECK-START-ARM: Group
         /// CHECK: foo
-        """).testCases[0]
-    self.assertFalse(testCase.forDebuggable)
-    self.assertEqual(testCase.testArch, "ARM")
+        """).test_cases[0]
+    self.assertFalse(test_case.for_debuggable)
+    self.assertEqual(test_case.test_arch, "ARM")
 
   def test_SetDebugAndArch(self):
-    testCase = self.parse("""
+    test_case = self.parse("""
         /// CHECK-START-ARM-DEBUGGABLE: Group
         /// CHECK: foo
-        """).testCases[0]
-    self.assertTrue(testCase.forDebuggable)
-    self.assertEqual(testCase.testArch, "ARM")
+        """).test_cases[0]
+    self.assertTrue(test_case.for_debuggable)
+    self.assertEqual(test_case.test_arch, "ARM")
+
 
 class CheckerParser_EvalTests(unittest.TestCase):
-  def parseTestCase(self, string):
-    checkerText = u"/// CHECK-START: pass\n" + ToUnicode(string)
-    checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText))
-    self.assertEqual(len(checkerFile.testCases), 1)
-    return checkerFile.testCases[0]
+  def parse_test_case(self, string):
+    checker_text = "/// CHECK-START: pass\n" + string
+    checker_file = parse_checker_stream("<test-file>", "CHECK", io.StringIO(checker_text))
+    self.assertEqual(len(checker_file.test_cases), 1)
+    return checker_file.test_cases[0]
 
-  def parseExpressions(self, string):
-    testCase = self.parseTestCase("/// CHECK-EVAL: " + string)
-    self.assertEqual(len(testCase.assertions), 1)
-    assertion = testCase.assertions[0]
-    self.assertEqual(assertion.variant, TestAssertion.Variant.Eval)
-    self.assertEqual(assertion.originalText, string)
-    return assertion.expressions
+  def parse_expressions(self, string):
+    test_case = self.parse_test_case("/// CHECK-EVAL: " + string)
+    self.assertEqual(len(test_case.statements), 1)
+    statement = test_case.statements[0]
+    self.assertEqual(statement.variant, TestStatement.Variant.EVAL)
+    self.assertEqual(statement.original_text, string)
+    return statement.expressions
 
   def assertParsesToPlainText(self, text):
-    testCase = self.parseTestCase("/// CHECK-EVAL: " + text)
-    self.assertEqual(len(testCase.assertions), 1)
-    assertion = testCase.assertions[0]
-    self.assertEqual(assertion.variant, TestAssertion.Variant.Eval)
-    self.assertEqual(assertion.originalText, text)
-    self.assertEqual(len(assertion.expressions), 1)
-    expression = assertion.expressions[0]
-    self.assertEqual(expression.variant, TestExpression.Variant.PlainText)
+    test_case = self.parse_test_case("/// CHECK-EVAL: " + text)
+    self.assertEqual(len(test_case.statements), 1)
+    statement = test_case.statements[0]
+    self.assertEqual(statement.variant, TestStatement.Variant.EVAL)
+    self.assertEqual(statement.original_text, text)
+    self.assertEqual(len(statement.expressions), 1)
+    expression = statement.expressions[0]
+    self.assertEqual(expression.variant, TestExpression.Variant.PLAIN_TEXT)
     self.assertEqual(expression.text, text)
 
   def test_PlainText(self):
@@ -400,25 +410,25 @@
     self.assertParsesToPlainText("<<ABC=>>")
 
   def test_VariableReference(self):
-    self.assertEqual(self.parseExpressions("<<ABC>>"),
-                     [ TestExpression.createVariableReference("ABC") ])
-    self.assertEqual(self.parseExpressions("123<<ABC>>"),
-                     [ TestExpression.createPlainText("123"),
-                       TestExpression.createVariableReference("ABC") ])
-    self.assertEqual(self.parseExpressions("123  <<ABC>>"),
-                     [ TestExpression.createPlainText("123  "),
-                       TestExpression.createVariableReference("ABC") ])
-    self.assertEqual(self.parseExpressions("<<ABC>>XYZ"),
-                     [ TestExpression.createVariableReference("ABC"),
-                       TestExpression.createPlainText("XYZ") ])
-    self.assertEqual(self.parseExpressions("<<ABC>>   XYZ"),
-                     [ TestExpression.createVariableReference("ABC"),
-                       TestExpression.createPlainText("   XYZ") ])
-    self.assertEqual(self.parseExpressions("123<<ABC>>XYZ"),
-                     [ TestExpression.createPlainText("123"),
-                       TestExpression.createVariableReference("ABC"),
-                       TestExpression.createPlainText("XYZ") ])
-    self.assertEqual(self.parseExpressions("123 <<ABC>>  XYZ"),
-                     [ TestExpression.createPlainText("123 "),
-                       TestExpression.createVariableReference("ABC"),
-                       TestExpression.createPlainText("  XYZ") ])
+    self.assertEqual(self.parse_expressions("<<ABC>>"),
+                     [TestExpression.create_variable_reference("ABC")])
+    self.assertEqual(self.parse_expressions("123<<ABC>>"),
+                     [TestExpression.create_plain_text("123"),
+                      TestExpression.create_variable_reference("ABC")])
+    self.assertEqual(self.parse_expressions("123  <<ABC>>"),
+                     [TestExpression.create_plain_text("123  "),
+                      TestExpression.create_variable_reference("ABC")])
+    self.assertEqual(self.parse_expressions("<<ABC>>XYZ"),
+                     [TestExpression.create_variable_reference("ABC"),
+                      TestExpression.create_plain_text("XYZ")])
+    self.assertEqual(self.parse_expressions("<<ABC>>   XYZ"),
+                     [TestExpression.create_variable_reference("ABC"),
+                      TestExpression.create_plain_text("   XYZ")])
+    self.assertEqual(self.parse_expressions("123<<ABC>>XYZ"),
+                     [TestExpression.create_plain_text("123"),
+                      TestExpression.create_variable_reference("ABC"),
+                      TestExpression.create_plain_text("XYZ")])
+    self.assertEqual(self.parse_expressions("123 <<ABC>>  XYZ"),
+                     [TestExpression.create_plain_text("123 "),
+                      TestExpression.create_variable_reference("ABC"),
+                      TestExpression.create_plain_text("  XYZ")])
diff --git a/tools/checker/file_format/common.py b/tools/checker/file_format/common.py
index 4931550..3127321 100644
--- a/tools/checker/file_format/common.py
+++ b/tools/checker/file_format/common.py
@@ -12,7 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-def SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
+
+def split_stream(stream, fn_process_line, fn_line_outside_chunk):
   """ Reads the given input stream and splits it into chunks based on
       information extracted from individual lines.
 
@@ -24,12 +25,12 @@
    - fnLineOutsideChunk: Called on attempt to attach data prior to creating
      a chunk.
   """
-  lineNo = 0
-  allChunks = []
-  currentChunk = None
+  line_no = 0
+  all_chunks = []
+  current_chunk = None
 
   for line in stream:
-    lineNo += 1
+    line_no += 1
     line = line.strip()
     if not line:
       continue
@@ -37,15 +38,15 @@
     # Let the child class process the line and return information about it.
     # The _processLine method can modify the content of the line (or delete it
     # entirely) and specify whether it starts a new group.
-    processedLine, newChunkName, testArch = fnProcessLine(line, lineNo)
+    processed_line, new_chunk_name, test_arch = fn_process_line(line, line_no)
     # Currently, only a full chunk can be specified as architecture-specific.
-    assert testArch is None or newChunkName is not None
-    if newChunkName is not None:
-      currentChunk = (newChunkName, [], lineNo, testArch)
-      allChunks.append(currentChunk)
-    if processedLine is not None:
-      if currentChunk is not None:
-        currentChunk[1].append(processedLine)
+    assert test_arch is None or new_chunk_name is not None
+    if new_chunk_name is not None:
+      current_chunk = (new_chunk_name, [], line_no, test_arch)
+      all_chunks.append(current_chunk)
+    if processed_line is not None:
+      if current_chunk is not None:
+        current_chunk[1].append(processed_line)
       else:
-        fnLineOutsideChunk(line, lineNo)
-  return allChunks
+        fn_line_outside_chunk(line, line_no)
+  return all_chunks
diff --git a/tools/checker/match/file.py b/tools/checker/match/file.py
index 3b2e67e..a573ccc 100644
--- a/tools/checker/match/file.py
+++ b/tools/checker/match/file.py
@@ -12,182 +12,355 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from collections                      import namedtuple
-from common.immutables                import ImmutableDict
-from common.logger                    import Logger
-from file_format.c1visualizer.struct  import C1visualizerFile, C1visualizerPass
-from file_format.checker.struct       import CheckerFile, TestCase, TestAssertion
-from match.line                       import MatchLines, EvaluateLine
+from collections import namedtuple
+
+from common.immutables import ImmutableDict
+from common.logger import Logger
+from file_format.checker.struct import TestStatement
+from match.line import match_lines, evaluate_line
 
 MatchScope = namedtuple("MatchScope", ["start", "end"])
 MatchInfo = namedtuple("MatchInfo", ["scope", "variables"])
 
+
 class MatchFailedException(Exception):
-  def __init__(self, assertion, lineNo, variables):
-    self.assertion = assertion
-    self.lineNo = lineNo
+  def __init__(self, statement, line_no, variables):
+    self.statement = statement
+    self.line_no = line_no
     self.variables = variables
 
-def splitIntoGroups(assertions):
-  """ Breaks up a list of assertions, grouping instructions which should be
-      tested in the same scope (consecutive DAG and NOT instructions).
-   """
-  splitAssertions = []
-  lastVariant = None
-  for assertion in assertions:
-    if (assertion.variant == lastVariant and
-        assertion.variant in [TestAssertion.Variant.DAG, TestAssertion.Variant.Not]):
-      splitAssertions[-1].append(assertion)
-    else:
-      splitAssertions.append([assertion])
-      lastVariant = assertion.variant
-  return splitAssertions
 
-def findMatchingLine(assertion, c1Pass, scope, variables, excludeLines=[]):
-  """ Finds the first line in `c1Pass` which matches `assertion`.
+class BadStructureException(Exception):
+  def __init__(self, msg, line_no):
+    self.msg = msg
+    self.line_no = line_no
+
+
+class IfStack:
+  """
+  The purpose of this class is to keep track of which branch the cursor is in.
+  This will let us know if the line read by the cursor should be processed or not.
+  Furthermore, this class contains the methods to handle the CHECK-[IF, ELIF, ELSE, FI]
+  statements, and consequently update the stack with new information.
+
+  The following elements can appear on the stack:
+  - BRANCH_TAKEN: a branch is taken if its condition evaluates to true and
+    its parent branch was also previously taken.
+  - BRANCH_NOT_TAKEN_YET: the branch's parent was taken, but this branch wasn't as its
+    condition did not evaluate to true.
+  - BRANCH_NOT_TAKEN: a branch is not taken when its parent was either NotTaken or NotTakenYet.
+    It doesn't matter if the condition would evaluate to true, that's not even checked.
+
+  CHECK-IF is the only instruction that pushes a new element on the stack. CHECK-ELIF
+  and CHECK-ELSE will update the top of the stack to keep track of what's been seen.
+  That means that we can check if the line currently pointed to by the cursor should be
+  processed just by looking at the top of the stack.
+  CHECK-FI will pop the last element.
+
+  `BRANCH_TAKEN`, `BRANCH_NOT_TAKEN`, `BRANCH_NOT_TAKEN_YET` are implemented as positive integers.
+  Negated values of `BRANCH_TAKEN` and `BRANCH_NOT_TAKEN` may be appear; `-BRANCH_TAKEN` and
+  `-BRANCH_NOT_TAKEN` have the same meaning as `BRANCH_TAKEN` and `BRANCH_NOT_TAKEN`
+  (respectively), but they indicate that we went past the ELSE branch. Knowing that, we can
+  output a precise error message if the user creates a malformed branching structure.
+  """
+
+  BRANCH_TAKEN, BRANCH_NOT_TAKEN, BRANCH_NOT_TAKEN_YET = range(1, 4)
+
+  def __init__(self):
+    self.stack = []
+
+  def can_execute(self):
+    """
+    Returns true if we're not in any branch, or the branch we're
+    currently in was taken.
+    """
+    if self._is_empty():
+      return True
+    return abs(self._peek()) == IfStack.BRANCH_TAKEN
+
+  def handle(self, statement, variables):
+    """
+    This function is invoked if the cursor is pointing to a
+    CHECK-[IF, ELIF, ELSE, FI] line.
+    """
+    variant = statement.variant
+    if variant is TestStatement.Variant.IF:
+      self._if(statement, variables)
+    elif variant is TestStatement.Variant.ELIF:
+      self._elif(statement, variables)
+    elif variant is TestStatement.Variant.ELSE:
+      self._else(statement)
+    else:
+      assert variant is TestStatement.Variant.FI
+      self._fi(statement)
+
+  def eof(self):
+    """
+    The last line the cursor points to is always EOF.
+    """
+    if not self._is_empty():
+      raise BadStructureException("Missing CHECK-FI", -1)
+
+  def _is_empty(self):
+    return not self.stack
+
+  def _if(self, statement, variables):
+    if not self._is_empty() and abs(self._peek()) in [IfStack.BRANCH_NOT_TAKEN,
+                                                      IfStack.BRANCH_NOT_TAKEN_YET]:
+      self._push(IfStack.BRANCH_NOT_TAKEN)
+    elif evaluate_line(statement, variables):
+      self._push(IfStack.BRANCH_TAKEN)
+    else:
+      self._push(IfStack.BRANCH_NOT_TAKEN_YET)
+
+  def _elif(self, statement, variables):
+    if self._is_empty():
+      raise BadStructureException("CHECK-ELIF must be after CHECK-IF or CHECK-ELIF",
+                                  statement.line_no)
+    if self._peek() < 0:
+      raise BadStructureException("CHECK-ELIF cannot be after CHECK-ELSE", statement.line_no)
+    if self._peek() == IfStack.BRANCH_TAKEN:
+      self._set_last(IfStack.BRANCH_NOT_TAKEN)
+    elif self._peek() == IfStack.BRANCH_NOT_TAKEN_YET:
+      if evaluate_line(statement, variables):
+        self._set_last(IfStack.BRANCH_TAKEN)
+      # else, the CHECK-ELIF condition is False, so do nothing: the last element on the stack is
+      # already set to BRANCH_NOT_TAKEN_YET.
+    else:
+      assert self._peek() == IfStack.BRANCH_NOT_TAKEN
+
+  def _else(self, statement):
+    if self._is_empty():
+      raise BadStructureException("CHECK-ELSE must be after CHECK-IF or CHECK-ELIF",
+                                  statement.line_no)
+    if self._peek() < 0:
+      raise BadStructureException("Consecutive CHECK-ELSE statements", statement.line_no)
+    if self._peek() in [IfStack.BRANCH_TAKEN, IfStack.BRANCH_NOT_TAKEN]:
+      # Notice that we're setting -BRANCH_NOT_TAKEN rather that BRANCH_NOT_TAKEN as we went past the
+      # ELSE branch.
+      self._set_last(-IfStack.BRANCH_NOT_TAKEN)
+    else:
+      assert self._peek() == IfStack.BRANCH_NOT_TAKEN_YET
+      # Setting -BRANCH_TAKEN rather BRANCH_TAKEN for the same reason.
+      self._set_last(-IfStack.BRANCH_TAKEN)
+
+  def _fi(self, statement):
+    if self._is_empty():
+      raise BadStructureException("CHECK-FI does not have a matching CHECK-IF", statement.line_no)
+    self.stack.pop()
+
+  def _peek(self):
+    assert not self._is_empty()
+    return self.stack[-1]
+
+  def _push(self, element):
+    self.stack.append(element)
+
+  def _set_last(self, element):
+    self.stack[-1] = element
+
+
+def find_matching_line(statement, c1_pass, scope, variables, exclude_lines=[]):
+  """ Finds the first line in `c1_pass` which matches `statement`.
 
   Scan only lines numbered between `scope.start` and `scope.end` and not on the
   `excludeLines` list.
 
-  Returns the index of the `c1Pass` line matching the assertion and variables
+  Returns the index of the `c1Pass` line matching the statement and variables
   values after the match.
 
   Raises MatchFailedException if no such `c1Pass` line can be found.
   """
   for i in range(scope.start, scope.end):
-    if i in excludeLines: continue
-    newVariables = MatchLines(assertion, c1Pass.body[i], variables)
-    if newVariables is not None:
-      return MatchInfo(MatchScope(i, i), newVariables)
-  raise MatchFailedException(assertion, scope.start, variables)
+    if i in exclude_lines:
+      continue
+    new_variables = match_lines(statement, c1_pass.body[i], variables)
+    if new_variables is not None:
+      return MatchInfo(MatchScope(i, i), new_variables)
+  raise MatchFailedException(statement, scope.start, variables)
 
-def matchDagGroup(assertions, c1Pass, scope, variables):
-  """ Attempts to find matching `c1Pass` lines for a group of DAG assertions.
 
-  Assertions are matched in the list order and variable values propagated. Only
-  lines in `scope` are scanned and each line can only match one assertion.
+class ExecutionState(object):
+  def __init__(self, c1_pass, variables={}):
+    self.cursor = 0
+    self.c1_pass = c1_pass
+    self.c1_length = len(c1_pass.body)
+    self.variables = ImmutableDict(variables)
+    self.dag_queue = []
+    self.not_queue = []
+    self.if_stack = IfStack()
+    self.last_variant = None
 
-  Returns the range of `c1Pass` lines covered by this group (min/max of matching
-  line numbers) and the variable values after the match of the last assertion.
+  def move_cursor(self, match):
+    assert self.cursor <= match.scope.end
 
-  Raises MatchFailedException when an assertion cannot be satisfied.
-  """
-  matchedLines = []
-  for assertion in assertions:
-    assert assertion.variant == TestAssertion.Variant.DAG
-    match = findMatchingLine(assertion, c1Pass, scope, variables, matchedLines)
-    variables = match.variables
-    assert match.scope.start == match.scope.end
-    assert match.scope.start not in matchedLines
-    matchedLines.append(match.scope.start)
-  return MatchInfo(MatchScope(min(matchedLines), max(matchedLines)), variables)
+    # Handle any pending NOT statements before moving the cursor
+    self.handle_not_queue(MatchScope(self.cursor, match.scope.start))
 
-def testNotGroup(assertions, c1Pass, scope, variables):
-  """ Verifies that none of the given NOT assertions matches a line inside
-      the given `scope` of `c1Pass` lines.
+    self.cursor = match.scope.end + 1
+    self.variables = match.variables
 
-  Raises MatchFailedException if an assertion matches a line in the scope.
-  """
-  for i in range(scope.start, scope.end):
-    line = c1Pass.body[i]
-    for assertion in assertions:
-      assert assertion.variant == TestAssertion.Variant.Not
-      if MatchLines(assertion, line, variables) is not None:
-        raise MatchFailedException(assertion, i, variables)
+  def handle_dag_queue(self, scope):
+    """ Attempts to find matching `c1Pass` lines for a group of DAG statements.
 
-def testEvalGroup(assertions, scope, variables):
-  for assertion in assertions:
-    if not EvaluateLine(assertion, variables):
-      raise MatchFailedException(assertion, scope.start, variables)
+    Statements are matched in the list order and variable values propagated. Only
+    lines in `scope` are scanned and each line can only match one statement.
 
-def MatchTestCase(testCase, c1Pass):
+    Returns the range of `c1Pass` lines covered by this group (min/max of matching
+    line numbers) and the variable values after the match of the last statement.
+
+    Raises MatchFailedException when a statement cannot be satisfied.
+    """
+    if not self.dag_queue:
+      return
+
+    matched_lines = []
+    variables = self.variables
+
+    for statement in self.dag_queue:
+      assert statement.variant == TestStatement.Variant.DAG
+      match = find_matching_line(statement, self.c1_pass, scope, variables, matched_lines)
+      variables = match.variables
+      assert match.scope.start == match.scope.end
+      assert match.scope.start not in matched_lines
+      matched_lines.append(match.scope.start)
+
+    match = MatchInfo(MatchScope(min(matched_lines), max(matched_lines)), variables)
+    self.dag_queue = []
+    self.move_cursor(match)
+
+  def handle_not_queue(self, scope):
+    """ Verifies that none of the given NOT statements matches a line inside
+        the given `scope` of `c1Pass` lines.
+
+    Raises MatchFailedException if a statement matches a line in the scope.
+    """
+    for statement in self.not_queue:
+      assert statement.variant == TestStatement.Variant.NOT
+      for i in range(scope.start, scope.end):
+        if match_lines(statement, self.c1_pass.body[i], self.variables) is not None:
+          raise MatchFailedException(statement, i, self.variables)
+    self.not_queue = []
+
+  def handle_eof(self):
+    """ EOF marker always moves the cursor to the end of the file."""
+    match = MatchInfo(MatchScope(self.c1_length, self.c1_length), None)
+    self.move_cursor(match)
+
+  def handle_in_order(self, statement):
+    """ Single in-order statement. Find the first line that matches and move
+        the cursor to the subsequent line.
+
+    Raises MatchFailedException if no such line can be found.
+    """
+    scope = MatchScope(self.cursor, self.c1_length)
+    match = find_matching_line(statement, self.c1_pass, scope, self.variables)
+    self.move_cursor(match)
+
+  def handle_next_line(self, statement):
+    """ Single next-line statement. Test if the current line matches and move
+        the cursor to the next line if it does.
+
+    Raises MatchFailedException if the current line does not match.
+    """
+    if self.last_variant not in [TestStatement.Variant.IN_ORDER, TestStatement.Variant.NEXT_LINE]:
+      raise BadStructureException("A next-line statement can only be placed "
+                                  "after an in-order statement or another next-line statement.",
+                                  statement.line_no)
+
+    scope = MatchScope(self.cursor, self.cursor + 1)
+    match = find_matching_line(statement, self.c1_pass, scope, self.variables)
+    self.move_cursor(match)
+
+  def handle_eval(self, statement):
+    """ Evaluates the statement in the current context.
+
+    Raises MatchFailedException if the expression evaluates to False.
+    """
+    if not evaluate_line(statement, self.variables):
+      raise MatchFailedException(statement, self.cursor, self.variables)
+
+  def handle(self, statement):
+    variant = None if statement is None else statement.variant
+
+    if variant in [TestStatement.Variant.IF,
+                   TestStatement.Variant.ELIF,
+                   TestStatement.Variant.ELSE,
+                   TestStatement.Variant.FI]:
+      self.if_stack.handle(statement, self.variables)
+      return
+
+    if variant is None:
+      self.if_stack.eof()
+
+    if not self.if_stack.can_execute():
+      return
+
+    # First non-DAG statement always triggers execution of any preceding
+    # DAG statements.
+    if variant is not TestStatement.Variant.DAG:
+      self.handle_dag_queue(MatchScope(self.cursor, self.c1_length))
+
+    if variant is None:
+      self.handle_eof()
+    elif variant is TestStatement.Variant.IN_ORDER:
+      self.handle_in_order(statement)
+    elif variant is TestStatement.Variant.NEXT_LINE:
+      self.handle_next_line(statement)
+    elif variant is TestStatement.Variant.DAG:
+      self.dag_queue.append(statement)
+    elif variant is TestStatement.Variant.NOT:
+      self.not_queue.append(statement)
+    else:
+      assert variant is TestStatement.Variant.EVAL
+      self.handle_eval(statement)
+
+    self.last_variant = variant
+
+
+def match_test_case(test_case, c1_pass, instruction_set_features):
   """ Runs a test case against a C1visualizer graph dump.
 
-  Raises MatchFailedException when an assertion cannot be satisfied.
+  Raises MatchFailedException when a statement cannot be satisfied.
   """
-  assert testCase.name == c1Pass.name
+  assert test_case.name == c1_pass.name
 
-  matchFrom = 0
-  variables = ImmutableDict()
-  c1Length = len(c1Pass.body)
+  initial_variables = {"ISA_FEATURES": instruction_set_features}
+  state = ExecutionState(c1_pass, initial_variables)
+  test_statements = test_case.statements + [None]
+  for statement in test_statements:
+    state.handle(statement)
 
-  # NOT assertions are verified retrospectively, once the scope is known.
-  pendingNotAssertions = None
 
-  # Prepare assertions by grouping those that are verified in the same scope.
-  # We also add None as an EOF assertion that will set scope for NOTs.
-  assertionGroups = splitIntoGroups(testCase.assertions)
-  assertionGroups.append(None)
-
-  for assertionGroup in assertionGroups:
-    if assertionGroup is None:
-      # EOF marker always matches the last+1 line of c1Pass.
-      match = MatchInfo(MatchScope(c1Length, c1Length), None)
-    elif assertionGroup[0].variant == TestAssertion.Variant.Not:
-      # NOT assertions will be tested together with the next group.
-      assert not pendingNotAssertions
-      pendingNotAssertions = assertionGroup
+def match_files(checker_file, c1_file, target_arch, debuggable_mode, print_cfg):
+  for test_case in checker_file.test_cases:
+    if test_case.test_arch not in [None, target_arch]:
       continue
-    elif assertionGroup[0].variant == TestAssertion.Variant.InOrder:
-      # Single in-order assertion. Find the first line that matches.
-      assert len(assertionGroup) == 1
-      scope = MatchScope(matchFrom, c1Length)
-      match = findMatchingLine(assertionGroup[0], c1Pass, scope, variables)
-    elif assertionGroup[0].variant == TestAssertion.Variant.NextLine:
-      # Single next-line assertion. Test if the current line matches.
-      assert len(assertionGroup) == 1
-      scope = MatchScope(matchFrom, matchFrom + 1)
-      match = findMatchingLine(assertionGroup[0], c1Pass, scope, variables)
-    elif assertionGroup[0].variant == TestAssertion.Variant.DAG:
-      # A group of DAG assertions. Match them all starting from the same point.
-      scope = MatchScope(matchFrom, c1Length)
-      match = matchDagGroup(assertionGroup, c1Pass, scope, variables)
-    else:
-      assert assertionGroup[0].variant == TestAssertion.Variant.Eval
-      scope = MatchScope(matchFrom, c1Length)
-      testEvalGroup(assertionGroup, scope, variables)
-      continue
-
-    if pendingNotAssertions:
-      # Previous group were NOT assertions. Make sure they don't match any lines
-      # in the [matchFrom, match.start) scope.
-      scope = MatchScope(matchFrom, match.scope.start)
-      testNotGroup(pendingNotAssertions, c1Pass, scope, variables)
-      pendingNotAssertions = None
-
-    # Update state.
-    assert matchFrom <= match.scope.end
-    matchFrom = match.scope.end + 1
-    variables = match.variables
-
-def MatchFiles(checkerFile, c1File, targetArch, debuggableMode):
-  for testCase in checkerFile.testCases:
-    if testCase.testArch not in [None, targetArch]:
-      continue
-    if testCase.forDebuggable != debuggableMode:
+    if test_case.for_debuggable != debuggable_mode:
       continue
 
     # TODO: Currently does not handle multiple occurrences of the same group
     # name, e.g. when a pass is run multiple times. It will always try to
     # match a check group against the first output group of the same name.
-    c1Pass = c1File.findPass(testCase.name)
-    if c1Pass is None:
-      with file(c1File.fileName) as cfgFile:
-        Logger.log(''.join(cfgFile), Logger.Level.Error)
+    c1_pass = c1_file.find_pass(test_case.name)
+    if c1_pass is None:
+      with open(c1_file.full_file_name) as cfg_file:
+        Logger.log("".join(cfg_file), Logger.Level.ERROR)
       Logger.fail("Test case not found in the CFG file",
-                  testCase.fileName, testCase.startLineNo, testCase.name)
+                  c1_file.full_file_name, test_case.start_line_no, test_case.name)
 
-    Logger.startTest(testCase.name)
+    Logger.start_test(test_case.name)
     try:
-      MatchTestCase(testCase, c1Pass)
-      Logger.testPassed()
+      match_test_case(test_case, c1_pass, c1_file.instruction_set_features)
+      Logger.test_passed()
     except MatchFailedException as e:
-      lineNo = c1Pass.startLineNo + e.lineNo
-      if e.assertion.variant == TestAssertion.Variant.Not:
-        msg = "NOT assertion matched line {}"
+      line_no = c1_pass.start_line_no + e.line_no
+      if e.statement.variant == TestStatement.Variant.NOT:
+        msg = "NOT statement matched line {}"
       else:
-        msg = "Assertion could not be matched starting from line {}"
-      msg = msg.format(lineNo)
-      with file(c1File.fileName) as cfgFile:
-        Logger.log(''.join(cfgFile), Logger.Level.Error)
-      Logger.testFailed(msg, e.assertion, e.variables)
+        msg = "Statement could not be matched starting from line {}"
+      msg = msg.format(line_no)
+      if print_cfg:
+        with open(c1_file.full_file_name) as cfg_file:
+          Logger.log("".join(cfg_file), Logger.Level.ERROR)
+      Logger.test_failed(msg, e.statement, e.variables)
diff --git a/tools/checker/match/line.py b/tools/checker/match/line.py
index ed48a53..16144e1 100644
--- a/tools/checker/match/line.py
+++ b/tools/checker/match/line.py
@@ -12,104 +12,124 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from common.logger              import Logger
-from file_format.checker.struct import TestExpression, TestAssertion
+from common.logger import Logger
+from file_format.checker.struct import TestExpression, TestStatement
 
+# Required for eval.
+import os
 import re
 
-def headAndTail(list):
+
+def head_and_tail(list):
   return list[0], list[1:]
 
-def splitAtSeparators(expressions):
-  """ Splits a list of TestExpressions at separators. """
-  splitExpressions = []
-  wordStart = 0
-  for index, expression in enumerate(expressions):
-    if expression.variant == TestExpression.Variant.Separator:
-      splitExpressions.append(expressions[wordStart:index])
-      wordStart = index + 1
-  splitExpressions.append(expressions[wordStart:])
-  return splitExpressions
 
-def getVariable(name, variables, pos):
+def split_at_separators(expressions):
+  """ Splits a list of TestExpressions at separators. """
+  split_expressions = []
+  word_start = 0
+  for index, expression in enumerate(expressions):
+    if expression.variant == TestExpression.Variant.SEPARATOR:
+      split_expressions.append(expressions[word_start:index])
+      word_start = index + 1
+  split_expressions.append(expressions[word_start:])
+  return split_expressions
+
+
+def get_variable(name, variables, pos):
   if name in variables:
     return variables[name]
   else:
-    Logger.testFailed("Missing definition of variable \"{}\"".format(name), pos, variables)
+    Logger.test_failed('Missing definition of variable "{}"'.format(name), pos, variables)
 
-def setVariable(name, value, variables, pos):
+
+def set_variable(name, value, variables, pos):
   if name not in variables:
-    return variables.copyWith(name, value)
+    return variables.copy_with(name, value)
   else:
-    Logger.testFailed("Multiple definitions of variable \"{}\"".format(name), pos, variables)
+    Logger.test_failed('Multiple definitions of variable "{}"'.format(name), pos, variables)
 
-def matchWords(checkerWord, stringWord, variables, pos):
+
+def match_words(checker_word, string_word, variables, pos):
   """ Attempts to match a list of TestExpressions against a string.
       Returns updated variable dictionary if successful and None otherwise.
   """
-  for expression in checkerWord:
+  for expression in checker_word:
     # If `expression` is a variable reference, replace it with the value.
-    if expression.variant == TestExpression.Variant.VarRef:
-      pattern = re.escape(getVariable(expression.name, variables, pos))
+    if expression.variant == TestExpression.Variant.VAR_REF:
+      pattern = re.escape(get_variable(expression.name, variables, pos))
     else:
       pattern = expression.text
 
+    try:
+      pattern = re.compile(pattern)
+    except re.error as e:
+      message = ('Invalid regex "{}" at {}:{},'
+                 ' compiling fails with error: {}'.format(pattern, pos.filename, pos.line_no, e))
+      raise RuntimeError(message)
+
     # Match the expression's regex pattern against the remainder of the word.
     # Note: re.match will succeed only if matched from the beginning.
-    match = re.match(pattern, stringWord)
+    match = re.match(pattern, string_word)
     if not match:
       return None
 
     # If `expression` was a variable definition, set the variable's value.
-    if expression.variant == TestExpression.Variant.VarDef:
-      variables = setVariable(expression.name, stringWord[:match.end()], variables, pos)
+    if expression.variant == TestExpression.Variant.VAR_DEF:
+      variables = set_variable(expression.name, string_word[:match.end()], variables, pos)
 
     # Move cursor by deleting the matched characters.
-    stringWord = stringWord[match.end():]
+    string_word = string_word[match.end():]
 
   # Make sure the entire word matched, i.e. `stringWord` is empty.
-  if stringWord:
+  if string_word:
     return None
 
   return variables
 
-def MatchLines(checkerLine, stringLine, variables):
+
+def match_lines(checker_line, string_line, variables):
   """ Attempts to match a CHECK line against a string. Returns variable state
       after the match if successful and None otherwise.
   """
-  assert checkerLine.variant != TestAssertion.Variant.Eval
+  assert checker_line.variant != TestStatement.Variant.EVAL
 
-  checkerWords = splitAtSeparators(checkerLine.expressions)
-  stringWords = stringLine.split()
+  checker_words = split_at_separators(checker_line.expressions)
+  string_words = string_line.split()
 
-  while checkerWords:
+  while checker_words:
     # Get the next run of TestExpressions which must match one string word.
-    checkerWord, checkerWords = headAndTail(checkerWords)
+    checker_word, checker_words = head_and_tail(checker_words)
 
     # Keep reading words until a match is found.
-    wordMatched = False
-    while stringWords:
-      stringWord, stringWords = headAndTail(stringWords)
-      newVariables = matchWords(checkerWord, stringWord, variables, checkerLine)
-      if newVariables is not None:
-        wordMatched = True
-        variables = newVariables
+    word_matched = False
+    while string_words:
+      string_word, string_words = head_and_tail(string_words)
+      new_variables = match_words(checker_word, string_word, variables, checker_line)
+      if new_variables is not None:
+        word_matched = True
+        variables = new_variables
         break
-    if not wordMatched:
+    if not word_matched:
       return None
 
   # All TestExpressions matched. Return new variable state.
   return variables
 
-def getEvalText(expression, variables, pos):
-  if expression.variant == TestExpression.Variant.PlainText:
+
+def get_eval_text(expression, variables, pos):
+  if expression.variant == TestExpression.Variant.PLAIN_TEXT:
     return expression.text
   else:
-    assert expression.variant == TestExpression.Variant.VarRef
-    return getVariable(expression.name, variables, pos)
+    assert expression.variant == TestExpression.Variant.VAR_REF
+    return get_variable(expression.name, variables, pos)
 
-def EvaluateLine(checkerLine, variables):
-  assert checkerLine.variant == TestAssertion.Variant.Eval
-  eval_string = "".join(map(lambda expr: getEvalText(expr, variables, checkerLine),
-                            checkerLine.expressions))
+
+def evaluate_line(checker_line, variables):
+  assert checker_line.is_eval_content_statement()
+  # Required for eval.
+  hasIsaFeature = lambda feature: variables["ISA_FEATURES"].get(feature, False)
+  eval_string = "".join(get_eval_text(expr,
+                                      variables,
+                                      checker_line) for expr in checker_line.expressions)
   return eval(eval_string)
diff --git a/tools/checker/match/test.py b/tools/checker/match/test.py
index 5144ca9..adebd6d 100644
--- a/tools/checker/match/test.py
+++ b/tools/checker/match/test.py
@@ -12,37 +12,36 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from common.immutables               import ImmutableDict
-from common.testing                  import ToUnicode
-from file_format.c1visualizer.parser import ParseC1visualizerStream
-from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
-from file_format.checker.parser      import ParseCheckerStream, ParseCheckerAssertion
-from file_format.checker.struct      import CheckerFile, TestCase, TestAssertion
-from match.file                      import MatchTestCase, MatchFailedException
-from match.line                      import MatchLines
+from common.immutables import ImmutableDict
+from file_format.c1visualizer.parser import parse_c1_visualizer_stream
+from file_format.checker.parser import parse_checker_stream, parse_checker_statement
+from file_format.checker.struct import CheckerFile, TestCase, TestStatement
+from match.file import match_test_case, MatchFailedException, BadStructureException
+from match.line import match_lines
 
 import io
 import unittest
 
 CheckerException = SystemExit
 
+
 class MatchLines_Test(unittest.TestCase):
 
-  def createTestAssertion(self, checkerString):
-    checkerFile = CheckerFile("<checker-file>")
-    testCase = TestCase(checkerFile, "TestMethod TestPass", 0)
-    return ParseCheckerAssertion(testCase, checkerString, TestAssertion.Variant.InOrder, 0)
+  def create_test_statement(self, checker_string):
+    checker_file = CheckerFile("<checker-file>")
+    test_case = TestCase(checker_file, "TestMethod TestPass", 0)
+    return parse_checker_statement(test_case, checker_string, TestStatement.Variant.IN_ORDER, 0)
 
-  def tryMatch(self, checkerString, c1String, varState={}):
-    return MatchLines(self.createTestAssertion(checkerString),
-                      ToUnicode(c1String),
-                      ImmutableDict(varState))
+  def try_match(self, checker_string, c1_string, var_state={}):
+    return match_lines(self.create_test_statement(checker_string),
+                       c1_string,
+                       ImmutableDict(var_state))
 
-  def assertMatches(self, checkerString, c1String, varState={}):
-    self.assertIsNotNone(self.tryMatch(checkerString, c1String, varState))
+  def assertMatches(self, checker_string, c1_string, var_state={}):
+    self.assertIsNotNone(self.try_match(checker_string, c1_string, var_state))
 
-  def assertDoesNotMatch(self, checkerString, c1String, varState={}):
-    self.assertIsNone(self.tryMatch(checkerString, c1String, varState))
+  def assertDoesNotMatch(self, checker_string, c1_string, var_state={}):
+    self.assertIsNone(self.try_match(checker_string, c1_string, var_state))
 
   def test_TextAndWhitespace(self):
     self.assertMatches("foo", "foo")
@@ -70,16 +69,16 @@
     self.assertDoesNotMatch("foo<<X>>bar", "foobar", {"X": "A"})
     self.assertDoesNotMatch("foo<<X>>bar", "foo bar", {"X": "A"})
     with self.assertRaises(CheckerException):
-      self.tryMatch("foo<<X>>bar", "foobar", {})
+      self.try_match("foo<<X>>bar", "foobar", {})
 
   def test_VariableDefinition(self):
     self.assertMatches("foo<<X:A|B>>bar", "fooAbar")
     self.assertMatches("foo<<X:A|B>>bar", "fooBbar")
     self.assertDoesNotMatch("foo<<X:A|B>>bar", "fooCbar")
 
-    env = self.tryMatch("foo<<X:A.*B>>bar", "fooABbar", {})
+    env = self.try_match("foo<<X:A.*B>>bar", "fooABbar", {})
     self.assertEqual(env, {"X": "AB"})
-    env = self.tryMatch("foo<<X:A.*B>>bar", "fooAxxBbar", {})
+    env = self.try_match("foo<<X:A.*B>>bar", "fooAxxBbar", {})
     self.assertEqual(env, {"X": "AxxB"})
 
     self.assertMatches("foo<<X:A|B>>bar<<X>>baz", "fooAbarAbaz")
@@ -88,7 +87,7 @@
 
   def test_NoVariableRedefinition(self):
     with self.assertRaises(CheckerException):
-      self.tryMatch("<<X:...>><<X>><<X:...>><<X>>", "foofoobarbar")
+      self.try_match("<<X:...>><<X>><<X:...>><<X>>", "foofoobarbar")
 
   def test_EnvNotChangedOnPartialMatch(self):
     env = {"Y": "foo"}
@@ -102,33 +101,59 @@
 
 class MatchFiles_Test(unittest.TestCase):
 
-  def assertMatches(self, checkerString, c1String):
-    checkerString = \
+  def assertMatches(self, checker_string, c1_string, isa=None, instruction_set_features=None):
+    checker_string = \
       """
         /// CHECK-START: MyMethod MyPass
-      """ + checkerString
-    c1String = \
-      """
-        begin_compilation
-          name "MyMethod"
-          method "MyMethod"
-          date 1234
-        end_compilation
-        begin_cfg
-          name "MyPass"
-      """ + c1String + \
-      """
-        end_cfg
-      """
-    checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(ToUnicode(checkerString)))
-    c1File = ParseC1visualizerStream("<c1-file>", io.StringIO(ToUnicode(c1String)))
-    assert len(checkerFile.testCases) == 1
-    assert len(c1File.passes) == 1
-    MatchTestCase(checkerFile.testCases[0], c1File.passes[0])
+      """ + checker_string
+    meta_data = ""
+    if isa:
+      meta_data += "isa:" + isa
 
-  def assertDoesNotMatch(self, checkerString, c1String):
+    if instruction_set_features:
+      if meta_data:
+        meta_data += " "
+
+      joined_features = ",".join(
+        name if present else "-" + name for name, present in instruction_set_features.items())
+      meta_data += "isa_features:" + joined_features
+
+    meta_data_string = ""
+    if meta_data:
+      meta_data_string = \
+        """
+          begin_compilation
+            name "%s"
+            method "%s"
+            date 1234
+          end_compilation
+        """ % (meta_data, meta_data)
+    c1_string = meta_data_string + \
+               """
+                 begin_compilation
+                   name "MyMethod"
+                   method "MyMethod"
+                   date 1234
+                 end_compilation
+                 begin_cfg
+                   name "MyPass"
+               """ + c1_string + \
+               """
+                 end_cfg
+               """
+    checker_file = parse_checker_stream("<test-file>", "CHECK", io.StringIO(checker_string))
+    c1_file = parse_c1_visualizer_stream("<c1-file>", io.StringIO(c1_string))
+    assert len(checker_file.test_cases) == 1
+    assert len(c1_file.passes) == 1
+    match_test_case(checker_file.test_cases[0], c1_file.passes[0], c1_file.instruction_set_features)
+
+  def assertDoesNotMatch(self, checker_string, c1_string, isa=None, instruction_set_features=None):
     with self.assertRaises(MatchFailedException):
-      self.assertMatches(checkerString, c1String)
+      self.assertMatches(checker_string, c1_string, isa, instruction_set_features)
+
+  def assertBadStructure(self, checker_string, c1_string):
+    with self.assertRaises(BadStructureException):
+      self.assertMatches(checker_string, c1_string)
 
   def test_Text(self):
     self.assertMatches("/// CHECK: foo bar", "foo bar")
@@ -140,34 +165,34 @@
 
   def test_Variables(self):
     self.assertMatches(
-    """
-      /// CHECK: foo<<X:.>>bar
-      /// CHECK: abc<<X>>def
-    """,
-    """
-      foo0bar
-      abc0def
-    """)
+      """
+        /// CHECK: foo<<X:.>>bar
+        /// CHECK: abc<<X>>def
+      """,
+      """
+        foo0bar
+        abc0def
+      """)
     self.assertMatches(
-    """
-      /// CHECK: foo<<X:([0-9]+)>>bar
-      /// CHECK: abc<<X>>def
-      /// CHECK: ### <<X>> ###
-    """,
-    """
-      foo1234bar
-      abc1234def
-      ### 1234 ###
-    """)
+      """
+        /// CHECK: foo<<X:([0-9]+)>>bar
+        /// CHECK: abc<<X>>def
+        /// CHECK: ### <<X>> ###
+      """,
+      """
+        foo1234bar
+        abc1234def
+        ### 1234 ###
+      """)
     self.assertDoesNotMatch(
-    """
-      /// CHECK: foo<<X:([0-9]+)>>bar
-      /// CHECK: abc<<X>>def
-    """,
-    """
-      foo1234bar
-      abc1235def
-    """)
+      """
+        /// CHECK: foo<<X:([0-9]+)>>bar
+        /// CHECK: abc<<X>>def
+      """,
+      """
+        foo1234bar
+        abc1235def
+      """)
 
   def test_WholeWordMustMatch(self):
     self.assertMatches("/// CHECK: b{{.}}r", "abc bar def")
@@ -175,219 +200,252 @@
     self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc barX def")
     self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc b r def")
 
-  def test_InOrderAssertions(self):
+  def test_InOrderStatements(self):
     self.assertMatches(
-    """
-      /// CHECK: foo
-      /// CHECK: bar
-    """,
-    """
-      foo
-      bar
-    """)
+      """
+        /// CHECK: foo
+        /// CHECK: bar
+      """,
+      """
+        foo
+        bar
+      """)
     self.assertDoesNotMatch(
-    """
-      /// CHECK: foo
-      /// CHECK: bar
-    """,
-    """
-      bar
-      foo
-    """)
+      """
+        /// CHECK: foo
+        /// CHECK: bar
+      """,
+      """
+        bar
+        foo
+      """)
 
-  def test_NextLineAssertions(self):
+  def test_NextLineStatements(self):
     self.assertMatches(
-    """
-      /// CHECK:      foo
-      /// CHECK-NEXT: bar
-      /// CHECK-NEXT: abc
-      /// CHECK:      def
-    """,
-    """
-      foo
-      bar
-      abc
-      def
-    """)
+      """
+        /// CHECK:      foo
+        /// CHECK-NEXT: bar
+        /// CHECK-NEXT: abc
+        /// CHECK:      def
+      """,
+      """
+        foo
+        bar
+        abc
+        def
+      """)
     self.assertMatches(
-    """
-      /// CHECK:      foo
-      /// CHECK-NEXT: bar
-      /// CHECK:      def
-    """,
-    """
-      foo
-      bar
-      abc
-      def
-    """)
+      """
+        /// CHECK:      foo
+        /// CHECK-NEXT: bar
+        /// CHECK:      def
+      """,
+      """
+        foo
+        bar
+        abc
+        def
+      """)
     self.assertDoesNotMatch(
-    """
-      /// CHECK:      foo
-      /// CHECK-NEXT: bar
-    """,
-    """
-      foo
-      abc
-      bar
-    """)
+      """
+        /// CHECK:      foo
+        /// CHECK-NEXT: bar
+      """,
+      """
+        foo
+        abc
+        bar
+      """)
 
     self.assertDoesNotMatch(
-    """
-      /// CHECK:      foo
-      /// CHECK-NEXT: bar
-    """,
-    """
-      bar
-      foo
-      abc
-    """)
+      """
+        /// CHECK:      foo
+        /// CHECK-NEXT: bar
+      """,
+      """
+        bar
+        foo
+        abc
+      """)
 
-  def test_DagAssertions(self):
+  def test_DagStatements(self):
     self.assertMatches(
-    """
-      /// CHECK-DAG: foo
-      /// CHECK-DAG: bar
-    """,
-    """
-      foo
-      bar
-    """)
+      """
+        /// CHECK-DAG: foo
+        /// CHECK-DAG: bar
+      """,
+      """
+        foo
+        bar
+      """)
     self.assertMatches(
-    """
-      /// CHECK-DAG: foo
-      /// CHECK-DAG: bar
-    """,
-    """
-      bar
-      foo
-    """)
+      """
+        /// CHECK-DAG: foo
+        /// CHECK-DAG: bar
+      """,
+      """
+        bar
+        foo
+      """)
 
-  def test_DagAssertionsScope(self):
+  def test_DagStatementsScope(self):
     self.assertMatches(
-    """
-      /// CHECK:     foo
-      /// CHECK-DAG: abc
-      /// CHECK-DAG: def
-      /// CHECK:     bar
-    """,
-    """
-      foo
-      def
-      abc
-      bar
-    """)
+      """
+        /// CHECK:     foo
+        /// CHECK-DAG: abc
+        /// CHECK-DAG: def
+        /// CHECK:     bar
+      """,
+      """
+        foo
+        def
+        abc
+        bar
+      """)
     self.assertDoesNotMatch(
-    """
-      /// CHECK:     foo
-      /// CHECK-DAG: abc
-      /// CHECK-DAG: def
-      /// CHECK:     bar
-    """,
-    """
-      foo
-      abc
-      bar
-      def
-    """)
+      """
+        /// CHECK:     foo
+        /// CHECK-DAG: abc
+        /// CHECK-DAG: def
+        /// CHECK:     bar
+      """,
+      """
+        foo
+        abc
+        bar
+        def
+      """)
     self.assertDoesNotMatch(
-    """
-      /// CHECK:     foo
-      /// CHECK-DAG: abc
-      /// CHECK-DAG: def
-      /// CHECK:     bar
-    """,
-    """
-      foo
-      def
-      bar
-      abc
-    """)
+      """
+        /// CHECK:     foo
+        /// CHECK-DAG: abc
+        /// CHECK-DAG: def
+        /// CHECK:     bar
+      """,
+      """
+        foo
+        def
+        bar
+        abc
+      """)
 
-  def test_NotAssertions(self):
+  def test_NotStatements(self):
     self.assertMatches(
-    """
-      /// CHECK-NOT: foo
-    """,
-    """
-      abc
-      def
-    """)
+      """
+        /// CHECK-NOT: foo
+      """,
+      """
+        abc
+        def
+      """)
     self.assertDoesNotMatch(
-    """
-      /// CHECK-NOT: foo
-    """,
-    """
-      abc foo
-      def
-    """)
+      """
+        /// CHECK-NOT: foo
+      """,
+      """
+        abc foo
+        def
+      """)
     self.assertDoesNotMatch(
-    """
-      /// CHECK-NOT: foo
-      /// CHECK-NOT: bar
-    """,
-    """
-      abc
-      def bar
-    """)
+      """
+        /// CHECK-NOT: foo
+        /// CHECK-NOT: bar
+      """,
+      """
+        abc
+        def bar
+      """)
 
-  def test_NotAssertionsScope(self):
+  def test_NotStatementsScope(self):
     self.assertMatches(
-    """
-      /// CHECK:     abc
-      /// CHECK-NOT: foo
-      /// CHECK:     def
-    """,
-    """
-      abc
-      def
-    """)
+      """
+        /// CHECK:     abc
+        /// CHECK-NOT: foo
+        /// CHECK:     def
+      """,
+      """
+        abc
+        def
+      """)
     self.assertMatches(
-    """
-      /// CHECK:     abc
-      /// CHECK-NOT: foo
-      /// CHECK:     def
-    """,
-    """
-      abc
-      def
-      foo
-    """)
+      """
+        /// CHECK:     abc
+        /// CHECK-NOT: foo
+        /// CHECK:     def
+      """,
+      """
+        abc
+        def
+        foo
+      """)
     self.assertDoesNotMatch(
-    """
-      /// CHECK:     abc
-      /// CHECK-NOT: foo
-      /// CHECK:     def
-    """,
-    """
-      abc
-      foo
-      def
-    """)
+      """
+        /// CHECK:     abc
+        /// CHECK-NOT: foo
+        /// CHECK:     def
+      """,
+      """
+        abc
+        foo
+        def
+      """)
+    self.assertDoesNotMatch(
+      """
+        /// CHECK-NOT:  foo
+        /// CHECK-EVAL: 1 + 1 == 2
+        /// CHECK:      bar
+      """,
+      """
+        foo
+        abc
+        bar
+      """)
+    self.assertMatches(
+      """
+        /// CHECK-DAG:  bar
+        /// CHECK-DAG:  abc
+        /// CHECK-NOT:  foo
+      """,
+      """
+        foo
+        abc
+        bar
+      """)
+    self.assertDoesNotMatch(
+      """
+        /// CHECK-DAG:  abc
+        /// CHECK-DAG:  foo
+        /// CHECK-NOT:  bar
+      """,
+      """
+        foo
+        abc
+        bar
+      """)
 
   def test_LineOnlyMatchesOnce(self):
     self.assertMatches(
-    """
-      /// CHECK-DAG: foo
-      /// CHECK-DAG: foo
-    """,
-    """
-      foo
-      abc
-      foo
-    """)
+      """
+        /// CHECK-DAG: foo
+        /// CHECK-DAG: foo
+      """,
+      """
+        foo
+        abc
+        foo
+      """)
     self.assertDoesNotMatch(
-    """
-      /// CHECK-DAG: foo
-      /// CHECK-DAG: foo
-    """,
-    """
-      foo
-      abc
-      bar
-    """)
+      """
+        /// CHECK-DAG: foo
+        /// CHECK-DAG: foo
+      """,
+      """
+        foo
+        abc
+        bar
+      """)
 
-  def test_EvalAssertions(self):
+  def test_EvalStatements(self):
     self.assertMatches("/// CHECK-EVAL: True", "foo")
     self.assertDoesNotMatch("/// CHECK-EVAL: False", "foo")
 
@@ -398,5 +456,556 @@
                        /// CHECK-DAG: <<X:\d+>> <<Y:\d+>>
                        /// CHECK-EVAL: <<X>> > <<Y>>
                      """
-    self.assertMatches(twoVarTestCase, "42 41");
+    self.assertMatches(twoVarTestCase, "42 41")
     self.assertDoesNotMatch(twoVarTestCase, "42 43")
+
+  def test_MisplacedNext(self):
+    self.assertBadStructure(
+      """
+        /// CHECK-DAG:  foo
+        /// CHECK-NEXT: bar
+      """,
+      """
+      foo
+      bar
+      """)
+    self.assertBadStructure(
+      """
+        /// CHECK-NOT:  foo
+        /// CHECK-NEXT: bar
+      """,
+      """
+      foo
+      bar
+      """)
+    self.assertBadStructure(
+      """
+        /// CHECK-EVAL: True
+        /// CHECK-NEXT: bar
+      """,
+      """
+      foo
+      bar
+      """)
+    self.assertBadStructure(
+      """
+        /// CHECK-NEXT: bar
+      """,
+      """
+      foo
+      bar
+      """)
+
+  def test_EnvVariableEval(self):
+    self.assertMatches(
+      """
+        /// CHECK-IF: os.environ.get('MARTY_MCFLY') != '89mph!'
+        /// CHECK-FI:
+      """,
+      """
+      foo
+      """
+    )
+    self.assertMatches(
+      """
+        /// CHECK-EVAL: os.environ.get('MARTY_MCFLY') != '89mph!'
+      """,
+      """
+      foo
+      """
+    )
+
+  def test_IfStatements(self):
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: True
+        ///   CHECK-NEXT: foo2
+        /// CHECK-FI:
+        /// CHECK-NEXT: foo3
+        /// CHECK-NEXT: bar
+      """,
+      """
+      foo1
+      foo2
+      foo3
+      bar
+      """)
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: False
+        ///   CHECK-NEXT:    foo2
+        /// CHECK-FI:
+        /// CHECK-NEXT:    bar
+      """,
+      """
+      foo1
+      bar
+      """)
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: True
+        ///   CHECK-DAG:    foo2
+        /// CHECK-FI:
+        /// CHECK-DAG:    bar
+        /// CHECK: foo3
+      """,
+      """
+      foo1
+      bar
+      foo2
+      foo3
+      """)
+    self.assertDoesNotMatch(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: False
+        ///   CHECK-NEXT: foo2
+        /// CHECK-FI:
+        /// CHECK-NEXT: foo3
+      """,
+      """
+      foo1
+      foo2
+      foo3
+      """)
+
+  def test_IfElseStatements(self):
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: True
+        ///   CHECK-NEXT:    foo2
+        /// CHECK-ELSE:
+        ///   CHECK-NEXT:    foo3
+        /// CHECK-FI:
+        /// CHECK-NEXT:    bar
+      """,
+      """
+      foo1
+      foo2
+      bar
+      """)
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: False
+        ///   CHECK-NEXT:    foo2
+        /// CHECK-ELSE:
+        ///   CHECK-NEXT:    foo3
+        /// CHECK-FI:
+        /// CHECK-NEXT:    bar
+      """,
+      """
+      foo1
+      foo3
+      bar
+      """)
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: False
+        ///   CHECK-NEXT:    foo2
+        /// CHECK-ELSE:
+        ///   CHECK-DAG:    bar
+        /// CHECK-FI:
+        /// CHECK-DAG:    foo3
+        /// CHECK: foo4
+      """,
+      """
+      foo1
+      foo3
+      bar
+      foo4
+      """)
+    self.assertDoesNotMatch(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: False
+        ///   CHECK-NEXT:    foo2
+        /// CHECK-ELSE:
+        ///   CHECK-NEXT:    foo3
+        /// CHECK-FI:
+        /// CHECK-NEXT:    bar
+      """,
+      """
+      foo1
+      foo2
+      bar
+      """)
+
+  def test_IfElifElseStatements(self):
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: True
+        ///   CHECK-NEXT:    foo2
+        /// CHECK-ELIF: True
+        ///   CHECK-NEXT:    foo3
+        /// CHECK-ELIF: True
+        ///   CHECK-NEXT:    foo4
+        /// CHECK-FI:
+        /// CHECK-NEXT:    bar
+      """,
+      """
+      foo1
+      foo2
+      bar
+      """)
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: False
+        ///   CHECK-NEXT:    foo2
+        /// CHECK-ELIF: False
+        ///   CHECK-NEXT:    foo3
+        /// CHECK-ELIF: True
+        ///   CHECK-NEXT:    foo4
+        /// CHECK-FI:
+        /// CHECK-NEXT:    bar
+      """,
+      """
+      foo1
+      foo4
+      bar
+      """)
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: False
+        ///   CHECK-NEXT:    foo2
+        /// CHECK-ELIF: True
+        ///   CHECK-NEXT:    foo3
+        /// CHECK-ELIF: True
+        ///   CHECK-NEXT:    foo4
+        /// CHECK-FI:
+        /// CHECK-NEXT:    bar
+      """,
+      """
+      foo1
+      foo3
+      bar
+      """)
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: False
+        ///   CHECK-NEXT:    foo2
+        /// CHECK-ELIF: False
+        ///   CHECK-NEXT:    foo3
+        /// CHECK-ELIF: False
+        ///   CHECK-NEXT:    foo4
+        /// CHECK-FI:
+        /// CHECK-NEXT:    bar
+      """,
+      """
+      foo1
+      bar
+      """)
+    self.assertDoesNotMatch(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: False
+        ///   CHECK-NEXT:    foo2
+        /// CHECK-ELIF: True
+        ///   CHECK-NEXT:    foo3
+        /// CHECK-ELSE:
+        ///   CHECK-NEXT:    foo4
+        /// CHECK-FI:
+        /// CHECK-NEXT:    bar
+      """,
+      """
+      foo1
+      foo2
+      bar
+      """)
+
+  def test_NestedBranching(self):
+    self.assertMatches(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: True
+        ///   CHECK-IF: True
+        ///     CHECK-NEXT:    foo2
+        ///   CHECK-ELSE:
+        ///     CHECK-NEXT:    foo3
+        ///   CHECK-FI:
+        /// CHECK-ELSE:
+        ///   CHECK-IF: True
+        ///     CHECK-NEXT:    foo4
+        ///   CHECK-ELSE:
+        ///     CHECK-NEXT:    foo5
+        ///   CHECK-FI:
+        /// CHECK-FI:
+        /// CHECK-NEXT: foo6
+      """,
+      """
+      foo1
+      foo2
+      foo6
+      """)
+    self.assertMatches(
+      """
+        /// CHECK-IF: True
+        ///   CHECK-IF: False
+        ///     CHECK:    foo1
+        ///   CHECK-ELSE:
+        ///     CHECK:    foo2
+        ///   CHECK-FI:
+        /// CHECK-ELSE:
+        ///   CHECK-IF: True
+        ///     CHECK:    foo3
+        ///   CHECK-ELSE:
+        ///     CHECK:    foo4
+        ///   CHECK-FI:
+        /// CHECK-FI:
+      """,
+      """
+      foo2
+      """)
+    self.assertMatches(
+      """
+        /// CHECK-IF: False
+        ///   CHECK-IF: True
+        ///     CHECK:    foo1
+        ///   CHECK-ELSE:
+        ///     CHECK:    foo2
+        ///   CHECK-FI:
+        /// CHECK-ELSE:
+        ///   CHECK-IF: False
+        ///     CHECK:    foo3
+        ///   CHECK-ELSE:
+        ///     CHECK-IF: False
+        ///       CHECK:    foo4
+        ///     CHECK-ELSE:
+        ///       CHECK: foo5
+        ///     CHECK-FI:
+        ///   CHECK-FI:
+        /// CHECK-FI:
+      """,
+      """
+      foo5
+      """)
+    self.assertDoesNotMatch(
+      """
+        /// CHECK: foo1
+        /// CHECK-IF: True
+        ///   CHECK-IF: False
+        ///     CHECK-NEXT:    foo2
+        ///   CHECK-ELSE:
+        ///     CHECK-NEXT:    foo3
+        ///   CHECK-FI:
+        /// CHECK-NEXT: foo6
+      """,
+      """
+      foo1
+      foo2
+      foo6
+      """)
+
+  def test_VariablesInBranches(self):
+    self.assertMatches(
+      """
+        /// CHECK-IF: True
+        ///   CHECK: foo<<VarA:\d+>>
+        /// CHECK-FI:
+        /// CHECK-EVAL: <<VarA>> == 12
+      """,
+      """
+      foo12
+      """)
+    self.assertDoesNotMatch(
+      """
+        /// CHECK-IF: True
+        ///   CHECK: foo<<VarA:\d+>>
+        /// CHECK-FI:
+        /// CHECK-EVAL: <<VarA>> == 99
+      """,
+      """
+      foo12
+      """)
+    self.assertMatches(
+      """
+        /// CHECK-IF: True
+        ///   CHECK: foo<<VarA:\d+>>
+        ///   CHECK-IF: <<VarA>> == 12
+        ///     CHECK: bar<<VarB:M|N>>
+        ///   CHECK-FI:
+        /// CHECK-FI:
+        /// CHECK-EVAL: "<<VarB>>" == "M"
+      """,
+      """
+      foo12
+      barM
+      """)
+    self.assertMatches(
+      """
+        /// CHECK-IF: False
+        ///   CHECK: foo<<VarA:\d+>>
+        /// CHECK-ELIF: True
+        ///   CHECK: foo<<VarA:M|N>>
+        /// CHECK-FI:
+        /// CHECK-EVAL: "<<VarA>>" == "M"
+      """,
+      """
+      fooM
+      """)
+    self.assertMatches(
+      """
+        /// CHECK-IF: False
+        ///   CHECK: foo<<VarA:A|B>>
+        /// CHECK-ELIF: False
+        ///   CHECK: foo<<VarA:A|B>>
+        /// CHECK-ELSE:
+        ///   CHECK-IF: False
+        ///     CHECK: foo<<VarA:A|B>>
+        ///   CHECK-ELSE:
+        ///     CHECK: foo<<VarA:M|N>>
+        ///   CHECK-FI:
+        /// CHECK-FI:
+        /// CHECK-EVAL: "<<VarA>>" == "N"
+      """,
+      """
+      fooN
+      """)
+
+  def test_MalformedBranching(self):
+    self.assertBadStructure(
+      """
+        /// CHECK-IF: True
+        /// CHECK: foo
+      """,
+      """
+      foo
+      """)
+    self.assertBadStructure(
+      """
+        /// CHECK-ELSE:
+        /// CHECK: foo
+      """,
+      """
+      foo
+      """)
+    self.assertBadStructure(
+      """
+        /// CHECK-IF: True
+        /// CHECK: foo
+        /// CHECK-ELSE:
+      """,
+      """
+      foo
+      """)
+    self.assertBadStructure(
+      """
+        /// CHECK-IF: True
+        ///   CHECK: foo
+        /// CHECK-ELIF:
+        ///   CHECK: foo
+        ///   CHECK-IF: True
+        ///     CHECK: foo
+        /// CHECK-FI:
+      """,
+      """
+      foo
+      """)
+    self.assertBadStructure(
+      """
+        /// CHECK-IF: True
+        ///   CHECK: foo
+        /// CHECK-ELSE:
+        ///   CHECK: foo
+        /// CHECK-ELIF:
+        ///   CHECK: foo
+        /// CHECK-FI:
+      """,
+      """
+      foo
+      """)
+    self.assertBadStructure(
+      """
+        /// CHECK-IF: True
+        ///   CHECK: foo
+        /// CHECK-ELSE:
+        ///   CHECK: foo
+        /// CHECK-ELSE:
+        ///   CHECK: foo
+        /// CHECK-FI:
+      """,
+      """
+      foo
+      """)
+
+  def test_hasIsaFeature(self):
+    no_isa = None
+    self.assertMatches(
+      """
+        /// CHECK-EVAL: hasIsaFeature('feature1') and not hasIsaFeature('feature2')
+      """,
+      """
+      foo
+      """,
+      no_isa,
+      ImmutableDict({"feature1": True})
+    )
+    self.assertDoesNotMatch(
+      """
+        /// CHECK-EVAL: not hasIsaFeature('feature1')
+      """,
+      """
+      foo
+      """,
+      no_isa,
+      ImmutableDict({"feature1": True})
+    )
+    self.assertMatches(
+      """
+        /// CHECK-IF: hasIsaFeature('feature2')
+        ///   CHECK: bar1
+        /// CHECK-ELSE:
+        ///   CHECK: bar2
+        /// CHECK-FI:
+      """,
+      """
+      foo
+      bar1
+      """,
+      no_isa,
+      ImmutableDict({"feature1": False, "feature2": True})
+    )
+    self.assertMatches(
+      """
+        /// CHECK-EVAL: hasIsaFeature('feature1') and not hasIsaFeature('feature2')
+      """,
+      """
+      foo
+      """,
+      "some_isa",
+      ImmutableDict({"feature1": True})
+    )
+    self.assertDoesNotMatch(
+      """
+        /// CHECK-EVAL: not hasIsaFeature('feature1')
+      """,
+      """
+      foo
+      """,
+      "some_isa",
+      ImmutableDict({"feature1": True})
+    )
+    self.assertMatches(
+      """
+        /// CHECK-IF: hasIsaFeature('feature2')
+        ///   CHECK: bar1
+        /// CHECK-ELSE:
+        ///   CHECK: bar2
+        /// CHECK-FI:
+      """,
+      """
+      foo
+      bar1
+      """,
+      "some_isa",
+      ImmutableDict({"feature1": False, "feature2": True})
+    )
diff --git a/tools/checker/run_unit_tests.py b/tools/checker/run_unit_tests.py
index a0d274d..7611c2e 100755
--- a/tools/checker/run_unit_tests.py
+++ b/tools/checker/run_unit_tests.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 #
 # Copyright (C) 2014 The Android Open Source Project
 #
@@ -14,18 +14,18 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from common.logger                 import Logger
+from common.logger import Logger
 from file_format.c1visualizer.test import C1visualizerParser_Test
-from file_format.checker.test      import CheckerParser_PrefixTest, \
-                                          CheckerParser_TestExpressionTest, \
-                                          CheckerParser_FileLayoutTest, \
-                                          CheckerParser_SuffixTests, \
-                                          CheckerParser_EvalTests
-from match.test                    import MatchLines_Test, \
-                                          MatchFiles_Test
+from file_format.checker.test import CheckerParser_PrefixTest, \
+  CheckerParser_TestExpressionTest, \
+  CheckerParser_FileLayoutTest, \
+  CheckerParser_SuffixTests, \
+  CheckerParser_EvalTests
+from match.test import MatchLines_Test, \
+  MatchFiles_Test
 
 import unittest
 
-if __name__ == '__main__':
-  Logger.Verbosity = Logger.Level.NoOutput
+if __name__ == "__main__":
+  Logger.Verbosity = Logger.Level.NO_OUTPUT
   unittest.main(verbosity=2)
diff --git a/tools/class2greylist/Android.bp b/tools/class2greylist/Android.bp
deleted file mode 100644
index f54aee7..0000000
--- a/tools/class2greylist/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// 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.
-//
-
-java_library_host {
-    name: "class2greylistlib",
-    srcs: ["src/**/*.java"],
-    static_libs: [
-        "commons-cli-1.2",
-        "apache-bcel",
-        "guava",
-        "testng",
-        "hamcrest-library",
-    ],
-}
-
-java_binary_host {
-    name: "class2greylist",
-    manifest: "src/class2greylist.mf",
-    static_libs: [
-        "class2greylistlib",
-    ],
-}
diff --git a/tools/class2greylist/src/class2greylist.mf b/tools/class2greylist/src/class2greylist.mf
deleted file mode 100644
index ea3a3d9..0000000
--- a/tools/class2greylist/src/class2greylist.mf
+++ /dev/null
@@ -1 +0,0 @@
-Main-Class: com.android.class2greylist.Class2Greylist
diff --git a/tools/class2greylist/src/com/android/class2greylist/AlternativeNotFoundError.java b/tools/class2greylist/src/com/android/class2greylist/AlternativeNotFoundError.java
deleted file mode 100644
index 10b2d9a..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/AlternativeNotFoundError.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-public class AlternativeNotFoundError extends Exception {
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/AnnotatedClassContext.java b/tools/class2greylist/src/com/android/class2greylist/AnnotatedClassContext.java
deleted file mode 100644
index 1dd74dd..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/AnnotatedClassContext.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.
- */
-package com.android.class2greylist;
-
-import java.util.Formatter;
-import java.util.Locale;
-import org.apache.bcel.Const;
-import org.apache.bcel.classfile.FieldOrMethod;
-import org.apache.bcel.classfile.JavaClass;
-
-/**
- * Encapsulates context for a single annotation on a class.
- */
-public class AnnotatedClassContext extends AnnotationContext {
-
-    public final String signatureFormatString;
-
-    public AnnotatedClassContext(
-            Status status,
-            JavaClass definingClass,
-            String signatureFormatString) {
-        super(status, definingClass);
-        this.signatureFormatString = signatureFormatString;
-    }
-
-    @Override
-    public String getMemberDescriptor() {
-        return String.format(Locale.US, signatureFormatString, getClassDescriptor());
-    }
-
-    @Override
-    public void reportError(String message, Object... args) {
-        Formatter error = new Formatter();
-        error
-            .format("%s: %s: ", definingClass.getSourceFileName(), definingClass.getClassName())
-            .format(Locale.US, message, args);
-
-        status.error(error.toString());
-    }
-
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/AnnotatedMemberContext.java b/tools/class2greylist/src/com/android/class2greylist/AnnotatedMemberContext.java
deleted file mode 100644
index 4802788..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/AnnotatedMemberContext.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-package com.android.class2greylist;
-
-import java.util.Formatter;
-import org.apache.bcel.Const;
-import org.apache.bcel.classfile.FieldOrMethod;
-import org.apache.bcel.classfile.JavaClass;
-
-import java.util.Locale;
-
-/**
- * Encapsulates context for a single annotation on a class member.
- */
-public class AnnotatedMemberContext extends AnnotationContext {
-
-    public final FieldOrMethod member;
-    public final String signatureFormatString;
-
-    public AnnotatedMemberContext(
-        Status status,
-        JavaClass definingClass,
-        FieldOrMethod member,
-        String signatureFormatString) {
-        super(status, definingClass);
-        this.member = member;
-        this.signatureFormatString = signatureFormatString;
-    }
-
-    @Override
-    public String getMemberDescriptor() {
-        return String.format(Locale.US, signatureFormatString,
-            getClassDescriptor(), member.getName(), member.getSignature());
-    }
-
-    @Override
-    public void reportError(String message, Object... args) {
-        Formatter error = new Formatter();
-        error
-            .format("%s: %s.%s: ", definingClass.getSourceFileName(),
-                definingClass.getClassName(), member.getName())
-            .format(Locale.US, message, args);
-
-        status.error(error.toString());
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/AnnotationConsumer.java b/tools/class2greylist/src/com/android/class2greylist/AnnotationConsumer.java
deleted file mode 100644
index 0f5f413..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/AnnotationConsumer.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.android.class2greylist;
-
-import java.util.Map;
-import java.util.Set;
-
-public interface AnnotationConsumer {
-    /**
-     * Handle a parsed annotation for a class member.
-     *
-     * @param apiSignature Signature of the class member.
-     * @param annotationProperties Map of stringified properties of this annotation.
-     * @param parsedFlags Array of flags parsed from the annotation for this member.
-     */
-    public void consume(String apiSignature, Map<String, String> annotationProperties,
-            Set<String> parsedFlags);
-
-    public void close();
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/AnnotationContext.java b/tools/class2greylist/src/com/android/class2greylist/AnnotationContext.java
deleted file mode 100644
index f0f7446..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/AnnotationContext.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.
- */
-package com.android.class2greylist;
-
-import org.apache.bcel.Const;
-import org.apache.bcel.classfile.JavaClass;
-
-/**
- */
-public abstract class AnnotationContext implements ErrorReporter {
-
-  public final Status status;
-  public final JavaClass definingClass;
-
-  public AnnotationContext(Status status, JavaClass definingClass) {
-    this.status = status;
-    this.definingClass = definingClass;
-  }
-
-  public String getClassDescriptor() {
-      // JavaClass.getName() returns the Java-style name (with . not /), so we must fetch
-      // the original class name from the constant pool.
-      return definingClass.getConstantPool().getConstantString(
-              definingClass.getClassNameIndex(), Const.CONSTANT_Class);
-  }
-
-  /**
-   * @return the full descriptor of this member, in the format expected in
-   * the greylist.
-   */
-  public abstract String getMemberDescriptor();
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/AnnotationHandler.java b/tools/class2greylist/src/com/android/class2greylist/AnnotationHandler.java
deleted file mode 100644
index ba1f583..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/AnnotationHandler.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.android.class2greylist;
-
-import java.util.Map;
-import java.util.HashMap;
-
-import org.apache.bcel.classfile.AnnotationEntry;
-import org.apache.bcel.classfile.ElementValuePair;
-
-
-/**
- * Base class for an annotation handler, which handle individual annotations on
- * class members.
- */
-public abstract class AnnotationHandler {
-    abstract void handleAnnotation(AnnotationEntry annotation, AnnotationContext context);
-
-    protected Map<String, String> stringifyAnnotationProperties(AnnotationEntry annotation) {
-        Map<String, String> content = new HashMap<String, String>();
-
-        // Stringify all annotation properties.
-        for (ElementValuePair prop : annotation.getElementValuePairs()) {
-            content.put(prop.getNameString(), prop.getValue().stringifyValue());
-        }
-
-        return content;
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/AnnotationPropertyWriter.java b/tools/class2greylist/src/com/android/class2greylist/AnnotationPropertyWriter.java
deleted file mode 100644
index 6656d3f..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/AnnotationPropertyWriter.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.android.class2greylist;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-public class AnnotationPropertyWriter implements AnnotationConsumer {
-
-    private final PrintStream mOutput;
-    private final List<Map<String, String>> mContents;
-    private final Set<String> mColumns;
-
-    public AnnotationPropertyWriter(String csvFile) throws FileNotFoundException {
-        mOutput = new PrintStream(new FileOutputStream(new File(csvFile)));
-        mContents = new ArrayList<>();
-        mColumns = new HashSet<>();
-    }
-
-    public AnnotationPropertyWriter(OutputStream output) {
-        mOutput = new PrintStream(output);
-        mContents = new ArrayList<>();
-        mColumns = new HashSet<>();
-    }
-
-    public void consume(String apiSignature, Map<String, String> annotationProperties,
-            Set<String> parsedFlags) {
-        // Clone properties map.
-        Map<String, String> contents = new HashMap(annotationProperties);
-
-        // Append the member signature.
-        contents.put("signature", apiSignature);
-
-        // Store data.
-        mColumns.addAll(contents.keySet());
-        mContents.add(contents);
-    }
-
-    private static String escapeCsvColumn(String column) {
-        // Using '|' as a quote character, as in frameworks/base/tools/hiddenapi/merge_csv.py
-        // Escape '|' characters in the column, then wrap the column in '|' characters.
-        column = column.replace("|", "||");
-        return "|" + column + "|";
-    }
-
-    public void close() {
-        // Sort columns by name and print header row.
-        List<String> columns = new ArrayList<>(mColumns);
-        columns.sort(Comparator.naturalOrder());
-        mOutput.println(columns.stream().collect(Collectors.joining(",")));
-
-        // Sort contents according to columns and print.
-        for (Map<String, String> row : mContents) {
-            mOutput.println(columns.stream().map(column -> row.getOrDefault(column, ""))
-                    .map(column -> escapeCsvColumn(column))
-                    .collect(Collectors.joining(",")));
-        }
-
-        // Close output.
-        mOutput.close();
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/AnnotationVisitor.java b/tools/class2greylist/src/com/android/class2greylist/AnnotationVisitor.java
deleted file mode 100644
index 3a58cf1..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/AnnotationVisitor.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.class2greylist;
-
-import org.apache.bcel.classfile.AnnotationEntry;
-import org.apache.bcel.classfile.DescendingVisitor;
-import org.apache.bcel.classfile.EmptyVisitor;
-import org.apache.bcel.classfile.Field;
-import org.apache.bcel.classfile.FieldOrMethod;
-import org.apache.bcel.classfile.JavaClass;
-import org.apache.bcel.classfile.Method;
-
-import java.util.Map;
-
-/**
- * Visits a JavaClass instance and passes any annotated members to a {@link AnnotationHandler}
- * according to the map provided.
- */
-public class AnnotationVisitor extends EmptyVisitor {
-
-    private final JavaClass mClass;
-    private final Status mStatus;
-    private final DescendingVisitor mDescendingVisitor;
-    private final Map<String, AnnotationHandler> mAnnotationHandlers;
-
-    /**
-     * Creates a visitor for a class.
-     *
-     * @param clazz Class to visit
-     * @param status For reporting debug information
-     * @param handlers Map of {@link AnnotationHandler}. The keys should be annotation names, as
-     *                 class descriptors.
-     */
-    public AnnotationVisitor(JavaClass clazz, Status status,
-            Map<String, AnnotationHandler> handlers) {
-        mClass = clazz;
-        mStatus = status;
-        mAnnotationHandlers = handlers;
-        mDescendingVisitor = new DescendingVisitor(clazz, this);
-    }
-
-    public void visit() {
-        mStatus.debug("Visit class %s", mClass.getClassName());
-        AnnotationContext context = new AnnotatedClassContext(mStatus, mClass, "L%s;");
-        AnnotationEntry[] annotationEntries = mClass.getAnnotationEntries();
-        handleAnnotations(context, annotationEntries);
-
-        mDescendingVisitor.visit();
-    }
-
-    @Override
-    public void visitMethod(Method method) {
-        visitMember(method, "L%s;->%s%s");
-    }
-
-    @Override
-    public void visitField(Field field) {
-        visitMember(field, "L%s;->%s:%s");
-    }
-
-    private void visitMember(FieldOrMethod member, String signatureFormatString) {
-        mStatus.debug("Visit member %s : %s", member.getName(), member.getSignature());
-        AnnotationContext context = new AnnotatedMemberContext(mStatus,
-            (JavaClass) mDescendingVisitor.predecessor(), member,
-            signatureFormatString);
-        AnnotationEntry[] annotationEntries = member.getAnnotationEntries();
-        handleAnnotations(context, annotationEntries);
-    }
-
-    private void handleAnnotations(AnnotationContext context, AnnotationEntry[] annotationEntries) {
-        for (AnnotationEntry a : annotationEntries) {
-            if (mAnnotationHandlers.containsKey(a.getAnnotationType())) {
-                mStatus.debug("Member has annotation %s for which we have a handler",
-                        a.getAnnotationType());
-                mAnnotationHandlers.get(a.getAnnotationType()).handleAnnotation(a, context);
-            } else {
-                mStatus.debug("Member has annotation %s for which we do not have a handler",
-                    a.getAnnotationType());
-            }
-        }
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/ApiComponents.java b/tools/class2greylist/src/com/android/class2greylist/ApiComponents.java
deleted file mode 100644
index 3da4fe8..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/ApiComponents.java
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Class which can parse either dex style signatures (e.g. Lfoo/bar/baz$bat;->foo()V) or javadoc
- * links to class members (e.g. {@link #toString()} or {@link java.util.List#clear()}).
- */
-public class ApiComponents {
-    private static final String PRIMITIVE_TYPES = "ZBCSIJFD";
-    private final PackageAndClassName mPackageAndClassName;
-    // The reference can be just to a class, in which case mMemberName should be empty.
-    private final String mMemberName;
-    // If the member being referenced is a field, this will always be empty.
-    private final String mMethodParameterTypes;
-
-    private ApiComponents(PackageAndClassName packageAndClassName, String memberName,
-            String methodParameterTypes) {
-        mPackageAndClassName = packageAndClassName;
-        mMemberName = memberName;
-        mMethodParameterTypes = methodParameterTypes;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder()
-                .append(mPackageAndClassName.packageName)
-                .append(".")
-                .append(mPackageAndClassName.className);
-        if (!mMemberName.isEmpty()) {
-            sb.append("#").append(mMemberName).append("(").append(mMethodParameterTypes).append(
-                    ")");
-        }
-        return sb.toString();
-    }
-
-    public PackageAndClassName getPackageAndClassName() {
-        return mPackageAndClassName;
-    }
-
-    public String getMemberName() {
-        return mMemberName;
-    }
-
-    public String getMethodParameterTypes() {
-        return mMethodParameterTypes;
-    }
-
-    /**
-     * Parse a JNI class descriptor. e.g. Lfoo/bar/Baz;
-     *
-     * @param sc Cursor over string assumed to contain a JNI class descriptor.
-     * @return The fully qualified class, in 'dot notation' (e.g. foo.bar.Baz for a class named Baz
-     * in the foo.bar package). The cursor will be placed after the semicolon.
-     */
-    private static String parseJNIClassDescriptor(StringCursor sc)
-            throws SignatureSyntaxError, StringCursorOutOfBoundsException {
-        if (sc.peek() != 'L') {
-            throw new SignatureSyntaxError(
-                    "Expected JNI class descriptor to start with L, but instead got " + sc.peek(),
-                    sc);
-        }
-        // Consume the L.
-        sc.next();
-        int semiColonPos = sc.find(';');
-        if (semiColonPos == -1) {
-            throw new SignatureSyntaxError("Expected semicolon at the end of JNI class descriptor",
-                    sc);
-        }
-        String jniClassDescriptor = sc.next(semiColonPos);
-        // Consume the semicolon.
-        sc.next();
-        return jniClassDescriptor.replace("/", ".");
-    }
-
-    /**
-     * Parse a primitive JNI type
-     *
-     * @param sc Cursor over a string assumed to contain a primitive JNI type.
-     * @return String containing parsed primitive JNI type.
-     */
-    private static String parseJNIPrimitiveType(StringCursor sc)
-            throws SignatureSyntaxError, StringCursorOutOfBoundsException {
-        char c = sc.next();
-        switch (c) {
-            case 'Z':
-                return "boolean";
-            case 'B':
-                return "byte";
-            case 'C':
-                return "char";
-            case 'S':
-                return "short";
-            case 'I':
-                return "int";
-            case 'J':
-                return "long";
-            case 'F':
-                return "float";
-            case 'D':
-                return "double";
-            default:
-                throw new SignatureSyntaxError(c + " is not a primitive type!", sc);
-        }
-    }
-
-    /**
-     * Parse a JNI type; can be either a primitive or object type. Arrays are handled separately.
-     *
-     * @param sc Cursor over the string assumed to contain a JNI type.
-     * @return String containing parsed JNI type.
-     */
-    private static String parseJniTypeWithoutArrayDimensions(StringCursor sc)
-            throws SignatureSyntaxError, StringCursorOutOfBoundsException {
-        char c = sc.peek();
-        if (PRIMITIVE_TYPES.indexOf(c) != -1) {
-            return parseJNIPrimitiveType(sc);
-        } else if (c == 'L') {
-            return parseJNIClassDescriptor(sc);
-        }
-        throw new SignatureSyntaxError("Illegal token " + c + " within signature", sc);
-    }
-
-    /**
-     * Parse a JNI type.
-     *
-     * This parameter can be an array, in which case it will be preceded by a number of open square
-     * brackets (corresponding to its dimensionality)
-     *
-     * @param sc Cursor over the string assumed to contain a JNI type.
-     * @return Same as {@link #parseJniTypeWithoutArrayDimensions}, but also handle arrays.
-     */
-    private static String parseJniType(StringCursor sc)
-            throws SignatureSyntaxError, StringCursorOutOfBoundsException {
-        int arrayDimension = 0;
-        while (sc.peek() == '[') {
-            ++arrayDimension;
-            sc.next();
-        }
-        StringBuilder sb = new StringBuilder();
-        sb.append(parseJniTypeWithoutArrayDimensions(sc));
-        for (int i = 0; i < arrayDimension; ++i) {
-            sb.append("[]");
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Converts the parameters of method from JNI notation to Javadoc link notation. e.g.
-     * "(IILfoo/bar/Baz;)V" turns into "int, int, foo.bar.Baz". The parentheses and return type are
-     * discarded.
-     *
-     * @param sc Cursor over the string assumed to contain a JNI method parameters.
-     * @return Comma separated list of parameter types.
-     */
-    private static String convertJNIMethodParametersToJavadoc(StringCursor sc)
-            throws SignatureSyntaxError, StringCursorOutOfBoundsException {
-        List<String> methodParameterTypes = new ArrayList<>();
-        if (sc.next() != '(') {
-            throw new IllegalArgumentException("Trying to parse method params of an invalid dex " +
-                    "signature: " + sc.getOriginalString());
-        }
-        while (sc.peek() != ')') {
-            methodParameterTypes.add(parseJniType(sc));
-        }
-        return String.join(", ", methodParameterTypes);
-    }
-
-    /**
-     * Generate ApiComponents from a dex signature.
-     *
-     * This is used to extract the necessary context for an alternative API to try to infer missing
-     * information.
-     *
-     * @param signature Dex signature.
-     * @return ApiComponents instance with populated package, class name, and parameter types if
-     * applicable.
-     */
-    public static ApiComponents fromDexSignature(String signature) throws SignatureSyntaxError {
-        StringCursor sc = new StringCursor(signature);
-        try {
-            String fullyQualifiedClass = parseJNIClassDescriptor(sc);
-
-            PackageAndClassName packageAndClassName =
-                    PackageAndClassName.splitClassName(fullyQualifiedClass);
-            if (!sc.peek(2).equals("->")) {
-                throw new SignatureSyntaxError("Expected '->'", sc);
-            }
-            // Consume "->"
-            sc.next(2);
-            String memberName = "";
-            String methodParameterTypes = "";
-            int leftParenPos = sc.find('(');
-            if (leftParenPos != -1) {
-                memberName = sc.next(leftParenPos);
-                methodParameterTypes = convertJNIMethodParametersToJavadoc(sc);
-            } else {
-                int colonPos = sc.find(':');
-                if (colonPos == -1) {
-                    throw new IllegalArgumentException("Expected : or -> beyond position "
-                            + sc.position() + " in " + signature);
-                } else {
-                    memberName = sc.next(colonPos);
-                    // Consume the ':'.
-                    sc.next();
-                    // Consume the type.
-                    parseJniType(sc);
-                }
-            }
-            return new ApiComponents(packageAndClassName, memberName, methodParameterTypes);
-        } catch (StringCursorOutOfBoundsException e) {
-            throw new SignatureSyntaxError(
-                    "Unexpectedly reached end of string while trying to parse signature ", sc);
-        }
-    }
-
-    /**
-     * Generate ApiComponents from a link tag.
-     *
-     * @param linkTag          The contents of a link tag.
-     * @param contextSignature The signature of the private API that this is an alternative for.
-     *                         Used to infer unspecified components.
-     */
-    public static ApiComponents fromLinkTag(String linkTag, String contextSignature)
-            throws JavadocLinkSyntaxError {
-        ApiComponents contextAlternative;
-        try {
-            contextAlternative = fromDexSignature(contextSignature);
-        } catch (SignatureSyntaxError e) {
-            throw new RuntimeException(
-                    "Failed to parse the context signature for public alternative!");
-        }
-        StringCursor sc = new StringCursor(linkTag);
-        try {
-
-            String memberName = "";
-            String methodParameterTypes = "";
-
-            int tagPos = sc.find('#');
-            String fullyQualifiedClassName = sc.next(tagPos);
-
-            PackageAndClassName packageAndClassName =
-                    PackageAndClassName.splitClassName(fullyQualifiedClassName);
-
-            if (packageAndClassName.packageName.isEmpty()) {
-                packageAndClassName.packageName = contextAlternative.getPackageAndClassName()
-                        .packageName;
-            }
-
-            if (packageAndClassName.className.isEmpty()) {
-                packageAndClassName.className = contextAlternative.getPackageAndClassName()
-                        .className;
-            }
-
-            if (tagPos == -1) {
-                // This suggested alternative is just a class. We can allow that.
-                return new ApiComponents(packageAndClassName, "", "");
-            } else {
-                // Consume the #.
-                sc.next();
-            }
-
-            int leftParenPos = sc.find('(');
-            memberName = sc.next(leftParenPos);
-            if (leftParenPos != -1) {
-                // Consume the '('.
-                sc.next();
-                int rightParenPos = sc.find(')');
-                if (rightParenPos == -1) {
-                    throw new JavadocLinkSyntaxError(
-                            "Linked method is missing a closing parenthesis", sc);
-                } else {
-                    methodParameterTypes = sc.next(rightParenPos);
-                }
-            }
-
-            return new ApiComponents(packageAndClassName, memberName, methodParameterTypes);
-        } catch (StringCursorOutOfBoundsException e) {
-            throw new JavadocLinkSyntaxError(
-                    "Unexpectedly reached end of string while trying to parse javadoc link", sc);
-        }
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof ApiComponents)) {
-            return false;
-        }
-        ApiComponents other = (ApiComponents) obj;
-        return mPackageAndClassName.equals(other.mPackageAndClassName) && mMemberName.equals(
-                other.mMemberName) && mMethodParameterTypes.equals(other.mMethodParameterTypes);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mPackageAndClassName, mMemberName, mMethodParameterTypes);
-    }
-
-    /**
-     * Less restrictive comparator to use in case a link tag is missing a method's parameters.
-     * e.g. foo.bar.Baz#foo will be considered the same as foo.bar.Baz#foo(int, int) and
-     * foo.bar.Baz#foo(long, long). If the class only has one method with that name, then specifying
-     * its parameter types is optional within the link tag.
-     */
-    public boolean equalsIgnoringParam(ApiComponents other) {
-        return mPackageAndClassName.equals(other.mPackageAndClassName) &&
-                mMemberName.equals(other.mMemberName);
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/ApiResolver.java b/tools/class2greylist/src/com/android/class2greylist/ApiResolver.java
deleted file mode 100644
index b120978..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/ApiResolver.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-import com.google.common.base.Strings;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-public class ApiResolver {
-    private final List<ApiComponents> mPotentialPublicAlternatives;
-    private final Set<PackageAndClassName> mPublicApiClasses;
-
-    private static final Pattern LINK_TAG_PATTERN = Pattern.compile("\\{@link ([^\\}]+)\\}");
-    private static final Pattern CODE_TAG_PATTERN = Pattern.compile("\\{@code ([^\\}]+)\\}");
-    private static final Integer MIN_SDK_REQUIRING_PUBLIC_ALTERNATIVES = 29;
-
-    public ApiResolver() {
-        mPotentialPublicAlternatives = null;
-        mPublicApiClasses = null;
-    }
-
-    public ApiResolver(Set<String> publicApis) {
-        mPotentialPublicAlternatives = publicApis.stream()
-                .map(api -> {
-                    try {
-                        return ApiComponents.fromDexSignature(api);
-                    } catch (SignatureSyntaxError e) {
-                        throw new RuntimeException("Could not parse public API signature:", e);
-                    }
-                })
-                .collect(Collectors.toList());
-        mPublicApiClasses = mPotentialPublicAlternatives.stream()
-                .map(api -> api.getPackageAndClassName())
-                .collect(Collectors.toCollection(HashSet::new));
-    }
-
-    /**
-     * Verify that all public alternatives are valid.
-     *
-     * @param publicAlternativesString String containing public alternative explanations.
-     * @param signature                Signature of the member that has the annotation.
-     */
-    public void resolvePublicAlternatives(String publicAlternativesString, String signature,
-                                          Integer maxSdkVersion)
-            throws JavadocLinkSyntaxError, AlternativeNotFoundError,
-                    RequiredAlternativeNotSpecifiedError {
-        if (Strings.isNullOrEmpty(publicAlternativesString) && maxSdkVersion != null
-                && maxSdkVersion >= MIN_SDK_REQUIRING_PUBLIC_ALTERNATIVES) {
-            throw new RequiredAlternativeNotSpecifiedError();
-        }
-        if (publicAlternativesString != null && mPotentialPublicAlternatives != null) {
-            // Grab all instances of type {@link foo}
-            Matcher matcher = LINK_TAG_PATTERN.matcher(publicAlternativesString);
-            boolean hasLinkAlternative = false;
-            // Validate all link tags
-            while (matcher.find()) {
-                hasLinkAlternative = true;
-                String alternativeString = matcher.group(1);
-                ApiComponents alternative = ApiComponents.fromLinkTag(alternativeString,
-                        signature);
-                if (alternative.getMemberName().isEmpty()) {
-                    // Provided class as alternative
-                    if (!mPublicApiClasses.contains(alternative.getPackageAndClassName())) {
-                        throw new ClassAlternativeNotFoundError(alternative);
-                    }
-                } else if (!mPotentialPublicAlternatives.contains(alternative)) {
-                    // If the link is not a public alternative, it must because the link does not
-                    // contain the method parameter types, e.g. {@link foo.bar.Baz#foo} instead of
-                    // {@link foo.bar.Baz#foo(int)}. If the method name is unique within the class,
-                    // we can handle it.
-                    if (!Strings.isNullOrEmpty(alternative.getMethodParameterTypes())) {
-                        throw new MemberAlternativeNotFoundError(alternative);
-                    }
-                    List<ApiComponents> almostMatches = mPotentialPublicAlternatives.stream()
-                            .filter(api -> api.equalsIgnoringParam(alternative))
-                            .collect(Collectors.toList());
-                    if (almostMatches.size() == 0) {
-                        throw new MemberAlternativeNotFoundError(alternative);
-                    } else if (almostMatches.size() > 1) {
-                        throw new MultipleAlternativesFoundError(alternative, almostMatches);
-                    }
-                }
-            }
-            // No {@link ...} alternatives exist; try looking for {@code ...}
-            if (!hasLinkAlternative) {
-                if (!CODE_TAG_PATTERN.matcher(publicAlternativesString).find()) {
-                    throw new NoAlternativesSpecifiedError();
-                }
-            }
-        }
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java b/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java
deleted file mode 100644
index afdd692..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.class2greylist;
-
-import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
-import com.google.common.io.Files;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Build time tool for extracting a list of members from jar files that have the @UsedByApps
- * annotation, for building the greylist.
- */
-public class Class2Greylist {
-
-    private static final String UNSUPPORTED_APP_USAGE_ANNOTATION =
-            "android.compat.annotation.UnsupportedAppUsage";
-
-    private static final String FLAG_GREYLIST = "greylist";
-    private static final String FLAG_BLACKLIST = "blacklist";
-    private static final String FLAG_GREYLIST_MAX_O = "greylist-max-o";
-    private static final String FLAG_GREYLIST_MAX_P = "greylist-max-p";
-    private static final String FLAG_GREYLIST_MAX_Q = "greylist-max-q";
-
-    private static final String FLAG_PUBLIC_API = "public-api";
-
-    private static final Map<Integer, String> TARGET_SDK_TO_LIST_MAP;
-    static {
-        Map<Integer, String> map = new HashMap<>();
-        map.put(null, FLAG_GREYLIST);
-        map.put(0, FLAG_BLACKLIST);
-        map.put(26, FLAG_GREYLIST_MAX_O);
-        map.put(28, FLAG_GREYLIST_MAX_P);
-        map.put(29, FLAG_GREYLIST_MAX_Q);
-        TARGET_SDK_TO_LIST_MAP = Collections.unmodifiableMap(map);
-    }
-
-    private final Status mStatus;
-    private final String[] mJarFiles;
-    private final AnnotationConsumer mOutput;
-    private final Set<String> mPublicApis;
-
-    public static void main(String[] args) {
-        Options options = new Options();
-        options.addOption(OptionBuilder
-                .withLongOpt("stub-api-flags")
-                .hasArgs(1)
-                .withDescription("CSV file with API flags generated from public API stubs. " +
-                        "Used to de-dupe bridge methods.")
-                .create("s"));
-        options.addOption(OptionBuilder
-                .withLongOpt("write-flags-csv")
-                .hasArgs(1)
-                .withDescription("Specify file to write hiddenapi flags to.")
-                .create('w'));
-        options.addOption(OptionBuilder
-                .withLongOpt("debug")
-                .hasArgs(0)
-                .withDescription("Enable debug")
-                .create("d"));
-        options.addOption(OptionBuilder
-                .withLongOpt("dump-all-members")
-                .withDescription("Dump all members from jar files to stdout. Ignore annotations. " +
-                        "Do not use in conjunction with any other arguments.")
-                .hasArgs(0)
-                .create('m'));
-        options.addOption(OptionBuilder
-                .withLongOpt("write-metadata-csv")
-                .hasArgs(1)
-                .withDescription("Specify a file to write API metaadata to. This is a CSV file " +
-                        "containing any annotation properties for all members. Do not use in " +
-                        "conjunction with --write-flags-csv.")
-                .create('c'));
-        options.addOption(OptionBuilder
-                .withLongOpt("help")
-                .hasArgs(0)
-                .withDescription("Show this help")
-                .create('h'));
-
-        CommandLineParser parser = new GnuParser();
-        CommandLine cmd;
-
-        try {
-            cmd = parser.parse(options, args);
-        } catch (ParseException e) {
-            System.err.println(e.getMessage());
-            help(options);
-            return;
-        }
-        if (cmd.hasOption('h')) {
-            help(options);
-        }
-
-
-        String[] jarFiles = cmd.getArgs();
-        if (jarFiles.length == 0) {
-            System.err.println("Error: no jar files specified.");
-            help(options);
-        }
-
-        Status status = new Status(cmd.hasOption('d'));
-
-        if (cmd.hasOption('m')) {
-            dumpAllMembers(status, jarFiles);
-        } else {
-            try {
-                Class2Greylist c2gl = new Class2Greylist(
-                        status,
-                        cmd.getOptionValue('s', null),
-                        cmd.getOptionValue('w', null),
-                        cmd.getOptionValue('c', null),
-                        jarFiles);
-                c2gl.main();
-            } catch (IOException e) {
-                status.error(e);
-            }
-        }
-
-        if (status.ok()) {
-            System.exit(0);
-        } else {
-            System.exit(1);
-        }
-
-    }
-
-    private Class2Greylist(Status status, String stubApiFlagsFile, String csvFlagsFile,
-            String csvMetadataFile, String[] jarFiles)
-            throws IOException {
-        mStatus = status;
-        mJarFiles = jarFiles;
-        if (csvMetadataFile != null) {
-            mOutput = new AnnotationPropertyWriter(csvMetadataFile);
-        } else {
-            mOutput = new HiddenapiFlagsWriter(csvFlagsFile);
-        }
-
-        if (stubApiFlagsFile != null) {
-            mPublicApis =
-                    Files.readLines(new File(stubApiFlagsFile), StandardCharsets.UTF_8).stream()
-                        .map(s -> Splitter.on(",").splitToList(s))
-                        .filter(s -> s.contains(FLAG_PUBLIC_API))
-                        .map(s -> s.get(0))
-                        .collect(Collectors.toSet());
-        } else {
-            mPublicApis = Collections.emptySet();
-        }
-    }
-
-    private Map<String, AnnotationHandler> createAnnotationHandlers() {
-        Builder<String, AnnotationHandler> builder = ImmutableMap.builder();
-        UnsupportedAppUsageAnnotationHandler greylistAnnotationHandler =
-                new UnsupportedAppUsageAnnotationHandler(
-                    mStatus, mOutput, mPublicApis, TARGET_SDK_TO_LIST_MAP);
-
-        addRepeatedAnnotationHandlers(
-                builder,
-                classNameToSignature(UNSUPPORTED_APP_USAGE_ANNOTATION),
-                classNameToSignature(UNSUPPORTED_APP_USAGE_ANNOTATION + "$Container"),
-                greylistAnnotationHandler);
-
-        CovariantReturnTypeHandler covariantReturnTypeHandler = new CovariantReturnTypeHandler(
-            mOutput, mPublicApis, FLAG_PUBLIC_API);
-
-        return addRepeatedAnnotationHandlers(builder, CovariantReturnTypeHandler.ANNOTATION_NAME,
-            CovariantReturnTypeHandler.REPEATED_ANNOTATION_NAME, covariantReturnTypeHandler)
-            .build();
-    }
-
-    private String classNameToSignature(String a) {
-        return "L" + a.replace('.', '/') + ";";
-    }
-
-    /**
-     * Add a handler for an annotation as well as an handler for the container annotation that is
-     * used when the annotation is repeated.
-     *
-     * @param builder the builder for the map to which the handlers will be added.
-     * @param annotationName the name of the annotation.
-     * @param containerAnnotationName the name of the annotation container.
-     * @param handler the handler for the annotation.
-     */
-    private static Builder<String, AnnotationHandler> addRepeatedAnnotationHandlers(
-        Builder<String, AnnotationHandler> builder,
-        String annotationName, String containerAnnotationName,
-        AnnotationHandler handler) {
-        return builder
-            .put(annotationName, handler)
-            .put(containerAnnotationName, new RepeatedAnnotationHandler(annotationName, handler));
-    }
-
-    private void main() {
-        Map<String, AnnotationHandler> handlers = createAnnotationHandlers();
-        for (String jarFile : mJarFiles) {
-            mStatus.debug("Processing jar file %s", jarFile);
-            try {
-                JarReader reader = new JarReader(mStatus, jarFile);
-                reader.stream().forEach(clazz -> new AnnotationVisitor(clazz, mStatus, handlers)
-                        .visit());
-                reader.close();
-            } catch (IOException e) {
-                mStatus.error(e);
-            }
-        }
-        mOutput.close();
-    }
-
-    private static void dumpAllMembers(Status status, String[] jarFiles) {
-        for (String jarFile : jarFiles) {
-            status.debug("Processing jar file %s", jarFile);
-            try {
-                JarReader reader = new JarReader(status, jarFile);
-                reader.stream().forEach(clazz -> new MemberDumpingVisitor(clazz, status)
-                        .visit());
-                reader.close();
-            } catch (IOException e) {
-                status.error(e);
-            }
-        }
-    }
-
-    private static void help(Options options) {
-        new HelpFormatter().printHelp(
-                "class2greylist path/to/classes.jar [classes2.jar ...]",
-                "Extracts greylist entries from classes jar files given",
-                options, null, true);
-        System.exit(1);
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/ClassAlternativeNotFoundError.java b/tools/class2greylist/src/com/android/class2greylist/ClassAlternativeNotFoundError.java
deleted file mode 100644
index 1f398f1..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/ClassAlternativeNotFoundError.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-public class ClassAlternativeNotFoundError extends AlternativeNotFoundError {
-    public final ApiComponents alternative;
-
-    ClassAlternativeNotFoundError(ApiComponents alternative) {
-        this.alternative = alternative;
-    }
-
-    @Override
-    public String toString() {
-        return "Specified class " + alternative.getPackageAndClassName() + " does not exist!";
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/CovariantReturnTypeHandler.java b/tools/class2greylist/src/com/android/class2greylist/CovariantReturnTypeHandler.java
deleted file mode 100644
index eb2e42d..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/CovariantReturnTypeHandler.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.android.class2greylist;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-
-import org.apache.bcel.classfile.AnnotationEntry;
-import org.apache.bcel.classfile.ElementValuePair;
-import org.apache.bcel.classfile.Method;
-
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Handles {@code CovariantReturnType} annotations, generating whitelist
- * entries from them.
- *
- * <p>A whitelist entry is generated with the same descriptor as the original
- * method, but with the return type replaced with than specified by the
- * {@link #RETURN_TYPE} property.
- *
- * <p>Methods are also validated against the public API list, to assert that
- * the annotated method is already a public API.
- */
-public class CovariantReturnTypeHandler extends AnnotationHandler {
-
-    private static final String SHORT_NAME = "CovariantReturnType";
-    public static final String ANNOTATION_NAME = "Ldalvik/annotation/codegen/CovariantReturnType;";
-    public static final String REPEATED_ANNOTATION_NAME =
-        "Ldalvik/annotation/codegen/CovariantReturnType$CovariantReturnTypes;";
-
-    private static final String RETURN_TYPE = "returnType";
-
-    private final AnnotationConsumer mAnnotationConsumer;
-    private final Set<String> mPublicApis;
-    private final String mHiddenapiFlag;
-
-    public CovariantReturnTypeHandler(AnnotationConsumer consumer, Set<String> publicApis,
-            String hiddenapiFlag) {
-        mAnnotationConsumer = consumer;
-        mPublicApis = publicApis;
-        mHiddenapiFlag = hiddenapiFlag;
-    }
-
-    @Override
-    public void handleAnnotation(AnnotationEntry annotation, AnnotationContext context) {
-        if (context instanceof AnnotatedClassContext) {
-            return;
-        }
-        handleAnnotation(annotation, (AnnotatedMemberContext) context);
-    }
-
-    private void handleAnnotation(AnnotationEntry annotation, AnnotatedMemberContext context) {
-        // Verify that the annotation has been applied to what we expect, and
-        // has the right form. Note, this should not strictly be necessary, as
-        // the annotation has a target of just 'method' and the property
-        // returnType does not have a default value, but checking makes the code
-        // less brittle to future changes.
-        if (!(context.member instanceof Method)) {
-            context.reportError("Cannot specify %s on a field", RETURN_TYPE);
-            return;
-        }
-        String returnType = findReturnType(annotation);
-        if (returnType == null) {
-            context.reportError("No %s set on @%s", RETURN_TYPE, SHORT_NAME);
-            return;
-        }
-        if (!mPublicApis.contains(context.getMemberDescriptor())) {
-            context.reportError("Found @%s on non-SDK method", SHORT_NAME);
-            return;
-        }
-
-        // Generate the signature of overload that we expect the annotation will
-        // cause the platform dexer to create.
-        String typeSignature = context.member.getSignature();
-        int closingBrace = typeSignature.indexOf(')');
-        Preconditions.checkState(closingBrace != -1,
-                "No ) found in method type signature %s", typeSignature);
-        typeSignature = new StringBuilder()
-                .append(typeSignature.substring(0, closingBrace + 1))
-                .append(returnType)
-                .toString();
-        String signature = String.format(Locale.US, context.signatureFormatString,
-                context.getClassDescriptor(), context.member.getName(), typeSignature);
-
-        if (mPublicApis.contains(signature)) {
-            context.reportError("Signature %s generated from @%s already exists as a public API",
-                    signature, SHORT_NAME);
-            return;
-        }
-
-        mAnnotationConsumer.consume(signature, stringifyAnnotationProperties(annotation),
-                ImmutableSet.of(mHiddenapiFlag));
-    }
-
-    private String findReturnType(AnnotationEntry a) {
-        for (ElementValuePair property : a.getElementValuePairs()) {
-            if (property.getNameString().equals(RETURN_TYPE)) {
-                return property.getValue().stringifyValue();
-            }
-        }
-        // not found
-        return null;
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/ErrorReporter.java b/tools/class2greylist/src/com/android/class2greylist/ErrorReporter.java
deleted file mode 100644
index 24a92f0..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/ErrorReporter.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-public interface ErrorReporter {
-    /**
-     * Report an error in this context. The final error message will include
-     * the class and member names, and the source file name.
-     */
-    void reportError(String message, Object... args);
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/HiddenapiFlagsWriter.java b/tools/class2greylist/src/com/android/class2greylist/HiddenapiFlagsWriter.java
deleted file mode 100644
index 54ca17c..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/HiddenapiFlagsWriter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.android.class2greylist;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-public class HiddenapiFlagsWriter implements AnnotationConsumer {
-
-    private final PrintStream mOutput;
-
-    public HiddenapiFlagsWriter(String csvFile) throws FileNotFoundException {
-        mOutput = new PrintStream(new FileOutputStream(new File(csvFile)));
-    }
-
-    public void consume(String apiSignature, Map<String, String> annotationProperties,
-            Set<String> parsedFlags) {
-        if (parsedFlags.size() > 0) {
-            mOutput.println(apiSignature + "," + String.join(",", asSortedList(parsedFlags)));
-        }
-    }
-
-    public void close() {
-        mOutput.close();
-    }
-
-    private static List<String> asSortedList(Set<String> s) {
-        List<String> list = new ArrayList<>(s);
-        Collections.sort(list);
-        return list;
-    }
-
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/JarReader.java b/tools/class2greylist/src/com/android/class2greylist/JarReader.java
deleted file mode 100644
index f3a9d0b..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/JarReader.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.class2greylist;
-
-import org.apache.bcel.classfile.ClassParser;
-import org.apache.bcel.classfile.JavaClass;
-
-import java.io.IOException;
-import java.util.Objects;
-import java.util.stream.Stream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-/**
- * Reads {@link JavaClass} members from a zip/jar file, providing a stream of them for processing.
- * Any errors are reported via {@link Status#error(Throwable)}.
- */
-public class JarReader {
-
-    private final Status mStatus;
-    private final String mFileName;
-    private final ZipFile mZipFile;
-
-    public JarReader(Status s, String filename) throws IOException {
-        mStatus = s;
-        mFileName = filename;
-        mZipFile = new ZipFile(mFileName);
-    }
-
-    private JavaClass openZipEntry(ZipEntry e) {
-        try {
-            mStatus.debug("Reading %s from %s", e.getName(), mFileName);
-            return new ClassParser(mZipFile.getInputStream(e), e.getName()).parse();
-        } catch (IOException ioe) {
-            mStatus.error(ioe);
-            return null;
-        }
-    }
-
-
-    public Stream<JavaClass> stream() {
-        return mZipFile.stream()
-                .filter(zipEntry -> zipEntry.getName().endsWith(".class"))
-                .map(zipEntry -> openZipEntry(zipEntry))
-                .filter(Objects::nonNull);
-    }
-
-    public void close() throws IOException {
-        mZipFile.close();
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/JavadocLinkSyntaxError.java b/tools/class2greylist/src/com/android/class2greylist/JavadocLinkSyntaxError.java
deleted file mode 100644
index 55014cb..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/JavadocLinkSyntaxError.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-public class JavadocLinkSyntaxError extends Exception {
-    public final String expected;
-    public final int position;
-    public final String context;
-
-    public JavadocLinkSyntaxError(String expected, StringCursor sc) {
-        super(expected + " at position " + sc.position() + " in " + sc.getOriginalString());
-        this.expected = expected;
-        this.position = sc.position();
-        this.context = sc.getOriginalString();
-    }
-}
-
diff --git a/tools/class2greylist/src/com/android/class2greylist/MemberAlternativeNotFoundError.java b/tools/class2greylist/src/com/android/class2greylist/MemberAlternativeNotFoundError.java
deleted file mode 100644
index 43f853e..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/MemberAlternativeNotFoundError.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-public class MemberAlternativeNotFoundError extends AlternativeNotFoundError {
-    public final ApiComponents alternative;
-
-    MemberAlternativeNotFoundError(ApiComponents alternative) {
-        this.alternative = alternative;
-    }
-
-    @Override
-    public String toString() {
-        return "Could not find public api " + alternative + ".";
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/MemberDumpingVisitor.java b/tools/class2greylist/src/com/android/class2greylist/MemberDumpingVisitor.java
deleted file mode 100644
index 89c8bd7..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/MemberDumpingVisitor.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.android.class2greylist;
-
-import org.apache.bcel.classfile.DescendingVisitor;
-import org.apache.bcel.classfile.EmptyVisitor;
-import org.apache.bcel.classfile.Field;
-import org.apache.bcel.classfile.FieldOrMethod;
-import org.apache.bcel.classfile.JavaClass;
-import org.apache.bcel.classfile.Method;
-
-/**
- * A class file visitor that simply prints to stdout the signature of every member within the class.
- */
-public class MemberDumpingVisitor extends EmptyVisitor {
-
-    private final Status mStatus;
-    private final DescendingVisitor mDescendingVisitor;
-
-    /**
-     * Creates a visitor for a class.
-     *
-     * @param clazz Class to visit
-     */
-    public MemberDumpingVisitor(JavaClass clazz, Status status) {
-        mStatus = status;
-        mDescendingVisitor = new DescendingVisitor(clazz, this);
-    }
-
-    public void visit() {
-        mDescendingVisitor.visit();
-    }
-
-    @Override
-    public void visitMethod(Method method) {
-        visitMember(method, "L%s;->%s%s");
-    }
-
-    @Override
-    public void visitField(Field field) {
-        visitMember(field, "L%s;->%s:%s");
-    }
-
-    private void visitMember(FieldOrMethod member, String signatureFormatString) {
-        AnnotationContext context = new AnnotatedMemberContext(mStatus,
-            (JavaClass) mDescendingVisitor.predecessor(), member,
-            signatureFormatString);
-        System.out.println(context.getMemberDescriptor());
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/MultipleAlternativesFoundError.java b/tools/class2greylist/src/com/android/class2greylist/MultipleAlternativesFoundError.java
deleted file mode 100644
index a598534..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/MultipleAlternativesFoundError.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-import com.google.common.base.Joiner;
-
-import java.util.List;
-
-public class MultipleAlternativesFoundError extends AlternativeNotFoundError {
-    public final ApiComponents alternative;
-    public final List<ApiComponents> almostMatches;
-
-    public MultipleAlternativesFoundError(ApiComponents alternative,
-            List<ApiComponents> almostMatches) {
-        this.alternative = alternative;
-        this.almostMatches = almostMatches;
-    }
-
-    @Override
-    public String toString() {
-        return "Alternative " + alternative + " returned multiple matches: "
-                + Joiner.on(", ").join(almostMatches);
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/NoAlternativesSpecifiedError.java b/tools/class2greylist/src/com/android/class2greylist/NoAlternativesSpecifiedError.java
deleted file mode 100644
index 28c5003..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/NoAlternativesSpecifiedError.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-public class NoAlternativesSpecifiedError extends AlternativeNotFoundError {
-
-    @Override
-    public String toString() {
-        return "Hidden API has a public alternative annotation field, but no concrete "
-                + "explanations. Please provide either a reference to an SDK method using javadoc "
-                + "syntax, e.g. {@link foo.bar.Baz#bat}, or a small code snippet if the "
-                + "alternative is part of a support library or third party library, e.g. "
-                + "{@code foo.bar.Baz bat = new foo.bar.Baz(); bat.doSomething();}.\n"
-                + "If this is too restrictive for your use case, please contact compat-team@.";
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/PackageAndClassName.java b/tools/class2greylist/src/com/android/class2greylist/PackageAndClassName.java
deleted file mode 100644
index 709092d..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/PackageAndClassName.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-import java.util.Objects;
-
-class PackageAndClassName{
-    public String packageName;
-    public String className;
-
-    private PackageAndClassName(String packageName, String className) {
-        this.packageName = packageName;
-        this.className = className;
-    }
-
-    /**
-     * Given a potentially fully qualified class name, split it into package and class.
-     *
-     * @param fullyQualifiedClassName potentially fully qualified class name.
-     * @return A pair of strings, containing the package name (or empty if not specified) and
-     * the
-     * class name (or empty if string is empty).
-     */
-    public static PackageAndClassName splitClassName(String fullyQualifiedClassName) {
-        int lastDotIdx = fullyQualifiedClassName.lastIndexOf('.');
-        if (lastDotIdx == -1) {
-            return new PackageAndClassName("", fullyQualifiedClassName);
-        }
-        String packageName = fullyQualifiedClassName.substring(0, lastDotIdx);
-        String className = fullyQualifiedClassName.substring(lastDotIdx + 1);
-        return new PackageAndClassName(packageName, className);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof PackageAndClassName)) {
-            return false;
-        }
-        PackageAndClassName other = (PackageAndClassName) obj;
-        return Objects.equals(packageName, other.packageName) && Objects.equals(className,
-                other.className);
-    }
-
-    @Override
-    public String toString() {
-        return packageName + "." + className;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(packageName, className);
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/RepeatedAnnotationHandler.java b/tools/class2greylist/src/com/android/class2greylist/RepeatedAnnotationHandler.java
deleted file mode 100644
index 61949e3..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/RepeatedAnnotationHandler.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.android.class2greylist;
-
-import com.google.common.base.Preconditions;
-import org.apache.bcel.classfile.AnnotationElementValue;
-import org.apache.bcel.classfile.AnnotationEntry;
-import org.apache.bcel.classfile.ArrayElementValue;
-import org.apache.bcel.classfile.ElementValue;
-import org.apache.bcel.classfile.ElementValuePair;
-
-/**
- * Handles a repeated annotation container.
- *
- * <p>The enclosed annotations are passed to the {@link #mWrappedHandler}.
- */
-public class RepeatedAnnotationHandler extends AnnotationHandler {
-
-    private static final String VALUE = "value";
-
-    private final AnnotationHandler mWrappedHandler;
-    private final String mInnerAnnotationName;
-
-    RepeatedAnnotationHandler(String innerAnnotationName, AnnotationHandler wrappedHandler) {
-        mWrappedHandler = wrappedHandler;
-        mInnerAnnotationName = innerAnnotationName;
-    }
-
-    @Override
-    public void handleAnnotation(AnnotationEntry annotation, AnnotationContext context) {
-        // Verify that the annotation has the form we expect
-        ElementValuePair value = findValue(annotation);
-        if (value == null) {
-            context.reportError("No value found on %s", annotation.getAnnotationType());
-            return;
-        }
-        Preconditions.checkArgument(value.getValue() instanceof ArrayElementValue);
-        ArrayElementValue array = (ArrayElementValue) value.getValue();
-
-        // call wrapped handler on each enclosed annotation:
-        for (ElementValue v : array.getElementValuesArray()) {
-            Preconditions.checkArgument(v instanceof AnnotationElementValue);
-            AnnotationElementValue aev = (AnnotationElementValue) v;
-            Preconditions.checkArgument(
-                    aev.getAnnotationEntry().getAnnotationType().equals(mInnerAnnotationName));
-            mWrappedHandler.handleAnnotation(aev.getAnnotationEntry(), context);
-        }
-    }
-
-    private ElementValuePair findValue(AnnotationEntry a) {
-        for (ElementValuePair property : a.getElementValuePairs()) {
-            if (property.getNameString().equals(VALUE)) {
-                return property;
-            }
-        }
-        // not found
-        return null;
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/RequiredAlternativeNotSpecifiedError.java b/tools/class2greylist/src/com/android/class2greylist/RequiredAlternativeNotSpecifiedError.java
deleted file mode 100644
index a65f1fe..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/RequiredAlternativeNotSpecifiedError.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-/**
- * Exception to be thrown when a greylisted private api gets restricted to max-FOO (where FOO is Q
- * or later), without providing a public API alternative.
- */
-public class RequiredAlternativeNotSpecifiedError extends Exception {
-
-}
-
diff --git a/tools/class2greylist/src/com/android/class2greylist/SignatureSyntaxError.java b/tools/class2greylist/src/com/android/class2greylist/SignatureSyntaxError.java
deleted file mode 100644
index 7685caa..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/SignatureSyntaxError.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-public class SignatureSyntaxError extends Exception {
-    public final String expected;
-    public final int position;
-    public final String context;
-    public SignatureSyntaxError(String expected, StringCursor sc) {
-        super(expected + " at position " + sc.position() + " in " + sc.getOriginalString());
-        this.expected = expected;
-        this.position = sc.position();
-        this.context = sc.getOriginalString();
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/Status.java b/tools/class2greylist/src/com/android/class2greylist/Status.java
deleted file mode 100644
index b5ee9f1..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/Status.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.class2greylist;
-
-import java.util.Locale;
-
-public class Status {
-
-    // Highlight "Error:" in red.
-    private static final String ERROR = "\u001B[31mError: \u001B[0m";
-
-    private final boolean mDebug;
-    private boolean mHasErrors;
-
-    public Status(boolean debug) {
-        mDebug = debug;
-    }
-
-    public void debug(String msg, Object... args) {
-        if (mDebug) {
-            System.err.println(String.format(Locale.US, msg, args));
-        }
-    }
-
-    public void error(Throwable t) {
-        System.err.print(ERROR);
-        t.printStackTrace(System.err);
-        mHasErrors = true;
-    }
-
-    public void error(String message, Object... args) {
-        System.err.print(ERROR);
-        System.err.println(String.format(Locale.US, message, args));
-        mHasErrors = true;
-    }
-
-    public boolean ok() {
-        return !mHasErrors;
-    }
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/StringCursor.java b/tools/class2greylist/src/com/android/class2greylist/StringCursor.java
deleted file mode 100644
index 08e8521..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/StringCursor.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-/**
- * Utility class to simplify parsing of signatures.
- */
-public class StringCursor {
-
-    private final String mString;
-    private int mCursor;
-
-    public StringCursor(String str) {
-        mString = str;
-        mCursor = 0;
-    }
-
-    /**
-     * Position of cursor in string.
-     *
-     * @return Current position of cursor in string.
-     */
-    public int position() {
-        return mCursor;
-    }
-
-    /**
-     * Peek current cursor position.
-     *
-     * @return The character at the current cursor position.
-     */
-    public char peek() {
-        return mString.charAt(mCursor);
-    }
-
-    /**
-     * Peek several characters at the current cursor position without moving the cursor.
-     *
-     * @param n The number of characters to peek.
-     * @return A string with x characters from the cursor position. If n is -1, return the whole
-     *        rest of the string.
-     */
-    public String peek(int n) throws StringCursorOutOfBoundsException {
-        if (n == -1) {
-            return mString.substring(mCursor);
-        }
-        if (n < 0 || (n + mCursor) >= mString.length()) {
-            throw new StringCursorOutOfBoundsException();
-        }
-        return mString.substring(mCursor, mCursor + n);
-    }
-
-    /**
-     * Consume the character at the current cursor position and move the cursor forwards.
-     *
-     * @return The character at the current cursor position.
-     */
-    public char next() throws StringCursorOutOfBoundsException {
-        if (!hasNext()) {
-            throw new StringCursorOutOfBoundsException();
-        }
-        return mString.charAt(mCursor++);
-    }
-
-    /**
-     * Consume several characters at the current cursor position and move the cursor further along.
-     *
-     * @param n The number of characters to consume.
-     * @return A string with x characters from the cursor position. If n is -1, return the whole
-     *         rest of the string.
-     */
-    public String next(int n) throws StringCursorOutOfBoundsException {
-        if (n == -1) {
-            String restOfString = mString.substring(mCursor);
-            mCursor = mString.length();
-            return restOfString;
-        }
-        if (n < 0) {
-            throw new StringCursorOutOfBoundsException();
-        }
-        mCursor += n;
-        return mString.substring(mCursor - n, mCursor);
-    }
-
-    /**
-     * Search for the first occurrence of a character beyond the current cursor position.
-     *
-     * @param c The character to search for.
-     * @return The offset of the first occurrence of c in the string beyond the cursor position.
-     * If the character does not exist, return -1.
-     */
-    public int find(char c) {
-        int firstIndex = mString.indexOf(c, mCursor);
-        if (firstIndex == -1) {
-            return -1;
-        }
-        return firstIndex - mCursor;
-    }
-
-    /**
-     * Check if cursor has reached end of string.
-     *
-     * @return Cursor has reached end of string.
-     */
-    public boolean hasNext() {
-        return mCursor < mString.length();
-    }
-
-    @Override
-    public String toString() {
-        return mString.substring(mCursor);
-    }
-
-    public String getOriginalString() {
-        return mString;
-    }
-}
\ No newline at end of file
diff --git a/tools/class2greylist/src/com/android/class2greylist/StringCursorOutOfBoundsException.java b/tools/class2greylist/src/com/android/class2greylist/StringCursorOutOfBoundsException.java
deleted file mode 100644
index caf0bd6..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/StringCursorOutOfBoundsException.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-public class StringCursorOutOfBoundsException extends IndexOutOfBoundsException {
-
-}
diff --git a/tools/class2greylist/src/com/android/class2greylist/UnsupportedAppUsageAnnotationHandler.java b/tools/class2greylist/src/com/android/class2greylist/UnsupportedAppUsageAnnotationHandler.java
deleted file mode 100644
index 3ce00df..0000000
--- a/tools/class2greylist/src/com/android/class2greylist/UnsupportedAppUsageAnnotationHandler.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package com.android.class2greylist;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableSet;
-
-import org.apache.bcel.Const;
-import org.apache.bcel.classfile.AnnotationEntry;
-import org.apache.bcel.classfile.ElementValue;
-import org.apache.bcel.classfile.ElementValuePair;
-import org.apache.bcel.classfile.FieldOrMethod;
-import org.apache.bcel.classfile.Method;
-import org.apache.bcel.classfile.SimpleElementValue;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Predicate;
-
-/**
- * Processes {@code UnsupportedAppUsage} annotations to generate greylist
- * entries.
- *
- * Any annotations with a {@link #EXPECTED_SIGNATURE_PROPERTY} property will have their
- * generated signature verified against this, and an error will be reported if
- * it does not match. Exclusions are made for bridge methods.
- *
- * Any {@link #MAX_TARGET_SDK_PROPERTY} properties will be validated against the given
- * set of valid values, then passed through to the greylist consumer.
- */
-public class UnsupportedAppUsageAnnotationHandler extends AnnotationHandler {
-
-    // properties of greylist annotations:
-    private static final String EXPECTED_SIGNATURE_PROPERTY = "expectedSignature";
-    private static final String MAX_TARGET_SDK_PROPERTY = "maxTargetSdk";
-    private static final String IMPLICIT_MEMBER_PROPERTY = "implicitMember";
-    private static final String PUBLIC_ALTERNATIVES_PROPERTY = "publicAlternatives";
-
-    private final Status mStatus;
-    private final Predicate<ClassMember> mClassMemberFilter;
-    private final Map<Integer, String> mSdkVersionToFlagMap;
-    private final AnnotationConsumer mAnnotationConsumer;
-
-    private ApiResolver mApiResolver;
-
-    /**
-     * Represents a member of a class file (a field or method).
-     */
-    @VisibleForTesting
-    public static class ClassMember {
-
-        /**
-         * Signature of this class member.
-         */
-        public final String signature;
-
-        /**
-         * Indicates if this is a synthetic bridge method.
-         */
-        public final boolean isBridgeMethod;
-
-        public ClassMember(String signature, boolean isBridgeMethod) {
-            this.signature = signature;
-            this.isBridgeMethod = isBridgeMethod;
-        }
-    }
-
-    public UnsupportedAppUsageAnnotationHandler(Status status,
-            AnnotationConsumer annotationConsumer, Set<String> publicApis,
-            Map<Integer, String> sdkVersionToFlagMap) {
-        this(status, annotationConsumer,
-                member -> !(member.isBridgeMethod && publicApis.contains(member.signature)),
-                sdkVersionToFlagMap);
-        mApiResolver = new ApiResolver(publicApis);
-    }
-
-    @VisibleForTesting
-    public UnsupportedAppUsageAnnotationHandler(Status status,
-            AnnotationConsumer annotationConsumer, Predicate<ClassMember> memberFilter,
-            Map<Integer, String> sdkVersionToFlagMap) {
-        mStatus = status;
-        mAnnotationConsumer = annotationConsumer;
-        mClassMemberFilter = memberFilter;
-        mSdkVersionToFlagMap = sdkVersionToFlagMap;
-        mApiResolver = new ApiResolver();
-    }
-
-    @Override
-    public void handleAnnotation(AnnotationEntry annotation, AnnotationContext context) {
-        boolean isBridgeMethod = false;
-        if (context instanceof AnnotatedMemberContext) {
-            AnnotatedMemberContext memberContext = (AnnotatedMemberContext) context;
-            FieldOrMethod member = memberContext.member;
-            isBridgeMethod = (member instanceof Method) &&
-                    (member.getAccessFlags() & Const.ACC_BRIDGE) != 0;
-            if (isBridgeMethod) {
-                mStatus.debug("Member is a bridge method");
-            }
-        }
-
-        String signature = context.getMemberDescriptor();
-        Integer maxTargetSdk = null;
-        String implicitMemberSignature = null;
-        String publicAlternativesString = null;
-
-        for (ElementValuePair property : annotation.getElementValuePairs()) {
-            switch (property.getNameString()) {
-                case EXPECTED_SIGNATURE_PROPERTY:
-                    String expected = property.getValue().stringifyValue();
-                    // Don't enforce for bridge methods; they're generated so won't match.
-                    if (!isBridgeMethod && !signature.equals(expected)) {
-                        context.reportError("Expected signature does not match generated:\n"
-                                + "Expected:  %s\n"
-                                + "Generated: %s", expected, signature);
-                        return;
-                    }
-                    break;
-                case MAX_TARGET_SDK_PROPERTY:
-                    if (property.getValue().getElementValueType() != ElementValue.PRIMITIVE_INT) {
-                        context.reportError("Expected property %s to be of type int; got %d",
-                                property.getNameString(),
-                                property.getValue().getElementValueType());
-                        return;
-                    }
-
-                    maxTargetSdk = ((SimpleElementValue) property.getValue()).getValueInt();
-                    break;
-                case IMPLICIT_MEMBER_PROPERTY:
-                    implicitMemberSignature = property.getValue().stringifyValue();
-                    if (context instanceof AnnotatedClassContext) {
-                        signature = String.format("L%s;->%s",
-                                context.getClassDescriptor(), implicitMemberSignature);
-                    } else {
-                        context.reportError(
-                                "Expected annotation with an %s property to be on a class but is "
-                                        + "on %s",
-                                IMPLICIT_MEMBER_PROPERTY,
-                                signature);
-                        return;
-                    }
-                    break;
-                case PUBLIC_ALTERNATIVES_PROPERTY:
-                    publicAlternativesString = property.getValue().stringifyValue();
-                    break;
-            }
-        }
-
-        if (context instanceof AnnotatedClassContext && implicitMemberSignature == null) {
-            context.reportError(
-                    "Missing property %s on annotation on class %s",
-                    IMPLICIT_MEMBER_PROPERTY,
-                    signature);
-            return;
-        }
-
-        // Verify that maxTargetSdk is valid.
-        if (!mSdkVersionToFlagMap.containsKey(maxTargetSdk)) {
-            context.reportError("Invalid value for %s: got %d, expected one of [%s]",
-                    MAX_TARGET_SDK_PROPERTY,
-                    maxTargetSdk,
-                    mSdkVersionToFlagMap.keySet());
-            return;
-        }
-
-        try {
-            mApiResolver.resolvePublicAlternatives(publicAlternativesString, signature,
-                    maxTargetSdk);
-        } catch (JavadocLinkSyntaxError | AlternativeNotFoundError e) {
-            context.reportError(e.toString());
-        } catch (RequiredAlternativeNotSpecifiedError e) {
-            context.reportError("Signature %s moved to %s without specifying public "
-                            + "alternatives; Refer to go/unsupportedappusage-public-alternatives "
-                            + "for details.",
-                    signature, mSdkVersionToFlagMap.get(maxTargetSdk));
-        }
-
-        // Consume this annotation if it matches the predicate.
-        if (mClassMemberFilter.test(new ClassMember(signature, isBridgeMethod))) {
-            mAnnotationConsumer.consume(signature, stringifyAnnotationProperties(annotation),
-                    ImmutableSet.of(mSdkVersionToFlagMap.get(maxTargetSdk)));
-        }
-    }
-}
diff --git a/tools/class2greylist/test/Android.bp b/tools/class2greylist/test/Android.bp
deleted file mode 100644
index 5483ea0..0000000
--- a/tools/class2greylist/test/Android.bp
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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.
-
-java_test_host {
-    name: "class2greylisttest",
-
-    // Only compile source java files in this apk.
-    srcs: ["src/**/*.java"],
-
-    static_libs: [
-        "class2greylistlib",
-        "libjavac",
-        "truth-host-prebuilt",
-        "mockito-host",
-        "junit-host",
-        "objenesis",
-    ],
-}
diff --git a/tools/class2greylist/test/AndroidTest.xml b/tools/class2greylist/test/AndroidTest.xml
deleted file mode 100644
index 66bb634..0000000
--- a/tools/class2greylist/test/AndroidTest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="class2greylist tests">
-    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
-        <option name="jar" value="class2greylisttest.jar" />
-        <option name="runtime-hint" value="1m" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/tools/class2greylist/test/src/com/android/class2greylist/AnnotationHandlerTestBase.java b/tools/class2greylist/test/src/com/android/class2greylist/AnnotationHandlerTestBase.java
deleted file mode 100644
index 65ebbf0..0000000
--- a/tools/class2greylist/test/src/com/android/class2greylist/AnnotationHandlerTestBase.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.class2greylist;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.withSettings;
-
-import com.android.javac.Javac;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.rules.TestName;
-
-import java.io.IOException;
-
-public class AnnotationHandlerTestBase {
-
-    @Rule
-    public TestName mTestName = new TestName();
-
-    protected Javac mJavac;
-    protected AnnotationConsumer mConsumer;
-    protected Status mStatus;
-
-    @Before
-    public void baseSetup() throws IOException {
-        System.out.println(String.format("\n============== STARTING TEST: %s ==============\n",
-                mTestName.getMethodName()));
-        mConsumer = mock(AnnotationConsumer.class);
-        mStatus = mock(Status.class, withSettings().verboseLogging());
-        mJavac = new Javac();
-    }
-
-    protected void assertNoErrors() {
-        verify(mStatus, never()).error(any(Throwable.class));
-        verify(mStatus, never()).error(any(), any());
-    }
-}
diff --git a/tools/class2greylist/test/src/com/android/class2greylist/AnnotationPropertyWriterTest.java b/tools/class2greylist/test/src/com/android/class2greylist/AnnotationPropertyWriterTest.java
deleted file mode 100644
index a6c7770..0000000
--- a/tools/class2greylist/test/src/com/android/class2greylist/AnnotationPropertyWriterTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.common.collect.ImmutableMap;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-
-public class AnnotationPropertyWriterTest {
-
-    private ByteArrayOutputStream mByteArrayOutputStream;
-    private AnnotationPropertyWriter mAnnotationPropertyWriter;
-
-    @Before
-    public void setup() {
-        mByteArrayOutputStream = new ByteArrayOutputStream();
-        mAnnotationPropertyWriter = new AnnotationPropertyWriter(mByteArrayOutputStream);
-    }
-
-    @Test
-    public void testExportPropertiesNoEscaping() {
-        String signature = "foo";
-        Map<String, String> annotationProperties = ImmutableMap.of(
-                "prop", "val"
-        );
-        Set<String> parsedFlags = new HashSet<String>();
-        mAnnotationPropertyWriter.consume(signature, annotationProperties, parsedFlags);
-        mAnnotationPropertyWriter.close();
-
-        String output = mByteArrayOutputStream.toString();
-        String expected = "prop,signature\n"
-                + "|val|,|foo|\n";
-        assertThat(output).isEqualTo(expected);
-    }
-
-    @Test
-    public void testExportPropertiesEscapeQuotes() {
-        String signature = "foo";
-        Map<String, String> annotationProperties = ImmutableMap.of(
-                "prop", "val1 | val2 | val3"
-        );
-        Set<String> parsedFlags = new HashSet<String>();
-        mAnnotationPropertyWriter.consume(signature, annotationProperties, parsedFlags);
-        mAnnotationPropertyWriter.close();
-
-        String output = mByteArrayOutputStream.toString();
-        String expected = "prop,signature\n"
-                + "|val1 || val2 || val3|,|foo|\n";
-        assertThat(output).isEqualTo(expected);
-    }
-}
diff --git a/tools/class2greylist/test/src/com/android/class2greylist/ApiComponentsTest.java b/tools/class2greylist/test/src/com/android/class2greylist/ApiComponentsTest.java
deleted file mode 100644
index e93d1e1..0000000
--- a/tools/class2greylist/test/src/com/android/class2greylist/ApiComponentsTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.assertThrows;
-
-import org.junit.Test;
-
-
-public class ApiComponentsTest extends AnnotationHandlerTestBase {
-
-    @Test
-    public void testGetApiComponentsPackageFromSignature() throws SignatureSyntaxError {
-        ApiComponents api = ApiComponents.fromDexSignature("La/b/C;->foo()V");
-        PackageAndClassName packageAndClassName = api.getPackageAndClassName();
-        assertThat(packageAndClassName.packageName).isEqualTo("a.b");
-    }
-
-    @Test
-    public void testGetApiComponentsFromSignature() throws SignatureSyntaxError {
-        ApiComponents api = ApiComponents.fromDexSignature("La/b/C;->foo(IJLfoo2/bar/Baz;)V");
-        PackageAndClassName packageAndClassName = api.getPackageAndClassName();
-        assertThat(packageAndClassName.className).isEqualTo("C");
-        assertThat(api.getMemberName()).isEqualTo("foo");
-        assertThat(api.getMethodParameterTypes()).isEqualTo("int, long, foo2.bar.Baz");
-    }
-
-    @Test
-    public void testInvalidDexSignatureInvalidClassFormat() throws SignatureSyntaxError {
-        assertThrows(SignatureSyntaxError.class, () -> {
-            ApiComponents.fromDexSignature("a/b/C;->foo()V");
-        });
-        assertThrows(SignatureSyntaxError.class, () -> {
-            ApiComponents.fromDexSignature("La/b/C->foo()V");
-        });
-    }
-
-    @Test
-    public void testInvalidDexSignatureInvalidParameterType() throws SignatureSyntaxError {
-        assertThrows(SignatureSyntaxError.class, () -> {
-            ApiComponents.fromDexSignature("a/b/C;->foo(foo)V");
-        });
-    }
-
-    @Test
-    public void testInvalidDexSignatureInvalidReturnType() throws SignatureSyntaxError {
-        assertThrows(SignatureSyntaxError.class, () -> {
-            ApiComponents.fromDexSignature("a/b/C;->foo()foo");
-        });
-    }
-
-    @Test
-    public void testInvalidDexSignatureMissingReturnType() throws SignatureSyntaxError {
-        assertThrows(SignatureSyntaxError.class, () -> {
-            ApiComponents.fromDexSignature("a/b/C;->foo(I)");
-        });
-    }
-
-    @Test
-    public void testInvalidDexSignatureMissingArrowOrColon() throws SignatureSyntaxError {
-        assertThrows(SignatureSyntaxError.class, () -> {
-            ApiComponents.fromDexSignature("La/b/C;foo()V");
-        });
-    }
-
-    @Test
-    public void testGetApiComponentsFromFieldLink() throws JavadocLinkSyntaxError {
-        ApiComponents api = ApiComponents.fromLinkTag("a.b.C#foo(int, long, foo2.bar.Baz)",
-                "La/b/C;->foo:I");
-        PackageAndClassName packageAndClassName = api.getPackageAndClassName();
-        assertThat(packageAndClassName.packageName).isEqualTo("a.b");
-        assertThat(packageAndClassName.className).isEqualTo("C");
-        assertThat(api.getMemberName()).isEqualTo("foo");
-    }
-
-    @Test
-    public void testGetApiComponentsLinkOnlyClass() throws JavadocLinkSyntaxError {
-        ApiComponents api = ApiComponents.fromLinkTag("b.c.D", "La/b/C;->foo:I");
-        PackageAndClassName packageAndClassName = api.getPackageAndClassName();
-        assertThat(packageAndClassName.packageName).isEqualTo("b.c");
-        assertThat(packageAndClassName.className).isEqualTo("D");
-        assertThat(api.getMethodParameterTypes()).isEqualTo("");
-    }
-
-    @Test
-    public void testGetApiComponentsFromLinkOnlyClassDeducePackage() throws JavadocLinkSyntaxError {
-        ApiComponents api = ApiComponents.fromLinkTag("D", "La/b/C;->foo:I");
-        PackageAndClassName packageAndClassName = api.getPackageAndClassName();
-        assertThat(packageAndClassName.packageName).isEqualTo("a.b");
-        assertThat(packageAndClassName.className).isEqualTo("D");
-        assertThat(api.getMemberName().isEmpty()).isTrue();
-        assertThat(api.getMethodParameterTypes().isEmpty()).isTrue();
-    }
-
-    @Test
-    public void testGetApiComponentsParametersFromMethodLink() throws JavadocLinkSyntaxError {
-        ApiComponents api = ApiComponents.fromLinkTag("a.b.C#foo(int, long, foo2.bar.Baz)",
-                "La/b/C;->foo:I");
-        assertThat(api.getMethodParameterTypes()).isEqualTo("int, long, foo2.bar.Baz");
-    }
-
-    @Test
-    public void testDeduceApiComponentsPackageFromLinkUsingContext() throws JavadocLinkSyntaxError {
-        ApiComponents api = ApiComponents.fromLinkTag("C#foo(int, long, foo2.bar.Baz)",
-                "La/b/C;->foo:I");
-        PackageAndClassName packageAndClassName = api.getPackageAndClassName();
-        assertThat(packageAndClassName.packageName).isEqualTo("a.b");
-    }
-
-    @Test
-    public void testDeduceApiComponentsPackageAndClassFromLinkUsingContext()
-            throws JavadocLinkSyntaxError {
-        ApiComponents api = ApiComponents.fromLinkTag("#foo(int, long, foo2.bar.Baz)",
-                "La/b/C;->foo:I");
-        PackageAndClassName packageAndClassName = api.getPackageAndClassName();
-        assertThat(packageAndClassName.packageName).isEqualTo("a.b");
-        assertThat(packageAndClassName.className).isEqualTo("C");
-    }
-
-    @Test
-    public void testInvalidLinkTagUnclosedParenthesis() throws JavadocLinkSyntaxError {
-        assertThrows(JavadocLinkSyntaxError.class, () -> {
-            ApiComponents.fromLinkTag("a.b.C#foo(int,float", "La/b/C;->foo()V");
-        });
-    }
-
-}
\ No newline at end of file
diff --git a/tools/class2greylist/test/src/com/android/class2greylist/ApiResolverTest.java b/tools/class2greylist/test/src/com/android/class2greylist/ApiResolverTest.java
deleted file mode 100644
index 888a9b5..0000000
--- a/tools/class2greylist/test/src/com/android/class2greylist/ApiResolverTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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
- */
-
-package com.android.class2greylist;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.expectThrows;
-import static org.testng.Assert.assertThrows;
-
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-public class ApiResolverTest extends AnnotationHandlerTestBase {
-    @Test
-    public void testFindPublicAlternativeExactly()
-            throws JavadocLinkSyntaxError, AlternativeNotFoundError,
-            RequiredAlternativeNotSpecifiedError {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>(
-                Arrays.asList("La/b/C;->foo(I)V", "La/b/C;->bar(I)V")));
-        ApiResolver resolver = new ApiResolver(publicApis);
-        resolver.resolvePublicAlternatives("{@link a.b.C#foo(int)}", "Lb/c/D;->bar()V", 1);
-    }
-
-    @Test
-    public void testFindPublicAlternativeDeducedPackageName()
-            throws JavadocLinkSyntaxError, AlternativeNotFoundError,
-            RequiredAlternativeNotSpecifiedError {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>(
-                Arrays.asList("La/b/C;->foo(I)V", "La/b/C;->bar(I)V")));
-        ApiResolver resolver = new ApiResolver(publicApis);
-        resolver.resolvePublicAlternatives("{@link C#foo(int)}", "La/b/D;->bar()V", 1);
-    }
-
-    @Test
-    public void testFindPublicAlternativeDeducedPackageAndClassName()
-            throws JavadocLinkSyntaxError, AlternativeNotFoundError,
-            RequiredAlternativeNotSpecifiedError {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>(
-                Arrays.asList("La/b/C;->foo(I)V", "La/b/C;->bar(I)V")));
-        ApiResolver resolver = new ApiResolver(publicApis);
-        resolver.resolvePublicAlternatives("{@link #foo(int)}", "La/b/C;->bar()V", 1);
-    }
-
-    @Test
-    public void testFindPublicAlternativeDeducedParameterTypes()
-            throws JavadocLinkSyntaxError, AlternativeNotFoundError,
-            RequiredAlternativeNotSpecifiedError {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>(
-                Arrays.asList("La/b/C;->foo(I)V", "La/b/C;->bar(I)V")));
-        ApiResolver resolver = new ApiResolver(publicApis);
-        resolver.resolvePublicAlternatives("{@link #foo}", "La/b/C;->bar()V", 1);
-    }
-
-    @Test
-    public void testFindPublicAlternativeFailDueToMultipleParameterTypes()
-            throws SignatureSyntaxError {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>(
-                Arrays.asList("La/b/C;->foo(I)V", "La/b/C;->bar(I)I", "La/b/C;->foo(II)V")));
-        ApiResolver resolver = new ApiResolver(publicApis);
-        MultipleAlternativesFoundError e = expectThrows(MultipleAlternativesFoundError.class,
-                () -> resolver.resolvePublicAlternatives("{@link #foo}", "La/b/C;->bar()V", 1));
-        assertThat(e.almostMatches).containsExactly(
-                ApiComponents.fromDexSignature("La/b/C;->foo(I)V"),
-                ApiComponents.fromDexSignature("La/b/C;->foo(II)V")
-        );
-    }
-
-    @Test
-    public void testFindPublicAlternativeFailNoAlternative() {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>(
-                Arrays.asList("La/b/C;->bar(I)V")));
-        ApiResolver resolver = new ApiResolver(publicApis);
-        assertThrows(MemberAlternativeNotFoundError.class, ()
-                -> resolver.resolvePublicAlternatives("{@link #foo(int)}", "La/b/C;->bar()V", 1));
-    }
-
-    @Test
-    public void testFindPublicAlternativeFailNoAlternativeNoParameterTypes() {
-
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>(
-                Arrays.asList("La/b/C;->bar(I)V")));
-        ApiResolver resolver = new ApiResolver(publicApis);
-        assertThrows(MemberAlternativeNotFoundError.class,
-                () -> resolver.resolvePublicAlternatives("{@link #foo}", "La/b/C;->bar()V", 1));
-    }
-
-    @Test
-    public void testNoPublicClassAlternatives() {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>());
-        ApiResolver resolver = new ApiResolver(publicApis);
-        expectThrows(NoAlternativesSpecifiedError.class,
-                () -> resolver.resolvePublicAlternatives("Foo", "La/b/C;->bar()V", 1));
-    }
-
-    @Test
-    public void testPublicAlternativesJustPackageAndClassName()
-            throws JavadocLinkSyntaxError, AlternativeNotFoundError,
-            RequiredAlternativeNotSpecifiedError {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>(
-                Arrays.asList("La/b/C;->bar(I)V")));
-        ApiResolver resolver = new ApiResolver(publicApis);
-        resolver.resolvePublicAlternatives("Foo {@link a.b.C}", "Lb/c/D;->bar()V", 1);
-    }
-
-    @Test
-    public void testPublicAlternativesJustClassName()
-            throws JavadocLinkSyntaxError, AlternativeNotFoundError,
-            RequiredAlternativeNotSpecifiedError {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>(
-                Arrays.asList("La/b/C;->bar(I)V")));
-        ApiResolver resolver = new ApiResolver(publicApis);
-        resolver.resolvePublicAlternatives("Foo {@link C}", "La/b/D;->bar()V", 1);
-    }
-
-    @Test
-    public void testNoPublicAlternativesButHasExplanation()
-            throws JavadocLinkSyntaxError, AlternativeNotFoundError,
-            RequiredAlternativeNotSpecifiedError {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>());
-        ApiResolver resolver = new ApiResolver(publicApis);
-        resolver.resolvePublicAlternatives("Foo {@code bar}", "La/b/C;->bar()V", 1);
-    }
-
-    @Test
-    public void testNoPublicAlternativesSpecifiedWithMaxSdk() {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>());
-        ApiResolver resolver = new ApiResolver(publicApis);
-        assertThrows(RequiredAlternativeNotSpecifiedError.class,
-                () -> resolver.resolvePublicAlternatives(null, "La/b/C;->bar()V", 29));
-    }
-
-    @Test
-    public void testNoPublicAlternativesSpecifiedWithMaxLessThanQ()
-            throws JavadocLinkSyntaxError, AlternativeNotFoundError,
-            RequiredAlternativeNotSpecifiedError {
-        Set<String> publicApis = Collections.unmodifiableSet(new HashSet<>());
-        ApiResolver resolver = new ApiResolver(publicApis);
-        resolver.resolvePublicAlternatives(null, "La/b/C;->bar()V", 28);
-    }
-
-}
\ No newline at end of file
diff --git a/tools/class2greylist/test/src/com/android/class2greylist/CovariantReturnTypeHandlerTest.java b/tools/class2greylist/test/src/com/android/class2greylist/CovariantReturnTypeHandlerTest.java
deleted file mode 100644
index 9f924b2..0000000
--- a/tools/class2greylist/test/src/com/android/class2greylist/CovariantReturnTypeHandlerTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.class2greylist;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import static java.util.Collections.emptySet;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import java.io.IOException;
-import java.util.Map;
-
-public class CovariantReturnTypeHandlerTest extends AnnotationHandlerTestBase {
-
-    private static final String ANNOTATION = "Lannotation/Annotation;";
-    private static final String FLAG = "test-flag";
-
-    @Before
-    public void setup() throws IOException {
-        // To keep the test simpler and more concise, we don't use the real
-        // @CovariantReturnType annotation here, but use our own @Annotation.
-        // It doesn't have to match the real annotation, just have the same
-        // property (returnType).
-        mJavac.addSource("annotation.Annotation", Joiner.on('\n').join(
-                "package annotation;",
-                "import static java.lang.annotation.RetentionPolicy.CLASS;",
-                "import java.lang.annotation.Retention;",
-                "@Retention(CLASS)",
-                "public @interface Annotation {",
-                "  Class<?> returnType();",
-                "}"));
-    }
-
-    @Test
-    public void testReturnTypeWhitelisted() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Annotation;",
-                "public class Class {",
-                "  @Annotation(returnType=Integer.class)",
-                "  public String method() {return null;}",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION,
-                        new CovariantReturnTypeHandler(
-                                mConsumer,
-                                ImmutableSet.of("La/b/Class;->method()Ljava/lang/String;"),
-                                FLAG));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-
-        assertNoErrors();
-        verify(mConsumer, times(1)).consume(
-                eq("La/b/Class;->method()Ljava/lang/Integer;"), any(), eq(ImmutableSet.of(FLAG)));
-    }
-
-    @Test
-    public void testAnnotatedMemberNotPublicApi() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Annotation;",
-                "public class Class {",
-                "  @Annotation(returnType=Integer.class)",
-                "  public String method() {return null;}",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION,
-                        new CovariantReturnTypeHandler(
-                                mConsumer,
-                                emptySet(),
-                                FLAG));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-
-        verify(mStatus, atLeastOnce()).error(any(), any());
-    }
-
-    @Test
-    public void testReturnTypeAlreadyWhitelisted() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Annotation;",
-                "public class Class {",
-                "  @Annotation(returnType=Integer.class)",
-                "  public String method() {return null;}",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION,
-                        new CovariantReturnTypeHandler(
-                                mConsumer,
-                                ImmutableSet.of(
-                                        "La/b/Class;->method()Ljava/lang/String;",
-                                        "La/b/Class;->method()Ljava/lang/Integer;"
-                                ),
-                                FLAG));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-
-        verify(mStatus, atLeastOnce()).error(any(), any());
-    }
-
-    @Test
-    public void testAnnotationOnField() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Annotation;",
-                "public class Class {",
-                "  @Annotation(returnType=Integer.class)",
-                "  public String field;",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION,
-                        new CovariantReturnTypeHandler(
-                                mConsumer,
-                                emptySet(),
-                                FLAG));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-
-        verify(mStatus, atLeastOnce()).error(any(), any());
-    }
-}
diff --git a/tools/class2greylist/test/src/com/android/class2greylist/RepeatedAnnotationHandlerTest.java b/tools/class2greylist/test/src/com/android/class2greylist/RepeatedAnnotationHandlerTest.java
deleted file mode 100644
index f2f70ee..0000000
--- a/tools/class2greylist/test/src/com/android/class2greylist/RepeatedAnnotationHandlerTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.class2greylist;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableMap;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import org.apache.bcel.classfile.AnnotationEntry;
-import org.junit.Before;
-import org.junit.Test;
-
-public class RepeatedAnnotationHandlerTest extends AnnotationHandlerTestBase {
-
-    @Before
-    public void setup() {
-        // To keep the test simpler and more concise, we don't use a real annotation here, but use
-        // our own @Annotation and @Annotation.Multi that have the same relationship.
-        mJavac.addSource("annotation.Annotation", Joiner.on('\n').join(
-                "package annotation;",
-                "import static java.lang.annotation.RetentionPolicy.CLASS;",
-                "import java.lang.annotation.Repeatable;",
-                "import java.lang.annotation.Retention;",
-                "@Repeatable(Annotation.Multi.class)",
-                "@Retention(CLASS)",
-                "public @interface Annotation {",
-                "  Class<?> clazz();",
-                "  @Retention(CLASS)",
-                "  @interface Multi {",
-                "    Annotation[] value();",
-                "  }",
-                "}"));
-    }
-
-    @Test
-    public void testRepeated() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Annotation;",
-                "public class Class {",
-                "  @Annotation(clazz=Integer.class)",
-                "  @Annotation(clazz=Long.class)",
-                "  public String method() {return null;}",
-                "}"));
-        mJavac.compile();
-
-        TestAnnotationHandler handler = new TestAnnotationHandler();
-        Map<String, AnnotationHandler> handlerMap =
-            ImmutableMap.of("Lannotation/Annotation$Multi;",
-                new RepeatedAnnotationHandler("Lannotation/Annotation;", handler));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-
-        assertNoErrors();
-        assertThat(handler.getClasses()).containsExactly(
-                "Ljava/lang/Integer;",
-                "Ljava/lang/Long;");
-    }
-
-    private static class TestAnnotationHandler extends AnnotationHandler {
-
-        private final List<String> classes;
-
-        private TestAnnotationHandler() {
-            this.classes = new ArrayList<>();
-        }
-
-        @Override
-        void handleAnnotation(AnnotationEntry annotation,
-            AnnotationContext context) {
-            classes.add(annotation.getElementValuePairs()[0].getValue().stringifyValue());
-        }
-
-        private List<String> getClasses() {
-            return classes;
-        }
-    }
-}
diff --git a/tools/class2greylist/test/src/com/android/class2greylist/UnsupportedAppUsageAnnotationHandlerTest.java b/tools/class2greylist/test/src/com/android/class2greylist/UnsupportedAppUsageAnnotationHandlerTest.java
deleted file mode 100644
index a6d6a16..0000000
--- a/tools/class2greylist/test/src/com/android/class2greylist/UnsupportedAppUsageAnnotationHandlerTest.java
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.class2greylist;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import static java.util.Collections.emptyMap;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Predicate;
-
-public class UnsupportedAppUsageAnnotationHandlerTest extends AnnotationHandlerTestBase {
-
-    private static final String ANNOTATION = "Lannotation/Anno;";
-
-    private static final Map<Integer, String> NULL_SDK_MAP;
-    static {
-        Map<Integer, String> map = new HashMap<>();
-        map.put(null, "flag-null");
-        NULL_SDK_MAP = Collections.unmodifiableMap(map);
-    }
-
-    @Before
-    public void setup() throws IOException {
-        mJavac.addSource("annotation.Anno", Joiner.on('\n').join(
-                "package annotation;",
-                "import static java.lang.annotation.RetentionPolicy.CLASS;",
-                "import java.lang.annotation.Retention;",
-                "import java.lang.annotation.Repeatable;",
-                "@Retention(CLASS)",
-                "@Repeatable(Anno.Container.class)",
-                "public @interface Anno {",
-                "  String expectedSignature() default \"\";",
-                "  int maxTargetSdk() default Integer.MAX_VALUE;",
-                "  String implicitMember() default \"\";",
-                "  @Retention(CLASS)",
-                "  public @interface Container {",
-                "    Anno[] value();",
-                "  }",
-                "}"));
-    }
-
-    private UnsupportedAppUsageAnnotationHandler createGreylistHandler(
-            Predicate<UnsupportedAppUsageAnnotationHandler.ClassMember> greylistFilter,
-            Map<Integer, String> validMaxTargetSdkValues) {
-        return new UnsupportedAppUsageAnnotationHandler(
-                mStatus, mConsumer, greylistFilter, validMaxTargetSdkValues);
-    }
-
-    @Test
-    public void testGreylistMethod() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  @Anno",
-                "  public void method() {}",
-                "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus,
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        verify(mConsumer, times(1)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getValue()).isEqualTo("La/b/Class;->method()V");
-    }
-
-    @Test
-    public void testGreylistConstructor() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  @Anno",
-                "  public Class() {}",
-                "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus,
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        verify(mConsumer, times(1)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getValue()).isEqualTo("La/b/Class;-><init>()V");
-    }
-
-    @Test
-    public void testGreylistField() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  @Anno",
-                "  public int i;",
-                "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus,
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        verify(mConsumer, times(1)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getValue()).isEqualTo("La/b/Class;->i:I");
-    }
-
-    @Test
-    public void testGreylistImplicit() throws IOException {
-        mJavac.addSource("a.b.EnumClass", Joiner.on('\n').join(
-            "package a.b;",
-            "import annotation.Anno;",
-            "@Anno(implicitMember=\"values()[La/b/EnumClass;\")",
-            "public enum EnumClass {",
-            "  VALUE",
-            "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.EnumClass"), mStatus,
-            ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        verify(mConsumer, times(1)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getValue()).isEqualTo("La/b/EnumClass;->values()[La/b/EnumClass;");
-    }
-
-    @Test
-    public void testGreylistImplicit_Invalid_MissingOnClass() throws IOException {
-        mJavac.addSource("a.b.EnumClass", Joiner.on('\n').join(
-            "package a.b;",
-            "import annotation.Anno;",
-            "@Anno",
-            "public enum EnumClass {",
-            "  VALUE",
-            "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.EnumClass"), mStatus,
-            ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        ArgumentCaptor<String> format = ArgumentCaptor.forClass(String.class);
-        verify(mStatus, times(1)).error(format.capture(), any());
-        // Ensure that the correct error is reported.
-        assertThat(format.getValue())
-            .contains("Missing property implicitMember on annotation on class");
-    }
-
-    @Test
-    public void testGreylistImplicit_Invalid_PresentOnMember() throws IOException {
-        mJavac.addSource("a.b.EnumClass", Joiner.on('\n').join(
-            "package a.b;",
-            "import annotation.Anno;",
-            "public enum EnumClass {",
-            "  @Anno(implicitMember=\"values()[La/b/EnumClass;\")",
-            "  VALUE",
-            "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.EnumClass"), mStatus,
-            ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        ArgumentCaptor<String> format = ArgumentCaptor.forClass(String.class);
-        verify(mStatus, times(1)).error(format.capture(), any());
-        assertThat(format.getValue())
-            .contains("Expected annotation with an implicitMember property to be on a class");
-    }
-
-    @Test
-    public void testGreylistMethodExpectedSignature() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  @Anno(expectedSignature=\"La/b/Class;->method()V\")",
-                "  public void method() {}",
-                "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus,
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        verify(mConsumer, times(1)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getValue()).isEqualTo("La/b/Class;->method()V");
-    }
-
-    @Test
-    public void testGreylistMethodExpectedSignatureWrong() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  @Anno(expectedSignature=\"La/b/Class;->nomethod()V\")",
-                "  public void method() {}",
-                "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus,
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        verify(mStatus, times(1)).error(any(), any());
-    }
-
-    @Test
-    public void testGreylistInnerClassMethod() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  public class Inner {",
-                "    @Anno",
-                "    public void method() {}",
-                "  }",
-                "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class$Inner"), mStatus,
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        verify(mConsumer, times(1)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getValue()).isEqualTo("La/b/Class$Inner;->method()V");
-    }
-
-    @Test
-    public void testMethodNotGreylisted() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "public class Class {",
-                "  public void method() {}",
-                "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus,
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        assertNoErrors();
-        verify(mConsumer, never()).consume(any(String.class), any(), any());
-    }
-
-    @Test
-    public void testMethodArgGenerics() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class<T extends String> {",
-                "  @Anno(expectedSignature=\"La/b/Class;->method(Ljava/lang/String;)V\")",
-                "  public void method(T arg) {}",
-                "}"));
-        mJavac.compile();
-
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus,
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP))
-        ).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        verify(mConsumer, times(1)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getValue()).isEqualTo("La/b/Class;->method(Ljava/lang/String;)V");
-    }
-
-    @Test
-    public void testOverrideMethodWithBridge() throws IOException {
-        mJavac.addSource("a.b.Base", Joiner.on('\n').join(
-                "package a.b;",
-                "abstract class Base<T> {",
-                "  protected abstract void method(T arg);",
-                "}"));
-
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class<T extends String> extends Base<T> {",
-                "  @Override",
-                "  @Anno(expectedSignature=\"La/b/Class;->method(Ljava/lang/String;)V\")",
-                "  public void method(T arg) {}",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Base"), mStatus, handlerMap).visit();
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        // A bridge method is generated for the above, so we expect 2 greylist entries.
-        verify(mConsumer, times(2)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getAllValues()).containsExactly(
-                "La/b/Class;->method(Ljava/lang/Object;)V",
-                "La/b/Class;->method(Ljava/lang/String;)V");
-    }
-
-    @Test
-    public void testOverridePublicMethodWithBridge() throws IOException {
-        mJavac.addSource("a.b.Base", Joiner.on('\n').join(
-                "package a.b;",
-                "public abstract class Base<T> {",
-                "  public void method(T arg) {}",
-                "}"));
-
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class<T extends String> extends Base<T> {",
-                "  @Override",
-                "  @Anno(expectedSignature=\"La/b/Class;->method(Ljava/lang/String;)V\")",
-                "  public void method(T arg) {}",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Base"), mStatus, handlerMap).visit();
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        // A bridge method is generated for the above, so we expect 2 greylist entries.
-        verify(mConsumer, times(2)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getAllValues()).containsExactly(
-                "La/b/Class;->method(Ljava/lang/Object;)V",
-                "La/b/Class;->method(Ljava/lang/String;)V");
-    }
-
-    @Test
-    public void testBridgeMethodsFromInterface() throws IOException {
-        mJavac.addSource("a.b.Interface", Joiner.on('\n').join(
-                "package a.b;",
-                "public interface Interface {",
-                "  public void method(Object arg);",
-                "}"));
-
-        mJavac.addSource("a.b.Base", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "class Base {",
-                "  @Anno(expectedSignature=\"La/b/Base;->method(Ljava/lang/Object;)V\")",
-                "  public void method(Object arg) {}",
-                "}"));
-
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "public class Class extends Base implements Interface {",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Interface"), mStatus, handlerMap)
-                .visit();
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Base"), mStatus, handlerMap).visit();
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        // A bridge method is generated for the above, so we expect 2 greylist entries.
-        verify(mConsumer, times(2)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getAllValues()).containsExactly(
-                "La/b/Class;->method(Ljava/lang/Object;)V",
-                "La/b/Base;->method(Ljava/lang/Object;)V");
-    }
-
-    @Test
-    public void testPublicBridgeExcluded() throws IOException {
-        mJavac.addSource("a.b.Base", Joiner.on('\n').join(
-                "package a.b;",
-                "public abstract class Base<T> {",
-                "  public void method(T arg) {}",
-                "}"));
-
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class<T extends String> extends Base<T> {",
-                "  @Override",
-                "  @Anno",
-                "  public void method(T arg) {}",
-                "}"));
-        mJavac.compile();
-
-        Set<String> publicApis = Sets.newHashSet(
-                "La/b/Base;->method(Ljava/lang/Object;)V",
-                "La/b/Class;->method(Ljava/lang/Object;)V");
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION,
-                        new UnsupportedAppUsageAnnotationHandler(
-                                mStatus,
-                                mConsumer,
-                                publicApis,
-                                NULL_SDK_MAP));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Base"), mStatus, handlerMap).visit();
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        // The bridge method generated for the above, is a public API so should be excluded
-        verify(mConsumer, times(1)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getValue()).isEqualTo("La/b/Class;->method(Ljava/lang/String;)V");
-    }
-
-    @Test
-    public void testVolatileField() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  @Anno(expectedSignature=\"La/b/Class;->field:I\")",
-                "  public volatile int field;",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(
-                        member -> !member.isBridgeMethod, // exclude bridge methods
-                        NULL_SDK_MAP));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-        assertNoErrors();
-        ArgumentCaptor<String> greylist = ArgumentCaptor.forClass(String.class);
-        verify(mConsumer, times(1)).consume(greylist.capture(), any(), any());
-        assertThat(greylist.getValue()).isEqualTo("La/b/Class;->field:I");
-    }
-
-    @Test
-    public void testVolatileFieldWrongSignature() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  @Anno(expectedSignature=\"La/b/Class;->wrong:I\")",
-                "  public volatile int field;",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(x -> true, NULL_SDK_MAP));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-        verify(mStatus, times(1)).error(any(), any());
-    }
-
-    @Test
-    public void testMethodMaxTargetSdk() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  @Anno(maxTargetSdk=1)",
-                "  public int field;",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(
-                        x -> true,
-                        ImmutableMap.of(1, "flag1")));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-        assertNoErrors();
-        verify(mConsumer, times(1)).consume(any(), any(), eq(ImmutableSet.of("flag1")));
-    }
-
-    @Test
-    public void testMethodNoMaxTargetSdk() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  @Anno",
-                "  public int field;",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(
-                        x -> true,
-                        NULL_SDK_MAP));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-        assertNoErrors();
-        verify(mConsumer, times(1)).consume(any(), any(), eq(ImmutableSet.of("flag-null")));
-    }
-
-    @Test
-    public void testMethodMaxTargetSdkOutOfRange() throws IOException {
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno;",
-                "public class Class {",
-                "  @Anno(maxTargetSdk=2)",
-                "  public int field;",
-                "}"));
-        mJavac.compile();
-
-        Map<String, AnnotationHandler> handlerMap =
-                ImmutableMap.of(ANNOTATION, createGreylistHandler(
-                        x -> true,
-                        NULL_SDK_MAP));
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
-        verify(mStatus, times(1)).error(any(), any());
-    }
-
-    @Test
-    public void testAnnotationPropertiesIntoMap() throws IOException {
-        mJavac.addSource("annotation.Anno2", Joiner.on('\n').join(
-                "package annotation;",
-                "import static java.lang.annotation.RetentionPolicy.CLASS;",
-                "import java.lang.annotation.Retention;",
-                "@Retention(CLASS)",
-                "public @interface Anno2 {",
-                "  String expectedSignature() default \"\";",
-                "  int maxTargetSdk() default Integer.MAX_VALUE;",
-                "  long trackingBug() default 0;",
-                "}"));
-        mJavac.addSource("a.b.Class", Joiner.on('\n').join(
-                "package a.b;",
-                "import annotation.Anno2;",
-                "public class Class {",
-                "  @Anno2(maxTargetSdk=2, trackingBug=123456789)",
-                "  public int field;",
-                "}"));
-        mJavac.compile();
-        new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus,
-                ImmutableMap.of("Lannotation/Anno2;", createGreylistHandler(x -> true,
-                        ImmutableMap.of(2, "flag2")))
-        ).visit();
-
-        assertNoErrors();
-        ArgumentCaptor<Map<String, String>> properties = ArgumentCaptor.forClass(Map.class);
-        verify(mConsumer, times(1)).consume(any(), properties.capture(), any());
-        assertThat(properties.getValue()).containsExactly(
-                "maxTargetSdk", "2",
-                "trackingBug", "123456789");
-    }
-
-}
diff --git a/tools/compile-jar.py b/tools/compile-jar.py
new file mode 100755
index 0000000..56a07d5
--- /dev/null
+++ b/tools/compile-jar.py
@@ -0,0 +1,257 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2021 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.
+
+#
+# This script runs dex2oat on the host to compile a provided JAR or APK.
+#
+
+import argparse
+import itertools
+import shlex
+import subprocess
+import os
+import os.path
+
+def run_print(lst):
+  return " ".join(map(shlex.quote, lst))
+
+
+def parse_args():
+  parser = argparse.ArgumentParser(
+      description="compile dex or jar files",
+      epilog="Unrecognized options are passed on to dex2oat unmodified.")
+  parser.add_argument(
+      "--dex2oat",
+      action="store",
+      default=os.path.expandvars("$ANDROID_HOST_OUT/bin/dex2oatd64"),
+      help="selects the dex2oat to use.")
+  parser.add_argument(
+      "--debug",
+      action="store_true",
+      default=False,
+      help="launches dex2oatd with lldb-server g :5039. Connect using vscode or remote lldb"
+  )
+  parser.add_argument(
+      "--profman",
+      action="store",
+      default=os.path.expandvars("$ANDROID_HOST_OUT/bin/profmand"),
+      help="selects the profman to use.")
+  parser.add_argument(
+      "--debug-profman",
+      action="store_true",
+      default=False,
+      help="launches profman with lldb-server g :5039. Connect using vscode or remote lldb"
+  )
+  profs = parser.add_mutually_exclusive_group()
+  profs.add_argument(
+      "--profile-file",
+      action="store",
+      help="Use this profile file. Probably want to pass --compiler-filter=speed-profile with this."
+  )
+  profs.add_argument(
+      "--profile-line",
+      action="append",
+      default=[],
+      help="functions to add to a profile. Probably want to pass --compiler-filter=speed-profile with this. All functions are marked as 'hot'. Use --profile-file for more control."
+  )
+  parser.add_argument(
+      "--add-bcp",
+      action="append",
+      default=[],
+      nargs=2,
+      metavar=("BCP_FILE", "BCP_LOCATION"),
+      help="File and location to add to the boot-class-path. Note no deduplication is attempted."
+  )
+  parser.add_argument(
+      "--arch",
+      action="store",
+      choices=["arm", "arm64", "x86", "x86_64", "host64", "host32"],
+      default="host64",
+      help="architecture to compile for. Defaults to host64")
+  parser.add_argument(
+      "--odex-file",
+      action="store",
+      help="odex file to write. File discarded if not set",
+      default=None)
+  parser.add_argument(
+      "--save-profile",
+      action="store",
+      type=argparse.FileType("w"),
+      default=None,
+      help="File path to store the profile to")
+  parser.add_argument(
+      "dex_files", help="dex/jar files", nargs="+", metavar="DEX")
+  return parser.parse_known_args()
+
+
+def get_bcp_runtime_args(additions, image, arch):
+  add_files = map(lambda a: a[0], additions)
+  add_locs = map(lambda a: a[1], additions)
+  if arch != "host32" and arch != "host64":
+    args = [
+        "art/tools/host_bcp.sh",
+        os.path.expandvars(
+            "${{OUT}}/system/framework/oat/{}/services.odex".format(arch)),
+        "--use-first-dir"
+    ]
+    print("Running: {}".format(run_print(args)))
+    print("=START=======================================")
+    res = subprocess.run(args, capture_output=True, text=True)
+    print("=END=========================================")
+    if res.returncode != 0:
+      print("Falling back to com.android.art BCP")
+      args = [
+          "art/tools/host_bcp.sh",
+          os.path.expandvars(
+              "${{OUT}}/apex/com.android.art.debug/javalib/{}/boot.oat".format(arch)),
+          "--use-first-dir"
+      ]
+      print("Running: {}".format(run_print(args)))
+      print("=START=======================================")
+      res = subprocess.run(args, capture_output=True, text=True)
+      print("=END=========================================")
+      res.check_returncode()
+    segments = res.stdout.split()
+    def extend_bcp(segment: str):
+      # TODO We should make the bcp have absolute paths.
+      if segment.startswith("-Xbootclasspath:"):
+        return ":".join(itertools.chain((segment,), add_files))
+      elif segment.startswith("-Xbootclasspath-locations:"):
+        return ":".join(itertools.chain((segment,), add_locs))
+      else:
+        return segment
+    return list(map(extend_bcp, segments))
+  else:
+    # Host we just use the bcp locations for both.
+    res = open(
+        os.path.expandvars(
+            "$ANDROID_HOST_OUT/apex/art_boot_images/javalib/{}/boot.oat".format(
+                "x86" if arch == "host32" else "x86_64")), "rb").read()
+    bcp_tag = b"bootclasspath\0"
+    bcp_start = res.find(bcp_tag) + len(bcp_tag)
+    bcp = res[bcp_start:bcp_start + res[bcp_start:].find(b"\0")]
+    img_bcp = bcp.decode()
+    # TODO We should make the str_bcp have absolute paths.
+    str_bcp = ":".join(itertools.chain((img_bcp,), add_files))
+    str_bcp_loc = ":".join(itertools.chain((img_bcp,), add_locs))
+    return [
+        "--runtime-arg", "-Xbootclasspath:{}".format(str_bcp),
+        "--runtime-arg", "-Xbootclasspath-locations:{}".format(str_bcp_loc)
+    ]
+
+
+def fdfile(fd):
+  return "/proc/{}/fd/{}".format(os.getpid(), fd)
+
+
+def get_profile_args(args, location_base):
+  """Handle all the profile file options."""
+  if args.profile_file is None and len(args.profile_line) == 0:
+    return []
+  if args.profile_file:
+    with open(args.profile_file, "rb") as prof:
+      prof_magic = prof.read(4)
+      if prof_magic == b'pro\0':
+        # Looks like the profile-file is a binary profile. Just use it directly
+        return ['--profile-file={}'.format(args.profile_file)]
+  if args.debug_profman:
+    profman_args = ["lldb-server", "g", ":5039", "--", args.profman]
+  else:
+    profman_args = [args.profman]
+  if args.save_profile:
+    prof_out_fd = args.save_profile.fileno()
+    os.set_inheritable(prof_out_fd, True)
+  else:
+    prof_out_fd = os.memfd_create("reference_prof", flags=0)
+  if args.debug_profman:
+    profman_args.append("--reference-profile-file={}".format(
+        fdfile(prof_out_fd)))
+  else:
+    profman_args.append("--reference-profile-file-fd={}".format(prof_out_fd))
+  if args.profile_file:
+    profman_args.append("--create-profile-from={}".format(args.profile_file))
+  else:
+    prof_in_fd = os.memfd_create("input_prof", flags=0)
+    # Why on earth does fdopen take control of the fd and not mention it in the docs.
+    with os.fdopen(os.dup(prof_in_fd), "w") as prof_in:
+      for l in args.profile_line:
+        print(l, file=prof_in)
+    profman_args.append("--create-profile-from={}".format(fdfile(prof_in_fd)))
+  for f in args.dex_files:
+    profman_args.append("--apk={}".format(f))
+    profman_args.append("--dex-location={}".format(
+        os.path.join(location_base, os.path.basename(f))))
+  print("Running: {}".format(run_print(profman_args)))
+  print("=START=======================================")
+  subprocess.run(profman_args, close_fds=False).check_returncode()
+  print("=END=========================================")
+  if args.debug:
+    return ["--profile-file={}".format(fdfile(prof_out_fd))]
+  else:
+    return ["--profile-file={}".format(fdfile(prof_out_fd))]
+
+
+def main():
+  args, extra = parse_args()
+  if args.arch == "host32" or args.arch == "host64":
+    location_base = os.path.expandvars("${ANDROID_HOST_OUT}/framework/")
+    real_arch = "x86" if args.arch == "host32" else "x86_64"
+    boot_image = os.path.expandvars(
+        "$ANDROID_HOST_OUT/apex/art_boot_images/javalib/boot.art")
+    android_root = os.path.expandvars("$ANDROID_HOST_OUT")
+    for f in args.dex_files:
+      extra.append("--dex-location={}".format(
+          os.path.join(location_base, os.path.basename(f))))
+      extra.append("--dex-file={}".format(f))
+  else:
+    location_base = "/system/framework"
+    real_arch = args.arch
+    boot_image = os.path.expandvars(":".join([
+        "${OUT}/apex/art_boot_images/javalib/boot.art",
+        "${OUT}/system/framework/boot-framework.art"
+    ]))
+    android_root = os.path.expandvars("$OUT/system")
+    for f in args.dex_files:
+      extra.append("--dex-location={}".format(
+          os.path.join(location_base, os.path.basename(f))))
+      extra.append("--dex-file={}".format(f))
+  extra += get_bcp_runtime_args(args.add_bcp, boot_image, args.arch)
+  extra += get_profile_args(args, location_base)
+  extra.append("--instruction-set={}".format(real_arch))
+  extra.append("--boot-image={}".format(boot_image))
+  extra.append("--android-root={}".format(android_root))
+  extra += ["--runtime-arg", "-Xms64m", "--runtime-arg", "-Xmx512m"]
+  if args.odex_file is not None:
+    extra.append("--oat-file={}".format(args.odex_file))
+  else:
+    if args.debug:
+      raise Exception("Debug requires a real output file. :(")
+    extra.append("--oat-fd={}".format(os.memfd_create("odex_fd", flags=0)))
+    extra.append("--oat-location={}".format("/tmp/odex_fd.odex"))
+    extra.append("--output-vdex-fd={}".format(
+        os.memfd_create("vdex_fd", flags=0)))
+  pre_args = []
+  if args.debug:
+    pre_args = ["lldb-server", "g", ":5039", "--"]
+  pre_args.append(args.dex2oat)
+  print("Running: {}".format(run_print(pre_args + extra)))
+  print("=START=======================================")
+  subprocess.run(pre_args + extra, close_fds=False).check_returncode()
+  print("=END=========================================")
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/compile-jar.sh b/tools/compile-jar.sh
index 5024ccc..5a65667 100755
--- a/tools/compile-jar.sh
+++ b/tools/compile-jar.sh
@@ -15,7 +15,9 @@
 # limitations under the License.
 
 #
-# This script creates a boot image profile based on input profiles.
+# This script runs dex2oat on the host to compile a provided JAR or APK.
+#
+# This is a wrapper around the more powerful compile-jar.py script
 #
 
 if [[ "$#" -lt 1 ]]; then
@@ -24,6 +26,7 @@
   exit 1
 fi
 
+EXTRA_ARGS=
 FILE=$1
 shift
 OUTPUT=$1
@@ -31,11 +34,4 @@
 ISA=$1
 shift
 
-dex2oat \
-    --runtime-arg -Xms64m --runtime-arg -Xmx512m \
-    --boot-image=${OUT}/apex/com.android.art/javalib/boot.art:${OUT}/system/framework/boot-framework.art \
-    $(${ANDROID_BUILD_TOP}/art/tools/host_bcp.sh ${OUT}/system/framework/oat/${ISA}/services.odex --use-first-dir) \
-    --dex-file=${FILE} --dex-location=/system/framework/${FILE} \
-    --oat-file=${OUTPUT} \
-    --android-root=${OUT}/system --instruction-set=$ISA \
-    $@
+$ANDROID_BUILD_TOP/art/tools/compile-jar.py --arch=$ISA --odex-file=$OUTPUT $FILE $@
diff --git a/tools/cpp-define-generator/Android.bp b/tools/cpp-define-generator/Android.bp
index 701735f..a436430 100644
--- a/tools/cpp-define-generator/Android.bp
+++ b/tools/cpp-define-generator/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // This produces human-readable asm_defines.s with the embedded compile-time constants.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_object {
     name: "asm_defines.s",
     host_supported: true,
@@ -25,21 +34,49 @@
     ],
     header_libs: [
         "art_libartbase_headers", // For base/bit_utils.h
+        "jni_headers",
         "libart_runtime_headers_ndk",
         "libdexfile_all_headers", // For dex/modifiers.h
     ],
+    target: {
+        android: {
+            header_libs: ["libc_headers"], // TODO(b/153662223): Clean this up.
+        },
+        linux_bionic: {
+            header_libs: ["libc_headers"], // TODO(b/153662223): Clean this up.
+        },
+    },
     // Produce text file rather than binary.
     cflags: ["-S"],
     srcs: ["asm_defines.cc"],
     apex_available: [
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
+    ],
+}
+
+soong_config_module_type_import {
+    from: "art/build/SoongConfig.bp",
+    module_types: [
+        "art_module_cc_genrule",
     ],
 }
 
 // This extracts the compile-time constants from asm_defines.s and creates the header.
-cc_genrule {
+art_module_cc_genrule {
     name: "cpp-define-generator-asm-support",
+
+    // :asm_defines.s is only available when building ART from source, so do the
+    // same here.
+    // TODO(b/172480617): Clean up when sources are gone from the platform tree
+    // and we no longer need to support sources present when prebuilts are used.
+    enabled: false,
+    soong_config_variables: {
+        source_build: {
+            enabled: true,
+        },
+    },
+
     host_supported: true,
     device_supported: true,
     srcs: [":asm_defines.s"],
@@ -50,11 +87,18 @@
         darwin: {
             enabled: false,
         },
+        windows: {
+            // When the module is enabled globally in the soong_config_variables
+            // stanza above, it gets enabled on windows too. Hence we need to
+            // disable it explicitly.
+            // TODO(b/172480617): Clean up with that.
+            enabled: false,
+        },
     },
 
     apex_available: [
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
     ],
 }
 
@@ -64,9 +108,10 @@
     export_include_dirs: ["."],
 
     apex_available: [
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
     ],
+    min_sdk_version: "S",
 }
 
 python_binary_host {
diff --git a/tools/cpp-define-generator/art_method.def b/tools/cpp-define-generator/art_method.def
index 75fbab0..a73bbed 100644
--- a/tools/cpp-define-generator/art_method.def
+++ b/tools/cpp-define-generator/art_method.def
@@ -16,18 +16,35 @@
 
 #if ASM_DEFINE_INCLUDE_DEPENDENCIES
 #include "art_method.h"
+#include "imtable.h"
 #endif
 
 ASM_DEFINE(ART_METHOD_ACCESS_FLAGS_OFFSET,
            art::ArtMethod::AccessFlagsOffset().Int32Value())
 ASM_DEFINE(ART_METHOD_IS_STATIC_FLAG,
            art::kAccStatic)
+ASM_DEFINE(ART_METHOD_IS_STATIC_FLAG_BIT,
+           art::MostSignificantBit(art::kAccStatic))
+ASM_DEFINE(ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG,
+           art::kAccNterpInvokeFastPathFlag)
+ASM_DEFINE(ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG_BIT,
+           art::MostSignificantBit(art::kAccNterpInvokeFastPathFlag))
+ASM_DEFINE(ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG,
+           art::kAccNterpEntryPointFastPathFlag)
+ASM_DEFINE(ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG_BIT,
+           art::MostSignificantBit(art::kAccNterpEntryPointFastPathFlag))
+ASM_DEFINE(ART_METHOD_IMT_MASK,
+           art::ImTable::kSizeTruncToPowerOfTwo - 1)
 ASM_DEFINE(ART_METHOD_DECLARING_CLASS_OFFSET,
            art::ArtMethod::DeclaringClassOffset().Int32Value())
 ASM_DEFINE(ART_METHOD_JNI_OFFSET_32,
            art::ArtMethod::EntryPointFromJniOffset(art::PointerSize::k32).Int32Value())
 ASM_DEFINE(ART_METHOD_JNI_OFFSET_64,
            art::ArtMethod::EntryPointFromJniOffset(art::PointerSize::k64).Int32Value())
+ASM_DEFINE(ART_METHOD_DATA_OFFSET_32,
+           art::ArtMethod::DataOffset(art::PointerSize::k32).Int32Value())
+ASM_DEFINE(ART_METHOD_DATA_OFFSET_64,
+           art::ArtMethod::DataOffset(art::PointerSize::k64).Int32Value())
 ASM_DEFINE(ART_METHOD_QUICK_CODE_OFFSET_32,
            art::ArtMethod::EntryPointFromQuickCompiledCodeOffset(art::PointerSize::k32).Int32Value())
 ASM_DEFINE(ART_METHOD_QUICK_CODE_OFFSET_64,
diff --git a/tools/cpp-define-generator/asm_defines.def b/tools/cpp-define-generator/asm_defines.def
index a64676f..fb011a2 100644
--- a/tools/cpp-define-generator/asm_defines.def
+++ b/tools/cpp-define-generator/asm_defines.def
@@ -25,7 +25,6 @@
 #include "lockword.def"
 #include "mirror_array.def"
 #include "mirror_class.def"
-#include "mirror_dex_cache.def"
 #include "mirror_object.def"
 #include "mirror_string.def"
 #include "osr.def"
diff --git a/tools/cpp-define-generator/code_item.def b/tools/cpp-define-generator/code_item.def
index 01b0e85..24d62a8 100644
--- a/tools/cpp-define-generator/code_item.def
+++ b/tools/cpp-define-generator/code_item.def
@@ -16,6 +16,7 @@
 
 #if ASM_DEFINE_INCLUDE_DEPENDENCIES
 #include "dex/standard_dex_file.h"
+#include "dex/compact_dex_file.h"
 #endif
 
 ASM_DEFINE(CODE_ITEM_REGISTERS_SIZE_OFFSET,
@@ -26,3 +27,37 @@
            art::StandardDexFile::CodeItem::OutsSizeOffset())
 ASM_DEFINE(CODE_ITEM_INSNS_OFFSET,
            art::StandardDexFile::CodeItem::InsnsOffset())
+
+ASM_DEFINE(COMPACT_CODE_ITEM_FIELDS_OFFSET,
+           art::CompactDexFile::CodeItem::FieldsOffset())
+ASM_DEFINE(COMPACT_CODE_ITEM_FLAGS_OFFSET,
+           art::CompactDexFile::CodeItem::InsnsCountAndFlagsOffset())
+ASM_DEFINE(COMPACT_CODE_ITEM_INSNS_OFFSET,
+           art::CompactDexFile::CodeItem::InsnsOffset())
+
+ASM_DEFINE(COMPACT_CODE_ITEM_REGISTERS_INS_OUTS_FLAGS,
+           art::CompactDexFile::CodeItem::kFlagPreHeaderRegistersSize |
+           art::CompactDexFile::CodeItem::kFlagPreHeaderInsSize |
+           art::CompactDexFile::CodeItem::kFlagPreHeaderOutsSize)
+ASM_DEFINE(COMPACT_CODE_ITEM_REGISTERS_FLAG,
+           art::CompactDexFile::CodeItem::kFlagPreHeaderRegistersSize)
+ASM_DEFINE(COMPACT_CODE_ITEM_INS_FLAG,
+           art::CompactDexFile::CodeItem::kFlagPreHeaderInsSize)
+ASM_DEFINE(COMPACT_CODE_ITEM_OUTS_FLAG,
+           art::CompactDexFile::CodeItem::kFlagPreHeaderOutsSize)
+ASM_DEFINE(COMPACT_CODE_ITEM_INSNS_FLAG,
+           art::CompactDexFile::CodeItem::kFlagPreHeaderInsnsSize)
+ASM_DEFINE(COMPACT_CODE_ITEM_REGISTERS_BIT,
+           art::CompactDexFile::CodeItem::kBitPreHeaderRegistersSize)
+ASM_DEFINE(COMPACT_CODE_ITEM_INS_BIT,
+           art::CompactDexFile::CodeItem::kBitPreHeaderInsSize)
+ASM_DEFINE(COMPACT_CODE_ITEM_OUTS_BIT,
+           art::CompactDexFile::CodeItem::kBitPreHeaderOutsSize)
+ASM_DEFINE(COMPACT_CODE_ITEM_INSNS_BIT,
+           art::CompactDexFile::CodeItem::kBitPreHeaderInsnsSize)
+ASM_DEFINE(COMPACT_CODE_ITEM_REGISTERS_SIZE_SHIFT,
+           art::CompactDexFile::CodeItem::kRegistersSizeShift)
+ASM_DEFINE(COMPACT_CODE_ITEM_INS_SIZE_SHIFT,
+           art::CompactDexFile::CodeItem::kInsSizeShift)
+ASM_DEFINE(COMPACT_CODE_ITEM_OUTS_SIZE_SHIFT,
+           art::CompactDexFile::CodeItem::kOutsSizeShift)
diff --git a/tools/cpp-define-generator/globals.def b/tools/cpp-define-generator/globals.def
index 6c9b2b0..50f9b33 100644
--- a/tools/cpp-define-generator/globals.def
+++ b/tools/cpp-define-generator/globals.def
@@ -23,6 +23,7 @@
 #include "gc/accounting/card_table.h"
 #include "gc/heap.h"
 #include "interpreter/mterp/mterp.h"
+#include "interpreter/mterp/nterp.h"
 #include "jit/jit.h"
 #include "mirror/object.h"
 #include "mirror/object_reference.h"
@@ -30,6 +31,10 @@
 #include "stack.h"
 #endif
 
+ASM_DEFINE(ACCESS_FLAGS_METHOD_IS_NATIVE,
+           art::kAccNative)
+ASM_DEFINE(ACCESS_FLAGS_METHOD_IS_NATIVE_BIT,
+           art::MostSignificantBit(art::kAccNative))
 ASM_DEFINE(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE,
            art::kAccFastNative)
 ASM_DEFINE(ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE,
@@ -76,3 +81,7 @@
            std::memory_order_relaxed)
 ASM_DEFINE(STACK_OVERFLOW_RESERVED_BYTES,
            GetStackOverflowReservedBytes(art::kRuntimeISA))
+ASM_DEFINE(NTERP_HOTNESS_MASK,
+           art::interpreter::kNterpHotnessMask)
+ASM_DEFINE(NTERP_HOTNESS_BITS,
+           art::POPCOUNT(art::interpreter::kNterpHotnessMask))
diff --git a/tools/cpp-define-generator/make_header.py b/tools/cpp-define-generator/make_header.py
index f3657b1..3ea0d9a 100755
--- a/tools/cpp-define-generator/make_header.py
+++ b/tools/cpp-define-generator/make_header.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2018 The Android Open Source Project
 #
diff --git a/tools/cpp-define-generator/make_header_test.py b/tools/cpp-define-generator/make_header_test.py
index a484285..4ce59d2 100755
--- a/tools/cpp-define-generator/make_header_test.py
+++ b/tools/cpp-define-generator/make_header_test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2018 The Android Open Source Project
 #
diff --git a/tools/cpp-define-generator/mirror_dex_cache.def b/tools/cpp-define-generator/mirror_dex_cache.def
deleted file mode 100644
index 5272e86..0000000
--- a/tools/cpp-define-generator/mirror_dex_cache.def
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.
- */
-
-#if ASM_DEFINE_INCLUDE_DEPENDENCIES
-#include "mirror/dex_cache.h"
-#endif
-
-ASM_DEFINE(METHOD_DEX_CACHE_SIZE_MINUS_ONE,
-           art::mirror::DexCache::kDexCacheMethodCacheSize - 1)
-ASM_DEFINE(MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET,
-           art::mirror::DexCache::ResolvedMethodsOffset().Int32Value())
-ASM_DEFINE(STRING_DEX_CACHE_ELEMENT_SIZE,
-           sizeof(art::mirror::StringDexCachePair))
-ASM_DEFINE(STRING_DEX_CACHE_ELEMENT_SIZE_SHIFT,
-           art::WhichPowerOf2(sizeof(art::mirror::StringDexCachePair)))
-ASM_DEFINE(STRING_DEX_CACHE_HASH_BITS,
-           art::LeastSignificantBit(art::mirror::DexCache::kDexCacheStringCacheSize))
-ASM_DEFINE(STRING_DEX_CACHE_SIZE_MINUS_ONE,
-           art::mirror::DexCache::kDexCacheStringCacheSize - 1)
-ASM_DEFINE(METHOD_DEX_CACHE_HASH_BITS,
-           art::LeastSignificantBit(art::mirror::DexCache::kDexCacheMethodCacheSize))
diff --git a/tools/create_minidebuginfo/Android.bp b/tools/create_minidebuginfo/Android.bp
new file mode 100644
index 0000000..95ac702
--- /dev/null
+++ b/tools/create_minidebuginfo/Android.bp
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2021 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.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+art_cc_binary {
+    name: "create_minidebuginfo",
+    defaults: [
+        "art_debug_defaults",
+        "art_defaults",
+    ],
+    host_supported: true,
+    device_supported: false,
+    srcs: [
+        "create_minidebuginfo.cc",
+    ],
+    static_libs: [
+        "libartbase",
+        "libbase",
+        "libelffile",
+        "liblzma",
+        "liblog",
+    ],
+}
diff --git a/tools/create_minidebuginfo/create_minidebuginfo.cc b/tools/create_minidebuginfo/create_minidebuginfo.cc
new file mode 100644
index 0000000..506661a
--- /dev/null
+++ b/tools/create_minidebuginfo/create_minidebuginfo.cc
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2021 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 "android-base/logging.h"
+
+#include "base/os.h"
+#include "base/unix_file/fd_file.h"
+#include "elf/elf_builder.h"
+#include "elf/elf_debug_reader.h"
+#include "elf/xz_utils.h"
+#include "stream/file_output_stream.h"
+#include "stream/vector_output_stream.h"
+
+#include <algorithm>
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <vector>
+
+namespace art {
+
+static constexpr size_t kBlockSize = 32 * KB;
+
+constexpr const char kSortedSymbolName[] = "$android.symtab.sorted";
+
+template<typename ElfTypes>
+static void WriteMinidebugInfo(const std::vector<uint8_t>& input, std::vector<uint8_t>* output) {
+  using Elf_Addr = typename ElfTypes::Addr;
+  using Elf_Shdr = typename ElfTypes::Shdr;
+  using Elf_Sym = typename ElfTypes::Sym;
+  using Elf_Word = typename ElfTypes::Word;
+  using CIE = typename ElfDebugReader<ElfTypes>::CIE;
+  using FDE = typename ElfDebugReader<ElfTypes>::FDE;
+
+  ElfDebugReader<ElfTypes> reader(input);
+
+  std::vector<uint8_t> output_elf_data;
+  VectorOutputStream output_stream("Output ELF", &output_elf_data);
+  InstructionSet isa = ElfBuilder<ElfTypes>::GetIsaFromHeader(*reader.GetHeader());
+  std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &output_stream));
+  builder->Start(/*write_program_headers=*/ false);
+
+  auto* text = builder->GetText();
+  const Elf_Shdr* original_text = reader.GetSection(".text");
+  CHECK(original_text != nullptr);
+  text->AllocateVirtualMemory(original_text->sh_addr, original_text->sh_size);
+
+  auto* strtab = builder->GetStrTab();
+  auto* symtab = builder->GetSymTab();
+  strtab->Start();
+  {
+    std::multimap<std::string_view, Elf_Sym> syms;
+    reader.VisitFunctionSymbols([&](Elf_Sym sym, const char* name) {
+      // Exclude non-function or empty symbols.
+      if (ELF32_ST_TYPE(sym.st_info) == STT_FUNC && sym.st_size != 0) {
+        syms.emplace(name, sym);
+      }
+    });
+    reader.VisitDynamicSymbols([&](Elf_Sym sym, const char* name) {
+      // Exclude symbols which will be preserved in the dynamic table anyway.
+      auto it = syms.find(name);
+      if (it != syms.end() && it->second.st_value == sym.st_value) {
+        syms.erase(it);
+      }
+    });
+    if (!syms.empty()) {
+      symtab->Add(strtab->Write(kSortedSymbolName), nullptr, 0, 0, STB_GLOBAL, STT_NOTYPE);
+    }
+    for (auto& entry : syms) {
+      std::string_view name = entry.first;
+      const Elf_Sym& sym = entry.second;
+      Elf_Word name_idx = strtab->Write(name);
+      symtab->Add(name_idx, text, sym.st_value, sym.st_size, STB_GLOBAL, STT_FUNC);
+    }
+  }
+  strtab->End();
+  symtab->WriteCachedSection();
+
+  auto* debug_frame = builder->GetDebugFrame();
+  debug_frame->Start();
+  {
+    std::map<std::basic_string_view<uint8_t>, Elf_Addr> cie_dedup;
+    std::unordered_map<const CIE*, Elf_Addr> new_cie_offset;
+    std::deque<std::pair<const FDE*, const CIE*>> entries;
+    // Read, de-duplicate and write CIE entries.  Read FDE entries.
+    reader.VisitDebugFrame(
+        [&](const CIE* cie) {
+          std::basic_string_view<uint8_t> key(cie->data(), cie->size());
+          auto it = cie_dedup.emplace(key, debug_frame->GetPosition());
+          if (/* inserted */ it.second) {
+            debug_frame->WriteFully(cie->data(), cie->size());
+          }
+          new_cie_offset[cie] = it.first->second;
+        },
+        [&](const FDE* fde, const CIE* cie) {
+          entries.emplace_back(std::make_pair(fde, cie));
+        });
+    // Sort FDE entries by opcodes to improve locality for compression (saves ~25%).
+    std::stable_sort(entries.begin(), entries.end(), [](const auto& lhs, const auto& rhs) {
+      constexpr size_t opcode_offset = sizeof(FDE);
+      return std::lexicographical_compare(
+          lhs.first->data() + opcode_offset, lhs.first->data() + lhs.first->size(),
+          rhs.first->data() + opcode_offset, rhs.first->data() + rhs.first->size());
+    });
+    // Write all FDE entries while adjusting the CIE offsets to the new locations.
+    for (const auto& entry : entries) {
+      const FDE* fde = entry.first;
+      const CIE* cie = entry.second;
+      FDE new_header = *fde;
+      new_header.cie_pointer = new_cie_offset[cie];
+      debug_frame->WriteFully(&new_header, sizeof(FDE));
+      debug_frame->WriteFully(fde->data() + sizeof(FDE), fde->size() - sizeof(FDE));
+    }
+  }
+  debug_frame->End();
+
+  builder->End();
+  CHECK(builder->Good());
+
+  XzCompress(ArrayRef<const uint8_t>(output_elf_data), output, 9 /*size*/, kBlockSize);
+}
+
+static int Main(int argc, char** argv) {
+  // Check command like arguments.
+  if (argc != 3) {
+    printf("Usage: create_minidebuginfo ELF_FILE OUT_FILE\n");
+    printf("  ELF_FILE: The path to an ELF file with full symbols (before being stripped).\n");
+    printf("  OUT_FILE: The path for the generated mini-debug-info data (not an elf file).\n");
+    return 1;
+  }
+  const char* input_filename = argv[1];
+  const char* output_filename = argv[2];
+
+  // Read input file.
+  std::unique_ptr<File> input_file(OS::OpenFileForReading(input_filename));
+  CHECK(input_file.get() != nullptr) << "Failed to open input file";
+  std::vector<uint8_t> elf(input_file->GetLength());
+  CHECK(input_file->ReadFully(elf.data(), elf.size())) << "Failed to read input file";
+
+  // Write output file.
+  std::vector<uint8_t> output;
+  if (ElfDebugReader<ElfTypes32>::IsValidElfHeader(elf)) {
+    WriteMinidebugInfo<ElfTypes32>(elf, &output);
+  } else if (ElfDebugReader<ElfTypes64>::IsValidElfHeader(elf)) {
+    WriteMinidebugInfo<ElfTypes64>(elf, &output);
+  } else {
+    LOG(FATAL) << "Invalid ELF file header " << input_filename;
+  }
+  std::unique_ptr<File> output_file(OS::CreateEmptyFile(output_filename));
+  if (!output_file->WriteFully(output.data(), output.size()) || output_file->FlushClose() != 0) {
+    LOG(FATAL) << "Failed to write " << output_filename;
+  }
+  return 0;
+}
+
+}  // namespace art
+
+int main(int argc, char** argv) {
+  return art::Main(argc, argv);
+}
diff --git a/tools/dex2oat_wrapper b/tools/dex2oat_wrapper
new file mode 100644
index 0000000..63e2348
--- /dev/null
+++ b/tools/dex2oat_wrapper
@@ -0,0 +1,121 @@
+# Copyright (C) 2020 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.
+
+# This script is used on host and device. It uses a common subset
+# shell dialect that should work on the host (e.g. bash), and
+# Android (e.g. mksh).
+
+# The purpose of this script is to invoke dex2oat with the right
+# boot classpath and bootclasspath locations.
+
+# Follow all sym links to get the program name.
+if [[ -n "$BASH_SOURCE" ]]; then
+  PROG_NAME="$BASH_SOURCE"
+else
+  PROG_NAME="$0"
+fi
+while [ -h "$PROG_NAME" ]; do
+  # On Mac OS, readlink -f doesn't work.
+  PROG_NAME="$(readlink "$PROG_NAME")"
+done
+
+PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
+ANDROID_ROOT="$(cd $PROG_DIR/..; pwd -P)"
+
+declare -a args=("$@")
+arg_idx=0
+while true; do
+  if [[ $1 == "-Xbootclasspath:*" ]]; then
+    DEX2OAT_BCP=$1
+    # Remove '-Xbootclasspath:' from the arguments.
+    DEX2OAT_BCP=${DEX2OAT_BCP##-Xbootclasspath:}
+    unset args[arg_idx]
+    shift
+  elif [[ $1 == "-Xbootclasspath-locations:*" ]]; then
+    DEX2OAT_BCP_LOCS=$1
+    # Remove '-Xbootclasspath-locations:' from the argument.
+    DEX2OAT_BCP_LOCS=${DEX2OAT_BCP_LOCS##-Xbootclasspath-locations:}
+    unset args[arg_idx]
+    shift
+  elif [[ $1 == "--32" ]]; then
+    BITNESS=32
+    LD_LIBRARY_PATH=$ANDROID_ROOT/lib:$LD_LIBRARY_PATH
+    unset args[arg_idx]
+    shift
+  elif [[ $1 == "--64" ]]; then
+    BITNESS=64
+    LD_LIBRARY_PATH=$ANDROID_ROOT/lib64:$LD_LIBRARY_PATH
+    unset args[arg_idx]
+    shift
+  elif [[ "$1" == "" ]]; then
+    break
+  else
+    shift
+  fi
+  arg_idx=$((arg_idx + 1))
+done
+
+if [ -z "$BITNESS" ]; then
+  echo "Either --32 or --64 is required as argument to specify bitness"
+  exit 1
+fi
+
+# Create boot class path filename or location list.
+# It takes one optional argument which is the prefix to be inserted before each entry.
+function get_boot_class_path() {
+  # Note: This must start with the CORE_IMG_JARS in Android.common_path.mk
+  local modules="core-oj core-libart okhttp bouncycastle apache-xml core-icu4j conscrypt"
+  local prefix="$1"
+  local result=""
+  local separator=""
+  for module in ${modules}; do
+    case "$module" in
+      (conscrypt)  local apex="com.android.conscrypt";;
+      (core-icu4j) local apex="com.android.i18n";;
+      (*)          local apex="com.android.art";;
+    esac
+    result+="${separator}${prefix}/apex/${apex}/javalib/${module}.jar"
+    separator=":"
+  done
+  echo "$result"
+}
+
+# Create default boot class path if none was provided.
+if [[ "$DEX2OAT_BCP" = "" ]]; then
+  ANDROID_ROOT_MINUS_PWD="${ANDROID_ROOT#$PWD/}"  # For example: out/host/linux-x86
+  if [[ "$ANDROID_ROOT_MINUS_PWD" == */host/* ]]; then
+    DEX2OAT_BCP="$(get_boot_class_path $ANDROID_ROOT)"
+    DEX2OAT_BCP_LOCS="$(get_boot_class_path $ANDROID_ROOT_MINUS_PWD)"
+  elif [[ "$ANDROID_ROOT_MINUS_PWD" == */target/* ]]; then
+    DEX2OAT_BCP="$(get_boot_class_path $ANDROID_ROOT)"
+    DEX2OAT_BCP_LOCS="$(get_boot_class_path)"
+  else
+    echo "Can not determine whether are running on host or target"
+    exit 1
+  fi
+fi
+
+# If the dex2oat binary with the bitness as a suffix doesn't exist,
+# try with a dex2oat without suffix.
+DEX2OAT_SUFFIX=$BITNESS
+if [[ ! -f $ANDROID_ROOT/bin/dex2oat${DEX2OAT_SUFFIX} ]]; then
+  DEX2OAT_SUFFIX=""
+fi
+
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH \
+  $ANDROID_ROOT/bin/dex2oat${DEX2OAT_SUFFIX} \
+    --android-root=$ANDROID_ROOT \
+    --runtime-arg -Xbootclasspath:$DEX2OAT_BCP \
+    --runtime-arg -Xbootclasspath-locations:$DEX2OAT_BCP_LOCS \
+    ${args[@]}
diff --git a/tools/dexanalyze/Android.bp b/tools/dexanalyze/Android.bp
index e7ae113..2a625d6 100644
--- a/tools/dexanalyze/Android.bp
+++ b/tools/dexanalyze/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "dexanalyze-defaults",
     defaults: ["art_defaults"],
@@ -38,18 +47,25 @@
         "libbase",
     ],
     apex_available: [
-        "com.android.art.release",
+        "com.android.art",
         "com.android.art.debug",
     ],
 }
 
 art_cc_test {
     name: "art_dexanalyze_tests",
-    required: ["dexanalyze"],
     defaults: [
         "art_gtest_defaults",
     ],
+    data: [
+        ":art-gtest-jars-MultiDex",
+    ],
     srcs: [
         "dexanalyze_test.cc",
     ],
+    target: {
+        host: {
+            required: ["dexanalyze"],
+        },
+    },
 }
diff --git a/tools/dexanalyze/dexanalyze.cc b/tools/dexanalyze/dexanalyze.cc
index 040f41b..f0ce4c4 100644
--- a/tools/dexanalyze/dexanalyze.cc
+++ b/tools/dexanalyze/dexanalyze.cc
@@ -51,7 +51,7 @@
     LOG(ERROR)
         << "Usage " << argv[0] << " [options] <dex files>\n"
         << "    [options] is a combination of the following\n"
-        << "    -count_indices (Count dex indices accessed from code items)\n"
+        << "    -count-indices (Count dex indices accessed from code items)\n"
         << "    -analyze-strings (Analyze string data)\n"
         << "    -analyze-debug-info (Analyze debug info)\n"
         << "    -new-bytecode (Bytecode optimizations)\n"
diff --git a/tools/dexfuzz/Android.bp b/tools/dexfuzz/Android.bp
index b095e00..02bda0e 100644
--- a/tools/dexfuzz/Android.bp
+++ b/tools/dexfuzz/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // --- dexfuzz.jar ----------------
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 java_library_host {
     name: "dexfuzz",
     srcs: ["src/**/*.java"],
diff --git a/tools/dexfuzz/Android.mk b/tools/dexfuzz/Android.mk
index e316fad..929b687 100644
--- a/tools/dexfuzz/Android.mk
+++ b/tools/dexfuzz/Android.mk
@@ -18,4 +18,5 @@
 
 # --- dexfuzz script with core image dependencies ----------------
 .PHONY: fuzzer
+
 fuzzer: dexfuzz-script $(HOST_CORE_IMG_OUTS)
diff --git a/tools/dexfuzz/src/dexfuzz/program/CodeTranslator.java b/tools/dexfuzz/src/dexfuzz/program/CodeTranslator.java
index 5335d15..710ab9f 100644
--- a/tools/dexfuzz/src/dexfuzz/program/CodeTranslator.java
+++ b/tools/dexfuzz/src/dexfuzz/program/CodeTranslator.java
@@ -269,7 +269,7 @@
         mTryBlock.endInsn = insnLocationMap.get(endLocation);
       }
 
-      // Sanity checks.
+      // Verify start and end instructions.
       if (mTryBlock.startInsn == null) {
         Log.errorAndQuit(String.format(
             "Couldn't find a mutatable insn at start offset 0x%x",
@@ -289,7 +289,7 @@
       if (encodedCatchHandler.size <= 0) {
         mTryBlock.catchAllHandler =
             insnLocationMap.get(encodedCatchHandler.catchAllAddr);
-        // Sanity check.
+        // Verify catch-all handler instruction.
         if (mTryBlock.catchAllHandler == null) {
           Log.errorAndQuit(
               String.format("Couldn't find a mutatable insn at catch-all offset 0x%x",
@@ -303,7 +303,7 @@
       for (int i = 0; i < Math.abs(encodedCatchHandler.size); i++) {
         EncodedTypeAddrPair handler = encodedCatchHandler.handlers[i];
         MInsn handlerInsn = insnLocationMap.get(handler.addr);
-        // Sanity check.
+        // Verify catch handler instruction.
         if (handlerInsn == null) {
           Log.errorAndQuit(String.format(
               "Couldn't find a mutatable instruction at handler offset 0x%x",
diff --git a/tools/dexfuzz/src/dexfuzz/program/mutators/RandomInstructionGenerator.java b/tools/dexfuzz/src/dexfuzz/program/mutators/RandomInstructionGenerator.java
index ff43c7c..dfc57ac 100644
--- a/tools/dexfuzz/src/dexfuzz/program/mutators/RandomInstructionGenerator.java
+++ b/tools/dexfuzz/src/dexfuzz/program/mutators/RandomInstructionGenerator.java
@@ -133,14 +133,10 @@
       if (Opcode.isBetween(newOpcode, Opcode.FILLED_NEW_ARRAY, Opcode.FILL_ARRAY_DATA)
           || Opcode.isBetween(newOpcode, Opcode.PACKED_SWITCH, Opcode.SPARSE_SWITCH)
           || Opcode.isBetween(newOpcode, Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_INTERFACE)
-          || Opcode.isBetween(newOpcode,
-              Opcode.INVOKE_VIRTUAL_RANGE, Opcode.INVOKE_INTERFACE_RANGE)
-              // Can never accept these instructions at compile time.
-              || Opcode.isBetween(newOpcode, Opcode.IGET_QUICK, Opcode.IPUT_SHORT_QUICK)
-              // Unused opcodes...
-              || Opcode.isBetween(newOpcode, Opcode.UNUSED_3E, Opcode.UNUSED_43)
-              || Opcode.isBetween(newOpcode, Opcode.UNUSED_79, Opcode.UNUSED_7A)
-              || Opcode.isBetween(newOpcode, Opcode.UNUSED_EF, Opcode.UNUSED_FF)) {
+          || Opcode.isBetween(newOpcode, Opcode.INVOKE_VIRTUAL_RANGE, Opcode.INVOKE_INTERFACE_RANGE)
+          || Opcode.isBetween(newOpcode, Opcode.UNUSED_3E, Opcode.UNUSED_43)
+          || Opcode.isBetween(newOpcode, Opcode.UNUSED_79, Opcode.UNUSED_7A)
+          || Opcode.isBetween(newOpcode, Opcode.UNUSED_E3, Opcode.UNUSED_FF)) {
         foundOpcode = false;
       }
     }
diff --git a/tools/dexfuzz/src/dexfuzz/rawdex/Instruction.java b/tools/dexfuzz/src/dexfuzz/rawdex/Instruction.java
index adafa62..a9b93d4 100644
--- a/tools/dexfuzz/src/dexfuzz/rawdex/Instruction.java
+++ b/tools/dexfuzz/src/dexfuzz/rawdex/Instruction.java
@@ -434,7 +434,7 @@
     addOpcodeInfo(Opcode.INVOKE_DIRECT, "invoke-direct", 0x70, new Format35c());
     addOpcodeInfo(Opcode.INVOKE_STATIC, "invoke-static", 0x71, new Format35c());
     addOpcodeInfo(Opcode.INVOKE_INTERFACE, "invoke-interface", 0x72, new Format35c());
-    addOpcodeInfo(Opcode.RETURN_VOID_NO_BARRIER, "return-void-no-barrier", 0x73, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_73, "unused-73", 0x73, new Format10x());
     addOpcodeInfo(Opcode.INVOKE_VIRTUAL_RANGE, "invoke-virtual/range", 0x74, new Format3rc());
     addOpcodeInfo(Opcode.INVOKE_SUPER_RANGE, "invoke-super/range", 0x75, new Format3rc());
     addOpcodeInfo(Opcode.INVOKE_DIRECT_RANGE, "invoke-direct/range", 0x76, new Format3rc());
@@ -547,19 +547,18 @@
     addOpcodeInfo(Opcode.SHL_INT_LIT8, "shl-int/lit8", 0xe0, new Format22b());
     addOpcodeInfo(Opcode.SHR_INT_LIT8, "shr-int/lit8", 0xe1, new Format22b());
     addOpcodeInfo(Opcode.USHR_INT_LIT8, "ushr-int/lit8", 0xe2, new Format22b());
-    addOpcodeInfo(Opcode.IGET_QUICK, "+iget-quick", 0xe3, new Format22c());
-    addOpcodeInfo(Opcode.IGET_WIDE_QUICK, "+iget-wide-quick", 0xe4, new Format22c());
-    addOpcodeInfo(Opcode.IGET_OBJECT_QUICK, "+iget-object-quick", 0xe5, new Format22c());
-    addOpcodeInfo(Opcode.IPUT_QUICK, "+iput-quick", 0xe6, new Format22c());
-    addOpcodeInfo(Opcode.IPUT_WIDE_QUICK, "+iput-wide-quick", 0xe7, new Format22c());
-    addOpcodeInfo(Opcode.IPUT_OBJECT_QUICK, "+iput-object-quick", 0xe8, new Format22c());
-    addOpcodeInfo(Opcode.INVOKE_VIRTUAL_QUICK, "+invoke-virtual-quick", 0xe9, new Format35c());
-    addOpcodeInfo(Opcode.INVOKE_VIRTUAL_QUICK_RANGE, "+invoke-virtual-quick/range",
-        0xea, new Format3rc());
-    addOpcodeInfo(Opcode.IPUT_BOOLEAN_QUICK, "+iput-boolean-quick", 0xeb, new Format22c());
-    addOpcodeInfo(Opcode.IPUT_BYTE_QUICK, "+iput-byte-quick", 0xec, new Format22c());
-    addOpcodeInfo(Opcode.IPUT_CHAR_QUICK, "+iput-char-quick", 0xed, new Format22c());
-    addOpcodeInfo(Opcode.IPUT_SHORT_QUICK, "+iput-short-quick", 0xee, new Format22c());
+    addOpcodeInfo(Opcode.UNUSED_E3, "unused-e3", 0xe3, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_E4, "unused-e4", 0xe4, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_E5, "unused-e5", 0xe5, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_E6, "unused-e6", 0xe6, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_E7, "unused-e7", 0xe7, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_E8, "unused-e8", 0xe8, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_E9, "unused-e9", 0xe9, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_EA, "unused-ea", 0xea, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_EB, "unused-eb", 0xeb, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_EC, "unused-ec", 0xec, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_ED, "unused-ed", 0xed, new Format10x());
+    addOpcodeInfo(Opcode.UNUSED_EE, "unused-ee", 0xee, new Format10x());
     addOpcodeInfo(Opcode.UNUSED_EF, "unused-ef", 0xef, new Format10x());
     addOpcodeInfo(Opcode.UNUSED_F0, "unused-f0", 0xf0, new Format10x());
     addOpcodeInfo(Opcode.UNUSED_F1, "unused-f1", 0xf1, new Format10x());
diff --git a/tools/dexfuzz/src/dexfuzz/rawdex/Opcode.java b/tools/dexfuzz/src/dexfuzz/rawdex/Opcode.java
index f7c7788..76e8ef9 100644
--- a/tools/dexfuzz/src/dexfuzz/rawdex/Opcode.java
+++ b/tools/dexfuzz/src/dexfuzz/rawdex/Opcode.java
@@ -132,7 +132,7 @@
   INVOKE_DIRECT,
   INVOKE_STATIC,
   INVOKE_INTERFACE,
-  RETURN_VOID_NO_BARRIER,
+  UNUSED_73,
   INVOKE_VIRTUAL_RANGE,
   INVOKE_SUPER_RANGE,
   INVOKE_DIRECT_RANGE,
@@ -244,18 +244,18 @@
   SHL_INT_LIT8,
   SHR_INT_LIT8,
   USHR_INT_LIT8,
-  IGET_QUICK,
-  IGET_WIDE_QUICK,
-  IGET_OBJECT_QUICK,
-  IPUT_QUICK,
-  IPUT_WIDE_QUICK,
-  IPUT_OBJECT_QUICK,
-  INVOKE_VIRTUAL_QUICK,
-  INVOKE_VIRTUAL_QUICK_RANGE,
-  IPUT_BOOLEAN_QUICK,
-  IPUT_BYTE_QUICK,
-  IPUT_CHAR_QUICK,
-  IPUT_SHORT_QUICK,
+  UNUSED_E3,
+  UNUSED_E4,
+  UNUSED_E5,
+  UNUSED_E6,
+  UNUSED_E7,
+  UNUSED_E8,
+  UNUSED_E9,
+  UNUSED_EA,
+  UNUSED_EB,
+  UNUSED_EC,
+  UNUSED_ED,
+  UNUSED_EE,
   UNUSED_EF,
   UNUSED_F0,
   UNUSED_F1,
diff --git a/tools/dmtracedump/Android.bp b/tools/dmtracedump/Android.bp
index 9f207e9..dc6f250 100644
--- a/tools/dmtracedump/Android.bp
+++ b/tools/dmtracedump/Android.bp
@@ -14,6 +14,15 @@
 
 // Java method trace dump tool
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 art_cc_binary {
     name: "dmtracedump",
     host_supported: true,
diff --git a/tools/dt_fds_forward.py b/tools/dt_fds_forward.py
index 1f9c41f..2c6a84d 100755
--- a/tools/dt_fds_forward.py
+++ b/tools/dt_fds_forward.py
@@ -38,6 +38,7 @@
 LISTEN_START_MESSAGE   = b"dt_fd_forward:START-LISTEN\x00"
 LISTEN_END_MESSAGE     = b"dt_fd_forward:END-LISTEN\x00"
 ACCEPTED_MESSAGE       = b"dt_fd_forward:ACCEPTED\x00"
+HANDSHAKEN_MESSAGE     = b"dt_fd_forward:HANDSHAKE-COMPLETE\x00"
 CLOSE_MESSAGE          = b"dt_fd_forward:CLOSING\x00"
 
 libc = ctypes.cdll.LoadLibrary("libc.so.6")
@@ -105,6 +106,8 @@
           listening = False
         elif buf == ACCEPTED_MESSAGE:
           print("Fds were accepted.")
+        elif buf == HANDSHAKEN_MESSAGE:
+          print("Handshake completed.")
         elif buf == CLOSE_MESSAGE:
           # TODO Dup the fds and send a fake DDMS message like the actual plugin would.
           print("Fds were closed")
diff --git a/tools/generate_operator_out.py b/tools/generate_operator_out.py
index 921ae68..f1491d8 100755
--- a/tools/generate_operator_out.py
+++ b/tools/generate_operator_out.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2012 The Android Open Source Project
 #
@@ -206,7 +206,7 @@
             print('namespace %s {' % namespace)
 
         print(
-            'std::ostream& operator<<(std::ostream& os, const %s& rhs) {' % enum_name)
+            'std::ostream& operator<<(std::ostream& os, %s rhs) {' % enum_name)
         print('  switch (rhs) {')
         for (enum_value, enum_text) in _ENUMS[enum_name]:
             print('    case %s: os << "%s"; break;' % (enum_value, enum_text))
diff --git a/tools/golem/build-target.sh b/tools/golem/build-target.sh
index 45c9125..21d8823 100755
--- a/tools/golem/build-target.sh
+++ b/tools/golem/build-target.sh
@@ -269,6 +269,10 @@
   execute lunch "$lunch_target"
   # Golem uses master-art repository which is missing a lot of other libraries.
   setenv SOONG_ALLOW_MISSING_DEPENDENCIES true
+  # Let the build system know we're not aiming to do a full platform build.
+  if [ ! -d frameworks/base ]; then
+    setenv TARGET_BUILD_UNBUNDLED true
+  fi
   # Golem may be missing tools such as javac from its path.
   setenv_escape PATH "/usr/lib/jvm/java-8-openjdk-amd64/bin/:$PATH" '/usr/lib/jvm/java-8-openjdk-amd64/bin/:$PATH'
 else
diff --git a/tools/hiddenapi/Android.bp b/tools/hiddenapi/Android.bp
index e77e4c7..4cd8160 100644
--- a/tools/hiddenapi/Android.bp
+++ b/tools/hiddenapi/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "hiddenapi-defaults",
     host_supported: true,
@@ -24,26 +33,33 @@
     ],
 
     target: {
-        android: {
-            compile_multilib: "prefer32",
-        },
         darwin: {
             enabled: true,
         },
     },
 
-    shared_libs: [
+    stl: "c++_static",
+    static_libs: [
         "libbase",
     ],
 }
 
 art_cc_binary {
     name: "hiddenapi",
-    defaults: ["hiddenapi-defaults"],
-    shared_libs: [
-        "libdexfile",
-        "libartbase",
+    defaults: [
+        "hiddenapi-defaults",
+        "libartbase_static_defaults",
+        "libdexfile_static_defaults",
     ],
+    target: {
+        host: {
+            // Override the prefer32 added by art_cc_binary when
+            // HOST_PREFER_32_BIT is in use. Note that this override cannot be
+            // in cc_defaults because it'd get overridden by the load hook even
+            // when it uses PrependProperties.
+            compile_multilib: "64",
+        },
+    },
 }
 
 art_cc_binary {
@@ -51,10 +67,8 @@
     defaults: [
         "art_debug_defaults",
         "hiddenapi-defaults",
-    ],
-    shared_libs: [
-        "libdexfiled",
-        "libartbased",
+        "libartbased_static_defaults",
+        "libdexfiled_static_defaults",
     ],
 }
 
@@ -65,5 +79,10 @@
     defaults: [
         "art_gtest_defaults",
     ],
+    data: [
+        ":art-gtest-jars-HiddenApi",
+        ":art-gtest-jars-HiddenApiStubs",
+    ],
     srcs: ["hiddenapi_test.cc"],
+    required: ["hiddenapid"],
 }
diff --git a/tools/hiddenapi/README.md b/tools/hiddenapi/README.md
index cad1212..17cb95f 100644
--- a/tools/hiddenapi/README.md
+++ b/tools/hiddenapi/README.md
@@ -2,17 +2,17 @@
 =========
 
 This tool iterates over all class members inside given DEX files and modifies
-their access flags if their signatures appear on one of two lists - greylist and
-blacklist - provided as text file inputs. These access flags denote to the
+their access flags if their signatures appear on one of two lists - unsupported and
+blocklist - provided as text file inputs. These access flags denote to the
 runtime that the marked methods/fields should be treated as internal APIs with
 access restricted only to platform code. Methods/fields not mentioned on the two
-lists are assumed to be on a whitelist and left accessible by all code.
+lists are assumed to be part of the SDK and left accessible by all code.
 
 API signatures
 ==============
 
-The methods/fields to be marked are specified in two text files (greylist,
-blacklist) provided an input. Only one signature per line is allowed.
+The methods/fields to be marked are specified in two text files (unsupported,
+blocklist) provided an input. Only one signature per line is allowed.
 
 Types are expected in their DEX format - class descriptors are to be provided in
 "slash" form, e.g. "Ljava/lang/Object;", primitive types in their shorty form,
@@ -49,6 +49,6 @@
 
 Two following bit encoding is used to denote the membership of a method/field:
 
- * whitelist: `false`, `false`
- * greylist: `true`, `false`
- * blacklist: `true`, `true`
+ * sdk: `false`, `false`
+ * unsupported: `true`, `false`
+ * blocklist: `true`, `true`
diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc
index f6d599f..7954fa4 100644
--- a/tools/hiddenapi/hiddenapi.cc
+++ b/tools/hiddenapi/hiddenapi.cc
@@ -82,10 +82,19 @@
   UsageError("    --api-flags=<filename>:");
   UsageError("        CSV file with signatures of methods/fields and their respective flags");
   UsageError("");
+  UsageError("    --max-hiddenapi-level=<max-target-*>:");
+  UsageError("        the maximum hidden api level for APIs. If an API was originally restricted");
+  UsageError("        to a newer sdk, turn it into a regular unsupported API instead.");
+  UsageError("        instead. The full list of valid values is in hiddenapi_flags.h");
+  UsageError("");
   UsageError("    --no-force-assign-all:");
   UsageError("        Disable check that all dex entries have been assigned a flag");
   UsageError("");
   UsageError("  Command \"list\": dump lists of public and private API");
+  UsageError("    --dependency-stub-dex=<filename>: dex file containing API stubs provided");
+  UsageError("      by other parts of the bootclasspath. These are used to resolve");
+  UsageError("      dependencies in dex files specified in --boot-dex but do not appear in");
+  UsageError("      the output");
   UsageError("    --boot-dex=<filename>: dex file which belongs to boot class path");
   UsageError("    --public-stub-classpath=<filenames>:");
   UsageError("    --system-stub-classpath=<filenames>:");
@@ -95,6 +104,10 @@
   UsageError("        classpath. Multiple classpaths can be specified");
   UsageError("");
   UsageError("    --out-api-flags=<filename>: output file for a CSV file with API flags");
+  UsageError("    --fragment: the input is only a fragment of the whole bootclasspath and may");
+  UsageError("      not include a complete set of classes. That requires the tool to ignore");
+  UsageError("      missing classes and members. Specify --verbose to see the warnings.");
+  UsageError("    --verbose: output all warnings, even when --fragment is specified.");
   UsageError("");
 
   exit(EXIT_FAILURE);
@@ -187,7 +200,7 @@
                   GetName() == other.GetName() &&
                   GetSignature() == other.GetSignature();
 
-    // Sanity checks if they do match.
+    // Soundness check that they do match.
     if (equals) {
       CHECK_EQ(IsVirtualMethod(), other.IsVirtualMethod());
     }
@@ -231,8 +244,8 @@
 
 class ClassPath final {
  public:
-  ClassPath(const std::vector<std::string>& dex_paths, bool open_writable) {
-    OpenDexFiles(dex_paths, open_writable);
+  ClassPath(const std::vector<std::string>& dex_paths, bool open_writable, bool ignore_empty) {
+    OpenDexFiles(dex_paths, open_writable, ignore_empty);
   }
 
   template<typename Fn>
@@ -270,7 +283,9 @@
   }
 
  private:
-  void OpenDexFiles(const std::vector<std::string>& dex_paths, bool open_writable) {
+  void OpenDexFiles(const std::vector<std::string>& dex_paths,
+                    bool open_writable,
+                    bool ignore_empty) {
     ArtDexFileLoader dex_loader;
     std::string error_msg;
 
@@ -305,7 +320,10 @@
                                        /* verify_checksum= */ true,
                                        &error_msg,
                                        &dex_files_);
-        CHECK(success) << "Open failed for '" << filename << "' " << error_msg;
+        // If requested ignore a jar with no classes.dex files.
+        if (!success && ignore_empty && error_msg != "Entry not found") {
+          CHECK(success) << "Open failed for '" << filename << "' " << error_msg;
+        }
       }
     }
   }
@@ -439,8 +457,8 @@
 
 class Hierarchy final {
  public:
-  explicit Hierarchy(ClassPath& classpath) : classpath_(classpath) {
-    BuildClassHierarchy();
+  Hierarchy(ClassPath& classpath, bool fragment, bool verbose) : classpath_(classpath) {
+    BuildClassHierarchy(fragment, verbose);
   }
 
   // Perform an operation for each member of the hierarchy which could potentially
@@ -507,7 +525,7 @@
     }
   }
 
-  void BuildClassHierarchy() {
+  void BuildClassHierarchy(bool fragment, bool verbose) {
     // Create one HierarchyClass entry in `classes_` per class descriptor
     // and add all DexClass objects with the same descriptor to that entry.
     classpath_.ForEachDexClass([this](const DexClass& klass) {
@@ -525,18 +543,23 @@
         continue;
       }
 
-      HierarchyClass* superclass = FindClass(dex_klass.GetSuperclassDescriptor());
-      CHECK(superclass != nullptr)
-          << "Superclass " << dex_klass.GetSuperclassDescriptor()
-          << " of class " << dex_klass.GetDescriptor() << " from dex file \""
-          << dex_klass.GetDexFile().GetLocation() << "\" was not found. "
-          << "Either the superclass is missing or it appears later in the classpath spec.";
-      klass.AddExtends(*superclass);
+      auto add_extends = [&](const std::string_view& extends_desc) {
+        HierarchyClass* extends = FindClass(extends_desc);
+        if (extends != nullptr) {
+          klass.AddExtends(*extends);
+        } else if (!fragment || verbose) {
+          auto severity = verbose ? ::android::base::WARNING : ::android::base::FATAL;
+          LOG(severity)
+              << "Superclass/interface " << extends_desc
+              << " of class " << dex_klass.GetDescriptor() << " from dex file \""
+              << dex_klass.GetDexFile().GetLocation() << "\" was not found. "
+              << "Either it is missing or it appears later in the classpath spec.";
+        }
+      };
 
+      add_extends(dex_klass.GetSuperclassDescriptor());
       for (const std::string_view& iface_desc : dex_klass.GetInterfaceDescriptors()) {
-        HierarchyClass* iface = FindClass(iface_desc);
-        CHECK(iface != nullptr);
-        klass.AddExtends(*iface);
+        add_extends(iface_desc);
       }
     }
   }
@@ -898,6 +921,8 @@
             api_flags_path_ = std::string(option.substr(strlen("--api-flags=")));
           } else if (option == "--no-force-assign-all") {
             force_assign_all_ = false;
+          } else if (StartsWith(option, "--max-hiddenapi-level=")) {
+            max_hiddenapi_level_ = std::string(option.substr(strlen("--max-hiddenapi-level=")));
           } else {
             Usage("Unknown argument '%s'", raw_option);
           }
@@ -907,7 +932,12 @@
         for (int i = 1; i < argc; ++i) {
           const char* raw_option = argv[i];
           const std::string_view option(raw_option);
-          if (StartsWith(option, "--boot-dex=")) {
+          if (StartsWith(option, "--dependency-stub-dex=")) {
+            const std::string path(std::string(option.substr(strlen("--dependency-stub-dex="))));
+            dependency_stub_dex_paths_.push_back(path);
+            // Add path to the boot dex path to resolve dependencies.
+            boot_dex_paths_.push_back(path);
+          } else if (StartsWith(option, "--boot-dex=")) {
             boot_dex_paths_.push_back(std::string(option.substr(strlen("--boot-dex="))));
           } else if (StartsWith(option, "--public-stub-classpath=")) {
             stub_classpaths_.push_back(std::make_pair(
@@ -927,6 +957,10 @@
                 ApiStubs::Kind::kCorePlatformApi));
           } else if (StartsWith(option, "--out-api-flags=")) {
             api_flags_path_ = std::string(option.substr(strlen("--out-api-flags=")));
+          } else if (option == "--fragment") {
+            fragment_ = true;
+          } else if (option == "--verbose") {
+            verbose_ = true;
           } else {
             Usage("Unknown argument '%s'", raw_option);
           }
@@ -955,7 +989,9 @@
       const std::string& input_path = boot_dex_paths_[i];
       const std::string& output_path = output_dex_paths_[i];
 
-      ClassPath boot_classpath({ input_path }, /* open_writable= */ false);
+      ClassPath boot_classpath({ input_path },
+                               /* open_writable= */ false,
+                               /* ignore_empty= */ false);
       std::vector<const DexFile*> input_dex_files = boot_classpath.GetDexFiles();
       CHECK_EQ(input_dex_files.size(), 1u);
       const DexFile& input_dex = *input_dex_files[0];
@@ -969,7 +1005,7 @@
             bool api_list_found = (it != api_list.end());
             CHECK(!force_assign_all_ || api_list_found)
                 << "Could not find hiddenapi flags for dex entry: " << boot_member.GetApiEntry();
-            builder.WriteFlags(api_list_found ? it->second : ApiList::Whitelist());
+            builder.WriteFlags(api_list_found ? it->second : ApiList::Sdk());
           };
           auto fn_field = [&](const ClassAccessor::Field& boot_field) {
             fn_shared(DexMember(boot_class, boot_field));
@@ -1005,12 +1041,23 @@
 
       const std::string& signature = values[0];
 
+      // Skip signature
+      std::vector<std::string>::iterator apiListBegin = values.begin() + 1;
+      std::vector<std::string>::iterator apiListEnd = values.end();
+      if (!max_hiddenapi_level_.empty()) {
+          auto clamp_fn = [this](const std::string& apiListName) {
+              return ApiList::CoerceAtMost(apiListName,
+                                           max_hiddenapi_level_);
+          };
+          std::transform(apiListBegin, apiListEnd, apiListBegin, clamp_fn);
+      }
+
       CHECK(api_flag_map.find(signature) == api_flag_map.end()) << path << ":" << line_number
           << ": Duplicate entry: " << signature << kErrorHelp;
 
       ApiList membership;
 
-      bool success = ApiList::FromNames(values.begin() + 1, values.end(), &membership);
+      bool success = ApiList::FromNames(apiListBegin, apiListEnd, &membership);
       CHECK(success) << path << ":" << line_number
           << ": Some flags were not recognized: " << line << kErrorHelp;
       CHECK(membership.IsValid()) << path << ":" << line_number
@@ -1023,6 +1070,10 @@
     return api_flag_map;
   }
 
+  // A special flag added to the set of flags in boot_members to indicate that
+  // it should be excluded from the output.
+  static constexpr std::string_view kExcludeFromOutput{"exclude-from-output"};
+
   void ListApi() {
     if (boot_dex_paths_.empty()) {
       Usage("No boot DEX files specified");
@@ -1040,19 +1091,35 @@
     std::set<std::string> unresolved;
 
     // Open all dex files.
-    ClassPath boot_classpath(boot_dex_paths_, /* open_writable= */ false);
-    Hierarchy boot_hierarchy(boot_classpath);
+    ClassPath boot_classpath(boot_dex_paths_,
+                             /* open_writable= */ false,
+                             /* ignore_empty= */ false);
+    Hierarchy boot_hierarchy(boot_classpath, fragment_, verbose_);
 
     // Mark all boot dex members private.
     boot_classpath.ForEachDexMember([&](const DexMember& boot_member) {
       boot_members[boot_member.GetApiEntry()] = {};
     });
 
+    // Open all dependency API stub dex files.
+    ClassPath dependency_classpath(dependency_stub_dex_paths_,
+                                   /* open_writable= */ false,
+                                   /* ignore_empty= */ false);
+
+    // Mark all dependency API stub dex members as coming from the dependency.
+    dependency_classpath.ForEachDexMember([&](const DexMember& boot_member) {
+      boot_members[boot_member.GetApiEntry()] = {kExcludeFromOutput};
+    });
+
     // Resolve each SDK dex member against the framework and mark it white.
     for (const auto& cp_entry : stub_classpaths_) {
+      // Ignore any empty stub jars as it just means that they provide no APIs
+      // for the current kind, e.g. framework-sdkextensions does not provide
+      // any public APIs.
       ClassPath stub_classpath(android::base::Split(cp_entry.first, ":"),
-                               /* open_writable= */ false);
-      Hierarchy stub_hierarchy(stub_classpath);
+                               /* open_writable= */ false,
+                               /* ignore_empty= */ true);
+      Hierarchy stub_hierarchy(stub_classpath, fragment_, verbose_);
       const ApiStubs::Kind stub_api = cp_entry.second;
 
       stub_classpath.ForEachDexMember(
@@ -1076,16 +1143,23 @@
     }
 
     // Print errors.
-    for (const std::string& str : unresolved) {
-      LOG(WARNING) << "unresolved: " << str;
+    if (!fragment_ || verbose_) {
+      for (const std::string& str : unresolved) {
+        LOG(WARNING) << "unresolved: " << str;
+      }
     }
 
     // Write into public/private API files.
     std::ofstream file_flags(api_flags_path_.c_str());
     for (const auto& entry : boot_members) {
-      if (entry.second.empty()) {
+      std::set<std::string_view> flags = entry.second;
+      if (flags.empty()) {
+        // There are no flags so it cannot be from the dependency stub API dex
+        // files so just output the signature.
         file_flags << entry.first << std::endl;
-      } else {
+      } else if (flags.find(kExcludeFromOutput) == flags.end()) {
+        // The entry has flags and is not from the dependency stub API dex so
+        // output it.
         file_flags << entry.first << ",";
         file_flags << android::base::Join(entry.second, ",") << std::endl;
       }
@@ -1100,6 +1174,10 @@
   // Paths to DEX files which should be processed.
   std::vector<std::string> boot_dex_paths_;
 
+  // Paths to DEX files containing API stubs provided by other parts of the
+  // boot class path which the DEX files in boot_dex_paths depend.
+  std::vector<std::string> dependency_stub_dex_paths_;
+
   // Output paths where modified DEX files should be written.
   std::vector<std::string> output_dex_paths_;
 
@@ -1110,6 +1188,17 @@
   // Path to CSV file containing the list of API members and their flags.
   // This could be both an input and output path.
   std::string api_flags_path_;
+
+  // Override limit for sdk-max-* hidden APIs.
+  std::string max_hiddenapi_level_;
+
+  // Whether the input is only a fragment of the whole bootclasspath and may
+  // not include a complete set of classes. That requires the tool to ignore missing
+  // classes and members.
+  bool fragment_ = false;
+
+  // Whether to output all warnings, even when `fragment_` is set.
+  bool verbose_ = false;
 };
 
 }  // namespace hiddenapi
diff --git a/tools/hiddenapi/hiddenapi_test.cc b/tools/hiddenapi/hiddenapi_test.cc
index 41eb4db..2593edd 100644
--- a/tools/hiddenapi/hiddenapi_test.cc
+++ b/tools/hiddenapi/hiddenapi_test.cc
@@ -66,8 +66,8 @@
 
     std::vector<std::string> argv_str;
     argv_str.push_back(GetHiddenApiCmd());
-    argv_str.insert(argv_str.end(), extra_args.begin(), extra_args.end());
     argv_str.push_back("encode");
+    argv_str.insert(argv_str.end(), extra_args.begin(), extra_args.end());
     argv_str.push_back("--input-dex=" + in_dex.GetFilename());
     argv_str.push_back("--output-dex=" + out_dex.GetFilename());
     argv_str.push_back("--api-flags=" + flags_csv.GetFilename());
@@ -179,7 +179,7 @@
     CHECK(accessor.HasClassData()) << "Class " << accessor.GetDescriptor() << " has no data";
 
     if (!accessor.HasHiddenapiClassData()) {
-      return hiddenapi::ApiList::Whitelist();
+      return hiddenapi::ApiList::Sdk();
     }
 
     for (const ClassAccessor::Field& field : accessor.GetFields()) {
@@ -206,7 +206,7 @@
     CHECK(accessor.HasClassData()) << "Class " << accessor.GetDescriptor() << " has no data";
 
     if (!accessor.HasHiddenapiClassData()) {
-      return hiddenapi::ApiList::Whitelist();
+      return hiddenapi::ApiList::Sdk();
     }
 
     for (const ClassAccessor::Method& method : accessor.GetMethods()) {
@@ -267,52 +267,52 @@
 TEST_F(HiddenApiTest, InstanceFieldNoMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->ifield:LBadType1;,greylist" << std::endl
-      << "LMain;->ifield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->ifield:LBadType3;,blacklist" << std::endl;
+      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
+      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->ifield:LBadType3;,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Whitelist(), GetIFieldHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetIFieldHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, InstanceFieldLightGreylistMatch) {
+TEST_F(HiddenApiTest, InstanceFieldLightunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->ifield:I,greylist" << std::endl
-      << "LMain;->ifield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->ifield:LBadType3;,blacklist" << std::endl;
+      << "LMain;->ifield:I,unsupported" << std::endl
+      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->ifield:LBadType3;,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Greylist(), GetIFieldHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetIFieldHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, InstanceFieldDarkGreylistMatch) {
+TEST_F(HiddenApiTest, InstanceFieldDarkunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->ifield:LBadType1;,greylist" << std::endl
-      << "LMain;->ifield:I,greylist-max-o" << std::endl
-      << "LMain;->ifield:LBadType3;,blacklist" << std::endl;
+      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
+      << "LMain;->ifield:I,max-target-o" << std::endl
+      << "LMain;->ifield:LBadType3;,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::GreylistMaxO(), GetIFieldHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetIFieldHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, InstanceFieldBlacklistMatch) {
+TEST_F(HiddenApiTest, InstanceFieldblockedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->ifield:LBadType1;,greylist" << std::endl
-      << "LMain;->ifield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->ifield:I,blacklist" << std::endl;
+      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
+      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->ifield:I,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Blacklist(), GetIFieldHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetIFieldHiddenFlags(*dex_file));
 }
 
 TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch1) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->ifield:LBadType1;,greylist" << std::endl
-      << "LMain;->ifield:I,blacklist,greylist-max-o" << std::endl;
+      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
+      << "LMain;->ifield:I,blocked,max-target-o" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -320,8 +320,8 @@
 TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch2) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->ifield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->ifield:I,blacklist,greylist" << std::endl;
+      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->ifield:I,blocked,unsupported" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -329,8 +329,8 @@
 TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch3) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->ifield:I,greylist,greylist-max-o" << std::endl
-      << "LMain;->ifield:LBadType3;,blacklist" << std::endl;
+      << "LMain;->ifield:I,unsupported,max-target-o" << std::endl
+      << "LMain;->ifield:LBadType3;,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -338,52 +338,52 @@
 TEST_F(HiddenApiTest, StaticFieldNoMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->sfield:LBadType1;,greylist" << std::endl
-      << "LMain;->sfield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->sfield:LBadType3;,blacklist" << std::endl;
+      << "LMain;->sfield:LBadType1;,unsupported" << std::endl
+      << "LMain;->sfield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->sfield:LBadType3;,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Whitelist(), GetSFieldHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetSFieldHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, StaticFieldLightGreylistMatch) {
+TEST_F(HiddenApiTest, StaticFieldLightunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->sfield:Ljava/lang/Object;,greylist" << std::endl
-      << "LMain;->sfield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->sfield:LBadType3;,blacklist" << std::endl;
+      << "LMain;->sfield:Ljava/lang/Object;,unsupported" << std::endl
+      << "LMain;->sfield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->sfield:LBadType3;,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Greylist(), GetSFieldHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetSFieldHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, StaticFieldDarkGreylistMatch) {
+TEST_F(HiddenApiTest, StaticFieldDarkunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->sfield:LBadType1;,greylist" << std::endl
-      << "LMain;->sfield:Ljava/lang/Object;,greylist-max-o" << std::endl
-      << "LMain;->sfield:LBadType3;,blacklist" << std::endl;
+      << "LMain;->sfield:LBadType1;,unsupported" << std::endl
+      << "LMain;->sfield:Ljava/lang/Object;,max-target-o" << std::endl
+      << "LMain;->sfield:LBadType3;,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::GreylistMaxO(), GetSFieldHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetSFieldHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, StaticFieldBlacklistMatch) {
+TEST_F(HiddenApiTest, StaticFieldblockedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->sfield:LBadType1;,greylist" << std::endl
-      << "LMain;->sfield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->sfield:Ljava/lang/Object;,blacklist" << std::endl;
+      << "LMain;->sfield:LBadType1;,unsupported" << std::endl
+      << "LMain;->sfield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->sfield:Ljava/lang/Object;,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Blacklist(), GetSFieldHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetSFieldHiddenFlags(*dex_file));
 }
 
 TEST_F(HiddenApiTest, StaticFieldTwoListsMatch1) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->sfield:LBadType1;,greylist" << std::endl
-      << "LMain;->sfield:Ljava/lang/Object;,blacklist,greylist-max-o" << std::endl;
+      << "LMain;->sfield:LBadType1;,unsupported" << std::endl
+      << "LMain;->sfield:Ljava/lang/Object;,blocked,max-target-o" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -391,8 +391,8 @@
 TEST_F(HiddenApiTest, StaticFieldTwoListsMatch2) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->sfield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->sfield:Ljava/lang/Object;,blacklist,greylist" << std::endl;
+      << "LMain;->sfield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->sfield:Ljava/lang/Object;,blocked,unsupported" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -400,8 +400,8 @@
 TEST_F(HiddenApiTest, StaticFieldTwoListsMatch3) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->sfield:Ljava/lang/Object;,greylist,greylist-max-o" << std::endl
-      << "LMain;->sfield:LBadType3;,blacklist" << std::endl;
+      << "LMain;->sfield:Ljava/lang/Object;,unsupported,max-target-o" << std::endl
+      << "LMain;->sfield:LBadType3;,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -409,52 +409,52 @@
 TEST_F(HiddenApiTest, InstanceMethodNoMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->imethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->imethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->imethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->imethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->imethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->imethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Whitelist(), GetIMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetIMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, InstanceMethodLightGreylistMatch) {
+TEST_F(HiddenApiTest, InstanceMethodLightunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->imethod(J)V,greylist" << std::endl
-      << "LMain;->imethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->imethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->imethod(J)V,unsupported" << std::endl
+      << "LMain;->imethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->imethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Greylist(), GetIMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetIMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, InstanceMethodDarkGreylistMatch) {
+TEST_F(HiddenApiTest, InstanceMethodDarkunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->imethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->imethod(J)V,greylist-max-o" << std::endl
-      << "LMain;->imethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->imethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->imethod(J)V,max-target-o" << std::endl
+      << "LMain;->imethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::GreylistMaxO(), GetIMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetIMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, InstanceMethodBlacklistMatch) {
+TEST_F(HiddenApiTest, InstanceMethodblockedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->imethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->imethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->imethod(J)V,blacklist" << std::endl;
+      << "LMain;->imethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->imethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->imethod(J)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Blacklist(), GetIMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetIMethodHiddenFlags(*dex_file));
 }
 
 TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch1) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->imethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->imethod(J)V,blacklist,greylist-max-o" << std::endl;
+      << "LMain;->imethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->imethod(J)V,blocked,max-target-o" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -462,8 +462,8 @@
 TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch2) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->imethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->imethod(J)V,blacklist,greylist" << std::endl;
+      << "LMain;->imethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->imethod(J)V,blocked,unsupported" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -471,8 +471,8 @@
 TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch3) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->imethod(J)V,greylist,greylist-max-o" << std::endl
-      << "LMain;->imethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->imethod(J)V,unsupported,max-target-o" << std::endl
+      << "LMain;->imethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -480,52 +480,52 @@
 TEST_F(HiddenApiTest, StaticMethodNoMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->smethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->smethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->smethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->smethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->smethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->smethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Whitelist(), GetSMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetSMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, StaticMethodLightGreylistMatch) {
+TEST_F(HiddenApiTest, StaticMethodLightunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->smethod(Ljava/lang/Object;)V,greylist" << std::endl
-      << "LMain;->smethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->smethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->smethod(Ljava/lang/Object;)V,unsupported" << std::endl
+      << "LMain;->smethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->smethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Greylist(), GetSMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetSMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, StaticMethodDarkGreylistMatch) {
+TEST_F(HiddenApiTest, StaticMethodDarkunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->smethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->smethod(Ljava/lang/Object;)V,greylist-max-o" << std::endl
-      << "LMain;->smethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->smethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->smethod(Ljava/lang/Object;)V,max-target-o" << std::endl
+      << "LMain;->smethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::GreylistMaxO(), GetSMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetSMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, StaticMethodBlacklistMatch) {
+TEST_F(HiddenApiTest, StaticMethodblockedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->smethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->smethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->smethod(Ljava/lang/Object;)V,blacklist" << std::endl;
+      << "LMain;->smethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->smethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->smethod(Ljava/lang/Object;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Blacklist(), GetSMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetSMethodHiddenFlags(*dex_file));
 }
 
 TEST_F(HiddenApiTest, StaticMethodTwoListsMatch1) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->smethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->smethod(Ljava/lang/Object;)V,blacklist,greylist-max-o" << std::endl;
+      << "LMain;->smethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->smethod(Ljava/lang/Object;)V,blocked,max-target-o" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -533,8 +533,8 @@
 TEST_F(HiddenApiTest, StaticMethodTwoListsMatch2) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->smethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->smethod(Ljava/lang/Object;)V,blacklist,greylist" << std::endl;
+      << "LMain;->smethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->smethod(Ljava/lang/Object;)V,blocked,unsupported" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -542,8 +542,8 @@
 TEST_F(HiddenApiTest, StaticMethodTwoListsMatch3) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->smethod(Ljava/lang/Object;)V,greylist,greylist-max-o" << std::endl
-      << "LMain;->smethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->smethod(Ljava/lang/Object;)V,unsupported,max-target-o" << std::endl
+      << "LMain;->smethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -551,52 +551,52 @@
 TEST_F(HiddenApiTest, InstanceNativeMethodNoMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->inmethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->inmethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->inmethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->inmethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->inmethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->inmethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Whitelist(), GetINMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetINMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, InstanceNativeMethodLightGreylistMatch) {
+TEST_F(HiddenApiTest, InstanceNativeMethodLightunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->inmethod(C)V,greylist" << std::endl
-      << "LMain;->inmethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->inmethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->inmethod(C)V,unsupported" << std::endl
+      << "LMain;->inmethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->inmethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Greylist(), GetINMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetINMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, InstanceNativeMethodDarkGreylistMatch) {
+TEST_F(HiddenApiTest, InstanceNativeMethodDarkunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->inmethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->inmethod(C)V,greylist-max-o" << std::endl
-      << "LMain;->inmethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->inmethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->inmethod(C)V,max-target-o" << std::endl
+      << "LMain;->inmethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::GreylistMaxO(), GetINMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetINMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, InstanceNativeMethodBlacklistMatch) {
+TEST_F(HiddenApiTest, InstanceNativeMethodblockedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->inmethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->inmethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->inmethod(C)V,blacklist" << std::endl;
+      << "LMain;->inmethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->inmethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->inmethod(C)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Blacklist(), GetINMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetINMethodHiddenFlags(*dex_file));
 }
 
 TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch1) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->inmethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->inmethod(C)V,blacklist,greylist-max-o" << std::endl;
+      << "LMain;->inmethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->inmethod(C)V,blocked,max-target-o" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -604,8 +604,8 @@
 TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch2) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->inmethod(C)V,blacklist,greylist" << std::endl
-      << "LMain;->inmethod(LBadType2;)V,greylist-max-o" << std::endl;
+      << "LMain;->inmethod(C)V,blocked,unsupported" << std::endl
+      << "LMain;->inmethod(LBadType2;)V,max-target-o" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -613,8 +613,8 @@
 TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch3) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->inmethod(C)V,greylist,greylist-max-o" << std::endl
-      << "LMain;->inmethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->inmethod(C)V,unsupported,max-target-o" << std::endl
+      << "LMain;->inmethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -622,52 +622,52 @@
 TEST_F(HiddenApiTest, StaticNativeMethodNoMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->snmethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->snmethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->snmethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->snmethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->snmethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->snmethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Whitelist(), GetSNMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetSNMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, StaticNativeMethodLightGreylistMatch) {
+TEST_F(HiddenApiTest, StaticNativeMethodLightunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->snmethod(Ljava/lang/Integer;)V,greylist" << std::endl
-      << "LMain;->snmethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->snmethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->snmethod(Ljava/lang/Integer;)V,unsupported" << std::endl
+      << "LMain;->snmethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->snmethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Greylist(), GetSNMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetSNMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, StaticNativeMethodDarkGreylistMatch) {
+TEST_F(HiddenApiTest, StaticNativeMethodDarkunsupportedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->snmethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->snmethod(Ljava/lang/Integer;)V,greylist-max-o" << std::endl
-      << "LMain;->snmethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->snmethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->snmethod(Ljava/lang/Integer;)V,max-target-o" << std::endl
+      << "LMain;->snmethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::GreylistMaxO(), GetSNMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetSNMethodHiddenFlags(*dex_file));
 }
 
-TEST_F(HiddenApiTest, StaticNativeMethodBlacklistMatch) {
+TEST_F(HiddenApiTest, StaticNativeMethodblockedMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->snmethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->snmethod(LBadType2;)V,greylist-max-o" << std::endl
-      << "LMain;->snmethod(Ljava/lang/Integer;)V,blacklist" << std::endl;
+      << "LMain;->snmethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->snmethod(LBadType2;)V,max-target-o" << std::endl
+      << "LMain;->snmethod(Ljava/lang/Integer;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
-  ASSERT_EQ(hiddenapi::ApiList::Blacklist(), GetSNMethodHiddenFlags(*dex_file));
+  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetSNMethodHiddenFlags(*dex_file));
 }
 
 TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch1) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->snmethod(LBadType1;)V,greylist" << std::endl
-      << "LMain;->snmethod(Ljava/lang/Integer;)V,blacklist,greylist-max-o" << std::endl;
+      << "LMain;->snmethod(LBadType1;)V,unsupported" << std::endl
+      << "LMain;->snmethod(Ljava/lang/Integer;)V,blocked,max-target-o" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -675,8 +675,8 @@
 TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch2) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->snmethod(Ljava/lang/Integer;)V,blacklist,greylist" << std::endl
-      << "LMain;->snmethod(LBadType2;)V,greylist-max-o" << std::endl;
+      << "LMain;->snmethod(Ljava/lang/Integer;)V,blocked,unsupported" << std::endl
+      << "LMain;->snmethod(LBadType2;)V,max-target-o" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -684,8 +684,8 @@
 TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch3) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->snmethod(Ljava/lang/Integer;)V,greylist,greylist-max-o" << std::endl
-      << "LMain;->snmethod(LBadType3;)V,blacklist" << std::endl;
+      << "LMain;->snmethod(Ljava/lang/Integer;)V,unsupported,max-target-o" << std::endl
+      << "LMain;->snmethod(LBadType3;)V,blocked" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
@@ -693,37 +693,91 @@
 TEST_F(HiddenApiTest, InstanceFieldCorePlatformApiMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->ifield:LBadType1;,greylist" << std::endl
-      << "LMain;->ifield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->ifield:I,greylist,core-platform-api" << std::endl;
+      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
+      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->ifield:I,unsupported,core-platform-api" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
   ASSERT_EQ(hiddenapi::ApiList::CorePlatformApi() |
-  hiddenapi::ApiList::Greylist(), GetIFieldHiddenFlags(*dex_file));
+  hiddenapi::ApiList::Unsupported(), GetIFieldHiddenFlags(*dex_file));
 }
 
 TEST_F(HiddenApiTest, InstanceFieldTestApiMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->ifield:LBadType1;,greylist" << std::endl
-      << "LMain;->ifield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->ifield:I,greylist,test-api" << std::endl;
+      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
+      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->ifield:I,unsupported,test-api" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_NE(dex_file.get(), nullptr);
   ASSERT_EQ(hiddenapi::ApiList::TestApi()
-  | hiddenapi::ApiList::Greylist(), GetIFieldHiddenFlags(*dex_file));
+  | hiddenapi::ApiList::Unsupported(), GetIFieldHiddenFlags(*dex_file));
 }
 
 TEST_F(HiddenApiTest, InstanceFieldUnknownFlagMatch) {
   ScratchFile dex, flags_csv;
   OpenStream(flags_csv)
-      << "LMain;->ifield:LBadType1;,greylist" << std::endl
-      << "LMain;->ifield:LBadType2;,greylist-max-o" << std::endl
-      << "LMain;->ifield:I,greylist,unknown-flag" << std::endl;
+      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
+      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
+      << "LMain;->ifield:I,unsupported,unknown-flag" << std::endl;
   auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
   ASSERT_EQ(dex_file.get(), nullptr);
 }
 
+TEST_F(HiddenApiTest, InstanceFieldMaxSdkHigherThanMaxHiddenApiLevel) {
+  ScratchFile dex, flags_csv;
+  OpenStream(flags_csv)
+      << "LMain;->ifield:I,max-target-r" << std::endl;
+  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-q"}, dex);
+  ASSERT_NE(dex_file.get(), nullptr);
+  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldMaxSdkEqualsMaxHiddenApiLevel) {
+  ScratchFile dex, flags_csv;
+  OpenStream(flags_csv)
+      << "LMain;->ifield:I,max-target-r" << std::endl;
+  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-r"}, dex);
+  ASSERT_NE(dex_file.get(), nullptr);
+  ASSERT_EQ(hiddenapi::ApiList::MaxTargetR(), GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldMaxSdkLowerThanMaxHiddenApiLevel) {
+  ScratchFile dex, flags_csv;
+  OpenStream(flags_csv)
+      << "LMain;->ifield:I,max-target-q" << std::endl;
+  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-r"}, dex);
+  ASSERT_NE(dex_file.get(), nullptr);
+  ASSERT_EQ(hiddenapi::ApiList::MaxTargetQ(), GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldBlockedUnchangedByMaxHiddenApiLevel) {
+  ScratchFile dex, flags_csv;
+  OpenStream(flags_csv)
+      << "LMain;->ifield:I,blocked" << std::endl;
+  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-r"}, dex);
+  ASSERT_NE(dex_file.get(), nullptr);
+  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldUnsupportedUnchangedByMaxHiddenApiLevel) {
+  ScratchFile dex, flags_csv;
+  OpenStream(flags_csv)
+      << "LMain;->ifield:I,unsupported" << std::endl;
+  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-r"}, dex);
+  ASSERT_NE(dex_file.get(), nullptr);
+  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldSdkUnchangedByMaxHiddenApiLevel) {
+  ScratchFile dex, flags_csv;
+  OpenStream(flags_csv)
+      << "LMain;->ifield:I,sdk" << std::endl;
+  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-r"}, dex);
+  ASSERT_NE(dex_file.get(), nullptr);
+  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetIFieldHiddenFlags(*dex_file));
+}
+
 // The following tests use this class hierarchy:
 //
 //    AbstractPackageClass  PublicInterface
diff --git a/tools/javac-helper.sh b/tools/javac-helper.sh
index 03ea829..0182025 100755
--- a/tools/javac-helper.sh
+++ b/tools/javac-helper.sh
@@ -97,6 +97,7 @@
   bcp_arg="$(join_by ":" "${javac_bootclasspath[@]}")"
   javac_args=(-bootclasspath "$bcp_arg")
 fi
+javac_args+=(-encoding utf8)
 
 if [[ $showcommands == y ]]; then
   echo ${JAVAC} "${javac_args[@]}" "$@"
diff --git a/tools/jfuzz/Android.bp b/tools/jfuzz/Android.bp
index f0d8b37..fec7888 100644
--- a/tools/jfuzz/Android.bp
+++ b/tools/jfuzz/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // Fuzzer tool.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_binary_host {
     name: "jfuzz",
     srcs: ["jfuzz.cc"],
diff --git a/tools/jvmti-agents/README.md b/tools/jvmti-agents/README.md
index 35dfc68..b093289 100644
--- a/tools/jvmti-agents/README.md
+++ b/tools/jvmti-agents/README.md
@@ -7,10 +7,12 @@
 
 * [libbreakpointlogger](./breakpoint-logger)
 * [libdumpjvmti](./dump-jvmti-state)
+* [libenablevlog](./enable-vlog)
 * [libfieldnull](./field-null-percent)
 * [libjitload](./jit-load)
 * [liblistextensions](./list-extensions)
 * [libforceredefine](./simple-force-redefine)
+* [libsimpleprofile](./simple-profile)
 * [litifast](./ti-fast)
 * [libtitrace](./titrace)
 * [libwrapagentproperties](./wrapagentproperties)
\ No newline at end of file
diff --git a/tools/jvmti-agents/breakpoint-logger/Android.bp b/tools/jvmti-agents/breakpoint-logger/Android.bp
index 57878cd..c997a04 100644
--- a/tools/jvmti-agents/breakpoint-logger/Android.bp
+++ b/tools/jvmti-agents/breakpoint-logger/Android.bp
@@ -16,6 +16,15 @@
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "breakpointlogger-defaults",
     host_supported: true,
@@ -36,6 +45,7 @@
         },
     },
     header_libs: [
+        "jni_headers",
         "libopenjdkjvmti_headers",
     ],
 }
diff --git a/tools/jvmti-agents/chain-agents/Android.bp b/tools/jvmti-agents/chain-agents/Android.bp
index 9d66069..419a1e4 100644
--- a/tools/jvmti-agents/chain-agents/Android.bp
+++ b/tools/jvmti-agents/chain-agents/Android.bp
@@ -16,6 +16,15 @@
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "chainagents-base-defaults",
     srcs: ["chainagents.cc"],
diff --git a/tools/jvmti-agents/dump-jvmti-state/Android.bp b/tools/jvmti-agents/dump-jvmti-state/Android.bp
index 3a48941..021901b 100644
--- a/tools/jvmti-agents/dump-jvmti-state/Android.bp
+++ b/tools/jvmti-agents/dump-jvmti-state/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "dumpjvmti-defaults",
     host_supported: true,
@@ -29,6 +38,7 @@
         "libbase",
     ],
     header_libs: [
+        "jni_headers",
         "libopenjdkjvmti_headers",
     ],
 }
diff --git a/tools/jvmti-agents/enable-vlog/Android.bp b/tools/jvmti-agents/enable-vlog/Android.bp
new file mode 100644
index 0000000..9274dc5
--- /dev/null
+++ b/tools/jvmti-agents/enable-vlog/Android.bp
@@ -0,0 +1,82 @@
+//
+// Copyright (C) 2020 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.
+//
+
+// Build variants {target,host} x {debug,ndebug} x {32,64}
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+cc_defaults {
+    name: "enablevlog-base-defaults",
+    srcs: ["enablevlog.cc"],
+    defaults: ["art_defaults"],
+
+    // Note that this tool needs to be built for both 32-bit and 64-bit since it requires
+    // to be same ISA as what it is attached to.
+    compile_multilib: "both",
+    header_libs: [
+        "libopenjdkjvmti_headers",
+        "libnativehelper_header_only",
+        "jni_headers",
+    ],
+}
+
+cc_defaults {
+    name: "enablevlog-defaults",
+    host_supported: true,
+    shared_libs: [
+        "libbase",
+    ],
+    defaults: ["enablevlog-base-defaults"],
+}
+
+cc_defaults {
+    name: "enablevlog-static-defaults",
+    host_supported: false,
+    defaults: ["enablevlog-base-defaults"],
+
+    shared_libs: [
+        "liblog",
+    ],
+    static_libs: [
+        "libbase_ndk",
+    ],
+    sdk_version: "current",
+    stl: "c++_static",
+}
+
+art_cc_library {
+    name: "libenablevlogs",
+    defaults: ["enablevlog-static-defaults"],
+}
+
+art_cc_library {
+    name: "libenablevlog",
+    defaults: ["enablevlog-defaults"],
+}
+
+art_cc_library {
+    name: "libenablevlogd",
+    defaults: [
+        "art_debug_defaults",
+        "enablevlog-defaults",
+    ],
+}
diff --git a/tools/jvmti-agents/enable-vlog/README.md b/tools/jvmti-agents/enable-vlog/README.md
new file mode 100644
index 0000000..e43c075
--- /dev/null
+++ b/tools/jvmti-agents/enable-vlog/README.md
@@ -0,0 +1,93 @@
+# enablevlog
+
+enablevlog is a JVMTI agent designed for changing the VLOG options of a
+running process. Currently it only allows one to turn vlog options 'on'.
+
+# Usage
+### Build
+>    `m libenablevlog`
+
+The libraries will be built for 32-bit, 64-bit, host and target. Below
+examples assume you want to use the 64-bit version.
+
+Use `libenablevlogs` if you wish to build a version without non-NDK dynamic
+dependencies.
+
+### Command Line
+
+The agent is loaded using -agentpath like normal. It takes arguments in the
+following format:
+
+`[vlog1[,vlog2[,...]]]`
+
+It will cause the runtime to act as though you had passed these after the
+`-verbose:[...]` argument to `dalvikvm`.
+
+#### Supported events
+
+At the time of writing, the following events may be listened for with this agent
+
+* `class`
+
+* `collector`
+
+* `compiler`
+
+* `deopt`
+
+* `gc`
+
+* `heap`
+
+* `interpreter`
+
+* `jdwp`
+
+* `jit`
+
+* `jni`
+
+* `monitor`
+
+* `oat`
+
+* `profiler`
+
+* `signals`
+
+* `simulator`
+
+* `startup`
+
+* `third-party-jni`
+
+* `threads`
+
+* `verifier`
+
+* `verifier-debug`
+
+* `image`
+
+* `systrace-locks`
+
+* `plugin`
+
+* `agents`
+
+* `dex`
+
+These are not particularly stable and new options might get added. Examine
+the LogVerbosity struct definition and the parser for a up-to-date list.
+
+#### ART
+>    `art -Xplugin:$ANDROID_HOST_OUT/lib64/libopenjdkjvmti.so '-agentpath:libenablevlog.so=class,profiler' -cp tmp/java/helloworld.dex -Xint helloworld`
+
+* `-Xplugin` and `-agentpath` need to be used, otherwise the agent will fail during init.
+* If using `libartd.so`, make sure to use the debug version of jvmti.
+
+>    `adb shell setenforce 0`
+>
+>    `adb push $ANDROID_PRODUCT_OUT/system/lib64/libenablevlog.so /data/local/tmp/`
+>
+>    `adb shell am start-activity --attach-agent /data/local/tmp/libenablevlog.so=class,jit some.debuggable.apps/.the.app.MainActivity`
diff --git a/tools/jvmti-agents/enable-vlog/enablevlog.cc b/tools/jvmti-agents/enable-vlog/enablevlog.cc
new file mode 100644
index 0000000..7bee013
--- /dev/null
+++ b/tools/jvmti-agents/enable-vlog/enablevlog.cc
@@ -0,0 +1,119 @@
+// Copyright (C) 2020 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 <android-base/logging.h>
+#include <jni.h>
+#include <jvmti.h>
+
+#include <iostream>
+#include <string_view>
+
+namespace enablevlog {
+
+namespace {
+
+// Special art ti-version number. We will use this as a fallback if we cannot get a regular JVMTI
+// env.
+static constexpr jint kArtTiVersion = JVMTI_VERSION_1_2 | 0x40000000;
+
+// The extension that lets us change the VLOG flags.
+static constexpr std::string_view kSetVerboseExtensionName =
+    "com.android.art.misc.set_verbose_flag_ext";
+
+// Extension prototype
+using SetVerboseFlagExt = jvmtiError (*)(jvmtiEnv*, const char*, jboolean);
+
+template <typename T>
+static inline jvmtiError Deallocate(jvmtiEnv* env, T* mem) {
+  return env->Deallocate(reinterpret_cast<unsigned char*>(mem));
+}
+
+template <typename T>
+void Dealloc(jvmtiEnv* env, T* t) {
+  env->Deallocate(reinterpret_cast<unsigned char*>(t));
+}
+
+template <typename T, typename... Rest>
+void Dealloc(jvmtiEnv* env, T* t, Rest... rs) {
+  Dealloc(env, t);
+  Dealloc(env, rs...);
+}
+
+void DeallocParams(jvmtiEnv* env, jvmtiParamInfo* params, jint n_params) {
+  for (jint i = 0; i < n_params; i++) {
+    Dealloc(env, params[i].name);
+  }
+}
+
+template <typename T>
+T GetExtensionFunction(jvmtiEnv* jvmti, const std::string_view& name) {
+  jint n_ext = 0;
+  void* res = nullptr;
+  jvmtiExtensionFunctionInfo* infos = nullptr;
+  if (jvmti->GetExtensionFunctions(&n_ext, &infos) != JVMTI_ERROR_NONE) {
+    LOG(FATAL) << "Unable to get extensions";
+  }
+  for (jint i = 0; i < n_ext; i++) {
+    const jvmtiExtensionFunctionInfo& info = infos[i];
+    if (name == info.id) {
+      res = reinterpret_cast<void*>(info.func);
+    }
+    DeallocParams(jvmti, info.params, info.param_count);
+    Dealloc(jvmti, info.short_description, info.errors, info.id, info.params);
+  }
+  Dealloc(jvmti, infos);
+  return reinterpret_cast<T>(res);
+}
+
+static jint SetupJvmtiEnv(JavaVM* vm, jvmtiEnv** jvmti) {
+  jint res = 0;
+  res = vm->GetEnv(reinterpret_cast<void**>(jvmti), JVMTI_VERSION_1_1);
+
+  if (res != JNI_OK || *jvmti == nullptr) {
+    LOG(ERROR) << "Unable to access JVMTI, error code " << res;
+    return vm->GetEnv(reinterpret_cast<void**>(jvmti), kArtTiVersion);
+  }
+  return res;
+}
+
+}  // namespace
+
+static jint AgentStart(JavaVM* vm, char* options, void* reserved ATTRIBUTE_UNUSED) {
+  jvmtiEnv* jvmti = nullptr;
+  if (SetupJvmtiEnv(vm, &jvmti) != JNI_OK) {
+    LOG(ERROR) << "Could not get JVMTI env or ArtTiEnv!";
+    return JNI_ERR;
+  }
+  SetVerboseFlagExt svfe = GetExtensionFunction<SetVerboseFlagExt>(jvmti, kSetVerboseExtensionName);
+  if (svfe == nullptr) {
+    LOG(ERROR) << "Could not find extension " << kSetVerboseExtensionName;
+    return JNI_ERR;
+  } else if (svfe(jvmti, options, true) != JVMTI_ERROR_NONE) {
+    return JNI_ERR;
+  } else {
+    return JNI_OK;
+  }
+}
+
+// Late attachment (e.g. 'am attach-agent').
+extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, char* options, void* reserved) {
+  return AgentStart(vm, options, reserved);
+}
+
+// Early attachment
+extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* jvm, char* options, void* reserved) {
+  return AgentStart(jvm, options, reserved);
+}
+
+}  // namespace enablevlog
diff --git a/tools/jvmti-agents/field-counts/Android.bp b/tools/jvmti-agents/field-counts/Android.bp
index a91af99..2a17b3b 100644
--- a/tools/jvmti-agents/field-counts/Android.bp
+++ b/tools/jvmti-agents/field-counts/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "fieldcount-base-defaults",
     srcs: ["fieldcount.cc"],
@@ -24,9 +33,9 @@
     // to be same ISA as what it is attached to.
     compile_multilib: "both",
     header_libs: [
+        "jni_headers",
         "libopenjdkjvmti_headers",
         "libnativehelper_header_only",
-        "jni_headers",
     ],
 }
 
diff --git a/tools/jvmti-agents/field-null-percent/Android.bp b/tools/jvmti-agents/field-null-percent/Android.bp
index 4950b7f..33d7460 100644
--- a/tools/jvmti-agents/field-null-percent/Android.bp
+++ b/tools/jvmti-agents/field-null-percent/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "fieldnull-base-defaults",
     srcs: ["fieldnull.cc"],
@@ -24,6 +33,7 @@
     // to be same ISA as what it is attached to.
     compile_multilib: "both",
     header_libs: [
+        "jni_headers",
         "libopenjdkjvmti_headers",
     ],
 }
diff --git a/tools/jvmti-agents/jit-load/Android.bp b/tools/jvmti-agents/jit-load/Android.bp
index 5adf98c..209992d 100644
--- a/tools/jvmti-agents/jit-load/Android.bp
+++ b/tools/jvmti-agents/jit-load/Android.bp
@@ -16,6 +16,15 @@
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "jitload-defaults",
     host_supported: true,
@@ -38,6 +47,7 @@
         },
     },
     header_libs: [
+        "jni_headers",
         "libopenjdkjvmti_headers",
     ],
 }
diff --git a/tools/jvmti-agents/list-extensions/Android.bp b/tools/jvmti-agents/list-extensions/Android.bp
index 09ba5aa..e0bc937 100644
--- a/tools/jvmti-agents/list-extensions/Android.bp
+++ b/tools/jvmti-agents/list-extensions/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "listextensions-defaults",
     host_supported: true,
@@ -29,6 +38,7 @@
         "libbase",
     ],
     header_libs: [
+        "jni_headers",
         "libopenjdkjvmti_headers",
     ],
 }
diff --git a/tools/jvmti-agents/simple-force-redefine/Android.bp b/tools/jvmti-agents/simple-force-redefine/Android.bp
index 38eb9f7..996f312 100644
--- a/tools/jvmti-agents/simple-force-redefine/Android.bp
+++ b/tools/jvmti-agents/simple-force-redefine/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "forceredefine-defaults",
     host_supported: true,
diff --git a/tools/jvmti-agents/simple-profile/Android.bp b/tools/jvmti-agents/simple-profile/Android.bp
new file mode 100644
index 0000000..12d0aeb
--- /dev/null
+++ b/tools/jvmti-agents/simple-profile/Android.bp
@@ -0,0 +1,102 @@
+//
+// Copyright (C) 2020 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.
+//
+
+// Build variants {target,host} x {debug,ndebug} x {32,64}
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
+cc_defaults {
+    name: "simpleprofile-base-defaults",
+    host_supported: true,
+    srcs: ["simple_profile.cc"],
+    defaults: ["art_defaults"],
+
+    // Note that this tool needs to be built for both 32-bit and 64-bit since it requires
+    // to be same ISA as what it is attached to.
+    compile_multilib: "both",
+
+    target: {
+        android: {
+        },
+        host: {
+        },
+    },
+    header_libs: [
+        "jni_headers",
+        "libopenjdkjvmti_headers",
+        "libnativehelper_header_only",
+    ],
+}
+
+cc_defaults {
+    name: "simpleprofile-defaults",
+    defaults: ["simpleprofile-base-defaults"],
+    shared_libs: [
+        "libbase",
+    ],
+}
+
+cc_defaults {
+    name: "simpleprofile-static-defaults",
+    host_supported: false,
+    defaults: ["simpleprofile-base-defaults"],
+
+    shared_libs: [
+        "liblog",
+    ],
+    static_libs: [
+        "libbase_ndk",
+    ],
+    sdk_version: "current",
+    stl: "c++_static",
+}
+
+art_cc_library {
+    name: "libsimpleprofiles",
+    defaults: ["simpleprofile-static-defaults"],
+}
+
+art_cc_library {
+    name: "libsimpleprofileds",
+    defaults: [
+        "art_debug_defaults",
+        "simpleprofile-static-defaults",
+    ],
+    shared_libs: [],
+}
+
+art_cc_library {
+    name: "libsimpleprofile",
+    defaults: ["simpleprofile-defaults"],
+    shared_libs: [
+    ],
+}
+
+art_cc_library {
+    name: "libsimpleprofiled",
+    defaults: [
+        "art_debug_defaults",
+        "simpleprofile-defaults",
+    ],
+    shared_libs: [],
+}
diff --git a/tools/jvmti-agents/simple-profile/README.md b/tools/jvmti-agents/simple-profile/README.md
new file mode 100644
index 0000000..4a069fb
--- /dev/null
+++ b/tools/jvmti-agents/simple-profile/README.md
@@ -0,0 +1,63 @@
+# simpleprofile
+
+simpleprofile is a JVMTI agent that lets one get simple JSON profiles with JVMTI
+
+# Usage
+### Build
+>    `m libsimpleprofile`  # or 'm libsimpleprofiled' with debugging checks enabled
+
+For binaries with NDK shared libraries only.
+>    `m libsimpleprofiled` # or `m libsimpleprofileds` with debugging checks enabled.
+
+The libraries will be built for 32-bit, 64-bit, host and target. Below examples
+assume you want to use the 64-bit version.
+
+### Command Line
+
+The agent is loaded using -agentpath like normal. It takes arguments in the
+following format:
+>     `file-output[,dump_on_shutdown][,dump_on_main_stop]`
+
+
+#### ART
+>    `art -Xplugin:$ANDROID_HOST_OUT/lib64/libopenjdkjvmti.so '-agentpath:libsimpleprofiled.so=/proc/self/fd/2,dump_on_main_stop' -cp tmp/java/helloworld.dex -Xint helloworld`
+
+* `-Xplugin` and `-agentpath` need to be used, otherwise the agent will fail during init.
+* If using `libartd.so`, make sure to use the debug version of jvmti.
+
+#### Device
+```
+% adb root
+% adb shell setenforce 0
+% adb push $OUT/system/lib64/libsimpleprofileds.so /data/local/tmp/libsimpleprofileds.so
+% adb shell
+blueline:/data/data/com.google.android.apps.maps # cp /data/local/tmp/libsimpleprofileds.so .
+blueline:/data/data/com.google.android.apps.maps # ps -A | grep maps
+u0_a178        9143    927 15691440 190132 SyS_epoll_wait     0 S com.google.android.apps.maps
+blueline:/data/data/com.google.android.apps.maps # cmd activity attach-agent com.google.android.apps.maps $PWD/libsimpleprofileds.so=$PWD/maps.json
+blueline:/data/data/com.google.android.apps.maps # # Do things on the app.
+blueline:/data/data/com.google.android.apps.maps # kill -3 9143
+blueline:/data/data/com.google.android.apps.maps # wc -l maps.json
+17901 maps.json
+blueline:/data/data/com.google.android.apps.maps # ^D
+% adb pull /data/data/com.google.android.apps.maps/maps.json
+```
+
+#### RI
+>    `java '-agentpath:libsimpleprofiled.so=/proc/self/fd/2,dump_on_main_stop' -cp tmp/helloworld/classes helloworld`
+
+### Output
+A normal run will look something like this:
+
+    % ./test/run-test --64 --host --dev --with-agent $ANDROID_HOST_OUT/lib64/libsimpleprofiled.so=dump_on_main_stop,/proc/self/fd/1 001-HelloWorld
+    <normal output removed>
+    Hello, world!
+    ...
+    {"class_name":"Ljava/util/HashMap$KeySet;","method_name":"iterator","method_descriptor":"()Ljava/util/Iterator;","count":6},
+    {"class_name":"Ljava/util/HashMap$KeyIterator;","method_name":"<init>","method_descriptor":"(Ljava/util/HashMap;)V","count":6},
+    {"class_name":"Ljava/util/HashMap$HashIterator;","method_name":"<init>","method_descriptor":"(Ljava/util/HashMap;)V","count":6},
+    {"class_name":"Ljava/lang/String;","method_name":"equals","method_descriptor":"(Ljava/lang/Object;)Z","count":128},
+    {"class_name":"Ljava/util/Collections$UnmodifiableCollection$1;","method_name":"next","method_descriptor":"()Ljava/lang/Object;","count":38},
+    {"class_name":"Ljava/util/HashMap$KeyIterator;","method_name":"next","method_descriptor":"()Ljava/lang/Object;","count":38},
+    {"class_name":"Lsun/misc/Cleaner;","method_name":"add","method_descriptor":"(Lsun/misc/Cleaner;)Lsun/misc/Cleaner;","count":1},
+    ...
diff --git a/tools/jvmti-agents/simple-profile/simple_profile.cc b/tools/jvmti-agents/simple-profile/simple_profile.cc
new file mode 100644
index 0000000..5ead97e
--- /dev/null
+++ b/tools/jvmti-agents/simple-profile/simple_profile.cc
@@ -0,0 +1,523 @@
+// Copyright (C) 2020 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 <android-base/logging.h>
+#include <fcntl.h>
+#include <jni.h>
+#include <jvmti.h>
+
+#include <atomic>
+#include <cstring>
+#include <iomanip>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "android-base/unique_fd.h"
+#include "nativehelper/scoped_local_ref.h"
+
+namespace simple_profile {
+
+static constexpr jint kArtTiVersion = JVMTI_VERSION_1_2 | 0x40000000;
+
+#define CHECK_JVMTI(a) CHECK_EQ(JVMTI_ERROR_NONE, a)
+
+struct DataDefinition {
+  std::string_view class_name;
+  std::string_view method_name;
+  std::string_view method_descriptor;
+  uint64_t count;
+};
+
+std::ostream& operator<<(std::ostream& os, const DataDefinition& dd) {
+  return os << "{\"class_name\":\"" << dd.class_name << "\",\"method_name\":\"" << dd.method_name
+            << "\",\"method_descriptor\":\"" << dd.method_descriptor << "\",\"count\":" << dd.count
+            << "}";
+}
+
+class SimpleProfileData {
+ public:
+  SimpleProfileData(
+      jvmtiEnv* env, std::string out_fd_name, int fd, bool dump_on_shutdown, bool dump_on_main_stop)
+      : dump_id_(0),
+        out_fd_name_(out_fd_name),
+        out_fd_(fd),
+        shutdown_(false),
+        dump_on_shutdown_(dump_on_shutdown || dump_on_main_stop),
+        dump_on_main_stop_(dump_on_main_stop) {
+    CHECK_JVMTI(env->CreateRawMonitor("simple_profile_mon", &mon_));
+    method_counts_.reserve(10000);
+  }
+
+  void Dump(jvmtiEnv* jvmti);
+  void Enter(jvmtiEnv* jvmti, JNIEnv* env, jmethodID meth);
+
+  void RunDumpLoop(jvmtiEnv* jvmti, JNIEnv* env);
+
+  static SimpleProfileData* GetProfileData(jvmtiEnv* env) {
+    void* data;
+    CHECK_JVMTI(env->GetEnvironmentLocalStorage(&data));
+    return static_cast<SimpleProfileData*>(data);
+  }
+
+  void FinishInitialization(jvmtiEnv* jvmti, JNIEnv* jni, jthread cur);
+  void Shutdown(jvmtiEnv* jvmti, JNIEnv* jni);
+
+ private:
+  void DoDump(jvmtiEnv* jvmti, JNIEnv* jni, std::unordered_map<jmethodID, uint64_t> copy);
+
+  jlong dump_id_;
+  jrawMonitorID mon_;
+  std::string out_fd_name_;
+  int out_fd_;
+  std::unordered_map<jmethodID, uint64_t> method_counts_;
+  bool shutdown_;
+  bool dump_on_shutdown_;
+  bool dump_on_main_stop_;
+};
+
+struct ScopedJvmtiMonitor {
+ public:
+  ScopedJvmtiMonitor(jvmtiEnv* env, jrawMonitorID mon) : jvmti_(env), mon_(mon) {
+    CHECK_JVMTI(jvmti_->RawMonitorEnter(mon_));
+  }
+
+  ~ScopedJvmtiMonitor() {
+    CHECK_JVMTI(jvmti_->RawMonitorExit(mon_));
+  }
+
+  void Notify() {
+    CHECK_JVMTI(jvmti_->RawMonitorNotifyAll(mon_));
+  }
+
+  void Wait() {
+    CHECK_JVMTI(jvmti_->RawMonitorWait(mon_, 0));
+  }
+
+ private:
+  jvmtiEnv* jvmti_;
+  jrawMonitorID mon_;
+};
+
+void SimpleProfileData::Enter(jvmtiEnv* jvmti, JNIEnv* env, jmethodID meth) {
+  ScopedJvmtiMonitor sjm(jvmti, mon_);
+  // Keep all classes from being unloaded to allow us to know we can get the method info later.
+  jclass tmp;
+  CHECK_JVMTI(jvmti->GetMethodDeclaringClass(meth, &tmp));
+  ScopedLocalRef<jclass> klass(env, tmp);
+  jlong tag;
+  CHECK_JVMTI(jvmti->GetTag(klass.get(), &tag));
+  if (tag == 0) {
+    CHECK_JVMTI(jvmti->SetTag(klass.get(), 1u));
+    env->NewGlobalRef(klass.get());
+  }
+  method_counts_.insert({ meth, 0u }).first->second++;
+}
+
+void SimpleProfileData::Dump(jvmtiEnv* jvmti) {
+  ScopedJvmtiMonitor sjm(jvmti, mon_);
+  dump_id_++;
+  sjm.Notify();
+}
+
+void SimpleProfileData::RunDumpLoop(jvmtiEnv* jvmti, JNIEnv* env) {
+  jlong current_id = 0;
+  do {
+    std::unordered_map<jmethodID, uint64_t> copy;
+    {
+      ScopedJvmtiMonitor sjm(jvmti, mon_);
+      while (!shutdown_ && current_id == dump_id_) {
+        sjm.Wait();
+      }
+      if (shutdown_) {
+        break;
+      }
+      current_id = dump_id_;
+      copy = method_counts_;
+    }
+    DoDump(jvmti, env, std::move(copy));
+  } while (true);
+}
+
+void SimpleProfileData::Shutdown(jvmtiEnv* jvmti, JNIEnv* jni) {
+  std::unordered_map<jmethodID, uint64_t> copy;
+  {
+    ScopedJvmtiMonitor sjm(jvmti, mon_);
+    if (shutdown_) {
+      return;
+    }
+    shutdown_ = true;
+    copy = method_counts_;
+    sjm.Notify();
+  }
+  if (dump_on_shutdown_) {
+    DoDump(jvmti, jni, std::move(copy));
+  }
+}
+
+void SimpleProfileData::FinishInitialization(jvmtiEnv* jvmti, JNIEnv* env, jthread cur) {
+  // Finish up startup.
+  // Create a Thread object.
+  std::string name = std::string("profile dump Thread: ") + this->out_fd_name_;
+  ScopedLocalRef<jobject> thread_name(env, env->NewStringUTF(name.c_str()));
+  CHECK_NE(thread_name.get(), nullptr);
+
+  ScopedLocalRef<jclass> thread_klass(env, env->FindClass("java/lang/Thread"));
+  CHECK_NE(thread_klass.get(), nullptr);
+  ScopedLocalRef<jobject> thread(env, env->AllocObject(thread_klass.get()));
+  CHECK_NE(thread.get(), nullptr);
+  jmethodID initID = env->GetMethodID(thread_klass.get(), "<init>", "(Ljava/lang/String;)V");
+  jmethodID setDaemonId = env->GetMethodID(thread_klass.get(), "setDaemon", "(Z)V");
+  CHECK_NE(initID, nullptr);
+  CHECK_NE(setDaemonId, nullptr);
+  env->CallNonvirtualVoidMethod(thread.get(), thread_klass.get(), initID, thread_name.get());
+  env->CallVoidMethod(thread.get(), setDaemonId, JNI_TRUE);
+  CHECK(!env->ExceptionCheck());
+
+  CHECK_JVMTI(jvmti->RunAgentThread(
+      thread.get(),
+      [](jvmtiEnv* jvmti, JNIEnv* jni, void* unused_data ATTRIBUTE_UNUSED) {
+        SimpleProfileData* data = SimpleProfileData::GetProfileData(jvmti);
+        data->RunDumpLoop(jvmti, jni);
+      },
+      nullptr,
+      JVMTI_THREAD_NORM_PRIORITY));
+
+  CHECK_JVMTI(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_ENTRY, nullptr));
+  CHECK_JVMTI(
+      jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_DATA_DUMP_REQUEST, nullptr));
+  if (dump_on_main_stop_) {
+    CHECK_JVMTI(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_THREAD_END, cur));
+  }
+  CHECK_JVMTI(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, nullptr));
+}
+
+class ScopedClassInfo {
+ public:
+  ScopedClassInfo(jvmtiEnv* jvmti_env, jclass c)
+      : jvmti_env_(jvmti_env), class_(c), name_(nullptr), generic_(nullptr) {}
+
+  ~ScopedClassInfo() {
+    if (class_ != nullptr) {
+      jvmti_env_->Deallocate(reinterpret_cast<unsigned char*>(name_));
+      jvmti_env_->Deallocate(reinterpret_cast<unsigned char*>(generic_));
+    }
+  }
+
+  bool Init() {
+    if (class_ == nullptr) {
+      name_ = const_cast<char*>("<NONE>");
+      generic_ = const_cast<char*>("<NONE>");
+      return true;
+    } else {
+      return jvmti_env_->GetClassSignature(class_, &name_, &generic_) == JVMTI_ERROR_NONE;
+    }
+  }
+
+  jclass GetClass() const {
+    return class_;
+  }
+  const char* GetName() const {
+    return name_;
+  }
+  // Generic type parameters, whatever is in the <> for a class
+  const char* GetGeneric() const {
+    return generic_;
+  }
+
+ private:
+  jvmtiEnv* jvmti_env_;
+  jclass class_;
+  char* name_;
+  char* generic_;
+};
+
+class ScopedMethodInfo {
+ public:
+  ScopedMethodInfo(jvmtiEnv* jvmti_env, JNIEnv* env, jmethodID method)
+      : jvmti_env_(jvmti_env),
+        env_(env),
+        method_(method),
+        declaring_class_(nullptr),
+        class_info_(nullptr),
+        name_(nullptr),
+        signature_(nullptr),
+        generic_(nullptr) {}
+
+  ~ScopedMethodInfo() {
+    env_->DeleteLocalRef(declaring_class_);
+    jvmti_env_->Deallocate(reinterpret_cast<unsigned char*>(name_));
+    jvmti_env_->Deallocate(reinterpret_cast<unsigned char*>(signature_));
+    jvmti_env_->Deallocate(reinterpret_cast<unsigned char*>(generic_));
+  }
+
+  bool Init() {
+    if (jvmti_env_->GetMethodDeclaringClass(method_, &declaring_class_) != JVMTI_ERROR_NONE) {
+      LOG(INFO) << "No decl";
+      return false;
+    }
+    class_info_.reset(new ScopedClassInfo(jvmti_env_, declaring_class_));
+    return class_info_->Init() &&
+           (jvmti_env_->GetMethodName(method_, &name_, &signature_, &generic_) == JVMTI_ERROR_NONE);
+  }
+
+  const ScopedClassInfo& GetDeclaringClassInfo() const {
+    return *class_info_;
+  }
+
+  jclass GetDeclaringClass() const {
+    return declaring_class_;
+  }
+
+  const char* GetName() const {
+    return name_;
+  }
+
+  const char* GetSignature() const {
+    return signature_;
+  }
+
+  const char* GetGeneric() const {
+    return generic_;
+  }
+
+ private:
+  jvmtiEnv* jvmti_env_;
+  JNIEnv* env_;
+  jmethodID method_;
+  jclass declaring_class_;
+  std::unique_ptr<ScopedClassInfo> class_info_;
+  char* name_;
+  char* signature_;
+  char* generic_;
+
+  friend std::ostream& operator<<(std::ostream& os, ScopedMethodInfo const& method);
+};
+
+std::ostream& operator<<(std::ostream& os, const ScopedMethodInfo* method) {
+  return os << *method;
+}
+
+std::ostream& operator<<(std::ostream& os, ScopedMethodInfo const& method) {
+  return os << method.GetDeclaringClassInfo().GetName() << "->" << method.GetName()
+            << method.GetSignature();
+}
+
+void SimpleProfileData::DoDump(jvmtiEnv* jvmti,
+                               JNIEnv* jni,
+                               std::unordered_map<jmethodID, uint64_t> copy) {
+  std::ostringstream oss;
+  oss << "[";
+  bool is_first = true;
+  for (auto [meth, cnt] : copy) {
+    ScopedMethodInfo smi(jvmti, jni, meth);
+    if (!smi.Init()) {
+      continue;
+    }
+    if (!is_first) {
+      oss << "," << std::endl;
+    }
+    is_first = false;
+    oss << DataDefinition {
+      .class_name = smi.GetDeclaringClassInfo().GetName(),
+      .method_name = smi.GetName(),
+      .method_descriptor = smi.GetSignature(),
+      .count = cnt,
+    };
+  }
+  oss << "]";
+  CHECK_GE(TEMP_FAILURE_RETRY(write(out_fd_, oss.str().c_str(), oss.str().size())), 0)
+      << strerror(errno) << out_fd_ << " " << out_fd_name_;
+  fsync(out_fd_);
+}
+
+static void DataDumpCb(jvmtiEnv* jvmti_env) {
+  SimpleProfileData* data = SimpleProfileData::GetProfileData(jvmti_env);
+  data->Dump(jvmti_env);
+}
+
+static void MethodEntryCB(jvmtiEnv* jvmti_env,
+                          JNIEnv* env,
+                          jthread thread ATTRIBUTE_UNUSED,
+                          jmethodID method) {
+  SimpleProfileData* data = SimpleProfileData::GetProfileData(jvmti_env);
+  data->Enter(jvmti_env, env, method);
+}
+
+static void VMInitCB(jvmtiEnv* jvmti, JNIEnv* env, jthread thr) {
+  SimpleProfileData* data = SimpleProfileData::GetProfileData(jvmti);
+  data->FinishInitialization(jvmti, env, thr);
+}
+static void VMDeathCB(jvmtiEnv* jvmti, JNIEnv* env) {
+  SimpleProfileData* data = SimpleProfileData::GetProfileData(jvmti);
+  data->Shutdown(jvmti, env);
+}
+
+// Fills targets with the breakpoints to add.
+// Lname/of/Klass;->methodName(Lsig/of/Method)Lreturn/Type;@location,<...>
+static bool ParseArgs(const std::string& start_options,
+                      /*out*/ std::string* fd_name,
+                      /*out*/ int* fd,
+                      /*out*/ bool* dump_on_shutdown,
+                      /*out*/ bool* dump_on_main_stop) {
+  std::istringstream iss(start_options);
+  std::string item;
+  *dump_on_main_stop = false;
+  *dump_on_shutdown = false;
+  bool has_fd = false;
+  while (std::getline(iss, item, ',')) {
+    if (item == "dump_on_shutdown") {
+      *dump_on_shutdown = true;
+    } else if (item == "dump_on_main_stop") {
+      *dump_on_main_stop = true;
+    } else if (has_fd) {
+      LOG(ERROR) << "Too many args!";
+      return false;
+    } else {
+      has_fd = true;
+      *fd_name = item;
+      *fd = TEMP_FAILURE_RETRY(open(fd_name->c_str(), O_WRONLY | O_CLOEXEC | O_CREAT, 00666));
+      CHECK_GE(*fd, 0) << strerror(errno);
+    }
+  }
+  return has_fd;
+}
+
+enum class StartType {
+  OnAttach,
+  OnLoad,
+};
+
+static jint SetupJvmtiEnv(JavaVM* vm, jvmtiEnv** jvmti) {
+  jint res = 0;
+  res = vm->GetEnv(reinterpret_cast<void**>(jvmti), JVMTI_VERSION_1_1);
+
+  if (res != JNI_OK || *jvmti == nullptr) {
+    LOG(ERROR) << "Unable to access JVMTI, error code " << res;
+    return vm->GetEnv(reinterpret_cast<void**>(jvmti), kArtTiVersion);
+  }
+  return res;
+}
+
+static jint AgentStart(StartType start,
+                       JavaVM* vm,
+                       const char* options,
+                       void* reserved ATTRIBUTE_UNUSED) {
+  if (options == nullptr) {
+    options = "";
+  }
+  jvmtiEnv* jvmti = nullptr;
+  jvmtiError error = JVMTI_ERROR_NONE;
+  {
+    jint res = 0;
+    res = SetupJvmtiEnv(vm, &jvmti);
+
+    if (res != JNI_OK || jvmti == nullptr) {
+      LOG(ERROR) << "Unable to access JVMTI, error code " << res;
+      return JNI_ERR;
+    }
+  }
+
+  int fd;
+  std::string fd_name;
+  bool dump_on_shutdown;
+  bool dump_on_main_stop;
+  if (!ParseArgs(options,
+                 /*out*/ &fd_name,
+                 /*out*/ &fd,
+                 /*out*/ &dump_on_shutdown,
+                 /*out*/ &dump_on_main_stop)) {
+    LOG(ERROR) << "failed to get output file from " << options << "!";
+    return JNI_ERR;
+  }
+
+  void* data_mem = nullptr;
+  error = jvmti->Allocate(sizeof(SimpleProfileData), reinterpret_cast<unsigned char**>(&data_mem));
+  if (error != JVMTI_ERROR_NONE) {
+    LOG(ERROR) << "Unable to alloc memory for breakpoint target data";
+    return JNI_ERR;
+  }
+
+  SimpleProfileData* data =
+      new (data_mem) SimpleProfileData(jvmti, fd_name, fd, dump_on_shutdown, dump_on_main_stop);
+  error = jvmti->SetEnvironmentLocalStorage(data);
+  if (error != JVMTI_ERROR_NONE) {
+    LOG(ERROR) << "Unable to set local storage";
+    return JNI_ERR;
+  }
+
+  jvmtiCapabilities caps {};
+  caps.can_generate_method_entry_events = JNI_TRUE;
+  caps.can_tag_objects = JNI_TRUE;
+  error = jvmti->AddCapabilities(&caps);
+  if (error != JVMTI_ERROR_NONE) {
+    LOG(ERROR) << "Unable to set caps";
+    return JNI_ERR;
+  }
+
+  jvmtiEventCallbacks callbacks {};
+  callbacks.MethodEntry = &MethodEntryCB;
+  callbacks.VMInit = &VMInitCB;
+  callbacks.DataDumpRequest = &DataDumpCb;
+  callbacks.VMDeath = &VMDeathCB;
+  callbacks.ThreadEnd = [](jvmtiEnv* env, JNIEnv* jni, jthread thr ATTRIBUTE_UNUSED) {
+    VMDeathCB(env, jni);
+  };
+
+  error = jvmti->SetEventCallbacks(&callbacks, static_cast<jint>(sizeof(callbacks)));
+
+  if (error != JVMTI_ERROR_NONE) {
+    LOG(ERROR) << "Unable to set event callbacks.";
+    return JNI_ERR;
+  }
+
+  if (start == StartType::OnAttach) {
+    JNIEnv* env = nullptr;
+    jint res = 0;
+    res = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_2);
+    if (res != JNI_OK || env == nullptr) {
+      LOG(ERROR) << "Unable to get jnienv";
+      return JNI_ERR;
+    }
+    jthread temp;
+    ScopedLocalRef<jthread> cur(env, nullptr);
+    CHECK_JVMTI(jvmti->GetCurrentThread(&temp));
+    cur.reset(temp);
+    VMInitCB(jvmti, env, cur.get());
+  } else {
+    error = jvmti->SetEventNotificationMode(
+        JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, nullptr /* all threads */);
+    if (error != JVMTI_ERROR_NONE) {
+      LOG(ERROR) << "Unable to set event vminit";
+      return JNI_ERR;
+    }
+  }
+  return JNI_OK;
+}
+
+// Late attachment (e.g. 'am attach-agent').
+extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, char* options, void* reserved) {
+  return AgentStart(StartType::OnAttach, vm, options, reserved);
+}
+
+// Early attachment
+extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* jvm, char* options, void* reserved) {
+  return AgentStart(StartType::OnLoad, jvm, options, reserved);
+}
+
+}  // namespace simple_profile
diff --git a/tools/jvmti-agents/ti-alloc-sample/Android.bp b/tools/jvmti-agents/ti-alloc-sample/Android.bp
index 0dc2dd8..50a42fc 100644
--- a/tools/jvmti-agents/ti-alloc-sample/Android.bp
+++ b/tools/jvmti-agents/ti-alloc-sample/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "ti-alloc-sample-base-defaults",
     srcs: ["ti_alloc_sample.cc"],
diff --git a/tools/jvmti-agents/ti-fast/Android.bp b/tools/jvmti-agents/ti-fast/Android.bp
index 797654b..2d02298 100644
--- a/tools/jvmti-agents/ti-fast/Android.bp
+++ b/tools/jvmti-agents/ti-fast/Android.bp
@@ -15,6 +15,15 @@
 //
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "tifast-base-defaults",
     srcs: ["tifast.cc"],
diff --git a/tools/jvmti-agents/titrace/Android.bp b/tools/jvmti-agents/titrace/Android.bp
index 21c2bf0..d27bc0f 100644
--- a/tools/jvmti-agents/titrace/Android.bp
+++ b/tools/jvmti-agents/titrace/Android.bp
@@ -16,6 +16,15 @@
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "titrace-defaults",
     host_supported: true,
@@ -39,6 +48,7 @@
         },
     },
     header_libs: [
+        "jni_headers",
         "libopenjdkjvmti_headers",
         "libdexfile_all_headers", // for dex_instruction_list.h only
     ],
diff --git a/tools/jvmti-agents/wrapagentproperties/Android.bp b/tools/jvmti-agents/wrapagentproperties/Android.bp
index 88b1e67..8954ce2 100644
--- a/tools/jvmti-agents/wrapagentproperties/Android.bp
+++ b/tools/jvmti-agents/wrapagentproperties/Android.bp
@@ -16,6 +16,15 @@
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "wrapagentproperties-defaults",
     host_supported: true,
@@ -36,6 +45,7 @@
         },
     },
     header_libs: [
+        "jni_headers",
         "libopenjdkjvmti_headers",
     ],
 }
diff --git a/tools/libcore_debug_failures.txt b/tools/libcore_debug_failures.txt
new file mode 100644
index 0000000..54d5f4f
--- /dev/null
+++ b/tools/libcore_debug_failures.txt
@@ -0,0 +1,17 @@
+/*
+ * This file contains expectations for ART's buildbot when running in debug mode
+ * (without gcstress).
+ *
+ * The script that uses this file is art/tools/run-libcore-tests.sh.
+ */
+
+[
+{
+  description: "Timeouts with device for debug builds.",
+  result: EXEC_FAILED,
+  bug: 181968447,
+  modes: [device],
+  names: ["libcore.java.math.BigIntegerTest#test_Constructor_IILjava_util_Random",
+          "libcore.java.math.BigIntegerTest#test_probablePrime"]
+}
+]
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index 336de1a..1280038 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -25,13 +25,13 @@
 {
   description: "Differences between vogar and cts in user directory",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   name: "libcore.java.lang.SystemTest#testSystemProperties_mutable"
 },
 {
   description: "Differences between vogar and cts. Passes with --mode activity",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   names: ["libcore.java.lang.OldSystemTest#test_getProperties"]
 },
 {
@@ -40,7 +40,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_testdex],
+  modes: [device],
   names: ["libcore.libcore.io.OsTest#testUnixDomainSockets_in_file_system"]
 },
 {
@@ -55,7 +55,7 @@
 {
   description: "Issue with incorrect device time (1970)",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   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"],
@@ -65,20 +65,17 @@
   description: "Issue with incorrect device time (1970). Test assumes that DateTime.now()
                 is greater then a date in 1998.",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   names: ["org.apache.harmony.tests.java.util.DateTest#test_Constructor"]
 },
 {
   description: "Failing due to a locale problem on hammerhead.",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   names: ["libcore.icu.DateIntervalFormatTest#test10089890",
           "libcore.icu.DateIntervalFormatTest#test10209343_when_not_this_year",
           "libcore.icu.DateIntervalFormatTest#test10560853_for_single_day_events",
           "libcore.icu.DateIntervalFormatTest#test10560853_when_time_not_displayed",
-          "libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeDateTimeString",
-          "libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeTimeSpanString",
-          "libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeTimeSpanStringAbbrev",
           "libcore.java.text.OldDateFormatTest#test_parseLString",
           "libcore.java.text.SimpleDateFormatTest#testDstZoneNameWithNonDstTimestamp",
           "libcore.java.text.SimpleDateFormatTest#testDstZoneWithNonDstTimestampForNonHourDstZone",
@@ -88,7 +85,7 @@
 {
   description: "Failing due to missing localhost on hammerhead and volantis.",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   names: ["libcore.javax.crypto.CipherTest#testCipherInitWithCertificate",
           "libcore.net.NetworkSecurityPolicyTest#testCleartextTrafficPolicyWithFtpURLConnection",
           "libcore.net.NetworkSecurityPolicyTest#testCleartextTrafficPolicyWithJarFtpURLConnection",
@@ -103,13 +100,13 @@
 {
   description: "Test timeouts",
   result: EXEC_TIMEOUT,
-  modes: [device_testdex],
+  modes: [device],
   names: ["org.apache.harmony.tests.java.util.ScannerTest#testPerformance"]
 },
 {
   description: "Needs the newest cat version on the device",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   names: ["org.apache.harmony.tests.java.lang.ProcessTest#test_getErrorStream"]
 },
 {
@@ -119,7 +116,7 @@
 },
 {
   description: "Linker issues in chrooted environment",
-  modes: [device_testdex],
+  modes: [device],
   result: EXEC_FAILED,
   names: ["org.apache.harmony.tests.java.lang.ProcessManagerTest#testEnvironment"]
 },
@@ -132,18 +129,18 @@
 {
   description: "test_xattr fails on arm64 on the buildbots only: needs investigation",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   names: ["libcore.libcore.io.OsTest#test_xattr"],
   bug: 22258911
 },
 {
   description: "fails on L builds: needs investigation",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   names: ["org.apache.harmony.tests.java.lang.ClassTest#test_forNameLjava_lang_String"]
 },
 {
-  description: "Lack of IPv6 on some buildbot slaves",
+  description: "Lack of IPv6 on some buildbot workers",
   result: EXEC_FAILED,
   names: ["libcore.libcore.io.OsTest#test_byteBufferPositions_sendto_recvfrom_af_inet6",
           "libcore.libcore.io.OsTest#test_sendtoSocketAddress_af_inet6",
@@ -165,7 +162,7 @@
   description: "Flaky test",
   result: EXEC_FAILED,
   bug: 30107038,
-  modes: [device_testdex],
+  modes: [device],
   names: ["org.apache.harmony.tests.java.lang.ProcessTest#test_destroyForcibly"]
 },
 {
@@ -173,7 +170,7 @@
                 Unclear if this relates to the tests running sh as a child process.",
   result: EXEC_FAILED,
   bug: 30657148,
-  modes: [device_testdex],
+  modes: [device],
   names: ["libcore.java.lang.ProcessBuilderTest#testRedirectInherit",
           "libcore.java.lang.ProcessBuilderTest#testRedirect_nullStreams"]
 },
@@ -197,7 +194,7 @@
 {
   description: "Timeout on heap-poisoning target builds",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   bug: 116446372,
   names: ["libcore.libcore.io.FdsanTest#testSocket"]
 },
@@ -227,20 +224,9 @@
   ]
 },
 {
-  description: "Apex related",
-  result: EXEC_FAILED,
-  modes: [device_testdex],
-  bug: 122642227,
-  names: [
-    "libcore.libcore.icu.TimeZoneIntegrationTest#testTimeZoneDataVersion",
-    "libcore.libcore.icu.TimeZoneIntegrationTest#testTimeZoneDebugInfo",
-    "libcore.libcore.icu.TimeZoneIntegrationTest#testTzDataSetVersions"
-  ]
-},
-{
   description: "Timeout on walleye bots, currenlty on OPM1.171019.019. But test passes on Q, so just mark it fail here.",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   names: [
     "libcore.libcore.io.OsTest#testCrossFamilyBindConnectSendto"
   ]
@@ -264,7 +250,7 @@
 {
   description: "Fails on device",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   bug: 145348591,
   names: ["libcore.android.system.OsTest#test_if_nametoindex_if_indextoname"]
 },
@@ -272,5 +258,30 @@
   description: "Fails on non-Android and Android versions < R",
   result: EXEC_FAILED,
   names: ["libcore.android.system.OsTest#test_NetlinkSocket"]
+},
+{
+  description: "Times out on device",
+  result: EXEC_FAILED,
+  modes: [device],
+  bug: 161898207,
+  names: ["libcore.java.util.zip.ZipFileTest#testZipFileWithLotsOfEntries"]
+},
+{
+  description: "Times out on device with gcstress and poisoning configurations",
+  result: EXEC_FAILED,
+  modes: [device],
+  bug: 161420453,
+  names: ["libcore.java.text.DecimalFormatTest#testCurrencySymbolSpacing"]
+},
+{
+  description: "Test failures due to mismatch of conscrypt and boringssl versions on host",
+  result: EXEC_FAILED,
+  modes: [host],
+  names: ["libcore.javax.net.ssl.DefaultHostnameVerifierTest#testAltIpOnlyCert",
+          "libcore.javax.net.ssl.DefaultHostnameVerifierTest#testSubjectAltOnlyCert",
+          "libcore.javax.net.ssl.DefaultHostnameVerifierTest#testSubjectWithAltNamesCert",
+          "libcore.javax.net.ssl.DefaultHostnameVerifierTest#testSubjectWithWildAltNamesCert",
+          "libcore.javax.net.ssl.DefaultHostnameVerifierTest#testWildAltNameOnlyCert"],
+  bug: 166619732
 }
 ]
diff --git a/tools/libcore_fugu_failures.txt b/tools/libcore_fugu_failures.txt
index 11183bb..0fff814 100644
--- a/tools/libcore_fugu_failures.txt
+++ b/tools/libcore_fugu_failures.txt
@@ -10,7 +10,7 @@
   description: "Test using memfd_create() syscall, only available from Linux 3.17.",
   result: EXEC_FAILED,
   bug: 146113753,
-  modes: [device_testdex],
+  modes: [device],
   names: [
     "libcore.android.system.OsTest#testMemfdCreate",
     "libcore.android.system.OsTest#testMemfdCreateErrno",
@@ -21,7 +21,7 @@
   description: "Test using the getrandom() syscall, only available from Linux 3.17.",
   result: EXEC_FAILED,
   bug: 141230711,
-  modes: [device_testdex],
+  modes: [device],
   names: [
     "libcore.java.math.BigIntegerTest#test_Constructor_IILjava_util_Random",
     "libcore.java.math.BigIntegerTest#test_probablePrime",
diff --git a/tools/libcore_gcstress_debug_failures.txt b/tools/libcore_gcstress_debug_failures.txt
index 0112644..047543d 100644
--- a/tools/libcore_gcstress_debug_failures.txt
+++ b/tools/libcore_gcstress_debug_failures.txt
@@ -7,14 +7,11 @@
 {
   description: "Timeouts on target with gcstress and debug.",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   names: ["jsr166.CompletableFutureTest#testCompleteOnTimeout_completed",
           "jsr166.CompletableFutureTest#testDelayedExecutor",
           "jsr166.ExecutorsTest#testTimedCallable",
           "jsr166.RecursiveActionTest#testJoinIgnoresInterruptsOutsideForkJoinPool",
-          "libcore.libcore.icu.TransliteratorTest#testAll",
-          "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_bug25821045",
-          "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_bug25883157",
           "libcore.java.lang.ref.ReferenceQueueTest#testRemoveWithDelayedResultAndTimeout",
           "libcore.java.text.DecimalFormatTest#testWhitespaceError",
           "libcore.java.text.DecimalFormatTest#testWhitespaceTolerated",
@@ -40,25 +37,13 @@
           "jsr166.StampedLockTest#testReadLockInterruptibly_Interruptible",
           "jsr166.StampedLockTest#testReadLockInterruptibly",
           "jsr166.StampedLockTest#testWriteLockInterruptibly",
+          "jsr166.TimeUnitTest#testConvert",
+          "libcore.java.lang.StringTest#testFastPathString_wellFormedUtf8Sequence",
+          "libcore.java.math.BigIntegerTest#test_Constructor_IILjava_util_Random",
+          "libcore.java.math.BigIntegerTest#test_probablePrime",
+          "org.apache.harmony.luni.tests.internal.net.www.protocol.http.HttpURLConnectionTest#testUsingProxy",
           "org.apache.harmony.tests.java.lang.ProcessManagerTest#testSleep",
-          "libcore.java.lang.StringTest#testFastPathString_wellFormedUtf8Sequence"
-  ]
-},
-{
-  description: "Sometimes times out with gcstress and debug.",
-  result: EXEC_FAILED,
-  bug: 78228743,
-  names: [
-    "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_combineDateAndTime_apostrophe",
-    "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeDateTimeString",
-    "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeDateTimeStringCTS",
-    "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeDateTimeStringDST",
-    "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeDateTimeStringItalian",
-    "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeTimeSpanString",
-    "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeTimeSpanStringAbbrev",
-    "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeTimeSpanStringCTS",
-    "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeTimeSpanStringFrench",
-    "libcore.libcore.icu.RelativeDateTimeFormatterTest#test_getRelativeTimeSpanStringGerman"
+          "org.apache.harmony.tests.java.math.BigIntegerConstructorsTest#testConstructorPrime"
   ]
 }
 ]
diff --git a/tools/libcore_gcstress_failures.txt b/tools/libcore_gcstress_failures.txt
index 9af2f64..6c17e15 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_testdex],
+  modes: [device],
   names: ["libcore.javax.crypto.CipherBasicsTest#testGcmEncryption"]
 },
 {
@@ -26,16 +26,27 @@
 {
   description: "Timeouts.",
   result: EXEC_FAILED,
-  modes: [device_testdex],
+  modes: [device],
   names: ["jsr166.TimeUnitTest#testConvert",
           "libcore.java.lang.StringTest#testFastPathString_wellFormedUtf8Sequence",
-          "libcore.java.text.DecimalFormatTest#testCurrencySymbolSpacing",
+          "libcore.java.math.BigIntegerTest#test_Constructor_IILjava_util_Random",
+          "libcore.java.math.BigIntegerTest#test_probablePrime",
           "libcore.java.text.SimpleDateFormatTest#testLocales",
+          "libcore.java.util.stream.CollectorsTest#counting_largeStream",
           "org.apache.harmony.tests.java.lang.ref.ReferenceQueueTest#test_remove",
-          "org.apache.harmony.tests.java.lang.ProcessManagerTest#testSleep",
           "org.apache.harmony.tests.java.lang.String2Test#test_getBytes",
+          "org.apache.harmony.tests.java.math.BigIntegerConstructorsTest#testConstructorPrime",
           "org.apache.harmony.tests.java.text.DateFormatTest#test_getAvailableLocales",
           "org.apache.harmony.tests.java.util.TimerTest#testOverdueTaskExecutesImmediately",
           "org.apache.harmony.tests.java.util.WeakHashMapTest#test_keySet_hasNext"]
+},
+{
+  description: "Timeouts.",
+  result: EXEC_FAILED,
+  bug: 157520256,
+  modes: [device],
+  names: ["jsr166.ForkJoinPoolTest#testIsQuiescent",
+          "org.apache.harmony.tests.java.util.regex.MatcherTest#testAllCodePoints_P",
+          "org.apache.harmony.tests.java.util.regex.MatcherTest#testAllCodePoints_p"]
 }
 ]
diff --git a/tools/libjavac/Android.bp b/tools/libjavac/Android.bp
deleted file mode 100644
index c93402e..0000000
--- a/tools/libjavac/Android.bp
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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.
-
-// This is a helper library for host tests that compile Java code at test time.
-java_library_host {
-    name: "libjavac",
-
-    visibility: ["//visibility:public"],
-
-    srcs: ["src/**/*.java"],
-
-    static_libs: [
-        "apache-bcel",
-        "guava",
-    ],
-}
diff --git a/tools/libjavac/src/com/android/javac/Javac.java b/tools/libjavac/src/com/android/javac/Javac.java
deleted file mode 100644
index 8ed7278..0000000
--- a/tools/libjavac/src/com/android/javac/Javac.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.javac;
-
-import com.google.common.collect.Lists;
-import com.google.common.io.Files;
-
-import java.util.stream.Collectors;
-import org.apache.bcel.classfile.ClassParser;
-import org.apache.bcel.classfile.JavaClass;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-
-import javax.annotation.processing.Processor;
-import javax.tools.DiagnosticCollector;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.StandardLocation;
-import javax.tools.ToolProvider;
-
-/**
- * Helper class for compiling snippets of Java source and providing access to the resulting class
- * files.
- */
-public class Javac {
-
-    private final JavaCompiler mJavac;
-    private final StandardJavaFileManager mFileMan;
-    private final List<JavaFileObject> mCompilationUnits;
-    private final File mClassOutDir;
-
-    public Javac() throws IOException {
-        mJavac = ToolProvider.getSystemJavaCompiler();
-        mFileMan = mJavac.getStandardFileManager(null, Locale.US, null);
-        mClassOutDir = Files.createTempDir();
-        mFileMan.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(mClassOutDir));
-        mFileMan.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(mClassOutDir));
-        mCompilationUnits = new ArrayList<>();
-    }
-
-    private String classToFileName(String classname) {
-        return classname.replace('.', '/');
-    }
-
-    public Javac addSource(String classname, String contents) {
-        JavaFileObject java = new SimpleJavaFileObject(URI.create(
-                String.format("string:///%s.java", classToFileName(classname))),
-                JavaFileObject.Kind.SOURCE
-                ){
-            @Override
-            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
-                return contents;
-            }
-        };
-        mCompilationUnits.add(java);
-        return this;
-    }
-
-    public void compile() {
-        compileWithAnnotationProcessor(null);
-    }
-
-    public void compileWithAnnotationProcessor(Processor processor) {
-        DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>();
-        JavaCompiler.CompilationTask task = mJavac.getTask(
-                null,
-                mFileMan,
-                diagnosticCollector,
-                null,
-                null,
-                mCompilationUnits);
-        if (processor != null) {
-            task.setProcessors(Lists.newArrayList(processor));
-        }
-        boolean result = task.call();
-        if (!result) {
-            throw new IllegalStateException(
-                    "Compilation failed:" +
-                            diagnosticCollector.getDiagnostics()
-                                    .stream()
-                                    .map(Object::toString)
-                                    .collect(Collectors.joining("\n")));
-        }
-    }
-
-    public InputStream getOutputFile(String filename) throws IOException {
-        Iterable<? extends JavaFileObject> objs = mFileMan.getJavaFileObjects(
-                new File(mClassOutDir, filename));
-        if (!objs.iterator().hasNext()) {
-            return null;
-        }
-        return objs.iterator().next().openInputStream();
-    }
-
-    public InputStream getClassFile(String classname) throws IOException {
-        return getOutputFile(String.format("%s.class", classToFileName(classname)));
-    }
-
-    public JavaClass getCompiledClass(String classname) throws IOException {
-        return new ClassParser(getClassFile(classname),
-                String.format("%s.class", classToFileName(classname))).parse();
-    }
-}
diff --git a/tools/luci/config/cr-buildbucket.cfg b/tools/luci/config/cr-buildbucket.cfg
index 89aeda2..3d873f9 100644
--- a/tools/luci/config/cr-buildbucket.cfg
+++ b/tools/luci/config/cr-buildbucket.cfg
@@ -41,12 +41,17 @@
       build_numbers: YES
       # Some builders require specific hardware, so we make the assignment in bots.cfg
       auto_builder_dimension: YES
-      luci_migration_host: "luci-migration.appspot.com"
       recipe {
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         name: "art"
-        properties: "mastername:client.art"
+        properties: "builder_group:client.art"
+      }
+      # Directory called "art" that persists from build to build (one per bot).
+      # We can checkout and build in this directory to get fast incremental builds.
+      caches {
+        name: "art"
+        path: "art"
       }
     }
 
@@ -69,12 +74,6 @@
       name: "angler-armv8-ndebug"
     }
     builders {
-      name: "aosp-builder-cc"
-    }
-    builders {
-      name: "aosp-builder-cms"
-    }
-    builders {
       name: "bullhead-armv7-gcstress-ndebug"
     }
     builders {
diff --git a/tools/luci/config/luci-milo.cfg b/tools/luci/config/luci-milo.cfg
index 22b4e17..a9ee3a2 100644
--- a/tools/luci/config/luci-milo.cfg
+++ b/tools/luci/config/luci-milo.cfg
@@ -39,16 +39,6 @@
     short_name: "ndbg"
   }
   builders {
-    name: "buildbucket/luci.art.ci/aosp-builder-cc"
-    category: "aosp"
-    short_name: "cc"
-  }
-  builders {
-    name: "buildbucket/luci.art.ci/aosp-builder-cms"
-    category: "aosp"
-    short_name: "cms"
-  }
-  builders {
     name: "buildbucket/luci.art.ci/bullhead-armv7-gcstress-ndebug"
     category: "bullhead|armv7|gcstress"
     short_name: "dbg"
diff --git a/tools/luci/config/luci-notify.cfg b/tools/luci/config/luci-notify.cfg
index 994cdfd..0e7eb89 100644
--- a/tools/luci/config/luci-notify.cfg
+++ b/tools/luci/config/luci-notify.cfg
@@ -40,14 +40,6 @@
     bucket: "ci"
   }
   builders {
-    name: "aosp-builder-cc"
-    bucket: "ci"
-  }
-  builders {
-    name: "aosp-builder-cms"
-    bucket: "ci"
-  }
-  builders {
     name: "bullhead-armv7-gcstress-ndebug"
     bucket: "ci"
   }
diff --git a/tools/luci/config/luci-scheduler.cfg b/tools/luci/config/luci-scheduler.cfg
index 489ba04..de5edc8 100644
--- a/tools/luci/config/luci-scheduler.cfg
+++ b/tools/luci/config/luci-scheduler.cfg
@@ -30,8 +30,6 @@
   triggers: "angler-armv8-debug"
   triggers: "angler-armv8-non-gen-cc"
   triggers: "angler-armv8-ndebug"
-  triggers: "aosp-builder-cc"
-  triggers: "aosp-builder-cms"
   triggers: "bullhead-armv7-gcstress-ndebug"
   triggers: "bullhead-armv8-gcstress-debug"
   triggers: "bullhead-armv8-gcstress-ndebug"
@@ -67,8 +65,6 @@
   triggers: "angler-armv8-debug"
   triggers: "angler-armv8-non-gen-cc"
   triggers: "angler-armv8-ndebug"
-  triggers: "aosp-builder-cc"
-  triggers: "aosp-builder-cms"
   triggers: "bullhead-armv7-gcstress-ndebug"
   triggers: "bullhead-armv8-gcstress-debug"
   triggers: "bullhead-armv8-gcstress-ndebug"
@@ -104,8 +100,6 @@
   triggers: "angler-armv8-debug"
   triggers: "angler-armv8-non-gen-cc"
   triggers: "angler-armv8-ndebug"
-  triggers: "aosp-builder-cc"
-  triggers: "aosp-builder-cms"
   triggers: "bullhead-armv7-gcstress-ndebug"
   triggers: "bullhead-armv8-gcstress-debug"
   triggers: "bullhead-armv8-gcstress-ndebug"
@@ -188,26 +182,6 @@
 }
 
 job {
-  id: "aosp-builder-cc"
-  acl_sets: "default"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.art.ci"
-    builder: "aosp-builder-cc"
-  }
-}
-
-job {
-  id: "aosp-builder-cms"
-  acl_sets: "default"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.art.ci"
-    builder: "aosp-builder-cms"
-  }
-}
-
-job {
   id: "bullhead-armv7-gcstress-ndebug"
   acl_sets: "default"
   buildbucket {
diff --git a/tools/method-to-descriptor.py b/tools/method-to-descriptor.py
new file mode 100755
index 0000000..b0bcf22
--- /dev/null
+++ b/tools/method-to-descriptor.py
@@ -0,0 +1,146 @@
+#!/usr/bin/python3
+#
+# Copyright 2020, 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.
+"""Converts a method to a descriptor or vice-versa.
+
+eg:
+
+% echo 'void myclass.foobar(long, java.lang.Object)' | method-to-descriptor.py
+Lmyclass;->foobar(jLjaga/lang/Object;)V
+% echo 'Lmyclass;->foobar(j)V' | method2descriptor.py -r
+void myclass.foobar(long)
+"""
+
+import argparse
+import sys
+
+
+def GetStdinLineIter():
+  """reads from stdin"""
+  return map(str.strip, sys.stdin)
+
+
+def readDescriptor(s):
+  """Reads a single descriptor and returns the string starting at the point after the descriptor"""
+  if s[0] == "[":
+    inner, rest = readDescriptor(s[1:])
+    return "[" + inner, rest
+  elif s[0] == "L":
+    type_end = s.index(";")
+    return s[:type_end + 1], s[type_end + 1:]
+  else:
+    assert s[0] in {"B", "C", "D", "F", "I", "J", "S", "Z", "V"}, s[0]
+    return s[0], s[1:]
+
+
+# Descriptor to name for basic types
+TYPE_MAP = {
+    "V": "void",
+    "B": "byte",
+    "C": "char",
+    "D": "double",
+    "F": "float",
+    "I": "int",
+    "J": "long",
+    "S": "short",
+    "Z": "boolean"
+}
+
+# Name to descriptor
+DESC_MAP = dict((y, x) for x, y in TYPE_MAP.items())
+
+def TypeDescriptorToName(desc):
+  """Turn a single type descirptor into a name"""
+  if desc[0] == "[":
+    inner = TypeDescriptorToName(desc[1:])
+    return inner + "[]"
+  elif desc[0] == "L":
+    assert desc[-1] == ";", desc
+    return desc[1:-1].replace("/", ".")
+  else:
+    return TYPE_MAP[desc]
+
+def DescriptorToName(desc):
+  """Turn a method descriptor into a name"""
+  class_name, rest = readDescriptor(desc)
+  assert rest[0:2] == "->", desc
+  rest = rest[2:]
+  args_start = rest.index("(")
+  func_name = rest[:args_start]
+  rest = rest[args_start + 1:]
+  args = []
+  while rest[0] != ")":
+    cur_arg, rest = readDescriptor(rest)
+    args.append(cur_arg)
+  rest = rest[1:]
+  return_type, rest = readDescriptor(rest)
+  assert rest.strip() == "", desc
+  return "{} {}.{}({})".format(
+      TypeDescriptorToName(return_type), TypeDescriptorToName(class_name),
+      func_name, ",".join(map(TypeDescriptorToName, args)))
+
+def SingleNameToDescriptor(name):
+  if name in DESC_MAP:
+    return DESC_MAP[name]
+  elif name.endswith("[]"):
+    return "[" + SingleNameToDescriptor(name[:-2])
+  elif name == "":
+    return ""
+  else:
+    return "L" + name.replace(".", "/") + ";"
+
+
+def NameToDescriptor(desc):
+  return_name = desc.split()[0]
+  name_and_args = desc.split()[1]
+  args_start = name_and_args.index("(")
+  names = name_and_args[0:args_start]
+  meth_split = names.rfind(".")
+  class_name = names[:meth_split]
+  meth_name = names[meth_split + 1:]
+  args = map(str.strip, name_and_args[args_start + 1:-1].split(","))
+  return "{}->{}({}){}".format(
+      SingleNameToDescriptor(class_name), meth_name,
+      "".join(map(SingleNameToDescriptor, args)),
+      SingleNameToDescriptor(return_name))
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      "method-to-descriptor.py",
+      description="Convert a java method-name/stream into it's descriptor or vice-versa."
+  )
+  parser.add_argument(
+      "-r",
+      "--reverse",
+      dest="reverse",
+      action="store_true",
+      default=False,
+      help="reverse. Go from descriptor to method-declaration")
+  parser.add_argument("method", help="what to change", nargs="*")
+  args = parser.parse_args()
+  if args.method != []:
+    inputs = iter(args.method)
+  else:
+    inputs = GetStdinLineIter()
+  for name in inputs:
+    if args.reverse:
+      print(DescriptorToName(name))
+    else:
+      print(NameToDescriptor(name))
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/pylibdexfile.py b/tools/pylibdexfile.py
new file mode 100644
index 0000000..83e7685
--- /dev/null
+++ b/tools/pylibdexfile.py
@@ -0,0 +1,193 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2021 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.
+
+#
+# This script can get info out of dexfiles using libdexfile.so external API
+#
+
+from abc import ABC
+from ctypes import *
+import os.path
+import functools
+import zipfile
+
+libdexfile = CDLL(
+    os.path.expandvars("$ANDROID_HOST_OUT/lib64/libdexfiled.so"))
+
+ExtDexFile = c_void_p
+
+class ExtMethodInfo(Structure):
+  """Output format for MethodInfo"""
+  _fields_ = [("sizeof_struct", c_size_t),
+              ("addr", c_int32),
+              ("size", c_int32),
+              ("name", POINTER(c_char)),
+              ("name_size", c_size_t)]
+
+AllMethodsCallback = CFUNCTYPE(c_int, c_void_p, POINTER(ExtMethodInfo))
+libdexfile.ExtDexFileOpenFromMemory.argtypes = [
+    c_void_p,
+    POINTER(c_size_t),
+    c_char_p,
+    POINTER(ExtDexFile)
+]
+libdexfile.ExtDexFileOpenFromMemory.restype = c_int
+libdexfile.ExtDexFileGetAllMethodInfos.argtypes = [
+    ExtDexFile, c_int, AllMethodsCallback, c_void_p
+]
+
+class DexClass(object):
+  """Accessor for DexClass Data"""
+
+  def __init__(self, name):
+    self.name = name.strip()
+    self.arrays = name.count("[")
+    self.base_name = self.name if self.arrays == 0 else self.name[:-(
+        self.arrays * 2)]
+
+  def __repr__(self):
+    return self.name
+
+  @functools.cached_property
+  def descriptor(self):
+    """The name as a descriptor"""
+    if self.base_name == "int":
+      return "[" * self.arrays + "I"
+    elif self.base_name == "short":
+      return "[" * self.arrays + "S"
+    elif self.base_name == "long":
+      return "[" * self.arrays + "J"
+    elif self.base_name == "char":
+      return "[" * self.arrays + "C"
+    elif self.base_name == "boolean":
+      return "[" * self.arrays + "Z"
+    elif self.base_name == "byte":
+      return "[" * self.arrays + "B"
+    elif self.base_name == "float":
+      return "[" * self.arrays + "F"
+    elif self.base_name == "double":
+      return "[" * self.arrays + "D"
+    elif self.base_name == "void":
+      return "[" * self.arrays + "V"
+    else:
+      return "[" * self.arrays + "L{};".format("/".join(
+          self.base_name.split(".")))
+
+
+class Method(object):
+  """Method info wrapper"""
+
+  def __init__(self, mi):
+    self.offset = mi.addr
+    self.len = mi.size
+    self.name = string_at(mi.name, mi.name_size).decode("utf-8")
+
+  def __repr__(self):
+    return "(" + self.name + ")"
+
+  @functools.cached_property
+  def descriptor(self):
+    """name as a descriptor"""
+    ret = DexClass(self.name.split(" ")[0])
+    non_ret = self.name[len(ret.name) + 1:]
+    arg_str = non_ret[non_ret.find("(") + 1:-1]
+    args = [] if arg_str == "" else map(
+        lambda a: DexClass(a.strip()).descriptor, arg_str.split(","))
+    class_and_meth = non_ret[0:non_ret.find("(")]
+    class_only = DexClass(class_and_meth[0:class_and_meth.rfind(".")])
+    meth = class_and_meth[class_and_meth.rfind(".") + 1:]
+    return "{cls}->{meth}({args}){ret}".format(
+        cls=class_only.descriptor,
+        meth=meth,
+        args="".join(args),
+        ret=ret.descriptor)
+
+  @functools.cached_property
+  def name_only(self):
+    """name without the return-type or arguments in java format"""
+    ret = DexClass(self.name.split(" ")[0])
+    non_ret = self.name[len(ret.name) + 1:]
+    class_and_meth = non_ret[0:non_ret.find("(")]
+    return class_and_meth
+
+  @functools.cached_property
+  def klass(self):
+    """declaring DexClass."""
+    ret = DexClass(self.name.split(" ")[0])
+    non_ret = self.name[len(ret.name) + 1:]
+    class_and_meth = non_ret[0:non_ret.find("(")]
+    return DexClass(class_and_meth[0:class_and_meth.rfind(".")])
+
+
+class BaseDexFile(ABC):
+  """DexFile base class"""
+
+  def __init__(self):
+    self.ext_dex_file_ = None
+    return
+
+  @functools.cached_property
+  def methods(self):
+    """Methods in the dex-file"""
+    meths = []
+
+    @AllMethodsCallback
+    def my_cb(_, info):
+      """Callback visitor for method infos"""
+      meths.append(Method(info[0]))
+      return 0
+
+    libdexfile.ExtDexFileGetAllMethodInfos(self.ext_dex_file_,
+                                           c_int(1), my_cb, c_void_p())
+    return meths
+
+class MemDexFile(BaseDexFile):
+  """DexFile using memory"""
+
+  def __init__(self, dat, loc):
+    assert type(dat) == bytes
+    super().__init__()
+    # Don't want GC to screw us over.
+    self.mem_ref = (c_byte * len(dat)).from_buffer_copy(dat)
+    res_fle_ptr = pointer(c_void_p())
+    res = libdexfile.ExtDexFileOpenFromMemory(
+        self.mem_ref, byref(c_size_t(len(dat))),
+        create_string_buffer(bytes(loc, "utf-8")), res_fle_ptr)
+    if res != 0:
+      raise Exception("Failed to open file: {}. Error {}.".format(loc, res))
+    self.ext_dex_file_ = res_fle_ptr.contents
+
+class FileDexFile(MemDexFile):
+  """DexFile using a file"""
+
+  def __init__(self, file, loc):
+    if type(file) == str:
+      self.file = open(file, "rb")
+      self.loc = file
+    else:
+      self.file = file
+      self.loc = "file_obj"
+    super().__init__(self.file.read(), self.loc)
+
+def OpenJar(fle):
+  """Opens all classes[0-9]*.dex files in a zip archive"""
+  res = []
+  with zipfile.ZipFile(fle) as zf:
+    for f in zf.namelist():
+      if f.endswith(".dex") and f.startswith("classes"):
+        res.append(
+            MemDexFile(zf.read(f), "classes" if type(fle) != str else fle))
+  return res
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index 9ad9d66..4d6e135 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -40,18 +40,25 @@
   local separator=""
   for var
   do
-    printf -- "${separator}${dir}/${var}${suffix}.jar";
+    if [ "$var" = "conscrypt" ] && [ "$mode" = "target" ]; then
+      printf -- "${separator}/apex/com.android.conscrypt/javalib/conscrypt.jar";
+    elif [ "$var" = "core-icu4j" ] && [ "$mode" = "target" ]; then
+      printf -- "${separator}/apex/com.android.i18n/javalib/core-icu4j.jar";
+    else
+      printf -- "${separator}${dir}/${var}${suffix}.jar";
+    fi
     separator=":"
   done
 }
 
 # 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.
+# because that's what we use for compiling the boot.art image.
 # It may contain additional modules from TEST_CORE_JARS.
-BOOT_CLASSPATH_JARS="core-oj core-libart core-icu4j okhttp bouncycastle apache-xml conscrypt"
+BOOT_CLASSPATH_JARS="core-oj core-libart okhttp bouncycastle apache-xml core-icu4j conscrypt"
 
 vm_args=""
 art="$android_root/bin/art"
+mode="target"
 art_debugee="sh $android_root/bin/art"
 args=$@
 chroot_option=
@@ -65,8 +72,8 @@
 debug="no"
 explicit_debug="no"
 verbose="no"
-image="-Ximage:/data/art-test/core.art"
-boot_classpath="$(boot_classpath_arg /system/framework -testdex $BOOT_CLASSPATH_JARS)"
+image="-Ximage:/apex/com.android.art/javalib/boot.art"
+boot_classpath="$(boot_classpath_arg /apex/com.android.art/javalib "" $BOOT_CLASSPATH_JARS)"
 boot_classpath_locations=""
 with_jdwp_path=""
 agent_wrapper=""
@@ -74,7 +81,6 @@
 # By default, we run the whole JDWP test suite.
 has_specific_test="no"
 test="org.apache.harmony.jpda.tests.share.AllTests"
-mode="target"
 # Use JIT compiling by default.
 use_jit=true
 instant_jit=false
@@ -122,11 +128,6 @@
     # 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"
diff --git a/tools/run-libcore-tests.py b/tools/run-libcore-tests.py
new file mode 100755
index 0000000..afbc62f
--- /dev/null
+++ b/tools/run-libcore-tests.py
@@ -0,0 +1,269 @@
+#!/usr/bin/env python3
+#
+# [VPYTHON:BEGIN]
+# python_version: "3.8"
+# [VPYTHON:END]
+#
+# Copyright (C) 2021 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 sys, os, argparse, subprocess, shlex, re, concurrent.futures, multiprocessing
+
+def parse_args():
+  parser = argparse.ArgumentParser(description="Run libcore tests using the vogar testing tool.")
+  parser.add_argument('--mode', choices=['device', 'host', 'jvm'], required=True,
+                      help='Specify where tests should be run.')
+  parser.add_argument('--variant', choices=['X32', 'X64'],
+                      help='Which dalvikvm variant to execute with.')
+  parser.add_argument('-j', '--jobs', type=int,
+                      help='Number of tests to run simultaneously.')
+  parser.add_argument('--timeout', type=int,
+                      help='How long to run the test before aborting (seconds).')
+  parser.add_argument('--debug', action='store_true',
+                      help='Use debug version of ART (device|host only).')
+  parser.add_argument('--dry-run', action='store_true',
+                      help='Print vogar command-line, but do not run.')
+  parser.add_argument('--no-getrandom', action='store_false', dest='getrandom',
+                      help='Ignore failures from getrandom() (for kernel < 3.17).')
+  parser.add_argument('--no-jit', action='store_false', dest='jit',
+                      help='Disable JIT (device|host only).')
+  parser.add_argument('--gcstress', action='store_true',
+                      help='Enable GC stress configuration (device|host only).')
+  parser.add_argument('tests', nargs="*",
+                      help='Name(s) of the test(s) to run')
+  return parser.parse_args()
+
+ART_TEST_ANDROID_ROOT = os.environ.get("ART_TEST_ANDROID_ROOT", "/system")
+ART_TEST_CHROOT = os.environ.get("ART_TEST_CHROOT")
+ANDROID_PRODUCT_OUT = os.environ.get("ANDROID_PRODUCT_OUT")
+
+LIBCORE_TEST_NAMES = [
+  # Naive critical path optimization: Run the longest tests first.
+  "org.apache.harmony.tests.java.util",  # 90min under gcstress
+  "libcore.java.lang",                   # 90min under gcstress
+  "jsr166",                              # 60min under gcstress
+  "libcore.java.util",                   # 60min under gcstress
+  "libcore.java.math",                   # 50min under gcstress
+  "org.apache.harmony.crypto",           # 30min under gcstress
+  "org.apache.harmony.tests.java.io",    # 30min under gcstress
+  "org.apache.harmony.tests.java.text",  # 30min under gcstress
+  # Split highmemorytest to individual classes since it is too big.
+  "libcore.highmemorytest.java.text.DateFormatTest",
+  "libcore.highmemorytest.java.text.DecimalFormatTest",
+  "libcore.highmemorytest.java.text.SimpleDateFormatTest",
+  "libcore.highmemorytest.java.time.format.DateTimeFormatterTest",
+  "libcore.highmemorytest.java.util.CalendarTest",
+  "libcore.highmemorytest.java.util.CurrencyTest",
+  "libcore.highmemorytest.libcore.icu.LocaleDataTest",
+  # All other tests in alphabetical order.
+  "libcore.android.system",
+  "libcore.build",
+  "libcore.dalvik.system",
+  "libcore.java.awt",
+  "libcore.java.text",
+  "libcore.javax.crypto",
+  "libcore.javax.net",
+  "libcore.javax.security",
+  "libcore.javax.sql",
+  "libcore.javax.xml",
+  "libcore.libcore.icu",
+  "libcore.libcore.internal",
+  "libcore.libcore.io",
+  "libcore.libcore.net",
+  "libcore.libcore.reflect",
+  "libcore.libcore.util",
+  "libcore.sun.invoke",
+  "libcore.sun.misc",
+  "libcore.sun.net",
+  "libcore.sun.security",
+  "libcore.sun.util",
+  "libcore.xml",
+  "org.apache.harmony.annotation",
+  "org.apache.harmony.luni",
+  "org.apache.harmony.nio",
+  "org.apache.harmony.regex",
+  "org.apache.harmony.testframework",
+  "org.apache.harmony.tests.java.lang",
+  "org.apache.harmony.tests.java.math",
+  "org.apache.harmony.tests.javax.security",
+  "tests.java.lang.String",
+]
+# "org.apache.harmony.security",  # We don't have rights to revert changes in case of failures.
+
+# Note: This must start with the CORE_IMG_JARS in Android.common_path.mk
+# because that's what we use for compiling the boot.art image.
+# It may contain additional modules from TEST_CORE_JARS.
+BOOT_CLASSPATH = [
+  "/apex/com.android.art/javalib/core-oj.jar",
+  "/apex/com.android.art/javalib/core-libart.jar",
+  "/apex/com.android.art/javalib/okhttp.jar",
+  "/apex/com.android.art/javalib/bouncycastle.jar",
+  "/apex/com.android.art/javalib/apache-xml.jar",
+  "/apex/com.android.i18n/javalib/core-icu4j.jar",
+  "/apex/com.android.conscrypt/javalib/conscrypt.jar",
+]
+
+CLASSPATH = ["core-tests", "jsr166-tests", "mockito-target"]
+
+def get_jar_filename(classpath):
+  base_path = (ANDROID_PRODUCT_OUT + "/../..") if ANDROID_PRODUCT_OUT else "out/target"
+  base_path = os.path.normpath(base_path)  # Normalize ".." components for readability.
+  return f"{base_path}/common/obj/JAVA_LIBRARIES/{classpath}_intermediates/classes.jar"
+
+def get_timeout_secs():
+  default_timeout_secs = 600
+  if args.mode == "device" and args.gcstress:
+    default_timeout_secs = 1200
+    if args.debug:
+      default_timeout_secs = 1800
+  return args.timeout or default_timeout_secs
+
+def get_expected_failures():
+  failures = ["art/tools/libcore_failures.txt"]
+  if args.mode != "jvm":
+    if args.gcstress:
+      failures.append("art/tools/libcore_gcstress_failures.txt")
+    if args.gcstress and args.debug:
+      failures.append("art/tools/libcore_gcstress_debug_failures.txt")
+    if args.debug and not args.gcstress and args.getrandom:
+      failures.append("art/tools/libcore_debug_failures.txt")
+    if not args.getrandom:
+      failures.append("art/tools/libcore_fugu_failures.txt")
+  return failures
+
+def get_test_names():
+  if args.tests:
+    return args.tests
+  test_names = list(LIBCORE_TEST_NAMES)
+  # See b/78228743 and b/178351808.
+  if args.gcstress or args.debug or args.mode == "jvm":
+    test_names = list(t for t in test_names if not t.startswith("libcore.highmemorytest"))
+  return test_names
+
+def get_vogar_command(test_name):
+  cmd = ["vogar"]
+  if args.mode == "device":
+    cmd.append("--mode=device --vm-arg -Ximage:/apex/com.android.art/javalib/boot.art")
+    cmd.append("--vm-arg -Xbootclasspath:" + ":".join(BOOT_CLASSPATH))
+  if args.mode == "host":
+    # We explicitly give a wrong path for the image, to ensure vogar
+    # will create a boot image with the default compiler. Note that
+    # giving an existing image on host does not work because of
+    # classpath/resources differences when compiling the boot image.
+    cmd.append("--mode=host --vm-arg -Ximage:/non/existent/vogar.art")
+  if args.mode == "jvm":
+    cmd.append("--mode=jvm")
+  if args.variant:
+    cmd.append("--variant=" + args.variant)
+  if args.gcstress:
+    cmd.append("--vm-arg -Xgc:gcstress")
+  if args.debug:
+    cmd.append("--vm-arg -XXlib:libartd.so --vm-arg -XX:SlowDebug=true")
+
+  if args.mode == "device":
+    if ART_TEST_CHROOT:
+      cmd.append(f"--chroot {ART_TEST_CHROOT} --device-dir=/tmp/vogar/test-{test_name}")
+    else:
+      cmd.append("--device-dir=/data/local/tmp/vogar/test-{test_name}")
+    cmd.append(f"--vm-command={ART_TEST_ANDROID_ROOT}/bin/art")
+  else:
+    cmd.append(f"--device-dir=/tmp/vogar/test-{test_name}")
+
+  if args.mode != "jvm":
+    cmd.append("--timeout {}".format(get_timeout_secs()))
+
+    # Suppress explicit gc logs that are triggered an absurd number of times by these tests.
+    cmd.append("--vm-arg -XX:AlwaysLogExplicitGcs:false")
+    cmd.append("--toolchain d8 --language CUR")
+    if args.jit:
+      cmd.append("--vm-arg -Xcompiler-option --vm-arg --compiler-filter=quicken")
+    cmd.append("--vm-arg -Xusejit:{}".format(str(args.jit).lower()))
+
+    if args.gcstress:
+      # Bump pause threshold as long pauses cause explicit gc logging to occur irrespective
+      # of -XX:AlwayLogExplicitGcs:false.
+      cmd.append("--vm-arg -XX:LongPauseLogThreshold=15") # 15 ms (default: 5ms))
+
+  # Suppress color codes if not attached to a terminal
+  if not sys.stdout.isatty():
+    cmd.append("--no-color")
+
+  cmd.extend("--expectations " + f for f in get_expected_failures())
+  cmd.extend("--classpath " + get_jar_filename(cp) for cp in CLASSPATH)
+  cmd.append(test_name)
+  return cmd
+
+def get_target_cpu_count():
+  adb_command = 'adb shell cat /sys/devices/system/cpu/present'
+  with subprocess.Popen(adb_command.split(),
+                        stderr=subprocess.STDOUT,
+                        stdout=subprocess.PIPE,
+                        universal_newlines=True) as proc:
+    assert(proc.wait() == 0)  # Check the exit code.
+    match = re.match(r'\d*-(\d*)', proc.stdout.read())
+    assert(match)
+    return int(match.group(1)) + 1  # Add one to convert from "last-index" to "count"
+
+def main():
+  global args
+  args = parse_args()
+
+  if not os.path.exists('build/envsetup.sh'):
+    raise AssertionError("Script needs to be run at the root of the android tree")
+  for jar in map(get_jar_filename, CLASSPATH):
+    if not os.path.exists(jar):
+      raise AssertionError(f"Missing {jar}. Run buildbot-build.sh first.")
+
+  if not args.jobs:
+    if args.mode == "device":
+      args.jobs = get_target_cpu_count()
+    else:
+      args.jobs = multiprocessing.cpu_count()
+      if args.gcstress:
+        # TODO: Investigate and fix the underlying issues.
+        args.jobs = args.jobs // 2
+
+  def run_test(test_name):
+    cmd = " ".join(get_vogar_command(test_name))
+    if args.dry_run:
+      return test_name, cmd, "Dry-run: skipping execution", 0
+    with subprocess.Popen(shlex.split(cmd),
+                          stderr=subprocess.STDOUT,
+                          stdout=subprocess.PIPE,
+                          universal_newlines=True) as proc:
+      return test_name, cmd, proc.communicate()[0], proc.wait()
+
+  failed_regex = re.compile(r"^.* FAIL \((?:EXEC_FAILED|ERROR)\)$", re.MULTILINE)
+  failed_tests, max_exit_code = [], 0
+  with concurrent.futures.ThreadPoolExecutor(max_workers=args.jobs) as pool:
+    futures = [pool.submit(run_test, test_name) for test_name in get_test_names()]
+    print(f"Running {len(futures)} tasks on {args.jobs} core(s)...\n")
+    for i, future in enumerate(concurrent.futures.as_completed(futures)):
+      test_name, cmd, stdout, exit_code = future.result()
+      if exit_code != 0 or args.dry_run:
+        print(cmd)
+        print(stdout.strip())
+      else:
+        print(stdout.strip().split("\n")[-1])  # Vogar final summary line.
+      failed_match = failed_regex.findall(stdout)
+      failed_tests.extend(failed_match)
+      max_exit_code = max(max_exit_code, exit_code)
+      result = "PASSED" if exit_code == 0 else f"FAILED ({len(failed_match)} test(s) failed)"
+      print(f"[{i+1}/{len(futures)}] Test set {test_name} {result}\n")
+  print(f"Overall, {len(failed_tests)} test(s) failed:")
+  print("\n".join(failed_tests))
+  sys.exit(max_exit_code)
+
+if __name__ == '__main__':
+  main()
diff --git a/tools/run-libcore-tests.sh b/tools/run-libcore-tests.sh
index 726b12d..7cbf5ea 100755
--- a/tools/run-libcore-tests.sh
+++ b/tools/run-libcore-tests.sh
@@ -14,309 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Exit on errors.
-set -e
-
-if [ ! -d libcore ]; then
-  echo "Script needs to be run at the root of the android tree"
-  exit 1
-fi
-
-# "Root" (actually "system") directory on device (in the case of
-# target testing).
-android_root=${ART_TEST_ANDROID_ROOT:-/system}
-
-function classes_jar_path {
-  local var="$1"
-  local suffix="jar"
-  if [ -z "$ANDROID_PRODUCT_OUT" ] ; then
-    local java_libraries=out/target/common/obj/JAVA_LIBRARIES
-  else
-    local java_libraries=${ANDROID_PRODUCT_OUT}/../../common/obj/JAVA_LIBRARIES
-  fi
-  echo "${java_libraries}/${var}_intermediates/classes.${suffix}"
-}
-
-function cparg {
-  for var
-  do
-    printf -- "--classpath $(classes_jar_path "$var") ";
-  done
-}
-
-function boot_classpath_arg {
-  local dir="$1"
-  local suffix="$2"
-  shift 2
-  printf -- "--vm-arg -Xbootclasspath"
-  for var
-  do
-    printf -- ":${dir}/${var}${suffix}.jar";
-  done
-}
-
-function usage {
-  local me=$(basename "${BASH_SOURCE[0]}")
-  (
-    cat << EOF
-  Usage: ${me} --mode=<mode> [options] [-- <package_to_test> ...]
-
-  Run libcore tests using the vogar testing tool.
-
-  Required parameters:
-    --mode=device|host|jvm Specify where tests should be run.
-
-  Optional parameters:
-    --debug                Use debug version of ART (device|host only).
-    --dry-run              Print vogar command-line, but do not run.
-    --no-getrandom         Ignore failures from getrandom() (for kernel < 3.17).
-    --no-jit               Disable JIT (device|host only).
-    --Xgc:gcstress         Enable GC stress configuration (device|host only).
-
-  The script passes unrecognized options to the command-line created for vogar.
-
-  The script runs a hardcoded list of libcore test packages by default. The user
-  may run a subset of packages by appending '--' followed by a list of package
-  names.
-
-  Examples:
-
-    1. Run full test suite on host:
-      ${me} --mode=host
-
-    2. Run full test suite on device:
-      ${me} --mode=device
-
-    3. Run tests only from the libcore.java.lang package on device:
-      ${me} --mode=device -- libcore.java.lang
-EOF
-  ) | sed -e 's/^  //' >&2 # Strip leading whitespace from heredoc.
-}
-
-# Packages that currently work correctly with the expectation files.
-working_packages=("libcore.android.system"
-                  "libcore.build"
-                  "libcore.dalvik.system"
-                  "libcore.java.awt"
-                  "libcore.java.lang"
-                  "libcore.java.math"
-                  "libcore.java.text"
-                  "libcore.java.util"
-                  "libcore.javax.crypto"
-                  "libcore.javax.net"
-                  "libcore.javax.security"
-                  "libcore.javax.sql"
-                  "libcore.javax.xml"
-                  "libcore.libcore.internal"
-                  "libcore.libcore.io"
-                  "libcore.libcore.net"
-                  "libcore.libcore.reflect"
-                  "libcore.libcore.util"
-                  "libcore.libcore.timezone"
-                  "libcore.sun.invoke"
-                  "libcore.sun.net"
-                  "libcore.sun.misc"
-                  "libcore.sun.security"
-                  "libcore.sun.util"
-                  "libcore.xml"
-                  "org.apache.harmony.annotation"
-                  "org.apache.harmony.crypto"
-                  "org.apache.harmony.luni"
-                  "org.apache.harmony.nio"
-                  "org.apache.harmony.regex"
-                  "org.apache.harmony.testframework"
-                  "org.apache.harmony.tests.java.io"
-                  "org.apache.harmony.tests.java.lang"
-                  "org.apache.harmony.tests.java.math"
-                  "org.apache.harmony.tests.java.util"
-                  "org.apache.harmony.tests.java.text"
-                  "org.apache.harmony.tests.javax.security"
-                  "tests.java.lang.String"
-                  "jsr166")
-
-# List of packages we could run, but don't have rights to revert
-# changes in case of failures.
-# "org.apache.harmony.security"
-
-#
-# Setup environment for running tests.
-#
-source build/envsetup.sh >&/dev/null # for get_build_var, setpaths
-setpaths # include platform prebuilt java, javac, etc in $PATH.
-
-# 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.
-BOOT_CLASSPATH_JARS="core-oj core-libart core-icu4j okhttp bouncycastle apache-xml conscrypt"
-
-DEPS="core-tests jsr166-tests mockito-target"
-
-for lib in $DEPS
-do
-  if [[ ! -f "$(classes_jar_path "$lib")" ]]; then
-    echo "${lib} is missing. Before running, you must run art/tools/buildbot-build.sh"
-    exit 1
-  fi
-done
-
-#
-# Defaults affected by command-line parsing
-#
-
-# Use JIT compiling by default.
-use_jit=true
-
-gcstress=false
-debug=false
-dry_run=false
-
-# Run tests that use the getrandom() syscall? (Requires Linux 3.17+).
-getrandom=true
-
-# Execution mode specifies where to run tests (device|host|jvm).
-execution_mode=""
-
-# Default expectations file.
-expectations="--expectations art/tools/libcore_failures.txt"
-
-vogar_args=""
-while [ -n "$1" ]; do
-  case "$1" in
-    --mode=device)
-      # Use --mode=device_testdex not --mode=device for buildbot-build.sh.
-      # See commit 191cae33c7c24e for more details.
-      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)"
-      execution_mode="device"
-      ;;
-    --mode=host)
-      # We explicitly give a wrong path for the image, to ensure vogar
-      # will create a boot image with the default compiler. Note that
-      # giving an existing image on host does not work because of
-      # classpath/resources differences when compiling the boot image.
-      vogar_args="$vogar_args $1 --vm-arg -Ximage:/non/existent/vogar.art"
-      execution_mode="host"
-      ;;
-    --mode=jvm)
-      vogar_args="$vogar_args $1"
-      execution_mode="jvm"
-      ;;
-    --no-getrandom)
-      getrandom=false
-      ;;
-    --no-jit)
-      use_jit=false
-      ;;
-    --debug)
-      vogar_args="$vogar_args --vm-arg -XXlib:libartd.so --vm-arg -XX:SlowDebug=true"
-      debug=true
-      ;;
-    -Xgc:gcstress)
-      vogar_args="$vogar_args $1"
-      gcstress=true
-      ;;
-    --dry-run)
-      dry_run=true
-      ;;
-    --)
-      shift
-      # Assume remaining elements are packages to test.
-      user_packages=("$@")
-      break
-      ;;
-    --help)
-      usage
-      exit 1
-      ;;
-    *)
-      vogar_args="$vogar_args $1"
-      ;;
-  esac
-  shift
-done
-
-if [ -z "$execution_mode" ]; then
-  usage
-  exit 1
-fi
-
-# Default timeout, gets overridden on device under gcstress.
-timeout_secs=480
-
-if [ $execution_mode = "device" ]; then
-  # Honor environment variable ART_TEST_CHROOT.
-  if [[ -n "$ART_TEST_CHROOT" ]]; then
-    # Set Vogar's `--chroot` option.
-    vogar_args="$vogar_args --chroot $ART_TEST_CHROOT"
-    vogar_args="$vogar_args --device-dir=/tmp"
-  else
-    # When not using a chroot on device, set Vogar's work directory to
-    # /data/local/tmp.
-    vogar_args="$vogar_args --device-dir=/data/local/tmp"
-  fi
-  vogar_args="$vogar_args --vm-command=$android_root/bin/art"
-
-  # Increase the timeout, as vogar cannot set individual test
-  # timeout when being asked to run packages, and some tests go above
-  # the default timeout.
-  if $gcstress; then
-    if $debug; then
-      timeout_secs=1440
-    else
-      timeout_secs=900
-    fi
-  fi
-fi  # $execution_mode = "device"
-
-if [ $execution_mode = "device" -o $execution_mode = "host" ]; then
-  # Add timeout to vogar command-line.
-  vogar_args="$vogar_args --timeout $timeout_secs"
-
-  # set the toolchain to use.
-  vogar_args="$vogar_args --toolchain d8 --language CUR"
-
-  # JIT settings.
-  if $use_jit; then
-    vogar_args="$vogar_args --vm-arg -Xcompiler-option --vm-arg --compiler-filter=quicken"
-  fi
-  vogar_args="$vogar_args --vm-arg -Xusejit:$use_jit"
-
-  # gcstress may lead to timeouts, so we need dedicated expectations files for it.
-  if $gcstress; then
-    expectations="$expectations --expectations art/tools/libcore_gcstress_failures.txt"
-    if $debug; then
-      expectations="$expectations --expectations art/tools/libcore_gcstress_debug_failures.txt"
-    fi
-  else
-    # We only run this package when user has not specified packages
-    # to run and not under gcstress as it can cause timeouts. See
-    # b/78228743.
-    working_packages+=("libcore.libcore.icu")
-  fi
-
-  if $getrandom; then :; else
-    # Ignore failures in tests that use the system calls not supported
-    # on fugu (Nexus Player, kernel version Linux 3.10).
-    expectations="$expectations --expectations art/tools/libcore_fugu_failures.txt"
-  fi
-fi
-
-if [ ! -t 1 ] ; then
-  # Suppress color codes if not attached to a terminal
-  vogar_args="$vogar_args --no-color"
-fi
-
-# Override working_packages if user provided specific packages to
-# test.
-if [[ ${#user_packages[@]} != 0 ]] ; then
-  working_packages=("${user_packages[@]}")
-fi
-
-# Run the tests using vogar.
-echo "Running tests for the following test packages:"
-echo ${working_packages[@]} | tr " " "\n"
-
-cmd="vogar $vogar_args $expectations $(cparg $DEPS) ${working_packages[@]}"
-echo "Running $cmd"
-$dry_run || eval $cmd
+art/tools/run-libcore-tests.py "$@"
diff --git a/tools/run-libjdwp-tests.sh b/tools/run-libjdwp-tests.sh
index b816aab..ce70ea2 100755
--- a/tools/run-libjdwp-tests.sh
+++ b/tools/run-libjdwp-tests.sh
@@ -40,6 +40,7 @@
 has_variant="no"
 has_mode="no"
 mode="target"
+has_gcstress="no"
 has_timeout="no"
 has_verbose="no"
 # The bitmap of log messages in libjdwp. See list in the help message for more
@@ -87,6 +88,9 @@
   elif [[ $1 == --variant=* ]]; then
     has_variant="yes"
     shift
+  elif [[ $1 == *gcstress ]]; then
+    has_gcstress="yes"
+    shift
   elif [[ "$1" == "" ]]; then
     break
   else
@@ -106,11 +110,12 @@
 if [[ "$has_timeout" = "no" ]]; then
   # Double the timeout to 20 seconds
   args+=(--test-timeout-ms)
-  if [[ "$has_verbose" = "no" ]]; then
-    args+=(20000)
+  if [[ "$has_verbose" = "yes" || "$has_gcstress" = "yes" ]]; then
+    # Extra time if verbose or gcstress is set since those can be
+    # quite heavy.
+    args+=(300000)
   else
-    # Even more time if verbose is set since those can be quite heavy.
-    args+=(200000)
+    args+=(20000)
   fi
 fi
 
diff --git a/tools/signal_dumper/Android.bp b/tools/signal_dumper/Android.bp
index e727f9f..33450d1 100644
--- a/tools/signal_dumper/Android.bp
+++ b/tools/signal_dumper/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "signal_dumper_libbase_static_deps",
     static_libs: ["liblog"],
@@ -21,13 +30,22 @@
 
 cc_defaults {
     name: "signal_dumper_libunwindstack_static_deps",
-    defaults: ["signal_dumper_libbase_static_deps"],
+    defaults: [
+        "libdexfile_support_static_defaults",
+        "signal_dumper_libbase_static_deps",
+    ],
     static_libs: [
         "libbase",
-        "libdexfile_support_static",
         "liblog",
         "liblzma",
     ],
+    target: {
+        bionic: {
+            whole_static_libs: [
+                "libasync_safe",
+            ],
+        },
+    },
 }
 
 cc_defaults {
diff --git a/tools/symbolize.sh b/tools/symbolize.sh
index f5686e6..2b6a5a1 100755
--- a/tools/symbolize.sh
+++ b/tools/symbolize.sh
@@ -26,7 +26,7 @@
 fi
 
 # Pull the file from the device and symbolize it.
-function one() {
+one() {
   echo $1 $2
   if [ "x$INTERACTIVE" = "xyes" ] ; then
     echo -n "What to do? [Y/n/q] "
@@ -39,17 +39,20 @@
     fi
   fi
   adb pull $1/$2 /tmp || exit 1
+  # pull vdex file for oatdump
+  vdex=${2%.*}.vdex
+  adb pull $1/$vdex /tmp/ 2>/dev/null
   mkdir -p $OUT/symbols/$1
   oatdump --symbolize=/tmp/$2 --output=$OUT/symbols/$1/$2
 }
 
 # adb shell find seems to output in DOS format (CRLF), which messes up scripting
-function adbshellstrip() {
+adbshellstrip() {
   adb shell $@ | sed 's/\r$//'
 }
 
 # Search in all of /data on device.
-function all() {
+all() {
   FILES=$(adbshellstrip find /data -name "'*.oat'" -o -name "'*.dex'" -o -name "'*.odex'")
   for FILE in $FILES ; do
     DIR=$(dirname $FILE)
diff --git a/tools/tracefast-plugin/Android.bp b/tools/tracefast-plugin/Android.bp
index 7cdf1dc..21cb0a7 100644
--- a/tools/tracefast-plugin/Android.bp
+++ b/tools/tracefast-plugin/Android.bp
@@ -16,6 +16,15 @@
 
 // Build variants {target,host} x {debug,ndebug} x {32,64}
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_defaults {
     name: "tracefast-defaults",
     host_supported: true,
diff --git a/tools/veridex/Android.bp b/tools/veridex/Android.bp
index 1640a46..d5f5162 100644
--- a/tools/veridex/Android.bp
+++ b/tools/veridex/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "art_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["art_license"],
+}
+
 cc_binary {
     name: "veridex",
     defaults: ["art_defaults"],
diff --git a/tools/veridex/Android.mk b/tools/veridex/Android.mk
index c510a51..a298af4 100644
--- a/tools/veridex/Android.mk
+++ b/tools/veridex/Android.mk
@@ -14,6 +14,8 @@
 # limitations under the License.
 #
 
+# TODO(b/172480617): Clean up the platform dependencies on this.
+
 LOCAL_PATH := $(call my-dir)
 
 # The veridex tool takes stub dex files as input, so we generate both the system and oahl
diff --git a/tools/veridex/appcompat.sh b/tools/veridex/appcompat.sh
index ce90c06..8cbec92 100755
--- a/tools/veridex/appcompat.sh
+++ b/tools/veridex/appcompat.sh
@@ -28,7 +28,7 @@
   exec ${SCRIPT_DIR}/veridex \
     --core-stubs=${SCRIPT_DIR}/system-stubs.zip:${SCRIPT_DIR}/org.apache.http.legacy-stubs.zip \
     --api-flags=${SCRIPT_DIR}/hiddenapi-flags.csv \
-    --exclude-api-lists=whitelist,invalid \
+    --exclude-api-lists=sdk,invalid \
     $@
 fi
 
@@ -72,7 +72,7 @@
 
 # If --exclude-api-lists is not passed directly, exclude whitelist APIs.
 if [[ "$@" != "*--exclude-api-lists=*" ]]; then
-  extra_flags="${extra_flags} --exclude-api-lists=whitelist,invalid"
+  extra_flags="${extra_flags} --exclude-api-lists=sdk,invalid"
 fi
 
 ${ANDROID_HOST_OUT}/bin/veridex \
diff --git a/tools/veridex/flow_analysis.cc b/tools/veridex/flow_analysis.cc
index 65f2363..2a8b8a0 100644
--- a/tools/veridex/flow_analysis.cc
+++ b/tools/veridex/flow_analysis.cc
@@ -47,6 +47,9 @@
 }
 
 bool VeriFlowAnalysis::MergeRegisterValues(uint32_t dex_pc) {
+  if (dex_pc >= code_item_accessor_.InsnsSizeInCodeUnits()) {
+    return false;
+  }
   // TODO: Do the merging. Right now, just return that we should continue
   // the iteration if the instruction has not been visited.
   if (!instruction_infos_[dex_pc].has_been_visited) {
@@ -85,9 +88,14 @@
   }
 
   // Iterate over all instructions and find branching instructions.
+  const uint32_t max_pc = code_item_accessor_.InsnsSizeInCodeUnits();
   for (const DexInstructionPcPair& pair : code_item_accessor_) {
     const uint32_t dex_pc = pair.DexPc();
     const Instruction& instruction = pair.Inst();
+    if (dex_pc >= max_pc) {
+      // We need to prevent abnormal access for outside of code
+      break;
+    }
 
     if (instruction.IsBranch()) {
       SetAsBranchTarget(dex_pc + instruction.GetTargetOffset());
@@ -107,22 +115,32 @@
                                       RegisterSource kind,
                                       VeriClass* cls,
                                       uint32_t source_id) {
-  current_registers_[dex_register] = RegisterValue(
-      kind, DexFileReference(&resolver_->GetDexFile(), source_id), cls);
+  // veridex doesn't do any code verification, so it can be that there are bogus dex
+  // instructions that update a non-existent register.
+  if (dex_register < current_registers_.size()) {
+    current_registers_[dex_register] = RegisterValue(
+        kind, DexFileReference(&resolver_->GetDexFile(), source_id), cls);
+  }
 }
 
 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const RegisterValue& value) {
-  current_registers_[dex_register] = value;
+  if (dex_register < current_registers_.size()) {
+    current_registers_[dex_register] = value;
+  }
 }
 
 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const VeriClass* cls) {
-  current_registers_[dex_register] =
-      RegisterValue(RegisterSource::kNone, DexFileReference(nullptr, 0), cls);
+  if (dex_register < current_registers_.size()) {
+    current_registers_[dex_register] =
+        RegisterValue(RegisterSource::kNone, DexFileReference(nullptr, 0), cls);
+  }
 }
 
 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, int32_t value, const VeriClass* cls) {
-  current_registers_[dex_register] =
-      RegisterValue(RegisterSource::kConstant, value, DexFileReference(nullptr, 0), cls);
+  if (dex_register < current_registers_.size()) {
+    current_registers_[dex_register] =
+        RegisterValue(RegisterSource::kConstant, value, DexFileReference(nullptr, 0), cls);
+  }
 }
 
 const RegisterValue& VeriFlowAnalysis::GetRegister(uint32_t dex_register) const {
@@ -199,7 +217,12 @@
     work_list.pop_back();
     CHECK(IsBranchTarget(dex_pc));
     current_registers_ = *dex_registers_[dex_pc].get();
+    const uint32_t max_pc = code_item_accessor_.InsnsSizeInCodeUnits();
     while (true) {
+      if (dex_pc >= max_pc) {
+        // We need to prevent abnormal access for outside of code
+        break;
+      }
       const uint16_t* insns = code_item_accessor_.Insns() + dex_pc;
       const Instruction& inst = *Instruction::At(insns);
       ProcessDexInstruction(inst);
diff --git a/tools/veridex/hidden_api_finder.cc b/tools/veridex/hidden_api_finder.cc
index e740cf4..d7ed1e4 100644
--- a/tools/veridex/hidden_api_finder.cc
+++ b/tools/veridex/hidden_api_finder.cc
@@ -33,7 +33,7 @@
                                   VeridexResolver* resolver,
                                   MethodReference ref) {
   // Note: we always query whether a method is in boot, as the app
-  // might define blacklisted APIs (which won't be used at runtime).
+  // might define blocked APIs (which won't be used at runtime).
   const auto& name = HiddenApi::GetApiMethodName(resolver->GetDexFile(), method_id);
   method_locations_[name].push_back(ref);
 }
@@ -42,7 +42,7 @@
                                  VeridexResolver* resolver,
                                  MethodReference ref) {
   // Note: we always query whether a field is in a boot, as the app
-  // might define blacklisted APIs (which won't be used at runtime).
+  // might define blocked APIs (which won't be used at runtime).
   const auto& name = HiddenApi::GetApiFieldName(resolver->GetDexFile(), field_id);
   field_locations_[name].push_back(ref);
 }
@@ -61,7 +61,14 @@
   for (ClassAccessor accessor : dex_file.GetClasses()) {
     if (class_filter.Matches(accessor.GetDescriptor())) {
       for (const ClassAccessor::Method& method : accessor.GetMethods()) {
-        for (const DexInstructionPcPair& inst : method.GetInstructions()) {
+        CodeItemInstructionAccessor codes = method.GetInstructions();
+        const uint32_t max_pc = codes.InsnsSizeInCodeUnits();
+        for (const DexInstructionPcPair& inst : codes) {
+          if (inst.DexPc() >= max_pc) {
+            // We need to prevent abnormal access for outside of code
+            break;
+          }
+
           switch (inst->Opcode()) {
             case Instruction::CONST_STRING: {
               dex::StringIndex string_index(inst->VRegB_21c());